at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board
This adds the support of atmel-mci sd/mmc driver in at91sam9g45 devices and board files. This also configures the DMA controller slave interface for at_hdmac dmaengine driver. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
This commit is contained in:
parent
a2a571b74a
commit
75305d768d
3 changed files with 190 additions and 1 deletions
|
@ -15,6 +15,7 @@
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/i2c-gpio.h>
|
#include <linux/i2c-gpio.h>
|
||||||
|
#include <linux/atmel-mci.h>
|
||||||
|
|
||||||
#include <linux/fb.h>
|
#include <linux/fb.h>
|
||||||
#include <video/atmel_lcdc.h>
|
#include <video/atmel_lcdc.h>
|
||||||
|
@ -25,6 +26,7 @@
|
||||||
#include <mach/at91sam9g45_matrix.h>
|
#include <mach/at91sam9g45_matrix.h>
|
||||||
#include <mach/at91sam9_smc.h>
|
#include <mach/at91sam9_smc.h>
|
||||||
#include <mach/at_hdmac.h>
|
#include <mach/at_hdmac.h>
|
||||||
|
#include <mach/atmel-mci.h>
|
||||||
|
|
||||||
#include "generic.h"
|
#include "generic.h"
|
||||||
|
|
||||||
|
@ -349,6 +351,169 @@ void __init at91_add_device_eth(struct at91_eth_data *data) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------
|
||||||
|
* MMC / SD
|
||||||
|
* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
|
||||||
|
static u64 mmc_dmamask = DMA_BIT_MASK(32);
|
||||||
|
static struct mci_platform_data mmc0_data, mmc1_data;
|
||||||
|
|
||||||
|
static struct resource mmc0_resources[] = {
|
||||||
|
[0] = {
|
||||||
|
.start = AT91SAM9G45_BASE_MCI0,
|
||||||
|
.end = AT91SAM9G45_BASE_MCI0 + SZ_16K - 1,
|
||||||
|
.flags = IORESOURCE_MEM,
|
||||||
|
},
|
||||||
|
[1] = {
|
||||||
|
.start = AT91SAM9G45_ID_MCI0,
|
||||||
|
.end = AT91SAM9G45_ID_MCI0,
|
||||||
|
.flags = IORESOURCE_IRQ,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device at91sam9g45_mmc0_device = {
|
||||||
|
.name = "atmel_mci",
|
||||||
|
.id = 0,
|
||||||
|
.dev = {
|
||||||
|
.dma_mask = &mmc_dmamask,
|
||||||
|
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||||
|
.platform_data = &mmc0_data,
|
||||||
|
},
|
||||||
|
.resource = mmc0_resources,
|
||||||
|
.num_resources = ARRAY_SIZE(mmc0_resources),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct resource mmc1_resources[] = {
|
||||||
|
[0] = {
|
||||||
|
.start = AT91SAM9G45_BASE_MCI1,
|
||||||
|
.end = AT91SAM9G45_BASE_MCI1 + SZ_16K - 1,
|
||||||
|
.flags = IORESOURCE_MEM,
|
||||||
|
},
|
||||||
|
[1] = {
|
||||||
|
.start = AT91SAM9G45_ID_MCI1,
|
||||||
|
.end = AT91SAM9G45_ID_MCI1,
|
||||||
|
.flags = IORESOURCE_IRQ,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device at91sam9g45_mmc1_device = {
|
||||||
|
.name = "atmel_mci",
|
||||||
|
.id = 1,
|
||||||
|
.dev = {
|
||||||
|
.dma_mask = &mmc_dmamask,
|
||||||
|
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||||
|
.platform_data = &mmc1_data,
|
||||||
|
},
|
||||||
|
.resource = mmc1_resources,
|
||||||
|
.num_resources = ARRAY_SIZE(mmc1_resources),
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Consider only one slot : slot 0 */
|
||||||
|
void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Must have at least one usable slot */
|
||||||
|
if (!data->slot[0].bus_width)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
|
||||||
|
{
|
||||||
|
struct at_dma_slave *atslave;
|
||||||
|
struct mci_dma_data *alt_atslave;
|
||||||
|
|
||||||
|
alt_atslave = kzalloc(sizeof(struct mci_dma_data), GFP_KERNEL);
|
||||||
|
atslave = &alt_atslave->sdata;
|
||||||
|
|
||||||
|
/* DMA slave channel configuration */
|
||||||
|
atslave->dma_dev = &at_hdmac_device.dev;
|
||||||
|
atslave->reg_width = AT_DMA_SLAVE_WIDTH_32BIT;
|
||||||
|
atslave->cfg = ATC_FIFOCFG_HALFFIFO
|
||||||
|
| ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW;
|
||||||
|
atslave->ctrla = ATC_SCSIZE_16 | ATC_DCSIZE_16;
|
||||||
|
if (mmc_id == 0) /* MCI0 */
|
||||||
|
atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI0)
|
||||||
|
| ATC_DST_PER(AT_DMA_ID_MCI0);
|
||||||
|
|
||||||
|
else /* MCI1 */
|
||||||
|
atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI1)
|
||||||
|
| ATC_DST_PER(AT_DMA_ID_MCI1);
|
||||||
|
|
||||||
|
data->dma_slave = alt_atslave;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* input/irq */
|
||||||
|
if (data->slot[0].detect_pin) {
|
||||||
|
at91_set_gpio_input(data->slot[0].detect_pin, 1);
|
||||||
|
at91_set_deglitch(data->slot[0].detect_pin, 1);
|
||||||
|
}
|
||||||
|
if (data->slot[0].wp_pin)
|
||||||
|
at91_set_gpio_input(data->slot[0].wp_pin, 1);
|
||||||
|
|
||||||
|
if (mmc_id == 0) { /* MCI0 */
|
||||||
|
|
||||||
|
/* CLK */
|
||||||
|
at91_set_A_periph(AT91_PIN_PA0, 0);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
if (data->slot[0].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);
|
||||||
|
if (data->slot[0].bus_width == 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mmc0_data = *data;
|
||||||
|
at91_clock_associate("mci0_clk", &at91sam9g45_mmc0_device.dev, "mci_clk");
|
||||||
|
platform_device_register(&at91sam9g45_mmc0_device);
|
||||||
|
|
||||||
|
} else { /* 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);
|
||||||
|
if (data->slot[0].bus_width == 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);
|
||||||
|
if (data->slot[0].bus_width == 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mmc1_data = *data;
|
||||||
|
at91_clock_associate("mci1_clk", &at91sam9g45_mmc1_device.dev, "mci_clk");
|
||||||
|
platform_device_register(&at91sam9g45_mmc1_device);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* --------------------------------------------------------------------
|
/* --------------------------------------------------------------------
|
||||||
* NAND / SmartMedia
|
* NAND / SmartMedia
|
||||||
* -------------------------------------------------------------------- */
|
* -------------------------------------------------------------------- */
|
||||||
|
|
|
@ -24,7 +24,9 @@
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <linux/leds.h>
|
#include <linux/leds.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
|
#include <linux/atmel-mci.h>
|
||||||
|
|
||||||
|
#include <mach/hardware.h>
|
||||||
#include <video/atmel_lcdc.h>
|
#include <video/atmel_lcdc.h>
|
||||||
|
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
|
@ -97,6 +99,25 @@ static struct spi_board_info ek_spi_devices[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MCI (SD/MMC)
|
||||||
|
*/
|
||||||
|
static struct mci_platform_data __initdata mci0_data = {
|
||||||
|
.slot[0] = {
|
||||||
|
.bus_width = 4,
|
||||||
|
.detect_pin = AT91_PIN_PD10,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct mci_platform_data __initdata mci1_data = {
|
||||||
|
.slot[0] = {
|
||||||
|
.bus_width = 4,
|
||||||
|
.detect_pin = AT91_PIN_PD11,
|
||||||
|
.wp_pin = AT91_PIN_PD29,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MACB Ethernet device
|
* MACB Ethernet device
|
||||||
*/
|
*/
|
||||||
|
@ -380,6 +401,9 @@ static void __init ek_board_init(void)
|
||||||
at91_add_device_usba(&ek_usba_udc_data);
|
at91_add_device_usba(&ek_usba_udc_data);
|
||||||
/* SPI */
|
/* SPI */
|
||||||
at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
|
at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
|
||||||
|
/* MMC */
|
||||||
|
at91_add_device_mci(0, &mci0_data);
|
||||||
|
at91_add_device_mci(1, &mci1_data);
|
||||||
/* Ethernet */
|
/* Ethernet */
|
||||||
at91_add_device_eth(&ek_macb_data);
|
at91_add_device_eth(&ek_macb_data);
|
||||||
/* NAND */
|
/* NAND */
|
||||||
|
|
|
@ -237,7 +237,7 @@ endchoice
|
||||||
|
|
||||||
config MMC_ATMELMCI_DMA
|
config MMC_ATMELMCI_DMA
|
||||||
bool "Atmel MCI DMA support (EXPERIMENTAL)"
|
bool "Atmel MCI DMA support (EXPERIMENTAL)"
|
||||||
depends on MMC_ATMELMCI && AVR32 && DMA_ENGINE && EXPERIMENTAL
|
depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE && EXPERIMENTAL
|
||||||
help
|
help
|
||||||
Say Y here to have the Atmel MCI driver use a DMA engine to
|
Say Y here to have the Atmel MCI driver use a DMA engine to
|
||||||
do data transfers and thus increase the throughput and
|
do data transfers and thus increase the throughput and
|
||||||
|
|
Loading…
Reference in a new issue