[U-Boot] [PATCH v2] AT91: Add SD/MMC controller support

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@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__ */

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@free-electrons.com Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD plagnioj@jcrosoft.com --- Changes since v1 - 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
Changes since v2 - allow using 8-bit bus width on CPUs that support it - change the arguments of atmel_mciX_hw_init to (slot, bus) so that it's more meaningful than (bitmask)
cpu/arm926ejs/at91/at91cap9_devices.c | 40 +++++++++++++++ cpu/arm926ejs/at91/at91sam9260_devices.c | 37 ++++++++++++++ cpu/arm926ejs/at91/at91sam9261_devices.c | 21 ++++++++ cpu/arm926ejs/at91/at91sam9263_devices.c | 72 +++++++++++++++++++++++++++ cpu/arm926ejs/at91/at91sam9m10g45_devices.c | 56 +++++++++++++++++++++ cpu/arm926ejs/at91/at91sam9rl_devices.c | 25 +++++++++ include/asm-arm/arch-at91/at91_common.h | 2 + include/asm-arm/arch-at91/at91cap9.h | 2 + include/asm-arm/arch-at91/at91sam9260.h | 1 + include/asm-arm/arch-at91/at91sam9261.h | 1 + include/asm-arm/arch-at91/at91sam9263.h | 2 + include/asm-arm/arch-at91/at91sam9g45.h | 2 + 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 ++ 15 files changed, 273 insertions(+), 0 deletions(-)
diff --git a/cpu/arm926ejs/at91/at91cap9_devices.c b/cpu/arm926ejs/at91/at91cap9_devices.c index 39e405f..de7048b 100644 --- a/cpu/arm926ejs/at91/at91cap9_devices.c +++ b/cpu/arm926ejs/at91/at91cap9_devices.c @@ -79,6 +79,46 @@ void at91_serial_hw_init(void) #endif }
+#ifdef CONFIG_ATMEL_MCI +void at91_mci0_hw_init(int slot, int bus_width) +{ + at91_sys_write(AT91_PMC_PCER, 1 << AT91CAP9_ID_MCI0); + + /* CLK */ + at91_set_A_periph(AT91_PIN_PA2, 0); + + /* CMD */ + at91_set_A_periph(AT91_PIN_PA1, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA0, 1); + if (bus_width == 4) { + at91_set_A_periph(AT91_PIN_PA3, 1); + at91_set_A_periph(AT91_PIN_PA4, 1); + at91_set_A_periph(AT91_PIN_PA5, 1); + } +} + +void at91_mci1_hw_init(int slot, int bus_width) +{ + at91_sys_write(AT91_PMC_PCER, 1 << AT91CAP9_ID_MCI0); + + /* CLK */ + at91_set_A_periph(AT91_PIN_PA16, 0); + + /* CMD */ + at91_set_A_periph(AT91_PIN_PA17, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA18, 1); + if (bus_width == 4) { + 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 + #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..f724f58 100644 --- a/cpu/arm926ejs/at91/at91sam9260_devices.c +++ b/cpu/arm926ejs/at91/at91sam9260_devices.c @@ -75,6 +75,43 @@ void at91_serial_hw_init(void) #endif }
+#ifdef CONFIG_ATMEL_MCI +void at91_mci0_hw_init(int slot, int bus_width) +{ + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_MCI); + + /* CLK */ + at91_set_A_periph(AT91_PIN_PA8, 0); + + switch (slot) { + case 0: + /* CMD */ + at91_set_A_periph(AT91_PIN_PA7, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA6, 1); + if (bus_width == 4) { + at91_set_A_periph(AT91_PIN_PA9, 1); + at91_set_A_periph(AT91_PIN_PA10, 1); + at91_set_A_periph(AT91_PIN_PA11, 1); + } + break; + case 1: + /* CMD */ + at91_set_B_periph(AT91_PIN_PA1, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_B_periph(AT91_PIN_PA0, 1); + if (bus_width == 4) { + at91_set_B_periph(AT91_PIN_PA3, 1); + at91_set_B_periph(AT91_PIN_PA4, 1); + at91_set_B_periph(AT91_PIN_PA5, 1); + } + break; + } +} +#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..be76acf 100644 --- a/cpu/arm926ejs/at91/at91sam9261_devices.c +++ b/cpu/arm926ejs/at91/at91sam9261_devices.c @@ -75,6 +75,27 @@ void at91_serial_hw_init(void) #endif }
+#ifdef CONFIG_ATMEL_MCI +void at91_mci0_hw_init(int slot, int bus_width) +{ + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9261_ID_MCI); + + /* CLK */ + at91_set_B_periph(AT91_PIN_PA2, 0); + + /* CMD */ + at91_set_B_periph(AT91_PIN_PA1, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_B_periph(AT91_PIN_PA0, 1); + if (bus_width == 4) { + 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..c06a541 100644 --- a/cpu/arm926ejs/at91/at91sam9263_devices.c +++ b/cpu/arm926ejs/at91/at91sam9263_devices.c @@ -79,6 +79,78 @@ void at91_serial_hw_init(void) #endif }
+#ifdef CONFIG_ATMEL_MCI +void at91_mci0_hw_init(int slot, int bus_width) +{ + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9263_ID_MCI0); + + /* CLK */ + at91_set_A_periph(AT91_PIN_PA12, 0); + + switch (slot) { + case 0: + /* CMD */ + at91_set_A_periph(AT91_PIN_PA1, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA0, 1); + if (bus_width == 4) { + at91_set_A_periph(AT91_PIN_PA3, 1); + at91_set_A_periph(AT91_PIN_PA4, 1); + at91_set_A_periph(AT91_PIN_PA5, 1); + } + break; + case 1: + /* CMD */ + at91_set_A_periph(AT91_PIN_PA16, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA17, 1); + if (bus_width == 4) { + at91_set_A_periph(AT91_PIN_PA18, 1); + at91_set_A_periph(AT91_PIN_PA19, 1); + at91_set_A_periph(AT91_PIN_PA20, 1); + } + break; + } +} + +void at91_mci1_hw_init(int slot, int bus_width) +{ + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9263_ID_MCI1); + + /* CLK */ + at91_set_A_periph(AT91_PIN_PA6, 0); + + switch (slot) { + case 0: + /* CMD */ + at91_set_A_periph(AT91_PIN_PA7, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA8, 1); + if (bus_width == 4) { + at91_set_A_periph(AT91_PIN_PA9, 1); + at91_set_A_periph(AT91_PIN_PA10, 1); + at91_set_A_periph(AT91_PIN_PA11, 1); + } + break; + case 1: + /* CMD */ + at91_set_B_periph(AT91_PIN_PA21, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_B_periph(AT91_PIN_PA22, 1); + if (bus_width == 4) { + at91_set_B_periph(AT91_PIN_PA23, 1); + at91_set_B_periph(AT91_PIN_PA24, 1); + at91_set_B_periph(AT91_PIN_PA25, 1); + } + break; + } +} +#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..91a0546 100644 --- a/cpu/arm926ejs/at91/at91sam9m10g45_devices.c +++ b/cpu/arm926ejs/at91/at91sam9m10g45_devices.c @@ -75,6 +75,62 @@ void at91_serial_hw_init(void) #endif }
+#ifdef CONFIG_ATMEL_MCI +void at91_mci0_hw_init(int slot, int bus_width) +{ + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9G45_ID_MCI0); + + at91_set_A_periph(AT91_PIN_PA12, 0); + + /* CLK */ + at91_set_A_periph(AT91_PIN_PA0, 1); + + /* CMD */ + at91_set_A_periph(AT91_PIN_PA1, 1); + + /* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */ + at91_set_A_periph(AT91_PIN_PA2, 1); + switch (bus_width) { + case 8: + at91_set_A_periph(AT91_PIN_PA6, 1); + at91_set_A_periph(AT91_PIN_PA7, 1); + at91_set_A_periph(AT91_PIN_PA8, 1); + at91_set_A_periph(AT91_PIN_PA9, 1); + case 4: + at91_set_A_periph(AT91_PIN_PA3, 1); + at91_set_A_periph(AT91_PIN_PA4, 1); + at91_set_A_periph(AT91_PIN_PA5, 1); + break; + } +} + +void at91_mci1_hw_init(int slot, int bus_width) +{ + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9G45_ID_MCI1); + + /* CLK */ + at91_set_A_periph(AT91_PIN_PA31, 0); + + /* CMD */ + at91_set_A_periph(AT91_PIN_PA22, 1); + + /* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */ + at91_set_A_periph(AT91_PIN_PA23, 1); + switch (bus_width) { + case 8: + at91_set_A_periph(AT91_PIN_PA27, 1); + at91_set_A_periph(AT91_PIN_PA28, 1); + at91_set_A_periph(AT91_PIN_PA29, 1); + at91_set_A_periph(AT91_PIN_PA30, 1); + case 4: + at91_set_A_periph(AT91_PIN_PA24, 1); + at91_set_A_periph(AT91_PIN_PA25, 1); + at91_set_A_periph(AT91_PIN_PA26, 1); + break; + } +} +#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..3945e13 100644 --- a/cpu/arm926ejs/at91/at91sam9rl_devices.c +++ b/cpu/arm926ejs/at91/at91sam9rl_devices.c @@ -75,6 +75,31 @@ 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(int slot, int bus_width) +{ + at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9RL_ID_MCI); + + /* CLK */ + at91_set_A_periph(AT91_PIN_PA2, 0); + + /* CMD */ + at91_set_A_periph(AT91_PIN_PA1, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA0, 1); + if (bus_width == 4) { + 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/include/asm-arm/arch-at91/at91_common.h b/include/asm-arm/arch-at91/at91_common.h index 01840ee..1c96b40 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(int slot, int bus_width); +void at91_mci1_hw_init(int slot, int bus_width); 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 98bfcc7..de731ac 100644 --- a/include/asm-arm/arch-at91/at91cap9.h +++ b/include/asm-arm/arch-at91/at91cap9.h @@ -112,6 +112,8 @@ #define AT91_BASE_SPI AT91CAP9_BASE_SPI0 #define AT91_ID_UHP AT91CAP9_ID_UHP #define AT91_PMC_UHP AT91CAP9_PMC_UHP +#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 f2aef8a..6b26140 100644 --- a/include/asm-arm/arch-at91/at91sam9260.h +++ b/include/asm-arm/arch-at91/at91sam9260.h @@ -108,6 +108,7 @@ #define AT91_BASE_SPI AT91SAM9260_BASE_SPI0 #define AT91_ID_UHP AT91SAM9260_ID_UHP #define AT91_PMC_UHP AT91SAM926x_PMC_UHP +#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 55bd49a..48fb8f4 100644 --- a/include/asm-arm/arch-at91/at91sam9261.h +++ b/include/asm-arm/arch-at91/at91sam9261.h @@ -91,6 +91,7 @@ #define AT91_BASE_SPI AT91SAM9261_BASE_SPI0 #define AT91_ID_UHP AT91SAM9261_ID_UHP #define AT91_PMC_UHP AT91SAM926x_PMC_UHP +#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 d862129..4f29e65 100644 --- a/include/asm-arm/arch-at91/at91sam9263.h +++ b/include/asm-arm/arch-at91/at91sam9263.h @@ -111,6 +111,8 @@ #define AT91_BASE_SPI AT91SAM9263_BASE_SPI0 #define AT91_ID_UHP AT91SAM9263_ID_UHP #define AT91_PMC_UHP AT91SAM926x_PMC_UHP +#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 d02b157..f232600 100644 --- a/include/asm-arm/arch-at91/at91sam9g45.h +++ b/include/asm-arm/arch-at91/at91sam9g45.h @@ -118,6 +118,8 @@ #define AT91_BASE_SPI AT91SAM9G45_BASE_SPI0 #define AT91_ID_UHP AT91SAM9G45_ID_UHPHS #define AT91_PMC_UHP AT91SAM926x_PMC_UHP +#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 3638f92..d26a607 100644 --- a/include/asm-arm/arch-at91/at91sam9rl.h +++ b/include/asm-arm/arch-at91/at91sam9rl.h @@ -101,6 +101,7 @@
#define AT91_BASE_SPI AT91SAM9RL_BASE_SPI #define AT91_ID_UHP AT91SAM9RL_ID_UHP +#define AT91_BASE_MCI0 AT91SAM9RL_BASE_MCI
/* 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..de0aba7 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__ */

