blob: 76cb05ab9341a447743165ab80c332eb3f880103 [file] [log] [blame]
Andrew Victor65dbf342006-04-02 19:18:51 +01001/*
Pierre Ossman70f10482007-07-11 20:04:50 +02002 * linux/drivers/mmc/host/at91_mci.c - ATMEL AT91 MCI Driver
Andrew Victor65dbf342006-04-02 19:18:51 +01003 *
4 * Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved
5 *
6 * Copyright (C) 2006 Malcolm Noyes
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13/*
Andrew Victor99eeb8d2006-12-11 12:40:23 +010014 This is the AT91 MCI driver that has been tested with both MMC cards
Andrew Victor65dbf342006-04-02 19:18:51 +010015 and SD-cards. Boards that support write protect are now supported.
16 The CCAT91SBC001 board does not support SD cards.
17
18 The three entry points are at91_mci_request, at91_mci_set_ios
19 and at91_mci_get_ro.
20
21 SET IOS
22 This configures the device to put it into the correct mode and clock speed
23 required.
24
25 MCI REQUEST
26 MCI request processes the commands sent in the mmc_request structure. This
27 can consist of a processing command and a stop command in the case of
28 multiple block transfers.
29
30 There are three main types of request, commands, reads and writes.
31
32 Commands are straight forward. The command is submitted to the controller and
33 the request function returns. When the controller generates an interrupt to indicate
34 the command is finished, the response to the command are read and the mmc_request_done
35 function called to end the request.
36
37 Reads and writes work in a similar manner to normal commands but involve the PDC (DMA)
38 controller to manage the transfers.
39
40 A read is done from the controller directly to the scatterlist passed in from the request.
Andrew Victor99eeb8d2006-12-11 12:40:23 +010041 Due to a bug in the AT91RM9200 controller, when a read is completed, all the words are byte
42 swapped in the scatterlist buffers. AT91SAM926x are not affected by this bug.
Andrew Victor65dbf342006-04-02 19:18:51 +010043
44 The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY
45
46 A write is slightly different in that the bytes to write are read from the scatterlist
47 into a dma memory buffer (this is in case the source buffer should be read only). The
48 entire write buffer is then done from this single dma memory buffer.
49
50 The sequence of write interrupts is: ENDTX, TXBUFE, NOTBUSY, CMDRDY
51
52 GET RO
53 Gets the status of the write protect pin, if available.
54*/
55
Andrew Victor65dbf342006-04-02 19:18:51 +010056#include <linux/module.h>
57#include <linux/moduleparam.h>
58#include <linux/init.h>
59#include <linux/ioport.h>
60#include <linux/platform_device.h>
61#include <linux/interrupt.h>
62#include <linux/blkdev.h>
63#include <linux/delay.h>
64#include <linux/err.h>
65#include <linux/dma-mapping.h>
66#include <linux/clk.h>
Andrew Victor93a3ddc2007-02-08 11:31:22 +010067#include <linux/atmel_pdc.h>
Andrew Victor65dbf342006-04-02 19:18:51 +010068
69#include <linux/mmc/host.h>
Andrew Victor65dbf342006-04-02 19:18:51 +010070
71#include <asm/io.h>
72#include <asm/irq.h>
David Brownell6e996ee2008-02-04 18:12:48 +010073#include <asm/gpio.h>
74
Russell Kinga09e64f2008-08-05 16:14:15 +010075#include <mach/board.h>
76#include <mach/cpu.h>
77#include <mach/at91_mci.h>
Andrew Victor65dbf342006-04-02 19:18:51 +010078
79#define DRIVER_NAME "at91_mci"
80
Andrew Victordf05a302006-10-23 14:50:09 +020081#define FL_SENT_COMMAND (1 << 0)
82#define FL_SENT_STOP (1 << 1)
Andrew Victor65dbf342006-04-02 19:18:51 +010083
Andrew Victordf05a302006-10-23 14:50:09 +020084#define AT91_MCI_ERRORS (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE \
85 | AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE \
Nicolas Ferre37b758e82007-08-08 12:01:44 +020086 | AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)
Andrew Victor65dbf342006-04-02 19:18:51 +010087
Andrew Victore0b19b82006-10-25 19:42:38 +020088#define at91_mci_read(host, reg) __raw_readl((host)->baseaddr + (reg))
89#define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg))
Andrew Victor65dbf342006-04-02 19:18:51 +010090
Wolfgang Muees3780d902010-03-05 13:43:40 -080091#define MCI_BLKSIZE 512
92#define MCI_MAXBLKSIZE 4095
93#define MCI_BLKATONCE 256
94#define MCI_BUFSIZE (MCI_BLKSIZE * MCI_BLKATONCE)
Andrew Victor65dbf342006-04-02 19:18:51 +010095
96/*
97 * Low level type for this driver
98 */
99struct at91mci_host
100{
101 struct mmc_host *mmc;
102 struct mmc_command *cmd;
103 struct mmc_request *request;
104
Andrew Victore0b19b82006-10-25 19:42:38 +0200105 void __iomem *baseaddr;
Andrew Victor17ea0592006-10-23 14:44:40 +0200106 int irq;
Andrew Victore0b19b82006-10-25 19:42:38 +0200107
Andrew Victor65dbf342006-04-02 19:18:51 +0100108 struct at91_mmc_data *board;
109 int present;
110
Andrew Victor3dd3b032006-10-23 14:46:54 +0200111 struct clk *mci_clk;
112
Andrew Victor65dbf342006-04-02 19:18:51 +0100113 /*
114 * Flag indicating when the command has been sent. This is used to
115 * work out whether or not to send the stop
116 */
117 unsigned int flags;
118 /* flag for current bus settings */
119 u32 bus_mode;
120
121 /* DMA buffer used for transmitting */
122 unsigned int* buffer;
123 dma_addr_t physical_address;
124 unsigned int total_length;
125
126 /* Latest in the scatterlist that has been enabled for transfer, but not freed */
127 int in_use_index;
128
129 /* Latest in the scatterlist that has been enabled for transfer */
130 int transfer_index;
Marc Pignate181dce2008-05-30 14:06:32 +0200131
132 /* Timer for timeouts */
133 struct timer_list timer;
Andrew Victor65dbf342006-04-02 19:18:51 +0100134};
135
Marc Pignatc5a89c62008-05-30 14:07:47 +0200136/*
137 * Reset the controller and restore most of the state
138 */
139static void at91_reset_host(struct at91mci_host *host)
140{
141 unsigned long flags;
142 u32 mr;
143 u32 sdcr;
144 u32 dtor;
145 u32 imr;
146
147 local_irq_save(flags);
148 imr = at91_mci_read(host, AT91_MCI_IMR);
149
150 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
151
152 /* save current state */
153 mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
154 sdcr = at91_mci_read(host, AT91_MCI_SDCR);
155 dtor = at91_mci_read(host, AT91_MCI_DTOR);
156
157 /* reset the controller */
158 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
159
160 /* restore state */
161 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
162 at91_mci_write(host, AT91_MCI_MR, mr);
163 at91_mci_write(host, AT91_MCI_SDCR, sdcr);
164 at91_mci_write(host, AT91_MCI_DTOR, dtor);
165 at91_mci_write(host, AT91_MCI_IER, imr);
166
167 /* make sure sdio interrupts will fire */
168 at91_mci_read(host, AT91_MCI_SR);
169
170 local_irq_restore(flags);
171}
172
Marc Pignate181dce2008-05-30 14:06:32 +0200173static void at91_timeout_timer(unsigned long data)
174{
175 struct at91mci_host *host;
176
177 host = (struct at91mci_host *)data;
178
179 if (host->request) {
180 dev_err(host->mmc->parent, "Timeout waiting end of packet\n");
181
182 if (host->cmd && host->cmd->data) {
183 host->cmd->data->error = -ETIMEDOUT;
184 } else {
185 if (host->cmd)
186 host->cmd->error = -ETIMEDOUT;
187 else
188 host->request->cmd->error = -ETIMEDOUT;
189 }
190
Marc Pignatc5a89c62008-05-30 14:07:47 +0200191 at91_reset_host(host);
Marc Pignate181dce2008-05-30 14:06:32 +0200192 mmc_request_done(host->mmc, host->request);
193 }
194}
195
Andrew Victor65dbf342006-04-02 19:18:51 +0100196/*
197 * Copy from sg to a dma block - used for transfers
198 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200199static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
Andrew Victor65dbf342006-04-02 19:18:51 +0100200{
201 unsigned int len, i, size;
202 unsigned *dmabuf = host->buffer;
203
Ville Syrjala5385edc2008-06-14 20:27:20 +0300204 size = data->blksz * data->blocks;
Andrew Victor65dbf342006-04-02 19:18:51 +0100205 len = data->sg_len;
206
Ville Syrjala5385edc2008-06-14 20:27:20 +0300207 /* AT91SAM926[0/3] Data Write Operation and number of bytes erratum */
208 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
209 if (host->total_length == 12)
210 memset(dmabuf, 0, 12);
211
Andrew Victor65dbf342006-04-02 19:18:51 +0100212 /*
213 * Just loop through all entries. Size might not
214 * be the entire list though so make sure that
215 * we do not transfer too much.
216 */
217 for (i = 0; i < len; i++) {
218 struct scatterlist *sg;
219 int amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100220 unsigned int *sgbuffer;
221
222 sg = &data->sg[i];
223
Jens Axboe45711f12007-10-22 21:19:53 +0200224 sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
Andrew Victor65dbf342006-04-02 19:18:51 +0100225 amount = min(size, sg->length);
226 size -= amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100227
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100228 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
229 int index;
230
231 for (index = 0; index < (amount / 4); index++)
232 *dmabuf++ = swab32(sgbuffer[index]);
Ville Syrjala5385edc2008-06-14 20:27:20 +0300233 } else {
Wolfgang Muees0b3520f2010-03-05 13:43:38 -0800234 char *tmpv = (char *)dmabuf;
235 memcpy(tmpv, sgbuffer, amount);
236 tmpv += amount;
237 dmabuf = (unsigned *)tmpv;
Ville Syrjala5385edc2008-06-14 20:27:20 +0300238 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100239
Wolfgang Muees0b3520f2010-03-05 13:43:38 -0800240 kunmap_atomic(((void *)sgbuffer) - sg->offset, KM_BIO_SRC_IRQ);
Andrew Victor65dbf342006-04-02 19:18:51 +0100241
242 if (size == 0)
243 break;
244 }
245
246 /*
247 * Check that we didn't get a request to transfer
248 * more data than can fit into the SG list.
249 */
250 BUG_ON(size != 0);
251}
252
253/*
254 * Prepare a dma read
255 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200256static void at91_mci_pre_dma_read(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100257{
258 int i;
259 struct scatterlist *sg;
260 struct mmc_command *cmd;
261 struct mmc_data *data;
262
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100263 pr_debug("pre dma read\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100264
265 cmd = host->cmd;
266 if (!cmd) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100267 pr_debug("no command\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100268 return;
269 }
270
271 data = cmd->data;
272 if (!data) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100273 pr_debug("no data\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100274 return;
275 }
276
277 for (i = 0; i < 2; i++) {
278 /* nothing left to transfer */
279 if (host->transfer_index >= data->sg_len) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100280 pr_debug("Nothing left to transfer (index = %d)\n", host->transfer_index);
Andrew Victor65dbf342006-04-02 19:18:51 +0100281 break;
282 }
283
284 /* Check to see if this needs filling */
285 if (i == 0) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100286 if (at91_mci_read(host, ATMEL_PDC_RCR) != 0) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100287 pr_debug("Transfer active in current\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100288 continue;
289 }
290 }
291 else {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100292 if (at91_mci_read(host, ATMEL_PDC_RNCR) != 0) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100293 pr_debug("Transfer active in next\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100294 continue;
295 }
296 }
297
298 /* Setup the next transfer */
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100299 pr_debug("Using transfer index %d\n", host->transfer_index);
Andrew Victor65dbf342006-04-02 19:18:51 +0100300
301 sg = &data->sg[host->transfer_index++];
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100302 pr_debug("sg = %p\n", sg);
Andrew Victor65dbf342006-04-02 19:18:51 +0100303
Jens Axboe45711f12007-10-22 21:19:53 +0200304 sg->dma_address = dma_map_page(NULL, sg_page(sg), sg->offset, sg->length, DMA_FROM_DEVICE);
Andrew Victor65dbf342006-04-02 19:18:51 +0100305
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100306 pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
Andrew Victor65dbf342006-04-02 19:18:51 +0100307
308 if (i == 0) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100309 at91_mci_write(host, ATMEL_PDC_RPR, sg->dma_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200310 at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ? sg->length : sg->length / 4);
Andrew Victor65dbf342006-04-02 19:18:51 +0100311 }
312 else {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100313 at91_mci_write(host, ATMEL_PDC_RNPR, sg->dma_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200314 at91_mci_write(host, ATMEL_PDC_RNCR, (data->blksz & 0x3) ? sg->length : sg->length / 4);
Andrew Victor65dbf342006-04-02 19:18:51 +0100315 }
316 }
317
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100318 pr_debug("pre dma read done\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100319}
320
321/*
322 * Handle after a dma read
323 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200324static void at91_mci_post_dma_read(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100325{
326 struct mmc_command *cmd;
327 struct mmc_data *data;
328
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100329 pr_debug("post dma read\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100330
331 cmd = host->cmd;
332 if (!cmd) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100333 pr_debug("no command\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100334 return;
335 }
336
337 data = cmd->data;
338 if (!data) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100339 pr_debug("no data\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100340 return;
341 }
342
343 while (host->in_use_index < host->transfer_index) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100344 struct scatterlist *sg;
345
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100346 pr_debug("finishing index %d\n", host->in_use_index);
Andrew Victor65dbf342006-04-02 19:18:51 +0100347
348 sg = &data->sg[host->in_use_index++];
349
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100350 pr_debug("Unmapping page %08X\n", sg->dma_address);
Andrew Victor65dbf342006-04-02 19:18:51 +0100351
352 dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
353
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100354 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
Nicolas Ferreed99c542007-07-09 14:58:16 +0200355 unsigned int *buffer;
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100356 int index;
Andrew Victor65dbf342006-04-02 19:18:51 +0100357
Nicolas Ferreed99c542007-07-09 14:58:16 +0200358 /* Swap the contents of the buffer */
Jens Axboe45711f12007-10-22 21:19:53 +0200359 buffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200360 pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
361
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100362 for (index = 0; index < (sg->length / 4); index++)
363 buffer[index] = swab32(buffer[index]);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200364
365 kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
Andrew Victor65dbf342006-04-02 19:18:51 +0100366 }
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100367
Jens Axboe45711f12007-10-22 21:19:53 +0200368 flush_dcache_page(sg_page(sg));
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200369
370 data->bytes_xfered += sg->length;
Andrew Victor65dbf342006-04-02 19:18:51 +0100371 }
372
373 /* Is there another transfer to trigger? */
374 if (host->transfer_index < data->sg_len)
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200375 at91_mci_pre_dma_read(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100376 else {
Nicolas Ferreed99c542007-07-09 14:58:16 +0200377 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
Andrew Victore0b19b82006-10-25 19:42:38 +0200378 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
Andrew Victor65dbf342006-04-02 19:18:51 +0100379 }
380
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100381 pr_debug("post dma read done\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100382}
383
384/*
385 * Handle transmitted data
386 */
387static void at91_mci_handle_transmitted(struct at91mci_host *host)
388{
389 struct mmc_command *cmd;
390 struct mmc_data *data;
391
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100392 pr_debug("Handling the transmit\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100393
394 /* Disable the transfer */
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100395 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100396
397 /* Now wait for cmd ready */
Andrew Victore0b19b82006-10-25 19:42:38 +0200398 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
Andrew Victor65dbf342006-04-02 19:18:51 +0100399
400 cmd = host->cmd;
401 if (!cmd) return;
402
403 data = cmd->data;
404 if (!data) return;
405
Pierre Ossmanbe0192a2007-07-24 21:11:47 +0200406 if (cmd->data->blocks > 1) {
Nicolas Ferreed99c542007-07-09 14:58:16 +0200407 pr_debug("multiple write : wait for BLKE...\n");
408 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
409 } else
410 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
Andrew Victor65dbf342006-04-02 19:18:51 +0100411}
412
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200413/*
414 * Update bytes tranfered count during a write operation
415 */
416static void at91_mci_update_bytes_xfered(struct at91mci_host *host)
417{
418 struct mmc_data *data;
419
420 /* always deal with the effective request (and not the current cmd) */
421
422 if (host->request->cmd && host->request->cmd->error != 0)
423 return;
424
425 if (host->request->data) {
426 data = host->request->data;
427 if (data->flags & MMC_DATA_WRITE) {
428 /* card is in IDLE mode now */
429 pr_debug("-> bytes_xfered %d, total_length = %d\n",
430 data->bytes_xfered, host->total_length);
Ville Syrjala5385edc2008-06-14 20:27:20 +0300431 data->bytes_xfered = data->blksz * data->blocks;
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200432 }
433 }
434}
435
436
Nicolas Ferreed99c542007-07-09 14:58:16 +0200437/*Handle after command sent ready*/
438static int at91_mci_handle_cmdrdy(struct at91mci_host *host)
439{
440 if (!host->cmd)
441 return 1;
442 else if (!host->cmd->data) {
443 if (host->flags & FL_SENT_STOP) {
444 /*After multi block write, we must wait for NOTBUSY*/
445 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
446 } else return 1;
447 } else if (host->cmd->data->flags & MMC_DATA_WRITE) {
448 /*After sendding multi-block-write command, start DMA transfer*/
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200449 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE | AT91_MCI_BLKE);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200450 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
451 }
452
453 /* command not completed, have to wait */
454 return 0;
455}
456
457
Andrew Victor65dbf342006-04-02 19:18:51 +0100458/*
459 * Enable the controller
460 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200461static void at91_mci_enable(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100462{
Nicolas Ferreed99c542007-07-09 14:58:16 +0200463 unsigned int mr;
464
Andrew Victore0b19b82006-10-25 19:42:38 +0200465 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200466 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
Andrew Victore0b19b82006-10-25 19:42:38 +0200467 at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200468 mr = AT91_MCI_PDCMODE | 0x34a;
469
470 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
471 mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
472
473 at91_mci_write(host, AT91_MCI_MR, mr);
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100474
475 /* use Slot A or B (only one at same time) */
476 at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
Andrew Victor65dbf342006-04-02 19:18:51 +0100477}
478
479/*
480 * Disable the controller
481 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200482static void at91_mci_disable(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100483{
Andrew Victore0b19b82006-10-25 19:42:38 +0200484 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
Andrew Victor65dbf342006-04-02 19:18:51 +0100485}
486
487/*
488 * Send a command
Andrew Victor65dbf342006-04-02 19:18:51 +0100489 */
Nicolas Ferreed99c542007-07-09 14:58:16 +0200490static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
Andrew Victor65dbf342006-04-02 19:18:51 +0100491{
492 unsigned int cmdr, mr;
493 unsigned int block_length;
494 struct mmc_data *data = cmd->data;
495
496 unsigned int blocks;
497 unsigned int ier = 0;
498
499 host->cmd = cmd;
500
Nicolas Ferreed99c542007-07-09 14:58:16 +0200501 /* Needed for leaving busy state before CMD1 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200502 if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100503 pr_debug("Clearing timeout\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200504 at91_mci_write(host, AT91_MCI_ARGR, 0);
505 at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
506 while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100507 /* spin */
Andrew Victore0b19b82006-10-25 19:42:38 +0200508 pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
Andrew Victor65dbf342006-04-02 19:18:51 +0100509 }
510 }
Nicolas Ferreed99c542007-07-09 14:58:16 +0200511
Andrew Victor65dbf342006-04-02 19:18:51 +0100512 cmdr = cmd->opcode;
513
514 if (mmc_resp_type(cmd) == MMC_RSP_NONE)
515 cmdr |= AT91_MCI_RSPTYP_NONE;
516 else {
517 /* if a response is expected then allow maximum response latancy */
518 cmdr |= AT91_MCI_MAXLAT;
519 /* set 136 bit response for R2, 48 bit response otherwise */
520 if (mmc_resp_type(cmd) == MMC_RSP_R2)
521 cmdr |= AT91_MCI_RSPTYP_136;
522 else
523 cmdr |= AT91_MCI_RSPTYP_48;
524 }
525
526 if (data) {
Marc Pignat1d4de9e2007-08-09 13:56:29 +0200527
Ville Syrjala9da3cba2008-06-09 22:06:44 +0300528 if (cpu_is_at91rm9200() || cpu_is_at91sam9261()) {
529 if (data->blksz & 0x3) {
530 pr_debug("Unsupported block size\n");
531 cmd->error = -EINVAL;
532 mmc_request_done(host->mmc, host->request);
533 return;
534 }
535 if (data->flags & MMC_DATA_STREAM) {
536 pr_debug("Stream commands not supported\n");
537 cmd->error = -EINVAL;
538 mmc_request_done(host->mmc, host->request);
539 return;
540 }
Marc Pignat1d4de9e2007-08-09 13:56:29 +0200541 }
542
Russell Kinga3fd4a12006-06-04 17:51:15 +0100543 block_length = data->blksz;
Andrew Victor65dbf342006-04-02 19:18:51 +0100544 blocks = data->blocks;
545
546 /* always set data start - also set direction flag for read */
547 if (data->flags & MMC_DATA_READ)
548 cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
549 else if (data->flags & MMC_DATA_WRITE)
550 cmdr |= AT91_MCI_TRCMD_START;
551
552 if (data->flags & MMC_DATA_STREAM)
553 cmdr |= AT91_MCI_TRTYP_STREAM;
Pierre Ossmanbe0192a2007-07-24 21:11:47 +0200554 if (data->blocks > 1)
Andrew Victor65dbf342006-04-02 19:18:51 +0100555 cmdr |= AT91_MCI_TRTYP_MULTIPLE;
556 }
557 else {
558 block_length = 0;
559 blocks = 0;
560 }
561
Marc Pignatb6cedb32007-06-06 20:27:59 +0200562 if (host->flags & FL_SENT_STOP)
Andrew Victor65dbf342006-04-02 19:18:51 +0100563 cmdr |= AT91_MCI_TRCMD_STOP;
564
565 if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
566 cmdr |= AT91_MCI_OPDCMD;
567
568 /*
569 * Set the arguments and send the command
570 */
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200571 pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
Andrew Victore0b19b82006-10-25 19:42:38 +0200572 cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
Andrew Victor65dbf342006-04-02 19:18:51 +0100573
574 if (!data) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100575 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
576 at91_mci_write(host, ATMEL_PDC_RPR, 0);
577 at91_mci_write(host, ATMEL_PDC_RCR, 0);
578 at91_mci_write(host, ATMEL_PDC_RNPR, 0);
579 at91_mci_write(host, ATMEL_PDC_RNCR, 0);
580 at91_mci_write(host, ATMEL_PDC_TPR, 0);
581 at91_mci_write(host, ATMEL_PDC_TCR, 0);
582 at91_mci_write(host, ATMEL_PDC_TNPR, 0);
583 at91_mci_write(host, ATMEL_PDC_TNCR, 0);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200584 ier = AT91_MCI_CMDRDY;
585 } else {
586 /* zero block length and PDC mode */
Ville Syrjala12bd2572008-06-09 22:06:45 +0300587 mr = at91_mci_read(host, AT91_MCI_MR) & 0x5fff;
Marc Pignat80f92542008-05-30 14:05:24 +0200588 mr |= (data->blksz & 0x3) ? AT91_MCI_PDCFBYTE : 0;
589 mr |= (block_length << 16);
590 mr |= AT91_MCI_PDCMODE;
591 at91_mci_write(host, AT91_MCI_MR, mr);
Andrew Victor65dbf342006-04-02 19:18:51 +0100592
Ville Syrjala9da3cba2008-06-09 22:06:44 +0300593 if (!(cpu_is_at91rm9200() || cpu_is_at91sam9261()))
Marc Pignatc5a89c62008-05-30 14:07:47 +0200594 at91_mci_write(host, AT91_MCI_BLKR,
595 AT91_MCI_BLKR_BCNT(blocks) |
596 AT91_MCI_BLKR_BLKLEN(block_length));
597
Nicolas Ferreed99c542007-07-09 14:58:16 +0200598 /*
599 * Disable the PDC controller
600 */
601 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100602
Nicolas Ferreed99c542007-07-09 14:58:16 +0200603 if (cmdr & AT91_MCI_TRCMD_START) {
604 data->bytes_xfered = 0;
605 host->transfer_index = 0;
606 host->in_use_index = 0;
607 if (cmdr & AT91_MCI_TRDIR) {
608 /*
609 * Handle a read
610 */
Nicolas Ferreed99c542007-07-09 14:58:16 +0200611 host->total_length = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100612
Nicolas Ferreed99c542007-07-09 14:58:16 +0200613 at91_mci_pre_dma_read(host);
614 ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
615 }
616 else {
617 /*
618 * Handle a write
619 */
620 host->total_length = block_length * blocks;
Ville Syrjala5385edc2008-06-14 20:27:20 +0300621 /*
622 * AT91SAM926[0/3] Data Write Operation and
623 * number of bytes erratum
624 */
625 if (cpu_is_at91sam9260 () || cpu_is_at91sam9263())
626 if (host->total_length < 12)
627 host->total_length = 12;
David Brownelle385ea62008-09-02 14:35:46 -0700628
Nicolas Ferreed99c542007-07-09 14:58:16 +0200629 at91_mci_sg_to_dma(host, data);
Andrew Victor65dbf342006-04-02 19:18:51 +0100630
Nicolas Ferreed99c542007-07-09 14:58:16 +0200631 pr_debug("Transmitting %d bytes\n", host->total_length);
Andrew Victor65dbf342006-04-02 19:18:51 +0100632
Nicolas Ferreed99c542007-07-09 14:58:16 +0200633 at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200634 at91_mci_write(host, ATMEL_PDC_TCR, (data->blksz & 0x3) ?
635 host->total_length : host->total_length / 4);
636
Nicolas Ferreed99c542007-07-09 14:58:16 +0200637 ier = AT91_MCI_CMDRDY;
638 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100639 }
640 }
641
642 /*
643 * Send the command and then enable the PDC - not the other way round as
644 * the data sheet says
645 */
646
Andrew Victore0b19b82006-10-25 19:42:38 +0200647 at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
648 at91_mci_write(host, AT91_MCI_CMDR, cmdr);
Andrew Victor65dbf342006-04-02 19:18:51 +0100649
650 if (cmdr & AT91_MCI_TRCMD_START) {
651 if (cmdr & AT91_MCI_TRDIR)
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100652 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
Andrew Victor65dbf342006-04-02 19:18:51 +0100653 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100654
Nicolas Ferreed99c542007-07-09 14:58:16 +0200655 /* Enable selected interrupts */
Andrew Victordf05a302006-10-23 14:50:09 +0200656 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
Andrew Victor65dbf342006-04-02 19:18:51 +0100657}
658
659/*
660 * Process the next step in the request
661 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200662static void at91_mci_process_next(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100663{
664 if (!(host->flags & FL_SENT_COMMAND)) {
665 host->flags |= FL_SENT_COMMAND;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200666 at91_mci_send_command(host, host->request->cmd);
Andrew Victor65dbf342006-04-02 19:18:51 +0100667 }
668 else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
669 host->flags |= FL_SENT_STOP;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200670 at91_mci_send_command(host, host->request->stop);
Marc Pignate181dce2008-05-30 14:06:32 +0200671 } else {
672 del_timer(&host->timer);
Marc Pignatc5a89c62008-05-30 14:07:47 +0200673 /* the at91rm9200 mci controller hangs after some transfers,
674 * and the workaround is to reset it after each transfer.
675 */
676 if (cpu_is_at91rm9200())
677 at91_reset_host(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100678 mmc_request_done(host->mmc, host->request);
Marc Pignate181dce2008-05-30 14:06:32 +0200679 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100680}
681
682/*
683 * Handle a command that has been completed
684 */
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200685static void at91_mci_completed_command(struct at91mci_host *host, unsigned int status)
Andrew Victor65dbf342006-04-02 19:18:51 +0100686{
687 struct mmc_command *cmd = host->cmd;
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200688 struct mmc_data *data = cmd->data;
Andrew Victor65dbf342006-04-02 19:18:51 +0100689
Eric Benard7a6588b2008-05-30 14:26:05 +0200690 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Andrew Victor65dbf342006-04-02 19:18:51 +0100691
Andrew Victore0b19b82006-10-25 19:42:38 +0200692 cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
693 cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
694 cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
695 cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
Andrew Victor65dbf342006-04-02 19:18:51 +0100696
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200697 pr_debug("Status = %08X/%08x [%08X %08X %08X %08X]\n",
698 status, at91_mci_read(host, AT91_MCI_SR),
699 cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
Andrew Victor65dbf342006-04-02 19:18:51 +0100700
Andrew Victor9e3866b2007-10-17 11:53:40 +0200701 if (status & AT91_MCI_ERRORS) {
Marc Pignatb6cedb32007-06-06 20:27:59 +0200702 if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
Pierre Ossman17b04292007-07-22 22:18:46 +0200703 cmd->error = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100704 }
705 else {
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200706 if (status & (AT91_MCI_DTOE | AT91_MCI_DCRCE)) {
707 if (data) {
708 if (status & AT91_MCI_DTOE)
709 data->error = -ETIMEDOUT;
710 else if (status & AT91_MCI_DCRCE)
711 data->error = -EILSEQ;
712 }
713 } else {
714 if (status & AT91_MCI_RTOE)
715 cmd->error = -ETIMEDOUT;
716 else if (status & AT91_MCI_RCRCE)
717 cmd->error = -EILSEQ;
718 else
719 cmd->error = -EIO;
720 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100721
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200722 pr_debug("Error detected and set to %d/%d (cmd = %d, retries = %d)\n",
723 cmd->error, data ? data->error : 0,
724 cmd->opcode, cmd->retries);
Andrew Victor65dbf342006-04-02 19:18:51 +0100725 }
726 }
727 else
Pierre Ossman17b04292007-07-22 22:18:46 +0200728 cmd->error = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100729
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200730 at91_mci_process_next(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100731}
732
733/*
734 * Handle an MMC request
735 */
736static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
737{
738 struct at91mci_host *host = mmc_priv(mmc);
739 host->request = mrq;
740 host->flags = 0;
741
Wolfgang Mueesa04ac5b2010-03-05 13:43:39 -0800742 /* more than 1s timeout needed with slow SD cards */
743 mod_timer(&host->timer, jiffies + msecs_to_jiffies(2000));
Marc Pignate181dce2008-05-30 14:06:32 +0200744
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200745 at91_mci_process_next(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100746}
747
748/*
749 * Set the IOS
750 */
751static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
752{
753 int clkdiv;
754 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor3dd3b032006-10-23 14:46:54 +0200755 unsigned long at91_master_clock = clk_get_rate(host->mci_clk);
Andrew Victor65dbf342006-04-02 19:18:51 +0100756
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100757 host->bus_mode = ios->bus_mode;
Andrew Victor65dbf342006-04-02 19:18:51 +0100758
759 if (ios->clock == 0) {
760 /* Disable the MCI controller */
Andrew Victore0b19b82006-10-25 19:42:38 +0200761 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100762 clkdiv = 0;
763 }
764 else {
765 /* Enable the MCI controller */
Andrew Victore0b19b82006-10-25 19:42:38 +0200766 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
Andrew Victor65dbf342006-04-02 19:18:51 +0100767
768 if ((at91_master_clock % (ios->clock * 2)) == 0)
769 clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
770 else
771 clkdiv = (at91_master_clock / ios->clock) / 2;
772
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100773 pr_debug("clkdiv = %d. mcck = %ld\n", clkdiv,
Andrew Victor65dbf342006-04-02 19:18:51 +0100774 at91_master_clock / (2 * (clkdiv + 1)));
775 }
776 if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100777 pr_debug("MMC: Setting controller bus width to 4\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200778 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100779 }
780 else {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100781 pr_debug("MMC: Setting controller bus width to 1\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200782 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100783 }
784
785 /* Set the clock divider */
Andrew Victore0b19b82006-10-25 19:42:38 +0200786 at91_mci_write(host, AT91_MCI_MR, (at91_mci_read(host, AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv);
Andrew Victor65dbf342006-04-02 19:18:51 +0100787
788 /* maybe switch power to the card */
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100789 if (host->board->vcc_pin) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100790 switch (ios->power_mode) {
791 case MMC_POWER_OFF:
David Brownell6e996ee2008-02-04 18:12:48 +0100792 gpio_set_value(host->board->vcc_pin, 0);
Andrew Victor65dbf342006-04-02 19:18:51 +0100793 break;
794 case MMC_POWER_UP:
David Brownell6e996ee2008-02-04 18:12:48 +0100795 gpio_set_value(host->board->vcc_pin, 1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100796 break;
Marc Pignate5c0ef92008-05-09 11:07:07 +0200797 case MMC_POWER_ON:
798 break;
799 default:
800 WARN_ON(1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100801 }
802 }
803}
804
805/*
806 * Handle an interrupt
807 */
David Howells7d12e782006-10-05 14:55:46 +0100808static irqreturn_t at91_mci_irq(int irq, void *devid)
Andrew Victor65dbf342006-04-02 19:18:51 +0100809{
810 struct at91mci_host *host = devid;
811 int completed = 0;
Andrew Victordf05a302006-10-23 14:50:09 +0200812 unsigned int int_status, int_mask;
Andrew Victor65dbf342006-04-02 19:18:51 +0100813
Andrew Victore0b19b82006-10-25 19:42:38 +0200814 int_status = at91_mci_read(host, AT91_MCI_SR);
Andrew Victordf05a302006-10-23 14:50:09 +0200815 int_mask = at91_mci_read(host, AT91_MCI_IMR);
Nicolas Ferre37b758e82007-08-08 12:01:44 +0200816
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200817 pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask,
Andrew Victordf05a302006-10-23 14:50:09 +0200818 int_status & int_mask);
Nicolas Ferre37b758e82007-08-08 12:01:44 +0200819
Andrew Victordf05a302006-10-23 14:50:09 +0200820 int_status = int_status & int_mask;
Andrew Victor65dbf342006-04-02 19:18:51 +0100821
Andrew Victordf05a302006-10-23 14:50:09 +0200822 if (int_status & AT91_MCI_ERRORS) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100823 completed = 1;
Nicolas Ferre37b758e82007-08-08 12:01:44 +0200824
Andrew Victordf05a302006-10-23 14:50:09 +0200825 if (int_status & AT91_MCI_UNRE)
826 pr_debug("MMC: Underrun error\n");
827 if (int_status & AT91_MCI_OVRE)
828 pr_debug("MMC: Overrun error\n");
829 if (int_status & AT91_MCI_DTOE)
830 pr_debug("MMC: Data timeout\n");
831 if (int_status & AT91_MCI_DCRCE)
832 pr_debug("MMC: CRC error in data\n");
833 if (int_status & AT91_MCI_RTOE)
834 pr_debug("MMC: Response timeout\n");
835 if (int_status & AT91_MCI_RENDE)
836 pr_debug("MMC: Response end bit error\n");
837 if (int_status & AT91_MCI_RCRCE)
838 pr_debug("MMC: Response CRC error\n");
839 if (int_status & AT91_MCI_RDIRE)
840 pr_debug("MMC: Response direction error\n");
841 if (int_status & AT91_MCI_RINDE)
842 pr_debug("MMC: Response index error\n");
843 } else {
844 /* Only continue processing if no errors */
Andrew Victor65dbf342006-04-02 19:18:51 +0100845
Andrew Victor65dbf342006-04-02 19:18:51 +0100846 if (int_status & AT91_MCI_TXBUFE) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100847 pr_debug("TX buffer empty\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100848 at91_mci_handle_transmitted(host);
849 }
850
Nicolas Ferreed99c542007-07-09 14:58:16 +0200851 if (int_status & AT91_MCI_ENDRX) {
852 pr_debug("ENDRX\n");
853 at91_mci_post_dma_read(host);
854 }
855
Andrew Victor65dbf342006-04-02 19:18:51 +0100856 if (int_status & AT91_MCI_RXBUFF) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100857 pr_debug("RX buffer full\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200858 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
859 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_RXBUFF | AT91_MCI_ENDRX);
860 completed = 1;
Andrew Victor65dbf342006-04-02 19:18:51 +0100861 }
862
Andrew Victordf05a302006-10-23 14:50:09 +0200863 if (int_status & AT91_MCI_ENDTX)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100864 pr_debug("Transmit has ended\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100865
Andrew Victor65dbf342006-04-02 19:18:51 +0100866 if (int_status & AT91_MCI_NOTBUSY) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100867 pr_debug("Card is ready\n");
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200868 at91_mci_update_bytes_xfered(host);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200869 completed = 1;
Andrew Victor65dbf342006-04-02 19:18:51 +0100870 }
871
Andrew Victordf05a302006-10-23 14:50:09 +0200872 if (int_status & AT91_MCI_DTIP)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100873 pr_debug("Data transfer in progress\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100874
Nicolas Ferreed99c542007-07-09 14:58:16 +0200875 if (int_status & AT91_MCI_BLKE) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100876 pr_debug("Block transfer has ended\n");
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200877 if (host->request->data && host->request->data->blocks > 1) {
878 /* multi block write : complete multi write
879 * command and send stop */
880 completed = 1;
881 } else {
882 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
883 }
Nicolas Ferreed99c542007-07-09 14:58:16 +0200884 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100885
Eric Benard7a6588b2008-05-30 14:26:05 +0200886 if (int_status & AT91_MCI_SDIOIRQA)
887 mmc_signal_sdio_irq(host->mmc);
888
889 if (int_status & AT91_MCI_SDIOIRQB)
890 mmc_signal_sdio_irq(host->mmc);
891
Andrew Victordf05a302006-10-23 14:50:09 +0200892 if (int_status & AT91_MCI_TXRDY)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100893 pr_debug("Ready to transmit\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100894
Andrew Victordf05a302006-10-23 14:50:09 +0200895 if (int_status & AT91_MCI_RXRDY)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100896 pr_debug("Ready to receive\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100897
898 if (int_status & AT91_MCI_CMDRDY) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100899 pr_debug("Command ready\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200900 completed = at91_mci_handle_cmdrdy(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100901 }
902 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100903
904 if (completed) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100905 pr_debug("Completed command\n");
Eric Benard7a6588b2008-05-30 14:26:05 +0200906 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200907 at91_mci_completed_command(host, int_status);
Andrew Victordf05a302006-10-23 14:50:09 +0200908 } else
Eric Benard7a6588b2008-05-30 14:26:05 +0200909 at91_mci_write(host, AT91_MCI_IDR, int_status & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Andrew Victor65dbf342006-04-02 19:18:51 +0100910
911 return IRQ_HANDLED;
912}
913
David Howells7d12e782006-10-05 14:55:46 +0100914static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100915{
916 struct at91mci_host *host = _host;
David Brownell6e996ee2008-02-04 18:12:48 +0100917 int present = !gpio_get_value(irq_to_gpio(irq));
Andrew Victor65dbf342006-04-02 19:18:51 +0100918
919 /*
920 * we expect this irq on both insert and remove,
921 * and use a short delay to debounce.
922 */
923 if (present != host->present) {
924 host->present = present;
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100925 pr_debug("%s: card %s\n", mmc_hostname(host->mmc),
Andrew Victor65dbf342006-04-02 19:18:51 +0100926 present ? "insert" : "remove");
927 if (!present) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100928 pr_debug("****** Resetting SD-card bus width ******\n");
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100929 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100930 }
Wolfgang Mueesa04ac5b2010-03-05 13:43:39 -0800931 /* 0.5s needed because of early card detect switch firing */
932 mmc_detect_change(host->mmc, msecs_to_jiffies(500));
Andrew Victor65dbf342006-04-02 19:18:51 +0100933 }
934 return IRQ_HANDLED;
935}
936
David Brownella26b4982006-12-26 14:45:26 -0800937static int at91_mci_get_ro(struct mmc_host *mmc)
Andrew Victor65dbf342006-04-02 19:18:51 +0100938{
Andrew Victor65dbf342006-04-02 19:18:51 +0100939 struct at91mci_host *host = mmc_priv(mmc);
940
Anton Vorontsov08f80bb2008-06-17 18:17:39 +0400941 if (host->board->wp_pin)
942 return !!gpio_get_value(host->board->wp_pin);
943 /*
944 * Board doesn't support read only detection; let the mmc core
945 * decide what to do.
946 */
947 return -ENOSYS;
Andrew Victor65dbf342006-04-02 19:18:51 +0100948}
949
Eric Benard7a6588b2008-05-30 14:26:05 +0200950static void at91_mci_enable_sdio_irq(struct mmc_host *mmc, int enable)
951{
952 struct at91mci_host *host = mmc_priv(mmc);
953
954 pr_debug("%s: sdio_irq %c : %s\n", mmc_hostname(host->mmc),
955 host->board->slot_b ? 'B':'A', enable ? "enable" : "disable");
956 at91_mci_write(host, enable ? AT91_MCI_IER : AT91_MCI_IDR,
957 host->board->slot_b ? AT91_MCI_SDIOIRQB : AT91_MCI_SDIOIRQA);
958
959}
960
David Brownellab7aefd2006-11-12 17:55:30 -0800961static const struct mmc_host_ops at91_mci_ops = {
Andrew Victor65dbf342006-04-02 19:18:51 +0100962 .request = at91_mci_request,
963 .set_ios = at91_mci_set_ios,
964 .get_ro = at91_mci_get_ro,
Eric Benard7a6588b2008-05-30 14:26:05 +0200965 .enable_sdio_irq = at91_mci_enable_sdio_irq,
Andrew Victor65dbf342006-04-02 19:18:51 +0100966};
967
968/*
969 * Probe for the device
970 */
David Brownella26b4982006-12-26 14:45:26 -0800971static int __init at91_mci_probe(struct platform_device *pdev)
Andrew Victor65dbf342006-04-02 19:18:51 +0100972{
973 struct mmc_host *mmc;
974 struct at91mci_host *host;
Andrew Victor17ea0592006-10-23 14:44:40 +0200975 struct resource *res;
Andrew Victor65dbf342006-04-02 19:18:51 +0100976 int ret;
977
Andrew Victor17ea0592006-10-23 14:44:40 +0200978 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
979 if (!res)
980 return -ENXIO;
981
982 if (!request_mem_region(res->start, res->end - res->start + 1, DRIVER_NAME))
983 return -EBUSY;
984
Andrew Victor65dbf342006-04-02 19:18:51 +0100985 mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
986 if (!mmc) {
David Brownell6e996ee2008-02-04 18:12:48 +0100987 ret = -ENOMEM;
988 dev_dbg(&pdev->dev, "couldn't allocate mmc host\n");
989 goto fail6;
Andrew Victor65dbf342006-04-02 19:18:51 +0100990 }
991
992 mmc->ops = &at91_mci_ops;
993 mmc->f_min = 375000;
994 mmc->f_max = 25000000;
995 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
Pierre Ossman23af6032008-07-06 01:10:27 +0200996 mmc->caps = MMC_CAP_SDIO_IRQ;
Andrew Victor65dbf342006-04-02 19:18:51 +0100997
Wolfgang Muees3780d902010-03-05 13:43:40 -0800998 mmc->max_blk_size = MCI_MAXBLKSIZE;
999 mmc->max_blk_count = MCI_BLKATONCE;
1000 mmc->max_req_size = MCI_BUFSIZE;
Pierre Ossmanfe4a3c72006-11-21 17:54:23 +01001001
Andrew Victor65dbf342006-04-02 19:18:51 +01001002 host = mmc_priv(mmc);
1003 host->mmc = mmc;
Andrew Victor65dbf342006-04-02 19:18:51 +01001004 host->bus_mode = 0;
1005 host->board = pdev->dev.platform_data;
1006 if (host->board->wire4) {
Nicolas Ferreed99c542007-07-09 14:58:16 +02001007 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
1008 mmc->caps |= MMC_CAP_4_BIT_DATA;
1009 else
David Brownell6e996ee2008-02-04 18:12:48 +01001010 dev_warn(&pdev->dev, "4 wire bus mode not supported"
Nicolas Ferreed99c542007-07-09 14:58:16 +02001011 " - using 1 wire\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001012 }
1013
Wolfgang Muees3780d902010-03-05 13:43:40 -08001014 host->buffer = dma_alloc_coherent(&pdev->dev, MCI_BUFSIZE,
1015 &host->physical_address, GFP_KERNEL);
1016 if (!host->buffer) {
1017 ret = -ENOMEM;
1018 dev_err(&pdev->dev, "Can't allocate transmit buffer\n");
1019 goto fail5;
1020 }
1021
Andrew Victor65dbf342006-04-02 19:18:51 +01001022 /*
David Brownell6e996ee2008-02-04 18:12:48 +01001023 * Reserve GPIOs ... board init code makes sure these pins are set
1024 * up as GPIOs with the right direction (input, except for vcc)
1025 */
1026 if (host->board->det_pin) {
1027 ret = gpio_request(host->board->det_pin, "mmc_detect");
1028 if (ret < 0) {
1029 dev_dbg(&pdev->dev, "couldn't claim card detect pin\n");
Wolfgang Muees3780d902010-03-05 13:43:40 -08001030 goto fail4b;
David Brownell6e996ee2008-02-04 18:12:48 +01001031 }
1032 }
1033 if (host->board->wp_pin) {
1034 ret = gpio_request(host->board->wp_pin, "mmc_wp");
1035 if (ret < 0) {
1036 dev_dbg(&pdev->dev, "couldn't claim wp sense pin\n");
1037 goto fail4;
1038 }
1039 }
1040 if (host->board->vcc_pin) {
1041 ret = gpio_request(host->board->vcc_pin, "mmc_vcc");
1042 if (ret < 0) {
1043 dev_dbg(&pdev->dev, "couldn't claim vcc switch pin\n");
1044 goto fail3;
1045 }
1046 }
1047
1048 /*
Andrew Victor65dbf342006-04-02 19:18:51 +01001049 * Get Clock
1050 */
Andrew Victor3dd3b032006-10-23 14:46:54 +02001051 host->mci_clk = clk_get(&pdev->dev, "mci_clk");
1052 if (IS_ERR(host->mci_clk)) {
David Brownell6e996ee2008-02-04 18:12:48 +01001053 ret = -ENODEV;
1054 dev_dbg(&pdev->dev, "no mci_clk?\n");
1055 goto fail2;
Andrew Victor65dbf342006-04-02 19:18:51 +01001056 }
Andrew Victor65dbf342006-04-02 19:18:51 +01001057
Andrew Victor17ea0592006-10-23 14:44:40 +02001058 /*
1059 * Map I/O region
1060 */
1061 host->baseaddr = ioremap(res->start, res->end - res->start + 1);
1062 if (!host->baseaddr) {
David Brownell6e996ee2008-02-04 18:12:48 +01001063 ret = -ENOMEM;
1064 goto fail1;
Andrew Victor17ea0592006-10-23 14:44:40 +02001065 }
Andrew Victore0b19b82006-10-25 19:42:38 +02001066
1067 /*
1068 * Reset hardware
1069 */
Andrew Victor3dd3b032006-10-23 14:46:54 +02001070 clk_enable(host->mci_clk); /* Enable the peripheral clock */
Andrew Victore0b19b82006-10-25 19:42:38 +02001071 at91_mci_disable(host);
1072 at91_mci_enable(host);
1073
Andrew Victor65dbf342006-04-02 19:18:51 +01001074 /*
1075 * Allocate the MCI interrupt
1076 */
Andrew Victor17ea0592006-10-23 14:44:40 +02001077 host->irq = platform_get_irq(pdev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +01001078 ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED,
1079 mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001080 if (ret) {
David Brownell6e996ee2008-02-04 18:12:48 +01001081 dev_dbg(&pdev->dev, "request MCI interrupt failed\n");
1082 goto fail0;
Andrew Victor65dbf342006-04-02 19:18:51 +01001083 }
1084
Nicolas Ferre99ba0402008-11-27 17:23:49 +01001085 setup_timer(&host->timer, at91_timeout_timer, (unsigned long)host);
1086
Andrew Victor65dbf342006-04-02 19:18:51 +01001087 platform_set_drvdata(pdev, mmc);
1088
1089 /*
1090 * Add host to MMC layer
1091 */
Marc Pignat63b66432007-07-16 11:07:02 +02001092 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001093 host->present = !gpio_get_value(host->board->det_pin);
Marc Pignat63b66432007-07-16 11:07:02 +02001094 }
Andrew Victor65dbf342006-04-02 19:18:51 +01001095 else
1096 host->present = -1;
1097
1098 mmc_add_host(mmc);
1099
1100 /*
1101 * monitor card insertion/removal if we can
1102 */
1103 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001104 ret = request_irq(gpio_to_irq(host->board->det_pin),
1105 at91_mmc_det_irq, 0, mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001106 if (ret)
David Brownell6e996ee2008-02-04 18:12:48 +01001107 dev_warn(&pdev->dev, "request MMC detect irq failed\n");
1108 else
1109 device_init_wakeup(&pdev->dev, 1);
Andrew Victor65dbf342006-04-02 19:18:51 +01001110 }
1111
Andrew Victorf3a8efa2006-10-23 14:53:20 +02001112 pr_debug("Added MCI driver\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001113
1114 return 0;
David Brownell6e996ee2008-02-04 18:12:48 +01001115
1116fail0:
1117 clk_disable(host->mci_clk);
1118 iounmap(host->baseaddr);
1119fail1:
1120 clk_put(host->mci_clk);
1121fail2:
1122 if (host->board->vcc_pin)
1123 gpio_free(host->board->vcc_pin);
1124fail3:
1125 if (host->board->wp_pin)
1126 gpio_free(host->board->wp_pin);
1127fail4:
1128 if (host->board->det_pin)
1129 gpio_free(host->board->det_pin);
Wolfgang Muees3780d902010-03-05 13:43:40 -08001130fail4b:
1131 if (host->buffer)
1132 dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
1133 host->buffer, host->physical_address);
David Brownell6e996ee2008-02-04 18:12:48 +01001134fail5:
1135 mmc_free_host(mmc);
1136fail6:
1137 release_mem_region(res->start, res->end - res->start + 1);
1138 dev_err(&pdev->dev, "probe failed, err %d\n", ret);
1139 return ret;
Andrew Victor65dbf342006-04-02 19:18:51 +01001140}
1141
1142/*
1143 * Remove a device
1144 */
David Brownella26b4982006-12-26 14:45:26 -08001145static int __exit at91_mci_remove(struct platform_device *pdev)
Andrew Victor65dbf342006-04-02 19:18:51 +01001146{
1147 struct mmc_host *mmc = platform_get_drvdata(pdev);
1148 struct at91mci_host *host;
Andrew Victor17ea0592006-10-23 14:44:40 +02001149 struct resource *res;
Andrew Victor65dbf342006-04-02 19:18:51 +01001150
1151 if (!mmc)
1152 return -1;
1153
1154 host = mmc_priv(mmc);
1155
Wolfgang Muees3780d902010-03-05 13:43:40 -08001156 if (host->buffer)
1157 dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
1158 host->buffer, host->physical_address);
1159
Anti Sulline0cda542007-08-30 16:15:16 +02001160 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001161 if (device_can_wakeup(&pdev->dev))
1162 free_irq(gpio_to_irq(host->board->det_pin), host);
Marc Pignat63b66432007-07-16 11:07:02 +02001163 device_init_wakeup(&pdev->dev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +01001164 gpio_free(host->board->det_pin);
Andrew Victor65dbf342006-04-02 19:18:51 +01001165 }
1166
Andrew Victore0b19b82006-10-25 19:42:38 +02001167 at91_mci_disable(host);
Marc Pignate181dce2008-05-30 14:06:32 +02001168 del_timer_sync(&host->timer);
Andrew Victor17ea0592006-10-23 14:44:40 +02001169 mmc_remove_host(mmc);
1170 free_irq(host->irq, host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001171
Andrew Victor3dd3b032006-10-23 14:46:54 +02001172 clk_disable(host->mci_clk); /* Disable the peripheral clock */
1173 clk_put(host->mci_clk);
Andrew Victor65dbf342006-04-02 19:18:51 +01001174
David Brownell6e996ee2008-02-04 18:12:48 +01001175 if (host->board->vcc_pin)
1176 gpio_free(host->board->vcc_pin);
1177 if (host->board->wp_pin)
1178 gpio_free(host->board->wp_pin);
1179
Andrew Victor17ea0592006-10-23 14:44:40 +02001180 iounmap(host->baseaddr);
1181 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1182 release_mem_region(res->start, res->end - res->start + 1);
Andrew Victor65dbf342006-04-02 19:18:51 +01001183
Andrew Victor17ea0592006-10-23 14:44:40 +02001184 mmc_free_host(mmc);
1185 platform_set_drvdata(pdev, NULL);
Andrew Victorb44fb7a2006-06-19 13:06:05 +01001186 pr_debug("MCI Removed\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001187
1188 return 0;
1189}
1190
1191#ifdef CONFIG_PM
1192static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
1193{
1194 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001195 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001196 int ret = 0;
1197
Anti Sulline0cda542007-08-30 16:15:16 +02001198 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001199 enable_irq_wake(host->board->det_pin);
1200
Andrew Victor65dbf342006-04-02 19:18:51 +01001201 if (mmc)
1202 ret = mmc_suspend_host(mmc, state);
1203
1204 return ret;
1205}
1206
1207static int at91_mci_resume(struct platform_device *pdev)
1208{
1209 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001210 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001211 int ret = 0;
1212
Anti Sulline0cda542007-08-30 16:15:16 +02001213 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001214 disable_irq_wake(host->board->det_pin);
1215
Andrew Victor65dbf342006-04-02 19:18:51 +01001216 if (mmc)
1217 ret = mmc_resume_host(mmc);
1218
1219 return ret;
1220}
1221#else
1222#define at91_mci_suspend NULL
1223#define at91_mci_resume NULL
1224#endif
1225
1226static struct platform_driver at91_mci_driver = {
David Brownella26b4982006-12-26 14:45:26 -08001227 .remove = __exit_p(at91_mci_remove),
Andrew Victor65dbf342006-04-02 19:18:51 +01001228 .suspend = at91_mci_suspend,
1229 .resume = at91_mci_resume,
1230 .driver = {
1231 .name = DRIVER_NAME,
1232 .owner = THIS_MODULE,
1233 },
1234};
1235
1236static int __init at91_mci_init(void)
1237{
David Brownella26b4982006-12-26 14:45:26 -08001238 return platform_driver_probe(&at91_mci_driver, at91_mci_probe);
Andrew Victor65dbf342006-04-02 19:18:51 +01001239}
1240
1241static void __exit at91_mci_exit(void)
1242{
1243 platform_driver_unregister(&at91_mci_driver);
1244}
1245
1246module_init(at91_mci_init);
1247module_exit(at91_mci_exit);
1248
1249MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
1250MODULE_AUTHOR("Nick Randell");
1251MODULE_LICENSE("GPL");
Kay Sieversbc65c722008-04-15 14:34:28 -07001252MODULE_ALIAS("platform:at91_mci");