Gabe Black (gabeblack@chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3646
-gerrit
commit da673f557663d0cca49f19a2ee0ece643c07fdf3 Author: Gabe Black gabeblack@google.com Date: Thu May 16 05:53:40 2013 -0700
pit: Add a "pit" mainboard which is mostly a copy of "snow".
This change adds a pit mainboard which is mostly a copy of snow, except that mentions of the 5250 were replaced with the 5420, and mentions of snow were replaced with pit.
Change-Id: I8eb0ce379eb2fa353bb88d5656a0c5e2290afbf0 Signed-off-by: Gabe Black gabeblack@chromium.org --- src/mainboard/google/Kconfig | 3 + src/mainboard/google/pit/Kconfig | 56 ++++ src/mainboard/google/pit/Makefile.inc | 27 ++ src/mainboard/google/pit/chromeos.c | 105 +++++++ src/mainboard/google/pit/devicetree.cb | 33 ++ src/mainboard/google/pit/exynos5420.h | 33 ++ src/mainboard/google/pit/mainboard.c | 273 +++++++++++++++++ src/mainboard/google/pit/memory.c | 546 +++++++++++++++++++++++++++++++++ src/mainboard/google/pit/romstage.c | 191 ++++++++++++ src/mainboard/google/pit/wakeup.c | 29 ++ 10 files changed, 1296 insertions(+)
diff --git a/src/mainboard/google/Kconfig b/src/mainboard/google/Kconfig index e389b59..0e34a8d 100644 --- a/src/mainboard/google/Kconfig +++ b/src/mainboard/google/Kconfig @@ -32,6 +32,8 @@ config BOARD_GOOGLE_LINK bool "Link" config BOARD_GOOGLE_PARROT bool "Parrot" +config BOARD_GOOGLE_PIT + bool "Pit" config BOARD_GOOGLE_SNOW bool "Snow" config BOARD_GOOGLE_STOUT @@ -42,6 +44,7 @@ endchoice source "src/mainboard/google/butterfly/Kconfig" source "src/mainboard/google/link/Kconfig" source "src/mainboard/google/parrot/Kconfig" +source "src/mainboard/google/pit/Kconfig" source "src/mainboard/google/snow/Kconfig" source "src/mainboard/google/stout/Kconfig"
diff --git a/src/mainboard/google/pit/Kconfig b/src/mainboard/google/pit/Kconfig new file mode 100644 index 0000000..8aed0a0 --- /dev/null +++ b/src/mainboard/google/pit/Kconfig @@ -0,0 +1,56 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2013 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_PIT + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select ARCH_ARMV7 + select CPU_SAMSUNG_EXYNOS5420 + select HAVE_UART_MEMORY_MAPPED + select EC_GOOGLE_CHROMEEC + select EC_GOOGLE_CHROMEEC_I2C + select BOARD_ROMSIZE_KB_4096 + select DRIVER_MAXIM_MAX77686 + select CHROMEOS + select DRIVER_TI_TPS65090 + select MAINBOARD_HAS_NATIVE_VGA_INIT + select MAINBOARD_DO_NATIVE_VGA_INIT + +config MAINBOARD_DIR + string + default google/pit + +config MAINBOARD_PART_NUMBER + string + default "Pit" + +config MAX_CPUS + int + default 2 + +config DRAM_SIZE_MB + int + default 2048 + +config EC_GOOGLE_CHROMEEC_I2C_BUS + hex + default 4 + +endif # BOARD_GOOGLE_PIT diff --git a/src/mainboard/google/pit/Makefile.inc b/src/mainboard/google/pit/Makefile.inc new file mode 100644 index 0000000..2858743 --- /dev/null +++ b/src/mainboard/google/pit/Makefile.inc @@ -0,0 +1,27 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2012 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +bootblock-y += wakeup.c + +romstage-y += memory.c +romstage-y += romstage.c +romstage-y += wakeup.c + +ramstage-y += mainboard.c +ramstage-y += chromeos.c diff --git a/src/mainboard/google/pit/chromeos.c b/src/mainboard/google/pit/chromeos.c new file mode 100644 index 0000000..349ba1d --- /dev/null +++ b/src/mainboard/google/pit/chromeos.c @@ -0,0 +1,105 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <boot/coreboot_tables.h> +#include <console/console.h> +#include <ec/google/chromeec/ec.h> +#include <ec/google/chromeec/ec_commands.h> +#include <string.h> +#include <vendorcode/google/chromeos/chromeos.h> +#include <cpu/samsung/exynos5420/cpu.h> +#include <cpu/samsung/exynos5420/gpio.h> + +enum { + ACTIVE_LOW = 0, + ACTIVE_HIGH = 1 +}; + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = EXYNOS5_GPD1; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get_value(GPIO_D16); // WP_GPIO + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Lid: active high */ + gpios->gpios[count].port = EXYNOS5_GPX3; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = gpio_get_value(GPIO_X35); // LID_GPIO + strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH); + count++; + + /* Power: virtual GPIO active low */ + gpios->gpios[count].port = EXYNOS5_GPX1; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = + gpio_get_value(GPIO_X13); // POWER_GPIO + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: virtual GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + uint32_t ec_events; + + /* The GPIO is active low. */ + if (!gpio_get_value(GPIO_Y10)) // RECMODE_GPIO + return 1; + + ec_events = google_chromeec_get_events_b(); + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_recovery_mode_from_vbnv(void) +{ + return 0; +} diff --git a/src/mainboard/google/pit/devicetree.cb b/src/mainboard/google/pit/devicetree.cb new file mode 100644 index 0000000..3b6cdb9 --- /dev/null +++ b/src/mainboard/google/pit/devicetree.cb @@ -0,0 +1,33 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2012 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +chip cpu/samsung/exynos5420 + device cpu_cluster 0 on end + register "xres" = "1366" + register "yres" = "768" + register "bpp" = "16" + # complex magic timing! + register "clkval_f" = "2" + register "upper_margin" = "14" + register "lower_margin" = "3" + register "vsync" = "5" + register "left_margin" = "80" + register "right_margin" = "48" + register "hsync" = "32" +end diff --git a/src/mainboard/google/pit/exynos5420.h b/src/mainboard/google/pit/exynos5420.h new file mode 100644 index 0000000..98d36f9 --- /dev/null +++ b/src/mainboard/google/pit/exynos5420.h @@ -0,0 +1,33 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* I2C */ +#define I2C_0_SPEED 100000 +#define I2C_SLAVE 0 + +/* Voltages */ +#define VDD_ARM_MV 1300 // 1.3V +#define VDD_INT_UV 1012500 // 1.0125V +#define VDD_MIF_MV 1000 // 1.0V +#define VDD_G3D_MV 1200 // 1.2V +#define VDD_LDO2_MV 1500 // 1.5V +#define VDD_LDO3_MV 1800 // 1.8V +#define VDD_LDO5_MV 1800 // 1.8V +#define VDD_LDO10_MV 1800 // 1.8V + diff --git a/src/mainboard/google/pit/mainboard.c b/src/mainboard/google/pit/mainboard.c new file mode 100644 index 0000000..11b72c5 --- /dev/null +++ b/src/mainboard/google/pit/mainboard.c @@ -0,0 +1,273 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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 <edid.h> +#include <vbe.h> +#include <boot/coreboot_tables.h> +#include <arch/cache.h> +#include <arch/exception.h> +#include <cpu/samsung/exynos5420/tmu.h> +#include <cpu/samsung/exynos5420/clk.h> +#include <cpu/samsung/exynos5420/cpu.h> +#include <cpu/samsung/exynos5420/gpio.h> +#include <cpu/samsung/exynos5420/power.h> +#include <cpu/samsung/exynos5420/i2c.h> +#include <cpu/samsung/exynos5420/dp-core.h> + +#include "exynos5420.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 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, GPIO_OUTPUT); + gpio_set_pull(dp_pd_l, GPIO_PULL_NONE); + + gpio_set_value(dp_rst_l, 0); + gpio_cfg_pin(dp_rst_l, GPIO_OUTPUT); + gpio_set_pull(dp_rst_l, 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 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 backlight_en(void) +{ + /* Configure GPIO for LCD_BL_EN */ + gpio_direction_output(GPIO_X30, 1); +} + +#define TPS69050_BUS 4 /* Pit-specific */ + +#define FET1_CTRL 0x0f +#define FET6_CTRL 0x14 + +static void lcd_vdd(void) +{ + /* Enable FET6, lcd panel */ + tps65090_fet_enable(TPS69050_BUS, FET6_CTRL); +} + +static void backlight_vdd(void) +{ + /* Enable FET1, backlight */ + tps65090_fet_enable(TPS69050_BUS, FET1_CTRL); + udelay(LCD_T5_DELAY_MS * 1000); +} + +//static struct video_info smdk5420_dp_config = { +static struct video_info 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 EXYNOS5420_DP1_BASE 0x145b0000 +#define 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 *)EXYNOS5420_DP1_BASE, + .video_info = &dp_video_info, + }; + void *fb_addr; + + i2c_init(TPS69050_BUS, I2C_0_SPEED, I2C_SLAVE); + i2c_init(7, I2C_0_SPEED, I2C_SLAVE); + + tmu_init(&exynos5420_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(&edid, (uintptr_t)(fb_addr) + 64*KiB); + + lcd_vdd(); + do { + udelay(50); + } while (!exynos_dp_hotplug()); + + exynos_dp_bridge_setup(); + for (dp_tries = 1; dp_tries <= 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); + + backlight_vdd(); + backlight_pwm(); + backlight_en(); + /* if we're here, we're successful */ + break; + } + + if (dp_tries > MAX_DP_TRIES) + printk(BIOS_ERR, "%s: Failed to set up displayport\n", __func__); + + gpio_info(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; + + /* set up coreboot tables */ + /* FIXME: this should happen somewhere else */ + 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 */ + exynos5420_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(); +} + +struct chip_operations mainboard_ops = { + .name = "Samsung/Google ARM Chromebook", + .enable_dev = mainboard_enable, +}; diff --git a/src/mainboard/google/pit/memory.c b/src/mainboard/google/pit/memory.c new file mode 100644 index 0000000..e420fe0 --- /dev/null +++ b/src/mainboard/google/pit/memory.c @@ -0,0 +1,546 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stddef.h> +#include <stdlib.h> +#include <console/console.h> + +#include <cpu/samsung/exynos5420/gpio.h> +#include <cpu/samsung/exynos5420/setup.h> +#include <cpu/samsung/exynos5420/dmc.h> +#include <cpu/samsung/exynos5420/clk.h> + +const struct mem_timings mem_timings[] = { + { + .mem_manuf = MEM_MANUF_ELPIDA, + .mem_type = DDR_MODE_DDR3, + .frequency_mhz = 800, + .mpll_mdiv = 0x64, + .mpll_pdiv = 0x3, + .mpll_sdiv = 0x0, + .cpll_mdiv = 0xde, + .cpll_pdiv = 0x4, + .cpll_sdiv = 0x2, + .gpll_mdiv = 0x215, + .gpll_pdiv = 0xc, + .gpll_sdiv = 0x1, + .epll_mdiv = 0x60, + .epll_pdiv = 0x3, + .epll_sdiv = 0x3, + .vpll_mdiv = 0x96, + .vpll_pdiv = 0x3, + .vpll_sdiv = 0x2, + + .bpll_mdiv = 0x64, + .bpll_pdiv = 0x3, + .bpll_sdiv = 0x0, + .use_bpll = 0, + .pclk_cdrex_ratio = 0x5, + .direct_cmd_msr = { + 0x00020018, 0x00030000, 0x00010042, 0x00000d70 + }, + .timing_ref = 0x000000bb, + .timing_row = 0x8c36660f, + .timing_data = 0x3630580b, + .timing_power = 0x41000a44, + .phy0_dqs = 0x08080808, + .phy1_dqs = 0x08080808, + .phy0_dq = 0x08080808, + .phy1_dq = 0x08080808, + .phy0_tFS = 0x4, + .phy1_tFS = 0x4, + .phy0_pulld_dqs = 0xf, + .phy1_pulld_dqs = 0xf, + + .lpddr3_ctrl_phy_reset = 0x1, + .ctrl_start_point = 0x10, + .ctrl_inc = 0x10, + .ctrl_start = 0x1, + .ctrl_dll_on = 0x1, + .ctrl_ref = 0x8, + + .ctrl_force = 0x1a, + .ctrl_rdlat = 0x0b, + .ctrl_bstlen = 0x08, + + .fp_resync = 0x8, + .iv_size = 0x7, + .dfi_init_start = 1, + .aref_en = 1, + + .rd_fetch = 0x3, + + .zq_mode_dds = 0x7, + .zq_mode_term = 0x1, + .zq_mode_noterm = 0, + + /* + * Dynamic Clock: Always Running + * Memory Burst length: 8 + * Number of chips: 1 + * Memory Bus width: 32 bit + * Memory Type: DDR3 + * Additional Latancy for PLL: 0 Cycle + */ + .memcontrol = DMC_MEMCONTROL_CLK_STOP_DISABLE | + DMC_MEMCONTROL_DPWRDN_DISABLE | + DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE | + DMC_MEMCONTROL_TP_DISABLE | + DMC_MEMCONTROL_DSREF_ENABLE | + DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) | + DMC_MEMCONTROL_MEM_TYPE_DDR3 | + DMC_MEMCONTROL_MEM_WIDTH_32BIT | + DMC_MEMCONTROL_NUM_CHIP_1 | + DMC_MEMCONTROL_BL_8 | + DMC_MEMCONTROL_PZQ_DISABLE | + DMC_MEMCONTROL_MRR_BYTE_7_0, + .memconfig = DMC_MEMCONFIGx_CHIP_MAP_INTERLEAVED | + DMC_MEMCONFIGx_CHIP_COL_10 | + DMC_MEMCONFIGx_CHIP_ROW_15 | + DMC_MEMCONFIGx_CHIP_BANK_8, + .membaseconfig0 = DMC_MEMBASECONFIG_VAL(0x40), + .membaseconfig1 = DMC_MEMBASECONFIG_VAL(0x80), + .prechconfig_tp_cnt = 0xff, + .dpwrdn_cyc = 0xff, + .dsref_cyc = 0xffff, + .concontrol = DMC_CONCONTROL_DFI_INIT_START_DISABLE | + DMC_CONCONTROL_TIMEOUT_LEVEL0 | + DMC_CONCONTROL_RD_FETCH_DISABLE | + DMC_CONCONTROL_EMPTY_DISABLE | + DMC_CONCONTROL_AREF_EN_DISABLE | + DMC_CONCONTROL_IO_PD_CON_DISABLE, + .dmc_channels = 2, + .chips_per_channel = 2, + .chips_to_configure = 1, + .send_zq_init = 1, + .impedance = IMP_OUTPUT_DRV_30_OHM, + .gate_leveling_enable = 0, + }, { + .mem_manuf = MEM_MANUF_SAMSUNG, + .mem_type = DDR_MODE_DDR3, + .frequency_mhz = 800, + .mpll_mdiv = 0x64, + .mpll_pdiv = 0x3, + .mpll_sdiv = 0x0, + .cpll_mdiv = 0xde, + .cpll_pdiv = 0x4, + .cpll_sdiv = 0x2, + .gpll_mdiv = 0x215, + .gpll_pdiv = 0xc, + .gpll_sdiv = 0x1, + .epll_mdiv = 0x60, + .epll_pdiv = 0x3, + .epll_sdiv = 0x3, + .vpll_mdiv = 0x96, + .vpll_pdiv = 0x3, + .vpll_sdiv = 0x2, + + .bpll_mdiv = 0x64, + .bpll_pdiv = 0x3, + .bpll_sdiv = 0x0, + .use_bpll = 0, + .pclk_cdrex_ratio = 0x5, + .direct_cmd_msr = { + 0x00020018, 0x00030000, 0x00010000, 0x00000d70 + }, + .timing_ref = 0x000000bb, + .timing_row = 0x8c36660f, + .timing_data = 0x3630580b, + .timing_power = 0x41000a44, + .phy0_dqs = 0x08080808, + .phy1_dqs = 0x08080808, + .phy0_dq = 0x08080808, + .phy1_dq = 0x08080808, + .phy0_tFS = 0x8, + .phy1_tFS = 0x8, + .phy0_pulld_dqs = 0xf, + .phy1_pulld_dqs = 0xf, + + .lpddr3_ctrl_phy_reset = 0x1, + .ctrl_start_point = 0x10, + .ctrl_inc = 0x10, + .ctrl_start = 0x1, + .ctrl_dll_on = 0x1, + .ctrl_ref = 0x8, + + .ctrl_force = 0x1a, + .ctrl_rdlat = 0x0b, + .ctrl_bstlen = 0x08, + + .fp_resync = 0x8, + .iv_size = 0x7, + .dfi_init_start = 1, + .aref_en = 1, + + .rd_fetch = 0x3, + + .zq_mode_dds = 0x5, + .zq_mode_term = 0x1, + .zq_mode_noterm = 1, + + /* + * Dynamic Clock: Always Running + * Memory Burst length: 8 + * Number of chips: 1 + * Memory Bus width: 32 bit + * Memory Type: DDR3 + * Additional Latancy for PLL: 0 Cycle + */ + .memcontrol = DMC_MEMCONTROL_CLK_STOP_DISABLE | + DMC_MEMCONTROL_DPWRDN_DISABLE | + DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE | + DMC_MEMCONTROL_TP_DISABLE | + DMC_MEMCONTROL_DSREF_ENABLE | + DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) | + DMC_MEMCONTROL_MEM_TYPE_DDR3 | + DMC_MEMCONTROL_MEM_WIDTH_32BIT | + DMC_MEMCONTROL_NUM_CHIP_1 | + DMC_MEMCONTROL_BL_8 | + DMC_MEMCONTROL_PZQ_DISABLE | + DMC_MEMCONTROL_MRR_BYTE_7_0, + .memconfig = DMC_MEMCONFIGx_CHIP_MAP_INTERLEAVED | + DMC_MEMCONFIGx_CHIP_COL_10 | + DMC_MEMCONFIGx_CHIP_ROW_15 | + DMC_MEMCONFIGx_CHIP_BANK_8, + .membaseconfig0 = DMC_MEMBASECONFIG_VAL(0x40), + .membaseconfig1 = DMC_MEMBASECONFIG_VAL(0x80), + .prechconfig_tp_cnt = 0xff, + .dpwrdn_cyc = 0xff, + .dsref_cyc = 0xffff, + .concontrol = DMC_CONCONTROL_DFI_INIT_START_DISABLE | + DMC_CONCONTROL_TIMEOUT_LEVEL0 | + DMC_CONCONTROL_RD_FETCH_DISABLE | + DMC_CONCONTROL_EMPTY_DISABLE | + DMC_CONCONTROL_AREF_EN_DISABLE | + DMC_CONCONTROL_IO_PD_CON_DISABLE, + .dmc_channels = 2, + .chips_per_channel = 2, + .chips_to_configure = 1, + .send_zq_init = 1, + .impedance = IMP_OUTPUT_DRV_40_OHM, + .gate_leveling_enable = 1, + }, + { + .mem_manuf = MEM_MANUF_ELPIDA, + .mem_type = DDR_MODE_DDR3, + .frequency_mhz = 780, + .mpll_mdiv = 0x64, + .mpll_pdiv = 0x3, + .mpll_sdiv = 0x0, + .cpll_mdiv = 0xde, + .cpll_pdiv = 0x4, + .cpll_sdiv = 0x2, + .gpll_mdiv = 0x215, + .gpll_pdiv = 0xc, + .gpll_sdiv = 0x1, + .epll_mdiv = 0x60, + .epll_pdiv = 0x3, + .epll_sdiv = 0x3, + .vpll_mdiv = 0x96, + .vpll_pdiv = 0x3, + .vpll_sdiv = 0x2, + + .bpll_mdiv = 0x82, + .bpll_pdiv = 0x4, + .bpll_sdiv = 0x0, + .use_bpll = 1, + .pclk_cdrex_ratio = 0x5, + .direct_cmd_msr = { + 0x00020018, 0x00030000, 0x00010042, 0x00000d70 + }, + .timing_ref = 0x000000bb, + .timing_row = 0x8c36660f, + .timing_data = 0x3630580b, + .timing_power = 0x41000a44, + .phy0_dqs = 0x08080808, + .phy1_dqs = 0x08080808, + .phy0_dq = 0x08080808, + .phy1_dq = 0x08080808, + .phy0_tFS = 0x4, + .phy1_tFS = 0x4, + .phy0_pulld_dqs = 0xf, + .phy1_pulld_dqs = 0xf, + + .lpddr3_ctrl_phy_reset = 0x1, + .ctrl_start_point = 0x10, + .ctrl_inc = 0x10, + .ctrl_start = 0x1, + .ctrl_dll_on = 0x1, + .ctrl_ref = 0x8, + + .ctrl_force = 0x1a, + .ctrl_rdlat = 0x0b, + .ctrl_bstlen = 0x08, + + .fp_resync = 0x8, + .iv_size = 0x7, + .dfi_init_start = 1, + .aref_en = 1, + + .rd_fetch = 0x3, + + .zq_mode_dds = 0x7, + .zq_mode_term = 0x1, + .zq_mode_noterm = 0, + + /* + * Dynamic Clock: Always Running + * Memory Burst length: 8 + * Number of chips: 1 + * Memory Bus width: 32 bit + * Memory Type: DDR3 + * Additional Latancy for PLL: 0 Cycle + */ + .memcontrol = DMC_MEMCONTROL_CLK_STOP_DISABLE | + DMC_MEMCONTROL_DPWRDN_DISABLE | + DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE | + DMC_MEMCONTROL_TP_DISABLE | + DMC_MEMCONTROL_DSREF_ENABLE | + DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) | + DMC_MEMCONTROL_MEM_TYPE_DDR3 | + DMC_MEMCONTROL_MEM_WIDTH_32BIT | + DMC_MEMCONTROL_NUM_CHIP_1 | + DMC_MEMCONTROL_BL_8 | + DMC_MEMCONTROL_PZQ_DISABLE | + DMC_MEMCONTROL_MRR_BYTE_7_0, + .memconfig = DMC_MEMCONFIGx_CHIP_MAP_INTERLEAVED | + DMC_MEMCONFIGx_CHIP_COL_10 | + DMC_MEMCONFIGx_CHIP_ROW_15 | + DMC_MEMCONFIGx_CHIP_BANK_8, + .membaseconfig0 = DMC_MEMBASECONFIG_VAL(0x40), + .membaseconfig1 = DMC_MEMBASECONFIG_VAL(0x80), + .prechconfig_tp_cnt = 0xff, + .dpwrdn_cyc = 0xff, + .dsref_cyc = 0xffff, + .concontrol = DMC_CONCONTROL_DFI_INIT_START_DISABLE | + DMC_CONCONTROL_TIMEOUT_LEVEL0 | + DMC_CONCONTROL_RD_FETCH_DISABLE | + DMC_CONCONTROL_EMPTY_DISABLE | + DMC_CONCONTROL_AREF_EN_DISABLE | + DMC_CONCONTROL_IO_PD_CON_DISABLE, + .dmc_channels = 2, + .chips_per_channel = 2, + .chips_to_configure = 1, + .send_zq_init = 1, + .impedance = IMP_OUTPUT_DRV_30_OHM, + .gate_leveling_enable = 0, + }, { + .mem_manuf = MEM_MANUF_SAMSUNG, + .mem_type = DDR_MODE_DDR3, + .frequency_mhz = 780, + .mpll_mdiv = 0x64, + .mpll_pdiv = 0x3, + .mpll_sdiv = 0x0, + .cpll_mdiv = 0xde, + .cpll_pdiv = 0x4, + .cpll_sdiv = 0x2, + .gpll_mdiv = 0x215, + .gpll_pdiv = 0xc, + .gpll_sdiv = 0x1, + .epll_mdiv = 0x60, + .epll_pdiv = 0x3, + .epll_sdiv = 0x3, + .vpll_mdiv = 0x96, + .vpll_pdiv = 0x3, + .vpll_sdiv = 0x2, + + .bpll_mdiv = 0x82, + .bpll_pdiv = 0x4, + .bpll_sdiv = 0x0, + .use_bpll = 1, + .pclk_cdrex_ratio = 0x5, + .direct_cmd_msr = { + 0x00020018, 0x00030000, 0x00010000, 0x00000d70 + }, + .timing_ref = 0x000000bb, + .timing_row = 0x8c36660f, + .timing_data = 0x3630580b, + .timing_power = 0x41000a44, + .phy0_dqs = 0x08080808, + .phy1_dqs = 0x08080808, + .phy0_dq = 0x08080808, + .phy1_dq = 0x08080808, + .phy0_tFS = 0x8, + .phy1_tFS = 0x8, + .phy0_pulld_dqs = 0xf, + .phy1_pulld_dqs = 0xf, + + .lpddr3_ctrl_phy_reset = 0x1, + .ctrl_start_point = 0x10, + .ctrl_inc = 0x10, + .ctrl_start = 0x1, + .ctrl_dll_on = 0x1, + .ctrl_ref = 0x8, + + .ctrl_force = 0x1a, + .ctrl_rdlat = 0x0b, + .ctrl_bstlen = 0x08, + + .fp_resync = 0x8, + .iv_size = 0x7, + .dfi_init_start = 1, + .aref_en = 1, + + .rd_fetch = 0x3, + + .zq_mode_dds = 0x5, + .zq_mode_term = 0x1, + .zq_mode_noterm = 1, + + /* + * Dynamic Clock: Always Running + * Memory Burst length: 8 + * Number of chips: 1 + * Memory Bus width: 32 bit + * Memory Type: DDR3 + * Additional Latancy for PLL: 0 Cycle + */ + .memcontrol = DMC_MEMCONTROL_CLK_STOP_DISABLE | + DMC_MEMCONTROL_DPWRDN_DISABLE | + DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE | + DMC_MEMCONTROL_TP_DISABLE | + DMC_MEMCONTROL_DSREF_ENABLE | + DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) | + DMC_MEMCONTROL_MEM_TYPE_DDR3 | + DMC_MEMCONTROL_MEM_WIDTH_32BIT | + DMC_MEMCONTROL_NUM_CHIP_1 | + DMC_MEMCONTROL_BL_8 | + DMC_MEMCONTROL_PZQ_DISABLE | + DMC_MEMCONTROL_MRR_BYTE_7_0, + .memconfig = DMC_MEMCONFIGx_CHIP_MAP_INTERLEAVED | + DMC_MEMCONFIGx_CHIP_COL_10 | + DMC_MEMCONFIGx_CHIP_ROW_15 | + DMC_MEMCONFIGx_CHIP_BANK_8, + .membaseconfig0 = DMC_MEMBASECONFIG_VAL(0x40), + .membaseconfig1 = DMC_MEMBASECONFIG_VAL(0x80), + .prechconfig_tp_cnt = 0xff, + .dpwrdn_cyc = 0xff, + .dsref_cyc = 0xffff, + .concontrol = DMC_CONCONTROL_DFI_INIT_START_DISABLE | + DMC_CONCONTROL_TIMEOUT_LEVEL0 | + DMC_CONCONTROL_RD_FETCH_DISABLE | + DMC_CONCONTROL_EMPTY_DISABLE | + DMC_CONCONTROL_AREF_EN_DISABLE | + DMC_CONCONTROL_IO_PD_CON_DISABLE, + .dmc_channels = 2, + .chips_per_channel = 2, + .chips_to_configure = 1, + .send_zq_init = 1, + .impedance = IMP_OUTPUT_DRV_40_OHM, + .gate_leveling_enable = 1, + } +}; + +#define BOARD_ID0_GPIO 88 /* GPD0, pin 0 */ +#define BOARD_ID1_GPIO 89 /* GPD0, pin 1 */ + +enum board_config { + PIT_CONFIG_UNKNOWN = -1, + PIT_CONFIG_SAMSUNG_EVT, + PIT_CONFIG_ELPIDA_EVT, + PIT_CONFIG_SAMSUNG_DVT, + PIT_CONFIG_ELPIDA_DVT, + PIT_CONFIG_SAMSUNG_PVT, + PIT_CONFIG_ELPIDA_PVT, + PIT_CONFIG_SAMSUNG_MP, + PIT_CONFIG_ELPIDA_MP, + PIT_CONFIG_RSVD, +}; + +struct { + enum mvl3 id0, id1; + enum board_config config; +} id_map[] = { + /* ID0 ID1 config */ + { LOGIC_0, LOGIC_0, PIT_CONFIG_SAMSUNG_MP }, + { LOGIC_0, LOGIC_1, PIT_CONFIG_ELPIDA_MP }, + { LOGIC_1, LOGIC_0, PIT_CONFIG_SAMSUNG_DVT }, + { LOGIC_1, LOGIC_1, PIT_CONFIG_ELPIDA_DVT }, + { LOGIC_0, LOGIC_Z, PIT_CONFIG_SAMSUNG_PVT }, + { LOGIC_1, LOGIC_Z, PIT_CONFIG_ELPIDA_PVT }, + { LOGIC_Z, LOGIC_0, PIT_CONFIG_SAMSUNG_MP }, + { LOGIC_Z, LOGIC_Z, PIT_CONFIG_ELPIDA_MP }, + { LOGIC_Z, LOGIC_1, PIT_CONFIG_RSVD }, +}; + +static int board_get_config(void) +{ + int i; + int id0, id1; + enum board_config config = PIT_CONFIG_UNKNOWN; + + id0 = gpio_read_mvl3(BOARD_ID0_GPIO); + id1 = gpio_read_mvl3(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(id_map); i++) { + if (id0 == id_map[i].id0 && id1 == id_map[i].id1) { + config = id_map[i].config; + break; + } + } + + return config; +} + +struct mem_timings *get_mem_timings(void) +{ + int i; + enum board_config config; + enum ddr_mode mem_type; + unsigned int frequency_mhz; + enum mem_manuf mem_manuf; + const struct mem_timings *mem; + + config = board_get_config(); + switch (config) { + case PIT_CONFIG_ELPIDA_EVT: + case PIT_CONFIG_ELPIDA_DVT: + case PIT_CONFIG_ELPIDA_PVT: + case PIT_CONFIG_ELPIDA_MP: + mem_manuf = MEM_MANUF_ELPIDA; + mem_type = DDR_MODE_DDR3; + frequency_mhz = 800; + break; + case PIT_CONFIG_SAMSUNG_EVT: + case PIT_CONFIG_SAMSUNG_DVT: + case PIT_CONFIG_SAMSUNG_PVT: + case PIT_CONFIG_SAMSUNG_MP: + mem_manuf = MEM_MANUF_SAMSUNG; + mem_type = DDR_MODE_DDR3; + frequency_mhz = 800; + break; + default: + printk(BIOS_CRIT, "Unknown board configuration.\n"); + return NULL; + } + + for (i = 0, mem = mem_timings; i < ARRAY_SIZE(mem_timings); + i++, mem++) { + if (mem->mem_type == mem_type && + mem->frequency_mhz == frequency_mhz && + mem->mem_manuf == mem_manuf) + return (struct mem_timings *)mem; + } + + return NULL; +} diff --git a/src/mainboard/google/pit/romstage.c b/src/mainboard/google/pit/romstage.c new file mode 100644 index 0000000..08f19f5 --- /dev/null +++ b/src/mainboard/google/pit/romstage.c @@ -0,0 +1,191 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <types.h> + +#include <armv7.h> +#include <cbfs.h> + +#include <arch/cache.h> +#include <cpu/samsung/exynos5420/i2c.h> +#include <cpu/samsung/exynos5420/clk.h> +#include <cpu/samsung/exynos5420/cpu.h> +#include <cpu/samsung/exynos5420/dmc.h> +#include <cpu/samsung/exynos5420/gpio.h> +#include <cpu/samsung/exynos5420/setup.h> +#include <cpu/samsung/exynos5420/periph.h> +#include <cpu/samsung/exynos5420/power.h> +#include <cpu/samsung/exynos5420/wakeup.h> +#include <console/console.h> +#include <arch/stages.h> + +#include <drivers/maxim/max77686/max77686.h> +#include <device/i2c.h> + +#include "exynos5420.h" + +#define PMIC_BUS 0 +#define MMC0_GPIO_PIN (58) + +static void setup_power(void) +{ + int error = 0; + + power_init(); + + /* Initialize I2C bus to configure PMIC. */ + i2c_init(0, I2C_0_SPEED, 0x00); + + printk(BIOS_DEBUG, "%s: Setting up PMIC...\n", __func__); + /* + * We're using CR1616 coin cell battery that is non-rechargeable + * battery. But, BBCHOSTEN bit of the BBAT Charger Register in + * MAX77686 is enabled by default for charging coin cell. + * + * Also, we cannot meet the coin cell reverse current spec. in UL + * standard if BBCHOSTEN bit is enabled. + * + * Disable Coin BATT Charging + */ + error = max77686_disable_backup_batt(PMIC_BUS); + + error |= max77686_volsetting(PMIC_BUS, PMIC_BUCK2, VDD_ARM_MV, + REG_ENABLE, MAX77686_MV); + error |= max77686_volsetting(PMIC_BUS, PMIC_BUCK3, VDD_INT_UV, + REG_ENABLE, MAX77686_UV); + error |= max77686_volsetting(PMIC_BUS, PMIC_BUCK1, VDD_MIF_MV, + REG_ENABLE, MAX77686_MV); + error |= max77686_volsetting(PMIC_BUS, PMIC_BUCK4, VDD_G3D_MV, + REG_ENABLE, MAX77686_MV); + error |= max77686_volsetting(PMIC_BUS, PMIC_LDO2, VDD_LDO2_MV, + REG_ENABLE, MAX77686_MV); + error |= max77686_volsetting(PMIC_BUS, PMIC_LDO3, VDD_LDO3_MV, + REG_ENABLE, MAX77686_MV); + error |= max77686_volsetting(PMIC_BUS, PMIC_LDO5, VDD_LDO5_MV, + REG_ENABLE, MAX77686_MV); + error |= max77686_volsetting(PMIC_BUS, PMIC_LDO10, VDD_LDO10_MV, + REG_ENABLE, MAX77686_MV); + + error |= max77686_enable_32khz_cp(PMIC_BUS); + + if (error) { + printk(BIOS_CRIT, "%s: PMIC error: %#x\n", __func__, error); + die("Failed to intialize PMIC.\n"); + } +} + +static void setup_storage(void) +{ + /* MMC0: Fixed, 8 bit mode, connected with GPIO. */ + if (clock_set_mshci(PERIPH_ID_SDMMC0)) + printk(BIOS_CRIT, "%s: Failed to set MMC0 clock.\n", __func__); + if (gpio_direction_output(MMC0_GPIO_PIN, 1)) { + printk(BIOS_CRIT, "%s: Unable to power on MMC0.\n", __func__); + } + gpio_set_pull(MMC0_GPIO_PIN, GPIO_PULL_NONE); + gpio_set_drv(MMC0_GPIO_PIN, GPIO_DRV_4X); + exynos_pinmux_config(PERIPH_ID_SDMMC0, PINMUX_FLAG_8BIT_MODE); + + /* MMC2: Removable, 4 bit mode, no GPIO. */ + clock_set_mshci(PERIPH_ID_SDMMC2); + exynos_pinmux_config(PERIPH_ID_SDMMC2, 0); +} + +static void setup_graphics(void) +{ + exynos_pinmux_config(PERIPH_ID_DPHPD, 0); +} + +static void setup_gpio(void) +{ + gpio_direction_input(GPIO_D16); // WP_GPIO + gpio_set_pull(GPIO_D16, GPIO_PULL_NONE); + + gpio_direction_input(GPIO_Y10); // RECMODE_GPIO + gpio_set_pull(GPIO_Y10, GPIO_PULL_NONE); + + gpio_direction_input(GPIO_X35); // LID_GPIO + gpio_set_pull(GPIO_X35, GPIO_PULL_NONE); + + gpio_direction_input(GPIO_X13); // POWER_GPIO + gpio_set_pull(GPIO_X13, GPIO_PULL_NONE); +} + +static void setup_memory(struct mem_timings *mem, int is_resume) +{ + printk(BIOS_SPEW, "man: 0x%x type: 0x%x, div: 0x%x, mhz: 0x%x\n", + mem->mem_manuf, + mem->mem_type, + mem->mpll_mdiv, + mem->frequency_mhz); + + /* FIXME Currently memory initialization with mem_reset on normal boot + * will cause resume to fail (even if we don't do mem_reset on resume), + * and the workaround is to temporarily always enable "is_resume". + * This should be removed when the root cause of resume issue is found. + */ + is_resume = 1; + + if (ddr3_mem_ctrl_init(mem, DMC_INTERLEAVE_SIZE, !is_resume)) { + die("Failed to initialize memory controller.\n"); + } +} + +static struct mem_timings *setup_clock(void) +{ + struct mem_timings *mem = get_mem_timings(); + struct arm_clk_ratios *arm_ratios = get_arm_clk_ratios(); + if (!mem) { + die("Unable to auto-detect memory timings\n"); + } + system_clock_init(mem, arm_ratios); + return mem; +} + +void main(void) +{ + struct mem_timings *mem; + void *entry; + int is_resume = (get_wakeup_state() != IS_NOT_WAKEUP); + + /* Clock must be initialized before console_init, otherwise you may need + * to re-initialize serial console drivers again. */ + mem = setup_clock(); + + if (!is_resume) { + console_init(); + setup_power(); + } + + setup_memory(mem, is_resume); + + if (is_resume) { + wakeup(); + } + + setup_storage(); + setup_gpio(); + setup_graphics(); + + /* Set SPI (primary CBFS media) clock to 50MHz. */ + clock_set_rate(PERIPH_ID_SPI1, 50000000); + + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/coreboot_ram"); + stage_exit(entry); +} diff --git a/src/mainboard/google/pit/wakeup.c b/src/mainboard/google/pit/wakeup.c new file mode 100644 index 0000000..a82b632 --- /dev/null +++ b/src/mainboard/google/pit/wakeup.c @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <cpu/samsung/exynos5420/gpio.h> +#include <cpu/samsung/exynos5420/wakeup.h> + +int wakeup_need_reset(void) +{ + /* The "wake up" event is not reliable (known as "bad wakeup") and needs + * reset if GPIO value is high. */ + return gpio_get_value(GPIO_Y10); +} +