[U-Boot] [PATCH] MCI support for AT91 family processors.

Albin Tonnerre albin.tonnerre at free-electrons.com
Sat Aug 29 20:33:19 CEST 2009


Hello Sami,

On Sat, Aug 29, 2009 at 08:18:32PM +0300, Sami Kantoluoto wrote :
> Fixed to parse CSD correctly on little endian processors as gcc orders
> bitfields differently between big and little endian ones.

Please also see this patch, which will fix those bugs as weel, while switching
to the new GENRIC_MMC API:
http://lists.denx.de/pipermail/u-boot/2009-August/059456.html
I'd highly appreciate if you could test it, to get some feedback

> diff --git a/include/asm-arm/arch-at91/clk.h b/include/asm-arm/arch-at91/clk.h
> index f642dd9..26b537c 100644
> --- a/include/asm-arm/arch-at91/clk.h
> +++ b/include/asm-arm/arch-at91/clk.h
> @@ -54,6 +54,11 @@ static inline unsigned long get_spi_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();
> +}
> +
>  static inline unsigned long get_twi_clk_rate(unsigned int dev_id)
>  {
>  	return get_mck_clk_rate();

This is still rather incomplete, you're lacking the definition of MMCI_BASE and
the configuration for the MCI controller, which should be done in the
at91sam*_devices.c files. See the attached patch (relying on the patch
mentionned above) that adds such support. It's not complete yet either: it
partially lacks support for models which have 2 MCI controllers, but that's not
the case of the 9G20 anyway (that's just a matter of putting proper ifdefs
before defining AT91_BASE_MCI).
If what I've done in this patch is not the way to go, I'd appreciate guidance on
how to do it correctly.

Regards,
Albin

---
 cpu/arm926ejs/at91/at91cap9_devices.c       |   36 +++++++++++++++++++
 cpu/arm926ejs/at91/at91sam9260_devices.c    |   25 +++++++++++++
 cpu/arm926ejs/at91/at91sam9261_devices.c    |   18 ++++++++++
 cpu/arm926ejs/at91/at91sam9263_devices.c    |   50 +++++++++++++++++++++++++++
 cpu/arm926ejs/at91/at91sam9m10g45_devices.c |   50 +++++++++++++++++++++++++++
 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/clk.h             |    5 +++
 include/asm-arm/arch-at91/hardware.h        |    1 +
 include/asm-arm/arch-at91/memory-map.h      |    1 +
 11 files changed, 217 insertions(+), 0 deletions(-)

diff --git a/cpu/arm926ejs/at91/at91cap9_devices.c b/cpu/arm926ejs/at91/at91cap9_devices.c
index 39e405f..2dc1984 100644
--- a/cpu/arm926ejs/at91/at91cap9_devices.c
+++ b/cpu/arm926ejs/at91/at91cap9_devices.c
@@ -79,6 +79,42 @@ void at91_serial_hw_init(void)
 #endif
 }
 
+#ifdef CONFIG_ATMEL_MCI
+#ifdef CONFIG_AT91_MCI0
+void at91_mci0_hw_init(int slot)
+{
+	at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9263_ID_MCI0);
+	at91_set_A_periph(AT91_PIN_PA2, 0);
+
+	switch(slot) {
+		case 0:
+			at91_set_A_periph(AT91_PIN_PA0, 1);
+			at91_set_A_periph(AT91_PIN_PA1, 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);
+			break;
+	}
+}
+#elif defined(CONFIG_AT91_MCI1
+void at91_mci1_hw_init(int slot)
+{
+	at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9263_ID_MCI);
+	at91_set_A_periph(AT91_PIN_PA16, 0);
+
+	switch(slot) {
+		case 0:
+			at91_set_A_periph(AT91_PIN_PA17, 1);
+			at91_set_A_periph(AT91_PIN_PA18, 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);
+			break;
+	}
+}
+#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..413fc8b 100644
--- a/cpu/arm926ejs/at91/at91sam9260_devices.c
+++ b/cpu/arm926ejs/at91/at91sam9260_devices.c
@@ -75,6 +75,31 @@ void at91_serial_hw_init(void)
 #endif
 }
 
+#ifdef CONFIG_ATMEL_MCI
+void at91_mci0_hw_init(int slot)
+{
+	at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_MCI);
+	at91_set_A_periph(AT91_PIN_PA8, 0);
+
+	switch(slot) {
+		case 0:
+			at91_set_A_periph(AT91_PIN_PA6, 1);
+			at91_set_A_periph(AT91_PIN_PA7, 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);
+			break;
+		case 1:
+			at91_set_B_periph(AT91_PIN_PA0, 1);
+			at91_set_B_periph(AT91_PIN_PA1, 1);
+			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..e777367 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(int slot)
+{
+	at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9261_ID_MCI);
+	at91_set_B_periph(AT91_PIN_PA2, 0);
+
+	switch(slot) {
+		case 0:
+			at91_set_B_periph(AT91_PIN_PA0, 1);
+			at91_set_B_periph(AT91_PIN_PA1, 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);
+			break;
+	}
+}
+#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..e861108 100644
--- a/cpu/arm926ejs/at91/at91sam9263_devices.c
+++ b/cpu/arm926ejs/at91/at91sam9263_devices.c
@@ -79,6 +79,56 @@ void at91_serial_hw_init(void)
 #endif
 }
 
