diff options
Diffstat (limited to 'drivers/mmc/host/at91_mci.c')
-rw-r--r-- | drivers/mmc/host/at91_mci.c | 257 |
1 files changed, 207 insertions, 50 deletions
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index 8979ad330a4d..f15e2064305c 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c | |||
@@ -125,9 +125,72 @@ struct at91mci_host | |||
125 | 125 | ||
126 | /* Latest in the scatterlist that has been enabled for transfer */ | 126 | /* Latest in the scatterlist that has been enabled for transfer */ |
127 | int transfer_index; | 127 | int transfer_index; |
128 | |||
129 | /* Timer for timeouts */ | ||
130 | struct timer_list timer; | ||
128 | }; | 131 | }; |
129 | 132 | ||
130 | /* | 133 | /* |
134 | * Reset the controller and restore most of the state | ||
135 | */ | ||
136 | static void at91_reset_host(struct at91mci_host *host) | ||
137 | { | ||
138 | unsigned long flags; | ||
139 | u32 mr; | ||
140 | u32 sdcr; | ||
141 | u32 dtor; | ||
142 | u32 imr; | ||
143 | |||
144 | local_irq_save(flags); | ||
145 | imr = at91_mci_read(host, AT91_MCI_IMR); | ||
146 | |||
147 | at91_mci_write(host, AT91_MCI_IDR, 0xffffffff); | ||
148 | |||
149 | /* save current state */ | ||
150 | mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff; | ||
151 | sdcr = at91_mci_read(host, AT91_MCI_SDCR); | ||
152 | dtor = at91_mci_read(host, AT91_MCI_DTOR); | ||
153 | |||
154 | /* reset the controller */ | ||
155 | at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST); | ||
156 | |||
157 | /* restore state */ | ||
158 | at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN); | ||
159 | at91_mci_write(host, AT91_MCI_MR, mr); | ||
160 | at91_mci_write(host, AT91_MCI_SDCR, sdcr); | ||
161 | at91_mci_write(host, AT91_MCI_DTOR, dtor); | ||
162 | at91_mci_write(host, AT91_MCI_IER, imr); | ||
163 | |||
164 | /* make sure sdio interrupts will fire */ | ||
165 | at91_mci_read(host, AT91_MCI_SR); | ||
166 | |||
167 | local_irq_restore(flags); | ||
168 | } | ||
169 | |||
170 | static void at91_timeout_timer(unsigned long data) | ||
171 | { | ||
172 | struct at91mci_host *host; | ||
173 | |||
174 | host = (struct at91mci_host *)data; | ||
175 | |||
176 | if (host->request) { | ||
177 | dev_err(host->mmc->parent, "Timeout waiting end of packet\n"); | ||
178 | |||
179 | if (host->cmd && host->cmd->data) { | ||
180 | host->cmd->data->error = -ETIMEDOUT; | ||
181 | } else { | ||
182 | if (host->cmd) | ||
183 | host->cmd->error = -ETIMEDOUT; | ||
184 | else | ||
185 | host->request->cmd->error = -ETIMEDOUT; | ||
186 | } | ||
187 | |||
188 | at91_reset_host(host); | ||
189 | mmc_request_done(host->mmc, host->request); | ||
190 | } | ||
191 | } | ||
192 | |||
193 | /* | ||
131 | * Copy from sg to a dma block - used for transfers | 194 | * Copy from sg to a dma block - used for transfers |
132 | */ | 195 | */ |
133 | static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data) | 196 | static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data) |
@@ -135,9 +198,14 @@ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data | |||
135 | unsigned int len, i, size; | 198 | unsigned int len, i, size; |
136 | unsigned *dmabuf = host->buffer; | 199 | unsigned *dmabuf = host->buffer; |
137 | 200 | ||
138 | size = host->total_length; | 201 | size = data->blksz * data->blocks; |
139 | len = data->sg_len; | 202 | len = data->sg_len; |
140 | 203 | ||
204 | /* AT91SAM926[0/3] Data Write Operation and number of bytes erratum */ | ||
205 | if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) | ||
206 | if (host->total_length == 12) | ||
207 | memset(dmabuf, 0, 12); | ||
208 | |||
141 | /* | 209 | /* |
142 | * Just loop through all entries. Size might not | 210 | * Just loop through all entries. Size might not |
143 | * be the entire list though so make sure that | 211 | * be the entire list though so make sure that |
@@ -159,9 +227,10 @@ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data | |||
159 | 227 | ||
160 | for (index = 0; index < (amount / 4); index++) | 228 | for (index = 0; index < (amount / 4); index++) |
161 | *dmabuf++ = swab32(sgbuffer[index]); | 229 | *dmabuf++ = swab32(sgbuffer[index]); |
162 | } | 230 | } else { |
163 | else | ||
164 | memcpy(dmabuf, sgbuffer, amount); | 231 | memcpy(dmabuf, sgbuffer, amount); |
232 | dmabuf += amount; | ||
233 | } | ||
165 | 234 | ||
166 | kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); | 235 | kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); |
167 | 236 | ||
@@ -233,11 +302,11 @@ static void at91_mci_pre_dma_read(struct at91mci_host *host) | |||
233 | 302 | ||
234 | if (i == 0) { | 303 | if (i == 0) { |
235 | at91_mci_write(host, ATMEL_PDC_RPR, sg->dma_address); | 304 | at91_mci_write(host, ATMEL_PDC_RPR, sg->dma_address); |
236 | at91_mci_write(host, ATMEL_PDC_RCR, sg->length / 4); | 305 | at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ? sg->length : sg->length / 4); |
237 | } | 306 | } |
238 | else { | 307 | else { |
239 | at91_mci_write(host, ATMEL_PDC_RNPR, sg->dma_address); | 308 | at91_mci_write(host, ATMEL_PDC_RNPR, sg->dma_address); |
240 | at91_mci_write(host, ATMEL_PDC_RNCR, sg->length / 4); | 309 | at91_mci_write(host, ATMEL_PDC_RNCR, (data->blksz & 0x3) ? sg->length : sg->length / 4); |
241 | } | 310 | } |
242 | } | 311 | } |
243 | 312 | ||
@@ -277,8 +346,6 @@ static void at91_mci_post_dma_read(struct at91mci_host *host) | |||
277 | 346 | ||
278 | dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE); | 347 | dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE); |
279 | 348 | ||
280 | data->bytes_xfered += sg->length; | ||
281 | |||
282 | if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */ | 349 | if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */ |
283 | unsigned int *buffer; | 350 | unsigned int *buffer; |
284 | int index; | 351 | int index; |
@@ -294,6 +361,8 @@ static void at91_mci_post_dma_read(struct at91mci_host *host) | |||
294 | } | 361 | } |
295 | 362 | ||
296 | flush_dcache_page(sg_page(sg)); | 363 | flush_dcache_page(sg_page(sg)); |
364 | |||
365 | data->bytes_xfered += sg->length; | ||
297 | } | 366 | } |
298 | 367 | ||
299 | /* Is there another transfer to trigger? */ | 368 | /* Is there another transfer to trigger? */ |
@@ -334,10 +403,32 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host) | |||
334 | at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE); | 403 | at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE); |
335 | } else | 404 | } else |
336 | at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY); | 405 | at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY); |
406 | } | ||
407 | |||
408 | /* | ||
409 | * Update bytes tranfered count during a write operation | ||
410 | */ | ||
411 | static void at91_mci_update_bytes_xfered(struct at91mci_host *host) | ||
412 | { | ||
413 | struct mmc_data *data; | ||
414 | |||
415 | /* always deal with the effective request (and not the current cmd) */ | ||
416 | |||
417 | if (host->request->cmd && host->request->cmd->error != 0) | ||
418 | return; | ||
337 | 419 | ||
338 | data->bytes_xfered = host->total_length; | 420 | if (host->request->data) { |
421 | data = host->request->data; | ||
422 | if (data->flags & MMC_DATA_WRITE) { | ||
423 | /* card is in IDLE mode now */ | ||
424 | pr_debug("-> bytes_xfered %d, total_length = %d\n", | ||
425 | data->bytes_xfered, host->total_length); | ||
426 | data->bytes_xfered = data->blksz * data->blocks; | ||
427 | } | ||
428 | } | ||
339 | } | 429 | } |
340 | 430 | ||
431 | |||
341 | /*Handle after command sent ready*/ | 432 | /*Handle after command sent ready*/ |
342 | static int at91_mci_handle_cmdrdy(struct at91mci_host *host) | 433 | static int at91_mci_handle_cmdrdy(struct at91mci_host *host) |
343 | { | 434 | { |
@@ -350,8 +441,7 @@ static int at91_mci_handle_cmdrdy(struct at91mci_host *host) | |||
350 | } else return 1; | 441 | } else return 1; |
351 | } else if (host->cmd->data->flags & MMC_DATA_WRITE) { | 442 | } else if (host->cmd->data->flags & MMC_DATA_WRITE) { |
352 | /*After sendding multi-block-write command, start DMA transfer*/ | 443 | /*After sendding multi-block-write command, start DMA transfer*/ |
353 | at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE); | 444 | at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE | AT91_MCI_BLKE); |
354 | at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE); | ||
355 | at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN); | 445 | at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN); |
356 | } | 446 | } |
357 | 447 | ||
@@ -430,11 +520,19 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command | |||
430 | 520 | ||
431 | if (data) { | 521 | if (data) { |
432 | 522 | ||
433 | if ( data->blksz & 0x3 ) { | 523 | if (cpu_is_at91rm9200() || cpu_is_at91sam9261()) { |
434 | pr_debug("Unsupported block size\n"); | 524 | if (data->blksz & 0x3) { |
435 | cmd->error = -EINVAL; | 525 | pr_debug("Unsupported block size\n"); |
436 | mmc_request_done(host->mmc, host->request); | 526 | cmd->error = -EINVAL; |
437 | return; | 527 | mmc_request_done(host->mmc, host->request); |
528 | return; | ||
529 | } | ||
530 | if (data->flags & MMC_DATA_STREAM) { | ||
531 | pr_debug("Stream commands not supported\n"); | ||
532 | cmd->error = -EINVAL; | ||
533 | mmc_request_done(host->mmc, host->request); | ||
534 | return; | ||
535 | } | ||
438 | } | 536 | } |
439 | 537 | ||
440 | block_length = data->blksz; | 538 | block_length = data->blksz; |
@@ -481,8 +579,16 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command | |||
481 | ier = AT91_MCI_CMDRDY; | 579 | ier = AT91_MCI_CMDRDY; |
482 | } else { | 580 | } else { |
483 | /* zero block length and PDC mode */ | 581 | /* zero block length and PDC mode */ |
484 | mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff; | 582 | mr = at91_mci_read(host, AT91_MCI_MR) & 0x5fff; |
485 | at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE); | 583 | mr |= (data->blksz & 0x3) ? AT91_MCI_PDCFBYTE : 0; |
584 | mr |= (block_length << 16); | ||
585 | mr |= AT91_MCI_PDCMODE; | ||
586 | at91_mci_write(host, AT91_MCI_MR, mr); | ||
587 | |||
588 | if (!(cpu_is_at91rm9200() || cpu_is_at91sam9261())) | ||
589 | at91_mci_write(host, AT91_MCI_BLKR, | ||
590 | AT91_MCI_BLKR_BCNT(blocks) | | ||
591 | AT91_MCI_BLKR_BLKLEN(block_length)); | ||
486 | 592 | ||
487 | /* | 593 | /* |
488 | * Disable the PDC controller | 594 | * Disable the PDC controller |
@@ -508,6 +614,13 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command | |||
508 | * Handle a write | 614 | * Handle a write |
509 | */ | 615 | */ |
510 | host->total_length = block_length * blocks; | 616 | host->total_length = block_length * blocks; |
617 | /* | ||
618 | * AT91SAM926[0/3] Data Write Operation and | ||
619 | * number of bytes erratum | ||
620 | */ | ||
621 | if (cpu_is_at91sam9260 () || cpu_is_at91sam9263()) | ||
622 | if (host->total_length < 12) | ||
623 | host->total_length = 12; | ||
511 | host->buffer = dma_alloc_coherent(NULL, | 624 | host->buffer = dma_alloc_coherent(NULL, |
512 | host->total_length, | 625 | host->total_length, |
513 | &host->physical_address, GFP_KERNEL); | 626 | &host->physical_address, GFP_KERNEL); |
@@ -517,7 +630,9 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command | |||
517 | pr_debug("Transmitting %d bytes\n", host->total_length); | 630 | pr_debug("Transmitting %d bytes\n", host->total_length); |
518 | 631 | ||
519 | at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address); | 632 | at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address); |
520 | at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4); | 633 | at91_mci_write(host, ATMEL_PDC_TCR, (data->blksz & 0x3) ? |
634 | host->total_length : host->total_length / 4); | ||
635 | |||
521 | ier = AT91_MCI_CMDRDY; | 636 | ier = AT91_MCI_CMDRDY; |
522 | } | 637 | } |
523 | } | 638 | } |
@@ -552,20 +667,26 @@ static void at91_mci_process_next(struct at91mci_host *host) | |||
552 | else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) { | 667 | else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) { |
553 | host->flags |= FL_SENT_STOP; | 668 | host->flags |= FL_SENT_STOP; |
554 | at91_mci_send_command(host, host->request->stop); | 669 | at91_mci_send_command(host, host->request->stop); |
555 | } | 670 | } else { |
556 | else | 671 | del_timer(&host->timer); |
672 | /* the at91rm9200 mci controller hangs after some transfers, | ||
673 | * and the workaround is to reset it after each transfer. | ||
674 | */ | ||
675 | if (cpu_is_at91rm9200()) | ||
676 | at91_reset_host(host); | ||
557 | mmc_request_done(host->mmc, host->request); | 677 | mmc_request_done(host->mmc, host->request); |
678 | } | ||
558 | } | 679 | } |
559 | 680 | ||
560 | /* | 681 | /* |
561 | * Handle a command that has been completed | 682 | * Handle a command that has been completed |
562 | */ | 683 | */ |
563 | static void at91_mci_completed_command(struct at91mci_host *host) | 684 | static void at91_mci_completed_command(struct at91mci_host *host, unsigned int status) |
564 | { | 685 | { |
565 | struct mmc_command *cmd = host->cmd; | 686 | struct mmc_command *cmd = host->cmd; |
566 | unsigned int status; | 687 | struct mmc_data *data = cmd->data; |
567 | 688 | ||
568 | at91_mci_write(host, AT91_MCI_IDR, 0xffffffff); | 689 | at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB)); |
569 | 690 | ||
570 | cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0)); | 691 | cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0)); |
571 | cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1)); | 692 | cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1)); |
@@ -577,25 +698,34 @@ static void at91_mci_completed_command(struct at91mci_host *host) | |||
577 | host->buffer = NULL; | 698 | host->buffer = NULL; |
578 | } | 699 | } |
579 | 700 | ||
580 | status = at91_mci_read(host, AT91_MCI_SR); | 701 | pr_debug("Status = %08X/%08x [%08X %08X %08X %08X]\n", |
581 | 702 | status, at91_mci_read(host, AT91_MCI_SR), | |
582 | pr_debug("Status = %08X [%08X %08X %08X %08X]\n", | 703 | cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); |
583 | status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); | ||
584 | 704 | ||
585 | if (status & AT91_MCI_ERRORS) { | 705 | if (status & AT91_MCI_ERRORS) { |
586 | if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) { | 706 | if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) { |
587 | cmd->error = 0; | 707 | cmd->error = 0; |
588 | } | 708 | } |
589 | else { | 709 | else { |
590 | if (status & (AT91_MCI_RTOE | AT91_MCI_DTOE)) | 710 | if (status & (AT91_MCI_DTOE | AT91_MCI_DCRCE)) { |
591 | cmd->error = -ETIMEDOUT; | 711 | if (data) { |
592 | else if (status & (AT91_MCI_RCRCE | AT91_MCI_DCRCE)) | 712 | if (status & AT91_MCI_DTOE) |
593 | cmd->error = -EILSEQ; | 713 | data->error = -ETIMEDOUT; |
594 | else | 714 | else if (status & AT91_MCI_DCRCE) |
595 | cmd->error = -EIO; | 715 | data->error = -EILSEQ; |
716 | } | ||
717 | } else { | ||
718 | if (status & AT91_MCI_RTOE) | ||
719 | cmd->error = -ETIMEDOUT; | ||
720 | else if (status & AT91_MCI_RCRCE) | ||
721 | cmd->error = -EILSEQ; | ||
722 | else | ||
723 | cmd->error = -EIO; | ||
724 | } | ||
596 | 725 | ||
597 | pr_debug("Error detected and set to %d (cmd = %d, retries = %d)\n", | 726 | pr_debug("Error detected and set to %d/%d (cmd = %d, retries = %d)\n", |
598 | cmd->error, cmd->opcode, cmd->retries); | 727 | cmd->error, data ? data->error : 0, |
728 | cmd->opcode, cmd->retries); | ||
599 | } | 729 | } |
600 | } | 730 | } |
601 | else | 731 | else |
@@ -613,6 +743,8 @@ static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
613 | host->request = mrq; | 743 | host->request = mrq; |
614 | host->flags = 0; | 744 | host->flags = 0; |
615 | 745 | ||
746 | mod_timer(&host->timer, jiffies + HZ); | ||
747 | |||
616 | at91_mci_process_next(host); | 748 | at91_mci_process_next(host); |
617 | } | 749 | } |
618 | 750 | ||
@@ -736,6 +868,7 @@ static irqreturn_t at91_mci_irq(int irq, void *devid) | |||
736 | 868 | ||
737 | if (int_status & AT91_MCI_NOTBUSY) { | 869 | if (int_status & AT91_MCI_NOTBUSY) { |
738 | pr_debug("Card is ready\n"); | 870 | pr_debug("Card is ready\n"); |
871 | at91_mci_update_bytes_xfered(host); | ||
739 | completed = 1; | 872 | completed = 1; |
740 | } | 873 | } |
741 | 874 | ||
@@ -744,9 +877,21 @@ static irqreturn_t at91_mci_irq(int irq, void *devid) | |||
744 | 877 | ||
745 | if (int_status & AT91_MCI_BLKE) { | 878 | if (int_status & AT91_MCI_BLKE) { |
746 | pr_debug("Block transfer has ended\n"); | 879 | pr_debug("Block transfer has ended\n"); |
747 | completed = 1; | 880 | if (host->request->data && host->request->data->blocks > 1) { |
881 | /* multi block write : complete multi write | ||
882 | * command and send stop */ | ||
883 | completed = 1; | ||
884 | } else { | ||
885 | at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY); | ||
886 | } | ||
748 | } | 887 | } |
749 | 888 | ||
889 | if (int_status & AT91_MCI_SDIOIRQA) | ||
890 | mmc_signal_sdio_irq(host->mmc); | ||
891 | |||
892 | if (int_status & AT91_MCI_SDIOIRQB) | ||
893 | mmc_signal_sdio_irq(host->mmc); | ||
894 | |||
750 | if (int_status & AT91_MCI_TXRDY) | 895 | if (int_status & AT91_MCI_TXRDY) |
751 | pr_debug("Ready to transmit\n"); | 896 | pr_debug("Ready to transmit\n"); |
752 | 897 | ||
@@ -761,10 +906,10 @@ static irqreturn_t at91_mci_irq(int irq, void *devid) | |||
761 | 906 | ||
762 | if (completed) { | 907 | if (completed) { |
763 | pr_debug("Completed command\n"); | 908 | pr_debug("Completed command\n"); |
764 | at91_mci_write(host, AT91_MCI_IDR, 0xffffffff); | 909 | at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB)); |
765 | at91_mci_completed_command(host); | 910 | at91_mci_completed_command(host, int_status); |
766 | } else | 911 | } else |
767 | at91_mci_write(host, AT91_MCI_IDR, int_status); | 912 | at91_mci_write(host, AT91_MCI_IDR, int_status & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB)); |
768 | 913 | ||
769 | return IRQ_HANDLED; | 914 | return IRQ_HANDLED; |
770 | } | 915 | } |
@@ -793,25 +938,33 @@ static irqreturn_t at91_mmc_det_irq(int irq, void *_host) | |||
793 | 938 | ||
794 | static int at91_mci_get_ro(struct mmc_host *mmc) | 939 | static int at91_mci_get_ro(struct mmc_host *mmc) |
795 | { | 940 | { |
796 | int read_only = 0; | ||
797 | struct at91mci_host *host = mmc_priv(mmc); | 941 | struct at91mci_host *host = mmc_priv(mmc); |
798 | 942 | ||
799 | if (host->board->wp_pin) { | 943 | if (host->board->wp_pin) |
800 | read_only = gpio_get_value(host->board->wp_pin); | 944 | return !!gpio_get_value(host->board->wp_pin); |
801 | printk(KERN_WARNING "%s: card is %s\n", mmc_hostname(mmc), | 945 | /* |
802 | (read_only ? "read-only" : "read-write") ); | 946 | * Board doesn't support read only detection; let the mmc core |
803 | } | 947 | * decide what to do. |
804 | else { | 948 | */ |
805 | printk(KERN_WARNING "%s: host does not support reading read-only " | 949 | return -ENOSYS; |
806 | "switch. Assuming write-enable.\n", mmc_hostname(mmc)); | 950 | } |
807 | } | 951 | |
808 | return read_only; | 952 | static void at91_mci_enable_sdio_irq(struct mmc_host *mmc, int enable) |
953 | { | ||
954 | struct at91mci_host *host = mmc_priv(mmc); | ||
955 | |||
956 | pr_debug("%s: sdio_irq %c : %s\n", mmc_hostname(host->mmc), | ||
957 | host->board->slot_b ? 'B':'A', enable ? "enable" : "disable"); | ||
958 | at91_mci_write(host, enable ? AT91_MCI_IER : AT91_MCI_IDR, | ||
959 | host->board->slot_b ? AT91_MCI_SDIOIRQB : AT91_MCI_SDIOIRQA); | ||
960 | |||
809 | } | 961 | } |
810 | 962 | ||
811 | static const struct mmc_host_ops at91_mci_ops = { | 963 | static const struct mmc_host_ops at91_mci_ops = { |
812 | .request = at91_mci_request, | 964 | .request = at91_mci_request, |
813 | .set_ios = at91_mci_set_ios, | 965 | .set_ios = at91_mci_set_ios, |
814 | .get_ro = at91_mci_get_ro, | 966 | .get_ro = at91_mci_get_ro, |
967 | .enable_sdio_irq = at91_mci_enable_sdio_irq, | ||
815 | }; | 968 | }; |
816 | 969 | ||
817 | /* | 970 | /* |
@@ -842,6 +995,7 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
842 | mmc->f_min = 375000; | 995 | mmc->f_min = 375000; |
843 | mmc->f_max = 25000000; | 996 | mmc->f_max = 25000000; |
844 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | 997 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
998 | mmc->caps = MMC_CAP_SDIO_IRQ; | ||
845 | 999 | ||
846 | mmc->max_blk_size = 4095; | 1000 | mmc->max_blk_size = 4095; |
847 | mmc->max_blk_count = mmc->max_req_size; | 1001 | mmc->max_blk_count = mmc->max_req_size; |
@@ -935,6 +1089,8 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
935 | 1089 | ||
936 | mmc_add_host(mmc); | 1090 | mmc_add_host(mmc); |
937 | 1091 | ||
1092 | setup_timer(&host->timer, at91_timeout_timer, (unsigned long)host); | ||
1093 | |||
938 | /* | 1094 | /* |
939 | * monitor card insertion/removal if we can | 1095 | * monitor card insertion/removal if we can |
940 | */ | 1096 | */ |
@@ -995,6 +1151,7 @@ static int __exit at91_mci_remove(struct platform_device *pdev) | |||
995 | } | 1151 | } |
996 | 1152 | ||
997 | at91_mci_disable(host); | 1153 | at91_mci_disable(host); |
1154 | del_timer_sync(&host->timer); | ||
998 | mmc_remove_host(mmc); | 1155 | mmc_remove_host(mmc); |
999 | free_irq(host->irq, host); | 1156 | free_irq(host->irq, host); |
1000 | 1157 | ||