exynos/snow: partial clean-up of snow bootblock using build class

This removes some duplicate code from Snow's mainboard bootblock
by utilizing the bootblock build class.

Change-Id: I153247370a8c5127260082dcdca3ebdc5e104fb8
Signed-off-by: David Hendricks <dhendrix@chromium.org>
Reviewed-on: http://review.coreboot.org/2270
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
David Hendricks 2013-02-03 19:13:36 -08:00 committed by Ronald G. Minnich
parent ad7f98cb01
commit aa6701c090
6 changed files with 55 additions and 273 deletions

View File

@ -1,3 +1,5 @@
bootblock-y += syslib.c
romstage-y += cache_v7.c romstage-y += cache_v7.c
romstage-y += cache-cp15.c romstage-y += cache-cp15.c
romstage-y += div0.c romstage-y += div0.c

View File

@ -18,7 +18,7 @@ config SATA_AHCI
# #
# 0x0202_0000: vendor-provided BL1 # 0x0202_0000: vendor-provided BL1
# 0x0202_3400: bootblock, assume up to 32KB in size # 0x0202_3400: bootblock, assume up to 32KB in size
# 0x0202_2600: ID section, assume 2KB in size. This will be # 0x0202_7000: ID section, assume 2KB in size. This will be
# within the bootblock section. # within the bootblock section.
# 0x0203_0000: romstage, assume up to 128KB in size. # 0x0203_0000: romstage, assume up to 128KB in size.
# 0x0207_7f00: stack pointer # 0x0207_7f00: stack pointer
@ -38,7 +38,7 @@ config BOOTBLOCK_BASE
config ID_SECTION_BASE config ID_SECTION_BASE
hex hex
default 0x02026000 default 0x02027000
config ROMSTAGE_BASE config ROMSTAGE_BASE
hex hex

View File

@ -3,6 +3,12 @@
# image outside of CBFS # image outside of CBFS
#INTERMEDIATE += exynos5250_add_bl1 #INTERMEDIATE += exynos5250_add_bl1
# Clock init is done in bootblock to support UART output for
# debugging. We may add a Kconfig option to disable clock init
# in the bootblock and try moving it entirely into romstage.
bootblock-y += clock_init.c
bootblock-y += clock.c
romstage-y += clock.c romstage-y += clock.c
romstage-y += clock_init.c romstage-y += clock_init.c
romstage-y += exynos_cache.c romstage-y += exynos_cache.c

View File

