blob: e2ad5b0eb8b83ea81db051d065ba0f288bd88940 [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.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Stefan Reinauer043eb0e2013-05-10 16:21:58 -070017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Ronald G. Minnichf89e6b22012-12-10 16:13:43 -080018 */
19
Julius Werner1ed0c8c2014-10-20 13:16:29 -070020#include <arch/cache.h>
21#include <boot/coreboot_tables.h>
David Hendricks50c0a502013-01-31 17:05:50 -080022#include <console/console.h>
Julius Werner1ed0c8c2014-10-20 13:16:29 -070023#include <cbmem.h>
24#include <delay.h>
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070025#include <device/device.h>
26#include <device/i2c.h>
27#include <drivers/ti/tps65090/tps65090.h>
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070028#include <edid.h>
Julius Werner1ed0c8c2014-10-20 13:16:29 -070029#include <soc/clk.h>
30#include <soc/dp.h>
31#include <soc/dp-core.h>
32#include <soc/gpio.h>
33#include <soc/i2c.h>
34#include <soc/periph.h>
35#include <soc/power.h>
36#include <soc/tmu.h>
37#include <soc/usb.h>
Julius Wernerec5e5e02014-08-20 15:29:56 -070038#include <symbols.h>
Julius Werner1ed0c8c2014-10-20 13:16:29 -070039#include <vbe.h>
David Hendricks0d4f97e2013-02-03 18:09:58 -080040
Stefan Reinauer043eb0e2013-05-10 16:21:58 -070041#include "exynos5250.h"
David Hendricks0d4f97e2013-02-03 18:09:58 -080042
Julius Wernerad4556f22013-08-21 17:33:31 -070043#define MMC0_GPIO_PIN (58)
44
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070045/* convenient shorthand (in MB) */
Julius Wernerec5e5e02014-08-20 15:29:56 -070046#define DRAM_START ((uintptr_t)_dram/MiB)
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070047#define DRAM_SIZE CONFIG_DRAM_SIZE_MB
48#define DRAM_END (DRAM_START + DRAM_SIZE) /* plus one... */
49
Stefan Reinauer043eb0e2013-05-10 16:21:58 -070050static struct edid edid = {
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070051 .ha = 1366,
52 .va = 768,
Ronald G. Minnich9518b562013-09-19 16:45:22 -070053 .framebuffer_bits_per_pixel = 16,
Gabe Blackdcaaba42013-07-07 04:05:51 -070054 .x_resolution = 1366,
55 .y_resolution = 768,
56 .bytes_per_line = 2 * 1366
David Hendricks0d4f97e2013-02-03 18:09:58 -080057};
58
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070059/* TODO: transplanted DP stuff, clean up once we have something that works */
60static enum exynos5_gpio_pin dp_pd_l = GPIO_Y25; /* active low */
61static enum exynos5_gpio_pin dp_rst_l = GPIO_X15; /* active low */
62static enum exynos5_gpio_pin dp_hpd = GPIO_X07; /* active high */
63
64static void exynos_dp_bridge_setup(void)
Ronald G. Minnichf89e6b22012-12-10 16:13:43 -080065{
Gabe Blackfe640602013-06-15 20:33:05 -070066 exynos_pinmux_dphpd();
David Hendricks0d4f97e2013-02-03 18:09:58 -080067
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070068 gpio_set_value(dp_pd_l, 1);
Stefan Reinauerdc006c12013-05-15 14:54:07 -070069 gpio_cfg_pin(dp_pd_l, GPIO_OUTPUT);
70 gpio_set_pull(dp_pd_l, GPIO_PULL_NONE);
David Hendricks0d4f97e2013-02-03 18:09:58 -080071
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070072 gpio_set_value(dp_rst_l, 0);
Stefan Reinauerdc006c12013-05-15 14:54:07 -070073 gpio_cfg_pin(dp_rst_l, GPIO_OUTPUT);
74 gpio_set_pull(dp_rst_l, GPIO_PULL_NONE);
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070075 udelay(10);
76 gpio_set_value(dp_rst_l, 1);
Ronald G. Minnichf89e6b22012-12-10 16:13:43 -080077}
78
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -070079static void exynos_dp_bridge_init(void)
80{
81 /* De-assert PD (and possibly RST) to power up the bridge */
82 gpio_set_value(dp_pd_l, 1);
83 gpio_set_value(dp_rst_l, 1);
84
85 /*
86 * We need to wait for 90ms after bringing up the bridge since
87 * there is a phantom "high" on the HPD chip during its
88 * bootup. The phantom high comes within 7ms of de-asserting
89 * PD and persists for at least 15ms. The real high comes
90 * roughly 50ms after PD is de-asserted. The phantom high
91 * makes it hard for us to know when the NXP chip is up.
92 */
93 udelay(90000);
94}
95
96static int exynos_dp_hotplug(void)
97{
98 /* Check HPD. If it's high, we're all good. */
99 return gpio_get_value(dp_hpd) ? 0 : 1;
100}
101
102static void exynos_dp_reset(void)
103{
104 gpio_set_value(dp_pd_l, 0);
105 gpio_set_value(dp_rst_l, 0);
106 /* paranoid delay period (300ms) */
107 udelay(300 * 1000);
108}
109
110/*
111 * This delay is T3 in the LCD timing spec (defined as >200ms). We set
112 * this down to 60ms since that's the approximate maximum amount of time
113 * it'll take a bridge to start outputting LVDS data. The delay of
114 * >200ms is just a conservative value to avoid turning on the backlight
115 * when there's random LCD data on the screen. Shaving 140ms off the
116 * boot is an acceptable trade-off.
117 */
118#define LCD_T3_DELAY_MS 60
119
120#define LCD_T5_DELAY_MS 10
121#define LCD_T6_DELAY_MS 10
122
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700123static void backlight_pwm(void)
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700124{
125 /*Configure backlight PWM as a simple output high (100% brightness) */
126 gpio_direction_output(GPIO_B20, 1);
127 udelay(LCD_T6_DELAY_MS * 1000);
128}
129
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700130static void backlight_en(void)
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700131{
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700132 /* Configure GPIO for LCD_BL_EN */
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700133 gpio_direction_output(GPIO_X30, 1);
134}
135
Gabe Black49c98dc2014-01-22 21:06:32 -0800136#define TPS65090_BUS 4 /* Daisy-specific */
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700137
138#define FET1_CTRL 0x0f
Julius Wernerad4556f22013-08-21 17:33:31 -0700139#define FET4_CTRL 0x12
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700140#define FET6_CTRL 0x14
141
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700142static void lcd_vdd(void)
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700143{
144 /* Enable FET6, lcd panel */
David Hendricks8ccabb62013-08-01 19:12:56 -0700145 tps65090_fet_enable(TPS65090_BUS, FET6_CTRL);
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700146}
147
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700148static void backlight_vdd(void)
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700149{
150 /* Enable FET1, backlight */
David Hendricks8ccabb62013-08-01 19:12:56 -0700151 tps65090_fet_enable(TPS65090_BUS, FET1_CTRL);
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700152 udelay(LCD_T5_DELAY_MS * 1000);
153}
154
Julius Wernerad4556f22013-08-21 17:33:31 -0700155static void sdmmc_vdd(void)
156{
157 /* Enable FET4, P3.3V_SDCARD */
158 tps65090_fet_enable(TPS65090_BUS, FET4_CTRL);
159}
160
Julius Werner79bff702013-08-15 17:34:45 -0700161static enum exynos5_gpio_pin usb_host_vbus = GPIO_X11;
162static enum exynos5_gpio_pin usb_drd_vbus = GPIO_X27;
163/* static enum exynos5_gpio_pin hsic_reset_l = GPIO_E10; */
164
Julius Werner68aef112013-09-03 15:07:31 -0700165static void prepare_usb(void)
166{
167 /* Kick this reset off early so it gets at least 100ms to settle */
168 reset_usb_drd_dwc3();
169}
170
Julius Werner79bff702013-08-15 17:34:45 -0700171static void setup_usb(void)
172{
173 /* HSIC not needed in firmware on this board */
Julius Werner68aef112013-09-03 15:07:31 -0700174 setup_usb_drd_phy();
175 setup_usb_drd_dwc3();
Julius Werner79bff702013-08-15 17:34:45 -0700176 setup_usb_host_phy(0);
177
178 gpio_direction_output(usb_host_vbus, 1);
179 gpio_direction_output(usb_drd_vbus, 1);
180}
181
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700182//static struct video_info smdk5250_dp_config = {
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700183static struct video_info dp_video_info = {
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700184 /* FIXME: fix video_info struct to use const for name */
185 .name = (char *)"eDP-LVDS NXP PTN3460",
186
187 .h_sync_polarity = 0,
188 .v_sync_polarity = 0,
189 .interlaced = 0,
190
191 .color_space = COLOR_RGB,
192 .dynamic_range = VESA,
193 .ycbcr_coeff = COLOR_YCBCR601,
194 .color_depth = COLOR_8,
195
196 .link_rate = LINK_RATE_2_70GBPS,
197 .lane_count = LANE_COUNT2,
198};
199
200/* FIXME: move some place more appropriate */
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700201#define MAX_DP_TRIES 5
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700202
203/*
204 * This function disables the USB3.0 PLL to save power
205 */
206static void disable_usb30_pll(void)
207{
208 enum exynos5_gpio_pin usb3_pll_l = GPIO_Y11;
209
210 gpio_direction_output(usb3_pll_l, 0);
211}
212
Julius Wernerad4556f22013-08-21 17:33:31 -0700213static void setup_storage(void)
214{
215 /* MMC0: Fixed, 8 bit mode, connected with GPIO. */
216 if (clock_set_mshci(PERIPH_ID_SDMMC0))
217 printk(BIOS_CRIT, "%s: Failed to set MMC0 clock.\n", __func__);
218 if (gpio_direction_output(MMC0_GPIO_PIN, 1)) {
219 printk(BIOS_CRIT, "%s: Unable to power on MMC0.\n", __func__);
220 }
221 gpio_set_pull(MMC0_GPIO_PIN, GPIO_PULL_NONE);
222 gpio_set_drv(MMC0_GPIO_PIN, GPIO_DRV_4X);
223 exynos_pinmux_sdmmc0();
224
225 /* MMC2: Removable, 4 bit mode, no GPIO. */
226 /* (Must be after romstage to avoid breaking SDMMC boot.) */
227 clock_set_mshci(PERIPH_ID_SDMMC2);
228 exynos_pinmux_sdmmc2();
229}
230
Gabe Black1387b432013-05-18 15:55:47 -0700231static void gpio_init(void)
232{
233 /* Set up the I2C busses. */
Gabe Blackfe640602013-06-15 20:33:05 -0700234 exynos_pinmux_i2c0();
235 exynos_pinmux_i2c1();
236 exynos_pinmux_i2c2();
237 exynos_pinmux_i2c3();
238 exynos_pinmux_i2c4();
239 exynos_pinmux_i2c7();
Gabe Black1387b432013-05-18 15:55:47 -0700240
241 /* Set up the GPIOs used to arbitrate for I2C bus 4. */
242 gpio_set_pull(GPIO_F03, GPIO_PULL_NONE);
243 gpio_set_pull(GPIO_E04, GPIO_PULL_NONE);
244 gpio_direction_output(GPIO_F03, 1);
245 gpio_direction_input(GPIO_E04);
246
247 /* Set up the GPIO used to enable the audio codec. */
248 gpio_set_pull(GPIO_X17, GPIO_PULL_NONE);
249 gpio_set_pull(GPIO_X15, GPIO_PULL_NONE);
250 gpio_direction_output(GPIO_X17, 1);
251 gpio_direction_output(GPIO_X15, 1);
252
253 /* Set up the I2S busses. */
Gabe Blacke6789c12013-08-05 22:19:36 -0700254 exynos_pinmux_i2s0();
Gabe Blackfe640602013-06-15 20:33:05 -0700255 exynos_pinmux_i2s1();
Gabe Black1387b432013-05-18 15:55:47 -0700256}
257
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700258/* this happens after cpu_init where exynos resources are set */
259static void mainboard_init(device_t dev)
260{
261 int dp_tries;
262 struct s5p_dp_device dp_device = {
Julius Wernerfa938c72013-08-29 14:17:36 -0700263 .base = exynos_dp1,
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700264 .video_info = &dp_video_info,
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700265 };
Stefan Reinauer66287442013-06-19 15:54:19 -0700266 void *fb_addr = (void *)(get_fb_base_kb() * KiB);
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700267
Julius Werner68aef112013-09-03 15:07:31 -0700268 prepare_usb();
Gabe Black1387b432013-05-18 15:55:47 -0700269 gpio_init();
Julius Wernerad4556f22013-08-21 17:33:31 -0700270 setup_storage();
Gabe Black1387b432013-05-18 15:55:47 -0700271
David Hendricks8ccabb62013-08-01 19:12:56 -0700272 i2c_init(TPS65090_BUS, I2C_0_SPEED, I2C_SLAVE);
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700273 i2c_init(7, I2C_0_SPEED, I2C_SLAVE);
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700274
275 tmu_init(&exynos5250_tmu_info);
276
277 /* Clock Gating all the unused IP's to save power */
278 clock_gate();
279
280 /* Disable USB3.0 PLL to save 250mW of power */
281 disable_usb30_pll();
282
Julius Wernerad4556f22013-08-21 17:33:31 -0700283 sdmmc_vdd();
284
Gabe Black1e797bd2013-05-18 15:58:46 -0700285 set_vbe_mode_info_valid(&edid, (uintptr_t)fb_addr);
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700286
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700287 lcd_vdd();
Stefan Reinauera86c33a2013-05-17 10:34:25 -0700288
289 // FIXME: should timeout
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700290 do {
291 udelay(50);
292 } while (!exynos_dp_hotplug());
293
294 exynos_dp_bridge_setup();
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700295 for (dp_tries = 1; dp_tries <= MAX_DP_TRIES; dp_tries++) {
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700296 exynos_dp_bridge_init();
297 if (exynos_dp_hotplug()) {
298 exynos_dp_reset();
299 continue;
300 }
301
302 if (dp_controller_init(&dp_device))
303 continue;
304
305 udelay(LCD_T3_DELAY_MS * 1000);
306
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700307 backlight_vdd();
308 backlight_pwm();
309 backlight_en();
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700310 /* if we're here, we're successful */
311 break;
312 }
313
Stefan Reinauer043eb0e2013-05-10 16:21:58 -0700314 if (dp_tries > MAX_DP_TRIES)
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700315 printk(BIOS_ERR, "%s: Failed to set up displayport\n", __func__);
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700316
Julius Werner68aef112013-09-03 15:07:31 -0700317 setup_usb();
318
Stefan Reinauera86c33a2013-05-17 10:34:25 -0700319 // Uncomment to get excessive GPIO output:
320 // gpio_info();
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700321}
322
323static void mainboard_enable(device_t dev)
324{
325 dev->ops->init = &mainboard_init;
326
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700327 /* set up dcache and MMU */
328 /* FIXME: this should happen via resource allocator */
329 exynos5250_config_l2_cache();
330 mmu_init();
331 mmu_config_range(0, DRAM_START, DCACHE_OFF);
332 mmu_config_range(DRAM_START, DRAM_SIZE, DCACHE_WRITEBACK);
Julius Wernerec5e5e02014-08-20 15:29:56 -0700333 mmu_config_range((uintptr_t)_dma_coherent/MiB,
334 _dma_coherent_size/MiB, DCACHE_OFF);
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700335 mmu_config_range(DRAM_END, 4096 - DRAM_END, DCACHE_OFF);
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700336 dcache_mmu_enable();
337
Stefan Reinauer2ae6d6f2013-05-09 16:16:13 -0700338 const unsigned epll_hz = 192000000;
339 const unsigned sample_rate = 48000;
340 const unsigned lr_frame_size = 256;
341 clock_epll_set_rate(epll_hz);
342 clock_select_i2s_clk_source();
343 clock_set_i2s_clk_prescaler(epll_hz, sample_rate * lr_frame_size);
344
345 power_enable_xclkout();
346}
347
Ronald G. Minnichf89e6b22012-12-10 16:13:43 -0800348struct chip_operations mainboard_ops = {
David Hendricks054c83a2015-01-09 11:46:43 -0800349 .name = "daisy",
350 .enable_dev = mainboard_enable,
Ronald G. Minnichf89e6b22012-12-10 16:13:43 -0800351};
Julius Wernerb8fad3d2013-08-27 15:48:32 -0700352
353void lb_board(struct lb_header *header)
354{
355 struct lb_range *dma;
356
357 dma = (struct lb_range *)lb_new_record(header);
358 dma->tag = LB_TAB_DMA;
359 dma->size = sizeof(*dma);
Julius Wernerec5e5e02014-08-20 15:29:56 -0700360 dma->range_start = (uintptr_t)_dma_coherent;
361 dma->range_size = _dma_coherent_size;
Julius Wernerb8fad3d2013-08-27 15:48:32 -0700362}