diff --git a/src/arch/armv7/lib/Makefile.inc b/src/arch/armv7/lib/Makefile.inc index 2470db2e80..e0445ceea2 100644 --- a/src/arch/armv7/lib/Makefile.inc +++ b/src/arch/armv7/lib/Makefile.inc @@ -1,3 +1,5 @@ +bootblock-y += syslib.c + romstage-y += cache_v7.c romstage-y += cache-cp15.c romstage-y += div0.c diff --git a/src/cpu/samsung/exynos5250/Kconfig b/src/cpu/samsung/exynos5250/Kconfig index 41a1446ef2..ec1d7af558 100644 --- a/src/cpu/samsung/exynos5250/Kconfig +++ b/src/cpu/samsung/exynos5250/Kconfig @@ -18,7 +18,7 @@ config SATA_AHCI # # 0x0202_0000: vendor-provided BL1 # 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. # 0x0203_0000: romstage, assume up to 128KB in size. # 0x0207_7f00: stack pointer @@ -38,7 +38,7 @@ config BOOTBLOCK_BASE config ID_SECTION_BASE hex - default 0x02026000 + default 0x02027000 config ROMSTAGE_BASE hex diff --git a/src/cpu/samsung/exynos5250/Makefile.inc b/src/cpu/samsung/exynos5250/Makefile.inc index 6eee50328f..db28221179 100644 --- a/src/cpu/samsung/exynos5250/Makefile.inc +++ b/src/cpu/samsung/exynos5250/Makefile.inc @@ -3,6 +3,12 @@ # image outside of CBFS #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_init.c romstage-y += exynos_cache.c diff --git a/src/cpu/samsung/exynos5250/clock_init.c b/src/cpu/samsung/exynos5250/clock_init.c index 421d880fa7..53bab1a53a 100644 --- a/src/cpu/samsung/exynos5250/clock_init.c +++ b/src/cpu/samsung/exynos5250/clock_init.c @@ -597,6 +597,38 @@ static int autodetect_memory(void) #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). * @@ -608,7 +640,7 @@ int clock_get_mem_selection(enum ddr_mode *mem_type, { struct spl_machine_param *params; - params = spl_get_machine_params(); + params = &machine_param; *mem_type = params->mem_type; *frequency_mhz = params->frequency_mhz; *arm_freq = params->arm_freq_mhz; @@ -719,7 +751,7 @@ struct arm_clk_ratios *get_arm_ratios(void) return arm_ratio; } - die("get_arm_ratios: Failed to find ratio\n"); +// die("get_arm_ratios: Failed to find ratio\n"); return NULL; } diff --git a/src/cpu/samsung/s5p-common/Makefile.inc b/src/cpu/samsung/s5p-common/Makefile.inc index 7de3c285d2..df67573b84 100644 --- a/src/cpu/samsung/s5p-common/Makefile.inc +++ b/src/cpu/samsung/s5p-common/Makefile.inc @@ -1,3 +1,6 @@ +bootblock-y += pwm.c +bootblock-y += timer.c + romstage-y += cpu_info.c romstage-y += pwm.c # needed by timer.c romstage-y += s5p_gpio.c diff --git a/src/mainboard/google/snow/bootblock.c b/src/mainboard/google/snow/bootblock.c index 7609410c3a..fd3c505b1e 100644 --- a/src/mainboard/google/snow/bootblock.c +++ b/src/mainboard/google/snow/bootblock.c @@ -42,112 +42,6 @@ #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 { unsigned int reg_addr; /* Address of register for 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 -/* 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) { // 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; // 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; 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; - freq = my_clock_get_periph_rate(PERIPH_ID_I2C0); + freq = clock_get_periph_rate(PERIPH_ID_I2C0); /* calculate prescaler and divisor values */ if ((freq / pres / (16 + 1)) > speed) /* set prescaler to 512 */ @@ -1222,7 +959,8 @@ static void power_init(void) 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_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, @@ -1354,8 +1093,8 @@ static void clock_init(void) struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE; struct exynos5_mct_regs *mct_regs = (struct exynos5_mct_regs *)EXYNOS5_MULTI_CORE_TIMER_BASE; - struct mem_timings *mem = &mem_timings[0]; - struct arm_clk_ratios *arm_clk_ratio = &arm_clk_ratios[0]; + struct mem_timings *mem = &my_mem_timings[0]; + struct arm_clk_ratios *arm_clk_ratio = &my_arm_clk_ratios[0]; u32 val, tmp; /* Turn on the MCT as early as possible. */