Commit 75305d768d296a07fd02df9af3e5de326df1c72e
1 parent
a2a571b74a
Exists in
master
and in
7 other branches
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 |