aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorLudovic Desroches <ludovic.desroches@atmel.com>2012-05-16 09:25:58 -0400
committerChris Ball <cjb@laptop.org>2012-05-17 08:41:10 -0400
commit7a90dcc2d7ceb64bb37044a8d2ee462b936ddf73 (patch)
treef644f917c2d1e48e94830b6cd30cc0af580513c9 /drivers/mmc
parent705ad0472bd55fa38e6c594b2d6318c31e86068a (diff)
mmc: atmel-mci: the r/w proof capability lack was not well managed
First mci IPs (mainly on rm9200 and 9261) don't have the r/w proof capability. The driver didn't work correctly without this capability in PDC mode because of the double buffer switch which is too slow even if we stop the transfer to perform this switch. Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/atmel-mci.c92
1 files changed, 78 insertions, 14 deletions
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index e94476beca18..6f56ef025ab5 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -91,6 +91,11 @@ struct atmel_mci_dma {
91 * @regs: Pointer to MMIO registers. 91 * @regs: Pointer to MMIO registers.
92 * @sg: Scatterlist entry currently being processed by PIO or PDC code. 92 * @sg: Scatterlist entry currently being processed by PIO or PDC code.
93 * @pio_offset: Offset into the current scatterlist entry. 93 * @pio_offset: Offset into the current scatterlist entry.
94 * @buffer: Buffer used if we don't have the r/w proof capability. We
95 * don't have the time to switch pdc buffers so we have to use only
96 * one buffer for the full transaction.
97 * @buf_size: size of the buffer.
98 * @phys_buf_addr: buffer address needed for pdc.
94 * @cur_slot: The slot which is currently using the controller. 99 * @cur_slot: The slot which is currently using the controller.
95 * @mrq: The request currently being processed on @cur_slot, 100 * @mrq: The request currently being processed on @cur_slot,
96 * or NULL if the controller is idle. 101 * or NULL if the controller is idle.
@@ -166,6 +171,9 @@ struct atmel_mci {
166 171
167 struct scatterlist *sg; 172 struct scatterlist *sg;
168 unsigned int pio_offset; 173 unsigned int pio_offset;
174 unsigned int *buffer;
175 unsigned int buf_size;
176 dma_addr_t buf_phys_addr;
169 177
170 struct atmel_mci_slot *cur_slot; 178 struct atmel_mci_slot *cur_slot;
171 struct mmc_request *mrq; 179 struct mmc_request *mrq;
@@ -480,6 +488,11 @@ err:
480 dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); 488 dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n");
481} 489}
482 490
491static inline unsigned int atmci_get_version(struct atmel_mci *host)
492{
493 return atmci_readl(host, ATMCI_VERSION) & 0x00000fff;
494}
495
483static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host, 496static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host,
484 unsigned int ns) 497 unsigned int ns)
485{ 498{
@@ -603,6 +616,7 @@ static void atmci_pdc_set_single_buf(struct atmel_mci *host,
603 enum atmci_xfer_dir dir, enum atmci_pdc_buf buf_nb) 616 enum atmci_xfer_dir dir, enum atmci_pdc_buf buf_nb)
604{ 617{
605 u32 pointer_reg, counter_reg; 618 u32 pointer_reg, counter_reg;
619 unsigned int buf_size;
606 620
607 if (dir == XFER_RECEIVE) { 621 if (dir == XFER_RECEIVE) {
608 pointer_reg = ATMEL_PDC_RPR; 622 pointer_reg = ATMEL_PDC_RPR;
@@ -617,8 +631,15 @@ static void atmci_pdc_set_single_buf(struct atmel_mci *host,
617 counter_reg += ATMEL_PDC_SCND_BUF_OFF; 631 counter_reg += ATMEL_PDC_SCND_BUF_OFF;
618 } 632 }
619 633
620 atmci_writel(host, pointer_reg, sg_dma_address(host->sg)); 634 if (!host->caps.has_rwproof) {
621 if (host->data_size <= sg_dma_len(host->sg)) { 635 buf_size = host->buf_size;
636 atmci_writel(host, pointer_reg, host->buf_phys_addr);
637 } else {
638 buf_size = sg_dma_len(host->sg);
639 atmci_writel(host, pointer_reg, sg_dma_address(host->sg));
640 }
641
642 if (host->data_size <= buf_size) {
622 if (host->data_size & 0x3) { 643 if (host->data_size & 0x3) {
623 /* If size is different from modulo 4, transfer bytes */ 644 /* If size is different from modulo 4, transfer bytes */
624 atmci_writel(host, counter_reg, host->data_size); 645 atmci_writel(host, counter_reg, host->data_size);
@@ -670,7 +691,15 @@ static void atmci_pdc_cleanup(struct atmel_mci *host)
670 */ 691 */
671static void atmci_pdc_complete(struct atmel_mci *host) 692static void atmci_pdc_complete(struct atmel_mci *host)
672{ 693{
694 int transfer_size = host->data->blocks * host->data->blksz;
695
673 atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS); 696 atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
697
698 if ((!host->caps.has_rwproof)
699 && (host->data->flags & MMC_DATA_READ))
700 sg_copy_from_buffer(host->data->sg, host->data->sg_len,
701 host->buffer, transfer_size);
702
674 atmci_pdc_cleanup(host); 703 atmci_pdc_cleanup(host);
675 704
676 /* 705 /*
@@ -818,6 +847,12 @@ atmci_prepare_data_pdc(struct atmel_mci *host, struct mmc_data *data)
818 /* Configure PDC */ 847 /* Configure PDC */
819 host->data_size = data->blocks * data->blksz; 848 host->data_size = data->blocks * data->blksz;
820 sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, dir); 849 sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, dir);
850
851 if ((!host->caps.has_rwproof)
852 && (host->data->flags & MMC_DATA_WRITE))
853 sg_copy_to_buffer(host->data->sg, host->data->sg_len,
854 host->buffer, host->data_size);
855
821 if (host->data_size) 856 if (host->data_size)
822 atmci_pdc_set_both_buf(host, 857 atmci_pdc_set_both_buf(host,
823 ((dir == DMA_FROM_DEVICE) ? XFER_RECEIVE : XFER_TRANSMIT)); 858 ((dir == DMA_FROM_DEVICE) ? XFER_RECEIVE : XFER_TRANSMIT));
@@ -1877,13 +1912,26 @@ static int __init atmci_init_slot(struct atmel_mci *host,
1877 mmc->caps |= MMC_CAP_SDIO_IRQ; 1912 mmc->caps |= MMC_CAP_SDIO_IRQ;
1878 if (host->caps.has_highspeed) 1913 if (host->caps.has_highspeed)
1879 mmc->caps |= MMC_CAP_SD_HIGHSPEED; 1914 mmc->caps |= MMC_CAP_SD_HIGHSPEED;
1880 if (slot_data->bus_width >= 4) 1915 /*
1916 * Without the read/write proof capability, it is strongly suggested to
1917 * use only one bit for data to prevent fifo underruns and overruns
1918 * which will corrupt data.
1919 */
1920 if ((slot_data->bus_width >= 4) && host->caps.has_rwproof)
1881 mmc->caps |= MMC_CAP_4_BIT_DATA; 1921 mmc->caps |= MMC_CAP_4_BIT_DATA;
1882 1922
1883 mmc->max_segs = 64; 1923 if (atmci_get_version(host) < 0x200) {
1884 mmc->max_req_size = 32768 * 512; 1924 mmc->max_segs = 256;
1885 mmc->max_blk_size = 32768; 1925 mmc->max_blk_size = 4095;
1886 mmc->max_blk_count = 512; 1926 mmc->max_blk_count = 256;
1927 mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
1928 mmc->max_seg_size = mmc->max_blk_size * mmc->max_segs;
1929 } else {
1930 mmc->max_segs = 64;
1931 mmc->max_req_size = 32768 * 512;
1932 mmc->max_blk_size = 32768;
1933 mmc->max_blk_count = 512;
1934 }
1887 1935
1888 /* Assume card is present initially */ 1936 /* Assume card is present initially */
1889 set_bit(ATMCI_CARD_PRESENT, &slot->flags); 1937 set_bit(ATMCI_CARD_PRESENT, &slot->flags);
@@ -2007,11 +2055,6 @@ static bool atmci_configure_dma(struct atmel_mci *host)
2007 } 2055 }
2008} 2056}
2009 2057
2010static inline unsigned int atmci_get_version(struct atmel_mci *host)
2011{
2012 return atmci_readl(host, ATMCI_VERSION) & 0x00000fff;
2013}
2014
2015/* 2058/*
2016 * HSMCI (High Speed MCI) module is not fully compatible with MCI module. 2059 * 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 2060 * HSMCI provides DMA support and a new config register but no more supports
@@ -2138,14 +2181,20 @@ static int __init atmci_probe(struct platform_device *pdev)
2138 if (pdata->slot[0].bus_width) { 2181 if (pdata->slot[0].bus_width) {
2139 ret = atmci_init_slot(host, &pdata->slot[0], 2182 ret = atmci_init_slot(host, &pdata->slot[0],
2140 0, ATMCI_SDCSEL_SLOT_A, ATMCI_SDIOIRQA); 2183 0, ATMCI_SDCSEL_SLOT_A, ATMCI_SDIOIRQA);
2141 if (!ret) 2184 if (!ret) {
2142 nr_slots++; 2185 nr_slots++;
2186 host->buf_size = host->slot[0]->mmc->max_req_size;
2187 }
2143 } 2188 }
2144 if (pdata->slot[1].bus_width) { 2189 if (pdata->slot[1].bus_width) {
2145 ret = atmci_init_slot(host, &pdata->slot[1], 2190 ret = atmci_init_slot(host, &pdata->slot[1],
2146 1, ATMCI_SDCSEL_SLOT_B, ATMCI_SDIOIRQB); 2191 1, ATMCI_SDCSEL_SLOT_B, ATMCI_SDIOIRQB);
2147 if (!ret) 2192 if (!ret) {
2148 nr_slots++; 2193 nr_slots++;
2194 if (host->slot[1]->mmc->max_req_size > host->buf_size)
2195 host->buf_size =
2196 host->slot[1]->mmc->max_req_size;
2197 }
2149 } 2198 }
2150 2199
2151 if (!nr_slots) { 2200 if (!nr_slots) {
@@ -2153,6 +2202,17 @@ static int __init atmci_probe(struct platform_device *pdev)
2153 goto err_init_slot; 2202 goto err_init_slot;
2154 } 2203 }
2155 2204
2205 if (!host->caps.has_rwproof) {
2206 host->buffer = dma_alloc_coherent(&pdev->dev, host->buf_size,
2207 &host->buf_phys_addr,
2208 GFP_KERNEL);
2209 if (!host->buffer) {
2210 ret = -ENOMEM;
2211 dev_err(&pdev->dev, "buffer allocation failed\n");
2212 goto err_init_slot;
2213 }
2214 }
2215
2156 dev_info(&pdev->dev, 2216 dev_info(&pdev->dev,
2157 "Atmel MCI controller at 0x%08lx irq %d, %u slots\n", 2217 "Atmel MCI controller at 0x%08lx irq %d, %u slots\n",
2158 host->mapbase, irq, nr_slots); 2218 host->mapbase, irq, nr_slots);
@@ -2179,6 +2239,10 @@ static int __exit atmci_remove(struct platform_device *pdev)
2179 2239
2180 platform_set_drvdata(pdev, NULL); 2240 platform_set_drvdata(pdev, NULL);
2181 2241
2242 if (host->buffer)
2243 dma_free_coherent(&pdev->dev, host->buf_size,
2244 host->buffer, host->buf_phys_addr);
2245
2182 for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) { 2246 for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
2183 if (host->slot[i]) 2247 if (host->slot[i])
2184 atmci_cleanup_slot(host->slot[i], i); 2248 atmci_cleanup_slot(host->slot[i], i);