mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-10-12 09:11:49 +00:00
2955d60015
Some Exynos5250 silicon may require 1.05v on the MIF to be stable, so to be safe we can default to 1.05v instead of 1.00v. This can be set optimally later in the boot process by the kernel. The 0x6 value for 1.05v comes from the MAX77686 datasheet. Signed-off-by: Bernie Thompson <bhthompson@chromium.org> Acked-by: Simon Glass <sjg@chromium.org> Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>
444 lines
9.9 KiB
C
444 lines
9.9 KiB
C
/*
|
|
* Copyright (C) 2012 Samsung Electronics
|
|
*
|
|
* See file CREDITS for list of people who contributed to this
|
|
* project.
|
|
*
|
|
* 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; either version 2 of
|
|
* the License, or (at your option) any later version.
|
|
*
|
|
* 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., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307 USA
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <fdtdec.h>
|
|
#include <asm/io.h>
|
|
#include <errno.h>
|
|
#include <i2c.h>
|
|
#include <lcd.h>
|
|
#include <netdev.h>
|
|
#include <spi.h>
|
|
#include <asm/arch/cpu.h>
|
|
#include <asm/arch/dwmmc.h>
|
|
#include <asm/arch/gpio.h>
|
|
#include <asm/arch/mmc.h>
|
|
#include <asm/arch/pinmux.h>
|
|
#include <asm/arch/power.h>
|
|
#include <asm/arch/sromc.h>
|
|
#include <asm/arch/dp_info.h>
|
|
#include <power/pmic.h>
|
|
#include <power/max77686_pmic.h>
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
#ifdef CONFIG_USB_EHCI_EXYNOS
|
|
int board_usb_vbus_init(void)
|
|
{
|
|
struct exynos5_gpio_part1 *gpio1 = (struct exynos5_gpio_part1 *)
|
|
samsung_get_base_gpio_part1();
|
|
|
|
/* Enable VBUS power switch */
|
|
s5p_gpio_direction_output(&gpio1->x2, 6, 1);
|
|
|
|
/* VBUS turn ON time */
|
|
mdelay(3);
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_SOUND_MAX98095
|
|
static void board_enable_audio_codec(void)
|
|
{
|
|
struct exynos5_gpio_part1 *gpio1 = (struct exynos5_gpio_part1 *)
|
|
samsung_get_base_gpio_part1();
|
|
|
|
/* Enable MAX98095 Codec */
|
|
s5p_gpio_direction_output(&gpio1->x1, 7, 1);
|
|
s5p_gpio_set_pull(&gpio1->x1, 7, GPIO_PULL_NONE);
|
|
}
|
|
#endif
|
|
|
|
int board_init(void)
|
|
{
|
|
gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL);
|
|
|
|
#ifdef CONFIG_EXYNOS_SPI
|
|
spi_init();
|
|
#endif
|
|
#ifdef CONFIG_USB_EHCI_EXYNOS
|
|
board_usb_vbus_init();
|
|
#endif
|
|
#ifdef CONFIG_SOUND_MAX98095
|
|
board_enable_audio_codec();
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
int dram_init(void)
|
|
{
|
|
int i;
|
|
u32 addr;
|
|
|
|
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
|
|
addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
|
|
gd->ram_size += get_ram_size((long *)addr, SDRAM_BANK_SIZE);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#if defined(CONFIG_POWER)
|
|
static int pmic_reg_update(struct pmic *p, int reg, uint regval)
|
|
{
|
|
u32 val;
|
|
int ret = 0;
|
|
|
|
ret = pmic_reg_read(p, reg, &val);
|
|
if (ret) {
|
|
debug("%s: PMIC %d register read failed\n", __func__, reg);
|
|
return -1;
|
|
}
|
|
val |= regval;
|
|
ret = pmic_reg_write(p, reg, val);
|
|
if (ret) {
|
|
debug("%s: PMIC %d register write failed\n", __func__, reg);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int power_init_board(void)
|
|
{
|
|
struct pmic *p;
|
|
|
|
set_ps_hold_ctrl();
|
|
|
|
i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
|
|
|
|
if (pmic_init(I2C_PMIC))
|
|
return -1;
|
|
|
|
p = pmic_get("MAX77686_PMIC");
|
|
if (!p)
|
|
return -ENODEV;
|
|
|
|
if (pmic_probe(p))
|
|
return -1;
|
|
|
|
if (pmic_reg_update(p, MAX77686_REG_PMIC_32KHZ, MAX77686_32KHCP_EN))
|
|
return -1;
|
|
|
|
if (pmic_reg_update(p, MAX77686_REG_PMIC_BBAT,
|
|
MAX77686_BBCHOSTEN | MAX77686_BBCVS_3_5V))
|
|
return -1;
|
|
|
|
/* VDD_MIF */
|
|
if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK1OUT,
|
|
MAX77686_BUCK1OUT_1_05V)) {
|
|
debug("%s: PMIC %d register write failed\n", __func__,
|
|
MAX77686_REG_PMIC_BUCK1OUT);
|
|
return -1;
|
|
}
|
|
|
|
if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK1CRTL,
|
|
MAX77686_BUCK1CTRL_EN))
|
|
return -1;
|
|
|
|
/* VDD_ARM */
|
|
if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK2DVS1,
|
|
MAX77686_BUCK2DVS1_1_3V)) {
|
|
debug("%s: PMIC %d register write failed\n", __func__,
|
|
MAX77686_REG_PMIC_BUCK2DVS1);
|
|
return -1;
|
|
}
|
|
|
|
if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK2CTRL1,
|
|
MAX77686_BUCK2CTRL_ON))
|
|
return -1;
|
|
|
|
/* VDD_INT */
|
|
if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK3DVS1,
|
|
MAX77686_BUCK3DVS1_1_0125V)) {
|
|
debug("%s: PMIC %d register write failed\n", __func__,
|
|
MAX77686_REG_PMIC_BUCK3DVS1);
|
|
return -1;
|
|
}
|
|
|
|
if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK3CTRL,
|
|
MAX77686_BUCK3CTRL_ON))
|
|
return -1;
|
|
|
|
/* VDD_G3D */
|
|
if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK4DVS1,
|
|
MAX77686_BUCK4DVS1_1_2V)) {
|
|
debug("%s: PMIC %d register write failed\n", __func__,
|
|
MAX77686_REG_PMIC_BUCK4DVS1);
|
|
return -1;
|
|
}
|
|
|
|
if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK4CTRL1,
|
|
MAX77686_BUCK3CTRL_ON))
|
|
return -1;
|
|
|
|
/* VDD_LDO2 */
|
|
if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO2CTRL1,
|
|
MAX77686_LD02CTRL1_1_5V | EN_LDO))
|
|
return -1;
|
|
|
|
/* VDD_LDO3 */
|
|
if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO3CTRL1,
|
|
MAX77686_LD03CTRL1_1_8V | EN_LDO))
|
|
return -1;
|
|
|
|
/* VDD_LDO5 */
|
|
if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO5CTRL1,
|
|
MAX77686_LD05CTRL1_1_8V | EN_LDO))
|
|
return -1;
|
|
|
|
/* VDD_LDO10 */
|
|
if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO10CTRL1,
|
|
MAX77686_LD10CTRL1_1_8V | EN_LDO))
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
void dram_init_banksize(void)
|
|
{
|
|
int i;
|
|
u32 addr, size;
|
|
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
|
|
addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
|
|
size = get_ram_size((long *)addr, SDRAM_BANK_SIZE);
|
|
gd->bd->bi_dram[i].start = addr;
|
|
gd->bd->bi_dram[i].size = size;
|
|
}
|
|
}
|
|
|
|
int board_eth_init(bd_t *bis)
|
|
{
|
|
#ifdef CONFIG_SMC911X
|
|
u32 smc_bw_conf, smc_bc_conf;
|
|
struct fdt_sromc config;
|
|
fdt_addr_t base_addr;
|
|
|
|
/* Non-FDT configuration - bank number and timing parameters*/
|
|
config.bank = CONFIG_ENV_SROM_BANK;
|
|
config.width = 2;
|
|
|
|
config.timing[FDT_SROM_TACS] = 0x01;
|
|
config.timing[FDT_SROM_TCOS] = 0x01;
|
|
config.timing[FDT_SROM_TACC] = 0x06;
|
|
config.timing[FDT_SROM_TCOH] = 0x01;
|
|
config.timing[FDT_SROM_TAH] = 0x0C;
|
|
config.timing[FDT_SROM_TACP] = 0x09;
|
|
config.timing[FDT_SROM_PMC] = 0x01;
|
|
base_addr = CONFIG_SMC911X_BASE;
|
|
|
|
/* Ethernet needs data bus width of 16 bits */
|
|
if (config.width != 2) {
|
|
debug("%s: Unsupported bus width %d\n", __func__,
|
|
config.width);
|
|
return -1;
|
|
}
|
|
smc_bw_conf = SROMC_DATA16_WIDTH(config.bank)
|
|
| SROMC_BYTE_ENABLE(config.bank);
|
|
|
|
smc_bc_conf = SROMC_BC_TACS(config.timing[FDT_SROM_TACS]) |\
|
|
SROMC_BC_TCOS(config.timing[FDT_SROM_TCOS]) |\
|
|
SROMC_BC_TACC(config.timing[FDT_SROM_TACC]) |\
|
|
SROMC_BC_TCOH(config.timing[FDT_SROM_TCOH]) |\
|
|
SROMC_BC_TAH(config.timing[FDT_SROM_TAH]) |\
|
|
SROMC_BC_TACP(config.timing[FDT_SROM_TACP]) |\
|
|
SROMC_BC_PMC(config.timing[FDT_SROM_PMC]);
|
|
|
|
/* Select and configure the SROMC bank */
|
|
exynos_pinmux_config(PERIPH_ID_SROMC, config.bank);
|
|
s5p_config_sromc(config.bank, smc_bw_conf, smc_bc_conf);
|
|
return smc911x_initialize(0, base_addr);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_DISPLAY_BOARDINFO
|
|
int checkboard(void)
|
|
{
|
|
printf("\nBoard: SMDK5250\n");
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_GENERIC_MMC
|
|
int board_mmc_init(bd_t *bis)
|
|
{
|
|
int err, ret = 0, index, bus_width;
|
|
u32 base;
|
|
|
|
err = exynos_pinmux_config(PERIPH_ID_SDMMC0, PINMUX_FLAG_8BIT_MODE);
|
|
if (err)
|
|
debug("SDMMC0 not configured\n");
|
|
ret |= err;
|
|
|
|
/*EMMC: dwmmc Channel-0 with 8 bit bus width */
|
|
index = 0;
|
|
base = samsung_get_base_mmc() + (0x10000 * index);
|
|
bus_width = 8;
|
|
err = exynos_dwmci_add_port(index, base, bus_width, (u32)NULL);
|
|
if (err)
|
|
debug("dwmmc Channel-0 init failed\n");
|
|
ret |= err;
|
|
|
|
err = exynos_pinmux_config(PERIPH_ID_SDMMC2, PINMUX_FLAG_NONE);
|
|
if (err)
|
|
debug("SDMMC2 not configured\n");
|
|
ret |= err;
|
|
|
|
/*SD: dwmmc Channel-2 with 4 bit bus width */
|
|
index = 2;
|
|
base = samsung_get_base_mmc() + (0x10000 * index);
|
|
bus_width = 4;
|
|
err = exynos_dwmci_add_port(index, base, bus_width, (u32)NULL);
|
|
if (err)
|
|
debug("dwmmc Channel-2 init failed\n");
|
|
ret |= err;
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
static int board_uart_init(void)
|
|
{
|
|
int err, uart_id, ret = 0;
|
|
|
|
for (uart_id = PERIPH_ID_UART0; uart_id <= PERIPH_ID_UART3; uart_id++) {
|
|
err = exynos_pinmux_config(uart_id, PINMUX_FLAG_NONE);
|
|
if (err) {
|
|
debug("UART%d not configured\n",
|
|
(uart_id - PERIPH_ID_UART0));
|
|
ret |= err;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#ifdef CONFIG_BOARD_EARLY_INIT_F
|
|
int board_early_init_f(void)
|
|
{
|
|
int err;
|
|
err = board_uart_init();
|
|
if (err) {
|
|
debug("UART init failed\n");
|
|
return err;
|
|
}
|
|
#ifdef CONFIG_SYS_I2C_INIT_BOARD
|
|
board_i2c_init(NULL);
|
|
#endif
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_LCD
|
|
void exynos_cfg_lcd_gpio(void)
|
|
{
|
|
struct exynos5_gpio_part1 *gpio1 =
|
|
(struct exynos5_gpio_part1 *) samsung_get_base_gpio_part1();
|
|
|
|
/* For Backlight */
|
|
s5p_gpio_cfg_pin(&gpio1->b2, 0, GPIO_OUTPUT);
|
|
s5p_gpio_set_value(&gpio1->b2, 0, 1);
|
|
|
|
/* LCD power on */
|
|
s5p_gpio_cfg_pin(&gpio1->x1, 5, GPIO_OUTPUT);
|
|
s5p_gpio_set_value(&gpio1->x1, 5, 1);
|
|
|
|
/* Set Hotplug detect for DP */
|
|
s5p_gpio_cfg_pin(&gpio1->x0, 7, GPIO_FUNC(0x3));
|
|
}
|
|
|
|
void exynos_set_dp_phy(unsigned int onoff)
|
|
{
|
|
set_dp_phy_ctrl(onoff);
|
|
}
|
|
|
|
vidinfo_t panel_info = {
|
|
.vl_freq = 60,
|
|
.vl_col = 2560,
|
|
.vl_row = 1600,
|
|
.vl_width = 2560,
|
|
.vl_height = 1600,
|
|
.vl_clkp = CONFIG_SYS_LOW,
|
|
.vl_hsp = CONFIG_SYS_LOW,
|
|
.vl_vsp = CONFIG_SYS_LOW,
|
|
.vl_dp = CONFIG_SYS_LOW,
|
|
.vl_bpix = 4, /* LCD_BPP = 2^4, for output conosle on LCD */
|
|
|
|
/* wDP panel timing infomation */
|
|
.vl_hspw = 32,
|
|
.vl_hbpd = 80,
|
|
.vl_hfpd = 48,
|
|
|
|
.vl_vspw = 6,
|
|
.vl_vbpd = 37,
|
|
.vl_vfpd = 3,
|
|
.vl_cmd_allow_len = 0xf,
|
|
|
|
.win_id = 3,
|
|
.dual_lcd_enabled = 0,
|
|
|
|
.init_delay = 0,
|
|
.power_on_delay = 0,
|
|
.reset_delay = 0,
|
|
.interface_mode = FIMD_RGB_INTERFACE,
|
|
.dp_enabled = 1,
|
|
};
|
|
|
|
static struct edp_device_info edp_info = {
|
|
.disp_info = {
|
|
.h_res = 2560,
|
|
.h_sync_width = 32,
|
|
.h_back_porch = 80,
|
|
.h_front_porch = 48,
|
|
.v_res = 1600,
|
|
.v_sync_width = 6,
|
|
.v_back_porch = 37,
|
|
.v_front_porch = 3,
|
|
.v_sync_rate = 60,
|
|
},
|
|
.lt_info = {
|
|
.lt_status = DP_LT_NONE,
|
|
},
|
|
.video_info = {
|
|
.master_mode = 0,
|
|
.bist_mode = DP_DISABLE,
|
|
.bist_pattern = NO_PATTERN,
|
|
.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,
|
|
},
|
|
};
|
|
|
|
static struct exynos_dp_platform_data dp_platform_data = {
|
|
.edp_dev_info = &edp_info,
|
|
};
|
|
|
|
void init_panel_info(vidinfo_t *vid)
|
|
{
|
|
vid->rgb_mode = MODE_RGB_P;
|
|
exynos_set_dp_platform_data(&dp_platform_data);
|
|
}
|
|
#endif
|