--- arch/avr32/boards/atngw/setup.c | 7 ++++ arch/avr32/mach-at32ap/at32ap7000.c | 13 +++++++-- drivers/mmc/atmel-mci.c | 49 ++++++++++++++++++++++++++++++++++ include/asm-avr32/arch-at32ap/board.h | 7 ++++ 4 files changed, 72 insertions(+), 4 deletions(-) Index: linux-2.6.18-avr32/arch/avr32/boards/atngw/setup.c =================================================================== --- linux-2.6.18-avr32.orig/arch/avr32/boards/atngw/setup.c 2007-01-15 10:24:38.000000000 +0100 +++ linux-2.6.18-avr32/arch/avr32/boards/atngw/setup.c 2007-01-15 10:25:04.000000000 +0100 @@ -35,6 +35,11 @@ static struct spi_board_info spi_board_i }, }; +static struct mmci_platform_data __initdata mmci0_data = { + .detect_pin = GPIO_PIN_PC(25), + .wp_pin = GPIO_PIN_PE(0), +}; + static int __init parse_tag_ethernet(struct tag *tag) { int i; @@ -72,7 +77,7 @@ static int __init atngw_init(void) spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); at32_add_device_spi(0); - at32_add_device_mmci(0); + at32_add_device_mmci(0, &mmci0_data); at32_add_device_usb(0); return 0; Index: linux-2.6.18-avr32/arch/avr32/mach-at32ap/at32ap7000.c =================================================================== --- linux-2.6.18-avr32.orig/arch/avr32/mach-at32ap/at32ap7000.c 2007-01-15 10:24:38.000000000 +0100 +++ linux-2.6.18-avr32/arch/avr32/mach-at32ap/at32ap7000.c 2007-01-15 10:25:04.000000000 +0100 @@ -749,14 +749,16 @@ at32_add_device_eth(unsigned int id, str /* -------------------------------------------------------------------- * MMC * -------------------------------------------------------------------- */ +static struct mmci_platform_data mmci0_data; static struct resource mmci0_resource[] = { PBMEM(0xfff02400), IRQ(28), }; -DEFINE_DEV(mmci, 0); +DEFINE_DEV_DATA(mmci, 0); DEV_CLK(mck, mmci0, pbb, 9); -struct platform_device *__init at32_add_device_mmci(unsigned int id) +struct platform_device *__init +at32_add_device_mmci(unsigned int id, struct mmci_platform_data *data) { struct platform_device *pdev; @@ -774,6 +776,13 @@ struct platform_device *__init at32_add_ return NULL; } + if (data && data->detect_pin != GPIO_PIO_NONE) + at32_select_gpio(data->detect_pin, 0); + if (data && data->wp_pin != GPIO_PIO_NONE) + at32_select_gpio(data->wp_pin, 0); + + memcpy(pdev->dev.platform_data, data, + sizeof(struct mmci_platform_data)); platform_device_register(pdev); return pdev; } Index: linux-2.6.18-avr32/include/asm-avr32/arch-at32ap/board.h =================================================================== --- linux-2.6.18-avr32.orig/include/asm-avr32/arch-at32ap/board.h 2007-01-15 10:24:38.000000000 +0100 +++ linux-2.6.18-avr32/include/asm-avr32/arch-at32ap/board.h 2007-01-15 10:25:04.000000000 +0100 @@ -24,7 +24,12 @@ struct eth_platform_data { struct platform_device * at32_add_device_eth(unsigned int id, struct eth_platform_data *data); -struct platform_device *at32_add_device_mmci(unsigned int id); +struct mmci_platform_data { + unsigned int detect_pin; + unsigned int wp_pin; +}; +struct platform_device * +at32_add_device_mmci(unsigned int id, struct mmci_platform_data *data); struct platform_device *at32_add_device_spi(unsigned int id); struct platform_device *at32_add_device_twi(unsigned int id); Index: linux-2.6.18-avr32/drivers/mmc/atmel-mci.c =================================================================== --- linux-2.6.18-avr32.orig/drivers/mmc/atmel-mci.c 2007-01-15 10:23:19.000000000 +0100 +++ linux-2.6.18-avr32/drivers/mmc/atmel-mci.c 2007-01-15 10:27:37.000000000 +0100 @@ -22,6 +22,9 @@ #include #include +#include +#include +#include #include "atmel-mci.h" @@ -68,9 +71,13 @@ struct atmel_mci { unsigned long completed_events; u32 error_status; + int present; + unsigned int wp_present:1; + unsigned long bus_hz; unsigned long mapbase; struct clk *mck; + struct mmci_platform_data *board; struct platform_device *pdev; }; @@ -626,6 +633,7 @@ static int __devinit atmci_probe(struct if (!host->regs) goto out_disable_clk; + host->board = pdev->dev.platform_data; host->bus_hz = clk_get_rate(host->mck); host->mapbase = regs->start; @@ -641,6 +649,32 @@ static int __devinit atmci_probe(struct if (ret) goto out_unmap; + if (host->board && host->board->detect_pin != GPIO_PIO_NONE) { + ret = gpio_request(host->board->detect_pin, "mmc_detect"); + if (ret) { + printk(KERN_WARNING "%s: no detect pin available (%d)\n", + mmc_hostname(host->mmc), ret); + host->present = -1; + } else { + host->present = !gpio_get_value(host->board->detect_pin); + } + } else { + host->present = -1; + } + + if (host->board && host->board->wp_pin != GPIO_PIO_NONE) { + ret = gpio_request(host->board->wp_pin, "mmc_wp"); + if (ret) { + printk(KERN_WARNING "%s: no WP pin available (%d)\n", + mmc_hostname(host->mmc), ret); + host->wp_present = 0; + } else { + host->wp_present = 1; + } + } else { + host->wp_present = 0; + } + /* TODO: Get this information from platform data */ ret = -ENOMEM; host->dma.req.req.dmac = find_dma_controller(0); @@ -677,6 +711,10 @@ static int __devinit atmci_probe(struct return 0; out_free_irq: + if (host->present != -1) + gpio_free(host->board->detect_pin); + if (host->board->wp_pin != GPIO_PIO_NONE) + gpio_free(host->board->wp_pin); free_irq(irq, mmc); out_unmap: iounmap(host->regs); @@ -701,6 +739,17 @@ static int __devexit atmci_remove(struct mci_writel(host, CR, MCI_BIT(MCIDIS)); mci_readl(host, SR); + if (host->dma.req.req.channel) + dma_release_channel(host->dma.req.req.dmac, + host->dma.req.req.channel); + + if (host->present != -1) { + cancel_delayed_work(&host->mmc->detect); + gpio_free(host->board->detect_pin); + } + if (host->board->wp_pin != GPIO_PIO_NONE) + gpio_free(host->board->wp_pin); + free_irq(platform_get_irq(pdev, 0), host->mmc); iounmap(host->regs);