blob: 339e5913e5ccf0b8f0422f6f494cf5808d98b6fb [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>
Marc Kleine-Budde23ef3092010-09-09 16:37:48 -070069#include <linux/highmem.h>
Andrew Victor65dbf342006-04-02 19:18:51 +010070
71#include <linux/mmc/host.h>
Andrew Victor65dbf342006-04-02 19:18:51 +010072
73#include <asm/io.h>
74#include <asm/irq.h>
David Brownell6e996ee2008-02-04 18:12:48 +010075#include <asm/gpio.h>
76
Russell Kinga09e64f2008-08-05 16:14:15 +010077#include <mach/board.h>
78#include <mach/cpu.h>
79#include <mach/at91_mci.h>
Andrew Victor65dbf342006-04-02 19:18:51 +010080
81#define DRIVER_NAME "at91_mci"
82
Nicolas Ferre5b27a1a2010-03-05 13:43:44 -080083static inline int at91mci_is_mci1rev2xx(void)
84{
85 return ( cpu_is_at91sam9260()
86 || cpu_is_at91sam9263()
87 || cpu_is_at91cap9()
88 || cpu_is_at91sam9rl()
89 || cpu_is_at91sam9g10()
90 || cpu_is_at91sam9g20()
91 );
92}
93
Andrew Victordf05a302006-10-23 14:50:09 +020094#define FL_SENT_COMMAND (1 << 0)
95#define FL_SENT_STOP (1 << 1)
Andrew Victor65dbf342006-04-02 19:18:51 +010096
Andrew Victordf05a302006-10-23 14:50:09 +020097#define AT91_MCI_ERRORS (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE \
98 | AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE \
Nicolas Ferre37b758e2007-08-08 12:01:44 +020099 | AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)
Andrew Victor65dbf342006-04-02 19:18:51 +0100100
Andrew Victore0b19b82006-10-25 19:42:38 +0200101#define at91_mci_read(host, reg) __raw_readl((host)->baseaddr + (reg))
102#define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg))
Andrew Victor65dbf342006-04-02 19:18:51 +0100103
Wolfgang Muees3780d902010-03-05 13:43:40 -0800104#define MCI_BLKSIZE 512
105#define MCI_MAXBLKSIZE 4095
106#define MCI_BLKATONCE 256
107#define MCI_BUFSIZE (MCI_BLKSIZE * MCI_BLKATONCE)
Andrew Victor65dbf342006-04-02 19:18:51 +0100108
109/*
110 * Low level type for this driver
111 */
112struct at91mci_host
113{
114 struct mmc_host *mmc;
115 struct mmc_command *cmd;
116 struct mmc_request *request;
117
Andrew Victore0b19b82006-10-25 19:42:38 +0200118 void __iomem *baseaddr;
Andrew Victor17ea0592006-10-23 14:44:40 +0200119 int irq;
Andrew Victore0b19b82006-10-25 19:42:38 +0200120
Andrew Victor65dbf342006-04-02 19:18:51 +0100121 struct at91_mmc_data *board;
122 int present;
123
Andrew Victor3dd3b032006-10-23 14:46:54 +0200124 struct clk *mci_clk;
125
Andrew Victor65dbf342006-04-02 19:18:51 +0100126 /*
127 * Flag indicating when the command has been sent. This is used to
128 * work out whether or not to send the stop
129 */
130 unsigned int flags;
131 /* flag for current bus settings */
132 u32 bus_mode;
133
134 /* DMA buffer used for transmitting */
135 unsigned int* buffer;
136 dma_addr_t physical_address;
137 unsigned int total_length;
138
139 /* Latest in the scatterlist that has been enabled for transfer, but not freed */
140 int in_use_index;
141
142 /* Latest in the scatterlist that has been enabled for transfer */
143 int transfer_index;
Marc Pignate181dce2008-05-30 14:06:32 +0200144
145 /* Timer for timeouts */
146 struct timer_list timer;
Andrew Victor65dbf342006-04-02 19:18:51 +0100147};
148
Marc Pignatc5a89c62008-05-30 14:07:47 +0200149/*
150 * Reset the controller and restore most of the state
151 */
152static void at91_reset_host(struct at91mci_host *host)
153{
154 unsigned long flags;
155 u32 mr;
156 u32 sdcr;
157 u32 dtor;
158 u32 imr;
159
160 local_irq_save(flags);
161 imr = at91_mci_read(host, AT91_MCI_IMR);
162
163 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
164
165 /* save current state */
166 mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
167 sdcr = at91_mci_read(host, AT91_MCI_SDCR);
168 dtor = at91_mci_read(host, AT91_MCI_DTOR);
169
170 /* reset the controller */
171 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
172
173 /* restore state */
174 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
175 at91_mci_write(host, AT91_MCI_MR, mr);
176 at91_mci_write(host, AT91_MCI_SDCR, sdcr);
177 at91_mci_write(host, AT91_MCI_DTOR, dtor);
178 at91_mci_write(host, AT91_MCI_IER, imr);
179
180 /* make sure sdio interrupts will fire */
181 at91_mci_read(host, AT91_MCI_SR);
182
183 local_irq_restore(flags);
184}
185
Marc Pignate181dce2008-05-30 14:06:32 +0200186static void at91_timeout_timer(unsigned long data)
187{
188 struct at91mci_host *host;
189
190 host = (struct at91mci_host *)data;
191
192 if (host->request) {
193 dev_err(host->mmc->parent, "Timeout waiting end of packet\n");
194
195 if (host->cmd && host->cmd->data) {
196 host->cmd->data->error = -ETIMEDOUT;
197 } else {
198 if (host->cmd)
199 host->cmd->error = -ETIMEDOUT;
200 else
201 host->request->cmd->error = -ETIMEDOUT;
202 }
203
Marc Pignatc5a89c62008-05-30 14:07:47 +0200204 at91_reset_host(host);
Marc Pignate181dce2008-05-30 14:06:32 +0200205 mmc_request_done(host->mmc, host->request);
206 }
207}
208
Andrew Victor65dbf342006-04-02 19:18:51 +0100209/*
210 * Copy from sg to a dma block - used for transfers
211 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200212static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
Andrew Victor65dbf342006-04-02 19:18:51 +0100213{
214 unsigned int len, i, size;
215 unsigned *dmabuf = host->buffer;
216
Ville Syrjala5385edc2008-06-14 20:27:20 +0300217 size = data->blksz * data->blocks;
Andrew Victor65dbf342006-04-02 19:18:51 +0100218 len = data->sg_len;
219
Nicolas Ferre5b27a1a2010-03-05 13:43:44 -0800220 /* MCI1 rev2xx Data Write Operation and number of bytes erratum */
221 if (at91mci_is_mci1rev2xx())
Ville Syrjala5385edc2008-06-14 20:27:20 +0300222 if (host->total_length == 12)
223 memset(dmabuf, 0, 12);
224
Andrew Victor65dbf342006-04-02 19:18:51 +0100225 /*
226 * Just loop through all entries. Size might not
227 * be the entire list though so make sure that
228 * we do not transfer too much.
229 */
230 for (i = 0; i < len; i++) {
231 struct scatterlist *sg;
232 int amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100233 unsigned int *sgbuffer;
234
235 sg = &data->sg[i];
236
Jens Axboe45711f12007-10-22 21:19:53 +0200237 sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
Andrew Victor65dbf342006-04-02 19:18:51 +0100238 amount = min(size, sg->length);
239 size -= amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100240
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100241 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
242 int index;
243
244 for (index = 0; index < (amount / 4); index++)
245 *dmabuf++ = swab32(sgbuffer[index]);
Ville Syrjala5385edc2008-06-14 20:27:20 +0300246 } else {
Wolfgang Muees0b3520f2010-03-05 13:43:38 -0800247 char *tmpv = (char *)dmabuf;
248 memcpy(tmpv, sgbuffer, amount);
249 tmpv += amount;
250 dmabuf = (unsigned *)tmpv;
Ville Syrjala5385edc2008-06-14 20:27:20 +0300251 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100252
Nicolas Ferre752993e2010-03-05 13:43:45 -0800253 kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
Andrew Victor65dbf342006-04-02 19:18:51 +0100254
255 if (size == 0)
256 break;
257 }
258
259 /*
260 * Check that we didn't get a request to transfer
261 * more data than can fit into the SG list.
262 */
263 BUG_ON(size != 0);
264}
265
266/*
Andrew Victor65dbf342006-04-02 19:18:51 +0100267 * Handle after a dma read
268 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200269static void at91_mci_post_dma_read(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100270{
271 struct mmc_command *cmd;
272 struct mmc_data *data;
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800273 unsigned int len, i, size;
274 unsigned *dmabuf = host->buffer;
Andrew Victor65dbf342006-04-02 19:18:51 +0100275
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100276 pr_debug("post dma read\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100277
278 cmd = host->cmd;
279 if (!cmd) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100280 pr_debug("no command\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100281 return;
282 }
283
284 data = cmd->data;
285 if (!data) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100286 pr_debug("no data\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100287 return;
288 }
289
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800290 size = data->blksz * data->blocks;
291 len = data->sg_len;
292
293 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
294 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
295
296 for (i = 0; i < len; i++) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100297 struct scatterlist *sg;
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800298 int amount;
299 unsigned int *sgbuffer;
Andrew Victor65dbf342006-04-02 19:18:51 +0100300
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800301 sg = &data->sg[i];
Andrew Victor65dbf342006-04-02 19:18:51 +0100302
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800303 sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
304 amount = min(size, sg->length);
305 size -= amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100306
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100307 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
308 int index;
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800309 for (index = 0; index < (amount / 4); index++)
310 sgbuffer[index] = swab32(*dmabuf++);
311 } else {
312 char *tmpv = (char *)dmabuf;
313 memcpy(sgbuffer, tmpv, amount);
314 tmpv += amount;
315 dmabuf = (unsigned *)tmpv;
Andrew Victor65dbf342006-04-02 19:18:51 +0100316 }
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100317
Nicolas Ferrebdef2fe2010-05-15 12:32:31 -0400318 flush_kernel_dcache_page(sg_page(sg));
Nicolas Ferre752993e2010-03-05 13:43:45 -0800319 kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800320 data->bytes_xfered += amount;
321 if (size == 0)
322 break;
Andrew Victor65dbf342006-04-02 19:18:51 +0100323 }
324
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100325 pr_debug("post dma read done\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100326}
327
328/*
329 * Handle transmitted data
330 */
331static void at91_mci_handle_transmitted(struct at91mci_host *host)
332{
333 struct mmc_command *cmd;
334 struct mmc_data *data;
335
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100336 pr_debug("Handling the transmit\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100337
338 /* Disable the transfer */
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100339 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100340
341 /* Now wait for cmd ready */
Andrew Victore0b19b82006-10-25 19:42:38 +0200342 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
Andrew Victor65dbf342006-04-02 19:18:51 +0100343
344 cmd = host->cmd;
345 if (!cmd) return;
346
347 data = cmd->data;
348 if (!data) return;
349
Pierre Ossmanbe0192a2007-07-24 21:11:47 +0200350 if (cmd->data->blocks > 1) {
Nicolas Ferreed99c542007-07-09 14:58:16 +0200351 pr_debug("multiple write : wait for BLKE...\n");
352 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
353 } else
354 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
Andrew Victor65dbf342006-04-02 19:18:51 +0100355}
356
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200357/*
358 * Update bytes tranfered count during a write operation
359 */
360static void at91_mci_update_bytes_xfered(struct at91mci_host *host)
361{
362 struct mmc_data *data;
363
364 /* always deal with the effective request (and not the current cmd) */
365
366 if (host->request->cmd && host->request->cmd->error != 0)
367 return;
368
369 if (host->request->data) {
370 data = host->request->data;
371 if (data->flags & MMC_DATA_WRITE) {
372 /* card is in IDLE mode now */
373 pr_debug("-> bytes_xfered %d, total_length = %d\n",
374 data->bytes_xfered, host->total_length);
Ville Syrjala5385edc2008-06-14 20:27:20 +0300375 data->bytes_xfered = data->blksz * data->blocks;
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200376 }
377 }
378}
379
380
Nicolas Ferreed99c542007-07-09 14:58:16 +0200381/*Handle after command sent ready*/
382static int at91_mci_handle_cmdrdy(struct at91mci_host *host)
383{
384 if (!host->cmd)
385 return 1;
386 else if (!host->cmd->data) {
387 if (host->flags & FL_SENT_STOP) {
388 /*After multi block write, we must wait for NOTBUSY*/
389 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
390 } else return 1;
391 } else if (host->cmd->data->flags & MMC_DATA_WRITE) {
392 /*After sendding multi-block-write command, start DMA transfer*/
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200393 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE | AT91_MCI_BLKE);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200394 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
395 }
396
397 /* command not completed, have to wait */
398 return 0;
399}
400
401
Andrew Victor65dbf342006-04-02 19:18:51 +0100402/*
403 * Enable the controller
404 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200405static void at91_mci_enable(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100406{
Nicolas Ferreed99c542007-07-09 14:58:16 +0200407 unsigned int mr;
408
Andrew Victore0b19b82006-10-25 19:42:38 +0200409 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200410 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
Andrew Victore0b19b82006-10-25 19:42:38 +0200411 at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200412 mr = AT91_MCI_PDCMODE | 0x34a;
413
Nicolas Ferre5b27a1a2010-03-05 13:43:44 -0800414 if (at91mci_is_mci1rev2xx())
Nicolas Ferreed99c542007-07-09 14:58:16 +0200415 mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
416
417 at91_mci_write(host, AT91_MCI_MR, mr);
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100418
419 /* use Slot A or B (only one at same time) */
420 at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
Andrew Victor65dbf342006-04-02 19:18:51 +0100421}
422
423/*
424 * Disable the controller
425 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200426static void at91_mci_disable(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100427{
Andrew Victore0b19b82006-10-25 19:42:38 +0200428 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
Andrew Victor65dbf342006-04-02 19:18:51 +0100429}
430
431/*
432 * Send a command
Andrew Victor65dbf342006-04-02 19:18:51 +0100433 */
Nicolas Ferreed99c542007-07-09 14:58:16 +0200434static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
Andrew Victor65dbf342006-04-02 19:18:51 +0100435{
436 unsigned int cmdr, mr;
437 unsigned int block_length;
438 struct mmc_data *data = cmd->data;
439
440 unsigned int blocks;
441 unsigned int ier = 0;
442
443 host->cmd = cmd;
444
Nicolas Ferreed99c542007-07-09 14:58:16 +0200445 /* Needed for leaving busy state before CMD1 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200446 if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100447 pr_debug("Clearing timeout\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200448 at91_mci_write(host, AT91_MCI_ARGR, 0);
449 at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
450 while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100451 /* spin */
Andrew Victore0b19b82006-10-25 19:42:38 +0200452 pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
Andrew Victor65dbf342006-04-02 19:18:51 +0100453 }
454 }
Nicolas Ferreed99c542007-07-09 14:58:16 +0200455
Andrew Victor65dbf342006-04-02 19:18:51 +0100456 cmdr = cmd->opcode;
457
458 if (mmc_resp_type(cmd) == MMC_RSP_NONE)
459 cmdr |= AT91_MCI_RSPTYP_NONE;
460 else {
461 /* if a response is expected then allow maximum response latancy */
462 cmdr |= AT91_MCI_MAXLAT;
463 /* set 136 bit response for R2, 48 bit response otherwise */
464 if (mmc_resp_type(cmd) == MMC_RSP_R2)
465 cmdr |= AT91_MCI_RSPTYP_136;
466 else
467 cmdr |= AT91_MCI_RSPTYP_48;
468 }
469
470 if (data) {
Marc Pignat1d4de9e2007-08-09 13:56:29 +0200471
Ville Syrjala9da3cba2008-06-09 22:06:44 +0300472 if (cpu_is_at91rm9200() || cpu_is_at91sam9261()) {
473 if (data->blksz & 0x3) {
474 pr_debug("Unsupported block size\n");
475 cmd->error = -EINVAL;
476 mmc_request_done(host->mmc, host->request);
477 return;
478 }
479 if (data->flags & MMC_DATA_STREAM) {
480 pr_debug("Stream commands not supported\n");
481 cmd->error = -EINVAL;
482 mmc_request_done(host->mmc, host->request);
483 return;
484 }
Marc Pignat1d4de9e2007-08-09 13:56:29 +0200485 }
486
Russell Kinga3fd4a12006-06-04 17:51:15 +0100487 block_length = data->blksz;
Andrew Victor65dbf342006-04-02 19:18:51 +0100488 blocks = data->blocks;
489
490 /* always set data start - also set direction flag for read */
491 if (data->flags & MMC_DATA_READ)
492 cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
493 else if (data->flags & MMC_DATA_WRITE)
494 cmdr |= AT91_MCI_TRCMD_START;
495
496 if (data->flags & MMC_DATA_STREAM)
497 cmdr |= AT91_MCI_TRTYP_STREAM;
Pierre Ossmanbe0192a2007-07-24 21:11:47 +0200498 if (data->blocks > 1)
Andrew Victor65dbf342006-04-02 19:18:51 +0100499 cmdr |= AT91_MCI_TRTYP_MULTIPLE;
500 }
501 else {
502 block_length = 0;
503 blocks = 0;
504 }
505
Marc Pignatb6cedb32007-06-06 20:27:59 +0200506 if (host->flags & FL_SENT_STOP)
Andrew Victor65dbf342006-04-02 19:18:51 +0100507 cmdr |= AT91_MCI_TRCMD_STOP;
508
509 if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
510 cmdr |= AT91_MCI_OPDCMD;
511
512 /*
513 * Set the arguments and send the command
514 */
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200515 pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
Andrew Victore0b19b82006-10-25 19:42:38 +0200516 cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
Andrew Victor65dbf342006-04-02 19:18:51 +0100517
518 if (!data) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100519 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
520 at91_mci_write(host, ATMEL_PDC_RPR, 0);
521 at91_mci_write(host, ATMEL_PDC_RCR, 0);
522 at91_mci_write(host, ATMEL_PDC_RNPR, 0);
523 at91_mci_write(host, ATMEL_PDC_RNCR, 0);
524 at91_mci_write(host, ATMEL_PDC_TPR, 0);
525 at91_mci_write(host, ATMEL_PDC_TCR, 0);
526 at91_mci_write(host, ATMEL_PDC_TNPR, 0);
527 at91_mci_write(host, ATMEL_PDC_TNCR, 0);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200528 ier = AT91_MCI_CMDRDY;
529 } else {
530 /* zero block length and PDC mode */
Ville Syrjala12bd2572008-06-09 22:06:45 +0300531 mr = at91_mci_read(host, AT91_MCI_MR) & 0x5fff;
Marc Pignat80f92542008-05-30 14:05:24 +0200532 mr |= (data->blksz & 0x3) ? AT91_MCI_PDCFBYTE : 0;
533 mr |= (block_length << 16);
534 mr |= AT91_MCI_PDCMODE;
535 at91_mci_write(host, AT91_MCI_MR, mr);
Andrew Victor65dbf342006-04-02 19:18:51 +0100536
Ville Syrjala9da3cba2008-06-09 22:06:44 +0300537 if (!(cpu_is_at91rm9200() || cpu_is_at91sam9261()))
Marc Pignatc5a89c62008-05-30 14:07:47 +0200538 at91_mci_write(host, AT91_MCI_BLKR,
539 AT91_MCI_BLKR_BCNT(blocks) |
540 AT91_MCI_BLKR_BLKLEN(block_length));
541
Nicolas Ferreed99c542007-07-09 14:58:16 +0200542 /*
543 * Disable the PDC controller
544 */
545 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100546
Nicolas Ferreed99c542007-07-09 14:58:16 +0200547 if (cmdr & AT91_MCI_TRCMD_START) {
548 data->bytes_xfered = 0;
549 host->transfer_index = 0;
550 host->in_use_index = 0;
551 if (cmdr & AT91_MCI_TRDIR) {
552 /*
553 * Handle a read
554 */
Nicolas Ferreed99c542007-07-09 14:58:16 +0200555 host->total_length = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100556
Wolfgang Muees86ee26f2010-03-05 13:43:41 -0800557 at91_mci_write(host, ATMEL_PDC_RPR, host->physical_address);
558 at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ?
559 (blocks * block_length) : (blocks * block_length) / 4);
560 at91_mci_write(host, ATMEL_PDC_RNPR, 0);
561 at91_mci_write(host, ATMEL_PDC_RNCR, 0);
562
Nicolas Ferreed99c542007-07-09 14:58:16 +0200563 ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
564 }
565 else {
566 /*
567 * Handle a write
568 */
569 host->total_length = block_length * blocks;
Ville Syrjala5385edc2008-06-14 20:27:20 +0300570 /*
Nicolas Ferre5b27a1a2010-03-05 13:43:44 -0800571 * MCI1 rev2xx Data Write Operation and
Ville Syrjala5385edc2008-06-14 20:27:20 +0300572 * number of bytes erratum
573 */
Nicolas Ferre5b27a1a2010-03-05 13:43:44 -0800574 if (at91mci_is_mci1rev2xx())
Ville Syrjala5385edc2008-06-14 20:27:20 +0300575 if (host->total_length < 12)
576 host->total_length = 12;
David Brownelle385ea62008-09-02 14:35:46 -0700577
Nicolas Ferreed99c542007-07-09 14:58:16 +0200578 at91_mci_sg_to_dma(host, data);
Andrew Victor65dbf342006-04-02 19:18:51 +0100579
Nicolas Ferreed99c542007-07-09 14:58:16 +0200580 pr_debug("Transmitting %d bytes\n", host->total_length);
Andrew Victor65dbf342006-04-02 19:18:51 +0100581
Nicolas Ferreed99c542007-07-09 14:58:16 +0200582 at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200583 at91_mci_write(host, ATMEL_PDC_TCR, (data->blksz & 0x3) ?
584 host->total_length : host->total_length / 4);
585
Nicolas Ferreed99c542007-07-09 14:58:16 +0200586 ier = AT91_MCI_CMDRDY;
587 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100588 }
589 }
590
591 /*
592 * Send the command and then enable the PDC - not the other way round as
593 * the data sheet says
594 */
595
Andrew Victore0b19b82006-10-25 19:42:38 +0200596 at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
597 at91_mci_write(host, AT91_MCI_CMDR, cmdr);
Andrew Victor65dbf342006-04-02 19:18:51 +0100598
599 if (cmdr & AT91_MCI_TRCMD_START) {
600 if (cmdr & AT91_MCI_TRDIR)
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100601 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
Andrew Victor65dbf342006-04-02 19:18:51 +0100602 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100603
Nicolas Ferreed99c542007-07-09 14:58:16 +0200604 /* Enable selected interrupts */
Andrew Victordf05a302006-10-23 14:50:09 +0200605 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
Andrew Victor65dbf342006-04-02 19:18:51 +0100606}
607
608/*
609 * Process the next step in the request
610 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200611static void at91_mci_process_next(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100612{
613 if (!(host->flags & FL_SENT_COMMAND)) {
614 host->flags |= FL_SENT_COMMAND;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200615 at91_mci_send_command(host, host->request->cmd);
Andrew Victor65dbf342006-04-02 19:18:51 +0100616 }
617 else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
618 host->flags |= FL_SENT_STOP;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200619 at91_mci_send_command(host, host->request->stop);
Marc Pignate181dce2008-05-30 14:06:32 +0200620 } else {
621 del_timer(&host->timer);
Marc Pignatc5a89c62008-05-30 14:07:47 +0200622 /* the at91rm9200 mci controller hangs after some transfers,
623 * and the workaround is to reset it after each transfer.
624 */
625 if (cpu_is_at91rm9200())
626 at91_reset_host(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100627 mmc_request_done(host->mmc, host->request);
Marc Pignate181dce2008-05-30 14:06:32 +0200628 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100629}
630
631/*
632 * Handle a command that has been completed
633 */
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200634static void at91_mci_completed_command(struct at91mci_host *host, unsigned int status)
Andrew Victor65dbf342006-04-02 19:18:51 +0100635{
636 struct mmc_command *cmd = host->cmd;
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200637 struct mmc_data *data = cmd->data;
Andrew Victor65dbf342006-04-02 19:18:51 +0100638
Eric Benard7a6588b2008-05-30 14:26:05 +0200639 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Andrew Victor65dbf342006-04-02 19:18:51 +0100640
Andrew Victore0b19b82006-10-25 19:42:38 +0200641 cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
642 cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
643 cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
644 cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
Andrew Victor65dbf342006-04-02 19:18:51 +0100645
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200646 pr_debug("Status = %08X/%08x [%08X %08X %08X %08X]\n",
647 status, at91_mci_read(host, AT91_MCI_SR),
648 cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
Andrew Victor65dbf342006-04-02 19:18:51 +0100649
Andrew Victor9e3866b2007-10-17 11:53:40 +0200650 if (status & AT91_MCI_ERRORS) {
Marc Pignatb6cedb32007-06-06 20:27:59 +0200651 if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
Pierre Ossman17b04292007-07-22 22:18:46 +0200652 cmd->error = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100653 }
654 else {
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200655 if (status & (AT91_MCI_DTOE | AT91_MCI_DCRCE)) {
656 if (data) {
657 if (status & AT91_MCI_DTOE)
658 data->error = -ETIMEDOUT;
659 else if (status & AT91_MCI_DCRCE)
660 data->error = -EILSEQ;
661 }
662 } else {
663 if (status & AT91_MCI_RTOE)
664 cmd->error = -ETIMEDOUT;
665 else if (status & AT91_MCI_RCRCE)
666 cmd->error = -EILSEQ;
667 else
668 cmd->error = -EIO;
669 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100670
Nicolas Ferrefa1fe012008-06-10 11:27:29 +0200671 pr_debug("Error detected and set to %d/%d (cmd = %d, retries = %d)\n",
672 cmd->error, data ? data->error : 0,
673 cmd->opcode, cmd->retries);
Andrew Victor65dbf342006-04-02 19:18:51 +0100674 }
675 }
676 else
Pierre Ossman17b04292007-07-22 22:18:46 +0200677 cmd->error = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100678
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200679 at91_mci_process_next(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100680}
681
682/*
683 * Handle an MMC request
684 */
685static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
686{
687 struct at91mci_host *host = mmc_priv(mmc);
688 host->request = mrq;
689 host->flags = 0;
690
Wolfgang Mueesa04ac5b2010-03-05 13:43:39 -0800691 /* more than 1s timeout needed with slow SD cards */
692 mod_timer(&host->timer, jiffies + msecs_to_jiffies(2000));
Marc Pignate181dce2008-05-30 14:06:32 +0200693
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200694 at91_mci_process_next(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100695}
696
697/*
698 * Set the IOS
699 */
700static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
701{
702 int clkdiv;
703 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor3dd3b032006-10-23 14:46:54 +0200704 unsigned long at91_master_clock = clk_get_rate(host->mci_clk);
Andrew Victor65dbf342006-04-02 19:18:51 +0100705
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100706 host->bus_mode = ios->bus_mode;
Andrew Victor65dbf342006-04-02 19:18:51 +0100707
708 if (ios->clock == 0) {
709 /* Disable the MCI controller */
Andrew Victore0b19b82006-10-25 19:42:38 +0200710 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100711 clkdiv = 0;
712 }
713 else {
714 /* Enable the MCI controller */
Andrew Victore0b19b82006-10-25 19:42:38 +0200715 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
Andrew Victor65dbf342006-04-02 19:18:51 +0100716
717 if ((at91_master_clock % (ios->clock * 2)) == 0)
718 clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
719 else
720 clkdiv = (at91_master_clock / ios->clock) / 2;
721
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100722 pr_debug("clkdiv = %d. mcck = %ld\n", clkdiv,
Andrew Victor65dbf342006-04-02 19:18:51 +0100723 at91_master_clock / (2 * (clkdiv + 1)));
724 }
725 if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100726 pr_debug("MMC: Setting controller bus width to 4\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200727 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100728 }
729 else {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100730 pr_debug("MMC: Setting controller bus width to 1\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200731 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100732 }
733
734 /* Set the clock divider */
Andrew Victore0b19b82006-10-25 19:42:38 +0200735 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 +0100736
737 /* maybe switch power to the card */
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100738 if (host->board->vcc_pin) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100739 switch (ios->power_mode) {
740 case MMC_POWER_OFF:
David Brownell6e996ee2008-02-04 18:12:48 +0100741 gpio_set_value(host->board->vcc_pin, 0);
Andrew Victor65dbf342006-04-02 19:18:51 +0100742 break;
743 case MMC_POWER_UP:
David Brownell6e996ee2008-02-04 18:12:48 +0100744 gpio_set_value(host->board->vcc_pin, 1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100745 break;
Marc Pignate5c0ef92008-05-09 11:07:07 +0200746 case MMC_POWER_ON:
747 break;
748 default:
749 WARN_ON(1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100750 }
751 }
752}
753
754/*
755 * Handle an interrupt
756 */
David Howells7d12e782006-10-05 14:55:46 +0100757static irqreturn_t at91_mci_irq(int irq, void *devid)
Andrew Victor65dbf342006-04-02 19:18:51 +0100758{
759 struct at91mci_host *host = devid;
760 int completed = 0;
Andrew Victordf05a302006-10-23 14:50:09 +0200761 unsigned int int_status, int_mask;
Andrew Victor65dbf342006-04-02 19:18:51 +0100762
Andrew Victore0b19b82006-10-25 19:42:38 +0200763 int_status = at91_mci_read(host, AT91_MCI_SR);
Andrew Victordf05a302006-10-23 14:50:09 +0200764 int_mask = at91_mci_read(host, AT91_MCI_IMR);
Nicolas Ferre37b758e2007-08-08 12:01:44 +0200765
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200766 pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask,
Andrew Victordf05a302006-10-23 14:50:09 +0200767 int_status & int_mask);
Nicolas Ferre37b758e2007-08-08 12:01:44 +0200768
Andrew Victordf05a302006-10-23 14:50:09 +0200769 int_status = int_status & int_mask;
Andrew Victor65dbf342006-04-02 19:18:51 +0100770
Andrew Victordf05a302006-10-23 14:50:09 +0200771 if (int_status & AT91_MCI_ERRORS) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100772 completed = 1;
Nicolas Ferre37b758e2007-08-08 12:01:44 +0200773
Andrew Victordf05a302006-10-23 14:50:09 +0200774 if (int_status & AT91_MCI_UNRE)
775 pr_debug("MMC: Underrun error\n");
776 if (int_status & AT91_MCI_OVRE)
777 pr_debug("MMC: Overrun error\n");
778 if (int_status & AT91_MCI_DTOE)
779 pr_debug("MMC: Data timeout\n");
780 if (int_status & AT91_MCI_DCRCE)
781 pr_debug("MMC: CRC error in data\n");
782 if (int_status & AT91_MCI_RTOE)
783 pr_debug("MMC: Response timeout\n");
784 if (int_status & AT91_MCI_RENDE)
785 pr_debug("MMC: Response end bit error\n");
786 if (int_status & AT91_MCI_RCRCE)
787 pr_debug("MMC: Response CRC error\n");
788 if (int_status & AT91_MCI_RDIRE)
789 pr_debug("MMC: Response direction error\n");
790 if (int_status & AT91_MCI_RINDE)
791 pr_debug("MMC: Response index error\n");
792 } else {
793 /* Only continue processing if no errors */
Andrew Victor65dbf342006-04-02 19:18:51 +0100794
Andrew Victor65dbf342006-04-02 19:18:51 +0100795 if (int_status & AT91_MCI_TXBUFE) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100796 pr_debug("TX buffer empty\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100797 at91_mci_handle_transmitted(host);
798 }
799
Nicolas Ferreed99c542007-07-09 14:58:16 +0200800 if (int_status & AT91_MCI_ENDRX) {
801 pr_debug("ENDRX\n");
802 at91_mci_post_dma_read(host);
803 }
804
Andrew Victor65dbf342006-04-02 19:18:51 +0100805 if (int_status & AT91_MCI_RXBUFF) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100806 pr_debug("RX buffer full\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200807 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
808 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_RXBUFF | AT91_MCI_ENDRX);
809 completed = 1;
Andrew Victor65dbf342006-04-02 19:18:51 +0100810 }
811
Andrew Victordf05a302006-10-23 14:50:09 +0200812 if (int_status & AT91_MCI_ENDTX)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100813 pr_debug("Transmit has ended\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100814
Andrew Victor65dbf342006-04-02 19:18:51 +0100815 if (int_status & AT91_MCI_NOTBUSY) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100816 pr_debug("Card is ready\n");
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200817 at91_mci_update_bytes_xfered(host);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200818 completed = 1;
Andrew Victor65dbf342006-04-02 19:18:51 +0100819 }
820
Andrew Victordf05a302006-10-23 14:50:09 +0200821 if (int_status & AT91_MCI_DTIP)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100822 pr_debug("Data transfer in progress\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100823
Nicolas Ferreed99c542007-07-09 14:58:16 +0200824 if (int_status & AT91_MCI_BLKE) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100825 pr_debug("Block transfer has ended\n");
Nicolas Ferre4ac24a82008-05-30 14:18:57 +0200826 if (host->request->data && host->request->data->blocks > 1) {
827 /* multi block write : complete multi write
828 * command and send stop */
829 completed = 1;
830 } else {
831 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
832 }
Nicolas Ferreed99c542007-07-09 14:58:16 +0200833 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100834
Eric Benard7a6588b2008-05-30 14:26:05 +0200835 if (int_status & AT91_MCI_SDIOIRQA)
836 mmc_signal_sdio_irq(host->mmc);
837
838 if (int_status & AT91_MCI_SDIOIRQB)
839 mmc_signal_sdio_irq(host->mmc);
840
Andrew Victordf05a302006-10-23 14:50:09 +0200841 if (int_status & AT91_MCI_TXRDY)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100842 pr_debug("Ready to transmit\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100843
Andrew Victordf05a302006-10-23 14:50:09 +0200844 if (int_status & AT91_MCI_RXRDY)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100845 pr_debug("Ready to receive\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100846
847 if (int_status & AT91_MCI_CMDRDY) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100848 pr_debug("Command ready\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200849 completed = at91_mci_handle_cmdrdy(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100850 }
851 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100852
853 if (completed) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100854 pr_debug("Completed command\n");
Eric Benard7a6588b2008-05-30 14:26:05 +0200855 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Nicolas Ferreba7deee2008-05-30 14:28:45 +0200856 at91_mci_completed_command(host, int_status);
Andrew Victordf05a302006-10-23 14:50:09 +0200857 } else
Eric Benard7a6588b2008-05-30 14:26:05 +0200858 at91_mci_write(host, AT91_MCI_IDR, int_status & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
Andrew Victor65dbf342006-04-02 19:18:51 +0100859
860 return IRQ_HANDLED;
861}
862
David Howells7d12e782006-10-05 14:55:46 +0100863static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100864{
865 struct at91mci_host *host = _host;
David Brownell6e996ee2008-02-04 18:12:48 +0100866 int present = !gpio_get_value(irq_to_gpio(irq));
Andrew Victor65dbf342006-04-02 19:18:51 +0100867
868 /*
869 * we expect this irq on both insert and remove,
870 * and use a short delay to debounce.
871 */
872 if (present != host->present) {
873 host->present = present;
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100874 pr_debug("%s: card %s\n", mmc_hostname(host->mmc),
Andrew Victor65dbf342006-04-02 19:18:51 +0100875 present ? "insert" : "remove");
876 if (!present) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100877 pr_debug("****** Resetting SD-card bus width ******\n");
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100878 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100879 }
Wolfgang Mueesa04ac5b2010-03-05 13:43:39 -0800880 /* 0.5s needed because of early card detect switch firing */
881 mmc_detect_change(host->mmc, msecs_to_jiffies(500));
Andrew Victor65dbf342006-04-02 19:18:51 +0100882 }
883 return IRQ_HANDLED;
884}
885
David Brownella26b4982006-12-26 14:45:26 -0800886static int at91_mci_get_ro(struct mmc_host *mmc)
Andrew Victor65dbf342006-04-02 19:18:51 +0100887{
Andrew Victor65dbf342006-04-02 19:18:51 +0100888 struct at91mci_host *host = mmc_priv(mmc);
889
Anton Vorontsov08f80bb2008-06-17 18:17:39 +0400890 if (host->board->wp_pin)
891 return !!gpio_get_value(host->board->wp_pin);
892 /*
893 * Board doesn't support read only detection; let the mmc core
894 * decide what to do.
895 */
896 return -ENOSYS;
Andrew Victor65dbf342006-04-02 19:18:51 +0100897}
898
Eric Benard7a6588b2008-05-30 14:26:05 +0200899static void at91_mci_enable_sdio_irq(struct mmc_host *mmc, int enable)
900{
901 struct at91mci_host *host = mmc_priv(mmc);
902
903 pr_debug("%s: sdio_irq %c : %s\n", mmc_hostname(host->mmc),
904 host->board->slot_b ? 'B':'A', enable ? "enable" : "disable");
905 at91_mci_write(host, enable ? AT91_MCI_IER : AT91_MCI_IDR,
906 host->board->slot_b ? AT91_MCI_SDIOIRQB : AT91_MCI_SDIOIRQA);
907
908}
909
David Brownellab7aefd2006-11-12 17:55:30 -0800910static const struct mmc_host_ops at91_mci_ops = {
Andrew Victor65dbf342006-04-02 19:18:51 +0100911 .request = at91_mci_request,
912 .set_ios = at91_mci_set_ios,
913 .get_ro = at91_mci_get_ro,
Eric Benard7a6588b2008-05-30 14:26:05 +0200914 .enable_sdio_irq = at91_mci_enable_sdio_irq,
Andrew Victor65dbf342006-04-02 19:18:51 +0100915};
916
917/*
918 * Probe for the device
919 */
David Brownella26b4982006-12-26 14:45:26 -0800920static int __init at91_mci_probe(struct platform_device *pdev)
Andrew Victor65dbf342006-04-02 19:18:51 +0100921{
922 struct mmc_host *mmc;
923 struct at91mci_host *host;
Andrew Victor17ea0592006-10-23 14:44:40 +0200924 struct resource *res;
Andrew Victor65dbf342006-04-02 19:18:51 +0100925 int ret;
926
Andrew Victor17ea0592006-10-23 14:44:40 +0200927 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
928 if (!res)
929 return -ENXIO;
930
H Hartley Sweetenaf2a85f2009-12-14 14:10:26 -0500931 if (!request_mem_region(res->start, resource_size(res), DRIVER_NAME))
Andrew Victor17ea0592006-10-23 14:44:40 +0200932 return -EBUSY;
933
Andrew Victor65dbf342006-04-02 19:18:51 +0100934 mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
935 if (!mmc) {
David Brownell6e996ee2008-02-04 18:12:48 +0100936 ret = -ENOMEM;
937 dev_dbg(&pdev->dev, "couldn't allocate mmc host\n");
938 goto fail6;
Andrew Victor65dbf342006-04-02 19:18:51 +0100939 }
940
941 mmc->ops = &at91_mci_ops;
942 mmc->f_min = 375000;
943 mmc->f_max = 25000000;
944 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
Nicolas Ferre541e7ef2010-03-05 13:43:43 -0800945 mmc->caps = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100946
Wolfgang Muees3780d902010-03-05 13:43:40 -0800947 mmc->max_blk_size = MCI_MAXBLKSIZE;
948 mmc->max_blk_count = MCI_BLKATONCE;
949 mmc->max_req_size = MCI_BUFSIZE;
Wolfgang Muees9af13be2010-03-05 13:43:42 -0800950 mmc->max_phys_segs = MCI_BLKATONCE;
951 mmc->max_hw_segs = MCI_BLKATONCE;
952 mmc->max_seg_size = MCI_BUFSIZE;
Pierre Ossmanfe4a3c72006-11-21 17:54:23 +0100953
Andrew Victor65dbf342006-04-02 19:18:51 +0100954 host = mmc_priv(mmc);
955 host->mmc = mmc;
Andrew Victor65dbf342006-04-02 19:18:51 +0100956 host->bus_mode = 0;
957 host->board = pdev->dev.platform_data;
958 if (host->board->wire4) {
Nicolas Ferre5b27a1a2010-03-05 13:43:44 -0800959 if (at91mci_is_mci1rev2xx())
Nicolas Ferreed99c542007-07-09 14:58:16 +0200960 mmc->caps |= MMC_CAP_4_BIT_DATA;
961 else
David Brownell6e996ee2008-02-04 18:12:48 +0100962 dev_warn(&pdev->dev, "4 wire bus mode not supported"
Nicolas Ferreed99c542007-07-09 14:58:16 +0200963 " - using 1 wire\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100964 }
965
Wolfgang Muees3780d902010-03-05 13:43:40 -0800966 host->buffer = dma_alloc_coherent(&pdev->dev, MCI_BUFSIZE,
967 &host->physical_address, GFP_KERNEL);
968 if (!host->buffer) {
969 ret = -ENOMEM;
970 dev_err(&pdev->dev, "Can't allocate transmit buffer\n");
971 goto fail5;
972 }
973
Nicolas Ferre541e7ef2010-03-05 13:43:43 -0800974 /* Add SDIO capability when available */
Nicolas Ferre5b27a1a2010-03-05 13:43:44 -0800975 if (at91mci_is_mci1rev2xx()) {
976 /* at91mci MCI1 rev2xx sdio interrupt erratum */
Nicolas Ferre541e7ef2010-03-05 13:43:43 -0800977 if (host->board->wire4 || !host->board->slot_b)
978 mmc->caps |= MMC_CAP_SDIO_IRQ;
979 }
980
Andrew Victor65dbf342006-04-02 19:18:51 +0100981 /*
David Brownell6e996ee2008-02-04 18:12:48 +0100982 * Reserve GPIOs ... board init code makes sure these pins are set
983 * up as GPIOs with the right direction (input, except for vcc)
984 */
985 if (host->board->det_pin) {
986 ret = gpio_request(host->board->det_pin, "mmc_detect");
987 if (ret < 0) {
988 dev_dbg(&pdev->dev, "couldn't claim card detect pin\n");
Wolfgang Muees3780d902010-03-05 13:43:40 -0800989 goto fail4b;
David Brownell6e996ee2008-02-04 18:12:48 +0100990 }
991 }
992 if (host->board->wp_pin) {
993 ret = gpio_request(host->board->wp_pin, "mmc_wp");
994 if (ret < 0) {
995 dev_dbg(&pdev->dev, "couldn't claim wp sense pin\n");
996 goto fail4;
997 }
998 }
999 if (host->board->vcc_pin) {
1000 ret = gpio_request(host->board->vcc_pin, "mmc_vcc");
1001 if (ret < 0) {
1002 dev_dbg(&pdev->dev, "couldn't claim vcc switch pin\n");
1003 goto fail3;
1004 }
1005 }
1006
1007 /*
Andrew Victor65dbf342006-04-02 19:18:51 +01001008 * Get Clock
1009 */
Andrew Victor3dd3b032006-10-23 14:46:54 +02001010 host->mci_clk = clk_get(&pdev->dev, "mci_clk");
1011 if (IS_ERR(host->mci_clk)) {
David Brownell6e996ee2008-02-04 18:12:48 +01001012 ret = -ENODEV;
1013 dev_dbg(&pdev->dev, "no mci_clk?\n");
1014 goto fail2;
Andrew Victor65dbf342006-04-02 19:18:51 +01001015 }
Andrew Victor65dbf342006-04-02 19:18:51 +01001016
Andrew Victor17ea0592006-10-23 14:44:40 +02001017 /*
1018 * Map I/O region
1019 */
H Hartley Sweetenaf2a85f2009-12-14 14:10:26 -05001020 host->baseaddr = ioremap(res->start, resource_size(res));
Andrew Victor17ea0592006-10-23 14:44:40 +02001021 if (!host->baseaddr) {
David Brownell6e996ee2008-02-04 18:12:48 +01001022 ret = -ENOMEM;
1023 goto fail1;
Andrew Victor17ea0592006-10-23 14:44:40 +02001024 }
Andrew Victore0b19b82006-10-25 19:42:38 +02001025
1026 /*
1027 * Reset hardware
1028 */
Andrew Victor3dd3b032006-10-23 14:46:54 +02001029 clk_enable(host->mci_clk); /* Enable the peripheral clock */
Andrew Victore0b19b82006-10-25 19:42:38 +02001030 at91_mci_disable(host);
1031 at91_mci_enable(host);
1032
Andrew Victor65dbf342006-04-02 19:18:51 +01001033 /*
1034 * Allocate the MCI interrupt
1035 */
Andrew Victor17ea0592006-10-23 14:44:40 +02001036 host->irq = platform_get_irq(pdev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +01001037 ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED,
1038 mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001039 if (ret) {
David Brownell6e996ee2008-02-04 18:12:48 +01001040 dev_dbg(&pdev->dev, "request MCI interrupt failed\n");
1041 goto fail0;
Andrew Victor65dbf342006-04-02 19:18:51 +01001042 }
1043
Nicolas Ferre99ba0402008-11-27 17:23:49 +01001044 setup_timer(&host->timer, at91_timeout_timer, (unsigned long)host);
1045
Andrew Victor65dbf342006-04-02 19:18:51 +01001046 platform_set_drvdata(pdev, mmc);
1047
1048 /*
1049 * Add host to MMC layer
1050 */
Marc Pignat63b66432007-07-16 11:07:02 +02001051 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001052 host->present = !gpio_get_value(host->board->det_pin);
Marc Pignat63b66432007-07-16 11:07:02 +02001053 }
Andrew Victor65dbf342006-04-02 19:18:51 +01001054 else
1055 host->present = -1;
1056
1057 mmc_add_host(mmc);
1058
1059 /*
1060 * monitor card insertion/removal if we can
1061 */
1062 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001063 ret = request_irq(gpio_to_irq(host->board->det_pin),
1064 at91_mmc_det_irq, 0, mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001065 if (ret)
David Brownell6e996ee2008-02-04 18:12:48 +01001066 dev_warn(&pdev->dev, "request MMC detect irq failed\n");
1067 else
1068 device_init_wakeup(&pdev->dev, 1);
Andrew Victor65dbf342006-04-02 19:18:51 +01001069 }
1070
Andrew Victorf3a8efa2006-10-23 14:53:20 +02001071 pr_debug("Added MCI driver\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001072
1073 return 0;
David Brownell6e996ee2008-02-04 18:12:48 +01001074
1075fail0:
1076 clk_disable(host->mci_clk);
1077 iounmap(host->baseaddr);
1078fail1:
1079 clk_put(host->mci_clk);
1080fail2:
1081 if (host->board->vcc_pin)
1082 gpio_free(host->board->vcc_pin);
1083fail3:
1084 if (host->board->wp_pin)
1085 gpio_free(host->board->wp_pin);
1086fail4:
1087 if (host->board->det_pin)
1088 gpio_free(host->board->det_pin);
Wolfgang Muees3780d902010-03-05 13:43:40 -08001089fail4b:
1090 if (host->buffer)
1091 dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
1092 host->buffer, host->physical_address);
David Brownell6e996ee2008-02-04 18:12:48 +01001093fail5:
1094 mmc_free_host(mmc);
1095fail6:
H Hartley Sweetenaf2a85f2009-12-14 14:10:26 -05001096 release_mem_region(res->start, resource_size(res));
David Brownell6e996ee2008-02-04 18:12:48 +01001097 dev_err(&pdev->dev, "probe failed, err %d\n", ret);
1098 return ret;
Andrew Victor65dbf342006-04-02 19:18:51 +01001099}
1100
1101/*
1102 * Remove a device
1103 */
David Brownella26b4982006-12-26 14:45:26 -08001104static int __exit at91_mci_remove(struct platform_device *pdev)
Andrew Victor65dbf342006-04-02 19:18:51 +01001105{
1106 struct mmc_host *mmc = platform_get_drvdata(pdev);
1107 struct at91mci_host *host;
Andrew Victor17ea0592006-10-23 14:44:40 +02001108 struct resource *res;
Andrew Victor65dbf342006-04-02 19:18:51 +01001109
1110 if (!mmc)
1111 return -1;
1112
1113 host = mmc_priv(mmc);
1114
Wolfgang Muees3780d902010-03-05 13:43:40 -08001115 if (host->buffer)
1116 dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
1117 host->buffer, host->physical_address);
1118
Anti Sulline0cda542007-08-30 16:15:16 +02001119 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001120 if (device_can_wakeup(&pdev->dev))
1121 free_irq(gpio_to_irq(host->board->det_pin), host);
Marc Pignat63b66432007-07-16 11:07:02 +02001122 device_init_wakeup(&pdev->dev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +01001123 gpio_free(host->board->det_pin);
Andrew Victor65dbf342006-04-02 19:18:51 +01001124 }
1125
Andrew Victore0b19b82006-10-25 19:42:38 +02001126 at91_mci_disable(host);
Marc Pignate181dce2008-05-30 14:06:32 +02001127 del_timer_sync(&host->timer);
Andrew Victor17ea0592006-10-23 14:44:40 +02001128 mmc_remove_host(mmc);
1129 free_irq(host->irq, host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001130
Andrew Victor3dd3b032006-10-23 14:46:54 +02001131 clk_disable(host->mci_clk); /* Disable the peripheral clock */
1132 clk_put(host->mci_clk);
Andrew Victor65dbf342006-04-02 19:18:51 +01001133
David Brownell6e996ee2008-02-04 18:12:48 +01001134 if (host->board->vcc_pin)
1135 gpio_free(host->board->vcc_pin);
1136 if (host->board->wp_pin)
1137 gpio_free(host->board->wp_pin);
1138
Andrew Victor17ea0592006-10-23 14:44:40 +02001139 iounmap(host->baseaddr);
1140 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
H Hartley Sweetenaf2a85f2009-12-14 14:10:26 -05001141 release_mem_region(res->start, resource_size(res));
Andrew Victor65dbf342006-04-02 19:18:51 +01001142
Andrew Victor17ea0592006-10-23 14:44:40 +02001143 mmc_free_host(mmc);
1144 platform_set_drvdata(pdev, NULL);
Andrew Victorb44fb7a2006-06-19 13:06:05 +01001145 pr_debug("MCI Removed\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001146
1147 return 0;
1148}
1149
1150#ifdef CONFIG_PM
1151static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
1152{
1153 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001154 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001155 int ret = 0;
1156
Anti Sulline0cda542007-08-30 16:15:16 +02001157 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001158 enable_irq_wake(host->board->det_pin);
1159
Andrew Victor65dbf342006-04-02 19:18:51 +01001160 if (mmc)
Matt Fleming1a13f8f2010-05-26 14:42:08 -07001161 ret = mmc_suspend_host(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001162
1163 return ret;
1164}
1165
1166static int at91_mci_resume(struct platform_device *pdev)
1167{
1168 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001169 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001170 int ret = 0;
1171
Anti Sulline0cda542007-08-30 16:15:16 +02001172 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001173 disable_irq_wake(host->board->det_pin);
1174
Andrew Victor65dbf342006-04-02 19:18:51 +01001175 if (mmc)
1176 ret = mmc_resume_host(mmc);
1177
1178 return ret;
1179}
1180#else
1181#define at91_mci_suspend NULL
1182#define at91_mci_resume NULL
1183#endif
1184
1185static struct platform_driver at91_mci_driver = {
David Brownella26b4982006-12-26 14:45:26 -08001186 .remove = __exit_p(at91_mci_remove),
Andrew Victor65dbf342006-04-02 19:18:51 +01001187 .suspend = at91_mci_suspend,
1188 .resume = at91_mci_resume,
1189 .driver = {
1190 .name = DRIVER_NAME,
1191 .owner = THIS_MODULE,
1192 },
1193};
1194
1195static int __init at91_mci_init(void)
1196{
David Brownella26b4982006-12-26 14:45:26 -08001197 return platform_driver_probe(&at91_mci_driver, at91_mci_probe);
Andrew Victor65dbf342006-04-02 19:18:51 +01001198}
1199
1200static void __exit at91_mci_exit(void)
1201{
1202 platform_driver_unregister(&at91_mci_driver);
1203}
1204
1205module_init(at91_mci_init);
1206module_exit(at91_mci_exit);
1207
1208MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
1209MODULE_AUTHOR("Nick Randell");
1210MODULE_LICENSE("GPL");
Kay Sieversbc65c722008-04-15 14:34:28 -07001211MODULE_ALIAS("platform:at91_mci");