blob: 591ab540b407ad9805c3aa384795b2c59a7d8c69 [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 Ferre37b758e82007-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 Ferre37b758e82007-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 Ferre37b758e82007-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 Ferre37b758e82007-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;
Martin K. Petersena36274e2010-09-10 01:33:59 -0400950 mmc->max_segs = MCI_BLKATONCE;
Wolfgang Muees9af13be2010-03-05 13:43:42 -0800951 mmc->max_seg_size = MCI_BUFSIZE;
Pierre Ossmanfe4a3c72006-11-21 17:54:23 +0100952
Andrew Victor65dbf342006-04-02 19:18:51 +0100953 host = mmc_priv(mmc);
954 host->mmc = mmc;
Andrew Victor65dbf342006-04-02 19:18:51 +0100955 host->bus_mode = 0;
956 host->board = pdev->dev.platform_data;
957 if (host->board->wire4) {
Nicolas Ferre5b27a1a2010-03-05 13:43:44 -0800958 if (at91mci_is_mci1rev2xx())
Nicolas Ferreed99c542007-07-09 14:58:16 +0200959 mmc->caps |= MMC_CAP_4_BIT_DATA;
960 else
David Brownell6e996ee2008-02-04 18:12:48 +0100961 dev_warn(&pdev->dev, "4 wire bus mode not supported"
Nicolas Ferreed99c542007-07-09 14:58:16 +0200962 " - using 1 wire\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100963 }
964
Wolfgang Muees3780d902010-03-05 13:43:40 -0800965 host->buffer = dma_alloc_coherent(&pdev->dev, MCI_BUFSIZE,
966 &host->physical_address, GFP_KERNEL);
967 if (!host->buffer) {
968 ret = -ENOMEM;
969 dev_err(&pdev->dev, "Can't allocate transmit buffer\n");
970 goto fail5;
971 }
972
Nicolas Ferre541e7ef2010-03-05 13:43:43 -0800973 /* Add SDIO capability when available */
Nicolas Ferre5b27a1a2010-03-05 13:43:44 -0800974 if (at91mci_is_mci1rev2xx()) {
975 /* at91mci MCI1 rev2xx sdio interrupt erratum */
Nicolas Ferre541e7ef2010-03-05 13:43:43 -0800976 if (host->board->wire4 || !host->board->slot_b)
977 mmc->caps |= MMC_CAP_SDIO_IRQ;
978 }
979
Andrew Victor65dbf342006-04-02 19:18:51 +0100980 /*
David Brownell6e996ee2008-02-04 18:12:48 +0100981 * Reserve GPIOs ... board init code makes sure these pins are set
982 * up as GPIOs with the right direction (input, except for vcc)
983 */
984 if (host->board->det_pin) {
985 ret = gpio_request(host->board->det_pin, "mmc_detect");
986 if (ret < 0) {
987 dev_dbg(&pdev->dev, "couldn't claim card detect pin\n");
Wolfgang Muees3780d902010-03-05 13:43:40 -0800988 goto fail4b;
David Brownell6e996ee2008-02-04 18:12:48 +0100989 }
990 }
991 if (host->board->wp_pin) {
992 ret = gpio_request(host->board->wp_pin, "mmc_wp");
993 if (ret < 0) {
994 dev_dbg(&pdev->dev, "couldn't claim wp sense pin\n");
995 goto fail4;
996 }
997 }
998 if (host->board->vcc_pin) {
999 ret = gpio_request(host->board->vcc_pin, "mmc_vcc");
1000 if (ret < 0) {
1001 dev_dbg(&pdev->dev, "couldn't claim vcc switch pin\n");
1002 goto fail3;
1003 }
1004 }
1005
1006 /*
Andrew Victor65dbf342006-04-02 19:18:51 +01001007 * Get Clock
1008 */
Andrew Victor3dd3b032006-10-23 14:46:54 +02001009 host->mci_clk = clk_get(&pdev->dev, "mci_clk");
1010 if (IS_ERR(host->mci_clk)) {
David Brownell6e996ee2008-02-04 18:12:48 +01001011 ret = -ENODEV;
1012 dev_dbg(&pdev->dev, "no mci_clk?\n");
1013 goto fail2;
Andrew Victor65dbf342006-04-02 19:18:51 +01001014 }
Andrew Victor65dbf342006-04-02 19:18:51 +01001015
Andrew Victor17ea0592006-10-23 14:44:40 +02001016 /*
1017 * Map I/O region
1018 */
H Hartley Sweetenaf2a85f2009-12-14 14:10:26 -05001019 host->baseaddr = ioremap(res->start, resource_size(res));
Andrew Victor17ea0592006-10-23 14:44:40 +02001020 if (!host->baseaddr) {
David Brownell6e996ee2008-02-04 18:12:48 +01001021 ret = -ENOMEM;
1022 goto fail1;
Andrew Victor17ea0592006-10-23 14:44:40 +02001023 }
Andrew Victore0b19b82006-10-25 19:42:38 +02001024
1025 /*
1026 * Reset hardware
1027 */
Andrew Victor3dd3b032006-10-23 14:46:54 +02001028 clk_enable(host->mci_clk); /* Enable the peripheral clock */
Andrew Victore0b19b82006-10-25 19:42:38 +02001029 at91_mci_disable(host);
1030 at91_mci_enable(host);
1031
Andrew Victor65dbf342006-04-02 19:18:51 +01001032 /*
1033 * Allocate the MCI interrupt
1034 */
Andrew Victor17ea0592006-10-23 14:44:40 +02001035 host->irq = platform_get_irq(pdev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +01001036 ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED,
1037 mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001038 if (ret) {
David Brownell6e996ee2008-02-04 18:12:48 +01001039 dev_dbg(&pdev->dev, "request MCI interrupt failed\n");
1040 goto fail0;
Andrew Victor65dbf342006-04-02 19:18:51 +01001041 }
1042
Nicolas Ferre99ba0402008-11-27 17:23:49 +01001043 setup_timer(&host->timer, at91_timeout_timer, (unsigned long)host);
1044
Andrew Victor65dbf342006-04-02 19:18:51 +01001045 platform_set_drvdata(pdev, mmc);
1046
1047 /*
1048 * Add host to MMC layer
1049 */
Marc Pignat63b66432007-07-16 11:07:02 +02001050 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001051 host->present = !gpio_get_value(host->board->det_pin);
Marc Pignat63b66432007-07-16 11:07:02 +02001052 }
Andrew Victor65dbf342006-04-02 19:18:51 +01001053 else
1054 host->present = -1;
1055
1056 mmc_add_host(mmc);
1057
1058 /*
1059 * monitor card insertion/removal if we can
1060 */
1061 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001062 ret = request_irq(gpio_to_irq(host->board->det_pin),
1063 at91_mmc_det_irq, 0, mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001064 if (ret)
David Brownell6e996ee2008-02-04 18:12:48 +01001065 dev_warn(&pdev->dev, "request MMC detect irq failed\n");
1066 else
1067 device_init_wakeup(&pdev->dev, 1);
Andrew Victor65dbf342006-04-02 19:18:51 +01001068 }
1069
Andrew Victorf3a8efa2006-10-23 14:53:20 +02001070 pr_debug("Added MCI driver\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001071
1072 return 0;
David Brownell6e996ee2008-02-04 18:12:48 +01001073
1074fail0:
1075 clk_disable(host->mci_clk);
1076 iounmap(host->baseaddr);
1077fail1:
1078 clk_put(host->mci_clk);
1079fail2:
1080 if (host->board->vcc_pin)
1081 gpio_free(host->board->vcc_pin);
1082fail3:
1083 if (host->board->wp_pin)
1084 gpio_free(host->board->wp_pin);
1085fail4:
1086 if (host->board->det_pin)
1087 gpio_free(host->board->det_pin);
Wolfgang Muees3780d902010-03-05 13:43:40 -08001088fail4b:
1089 if (host->buffer)
1090 dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
1091 host->buffer, host->physical_address);
David Brownell6e996ee2008-02-04 18:12:48 +01001092fail5:
1093 mmc_free_host(mmc);
1094fail6:
H Hartley Sweetenaf2a85f2009-12-14 14:10:26 -05001095 release_mem_region(res->start, resource_size(res));
David Brownell6e996ee2008-02-04 18:12:48 +01001096 dev_err(&pdev->dev, "probe failed, err %d\n", ret);
1097 return ret;
Andrew Victor65dbf342006-04-02 19:18:51 +01001098}
1099
1100/*
1101 * Remove a device
1102 */
David Brownella26b4982006-12-26 14:45:26 -08001103static int __exit at91_mci_remove(struct platform_device *pdev)
Andrew Victor65dbf342006-04-02 19:18:51 +01001104{
1105 struct mmc_host *mmc = platform_get_drvdata(pdev);
1106 struct at91mci_host *host;
Andrew Victor17ea0592006-10-23 14:44:40 +02001107 struct resource *res;
Andrew Victor65dbf342006-04-02 19:18:51 +01001108
1109 if (!mmc)
1110 return -1;
1111
1112 host = mmc_priv(mmc);
1113
Wolfgang Muees3780d902010-03-05 13:43:40 -08001114 if (host->buffer)
1115 dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
1116 host->buffer, host->physical_address);
1117
Anti Sulline0cda542007-08-30 16:15:16 +02001118 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001119 if (device_can_wakeup(&pdev->dev))
1120 free_irq(gpio_to_irq(host->board->det_pin), host);
Marc Pignat63b66432007-07-16 11:07:02 +02001121 device_init_wakeup(&pdev->dev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +01001122 gpio_free(host->board->det_pin);
Andrew Victor65dbf342006-04-02 19:18:51 +01001123 }
1124
Andrew Victore0b19b82006-10-25 19:42:38 +02001125 at91_mci_disable(host);
Marc Pignate181dce2008-05-30 14:06:32 +02001126 del_timer_sync(&host->timer);
Andrew Victor17ea0592006-10-23 14:44:40 +02001127 mmc_remove_host(mmc);
1128 free_irq(host->irq, host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001129
Andrew Victor3dd3b032006-10-23 14:46:54 +02001130 clk_disable(host->mci_clk); /* Disable the peripheral clock */
1131 clk_put(host->mci_clk);
Andrew Victor65dbf342006-04-02 19:18:51 +01001132
David Brownell6e996ee2008-02-04 18:12:48 +01001133 if (host->board->vcc_pin)
1134 gpio_free(host->board->vcc_pin);
1135 if (host->board->wp_pin)
1136 gpio_free(host->board->wp_pin);
1137
Andrew Victor17ea0592006-10-23 14:44:40 +02001138 iounmap(host->baseaddr);
1139 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
H Hartley Sweetenaf2a85f2009-12-14 14:10:26 -05001140 release_mem_region(res->start, resource_size(res));
Andrew Victor65dbf342006-04-02 19:18:51 +01001141
Andrew Victor17ea0592006-10-23 14:44:40 +02001142 mmc_free_host(mmc);
1143 platform_set_drvdata(pdev, NULL);
Andrew Victorb44fb7a2006-06-19 13:06:05 +01001144 pr_debug("MCI Removed\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001145
1146 return 0;
1147}
1148
1149#ifdef CONFIG_PM
1150static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
1151{
1152 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001153 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001154 int ret = 0;
1155
Anti Sulline0cda542007-08-30 16:15:16 +02001156 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001157 enable_irq_wake(host->board->det_pin);
1158
Andrew Victor65dbf342006-04-02 19:18:51 +01001159 if (mmc)
Matt Fleming1a13f8f2010-05-26 14:42:08 -07001160 ret = mmc_suspend_host(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001161
1162 return ret;
1163}
1164
1165static int at91_mci_resume(struct platform_device *pdev)
1166{
1167 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001168 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001169 int ret = 0;
1170
Anti Sulline0cda542007-08-30 16:15:16 +02001171 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001172 disable_irq_wake(host->board->det_pin);
1173
Andrew Victor65dbf342006-04-02 19:18:51 +01001174 if (mmc)
1175 ret = mmc_resume_host(mmc);
1176
1177 return ret;
1178}
1179#else
1180#define at91_mci_suspend NULL
1181#define at91_mci_resume NULL
1182#endif
1183
1184static struct platform_driver at91_mci_driver = {
David Brownella26b4982006-12-26 14:45:26 -08001185 .remove = __exit_p(at91_mci_remove),
Andrew Victor65dbf342006-04-02 19:18:51 +01001186 .suspend = at91_mci_suspend,
1187 .resume = at91_mci_resume,
1188 .driver = {
1189 .name = DRIVER_NAME,
1190 .owner = THIS_MODULE,
1191 },
1192};
1193
1194static int __init at91_mci_init(void)
1195{
David Brownella26b4982006-12-26 14:45:26 -08001196 return platform_driver_probe(&at91_mci_driver, at91_mci_probe);
Andrew Victor65dbf342006-04-02 19:18:51 +01001197}
1198
1199static void __exit at91_mci_exit(void)
1200{
1201 platform_driver_unregister(&at91_mci_driver);
1202}
1203
1204module_init(at91_mci_init);
1205module_exit(at91_mci_exit);
1206
1207MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
1208MODULE_AUTHOR("Nick Randell");
1209MODULE_LICENSE("GPL");
Kay Sieversbc65c722008-04-15 14:34:28 -07001210MODULE_ALIAS("platform:at91_mci");