Dear Albin Tonnerre,
In message 1252442374-25386-1-git-send-email-albin.tonnerre@free-electrons.com you wrote:
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@free-electrons.com Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD plagnioj@jcrosoft.com
Changes since v1
- 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
Changes since v2
- allow using 8-bit bus width on CPUs that support it
- change the arguments of atmel_mciX_hw_init to (slot, bus) so that it's more meaningful than (bitmask)
What's the current state of this patch? Do you consider it ripe for inclusion into mainline, or do you still have changes pending?
Best regards,
Wolfgang Denk

On Sun, 22 Nov 2009 22:17 +0100, Wolfgang Denk wrote :
Dear Albin Tonnerre,
In message 1252442374-25386-1-git-send-email-albin.tonnerre@free-electrons.com you wrote:
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@free-electrons.com Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD plagnioj@jcrosoft.com
Changes since v1
- 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
Changes since v2
- allow using 8-bit bus width on CPUs that support it
- change the arguments of atmel_mciX_hw_init to (slot, bus) so that it's more meaningful than (bitmask)
What's the current state of this patch? Do you consider it ripe for inclusion into mainline, or do you still have changes pending?
I consider it ready for inclusion. Thanks for the heads-up.
Regards,

Hello there,
I tried to get mmc working on a board using an at91sam9g20. The mmc-card is wired on slotb.
I applied the patches:
http://lists.denx.de/pipermail/u-boot/2009-September/060053.html http://lists.denx.de/pipermail/u-boot/2009-August/059456.html http://lists.denx.de/pipermail/u-boot/2009-September/060243.html
It didn't work as I always got (apart from the message of a too low clock which I avoided by setting f_min / f_max on my own):
mmc: command 8 failed (status: 0x0010c1e5) mmc: command 55 failed (status: 0x0010c1e5) mmc: command 1 failed (status: 0x0010c1e5) Card did not respond to voltage select!
So I had a look at linux sources and discovered that the MCI selected the wrong slot. After modifying atmel_mci_set_ios() to set SDCR to use slotb ("mmci_writel(SDCR, sdcr | 1);") I got my card working.
Hope this helps someone.
Regards
Sebastian Heutling

