blob: b91040cc3f72186014093401b5201a2e760b314f [file] [log] [blame]
Gabe Blackd3163ab2013-05-16 05:53:40 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2013 Google 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 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <console/console.h>
21#include <device/device.h>
22#include <device/i2c.h>
Gabe Blackd3163ab2013-05-16 05:53:40 -070023#include <cbmem.h>
24#include <delay.h>
25#include <edid.h>
26#include <vbe.h>
27#include <boot/coreboot_tables.h>
28#include <arch/cache.h>
29#include <arch/exception.h>
30#include <cpu/samsung/exynos5420/tmu.h>
31#include <cpu/samsung/exynos5420/clk.h>
32#include <cpu/samsung/exynos5420/cpu.h>
33#include <cpu/samsung/exynos5420/gpio.h>
34#include <cpu/samsung/exynos5420/power.h>
35#include <cpu/samsung/exynos5420/i2c.h>
36#include <cpu/samsung/exynos5420/dp-core.h>
Gabe Blackd686acd2013-06-30 05:19:53 -070037#include <drivers/parade/ps8625/ps8625.h>
Gabe Blackc0b21442013-06-28 14:27:16 -070038#include <ec/google/chromeec/ec.h>
Gabe Blackd686acd2013-06-30 05:19:53 -070039#include <stdlib.h>
Gabe Blackd3163ab2013-05-16 05:53:40 -070040
41#include "exynos5420.h"
42
43/* convenient shorthand (in MB) */
44#define DRAM_START (CONFIG_SYS_SDRAM_BASE >> 20)
45#define DRAM_SIZE CONFIG_DRAM_SIZE_MB
46#define DRAM_END (DRAM_START + DRAM_SIZE) /* plus one... */
47
48static struct edid edid = {
49 .ha = 1366,
50 .va = 768,
51 .bpp = 16,
52};
53
54/* TODO: transplanted DP stuff, clean up once we have something that works */
Gabe Black63bb6102013-06-19 03:29:45 -070055static enum exynos5_gpio_pin dp_pd_l = GPIO_X35; /* active low */
56static enum exynos5_gpio_pin dp_rst_l = GPIO_Y77; /* active low */
57static enum exynos5_gpio_pin dp_hpd = GPIO_X26; /* active high */
58static enum exynos5_gpio_pin bl_pwm = GPIO_B20; /* active high */
59static enum exynos5_gpio_pin bl_en = GPIO_X22; /* active high */
Gabe Blackd3163ab2013-05-16 05:53:40 -070060
Gabe Blackd686acd2013-06-30 05:19:53 -070061static void parade_dp_bridge_setup(void)
Gabe Blackd3163ab2013-05-16 05:53:40 -070062{
Gabe Blackd3163ab2013-05-16 05:53:40 -070063 gpio_set_value(dp_pd_l, 1);
64 gpio_cfg_pin(dp_pd_l, GPIO_OUTPUT);
65 gpio_set_pull(dp_pd_l, GPIO_PULL_NONE);
66
67 gpio_set_value(dp_rst_l, 0);
68 gpio_cfg_pin(dp_rst_l, GPIO_OUTPUT);
69 gpio_set_pull(dp_rst_l, GPIO_PULL_NONE);
70 udelay(10);
71 gpio_set_value(dp_rst_l, 1);
Gabe Blackc0b21442013-06-28 14:27:16 -070072
73 gpio_cfg_pin(dp_hpd, GPIO_INPUT);
Gabe Blackd3163ab2013-05-16 05:53:40 -070074
Gabe Blackd686acd2013-06-30 05:19:53 -070075 /* De-assert PD (and possibly RST) to power up the bridge. */
Gabe Blackd3163ab2013-05-16 05:53:40 -070076 gpio_set_value(dp_pd_l, 1);
77 gpio_set_value(dp_rst_l, 1);
78
Gabe Blackd686acd2013-06-30 05:19:53 -070079 /* Hang around for the bridge to come up. */
80 mdelay(40);
Gabe Blackd3163ab2013-05-16 05:53:40 -070081
Gabe Blackd686acd2013-06-30 05:19:53 -070082 /* Configure the bridge chip. */
83 exynos_pinmux_i2c7();
84 i2c_init(7, 100000, 0x00);
Gabe Blackd3163ab2013-05-16 05:53:40 -070085
Gabe Blackd686acd2013-06-30 05:19:53 -070086 parade_ps8625_bridge_setup(7, 0x48);
Gabe Blackd3163ab2013-05-16 05:53:40 -070087}
88
89/*
90 * This delay is T3 in the LCD timing spec (defined as >200ms). We set
91 * this down to 60ms since that's the approximate maximum amount of time
92 * it'll take a bridge to start outputting LVDS data. The delay of
93 * >200ms is just a conservative value to avoid turning on the backlight
94 * when there's random LCD data on the screen. Shaving 140ms off the
95 * boot is an acceptable trade-off.
96 */
97#define LCD_T3_DELAY_MS 60
98
99#define LCD_T5_DELAY_MS 10
100#define LCD_T6_DELAY_MS 10
101
102static void backlight_pwm(void)
103{
104 /*Configure backlight PWM as a simple output high (100% brightness) */
Gabe Black63bb6102013-06-19 03:29:45 -0700105 gpio_direction_output(bl_pwm, 1);
Gabe Blackd3163ab2013-05-16 05:53:40 -0700106 udelay(LCD_T6_DELAY_MS * 1000);
107}
108
109static void backlight_en(void)
110{
111 /* Configure GPIO for LCD_BL_EN */
Gabe Black63bb6102013-06-19 03:29:45 -0700112 gpio_direction_output(bl_en, 1);
Gabe Blackd3163ab2013-05-16 05:53:40 -0700113}
114
Gabe Blackd3163ab2013-05-16 05:53:40 -0700115//static struct video_info smdk5420_dp_config = {
116static struct video_info dp_video_info = {
117 /* FIXME: fix video_info struct to use const for name */
118 .name = (char *)"eDP-LVDS NXP PTN3460",
119
120 .h_sync_polarity = 0,
121 .v_sync_polarity = 0,
122 .interlaced = 0,
123
124 .color_space = COLOR_RGB,
125 .dynamic_range = VESA,
126 .ycbcr_coeff = COLOR_YCBCR601,
127 .color_depth = COLOR_8,
128
129 .link_rate = LINK_RATE_2_70GBPS,
130 .lane_count = LANE_COUNT2,
131};
132
133/* FIXME: move some place more appropriate */
134#define EXYNOS5420_DP1_BASE 0x145b0000
135#define MAX_DP_TRIES 5
136
137/*
138 * This function disables the USB3.0 PLL to save power
139 */
140static void disable_usb30_pll(void)
141{
142 enum exynos5_gpio_pin usb3_pll_l = GPIO_Y11;
143
144 gpio_direction_output(usb3_pll_l, 0);
145}
146
Gabe Black04d6e012013-06-23 03:16:46 -0700147static void gpio_init(void)
148{
149 /* Set up the I2C busses. */
150 exynos_pinmux_i2c2();
151 exynos_pinmux_i2c4();
152 exynos_pinmux_i2c7();
153 exynos_pinmux_i2c8();
154 exynos_pinmux_i2c9();
155 exynos_pinmux_i2c10();
156}
157
Gabe Blackc0b21442013-06-28 14:27:16 -0700158enum {
159 FET_CTRL_WAIT = 3 << 2,
160 FET_CTRL_ADENFET = 1 << 1,
161 FET_CTRL_ENFET = 1 << 0
162};
163
164static void tps65090_thru_ec_fet_set(int index)
165{
166 uint8_t value = FET_CTRL_ADENFET | FET_CTRL_WAIT | FET_CTRL_ENFET;
167
168 if (google_chromeec_i2c_xfer(0x48, 0xe + index, 1, &value, 1, 0)) {
169 printk(BIOS_ERR,
170 "Error sending i2c pass through command to EC.\n");
171 return;
172 }
173}
174
175static void lcd_vdd(void)
176{
177 /* Enable FET6, lcd panel */
178 tps65090_thru_ec_fet_set(6);
179}
180
181static void backlight_vdd(void)
182{
183 /* Enable FET1, backlight */
184 tps65090_thru_ec_fet_set(1);
185}
186
Gabe Blackd3163ab2013-05-16 05:53:40 -0700187/* this happens after cpu_init where exynos resources are set */
188static void mainboard_init(device_t dev)
189{
Gabe Blackd3163ab2013-05-16 05:53:40 -0700190 struct s5p_dp_device dp_device = {
191 .base = (struct exynos5_dp *)EXYNOS5420_DP1_BASE,
192 .video_info = &dp_video_info,
193 };
194 void *fb_addr;
195
Gabe Black04d6e012013-06-23 03:16:46 -0700196 gpio_init();
197
Gabe Blackd3163ab2013-05-16 05:53:40 -0700198 tmu_init(&exynos5420_tmu_info);
199
200 /* Clock Gating all the unused IP's to save power */
201 clock_gate();
202
203 /* Disable USB3.0 PLL to save 250mW of power */
204 disable_usb30_pll();
205
206 fb_addr = cbmem_find(CBMEM_ID_CONSOLE);
Stefan Reinauerf1751912013-05-20 15:17:44 -0700207 set_vbe_mode_info_valid(&edid, (uintptr_t)fb_addr);
Gabe Blackd3163ab2013-05-16 05:53:40 -0700208
Gabe Blackc0b21442013-06-28 14:27:16 -0700209 lcd_vdd();
Stefan Reinauerc2c4f842013-05-20 12:51:02 -0700210
Gabe Blackd686acd2013-06-30 05:19:53 -0700211 parade_dp_bridge_setup();
212 dp_controller_init(&dp_device);
Gabe Blackd3163ab2013-05-16 05:53:40 -0700213
Gabe Blackd686acd2013-06-30 05:19:53 -0700214 udelay(LCD_T3_DELAY_MS * 1000);
Gabe Blackd3163ab2013-05-16 05:53:40 -0700215
Gabe Blackd686acd2013-06-30 05:19:53 -0700216 backlight_vdd();
217 backlight_pwm();
218 backlight_en();
Gabe Blackd3163ab2013-05-16 05:53:40 -0700219
Stefan Reinauerc2c4f842013-05-20 12:51:02 -0700220 // Uncomment to get excessive GPIO output:
221 // gpio_info();
Gabe Blackd3163ab2013-05-16 05:53:40 -0700222}
223
Kyösti Mälkki95c39c22013-06-22 14:05:28 +0300224void get_cbmem_table(uint64_t *base, uint64_t *size)
Kyösti Mälkki1ae305e2013-09-04 13:05:01 +0300225{
Kyösti Mälkki95c39c22013-06-22 14:05:28 +0300226 *size = CONFIG_COREBOOT_TABLES_SIZE;
227 *base = CONFIG_SYS_SDRAM_BASE +
Kyösti Mälkki1ae305e2013-09-04 13:05:01 +0300228 ((unsigned)CONFIG_DRAM_SIZE_MB << 20ULL) -
229 CONFIG_COREBOOT_TABLES_SIZE;
Kyösti Mälkki1ae305e2013-09-04 13:05:01 +0300230}
231
Gabe Blackd3163ab2013-05-16 05:53:40 -0700232static void mainboard_enable(device_t dev)
233{
234 dev->ops->init = &mainboard_init;
235
236 /* set up coreboot tables */
Kyösti Mälkki95c39c22013-06-22 14:05:28 +0300237 cbmem_initialize();
Gabe Blackd3163ab2013-05-16 05:53:40 -0700238
239 /* set up dcache and MMU */
240 /* FIXME: this should happen via resource allocator */
241 exynos5420_config_l2_cache();
242 mmu_init();
243 mmu_config_range(0, DRAM_START, DCACHE_OFF);
244 mmu_config_range(DRAM_START, DRAM_SIZE, DCACHE_WRITEBACK);
245 mmu_config_range(DRAM_END, 4096 - DRAM_END, DCACHE_OFF);
246 dcache_invalidate_all();
247 dcache_mmu_enable();
248
249 /* this is going to move, but we must have it now and we're
250 * not sure where */
251 exception_init();
252
253 const unsigned epll_hz = 192000000;
254 const unsigned sample_rate = 48000;
255 const unsigned lr_frame_size = 256;
256 clock_epll_set_rate(epll_hz);
257 clock_select_i2s_clk_source();
258 clock_set_i2s_clk_prescaler(epll_hz, sample_rate * lr_frame_size);
259
260 power_enable_xclkout();
261}
262
263struct chip_operations mainboard_ops = {
264 .name = "Samsung/Google ARM Chromebook",
265 .enable_dev = mainboard_enable,
266};