1*1592ef85SReinhard MeyerHow to use SD/MMC cards with Atmel SoCs having MCI hardware 2*1592ef85SReinhard Meyer----------------------------------------------------------- 3*1592ef85SReinhard Meyer2010-08-16 Reinhard Meyer <reinhard.meyer@emk-elektronik.de> 4*1592ef85SReinhard Meyer 5*1592ef85SReinhard MeyerThis is a new approach to use Atmel MCI hardware with the 6*1592ef85SReinhard Meyergeneral MMC framework. Therefore it benefits from that 7*1592ef85SReinhard Meyerframework's abilities to handle SDHC Cards and the ability 8*1592ef85SReinhard Meyerto write blocks. 9*1592ef85SReinhard Meyer 10*1592ef85SReinhard Meyer- AT91SAM9XE512 (tested, will definitely work with XE128 and XE256) 11*1592ef85SReinhard Meyer- AT91SAM9260 (not tested, but MCI is to AT91SAM9XE) 12*1592ef85SReinhard Meyer- AT91SAM9G20 (not tested, should work) 13*1592ef85SReinhard Meyer 14*1592ef85SReinhard MeyerIt should work with all other ATMEL devices that have MCI, 15*1592ef85SReinhard Meyerincluding AVR32. 16*1592ef85SReinhard Meyer 17*1592ef85SReinhard MeyerThe generic driver does NOT assign port pins to the MCI block 18*1592ef85SReinhard Meyernor does it start the MCI clock. This has to be handled in a 19*1592ef85SReinhard Meyerboard/SoC specific manner before the driver is initialized: 20*1592ef85SReinhard Meyer 21*1592ef85SReinhard Meyerexample: this is added to at91sam9260_devices.c: 22*1592ef85SReinhard Meyer 23*1592ef85SReinhard Meyer#if defined(CONFIG_ATMEL_MCI) || defined(CONFIG_GENERIC_ATMEL_MCI) 24*1592ef85SReinhard Meyervoid at91_mci_hw_init(void) 25*1592ef85SReinhard Meyer{ 26*1592ef85SReinhard Meyer at91_set_a_periph(AT91_PIO_PORTA, 8, PUP); /* MCCK */ 27*1592ef85SReinhard Meyer#if defined(CONFIG_ATMEL_MCI_PORTB) 28*1592ef85SReinhard Meyer at91_set_b_periph(AT91_PIO_PORTA, 1, PUP); /* MCCDB */ 29*1592ef85SReinhard Meyer at91_set_b_periph(AT91_PIO_PORTA, 0, PUP); /* MCDB0 */ 30*1592ef85SReinhard Meyer at91_set_b_periph(AT91_PIO_PORTA, 5, PUP); /* MCDB1 */ 31*1592ef85SReinhard Meyer at91_set_b_periph(AT91_PIO_PORTA, 4, PUP); /* MCDB2 */ 32*1592ef85SReinhard Meyer at91_set_b_periph(AT91_PIO_PORTA, 3, PUP); /* MCDB3 */ 33*1592ef85SReinhard Meyer#else 34*1592ef85SReinhard Meyer at91_set_a_periph(AT91_PIO_PORTA, 7, PUP); /* MCCDA */ 35*1592ef85SReinhard Meyer at91_set_a_periph(AT91_PIO_PORTA, 6, PUP); /* MCDA0 */ 36*1592ef85SReinhard Meyer at91_set_a_periph(AT91_PIO_PORTA, 9, PUP); /* MCDA1 */ 37*1592ef85SReinhard Meyer at91_set_a_periph(AT91_PIO_PORTA, 10, PUP); /* MCDA2 */ 38*1592ef85SReinhard Meyer at91_set_a_periph(AT91_PIO_PORTA, 11, PUP); /* MCDA3 */ 39*1592ef85SReinhard Meyer#endif 40*1592ef85SReinhard Meyer} 41*1592ef85SReinhard Meyer#endif 42*1592ef85SReinhard Meyer 43*1592ef85SReinhard Meyerthe board specific file need added: 44*1592ef85SReinhard Meyer... 45*1592ef85SReinhard Meyer#ifdef CONFIG_GENERIC_ATMEL_MCI 46*1592ef85SReinhard Meyer# include <mmc.h> 47*1592ef85SReinhard Meyer#endif 48*1592ef85SReinhard Meyer... 49*1592ef85SReinhard Meyer#ifdef CONFIG_GENERIC_ATMEL_MCI 50*1592ef85SReinhard Meyer/* this is a weak define that we are overriding */ 51*1592ef85SReinhard Meyerint board_mmc_init(bd_t *bd) 52*1592ef85SReinhard Meyer{ 53*1592ef85SReinhard Meyer /* Enable clock */ 54*1592ef85SReinhard Meyer at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_MCI); 55*1592ef85SReinhard Meyer at91_mci_hw_init(); 56*1592ef85SReinhard Meyer 57*1592ef85SReinhard Meyer /* This calls the atmel_mci_init in gen_atmel_mci.c */ 58*1592ef85SReinhard Meyer return atmel_mci_init((void *)AT91_BASE_MCI); 59*1592ef85SReinhard Meyer} 60*1592ef85SReinhard Meyer 61*1592ef85SReinhard Meyer/* this is a weak define that we are overriding */ 62*1592ef85SReinhard Meyerint board_mmc_getcd(u8 *cd, struct mmc *mmc) 63*1592ef85SReinhard Meyer{ 64*1592ef85SReinhard Meyer /* 65*1592ef85SReinhard Meyer * the only currently existing use of this function 66*1592ef85SReinhard Meyer * (fsl_esdhc.c) suggests this function must return 67*1592ef85SReinhard Meyer * *cs = TRUE if a card is NOT detected -> in most 68*1592ef85SReinhard Meyer * cases the value of the pin when the detect switch 69*1592ef85SReinhard Meyer * closes to GND 70*1592ef85SReinhard Meyer */ 71*1592ef85SReinhard Meyer *cd = at91_get_gpio_value (CONFIG_SYS_MMC_CD_PIN) ? 1 : 0; 72*1592ef85SReinhard Meyer return 0; 73*1592ef85SReinhard Meyer} 74*1592ef85SReinhard Meyer 75*1592ef85SReinhard Meyer#endif 76*1592ef85SReinhard Meyer 77*1592ef85SReinhard Meyerand the board definition files needs: 78*1592ef85SReinhard Meyer 79*1592ef85SReinhard Meyer/* SD/MMC card */ 80*1592ef85SReinhard Meyer#define CONFIG_MMC 1 81*1592ef85SReinhard Meyer#define CONFIG_GENERIC_MMC 1 82*1592ef85SReinhard Meyer#define CONFIG_GENERIC_ATMEL_MCI 1 83*1592ef85SReinhard Meyer#define CONFIG_ATMEL_MCI_PORTB 1 /* Atmel XE-EK uses port B */ 84*1592ef85SReinhard Meyer#define CONFIG_SYS_MMC_CD_PIN AT91_PIN_PC9 85*1592ef85SReinhard Meyer#define CONFIG_CMD_MMC 1 86*1592ef85SReinhard Meyer 87