blob: dd986c4348543abfebcfa5e0e69fba1d4fb888e6 [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
Vadim Bendebury8e8a00c2016-04-22 12:25:07 -070017#include <boardid.h>
Julius Wernerc49782c2016-11-21 20:14:18 -080018#include <console/console.h>
Lin Huangb497b482016-03-31 18:44:13 +080019#include <delay.h>
huang lina6dbfb52016-03-02 18:38:40 +080020#include <device/device.h>
Lin Huangb497b482016-03-31 18:44:13 +080021#include <device/i2c.h>
Julius Wernerc49782c2016-11-21 20:14:18 -080022#include <ec/google/chromeec/ec.h>
Vadim Bendebury1e80ab32016-03-28 00:44:54 -070023#include <gpio.h>
Lin Huang5a4be8a2016-05-17 15:45:53 +080024#include <soc/bl31_plat_params.h>
Vadim Bendebury1e80ab32016-03-28 00:44:54 -070025#include <soc/clock.h>
Lin Huangb497b482016-03-31 18:44:13 +080026#include <soc/display.h>
Vadim Bendebury1e80ab32016-03-28 00:44:54 -070027#include <soc/grf.h>
Lin Huangb497b482016-03-31 18:44:13 +080028#include <soc/i2c.h>
Liangfeng Wu76655cb2016-05-26 16:06:58 +080029#include <soc/usb.h>
Simon Glassbc679bc2016-06-19 16:09:21 -060030#include <vendorcode/google/chromeos/chromeos.h>
Vadim Bendebury1e80ab32016-03-28 00:44:54 -070031
Vadim Bendebury993dbe12016-05-22 15:53:37 -070032#include "board.h"
33
Brian Norrise06a1b82016-09-21 18:16:54 -070034/*
35 * Wifi's PDN/RST line is pulled down by its (unpowered) voltage rails, but
36 * this reset pin is pulled up by default. Let's drive it low as early as we
37 * can.
38 */
39static void deassert_wifi_power(void)
40{
41 gpio_output(GPIO(1, B, 3), 0); /* Assert WLAN_MODULE_RST# */
42}
43
Lin Huang2f7ed8d2016-04-08 18:56:20 +080044static void configure_emmc(void)
45{
46 /* Host controller does not support programmable clock generator.
47 * If we don't do this setting, when we use phy to control the
48 * emmc clock(when clock exceed 50MHz), it will get wrong clock.
49 *
50 * Refer to TRM V0.3 Part 1 Chapter 15 PAGE 782 for this register.
51 * Please search "_CON11[7:0]" to locate register description.
52 */
53 write32(&rk3399_grf->emmccore_con[11], RK_CLRSETBITS(0xff, 0));
54
55 rkclk_configure_emmc();
56}
57
Lin Huangc9fea5c2016-08-30 15:34:42 -070058static void register_apio_suspend(void)
59{
60 static struct bl31_apio_param param_apio = {
61 .h = {
62 .type = PARAM_SUSPEND_APIO,
63 },
64 .apio = {
65 .apio1 = 1,
66 .apio2 = 1,
67 .apio3 = 1,
68 .apio4 = 1,
69 .apio5 = 1,
70 },
71 };
72 register_bl31_param(&param_apio.h);
73}
74
Lin Huang7d8ccfb2016-08-22 17:35:40 -070075static void register_gpio_suspend(void)
76{
77 /*
78 * These three GPIO params are used to shut down the 1.5V, 1.8V and
79 * 3.3V power rails, which need to be shut down ordered by voltage,
80 * with highest voltage first.
81 * Since register_bl31() appends to the front of the list, we need to
82 * register them backwards, with 1.5V coming first.
83 */
84 static struct bl31_gpio_param param_p15_en = {
85 .h = {
86 .type = PARAM_SUSPEND_GPIO,
87 },
88 .gpio = {
89 .polarity = BL31_GPIO_LEVEL_LOW,
90 },
91 };
92 param_p15_en.gpio.index = GET_GPIO_NUM(GPIO_P15V_EN);
93 register_bl31_param(&param_p15_en.h);
94
95 static struct bl31_gpio_param param_p18_audio_en = {
96 .h = {
97 .type = PARAM_SUSPEND_GPIO,
98 },
99 .gpio = {
100 .polarity = BL31_GPIO_LEVEL_LOW,
101 },
102 };
103 param_p18_audio_en.gpio.index = GET_GPIO_NUM(GPIO_P18V_AUDIO_PWREN);
104 register_bl31_param(&param_p18_audio_en.h);
105
106 static struct bl31_gpio_param param_p30_en = {
107 .h = {
108 .type = PARAM_SUSPEND_GPIO,
109 },
110 .gpio = {
111 .polarity = BL31_GPIO_LEVEL_LOW,
112 },
113 };
114 param_p30_en.gpio.index = GET_GPIO_NUM(GPIO_P30V_EN);
115 register_bl31_param(&param_p30_en.h);
116}
117
Lin Huang5a4be8a2016-05-17 15:45:53 +0800118static void register_reset_to_bl31(void)
119{
120 static struct bl31_gpio_param param_reset = {
121 .h = {
122 .type = PARAM_RESET,
123 },
124 .gpio = {
125 .polarity = 1,
126 },
127 };
128
129 /* gru/kevin reset pin: gpio0b3 */
130 param_reset.gpio.index = GET_GPIO_NUM(GPIO_RESET),
131
132 register_bl31_param(&param_reset.h);
133}
134
Lin Huang9a5c4fe2016-05-19 11:11:23 +0800135static void register_poweroff_to_bl31(void)
136{
137 static struct bl31_gpio_param param_poweroff = {
138 .h = {
139 .type = PARAM_POWEROFF,
140 },
141 .gpio = {
142 .polarity = 1,
143 },
144 };
145
146 /*
147 * gru/kevin power off pin: gpio1a6,
148 * reuse with tsadc int pin, so iomux need set back to
149 * gpio in BL31 and depthcharge before you setting this gpio
150 */
151 param_poweroff.gpio.index = GET_GPIO_NUM(GPIO_POWEROFF),
152
153 register_bl31_param(&param_poweroff.h);
154}
155
Vadim Bendebury1e80ab32016-03-28 00:44:54 -0700156static void configure_sdmmc(void)
157{
158 gpio_output(GPIO(4, D, 5), 1); /* SDMMC_PWR_EN */
159 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
Liangfeng Wu76655cb2016-05-26 16:06:58 +0800246static void setup_usb(void)
247{
Julius Werner1c8491c2016-08-15 17:58:05 -0700248 /* A few magic PHY tuning values that improve eye diagram amplitude
249 * and make it extra sure we get reliable communication in firmware. */
250 /* Set max ODT compensation voltage and current tuning reference. */
William wu9f470b12016-11-10 19:34:45 +0800251 write32(&rk3399_grf->usbphy0_ctrl[3], RK_CLRSETBITS(0xfff, 0x2e3));
252 write32(&rk3399_grf->usbphy1_ctrl[3], RK_CLRSETBITS(0xfff, 0x2e3));
253
William wu5b1bb3d2016-09-29 15:18:41 +0800254 if (IS_ENABLED(CONFIG_BOARD_GOOGLE_KEVIN)) {
William wu9f470b12016-11-10 19:34:45 +0800255 /* Set max pre-emphasis level, only on Kevin PHY0 and PHY1 */
256 write32(&rk3399_grf->usbphy0_ctrl[12],
257 RK_CLRSETBITS(0xffff, 0xa7));
258 write32(&rk3399_grf->usbphy1_ctrl[12],
259 RK_CLRSETBITS(0xffff, 0xa7));
260
261 /* Disable the pre-emphasize in eop state and chirp
262 * state to avoid mis-trigger the disconnect detection
263 * and also avoid high-speed handshake fail */
264 write32(&rk3399_grf->usbphy0_ctrl[0], RK_CLRBITS(0x3));
265 write32(&rk3399_grf->usbphy1_ctrl[0], RK_CLRBITS(0x3));
266 write32(&rk3399_grf->usbphy0_ctrl[13], RK_CLRBITS(0x3));
267 write32(&rk3399_grf->usbphy1_ctrl[13], RK_CLRBITS(0x3));
268
269 /* ODT auto compensation bypass, set max driver strength */
270 write32(&rk3399_grf->usbphy0_ctrl[2],
271 RK_CLRSETBITS(0x7e << 4, 0x60 << 4));
272 write32(&rk3399_grf->usbphy1_ctrl[2],
273 RK_CLRSETBITS(0x7e << 4, 0x60 << 4));
274
275 /* ODT auto refresh bypass, and set the max
276 * bias current tuning reference */
277 write32(&rk3399_grf->usbphy0_ctrl[3],
278 RK_CLRSETBITS(0x21c, 1 << 4));
279 write32(&rk3399_grf->usbphy1_ctrl[3],
280 RK_CLRSETBITS(0x21c, 1 << 4));
William wu5b1bb3d2016-09-29 15:18:41 +0800281 }
Julius Werner1c8491c2016-08-15 17:58:05 -0700282
Julius Werner785ff1b2016-08-03 19:18:39 -0700283 setup_usb_otg0();
284 setup_usb_otg1();
Julius Wernerc49782c2016-11-21 20:14:18 -0800285
286 /*
287 * Need to power-cycle USB ports for use in firmware, since some devices
288 * can't fall back to USB 2.0 after they saw SuperSpeed terminations.
289 * This takes about a dozen milliseconds, so only do it in boot modes
290 * that have firmware UI (which one could select USB boot from).
291 */
292 if (display_init_required()) {
293 usb_power_cycle(0);
294 usb_power_cycle(1);
295 }
Liangfeng Wu76655cb2016-05-26 16:06:58 +0800296}
297
huang lina6dbfb52016-03-02 18:38:40 +0800298static void mainboard_init(device_t dev)
299{
Brian Norrise06a1b82016-09-21 18:16:54 -0700300 deassert_wifi_power();
Vadim Bendebury1e80ab32016-03-28 00:44:54 -0700301 configure_sdmmc();
Lin Huang2f7ed8d2016-04-08 18:56:20 +0800302 configure_emmc();
Xing Zheng96fbc312016-05-19 11:39:20 +0800303 configure_codec();
Lin Huangb497b482016-03-31 18:44:13 +0800304 configure_display();
Liangfeng Wu76655cb2016-05-26 16:06:58 +0800305 setup_usb();
Lin Huang5a4be8a2016-05-17 15:45:53 +0800306 register_reset_to_bl31();
Lin Huang9a5c4fe2016-05-19 11:11:23 +0800307 register_poweroff_to_bl31();
Lin Huang7d8ccfb2016-08-22 17:35:40 -0700308 register_gpio_suspend();
Lin Huangc9fea5c2016-08-30 15:34:42 -0700309 register_apio_suspend();
Lin Huangb497b482016-03-31 18:44:13 +0800310}
311
312static void enable_backlight_booster(void)
313{
314 const struct {
315 uint8_t reg;
316 uint8_t value;
317 } i2c_writes[] = {
318 {1, 0x84},
319 {1, 0x85},
320 {0, 0x26}
321 };
322 int i;
323 const int booster_i2c_port = 0;
324 uint8_t i2c_buf[2];
325 struct i2c_seg i2c_command = { .read = 0, .chip = 0x2c,
326 .buf = i2c_buf, .len = sizeof(i2c_buf)
327 };
328
329 /*
330 * This function is called on Gru right after BL_EN is asserted. It
331 * takes time for the switcher chip to come online, let's wait a bit
332 * to let the voltage settle, so that the chip can be accessed.
333 */
334 udelay(1000);
335
Julius Werner7feb86b2016-09-02 11:25:56 -0700336 gpio_input(GPIO(1, B, 7)); /* I2C0_SDA remove pull_up */
337 gpio_input(GPIO(1, C, 0)); /* I2C0_SCL remove pull_up */
338
339 i2c_init(0, 100*KHz);
340
Lin Huangb497b482016-03-31 18:44:13 +0800341 write32(&rk3399_pmugrf->iomux_i2c0_sda, IOMUX_I2C0_SDA);
342 write32(&rk3399_pmugrf->iomux_i2c0_scl, IOMUX_I2C0_SCL);
Lin Huangb497b482016-03-31 18:44:13 +0800343
344 for (i = 0; i < ARRAY_SIZE(i2c_writes); i++) {
345 i2c_buf[0] = i2c_writes[i].reg;
346 i2c_buf[1] = i2c_writes[i].value;
347 i2c_transfer(booster_i2c_port, &i2c_command, 1);
348 }
349}
350
351void mainboard_power_on_backlight(void)
352{
353 gpio_output(GPIO(1, C, 1), 1); /* BL_EN */
354
Julius Werner5e6771b2016-07-29 16:15:04 -0700355 if (IS_ENABLED(CONFIG_BOARD_GOOGLE_GRU) && board_id() == 0)
Lin Huangb497b482016-03-31 18:44:13 +0800356 enable_backlight_booster();
huang lina6dbfb52016-03-02 18:38:40 +0800357}
358
359static void mainboard_enable(device_t dev)
360{
361 dev->ops->init = &mainboard_init;
362}
363
364struct chip_operations mainboard_ops = {
365 .name = CONFIG_MAINBOARD_PART_NUMBER,
366 .enable_dev = mainboard_enable,
367};