Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] Improve DMA chaining for ahash requests
From: Romain Perier @ 2016-10-03 15:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003151739.11615-1-romain.perier@free-electrons.com>

Hello,

Le 03/10/2016 17:17, Romain Perier a ?crit :
> This series contain performance improvement regarding ahash requests.
> So far, ahash requests were systematically not chained at the DMA level.
> However, in some case, like this is the case by using IPSec, some ahash
> requests can be processed directly by the engine, and don't have
> intermediaire partial update states.
>
> This series firstly re-work the way outer IVs are copied from the SRAM
> into the dma pool. To do so, we introduce a common dma pool for all type
> of requests that contains outer results (like IV or digest). Then, for
> ahash requests that can be processed directly by the engine, outer
> results are copied from the SRAM into the common dma pool. These requests
> are then allowed to be chained at the DMA level.
>
>
> Benchmarking results with iperf throught IPSec
> ==============================================
> 		ESP			AH
>
> Before		343 Mbits/s		492 Mbits/s
> After		392 Mbits/s		557 Mbits/s
> Improvement	+14%			+13%
>
> Romain Perier (2):
>    crypto: marvell - Use an unique pool to copy results of requests
>    crypto: marvell - Don't break chain for computable last ahash requests
>
>   drivers/crypto/marvell/cesa.c   |  4 ---
>   drivers/crypto/marvell/cesa.h   |  5 ++-
>   drivers/crypto/marvell/cipher.c |  6 ++--
>   drivers/crypto/marvell/hash.c   | 79 +++++++++++++++++++++++++++++++++--------
>   drivers/crypto/marvell/tdma.c   | 17 +++++----
>   5 files changed, 78 insertions(+), 33 deletions(-)
>

After an internal discussion, we can handle things differently. Instead 
of allocating a new mv_cesa_op_ctx in the op_pool, we can just allocate 
a new descriptor which points to the first op ctx of the chain, and then 
copy outer data.

Please ignore this series.

Regards,

-- 
Romain Perier, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH v2] drm: tilcdc: add a da850-specific compatible string
From: Bartosz Golaszewski @ 2016-10-03 15:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <12dad169-de04-ce7d-0422-94c57074c839@ti.com>

