[U-Boot] [PATCH v2] AT91: Add SD/MMC controller support
Albin Tonnerre
albin.tonnerre at free-electrons.com
Sat Sep 5 14:23:00 CEST 2009
This patch allows to use the atmel_mci SD/MMC driver on the at91 architecture.
It contains:
- initialization code for the MCI controller for all the supported AT91. It
allows the use of only one controller even if a SoC has two controllers
(anyway there's no support for it in atmel_mci as of now)
- the necessary get_mci_clk_rate function
- definition of MMCI_BASE for use in atmel_mci
- the cpu_mmc_init function. As of now this is not used, but will be required
when atmel_mci is ported to the new generic mmc API.
Signed-off-by: Albin Tonnerre <albin.tonnerre at free-electrons.com>
---
Changes since v1 (http://lists.denx.de/pipermail/u-boot/2009-September/059665.html):
- Fix the MCI controller ID in the init code for CAP9, SAM9263 and SAM9G45
- Move AT91_BASE_MCI* define to soc header
- define AT91_BASE_MCI{0,1} instead of AT91_BASE_MCI for boards which have 2
controllers
- rework the way MMCI_BASE is defined accordingly
Note: I am fully aware that MMCI0_BASE and MMCI1_BASE should be defined, instead
of MMCI_BASE. However, I'd rather wait until the patch that switches atmel_mci
to the generic mmc API is accepted, as it will be easier to do it then.
cpu/arm926ejs/at91/at91cap9_devices.c | 37 ++++++++++++++++++
cpu/arm926ejs/at91/at91sam9260_devices.c | 27 +++++++++++++
cpu/arm926ejs/at91/at91sam9261_devices.c | 18 +++++++++
cpu/arm926ejs/at91/at91sam9263_devices.c | 55 +++++++++++++++++++++++++++
cpu/arm926ejs/at91/at91sam9m10g45_devices.c | 55 +++++++++++++++++++++++++++
cpu/arm926ejs/at91/at91sam9rl_devices.c | 22 +++++++++++
cpu/arm926ejs/at91/cpu.c | 7 +++
include/asm-arm/arch-at91/at91_common.h | 2 +
include/asm-arm/arch-at91/at91cap9.h | 3 +
include/asm-arm/arch-at91/at91sam9260.h | 2 +
include/asm-arm/arch-at91/at91sam9261.h | 1 +
include/asm-arm/arch-at91/at91sam9263.h | 3 +
include/asm-arm/arch-at91/at91sam9g45.h | 3 +
include/asm-arm/arch-at91/at91sam9rl.h | 1 +
include/asm-arm/arch-at91/clk.h | 5 ++
include/asm-arm/arch-at91/memory-map.h | 6 +++
16 files changed, 247 insertions(+), 0 deletions(-)
diff --git a/cpu/arm926ejs/at91/at91cap9_devices.c b/cpu/arm926ejs/at91/at91cap9_devices.c
index 39e405f..53a58a9 100644
--- a/cpu/arm926ejs/at91/at91cap9_devices.c
+++ b/cpu/arm926ejs/at91/at91cap9_devices.c
@@ -79,6 +79,43 @@ void at91_serial_hw_init(void)
#endif
}
+#ifdef CONFIG_ATMEL_MCI
+#ifdef CONFIG_AT91_MCI0
+void at91_mci0_hw_init(unsigned long mask)
+{
+ at91_sys_write(AT91_PMC_PCER, 1 << AT91CAP9_ID_MCI0);
+ at91_set_A_periph(AT91_PIN_PA2, 0);
+
+ if (mask & (1 << 0)) {
+ at91_set_A_periph(AT91_PIN_PA0, 1);
+ at91_set_A_periph(AT91_PIN_PA1, 1);
+ if (mask & (1 << 1)) {
+ at91_set_A_periph(AT91_PIN_PA3, 1);
+ at91_set_A_periph(AT91_PIN_PA4, 1);
+ at91_set_A_periph(AT91_PIN_PA5, 1);
+ }
+ }
+}
+#endif
+#ifdef CONFIG_AT91_MCI1
+void at91_mci1_hw_init(unsigned long mask)
+{
+ at91_sys_write(AT91_PMC_PCER, 1 << AT91CAP9_ID_MCI1);
+ at91_set_A_periph(AT91_PIN_PA16, 0);
+
+ if (mask & (1 << 0)) {
+ at91_set_A_periph(AT91_PIN_PA17, 1);
+ at91_set_A_periph(AT91_PIN_PA18, 1);
+ if (mask & (1 << 1)) {
+ at91_set_A_periph(AT91_PIN_PA19, 1);
+ at91_set_A_periph(AT91_PIN_PA20, 1);
+ at91_set_A_periph(AT91_PIN_PA21, 1);
+ }
+ }
+}
+#endif
+#endif
+
#ifdef CONFIG_HAS_DATAFLASH
void at91_spi0_hw_init(unsigned long cs_mask)
{
diff --git a/cpu/arm926ejs/at91/at91sam9260_devices.c b/cpu/arm926ejs/at91/at91sam9260_devices.c
index f86cb99..ea22030 100644
--- a/cpu/arm926ejs/at91/at91sam9260_devices.c
+++ b/cpu/arm926ejs/at91/at91sam9260_devices.c
@@ -75,6 +75,33 @@ void at91_serial_hw_init(void)
#endif
}
+#ifdef CONFIG_ATMEL_MCI
+void at91_mci0_hw_init(unsigned long mask)
+{
+ at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_MCI);
+ at91_set_A_periph(AT91_PIN_PA8, 0);
+
+ if (mask & (1 << 0)) {
+ at91_set_A_periph(AT91_PIN_PA6, 1);
+ at91_set_A_periph(AT91_PIN_PA7, 1);
+ if (mask & (1 << 1)) {
+ at91_set_A_periph(AT91_PIN_PA9, 1);
+ at91_set_A_periph(AT91_PIN_PA10, 1);
+ at91_set_A_periph(AT91_PIN_PA11, 1);
+ }
+ }
+ if (mask & (1 << 2)) {
+ at91_set_B_periph(AT91_PIN_PA0, 1);
+ at91_set_B_periph(AT91_PIN_PA1, 1);
+ if (mask & (1 << 3)) {
+ at91_set_B_periph(AT91_PIN_PA3, 1);
+ at91_set_B_periph(AT91_PIN_PA4, 1);
+ at91_set_B_periph(AT91_PIN_PA5, 1);
+ }
+ }
+}
+#endif /* ATMEL_MCI */
+
#if defined(CONFIG_HAS_DATAFLASH) || defined(CONFIG_ATMEL_SPI)
void at91_spi0_hw_init(unsigned long cs_mask)
{
diff --git a/cpu/arm926ejs/at91/at91sam9261_devices.c b/cpu/arm926ejs/at91/at91sam9261_devices.c
index 16d411f..7ee573c 100644
--- a/cpu/arm926ejs/at91/at91sam9261_devices.c
+++ b/cpu/arm926ejs/at91/at91sam9261_devices.c
@@ -75,6 +75,24 @@ void at91_serial_hw_init(void)
#endif
}
+#ifdef CONFIG_ATMEL_MCI
+void at91_mci0_hw_init(unsigned long mask)
+{
+ at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9261_ID_MCI);
+ at91_set_B_periph(AT91_PIN_PA2, 0);
+
+ if (mask & (1 << 0)) {
+ at91_set_B_periph(AT91_PIN_PA0, 1);
+ at91_set_B_periph(AT91_PIN_PA1, 1);
+ if (mask & (1 << 1)) {
+ at91_set_B_periph(AT91_PIN_PA4, 1);
+ at91_set_B_periph(AT91_PIN_PA5, 1);
+ at91_set_B_periph(AT91_PIN_PA6, 1);
+ }
+ }
+}
+#endif /* ATMEL_MCI */
+
#ifdef CONFIG_HAS_DATAFLASH
void at91_spi0_hw_init(unsigned long cs_mask)
{
diff --git a/cpu/arm926ejs/at91/at91sam9263_devices.c b/cpu/arm926ejs/at91/at91sam9263_devices.c
index f72efdf..6a89fab 100644
--- a/cpu/arm926ejs/at91/at91sam9263_devices.c
+++ b/cpu/arm926ejs/at91/at91sam9263_devices.c
@@ -79,6 +79,61 @@ void at91_serial_hw_init(void)
#endif
}
+#ifdef CONFIG_ATMEL_MCI
+#ifdef CONFIG_AT91_MCI0
+void at91_mci0_hw_init(unsigned long mask)
+{
+ at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9263_ID_MCI0);
+ at91_set_A_periph(AT91_PIN_PA12, 0);
+
+ if (mask & (1 << 0)) {
+ at91_set_A_periph(AT91_PIN_PA0, 1);
+ at91_set_A_periph(AT91_PIN_PA1, 1);
+ if (mask & (1 << 1)) {
+ at91_set_A_periph(AT91_PIN_PA3, 1);
+ at91_set_A_periph(AT91_PIN_PA4, 1);
+ at91_set_A_periph(AT91_PIN_PA5, 1);
+ }
+ }
+ if (mask & (1 << 2)) {
+ at91_set_A_periph(AT91_PIN_PA16, 1);
+ at91_set_A_periph(AT91_PIN_PA17, 1);
+ if (mask & (1 << 3)) {
+ at91_set_A_periph(AT91_PIN_PA18, 1);
+ at91_set_A_periph(AT91_PIN_PA19, 1);
+ at91_set_A_periph(AT91_PIN_PA20, 1);
+ }
+ }
+}
+#endif
+#ifdef CONFIG_AT91_MCI1
+void at91_mci1_hw_init(unsigned long mask)
+{
+ at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9263_ID_MCI1);
+ at91_set_A_periph(AT91_PIN_PA6, 0);
+
+ if (mask & (1 << 0)) {
+ at91_set_A_periph(AT91_PIN_PA7, 1);
+ at91_set_A_periph(AT91_PIN_PA8, 1);
+ if (mask & (1 << 1)) {
+ at91_set_A_periph(AT91_PIN_PA9, 1);
+ at91_set_A_periph(AT91_PIN_PA10, 1);
+ at91_set_A_periph(AT91_PIN_PA11, 1);
+ }
+ }
+ if (mask & (1 << 2)) {
+ at91_set_B_periph(AT91_PIN_PA21, 1);
+ at91_set_B_periph(AT91_PIN_PA22, 1);
+ if (mask & (1 << 3)) {
+ at91_set_B_periph(AT91_PIN_PA23, 1);
+ at91_set_B_periph(AT91_PIN_PA24, 1);
+ at91_set_B_periph(AT91_PIN_PA25, 1);
+ }
+ }
+}
+#endif
+#endif
+
#ifdef CONFIG_HAS_DATAFLASH
void at91_spi0_hw_init(unsigned long cs_mask)
{
diff --git a/cpu/arm926ejs/at91/at91sam9m10g45_devices.c b/cpu/arm926ejs/at91/at91sam9m10g45_devices.c
index 98d90f2..c4db5f4 100644
--- a/cpu/arm926ejs/at91/at91sam9m10g45_devices.c
+++ b/cpu/arm926ejs/at91/at91sam9m10g45_devices.c
@@ -75,6 +75,61 @@ void at91_serial_hw_init(void)
#endif
}
+#ifdef CONFIG_ATMEL_MCI
+#ifdef CONFIG_AT91_MCI0
+void at91_mci0_hw_init(unsigned long mask)
+{
+ at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9G45_ID_MCI0);
+ at91_set_A_periph(AT91_PIN_PA12, 0);
+
+ if (mask & (1 << 0)) {
+ at91_set_A_periph(AT91_PIN_PA0, 1);
+ at91_set_A_periph(AT91_PIN_PA1, 1);
+ if (mask & (1 << 1)) {
+ at91_set_A_periph(AT91_PIN_PA3, 1);
+ at91_set_A_periph(AT91_PIN_PA4, 1);
+ at91_set_A_periph(AT91_PIN_PA5, 1);
+ }
+ }
+ if (mask & (1 << 2)) {
+ at91_set_A_periph(AT91_PIN_PA16, 1);
+ at91_set_A_periph(AT91_PIN_PA17, 1);
+ if (mask & (1 << 3)) {
+ at91_set_A_periph(AT91_PIN_PA18, 1);
+ at91_set_A_periph(AT91_PIN_PA19, 1);
+ at91_set_A_periph(AT91_PIN_PA20, 1);
+ }
+ }
+}
+#endif
+#ifdef CONFIG_AT91_MCI1
+void at91_mci1_hw_init(unsigned long mask)
+{
+ at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9G45_ID_MCI1);
+ at91_set_A_periph(AT91_PIN_PA6, 0);
+
+ if (mask & (1 << 0)) {
+ at91_set_A_periph(AT91_PIN_PA7, 1);
+ at91_set_A_periph(AT91_PIN_PA8, 1);
+ if (mask & (1 << 1)) {
+ at91_set_A_periph(AT91_PIN_PA9, 1);
+ at91_set_A_periph(AT91_PIN_PA10, 1);
+ at91_set_A_periph(AT91_PIN_PA11, 1);
+ }
+ }
+ if (mask & (1 << 2)) {
+ at91_set_B_periph(AT91_PIN_PA0, 1);
+ at91_set_B_periph(AT91_PIN_PA1, 1);
+ if (mask & (1 << 3)) {
+ at91_set_B_periph(AT91_PIN_PA3, 1);
+ at91_set_B_periph(AT91_PIN_PA4, 1);
+ at91_set_B_periph(AT91_PIN_PA5, 1);
+ }
+ }
+}
+#endif
+#endif
+
#ifdef CONFIG_ATMEL_SPI
void at91_spi0_hw_init(unsigned long cs_mask)
{
diff --git a/cpu/arm926ejs/at91/at91sam9rl_devices.c b/cpu/arm926ejs/at91/at91sam9rl_devices.c
index ebed193..41ae4a8 100644
--- a/cpu/arm926ejs/at91/at91sam9rl_devices.c
+++ b/cpu/arm926ejs/at91/at91sam9rl_devices.c
@@ -75,6 +75,28 @@ void at91_serial_hw_init(void)
#endif
}
+/*
+ * The AT91SAM9RL64 is said to have 2 slots, but the datasheet doesn't
+ * seem to mention to what pins the second slot is assigned
+ */
+#ifdef CONFIG_ATMEL_MCI
+void at91_mci0_hw_init(unsigned long mask)
+{
+ at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_MCI);
+ at91_set_A_periph(AT91_PIN_PA2, 0);
+
+ if (mask & (1 << 0)) {
+ at91_set_A_periph(AT91_PIN_PA0, 1);
+ at91_set_A_periph(AT91_PIN_PA1, 1);
+ if (mask & (1 << 1)) {
+ at91_set_A_periph(AT91_PIN_PA3, 1);
+ at91_set_A_periph(AT91_PIN_PA4, 1);
+ at91_set_A_periph(AT91_PIN_PA5, 1);
+ }
+ }
+}
+#endif /* ATMEL_MCI */
+
#ifdef CONFIG_HAS_DATAFLASH
void at91_spi0_hw_init(unsigned long cs_mask)
{
diff --git a/cpu/arm926ejs/at91/cpu.c b/cpu/arm926ejs/at91/cpu.c
index f2f7b62..f96b715 100644
--- a/cpu/arm926ejs/at91/cpu.c
+++ b/cpu/arm926ejs/at91/cpu.c
@@ -52,3 +52,10 @@ int print_cpuinfo(void)
return 0;
}
#endif
+
+#ifdef CONFIG_GENERIC_MMC
+int cpu_mmc_init(bd_t *bis)
+{
+ atmel_mci_init(bis);
+}
+#endif /* GENERIC_MMC */
diff --git a/include/asm-arm/arch-at91/at91_common.h b/include/asm-arm/arch-at91/at91_common.h
index 01840ee..01fcdd6 100644
--- a/include/asm-arm/arch-at91/at91_common.h
+++ b/include/asm-arm/arch-at91/at91_common.h
@@ -32,6 +32,8 @@ void at91_serial0_hw_init(void);
void at91_serial1_hw_init(void);
void at91_serial2_hw_init(void);
void at91_serial3_hw_init(void);
+void at91_mci0_hw_init(unsigned long mask);
+void at91_mci1_hw_init(unsigned long mask);
void at91_spi0_hw_init(unsigned long cs_mask);
void at91_spi1_hw_init(unsigned long cs_mask);
void at91_uhp_hw_init(void);
diff --git a/include/asm-arm/arch-at91/at91cap9.h b/include/asm-arm/arch-at91/at91cap9.h
index b128ac5..2ad3280 100644
--- a/include/asm-arm/arch-at91/at91cap9.h
+++ b/include/asm-arm/arch-at91/at91cap9.h
@@ -109,6 +109,9 @@
#define AT91_USART1 AT91CAP9_BASE_US1
#define AT91_USART2 AT91CAP9_BASE_US2
+#define AT91_BASE_MCI0 AT91CAP9_BASE_MCI0
+#define AT91_BASE_MCI1 AT91CAP9_BASE_MCI1
+
/*
* SCKCR flags
*/
diff --git a/include/asm-arm/arch-at91/at91sam9260.h b/include/asm-arm/arch-at91/at91sam9260.h
index 73975f4..b92f0ee 100644
--- a/include/asm-arm/arch-at91/at91sam9260.h
+++ b/include/asm-arm/arch-at91/at91sam9260.h
@@ -105,6 +105,8 @@
#define AT91_USART4 AT91SAM9260_BASE_US4
#define AT91_USART5 AT91SAM9260_BASE_US5
+#define AT91_BASE_MCI0 AT91SAM9260_BASE_MCI
+
/*
* Internal Memory.
*/
diff --git a/include/asm-arm/arch-at91/at91sam9261.h b/include/asm-arm/arch-at91/at91sam9261.h
index b303e07..11fdc3e 100644
--- a/include/asm-arm/arch-at91/at91sam9261.h
+++ b/include/asm-arm/arch-at91/at91sam9261.h
@@ -88,6 +88,7 @@
#define AT91_USART1 AT91SAM9261_BASE_US1
#define AT91_USART2 AT91SAM9261_BASE_US2
+#define AT91_BASE_MCI0 AT91SAM9261_BASE_MCI
/*
* Internal Memory.
diff --git a/include/asm-arm/arch-at91/at91sam9263.h b/include/asm-arm/arch-at91/at91sam9263.h
index 966a683..6bf124b 100644
--- a/include/asm-arm/arch-at91/at91sam9263.h
+++ b/include/asm-arm/arch-at91/at91sam9263.h
@@ -108,6 +108,9 @@
#define AT91_SMC AT91_SMC0
#define AT91_SDRAMC AT91_SDRAMC0
+#define AT91_BASE_MCI0 AT91SAM9263_BASE_MCI0
+#define AT91_BASE_MCI1 AT91SAM9263_BASE_MCI1
+
/*
* Internal Memory.
*/
diff --git a/include/asm-arm/arch-at91/at91sam9g45.h b/include/asm-arm/arch-at91/at91sam9g45.h
index 0feed9c..16deadc 100644
--- a/include/asm-arm/arch-at91/at91sam9g45.h
+++ b/include/asm-arm/arch-at91/at91sam9g45.h
@@ -114,6 +114,9 @@
#define AT91_USART2 AT91SAM9G45_BASE_US2
#define AT91_USART3 AT91SAM9G45_BASE_US3
+#define AT91_BASE_MCI0 AT91SAM9G45_BASE_MCI0
+#define AT91_BASE_MCI1 AT91SAM9G45_BASE_MCI1
+
/*
* Internal Memory.
*/
diff --git a/include/asm-arm/arch-at91/at91sam9rl.h b/include/asm-arm/arch-at91/at91sam9rl.h
index 4dd8037..f0da7a2 100644
--- a/include/asm-arm/arch-at91/at91sam9rl.h
+++ b/include/asm-arm/arch-at91/at91sam9rl.h
@@ -99,6 +99,7 @@
#define AT91_USART2 AT91SAM9RL_BASE_US2
#define AT91_USART3 AT91SAM9RL_BASE_US3
+#define AT91_BASE_MCI0 AT91SAM9RL_BASE_MCI
/*
* Internal Memory.
diff --git a/include/asm-arm/arch-at91/clk.h b/include/asm-arm/arch-at91/clk.h
index f642dd9..457e6c9 100644
--- a/include/asm-arm/arch-at91/clk.h
+++ b/include/asm-arm/arch-at91/clk.h
@@ -59,5 +59,10 @@ static inline unsigned long get_twi_clk_rate(unsigned int dev_id)
return get_mck_clk_rate();
}
+static inline unsigned long get_mci_clk_rate(void)
+{
+ return get_mck_clk_rate();
+}
+
int at91_clock_init(unsigned long main_clock);
#endif /* __ASM_ARM_ARCH_CLK_H__ */
diff --git a/include/asm-arm/arch-at91/memory-map.h b/include/asm-arm/arch-at91/memory-map.h
index f605f37..445d128 100644
--- a/include/asm-arm/arch-at91/memory-map.h
+++ b/include/asm-arm/arch-at91/memory-map.h
@@ -32,4 +32,10 @@
#define USART3_BASE (AT91_BASE_SYS + AT91_DBGU)
#define SPI0_BASE AT91_BASE_SPI
+#ifndef (CONFIG_AT91_MCI1)
+# define MMCI_BASE AT91_BASE_MCI0
+#else
+# define MMCI_BASE AT91_BASE_MCI1
+#endif
+
#endif /* __ASM_ARM_ARCH_MEMORYMAP_H__ */
--
1.6.3.3
More information about the U-Boot
mailing list