Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mmc: s3cmci: port DMA code to dmaengine API

Utilise new s3c24xx-dma dmaengine driver for DMA ops.

Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>

authored by

Vasily Khoruzhick and committed by
Ulf Hansson
b45e4b50 1b3f626e

+52 -142
+1 -9
drivers/mmc/host/Kconfig
··· 440 440 config MMC_S3C 441 441 tristate "Samsung S3C SD/MMC Card Interface support" 442 442 depends on ARCH_S3C24XX 443 + depends on S3C24XX_DMAC 443 444 help 444 445 This selects a driver for the MCI interface found in 445 446 Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs. ··· 477 476 Currently, the DMA support in this driver seems to not be 478 477 working properly and needs to be debugged before this 479 478 option is useful. 480 - 481 - config MMC_S3C_PIODMA 482 - bool "Support for both PIO and DMA" 483 - help 484 - Compile both the PIO and DMA transfer routines into the 485 - driver and let the platform select at run-time which one 486 - is best. 487 - 488 - See notes for the DMA option. 489 479 490 480 endchoice 491 481
+50 -130
drivers/mmc/host/s3cmci.c
··· 12 12 */ 13 13 14 14 #include <linux/module.h> 15 + #include <linux/dmaengine.h> 15 16 #include <linux/dma-mapping.h> 16 17 #include <linux/clk.h> 17 18 #include <linux/mmc/host.h> ··· 28 27 #include <mach/dma.h> 29 28 #include <mach/gpio-samsung.h> 30 29 30 + #include <linux/platform_data/dma-s3c24xx.h> 31 31 #include <linux/platform_data/mmc-s3cmci.h> 32 32 33 33 #include "s3cmci.h" ··· 142 140 dev_dbg(&host->pdev->dev, args); \ 143 141 } while (0) 144 142 145 - static struct s3c2410_dma_client s3cmci_dma_client = { 146 - .name = "s3c-mci", 147 - }; 148 - 149 143 static void finalize_request(struct s3cmci_host *host); 150 144 static void s3cmci_send_request(struct mmc_host *mmc); 151 145 static void s3cmci_reset(struct s3cmci_host *host); ··· 254 256 { 255 257 #ifdef CONFIG_MMC_S3C_PIO 256 258 return false; 257 - #elif defined(CONFIG_MMC_S3C_DMA) 259 + #else /* CONFIG_MMC_S3C_DMA */ 258 260 return true; 259 - #else 260 - return host->dodma; 261 - #endif 262 - } 263 - 264 - /** 265 - * s3cmci_host_canpio - return true if host has pio code available 266 - * 267 - * Return true if the driver has been compiled with the PIO support code 268 - * available. 269 - */ 270 - static inline bool s3cmci_host_canpio(void) 271 - { 272 - #ifdef CONFIG_MMC_S3C_PIO 273 - return true; 274 - #else 275 - return false; 276 261 #endif 277 262 } 278 263 ··· 822 841 return IRQ_HANDLED; 823 842 } 824 843 825 - static void s3cmci_dma_done_callback(struct s3c2410_dma_chan *dma_ch, 826 - void *buf_id, int size, 827 - enum s3c2410_dma_buffresult result) 844 + static void s3cmci_dma_done_callback(void *arg) 828 845 { 829 - struct s3cmci_host *host = buf_id; 846 + struct s3cmci_host *host = arg; 830 847 unsigned long iflags; 831 - u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt; 832 - 833 - mci_csta = readl(host->base + S3C2410_SDICMDSTAT); 834 - mci_dsta = readl(host->base + S3C2410_SDIDSTA); 835 - mci_fsta = readl(host->base + S3C2410_SDIFSTA); 836 - mci_dcnt = readl(host->base + S3C2410_SDIDCNT); 837 848 838 849 BUG_ON(!host->mrq); 839 850 BUG_ON(!host->mrq->data); 840 - BUG_ON(!host->dmatogo); 841 851 842 852 spin_lock_irqsave(&host->complete_lock, iflags); 843 853 844 - if (result != S3C2410_RES_OK) { 845 - dbg(host, dbg_fail, "DMA FAILED: csta=0x%08x dsta=0x%08x " 846 - "fsta=0x%08x dcnt:0x%08x result:0x%08x toGo:%u\n", 847 - mci_csta, mci_dsta, mci_fsta, 848 - mci_dcnt, result, host->dmatogo); 849 - 850 - goto fail_request; 851 - } 852 - 853 - host->dmatogo--; 854 - if (host->dmatogo) { 855 - dbg(host, dbg_dma, "DMA DONE Size:%i DSTA:[%08x] " 856 - "DCNT:[%08x] toGo:%u\n", 857 - size, mci_dsta, mci_dcnt, host->dmatogo); 858 - 859 - goto out; 860 - } 861 - 862 - dbg(host, dbg_dma, "DMA FINISHED Size:%i DSTA:%08x DCNT:%08x\n", 863 - size, mci_dsta, mci_dcnt); 854 + dbg(host, dbg_dma, "DMA FINISHED\n"); 864 855 865 856 host->dma_complete = 1; 866 857 host->complete_what = COMPLETION_FINALIZE; 867 858 868 - out: 869 859 tasklet_schedule(&host->pio_tasklet); 870 860 spin_unlock_irqrestore(&host->complete_lock, iflags); 871 - return; 872 861 873 - fail_request: 874 - host->mrq->data->error = -EINVAL; 875 - host->complete_what = COMPLETION_FINALIZE; 876 - clear_imask(host); 877 - 878 - goto out; 879 862 } 880 863 881 864 static void finalize_request(struct s3cmci_host *host) ··· 911 966 * DMA channel and the fifo to clear out any garbage. */ 912 967 if (mrq->data->error != 0) { 913 968 if (s3cmci_host_usedma(host)) 914 - s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH); 969 + dmaengine_terminate_all(host->dma); 915 970 916 971 if (host->is2440) { 917 972 /* Clear failure register and reset fifo. */ ··· 935 990 936 991 s3cmci_check_sdio_irq(host); 937 992 mmc_request_done(host->mmc, mrq); 938 - } 939 - 940 - static void s3cmci_dma_setup(struct s3cmci_host *host, 941 - enum dma_data_direction source) 942 - { 943 - static enum dma_data_direction last_source = -1; 944 - static int setup_ok; 945 - 946 - if (last_source == source) 947 - return; 948 - 949 - last_source = source; 950 - 951 - s3c2410_dma_devconfig(host->dma, source, 952 - host->mem->start + host->sdidata); 953 - 954 - if (!setup_ok) { 955 - s3c2410_dma_config(host->dma, 4); 956 - s3c2410_dma_set_buffdone_fn(host->dma, 957 - s3cmci_dma_done_callback); 958 - s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART); 959 - setup_ok = 1; 960 - } 961 993 } 962 994 963 995 static void s3cmci_send_command(struct s3cmci_host *host, ··· 1084 1162 1085 1163 static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data) 1086 1164 { 1087 - int dma_len, i; 1088 1165 int rw = data->flags & MMC_DATA_WRITE; 1166 + struct dma_async_tx_descriptor *desc; 1167 + struct dma_slave_config conf = { 1168 + .src_addr = host->mem->start + host->sdidata, 1169 + .dst_addr = host->mem->start + host->sdidata, 1170 + .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, 1171 + .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, 1172 + }; 1089 1173 1090 1174 BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR); 1091 1175 1092 - s3cmci_dma_setup(host, rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE); 1093 - s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH); 1176 + /* Restore prescaler value */ 1177 + writel(host->prescaler, host->base + S3C2410_SDIPRE); 1094 1178 1095 - dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, 1179 + if (!rw) 1180 + conf.direction = DMA_DEV_TO_MEM; 1181 + else 1182 + conf.direction = DMA_MEM_TO_DEV; 1183 + 1184 + dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, 1096 1185 rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE); 1097 1186 1098 - if (dma_len == 0) 1099 - return -ENOMEM; 1100 - 1101 - host->dma_complete = 0; 1102 - host->dmatogo = dma_len; 1103 - 1104 - for (i = 0; i < dma_len; i++) { 1105 - int res; 1106 - 1107 - dbg(host, dbg_dma, "enqueue %i: %08x@%u\n", i, 1108 - sg_dma_address(&data->sg[i]), 1109 - sg_dma_len(&data->sg[i])); 1110 - 1111 - res = s3c2410_dma_enqueue(host->dma, host, 1112 - sg_dma_address(&data->sg[i]), 1113 - sg_dma_len(&data->sg[i])); 1114 - 1115 - if (res) { 1116 - s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH); 1117 - return -EBUSY; 1118 - } 1119 - } 1120 - 1121 - s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_START); 1187 + dmaengine_slave_config(host->dma, &conf); 1188 + desc = dmaengine_prep_slave_sg(host->dma, data->sg, data->sg_len, 1189 + conf.direction, 1190 + DMA_CTRL_ACK | DMA_PREP_INTERRUPT); 1191 + if (!desc) 1192 + goto unmap_exit; 1193 + desc->callback = s3cmci_dma_done_callback; 1194 + desc->callback_param = host; 1195 + dmaengine_submit(desc); 1196 + dma_async_issue_pending(host->dma); 1122 1197 1123 1198 return 0; 1199 + 1200 + unmap_exit: 1201 + dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, 1202 + rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE); 1203 + return -ENOMEM; 1124 1204 } 1125 1205 1126 1206 static void s3cmci_send_request(struct mmc_host *mmc) ··· 1600 1676 host->complete_what = COMPLETION_NONE; 1601 1677 host->pio_active = XFER_NONE; 1602 1678 1603 - #ifdef CONFIG_MMC_S3C_PIODMA 1604 - host->dodma = host->pdata->use_dma; 1605 - #endif 1606 - 1607 1679 host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1608 1680 if (!host->mem) { 1609 1681 dev_err(&pdev->dev, ··· 1685 1765 /* depending on the dma state, get a dma channel to use. */ 1686 1766 1687 1767 if (s3cmci_host_usedma(host)) { 1688 - host->dma = s3c2410_dma_request(DMACH_SDI, &s3cmci_dma_client, 1689 - host); 1690 - if (host->dma < 0) { 1768 + dma_cap_mask_t mask; 1769 + 1770 + dma_cap_zero(mask); 1771 + dma_cap_set(DMA_SLAVE, mask); 1772 + 1773 + host->dma = dma_request_slave_channel_compat(mask, 1774 + s3c24xx_dma_filter, (void *)DMACH_SDI, &pdev->dev, "rx-tx"); 1775 + if (!host->dma) { 1691 1776 dev_err(&pdev->dev, "cannot get DMA channel.\n"); 1692 - if (!s3cmci_host_canpio()) { 1693 - ret = -EBUSY; 1694 - goto probe_free_gpio_wp; 1695 - } else { 1696 - dev_warn(&pdev->dev, "falling back to PIO.\n"); 1697 - host->dodma = 0; 1698 - } 1777 + ret = -EBUSY; 1778 + goto probe_free_gpio_wp; 1699 1779 } 1700 1780 } 1701 1781 ··· 1736 1816 mmc->max_segs = 128; 1737 1817 1738 1818 dbg(host, dbg_debug, 1739 - "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n", 1819 + "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%p.\n", 1740 1820 (host->is2440?"2440":""), 1741 1821 host->base, host->irq, host->irq_cd, host->dma); 1742 1822 ··· 1772 1852 1773 1853 probe_free_dma: 1774 1854 if (s3cmci_host_usedma(host)) 1775 - s3c2410_dma_free(host->dma, &s3cmci_dma_client); 1855 + dma_release_channel(host->dma); 1776 1856 1777 1857 probe_free_gpio_wp: 1778 1858 if (!host->pdata->no_wprotect) ··· 1834 1914 tasklet_disable(&host->pio_tasklet); 1835 1915 1836 1916 if (s3cmci_host_usedma(host)) 1837 - s3c2410_dma_free(host->dma, &s3cmci_dma_client); 1917 + dma_release_channel(host->dma); 1838 1918 1839 1919 free_irq(host->irq, host); 1840 1920
+1 -3
drivers/mmc/host/s3cmci.h
··· 26 26 void __iomem *base; 27 27 int irq; 28 28 int irq_cd; 29 - int dma; 29 + struct dma_chan *dma; 30 30 31 31 unsigned long clk_rate; 32 32 unsigned long clk_div; ··· 36 36 int is2440; 37 37 unsigned sdiimsk; 38 38 unsigned sdidata; 39 - int dodma; 40 - int dmatogo; 41 39 42 40 bool irq_disabled; 43 41 bool irq_enabled;