blob: a6dd7da37357a11667755d22d6898df8e3fc97e9 [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>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090068#include <linux/gfp.h>
Andrew Victor65dbf342006-04-02 19:18:51 +010069
70#include <linux/mmc/host.h>
Andrew Victor65dbf342006-04-02 19:18:51 +010071
72#include <asm/io.h>
73#include <asm/irq.h>
David Brownell6e996ee2008-02-04 18:12:48 +010074#include <asm/gpio.h>
75
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
Nicolas Ferre5b27a1a2010-03-05 13:43:44 -080082static inline int at91mci_is_mci1rev2xx(void)
83{
84 return ( cpu_is_at91sam9260()
85 || cpu_is_at91sam9263()
86 || cpu_is_at91cap9()
87 || cpu_is_at91sam9rl()
88 || cpu_is_at91sam9g10()
89 || cpu_is_at91sam9g20()
90 );
91}
92
Andrew Victordf05a302006-10-23 14:50:09 +020093#define FL_SENT_COMMAND (1 << 0)
94#define FL_SENT_STOP (1 << 1)
Andrew Victor65dbf342006-04-02 19:18:51 +010095
Andrew Victordf05a302006-10-23 14:50:09 +020096#define AT91_MCI_ERRORS (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE \
97 | AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE \
Nicolas Ferre37b758e82007-08-08 12:01:44 +020098 | AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)
Andrew Victor65dbf342006-04-02 19:18:51 +010099
Andrew Victore0b19b82006-10-25 19:42:38 +0200100#define at91_mci_read(host, reg) __raw_readl((host)->baseaddr + (reg))
101#define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg))
Andrew Victor65dbf342006-04-02 19:18:51 +0100102
Wolfgang Muees3780d902010-03-05 13:43:40 -0800103#define MCI_BLKSIZE 512
104#define MCI_MAXBLKSIZE 4095
105#define MCI_BLKATONCE 256
106#define MCI_BUFSIZE (MCI_BLKSIZE * MCI_BLKATONCE)
Andrew Victor65dbf342006-04-02 19:18:51 +0100107
108/*
109 * Low level type for this driver
110 */
111struct at91mci_host
112{
113 struct mmc_host *mmc;
114 struct mmc_command *cmd;
115 struct mmc_request *request;
116
Andrew Victore0b19b82006-10-25 19:42:38 +0200117 void __iomem *baseaddr;
Andrew Victor17ea0592006-10-23 14:44:40 +0200118 int irq;
Andrew Victore0b19b82006-10-25 19:42:38 +0200119
Andrew Victor65dbf342006-04-02 19:18:51 +0100120 struct at91_mmc_data *board;
121 int present;
122
Andrew Victor3dd3b032006-10-23 14:46:54 +0200123 struct clk *mci_clk;
124
Andrew Victor65dbf342006-04-02 19:18:51 +0100125 /*
126 * Flag indicating when the command has been sent. This is used to
127 * work out whether or not to send the stop
128 */
129 unsigned int flags;
130 /* flag for current bus settings */
131 u32 bus_mode;
132
133 /* DMA buffer used for transmitting */
134 unsigned int* buffer;
135 dma_addr_t physical_address;
136 unsigned int total_length;
137
138 /* Latest in the scatterlist that has been enabled for transfer, but not freed */
139 int in_use_index;
140
141 /* Latest in the scatterlist that has been enabled for transfer */
142 int transfer_index;
Marc Pignate181dce2008-05-30 14:06:32 +0200143
144 /* Timer for timeouts */
145 struct timer_list timer;
Andrew Victor65dbf342006-04-02 19:18:51 +0100146};
147
Marc Pignatc5a89c62008-05-30 14:07:47 +0200148/*
149 * Reset the controller and restore most of the state
150 */
151static void at91_reset_host(struct at91mci_host *host)
152{
153 unsigned long flags;
154 u32 mr;
155 u32 sdcr;
156 u32 dtor;
157 u32 imr;
158
159 local_irq_save(flags);
160 imr = at91_mci_read(host, AT91_MCI_IMR);
161
162 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
163
164 /* save current state */
165 mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
166 sdcr = at91_mci_read(host, AT91_MCI_SDCR);
167 dtor = at91_mci_read(host, AT91_MCI_DTOR);
168
169 /* reset the controller */
170 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
171
172 /* restore state */
173 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
174 at91_mci_write(host, AT91_MCI_MR, mr);
175 at91_mci_write(host, AT91_MCI_SDCR, sdcr);
176 at91_mci_write(host, AT91_MCI_DTOR, dtor);
177 at91_mci_write(host, AT91_MCI_IER, imr);
178
179 /* make sure sdio interrupts will fire */
180 at91_mci_read(host, AT91_MCI_SR);
181
182 local_irq_restore(flags);
183}
184
Marc Pignate181dce2008-05-30 14:06:32 +0200185static void at91_timeout_timer(unsigned long data)
186{
187 struct at91mci_host *host;
188
189 host = (struct at91mci_host *)data;
190
191 if (host->request) {
192 dev_err(host->mmc->parent, "Timeout waiting end of packet\n");
193
194 if (host->cmd && host->cmd->data) {
195 host->cmd->data->error = -ETIMEDOUT;
196 } else {
197 if (host->cmd)
198 host->cmd->error = -ETIMEDOUT;
199 else
200 host->request->cmd->error = -ETIMEDOUT;
201 }
202
Marc Pignatc5a89c62008-05-30 14:07:47 +0200203 at91_reset_host(host);
Marc Pignate181dce2008-05-30 14:06:32 +0200204 mmc_request_done(host->mmc, host->request);
205 }
206}
207
Andrew Victor65dbf342006-04-02 19:18:51 +0100208/*
209 * Copy from sg to a dma block - used for transfers
210 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200211static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
Andrew Victor65dbf342006-04-02 19:18:51 +0100212{
213 unsigned int len, i, size;
214 unsigned *dmabuf = host->buffer;
215
Ville Syrjala5385edc2008-06-14 20:27:20 +0300216 size = data->blksz * data->blocks;
Andrew Victor65dbf342006-04-02 19:18:51 +0100217 len = data->sg_len;
218
Nicolas Ferre5b27a1a2010-03-05 13:43:44 -0800219 /* MCI1 rev2xx Data Write Operation and number of bytes erratum */
220 if (at91mci_is_mci1rev2xx())
Ville Syrjala5385edc2008-06-14 20:27:20 +0300221 if (host->total_length == 12)
222 memset(dmabuf, 0, 12);
223
Andrew Victor65dbf342006-04-02 19:18:51 +0100224 /*
225 * Just loop through all entries. Size might not
226 * be the entire list though so make sure that
227 * we do not transfer too much.
228 */
229 for (i = 0; i < len; i++) {
230 struct scatterlist *sg;
231 int amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100232 unsigned int *sgbuffer;
233
234 sg = &data->sg[i];
235
Jens Axboe45711f12007-10-22 21:19:53 +0200236 sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
Andrew Victor65dbf342006-04-02 19:18:51 +0100237 amount = min(size, sg->length);
238 size -= amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100239
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100240 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
241 int index;
242
243 for (index = 0; index < (amount / 4); index++)
244 *dmabuf++ = swab32(sgbuffer[index]);
Ville Syrjala5385edc2008-06-14 20:27:20 +0300245 } else {
Wolfgang Muees0b3520f2010-03-05 13:43:38 -0800246 char *tmpv = (char *)dmabuf;
247 memcpy(tmpv, sgbuffer, amount);
248 tmpv += amount;
249 dmabuf = (unsigned *)tmpv;
Ville Syrjala5385edc2008-06-14 20:27:20 +0300250 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100251
Nicolas Ferre752993e2010-03-05 13:43:45 -0800252 kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
Andrew Victor65dbf342006-04-02 19:18:51 +0100253
254 if (size == 0)
255 break;
256 }
257
258 /*
259 * Check that we didn't get a request to transfer
260 * more data than can fit into the SG list.
261 */
262 BUG_ON(size != 0);
263}
264
265/*
Andrew Victor65dbf342006-04-02 19:18:51 +0100266 * Handle after a dma read
267 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200268static void at91_mci_post_dma_read(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100269{
270 struct mmc_command *cmd;
271 struct mmc_data *data;
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800272 unsigned int len, i, size;
273 unsigned *dmabuf = host->buffer;
Andrew Victor65dbf342006-04-02 19:18:51 +0100274
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100275 pr_debug("post dma read\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100276
277 cmd = host->cmd;
278 if (!cmd) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100279 pr_debug("no command\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100280 return;
281 }
282
283 data = cmd->data;
284 if (!data) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100285 pr_debug("no data\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100286 return;
287 }
288
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800289 size = data->blksz * data->blocks;
290 len = data->sg_len;
291
292 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
293 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
294
295 for (i = 0; i < len; i++) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100296 struct scatterlist *sg;
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800297 int amount;
298 unsigned int *sgbuffer;
Andrew Victor65dbf342006-04-02 19:18:51 +0100299
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800300 sg = &data->sg[i];
Andrew Victor65dbf342006-04-02 19:18:51 +0100301
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800302 sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
303 amount = min(size, sg->length);
304 size -= amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100305
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100306 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
307 int index;
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800308 for (index = 0; index < (amount / 4); index++)
309 sgbuffer[index] = swab32(*dmabuf++);
310 } else {
311 char *tmpv = (char *)dmabuf;
312 memcpy(sgbuffer, tmpv, amount);
313 tmpv += amount;
314 dmabuf = (unsigned *)tmpv;
Andrew Victor65dbf342006-04-02 19:18:51 +0100315 }
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100316
Nicolas Ferre752993e2010-03-05 13:43:45 -0800317 kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800318 dmac_flush_range((void *)sgbuffer, ((void *)sgbuffer) + amount);
319 data->bytes_xfered += amount;
320 if (size == 0)
321 break;
Andrew Victor65dbf342006-04-02 19:18:51 +0100322 }
323
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100324 pr_debug("post dma read done\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100325}
326
327/*
328 * Handle transmitted data
329 */
330static void at91_mci_handle_transmitted(struct at91mci_host *host)
331{
332 struct mmc_command *cmd;
333 struct mmc_data *data;
334
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100335 pr_debug("Handling the transmit\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100336
337 /* Disable the transfer */
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100338 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100339
340 /* Now wait for cmd ready */
Andrew Victore0b19b82006-10-25 19:42:38 +0200341 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
Andrew Victor65dbf342006-04-02 19:18:51 +0100342
343 cmd = host->cmd;
344 if (!cmd) return;
345
346 data = cmd->data;
347 if (!data) return;
348
Pierre Ossmanbe0192a2007-07-24 21:11:47 +0200349 if (cmd->data->blocks > 1) {
Nicolas Ferreed99c542007-07-09 14:58:16 +0200350 pr_debug("multiple write : wait for BLKE...\n");
351 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
352 } else
353 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
Andrew Victor65dbf342006-04-02 19:18:51 +0100354}
355
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200356/*
357 * Update bytes tranfered count during a write operation
358 */
359static void at91_mci_update_bytes_xfered(struct at91mci_host *host)
360{
361 struct mmc_data *data;
362
363 /* always deal with the effective request (and not the current cmd) */
364
365 if (host->request->cmd && host->request->cmd->error != 0)
366 return;
367
368 if (host->request->data) {
369 data = host->request->data;
370 if (data->flags & MMC_DATA_WRITE) {
371 /* card is in IDLE mode now */
372 pr_debug("-> bytes_xfered %d, total_length = %d\n",
373 data->bytes_xfered, host->total_length);
Ville Syrjala5385edc2008-06-14 20:27:20 +0300374 data->bytes_xfered = data->blksz * data->blocks;
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200375 }
376 }
377}
378
379
Nicolas Ferreed99c542007-07-09 14:58:16 +0200380/*Handle after command sent ready*/
381static int at91_mci_handle_cmdrdy(struct at91mci_host *host)
382{
383 if (!host->cmd)
384 return 1;
385 else if (!host->cmd->data) {
386 if (host->flags & FL_SENT_STOP) {
387 /*After multi block write, we must wait for NOTBUSY*/
388 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
389 } else return 1;
390 } else if (host->cmd->data->flags & MMC_DATA_WRITE) {
391 /*After sendding multi-block-write command, start DMA transfer*/
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200392 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE | AT91_MCI_BLKE);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200393 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
394 }
395
396 /* command not completed, have to wait */
397 return 0;
398}
399
400
Andrew Victor65dbf342006-04-02 19:18:51 +0100401/*
402 * Enable the controller
403 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200404static void at91_mci_enable(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100405{
Nicolas Ferreed99c542007-07-09 14:58:16 +0200406 unsigned int mr;
407
Andrew Victore0b19b82006-10-25 19:42:38 +0200408 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200409 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
Andrew Victore0b19b82006-10-25 19:42:38 +0200410 at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200411 mr = AT91_MCI_PDCMODE | 0x34a;
412
Nicolas Ferre5b27a1a2010-03-05 13:43:44 -0800413 if (at91mci_is_mci1rev2xx())
Nicolas Ferreed99c542007-07-09 14:58:16 +0200414 mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
415
416 at91_mci_write(host, AT91_MCI_MR, mr);
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100417
418 /* use Slot A or B (only one at same time) */
419 at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
Andrew Victor65dbf342006-04-02 19:18:51 +0100420}
421
422/*
423 * Disable the controller
424 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200425static void at91_mci_disable(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100426{
Andrew Victore0b19b82006-10-25 19:42:38 +0200427 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
Andrew Victor65dbf342006-04-02 19:18:51 +0100428}
429
430/*
431 * Send a command
Andrew Victor65dbf342006-04-02 19:18:51 +0100432 */
Nicolas Ferreed99c542007-07-09 14:58:16 +0200433static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
Andrew Victor65dbf342006-04-02 19:18:51 +0100434{
435 unsigned int cmdr, mr;
436 unsigned int block_length;
437 struct mmc_data *data = cmd->data;
438
439 unsigned int blocks;
440 unsigned int ier = 0;
441
442 host->cmd = cmd;
443
Nicolas Ferreed99c542007-07-09 14:58:16 +0200444 /* Needed for leaving busy state before CMD1 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200445 if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100446 pr_debug("Clearing timeout\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200447 at91_mci_write(host, AT91_MCI_ARGR, 0);
448 at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
449 while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100450 /* spin */
Andrew Victore0b19b82006-10-25 19:42:38 +0200451 pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
Andrew Victor65dbf342006-04-02 19:18:51 +0100452 }
453 }
Nicolas Ferreed99c542007-07-09 14:58:16 +0200454
Andrew Victor65dbf342006-04-02 19:18:51 +0100455 cmdr = cmd->opcode;
456
457 if (mmc_resp_type(cmd) == MMC_RSP_NONE)
458 cmdr |= AT91_MCI_RSPTYP_NONE;
459 else {
460 /* if a response is expected then allow maximum response latancy */
461 cmdr |= AT91_MCI_MAXLAT;
462 /* set 136 bit response for R2, 48 bit response otherwise */
463 if (mmc_resp_type(cmd) == MMC_RSP_R2)
464 cmdr |= AT91_MCI_RSPTYP_136;
465 else
466 cmdr |= AT91_MCI_RSPTYP_48;
467 }
468
469 if (data) {
Marc Pignat1d4de9e2007-08-09 13:56:29 +0200470
Ville Syrjala9da3cba2008-06-09 22:06:44 +0300471 if (cpu_is_at91rm9200() || cpu_is_at91sam9261()) {
472 if (data->blksz & 0x3) {
473 pr_debug("Unsupported block size\n");
474 cmd->error = -EINVAL;
475 mmc_request_done(host->mmc, host->request);
476 return;
477 }
478 if (data->flags & MMC_DATA_STREAM) {
479 pr_debug("Stream commands not supported\n");
480 cmd->error = -EINVAL;
481 mmc_request_done(host->mmc, host->request);
482 return;
483 }
Marc Pignat1d4de9e2007-08-09 13:56:29 +0200484 }
485
Russell Kinga3fd4a12006-06-04 17:51:15 +0100486 block_length = data->blksz;
Andrew Victor65dbf342006-04-02 19:18:51 +0100487 blocks = data->blocks;
488
489 /* always set data start - also set direction flag for read */
490 if (data->flags & MMC_DATA_READ)
491 cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
492 else if (data->flags & MMC_DATA_WRITE)
493 cmdr |= AT91_MCI_TRCMD_START;
494
495 if (data->flags & MMC_DATA_STREAM)
496 cmdr |= AT91_MCI_TRTYP_STREAM;
Pierre Ossmanbe0192a2007-07-24 21:11:47 +0200497 if (data->blocks > 1)
Andrew Victor65dbf342006-04-02 19:18:51 +0100498 cmdr |= AT91_MCI_TRTYP_MULTIPLE;
499 }
500 else {
501 block_length = 0;
502 blocks = 0;
503 }
504
Marc Pignatb6cedb32007-06-06 20:27:59 +0200505 if (host->flags & FL_SENT_STOP)
Andrew Victor65dbf342006-04-02 19:18:51 +0100506 cmdr |= AT91_MCI_TRCMD_STOP;
507
508 if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
509 cmdr |= AT91_MCI_OPDCMD;
510
511 /*
512 * Set the arguments and send the command
513 */
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200514 pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
Andrew Victore0b19b82006-10-25 19:42:38 +0200515 cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
Andrew Victor65dbf342006-04-02 19:18:51 +0100516
517 if (!data) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100518 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
519 at91_mci_write(host, ATMEL_PDC_RPR, 0);
520 at91_mci_write(host, ATMEL_PDC_RCR, 0);
521 at91_mci_write(host, ATMEL_PDC_RNPR, 0);
522 at91_mci_write(host, ATMEL_PDC_RNCR, 0);
523 at91_mci_write(host, ATMEL_PDC_TPR, 0);
524 at91_mci_write(host, ATMEL_PDC_TCR, 0);
525 at91_mci_write(host, ATMEL_PDC_TNPR, 0);
526 at91_mci_write(host, ATMEL_PDC_TNCR, 0);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200527 ier = AT91_MCI_CMDRDY;
528 } else {
529 /* zero block length and PDC mode */
Ville Syrjala12bd2572008-06-09 22:06:45 +0300530 mr = at91_mci_read(host, AT91_MCI_MR) & 0x5fff;
Marc Pignat80f92542008-05-30 14:05:24 +0200531 mr |= (data->blksz & 0x3) ? AT91_MCI_PDCFBYTE : 0;
532 mr |= (block_length << 16);
533 mr |= AT91_MCI_PDCMODE;
534 at91_mci_write(host, AT91_MCI_MR, mr);
Andrew Victor65dbf342006-04-02 19:18:51 +0100535
Ville Syrjala9da3cba2008-06-09 22:06:44 +0300536 if (!(cpu_is_at91rm9200() || cpu_is_at91sam9261()))
Marc Pignatc5a89c62008-05-30 14:07:47 +0200537 at91_mci_write(host, AT91_MCI_BLKR,
538 AT91_MCI_BLKR_BCNT(blocks) |
539 AT91_MCI_BLKR_BLKLEN(block_length));
540
Nicolas Ferreed99c542007-07-09 14:58:16 +0200541 /*
542 * Disable the PDC controller
543 */
544 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100545
Nicolas Ferreed99c542007-07-09 14:58:16 +0200546 if (cmdr & AT91_MCI_TRCMD_START) {
547 data->bytes_xfered = 0;
548 host->transfer_index = 0;
549 host->in_use_index = 0;
550 if (cmdr & AT91_MCI_TRDIR) {
551 /*
552 * Handle a read
553 */
Nicolas Ferreed99c542007-07-09 14:58:16 +0200554 host->total_length = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100555
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800556 at91_mci_write(host, ATMEL_PDC_RPR, host->physical_address);
557 at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ?
558 (blocks * block_length) : (blocks * block_length) / 4);
559 at91_mci_write(host, ATMEL_PDC_RNPR, 0);
560 at91_mci_write(host, ATMEL_PDC_RNCR, 0);
561
Nicolas Ferreed99c542007-07-09 14:58:16 +0200562 ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
563 }
564 else {
565 /*
566 * Handle a write
567 */
568 host->total_length = block_length * blocks;
Ville Syrjala5385edc2008-06-14 20:27:20 +0300569 /*
Nicolas Ferre5b27a1a2010-03-05 13:43:44 -0800570 * MCI1 rev2xx Data Write Operation and
Ville Syrjala5385edc2008-06-14 20:27:20 +0300571 * number of bytes erratum
572 */
Nicolas Ferre5b27a1a2010-03-05 13:43:44 -0800573 if (at91mci_is_mci1rev2xx())
Ville Syrjala5385edc2008-06-14 20:27:20 +0300574 if (host->total_length < 12)
575 host->total_length = 12;
David Brownelle385ea62008-09-02 14:35:46 -0700576
Nicolas Ferreed99c542007-07-09 14:58:16 +0200577 at91_mci_sg_to_dma(host, data);
Andrew Victor65dbf342006-04-02 19:18:51 +0100578
Nicolas Ferreed99c542007-07-09 14:58:16 +0200579 pr_debug("Transmitting %d bytes\n", host->total_length);
Andrew Victor65dbf342006-04-02 19:18:51 +0100580
Nicolas Ferreed99c542007-07-09 14:58:16 +0200581 at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200582 at91_mci_write(host, ATMEL_PDC_TCR, (data->blksz & 0x3) ?
583 host->total_length : host->total_length / 4);
584
Nicolas Ferreed99c542007-07-09 14:58:16 +0200585 ier = AT91_MCI_CMDRDY;
586 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100587 }
588 }
589
590 /*
591 * Send the command and then enable the PDC - not the other way round as
592 * the data sheet says
593 */
594
Andrew Victore0b19b82006-10-25 19:42:38 +0200595 at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
596 at91_mci_write(host, AT91_MCI_CMDR, cmdr);
Andrew Victor65dbf342006-04-02 19:18:51 +0100597
598 if (cmdr & AT91_MCI_TRCMD_START) {
599 if (cmdr & AT91_MCI_TRDIR)
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100600 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
Andrew Victor65dbf342006-04-02 19:18:51 +0100601 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100602
Nicolas Ferreed99c542007-07-09 14:58:16 +0200603 /* Enable selected interrupts */
Andrew Victordf05a302006-10-23 14:50:09 +0200604 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
Andrew Victor65dbf342006-04-02 19:18:51 +0100605}
606
607/*
608 * Process the next step in the request
609 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200610static void at91_mci_process_next(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100611{
612 if (!(host->flags & FL_SENT_COMMAND)) {
613 host->flags |= FL_SENT_COMMAND;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200614 at91_mci_send_command(host, host->request->cmd);
Andrew Victor65dbf342006-04-02 19:18:51 +0100615 }
616 else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
617 host->flags |= FL_SENT_STOP;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200618 at91_mci_send_command(host, host->request->stop);
Marc Pignate181dce2008-05-30 14:06:32 +0200619 } else {
620 del_timer(&host->timer);
Marc Pignatc5a89c62008-05-30 14:07:47 +0200621 /* the at91rm9200 mci controller hangs after some transfers,
622 * and the workaround is to reset it after each transfer.
623 */
624 if (cpu_is_at91rm9200())
625 at91_reset_host(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100626 mmc_request_done(host->mmc, host->request);
Marc Pignate181dce2008-05-30 14:06:32 +0200627 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100628}
629
630/*
631 * Handle a command that has been completed
632 */
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200633static void at91_mci_completed_command(struct at91mci_host *host, unsigned int status)
Andrew Victor65dbf342006-04-02 19:18:51 +0100634{
635 struct mmc_command *cmd = host->cmd;
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200636 struct mmc_data *data = cmd->data;
Andrew Victor65dbf342006-04-02 19:18:51 +0100637
Eric Benard7a6588b2008-05-30 14:26:05 +0200638 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Andrew Victor65dbf342006-04-02 19:18:51 +0100639
Andrew Victore0b19b82006-10-25 19:42:38 +0200640 cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
641 cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
642 cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
643 cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
Andrew Victor65dbf342006-04-02 19:18:51 +0100644
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200645 pr_debug("Status = %08X/%08x [%08X %08X %08X %08X]\n",
646 status, at91_mci_read(host, AT91_MCI_SR),
647 cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
Andrew Victor65dbf342006-04-02 19:18:51 +0100648
Andrew Victor9e3866b2007-10-17 11:53:40 +0200649 if (status & AT91_MCI_ERRORS) {
Marc Pignatb6cedb32007-06-06 20:27:59 +0200650 if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
Pierre Ossman17b04292007-07-22 22:18:46 +0200651 cmd->error = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100652 }
653 else {
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200654 if (status & (AT91_MCI_DTOE | AT91_MCI_DCRCE)) {
655 if (data) {
656 if (status & AT91_MCI_DTOE)
657 data->error = -ETIMEDOUT;
658 else if (status & AT91_MCI_DCRCE)
659 data->error = -EILSEQ;
660 }
661 } else {
662 if (status & AT91_MCI_RTOE)
663 cmd->error = -ETIMEDOUT;
664 else if (status & AT91_MCI_RCRCE)
665 cmd->error = -EILSEQ;
666 else
667 cmd->error = -EIO;
668 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100669
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200670 pr_debug("Error detected and set to %d/%d (cmd = %d, retries = %d)\n",
671 cmd->error, data ? data->error : 0,
672 cmd->opcode, cmd->retries);
Andrew Victor65dbf342006-04-02 19:18:51 +0100673 }
674 }
675 else
Pierre Ossman17b04292007-07-22 22:18:46 +0200676 cmd->error = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100677
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200678 at91_mci_process_next(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100679}
680
681/*
682 * Handle an MMC request
683 */
684static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
685{
686 struct at91mci_host *host = mmc_priv(mmc);
687 host->request = mrq;
688 host->flags = 0;
689
Wolfgang Mueesa04ac5b2010-03-05 13:43:39 -0800690 /* more than 1s timeout needed with slow SD cards */
691 mod_timer(&host->timer, jiffies + msecs_to_jiffies(2000));
Marc Pignate181dce2008-05-30 14:06:32 +0200692
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200693 at91_mci_process_next(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100694}
695
696/*
697 * Set the IOS
698 */
699static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
700{
701 int clkdiv;
702 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor3dd3b032006-10-23 14:46:54 +0200703 unsigned long at91_master_clock = clk_get_rate(host->mci_clk);
Andrew Victor65dbf342006-04-02 19:18:51 +0100704
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100705 host->bus_mode = ios->bus_mode;
Andrew Victor65dbf342006-04-02 19:18:51 +0100706
707 if (ios->clock == 0) {
708 /* Disable the MCI controller */
Andrew Victore0b19b82006-10-25 19:42:38 +0200709 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100710 clkdiv = 0;
711 }
712 else {
713 /* Enable the MCI controller */
Andrew Victore0b19b82006-10-25 19:42:38 +0200714 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
Andrew Victor65dbf342006-04-02 19:18:51 +0100715
716 if ((at91_master_clock % (ios->clock * 2)) == 0)
717 clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
718 else
719 clkdiv = (at91_master_clock / ios->clock) / 2;
720
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100721 pr_debug("clkdiv = %d. mcck = %ld\n", clkdiv,
Andrew Victor65dbf342006-04-02 19:18:51 +0100722 at91_master_clock / (2 * (clkdiv + 1)));
723 }
724 if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100725 pr_debug("MMC: Setting controller bus width to 4\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200726 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100727 }
728 else {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100729 pr_debug("MMC: Setting controller bus width to 1\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200730 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100731 }
732
733 /* Set the clock divider */
Andrew Victore0b19b82006-10-25 19:42:38 +0200734 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 +0100735
736 /* maybe switch power to the card */
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100737 if (host->board->vcc_pin) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100738 switch (ios->power_mode) {
739 case MMC_POWER_OFF:
David Brownell6e996ee2008-02-04 18:12:48 +0100740 gpio_set_value(host->board->vcc_pin, 0);
Andrew Victor65dbf342006-04-02 19:18:51 +0100741 break;
742 case MMC_POWER_UP:
David Brownell6e996ee2008-02-04 18:12:48 +0100743 gpio_set_value(host->board->vcc_pin, 1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100744 break;
Marc Pignate5c0ef92008-05-09 11:07:07 +0200745 case MMC_POWER_ON:
746 break;
747 default:
748 WARN_ON(1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100749 }
750 }
751}
752
753/*
754 * Handle an interrupt
755 */
David Howells7d12e782006-10-05 14:55:46 +0100756static irqreturn_t at91_mci_irq(int irq, void *devid)
Andrew Victor65dbf342006-04-02 19:18:51 +0100757{
758 struct at91mci_host *host = devid;
759 int completed = 0;
Andrew Victordf05a302006-10-23 14:50:09 +0200760 unsigned int int_status, int_mask;
Andrew Victor65dbf342006-04-02 19:18:51 +0100761
Andrew Victore0b19b82006-10-25 19:42:38 +0200762 int_status = at91_mci_read(host, AT91_MCI_SR);
Andrew Victordf05a302006-10-23 14:50:09 +0200763 int_mask = at91_mci_read(host, AT91_MCI_IMR);
Nicolas Ferre37b758e82007-08-08 12:01:44 +0200764
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200765 pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask,
Andrew Victordf05a302006-10-23 14:50:09 +0200766 int_status & int_mask);
Nicolas Ferre37b758e82007-08-08 12:01:44 +0200767
Andrew Victordf05a302006-10-23 14:50:09 +0200768 int_status = int_status & int_mask;
Andrew Victor65dbf342006-04-02 19:18:51 +0100769
Andrew Victordf05a302006-10-23 14:50:09 +0200770 if (int_status & AT91_MCI_ERRORS) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100771 completed = 1;
Nicolas Ferre37b758e82007-08-08 12:01:44 +0200772
Andrew Victordf05a302006-10-23 14:50:09 +0200773 if (int_status & AT91_MCI_UNRE)
774 pr_debug("MMC: Underrun error\n");
775 if (int_status & AT91_MCI_OVRE)
776 pr_debug("MMC: Overrun error\n");
777 if (int_status & AT91_MCI_DTOE)
778 pr_debug("MMC: Data timeout\n");
779 if (int_status & AT91_MCI_DCRCE)
780 pr_debug("MMC: CRC error in data\n");
781 if (int_status & AT91_MCI_RTOE)
782 pr_debug("MMC: Response timeout\n");
783 if (int_status & AT91_MCI_RENDE)
784 pr_debug("MMC: Response end bit error\n");
785 if (int_status & AT91_MCI_RCRCE)
786 pr_debug("MMC: Response CRC error\n");
787 if (int_status & AT91_MCI_RDIRE)
788 pr_debug("MMC: Response direction error\n");
789 if (int_status & AT91_MCI_RINDE)
790 pr_debug("MMC: Response index error\n");
791 } else {
792 /* Only continue processing if no errors */
Andrew Victor65dbf342006-04-02 19:18:51 +0100793
Andrew Victor65dbf342006-04-02 19:18:51 +0100794 if (int_status & AT91_MCI_TXBUFE) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100795 pr_debug("TX buffer empty\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100796 at91_mci_handle_transmitted(host);
797 }
798
Nicolas Ferreed99c542007-07-09 14:58:16 +0200799 if (int_status & AT91_MCI_ENDRX) {
800 pr_debug("ENDRX\n");
801 at91_mci_post_dma_read(host);
802 }
803
Andrew Victor65dbf342006-04-02 19:18:51 +0100804 if (int_status & AT91_MCI_RXBUFF) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100805 pr_debug("RX buffer full\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200806 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
807 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_RXBUFF | AT91_MCI_ENDRX);
808 completed = 1;
Andrew Victor65dbf342006-04-02 19:18:51 +0100809 }
810
Andrew Victordf05a302006-10-23 14:50:09 +0200811 if (int_status & AT91_MCI_ENDTX)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100812 pr_debug("Transmit has ended\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100813
Andrew Victor65dbf342006-04-02 19:18:51 +0100814 if (int_status & AT91_MCI_NOTBUSY) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100815 pr_debug("Card is ready\n");
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200816 at91_mci_update_bytes_xfered(host);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200817 completed = 1;
Andrew Victor65dbf342006-04-02 19:18:51 +0100818 }
819
Andrew Victordf05a302006-10-23 14:50:09 +0200820 if (int_status & AT91_MCI_DTIP)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100821 pr_debug("Data transfer in progress\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100822
Nicolas Ferreed99c542007-07-09 14:58:16 +0200823 if (int_status & AT91_MCI_BLKE) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100824 pr_debug("Block transfer has ended\n");
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200825 if (host->request->data && host->request->data->blocks > 1) {
826 /* multi block write : complete multi write
827 * command and send stop */
828 completed = 1;
829 } else {
830 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
831 }
Nicolas Ferreed99c542007-07-09 14:58:16 +0200832 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100833
Eric Benard7a6588b2008-05-30 14:26:05 +0200834 if (int_status & AT91_MCI_SDIOIRQA)
835 mmc_signal_sdio_irq(host->mmc);
836
837 if (int_status & AT91_MCI_SDIOIRQB)
838 mmc_signal_sdio_irq(host->mmc);
839
Andrew Victordf05a302006-10-23 14:50:09 +0200840 if (int_status & AT91_MCI_TXRDY)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100841 pr_debug("Ready to transmit\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100842
Andrew Victordf05a302006-10-23 14:50:09 +0200843 if (int_status & AT91_MCI_RXRDY)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100844 pr_debug("Ready to receive\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100845
846 if (int_status & AT91_MCI_CMDRDY) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100847 pr_debug("Command ready\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200848 completed = at91_mci_handle_cmdrdy(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100849 }
850 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100851
852 if (completed) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100853 pr_debug("Completed command\n");
Eric Benard7a6588b2008-05-30 14:26:05 +0200854 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200855 at91_mci_completed_command(host, int_status);
Andrew Victordf05a302006-10-23 14:50:09 +0200856 } else
Eric Benard7a6588b2008-05-30 14:26:05 +0200857 at91_mci_write(host, AT91_MCI_IDR, int_status & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Andrew Victor65dbf342006-04-02 19:18:51 +0100858
859 return IRQ_HANDLED;
860}
861
David Howells7d12e782006-10-05 14:55:46 +0100862static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100863{
864 struct at91mci_host *host = _host;
David Brownell6e996ee2008-02-04 18:12:48 +0100865 int present = !gpio_get_value(irq_to_gpio(irq));
Andrew Victor65dbf342006-04-02 19:18:51 +0100866
867 /*
868 * we expect this irq on both insert and remove,
869 * and use a short delay to debounce.
870 */
871 if (present != host->present) {
872 host->present = present;
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100873 pr_debug("%s: card %s\n", mmc_hostname(host->mmc),
Andrew Victor65dbf342006-04-02 19:18:51 +0100874 present ? "insert" : "remove");
875 if (!present) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100876 pr_debug("****** Resetting SD-card bus width ******\n");
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100877 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100878 }
Wolfgang Mueesa04ac5b2010-03-05 13:43:39 -0800879 /* 0.5s needed because of early card detect switch firing */
880 mmc_detect_change(host->mmc, msecs_to_jiffies(500));
Andrew Victor65dbf342006-04-02 19:18:51 +0100881 }
882 return IRQ_HANDLED;
883}
884
David Brownella26b4982006-12-26 14:45:26 -0800885static int at91_mci_get_ro(struct mmc_host *mmc)
Andrew Victor65dbf342006-04-02 19:18:51 +0100886{
Andrew Victor65dbf342006-04-02 19:18:51 +0100887 struct at91mci_host *host = mmc_priv(mmc);
888
Anton Vorontsov08f80bb2008-06-17 18:17:39 +0400889 if (host->board->wp_pin)
890 return !!gpio_get_value(host->board->wp_pin);
891 /*
892 * Board doesn't support read only detection; let the mmc core
893 * decide what to do.
894 */
895 return -ENOSYS;
Andrew Victor65dbf342006-04-02 19:18:51 +0100896}
897
Eric Benard7a6588b2008-05-30 14:26:05 +0200898static void at91_mci_enable_sdio_irq(struct mmc_host *mmc, int enable)
899{
900 struct at91mci_host *host = mmc_priv(mmc);
901
902 pr_debug("%s: sdio_irq %c : %s\n", mmc_hostname(host->mmc),
903 host->board->slot_b ? 'B':'A', enable ? "enable" : "disable");
904 at91_mci_write(host, enable ? AT91_MCI_IER : AT91_MCI_IDR,
905 host->board->slot_b ? AT91_MCI_SDIOIRQB : AT91_MCI_SDIOIRQA);
906
907}
908
David Brownellab7aefd2006-11-12 17:55:30 -0800909static const struct mmc_host_ops at91_mci_ops = {
Andrew Victor65dbf342006-04-02 19:18:51 +0100910 .request = at91_mci_request,
911 .set_ios = at91_mci_set_ios,
912 .get_ro = at91_mci_get_ro,
Eric Benard7a6588b2008-05-30 14:26:05 +0200913 .enable_sdio_irq = at91_mci_enable_sdio_irq,
Andrew Victor65dbf342006-04-02 19:18:51 +0100914};
915
916/*
917 * Probe for the device
918 */
David Brownella26b4982006-12-26 14:45:26 -0800919static int __init at91_mci_probe(struct platform_device *pdev)
Andrew Victor65dbf342006-04-02 19:18:51 +0100920{
921 struct mmc_host *mmc;
922 struct at91mci_host *host;
Andrew Victor17ea0592006-10-23 14:44:40 +0200923 struct resource *res;
Andrew Victor65dbf342006-04-02 19:18:51 +0100924 int ret;
925
Andrew Victor17ea0592006-10-23 14:44:40 +0200926 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
927 if (!res)
928 return -ENXIO;
929
930 if (!request_mem_region(res->start, res->end - res->start + 1, DRIVER_NAME))
931 return -EBUSY;
932
Andrew Victor65dbf342006-04-02 19:18:51 +0100933 mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
934 if (!mmc) {
David Brownell6e996ee2008-02-04 18:12:48 +0100935 ret = -ENOMEM;
936 dev_dbg(&pdev->dev, "couldn't allocate mmc host\n");
937 goto fail6;
Andrew Victor65dbf342006-04-02 19:18:51 +0100938 }
939
940 mmc->ops = &at91_mci_ops;
941 mmc->f_min = 375000;
942 mmc->f_max = 25000000;
943 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
Nicolas Ferre541e7ef2010-03-05 13:43:43 -0800944 mmc->caps = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100945
Wolfgang Muees3780d902010-03-05 13:43:40 -0800946 mmc->max_blk_size = MCI_MAXBLKSIZE;
947 mmc->max_blk_count = MCI_BLKATONCE;
948 mmc->max_req_size = MCI_BUFSIZE;
Wolfgang Muees9af13be2010-03-05 13:43:42 -0800949 mmc->max_phys_segs = MCI_BLKATONCE;
950 mmc->max_hw_segs = MCI_BLKATONCE;
951 mmc->max_seg_size = MCI_BUFSIZE;
Pierre Ossmanfe4a3c72006-11-21 17:54:23 +0100952
Andrew Victor65dbf342006-04-02 19:18:51 +0100953 host = mmc_priv(mmc);
954 host->mmc = mmc;
Andrew Victor65dbf342006-04-02 19:18:51 +0100955 host->bus_mode = 0;
956 host->board = pdev->dev.platform_data;
957 if (host->board->wire4) {
Nicolas Ferre5b27a1a2010-03-05 13:43:44 -0800958 if (at91mci_is_mci1rev2xx())
Nicolas Ferreed99c542007-07-09 14:58:16 +0200959 mmc->caps |= MMC_CAP_4_BIT_DATA;
960 else
David Brownell6e996ee2008-02-04 18:12:48 +0100961 dev_warn(&pdev->dev, "4 wire bus mode not supported"
Nicolas Ferreed99c542007-07-09 14:58:16 +0200962 " - using 1 wire\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100963 }
964
Wolfgang Muees3780d902010-03-05 13:43:40 -0800965 host->buffer = dma_alloc_coherent(&pdev->dev, MCI_BUFSIZE,
966 &host->physical_address, GFP_KERNEL);
967 if (!host->buffer) {
968 ret = -ENOMEM;
969 dev_err(&pdev->dev, "Can't allocate transmit buffer\n");
970 goto fail5;
971 }
972
Nicolas Ferre541e7ef2010-03-05 13:43:43 -0800973 /* Add SDIO capability when available */
Nicolas Ferre5b27a1a2010-03-05 13:43:44 -0800974 if (at91mci_is_mci1rev2xx()) {
975 /* at91mci MCI1 rev2xx sdio interrupt erratum */
Nicolas Ferre541e7ef2010-03-05 13:43:43 -0800976 if (host->board->wire4 || !host->board->slot_b)
977 mmc->caps |= MMC_CAP_SDIO_IRQ;
978 }
979
Andrew Victor65dbf342006-04-02 19:18:51 +0100980 /*
David Brownell6e996ee2008-02-04 18:12:48 +0100981 * Reserve GPIOs ... board init code makes sure these pins are set
982 * up as GPIOs with the right direction (input, except for vcc)
983 */
984 if (host->board->det_pin) {
985 ret = gpio_request(host->board->det_pin, "mmc_detect");
986 if (ret < 0) {
987 dev_dbg(&pdev->dev, "couldn't claim card detect pin\n");
Wolfgang Muees3780d902010-03-05 13:43:40 -0800988 goto fail4b;
David Brownell6e996ee2008-02-04 18:12:48 +0100989 }
990 }
991 if (host->board->wp_pin) {
992 ret = gpio_request(host->board->wp_pin, "mmc_wp");
993 if (ret < 0) {
994 dev_dbg(&pdev->dev, "couldn't claim wp sense pin\n");
995 goto fail4;
996 }
997 }
998 if (host->board->vcc_pin) {
999 ret = gpio_request(host->board->vcc_pin, "mmc_vcc");
1000 if (ret < 0) {
1001 dev_dbg(&pdev->dev, "couldn't claim vcc switch pin\n");
1002 goto fail3;
1003 }
1004 }
1005
1006 /*
Andrew Victor65dbf342006-04-02 19:18:51 +01001007 * Get Clock
1008 */
Andrew Victor3dd3b032006-10-23 14:46:54 +02001009 host->mci_clk = clk_get(&pdev->dev, "mci_clk");
1010 if (IS_ERR(host->mci_clk)) {
David Brownell6e996ee2008-02-04 18:12:48 +01001011 ret = -ENODEV;
1012 dev_dbg(&pdev->dev, "no mci_clk?\n");
1013 goto fail2;
Andrew Victor65dbf342006-04-02 19:18:51 +01001014 }
Andrew Victor65dbf342006-04-02 19:18:51 +01001015
Andrew Victor17ea0592006-10-23 14:44:40 +02001016 /*
1017 * Map I/O region
1018 */
1019 host->baseaddr = ioremap(res->start, res->end - res->start + 1);
1020 if (!host->baseaddr) {
David Brownell6e996ee2008-02-04 18:12:48 +01001021 ret = -ENOMEM;
1022 goto fail1;
Andrew Victor17ea0592006-10-23 14:44:40 +02001023 }
Andrew Victore0b19b82006-10-25 19:42:38 +02001024
1025 /*
1026 * Reset hardware
1027 */
Andrew Victor3dd3b032006-10-23 14:46:54 +02001028 clk_enable(host->mci_clk); /* Enable the peripheral clock */
Andrew Victore0b19b82006-10-25 19:42:38 +02001029 at91_mci_disable(host);
1030 at91_mci_enable(host);
1031
Andrew Victor65dbf342006-04-02 19:18:51 +01001032 /*
1033 * Allocate the MCI interrupt
1034 */
Andrew Victor17ea0592006-10-23 14:44:40 +02001035 host->irq = platform_get_irq(pdev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +01001036 ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED,
1037 mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001038 if (ret) {
David Brownell6e996ee2008-02-04 18:12:48 +01001039 dev_dbg(&pdev->dev, "request MCI interrupt failed\n");
1040 goto fail0;
Andrew Victor65dbf342006-04-02 19:18:51 +01001041 }
1042
Nicolas Ferre99ba0402008-11-27 17:23:49 +01001043 setup_timer(&host->timer, at91_timeout_timer, (unsigned long)host);
1044
Andrew Victor65dbf342006-04-02 19:18:51 +01001045 platform_set_drvdata(pdev, mmc);
1046
1047 /*
1048 * Add host to MMC layer
1049 */
Marc Pignat63b66432007-07-16 11:07:02 +02001050 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001051 host->present = !gpio_get_value(host->board->det_pin);
Marc Pignat63b66432007-07-16 11:07:02 +02001052 }
Andrew Victor65dbf342006-04-02 19:18:51 +01001053 else
1054 host->present = -1;
1055
1056 mmc_add_host(mmc);
1057
1058 /*
1059 * monitor card insertion/removal if we can
1060 */
1061 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001062 ret = request_irq(gpio_to_irq(host->board->det_pin),
1063 at91_mmc_det_irq, 0, mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001064 if (ret)
David Brownell6e996ee2008-02-04 18:12:48 +01001065 dev_warn(&pdev->dev, "request MMC detect irq failed\n");
1066 else
1067 device_init_wakeup(&pdev->dev, 1);
Andrew Victor65dbf342006-04-02 19:18:51 +01001068 }
1069
Andrew Victorf3a8efa2006-10-23 14:53:20 +02001070 pr_debug("Added MCI driver\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001071
1072 return 0;
David Brownell6e996ee2008-02-04 18:12:48 +01001073
1074fail0:
1075 clk_disable(host->mci_clk);
1076 iounmap(host->baseaddr);
1077fail1:
1078 clk_put(host->mci_clk);
1079fail2:
1080 if (host->board->vcc_pin)
1081 gpio_free(host->board->vcc_pin);
1082fail3:
1083 if (host->board->wp_pin)
1084 gpio_free(host->board->wp_pin);
1085fail4:
1086 if (host->board->det_pin)
1087 gpio_free(host->board->det_pin);
Wolfgang Muees3780d902010-03-05 13:43:40 -08001088fail4b:
1089 if (host->buffer)
1090 dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
1091 host->buffer, host->physical_address);
David Brownell6e996ee2008-02-04 18:12:48 +01001092fail5:
1093 mmc_free_host(mmc);
1094fail6:
1095 release_mem_region(res->start, res->end - res->start + 1);
1096 dev_err(&pdev->dev, "probe failed, err %d\n", ret);
1097 return ret;
Andrew Victor65dbf342006-04-02 19:18:51 +01001098}
1099
1100/*
1101 * Remove a device
1102 */
David Brownella26b4982006-12-26 14:45:26 -08001103static int __exit at91_mci_remove(struct platform_device *pdev)
Andrew Victor65dbf342006-04-02 19:18:51 +01001104{
1105 struct mmc_host *mmc = platform_get_drvdata(pdev);
1106 struct at91mci_host *host;
Andrew Victor17ea0592006-10-23 14:44:40 +02001107 struct resource *res;
Andrew Victor65dbf342006-04-02 19:18:51 +01001108
1109 if (!mmc)
1110 return -1;
1111
1112 host = mmc_priv(mmc);
1113
Wolfgang Muees3780d902010-03-05 13:43:40 -08001114 if (host->buffer)
1115 dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
1116 host->buffer, host->physical_address);
1117
Anti Sulline0cda542007-08-30 16:15:16 +02001118 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001119 if (device_can_wakeup(&pdev->dev))
1120 free_irq(gpio_to_irq(host->board->det_pin), host);
Marc Pignat63b66432007-07-16 11:07:02 +02001121 device_init_wakeup(&pdev->dev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +01001122 gpio_free(host->board->det_pin);
Andrew Victor65dbf342006-04-02 19:18:51 +01001123 }
1124
Andrew Victore0b19b82006-10-25 19:42:38 +02001125 at91_mci_disable(host);
Marc Pignate181dce2008-05-30 14:06:32 +02001126 del_timer_sync(&host->timer);
Andrew Victor17ea0592006-10-23 14:44:40 +02001127 mmc_remove_host(mmc);
1128 free_irq(host->irq, host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001129
Andrew Victor3dd3b032006-10-23 14:46:54 +02001130 clk_disable(host->mci_clk); /* Disable the peripheral clock */
1131 clk_put(host->mci_clk);
Andrew Victor65dbf342006-04-02 19:18:51 +01001132
David Brownell6e996ee2008-02-04 18:12:48 +01001133 if (host->board->vcc_pin)
1134 gpio_free(host->board->vcc_pin);
1135 if (host->board->wp_pin)
1136 gpio_free(host->board->wp_pin);
1137
Andrew Victor17ea0592006-10-23 14:44:40 +02001138 iounmap(host->baseaddr);
1139 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1140 release_mem_region(res->start, res->end - res->start + 1);
Andrew Victor65dbf342006-04-02 19:18:51 +01001141
Andrew Victor17ea0592006-10-23 14:44:40 +02001142 mmc_free_host(mmc);
1143 platform_set_drvdata(pdev, NULL);
Andrew Victorb44fb7a2006-06-19 13:06:05 +01001144 pr_debug("MCI Removed\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001145
1146 return 0;
1147}
1148
1149#ifdef CONFIG_PM
1150static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
1151{
1152 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001153 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001154 int ret = 0;
1155
Anti Sulline0cda542007-08-30 16:15:16 +02001156 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001157 enable_irq_wake(host->board->det_pin);
1158
Andrew Victor65dbf342006-04-02 19:18:51 +01001159 if (mmc)
1160 ret = mmc_suspend_host(mmc, state);
1161
1162 return ret;
1163}
1164
1165static int at91_mci_resume(struct platform_device *pdev)
1166{
1167 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001168 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001169 int ret = 0;
1170
Anti Sulline0cda542007-08-30 16:15:16 +02001171 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001172 disable_irq_wake(host->board->det_pin);
1173
Andrew Victor65dbf342006-04-02 19:18:51 +01001174 if (mmc)
1175 ret = mmc_resume_host(mmc);
1176
1177 return ret;
1178}
1179#else
1180#define at91_mci_suspend NULL
1181#define at91_mci_resume NULL
1182#endif
1183
1184static struct platform_driver at91_mci_driver = {
David Brownella26b4982006-12-26 14:45:26 -08001185 .remove = __exit_p(at91_mci_remove),
Andrew Victor65dbf342006-04-02 19:18:51 +01001186 .suspend = at91_mci_suspend,
1187 .resume = at91_mci_resume,
1188 .driver = {
1189 .name = DRIVER_NAME,
1190 .owner = THIS_MODULE,
1191 },
1192};
1193
1194static int __init at91_mci_init(void)
1195{
David Brownella26b4982006-12-26 14:45:26 -08001196 return platform_driver_probe(&at91_mci_driver, at91_mci_probe);
Andrew Victor65dbf342006-04-02 19:18:51 +01001197}
1198
1199static void __exit at91_mci_exit(void)
1200{
1201 platform_driver_unregister(&at91_mci_driver);
1202}
1203
1204module_init(at91_mci_init);
1205module_exit(at91_mci_exit);
1206
1207MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
1208MODULE_AUTHOR("Nick Randell");
1209MODULE_LICENSE("GPL");
Kay Sieversbc65c722008-04-15 14:34:28 -07001210MODULE_ALIAS("platform:at91_mci");