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)); |