diff options
author | Heiko Schocher <hs@denx.de> | 2014-10-31 08:31:04 +0100 |
---|---|---|
committer | Tom Rini <trini@ti.com> | 2014-11-17 08:47:17 -0500 |
commit | 5abc00d02082056765a8029675e7b05ab6c35263 (patch) | |
tree | 381ca30258c8bcc82372e99ba2f903b9a74492c7 /arch/arm/cpu/at91-common | |
parent | 667af36905157b65fd79493e7f821db606ebbd33 (diff) | |
download | u-boot-imx-5abc00d02082056765a8029675e7b05ab6c35263.zip u-boot-imx-5abc00d02082056765a8029675e7b05ab6c35263.tar.gz u-boot-imx-5abc00d02082056765a8029675e7b05ab6c35263.tar.bz2 |
arm, spl, at91: add at91sam9260 and at91sam9g45 spl support
add support for using spl code on at91sam9260 and at91sam9g45
based boards.
Signed-off-by: Heiko Schocher <hs@denx.de>
Reviewed-by: Bo Shen <voice.shen@atmel.com>
Reviewed-by: Andreas Bießmann <andreas.devel@googlemail.com>
[adopt Bo's change in spl.c]
Signed-off-by: Andreas Bießmann <andreas.devel@googlemail.com>
Diffstat (limited to 'arch/arm/cpu/at91-common')
-rw-r--r-- | arch/arm/cpu/at91-common/Makefile | 5 | ||||
-rw-r--r-- | arch/arm/cpu/at91-common/sdram.c | 77 | ||||
-rw-r--r-- | arch/arm/cpu/at91-common/spl.c | 95 | ||||
-rw-r--r-- | arch/arm/cpu/at91-common/spl_at91.c | 124 | ||||
-rw-r--r-- | arch/arm/cpu/at91-common/spl_atmel.c | 80 |
5 files changed, 285 insertions, 96 deletions
diff --git a/arch/arm/cpu/at91-common/Makefile b/arch/arm/cpu/at91-common/Makefile index f62863a..89e1577 100644 --- a/arch/arm/cpu/at91-common/Makefile +++ b/arch/arm/cpu/at91-common/Makefile @@ -10,7 +10,8 @@ obj-$(CONFIG_AT91_WANTS_COMMON_PHY) += phy.o ifneq ($(CONFIG_SPL_BUILD),) -obj-$(CONFIG_AT91SAM9M10G45) += mpddrc.o -obj-$(CONFIG_SAMA5D3) += mpddrc.o +obj-$(CONFIG_AT91SAM9G20) += sdram.o spl_at91.o +obj-$(CONFIG_AT91SAM9M10G45) += mpddrc.o spl_at91.o +obj-$(CONFIG_SAMA5D3) += mpddrc.o spl_atmel.o obj-y += spl.o endif diff --git a/arch/arm/cpu/at91-common/sdram.c b/arch/arm/cpu/at91-common/sdram.c new file mode 100644 index 0000000..5758b06 --- /dev/null +++ b/arch/arm/cpu/at91-common/sdram.c @@ -0,0 +1,77 @@ +/* + * (C) Copyright 2014 + * Heiko Schocher, DENX Software Engineering, hs@denx.de. + * + * Based on: + * (C) Copyright 2007-2008 + * Stelian Pop <stelian@popies.net> + * Lead Tech Design <www.leadtechdesign.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/at91_common.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/at91sam9_sdramc.h> +#include <asm/arch/gpio.h> + +int sdramc_initialize(unsigned int sdram_address, const struct sdramc_reg *p) +{ + struct sdramc_reg *reg = (struct sdramc_reg *)ATMEL_BASE_SDRAMC; + unsigned int i; + + /* SDRAM feature must be in the configuration register */ + writel(p->cr, ®->cr); + + /* The SDRAM memory type must be set in the Memory Device Register */ + writel(p->mdr, ®->mdr); + + /* + * The minimum pause of 200 us is provided to precede any single + * toggle + */ + for (i = 0; i < 1000; i++) + ; + + /* A NOP command is issued to the SDRAM devices */ + writel(AT91_SDRAMC_MODE_NOP, ®->mr); + writel(0x00000000, sdram_address); + + /* An All Banks Precharge command is issued to the SDRAM devices */ + writel(AT91_SDRAMC_MODE_PRECHARGE, ®->mr); + writel(0x00000000, sdram_address); + + for (i = 0; i < 10000; i++) + ; + + /* Eight auto-refresh cycles are provided */ + for (i = 0; i < 8; i++) { + writel(AT91_SDRAMC_MODE_REFRESH, ®->mr); + writel(0x00000001 + i, sdram_address + 4 + 4 * i); + } + + /* + * A Mode Register set (MRS) cyscle is issued to program the + * SDRAM parameters(TCSR, PASR, DS) + */ + writel(AT91_SDRAMC_MODE_LMR, ®->mr); + writel(0xcafedede, sdram_address + 0x24); + + /* + * The application must go into Normal Mode, setting Mode + * to 0 in the Mode Register and perform a write access at + * any location in the SDRAM. + */ + writel(AT91_SDRAMC_MODE_NORMAL, ®->mr); + writel(0x00000000, sdram_address); /* Perform Normal mode */ + + /* + * Write the refresh rate into the count field in the SDRAMC + * Refresh Timer Rgister. + */ + writel(p->tr, ®->tr); + + return 0; +} diff --git a/arch/arm/cpu/at91-common/spl.c b/arch/arm/cpu/at91-common/spl.c index 81f5f53..6473320 100644 --- a/arch/arm/cpu/at91-common/spl.c +++ b/arch/arm/cpu/at91-common/spl.c @@ -8,89 +8,17 @@ #include <common.h> #include <asm/io.h> #include <asm/arch/at91_common.h> -#include <asm/arch/at91_pmc.h> #include <asm/arch/at91_wdt.h> #include <asm/arch/clk.h> #include <spl.h> -static void at91_disable_wdt(void) +void at91_disable_wdt(void) { struct at91_wdt *wdt = (struct at91_wdt *)ATMEL_BASE_WDT; writel(AT91_WDT_MR_WDDIS, &wdt->mr); } -static void switch_to_main_crystal_osc(void) -{ - struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; - u32 tmp; - - tmp = readl(&pmc->mor); - tmp &= ~AT91_PMC_MOR_OSCOUNT(0xff); - tmp &= ~AT91_PMC_MOR_KEY(0xff); - tmp |= AT91_PMC_MOR_MOSCEN; - tmp |= AT91_PMC_MOR_OSCOUNT(8); - tmp |= AT91_PMC_MOR_KEY(0x37); - writel(tmp, &pmc->mor); - while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCS)) - ; - - tmp = readl(&pmc->mor); - tmp &= ~AT91_PMC_MOR_OSCBYPASS; - tmp &= ~AT91_PMC_MOR_KEY(0xff); - tmp |= AT91_PMC_MOR_KEY(0x37); - writel(tmp, &pmc->mor); - - tmp = readl(&pmc->mor); - tmp |= AT91_PMC_MOR_MOSCSEL; - tmp &= ~AT91_PMC_MOR_KEY(0xff); - tmp |= AT91_PMC_MOR_KEY(0x37); - writel(tmp, &pmc->mor); - - while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCSELS)) - ; - - /* Wait until MAINRDY field is set to make sure main clock is stable */ - while (!(readl(&pmc->mcfr) & AT91_PMC_MAINRDY)) - ; - - tmp = readl(&pmc->mor); - tmp &= ~AT91_PMC_MOR_MOSCRCEN; - tmp &= ~AT91_PMC_MOR_KEY(0xff); - tmp |= AT91_PMC_MOR_KEY(0x37); - writel(tmp, &pmc->mor); -} - -void at91_plla_init(u32 pllar) -{ - struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; - - writel(pllar, &pmc->pllar); - while (!(readl(&pmc->sr) & (AT91_PMC_LOCKA | AT91_PMC_MCKRDY))) - ; -} - -void at91_mck_init(u32 mckr) -{ - struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; - u32 tmp; - - tmp = readl(&pmc->mckr); - tmp &= ~(AT91_PMC_MCKR_CSS_MASK | - AT91_PMC_MCKR_PRES_MASK | - AT91_PMC_MCKR_MDIV_MASK | - AT91_PMC_MCKR_PLLADIV_2); - tmp |= mckr & (AT91_PMC_MCKR_CSS_MASK | - AT91_PMC_MCKR_PRES_MASK | - AT91_PMC_MCKR_MDIV_MASK | - AT91_PMC_MCKR_PLLADIV_2); - writel(tmp, &pmc->mckr); - - while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY)) - ; -} - - u32 spl_boot_device(void) { #ifdef CONFIG_SYS_USE_MMC @@ -116,24 +44,3 @@ u32 spl_boot_mode(void) hang(); } } - -void s_init(void) -{ - switch_to_main_crystal_osc(); - - /* disable watchdog */ - at91_disable_wdt(); - - /* PMC configuration */ - at91_pmc_init(); - - at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK); - - timer_init(); - - board_early_init_f(); - - preloader_console_init(); - - mem_init(); -} diff --git a/arch/arm/cpu/at91-common/spl_at91.c b/arch/arm/cpu/at91-common/spl_at91.c new file mode 100644 index 0000000..89f588b --- /dev/null +++ b/arch/arm/cpu/at91-common/spl_at91.c @@ -0,0 +1,124 @@ +/* + * (C) Copyright 2014 DENX Software Engineering + * Heiko Schocher <hs@denx.de> + * + * Based on: + * Copyright (C) 2013 Atmel Corporation + * Bo Shen <voice.shen@atmel.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/at91_common.h> +#include <asm/arch/at91sam9_matrix.h> +#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 enable_ext_reset(void) +{ + struct at91_rstc *rstc = (struct at91_rstc *)ATMEL_BASE_RSTC; + + writel(AT91_RSTC_KEY | AT91_RSTC_MR_URSTEN, &rstc->mr); +} + +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 __weak matrix_init(void) +{ +} + +void __weak at91_spl_board_init(void) +{ +} + +void spl_board_init(void) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + + lowlevel_clock_init(); + at91_disable_wdt(); + + /* + * At this stage the main oscillator is supposed to be enabled + * PCK = MCK = MOSC + */ + writel(0x00, &pmc->pllicpr); + + /* Configure PLLA = MOSC * (PLL_MULA + 1) / PLL_DIVA */ + at91_plla_init(CONFIG_SYS_AT91_PLLA); + + /* PCK = PLLA = 2 * MCK */ + at91_mck_init(CONFIG_SYS_MCKR); + + /* 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(); + + /* Initialize matrix */ + matrix_init(); + + 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(); +} diff --git a/arch/arm/cpu/at91-common/spl_atmel.c b/arch/arm/cpu/at91-common/spl_atmel.c new file mode 100644 index 0000000..7297530 --- /dev/null +++ b/arch/arm/cpu/at91-common/spl_atmel.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2013 Atmel Corporation + * Bo Shen <voice.shen@atmel.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/at91_common.h> +#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 switch_to_main_crystal_osc(void) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + u32 tmp; + + tmp = readl(&pmc->mor); + tmp &= ~AT91_PMC_MOR_OSCOUNT(0xff); + tmp &= ~AT91_PMC_MOR_KEY(0xff); + tmp |= AT91_PMC_MOR_MOSCEN; + tmp |= AT91_PMC_MOR_OSCOUNT(8); + tmp |= AT91_PMC_MOR_KEY(0x37); + writel(tmp, &pmc->mor); + while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCS)) + ; + + tmp = readl(&pmc->mor); + tmp &= ~AT91_PMC_MOR_OSCBYPASS; + tmp &= ~AT91_PMC_MOR_KEY(0xff); + tmp |= AT91_PMC_MOR_KEY(0x37); + writel(tmp, &pmc->mor); + + tmp = readl(&pmc->mor); + tmp |= AT91_PMC_MOR_MOSCSEL; + tmp &= ~AT91_PMC_MOR_KEY(0xff); + tmp |= AT91_PMC_MOR_KEY(0x37); + writel(tmp, &pmc->mor); + + while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCSELS)) + ; + + /* Wait until MAINRDY field is set to make sure main clock is stable */ + while (!(readl(&pmc->mcfr) & AT91_PMC_MAINRDY)) + ; + + tmp = readl(&pmc->mor); + tmp &= ~AT91_PMC_MOR_MOSCRCEN; + tmp &= ~AT91_PMC_MOR_KEY(0xff); + tmp |= AT91_PMC_MOR_KEY(0x37); + writel(tmp, &pmc->mor); +} + +void s_init(void) +{ + switch_to_main_crystal_osc(); + + /* disable watchdog */ + at91_disable_wdt(); + + /* PMC configuration */ + at91_pmc_init(); + + at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK); + + timer_init(); + + board_early_init_f(); + + preloader_console_init(); + + mem_init(); +} |