linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/20] Add QCOM QPIC NAND support
@ 2017-08-05 16:19 Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 01/20] mtd: nand: qcom: program NAND_DEV_CMD_VLD register Abhishek Sahu
                   ` (19 more replies)
  0 siblings, 20 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

* v3:

1. Removed the patches already applied to linux-next and
   rebased the remaining patches on [1]
2. Reordered the patches and put the BAM DMA changes [2]
   dependent patches and compatible string patches in last
3. Removed the register offsets array and used the dev_cmd offsets
4. Changed some macro names to small letters for better code readability
5. Changed the compatible string to SoC specific
6. Did minor code changes for adding comment, error handling, structure names
7. Combined raw write (patch#18) and passing flag parameter (patch#22) patch
   into one
8. Made separate patch for compatible string and NAND properties
9. Made separate patch for BAM command descriptor and data descriptors handling
10. Changed commit message for some of the patches
11. Addressed review comments given in v2
12. Added Reviewed-by of Archit for some of the patches from v2
13. All the MTD tests are working fine for IPQ8064 AP148, IPQ4019 DK04 and
    IPQ8074 HK01 boards for v3 patches

[1] http://git.infradead.org/l2-mtd.git/shortlog/refs/heads/nand/next
[2] http://www.spinics.net/lists/dmaengine/msg13662.html

* v2:

1. Addressed the review comments given in v1
2. Removed the DMA coherent buffer for register read and used
   streaming DMA API’s
3. Reorganized the NAND read and write functions
4. Separated patch for driver and documentation changes
5. Changed the compatible string for EBI2

* v1:

http://www.spinics.net/lists/devicetree/msg183706.html

Abhishek Sahu (20):
  mtd: nand: qcom: program NAND_DEV_CMD_VLD register
  mtd: nand: qcom: support for NAND controller properties
  mtd: nand: qcom: add bam property for QPIC NAND controller
  mtd: nand: qcom: add and initialize QPIC DMA resources
  mtd: nand: qcom: DMA mapping support for register read buffer
  mtd: nand: qcom: allocate BAM transaction
  mtd: nand: qcom: add BAM DMA descriptor handling
  mtd: nand: qcom: support for passing flags in transfer functions
  mtd: nand: qcom: support for read location registers
  mtd: nand: qcom: erased codeword detection configuration
  mtd: nand: qcom: enable BAM or ADM mode
  mtd: nand: qcom: QPIC data descriptors handling
  mtd: nand: qcom: support for different DEV_CMD register offsets
  mtd: nand: qcom: add command elements in BAM transaction
  mtd: nand: qcom: support for command descriptor formation
  dt-bindings: qcom_nandc: fix the ipq806x device tree example
  dt-bindings: qcom_nandc: IPQ4019 QPIC NAND documentation
  dt-bindings: qcom_nandc: IPQ8074 QPIC NAND documentation
  mtd: nand: qcom: Support for IPQ4019 QPIC NAND controller
  mtd: nand: qcom: Support for IPQ8074 QPIC NAND controller

 .../devicetree/bindings/mtd/qcom_nandc.txt         |  63 +-
 drivers/mtd/nand/qcom_nandc.c                      | 863 ++++++++++++++++++---
 2 files changed, 814 insertions(+), 112 deletions(-)

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 01/20] mtd: nand: qcom: program NAND_DEV_CMD_VLD register
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-10  9:42   ` Boris Brezillon
  2017-08-05 16:19 ` [PATCH v3 02/20] mtd: nand: qcom: support for NAND controller properties Abhishek Sahu
                   ` (18 subsequent siblings)
  19 siblings, 1 reply; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu, stable

The NAND page read fails without complete boot chain since
NAND_DEV_CMD_VLD value is not proper. The default power on reset
value for this register is

    0xe - ERASE_START_VALID | WRITE_START_VALID | READ_STOP_VALID

The READ_START_VALID should be enabled for sending PAGE_READ
command. READ_STOP_VALID should be cleared since normal NAND
page read does not require READ_STOP command.

Fixes: c76b78d8ec05a ("mtd: nand: Qualcomm NAND controller driver")
Cc: stable@vger.kernel.org
Reviewed-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/mtd/nand/qcom_nandc.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index 0289f09..7406019 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -110,6 +110,10 @@
 
 /* NAND_DEV_CMD_VLD bits */
 #define	READ_START_VLD			0
+#define	READ_STOP_VALID			1
+#define	WRITE_START_VALID		2
+#define	ERASE_START_VALID		3
+#define	SEQ_READ_START_VLD		4
 
 /* NAND_EBI2_ECC_BUF_CFG bits */
 #define	NUM_STEPS			0
@@ -148,6 +152,12 @@
 #define	FETCH_ID			0xb
 #define	RESET_DEVICE			0xd
 
+/* Default Value for NAND_DEV_CMD_VLD */
+#define NAND_DEV_CMD_VLD_VAL		(BIT(READ_START_VLD)	| \
+					 BIT(WRITE_START_VALID)	| \
+					 BIT(ERASE_START_VALID)	| \
+					 BIT(SEQ_READ_START_VLD))
+
 /*
  * the NAND controller performs reads/writes with ECC in 516 byte chunks.
  * the driver calls the chunks 'step' or 'codeword' interchangeably
@@ -1995,13 +2005,14 @@ static int qcom_nandc_setup(struct qcom_nand_controller *nandc)
 {
 	/* kill onenand */
 	nandc_write(nandc, SFLASHC_BURST_CFG, 0);
+	nandc_write(nandc, NAND_DEV_CMD_VLD, NAND_DEV_CMD_VLD_VAL);
 
 	/* enable ADM DMA */
 	nandc_write(nandc, NAND_FLASH_CHIP_SELECT, DM_EN);
 
 	/* save the original values of these registers */
 	nandc->cmd1 = nandc_read(nandc, NAND_DEV_CMD1);
-	nandc->vld = nandc_read(nandc, NAND_DEV_CMD_VLD);
+	nandc->vld = NAND_DEV_CMD_VLD_VAL;
 
 	return 0;
 }
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 02/20] mtd: nand: qcom: support for NAND controller properties
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 01/20] mtd: nand: qcom: program NAND_DEV_CMD_VLD register Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 03/20] mtd: nand: qcom: add bam property for QPIC NAND controller Abhishek Sahu
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

Currently driver data is being assigned directly with ECC modes.
Now, the plan is to add more NAND controller versions which will
have different properties. This patch reorganizes the current driver
data assignment by creating NAND controller properties structure
which will contain all properties specific to NAND controller.

Reviewed-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/mtd/nand/qcom_nandc.c | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index 7406019..4dc6b7e 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -242,7 +242,7 @@ struct nandc_regs {
  *				writes. contains the register values to be
  *				written to controller
  * @cmd1/vld:			some fixed controller register values
- * @ecc_modes:			supported ECC modes by the current controller,
+ * @props:			properties of current NAND controller,
  *				initialized via DT match data
  */
 struct qcom_nand_controller {
@@ -273,7 +273,7 @@ struct qcom_nand_controller {
 	struct nandc_regs *regs;
 
 	u32 cmd1, vld;
-	u32 ecc_modes;
+	const struct qcom_nandc_props *props;
 };
 
 /*
@@ -326,6 +326,15 @@ struct qcom_nand_host {
 	u32 clrreadstatus;
 };
 
+/*
+ * This data type corresponds to the nand controller properties which varies
+ * among different NAND controllers.
+ * @ecc_modes - ecc mode for NAND
+ */
+struct qcom_nandc_props {
+	u32 ecc_modes;
+};
+
 static inline struct qcom_nand_host *to_qcom_nand_host(struct nand_chip *chip)
 {
 	return container_of(chip, struct qcom_nand_host, chip);
@@ -1827,7 +1836,7 @@ static int qcom_nand_host_setup(struct qcom_nand_host *host)
 		 * uses lesser bytes for ECC. If RS is used, the ECC bytes is
 		 * always 10 bytes
 		 */
-		if (nandc->ecc_modes & ECC_BCH_4BIT) {
+		if (nandc->props->ecc_modes & ECC_BCH_4BIT) {
 			/* BCH */
 			host->bch_enabled = true;
 			ecc_mode = 0;
@@ -2174,7 +2183,7 @@ static int qcom_nandc_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	nandc->ecc_modes = (unsigned long)dev_data;
+	nandc->props = dev_data;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	nandc->base = devm_ioremap_resource(dev, res);
@@ -2243,15 +2252,18 @@ static int qcom_nandc_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#define EBI2_NANDC_ECC_MODES	(ECC_RS_4BIT | ECC_BCH_8BIT)
+static const struct qcom_nandc_props ipq806x_nandc_props = {
+	.ecc_modes = (ECC_RS_4BIT | ECC_BCH_8BIT),
+};
 
 /*
  * data will hold a struct pointer containing more differences once we support
  * more controller variants
  */
 static const struct of_device_id qcom_nandc_of_match[] = {
-	{	.compatible = "qcom,ipq806x-nand",
-		.data = (void *)EBI2_NANDC_ECC_MODES,
+	{
+		.compatible = "qcom,ipq806x-nand",
+		.data = &ipq806x_nandc_props,
 	},
 	{}
 };
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 03/20] mtd: nand: qcom: add bam property for QPIC NAND controller
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 01/20] mtd: nand: qcom: program NAND_DEV_CMD_VLD register Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 02/20] mtd: nand: qcom: support for NAND controller properties Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 04/20] mtd: nand: qcom: add and initialize QPIC DMA resources Abhishek Sahu
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

The current driver only supports EBI2 NAND controller which uses
ADM DMA. The latest QCOM SoC uses QPIC NAND controller with BAM
DMA. NAND registers and programming sequence are same for EBI2
and QPIC NAND so the same driver can support QPIC NAND also by
adding the BAM DMA support. This patch adds the is_bam in NAND
property which will be checked for determining the DMA engine type.

Reviewed-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/mtd/nand/qcom_nandc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index 4dc6b7e..08cda7d 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -330,9 +330,11 @@ struct qcom_nand_host {
  * This data type corresponds to the nand controller properties which varies
  * among different NAND controllers.
  * @ecc_modes - ecc mode for NAND
+ * @is_bam - whether NAND controller is using BAM
  */
 struct qcom_nandc_props {
 	u32 ecc_modes;
+	bool is_bam;
 };
 
 static inline struct qcom_nand_host *to_qcom_nand_host(struct nand_chip *chip)
@@ -2254,6 +2256,7 @@ static int qcom_nandc_remove(struct platform_device *pdev)
 
 static const struct qcom_nandc_props ipq806x_nandc_props = {
 	.ecc_modes = (ECC_RS_4BIT | ECC_BCH_8BIT),
+	.is_bam = false,
 };
 
 /*
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 04/20] mtd: nand: qcom: add and initialize QPIC DMA resources
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
                   ` (2 preceding siblings ...)
  2017-08-05 16:19 ` [PATCH v3 03/20] mtd: nand: qcom: add bam property for QPIC NAND controller Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 05/20] mtd: nand: qcom: DMA mapping support for register read buffer Abhishek Sahu
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

1. QPIC NAND controller uses 3 BAM channels: command, data tx
   and data rx while EBI2 NAND controller uses only single ADM
   channel.
2. CRCI is only required for ADM DMA and it's not required for
   BAM DMA.

Reviewed-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/mtd/nand/qcom_nandc.c | 86 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 68 insertions(+), 18 deletions(-)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index 08cda7d..0b2c8a1 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -257,9 +257,22 @@ struct qcom_nand_controller {
 	struct clk *core_clk;
 	struct clk *aon_clk;
 
-	struct dma_chan *chan;
-	unsigned int cmd_crci;
-	unsigned int data_crci;
+	union {
+		/* will be used only by QPIC for BAM DMA */
+		struct {
+			struct dma_chan *tx_chan;
+			struct dma_chan *rx_chan;
+			struct dma_chan *cmd_chan;
+		};
+
+		/* will be used only by EBI2 for ADM DMA */
+		struct {
+			struct dma_chan *chan;
+			unsigned int cmd_crci;
+			unsigned int data_crci;
+		};
+	};
+
 	struct list_head desc_list;
 
 	u8		*data_buffer;
@@ -1992,10 +2005,31 @@ static int qcom_nandc_alloc(struct qcom_nand_controller *nandc)
 	if (!nandc->reg_read_buf)
 		return -ENOMEM;
 
-	nandc->chan = dma_request_slave_channel(nandc->dev, "rxtx");
-	if (!nandc->chan) {
-		dev_err(nandc->dev, "failed to request slave channel\n");
-		return -ENODEV;
+	if (nandc->props->is_bam) {
+		nandc->tx_chan = dma_request_slave_channel(nandc->dev, "tx");
+		if (!nandc->tx_chan) {
+			dev_err(nandc->dev, "failed to request tx channel\n");
+			return -ENODEV;
+		}
+
+		nandc->rx_chan = dma_request_slave_channel(nandc->dev, "rx");
+		if (!nandc->rx_chan) {
+			dev_err(nandc->dev, "failed to request rx channel\n");
+			return -ENODEV;
+		}
+
+		nandc->cmd_chan = dma_request_slave_channel(nandc->dev, "cmd");
+		if (!nandc->cmd_chan) {
+			dev_err(nandc->dev, "failed to request cmd channel\n");
+			return -ENODEV;
+		}
+	} else {
+		nandc->chan = dma_request_slave_channel(nandc->dev, "rxtx");
+		if (!nandc->chan) {
+			dev_err(nandc->dev,
+				"failed to request slave channel\n");
+			return -ENODEV;
+		}
 	}
 
 	INIT_LIST_HEAD(&nandc->desc_list);
@@ -2008,7 +2042,19 @@ static int qcom_nandc_alloc(struct qcom_nand_controller *nandc)
 
 static void qcom_nandc_unalloc(struct qcom_nand_controller *nandc)
 {
-	dma_release_channel(nandc->chan);
+	if (nandc->props->is_bam) {
+		if (nandc->tx_chan)
+			dma_release_channel(nandc->tx_chan);
+
+		if (nandc->rx_chan)
+			dma_release_channel(nandc->rx_chan);
+
+		if (nandc->cmd_chan)
+			dma_release_channel(nandc->cmd_chan);
+	} else {
+		if (nandc->chan)
+			dma_release_channel(nandc->chan);
+	}
 }
 
 /* one time setup of a few nand controller registers */
@@ -2149,16 +2195,20 @@ static int qcom_nandc_parse_dt(struct platform_device *pdev)
 	struct device_node *np = nandc->dev->of_node;
 	int ret;
 
-	ret = of_property_read_u32(np, "qcom,cmd-crci", &nandc->cmd_crci);
-	if (ret) {
-		dev_err(nandc->dev, "command CRCI unspecified\n");
-		return ret;
-	}
+	if (!nandc->props->is_bam) {
+		ret = of_property_read_u32(np, "qcom,cmd-crci",
+					   &nandc->cmd_crci);
+		if (ret) {
+			dev_err(nandc->dev, "command CRCI unspecified\n");
+			return ret;
+		}
 
-	ret = of_property_read_u32(np, "qcom,data-crci", &nandc->data_crci);
-	if (ret) {
-		dev_err(nandc->dev, "data CRCI unspecified\n");
-		return ret;
+		ret = of_property_read_u32(np, "qcom,data-crci",
+					   &nandc->data_crci);
+		if (ret) {
+			dev_err(nandc->dev, "data CRCI unspecified\n");
+			return ret;
+		}
 	}
 
 	return 0;
@@ -2208,7 +2258,7 @@ static int qcom_nandc_probe(struct platform_device *pdev)
 
 	ret = qcom_nandc_alloc(nandc);
 	if (ret)
-		return ret;
+		goto err_core_clk;
 
 	ret = clk_prepare_enable(nandc->core_clk);
 	if (ret)
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 05/20] mtd: nand: qcom: DMA mapping support for register read buffer
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
                   ` (3 preceding siblings ...)
  2017-08-05 16:19 ` [PATCH v3 04/20] mtd: nand: qcom: add and initialize QPIC DMA resources Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 06/20] mtd: nand: qcom: allocate BAM transaction Abhishek Sahu
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

The EBI2 NAND controller directly remaps register read buffer with
dma_map_sg and DMA address of this buffer will be passed to DMA
API’s. While, on QPIC NAND controller, which uses BAM DMA, we read
the controller registers by preparing a BAM command descriptor. This
command descriptor requires the

  - controller register address
  - the DMA address in which we want to store the value read
    back from the controller register.

This command descriptor will be remapped with dma_map_sg
and its DMA address will be passed to DMA API’s. Therefore,
it's required that we also map our register read buffer for
DMA (using dma_map_single). We use the returned DMA address
for preparing entries in our command descriptor.

This patch adds the DMA mapping support for register read
buffer. This buffer will be DMA mapped during allocation
time. Before starting of any operation, this buffer will
be synced for device operation and after operation
completion, it will be synced again for CPU.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/mtd/nand/qcom_nandc.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index 0b2c8a1..064d06b 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -236,6 +236,7 @@ struct nandc_regs {
  *				by upper layers directly
  * @buf_size/count/start:	markers for chip->read_buf/write_buf functions
  * @reg_read_buf:		local buffer for reading back registers via DMA
+ * @reg_read_dma:		contains dma address for register read buffer
  * @reg_read_pos:		marker for data read in reg_read_buf
  *
  * @regs:			a contiguous chunk of memory for DMA register
@@ -281,6 +282,7 @@ struct qcom_nand_controller {
 	int		buf_start;
 
 	__le32 *reg_read_buf;
+	dma_addr_t reg_read_dma;
 	int reg_read_pos;
 
 	struct nandc_regs *regs;
@@ -373,6 +375,24 @@ static inline void nandc_write(struct qcom_nand_controller *nandc, int offset,
 	iowrite32(val, nandc->base + offset);
 }
 
+static inline void nandc_read_buffer_sync(struct qcom_nand_controller *nandc,
+					  bool is_cpu)
+{
+	if (!nandc->props->is_bam)
+		return;
+
+	if (is_cpu)
+		dma_sync_single_for_cpu(nandc->dev, nandc->reg_read_dma,
+					MAX_REG_RD *
+					sizeof(*nandc->reg_read_buf),
+					DMA_FROM_DEVICE);
+	else
+		dma_sync_single_for_device(nandc->dev, nandc->reg_read_dma,
+					   MAX_REG_RD *
+					   sizeof(*nandc->reg_read_buf),
+					   DMA_FROM_DEVICE);
+}
+
 static __le32 *offset_to_nandc_reg(struct nandc_regs *regs, int offset)
 {
 	switch (offset) {
@@ -857,6 +877,7 @@ static void free_descs(struct qcom_nand_controller *nandc)
 static void clear_read_regs(struct qcom_nand_controller *nandc)
 {
 	nandc->reg_read_pos = 0;
+	nandc_read_buffer_sync(nandc, false);
 }
 
 static void pre_command(struct qcom_nand_host *host, int command)
@@ -886,6 +907,7 @@ static void parse_erase_write_errors(struct qcom_nand_host *host, int command)
 	int i;
 
 	num_cw = command == NAND_CMD_PAGEPROG ? ecc->steps : 1;
+	nandc_read_buffer_sync(nandc, true);
 
 	for (i = 0; i < num_cw; i++) {
 		u32 flash_status = le32_to_cpu(nandc->reg_read_buf[i]);
@@ -907,6 +929,7 @@ static void post_command(struct qcom_nand_host *host, int command)
 
 	switch (command) {
 	case NAND_CMD_READID:
+		nandc_read_buffer_sync(nandc, true);
 		memcpy(nandc->data_buffer, nandc->reg_read_buf,
 		       nandc->buf_count);
 		break;
@@ -1070,6 +1093,7 @@ static int parse_read_errors(struct qcom_nand_host *host, u8 *data_buf,
 	int i;
 
 	buf = (struct read_stats *)nandc->reg_read_buf;
+	nandc_read_buffer_sync(nandc, true);
 
 	for (i = 0; i < ecc->steps; i++, buf++) {
 		u32 flash, buffer, erased_cw;
@@ -2006,6 +2030,16 @@ static int qcom_nandc_alloc(struct qcom_nand_controller *nandc)
 		return -ENOMEM;
 
 	if (nandc->props->is_bam) {
+		nandc->reg_read_dma =
+			dma_map_single(nandc->dev, nandc->reg_read_buf,
+				       MAX_REG_RD *
+				       sizeof(*nandc->reg_read_buf),
+				       DMA_FROM_DEVICE);
+		if (dma_mapping_error(nandc->dev, nandc->reg_read_dma)) {
+			dev_err(nandc->dev, "failed to DMA MAP reg buffer\n");
+			return -EIO;
+		}
+
 		nandc->tx_chan = dma_request_slave_channel(nandc->dev, "tx");
 		if (!nandc->tx_chan) {
 			dev_err(nandc->dev, "failed to request tx channel\n");
@@ -2043,6 +2077,12 @@ static int qcom_nandc_alloc(struct qcom_nand_controller *nandc)
 static void qcom_nandc_unalloc(struct qcom_nand_controller *nandc)
 {
 	if (nandc->props->is_bam) {
+		if (!dma_mapping_error(nandc->dev, nandc->reg_read_dma))
+			dma_unmap_single(nandc->dev, nandc->reg_read_dma,
+					 MAX_REG_RD *
+					 sizeof(*nandc->reg_read_buf),
+					 DMA_FROM_DEVICE);
+
 		if (nandc->tx_chan)
 			dma_release_channel(nandc->tx_chan);
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 06/20] mtd: nand: qcom: allocate BAM transaction
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
                   ` (4 preceding siblings ...)
  2017-08-05 16:19 ` [PATCH v3 05/20] mtd: nand: qcom: DMA mapping support for register read buffer Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 07/20] mtd: nand: qcom: add BAM DMA descriptor handling Abhishek Sahu
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

- The BAM transaction is the core data structure which will be used
for all the data transfers in QPIC NAND. Since the core framework
in nand_base.c is serializing all the NAND requests so allocating
BAM transaction before every transfer will be overhead. The memory
for it be allocated during probe time and before every transfer,
it will be cleared.

- The BAM transaction contains the array of
command and data scatter gather list and indexes. For
every transfer, all the resource will be taken from BAM
transaction.

- The size of the buffer used for BAM transactions
is calculated based on the NAND device with the maximum page size,
among all the devices connected to the
controller.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/mtd/nand/qcom_nandc.c | 94 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 94 insertions(+)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index 064d06b..89bdee9 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -179,6 +179,32 @@
 #define	ECC_BCH_4BIT	BIT(2)
 #define	ECC_BCH_8BIT	BIT(3)
 
+#define QPIC_PER_CW_CMD_SGL		32
+#define QPIC_PER_CW_DATA_SGL		8
+
+/*
+ * This data type corresponds to the BAM transaction which will be used for all
+ * NAND transfers.
+ * @cmd_sgl - sgl for NAND BAM command pipe
+ * @data_sgl - sgl for NAND BAM consumer/producer pipe
+ * @cmd_sgl_pos - current index in command sgl.
+ * @cmd_sgl_start - start index in command sgl.
+ * @tx_sgl_pos - current index in data sgl for tx.
+ * @tx_sgl_start - start index in data sgl for tx.
+ * @rx_sgl_pos - current index in data sgl for rx.
+ * @rx_sgl_start - start index in data sgl for rx.
+ */
+struct bam_transaction {
+	struct scatterlist *cmd_sgl;
+	struct scatterlist *data_sgl;
+	u32 cmd_sgl_pos;
+	u32 cmd_sgl_start;
+	u32 tx_sgl_pos;
+	u32 tx_sgl_start;
+	u32 rx_sgl_pos;
+	u32 rx_sgl_start;
+};
+
 struct desc_info {
 	struct list_head node;
 
@@ -245,6 +271,8 @@ struct nandc_regs {
  * @cmd1/vld:			some fixed controller register values
  * @props:			properties of current NAND controller,
  *				initialized via DT match data
+ * @max_cwperpage:		maximum QPIC codewords required. calculated
+ *				from all connected NAND devices pagesize
  */
 struct qcom_nand_controller {
 	struct nand_hw_control controller;
@@ -275,11 +303,13 @@ struct qcom_nand_controller {
 	};
 
 	struct list_head desc_list;
+	struct bam_transaction *bam_txn;
 
 	u8		*data_buffer;
 	int		buf_size;
 	int		buf_count;
 	int		buf_start;
+	unsigned int	max_cwperpage;
 
 	__le32 *reg_read_buf;
 	dma_addr_t reg_read_dma;
@@ -352,6 +382,44 @@ struct qcom_nandc_props {
 	bool is_bam;
 };
 
+/* Frees the BAM transaction memory */
+static void free_bam_transaction(struct qcom_nand_controller *nandc)
+{
+	struct bam_transaction *bam_txn = nandc->bam_txn;
+
+	devm_kfree(nandc->dev, bam_txn);
+}
+
+/* Allocates and Initializes the BAM transaction */
+static struct bam_transaction *
+alloc_bam_transaction(struct qcom_nand_controller *nandc)
+{
+	struct bam_transaction *bam_txn;
+	size_t bam_txn_size;
+	unsigned int num_cw = nandc->max_cwperpage;
+	void *bam_txn_buf;
+
+	bam_txn_size =
+		sizeof(*bam_txn) + num_cw *
+		((sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL) +
+		(sizeof(*bam_txn->data_sgl) * QPIC_PER_CW_DATA_SGL));
+
+	bam_txn_buf = devm_kzalloc(nandc->dev, bam_txn_size, GFP_KERNEL);
+	if (!bam_txn_buf)
+		return NULL;
+
+	bam_txn = bam_txn_buf;
+	bam_txn_buf += sizeof(*bam_txn);
+
+	bam_txn->cmd_sgl = bam_txn_buf;
+	bam_txn_buf +=
+		sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL * num_cw;
+
+	bam_txn->data_sgl = bam_txn_buf;
+
+	return bam_txn;
+}
+
 static inline struct qcom_nand_host *to_qcom_nand_host(struct nand_chip *chip)
 {
 	return container_of(chip, struct qcom_nand_host, chip);
@@ -1923,6 +1991,8 @@ static int qcom_nand_host_setup(struct qcom_nand_host *host)
 	mtd_set_ooblayout(mtd, &qcom_nand_ooblayout_ops);
 
 	cwperpage = mtd->writesize / ecc->size;
+	nandc->max_cwperpage = max_t(unsigned int, nandc->max_cwperpage,
+				     cwperpage);
 
 	/*
 	 * DATA_UD_BYTES varies based on whether the read/write command protects
@@ -2057,6 +2127,20 @@ static int qcom_nandc_alloc(struct qcom_nand_controller *nandc)
 			dev_err(nandc->dev, "failed to request cmd channel\n");
 			return -ENODEV;
 		}
+
+		/*
+		 * Initially allocate BAM transaction to read ONFI param page.
+		 * After detecting all the devices, this BAM transaction will
+		 * be freed and the next BAM tranasction will be allocated with
+		 * maximum codeword size
+		 */
+		nandc->max_cwperpage = 1;
+		nandc->bam_txn = alloc_bam_transaction(nandc);
+		if (!nandc->bam_txn) {
+			dev_err(nandc->dev,
+				"failed to allocate bam transaction\n");
+			return -ENOMEM;
+		}
 	} else {
 		nandc->chan = dma_request_slave_channel(nandc->dev, "rxtx");
 		if (!nandc->chan) {
@@ -2214,6 +2298,16 @@ static int qcom_probe_nand_devices(struct qcom_nand_controller *nandc)
 	if (list_empty(&nandc->host_list))
 		return -ENODEV;
 
+	if (nandc->props->is_bam) {
+		free_bam_transaction(nandc);
+		nandc->bam_txn = alloc_bam_transaction(nandc);
+		if (!nandc->bam_txn) {
+			dev_err(nandc->dev,
+				"failed to allocate bam transaction\n");
+			return -ENOMEM;
+		}
+	}
+
 	list_for_each_entry_safe(host, tmp, &nandc->host_list, node) {
 		ret = qcom_nand_mtd_register(nandc, host, child);
 		if (ret) {
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 07/20] mtd: nand: qcom: add BAM DMA descriptor handling
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
                   ` (5 preceding siblings ...)
  2017-08-05 16:19 ` [PATCH v3 06/20] mtd: nand: qcom: allocate BAM transaction Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 08/20] mtd: nand: qcom: support for passing flags in transfer functions Abhishek Sahu
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

1. prepare_bam_async_desc is the function which will call
   all the DMA API’s. It will fetch the outstanding scatter gather
   list for passed channel and will do the DMA descriptor formation.
   The DMA flag is dependent upon the type of channel.

2. For ADM DMA, the descriptor is being formed for every DMA
   request so its sgl count will be always 1 while in BAM DMA, the
   clubbing of descriptor is being done to increase throughput.

3. ADM DMA uses only one channel while in BAM DMA, data descriptors
   will be submitted to tx channel (for write) or rx channel
   (for read) and all the registers read/write descriptors in
   command channel.

Reviewed-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/mtd/nand/qcom_nandc.c | 148 ++++++++++++++++++++++++++++++++++++++----
 1 file changed, 136 insertions(+), 12 deletions(-)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index 89bdee9..825ad4a 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -205,11 +205,27 @@ struct bam_transaction {
 	u32 rx_sgl_start;
 };
 
+/*
+ * This data type corresponds to the nand dma descriptor
+ * @list - list for desc_info
+ * @dir - DMA transfer direction
+ * @adm_sgl - sgl which will be used for single sgl dma descriptor. Only used by
+ *	      ADM
+ * @bam_sgl - sgl which will be used for dma descriptor. Only used by BAM
+ * @sgl_cnt - number of SGL in bam_sgl. Only used by BAM
+ * @dma_desc - low level DMA engine descriptor
+ */
 struct desc_info {
 	struct list_head node;
 
 	enum dma_data_direction dir;
-	struct scatterlist sgl;
+	union {
+		struct scatterlist adm_sgl;
+		struct {
+			struct scatterlist *bam_sgl;
+			int sgl_cnt;
+		};
+	};
 	struct dma_async_tx_descriptor *dma_desc;
 };
 
@@ -570,9 +586,78 @@ static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read)
 	nandc_set_reg(nandc, NAND_EXEC_CMD, 1);
 }
 
-static int prep_dma_desc(struct qcom_nand_controller *nandc, bool read,
-			 int reg_off, const void *vaddr, int size,
-			 bool flow_control)
+/*
+ * Maps the scatter gather list for DMA transfer and forms the DMA descriptor
+ * for BAM. This descriptor will be added in the NAND DMA descriptor queue
+ * which will be submitted to DMA engine.
+ */
+static int prepare_bam_async_desc(struct qcom_nand_controller *nandc,
+				  struct dma_chan *chan,
+				  unsigned long flags)
+{
+	struct desc_info *desc;
+	struct scatterlist *sgl;
+	unsigned int sgl_cnt;
+	int ret;
+	struct bam_transaction *bam_txn = nandc->bam_txn;
+	enum dma_transfer_direction dir_eng;
+	struct dma_async_tx_descriptor *dma_desc;
+
+	desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+
+	if (chan == nandc->cmd_chan) {
+		sgl = &bam_txn->cmd_sgl[bam_txn->cmd_sgl_start];
+		sgl_cnt = bam_txn->cmd_sgl_pos - bam_txn->cmd_sgl_start;
+		bam_txn->cmd_sgl_start = bam_txn->cmd_sgl_pos;
+		dir_eng = DMA_MEM_TO_DEV;
+		desc->dir = DMA_TO_DEVICE;
+	} else if (chan == nandc->tx_chan) {
+		sgl = &bam_txn->data_sgl[bam_txn->tx_sgl_start];
+		sgl_cnt = bam_txn->tx_sgl_pos - bam_txn->tx_sgl_start;
+		bam_txn->tx_sgl_start = bam_txn->tx_sgl_pos;
+		dir_eng = DMA_MEM_TO_DEV;
+		desc->dir = DMA_TO_DEVICE;
+	} else {
+		sgl = &bam_txn->data_sgl[bam_txn->rx_sgl_start];
+		sgl_cnt = bam_txn->rx_sgl_pos - bam_txn->rx_sgl_start;
+		bam_txn->rx_sgl_start = bam_txn->rx_sgl_pos;
+		dir_eng = DMA_DEV_TO_MEM;
+		desc->dir = DMA_FROM_DEVICE;
+	}
+
+	sg_mark_end(sgl + sgl_cnt - 1);
+	ret = dma_map_sg(nandc->dev, sgl, sgl_cnt, desc->dir);
+	if (ret == 0) {
+		dev_err(nandc->dev, "failure in mapping desc\n");
+		kfree(desc);
+		return -ENOMEM;
+	}
+
+	desc->sgl_cnt = sgl_cnt;
+	desc->bam_sgl = sgl;
+
+	dma_desc = dmaengine_prep_slave_sg(chan, sgl, sgl_cnt, dir_eng,
+					   flags);
+
+	if (!dma_desc) {
+		dev_err(nandc->dev, "failure in prep desc\n");
+		dma_unmap_sg(nandc->dev, sgl, sgl_cnt, desc->dir);
+		kfree(desc);
+		return -EINVAL;
+	}
+
+	desc->dma_desc = dma_desc;
+
+	list_add_tail(&desc->node, &nandc->desc_list);
+
+	return 0;
+}
+
+static int prep_adm_dma_desc(struct qcom_nand_controller *nandc, bool read,
+			     int reg_off, const void *vaddr, int size,
+			     bool flow_control)
 {
 	struct desc_info *desc;
 	struct dma_async_tx_descriptor *dma_desc;
@@ -585,7 +670,7 @@ static int prep_dma_desc(struct qcom_nand_controller *nandc, bool read,
 	if (!desc)
 		return -ENOMEM;
 
-	sgl = &desc->sgl;
+	sgl = &desc->adm_sgl;
 
 	sg_init_one(sgl, vaddr, size);
 
@@ -661,7 +746,7 @@ static int read_reg_dma(struct qcom_nand_controller *nandc, int first,
 	vaddr = nandc->reg_read_buf + nandc->reg_read_pos;
 	nandc->reg_read_pos += num_regs;
 
-	return prep_dma_desc(nandc, true, first, vaddr, size, flow_control);
+	return prep_adm_dma_desc(nandc, true, first, vaddr, size, flow_control);
 }
 
 /*
@@ -692,7 +777,8 @@ static int write_reg_dma(struct qcom_nand_controller *nandc, int first,
 
 	size = num_regs * sizeof(u32);
 
-	return prep_dma_desc(nandc, false, first, vaddr, size, flow_control);
+	return prep_adm_dma_desc(nandc, false, first, vaddr, size,
+				 flow_control);
 }
 
 /*
@@ -706,7 +792,7 @@ static int write_reg_dma(struct qcom_nand_controller *nandc, int first,
 static int read_data_dma(struct qcom_nand_controller *nandc, int reg_off,
 			 const u8 *vaddr, int size)
 {
-	return prep_dma_desc(nandc, true, reg_off, vaddr, size, false);
+	return prep_adm_dma_desc(nandc, true, reg_off, vaddr, size, false);
 }
 
 /*
@@ -720,7 +806,7 @@ static int read_data_dma(struct qcom_nand_controller *nandc, int reg_off,
 static int write_data_dma(struct qcom_nand_controller *nandc, int reg_off,
 			  const u8 *vaddr, int size)
 {
-	return prep_dma_desc(nandc, false, reg_off, vaddr, size, false);
+	return prep_adm_dma_desc(nandc, false, reg_off, vaddr, size, false);
 }
 
 /*
@@ -920,12 +1006,43 @@ static int submit_descs(struct qcom_nand_controller *nandc)
 {
 	struct desc_info *desc;
 	dma_cookie_t cookie = 0;
+	struct bam_transaction *bam_txn = nandc->bam_txn;
+	int r;
+
+	if (nandc->props->is_bam) {
+		if (bam_txn->rx_sgl_pos > bam_txn->rx_sgl_start) {
+			r = prepare_bam_async_desc(nandc, nandc->rx_chan, 0);
+			if (r)
+				return r;
+		}
+
+		if (bam_txn->tx_sgl_pos > bam_txn->tx_sgl_start) {
+			r = prepare_bam_async_desc(nandc, nandc->tx_chan,
+						   DMA_PREP_INTERRUPT);
+			if (r)
+				return r;
+		}
+
+		if (bam_txn->cmd_sgl_pos > bam_txn->cmd_sgl_start) {
+			r = prepare_bam_async_desc(nandc, nandc->cmd_chan, 0);
+			if (r)
+				return r;
+		}
+	}
 
 	list_for_each_entry(desc, &nandc->desc_list, node)
 		cookie = dmaengine_submit(desc->dma_desc);
 
-	if (dma_sync_wait(nandc->chan, cookie) != DMA_COMPLETE)
-		return -ETIMEDOUT;
+	if (nandc->props->is_bam) {
+		dma_async_issue_pending(nandc->tx_chan);
+		dma_async_issue_pending(nandc->rx_chan);
+
+		if (dma_sync_wait(nandc->cmd_chan, cookie) != DMA_COMPLETE)
+			return -ETIMEDOUT;
+	} else {
+		if (dma_sync_wait(nandc->chan, cookie) != DMA_COMPLETE)
+			return -ETIMEDOUT;
+	}
 
 	return 0;
 }
@@ -936,7 +1053,14 @@ static void free_descs(struct qcom_nand_controller *nandc)
 
 	list_for_each_entry_safe(desc, n, &nandc->desc_list, node) {
 		list_del(&desc->node);
-		dma_unmap_sg(nandc->dev, &desc->sgl, 1, desc->dir);
+
+		if (nandc->props->is_bam)
+			dma_unmap_sg(nandc->dev, desc->bam_sgl,
+				     desc->sgl_cnt, desc->dir);
+		else
+			dma_unmap_sg(nandc->dev, &desc->adm_sgl, 1,
+				     desc->dir);
+
 		kfree(desc);
 	}
 }
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 08/20] mtd: nand: qcom: support for passing flags in transfer functions
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
                   ` (6 preceding siblings ...)
  2017-08-05 16:19 ` [PATCH v3 07/20] mtd: nand: qcom: add BAM DMA descriptor handling Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 09/20] mtd: nand: qcom: support for read location registers Abhishek Sahu
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

The BAM has multiple flags to control the transfer. This patch
adds flags parameter in register and data transfer functions and
modifies all these functions call with appropriate flags using
following rule

1. Read and write can’t go in single command descriptor so
   separate SGL should be used.
2. For some of the requests, NWD flag should be set in BAM
   DMA descriptor.
3. For Data write, the BAM has internal buffer for each codeword.
   All write request will modify the data in internal buffer and
   this buffer will be flushed to NAND device once EOT flag is set.
   So for all the write requests in single codeword, the EOT should
   be cleared for all tx data descriptors except the last one.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/mtd/nand/qcom_nandc.c | 122 ++++++++++++++++++++++++------------------
 1 file changed, 70 insertions(+), 52 deletions(-)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index 825ad4a..fb1f5de 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -182,6 +182,14 @@
 #define QPIC_PER_CW_CMD_SGL		32
 #define QPIC_PER_CW_DATA_SGL		8
 
+/* Flags used for BAM DMA desc preparation*/
+/* Don't set the EOT in current tx sgl */
+#define NAND_BAM_NO_EOT			BIT(0)
+/* Set the NWD flag in current sgl */
+#define NAND_BAM_NWD			BIT(1)
+/* Finish writing in the current sgl and start writing in another sgl */
+#define NAND_BAM_NEXT_SGL		BIT(2)
+
 /*
  * This data type corresponds to the BAM transaction which will be used for all
  * NAND transfers.
@@ -733,7 +741,7 @@ static int prep_adm_dma_desc(struct qcom_nand_controller *nandc, bool read,
  * @num_regs:		number of registers to read
  */
 static int read_reg_dma(struct qcom_nand_controller *nandc, int first,
-			int num_regs)
+			int num_regs, unsigned int flags)
 {
 	bool flow_control = false;
 	void *vaddr;
@@ -757,7 +765,7 @@ static int read_reg_dma(struct qcom_nand_controller *nandc, int first,
  * @num_regs:		number of registers to write
  */
 static int write_reg_dma(struct qcom_nand_controller *nandc, int first,
-			 int num_regs)
+			 int num_regs, unsigned int flags)
 {
 	bool flow_control = false;
 	struct nandc_regs *regs = nandc->regs;
@@ -769,6 +777,9 @@ static int write_reg_dma(struct qcom_nand_controller *nandc, int first,
 	if (first == NAND_FLASH_CMD)
 		flow_control = true;
 
+	if (first == NAND_EXEC_CMD)
+		flags |= NAND_BAM_NWD;
+
 	if (first == NAND_DEV_CMD1_RESTORE)
 		first = NAND_DEV_CMD1;
 
@@ -790,7 +801,7 @@ static int write_reg_dma(struct qcom_nand_controller *nandc, int first,
  * @size:		DMA transaction size in bytes
  */
 static int read_data_dma(struct qcom_nand_controller *nandc, int reg_off,
-			 const u8 *vaddr, int size)
+			 const u8 *vaddr, int size, unsigned int flags)
 {
 	return prep_adm_dma_desc(nandc, true, reg_off, vaddr, size, false);
 }
@@ -804,7 +815,7 @@ static int read_data_dma(struct qcom_nand_controller *nandc, int reg_off,
  * @size:		DMA transaction size in bytes
  */
 static int write_data_dma(struct qcom_nand_controller *nandc, int reg_off,
-			  const u8 *vaddr, int size)
+			  const u8 *vaddr, int size, unsigned int flags)
 {
 	return prep_adm_dma_desc(nandc, false, reg_off, vaddr, size, false);
 }
@@ -815,9 +826,9 @@ static int write_data_dma(struct qcom_nand_controller *nandc, int reg_off,
  */
 static void config_nand_page_read(struct qcom_nand_controller *nandc)
 {
-	write_reg_dma(nandc, NAND_ADDR0, 2);
-	write_reg_dma(nandc, NAND_DEV0_CFG0, 3);
-	write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1);
+	write_reg_dma(nandc, NAND_ADDR0, 2, 0);
+	write_reg_dma(nandc, NAND_DEV0_CFG0, 3, 0);
+	write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1, 0);
 }
 
 /*
@@ -826,11 +837,12 @@ static void config_nand_page_read(struct qcom_nand_controller *nandc)
  */
 static void config_nand_cw_read(struct qcom_nand_controller *nandc)
 {
-	write_reg_dma(nandc, NAND_FLASH_CMD, 1);
-	write_reg_dma(nandc, NAND_EXEC_CMD, 1);
+	write_reg_dma(nandc, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
+	write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
 
-	read_reg_dma(nandc, NAND_FLASH_STATUS, 2);
-	read_reg_dma(nandc, NAND_ERASED_CW_DETECT_STATUS, 1);
+	read_reg_dma(nandc, NAND_FLASH_STATUS, 2, 0);
+	read_reg_dma(nandc, NAND_ERASED_CW_DETECT_STATUS, 1,
+		     NAND_BAM_NEXT_SGL);
 }
 
 /*
@@ -849,9 +861,10 @@ static void config_nand_single_cw_page_read(struct qcom_nand_controller *nandc)
  */
 static void config_nand_page_write(struct qcom_nand_controller *nandc)
 {
-	write_reg_dma(nandc, NAND_ADDR0, 2);
-	write_reg_dma(nandc, NAND_DEV0_CFG0, 3);
-	write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1);
+	write_reg_dma(nandc, NAND_ADDR0, 2, 0);
+	write_reg_dma(nandc, NAND_DEV0_CFG0, 3, 0);
+	write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1,
+		      NAND_BAM_NEXT_SGL);
 }
 
 /*
@@ -860,13 +873,13 @@ static void config_nand_page_write(struct qcom_nand_controller *nandc)
  */
 static void config_nand_cw_write(struct qcom_nand_controller *nandc)
 {
-	write_reg_dma(nandc, NAND_FLASH_CMD, 1);
-	write_reg_dma(nandc, NAND_EXEC_CMD, 1);
+	write_reg_dma(nandc, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
+	write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
 
-	read_reg_dma(nandc, NAND_FLASH_STATUS, 1);
+	read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
 
-	write_reg_dma(nandc, NAND_FLASH_STATUS, 1);
-	write_reg_dma(nandc, NAND_READ_STATUS, 1);
+	write_reg_dma(nandc, NAND_FLASH_STATUS, 1, 0);
+	write_reg_dma(nandc, NAND_READ_STATUS, 1, NAND_BAM_NEXT_SGL);
 }
 
 /*
@@ -914,8 +927,8 @@ static int nandc_param(struct qcom_nand_host *host)
 	nandc_set_reg(nandc, NAND_DEV_CMD1_RESTORE, nandc->cmd1);
 	nandc_set_reg(nandc, NAND_DEV_CMD_VLD_RESTORE, nandc->vld);
 
-	write_reg_dma(nandc, NAND_DEV_CMD_VLD, 1);
-	write_reg_dma(nandc, NAND_DEV_CMD1, 1);
+	write_reg_dma(nandc, NAND_DEV_CMD_VLD, 1, 0);
+	write_reg_dma(nandc, NAND_DEV_CMD1, 1, NAND_BAM_NEXT_SGL);
 
 	nandc->buf_count = 512;
 	memset(nandc->data_buffer, 0xff, nandc->buf_count);
@@ -923,11 +936,11 @@ static int nandc_param(struct qcom_nand_host *host)
 	config_nand_single_cw_page_read(nandc);
 
 	read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer,
-		      nandc->buf_count);
+		      nandc->buf_count, 0);
 
 	/* restore CMD1 and VLD regs */
-	write_reg_dma(nandc, NAND_DEV_CMD1_RESTORE, 1);
-	write_reg_dma(nandc, NAND_DEV_CMD_VLD_RESTORE, 1);
+	write_reg_dma(nandc, NAND_DEV_CMD1_RESTORE, 1, 0);
+	write_reg_dma(nandc, NAND_DEV_CMD_VLD_RESTORE, 1, NAND_BAM_NEXT_SGL);
 
 	return 0;
 }
@@ -949,14 +962,14 @@ static int erase_block(struct qcom_nand_host *host, int page_addr)
 	nandc_set_reg(nandc, NAND_FLASH_STATUS, host->clrflashstatus);
 	nandc_set_reg(nandc, NAND_READ_STATUS, host->clrreadstatus);
 
-	write_reg_dma(nandc, NAND_FLASH_CMD, 3);
-	write_reg_dma(nandc, NAND_DEV0_CFG0, 2);
-	write_reg_dma(nandc, NAND_EXEC_CMD, 1);
+	write_reg_dma(nandc, NAND_FLASH_CMD, 3, NAND_BAM_NEXT_SGL);
+	write_reg_dma(nandc, NAND_DEV0_CFG0, 2, NAND_BAM_NEXT_SGL);
+	write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
 
-	read_reg_dma(nandc, NAND_FLASH_STATUS, 1);
+	read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
 
-	write_reg_dma(nandc, NAND_FLASH_STATUS, 1);
-	write_reg_dma(nandc, NAND_READ_STATUS, 1);
+	write_reg_dma(nandc, NAND_FLASH_STATUS, 1, 0);
+	write_reg_dma(nandc, NAND_READ_STATUS, 1, NAND_BAM_NEXT_SGL);
 
 	return 0;
 }
@@ -976,10 +989,10 @@ static int read_id(struct qcom_nand_host *host, int column)
 	nandc_set_reg(nandc, NAND_FLASH_CHIP_SELECT, DM_EN);
 	nandc_set_reg(nandc, NAND_EXEC_CMD, 1);
 
-	write_reg_dma(nandc, NAND_FLASH_CMD, 4);
-	write_reg_dma(nandc, NAND_EXEC_CMD, 1);
+	write_reg_dma(nandc, NAND_FLASH_CMD, 4, NAND_BAM_NEXT_SGL);
+	write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
 
-	read_reg_dma(nandc, NAND_READ_ID, 1);
+	read_reg_dma(nandc, NAND_READ_ID, 1, NAND_BAM_NEXT_SGL);
 
 	return 0;
 }
@@ -993,10 +1006,10 @@ static int reset(struct qcom_nand_host *host)
 	nandc_set_reg(nandc, NAND_FLASH_CMD, RESET_DEVICE);
 	nandc_set_reg(nandc, NAND_EXEC_CMD, 1);
 
-	write_reg_dma(nandc, NAND_FLASH_CMD, 1);
-	write_reg_dma(nandc, NAND_EXEC_CMD, 1);
+	write_reg_dma(nandc, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
+	write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
 
-	read_reg_dma(nandc, NAND_FLASH_STATUS, 1);
+	read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
 
 	return 0;
 }
@@ -1392,7 +1405,7 @@ static int read_page_ecc(struct qcom_nand_host *host, u8 *data_buf,
 
 		if (data_buf)
 			read_data_dma(nandc, FLASH_BUF_ACC, data_buf,
-				      data_size);
+				      data_size, 0);
 
 		/*
 		 * when ecc is enabled, the controller doesn't read the real
@@ -1408,7 +1421,7 @@ static int read_page_ecc(struct qcom_nand_host *host, u8 *data_buf,
 				*oob_buf++ = 0xff;
 
 			read_data_dma(nandc, FLASH_BUF_ACC + data_size,
-				      oob_buf, oob_size);
+				      oob_buf, oob_size, 0);
 		}
 
 		if (data_buf)
@@ -1450,7 +1463,7 @@ static int copy_last_cw(struct qcom_nand_host *host, int page)
 
 	config_nand_single_cw_page_read(nandc);
 
-	read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, size);
+	read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, size, 0);
 
 	ret = submit_descs(nandc);
 	if (ret)
@@ -1519,19 +1532,19 @@ static int qcom_nandc_read_page_raw(struct mtd_info *mtd,
 
 		config_nand_cw_read(nandc);
 
-		read_data_dma(nandc, reg_off, data_buf, data_size1);
+		read_data_dma(nandc, reg_off, data_buf, data_size1, 0);
 		reg_off += data_size1;
 		data_buf += data_size1;
 
-		read_data_dma(nandc, reg_off, oob_buf, oob_size1);
+		read_data_dma(nandc, reg_off, oob_buf, oob_size1, 0);
 		reg_off += oob_size1;
 		oob_buf += oob_size1;
 
-		read_data_dma(nandc, reg_off, data_buf, data_size2);
+		read_data_dma(nandc, reg_off, data_buf, data_size2, 0);
 		reg_off += data_size2;
 		data_buf += data_size2;
 
-		read_data_dma(nandc, reg_off, oob_buf, oob_size2);
+		read_data_dma(nandc, reg_off, oob_buf, oob_size2, 0);
 		oob_buf += oob_size2;
 	}
 
@@ -1598,7 +1611,8 @@ static int qcom_nandc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 		}
 
 
-		write_data_dma(nandc, FLASH_BUF_ACC, data_buf, data_size);
+		write_data_dma(nandc, FLASH_BUF_ACC, data_buf, data_size,
+			       i == (ecc->steps - 1) ? NAND_BAM_NO_EOT : 0);
 
 		/*
 		 * when ECC is enabled, we don't really need to write anything
@@ -1611,7 +1625,7 @@ static int qcom_nandc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 			oob_buf += host->bbm_size;
 
 			write_data_dma(nandc, FLASH_BUF_ACC + data_size,
-				       oob_buf, oob_size);
+				       oob_buf, oob_size, 0);
 		}
 
 		config_nand_cw_write(nandc);
@@ -1666,19 +1680,22 @@ static int qcom_nandc_write_page_raw(struct mtd_info *mtd,
 			oob_size2 = host->ecc_bytes_hw + host->spare_bytes;
 		}
 
-		write_data_dma(nandc, reg_off, data_buf, data_size1);
+		write_data_dma(nandc, reg_off, data_buf, data_size1,
+			       NAND_BAM_NO_EOT);
 		reg_off += data_size1;
 		data_buf += data_size1;
 
-		write_data_dma(nandc, reg_off, oob_buf, oob_size1);
+		write_data_dma(nandc, reg_off, oob_buf, oob_size1,
+			       NAND_BAM_NO_EOT);
 		reg_off += oob_size1;
 		oob_buf += oob_size1;
 
-		write_data_dma(nandc, reg_off, data_buf, data_size2);
+		write_data_dma(nandc, reg_off, data_buf, data_size2,
+			       NAND_BAM_NO_EOT);
 		reg_off += data_size2;
 		data_buf += data_size2;
 
-		write_data_dma(nandc, reg_off, oob_buf, oob_size2);
+		write_data_dma(nandc, reg_off, oob_buf, oob_size2, 0);
 		oob_buf += oob_size2;
 
 		config_nand_cw_write(nandc);
@@ -1732,8 +1749,8 @@ static int qcom_nandc_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
 	update_rw_regs(host, 1, false);
 
 	config_nand_page_write(nandc);
-	write_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer,
-		       data_size + oob_size);
+	write_data_dma(nandc, FLASH_BUF_ACC,
+		       nandc->data_buffer, data_size + oob_size, 0);
 	config_nand_cw_write(nandc);
 
 	ret = submit_descs(nandc);
@@ -1817,7 +1834,8 @@ static int qcom_nandc_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	update_rw_regs(host, 1, false);
 
 	config_nand_page_write(nandc);
-	write_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, host->cw_size);
+	write_data_dma(nandc, FLASH_BUF_ACC,
+		       nandc->data_buffer, host->cw_size, 0);
 	config_nand_cw_write(nandc);
 
 	ret = submit_descs(nandc);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 09/20] mtd: nand: qcom: support for read location registers
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
                   ` (7 preceding siblings ...)
  2017-08-05 16:19 ` [PATCH v3 08/20] mtd: nand: qcom: support for passing flags in transfer functions Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 10/20] mtd: nand: qcom: erased codeword detection configuration Abhishek Sahu
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

In EBI2, all codeword data will be read in FLASH_BUF_ACC buffer
and ADM will copy the data from source (FLASH_BUF_ACC) to
destination (memory for data read).

In QPIC, there is no FLASH_BUF_ACC and all the codeword data will
held in QPIC BAM FIFO buffers. It provides multiple READ_LOCATION
registers which will be used for copying the data from FIFO to
memory. The READ_LOCATION register will be used to read a
specific amount of data from a specific offset within the flash
buffer. It supports sequential offset requests. Each request is
composed of the following fields:

a. Offset within the flash buffer from which data should be
   read
b. Amount of data to be read
c. Flag bit specifying the last read request from the flash
   buffer. Following the last read request the NANDc refers to the
   buffer as empty.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/mtd/nand/qcom_nandc.c | 64 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index fb1f5de..28543c1 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -53,6 +53,8 @@
 #define	NAND_VERSION			0xf08
 #define	NAND_READ_LOCATION_0		0xf20
 #define	NAND_READ_LOCATION_1		0xf24
+#define	NAND_READ_LOCATION_2		0xf28
+#define	NAND_READ_LOCATION_3		0xf2c
 
 /* dummy register offsets, used by write_reg_dma */
 #define	NAND_DEV_CMD1_RESTORE		0xdead
@@ -135,6 +137,11 @@
 #define	ERASED_PAGE			(PAGE_ALL_ERASED | PAGE_ERASED)
 #define	ERASED_CW			(CODEWORD_ALL_ERASED | CODEWORD_ERASED)
 
+/* NAND_READ_LOCATION_n bits */
+#define READ_LOCATION_OFFSET		0
+#define READ_LOCATION_SIZE		16
+#define READ_LOCATION_LAST		31
+
 /* Version Mask */
 #define	NAND_VERSION_MAJOR_MASK		0xf0000000
 #define	NAND_VERSION_MAJOR_SHIFT	28
@@ -179,6 +186,12 @@
 #define	ECC_BCH_4BIT	BIT(2)
 #define	ECC_BCH_8BIT	BIT(3)
 
+#define nandc_set_readl(nandc, reg, offset, size, is_last)	\
+nandc_set_reg(nandc, NAND_READ_LOCATION_##reg,			\
+	      ((offset) << READ_LOCATION_OFFSET) |		\
+	      ((size) << READ_LOCATION_SIZE) |			\
+	      ((is_last) << READ_LOCATION_LAST))
+
 #define QPIC_PER_CW_CMD_SGL		32
 #define QPIC_PER_CW_DATA_SGL		8
 
@@ -262,6 +275,11 @@ struct nandc_regs {
 	__le32 orig_vld;
 
 	__le32 ecc_buf_cfg;
+	__le32 read_location0;
+	__le32 read_location1;
+	__le32 read_location2;
+	__le32 read_location3;
+
 };
 
 /*
@@ -518,6 +536,14 @@ static __le32 *offset_to_nandc_reg(struct nandc_regs *regs, int offset)
 		return &regs->orig_vld;
 	case NAND_EBI2_ECC_BUF_CFG:
 		return &regs->ecc_buf_cfg;
+	case NAND_READ_LOCATION_0:
+		return &regs->read_location0;
+	case NAND_READ_LOCATION_1:
+		return &regs->read_location1;
+	case NAND_READ_LOCATION_2:
+		return &regs->read_location2;
+	case NAND_READ_LOCATION_3:
+		return &regs->read_location3;
 	default:
 		return NULL;
 	}
@@ -592,6 +618,10 @@ static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read)
 	nandc_set_reg(nandc, NAND_FLASH_STATUS, host->clrflashstatus);
 	nandc_set_reg(nandc, NAND_READ_STATUS, host->clrreadstatus);
 	nandc_set_reg(nandc, NAND_EXEC_CMD, 1);
+
+	if (read)
+		nandc_set_readl(nandc, 0, 0, host->use_ecc ?
+				host->cw_data : host->cw_size, 1);
 }
 
 /*
@@ -837,6 +867,10 @@ static void config_nand_page_read(struct qcom_nand_controller *nandc)
  */
 static void config_nand_cw_read(struct qcom_nand_controller *nandc)
 {
+	if (nandc->props->is_bam)
+		write_reg_dma(nandc, NAND_READ_LOCATION_0, 4,
+			      NAND_BAM_NEXT_SGL);
+
 	write_reg_dma(nandc, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
 	write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
 
@@ -926,6 +960,7 @@ static int nandc_param(struct qcom_nand_host *host)
 
 	nandc_set_reg(nandc, NAND_DEV_CMD1_RESTORE, nandc->cmd1);
 	nandc_set_reg(nandc, NAND_DEV_CMD_VLD_RESTORE, nandc->vld);
+	nandc_set_readl(nandc, 0, 0, 512, 1);
 
 	write_reg_dma(nandc, NAND_DEV_CMD_VLD, 1, 0);
 	write_reg_dma(nandc, NAND_DEV_CMD1, 1, NAND_BAM_NEXT_SGL);
@@ -1401,6 +1436,19 @@ static int read_page_ecc(struct qcom_nand_host *host, u8 *data_buf,
 			oob_size = host->ecc_bytes_hw + host->spare_bytes;
 		}
 
+		if (nandc->props->is_bam) {
+			if (data_buf && oob_buf) {
+				nandc_set_readl(nandc, 0, 0, data_size, 0);
+				nandc_set_readl(nandc, 1, data_size,
+						oob_size, 1);
+			} else if (data_buf) {
+				nandc_set_readl(nandc, 0, 0, data_size, 1);
+			} else {
+				nandc_set_readl(nandc, 0, data_size,
+						oob_size, 1);
+			}
+		}
+
 		config_nand_cw_read(nandc);
 
 		if (data_buf)
@@ -1460,6 +1508,7 @@ static int copy_last_cw(struct qcom_nand_host *host, int page)
 
 	set_address(host, host->cw_size * (ecc->steps - 1), page);
 	update_rw_regs(host, 1, true);
+	nandc_set_readl(nandc, 0, 0, size, 1);
 
 	config_nand_single_cw_page_read(nandc);
 
@@ -1505,6 +1554,7 @@ static int qcom_nandc_read_page_raw(struct mtd_info *mtd,
 	u8 *data_buf, *oob_buf;
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 	int i, ret;
+	int read_loc;
 
 	data_buf = buf;
 	oob_buf = chip->oob_poi;
@@ -1530,6 +1580,20 @@ static int qcom_nandc_read_page_raw(struct mtd_info *mtd,
 			oob_size2 = host->ecc_bytes_hw + host->spare_bytes;
 		}
 
+		if (nandc->props->is_bam) {
+			read_loc = 0;
+			nandc_set_readl(nandc, 0, read_loc, data_size1, 0);
+			read_loc += data_size1;
+
+			nandc_set_readl(nandc, 1, read_loc, oob_size1, 0);
+			read_loc += oob_size1;
+
+			nandc_set_readl(nandc, 2, read_loc, data_size2, 0);
+			read_loc += data_size2;
+
+			nandc_set_readl(nandc, 3, read_loc, oob_size2, 1);
+		}
+
 		config_nand_cw_read(nandc);
 
 		read_data_dma(nandc, reg_off, data_buf, data_size1, 0);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 10/20] mtd: nand: qcom: erased codeword detection configuration
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
                   ` (8 preceding siblings ...)
  2017-08-05 16:19 ` [PATCH v3 09/20] mtd: nand: qcom: support for read location registers Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 11/20] mtd: nand: qcom: enable BAM or ADM mode Abhishek Sahu
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

The NAND controller returns ECC failure during read of completely
erased codeword. The NAND controller has hardware functionality
to detect erased codeword in case of BCH ECC algorithm. The
NAND_ERASED_CW_DETECT_CFG register controls the erased
codeword/page detection controller. This register should be reset
before every page read by setting and clearing bit 0 of
NAND_ERASED_CW_DETECT_CFG.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/mtd/nand/qcom_nandc.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index 28543c1..67c7e62 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -202,6 +202,11 @@
 #define NAND_BAM_NWD			BIT(1)
 /* Finish writing in the current sgl and start writing in another sgl */
 #define NAND_BAM_NEXT_SGL		BIT(2)
+/*
+ * Erased codeword status is being used two times in single transfer so this
+ * flag will determine the current value of erased codeword status register
+ */
+#define NAND_ERASED_CW_SET		BIT(4)
 
 /*
  * This data type corresponds to the BAM transaction which will be used for all
@@ -280,6 +285,8 @@ struct nandc_regs {
 	__le32 read_location2;
 	__le32 read_location3;
 
+	__le32 erased_cw_detect_cfg_clr;
+	__le32 erased_cw_detect_cfg_set;
 };
 
 /*
@@ -807,6 +814,13 @@ static int write_reg_dma(struct qcom_nand_controller *nandc, int first,
 	if (first == NAND_FLASH_CMD)
 		flow_control = true;
 
+	if (first == NAND_ERASED_CW_DETECT_CFG) {
+		if (flags & NAND_ERASED_CW_SET)
+			vaddr = &regs->erased_cw_detect_cfg_set;
+		else
+			vaddr = &regs->erased_cw_detect_cfg_clr;
+	}
+
 	if (first == NAND_EXEC_CMD)
 		flags |= NAND_BAM_NWD;
 
@@ -859,6 +873,9 @@ static void config_nand_page_read(struct qcom_nand_controller *nandc)
 	write_reg_dma(nandc, NAND_ADDR0, 2, 0);
 	write_reg_dma(nandc, NAND_DEV0_CFG0, 3, 0);
 	write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1, 0);
+	write_reg_dma(nandc, NAND_ERASED_CW_DETECT_CFG, 1, 0);
+	write_reg_dma(nandc, NAND_ERASED_CW_DETECT_CFG, 1,
+		      NAND_ERASED_CW_SET | NAND_BAM_NEXT_SGL);
 }
 
 /*
@@ -2261,6 +2278,10 @@ static int qcom_nand_host_setup(struct qcom_nand_host *host)
 
 	host->clrflashstatus = FS_READY_BSY_N;
 	host->clrreadstatus = 0xc0;
+	nandc->regs->erased_cw_detect_cfg_clr =
+		cpu_to_le32(CLR_ERASED_PAGE_DET);
+	nandc->regs->erased_cw_detect_cfg_set =
+		cpu_to_le32(SET_ERASED_PAGE_DET);
 
 	dev_dbg(nandc->dev,
 		"cfg0 %x cfg1 %x ecc_buf_cfg %x ecc_bch cfg %x cw_size %d cw_data %d strength %d parity_bytes %d steps %d\n",
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 11/20] mtd: nand: qcom: enable BAM or ADM mode
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
                   ` (9 preceding siblings ...)
  2017-08-05 16:19 ` [PATCH v3 10/20] mtd: nand: qcom: erased codeword detection configuration Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 12/20] mtd: nand: qcom: QPIC data descriptors handling Abhishek Sahu
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

1. DM_EN is only required for EBI2 NAND controller which uses ADM
2. BAM mode will be disabled after power on reset which needs to
   be enabled before starting any BAM transfers.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/mtd/nand/qcom_nandc.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index 67c7e62..af69a89 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -165,6 +165,9 @@
 					 BIT(ERASE_START_VALID)	| \
 					 BIT(SEQ_READ_START_VLD))
 
+/* NAND_CTRL bits */
+#define	BAM_MODE_EN			BIT(0)
+
 /*
  * the NAND controller performs reads/writes with ECC in 516 byte chunks.
  * the driver calls the chunks 'step' or 'codeword' interchangeably
@@ -1038,7 +1041,8 @@ static int read_id(struct qcom_nand_host *host, int column)
 	nandc_set_reg(nandc, NAND_FLASH_CMD, FETCH_ID);
 	nandc_set_reg(nandc, NAND_ADDR0, column);
 	nandc_set_reg(nandc, NAND_ADDR1, 0);
-	nandc_set_reg(nandc, NAND_FLASH_CHIP_SELECT, DM_EN);
+	nandc_set_reg(nandc, NAND_FLASH_CHIP_SELECT,
+		      nandc->props->is_bam ? 0 : DM_EN);
 	nandc_set_reg(nandc, NAND_EXEC_CMD, 1);
 
 	write_reg_dma(nandc, NAND_FLASH_CMD, 4, NAND_BAM_NEXT_SGL);
@@ -2411,12 +2415,19 @@ static void qcom_nandc_unalloc(struct qcom_nand_controller *nandc)
 /* one time setup of a few nand controller registers */
 static int qcom_nandc_setup(struct qcom_nand_controller *nandc)
 {
+	u32 nand_ctrl;
+
 	/* kill onenand */
 	nandc_write(nandc, SFLASHC_BURST_CFG, 0);
 	nandc_write(nandc, NAND_DEV_CMD_VLD, NAND_DEV_CMD_VLD_VAL);
 
-	/* enable ADM DMA */
-	nandc_write(nandc, NAND_FLASH_CHIP_SELECT, DM_EN);
+	/* enable ADM or BAM DMA */
+	if (nandc->props->is_bam) {
+		nand_ctrl = nandc_read(nandc, NAND_CTRL);
+		nandc_write(nandc, NAND_CTRL, nand_ctrl | BAM_MODE_EN);
+	} else {
+		nandc_write(nandc, NAND_FLASH_CHIP_SELECT, DM_EN);
+	}
 
 	/* save the original values of these registers */
 	nandc->cmd1 = nandc_read(nandc, NAND_DEV_CMD1);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 12/20] mtd: nand: qcom: QPIC data descriptors handling
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
                   ` (10 preceding siblings ...)
  2017-08-05 16:19 ` [PATCH v3 11/20] mtd: nand: qcom: enable BAM or ADM mode Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 13/20] mtd: nand: qcom: support for different DEV_CMD register offsets Abhishek Sahu
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

1. Add the data descriptor preparation function which will be used
   only by BAM DMA for forming the data SGL’s
2. Add clear BAM transaction and call it before every new request
3. Check DMA mode for ADM or BAM and call the appropriate
   descriptor formation function.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/mtd/nand/qcom_nandc.c | 76 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index af69a89..d7a2ca4 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -472,6 +472,27 @@ static void free_bam_transaction(struct qcom_nand_controller *nandc)
 	return bam_txn;
 }
 
+/* Clears the BAM transaction indexes */
+static void clear_bam_transaction(struct qcom_nand_controller *nandc)
+{
+	struct bam_transaction *bam_txn = nandc->bam_txn;
+
+	if (!nandc->props->is_bam)
+		return;
+
+	bam_txn->cmd_sgl_pos = 0;
+	bam_txn->cmd_sgl_start = 0;
+	bam_txn->tx_sgl_pos = 0;
+	bam_txn->tx_sgl_start = 0;
+	bam_txn->rx_sgl_pos = 0;
+	bam_txn->rx_sgl_start = 0;
+
+	sg_init_table(bam_txn->cmd_sgl, nandc->max_cwperpage *
+		      QPIC_PER_CW_CMD_SGL);
+	sg_init_table(bam_txn->data_sgl, nandc->max_cwperpage *
+		      QPIC_PER_CW_DATA_SGL);
+}
+
 static inline struct qcom_nand_host *to_qcom_nand_host(struct nand_chip *chip)
 {
 	return container_of(chip, struct qcom_nand_host, chip);
@@ -703,6 +724,41 @@ static int prepare_bam_async_desc(struct qcom_nand_controller *nandc,
 	return 0;
 }
 
+/*
+ * Prepares the data descriptor for BAM DMA which will be used for NAND
+ * data reads and writes.
+ */
+static int prep_bam_dma_desc_data(struct qcom_nand_controller *nandc, bool read,
+				  const void *vaddr,
+				  int size, unsigned int flags)
+{
+	int ret;
+	struct bam_transaction *bam_txn = nandc->bam_txn;
+
+	if (read) {
+		sg_set_buf(&bam_txn->data_sgl[bam_txn->rx_sgl_pos],
+			   vaddr, size);
+		bam_txn->rx_sgl_pos++;
+	} else {
+		sg_set_buf(&bam_txn->data_sgl[bam_txn->tx_sgl_pos],
+			   vaddr, size);
+		bam_txn->tx_sgl_pos++;
+
+		/*
+		 * BAM will only set EOT for DMA_PREP_INTERRUPT so if this flag
+		 * is not set, form the DMA descriptor
+		 */
+		if (!(flags & NAND_BAM_NO_EOT)) {
+			ret = prepare_bam_async_desc(nandc, nandc->tx_chan,
+						     DMA_PREP_INTERRUPT);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
 static int prep_adm_dma_desc(struct qcom_nand_controller *nandc, bool read,
 			     int reg_off, const void *vaddr, int size,
 			     bool flow_control)
@@ -850,6 +906,9 @@ static int write_reg_dma(struct qcom_nand_controller *nandc, int first,
 static int read_data_dma(struct qcom_nand_controller *nandc, int reg_off,
 			 const u8 *vaddr, int size, unsigned int flags)
 {
+	if (nandc->props->is_bam)
+		return prep_bam_dma_desc_data(nandc, true, vaddr, size, flags);
+
 	return prep_adm_dma_desc(nandc, true, reg_off, vaddr, size, false);
 }
 
@@ -864,6 +923,9 @@ static int read_data_dma(struct qcom_nand_controller *nandc, int reg_off,
 static int write_data_dma(struct qcom_nand_controller *nandc, int reg_off,
 			  const u8 *vaddr, int size, unsigned int flags)
 {
+	if (nandc->props->is_bam)
+		return prep_bam_dma_desc_data(nandc, false, vaddr, size, flags);
+
 	return prep_adm_dma_desc(nandc, false, reg_off, vaddr, size, false);
 }
 
@@ -1152,6 +1214,10 @@ static void pre_command(struct qcom_nand_host *host, int command)
 	host->last_command = command;
 
 	clear_read_regs(nandc);
+
+	if (command == NAND_CMD_RESET || command == NAND_CMD_READID ||
+	    command == NAND_CMD_PARAM || command == NAND_CMD_ERASE1)
+		clear_bam_transaction(nandc);
 }
 
 /*
@@ -1556,6 +1622,7 @@ static int qcom_nandc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 	data_buf = buf;
 	oob_buf = oob_required ? chip->oob_poi : NULL;
 
+	clear_bam_transaction(nandc);
 	ret = read_page_ecc(host, data_buf, oob_buf);
 	if (ret) {
 		dev_err(nandc->dev, "failure to read page\n");
@@ -1581,6 +1648,8 @@ static int qcom_nandc_read_page_raw(struct mtd_info *mtd,
 	oob_buf = chip->oob_poi;
 
 	host->use_ecc = false;
+
+	clear_bam_transaction(nandc);
 	update_rw_regs(host, ecc->steps, true);
 	config_nand_page_read(nandc);
 
@@ -1652,6 +1721,7 @@ static int qcom_nandc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
 	int ret;
 
 	clear_read_regs(nandc);
+	clear_bam_transaction(nandc);
 
 	host->use_ecc = true;
 	set_address(host, 0, page);
@@ -1675,6 +1745,7 @@ static int qcom_nandc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 	int i, ret;
 
 	clear_read_regs(nandc);
+	clear_bam_transaction(nandc);
 
 	data_buf = (u8 *)buf;
 	oob_buf = chip->oob_poi;
@@ -1740,6 +1811,7 @@ static int qcom_nandc_write_page_raw(struct mtd_info *mtd,
 	int i, ret;
 
 	clear_read_regs(nandc);
+	clear_bam_transaction(nandc);
 
 	data_buf = (u8 *)buf;
 	oob_buf = chip->oob_poi;
@@ -1816,11 +1888,13 @@ static int qcom_nandc_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
 
 	host->use_ecc = true;
 
+	clear_bam_transaction(nandc);
 	ret = copy_last_cw(host, page);
 	if (ret)
 		return ret;
 
 	clear_read_regs(nandc);
+	clear_bam_transaction(nandc);
 
 	/* calculate the data and oob size for the last codeword/step */
 	data_size = ecc->size - ((ecc->steps - 1) << 2);
@@ -1873,6 +1947,7 @@ static int qcom_nandc_block_bad(struct mtd_info *mtd, loff_t ofs)
 	 */
 	host->use_ecc = false;
 
+	clear_bam_transaction(nandc);
 	ret = copy_last_cw(host, page);
 	if (ret)
 		goto err;
@@ -1903,6 +1978,7 @@ static int qcom_nandc_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	int page, ret, status = 0;
 
 	clear_read_regs(nandc);
+	clear_bam_transaction(nandc);
 
 	/*
 	 * to mark the BBM as bad, we flash the entire last codeword with 0s.
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 13/20] mtd: nand: qcom: support for different DEV_CMD register offsets
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
                   ` (11 preceding siblings ...)
  2017-08-05 16:19 ` [PATCH v3 12/20] mtd: nand: qcom: QPIC data descriptors handling Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 14/20] mtd: nand: qcom: add command elements in BAM transaction Abhishek Sahu
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

The FLASH_DEV_CMD registers starting offset is not same in
different QPIC NAND controller versions. This patch adds
the starting offset in NAND controller properties and uses
the same for calculating the actual offset of these registers.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/mtd/nand/qcom_nandc.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index d7a2ca4..c940a20 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -195,6 +195,9 @@
 	      ((size) << READ_LOCATION_SIZE) |			\
 	      ((is_last) << READ_LOCATION_LAST))
 
+/* Returns the actual register address for NAND_FLASH_DEV_* */
+#define nandc_dev_addr(nandc, reg) ((nandc)->props->flash_dev_offset + (reg))
+
 #define QPIC_PER_CW_CMD_SGL		32
 #define QPIC_PER_CW_DATA_SGL		8
 
@@ -428,10 +431,12 @@ struct qcom_nand_host {
  * among different NAND controllers.
  * @ecc_modes - ecc mode for NAND
  * @is_bam - whether NAND controller is using BAM
+ * @flash_dev_offset - NAND_FLASH_DEV_* registers start offset
  */
 struct qcom_nandc_props {
 	u32 ecc_modes;
 	bool is_bam;
+	u32 flash_dev_offset;
 };
 
 /* Frees the BAM transaction memory */
@@ -846,6 +851,9 @@ static int read_reg_dma(struct qcom_nand_controller *nandc, int first,
 	if (first == NAND_READ_ID || first == NAND_FLASH_STATUS)
 		flow_control = true;
 
+	if (first == NAND_DEV_CMD_VLD || first == NAND_DEV_CMD1)
+		first = nandc_dev_addr(nandc, first);
+
 	size = num_regs * sizeof(u32);
 	vaddr = nandc->reg_read_buf + nandc->reg_read_pos;
 	nandc->reg_read_pos += num_regs;
@@ -883,11 +891,11 @@ static int write_reg_dma(struct qcom_nand_controller *nandc, int first,
 	if (first == NAND_EXEC_CMD)
 		flags |= NAND_BAM_NWD;
 
-	if (first == NAND_DEV_CMD1_RESTORE)
-		first = NAND_DEV_CMD1;
+	if (first == NAND_DEV_CMD1_RESTORE || first == NAND_DEV_CMD1)
+		first = nandc_dev_addr(nandc, NAND_DEV_CMD1);
 
-	if (first == NAND_DEV_CMD_VLD_RESTORE)
-		first = NAND_DEV_CMD_VLD;
+	if (first == NAND_DEV_CMD_VLD_RESTORE || first == NAND_DEV_CMD_VLD)
+		first = nandc_dev_addr(nandc, NAND_DEV_CMD_VLD);
 
 	size = num_regs * sizeof(u32);
 
@@ -2495,7 +2503,8 @@ static int qcom_nandc_setup(struct qcom_nand_controller *nandc)
 
 	/* kill onenand */
 	nandc_write(nandc, SFLASHC_BURST_CFG, 0);
-	nandc_write(nandc, NAND_DEV_CMD_VLD, NAND_DEV_CMD_VLD_VAL);
+	nandc_write(nandc, nandc_dev_addr(nandc, NAND_DEV_CMD_VLD),
+		    NAND_DEV_CMD_VLD_VAL);
 
 	/* enable ADM or BAM DMA */
 	if (nandc->props->is_bam) {
@@ -2506,7 +2515,7 @@ static int qcom_nandc_setup(struct qcom_nand_controller *nandc)
 	}
 
 	/* save the original values of these registers */
-	nandc->cmd1 = nandc_read(nandc, NAND_DEV_CMD1);
+	nandc->cmd1 = nandc_read(nandc, nandc_dev_addr(nandc, NAND_DEV_CMD1));
 	nandc->vld = NAND_DEV_CMD_VLD_VAL;
 
 	return 0;
@@ -2755,6 +2764,7 @@ static int qcom_nandc_remove(struct platform_device *pdev)
 static const struct qcom_nandc_props ipq806x_nandc_props = {
 	.ecc_modes = (ECC_RS_4BIT | ECC_BCH_8BIT),
 	.is_bam = false,
+	.flash_dev_offset = 0x0,
 };
 
 /*
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 14/20] mtd: nand: qcom: add command elements in BAM transaction
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
                   ` (12 preceding siblings ...)
  2017-08-05 16:19 ` [PATCH v3 13/20] mtd: nand: qcom: support for different DEV_CMD register offsets Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-09  8:29   ` Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 15/20] mtd: nand: qcom: support for command descriptor formation Abhishek Sahu
                   ` (5 subsequent siblings)
  19 siblings, 1 reply; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

All the QPIC register read/write through BAM DMA requires
command descriptor which contains the array of command elements.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/mtd/nand/qcom_nandc.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index c940a20..9c12404 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -22,6 +22,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/delay.h>
+#include <linux/dma/qcom_bam_dma.h>
 
 /* NANDc reg offsets */
 #define	NAND_FLASH_CMD			0x00
@@ -198,6 +199,7 @@
 /* Returns the actual register address for NAND_FLASH_DEV_* */
 #define nandc_dev_addr(nandc, reg) ((nandc)->props->flash_dev_offset + (reg))
 
+#define QPIC_PER_CW_CMD_ELEMENTS	32
 #define QPIC_PER_CW_CMD_SGL		32
 #define QPIC_PER_CW_DATA_SGL		8
 
@@ -217,8 +219,13 @@
 /*
  * This data type corresponds to the BAM transaction which will be used for all
  * NAND transfers.
+ * @bam_ce - the array of BAM command elements
  * @cmd_sgl - sgl for NAND BAM command pipe
  * @data_sgl - sgl for NAND BAM consumer/producer pipe
+ * @bam_ce_pos - the index in bam_ce which is available for next sgl
+ * @bam_ce_start - the index in bam_ce which marks the start position ce
+ *		   for current sgl. It will be used for size calculation
+ *		   for current sgl
  * @cmd_sgl_pos - current index in command sgl.
  * @cmd_sgl_start - start index in command sgl.
  * @tx_sgl_pos - current index in data sgl for tx.
@@ -227,8 +234,11 @@
  * @rx_sgl_start - start index in data sgl for rx.
  */
 struct bam_transaction {
+	struct bam_cmd_element *bam_ce;
 	struct scatterlist *cmd_sgl;
 	struct scatterlist *data_sgl;
+	u32 bam_ce_pos;
+	u32 bam_ce_start;
 	u32 cmd_sgl_pos;
 	u32 cmd_sgl_start;
 	u32 tx_sgl_pos;
@@ -458,7 +468,8 @@ static void free_bam_transaction(struct qcom_nand_controller *nandc)
 
 	bam_txn_size =
 		sizeof(*bam_txn) + num_cw *
-		((sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL) +
+		((sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS) +
+		(sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL) +
 		(sizeof(*bam_txn->data_sgl) * QPIC_PER_CW_DATA_SGL));
 
 	bam_txn_buf = devm_kzalloc(nandc->dev, bam_txn_size, GFP_KERNEL);
@@ -468,6 +479,10 @@ static void free_bam_transaction(struct qcom_nand_controller *nandc)
 	bam_txn = bam_txn_buf;
 	bam_txn_buf += sizeof(*bam_txn);
 
+	bam_txn->bam_ce = bam_txn_buf;
+	bam_txn_buf +=
+		sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS * num_cw;
+
 	bam_txn->cmd_sgl = bam_txn_buf;
 	bam_txn_buf +=
 		sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL * num_cw;
@@ -485,6 +500,8 @@ static void clear_bam_transaction(struct qcom_nand_controller *nandc)
 	if (!nandc->props->is_bam)
 		return;
 
+	bam_txn->bam_ce_pos = 0;
+	bam_txn->bam_ce_start = 0;
 	bam_txn->cmd_sgl_pos = 0;
 	bam_txn->cmd_sgl_start = 0;
 	bam_txn->tx_sgl_pos = 0;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 15/20] mtd: nand: qcom: support for command descriptor formation
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
                   ` (13 preceding siblings ...)
  2017-08-05 16:19 ` [PATCH v3 14/20] mtd: nand: qcom: add command elements in BAM transaction Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-09  8:32   ` Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 16/20] dt-bindings: qcom_nandc: fix the ipq806x device tree example Abhishek Sahu
                   ` (4 subsequent siblings)
  19 siblings, 1 reply; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

1. Add the function for command descriptor preparation which will
   be used only by BAM DMA and it will form the DMA descriptors
   containing command elements
2. DMA_PREP_CMD flag should be used for forming command DMA
   descriptors

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/mtd/nand/qcom_nandc.c | 108 +++++++++++++++++++++++++++++++++++-------
 1 file changed, 92 insertions(+), 16 deletions(-)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index 9c12404..16463ac 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -196,6 +196,14 @@
 	      ((size) << READ_LOCATION_SIZE) |			\
 	      ((is_last) << READ_LOCATION_LAST))
 
+/* Returns the NAND register physical address */
+#define nandc_reg_phys(chip, offset) ((chip)->base_phys + (offset))
+
+/* Returns the dma address for reg read buffer */
+#define reg_buf_dma_addr(chip, vaddr) \
+	((chip)->reg_read_dma + \
+	((uint8_t *)(vaddr) - (uint8_t *)(chip)->reg_read_buf))
+
 /* Returns the actual register address for NAND_FLASH_DEV_* */
 #define nandc_dev_addr(nandc, reg) ((nandc)->props->flash_dev_offset + (reg))
 
@@ -313,7 +321,8 @@ struct nandc_regs {
  *				controller
  * @dev:			parent device
  * @base:			MMIO base
- * @base_dma:			physical base address of controller registers
+ * @base_phys:			physical base address of controller registers
+ * @base_dma:			dma base address of controller registers
  * @core_clk:			controller clock
  * @aon_clk:			another controller clock
  *
@@ -346,6 +355,7 @@ struct qcom_nand_controller {
 	struct device *dev;
 
 	void __iomem *base;
+	phys_addr_t base_phys;
 	dma_addr_t base_dma;
 
 	struct clk *core_clk;
@@ -747,6 +757,66 @@ static int prepare_bam_async_desc(struct qcom_nand_controller *nandc,
 }
 
 /*
+ * Prepares the command descriptor for BAM DMA which will be used for NAND
+ * register reads and writes. The command descriptor requires the command
+ * to be formed in command element type so this function uses the command
+ * element from bam transaction ce array and fills the same with required
+ * data. A single SGL can contain multiple command elements so
+ * NAND_BAM_NEXT_SGL will be used for starting the separate SGL
+ * after the current command element.
+ */
+static int prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, bool read,
+				 int reg_off, const void *vaddr,
+				 int size, unsigned int flags)
+{
+	int bam_ce_size;
+	int i, ret;
+	struct bam_cmd_element *bam_ce_buffer;
+	struct bam_transaction *bam_txn = nandc->bam_txn;
+
+	bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_pos];
+
+	/* fill the command desc */
+	for (i = 0; i < size; i++) {
+		if (read)
+			bam_prep_ce(&bam_ce_buffer[i],
+				    nandc_reg_phys(nandc, reg_off + 4 * i),
+				    BAM_READ_COMMAND,
+				    reg_buf_dma_addr(nandc,
+						     (__le32 *)vaddr + i));
+		else
+			bam_prep_ce_le32(&bam_ce_buffer[i],
+					 nandc_reg_phys(nandc, reg_off + 4 * i),
+					 BAM_WRITE_COMMAND,
+					 *((__le32 *)vaddr + i));
+	}
+
+	bam_txn->bam_ce_pos += size;
+
+	/* use the separate sgl after this command */
+	if (flags & NAND_BAM_NEXT_SGL) {
+		bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_start];
+		bam_ce_size = (bam_txn->bam_ce_pos -
+				bam_txn->bam_ce_start) *
+				sizeof(struct bam_cmd_element);
+		sg_set_buf(&bam_txn->cmd_sgl[bam_txn->cmd_sgl_pos],
+			   bam_ce_buffer, bam_ce_size);
+		bam_txn->cmd_sgl_pos++;
+		bam_txn->bam_ce_start = bam_txn->bam_ce_pos;
+
+		if (flags & NAND_BAM_NWD) {
+			ret = prepare_bam_async_desc(nandc, nandc->cmd_chan,
+						     DMA_PREP_FENCE |
+						     DMA_PREP_CMD);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+/*
  * Prepares the data descriptor for BAM DMA which will be used for NAND
  * data reads and writes.
  */
@@ -863,19 +933,22 @@ static int read_reg_dma(struct qcom_nand_controller *nandc, int first,
 {
 	bool flow_control = false;
 	void *vaddr;
-	int size;
 
-	if (first == NAND_READ_ID || first == NAND_FLASH_STATUS)
-		flow_control = true;
+	vaddr = nandc->reg_read_buf + nandc->reg_read_pos;
+	nandc->reg_read_pos += num_regs;
 
 	if (first == NAND_DEV_CMD_VLD || first == NAND_DEV_CMD1)
 		first = nandc_dev_addr(nandc, first);
 
-	size = num_regs * sizeof(u32);
-	vaddr = nandc->reg_read_buf + nandc->reg_read_pos;
-	nandc->reg_read_pos += num_regs;
+	if (nandc->props->is_bam)
+		return prep_bam_dma_desc_cmd(nandc, true, first, vaddr,
+					     num_regs, flags);
 
-	return prep_adm_dma_desc(nandc, true, first, vaddr, size, flow_control);
+	if (first == NAND_READ_ID || first == NAND_FLASH_STATUS)
+		flow_control = true;
+
+	return prep_adm_dma_desc(nandc, true, first, vaddr,
+				 num_regs * sizeof(u32), flow_control);
 }
 
 /*
@@ -891,13 +964,9 @@ static int write_reg_dma(struct qcom_nand_controller *nandc, int first,
 	bool flow_control = false;
 	struct nandc_regs *regs = nandc->regs;
 	void *vaddr;
-	int size;
 
 	vaddr = offset_to_nandc_reg(regs, first);
 
-	if (first == NAND_FLASH_CMD)
-		flow_control = true;
-
 	if (first == NAND_ERASED_CW_DETECT_CFG) {
 		if (flags & NAND_ERASED_CW_SET)
 			vaddr = &regs->erased_cw_detect_cfg_set;
@@ -914,10 +983,15 @@ static int write_reg_dma(struct qcom_nand_controller *nandc, int first,
 	if (first == NAND_DEV_CMD_VLD_RESTORE || first == NAND_DEV_CMD_VLD)
 		first = nandc_dev_addr(nandc, NAND_DEV_CMD_VLD);
 
-	size = num_regs * sizeof(u32);
+	if (nandc->props->is_bam)
+		return prep_bam_dma_desc_cmd(nandc, false, first, vaddr,
+					     num_regs, flags);
+
+	if (first == NAND_FLASH_CMD)
+		flow_control = true;
 
-	return prep_adm_dma_desc(nandc, false, first, vaddr, size,
-				 flow_control);
+	return prep_adm_dma_desc(nandc, false, first, vaddr,
+				 num_regs * sizeof(u32), flow_control);
 }
 
 /*
@@ -1180,7 +1254,8 @@ static int submit_descs(struct qcom_nand_controller *nandc)
 		}
 
 		if (bam_txn->cmd_sgl_pos > bam_txn->cmd_sgl_start) {
-			r = prepare_bam_async_desc(nandc, nandc->cmd_chan, 0);
+			r = prepare_bam_async_desc(nandc, nandc->cmd_chan,
+						   DMA_PREP_CMD);
 			if (r)
 				return r;
 		}
@@ -2716,6 +2791,7 @@ static int qcom_nandc_probe(struct platform_device *pdev)
 	if (IS_ERR(nandc->base))
 		return PTR_ERR(nandc->base);
 
+	nandc->base_phys = res->start;
 	nandc->base_dma = phys_to_dma(dev, (phys_addr_t)res->start);
 
 	nandc->core_clk = devm_clk_get(dev, "core");
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 16/20] dt-bindings: qcom_nandc: fix the ipq806x device tree example
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
                   ` (14 preceding siblings ...)
  2017-08-05 16:19 ` [PATCH v3 15/20] mtd: nand: qcom: support for command descriptor formation Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-10 20:26   ` Rob Herring
  2017-08-05 16:19 ` [PATCH v3 17/20] dt-bindings: qcom_nandc: IPQ4019 QPIC NAND documentation Abhishek Sahu
                   ` (3 subsequent siblings)
  19 siblings, 1 reply; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

1. Correct the compatible string for IPQ806x
2. Change the NAND controller and NAND chip nodes name
   for more clarity.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 Documentation/devicetree/bindings/mtd/qcom_nandc.txt | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/mtd/qcom_nandc.txt b/Documentation/devicetree/bindings/mtd/qcom_nandc.txt
index 26360fe..f475b65 100644
--- a/Documentation/devicetree/bindings/mtd/qcom_nandc.txt
+++ b/Documentation/devicetree/bindings/mtd/qcom_nandc.txt
@@ -42,8 +42,8 @@ partition.txt for more detail.
 
 Example:
 
-nand@1ac00000 {
-	compatible = "qcom,ebi2-nandc";
+nand-controller@1ac00000 {
+	compatible = "qcom,ipq806x-nand";
 	reg = <0x1ac00000 0x800>;
 
 	clocks = <&gcc EBI2_CLK>,
@@ -58,7 +58,7 @@ nand@1ac00000 {
 	#address-cells = <1>;
 	#size-cells = <0>;
 
-	nandcs@0 {
+	nand@0 {
 		reg = <0>;
 
 		nand-ecc-strength = <4>;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 17/20] dt-bindings: qcom_nandc: IPQ4019 QPIC NAND documentation
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
                   ` (15 preceding siblings ...)
  2017-08-05 16:19 ` [PATCH v3 16/20] dt-bindings: qcom_nandc: fix the ipq806x device tree example Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-10 20:27   ` Rob Herring
  2017-08-05 16:19 ` [PATCH v3 18/20] dt-bindings: qcom_nandc: IPQ8074 " Abhishek Sahu
                   ` (2 subsequent siblings)
  19 siblings, 1 reply; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

1. Qualcom IPQ4019 SoC uses QPIC NAND controller version 1.4.0
   which uses BAM DMA Engine while IPQ806x uses EBI2 NAND
   which uses ADM DMA Engine.
2. QPIC NAND will 3 BAM channels: command, data tx and data rx
   while EBI2 NAND uses only single ADM channel.
3. CRCI is only required for ADM DMA and its not required for
   BAM DMA.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 .../devicetree/bindings/mtd/qcom_nandc.txt         | 55 +++++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mtd/qcom_nandc.txt b/Documentation/devicetree/bindings/mtd/qcom_nandc.txt
index f475b65..d93b952 100644
--- a/Documentation/devicetree/bindings/mtd/qcom_nandc.txt
+++ b/Documentation/devicetree/bindings/mtd/qcom_nandc.txt
@@ -1,11 +1,18 @@
 * Qualcomm NAND controller
 
 Required properties:
-- compatible:		should be "qcom,ipq806x-nand"
+- compatible:		must be one of the following:
+    * "qcom,ipq806x-nand" - for EBI2 NAND controller being used in IPQ806x
+			    SoC and it uses ADM DMA
+    * "qcom,ipq4019-nand" - for QPIC NAND controller v1.4.0 being used in
+                            IPQ4019 SoC and it uses BAM DMA
+
 - reg:			MMIO address range
 - clocks:		must contain core clock and always on clock
 - clock-names:		must contain "core" for the core clock and "aon" for the
 			always on clock
+
+EBI2 specific properties:
 - dmas:			DMA specifier, consisting of a phandle to the ADM DMA
 			controller node and the channel number to be used for
 			NAND. Refer to dma.txt and qcom_adm.txt for more details
@@ -16,6 +23,12 @@ Required properties:
 - qcom,data-crci:	must contain the ADM data type CRCI block instance
 			number specified for the NAND controller on the given
 			platform
+
+QPIC specific properties:
+- dmas:			DMA specifier, consisting of a phandle to the BAM DMA
+			and the channel number to be used for NAND. Refer to
+			dma.txt, qcom_bam_dma.txt for more details
+- dma-names:		must contain all 3 channel names : "tx", "rx", "cmd"
 - #address-cells:	<1> - subnodes give the chip-select number
 - #size-cells:		<0>
 
@@ -82,3 +95,43 @@ nand-controller@1ac00000 {
 		};
 	};
 };
+
+nand-controller@79b0000 {
+	compatible = "qcom,ipq4019-nand";
+	reg = <0x79b0000 0x1000>;
+
+	clocks = <&gcc GCC_QPIC_CLK>,
+		<&gcc GCC_QPIC_AHB_CLK>;
+	clock-names = "core", "aon";
+
+	dmas = <&qpicbam 0>,
+		<&qpicbam 1>,
+		<&qpicbam 2>;
+	dma-names = "tx", "rx", "cmd";
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	nand@0 {
+		reg = <0>;
+		nand-ecc-strength = <4>;
+		nand-ecc-step-size = <512>;
+		nand-bus-width = <8>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "boot-nand";
+				reg = <0 0x58a0000>;
+			};
+
+			partition@58a0000 {
+				label = "fs-nand";
+				reg = <0x58a0000 0x4000000>;
+			};
+		};
+	};
+};
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 18/20] dt-bindings: qcom_nandc: IPQ8074 QPIC NAND documentation
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
                   ` (16 preceding siblings ...)
  2017-08-05 16:19 ` [PATCH v3 17/20] dt-bindings: qcom_nandc: IPQ4019 QPIC NAND documentation Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-10 20:30   ` Rob Herring
  2017-08-05 16:19 ` [PATCH v3 19/20] mtd: nand: qcom: Support for IPQ4019 QPIC NAND controller Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 20/20] mtd: nand: qcom: Support for IPQ8074 " Abhishek Sahu
  19 siblings, 1 reply; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

Qualcom IPQ8074 SoC uses QPIC NAND controller version 1.5.0
which uses BAM DMA Engine.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 Documentation/devicetree/bindings/mtd/qcom_nandc.txt | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mtd/qcom_nandc.txt b/Documentation/devicetree/bindings/mtd/qcom_nandc.txt
index d93b952..8dfa543 100644
--- a/Documentation/devicetree/bindings/mtd/qcom_nandc.txt
+++ b/Documentation/devicetree/bindings/mtd/qcom_nandc.txt
@@ -6,6 +6,8 @@ Required properties:
 			    SoC and it uses ADM DMA
     * "qcom,ipq4019-nand" - for QPIC NAND controller v1.4.0 being used in
                             IPQ4019 SoC and it uses BAM DMA
+    * "qcom,ipq8074-nand" - for QPIC NAND controller v1.5.0 being used in
+                            IPQ8074 SoC and it uses BAM DMA
 
 - reg:			MMIO address range
 - clocks:		must contain core clock and always on clock
@@ -97,7 +99,7 @@ nand-controller@1ac00000 {
 };
 
 nand-controller@79b0000 {
-	compatible = "qcom,ipq4019-nand";
+	compatible = "qcom,ipq4019-nand", "qcom,ipq8074-nand";
 	reg = <0x79b0000 0x1000>;
 
 	clocks = <&gcc GCC_QPIC_CLK>,
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 19/20] mtd: nand: qcom: Support for IPQ4019 QPIC NAND controller
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
                   ` (17 preceding siblings ...)
  2017-08-05 16:19 ` [PATCH v3 18/20] dt-bindings: qcom_nandc: IPQ8074 " Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  2017-08-05 16:19 ` [PATCH v3 20/20] mtd: nand: qcom: Support for IPQ8074 " Abhishek Sahu
  19 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

Add the compatible string for IPQ4019 QPIC NAND controller
version 1.4.0 which uses BAM DMA.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/mtd/nand/qcom_nandc.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index 16463ac..cc58e8f 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -2860,6 +2860,12 @@ static int qcom_nandc_remove(struct platform_device *pdev)
 	.flash_dev_offset = 0x0,
 };
 
+static const struct qcom_nandc_props ipq4019_nandc_props = {
+	.ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT),
+	.is_bam = true,
+	.flash_dev_offset = 0x0,
+};
+
 /*
  * data will hold a struct pointer containing more differences once we support
  * more controller variants
@@ -2869,6 +2875,10 @@ static int qcom_nandc_remove(struct platform_device *pdev)
 		.compatible = "qcom,ipq806x-nand",
 		.data = &ipq806x_nandc_props,
 	},
+	{
+		.compatible = "qcom,ipq4019-nand",
+		.data = &ipq4019_nandc_props,
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(of, qcom_nandc_of_match);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH v3 20/20] mtd: nand: qcom: Support for IPQ8074 QPIC NAND controller
  2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
                   ` (18 preceding siblings ...)
  2017-08-05 16:19 ` [PATCH v3 19/20] mtd: nand: qcom: Support for IPQ4019 QPIC NAND controller Abhishek Sahu
@ 2017-08-05 16:19 ` Abhishek Sahu
  19 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-05 16:19 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan,
	Abhishek Sahu

Add the compatible string for IPQ8074 QPIC NAND controller
version 1.5.0 which uses BAM DMA and its FLASH_DEV_CMD registers
starting offset is 0x7000.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/mtd/nand/qcom_nandc.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index cc58e8f..d606262 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -2866,6 +2866,12 @@ static int qcom_nandc_remove(struct platform_device *pdev)
 	.flash_dev_offset = 0x0,
 };
 
+static const struct qcom_nandc_props ipq8074_nandc_props = {
+	.ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT),
+	.is_bam = true,
+	.flash_dev_offset = 0x7000,
+};
+
 /*
  * data will hold a struct pointer containing more differences once we support
  * more controller variants
@@ -2879,6 +2885,10 @@ static int qcom_nandc_remove(struct platform_device *pdev)
 		.compatible = "qcom,ipq4019-nand",
 		.data = &ipq4019_nandc_props,
 	},
+	{
+		.compatible = "qcom,ipq8074-nand",
+		.data = &ipq8074_nandc_props,
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(of, qcom_nandc_of_match);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

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

* Re: [PATCH v3 14/20] mtd: nand: qcom: add command elements in BAM transaction
  2017-08-05 16:19 ` [PATCH v3 14/20] mtd: nand: qcom: add command elements in BAM transaction Abhishek Sahu
@ 2017-08-09  8:29   ` Abhishek Sahu
  0 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-09  8:29 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan

On 2017-08-05 21:49, Abhishek Sahu wrote:
> All the QPIC register read/write through BAM DMA requires
> command descriptor which contains the array of command elements.
> 
> Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>

  This patch has build dependency on
  http://www.spinics.net/lists/dmaengine/msg13665.html

> ---
>  drivers/mtd/nand/qcom_nandc.c | 19 ++++++++++++++++++-
>  1 file changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/nand/qcom_nandc.c 
> b/drivers/mtd/nand/qcom_nandc.c
> index c940a20..9c12404 100644
> --- a/drivers/mtd/nand/qcom_nandc.c
> +++ b/drivers/mtd/nand/qcom_nandc.c
> @@ -22,6 +22,7 @@
>  #include <linux/of.h>
>  #include <linux/of_device.h>
>  #include <linux/delay.h>
> +#include <linux/dma/qcom_bam_dma.h>
> 
>  /* NANDc reg offsets */
>  #define	NAND_FLASH_CMD			0x00
> @@ -198,6 +199,7 @@
>  /* Returns the actual register address for NAND_FLASH_DEV_* */
>  #define nandc_dev_addr(nandc, reg) ((nandc)->props->flash_dev_offset + 
> (reg))
> 
> +#define QPIC_PER_CW_CMD_ELEMENTS	32
>  #define QPIC_PER_CW_CMD_SGL		32
>  #define QPIC_PER_CW_DATA_SGL		8
> 
> @@ -217,8 +219,13 @@
>  /*
>   * This data type corresponds to the BAM transaction which will be 
> used for all
>   * NAND transfers.
> + * @bam_ce - the array of BAM command elements
>   * @cmd_sgl - sgl for NAND BAM command pipe
>   * @data_sgl - sgl for NAND BAM consumer/producer pipe
> + * @bam_ce_pos - the index in bam_ce which is available for next sgl
> + * @bam_ce_start - the index in bam_ce which marks the start position 
> ce
> + *		   for current sgl. It will be used for size calculation
> + *		   for current sgl
>   * @cmd_sgl_pos - current index in command sgl.
>   * @cmd_sgl_start - start index in command sgl.
>   * @tx_sgl_pos - current index in data sgl for tx.
> @@ -227,8 +234,11 @@
>   * @rx_sgl_start - start index in data sgl for rx.
>   */
>  struct bam_transaction {
> +	struct bam_cmd_element *bam_ce;
>  	struct scatterlist *cmd_sgl;
>  	struct scatterlist *data_sgl;
> +	u32 bam_ce_pos;
> +	u32 bam_ce_start;
>  	u32 cmd_sgl_pos;
>  	u32 cmd_sgl_start;
>  	u32 tx_sgl_pos;
> @@ -458,7 +468,8 @@ static void free_bam_transaction(struct
> qcom_nand_controller *nandc)
> 
>  	bam_txn_size =
>  		sizeof(*bam_txn) + num_cw *
> -		((sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL) +
> +		((sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS) +
> +		(sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL) +
>  		(sizeof(*bam_txn->data_sgl) * QPIC_PER_CW_DATA_SGL));
> 
>  	bam_txn_buf = devm_kzalloc(nandc->dev, bam_txn_size, GFP_KERNEL);
> @@ -468,6 +479,10 @@ static void free_bam_transaction(struct
> qcom_nand_controller *nandc)
>  	bam_txn = bam_txn_buf;
>  	bam_txn_buf += sizeof(*bam_txn);
> 
> +	bam_txn->bam_ce = bam_txn_buf;
> +	bam_txn_buf +=
> +		sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS * num_cw;
> +
>  	bam_txn->cmd_sgl = bam_txn_buf;
>  	bam_txn_buf +=
>  		sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL * num_cw;
> @@ -485,6 +500,8 @@ static void clear_bam_transaction(struct
> qcom_nand_controller *nandc)
>  	if (!nandc->props->is_bam)
>  		return;
> 
> +	bam_txn->bam_ce_pos = 0;
> +	bam_txn->bam_ce_start = 0;
>  	bam_txn->cmd_sgl_pos = 0;
>  	bam_txn->cmd_sgl_start = 0;
>  	bam_txn->tx_sgl_pos = 0;

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

* Re: [PATCH v3 15/20] mtd: nand: qcom: support for command descriptor formation
  2017-08-05 16:19 ` [PATCH v3 15/20] mtd: nand: qcom: support for command descriptor formation Abhishek Sahu
@ 2017-08-09  8:32   ` Abhishek Sahu
  0 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-09  8:32 UTC (permalink / raw)
  To: dwmw2, boris.brezillon, computersforpeace, marek.vasut, robh+dt,
	mark.rutland
  Cc: richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan

On 2017-08-05 21:49, Abhishek Sahu wrote:
> 1. Add the function for command descriptor preparation which will
>    be used only by BAM DMA and it will form the DMA descriptors
>    containing command elements
> 2. DMA_PREP_CMD flag should be used for forming command DMA
>    descriptors
> 
> Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>

  This patch has build dependency on
  http://www.spinics.net/lists/dmaengine/msg13665.html

> ---
>  drivers/mtd/nand/qcom_nandc.c | 108 
> +++++++++++++++++++++++++++++++++++-------
>  1 file changed, 92 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/mtd/nand/qcom_nandc.c 
> b/drivers/mtd/nand/qcom_nandc.c
> index 9c12404..16463ac 100644
> --- a/drivers/mtd/nand/qcom_nandc.c
> +++ b/drivers/mtd/nand/qcom_nandc.c
> @@ -196,6 +196,14 @@
>  	      ((size) << READ_LOCATION_SIZE) |			\
>  	      ((is_last) << READ_LOCATION_LAST))
> 
> +/* Returns the NAND register physical address */
> +#define nandc_reg_phys(chip, offset) ((chip)->base_phys + (offset))
> +
> +/* Returns the dma address for reg read buffer */
> +#define reg_buf_dma_addr(chip, vaddr) \
> +	((chip)->reg_read_dma + \
> +	((uint8_t *)(vaddr) - (uint8_t *)(chip)->reg_read_buf))
> +
>  /* Returns the actual register address for NAND_FLASH_DEV_* */
>  #define nandc_dev_addr(nandc, reg) ((nandc)->props->flash_dev_offset + 
> (reg))
> 
> @@ -313,7 +321,8 @@ struct nandc_regs {
>   *				controller
>   * @dev:			parent device
>   * @base:			MMIO base
> - * @base_dma:			physical base address of controller registers
> + * @base_phys:			physical base address of controller registers
> + * @base_dma:			dma base address of controller registers
>   * @core_clk:			controller clock
>   * @aon_clk:			another controller clock
>   *
> @@ -346,6 +355,7 @@ struct qcom_nand_controller {
>  	struct device *dev;
> 
>  	void __iomem *base;
> +	phys_addr_t base_phys;
>  	dma_addr_t base_dma;
> 
>  	struct clk *core_clk;
> @@ -747,6 +757,66 @@ static int prepare_bam_async_desc(struct
> qcom_nand_controller *nandc,
>  }
> 
>  /*
> + * Prepares the command descriptor for BAM DMA which will be used for 
> NAND
> + * register reads and writes. The command descriptor requires the 
> command
> + * to be formed in command element type so this function uses the 
> command
> + * element from bam transaction ce array and fills the same with 
> required
> + * data. A single SGL can contain multiple command elements so
> + * NAND_BAM_NEXT_SGL will be used for starting the separate SGL
> + * after the current command element.
> + */
> +static int prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, 
> bool read,
> +				 int reg_off, const void *vaddr,
> +				 int size, unsigned int flags)
> +{
> +	int bam_ce_size;
> +	int i, ret;
> +	struct bam_cmd_element *bam_ce_buffer;
> +	struct bam_transaction *bam_txn = nandc->bam_txn;
> +
> +	bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_pos];
> +
> +	/* fill the command desc */
> +	for (i = 0; i < size; i++) {
> +		if (read)
> +			bam_prep_ce(&bam_ce_buffer[i],
> +				    nandc_reg_phys(nandc, reg_off + 4 * i),
> +				    BAM_READ_COMMAND,
> +				    reg_buf_dma_addr(nandc,
> +						     (__le32 *)vaddr + i));
> +		else
> +			bam_prep_ce_le32(&bam_ce_buffer[i],
> +					 nandc_reg_phys(nandc, reg_off + 4 * i),
> +					 BAM_WRITE_COMMAND,
> +					 *((__le32 *)vaddr + i));
> +	}
> +
> +	bam_txn->bam_ce_pos += size;
> +
> +	/* use the separate sgl after this command */
> +	if (flags & NAND_BAM_NEXT_SGL) {
> +		bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_start];
> +		bam_ce_size = (bam_txn->bam_ce_pos -
> +				bam_txn->bam_ce_start) *
> +				sizeof(struct bam_cmd_element);
> +		sg_set_buf(&bam_txn->cmd_sgl[bam_txn->cmd_sgl_pos],
> +			   bam_ce_buffer, bam_ce_size);
> +		bam_txn->cmd_sgl_pos++;
> +		bam_txn->bam_ce_start = bam_txn->bam_ce_pos;
> +
> +		if (flags & NAND_BAM_NWD) {
> +			ret = prepare_bam_async_desc(nandc, nandc->cmd_chan,
> +						     DMA_PREP_FENCE |
> +						     DMA_PREP_CMD);
> +			if (ret)
> +				return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +/*
>   * Prepares the data descriptor for BAM DMA which will be used for 
> NAND
>   * data reads and writes.
>   */
> @@ -863,19 +933,22 @@ static int read_reg_dma(struct
> qcom_nand_controller *nandc, int first,
>  {
>  	bool flow_control = false;
>  	void *vaddr;
> -	int size;
> 
> -	if (first == NAND_READ_ID || first == NAND_FLASH_STATUS)
> -		flow_control = true;
> +	vaddr = nandc->reg_read_buf + nandc->reg_read_pos;
> +	nandc->reg_read_pos += num_regs;
> 
>  	if (first == NAND_DEV_CMD_VLD || first == NAND_DEV_CMD1)
>  		first = nandc_dev_addr(nandc, first);
> 
> -	size = num_regs * sizeof(u32);
> -	vaddr = nandc->reg_read_buf + nandc->reg_read_pos;
> -	nandc->reg_read_pos += num_regs;
> +	if (nandc->props->is_bam)
> +		return prep_bam_dma_desc_cmd(nandc, true, first, vaddr,
> +					     num_regs, flags);
> 
> -	return prep_adm_dma_desc(nandc, true, first, vaddr, size, 
> flow_control);
> +	if (first == NAND_READ_ID || first == NAND_FLASH_STATUS)
> +		flow_control = true;
> +
> +	return prep_adm_dma_desc(nandc, true, first, vaddr,
> +				 num_regs * sizeof(u32), flow_control);
>  }
> 
>  /*
> @@ -891,13 +964,9 @@ static int write_reg_dma(struct
> qcom_nand_controller *nandc, int first,
>  	bool flow_control = false;
>  	struct nandc_regs *regs = nandc->regs;
>  	void *vaddr;
> -	int size;
> 
>  	vaddr = offset_to_nandc_reg(regs, first);
> 
> -	if (first == NAND_FLASH_CMD)
> -		flow_control = true;
> -
>  	if (first == NAND_ERASED_CW_DETECT_CFG) {
>  		if (flags & NAND_ERASED_CW_SET)
>  			vaddr = &regs->erased_cw_detect_cfg_set;
> @@ -914,10 +983,15 @@ static int write_reg_dma(struct
> qcom_nand_controller *nandc, int first,
>  	if (first == NAND_DEV_CMD_VLD_RESTORE || first == NAND_DEV_CMD_VLD)
>  		first = nandc_dev_addr(nandc, NAND_DEV_CMD_VLD);
> 
> -	size = num_regs * sizeof(u32);
> +	if (nandc->props->is_bam)
> +		return prep_bam_dma_desc_cmd(nandc, false, first, vaddr,
> +					     num_regs, flags);
> +
> +	if (first == NAND_FLASH_CMD)
> +		flow_control = true;
> 
> -	return prep_adm_dma_desc(nandc, false, first, vaddr, size,
> -				 flow_control);
> +	return prep_adm_dma_desc(nandc, false, first, vaddr,
> +				 num_regs * sizeof(u32), flow_control);
>  }
> 
>  /*
> @@ -1180,7 +1254,8 @@ static int submit_descs(struct
> qcom_nand_controller *nandc)
>  		}
> 
>  		if (bam_txn->cmd_sgl_pos > bam_txn->cmd_sgl_start) {
> -			r = prepare_bam_async_desc(nandc, nandc->cmd_chan, 0);
> +			r = prepare_bam_async_desc(nandc, nandc->cmd_chan,
> +						   DMA_PREP_CMD);
>  			if (r)
>  				return r;
>  		}
> @@ -2716,6 +2791,7 @@ static int qcom_nandc_probe(struct 
> platform_device *pdev)
>  	if (IS_ERR(nandc->base))
>  		return PTR_ERR(nandc->base);
> 
> +	nandc->base_phys = res->start;
>  	nandc->base_dma = phys_to_dma(dev, (phys_addr_t)res->start);
> 
>  	nandc->core_clk = devm_clk_get(dev, "core");

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

* Re: [PATCH v3 01/20] mtd: nand: qcom: program NAND_DEV_CMD_VLD register
  2017-08-05 16:19 ` [PATCH v3 01/20] mtd: nand: qcom: program NAND_DEV_CMD_VLD register Abhishek Sahu
@ 2017-08-10  9:42   ` Boris Brezillon
  2017-08-10 10:31     ` Abhishek Sahu
  0 siblings, 1 reply; 29+ messages in thread
From: Boris Brezillon @ 2017-08-10  9:42 UTC (permalink / raw)
  To: Abhishek Sahu
  Cc: dwmw2, computersforpeace, marek.vasut, robh+dt, mark.rutland,
	richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan, stable

Le Sat,  5 Aug 2017 21:49:39 +0530,
Abhishek Sahu <absahu@codeaurora.org> a écrit :

> The NAND page read fails without complete boot chain since
> NAND_DEV_CMD_VLD value is not proper. The default power on reset
> value for this register is
> 
>     0xe - ERASE_START_VALID | WRITE_START_VALID | READ_STOP_VALID
> 
> The READ_START_VALID should be enabled for sending PAGE_READ
> command. READ_STOP_VALID should be cleared since normal NAND
> page read does not require READ_STOP command.
> 
> Fixes: c76b78d8ec05a ("mtd: nand: Qualcomm NAND controller driver")
> Cc: stable@vger.kernel.org
> Reviewed-by: Archit Taneja <architt@codeaurora.org>
> Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
> ---
>  drivers/mtd/nand/qcom_nandc.c | 13 ++++++++++++-
>  1 file changed, 12 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
> index 0289f09..7406019 100644
> --- a/drivers/mtd/nand/qcom_nandc.c
> +++ b/drivers/mtd/nand/qcom_nandc.c
> @@ -110,6 +110,10 @@
>  
>  /* NAND_DEV_CMD_VLD bits */
>  #define	READ_START_VLD			0
> +#define	READ_STOP_VALID			1
> +#define	WRITE_START_VALID		2
> +#define	ERASE_START_VALID		3
> +#define	SEQ_READ_START_VLD		4

Why not

#define	READ_START_VLD				BIT(0)
#define	READ_STOP_VALID				BIT(1)
#define	WRITE_START_VALID			BIT(2)
#define	ERASE_START_VALID			BIT(3)
#define	SEQ_READ_START_VLD			BIT(4)

>  
>  /* NAND_EBI2_ECC_BUF_CFG bits */
>  #define	NUM_STEPS			0
> @@ -148,6 +152,12 @@
>  #define	FETCH_ID			0xb
>  #define	RESET_DEVICE			0xd
>  
> +/* Default Value for NAND_DEV_CMD_VLD */
> +#define NAND_DEV_CMD_VLD_VAL		(BIT(READ_START_VLD)	| \
> +					 BIT(WRITE_START_VALID)	| \
> +					 BIT(ERASE_START_VALID)	| \
> +					 BIT(SEQ_READ_START_VLD))
> +

and then:

#define NAND_DEV_CMD_VLD_VAL	(READ_START_VLD	| \
				 WRITE_START_VALID | \
				 ERASE_START_VALID | \
				 SEQ_READ_START_VLD)

BTW, can you use consistent suffixes? Sometime definitions are suffixed
with _VLD and others are suffixed with _VALID.

>  /*
>   * the NAND controller performs reads/writes with ECC in 516 byte chunks.
>   * the driver calls the chunks 'step' or 'codeword' interchangeably
> @@ -1995,13 +2005,14 @@ static int qcom_nandc_setup(struct qcom_nand_controller *nandc)
>  {
>  	/* kill onenand */
>  	nandc_write(nandc, SFLASHC_BURST_CFG, 0);
> +	nandc_write(nandc, NAND_DEV_CMD_VLD, NAND_DEV_CMD_VLD_VAL);
>  
>  	/* enable ADM DMA */
>  	nandc_write(nandc, NAND_FLASH_CHIP_SELECT, DM_EN);
>  
>  	/* save the original values of these registers */
>  	nandc->cmd1 = nandc_read(nandc, NAND_DEV_CMD1);
> -	nandc->vld = nandc_read(nandc, NAND_DEV_CMD_VLD);
> +	nandc->vld = NAND_DEV_CMD_VLD_VAL;
>  
>  	return 0;
>  }

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

* Re: [PATCH v3 01/20] mtd: nand: qcom: program NAND_DEV_CMD_VLD register
  2017-08-10  9:42   ` Boris Brezillon
@ 2017-08-10 10:31     ` Abhishek Sahu
  0 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-10 10:31 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: dwmw2, computersforpeace, marek.vasut, robh+dt, mark.rutland,
	richard, cyrille.pitchen, devicetree, linux-arm-msm,
	linux-kernel, linux-mtd, andy.gross, architt, sricharan, stable

On 2017-08-10 15:12, Boris Brezillon wrote:
> Le Sat,  5 Aug 2017 21:49:39 +0530,
> Abhishek Sahu <absahu@codeaurora.org> a écrit :
> 
>> The NAND page read fails without complete boot chain since
>> NAND_DEV_CMD_VLD value is not proper. The default power on reset
>> value for this register is
>> 
>>     0xe - ERASE_START_VALID | WRITE_START_VALID | READ_STOP_VALID
>> 
>> The READ_START_VALID should be enabled for sending PAGE_READ
>> command. READ_STOP_VALID should be cleared since normal NAND
>> page read does not require READ_STOP command.
>> 
>> Fixes: c76b78d8ec05a ("mtd: nand: Qualcomm NAND controller driver")
>> Cc: stable@vger.kernel.org
>> Reviewed-by: Archit Taneja <architt@codeaurora.org>
>> Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
>> ---
>>  drivers/mtd/nand/qcom_nandc.c | 13 ++++++++++++-
>>  1 file changed, 12 insertions(+), 1 deletion(-)
>> 
>> diff --git a/drivers/mtd/nand/qcom_nandc.c 
>> b/drivers/mtd/nand/qcom_nandc.c
>> index 0289f09..7406019 100644
>> --- a/drivers/mtd/nand/qcom_nandc.c
>> +++ b/drivers/mtd/nand/qcom_nandc.c
>> @@ -110,6 +110,10 @@
>> 
>>  /* NAND_DEV_CMD_VLD bits */
>>  #define	READ_START_VLD			0
>> +#define	READ_STOP_VALID			1
>> +#define	WRITE_START_VALID		2
>> +#define	ERASE_START_VALID		3
>> +#define	SEQ_READ_START_VLD		4
> 
> Why not
> 
> #define	READ_START_VLD				BIT(0)
> #define	READ_STOP_VALID				BIT(1)
> #define	WRITE_START_VALID			BIT(2)
> #define	ERASE_START_VALID			BIT(3)
> #define	SEQ_READ_START_VLD			BIT(4)
> 

  Sure. we can change to use BIT macro.

  We are using READ_START_VLD only at one place so will replace in
  current code from

  /* configure CMD1 and VLD for ONFI param probing */
         nandc_set_reg(nandc, NAND_DEV_CMD_VLD,
                       (nandc->vld & ~(1 << READ_START_VLD))
                       | 0 << READ_START_VLD);
  to

  nandc_set_reg(nandc, NAND_DEV_CMD_VLD, nandc->vld & ~READ_START_VLD)

>> 
>>  /* NAND_EBI2_ECC_BUF_CFG bits */
>>  #define	NUM_STEPS			0
>> @@ -148,6 +152,12 @@
>>  #define	FETCH_ID			0xb
>>  #define	RESET_DEVICE			0xd
>> 
>> +/* Default Value for NAND_DEV_CMD_VLD */
>> +#define NAND_DEV_CMD_VLD_VAL		(BIT(READ_START_VLD)	| \
>> +					 BIT(WRITE_START_VALID)	| \
>> +					 BIT(ERASE_START_VALID)	| \
>> +					 BIT(SEQ_READ_START_VLD))
>> +
> 
> and then:
> 
> #define NAND_DEV_CMD_VLD_VAL	(READ_START_VLD	| \
> 				 WRITE_START_VALID | \
> 				 ERASE_START_VALID | \
> 				 SEQ_READ_START_VLD)
> 
> BTW, can you use consistent suffixes? Sometime definitions are suffixed
> with _VLD and others are suffixed with _VALID.
> 

  Sure. I will change all the names to _VLD.

>>  /*
>>   * the NAND controller performs reads/writes with ECC in 516 byte 
>> chunks.
>>   * the driver calls the chunks 'step' or 'codeword' interchangeably
>> @@ -1995,13 +2005,14 @@ static int qcom_nandc_setup(struct 
>> qcom_nand_controller *nandc)
>>  {
>>  	/* kill onenand */
>>  	nandc_write(nandc, SFLASHC_BURST_CFG, 0);
>> +	nandc_write(nandc, NAND_DEV_CMD_VLD, NAND_DEV_CMD_VLD_VAL);
>> 
>>  	/* enable ADM DMA */
>>  	nandc_write(nandc, NAND_FLASH_CHIP_SELECT, DM_EN);
>> 
>>  	/* save the original values of these registers */
>>  	nandc->cmd1 = nandc_read(nandc, NAND_DEV_CMD1);
>> -	nandc->vld = nandc_read(nandc, NAND_DEV_CMD_VLD);
>> +	nandc->vld = NAND_DEV_CMD_VLD_VAL;
>> 
>>  	return 0;
>>  }

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

* Re: [PATCH v3 16/20] dt-bindings: qcom_nandc: fix the ipq806x device tree example
  2017-08-05 16:19 ` [PATCH v3 16/20] dt-bindings: qcom_nandc: fix the ipq806x device tree example Abhishek Sahu
@ 2017-08-10 20:26   ` Rob Herring
  0 siblings, 0 replies; 29+ messages in thread
From: Rob Herring @ 2017-08-10 20:26 UTC (permalink / raw)
  To: Abhishek Sahu
  Cc: dwmw2, boris.brezillon, computersforpeace, marek.vasut,
	mark.rutland, richard, cyrille.pitchen, devicetree,
	linux-arm-msm, linux-kernel, linux-mtd, andy.gross, architt,
	sricharan

On Sat, Aug 05, 2017 at 09:49:54PM +0530, Abhishek Sahu wrote:
> 1. Correct the compatible string for IPQ806x
> 2. Change the NAND controller and NAND chip nodes name
>    for more clarity.
> 
> Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
> ---
>  Documentation/devicetree/bindings/mtd/qcom_nandc.txt | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)

Acked-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v3 17/20] dt-bindings: qcom_nandc: IPQ4019 QPIC NAND documentation
  2017-08-05 16:19 ` [PATCH v3 17/20] dt-bindings: qcom_nandc: IPQ4019 QPIC NAND documentation Abhishek Sahu
@ 2017-08-10 20:27   ` Rob Herring
  0 siblings, 0 replies; 29+ messages in thread
From: Rob Herring @ 2017-08-10 20:27 UTC (permalink / raw)
  To: Abhishek Sahu
  Cc: dwmw2, boris.brezillon, computersforpeace, marek.vasut,
	mark.rutland, richard, cyrille.pitchen, devicetree,
	linux-arm-msm, linux-kernel, linux-mtd, andy.gross, architt,
	sricharan

On Sat, Aug 05, 2017 at 09:49:55PM +0530, Abhishek Sahu wrote:
> 1. Qualcom IPQ4019 SoC uses QPIC NAND controller version 1.4.0
>    which uses BAM DMA Engine while IPQ806x uses EBI2 NAND
>    which uses ADM DMA Engine.
> 2. QPIC NAND will 3 BAM channels: command, data tx and data rx
>    while EBI2 NAND uses only single ADM channel.
> 3. CRCI is only required for ADM DMA and its not required for
>    BAM DMA.
> 
> Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
> ---
>  .../devicetree/bindings/mtd/qcom_nandc.txt         | 55 +++++++++++++++++++++-
>  1 file changed, 54 insertions(+), 1 deletion(-)

Acked-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v3 18/20] dt-bindings: qcom_nandc: IPQ8074 QPIC NAND documentation
  2017-08-05 16:19 ` [PATCH v3 18/20] dt-bindings: qcom_nandc: IPQ8074 " Abhishek Sahu
@ 2017-08-10 20:30   ` Rob Herring
  2017-08-11  9:02     ` Abhishek Sahu
  0 siblings, 1 reply; 29+ messages in thread
From: Rob Herring @ 2017-08-10 20:30 UTC (permalink / raw)
  To: Abhishek Sahu
  Cc: dwmw2, boris.brezillon, computersforpeace, marek.vasut,
	mark.rutland, richard, cyrille.pitchen, devicetree,
	linux-arm-msm, linux-kernel, linux-mtd, andy.gross, architt,
	sricharan

On Sat, Aug 05, 2017 at 09:49:56PM +0530, Abhishek Sahu wrote:
> Qualcom IPQ8074 SoC uses QPIC NAND controller version 1.5.0
> which uses BAM DMA Engine.
> 
> Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
> ---
>  Documentation/devicetree/bindings/mtd/qcom_nandc.txt | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/mtd/qcom_nandc.txt b/Documentation/devicetree/bindings/mtd/qcom_nandc.txt
> index d93b952..8dfa543 100644
> --- a/Documentation/devicetree/bindings/mtd/qcom_nandc.txt
> +++ b/Documentation/devicetree/bindings/mtd/qcom_nandc.txt
> @@ -6,6 +6,8 @@ Required properties:
>  			    SoC and it uses ADM DMA
>      * "qcom,ipq4019-nand" - for QPIC NAND controller v1.4.0 being used in
>                              IPQ4019 SoC and it uses BAM DMA
> +    * "qcom,ipq8074-nand" - for QPIC NAND controller v1.5.0 being used in
> +                            IPQ8074 SoC and it uses BAM DMA
>  
>  - reg:			MMIO address range
>  - clocks:		must contain core clock and always on clock
> @@ -97,7 +99,7 @@ nand-controller@1ac00000 {
>  };
>  
>  nand-controller@79b0000 {
> -	compatible = "qcom,ipq4019-nand";
> +	compatible = "qcom,ipq4019-nand", "qcom,ipq8074-nand";

The order here should be reversed as 8074 is the newer one. And if 4019 
is the fallback compatible, that needs to be documented above.

Rob

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

* Re: [PATCH v3 18/20] dt-bindings: qcom_nandc: IPQ8074 QPIC NAND documentation
  2017-08-10 20:30   ` Rob Herring
@ 2017-08-11  9:02     ` Abhishek Sahu
  0 siblings, 0 replies; 29+ messages in thread
From: Abhishek Sahu @ 2017-08-11  9:02 UTC (permalink / raw)
  To: Rob Herring
  Cc: dwmw2, boris.brezillon, computersforpeace, marek.vasut,
	mark.rutland, richard, cyrille.pitchen, devicetree,
	linux-arm-msm, linux-kernel, linux-mtd, andy.gross, architt,
	sricharan

On 2017-08-11 02:00, Rob Herring wrote:
> On Sat, Aug 05, 2017 at 09:49:56PM +0530, Abhishek Sahu wrote:
>> Qualcom IPQ8074 SoC uses QPIC NAND controller version 1.5.0
>> which uses BAM DMA Engine.
>> 
>> Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
>> ---
>>  Documentation/devicetree/bindings/mtd/qcom_nandc.txt | 4 +++-
>>  1 file changed, 3 insertions(+), 1 deletion(-)
>> 
>> diff --git a/Documentation/devicetree/bindings/mtd/qcom_nandc.txt 
>> b/Documentation/devicetree/bindings/mtd/qcom_nandc.txt
>> index d93b952..8dfa543 100644
>> --- a/Documentation/devicetree/bindings/mtd/qcom_nandc.txt
>> +++ b/Documentation/devicetree/bindings/mtd/qcom_nandc.txt
>> @@ -6,6 +6,8 @@ Required properties:
>>  			    SoC and it uses ADM DMA
>>      * "qcom,ipq4019-nand" - for QPIC NAND controller v1.4.0 being 
>> used in
>>                              IPQ4019 SoC and it uses BAM DMA
>> +    * "qcom,ipq8074-nand" - for QPIC NAND controller v1.5.0 being 
>> used in
>> +                            IPQ8074 SoC and it uses BAM DMA
>> 
>>  - reg:			MMIO address range
>>  - clocks:		must contain core clock and always on clock
>> @@ -97,7 +99,7 @@ nand-controller@1ac00000 {
>>  };
>> 
>>  nand-controller@79b0000 {
>> -	compatible = "qcom,ipq4019-nand";
>> +	compatible = "qcom,ipq4019-nand", "qcom,ipq8074-nand";
> 
> The order here should be reversed as 8074 is the newer one. And if 4019
> is the fallback compatible, that needs to be documented above.
> 

  Thanks Rob for review.

  This is not fallback compatible. I checked the other device tree
  binding examples and it seems, we don't have to add every
  similar compatible string in example. I will remove the
  qcom,ipq8074-nand from example which is causing confusion.

> Rob

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

end of thread, other threads:[~2017-08-11  9:02 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-05 16:19 [PATCH v3 00/20] Add QCOM QPIC NAND support Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 01/20] mtd: nand: qcom: program NAND_DEV_CMD_VLD register Abhishek Sahu
2017-08-10  9:42   ` Boris Brezillon
2017-08-10 10:31     ` Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 02/20] mtd: nand: qcom: support for NAND controller properties Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 03/20] mtd: nand: qcom: add bam property for QPIC NAND controller Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 04/20] mtd: nand: qcom: add and initialize QPIC DMA resources Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 05/20] mtd: nand: qcom: DMA mapping support for register read buffer Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 06/20] mtd: nand: qcom: allocate BAM transaction Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 07/20] mtd: nand: qcom: add BAM DMA descriptor handling Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 08/20] mtd: nand: qcom: support for passing flags in transfer functions Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 09/20] mtd: nand: qcom: support for read location registers Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 10/20] mtd: nand: qcom: erased codeword detection configuration Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 11/20] mtd: nand: qcom: enable BAM or ADM mode Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 12/20] mtd: nand: qcom: QPIC data descriptors handling Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 13/20] mtd: nand: qcom: support for different DEV_CMD register offsets Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 14/20] mtd: nand: qcom: add command elements in BAM transaction Abhishek Sahu
2017-08-09  8:29   ` Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 15/20] mtd: nand: qcom: support for command descriptor formation Abhishek Sahu
2017-08-09  8:32   ` Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 16/20] dt-bindings: qcom_nandc: fix the ipq806x device tree example Abhishek Sahu
2017-08-10 20:26   ` Rob Herring
2017-08-05 16:19 ` [PATCH v3 17/20] dt-bindings: qcom_nandc: IPQ4019 QPIC NAND documentation Abhishek Sahu
2017-08-10 20:27   ` Rob Herring
2017-08-05 16:19 ` [PATCH v3 18/20] dt-bindings: qcom_nandc: IPQ8074 " Abhishek Sahu
2017-08-10 20:30   ` Rob Herring
2017-08-11  9:02     ` Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 19/20] mtd: nand: qcom: Support for IPQ4019 QPIC NAND controller Abhishek Sahu
2017-08-05 16:19 ` [PATCH v3 20/20] mtd: nand: qcom: Support for IPQ8074 " Abhishek Sahu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).