blob: 74c83bcdedf7e7ebf3ab7cecd8f49003cb45ef5f [file] [log] [blame]
huang lina6dbfb52016-03-02 18:38:40 +08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2016 Rockchip Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
philipchen21b08522017-04-27 18:25:11 -070017#include <assert.h>
Vadim Bendebury8e8a00c2016-04-22 12:25:07 -070018#include <boardid.h>
Julius Wernerc49782c2016-11-21 20:14:18 -080019#include <console/console.h>
Lin Huangb497b482016-03-31 18:44:13 +080020#include <delay.h>
huang lina6dbfb52016-03-02 18:38:40 +080021#include <device/device.h>
Lin Huangb497b482016-03-31 18:44:13 +080022#include <device/i2c.h>
Julius Wernerc49782c2016-11-21 20:14:18 -080023#include <ec/google/chromeec/ec.h>
Vadim Bendebury1e80ab32016-03-28 00:44:54 -070024#include <gpio.h>
Lin Huang5a4be8a2016-05-17 15:45:53 +080025#include <soc/bl31_plat_params.h>
Vadim Bendebury1e80ab32016-03-28 00:44:54 -070026#include <soc/clock.h>
Lin Huangb497b482016-03-31 18:44:13 +080027#include <soc/display.h>
Vadim Bendebury1e80ab32016-03-28 00:44:54 -070028#include <soc/grf.h>
Lin Huangb497b482016-03-31 18:44:13 +080029#include <soc/i2c.h>
Liangfeng Wu76655cb2016-05-26 16:06:58 +080030#include <soc/usb.h>
Simon Glassbc679bc2016-06-19 16:09:21 -060031#include <vendorcode/google/chromeos/chromeos.h>
Vadim Bendebury1e80ab32016-03-28 00:44:54 -070032
Vadim Bendebury993dbe12016-05-22 15:53:37 -070033#include "board.h"
34
Brian Norrise06a1b82016-09-21 18:16:54 -070035/*
36 * Wifi's PDN/RST line is pulled down by its (unpowered) voltage rails, but
37 * this reset pin is pulled up by default. Let's drive it low as early as we
38 * can.
39 */
40static void deassert_wifi_power(void)
41{
42 gpio_output(GPIO(1, B, 3), 0); /* Assert WLAN_MODULE_RST# */
43}
44
Lin Huang2f7ed8d2016-04-08 18:56:20 +080045static void configure_emmc(void)
46{
47 /* Host controller does not support programmable clock generator.
48 * If we don't do this setting, when we use phy to control the
49 * emmc clock(when clock exceed 50MHz), it will get wrong clock.
50 *
51 * Refer to TRM V0.3 Part 1 Chapter 15 PAGE 782 for this register.
52 * Please search "_CON11[7:0]" to locate register description.
53 */
54 write32(&rk3399_grf->emmccore_con[11], RK_CLRSETBITS(0xff, 0));
55
56 rkclk_configure_emmc();
57}
58
Lin Huangc9fea5c2016-08-30 15:34:42 -070059static void register_apio_suspend(void)
60{
61 static struct bl31_apio_param param_apio = {
62 .h = {
63 .type = PARAM_SUSPEND_APIO,
64 },
65 .apio = {
66 .apio1 = 1,
67 .apio2 = 1,
68 .apio3 = 1,
69 .apio4 = 1,
70 .apio5 = 1,
71 },
72 };
73 register_bl31_param(&param_apio.h);
74}
75
Lin Huang7d8ccfb2016-08-22 17:35:40 -070076static void register_gpio_suspend(void)
77{
78 /*
79 * These three GPIO params are used to shut down the 1.5V, 1.8V and
80 * 3.3V power rails, which need to be shut down ordered by voltage,
81 * with highest voltage first.
82 * Since register_bl31() appends to the front of the list, we need to
83 * register them backwards, with 1.5V coming first.
84 */
85 static struct bl31_gpio_param param_p15_en = {
86 .h = {
87 .type = PARAM_SUSPEND_GPIO,
88 },
89 .gpio = {
90 .polarity = BL31_GPIO_LEVEL_LOW,
91 },
92 };
93 param_p15_en.gpio.index = GET_GPIO_NUM(GPIO_P15V_EN);
94 register_bl31_param(&param_p15_en.h);
95
96 static struct bl31_gpio_param param_p18_audio_en = {
97 .h = {
98 .type = PARAM_SUSPEND_GPIO,
99 },
100 .gpio = {
101 .polarity = BL31_GPIO_LEVEL_LOW,
102 },
103 };
104 param_p18_audio_en.gpio.index = GET_GPIO_NUM(GPIO_P18V_AUDIO_PWREN);
105 register_bl31_param(&param_p18_audio_en.h);
106
107 static struct bl31_gpio_param param_p30_en = {
108 .h = {
109 .type = PARAM_SUSPEND_GPIO,
110 },
111 .gpio = {
112 .polarity = BL31_GPIO_LEVEL_LOW,
113 },
114 };
115 param_p30_en.gpio.index = GET_GPIO_NUM(GPIO_P30V_EN);
116 register_bl31_param(&param_p30_en.h);
117}
118
Lin Huang5a4be8a2016-05-17 15:45:53 +0800119static void register_reset_to_bl31(void)
120{
121 static struct bl31_gpio_param param_reset = {
122 .h = {
123 .type = PARAM_RESET,
124 },
125 .gpio = {
126 .polarity = 1,
127 },
128 };
129
130 /* gru/kevin reset pin: gpio0b3 */
131 param_reset.gpio.index = GET_GPIO_NUM(GPIO_RESET),
132
133 register_bl31_param(&param_reset.h);
134}
135
Lin Huang9a5c4fe2016-05-19 11:11:23 +0800136static void register_poweroff_to_bl31(void)
137{
138 static struct bl31_gpio_param param_poweroff = {
139 .h = {
140 .type = PARAM_POWEROFF,
141 },
142 .gpio = {
143 .polarity = 1,
144 },
145 };
146
147 /*
148 * gru/kevin power off pin: gpio1a6,
149 * reuse with tsadc int pin, so iomux need set back to
150 * gpio in BL31 and depthcharge before you setting this gpio
151 */
152 param_poweroff.gpio.index = GET_GPIO_NUM(GPIO_POWEROFF),
153
154 register_bl31_param(&param_poweroff.h);
155}
156
Vadim Bendebury1e80ab32016-03-28 00:44:54 -0700157static void configure_sdmmc(void)
158{
Vadim Bendebury1e80ab32016-03-28 00:44:54 -0700159 gpio_output(GPIO(2, A, 2), 1); /* SDMMC_SDIO_PWR_EN */
Vadim Bendebury2832c412016-05-11 15:03:44 +0800160
161 /* SDMMC_DET_L is different on Kevin board revision 0. */
162 if (IS_ENABLED(CONFIG_BOARD_GOOGLE_KEVIN) && (board_id() == 0))
Vadim Bendebury8e8a00c2016-04-22 12:25:07 -0700163 gpio_input(GPIO(4, D, 2));
Vadim Bendebury2832c412016-05-11 15:03:44 +0800164 else
Vadim Bendebury8e8a00c2016-04-22 12:25:07 -0700165 gpio_input(GPIO(4, D, 0));
Vadim Bendebury2832c412016-05-11 15:03:44 +0800166
Vadim Bendebury1e80ab32016-03-28 00:44:54 -0700167 gpio_output(GPIO(2, D, 4), 0); /* Keep the max voltage */
Vadim Bendebury8e8a00c2016-04-22 12:25:07 -0700168
Julius Werner7feb86b2016-09-02 11:25:56 -0700169 gpio_input(GPIO(4, B, 0)); /* SDMMC0_D0 remove pull-up */
170 gpio_input(GPIO(4, B, 1)); /* SDMMC0_D1 remove pull-up */
171 gpio_input(GPIO(4, B, 2)); /* SDMMC0_D2 remove pull-up */
172 gpio_input(GPIO(4, B, 3)); /* SDMMC0_D3 remove pull-up */
173 gpio_input(GPIO(4, B, 4)); /* SDMMC0_CLK remove pull-down */
174 gpio_input(GPIO(4, B, 5)); /* SDMMC0_CMD remove pull-up */
175
Vadim Bendeburyad6ee022016-05-12 16:54:00 +0800176 write32(&rk3399_grf->gpio2_p[2][1], RK_CLRSETBITS(0xfff, 0));
177
178 /*
179 * Set all outputs' drive strength to 8 mA. Group 4 bank B driver
180 * strength requires three bits per pin. Value of 2 written in that
181 * three bit field means '8 mA', as deduced from the kernel code.
182 *
183 * Thus the six pins involved in SDMMC interface require 18 bits to
184 * configure drive strength, but each 32 bit register provides only 16
185 * bits for this setting, this covers 5 pins fully and one bit from
186 * the 6th pin. Two more bits spill over to the next register. This is
187 * described on page 378 of rk3399 TRM Version 0.3 Part 1.
188 */
189 write32(&rk3399_grf->gpio4b_e01,
190 RK_CLRSETBITS(0xffff,
191 (2 << 0) | (2 << 3) |
192 (2 << 6) | (2 << 9) | (2 << 12)));
193 write32(&rk3399_grf->gpio4b_e2, RK_CLRSETBITS(3, 1));
194
195 /* And now set the multiplexor to enable SDMMC0. */
Vadim Bendebury1e80ab32016-03-28 00:44:54 -0700196 write32(&rk3399_grf->iomux_sdmmc, IOMUX_SDMMC);
197}
huang lina6dbfb52016-03-02 18:38:40 +0800198
Xing Zheng96fbc312016-05-19 11:39:20 +0800199static void configure_codec(void)
200{
Julius Werner7feb86b2016-09-02 11:25:56 -0700201 gpio_input(GPIO(3, D, 0)); /* I2S0_SCLK remove pull-up */
202 gpio_input(GPIO(3, D, 1)); /* I2S0_RX remove pull-up */
203 gpio_input(GPIO(3, D, 2)); /* I2S0_TX remove pull-up */
204 gpio_input(GPIO(3, D, 3)); /* I2S0_SDI0 remove pull-up */
205 gpio_input(GPIO(3, D, 4)); /* I2S0_SDI1 remove pull-up */
206 /* GPIO3_D5 (I2S0_SDI2SDO2) not connected */
207 gpio_input(GPIO(3, D, 6)); /* I2S0_SDO1 remove pull-up */
208 gpio_input(GPIO(3, D, 7)); /* I2S0_SDO0 remove pull-up */
209 gpio_input(GPIO(4, A, 0)); /* I2S0_MCLK remove pull-up */
210
Xing Zheng96fbc312016-05-19 11:39:20 +0800211 write32(&rk3399_grf->iomux_i2s0, IOMUX_I2S0);
212 write32(&rk3399_grf->iomux_i2sclk, IOMUX_I2SCLK);
213
214 /* AUDIO IO domain 1.8V voltage selection */
215 write32(&rk3399_grf->io_vsel, RK_SETBITS(1 << 1));
216
217 /* CPU1_P1.8V_AUDIO_PWREN for P1.8_AUDIO */
218 gpio_output(GPIO(0, A, 2), 1);
219
220 /* set CPU1_SPK_PA_EN output */
221 gpio_output(GPIO(1, A, 2), 0);
222
223 rkclk_configure_i2s(12288000);
224}
225
Lin Huangb497b482016-03-31 18:44:13 +0800226static void configure_display(void)
227{
228 /* set pinmux for edp HPD*/
229 gpio_input_pulldown(GPIO(4, C, 7));
230 write32(&rk3399_grf->iomux_edp_hotplug, IOMUX_EDP_HOTPLUG);
231
232 gpio_output(GPIO(4, D, 3), 1); /* CPU3_EDP_VDDEN for P3.3V_DISP */
233}
234
Julius Wernerc49782c2016-11-21 20:14:18 -0800235static void usb_power_cycle(int port)
236{
237 if (google_chromeec_set_usb_pd_role(port, USB_PD_CTRL_ROLE_FORCE_SINK))
238 printk(BIOS_ERR, "ERROR: Cannot force USB%d PD sink\n", port);
239
240 mdelay(10); /* Make sure USB stick is fully depowered. */
241
242 if (google_chromeec_set_usb_pd_role(port, USB_PD_CTRL_ROLE_TOGGLE_ON))
243 printk(BIOS_ERR, "ERROR: Cannot restore USB%d PD mode\n", port);
244}
245
philipchen21b08522017-04-27 18:25:11 -0700246static void setup_usb(int port)
Liangfeng Wu76655cb2016-05-26 16:06:58 +0800247{
philipchen21b08522017-04-27 18:25:11 -0700248 /* Must be PHY0 or PHY1. */
249 assert(port == 0 || port == 1);
250
William wu605a87c2017-01-09 19:02:39 +0800251 /*
252 * A few magic PHY tuning values that improve eye diagram amplitude
253 * and make it extra sure we get reliable communication in firmware
254 * Set max ODT compensation voltage and current tuning reference.
255 */
philipchen21b08522017-04-27 18:25:11 -0700256 write32(&rk3399_grf->usbphy_ctrl[port][3], RK_CLRSETBITS(0xfff, 0x2e3));
William wu9f470b12016-11-10 19:34:45 +0800257
Caesar Wang9e588002017-02-10 11:16:13 +0800258 /* Set max pre-emphasis level on PHY0 and PHY1. */
philipchen21b08522017-04-27 18:25:11 -0700259 write32(&rk3399_grf->usbphy_ctrl[port][12],
Caesar Wang9e588002017-02-10 11:16:13 +0800260 RK_CLRSETBITS(0xffff, 0xa7));
William wu9f470b12016-11-10 19:34:45 +0800261
Caesar Wang9e588002017-02-10 11:16:13 +0800262 /*
William wuebbdd282017-01-23 20:54:22 +0800263 * 1. Disable the pre-emphasize in eop state and chirp
Caesar Wang9e588002017-02-10 11:16:13 +0800264 * state to avoid mis-trigger the disconnect detection
265 * and also avoid high-speed handshake fail for PHY0
266 * and PHY1 consist of otg-port and host-port.
William wuebbdd282017-01-23 20:54:22 +0800267 *
268 * 2. Configure PHY0 and PHY1 otg-ports squelch detection
269 * threshold to 125mV (default is 150mV).
Caesar Wang9e588002017-02-10 11:16:13 +0800270 */
philipchen21b08522017-04-27 18:25:11 -0700271 write32(&rk3399_grf->usbphy_ctrl[port][0],
William wuebbdd282017-01-23 20:54:22 +0800272 RK_CLRSETBITS(7 << 13 | 3 << 0, 6 << 13));
philipchen21b08522017-04-27 18:25:11 -0700273 write32(&rk3399_grf->usbphy_ctrl[port][13], RK_CLRBITS(3 << 0));
William wu9f470b12016-11-10 19:34:45 +0800274
Caesar Wang9e588002017-02-10 11:16:13 +0800275 /*
276 * ODT auto compensation bypass, and set max driver
277 * strength only for PHY0 and PHY1 otg-port.
278 */
philipchen21b08522017-04-27 18:25:11 -0700279 write32(&rk3399_grf->usbphy_ctrl[port][2],
Caesar Wang9e588002017-02-10 11:16:13 +0800280 RK_CLRSETBITS(0x7e << 4, 0x60 << 4));
William wu9f470b12016-11-10 19:34:45 +0800281
Caesar Wang9e588002017-02-10 11:16:13 +0800282 /*
283 * ODT auto refresh bypass, and set the max bias current
284 * tuning reference only for PHY0 and PHY1 otg-port.
285 */
philipchen21b08522017-04-27 18:25:11 -0700286 write32(&rk3399_grf->usbphy_ctrl[port][3],
Caesar Wang9e588002017-02-10 11:16:13 +0800287 RK_CLRSETBITS(0x21c, 1 << 4));
William wu605a87c2017-01-09 19:02:39 +0800288
Caesar Wang9e588002017-02-10 11:16:13 +0800289 /*
290 * ODT auto compensation bypass, and set default driver
291 * strength only for PHY0 and PHY1 host-port.
292 */
philipchen21b08522017-04-27 18:25:11 -0700293 write32(&rk3399_grf->usbphy_ctrl[port][15], RK_SETBITS(1 << 10));
William wu605a87c2017-01-09 19:02:39 +0800294
Caesar Wang9e588002017-02-10 11:16:13 +0800295 /* ODT auto refresh bypass only for PHY0 and PHY1 host-port. */
philipchen21b08522017-04-27 18:25:11 -0700296 write32(&rk3399_grf->usbphy_ctrl[port][16], RK_CLRBITS(1 << 9));
Julius Werner1c8491c2016-08-15 17:58:05 -0700297
philipchen21b08522017-04-27 18:25:11 -0700298 if (port == 0)
299 setup_usb_otg0();
300 else
301 setup_usb_otg1();
Julius Wernerc49782c2016-11-21 20:14:18 -0800302
303 /*
304 * Need to power-cycle USB ports for use in firmware, since some devices
305 * can't fall back to USB 2.0 after they saw SuperSpeed terminations.
306 * This takes about a dozen milliseconds, so only do it in boot modes
307 * that have firmware UI (which one could select USB boot from).
308 */
philipchen21b08522017-04-27 18:25:11 -0700309 if (display_init_required())
310 usb_power_cycle(port);
Liangfeng Wu76655cb2016-05-26 16:06:58 +0800311}
312
huang lina6dbfb52016-03-02 18:38:40 +0800313static void mainboard_init(device_t dev)
314{
Brian Norrise06a1b82016-09-21 18:16:54 -0700315 deassert_wifi_power();
Vadim Bendebury1e80ab32016-03-28 00:44:54 -0700316 configure_sdmmc();
Lin Huang2f7ed8d2016-04-08 18:56:20 +0800317 configure_emmc();
Xing Zheng96fbc312016-05-19 11:39:20 +0800318 configure_codec();
Lin Huangb497b482016-03-31 18:44:13 +0800319 configure_display();
philipchen21b08522017-04-27 18:25:11 -0700320 setup_usb(0);
321 if (!IS_ENABLED(CONFIG_BOARD_GOOGLE_SCARLET))
322 setup_usb(1);
Lin Huang5a4be8a2016-05-17 15:45:53 +0800323 register_reset_to_bl31();
Lin Huang9a5c4fe2016-05-19 11:11:23 +0800324 register_poweroff_to_bl31();
Lin Huang7d8ccfb2016-08-22 17:35:40 -0700325 register_gpio_suspend();
Lin Huangc9fea5c2016-08-30 15:34:42 -0700326 register_apio_suspend();
Lin Huangb497b482016-03-31 18:44:13 +0800327}
328
Philip Chena304b692017-04-06 10:17:08 -0700329static void prepare_backlight_i2c(void)
Lin Huangb497b482016-03-31 18:44:13 +0800330{
Julius Werner7feb86b2016-09-02 11:25:56 -0700331 gpio_input(GPIO(1, B, 7)); /* I2C0_SDA remove pull_up */
332 gpio_input(GPIO(1, C, 0)); /* I2C0_SCL remove pull_up */
333
334 i2c_init(0, 100*KHz);
335
Lin Huangb497b482016-03-31 18:44:13 +0800336 write32(&rk3399_pmugrf->iomux_i2c0_sda, IOMUX_I2C0_SDA);
337 write32(&rk3399_pmugrf->iomux_i2c0_scl, IOMUX_I2C0_SCL);
Lin Huangb497b482016-03-31 18:44:13 +0800338}
339
340void mainboard_power_on_backlight(void)
341{
Vadim Bendeburyf1343df2016-05-22 15:53:37 -0700342 gpio_output(GPIO_BACKLIGHT, 1); /* BL_EN */
Lin Huangb497b482016-03-31 18:44:13 +0800343
Philip Chena304b692017-04-06 10:17:08 -0700344 if (IS_ENABLED(CONFIG_BOARD_GOOGLE_GRU))
345 prepare_backlight_i2c();
huang lina6dbfb52016-03-02 18:38:40 +0800346}
347
348static void mainboard_enable(device_t dev)
349{
350 dev->ops->init = &mainboard_init;
351}
352
353struct chip_operations mainboard_ops = {
354 .name = CONFIG_MAINBOARD_PART_NUMBER,
355 .enable_dev = mainboard_enable,
356};