Commit 75305d768d296a07fd02df9af3e5de326df1c72e

Authored by Nicolas Ferre
1 parent a2a571b74a

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>

Showing 3 changed files with 190 additions and 1 deletions Side-by-side Diff

arch/arm/mach-at91/at91sam9g45_devices.c
... ... @@ -15,6 +15,7 @@
15 15 #include <linux/dma-mapping.h>
16 16 #include <linux/platform_device.h>
17 17 #include <linux/i2c-gpio.h>
  18 +#include <linux/atmel-mci.h>
18 19  
19 20 #include <linux/fb.h>
20 21 #include <video/atmel_lcdc.h>
... ... @@ -25,6 +26,7 @@
25 26 #include <mach/at91sam9g45_matrix.h>
26 27 #include <mach/at91sam9_smc.h>
27 28 #include <mach/at_hdmac.h>
  29 +#include <mach/atmel-mci.h>
28 30  
29 31 #include "generic.h"
30 32  
... ... @@ -346,6 +348,169 @@
346 348 }
347 349 #else
348 350 void __init at91_add_device_eth(struct at91_eth_data *data) {}
  351 +#endif
  352 +
  353 +
  354 +/* --------------------------------------------------------------------
  355 + * MMC / SD
  356 + * -------------------------------------------------------------------- */
  357 +
  358 +#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
  359 +static u64 mmc_dmamask = DMA_BIT_MASK(32);
  360 +static struct mci_platform_data mmc0_data, mmc1_data;
  361 +
  362 +static struct resource mmc0_resources[] = {
  363 + [0] = {
  364 + .start = AT91SAM9G45_BASE_MCI0,
  365 + .end = AT91SAM9G45_BASE_MCI0 + SZ_16K - 1,
  366 + .flags = IORESOURCE_MEM,
  367 + },
  368 + [1] = {
  369 + .start = AT91SAM9G45_ID_MCI0,
  370 + .end = AT91SAM9G45_ID_MCI0,
  371 + .flags = IORESOURCE_IRQ,
  372 + },
  373 +};
  374 +
  375 +static struct platform_device at91sam9g45_mmc0_device = {
  376 + .name = "atmel_mci",
  377 + .id = 0,
  378 + .dev = {
  379 + .dma_mask = &mmc_dmamask,
  380 + .coherent_dma_mask = DMA_BIT_MASK(32),
  381 + .platform_data = &mmc0_data,
  382 + },
  383 + .resource = mmc0_resources,
  384 + .num_resources = ARRAY_SIZE(mmc0_resources),
  385 +};
  386 +
  387 +static struct resource mmc1_resources[] = {
  388 + [0] = {
  389 + .start = AT91SAM9G45_BASE_MCI1,
  390 + .end = AT91SAM9G45_BASE_MCI1 + SZ_16K - 1,
  391 + .flags = IORESOURCE_MEM,
  392 + },
  393 + [1] = {
  394 + .start = AT91SAM9G45_ID_MCI1,
  395 + .end = AT91SAM9G45_ID_MCI1,
  396 + .flags = IORESOURCE_IRQ,
  397 + },
  398 +};
  399 +
  400 +static struct platform_device at91sam9g45_mmc1_device = {
  401 + .name = "atmel_mci",
  402 + .id = 1,
  403 + .dev = {
  404 + .dma_mask = &mmc_dmamask,
  405 + .coherent_dma_mask = DMA_BIT_MASK(32),
  406 + .platform_data = &mmc1_data,
  407 + },
  408 + .resource = mmc1_resources,
  409 + .num_resources = ARRAY_SIZE(mmc1_resources),
  410 +};
  411 +
  412 +/* Consider only one slot : slot 0 */
  413 +void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
  414 +{
  415 +
  416 + if (!data)
  417 + return;
  418 +
  419 + /* Must have at least one usable slot */
  420 + if (!data->slot[0].bus_width)
  421 + return;
  422 +
  423 +#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
  424 + {
  425 + struct at_dma_slave *atslave;
  426 + struct mci_dma_data *alt_atslave;
  427 +
  428 + alt_atslave = kzalloc(sizeof(struct mci_dma_data), GFP_KERNEL);
  429 + atslave = &alt_atslave->sdata;
  430 +
  431 + /* DMA slave channel configuration */
  432 + atslave->dma_dev = &at_hdmac_device.dev;
  433 + atslave->reg_width = AT_DMA_SLAVE_WIDTH_32BIT;
  434 + atslave->cfg = ATC_FIFOCFG_HALFFIFO
  435 + | ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW;
  436 + atslave->ctrla = ATC_SCSIZE_16 | ATC_DCSIZE_16;
  437 + if (mmc_id == 0) /* MCI0 */
  438 + atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI0)
  439 + | ATC_DST_PER(AT_DMA_ID_MCI0);
  440 +
  441 + else /* MCI1 */
  442 + atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI1)
  443 + | ATC_DST_PER(AT_DMA_ID_MCI1);
  444 +
  445 + data->dma_slave = alt_atslave;
  446 + }
  447 +#endif
  448 +
  449 +
  450 + /* input/irq */
  451 + if (data->slot[0].detect_pin) {
  452 + at91_set_gpio_input(data->slot[0].detect_pin, 1);
  453 + at91_set_deglitch(data->slot[0].detect_pin, 1);
  454 + }
  455 + if (data->slot[0].wp_pin)
  456 + at91_set_gpio_input(data->slot[0].wp_pin, 1);
  457 +
  458 + if (mmc_id == 0) { /* MCI0 */
  459 +
  460 + /* CLK */
  461 + at91_set_A_periph(AT91_PIN_PA0, 0);
  462 +
  463 + /* CMD */
  464 + at91_set_A_periph(AT91_PIN_PA1, 1);
  465 +
  466 + /* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */
  467 + at91_set_A_periph(AT91_PIN_PA2, 1);
  468 + if (data->slot[0].bus_width == 4) {
  469 + at91_set_A_periph(AT91_PIN_PA3, 1);
  470 + at91_set_A_periph(AT91_PIN_PA4, 1);
  471 + at91_set_A_periph(AT91_PIN_PA5, 1);
  472 + if (data->slot[0].bus_width == 8) {
  473 + at91_set_A_periph(AT91_PIN_PA6, 1);
  474 + at91_set_A_periph(AT91_PIN_PA7, 1);
  475 + at91_set_A_periph(AT91_PIN_PA8, 1);
  476 + at91_set_A_periph(AT91_PIN_PA9, 1);
  477 + }
  478 + }
  479 +
  480 + mmc0_data = *data;
  481 + at91_clock_associate("mci0_clk", &at91sam9g45_mmc0_device.dev, "mci_clk");
  482 + platform_device_register(&at91sam9g45_mmc0_device);
  483 +
  484 + } else { /* MCI1 */
  485 +
  486 + /* CLK */
  487 + at91_set_A_periph(AT91_PIN_PA31, 0);
  488 +
  489 + /* CMD */
  490 + at91_set_A_periph(AT91_PIN_PA22, 1);
  491 +
  492 + /* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */
  493 + at91_set_A_periph(AT91_PIN_PA23, 1);
  494 + if (data->slot[0].bus_width == 4) {
  495 + at91_set_A_periph(AT91_PIN_PA24, 1);
  496 + at91_set_A_periph(AT91_PIN_PA25, 1);
  497 + at91_set_A_periph(AT91_PIN_PA26, 1);
  498 + if (data->slot[0].bus_width == 8) {
  499 + at91_set_A_periph(AT91_PIN_PA27, 1);
  500 + at91_set_A_periph(AT91_PIN_PA28, 1);
  501 + at91_set_A_periph(AT91_PIN_PA29, 1);
  502 + at91_set_A_periph(AT91_PIN_PA30, 1);
  503 + }
  504 + }
  505 +
  506 + mmc1_data = *data;
  507 + at91_clock_associate("mci1_clk", &at91sam9g45_mmc1_device.dev, "mci_clk");
  508 + platform_device_register(&at91sam9g45_mmc1_device);
  509 +
  510 + }
  511 +}
  512 +#else
  513 +void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
