blob: 8327daebb396aeeaf2f4a395d9797694c1d14ebe [file] [log] [blame]
Andrew Victor65dbf342006-04-02 19:18:51 +01001/*
Pierre Ossman70f10482007-07-11 20:04:50 +02002 * linux/drivers/mmc/host/at91_mci.c - ATMEL AT91 MCI Driver
Andrew Victor65dbf342006-04-02 19:18:51 +01003 *
4 * Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved
5 *
6 * Copyright (C) 2006 Malcolm Noyes
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13/*
Andrew Victor99eeb8d2006-12-11 12:40:23 +010014 This is the AT91 MCI driver that has been tested with both MMC cards
Andrew Victor65dbf342006-04-02 19:18:51 +010015 and SD-cards. Boards that support write protect are now supported.
16 The CCAT91SBC001 board does not support SD cards.
17
18 The three entry points are at91_mci_request, at91_mci_set_ios
19 and at91_mci_get_ro.
20
21 SET IOS
22 This configures the device to put it into the correct mode and clock speed
23 required.
24
25 MCI REQUEST
26 MCI request processes the commands sent in the mmc_request structure. This
27 can consist of a processing command and a stop command in the case of
28 multiple block transfers.
29
30 There are three main types of request, commands, reads and writes.
31
32 Commands are straight forward. The command is submitted to the controller and
33 the request function returns. When the controller generates an interrupt to indicate
34 the command is finished, the response to the command are read and the mmc_request_done
35 function called to end the request.
36
37 Reads and writes work in a similar manner to normal commands but involve the PDC (DMA)
38 controller to manage the transfers.
39
40 A read is done from the controller directly to the scatterlist passed in from the request.
Andrew Victor99eeb8d2006-12-11 12:40:23 +010041 Due to a bug in the AT91RM9200 controller, when a read is completed, all the words are byte
42 swapped in the scatterlist buffers. AT91SAM926x are not affected by this bug.
Andrew Victor65dbf342006-04-02 19:18:51 +010043
44 The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY
45
46 A write is slightly different in that the bytes to write are read from the scatterlist
47 into a dma memory buffer (this is in case the source buffer should be read only). The
48 entire write buffer is then done from this single dma memory buffer.
49
50 The sequence of write interrupts is: ENDTX, TXBUFE, NOTBUSY, CMDRDY
51
52 GET RO
53 Gets the status of the write protect pin, if available.
54*/
55
Andrew Victor65dbf342006-04-02 19:18:51 +010056#include <linux/module.h>
57#include <linux/moduleparam.h>
58#include <linux/init.h>
59#include <linux/ioport.h>
60#include <linux/platform_device.h>
61#include <linux/interrupt.h>
62#include <linux/blkdev.h>
63#include <linux/delay.h>
64#include <linux/err.h>
65#include <linux/dma-mapping.h>
66#include <linux/clk.h>
Andrew Victor93a3ddc2007-02-08 11:31:22 +010067#include <linux/atmel_pdc.h>
Andrew Victor65dbf342006-04-02 19:18:51 +010068
69#include <linux/mmc/host.h>
Andrew Victor65dbf342006-04-02 19:18:51 +010070
71#include <asm/io.h>
72#include <asm/irq.h>
David Brownell6e996ee2008-02-04 18:12:48 +010073#include <asm/gpio.h>
74
Russell Kinga09e64f2008-08-05 16:14:15 +010075#include <mach/board.h>
76#include <mach/cpu.h>
77#include <mach/at91_mci.h>
Andrew Victor65dbf342006-04-02 19:18:51 +010078
79#define DRIVER_NAME "at91_mci"
80
Andrew Victordf05a302006-10-23 14:50:09 +020081#define FL_SENT_COMMAND (1 << 0)
82#define FL_SENT_STOP (1 << 1)
Andrew Victor65dbf342006-04-02 19:18:51 +010083
Andrew Victordf05a302006-10-23 14:50:09 +020084#define AT91_MCI_ERRORS (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE \
85 | AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE \
Nicolas Ferre37b758e82007-08-08 12:01:44 +020086 | AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)
Andrew Victor65dbf342006-04-02 19:18:51 +010087
Andrew Victore0b19b82006-10-25 19:42:38 +020088#define at91_mci_read(host, reg) __raw_readl((host)->baseaddr + (reg))
89#define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg))
Andrew Victor65dbf342006-04-02 19:18:51 +010090
Wolfgang Muees3780d902010-03-05 13:43:40 -080091#define MCI_BLKSIZE 512
92#define MCI_MAXBLKSIZE 4095
93#define MCI_BLKATONCE 256
94#define MCI_BUFSIZE (MCI_BLKSIZE * MCI_BLKATONCE)
Andrew Victor65dbf342006-04-02 19:18:51 +010095
96/*
97 * Low level type for this driver
98 */
99struct at91mci_host
100{
101 struct mmc_host *mmc;
102 struct mmc_command *cmd;
103 struct mmc_request *request;
104
Andrew Victore0b19b82006-10-25 19:42:38 +0200105 void __iomem *baseaddr;
Andrew Victor17ea0592006-10-23 14:44:40 +0200106 int irq;
Andrew Victore0b19b82006-10-25 19:42:38 +0200107
Andrew Victor65dbf342006-04-02 19:18:51 +0100108 struct at91_mmc_data *board;
109 int present;
110
Andrew Victor3dd3b032006-10-23 14:46:54 +0200111 struct clk *mci_clk;
112
Andrew Victor65dbf342006-04-02 19:18:51 +0100113 /*
114 * Flag indicating when the command has been sent. This is used to
115 * work out whether or not to send the stop
116 */
117 unsigned int flags;
118 /* flag for current bus settings */
119 u32 bus_mode;
120
121 /* DMA buffer used for transmitting */
122 unsigned int* buffer;
123 dma_addr_t physical_address;
124 unsigned int total_length;
125
126 /* Latest in the scatterlist that has been enabled for transfer, but not freed */
127 int in_use_index;
128
129 /* Latest in the scatterlist that has been enabled for transfer */
130 int transfer_index;
Marc Pignate181dce2008-05-30 14:06:32 +0200131
132 /* Timer for timeouts */
133 struct timer_list timer;
Andrew Victor65dbf342006-04-02 19:18:51 +0100134};
135
Marc Pignatc5a89c62008-05-30 14:07:47 +0200136/*
137 * Reset the controller and restore most of the state
138 */
139static void at91_reset_host(struct at91mci_host *host)
140{
141 unsigned long flags;
142 u32 mr;
143 u32 sdcr;
144 u32 dtor;
145 u32 imr;
146
147 local_irq_save(flags);
148 imr = at91_mci_read(host, AT91_MCI_IMR);
149
150 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
151
152 /* save current state */
153 mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
154 sdcr = at91_mci_read(host, AT91_MCI_SDCR);
155 dtor = at91_mci_read(host, AT91_MCI_DTOR);
156
157 /* reset the controller */
158 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
159
160 /* restore state */
161 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
162 at91_mci_write(host, AT91_MCI_MR, mr);
163 at91_mci_write(host, AT91_MCI_SDCR, sdcr);
164 at91_mci_write(host, AT91_MCI_DTOR, dtor);
165 at91_mci_write(host, AT91_MCI_IER, imr);
166
167 /* make sure sdio interrupts will fire */
168 at91_mci_read(host, AT91_MCI_SR);
169
170 local_irq_restore(flags);
171}
172
Marc Pignate181dce2008-05-30 14:06:32 +0200173static void at91_timeout_timer(unsigned long data)
174{
175 struct at91mci_host *host;
176
177 host = (struct at91mci_host *)data;
178
179 if (host->request) {
180 dev_err(host->mmc->parent, "Timeout waiting end of packet\n");
181
182 if (host->cmd && host->cmd->data) {
183 host->cmd->data->error = -ETIMEDOUT;
184 } else {
185 if (host->cmd)
186 host->cmd->error = -ETIMEDOUT;
187 else
188 host->request->cmd->error = -ETIMEDOUT;
189 }
190
Marc Pignatc5a89c62008-05-30 14:07:47 +0200191 at91_reset_host(host);
Marc Pignate181dce2008-05-30 14:06:32 +0200192 mmc_request_done(host->mmc, host->request);
193 }
194}
195
Andrew Victor65dbf342006-04-02 19:18:51 +0100196/*
197 * Copy from sg to a dma block - used for transfers
198 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200199static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
Andrew Victor65dbf342006-04-02 19:18:51 +0100200{
201 unsigned int len, i, size;
202 unsigned *dmabuf = host->buffer;
203
Ville Syrjala5385edc2008-06-14 20:27:20 +0300204 size = data->blksz * data->blocks;
Andrew Victor65dbf342006-04-02 19:18:51 +0100205 len = data->sg_len;
206
Ville Syrjala5385edc2008-06-14 20:27:20 +0300207 /* AT91SAM926[0/3] Data Write Operation and number of bytes erratum */
208 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
209 if (host->total_length == 12)
210 memset(dmabuf, 0, 12);
211
Andrew Victor65dbf342006-04-02 19:18:51 +0100212 /*
213 * Just loop through all entries. Size might not
214 * be the entire list though so make sure that
215 * we do not transfer too much.
216 */
217 for (i = 0; i < len; i++) {
218 struct scatterlist *sg;
219 int amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100220 unsigned int *sgbuffer;
221
222 sg = &data->sg[i];
223
Jens Axboe45711f12007-10-22 21:19:53 +0200224 sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
Andrew Victor65dbf342006-04-02 19:18:51 +0100225 amount = min(size, sg->length);
226 size -= amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100227
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100228 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
229 int index;
230
231 for (index = 0; index < (amount / 4); index++)
232 *dmabuf++ = swab32(sgbuffer[index]);
Ville Syrjala5385edc2008-06-14 20:27:20 +0300233 } else {
Wolfgang Muees0b3520f2010-03-05 13:43:38 -0800234 char *tmpv = (char *)dmabuf;
235 memcpy(tmpv, sgbuffer, amount);
236 tmpv += amount;
237 dmabuf = (unsigned *)tmpv;
Ville Syrjala5385edc2008-06-14 20:27:20 +0300238 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100239
Wolfgang Muees0b3520f2010-03-05 13:43:38 -0800240 kunmap_atomic(((void *)sgbuffer) - sg->offset, KM_BIO_SRC_IRQ);
Andrew Victor65dbf342006-04-02 19:18:51 +0100241
242 if (size == 0)
243 break;
244 }
245
246 /*
247 * Check that we didn't get a request to transfer
248 * more data than can fit into the SG list.
249 */
250 BUG_ON(size != 0);
251}
252
253/*
Andrew Victor65dbf342006-04-02 19:18:51 +0100254 * Handle after a dma read
255 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200256static void at91_mci_post_dma_read(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100257{
258 struct mmc_command *cmd;
259 struct mmc_data *data;
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800260 unsigned int len, i, size;
261 unsigned *dmabuf = host->buffer;
Andrew Victor65dbf342006-04-02 19:18:51 +0100262
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100263 pr_debug("post dma read\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100264
265 cmd = host->cmd;
266 if (!cmd) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100267 pr_debug("no command\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100268 return;
269 }
270
271 data = cmd->data;
272 if (!data) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100273 pr_debug("no data\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100274 return;
275 }
276
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800277 size = data->blksz * data->blocks;
278 len = data->sg_len;
279
280 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
281 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
282
283 for (i = 0; i < len; i++) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100284 struct scatterlist *sg;
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800285 int amount;
286 unsigned int *sgbuffer;
Andrew Victor65dbf342006-04-02 19:18:51 +0100287
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800288 sg = &data->sg[i];
Andrew Victor65dbf342006-04-02 19:18:51 +0100289
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800290 sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
291 amount = min(size, sg->length);
292 size -= amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100293
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100294 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
295 int index;
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800296 for (index = 0; index < (amount / 4); index++)
297 sgbuffer[index] = swab32(*dmabuf++);
298 } else {
299 char *tmpv = (char *)dmabuf;
300 memcpy(sgbuffer, tmpv, amount);
301 tmpv += amount;
302 dmabuf = (unsigned *)tmpv;
Andrew Victor65dbf342006-04-02 19:18:51 +0100303 }
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100304
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800305 kunmap_atomic(((void *)sgbuffer)-sg->offset, KM_BIO_SRC_IRQ);
306 dmac_flush_range((void *)sgbuffer, ((void *)sgbuffer) + amount);
307 data->bytes_xfered += amount;
308 if (size == 0)
309 break;
Andrew Victor65dbf342006-04-02 19:18:51 +0100310 }
311
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100312 pr_debug("post dma read done\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100313}
314
315/*
316 * Handle transmitted data
317 */
318static void at91_mci_handle_transmitted(struct at91mci_host *host)
319{
320 struct mmc_command *cmd;
321 struct mmc_data *data;
322
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100323 pr_debug("Handling the transmit\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100324
325 /* Disable the transfer */
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100326 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100327
328 /* Now wait for cmd ready */
Andrew Victore0b19b82006-10-25 19:42:38 +0200329 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
Andrew Victor65dbf342006-04-02 19:18:51 +0100330
331 cmd = host->cmd;
332 if (!cmd) return;
333
334 data = cmd->data;
335 if (!data) return;
336
Pierre Ossmanbe0192a2007-07-24 21:11:47 +0200337 if (cmd->data->blocks > 1) {
Nicolas Ferreed99c542007-07-09 14:58:16 +0200338 pr_debug("multiple write : wait for BLKE...\n");
339 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
340 } else
341 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
Andrew Victor65dbf342006-04-02 19:18:51 +0100342}
343
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200344/*
345 * Update bytes tranfered count during a write operation
346 */
347static void at91_mci_update_bytes_xfered(struct at91mci_host *host)
348{
349 struct mmc_data *data;
350
351 /* always deal with the effective request (and not the current cmd) */
352
353 if (host->request->cmd && host->request->cmd->error != 0)
354 return;
355
356 if (host->request->data) {
357 data = host->request->data;
358 if (data->flags & MMC_DATA_WRITE) {
359 /* card is in IDLE mode now */
360 pr_debug("-> bytes_xfered %d, total_length = %d\n",
361 data->bytes_xfered, host->total_length);
Ville Syrjala5385edc2008-06-14 20:27:20 +0300362 data->bytes_xfered = data->blksz * data->blocks;
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200363 }
364 }
365}
366
367
Nicolas Ferreed99c542007-07-09 14:58:16 +0200368/*Handle after command sent ready*/
369static int at91_mci_handle_cmdrdy(struct at91mci_host *host)
370{
371 if (!host->cmd)
372 return 1;
373 else if (!host->cmd->data) {
374 if (host->flags & FL_SENT_STOP) {
375 /*After multi block write, we must wait for NOTBUSY*/
376 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
377 } else return 1;
378 } else if (host->cmd->data->flags & MMC_DATA_WRITE) {
379 /*After sendding multi-block-write command, start DMA transfer*/
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200380 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE | AT91_MCI_BLKE);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200381 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
382 }
383
384 /* command not completed, have to wait */
385 return 0;
386}
387
388
Andrew Victor65dbf342006-04-02 19:18:51 +0100389/*
390 * Enable the controller
391 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200392static void at91_mci_enable(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100393{
Nicolas Ferreed99c542007-07-09 14:58:16 +0200394 unsigned int mr;
395
Andrew Victore0b19b82006-10-25 19:42:38 +0200396 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200397 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
Andrew Victore0b19b82006-10-25 19:42:38 +0200398 at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200399 mr = AT91_MCI_PDCMODE | 0x34a;
400
401 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
402 mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
403
404 at91_mci_write(host, AT91_MCI_MR, mr);
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100405
406 /* use Slot A or B (only one at same time) */
407 at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
Andrew Victor65dbf342006-04-02 19:18:51 +0100408}
409
410/*
411 * Disable the controller
412 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200413static void at91_mci_disable(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100414{
Andrew Victore0b19b82006-10-25 19:42:38 +0200415 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
Andrew Victor65dbf342006-04-02 19:18:51 +0100416}
417
418/*
419 * Send a command
Andrew Victor65dbf342006-04-02 19:18:51 +0100420 */
Nicolas Ferreed99c542007-07-09 14:58:16 +0200421static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
Andrew Victor65dbf342006-04-02 19:18:51 +0100422{
423 unsigned int cmdr, mr;
424 unsigned int block_length;
425 struct mmc_data *data = cmd->data;
426
427 unsigned int blocks;
428 unsigned int ier = 0;
429
430 host->cmd = cmd;
431
Nicolas Ferreed99c542007-07-09 14:58:16 +0200432 /* Needed for leaving busy state before CMD1 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200433 if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100434 pr_debug("Clearing timeout\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200435 at91_mci_write(host, AT91_MCI_ARGR, 0);
436 at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
437 while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100438 /* spin */
Andrew Victore0b19b82006-10-25 19:42:38 +0200439 pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
Andrew Victor65dbf342006-04-02 19:18:51 +0100440 }
441 }
Nicolas Ferreed99c542007-07-09 14:58:16 +0200442
Andrew Victor65dbf342006-04-02 19:18:51 +0100443 cmdr = cmd->opcode;
444
445 if (mmc_resp_type(cmd) == MMC_RSP_NONE)
446 cmdr |= AT91_MCI_RSPTYP_NONE;
447 else {
448 /* if a response is expected then allow maximum response latancy */
449 cmdr |= AT91_MCI_MAXLAT;
450 /* set 136 bit response for R2, 48 bit response otherwise */
451 if (mmc_resp_type(cmd) == MMC_RSP_R2)
452 cmdr |= AT91_MCI_RSPTYP_136;
453 else
454 cmdr |= AT91_MCI_RSPTYP_48;
455 }
456
457 if (data) {
Marc Pignat1d4de9e2007-08-09 13:56:29 +0200458
Ville Syrjala9da3cba2008-06-09 22:06:44 +0300459 if (cpu_is_at91rm9200() || cpu_is_at91sam9261()) {
460 if (data->blksz & 0x3) {
461 pr_debug("Unsupported block size\n");
462 cmd->error = -EINVAL;
463 mmc_request_done(host->mmc, host->request);
464 return;
465 }
466 if (data->flags & MMC_DATA_STREAM) {
467 pr_debug("Stream commands not supported\n");
468 cmd->error = -EINVAL;
469 mmc_request_done(host->mmc, host->request);
470 return;
471 }
Marc Pignat1d4de9e2007-08-09 13:56:29 +0200472 }
473
Russell Kinga3fd4a12006-06-04 17:51:15 +0100474 block_length = data->blksz;
Andrew Victor65dbf342006-04-02 19:18:51 +0100475 blocks = data->blocks;
476
477 /* always set data start - also set direction flag for read */
478 if (data->flags & MMC_DATA_READ)
479 cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
480 else if (data->flags & MMC_DATA_WRITE)
481 cmdr |= AT91_MCI_TRCMD_START;
482
483 if (data->flags & MMC_DATA_STREAM)
484 cmdr |= AT91_MCI_TRTYP_STREAM;
Pierre Ossmanbe0192a2007-07-24 21:11:47 +0200485 if (data->blocks > 1)
Andrew Victor65dbf342006-04-02 19:18:51 +0100486 cmdr |= AT91_MCI_TRTYP_MULTIPLE;
487 }
488 else {
489 block_length = 0;
490 blocks = 0;
491 }
492
Marc Pignatb6cedb32007-06-06 20:27:59 +0200493 if (host->flags & FL_SENT_STOP)
Andrew Victor65dbf342006-04-02 19:18:51 +0100494 cmdr |= AT91_MCI_TRCMD_STOP;
495
496 if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
497 cmdr |= AT91_MCI_OPDCMD;
498
499 /*
500 * Set the arguments and send the command
501 */
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200502 pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
Andrew Victore0b19b82006-10-25 19:42:38 +0200503 cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
Andrew Victor65dbf342006-04-02 19:18:51 +0100504
505 if (!data) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100506 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
507 at91_mci_write(host, ATMEL_PDC_RPR, 0);
508 at91_mci_write(host, ATMEL_PDC_RCR, 0);
509 at91_mci_write(host, ATMEL_PDC_RNPR, 0);
510 at91_mci_write(host, ATMEL_PDC_RNCR, 0);
511 at91_mci_write(host, ATMEL_PDC_TPR, 0);
512 at91_mci_write(host, ATMEL_PDC_TCR, 0);
513 at91_mci_write(host, ATMEL_PDC_TNPR, 0);
514 at91_mci_write(host, ATMEL_PDC_TNCR, 0);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200515 ier = AT91_MCI_CMDRDY;
516 } else {
517 /* zero block length and PDC mode */
Ville Syrjala12bd2572008-06-09 22:06:45 +0300518 mr = at91_mci_read(host, AT91_MCI_MR) & 0x5fff;
Marc Pignat80f92542008-05-30 14:05:24 +0200519 mr |= (data->blksz & 0x3) ? AT91_MCI_PDCFBYTE : 0;
520 mr |= (block_length << 16);
521 mr |= AT91_MCI_PDCMODE;
522 at91_mci_write(host, AT91_MCI_MR, mr);
Andrew Victor65dbf342006-04-02 19:18:51 +0100523
Ville Syrjala9da3cba2008-06-09 22:06:44 +0300524 if (!(cpu_is_at91rm9200() || cpu_is_at91sam9261()))
Marc Pignatc5a89c62008-05-30 14:07:47 +0200525 at91_mci_write(host, AT91_MCI_BLKR,
526 AT91_MCI_BLKR_BCNT(blocks) |
527 AT91_MCI_BLKR_BLKLEN(block_length));
528
Nicolas Ferreed99c542007-07-09 14:58:16 +0200529 /*
530 * Disable the PDC controller
531 */
532 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100533
Nicolas Ferreed99c542007-07-09 14:58:16 +0200534 if (cmdr & AT91_MCI_TRCMD_START) {
535 data->bytes_xfered = 0;
536 host->transfer_index = 0;
537 host->in_use_index = 0;
538 if (cmdr & AT91_MCI_TRDIR) {
539 /*
540 * Handle a read
541 */
Nicolas Ferreed99c542007-07-09 14:58:16 +0200542 host->total_length = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100543
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800544 at91_mci_write(host, ATMEL_PDC_RPR, host->physical_address);
545 at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ?
546 (blocks * block_length) : (blocks * block_length) / 4);
547 at91_mci_write(host, ATMEL_PDC_RNPR, 0);
548 at91_mci_write(host, ATMEL_PDC_RNCR, 0);
549
Nicolas Ferreed99c542007-07-09 14:58:16 +0200550 ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
551 }
552 else {
553 /*
554 * Handle a write
555 */
556 host->total_length = block_length * blocks;
Ville Syrjala5385edc2008-06-14 20:27:20 +0300557 /*
558 * AT91SAM926[0/3] Data Write Operation and
559 * number of bytes erratum
560 */
561 if (cpu_is_at91sam9260 () || cpu_is_at91sam9263())
562 if (host->total_length < 12)
563 host->total_length = 12;
David Brownelle385ea62008-09-02 14:35:46 -0700564
Nicolas Ferreed99c542007-07-09 14:58:16 +0200565 at91_mci_sg_to_dma(host, data);
Andrew Victor65dbf342006-04-02 19:18:51 +0100566
Nicolas Ferreed99c542007-07-09 14:58:16 +0200567 pr_debug("Transmitting %d bytes\n", host->total_length);
Andrew Victor65dbf342006-04-02 19:18:51 +0100568
Nicolas Ferreed99c542007-07-09 14:58:16 +0200569 at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200570 at91_mci_write(host, ATMEL_PDC_TCR, (data->blksz & 0x3) ?
571 host->total_length : host->total_length / 4);
572
Nicolas Ferreed99c542007-07-09 14:58:16 +0200573 ier = AT91_MCI_CMDRDY;
574 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100575 }
576 }
577
578 /*
579 * Send the command and then enable the PDC - not the other way round as
580 * the data sheet says
581 */
582
Andrew Victore0b19b82006-10-25 19:42:38 +0200583 at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
584 at91_mci_write(host, AT91_MCI_CMDR, cmdr);
Andrew Victor65dbf342006-04-02 19:18:51 +0100585
586 if (cmdr & AT91_MCI_TRCMD_START) {
587 if (cmdr & AT91_MCI_TRDIR)
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100588 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
Andrew Victor65dbf342006-04-02 19:18:51 +0100589 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100590
Nicolas Ferreed99c542007-07-09 14:58:16 +0200591 /* Enable selected interrupts */
Andrew Victordf05a302006-10-23 14:50:09 +0200592 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
Andrew Victor65dbf342006-04-02 19:18:51 +0100593}
594
595/*
596 * Process the next step in the request
597 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200598static void at91_mci_process_next(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100599{
600 if (!(host->flags & FL_SENT_COMMAND)) {
601 host->flags |= FL_SENT_COMMAND;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200602 at91_mci_send_command(host, host->request->cmd);
Andrew Victor65dbf342006-04-02 19:18:51 +0100603 }
604 else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
605 host->flags |= FL_SENT_STOP;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200606 at91_mci_send_command(host, host->request->stop);
Marc Pignate181dce2008-05-30 14:06:32 +0200607 } else {
608 del_timer(&host->timer);
Marc Pignatc5a89c62008-05-30 14:07:47 +0200609 /* the at91rm9200 mci controller hangs after some transfers,
610 * and the workaround is to reset it after each transfer.
611 */
612 if (cpu_is_at91rm9200())
613 at91_reset_host(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100614 mmc_request_done(host->mmc, host->request);
Marc Pignate181dce2008-05-30 14:06:32 +0200615 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100616}
617
618/*
619 * Handle a command that has been completed
620 */
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200621static void at91_mci_completed_command(struct at91mci_host *host, unsigned int status)
Andrew Victor65dbf342006-04-02 19:18:51 +0100622{
623 struct mmc_command *cmd = host->cmd;
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200624 struct mmc_data *data = cmd->data;
Andrew Victor65dbf342006-04-02 19:18:51 +0100625
Eric Benard7a6588b2008-05-30 14:26:05 +0200626 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Andrew Victor65dbf342006-04-02 19:18:51 +0100627
Andrew Victore0b19b82006-10-25 19:42:38 +0200628 cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
629 cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
630 cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
631 cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
Andrew Victor65dbf342006-04-02 19:18:51 +0100632
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200633 pr_debug("Status = %08X/%08x [%08X %08X %08X %08X]\n",
634 status, at91_mci_read(host, AT91_MCI_SR),
635 cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
Andrew Victor65dbf342006-04-02 19:18:51 +0100636
Andrew Victor9e3866b2007-10-17 11:53:40 +0200637 if (status & AT91_MCI_ERRORS) {
Marc Pignatb6cedb32007-06-06 20:27:59 +0200638 if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
Pierre Ossman17b04292007-07-22 22:18:46 +0200639 cmd->error = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100640 }
641 else {
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200642 if (status & (AT91_MCI_DTOE | AT91_MCI_DCRCE)) {
643 if (data) {
644 if (status & AT91_MCI_DTOE)
645 data->error = -ETIMEDOUT;
646 else if (status & AT91_MCI_DCRCE)
647 data->error = -EILSEQ;
648 }
649 } else {
650 if (status & AT91_MCI_RTOE)
651 cmd->error = -ETIMEDOUT;
652 else if (status & AT91_MCI_RCRCE)
653 cmd->error = -EILSEQ;
654 else
655 cmd->error = -EIO;
656 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100657
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200658 pr_debug("Error detected and set to %d/%d (cmd = %d, retries = %d)\n",
659 cmd->error, data ? data->error : 0,
660 cmd->opcode, cmd->retries);
Andrew Victor65dbf342006-04-02 19:18:51 +0100661 }
662 }
663 else
Pierre Ossman17b04292007-07-22 22:18:46 +0200664 cmd->error = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100665
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200666 at91_mci_process_next(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100667}
668
669/*
670 * Handle an MMC request
671 */
672static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
673{
674 struct at91mci_host *host = mmc_priv(mmc);
675 host->request = mrq;
676 host->flags = 0;
677
Wolfgang Mueesa04ac5b2010-03-05 13:43:39 -0800678 /* more than 1s timeout needed with slow SD cards */
679 mod_timer(&host->timer, jiffies + msecs_to_jiffies(2000));
Marc Pignate181dce2008-05-30 14:06:32 +0200680
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200681 at91_mci_process_next(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100682}
683
684/*
685 * Set the IOS
686 */
687static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
688{
689 int clkdiv;
690 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor3dd3b032006-10-23 14:46:54 +0200691 unsigned long at91_master_clock = clk_get_rate(host->mci_clk);
Andrew Victor65dbf342006-04-02 19:18:51 +0100692
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100693 host->bus_mode = ios->bus_mode;
Andrew Victor65dbf342006-04-02 19:18:51 +0100694
695 if (ios->clock == 0) {
696 /* Disable the MCI controller */
Andrew Victore0b19b82006-10-25 19:42:38 +0200697 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100698 clkdiv = 0;
699 }
700 else {
701 /* Enable the MCI controller */
Andrew Victore0b19b82006-10-25 19:42:38 +0200702 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
Andrew Victor65dbf342006-04-02 19:18:51 +0100703
704 if ((at91_master_clock % (ios->clock * 2)) == 0)
705 clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
706 else
707 clkdiv = (at91_master_clock / ios->clock) / 2;
708
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100709 pr_debug("clkdiv = %d. mcck = %ld\n", clkdiv,
Andrew Victor65dbf342006-04-02 19:18:51 +0100710 at91_master_clock / (2 * (clkdiv + 1)));
711 }
712 if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100713 pr_debug("MMC: Setting controller bus width to 4\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200714 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100715 }
716 else {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100717 pr_debug("MMC: Setting controller bus width to 1\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200718 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100719 }
720
721 /* Set the clock divider */
Andrew Victore0b19b82006-10-25 19:42:38 +0200722 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 +0100723
724 /* maybe switch power to the card */
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100725 if (host->board->vcc_pin) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100726 switch (ios->power_mode) {
727 case MMC_POWER_OFF:
David Brownell6e996ee2008-02-04 18:12:48 +0100728 gpio_set_value(host->board->vcc_pin, 0);
Andrew Victor65dbf342006-04-02 19:18:51 +0100729 break;
730 case MMC_POWER_UP:
David Brownell6e996ee2008-02-04 18:12:48 +0100731 gpio_set_value(host->board->vcc_pin, 1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100732 break;
Marc Pignate5c0ef92008-05-09 11:07:07 +0200733 case MMC_POWER_ON:
734 break;
735 default:
736 WARN_ON(1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100737 }
738 }
739}
740
741/*
742 * Handle an interrupt
743 */
David Howells7d12e782006-10-05 14:55:46 +0100744static irqreturn_t at91_mci_irq(int irq, void *devid)
Andrew Victor65dbf342006-04-02 19:18:51 +0100745{
746 struct at91mci_host *host = devid;
747 int completed = 0;
Andrew Victordf05a302006-10-23 14:50:09 +0200748 unsigned int int_status, int_mask;
Andrew Victor65dbf342006-04-02 19:18:51 +0100749
Andrew Victore0b19b82006-10-25 19:42:38 +0200750 int_status = at91_mci_read(host, AT91_MCI_SR);
Andrew Victordf05a302006-10-23 14:50:09 +0200751 int_mask = at91_mci_read(host, AT91_MCI_IMR);
Nicolas Ferre37b758e82007-08-08 12:01:44 +0200752
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200753 pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask,
Andrew Victordf05a302006-10-23 14:50:09 +0200754 int_status & int_mask);
Nicolas Ferre37b758e82007-08-08 12:01:44 +0200755
Andrew Victordf05a302006-10-23 14:50:09 +0200756 int_status = int_status & int_mask;
Andrew Victor65dbf342006-04-02 19:18:51 +0100757
Andrew Victordf05a302006-10-23 14:50:09 +0200758 if (int_status & AT91_MCI_ERRORS) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100759 completed = 1;
Nicolas Ferre37b758e82007-08-08 12:01:44 +0200760
Andrew Victordf05a302006-10-23 14:50:09 +0200761 if (int_status & AT91_MCI_UNRE)
762 pr_debug("MMC: Underrun error\n");
763 if (int_status & AT91_MCI_OVRE)
764 pr_debug("MMC: Overrun error\n");
765 if (int_status & AT91_MCI_DTOE)
766 pr_debug("MMC: Data timeout\n");
767 if (int_status & AT91_MCI_DCRCE)
768 pr_debug("MMC: CRC error in data\n");
769 if (int_status & AT91_MCI_RTOE)
770 pr_debug("MMC: Response timeout\n");
771 if (int_status & AT91_MCI_RENDE)
772 pr_debug("MMC: Response end bit error\n");
773 if (int_status & AT91_MCI_RCRCE)
774 pr_debug("MMC: Response CRC error\n");
775 if (int_status & AT91_MCI_RDIRE)
776 pr_debug("MMC: Response direction error\n");
777 if (int_status & AT91_MCI_RINDE)
778 pr_debug("MMC: Response index error\n");
779 } else {
780 /* Only continue processing if no errors */
Andrew Victor65dbf342006-04-02 19:18:51 +0100781
Andrew Victor65dbf342006-04-02 19:18:51 +0100782 if (int_status & AT91_MCI_TXBUFE) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100783 pr_debug("TX buffer empty\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100784 at91_mci_handle_transmitted(host);
785 }
786
Nicolas Ferreed99c542007-07-09 14:58:16 +0200787 if (int_status & AT91_MCI_ENDRX) {
788 pr_debug("ENDRX\n");
789 at91_mci_post_dma_read(host);
790 }
791
Andrew Victor65dbf342006-04-02 19:18:51 +0100792 if (int_status & AT91_MCI_RXBUFF) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100793 pr_debug("RX buffer full\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200794 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
795 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_RXBUFF | AT91_MCI_ENDRX);
796 completed = 1;
Andrew Victor65dbf342006-04-02 19:18:51 +0100797 }
798
Andrew Victordf05a302006-10-23 14:50:09 +0200799 if (int_status & AT91_MCI_ENDTX)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100800 pr_debug("Transmit has ended\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100801
Andrew Victor65dbf342006-04-02 19:18:51 +0100802 if (int_status & AT91_MCI_NOTBUSY) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100803 pr_debug("Card is ready\n");
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200804 at91_mci_update_bytes_xfered(host);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200805 completed = 1;
Andrew Victor65dbf342006-04-02 19:18:51 +0100806 }
807
Andrew Victordf05a302006-10-23 14:50:09 +0200808 if (int_status & AT91_MCI_DTIP)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100809 pr_debug("Data transfer in progress\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100810
Nicolas Ferreed99c542007-07-09 14:58:16 +0200811 if (int_status & AT91_MCI_BLKE) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100812 pr_debug("Block transfer has ended\n");
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200813 if (host->request->data && host->request->data->blocks > 1) {
814 /* multi block write : complete multi write
815 * command and send stop */
816 completed = 1;
817 } else {
818 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
819 }
Nicolas Ferreed99c542007-07-09 14:58:16 +0200820 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100821
Eric Benard7a6588b2008-05-30 14:26:05 +0200822 if (int_status & AT91_MCI_SDIOIRQA)
823 mmc_signal_sdio_irq(host->mmc);
824
825 if (int_status & AT91_MCI_SDIOIRQB)
826 mmc_signal_sdio_irq(host->mmc);
827
Andrew Victordf05a302006-10-23 14:50:09 +0200828 if (int_status & AT91_MCI_TXRDY)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100829 pr_debug("Ready to transmit\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100830
Andrew Victordf05a302006-10-23 14:50:09 +0200831 if (int_status & AT91_MCI_RXRDY)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100832 pr_debug("Ready to receive\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100833
834 if (int_status & AT91_MCI_CMDRDY) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100835 pr_debug("Command ready\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200836 completed = at91_mci_handle_cmdrdy(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100837 }
838 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100839
840 if (completed) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100841 pr_debug("Completed command\n");
Eric Benard7a6588b2008-05-30 14:26:05 +0200842 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200843 at91_mci_completed_command(host, int_status);
Andrew Victordf05a302006-10-23 14:50:09 +0200844 } else
Eric Benard7a6588b2008-05-30 14:26:05 +0200845 at91_mci_write(host, AT91_MCI_IDR, int_status & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Andrew Victor65dbf342006-04-02 19:18:51 +0100846
847 return IRQ_HANDLED;
848}
849
David Howells7d12e782006-10-05 14:55:46 +0100850static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100851{
852 struct at91mci_host *host = _host;
David Brownell6e996ee2008-02-04 18:12:48 +0100853 int present = !gpio_get_value(irq_to_gpio(irq));
Andrew Victor65dbf342006-04-02 19:18:51 +0100854
855 /*
856 * we expect this irq on both insert and remove,
857 * and use a short delay to debounce.
858 */
859 if (present != host->present) {
860 host->present = present;
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100861 pr_debug("%s: card %s\n", mmc_hostname(host->mmc),
Andrew Victor65dbf342006-04-02 19:18:51 +0100862 present ? "insert" : "remove");
863 if (!present) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100864 pr_debug("****** Resetting SD-card bus width ******\n");
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100865 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100866 }
Wolfgang Mueesa04ac5b2010-03-05 13:43:39 -0800867 /* 0.5s needed because of early card detect switch firing */
868 mmc_detect_change(host->mmc, msecs_to_jiffies(500));
Andrew Victor65dbf342006-04-02 19:18:51 +0100869 }
870 return IRQ_HANDLED;
871}
872
David Brownella26b4982006-12-26 14:45:26 -0800873static int at91_mci_get_ro(struct mmc_host *mmc)
Andrew Victor65dbf342006-04-02 19:18:51 +0100874{
Andrew Victor65dbf342006-04-02 19:18:51 +0100875 struct at91mci_host *host = mmc_priv(mmc);
876
Anton Vorontsov08f80bb2008-06-17 18:17:39 +0400877 if (host->board->wp_pin)
878 return !!gpio_get_value(host->board->wp_pin);
879 /*
880 * Board doesn't support read only detection; let the mmc core
881 * decide what to do.
882 */
883 return -ENOSYS;
Andrew Victor65dbf342006-04-02 19:18:51 +0100884}
885
Eric Benard7a6588b2008-05-30 14:26:05 +0200886static void at91_mci_enable_sdio_irq(struct mmc_host *mmc, int enable)
887{
888 struct at91mci_host *host = mmc_priv(mmc);
889
890 pr_debug("%s: sdio_irq %c : %s\n", mmc_hostname(host->mmc),
891 host->board->slot_b ? 'B':'A', enable ? "enable" : "disable");
892 at91_mci_write(host, enable ? AT91_MCI_IER : AT91_MCI_IDR,
893 host->board->slot_b ? AT91_MCI_SDIOIRQB : AT91_MCI_SDIOIRQA);
894
895}
896
David Brownellab7aefd2006-11-12 17:55:30 -0800897static const struct mmc_host_ops at91_mci_ops = {
Andrew Victor65dbf342006-04-02 19:18:51 +0100898 .request = at91_mci_request,
899 .set_ios = at91_mci_set_ios,
900 .get_ro = at91_mci_get_ro,
Eric Benard7a6588b2008-05-30 14:26:05 +0200901 .enable_sdio_irq = at91_mci_enable_sdio_irq,
Andrew Victor65dbf342006-04-02 19:18:51 +0100902};
903
904/*
905 * Probe for the device
906 */
David Brownella26b4982006-12-26 14:45:26 -0800907static int __init at91_mci_probe(struct platform_device *pdev)
Andrew Victor65dbf342006-04-02 19:18:51 +0100908{
909 struct mmc_host *mmc;
910 struct at91mci_host *host;
Andrew Victor17ea0592006-10-23 14:44:40 +0200911 struct resource *res;
Andrew Victor65dbf342006-04-02 19:18:51 +0100912 int ret;
913
Andrew Victor17ea0592006-10-23 14:44:40 +0200914 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
915 if (!res)
916 return -ENXIO;
917
918 if (!request_mem_region(res->start, res->end - res->start + 1, DRIVER_NAME))
919 return -EBUSY;
920
Andrew Victor65dbf342006-04-02 19:18:51 +0100921 mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
922 if (!mmc) {
David Brownell6e996ee2008-02-04 18:12:48 +0100923 ret = -ENOMEM;
924 dev_dbg(&pdev->dev, "couldn't allocate mmc host\n");
925 goto fail6;
Andrew Victor65dbf342006-04-02 19:18:51 +0100926 }
927
928 mmc->ops = &at91_mci_ops;
929 mmc->f_min = 375000;
930 mmc->f_max = 25000000;
931 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
Nicolas Ferre541e7ef2010-03-05 13:43:43 -0800932 mmc->caps = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100933
Wolfgang Muees3780d902010-03-05 13:43:40 -0800934 mmc->max_blk_size = MCI_MAXBLKSIZE;
935 mmc->max_blk_count = MCI_BLKATONCE;
936 mmc->max_req_size = MCI_BUFSIZE;
Wolfgang Muees9af13be2010-03-05 13:43:42 -0800937 mmc->max_phys_segs = MCI_BLKATONCE;
938 mmc->max_hw_segs = MCI_BLKATONCE;
939 mmc->max_seg_size = MCI_BUFSIZE;
Pierre Ossmanfe4a3c72006-11-21 17:54:23 +0100940
Andrew Victor65dbf342006-04-02 19:18:51 +0100941 host = mmc_priv(mmc);
942 host->mmc = mmc;
Andrew Victor65dbf342006-04-02 19:18:51 +0100943 host->bus_mode = 0;
944 host->board = pdev->dev.platform_data;
945 if (host->board->wire4) {
Nicolas Ferreed99c542007-07-09 14:58:16 +0200946 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
947 mmc->caps |= MMC_CAP_4_BIT_DATA;
948 else
David Brownell6e996ee2008-02-04 18:12:48 +0100949 dev_warn(&pdev->dev, "4 wire bus mode not supported"
Nicolas Ferreed99c542007-07-09 14:58:16 +0200950 " - using 1 wire\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100951 }
952
Wolfgang Muees3780d902010-03-05 13:43:40 -0800953 host->buffer = dma_alloc_coherent(&pdev->dev, MCI_BUFSIZE,
954 &host->physical_address, GFP_KERNEL);
955 if (!host->buffer) {
956 ret = -ENOMEM;
957 dev_err(&pdev->dev, "Can't allocate transmit buffer\n");
958 goto fail5;
959 }
960
Nicolas Ferre541e7ef2010-03-05 13:43:43 -0800961 /* Add SDIO capability when available */
962 if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
963 /* AT91SAM9260/9263 erratum */
964 if (host->board->wire4 || !host->board->slot_b)
965 mmc->caps |= MMC_CAP_SDIO_IRQ;
966 }
967
Andrew Victor65dbf342006-04-02 19:18:51 +0100968 /*
David Brownell6e996ee2008-02-04 18:12:48 +0100969 * Reserve GPIOs ... board init code makes sure these pins are set
970 * up as GPIOs with the right direction (input, except for vcc)
971 */
972 if (host->board->det_pin) {
973 ret = gpio_request(host->board->det_pin, "mmc_detect");
974 if (ret < 0) {
975 dev_dbg(&pdev->dev, "couldn't claim card detect pin\n");
Wolfgang Muees3780d902010-03-05 13:43:40 -0800976 goto fail4b;
David Brownell6e996ee2008-02-04 18:12:48 +0100977 }
978 }
979 if (host->board->wp_pin) {
980 ret = gpio_request(host->board->wp_pin, "mmc_wp");
981 if (ret < 0) {
982 dev_dbg(&pdev->dev, "couldn't claim wp sense pin\n");
983 goto fail4;
984 }
985 }
986 if (host->board->vcc_pin) {
987 ret = gpio_request(host->board->vcc_pin, "mmc_vcc");
988 if (ret < 0) {
989 dev_dbg(&pdev->dev, "couldn't claim vcc switch pin\n");
990 goto fail3;
991 }
992 }
993
994 /*
Andrew Victor65dbf342006-04-02 19:18:51 +0100995 * Get Clock
996 */
Andrew Victor3dd3b032006-10-23 14:46:54 +0200997 host->mci_clk = clk_get(&pdev->dev, "mci_clk");
998 if (IS_ERR(host->mci_clk)) {
David Brownell6e996ee2008-02-04 18:12:48 +0100999 ret = -ENODEV;
1000 dev_dbg(&pdev->dev, "no mci_clk?\n");
1001 goto fail2;
Andrew Victor65dbf342006-04-02 19:18:51 +01001002 }
Andrew Victor65dbf342006-04-02 19:18:51 +01001003
Andrew Victor17ea0592006-10-23 14:44:40 +02001004 /*
1005 * Map I/O region
1006 */
1007 host->baseaddr = ioremap(res->start, res->end - res->start + 1);
1008 if (!host->baseaddr) {
David Brownell6e996ee2008-02-04 18:12:48 +01001009 ret = -ENOMEM;
1010 goto fail1;
Andrew Victor17ea0592006-10-23 14:44:40 +02001011 }
Andrew Victore0b19b82006-10-25 19:42:38 +02001012
1013 /*
1014 * Reset hardware
1015 */
Andrew Victor3dd3b032006-10-23 14:46:54 +02001016 clk_enable(host->mci_clk); /* Enable the peripheral clock */
Andrew Victore0b19b82006-10-25 19:42:38 +02001017 at91_mci_disable(host);
1018 at91_mci_enable(host);
1019
Andrew Victor65dbf342006-04-02 19:18:51 +01001020 /*
1021 * Allocate the MCI interrupt
1022 */
Andrew Victor17ea0592006-10-23 14:44:40 +02001023 host->irq = platform_get_irq(pdev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +01001024 ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED,
1025 mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001026 if (ret) {
David Brownell6e996ee2008-02-04 18:12:48 +01001027 dev_dbg(&pdev->dev, "request MCI interrupt failed\n");
1028 goto fail0;
Andrew Victor65dbf342006-04-02 19:18:51 +01001029 }
1030
Nicolas Ferre99ba0402008-11-27 17:23:49 +01001031 setup_timer(&host->timer, at91_timeout_timer, (unsigned long)host);
1032
Andrew Victor65dbf342006-04-02 19:18:51 +01001033 platform_set_drvdata(pdev, mmc);
1034
1035 /*
1036 * Add host to MMC layer
1037 */
Marc Pignat63b66432007-07-16 11:07:02 +02001038 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001039 host->present = !gpio_get_value(host->board->det_pin);
Marc Pignat63b66432007-07-16 11:07:02 +02001040 }
Andrew Victor65dbf342006-04-02 19:18:51 +01001041 else
1042 host->present = -1;
1043
1044 mmc_add_host(mmc);
1045
1046 /*
1047 * monitor card insertion/removal if we can
1048 */
1049 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001050 ret = request_irq(gpio_to_irq(host->board->det_pin),
1051 at91_mmc_det_irq, 0, mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001052 if (ret)
David Brownell6e996ee2008-02-04 18:12:48 +01001053 dev_warn(&pdev->dev, "request MMC detect irq failed\n");
1054 else
1055 device_init_wakeup(&pdev->dev, 1);
Andrew Victor65dbf342006-04-02 19:18:51 +01001056 }
1057
Andrew Victorf3a8efa2006-10-23 14:53:20 +02001058 pr_debug("Added MCI driver\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001059
1060 return 0;
David Brownell6e996ee2008-02-04 18:12:48 +01001061
1062fail0:
1063 clk_disable(host->mci_clk);
1064 iounmap(host->baseaddr);
1065fail1:
1066 clk_put(host->mci_clk);
1067fail2:
1068 if (host->board->vcc_pin)
1069 gpio_free(host->board->vcc_pin);
1070fail3:
1071 if (host->board->wp_pin)
1072 gpio_free(host->board->wp_pin);
1073fail4:
1074 if (host->board->det_pin)
1075 gpio_free(host->board->det_pin);
Wolfgang Muees3780d902010-03-05 13:43:40 -08001076fail4b:
1077 if (host->buffer)
1078 dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
1079 host->buffer, host->physical_address);
David Brownell6e996ee2008-02-04 18:12:48 +01001080fail5:
1081 mmc_free_host(mmc);
1082fail6:
1083 release_mem_region(res->start, res->end - res->start + 1);
1084 dev_err(&pdev->dev, "probe failed, err %d\n", ret);
1085 return ret;
Andrew Victor65dbf342006-04-02 19:18:51 +01001086}
1087
1088/*
1089 * Remove a device
1090 */
David Brownella26b4982006-12-26 14:45:26 -08001091static int __exit at91_mci_remove(struct platform_device *pdev)
Andrew Victor65dbf342006-04-02 19:18:51 +01001092{
1093 struct mmc_host *mmc = platform_get_drvdata(pdev);
1094 struct at91mci_host *host;
Andrew Victor17ea0592006-10-23 14:44:40 +02001095 struct resource *res;
Andrew Victor65dbf342006-04-02 19:18:51 +01001096
1097 if (!mmc)
1098 return -1;
1099
1100 host = mmc_priv(mmc);
1101
Wolfgang Muees3780d902010-03-05 13:43:40 -08001102 if (host->buffer)
1103 dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
1104 host->buffer, host->physical_address);
1105
Anti Sulline0cda542007-08-30 16:15:16 +02001106 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001107 if (device_can_wakeup(&pdev->dev))
1108 free_irq(gpio_to_irq(host->board->det_pin), host);
Marc Pignat63b66432007-07-16 11:07:02 +02001109 device_init_wakeup(&pdev->dev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +01001110 gpio_free(host->board->det_pin);
Andrew Victor65dbf342006-04-02 19:18:51 +01001111 }
1112
Andrew Victore0b19b82006-10-25 19:42:38 +02001113 at91_mci_disable(host);
Marc Pignate181dce2008-05-30 14:06:32 +02001114 del_timer_sync(&host->timer);
Andrew Victor17ea0592006-10-23 14:44:40 +02001115 mmc_remove_host(mmc);
1116 free_irq(host->irq, host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001117
Andrew Victor3dd3b032006-10-23 14:46:54 +02001118 clk_disable(host->mci_clk); /* Disable the peripheral clock */
1119 clk_put(host->mci_clk);
Andrew Victor65dbf342006-04-02 19:18:51 +01001120
David Brownell6e996ee2008-02-04 18:12:48 +01001121 if (host->board->vcc_pin)
1122 gpio_free(host->board->vcc_pin);
1123 if (host->board->wp_pin)
1124 gpio_free(host->board->wp_pin);
1125
Andrew Victor17ea0592006-10-23 14:44:40 +02001126 iounmap(host->baseaddr);
1127 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1128 release_mem_region(res->start, res->end - res->start + 1);
Andrew Victor65dbf342006-04-02 19:18:51 +01001129
Andrew Victor17ea0592006-10-23 14:44:40 +02001130 mmc_free_host(mmc);
1131 platform_set_drvdata(pdev, NULL);
Andrew Victorb44fb7a2006-06-19 13:06:05 +01001132 pr_debug("MCI Removed\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001133
1134 return 0;
1135}
1136
1137#ifdef CONFIG_PM
1138static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
1139{
1140 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001141 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001142 int ret = 0;
1143
Anti Sulline0cda542007-08-30 16:15:16 +02001144 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001145 enable_irq_wake(host->board->det_pin);
1146
Andrew Victor65dbf342006-04-02 19:18:51 +01001147 if (mmc)
1148 ret = mmc_suspend_host(mmc, state);
1149
1150 return ret;
1151}
1152
1153static int at91_mci_resume(struct platform_device *pdev)
1154{
1155 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001156 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001157 int ret = 0;
1158
Anti Sulline0cda542007-08-30 16:15:16 +02001159 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001160 disable_irq_wake(host->board->det_pin);
1161
Andrew Victor65dbf342006-04-02 19:18:51 +01001162 if (mmc)
1163 ret = mmc_resume_host(mmc);
1164
1165 return ret;
1166}
1167#else
1168#define at91_mci_suspend NULL
1169#define at91_mci_resume NULL
1170#endif
1171
1172static struct platform_driver at91_mci_driver = {
David Brownella26b4982006-12-26 14:45:26 -08001173 .remove = __exit_p(at91_mci_remove),
Andrew Victor65dbf342006-04-02 19:18:51 +01001174 .suspend = at91_mci_suspend,
1175 .resume = at91_mci_resume,
1176 .driver = {
1177 .name = DRIVER_NAME,
1178 .owner = THIS_MODULE,
1179 },
1180};
1181
1182static int __init at91_mci_init(void)
1183{
David Brownella26b4982006-12-26 14:45:26 -08001184 return platform_driver_probe(&at91_mci_driver, at91_mci_probe);
Andrew Victor65dbf342006-04-02 19:18:51 +01001185}
1186
1187static void __exit at91_mci_exit(void)
1188{
1189 platform_driver_unregister(&at91_mci_driver);
1190}
1191
1192module_init(at91_mci_init);
1193module_exit(at91_mci_exit);
1194
1195MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
1196MODULE_AUTHOR("Nick Randell");
1197MODULE_LICENSE("GPL");
Kay Sieversbc65c722008-04-15 14:34:28 -07001198MODULE_ALIAS("platform:at91_mci");