aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/avr32/boards/atngw100/setup.c7
-rw-r--r--arch/avr32/boards/atstk1000/atstk1002.c3
-rw-r--r--arch/avr32/mach-at32ap/at32ap700x.c30
-rw-r--r--drivers/mmc/host/Kconfig10
-rw-r--r--drivers/mmc/host/Makefile1
-rw-r--r--drivers/mmc/host/atmel-mci-regs.h91
-rw-r--r--drivers/mmc/host/atmel-mci.c981
-rw-r--r--include/asm-avr32/arch-at32ap/board.h6
-rw-r--r--include/asm-avr32/atmel-mci.h9
9 files changed, 1132 insertions, 6 deletions
diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c
index a51bb9fb3c8..c7fe94d03a1 100644
--- a/arch/avr32/boards/atngw100/setup.c
+++ b/arch/avr32/boards/atngw100/setup.c
@@ -19,6 +19,7 @@
19#include <linux/leds.h> 19#include <linux/leds.h>
20#include <linux/spi/spi.h> 20#include <linux/spi/spi.h>
21 21
22#include <asm/atmel-mci.h>
22#include <asm/io.h> 23#include <asm/io.h>
23#include <asm/setup.h> 24#include <asm/setup.h>
24 25
@@ -51,6 +52,11 @@ static struct spi_board_info spi0_board_info[] __initdata = {
51 }, 52 },
52}; 53};
53 54
55static struct mci_platform_data __initdata mci0_data = {
56 .detect_pin = GPIO_PIN_PC(25),
57 .wp_pin = GPIO_PIN_PE(0),
58};
59
54/* 60/*
55 * The next two functions should go away as the boot loader is 61 * The next two functions should go away as the boot loader is
56 * supposed to initialize the macb address registers with a valid 62 * supposed to initialize the macb address registers with a valid
@@ -170,6 +176,7 @@ static int __init atngw100_init(void)
170 set_hw_addr(at32_add_device_eth(1, &eth_data[1])); 176 set_hw_addr(at32_add_device_eth(1, &eth_data[1]));
171 177
172 at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); 178 at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
179 at32_add_device_mci(0, &mci0_data);
173 at32_add_device_usba(0, NULL); 180 at32_add_device_usba(0, NULL);
174 181
175 for (i = 0; i < ARRAY_SIZE(ngw_leds); i++) { 182 for (i = 0; i < ARRAY_SIZE(ngw_leds); i++) {
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c
index 86b363c1c25..e11659b732f 100644
--- a/arch/avr32/boards/atstk1000/atstk1002.c
+++ b/arch/avr32/boards/atstk1000/atstk1002.c
@@ -234,6 +234,9 @@ static int __init atstk1002_init(void)
234#ifdef CONFIG_BOARD_ATSTK100X_SPI1 234#ifdef CONFIG_BOARD_ATSTK100X_SPI1
235 at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); 235 at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
236#endif 236#endif
237#ifndef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
238 at32_add_device_mci(0, NULL);
239#endif
237#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM 240#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
238 set_hw_addr(at32_add_device_eth(1, &eth_data[1])); 241 set_hw_addr(at32_add_device_eth(1, &eth_data[1]));
239#else 242#else
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index 07b21b121ee..021d5121718 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -14,6 +14,7 @@
14#include <linux/spi/spi.h> 14#include <linux/spi/spi.h>
15#include <linux/usb/atmel_usba_udc.h> 15#include <linux/usb/atmel_usba_udc.h>
16 16
17#include <asm/atmel-mci.h>
17#include <asm/io.h> 18#include <asm/io.h>
18#include <asm/irq.h> 19#include <asm/irq.h>
19 20
@@ -1278,20 +1279,32 @@ static struct clk atmel_mci0_pclk = {
1278 .index = 9, 1279 .index = 9,
1279}; 1280};
1280 1281
1281struct platform_device *__init at32_add_device_mci(unsigned int id) 1282struct platform_device *__init
1283at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
1282{ 1284{
1283 struct platform_device *pdev; 1285 struct mci_platform_data _data;
1286 struct platform_device *pdev;
1287 struct dw_dma_slave *dws;
1284 1288
1285 if (id != 0) 1289 if (id != 0)
1286 return NULL; 1290 return NULL;
1287 1291
1288 pdev = platform_device_alloc("atmel_mci", id); 1292 pdev = platform_device_alloc("atmel_mci", id);
1289 if (!pdev) 1293 if (!pdev)
1290 return NULL; 1294 goto fail;
1291 1295
1292 if (platform_device_add_resources(pdev, atmel_mci0_resource, 1296 if (platform_device_add_resources(pdev, atmel_mci0_resource,
1293 ARRAY_SIZE(atmel_mci0_resource))) 1297 ARRAY_SIZE(atmel_mci0_resource)))
1294 goto err_add_resources; 1298 goto fail;
1299
1300 if (!data) {
1301 data = &_data;
1302 memset(data, 0, sizeof(struct mci_platform_data));
1303 }
1304
1305 if (platform_device_add_data(pdev, data,
1306 sizeof(struct mci_platform_data)))
1307 goto fail;
1295 1308
1296 select_peripheral(PA(10), PERIPH_A, 0); /* CLK */ 1309 select_peripheral(PA(10), PERIPH_A, 0); /* CLK */
1297 select_peripheral(PA(11), PERIPH_A, 0); /* CMD */ 1310 select_peripheral(PA(11), PERIPH_A, 0); /* CMD */
@@ -1300,12 +1313,19 @@ struct platform_device *__init at32_add_device_mci(unsigned int id)
1300 select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */ 1313 select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */
1301 select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */ 1314 select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */
1302 1315
1316 if (data) {
1317 if (data->detect_pin != GPIO_PIN_NONE)
1318 at32_select_gpio(data->detect_pin, 0);
1319 if (data->wp_pin != GPIO_PIN_NONE)
1320 at32_select_gpio(data->wp_pin, 0);
1321 }
1322
1303 atmel_mci0_pclk.dev = &pdev->dev; 1323 atmel_mci0_pclk.dev = &pdev->dev;
1304 1324
1305 platform_device_add(pdev); 1325 platform_device_add(pdev);
1306 return pdev; 1326 return pdev;
1307 1327
1308err_add_resources: 1328fail:
1309 platform_device_put(pdev); 1329 platform_device_put(pdev);
1310 return NULL; 1330 return NULL;
1311} 1331}
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index dc88c03662a..198df423435 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -104,6 +104,16 @@ config MMC_AT91
104 104
105 If unsure, say N. 105 If unsure, say N.
106 106
107config MMC_ATMELMCI
108 tristate "Atmel Multimedia Card Interface support"
109 depends on AVR32
110 help
111 This selects the Atmel Multimedia Card Interface driver. If
112 you have an AT32 (AVR32) platform with a Multimedia Card
113 slot, say Y or M here.
114
115 If unsure, say N.
116
107config MMC_IMX 117config MMC_IMX
108 tristate "Motorola i.MX Multimedia Card Interface support" 118 tristate "Motorola i.MX Multimedia Card Interface support"
109 depends on ARCH_IMX 119 depends on ARCH_IMX
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index b3e023bf8c7..2dc9ff23cfb 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MMC_WBSD) += wbsd.o
16obj-$(CONFIG_MMC_AU1X) += au1xmmc.o 16obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
17obj-$(CONFIG_MMC_OMAP) += omap.o 17obj-$(CONFIG_MMC_OMAP) += omap.o
18obj-$(CONFIG_MMC_AT91) += at91_mci.o 18obj-$(CONFIG_MMC_AT91) += at91_mci.o
19obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o
19obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o 20obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o
20obj-$(CONFIG_MMC_SPI) += mmc_spi.o 21obj-$(CONFIG_MMC_SPI) += mmc_spi.o
21obj-$(CONFIG_MMC_S3C) += s3cmci.o 22obj-$(CONFIG_MMC_S3C) += s3cmci.o
diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h
new file mode 100644
index 00000000000..a9a5657706c
--- /dev/null
+++ b/drivers/mmc/host/atmel-mci-regs.h
@@ -0,0 +1,91 @@
1/*
2 * Atmel MultiMedia Card Interface driver
3 *
4 * Copyright (C) 2004-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#ifndef __DRIVERS_MMC_ATMEL_MCI_H__
11#define __DRIVERS_MMC_ATMEL_MCI_H__
12
13/* MCI Register Definitions */
14#define MCI_CR 0x0000 /* Control */
15# define MCI_CR_MCIEN ( 1 << 0) /* MCI Enable */
16# define MCI_CR_MCIDIS ( 1 << 1) /* MCI Disable */
17# define MCI_CR_SWRST ( 1 << 7) /* Software Reset */
18#define MCI_MR 0x0004 /* Mode */
19# define MCI_MR_CLKDIV(x) ((x) << 0) /* Clock Divider */
20# define MCI_MR_RDPROOF ( 1 << 11) /* Read Proof */
21# define MCI_MR_WRPROOF ( 1 << 12) /* Write Proof */
22#define MCI_DTOR 0x0008 /* Data Timeout */
23# define MCI_DTOCYC(x) ((x) << 0) /* Data Timeout Cycles */
24# define MCI_DTOMUL(x) ((x) << 4) /* Data Timeout Multiplier */
25#define MCI_SDCR 0x000c /* SD Card / SDIO */
26# define MCI_SDCSEL_SLOT_A ( 0 << 0) /* Select SD slot A */
27# define MCI_SDCSEL_SLOT_B ( 1 << 0) /* Select SD slot A */
28# define MCI_SDCBUS_1BIT ( 0 << 7) /* 1-bit data bus */
29# define MCI_SDCBUS_4BIT ( 1 << 7) /* 4-bit data bus */
30#define MCI_ARGR 0x0010 /* Command Argument */
31#define MCI_CMDR 0x0014 /* Command */
32# define MCI_CMDR_CMDNB(x) ((x) << 0) /* Command Opcode */
33# define MCI_CMDR_RSPTYP_NONE ( 0 << 6) /* No response */
34# define MCI_CMDR_RSPTYP_48BIT ( 1 << 6) /* 48-bit response */
35# define MCI_CMDR_RSPTYP_136BIT ( 2 << 6) /* 136-bit response */
36# define MCI_CMDR_SPCMD_INIT ( 1 << 8) /* Initialization command */
37# define MCI_CMDR_SPCMD_SYNC ( 2 << 8) /* Synchronized command */
38# define MCI_CMDR_SPCMD_INT ( 4 << 8) /* Interrupt command */
39# define MCI_CMDR_SPCMD_INTRESP ( 5 << 8) /* Interrupt response */
40# define MCI_CMDR_OPDCMD ( 1 << 11) /* Open Drain */
41# define MCI_CMDR_MAXLAT_5CYC ( 0 << 12) /* Max latency 5 cycles */
42# define MCI_CMDR_MAXLAT_64CYC ( 1 << 12) /* Max latency 64 cycles */
43# define MCI_CMDR_START_XFER ( 1 << 16) /* Start data transfer */
44# define MCI_CMDR_STOP_XFER ( 2 << 16) /* Stop data transfer */
45# define MCI_CMDR_TRDIR_WRITE ( 0 << 18) /* Write data */
46# define MCI_CMDR_TRDIR_READ ( 1 << 18) /* Read data */
47# define MCI_CMDR_BLOCK ( 0 << 19) /* Single-block transfer */
48# define MCI_CMDR_MULTI_BLOCK ( 1 << 19) /* Multi-block transfer */
49# define MCI_CMDR_STREAM ( 2 << 19) /* MMC Stream transfer */
50# define MCI_CMDR_SDIO_BYTE ( 4 << 19) /* SDIO Byte transfer */
51# define MCI_CMDR_SDIO_BLOCK ( 5 << 19) /* SDIO Block transfer */
52# define MCI_CMDR_SDIO_SUSPEND ( 1 << 24) /* SDIO Suspend Command */
53# define MCI_CMDR_SDIO_RESUME ( 2 << 24) /* SDIO Resume Command */
54#define MCI_BLKR 0x0018 /* Block */
55# define MCI_BCNT(x) ((x) << 0) /* Data Block Count */
56# define MCI_BLKLEN(x) ((x) << 16) /* Data Block Length */
57#define MCI_RSPR 0x0020 /* Response 0 */
58#define MCI_RSPR1 0x0024 /* Response 1 */
59#define MCI_RSPR2 0x0028 /* Response 2 */
60#define MCI_RSPR3 0x002c /* Response 3 */
61#define MCI_RDR 0x0030 /* Receive Data */
62#define MCI_TDR 0x0034 /* Transmit Data */
63#define MCI_SR 0x0040 /* Status */
64#define MCI_IER 0x0044 /* Interrupt Enable */
65#define MCI_IDR 0x0048 /* Interrupt Disable */
66#define MCI_IMR 0x004c /* Interrupt Mask */
67# define MCI_CMDRDY ( 1 << 0) /* Command Ready */
68# define MCI_RXRDY ( 1 << 1) /* Receiver Ready */
69# define MCI_TXRDY ( 1 << 2) /* Transmitter Ready */
70# define MCI_BLKE ( 1 << 3) /* Data Block Ended */
71# define MCI_DTIP ( 1 << 4) /* Data Transfer In Progress */
72# define MCI_NOTBUSY ( 1 << 5) /* Data Not Busy */
73# define MCI_SDIOIRQA ( 1 << 8) /* SDIO IRQ in slot A */
74# define MCI_SDIOIRQB ( 1 << 9) /* SDIO IRQ in slot B */
75# define MCI_RINDE ( 1 << 16) /* Response Index Error */
76# define MCI_RDIRE ( 1 << 17) /* Response Direction Error */
77# define MCI_RCRCE ( 1 << 18) /* Response CRC Error */
78# define MCI_RENDE ( 1 << 19) /* Response End Bit Error */
79# define MCI_RTOE ( 1 << 20) /* Response Time-Out Error */
80# define MCI_DCRCE ( 1 << 21) /* Data CRC Error */
81# define MCI_DTOE ( 1 << 22) /* Data Time-Out Error */
82# define MCI_OVRE ( 1 << 30) /* RX Overrun Error */
83# define MCI_UNRE ( 1 << 31) /* TX Underrun Error */
84
85/* Register access macros */
86#define mci_readl(port,reg) \
87 __raw_readl((port)->regs + MCI_##reg)
88#define mci_writel(port,reg,value) \
89 __raw_writel((value), (port)->regs + MCI_##reg)
90
91#endif /* __DRIVERS_MMC_ATMEL_MCI_H__ */
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
new file mode 100644
index 00000000000..25d5324ab7e
--- /dev/null
+++ b/drivers/mmc/host/atmel-mci.c
@@ -0,0 +1,981 @@
1/*
2 * Atmel MultiMedia Card Interface driver
3 *
4 * Copyright (C) 2004-2008 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/blkdev.h>
11#include <linux/clk.h>
12#include <linux/device.h>
13#include <linux/init.h>
14#include <linux/interrupt.h>
15#include <linux/ioport.h>
16#include <linux/module.h>
17#include <linux/platform_device.h>
18#include <linux/scatterlist.h>
19
20#include <linux/mmc/host.h>
21
22#include <asm/atmel-mci.h>
23#include <asm/io.h>
24#include <asm/unaligned.h>
25
26#include <asm/arch/board.h>
27#include <asm/arch/gpio.h>
28
29#include "atmel-mci-regs.h"
30
31#define ATMCI_DATA_ERROR_FLAGS (MCI_DCRCE | MCI_DTOE | MCI_OVRE | MCI_UNRE)
32
33enum {
34 EVENT_CMD_COMPLETE = 0,
35 EVENT_DATA_ERROR,
36 EVENT_DATA_COMPLETE,
37 EVENT_STOP_SENT,
38 EVENT_STOP_COMPLETE,
39 EVENT_XFER_COMPLETE,
40};
41
42struct atmel_mci {
43 struct mmc_host *mmc;
44 void __iomem *regs;
45
46 struct scatterlist *sg;
47 unsigned int pio_offset;
48
49 struct mmc_request *mrq;
50 struct mmc_command *cmd;
51 struct mmc_data *data;
52
53 u32 cmd_status;
54 u32 data_status;
55 u32 stop_status;
56 u32 stop_cmdr;
57
58 u32 mode_reg;
59 u32 sdc_reg;
60
61 struct tasklet_struct tasklet;
62 unsigned long pending_events;
63 unsigned long completed_events;
64
65 int present;
66 int detect_pin;
67 int wp_pin;
68
69 /* For detect pin debouncing */
70 struct timer_list detect_timer;
71
72 unsigned long bus_hz;
73 unsigned long mapbase;
74 struct clk *mck;
75 struct platform_device *pdev;
76};
77
78#define atmci_is_completed(host, event) \
79 test_bit(event, &host->completed_events)
80#define atmci_test_and_clear_pending(host, event) \
81 test_and_clear_bit(event, &host->pending_events)
82#define atmci_test_and_set_completed(host, event) \
83 test_and_set_bit(event, &host->completed_events)
84#define atmci_set_completed(host, event) \
85 set_bit(event, &host->completed_events)
86#define atmci_set_pending(host, event) \
87 set_bit(event, &host->pending_events)
88#define atmci_clear_pending(host, event) \
89 clear_bit(event, &host->pending_events)
90
91
92static void atmci_enable(struct atmel_mci *host)
93{
94 clk_enable(host->mck);
95 mci_writel(host, CR, MCI_CR_MCIEN);
96 mci_writel(host, MR, host->mode_reg);
97 mci_writel(host, SDCR, host->sdc_reg);
98}
99
100static void atmci_disable(struct atmel_mci *host)
101{
102 mci_writel(host, CR, MCI_CR_SWRST);
103
104 /* Stall until write is complete, then disable the bus clock */
105 mci_readl(host, SR);
106 clk_disable(host->mck);
107}
108
109static inline unsigned int ns_to_clocks(struct atmel_mci *host,
110 unsigned int ns)
111{
112 return (ns * (host->bus_hz / 1000000) + 999) / 1000;
113}
114
115static void atmci_set_timeout(struct atmel_mci *host,
116 struct mmc_data *data)
117{
118 static unsigned dtomul_to_shift[] = {
119 0, 4, 7, 8, 10, 12, 16, 20
120 };
121 unsigned timeout;
122 unsigned dtocyc;
123 unsigned dtomul;
124
125 timeout = ns_to_clocks(host, data->timeout_ns) + data->timeout_clks;
126
127 for (dtomul = 0; dtomul < 8; dtomul++) {
128 unsigned shift = dtomul_to_shift[dtomul];
129 dtocyc = (timeout + (1 << shift) - 1) >> shift;
130 if (dtocyc < 15)
131 break;
132 }
133
134 if (dtomul >= 8) {
135 dtomul = 7;
136 dtocyc = 15;
137 }
138
139 dev_vdbg(&host->mmc->class_dev, "setting timeout to %u cycles\n",
140 dtocyc << dtomul_to_shift[dtomul]);
141 mci_writel(host, DTOR, (MCI_DTOMUL(dtomul) | MCI_DTOCYC(dtocyc)));
142}
143
144/*
145 * Return mask with command flags to be enabled for this command.
146 */
147static u32 atmci_prepare_command(struct mmc_host *mmc,
148 struct mmc_command *cmd)
149{
150 struct mmc_data *data;
151 u32 cmdr;
152
153 cmd->error = -EINPROGRESS;
154
155 cmdr = MCI_CMDR_CMDNB(cmd->opcode);
156
157 if (cmd->flags & MMC_RSP_PRESENT) {
158 if (cmd->flags & MMC_RSP_136)
159 cmdr |= MCI_CMDR_RSPTYP_136BIT;
160 else
161 cmdr |= MCI_CMDR_RSPTYP_48BIT;
162 }
163
164 /*
165 * This should really be MAXLAT_5 for CMD2 and ACMD41, but
166 * it's too difficult to determine whether this is an ACMD or
167 * not. Better make it 64.
168 */
169 cmdr |= MCI_CMDR_MAXLAT_64CYC;
170
171 if (mmc->ios.bus_mode == MMC_BUSMODE_OPENDRAIN)
172 cmdr |= MCI_CMDR_OPDCMD;
173
174 data = cmd->data;
175 if (data) {
176 cmdr |= MCI_CMDR_START_XFER;
177 if (data->flags & MMC_DATA_STREAM)
178 cmdr |= MCI_CMDR_STREAM;
179 else if (data->blocks > 1)
180 cmdr |= MCI_CMDR_MULTI_BLOCK;
181 else
182 cmdr |= MCI_CMDR_BLOCK;
183
184 if (data->flags & MMC_DATA_READ)
185 cmdr |= MCI_CMDR_TRDIR_READ;
186 }
187
188 return cmdr;
189}
190
191static void atmci_start_command(struct atmel_mci *host,
192 struct mmc_command *cmd,
193 u32 cmd_flags)
194{
195 /* Must read host->cmd after testing event flags */
196 smp_rmb();
197 WARN_ON(host->cmd);
198 host->cmd = cmd;
199
200 dev_vdbg(&host->mmc->class_dev,
201 "start command: ARGR=0x%08x CMDR=0x%08x\n",
202 cmd->arg, cmd_flags);
203
204 mci_writel(host, ARGR, cmd->arg);
205 mci_writel(host, CMDR, cmd_flags);
206}
207
208static void send_stop_cmd(struct mmc_host *mmc, struct mmc_data *data)
209{
210 struct atmel_mci *host = mmc_priv(mmc);
211
212 atmci_start_command(host, data->stop, host->stop_cmdr);
213 mci_writel(host, IER, MCI_CMDRDY);
214}
215
216static void atmci_request_end(struct mmc_host *mmc, struct mmc_request *mrq)
217{
218 struct atmel_mci *host = mmc_priv(mmc);
219
220 WARN_ON(host->cmd || host->data);
221 host->mrq = NULL;
222
223 atmci_disable(host);
224
225 mmc_request_done(mmc, mrq);
226}
227
228/*
229 * Returns a mask of interrupt flags to be enabled after the whole
230 * request has been prepared.
231 */
232static u32 atmci_submit_data(struct mmc_host *mmc, struct mmc_data *data)
233{
234 struct atmel_mci *host = mmc_priv(mmc);
235 u32 iflags;
236
237 data->error = -EINPROGRESS;
238
239 WARN_ON(host->data);
240 host->sg = NULL;
241 host->data = data;
242
243 mci_writel(host, BLKR, MCI_BCNT(data->blocks)
244 | MCI_BLKLEN(data->blksz));
245 dev_vdbg(&mmc->class_dev, "BLKR=0x%08x\n",
246 MCI_BCNT(data->blocks) | MCI_BLKLEN(data->blksz));
247
248 iflags = ATMCI_DATA_ERROR_FLAGS;
249 host->sg = data->sg;
250 host->pio_offset = 0;
251 if (data->flags & MMC_DATA_READ)
252 iflags |= MCI_RXRDY;
253 else
254 iflags |= MCI_TXRDY;
255
256 return iflags;
257}
258
259static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
260{
261 struct atmel_mci *host = mmc_priv(mmc);
262 struct mmc_data *data;
263 struct mmc_command *cmd;
264 u32 iflags;
265 u32 cmdflags = 0;
266
267 iflags = mci_readl(host, IMR);
268 if (iflags)
269 dev_warn(&mmc->class_dev, "WARNING: IMR=0x%08x\n",
270 mci_readl(host, IMR));
271
272 WARN_ON(host->mrq != NULL);
273
274 /*
275 * We may "know" the card is gone even though there's still an
276 * electrical connection. If so, we really need to communicate
277 * this to the MMC core since there won't be any more
278 * interrupts as the card is completely removed. Otherwise,
279 * the MMC core might believe the card is still there even
280 * though the card was just removed very slowly.
281 */
282 if (!host->present) {
283 mrq->cmd->error = -ENOMEDIUM;
284 mmc_request_done(mmc, mrq);
285 return;
286 }
287
288 host->mrq = mrq;
289 host->pending_events = 0;
290 host->completed_events = 0;
291
292 atmci_enable(host);
293
294 /* We don't support multiple blocks of weird lengths. */
295 data = mrq->data;
296 if (data) {
297 if (data->blocks > 1 && data->blksz & 3)
298 goto fail;
299 atmci_set_timeout(host, data);
300 }
301
302 iflags = MCI_CMDRDY;
303 cmd = mrq->cmd;
304 cmdflags = atmci_prepare_command(mmc, cmd);
305 atmci_start_command(host, cmd, cmdflags);
306
307 if (data)
308 iflags |= atmci_submit_data(mmc, data);
309
310 if (mrq->stop) {
311 host->stop_cmdr = atmci_prepare_command(mmc, mrq->stop);
312 host->stop_cmdr |= MCI_CMDR_STOP_XFER;
313 if (!(data->flags & MMC_DATA_WRITE))
314 host->stop_cmdr |= MCI_CMDR_TRDIR_READ;
315 if (data->flags & MMC_DATA_STREAM)
316 host->stop_cmdr |= MCI_CMDR_STREAM;
317 else
318 host->stop_cmdr |= MCI_CMDR_MULTI_BLOCK;
319 }
320
321 /*
322 * We could have enabled interrupts earlier, but I suspect
323 * that would open up a nice can of interesting race
324 * conditions (e.g. command and data complete, but stop not
325 * prepared yet.)
326 */
327 mci_writel(host, IER, iflags);
328
329 return;
330
331fail:
332 atmci_disable(host);
333 host->mrq = NULL;
334 mrq->cmd->error = -EINVAL;
335 mmc_request_done(mmc, mrq);
336}
337
338static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
339{
340 struct atmel_mci *host = mmc_priv(mmc);
341
342 if (ios->clock) {
343 u32 clkdiv;
344
345 /* Set clock rate */
346 clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * ios->clock) - 1;
347 if (clkdiv > 255) {
348 dev_warn(&mmc->class_dev,
349 "clock %u too slow; using %lu\n",
350 ios->clock, host->bus_hz / (2 * 256));
351 clkdiv = 255;
352 }
353
354 host->mode_reg = MCI_MR_CLKDIV(clkdiv) | MCI_MR_WRPROOF
355 | MCI_MR_RDPROOF;
356 }
357
358 switch (ios->bus_width) {
359 case MMC_BUS_WIDTH_1:
360 host->sdc_reg = 0;
361 break;
362 case MMC_BUS_WIDTH_4:
363 host->sdc_reg = MCI_SDCBUS_4BIT;
364 break;
365 }
366
367 switch (ios->power_mode) {
368 case MMC_POWER_ON:
369 /* Send init sequence (74 clock cycles) */
370 atmci_enable(host);
371 mci_writel(host, CMDR, MCI_CMDR_SPCMD_INIT);
372 while (!(mci_readl(host, SR) & MCI_CMDRDY))
373 cpu_relax();
374 atmci_disable(host);
375 break;
376 default:
377 /*
378 * TODO: None of the currently available AVR32-based
379 * boards allow MMC power to be turned off. Implement
380 * power control when this can be tested properly.
381 */
382 break;
383 }
384}
385
386static int atmci_get_ro(struct mmc_host *mmc)
387{
388 int read_only = 0;
389 struct atmel_mci *host = mmc_priv(mmc);
390
391 if (host->wp_pin >= 0) {
392 read_only = gpio_get_value(host->wp_pin);
393 dev_dbg(&mmc->class_dev, "card is %s\n",
394 read_only ? "read-only" : "read-write");
395 } else {
396 dev_dbg(&mmc->class_dev,
397 "no pin for checking read-only switch."
398 " Assuming write-enable.\n");
399 }
400
401 return read_only;
402}
403
404static struct mmc_host_ops atmci_ops = {
405 .request = atmci_request,
406 .set_ios = atmci_set_ios,
407 .get_ro = atmci_get_ro,
408};
409
410static void atmci_command_complete(struct atmel_mci *host,
411 struct mmc_command *cmd, u32 status)
412{
413 /* Read the response from the card (up to 16 bytes) */
414 cmd->resp[0] = mci_readl(host, RSPR);
415 cmd->resp[1] = mci_readl(host, RSPR);
416 cmd->resp[2] = mci_readl(host, RSPR);
417 cmd->resp[3] = mci_readl(host, RSPR);
418
419 if (status & MCI_RTOE)
420 cmd->error = -ETIMEDOUT;
421 else if ((cmd->flags & MMC_RSP_CRC) && (status & MCI_RCRCE))
422 cmd->error = -EILSEQ;
423 else if (status & (MCI_RINDE | MCI_RDIRE | MCI_RENDE))
424 cmd->error = -EIO;
425 else
426 cmd->error = 0;
427
428 if (cmd->error) {
429 dev_dbg(&host->mmc->class_dev,
430 "command error: status=0x%08x\n", status);
431
432 if (cmd->data) {
433 host->data = NULL;
434 mci_writel(host, IDR, MCI_NOTBUSY
435 | MCI_TXRDY | MCI_RXRDY
436 | ATMCI_DATA_ERROR_FLAGS);
437 }
438 }
439}
440
441static void atmci_detect_change(unsigned long data)
442{
443 struct atmel_mci *host = (struct atmel_mci *)data;
444 struct mmc_request *mrq = host->mrq;
445 int present;
446
447 /*
448 * atmci_remove() sets detect_pin to -1 before freeing the
449 * interrupt. We must not re-enable the interrupt if it has
450 * been freed.
451 */
452 smp_rmb();
453 if (host->detect_pin < 0)
454 return;
455
456 enable_irq(gpio_to_irq(host->detect_pin));
457 present = !gpio_get_value(host->detect_pin);
458
459 dev_vdbg(&host->pdev->dev, "detect change: %d (was %d)\n",
460 present, host->present);
461
462 if (present != host->present) {
463 dev_dbg(&host->mmc->class_dev, "card %s\n",
464 present ? "inserted" : "removed");
465 host->present = present;
466
467 /* Reset controller if card is gone */
468 if (!present) {
469 mci_writel(host, CR, MCI_CR_SWRST);
470 mci_writel(host, IDR, ~0UL);
471 mci_writel(host, CR, MCI_CR_MCIEN);
472 }
473
474 /* Clean up queue if present */
475 if (mrq) {
476 /*
477 * Reset controller to terminate any ongoing
478 * commands or data transfers.
479 */
480 mci_writel(host, CR, MCI_CR_SWRST);
481
482 if (!atmci_is_completed(host, EVENT_CMD_COMPLETE))
483 mrq->cmd->error = -ENOMEDIUM;
484
485 if (mrq->data && !atmci_is_completed(host,
486 EVENT_DATA_COMPLETE)) {
487 host->data = NULL;
488 mrq->data->error = -ENOMEDIUM;
489 }
490 if (mrq->stop && !atmci_is_completed(host,
491 EVENT_STOP_COMPLETE))
492 mrq->stop->error = -ENOMEDIUM;
493
494 host->cmd = NULL;
495 atmci_request_end(host->mmc, mrq);
496 }
497
498 mmc_detect_change(host->mmc, 0);
499 }
500}
501
502static void atmci_tasklet_func(unsigned long priv)
503{
504 struct mmc_host *mmc = (struct mmc_host *)priv;
505 struct atmel_mci *host = mmc_priv(mmc);
506 struct mmc_request *mrq = host->mrq;
507 struct mmc_data *data = host->data;
508
509 dev_vdbg(&mmc->class_dev,
510 "tasklet: pending/completed/mask %lx/%lx/%x\n",
511 host->pending_events, host->completed_events,
512 mci_readl(host, IMR));
513
514 if (atmci_test_and_clear_pending(host, EVENT_CMD_COMPLETE)) {
515 /*
516 * host->cmd must be set to NULL before the interrupt
517 * handler sees EVENT_CMD_COMPLETE
518 */
519 host->cmd = NULL;
520 smp_wmb();
521 atmci_set_completed(host, EVENT_CMD_COMPLETE);
522 atmci_command_complete(host, mrq->cmd, host->cmd_status);
523
524 if (!mrq->cmd->error && mrq->stop
525 && atmci_is_completed(host, EVENT_XFER_COMPLETE)
526 && !atmci_test_and_set_completed(host,
527 EVENT_STOP_SENT))
528 send_stop_cmd(host->mmc, mrq->data);
529 }
530 if (atmci_test_and_clear_pending(host, EVENT_STOP_COMPLETE)) {
531 /*
532 * host->cmd must be set to NULL before the interrupt
533 * handler sees EVENT_STOP_COMPLETE
534 */
535 host->cmd = NULL;
536 smp_wmb();
537 atmci_set_completed(host, EVENT_STOP_COMPLETE);
538 atmci_command_complete(host, mrq->stop, host->stop_status);
539 }
540 if (atmci_test_and_clear_pending(host, EVENT_DATA_ERROR)) {
541 u32 status = host->data_status;
542
543 dev_vdbg(&mmc->class_dev, "data error: status=%08x\n", status);
544
545 atmci_set_completed(host, EVENT_DATA_ERROR);
546 atmci_set_completed(host, EVENT_DATA_COMPLETE);
547
548 if (status & MCI_DTOE) {
549 dev_dbg(&mmc->class_dev,
550 "data timeout error\n");
551 data->error = -ETIMEDOUT;
552 } else if (status & MCI_DCRCE) {
553 dev_dbg(&mmc->class_dev, "data CRC error\n");
554 data->error = -EILSEQ;
555 } else {
556 dev_dbg(&mmc->class_dev,
557 "data FIFO error (status=%08x)\n",
558 status);
559 data->error = -EIO;
560 }
561
562 if (host->present && data->stop
563 && atmci_is_completed(host, EVENT_CMD_COMPLETE)
564 && !atmci_test_and_set_completed(
565 host, EVENT_STOP_SENT))
566 send_stop_cmd(host->mmc, data);
567
568 host->data = NULL;
569 }
570 if (atmci_test_and_clear_pending(host, EVENT_DATA_COMPLETE)) {
571 atmci_set_completed(host, EVENT_DATA_COMPLETE);
572
573 if (!atmci_is_completed(host, EVENT_DATA_ERROR)) {
574 data->bytes_xfered = data->blocks * data->blksz;
575 data->error = 0;
576 }
577
578 host->data = NULL;
579 }
580
581 if (host->mrq && !host->cmd && !host->data)
582 atmci_request_end(mmc, host->mrq);
583}
584
585static void atmci_read_data_pio(struct atmel_mci *host)
586{
587 struct scatterlist *sg = host->sg;
588 void *buf = sg_virt(sg);
589 unsigned int offset = host->pio_offset;
590 struct mmc_data *data = host->data;
591 u32 value;
592 u32 status;
593 unsigned int nbytes = 0;
594
595 do {
596 value = mci_readl(host, RDR);
597 if (likely(offset + 4 <= sg->length)) {
598 put_unaligned(value, (u32 *)(buf + offset));
599
600 offset += 4;
601 nbytes += 4;
602
603 if (offset == sg->length) {
604 host->sg = sg = sg_next(sg);
605 if (!sg)
606 goto done;
607
608 offset = 0;
609 buf = sg_virt(sg);
610 }
611 } else {
612 unsigned int remaining = sg->length - offset;
613 memcpy(buf + offset, &value, remaining);
614 nbytes += remaining;
615
616 flush_dcache_page(sg_page(sg));
617 host->sg = sg = sg_next(sg);
618 if (!sg)
619 goto done;
620
621 offset = 4 - remaining;
622 buf = sg_virt(sg);
623 memcpy(buf, (u8 *)&value + remaining, offset);
624 nbytes += offset;
625 }
626
627 status = mci_readl(host, SR);
628 if (status & ATMCI_DATA_ERROR_FLAGS) {
629 mci_writel(host, IDR, (MCI_NOTBUSY | MCI_RXRDY
630 | ATMCI_DATA_ERROR_FLAGS));
631 host->data_status = status;
632 atmci_set_pending(host, EVENT_DATA_ERROR);
633 tasklet_schedule(&host->tasklet);
634 break;
635 }
636 } while (status & MCI_RXRDY);
637
638 host->pio_offset = offset;
639 data->bytes_xfered += nbytes;
640
641 return;
642
643done:
644 mci_writel(host, IDR, MCI_RXRDY);
645 mci_writel(host, IER, MCI_NOTBUSY);
646 data->bytes_xfered += nbytes;
647 atmci_set_completed(host, EVENT_XFER_COMPLETE);
648 if (data->stop && atmci_is_completed(host, EVENT_CMD_COMPLETE)
649 && !atmci_test_and_set_completed(host, EVENT_STOP_SENT))
650 send_stop_cmd(host->mmc, data);
651}
652
653static void atmci_write_data_pio(struct atmel_mci *host)
654{
655 struct scatterlist *sg = host->sg;
656 void *buf = sg_virt(sg);
657 unsigned int offset = host->pio_offset;
658 struct mmc_data *data = host->data;
659 u32 value;
660 u32 status;
661 unsigned int nbytes = 0;
662
663 do {
664 if (likely(offset + 4 <= sg->length)) {
665 value = get_unaligned((u32 *)(buf + offset));
666 mci_writel(host, TDR, value);
667
668 offset += 4;
669 nbytes += 4;
670 if (offset == sg->length) {
671 host->sg = sg = sg_next(sg);
672 if (!sg)
673 goto done;
674
675 offset = 0;
676 buf = sg_virt(sg);
677 }
678 } else {
679 unsigned int remaining = sg->length - offset;
680
681 value = 0;
682 memcpy(&value, buf + offset, remaining);
683 nbytes += remaining;
684
685 host->sg = sg = sg_next(sg);
686 if (!sg) {
687 mci_writel(host, TDR, value);
688 goto done;
689 }
690
691 offset = 4 - remaining;
692 buf = sg_virt(sg);
693 memcpy((u8 *)&value + remaining, buf, offset);
694 mci_writel(host, TDR, value);
695 nbytes += offset;
696 }
697
698 status = mci_readl(host, SR);
699 if (status & ATMCI_DATA_ERROR_FLAGS) {
700 mci_writel(host, IDR, (MCI_NOTBUSY | MCI_TXRDY
701 | ATMCI_DATA_ERROR_FLAGS));
702 host->data_status = status;
703 atmci_set_pending(host, EVENT_DATA_ERROR);
704 tasklet_schedule(&host->tasklet);
705 break;
706 }
707 } while (status & MCI_TXRDY);
708
709 host->pio_offset = offset;
710 data->bytes_xfered += nbytes;
711
712 return;
713
714done:
715 mci_writel(host, IDR, MCI_TXRDY);
716 mci_writel(host, IER, MCI_NOTBUSY);
717 data->bytes_xfered += nbytes;
718 atmci_set_completed(host, EVENT_XFER_COMPLETE);
719 if (data->stop && atmci_is_completed(host, EVENT_CMD_COMPLETE)
720 && !atmci_test_and_set_completed(host, EVENT_STOP_SENT))
721 send_stop_cmd(host->mmc, data);
722}
723
724static void atmci_cmd_interrupt(struct mmc_host *mmc, u32 status)
725{
726 struct atmel_mci *host = mmc_priv(mmc);
727
728 mci_writel(host, IDR, MCI_CMDRDY);
729
730 if (atmci_is_completed(host, EVENT_STOP_SENT)) {
731 host->stop_status = status;
732 atmci_set_pending(host, EVENT_STOP_COMPLETE);
733 } else {
734 host->cmd_status = status;
735 atmci_set_pending(host, EVENT_CMD_COMPLETE);
736 }
737
738 tasklet_schedule(&host->tasklet);
739}
740
741static irqreturn_t atmci_interrupt(int irq, void *dev_id)
742{
743 struct mmc_host *mmc = dev_id;
744 struct atmel_mci *host = mmc_priv(mmc);
745 u32 status, mask, pending;
746 unsigned int pass_count = 0;
747
748 spin_lock(&mmc->lock);
749
750 do {
751 status = mci_readl(host, SR);
752 mask = mci_readl(host, IMR);
753 pending = status & mask;
754 if (!pending)
755 break;
756
757 if (pending & ATMCI_DATA_ERROR_FLAGS) {
758 mci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS
759 | MCI_RXRDY | MCI_TXRDY);
760 pending &= mci_readl(host, IMR);
761 host->data_status = status;
762 atmci_set_pending(host, EVENT_DATA_ERROR);
763 tasklet_schedule(&host->tasklet);
764 }
765 if (pending & MCI_NOTBUSY) {
766 mci_writel(host, IDR, (MCI_NOTBUSY
767 | ATMCI_DATA_ERROR_FLAGS));
768 atmci_set_pending(host, EVENT_DATA_COMPLETE);
769 tasklet_schedule(&host->tasklet);
770 }
771 if (pending & MCI_RXRDY)
772 atmci_read_data_pio(host);
773 if (pending & MCI_TXRDY)
774 atmci_write_data_pio(host);
775
776 if (pending & MCI_CMDRDY)
777 atmci_cmd_interrupt(mmc, status);
778 } while (pass_count++ < 5);
779
780 spin_unlock(&mmc->lock);
781
782 return pass_count ? IRQ_HANDLED : IRQ_NONE;
783}
784
785static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id)
786{
787 struct mmc_host *mmc = dev_id;
788 struct atmel_mci *host = mmc_priv(mmc);
789
790 /*
791 * Disable interrupts until the pin has stabilized and check
792 * the state then. Use mod_timer() since we may be in the
793 * middle of the timer routine when this interrupt triggers.
794 */
795 disable_irq_nosync(irq);
796 mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(20));
797
798 return IRQ_HANDLED;
799}
800
801static int __init atmci_probe(struct platform_device *pdev)
802{
803 struct mci_platform_data *pdata;
804 struct atmel_mci *host;
805 struct mmc_host *mmc;
806 struct resource *regs;
807 int irq;
808 int ret;
809
810 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
811 if (!regs)
812 return -ENXIO;
813 pdata = pdev->dev.platform_data;
814 if (!pdata)
815 return -ENXIO;
816 irq = platform_get_irq(pdev, 0);
817 if (irq < 0)
818 return irq;
819
820 mmc = mmc_alloc_host(sizeof(struct atmel_mci), &pdev->dev);
821 if (!mmc)
822 return -ENOMEM;
823
824 host = mmc_priv(mmc);
825 host->pdev = pdev;
826 host->mmc = mmc;
827 host->detect_pin = pdata->detect_pin;
828 host->wp_pin = pdata->wp_pin;
829
830 host->mck = clk_get(&pdev->dev, "mci_clk");
831 if (IS_ERR(host->mck)) {
832 ret = PTR_ERR(host->mck);
833 goto err_clk_get;
834 }
835
836 ret = -ENOMEM;
837 host->regs = ioremap(regs->start, regs->end - regs->start + 1);
838 if (!host->regs)
839 goto err_ioremap;
840
841 clk_enable(host->mck);
842 mci_writel(host, CR, MCI_CR_SWRST);
843 host->bus_hz = clk_get_rate(host->mck);
844 clk_disable(host->mck);
845
846 host->mapbase = regs->start;
847
848 mmc->ops = &atmci_ops;
849 mmc->f_min = (host->bus_hz + 511) / 512;
850 mmc->f_max = host->bus_hz / 2;
851 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
852 mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE;
853
854 mmc->max_hw_segs = 64;
855 mmc->max_phys_segs = 64;
856 mmc->max_req_size = 32768 * 512;
857 mmc->max_blk_size = 32768;
858 mmc->max_blk_count = 512;
859
860 tasklet_init(&host->tasklet, atmci_tasklet_func, (unsigned long)mmc);
861
862 ret = request_irq(irq, atmci_interrupt, 0, pdev->dev.bus_id, mmc);
863 if (ret)
864 goto err_request_irq;
865
866 /* Assume card is present if we don't have a detect pin */
867 host->present = 1;
868 if (host->detect_pin >= 0) {
869 if (gpio_request(host->detect_pin, "mmc_detect")) {
870 dev_dbg(&mmc->class_dev, "no detect pin available\n");
871 host->detect_pin = -1;
872 } else {
873 host->present = !gpio_get_value(host->detect_pin);
874 }
875 }
876 if (host->wp_pin >= 0) {
877 if (gpio_request(host->wp_pin, "mmc_wp")) {
878 dev_dbg(&mmc->class_dev, "no WP pin available\n");
879 host->wp_pin = -1;
880 }
881 }
882
883 platform_set_drvdata(pdev, host);
884
885 mmc_add_host(mmc);
886
887 if (host->detect_pin >= 0) {
888 setup_timer(&host->detect_timer, atmci_detect_change,
889 (unsigned long)host);
890
891 ret = request_irq(gpio_to_irq(host->detect_pin),
892 atmci_detect_interrupt,
893 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
894 "mmc-detect", mmc);
895 if (ret) {
896 dev_dbg(&mmc->class_dev,
897 "could not request IRQ %d for detect pin\n",
898 gpio_to_irq(host->detect_pin));
899 gpio_free(host->detect_pin);
900 host->detect_pin = -1;
901 }
902 }
903
904 dev_info(&mmc->class_dev,
905 "Atmel MCI controller at 0x%08lx irq %d\n",
906 host->mapbase, irq);
907
908 return 0;
909
910err_request_irq:
911 iounmap(host->regs);
912err_ioremap:
913 clk_put(host->mck);
914err_clk_get:
915 mmc_free_host(mmc);
916 return ret;
917}
918
919static int __exit atmci_remove(struct platform_device *pdev)
920{
921 struct atmel_mci *host = platform_get_drvdata(pdev);
922
923 platform_set_drvdata(pdev, NULL);
924
925 if (host) {
926 if (host->detect_pin >= 0) {
927 int pin = host->detect_pin;
928
929 /* Make sure the timer doesn't enable the interrupt */
930 host->detect_pin = -1;
931 smp_wmb();
932
933 free_irq(gpio_to_irq(pin), host->mmc);
934 del_timer_sync(&host->detect_timer);
935 gpio_free(pin);
936 }
937
938 mmc_remove_host(host->mmc);
939
940 clk_enable(host->mck);
941 mci_writel(host, IDR, ~0UL);
942 mci_writel(host, CR, MCI_CR_MCIDIS);
943 mci_readl(host, SR);
944 clk_disable(host->mck);
945
946 if (host->wp_pin >= 0)
947 gpio_free(host->wp_pin);
948
949 free_irq(platform_get_irq(pdev, 0), host->mmc);
950 iounmap(host->regs);
951
952 clk_put(host->mck);
953
954 mmc_free_host(host->mmc);
955 }
956 return 0;
957}
958
959static struct platform_driver atmci_driver = {
960 .remove = __exit_p(atmci_remove),
961 .driver = {
962 .name = "atmel_mci",
963 },
964};
965
966static int __init atmci_init(void)
967{
968 return platform_driver_probe(&atmci_driver, atmci_probe);
969}
970
971static void __exit atmci_exit(void)
972{
973 platform_driver_unregister(&atmci_driver);
974}
975
976module_init(atmci_init);
977module_exit(atmci_exit);
978
979MODULE_DESCRIPTION("Atmel Multimedia Card Interface driver");
980MODULE_AUTHOR("Haavard Skinnemoen <haavard.skinnemoen@atmel.com>");
981MODULE_LICENSE("GPL v2");
diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h
index b4cddfaca90..a3783861cdd 100644
--- a/include/asm-avr32/arch-at32ap/board.h
+++ b/include/asm-avr32/arch-at32ap/board.h
@@ -77,7 +77,11 @@ struct i2c_board_info;
77struct platform_device *at32_add_device_twi(unsigned int id, 77struct platform_device *at32_add_device_twi(unsigned int id,
78 struct i2c_board_info *b, 78 struct i2c_board_info *b,
79 unsigned int n); 79 unsigned int n);
80struct platform_device *at32_add_device_mci(unsigned int id); 80
81struct mci_platform_data;
82struct platform_device *
83at32_add_device_mci(unsigned int id, struct mci_platform_data *data);
84
81struct platform_device *at32_add_device_ac97c(unsigned int id); 85struct platform_device *at32_add_device_ac97c(unsigned int id);
82struct platform_device *at32_add_device_abdac(unsigned int id); 86struct platform_device *at32_add_device_abdac(unsigned int id);
83struct platform_device *at32_add_device_psif(unsigned int id); 87struct platform_device *at32_add_device_psif(unsigned int id);
diff --git a/include/asm-avr32/atmel-mci.h b/include/asm-avr32/atmel-mci.h
new file mode 100644
index 00000000000..c2ea6e1c9aa
--- /dev/null
+++ b/include/asm-avr32/atmel-mci.h
@@ -0,0 +1,9 @@
1#ifndef __ASM_AVR32_ATMEL_MCI_H
2#define __ASM_AVR32_ATMEL_MCI_H
3
4struct mci_platform_data {
5 int detect_pin;
6 int wp_pin;
7};
8
9#endif /* __ASM_AVR32_ATMEL_MCI_H */