linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] mtd: hyperbus: hbmc-am654: Add DMA support
@ 2020-09-17  7:47 Vignesh Raghavendra
  2020-09-17  7:47 ` [PATCH 1/4] mtd: hyperbus: Provide per device private pointer Vignesh Raghavendra
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Vignesh Raghavendra @ 2020-09-17  7:47 UTC (permalink / raw)
  To: Vignesh Raghavendra
  Cc: Miquel Raynal, Richard Weinberger, Sergei Shtylyov, linux-mtd,
	linux-kernel

This series add DMA support for reading data from HyperBus memory
devices for TI's AM654/J721e SoCs

With DMA there is ~5x improvement in read througput.

Vignesh Raghavendra (4):
  mtd: hyperbus: Provide per device private pointer
  mtd: hyperbus: hbmc-am654: Fix direct mapping setup flash access
  mtd: hyperbus: hbmc-am654: Drop pm_runtime* calls from probe
  mtd: hyperbus: hbmc-am654: Add DMA support for reads

 drivers/mtd/hyperbus/hbmc-am654.c | 148 ++++++++++++++++++++++++++----
 include/linux/mtd/hyperbus.h      |   2 +
 2 files changed, 134 insertions(+), 16 deletions(-)

-- 
2.28.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/4] mtd: hyperbus: Provide per device private pointer
  2020-09-17  7:47 [PATCH 0/4] mtd: hyperbus: hbmc-am654: Add DMA support Vignesh Raghavendra
@ 2020-09-17  7:47 ` Vignesh Raghavendra
  2020-09-17  7:47 ` [PATCH 2/4] mtd: hyperbus: hbmc-am654: Fix direct mapping setup flash access Vignesh Raghavendra
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Vignesh Raghavendra @ 2020-09-17  7:47 UTC (permalink / raw)
  To: Vignesh Raghavendra
  Cc: Miquel Raynal, Richard Weinberger, Sergei Shtylyov, linux-mtd,
	linux-kernel

Provide per device private pointer that can be used by controller
drivers to store device specific private data.

Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
---
 include/linux/mtd/hyperbus.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/mtd/hyperbus.h b/include/linux/mtd/hyperbus.h
index 2129f7d3b6eb..d8cb1aec826d 100644
--- a/include/linux/mtd/hyperbus.h
+++ b/include/linux/mtd/hyperbus.h
@@ -20,6 +20,7 @@ enum hyperbus_memtype {
  * @mtd: pointer to MTD struct
  * @ctlr: pointer to HyperBus controller struct
  * @memtype: type of memory device: HyperFlash or HyperRAM
+ * @priv: pointer to controller specific per device private data
  */
 
 struct hyperbus_device {
@@ -28,6 +29,7 @@ struct hyperbus_device {
 	struct mtd_info *mtd;
 	struct hyperbus_ctlr *ctlr;
 	enum hyperbus_memtype memtype;
+	void *priv;
 };
 
 /**
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] mtd: hyperbus: hbmc-am654: Fix direct mapping setup flash access
  2020-09-17  7:47 [PATCH 0/4] mtd: hyperbus: hbmc-am654: Add DMA support Vignesh Raghavendra
  2020-09-17  7:47 ` [PATCH 1/4] mtd: hyperbus: Provide per device private pointer Vignesh Raghavendra
