diff options
Diffstat (limited to 'drivers/mmc/host/atmel-mci.c')
-rw-r--r-- | drivers/mmc/host/atmel-mci.c | 469 |
1 files changed, 337 insertions, 132 deletions
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index e94476beca18..420aca642b14 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
@@ -45,19 +45,19 @@ | |||
45 | #define ATMCI_DMA_THRESHOLD 16 | 45 | #define ATMCI_DMA_THRESHOLD 16 |
46 | 46 | ||
47 | enum { | 47 | enum { |
48 | EVENT_CMD_COMPLETE = 0, | 48 | EVENT_CMD_RDY = 0, |
49 | EVENT_XFER_COMPLETE, | 49 | EVENT_XFER_COMPLETE, |
50 | EVENT_DATA_COMPLETE, | 50 | EVENT_NOTBUSY, |
51 | EVENT_DATA_ERROR, | 51 | EVENT_DATA_ERROR, |
52 | }; | 52 | }; |
53 | 53 | ||
54 | enum atmel_mci_state { | 54 | enum atmel_mci_state { |
55 | STATE_IDLE = 0, | 55 | STATE_IDLE = 0, |
56 | STATE_SENDING_CMD, | 56 | STATE_SENDING_CMD, |
57 | STATE_SENDING_DATA, | 57 | STATE_DATA_XFER, |
58 | STATE_DATA_BUSY, | 58 | STATE_WAITING_NOTBUSY, |
59 | STATE_SENDING_STOP, | 59 | STATE_SENDING_STOP, |
60 | STATE_DATA_ERROR, | 60 | STATE_END_REQUEST, |
61 | }; | 61 | }; |
62 | 62 | ||
63 | enum atmci_xfer_dir { | 63 | enum atmci_xfer_dir { |
@@ -78,6 +78,9 @@ struct atmel_mci_caps { | |||
78 | bool has_highspeed; | 78 | bool has_highspeed; |
79 | bool has_rwproof; | 79 | bool has_rwproof; |
80 | bool has_odd_clk_div; | 80 | bool has_odd_clk_div; |
81 | bool has_bad_data_ordering; | ||
82 | bool need_reset_after_xfer; | ||
83 | bool need_blksz_mul_4; | ||
81 | }; | 84 | }; |
82 | 85 | ||
83 | struct atmel_mci_dma { | 86 | struct atmel_mci_dma { |
@@ -91,6 +94,11 @@ struct atmel_mci_dma { | |||
91 | * @regs: Pointer to MMIO registers. | 94 | * @regs: Pointer to MMIO registers. |
92 | * @sg: Scatterlist entry currently being processed by PIO or PDC code. | 95 | * @sg: Scatterlist entry currently being processed by PIO or PDC code. |
93 | * @pio_offset: Offset into the current scatterlist entry. | 96 | * @pio_offset: Offset into the current scatterlist entry. |
97 | * @buffer: Buffer used if we don't have the r/w proof capability. We | ||
98 | * don't have the time to switch pdc buffers so we have to use only | ||
99 | * one buffer for the full transaction. | ||
100 | * @buf_size: size of the buffer. | ||
101 | * @phys_buf_addr: buffer address needed for pdc. | ||
94 | * @cur_slot: The slot which is currently using the controller. | 102 | * @cur_slot: The slot which is currently using the controller. |
95 | * @mrq: The request currently being processed on @cur_slot, | 103 | * @mrq: The request currently being processed on @cur_slot, |
96 | * or NULL if the controller is idle. | 104 | * or NULL if the controller is idle. |
@@ -116,6 +124,7 @@ struct atmel_mci_dma { | |||
116 | * @queue: List of slots waiting for access to the controller. | 124 | * @queue: List of slots waiting for access to the controller. |
117 | * @need_clock_update: Update the clock rate before the next request. | 125 | * @need_clock_update: Update the clock rate before the next request. |
118 | * @need_reset: Reset controller before next request. | 126 | * @need_reset: Reset controller before next request. |
127 | * @timer: Timer to balance the data timeout error flag which cannot rise. | ||
119 | * @mode_reg: Value of the MR register. | 128 | * @mode_reg: Value of the MR register. |
120 | * @cfg_reg: Value of the CFG register. | 129 | * @cfg_reg: Value of the CFG register. |
121 | * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus | 130 | * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus |
@@ -166,6 +175,9 @@ struct atmel_mci { | |||
166 | 175 | ||
167 | struct scatterlist *sg; | 176 | struct scatterlist *sg; |
168 | unsigned int pio_offset; | 177 | unsigned int pio_offset; |
178 | unsigned int *buffer; | ||
179 | unsigned int buf_size; | ||
180 | dma_addr_t buf_phys_addr; | ||
169 | 181 | ||
170 | struct atmel_mci_slot *cur_slot; | 182 | struct atmel_mci_slot *cur_slot; |
171 | struct mmc_request *mrq; | 183 | struct mmc_request *mrq; |
@@ -189,6 +201,7 @@ struct atmel_mci { | |||
189 | 201 | ||
190 | bool need_clock_update; | 202 | bool need_clock_update; |
191 | bool need_reset; | 203 | bool need_reset; |
204 | struct timer_list timer; | ||
192 | u32 mode_reg; | 205 | u32 mode_reg; |
193 | u32 cfg_reg; | 206 | u32 cfg_reg; |
194 | unsigned long bus_hz; | 207 | unsigned long bus_hz; |
@@ -480,6 +493,32 @@ err: | |||
480 | dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); | 493 | dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); |
481 | } | 494 | } |
482 | 495 | ||
496 | static inline unsigned int atmci_get_version(struct atmel_mci *host) | ||
497 | { | ||
498 | return atmci_readl(host, ATMCI_VERSION) & 0x00000fff; | ||
499 | } | ||
500 | |||
501 | static void atmci_timeout_timer(unsigned long data) | ||
502 | { | ||
503 | struct atmel_mci *host; | ||
504 | |||
505 | host = (struct atmel_mci *)data; | ||
506 | |||
507 | dev_dbg(&host->pdev->dev, "software timeout\n"); | ||
508 | |||
509 | if (host->mrq->cmd->data) { | ||
510 | host->mrq->cmd->data->error = -ETIMEDOUT; | ||
511 | host->data = NULL; | ||
512 | } else { | ||
513 | host->mrq->cmd->error = -ETIMEDOUT; | ||
514 | host->cmd = NULL; | ||
515 | } | ||
516 | host->need_reset = 1; | ||
517 | host->state = STATE_END_REQUEST; | ||
518 | smp_wmb(); | ||
519 | tasklet_schedule(&host->tasklet); | ||
520 | } | ||
521 | |||
483 | static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host, | 522 | static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host, |
484 | unsigned int ns) | 523 | unsigned int ns) |
485 | { | 524 | { |
@@ -591,6 +630,7 @@ static void atmci_send_command(struct atmel_mci *host, | |||
591 | 630 | ||
592 | static void atmci_send_stop_cmd(struct atmel_mci *host, struct mmc_data *data) | 631 | static void atmci_send_stop_cmd(struct atmel_mci *host, struct mmc_data *data) |
593 | { | 632 | { |
633 | dev_dbg(&host->pdev->dev, "send stop command\n"); | ||
594 | atmci_send_command(host, data->stop, host->stop_cmdr); | 634 | atmci_send_command(host, data->stop, host->stop_cmdr); |
595 | atmci_writel(host, ATMCI_IER, ATMCI_CMDRDY); | 635 | atmci_writel(host, ATMCI_IER, ATMCI_CMDRDY); |
596 | } | 636 | } |
@@ -603,6 +643,7 @@ static void atmci_pdc_set_single_buf(struct atmel_mci *host, | |||
603 | enum atmci_xfer_dir dir, enum atmci_pdc_buf buf_nb) | 643 | enum atmci_xfer_dir dir, enum atmci_pdc_buf buf_nb) |
604 | { | 644 | { |
605 | u32 pointer_reg, counter_reg; | 645 | u32 pointer_reg, counter_reg; |
646 | unsigned int buf_size; | ||
606 | 647 | ||
607 | if (dir == XFER_RECEIVE) { | 648 | if (dir == XFER_RECEIVE) { |
608 | pointer_reg = ATMEL_PDC_RPR; | 649 | pointer_reg = ATMEL_PDC_RPR; |
@@ -617,8 +658,15 @@ static void atmci_pdc_set_single_buf(struct atmel_mci *host, | |||
617 | counter_reg += ATMEL_PDC_SCND_BUF_OFF; | 658 | counter_reg += ATMEL_PDC_SCND_BUF_OFF; |
618 | } | 659 | } |
619 | 660 | ||
620 | atmci_writel(host, pointer_reg, sg_dma_address(host->sg)); | 661 | if (!host->caps.has_rwproof) { |
621 | if (host->data_size <= sg_dma_len(host->sg)) { | 662 | buf_size = host->buf_size; |
663 | atmci_writel(host, pointer_reg, host->buf_phys_addr); | ||
664 | } else { | ||
665 | buf_size = sg_dma_len(host->sg); | ||
666 | atmci_writel(host, pointer_reg, sg_dma_address(host->sg)); | ||
667 | } | ||
668 | |||
669 | if (host->data_size <= buf_size) { | ||
622 | if (host->data_size & 0x3) { | 670 | if (host->data_size & 0x3) { |
623 | /* If size is different from modulo 4, transfer bytes */ | 671 | /* If size is different from modulo 4, transfer bytes */ |
624 | atmci_writel(host, counter_reg, host->data_size); | 672 | atmci_writel(host, counter_reg, host->data_size); |
@@ -670,7 +718,20 @@ static void atmci_pdc_cleanup(struct atmel_mci *host) | |||
670 | */ | 718 | */ |
671 | static void atmci_pdc_complete(struct atmel_mci *host) | 719 | static void atmci_pdc_complete(struct atmel_mci *host) |
672 | { | 720 | { |
721 | int transfer_size = host->data->blocks * host->data->blksz; | ||
722 | int i; | ||
723 | |||
673 | atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS); | 724 | atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS); |
725 | |||
726 | if ((!host->caps.has_rwproof) | ||
727 | && (host->data->flags & MMC_DATA_READ)) { | ||
728 | if (host->caps.has_bad_data_ordering) | ||
729 | for (i = 0; i < transfer_size; i++) | ||
730 | host->buffer[i] = swab32(host->buffer[i]); | ||
731 | sg_copy_from_buffer(host->data->sg, host->data->sg_len, | ||
732 | host->buffer, transfer_size); | ||
733 | } | ||
734 | |||
674 | atmci_pdc_cleanup(host); | 735 | atmci_pdc_cleanup(host); |
675 | 736 | ||
676 | /* | 737 | /* |
@@ -678,9 +739,10 @@ static void atmci_pdc_complete(struct atmel_mci *host) | |||
678 | * to send the stop command or waiting for NBUSY in this case. | 739 | * to send the stop command or waiting for NBUSY in this case. |
679 | */ | 740 | */ |
680 | if (host->data) { | 741 | if (host->data) { |
742 | dev_dbg(&host->pdev->dev, | ||
743 | "(%s) set pending xfer complete\n", __func__); | ||
681 | atmci_set_pending(host, EVENT_XFER_COMPLETE); | 744 | atmci_set_pending(host, EVENT_XFER_COMPLETE); |
682 | tasklet_schedule(&host->tasklet); | 745 | tasklet_schedule(&host->tasklet); |
683 | atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); | ||
684 | } | 746 | } |
685 | } | 747 | } |
686 | 748 | ||
@@ -716,6 +778,8 @@ static void atmci_dma_complete(void *arg) | |||
716 | * to send the stop command or waiting for NBUSY in this case. | 778 | * to send the stop command or waiting for NBUSY in this case. |
717 | */ | 779 | */ |
718 | if (data) { | 780 | if (data) { |
781 | dev_dbg(&host->pdev->dev, | ||
782 | "(%s) set pending xfer complete\n", __func__); | ||
719 | atmci_set_pending(host, EVENT_XFER_COMPLETE); | 783 | atmci_set_pending(host, EVENT_XFER_COMPLETE); |
720 | tasklet_schedule(&host->tasklet); | 784 | tasklet_schedule(&host->tasklet); |
721 | 785 | ||
@@ -791,6 +855,7 @@ atmci_prepare_data_pdc(struct atmel_mci *host, struct mmc_data *data) | |||
791 | u32 iflags, tmp; | 855 | u32 iflags, tmp; |
792 | unsigned int sg_len; | 856 | unsigned int sg_len; |
793 | enum dma_data_direction dir; | 857 | enum dma_data_direction dir; |
858 | int i; | ||
794 | 859 | ||
795 | data->error = -EINPROGRESS; | 860 | data->error = -EINPROGRESS; |
796 | 861 | ||
@@ -806,7 +871,7 @@ atmci_prepare_data_pdc(struct atmel_mci *host, struct mmc_data *data) | |||
806 | iflags |= ATMCI_ENDRX | ATMCI_RXBUFF; | 871 | iflags |= ATMCI_ENDRX | ATMCI_RXBUFF; |
807 | } else { | 872 | } else { |
808 | dir = DMA_TO_DEVICE; | 873 | dir = DMA_TO_DEVICE; |
809 | iflags |= ATMCI_ENDTX | ATMCI_TXBUFE; | 874 | iflags |= ATMCI_ENDTX | ATMCI_TXBUFE | ATMCI_BLKE; |
810 | } | 875 | } |
811 | 876 | ||
812 | /* Set BLKLEN */ | 877 | /* Set BLKLEN */ |
@@ -818,6 +883,16 @@ atmci_prepare_data_pdc(struct atmel_mci *host, struct mmc_data *data) | |||
818 | /* Configure PDC */ | 883 | /* Configure PDC */ |
819 | host->data_size = data->blocks * data->blksz; | 884 | host->data_size = data->blocks * data->blksz; |
820 | sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, dir); | 885 | sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, dir); |
886 | |||
887 | if ((!host->caps.has_rwproof) | ||
888 | && (host->data->flags & MMC_DATA_WRITE)) { | ||
889 | sg_copy_to_buffer(host->data->sg, host->data->sg_len, | ||
890 | host->buffer, host->data_size); | ||
891 | if (host->caps.has_bad_data_ordering) | ||
892 | for (i = 0; i < host->data_size; i++) | ||
893 | host->buffer[i] = swab32(host->buffer[i]); | ||
894 | } | ||
895 | |||
821 | if (host->data_size) | 896 | if (host->data_size) |
822 | atmci_pdc_set_both_buf(host, | 897 | atmci_pdc_set_both_buf(host, |
823 | ((dir == DMA_FROM_DEVICE) ? XFER_RECEIVE : XFER_TRANSMIT)); | 898 | ((dir == DMA_FROM_DEVICE) ? XFER_RECEIVE : XFER_TRANSMIT)); |
@@ -931,6 +1006,8 @@ atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) | |||
931 | 1006 | ||
932 | static void atmci_stop_transfer(struct atmel_mci *host) | 1007 | static void atmci_stop_transfer(struct atmel_mci *host) |
933 | { | 1008 | { |
1009 | dev_dbg(&host->pdev->dev, | ||
1010 | "(%s) set pending xfer complete\n", __func__); | ||
934 | atmci_set_pending(host, EVENT_XFER_COMPLETE); | 1011 | atmci_set_pending(host, EVENT_XFER_COMPLETE); |
935 | atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); | 1012 | atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); |
936 | } | 1013 | } |
@@ -940,8 +1017,7 @@ static void atmci_stop_transfer(struct atmel_mci *host) | |||
940 | */ | 1017 | */ |
941 | static void atmci_stop_transfer_pdc(struct atmel_mci *host) | 1018 | static void atmci_stop_transfer_pdc(struct atmel_mci *host) |
942 | { | 1019 | { |
943 | atmci_set_pending(host, EVENT_XFER_COMPLETE); | 1020 | atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS); |
944 | atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); | ||
945 | } | 1021 | } |
946 | 1022 | ||
947 | static void atmci_stop_transfer_dma(struct atmel_mci *host) | 1023 | static void atmci_stop_transfer_dma(struct atmel_mci *host) |
@@ -953,6 +1029,8 @@ static void atmci_stop_transfer_dma(struct atmel_mci *host) | |||
953 | atmci_dma_cleanup(host); | 1029 | atmci_dma_cleanup(host); |
954 | } else { | 1030 | } else { |
955 | /* Data transfer was stopped by the interrupt handler */ | 1031 | /* Data transfer was stopped by the interrupt handler */ |
1032 | dev_dbg(&host->pdev->dev, | ||
1033 | "(%s) set pending xfer complete\n", __func__); | ||
956 | atmci_set_pending(host, EVENT_XFER_COMPLETE); | 1034 | atmci_set_pending(host, EVENT_XFER_COMPLETE); |
957 | atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); | 1035 | atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); |
958 | } | 1036 | } |
@@ -977,9 +1055,12 @@ static void atmci_start_request(struct atmel_mci *host, | |||
977 | 1055 | ||
978 | host->pending_events = 0; | 1056 | host->pending_events = 0; |
979 | host->completed_events = 0; | 1057 | host->completed_events = 0; |
1058 | host->cmd_status = 0; | ||
980 | host->data_status = 0; | 1059 | host->data_status = 0; |
981 | 1060 | ||
982 | if (host->need_reset) { | 1061 | dev_dbg(&host->pdev->dev, "start request: cmd %u\n", mrq->cmd->opcode); |
1062 | |||
1063 | if (host->need_reset || host->caps.need_reset_after_xfer) { | ||
983 | iflags = atmci_readl(host, ATMCI_IMR); | 1064 | iflags = atmci_readl(host, ATMCI_IMR); |
984 | iflags &= (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB); | 1065 | iflags &= (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB); |
985 | atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); | 1066 | atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); |
@@ -994,7 +1075,7 @@ static void atmci_start_request(struct atmel_mci *host, | |||
994 | 1075 | ||
995 | iflags = atmci_readl(host, ATMCI_IMR); | 1076 | iflags = atmci_readl(host, ATMCI_IMR); |
996 | if (iflags & ~(ATMCI_SDIOIRQA | ATMCI_SDIOIRQB)) | 1077 | if (iflags & ~(ATMCI_SDIOIRQA | ATMCI_SDIOIRQB)) |
997 | dev_warn(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n", | 1078 | dev_dbg(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n", |
998 | iflags); | 1079 | iflags); |
999 | 1080 | ||
1000 | if (unlikely(test_and_clear_bit(ATMCI_CARD_NEED_INIT, &slot->flags))) { | 1081 | if (unlikely(test_and_clear_bit(ATMCI_CARD_NEED_INIT, &slot->flags))) { |
@@ -1043,6 +1124,8 @@ static void atmci_start_request(struct atmel_mci *host, | |||
1043 | * prepared yet.) | 1124 | * prepared yet.) |
1044 | */ | 1125 | */ |
1045 | atmci_writel(host, ATMCI_IER, iflags); | 1126 | atmci_writel(host, ATMCI_IER, iflags); |
1127 | |||
1128 | mod_timer(&host->timer, jiffies + msecs_to_jiffies(2000)); | ||
1046 | } | 1129 | } |
1047 | 1130 | ||
1048 | static void atmci_queue_request(struct atmel_mci *host, | 1131 | static void atmci_queue_request(struct atmel_mci *host, |
@@ -1057,6 +1140,7 @@ static void atmci_queue_request(struct atmel_mci *host, | |||
1057 | host->state = STATE_SENDING_CMD; | 1140 | host->state = STATE_SENDING_CMD; |
1058 | atmci_start_request(host, slot); | 1141 | atmci_start_request(host, slot); |
1059 | } else { | 1142 | } else { |
1143 | dev_dbg(&host->pdev->dev, "queue request\n"); | ||
1060 | list_add_tail(&slot->queue_node, &host->queue); | 1144 | list_add_tail(&slot->queue_node, &host->queue); |
1061 | } | 1145 | } |
1062 | spin_unlock_bh(&host->lock); | 1146 | spin_unlock_bh(&host->lock); |
@@ -1069,6 +1153,7 @@ static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
1069 | struct mmc_data *data; | 1153 | struct mmc_data *data; |
1070 | 1154 | ||
1071 | WARN_ON(slot->mrq); | 1155 | WARN_ON(slot->mrq); |
1156 | dev_dbg(&host->pdev->dev, "MRQ: cmd %u\n", mrq->cmd->opcode); | ||
1072 | 1157 | ||
1073 | /* | 1158 | /* |
1074 | * We may "know" the card is gone even though there's still an | 1159 | * We may "know" the card is gone even though there's still an |
@@ -1308,6 +1393,8 @@ static void atmci_request_end(struct atmel_mci *host, struct mmc_request *mrq) | |||
1308 | host->state = STATE_IDLE; | 1393 | host->state = STATE_IDLE; |
1309 | } | 1394 | } |
1310 | 1395 | ||
1396 | del_timer(&host->timer); | ||
1397 | |||
1311 | spin_unlock(&host->lock); | 1398 | spin_unlock(&host->lock); |
1312 | mmc_request_done(prev_mmc, mrq); | 1399 | mmc_request_done(prev_mmc, mrq); |
1313 | spin_lock(&host->lock); | 1400 | spin_lock(&host->lock); |
@@ -1330,21 +1417,13 @@ static void atmci_command_complete(struct atmel_mci *host, | |||
1330 | cmd->error = -EILSEQ; | 1417 | cmd->error = -EILSEQ; |
1331 | else if (status & (ATMCI_RINDE | ATMCI_RDIRE | ATMCI_RENDE)) | 1418 | else if (status & (ATMCI_RINDE | ATMCI_RDIRE | ATMCI_RENDE)) |
1332 | cmd->error = -EIO; | 1419 | cmd->error = -EIO; |
1333 | else | 1420 | else if (host->mrq->data && (host->mrq->data->blksz & 3)) { |
1334 | cmd->error = 0; | 1421 | if (host->caps.need_blksz_mul_4) { |
1335 | 1422 | cmd->error = -EINVAL; | |
1336 | if (cmd->error) { | 1423 | host->need_reset = 1; |
1337 | dev_dbg(&host->pdev->dev, | ||
1338 | "command error: status=0x%08x\n", status); | ||
1339 | |||
1340 | if (cmd->data) { | ||
1341 | host->stop_transfer(host); | ||
1342 | host->data = NULL; | ||
1343 | atmci_writel(host, ATMCI_IDR, ATMCI_NOTBUSY | ||
1344 | | ATMCI_TXRDY | ATMCI_RXRDY | ||
1345 | | ATMCI_DATA_ERROR_FLAGS); | ||
1346 | } | 1424 | } |
1347 | } | 1425 | } else |
1426 | cmd->error = 0; | ||
1348 | } | 1427 | } |
1349 | 1428 | ||
1350 | static void atmci_detect_change(unsigned long data) | 1429 | static void atmci_detect_change(unsigned long data) |
@@ -1407,23 +1486,21 @@ static void atmci_detect_change(unsigned long data) | |||
1407 | break; | 1486 | break; |
1408 | case STATE_SENDING_CMD: | 1487 | case STATE_SENDING_CMD: |
1409 | mrq->cmd->error = -ENOMEDIUM; | 1488 | mrq->cmd->error = -ENOMEDIUM; |
1410 | if (!mrq->data) | 1489 | if (mrq->data) |
1411 | break; | 1490 | host->stop_transfer(host); |
1412 | /* fall through */ | 1491 | break; |
1413 | case STATE_SENDING_DATA: | 1492 | case STATE_DATA_XFER: |
1414 | mrq->data->error = -ENOMEDIUM; | 1493 | mrq->data->error = -ENOMEDIUM; |
1415 | host->stop_transfer(host); | 1494 | host->stop_transfer(host); |
1416 | break; | 1495 | break; |
1417 | case STATE_DATA_BUSY: | 1496 | case STATE_WAITING_NOTBUSY: |
1418 | case STATE_DATA_ERROR: | 1497 | mrq->data->error = -ENOMEDIUM; |
1419 | if (mrq->data->error == -EINPROGRESS) | 1498 | break; |
1420 | mrq->data->error = -ENOMEDIUM; | ||
1421 | if (!mrq->stop) | ||
1422 | break; | ||
1423 | /* fall through */ | ||
1424 | case STATE_SENDING_STOP: | 1499 | case STATE_SENDING_STOP: |
1425 | mrq->stop->error = -ENOMEDIUM; | 1500 | mrq->stop->error = -ENOMEDIUM; |
1426 | break; | 1501 | break; |
1502 | case STATE_END_REQUEST: | ||
1503 | break; | ||
1427 | } | 1504 | } |
1428 | 1505 | ||
1429 | atmci_request_end(host, mrq); | 1506 | atmci_request_end(host, mrq); |
@@ -1451,7 +1528,6 @@ static void atmci_tasklet_func(unsigned long priv) | |||
1451 | struct atmel_mci *host = (struct atmel_mci *)priv; | 1528 | struct atmel_mci *host = (struct atmel_mci *)priv; |
1452 | struct mmc_request *mrq = host->mrq; | 1529 | struct mmc_request *mrq = host->mrq; |
1453 | struct mmc_data *data = host->data; | 1530 | struct mmc_data *data = host->data; |
1454 | struct mmc_command *cmd = host->cmd; | ||
1455 | enum atmel_mci_state state = host->state; | 1531 | enum atmel_mci_state state = host->state; |
1456 | enum atmel_mci_state prev_state; | 1532 | enum atmel_mci_state prev_state; |
1457 | u32 status; | 1533 | u32 status; |
@@ -1467,107 +1543,186 @@ static void atmci_tasklet_func(unsigned long priv) | |||
1467 | 1543 | ||
1468 | do { | 1544 | do { |
1469 | prev_state = state; | 1545 | prev_state = state; |
1546 | dev_dbg(&host->pdev->dev, "FSM: state=%d\n", state); | ||
1470 | 1547 | ||
1471 | switch (state) { | 1548 | switch (state) { |
1472 | case STATE_IDLE: | 1549 | case STATE_IDLE: |
1473 | break; | 1550 | break; |
1474 | 1551 | ||
1475 | case STATE_SENDING_CMD: | 1552 | case STATE_SENDING_CMD: |
1553 | /* | ||
1554 | * Command has been sent, we are waiting for command | ||
1555 | * ready. Then we have three next states possible: | ||
1556 | * END_REQUEST by default, WAITING_NOTBUSY if it's a | ||
1557 | * command needing it or DATA_XFER if there is data. | ||
1558 | */ | ||
1559 | dev_dbg(&host->pdev->dev, "FSM: cmd ready?\n"); | ||
1476 | if (!atmci_test_and_clear_pending(host, | 1560 | if (!atmci_test_and_clear_pending(host, |
1477 | EVENT_CMD_COMPLETE)) | 1561 | EVENT_CMD_RDY)) |
1478 | break; | 1562 | break; |
1479 | 1563 | ||
1564 | dev_dbg(&host->pdev->dev, "set completed cmd ready\n"); | ||
1480 | host->cmd = NULL; | 1565 | host->cmd = NULL; |
1481 | atmci_set_completed(host, EVENT_CMD_COMPLETE); | 1566 | atmci_set_completed(host, EVENT_CMD_RDY); |
1482 | atmci_command_complete(host, mrq->cmd); | 1567 | atmci_command_complete(host, mrq->cmd); |
1483 | if (!mrq->data || cmd->error) { | 1568 | if (mrq->data) { |
1484 | atmci_request_end(host, host->mrq); | 1569 | dev_dbg(&host->pdev->dev, |
1485 | goto unlock; | 1570 | "command with data transfer"); |
1486 | } | 1571 | /* |
1572 | * If there is a command error don't start | ||
1573 | * data transfer. | ||
1574 | */ | ||
1575 | if (mrq->cmd->error) { | ||
1576 | host->stop_transfer(host); | ||
1577 | host->data = NULL; | ||
1578 | atmci_writel(host, ATMCI_IDR, | ||
1579 | ATMCI_TXRDY | ATMCI_RXRDY | ||
1580 | | ATMCI_DATA_ERROR_FLAGS); | ||
1581 | state = STATE_END_REQUEST; | ||
1582 | } else | ||
1583 | state = STATE_DATA_XFER; | ||
1584 | } else if ((!mrq->data) && (mrq->cmd->flags & MMC_RSP_BUSY)) { | ||
1585 | dev_dbg(&host->pdev->dev, | ||
1586 | "command response need waiting notbusy"); | ||
1587 | atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); | ||
1588 | state = STATE_WAITING_NOTBUSY; | ||
1589 | } else | ||
1590 | state = STATE_END_REQUEST; | ||
1487 | 1591 | ||
1488 | prev_state = state = STATE_SENDING_DATA; | 1592 | break; |
1489 | /* fall through */ | ||
1490 | 1593 | ||
1491 | case STATE_SENDING_DATA: | 1594 | case STATE_DATA_XFER: |
1492 | if (atmci_test_and_clear_pending(host, | 1595 | if (atmci_test_and_clear_pending(host, |
1493 | EVENT_DATA_ERROR)) { | 1596 | EVENT_DATA_ERROR)) { |
1494 | host->stop_transfer(host); | 1597 | dev_dbg(&host->pdev->dev, "set completed data error\n"); |
1495 | if (data->stop) | 1598 | atmci_set_completed(host, EVENT_DATA_ERROR); |
1496 | atmci_send_stop_cmd(host, data); | 1599 | state = STATE_END_REQUEST; |
1497 | state = STATE_DATA_ERROR; | ||
1498 | break; | 1600 | break; |
1499 | } | 1601 | } |
1500 | 1602 | ||
1603 | /* | ||
1604 | * A data transfer is in progress. The event expected | ||
1605 | * to move to the next state depends of data transfer | ||
1606 | * type (PDC or DMA). Once transfer done we can move | ||
1607 | * to the next step which is WAITING_NOTBUSY in write | ||
1608 | * case and directly SENDING_STOP in read case. | ||
1609 | */ | ||
1610 | dev_dbg(&host->pdev->dev, "FSM: xfer complete?\n"); | ||
1501 | if (!atmci_test_and_clear_pending(host, | 1611 | if (!atmci_test_and_clear_pending(host, |
1502 | EVENT_XFER_COMPLETE)) | 1612 | EVENT_XFER_COMPLETE)) |
1503 | break; | 1613 | break; |
1504 | 1614 | ||
1615 | dev_dbg(&host->pdev->dev, | ||
1616 | "(%s) set completed xfer complete\n", | ||
1617 | __func__); | ||
1505 | atmci_set_completed(host, EVENT_XFER_COMPLETE); | 1618 | atmci_set_completed(host, EVENT_XFER_COMPLETE); |
1506 | prev_state = state = STATE_DATA_BUSY; | ||
1507 | /* fall through */ | ||
1508 | 1619 | ||
1509 | case STATE_DATA_BUSY: | 1620 | if (host->data->flags & MMC_DATA_WRITE) { |
1510 | if (!atmci_test_and_clear_pending(host, | 1621 | atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); |
1511 | EVENT_DATA_COMPLETE)) | 1622 | state = STATE_WAITING_NOTBUSY; |
1512 | break; | 1623 | } else if (host->mrq->stop) { |
1513 | 1624 | atmci_writel(host, ATMCI_IER, ATMCI_CMDRDY); | |
1514 | host->data = NULL; | 1625 | atmci_send_stop_cmd(host, data); |
1515 | atmci_set_completed(host, EVENT_DATA_COMPLETE); | 1626 | state = STATE_SENDING_STOP; |
1516 | status = host->data_status; | ||
1517 | if (unlikely(status & ATMCI_DATA_ERROR_FLAGS)) { | ||
1518 | if (status & ATMCI_DTOE) { | ||
1519 | dev_dbg(&host->pdev->dev, | ||
1520 | "data timeout error\n"); | ||
1521 | data->error = -ETIMEDOUT; | ||
1522 | } else if (status & ATMCI_DCRCE) { | ||
1523 | dev_dbg(&host->pdev->dev, | ||
1524 | "data CRC error\n"); | ||
1525 | data->error = -EILSEQ; | ||
1526 | } else { | ||
1527 | dev_dbg(&host->pdev->dev, | ||
1528 | "data FIFO error (status=%08x)\n", | ||
1529 | status); | ||
1530 | data->error = -EIO; | ||
1531 | } | ||
1532 | } else { | 1627 | } else { |
1628 | host->data = NULL; | ||
1533 | data->bytes_xfered = data->blocks * data->blksz; | 1629 | data->bytes_xfered = data->blocks * data->blksz; |
1534 | data->error = 0; | 1630 | data->error = 0; |
1535 | atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS); | 1631 | state = STATE_END_REQUEST; |
1536 | } | 1632 | } |
1633 | break; | ||
1537 | 1634 | ||
1538 | if (!data->stop) { | 1635 | case STATE_WAITING_NOTBUSY: |
1539 | atmci_request_end(host, host->mrq); | 1636 | /* |
1540 | goto unlock; | 1637 | * We can be in the state for two reasons: a command |
1541 | } | 1638 | * requiring waiting not busy signal (stop command |
1639 | * included) or a write operation. In the latest case, | ||
1640 | * we need to send a stop command. | ||
1641 | */ | ||
1642 | dev_dbg(&host->pdev->dev, "FSM: not busy?\n"); | ||
1643 | if (!atmci_test_and_clear_pending(host, | ||
1644 | EVENT_NOTBUSY)) | ||
1645 | break; | ||
1542 | 1646 | ||
1543 | prev_state = state = STATE_SENDING_STOP; | 1647 | dev_dbg(&host->pdev->dev, "set completed not busy\n"); |
1544 | if (!data->error) | 1648 | atmci_set_completed(host, EVENT_NOTBUSY); |
1545 | atmci_send_stop_cmd(host, data); | 1649 | |
1546 | /* fall through */ | 1650 | if (host->data) { |
1651 | /* | ||
1652 | * For some commands such as CMD53, even if | ||
1653 | * there is data transfer, there is no stop | ||
1654 | * command to send. | ||
1655 | */ | ||
1656 | if (host->mrq->stop) { | ||
1657 | atmci_writel(host, ATMCI_IER, | ||
1658 | ATMCI_CMDRDY); | ||
1659 | atmci_send_stop_cmd(host, data); | ||
1660 | state = STATE_SENDING_STOP; | ||
1661 | } else { | ||
1662 | host->data = NULL; | ||
1663 | data->bytes_xfered = data->blocks | ||
1664 | * data->blksz; | ||
1665 | data->error = 0; | ||
1666 | state = STATE_END_REQUEST; | ||
1667 | } | ||
1668 | } else | ||
1669 | state = STATE_END_REQUEST; | ||
1670 | break; | ||
1547 | 1671 | ||
1548 | case STATE_SENDING_STOP: | 1672 | case STATE_SENDING_STOP: |
1673 | /* | ||
1674 | * In this state, it is important to set host->data to | ||
1675 | * NULL (which is tested in the waiting notbusy state) | ||
1676 | * in order to go to the end request state instead of | ||
1677 | * sending stop again. | ||
1678 | */ | ||
1679 | dev_dbg(&host->pdev->dev, "FSM: cmd ready?\n"); | ||
1549 | if (!atmci_test_and_clear_pending(host, | 1680 | if (!atmci_test_and_clear_pending(host, |
1550 | EVENT_CMD_COMPLETE)) | 1681 | EVENT_CMD_RDY)) |
1551 | break; | 1682 | break; |
1552 | 1683 | ||
1684 | dev_dbg(&host->pdev->dev, "FSM: cmd ready\n"); | ||
1553 | host->cmd = NULL; | 1685 | host->cmd = NULL; |
1686 | host->data = NULL; | ||
1687 | data->bytes_xfered = data->blocks * data->blksz; | ||
1688 | data->error = 0; | ||
1554 | atmci_command_complete(host, mrq->stop); | 1689 | atmci_command_complete(host, mrq->stop); |
1555 | atmci_request_end(host, host->mrq); | 1690 | if (mrq->stop->error) { |
1556 | goto unlock; | 1691 | host->stop_transfer(host); |
1692 | atmci_writel(host, ATMCI_IDR, | ||
1693 | ATMCI_TXRDY | ATMCI_RXRDY | ||
1694 | | ATMCI_DATA_ERROR_FLAGS); | ||
1695 | state = STATE_END_REQUEST; | ||
1696 | } else { | ||
1697 | atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); | ||
1698 | state = STATE_WAITING_NOTBUSY; | ||
1699 | } | ||
1700 | break; | ||
1557 | 1701 | ||
1558 | case STATE_DATA_ERROR: | 1702 | case STATE_END_REQUEST: |
1559 | if (!atmci_test_and_clear_pending(host, | 1703 | atmci_writel(host, ATMCI_IDR, ATMCI_TXRDY | ATMCI_RXRDY |
1560 | EVENT_XFER_COMPLETE)) | 1704 | | ATMCI_DATA_ERROR_FLAGS); |
1561 | break; | 1705 | status = host->data_status; |
1706 | if (unlikely(status)) { | ||
1707 | host->stop_transfer(host); | ||
1708 | host->data = NULL; | ||
1709 | if (status & ATMCI_DTOE) { | ||
1710 | data->error = -ETIMEDOUT; | ||
1711 | } else if (status & ATMCI_DCRCE) { | ||
1712 | data->error = -EILSEQ; | ||
1713 | } else { | ||
1714 | data->error = -EIO; | ||
1715 | } | ||
1716 | } | ||
1562 | 1717 | ||
1563 | state = STATE_DATA_BUSY; | 1718 | atmci_request_end(host, host->mrq); |
1719 | state = STATE_IDLE; | ||
1564 | break; | 1720 | break; |
1565 | } | 1721 | } |
1566 | } while (state != prev_state); | 1722 | } while (state != prev_state); |
1567 | 1723 | ||
1568 | host->state = state; | 1724 | host->state = state; |
1569 | 1725 | ||
1570 | unlock: | ||
1571 | spin_unlock(&host->lock); | 1726 | spin_unlock(&host->lock); |
1572 | } | 1727 | } |
1573 | 1728 | ||
@@ -1620,9 +1775,6 @@ static void atmci_read_data_pio(struct atmel_mci *host) | |||
1620 | | ATMCI_DATA_ERROR_FLAGS)); | 1775 | | ATMCI_DATA_ERROR_FLAGS)); |
1621 | host->data_status = status; | 1776 | host->data_status = status; |
1622 | data->bytes_xfered += nbytes; | 1777 | data->bytes_xfered += nbytes; |
1623 | smp_wmb(); | ||
1624 | atmci_set_pending(host, EVENT_DATA_ERROR); | ||
1625 | tasklet_schedule(&host->tasklet); | ||
1626 | return; | 1778 | return; |
1627 | } | 1779 | } |
1628 | } while (status & ATMCI_RXRDY); | 1780 | } while (status & ATMCI_RXRDY); |
@@ -1691,9 +1843,6 @@ static void atmci_write_data_pio(struct atmel_mci *host) | |||
1691 | | ATMCI_DATA_ERROR_FLAGS)); | 1843 | | ATMCI_DATA_ERROR_FLAGS)); |
1692 | host->data_status = status; | 1844 | host->data_status = status; |
1693 | data->bytes_xfered += nbytes; | 1845 | data->bytes_xfered += nbytes; |
1694 | smp_wmb(); | ||
1695 | atmci_set_pending(host, EVENT_DATA_ERROR); | ||
1696 | tasklet_schedule(&host->tasklet); | ||
1697 | return; | 1846 | return; |
1698 | } | 1847 | } |
1699 | } while (status & ATMCI_TXRDY); | 1848 | } while (status & ATMCI_TXRDY); |
@@ -1711,16 +1860,6 @@ done: | |||
1711 | atmci_set_pending(host, EVENT_XFER_COMPLETE); | 1860 | atmci_set_pending(host, EVENT_XFER_COMPLETE); |
1712 | } | 1861 | } |
1713 | 1862 | ||
1714 | static void atmci_cmd_interrupt(struct atmel_mci *host, u32 status) | ||
1715 | { | ||
1716 | atmci_writel(host, ATMCI_IDR, ATMCI_CMDRDY); | ||
1717 | |||
1718 | host->cmd_status = status; | ||
1719 | smp_wmb(); | ||
1720 | atmci_set_pending(host, EVENT_CMD_COMPLETE); | ||
1721 | tasklet_schedule(&host->tasklet); | ||
1722 | } | ||
1723 | |||
1724 | static void atmci_sdio_interrupt(struct atmel_mci *host, u32 status) | 1863 | static void atmci_sdio_interrupt(struct atmel_mci *host, u32 status) |
1725 | { | 1864 | { |
1726 | int i; | 1865 | int i; |
@@ -1748,17 +1887,21 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) | |||
1748 | break; | 1887 | break; |
1749 | 1888 | ||
1750 | if (pending & ATMCI_DATA_ERROR_FLAGS) { | 1889 | if (pending & ATMCI_DATA_ERROR_FLAGS) { |
1890 | dev_dbg(&host->pdev->dev, "IRQ: data error\n"); | ||
1751 | atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS | 1891 | atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS |
1752 | | ATMCI_RXRDY | ATMCI_TXRDY); | 1892 | | ATMCI_RXRDY | ATMCI_TXRDY |
1753 | pending &= atmci_readl(host, ATMCI_IMR); | 1893 | | ATMCI_ENDRX | ATMCI_ENDTX |
1894 | | ATMCI_RXBUFF | ATMCI_TXBUFE); | ||
1754 | 1895 | ||
1755 | host->data_status = status; | 1896 | host->data_status = status; |
1897 | dev_dbg(&host->pdev->dev, "set pending data error\n"); | ||
1756 | smp_wmb(); | 1898 | smp_wmb(); |
1757 | atmci_set_pending(host, EVENT_DATA_ERROR); | 1899 | atmci_set_pending(host, EVENT_DATA_ERROR); |
1758 | tasklet_schedule(&host->tasklet); | 1900 | tasklet_schedule(&host->tasklet); |
1759 | } | 1901 | } |
1760 | 1902 | ||
1761 | if (pending & ATMCI_TXBUFE) { | 1903 | if (pending & ATMCI_TXBUFE) { |
1904 | dev_dbg(&host->pdev->dev, "IRQ: tx buffer empty\n"); | ||
1762 | atmci_writel(host, ATMCI_IDR, ATMCI_TXBUFE); | 1905 | atmci_writel(host, ATMCI_IDR, ATMCI_TXBUFE); |
1763 | atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX); | 1906 | atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX); |
1764 | /* | 1907 | /* |
@@ -1774,6 +1917,7 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) | |||
1774 | atmci_pdc_complete(host); | 1917 | atmci_pdc_complete(host); |
1775 | } | 1918 | } |
1776 | } else if (pending & ATMCI_ENDTX) { | 1919 | } else if (pending & ATMCI_ENDTX) { |
1920 | dev_dbg(&host->pdev->dev, "IRQ: end of tx buffer\n"); | ||
1777 | atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX); | 1921 | atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX); |
1778 | 1922 | ||
1779 | if (host->data_size) { | 1923 | if (host->data_size) { |
@@ -1784,6 +1928,7 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) | |||
1784 | } | 1928 | } |
1785 | 1929 | ||
1786 | if (pending & ATMCI_RXBUFF) { | 1930 | if (pending & ATMCI_RXBUFF) { |
1931 | dev_dbg(&host->pdev->dev, "IRQ: rx buffer full\n"); | ||
1787 | atmci_writel(host, ATMCI_IDR, ATMCI_RXBUFF); | 1932 | atmci_writel(host, ATMCI_IDR, ATMCI_RXBUFF); |
1788 | atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX); | 1933 | atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX); |
1789 | /* | 1934 | /* |
@@ -1799,6 +1944,7 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) | |||
1799 | atmci_pdc_complete(host); | 1944 | atmci_pdc_complete(host); |
1800 | } | 1945 | } |
1801 | } else if (pending & ATMCI_ENDRX) { | 1946 | } else if (pending & ATMCI_ENDRX) { |
1947 | dev_dbg(&host->pdev->dev, "IRQ: end of rx buffer\n"); | ||
1802 | atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX); | 1948 | atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX); |
1803 | 1949 | ||
1804 | if (host->data_size) { | 1950 | if (host->data_size) { |
@@ -1808,23 +1954,44 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) | |||
1808 | } | 1954 | } |
1809 | } | 1955 | } |
1810 | 1956 | ||
1957 | /* | ||
1958 | * First mci IPs, so mainly the ones having pdc, have some | ||
1959 | * issues with the notbusy signal. You can't get it after | ||
1960 | * data transmission if you have not sent a stop command. | ||
1961 | * The appropriate workaround is to use the BLKE signal. | ||
1962 | */ | ||
1963 | if (pending & ATMCI_BLKE) { | ||
1964 | dev_dbg(&host->pdev->dev, "IRQ: blke\n"); | ||
1965 | atmci_writel(host, ATMCI_IDR, ATMCI_BLKE); | ||
1966 | smp_wmb(); | ||
1967 | dev_dbg(&host->pdev->dev, "set pending notbusy\n"); | ||
1968 | atmci_set_pending(host, EVENT_NOTBUSY); | ||
1969 | tasklet_schedule(&host->tasklet); | ||
1970 | } | ||
1811 | 1971 | ||
1812 | if (pending & ATMCI_NOTBUSY) { | 1972 | if (pending & ATMCI_NOTBUSY) { |
1813 | atmci_writel(host, ATMCI_IDR, | 1973 | dev_dbg(&host->pdev->dev, "IRQ: not_busy\n"); |
1814 | ATMCI_DATA_ERROR_FLAGS | ATMCI_NOTBUSY); | 1974 | atmci_writel(host, ATMCI_IDR, ATMCI_NOTBUSY); |
1815 | if (!host->data_status) | ||
1816 | host->data_status = status; | ||
1817 | smp_wmb(); | 1975 | smp_wmb(); |
1818 | atmci_set_pending(host, EVENT_DATA_COMPLETE); | 1976 | dev_dbg(&host->pdev->dev, "set pending notbusy\n"); |
1977 | atmci_set_pending(host, EVENT_NOTBUSY); | ||
1819 | tasklet_schedule(&host->tasklet); | 1978 | tasklet_schedule(&host->tasklet); |
1820 | } | 1979 | } |
1980 | |||
1821 | if (pending & ATMCI_RXRDY) | 1981 | if (pending & ATMCI_RXRDY) |
1822 | atmci_read_data_pio(host); | 1982 | atmci_read_data_pio(host); |
1823 | if (pending & ATMCI_TXRDY) | 1983 | if (pending & ATMCI_TXRDY) |
1824 | atmci_write_data_pio(host); | 1984 | atmci_write_data_pio(host); |
1825 | 1985 | ||
1826 | if (pending & ATMCI_CMDRDY) | 1986 | if (pending & ATMCI_CMDRDY) { |
1827 | atmci_cmd_interrupt(host, status); | 1987 | dev_dbg(&host->pdev->dev, "IRQ: cmd ready\n"); |
1988 | atmci_writel(host, ATMCI_IDR, ATMCI_CMDRDY); | ||
1989 | host->cmd_status = status; | ||
1990 | smp_wmb(); | ||
1991 | dev_dbg(&host->pdev->dev, "set pending cmd rdy\n"); | ||
1992 | atmci_set_pending(host, EVENT_CMD_RDY); | ||
1993 | tasklet_schedule(&host->tasklet); | ||
1994 | } | ||
1828 | 1995 | ||
1829 | if (pending & (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB)) | 1996 | if (pending & (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB)) |
1830 | atmci_sdio_interrupt(host, status); | 1997 | atmci_sdio_interrupt(host, status); |
@@ -1877,13 +2044,26 @@ static int __init atmci_init_slot(struct atmel_mci *host, | |||
1877 | mmc->caps |= MMC_CAP_SDIO_IRQ; | 2044 | mmc->caps |= MMC_CAP_SDIO_IRQ; |
1878 | if (host->caps.has_highspeed) | 2045 | if (host->caps.has_highspeed) |
1879 | mmc->caps |= MMC_CAP_SD_HIGHSPEED; | 2046 | mmc->caps |= MMC_CAP_SD_HIGHSPEED; |
1880 | if (slot_data->bus_width >= 4) | 2047 | /* |
2048 | * Without the read/write proof capability, it is strongly suggested to | ||
2049 | * use only one bit for data to prevent fifo underruns and overruns | ||
2050 | * which will corrupt data. | ||
2051 | */ | ||
2052 | if ((slot_data->bus_width >= 4) && host->caps.has_rwproof) | ||
1881 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 2053 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
1882 | 2054 | ||
1883 | mmc->max_segs = 64; | 2055 | if (atmci_get_version(host) < 0x200) { |
1884 | mmc->max_req_size = 32768 * 512; | 2056 | mmc->max_segs = 256; |
1885 | mmc->max_blk_size = 32768; | 2057 | mmc->max_blk_size = 4095; |
1886 | mmc->max_blk_count = 512; | 2058 | mmc->max_blk_count = 256; |
2059 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | ||
2060 | mmc->max_seg_size = mmc->max_blk_size * mmc->max_segs; | ||
2061 | } else { | ||
2062 | mmc->max_segs = 64; | ||
2063 | mmc->max_req_size = 32768 * 512; | ||
2064 | mmc->max_blk_size = 32768; | ||
2065 | mmc->max_blk_count = 512; | ||
2066 | } | ||
1887 | 2067 | ||
1888 | /* Assume card is present initially */ | 2068 | /* Assume card is present initially */ |
1889 | set_bit(ATMCI_CARD_PRESENT, &slot->flags); | 2069 | set_bit(ATMCI_CARD_PRESENT, &slot->flags); |
@@ -2007,11 +2187,6 @@ static bool atmci_configure_dma(struct atmel_mci *host) | |||
2007 | } | 2187 | } |
2008 | } | 2188 | } |
2009 | 2189 | ||
2010 | static inline unsigned int atmci_get_version(struct atmel_mci *host) | ||
2011 | { | ||
2012 | return atmci_readl(host, ATMCI_VERSION) & 0x00000fff; | ||
2013 | } | ||
2014 | |||
2015 | /* | 2190 | /* |
2016 | * HSMCI (High Speed MCI) module is not fully compatible with MCI module. | 2191 | * HSMCI (High Speed MCI) module is not fully compatible with MCI module. |
2017 | * HSMCI provides DMA support and a new config register but no more supports | 2192 | * HSMCI provides DMA support and a new config register but no more supports |
@@ -2032,6 +2207,9 @@ static void __init atmci_get_cap(struct atmel_mci *host) | |||
2032 | host->caps.has_highspeed = 0; | 2207 | host->caps.has_highspeed = 0; |
2033 | host->caps.has_rwproof = 0; | 2208 | host->caps.has_rwproof = 0; |
2034 | host->caps.has_odd_clk_div = 0; | 2209 | host->caps.has_odd_clk_div = 0; |
2210 | host->caps.has_bad_data_ordering = 1; | ||
2211 | host->caps.need_reset_after_xfer = 1; | ||
2212 | host->caps.need_blksz_mul_4 = 1; | ||
2035 | 2213 | ||
2036 | /* keep only major version number */ | 2214 | /* keep only major version number */ |
2037 | switch (version & 0xf00) { | 2215 | switch (version & 0xf00) { |
@@ -2051,7 +2229,11 @@ static void __init atmci_get_cap(struct atmel_mci *host) | |||
2051 | host->caps.has_highspeed = 1; | 2229 | host->caps.has_highspeed = 1; |
2052 | case 0x200: | 2230 | case 0x200: |
2053 | host->caps.has_rwproof = 1; | 2231 | host->caps.has_rwproof = 1; |
2232 | host->caps.need_blksz_mul_4 = 0; | ||
2054 | case 0x100: | 2233 | case 0x100: |
2234 | host->caps.has_bad_data_ordering = 0; | ||
2235 | host->caps.need_reset_after_xfer = 0; | ||
2236 | case 0x0: | ||
2055 | break; | 2237 | break; |
2056 | default: | 2238 | default: |
2057 | host->caps.has_pdc = 0; | 2239 | host->caps.has_pdc = 0; |
@@ -2138,14 +2320,20 @@ static int __init atmci_probe(struct platform_device *pdev) | |||
2138 | if (pdata->slot[0].bus_width) { | 2320 | if (pdata->slot[0].bus_width) { |
2139 | ret = atmci_init_slot(host, &pdata->slot[0], | 2321 | ret = atmci_init_slot(host, &pdata->slot[0], |
2140 | 0, ATMCI_SDCSEL_SLOT_A, ATMCI_SDIOIRQA); | 2322 | 0, ATMCI_SDCSEL_SLOT_A, ATMCI_SDIOIRQA); |
2141 | if (!ret) | 2323 | if (!ret) { |
2142 | nr_slots++; | 2324 | nr_slots++; |
2325 | host->buf_size = host->slot[0]->mmc->max_req_size; | ||
2326 | } | ||
2143 | } | 2327 | } |
2144 | if (pdata->slot[1].bus_width) { | 2328 | if (pdata->slot[1].bus_width) { |
2145 | ret = atmci_init_slot(host, &pdata->slot[1], | 2329 | ret = atmci_init_slot(host, &pdata->slot[1], |
2146 | 1, ATMCI_SDCSEL_SLOT_B, ATMCI_SDIOIRQB); | 2330 | 1, ATMCI_SDCSEL_SLOT_B, ATMCI_SDIOIRQB); |
2147 | if (!ret) | 2331 | if (!ret) { |
2148 | nr_slots++; | 2332 | nr_slots++; |
2333 | if (host->slot[1]->mmc->max_req_size > host->buf_size) | ||
2334 | host->buf_size = | ||
2335 | host->slot[1]->mmc->max_req_size; | ||
2336 | } | ||
2149 | } | 2337 | } |
2150 | 2338 | ||
2151 | if (!nr_slots) { | 2339 | if (!nr_slots) { |
@@ -2153,6 +2341,19 @@ static int __init atmci_probe(struct platform_device *pdev) | |||
2153 | goto err_init_slot; | 2341 | goto err_init_slot; |
2154 | } | 2342 | } |
2155 | 2343 | ||
2344 | if (!host->caps.has_rwproof) { | ||
2345 | host->buffer = dma_alloc_coherent(&pdev->dev, host->buf_size, | ||
2346 | &host->buf_phys_addr, | ||
2347 | GFP_KERNEL); | ||
2348 | if (!host->buffer) { | ||
2349 | ret = -ENOMEM; | ||
2350 | dev_err(&pdev->dev, "buffer allocation failed\n"); | ||
2351 | goto err_init_slot; | ||
2352 | } | ||
2353 | } | ||
2354 | |||
2355 | setup_timer(&host->timer, atmci_timeout_timer, (unsigned long)host); | ||
2356 | |||
2156 | dev_info(&pdev->dev, | 2357 | dev_info(&pdev->dev, |
2157 | "Atmel MCI controller at 0x%08lx irq %d, %u slots\n", | 2358 | "Atmel MCI controller at 0x%08lx irq %d, %u slots\n", |
2158 | host->mapbase, irq, nr_slots); | 2359 | host->mapbase, irq, nr_slots); |
@@ -2179,6 +2380,10 @@ static int __exit atmci_remove(struct platform_device *pdev) | |||
2179 | 2380 | ||
2180 | platform_set_drvdata(pdev, NULL); | 2381 | platform_set_drvdata(pdev, NULL); |
2181 | 2382 | ||
2383 | if (host->buffer) | ||
2384 | dma_free_coherent(&pdev->dev, host->buf_size, | ||
2385 | host->buffer, host->buf_phys_addr); | ||
2386 | |||
2182 | for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) { | 2387 | for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) { |
2183 | if (host->slot[i]) | 2388 | if (host->slot[i]) |
2184 | atmci_cleanup_slot(host->slot[i], i); | 2389 | atmci_cleanup_slot(host->slot[i], i); |