2016-10-01 11:30 GMT+02:00 Sekhar Nori <nsekhar@ti.com>:
> On Friday 30 September 2016 07:22 PM, Bartosz Golaszewski wrote:
>> Due to some potential tweaks for the da850 LCDC (for example: the
>> required memory bandwith settings) we need a separate compatible
>> for the IP present on the da850 boards.
>>
>
> This documentation does not help much :( It should be on the lines of:
>
> compatible: value should be "ti,am33xx-tilcdc" for AM335x based boards
>             value should be "ti,da850-tilcdc" for DA850/AM18x/OMAP-L138
>             based boards
>
> There are many existing examples of the way compatible strings are
> documented. You can take a look at them too. Also, since you are
> introducing a new device-tree compatible, please keep the devicetree
> list and maintainers in CC too. I don't think it shows up in
> get_maintainer.pl, so you will have to remember to do it.
>

Hi Sekhar,

sorry for that, hope v3 is good.

Thanks,
Bartosz

^ permalink raw reply

* [PATCH v3] drm: tilcdc: add a da850-specific compatible string
From: Bartosz Golaszewski @ 2016-10-03 15:45 UTC (permalink / raw)
  To: linux-arm-kernel

Due to some potential tweaks for the da850 LCDC (for example: the
required memory bandwith settings) we need a separate compatible
for the IP present on the da850 boards.

Suggested-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
v1 -> v2:
- added the new compatible to the bindings documentation

v2 -> v3:
- made the documentation more detailed

 Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt | 6 ++++--
 drivers/gpu/drm/tilcdc/tilcdc_drv.c                         | 1 +
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt b/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt
index a83abd7..6fddb4f 100644
--- a/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt
+++ b/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt
@@ -1,7 +1,9 @@
 Device-Tree bindings for tilcdc DRM driver
 
 Required properties:
- - compatible: value should be "ti,am33xx-tilcdc".
+ - compatible: value should be one of the following:
+    - "ti,am33xx-tilcdc" for AM335x based boards
+    - "ti,da850-tilcdc" for DA850/AM18x/OMAP-L138 based boards
  - interrupts: the interrupt number
  - reg: base address and size of the LCDC device
 
@@ -51,7 +53,7 @@ Optional nodes:
 Example:
 
 	fb: fb at 4830e000 {
-		compatible = "ti,am33xx-tilcdc";
+		compatible = "ti,am33xx-tilcdc", "ti,da850-tilcdc";
 		reg = <0x4830e000 0x1000>;
 		interrupt-parent = <&intc>;
 		interrupts = <36>;
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index a694977..231f2c7 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -723,6 +723,7 @@ static int tilcdc_pdev_remove(struct platform_device *pdev)
 
 static struct of_device_id tilcdc_of_match[] = {
 		{ .compatible = "ti,am33xx-tilcdc", },
+		{ .compatible = "ti,da850-tilcdc", },
 		{ },
 };
 MODULE_DEVICE_TABLE(of, tilcdc_of_match);
-- 
2.9.3

^ permalink raw reply related

* [PATCH v6 1/6] of: Add vendor prefix for Engicam s.r.l company
From: Jagan Teki @ 2016-10-03 15:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAL_JsqL9ewVsWL1HUtPuMHvcSP+nW=d=F3++ibLhOF64xz8YwQ@mail.gmail.com>

On Mon, Oct 3, 2016 at 9:06 PM, Rob Herring <robh@kernel.org> wrote:
> On Mon, Sep 26, 2016 at 2:25 PM, Jagan Teki <jteki@openedev.com> wrote:
>> From: Jagan Teki <jagan@amarulasolutions.com>
>>
>> Engicam providing design services of electronic systems with
>> high content of technology, relying on a long experience in
>> electronic design.
>>
>> For more info visit
>> http://www.engicam.com/en/
>>
>> Cc: Sascha Hauer <kernel@pengutronix.de>
>> Cc: Fabio Estevam <fabio.estevam@nxp.com>
>> Cc: Shawn Guo <shawnguo@kernel.org>
>> Cc: Matteo Lisi <matteo.lisi@engicam.com>
>> Cc: Michael Trimarchi <michael@amarulasolutions.com>
>> Acked-by: Rob Herring <robh@kernel.org>
>> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
>
> I've applied this patch to the DT tree to avoid any conflicts with
> sorting vendor-prefixes.txt.

Thanks.

Shawn - can you pick this series.

thanks!
-- 
Jagan Teki
Free Software Engineer | Amarula Solutions
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

^ permalink raw reply

* [PATCH v6 1/6] of: Add vendor prefix for Engicam s.r.l company
From: Rob Herring @ 2016-10-03 15:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1474917937-29336-1-git-send-email-jteki@openedev.com>

On Mon, Sep 26, 2016 at 2:25 PM, Jagan Teki <jteki@openedev.com> wrote:
> From: Jagan Teki <jagan@amarulasolutions.com>
>
> Engicam providing design services of electronic systems with
> high content of technology, relying on a long experience in
> electronic design.
>
> For more info visit
> http://www.engicam.com/en/
>
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: Fabio Estevam <fabio.estevam@nxp.com>
> Cc: Shawn Guo <shawnguo@kernel.org>
> Cc: Matteo Lisi <matteo.lisi@engicam.com>
> Cc: Michael Trimarchi <michael@amarulasolutions.com>
> Acked-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>

I've applied this patch to the DT tree to avoid any conflicts with
sorting vendor-prefixes.txt.

Rob

^ permalink raw reply

* [PATCH v2 2/2] crypto: marvell - Don't break chain for computable last ahash requests
From: Romain Perier @ 2016-10-03 15:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003151739.11615-1-romain.perier@free-electrons.com>

Currently, the driver breaks chain for all kind of hash requests in order to
don't override intermediate states of partial ahash updates. However, some final
ahash requests can be directly processed by the engine, and so without
intermediate state. This is typically the case for most for the HMAC requests
processed via IPSec.

This commits adds a TDMA descriptor to copy outer data for these of requests
into the "op" dma pool, then it allow to chain these requests at the DMA level.
The 'complete' operation is also updated to retrieve the MAC digest from the
right location.

Signed-off-by: Romain Perier <romain.perier@free-electrons.com>
---

Changes in v2:
 - Replaced BUG_ON by an error
 - Add a variable "break_chain", with "type" to break the chain
   with ahash requests. It improves code readability.

 drivers/crypto/marvell/cipher.c | 10 +++---
 drivers/crypto/marvell/hash.c   | 79 +++++++++++++++++++++++++++++++++--------
 drivers/crypto/marvell/tdma.c   |  4 +--
 3 files changed, 71 insertions(+), 22 deletions(-)

diff --git a/drivers/crypto/marvell/cipher.c b/drivers/crypto/marvell/cipher.c
index 098871a..8bc52bf 100644
--- a/drivers/crypto/marvell/cipher.c
+++ b/drivers/crypto/marvell/cipher.c
@@ -212,8 +212,7 @@ mv_cesa_ablkcipher_complete(struct crypto_async_request *req)
 		struct mv_cesa_req *basereq;
 
 		basereq = &creq->base;
-		memcpy(ablkreq->info, basereq->chain.last->op->ctx.blkcipher.iv,
-		       ivsize);
+		memcpy(ablkreq->info, basereq->chain.last->data, ivsize);
 	} else {
 		memcpy_fromio(ablkreq->info,
 			      engine->sram + CESA_SA_CRYPT_IV_SRAM_OFFSET,
@@ -374,9 +373,10 @@ static int mv_cesa_ablkcipher_dma_req_init(struct ablkcipher_request *req,
 
 	/* Add output data for IV */
 	ivsize = crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(req));
-	ret = mv_cesa_dma_add_result_op(&basereq->chain, CESA_SA_CFG_SRAM_OFFSET,
-				    CESA_SA_DATA_SRAM_OFFSET,
-				    CESA_TDMA_SRC_IN_SRAM, flags);
+	ret = mv_cesa_dma_add_result_op(&basereq->chain,
+					CESA_SA_CRYPT_IV_SRAM_OFFSET,
+					ivsize,
+					CESA_TDMA_SRC_IN_SRAM, flags);
 
 	if (ret)
 		goto err_free_tdma;
diff --git a/drivers/crypto/marvell/hash.c b/drivers/crypto/marvell/hash.c
index 9f28468..35baf4f 100644
--- a/drivers/crypto/marvell/hash.c
+++ b/drivers/crypto/marvell/hash.c
@@ -312,24 +312,53 @@ static void mv_cesa_ahash_complete(struct crypto_async_request *req)
 	int i;
 
 	digsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(ahashreq));
-	for (i = 0; i < digsize / 4; i++)
-		creq->state[i] = readl_relaxed(engine->regs + CESA_IVDIG(i));
 
-	if (creq->last_req) {
+	if (mv_cesa_req_get_type(&creq->base) == CESA_DMA_REQ &&
+	    !(creq->base.chain.last->flags & CESA_TDMA_BREAK_CHAIN)) {
+		struct mv_cesa_tdma_desc *tdma = NULL;
+		__le32 *data = NULL;
+
+		for (tdma = creq->base.chain.first; tdma; tdma = tdma->next) {
+			u32 type = tdma->flags & CESA_TDMA_TYPE_MSK;
+			if (type ==  CESA_TDMA_RESULT)
+				break;
+		}
+
+		if (!tdma) {
+			dev_err(cesa_dev->dev, "Failed to retrieve tdma "
+					       "descriptor for outer data\n");
+			return;
+		}
+
 		/*
-		 * Hardware's MD5 digest is in little endian format, but
-		 * SHA in big endian format
+		 * Result is already in the correct endianess when the SA is
+		 * used
 		 */
-		if (creq->algo_le) {
-			__le32 *result = (void *)ahashreq->result;
+		data = tdma->data;
+		for (i = 0; i < digsize / 4; i++)
+			creq->state[i] = cpu_to_le32(data[i]);
 
-			for (i = 0; i < digsize / 4; i++)
-				result[i] = cpu_to_le32(creq->state[i]);
-		} else {
-			__be32 *result = (void *)ahashreq->result;
+		memcpy(ahashreq->result, data, digsize);
+	} else {
+		for (i = 0; i < digsize / 4; i++)
+			creq->state[i] = readl_relaxed(engine->regs +
+						       CESA_IVDIG(i));
+		if (creq->last_req) {
+			/*
+			* Hardware's MD5 digest is in little endian format, but
+			* SHA in big endian format
+			*/
+			if (creq->algo_le) {
+				__le32 *result = (void *)ahashreq->result;
+
+				for (i = 0; i < digsize / 4; i++)
+					result[i] = cpu_to_le32(creq->state[i]);
+			} else {
+				__be32 *result = (void *)ahashreq->result;
 
-			for (i = 0; i < digsize / 4; i++)
-				result[i] = cpu_to_be32(creq->state[i]);
+				for (i = 0; i < digsize / 4; i++)
+					result[i] = cpu_to_be32(creq->state[i]);
+			}
 		}
 	}
 
@@ -504,6 +533,12 @@ mv_cesa_ahash_dma_last_req(struct mv_cesa_tdma_chain *chain,
 						CESA_SA_DESC_CFG_LAST_FRAG,
 				      CESA_SA_DESC_CFG_FRAG_MSK);
 
+		ret = mv_cesa_dma_add_result_op(chain,
+						CESA_SA_MAC_DIG_SRAM_OFFSET,
+						32,
+						CESA_TDMA_SRC_IN_SRAM, flags);
+		if (ret)
+			return ERR_PTR(-ENOMEM);
 		return op;
 	}
 
@@ -564,6 +599,8 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
 	struct mv_cesa_op_ctx *op = NULL;
 	unsigned int frag_len;
 	int ret;
+	u32 type;
+	bool break_chain = true;
 
 	basereq->chain.first = NULL;
 	basereq->chain.last = NULL;
@@ -635,6 +672,16 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
 		goto err_free_tdma;
 	}
 
+	/*
+	 * If results are copied via DMA, this means that this
+	 * request can be directly processed by the engine,
+	 * without partial updates. So we can chain it at the
+	 * DMA level with other requests.
+	 */
+	type = basereq->chain.last->flags & CESA_TDMA_TYPE_MSK;
+	if (type == CESA_TDMA_RESULT)
+		break_chain = false;
+
 	if (op) {
 		/* Add dummy desc to wait for crypto operation end */
 		ret = mv_cesa_dma_add_dummy_end(&basereq->chain, flags);
@@ -648,8 +695,10 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
 	else
 		creq->cache_ptr = 0;
 
-	basereq->chain.last->flags |= (CESA_TDMA_END_OF_REQ |
-				       CESA_TDMA_BREAK_CHAIN);
+	basereq->chain.last->flags |= CESA_TDMA_END_OF_REQ;
+
+	if (break_chain)
+		basereq->chain.last->flags |= CESA_TDMA_BREAK_CHAIN;
 
 	return 0;
 
diff --git a/drivers/crypto/marvell/tdma.c b/drivers/crypto/marvell/tdma.c
index 2e15f19..8d33003 100644
--- a/drivers/crypto/marvell/tdma.c
+++ b/drivers/crypto/marvell/tdma.c
@@ -70,7 +70,7 @@ void mv_cesa_dma_cleanup(struct mv_cesa_req *dreq)
 			dma_pool_free(cesa_dev->dma->op_pool, tdma->op,
 				      le32_to_cpu(tdma->src));
 		else if (type == CESA_TDMA_RESULT)
-			dma_pool_free(cesa_dev->dma->op_pool, tdma->op,
+			dma_pool_free(cesa_dev->dma->op_pool, tdma->data,
 				      le32_to_cpu(tdma->dst));
 
 		tdma = tdma->next;
@@ -227,7 +227,7 @@ int mv_cesa_dma_add_result_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
 	tdma->byte_cnt = cpu_to_le32(size | BIT(31));
 	tdma->src = src;
 	tdma->dst = cpu_to_le32(dma_handle);
-	tdma->op = result;
+	tdma->data = result;
 
 	flags &= (CESA_TDMA_DST_IN_SRAM | CESA_TDMA_SRC_IN_SRAM);
 	tdma->flags = flags | CESA_TDMA_RESULT;
-- 
2.9.3

^ permalink raw reply related

* [PATCH v2 1/2] crypto: marvell - Use an unique pool to copy results of requests
From: Romain Perier @ 2016-10-03 15:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003151739.11615-1-romain.perier@free-electrons.com>

So far, we used a dedicated dma pool to copy the result of outer IV for
cipher requests. Instead of using a dma pool per outer data, we prefer
use the op dma pool that contains all part of the request from the SRAM.
Then, the outer data that is likely to be used by the 'complete'
operation, is copied later. In this way, any type of result can be
retrieved by DMA for cipher or ahash requests.

Signed-off-by: Romain Perier <romain.perier@free-electrons.com>
---

Changes in v2:
  - Use the dma pool "op" to retrieve outer data intead of introducing
    a new one.

 drivers/crypto/marvell/cesa.c   |  4 ----
 drivers/crypto/marvell/cesa.h   |  5 ++---
 drivers/crypto/marvell/cipher.c |  8 +++++---
 drivers/crypto/marvell/tdma.c   | 17 ++++++++---------
 4 files changed, 15 insertions(+), 19 deletions(-)

diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c
index 37dadb2..6e7a5c7 100644
--- a/drivers/crypto/marvell/cesa.c
+++ b/drivers/crypto/marvell/cesa.c
@@ -375,10 +375,6 @@ static int mv_cesa_dev_dma_init(struct mv_cesa_dev *cesa)
 	if (!dma->padding_pool)
 		return -ENOMEM;
 
-	dma->iv_pool = dmam_pool_create("cesa_iv", dev, 16, 1, 0);
-	if (!dma->iv_pool)
-		return -ENOMEM;
-
 	cesa->dma = dma;
 
 	return 0;
diff --git a/drivers/crypto/marvell/cesa.h b/drivers/crypto/marvell/cesa.h
index e423d33..a768da7 100644
--- a/drivers/crypto/marvell/cesa.h
+++ b/drivers/crypto/marvell/cesa.h
@@ -277,7 +277,7 @@ struct mv_cesa_op_ctx {
 #define CESA_TDMA_DUMMY				0
 #define CESA_TDMA_DATA				1
 #define CESA_TDMA_OP				2
-#define CESA_TDMA_IV				3
+#define CESA_TDMA_RESULT			3
 
 /**
  * struct mv_cesa_tdma_desc - TDMA descriptor
@@ -393,7 +393,6 @@ struct mv_cesa_dev_dma {
 	struct dma_pool *op_pool;
 	struct dma_pool *cache_pool;
 	struct dma_pool *padding_pool;
-	struct dma_pool *iv_pool;
 };
 
 /**
@@ -839,7 +838,7 @@ mv_cesa_tdma_desc_iter_init(struct mv_cesa_tdma_chain *chain)
 	memset(chain, 0, sizeof(*chain));
 }
 
-int mv_cesa_dma_add_iv_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
+int mv_cesa_dma_add_result_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
 			  u32 size, u32 flags, gfp_t gfp_flags);
 
 struct mv_cesa_op_ctx *mv_cesa_dma_add_op(struct mv_cesa_tdma_chain *chain,
diff --git a/drivers/crypto/marvell/cipher.c b/drivers/crypto/marvell/cipher.c
index d19dc96..098871a 100644
--- a/drivers/crypto/marvell/cipher.c
+++ b/drivers/crypto/marvell/cipher.c
@@ -212,7 +212,8 @@ mv_cesa_ablkcipher_complete(struct crypto_async_request *req)
 		struct mv_cesa_req *basereq;
 
 		basereq = &creq->base;
-		memcpy(ablkreq->info, basereq->chain.last->data, ivsize);
+		memcpy(ablkreq->info, basereq->chain.last->op->ctx.blkcipher.iv,
+		       ivsize);
 	} else {
 		memcpy_fromio(ablkreq->info,
 			      engine->sram + CESA_SA_CRYPT_IV_SRAM_OFFSET,
@@ -373,8 +374,9 @@ static int mv_cesa_ablkcipher_dma_req_init(struct ablkcipher_request *req,
 
 	/* Add output data for IV */
 	ivsize = crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(req));
-	ret = mv_cesa_dma_add_iv_op(&basereq->chain, CESA_SA_CRYPT_IV_SRAM_OFFSET,
-				    ivsize, CESA_TDMA_SRC_IN_SRAM, flags);
+	ret = mv_cesa_dma_add_result_op(&basereq->chain, CESA_SA_CFG_SRAM_OFFSET,
+				    CESA_SA_DATA_SRAM_OFFSET,
+				    CESA_TDMA_SRC_IN_SRAM, flags);
 
 	if (ret)
 		goto err_free_tdma;
diff --git a/drivers/crypto/marvell/tdma.c b/drivers/crypto/marvell/tdma.c
index 9fd7a5f..2e15f19 100644
--- a/drivers/crypto/marvell/tdma.c
+++ b/drivers/crypto/marvell/tdma.c
@@ -69,8 +69,8 @@ void mv_cesa_dma_cleanup(struct mv_cesa_req *dreq)
 		if (type == CESA_TDMA_OP)
 			dma_pool_free(cesa_dev->dma->op_pool, tdma->op,
 				      le32_to_cpu(tdma->src));
-		else if (type == CESA_TDMA_IV)
-			dma_pool_free(cesa_dev->dma->iv_pool, tdma->data,
+		else if (type == CESA_TDMA_RESULT)
+			dma_pool_free(cesa_dev->dma->op_pool, tdma->op,
 				      le32_to_cpu(tdma->dst));
 
 		tdma = tdma->next;
@@ -209,29 +209,28 @@ mv_cesa_dma_add_desc(struct mv_cesa_tdma_chain *chain, gfp_t flags)
 	return new_tdma;
 }
 
-int mv_cesa_dma_add_iv_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
+int mv_cesa_dma_add_result_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
 			  u32 size, u32 flags, gfp_t gfp_flags)
 {
-
 	struct mv_cesa_tdma_desc *tdma;
-	u8 *iv;
+	struct mv_cesa_op_ctx *result;
 	dma_addr_t dma_handle;
 
 	tdma = mv_cesa_dma_add_desc(chain, gfp_flags);
 	if (IS_ERR(tdma))
 		return PTR_ERR(tdma);
 
-	iv = dma_pool_alloc(cesa_dev->dma->iv_pool, gfp_flags, &dma_handle);
-	if (!iv)
+	result = dma_pool_alloc(cesa_dev->dma->op_pool, gfp_flags, &dma_handle);
+	if (!result)
 		return -ENOMEM;
 
 	tdma->byte_cnt = cpu_to_le32(size | BIT(31));
 	tdma->src = src;
 	tdma->dst = cpu_to_le32(dma_handle);
-	tdma->data = iv;
+	tdma->op = result;
 
 	flags &= (CESA_TDMA_DST_IN_SRAM | CESA_TDMA_SRC_IN_SRAM);
-	tdma->flags = flags | CESA_TDMA_IV;
+	tdma->flags = flags | CESA_TDMA_RESULT;
 	return 0;
 }
 
-- 
2.9.3

^ permalink raw reply related

* [PATCH v2 0/2] Improve DMA chaining for ahash requests
From: Romain Perier @ 2016-10-03 15:17 UTC (permalink / raw)
  To: linux-arm-kernel

This series contain performance improvement regarding ahash requests.
So far, ahash requests were systematically not chained at the DMA level.
However, in some case, like this is the case by using IPSec, some ahash
requests can be processed directly by the engine, and don't have
intermediaire partial update states.

This series firstly re-work the way outer IVs are copied from the SRAM
into the dma pool. To do so, we introduce a common dma pool for all type
of requests that contains outer results (like IV or digest). Then, for
ahash requests that can be processed directly by the engine, outer
results are copied from the SRAM into the common dma pool. These requests
are then allowed to be chained at the DMA level.


Benchmarking results with iperf throught IPSec
==============================================
		ESP			AH

Before		343 Mbits/s		492 Mbits/s
After		392 Mbits/s		557 Mbits/s
Improvement	+14%			+13%

Romain Perier (2):
  crypto: marvell - Use an unique pool to copy results of requests
  crypto: marvell - Don't break chain for computable last ahash requests

 drivers/crypto/marvell/cesa.c   |  4 ---
 drivers/crypto/marvell/cesa.h   |  5 ++-
 drivers/crypto/marvell/cipher.c |  6 ++--
 drivers/crypto/marvell/hash.c   | 79 +++++++++++++++++++++++++++++++++--------
 drivers/crypto/marvell/tdma.c   | 17 +++++----
 5 files changed, 78 insertions(+), 33 deletions(-)

-- 
2.9.3

^ permalink raw reply

* Tegra baseline test results for v4.8
From: Jon Hunter @ 2016-10-03 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

Here are some basic Tegra test results for Linux v4.8.
Logs and other details at:

    https://nvtb.github.io//linux/test_v4.8/20161002170103/


Test summary
------------

Build: zImage:
    Pass: ( 2/ 2): multi_v7_defconfig, tegra_defconfig

Build: Image:
    Pass: ( 1/ 1): defconfig

Boot to userspace: defconfig:
    Pass: ( 4/ 4): qemu-vexpress64, tegra132-norrin,
		   tegra210-p2371-0000, tegra210-smaug

Boot to userspace: multi_v7_defconfig:
    Pass: ( 5/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra124-nyan-big, tegra20-trimslice, tegra30-beaver

Boot to userspace: tegra_defconfig:
    Pass: ( 5/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra124-nyan-big, tegra20-trimslice, tegra30-beaver

PM: System suspend: multi_v7_defconfig:
    Pass: ( 5/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra124-nyan-big, tegra20-trimslice, tegra30-beaver

PM: System suspend: tegra_defconfig:
    Pass: ( 5/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra124-nyan-big, tegra20-trimslice, tegra30-beaver


vmlinux object size
(delta in bytes from test_v4.8-rc8 (08895a8b6b06ed2323cd97a36ee40a116b3db8ed)):
   text     data      bss    total  kernel
     +4        0        0       +4  defconfig
   +156        0        0     +156  multi_v7_defconfig
   +220        0        0     +220  tegra_defconfig


Boot-time memory difference
(delta in bytes from test_v4.8-rc8 (08895a8b6b06ed2323cd97a36ee40a116b3db8ed))
    avail    rsrvd     high    freed                board              kconfig                  dtb
        .        .        .        .      qemu-vexpress64            defconfig           __internal
        .        .        .        . tegra114-dalmore-a04   multi_v7_defconfig     tegra114-dalmore
        .        .        .        . tegra114-dalmore-a04      tegra_defconfig     tegra114-dalmore
        .        .        .        .  tegra124-jetson-tk1   multi_v7_defconfig  tegra124-jetson-tk1
        .        .        .        .  tegra124-jetson-tk1      tegra_defconfig  tegra124-jetson-tk1
        .        .        .        .    tegra124-nyan-big   multi_v7_defconfig    tegra124-nyan-big
        .        .        .        .    tegra124-nyan-big      tegra_defconfig    tegra124-nyan-big
        .        .        .        .      tegra132-norrin            defconfig      tegra132-norrin
        .        .        .        .    tegra20-trimslice   multi_v7_defconfig    tegra20-trimslice
        .        .        .        .    tegra20-trimslice      tegra_defconfig    tegra20-trimslice
        .        .        .        .  tegra210-p2371-0000            defconfig  tegra210-p2371-0000
        .        .        .        .       tegra210-smaug            defconfig       tegra210-smaug
        .        .        .        .       tegra30-beaver   multi_v7_defconfig       tegra30-beaver
        .        .        .        .       tegra30-beaver      tegra_defconfig       tegra30-beaver

--
nvpublic

^ permalink raw reply

* Tegra baseline test results for v4.8-rc8
From: Jon Hunter @ 2016-10-03 14:57 UTC (permalink / raw)
  To: linux-arm-kernel

Here are some basic Tegra test results for Linux v4.8-rc8.
Logs and other details at:

    https://nvtb.github.io//linux/test_v4.8-rc8/20160925190103/


Test summary
------------

Build: zImage:
    Pass: ( 2/ 2): multi_v7_defconfig, tegra_defconfig

Build: Image:
    Pass: ( 1/ 1): defconfig

Boot to userspace: defconfig:
    Pass: ( 4/ 4): qemu-vexpress64, tegra132-norrin,
		   tegra210-p2371-0000, tegra210-smaug

Boot to userspace: multi_v7_defconfig:
    Pass: ( 5/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra124-nyan-big, tegra20-trimslice, tegra30-beaver

Boot to userspace: tegra_defconfig:
    Pass: ( 5/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra124-nyan-big, tegra20-trimslice, tegra30-beaver

PM: System suspend: multi_v7_defconfig:
    Pass: ( 5/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra124-nyan-big, tegra20-trimslice, tegra30-beaver

PM: System suspend: tegra_defconfig:
    Pass: ( 5/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra124-nyan-big, tegra20-trimslice, tegra30-beaver


vmlinux object size
(delta in bytes from test_v4.8-rc7 (3be7988674ab33565700a37b210f502563d932e6)):
   text     data      bss    total  kernel
     -4        0        0       -4  defconfig
   +850        0        0     +850  multi_v7_defconfig
   +534        0        0     +534  tegra_defconfig


Boot-time memory difference
(delta in bytes from test_v4.8-rc7 (3be7988674ab33565700a37b210f502563d932e6))
    avail    rsrvd     high    freed                board              kconfig                  dtb
        .        .        .        .      qemu-vexpress64            defconfig           __internal
        .        .        .        . tegra114-dalmore-a04   multi_v7_defconfig     tegra114-dalmore
        .        .        .        . tegra114-dalmore-a04      tegra_defconfig     tegra114-dalmore
        .        .        .        .  tegra124-jetson-tk1   multi_v7_defconfig  tegra124-jetson-tk1
        .        .        .        .  tegra124-jetson-tk1      tegra_defconfig  tegra124-jetson-tk1
        .        .        .        .    tegra124-nyan-big   multi_v7_defconfig    tegra124-nyan-big
        .        .        .        .    tegra124-nyan-big      tegra_defconfig    tegra124-nyan-big
        .        .        .        .      tegra132-norrin            defconfig      tegra132-norrin
        .        .        .        .    tegra20-trimslice   multi_v7_defconfig    tegra20-trimslice
        .        .        .        .    tegra20-trimslice      tegra_defconfig    tegra20-trimslice
        .        .        .        .  tegra210-p2371-0000            defconfig  tegra210-p2371-0000
        .        .        .        .       tegra210-smaug            defconfig       tegra210-smaug
        .        .        .        .       tegra30-beaver   multi_v7_defconfig       tegra30-beaver
        .        .        .        .       tegra30-beaver      tegra_defconfig       tegra30-beaver

--
nvpublic

^ permalink raw reply

* [PATCH] coresight: tmc: implementing TMC-ETR AUX space API
From: Suzuki K Poulose @ 2016-10-03 14:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1474319674-18172-1-git-send-email-mathieu.poirier@linaro.org>

On 19/09/16 22:14, Mathieu Poirier wrote:
> This patch implements the AUX area interfaces required to
> use the TMC-ETR (configured to work in scatter-gather mode)
> from the Perf sub-system.
>
> Some of this work was inspired from the original implementation
> done by Pratik Patel at CodeAurora.
>

Hi Mathieu,

Thanks for nailing the monster. I have a few comments below on the implementation.

> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> ---
>  drivers/hwtracing/coresight/coresight-tmc-etr.c | 629 +++++++++++++++++++++++-
>  drivers/hwtracing/coresight/coresight-tmc.h     |   1 +
>  2 files changed, 621 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> index 6d7de0309e94..581d6393bb5d 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> @@ -17,10 +17,60 @@
>
>  #include <linux/coresight.h>
>  #include <linux/dma-mapping.h>
> +#include <linux/slab.h>
> +
>  #include "coresight-priv.h"
>  #include "coresight-tmc.h"
>
> -void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
> +/**
> + * struct etr_page - DMA'able and virtual address representation for a page
> + * @daddr:		DMA'able page address returned by dma_map_page()
> + * @vaddr:		Virtual address returned by page_address()
> + */
> +struct etr_page {
> +	dma_addr_t	daddr;
> +	u64		vaddr;
> +};
> +
> +/**
> + * struct cs_etr_buffer - keep track of a recording session' specifics
> + * @dev:		device reference to be used with the DMA API
> + * @tmc:		generic portion of the TMC buffers
> + * @etr_nr_pages:	number of memory pages for the ETR-SG trace storage
> + * @pt_vaddr:		the virtual address of the first page table entry
> + * @page_addr:		quick access to all the pages held in the page table
> + */
> +struct cs_etr_buffers {
> +	struct device		*dev;
> +	struct cs_buffers	tmc;
> +	unsigned int		etr_nr_pages;
> +	void __iomem		*pt_vaddr;
> +	struct etr_page		page_addr[0];
> +};
> +
> +#define TMC_ETR_ENTRIES_PER_PT (PAGE_SIZE / sizeof(u32))
> +
> +/*
> + * Helpers for scatter-gather descriptors.  Descriptors are defined as follow:
> + *
> + * ---Bit31------------Bit4-------Bit1-----Bit0--
> + * |     Address[39:12]    | SBZ |  Entry Type  |
> + * ----------------------------------------------
> + *
> + * Address: Bits [39:12] of a physical page address. Bits [11:0] are
> + *	    always zero.
> + *
> + * Entry type:	b10 - Normal entry
> + *		b11 - Last entry in a page table
> + *		b01 - Last entry
> + */
> +#define TMC_ETR_SG_LST_ENT(phys_pte)	(((phys_pte >> PAGE_SHIFT) << 4) | 0x1)
> +#define TMC_ETR_SG_ENT(phys_pte)	(((phys_pte >> PAGE_SHIFT) << 4) | 0x2)
> +#define TMC_ETR_SG_NXT_TBL(phys_pte)	(((phys_pte >> PAGE_SHIFT) << 4) | 0x3)
> +

Please be aware that on arm64, the PAGE_SIZE can be 16K or 64K. So hard coding
PAGE_SHIFT here might be problematic on those configurations as the ETR page size
is always 4K.

> +#define TMC_ETR_SG_ENT_TO_PG(entry)	((entry >> 4) << PAGE_SHIFT)
> +
> +void tmc_etr_enable_hw_cnt_mem(struct tmc_drvdata *drvdata)
>  {
>  	u32 axictl;
>
> @@ -57,7 +107,47 @@ void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
>  	CS_LOCK(drvdata->base);
>  }
>
> -static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
> +void tmc_etr_enable_hw_sg_mem(struct tmc_drvdata *drvdata)


> +	 * DBAHI Holds the upper eight bits of the 40-bit address used to
> +	 * locate the trace buffer in system memory.
> +	 */
> +	writel_relaxed((drvdata->paddr >> 32) & 0xFF,
> +			drvdata->base + TMC_DBAHI);

I think we should do the same for tmc_etr_enable_hw_cnt_mem().

> @@ -199,7 +290,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, u32 mode)
>  		goto out;
>  	}
>
> -	tmc_etr_enable_hw(drvdata);
> +	tmc_etr_enable_hw_sg_mem(drvdata);
>  out:
>  	spin_unlock_irqrestore(&drvdata->spinlock, flags);
>
> @@ -241,9 +332,528 @@ static void tmc_disable_etr_sink(struct coresight_device *csdev)
>  	dev_info(drvdata->dev, "TMC-ETR disabled\n");
>  }
>
> +/*
> + * The default perf ring buffer size is 32 and 1024 pages for user and kernel
> + * space respectively.  The size of the intermediate SG list is allowed
> + * to match the size of the perf ring buffer but cap it to the default
> + * kernel size.
> + */
> +#define DEFAULT_NR_KERNEL_PAGES	1024
> +static int tmc_get_etr_pages(int nr_pages)

The name could be confusing, as it kind of implies it allocates nr_pages.
It might be worth renaming it to tmc_get_etr_pages_nr ?

> +{
> +	if (nr_pages <= DEFAULT_NR_KERNEL_PAGES)
> +		return nr_pages;
> +
> +	return DEFAULT_NR_KERNEL_PAGES;
> +}
> +
> +/*
> + * Go through all the pages in the SG list and check if @phys_addr
> + * falls within one of those.  If so record the information in
> + * @page and @offset.
> + */
> +static int
> +tmc_get_sg_page_index(struct cs_etr_buffers *etr_buffer,
> +		      u64 phys_addr, u32 *page, u32 *offset)
> +{
> +	int i = 0, pte = 0, nr_pages = etr_buffer->etr_nr_pages;
> +	u32 *page_table_itr = etr_buffer->pt_vaddr;
> +	phys_addr_t phys_page_addr;
> +
> +	/* Circle through all the pages in the SG list */
> +	while (pte < nr_pages) {
> +		phys_page_addr = TMC_ETR_SG_ENT_TO_PG((u64)*page_table_itr);

Could we not find the phys_addr by scanning the etr_pages[].daddr and use the
index to hope through the PageTable links to reach the entry which could have it
and return the offset within that page ?

> +
> +		/* Does @phys_addr falls within this page? */
> +		if (phys_addr >= phys_page_addr &&
> +		    phys_addr < (phys_page_addr + PAGE_SIZE)) {
> +			*page = pte;
> +			*offset = phys_addr - phys_page_addr;
> +			return 0;
> +		}
> +
> +		if (pte == nr_pages - 1) {
> +			/* The last page in the SG list */
> +			pte++;
> +		} else if (i == TMC_ETR_ENTRIES_PER_PT - 1) {
> +			/*
> +			 * The last entry in this page table - get a reference
> +			 * on the next page table and do _not_ increment @pte
> +			 */
> +			page_table_itr = phys_to_virt(phys_page_addr);
> +			i = 0;
> +		} else {
> +			/* A normal page in the SG list */
> +			page_table_itr++;
> +			pte++;
> +			i++;
> +		}
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static void tmc_sg_page_sync(struct cs_etr_buffers *etr_buffer,
> +			     int start_page, u64 to_sync)

nit: to_sync doesn't give a clue on what the unit is ? pages ? bytes ?
could it be u64 size ?

> +{
> +	int i, index;
> +	int pages_to_sync = DIV_ROUND_UP_ULL(to_sync, PAGE_SIZE);
> +	dma_addr_t daddr;
> +	struct device *dev = etr_buffer->dev;
> +
> +	for (i = start_page; i < (start_page + pages_to_sync); i++) {
> +		/* Wrap around the etr page list if need be */
> +		index = i % etr_buffer->etr_nr_pages;
> +		daddr = etr_buffer->page_addr[index].daddr;
> +		dma_sync_single_for_cpu(dev, daddr, PAGE_SIZE, DMA_FROM_DEVICE);
> +	}
> +}
> +

> +static void tmc_free_sg_buffer(struct cs_etr_buffers *etr_buffer, int nr_pages)
> +{
> +	int i = 0, pte = 0;
> +	u32 *page_addr, *page_table_itr;
> +	u32 *page_table_addr = etr_buffer->pt_vaddr;
> +	phys_addr_t phys_page_addr;
> +	dma_addr_t daddr;
> +	struct device *dev = etr_buffer->dev;
> +
> +	if (!page_table_addr)
> +		return;
> +

Please check comments on tmc_alloc_sg_buffer().

> +
> +static int
> +tmc_alloc_sg_buffer(struct cs_etr_buffers *etr_buffer, int cpu, int nr_pages)
> +{
> +	int i = 0, node, pte = 0, ret = 0;
> +	dma_addr_t dma_page_addr;
> +	u32 *page_table_addr, *page_addr;
> +	struct page *page;
> +	struct device *dev = etr_buffer->dev;
> +
> +	if (cpu == -1)
> +		cpu = smp_processor_id();
> +	node = cpu_to_node(cpu);
> +
> +	/* Allocate the first page table */
> +	page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 0);
> +	if (!page)
> +		return -ENOMEM;
> +
> +	page_table_addr = page_address(page);

Would it be simpler to allocate the pages required for the PageTables and track them
separately ? i.e for a given nr_pages, we could easily calculate the number of Table
entries required.

nr_table_pages = (nr_pages << (PAGE_SHIFT - 12)) / (TMC_ETR_ENTRIES_PER_PT - 1);
table_pages = alloc_pages_exact_nid(node, GFP_KERNEL|__GFP_ZERO, nr_table_pages * PAGE_SIZE);

where, PAGE_SHIFT - 12 ( = PAGE_SHIFT_4K) gives the log2 number 4K pages in a system
page.

That way, we can link the pages easily and also free them easily in tmc_free_sg_buffer() without
traversing the page table once again, since we track the ETR pages and the pages for the tables now.
Also the page table initialisation below could be much simpler as we could link the table entries
at one shot.
	
> +	/*
> +	 * Keep track of the first page table, the rest will be chained
> +	 * in the last page table entry.
> +	 */
> +	etr_buffer->pt_vaddr = page_table_addr;
> +
> +	while (pte < nr_pages) {
> +		page = alloc_pages_node(node,
> +					GFP_KERNEL | __GFP_ZERO, 0);
> +		if (!page) {
> +			ret = -ENOMEM;
> +			goto err;
> +		}
> +
> +		page_addr = page_address(page);
> +
> +		if (pte == nr_pages - 1) {
> +			/* The last page in the list */
> +			dma_page_addr = tmc_setup_dma_page(dev, page);
> +			if (dma_page_addr == -EINVAL) {
> +				ret = -EINVAL;
> +				goto err;
> +			}
> +
> +			*page_table_addr = TMC_ETR_SG_LST_ENT(dma_page_addr);
> +
> +			etr_buffer->page_addr[pte].vaddr = (u64)page_addr;
> +			etr_buffer->page_addr[pte].daddr = dma_page_addr;
> +
> +			pte++;
> +		} else if (i == TMC_ETR_ENTRIES_PER_PT - 1) {
> +			/* The last entry in this page table */
> +			*page_table_addr =
> +				TMC_ETR_SG_NXT_TBL(virt_to_phys(page_addr));

Shouldn't this also be a dma_addr_t of the page ? The TMC ETR would use the
address in the table to "read" the page table in this case, while the other
pte entries are used to "write" data to the addresses (for which you correctly
set up the dma address). I don't see why the "read" address should be any different.
The TMC TRM uses PTn_BaseAddr for the page table base, which can be confusing.
But if you see the DBALO which points to the PT0_BaseAddr, it should be clear.

> +			/* Move on to the next page table */
> +			page_table_addr = page_addr;
> +
> +			i = 0;
> +		} else {
> +			/* A normal page in the SG list */
> +			dma_page_addr = tmc_setup_dma_page(dev, page);
> +			if (dma_page_addr == -EINVAL) {
> +				ret = -EINVAL;
> +				goto err;
> +			}
> +
> +			*page_table_addr = TMC_ETR_SG_ENT(dma_page_addr);
> +
> +			etr_buffer->page_addr[pte].vaddr = (u64)page_addr;
> +			etr_buffer->page_addr[pte].daddr = dma_page_addr;
> +
> +			page_table_addr++;

As mentioned above, with a page size other than 4K, we are wasting space here.

> +			pte++;
> +			i++;
> +		}
> +	}
> +
> +	return 0;
> +
> +err:
> +	tmc_free_sg_buffer(etr_buffer, pte);
> +	etr_buffer->pt_vaddr = NULL;
> +	return ret;
> +}
> +
> +static void *tmc_alloc_etr_buffer(struct coresight_device *csdev, int cpu,
> +				  void **pages, int nr_pages, bool overwrite)
> +{
> +	int etr_pages, node;
> +	struct device *dev = csdev->dev.parent;
> +	struct cs_etr_buffers *buf;
> +
> +	if (cpu == -1)
> +		cpu = smp_processor_id();
> +	node = cpu_to_node(cpu);
> +
> +	/* Register DBALO and DBAHI form a 40-bit address range */
> +	if (dma_set_mask(dev, DMA_BIT_MASK(40)))
> +		return NULL;
> +
> +	/*
> +	 * The HW can't start collecting data in the middle of the SG list,
> +	 * it must start at the beginning.  As such we can't use the ring
> +	 * buffer provided by perf as entries into the page tables since
> +	 * it is not guaranteed that user space will have the chance to
> +	 * consume the data before the next trace run begins.
> +	 *
> +	 * To work around this reserve a set of pages that will be used as
> +	 * and intermediate (SG) buffer.  This isn't optimal but the best we
> +	 * can do with the current HW revision.

Just for my understanding, is this because we don't get a notification from
the hardware when the buffers are (getting) full ?

> +	 */
> +	etr_pages = tmc_get_etr_pages(nr_pages);

nit: As mentioned above the function name and the variable name etr_pages could be
confusing. How about renaming the variable to nr_etr_pages ?

> +static int tmc_set_etr_buffer(struct coresight_device *csdev,
> +			      struct perf_output_handle *handle,
> +			      void *sink_config)
> +{
> +	unsigned long head;
> +	struct cs_etr_buffers *buf = sink_config;
> +	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +
> +	/* wrap head around to the amount of space we have */
> +	head = handle->head & ((buf->tmc.nr_pages << PAGE_SHIFT) - 1);
> +
> +	/* find the page to write to */
> +	buf->tmc.cur = head / PAGE_SIZE;
> +
> +	/* and offset within that page */
> +	buf->tmc.offset = head % PAGE_SIZE;
> +
> +	local_set(&buf->tmc.data_size, 0);
> +
> +	/* Keep track of how big the internal SG list is */
> +	drvdata->size = buf->etr_nr_pages << PAGE_SHIFT;
> +
> +	/* Tell the HW where to put the trace data */
> +	drvdata->paddr = virt_to_phys(buf->pt_vaddr);

Shouldn't this be a dma_addr as we used to program in the normal mode ?

> +
> +	return 0;
> +}
> +
> +static unsigned long tmc_reset_etr_buffer(struct coresight_device *csdev,
> +					  struct perf_output_handle *handle,
> +					  void *sink_config, bool *lost)
> +{
> +	long size = 0;
> +	struct cs_etr_buffers *buf = sink_config;
> +	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +
> +	if (buf) {
> +		/*
> +		 * In snapshot mode ->data_size holds the new address of the
> +		 * ring buffer's head.  The size itself is the whole address
> +		 * range since we want the latest information.
> +		 */
> +		if (buf->tmc.snapshot) {
> +			size = buf->tmc.nr_pages << PAGE_SHIFT;
> +			handle->head = local_xchg(&buf->tmc.data_size, size);
> +		}
> +
> +		/*
> +		 * Tell the tracer PMU how much we got in this run and if
> +		 * something went wrong along the way.  Nobody else can use
> +		 * this cs_etr_buffers instance until we are done.  As such
> +		 * resetting parameters here and squaring off with the ring
> +		 * buffer API in the tracer PMU is fine.
> +		 */
> +		*lost = !!local_xchg(&buf->tmc.lost, 0);
> +		size = local_xchg(&buf->tmc.data_size, 0);

I don't fully understand the cs_buffer API, but we set the data_size to 0, unconditionally here.
Whats the point of setting the data_size above for snapshot mode ?

> +	}
> +
> +	/* Get ready for another run */
> +	drvdata->vaddr = NULL;
> +	drvdata->paddr = 0;
> +
> +	return size;
> +}
> +
> +static void tmc_update_etr_buffer(struct coresight_device *csdev,
> +				  struct perf_output_handle *handle,
> +				  void *sink_config)
> +{
> +	bool full;
> +	int i, rb_index, sg_index = 0;
> +	u32 rwplo, rwphi, rb_offset, sg_offset = 0;
> +	u32 stop_index, stop_offset, to_copy, sg_size;
> +	u32 *rb_ptr, *sg_ptr;
> +	u64 rwp, to_read;
> +	struct cs_etr_buffers *etr_buf = sink_config;
> +	struct cs_buffers *cs_buf = &etr_buf->tmc;
> +	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +
> +	if (!etr_buf)
> +		return;
> +
> +	/* This shouldn't happen */
> +	if (WARN_ON_ONCE(local_read(&drvdata->mode) != CS_MODE_PERF))
> +		return;
> +
> +	CS_UNLOCK(drvdata->base);
> +
> +	tmc_flush_and_stop(drvdata);
> +
> +	rwplo = readl_relaxed(drvdata->base + TMC_RWP);
> +	rwphi = readl_relaxed(drvdata->base + TMC_RWPHI);
> +	full = (readl_relaxed(drvdata->base + TMC_STS) & TMC_STS_FULL);

nitpick: you don't need the brackets above.

> +
> +	/* Combine the high and low part of the rwp to make a full address */
> +	rwp = (u64)rwphi << 32;
> +	rwp |= rwplo;
> +
> +	/* Convert the stop address in RAM to a page and an offset */
> +	if (tmc_get_sg_page_index(etr_buf, rwp, &stop_index, &stop_offset))
> +		goto out;
> +
> +	if (full) {
> +		/*
> +		 * The buffer head has wrapped around.  As such the size
> +		 * is the entire buffer length and the index and offset in
> +		 * the scatter-gather list are moved forward.
> +		 */
> +		local_inc(&cs_buf->lost);
> +		to_read = drvdata->size;
> +		sg_index = stop_index;
> +		sg_offset = stop_offset;
> +	} else {
> +		to_read = (stop_index * PAGE_SIZE) + stop_offset;
> +	}
> +
> +	/*
> +	 * The TMC RAM buffer may be bigger than the space available in the
> +	 * perf ring buffer (handle->size).  If so advance the RRP so that we
> +	 * get the latest trace data.
> +	 */

A stupid question: Is this something we can tune in the tmc to match the handle->size so that we
don't have to worry about it ?

> +	if (to_read > handle->size) {
> +		u64 rrp;
> +
> +		/*
> +		 * Compute where we should start reading from
> +		 * relative to rwp.
> +		 */
> +		rrp = rwp + drvdata->size;
> +		/* Go back just enough */
> +		rrp -= handle->size;


This looks wrong to me. We cannot simply move the rrp pointer back and forth, as the buffer
is not guaranteed to be contiguous.

> +		/* Make sure we are still within our limits */
> +		rrp %= drvdata->size;

And the above step definitely makes it not an address. We may have to find the address by looking
at the page table.

> +
> +		/* Get a new index and offset based on rrp */
> +		if (tmc_get_sg_page_index(etr_buf, rrp,
> +					  &stop_index, &stop_offset))
> +			goto out;
> +
> +		/* Tell user space we lost data */
> +		local_inc(&cs_buf->lost);
> +		to_read = handle->size;
> +		/* Adjust start index and offset */
> +		sg_index = stop_index;
> +		sg_offset = stop_offset;
> +	}
> +
> +	/* Get a handle on where the Perf ring buffer is */
> +	rb_index = cs_buf->cur;
> +	rb_offset = cs_buf->offset;
> +
> +	/* Refresh the SG list */
> +	tmc_sg_page_sync(etr_buf, sg_index, to_read);
> +
> +	for (i = to_read; i > 0; ) {
> +		/* Get current location of the perf ring buffer */
> +		rb_ptr = cs_buf->data_pages[rb_index] + rb_offset;
> +		/* Get current location in the ETR SG list */
> +		sg_ptr = (u32 *)(etr_buf->page_addr[sg_index].vaddr +
> +				 sg_offset);
> +
> +		/*
> +		 * First figure out the maximum amount of data we can get out
> +		 * of the ETR SG list.
> +		 */
> +		if (i < PAGE_SIZE)
> +			sg_size = i;
> +		else
> +			sg_size = PAGE_SIZE - sg_offset;

If i < PAGE_SIZE and (PAGE_SIZE - sg_offset) < i, we could crash below trying to
copy from beyond the page.
I think it should be :

		sg_size = min(PAGE_SIZE - sg_offset, i);


Thanks
Suzuki

^ permalink raw reply

* [PATCH] Adding Support for Coresight Components on Zynq 7000.
From: Muhammad Abdul WAHAB @ 2016-10-03 14:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003133019.GF7630@xsjsorenbubuntu>

Hi again S?ren,

 > Sounds good. AFAICT, the change below should be OK. Probably some
 > stylistic changes to make it blend in with the rest of the DT (e.g.
 > use lower case characters in the address parts of the node name).

The change to low characters has been made for address part. I also
deleted some empty lines to respect the style of the rest of the DT.

 > I'd say that depends on what it is about. If it is about DT and the TPIU
 > Linux driver, I'd say, keep it on list and probably even include the
 > authors of that driver (the folks the get_maintainers script is
 > identifying for that driver).
 >
 > If it's specific to Zynq, the Xilinx forums can be quite helpful as
 > there are a lot of people familiar with the device
 > (https://forums.xilinx.com/t5/Embedded-Linux/bd-p/ELINUX).
 >
 > But when in doubt, feel free to reach out to me directly.

OK. Thank you !

M.Abdul WAHAB
---
--- linux-4.7/arch/arm/boot/dts/zynq-7000.dtsi.orig    2016-07-24 
21:23:50.000000000 +0200
+++ linux-4.7/arch/arm/boot/dts/zynq-7000.dtsi    2016-10-03 
15:54:35.228460164 +0200
@@ -96,6 +96,51 @@
              rx-fifo-depth = <0x40>;
          };

+        etb at f8801000 {
+            compatible = "arm,coresight-etb10", "arm,primecell";
+            reg = <0xf8801000 0x1000>;
+            coresight-default-sink;
+            clocks = <&clkc 47>;
+            clock-names = "apb_pclk";
+            port {
+                etb_in_port: endpoint at 0 {
+                    slave-mode;
+                    remote-endpoint = <&replicator_out_port0>;
+                };
+            };
+        };
+
+        funnel at f8804000 {
+            compatible = "arm,coresight-funnel", "arm,primecell";
+            reg = <0xf8804000 0x1000>;
+            clocks = <&clkc 47>;
+            clock-names = "apb_pclk";
+            ports {
+                #address-cells = <0x1>;
+                #size-cells = <0x0>;
+                port at 0 {
+                    reg = <0x0>;
+                    funnel_out_port0: endpoint {
+                        remote-endpoint = <&replicator_in_port0>;
+                    };
+                };
+                port at 1 {
+                    reg = <0x0>;
+                    funnel_in_port0: endpoint {
+                        slave-mode;
+                        remote-endpoint = <&ptm0_out_port>;
+                    };
+                };
+                port at 2 {
+                    reg = <0x1>;
+                    funnel_in_port1: endpoint {
+                        slave-mode;
+                        remote-endpoint = <&ptm1_out_port>;
+                    };
+                };
+            };
+        };
+
          gpio0: gpio at e000a000 {
              compatible = "xlnx,zynq-gpio-1.0";
              #gpio-cells = <2>;
@@ -311,6 +356,59 @@
              clocks = <&clkc 4>;
          };

+        ptm0 at f889c000 {
+            compatible = "arm,coresight-etm3x", "arm,primecell";
+            reg = <0xf889c000 0x1000>;
+            cpu = <&cpu0>;
+            clocks = <&clkc 47>;
+            clock-names = "apb_pclk";
+            port {
+                ptm0_out_port: endpoint {
+                    remote-endpoint = <&funnel_in_port0>;
+                };
+            };
+        };
+
+        ptm1 at f889d000 {
+            compatible = "arm,coresight-etm3x", "arm,primecell";
+            reg = <0xf889d000 0x1000>;
+            cpu = <&cpu1>;
+            clocks = <&clkc 47>;
+            clock-names = "apb_pclk";
+            port {
+                ptm1_out_port: endpoint {
+                    remote-endpoint = <&funnel_in_port1>;
+                };
+            };
+        };
+
+        replicator {
+            compatible = "arm,coresight-replicator";
+            ports {
+                #address-cells = <0x1>;
+                #size-cells = <0x0>;
+                port at 0 {
+                    reg = <0x0>;
+                    replicator_out_port0: endpoint {
+                        remote-endpoint = <&etb_in_port>;
+                    };
+                };
+                port at 1 {
+                    reg = <0x1>;
+                    replicator_out_port1: endpoint {
+                        remote-endpoint = <&tpiu_in_port>;
+                    };
+                };
+                port at 2 {
+                    reg = <0x0>;
+                    replicator_in_port0: endpoint {
+                        slave-mode;
+                        remote-endpoint = <&funnel_out_port0>;
+                    };
+                };
+            };
+        };
+
          ttc0: timer at f8001000 {
              interrupt-parent = <&intc>;
              interrupts = <0 10 4>, <0 11 4>, <0 12 4>;

^ permalink raw reply

* [PATCH v2 2/2] drm: zte: add initial vou drm driver
From: Daniel Vetter @ 2016-10-03 13:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACvgo53A7BpVWHgkFrZsjWnw_uW6xDmKRsrxF=46HOEWQ43BxA@mail.gmail.com>

On Mon, Oct 3, 2016 at 12:36 PM, Emil Velikov <emil.l.velikov@gmail.com> wrote:
>>> > +static int zx_gl_get_fmt(uint32_t format)
>>> > +{
>>> > +       switch (format) {
>>> > +       case DRM_FORMAT_ARGB8888:
>>> > +       case DRM_FORMAT_XRGB8888:
>>> > +               return GL_FMT_ARGB8888;
>>> > +       case DRM_FORMAT_RGB888:
>>> > +               return GL_FMT_RGB888;
>>> > +       case DRM_FORMAT_RGB565:
>>> > +               return GL_FMT_RGB565;
>>> > +       case DRM_FORMAT_ARGB1555:
>>> > +               return GL_FMT_ARGB1555;
>>> > +       case DRM_FORMAT_ARGB4444:
>>> > +               return GL_FMT_ARGB4444;
>>> > +       default:
>>> > +               WARN_ONCE(1, "invalid pixel format %d\n", format);
>>> > +               return -EINVAL;
>>> Afaics the only user of this is atomic_update() and that function
>>> cannot fail. You might want to move this to the _check() function.
>>> Same logic goes for the rest of the driver, in case I've missed any.
>>
>> The function does the conversion from DRM format values to the ones that
>> hardware accepts.  And I need to set up hardware register with the
>> converted value.
>>
>> I suppose that the error case in 'default' should never be hit, since
>> all valid format have been reported to DRM core by gl_formats?  In that
>> case, I can simply drop the WARN and return a sane default format
>> instead?
>>
> I'd just do the error checking in check() function and keep the
> mapping in update(). As devs add new formats to DRM core it's not
> possible for them to test every driver so getting a failure early is
> better (imho) than getting subtle visual and/or other issues. Either
> way it's up-to you really.

I think a WARN_ON here is perfectly fine. Like Shawn said, any invalid
formats should already be filtered out by the drm core (by checking
against the list of valid formats for this plane), so no need to move
this to ->check(). In i915.ko we have a MISSING_CASE macro to catch
these cases when someone adds a new format, but forgets to update all
the switch statements.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply

* [PATCH V4 04/10] dmaengine: qcom_hidma: configure DMA and MSI for OF
From: Sinan Kaya @ 2016-10-03 13:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003033851.GP2467@localhost>

On 10/2/2016 11:38 PM, Vinod Koul wrote:
>> I followed the pattern in of_platform_device_create_pdata function. of_msi_configure does
>> > nothing if MSI is not enabled as irq_find_matching_host returns NULL. It didn't have any
>> > side effects on my testing either.
> yeah later on I did look up the of_msi_configure() and I suspected this. I
> think it would be worthwhile to document this assumption here.

Sure, let me do that.

-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCH] Adding Support for Coresight Components on Zynq 7000.
From: Sören Brinkmann @ 2016-10-03 13:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5b56a00a-ac69-b15d-1155-bab53ed766f3@supelec.fr>

Hi Muhammad,

On Mon, 2016-10-03 at 14:56:16 +0200, Muhammad Abdul WAHAB wrote:
> Hi S?ren,
> 
> > I tried to refresh my Zynq knowledge a bit. The clkc provides the
> > dbg_trc clock, and that is the clock you need (not fclk). I couldn't
> > find it in the binding (I guess I messed that up), but apparently,
> > you can provide a 'trace_emio_clk' as input to the clkc node in the
> > Zynq DT. Then, with the muxes correctly configured (FSBL should do
> > that if you select the EMIO trace clock in Vivado), the dbg_trc
> > output of the clkc should be that EMIO clock. And the dbg_trc output
> > of the clkc is what should be consumed by the tpiu node. Though, as
> > I see it the binding/driver for the TPIU do not support that.
> >
> > I.e.
> > In the clkc description you'd have to add 'trace_emio_clk' to the
> > clock-names property together with a matching reference in the 'clocks'
> > property. As this change would be specific to local setups, this is not
> > really appropriate for upstream.
> >
> > Then, for the trace clock, ideally the TPIU would consume and enable it
> > as needed.
> 
> Thank you very much for this. I will have a look into it.
> Below is the patch without TPIU, is it possible to submit it ? I will submit
> the TPIU part very soon once I manage to get it working.

Sounds good. AFAICT, the change below should be OK. Probably some
stylistic changes to make it blend in with the rest of the DT (e.g.
use lower case characters in the address parts of the node name).

> 
> > Unfortunately, this is not how it works. The DT bindings are not a
> > recommendation. The DT description must follow the binding, otherwise
> > drivers will not work correctly, or best case, just ignore what you put
> > there.
> 
> Thanks. The idea of including TPIU part was to get feedback as I am far from
> being an expert on DT.
> 
> > As I don't see this in the coresight binding, I doubt that it has any
> > effect or should be here.
> 
> That's what I was thinking also. I will re-look into TPIU part and send it
> soon. Besides, if I want to ask you a question regarding TPIU or DT, can I
> contact you alone or should I keep sending it to all the CS/DT maintainers ?

I'd say that depends on what it is about. If it is about DT and the TPIU
Linux driver, I'd say, keep it on list and probably even include the
authors of that driver (the folks the get_maintainers script is
identifying for that driver).

If it's specific to Zynq, the Xilinx forums can be quite helpful as
there are a lot of people familiar with the device
(https://forums.xilinx.com/t5/Embedded-Linux/bd-p/ELINUX).

But when in doubt, feel free to reach out to me directly.

	S?ren

^ permalink raw reply

* Coresight ETF trace dump failed in Juno r1 with 4.8-rc8
From: Sudeep Holla @ 2016-10-03 13:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAGhh56F-VWCCy82msQ8CimZ4a0a2h=tqR2qv1KcfeyuQXo=R1w@mail.gmail.com>

Hi Venkatesh,

On 03/10/16 12:36, Venkatesh Vivekanandan wrote:
> Hi All,
>
> I am trying to collect ETF trace from Juno R1 and could see "cpu
> stall" while dumping the trace. Attached is the log of sequence
> followed. Was trying to collect the trace data from hardware and see
> if it is any valid data. Am I missing anything here?.
>

There are few fixes from me and Suzuki queued for v4.9.
Can you check if this issue persists even on linux-next ?

-- 
Regards,
Sudeep

^ permalink raw reply

* PROBLEM: DWC3 USB 3.0 not working on Odroid-XU4 with Exynos 5422
From: Michael Niewöhner @ 2016-10-03 13:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CANAwSgQMsK8YPxR==UXtR49kiJzYhkzvSCNwn8mDJfj-3wpa2w@mail.gmail.com>

Hi,

On Di, 2016-09-20 at 23:12 +0200, Michael Niew?hner wrote:
> 
> 
> Hi guys,
> > 
> > 
> > > 
> > > 
> > > Hi All
> > > ?
> > > Adding Vivek Gautam.
> > > ?
> > > On 29 August 2016 at 16:35, Michael Niew?hner
> > <linux@mniewoehner.de>
> > > 
> > > 
> > > wrote:
> > > > 
> > > > 
> > > > > 
> > > > > 
> > > > > ?
> > > > > Hi Mathias,
> > > > > On Mo, 2016-08-29 at 13:59 +0300, Mathias Nyman wrote:
> > > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > ?
> > > > > > > On 29.08.2016 10:28, Felipe Balbi wrote:
> > > > > > > > 
> > > > > > > > 
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > ?
> > > > > > > > > ?
> > > > > > > > > ?
> > > > > > > > > Hi,
> > > > > > > > > ?
> > > > > > > > > Michael Niew?hner <linux@mniewoehner.de> writes:
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > ?
> > > > > > > > > > > ?
> > > > > > > > > > > [1.] One line summary of the problem:
> > > > > > > > > > > DWC3 USB 3.0 not working on Odroid-XU4 with
> > > > > > Exynos 5422
> > > > > > > 
> > > > > > > 
> > > > > > > > 
> > > > > > > > 
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > ?
> > > > > > > > > > > [2.] Full description of the problem/report:
> > > > > > > > > > > No usb 3.0 devices are being detected when
> > > > > > attached while USB
> > > > > > > 
> > > > > > > 
> > > > > > > > 
> > > > > > > > 
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 2.0
> > > > > > > > > > > devices work on the same port.
> > > > > > > > > > > USB 3.0 works after applying patches [9.1] and
> > > > > > [9.2], but
> > > > > > > 
> > > > > > > 
> > > > > > > > 
> > > > > > > > 
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > seems
> > > > > > > > > > > to be
> > > > > > > > > > > buggy. The usb hub is redetected every time an
> > > > > > usb device is
> > > > > > > 
> > > > > > > 
> > > > > > > > 
> > > > > > > > 
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > attached.
> > > > > > > > > ?
> > > > > > > > > dwc3 is host, which means it's actually XHCI :-)
> > > > > > > > > ?
> > > > > > > > > Adding Mathias
> > > > > > > > > ?
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > ?
> > > > > > > > > > > ?
> > > > > > > > > > > dmesg:
> > > > > > > > > > > [??192.287080] usb 3-1.2: USB disconnect, device
> > > > > > number 7
> > > > > > > 
> > > > > > > 
> > > > > > > > 
> > > > > > > > 
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > [??210.370699] hub 3-1:1.0: hub_ext_port_status
> > > > > > failed (err =
> > > > > > > 
> > > > > > > 
> > > > > > > > 
> > > > > > > > 
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > -71)
> > > > > > > ?
> > > > > > > Looks like the hub GetPortStatus request fails with
> > > > protocol
> > > > > 
> > > > > 
> > > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > error.
> > > > > > > ?
> > > > > > > Reading xhci root hub port status is mostly just register
> > > > reads
> > > > > 
> > > > > 
> > > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > and
> > > > > > > writes. It
> > > > > > > shouldn't include any actual transfers that could return
> > > > -EPROTO
> > > > > 
> > > > > 
> > > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > ?
> > > > > > > So this is not the root hub? but a external or integrated
> > > > on your
> > > > > 
> > > > > 
> > > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > board, right?
> > > > > > > ?
> > > > > > > The protocol error -71 is returned at transfer errors or
> > > > if
> > > > > 
> > > > > 
> > > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > device
> > > > > > > stalled.
> > > > > > > ?
> > > > > > > Adding more xhci debugging options could show something:
> > > > > > > echo -n 'module xhci_hcd =p' >
> > > > > > > /sys/kernel/debug/dynamic_debug/control
> > > > > > > ?
> > > > > > > > 
> > > > > > > > 
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > ?
> > > > > > > > > ?
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > > ?
> > > > > > > > > > > ?
> > > > > > > > > > > [9.] Other notes, patches, fixes, workarounds:
> > > > > > > > > > > [9.1] https://lkml.org/lkml/2014/4/28/234
> > > > > > > > > > > [9.2] https://lkml.org/lkml/2015/2/2/259
> > > > > > > ?
> > > > > > > The additional patches that makes things somehow work
> > > > involve
> > > > > 
> > > > > 
> > > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > tuning
> > > > > > > the PHY,
> > > > > > > this is an area I'm not familiar with
> > > > > > > ?
> > > > > > > -Mathias
> > > > > > > ?
> > > > > ?
> > > > > ?
> > > > > I'm sorry, I should have said that this is the dmesg output
> > > with
> > > > 
> > > > 
> > > > > 
> > > > > 
> > > > > the
> > > > > patches applied. Without them there is no output at all when
> > > I
> > > > 
> > > > 
> > > > > 
> > > > > 
> > > > > attach
> > > > > an usb 3.0 device.
> > > > > ?
> > > > > Michael
> > > ?
> > > There are two dwc3 ports in the SoC : one for Gbit Ethernet
> > another
> > > 
> > > 
> > > one for on-board GL3521 USB 3.0 hub controller.
> > > ?
> > > 3.10.x kernel
> > > odroid at odroid:~$ lsusb -t
> > > /:??Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p,
> > 5000M
> > > 
> > > 
> > > ?????|__ Port 1: Dev 2, If 0, Class=Vendor Specific Class,
> > > Driver=r8152, 5000M
> > > /:??Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p,
> > 480M
> > > 
> > > 
> > > /:??Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p,
> > 5000M
> > > 
> > > 
> > > ?????|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/2p, 5000M
> > > /:??Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p,
> > 480M
> > > 
> > > 
> > > ?????|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/2p, 480M
> > > /:??Bus 02.Port 1: Dev 1, Class=root_hub, Driver=exynos-ohci/3p,
> > 12M
> > > 
> > > 
> > > /:??Bus 01.Port 1: Dev 1, Class=root_hub, Driver=s5p-ehci/3p,
> > 480M
> > > 
> > > 
> > > ?
> > > 4.x kernel
> > > odroid at odroid:~$ lsusb -t
> > > /:??Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p,
> > 5000M
> > > 
> > > 
> > > /:??Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p,
> > 480M
> > > 
> > > 
> > > ?????|__ Port 1: Dev 2, If 0, Class=Vendor Specific Class,
> > > Driver=r8152, 480M
> > > /:??Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p,
> > 5000M
> > > 
> > > 
> > > ?????|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/2p, 5000M
> > > ?????????|__ Port 1: Dev 3, If 0, Class=Mass Storage, Driver=usb-
> > > storage, 5000M
> > > ?????????|__ Port 2: Dev 4, If 0, Class=Mass Storage, Driver=usb-
> > > storage, 5000M
> > > /:??Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p,
> > 480M
> > > 
> > > 
> > > ?????|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/2p, 480M
> > > /:??Bus 02.Port 1: Dev 1, Class=root_hub, Driver=exynos-ohci/3p,
> > 12M
> > > 
> > > 
> > > /:??Bus 01.Port 1: Dev 1, Class=root_hub, Driver=exynos-ehci/3p,
> > 480M
> > > 
> > > 
> > > ?
> > > I fell that Ethernet driver r8152 is not getting registered to
> > > xhci-hcd to bus port 06
> > > which lead to other ports to miss configure, some time the
> > Ethernet
> > > 
> > > 
> > > port get register to bus port 04
> > > ?
> > > Their is also a possibility that all the port are not getting
> > proper
> > > 
> > > 
> > > power from the S2MPS11 PMIC
> > > and possible some reset of the phy is needed to reconfigure the
> > > exynos
> > > USB HSIC controller.
> > > ?
> > > Best Regards
> > > -Anand Moon
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-
> > > samsung-soc" in
> > > the body of a message to majordomo at vger.kernel.org
> > > More majordomo info at??http://vger.kernel.org/majordomo-
> > info.html
> ?
> ?
> today I've tested v4.8-rc7 (without the patches above). The USB 3.0
> ports have stopped working completely for me. Neither USB 2.0 nor USB
> 3.0 are being detected. The Ethernet port does not work, too. The
> USB-2.0-only Port works.
> ?
> There are some failures in the dmesg log:
> ...
> [???15.096251] 12100000.phy supply vbus not found, using dummy
> regulator
> ...
> [???19.642578] usb usb5-port1: connect-debounce failed
> ?
> ?
> dmesg:


looks like I forgot to append the dmesg in my last mail. Sorry about
that.
The problem is also present in v4.8. Let me know if you need more
information.

Michael


dmesg v4.8 without any additional patches:

[????0.000000] Booting Linux on physical CPU 0x100
[????0.000000] Linux version 4.8.0 (c0d3 at z3r0) (gcc version 5.3.1
20160412 (Linaro GCC 5.3-2016.05) ) #3 SMP Mon Oct 3 14:11:40 CEST 2016
[????0.000000] CPU: ARMv7 Processor [410fc073] revision 3 (ARMv7),
cr=10c5387d
[????0.000000] CPU: div instructions available: patching division code
[????0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing
instruction cache
[????0.000000] OF: fdt:Machine model: Hardkernel Odroid XU4
[????0.000000] Reserved memory: created DMA memory pool at 0xbe200000,
size 8 MiB
[????0.000000] OF: reserved mem: initialized node region_mfc_right,
compatible id shared-dma-pool
[????0.000000] Reserved memory: created DMA memory pool at 0xbd200000,
size 16 MiB
[????0.000000] OF: reserved mem: initialized node region_mfc_left,
compatible id shared-dma-pool
[????0.000000] Memory policy: Data cache writealloc
[????0.000000] Samsung CPU ID: 0xe5422001
[????0.000000] On node 0 totalpages: 512512
[????0.000000] free_area_init_node: node 0, pgdat c0c81840,
node_mem_map eee52000
[????0.000000]???Normal zone: 1728 pages used for memmap
[????0.000000]???Normal zone: 0 pages reserved
[????0.000000]???Normal zone: 196608 pages, LIFO batch:31
[????0.000000]???HighMem zone: 315904 pages, LIFO batch:31
[????0.000000] Running under secure firmware.
[????0.000000] percpu: Embedded 15 pages/cpu @eeda1000 s30272 r8192
d22976 u61440
[????0.000000] pcpu-alloc: s30272 r8192 d22976 u61440 alloc=15*4096
[????0.000000] pcpu-alloc: [0] 0 [0] 1 [0] 2 [0] 3 [0] 4 [0] 5 [0] 6
[0] 7?
[????0.000000] Built 1 zonelists in Zone order, mobility grouping
on.??Total pages: 510784
[????0.000000] Kernel command line: console=ttySAC2,115200n8
root=/dev/mmcblk1p2 rootfstype=ext4 rootwait earlyprintk debug
[????0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes)
[????0.000000] Dentry cache hash table entries: 131072 (order: 7,
524288 bytes)
[????0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144
bytes)
[????0.000000] Memory: 2018124K/2050048K available (7168K kernel code,
618K rwdata, 2064K rodata, 1024K init, 375K bss, 31924K reserved, 0K
cma-reserved, 1263616K highmem)
[????0.000000] Virtual kernel memory layout:
????vector??: 0xffff0000 - 0xffff1000???(???4 kB)
????fixmap??: 0xffc00000 - 0xfff00000???(3072 kB)
????vmalloc : 0xf0800000 - 0xff800000???( 240 MB)
????lowmem??: 0xc0000000 - 0xf0000000???( 768 MB)
????pkmap???: 0xbfe00000 - 0xc0000000???(???2 MB)
????modules : 0xbf000000 - 0xbfe00000???(??14 MB)
??????.text : 0xc0008000 - 0xc0800000???(8160 kB)
??????.init : 0xc0b00000 - 0xc0c00000???(1024 kB)
??????.data : 0xc0c00000 - 0xc0c9aafc???( 619 kB)
???????.bss : 0xc0c9c000 - 0xc0cf9d04???( 376 kB)
[????0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=8,
Nodes=1
[????0.000000] Hierarchical RCU implementation.
[????0.000000]??Build-time adjustment of leaf fanout to 32.
[????0.000000]??RCU restricting CPUs from NR_CPUS=16 to nr_cpu_ids=8.
[????0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=32,
nr_cpu_ids=8
[????0.000000] NR_IRQS:16 nr_irqs:16 16
[????0.000000] Switching to timer-based delay loop, resolution 41ns
[????0.000000] clocksource: mct-frc: mask: 0xffffffff max_cycles:
0xffffffff, max_idle_ns: 79635851949 ns
[????0.000007] sched_clock: 32 bits at 24MHz, resolution 41ns, wraps
every 89478484971ns
[????0.001695] Console: colour dummy device 80x30
[????0.001738] Calibrating delay loop (skipped), value calculated using
timer frequency.. 48.00 BogoMIPS (lpj=240000)
[????0.001758] pid_max: default: 32768 minimum: 301
[????0.001911] Security Framework initialized
[????0.001928] Yama: becoming mindful.
[????0.001960] AppArmor: AppArmor disabled by boot time parameter
[????0.002017] Mount-cache hash table entries: 2048 (order: 1, 8192
bytes)
[????0.002033] Mountpoint-cache hash table entries: 2048 (order: 1,
8192 bytes)
[????0.003077] CPU: Testing write buffer coherency: ok
[????0.003125] ftrace: allocating 25558 entries in 75 pages
[????0.058307] CPU0: update cpu_capacity 448
[????0.058329] CPU0: thread -1, cpu 0, socket 1, mpidr 80000100
[????0.058499] Setting up static identity map for 0x40100000 -
0x40100058
[????0.059140] ARM CCI driver probed
[????0.059353] Exynos MCPM support installed
[????0.063820] CPU1: update cpu_capacity 448
[????0.063828] CPU1: thread -1, cpu 1, socket 1, mpidr 80000101
[????0.064893] CPU2: update cpu_capacity 448
[????0.064901] CPU2: thread -1, cpu 2, socket 1, mpidr 80000102
[????0.065969] CPU3: update cpu_capacity 448
[????0.065977] CPU3: thread -1, cpu 3, socket 1, mpidr 80000103
[????0.066934] CPU4: update cpu_capacity 1535
[????0.066942] CPU4: thread -1, cpu 0, socket 0, mpidr 80000000
[????0.067971] CPU5: update cpu_capacity 1535
[????0.067978] CPU5: thread -1, cpu 1, socket 0, mpidr 80000001
[????0.068967] CPU6: update cpu_capacity 1535
[????0.068974] CPU6: thread -1, cpu 2, socket 0, mpidr 80000002
[????0.069977] CPU7: update cpu_capacity 1535
[????0.069984] CPU7: thread -1, cpu 3, socket 0, mpidr 80000003
[????0.070124] Brought up 8 CPUs
[????0.070187] SMP: Total of 8 processors activated (384.00 BogoMIPS).
[????0.070198] CPU: WARNING: CPU(s) started in wrong/inconsistent modes
(primary CPU mode 0x1a)
[????0.070207] CPU: This may indicate a broken bootloader or firmware.
[????0.072308] devtmpfs: initialized
[????0.097643] VFP support v0.3: implementor 41 architecture 2 part 30
variant 7 rev 3
[????0.098142] clocksource: jiffies: mask: 0xffffffff max_cycles:
0xffffffff, max_idle_ns: 19112604462750000 ns
[????0.098457] pinctrl core: initialized pinctrl subsystem
[????0.101390] NET: Registered protocol family 16
[????0.102209] DMA: preallocated 256 KiB pool for atomic coherent
allocations
[????0.149996] cpuidle: using governor ladder
[????0.189985] cpuidle: using governor menu
[????0.198708] hw-breakpoint: found 5 (+1 reserved) breakpoint and 4
watchpoint registers.
[????0.198724] hw-breakpoint: maximum watchpoint size is 8 bytes.
[????0.199088] Serial: AMBA PL011 UART driver
[????0.208742] iommu: Adding device 11000000.codec to group 0
[????0.244099] iommu: Adding device 14450000.mixer to group 1
[????0.244643] iommu: Adding device 11c00000.rotator to group 2
[????0.254076] iommu: Adding device 13e00000.video-scaler to group 3
[????0.254594] iommu: Adding device 13e10000.video-scaler to group 4
[????0.255107] iommu: Adding device 11f50000.jpeg to group 5
[????0.255613] iommu: Adding device 11f60000.jpeg to group 6
[????0.256003] EXYNOS5420 PMU initialized
[????0.312565] SCSI subsystem initialized
[????0.312938] usbcore: registered new interface driver usbfs
[????0.313031] usbcore: registered new interface driver hub
[????0.313226] usbcore: registered new device driver usb
[????0.314692] s3c-i2c 12c80000.i2c: slave address 0x00
[????0.314712] s3c-i2c 12c80000.i2c: bus frequency set to 65 KHz
[????0.315240] s3c-i2c 12c80000.i2c: i2c-2: S3C I2C adapter
[????0.315709] media: Linux media interface: v0.10
[????0.315777] Linux video capture interface: v2.00
[????0.315874] pps_core: LinuxPPS API ver. 1 registered
[????0.315885] pps_core: Software ver. 5.3.6 - Copyright 2005-2007
Rodolfo Giometti <giometti@linux.it>
[????0.315914] PTP clock support registered
[????0.317980] clocksource: Switched to clocksource mct-frc
[????0.385905] VFS: Disk quotas dquot_6.6.0
[????0.385987] VFS: Dquot-cache hash table entries: 1024 (order 0, 4096
bytes)
[????0.405341] NET: Registered protocol family 2
[????0.406054] TCP established hash table entries: 8192 (order: 3,
32768 bytes)
[????0.406137] TCP bind hash table entries: 8192 (order: 4, 65536
bytes)
[????0.406295] TCP: Hash tables configured (established 8192 bind 8192)
[????0.406360] UDP hash table entries: 512 (order: 2, 16384 bytes)
[????0.406402] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes)
[????0.406639] NET: Registered protocol family 1
[????0.410133] futex hash table entries: 2048 (order: 5, 131072 bytes)
[????0.410271] audit: initializing netlink subsys (disabled)
[????0.410335] audit: type=2000 audit(0.380:1): initialized
[????0.411455] workingset: timestamp_bits=14 max_order=19
bucket_order=5
[????0.422219] zbud: loaded
[????0.428206] Key type asymmetric registered
[????0.428281] bounce: pool size: 64 pages
[????0.428544] Block layer SCSI generic (bsg) driver version 0.4 loaded
(major 247)
[????0.428787] io scheduler noop registered
[????0.428801] io scheduler deadline registered (default)
[????0.429058] io scheduler cfq registered
[????0.439042] dma-pl330 121a0000.pdma: Loaded driver for PL330 DMAC-
241330
[????0.439060] dma-pl330 121a0000.pdma:?????????DBUFF-32x4bytes
Num_Chans-8 Num_Peri-32 Num_Events-32
[????0.443549] dma-pl330 121b0000.pdma: Loaded driver for PL330 DMAC-
241330
[????0.443568] dma-pl330 121b0000.pdma:?????????DBUFF-32x4bytes
Num_Chans-8 Num_Peri-32 Num_Events-32
[????0.444825] dma-pl330 10800000.mdma: Loaded driver for PL330 DMAC-
241330
[????0.444842] dma-pl330 10800000.mdma:?????????DBUFF-64x8bytes
Num_Chans-8 Num_Peri-1 Num_Events-32
[????0.446009] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[????0.448993] Serial: AMBA driver
[????0.449384] 12c00000.serial: ttySAC0 at MMIO 0x12c00000 (irq = 76,
base_baud = 0) is a S3C6400/10
[????0.449890] 12c10000.serial: ttySAC1 at MMIO 0x12c10000 (irq = 77,
base_baud = 0) is a S3C6400/10
[????0.450386] 12c20000.serial: ttySAC2 at MMIO 0x12c20000 (irq = 78,
base_baud = 0) is a S3C6400/10
[????1.007347] random: fast init done
[????1.291220] console [ttySAC2] enabled
[????1.295362] 12c30000.serial: ttySAC3 at MMIO 0x12c30000 (irq = 79,
base_baud = 0) is a S3C6400/10
[????1.304951] [drm] Initialized drm 1.1.0 20060810
[????1.311440] exynos-hdmi 14530000.hdmi: Failed to get supply 'vdd':
-517
[????1.318159] exynos-rot 11c00000.rotator: The exynos rotator is
probed successfully
[????1.324687] exynos-drm-gsc 13e00000.video-scaler: failed to get
system register.
[????1.331876] exynos-drm-gsc 13e00000.video-scaler: drm gsc registered
successfully.
[????1.339273] exynos-drm-gsc 13e10000.video-scaler: failed to get
system register.
[????1.346771] exynos-drm-gsc 13e10000.video-scaler: drm gsc registered
successfully.
[????1.354919] exynos-drm-ipp exynos-drm-ipp: drm ipp registered
successfully.
[????1.367209] libphy: Fixed MDIO Bus: probed
[????1.370337] usbcore: registered new interface driver usb-storage
[????1.376279] mousedev: PS/2 mouse device common for all mice
[????1.400256] vdd_ldo9: Bringing 3300000uV into 3000000-3000000uV
[????1.413855] vddq_mmc2: Bringing 3300000uV into 2800000-2800000uV
[????1.423183] vdd_ldo15: Bringing 3300000uV into 3100000-3100000uV
[????1.436801] vdd_sd: Bringing 3300000uV into 2800000-2800000uV
[????1.499343] s5m-rtc s2mps14-rtc: rtc core: registered s5m-rtc as
rtc0
[????1.512014] exynos-tmu 10060000.tmu: More trip points than supported
by this TMU.
[????1.518056] exynos-tmu 10060000.tmu: 2 trip points should be
configured in polling mode.
[????1.543169] sdhci: Secure Digital Host Controller Interface driver
[????1.547861] sdhci: Copyright(c) Pierre Ossman
[????1.552447] Synopsys Designware Multimedia Card Interface Driver
[????1.558827] dwmmc_exynos 12200000.mmc: IDMAC supports 32-bit address
mode.
[????1.565036] dwmmc_exynos 12200000.mmc: Using internal DMA
controller.
[????1.571462] dwmmc_exynos 12200000.mmc: Version ID is 250a
[????1.576835] dwmmc_exynos 12200000.mmc: DW MMC controller at irq
91,64 bit host data width,64 deep fifo
[????1.586254] dwmmc_exynos 12200000.mmc: Got CD GPIO
[????1.590920] dwmmc_exynos 12200000.mmc: allocated mmc-pwrseq
[????1.628648] mmc_host mmc0: Bus speed (slot 0) = 50000000Hz (slot req
400000Hz, actual 396825HZ div = 63)
[????1.658185] dwmmc_exynos 12200000.mmc: 1 slots initialized
[????1.662422] dwmmc_exynos 12220000.mmc: IDMAC supports 32-bit address
mode.
[????1.669071] dwmmc_exynos 12220000.mmc: Using internal DMA
controller.
[????1.675448] dwmmc_exynos 12220000.mmc: Version ID is 250a
[????1.680869] dwmmc_exynos 12220000.mmc: DW MMC controller at irq
92,64 bit host data width,64 deep fifo
[????1.718450] mmc_host mmc1: Bus speed (slot 0) = 50000000Hz (slot req
400000Hz, actual 396825HZ div = 63)
[????1.748015] dwmmc_exynos 12220000.mmc: 1 slots initialized
[????1.752198] sdhci-pltfm: SDHCI platform and OF driver helper
[????1.758808] ledtrig-cpu: registered to indicate activity on CPUs
[????1.763667] hidraw: raw HID events driver (C) Jiri Kosina
[????1.769408] usbcore: registered new interface driver usbhid
[????1.774539] usbhid: USB HID core driver
[????1.779758] exynos-audss-clk 3810000.audss-clock-controller: setup
completed
[????1.797575] exynos-nocp: new NoC Probe device registered:
10ca1000.nocp
[????1.802874] exynos-nocp: new NoC Probe device registered:
10ca1400.nocp
[????1.807126] mmc_host mmc1: Bus speed (slot 0) = 50000000Hz (slot req
50000000Hz, actual 50000000HZ div = 0)
[????1.807273] mmc1: new high speed SDHC card at address 59b4
[????1.807917] mmcblk1: mmc1:59b4 USDU1 14.7 GiB?
[????1.808982]??mmcblk1: p1 p2
[????1.831801] exynos-nocp: new NoC Probe device registered:
10ca1800.nocp
[????1.838398] exynos-nocp: new NoC Probe device registered:
10ca1c00.nocp
[????1.846409] NET: Registered protocol family 10
[????1.850110] mip6: Mobile IPv6
[????1.852315] NET: Registered protocol family 17
[????1.856737] mpls_gso: MPLS GSO support
[????1.860858] ThumbEE CPU extension supported.
[????1.864710] Registering SWP/SWPB emulation handler
[????1.870156] registered taskstats version 1
[????1.873593] zswap: loaded using pool lzo/zbud
[????1.882872] [drm] Exynos DRM: using 14450000.mixer device for DMA
mapping operations
[????1.889454] exynos-drm exynos-drm: bound 14450000.mixer (ops
0xc086e904)
[????1.896004] exynos-drm exynos-drm: bound 14530000.hdmi (ops
0xc086ead4)
[????1.902413] [drm] Supports vblank timestamp caching Rev 2
(21.10.2013).
[????1.908997] [drm] No driver support for vblank timestamp query.
[????1.914979] [drm] Initialized exynos 1.0.0 20110530 on minor 0
[????1.921516] s3c-rtc 101e0000.rtc: rtc disabled, re-enabling
[????1.926279] s3c-rtc 101e0000.rtc: warning: invalid RTC value so
initializing it
[????1.933578] rtc rtc1: invalid alarm value: 1900-1-2 0:0:0
[????1.939095] s3c-rtc 101e0000.rtc: rtc core: registered s3c as rtc1
[????1.946585] exynos-bus: new bus device registered: soc:bus_wcore (
84000 KHz ~ 400000 KHz)
[????1.954159] exynos-bus: new bus device registered: soc:bus_noc (
67000 KHz ~ 100000 KHz)
[????1.962043] exynos-bus: new bus device registered: soc:bus_fsys_apb
(100000 KHz ~ 200000 KHz)
[????1.970370] exynos-bus: new bus device registered: soc:bus_fsys
(100000 KHz ~ 200000 KHz)
[????1.978708] exynos-bus: new bus device registered: soc:bus_fsys2 (
75000 KHz ~ 150000 KHz)
[????1.987052] exynos-bus: new bus device registered: soc:bus_mfc (
96000 KHz ~ 333000 KHz)
[????1.995093] exynos-bus: new bus device registered: soc:bus_gen (
89000 KHz ~ 267000 KHz)
[????2.003458] exynos-bus: new bus device registered: soc:bus_peri (
67000 KHz ~??67000 KHz)
[????2.011853] devfreq soc:bus_wcore: Couldn't update frequency
transition information.
[????2.012120] exynos-bus: new bus device registered: soc:bus_g2d (
84000 KHz ~ 333000 KHz)
[????2.012845] exynos-bus: new bus device registered: soc:bus_g2d_acp (
67000 KHz ~ 267000 KHz)
[????2.013561] exynos-bus: new bus device registered: soc:bus_jpeg (
75000 KHz ~ 300000 KHz)
[????2.014273] exynos-bus: new bus device registered: soc:bus_jpeg_apb
( 84000 KHz ~ 167000 KHz)
[????2.014866] exynos-bus: new bus device registered:
soc:bus_disp1_fimd (120000 KHz ~ 200000 KHz)
[????2.015523] exynos-bus: new bus device registered: soc:bus_disp1
(120000 KHz ~ 300000 KHz)
[????2.016166] exynos-bus: new bus device registered:
soc:bus_gscl_scaler (150000 KHz ~ 300000 KHz)
[????2.016941] exynos-bus: new bus device registered: soc:bus_mscl (
84000 KHz ~ 400000 KHz)
[????2.019383] Power domain power-domain at 10044120 disable failed
[????2.026352] s5m-rtc s2mps14-rtc: setting system clock to 2000-01-01
00:00:04 UTC (946684804)
[????2.044135] PM: Hibernation image not present or could not be
loaded.
[????2.113332] EXT4-fs (mmcblk1p2): mounted filesystem with ordered
data mode. Opts: (null)
[????2.120019] VFS: Mounted root (ext4 filesystem) readonly on device
179:2.
[????2.127364] Freeing unused kernel memory: 1024K (c0b00000 -
c0c00000)
[????2.359928] systemd[1]: Mounting cgroup to /sys/fs/cgroup/cpuset of
type cgroup with options cpuset.
[????2.419442] systemd[1]: Mounting cgroup to
/sys/fs/cgroup/cpu,cpuacct of type cgroup with options cpu,cpuacct.
[????2.428599] systemd[1]: Mounting cgroup to /sys/fs/cgroup/blkio of
type cgroup with options blkio.
[????2.438504] systemd[1]: Mounting cgroup to /sys/fs/cgroup/memory of
type cgroup with options memory.
[????2.452714] systemd[1]: Mounting cgroup to /sys/fs/cgroup/devices of
type cgroup with options devices.
[????2.461081] systemd[1]: Mounting cgroup to /sys/fs/cgroup/freezer of
type cgroup with options freezer.
[????2.470341] systemd[1]: Mounting cgroup to
/sys/fs/cgroup/net_cls,net_prio of type cgroup with options
net_cls,net_prio.
[????2.481222] systemd[1]: Mounting cgroup to /sys/fs/cgroup/perf_event
of type cgroup with options perf_event.
[????2.491343] systemd[1]: systemd 215 running in system mode. (+PAM
+AUDIT +SELINUX +IMA +SYSVINIT +LIBCRYPTSETUP +GCRYPT +ACL +XZ -SECCOMP
-APPARMOR)
[????2.503894] systemd[1]: Detected architecture 'arm'.
[????2.733937] systemd-getty-generator[111]: Automatically adding
serial getty for /dev/ttySAC2.
[????2.738699] systemd-fstab-generator[112]: Parsing /etc/fstab
[????2.744149] systemd-rc-local-generator[120]: Automatically adding
rc-local.service.
[????2.745372] systemd-default-display-manager-generator[114]: No
/etc/X11/default-display-manager file, nothing to generate
[????2.746322] systemd-fstab-generator[112]: Found entry
what=/dev/mmcblk1p2 where=/ type=ext4
[????2.813116] systemd-gpt-auto-generator[117]: Root device
/dev/mmcblk1.
[????2.813603] systemd-sysv-generator[116]: Looking for unit files in
(higher priority first):
[????2.813612] systemd-sysv-generator[116]:?????/etc/systemd/system
[????2.813620] systemd-sysv-generator[116]:?????/run/systemd/system
[????2.813628] systemd-sysv-
generator[116]:?????/usr/local/lib/systemd/system
[????2.813635] systemd-sysv-generator[116]:?????/lib/systemd/system
[????2.813642] systemd-sysv-generator[116]:?????/usr/lib/systemd/system
[????2.813681] systemd-sysv-generator[116]: Looking for SysV init
scripts in:
[????2.813689] systemd-sysv-generator[116]:?????/etc/init.d
[????2.813699] systemd-sysv-generator[116]: Looking for SysV rcN.d
links in:
[????2.813706] systemd-sysv-generator[116]:?????/etc
[????2.815816] systemd-fstab-generator[112]: Found entry
what=/dev/mmcblk1p1 where=/boot type=vfat
[????2.819599] systemd-fstab-generator[112]: Checking was requested for
/dev/mmcblk1p1, but fsck.vfat does not exist: No such file or directory
[????2.874868] systemd-sysv-ge: 77 output lines suppressed due to
ratelimiting
[????2.959658] systemd-gpt-auto-generator[117]: Not a GPT partition
table, ignoring.
[????3.832303] systemd-journald[135]: Fixed max_use=98.5M
max_size=12.3M min_size=4.0M keep_free=147.8M
[????3.845615] systemd-journald[135]: Reserving 22435 entries in hash
table.
[????3.852075] systemd-journald[135]: Vacuuming...
[????3.855454] systemd-journald[135]: Vacuuming done, freed 0 bytes
[????3.861956] systemd-journald[135]: Flushing /dev/kmsg...
[????3.871445] systemd-journald[135]: Compressed data object 537 -> 288
[????3.899706] systemd-journald[135]: systemd-journald running as pid
135
[????4.454812] systemd-udevd[147]: starting version 215
[????4.611192] s5p-secss 10830000.sss: s5p-sss driver registered
[????4.626630] 12100000.phy supply vbus not found, using dummy
regulator
[????4.631925] 12100000.phy supply vbus-boost not found, using dummy
regulator
[????4.633739] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI)
Driver
[????4.638239] ehci-exynos: EHCI EXYNOS driver
[????4.642228] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[????4.646782] ohci-exynos: OHCI EXYNOS driver
[????4.660779] 12130000.phy supply vbus not found, using dummy
regulator
[????4.669297] exynos-ohci 12120000.usb: USB Host Controller
[????4.669734] exynos-ehci 12110000.usb: EHCI Host Controller
[????4.670063] exynos-ehci 12110000.usb: new USB bus registered,
assigned bus number 1
[????4.670250] exynos-ehci 12110000.usb: irq 89, io mem 0x12110000
[????4.693595] exynos-ohci 12120000.usb: new USB bus registered,
assigned bus number 2
[????4.698079] exynos-ehci 12110000.usb: USB 2.0 started, EHCI 1.00
[????4.698464] usb usb1: New USB device found, idVendor=1d6b,
idProduct=0002
[????4.698472] usb usb1: New USB device strings: Mfr=3, Product=2,
SerialNumber=1
[????4.698481] usb usb1: Product: EHCI Host Controller
[????4.698489] usb usb1: Manufacturer: Linux 4.8.0 ehci_hcd
[????4.698496] usb usb1: SerialNumber: 12110000.usb
[????4.699299] hub 1-0:1.0: USB hub found
[????4.699350] hub 1-0:1.0: 3 ports detected
[????4.742843] exynos-ohci 12120000.usb: irq 89, io mem 0x12120000
[????4.822232] usb usb2: New USB device found, idVendor=1d6b,
idProduct=0001
[????4.827543] usb usb2: New USB device strings: Mfr=3, Product=2,
SerialNumber=1
[????4.834815] usb usb2: Product: USB Host Controller
[????4.839569] usb usb2: Manufacturer: Linux 4.8.0 ohci_hcd
[????4.839580] usb usb2: SerialNumber: 12120000.usb
[????4.840406] hub 2-0:1.0: USB hub found
[????4.840468] hub 2-0:1.0: 3 ports detected
[????4.841589] 12500000.phy supply vbus not found, using dummy
regulator
[????4.841673] 12500000.phy supply vbus-boost not found, using dummy
regulator
[????4.842135] exynos-dwc3 soc:usb3-0: no suspend clk specified
[????4.843822] usb_phy_generic.0.auto supply vcc not found, using dummy
regulator
[????4.844425] usb_phy_generic.1.auto supply vcc not found, using dummy
regulator
[????4.845346] exynos-dwc3 soc:usb3-1: no suspend clk specified
[????4.848262] usb_phy_generic.2.auto supply vcc not found, using dummy
regulator
[????4.848573] usb_phy_generic.3.auto supply vcc not found, using dummy
regulator
[????4.873852] xhci-hcd xhci-hcd.4.auto: xHCI Host Controller
[????4.874040] xhci-hcd xhci-hcd.4.auto: new USB bus registered,
assigned bus number 3
[????4.874254] xhci-hcd xhci-hcd.4.auto: hcc params 0x0220f04c hci
version 0x100 quirks 0x00010010
[????4.874296] xhci-hcd xhci-hcd.4.auto: irq 135, io mem 0x12000000
[????4.874566] usb usb3: New USB device found, idVendor=1d6b,
idProduct=0002
[????4.874571] usb usb3: New USB device strings: Mfr=3, Product=2,
SerialNumber=1
[????4.874575] usb usb3: Product: xHCI Host Controller
[????4.874579] usb usb3: Manufacturer: Linux 4.8.0 xhci-hcd
[????4.874583] usb usb3: SerialNumber: xhci-hcd.4.auto
[????4.875065] hub 3-0:1.0: USB hub found
[????4.875105] hub 3-0:1.0: 1 port detected
[????4.875475] xhci-hcd xhci-hcd.4.auto: xHCI Host Controller
[????4.875623] xhci-hcd xhci-hcd.4.auto: new USB bus registered,
assigned bus number 4
[????4.875743] usb usb4: We don't know the algorithms for LPM for this
host, disabling LPM.
[????4.875926] usb usb4: New USB device found, idVendor=1d6b,
idProduct=0003
[????4.875930] usb usb4: New USB device strings: Mfr=3, Product=2,
SerialNumber=1
[????4.875934] usb usb4: Product: xHCI Host Controller
[????4.875938] usb usb4: Manufacturer: Linux 4.8.0 xhci-hcd
[????4.875942] usb usb4: SerialNumber: xhci-hcd.4.auto
[????4.876431] hub 4-0:1.0: USB hub found
[????4.876471] hub 4-0:1.0: 1 port detected
[????4.876897] xhci-hcd xhci-hcd.5.auto: xHCI Host Controller
[????4.877063] xhci-hcd xhci-hcd.5.auto: new USB bus registered,
assigned bus number 5
[????4.877266] xhci-hcd xhci-hcd.5.auto: hcc params 0x0220f04c hci
version 0x100 quirks 0x00010010
[????4.877299] xhci-hcd xhci-hcd.5.auto: irq 136, io mem 0x12400000
[????4.877525] usb usb5: New USB device found, idVendor=1d6b,
idProduct=0002
[????4.877530] usb usb5: New USB device strings: Mfr=3, Product=2,
SerialNumber=1
[????4.877534] usb usb5: Product: xHCI Host Controller
[????4.877538] usb usb5: Manufacturer: Linux 4.8.0 xhci-hcd
[????4.877541] usb usb5: SerialNumber: xhci-hcd.5.auto
[????4.878099] hub 5-0:1.0: USB hub found
[????4.878138] hub 5-0:1.0: 1 port detected
[????4.878494] xhci-hcd xhci-hcd.5.auto: xHCI Host Controller
[????4.878654] xhci-hcd xhci-hcd.5.auto: new USB bus registered,
assigned bus number 6
[????4.878769] usb usb6: We don't know the algorithms for LPM for this
host, disabling LPM.
[????4.878947] usb usb6: New USB device found, idVendor=1d6b,
idProduct=0003
[????4.878952] usb usb6: New USB device strings: Mfr=3, Product=2,
SerialNumber=1
[????4.878955] usb usb6: Product: xHCI Host Controller
[????4.878959] usb usb6: Manufacturer: Linux 4.8.0 xhci-hcd
[????4.878963] usb usb6: SerialNumber: xhci-hcd.5.auto
[????4.879480] hub 6-0:1.0: USB hub found
[????4.879520] hub 6-0:1.0: 1 port detected
[????5.304287] dma-pl330 3880000.adma: Loaded driver for PL330 DMAC-
241330
[????5.309497] dma-pl330 3880000.adma:??DBUFF-4x8bytes Num_Chans-6
Num_Peri-16 Num_Events-6
[????5.459652] EXT4-fs (mmcblk1p2): re-mounted. Opts: (null)
[????5.673544] FAT-fs (mmcblk1p1): utf8 is not a recommended IO charset
for FAT filesystems, filesystem will be case sensitive!
[????5.701124] FAT-fs (mmcblk1p1): Volume was not properly unmounted.
Some data may be corrupt. Please run fsck.
[????6.087658] systemd-journald[135]: Received request to flush runtime
journal from PID 1
[????6.095519] systemd-journald[135]: Vacuuming...
[????6.100071] systemd-journald[135]: Vacuuming done, freed 0 bytes
[????7.335312] RPC: Registered named UNIX socket transport module.
[????7.339802] RPC: Registered udp transport module.
[????7.344429] RPC: Registered tcp transport module.
[????7.349165] RPC: Registered tcp NFSv4.1 backchannel transport
module.
[????7.370961] FS-Cache: Loaded
[????7.406152] FS-Cache: Netfs 'nfs' registered for caching
[????7.453960] Installing knfsd (copyright (C) 1996 okir at monad.swb.de).
[????8.160157] random: crng init done
[????9.170682] usb usb5-port1: connect-debounce failed
[????9.170698] usb usb3-port1: connect-debounce failed

^ permalink raw reply

* [PATCH v2 4/4] ARM: dts: am4372: add DMA properties for tscadc
From: Mugunthan V N @ 2016-10-03 13:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003130318.12591-1-mugunthanvnm@ti.com>

Add DMA properties for tscadc

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 arch/arm/boot/dts/am4372.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi
index 0fadae5..6094d17 100644
--- a/arch/arm/boot/dts/am4372.dtsi
+++ b/arch/arm/boot/dts/am4372.dtsi
@@ -867,6 +867,8 @@
 			clocks = <&adc_tsc_fck>;
 			clock-names = "fck";
 			status = "disabled";
+			dmas = <&edma 53 0>, <&edma 57 0>;
+			dma-names = "fifo0", "fifo1";
 
 			tsc {
 				compatible = "ti,am3359-tsc";
-- 
2.10.0.372.g6fe1b14

^ permalink raw reply related

* [PATCH v2 3/4] ARM: dts: am33xx: add DMA properties for tscadc
From: Mugunthan V N @ 2016-10-03 13:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003130318.12591-1-mugunthanvnm@ti.com>

Add DMA properties for tscadc

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 arch/arm/boot/dts/am33xx.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 98748c6..6d607b8 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -917,6 +917,8 @@
 			interrupts = <16>;
 			ti,hwmods = "adc_tsc";
 			status = "disabled";
+			dmas = <&edma 53 0>, <&edma 57 0>;
+			dma-names = "fifo0", "fifo1";
 
 			tsc {
 				compatible = "ti,am3359-tsc";
-- 
2.10.0.372.g6fe1b14

^ permalink raw reply related

* [PATCH v2 2/4] drivers: iio: ti_am335x_adc: add dma support
From: Mugunthan V N @ 2016-10-03 13:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003130318.12591-1-mugunthanvnm@ti.com>

This patch adds the required pieces to ti_am335x_adc driver for
DMA support

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/iio/adc/ti_am335x_adc.c      | 145 ++++++++++++++++++++++++++++++++++-
 include/linux/mfd/ti_am335x_tscadc.h |   7 ++
 2 files changed, 149 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index c3cfacca..7e250be 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -30,10 +30,28 @@
 #include <linux/iio/buffer.h>
 #include <linux/iio/kfifo_buf.h>
 
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+
+#define DMA_BUFFER_SIZE		SZ_2K
+
+struct tiadc_dma {
+	struct dma_slave_config	conf;
+	struct dma_chan		*chan;
+	dma_addr_t		addr;
+	dma_cookie_t		cookie;
+	u8			*buf;
+	int			current_period;
+	int			period_size;
+	u8			fifo_thresh;
+};
+
 struct tiadc_device {
 	struct ti_tscadc_dev *mfd_tscadc;
+	struct tiadc_dma dma;
 	struct mutex fifo1_lock; /* to protect fifo access */
 	int channels;
+	int total_ch_enabled;
 	u8 channel_line[8];
 	u8 channel_step[8];
 	int buffer_en_ch_steps;
@@ -198,6 +216,67 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
 	return IRQ_HANDLED;
 }
 
+static void tiadc_dma_rx_complete(void *param)
+{
+	struct iio_dev *indio_dev = param;
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct tiadc_dma *dma = &adc_dev->dma;
+	u8 *data;
+	int i;
+
+	data = dma->buf + dma->current_period * dma->period_size;
+	dma->current_period = 1 - dma->current_period; /* swap the buffer ID */
+
+	for (i = 0; i < dma->period_size; i += indio_dev->scan_bytes) {
+		iio_push_to_buffers(indio_dev, data);
+		data += indio_dev->scan_bytes;
+	}
+}
+
+static int tiadc_start_dma(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct tiadc_dma *dma = &adc_dev->dma;
+	struct dma_async_tx_descriptor *desc;
+
+	dma->current_period = 0; /* We start to fill period 0 */
+	/*
+	 * Make the fifo thresh as the multiple of total number of
+	 * channels enabled, so make sure that cyclic DMA period
+	 * length is also a multiple of total number of channels
+	 * enabled. This ensures that no invalid data is reported
+	 * to the stack via iio_push_to_buffers().
+	 */
+	dma->fifo_thresh = rounddown(FIFO1_THRESHOLD + 1,
+				     adc_dev->total_ch_enabled) - 1;
+	/* Make sure that period length is multiple of fifo thresh level */
+	dma->period_size = rounddown(DMA_BUFFER_SIZE / 2,
+				    (dma->fifo_thresh + 1) * sizeof(u16));
+
+	dma->conf.src_maxburst = dma->fifo_thresh + 1;
+	dmaengine_slave_config(dma->chan, &dma->conf);
+
+	desc = dmaengine_prep_dma_cyclic(dma->chan, dma->addr,
+					 dma->period_size * 2,
+					 dma->period_size, DMA_DEV_TO_MEM,
+					 DMA_PREP_INTERRUPT);
+	if (!desc)
+		return -EBUSY;
+
+	desc->callback = tiadc_dma_rx_complete;
+	desc->callback_param = indio_dev;
+
+	dma->cookie = dmaengine_submit(desc);
+
+	dma_async_issue_pending(dma->chan);
+
+	tiadc_writel(adc_dev, REG_FIFO1THR, dma->fifo_thresh);
+	tiadc_writel(adc_dev, REG_DMA1REQ, dma->fifo_thresh);
+	tiadc_writel(adc_dev, REG_DMAENABLE_SET, DMA_FIFO1);
+
+	return 0;
+}
+
 static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
 {
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
@@ -218,20 +297,30 @@ static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
 static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
 {
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct tiadc_dma *dma = &adc_dev->dma;
+	unsigned int irq_enable;
 	unsigned int enb = 0;
 	u8 bit;
 
 	tiadc_step_config(indio_dev);
-	for_each_set_bit(bit, indio_dev->active_scan_mask, adc_dev->channels)
+	for_each_set_bit(bit, indio_dev->active_scan_mask, adc_dev->channels) {
 		enb |= (get_adc_step_bit(adc_dev, bit) << 1);
+		adc_dev->total_ch_enabled++;
+	}
 	adc_dev->buffer_en_ch_steps = enb;
 
+	if (dma->chan)
+		tiadc_start_dma(indio_dev);
+
 	am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, enb);
 
 	tiadc_writel(adc_dev,  REG_IRQSTATUS, IRQENB_FIFO1THRES
 				| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
-	tiadc_writel(adc_dev,  REG_IRQENABLE, IRQENB_FIFO1THRES
-				| IRQENB_FIFO1OVRRUN);
+
+	irq_enable = IRQENB_FIFO1OVRRUN;
+	if (!dma->chan)
+		irq_enable |= IRQENB_FIFO1THRES;
+	tiadc_writel(adc_dev,  REG_IRQENABLE, irq_enable);
 
 	return 0;
 }
@@ -239,12 +328,18 @@ static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
 static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
 {
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct tiadc_dma *dma = &adc_dev->dma;
 	int fifo1count, i, read;
 
 	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
 				IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
 	am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
 	adc_dev->buffer_en_ch_steps = 0;
+	adc_dev->total_ch_enabled = 0;
+	if (dma->chan) {
+		tiadc_writel(adc_dev, REG_DMAENABLE_CLEAR, 0x2);
+		dmaengine_terminate_async(dma->chan);
+	}
 
 	/* Flush FIFO of leftover data in the time it takes to disable adc */
 	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
@@ -430,6 +525,38 @@ static const struct iio_info tiadc_info = {
 	.driver_module = THIS_MODULE,
 };
 
+static int tiadc_request_dma(struct platform_device *pdev,
+			     struct tiadc_device *adc_dev)
+{
+	struct tiadc_dma	*dma = &adc_dev->dma;
+	dma_cap_mask_t		mask;
+
+	/* Default slave configuration parameters */
+	dma->conf.direction = DMA_DEV_TO_MEM;
+	dma->conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+	dma->conf.src_addr = adc_dev->mfd_tscadc->tscadc_phys_base + REG_FIFO1;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_CYCLIC, mask);
+
+	/* Get a channel for RX */
+	dma->chan = dma_request_chan(adc_dev->mfd_tscadc->dev, "fifo1");
+	if (!dma->chan)
+		return -ENODEV;
+
+	/* RX buffer */
+	dma->buf = dma_alloc_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
+				      &dma->addr, GFP_KERNEL);
+	if (!dma->buf)
+		goto err;
+
+	return 0;
+err:
+	dma_release_channel(dma->chan);
+
+	return -ENOMEM;
+}
+
 static int tiadc_parse_dt(struct platform_device *pdev,
 			  struct tiadc_device *adc_dev)
 {
@@ -512,8 +639,14 @@ static int tiadc_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, indio_dev);
 
+	err = tiadc_request_dma(pdev, adc_dev);
+	if (err && err != -ENODEV)
+		goto err_dma;
+
 	return 0;
 
+err_dma:
+	iio_device_unregister(indio_dev);
 err_buffer_unregister:
 	tiadc_iio_buffered_hardware_remove(indio_dev);
 err_free_channels:
@@ -525,8 +658,14 @@ static int tiadc_remove(struct platform_device *pdev)
 {
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct tiadc_dma *dma = &adc_dev->dma;
 	u32 step_en;
 
+	if (dma->chan) {
+		dma_free_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
+				  dma->buf, dma->addr);
+		dma_release_channel(dma->chan);
+	}
 	iio_device_unregister(indio_dev);
 	tiadc_iio_buffered_hardware_remove(indio_dev);
 	tiadc_channels_remove(indio_dev);
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index e45a208..b9a53e0 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -23,6 +23,8 @@
 #define REG_IRQENABLE		0x02C
 #define REG_IRQCLR		0x030
 #define REG_IRQWAKEUP		0x034
+#define REG_DMAENABLE_SET	0x038
+#define REG_DMAENABLE_CLEAR	0x03c
 #define REG_CTRL		0x040
 #define REG_ADCFSM		0x044
 #define REG_CLKDIV		0x04C
@@ -36,6 +38,7 @@
 #define REG_FIFO0THR		0xE8
 #define REG_FIFO1CNT		0xF0
 #define REG_FIFO1THR		0xF4
+#define REG_DMA1REQ		0xF8
 #define REG_FIFO0		0x100
 #define REG_FIFO1		0x200
 
@@ -126,6 +129,10 @@
 #define FIFOREAD_DATA_MASK (0xfff << 0)
 #define FIFOREAD_CHNLID_MASK (0xf << 16)
 
+/* DMA ENABLE/CLEAR Register */
+#define DMA_FIFO0		BIT(0)
+#define DMA_FIFO1		BIT(1)
+
 /* Sequencer Status */
 #define SEQ_STATUS BIT(5)
 #define CHARGE_STEP		0x11
-- 
2.10.0.372.g6fe1b14

^ permalink raw reply related

* [PATCH v2 1/4] mfd: ti_am335x_tscadc: store physical address
From: Mugunthan V N @ 2016-10-03 13:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003130318.12591-1-mugunthanvnm@ti.com>

store the physical address of the device in its priv to use it
for DMA addressing in the client drivers.

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 drivers/mfd/ti_am335x_tscadc.c       | 1 +
 include/linux/mfd/ti_am335x_tscadc.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index c8f027b..0f3fab4 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -183,6 +183,7 @@ static	int ti_tscadc_probe(struct platform_device *pdev)
 		tscadc->irq = err;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	tscadc->tscadc_phys_base = res->start;
 	tscadc->tscadc_base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(tscadc->tscadc_base))
 		return PTR_ERR(tscadc->tscadc_base);
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index 7f55b8b..e45a208 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -155,6 +155,7 @@ struct ti_tscadc_dev {
 	struct device *dev;
 	struct regmap *regmap;
 	void __iomem *tscadc_base;
+	phys_addr_t tscadc_phys_base;
 	int irq;
 	int used_cells;	/* 1-2 */
 	int tsc_wires;
-- 
2.10.0.372.g6fe1b14

^ permalink raw reply related

* [PATCH v2 0/4] Add DMA support for ti_am335x_adc driver
From: Mugunthan V N @ 2016-10-03 13:03 UTC (permalink / raw)
  To: linux-arm-kernel

The ADC has a 64 work depth fifo length which holds the ADC data
till the CPU reads. So when a user program needs a large ADC data
to operate on, then it has to do multiple reads to get its
buffer. Currently if the application asks for 4 samples per
channel with all 8 channels are enabled, kernel can provide only
3 samples per channel when all 8 channels are enabled (logs at
[1]). So with DMA support user can request for large number of
samples at a time (logs at [2]).

Tested the patch on AM437x-gp-evm and AM335x Boneblack with the
patch [3] to enable ADC and pushed a branch for testing [4]

Changes from Initial version:
* Changed DMA api from dma_request_slave_channel_compat() to
  dma_request_chan()
* Changed variable names to have more clear information as per
  comments from Peter.

[1] - http://pastebin.ubuntu.com/23211490/
[2] - http://pastebin.ubuntu.com/23269792/
[3] - http://pastebin.ubuntu.com/23211494/
[4] - git://git.ti.com/~mugunthanvnm/ti-linux-kernel/linux.git iio-dma-v2

Mugunthan V N (4):
  mfd: ti_am335x_tscadc: store physical address
  drivers: iio: ti_am335x_adc: add dma support
  ARM: dts: am33xx: add DMA properties for tscadc
  ARM: dts: am4372: add DMA properties for tscadc

 arch/arm/boot/dts/am33xx.dtsi        |   2 +
 arch/arm/boot/dts/am4372.dtsi        |   2 +
 drivers/iio/adc/ti_am335x_adc.c      | 145 ++++++++++++++++++++++++++++++++++-
 drivers/mfd/ti_am335x_tscadc.c       |   1 +
 include/linux/mfd/ti_am335x_tscadc.h |   8 ++
 5 files changed, 155 insertions(+), 3 deletions(-)

-- 
2.10.0.372.g6fe1b14

^ permalink raw reply

* [PATCH] drm/sun4i: Check that the plane coordinates are not negative
From: Maxime Ripard @ 2016-10-03 12:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160930180826.169e3daf@bbrezillon>

Hi Boris,

On Fri, Sep 30, 2016 at 06:08:26PM +0200, Boris Brezillon wrote:
> On Fri, 30 Sep 2016 16:33:20 +0200
> Maxime Ripard <maxime.ripard@free-electrons.com> wrote:
> 
> > Our planes cannot be set at negative coordinates. Make sure we reject such
> > configuration.
> > 
> > Reported-by: Boris Brezillon <boris.brezillon@free-electrons.com>
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  drivers/gpu/drm/sun4i/sun4i_layer.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
> > index f0035bf5efea..f5463c4c2cde 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
> > @@ -29,6 +29,9 @@ struct sun4i_plane_desc {
> >  static int sun4i_backend_layer_atomic_check(struct drm_plane *plane,
> >  					    struct drm_plane_state *state)
> >  {
> > +	if ((state->crtc_x < 0) || (state->crtc_y < 0))
> > +		return -EINVAL;
> > +
> 
> Hm, I think it's a perfectly valid use case from the DRM framework and
> DRM user PoV: you may want to place your plane at a negative CRTC
> offset (which means part of the plane will be hidden).
> 
> Maybe I'm wrong, but it seems you can support that by adapting the
> start address of your framebuffer pointer and the layer size.

Indeed, that would probably work. This is even somewhat what we've
been using to implement the VGA hack we use on the CHIP.

Can you send that patch?

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161003/32b3fe92/attachment.sig>

^ permalink raw reply

* [PATCH] Adding Support for Coresight Components on Zynq 7000.
From: Muhammad Abdul WAHAB @ 2016-10-03 12:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160930165325.GA7630@xsjsorenbubuntu>

Hi S?ren,

 > I tried to refresh my Zynq knowledge a bit. The clkc provides the
 > dbg_trc clock, and that is the clock you need (not fclk). I couldn't
 > find it in the binding (I guess I messed that up), but apparently,
 > you can provide a 'trace_emio_clk' as input to the clkc node in the
 > Zynq DT. Then, with the muxes correctly configured (FSBL should do
 > that if you select the EMIO trace clock in Vivado), the dbg_trc
 > output of the clkc should be that EMIO clock. And the dbg_trc output
 > of the clkc is what should be consumed by the tpiu node. Though, as
 > I see it the binding/driver for the TPIU do not support that.
 >
 > I.e.
 > In the clkc description you'd have to add 'trace_emio_clk' to the
 > clock-names property together with a matching reference in the 'clocks'
 > property. As this change would be specific to local setups, this is not
 > really appropriate for upstream.
 >
 > Then, for the trace clock, ideally the TPIU would consume and enable it
 > as needed.

Thank you very much for this. I will have a look into it.
Below is the patch without TPIU, is it possible to submit it ? I will 
submit the TPIU part very soon once I manage to get it working.

 > Unfortunately, this is not how it works. The DT bindings are not a
 > recommendation. The DT description must follow the binding, otherwise
 > drivers will not work correctly, or best case, just ignore what you put
 > there.

Thanks. The idea of including TPIU part was to get feedback as I am far 
from being an expert on DT.

 > As I don't see this in the coresight binding, I doubt that it has any
 > effect or should be here.

That's what I was thinking also. I will re-look into TPIU part and send 
it soon. Besides, if I want to ask you a question regarding TPIU or DT, 
can I contact you alone or should I keep sending it to all the CS/DT 
maintainers ?

Thanks,
M.Abdul WAHAB
---
--- linux-4.7/arch/arm/boot/dts/zynq-7000.dtsi.orig    2016-07-24 
21:23:50.000000000 +0200
+++ linux-4.7/arch/arm/boot/dts/zynq-7000.dtsi    2016-10-03 
14:38:00.164515838 +0200
@@ -96,6 +96,57 @@
              rx-fifo-depth = <0x40>;
          };

+        etb at F8801000 {
+            compatible = "arm,coresight-etb10", "arm,primecell";
+            reg = <0xf8801000 0x1000>;
+
+            coresight-default-sink;
+            clocks = <&clkc 47>;
+            clock-names = "apb_pclk";
+
+            port {
+                etb_in_port: endpoint at 0 {
+                    slave-mode;
+                    remote-endpoint = <&replicator_out_port0>;
+                };
+            };
+        };
+
+        funnel at F8804000 {
+            compatible = "arm,coresight-funnel", "arm,primecell";
+            reg = <0xf8804000 0x1000>;
+
+            clocks = <&clkc 47>;
+            clock-names = "apb_pclk";
+            ports {
+                #address-cells = <0x1>;
+                #size-cells = <0x0>;
+
+                port at 0 {
+                    reg = <0x0>;
+                    funnel_out_port0: endpoint {
+                        remote-endpoint = <&replicator_in_port0>;
+                    };
+                };
+
+                port at 1 {
+                    reg = <0x0>;
+                    funnel_in_port0: endpoint {
+                        slave-mode;
+                        remote-endpoint = <&ptm0_out_port>;
+                    };
+                };
+
+                port at 2 {
+                    reg = <0x1>;
+                    funnel_in_port1: endpoint {
+                        slave-mode;
+                        remote-endpoint = <&ptm1_out_port>;
+                    };
+                };
+            };
+        };
+
          gpio0: gpio at e000a000 {
              compatible = "xlnx,zynq-gpio-1.0";
              #gpio-cells = <2>;
@@ -311,6 +362,67 @@
              clocks = <&clkc 4>;
          };

+        ptm0 at F889C000 {
+            compatible = "arm,coresight-etm3x", "arm,primecell";
+            reg = <0xf889c000 0x1000>;
+
+            cpu = <&cpu0>;
+            clocks = <&clkc 47>;
+            clock-names = "apb_pclk";
+
+            port {
+                ptm0_out_port: endpoint {
+                    remote-endpoint = <&funnel_in_port0>;
+                };
+            };
+        };
+
+        ptm1 at F889D000 {
+            compatible = "arm,coresight-etm3x", "arm,primecell";
+            reg = <0xf889d000 0x1000>;
+
+            cpu = <&cpu1>;
+            clocks = <&clkc 47>;
+            clock-names = "apb_pclk";
+
+            port {
+                ptm1_out_port: endpoint {
+                    remote-endpoint = <&funnel_in_port1>;
+                };
+            };
+        };
+
+        replicator {
+            compatible = "arm,coresight-replicator";
+
+            ports {
+                #address-cells = <0x1>;
+                #size-cells = <0x0>;
+
+                port at 0 {
+                    reg = <0x0>;
+                    replicator_out_port0: endpoint {
+                        remote-endpoint = <&etb_in_port>;
+                    };
+                };
+
+                port at 1 {
+                    reg = <0x1>;
+                    replicator_out_port1: endpoint {
+                        remote-endpoint = <&tpiu_in_port>;
+                    };
+                };
+
+                port at 2 {
+                    reg = <0x0>;
+                    replicator_in_port0: endpoint {
+                        slave-mode;
+                        remote-endpoint = <&funnel_out_port0>;
+                    };
+                };
+            };
+        };
+
          ttc0: timer at f8001000 {
              interrupt-parent = <&intc>;
              interrupts = <0 10 4>,

^ permalink raw reply

* [PATCH v1 2/2] spi: spi-fsl-dspi: Add DMA support for Vybrid
From: Sanchayan Maity @ 2016-10-03 12:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <63fc108e2df00d2297a9b7014955f203bc802f34.1475498805.git.maitysanchayan@gmail.com>

Add DMA support for Vybrid.

Signed-off-by: Sanchayan Maity <maitysanchayan@gmail.com>
---
 drivers/spi/spi-fsl-dspi.c | 293 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 293 insertions(+)

diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 9e9dadb..ada50ee 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -15,6 +15,8 @@
 
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
@@ -40,6 +42,7 @@
 #define TRAN_STATE_WORD_ODD_NUM	0x04
 
 #define DSPI_FIFO_SIZE			4
+#define DSPI_DMA_BUFSIZE		(DSPI_FIFO_SIZE * 1024)
 
 #define SPI_MCR		0x00
 #define SPI_MCR_MASTER		(1 << 31)
@@ -71,6 +74,11 @@
 #define SPI_SR_EOQF		0x10000000
 #define SPI_SR_TCFQF		0x80000000
 
+#define SPI_RSER_TFFFE		BIT(25)
+#define SPI_RSER_TFFFD		BIT(24)
+#define SPI_RSER_RFDFE		BIT(17)
+#define SPI_RSER_RFDFD		BIT(16)
+
 #define SPI_RSER		0x30
 #define SPI_RSER_EOQFE		0x10000000
 #define SPI_RSER_TCFQE		0x80000000
@@ -108,6 +116,8 @@
 
 #define SPI_TCR_TCNT_MAX	0x10000
 
+#define DMA_COMPLETION_TIMEOUT	msecs_to_jiffies(3000)
+
 struct chip_data {
 	u32 mcr_val;
 	u32 ctar_val;
@@ -117,6 +127,7 @@ struct chip_data {
 enum dspi_trans_mode {
 	DSPI_EOQ_MODE = 0,
 	DSPI_TCFQ_MODE,
+	DSPI_DMA_MODE,
 };
 
 struct fsl_dspi_devtype_data {
@@ -139,6 +150,22 @@ static const struct fsl_dspi_devtype_data ls2085a_data = {
 	.max_clock_factor = 8,
 };
 
+struct fsl_dspi_dma {
+	u32 curr_xfer_len;
+
+	u32 *tx_dma_buf;
+	struct dma_chan *chan_tx;
+	dma_addr_t tx_dma_phys;
+	struct completion cmd_tx_complete;
+	struct dma_async_tx_descriptor *tx_desc;
+
+	u32 *rx_dma_buf;
+	struct dma_chan *chan_rx;
+	dma_addr_t rx_dma_phys;
+	struct completion cmd_rx_complete;
+	struct dma_async_tx_descriptor *rx_desc;
+};
+
 struct fsl_dspi {
 	struct spi_master	*master;
 	struct platform_device	*pdev;
@@ -165,6 +192,7 @@ struct fsl_dspi {
 	u32			waitflags;
 
 	u32			spi_tcnt;
+	struct fsl_dspi_dma	*dma;
 };
 
 static inline int is_double_byte_mode(struct fsl_dspi *dspi)
@@ -368,6 +396,264 @@ static void dspi_tcfq_read(struct fsl_dspi *dspi)
 	dspi_data_from_popr(dspi, rx_word);
 }
 
+static void dspi_tx_dma_callback(void *arg)
+{
+	struct fsl_dspi *dspi = arg;
+	struct fsl_dspi_dma *dma = dspi->dma;
+
+	complete(&dma->cmd_tx_complete);
+}
+
+static void dspi_rx_dma_callback(void *arg)
+{
+	struct fsl_dspi *dspi = arg;
+	struct fsl_dspi_dma *dma = dspi->dma;
+	int rx_word;
+	int i, len;
+	u16 d;
+
+	rx_word = is_double_byte_mode(dspi);
+
+	len = rx_word ? (dma->curr_xfer_len / 2) : dma->curr_xfer_len;
+
+	if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) {
+		for (i = 0; i < len; i++) {
+			d = dspi->dma->rx_dma_buf[i];
+			rx_word ? (*(u16 *)dspi->rx = d) :
+						(*(u8 *)dspi->rx = d);
+			dspi->rx += rx_word + 1;
+		}
+	}
+
+	complete(&dma->cmd_rx_complete);
+}
+
+static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi)
+{
+	struct fsl_dspi_dma *dma = dspi->dma;
+	struct device *dev = &dspi->pdev->dev;
+	int time_left;
+	int tx_word;
+	int i, len;
+	u16 val;
+
+	tx_word = is_double_byte_mode(dspi);
+
+	len = tx_word ? (dma->curr_xfer_len / 2) : dma->curr_xfer_len;
+
+	for (i = 0; i < len - 1; i++) {
+		val = tx_word ? *(u16 *) dspi->tx : *(u8 *) dspi->tx;
+		dspi->dma->tx_dma_buf[i] =
+			SPI_PUSHR_TXDATA(val) | SPI_PUSHR_PCS(dspi->cs) |
+			SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT;
+		dspi->tx += tx_word + 1;
+	}
+
+	val = tx_word ? *(u16 *) dspi->tx : *(u8 *) dspi->tx;
+	dspi->dma->tx_dma_buf[i] = SPI_PUSHR_TXDATA(val) |
+					SPI_PUSHR_PCS(dspi->cs) |
+					SPI_PUSHR_CTAS(0);
+	dspi->tx += tx_word + 1;
+
+	dma->tx_desc = dmaengine_prep_slave_single(dma->chan_tx,
+					dma->tx_dma_phys,
+					DSPI_DMA_BUFSIZE, DMA_MEM_TO_DEV,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!dma->tx_desc) {
+		dev_err(dev, "Not able to get desc for DMA xfer\n");
+		return -EIO;
+	}
+
+	dma->tx_desc->callback = dspi_tx_dma_callback;
+	dma->tx_desc->callback_param = dspi;
+	if (dma_submit_error(dmaengine_submit(dma->tx_desc))) {
+		dev_err(dev, "DMA submit failed\n");
+		return -EINVAL;
+	}
+
+	dma->rx_desc = dmaengine_prep_slave_single(dma->chan_rx,
+					dma->rx_dma_phys,
+					DSPI_DMA_BUFSIZE, DMA_DEV_TO_MEM,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!dma->rx_desc) {
+		dev_err(dev, "Not able to get desc for DMA xfer\n");
+		return -EIO;
+	}
+
+	dma->rx_desc->callback = dspi_rx_dma_callback;
+	dma->rx_desc->callback_param = dspi;
+	if (dma_submit_error(dmaengine_submit(dma->rx_desc))) {
+		dev_err(dev, "DMA submit failed\n");
+		return -EINVAL;
+	}
+
+	reinit_completion(&dspi->dma->cmd_rx_complete);
+	reinit_completion(&dspi->dma->cmd_tx_complete);
+
+	dma_async_issue_pending(dma->chan_rx);
+	dma_async_issue_pending(dma->chan_tx);
+
+	time_left = wait_for_completion_timeout(&dspi->dma->cmd_tx_complete,
+					DMA_COMPLETION_TIMEOUT);
+	if (time_left == 0) {
+		dev_err(dev, "DMA tx timeout\n");
+		dmaengine_terminate_all(dma->chan_tx);
+		dmaengine_terminate_all(dma->chan_rx);
+		return -ETIMEDOUT;
+	}
+
+	time_left = wait_for_completion_timeout(&dspi->dma->cmd_rx_complete,
+					DMA_COMPLETION_TIMEOUT);
+	if (time_left == 0) {
+		dev_err(dev, "DMA rx timeout\n");
+		dmaengine_terminate_all(dma->chan_tx);
+		dmaengine_terminate_all(dma->chan_rx);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int dspi_dma_xfer(struct fsl_dspi *dspi)
+{
+	struct fsl_dspi_dma *dma = dspi->dma;
+	struct device *dev = &dspi->pdev->dev;
+	int curr_remaining_bytes;
+	int ret = 0;
+
+	curr_remaining_bytes = dspi->len;
+	while (curr_remaining_bytes) {
+		regmap_write(dspi->regmap, SPI_RSER, 0);
+		regmap_write(dspi->regmap, SPI_RSER,
+			SPI_RSER_TFFFE | SPI_RSER_TFFFD |
+			SPI_RSER_RFDFE | SPI_RSER_RFDFD);
+
+		/* Check if current transfer fits the DMA buffer */
+		dma->curr_xfer_len = curr_remaining_bytes;
+		if (curr_remaining_bytes > DSPI_DMA_BUFSIZE / sizeof(u32))
+			dma->curr_xfer_len = DSPI_DMA_BUFSIZE / sizeof(u32);
+
+		ret = dspi_next_xfer_dma_submit(dspi);
+		if (ret) {
+			dev_err(dev, "DMA transfer failed\n");
+			goto exit;
+
+		} else {
+			curr_remaining_bytes -= dma->curr_xfer_len;
+			if (curr_remaining_bytes < 0)
+				curr_remaining_bytes = 0;
+			dspi->len = curr_remaining_bytes;
+		}
+	}
+
+exit:
+	return ret;
+}
+
+static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
+{
+	struct fsl_dspi_dma *dma;
+	struct dma_slave_config cfg;
+	struct device *dev = &dspi->pdev->dev;
+	int ret;
+
+	dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
+	if (!dma)
+		return -ENOMEM;
+
+	dma->chan_rx = dma_request_slave_channel(dev, "rx");
+	if (!dma->chan_rx) {
+		dev_err(dev, "rx dma channel not available\n");
+		ret = -ENODEV;
+		return ret;
+	}
+
+	dma->chan_tx = dma_request_slave_channel(dev, "tx");
+	if (!dma->chan_tx) {
+		dev_err(dev, "tx dma channel not available\n");
+		ret = -ENODEV;
+		goto err_tx_channel;
+	}
+
+	dma->tx_dma_buf = dma_alloc_coherent(dev, DSPI_DMA_BUFSIZE,
+					&dma->tx_dma_phys, GFP_KERNEL);
+	if (!dma->tx_dma_buf) {
+		ret = -ENOMEM;
+		goto err_tx_dma_buf;
+	}
+
+	dma->rx_dma_buf = dma_alloc_coherent(dev, DSPI_DMA_BUFSIZE,
+					&dma->rx_dma_phys, GFP_KERNEL);
+	if (!dma->rx_dma_buf) {
+		ret = -ENOMEM;
+		goto err_rx_dma_buf;
+	}
+
+	cfg.src_addr = phy_addr + SPI_POPR;
+	cfg.dst_addr = phy_addr + SPI_PUSHR;
+	cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	cfg.src_maxburst = 1;
+	cfg.dst_maxburst = 1;
+
+	cfg.direction = DMA_DEV_TO_MEM;
+	ret = dmaengine_slave_config(dma->chan_rx, &cfg);
+	if (ret) {
+		dev_err(dev, "can't configure rx dma channel\n");
+		ret = -EINVAL;
+		goto err_slave_config;
+	}
+
+	cfg.direction = DMA_MEM_TO_DEV;
+	ret = dmaengine_slave_config(dma->chan_tx, &cfg);
+	if (ret) {
+		dev_err(dev, "can't configure tx dma channel\n");
+		ret = -EINVAL;
+		goto err_slave_config;
+	}
+
+	dspi->dma = dma;
+	dspi->devtype_data->trans_mode = DSPI_DMA_MODE;
+	init_completion(&dma->cmd_tx_complete);
+	init_completion(&dma->cmd_rx_complete);
+
+	return 0;
+
+err_slave_config:
+	devm_kfree(dev, dma->rx_dma_buf);
+err_rx_dma_buf:
+	devm_kfree(dev, dma->tx_dma_buf);
+err_tx_dma_buf:
+	dma_release_channel(dma->chan_tx);
+err_tx_channel:
+	dma_release_channel(dma->chan_rx);
+
+	devm_kfree(dev, dma);
+	dspi->dma = NULL;
+
+	return ret;
+}
+
+static void dspi_release_dma(struct fsl_dspi *dspi)
+{
+	struct fsl_dspi_dma *dma = dspi->dma;
+	struct device *dev = &dspi->pdev->dev;
+
+	if (dma) {
+		if (dma->chan_tx) {
+			dma_unmap_single(dev, dma->tx_dma_phys,
+					DSPI_DMA_BUFSIZE, DMA_TO_DEVICE);
+			dma_release_channel(dma->chan_tx);
+		}
+
+		if (dma->chan_rx) {
+			dma_unmap_single(dev, dma->rx_dma_phys,
+					DSPI_DMA_BUFSIZE, DMA_FROM_DEVICE);
+			dma_release_channel(dma->chan_rx);
+		}
+	}
+}
+
 static int dspi_transfer_one_message(struct spi_master *master,
 		struct spi_message *message)
 {
@@ -424,6 +710,9 @@ static int dspi_transfer_one_message(struct spi_master *master,
 			regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_TCFQE);
 			dspi_tcfq_write(dspi);
 			break;
+		case DSPI_DMA_MODE:
+			status = dspi_dma_xfer(dspi);
+			goto out;
 		default:
 			dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n",
 				trans_mode);
@@ -730,6 +1019,9 @@ static int dspi_probe(struct platform_device *pdev)
 	}
 	clk_prepare_enable(dspi->clk);
 
+	if (dspi_request_dma(dspi, res->start))
+		dev_warn(&pdev->dev, "can't get dma channels\n");
+
 	master->max_speed_hz =
 		clk_get_rate(dspi->clk) / dspi->devtype_data->max_clock_factor;
 
@@ -758,6 +1050,7 @@ static int dspi_remove(struct platform_device *pdev)
 	struct fsl_dspi *dspi = spi_master_get_devdata(master);
 
 	/* Disconnect from the SPI framework */
+	dspi_release_dma(dspi);
 	clk_disable_unprepare(dspi->clk);
 	spi_unregister_master(dspi->master);
 	spi_master_put(dspi->master);
-- 
2.10.0

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox