diff options
Diffstat (limited to 'drivers/mmc/host/omap_hsmmc.c')
-rw-r--r-- | drivers/mmc/host/omap_hsmmc.c | 299 |
1 files changed, 264 insertions, 35 deletions
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 53b5e41b87cd..0e8a6d570fde 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -46,6 +46,9 @@ | |||
46 | #include <linux/platform_data/hsmmc-omap.h> | 46 | #include <linux/platform_data/hsmmc-omap.h> |
47 | 47 | ||
48 | /* OMAP HSMMC Host Controller Registers */ | 48 | /* OMAP HSMMC Host Controller Registers */ |
49 | #define OMAP_HSMMC_HL_REV 0x0000 | ||
50 | #define OMAP_HSMMC_HL_HWINFO 0x0004 | ||
51 | #define OMAP_HSMMC_HL_SYSCONFIG 0x0010 | ||
49 | #define OMAP_HSMMC_SYSSTATUS 0x0014 | 52 | #define OMAP_HSMMC_SYSSTATUS 0x0014 |
50 | #define OMAP_HSMMC_CON 0x002C | 53 | #define OMAP_HSMMC_CON 0x002C |
51 | #define OMAP_HSMMC_SDMASA 0x0100 | 54 | #define OMAP_HSMMC_SDMASA 0x0100 |
@@ -65,7 +68,10 @@ | |||
65 | #define OMAP_HSMMC_ISE 0x0138 | 68 | #define OMAP_HSMMC_ISE 0x0138 |
66 | #define OMAP_HSMMC_AC12 0x013C | 69 | #define OMAP_HSMMC_AC12 0x013C |
67 | #define OMAP_HSMMC_CAPA 0x0140 | 70 | #define OMAP_HSMMC_CAPA 0x0140 |
71 | #define OMAP_HSMMC_ADMAES 0x0154 | ||
72 | #define OMAP_HSMMC_ADMASAL 0x0158 | ||
68 | 73 | ||
74 | #define MADMA_EN (1 << 0) | ||
69 | #define VS18 (1 << 26) | 75 | #define VS18 (1 << 26) |
70 | #define VS30 (1 << 25) | 76 | #define VS30 (1 << 25) |
71 | #define HSS (1 << 21) | 77 | #define HSS (1 << 21) |
@@ -75,6 +81,7 @@ | |||
75 | #define SDVS_MASK 0x00000E00 | 81 | #define SDVS_MASK 0x00000E00 |
76 | #define SDVSCLR 0xFFFFF1FF | 82 | #define SDVSCLR 0xFFFFF1FF |
77 | #define SDVSDET 0x00000400 | 83 | #define SDVSDET 0x00000400 |
84 | #define DMA_SELECT (2 << 3) | ||
78 | #define AUTOIDLE 0x1 | 85 | #define AUTOIDLE 0x1 |
79 | #define SDBP (1 << 8) | 86 | #define SDBP (1 << 8) |
80 | #define DTO 0xe | 87 | #define DTO 0xe |
@@ -96,6 +103,7 @@ | |||
96 | #define FOUR_BIT (1 << 1) | 103 | #define FOUR_BIT (1 << 1) |
97 | #define HSPE (1 << 2) | 104 | #define HSPE (1 << 2) |
98 | #define IWE (1 << 24) | 105 | #define IWE (1 << 24) |
106 | #define DMA_MASTER (1 << 20) | ||
99 | #define DDR (1 << 19) | 107 | #define DDR (1 << 19) |
100 | #define CLKEXTFREE (1 << 16) | 108 | #define CLKEXTFREE (1 << 16) |
101 | #define CTPL (1 << 11) | 109 | #define CTPL (1 << 11) |
@@ -126,10 +134,11 @@ | |||
126 | #define DCRC_EN (1 << 21) | 134 | #define DCRC_EN (1 << 21) |
127 | #define DEB_EN (1 << 22) | 135 | #define DEB_EN (1 << 22) |
128 | #define ACE_EN (1 << 24) | 136 | #define ACE_EN (1 << 24) |
137 | #define ADMAE_EN (1 << 25) | ||
129 | #define CERR_EN (1 << 28) | 138 | #define CERR_EN (1 << 28) |
130 | #define BADA_EN (1 << 29) | 139 | #define BADA_EN (1 << 29) |
131 | 140 | ||
132 | #define INT_EN_MASK (BADA_EN | CERR_EN | ACE_EN | DEB_EN | DCRC_EN |\ | 141 | #define INT_EN_MASK (BADA_EN | CERR_EN | ADMAE_EN | ACE_EN | DEB_EN | DCRC_EN |\ |
133 | DTO_EN | CIE_EN | CEB_EN | CCRC_EN | CTO_EN | \ | 142 | DTO_EN | CIE_EN | CEB_EN | CCRC_EN | CTO_EN | \ |
134 | BRR_EN | BWR_EN | TC_EN | CC_EN) | 143 | BRR_EN | BWR_EN | TC_EN | CC_EN) |
135 | 144 | ||
@@ -167,6 +176,31 @@ | |||
167 | #define OMAP_HSMMC_WRITE(base, reg, val) \ | 176 | #define OMAP_HSMMC_WRITE(base, reg, val) \ |
168 | __raw_writel((val), (base) + OMAP_HSMMC_##reg) | 177 | __raw_writel((val), (base) + OMAP_HSMMC_##reg) |
169 | 178 | ||
179 | struct omap_hsmmc_adma_desc { | ||
180 | u8 attr; | ||
181 | u8 reserved; | ||
182 | u16 len; | ||
183 | u32 addr; | ||
184 | } __packed; | ||
185 | |||
186 | #define ADMA_MAX_LEN 65532 | ||
187 | |||
188 | /* Decriptor table defines */ | ||
189 | #define ADMA_DESC_ATTR_VALID BIT(0) | ||
190 | #define ADMA_DESC_ATTR_END BIT(1) | ||
191 | #define ADMA_DESC_ATTR_INT BIT(2) | ||
192 | #define ADMA_DESC_ATTR_ACT1 BIT(4) | ||
193 | #define ADMA_DESC_ATTR_ACT2 BIT(5) | ||
194 | |||
195 | #define ADMA_DESC_TRANSFER_DATA ADMA_DESC_ATTR_ACT2 | ||
196 | #define ADMA_DESC_LINK_DESC (ADMA_DESC_ATTR_ACT1 | ADMA_DESC_ATTR_ACT2) | ||
197 | |||
198 | /* ADMA error status */ | ||
199 | #define AES_MASK 0x3 | ||
200 | #define ST_FDS 0x0 | ||
201 | #define ST_STOP 0x1 | ||
202 | #define ST_TFR 0x3 | ||
203 | |||
170 | struct omap_hsmmc_next { | 204 | struct omap_hsmmc_next { |
171 | unsigned int dma_len; | 205 | unsigned int dma_len; |
172 | s32 cookie; | 206 | s32 cookie; |
@@ -198,6 +232,7 @@ struct omap_hsmmc_host { | |||
198 | int irq; | 232 | int irq; |
199 | int wake_irq; | 233 | int wake_irq; |
200 | int dma_ch; | 234 | int dma_ch; |
235 | int use_adma; | ||
201 | struct dma_chan *tx_chan; | 236 | struct dma_chan *tx_chan; |
202 | struct dma_chan *rx_chan; | 237 | struct dma_chan *rx_chan; |
203 | int response_busy; | 238 | int response_busy; |
@@ -212,6 +247,9 @@ struct omap_hsmmc_host { | |||
212 | struct omap_hsmmc_next next_data; | 247 | struct omap_hsmmc_next next_data; |
213 | struct omap_hsmmc_platform_data *pdata; | 248 | struct omap_hsmmc_platform_data *pdata; |
214 | 249 | ||
250 | struct omap_hsmmc_adma_desc *adma_desc_table; | ||
251 | dma_addr_t adma_desc_table_addr; | ||
252 | |||
215 | /* return MMC cover switch state, can be NULL if not supported. | 253 | /* return MMC cover switch state, can be NULL if not supported. |
216 | * | 254 | * |
217 | * possible return values: | 255 | * possible return values: |
@@ -770,6 +808,18 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) | |||
770 | OMAP_HSMMC_WRITE(host->base, IE, 0); | 808 | OMAP_HSMMC_WRITE(host->base, IE, 0); |
771 | OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); | 809 | OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); |
772 | 810 | ||
811 | if (host->use_adma) { | ||
812 | u32 val; | ||
813 | |||
814 | val = OMAP_HSMMC_READ(host->base, CON); | ||
815 | val |= DMA_MASTER; | ||
816 | OMAP_HSMMC_WRITE(host->base, CON, val); | ||
817 | |||
818 | val = OMAP_HSMMC_READ(host->base, HCTL); | ||
819 | val |= DMA_SELECT; | ||
820 | OMAP_HSMMC_WRITE(host->base, HCTL, val); | ||
821 | } | ||
822 | |||
773 | /* Do not initialize card-specific things if the power is off */ | 823 | /* Do not initialize card-specific things if the power is off */ |
774 | if (host->power_mode == MMC_POWER_OFF) | 824 | if (host->power_mode == MMC_POWER_OFF) |
775 | goto out; | 825 | goto out; |
@@ -987,6 +1037,10 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data) | |||
987 | return; | 1037 | return; |
988 | } | 1038 | } |
989 | 1039 | ||
1040 | if (host->use_adma && host->data && !data->host_cookie) | ||
1041 | dma_unmap_sg(host->dev, data->sg, data->sg_len, | ||
1042 | omap_hsmmc_get_dma_dir(host, data)); | ||
1043 | |||
990 | host->data = NULL; | 1044 | host->data = NULL; |
991 | 1045 | ||
992 | if (!data->error) | 1046 | if (!data->error) |
@@ -1048,13 +1102,17 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) | |||
1048 | host->dma_ch = -1; | 1102 | host->dma_ch = -1; |
1049 | spin_unlock_irqrestore(&host->irq_lock, flags); | 1103 | spin_unlock_irqrestore(&host->irq_lock, flags); |
1050 | 1104 | ||
1051 | if (dma_ch != -1) { | 1105 | if (host->use_adma) { |
1052 | struct dma_chan *chan = omap_hsmmc_get_dma_chan(host, host->data); | 1106 | dma_unmap_sg(host->dev, host->data->sg, host->data->sg_len, |
1053 | 1107 | omap_hsmmc_get_dma_dir(host, host->data)); | |
1108 | host->data->host_cookie = 0; | ||
1109 | } else if (dma_ch != -1) { | ||
1110 | struct dma_chan *chan = omap_hsmmc_get_dma_chan(host, | ||
1111 | host->data); | ||
1054 | dmaengine_terminate_all(chan); | 1112 | dmaengine_terminate_all(chan); |
1055 | dma_unmap_sg(chan->device->dev, | 1113 | dma_unmap_sg(chan->device->dev, |
1056 | host->data->sg, host->data->sg_len, | 1114 | host->data->sg, host->data->sg_len, |
1057 | omap_hsmmc_get_dma_dir(host, host->data)); | 1115 | omap_hsmmc_get_dma_dir(host, host->data)); |
1058 | 1116 | ||
1059 | host->data->host_cookie = 0; | 1117 | host->data->host_cookie = 0; |
1060 | } | 1118 | } |
@@ -1149,6 +1207,35 @@ static void hsmmc_command_incomplete(struct omap_hsmmc_host *host, | |||
1149 | host->mrq->cmd->error = err; | 1207 | host->mrq->cmd->error = err; |
1150 | } | 1208 | } |
1151 | 1209 | ||
1210 | static void omap_hsmmc_adma_err(struct omap_hsmmc_host *host) | ||
1211 | { | ||
1212 | u32 admaes, admasal; | ||
1213 | |||
1214 | admaes = OMAP_HSMMC_READ(host->base, ADMAES); | ||
1215 | admasal = OMAP_HSMMC_READ(host->base, ADMASAL); | ||
1216 | |||
1217 | switch (admaes & AES_MASK) { | ||
1218 | case ST_FDS: | ||
1219 | dev_err(mmc_dev(host->mmc), | ||
1220 | "ADMA err: ST_FDS, erroneous desc at 0x%08x\n", | ||
1221 | admasal); | ||
1222 | break; | ||
1223 | case ST_STOP: | ||
1224 | dev_err(mmc_dev(host->mmc), | ||
1225 | "ADMA err: ST_STOP, desc at 0x%08x follows the erroneous one\n", | ||
1226 | admasal); | ||
1227 | break; | ||
1228 | case ST_TFR: | ||
1229 | dev_err(mmc_dev(host->mmc), | ||
1230 | "ADMA err: ST_TFR, desc at 0x%08x follows the erroneous one\n", | ||
1231 | admasal); | ||
1232 | break; | ||
1233 | default: | ||
1234 | dev_warn(mmc_dev(host->mmc), "Unexpected ADMA error state\n"); | ||
1235 | break; | ||
1236 | } | ||
1237 | } | ||
1238 | |||
1152 | static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) | 1239 | static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) |
1153 | { | 1240 | { |
1154 | struct mmc_data *data; | 1241 | struct mmc_data *data; |
@@ -1167,6 +1254,13 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) | |||
1167 | end_trans = !end_cmd; | 1254 | end_trans = !end_cmd; |
1168 | host->response_busy = 0; | 1255 | host->response_busy = 0; |
1169 | } | 1256 | } |
1257 | |||
1258 | if (status & ADMAE_EN) { | ||
1259 | omap_hsmmc_adma_err(host); | ||
1260 | end_trans = 1; | ||
1261 | data->error = -EIO; | ||
1262 | } | ||
1263 | |||
1170 | if (status & (CTO_EN | DTO_EN)) | 1264 | if (status & (CTO_EN | DTO_EN)) |
1171 | hsmmc_command_incomplete(host, -ETIMEDOUT, end_cmd); | 1265 | hsmmc_command_incomplete(host, -ETIMEDOUT, end_cmd); |
1172 | else if (status & (CCRC_EN | DCRC_EN | DEB_EN | CEB_EN | | 1266 | else if (status & (CCRC_EN | DCRC_EN | DEB_EN | CEB_EN | |
@@ -1370,6 +1464,7 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host, | |||
1370 | struct dma_chan *chan) | 1464 | struct dma_chan *chan) |
1371 | { | 1465 | { |
1372 | int dma_len; | 1466 | int dma_len; |
1467 | struct device *dev; | ||
1373 | 1468 | ||
1374 | if (!next && data->host_cookie && | 1469 | if (!next && data->host_cookie && |
1375 | data->host_cookie != host->next_data.cookie) { | 1470 | data->host_cookie != host->next_data.cookie) { |
@@ -1379,9 +1474,14 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host, | |||
1379 | data->host_cookie = 0; | 1474 | data->host_cookie = 0; |
1380 | } | 1475 | } |
1381 | 1476 | ||
1477 | if (chan) | ||
1478 | dev = chan->device->dev; | ||
1479 | else | ||
1480 | dev = mmc_dev(host->mmc); | ||
1481 | |||
1382 | /* Check if next job is already prepared */ | 1482 | /* Check if next job is already prepared */ |
1383 | if (next || data->host_cookie != host->next_data.cookie) { | 1483 | if (next || data->host_cookie != host->next_data.cookie) { |
1384 | dma_len = dma_map_sg(chan->device->dev, data->sg, data->sg_len, | 1484 | dma_len = dma_map_sg(dev, data->sg, data->sg_len, |
1385 | omap_hsmmc_get_dma_dir(host, data)); | 1485 | omap_hsmmc_get_dma_dir(host, data)); |
1386 | 1486 | ||
1387 | } else { | 1487 | } else { |
@@ -1516,8 +1616,57 @@ static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host) | |||
1516 | | (req->data->blocks << 16)); | 1616 | | (req->data->blocks << 16)); |
1517 | set_data_timeout(host, req->data->timeout_ns, | 1617 | set_data_timeout(host, req->data->timeout_ns, |
1518 | req->data->timeout_clks); | 1618 | req->data->timeout_clks); |
1519 | chan = omap_hsmmc_get_dma_chan(host, req->data); | 1619 | if (host->use_adma) { |
1520 | dma_async_issue_pending(chan); | 1620 | OMAP_HSMMC_WRITE(host->base, ADMASAL, |
1621 | (u32)host->adma_desc_table_addr); | ||
1622 | } else { | ||
1623 | chan = omap_hsmmc_get_dma_chan(host, req->data); | ||
1624 | dma_async_issue_pending(chan); | ||
1625 | } | ||
1626 | } | ||
1627 | |||
1628 | static int omap_hsmmc_write_adma_desc(struct omap_hsmmc_host *host, void *desc, | ||
1629 | dma_addr_t addr, u16 len, u8 attr) | ||
1630 | { | ||
1631 | struct omap_hsmmc_adma_desc *dma_desc = desc; | ||
1632 | |||
1633 | dma_desc->len = len; | ||
1634 | dma_desc->addr = (u32)addr; | ||
1635 | dma_desc->reserved = 0; | ||
1636 | dma_desc->attr = attr; | ||
1637 | |||
1638 | return 0; | ||
1639 | } | ||
1640 | |||
1641 | static int omap_hsmmc_setup_adma_transfer(struct omap_hsmmc_host *host, | ||
1642 | struct mmc_request *req) | ||
1643 | { | ||
1644 | struct mmc_data *data = req->data; | ||
1645 | struct scatterlist *sg; | ||
1646 | int i; | ||
1647 | int len; | ||
1648 | int ret; | ||
1649 | dma_addr_t addr; | ||
1650 | struct omap_hsmmc_adma_desc *dma_desc; | ||
1651 | |||
1652 | ret = omap_hsmmc_pre_dma_transfer(host, data, NULL, NULL); | ||
1653 | if (ret) | ||
1654 | return ret; | ||
1655 | |||
1656 | dma_desc = host->adma_desc_table; | ||
1657 | for_each_sg(data->sg, sg, host->dma_len, i) { | ||
1658 | addr = sg_dma_address(sg); | ||
1659 | len = sg_dma_len(sg); | ||
1660 | WARN_ON(len > ADMA_MAX_LEN); | ||
1661 | omap_hsmmc_write_adma_desc(host, dma_desc, addr, len, | ||
1662 | ADMA_DESC_ATTR_VALID | | ||
1663 | ADMA_DESC_TRANSFER_DATA); | ||
1664 | dma_desc++; | ||
1665 | } | ||
1666 | omap_hsmmc_write_adma_desc(host, dma_desc, 0, 0, ADMA_DESC_ATTR_END | | ||
1667 | ADMA_DESC_ATTR_VALID); | ||
1668 | |||
1669 | return 0; | ||
1521 | } | 1670 | } |
1522 | 1671 | ||
1523 | /* | 1672 | /* |
@@ -1548,10 +1697,18 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req) | |||
1548 | return 0; | 1697 | return 0; |
1549 | } | 1698 | } |
1550 | 1699 | ||
1551 | ret = omap_hsmmc_setup_dma_transfer(host, req); | 1700 | if (host->use_adma) { |
1552 | if (ret != 0) { | 1701 | ret = omap_hsmmc_setup_adma_transfer(host, req); |
1553 | dev_err(mmc_dev(host->mmc), "MMC start dma failure\n"); | 1702 | if (ret != 0) { |
1554 | return ret; | 1703 | dev_err(mmc_dev(host->mmc), "MMC adma setup failed\n"); |
1704 | return ret; | ||
1705 | } | ||
1706 | } else { | ||
1707 | ret = omap_hsmmc_setup_dma_transfer(host, req); | ||
1708 | if (ret != 0) { | ||
1709 | dev_err(mmc_dev(host->mmc), "MMC start dma failure\n"); | ||
1710 | return ret; | ||
1711 | } | ||
1555 | } | 1712 | } |
1556 | return 0; | 1713 | return 0; |
1557 | } | 1714 | } |
@@ -1561,11 +1718,18 @@ static void omap_hsmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, | |||
1561 | { | 1718 | { |
1562 | struct omap_hsmmc_host *host = mmc_priv(mmc); | 1719 | struct omap_hsmmc_host *host = mmc_priv(mmc); |
1563 | struct mmc_data *data = mrq->data; | 1720 | struct mmc_data *data = mrq->data; |
1721 | struct device *dev; | ||
1722 | struct dma_chan *c; | ||
1564 | 1723 | ||
1565 | if (data->host_cookie) { | 1724 | if (data->host_cookie) { |
1566 | struct dma_chan *c = omap_hsmmc_get_dma_chan(host, data); | 1725 | if (host->use_adma) { |
1726 | dev = mmc_dev(mmc); | ||
1727 | } else { | ||
1728 | c = omap_hsmmc_get_dma_chan(host, mrq->data); | ||
1729 | dev = c->device->dev; | ||
1730 | } | ||
1567 | 1731 | ||
1568 | dma_unmap_sg(c->device->dev, data->sg, data->sg_len, | 1732 | dma_unmap_sg(dev, data->sg, data->sg_len, |
1569 | omap_hsmmc_get_dma_dir(host, data)); | 1733 | omap_hsmmc_get_dma_dir(host, data)); |
1570 | data->host_cookie = 0; | 1734 | data->host_cookie = 0; |
1571 | } | 1735 | } |
@@ -1581,7 +1745,8 @@ static void omap_hsmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq) | |||
1581 | return ; | 1745 | return ; |
1582 | } | 1746 | } |
1583 | 1747 | ||
1584 | c = omap_hsmmc_get_dma_chan(host, mrq->data); | 1748 | if (!host->use_adma) |
1749 | c = omap_hsmmc_get_dma_chan(host, mrq->data); | ||
1585 | 1750 | ||
1586 | if (omap_hsmmc_pre_dma_transfer(host, mrq->data, | 1751 | if (omap_hsmmc_pre_dma_transfer(host, mrq->data, |
1587 | &host->next_data, c)) | 1752 | &host->next_data, c)) |
@@ -1918,6 +2083,7 @@ static const struct omap_mmc_of_data omap3_pre_es3_mmc_of_data = { | |||
1918 | 2083 | ||
1919 | static const struct omap_mmc_of_data omap4_mmc_of_data = { | 2084 | static const struct omap_mmc_of_data omap4_mmc_of_data = { |
1920 | .reg_offset = 0x100, | 2085 | .reg_offset = 0x100, |
2086 | .controller_flags = OMAP_HSMMC_HAS_HWPARAM, | ||
1921 | }; | 2087 | }; |
1922 | static const struct omap_mmc_of_data am33xx_mmc_of_data = { | 2088 | static const struct omap_mmc_of_data am33xx_mmc_of_data = { |
1923 | .reg_offset = 0x100, | 2089 | .reg_offset = 0x100, |
@@ -1988,6 +2154,63 @@ static inline struct omap_hsmmc_platform_data | |||
1988 | } | 2154 | } |
1989 | #endif | 2155 | #endif |
1990 | 2156 | ||
2157 | static int omap_hsmmc_adma_init(struct omap_hsmmc_host *host) | ||
2158 | { | ||
2159 | struct mmc_host *mmc = host->mmc; | ||
2160 | u32 val; | ||
2161 | |||
2162 | host->adma_desc_table = dma_alloc_coherent(host->dev, mmc->max_segs + 1, | ||
2163 | &host->adma_desc_table_addr, | ||
2164 | GFP_KERNEL); | ||
2165 | if (!host->adma_desc_table) { | ||
2166 | dev_err(host->dev, "failed to allocate adma desc table\n"); | ||
2167 | return -ENOMEM; | ||
2168 | } | ||
2169 | |||
2170 | val = OMAP_HSMMC_READ(host->base, HCTL); | ||
2171 | val |= DMA_SELECT; | ||
2172 | OMAP_HSMMC_WRITE(host->base, HCTL, val); | ||
2173 | |||
2174 | val = OMAP_HSMMC_READ(host->base, CON); | ||
2175 | val |= DMA_MASTER; | ||
2176 | OMAP_HSMMC_WRITE(host->base, CON, val); | ||
2177 | |||
2178 | return 0; | ||
2179 | } | ||
2180 | |||
2181 | static void omap_hsmmc_adma_exit(struct omap_hsmmc_host *host) | ||
2182 | { | ||
2183 | struct mmc_host *mmc = host->mmc; | ||
2184 | |||
2185 | dma_free_coherent(host->dev, mmc->max_segs + 1, | ||
2186 | host->adma_desc_table, host->adma_desc_table_addr); | ||
2187 | } | ||
2188 | |||
2189 | static int omap_hsmmc_dma_init(struct omap_hsmmc_host *host) | ||
2190 | { | ||
2191 | host->rx_chan = dma_request_chan(host->dev, "rx"); | ||
2192 | if (IS_ERR(host->rx_chan)) { | ||
2193 | dev_err(mmc_dev(host->mmc), "RX DMA channel request failed\n"); | ||
2194 | return PTR_ERR(host->rx_chan); | ||
2195 | } | ||
2196 | |||
2197 | host->tx_chan = dma_request_chan(host->dev, "tx"); | ||
2198 | if (IS_ERR(host->tx_chan)) { | ||
2199 | dev_err(mmc_dev(host->mmc), "TX DMA channel request failed\n"); | ||
2200 | return PTR_ERR(host->tx_chan); | ||
2201 | } | ||
2202 | |||
2203 | return 0; | ||
2204 | } | ||
2205 | |||
2206 | static void omap_hsmmc_dma_exit(struct omap_hsmmc_host *host) | ||
2207 | { | ||
2208 | if (!IS_ERR_OR_NULL(host->tx_chan)) | ||
2209 | dma_release_channel(host->tx_chan); | ||
2210 | if (!IS_ERR_OR_NULL(host->rx_chan)) | ||
2211 | dma_release_channel(host->rx_chan); | ||
2212 | } | ||
2213 | |||
1991 | static int omap_hsmmc_probe(struct platform_device *pdev) | 2214 | static int omap_hsmmc_probe(struct platform_device *pdev) |
1992 | { | 2215 | { |
1993 | struct omap_hsmmc_platform_data *pdata = pdev->dev.platform_data; | 2216 | struct omap_hsmmc_platform_data *pdata = pdev->dev.platform_data; |
@@ -1995,6 +2218,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
1995 | struct omap_hsmmc_host *host = NULL; | 2218 | struct omap_hsmmc_host *host = NULL; |
1996 | struct resource *res; | 2219 | struct resource *res; |
1997 | int ret, irq; | 2220 | int ret, irq; |
2221 | u32 val; | ||
1998 | const struct of_device_id *match; | 2222 | const struct of_device_id *match; |
1999 | const struct omap_mmc_of_data *data; | 2223 | const struct omap_mmc_of_data *data; |
2000 | void __iomem *base; | 2224 | void __iomem *base; |
@@ -2049,6 +2273,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
2049 | host->next_data.cookie = 1; | 2273 | host->next_data.cookie = 1; |
2050 | host->pbias_enabled = 0; | 2274 | host->pbias_enabled = 0; |
2051 | host->vqmmc_enabled = 0; | 2275 | host->vqmmc_enabled = 0; |
2276 | host->use_adma = false; | ||
2052 | 2277 | ||
2053 | ret = omap_hsmmc_gpio_init(mmc, host, pdata); | 2278 | ret = omap_hsmmc_gpio_init(mmc, host, pdata); |
2054 | if (ret) | 2279 | if (ret) |
@@ -2101,6 +2326,12 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
2101 | host->dbclk = NULL; | 2326 | host->dbclk = NULL; |
2102 | } | 2327 | } |
2103 | 2328 | ||
2329 | if (host->pdata->controller_flags & OMAP_HSMMC_HAS_HWPARAM) { | ||
2330 | val = OMAP_HSMMC_READ(base, HL_HWINFO); | ||
2331 | if (val & MADMA_EN) | ||
2332 | host->use_adma = true; | ||
2333 | } | ||
2334 | |||
2104 | /* Since we do only SG emulation, we can have as many segs | 2335 | /* Since we do only SG emulation, we can have as many segs |
2105 | * as we want. */ | 2336 | * as we want. */ |
2106 | mmc->max_segs = 1024; | 2337 | mmc->max_segs = 1024; |
@@ -2108,7 +2339,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
2108 | mmc->max_blk_size = 512; /* Block Length at max can be 1024 */ | 2339 | mmc->max_blk_size = 512; /* Block Length at max can be 1024 */ |
2109 | mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */ | 2340 | mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */ |
2110 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | 2341 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
2111 | mmc->max_seg_size = mmc->max_req_size; | 2342 | if (host->use_adma) |
2343 | mmc->max_seg_size = ADMA_MAX_LEN; | ||
2344 | else | ||
2345 | mmc->max_seg_size = mmc->max_req_size; | ||
2112 | 2346 | ||
2113 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | | 2347 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | |
2114 | MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE; | 2348 | MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE; |
@@ -2124,19 +2358,12 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
2124 | 2358 | ||
2125 | omap_hsmmc_conf_bus_power(host); | 2359 | omap_hsmmc_conf_bus_power(host); |
2126 | 2360 | ||
2127 | host->rx_chan = dma_request_chan(&pdev->dev, "rx"); | 2361 | if (host->use_adma) |
2128 | if (IS_ERR(host->rx_chan)) { | 2362 | ret = omap_hsmmc_adma_init(host); |
2129 | dev_err(mmc_dev(host->mmc), "RX DMA channel request failed\n"); | 2363 | else |
2130 | ret = PTR_ERR(host->rx_chan); | 2364 | ret = omap_hsmmc_dma_init(host); |
2131 | goto err_irq; | 2365 | if (ret) |
2132 | } | ||
2133 | |||
2134 | host->tx_chan = dma_request_chan(&pdev->dev, "tx"); | ||
2135 | if (IS_ERR(host->tx_chan)) { | ||
2136 | dev_err(mmc_dev(host->mmc), "TX DMA channel request failed\n"); | ||
2137 | ret = PTR_ERR(host->tx_chan); | ||
2138 | goto err_irq; | 2366 | goto err_irq; |
2139 | } | ||
2140 | 2367 | ||
2141 | /* Request IRQ for MMC operations */ | 2368 | /* Request IRQ for MMC operations */ |
2142 | ret = devm_request_irq(&pdev->dev, host->irq, omap_hsmmc_irq, 0, | 2369 | ret = devm_request_irq(&pdev->dev, host->irq, omap_hsmmc_irq, 0, |
@@ -2192,10 +2419,10 @@ err_slot_name: | |||
2192 | mmc_remove_host(mmc); | 2419 | mmc_remove_host(mmc); |
2193 | err_irq: | 2420 | err_irq: |
2194 | device_init_wakeup(&pdev->dev, false); | 2421 | device_init_wakeup(&pdev->dev, false); |
2195 | if (!IS_ERR_OR_NULL(host->tx_chan)) | 2422 | if (host->use_adma) |
2196 | dma_release_channel(host->tx_chan); | 2423 | omap_hsmmc_adma_exit(host); |
2197 | if (!IS_ERR_OR_NULL(host->rx_chan)) | 2424 | else |
2198 | dma_release_channel(host->rx_chan); | 2425 | omap_hsmmc_dma_exit(host); |
2199 | pm_runtime_dont_use_autosuspend(host->dev); | 2426 | pm_runtime_dont_use_autosuspend(host->dev); |
2200 | pm_runtime_put_sync(host->dev); | 2427 | pm_runtime_put_sync(host->dev); |
2201 | pm_runtime_disable(host->dev); | 2428 | pm_runtime_disable(host->dev); |
@@ -2215,8 +2442,10 @@ static int omap_hsmmc_remove(struct platform_device *pdev) | |||
2215 | pm_runtime_get_sync(host->dev); | 2442 | pm_runtime_get_sync(host->dev); |
2216 | mmc_remove_host(host->mmc); | 2443 | mmc_remove_host(host->mmc); |
2217 | 2444 | ||
2218 | dma_release_channel(host->tx_chan); | 2445 | if (host->use_adma) |
2219 | dma_release_channel(host->rx_chan); | 2446 | omap_hsmmc_adma_exit(host); |
2447 | else | ||
2448 | omap_hsmmc_dma_exit(host); | ||
2220 | 2449 | ||
2221 | pm_runtime_dont_use_autosuspend(host->dev); | 2450 | pm_runtime_dont_use_autosuspend(host->dev); |
2222 | pm_runtime_put_sync(host->dev); | 2451 | pm_runtime_put_sync(host->dev); |