Hi,
for me this is working:
Downloaded u-boot 2009.08
file cpu/arm926ejs/at91/at91sam9260_devices.c
changed:
#if defined(CONFIG_HAS_DATAFLASH)
to:
#if defined(CONFIG_HAS_DATAFLASH) || defined(CONFIG_ATMEL_SPI)
patches:
SOC headers: http://lists.denx.de/pipermail/u-boot/2009-September/060053.html
SD Patch V3 http://lists.denx.de/pipermail/u-boot/2009-September/060243.html
MCI support http://lists.denx.de/pipermail/u-boot/2009-August/059595.html
add to board init code:
at91_mciX_hw_init (X for mci unit 0 / 1) for parameters have a look at cpu/arm926ejs/at91/at91sam9260_devices.c
bye Konrad Mattheis

Hi Konrad,
are you using the AT91SAM9G20-EK?
In that case the difference between us is that I'm working on a different board which is using the slotb MCI while the AT91SAM9G20-EK uses slota.
In case of slota it just worked because MCI_SDCR is 0 on reset but for slotb the SDCSEL field must be set to 1.
Regards
Sebastian Heutling
On 10/01/2009 09:59 AM, Konrad Mattheis wrote:
Hi,
for me this is working:
Downloaded u-boot 2009.08
file cpu/arm926ejs/at91/at91sam9260_devices.c
changed:
#if defined(CONFIG_HAS_DATAFLASH)
to:
#if defined(CONFIG_HAS_DATAFLASH) || defined(CONFIG_ATMEL_SPI)
patches:
SOC headers: http://lists.denx.de/pipermail/u-boot/2009-September/060053.html
SD Patch V3 http://lists.denx.de/pipermail/u-boot/2009-September/060243.html
MCI support http://lists.denx.de/pipermail/u-boot/2009-August/059595.html
add to board init code:
at91_mciX_hw_init (X for mci unit 0 / 1) for parameters have a look at cpu/arm926ejs/at91/at91sam9260_devices.c
bye Konrad Mattheis