@ 2020-09-17  7:47 ` Vignesh Raghavendra
  2020-09-17  7:47 ` [PATCH 3/4] mtd: hyperbus: hbmc-am654: Drop pm_runtime* calls from probe Vignesh Raghavendra
  2020-09-17  7:47 ` [PATCH 4/4] mtd: hyperbus: hbmc-am654: Add DMA support for reads Vignesh Raghavendra
  3 siblings, 0 replies; 5+ messages in thread
From: Vignesh Raghavendra @ 2020-09-17  7:47 UTC (permalink / raw)
  To: Vignesh Raghavendra
  Cc: Miquel Raynal, Richard Weinberger, Sergei Shtylyov, linux-mtd,
	linux-kernel

Setting up of direct mapping should be done with flash node's IO
address space and not with controller's IO region.

Fixes: b6fe8bc67d2d3 ("mtd: hyperbus: move direct mapping setup to AM654 HBMC driver")
Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
---
 drivers/mtd/hyperbus/hbmc-am654.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/hyperbus/hbmc-am654.c b/drivers/mtd/hyperbus/hbmc-am654.c
index e0e33f6bf513..1e70ecfffa39 100644
--- a/drivers/mtd/hyperbus/hbmc-am654.c
+++ b/drivers/mtd/hyperbus/hbmc-am654.c
@@ -70,7 +70,8 @@ static int am654_hbmc_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, priv);
 
-	ret = of_address_to_resource(np, 0, &res);
+	priv->hbdev.np = of_get_next_child(np, NULL);
+	ret = of_address_to_resource(priv->hbdev.np, 0, &res);
 	if (ret)
 		return ret;
 
@@ -103,7 +104,6 @@ static int am654_hbmc_probe(struct platform_device *pdev)
 	priv->ctlr.dev = dev;
 	priv->ctlr.ops = &am654_hbmc_ops;
 	priv->hbdev.ctlr = &priv->ctlr;
-	priv->hbdev.np = of_get_next_child(dev->of_node, NULL);
 	ret = hyperbus_register_device(&priv->hbdev);
 	if (ret) {
 		dev_err(dev, "failed to register controller\n");
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] mtd: hyperbus: hbmc-am654: Drop pm_runtime* calls from probe
  2020-09-17  7:47 [PATCH 0/4] mtd: hyperbus: hbmc-am654: Add DMA support Vignesh Raghavendra
  2020-09-17  7:47 ` [PATCH 1/4] mtd: hyperbus: Provide per device private pointer Vignesh Raghavendra
  2020-09-17  7:47 ` [PATCH 2/4] mtd: hyperbus: hbmc-am654: Fix direct mapping setup flash access Vignesh Raghavendra
@ 2020-09-17  7:47 ` Vignesh Raghavendra
  2020-09-17  7:47 ` [PATCH 4/4] mtd: hyperbus: hbmc-am654: Add DMA support for reads Vignesh Raghavendra
  3 siblings, 0 replies; 5+ messages in thread
From: Vignesh Raghavendra @ 2020-09-17  7:47 UTC (permalink / raw)
  To: Vignesh Raghavendra
  Cc: Miquel Raynal, Richard Weinberger, Sergei Shtylyov, linux-mtd,
	linux-kernel

Recent genpd changes for K3 platform ensure device is ON before driver
probe is called. Therefore, drop redundant pm_runtime_* calls from
driver to simplify the code.

Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
---
 drivers/mtd/hyperbus/hbmc-am654.c | 16 ++--------------
 1 file changed, 2 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/hyperbus/hbmc-am654.c b/drivers/mtd/hyperbus/hbmc-am654.c
index 1e70ecfffa39..b6a2400fcaa9 100644
--- a/drivers/mtd/hyperbus/hbmc-am654.c
+++ b/drivers/mtd/hyperbus/hbmc-am654.c
@@ -13,7 +13,6 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
 #include <linux/types.h>
 
 #define AM654_HBMC_CALIB_COUNT 25
@@ -89,13 +88,6 @@ static int am654_hbmc_probe(struct platform_device *pdev)
 		priv->mux_ctrl = control;
 	}
 
-	pm_runtime_enable(dev);
-	ret = pm_runtime_get_sync(dev);
-	if (ret < 0) {
-		pm_runtime_put_noidle(dev);
-		goto disable_pm;
-	}
-
 	priv->hbdev.map.size = resource_size(&res);
 	priv->hbdev.map.virt = devm_ioremap_resource(dev, &res);
 	if (IS_ERR(priv->hbdev.map.virt))
@@ -107,13 +99,11 @@ static int am654_hbmc_probe(struct platform_device *pdev)
 	ret = hyperbus_register_device(&priv->hbdev);
 	if (ret) {
 		dev_err(dev, "failed to register controller\n");
-		pm_runtime_put_sync(&pdev->dev);
-		goto disable_pm;
+		goto disable_mux;
 	}
 
 	return 0;
-disable_pm:
-	pm_runtime_disable(dev);
+disable_mux:
 	if (priv->mux_ctrl)
 		mux_control_deselect(priv->mux_ctrl);
 	return ret;
@@ -127,8 +117,6 @@ static int am654_hbmc_remove(struct platform_device *pdev)
 	ret = hyperbus_unregister_device(&priv->hbdev);
 	if (priv->mux_ctrl)
 		mux_control_deselect(priv->mux_ctrl);
-	pm_runtime_put_sync(&pdev->dev);
-	pm_runtime_disable(&pdev->dev);
 
 	return ret;
 }
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] mtd: hyperbus: hbmc-am654: Add DMA support for reads
  2020-09-17  7:47 [PATCH 0/4] mtd: hyperbus: hbmc-am654: Add DMA support Vignesh Raghavendra
                   ` (2 preceding siblings ...)
  2020-09-17  7:47 ` [PATCH 3/4] mtd: hyperbus: hbmc-am654: Drop pm_runtime* calls from probe Vignesh Raghavendra
@ 2020-09-17  7:47 ` Vignesh Raghavendra
  3 siblings, 0 replies; 5+ messages in thread