+#ifdef CONFIG_ATMEL_MCI
+#ifdef CONFIG_AT91_MCI0
+void at91_mci0_hw_init(int slot)
+{
+	at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9263_ID_MCI0);
+	at91_set_A_periph(AT91_PIN_PA12, 0);
+
+	switch(slot) {
+		case 0:
+			at91_set_A_periph(AT91_PIN_PA0, 1);
+			at91_set_A_periph(AT91_PIN_PA1, 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);
+			break;
+		case 1:
+			at91_set_A_periph(AT91_PIN_PA16, 1);
+			at91_set_A_periph(AT91_PIN_PA17, 1);
+			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;
+	}
+}
+#elif defined(CONFIG_AT91_MCI1
+void at91_mci1_hw_init(int slot)
+{
+	at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9263_ID_MCI);
+	at91_set_A_periph(AT91_PIN_PA6, 0);
+
+	switch(slot) {
+		case 0:
+			at91_set_A_periph(AT91_PIN_PA7, 1);
+			at91_set_A_periph(AT91_PIN_PA8, 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);
+			break;
+		case 1:
+			at91_set_B_periph(AT91_PIN_PA21, 1);
+			at91_set_B_periph(AT91_PIN_PA22, 1);
+			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
+#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..8b2d210 100644
--- a/cpu/arm926ejs/at91/at91sam9m10g45_devices.c
+++ b/cpu/arm926ejs/at91/at91sam9m10g45_devices.c
@@ -75,6 +75,56 @@ void at91_serial_hw_init(void)
 #endif
 }
 
+#ifdef CONFIG_ATMEL_MCI
+#ifdef CONFIG_AT91_MCI0
+void at91_mci0_hw_init(int slot)
+{
+	at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9263_ID_MCI0);
+	at91_set_A_periph(AT91_PIN_PA12, 0);
+
+	switch(slot) {
+		case 0:
+			at91_set_A_periph(AT91_PIN_PA0, 1);
+			at91_set_A_periph(AT91_PIN_PA1, 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);
+			break;
+		case 1:
+			at91_set_A_periph(AT91_PIN_PA16, 1);
+			at91_set_A_periph(AT91_PIN_PA17, 1);
+			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;
+	}
+}
+#elif defined(CONFIG_AT91_MCI1
+void at91_mci1_hw_init(int slot)
+{
+	at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9263_ID_MCI);
+	at91_set_A_periph(AT91_PIN_PA6, 0);
+
+	switch(slot) {
+		case 0:
+			at91_set_A_periph(AT91_PIN_PA7, 1);
+			at91_set_A_periph(AT91_PIN_PA8, 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);
+			break;
+		case 1:
+			at91_set_B_periph(AT91_PIN_PA0, 1);
+			at91_set_B_periph(AT91_PIN_PA1, 1);
+			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
+#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..1839b0c 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(int slot)
+{
+	at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_MCI);
+	at91_set_A_periph(AT91_PIN_PA2, 0);
+
+	switch(slot) {
+		case 0:
+			at91_set_A_periph(AT91_PIN_PA0, 1);
+			at91_set_A_periph(AT91_PIN_PA1, 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);
+			break;
+	}
+}
+#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..4bb9887 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);
+void at91_mci1_hw_init(int);
 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/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/hardware.h b/include/asm-arm/arch-at91/hardware.h
index de06a10..6430ade 100644
--- a/include/asm-arm/arch-at91/hardware.h
+++ b/include/asm-arm/arch-at91/hardware.h
@@ -20,6 +20,7 @@
 #include <asm/arch/at91rm9200.h>
 #elif defined(CONFIG_AT91SAM9260) || defined(CONFIG_AT91SAM9G20)
 #include <asm/arch/at91sam9260.h>
+#define AT91_BASE_MCI	AT91SAM9260_BASE_MCI
 #define AT91_BASE_SPI	AT91SAM9260_BASE_SPI0
 #define AT91_ID_UHP	AT91SAM9260_ID_UHP
 #define AT91_PMC_UHP	AT91SAM926x_PMC_UHP
diff --git a/include/asm-arm/arch-at91/memory-map.h b/include/asm-arm/arch-at91/memory-map.h
index f605f37..300b61d 100644
--- a/include/asm-arm/arch-at91/memory-map.h
+++ b/include/asm-arm/arch-at91/memory-map.h
@@ -31,5 +31,6 @@
 #define USART2_BASE AT91_USART2
 #define USART3_BASE (AT91_BASE_SYS + AT91_DBGU)
 #define SPI0_BASE	AT91_BASE_SPI
+#define MMCI_BASE AT91_BASE_MCI
 
 #endif /* __ASM_ARM_ARCH_MEMORYMAP_H__ */
-- 
Albin Tonnerre, Free Electrons
Kernel, drivers and embedded Linux development,
consulting, training and support.
http://free-electrons.com


More information about the U-Boot mailing list