blob: 5499a07121389d8c80b0faa860c897a2f32dd1b6 [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-only */
T Michael Turneyfda6cd62019-10-10 12:19:51 -07002
Vinod Polimera3b4c45e2020-03-03 12:13:26 +05303#include <bootmode.h>
Julius Wernere78fd112021-08-12 23:26:25 -07004#include <cbfs.h>
Elyes HAOUAS27718ac2020-09-19 09:32:36 +02005#include <console/console.h>
Vinod Polimera3b4c45e2020-03-03 12:13:26 +05306#include <delay.h>
Julius Werner55009af2019-12-02 22:03:27 -08007#include <device/device.h>
Vinod Polimera3b4c45e2020-03-03 12:13:26 +05308#include <device/i2c_simple.h>
Shaik Sajida Bhanu7bf3d0c2021-08-30 12:09:46 +05309#include <device/mmio.h>
Julius Werner5ff18082021-08-24 16:03:57 -070010#include <mipi/panel.h>
Vinod Polimera3b4c45e2020-03-03 12:13:26 +053011#include <drivers/ti/sn65dsi86bridge/sn65dsi86bridge.h>
Philip Chen64ed1f12021-10-18 18:28:14 -070012#include <drivers/parade/ps8640/ps8640.h>
Julius Wernere78fd112021-08-12 23:26:25 -070013#include <edid.h>
Patrick Rudolph8b56c8c2020-02-19 12:57:00 +010014#include <framebuffer_info.h>
Vinod Polimera3b4c45e2020-03-03 12:13:26 +053015#include <soc/display/mipi_dsi.h>
16#include <soc/display/mdssreg.h>
Ravi Kumar Bokka34960d42021-07-27 21:02:54 +053017#include <soc/qupv3_config_common.h>
18#include <soc/qup_se_handlers_common.h>
Rajesh Patil555c2d62021-06-16 14:13:00 +053019#include <soc/qupv3_i2c_common.h>
20#include <soc/qcom_qup_se.h>
T Michael Turney655220a2019-10-22 06:26:21 -070021#include <soc/usb.h>
Vinod Polimerae8cd4802021-03-16 18:37:40 +053022#include <types.h>
T Michael Turney655220a2019-10-22 06:26:21 -070023
Vinod Polimera3b4c45e2020-03-03 12:13:26 +053024#include "board.h"
Shaik Sajida Bhanu7bf3d0c2021-08-30 12:09:46 +053025#include <soc/addressmap.h>
Vinod Polimera3b4c45e2020-03-03 12:13:26 +053026
Julius Wernerf67f2b02021-09-28 14:46:59 -070027#define BRIDGE_BUS QUPV3_0_SE2
Philip Chen64ed1f12021-10-18 18:28:14 -070028#define BRIDGE_SN65DSI86_CHIP 0x2d
29#define BRIDGE_PS8640_CHIP 0x08
Vinod Polimera3b4c45e2020-03-03 12:13:26 +053030
T Michael Turney655220a2019-10-22 06:26:21 -070031static struct usb_board_data usb0_board_data = {
32 .pll_bias_control_2 = 0x22,
33 .imp_ctrl1 = 0x08,
34 .port_tune1 = 0xc5,
35};
36
37static void setup_usb(void)
38{
Julius Wernerdf33ef22020-08-24 16:06:41 -070039 /* Assert EN_PP3300_HUB for those board variants that use it. */
40 gpio_output(GPIO(84), 1);
41
T Michael Turney655220a2019-10-22 06:26:21 -070042 setup_usb_host0(&usb0_board_data);
43}
T Michael Turneyfda6cd62019-10-10 12:19:51 -070044
T Michael Turney9bf0dd82019-11-27 19:28:50 -080045static void qi2s_configure_gpios(void)
46{
T Michael Turney9bf0dd82019-11-27 19:28:50 -080047 gpio_configure(GPIO(49), GPIO49_FUNC_MI2S_1_SCK,
vsujithk32aed012020-05-14 12:50:24 +053048 GPIO_NO_PULL, GPIO_8MA, GPIO_OUTPUT);
T Michael Turney9bf0dd82019-11-27 19:28:50 -080049
50 gpio_configure(GPIO(50), GPIO50_FUNC_MI2S_1_WS,
vsujithk32aed012020-05-14 12:50:24 +053051 GPIO_NO_PULL, GPIO_8MA, GPIO_OUTPUT);
T Michael Turney9bf0dd82019-11-27 19:28:50 -080052
53 gpio_configure(GPIO(51), GPIO51_FUNC_MI2S_1_DATA0,
vsujithk32aed012020-05-14 12:50:24 +053054 GPIO_NO_PULL, GPIO_8MA, GPIO_OUTPUT);
T Michael Turney9bf0dd82019-11-27 19:28:50 -080055}
56
57static void load_qup_fw(void)
58{
59 qupv3_se_fw_load_and_init(QUPV3_0_SE1, SE_PROTOCOL_SPI, MIXED); /* ESIM SPI */
T Michael Turney9bf0dd82019-11-27 19:28:50 -080060 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 Chen64ed1f12021-10-18 18:28:14 -070076static 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 Chiub8fa1d32021-11-01 12:46:43 +080086 (CONFIG(BOARD_GOOGLE_LAZOR) && board_id() >= 9) ||
87 (CONFIG(BOARD_GOOGLE_KINGOFTOWN) && board_id() >= 1);
Philip Chen64ed1f12021-10-18 18:28:14 -070088}
89
90static void power_on_sn65dsi86_bridge(void)
Vinod Polimera3b4c45e2020-03-03 12:13:26 +053091{
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 Chen64ed1f12021-10-18 18:28:14 -0700101static 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 Chen64ed1f12021-10-18 18:28:14 -0700109
110 /*
xuxinxiongba2b1132021-11-06 16:11:30 +0800111 * 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 Chen64ed1f12021-10-18 18:28:14 -0700121 */
122 mdelay(2);
123
124 gpio_output(GPIO_PS8640_EDP_BRIDGE_RST_L, 1);
125}
126
Zanxi Chen2ef4b7e2021-09-02 15:26:31 +0800127static 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 Werner90ca4ae2021-09-14 15:50:08 -0700149static struct panel_serializable_data *get_mipi_panel(enum lb_fb_orientation *orientation)
Vinod Polimera3b4c45e2020-03-03 12:13:26 +0530150{
Zanxi Chen2ef4b7e2021-09-02 15:26:31 +0800151 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 Werner90ca4ae2021-09-14 15:50:08 -0700158 *orientation = LB_FB_ORIENTATION_LEFT_UP;
Zanxi Chen2ef4b7e2021-09-02 15:26:31 +0800159 break;
160 case 6:
161 cbfs_filename = "panel-AUO_B101UAN08_3";
Julius Werner90ca4ae2021-09-14 15:50:08 -0700162 *orientation = LB_FB_ORIENTATION_LEFT_UP;
Zanxi Chen2ef4b7e2021-09-02 15:26:31 +0800163 break;
164 }
165 }
166
Sheng-Liang Panb22a4352021-10-15 19:15:13 +0800167 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 Chen75a29bc2021-09-14 21:22:45 +0800176 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 Chen2ef4b7e2021-09-02 15:26:31 +0800189 if (!cbfs_filename)
190 return NULL;
Vinod Polimera3b4c45e2020-03-03 12:13:26 +0530191
Julius Wernere78fd112021-08-12 23:26:25 -0700192 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 Polimerae8cd4802021-03-16 18:37:40 +0530196 }
Vinod Polimera3b4c45e2020-03-03 12:13:26 +0530197
Julius Wernere78fd112021-08-12 23:26:25 -0700198 return panel;
199}
Vinod Polimera6ea80332021-03-17 16:11:12 +0530200
Julius Wernere78fd112021-08-12 23:26:25 -0700201static 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 Chen64ed1f12021-10-18 18:28:14 -0700208
Julius Wernere78fd112021-08-12 23:26:25 -0700209 if (CONFIG(TROGDOR_HAS_MIPI_PANEL)) {
210 if (mdss_dsi_panel_initialize(panel->init))
211 return CB_ERR;
Philip Chen64ed1f12021-10-18 18:28:14 -0700212 } 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 Wernere78fd112021-08-12 23:26:25 -0700219 if (CONFIG(TROGDOR_HAS_BRIDGE_BACKLIGHT))
Philip Chen64ed1f12021-10-18 18:28:14 -0700220 sn65dsi86_backlight_enable(BRIDGE_BUS, BRIDGE_SN65DSI86_CHIP);
Julius Wernere78fd112021-08-12 23:26:25 -0700221 }
222
223 mdp_dsi_video_config(&panel->edid);
224 mdss_dsi_video_mode_config(&panel->edid, dsi_bpp);
Vinod Polimera3b4c45e2020-03-03 12:13:26 +0530225 mdp_dsi_video_on();
Vinod Polimerae8cd4802021-03-16 18:37:40 +0530226
227 return CB_SUCCESS;
Vinod Polimera3b4c45e2020-03-03 12:13:26 +0530228}
229
230static void display_startup(void)
231{
Julius Werner1f84b2c2021-09-01 16:27:58 -0700232 struct panel_serializable_data edp_panel = {0};
233 struct panel_serializable_data *panel = &edp_panel;
Julius Werner90ca4ae2021-09-14 15:50:08 -0700234 enum lb_fb_orientation orientation = LB_FB_ORIENTATION_NORMAL;
Vinod Polimera3b4c45e2020-03-03 12:13:26 +0530235
Julius Wernerf67f2b02021-09-28 14:46:59 -0700236 /* Always initialize this so QUP firmware is loaded for the kernel. */
237 i2c_init(BRIDGE_BUS, I2C_SPEED_FAST);
238
Julius Wernere78fd112021-08-12 23:26:25 -0700239 if (!display_init_required()) {
Vinod Polimera3b4c45e2020-03-03 12:13:26 +0530240 printk(BIOS_INFO, "Skipping display init.\n");
Julius Wernere78fd112021-08-12 23:26:25 -0700241 return;
242 }
243
244 if (CONFIG(TROGDOR_HAS_MIPI_PANEL)) {
Zanxi Chen2ef4b7e2021-09-02 15:26:31 +0800245 configure_mipi_panel();
Julius Werner90ca4ae2021-09-14 15:50:08 -0700246 panel = get_mipi_panel(&orientation);
Julius Wernere78fd112021-08-12 23:26:25 -0700247 if (!panel)
248 return;
Philip Chen64ed1f12021-10-18 18:28:14 -0700249 } 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 Wernere78fd112021-08-12 23:26:25 -0700254 } else {
255 enum dp_pll_clk_src ref_clk = SN65_SEL_19MHZ;
Philip Chen64ed1f12021-10-18 18:28:14 -0700256 power_on_sn65dsi86_bridge();
Julius Wernere78fd112021-08-12 23:26:25 -0700257 mdelay(250); /* Delay for the panel to be up */
Philip Chen64ed1f12021-10-18 18:28:14 -0700258 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 Wernere78fd112021-08-12 23:26:25 -0700261 return;
Julius Wernere78fd112021-08-12 23:26:25 -0700262 }
263
264 printk(BIOS_INFO, "display init!\n");
265 edid_set_framebuffer_bits_per_pixel(&panel->edid, 32, 0);
Julius Werner90ca4ae2021-09-14 15:50:08 -0700266 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 Polimera3b4c45e2020-03-03 12:13:26 +0530270}
271
Shaik Sajida Bhanu7bf3d0c2021-08-30 12:09:46 +0530272static 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 Turneyfda6cd62019-10-10 12:19:51 -0700280static void mainboard_init(struct device *dev)
281{
Julius Wernera39c5772021-02-10 14:25:21 -0800282 /* 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 Turney655220a2019-10-22 06:26:21 -0700287 setup_usb();
T Michael Turney9bf0dd82019-11-27 19:28:50 -0800288 qi2s_configure_gpios();
289 load_qup_fw();
Vinod Polimera3b4c45e2020-03-03 12:13:26 +0530290 display_startup();
Shaik Sajida Bhanu7bf3d0c2021-08-30 12:09:46 +0530291 configure_sdhci();
T Michael Turneyfda6cd62019-10-10 12:19:51 -0700292}
293
294static void mainboard_enable(struct device *dev)
295{
296 dev->ops->init = &mainboard_init;
297}
298
299struct chip_operations mainboard_ops = {
T Michael Turneyfda6cd62019-10-10 12:19:51 -0700300 .enable_dev = mainboard_enable,
301};