[U-Boot-Users] [PATCH 26/26] Support AT91CAP9 revC CPUs

Stelian Pop
2008-05-08T20:52:34Z

The AT91CAP9 revC CPU has a few differences over the previous,
revB CPU which was distributed in small quantities only (revA was
an internal Atmel product only).

The revC silicon needs a special initialisation sequence to
switch from the internal (imprecise) RC oscillator to the
external 32k clock.

Signed-off-by: Stelian Pop <stelian@popies.net>
---
board/atmel/at91cap9adk/at91cap9adk.c | 28 ++++++++++++++++++++++++++++
include/asm-arm/arch-at91sam9/at91_pmc.h | 5 +++++
include/asm-arm/arch-at91sam9/at91cap9.h | 14 +++++++++++++-
3 files changed, 46 insertions(+), 1 deletions(-)

diff --git a/board/atmel/at91cap9adk/at91cap9adk.c b/board/atmel/at91cap9adk/at91cap9adk.c
index e353cea..a3eaf19 100644
--- a/board/atmel/at91cap9adk/at91cap9adk.c
+++ b/board/atmel/at91cap9adk/at91cap9adk.c
@@ -72,6 +72,33 @@ static void at91cap9_serial_hw_init(void)
#endif
}

+static void at91cap9_slowclock_hw_init(void)
+{
+ /*
+ * On AT91CAP9 revC CPUs, the slow clock can be based on an
+ * internal impreciseRC oscillator or an external 32kHz oscillator.
+ * Switch to the latter.
+ */
+#define ARCH_ID_AT91CAP9_REVB 0x399
+#define ARCH_ID_AT91CAP9_REVC 0x601
+ if (at91_sys_read(AT91_PMC_VER) == ARCH_ID_AT91CAP9_REVC) {
+ unsigned i, tmp = at91_sys_read(AT91_SCKCR);
+ if ((tmp & AT91CAP9_SCKCR_OSCSEL) == AT91CAP9_SCKCR_OSCSEL_RC) {
+ extern void timer_init(void);
+ timer_init();
+ tmp |= AT91CAP9_SCKCR_OSC32EN;
+ at91_sys_write(AT91_SCKCR, tmp);
+ for (i = 0; i < 1200; i++)
+ udelay(1000);
+ tmp |= AT91CAP9_SCKCR_OSCSEL_32;
+ at91_sys_write(AT91_SCKCR, tmp);
+ udelay(200);
+ tmp &= ~AT91CAP9_SCKCR_RCEN;
+ at91_sys_write(AT91_SCKCR, tmp);
+ }
+ }
+}
+
static void at91cap9_nor_hw_init(void)
{
unsigned long csa;
@@ -305,6 +332,7 @@ int board_init(void)
gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;

at91cap9_serial_hw_init();
+ at91cap9_slowclock_hw_init();
at91cap9_nor_hw_init();
#ifdef CONFIG_CMD_NAND
at91cap9_nand_hw_init();
diff --git a/include/asm-arm/arch-at91sam9/at91_pmc.h b/include/asm-arm/arch-at91sam9/at91_pmc.h
index 103be86..b57875d 100644
--- a/include/asm-arm/arch-at91sam9/at91_pmc.h
+++ b/include/asm-arm/arch-at91sam9/at91_pmc.h
@@ -96,4 +96,9 @@
#define AT91_PMC_PCK3RDY (1 << 11) /* Programmable Clock 3 */
#define AT91_PMC_IMR (AT91_PMC + 0x6c) /* Interrupt Mask Register */

+#define AT91_PMC_PROT (AT91_PMC + 0xe4) /* Protect Register [AT91CAP9 revC only] */
+#define AT91_PMC_PROTKEY 0x504d4301 /* Activation Code */
+
+#define AT91_PMC_VER (AT91_PMC + 0xfc) /* PMC Module Version [AT91CAP9 only] */
+
#endif
diff --git a/include/asm-arm/arch-at91sam9/at91cap9.h b/include/asm-arm/arch-at91sam9/at91cap9.h
index d1b33a0..0b52228 100644
--- a/include/asm-arm/arch-at91sam9/at91cap9.h
+++ b/include/asm-arm/arch-at91sam9/at91cap9.h
@@ -101,13 +101,25 @@
#define AT91_RTT (0xfffffd20 - AT91_BASE_SYS)
#define AT91_PIT (0xfffffd30 - AT91_BASE_SYS)
#define AT91_WDT (0xfffffd40 - AT91_BASE_SYS)
-#define AT91_GPBR (0xfffffd50 - AT91_BASE_SYS)
+#define AT91_SCKCR (0xfffffd50 - AT91_BASE_SYS)
+#define AT91_GPBR_REVB (0xfffffd50 - AT91_BASE_SYS)
+#define AT91_GPBR_REVC (0xfffffd60 - AT91_BASE_SYS)

#define AT91_USART0 AT91CAP9_BASE_US0
#define AT91_USART1 AT91CAP9_BASE_US1
#define AT91_USART2 AT91CAP9_BASE_US2

/*
+ * SCKCR flags
+ */
+#define AT91CAP9_SCKCR_RCEN (1 << 0) /* RC Oscillator Enable */
+#define AT91CAP9_SCKCR_OSC32EN (1 << 1) /* 32kHz Oscillator Enable */
+#define AT91CAP9_SCKCR_OSC32BYP (1 << 2) /* 32kHz Oscillator Bypass */
+#define AT91CAP9_SCKCR_OSCSEL (1 << 3) /* Slow Clock Selector */
+#define AT91CAP9_SCKCR_OSCSEL_RC (0 << 3)
+#define AT91CAP9_SCKCR_OSCSEL_32 (1 << 3)
+
+/*
* Internal Memory.
*/
#define AT91CAP9_SRAM_BASE 0x00100000 /* Internal SRAM base address */
--
1.5.3.3