blob: 336a9e5f4a35791734783739592251bebb5070d9 [file] [log] [blame]
Ronald G. Minnichf89e6b22012-12-10 16:13:43 -08001/*
Stefan Reinauer043eb0e2013-05-10 16:21:58 -07002 * This file is part of the coreboot project.
Ronald G. Minnichf89e6b22012-12-10 16:13:43 -08003 *
Stefan Reinauer08dc3572013-05-14 16:57:50 -07004 * Copyright 2013 Google Inc.
Stefan Reinauer043eb0e2013-05-10 16:21:58 -07005 *
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.
Ronald G. Minnichf89e6b22012-12-10 16:13:43 -08009 *
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.
Ronald G. Minnichf89e6b22012-12-10 16:13:43 -080014 */
15
Julius Werner1ed0c8c2014-10-20 13:16:29 -070016#include <arch/cache.h>
17#include <boot/coreboot_tables.h>
David Hendricks50c0a502013-01-31 17:05:50 -080018#include <console/console.h>
Julius Werner1ed0c8c2014-10-20 13:16:29 -070019#include <cbmem.h>
20#include <delay.h>
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070021#include <device/device.h>
Nico Huber0f2dd1e2017-08-01 14:02:40 +020022#include <device/i2c_simple.h>
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070023#include <drivers/ti/tps65090/tps65090.h>
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070024#include <edid.h>
Julius Werner1ed0c8c2014-10-20 13:16:29 -070025#include <soc/clk.h>
26#include <soc/dp.h>
27#include <soc/dp-core.h>
28#include <soc/gpio.h>
29#include <soc/i2c.h>
30#include <soc/periph.h>
31#include <soc/power.h>
32#include <soc/tmu.h>
33#include <soc/usb.h>
Julius Wernerec5e5e02014-08-20 15:29:56 -070034#include <symbols.h>
Julius Werner1ed0c8c2014-10-20 13:16:29 -070035#include <vbe.h>
David Hendricks0d4f97e2013-02-03 18:09:58 -080036
Stefan Reinauer043eb0e2013-05-10 16:21:58 -070037#include "exynos5250.h"
David Hendricks0d4f97e2013-02-03 18:09:58 -080038
Julius Wernerad4556f22013-08-21 17:33:31 -070039#define MMC0_GPIO_PIN (58)
40
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070041/* convenient shorthand (in MB) */
Julius Wernerec5e5e02014-08-20 15:29:56 -070042#define DRAM_START ((uintptr_t)_dram/MiB)
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070043#define DRAM_SIZE CONFIG_DRAM_SIZE_MB
44#define DRAM_END (DRAM_START + DRAM_SIZE) /* plus one... */
45
Stefan Reinauer043eb0e2013-05-10 16:21:58 -070046static struct edid edid = {
David Hendricks7dbf9c62015-07-30 18:49:48 -070047 .mode.ha = 1366,
48 .mode.va = 768,
Ronald G. Minnich9518b562013-09-19 16:45:22 -070049 .framebuffer_bits_per_pixel = 16,
Gabe Blackdcaaba42013-07-07 04:05:51 -070050 .x_resolution = 1366,
51 .y_resolution = 768,
52 .bytes_per_line = 2 * 1366
David Hendricks0d4f97e2013-02-03 18:09:58 -080053};
54
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070055/* TODO: transplanted DP stuff, clean up once we have something that works */
56static enum exynos5_gpio_pin dp_pd_l = GPIO_Y25; /* active low */
57static enum exynos5_gpio_pin dp_rst_l = GPIO_X15; /* active low */
58static enum exynos5_gpio_pin dp_hpd = GPIO_X07; /* active high */
59
60static void exynos_dp_bridge_setup(void)
Ronald G. Minnichf89e6b22012-12-10 16:13:43 -080061{
Gabe Blackfe640602013-06-15 20:33:05 -070062 exynos_pinmux_dphpd();
David Hendricks0d4f97e2013-02-03 18:09:58 -080063
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070064 gpio_set_value(dp_pd_l, 1);
Stefan Reinauerdc006c12013-05-15 14:54:07 -070065 gpio_cfg_pin(dp_pd_l, GPIO_OUTPUT);
66 gpio_set_pull(dp_pd_l, GPIO_PULL_NONE);
David Hendricks0d4f97e2013-02-03 18:09:58 -080067
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070068 gpio_set_value(dp_rst_l, 0);
Stefan Reinauerdc006c12013-05-15 14:54:07 -070069 gpio_cfg_pin(dp_rst_l, GPIO_OUTPUT);
70 gpio_set_pull(dp_rst_l, GPIO_PULL_NONE);
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070071 udelay(10);
72 gpio_set_value(dp_rst_l, 1);
Ronald G. Minnichf89e6b22012-12-10 16:13:43 -080073}
74
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070075static void exynos_dp_bridge_init(void)
76{
77 /* De-assert PD (and possibly RST) to power up the bridge */
78 gpio_set_value(dp_pd_l, 1);
79 gpio_set_value(dp_rst_l, 1);
80
81 /*
82 * We need to wait for 90ms after bringing up the bridge since
83 * there is a phantom "high" on the HPD chip during its
84 * bootup. The phantom high comes within 7ms of de-asserting
85 * PD and persists for at least 15ms. The real high comes
86 * roughly 50ms after PD is de-asserted. The phantom high
87 * makes it hard for us to know when the NXP chip is up.
88 */
89 udelay(90000);
90}
91
92static int exynos_dp_hotplug(void)
93{
94 /* Check HPD. If it's high, we're all good. */
95 return gpio_get_value(dp_hpd) ? 0 : 1;
96}
97
98static void exynos_dp_reset(void)
99{
100 gpio_set_value(dp_pd_l, 0);
101 gpio_set_value(dp_rst_l, 0);
102 /* paranoid delay period (300ms) */
103 udelay(300 * 1000);
104}
105
106/*
107 * This delay is T3 in the LCD timing spec (defined as >200ms). We set
108 * this down to 60ms since that's the approximate maximum amount of time
109 * it'll take a bridge to start outputting LVDS data. The delay of
110 * >200ms is just a conservative value to avoid turning on the backlight
111 * when there's random LCD data on the screen. Shaving 140ms off the
112 * boot is an acceptable trade-off.
113 */
114#define LCD_T3_DELAY_MS 60
115
116#define LCD_T5_DELAY_MS 10
117#define LCD_T6_DELAY_MS 10
118
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700119static void backlight_pwm(void)
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700120{
121 /*Configure backlight PWM as a simple output high (100% brightness) */
122 gpio_direction_output(GPIO_B20, 1);
123 udelay(LCD_T6_DELAY_MS * 1000);
124}
125
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700126static void backlight_en(void)
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700127{
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700128 /* Configure GPIO for LCD_BL_EN */
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700129 gpio_direction_output(GPIO_X30, 1);
130}
131
Gabe Black49c98dc2014-01-22 21:06:32 -0800132#define TPS65090_BUS 4 /* Daisy-specific */
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700133
134#define FET1_CTRL 0x0f
Julius Wernerad4556f22013-08-21 17:33:31 -0700135#define FET4_CTRL 0x12
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700136#define FET6_CTRL 0x14
137
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700138static void lcd_vdd(void)
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700139{
140 /* Enable FET6, lcd panel */
David Hendricks8ccabb62013-08-01 19:12:56 -0700141 tps65090_fet_enable(TPS65090_BUS, FET6_CTRL);
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700142}
143
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700144static void backlight_vdd(void)
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700145{
146 /* Enable FET1, backlight */
David Hendricks8ccabb62013-08-01 19:12:56 -0700147 tps65090_fet_enable(TPS65090_BUS, FET1_CTRL);
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700148 udelay(LCD_T5_DELAY_MS * 1000);
149}
150
Julius Wernerad4556f22013-08-21 17:33:31 -0700151static void sdmmc_vdd(void)
152{
153 /* Enable FET4, P3.3V_SDCARD */
154 tps65090_fet_enable(TPS65090_BUS, FET4_CTRL);
155}
156
Julius Werner79bff702013-08-15 17:34:45 -0700157static enum exynos5_gpio_pin usb_host_vbus = GPIO_X11;
158static enum exynos5_gpio_pin usb_drd_vbus = GPIO_X27;
159/* static enum exynos5_gpio_pin hsic_reset_l = GPIO_E10; */
160
Julius Werner68aef112013-09-03 15:07:31 -0700161static void prepare_usb(void)
162{
163 /* Kick this reset off early so it gets at least 100ms to settle */
164 reset_usb_drd_dwc3();
165}
166
Julius Werner79bff702013-08-15 17:34:45 -0700167static void setup_usb(void)
168{
169 /* HSIC not needed in firmware on this board */
Julius Werner68aef112013-09-03 15:07:31 -0700170 setup_usb_drd_phy();
171 setup_usb_drd_dwc3();
Julius Werner79bff702013-08-15 17:34:45 -0700172 setup_usb_host_phy(0);
173
174 gpio_direction_output(usb_host_vbus, 1);
175 gpio_direction_output(usb_drd_vbus, 1);
176}
177
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700178//static struct video_info smdk5250_dp_config = {
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700179static struct video_info dp_video_info = {
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700180 /* FIXME: fix video_info struct to use const for name */
181 .name = (char *)"eDP-LVDS NXP PTN3460",
182
183 .h_sync_polarity = 0,
184 .v_sync_polarity = 0,
185 .interlaced = 0,
186
187 .color_space = COLOR_RGB,
188 .dynamic_range = VESA,
189 .ycbcr_coeff = COLOR_YCBCR601,
190 .color_depth = COLOR_8,
191
192 .link_rate = LINK_RATE_2_70GBPS,
193 .lane_count = LANE_COUNT2,
194};
195
196/* FIXME: move some place more appropriate */
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700197#define MAX_DP_TRIES 5
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700198
199/*
200 * This function disables the USB3.0 PLL to save power
201 */
202static void disable_usb30_pll(void)
203{
204 enum exynos5_gpio_pin usb3_pll_l = GPIO_Y11;
205
206 gpio_direction_output(usb3_pll_l, 0);
207}
208
Julius Wernerad4556f22013-08-21 17:33:31 -0700209static void setup_storage(void)
210{
211 /* MMC0: Fixed, 8 bit mode, connected with GPIO. */
212 if (clock_set_mshci(PERIPH_ID_SDMMC0))
213 printk(BIOS_CRIT, "%s: Failed to set MMC0 clock.\n", __func__);
214 if (gpio_direction_output(MMC0_GPIO_PIN, 1)) {
215 printk(BIOS_CRIT, "%s: Unable to power on MMC0.\n", __func__);
216 }
217 gpio_set_pull(MMC0_GPIO_PIN, GPIO_PULL_NONE);
218 gpio_set_drv(MMC0_GPIO_PIN, GPIO_DRV_4X);
219 exynos_pinmux_sdmmc0();
220
221 /* MMC2: Removable, 4 bit mode, no GPIO. */
222 /* (Must be after romstage to avoid breaking SDMMC boot.) */
223 clock_set_mshci(PERIPH_ID_SDMMC2);
224 exynos_pinmux_sdmmc2();
225}
226
Gabe Black1387b432013-05-18 15:55:47 -0700227static void gpio_init(void)
228{
229 /* Set up the I2C busses. */
Gabe Blackfe640602013-06-15 20:33:05 -0700230 exynos_pinmux_i2c0();
231 exynos_pinmux_i2c1();
232 exynos_pinmux_i2c2();
233 exynos_pinmux_i2c3();
234 exynos_pinmux_i2c4();
235 exynos_pinmux_i2c7();
Gabe Black1387b432013-05-18 15:55:47 -0700236
237 /* Set up the GPIOs used to arbitrate for I2C bus 4. */
238 gpio_set_pull(GPIO_F03, GPIO_PULL_NONE);
239 gpio_set_pull(GPIO_E04, GPIO_PULL_NONE);
240 gpio_direction_output(GPIO_F03, 1);
241 gpio_direction_input(GPIO_E04);
242
243 /* Set up the GPIO used to enable the audio codec. */
244 gpio_set_pull(GPIO_X17, GPIO_PULL_NONE);
245 gpio_set_pull(GPIO_X15, GPIO_PULL_NONE);
246 gpio_direction_output(GPIO_X17, 1);
247 gpio_direction_output(GPIO_X15, 1);
248
249 /* Set up the I2S busses. */
Gabe Blacke6789c12013-08-05 22:19:36 -0700250 exynos_pinmux_i2s0();
Gabe Blackfe640602013-06-15 20:33:05 -0700251 exynos_pinmux_i2s1();
Gabe Black1387b432013-05-18 15:55:47 -0700252}
253
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700254/* this happens after cpu_init where exynos resources are set */
255static void mainboard_init(device_t dev)
256{
257 int dp_tries;
258 struct s5p_dp_device dp_device = {
Julius Wernerfa938c72013-08-29 14:17:36 -0700259 .base = exynos_dp1,
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700260 .video_info = &dp_video_info,
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700261 };
Stefan Reinauer66287442013-06-19 15:54:19 -0700262 void *fb_addr = (void *)(get_fb_base_kb() * KiB);
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700263
Julius Werner68aef112013-09-03 15:07:31 -0700264 prepare_usb();
Gabe Black1387b432013-05-18 15:55:47 -0700265 gpio_init();
Julius Wernerad4556f22013-08-21 17:33:31 -0700266 setup_storage();
Gabe Black1387b432013-05-18 15:55:47 -0700267
David Hendricks8ccabb62013-08-01 19:12:56 -0700268 i2c_init(TPS65090_BUS, I2C_0_SPEED, I2C_SLAVE);
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700269 i2c_init(7, I2C_0_SPEED, I2C_SLAVE);
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700270
271 tmu_init(&exynos5250_tmu_info);
272
273 /* Clock Gating all the unused IP's to save power */
274 clock_gate();
275
276 /* Disable USB3.0 PLL to save 250mW of power */
277 disable_usb30_pll();
278
Julius Wernerad4556f22013-08-21 17:33:31 -0700279 sdmmc_vdd();
280
Gabe Black1e797bd2013-05-18 15:58:46 -0700281 set_vbe_mode_info_valid(&edid, (uintptr_t)fb_addr);
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700282
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700283 lcd_vdd();
Stefan Reinauera86c33a2013-05-17 10:34:25 -0700284
285 // FIXME: should timeout
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700286 do {
287 udelay(50);
288 } while (!exynos_dp_hotplug());
289
290 exynos_dp_bridge_setup();
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700291 for (dp_tries = 1; dp_tries <= MAX_DP_TRIES; dp_tries++) {
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700292 exynos_dp_bridge_init();
293 if (exynos_dp_hotplug()) {
294 exynos_dp_reset();
295 continue;
296 }
297
298 if (dp_controller_init(&dp_device))
299 continue;
300
301 udelay(LCD_T3_DELAY_MS * 1000);
302
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700303 backlight_vdd();
304 backlight_pwm();
305 backlight_en();
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700306 /* if we're here, we're successful */
307 break;
308 }
309
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700310 if (dp_tries > MAX_DP_TRIES)
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700311 printk(BIOS_ERR, "%s: Failed to set up displayport\n", __func__);
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700312
Julius Werner68aef112013-09-03 15:07:31 -0700313 setup_usb();
314
Stefan Reinauera86c33a2013-05-17 10:34:25 -0700315 // Uncomment to get excessive GPIO output:
316 // gpio_info();
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700317}
318
319static void mainboard_enable(device_t dev)
320{
321 dev->ops->init = &mainboard_init;
322
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700323 /* set up dcache and MMU */
324 /* FIXME: this should happen via resource allocator */
325 exynos5250_config_l2_cache();
326 mmu_init();
327 mmu_config_range(0, DRAM_START, DCACHE_OFF);
328 mmu_config_range(DRAM_START, DRAM_SIZE, DCACHE_WRITEBACK);
Julius Wernerec5e5e02014-08-20 15:29:56 -0700329 mmu_config_range((uintptr_t)_dma_coherent/MiB,
330 _dma_coherent_size/MiB, DCACHE_OFF);
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700331 mmu_config_range(DRAM_END, 4096 - DRAM_END, DCACHE_OFF);
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700332 dcache_mmu_enable();
333
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700334 const unsigned epll_hz = 192000000;
335 const unsigned sample_rate = 48000;
336 const unsigned lr_frame_size = 256;
337 clock_epll_set_rate(epll_hz);
338 clock_select_i2s_clk_source();
339 clock_set_i2s_clk_prescaler(epll_hz, sample_rate * lr_frame_size);
340
341 power_enable_xclkout();
342}
343
Ronald G. Minnichf89e6b22012-12-10 16:13:43 -0800344struct chip_operations mainboard_ops = {
David Hendricks054c83a2015-01-09 11:46:43 -0800345 .name = "daisy",
346 .enable_dev = mainboard_enable,
Ronald G. Minnichf89e6b22012-12-10 16:13:43 -0800347};
Julius Wernerb8fad3d2013-08-27 15:48:32 -0700348
349void lb_board(struct lb_header *header)
350{
351 struct lb_range *dma;
352
353 dma = (struct lb_range *)lb_new_record(header);
354 dma->tag = LB_TAB_DMA;
355 dma->size = sizeof(*dma);
Julius Wernerec5e5e02014-08-20 15:29:56 -0700356 dma->range_start = (uintptr_t)_dma_coherent;
357 dma->range_size = _dma_coherent_size;
Julius Wernerb8fad3d2013-08-27 15:48:32 -0700358}