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>
This commit is contained in:
Heiko Schocher 2014-10-31 08:31:04 +01:00 committed by Tom Rini
parent 667af36905
commit 5abc00d020
13 changed files with 430 additions and 97 deletions

View File

@ -8,8 +8,10 @@
#include <common.h>
#include <asm/io.h>
#include <asm/arch/at91sam9260_matrix.h>
#include <asm/arch/at91_common.h>
#include <asm/arch/at91_pmc.h>
#include <asm/arch/at91sam9_sdramc.h>
#include <asm/arch/gpio.h>
/*
@ -207,3 +209,23 @@ void at91_mci_hw_init(void)
#endif
}
#endif
void at91_sdram_hw_init(void)
{
at91_set_a_periph(AT91_PIO_PORTC, 16, 0);
at91_set_a_periph(AT91_PIO_PORTC, 17, 0);
at91_set_a_periph(AT91_PIO_PORTC, 18, 0);
at91_set_a_periph(AT91_PIO_PORTC, 19, 0);
at91_set_a_periph(AT91_PIO_PORTC, 20, 0);
at91_set_a_periph(AT91_PIO_PORTC, 21, 0);
at91_set_a_periph(AT91_PIO_PORTC, 22, 0);
at91_set_a_periph(AT91_PIO_PORTC, 23, 0);
at91_set_a_periph(AT91_PIO_PORTC, 24, 0);
at91_set_a_periph(AT91_PIO_PORTC, 25, 0);
at91_set_a_periph(AT91_PIO_PORTC, 26, 0);
at91_set_a_periph(AT91_PIO_PORTC, 27, 0);
at91_set_a_periph(AT91_PIO_PORTC, 28, 0);
at91_set_a_periph(AT91_PIO_PORTC, 29, 0);
at91_set_a_periph(AT91_PIO_PORTC, 30, 0);
at91_set_a_periph(AT91_PIO_PORTC, 31, 0);
}

View File

@ -187,3 +187,63 @@ int at91_clock_init(unsigned long main_clock)
return 0;
}
#if !defined(AT91_PLL_LOCK_TIMEOUT)
#define AT91_PLL_LOCK_TIMEOUT 1000000
#endif
void at91_plla_init(u32 pllar)
{
struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
int timeout = AT91_PLL_LOCK_TIMEOUT;
writel(pllar, &pmc->pllar);
while (!(readl(&pmc->sr) & (AT91_PMC_LOCKA | AT91_PMC_MCKRDY))) {
timeout--;
if (timeout == 0)
break;
}
}
void at91_pllb_init(u32 pllbr)
{
struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
int timeout = AT91_PLL_LOCK_TIMEOUT;
writel(pllbr, &pmc->pllbr);
while (!(readl(&pmc->sr) & (AT91_PMC_LOCKB | AT91_PMC_MCKRDY))) {
timeout--;
if (timeout == 0)
break;
}
}
void at91_mck_init(u32 mckr)
{
struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
int timeout = AT91_PLL_LOCK_TIMEOUT;
u32 tmp;
tmp = readl(&pmc->mckr);
tmp &= ~(AT91_PMC_MCKR_PRES_MASK |
AT91_PMC_MCKR_MDIV_MASK |
AT91_PMC_MCKR_PLLADIV_MASK |
AT91_PMC_MCKR_CSS_MASK);
tmp |= mckr & (AT91_PMC_MCKR_PRES_MASK |
AT91_PMC_MCKR_MDIV_MASK |
AT91_PMC_MCKR_PLLADIV_MASK |
AT91_PMC_MCKR_CSS_MASK);
writel(tmp, &pmc->mckr);
while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY)) {
timeout--;
if (timeout == 0)
break;
}
}
void at91_periph_clk_enable(int id)
{
struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
writel(1 << id, &pmc->pcer);
}

View File

@ -111,6 +111,35 @@ int at91_clock_init(unsigned long main_clock)
return 0;
}
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))
;
}
void at91_periph_clk_enable(int id)
{
struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;

View File

@ -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

View File

@ -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, &reg->cr);
/* The SDRAM memory type must be set in the Memory Device Register */
writel(p->mdr, &reg->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, &reg->mr);
writel(0x00000000, sdram_address);
/* An All Banks Precharge command is issued to the SDRAM devices */
writel(AT91_SDRAMC_MODE_PRECHARGE, &reg->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, &reg->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, &reg->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, &reg->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, &reg->tr);
return 0;
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -23,9 +23,15 @@ void at91_udp_hw_init(void);
void at91_uhp_hw_init(void);
void at91_lcd_hw_init(void);
void at91_plla_init(u32 pllar);
void at91_pllb_init(u32 pllar);
void at91_mck_init(u32 mckr);
void at91_pmc_init(void);
void mem_init(void);
void at91_phy_reset(void);
void at91_sdram_hw_init(void);
void at91_mck_init(u32 mckr);
void at91_spl_board_init(void);
void at91_disable_wdt(void);
void matrix_init(void);
#endif /* AT91_COMMON_H */