@ -597,6 +597,38 @@ static int autodetect_memory(void)
#ifdef CONFIG_SPL_BUILD #ifdef CONFIG_SPL_BUILD
#define SIGNATURE 0xdeadbeef
/* Parameters of early board initialization in SPL */
static struct spl_machine_param machine_param = {
.signature = SIGNATURE,
.version = 1,
.params = "vmubfasirMw",
.size = sizeof(machine_param),
.mem_iv_size = 0x1f,
.mem_type = DDR_MODE_DDR3,
/*
* Set uboot_size to 0x100000 bytes.
*
* This is an overly conservative value chosen to accommodate all
* possible U-Boot image. You are advised to set this value to a
* smaller realistic size via scripts that modifies the .machine_param
* section of output U-Boot image.
*/
.uboot_size = 0x100000,
.boot_source = BOOT_MODE_OM,
.frequency_mhz = 800,
.arm_freq_mhz = 1700,
.serial_base = 0x12c30000,
.i2c_base = 0x12c60000,
// .board_rev_gpios = GPIO_D00 | (GPIO_D01 << 16),
.mem_manuf = MEM_MANUF_SAMSUNG,
// .bad_wake_gpio = GPIO_Y10,
};
/** /**
* Get the required memory type and speed (SPL version). * Get the required memory type and speed (SPL version).
* *
@ -608,7 +640,7 @@ int clock_get_mem_selection(enum ddr_mode *mem_type,
{ {
struct spl_machine_param *params; struct spl_machine_param *params;
params = spl_get_machine_params(); params = &machine_param;
*mem_type = params->mem_type; *mem_type = params->mem_type;
*frequency_mhz = params->frequency_mhz; *frequency_mhz = params->frequency_mhz;
*arm_freq = params->arm_freq_mhz; *arm_freq = params->arm_freq_mhz;
@ -719,7 +751,7 @@ struct arm_clk_ratios *get_arm_ratios(void)
return arm_ratio; return arm_ratio;
} }
die("get_arm_ratios: Failed to find ratio\n"); // die("get_arm_ratios: Failed to find ratio\n");
return NULL; return NULL;
} }

View File

@ -1,3 +1,6 @@
bootblock-y += pwm.c
bootblock-y += timer.c
romstage-y += cpu_info.c romstage-y += cpu_info.c
romstage-y += pwm.c # needed by timer.c romstage-y += pwm.c # needed by timer.c
romstage-y += s5p_gpio.c romstage-y += s5p_gpio.c

View File

@ -42,112 +42,6 @@
#define EXYNOS5_CLOCK_BASE 0x10010000 #define EXYNOS5_CLOCK_BASE 0x10010000
void clock_ll_set_pre_ratio(enum periph_id periph_id, unsigned divisor)
{
struct exynos5_clock *clk =
(struct exynos5_clock *)EXYNOS5_CLOCK_BASE;
unsigned shift;
unsigned mask = 0xff;
u32 *reg;
reg = &clk->div_peric1;
shift = 24;
clrsetbits_le32(reg, mask << shift, (divisor & mask) << shift);
}
void clock_ll_set_ratio(enum periph_id periph_id, unsigned divisor)
{
struct exynos5_clock *clk =
(struct exynos5_clock *)EXYNOS5_CLOCK_BASE;
unsigned shift;
unsigned mask = 0xff;
u32 *reg;
reg = &clk->div_peric1;
shift = 16;
clrsetbits_le32(reg, mask << shift, (divisor & mask) << shift);
}
/**
* Linearly searches for the most accurate main and fine stage clock scalars
* (divisors) for a specified target frequency and scalar bit sizes by checking
* all multiples of main_scalar_bits values. Will always return scalars up to or
* slower than target.
*
* @param main_scalar_bits Number of main scalar bits, must be > 0 and < 32
* @param fine_scalar_bits Number of fine scalar bits, must be > 0 and < 32
* @param input_freq Clock frequency to be scaled in Hz
* @param target_freq Desired clock frequency in Hz
* @param best_fine_scalar Pointer to store the fine stage divisor
*
* @return best_main_scalar Main scalar for desired frequency or -1 if none
* found
*/
static int clock_calc_best_scalar(unsigned int main_scaler_bits,
unsigned int fine_scalar_bits, unsigned int input_rate,
unsigned int target_rate, unsigned int *best_fine_scalar)
{
int i;
int best_main_scalar = -1;
unsigned int best_error = target_rate;
const unsigned int cap = (1 << fine_scalar_bits) - 1;
const unsigned int loops = 1 << main_scaler_bits;
#if 0
debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate,
target_rate, cap);
assert(best_fine_scalar != NULL);
assert(main_scaler_bits <= fine_scalar_bits);
#endif
*best_fine_scalar = 1;
if (input_rate == 0 || target_rate == 0)
return -1;
if (target_rate >= input_rate)
return 1;
for (i = 1; i <= loops; i++) {
const unsigned int effective_div = MAX(MIN(input_rate / i /
target_rate, cap), 1);
const unsigned int effective_rate = input_rate / i /
effective_div;
const int error = target_rate - effective_rate;
#if 0
debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div,
effective_rate, error);
#endif
if (error >= 0 && error <= best_error) {
best_error = error;
best_main_scalar = i;
*best_fine_scalar = effective_div;
}
}
return best_main_scalar;
}
int clock_set_rate(enum periph_id periph_id, unsigned int rate)
{
int main;
unsigned int fine;
main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
if (main < 0) {
// debug("%s: Cannot set clock rate for periph %d",
// __func__, periph_id);
return -1;
}
clock_ll_set_ratio(-1, main - 1);
clock_ll_set_pre_ratio(-1, fine - 1);
return 0;
}
struct gpio_info { struct gpio_info {
unsigned int reg_addr; /* Address of register for this part */ unsigned int reg_addr; /* Address of register for this part */
unsigned int max_gpio; /* Maximum GPIO in this part */ unsigned int max_gpio; /* Maximum GPIO in this part */
@ -234,163 +128,6 @@ static uint32_t uart3_base = CONFIG_CONSOLE_SERIAL_UART_ADDRESS;
#define CONFIG_SYS_CLK_FREQ 24000000 #define CONFIG_SYS_CLK_FREQ 24000000
/* exynos5: return pll clock frequency */
unsigned long get_pll_clk(int pllreg);
unsigned long get_pll_clk(int pllreg)
{
struct exynos5_clock *clk =
(struct exynos5_clock *)EXYNOS5_CLOCK_BASE;
unsigned long r, m, p, s, k = 0, mask, fout;
unsigned int freq;
switch (pllreg) {
case APLL:
r = readl(&clk->apll_con0);
break;
case BPLL:
r = readl(&clk->bpll_con0);
break;
case MPLL:
r = readl(&clk->mpll_con0);
break;
case EPLL:
r = readl(&clk->epll_con0);
k = readl(&clk->epll_con1);
break;
case VPLL:
r = readl(&clk->vpll_con0);
k = readl(&clk->vpll_con1);
break;
default:
// printk(BIOS_DEBUG, "Unsupported PLL (%d)\n", pllreg);
return 0;
}
/*
* APLL_CON: MIDV [25:16]
* MPLL_CON: MIDV [25:16]
* EPLL_CON: MIDV [24:16]
* VPLL_CON: MIDV [24:16]
*/
if (pllreg == APLL || pllreg == BPLL || pllreg == MPLL)
mask = 0x3ff;
else
mask = 0x1ff;
m = (r >> 16) & mask;
/* PDIV [13:8] */
p = (r >> 8) & 0x3f;
/* SDIV [2:0] */
s = r & 0x7;
freq = CONFIG_SYS_CLK_FREQ;
if (pllreg == EPLL) {
k = k & 0xffff;
/* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */
fout = (m + k / 65536) * (freq / (p * (1 << s)));
} else if (pllreg == VPLL) {
k = k & 0xfff;
/* FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV) */
fout = (m + k / 1024) * (freq / (p * (1 << s)));
} else {
/* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
fout = m * (freq / (p * (1 << s)));
}
return fout;
}
/* src_bit div_bit prediv_bit */
static struct clk_bit_info clk_bit_info[PERIPH_ID_COUNT] = {
{0, 4, 0, -1},
{4, 4, 4, -1},
{8, 4, 8, -1},
{12, 4, 12, -1},
{0, 4, 0, 8},
{4, 4, 16, 24},
{8, 4, 0, 8},
{12, 4, 16, 24},
{-1, -1, -1, -1},
{16, 4, 0, 8}, /* PERIPH_ID_SROMC */
{20, 4, 16, 24},
{24, 4, 0, 8},
{0, 4, 0, 4},
{4, 4, 12, 16},
{-1, 4, -1, -1},
{-1, 4, -1, -1},
{-1, 4, 24, 0},
{-1, 4, 24, 0},
{-1, 4, 24, 0},
{-1, 4, 24, 0},
{-1, 4, 24, 0},
{-1, 4, 24, 0},
{-1, 4, 24, 0},
{-1, 4, 24, 0},
{24, 4, 0, -1},
{24, 4, 0, -1},
{24, 4, 0, -1},
{24, 4, 0, -1},
{24, 4, 0, -1},
{-1, -1, -1, -1},
{-1, -1, -1, -1},
{-1, -1, -1, -1}, /* PERIPH_ID_I2S1 */
{24, 1, 20, -1}, /* PERIPH_ID_SATA */
};
static unsigned long my_clock_get_periph_rate(enum periph_id peripheral)
{
// struct exynos5_clock *clk =
// (struct exynos5_clock *)samsung_get_base_clock();
struct exynos5_clock *clk =
(struct exynos5_clock *)EXYNOS5_CLOCK_BASE;
struct clk_bit_info *bit_info = &clk_bit_info[peripheral];
// struct clk_bit_info bit_info = { 12, 4, 12, -1 };
unsigned long sclk, sub_clk;
unsigned int src, div, sub_div;
switch (peripheral) {
case PERIPH_ID_UART0:
case PERIPH_ID_UART1:
case PERIPH_ID_UART2:
case PERIPH_ID_UART3:
src = readl(&clk->src_peric0);
div = readl(&clk->div_peric0);
break;
case PERIPH_ID_I2C0:
case PERIPH_ID_I2C1:
case PERIPH_ID_I2C2:
case PERIPH_ID_I2C3:
case PERIPH_ID_I2C4:
case PERIPH_ID_I2C5:
case PERIPH_ID_I2C6:
case PERIPH_ID_I2C7:
src = 0;
sclk = get_pll_clk(MPLL);
sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit) & 0x7) + 1;
div = ((readl(&clk->div_top0) >> bit_info->prediv_bit) & 0x7) + 1;
return (sclk / sub_div) / div;
default:
return -1;
};
src = (src >> bit_info->src_bit) & ((1 << bit_info->n_src_bits) - 1);
if (src == SRC_MPLL)
sclk = get_pll_clk(MPLL);
else if (src == SRC_EPLL)
sclk = get_pll_clk(EPLL);
else if (src == SRC_VPLL)
sclk = get_pll_clk(VPLL);
else
return 0;
sub_div = (div >> bit_info->div_bit) & 0xf;
sub_clk = sclk / (sub_div + 1);
return sub_clk;
}
static void serial_setbrg_dev(void) static void serial_setbrg_dev(void)
{ {
// struct s5p_uart *const uart = s5p_get_base_uart(dev_index); // struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
@ -401,7 +138,7 @@ static void serial_setbrg_dev(void)
// enum periph_id periph; // enum periph_id periph;
// periph = exynos5_get_periph_id(base_port); // periph = exynos5_get_periph_id(base_port);
uclk = my_clock_get_periph_rate(PERIPH_ID_UART3); uclk = clock_get_periph_rate(PERIPH_ID_UART3);
val = uclk / baudrate; val = uclk / baudrate;
writel(val / 16 - 1, &uart->ubrdiv); writel(val / 16 - 1, &uart->ubrdiv);
@ -569,7 +306,7 @@ static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd)
{ {
unsigned long freq, pres = 16, div; unsigned long freq, pres = 16, div;
freq = my_clock_get_periph_rate(PERIPH_ID_I2C0); freq = clock_get_periph_rate(PERIPH_ID_I2C0);
/* calculate prescaler and divisor values */ /* calculate prescaler and divisor values */
if ((freq / pres / (16 + 1)) > speed) if ((freq / pres / (16 + 1)) > speed)
/* set prescaler to 512 */ /* set prescaler to 512 */
@ -1222,7 +959,8 @@ static void power_init(void)
REG_ENABLE, MAX77686_MV); REG_ENABLE, MAX77686_MV);
} }
struct mem_timings mem_timings[] = { /* FIXME(dhendrix): this will be removed in a follow-up patch */
struct mem_timings my_mem_timings[] = {
{ {
.mem_manuf = MEM_MANUF_ELPIDA, .mem_manuf = MEM_MANUF_ELPIDA,
.mem_type = DDR_MODE_DDR3, .mem_type = DDR_MODE_DDR3,
@ -1330,7 +1068,8 @@ struct mem_timings mem_timings[] = {
}, },
}; };
struct arm_clk_ratios arm_clk_ratios[] = { /* FIXME(dhendrix): this will be removed in a follow-up patch */
struct arm_clk_ratios my_arm_clk_ratios[] = {
{ {
.arm_freq_mhz = 1700, .arm_freq_mhz = 1700,
@ -1354,8 +1093,8 @@ static void clock_init(void)
struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE; struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE;
struct exynos5_mct_regs *mct_regs = struct exynos5_mct_regs *mct_regs =
(struct exynos5_mct_regs *)EXYNOS5_MULTI_CORE_TIMER_BASE; (struct exynos5_mct_regs *)EXYNOS5_MULTI_CORE_TIMER_BASE;
struct mem_timings *mem = &mem_timings[0]; struct mem_timings *mem = &my_mem_timings[0];
struct arm_clk_ratios *arm_clk_ratio = &arm_clk_ratios[0]; struct arm_clk_ratios *arm_clk_ratio = &my_arm_clk_ratios[0];
u32 val, tmp; u32 val, tmp;
/* Turn on the MCT as early as possible. */ /* Turn on the MCT as early as possible. */