/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mainboard.h" #define PMIC_BUS 0 #define MMC0_GPIO_PIN (58) #if 0 static int board_wakeup_permitted(void) { const int gpio = GPIO_Y10; int is_bad_wake; /* We're a bad wakeup if the gpio was defined and was high */ is_bad_wake = ((gpio != -1) && gpio_get_value(gpio)); return !is_bad_wake; } #endif static int setup_pmic(void) { int error = 0; /* * 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, CONFIG_VDD_ARM_MV, REG_ENABLE, MAX77686_MV); error |= max77686_volsetting(PMIC_BUS, PMIC_BUCK3, CONFIG_VDD_INT_UV, REG_ENABLE, MAX77686_UV); error |= max77686_volsetting(PMIC_BUS, PMIC_BUCK1, CONFIG_VDD_MIF_MV, REG_ENABLE, MAX77686_MV); error |= max77686_volsetting(PMIC_BUS, PMIC_BUCK4, CONFIG_VDD_G3D_MV, REG_ENABLE, MAX77686_MV); error |= max77686_volsetting(PMIC_BUS, PMIC_LDO2, CONFIG_VDD_LDO2_MV, REG_ENABLE, MAX77686_MV); error |= max77686_volsetting(PMIC_BUS, PMIC_LDO3, CONFIG_VDD_LDO3_MV, REG_ENABLE, MAX77686_MV); error |= max77686_volsetting(PMIC_BUS, PMIC_LDO5, CONFIG_VDD_LDO5_MV, REG_ENABLE, MAX77686_MV); error |= max77686_volsetting(PMIC_BUS, PMIC_LDO10, CONFIG_VDD_LDO10_MV, REG_ENABLE, MAX77686_MV); if (error) printk(BIOS_CRIT, "%s: Error during PMIC setup\n", __func__); return error; } static void initialize_s5p_mshc(void) { /* MMC0: Fixed, 8 bit mode, connected with GPIO. */ if (clock_set_mshci(PERIPH_ID_SDMMC0)) printk(BIOS_CRIT, "Failed to set clock for SDMMC0.\n"); if (gpio_direction_output(MMC0_GPIO_PIN, 1)) { printk(BIOS_CRIT, "Unable to power on SDMMC0.\n"); } gpio_set_pull(MMC0_GPIO_PIN, EXYNOS_GPIO_PULL_NONE); gpio_set_drv(MMC0_GPIO_PIN, EXYNOS_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 graphics(void) { exynos_pinmux_config(PERIPH_ID_DPHPD, 0); } static void chromeos_gpios(void) { struct exynos5_gpio_part1 *gpio_pt1; struct exynos5_gpio_part2 *gpio_pt2; enum { WP_GPIO = 6, RECMODE_GPIO = 0, LID_GPIO = 5, POWER_GPIO = 3 }; gpio_pt1 = (struct exynos5_gpio_part1 *)EXYNOS5_GPIO_PART1_BASE; gpio_pt2 = (struct exynos5_gpio_part2 *)EXYNOS5_GPIO_PART2_BASE; s5p_gpio_direction_input(&gpio_pt1->d1, WP_GPIO); s5p_gpio_set_pull(&gpio_pt1->d1, WP_GPIO, EXYNOS_GPIO_PULL_NONE); s5p_gpio_direction_input(&gpio_pt1->y1, RECMODE_GPIO); s5p_gpio_set_pull(&gpio_pt1->y1, RECMODE_GPIO, EXYNOS_GPIO_PULL_NONE); s5p_gpio_direction_input(&gpio_pt2->x3, LID_GPIO); s5p_gpio_set_pull(&gpio_pt2->x3, LID_GPIO, EXYNOS_GPIO_PULL_NONE); s5p_gpio_direction_input(&gpio_pt2->x1, POWER_GPIO); s5p_gpio_set_pull(&gpio_pt2->x1, POWER_GPIO, EXYNOS_GPIO_PULL_NONE); } void main(void) { struct mem_timings *mem; struct arm_clk_ratios *arm_ratios; int ret; void *entry; clock_set_rate(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */ /* Clock must be initialized before console_init, otherwise you may need * to re-initialize serial console drivers again. */ mem = get_mem_timings(); arm_ratios = get_arm_clk_ratios(); system_clock_init(mem, arm_ratios); console_init(); i2c_init(0, CONFIG_SYS_I2C_SPEED, 0x00); if (power_init()) power_shutdown(); printk(BIOS_DEBUG, "%s: setting up pmic...\n", __func__); if (setup_pmic()) power_shutdown(); if (!mem) { printk(BIOS_CRIT, "Unable to auto-detect memory timings\n"); while(1); } 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); ret = ddr3_mem_ctrl_init(mem, DMC_INTERLEAVE_SIZE); if (ret) { printk(BIOS_ERR, "Memory controller init failed, err: %x\n", ret); while(1); } initialize_s5p_mshc(); chromeos_gpios(); graphics(); entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/coreboot_ram"); printk(BIOS_INFO, "entry is 0x%p, leaving romstage.\n", entry); stage_exit(entry); }