blob: 63924e0c7ea9a6c3fab8c2b38857be8832149612 [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
Andrew Victor65dbf342006-04-02 19:18:51 +010091
92/*
93 * Low level type for this driver
94 */
95struct at91mci_host
96{
97 struct mmc_host *mmc;
98 struct mmc_command *cmd;
99 struct mmc_request *request;
100
Andrew Victore0b19b82006-10-25 19:42:38 +0200101 void __iomem *baseaddr;
Andrew Victor17ea0592006-10-23 14:44:40 +0200102 int irq;
Andrew Victore0b19b82006-10-25 19:42:38 +0200103
Andrew Victor65dbf342006-04-02 19:18:51 +0100104 struct at91_mmc_data *board;
105 int present;
106
Andrew Victor3dd3b032006-10-23 14:46:54 +0200107 struct clk *mci_clk;
108
Andrew Victor65dbf342006-04-02 19:18:51 +0100109 /*
110 * Flag indicating when the command has been sent. This is used to
111 * work out whether or not to send the stop
112 */
113 unsigned int flags;
114 /* flag for current bus settings */
115 u32 bus_mode;
116
117 /* DMA buffer used for transmitting */
118 unsigned int* buffer;
119 dma_addr_t physical_address;
120 unsigned int total_length;
121
122 /* Latest in the scatterlist that has been enabled for transfer, but not freed */
123 int in_use_index;
124
125 /* Latest in the scatterlist that has been enabled for transfer */
126 int transfer_index;
Marc Pignate181dce2008-05-30 14:06:32 +0200127
128 /* Timer for timeouts */
129 struct timer_list timer;
Andrew Victor65dbf342006-04-02 19:18:51 +0100130};
131
Marc Pignatc5a89c62008-05-30 14:07:47 +0200132/*
133 * Reset the controller and restore most of the state
134 */
135static void at91_reset_host(struct at91mci_host *host)
136{
137 unsigned long flags;
138 u32 mr;
139 u32 sdcr;
140 u32 dtor;
141 u32 imr;
142
143 local_irq_save(flags);
144 imr = at91_mci_read(host, AT91_MCI_IMR);
145
146 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
147
148 /* save current state */
149 mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
150 sdcr = at91_mci_read(host, AT91_MCI_SDCR);
151 dtor = at91_mci_read(host, AT91_MCI_DTOR);
152
153 /* reset the controller */
154 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
155
156 /* restore state */
157 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
158 at91_mci_write(host, AT91_MCI_MR, mr);
159 at91_mci_write(host, AT91_MCI_SDCR, sdcr);
160 at91_mci_write(host, AT91_MCI_DTOR, dtor);
161 at91_mci_write(host, AT91_MCI_IER, imr);
162
163 /* make sure sdio interrupts will fire */
164 at91_mci_read(host, AT91_MCI_SR);
165
166 local_irq_restore(flags);
167}
168
Marc Pignate181dce2008-05-30 14:06:32 +0200169static void at91_timeout_timer(unsigned long data)
170{
171 struct at91mci_host *host;
172
173 host = (struct at91mci_host *)data;
174
175 if (host->request) {
176 dev_err(host->mmc->parent, "Timeout waiting end of packet\n");
177
178 if (host->cmd && host->cmd->data) {
179 host->cmd->data->error = -ETIMEDOUT;
180 } else {
181 if (host->cmd)
182 host->cmd->error = -ETIMEDOUT;
183 else
184 host->request->cmd->error = -ETIMEDOUT;
185 }
186
Marc Pignatc5a89c62008-05-30 14:07:47 +0200187 at91_reset_host(host);
Marc Pignate181dce2008-05-30 14:06:32 +0200188 mmc_request_done(host->mmc, host->request);
189 }
190}
191
Andrew Victor65dbf342006-04-02 19:18:51 +0100192/*
193 * Copy from sg to a dma block - used for transfers
194 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200195static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
Andrew Victor65dbf342006-04-02 19:18:51 +0100196{
197 unsigned int len, i, size;
198 unsigned *dmabuf = host->buffer;
199
Ville Syrjala5385edc2008-06-14 20:27:20 +0300200 size = data->blksz * data->blocks;
Andrew Victor65dbf342006-04-02 19:18:51 +0100201 len = data->sg_len;
202
Ville Syrjala5385edc2008-06-14 20:27:20 +0300203 /* AT91SAM926[0/3] Data Write Operation and number of bytes erratum */
204 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
205 if (host->total_length == 12)
206 memset(dmabuf, 0, 12);
207
Andrew Victor65dbf342006-04-02 19:18:51 +0100208 /*
209 * Just loop through all entries. Size might not
210 * be the entire list though so make sure that
211 * we do not transfer too much.
212 */
213 for (i = 0; i < len; i++) {
214 struct scatterlist *sg;
215 int amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100216 unsigned int *sgbuffer;
217
218 sg = &data->sg[i];
219
Jens Axboe45711f12007-10-22 21:19:53 +0200220 sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
Andrew Victor65dbf342006-04-02 19:18:51 +0100221 amount = min(size, sg->length);
222 size -= amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100223
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100224 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
225 int index;
226
227 for (index = 0; index < (amount / 4); index++)
228 *dmabuf++ = swab32(sgbuffer[index]);
Ville Syrjala5385edc2008-06-14 20:27:20 +0300229 } else {
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100230 memcpy(dmabuf, sgbuffer, amount);
Ville Syrjala5385edc2008-06-14 20:27:20 +0300231 dmabuf += amount;
232 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100233
234 kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
235
236 if (size == 0)
237 break;
238 }
239
240 /*
241 * Check that we didn't get a request to transfer
242 * more data than can fit into the SG list.
243 */
244 BUG_ON(size != 0);
245}
246
247/*
248 * Prepare a dma read
249 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200250static void at91_mci_pre_dma_read(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100251{
252 int i;
253 struct scatterlist *sg;
254 struct mmc_command *cmd;
255 struct mmc_data *data;
256
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100257 pr_debug("pre dma read\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100258
259 cmd = host->cmd;
260 if (!cmd) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100261 pr_debug("no command\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100262 return;
263 }
264
265 data = cmd->data;
266 if (!data) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100267 pr_debug("no data\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100268 return;
269 }
270
271 for (i = 0; i < 2; i++) {
272 /* nothing left to transfer */
273 if (host->transfer_index >= data->sg_len) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100274 pr_debug("Nothing left to transfer (index = %d)\n", host->transfer_index);
Andrew Victor65dbf342006-04-02 19:18:51 +0100275 break;
276 }
277
278 /* Check to see if this needs filling */
279 if (i == 0) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100280 if (at91_mci_read(host, ATMEL_PDC_RCR) != 0) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100281 pr_debug("Transfer active in current\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100282 continue;
283 }
284 }
285 else {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100286 if (at91_mci_read(host, ATMEL_PDC_RNCR) != 0) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100287 pr_debug("Transfer active in next\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100288 continue;
289 }
290 }
291
292 /* Setup the next transfer */
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100293 pr_debug("Using transfer index %d\n", host->transfer_index);
Andrew Victor65dbf342006-04-02 19:18:51 +0100294
295 sg = &data->sg[host->transfer_index++];
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100296 pr_debug("sg = %p\n", sg);
Andrew Victor65dbf342006-04-02 19:18:51 +0100297
Jens Axboe45711f12007-10-22 21:19:53 +0200298 sg->dma_address = dma_map_page(NULL, sg_page(sg), sg->offset, sg->length, DMA_FROM_DEVICE);
Andrew Victor65dbf342006-04-02 19:18:51 +0100299
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100300 pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
Andrew Victor65dbf342006-04-02 19:18:51 +0100301
302 if (i == 0) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100303 at91_mci_write(host, ATMEL_PDC_RPR, sg->dma_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200304 at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ? sg->length : sg->length / 4);
Andrew Victor65dbf342006-04-02 19:18:51 +0100305 }
306 else {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100307 at91_mci_write(host, ATMEL_PDC_RNPR, sg->dma_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200308 at91_mci_write(host, ATMEL_PDC_RNCR, (data->blksz & 0x3) ? sg->length : sg->length / 4);
Andrew Victor65dbf342006-04-02 19:18:51 +0100309 }
310 }
311
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100312 pr_debug("pre dma read done\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100313}
314
315/*
316 * Handle after a dma read
317 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200318static void at91_mci_post_dma_read(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100319{
320 struct mmc_command *cmd;
321 struct mmc_data *data;
322
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100323 pr_debug("post dma read\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100324
325 cmd = host->cmd;
326 if (!cmd) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100327 pr_debug("no command\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100328 return;
329 }
330
331 data = cmd->data;
332 if (!data) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100333 pr_debug("no data\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100334 return;
335 }
336
337 while (host->in_use_index < host->transfer_index) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100338 struct scatterlist *sg;
339
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100340 pr_debug("finishing index %d\n", host->in_use_index);
Andrew Victor65dbf342006-04-02 19:18:51 +0100341
342 sg = &data->sg[host->in_use_index++];
343
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100344 pr_debug("Unmapping page %08X\n", sg->dma_address);
Andrew Victor65dbf342006-04-02 19:18:51 +0100345
346 dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
347
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100348 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
Nicolas Ferreed99c542007-07-09 14:58:16 +0200349 unsigned int *buffer;
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100350 int index;
Andrew Victor65dbf342006-04-02 19:18:51 +0100351
Nicolas Ferreed99c542007-07-09 14:58:16 +0200352 /* Swap the contents of the buffer */
Jens Axboe45711f12007-10-22 21:19:53 +0200353 buffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200354 pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
355
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100356 for (index = 0; index < (sg->length / 4); index++)
357 buffer[index] = swab32(buffer[index]);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200358
359 kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
Andrew Victor65dbf342006-04-02 19:18:51 +0100360 }
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100361
Jens Axboe45711f12007-10-22 21:19:53 +0200362 flush_dcache_page(sg_page(sg));
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200363
364 data->bytes_xfered += sg->length;
Andrew Victor65dbf342006-04-02 19:18:51 +0100365 }
366
367 /* Is there another transfer to trigger? */
368 if (host->transfer_index < data->sg_len)
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200369 at91_mci_pre_dma_read(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100370 else {
Nicolas Ferreed99c542007-07-09 14:58:16 +0200371 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
Andrew Victore0b19b82006-10-25 19:42:38 +0200372 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
Andrew Victor65dbf342006-04-02 19:18:51 +0100373 }
374
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100375 pr_debug("post dma read done\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100376}
377
378/*
379 * Handle transmitted data
380 */
381static void at91_mci_handle_transmitted(struct at91mci_host *host)
382{
383 struct mmc_command *cmd;
384 struct mmc_data *data;
385
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100386 pr_debug("Handling the transmit\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100387
388 /* Disable the transfer */
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100389 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100390
391 /* Now wait for cmd ready */
Andrew Victore0b19b82006-10-25 19:42:38 +0200392 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
Andrew Victor65dbf342006-04-02 19:18:51 +0100393
394 cmd = host->cmd;
395 if (!cmd) return;
396
397 data = cmd->data;
398 if (!data) return;
399
Pierre Ossmanbe0192a2007-07-24 21:11:47 +0200400 if (cmd->data->blocks > 1) {
Nicolas Ferreed99c542007-07-09 14:58:16 +0200401 pr_debug("multiple write : wait for BLKE...\n");
402 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
403 } else
404 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
Andrew Victor65dbf342006-04-02 19:18:51 +0100405}
406
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200407/*
408 * Update bytes tranfered count during a write operation
409 */
410static void at91_mci_update_bytes_xfered(struct at91mci_host *host)
411{
412 struct mmc_data *data;
413
414 /* always deal with the effective request (and not the current cmd) */
415
416 if (host->request->cmd && host->request->cmd->error != 0)
417 return;
418
419 if (host->request->data) {
420 data = host->request->data;
421 if (data->flags & MMC_DATA_WRITE) {
422 /* card is in IDLE mode now */
423 pr_debug("-> bytes_xfered %d, total_length = %d\n",
424 data->bytes_xfered, host->total_length);
Ville Syrjala5385edc2008-06-14 20:27:20 +0300425 data->bytes_xfered = data->blksz * data->blocks;
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200426 }
427 }
428}
429
430
Nicolas Ferreed99c542007-07-09 14:58:16 +0200431/*Handle after command sent ready*/
432static int at91_mci_handle_cmdrdy(struct at91mci_host *host)
433{
434 if (!host->cmd)
435 return 1;
436 else if (!host->cmd->data) {
437 if (host->flags & FL_SENT_STOP) {
438 /*After multi block write, we must wait for NOTBUSY*/
439 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
440 } else return 1;
441 } else if (host->cmd->data->flags & MMC_DATA_WRITE) {
442 /*After sendding multi-block-write command, start DMA transfer*/
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200443 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE | AT91_MCI_BLKE);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200444 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
445 }
446
447 /* command not completed, have to wait */
448 return 0;
449}
450
451
Andrew Victor65dbf342006-04-02 19:18:51 +0100452/*
453 * Enable the controller
454 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200455static void at91_mci_enable(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100456{
Nicolas Ferreed99c542007-07-09 14:58:16 +0200457 unsigned int mr;
458
Andrew Victore0b19b82006-10-25 19:42:38 +0200459 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200460 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
Andrew Victore0b19b82006-10-25 19:42:38 +0200461 at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200462 mr = AT91_MCI_PDCMODE | 0x34a;
463
464 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
465 mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
466
467 at91_mci_write(host, AT91_MCI_MR, mr);
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100468
469 /* use Slot A or B (only one at same time) */
470 at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
Andrew Victor65dbf342006-04-02 19:18:51 +0100471}
472
473/*
474 * Disable the controller
475 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200476static void at91_mci_disable(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100477{
Andrew Victore0b19b82006-10-25 19:42:38 +0200478 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
Andrew Victor65dbf342006-04-02 19:18:51 +0100479}
480
481/*
482 * Send a command
Andrew Victor65dbf342006-04-02 19:18:51 +0100483 */
Nicolas Ferreed99c542007-07-09 14:58:16 +0200484static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
Andrew Victor65dbf342006-04-02 19:18:51 +0100485{
486 unsigned int cmdr, mr;
487 unsigned int block_length;
488 struct mmc_data *data = cmd->data;
489
490 unsigned int blocks;
491 unsigned int ier = 0;
492
493 host->cmd = cmd;
494
Nicolas Ferreed99c542007-07-09 14:58:16 +0200495 /* Needed for leaving busy state before CMD1 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200496 if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100497 pr_debug("Clearing timeout\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200498 at91_mci_write(host, AT91_MCI_ARGR, 0);
499 at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
500 while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100501 /* spin */
Andrew Victore0b19b82006-10-25 19:42:38 +0200502 pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
Andrew Victor65dbf342006-04-02 19:18:51 +0100503 }
504 }
Nicolas Ferreed99c542007-07-09 14:58:16 +0200505
Andrew Victor65dbf342006-04-02 19:18:51 +0100506 cmdr = cmd->opcode;
507
508 if (mmc_resp_type(cmd) == MMC_RSP_NONE)
509 cmdr |= AT91_MCI_RSPTYP_NONE;
510 else {
511 /* if a response is expected then allow maximum response latancy */
512 cmdr |= AT91_MCI_MAXLAT;
513 /* set 136 bit response for R2, 48 bit response otherwise */
514 if (mmc_resp_type(cmd) == MMC_RSP_R2)
515 cmdr |= AT91_MCI_RSPTYP_136;
516 else
517 cmdr |= AT91_MCI_RSPTYP_48;
518 }
519
520 if (data) {
Marc Pignat1d4de9e2007-08-09 13:56:29 +0200521
Ville Syrjala9da3cba2008-06-09 22:06:44 +0300522 if (cpu_is_at91rm9200() || cpu_is_at91sam9261()) {
523 if (data->blksz & 0x3) {
524 pr_debug("Unsupported block size\n");
525 cmd->error = -EINVAL;
526 mmc_request_done(host->mmc, host->request);
527 return;
528 }
529 if (data->flags & MMC_DATA_STREAM) {
530 pr_debug("Stream commands not supported\n");
531 cmd->error = -EINVAL;
532 mmc_request_done(host->mmc, host->request);
533 return;
534 }
Marc Pignat1d4de9e2007-08-09 13:56:29 +0200535 }
536
Russell Kinga3fd4a12006-06-04 17:51:15 +0100537 block_length = data->blksz;
Andrew Victor65dbf342006-04-02 19:18:51 +0100538 blocks = data->blocks;
539
540 /* always set data start - also set direction flag for read */
541 if (data->flags & MMC_DATA_READ)
542 cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
543 else if (data->flags & MMC_DATA_WRITE)
544 cmdr |= AT91_MCI_TRCMD_START;
545
546 if (data->flags & MMC_DATA_STREAM)
547 cmdr |= AT91_MCI_TRTYP_STREAM;
Pierre Ossmanbe0192a2007-07-24 21:11:47 +0200548 if (data->blocks > 1)
Andrew Victor65dbf342006-04-02 19:18:51 +0100549 cmdr |= AT91_MCI_TRTYP_MULTIPLE;
550 }
551 else {
552 block_length = 0;
553 blocks = 0;
554 }
555
Marc Pignatb6cedb32007-06-06 20:27:59 +0200556 if (host->flags & FL_SENT_STOP)
Andrew Victor65dbf342006-04-02 19:18:51 +0100557 cmdr |= AT91_MCI_TRCMD_STOP;
558
559 if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
560 cmdr |= AT91_MCI_OPDCMD;
561
562 /*
563 * Set the arguments and send the command
564 */
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200565 pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
Andrew Victore0b19b82006-10-25 19:42:38 +0200566 cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
Andrew Victor65dbf342006-04-02 19:18:51 +0100567
568 if (!data) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100569 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
570 at91_mci_write(host, ATMEL_PDC_RPR, 0);
571 at91_mci_write(host, ATMEL_PDC_RCR, 0);
572 at91_mci_write(host, ATMEL_PDC_RNPR, 0);
573 at91_mci_write(host, ATMEL_PDC_RNCR, 0);
574 at91_mci_write(host, ATMEL_PDC_TPR, 0);
575 at91_mci_write(host, ATMEL_PDC_TCR, 0);
576 at91_mci_write(host, ATMEL_PDC_TNPR, 0);
577 at91_mci_write(host, ATMEL_PDC_TNCR, 0);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200578 ier = AT91_MCI_CMDRDY;
579 } else {
580 /* zero block length and PDC mode */
Ville Syrjala12bd2572008-06-09 22:06:45 +0300581 mr = at91_mci_read(host, AT91_MCI_MR) & 0x5fff;
Marc Pignat80f92542008-05-30 14:05:24 +0200582 mr |= (data->blksz & 0x3) ? AT91_MCI_PDCFBYTE : 0;
583 mr |= (block_length << 16);
584 mr |= AT91_MCI_PDCMODE;
585 at91_mci_write(host, AT91_MCI_MR, mr);
Andrew Victor65dbf342006-04-02 19:18:51 +0100586
Ville Syrjala9da3cba2008-06-09 22:06:44 +0300587 if (!(cpu_is_at91rm9200() || cpu_is_at91sam9261()))
Marc Pignatc5a89c62008-05-30 14:07:47 +0200588 at91_mci_write(host, AT91_MCI_BLKR,
589 AT91_MCI_BLKR_BCNT(blocks) |
590 AT91_MCI_BLKR_BLKLEN(block_length));
591
Nicolas Ferreed99c542007-07-09 14:58:16 +0200592 /*
593 * Disable the PDC controller
594 */
595 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100596
Nicolas Ferreed99c542007-07-09 14:58:16 +0200597 if (cmdr & AT91_MCI_TRCMD_START) {
598 data->bytes_xfered = 0;
599 host->transfer_index = 0;
600 host->in_use_index = 0;
601 if (cmdr & AT91_MCI_TRDIR) {
602 /*
603 * Handle a read
604 */
605 host->buffer = NULL;
606 host->total_length = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100607
Nicolas Ferreed99c542007-07-09 14:58:16 +0200608 at91_mci_pre_dma_read(host);
609 ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
610 }
611 else {
612 /*
613 * Handle a write
614 */
615 host->total_length = block_length * blocks;
Ville Syrjala5385edc2008-06-14 20:27:20 +0300616 /*
617 * AT91SAM926[0/3] Data Write Operation and
618 * number of bytes erratum
619 */
620 if (cpu_is_at91sam9260 () || cpu_is_at91sam9263())
621 if (host->total_length < 12)
622 host->total_length = 12;
David Brownelle385ea62008-09-02 14:35:46 -0700623
624 host->buffer = kmalloc(host->total_length, GFP_KERNEL);
625 if (!host->buffer) {
626 pr_debug("Can't alloc tx buffer\n");
627 cmd->error = -ENOMEM;
628 mmc_request_done(host->mmc, host->request);
629 return;
630 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100631
Nicolas Ferreed99c542007-07-09 14:58:16 +0200632 at91_mci_sg_to_dma(host, data);
Andrew Victor65dbf342006-04-02 19:18:51 +0100633
David Brownelle385ea62008-09-02 14:35:46 -0700634 host->physical_address = dma_map_single(NULL,
635 host->buffer, host->total_length,
636 DMA_TO_DEVICE);
637
Nicolas Ferreed99c542007-07-09 14:58:16 +0200638 pr_debug("Transmitting %d bytes\n", host->total_length);
Andrew Victor65dbf342006-04-02 19:18:51 +0100639
Nicolas Ferreed99c542007-07-09 14:58:16 +0200640 at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200641 at91_mci_write(host, ATMEL_PDC_TCR, (data->blksz & 0x3) ?
642 host->total_length : host->total_length / 4);
643
Nicolas Ferreed99c542007-07-09 14:58:16 +0200644 ier = AT91_MCI_CMDRDY;
645 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100646 }
647 }
648
649 /*
650 * Send the command and then enable the PDC - not the other way round as
651 * the data sheet says
652 */
653
Andrew Victore0b19b82006-10-25 19:42:38 +0200654 at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
655 at91_mci_write(host, AT91_MCI_CMDR, cmdr);
Andrew Victor65dbf342006-04-02 19:18:51 +0100656
657 if (cmdr & AT91_MCI_TRCMD_START) {
658 if (cmdr & AT91_MCI_TRDIR)
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100659 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
Andrew Victor65dbf342006-04-02 19:18:51 +0100660 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100661
Nicolas Ferreed99c542007-07-09 14:58:16 +0200662 /* Enable selected interrupts */
Andrew Victordf05a302006-10-23 14:50:09 +0200663 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
Andrew Victor65dbf342006-04-02 19:18:51 +0100664}
665
666/*
667 * Process the next step in the request
668 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200669static void at91_mci_process_next(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100670{
671 if (!(host->flags & FL_SENT_COMMAND)) {
672 host->flags |= FL_SENT_COMMAND;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200673 at91_mci_send_command(host, host->request->cmd);
Andrew Victor65dbf342006-04-02 19:18:51 +0100674 }
675 else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
676 host->flags |= FL_SENT_STOP;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200677 at91_mci_send_command(host, host->request->stop);
Marc Pignate181dce2008-05-30 14:06:32 +0200678 } else {
679 del_timer(&host->timer);
Marc Pignatc5a89c62008-05-30 14:07:47 +0200680 /* the at91rm9200 mci controller hangs after some transfers,
681 * and the workaround is to reset it after each transfer.
682 */
683 if (cpu_is_at91rm9200())
684 at91_reset_host(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100685 mmc_request_done(host->mmc, host->request);
Marc Pignate181dce2008-05-30 14:06:32 +0200686 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100687}
688
689/*
690 * Handle a command that has been completed
691 */
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200692static void at91_mci_completed_command(struct at91mci_host *host, unsigned int status)
Andrew Victor65dbf342006-04-02 19:18:51 +0100693{
694 struct mmc_command *cmd = host->cmd;
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200695 struct mmc_data *data = cmd->data;
Andrew Victor65dbf342006-04-02 19:18:51 +0100696
Eric Benard7a6588b2008-05-30 14:26:05 +0200697 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Andrew Victor65dbf342006-04-02 19:18:51 +0100698
Andrew Victore0b19b82006-10-25 19:42:38 +0200699 cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
700 cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
701 cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
702 cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
Andrew Victor65dbf342006-04-02 19:18:51 +0100703
704 if (host->buffer) {
David Brownelle385ea62008-09-02 14:35:46 -0700705 dma_unmap_single(NULL,
706 host->physical_address, host->total_length,
707 DMA_TO_DEVICE);
708 kfree(host->buffer);
Andrew Victor65dbf342006-04-02 19:18:51 +0100709 host->buffer = NULL;
710 }
711
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200712 pr_debug("Status = %08X/%08x [%08X %08X %08X %08X]\n",
713 status, at91_mci_read(host, AT91_MCI_SR),
714 cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
Andrew Victor65dbf342006-04-02 19:18:51 +0100715
Andrew Victor9e3866b2007-10-17 11:53:40 +0200716 if (status & AT91_MCI_ERRORS) {
Marc Pignatb6cedb32007-06-06 20:27:59 +0200717 if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
Pierre Ossman17b04292007-07-22 22:18:46 +0200718 cmd->error = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100719 }
720 else {
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200721 if (status & (AT91_MCI_DTOE | AT91_MCI_DCRCE)) {
722 if (data) {
723 if (status & AT91_MCI_DTOE)
724 data->error = -ETIMEDOUT;
725 else if (status & AT91_MCI_DCRCE)
726 data->error = -EILSEQ;
727 }
728 } else {
729 if (status & AT91_MCI_RTOE)
730 cmd->error = -ETIMEDOUT;
731 else if (status & AT91_MCI_RCRCE)
732 cmd->error = -EILSEQ;
733 else
734 cmd->error = -EIO;
735 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100736
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200737 pr_debug("Error detected and set to %d/%d (cmd = %d, retries = %d)\n",
738 cmd->error, data ? data->error : 0,
739 cmd->opcode, cmd->retries);
Andrew Victor65dbf342006-04-02 19:18:51 +0100740 }
741 }
742 else
Pierre Ossman17b04292007-07-22 22:18:46 +0200743 cmd->error = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100744
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200745 at91_mci_process_next(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100746}
747
748/*
749 * Handle an MMC request
750 */
751static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
752{
753 struct at91mci_host *host = mmc_priv(mmc);
754 host->request = mrq;
755 host->flags = 0;
756
Marc Pignate181dce2008-05-30 14:06:32 +0200757 mod_timer(&host->timer, jiffies + HZ);
758
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200759 at91_mci_process_next(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100760}
761
762/*
763 * Set the IOS
764 */
765static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
766{
767 int clkdiv;
768 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor3dd3b032006-10-23 14:46:54 +0200769 unsigned long at91_master_clock = clk_get_rate(host->mci_clk);
Andrew Victor65dbf342006-04-02 19:18:51 +0100770
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100771 host->bus_mode = ios->bus_mode;
Andrew Victor65dbf342006-04-02 19:18:51 +0100772
773 if (ios->clock == 0) {
774 /* Disable the MCI controller */
Andrew Victore0b19b82006-10-25 19:42:38 +0200775 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100776 clkdiv = 0;
777 }
778 else {
779 /* Enable the MCI controller */
Andrew Victore0b19b82006-10-25 19:42:38 +0200780 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
Andrew Victor65dbf342006-04-02 19:18:51 +0100781
782 if ((at91_master_clock % (ios->clock * 2)) == 0)
783 clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
784 else
785 clkdiv = (at91_master_clock / ios->clock) / 2;
786
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100787 pr_debug("clkdiv = %d. mcck = %ld\n", clkdiv,
Andrew Victor65dbf342006-04-02 19:18:51 +0100788 at91_master_clock / (2 * (clkdiv + 1)));
789 }
790 if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100791 pr_debug("MMC: Setting controller bus width to 4\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200792 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100793 }
794 else {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100795 pr_debug("MMC: Setting controller bus width to 1\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200796 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100797 }
798
799 /* Set the clock divider */
Andrew Victore0b19b82006-10-25 19:42:38 +0200800 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 +0100801
802 /* maybe switch power to the card */
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100803 if (host->board->vcc_pin) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100804 switch (ios->power_mode) {
805 case MMC_POWER_OFF:
David Brownell6e996ee2008-02-04 18:12:48 +0100806 gpio_set_value(host->board->vcc_pin, 0);
Andrew Victor65dbf342006-04-02 19:18:51 +0100807 break;
808 case MMC_POWER_UP:
David Brownell6e996ee2008-02-04 18:12:48 +0100809 gpio_set_value(host->board->vcc_pin, 1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100810 break;
Marc Pignate5c0ef92008-05-09 11:07:07 +0200811 case MMC_POWER_ON:
812 break;
813 default:
814 WARN_ON(1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100815 }
816 }
817}
818
819/*
820 * Handle an interrupt
821 */
David Howells7d12e782006-10-05 14:55:46 +0100822static irqreturn_t at91_mci_irq(int irq, void *devid)
Andrew Victor65dbf342006-04-02 19:18:51 +0100823{
824 struct at91mci_host *host = devid;
825 int completed = 0;
Andrew Victordf05a302006-10-23 14:50:09 +0200826 unsigned int int_status, int_mask;
Andrew Victor65dbf342006-04-02 19:18:51 +0100827
Andrew Victore0b19b82006-10-25 19:42:38 +0200828 int_status = at91_mci_read(host, AT91_MCI_SR);
Andrew Victordf05a302006-10-23 14:50:09 +0200829 int_mask = at91_mci_read(host, AT91_MCI_IMR);
Nicolas Ferre37b758e82007-08-08 12:01:44 +0200830
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200831 pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask,
Andrew Victordf05a302006-10-23 14:50:09 +0200832 int_status & int_mask);
Nicolas Ferre37b758e82007-08-08 12:01:44 +0200833
Andrew Victordf05a302006-10-23 14:50:09 +0200834 int_status = int_status & int_mask;
Andrew Victor65dbf342006-04-02 19:18:51 +0100835
Andrew Victordf05a302006-10-23 14:50:09 +0200836 if (int_status & AT91_MCI_ERRORS) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100837 completed = 1;
Nicolas Ferre37b758e82007-08-08 12:01:44 +0200838
Andrew Victordf05a302006-10-23 14:50:09 +0200839 if (int_status & AT91_MCI_UNRE)
840 pr_debug("MMC: Underrun error\n");
841 if (int_status & AT91_MCI_OVRE)
842 pr_debug("MMC: Overrun error\n");
843 if (int_status & AT91_MCI_DTOE)
844 pr_debug("MMC: Data timeout\n");
845 if (int_status & AT91_MCI_DCRCE)
846 pr_debug("MMC: CRC error in data\n");
847 if (int_status & AT91_MCI_RTOE)
848 pr_debug("MMC: Response timeout\n");
849 if (int_status & AT91_MCI_RENDE)
850 pr_debug("MMC: Response end bit error\n");
851 if (int_status & AT91_MCI_RCRCE)
852 pr_debug("MMC: Response CRC error\n");
853 if (int_status & AT91_MCI_RDIRE)
854 pr_debug("MMC: Response direction error\n");
855 if (int_status & AT91_MCI_RINDE)
856 pr_debug("MMC: Response index error\n");
857 } else {
858 /* Only continue processing if no errors */
Andrew Victor65dbf342006-04-02 19:18:51 +0100859
Andrew Victor65dbf342006-04-02 19:18:51 +0100860 if (int_status & AT91_MCI_TXBUFE) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100861 pr_debug("TX buffer empty\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100862 at91_mci_handle_transmitted(host);
863 }
864
Nicolas Ferreed99c542007-07-09 14:58:16 +0200865 if (int_status & AT91_MCI_ENDRX) {
866 pr_debug("ENDRX\n");
867 at91_mci_post_dma_read(host);
868 }
869
Andrew Victor65dbf342006-04-02 19:18:51 +0100870 if (int_status & AT91_MCI_RXBUFF) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100871 pr_debug("RX buffer full\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200872 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
873 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_RXBUFF | AT91_MCI_ENDRX);
874 completed = 1;
Andrew Victor65dbf342006-04-02 19:18:51 +0100875 }
876
Andrew Victordf05a302006-10-23 14:50:09 +0200877 if (int_status & AT91_MCI_ENDTX)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100878 pr_debug("Transmit has ended\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100879
Andrew Victor65dbf342006-04-02 19:18:51 +0100880 if (int_status & AT91_MCI_NOTBUSY) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100881 pr_debug("Card is ready\n");
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200882 at91_mci_update_bytes_xfered(host);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200883 completed = 1;
Andrew Victor65dbf342006-04-02 19:18:51 +0100884 }
885
Andrew Victordf05a302006-10-23 14:50:09 +0200886 if (int_status & AT91_MCI_DTIP)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100887 pr_debug("Data transfer in progress\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100888
Nicolas Ferreed99c542007-07-09 14:58:16 +0200889 if (int_status & AT91_MCI_BLKE) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100890 pr_debug("Block transfer has ended\n");
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200891 if (host->request->data && host->request->data->blocks > 1) {
892 /* multi block write : complete multi write
893 * command and send stop */
894 completed = 1;
895 } else {
896 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
897 }
Nicolas Ferreed99c542007-07-09 14:58:16 +0200898 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100899
Eric Benard7a6588b2008-05-30 14:26:05 +0200900 if (int_status & AT91_MCI_SDIOIRQA)
901 mmc_signal_sdio_irq(host->mmc);
902
903 if (int_status & AT91_MCI_SDIOIRQB)
904 mmc_signal_sdio_irq(host->mmc);
905
Andrew Victordf05a302006-10-23 14:50:09 +0200906 if (int_status & AT91_MCI_TXRDY)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100907 pr_debug("Ready to transmit\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100908
Andrew Victordf05a302006-10-23 14:50:09 +0200909 if (int_status & AT91_MCI_RXRDY)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100910 pr_debug("Ready to receive\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100911
912 if (int_status & AT91_MCI_CMDRDY) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100913 pr_debug("Command ready\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200914 completed = at91_mci_handle_cmdrdy(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100915 }
916 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100917
918 if (completed) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100919 pr_debug("Completed command\n");
Eric Benard7a6588b2008-05-30 14:26:05 +0200920 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200921 at91_mci_completed_command(host, int_status);
Andrew Victordf05a302006-10-23 14:50:09 +0200922 } else
Eric Benard7a6588b2008-05-30 14:26:05 +0200923 at91_mci_write(host, AT91_MCI_IDR, int_status & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Andrew Victor65dbf342006-04-02 19:18:51 +0100924
925 return IRQ_HANDLED;
926}
927
David Howells7d12e782006-10-05 14:55:46 +0100928static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100929{
930 struct at91mci_host *host = _host;
David Brownell6e996ee2008-02-04 18:12:48 +0100931 int present = !gpio_get_value(irq_to_gpio(irq));
Andrew Victor65dbf342006-04-02 19:18:51 +0100932
933 /*
934 * we expect this irq on both insert and remove,
935 * and use a short delay to debounce.
936 */
937 if (present != host->present) {
938 host->present = present;
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100939 pr_debug("%s: card %s\n", mmc_hostname(host->mmc),
Andrew Victor65dbf342006-04-02 19:18:51 +0100940 present ? "insert" : "remove");
941 if (!present) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100942 pr_debug("****** Resetting SD-card bus width ******\n");
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100943 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100944 }
945 mmc_detect_change(host->mmc, msecs_to_jiffies(100));
946 }
947 return IRQ_HANDLED;
948}
949
David Brownella26b4982006-12-26 14:45:26 -0800950static int at91_mci_get_ro(struct mmc_host *mmc)
Andrew Victor65dbf342006-04-02 19:18:51 +0100951{
Andrew Victor65dbf342006-04-02 19:18:51 +0100952 struct at91mci_host *host = mmc_priv(mmc);
953
Anton Vorontsov08f80bb2008-06-17 18:17:39 +0400954 if (host->board->wp_pin)
955 return !!gpio_get_value(host->board->wp_pin);
956 /*
957 * Board doesn't support read only detection; let the mmc core
958 * decide what to do.
959 */
960 return -ENOSYS;
Andrew Victor65dbf342006-04-02 19:18:51 +0100961}
962
Eric Benard7a6588b2008-05-30 14:26:05 +0200963static void at91_mci_enable_sdio_irq(struct mmc_host *mmc, int enable)
964{
965 struct at91mci_host *host = mmc_priv(mmc);
966
967 pr_debug("%s: sdio_irq %c : %s\n", mmc_hostname(host->mmc),
968 host->board->slot_b ? 'B':'A', enable ? "enable" : "disable");
969 at91_mci_write(host, enable ? AT91_MCI_IER : AT91_MCI_IDR,
970 host->board->slot_b ? AT91_MCI_SDIOIRQB : AT91_MCI_SDIOIRQA);
971
972}
973
David Brownellab7aefd2006-11-12 17:55:30 -0800974static const struct mmc_host_ops at91_mci_ops = {
Andrew Victor65dbf342006-04-02 19:18:51 +0100975 .request = at91_mci_request,
976 .set_ios = at91_mci_set_ios,
977 .get_ro = at91_mci_get_ro,
Eric Benard7a6588b2008-05-30 14:26:05 +0200978 .enable_sdio_irq = at91_mci_enable_sdio_irq,
Andrew Victor65dbf342006-04-02 19:18:51 +0100979};
980
981/*
982 * Probe for the device
983 */
David Brownella26b4982006-12-26 14:45:26 -0800984static int __init at91_mci_probe(struct platform_device *pdev)
Andrew Victor65dbf342006-04-02 19:18:51 +0100985{
986 struct mmc_host *mmc;
987 struct at91mci_host *host;
Andrew Victor17ea0592006-10-23 14:44:40 +0200988 struct resource *res;
Andrew Victor65dbf342006-04-02 19:18:51 +0100989 int ret;
990
Andrew Victor17ea0592006-10-23 14:44:40 +0200991 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
992 if (!res)
993 return -ENXIO;
994
995 if (!request_mem_region(res->start, res->end - res->start + 1, DRIVER_NAME))
996 return -EBUSY;
997
Andrew Victor65dbf342006-04-02 19:18:51 +0100998 mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
999 if (!mmc) {
David Brownell6e996ee2008-02-04 18:12:48 +01001000 ret = -ENOMEM;
1001 dev_dbg(&pdev->dev, "couldn't allocate mmc host\n");
1002 goto fail6;
Andrew Victor65dbf342006-04-02 19:18:51 +01001003 }
1004
1005 mmc->ops = &at91_mci_ops;
1006 mmc->f_min = 375000;
1007 mmc->f_max = 25000000;
1008 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
Pierre Ossman23af6032008-07-06 01:10:27 +02001009 mmc->caps = MMC_CAP_SDIO_IRQ;
Andrew Victor65dbf342006-04-02 19:18:51 +01001010
Pierre Ossmanfe4a3c72006-11-21 17:54:23 +01001011 mmc->max_blk_size = 4095;
Pierre Ossman55db8902006-11-21 17:55:45 +01001012 mmc->max_blk_count = mmc->max_req_size;
Pierre Ossmanfe4a3c72006-11-21 17:54:23 +01001013
Andrew Victor65dbf342006-04-02 19:18:51 +01001014 host = mmc_priv(mmc);
1015 host->mmc = mmc;
1016 host->buffer = NULL;
1017 host->bus_mode = 0;
1018 host->board = pdev->dev.platform_data;
1019 if (host->board->wire4) {
Nicolas Ferreed99c542007-07-09 14:58:16 +02001020 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
1021 mmc->caps |= MMC_CAP_4_BIT_DATA;
1022 else
David Brownell6e996ee2008-02-04 18:12:48 +01001023 dev_warn(&pdev->dev, "4 wire bus mode not supported"
Nicolas Ferreed99c542007-07-09 14:58:16 +02001024 " - using 1 wire\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001025 }
1026
1027 /*
David Brownell6e996ee2008-02-04 18:12:48 +01001028 * Reserve GPIOs ... board init code makes sure these pins are set
1029 * up as GPIOs with the right direction (input, except for vcc)
1030 */
1031 if (host->board->det_pin) {
1032 ret = gpio_request(host->board->det_pin, "mmc_detect");
1033 if (ret < 0) {
1034 dev_dbg(&pdev->dev, "couldn't claim card detect pin\n");
1035 goto fail5;
1036 }
1037 }
1038 if (host->board->wp_pin) {
1039 ret = gpio_request(host->board->wp_pin, "mmc_wp");
1040 if (ret < 0) {
1041 dev_dbg(&pdev->dev, "couldn't claim wp sense pin\n");
1042 goto fail4;
1043 }
1044 }
1045 if (host->board->vcc_pin) {
1046 ret = gpio_request(host->board->vcc_pin, "mmc_vcc");
1047 if (ret < 0) {
1048 dev_dbg(&pdev->dev, "couldn't claim vcc switch pin\n");
1049 goto fail3;
1050 }
1051 }
1052
1053 /*
Andrew Victor65dbf342006-04-02 19:18:51 +01001054 * Get Clock
1055 */
Andrew Victor3dd3b032006-10-23 14:46:54 +02001056 host->mci_clk = clk_get(&pdev->dev, "mci_clk");
1057 if (IS_ERR(host->mci_clk)) {
David Brownell6e996ee2008-02-04 18:12:48 +01001058 ret = -ENODEV;
1059 dev_dbg(&pdev->dev, "no mci_clk?\n");
1060 goto fail2;
Andrew Victor65dbf342006-04-02 19:18:51 +01001061 }
Andrew Victor65dbf342006-04-02 19:18:51 +01001062
Andrew Victor17ea0592006-10-23 14:44:40 +02001063 /*
1064 * Map I/O region
1065 */
1066 host->baseaddr = ioremap(res->start, res->end - res->start + 1);
1067 if (!host->baseaddr) {
David Brownell6e996ee2008-02-04 18:12:48 +01001068 ret = -ENOMEM;
1069 goto fail1;
Andrew Victor17ea0592006-10-23 14:44:40 +02001070 }
Andrew Victore0b19b82006-10-25 19:42:38 +02001071
1072 /*
1073 * Reset hardware
1074 */
Andrew Victor3dd3b032006-10-23 14:46:54 +02001075 clk_enable(host->mci_clk); /* Enable the peripheral clock */
Andrew Victore0b19b82006-10-25 19:42:38 +02001076 at91_mci_disable(host);
1077 at91_mci_enable(host);
1078
Andrew Victor65dbf342006-04-02 19:18:51 +01001079 /*
1080 * Allocate the MCI interrupt
1081 */
Andrew Victor17ea0592006-10-23 14:44:40 +02001082 host->irq = platform_get_irq(pdev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +01001083 ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED,
1084 mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001085 if (ret) {
David Brownell6e996ee2008-02-04 18:12:48 +01001086 dev_dbg(&pdev->dev, "request MCI interrupt failed\n");
1087 goto fail0;
Andrew Victor65dbf342006-04-02 19:18:51 +01001088 }
1089
Nicolas Ferre99ba0402008-11-27 17:23:49 +01001090 setup_timer(&host->timer, at91_timeout_timer, (unsigned long)host);
1091
Andrew Victor65dbf342006-04-02 19:18:51 +01001092 platform_set_drvdata(pdev, mmc);
1093
1094 /*
1095 * Add host to MMC layer
1096 */
Marc Pignat63b66432007-07-16 11:07:02 +02001097 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001098 host->present = !gpio_get_value(host->board->det_pin);
Marc Pignat63b66432007-07-16 11:07:02 +02001099 }
Andrew Victor65dbf342006-04-02 19:18:51 +01001100 else
1101 host->present = -1;
1102
1103 mmc_add_host(mmc);
1104
1105 /*
1106 * monitor card insertion/removal if we can
1107 */
1108 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001109 ret = request_irq(gpio_to_irq(host->board->det_pin),
1110 at91_mmc_det_irq, 0, mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001111 if (ret)
David Brownell6e996ee2008-02-04 18:12:48 +01001112 dev_warn(&pdev->dev, "request MMC detect irq failed\n");
1113 else
1114 device_init_wakeup(&pdev->dev, 1);
Andrew Victor65dbf342006-04-02 19:18:51 +01001115 }
1116
Andrew Victorf3a8efa2006-10-23 14:53:20 +02001117 pr_debug("Added MCI driver\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001118
1119 return 0;
David Brownell6e996ee2008-02-04 18:12:48 +01001120
1121fail0:
1122 clk_disable(host->mci_clk);
1123 iounmap(host->baseaddr);
1124fail1:
1125 clk_put(host->mci_clk);
1126fail2:
1127 if (host->board->vcc_pin)
1128 gpio_free(host->board->vcc_pin);
1129fail3:
1130 if (host->board->wp_pin)
1131 gpio_free(host->board->wp_pin);
1132fail4:
1133 if (host->board->det_pin)
1134 gpio_free(host->board->det_pin);
1135fail5:
1136 mmc_free_host(mmc);
1137fail6:
1138 release_mem_region(res->start, res->end - res->start + 1);
1139 dev_err(&pdev->dev, "probe failed, err %d\n", ret);
1140 return ret;
Andrew Victor65dbf342006-04-02 19:18:51 +01001141}
1142
1143/*
1144 * Remove a device
1145 */
David Brownella26b4982006-12-26 14:45:26 -08001146static int __exit at91_mci_remove(struct platform_device *pdev)
Andrew Victor65dbf342006-04-02 19:18:51 +01001147{
1148 struct mmc_host *mmc = platform_get_drvdata(pdev);
1149 struct at91mci_host *host;
Andrew Victor17ea0592006-10-23 14:44:40 +02001150 struct resource *res;
Andrew Victor65dbf342006-04-02 19:18:51 +01001151
1152 if (!mmc)
1153 return -1;
1154
1155 host = mmc_priv(mmc);
1156
Anti Sulline0cda542007-08-30 16:15:16 +02001157 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001158 if (device_can_wakeup(&pdev->dev))
1159 free_irq(gpio_to_irq(host->board->det_pin), host);
Marc Pignat63b66432007-07-16 11:07:02 +02001160 device_init_wakeup(&pdev->dev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +01001161 gpio_free(host->board->det_pin);
Andrew Victor65dbf342006-04-02 19:18:51 +01001162 }
1163
Andrew Victore0b19b82006-10-25 19:42:38 +02001164 at91_mci_disable(host);
Marc Pignate181dce2008-05-30 14:06:32 +02001165 del_timer_sync(&host->timer);
Andrew Victor17ea0592006-10-23 14:44:40 +02001166 mmc_remove_host(mmc);
1167 free_irq(host->irq, host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001168
Andrew Victor3dd3b032006-10-23 14:46:54 +02001169 clk_disable(host->mci_clk); /* Disable the peripheral clock */
1170 clk_put(host->mci_clk);
Andrew Victor65dbf342006-04-02 19:18:51 +01001171
David Brownell6e996ee2008-02-04 18:12:48 +01001172 if (host->board->vcc_pin)
1173 gpio_free(host->board->vcc_pin);
1174 if (host->board->wp_pin)
1175 gpio_free(host->board->wp_pin);
1176
Andrew Victor17ea0592006-10-23 14:44:40 +02001177 iounmap(host->baseaddr);
1178 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1179 release_mem_region(res->start, res->end - res->start + 1);
Andrew Victor65dbf342006-04-02 19:18:51 +01001180
Andrew Victor17ea0592006-10-23 14:44:40 +02001181 mmc_free_host(mmc);
1182 platform_set_drvdata(pdev, NULL);
Andrew Victorb44fb7a2006-06-19 13:06:05 +01001183 pr_debug("MCI Removed\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001184
1185 return 0;
1186}
1187
1188#ifdef CONFIG_PM
1189static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
1190{
1191 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001192 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001193 int ret = 0;
1194
Anti Sulline0cda542007-08-30 16:15:16 +02001195 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001196 enable_irq_wake(host->board->det_pin);
1197
Andrew Victor65dbf342006-04-02 19:18:51 +01001198 if (mmc)
1199 ret = mmc_suspend_host(mmc, state);
1200
1201 return ret;
1202}
1203
1204static int at91_mci_resume(struct platform_device *pdev)
1205{
1206 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001207 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001208 int ret = 0;
1209
Anti Sulline0cda542007-08-30 16:15:16 +02001210 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001211 disable_irq_wake(host->board->det_pin);
1212
Andrew Victor65dbf342006-04-02 19:18:51 +01001213 if (mmc)
1214 ret = mmc_resume_host(mmc);
1215
1216 return ret;
1217}
1218#else
1219#define at91_mci_suspend NULL
1220#define at91_mci_resume NULL
1221#endif
1222
1223static struct platform_driver at91_mci_driver = {
David Brownella26b4982006-12-26 14:45:26 -08001224 .remove = __exit_p(at91_mci_remove),
Andrew Victor65dbf342006-04-02 19:18:51 +01001225 .suspend = at91_mci_suspend,
1226 .resume = at91_mci_resume,
1227 .driver = {
1228 .name = DRIVER_NAME,
1229 .owner = THIS_MODULE,
1230 },
1231};
1232
1233static int __init at91_mci_init(void)
1234{
David Brownella26b4982006-12-26 14:45:26 -08001235 return platform_driver_probe(&at91_mci_driver, at91_mci_probe);
Andrew Victor65dbf342006-04-02 19:18:51 +01001236}
1237
1238static void __exit at91_mci_exit(void)
1239{
1240 platform_driver_unregister(&at91_mci_driver);
1241}
1242
1243module_init(at91_mci_init);
1244module_exit(at91_mci_exit);
1245
1246MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
1247MODULE_AUTHOR("Nick Randell");
1248MODULE_LICENSE("GPL");
Kay Sieversbc65c722008-04-15 14:34:28 -07001249MODULE_ALIAS("platform:at91_mci");