|
|
|
How to use SD/MMC cards with Atmel SoCs having MCI hardware
|
|
|
|
-----------------------------------------------------------
|
|
|
|
2010-08-16 Reinhard Meyer <reinhard.meyer@emk-elektronik.de>
|
|
|
|
|
|
|
|
This is a new approach to use Atmel MCI hardware with the
|
|
|
|
general MMC framework. Therefore it benefits from that
|
|
|
|
framework's abilities to handle SDHC Cards and the ability
|
|
|
|
to write blocks.
|
|
|
|
|
|
|
|
- AT91SAM9XE512 (tested, will definitely work with XE128 and XE256)
|
|
|
|
- AT91SAM9260 (not tested, but MCI is to AT91SAM9XE)
|
|
|
|
- AT91SAM9G20 (not tested, should work)
|
|
|
|
|
|
|
|
It should work with all other ATMEL devices that have MCI,
|
|
|
|
including AVR32.
|
|
|
|
|
|
|
|
The generic driver does NOT assign port pins to the MCI block
|
|
|
|
nor does it start the MCI clock. This has to be handled in a
|
|
|
|
board/SoC specific manner before the driver is initialized:
|
|
|
|
|
|
|
|
example: this is added to at91sam9260_devices.c:
|
|
|
|
|
|
|
|
#if defined(CONFIG_GENERIC_ATMEL_MCI)
|
|
|
|
void at91_mci_hw_init(void)
|
|
|
|
{
|
|
|
|
at91_set_a_periph(AT91_PIO_PORTA, 8, PUP); /* MCCK */
|
|
|
|
#if defined(CONFIG_ATMEL_MCI_PORTB)
|
|
|
|
at91_set_b_periph(AT91_PIO_PORTA, 1, PUP); /* MCCDB */
|
|
|
|
at91_set_b_periph(AT91_PIO_PORTA, 0, PUP); /* MCDB0 */
|
|
|
|
at91_set_b_periph(AT91_PIO_PORTA, 5, PUP); /* MCDB1 */
|
|
|
|
at91_set_b_periph(AT91_PIO_PORTA, 4, PUP); /* MCDB2 */
|
|
|
|
at91_set_b_periph(AT91_PIO_PORTA, 3, PUP); /* MCDB3 */
|
|
|
|
#else
|
|
|
|
at91_set_a_periph(AT91_PIO_PORTA, 7, PUP); /* MCCDA */
|
|
|
|
at91_set_a_periph(AT91_PIO_PORTA, 6, PUP); /* MCDA0 */
|
|
|
|
at91_set_a_periph(AT91_PIO_PORTA, 9, PUP); /* MCDA1 */
|
|
|
|
at91_set_a_periph(AT91_PIO_PORTA, 10, PUP); /* MCDA2 */
|
|
|
|
at91_set_a_periph(AT91_PIO_PORTA, 11, PUP); /* MCDA3 */
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
the board specific file need added:
|
|
|
|
...
|
|
|
|
#ifdef CONFIG_GENERIC_ATMEL_MCI
|
|
|
|
# include <mmc.h>
|
|
|
|
#endif
|
|
|
|
...
|
|
|
|
#ifdef CONFIG_GENERIC_ATMEL_MCI
|
|
|
|
/* this is a weak define that we are overriding */
|
|
|
|
int board_mmc_init(bd_t *bd)
|
|
|
|
{
|
|
|
|
/* Enable clock */
|
|
|
|
at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_MCI);
|
|
|
|
at91_mci_hw_init();
|
|
|
|
|
|
|
|
/* This calls the atmel_mci_init in gen_atmel_mci.c */
|
|
|
|
return atmel_mci_init((void *)AT91_BASE_MCI);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* this is a weak define that we are overriding */
|
|
|
|
int board_mmc_getcd(struct mmc *mmc)
|
|
|
|
{
|
|
|
|
return !at91_get_gpio_value(CONFIG_SYS_MMC_CD_PIN);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
and the board definition files needs:
|
|
|
|
|
|
|
|
/* SD/MMC card */
|
|
|
|
#define CONFIG_GENERIC_ATMEL_MCI 1
|
|
|
|
#define CONFIG_ATMEL_MCI_PORTB 1 /* Atmel XE-EK uses port B */
|
|
|
|
#define CONFIG_SYS_MMC_CD_PIN AT91_PIN_PC9
|
|
|
|
#define CONFIG_CMD_MMC 1
|