From: Vignesh Raghavendra @ 2020-09-17  7:47 UTC (permalink / raw)
  To: Vignesh Raghavendra
  Cc: Miquel Raynal, Richard Weinberger, Sergei Shtylyov, linux-mtd,
	linux-kernel

AM654 HyperBus controller provides MMIO interface to read data from
flash. So add DMA memcpy support for reading data over MMIO interface.
This provides 5x improvement in throughput and reduces CPU usage as
well.

Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
---
 drivers/mtd/hyperbus/hbmc-am654.c | 130 +++++++++++++++++++++++++++++-
 1 file changed, 129 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/hyperbus/hbmc-am654.c b/drivers/mtd/hyperbus/hbmc-am654.c
index b6a2400fcaa9..b6ab55560089 100644
--- a/drivers/mtd/hyperbus/hbmc-am654.c
+++ b/drivers/mtd/hyperbus/hbmc-am654.c
@@ -3,6 +3,10 @@
 // Copyright (C) 2019 Texas Instruments Incorporated - https://www.ti.com/
 // Author: Vignesh Raghavendra <vigneshr@ti.com>
 
+#include <linux/completion.h>
+#include <linux/dma-direction.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -13,10 +17,18 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
+#include <linux/sched/task_stack.h>
 #include <linux/types.h>
 
 #define AM654_HBMC_CALIB_COUNT 25
 
+struct am654_hbmc_device_priv {
+	struct completion rx_dma_complete;
+	phys_addr_t device_base;
+	struct hyperbus_ctlr *ctlr;
+	struct dma_chan *rx_chan;
+};
+
 struct am654_hbmc_priv {
 	struct hyperbus_ctlr ctlr;
 	struct hyperbus_device hbdev;
@@ -51,13 +63,107 @@ static int am654_hbmc_calibrate(struct hyperbus_device *hbdev)
 	return ret;
 }
 
+static void am654_hbmc_dma_callback(void *param)
+{
+	struct am654_hbmc_device_priv *priv = param;
+
+	complete(&priv->rx_dma_complete);
+}
+
+static int am654_hbmc_dma_read(struct am654_hbmc_device_priv *priv, void *to,
+			       unsigned long from, ssize_t len)
+
+{
+	enum dma_ctrl_flags flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+	struct dma_chan *rx_chan = priv->rx_chan;
+	struct dma_async_tx_descriptor *tx;
+	dma_addr_t dma_dst, dma_src;
+	dma_cookie_t cookie;
+	int ret;
+
+	if (!priv->rx_chan || !virt_addr_valid(to) || object_is_on_stack(to))
+		return -EINVAL;
+
+	dma_dst = dma_map_single(rx_chan->device->dev, to, len, DMA_FROM_DEVICE);
+	if (dma_mapping_error(rx_chan->device->dev, dma_dst)) {
+		dev_dbg(priv->ctlr->dev, "DMA mapping failed\n");
+		return -EIO;
+	}
+
+	dma_src = priv->device_base + from;
+	tx = dmaengine_prep_dma_memcpy(rx_chan, dma_dst, dma_src, len, flags);
+	if (!tx) {
+		dev_err(priv->ctlr->dev, "device_prep_dma_memcpy error\n");
+		ret = -EIO;
+		goto unmap_dma;
+	}
+
+	reinit_completion(&priv->rx_dma_complete);
+	tx->callback = am654_hbmc_dma_callback;
+	tx->callback_param = priv;
+	cookie = tx->tx_submit(tx);
+
+	ret = dma_submit_error(cookie);
+	if (ret) {
+		dev_err(priv->ctlr->dev, "dma_submit_error %d\n", cookie);
+		ret = -EIO;
+		goto unmap_dma;
+	}
+
+	dma_async_issue_pending(rx_chan);
+	ret = wait_for_completion_timeout(&priv->rx_dma_complete,
+					  msecs_to_jiffies(len + 1000));
+	if (ret <= 0) {
+		dmaengine_terminate_sync(rx_chan);
+		dev_err(priv->ctlr->dev, "DMA wait_for_completion_timeout\n");
+		ret = -ETIMEDOUT;
+		goto unmap_dma;
+	}
+	ret = 0;
+
+unmap_dma:
+	dma_unmap_single(rx_chan->device->dev, dma_dst, len, DMA_FROM_DEVICE);
+	return ret;
+}
+
+static void am654_hbmc_read(struct hyperbus_device *hbdev, void *to,
+			    unsigned long from, ssize_t len)
+{
+	struct am654_hbmc_device_priv *priv = hbdev->priv;
+
+	if (len < SZ_1K || am654_hbmc_dma_read(priv, to, from, len))
+		memcpy_fromio(to, hbdev->map.virt + from, len);
+}
+
 static const struct hyperbus_ops am654_hbmc_ops = {
 	.calibrate = am654_hbmc_calibrate,
+	.copy_from = am654_hbmc_read,
 };
 