Hi Sebastian,
yes I'm using an AT91SAM9G20-EK Rev.c with two SD slots. I used slot a but I think you just have to init slot b.
in PatchV3 you can read:
at91_mci0_hw_init(int slot, int bus_width)
switch (slot) { case 0: ..... case 1:
So I think you just have to call at91_mci0_hw_init(1,4) for slot b.
bye Konrad
-----Ursprüngliche Nachricht----- Von: Sebastian Heutling [mailto:heutling@who-ing.de] Gesendet: Donnerstag, 1. Oktober 2009 10:26 An: Konrad Mattheis Cc: u-boot@lists.denx.de Betreff: Re: AT91 working SD with u-boot
Hi Konrad,
are you using the AT91SAM9G20-EK?
In that case the difference between us is that I'm working on a different board which is using the slotb MCI while the AT91SAM9G20-EK uses slota.
In case of slota it just worked because MCI_SDCR is 0 on reset but for slotb the SDCSEL field must be set to 1.
Regards
Sebastian Heutling
On 10/01/2009 09:59 AM, Konrad Mattheis wrote:
Hi,
for me this is working:
Downloaded u-boot 2009.08
file cpu/arm926ejs/at91/at91sam9260_devices.c
changed:
#if defined(CONFIG_HAS_DATAFLASH)
to:
#if defined(CONFIG_HAS_DATAFLASH) || defined(CONFIG_ATMEL_SPI)
patches:
SOC headers: http://lists.denx.de/pipermail/u-boot/2009-September/060053.html
SD Patch V3 http://lists.denx.de/pipermail/u-boot/2009-September/060243.html
MCI support http://lists.denx.de/pipermail/u-boot/2009-August/059595.html
add to board init code:
at91_mciX_hw_init (X for mci unit 0 / 1) for parameters have a look
at cpu/arm926ejs/at91/at91sam9260_devices.c
bye Konrad Mattheis

Hi Konrad,
On 10/01/2009 10:33 AM, Konrad Mattheis wrote:
Hi Sebastian,
yes I'm using an AT91SAM9G20-EK Rev.c with two SD slots. I used slot a but I think you just have to init slot b.
in PatchV3 you can read:
at91_mci0_hw_init(int slot, int bus_width)
switch (slot) { case 0: ..... case 1:
So I think you just have to call at91_mci0_hw_init(1,4) for slot b.
No - that is not enough. It just enables the clock for MCI and configures the pins. But the MCI itself needs to know which slot to address.
Suppose you want to use both slots at the same time (and the drivers would support that). Then you would call:
at91_mci0_hw_init(0, 4) at91_mci0_hw_init(1, 4)
In order to access both slots the driver (atmel_mci) needs to select which slot to address. And that is what the SDCSEL field of MCI-SDCR is for (see also Datasheet of the AT91SAM9G20 35.9.4 (probably at page 607)).
Regards
Sebastian

On Thu, 01 Oct 2009 11:28 +0200, Sebastian Heutling wrote :
Hi Konrad,
On 10/01/2009 10:33 AM, Konrad Mattheis wrote:
Hi Sebastian,
yes I'm using an AT91SAM9G20-EK Rev.c with two SD slots. I used slot a but I think you just have to init slot b.
in PatchV3 you can read:
at91_mci0_hw_init(int slot, int bus_width)
switch (slot) { case 0: ..... case 1:
So I think you just have to call at91_mci0_hw_init(1,4) for slot b.
No - that is not enough. It just enables the clock for MCI and configures the pins. But the MCI itself needs to know which slot to address.
Suppose you want to use both slots at the same time (and the drivers would support that). Then you would call:
at91_mci0_hw_init(0, 4) at91_mci0_hw_init(1, 4)
In order to access both slots the driver (atmel_mci) needs to select which slot to address. And that is what the SDCSEL field of MCI-SDCR is for (see also Datasheet of the AT91SAM9G20 35.9.4 (probably at page 607)).
But the driver doesn't support for the moment. I might add such support if I have some time (and if that works - has anybody ever tried doing that with Linux?). For now the best way to get it working is to select the correct slot in your board config code.
Cheers,

Sebastian Heutling <heutling <at> who-ing.de> writes:
Hi Konrad,
are you using the AT91SAM9G20-EK?
In that case the difference between us is that I'm working on a different board which is using the slotb MCI while the AT91SAM9G20-EK uses slota.
In case of slota it just worked because MCI_SDCR is 0 on reset but for slotb the SDCSEL field must be set to 1.
Regards
Sebastian Heutling
On 10/01/2009 09:59 AM, Konrad Mattheis wrote:
Hi,
for me this is working:
Downloaded u-boot 2009.08
file cpu/arm926ejs/at91/at91sam9260_devices.c
changed:
#if defined(CONFIG_HAS_DATAFLASH)
to:
#if defined(CONFIG_HAS_DATAFLASH) || defined(CONFIG_ATMEL_SPI)
patches:
SOC headers: http://lists.denx.de/pipermail/u-boot/2009-September/060053.html
SD Patch V3 http://lists.denx.de/pipermail/u-boot/2009-September/060243.html
MCI support http://lists.denx.de/pipermail/u-boot/2009-August/059595.html
add to board init code:
at91_mciX_hw_init (X for mci unit 0 / 1) for parameters have a look at
cpu/arm926ejs/at91/at91sam9260_devices.c
bye Konrad Mattheis
Hello,
Thanks a lot for your post. Could you please let me know what configurations are to be added to /include/configs/board.h file to enable MMC/SD support. I've added the following configurations
/* MMC/SD Support */
/* To include File system support for MMC */ #define CONFIG_DOS_PARTITION #define CONFIG_CMD_EXT2 #define CONFIG_CMD_FAT #define CONFIG_MMC #define CONFIG_GENERIC_MMC #define CONFIG_DAVINCI_MMC #define CONFIG_CMD_MM
/* To enable Environment variables to reside on MMC. */ #define CONFIG_DOS_PARTITION 1 //#undef CONFIG_MMC #define CONFIG_SYS_MMC_BASE 0xFFFB4000 #define CONFIG_SYS_MMC_BLOCKSIZE 512
and when I enter mmcinit, u-boot says command not found. Please find the logs: and thanks alot for your time :)
Electrum> mmcElectrum> mmc Usage: MMC sub system Electrum> mmcinit Unknown command 'mmcinit' - try 'help' Electrum> mmcinfo MMC Device 0 not found
Thanks, Kalyan.
participants (5)
-
Albin Tonnerre
-
Kalyan
-
Konrad Mattheis
-
Sebastian Heutling
-
Wolfgang Denk