diff options
author | Stefan Reinauer <reinauer@chromium.org> | 2013-05-09 16:16:13 -0700 |
---|---|---|
committer | Stefan Reinauer <stefan.reinauer@coreboot.org> | 2013-07-10 02:40:17 +0200 |
commit | 2ae6d6f6de3d5fb6c1fdb039d0997814ac0b9798 (patch) | |
tree | f5355c4c59f0916ebb4d8ca79737267bbbcdf895 /src | |
parent | 78c3e3355003ff2c0c2917f445e0c8dd3e083f52 (diff) |
ARMv7: normalize ramstage code flow
In ram stage, all code flow should be tied to the resource allocator.
Stuff that has to happen before everything else goes into the mainboard
enable function in mainboard.c. This patch empties the main() wrapper
around hardwaremain.c, allowing to get rid of this special case in the
ARM port.
Change-Id: Ide91a23f1043b64acf64471f180a2297f0f40d97
Signed-off-by: Stefan Reinauer <reinauer@google.com>
Signed-off-by: Gabe Black <gabeblack@chromium.org>
Reviewed-on: http://review.coreboot.org/3638
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/mainboard/emulation/qemu-armv7/ramstage.c | 2 | ||||
-rw-r--r-- | src/mainboard/google/snow/Makefile.inc | 2 | ||||
-rw-r--r-- | src/mainboard/google/snow/mainboard.c | 279 | ||||
-rw-r--r-- | src/mainboard/google/snow/mainboard.h | 16 | ||||
-rw-r--r-- | src/mainboard/google/snow/memory.c | 64 | ||||
-rw-r--r-- | src/mainboard/google/snow/ramstage.c | 244 |
6 files changed, 299 insertions, 308 deletions
diff --git a/src/mainboard/emulation/qemu-armv7/ramstage.c b/src/mainboard/emulation/qemu-armv7/ramstage.c index 5fce9fa68c..32e6cab95a 100644 --- a/src/mainboard/emulation/qemu-armv7/ramstage.c +++ b/src/mainboard/emulation/qemu-armv7/ramstage.c @@ -13,8 +13,6 @@ * GNU General Public License for more details. */ -#include <console/console.h> - void hardwaremain(void); void main(void) { diff --git a/src/mainboard/google/snow/Makefile.inc b/src/mainboard/google/snow/Makefile.inc index 84a8c054d6..190bb36154 100644 --- a/src/mainboard/google/snow/Makefile.inc +++ b/src/mainboard/google/snow/Makefile.inc @@ -19,11 +19,11 @@ bootblock-y += wakeup.c -romstage-y += mainboard.c romstage-y += memory.c romstage-y += romstage.c romstage-y += wakeup.c # ramstage-y += ec.c +ramstage-y += mainboard.c ramstage-y += ramstage.c ramstage-y += chromeos.c diff --git a/src/mainboard/google/snow/mainboard.c b/src/mainboard/google/snow/mainboard.c index 4a0d181cd0..f4c8e6cf13 100644 --- a/src/mainboard/google/snow/mainboard.c +++ b/src/mainboard/google/snow/mainboard.c @@ -17,60 +17,255 @@ * MA 02111-1307 USA */ -#include <stdlib.h> -#include <gpio.h> -#include <device/device.h> #include <console/console.h> - -#include <cpu/samsung/exynos5-common/gpio.h> +#include <device/device.h> +#include <device/i2c.h> +#include <drivers/ti/tps65090/tps65090.h> +#include <cbmem.h> +#include <delay.h> +#include <edid.h> +#include <vbe.h> +#include <boot/coreboot_tables.h> +#include <arch/cache.h> +#include <arch/exception.h> +#include <arch/gpio.h> +#include <cpu/samsung/exynos5-common/exynos-tmu.h> +#include <cpu/samsung/exynos5250/clk.h> +#include <cpu/samsung/exynos5250/cpu.h> #include <cpu/samsung/exynos5250/gpio.h> +#include <cpu/samsung/exynos5250/power.h> + +#include <cpu/samsung/exynos5-common/i2c.h> +#include <cpu/samsung/exynos5-common/s5p-dp-core.h> + + +/* convenient shorthand (in MB) */ +#define DRAM_START (CONFIG_SYS_SDRAM_BASE >> 20) +#define DRAM_SIZE CONFIG_DRAM_SIZE_MB +#define DRAM_END (DRAM_START + DRAM_SIZE) /* plus one... */ + +static struct edid snow_edid = { + .ha = 1366, + .va = 768, + .bpp = 16, +}; + +/* TODO: transplanted DP stuff, clean up once we have something that works */ +static enum exynos5_gpio_pin dp_pd_l = GPIO_Y25; /* active low */ +static enum exynos5_gpio_pin dp_rst_l = GPIO_X15; /* active low */ +static enum exynos5_gpio_pin dp_hpd = GPIO_X07; /* active high */ + +static void exynos_dp_bridge_setup(void) +{ + exynos_pinmux_config(PERIPH_ID_DPHPD, 0); + + gpio_set_value(dp_pd_l, 1); + gpio_cfg_pin(dp_pd_l, EXYNOS_GPIO_OUTPUT); + gpio_set_pull(dp_pd_l, EXYNOS_GPIO_PULL_NONE); + + gpio_set_value(dp_rst_l, 0); + gpio_cfg_pin(dp_rst_l, EXYNOS_GPIO_OUTPUT); + gpio_set_pull(dp_rst_l, EXYNOS_GPIO_PULL_NONE); + udelay(10); + gpio_set_value(dp_rst_l, 1); +} + +static void exynos_dp_bridge_init(void) +{ + /* De-assert PD (and possibly RST) to power up the bridge */ + gpio_set_value(dp_pd_l, 1); + gpio_set_value(dp_rst_l, 1); + + /* + * We need to wait for 90ms after bringing up the bridge since + * there is a phantom "high" on the HPD chip during its + * bootup. The phantom high comes within 7ms of de-asserting + * PD and persists for at least 15ms. The real high comes + * roughly 50ms after PD is de-asserted. The phantom high + * makes it hard for us to know when the NXP chip is up. + */ + udelay(90000); +} + +static int exynos_dp_hotplug(void) +{ + /* Check HPD. If it's high, we're all good. */ + return gpio_get_value(dp_hpd) ? 0 : 1; +} + +static void exynos_dp_reset(void) +{ + gpio_set_value(dp_pd_l, 0); + gpio_set_value(dp_rst_l, 0); + /* paranoid delay period (300ms) */ + udelay(300 * 1000); +} + +/* + * This delay is T3 in the LCD timing spec (defined as >200ms). We set + * this down to 60ms since that's the approximate maximum amount of time + * it'll take a bridge to start outputting LVDS data. The delay of + * >200ms is just a conservative value to avoid turning on the backlight + * when there's random LCD data on the screen. Shaving 140ms off the + * boot is an acceptable trade-off. + */ +#define LCD_T3_DELAY_MS 60 + +#define LCD_T5_DELAY_MS 10 +#define LCD_T6_DELAY_MS 10 + +static void snow_backlight_pwm(void) +{ + /*Configure backlight PWM as a simple output high (100% brightness) */ + gpio_direction_output(GPIO_B20, 1); + udelay(LCD_T6_DELAY_MS * 1000); +} + +static void snow_backlight_en(void) +{ + /* * Configure GPIO for LCD_BL_EN */ + gpio_direction_output(GPIO_X30, 1); +} + +#define TPS69050_BUS 4 /* Snow-specific */ -#include "mainboard.h" - -#define SNOW_BOARD_ID0_GPIO 88 /* GPD0, pin 0 */ -#define SNOW_BOARD_ID1_GPIO 89 /* GPD0, pin 1 */ - -struct { - enum mvl3 id0, id1; - enum snow_board_config config; -} snow_id_map[] = { - /* ID0 ID1 config */ - { LOGIC_0, LOGIC_0, SNOW_CONFIG_SAMSUNG_MP }, - { LOGIC_0, LOGIC_1, SNOW_CONFIG_ELPIDA_MP }, - { LOGIC_1, LOGIC_0, SNOW_CONFIG_SAMSUNG_DVT }, - { LOGIC_1, LOGIC_1, SNOW_CONFIG_ELPIDA_DVT }, - { LOGIC_0, LOGIC_Z, SNOW_CONFIG_SAMSUNG_PVT }, - { LOGIC_1, LOGIC_Z, SNOW_CONFIG_ELPIDA_PVT }, - { LOGIC_Z, LOGIC_0, SNOW_CONFIG_SAMSUNG_MP }, - { LOGIC_Z, LOGIC_Z, SNOW_CONFIG_ELPIDA_MP }, - { LOGIC_Z, LOGIC_1, SNOW_CONFIG_RSVD }, +#define FET1_CTRL 0x0f +#define FET6_CTRL 0x14 + +static void snow_lcd_vdd(void) +{ + /* Enable FET6, lcd panel */ + tps65090_fet_enable(TPS69050_BUS, FET6_CTRL); +} + +static void snow_backlight_vdd(void) +{ + /* Enable FET1, backlight */ + tps65090_fet_enable(TPS69050_BUS, FET1_CTRL); + udelay(LCD_T5_DELAY_MS * 1000); +} + +//static struct video_info smdk5250_dp_config = { +static struct video_info snow_dp_video_info = { + /* FIXME: fix video_info struct to use const for name */ + .name = (char *)"eDP-LVDS NXP PTN3460", + + .h_sync_polarity = 0, + .v_sync_polarity = 0, + .interlaced = 0, + + .color_space = COLOR_RGB, + .dynamic_range = VESA, + .ycbcr_coeff = COLOR_YCBCR601, + .color_depth = COLOR_8, + + .link_rate = LINK_RATE_2_70GBPS, + .lane_count = LANE_COUNT2, }; -int board_get_config(void) +/* FIXME: move some place more appropriate */ +#define EXYNOS5250_DP1_BASE 0x145b0000 +#define SNOW_MAX_DP_TRIES 5 + +/* + * This function disables the USB3.0 PLL to save power + */ +static void disable_usb30_pll(void) { - int i; - int id0, id1; - enum snow_board_config config = SNOW_CONFIG_UNKNOWN; - - id0 = gpio_read_mvl3(SNOW_BOARD_ID0_GPIO); - id1 = gpio_read_mvl3(SNOW_BOARD_ID1_GPIO); - if (id0 < 0 || id1 < 0) - return -1; - printk(BIOS_DEBUG, "%s: id0: %u, id1: %u\n", __func__, id0, id1); - - for (i = 0; i < ARRAY_SIZE(snow_id_map); i++) { - if (id0 == snow_id_map[i].id0 && id1 == snow_id_map[i].id1) { - config = snow_id_map[i].config; - break; + enum exynos5_gpio_pin usb3_pll_l = GPIO_Y11; + + gpio_direction_output(usb3_pll_l, 0); +} + +/* this happens after cpu_init where exynos resources are set */ +static void mainboard_init(device_t dev) +{ + int dp_tries; + struct s5p_dp_device dp_device = { + .base = (struct exynos5_dp *)EXYNOS5250_DP1_BASE, + .video_info = &snow_dp_video_info, + }; + void *fb_addr; + + i2c_init(TPS69050_BUS, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + i2c_init(7, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + + tmu_init(&exynos5250_tmu_info); + + /* Clock Gating all the unused IP's to save power */ + clock_gate(); + + /* Disable USB3.0 PLL to save 250mW of power */ + disable_usb30_pll(); + + fb_addr = cbmem_find(CBMEM_ID_CONSOLE); + set_vbe_mode_info_valid(&snow_edid, (uintptr_t)(fb_addr) + 64*KiB); + + snow_lcd_vdd(); + do { + udelay(50); + } while (!exynos_dp_hotplug()); + + exynos_dp_bridge_setup(); + for (dp_tries = 1; dp_tries <= SNOW_MAX_DP_TRIES; dp_tries++) { + exynos_dp_bridge_init(); + if (exynos_dp_hotplug()) { + exynos_dp_reset(); + continue; } + + if (dp_controller_init(&dp_device)) + continue; + + udelay(LCD_T3_DELAY_MS * 1000); + + snow_backlight_vdd(); + snow_backlight_pwm(); + snow_backlight_en(); + /* if we're here, we're successful */ + break; } - return config; + if (dp_tries > SNOW_MAX_DP_TRIES) + printk(BIOS_ERR, "%s: Failed to set up displayport\n", __func__); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; + + /* set up coreboot tables */ + high_tables_size = CONFIG_COREBOOT_TABLES_SIZE; + high_tables_base = CONFIG_SYS_SDRAM_BASE + + ((unsigned)CONFIG_DRAM_SIZE_MB << 20ULL) - + CONFIG_COREBOOT_TABLES_SIZE; + cbmem_init(high_tables_base, high_tables_size); + + /* set up dcache and MMU */ + /* FIXME: this should happen via resource allocator */ + exynos5250_config_l2_cache(); + mmu_init(); + mmu_config_range(0, DRAM_START, DCACHE_OFF); + mmu_config_range(DRAM_START, DRAM_SIZE, DCACHE_WRITEBACK); + mmu_config_range(DRAM_END, 4096 - DRAM_END, DCACHE_OFF); + dcache_invalidate_all(); + dcache_mmu_enable(); + + /* this is going to move, but we must have it now and we're + * not sure where */ + exception_init(); + + const unsigned epll_hz = 192000000; + const unsigned sample_rate = 48000; + const unsigned lr_frame_size = 256; + clock_epll_set_rate(epll_hz); + clock_select_i2s_clk_source(); + clock_set_i2s_clk_prescaler(epll_hz, sample_rate * lr_frame_size); + + power_enable_xclkout(); } -#if 0 struct chip_operations mainboard_ops = { .name = "Samsung/Google ARM Chromebook", .enable_dev = mainboard_enable, }; -#endif diff --git a/src/mainboard/google/snow/mainboard.h b/src/mainboard/google/snow/mainboard.h index 5060b720f3..a91bed49da 100644 --- a/src/mainboard/google/snow/mainboard.h +++ b/src/mainboard/google/snow/mainboard.h @@ -19,22 +19,6 @@ #ifndef MAINBOARD_H #define MAINBOARD_H - -enum snow_board_config { - SNOW_CONFIG_UNKNOWN = -1, - SNOW_CONFIG_SAMSUNG_EVT, - SNOW_CONFIG_ELPIDA_EVT, - SNOW_CONFIG_SAMSUNG_DVT, - SNOW_CONFIG_ELPIDA_DVT, - SNOW_CONFIG_SAMSUNG_PVT, - SNOW_CONFIG_ELPIDA_PVT, - SNOW_CONFIG_SAMSUNG_MP, - SNOW_CONFIG_ELPIDA_MP, - SNOW_CONFIG_RSVD, -}; - -int board_get_config(void); - enum { SNOW_IS_NOT_WAKEUP, // A normal boot (not suspend/resume). SNOW_WAKEUP_DIRECT, // A wake up event that can be resumed any time. diff --git a/src/mainboard/google/snow/memory.c b/src/mainboard/google/snow/memory.c index ba8c91fd6e..0f72e69ff8 100644 --- a/src/mainboard/google/snow/memory.c +++ b/src/mainboard/google/snow/memory.c @@ -23,13 +23,16 @@ #include <stdlib.h> #include <console/console.h> +#include <gpio.h> +#include <cpu/samsung/exynos5-common/gpio.h> +#include <cpu/samsung/exynos5250/gpio.h> #include <cpu/samsung/exynos5250/setup.h> #include <cpu/samsung/exynos5250/dmc.h> #include <cpu/samsung/exynos5250/clock_init.h> #include "mainboard.h" -struct mem_timings mem_timings[] = { +const struct mem_timings mem_timings[] = { { .mem_manuf = MEM_MANUF_ELPIDA, .mem_type = DDR_MODE_DDR3, @@ -450,6 +453,61 @@ struct mem_timings mem_timings[] = { } }; +#define SNOW_BOARD_ID0_GPIO 88 /* GPD0, pin 0 */ +#define SNOW_BOARD_ID1_GPIO 89 /* GPD0, pin 1 */ + +enum snow_board_config { + SNOW_CONFIG_UNKNOWN = -1, + SNOW_CONFIG_SAMSUNG_EVT, + SNOW_CONFIG_ELPIDA_EVT, + SNOW_CONFIG_SAMSUNG_DVT, + SNOW_CONFIG_ELPIDA_DVT, + SNOW_CONFIG_SAMSUNG_PVT, + SNOW_CONFIG_ELPIDA_PVT, + SNOW_CONFIG_SAMSUNG_MP, + SNOW_CONFIG_ELPIDA_MP, + SNOW_CONFIG_RSVD, +}; + +struct { + enum mvl3 id0, id1; + enum snow_board_config config; +} snow_id_map[] = { + /* ID0 ID1 config */ + { LOGIC_0, LOGIC_0, SNOW_CONFIG_SAMSUNG_MP }, + { LOGIC_0, LOGIC_1, SNOW_CONFIG_ELPIDA_MP }, + { LOGIC_1, LOGIC_0, SNOW_CONFIG_SAMSUNG_DVT }, + { LOGIC_1, LOGIC_1, SNOW_CONFIG_ELPIDA_DVT }, + { LOGIC_0, LOGIC_Z, SNOW_CONFIG_SAMSUNG_PVT }, + { LOGIC_1, LOGIC_Z, SNOW_CONFIG_ELPIDA_PVT }, + { LOGIC_Z, LOGIC_0, SNOW_CONFIG_SAMSUNG_MP }, + { LOGIC_Z, LOGIC_Z, SNOW_CONFIG_ELPIDA_MP }, + { LOGIC_Z, LOGIC_1, SNOW_CONFIG_RSVD }, +}; + +static int board_get_config(void) +{ + int i; + int id0, id1; + enum snow_board_config config = SNOW_CONFIG_UNKNOWN; + + id0 = gpio_read_mvl3(SNOW_BOARD_ID0_GPIO); + id1 = gpio_read_mvl3(SNOW_BOARD_ID1_GPIO); + if (id0 < 0 || id1 < 0) + return -1; + printk(BIOS_DEBUG, "%s: id0: %u, id1: %u\n", __func__, id0, id1); + + for (i = 0; i < ARRAY_SIZE(snow_id_map); i++) { + if (id0 == snow_id_map[i].id0 && id1 == snow_id_map[i].id1) { + config = snow_id_map[i].config; + break; + } + } + + return config; +} + + struct mem_timings *get_mem_timings(void) { int i; @@ -457,7 +515,7 @@ struct mem_timings *get_mem_timings(void) enum ddr_mode mem_type; unsigned int frequency_mhz; enum mem_manuf mem_manuf; - struct mem_timings *mem; + const struct mem_timings *mem; board_config = board_get_config(); switch (board_config) { @@ -487,7 +545,7 @@ struct mem_timings *get_mem_timings(void) if (mem->mem_type == mem_type && mem->frequency_mhz == frequency_mhz && mem->mem_manuf == mem_manuf) - return mem; + return (struct mem_timings *)mem; } return NULL; diff --git a/src/mainboard/google/snow/ramstage.c b/src/mainboard/google/snow/ramstage.c index 93979b2a60..6aa6082fcf 100644 --- a/src/mainboard/google/snow/ramstage.c +++ b/src/mainboard/google/snow/ramstage.c @@ -17,252 +17,8 @@ * MA 02111-1307 USA */ -#include <console/console.h> -#include <device/device.h> -#include <device/i2c.h> -#include <drivers/ti/tps65090/tps65090.h> -#include <cbmem.h> -#include <delay.h> -#include <boot/coreboot_tables.h> -#include <arch/cache.h> -#include <arch/exception.h> -#include <arch/gpio.h> -#include <cpu/samsung/exynos5-common/exynos-tmu.h> -#include <cpu/samsung/exynos5250/clk.h> -#include <cpu/samsung/exynos5250/cpu.h> -#include <cpu/samsung/exynos5250/gpio.h> -#include <cpu/samsung/exynos5250/power.h> - -#include <cpu/samsung/exynos5-common/i2c.h> -#include <cpu/samsung/exynos5-common/s5p-dp-core.h> - - -/* convenient shorthand (in MB) */ -#define DRAM_START (CONFIG_SYS_SDRAM_BASE >> 20) -#define DRAM_SIZE CONFIG_DRAM_SIZE_MB -#define DRAM_END (DRAM_START + DRAM_SIZE) /* plus one... */ - - void hardwaremain(void); void main(void) { - /* FIXME this should be moved elsewhere. We don't want ramstage.c */ - - /* set up coreboot tables */ - high_tables_size = CONFIG_COREBOOT_TABLES_SIZE; - high_tables_base = CONFIG_SYS_SDRAM_BASE + - ((unsigned)CONFIG_DRAM_SIZE_MB << 20ULL) - - CONFIG_COREBOOT_TABLES_SIZE; - cbmem_init(high_tables_base, high_tables_size); - - /* set up dcache and MMU */ - /* FIXME: this should happen via resource allocator */ - exynos5250_config_l2_cache(); - mmu_init(); - mmu_config_range(0, DRAM_START, DCACHE_OFF); - mmu_config_range(DRAM_START, DRAM_SIZE, DCACHE_WRITEBACK); - mmu_config_range(DRAM_END, 4096 - DRAM_END, DCACHE_OFF); - dcache_invalidate_all(); - dcache_mmu_enable(); - - /* this is going to move, but we must have it now and we're - * not sure where */ - exception_init(); - - const unsigned epll_hz = 192000000; - const unsigned sample_rate = 48000; - const unsigned lr_frame_size = 256; - clock_epll_set_rate(epll_hz); - clock_select_i2s_clk_source(); - clock_set_i2s_clk_prescaler(epll_hz, sample_rate * lr_frame_size); - - power_enable_xclkout(); - hardwaremain(); } - -/* TODO: transplanted DP stuff, clean up once we have something that works */ -static enum exynos5_gpio_pin dp_pd_l = GPIO_Y25; /* active low */ -static enum exynos5_gpio_pin dp_rst_l = GPIO_X15; /* active low */ -static enum exynos5_gpio_pin dp_hpd = GPIO_X07; /* active high */ - -static void exynos_dp_bridge_setup(void) -{ - exynos_pinmux_config(PERIPH_ID_DPHPD, 0); - - gpio_set_value(dp_pd_l, 1); - gpio_cfg_pin(dp_pd_l, EXYNOS_GPIO_OUTPUT); - gpio_set_pull(dp_pd_l, EXYNOS_GPIO_PULL_NONE); - - gpio_set_value(dp_rst_l, 0); - gpio_cfg_pin(dp_rst_l, EXYNOS_GPIO_OUTPUT); - gpio_set_pull(dp_rst_l, EXYNOS_GPIO_PULL_NONE); - udelay(10); - gpio_set_value(dp_rst_l, 1); -} - -static void exynos_dp_bridge_init(void) -{ - /* De-assert PD (and possibly RST) to power up the bridge */ - gpio_set_value(dp_pd_l, 1); - gpio_set_value(dp_rst_l, 1); - - /* - * We need to wait for 90ms after bringing up the bridge since - * there is a phantom "high" on the HPD chip during its - * bootup. The phantom high comes within 7ms of de-asserting - * PD and persists for at least 15ms. The real high comes - * roughly 50ms after PD is de-asserted. The phantom high - * makes it hard for us to know when the NXP chip is up. - */ - udelay(90000); -} - -static int exynos_dp_hotplug(void) -{ - /* Check HPD. If it's high, we're all good. */ - return gpio_get_value(dp_hpd) ? 0 : 1; -} - -static void exynos_dp_reset(void) -{ - gpio_set_value(dp_pd_l, 0); - gpio_set_value(dp_rst_l, 0); - /* paranoid delay period (300ms) */ - udelay(300 * 1000); -} - -/* - * This delay is T3 in the LCD timing spec (defined as >200ms). We set - * this down to 60ms since that's the approximate maximum amount of time - * it'll take a bridge to start outputting LVDS data. The delay of - * >200ms is just a conservative value to avoid turning on the backlight - * when there's random LCD data on the screen. Shaving 140ms off the - * boot is an acceptable trade-off. - */ -#define LCD_T3_DELAY_MS 60 - -#define LCD_T5_DELAY_MS 10 -#define LCD_T6_DELAY_MS 10 - -static void snow_backlight_pwm(void) -{ - /*Configure backlight PWM as a simple output high (100% brightness) */ - gpio_direction_output(GPIO_B20, 1); - udelay(LCD_T6_DELAY_MS * 1000); -} - -static void snow_backlight_en(void) -{ - /* * Configure GPIO for LCD_BL_EN */ - gpio_direction_output(GPIO_X30, 1); -} - -#define TPS69050_BUS 4 /* Snow-specific */ - -#define FET1_CTRL 0x0f -#define FET6_CTRL 0x14 - -static void snow_lcd_vdd(void) -{ - /* Enable FET6, lcd panel */ - tps65090_fet_enable(TPS69050_BUS, FET6_CTRL); -} - -static void snow_backlight_vdd(void) -{ - /* Enable FET1, backlight */ - tps65090_fet_enable(TPS69050_BUS, FET1_CTRL); - udelay(LCD_T5_DELAY_MS * 1000); -} - -//static struct video_info smdk5250_dp_config = { -static struct video_info snow_dp_video_info = { - /* FIXME: fix video_info struct to use const for name */ - .name = (char *)"eDP-LVDS NXP PTN3460", - - .h_sync_polarity = 0, - .v_sync_polarity = 0, - .interlaced = 0, - - .color_space = COLOR_RGB, - .dynamic_range = VESA, - .ycbcr_coeff = COLOR_YCBCR601, - .color_depth = COLOR_8, - - .link_rate = LINK_RATE_2_70GBPS, - .lane_count = LANE_COUNT2, -}; - -/* FIXME: move some place more appropriate */ -#define EXYNOS5250_DP1_BASE 0x145b0000 -#define SNOW_MAX_DP_TRIES 5 - -/* - * This function disables the USB3.0 PLL to save power - */ -static void disable_usb30_pll(void) -{ - enum exynos5_gpio_pin usb3_pll_l = GPIO_Y11; - - gpio_direction_output(usb3_pll_l, 0); -} - -/* this happens after cpu_init where exynos resources are set */ -static void mainboard_init(device_t dev) -{ - int dp_tries; - struct s5p_dp_device dp_device = { - .base = (struct exynos5_dp *)EXYNOS5250_DP1_BASE, - .video_info = &snow_dp_video_info, - }; - - i2c_init(TPS69050_BUS, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); - i2c_init(7, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); - - tmu_init(&exynos5250_tmu_info); - - /* Clock Gating all the unused IP's to save power */ - clock_gate(); - - /* Disable USB3.0 PLL to save 250mW of power */ - disable_usb30_pll(); - - snow_lcd_vdd(); - do { - udelay(50); - } while (!exynos_dp_hotplug()); - - exynos_dp_bridge_setup(); - for (dp_tries = 1; dp_tries <= SNOW_MAX_DP_TRIES; dp_tries++) { - exynos_dp_bridge_init(); - if (exynos_dp_hotplug()) { - exynos_dp_reset(); - continue; - } - - if (dp_controller_init(&dp_device)) - continue; - - udelay(LCD_T3_DELAY_MS * 1000); - - snow_backlight_vdd(); - snow_backlight_pwm(); - snow_backlight_en(); - /* if we're here, we're successful */ - break; - } - - if (dp_tries > SNOW_MAX_DP_TRIES) - printk(BIOS_ERR, "%s: Failed to set up displayport\n", __func__); -} - -static void mainboard_enable(device_t dev) -{ - dev->ops->init = &mainboard_init; -} - -struct chip_operations mainboard_ops = { - .name = "Samsung/Google ARM Chromebook", - .enable_dev = mainboard_enable, -}; |