blob: fce171c7c67e88182f3d24b1a9423e627c89689b [file] [log] [blame]
Andrew Victor65dbf342006-04-02 19:18:51 +01001/*
Pierre Ossman70f10482007-07-11 20:04:50 +02002 * linux/drivers/mmc/host/at91_mci.c - ATMEL AT91 MCI Driver
Andrew Victor65dbf342006-04-02 19:18:51 +01003 *
4 * Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved
5 *
6 * Copyright (C) 2006 Malcolm Noyes
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13/*
Andrew Victor99eeb8d2006-12-11 12:40:23 +010014 This is the AT91 MCI driver that has been tested with both MMC cards
Andrew Victor65dbf342006-04-02 19:18:51 +010015 and SD-cards. Boards that support write protect are now supported.
16 The CCAT91SBC001 board does not support SD cards.
17
18 The three entry points are at91_mci_request, at91_mci_set_ios
19 and at91_mci_get_ro.
20
21 SET IOS
22 This configures the device to put it into the correct mode and clock speed
23 required.
24
25 MCI REQUEST
26 MCI request processes the commands sent in the mmc_request structure. This
27 can consist of a processing command and a stop command in the case of
28 multiple block transfers.
29
30 There are three main types of request, commands, reads and writes.
31
32 Commands are straight forward. The command is submitted to the controller and
33 the request function returns. When the controller generates an interrupt to indicate
34 the command is finished, the response to the command are read and the mmc_request_done
35 function called to end the request.
36
37 Reads and writes work in a similar manner to normal commands but involve the PDC (DMA)
38 controller to manage the transfers.
39
40 A read is done from the controller directly to the scatterlist passed in from the request.
Andrew Victor99eeb8d2006-12-11 12:40:23 +010041 Due to a bug in the AT91RM9200 controller, when a read is completed, all the words are byte
42 swapped in the scatterlist buffers. AT91SAM926x are not affected by this bug.
Andrew Victor65dbf342006-04-02 19:18:51 +010043
44 The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY
45
46 A write is slightly different in that the bytes to write are read from the scatterlist
47 into a dma memory buffer (this is in case the source buffer should be read only). The
48 entire write buffer is then done from this single dma memory buffer.
49
50 The sequence of write interrupts is: ENDTX, TXBUFE, NOTBUSY, CMDRDY
51
52 GET RO
53 Gets the status of the write protect pin, if available.
54*/
55
Andrew Victor65dbf342006-04-02 19:18:51 +010056#include <linux/module.h>
57#include <linux/moduleparam.h>
58#include <linux/init.h>
59#include <linux/ioport.h>
60#include <linux/platform_device.h>
61#include <linux/interrupt.h>
62#include <linux/blkdev.h>
63#include <linux/delay.h>
64#include <linux/err.h>
65#include <linux/dma-mapping.h>
66#include <linux/clk.h>
Andrew Victor93a3ddc2007-02-08 11:31:22 +010067#include <linux/atmel_pdc.h>
Andrew Victor65dbf342006-04-02 19:18:51 +010068
69#include <linux/mmc/host.h>
Andrew Victor65dbf342006-04-02 19:18:51 +010070
71#include <asm/io.h>
72#include <asm/irq.h>
David Brownell6e996ee2008-02-04 18:12:48 +010073#include <asm/gpio.h>
74
Andrew Victor65dbf342006-04-02 19:18:51 +010075#include <asm/mach/mmc.h>
76#include <asm/arch/board.h>
Andrew Victor99eeb8d2006-12-11 12:40:23 +010077#include <asm/arch/cpu.h>
Andrew Victor55d8bae2006-11-30 17:16:43 +010078#include <asm/arch/at91_mci.h>
Andrew Victor65dbf342006-04-02 19:18:51 +010079
80#define DRIVER_NAME "at91_mci"
81
Andrew Victordf05a302006-10-23 14:50:09 +020082#define FL_SENT_COMMAND (1 << 0)
83#define FL_SENT_STOP (1 << 1)
Andrew Victor65dbf342006-04-02 19:18:51 +010084
Andrew Victordf05a302006-10-23 14:50:09 +020085#define AT91_MCI_ERRORS (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE \
86 | AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE \
Nicolas Ferre37b758e2007-08-08 12:01:44 +020087 | AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)
Andrew Victor65dbf342006-04-02 19:18:51 +010088
Andrew Victore0b19b82006-10-25 19:42:38 +020089#define at91_mci_read(host, reg) __raw_readl((host)->baseaddr + (reg))
90#define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg))
Andrew Victor65dbf342006-04-02 19:18:51 +010091
Andrew Victor65dbf342006-04-02 19:18:51 +010092
93/*
94 * Low level type for this driver
95 */
96struct at91mci_host
97{
98 struct mmc_host *mmc;
99 struct mmc_command *cmd;
100 struct mmc_request *request;
101
Andrew Victore0b19b82006-10-25 19:42:38 +0200102 void __iomem *baseaddr;
Andrew Victor17ea0592006-10-23 14:44:40 +0200103 int irq;
Andrew Victore0b19b82006-10-25 19:42:38 +0200104
Andrew Victor65dbf342006-04-02 19:18:51 +0100105 struct at91_mmc_data *board;
106 int present;
107
Andrew Victor3dd3b032006-10-23 14:46:54 +0200108 struct clk *mci_clk;
109
Andrew Victor65dbf342006-04-02 19:18:51 +0100110 /*
111 * Flag indicating when the command has been sent. This is used to
112 * work out whether or not to send the stop
113 */
114 unsigned int flags;
115 /* flag for current bus settings */
116 u32 bus_mode;
117
118 /* DMA buffer used for transmitting */
119 unsigned int* buffer;
120 dma_addr_t physical_address;
121 unsigned int total_length;
122
123 /* Latest in the scatterlist that has been enabled for transfer, but not freed */
124 int in_use_index;
125
126 /* Latest in the scatterlist that has been enabled for transfer */
127 int transfer_index;
Marc Pignate181dce2008-05-30 14:06:32 +0200128
129 /* Timer for timeouts */
130 struct timer_list timer;
Andrew Victor65dbf342006-04-02 19:18:51 +0100131};
132
Marc Pignate181dce2008-05-30 14:06:32 +0200133static void at91_timeout_timer(unsigned long data)
134{
135 struct at91mci_host *host;
136
137 host = (struct at91mci_host *)data;
138
139 if (host->request) {
140 dev_err(host->mmc->parent, "Timeout waiting end of packet\n");
141
142 if (host->cmd && host->cmd->data) {
143 host->cmd->data->error = -ETIMEDOUT;
144 } else {
145 if (host->cmd)
146 host->cmd->error = -ETIMEDOUT;
147 else
148 host->request->cmd->error = -ETIMEDOUT;
149 }
150
151 mmc_request_done(host->mmc, host->request);
152 }
153}
154
Andrew Victor65dbf342006-04-02 19:18:51 +0100155/*
156 * Copy from sg to a dma block - used for transfers
157 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200158static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
Andrew Victor65dbf342006-04-02 19:18:51 +0100159{
160 unsigned int len, i, size;
161 unsigned *dmabuf = host->buffer;
162
163 size = host->total_length;
164 len = data->sg_len;
165
166 /*
167 * Just loop through all entries. Size might not
168 * be the entire list though so make sure that
169 * we do not transfer too much.
170 */
171 for (i = 0; i < len; i++) {
172 struct scatterlist *sg;
173 int amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100174 unsigned int *sgbuffer;
175
176 sg = &data->sg[i];
177
Jens Axboe45711f12007-10-22 21:19:53 +0200178 sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
Andrew Victor65dbf342006-04-02 19:18:51 +0100179 amount = min(size, sg->length);
180 size -= amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100181
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100182 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
183 int index;
184
185 for (index = 0; index < (amount / 4); index++)
186 *dmabuf++ = swab32(sgbuffer[index]);
187 }
188 else
189 memcpy(dmabuf, sgbuffer, amount);
Andrew Victor65dbf342006-04-02 19:18:51 +0100190
191 kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
192
193 if (size == 0)
194 break;
195 }
196
197 /*
198 * Check that we didn't get a request to transfer
199 * more data than can fit into the SG list.
200 */
201 BUG_ON(size != 0);
202}
203
204/*
205 * Prepare a dma read
206 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200207static void at91_mci_pre_dma_read(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100208{
209 int i;
210 struct scatterlist *sg;
211 struct mmc_command *cmd;
212 struct mmc_data *data;
213
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100214 pr_debug("pre dma read\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100215
216 cmd = host->cmd;
217 if (!cmd) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100218 pr_debug("no command\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100219 return;
220 }
221
222 data = cmd->data;
223 if (!data) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100224 pr_debug("no data\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100225 return;
226 }
227
228 for (i = 0; i < 2; i++) {
229 /* nothing left to transfer */
230 if (host->transfer_index >= data->sg_len) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100231 pr_debug("Nothing left to transfer (index = %d)\n", host->transfer_index);
Andrew Victor65dbf342006-04-02 19:18:51 +0100232 break;
233 }
234
235 /* Check to see if this needs filling */
236 if (i == 0) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100237 if (at91_mci_read(host, ATMEL_PDC_RCR) != 0) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100238 pr_debug("Transfer active in current\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100239 continue;
240 }
241 }
242 else {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100243 if (at91_mci_read(host, ATMEL_PDC_RNCR) != 0) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100244 pr_debug("Transfer active in next\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100245 continue;
246 }
247 }
248
249 /* Setup the next transfer */
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100250 pr_debug("Using transfer index %d\n", host->transfer_index);
Andrew Victor65dbf342006-04-02 19:18:51 +0100251
252 sg = &data->sg[host->transfer_index++];
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100253 pr_debug("sg = %p\n", sg);
Andrew Victor65dbf342006-04-02 19:18:51 +0100254
Jens Axboe45711f12007-10-22 21:19:53 +0200255 sg->dma_address = dma_map_page(NULL, sg_page(sg), sg->offset, sg->length, DMA_FROM_DEVICE);
Andrew Victor65dbf342006-04-02 19:18:51 +0100256
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100257 pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
Andrew Victor65dbf342006-04-02 19:18:51 +0100258
259 if (i == 0) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100260 at91_mci_write(host, ATMEL_PDC_RPR, sg->dma_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200261 at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ? sg->length : sg->length / 4);
Andrew Victor65dbf342006-04-02 19:18:51 +0100262 }
263 else {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100264 at91_mci_write(host, ATMEL_PDC_RNPR, sg->dma_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200265 at91_mci_write(host, ATMEL_PDC_RNCR, (data->blksz & 0x3) ? sg->length : sg->length / 4);
Andrew Victor65dbf342006-04-02 19:18:51 +0100266 }
267 }
268
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100269 pr_debug("pre dma read done\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100270}
271
272/*
273 * Handle after a dma read
274 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200275static void at91_mci_post_dma_read(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100276{
277 struct mmc_command *cmd;
278 struct mmc_data *data;
279
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100280 pr_debug("post dma read\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100281
282 cmd = host->cmd;
283 if (!cmd) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100284 pr_debug("no command\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100285 return;
286 }
287
288 data = cmd->data;
289 if (!data) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100290 pr_debug("no data\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100291 return;
292 }
293
294 while (host->in_use_index < host->transfer_index) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100295 struct scatterlist *sg;
296
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100297 pr_debug("finishing index %d\n", host->in_use_index);
Andrew Victor65dbf342006-04-02 19:18:51 +0100298
299 sg = &data->sg[host->in_use_index++];
300
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100301 pr_debug("Unmapping page %08X\n", sg->dma_address);
Andrew Victor65dbf342006-04-02 19:18:51 +0100302
303 dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
304
Andrew Victor65dbf342006-04-02 19:18:51 +0100305 data->bytes_xfered += sg->length;
306
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100307 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
Nicolas Ferreed99c542007-07-09 14:58:16 +0200308 unsigned int *buffer;
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100309 int index;
Andrew Victor65dbf342006-04-02 19:18:51 +0100310
Nicolas Ferreed99c542007-07-09 14:58:16 +0200311 /* Swap the contents of the buffer */
Jens Axboe45711f12007-10-22 21:19:53 +0200312 buffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200313 pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
314
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100315 for (index = 0; index < (sg->length / 4); index++)
316 buffer[index] = swab32(buffer[index]);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200317
318 kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
Andrew Victor65dbf342006-04-02 19:18:51 +0100319 }
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100320
Jens Axboe45711f12007-10-22 21:19:53 +0200321 flush_dcache_page(sg_page(sg));
Andrew Victor65dbf342006-04-02 19:18:51 +0100322 }
323
324 /* Is there another transfer to trigger? */
325 if (host->transfer_index < data->sg_len)
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200326 at91_mci_pre_dma_read(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100327 else {
Nicolas Ferreed99c542007-07-09 14:58:16 +0200328 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
Andrew Victore0b19b82006-10-25 19:42:38 +0200329 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
Andrew Victor65dbf342006-04-02 19:18:51 +0100330 }
331
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100332 pr_debug("post dma read done\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100333}
334
335/*
336 * Handle transmitted data
337 */
338static void at91_mci_handle_transmitted(struct at91mci_host *host)
339{
340 struct mmc_command *cmd;
341 struct mmc_data *data;
342
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100343 pr_debug("Handling the transmit\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100344
345 /* Disable the transfer */
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100346 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100347
348 /* Now wait for cmd ready */
Andrew Victore0b19b82006-10-25 19:42:38 +0200349 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
Andrew Victor65dbf342006-04-02 19:18:51 +0100350
351 cmd = host->cmd;
352 if (!cmd) return;
353
354 data = cmd->data;
355 if (!data) return;
356
Pierre Ossmanbe0192a2007-07-24 21:11:47 +0200357 if (cmd->data->blocks > 1) {
Nicolas Ferreed99c542007-07-09 14:58:16 +0200358 pr_debug("multiple write : wait for BLKE...\n");
359 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
360 } else
361 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
362
Andrew Victor65dbf342006-04-02 19:18:51 +0100363 data->bytes_xfered = host->total_length;
364}
365
Nicolas Ferreed99c542007-07-09 14:58:16 +0200366/*Handle after command sent ready*/
367static int at91_mci_handle_cmdrdy(struct at91mci_host *host)
368{
369 if (!host->cmd)
370 return 1;
371 else if (!host->cmd->data) {
372 if (host->flags & FL_SENT_STOP) {
373 /*After multi block write, we must wait for NOTBUSY*/
374 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
375 } else return 1;
376 } else if (host->cmd->data->flags & MMC_DATA_WRITE) {
377 /*After sendding multi-block-write command, start DMA transfer*/
378 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE);
379 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
380 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
381 }
382
383 /* command not completed, have to wait */
384 return 0;
385}
386
387
Andrew Victor65dbf342006-04-02 19:18:51 +0100388/*
389 * Enable the controller
390 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200391static void at91_mci_enable(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100392{
Nicolas Ferreed99c542007-07-09 14:58:16 +0200393 unsigned int mr;
394
Andrew Victore0b19b82006-10-25 19:42:38 +0200395 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200396 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
Andrew Victore0b19b82006-10-25 19:42:38 +0200397 at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200398 mr = AT91_MCI_PDCMODE | 0x34a;
399
400 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
401 mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
402
403 at91_mci_write(host, AT91_MCI_MR, mr);
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100404
405 /* use Slot A or B (only one at same time) */
406 at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
Andrew Victor65dbf342006-04-02 19:18:51 +0100407}
408
409/*
410 * Disable the controller
411 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200412static void at91_mci_disable(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100413{
Andrew Victore0b19b82006-10-25 19:42:38 +0200414 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
Andrew Victor65dbf342006-04-02 19:18:51 +0100415}
416
417/*
418 * Send a command
Andrew Victor65dbf342006-04-02 19:18:51 +0100419 */
Nicolas Ferreed99c542007-07-09 14:58:16 +0200420static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
Andrew Victor65dbf342006-04-02 19:18:51 +0100421{
422 unsigned int cmdr, mr;
423 unsigned int block_length;
424 struct mmc_data *data = cmd->data;
425
426 unsigned int blocks;
427 unsigned int ier = 0;
428
429 host->cmd = cmd;
430
Nicolas Ferreed99c542007-07-09 14:58:16 +0200431 /* Needed for leaving busy state before CMD1 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200432 if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100433 pr_debug("Clearing timeout\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200434 at91_mci_write(host, AT91_MCI_ARGR, 0);
435 at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
436 while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100437 /* spin */
Andrew Victore0b19b82006-10-25 19:42:38 +0200438 pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
Andrew Victor65dbf342006-04-02 19:18:51 +0100439 }
440 }
Nicolas Ferreed99c542007-07-09 14:58:16 +0200441
Andrew Victor65dbf342006-04-02 19:18:51 +0100442 cmdr = cmd->opcode;
443
444 if (mmc_resp_type(cmd) == MMC_RSP_NONE)
445 cmdr |= AT91_MCI_RSPTYP_NONE;
446 else {
447 /* if a response is expected then allow maximum response latancy */
448 cmdr |= AT91_MCI_MAXLAT;
449 /* set 136 bit response for R2, 48 bit response otherwise */
450 if (mmc_resp_type(cmd) == MMC_RSP_R2)
451 cmdr |= AT91_MCI_RSPTYP_136;
452 else
453 cmdr |= AT91_MCI_RSPTYP_48;
454 }
455
456 if (data) {
Marc Pignat1d4de9e2007-08-09 13:56:29 +0200457
Marc Pignat80f92542008-05-30 14:05:24 +0200458 if ( cpu_is_at91rm9200() && (data->blksz & 0x3) ) {
Marc Pignat1d4de9e2007-08-09 13:56:29 +0200459 pr_debug("Unsupported block size\n");
460 cmd->error = -EINVAL;
461 mmc_request_done(host->mmc, host->request);
462 return;
463 }
464
Russell Kinga3fd4a12006-06-04 17:51:15 +0100465 block_length = data->blksz;
Andrew Victor65dbf342006-04-02 19:18:51 +0100466 blocks = data->blocks;
467
468 /* always set data start - also set direction flag for read */
469 if (data->flags & MMC_DATA_READ)
470 cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
471 else if (data->flags & MMC_DATA_WRITE)
472 cmdr |= AT91_MCI_TRCMD_START;
473
474 if (data->flags & MMC_DATA_STREAM)
475 cmdr |= AT91_MCI_TRTYP_STREAM;
Pierre Ossmanbe0192a2007-07-24 21:11:47 +0200476 if (data->blocks > 1)
Andrew Victor65dbf342006-04-02 19:18:51 +0100477 cmdr |= AT91_MCI_TRTYP_MULTIPLE;
478 }
479 else {
480 block_length = 0;
481 blocks = 0;
482 }
483
Marc Pignatb6cedb32007-06-06 20:27:59 +0200484 if (host->flags & FL_SENT_STOP)
Andrew Victor65dbf342006-04-02 19:18:51 +0100485 cmdr |= AT91_MCI_TRCMD_STOP;
486
487 if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
488 cmdr |= AT91_MCI_OPDCMD;
489
490 /*
491 * Set the arguments and send the command
492 */
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200493 pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
Andrew Victore0b19b82006-10-25 19:42:38 +0200494 cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
Andrew Victor65dbf342006-04-02 19:18:51 +0100495
496 if (!data) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100497 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
498 at91_mci_write(host, ATMEL_PDC_RPR, 0);
499 at91_mci_write(host, ATMEL_PDC_RCR, 0);
500 at91_mci_write(host, ATMEL_PDC_RNPR, 0);
501 at91_mci_write(host, ATMEL_PDC_RNCR, 0);
502 at91_mci_write(host, ATMEL_PDC_TPR, 0);
503 at91_mci_write(host, ATMEL_PDC_TCR, 0);
504 at91_mci_write(host, ATMEL_PDC_TNPR, 0);
505 at91_mci_write(host, ATMEL_PDC_TNCR, 0);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200506 ier = AT91_MCI_CMDRDY;
507 } else {
508 /* zero block length and PDC mode */
509 mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
Marc Pignat80f92542008-05-30 14:05:24 +0200510 mr |= (data->blksz & 0x3) ? AT91_MCI_PDCFBYTE : 0;
511 mr |= (block_length << 16);
512 mr |= AT91_MCI_PDCMODE;
513 at91_mci_write(host, AT91_MCI_MR, mr);
Andrew Victor65dbf342006-04-02 19:18:51 +0100514
Nicolas Ferreed99c542007-07-09 14:58:16 +0200515 /*
516 * Disable the PDC controller
517 */
518 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100519
Nicolas Ferreed99c542007-07-09 14:58:16 +0200520 if (cmdr & AT91_MCI_TRCMD_START) {
521 data->bytes_xfered = 0;
522 host->transfer_index = 0;
523 host->in_use_index = 0;
524 if (cmdr & AT91_MCI_TRDIR) {
525 /*
526 * Handle a read
527 */
528 host->buffer = NULL;
529 host->total_length = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100530
Nicolas Ferreed99c542007-07-09 14:58:16 +0200531 at91_mci_pre_dma_read(host);
532 ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
533 }
534 else {
535 /*
536 * Handle a write
537 */
538 host->total_length = block_length * blocks;
539 host->buffer = dma_alloc_coherent(NULL,
540 host->total_length,
541 &host->physical_address, GFP_KERNEL);
Andrew Victor65dbf342006-04-02 19:18:51 +0100542
Nicolas Ferreed99c542007-07-09 14:58:16 +0200543 at91_mci_sg_to_dma(host, data);
Andrew Victor65dbf342006-04-02 19:18:51 +0100544
Nicolas Ferreed99c542007-07-09 14:58:16 +0200545 pr_debug("Transmitting %d bytes\n", host->total_length);
Andrew Victor65dbf342006-04-02 19:18:51 +0100546
Nicolas Ferreed99c542007-07-09 14:58:16 +0200547 at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200548 at91_mci_write(host, ATMEL_PDC_TCR, (data->blksz & 0x3) ?
549 host->total_length : host->total_length / 4);
550
Nicolas Ferreed99c542007-07-09 14:58:16 +0200551 ier = AT91_MCI_CMDRDY;
552 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100553 }
554 }
555
556 /*
557 * Send the command and then enable the PDC - not the other way round as
558 * the data sheet says
559 */
560
Andrew Victore0b19b82006-10-25 19:42:38 +0200561 at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
562 at91_mci_write(host, AT91_MCI_CMDR, cmdr);
Andrew Victor65dbf342006-04-02 19:18:51 +0100563
564 if (cmdr & AT91_MCI_TRCMD_START) {
565 if (cmdr & AT91_MCI_TRDIR)
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100566 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
Andrew Victor65dbf342006-04-02 19:18:51 +0100567 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100568
Nicolas Ferreed99c542007-07-09 14:58:16 +0200569 /* Enable selected interrupts */
Andrew Victordf05a302006-10-23 14:50:09 +0200570 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
Andrew Victor65dbf342006-04-02 19:18:51 +0100571}
572
573/*
574 * Process the next step in the request
575 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200576static void at91_mci_process_next(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100577{
578 if (!(host->flags & FL_SENT_COMMAND)) {
579 host->flags |= FL_SENT_COMMAND;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200580 at91_mci_send_command(host, host->request->cmd);
Andrew Victor65dbf342006-04-02 19:18:51 +0100581 }
582 else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
583 host->flags |= FL_SENT_STOP;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200584 at91_mci_send_command(host, host->request->stop);
Marc Pignate181dce2008-05-30 14:06:32 +0200585 } else {
586 del_timer(&host->timer);
Andrew Victor65dbf342006-04-02 19:18:51 +0100587 mmc_request_done(host->mmc, host->request);
Marc Pignate181dce2008-05-30 14:06:32 +0200588 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100589}
590
591/*
592 * Handle a command that has been completed
593 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200594static void at91_mci_completed_command(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100595{
596 struct mmc_command *cmd = host->cmd;
597 unsigned int status;
598
Andrew Victore0b19b82006-10-25 19:42:38 +0200599 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
Andrew Victor65dbf342006-04-02 19:18:51 +0100600
Andrew Victore0b19b82006-10-25 19:42:38 +0200601 cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
602 cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
603 cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
604 cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
Andrew Victor65dbf342006-04-02 19:18:51 +0100605
606 if (host->buffer) {
607 dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address);
608 host->buffer = NULL;
609 }
610
Andrew Victore0b19b82006-10-25 19:42:38 +0200611 status = at91_mci_read(host, AT91_MCI_SR);
Andrew Victor65dbf342006-04-02 19:18:51 +0100612
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100613 pr_debug("Status = %08X [%08X %08X %08X %08X]\n",
Andrew Victor65dbf342006-04-02 19:18:51 +0100614 status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
615
Andrew Victor9e3866b2007-10-17 11:53:40 +0200616 if (status & AT91_MCI_ERRORS) {
Marc Pignatb6cedb32007-06-06 20:27:59 +0200617 if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
Pierre Ossman17b04292007-07-22 22:18:46 +0200618 cmd->error = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100619 }
620 else {
621 if (status & (AT91_MCI_RTOE | AT91_MCI_DTOE))
Pierre Ossman17b04292007-07-22 22:18:46 +0200622 cmd->error = -ETIMEDOUT;
Andrew Victor65dbf342006-04-02 19:18:51 +0100623 else if (status & (AT91_MCI_RCRCE | AT91_MCI_DCRCE))
Pierre Ossman17b04292007-07-22 22:18:46 +0200624 cmd->error = -EILSEQ;
Andrew Victor65dbf342006-04-02 19:18:51 +0100625 else
Pierre Ossman17b04292007-07-22 22:18:46 +0200626 cmd->error = -EIO;
Andrew Victor65dbf342006-04-02 19:18:51 +0100627
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100628 pr_debug("Error detected and set to %d (cmd = %d, retries = %d)\n",
Andrew Victor65dbf342006-04-02 19:18:51 +0100629 cmd->error, cmd->opcode, cmd->retries);
630 }
631 }
632 else
Pierre Ossman17b04292007-07-22 22:18:46 +0200633 cmd->error = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100634
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200635 at91_mci_process_next(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100636}
637
638/*
639 * Handle an MMC request
640 */
641static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
642{
643 struct at91mci_host *host = mmc_priv(mmc);
644 host->request = mrq;
645 host->flags = 0;
646
Marc Pignate181dce2008-05-30 14:06:32 +0200647 mod_timer(&host->timer, jiffies + HZ);
648
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200649 at91_mci_process_next(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100650}
651
652/*
653 * Set the IOS
654 */
655static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
656{
657 int clkdiv;
658 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor3dd3b032006-10-23 14:46:54 +0200659 unsigned long at91_master_clock = clk_get_rate(host->mci_clk);
Andrew Victor65dbf342006-04-02 19:18:51 +0100660
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100661 host->bus_mode = ios->bus_mode;
Andrew Victor65dbf342006-04-02 19:18:51 +0100662
663 if (ios->clock == 0) {
664 /* Disable the MCI controller */
Andrew Victore0b19b82006-10-25 19:42:38 +0200665 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100666 clkdiv = 0;
667 }
668 else {
669 /* Enable the MCI controller */
Andrew Victore0b19b82006-10-25 19:42:38 +0200670 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
Andrew Victor65dbf342006-04-02 19:18:51 +0100671
672 if ((at91_master_clock % (ios->clock * 2)) == 0)
673 clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
674 else
675 clkdiv = (at91_master_clock / ios->clock) / 2;
676
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100677 pr_debug("clkdiv = %d. mcck = %ld\n", clkdiv,
Andrew Victor65dbf342006-04-02 19:18:51 +0100678 at91_master_clock / (2 * (clkdiv + 1)));
679 }
680 if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100681 pr_debug("MMC: Setting controller bus width to 4\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200682 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100683 }
684 else {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100685 pr_debug("MMC: Setting controller bus width to 1\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200686 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100687 }
688
689 /* Set the clock divider */
Andrew Victore0b19b82006-10-25 19:42:38 +0200690 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 +0100691
692 /* maybe switch power to the card */
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100693 if (host->board->vcc_pin) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100694 switch (ios->power_mode) {
695 case MMC_POWER_OFF:
David Brownell6e996ee2008-02-04 18:12:48 +0100696 gpio_set_value(host->board->vcc_pin, 0);
Andrew Victor65dbf342006-04-02 19:18:51 +0100697 break;
698 case MMC_POWER_UP:
David Brownell6e996ee2008-02-04 18:12:48 +0100699 gpio_set_value(host->board->vcc_pin, 1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100700 break;
Marc Pignate5c0ef92008-05-09 11:07:07 +0200701 case MMC_POWER_ON:
702 break;
703 default:
704 WARN_ON(1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100705 }
706 }
707}
708
709/*
710 * Handle an interrupt
711 */
David Howells7d12e782006-10-05 14:55:46 +0100712static irqreturn_t at91_mci_irq(int irq, void *devid)
Andrew Victor65dbf342006-04-02 19:18:51 +0100713{
714 struct at91mci_host *host = devid;
715 int completed = 0;
Andrew Victordf05a302006-10-23 14:50:09 +0200716 unsigned int int_status, int_mask;
Andrew Victor65dbf342006-04-02 19:18:51 +0100717
Andrew Victore0b19b82006-10-25 19:42:38 +0200718 int_status = at91_mci_read(host, AT91_MCI_SR);
Andrew Victordf05a302006-10-23 14:50:09 +0200719 int_mask = at91_mci_read(host, AT91_MCI_IMR);
Nicolas Ferre37b758e2007-08-08 12:01:44 +0200720
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200721 pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask,
Andrew Victordf05a302006-10-23 14:50:09 +0200722 int_status & int_mask);
Nicolas Ferre37b758e2007-08-08 12:01:44 +0200723
Andrew Victordf05a302006-10-23 14:50:09 +0200724 int_status = int_status & int_mask;
Andrew Victor65dbf342006-04-02 19:18:51 +0100725
Andrew Victordf05a302006-10-23 14:50:09 +0200726 if (int_status & AT91_MCI_ERRORS) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100727 completed = 1;
Nicolas Ferre37b758e2007-08-08 12:01:44 +0200728
Andrew Victordf05a302006-10-23 14:50:09 +0200729 if (int_status & AT91_MCI_UNRE)
730 pr_debug("MMC: Underrun error\n");
731 if (int_status & AT91_MCI_OVRE)
732 pr_debug("MMC: Overrun error\n");
733 if (int_status & AT91_MCI_DTOE)
734 pr_debug("MMC: Data timeout\n");
735 if (int_status & AT91_MCI_DCRCE)
736 pr_debug("MMC: CRC error in data\n");
737 if (int_status & AT91_MCI_RTOE)
738 pr_debug("MMC: Response timeout\n");
739 if (int_status & AT91_MCI_RENDE)
740 pr_debug("MMC: Response end bit error\n");
741 if (int_status & AT91_MCI_RCRCE)
742 pr_debug("MMC: Response CRC error\n");
743 if (int_status & AT91_MCI_RDIRE)
744 pr_debug("MMC: Response direction error\n");
745 if (int_status & AT91_MCI_RINDE)
746 pr_debug("MMC: Response index error\n");
747 } else {
748 /* Only continue processing if no errors */
Andrew Victor65dbf342006-04-02 19:18:51 +0100749
Andrew Victor65dbf342006-04-02 19:18:51 +0100750 if (int_status & AT91_MCI_TXBUFE) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100751 pr_debug("TX buffer empty\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100752 at91_mci_handle_transmitted(host);
753 }
754
Nicolas Ferreed99c542007-07-09 14:58:16 +0200755 if (int_status & AT91_MCI_ENDRX) {
756 pr_debug("ENDRX\n");
757 at91_mci_post_dma_read(host);
758 }
759
Andrew Victor65dbf342006-04-02 19:18:51 +0100760 if (int_status & AT91_MCI_RXBUFF) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100761 pr_debug("RX buffer full\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200762 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
763 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_RXBUFF | AT91_MCI_ENDRX);
764 completed = 1;
Andrew Victor65dbf342006-04-02 19:18:51 +0100765 }
766
Andrew Victordf05a302006-10-23 14:50:09 +0200767 if (int_status & AT91_MCI_ENDTX)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100768 pr_debug("Transmit has ended\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100769
Andrew Victor65dbf342006-04-02 19:18:51 +0100770 if (int_status & AT91_MCI_NOTBUSY) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100771 pr_debug("Card is ready\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200772 completed = 1;
Andrew Victor65dbf342006-04-02 19:18:51 +0100773 }
774
Andrew Victordf05a302006-10-23 14:50:09 +0200775 if (int_status & AT91_MCI_DTIP)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100776 pr_debug("Data transfer in progress\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100777
Nicolas Ferreed99c542007-07-09 14:58:16 +0200778 if (int_status & AT91_MCI_BLKE) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100779 pr_debug("Block transfer has ended\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200780 completed = 1;
781 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100782
Andrew Victordf05a302006-10-23 14:50:09 +0200783 if (int_status & AT91_MCI_TXRDY)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100784 pr_debug("Ready to transmit\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100785
Andrew Victordf05a302006-10-23 14:50:09 +0200786 if (int_status & AT91_MCI_RXRDY)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100787 pr_debug("Ready to receive\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100788
789 if (int_status & AT91_MCI_CMDRDY) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100790 pr_debug("Command ready\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200791 completed = at91_mci_handle_cmdrdy(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100792 }
793 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100794
795 if (completed) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100796 pr_debug("Completed command\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200797 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200798 at91_mci_completed_command(host);
Andrew Victordf05a302006-10-23 14:50:09 +0200799 } else
800 at91_mci_write(host, AT91_MCI_IDR, int_status);
Andrew Victor65dbf342006-04-02 19:18:51 +0100801
802 return IRQ_HANDLED;
803}
804
David Howells7d12e782006-10-05 14:55:46 +0100805static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100806{
807 struct at91mci_host *host = _host;
David Brownell6e996ee2008-02-04 18:12:48 +0100808 int present = !gpio_get_value(irq_to_gpio(irq));
Andrew Victor65dbf342006-04-02 19:18:51 +0100809
810 /*
811 * we expect this irq on both insert and remove,
812 * and use a short delay to debounce.
813 */
814 if (present != host->present) {
815 host->present = present;
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100816 pr_debug("%s: card %s\n", mmc_hostname(host->mmc),
Andrew Victor65dbf342006-04-02 19:18:51 +0100817 present ? "insert" : "remove");
818 if (!present) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100819 pr_debug("****** Resetting SD-card bus width ******\n");
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100820 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100821 }
822 mmc_detect_change(host->mmc, msecs_to_jiffies(100));
823 }
824 return IRQ_HANDLED;
825}
826
David Brownella26b4982006-12-26 14:45:26 -0800827static int at91_mci_get_ro(struct mmc_host *mmc)
Andrew Victor65dbf342006-04-02 19:18:51 +0100828{
Andrew Victor65dbf342006-04-02 19:18:51 +0100829 struct at91mci_host *host = mmc_priv(mmc);
830
Anton Vorontsov08f80bb2008-06-17 18:17:39 +0400831 if (host->board->wp_pin)
832 return !!gpio_get_value(host->board->wp_pin);
833 /*
834 * Board doesn't support read only detection; let the mmc core
835 * decide what to do.
836 */
837 return -ENOSYS;
Andrew Victor65dbf342006-04-02 19:18:51 +0100838}
839
David Brownellab7aefd2006-11-12 17:55:30 -0800840static const struct mmc_host_ops at91_mci_ops = {
Andrew Victor65dbf342006-04-02 19:18:51 +0100841 .request = at91_mci_request,
842 .set_ios = at91_mci_set_ios,
843 .get_ro = at91_mci_get_ro,
844};
845
846/*
847 * Probe for the device
848 */
David Brownella26b4982006-12-26 14:45:26 -0800849static int __init at91_mci_probe(struct platform_device *pdev)
Andrew Victor65dbf342006-04-02 19:18:51 +0100850{
851 struct mmc_host *mmc;
852 struct at91mci_host *host;
Andrew Victor17ea0592006-10-23 14:44:40 +0200853 struct resource *res;
Andrew Victor65dbf342006-04-02 19:18:51 +0100854 int ret;
855
Andrew Victor17ea0592006-10-23 14:44:40 +0200856 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
857 if (!res)
858 return -ENXIO;
859
860 if (!request_mem_region(res->start, res->end - res->start + 1, DRIVER_NAME))
861 return -EBUSY;
862
Andrew Victor65dbf342006-04-02 19:18:51 +0100863 mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
864 if (!mmc) {
David Brownell6e996ee2008-02-04 18:12:48 +0100865 ret = -ENOMEM;
866 dev_dbg(&pdev->dev, "couldn't allocate mmc host\n");
867 goto fail6;
Andrew Victor65dbf342006-04-02 19:18:51 +0100868 }
869
870 mmc->ops = &at91_mci_ops;
871 mmc->f_min = 375000;
872 mmc->f_max = 25000000;
873 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
874
Pierre Ossmanfe4a3c72006-11-21 17:54:23 +0100875 mmc->max_blk_size = 4095;
Pierre Ossman55db8902006-11-21 17:55:45 +0100876 mmc->max_blk_count = mmc->max_req_size;
Pierre Ossmanfe4a3c72006-11-21 17:54:23 +0100877
Andrew Victor65dbf342006-04-02 19:18:51 +0100878 host = mmc_priv(mmc);
879 host->mmc = mmc;
880 host->buffer = NULL;
881 host->bus_mode = 0;
882 host->board = pdev->dev.platform_data;
883 if (host->board->wire4) {
Nicolas Ferreed99c542007-07-09 14:58:16 +0200884 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
885 mmc->caps |= MMC_CAP_4_BIT_DATA;
886 else
David Brownell6e996ee2008-02-04 18:12:48 +0100887 dev_warn(&pdev->dev, "4 wire bus mode not supported"
Nicolas Ferreed99c542007-07-09 14:58:16 +0200888 " - using 1 wire\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100889 }
890
891 /*
David Brownell6e996ee2008-02-04 18:12:48 +0100892 * Reserve GPIOs ... board init code makes sure these pins are set
893 * up as GPIOs with the right direction (input, except for vcc)
894 */
895 if (host->board->det_pin) {
896 ret = gpio_request(host->board->det_pin, "mmc_detect");
897 if (ret < 0) {
898 dev_dbg(&pdev->dev, "couldn't claim card detect pin\n");
899 goto fail5;
900 }
901 }
902 if (host->board->wp_pin) {
903 ret = gpio_request(host->board->wp_pin, "mmc_wp");
904 if (ret < 0) {
905 dev_dbg(&pdev->dev, "couldn't claim wp sense pin\n");
906 goto fail4;
907 }
908 }
909 if (host->board->vcc_pin) {
910 ret = gpio_request(host->board->vcc_pin, "mmc_vcc");
911 if (ret < 0) {
912 dev_dbg(&pdev->dev, "couldn't claim vcc switch pin\n");
913 goto fail3;
914 }
915 }
916
917 /*
Andrew Victor65dbf342006-04-02 19:18:51 +0100918 * Get Clock
919 */
Andrew Victor3dd3b032006-10-23 14:46:54 +0200920 host->mci_clk = clk_get(&pdev->dev, "mci_clk");
921 if (IS_ERR(host->mci_clk)) {
David Brownell6e996ee2008-02-04 18:12:48 +0100922 ret = -ENODEV;
923 dev_dbg(&pdev->dev, "no mci_clk?\n");
924 goto fail2;
Andrew Victor65dbf342006-04-02 19:18:51 +0100925 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100926
Andrew Victor17ea0592006-10-23 14:44:40 +0200927 /*
928 * Map I/O region
929 */
930 host->baseaddr = ioremap(res->start, res->end - res->start + 1);
931 if (!host->baseaddr) {
David Brownell6e996ee2008-02-04 18:12:48 +0100932 ret = -ENOMEM;
933 goto fail1;
Andrew Victor17ea0592006-10-23 14:44:40 +0200934 }
Andrew Victore0b19b82006-10-25 19:42:38 +0200935
936 /*
937 * Reset hardware
938 */
Andrew Victor3dd3b032006-10-23 14:46:54 +0200939 clk_enable(host->mci_clk); /* Enable the peripheral clock */
Andrew Victore0b19b82006-10-25 19:42:38 +0200940 at91_mci_disable(host);
941 at91_mci_enable(host);
942
Andrew Victor65dbf342006-04-02 19:18:51 +0100943 /*
944 * Allocate the MCI interrupt
945 */
Andrew Victor17ea0592006-10-23 14:44:40 +0200946 host->irq = platform_get_irq(pdev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +0100947 ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED,
948 mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100949 if (ret) {
David Brownell6e996ee2008-02-04 18:12:48 +0100950 dev_dbg(&pdev->dev, "request MCI interrupt failed\n");
951 goto fail0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100952 }
953
954 platform_set_drvdata(pdev, mmc);
955
956 /*
957 * Add host to MMC layer
958 */
Marc Pignat63b66432007-07-16 11:07:02 +0200959 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +0100960 host->present = !gpio_get_value(host->board->det_pin);
Marc Pignat63b66432007-07-16 11:07:02 +0200961 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100962 else
963 host->present = -1;
964
965 mmc_add_host(mmc);
966
Marc Pignate181dce2008-05-30 14:06:32 +0200967 setup_timer(&host->timer, at91_timeout_timer, (unsigned long)host);
968
Andrew Victor65dbf342006-04-02 19:18:51 +0100969 /*
970 * monitor card insertion/removal if we can
971 */
972 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +0100973 ret = request_irq(gpio_to_irq(host->board->det_pin),
974 at91_mmc_det_irq, 0, mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100975 if (ret)
David Brownell6e996ee2008-02-04 18:12:48 +0100976 dev_warn(&pdev->dev, "request MMC detect irq failed\n");
977 else
978 device_init_wakeup(&pdev->dev, 1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100979 }
980
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200981 pr_debug("Added MCI driver\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100982
983 return 0;
David Brownell6e996ee2008-02-04 18:12:48 +0100984
985fail0:
986 clk_disable(host->mci_clk);
987 iounmap(host->baseaddr);
988fail1:
989 clk_put(host->mci_clk);
990fail2:
991 if (host->board->vcc_pin)
992 gpio_free(host->board->vcc_pin);
993fail3:
994 if (host->board->wp_pin)
995 gpio_free(host->board->wp_pin);
996fail4:
997 if (host->board->det_pin)
998 gpio_free(host->board->det_pin);
999fail5:
1000 mmc_free_host(mmc);
1001fail6:
1002 release_mem_region(res->start, res->end - res->start + 1);
1003 dev_err(&pdev->dev, "probe failed, err %d\n", ret);
1004 return ret;
Andrew Victor65dbf342006-04-02 19:18:51 +01001005}
1006
1007/*
1008 * Remove a device
1009 */
David Brownella26b4982006-12-26 14:45:26 -08001010static int __exit at91_mci_remove(struct platform_device *pdev)
Andrew Victor65dbf342006-04-02 19:18:51 +01001011{
1012 struct mmc_host *mmc = platform_get_drvdata(pdev);
1013 struct at91mci_host *host;
Andrew Victor17ea0592006-10-23 14:44:40 +02001014 struct resource *res;
Andrew Victor65dbf342006-04-02 19:18:51 +01001015
1016 if (!mmc)
1017 return -1;
1018
1019 host = mmc_priv(mmc);
1020
Anti Sulline0cda542007-08-30 16:15:16 +02001021 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +01001022 if (device_can_wakeup(&pdev->dev))
1023 free_irq(gpio_to_irq(host->board->det_pin), host);
Marc Pignat63b66432007-07-16 11:07:02 +02001024 device_init_wakeup(&pdev->dev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +01001025 gpio_free(host->board->det_pin);
Andrew Victor65dbf342006-04-02 19:18:51 +01001026 }
1027
Andrew Victore0b19b82006-10-25 19:42:38 +02001028 at91_mci_disable(host);
Marc Pignate181dce2008-05-30 14:06:32 +02001029 del_timer_sync(&host->timer);
Andrew Victor17ea0592006-10-23 14:44:40 +02001030 mmc_remove_host(mmc);
1031 free_irq(host->irq, host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001032
Andrew Victor3dd3b032006-10-23 14:46:54 +02001033 clk_disable(host->mci_clk); /* Disable the peripheral clock */
1034 clk_put(host->mci_clk);
Andrew Victor65dbf342006-04-02 19:18:51 +01001035
David Brownell6e996ee2008-02-04 18:12:48 +01001036 if (host->board->vcc_pin)
1037 gpio_free(host->board->vcc_pin);
1038 if (host->board->wp_pin)
1039 gpio_free(host->board->wp_pin);
1040
Andrew Victor17ea0592006-10-23 14:44:40 +02001041 iounmap(host->baseaddr);
1042 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1043 release_mem_region(res->start, res->end - res->start + 1);
Andrew Victor65dbf342006-04-02 19:18:51 +01001044
Andrew Victor17ea0592006-10-23 14:44:40 +02001045 mmc_free_host(mmc);
1046 platform_set_drvdata(pdev, NULL);
Andrew Victorb44fb7a2006-06-19 13:06:05 +01001047 pr_debug("MCI Removed\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001048
1049 return 0;
1050}
1051
1052#ifdef CONFIG_PM
1053static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
1054{
1055 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001056 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001057 int ret = 0;
1058
Anti Sulline0cda542007-08-30 16:15:16 +02001059 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001060 enable_irq_wake(host->board->det_pin);
1061
Andrew Victor65dbf342006-04-02 19:18:51 +01001062 if (mmc)
1063 ret = mmc_suspend_host(mmc, state);
1064
1065 return ret;
1066}
1067
1068static int at91_mci_resume(struct platform_device *pdev)
1069{
1070 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001071 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001072 int ret = 0;
1073
Anti Sulline0cda542007-08-30 16:15:16 +02001074 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001075 disable_irq_wake(host->board->det_pin);
1076
Andrew Victor65dbf342006-04-02 19:18:51 +01001077 if (mmc)
1078 ret = mmc_resume_host(mmc);
1079
1080 return ret;
1081}
1082#else
1083#define at91_mci_suspend NULL
1084#define at91_mci_resume NULL
1085#endif
1086
1087static struct platform_driver at91_mci_driver = {
David Brownella26b4982006-12-26 14:45:26 -08001088 .remove = __exit_p(at91_mci_remove),
Andrew Victor65dbf342006-04-02 19:18:51 +01001089 .suspend = at91_mci_suspend,
1090 .resume = at91_mci_resume,
1091 .driver = {
1092 .name = DRIVER_NAME,
1093 .owner = THIS_MODULE,
1094 },
1095};
1096
1097static int __init at91_mci_init(void)
1098{
David Brownella26b4982006-12-26 14:45:26 -08001099 return platform_driver_probe(&at91_mci_driver, at91_mci_probe);
Andrew Victor65dbf342006-04-02 19:18:51 +01001100}
1101
1102static void __exit at91_mci_exit(void)
1103{
1104 platform_driver_unregister(&at91_mci_driver);
1105}
1106
1107module_init(at91_mci_init);
1108module_exit(at91_mci_exit);
1109
1110MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
1111MODULE_AUTHOR("Nick Randell");
1112MODULE_LICENSE("GPL");
Kay Sieversbc65c722008-04-15 14:34:28 -07001113MODULE_ALIAS("platform:at91_mci");