Patrick Georgi | ac95903 | 2020-05-05 22:49:26 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
T Michael Turney | fda6cd6 | 2019-10-10 12:19:51 -0700 | [diff] [blame] | 2 | |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 3 | #include <bootmode.h> |
Julius Werner | e78fd11 | 2021-08-12 23:26:25 -0700 | [diff] [blame] | 4 | #include <cbfs.h> |
Elyes HAOUAS | 27718ac | 2020-09-19 09:32:36 +0200 | [diff] [blame] | 5 | #include <console/console.h> |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 6 | #include <delay.h> |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 7 | #include <device/device.h> |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 8 | #include <device/i2c_simple.h> |
Shaik Sajida Bhanu | 7bf3d0c | 2021-08-30 12:09:46 +0530 | [diff] [blame] | 9 | #include <device/mmio.h> |
Julius Werner | 5ff1808 | 2021-08-24 16:03:57 -0700 | [diff] [blame] | 10 | #include <mipi/panel.h> |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 11 | #include <drivers/ti/sn65dsi86bridge/sn65dsi86bridge.h> |
Philip Chen | 64ed1f1 | 2021-10-18 18:28:14 -0700 | [diff] [blame] | 12 | #include <drivers/parade/ps8640/ps8640.h> |
Julius Werner | e78fd11 | 2021-08-12 23:26:25 -0700 | [diff] [blame] | 13 | #include <edid.h> |
Patrick Rudolph | 8b56c8c | 2020-02-19 12:57:00 +0100 | [diff] [blame] | 14 | #include <framebuffer_info.h> |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 15 | #include <soc/display/mipi_dsi.h> |
| 16 | #include <soc/display/mdssreg.h> |
Ravi Kumar Bokka | 34960d4 | 2021-07-27 21:02:54 +0530 | [diff] [blame] | 17 | #include <soc/qupv3_config_common.h> |
| 18 | #include <soc/qup_se_handlers_common.h> |
Rajesh Patil | 555c2d6 | 2021-06-16 14:13:00 +0530 | [diff] [blame] | 19 | #include <soc/qupv3_i2c_common.h> |
| 20 | #include <soc/qcom_qup_se.h> |
T Michael Turney | 655220a | 2019-10-22 06:26:21 -0700 | [diff] [blame] | 21 | #include <soc/usb.h> |
Vinod Polimera | e8cd480 | 2021-03-16 18:37:40 +0530 | [diff] [blame] | 22 | #include <types.h> |
T Michael Turney | 655220a | 2019-10-22 06:26:21 -0700 | [diff] [blame] | 23 | |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 24 | #include "board.h" |
Shaik Sajida Bhanu | 7bf3d0c | 2021-08-30 12:09:46 +0530 | [diff] [blame] | 25 | #include <soc/addressmap.h> |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 26 | |
Julius Werner | f67f2b0 | 2021-09-28 14:46:59 -0700 | [diff] [blame] | 27 | #define BRIDGE_BUS QUPV3_0_SE2 |
Philip Chen | 64ed1f1 | 2021-10-18 18:28:14 -0700 | [diff] [blame] | 28 | #define BRIDGE_SN65DSI86_CHIP 0x2d |
| 29 | #define BRIDGE_PS8640_CHIP 0x08 |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 30 | |
T Michael Turney | 655220a | 2019-10-22 06:26:21 -0700 | [diff] [blame] | 31 | static struct usb_board_data usb0_board_data = { |
| 32 | .pll_bias_control_2 = 0x22, |
| 33 | .imp_ctrl1 = 0x08, |
| 34 | .port_tune1 = 0xc5, |
| 35 | }; |
| 36 | |
| 37 | static void setup_usb(void) |
| 38 | { |
Julius Werner | df33ef2 | 2020-08-24 16:06:41 -0700 | [diff] [blame] | 39 | /* Assert EN_PP3300_HUB for those board variants that use it. */ |
| 40 | gpio_output(GPIO(84), 1); |
| 41 | |
T Michael Turney | 655220a | 2019-10-22 06:26:21 -0700 | [diff] [blame] | 42 | setup_usb_host0(&usb0_board_data); |
| 43 | } |
T Michael Turney | fda6cd6 | 2019-10-10 12:19:51 -0700 | [diff] [blame] | 44 | |
T Michael Turney | 9bf0dd8 | 2019-11-27 19:28:50 -0800 | [diff] [blame] | 45 | static void qi2s_configure_gpios(void) |
| 46 | { |
T Michael Turney | 9bf0dd8 | 2019-11-27 19:28:50 -0800 | [diff] [blame] | 47 | gpio_configure(GPIO(49), GPIO49_FUNC_MI2S_1_SCK, |
vsujithk | 32aed01 | 2020-05-14 12:50:24 +0530 | [diff] [blame] | 48 | GPIO_NO_PULL, GPIO_8MA, GPIO_OUTPUT); |
T Michael Turney | 9bf0dd8 | 2019-11-27 19:28:50 -0800 | [diff] [blame] | 49 | |
| 50 | gpio_configure(GPIO(50), GPIO50_FUNC_MI2S_1_WS, |
vsujithk | 32aed01 | 2020-05-14 12:50:24 +0530 | [diff] [blame] | 51 | GPIO_NO_PULL, GPIO_8MA, GPIO_OUTPUT); |
T Michael Turney | 9bf0dd8 | 2019-11-27 19:28:50 -0800 | [diff] [blame] | 52 | |
| 53 | gpio_configure(GPIO(51), GPIO51_FUNC_MI2S_1_DATA0, |
vsujithk | 32aed01 | 2020-05-14 12:50:24 +0530 | [diff] [blame] | 54 | GPIO_NO_PULL, GPIO_8MA, GPIO_OUTPUT); |
T Michael Turney | 9bf0dd8 | 2019-11-27 19:28:50 -0800 | [diff] [blame] | 55 | } |
| 56 | |
| 57 | static void load_qup_fw(void) |
| 58 | { |
| 59 | qupv3_se_fw_load_and_init(QUPV3_0_SE1, SE_PROTOCOL_SPI, MIXED); /* ESIM SPI */ |
T Michael Turney | 9bf0dd8 | 2019-11-27 19:28:50 -0800 | [diff] [blame] | 60 | qupv3_se_fw_load_and_init(QUPV3_0_SE3, SE_PROTOCOL_UART, FIFO); /* BT UART */ |
| 61 | qupv3_se_fw_load_and_init(QUPV3_0_SE4, SE_PROTOCOL_I2C, MIXED); /* Pen Detect I2C */ |
| 62 | qupv3_se_fw_load_and_init(QUPV3_0_SE5, SE_PROTOCOL_I2C, MIXED); /* SAR I2C */ |
| 63 | qupv3_se_fw_load_and_init(QUPV3_1_SE1, SE_PROTOCOL_I2C, MIXED); /* Trackpad I2C */ |
| 64 | /* |
| 65 | * When coreboot firmware disables serial output, |
| 66 | * we still need to load console UART QUP FW for OS. |
| 67 | */ |
| 68 | if (!CONFIG(CONSOLE_SERIAL)) |
| 69 | qupv3_se_fw_load_and_init(QUPV3_1_SE2, SE_PROTOCOL_UART, FIFO); |
| 70 | |
| 71 | qupv3_se_fw_load_and_init(QUPV3_1_SE3, SE_PROTOCOL_I2C, MIXED); /* Speaker Amps I2C */ |
| 72 | qupv3_se_fw_load_and_init(QUPV3_1_SE4, SE_PROTOCOL_SPI, MIXED); /* Fingerprint SPI */ |
| 73 | qupv3_se_fw_load_and_init(QUPV3_1_SE5, SE_PROTOCOL_I2C, MIXED); /* Codec I2C */ |
| 74 | } |
| 75 | |
Philip Chen | 64ed1f1 | 2021-10-18 18:28:14 -0700 | [diff] [blame] | 76 | static bool is_ps8640_bridge(void) |
| 77 | { |
| 78 | /* |
| 79 | * Because the board_id pins for the early Homestar builds were |
| 80 | * misstuffed, after we enable tri-state board_id pins, a -rev1 |
| 81 | * board reports itself as -rev19, and a -rev2 board reports itself |
| 82 | * as -rev23. We need to account for those quirks here. |
| 83 | */ |
| 84 | return (CONFIG(BOARD_GOOGLE_HOMESTAR) && board_id() >= 4 && |
| 85 | board_id() != 19 && board_id() != 23) || |
Kevin Chiu | b8fa1d3 | 2021-11-01 12:46:43 +0800 | [diff] [blame] | 86 | (CONFIG(BOARD_GOOGLE_LAZOR) && board_id() >= 9) || |
| 87 | (CONFIG(BOARD_GOOGLE_KINGOFTOWN) && board_id() >= 1); |
Philip Chen | 64ed1f1 | 2021-10-18 18:28:14 -0700 | [diff] [blame] | 88 | } |
| 89 | |
| 90 | static void power_on_sn65dsi86_bridge(void) |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 91 | { |
| 92 | printk(BIOS_INFO, "%s: Bridge gpio init\n", __func__); |
| 93 | |
| 94 | /* Bridge Enable GPIO */ |
| 95 | gpio_output(GPIO_EDP_BRIDGE_ENABLE, 1); |
| 96 | |
| 97 | /* PP3300 EDP power supply */ |
| 98 | gpio_output(GPIO_EN_PP3300_DX_EDP, 1); |
| 99 | } |
| 100 | |
Philip Chen | 64ed1f1 | 2021-10-18 18:28:14 -0700 | [diff] [blame] | 101 | static void power_on_ps8640_bridge(void) |
| 102 | { |
| 103 | printk(BIOS_INFO, "%s: Bridge gpio init\n", __func__); |
| 104 | |
| 105 | /* PP3300 EDP panel power supply */ |
| 106 | gpio_output(GPIO_EN_PP3300_DX_EDP, 1); |
| 107 | |
| 108 | gpio_output(GPIO_PS8640_EDP_BRIDGE_3V3_ENABLE, 1); |
Philip Chen | 64ed1f1 | 2021-10-18 18:28:14 -0700 | [diff] [blame] | 109 | |
| 110 | /* |
xuxinxiong | ba2b113 | 2021-11-06 16:11:30 +0800 | [diff] [blame^] | 111 | * According to ps8640 v1.4 spec, and the raise time of vdd33 is a bit |
| 112 | * long, so wait for 4ms after VDD33 goes high and then deassert PD. |
| 113 | */ |
| 114 | mdelay(4); |
| 115 | |
| 116 | gpio_output(GPIO_PS8640_EDP_BRIDGE_PD_L, 1); |
| 117 | |
| 118 | /* |
| 119 | * According to ps8640 app note v0.6, wait for 2ms after VDD33 goes |
| 120 | * high and then deassert RST. |
Philip Chen | 64ed1f1 | 2021-10-18 18:28:14 -0700 | [diff] [blame] | 121 | */ |
| 122 | mdelay(2); |
| 123 | |
| 124 | gpio_output(GPIO_PS8640_EDP_BRIDGE_RST_L, 1); |
| 125 | } |
| 126 | |
Zanxi Chen | 2ef4b7e | 2021-09-02 15:26:31 +0800 | [diff] [blame] | 127 | static void configure_mipi_panel(void) |
| 128 | { |
| 129 | int panel_id = sku_id() >> 8; |
| 130 | gpio_output(GPIO_MIPI_1V8_ENABLE, 1); |
| 131 | mdelay(5); |
| 132 | gpio_output(GPIO_AVDD_LCD_ENABLE, 1); |
| 133 | mdelay(5); |
| 134 | gpio_output(GPIO_AVEE_LCD_ENABLE, 1); |
| 135 | mdelay(15); |
| 136 | gpio_output(GPIO_VDD_RESET_1V8, 1); |
| 137 | mdelay(15); |
| 138 | /* |
| 139 | * In mrbland, BOE panel_id = 3, it needs 15ms delay and |
| 140 | * do reset again according to spec(See in b/197300876). |
| 141 | */ |
| 142 | if (CONFIG(BOARD_GOOGLE_MRBLAND) && (panel_id == 3)) { |
| 143 | gpio_output(GPIO_VDD_RESET_1V8, 0); |
| 144 | mdelay(5); |
| 145 | gpio_output(GPIO_VDD_RESET_1V8, 1); |
| 146 | } |
| 147 | } |
| 148 | |
Julius Werner | 90ca4ae | 2021-09-14 15:50:08 -0700 | [diff] [blame] | 149 | static struct panel_serializable_data *get_mipi_panel(enum lb_fb_orientation *orientation) |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 150 | { |
Zanxi Chen | 2ef4b7e | 2021-09-02 15:26:31 +0800 | [diff] [blame] | 151 | const char *cbfs_filename = NULL; |
| 152 | int panel_id = sku_id() >> 8; |
| 153 | |
| 154 | if (CONFIG(BOARD_GOOGLE_MRBLAND)) { |
| 155 | switch (panel_id) { |
| 156 | case 3: |
| 157 | cbfs_filename = "panel-BOE_TV101WUM_N53"; |
Julius Werner | 90ca4ae | 2021-09-14 15:50:08 -0700 | [diff] [blame] | 158 | *orientation = LB_FB_ORIENTATION_LEFT_UP; |
Zanxi Chen | 2ef4b7e | 2021-09-02 15:26:31 +0800 | [diff] [blame] | 159 | break; |
| 160 | case 6: |
| 161 | cbfs_filename = "panel-AUO_B101UAN08_3"; |
Julius Werner | 90ca4ae | 2021-09-14 15:50:08 -0700 | [diff] [blame] | 162 | *orientation = LB_FB_ORIENTATION_LEFT_UP; |
Zanxi Chen | 2ef4b7e | 2021-09-02 15:26:31 +0800 | [diff] [blame] | 163 | break; |
| 164 | } |
| 165 | } |
| 166 | |
Sheng-Liang Pan | b22a435 | 2021-10-15 19:15:13 +0800 | [diff] [blame] | 167 | if (CONFIG(BOARD_GOOGLE_QUACKINGSTICK)) { |
| 168 | switch (panel_id) { |
| 169 | case 6: |
| 170 | cbfs_filename = "panel-AUO_B101UAN08_3"; |
| 171 | *orientation = LB_FB_ORIENTATION_LEFT_UP; |
| 172 | break; |
| 173 | } |
| 174 | } |
| 175 | |
Zanxi Chen | 75a29bc | 2021-09-14 21:22:45 +0800 | [diff] [blame] | 176 | if (CONFIG(BOARD_GOOGLE_WORMDINGLER)) { |
| 177 | switch (panel_id) { |
| 178 | case 0: |
| 179 | cbfs_filename = "panel-INX_P110ZZD_DF0"; |
| 180 | *orientation = LB_FB_ORIENTATION_LEFT_UP; |
| 181 | break; |
| 182 | case 4: |
| 183 | cbfs_filename = "panel-BOE_TV110C9M_LL0"; |
| 184 | *orientation = LB_FB_ORIENTATION_LEFT_UP; |
| 185 | break; |
| 186 | } |
| 187 | } |
| 188 | |
Zanxi Chen | 2ef4b7e | 2021-09-02 15:26:31 +0800 | [diff] [blame] | 189 | if (!cbfs_filename) |
| 190 | return NULL; |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 191 | |
Julius Werner | e78fd11 | 2021-08-12 23:26:25 -0700 | [diff] [blame] | 192 | struct panel_serializable_data *panel = cbfs_map(cbfs_filename, NULL); |
| 193 | if (!panel) { |
| 194 | printk(BIOS_ERR, "Could not find panel data for %s!\n", cbfs_filename); |
| 195 | return NULL; |
Vinod Polimera | e8cd480 | 2021-03-16 18:37:40 +0530 | [diff] [blame] | 196 | } |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 197 | |
Julius Werner | e78fd11 | 2021-08-12 23:26:25 -0700 | [diff] [blame] | 198 | return panel; |
| 199 | } |
Vinod Polimera | 6ea8033 | 2021-03-17 16:11:12 +0530 | [diff] [blame] | 200 | |
Julius Werner | e78fd11 | 2021-08-12 23:26:25 -0700 | [diff] [blame] | 201 | static enum cb_err display_init(struct panel_serializable_data *panel) |
| 202 | { |
| 203 | uint32_t dsi_bpp = 24; |
| 204 | uint32_t lanes = 4; |
| 205 | |
| 206 | if (mdss_dsi_config(&panel->edid, lanes, dsi_bpp)) |
| 207 | return CB_ERR; |
Philip Chen | 64ed1f1 | 2021-10-18 18:28:14 -0700 | [diff] [blame] | 208 | |
Julius Werner | e78fd11 | 2021-08-12 23:26:25 -0700 | [diff] [blame] | 209 | if (CONFIG(TROGDOR_HAS_MIPI_PANEL)) { |
| 210 | if (mdss_dsi_panel_initialize(panel->init)) |
| 211 | return CB_ERR; |
Philip Chen | 64ed1f1 | 2021-10-18 18:28:14 -0700 | [diff] [blame] | 212 | } else if (!is_ps8640_bridge()) { |
| 213 | /* |
| 214 | * Parade ps8640 is auto-configured based on a pre-programmed |
| 215 | * SPI-ROM. Only TI sn65dsi86 needs to be configured here. |
| 216 | */ |
| 217 | sn65dsi86_bridge_configure(BRIDGE_BUS, BRIDGE_SN65DSI86_CHIP, |
| 218 | &panel->edid, lanes, dsi_bpp); |
Julius Werner | e78fd11 | 2021-08-12 23:26:25 -0700 | [diff] [blame] | 219 | if (CONFIG(TROGDOR_HAS_BRIDGE_BACKLIGHT)) |
Philip Chen | 64ed1f1 | 2021-10-18 18:28:14 -0700 | [diff] [blame] | 220 | sn65dsi86_backlight_enable(BRIDGE_BUS, BRIDGE_SN65DSI86_CHIP); |
Julius Werner | e78fd11 | 2021-08-12 23:26:25 -0700 | [diff] [blame] | 221 | } |
| 222 | |
| 223 | mdp_dsi_video_config(&panel->edid); |
| 224 | mdss_dsi_video_mode_config(&panel->edid, dsi_bpp); |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 225 | mdp_dsi_video_on(); |
Vinod Polimera | e8cd480 | 2021-03-16 18:37:40 +0530 | [diff] [blame] | 226 | |
| 227 | return CB_SUCCESS; |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 228 | } |
| 229 | |
| 230 | static void display_startup(void) |
| 231 | { |
Julius Werner | 1f84b2c | 2021-09-01 16:27:58 -0700 | [diff] [blame] | 232 | struct panel_serializable_data edp_panel = {0}; |
| 233 | struct panel_serializable_data *panel = &edp_panel; |
Julius Werner | 90ca4ae | 2021-09-14 15:50:08 -0700 | [diff] [blame] | 234 | enum lb_fb_orientation orientation = LB_FB_ORIENTATION_NORMAL; |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 235 | |
Julius Werner | f67f2b0 | 2021-09-28 14:46:59 -0700 | [diff] [blame] | 236 | /* Always initialize this so QUP firmware is loaded for the kernel. */ |
| 237 | i2c_init(BRIDGE_BUS, I2C_SPEED_FAST); |
| 238 | |
Julius Werner | e78fd11 | 2021-08-12 23:26:25 -0700 | [diff] [blame] | 239 | if (!display_init_required()) { |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 240 | printk(BIOS_INFO, "Skipping display init.\n"); |
Julius Werner | e78fd11 | 2021-08-12 23:26:25 -0700 | [diff] [blame] | 241 | return; |
| 242 | } |
| 243 | |
| 244 | if (CONFIG(TROGDOR_HAS_MIPI_PANEL)) { |
Zanxi Chen | 2ef4b7e | 2021-09-02 15:26:31 +0800 | [diff] [blame] | 245 | configure_mipi_panel(); |
Julius Werner | 90ca4ae | 2021-09-14 15:50:08 -0700 | [diff] [blame] | 246 | panel = get_mipi_panel(&orientation); |
Julius Werner | e78fd11 | 2021-08-12 23:26:25 -0700 | [diff] [blame] | 247 | if (!panel) |
| 248 | return; |
Philip Chen | 64ed1f1 | 2021-10-18 18:28:14 -0700 | [diff] [blame] | 249 | } else if (is_ps8640_bridge()) { |
| 250 | power_on_ps8640_bridge(); |
| 251 | ps8640_init(BRIDGE_BUS, BRIDGE_PS8640_CHIP); |
| 252 | if (ps8640_get_edid(BRIDGE_BUS, BRIDGE_PS8640_CHIP, &panel->edid) < 0) |
| 253 | return; |
Julius Werner | e78fd11 | 2021-08-12 23:26:25 -0700 | [diff] [blame] | 254 | } else { |
| 255 | enum dp_pll_clk_src ref_clk = SN65_SEL_19MHZ; |
Philip Chen | 64ed1f1 | 2021-10-18 18:28:14 -0700 | [diff] [blame] | 256 | power_on_sn65dsi86_bridge(); |
Julius Werner | e78fd11 | 2021-08-12 23:26:25 -0700 | [diff] [blame] | 257 | mdelay(250); /* Delay for the panel to be up */ |
Philip Chen | 64ed1f1 | 2021-10-18 18:28:14 -0700 | [diff] [blame] | 258 | sn65dsi86_bridge_init(BRIDGE_BUS, BRIDGE_SN65DSI86_CHIP, ref_clk); |
| 259 | if (sn65dsi86_bridge_read_edid(BRIDGE_BUS, BRIDGE_SN65DSI86_CHIP, |
| 260 | &panel->edid) < 0) |
Julius Werner | e78fd11 | 2021-08-12 23:26:25 -0700 | [diff] [blame] | 261 | return; |
Julius Werner | e78fd11 | 2021-08-12 23:26:25 -0700 | [diff] [blame] | 262 | } |
| 263 | |
| 264 | printk(BIOS_INFO, "display init!\n"); |
| 265 | edid_set_framebuffer_bits_per_pixel(&panel->edid, 32, 0); |
Julius Werner | 90ca4ae | 2021-09-14 15:50:08 -0700 | [diff] [blame] | 266 | if (display_init(panel) == CB_SUCCESS) { |
| 267 | struct fb_info *fb = fb_new_framebuffer_info_from_edid(&panel->edid, 0); |
| 268 | fb_set_orientation(fb, orientation); |
| 269 | } |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 270 | } |
| 271 | |
Shaik Sajida Bhanu | 7bf3d0c | 2021-08-30 12:09:46 +0530 | [diff] [blame] | 272 | static void configure_sdhci(void) |
| 273 | { |
| 274 | /* Program eMMC drive strength to 16/16/16 mA */ |
| 275 | write32((void *)SDC1_TLMM_CFG_ADDR, 0x9FFF); |
| 276 | /* Program SD card drive strength to 16/10/10 mA */ |
| 277 | write32((void *)SDC2_TLMM_CFG_ADDR, 0x1FE4); |
| 278 | } |
| 279 | |
T Michael Turney | fda6cd6 | 2019-10-10 12:19:51 -0700 | [diff] [blame] | 280 | static void mainboard_init(struct device *dev) |
| 281 | { |
Julius Werner | a39c577 | 2021-02-10 14:25:21 -0800 | [diff] [blame] | 282 | /* Take FPMCU out of reset. Power was already applied |
| 283 | in romstage and should have stabilized by now. */ |
| 284 | if (CONFIG(TROGDOR_HAS_FINGERPRINT)) |
| 285 | gpio_output(GPIO_FP_RST_L, 1); |
| 286 | |
T Michael Turney | 655220a | 2019-10-22 06:26:21 -0700 | [diff] [blame] | 287 | setup_usb(); |
T Michael Turney | 9bf0dd8 | 2019-11-27 19:28:50 -0800 | [diff] [blame] | 288 | qi2s_configure_gpios(); |
| 289 | load_qup_fw(); |
Vinod Polimera | 3b4c45e | 2020-03-03 12:13:26 +0530 | [diff] [blame] | 290 | display_startup(); |
Shaik Sajida Bhanu | 7bf3d0c | 2021-08-30 12:09:46 +0530 | [diff] [blame] | 291 | configure_sdhci(); |
T Michael Turney | fda6cd6 | 2019-10-10 12:19:51 -0700 | [diff] [blame] | 292 | } |
| 293 | |
| 294 | static void mainboard_enable(struct device *dev) |
| 295 | { |
| 296 | dev->ops->init = &mainboard_init; |
| 297 | } |
| 298 | |
| 299 | struct chip_operations mainboard_ops = { |
T Michael Turney | fda6cd6 | 2019-10-10 12:19:51 -0700 | [diff] [blame] | 300 | .enable_dev = mainboard_enable, |
| 301 | }; |