+static int am654_hbmc_request_mmap_dma(struct am654_hbmc_device_priv *priv)
+{
+	struct dma_chan *rx_chan;
+	dma_cap_mask_t mask;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_MEMCPY, mask);
+
+	rx_chan = dma_request_chan_by_mask(&mask);
+	if (IS_ERR(rx_chan)) {
+		if (PTR_ERR(rx_chan) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		return 0;
+	}
+	priv->rx_chan = rx_chan;
+	init_completion(&priv->rx_dma_complete);
+
+	return 0;
+}
+
 static int am654_hbmc_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
+	struct am654_hbmc_device_priv *dev_priv;
 	struct device *dev = &pdev->dev;
 	struct am654_hbmc_priv *priv;
 	struct resource res;
@@ -96,13 +202,31 @@ static int am654_hbmc_probe(struct platform_device *pdev)
 	priv->ctlr.dev = dev;
 	priv->ctlr.ops = &am654_hbmc_ops;
 	priv->hbdev.ctlr = &priv->ctlr;
+
+	dev_priv = devm_kzalloc(dev, sizeof(*dev_priv), GFP_KERNEL);
+	if (!dev_priv) {
+		ret = -ENOMEM;
+		goto disable_mux;
+	}
+
+	priv->hbdev.priv = dev_priv;
+	dev_priv->device_base = res.start;
+	dev_priv->ctlr = &priv->ctlr;
+
+	ret = am654_hbmc_request_mmap_dma(dev_priv);
+	if (ret == -EPROBE_DEFER)
+		goto disable_mux;
+
 	ret = hyperbus_register_device(&priv->hbdev);
 	if (ret) {
 		dev_err(dev, "failed to register controller\n");
-		goto disable_mux;
+		goto release_dma;
 	}
 
 	return 0;
+release_dma:
+	if (dev_priv->rx_chan)
+		dma_release_channel(dev_priv->rx_chan);
 disable_mux:
 	if (priv->mux_ctrl)
 		mux_control_deselect(priv->mux_ctrl);
@@ -112,12 +236,16 @@ static int am654_hbmc_probe(struct platform_device *pdev)
 static int am654_hbmc_remove(struct platform_device *pdev)
 {
 	struct am654_hbmc_priv *priv = platform_get_drvdata(pdev);
+	struct am654_hbmc_device_priv *dev_priv = priv->hbdev.priv;
 	int ret;
 
 	ret = hyperbus_unregister_device(&priv->hbdev);
 	if (priv->mux_ctrl)
 		mux_control_deselect(priv->mux_ctrl);
 
+	if (dev_priv->rx_chan)
+		dma_release_channel(dev_priv->rx_chan);
+
 	return ret;
 }
 
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-09-17  9:33 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-17  7:47 [PATCH 0/4] mtd: hyperbus: hbmc-am654: Add DMA support Vignesh Raghavendra
2020-09-17  7:47 ` [PATCH 1/4] mtd: hyperbus: Provide per device private pointer Vignesh Raghavendra
2020-09-17  7:47 ` [PATCH 2/4] mtd: hyperbus: hbmc-am654: Fix direct mapping setup flash access Vignesh Raghavendra
2020-09-17  7:47 ` [PATCH 3/4] mtd: hyperbus: hbmc-am654: Drop pm_runtime* calls from probe Vignesh Raghavendra
2020-09-17  7:47 ` [PATCH 4/4] mtd: hyperbus: hbmc-am654: Add DMA support for reads Vignesh Raghavendra

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