View File

@ -133,6 +133,7 @@ typedef struct at91_pmc {
#define AT91_PMC_MCKR_MDIV_MASK 0x00000300
#endif
#define AT91_PMC_MCKR_PLLADIV_MASK 0x00003000
#define AT91_PMC_MCKR_PLLADIV_1 0x00000000
#define AT91_PMC_MCKR_PLLADIV_2 0x00001000

View File

@ -95,6 +95,7 @@
#define ATMEL_BASE_SDRAMC 0xffffea00
#define ATMEL_BASE_SMC 0xffffec00
#define ATMEL_BASE_MATRIX 0xffffee00
#define ATMEL_BASE_CCFG 0xffffef14
#define ATMEL_BASE_AIC 0xfffff000
#define ATMEL_BASE_DBGU 0xfffff200
#define ATMEL_BASE_PIOA 0xfffff400

View File

@ -61,5 +61,10 @@ struct at91_matrix {
#define AT91_MATRIX_DBPUC (1 << 8)
#define AT91_MATRIX_VDDIOMSEL_1_8V (0 << 16)
#define AT91_MATRIX_VDDIOMSEL_3_3V (1 << 16)
#define AT91_MATRIX_EBI_IOSR_SEL (1 << 17)
/* Maximum Number of Allowed Cycles for a Burst */
#define AT91_MATRIX_SLOT_CYCLE (0xff << 0)
#define AT91_MATRIX_SLOT_CYCLE_(x) (x << 0)
#endif

View File

@ -25,6 +25,21 @@
#define AT91_ASM_SDRAMC_CR (ATMEL_BASE_SDRAMC + 0x08)
#define AT91_ASM_SDRAMC_MDR (ATMEL_BASE_SDRAMC + 0x24)
#else
struct sdramc_reg {
u32 mr;
u32 tr;
u32 cr;
u32 lpr;
u32 ier;
u32 idr;
u32 imr;
u32 isr;
u32 mdr;
};
int sdramc_initialize(unsigned int sdram_address,
const struct sdramc_reg *p);
#endif
/* SDRAM Controller (SDRAMC) registers */
@ -62,11 +77,17 @@
#define AT91_SDRAMC_DBW_32 (0 << 7)
#define AT91_SDRAMC_DBW_16 (1 << 7)
#define AT91_SDRAMC_TWR (0xf << 8) /* Write Recovery Delay */
#define AT91_SDRAMC_TWR_VAL(x) (x << 8)
#define AT91_SDRAMC_TRC (0xf << 12) /* Row Cycle Delay */
#define AT91_SDRAMC_TRC_VAL(x) (x << 12)
#define AT91_SDRAMC_TRP (0xf << 16) /* Row Precharge Delay */
#define AT91_SDRAMC_TRP_VAL(x) (x << 16)
#define AT91_SDRAMC_TRCD (0xf << 20) /* Row to Column Delay */
#define AT91_SDRAMC_TRCD_VAL(x) (x << 20)
#define AT91_SDRAMC_TRAS (0xf << 24) /* Active to Precharge Delay */
#define AT91_SDRAMC_TRAS_VAL(x) (x << 24)
#define AT91_SDRAMC_TXSR (0xf << 28) /* Exit Self Refresh to Active Delay */
#define AT91_SDRAMC_TXSR_VAL(x) (x << 28)
#define AT91_SDRAMC_LPR (ATMEL_BASE_SDRAMC + 0x10) /* SDRAM Controller Low Power Register */
#define AT91_SDRAMC_LPCB (3 << 0) /* Low-power Configurations */
@ -93,5 +114,4 @@
#define AT91_SDRAMC_MD_SDRAM 0
#define AT91_SDRAMC_MD_LOW_POWER_SDRAM 1
#endif