[U-Boot] [v2 PATCH 10/12] arm, spl, at91: add at91sam9260 and at91sam9g45 spl support

Bo Shen
2014-10-31T01:50:12Z

Hi Heiko,

On 10/30/2014 04:15 PM, Heiko Schocher wrote:
> diff --git a/arch/arm/cpu/at91-common/spl.c b/arch/arm/cpu/at91-common/spl.c
> index 674a470..5c9a3ad 100644
> --- a/arch/arm/cpu/at91-common/spl.c
> +++ b/arch/arm/cpu/at91-common/spl.c

I am thinking, whether it be better to keep this file as two copy? This
will remove #ifdef, although a little code duplication.

If this solution acceptable, some suggestion as following:
- for armv5 (arm926ejs, now at91 series), named it spl_at91.c,
- for armv7 (cortex-a5, now, sama5d3), named it spl_atmel.c?
(As for arm9 series, we have at91 prefix for SoC name, and for armv7
SoC, we don't have at91 prefix, and it now changed to Atmel Smart)

> @@ -8,11 +8,18 @@
> #include <common.h>
> #include <asm/io.h>
> #include <asm/arch/at91_common.h>
> +#if !defined(CONFIG_SAMA5D3)
> +#include <asm/arch/at91sam9_matrix.h>
> +#endif
> +#include <asm/arch/at91_pit.h>
> #include <asm/arch/at91_pmc.h>
> +#include <asm/arch/at91_rstc.h>
> #include <asm/arch/at91_wdt.h>
> #include <asm/arch/clk.h>
> #include <spl.h>
>
> +DECLARE_GLOBAL_DATA_PTR;
> +
> static void at91_disable_wdt(void)
> {
> struct at91_wdt *wdt = (struct at91_wdt *)ATMEL_BASE_WDT;
> @@ -20,6 +27,33 @@ static void at91_disable_wdt(void)
> writel(AT91_WDT_MR_WDDIS, &wdt->mr);
> }
>
> +u32 spl_boot_device(void)
> +{
> +#ifdef CONFIG_SYS_USE_MMC
> + return BOOT_DEVICE_MMC1;
> +#elif CONFIG_SYS_USE_NANDFLASH
> + return BOOT_DEVICE_NAND;
> +#elif CONFIG_SYS_USE_SERIALFLASH
> + return BOOT_DEVICE_SPI;
> +#endif
> + return BOOT_DEVICE_NONE;
> +}
> +
> +u32 spl_boot_mode(void)
> +{
> + switch (spl_boot_device()) {
> +#ifdef CONFIG_SYS_USE_MMC
> + case BOOT_DEVICE_MMC1:
> + return MMCSD_MODE_FS;
> + break;
> +#endif
> + case BOOT_DEVICE_NONE:
> + default:
> + hang();
> + }
> +}
> +
> +#if defined(CONFIG_SAMA5D3)
> static void switch_to_main_crystal_osc(void)
> {
> struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
> @@ -57,77 +91,134 @@ static void switch_to_main_crystal_osc(void)
> writel(tmp, &pmc->mor);
> }
>
> -void at91_plla_init(u32 pllar)
> +void s_init(void)
> {
> - struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
> + switch_to_main_crystal_osc();
>
> - writel(pllar, &pmc->pllar);
> - while (!(readl(&pmc->sr) & (AT91_PMC_LOCKA | AT91_PMC_MCKRDY)))
> - ;
> -}
> + /* disable watchdog */
> + at91_disable_wdt();
>
> -void at91_mck_init(u32 mckr)
> -{
> - struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
> - u32 tmp;
> + /* PMC configuration */
> + at91_pmc_init();
>
> - tmp = readl(&pmc->mckr);
> - tmp &= ~(AT91_PMC_MCKR_PRES_MASK |
> - AT91_PMC_MCKR_MDIV_MASK |
> - AT91_PMC_MCKR_PLLADIV_2);
> - tmp |= mckr & (AT91_PMC_MCKR_PRES_MASK |
> - AT91_PMC_MCKR_MDIV_MASK |
> - AT91_PMC_MCKR_PLLADIV_2);
> - writel(tmp, &pmc->mckr);
> + at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK);
>
> - while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY))
> - ;
> -}
> + timer_init();
>
> + board_early_init_f();
>
> -u32 spl_boot_device(void)
> + preloader_console_init();
> +
> + mem_init();
> +}
> +#else
> +static void enable_ext_reset(void)
> {
> -#ifdef CONFIG_SYS_USE_MMC
> - return BOOT_DEVICE_MMC1;
> -#elif CONFIG_SYS_USE_NANDFLASH
> - return BOOT_DEVICE_NAND;
> -#elif CONFIG_SYS_USE_SERIALFLASH
> - return BOOT_DEVICE_SPI;
> -#endif
> - return BOOT_DEVICE_NONE;
> + struct at91_rstc *rstc = (struct at91_rstc *)ATMEL_BASE_RSTC;
> +
> + writel(AT91_RSTC_KEY | AT91_RSTC_MR_URSTEN, &rstc->mr);
> }
>
> -u32 spl_boot_mode(void)
> +#if defined(CONFIG_ATMEL_MATRIX_INIT)
> +static void matrix_init(void)
> {
> - switch (spl_boot_device()) {
> -#ifdef CONFIG_SYS_USE_MMC
> - case BOOT_DEVICE_MMC1:
> - return MMCSD_MODE_FS;
> - break;
> + struct at91_matrix *mat = (struct at91_matrix *)ATMEL_BASE_MATRIX;
> +
> + writel((readl(&mat->scfg[3]) & (~AT91_MATRIX_SLOT_CYCLE))
> + | AT91_MATRIX_SLOT_CYCLE_(0x40),
> + &mat->scfg[3]);
> +}
> #endif
> - case BOOT_DEVICE_NONE:
> - default:
> - hang();
> +
> +void lowlevel_clock_init(void)
> +{
> + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
> +
> + if (!(readl(&pmc->sr) & AT91_PMC_MOSCS)) {
> + /* Enable Main Oscillator */
> + writel(AT91_PMC_MOSCS | (0x40 << 8), &pmc->mor);
> +
> + /* Wait until Main Oscillator is stable */
> + while (!(readl(&pmc->sr) & AT91_PMC_MOSCS))
> + ;
> }
> +
> + /* After stabilization, switch to Main Oscillator */
> + if ((readl(&pmc->mckr) & AT91_PMC_CSS) == AT91_PMC_CSS_SLOW) {
> + unsigned long tmp;
> +
> + tmp = readl(&pmc->mckr);
> + tmp &= ~AT91_PMC_CSS;
> + tmp |= AT91_PMC_CSS_MAIN;
> + writel(tmp, &pmc->mckr);
> + while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY))
> + ;
> +
> + tmp &= ~AT91_PMC_PRES;
> + tmp |= AT91_PMC_PRES_1;
> + writel(tmp, &pmc->mckr);
> + while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY))
> + ;
> + }
> +
> + return;
> }
>
> -void s_init(void)
> +void __weak at91_spl_board_init(void)
> {
> - switch_to_main_crystal_osc();
> +}
>
> - /* disable watchdog */
> +void spl_board_init(void)
> +{
> + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
> +
> + lowlevel_clock_init();
> at91_disable_wdt();
>
> - /* PMC configuration */
> - at91_pmc_init();
> + /*
> + * At this stage the main oscillator is supposed to be enabled
> + * PCK = MCK = MOSC
> + */
> + writel(0x00, &pmc->pllicpr);
>
> - at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK);
> + /* Configure PLLA = MOSC * (PLL_MULA + 1) / PLL_DIVA */
> + at91_plla_init(CONFIG_SYS_AT91_PLLA);
>
> - timer_init();
> + /* PCK = PLLA = 2 * MCK */
> + at91_mck_init(CONFIG_SYS_MCKR);
>
> - board_early_init_f();
> + /* Switch MCK on PLLA output */
> + at91_mck_init(CONFIG_SYS_MCKR_CSS);
> +
> +#if defined(CONFIG_SYS_AT91_PLLB)
> + /* Configure PLLB */
> + at91_pllb_init(CONFIG_SYS_AT91_PLLB);
> +#endif
> +
> + /* Enable External Reset */
> + enable_ext_reset();
>
> +#if defined(CONFIG_ATMEL_MATRIX_INIT)
> + /* Initialize matrix */
> + matrix_init();
> +#endif

Can this also be weak function? And put matrix_init() code to SoC/board
related file.

> + gd->arch.mck_rate_hz = CONFIG_SYS_MASTER_CLOCK;
> + /*
> + * init timer long enough for using in spl.
> + */
> + timer_init();
> +
> + /* enable clocks for all PIOs */
> + at91_periph_clk_enable(ATMEL_ID_PIOA);
> + at91_periph_clk_enable(ATMEL_ID_PIOB);
> + at91_periph_clk_enable(ATMEL_ID_PIOC);
> + /* init console */
> + at91_seriald_hw_init();
> preloader_console_init();
>
> mem_init();
> +
> + at91_spl_board_init();
> }
> +#endif

Best Regards,
Bo Shen