diff options
| author | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-04-21 17:41:10 -0400 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-07-31 07:06:23 -0400 |
| commit | 4e078fbd581a92fa26ba2def4ac8f2a633cdcb5b (patch) | |
| tree | 6dae1ad3a0ffa44b762d2723ce8ee00e035c01ca | |
| parent | 3451c06754b5777d227aa99f85c35bdfabac3ca0 (diff) | |
mmc: omap: remove private DMA API implementation
Remove the private DMA API implementation from omap, making it use
entirely the DMA engine API.
Tested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
| -rw-r--r-- | drivers/mmc/host/omap.c | 235 |
1 files changed, 6 insertions, 229 deletions
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 25e7efee5733..50e08f03aa65 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c | |||
| @@ -101,8 +101,6 @@ | |||
| 101 | 101 | ||
| 102 | struct mmc_omap_host; | 102 | struct mmc_omap_host; |
| 103 | 103 | ||
| 104 | #define USE_DMA_PRIVATE | ||
| 105 | |||
| 106 | struct mmc_omap_slot { | 104 | struct mmc_omap_slot { |
| 107 | int id; | 105 | int id; |
| 108 | unsigned int vdd; | 106 | unsigned int vdd; |
| @@ -162,12 +160,6 @@ struct mmc_omap_host { | |||
| 162 | unsigned use_dma:1; | 160 | unsigned use_dma:1; |
| 163 | unsigned brs_received:1, dma_done:1; | 161 | unsigned brs_received:1, dma_done:1; |
| 164 | unsigned dma_in_use:1; | 162 | unsigned dma_in_use:1; |
| 165 | #ifdef USE_DMA_PRIVATE | ||
| 166 | unsigned dma_is_read:1; | ||
| 167 | int dma_ch; | ||
| 168 | struct timer_list dma_timer; | ||
| 169 | unsigned dma_len; | ||
| 170 | #endif | ||
| 171 | spinlock_t dma_lock; | 163 | spinlock_t dma_lock; |
| 172 | 164 | ||
| 173 | struct mmc_omap_slot *slots[OMAP_MMC_MAX_SLOTS]; | 165 | struct mmc_omap_slot *slots[OMAP_MMC_MAX_SLOTS]; |
| @@ -419,13 +411,6 @@ mmc_omap_release_dma(struct mmc_omap_host *host, struct mmc_data *data, | |||
| 419 | struct device *dev = mmc_dev(host->mmc); | 411 | struct device *dev = mmc_dev(host->mmc); |
| 420 | struct dma_chan *c; | 412 | struct dma_chan *c; |
| 421 | 413 | ||
| 422 | #ifdef USE_DMA_PRIVATE | ||
| 423 | BUG_ON(host->dma_ch < 0); | ||
| 424 | if (data->error) | ||
| 425 | omap_stop_dma(host->dma_ch); | ||
| 426 | /* Release DMA channel lazily */ | ||
| 427 | mod_timer(&host->dma_timer, jiffies + HZ); | ||
| 428 | #endif | ||
| 429 | if (data->flags & MMC_DATA_WRITE) { | 414 | if (data->flags & MMC_DATA_WRITE) { |
| 430 | dma_data_dir = DMA_TO_DEVICE; | 415 | dma_data_dir = DMA_TO_DEVICE; |
| 431 | c = host->dma_tx; | 416 | c = host->dma_tx; |
| @@ -548,18 +533,6 @@ mmc_omap_end_of_data(struct mmc_omap_host *host, struct mmc_data *data) | |||
| 548 | mmc_omap_xfer_done(host, data); | 533 | mmc_omap_xfer_done(host, data); |
| 549 | } | 534 | } |
| 550 | 535 | ||
| 551 | #ifdef USE_DMA_PRIVATE | ||
| 552 | static void | ||
| 553 | mmc_omap_dma_timer(unsigned long data) | ||
| 554 | { | ||
| 555 | struct mmc_omap_host *host = (struct mmc_omap_host *) data; | ||
| 556 | |||
| 557 | BUG_ON(host->dma_ch < 0); | ||
| 558 | omap_free_dma(host->dma_ch); | ||
| 559 | host->dma_ch = -1; | ||
| 560 | } | ||
| 561 | #endif | ||
| 562 | |||
| 563 | static void | 536 | static void |
| 564 | mmc_omap_dma_done(struct mmc_omap_host *host, struct mmc_data *data) | 537 | mmc_omap_dma_done(struct mmc_omap_host *host, struct mmc_data *data) |
| 565 | { | 538 | { |
| @@ -928,163 +901,6 @@ static void mmc_omap_dma_callback(void *priv) | |||
| 928 | mmc_omap_dma_done(host, data); | 901 | mmc_omap_dma_done(host, data); |
| 929 | } | 902 | } |
| 930 | 903 | ||
| 931 | #ifdef USE_DMA_PRIVATE | ||
| 932 | /* Prepare to transfer the next segment of a scatterlist */ | ||
| 933 | static void | ||
| 934 | mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) | ||
| 935 | { | ||
| 936 | int dma_ch = host->dma_ch; | ||
| 937 | unsigned long data_addr; | ||
| 938 | u16 buf, frame; | ||
| 939 | u32 count; | ||
| 940 | struct scatterlist *sg = &data->sg[host->sg_idx]; | ||
| 941 | int src_port = 0; | ||
| 942 | int dst_port = 0; | ||
| 943 | int sync_dev = 0; | ||
| 944 | |||
| 945 | data_addr = host->phys_base + OMAP_MMC_REG(host, DATA); | ||
| 946 | frame = data->blksz; | ||
| 947 | count = sg_dma_len(sg); | ||
| 948 | |||
| 949 | if ((data->blocks == 1) && (count > data->blksz)) | ||
| 950 | count = frame; | ||
| 951 | |||
| 952 | host->dma_len = count; | ||
| 953 | |||
| 954 | /* FIFO is 16x2 bytes on 15xx, and 32x2 bytes on 16xx and 24xx. | ||
| 955 | * Use 16 or 32 word frames when the blocksize is at least that large. | ||
| 956 | * Blocksize is usually 512 bytes; but not for some SD reads. | ||
| 957 | */ | ||
| 958 | if (cpu_is_omap15xx() && frame > 32) | ||
| 959 | frame = 32; | ||
| 960 | else if (frame > 64) | ||
| 961 | frame = 64; | ||
| 962 | count /= frame; | ||
| 963 | frame >>= 1; | ||
| 964 | |||
| 965 | if (!(data->flags & MMC_DATA_WRITE)) { | ||
| 966 | buf = 0x800f | ((frame - 1) << 8); | ||
| 967 | |||
| 968 | if (cpu_class_is_omap1()) { | ||
| 969 | src_port = OMAP_DMA_PORT_TIPB; | ||
| 970 | dst_port = OMAP_DMA_PORT_EMIFF; | ||
| 971 | } | ||
| 972 | if (cpu_is_omap24xx()) | ||
| 973 | sync_dev = OMAP24XX_DMA_MMC1_RX; | ||
| 974 | |||
| 975 | omap_set_dma_src_params(dma_ch, src_port, | ||
| 976 | OMAP_DMA_AMODE_CONSTANT, | ||
| 977 | data_addr, 0, 0); | ||
| 978 | omap_set_dma_dest_params(dma_ch, dst_port, | ||
| 979 | OMAP_DMA_AMODE_POST_INC, | ||
| 980 | sg_dma_address(sg), 0, 0); | ||
| 981 | omap_set_dma_dest_data_pack(dma_ch, 1); | ||
| 982 | omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4); | ||
| 983 | } else { | ||
| 984 | buf = 0x0f80 | ((frame - 1) << 0); | ||
| 985 | |||
| 986 | if (cpu_class_is_omap1()) { | ||
| 987 | src_port = OMAP_DMA_PORT_EMIFF; | ||
| 988 | dst_port = OMAP_DMA_PORT_TIPB; | ||
| 989 | } | ||
| 990 | if (cpu_is_omap24xx()) | ||
| 991 | sync_dev = OMAP24XX_DMA_MMC1_TX; | ||
| 992 | |||
| 993 | omap_set_dma_dest_params(dma_ch, dst_port, | ||
| 994 | OMAP_DMA_AMODE_CONSTANT, | ||
| 995 | data_addr, 0, 0); | ||
| 996 | omap_set_dma_src_params(dma_ch, src_port, | ||
| 997 | OMAP_DMA_AMODE_POST_INC, | ||
| 998 | sg_dma_address(sg), 0, 0); | ||
| 999 | omap_set_dma_src_data_pack(dma_ch, 1); | ||
| 1000 | omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4); | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | /* Max limit for DMA frame count is 0xffff */ | ||
| 1004 | BUG_ON(count > 0xffff); | ||
| 1005 | |||
| 1006 | OMAP_MMC_WRITE(host, BUF, buf); | ||
| 1007 | omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16, | ||
| 1008 | frame, count, OMAP_DMA_SYNC_FRAME, | ||
| 1009 | sync_dev, 0); | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | /* A scatterlist segment completed */ | ||
| 1013 | static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data) | ||
| 1014 | { | ||
| 1015 | struct mmc_omap_host *host = (struct mmc_omap_host *) data; | ||
| 1016 | struct mmc_data *mmcdat = host->data; | ||
| 1017 | |||
| 1018 | if (unlikely(host->dma_ch < 0)) { | ||
| 1019 | dev_err(mmc_dev(host->mmc), | ||
| 1020 | "DMA callback while DMA not enabled\n"); | ||
| 1021 | return; | ||
| 1022 | } | ||
| 1023 | /* FIXME: We really should do something to _handle_ the errors */ | ||
| 1024 | if (ch_status & OMAP1_DMA_TOUT_IRQ) { | ||
| 1025 | dev_err(mmc_dev(host->mmc),"DMA timeout\n"); | ||
| 1026 | return; | ||
| 1027 | } | ||
| 1028 | if (ch_status & OMAP_DMA_DROP_IRQ) { | ||
| 1029 | dev_err(mmc_dev(host->mmc), "DMA sync error\n"); | ||
| 1030 | return; | ||
| 1031 | } | ||
| 1032 | if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) { | ||
| 1033 | return; | ||
| 1034 | } | ||
| 1035 | mmcdat->bytes_xfered += host->dma_len; | ||
| 1036 | host->sg_idx++; | ||
| 1037 | if (host->sg_idx < host->sg_len) { | ||
| 1038 | mmc_omap_prepare_dma(host, host->data); | ||
| 1039 | omap_start_dma(host->dma_ch); | ||
| 1040 | } else | ||
| 1041 | mmc_omap_dma_done(host, host->data); | ||
| 1042 | } | ||
| 1043 | |||
| 1044 | static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data *data) | ||
| 1045 | { | ||
| 1046 | const char *dma_dev_name; | ||
| 1047 | int sync_dev, dma_ch, is_read, r; | ||
| 1048 | |||
| 1049 | is_read = !(data->flags & MMC_DATA_WRITE); | ||
| 1050 | del_timer_sync(&host->dma_timer); | ||
| 1051 | if (host->dma_ch >= 0) { | ||
| 1052 | if (is_read == host->dma_is_read) | ||
| 1053 | return 0; | ||
| 1054 | omap_free_dma(host->dma_ch); | ||
| 1055 | host->dma_ch = -1; | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | if (is_read) { | ||
| 1059 | if (host->id == 0) { | ||
| 1060 | sync_dev = OMAP_DMA_MMC_RX; | ||
| 1061 | dma_dev_name = "MMC1 read"; | ||
| 1062 | } else { | ||
| 1063 | sync_dev = OMAP_DMA_MMC2_RX; | ||
| 1064 | dma_dev_name = "MMC2 read"; | ||
| 1065 | } | ||
| 1066 | } else { | ||
| 1067 | if (host->id == 0) { | ||
| 1068 | sync_dev = OMAP_DMA_MMC_TX; | ||
| 1069 | dma_dev_name = "MMC1 write"; | ||
| 1070 | } else { | ||
| 1071 | sync_dev = OMAP_DMA_MMC2_TX; | ||
| 1072 | dma_dev_name = "MMC2 write"; | ||
| 1073 | } | ||
| 1074 | } | ||
| 1075 | r = omap_request_dma(sync_dev, dma_dev_name, mmc_omap_dma_cb, | ||
| 1076 | host, &dma_ch); | ||
| 1077 | if (r != 0) { | ||
| 1078 | dev_dbg(mmc_dev(host->mmc), "omap_request_dma() failed with %d\n", r); | ||
| 1079 | return r; | ||
| 1080 | } | ||
| 1081 | host->dma_ch = dma_ch; | ||
| 1082 | host->dma_is_read = is_read; | ||
| 1083 | |||
| 1084 | return 0; | ||
| 1085 | } | ||
| 1086 | #endif | ||
| 1087 | |||
| 1088 | static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_request *req) | 904 | static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_request *req) |
| 1089 | { | 905 | { |
| 1090 | u16 reg; | 906 | u16 reg; |
| @@ -1229,38 +1045,13 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) | |||
| 1229 | return; | 1045 | return; |
| 1230 | } | 1046 | } |
| 1231 | use_pio: | 1047 | use_pio: |
| 1232 | #ifdef USE_DMA_PRIVATE | ||
| 1233 | if (use_dma) { | ||
| 1234 | if (mmc_omap_get_dma_channel(host, data) == 0) { | ||
| 1235 | enum dma_data_direction dma_data_dir; | ||
| 1236 | |||
| 1237 | if (data->flags & MMC_DATA_WRITE) | ||
| 1238 | dma_data_dir = DMA_TO_DEVICE; | ||
| 1239 | else | ||
| 1240 | dma_data_dir = DMA_FROM_DEVICE; | ||
| 1241 | |||
| 1242 | host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg, | ||
| 1243 | sg_len, dma_data_dir); | ||
| 1244 | host->total_bytes_left = 0; | ||
| 1245 | mmc_omap_prepare_dma(host, req->data); | ||
| 1246 | host->brs_received = 0; | ||
| 1247 | host->dma_done = 0; | ||
| 1248 | host->dma_in_use = 1; | ||
| 1249 | } else | ||
| 1250 | use_dma = 0; | ||
| 1251 | } | ||
| 1252 | #else | ||
| 1253 | use_dma = 0; | ||
| 1254 | #endif | ||
| 1255 | 1048 | ||
| 1256 | /* Revert to PIO? */ | 1049 | /* Revert to PIO? */ |
| 1257 | if (!use_dma) { | 1050 | OMAP_MMC_WRITE(host, BUF, 0x1f1f); |
| 1258 | OMAP_MMC_WRITE(host, BUF, 0x1f1f); | 1051 | host->total_bytes_left = data->blocks * block_size; |
| 1259 | host->total_bytes_left = data->blocks * block_size; | 1052 | host->sg_len = sg_len; |
| 1260 | host->sg_len = sg_len; | 1053 | mmc_omap_sg_to_buf(host); |
| 1261 | mmc_omap_sg_to_buf(host); | 1054 | host->dma_in_use = 0; |
| 1262 | host->dma_in_use = 0; | ||
| 1263 | } | ||
| 1264 | } | 1055 | } |
| 1265 | 1056 | ||
| 1266 | static void mmc_omap_start_request(struct mmc_omap_host *host, | 1057 | static void mmc_omap_start_request(struct mmc_omap_host *host, |
| @@ -1277,12 +1068,7 @@ static void mmc_omap_start_request(struct mmc_omap_host *host, | |||
| 1277 | struct dma_chan *c = host->data->flags & MMC_DATA_WRITE ? | 1068 | struct dma_chan *c = host->data->flags & MMC_DATA_WRITE ? |
| 1278 | host->dma_tx : host->dma_rx; | 1069 | host->dma_tx : host->dma_rx; |
| 1279 | 1070 | ||
| 1280 | if (c) | 1071 | dma_async_issue_pending(c); |
| 1281 | dma_async_issue_pending(c); | ||
| 1282 | #ifdef USE_DMA_PRIVATE | ||
| 1283 | else | ||
| 1284 | omap_start_dma(host->dma_ch); | ||
| 1285 | #endif | ||
| 1286 | } | 1072 | } |
| 1287 | } | 1073 | } |
| 1288 | 1074 | ||
| @@ -1566,9 +1352,6 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev) | |||
| 1566 | setup_timer(&host->clk_timer, mmc_omap_clk_timer, (unsigned long) host); | 1352 | setup_timer(&host->clk_timer, mmc_omap_clk_timer, (unsigned long) host); |
| 1567 | 1353 | ||
| 1568 | spin_lock_init(&host->dma_lock); | 1354 | spin_lock_init(&host->dma_lock); |
| 1569 | #ifdef USE_DMA_PRIVATE | ||
| 1570 | setup_timer(&host->dma_timer, mmc_omap_dma_timer, (unsigned long) host); | ||
| 1571 | #endif | ||
| 1572 | spin_lock_init(&host->slot_lock); | 1355 | spin_lock_init(&host->slot_lock); |
| 1573 | init_waitqueue_head(&host->slot_wq); | 1356 | init_waitqueue_head(&host->slot_wq); |
| 1574 | 1357 | ||
| @@ -1579,13 +1362,7 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev) | |||
| 1579 | host->id = pdev->id; | 1362 | host->id = pdev->id; |
| 1580 | host->mem_res = res; | 1363 | host->mem_res = res; |
| 1581 | host->irq = irq; | 1364 | host->irq = irq; |
| 1582 | |||
| 1583 | host->use_dma = 1; | 1365 | host->use_dma = 1; |
| 1584 | #ifdef USE_DMA_PRIVATE | ||
| 1585 | host->dev->dma_mask = &pdata->dma_mask; | ||
| 1586 | host->dma_ch = -1; | ||
| 1587 | #endif | ||
| 1588 | |||
| 1589 | host->irq = irq; | 1366 | host->irq = irq; |
| 1590 | host->phys_base = host->mem_res->start; | 1367 | host->phys_base = host->mem_res->start; |
| 1591 | host->virt_base = ioremap(res->start, resource_size(res)); | 1368 | host->virt_base = ioremap(res->start, resource_size(res)); |
