blob: e40340f32e35a131453cd1f3a92045c77ff532a6 [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;
128};
129
130/*
131 * Copy from sg to a dma block - used for transfers
132 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200133static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
Andrew Victor65dbf342006-04-02 19:18:51 +0100134{
135 unsigned int len, i, size;
136 unsigned *dmabuf = host->buffer;
137
138 size = host->total_length;
139 len = data->sg_len;
140
141 /*
142 * Just loop through all entries. Size might not
143 * be the entire list though so make sure that
144 * we do not transfer too much.
145 */
146 for (i = 0; i < len; i++) {
147 struct scatterlist *sg;
148 int amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100149 unsigned int *sgbuffer;
150
151 sg = &data->sg[i];
152
Jens Axboe45711f12007-10-22 21:19:53 +0200153 sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
Andrew Victor65dbf342006-04-02 19:18:51 +0100154 amount = min(size, sg->length);
155 size -= amount;
Andrew Victor65dbf342006-04-02 19:18:51 +0100156
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100157 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
158 int index;
159
160 for (index = 0; index < (amount / 4); index++)
161 *dmabuf++ = swab32(sgbuffer[index]);
162 }
163 else
164 memcpy(dmabuf, sgbuffer, amount);
Andrew Victor65dbf342006-04-02 19:18:51 +0100165
166 kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
167
168 if (size == 0)
169 break;
170 }
171
172 /*
173 * Check that we didn't get a request to transfer
174 * more data than can fit into the SG list.
175 */
176 BUG_ON(size != 0);
177}
178
179/*
180 * Prepare a dma read
181 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200182static void at91_mci_pre_dma_read(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100183{
184 int i;
185 struct scatterlist *sg;
186 struct mmc_command *cmd;
187 struct mmc_data *data;
188
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100189 pr_debug("pre dma read\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100190
191 cmd = host->cmd;
192 if (!cmd) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100193 pr_debug("no command\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100194 return;
195 }
196
197 data = cmd->data;
198 if (!data) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100199 pr_debug("no data\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100200 return;
201 }
202
203 for (i = 0; i < 2; i++) {
204 /* nothing left to transfer */
205 if (host->transfer_index >= data->sg_len) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100206 pr_debug("Nothing left to transfer (index = %d)\n", host->transfer_index);
Andrew Victor65dbf342006-04-02 19:18:51 +0100207 break;
208 }
209
210 /* Check to see if this needs filling */
211 if (i == 0) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100212 if (at91_mci_read(host, ATMEL_PDC_RCR) != 0) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100213 pr_debug("Transfer active in current\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100214 continue;
215 }
216 }
217 else {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100218 if (at91_mci_read(host, ATMEL_PDC_RNCR) != 0) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100219 pr_debug("Transfer active in next\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100220 continue;
221 }
222 }
223
224 /* Setup the next transfer */
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100225 pr_debug("Using transfer index %d\n", host->transfer_index);
Andrew Victor65dbf342006-04-02 19:18:51 +0100226
227 sg = &data->sg[host->transfer_index++];
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100228 pr_debug("sg = %p\n", sg);
Andrew Victor65dbf342006-04-02 19:18:51 +0100229
Jens Axboe45711f12007-10-22 21:19:53 +0200230 sg->dma_address = dma_map_page(NULL, sg_page(sg), sg->offset, sg->length, DMA_FROM_DEVICE);
Andrew Victor65dbf342006-04-02 19:18:51 +0100231
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100232 pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
Andrew Victor65dbf342006-04-02 19:18:51 +0100233
234 if (i == 0) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100235 at91_mci_write(host, ATMEL_PDC_RPR, sg->dma_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200236 at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ? sg->length : sg->length / 4);
Andrew Victor65dbf342006-04-02 19:18:51 +0100237 }
238 else {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100239 at91_mci_write(host, ATMEL_PDC_RNPR, sg->dma_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200240 at91_mci_write(host, ATMEL_PDC_RNCR, (data->blksz & 0x3) ? sg->length : sg->length / 4);
Andrew Victor65dbf342006-04-02 19:18:51 +0100241 }
242 }
243
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100244 pr_debug("pre dma read done\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100245}
246
247/*
248 * Handle after a dma read
249 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200250static void at91_mci_post_dma_read(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100251{
252 struct mmc_command *cmd;
253 struct mmc_data *data;
254
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100255 pr_debug("post dma read\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100256
257 cmd = host->cmd;
258 if (!cmd) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100259 pr_debug("no command\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100260 return;
261 }
262
263 data = cmd->data;
264 if (!data) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100265 pr_debug("no data\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100266 return;
267 }
268
269 while (host->in_use_index < host->transfer_index) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100270 struct scatterlist *sg;
271
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100272 pr_debug("finishing index %d\n", host->in_use_index);
Andrew Victor65dbf342006-04-02 19:18:51 +0100273
274 sg = &data->sg[host->in_use_index++];
275
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100276 pr_debug("Unmapping page %08X\n", sg->dma_address);
Andrew Victor65dbf342006-04-02 19:18:51 +0100277
278 dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
279
Andrew Victor65dbf342006-04-02 19:18:51 +0100280 data->bytes_xfered += sg->length;
281
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100282 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
Nicolas Ferreed99c542007-07-09 14:58:16 +0200283 unsigned int *buffer;
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100284 int index;
Andrew Victor65dbf342006-04-02 19:18:51 +0100285
Nicolas Ferreed99c542007-07-09 14:58:16 +0200286 /* Swap the contents of the buffer */
Jens Axboe45711f12007-10-22 21:19:53 +0200287 buffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200288 pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
289
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100290 for (index = 0; index < (sg->length / 4); index++)
291 buffer[index] = swab32(buffer[index]);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200292
293 kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
Andrew Victor65dbf342006-04-02 19:18:51 +0100294 }
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100295
Jens Axboe45711f12007-10-22 21:19:53 +0200296 flush_dcache_page(sg_page(sg));
Andrew Victor65dbf342006-04-02 19:18:51 +0100297 }
298
299 /* Is there another transfer to trigger? */
300 if (host->transfer_index < data->sg_len)
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200301 at91_mci_pre_dma_read(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100302 else {
Nicolas Ferreed99c542007-07-09 14:58:16 +0200303 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
Andrew Victore0b19b82006-10-25 19:42:38 +0200304 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
Andrew Victor65dbf342006-04-02 19:18:51 +0100305 }
306
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100307 pr_debug("post dma read done\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100308}
309
310/*
311 * Handle transmitted data
312 */
313static void at91_mci_handle_transmitted(struct at91mci_host *host)
314{
315 struct mmc_command *cmd;
316 struct mmc_data *data;
317
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100318 pr_debug("Handling the transmit\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100319
320 /* Disable the transfer */
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100321 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100322
323 /* Now wait for cmd ready */
Andrew Victore0b19b82006-10-25 19:42:38 +0200324 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
Andrew Victor65dbf342006-04-02 19:18:51 +0100325
326 cmd = host->cmd;
327 if (!cmd) return;
328
329 data = cmd->data;
330 if (!data) return;
331
Pierre Ossmanbe0192a2007-07-24 21:11:47 +0200332 if (cmd->data->blocks > 1) {
Nicolas Ferreed99c542007-07-09 14:58:16 +0200333 pr_debug("multiple write : wait for BLKE...\n");
334 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
335 } else
336 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
337
Andrew Victor65dbf342006-04-02 19:18:51 +0100338 data->bytes_xfered = host->total_length;
339}
340
Nicolas Ferreed99c542007-07-09 14:58:16 +0200341/*Handle after command sent ready*/
342static int at91_mci_handle_cmdrdy(struct at91mci_host *host)
343{
344 if (!host->cmd)
345 return 1;
346 else if (!host->cmd->data) {
347 if (host->flags & FL_SENT_STOP) {
348 /*After multi block write, we must wait for NOTBUSY*/
349 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
350 } else return 1;
351 } else if (host->cmd->data->flags & MMC_DATA_WRITE) {
352 /*After sendding multi-block-write command, start DMA transfer*/
353 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE);
354 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
355 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
356 }
357
358 /* command not completed, have to wait */
359 return 0;
360}
361
362
Andrew Victor65dbf342006-04-02 19:18:51 +0100363/*
364 * Enable the controller
365 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200366static void at91_mci_enable(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100367{
Nicolas Ferreed99c542007-07-09 14:58:16 +0200368 unsigned int mr;
369
Andrew Victore0b19b82006-10-25 19:42:38 +0200370 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200371 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
Andrew Victore0b19b82006-10-25 19:42:38 +0200372 at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200373 mr = AT91_MCI_PDCMODE | 0x34a;
374
375 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
376 mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
377
378 at91_mci_write(host, AT91_MCI_MR, mr);
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100379
380 /* use Slot A or B (only one at same time) */
381 at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
Andrew Victor65dbf342006-04-02 19:18:51 +0100382}
383
384/*
385 * Disable the controller
386 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200387static void at91_mci_disable(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100388{
Andrew Victore0b19b82006-10-25 19:42:38 +0200389 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
Andrew Victor65dbf342006-04-02 19:18:51 +0100390}
391
392/*
393 * Send a command
Andrew Victor65dbf342006-04-02 19:18:51 +0100394 */
Nicolas Ferreed99c542007-07-09 14:58:16 +0200395static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
Andrew Victor65dbf342006-04-02 19:18:51 +0100396{
397 unsigned int cmdr, mr;
398 unsigned int block_length;
399 struct mmc_data *data = cmd->data;
400
401 unsigned int blocks;
402 unsigned int ier = 0;
403
404 host->cmd = cmd;
405
Nicolas Ferreed99c542007-07-09 14:58:16 +0200406 /* Needed for leaving busy state before CMD1 */
Andrew Victore0b19b82006-10-25 19:42:38 +0200407 if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100408 pr_debug("Clearing timeout\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200409 at91_mci_write(host, AT91_MCI_ARGR, 0);
410 at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
411 while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100412 /* spin */
Andrew Victore0b19b82006-10-25 19:42:38 +0200413 pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
Andrew Victor65dbf342006-04-02 19:18:51 +0100414 }
415 }
Nicolas Ferreed99c542007-07-09 14:58:16 +0200416
Andrew Victor65dbf342006-04-02 19:18:51 +0100417 cmdr = cmd->opcode;
418
419 if (mmc_resp_type(cmd) == MMC_RSP_NONE)
420 cmdr |= AT91_MCI_RSPTYP_NONE;
421 else {
422 /* if a response is expected then allow maximum response latancy */
423 cmdr |= AT91_MCI_MAXLAT;
424 /* set 136 bit response for R2, 48 bit response otherwise */
425 if (mmc_resp_type(cmd) == MMC_RSP_R2)
426 cmdr |= AT91_MCI_RSPTYP_136;
427 else
428 cmdr |= AT91_MCI_RSPTYP_48;
429 }
430
431 if (data) {
Marc Pignat1d4de9e2007-08-09 13:56:29 +0200432
Marc Pignat80f92542008-05-30 14:05:24 +0200433 if ( cpu_is_at91rm9200() && (data->blksz & 0x3) ) {
Marc Pignat1d4de9e2007-08-09 13:56:29 +0200434 pr_debug("Unsupported block size\n");
435 cmd->error = -EINVAL;
436 mmc_request_done(host->mmc, host->request);
437 return;
438 }
439
Russell Kinga3fd4a12006-06-04 17:51:15 +0100440 block_length = data->blksz;
Andrew Victor65dbf342006-04-02 19:18:51 +0100441 blocks = data->blocks;
442
443 /* always set data start - also set direction flag for read */
444 if (data->flags & MMC_DATA_READ)
445 cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
446 else if (data->flags & MMC_DATA_WRITE)
447 cmdr |= AT91_MCI_TRCMD_START;
448
449 if (data->flags & MMC_DATA_STREAM)
450 cmdr |= AT91_MCI_TRTYP_STREAM;
Pierre Ossmanbe0192a2007-07-24 21:11:47 +0200451 if (data->blocks > 1)
Andrew Victor65dbf342006-04-02 19:18:51 +0100452 cmdr |= AT91_MCI_TRTYP_MULTIPLE;
453 }
454 else {
455 block_length = 0;
456 blocks = 0;
457 }
458
Marc Pignatb6cedb32007-06-06 20:27:59 +0200459 if (host->flags & FL_SENT_STOP)
Andrew Victor65dbf342006-04-02 19:18:51 +0100460 cmdr |= AT91_MCI_TRCMD_STOP;
461
462 if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
463 cmdr |= AT91_MCI_OPDCMD;
464
465 /*
466 * Set the arguments and send the command
467 */
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200468 pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
Andrew Victore0b19b82006-10-25 19:42:38 +0200469 cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
Andrew Victor65dbf342006-04-02 19:18:51 +0100470
471 if (!data) {
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100472 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
473 at91_mci_write(host, ATMEL_PDC_RPR, 0);
474 at91_mci_write(host, ATMEL_PDC_RCR, 0);
475 at91_mci_write(host, ATMEL_PDC_RNPR, 0);
476 at91_mci_write(host, ATMEL_PDC_RNCR, 0);
477 at91_mci_write(host, ATMEL_PDC_TPR, 0);
478 at91_mci_write(host, ATMEL_PDC_TCR, 0);
479 at91_mci_write(host, ATMEL_PDC_TNPR, 0);
480 at91_mci_write(host, ATMEL_PDC_TNCR, 0);
Nicolas Ferreed99c542007-07-09 14:58:16 +0200481 ier = AT91_MCI_CMDRDY;
482 } else {
483 /* zero block length and PDC mode */
484 mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
Marc Pignat80f92542008-05-30 14:05:24 +0200485 mr |= (data->blksz & 0x3) ? AT91_MCI_PDCFBYTE : 0;
486 mr |= (block_length << 16);
487 mr |= AT91_MCI_PDCMODE;
488 at91_mci_write(host, AT91_MCI_MR, mr);
Andrew Victor65dbf342006-04-02 19:18:51 +0100489
Nicolas Ferreed99c542007-07-09 14:58:16 +0200490 /*
491 * Disable the PDC controller
492 */
493 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100494
Nicolas Ferreed99c542007-07-09 14:58:16 +0200495 if (cmdr & AT91_MCI_TRCMD_START) {
496 data->bytes_xfered = 0;
497 host->transfer_index = 0;
498 host->in_use_index = 0;
499 if (cmdr & AT91_MCI_TRDIR) {
500 /*
501 * Handle a read
502 */
503 host->buffer = NULL;
504 host->total_length = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100505
Nicolas Ferreed99c542007-07-09 14:58:16 +0200506 at91_mci_pre_dma_read(host);
507 ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
508 }
509 else {
510 /*
511 * Handle a write
512 */
513 host->total_length = block_length * blocks;
514 host->buffer = dma_alloc_coherent(NULL,
515 host->total_length,
516 &host->physical_address, GFP_KERNEL);
Andrew Victor65dbf342006-04-02 19:18:51 +0100517
Nicolas Ferreed99c542007-07-09 14:58:16 +0200518 at91_mci_sg_to_dma(host, data);
Andrew Victor65dbf342006-04-02 19:18:51 +0100519
Nicolas Ferreed99c542007-07-09 14:58:16 +0200520 pr_debug("Transmitting %d bytes\n", host->total_length);
Andrew Victor65dbf342006-04-02 19:18:51 +0100521
Nicolas Ferreed99c542007-07-09 14:58:16 +0200522 at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
Marc Pignat80f92542008-05-30 14:05:24 +0200523 at91_mci_write(host, ATMEL_PDC_TCR, (data->blksz & 0x3) ?
524 host->total_length : host->total_length / 4);
525
Nicolas Ferreed99c542007-07-09 14:58:16 +0200526 ier = AT91_MCI_CMDRDY;
527 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100528 }
529 }
530
531 /*
532 * Send the command and then enable the PDC - not the other way round as
533 * the data sheet says
534 */
535
Andrew Victore0b19b82006-10-25 19:42:38 +0200536 at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
537 at91_mci_write(host, AT91_MCI_CMDR, cmdr);
Andrew Victor65dbf342006-04-02 19:18:51 +0100538
539 if (cmdr & AT91_MCI_TRCMD_START) {
540 if (cmdr & AT91_MCI_TRDIR)
Andrew Victor93a3ddc2007-02-08 11:31:22 +0100541 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
Andrew Victor65dbf342006-04-02 19:18:51 +0100542 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100543
Nicolas Ferreed99c542007-07-09 14:58:16 +0200544 /* Enable selected interrupts */
Andrew Victordf05a302006-10-23 14:50:09 +0200545 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
Andrew Victor65dbf342006-04-02 19:18:51 +0100546}
547
548/*
549 * Process the next step in the request
550 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200551static void at91_mci_process_next(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100552{
553 if (!(host->flags & FL_SENT_COMMAND)) {
554 host->flags |= FL_SENT_COMMAND;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200555 at91_mci_send_command(host, host->request->cmd);
Andrew Victor65dbf342006-04-02 19:18:51 +0100556 }
557 else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
558 host->flags |= FL_SENT_STOP;
Nicolas Ferreed99c542007-07-09 14:58:16 +0200559 at91_mci_send_command(host, host->request->stop);
Andrew Victor65dbf342006-04-02 19:18:51 +0100560 }
561 else
562 mmc_request_done(host->mmc, host->request);
563}
564
565/*
566 * Handle a command that has been completed
567 */
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200568static void at91_mci_completed_command(struct at91mci_host *host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100569{
570 struct mmc_command *cmd = host->cmd;
571 unsigned int status;
572
Andrew Victore0b19b82006-10-25 19:42:38 +0200573 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
Andrew Victor65dbf342006-04-02 19:18:51 +0100574
Andrew Victore0b19b82006-10-25 19:42:38 +0200575 cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
576 cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
577 cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
578 cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
Andrew Victor65dbf342006-04-02 19:18:51 +0100579
580 if (host->buffer) {
581 dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address);
582 host->buffer = NULL;
583 }
584
Andrew Victore0b19b82006-10-25 19:42:38 +0200585 status = at91_mci_read(host, AT91_MCI_SR);
Andrew Victor65dbf342006-04-02 19:18:51 +0100586
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100587 pr_debug("Status = %08X [%08X %08X %08X %08X]\n",
Andrew Victor65dbf342006-04-02 19:18:51 +0100588 status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
589
Andrew Victor9e3866b2007-10-17 11:53:40 +0200590 if (status & AT91_MCI_ERRORS) {
Marc Pignatb6cedb32007-06-06 20:27:59 +0200591 if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
Pierre Ossman17b04292007-07-22 22:18:46 +0200592 cmd->error = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100593 }
594 else {
595 if (status & (AT91_MCI_RTOE | AT91_MCI_DTOE))
Pierre Ossman17b04292007-07-22 22:18:46 +0200596 cmd->error = -ETIMEDOUT;
Andrew Victor65dbf342006-04-02 19:18:51 +0100597 else if (status & (AT91_MCI_RCRCE | AT91_MCI_DCRCE))
Pierre Ossman17b04292007-07-22 22:18:46 +0200598 cmd->error = -EILSEQ;
Andrew Victor65dbf342006-04-02 19:18:51 +0100599 else
Pierre Ossman17b04292007-07-22 22:18:46 +0200600 cmd->error = -EIO;
Andrew Victor65dbf342006-04-02 19:18:51 +0100601
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100602 pr_debug("Error detected and set to %d (cmd = %d, retries = %d)\n",
Andrew Victor65dbf342006-04-02 19:18:51 +0100603 cmd->error, cmd->opcode, cmd->retries);
604 }
605 }
606 else
Pierre Ossman17b04292007-07-22 22:18:46 +0200607 cmd->error = 0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100608
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200609 at91_mci_process_next(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100610}
611
612/*
613 * Handle an MMC request
614 */
615static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
616{
617 struct at91mci_host *host = mmc_priv(mmc);
618 host->request = mrq;
619 host->flags = 0;
620
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200621 at91_mci_process_next(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100622}
623
624/*
625 * Set the IOS
626 */
627static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
628{
629 int clkdiv;
630 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor3dd3b032006-10-23 14:46:54 +0200631 unsigned long at91_master_clock = clk_get_rate(host->mci_clk);
Andrew Victor65dbf342006-04-02 19:18:51 +0100632
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100633 host->bus_mode = ios->bus_mode;
Andrew Victor65dbf342006-04-02 19:18:51 +0100634
635 if (ios->clock == 0) {
636 /* Disable the MCI controller */
Andrew Victore0b19b82006-10-25 19:42:38 +0200637 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100638 clkdiv = 0;
639 }
640 else {
641 /* Enable the MCI controller */
Andrew Victore0b19b82006-10-25 19:42:38 +0200642 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
Andrew Victor65dbf342006-04-02 19:18:51 +0100643
644 if ((at91_master_clock % (ios->clock * 2)) == 0)
645 clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
646 else
647 clkdiv = (at91_master_clock / ios->clock) / 2;
648
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100649 pr_debug("clkdiv = %d. mcck = %ld\n", clkdiv,
Andrew Victor65dbf342006-04-02 19:18:51 +0100650 at91_master_clock / (2 * (clkdiv + 1)));
651 }
652 if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100653 pr_debug("MMC: Setting controller bus width to 4\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200654 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100655 }
656 else {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100657 pr_debug("MMC: Setting controller bus width to 1\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200658 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100659 }
660
661 /* Set the clock divider */
Andrew Victore0b19b82006-10-25 19:42:38 +0200662 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 +0100663
664 /* maybe switch power to the card */
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100665 if (host->board->vcc_pin) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100666 switch (ios->power_mode) {
667 case MMC_POWER_OFF:
David Brownell6e996ee2008-02-04 18:12:48 +0100668 gpio_set_value(host->board->vcc_pin, 0);
Andrew Victor65dbf342006-04-02 19:18:51 +0100669 break;
670 case MMC_POWER_UP:
David Brownell6e996ee2008-02-04 18:12:48 +0100671 gpio_set_value(host->board->vcc_pin, 1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100672 break;
Marc Pignate5c0ef92008-05-09 11:07:07 +0200673 case MMC_POWER_ON:
674 break;
675 default:
676 WARN_ON(1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100677 }
678 }
679}
680
681/*
682 * Handle an interrupt
683 */
David Howells7d12e782006-10-05 14:55:46 +0100684static irqreturn_t at91_mci_irq(int irq, void *devid)
Andrew Victor65dbf342006-04-02 19:18:51 +0100685{
686 struct at91mci_host *host = devid;
687 int completed = 0;
Andrew Victordf05a302006-10-23 14:50:09 +0200688 unsigned int int_status, int_mask;
Andrew Victor65dbf342006-04-02 19:18:51 +0100689
Andrew Victore0b19b82006-10-25 19:42:38 +0200690 int_status = at91_mci_read(host, AT91_MCI_SR);
Andrew Victordf05a302006-10-23 14:50:09 +0200691 int_mask = at91_mci_read(host, AT91_MCI_IMR);
Nicolas Ferre37b758e2007-08-08 12:01:44 +0200692
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200693 pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask,
Andrew Victordf05a302006-10-23 14:50:09 +0200694 int_status & int_mask);
Nicolas Ferre37b758e2007-08-08 12:01:44 +0200695
Andrew Victordf05a302006-10-23 14:50:09 +0200696 int_status = int_status & int_mask;
Andrew Victor65dbf342006-04-02 19:18:51 +0100697
Andrew Victordf05a302006-10-23 14:50:09 +0200698 if (int_status & AT91_MCI_ERRORS) {
Andrew Victor65dbf342006-04-02 19:18:51 +0100699 completed = 1;
Nicolas Ferre37b758e2007-08-08 12:01:44 +0200700
Andrew Victordf05a302006-10-23 14:50:09 +0200701 if (int_status & AT91_MCI_UNRE)
702 pr_debug("MMC: Underrun error\n");
703 if (int_status & AT91_MCI_OVRE)
704 pr_debug("MMC: Overrun error\n");
705 if (int_status & AT91_MCI_DTOE)
706 pr_debug("MMC: Data timeout\n");
707 if (int_status & AT91_MCI_DCRCE)
708 pr_debug("MMC: CRC error in data\n");
709 if (int_status & AT91_MCI_RTOE)
710 pr_debug("MMC: Response timeout\n");
711 if (int_status & AT91_MCI_RENDE)
712 pr_debug("MMC: Response end bit error\n");
713 if (int_status & AT91_MCI_RCRCE)
714 pr_debug("MMC: Response CRC error\n");
715 if (int_status & AT91_MCI_RDIRE)
716 pr_debug("MMC: Response direction error\n");
717 if (int_status & AT91_MCI_RINDE)
718 pr_debug("MMC: Response index error\n");
719 } else {
720 /* Only continue processing if no errors */
Andrew Victor65dbf342006-04-02 19:18:51 +0100721
Andrew Victor65dbf342006-04-02 19:18:51 +0100722 if (int_status & AT91_MCI_TXBUFE) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100723 pr_debug("TX buffer empty\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100724 at91_mci_handle_transmitted(host);
725 }
726
Nicolas Ferreed99c542007-07-09 14:58:16 +0200727 if (int_status & AT91_MCI_ENDRX) {
728 pr_debug("ENDRX\n");
729 at91_mci_post_dma_read(host);
730 }
731
Andrew Victor65dbf342006-04-02 19:18:51 +0100732 if (int_status & AT91_MCI_RXBUFF) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100733 pr_debug("RX buffer full\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200734 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
735 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_RXBUFF | AT91_MCI_ENDRX);
736 completed = 1;
Andrew Victor65dbf342006-04-02 19:18:51 +0100737 }
738
Andrew Victordf05a302006-10-23 14:50:09 +0200739 if (int_status & AT91_MCI_ENDTX)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100740 pr_debug("Transmit has ended\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100741
Andrew Victor65dbf342006-04-02 19:18:51 +0100742 if (int_status & AT91_MCI_NOTBUSY) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100743 pr_debug("Card is ready\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200744 completed = 1;
Andrew Victor65dbf342006-04-02 19:18:51 +0100745 }
746
Andrew Victordf05a302006-10-23 14:50:09 +0200747 if (int_status & AT91_MCI_DTIP)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100748 pr_debug("Data transfer in progress\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100749
Nicolas Ferreed99c542007-07-09 14:58:16 +0200750 if (int_status & AT91_MCI_BLKE) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100751 pr_debug("Block transfer has ended\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200752 completed = 1;
753 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100754
Andrew Victordf05a302006-10-23 14:50:09 +0200755 if (int_status & AT91_MCI_TXRDY)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100756 pr_debug("Ready to transmit\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100757
Andrew Victordf05a302006-10-23 14:50:09 +0200758 if (int_status & AT91_MCI_RXRDY)
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100759 pr_debug("Ready to receive\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100760
761 if (int_status & AT91_MCI_CMDRDY) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100762 pr_debug("Command ready\n");
Nicolas Ferreed99c542007-07-09 14:58:16 +0200763 completed = at91_mci_handle_cmdrdy(host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100764 }
765 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100766
767 if (completed) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100768 pr_debug("Completed command\n");
Andrew Victore0b19b82006-10-25 19:42:38 +0200769 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
Nicolas Ferree8d04d32007-06-19 18:32:34 +0200770 at91_mci_completed_command(host);
Andrew Victordf05a302006-10-23 14:50:09 +0200771 } else
772 at91_mci_write(host, AT91_MCI_IDR, int_status);
Andrew Victor65dbf342006-04-02 19:18:51 +0100773
774 return IRQ_HANDLED;
775}
776
David Howells7d12e782006-10-05 14:55:46 +0100777static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
Andrew Victor65dbf342006-04-02 19:18:51 +0100778{
779 struct at91mci_host *host = _host;
David Brownell6e996ee2008-02-04 18:12:48 +0100780 int present = !gpio_get_value(irq_to_gpio(irq));
Andrew Victor65dbf342006-04-02 19:18:51 +0100781
782 /*
783 * we expect this irq on both insert and remove,
784 * and use a short delay to debounce.
785 */
786 if (present != host->present) {
787 host->present = present;
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100788 pr_debug("%s: card %s\n", mmc_hostname(host->mmc),
Andrew Victor65dbf342006-04-02 19:18:51 +0100789 present ? "insert" : "remove");
790 if (!present) {
Andrew Victorb44fb7a2006-06-19 13:06:05 +0100791 pr_debug("****** Resetting SD-card bus width ******\n");
Andrew Victor99eeb8d2006-12-11 12:40:23 +0100792 at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
Andrew Victor65dbf342006-04-02 19:18:51 +0100793 }
794 mmc_detect_change(host->mmc, msecs_to_jiffies(100));
795 }
796 return IRQ_HANDLED;
797}
798
David Brownella26b4982006-12-26 14:45:26 -0800799static int at91_mci_get_ro(struct mmc_host *mmc)
Andrew Victor65dbf342006-04-02 19:18:51 +0100800{
Andrew Victor65dbf342006-04-02 19:18:51 +0100801 struct at91mci_host *host = mmc_priv(mmc);
802
Anton Vorontsov08f80bb2008-06-17 18:17:39 +0400803 if (host->board->wp_pin)
804 return !!gpio_get_value(host->board->wp_pin);
805 /*
806 * Board doesn't support read only detection; let the mmc core
807 * decide what to do.
808 */
809 return -ENOSYS;
Andrew Victor65dbf342006-04-02 19:18:51 +0100810}
811
David Brownellab7aefd2006-11-12 17:55:30 -0800812static const struct mmc_host_ops at91_mci_ops = {
Andrew Victor65dbf342006-04-02 19:18:51 +0100813 .request = at91_mci_request,
814 .set_ios = at91_mci_set_ios,
815 .get_ro = at91_mci_get_ro,
816};
817
818/*
819 * Probe for the device
820 */
David Brownella26b4982006-12-26 14:45:26 -0800821static int __init at91_mci_probe(struct platform_device *pdev)
Andrew Victor65dbf342006-04-02 19:18:51 +0100822{
823 struct mmc_host *mmc;
824 struct at91mci_host *host;
Andrew Victor17ea0592006-10-23 14:44:40 +0200825 struct resource *res;
Andrew Victor65dbf342006-04-02 19:18:51 +0100826 int ret;
827
Andrew Victor17ea0592006-10-23 14:44:40 +0200828 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
829 if (!res)
830 return -ENXIO;
831
832 if (!request_mem_region(res->start, res->end - res->start + 1, DRIVER_NAME))
833 return -EBUSY;
834
Andrew Victor65dbf342006-04-02 19:18:51 +0100835 mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
836 if (!mmc) {
David Brownell6e996ee2008-02-04 18:12:48 +0100837 ret = -ENOMEM;
838 dev_dbg(&pdev->dev, "couldn't allocate mmc host\n");
839 goto fail6;
Andrew Victor65dbf342006-04-02 19:18:51 +0100840 }
841
842 mmc->ops = &at91_mci_ops;
843 mmc->f_min = 375000;
844 mmc->f_max = 25000000;
845 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
846
Pierre Ossmanfe4a3c72006-11-21 17:54:23 +0100847 mmc->max_blk_size = 4095;
Pierre Ossman55db8902006-11-21 17:55:45 +0100848 mmc->max_blk_count = mmc->max_req_size;
Pierre Ossmanfe4a3c72006-11-21 17:54:23 +0100849
Andrew Victor65dbf342006-04-02 19:18:51 +0100850 host = mmc_priv(mmc);
851 host->mmc = mmc;
852 host->buffer = NULL;
853 host->bus_mode = 0;
854 host->board = pdev->dev.platform_data;
855 if (host->board->wire4) {
Nicolas Ferreed99c542007-07-09 14:58:16 +0200856 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
857 mmc->caps |= MMC_CAP_4_BIT_DATA;
858 else
David Brownell6e996ee2008-02-04 18:12:48 +0100859 dev_warn(&pdev->dev, "4 wire bus mode not supported"
Nicolas Ferreed99c542007-07-09 14:58:16 +0200860 " - using 1 wire\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100861 }
862
863 /*
David Brownell6e996ee2008-02-04 18:12:48 +0100864 * Reserve GPIOs ... board init code makes sure these pins are set
865 * up as GPIOs with the right direction (input, except for vcc)
866 */
867 if (host->board->det_pin) {
868 ret = gpio_request(host->board->det_pin, "mmc_detect");
869 if (ret < 0) {
870 dev_dbg(&pdev->dev, "couldn't claim card detect pin\n");
871 goto fail5;
872 }
873 }
874 if (host->board->wp_pin) {
875 ret = gpio_request(host->board->wp_pin, "mmc_wp");
876 if (ret < 0) {
877 dev_dbg(&pdev->dev, "couldn't claim wp sense pin\n");
878 goto fail4;
879 }
880 }
881 if (host->board->vcc_pin) {
882 ret = gpio_request(host->board->vcc_pin, "mmc_vcc");
883 if (ret < 0) {
884 dev_dbg(&pdev->dev, "couldn't claim vcc switch pin\n");
885 goto fail3;
886 }
887 }
888
889 /*
Andrew Victor65dbf342006-04-02 19:18:51 +0100890 * Get Clock
891 */
Andrew Victor3dd3b032006-10-23 14:46:54 +0200892 host->mci_clk = clk_get(&pdev->dev, "mci_clk");
893 if (IS_ERR(host->mci_clk)) {
David Brownell6e996ee2008-02-04 18:12:48 +0100894 ret = -ENODEV;
895 dev_dbg(&pdev->dev, "no mci_clk?\n");
896 goto fail2;
Andrew Victor65dbf342006-04-02 19:18:51 +0100897 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100898
Andrew Victor17ea0592006-10-23 14:44:40 +0200899 /*
900 * Map I/O region
901 */
902 host->baseaddr = ioremap(res->start, res->end - res->start + 1);
903 if (!host->baseaddr) {
David Brownell6e996ee2008-02-04 18:12:48 +0100904 ret = -ENOMEM;
905 goto fail1;
Andrew Victor17ea0592006-10-23 14:44:40 +0200906 }
Andrew Victore0b19b82006-10-25 19:42:38 +0200907
908 /*
909 * Reset hardware
910 */
Andrew Victor3dd3b032006-10-23 14:46:54 +0200911 clk_enable(host->mci_clk); /* Enable the peripheral clock */
Andrew Victore0b19b82006-10-25 19:42:38 +0200912 at91_mci_disable(host);
913 at91_mci_enable(host);
914
Andrew Victor65dbf342006-04-02 19:18:51 +0100915 /*
916 * Allocate the MCI interrupt
917 */
Andrew Victor17ea0592006-10-23 14:44:40 +0200918 host->irq = platform_get_irq(pdev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +0100919 ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED,
920 mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100921 if (ret) {
David Brownell6e996ee2008-02-04 18:12:48 +0100922 dev_dbg(&pdev->dev, "request MCI interrupt failed\n");
923 goto fail0;
Andrew Victor65dbf342006-04-02 19:18:51 +0100924 }
925
926 platform_set_drvdata(pdev, mmc);
927
928 /*
929 * Add host to MMC layer
930 */
Marc Pignat63b66432007-07-16 11:07:02 +0200931 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +0100932 host->present = !gpio_get_value(host->board->det_pin);
Marc Pignat63b66432007-07-16 11:07:02 +0200933 }
Andrew Victor65dbf342006-04-02 19:18:51 +0100934 else
935 host->present = -1;
936
937 mmc_add_host(mmc);
938
939 /*
940 * monitor card insertion/removal if we can
941 */
942 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +0100943 ret = request_irq(gpio_to_irq(host->board->det_pin),
944 at91_mmc_det_irq, 0, mmc_hostname(mmc), host);
Andrew Victor65dbf342006-04-02 19:18:51 +0100945 if (ret)
David Brownell6e996ee2008-02-04 18:12:48 +0100946 dev_warn(&pdev->dev, "request MMC detect irq failed\n");
947 else
948 device_init_wakeup(&pdev->dev, 1);
Andrew Victor65dbf342006-04-02 19:18:51 +0100949 }
950
Andrew Victorf3a8efa2006-10-23 14:53:20 +0200951 pr_debug("Added MCI driver\n");
Andrew Victor65dbf342006-04-02 19:18:51 +0100952
953 return 0;
David Brownell6e996ee2008-02-04 18:12:48 +0100954
955fail0:
956 clk_disable(host->mci_clk);
957 iounmap(host->baseaddr);
958fail1:
959 clk_put(host->mci_clk);
960fail2:
961 if (host->board->vcc_pin)
962 gpio_free(host->board->vcc_pin);
963fail3:
964 if (host->board->wp_pin)
965 gpio_free(host->board->wp_pin);
966fail4:
967 if (host->board->det_pin)
968 gpio_free(host->board->det_pin);
969fail5:
970 mmc_free_host(mmc);
971fail6:
972 release_mem_region(res->start, res->end - res->start + 1);
973 dev_err(&pdev->dev, "probe failed, err %d\n", ret);
974 return ret;
Andrew Victor65dbf342006-04-02 19:18:51 +0100975}
976
977/*
978 * Remove a device
979 */
David Brownella26b4982006-12-26 14:45:26 -0800980static int __exit at91_mci_remove(struct platform_device *pdev)
Andrew Victor65dbf342006-04-02 19:18:51 +0100981{
982 struct mmc_host *mmc = platform_get_drvdata(pdev);
983 struct at91mci_host *host;
Andrew Victor17ea0592006-10-23 14:44:40 +0200984 struct resource *res;
Andrew Victor65dbf342006-04-02 19:18:51 +0100985
986 if (!mmc)
987 return -1;
988
989 host = mmc_priv(mmc);
990
Anti Sulline0cda542007-08-30 16:15:16 +0200991 if (host->board->det_pin) {
David Brownell6e996ee2008-02-04 18:12:48 +0100992 if (device_can_wakeup(&pdev->dev))
993 free_irq(gpio_to_irq(host->board->det_pin), host);
Marc Pignat63b66432007-07-16 11:07:02 +0200994 device_init_wakeup(&pdev->dev, 0);
David Brownell6e996ee2008-02-04 18:12:48 +0100995 gpio_free(host->board->det_pin);
Andrew Victor65dbf342006-04-02 19:18:51 +0100996 }
997
Andrew Victore0b19b82006-10-25 19:42:38 +0200998 at91_mci_disable(host);
Andrew Victor17ea0592006-10-23 14:44:40 +0200999 mmc_remove_host(mmc);
1000 free_irq(host->irq, host);
Andrew Victor65dbf342006-04-02 19:18:51 +01001001
Andrew Victor3dd3b032006-10-23 14:46:54 +02001002 clk_disable(host->mci_clk); /* Disable the peripheral clock */
1003 clk_put(host->mci_clk);
Andrew Victor65dbf342006-04-02 19:18:51 +01001004
David Brownell6e996ee2008-02-04 18:12:48 +01001005 if (host->board->vcc_pin)
1006 gpio_free(host->board->vcc_pin);
1007 if (host->board->wp_pin)
1008 gpio_free(host->board->wp_pin);
1009
Andrew Victor17ea0592006-10-23 14:44:40 +02001010 iounmap(host->baseaddr);
1011 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1012 release_mem_region(res->start, res->end - res->start + 1);
Andrew Victor65dbf342006-04-02 19:18:51 +01001013
Andrew Victor17ea0592006-10-23 14:44:40 +02001014 mmc_free_host(mmc);
1015 platform_set_drvdata(pdev, NULL);
Andrew Victorb44fb7a2006-06-19 13:06:05 +01001016 pr_debug("MCI Removed\n");
Andrew Victor65dbf342006-04-02 19:18:51 +01001017
1018 return 0;
1019}
1020
1021#ifdef CONFIG_PM
1022static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
1023{
1024 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001025 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001026 int ret = 0;
1027
Anti Sulline0cda542007-08-30 16:15:16 +02001028 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001029 enable_irq_wake(host->board->det_pin);
1030
Andrew Victor65dbf342006-04-02 19:18:51 +01001031 if (mmc)
1032 ret = mmc_suspend_host(mmc, state);
1033
1034 return ret;
1035}
1036
1037static int at91_mci_resume(struct platform_device *pdev)
1038{
1039 struct mmc_host *mmc = platform_get_drvdata(pdev);
Marc Pignat63b66432007-07-16 11:07:02 +02001040 struct at91mci_host *host = mmc_priv(mmc);
Andrew Victor65dbf342006-04-02 19:18:51 +01001041 int ret = 0;
1042
Anti Sulline0cda542007-08-30 16:15:16 +02001043 if (host->board->det_pin && device_may_wakeup(&pdev->dev))
Marc Pignat63b66432007-07-16 11:07:02 +02001044 disable_irq_wake(host->board->det_pin);
1045
Andrew Victor65dbf342006-04-02 19:18:51 +01001046 if (mmc)
1047 ret = mmc_resume_host(mmc);
1048
1049 return ret;
1050}
1051#else
1052#define at91_mci_suspend NULL
1053#define at91_mci_resume NULL
1054#endif
1055
1056static struct platform_driver at91_mci_driver = {
David Brownella26b4982006-12-26 14:45:26 -08001057 .remove = __exit_p(at91_mci_remove),
Andrew Victor65dbf342006-04-02 19:18:51 +01001058 .suspend = at91_mci_suspend,
1059 .resume = at91_mci_resume,
1060 .driver = {
1061 .name = DRIVER_NAME,
1062 .owner = THIS_MODULE,
1063 },
1064};
1065
1066static int __init at91_mci_init(void)
1067{
David Brownella26b4982006-12-26 14:45:26 -08001068 return platform_driver_probe(&at91_mci_driver, at91_mci_probe);
Andrew Victor65dbf342006-04-02 19:18:51 +01001069}
1070
1071static void __exit at91_mci_exit(void)
1072{
1073 platform_driver_unregister(&at91_mci_driver);
1074}
1075
1076module_init(at91_mci_init);
1077module_exit(at91_mci_exit);
1078
1079MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
1080MODULE_AUTHOR("Nick Randell");
1081MODULE_LICENSE("GPL");
Kay Sieversbc65c722008-04-15 14:34:28 -07001082MODULE_ALIAS("platform:at91_mci");