blob: e556d42cc45a755597e435e54e21235113611505 [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 Victor99eeb8df2006-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 Victor99eeb8df2006-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
Andrew Victor65dbf342006-04-02 19:18:51 +010075#include <asm/mach/mmc.h>
Russell Kinga09e64f2008-08-05 16:14:15 +010076#include <mach/board.h>
77#include <mach/cpu.h>
78#include <mach/at91_mci.h>
Andrew Victor65dbf342006-04-02 19:18:51 +010079
80#define DRIVER_NAME "at91_mci"
81
Andrew Victordf05a302006-10-23 14:50:09 +020082#define FL_SENT_COMMAND (1 << 0)
83#define FL_SENT_STOP (1 << 1)
Andrew Victor65dbf342006-04-02 19:18:51 +010084
Andrew Victordf05a302006-10-23 14:50:09 +020085#define AT91_MCI_ERRORS (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE \
86 | AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE \
Nicolas Ferre37b758e2007-08-08 12:01:44 +020087 | AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)
Andrew Victor65dbf342006-04-02 19:18:51 +010088
Andrew Victore0b19b82006-10-25 19:42:38 +020089#define at91_mci_read(host, reg) __raw_readl((host)->baseaddr + (reg))
90#define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg))
Andrew Victor65dbf342006-04-02 19:18:51 +010091
Andrew Victor65dbf342006-04-02 19:18:51 +010092
93/*
94 * Low level type for this driver
95 */
96struct at91mci_host
97{
98 struct mmc_host *mmc;
99 struct mmc_command *cmd;
100 struct mmc_request *request;
101
Andrew Victore0b19b82006-10-25 19:42:38 +0200102 void __iomem *baseaddr;
Andrew Victor17ea0592006-10-23 14:44:40 +0200103 int irq;
Andrew Victore0b19b82006-10-25 19:42:38 +0200104
Andrew Victor65dbf342006-04-02 19:18:51 +0100105 struct at91_mmc_data *board;
106 int present;
107
Andrew Victor3dd3b032006-10-23 14:46:54 +0200108 struct clk *mci_clk;
109
Andrew Victor65dbf342006-04-02 19:18:51 +0100110 /*
111 * Flag indicating when the command has been sent. This is used to
112 * work out whether or not to send the stop
113 */
114 unsigned int flags;
115 /* flag for current bus settings */
116 u32 bus_mode;
117
118 /* DMA buffer used for transmitting */
119 unsigned int* buffer;
120 dma_addr_t physical_address;
121 unsigned int total_length;
122
123 /* Latest in the scatterlist that has been enabled for transfer, but not freed */
124 int in_use_index;
125
126 /* Latest in the scatterlist that has been enabled for transfer */
127 int transfer_index;
Marc Pignate181dce2008-05-30 14:06:32 +0200128
129 /* Timer for timeouts */
130 struct timer_list timer;
Andrew Victor65dbf342006-04-02 19:18:51 +0100131};
132
Marc Pignatc5a89c62008-05-30 14:07:47 +0200133/*
134 * Reset the controller and restore most of the state
135 */
136static void at91_reset_host(struct at91mci_host *host)
137{
138 unsigned long flags;
139 u32 mr;
140 u32 sdcr;
141 u32 dtor;
142 u32 imr;
143
144 local_irq_save(flags);
145 imr = at91_mci_read(host, AT91_MCI_IMR);
146
147 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
148
149 /* save current state */
150 mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
151 sdcr = at91_mci_read(host, AT91_MCI_SDCR);
152 dtor = at91_mci_read(host, AT91_MCI_DTOR);
153
154 /* reset the controller */
155 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
156
157 /* restore state */
158 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
159 at91_mci_write(host, AT91_MCI_MR, mr);
160 at91_mci_write(host, AT91_MCI_SDCR, sdcr);
161 at91_mci_write(host, AT91_MCI_DTOR, dtor);
162 at91_mci_write(host, AT91_MCI_IER, imr);
163
164 /* make sure sdio interrupts will fire */
165 at91_mci_read(host, AT91_MCI_SR);
166
167 local_irq_restore(flags);
168}
169
Marc Pignate181dce2008-05-30 14:06:32 +0200170static void at91_timeout_timer(unsigned long data)
171{
172 struct at91mci_host *host;
173
174 host = (struct at91mci_host *)data;
175
176 if (host->request) {
177 dev_err(host->mmc->parent, "Timeout waiting end of packet\n");
178
179 if (host->cmd && host->cmd->data) {
180 host->cmd->data->error = -ETIMEDOUT;
181 } else {
182 if (host->cmd)
183 host->cmd->error = -ETIMEDOUT;
184 else
185 host->request->cmd->error = -ETIMEDOUT;
186 }
187
Marc Pignatc5a89c62008-05-30 14:07:47 +0200188 at91_reset_host(host);
Marc Pignate181dce2008-05-30 14:06:32 +0200189 mmc_request_done(host->mmc, host->request);
190 }
191}
192
Andrew Victor65dbf342006-04-02 19:18:51 +0100193/*
194 * Copy from sg to a dma block - used for transfers
195 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200196static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
Andrew Victor65dbf342006-04-02 19:18:51 +0100197{
198 unsigned int len, i, size;
199 unsigned *dmabuf = host->buffer;
200
Ville Syrjala5385edc2008-06-14 20:27:20 +0300201 size = data->blksz * data->blocks;
Andrew Victor65dbf342006-04-02 19:18:51 +0100202 len = data->sg_len;
203
Ville Syrjala5385edc2008-06-14 20:27:20 +0300204 /* AT91SAM926[0/3] Data Write Operation and number of bytes erratum */
205 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
206 if (host->total_length == 12)
207 memset(dmabuf, 0, 12);
208
Andrew Victor65dbf342006-04-02 19:18:51 +0100209 /*
210 * Just loop through all entries. Size might not
211 * be the entire list though so make sure that
212 * we do not transfer too much.
213 */
214 for (i = 0; i < len; i++) {
215 struct scatterlist *sg;
216 int amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100217 unsigned int *sgbuffer;
218
219 sg = &data->sg[i];
220
Jens Axboe45711f12007-10-22 21:19:53 +0200221 sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
Andrew Victor65dbf342006-04-02 19:18:51 +0100222 amount = min(size, sg->length);
223 size -= amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100224
Andrew Victor99eeb8df2006-12-11 12:40:23 +0100225 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
226 int index;
227
228 for (index = 0; index < (amount / 4); index++)
229 *dmabuf++ = swab32(sgbuffer[index]);
Ville Syrjala5385edc2008-06-14 20:27:20 +0300230 } else {
Andrew Victor99eeb8df2006-12-11 12:40:23 +0100231 memcpy(dmabuf, sgbuffer, amount);
Ville Syrjala5385edc2008-06-14 20:27:20 +0300232 dmabuf += amount;
233 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100234
235 kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
236
237 if (size == 0)
238 break;
239 }
240
241 /*
242 * Check that we didn't get a request to transfer
243 * more data than can fit into the SG list.
244 */
245 BUG_ON(size != 0);
246}
247
248/*
249 * Prepare a dma read
250 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200251static void at91_mci_pre_dma_read(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100252{
253 int i;
254 struct scatterlist *sg;
255 struct mmc_command *cmd;
256 struct mmc_data *data;
257
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100258 pr_debug("pre dma read\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100259
260 cmd = host->cmd;
261 if (!cmd) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100262 pr_debug("no command\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100263 return;
264 }
265
266 data = cmd->data;
267 if (!data) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100268 pr_debug("no data\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100269 return;
270 }
271
272 for (i = 0; i < 2; i++) {
273 /* nothing left to transfer */
274 if (host->transfer_index >= data->sg_len) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100275 pr_debug("Nothing left to transfer (index = %d)\n", host->transfer_index);
Andrew Victor65dbf342006-04-02 19:18:51 +0100276 break;
277 }
278
279 /* Check to see if this needs filling */
280 if (i == 0) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100281 if (at91_mci_read(host, ATMEL_PDC_RCR) != 0) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100282 pr_debug("Transfer active in current\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100283 continue;
284 }
285 }
286 else {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100287 if (at91_mci_read(host, ATMEL_PDC_RNCR) != 0) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100288 pr_debug("Transfer active in next\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100289 continue;
290 }
291 }
292
293 /* Setup the next transfer */
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100294 pr_debug("Using transfer index %d\n", host->transfer_index);
Andrew Victor65dbf342006-04-02 19:18:51 +0100295
296 sg = &data->sg[host->transfer_index++];
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100297 pr_debug("sg = %p\n", sg);
Andrew Victor65dbf342006-04-02 19:18:51 +0100298
Jens Axboe45711f12007-10-22 21:19:53 +0200299 sg->dma_address = dma_map_page(NULL, sg_page(sg), sg->offset, sg->length, DMA_FROM_DEVICE);
Andrew Victor65dbf342006-04-02 19:18:51 +0100300
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100301 pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
Andrew Victor65dbf342006-04-02 19:18:51 +0100302
303 if (i == 0) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100304 at91_mci_write(host, ATMEL_PDC_RPR, sg->dma_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200305 at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ? sg->length : sg->length / 4);
Andrew Victor65dbf342006-04-02 19:18:51 +0100306 }
307 else {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100308 at91_mci_write(host, ATMEL_PDC_RNPR, sg->dma_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200309 at91_mci_write(host, ATMEL_PDC_RNCR, (data->blksz & 0x3) ? sg->length : sg->length / 4);
Andrew Victor65dbf342006-04-02 19:18:51 +0100310 }
311 }
312
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100313 pr_debug("pre dma read done\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100314}
315
316/*
317 * Handle after a dma read
318 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200319static void at91_mci_post_dma_read(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100320{
321 struct mmc_command *cmd;
322 struct mmc_data *data;
323
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100324 pr_debug("post dma read\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100325
326 cmd = host->cmd;
327 if (!cmd) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100328 pr_debug("no command\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100329 return;
330 }
331
332 data = cmd->data;
333 if (!data) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100334 pr_debug("no data\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100335 return;
336 }
337
338 while (host->in_use_index < host->transfer_index) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100339 struct scatterlist *sg;
340
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100341 pr_debug("finishing index %d\n", host->in_use_index);
Andrew Victor65dbf342006-04-02 19:18:51 +0100342
343 sg = &data->sg[host->in_use_index++];
344
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100345 pr_debug("Unmapping page %08X\n", sg->dma_address);
Andrew Victor65dbf342006-04-02 19:18:51 +0100346
347 dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
348
Andrew Victor99eeb8df2006-12-11 12:40:23 +0100349 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
Nicolas Ferreed99c542007-07-09 14:58:16 +0200350 unsigned int *buffer;
Andrew Victor99eeb8df2006-12-11 12:40:23 +0100351 int index;
Andrew Victor65dbf342006-04-02 19:18:51 +0100352
Nicolas Ferreed99c542007-07-09 14:58:16 +0200353 /* Swap the contents of the buffer */
Jens Axboe45711f12007-10-22 21:19:53 +0200354 buffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200355 pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
356
Andrew Victor99eeb8df2006-12-11 12:40:23 +0100357 for (index = 0; index < (sg->length / 4); index++)
358 buffer[index] = swab32(buffer[index]);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200359
360 kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
Andrew Victor65dbf342006-04-02 19:18:51 +0100361 }
Andrew Victor99eeb8df2006-12-11 12:40:23 +0100362
Jens Axboe45711f12007-10-22 21:19:53 +0200363 flush_dcache_page(sg_page(sg));
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200364
365 data->bytes_xfered += sg->length;
Andrew Victor65dbf342006-04-02 19:18:51 +0100366 }
367
368 /* Is there another transfer to trigger? */
369 if (host->transfer_index < data->sg_len)
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200370 at91_mci_pre_dma_read(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100371 else {
Nicolas Ferreed99c542007-07-09 14:58:16 +0200372 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
Andrew Victore0b19b82006-10-25 19:42:38 +0200373 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
Andrew Victor65dbf342006-04-02 19:18:51 +0100374 }
375
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100376 pr_debug("post dma read done\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100377}
378
379/*
380 * Handle transmitted data
381 */
382static void at91_mci_handle_transmitted(struct at91mci_host *host)
383{
384 struct mmc_command *cmd;
385 struct mmc_data *data;
386
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100387 pr_debug("Handling the transmit\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100388
389 /* Disable the transfer */
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100390 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100391
392 /* Now wait for cmd ready */
Andrew Victore0b19b82006-10-25 19:42:38 +0200393 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
Andrew Victor65dbf342006-04-02 19:18:51 +0100394
395 cmd = host->cmd;
396 if (!cmd) return;
397
398 data = cmd->data;
399 if (!data) return;
400
Pierre Ossmanbe0192a2007-07-24 21:11:47 +0200401 if (cmd->data->blocks > 1) {
Nicolas Ferreed99c542007-07-09 14:58:16 +0200402 pr_debug("multiple write : wait for BLKE...\n");
403 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
404 } else
405 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
Andrew Victor65dbf342006-04-02 19:18:51 +0100406}
407
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200408/*
409 * Update bytes tranfered count during a write operation
410 */
411static void at91_mci_update_bytes_xfered(struct at91mci_host *host)
412{
413 struct mmc_data *data;
414
415 /* always deal with the effective request (and not the current cmd) */
416
417 if (host->request->cmd && host->request->cmd->error != 0)
418 return;
419
420 if (host->request->data) {
421 data = host->request->data;
422 if (data->flags & MMC_DATA_WRITE) {
423 /* card is in IDLE mode now */
424 pr_debug("-> bytes_xfered %d, total_length = %d\n",
425 data->bytes_xfered, host->total_length);
Ville Syrjala5385edc2008-06-14 20:27:20 +0300426 data->bytes_xfered = data->blksz * data->blocks;
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200427 }
428 }
429}
430
431
Nicolas Ferreed99c542007-07-09 14:58:16 +0200432/*Handle after command sent ready*/
433static int at91_mci_handle_cmdrdy(struct at91mci_host *host)
434{
435 if (!host->cmd)
436 return 1;
437 else if (!host->cmd->data) {
438 if (host->flags & FL_SENT_STOP) {
439 /*After multi block write, we must wait for NOTBUSY*/
440 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
441 } else return 1;
442 } else if (host->cmd->data->flags & MMC_DATA_WRITE) {
443 /*After sendding multi-block-write command, start DMA transfer*/
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200444 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE | AT91_MCI_BLKE);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200445 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
446 }
447
448 /* command not completed, have to wait */
449 return 0;
450}
451
452
Andrew Victor65dbf342006-04-02 19:18:51 +0100453/*
454 * Enable the controller
455 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200456static void at91_mci_enable(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100457{
Nicolas Ferreed99c542007-07-09 14:58:16 +0200458 unsigned int mr;
459
Andrew Victore0b19b82006-10-25 19:42:38 +0200460 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200461 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
Andrew Victore0b19b82006-10-25 19:42:38 +0200462 at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200463 mr = AT91_MCI_PDCMODE | 0x34a;
464
465 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
466 mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
467
468 at91_mci_write(host, AT91_MCI_MR, mr);
Andrew Victor99eeb8df2006-12-11 12:40:23 +0100469
470 /* use Slot A or B (only one at same time) */
471 at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
Andrew Victor65dbf342006-04-02 19:18:51 +0100472}
473
474/*
475 * Disable the controller
476 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200477static void at91_mci_disable(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100478{
Andrew Victore0b19b82006-10-25 19:42:38 +0200479 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
Andrew Victor65dbf342006-04-02 19:18:51 +0100480}
481
482/*
483 * Send a command
Andrew Victor65dbf342006-04-02 19:18:51 +0100484 */
Nicolas Ferreed99c542007-07-09 14:58:16 +0200485static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
Andrew Victor65dbf342006-04-02 19:18:51 +0100486{
487 unsigned int cmdr, mr;
488 unsigned int block_length;
489 struct mmc_data *data = cmd->data;
490
491 unsigned int blocks;
492 unsigned int ier = 0;
493
494 host->cmd = cmd;
495
Nicolas Ferreed99c542007-07-09 14:58:16 +0200496 /* Needed for leaving busy state before CMD1 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200497 if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100498 pr_debug("Clearing timeout\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200499 at91_mci_write(host, AT91_MCI_ARGR, 0);
500 at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
501 while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100502 /* spin */
Andrew Victore0b19b82006-10-25 19:42:38 +0200503 pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
Andrew Victor65dbf342006-04-02 19:18:51 +0100504 }
505 }
Nicolas Ferreed99c542007-07-09 14:58:16 +0200506
Andrew Victor65dbf342006-04-02 19:18:51 +0100507 cmdr = cmd->opcode;
508
509 if (mmc_resp_type(cmd) == MMC_RSP_NONE)
510 cmdr |= AT91_MCI_RSPTYP_NONE;
511 else {
512 /* if a response is expected then allow maximum response latancy */
513 cmdr |= AT91_MCI_MAXLAT;
514 /* set 136 bit response for R2, 48 bit response otherwise */
515 if (mmc_resp_type(cmd) == MMC_RSP_R2)
516 cmdr |= AT91_MCI_RSPTYP_136;
517 else
518 cmdr |= AT91_MCI_RSPTYP_48;
519 }
520
521 if (data) {
Marc Pignat1d4de9e2007-08-09 13:56:29 +0200522
Ville Syrjala9da3cba2008-06-09 22:06:44 +0300523 if (cpu_is_at91rm9200() || cpu_is_at91sam9261()) {
524 if (data->blksz & 0x3) {
525 pr_debug("Unsupported block size\n");
526 cmd->error = -EINVAL;
527 mmc_request_done(host->mmc, host->request);
528 return;
529 }
530 if (data->flags & MMC_DATA_STREAM) {
531 pr_debug("Stream commands not supported\n");
532 cmd->error = -EINVAL;
533 mmc_request_done(host->mmc, host->request);
534 return;
535 }
Marc Pignat1d4de9e2007-08-09 13:56:29 +0200536 }
537
Russell Kinga3fd4a12006-06-04 17:51:15 +0100538 block_length = data->blksz;
Andrew Victor65dbf342006-04-02 19:18:51 +0100539 blocks = data->blocks;
540
541 /* always set data start - also set direction flag for read */
542 if (data->flags & MMC_DATA_READ)
543 cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
544 else if (data->flags & MMC_DATA_WRITE)
545 cmdr |= AT91_MCI_TRCMD_START;
546
547 if (data->flags & MMC_DATA_STREAM)
548 cmdr |= AT91_MCI_TRTYP_STREAM;
Pierre Ossmanbe0192a2007-07-24 21:11:47 +0200549 if (data->blocks > 1)
Andrew Victor65dbf342006-04-02 19:18:51 +0100550 cmdr |= AT91_MCI_TRTYP_MULTIPLE;
551 }
552 else {
553 block_length = 0;
554 blocks = 0;
555 }
556
Marc Pignatb6cedb32007-06-06 20:27:59 +0200557 if (host->flags & FL_SENT_STOP)
Andrew Victor65dbf342006-04-02 19:18:51 +0100558 cmdr |= AT91_MCI_TRCMD_STOP;
559
560 if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
561 cmdr |= AT91_MCI_OPDCMD;
562
563 /*
564 * Set the arguments and send the command
565 */
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200566 pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
Andrew Victore0b19b82006-10-25 19:42:38 +0200567 cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
Andrew Victor65dbf342006-04-02 19:18:51 +0100568
569 if (!data) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100570 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
571 at91_mci_write(host, ATMEL_PDC_RPR, 0);
572 at91_mci_write(host, ATMEL_PDC_RCR, 0);
573 at91_mci_write(host, ATMEL_PDC_RNPR, 0);
574 at91_mci_write(host, ATMEL_PDC_RNCR, 0);
575 at91_mci_write(host, ATMEL_PDC_TPR, 0);
576 at91_mci_write(host, ATMEL_PDC_TCR, 0);
577 at91_mci_write(host, ATMEL_PDC_TNPR, 0);
578 at91_mci_write(host, ATMEL_PDC_TNCR, 0);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200579 ier = AT91_MCI_CMDRDY;
580 } else {
581 /* zero block length and PDC mode */
Ville Syrjala12bd2572008-06-09 22:06:45 +0300582 mr = at91_mci_read(host, AT91_MCI_MR) & 0x5fff;
Marc Pignat80f92542008-05-30 14:05:24 +0200583 mr |= (data->blksz & 0x3) ? AT91_MCI_PDCFBYTE : 0;
584 mr |= (block_length << 16);
585 mr |= AT91_MCI_PDCMODE;
586 at91_mci_write(host, AT91_MCI_MR, mr);
Andrew Victor65dbf342006-04-02 19:18:51 +0100587
Ville Syrjala9da3cba2008-06-09 22:06:44 +0300588 if (!(cpu_is_at91rm9200() || cpu_is_at91sam9261()))
Marc Pignatc5a89c62008-05-30 14:07:47 +0200589 at91_mci_write(host, AT91_MCI_BLKR,
590 AT91_MCI_BLKR_BCNT(blocks) |
591 AT91_MCI_BLKR_BLKLEN(block_length));
592
Nicolas Ferreed99c542007-07-09 14:58:16 +0200593 /*
594 * Disable the PDC controller
595 */
596 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100597
Nicolas Ferreed99c542007-07-09 14:58:16 +0200598 if (cmdr & AT91_MCI_TRCMD_START) {
599 data->bytes_xfered = 0;
600 host->transfer_index = 0;
601 host->in_use_index = 0;
602 if (cmdr & AT91_MCI_TRDIR) {
603 /*
604 * Handle a read
605 */
606 host->buffer = NULL;
607 host->total_length = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100608
Nicolas Ferreed99c542007-07-09 14:58:16 +0200609 at91_mci_pre_dma_read(host);
610 ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
611 }
612 else {
613 /*
614 * Handle a write
615 */
616 host->total_length = block_length * blocks;
Ville Syrjala5385edc2008-06-14 20:27:20 +0300617 /*
618 * AT91SAM926[0/3] Data Write Operation and
619 * number of bytes erratum
620 */
621 if (cpu_is_at91sam9260 () || cpu_is_at91sam9263())
622 if (host->total_length < 12)
623 host->total_length = 12;
David Brownelle385ea62008-09-02 14:35:46 -0700624
625 host->buffer = kmalloc(host->total_length, GFP_KERNEL);
626 if (!host->buffer) {
627 pr_debug("Can't alloc tx buffer\n");
628 cmd->error = -ENOMEM;
629 mmc_request_done(host->mmc, host->request);
630 return;
631 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100632
Nicolas Ferreed99c542007-07-09 14:58:16 +0200633 at91_mci_sg_to_dma(host, data);
Andrew Victor65dbf342006-04-02 19:18:51 +0100634
David Brownelle385ea62008-09-02 14:35:46 -0700635 host->physical_address = dma_map_single(NULL,
636 host->buffer, host->total_length,
637 DMA_TO_DEVICE);
638
Nicolas Ferreed99c542007-07-09 14:58:16 +0200639 pr_debug("Transmitting %d bytes\n", host->total_length);
Andrew Victor65dbf342006-04-02 19:18:51 +0100640
Nicolas Ferreed99c542007-07-09 14:58:16 +0200641 at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200642 at91_mci_write(host, ATMEL_PDC_TCR, (data->blksz & 0x3) ?
643 host->total_length : host->total_length / 4);
644
Nicolas Ferreed99c542007-07-09 14:58:16 +0200645 ier = AT91_MCI_CMDRDY;
646 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100647 }
648 }
649
650 /*
651 * Send the command and then enable the PDC - not the other way round as
652 * the data sheet says
653 */
654
Andrew Victore0b19b82006-10-25 19:42:38 +0200655 at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
656 at91_mci_write(host, AT91_MCI_CMDR, cmdr);
Andrew Victor65dbf342006-04-02 19:18:51 +0100657
658 if (cmdr & AT91_MCI_TRCMD_START) {
659 if (cmdr & AT91_MCI_TRDIR)
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100660 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
Andrew Victor65dbf342006-04-02 19:18:51 +0100661 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100662
Nicolas Ferreed99c542007-07-09 14:58:16 +0200663 /* Enable selected interrupts */
Andrew Victordf05a302006-10-23 14:50:09 +0200664 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
Andrew Victor65dbf342006-04-02 19:18:51 +0100665}
666
667/*
668 * Process the next step in the request
669 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200670static void at91_mci_process_next(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100671{
672 if (!(host->flags & FL_SENT_COMMAND)) {
673 host->flags |= FL_SENT_COMMAND;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200674 at91_mci_send_command(host, host->request->cmd);
Andrew Victor65dbf342006-04-02 19:18:51 +0100675 }
676 else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
677 host->flags |= FL_SENT_STOP;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200678 at91_mci_send_command(host, host->request->stop);
Marc Pignate181dce2008-05-30 14:06:32 +0200679 } else {
680 del_timer(&host->timer);
Marc Pignatc5a89c62008-05-30 14:07:47 +0200681 /* the at91rm9200 mci controller hangs after some transfers,
682 * and the workaround is to reset it after each transfer.
683 */
684 if (cpu_is_at91rm9200())
685 at91_reset_host(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100686 mmc_request_done(host->mmc, host->request);
Marc Pignate181dce2008-05-30 14:06:32 +0200687 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100688}
689
690/*
691 * Handle a command that has been completed
692 */
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200693static void at91_mci_completed_command(struct at91mci_host *host, unsigned int status)
Andrew Victor65dbf342006-04-02 19:18:51 +0100694{
695 struct mmc_command *cmd = host->cmd;
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200696 struct mmc_data *data = cmd->data;
Andrew Victor65dbf342006-04-02 19:18:51 +0100697
Eric Benard7a6588b2008-05-30 14:26:05 +0200698 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Andrew Victor65dbf342006-04-02 19:18:51 +0100699
Andrew Victore0b19b82006-10-25 19:42:38 +0200700 cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
701 cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
702 cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
703 cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
Andrew Victor65dbf342006-04-02 19:18:51 +0100704
705 if (host->buffer) {
David Brownelle385ea62008-09-02 14:35:46 -0700706 dma_unmap_single(NULL,
707 host->physical_address, host->total_length,
708 DMA_TO_DEVICE);
709 kfree(host->buffer);
Andrew Victor65dbf342006-04-02 19:18:51 +0100710 host->buffer = NULL;
711 }
712
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200713 pr_debug("Status = %08X/%08x [%08X %08X %08X %08X]\n",
714 status, at91_mci_read(host, AT91_MCI_SR),
715 cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
Andrew Victor65dbf342006-04-02 19:18:51 +0100716
Andrew Victor9e3866b2007-10-17 11:53:40 +0200717 if (status & AT91_MCI_ERRORS) {
Marc Pignatb6cedb32007-06-06 20:27:59 +0200718 if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
Pierre Ossman17b04292007-07-22 22:18:46 +0200719 cmd->error = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100720 }
721 else {
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200722 if (status & (AT91_MCI_DTOE | AT91_MCI_DCRCE)) {
723 if (data) {
724 if (status & AT91_MCI_DTOE)
725 data->error = -ETIMEDOUT;
726 else if (status & AT91_MCI_DCRCE)
727 data->error = -EILSEQ;
728 }
729 } else {
730 if (status & AT91_MCI_RTOE)
731 cmd->error = -ETIMEDOUT;
732 else if (status & AT91_MCI_RCRCE)
733 cmd->error = -EILSEQ;
734 else
735 cmd->error = -EIO;
736 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100737
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200738 pr_debug("Error detected and set to %d/%d (cmd = %d, retries = %d)\n",
739 cmd->error, data ? data->error : 0,
740 cmd->opcode, cmd->retries);
Andrew Victor65dbf342006-04-02 19:18:51 +0100741 }
742 }
743 else
Pierre Ossman17b04292007-07-22 22:18:46 +0200744 cmd->error = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100745
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200746 at91_mci_process_next(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100747}
748
749/*
750 * Handle an MMC request
751 */
752static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
753{
754 struct at91mci_host *host = mmc_priv(mmc);
755 host->request = mrq;
756 host->flags = 0;
757
Marc Pignate181dce2008-05-30 14:06:32 +0200758 mod_timer(&host->timer, jiffies + HZ);
759
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200760 at91_mci_process_next(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100761}
762
763/*
764 * Set the IOS
765 */
766static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
767{
768 int clkdiv;
769 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor3dd3b032006-10-23 14:46:54 +0200770 unsigned long at91_master_clock = clk_get_rate(host->mci_clk);
Andrew Victor65dbf342006-04-02 19:18:51 +0100771
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100772 host->bus_mode = ios->bus_mode;
Andrew Victor65dbf342006-04-02 19:18:51 +0100773
774 if (ios->clock == 0) {
775 /* Disable the MCI controller */
Andrew Victore0b19b82006-10-25 19:42:38 +0200776 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100777 clkdiv = 0;
778 }
779 else {
780 /* Enable the MCI controller */
Andrew Victore0b19b82006-10-25 19:42:38 +0200781 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
Andrew Victor65dbf342006-04-02 19:18:51 +0100782
783 if ((at91_master_clock % (ios->clock * 2)) == 0)
784 clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
785 else
786 clkdiv = (at91_master_clock / ios->clock) / 2;
787
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100788 pr_debug("clkdiv = %d. mcck = %ld\n", clkdiv,
Andrew Victor65dbf342006-04-02 19:18:51 +0100789 at91_master_clock / (2 * (clkdiv + 1)));
790 }
791 if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100792 pr_debug("MMC: Setting controller bus width to 4\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200793 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100794 }
795 else {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100796 pr_debug("MMC: Setting controller bus width to 1\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200797 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100798 }
799
800 /* Set the clock divider */
Andrew Victore0b19b82006-10-25 19:42:38 +0200801 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 +0100802
803 /* maybe switch power to the card */
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100804 if (host->board->vcc_pin) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100805 switch (ios->power_mode) {
806 case MMC_POWER_OFF:
David Brownell6e996ee2008-02-04 18:12:48 +0100807 gpio_set_value(host->board->vcc_pin, 0);
Andrew Victor65dbf342006-04-02 19:18:51 +0100808 break;
809 case MMC_POWER_UP:
David Brownell6e996ee2008-02-04 18:12:48 +0100810 gpio_set_value(host->board->vcc_pin, 1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100811 break;
Marc Pignate5c0ef92008-05-09 11:07:07 +0200812 case MMC_POWER_ON:
813 break;
814 default:
815 WARN_ON(1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100816 }
817 }
818}
819
820/*
821 * Handle an interrupt
822 */
David Howells7d12e782006-10-05 14:55:46 +0100823static irqreturn_t at91_mci_irq(int irq, void *devid)
Andrew Victor65dbf342006-04-02 19:18:51 +0100824{
825 struct at91mci_host *host = devid;
826 int completed = 0;
Andrew Victordf05a302006-10-23 14:50:09 +0200827 unsigned int int_status, int_mask;
Andrew Victor65dbf342006-04-02 19:18:51 +0100828
Andrew Victore0b19b82006-10-25 19:42:38 +0200829 int_status = at91_mci_read(host, AT91_MCI_SR);
Andrew Victordf05a302006-10-23 14:50:09 +0200830 int_mask = at91_mci_read(host, AT91_MCI_IMR);
Nicolas Ferre37b758e2007-08-08 12:01:44 +0200831
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200832 pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask,
Andrew Victordf05a302006-10-23 14:50:09 +0200833 int_status & int_mask);
Nicolas Ferre37b758e2007-08-08 12:01:44 +0200834
Andrew Victordf05a302006-10-23 14:50:09 +0200835 int_status = int_status & int_mask;
Andrew Victor65dbf342006-04-02 19:18:51 +0100836
Andrew Victordf05a302006-10-23 14:50:09 +0200837 if (int_status & AT91_MCI_ERRORS) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100838 completed = 1;
Nicolas Ferre37b758e2007-08-08 12:01:44 +0200839
Andrew Victordf05a302006-10-23 14:50:09 +0200840 if (int_status & AT91_MCI_UNRE)
841 pr_debug("MMC: Underrun error\n");
842 if (int_status & AT91_MCI_OVRE)
843 pr_debug("MMC: Overrun error\n");
844 if (int_status & AT91_MCI_DTOE)
845 pr_debug("MMC: Data timeout\n");
846 if (int_status & AT91_MCI_DCRCE)
847 pr_debug("MMC: CRC error in data\n");
848 if (int_status & AT91_MCI_RTOE)
849 pr_debug("MMC: Response timeout\n");
850 if (int_status & AT91_MCI_RENDE)
851 pr_debug("MMC: Response end bit error\n");
852 if (int_status & AT91_MCI_RCRCE)
853 pr_debug("MMC: Response CRC error\n");
854 if (int_status & AT91_MCI_RDIRE)
855 pr_debug("MMC: Response direction error\n");
856 if (int_status & AT91_MCI_RINDE)
857 pr_debug("MMC: Response index error\n");
858 } else {
859 /* Only continue processing if no errors */
Andrew Victor65dbf342006-04-02 19:18:51 +0100860
Andrew Victor65dbf342006-04-02 19:18:51 +0100861 if (int_status & AT91_MCI_TXBUFE) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100862 pr_debug("TX buffer empty\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100863 at91_mci_handle_transmitted(host);
864 }
865
Nicolas Ferreed99c542007-07-09 14:58:16 +0200866 if (int_status & AT91_MCI_ENDRX) {
867 pr_debug("ENDRX\n");
868 at91_mci_post_dma_read(host);
869 }
870
Andrew Victor65dbf342006-04-02 19:18:51 +0100871 if (int_status & AT91_MCI_RXBUFF) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100872 pr_debug("RX buffer full\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200873 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
874 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_RXBUFF | AT91_MCI_ENDRX);
875 completed = 1;
Andrew Victor65dbf342006-04-02 19:18:51 +0100876 }
877
Andrew Victordf05a302006-10-23 14:50:09 +0200878 if (int_status & AT91_MCI_ENDTX)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100879 pr_debug("Transmit has ended\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100880
Andrew Victor65dbf342006-04-02 19:18:51 +0100881 if (int_status & AT91_MCI_NOTBUSY) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100882 pr_debug("Card is ready\n");
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200883 at91_mci_update_bytes_xfered(host);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200884 completed = 1;
Andrew Victor65dbf342006-04-02 19:18:51 +0100885 }
886
Andrew Victordf05a302006-10-23 14:50:09 +0200887 if (int_status & AT91_MCI_DTIP)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100888 pr_debug("Data transfer in progress\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100889
Nicolas Ferreed99c542007-07-09 14:58:16 +0200890 if (int_status & AT91_MCI_BLKE) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100891 pr_debug("Block transfer has ended\n");
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200892 if (host->request->data && host->request->data->blocks > 1) {
893 /* multi block write : complete multi write
894 * command and send stop */
895 completed = 1;
896 } else {
897 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
898 }
Nicolas Ferreed99c542007-07-09 14:58:16 +0200899 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100900
Eric Benard7a6588b2008-05-30 14:26:05 +0200901 if (int_status & AT91_MCI_SDIOIRQA)
902 mmc_signal_sdio_irq(host->mmc);
903
904 if (int_status & AT91_MCI_SDIOIRQB)
905 mmc_signal_sdio_irq(host->mmc);
906
Andrew Victordf05a302006-10-23 14:50:09 +0200907 if (int_status & AT91_MCI_TXRDY)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100908 pr_debug("Ready to transmit\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100909
Andrew Victordf05a302006-10-23 14:50:09 +0200910 if (int_status & AT91_MCI_RXRDY)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100911 pr_debug("Ready to receive\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100912
913 if (int_status & AT91_MCI_CMDRDY) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100914 pr_debug("Command ready\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200915 completed = at91_mci_handle_cmdrdy(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100916 }
917 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100918
919 if (completed) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100920 pr_debug("Completed command\n");
Eric Benard7a6588b2008-05-30 14:26:05 +0200921 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200922 at91_mci_completed_command(host, int_status);
Andrew Victordf05a302006-10-23 14:50:09 +0200923 } else
Eric Benard7a6588b2008-05-30 14:26:05 +0200924 at91_mci_write(host, AT91_MCI_IDR, int_status & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Andrew Victor65dbf342006-04-02 19:18:51 +0100925
926 return IRQ_HANDLED;
927}
928
David Howells7d12e782006-10-05 14:55:46 +0100929static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100930{
931 struct at91mci_host *host = _host;
David Brownell6e996ee2008-02-04 18:12:48 +0100932 int present = !gpio_get_value(irq_to_gpio(irq));
Andrew Victor65dbf342006-04-02 19:18:51 +0100933
934 /*
935 * we expect this irq on both insert and remove,
936 * and use a short delay to debounce.
937 */
938 if (present != host->present) {
939 host->present = present;
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100940 pr_debug("%s: card %s\n", mmc_hostname(host->mmc),
Andrew Victor65dbf342006-04-02 19:18:51 +0100941 present ? "insert" : "remove");
942 if (!present) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100943 pr_debug("****** Resetting SD-card bus width ******\n");
Andrew Victor99eeb8df2006-12-11 12:40:23 +0100944 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100945 }
946 mmc_detect_change(host->mmc, msecs_to_jiffies(100));
947 }
948 return IRQ_HANDLED;
949}
950
David Brownella26b4982006-12-26 14:45:26 -0800951static int at91_mci_get_ro(struct mmc_host *mmc)
Andrew Victor65dbf342006-04-02 19:18:51 +0100952{
Andrew Victor65dbf342006-04-02 19:18:51 +0100953 struct at91mci_host *host = mmc_priv(mmc);
954
Anton Vorontsov08f80bb2008-06-17 18:17:39 +0400955 if (host->board->wp_pin)
956 return !!gpio_get_value(host->board->wp_pin);
957 /*
958 * Board doesn't support read only detection; let the mmc core
959 * decide what to do.
960 */
961 return -ENOSYS;
Andrew Victor65dbf342006-04-02 19:18:51 +0100962}
963
Eric Benard7a6588b2008-05-30 14:26:05 +0200964static void at91_mci_enable_sdio_irq(struct mmc_host *mmc, int enable)
965{
966 struct at91mci_host *host = mmc_priv(mmc);
967
968 pr_debug("%s: sdio_irq %c : %s\n", mmc_hostname(host->mmc),
969 host->board->slot_b ? 'B':'A', enable ? "enable" : "disable");
970 at91_mci_write(host, enable ? AT91_MCI_IER : AT91_MCI_IDR,
971 host->board->slot_b ? AT91_MCI_SDIOIRQB : AT91_MCI_SDIOIRQA);
972
973}
974
David Brownellab7aefd2006-11-12 17:55:30 -0800975static const struct mmc_host_ops at91_mci_ops = {
Andrew Victor65dbf342006-04-02 19:18:51 +0100976 .request = at91_mci_request,
977 .set_ios = at91_mci_set_ios,
978 .get_ro = at91_mci_get_ro,
Eric Benard7a6588b2008-05-30 14:26:05 +0200979 .enable_sdio_irq = at91_mci_enable_sdio_irq,
Andrew Victor65dbf342006-04-02 19:18:51 +0100980};
981
982/*
983 * Probe for the device
984 */
David Brownella26b4982006-12-26 14:45:26 -0800985static int __init at91_mci_probe(struct platform_device *pdev)
Andrew Victor65dbf342006-04-02 19:18:51 +0100986{
987 struct mmc_host *mmc;
988 struct at91mci_host *host;
Andrew Victor17ea0592006-10-23 14:44:40 +0200989 struct resource *res;
Andrew Victor65dbf342006-04-02 19:18:51 +0100990 int ret;
991
Andrew Victor17ea0592006-10-23 14:44:40 +0200992 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
993 if (!res)
994 return -ENXIO;
995
996 if (!request_mem_region(res->start, res->end - res->start + 1, DRIVER_NAME))
997 return -EBUSY;
998
Andrew Victor65dbf342006-04-02 19:18:51 +0100999 mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
1000 if (!mmc) {
David Brownell6e996ee2008-02-04 18:12:48 +01001001 ret = -ENOMEM;
1002 dev_dbg(&pdev->dev, "couldn't allocate mmc host\n");
1003 goto fail6;
Andrew Victor65dbf342006-04-02 19:18:51 +01001004 }
1005
1006 mmc->ops = &at91_mci_ops;
1007 mmc->f_min = 375000;
1008 mmc->f_max = 25000000;
1009 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
Pierre Ossman23af6032008-07-06 01:10:27 +02001010 mmc->caps = MMC_CAP_SDIO_IRQ;
Andrew Victor65dbf342006-04-02 19:18:51 +01001011
Pierre Ossmanfe4a3c72006-11-21 17:54:23 +01001012 mmc->max_blk_size = 4095;
Pierre Ossman55db8902006-11-21 17:55:45 +01001013 mmc->max_blk_count = mmc->max_req_size;
Pierre Ossmanfe4a3c72006-11-21 17:54:23 +01001014
Andrew Victor65dbf342006-04-02 19:18:51 +01001015 host = mmc_priv(mmc);
1016 host->mmc = mmc;
1017 host->buffer = NULL;
1018 host->bus_mode = 0;
1019 host->board = pdev->dev.platform_data;
1020 if (host->board->wire4) {
Nicolas Ferreed99c542007-07-09 14:58:16 +02001021 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
1022 mmc->caps |= MMC_CAP_4_BIT_DATA;
1023 else
David Brownell6e996ee2008-02-04 18:12:48 +01001024 dev_warn(&pdev->dev, "4 wire bus mode not supported"
Nicolas Ferreed99c542007-07-09 14:58:16 +02001025 " - using 1 wire\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001026 }
1027
1028 /*
David Brownell6e996ee2008-02-04 18:12:48 +01001029 * Reserve GPIOs ... board init code makes sure these pins are set
1030 * up as GPIOs with the right direction (input, except for vcc)
1031 */
1032 if (host->board->det_pin) {
1033 ret = gpio_request(host->board->det_pin, "mmc_detect");
1034 if (ret < 0) {
1035 dev_dbg(&pdev->dev, "couldn't claim card detect pin\n");
1036 goto fail5;
1037 }
1038 }
1039 if (host->board->wp_pin) {
1040 ret = gpio_request(host->board->wp_pin, "mmc_wp");
1041 if (ret < 0) {
1042 dev_dbg(&pdev->dev, "couldn't claim wp sense pin\n");
1043 goto fail4;
1044 }
1045 }
1046 if (host->board->vcc_pin) {
1047 ret = gpio_request(host->board->vcc_pin, "mmc_vcc");
1048 if (ret < 0) {
1049 dev_dbg(&pdev->dev, "couldn't claim vcc switch pin\n");
1050 goto fail3;
1051 }
1052 }
1053
1054 /*
Andrew Victor65dbf342006-04-02 19:18:51 +01001055 * Get Clock
1056 */
Andrew Victor3dd3b032006-10-23 14:46:54 +02001057 host->mci_clk = clk_get(&pdev->dev, "mci_clk");
1058 if (IS_ERR(host->mci_clk)) {
David Brownell6e996ee2008-02-04 18:12:48 +01001059 ret = -ENODEV;
1060 dev_dbg(&pdev->dev, "no mci_clk?\n");
1061 goto fail2;
Andrew Victor65dbf342006-04-02 19:18:51 +01001062 }
Andrew Victor65dbf342006-04-02 19:18:51 +01001063
Andrew Victor17ea0592006-10-23 14:44:40 +02001064 /*
1065 * Map I/O region
1066 */
1067 host->baseaddr = ioremap(res->start, res->end - res->start + 1);
1068 if (!host->baseaddr) {
David Brownell6e996ee2008-02-04 18:12:48 +01001069 ret = -ENOMEM;
1070 goto fail1;
Andrew Victor17ea0592006-10-23 14:44:40 +02001071 }
Andrew Victore0b19b82006-10-25 19:42:38 +02001072
1073 /*
1074 * Reset hardware
1075 */
Andrew Victor3dd3b032006-10-23 14:46:54 +02001076 clk_enable(host->mci_clk); /* Enable the peripheral clock */
Andrew Victore0b19b82006-10-25 19:42:38 +02001077 at91_mci_disable(host);
1078 at91_mci_enable(host);
1079
Andrew Victor65dbf342006-04-02 19:18:51 +01001080 /*
1081 * Allocate the MCI interrupt
1082 */
Andrew Victor17ea0592006-10-23 14:44:40 +02001083 host->irq = platform_get_irq(pdev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +01001084 ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED,
1085 mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001086 if (ret) {
David Brownell6e996ee2008-02-04 18:12:48 +01001087 dev_dbg(&pdev->dev, "request MCI interrupt failed\n");
1088 goto fail0;
Andrew Victor65dbf342006-04-02 19:18:51 +01001089 }
1090
Nicolas Ferre99ba0402008-11-27 17:23:49 +01001091 setup_timer(&host->timer, at91_timeout_timer, (unsigned long)host);
1092
Andrew Victor65dbf342006-04-02 19:18:51 +01001093 platform_set_drvdata(pdev, mmc);
1094
1095 /*
1096 * Add host to MMC layer
1097 */
Marc Pignat63b66432007-07-16 11:07:02 +02001098 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001099 host->present = !gpio_get_value(host->board->det_pin);
Marc Pignat63b66432007-07-16 11:07:02 +02001100 }
Andrew Victor65dbf342006-04-02 19:18:51 +01001101 else
1102 host->present = -1;
1103
1104 mmc_add_host(mmc);
1105
1106 /*
1107 * monitor card insertion/removal if we can
1108 */
1109 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001110 ret = request_irq(gpio_to_irq(host->board->det_pin),
1111 at91_mmc_det_irq, 0, mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001112 if (ret)
David Brownell6e996ee2008-02-04 18:12:48 +01001113 dev_warn(&pdev->dev, "request MMC detect irq failed\n");
1114 else
1115 device_init_wakeup(&pdev->dev, 1);
Andrew Victor65dbf342006-04-02 19:18:51 +01001116 }
1117
Andrew Victorf3a8efa2006-10-23 14:53:20 +02001118 pr_debug("Added MCI driver\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001119
1120 return 0;
David Brownell6e996ee2008-02-04 18:12:48 +01001121
1122fail0:
1123 clk_disable(host->mci_clk);
1124 iounmap(host->baseaddr);
1125fail1:
1126 clk_put(host->mci_clk);
1127fail2:
1128 if (host->board->vcc_pin)
1129 gpio_free(host->board->vcc_pin);
1130fail3:
1131 if (host->board->wp_pin)
1132 gpio_free(host->board->wp_pin);
1133fail4:
1134 if (host->board->det_pin)
1135 gpio_free(host->board->det_pin);
1136fail5:
1137 mmc_free_host(mmc);
1138fail6:
1139 release_mem_region(res->start, res->end - res->start + 1);
1140 dev_err(&pdev->dev, "probe failed, err %d\n", ret);
1141 return ret;
Andrew Victor65dbf342006-04-02 19:18:51 +01001142}
1143
1144/*
1145 * Remove a device
1146 */
David Brownella26b4982006-12-26 14:45:26 -08001147static int __exit at91_mci_remove(struct platform_device *pdev)
Andrew Victor65dbf342006-04-02 19:18:51 +01001148{
1149 struct mmc_host *mmc = platform_get_drvdata(pdev);
1150 struct at91mci_host *host;
Andrew Victor17ea0592006-10-23 14:44:40 +02001151 struct resource *res;
Andrew Victor65dbf342006-04-02 19:18:51 +01001152
1153 if (!mmc)
1154 return -1;
1155
1156 host = mmc_priv(mmc);
1157
Anti Sulline0cda542007-08-30 16:15:16 +02001158 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001159 if (device_can_wakeup(&pdev->dev))
1160 free_irq(gpio_to_irq(host->board->det_pin), host);
Marc Pignat63b66432007-07-16 11:07:02 +02001161 device_init_wakeup(&pdev->dev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +01001162 gpio_free(host->board->det_pin);
Andrew Victor65dbf342006-04-02 19:18:51 +01001163 }
1164
Andrew Victore0b19b82006-10-25 19:42:38 +02001165 at91_mci_disable(host);
Marc Pignate181dce2008-05-30 14:06:32 +02001166 del_timer_sync(&host->timer);
Andrew Victor17ea0592006-10-23 14:44:40 +02001167 mmc_remove_host(mmc);
1168 free_irq(host->irq, host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001169
Andrew Victor3dd3b032006-10-23 14:46:54 +02001170 clk_disable(host->mci_clk); /* Disable the peripheral clock */
1171 clk_put(host->mci_clk);
Andrew Victor65dbf342006-04-02 19:18:51 +01001172
David Brownell6e996ee2008-02-04 18:12:48 +01001173 if (host->board->vcc_pin)
1174 gpio_free(host->board->vcc_pin);
1175 if (host->board->wp_pin)
1176 gpio_free(host->board->wp_pin);
1177
Andrew Victor17ea0592006-10-23 14:44:40 +02001178 iounmap(host->baseaddr);
1179 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1180 release_mem_region(res->start, res->end - res->start + 1);
Andrew Victor65dbf342006-04-02 19:18:51 +01001181
Andrew Victor17ea0592006-10-23 14:44:40 +02001182 mmc_free_host(mmc);
1183 platform_set_drvdata(pdev, NULL);
Andrew Victorb44fb7a2006-06-19 13:06:05 +01001184 pr_debug("MCI Removed\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001185
1186 return 0;
1187}
1188
1189#ifdef CONFIG_PM
1190static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
1191{
1192 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001193 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001194 int ret = 0;
1195
Anti Sulline0cda542007-08-30 16:15:16 +02001196 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001197 enable_irq_wake(host->board->det_pin);
1198
Andrew Victor65dbf342006-04-02 19:18:51 +01001199 if (mmc)
1200 ret = mmc_suspend_host(mmc, state);
1201
1202 return ret;
1203}
1204
1205static int at91_mci_resume(struct platform_device *pdev)
1206{
1207 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001208 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001209 int ret = 0;
1210
Anti Sulline0cda542007-08-30 16:15:16 +02001211 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001212 disable_irq_wake(host->board->det_pin);
1213
Andrew Victor65dbf342006-04-02 19:18:51 +01001214 if (mmc)
1215 ret = mmc_resume_host(mmc);
1216
1217 return ret;
1218}
1219#else
1220#define at91_mci_suspend NULL
1221#define at91_mci_resume NULL
1222#endif
1223
1224static struct platform_driver at91_mci_driver = {
David Brownella26b4982006-12-26 14:45:26 -08001225 .remove = __exit_p(at91_mci_remove),
Andrew Victor65dbf342006-04-02 19:18:51 +01001226 .suspend = at91_mci_suspend,
1227 .resume = at91_mci_resume,
1228 .driver = {
1229 .name = DRIVER_NAME,
1230 .owner = THIS_MODULE,
1231 },
1232};
1233
1234static int __init at91_mci_init(void)
1235{
David Brownella26b4982006-12-26 14:45:26 -08001236 return platform_driver_probe(&at91_mci_driver, at91_mci_probe);
Andrew Victor65dbf342006-04-02 19:18:51 +01001237}
1238
1239static void __exit at91_mci_exit(void)
1240{
1241 platform_driver_unregister(&at91_mci_driver);
1242}
1243
1244module_init(at91_mci_init);
1245module_exit(at91_mci_exit);
1246
1247MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
1248MODULE_AUTHOR("Nick Randell");
1249MODULE_LICENSE("GPL");
Kay Sieversbc65c722008-04-15 14:34:28 -07001250MODULE_ALIAS("platform:at91_mci");