349 514 #endif
350 515  
351 516  
arch/arm/mach-at91/board-sam9m10g45ek.c
... ... @@ -24,7 +24,9 @@
24 24 #include <linux/input.h>
25 25 #include <linux/leds.h>
26 26 #include <linux/clk.h>
  27 +#include <linux/atmel-mci.h>
27 28  
  29 +#include <mach/hardware.h>
28 30 #include <video/atmel_lcdc.h>
29 31  
30 32 #include <asm/setup.h>
... ... @@ -98,6 +100,25 @@
98 100  
99 101  
100 102 /*
  103 + * MCI (SD/MMC)
  104 + */
  105 +static struct mci_platform_data __initdata mci0_data = {
  106 + .slot[0] = {
  107 + .bus_width = 4,
  108 + .detect_pin = AT91_PIN_PD10,
  109 + },
  110 +};
  111 +
  112 +static struct mci_platform_data __initdata mci1_data = {
  113 + .slot[0] = {
  114 + .bus_width = 4,
  115 + .detect_pin = AT91_PIN_PD11,
  116 + .wp_pin = AT91_PIN_PD29,
  117 + },
  118 +};
  119 +
  120 +
  121 +/*
101 122 * MACB Ethernet device
102 123 */
103 124 static struct at91_eth_data __initdata ek_macb_data = {
... ... @@ -380,6 +401,9 @@
380 401 at91_add_device_usba(&ek_usba_udc_data);
381 402 /* SPI */
382 403 at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
  404 + /* MMC */
  405 + at91_add_device_mci(0, &mci0_data);
  406 + at91_add_device_mci(1, &mci1_data);
383 407 /* Ethernet */
384 408 at91_add_device_eth(&ek_macb_data);
385 409 /* NAND */
drivers/mmc/host/Kconfig
... ... @@ -237,7 +237,7 @@
237 237  
238 238 config MMC_ATMELMCI_DMA
239 239 bool "Atmel MCI DMA support (EXPERIMENTAL)"
240   - depends on MMC_ATMELMCI && AVR32 && DMA_ENGINE && EXPERIMENTAL
  240 + depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE && EXPERIMENTAL
241 241 help
242 242 Say Y here to have the Atmel MCI driver use a DMA engine to
243 243 do data transfers and thus increase the throughput and