* [RFC PATCH 0/3] dra7/omap4/omap5: Enable ADMA2
@ 2016-05-18 8:45 Kishon Vijay Abraham I
2016-05-18 8:45 ` [RFC PATCH 1/3] mmc: host: omap_hsmmc: remove *use_dma* member Kishon Vijay Abraham I
` (2 more replies)
0 siblings, 3 replies; 17+ messages in thread
From: Kishon Vijay Abraham I @ 2016-05-18 8:45 UTC (permalink / raw)
To: linux-kernel, linux-omap, linux-arm-kernel, linux-mmc, afenkart,
ulf.hansson, linux, tony
Cc: rogerq, peter.ujfalusi, bcousson, galak, ijc+devicetree,
mark.rutland, pawel.moll, robh+dt, nsekhar, kishon
Add ADMA2 support in omap hsmmc driver. It's not added as
a dma engine since ADMA2 is only implemented in HSMMC.
Though this doesn't improve the throughput with high speed
cards, around 25% improvement is seen with HS200 card.
HS200 support is not yet added in OMAP HSMMC since
it has dependency with IODelay driver which is not yet
upstreamed.
Tested MMC1 and MMC2 in DRA7 (dra72-evm, dra7-evm) and OMAP5
(omap5-uevm).
Also tested having rootfs in MMC1 in DRA7, OMAP5, OMAP4 and OMAP3.
Kishon Vijay Abraham I (3):
mmc: host: omap_hsmmc: remove *use_dma* member
mmc: host: omap_hsmmc: Enable ADMA2
ARM: dts: dra7/omap4/omap5: Enable ADMA2
.../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 1 +
arch/arm/boot/dts/dra7.dtsi | 4 +
arch/arm/boot/dts/omap4.dtsi | 2 +
arch/arm/boot/dts/omap5.dtsi | 4 +
drivers/mmc/host/omap_hsmmc.c | 332 +++++++++++++++-----
include/linux/platform_data/hsmmc-omap.h | 1 +
6 files changed, 269 insertions(+), 75 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 17+ messages in thread
* [RFC PATCH 1/3] mmc: host: omap_hsmmc: remove *use_dma* member
2016-05-18 8:45 [RFC PATCH 0/3] dra7/omap4/omap5: Enable ADMA2 Kishon Vijay Abraham I
@ 2016-05-18 8:45 ` Kishon Vijay Abraham I
2016-05-18 8:45 ` [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2 Kishon Vijay Abraham I
2016-05-18 8:45 ` [RFC PATCH 3/3] ARM: dts: dra7/omap4/omap5: " Kishon Vijay Abraham I
2 siblings, 0 replies; 17+ messages in thread
From: Kishon Vijay Abraham I @ 2016-05-18 8:45 UTC (permalink / raw)
To: linux-kernel, linux-omap, linux-arm-kernel, linux-mmc, afenkart,
ulf.hansson, linux, tony
Cc: rogerq, peter.ujfalusi, bcousson, galak, ijc+devicetree,
mark.rutland, pawel.moll, robh+dt, nsekhar, kishon
omap_hsmmc doesn't support polled I/O. So remove *use_dma*
which is always set to '1'.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
drivers/mmc/host/omap_hsmmc.c | 36 +++++++++++++++---------------------
1 file changed, 15 insertions(+), 21 deletions(-)
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index f9ac3bb..cc916d5 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -198,7 +198,7 @@ struct omap_hsmmc_host {
u32 capa;
int irq;
int wake_irq;
- int use_dma, dma_ch;
+ int dma_ch;
struct dma_chan *tx_chan;
struct dma_chan *rx_chan;
int response_busy;
@@ -582,8 +582,8 @@ static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host,
u32 irq_mask = INT_EN_MASK;
unsigned long flags;
- if (host->use_dma)
- irq_mask &= ~(BRR_EN | BWR_EN);
+ /* BRR and BWR need not be enabled for DMA */
+ irq_mask &= ~(BRR_EN | BWR_EN);
/* Disable timeout for erases */
if (cmd->opcode == MMC_ERASE)
@@ -928,8 +928,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
cmdreg &= ~(DDIR);
}
- if (host->use_dma)
- cmdreg |= DMAE;
+ cmdreg |= DMAE;
host->req_in_progress = 1;
@@ -964,7 +963,7 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req
omap_hsmmc_disable_irq(host);
/* Do not complete the request if DMA is still in progress */
- if (mrq->data && host->use_dma && dma_ch != -1)
+ if (mrq->data && dma_ch != -1)
return;
host->mrq = NULL;
mmc_request_done(host->mmc, mrq);
@@ -1053,7 +1052,7 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno)
host->dma_ch = -1;
spin_unlock_irqrestore(&host->irq_lock, flags);
- if (host->use_dma && dma_ch != -1) {
+ if (dma_ch != -1) {
struct dma_chan *chan = omap_hsmmc_get_dma_chan(host, host->data);
dmaengine_terminate_all(chan);
@@ -1548,12 +1547,10 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req)
return 0;
}
- if (host->use_dma) {
- ret = omap_hsmmc_setup_dma_transfer(host, req);
- if (ret != 0) {
- dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
- return ret;
- }
+ ret = omap_hsmmc_setup_dma_transfer(host, req);
+ if (ret != 0) {
+ dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
+ return ret;
}
return 0;
}
@@ -1564,7 +1561,7 @@ static void omap_hsmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
struct omap_hsmmc_host *host = mmc_priv(mmc);
struct mmc_data *data = mrq->data;
- if (host->use_dma && data->host_cookie) {
+ if (data->host_cookie) {
struct dma_chan *c = omap_hsmmc_get_dma_chan(host, data);
dma_unmap_sg(c->device->dev, data->sg, data->sg_len,
@@ -1583,13 +1580,11 @@ static void omap_hsmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
return ;
}
- if (host->use_dma) {
- struct dma_chan *c = omap_hsmmc_get_dma_chan(host, mrq->data);
+ struct dma_chan *c = omap_hsmmc_get_dma_chan(host, mrq->data);
- if (omap_hsmmc_pre_dma_transfer(host, mrq->data,
- &host->next_data, c))
- mrq->data->host_cookie = 0;
- }
+ if (omap_hsmmc_pre_dma_transfer(host, mrq->data,
+ &host->next_data, c))
+ mrq->data->host_cookie = 0;
}
/*
@@ -2052,7 +2047,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
host->mmc = mmc;
host->pdata = pdata;
host->dev = &pdev->dev;
- host->use_dma = 1;
host->dma_ch = -1;
host->irq = irq;
host->mapbase = res->start + pdata->reg_offset;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
2016-05-18 8:45 [RFC PATCH 0/3] dra7/omap4/omap5: Enable ADMA2 Kishon Vijay Abraham I
2016-05-18 8:45 ` [RFC PATCH 1/3] mmc: host: omap_hsmmc: remove *use_dma* member Kishon Vijay Abraham I
@ 2016-05-18 8:45 ` Kishon Vijay Abraham I
2016-05-18 10:24 ` Peter Ujfalusi
` (2 more replies)
2016-05-18 8:45 ` [RFC PATCH 3/3] ARM: dts: dra7/omap4/omap5: " Kishon Vijay Abraham I
2 siblings, 3 replies; 17+ messages in thread
From: Kishon Vijay Abraham I @ 2016-05-18 8:45 UTC (permalink / raw)
To: linux-kernel, linux-omap, linux-arm-kernel, linux-mmc, afenkart,
ulf.hansson, linux, tony
Cc: rogerq, peter.ujfalusi, bcousson, galak, ijc+devicetree,
mark.rutland, pawel.moll, robh+dt, nsekhar, kishon
omap hsmmc host controller has ADMA2 feature. Enable it here
for better read and write throughput. Add a new dt binding
"ti,use_adma" to enable ADMA2.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
.../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 1 +
drivers/mmc/host/omap_hsmmc.c | 320 ++++++++++++++++----
include/linux/platform_data/hsmmc-omap.h | 1 +
3 files changed, 256 insertions(+), 66 deletions(-)
diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
index 74166a0..eb5ceec2 100644
--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
+++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
@@ -28,6 +28,7 @@ specifier is required.
dma-names: List of DMA request names. These strings correspond
1:1 with the DMA specifiers listed in dmas. The string naming is
to be "rx" and "tx" for RX and TX DMA requests, respectively.
+ti,use_adma: enable adma2 feature
Examples:
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index cc916d5..b4a7d18 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -66,6 +66,8 @@
#define OMAP_HSMMC_ISE 0x0138
#define OMAP_HSMMC_AC12 0x013C
#define OMAP_HSMMC_CAPA 0x0140
+#define OMAP_HSMMC_ADMAES 0x0154
+#define OMAP_HSMMC_ADMASAL 0x0158
#define VS18 (1 << 26)
#define VS30 (1 << 25)
@@ -76,6 +78,7 @@
#define SDVS_MASK 0x00000E00
#define SDVSCLR 0xFFFFF1FF
#define SDVSDET 0x00000400
+#define DMA_SELECT (2 << 3)
#define AUTOIDLE 0x1
#define SDBP (1 << 8)
#define DTO 0xe
@@ -97,6 +100,7 @@
#define FOUR_BIT (1 << 1)
#define HSPE (1 << 2)
#define IWE (1 << 24)
+#define DMA_MASTER (1 << 20)
#define DDR (1 << 19)
#define CLKEXTFREE (1 << 16)
#define CTPL (1 << 11)
@@ -127,10 +131,11 @@
#define DCRC_EN (1 << 21)
#define DEB_EN (1 << 22)
#define ACE_EN (1 << 24)
+#define ADMAE_EN (1 << 24)
#define CERR_EN (1 << 28)
#define BADA_EN (1 << 29)
-#define INT_EN_MASK (BADA_EN | CERR_EN | ACE_EN | DEB_EN | DCRC_EN |\
+#define INT_EN_MASK (BADA_EN | CERR_EN | ADMAE_EN | ACE_EN | DEB_EN | DCRC_EN |\
DTO_EN | CIE_EN | CEB_EN | CCRC_EN | CTO_EN | \
BRR_EN | BWR_EN | TC_EN | CC_EN)
@@ -168,6 +173,25 @@
#define OMAP_HSMMC_WRITE(base, reg, val) \
__raw_writel((val), (base) + OMAP_HSMMC_##reg)
+struct omap_hsmmc_adma_desc {
+ u8 attr;
+ u8 reserved;
+ u16 len;
+ u32 addr;
+} __packed;
+
+#define ADMA_MAX_LEN 65532
+
+/* Decriptor table defines */
+#define ADMA_DESC_ATTR_VALID BIT(0)
+#define ADMA_DESC_ATTR_END BIT(1)
+#define ADMA_DESC_ATTR_INT BIT(2)
+#define ADMA_DESC_ATTR_ACT1 BIT(4)
+#define ADMA_DESC_ATTR_ACT2 BIT(5)
+
+#define ADMA_DESC_TRANSFER_DATA ADMA_DESC_ATTR_ACT2
+#define ADMA_DESC_LINK_DESC (ADMA_DESC_ATTR_ACT1 | ADMA_DESC_ATTR_ACT2)
+
struct omap_hsmmc_next {
unsigned int dma_len;
s32 cookie;
@@ -213,6 +237,9 @@ struct omap_hsmmc_host {
struct omap_hsmmc_next next_data;
struct omap_hsmmc_platform_data *pdata;
+ struct omap_hsmmc_adma_desc *adma_desc_table;
+ dma_addr_t adma_desc_table_addr;
+
/* return MMC cover switch state, can be NULL if not supported.
*
* possible return values:
@@ -951,6 +978,19 @@ static struct dma_chan *omap_hsmmc_get_dma_chan(struct omap_hsmmc_host *host,
return data->flags & MMC_DATA_WRITE ? host->tx_chan : host->rx_chan;
}
+static void omap_hsmmc_adma_cleanup(struct omap_hsmmc_host *host)
+{
+ u32 val;
+
+ val = OMAP_HSMMC_READ(host->base, HCTL);
+ val &= ~DMA_SELECT;
+ OMAP_HSMMC_WRITE(host->base, HCTL, val);
+
+ val = OMAP_HSMMC_READ(host->base, CON);
+ val &= ~DMA_MASTER;
+ OMAP_HSMMC_WRITE(host->base, CON, val);
+}
+
static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_request *mrq)
{
int dma_ch;
@@ -963,8 +1003,11 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req
omap_hsmmc_disable_irq(host);
/* Do not complete the request if DMA is still in progress */
- if (mrq->data && dma_ch != -1)
+ if (host->pdata->controller_flags == OMAP_HSMMC_USE_ADMA)
+ omap_hsmmc_adma_cleanup(host);
+ else if (mrq->data && dma_ch != -1)
return;
+
host->mrq = NULL;
mmc_request_done(host->mmc, mrq);
pm_runtime_mark_last_busy(host->dev);
@@ -1052,15 +1095,22 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno)
host->dma_ch = -1;
spin_unlock_irqrestore(&host->irq_lock, flags);
- if (dma_ch != -1) {
- struct dma_chan *chan = omap_hsmmc_get_dma_chan(host, host->data);
-
- dmaengine_terminate_all(chan);
- dma_unmap_sg(chan->device->dev,
- host->data->sg, host->data->sg_len,
+ if (!(host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)) {
+ if (dma_ch != -1) {
+ struct dma_chan *chan = omap_hsmmc_get_dma_chan(host,
+ host->data);
+ dmaengine_terminate_all(chan);
+ dma_unmap_sg(chan->device->dev,
+ host->data->sg, host->data->sg_len,
omap_hsmmc_get_dma_dir(host, host->data));
+ host->data->host_cookie = 0;
+ }
+ } else {
+ dma_unmap_sg(host->dev, host->data->sg, host->data->sg_len,
+ omap_hsmmc_get_dma_dir(host, host->data));
host->data->host_cookie = 0;
+
}
host->data = NULL;
}
@@ -1191,6 +1241,14 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
}
dev_dbg(mmc_dev(host->mmc), "AC12 err: 0x%x\n", ac12);
}
+
+ if (status & ADMAE_EN) {
+ u32 val;
+
+ val = OMAP_HSMMC_READ(host->base, ADMAES);
+ dev_dbg(mmc_dev(host->mmc), "ADMA error status: 0x%x\n",
+ val);
+ }
}
OMAP_HSMMC_WRITE(host->base, STAT, status);
@@ -1378,6 +1436,7 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host,
struct dma_chan *chan)
{
int dma_len;
+ struct device *dev;
if (!next && data->host_cookie &&
data->host_cookie != host->next_data.cookie) {
@@ -1387,9 +1446,14 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host,
data->host_cookie = 0;
}
+ if (chan)
+ dev = chan->device->dev;
+ else
+ dev = mmc_dev(host->mmc);
+
/* Check if next job is already prepared */
if (next || data->host_cookie != host->next_data.cookie) {
- dma_len = dma_map_sg(chan->device->dev, data->sg, data->sg_len,
+ dma_len = dma_map_sg(dev, data->sg, data->sg_len,
omap_hsmmc_get_dma_dir(host, data));
} else {
@@ -1516,6 +1580,7 @@ static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host)
{
struct mmc_request *req = host->mrq;
struct dma_chan *chan;
+ int val;
if (!req->data)
return;
@@ -1523,10 +1588,66 @@ static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host)
| (req->data->blocks << 16));
set_data_timeout(host, req->data->timeout_ns,
req->data->timeout_clks);
- chan = omap_hsmmc_get_dma_chan(host, req->data);
- dma_async_issue_pending(chan);
+
+ if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA) {
+ val = OMAP_HSMMC_READ(host->base, HCTL);
+ val |= DMA_SELECT;
+ OMAP_HSMMC_WRITE(host->base, HCTL, val);
+
+ val = OMAP_HSMMC_READ(host->base, CON);
+ val |= DMA_MASTER;
+ OMAP_HSMMC_WRITE(host->base, CON, val);
+
+ OMAP_HSMMC_WRITE(host->base, ADMASAL,
+ (u32)host->adma_desc_table_addr);
+ } else {
+ chan = omap_hsmmc_get_dma_chan(host, req->data);
+ dma_async_issue_pending(chan);
+ }
+}
+
+static int omap_hsmmc_write_adma_desc(struct omap_hsmmc_host *host, void *desc,
+ dma_addr_t addr, u16 len, u8 attr)
+{
+ struct omap_hsmmc_adma_desc *dma_desc = desc;
+
+ dma_desc->len = len;
+ dma_desc->addr = (u32)addr;
+ dma_desc->reserved = 0;
+ dma_desc->attr = attr;
+
+ return 0;
}
+static int omap_hsmmc_setup_adma_transfer(struct omap_hsmmc_host *host,
+ struct mmc_request *req)
+{
+ struct mmc_data *data = req->data;
+ struct scatterlist *sg;
+ int i;
+ int len;
+ int ret;
+ dma_addr_t addr;
+ struct omap_hsmmc_adma_desc *dma_desc;
+
+ ret = omap_hsmmc_pre_dma_transfer(host, data, NULL, NULL);
+ if (ret)
+ return ret;
+
+ dma_desc = host->adma_desc_table;
+ for_each_sg(data->sg, sg, host->dma_len, i) {
+ addr = sg_dma_address(sg);
+ len = sg_dma_len(sg);
+ WARN_ON(len > ADMA_MAX_LEN);
+ omap_hsmmc_write_adma_desc(host, dma_desc, addr, len,
+ ADMA_DESC_ATTR_VALID |
+ ADMA_DESC_TRANSFER_DATA);
+ dma_desc++;
+ }
+ omap_hsmmc_write_adma_desc(host, dma_desc, 0, 0, ADMA_DESC_ATTR_END);
+
+ return 0;
+}
/*
* Configure block length for MMC/SD cards and initiate the transfer.
*/
@@ -1547,10 +1668,18 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req)
return 0;
}
- ret = omap_hsmmc_setup_dma_transfer(host, req);
- if (ret != 0) {
- dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
- return ret;
+ if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA) {
+ ret = omap_hsmmc_setup_adma_transfer(host, req);
+ if (ret != 0) {
+ dev_err(mmc_dev(host->mmc), "MMC adma setup failed\n");
+ return ret;
+ }
+ } else {
+ ret = omap_hsmmc_setup_dma_transfer(host, req);
+ if (ret != 0) {
+ dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
+ return ret;
+ }
}
return 0;
}
@@ -1560,11 +1689,18 @@ static void omap_hsmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
{
struct omap_hsmmc_host *host = mmc_priv(mmc);
struct mmc_data *data = mrq->data;
+ struct device *dev;
+ struct dma_chan *c;
if (data->host_cookie) {
- struct dma_chan *c = omap_hsmmc_get_dma_chan(host, data);
+ if (!(host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)) {
+ c = omap_hsmmc_get_dma_chan(host, mrq->data);
+ dev = c->device->dev;
+ } else {
+ dev = mmc_dev(mmc);
+ }
- dma_unmap_sg(c->device->dev, data->sg, data->sg_len,
+ dma_unmap_sg(dev, data->sg, data->sg_len,
omap_hsmmc_get_dma_dir(host, data));
data->host_cookie = 0;
}
@@ -1574,13 +1710,15 @@ static void omap_hsmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
bool is_first_req)
{
struct omap_hsmmc_host *host = mmc_priv(mmc);
+ struct dma_chan *c = NULL;
if (mrq->data->host_cookie) {
mrq->data->host_cookie = 0;
return ;
}
- struct dma_chan *c = omap_hsmmc_get_dma_chan(host, mrq->data);
+ if (!(host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA))
+ c = omap_hsmmc_get_dma_chan(host, mrq->data);
if (omap_hsmmc_pre_dma_transfer(host, mrq->data,
&host->next_data, c))
@@ -1967,6 +2105,9 @@ static struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
if (of_find_property(np, "ti,dual-volt", NULL))
pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT;
+ if (of_find_property(np, "ti,use_adma", NULL))
+ pdata->controller_flags |= OMAP_HSMMC_USE_ADMA;
+
pdata->gpio_cd = -EINVAL;
pdata->gpio_cod = -EINVAL;
pdata->gpio_wp = -EINVAL;
@@ -1992,6 +2133,84 @@ static inline struct omap_hsmmc_platform_data
}
#endif
+static int omap_hsmmc_adma_init(struct omap_hsmmc_host *host)
+{
+ struct mmc_host *mmc = host->mmc;
+
+ host->adma_desc_table = dma_alloc_coherent(host->dev, mmc->max_segs + 1,
+ &host->adma_desc_table_addr,
+ GFP_KERNEL);
+ if (!host->adma_desc_table) {
+ dev_err(host->dev, "failed to allocate adma desc table\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void omap_hsmmc_adma_exit(struct omap_hsmmc_host *host)
+{
+ struct mmc_host *mmc = host->mmc;
+
+ dma_free_coherent(host->dev, mmc->max_segs + 1,
+ host->adma_desc_table, host->adma_desc_table_addr);
+}
+
+static int omap_hsmmc_dma_init(struct omap_hsmmc_host *host)
+{
+ dma_cap_mask_t mask;
+ unsigned int tx_req, rx_req;
+ struct resource *res;
+ struct platform_device *pdev = to_platform_device(host->dev);
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ if (!pdev->dev.of_node) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
+ if (!res) {
+ dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
+ return -ENXIO;
+ }
+ tx_req = res->start;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
+ if (!res) {
+ dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
+ return -ENXIO;
+ }
+ rx_req = res->start;
+ }
+
+ host->rx_chan =
+ dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
+ &rx_req, &pdev->dev, "rx");
+
+ if (!host->rx_chan) {
+ dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel\n");
+ return -ENXIO;
+ }
+
+ host->tx_chan =
+ dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
+ &tx_req, &pdev->dev, "tx");
+
+ if (!host->tx_chan) {
+ dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel\n");
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static void omap_hsmmc_dma_exit(struct omap_hsmmc_host *host)
+{
+ if (host->tx_chan)
+ dma_release_channel(host->tx_chan);
+ if (host->rx_chan)
+ dma_release_channel(host->rx_chan);
+}
+
static int omap_hsmmc_probe(struct platform_device *pdev)
{
struct omap_hsmmc_platform_data *pdata = pdev->dev.platform_data;
@@ -2000,8 +2219,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
struct resource *res;
int ret, irq;
const struct of_device_id *match;
- dma_cap_mask_t mask;
- unsigned tx_req, rx_req;
const struct omap_mmc_of_data *data;
void __iomem *base;
@@ -2114,7 +2331,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
mmc->max_blk_size = 512; /* Block Length at max can be 1024 */
mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */
mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
- mmc->max_seg_size = mmc->max_req_size;
+ if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
+ mmc->max_seg_size = ADMA_MAX_LEN;
+ else
+ mmc->max_seg_size = mmc->max_req_size;
mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
@@ -2130,46 +2350,12 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
omap_hsmmc_conf_bus_power(host);
- if (!pdev->dev.of_node) {
- res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
- if (!res) {
- dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
- ret = -ENXIO;
- goto err_irq;
- }
- tx_req = res->start;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
- if (!res) {
- dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
- ret = -ENXIO;
- goto err_irq;
- }
- rx_req = res->start;
- }
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
-
- host->rx_chan =
- dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
- &rx_req, &pdev->dev, "rx");
-
- if (!host->rx_chan) {
- dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel\n");
- ret = -ENXIO;
- goto err_irq;
- }
-
- host->tx_chan =
- dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
- &tx_req, &pdev->dev, "tx");
-
- if (!host->tx_chan) {
- dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel\n");
- ret = -ENXIO;
+ if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
+ ret = omap_hsmmc_adma_init(host);
+ else
+ ret = omap_hsmmc_dma_init(host);
+ if (ret)
goto err_irq;
- }
/* Request IRQ for MMC operations */
ret = devm_request_irq(&pdev->dev, host->irq, omap_hsmmc_irq, 0,
@@ -2225,11 +2411,11 @@ err_slot_name:
mmc_remove_host(mmc);
err_irq:
device_init_wakeup(&pdev->dev, false);
- if (host->tx_chan)
- dma_release_channel(host->tx_chan);
- if (host->rx_chan)
- dma_release_channel(host->rx_chan);
pm_runtime_dont_use_autosuspend(host->dev);
+ if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
+ omap_hsmmc_adma_exit(host);
+ else
+ omap_hsmmc_dma_exit(host);
pm_runtime_put_sync(host->dev);
pm_runtime_disable(host->dev);
if (host->dbclk)
@@ -2248,8 +2434,10 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
pm_runtime_get_sync(host->dev);
mmc_remove_host(host->mmc);
- dma_release_channel(host->tx_chan);
- dma_release_channel(host->rx_chan);
+ if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
+ omap_hsmmc_adma_exit(host);
+ else
+ omap_hsmmc_dma_exit(host);
pm_runtime_dont_use_autosuspend(host->dev);
pm_runtime_put_sync(host->dev);
diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h
index 8e981be..e26013d 100644
--- a/include/linux/platform_data/hsmmc-omap.h
+++ b/include/linux/platform_data/hsmmc-omap.h
@@ -27,6 +27,7 @@
#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT BIT(0)
#define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ BIT(1)
#define OMAP_HSMMC_SWAKEUP_MISSING BIT(2)
+#define OMAP_HSMMC_USE_ADMA BIT(3)
struct omap_hsmmc_dev_attr {
u8 flags;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [RFC PATCH 3/3] ARM: dts: dra7/omap4/omap5: Enable ADMA2
2016-05-18 8:45 [RFC PATCH 0/3] dra7/omap4/omap5: Enable ADMA2 Kishon Vijay Abraham I
2016-05-18 8:45 ` [RFC PATCH 1/3] mmc: host: omap_hsmmc: remove *use_dma* member Kishon Vijay Abraham I
2016-05-18 8:45 ` [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2 Kishon Vijay Abraham I
@ 2016-05-18 8:45 ` Kishon Vijay Abraham I
2 siblings, 0 replies; 17+ messages in thread
From: Kishon Vijay Abraham I @ 2016-05-18 8:45 UTC (permalink / raw)
To: linux-kernel, linux-omap, linux-arm-kernel, linux-mmc, afenkart,
ulf.hansson, linux, tony
Cc: rogerq, peter.ujfalusi, bcousson, galak, ijc+devicetree,
mark.rutland, pawel.moll, robh+dt, nsekhar, kishon
Now that ADMA2 support is added in omap hsmmc controller driver,
enable ADMA2 for all the mmc instances that has ADMA2 support in
DRA7, OMAP4 and OMAP5 SoCs.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
arch/arm/boot/dts/dra7.dtsi | 4 ++++
arch/arm/boot/dts/omap4.dtsi | 2 ++
arch/arm/boot/dts/omap5.dtsi | 4 ++++
3 files changed, 10 insertions(+)
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index 13ac882..a63df6b 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -883,6 +883,7 @@
ti,hwmods = "mmc1";
ti,dual-volt;
ti,needs-special-reset;
+ ti,use_adma;
dmas = <&sdma_xbar 61>, <&sdma_xbar 62>;
dma-names = "tx", "rx";
status = "disabled";
@@ -895,6 +896,7 @@
interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "mmc2";
ti,needs-special-reset;
+ ti,use_adma;
dmas = <&sdma_xbar 47>, <&sdma_xbar 48>;
dma-names = "tx", "rx";
status = "disabled";
@@ -906,6 +908,7 @@
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "mmc3";
ti,needs-special-reset;
+ ti,use_adma;
dmas = <&sdma_xbar 77>, <&sdma_xbar 78>;
dma-names = "tx", "rx";
status = "disabled";
@@ -917,6 +920,7 @@
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "mmc4";
ti,needs-special-reset;
+ ti,use_adma;
dmas = <&sdma_xbar 57>, <&sdma_xbar 58>;
dma-names = "tx", "rx";
status = "disabled";
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 421fe9f..23c78b4 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -513,6 +513,7 @@
ti,hwmods = "mmc1";
ti,dual-volt;
ti,needs-special-reset;
+ ti,use_adma;
dmas = <&sdma 61>, <&sdma 62>;
dma-names = "tx", "rx";
pbias-supply = <&pbias_mmc_reg>;
@@ -524,6 +525,7 @@
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "mmc2";
ti,needs-special-reset;
+ ti,use_adma;
dmas = <&sdma 47>, <&sdma 48>;
dma-names = "tx", "rx";
};
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 120b6b8..3bf113b 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -566,6 +566,7 @@
ti,hwmods = "mmc1";
ti,dual-volt;
ti,needs-special-reset;
+ ti,use_adma;
dmas = <&sdma 61>, <&sdma 62>;
dma-names = "tx", "rx";
pbias-supply = <&pbias_mmc_reg>;
@@ -577,6 +578,7 @@
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "mmc2";
ti,needs-special-reset;
+ ti,use_adma;
dmas = <&sdma 47>, <&sdma 48>;
dma-names = "tx", "rx";
};
@@ -587,6 +589,7 @@
interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "mmc3";
ti,needs-special-reset;
+ ti,use_adma;
dmas = <&sdma 77>, <&sdma 78>;
dma-names = "tx", "rx";
};
@@ -597,6 +600,7 @@
interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "mmc4";
ti,needs-special-reset;
+ ti,use_adma;
dmas = <&sdma 57>, <&sdma 58>;
dma-names = "tx", "rx";
};
--
1.7.9.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
2016-05-18 8:45 ` [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2 Kishon Vijay Abraham I
@ 2016-05-18 10:24 ` Peter Ujfalusi
2016-05-18 19:30 ` Tony Lindgren
2016-05-19 6:06 ` Kishon Vijay Abraham I
2016-05-18 11:07 ` Peter Ujfalusi
2016-05-19 8:25 ` Peter Ujfalusi
2 siblings, 2 replies; 17+ messages in thread
From: Peter Ujfalusi @ 2016-05-18 10:24 UTC (permalink / raw)
To: Kishon Vijay Abraham I, linux-kernel, linux-omap,
linux-arm-kernel, linux-mmc, afenkart, ulf.hansson, linux, tony
Cc: rogerq, bcousson, galak, ijc+devicetree, mark.rutland, pawel.moll,
robh+dt, nsekhar
On 05/18/16 11:45, Kishon Vijay Abraham I wrote:
> omap hsmmc host controller has ADMA2 feature. Enable it here
> for better read and write throughput. Add a new dt binding
> "ti,use_adma" to enable ADMA2.
>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> ---
> .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 1 +
> drivers/mmc/host/omap_hsmmc.c | 320 ++++++++++++++++----
> include/linux/platform_data/hsmmc-omap.h | 1 +
> 3 files changed, 256 insertions(+), 66 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> index 74166a0..eb5ceec2 100644
> --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> @@ -28,6 +28,7 @@ specifier is required.
> dma-names: List of DMA request names. These strings correspond
> 1:1 with the DMA specifiers listed in dmas. The string naming is
> to be "rx" and "tx" for RX and TX DMA requests, respectively.
> +ti,use_adma: enable adma2 feature
Do we have use case when you want to fall back to generic DMA instead of aDMA2?
IMHO if the driver supports aDMA2, it is going to use it instead of the
generic s/eDMA.
What I mean is:
the driver implements the aDMA2 support.
if the IP has support for aDMA2, then it is going to use it, otherwise it will
use the generic DMA.
--
Péter
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
2016-05-18 8:45 ` [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2 Kishon Vijay Abraham I
2016-05-18 10:24 ` Peter Ujfalusi
@ 2016-05-18 11:07 ` Peter Ujfalusi
2016-05-19 8:25 ` Peter Ujfalusi
2 siblings, 0 replies; 17+ messages in thread
From: Peter Ujfalusi @ 2016-05-18 11:07 UTC (permalink / raw)
To: Kishon Vijay Abraham I, linux-kernel, linux-omap,
linux-arm-kernel, linux-mmc, afenkart, ulf.hansson, linux, tony
Cc: rogerq, bcousson, galak, ijc+devicetree, mark.rutland, pawel.moll,
robh+dt, nsekhar
On 05/18/16 11:45, Kishon Vijay Abraham I wrote:
> +static int omap_hsmmc_dma_init(struct omap_hsmmc_host *host)
> +{
> + dma_cap_mask_t mask;
> + unsigned int tx_req, rx_req;
> + struct resource *res;
> + struct platform_device *pdev = to_platform_device(host->dev);
> +
> + dma_cap_zero(mask);
> + dma_cap_set(DMA_SLAVE, mask);
> +
> + if (!pdev->dev.of_node) {
> + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
> + if (!res) {
> + dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
> + return -ENXIO;
> + }
> + tx_req = res->start;
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
> + if (!res) {
> + dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
> + return -ENXIO;
> + }
> + rx_req = res->start;
> + }
> +
> + host->rx_chan =
> + dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
> + &rx_req, &pdev->dev, "rx");
> +
> + if (!host->rx_chan) {
> + dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel\n");
> + return -ENXIO;
> + }
> +
> + host->tx_chan =
> + dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
> + &tx_req, &pdev->dev, "tx");
> +
> + if (!host->tx_chan) {
> + dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel\n");
> + return -ENXIO;
upstream moved to use dma_request_chan() so this part needs to be changed.
> + }
> +
> + return 0;
> +}
> +
> +static void omap_hsmmc_dma_exit(struct omap_hsmmc_host *host)
> +{
> + if (host->tx_chan)
> + dma_release_channel(host->tx_chan);
> + if (host->rx_chan)
> + dma_release_channel(host->rx_chan);
> +}
> +
> static int omap_hsmmc_probe(struct platform_device *pdev)
> {
> struct omap_hsmmc_platform_data *pdata = pdev->dev.platform_data;
> @@ -2000,8 +2219,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
> struct resource *res;
> int ret, irq;
> const struct of_device_id *match;
> - dma_cap_mask_t mask;
> - unsigned tx_req, rx_req;
> const struct omap_mmc_of_data *data;
> void __iomem *base;
>
> @@ -2114,7 +2331,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
> mmc->max_blk_size = 512; /* Block Length at max can be 1024 */
> mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */
> mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
> - mmc->max_seg_size = mmc->max_req_size;
> + if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
> + mmc->max_seg_size = ADMA_MAX_LEN;
> + else
> + mmc->max_seg_size = mmc->max_req_size;
>
> mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
> MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
> @@ -2130,46 +2350,12 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
>
> omap_hsmmc_conf_bus_power(host);
>
> - if (!pdev->dev.of_node) {
> - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
> - if (!res) {
> - dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
> - ret = -ENXIO;
> - goto err_irq;
> - }
> - tx_req = res->start;
> -
> - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
> - if (!res) {
> - dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
> - ret = -ENXIO;
> - goto err_irq;
> - }
> - rx_req = res->start;
> - }
> -
> - dma_cap_zero(mask);
> - dma_cap_set(DMA_SLAVE, mask);
> -
> - host->rx_chan =
> - dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
> - &rx_req, &pdev->dev, "rx");
> -
> - if (!host->rx_chan) {
> - dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel\n");
> - ret = -ENXIO;
> - goto err_irq;
> - }
> -
> - host->tx_chan =
> - dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
> - &tx_req, &pdev->dev, "tx");
> -
> - if (!host->tx_chan) {
> - dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel\n");
> - ret = -ENXIO;
> + if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
> + ret = omap_hsmmc_adma_init(host);
> + else
> + ret = omap_hsmmc_dma_init(host);
> + if (ret)
> goto err_irq;
> - }
>
> /* Request IRQ for MMC operations */
> ret = devm_request_irq(&pdev->dev, host->irq, omap_hsmmc_irq, 0,
> @@ -2225,11 +2411,11 @@ err_slot_name:
> mmc_remove_host(mmc);
> err_irq:
> device_init_wakeup(&pdev->dev, false);
> - if (host->tx_chan)
> - dma_release_channel(host->tx_chan);
> - if (host->rx_chan)
> - dma_release_channel(host->rx_chan);
> pm_runtime_dont_use_autosuspend(host->dev);
> + if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
> + omap_hsmmc_adma_exit(host);
> + else
> + omap_hsmmc_dma_exit(host);
> pm_runtime_put_sync(host->dev);
> pm_runtime_disable(host->dev);
> if (host->dbclk)
> @@ -2248,8 +2434,10 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
> pm_runtime_get_sync(host->dev);
> mmc_remove_host(host->mmc);
>
> - dma_release_channel(host->tx_chan);
> - dma_release_channel(host->rx_chan);
> + if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
> + omap_hsmmc_adma_exit(host);
> + else
> + omap_hsmmc_dma_exit(host);
>
> pm_runtime_dont_use_autosuspend(host->dev);
> pm_runtime_put_sync(host->dev);
> diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h
> index 8e981be..e26013d 100644
> --- a/include/linux/platform_data/hsmmc-omap.h
> +++ b/include/linux/platform_data/hsmmc-omap.h
> @@ -27,6 +27,7 @@
> #define OMAP_HSMMC_SUPPORTS_DUAL_VOLT BIT(0)
> #define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ BIT(1)
> #define OMAP_HSMMC_SWAKEUP_MISSING BIT(2)
> +#define OMAP_HSMMC_USE_ADMA BIT(3)
>
> struct omap_hsmmc_dev_attr {
> u8 flags;
>
--
Péter
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
2016-05-18 10:24 ` Peter Ujfalusi
@ 2016-05-18 19:30 ` Tony Lindgren
2016-05-19 6:14 ` Kishon Vijay Abraham I
2016-05-19 8:07 ` Peter Ujfalusi
2016-05-19 6:06 ` Kishon Vijay Abraham I
1 sibling, 2 replies; 17+ messages in thread
From: Tony Lindgren @ 2016-05-18 19:30 UTC (permalink / raw)
To: Peter Ujfalusi
Cc: Kishon Vijay Abraham I, linux-kernel, linux-omap,
linux-arm-kernel, linux-mmc, afenkart, ulf.hansson, linux, rogerq,
bcousson, galak, ijc+devicetree, mark.rutland, pawel.moll,
robh+dt, nsekhar
* Peter Ujfalusi <peter.ujfalusi@ti.com> [160518 03:26]:
> On 05/18/16 11:45, Kishon Vijay Abraham I wrote:
> > omap hsmmc host controller has ADMA2 feature. Enable it here
> > for better read and write throughput. Add a new dt binding
> > "ti,use_adma" to enable ADMA2.
> >
> > Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> > ---
> > .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 1 +
> > drivers/mmc/host/omap_hsmmc.c | 320 ++++++++++++++++----
> > include/linux/platform_data/hsmmc-omap.h | 1 +
> > 3 files changed, 256 insertions(+), 66 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> > index 74166a0..eb5ceec2 100644
> > --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> > +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> > @@ -28,6 +28,7 @@ specifier is required.
> > dma-names: List of DMA request names. These strings correspond
> > 1:1 with the DMA specifiers listed in dmas. The string naming is
> > to be "rx" and "tx" for RX and TX DMA requests, respectively.
> > +ti,use_adma: enable adma2 feature
>
> Do we have use case when you want to fall back to generic DMA instead of aDMA2?
Yes my guess is that PM runtime breaks with these currently..
> IMHO if the driver supports aDMA2, it is going to use it instead of the
> generic s/eDMA.
> What I mean is:
> the driver implements the aDMA2 support.
> if the IP has support for aDMA2, then it is going to use it, otherwise it will
> use the generic DMA.
Ideally the adma support would be a separate loadable module,
similar how the cppi41dma is a child of the OTG controller.
That way the systems wanting to use adma can just specify it
in the binding, and adma PM runtime support can be added later
on.
Of course this won't work if the adma registers are sprinkled
within the MMC controller registers..
Regards,
Tony
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
2016-05-18 10:24 ` Peter Ujfalusi
2016-05-18 19:30 ` Tony Lindgren
@ 2016-05-19 6:06 ` Kishon Vijay Abraham I
2016-05-19 8:02 ` Peter Ujfalusi
1 sibling, 1 reply; 17+ messages in thread
From: Kishon Vijay Abraham I @ 2016-05-19 6:06 UTC (permalink / raw)
To: Peter Ujfalusi, linux-kernel, linux-omap, linux-arm-kernel,
linux-mmc, afenkart, ulf.hansson, linux, tony
Cc: rogerq, bcousson, galak, ijc+devicetree, mark.rutland, pawel.moll,
robh+dt, nsekhar
Hi Peter,
On Wednesday 18 May 2016 03:54 PM, Peter Ujfalusi wrote:
> On 05/18/16 11:45, Kishon Vijay Abraham I wrote:
>> omap hsmmc host controller has ADMA2 feature. Enable it here
>> for better read and write throughput. Add a new dt binding
>> "ti,use_adma" to enable ADMA2.
>>
>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>> ---
>> .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 1 +
>> drivers/mmc/host/omap_hsmmc.c | 320 ++++++++++++++++----
>> include/linux/platform_data/hsmmc-omap.h | 1 +
>> 3 files changed, 256 insertions(+), 66 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>> index 74166a0..eb5ceec2 100644
>> --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>> +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>> @@ -28,6 +28,7 @@ specifier is required.
>> dma-names: List of DMA request names. These strings correspond
>> 1:1 with the DMA specifiers listed in dmas. The string naming is
>> to be "rx" and "tx" for RX and TX DMA requests, respectively.
>> +ti,use_adma: enable adma2 feature
>
> Do we have use case when you want to fall back to generic DMA instead of aDMA2?
> IMHO if the driver supports aDMA2, it is going to use it instead of the
> generic s/eDMA.
> What I mean is:
> the driver implements the aDMA2 support.
> if the IP has support for aDMA2, then it is going to use it, otherwise it will
> use the generic DMA.
hmm.. how will the driver know if the IP has support for aDMA2. Using dt
binding is one way. Using MMCHS_HL_HWINFO is another way but then the register
offsets in omap_hsmmc driver has to be modified for omap4+.
Thanks
Kishon
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
2016-05-18 19:30 ` Tony Lindgren
@ 2016-05-19 6:14 ` Kishon Vijay Abraham I
2016-05-19 8:07 ` Peter Ujfalusi
1 sibling, 0 replies; 17+ messages in thread
From: Kishon Vijay Abraham I @ 2016-05-19 6:14 UTC (permalink / raw)
To: Tony Lindgren, Peter Ujfalusi
Cc: linux-kernel, linux-omap, linux-arm-kernel, linux-mmc, afenkart,
ulf.hansson, linux, rogerq, bcousson, galak, ijc+devicetree,
mark.rutland, pawel.moll, robh+dt, nsekhar
Hi Tony,
On Thursday 19 May 2016 01:00 AM, Tony Lindgren wrote:
> * Peter Ujfalusi <peter.ujfalusi@ti.com> [160518 03:26]:
>> On 05/18/16 11:45, Kishon Vijay Abraham I wrote:
>>> omap hsmmc host controller has ADMA2 feature. Enable it here
>>> for better read and write throughput. Add a new dt binding
>>> "ti,use_adma" to enable ADMA2.
>>>
>>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>>> ---
>>> .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 1 +
>>> drivers/mmc/host/omap_hsmmc.c | 320 ++++++++++++++++----
>>> include/linux/platform_data/hsmmc-omap.h | 1 +
>>> 3 files changed, 256 insertions(+), 66 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> index 74166a0..eb5ceec2 100644
>>> --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> @@ -28,6 +28,7 @@ specifier is required.
>>> dma-names: List of DMA request names. These strings correspond
>>> 1:1 with the DMA specifiers listed in dmas. The string naming is
>>> to be "rx" and "tx" for RX and TX DMA requests, respectively.
>>> +ti,use_adma: enable adma2 feature
>>
>> Do we have use case when you want to fall back to generic DMA instead of aDMA2?
>
> Yes my guess is that PM runtime breaks with these currently..
pm_runtime_get is invoked during omap_hsmmc_request and pm_runtime_put is
invoked during omap_hsmmc_request_done. Both these calls are outside DMA API's.
So it shouldn't break anything w.r.t PM runtime no?
>
>> IMHO if the driver supports aDMA2, it is going to use it instead of the
>> generic s/eDMA.
>> What I mean is:
>> the driver implements the aDMA2 support.
>> if the IP has support for aDMA2, then it is going to use it, otherwise it will
>> use the generic DMA.
>
> Ideally the adma support would be a separate loadable module,
> similar how the cppi41dma is a child of the OTG controller.
>
> That way the systems wanting to use adma can just specify it
> in the binding, and adma PM runtime support can be added later
> on.
>
> Of course this won't work if the adma registers are sprinkled
> within the MMC controller registers..
right, adma registers are within the MMC controller register space.
Thanks
Kishon
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
2016-05-19 6:06 ` Kishon Vijay Abraham I
@ 2016-05-19 8:02 ` Peter Ujfalusi
0 siblings, 0 replies; 17+ messages in thread
From: Peter Ujfalusi @ 2016-05-19 8:02 UTC (permalink / raw)
To: Kishon Vijay Abraham I, linux-kernel, linux-omap,
linux-arm-kernel, linux-mmc, afenkart, ulf.hansson, linux, tony
Cc: rogerq, bcousson, galak, ijc+devicetree, mark.rutland, pawel.moll,
robh+dt, nsekhar
On 05/19/2016 09:06 AM, Kishon Vijay Abraham I wrote:
> Hi Peter,
>
> On Wednesday 18 May 2016 03:54 PM, Peter Ujfalusi wrote:
>> On 05/18/16 11:45, Kishon Vijay Abraham I wrote:
>>> omap hsmmc host controller has ADMA2 feature. Enable it here
>>> for better read and write throughput. Add a new dt binding
>>> "ti,use_adma" to enable ADMA2.
>>>
>>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>>> ---
>>> .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 1 +
>>> drivers/mmc/host/omap_hsmmc.c | 320 ++++++++++++++++----
>>> include/linux/platform_data/hsmmc-omap.h | 1 +
>>> 3 files changed, 256 insertions(+), 66 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> index 74166a0..eb5ceec2 100644
>>> --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> @@ -28,6 +28,7 @@ specifier is required.
>>> dma-names: List of DMA request names. These strings correspond
>>> 1:1 with the DMA specifiers listed in dmas. The string naming is
>>> to be "rx" and "tx" for RX and TX DMA requests, respectively.
>>> +ti,use_adma: enable adma2 feature
>>
>> Do we have use case when you want to fall back to generic DMA instead of aDMA2?
>> IMHO if the driver supports aDMA2, it is going to use it instead of the
>> generic s/eDMA.
>> What I mean is:
>> the driver implements the aDMA2 support.
>> if the IP has support for aDMA2, then it is going to use it, otherwise it will
>> use the generic DMA.
>
> hmm.. how will the driver know if the IP has support for aDMA2. Using dt
> binding is one way. Using MMCHS_HL_HWINFO is another way but then the register
> offsets in omap_hsmmc driver has to be modified for omap4+.
I remember Felipe saying that MMCHS_HL_HWINFO is not reliable for some reason?
But in any case it would be better IMHO if we query the HW for Master DMA
support and if it is available we will use it.
If it is really the case that MMCHS_HL_HWINFO is not reliable, then probably
have a flag for the MMC/SD phandle saying that ti,master_dma_supported to
indicate that it is capable has ADMA support also.
--
Péter
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
2016-05-18 19:30 ` Tony Lindgren
2016-05-19 6:14 ` Kishon Vijay Abraham I
@ 2016-05-19 8:07 ` Peter Ujfalusi
2016-05-19 14:57 ` Tony Lindgren
1 sibling, 1 reply; 17+ messages in thread
From: Peter Ujfalusi @ 2016-05-19 8:07 UTC (permalink / raw)
To: Tony Lindgren
Cc: Kishon Vijay Abraham I, linux-kernel, linux-omap,
linux-arm-kernel, linux-mmc, afenkart, ulf.hansson, linux, rogerq,
bcousson, galak, ijc+devicetree, mark.rutland, pawel.moll,
robh+dt, nsekhar
On 05/18/2016 10:30 PM, Tony Lindgren wrote:
> * Peter Ujfalusi <peter.ujfalusi@ti.com> [160518 03:26]:
>> On 05/18/16 11:45, Kishon Vijay Abraham I wrote:
>>> omap hsmmc host controller has ADMA2 feature. Enable it here
>>> for better read and write throughput. Add a new dt binding
>>> "ti,use_adma" to enable ADMA2.
>>>
>>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>>> ---
>>> .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 1 +
>>> drivers/mmc/host/omap_hsmmc.c | 320 ++++++++++++++++----
>>> include/linux/platform_data/hsmmc-omap.h | 1 +
>>> 3 files changed, 256 insertions(+), 66 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> index 74166a0..eb5ceec2 100644
>>> --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> @@ -28,6 +28,7 @@ specifier is required.
>>> dma-names: List of DMA request names. These strings correspond
>>> 1:1 with the DMA specifiers listed in dmas. The string naming is
>>> to be "rx" and "tx" for RX and TX DMA requests, respectively.
>>> +ti,use_adma: enable adma2 feature
>>
>> Do we have use case when you want to fall back to generic DMA instead of aDMA2?
>
> Yes my guess is that PM runtime breaks with these currently..
>
>> IMHO if the driver supports aDMA2, it is going to use it instead of the
>> generic s/eDMA.
>> What I mean is:
>> the driver implements the aDMA2 support.
>> if the IP has support for aDMA2, then it is going to use it, otherwise it will
>> use the generic DMA.
>
> Ideally the adma support would be a separate loadable module,
> similar how the cppi41dma is a child of the OTG controller.
The Master DMA is part of the hsmmc IP block. If the same ADMA module is
present on other IPs it might be beneficial to have a helper library to handle
it (allocating the descriptor pool, wrinting, updating descriptors, etc).
> That way the systems wanting to use adma can just specify it
> in the binding, and adma PM runtime support can be added later
> on.
>
> Of course this won't work if the adma registers are sprinkled
> within the MMC controller registers..
>
> Regards,
>
> Tony
>
--
Péter
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
2016-05-18 8:45 ` [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2 Kishon Vijay Abraham I
2016-05-18 10:24 ` Peter Ujfalusi
2016-05-18 11:07 ` Peter Ujfalusi
@ 2016-05-19 8:25 ` Peter Ujfalusi
2 siblings, 0 replies; 17+ messages in thread
From: Peter Ujfalusi @ 2016-05-19 8:25 UTC (permalink / raw)
To: Kishon Vijay Abraham I, linux-kernel, linux-omap,
linux-arm-kernel, linux-mmc, afenkart, ulf.hansson, linux, tony
Cc: rogerq, bcousson, galak, ijc+devicetree, mark.rutland, pawel.moll,
robh+dt, nsekhar
On 05/18/2016 11:45 AM, Kishon Vijay Abraham I wrote:
> omap hsmmc host controller has ADMA2 feature. Enable it here
> for better read and write throughput. Add a new dt binding
> "ti,use_adma" to enable ADMA2.
>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> ---
> .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 1 +
> drivers/mmc/host/omap_hsmmc.c | 320 ++++++++++++++++----
> include/linux/platform_data/hsmmc-omap.h | 1 +
> 3 files changed, 256 insertions(+), 66 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> index 74166a0..eb5ceec2 100644
> --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> @@ -28,6 +28,7 @@ specifier is required.
> dma-names: List of DMA request names. These strings correspond
> 1:1 with the DMA specifiers listed in dmas. The string naming is
> to be "rx" and "tx" for RX and TX DMA requests, respectively.
> +ti,use_adma: enable adma2 feature
>
> Examples:
>
> diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
> index cc916d5..b4a7d18 100644
> --- a/drivers/mmc/host/omap_hsmmc.c
> +++ b/drivers/mmc/host/omap_hsmmc.c
> @@ -66,6 +66,8 @@
> #define OMAP_HSMMC_ISE 0x0138
> #define OMAP_HSMMC_AC12 0x013C
> #define OMAP_HSMMC_CAPA 0x0140
> +#define OMAP_HSMMC_ADMAES 0x0154
> +#define OMAP_HSMMC_ADMASAL 0x0158
>
> #define VS18 (1 << 26)
> #define VS30 (1 << 25)
> @@ -76,6 +78,7 @@
> #define SDVS_MASK 0x00000E00
> #define SDVSCLR 0xFFFFF1FF
> #define SDVSDET 0x00000400
> +#define DMA_SELECT (2 << 3)
> #define AUTOIDLE 0x1
> #define SDBP (1 << 8)
> #define DTO 0xe
> @@ -97,6 +100,7 @@
> #define FOUR_BIT (1 << 1)
> #define HSPE (1 << 2)
> #define IWE (1 << 24)
> +#define DMA_MASTER (1 << 20)
> #define DDR (1 << 19)
> #define CLKEXTFREE (1 << 16)
> #define CTPL (1 << 11)
> @@ -127,10 +131,11 @@
> #define DCRC_EN (1 << 21)
> #define DEB_EN (1 << 22)
> #define ACE_EN (1 << 24)
> +#define ADMAE_EN (1 << 24)
> #define CERR_EN (1 << 28)
> #define BADA_EN (1 << 29)
>
> -#define INT_EN_MASK (BADA_EN | CERR_EN | ACE_EN | DEB_EN | DCRC_EN |\
> +#define INT_EN_MASK (BADA_EN | CERR_EN | ADMAE_EN | ACE_EN | DEB_EN | DCRC_EN |\
> DTO_EN | CIE_EN | CEB_EN | CCRC_EN | CTO_EN | \
> BRR_EN | BWR_EN | TC_EN | CC_EN)
>
> @@ -168,6 +173,25 @@
> #define OMAP_HSMMC_WRITE(base, reg, val) \
> __raw_writel((val), (base) + OMAP_HSMMC_##reg)
>
> +struct omap_hsmmc_adma_desc {
> + u8 attr;
> + u8 reserved;
> + u16 len;
> + u32 addr;
> +} __packed;
> +
> +#define ADMA_MAX_LEN 65532
> +
> +/* Decriptor table defines */
> +#define ADMA_DESC_ATTR_VALID BIT(0)
> +#define ADMA_DESC_ATTR_END BIT(1)
> +#define ADMA_DESC_ATTR_INT BIT(2)
> +#define ADMA_DESC_ATTR_ACT1 BIT(4)
> +#define ADMA_DESC_ATTR_ACT2 BIT(5)
> +
> +#define ADMA_DESC_TRANSFER_DATA ADMA_DESC_ATTR_ACT2
> +#define ADMA_DESC_LINK_DESC (ADMA_DESC_ATTR_ACT1 | ADMA_DESC_ATTR_ACT2)
> +
> struct omap_hsmmc_next {
> unsigned int dma_len;
> s32 cookie;
> @@ -213,6 +237,9 @@ struct omap_hsmmc_host {
> struct omap_hsmmc_next next_data;
> struct omap_hsmmc_platform_data *pdata;
>
> + struct omap_hsmmc_adma_desc *adma_desc_table;
> + dma_addr_t adma_desc_table_addr;
> +
> /* return MMC cover switch state, can be NULL if not supported.
> *
> * possible return values:
> @@ -951,6 +978,19 @@ static struct dma_chan *omap_hsmmc_get_dma_chan(struct omap_hsmmc_host *host,
> return data->flags & MMC_DATA_WRITE ? host->tx_chan : host->rx_chan;
> }
>
> +static void omap_hsmmc_adma_cleanup(struct omap_hsmmc_host *host)
> +{
> + u32 val;
> +
> + val = OMAP_HSMMC_READ(host->base, HCTL);
> + val &= ~DMA_SELECT;
> + OMAP_HSMMC_WRITE(host->base, HCTL, val);
> +
> + val = OMAP_HSMMC_READ(host->base, CON);
> + val &= ~DMA_MASTER;
> + OMAP_HSMMC_WRITE(host->base, CON, val);
> +}
> +
> static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_request *mrq)
> {
> int dma_ch;
> @@ -963,8 +1003,11 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req
>
> omap_hsmmc_disable_irq(host);
> /* Do not complete the request if DMA is still in progress */
> - if (mrq->data && dma_ch != -1)
> + if (host->pdata->controller_flags == OMAP_HSMMC_USE_ADMA)
host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA
and I would probably name the flag to OMAP_HSMMC_MASTER_DMA_SUPPORTED
> + omap_hsmmc_adma_cleanup(host);
> + else if (mrq->data && dma_ch != -1)
> return;
> +
> host->mrq = NULL;
> mmc_request_done(host->mmc, mrq);
> pm_runtime_mark_last_busy(host->dev);
> @@ -1052,15 +1095,22 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno)
> host->dma_ch = -1;
> spin_unlock_irqrestore(&host->irq_lock, flags);
>
> - if (dma_ch != -1) {
> - struct dma_chan *chan = omap_hsmmc_get_dma_chan(host, host->data);
> -
> - dmaengine_terminate_all(chan);
> - dma_unmap_sg(chan->device->dev,
> - host->data->sg, host->data->sg_len,
> + if (!(host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)) {
it might be better to use the same order in the driver for Master and Slave
DMA cases:
if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA) {
/* Master DMA case */
} else {
/* Slave DMA case */
}
It will make the driver easier to read.
> + if (dma_ch != -1) {
> + struct dma_chan *chan = omap_hsmmc_get_dma_chan(host,
> + host->data);
> + dmaengine_terminate_all(chan);
> + dma_unmap_sg(chan->device->dev,
> + host->data->sg, host->data->sg_len,
> omap_hsmmc_get_dma_dir(host, host->data));
>
> + host->data->host_cookie = 0;
> + }
> + } else {
> + dma_unmap_sg(host->dev, host->data->sg, host->data->sg_len,
> + omap_hsmmc_get_dma_dir(host, host->data));
> host->data->host_cookie = 0;
> +
> }
> host->data = NULL;
> }
> @@ -1191,6 +1241,14 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
> }
> dev_dbg(mmc_dev(host->mmc), "AC12 err: 0x%x\n", ac12);
> }
> +
> + if (status & ADMAE_EN) {
> + u32 val;
> +
> + val = OMAP_HSMMC_READ(host->base, ADMAES);
> + dev_dbg(mmc_dev(host->mmc), "ADMA error status: 0x%x\n",
> + val);
> + }
> }
>
> OMAP_HSMMC_WRITE(host->base, STAT, status);
> @@ -1378,6 +1436,7 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host,
> struct dma_chan *chan)
> {
> int dma_len;
> + struct device *dev;
>
> if (!next && data->host_cookie &&
> data->host_cookie != host->next_data.cookie) {
> @@ -1387,9 +1446,14 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host,
> data->host_cookie = 0;
> }
>
> + if (chan)
> + dev = chan->device->dev;
> + else
> + dev = mmc_dev(host->mmc);
> +
> /* Check if next job is already prepared */
> if (next || data->host_cookie != host->next_data.cookie) {
> - dma_len = dma_map_sg(chan->device->dev, data->sg, data->sg_len,
> + dma_len = dma_map_sg(dev, data->sg, data->sg_len,
> omap_hsmmc_get_dma_dir(host, data));
>
> } else {
> @@ -1516,6 +1580,7 @@ static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host)
> {
> struct mmc_request *req = host->mrq;
> struct dma_chan *chan;
> + int val;
>
> if (!req->data)
> return;
> @@ -1523,10 +1588,66 @@ static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host)
> | (req->data->blocks << 16));
> set_data_timeout(host, req->data->timeout_ns,
> req->data->timeout_clks);
> - chan = omap_hsmmc_get_dma_chan(host, req->data);
> - dma_async_issue_pending(chan);
> +
> + if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA) {
> + val = OMAP_HSMMC_READ(host->base, HCTL);
> + val |= DMA_SELECT;
> + OMAP_HSMMC_WRITE(host->base, HCTL, val);
> +
> + val = OMAP_HSMMC_READ(host->base, CON);
> + val |= DMA_MASTER;
> + OMAP_HSMMC_WRITE(host->base, CON, val);
> +
> + OMAP_HSMMC_WRITE(host->base, ADMASAL,
> + (u32)host->adma_desc_table_addr);
> + } else {
> + chan = omap_hsmmc_get_dma_chan(host, req->data);
> + dma_async_issue_pending(chan);
> + }
> +}
> +
> +static int omap_hsmmc_write_adma_desc(struct omap_hsmmc_host *host, void *desc,
> + dma_addr_t addr, u16 len, u8 attr)
> +{
> + struct omap_hsmmc_adma_desc *dma_desc = desc;
> +
> + dma_desc->len = len;
> + dma_desc->addr = (u32)addr;
> + dma_desc->reserved = 0;
> + dma_desc->attr = attr;
> +
> + return 0;
> }
>
> +static int omap_hsmmc_setup_adma_transfer(struct omap_hsmmc_host *host,
> + struct mmc_request *req)
> +{
> + struct mmc_data *data = req->data;
> + struct scatterlist *sg;
> + int i;
> + int len;
> + int ret;
> + dma_addr_t addr;
> + struct omap_hsmmc_adma_desc *dma_desc;
> +
> + ret = omap_hsmmc_pre_dma_transfer(host, data, NULL, NULL);
> + if (ret)
> + return ret;
> +
> + dma_desc = host->adma_desc_table;
> + for_each_sg(data->sg, sg, host->dma_len, i) {
> + addr = sg_dma_address(sg);
> + len = sg_dma_len(sg);
> + WARN_ON(len > ADMA_MAX_LEN);
> + omap_hsmmc_write_adma_desc(host, dma_desc, addr, len,
> + ADMA_DESC_ATTR_VALID |
> + ADMA_DESC_TRANSFER_DATA);
> + dma_desc++;
> + }
> + omap_hsmmc_write_adma_desc(host, dma_desc, 0, 0, ADMA_DESC_ATTR_END);
> +
> + return 0;
> +}
Would be nice to group the ADMA functions in one section, not scattering it
around the driver.
> /*
> * Configure block length for MMC/SD cards and initiate the transfer.
> */
> @@ -1547,10 +1668,18 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req)
> return 0;
> }
>
> - ret = omap_hsmmc_setup_dma_transfer(host, req);
> - if (ret != 0) {
> - dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
> - return ret;
> + if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA) {
> + ret = omap_hsmmc_setup_adma_transfer(host, req);
> + if (ret != 0) {
> + dev_err(mmc_dev(host->mmc), "MMC adma setup failed\n");
> + return ret;
> + }
> + } else {
> + ret = omap_hsmmc_setup_dma_transfer(host, req);
> + if (ret != 0) {
> + dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
> + return ret;
the error checking can go outside
> + }
> }
> return 0;
if (ret != 0)
dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
return ret;
if compiler complains about ret not beeing initialized
int rer = 0;
> }
> @@ -1560,11 +1689,18 @@ static void omap_hsmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
> {
> struct omap_hsmmc_host *host = mmc_priv(mmc);
> struct mmc_data *data = mrq->data;
> + struct device *dev;
> + struct dma_chan *c;
>
> if (data->host_cookie) {
> - struct dma_chan *c = omap_hsmmc_get_dma_chan(host, data);
> + if (!(host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)) {
> + c = omap_hsmmc_get_dma_chan(host, mrq->data);
> + dev = c->device->dev;
> + } else {
> + dev = mmc_dev(mmc);
> + }
>
> - dma_unmap_sg(c->device->dev, data->sg, data->sg_len,
> + dma_unmap_sg(dev, data->sg, data->sg_len,
> omap_hsmmc_get_dma_dir(host, data));
> data->host_cookie = 0;
> }
> @@ -1574,13 +1710,15 @@ static void omap_hsmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
> bool is_first_req)
> {
> struct omap_hsmmc_host *host = mmc_priv(mmc);
> + struct dma_chan *c = NULL;
>
> if (mrq->data->host_cookie) {
> mrq->data->host_cookie = 0;
> return ;
> }
>
> - struct dma_chan *c = omap_hsmmc_get_dma_chan(host, mrq->data);
> + if (!(host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA))
> + c = omap_hsmmc_get_dma_chan(host, mrq->data);
>
> if (omap_hsmmc_pre_dma_transfer(host, mrq->data,
> &host->next_data, c))
> @@ -1967,6 +2105,9 @@ static struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
> if (of_find_property(np, "ti,dual-volt", NULL))
> pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT;
>
> + if (of_find_property(np, "ti,use_adma", NULL))
> + pdata->controller_flags |= OMAP_HSMMC_USE_ADMA;
> +
> pdata->gpio_cd = -EINVAL;
> pdata->gpio_cod = -EINVAL;
> pdata->gpio_wp = -EINVAL;
> @@ -1992,6 +2133,84 @@ static inline struct omap_hsmmc_platform_data
> }
> #endif
>
> +static int omap_hsmmc_adma_init(struct omap_hsmmc_host *host)
> +{
> + struct mmc_host *mmc = host->mmc;
> +
> + host->adma_desc_table = dma_alloc_coherent(host->dev, mmc->max_segs + 1,
> + &host->adma_desc_table_addr,
> + GFP_KERNEL);
> + if (!host->adma_desc_table) {
> + dev_err(host->dev, "failed to allocate adma desc table\n");
> + return -ENOMEM;
Fall back to Slave DMA?
> + }
> +
> + return 0;
> +}
> +
> +static void omap_hsmmc_adma_exit(struct omap_hsmmc_host *host)
> +{
> + struct mmc_host *mmc = host->mmc;
> +
> + dma_free_coherent(host->dev, mmc->max_segs + 1,
> + host->adma_desc_table, host->adma_desc_table_addr);
> +}
> +
> +static int omap_hsmmc_dma_init(struct omap_hsmmc_host *host)
> +{
> + dma_cap_mask_t mask;
> + unsigned int tx_req, rx_req;
> + struct resource *res;
> + struct platform_device *pdev = to_platform_device(host->dev);
> +
> + dma_cap_zero(mask);
> + dma_cap_set(DMA_SLAVE, mask);
> +
> + if (!pdev->dev.of_node) {
> + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
> + if (!res) {
> + dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
> + return -ENXIO;
> + }
> + tx_req = res->start;
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
> + if (!res) {
> + dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
> + return -ENXIO;
> + }
> + rx_req = res->start;
> + }
> +
> + host->rx_chan =
> + dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
> + &rx_req, &pdev->dev, "rx");
> +
> + if (!host->rx_chan) {
> + dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel\n");
> + return -ENXIO;
> + }
> +
> + host->tx_chan =
> + dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
> + &tx_req, &pdev->dev, "tx");
> +
> + if (!host->tx_chan) {
> + dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel\n");
> + return -ENXIO;
> + }
> +
> + return 0;
> +}
> +
> +static void omap_hsmmc_dma_exit(struct omap_hsmmc_host *host)
> +{
> + if (host->tx_chan)
> + dma_release_channel(host->tx_chan);
> + if (host->rx_chan)
> + dma_release_channel(host->rx_chan);
> +}
> +
> static int omap_hsmmc_probe(struct platform_device *pdev)
> {
> struct omap_hsmmc_platform_data *pdata = pdev->dev.platform_data;
> @@ -2000,8 +2219,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
> struct resource *res;
> int ret, irq;
> const struct of_device_id *match;
> - dma_cap_mask_t mask;
> - unsigned tx_req, rx_req;
> const struct omap_mmc_of_data *data;
> void __iomem *base;
>
> @@ -2114,7 +2331,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
> mmc->max_blk_size = 512; /* Block Length at max can be 1024 */
> mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */
> mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
> - mmc->max_seg_size = mmc->max_req_size;
> + if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
> + mmc->max_seg_size = ADMA_MAX_LEN;
> + else
> + mmc->max_seg_size = mmc->max_req_size;
>
> mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
> MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
> @@ -2130,46 +2350,12 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
>
> omap_hsmmc_conf_bus_power(host);
>
> - if (!pdev->dev.of_node) {
> - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
> - if (!res) {
> - dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
> - ret = -ENXIO;
> - goto err_irq;
> - }
> - tx_req = res->start;
> -
> - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
> - if (!res) {
> - dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
> - ret = -ENXIO;
> - goto err_irq;
> - }
> - rx_req = res->start;
> - }
> -
> - dma_cap_zero(mask);
> - dma_cap_set(DMA_SLAVE, mask);
> -
> - host->rx_chan =
> - dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
> - &rx_req, &pdev->dev, "rx");
> -
> - if (!host->rx_chan) {
> - dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel\n");
> - ret = -ENXIO;
> - goto err_irq;
> - }
> -
> - host->tx_chan =
> - dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
> - &tx_req, &pdev->dev, "tx");
> -
> - if (!host->tx_chan) {
> - dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel\n");
> - ret = -ENXIO;
> + if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
> + ret = omap_hsmmc_adma_init(host);
> + else
> + ret = omap_hsmmc_dma_init(host);
> + if (ret)
> goto err_irq;
> - }
>
> /* Request IRQ for MMC operations */
> ret = devm_request_irq(&pdev->dev, host->irq, omap_hsmmc_irq, 0,
> @@ -2225,11 +2411,11 @@ err_slot_name:
> mmc_remove_host(mmc);
> err_irq:
> device_init_wakeup(&pdev->dev, false);
> - if (host->tx_chan)
> - dma_release_channel(host->tx_chan);
> - if (host->rx_chan)
> - dma_release_channel(host->rx_chan);
> pm_runtime_dont_use_autosuspend(host->dev);
> + if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
> + omap_hsmmc_adma_exit(host);
> + else
> + omap_hsmmc_dma_exit(host);
> pm_runtime_put_sync(host->dev);
> pm_runtime_disable(host->dev);
> if (host->dbclk)
> @@ -2248,8 +2434,10 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
> pm_runtime_get_sync(host->dev);
> mmc_remove_host(host->mmc);
>
> - dma_release_channel(host->tx_chan);
> - dma_release_channel(host->rx_chan);
> + if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
> + omap_hsmmc_adma_exit(host);
> + else
> + omap_hsmmc_dma_exit(host);
>
> pm_runtime_dont_use_autosuspend(host->dev);
> pm_runtime_put_sync(host->dev);
> diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h
> index 8e981be..e26013d 100644
> --- a/include/linux/platform_data/hsmmc-omap.h
> +++ b/include/linux/platform_data/hsmmc-omap.h
> @@ -27,6 +27,7 @@
> #define OMAP_HSMMC_SUPPORTS_DUAL_VOLT BIT(0)
> #define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ BIT(1)
> #define OMAP_HSMMC_SWAKEUP_MISSING BIT(2)
> +#define OMAP_HSMMC_USE_ADMA BIT(3)
>
> struct omap_hsmmc_dev_attr {
> u8 flags;
>
--
Péter
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
2016-05-19 8:07 ` Peter Ujfalusi
@ 2016-05-19 14:57 ` Tony Lindgren
2016-05-19 18:36 ` Felipe Balbi
0 siblings, 1 reply; 17+ messages in thread
From: Tony Lindgren @ 2016-05-19 14:57 UTC (permalink / raw)
To: Peter Ujfalusi
Cc: Kishon Vijay Abraham I, linux-kernel, linux-omap,
linux-arm-kernel, linux-mmc, afenkart, ulf.hansson, linux, rogerq,
bcousson, galak, ijc+devicetree, mark.rutland, pawel.moll,
robh+dt, nsekhar, Felipe Balbi
* Peter Ujfalusi <peter.ujfalusi@ti.com> [160519 01:10]:
> On 05/18/2016 10:30 PM, Tony Lindgren wrote:
> > Ideally the adma support would be a separate loadable module,
> > similar how the cppi41dma is a child of the OTG controller.
>
> The Master DMA is part of the hsmmc IP block. If the same ADMA module is
> present on other IPs it might be beneficial to have a helper library to handle
> it (allocating the descriptor pool, wrinting, updating descriptors, etc).
OK. Yeah if it's part of the MMC controller it makes no sense to
separate it. So then the conecrns are using alternate DMA
implementations and keeping PM runtime working :)
BTW, Felipe mentioned that the best thing to do in the long run would
be to set up sdhci-omap.c operating in ADMA mode.
Felipe, care to summarize what you had in mind?
Regards,
Tony
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
2016-05-19 14:57 ` Tony Lindgren
@ 2016-05-19 18:36 ` Felipe Balbi
2016-05-23 6:22 ` Kishon Vijay Abraham I
0 siblings, 1 reply; 17+ messages in thread
From: Felipe Balbi @ 2016-05-19 18:36 UTC (permalink / raw)
To: Tony Lindgren, Peter Ujfalusi
Cc: Kishon Vijay Abraham I, linux-kernel, linux-omap,
linux-arm-kernel, linux-mmc, afenkart, ulf.hansson, linux, rogerq,
bcousson, galak, ijc+devicetree, mark.rutland, pawel.moll,
robh+dt, nsekhar
[-- Attachment #1: Type: text/plain, Size: 1417 bytes --]
Hi,
Tony Lindgren <tony@atomide.com> writes:
> * Peter Ujfalusi <peter.ujfalusi@ti.com> [160519 01:10]:
>> On 05/18/2016 10:30 PM, Tony Lindgren wrote:
>> > Ideally the adma support would be a separate loadable module,
>> > similar how the cppi41dma is a child of the OTG controller.
>>
>> The Master DMA is part of the hsmmc IP block. If the same ADMA module is
>> present on other IPs it might be beneficial to have a helper library to handle
>> it (allocating the descriptor pool, wrinting, updating descriptors, etc).
>
> OK. Yeah if it's part of the MMC controller it makes no sense to
> separate it. So then the conecrns are using alternate DMA
> implementations and keeping PM runtime working :)
>
> BTW, Felipe mentioned that the best thing to do in the long run would
> be to set up sdhci-omap.c operating in ADMA mode.
>
> Felipe, care to summarize what you had in mind?
yeah, just write a new sdhci-omap.c to start moving away from
omap-hsmmc.c, just like it was done for 8250-omap.
At the beginning, it could be just the bare minimum to get it working
and slowly move over stuff like pm runtime, dmaengine, PIO. Move more
platforms over to that driver and, eventually, get rid of omap-hsmmc.c
altogether.
That way, development can be focussed on generic layers (SDHCI) to which
OMAP MMC controller is compliant (apart from the VERSION register
quirk).
--
balbi
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 818 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
2016-05-19 18:36 ` Felipe Balbi
@ 2016-05-23 6:22 ` Kishon Vijay Abraham I
2016-05-23 7:18 ` Felipe Balbi
0 siblings, 1 reply; 17+ messages in thread
From: Kishon Vijay Abraham I @ 2016-05-23 6:22 UTC (permalink / raw)
To: Felipe Balbi, Tony Lindgren, Peter Ujfalusi
Cc: linux-kernel, linux-omap, linux-arm-kernel, linux-mmc, afenkart,
ulf.hansson, linux, rogerq, bcousson, galak, ijc+devicetree,
mark.rutland, pawel.moll, robh+dt, nsekhar
Hi Felipe,
On Friday 20 May 2016 12:06 AM, Felipe Balbi wrote:
>
> Hi,
>
> Tony Lindgren <tony@atomide.com> writes:
>> * Peter Ujfalusi <peter.ujfalusi@ti.com> [160519 01:10]:
>>> On 05/18/2016 10:30 PM, Tony Lindgren wrote:
>>>> Ideally the adma support would be a separate loadable module,
>>>> similar how the cppi41dma is a child of the OTG controller.
>>>
>>> The Master DMA is part of the hsmmc IP block. If the same ADMA module is
>>> present on other IPs it might be beneficial to have a helper library to handle
>>> it (allocating the descriptor pool, wrinting, updating descriptors, etc).
>>
>> OK. Yeah if it's part of the MMC controller it makes no sense to
>> separate it. So then the conecrns are using alternate DMA
>> implementations and keeping PM runtime working :)
>>
>> BTW, Felipe mentioned that the best thing to do in the long run would
>> be to set up sdhci-omap.c operating in ADMA mode.
>>
>> Felipe, care to summarize what you had in mind?
>
> yeah, just write a new sdhci-omap.c to start moving away from
> omap-hsmmc.c, just like it was done for 8250-omap.
>
> At the beginning, it could be just the bare minimum to get it working
> and slowly move over stuff like pm runtime, dmaengine, PIO. Move more
> platforms over to that driver and, eventually, get rid of omap-hsmmc.c
> altogether.
>
> That way, development can be focussed on generic layers (SDHCI) to which
> OMAP MMC controller is compliant (apart from the VERSION register
> quirk).
About an year back, when I tried using SDHCI for OMAP I ran into issues and was
not able to get it working. IIRC SDHCI_PRESENT_STATE (or OMAP_HSMMC_PSTATE) was
not showing the correct state for card present and is unable to raise an
interrupt when a card is inserted. I didn't debug this further.
It also kept me wondering why gpio interrupt was always used for card detect
instead of using mmci_sdcd line of the controller.
Thanks
Kishon
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
2016-05-23 6:22 ` Kishon Vijay Abraham I
@ 2016-05-23 7:18 ` Felipe Balbi
2016-05-23 8:00 ` Kishon Vijay Abraham I
0 siblings, 1 reply; 17+ messages in thread
From: Felipe Balbi @ 2016-05-23 7:18 UTC (permalink / raw)
To: Kishon Vijay Abraham I, Tony Lindgren, Peter Ujfalusi
Cc: linux-kernel, linux-omap, linux-arm-kernel, linux-mmc, afenkart,
ulf.hansson, linux, rogerq, bcousson, galak, ijc+devicetree,
mark.rutland, pawel.moll, robh+dt, nsekhar
Hi Kishon,
Kishon Vijay Abraham I <kishon@ti.com> writes:
> Hi Felipe,
>
> On Friday 20 May 2016 12:06 AM, Felipe Balbi wrote:
>>
>> Hi,
>>
>> Tony Lindgren <tony@atomide.com> writes:
>>> * Peter Ujfalusi <peter.ujfalusi@ti.com> [160519 01:10]:
>>>> On 05/18/2016 10:30 PM, Tony Lindgren wrote:
>>>>> Ideally the adma support would be a separate loadable module,
>>>>> similar how the cppi41dma is a child of the OTG controller.
>>>>
>>>> The Master DMA is part of the hsmmc IP block. If the same ADMA module is
>>>> present on other IPs it might be beneficial to have a helper library to handle
>>>> it (allocating the descriptor pool, wrinting, updating descriptors, etc).
>>>
>>> OK. Yeah if it's part of the MMC controller it makes no sense to
>>> separate it. So then the conecrns are using alternate DMA
>>> implementations and keeping PM runtime working :)
>>>
>>> BTW, Felipe mentioned that the best thing to do in the long run would
>>> be to set up sdhci-omap.c operating in ADMA mode.
>>>
>>> Felipe, care to summarize what you had in mind?
>>
>> yeah, just write a new sdhci-omap.c to start moving away from
>> omap-hsmmc.c, just like it was done for 8250-omap.
>>
>> At the beginning, it could be just the bare minimum to get it working
>> and slowly move over stuff like pm runtime, dmaengine, PIO. Move more
>> platforms over to that driver and, eventually, get rid of omap-hsmmc.c
>> altogether.
>>
>> That way, development can be focussed on generic layers (SDHCI) to which
>> OMAP MMC controller is compliant (apart from the VERSION register
>> quirk).
>
> About an year back, when I tried using SDHCI for OMAP I ran into
> issues and was not able to get it working. IIRC SDHCI_PRESENT_STATE
> (or OMAP_HSMMC_PSTATE) was not showing the correct state for card
> present and is unable to raise an interrupt when a card is inserted. I
> didn't debug this further.
I'd say this is a bug in hsmmc. I remember seeing some bits in some
TI-specific register (before SDHCI address space starts) which can be
used to keep parts of SDHCI powered on exactly so normal WP and CD pins
work as expected.
In any case, adding support for GPIO-based card detect to generic SDHCI
shouldn't be too difficult :-)
> It also kept me wondering why gpio interrupt was always used for card
> detect instead of using mmci_sdcd line of the controller.
Probably a really, really old bug which nobody ever debugged properly ;-)
ps: you don't need that ADMA2 DT property, btw. There's a bit in another
register which you can check if $this controller was configured with
ADMA2 support or not. IIRC, OMAP5's TRM describes them.
--
balbi
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
2016-05-23 7:18 ` Felipe Balbi
@ 2016-05-23 8:00 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 17+ messages in thread
From: Kishon Vijay Abraham I @ 2016-05-23 8:00 UTC (permalink / raw)
To: Felipe Balbi, Tony Lindgren, Peter Ujfalusi
Cc: linux-kernel, linux-omap, linux-arm-kernel, linux-mmc, afenkart,
ulf.hansson, linux, rogerq, bcousson, galak, ijc+devicetree,
mark.rutland, pawel.moll, robh+dt, nsekhar
Hi Felipe,
On Monday 23 May 2016 12:48 PM, Felipe Balbi wrote:
>
> Hi Kishon,
>
> Kishon Vijay Abraham I <kishon@ti.com> writes:
>> Hi Felipe,
>>
>> On Friday 20 May 2016 12:06 AM, Felipe Balbi wrote:
>>>
>>> Hi,
>>>
>>> Tony Lindgren <tony@atomide.com> writes:
>>>> * Peter Ujfalusi <peter.ujfalusi@ti.com> [160519 01:10]:
>>>>> On 05/18/2016 10:30 PM, Tony Lindgren wrote:
>>>>>> Ideally the adma support would be a separate loadable module,
>>>>>> similar how the cppi41dma is a child of the OTG controller.
>>>>>
>>>>> The Master DMA is part of the hsmmc IP block. If the same ADMA module is
>>>>> present on other IPs it might be beneficial to have a helper library to handle
>>>>> it (allocating the descriptor pool, wrinting, updating descriptors, etc).
>>>>
>>>> OK. Yeah if it's part of the MMC controller it makes no sense to
>>>> separate it. So then the conecrns are using alternate DMA
>>>> implementations and keeping PM runtime working :)
>>>>
>>>> BTW, Felipe mentioned that the best thing to do in the long run would
>>>> be to set up sdhci-omap.c operating in ADMA mode.
>>>>
>>>> Felipe, care to summarize what you had in mind?
>>>
>>> yeah, just write a new sdhci-omap.c to start moving away from
>>> omap-hsmmc.c, just like it was done for 8250-omap.
>>>
>>> At the beginning, it could be just the bare minimum to get it working
>>> and slowly move over stuff like pm runtime, dmaengine, PIO. Move more
>>> platforms over to that driver and, eventually, get rid of omap-hsmmc.c
>>> altogether.
>>>
>>> That way, development can be focussed on generic layers (SDHCI) to which
>>> OMAP MMC controller is compliant (apart from the VERSION register
>>> quirk).
>>
>> About an year back, when I tried using SDHCI for OMAP I ran into
>> issues and was not able to get it working. IIRC SDHCI_PRESENT_STATE
>> (or OMAP_HSMMC_PSTATE) was not showing the correct state for card
>> present and is unable to raise an interrupt when a card is inserted. I
>> didn't debug this further.
>
> I'd say this is a bug in hsmmc. I remember seeing some bits in some
> TI-specific register (before SDHCI address space starts) which can be
> used to keep parts of SDHCI powered on exactly so normal WP and CD pins
> work as expected.
>
> In any case, adding support for GPIO-based card detect to generic SDHCI
> shouldn't be too difficult :-)
>
>> It also kept me wondering why gpio interrupt was always used for card
>> detect instead of using mmci_sdcd line of the controller.
>
> Probably a really, really old bug which nobody ever debugged properly ;-)
>
> ps: you don't need that ADMA2 DT property, btw. There's a bit in another
> register which you can check if $this controller was configured with
> ADMA2 support or not. IIRC, OMAP5's TRM describes them.
hmm yeah.. Should be the MADMA_EN in MMCHS_HL_HWINFO.
Thanks
Kishon
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2016-05-23 8:01 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-05-18 8:45 [RFC PATCH 0/3] dra7/omap4/omap5: Enable ADMA2 Kishon Vijay Abraham I
2016-05-18 8:45 ` [RFC PATCH 1/3] mmc: host: omap_hsmmc: remove *use_dma* member Kishon Vijay Abraham I
2016-05-18 8:45 ` [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2 Kishon Vijay Abraham I
2016-05-18 10:24 ` Peter Ujfalusi
2016-05-18 19:30 ` Tony Lindgren
2016-05-19 6:14 ` Kishon Vijay Abraham I
2016-05-19 8:07 ` Peter Ujfalusi
2016-05-19 14:57 ` Tony Lindgren
2016-05-19 18:36 ` Felipe Balbi
2016-05-23 6:22 ` Kishon Vijay Abraham I
2016-05-23 7:18 ` Felipe Balbi
2016-05-23 8:00 ` Kishon Vijay Abraham I
2016-05-19 6:06 ` Kishon Vijay Abraham I
2016-05-19 8:02 ` Peter Ujfalusi
2016-05-18 11:07 ` Peter Ujfalusi
2016-05-19 8:25 ` Peter Ujfalusi
2016-05-18 8:45 ` [RFC PATCH 3/3] ARM: dts: dra7/omap4/omap5: " Kishon Vijay Abraham I
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).