All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/10] ARM: berlin: add nand support
@ 2015-04-15 17:23 ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:23 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: Antoine Tenart, boris.brezillon, zmxu, jszhang, linux-arm-kernel,
	linux-mtd, linux-kernel

Hi all,

This series introduces the support for the Marvell Berlin nand
controller. It was tested on the Marvell Berlin BG2Q DMP board.

The support is added into the existing pxa3xx nand controller. Some
additions were done in order to get this controller working:
- Support for a non mandatory ECC clock has been added.
- The Berlin nand controller needs to poll the status register.
- Sequences of commands are quite different in order to perform write
  operation.

Since v3, this series had a lots of changes. The pxa3xx nand driver
was using its own flash table and had its own timings setup. I made
the required modifications to use the nand framework to perform these
steps. This worked nicely until we found out some boards use non-onfi
nands. To handle this case, I had to reintroduce the timing table in
the pxa3xx driver. In this case, the flash detection is done by the
framework, and the flash used *has to* be supported by the framework,
but its timing definitions remains inside the pxa3xx driver.

This should be tested on old platform using this driver, with non-onfi
devices and theirs definitions may have to be added in the nand_ids
table.

Another solution would have been to configure the timings in the
device tree, but this wouldn't have work for devices using board
files.

Antoine

Changes since v3:
        - Reworked the nand flash detection
        - Reworked the timings setup

Changes since v2:
        - Reworked the timings setup
        - Added a explanation in the default chunk size commit
        - Ensured commit 4/10 was useless and removed it
        - Fixed typos, cosmetic

Changes since v1:
        - Added a fallback to NULL when looking for the 'nfc' clock
        - Added the clocks in the bindings documentation
        - Reworked the DT
        - Removed non needed RNDOUT command
        - Used the standard RESET command
        - Fixed the flash type matching order
        - Remove all non tested flash types (only one left)
        - Added a check to explicitly not support nand chips with small pages
        - Remove useless checks for clocks in the probing function
        - Various clean up

Antoine Tenart (10):
  mtd: pxa3xx_nand: add a non mandatory ECC clock
  Documentation: bindings: document the clocks for pxa3xx-nand
  mtd: pxa3xx_nand: add a default chunk size
  mtd: pxa3xx_nand: rework flash detection and timing setup
  mtd: nand: add Samsung K9GBG08U0A-M to nand_ids table
  mtd: pxa3xx_nand: add support for the Marvell Berlin nand controller
  Documentation: bindings: add the Berlin nand controller compatible
  mtd: nand: let Marvell Berlin SoCs select the pxa3xx driver
  ARM: berlin: add BG2Q node for the nand
  ARM: berlin: enable flash on the BG2Q DMP

 .../devicetree/bindings/mtd/pxa3xx-nand.txt        |   5 +
 arch/arm/boot/dts/berlin2q-marvell-dmp.dts         |  25 ++
 arch/arm/boot/dts/berlin2q.dtsi                    |  13 +
 drivers/mtd/nand/Kconfig                           |   4 +-
 drivers/mtd/nand/nand_ids.c                        |   4 +
 drivers/mtd/nand/pxa3xx_nand.c                     | 432 +++++++++++++++------
 include/linux/platform_data/mtd-nand-pxa3xx.h      |  11 +-
 7 files changed, 366 insertions(+), 128 deletions(-)

-- 
2.3.5


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

* [PATCH v4 00/10] ARM: berlin: add nand support
@ 2015-04-15 17:23 ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:23 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: zmxu, boris.brezillon, Antoine Tenart, linux-kernel, linux-mtd,
	jszhang, linux-arm-kernel

Hi all,

This series introduces the support for the Marvell Berlin nand
controller. It was tested on the Marvell Berlin BG2Q DMP board.

The support is added into the existing pxa3xx nand controller. Some
additions were done in order to get this controller working:
- Support for a non mandatory ECC clock has been added.
- The Berlin nand controller needs to poll the status register.
- Sequences of commands are quite different in order to perform write
  operation.

Since v3, this series had a lots of changes. The pxa3xx nand driver
was using its own flash table and had its own timings setup. I made
the required modifications to use the nand framework to perform these
steps. This worked nicely until we found out some boards use non-onfi
nands. To handle this case, I had to reintroduce the timing table in
the pxa3xx driver. In this case, the flash detection is done by the
framework, and the flash used *has to* be supported by the framework,
but its timing definitions remains inside the pxa3xx driver.

This should be tested on old platform using this driver, with non-onfi
devices and theirs definitions may have to be added in the nand_ids
table.

Another solution would have been to configure the timings in the
device tree, but this wouldn't have work for devices using board
files.

Antoine

Changes since v3:
        - Reworked the nand flash detection
        - Reworked the timings setup

Changes since v2:
        - Reworked the timings setup
        - Added a explanation in the default chunk size commit
        - Ensured commit 4/10 was useless and removed it
        - Fixed typos, cosmetic

Changes since v1:
        - Added a fallback to NULL when looking for the 'nfc' clock
        - Added the clocks in the bindings documentation
        - Reworked the DT
        - Removed non needed RNDOUT command
        - Used the standard RESET command
        - Fixed the flash type matching order
        - Remove all non tested flash types (only one left)
        - Added a check to explicitly not support nand chips with small pages
        - Remove useless checks for clocks in the probing function
        - Various clean up

Antoine Tenart (10):
  mtd: pxa3xx_nand: add a non mandatory ECC clock
  Documentation: bindings: document the clocks for pxa3xx-nand
  mtd: pxa3xx_nand: add a default chunk size
  mtd: pxa3xx_nand: rework flash detection and timing setup
  mtd: nand: add Samsung K9GBG08U0A-M to nand_ids table
  mtd: pxa3xx_nand: add support for the Marvell Berlin nand controller
  Documentation: bindings: add the Berlin nand controller compatible
  mtd: nand: let Marvell Berlin SoCs select the pxa3xx driver
  ARM: berlin: add BG2Q node for the nand
  ARM: berlin: enable flash on the BG2Q DMP

 .../devicetree/bindings/mtd/pxa3xx-nand.txt        |   5 +
 arch/arm/boot/dts/berlin2q-marvell-dmp.dts         |  25 ++
 arch/arm/boot/dts/berlin2q.dtsi                    |  13 +
 drivers/mtd/nand/Kconfig                           |   4 +-
 drivers/mtd/nand/nand_ids.c                        |   4 +
 drivers/mtd/nand/pxa3xx_nand.c                     | 432 +++++++++++++++------
 include/linux/platform_data/mtd-nand-pxa3xx.h      |  11 +-
 7 files changed, 366 insertions(+), 128 deletions(-)

-- 
2.3.5

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

* [PATCH v4 00/10] ARM: berlin: add nand support
@ 2015-04-15 17:23 ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:23 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

This series introduces the support for the Marvell Berlin nand
controller. It was tested on the Marvell Berlin BG2Q DMP board.

The support is added into the existing pxa3xx nand controller. Some
additions were done in order to get this controller working:
- Support for a non mandatory ECC clock has been added.
- The Berlin nand controller needs to poll the status register.
- Sequences of commands are quite different in order to perform write
  operation.

Since v3, this series had a lots of changes. The pxa3xx nand driver
was using its own flash table and had its own timings setup. I made
the required modifications to use the nand framework to perform these
steps. This worked nicely until we found out some boards use non-onfi
nands. To handle this case, I had to reintroduce the timing table in
the pxa3xx driver. In this case, the flash detection is done by the
framework, and the flash used *has to* be supported by the framework,
but its timing definitions remains inside the pxa3xx driver.

This should be tested on old platform using this driver, with non-onfi
devices and theirs definitions may have to be added in the nand_ids
table.

Another solution would have been to configure the timings in the
device tree, but this wouldn't have work for devices using board
files.

Antoine

Changes since v3:
        - Reworked the nand flash detection
        - Reworked the timings setup

Changes since v2:
        - Reworked the timings setup
        - Added a explanation in the default chunk size commit
        - Ensured commit 4/10 was useless and removed it
        - Fixed typos, cosmetic

Changes since v1:
        - Added a fallback to NULL when looking for the 'nfc' clock
        - Added the clocks in the bindings documentation
        - Reworked the DT
        - Removed non needed RNDOUT command
        - Used the standard RESET command
        - Fixed the flash type matching order
        - Remove all non tested flash types (only one left)
        - Added a check to explicitly not support nand chips with small pages
        - Remove useless checks for clocks in the probing function
        - Various clean up

Antoine Tenart (10):
  mtd: pxa3xx_nand: add a non mandatory ECC clock
  Documentation: bindings: document the clocks for pxa3xx-nand
  mtd: pxa3xx_nand: add a default chunk size
  mtd: pxa3xx_nand: rework flash detection and timing setup
  mtd: nand: add Samsung K9GBG08U0A-M to nand_ids table
  mtd: pxa3xx_nand: add support for the Marvell Berlin nand controller
  Documentation: bindings: add the Berlin nand controller compatible
  mtd: nand: let Marvell Berlin SoCs select the pxa3xx driver
  ARM: berlin: add BG2Q node for the nand
  ARM: berlin: enable flash on the BG2Q DMP

 .../devicetree/bindings/mtd/pxa3xx-nand.txt        |   5 +
 arch/arm/boot/dts/berlin2q-marvell-dmp.dts         |  25 ++
 arch/arm/boot/dts/berlin2q.dtsi                    |  13 +
 drivers/mtd/nand/Kconfig                           |   4 +-
 drivers/mtd/nand/nand_ids.c                        |   4 +
 drivers/mtd/nand/pxa3xx_nand.c                     | 432 +++++++++++++++------
 include/linux/platform_data/mtd-nand-pxa3xx.h      |  11 +-
 7 files changed, 366 insertions(+), 128 deletions(-)

-- 
2.3.5

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

* [PATCH v4 01/10] mtd: pxa3xx_nand: add a non mandatory ECC clock
  2015-04-15 17:23 ` Antoine Tenart
  (?)
@ 2015-04-15 17:23   ` Antoine Tenart
  -1 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:23 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: Antoine Tenart, boris.brezillon, zmxu, jszhang, linux-arm-kernel,
	linux-mtd, linux-kernel

Some controllers (as the coming Berlin nand controller) need to enable
an ECC clock. Add support for this clock in the pxa3xx nand driver, and
leave it as non mandatory.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/pxa3xx_nand.c | 32 +++++++++++++++++++++++---------
 1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index d00ac392d1c4..55fce9527c2e 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -180,7 +180,7 @@ struct pxa3xx_nand_info {
 	struct nand_hw_control	controller;
 	struct platform_device	 *pdev;
 
-	struct clk		*clk;
+	struct clk		*clk, *ecc_clk;
 	void __iomem		*mmio_base;
 	unsigned long		mmio_phys;
 	struct completion	cmd_complete, dev_ready;
@@ -1608,15 +1608,26 @@ static int alloc_nand_resource(struct platform_device *pdev)
 
 	spin_lock_init(&chip->controller->lock);
 	init_waitqueue_head(&chip->controller->wq);
-	info->clk = devm_clk_get(&pdev->dev, NULL);
+	info->clk = devm_clk_get(&pdev->dev, "nfc");
 	if (IS_ERR(info->clk)) {
-		dev_err(&pdev->dev, "failed to get nand clock\n");
-		return PTR_ERR(info->clk);
+		info->clk = devm_clk_get(&pdev->dev, NULL);
+
+		if (IS_ERR(info->clk)) {
+			dev_err(&pdev->dev, "failed to get nand clock\n");
+			return PTR_ERR(info->clk);
+		}
 	}
 	ret = clk_prepare_enable(info->clk);
 	if (ret < 0)
 		return ret;
 
+	info->ecc_clk = devm_clk_get(&pdev->dev, "ecc");
+	if (!IS_ERR(info->ecc_clk)) {
+		ret = clk_prepare_enable(info->ecc_clk);
+		if (ret < 0)
+			goto fail_disable_clk;
+	}
+
 	if (use_dma) {
 		/*
 		 * This is a dirty hack to make this driver work from
@@ -1633,7 +1644,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
 				dev_err(&pdev->dev,
 					"no resource defined for data DMA\n");
 				ret = -ENXIO;
-				goto fail_disable_clk;
+				goto fail_disable_ecc_clk;
 			}
 			info->drcmr_dat = r->start;
 
@@ -1642,7 +1653,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
 				dev_err(&pdev->dev,
 					"no resource defined for cmd DMA\n");
 				ret = -ENXIO;
-				goto fail_disable_clk;
+				goto fail_disable_ecc_clk;
 			}
 			info->drcmr_cmd = r->start;
 		}
@@ -1652,14 +1663,14 @@ static int alloc_nand_resource(struct platform_device *pdev)
 	if (irq < 0) {
 		dev_err(&pdev->dev, "no IRQ resource defined\n");
 		ret = -ENXIO;
-		goto fail_disable_clk;
+		goto fail_disable_ecc_clk;
 	}
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	info->mmio_base = devm_ioremap_resource(&pdev->dev, r);
 	if (IS_ERR(info->mmio_base)) {
 		ret = PTR_ERR(info->mmio_base);
-		goto fail_disable_clk;
+		goto fail_disable_ecc_clk;
 	}
 	info->mmio_phys = r->start;
 
@@ -1668,7 +1679,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
 	info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
 	if (info->data_buff == NULL) {
 		ret = -ENOMEM;
-		goto fail_disable_clk;
+		goto fail_disable_ecc_clk;
 	}
 
 	/* initialize all interrupts to be disabled */
@@ -1687,6 +1698,8 @@ static int alloc_nand_resource(struct platform_device *pdev)
 fail_free_buf:
 	free_irq(irq, info);
 	kfree(info->data_buff);
+fail_disable_ecc_clk:
+	clk_disable_unprepare(info->ecc_clk);
 fail_disable_clk:
 	clk_disable_unprepare(info->clk);
 	return ret;
@@ -1709,6 +1722,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
 	pxa3xx_nand_free_buff(info);
 
 	clk_disable_unprepare(info->clk);
+	clk_disable_unprepare(info->ecc_clk);
 
 	for (cs = 0; cs < pdata->num_cs; cs++)
 		nand_release(info->host[cs]->mtd);
-- 
2.3.5


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

* [PATCH v4 01/10] mtd: pxa3xx_nand: add a non mandatory ECC clock
@ 2015-04-15 17:23   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:23 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: zmxu, boris.brezillon, Antoine Tenart, linux-kernel, linux-mtd,
	jszhang, linux-arm-kernel

Some controllers (as the coming Berlin nand controller) need to enable
an ECC clock. Add support for this clock in the pxa3xx nand driver, and
leave it as non mandatory.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/pxa3xx_nand.c | 32 +++++++++++++++++++++++---------
 1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index d00ac392d1c4..55fce9527c2e 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -180,7 +180,7 @@ struct pxa3xx_nand_info {
 	struct nand_hw_control	controller;
 	struct platform_device	 *pdev;
 
-	struct clk		*clk;
+	struct clk		*clk, *ecc_clk;
 	void __iomem		*mmio_base;
 	unsigned long		mmio_phys;
 	struct completion	cmd_complete, dev_ready;
@@ -1608,15 +1608,26 @@ static int alloc_nand_resource(struct platform_device *pdev)
 
 	spin_lock_init(&chip->controller->lock);
 	init_waitqueue_head(&chip->controller->wq);
-	info->clk = devm_clk_get(&pdev->dev, NULL);
+	info->clk = devm_clk_get(&pdev->dev, "nfc");
 	if (IS_ERR(info->clk)) {
-		dev_err(&pdev->dev, "failed to get nand clock\n");
-		return PTR_ERR(info->clk);
+		info->clk = devm_clk_get(&pdev->dev, NULL);
+
+		if (IS_ERR(info->clk)) {
+			dev_err(&pdev->dev, "failed to get nand clock\n");
+			return PTR_ERR(info->clk);
+		}
 	}
 	ret = clk_prepare_enable(info->clk);
 	if (ret < 0)
 		return ret;
 
+	info->ecc_clk = devm_clk_get(&pdev->dev, "ecc");
+	if (!IS_ERR(info->ecc_clk)) {
+		ret = clk_prepare_enable(info->ecc_clk);
+		if (ret < 0)
+			goto fail_disable_clk;
+	}
+
 	if (use_dma) {
 		/*
 		 * This is a dirty hack to make this driver work from
@@ -1633,7 +1644,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
 				dev_err(&pdev->dev,
 					"no resource defined for data DMA\n");
 				ret = -ENXIO;
-				goto fail_disable_clk;
+				goto fail_disable_ecc_clk;
 			}
 			info->drcmr_dat = r->start;
 
@@ -1642,7 +1653,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
 				dev_err(&pdev->dev,
 					"no resource defined for cmd DMA\n");
 				ret = -ENXIO;
-				goto fail_disable_clk;
+				goto fail_disable_ecc_clk;
 			}
 			info->drcmr_cmd = r->start;
 		}
@@ -1652,14 +1663,14 @@ static int alloc_nand_resource(struct platform_device *pdev)
 	if (irq < 0) {
 		dev_err(&pdev->dev, "no IRQ resource defined\n");
 		ret = -ENXIO;
-		goto fail_disable_clk;
+		goto fail_disable_ecc_clk;
 	}
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	info->mmio_base = devm_ioremap_resource(&pdev->dev, r);
 	if (IS_ERR(info->mmio_base)) {
 		ret = PTR_ERR(info->mmio_base);
-		goto fail_disable_clk;
+		goto fail_disable_ecc_clk;
 	}
 	info->mmio_phys = r->start;
 
@@ -1668,7 +1679,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
 	info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
 	if (info->data_buff == NULL) {
 		ret = -ENOMEM;
-		goto fail_disable_clk;
+		goto fail_disable_ecc_clk;
 	}
 
 	/* initialize all interrupts to be disabled */
@@ -1687,6 +1698,8 @@ static int alloc_nand_resource(struct platform_device *pdev)
 fail_free_buf:
 	free_irq(irq, info);
 	kfree(info->data_buff);
+fail_disable_ecc_clk:
+	clk_disable_unprepare(info->ecc_clk);
 fail_disable_clk:
 	clk_disable_unprepare(info->clk);
 	return ret;
@@ -1709,6 +1722,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
 	pxa3xx_nand_free_buff(info);
 
 	clk_disable_unprepare(info->clk);
+	clk_disable_unprepare(info->ecc_clk);
 
 	for (cs = 0; cs < pdata->num_cs; cs++)
 		nand_release(info->host[cs]->mtd);
-- 
2.3.5

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

* [PATCH v4 01/10] mtd: pxa3xx_nand: add a non mandatory ECC clock
@ 2015-04-15 17:23   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:23 UTC (permalink / raw)
  To: linux-arm-kernel

Some controllers (as the coming Berlin nand controller) need to enable
an ECC clock. Add support for this clock in the pxa3xx nand driver, and
leave it as non mandatory.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/pxa3xx_nand.c | 32 +++++++++++++++++++++++---------
 1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index d00ac392d1c4..55fce9527c2e 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -180,7 +180,7 @@ struct pxa3xx_nand_info {
 	struct nand_hw_control	controller;
 	struct platform_device	 *pdev;
 
-	struct clk		*clk;
+	struct clk		*clk, *ecc_clk;
 	void __iomem		*mmio_base;
 	unsigned long		mmio_phys;
 	struct completion	cmd_complete, dev_ready;
@@ -1608,15 +1608,26 @@ static int alloc_nand_resource(struct platform_device *pdev)
 
 	spin_lock_init(&chip->controller->lock);
 	init_waitqueue_head(&chip->controller->wq);
-	info->clk = devm_clk_get(&pdev->dev, NULL);
+	info->clk = devm_clk_get(&pdev->dev, "nfc");
 	if (IS_ERR(info->clk)) {
-		dev_err(&pdev->dev, "failed to get nand clock\n");
-		return PTR_ERR(info->clk);
+		info->clk = devm_clk_get(&pdev->dev, NULL);
+
+		if (IS_ERR(info->clk)) {
+			dev_err(&pdev->dev, "failed to get nand clock\n");
+			return PTR_ERR(info->clk);
+		}
 	}
 	ret = clk_prepare_enable(info->clk);
 	if (ret < 0)
 		return ret;
 
+	info->ecc_clk = devm_clk_get(&pdev->dev, "ecc");
+	if (!IS_ERR(info->ecc_clk)) {
+		ret = clk_prepare_enable(info->ecc_clk);
+		if (ret < 0)
+			goto fail_disable_clk;
+	}
+
 	if (use_dma) {
 		/*
 		 * This is a dirty hack to make this driver work from
@@ -1633,7 +1644,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
 				dev_err(&pdev->dev,
 					"no resource defined for data DMA\n");
 				ret = -ENXIO;
-				goto fail_disable_clk;
+				goto fail_disable_ecc_clk;
 			}
 			info->drcmr_dat = r->start;
 
@@ -1642,7 +1653,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
 				dev_err(&pdev->dev,
 					"no resource defined for cmd DMA\n");
 				ret = -ENXIO;
-				goto fail_disable_clk;
+				goto fail_disable_ecc_clk;
 			}
 			info->drcmr_cmd = r->start;
 		}
@@ -1652,14 +1663,14 @@ static int alloc_nand_resource(struct platform_device *pdev)
 	if (irq < 0) {
 		dev_err(&pdev->dev, "no IRQ resource defined\n");
 		ret = -ENXIO;
-		goto fail_disable_clk;
+		goto fail_disable_ecc_clk;
 	}
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	info->mmio_base = devm_ioremap_resource(&pdev->dev, r);
 	if (IS_ERR(info->mmio_base)) {
 		ret = PTR_ERR(info->mmio_base);
-		goto fail_disable_clk;
+		goto fail_disable_ecc_clk;
 	}
 	info->mmio_phys = r->start;
 
@@ -1668,7 +1679,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
 	info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
 	if (info->data_buff == NULL) {
 		ret = -ENOMEM;
-		goto fail_disable_clk;
+		goto fail_disable_ecc_clk;
 	}
 
 	/* initialize all interrupts to be disabled */
@@ -1687,6 +1698,8 @@ static int alloc_nand_resource(struct platform_device *pdev)
 fail_free_buf:
 	free_irq(irq, info);
 	kfree(info->data_buff);
+fail_disable_ecc_clk:
+	clk_disable_unprepare(info->ecc_clk);
 fail_disable_clk:
 	clk_disable_unprepare(info->clk);
 	return ret;
@@ -1709,6 +1722,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
 	pxa3xx_nand_free_buff(info);
 
 	clk_disable_unprepare(info->clk);
+	clk_disable_unprepare(info->ecc_clk);
 
 	for (cs = 0; cs < pdata->num_cs; cs++)
 		nand_release(info->host[cs]->mtd);
-- 
2.3.5

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

* [PATCH v4 02/10] Documentation: bindings: document the clocks for pxa3xx-nand
  2015-04-15 17:23 ` Antoine Tenart
  (?)
@ 2015-04-15 17:24   ` Antoine Tenart
  -1 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: Antoine Tenart, boris.brezillon, zmxu, jszhang, linux-arm-kernel,
	linux-mtd, linux-kernel

The pxa3xx nand driver requires at least one clock to probe correctly.
A second one, named 'ecc' can be specified if needed. Add the
corresponding documentation.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
index de8b517a5521..ecd1fc071f81 100644
--- a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
@@ -8,6 +8,8 @@ Required properties:
  - reg: 		The register base for the controller
  - interrupts:		The interrupt to map
  - #address-cells:	Set to <1> if the node includes partitions
+ - clocks:		A phandle to the clocks
+ - clock-names:		'nfc' and 'ecc'. The 'nfc' clock is mandatory.
 
 Optional properties:
 
@@ -32,6 +34,8 @@ Example:
 		compatible = "marvell,pxa3xx-nand";
 		reg = <0x43100000 90>;
 		interrupts = <45>;
+		clocks = <&gateclk 11>;
+		clock-names = "nfc";
 		#address-cells = <1>;
 
 		marvell,nand-enable-arbiter;
-- 
2.3.5


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

* [PATCH v4 02/10] Documentation: bindings: document the clocks for pxa3xx-nand
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: zmxu, boris.brezillon, Antoine Tenart, linux-kernel, linux-mtd,
	jszhang, linux-arm-kernel

The pxa3xx nand driver requires at least one clock to probe correctly.
A second one, named 'ecc' can be specified if needed. Add the
corresponding documentation.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
index de8b517a5521..ecd1fc071f81 100644
--- a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
@@ -8,6 +8,8 @@ Required properties:
  - reg: 		The register base for the controller
  - interrupts:		The interrupt to map
  - #address-cells:	Set to <1> if the node includes partitions
+ - clocks:		A phandle to the clocks
+ - clock-names:		'nfc' and 'ecc'. The 'nfc' clock is mandatory.
 
 Optional properties:
 
@@ -32,6 +34,8 @@ Example:
 		compatible = "marvell,pxa3xx-nand";
 		reg = <0x43100000 90>;
 		interrupts = <45>;
+		clocks = <&gateclk 11>;
+		clock-names = "nfc";
 		#address-cells = <1>;
 
 		marvell,nand-enable-arbiter;
-- 
2.3.5

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

* [PATCH v4 02/10] Documentation: bindings: document the clocks for pxa3xx-nand
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: linux-arm-kernel

The pxa3xx nand driver requires at least one clock to probe correctly.
A second one, named 'ecc' can be specified if needed. Add the
corresponding documentation.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
index de8b517a5521..ecd1fc071f81 100644
--- a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
@@ -8,6 +8,8 @@ Required properties:
  - reg: 		The register base for the controller
  - interrupts:		The interrupt to map
  - #address-cells:	Set to <1> if the node includes partitions
+ - clocks:		A phandle to the clocks
+ - clock-names:		'nfc' and 'ecc'. The 'nfc' clock is mandatory.
 
 Optional properties:
 
@@ -32,6 +34,8 @@ Example:
 		compatible = "marvell,pxa3xx-nand";
 		reg = <0x43100000 90>;
 		interrupts = <45>;
+		clocks = <&gateclk 11>;
+		clock-names = "nfc";
 		#address-cells = <1>;
 
 		marvell,nand-enable-arbiter;
-- 
2.3.5

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

* [PATCH v4 03/10] mtd: pxa3xx_nand: add a default chunk size
  2015-04-15 17:23 ` Antoine Tenart
  (?)
@ 2015-04-15 17:24   ` Antoine Tenart
  -1 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: Antoine Tenart, boris.brezillon, zmxu, jszhang, linux-arm-kernel,
	linux-mtd, linux-kernel

When keeping the configuration set by the bootloader (by using
the marvell,nand-keep-config property), the pxa3xx_nand_detect_config()
function is called and set the chunk size to 512 as a default value if
NDCR_PAGE_SZ is not set.

In the other case, when not keeping the bootloader configuration, no
chunk size is set. Fix this by adding a default chunk size of 512.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/pxa3xx_nand.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 55fce9527c2e..dc0edbc406bb 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1429,6 +1429,9 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
 		goto KEEP_CONFIG;
 
+	/* Set a default chunk size */
+	info->chunk_size = 512;
+
 	ret = pxa3xx_nand_sensing(info);
 	if (ret) {
 		dev_info(&info->pdev->dev, "There is no chip on cs %d!\n",
-- 
2.3.5


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

* [PATCH v4 03/10] mtd: pxa3xx_nand: add a default chunk size
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: zmxu, boris.brezillon, Antoine Tenart, linux-kernel, linux-mtd,
	jszhang, linux-arm-kernel

When keeping the configuration set by the bootloader (by using
the marvell,nand-keep-config property), the pxa3xx_nand_detect_config()
function is called and set the chunk size to 512 as a default value if
NDCR_PAGE_SZ is not set.

In the other case, when not keeping the bootloader configuration, no
chunk size is set. Fix this by adding a default chunk size of 512.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/pxa3xx_nand.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 55fce9527c2e..dc0edbc406bb 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1429,6 +1429,9 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
 		goto KEEP_CONFIG;
 
+	/* Set a default chunk size */
+	info->chunk_size = 512;
+
 	ret = pxa3xx_nand_sensing(info);
 	if (ret) {
 		dev_info(&info->pdev->dev, "There is no chip on cs %d!\n",
-- 
2.3.5

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

* [PATCH v4 03/10] mtd: pxa3xx_nand: add a default chunk size
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: linux-arm-kernel

When keeping the configuration set by the bootloader (by using
the marvell,nand-keep-config property), the pxa3xx_nand_detect_config()
function is called and set the chunk size to 512 as a default value if
NDCR_PAGE_SZ is not set.

In the other case, when not keeping the bootloader configuration, no
chunk size is set. Fix this by adding a default chunk size of 512.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/pxa3xx_nand.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 55fce9527c2e..dc0edbc406bb 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1429,6 +1429,9 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
 		goto KEEP_CONFIG;
 
+	/* Set a default chunk size */
+	info->chunk_size = 512;
+
 	ret = pxa3xx_nand_sensing(info);
 	if (ret) {
 		dev_info(&info->pdev->dev, "There is no chip on cs %d!\n",
-- 
2.3.5

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

* [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
  2015-04-15 17:23 ` Antoine Tenart
  (?)
@ 2015-04-15 17:24   ` Antoine Tenart
  -1 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: Antoine Tenart, boris.brezillon, zmxu, jszhang, linux-arm-kernel,
	linux-mtd, linux-kernel

Rework the pxa3xx_nand driver to allow using functions exported by the
nand framework to detect the flash and to configure the timings.

Because this driver supports some non-ONFI devices, we also keep the
custom timing setup of this driver so these devices won't break.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/pxa3xx_nand.c                | 220 ++++++++++++++------------
 include/linux/platform_data/mtd-nand-pxa3xx.h |  11 +-
 2 files changed, 123 insertions(+), 108 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index dc0edbc406bb..438770c56bd3 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -251,15 +251,14 @@ static struct pxa3xx_nand_timing timing[] = {
 };
 
 static struct pxa3xx_nand_flash builtin_flash_types[] = {
-{ "DEFAULT FLASH",      0,   0, 2048,  8,  8,    0, &timing[0] },
-{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, &timing[1] },
-{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, &timing[1] },
-{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, &timing[1] },
-{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, &timing[2] },
-{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, &timing[2] },
-{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, 4096, &timing[2] },
-{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, 4096, &timing[2] },
-{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3] },
+	{ 0x46ec, 16, 16, &timing[1] },
+	{ 0xdaec,  8,  8, &timing[1] },
+	{ 0xd7ec,  8,  8, &timing[1] },
+	{ 0xa12c,  8,  8, &timing[2] },
+	{ 0xb12c, 16, 16, &timing[2] },
+	{ 0xdc2c,  8,  8, &timing[2] },
+	{ 0xcc2c, 16, 16, &timing[2] },
+	{ 0xba20, 16, 16, &timing[3] },
 };
 
 static u8 bbt_pattern[] = {'M', 'V', 'B', 'b', 't', '0' };
@@ -320,9 +319,6 @@ static struct nand_ecclayout ecc_layout_4KB_bch8bit = {
 	.oobfree = { }
 };
 
-/* Define a default flash type setting serve as flash detecting only */
-#define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
-
 #define NDTR0_tCH(c)	(min((c), 7) << 19)
 #define NDTR0_tCS(c)	(min((c), 7) << 16)
 #define NDTR0_tWH(c)	(min((c), 7) << 11)
@@ -384,6 +380,92 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
 	nand_writel(info, NDTR1CS0, ndtr1);
 }
 
+static void pxa3xx_nand_set_sdr_timing(struct pxa3xx_nand_host *host,
+				       const struct nand_sdr_timings *t)
+{
+	struct pxa3xx_nand_info *info = host->info_data;
+	unsigned long nand_clk = clk_get_rate(info->clk);
+	uint32_t ndtr0, ndtr1;
+
+	u32 tCH_min = DIV_ROUND_UP(t->tCH_min, 1000);
+	u32 tCS_min = DIV_ROUND_UP(t->tCS_min, 1000);
+	u32 tWH_min = DIV_ROUND_UP(t->tWH_min, 1000);
+	u32 tWP_min = DIV_ROUND_UP(t->tWP_min, 1000);
+	u32 tREH_min = DIV_ROUND_UP(t->tREH_min, 1000);
+	u32 tRP_min = DIV_ROUND_UP(t->tRP_min, 1000);
+	u32 tRST_max = DIV_ROUND_UP_ULL(t->tRST_max, 1000);
+	u32 tWHR_min = DIV_ROUND_UP(t->tWHR_min, 1000);
+	u32 tAR_min = DIV_ROUND_UP(t->tAR_min, 1000);
+
+	ndtr0 = NDTR0_tCH(ns2cycle(tCH_min, nand_clk)) |
+		NDTR0_tCS(ns2cycle(tCS_min, nand_clk)) |
+		NDTR0_tWH(ns2cycle(tWH_min, nand_clk)) |
+		NDTR0_tWP(ns2cycle(tWP_min, nand_clk)) |
+		NDTR0_tRH(ns2cycle(tREH_min, nand_clk)) |
+		NDTR0_tRP(ns2cycle(tRP_min, nand_clk));
+
+	ndtr1 = NDTR1_tR(ns2cycle(tRST_max, nand_clk)) |
+		NDTR1_tWHR(ns2cycle(tWHR_min, nand_clk)) |
+		NDTR1_tAR(ns2cycle(tAR_min, nand_clk));
+
+	info->ndtr0cs0 = ndtr0;
+	info->ndtr1cs0 = ndtr1;
+	nand_writel(info, NDTR0CS0, ndtr0);
+	nand_writel(info, NDTR1CS0, ndtr1);
+}
+
+static int pxa3xx_nand_init_timings(struct pxa3xx_nand_host *host)
+{
+	const struct nand_sdr_timings *timings;
+	struct nand_chip *chip = &host->chip;
+	struct pxa3xx_nand_info *info = host->info_data;
+	const struct pxa3xx_nand_flash *f = NULL;
+	int mode, id, ntypes, i;
+
+	mode = onfi_get_async_timing_mode(chip);
+	if (mode == ONFI_TIMING_MODE_UNKNOWN) {
+		ntypes = ARRAY_SIZE(builtin_flash_types);
+
+		chip->cmdfunc(host->mtd, NAND_CMD_READID, 0x00, -1);
+
+		id = chip->read_byte(host->mtd);
+		id |= chip->read_byte(host->mtd) << 0x8;
+
+		for (i = 0; i < ntypes; i++) {
+			f = &builtin_flash_types[i];
+
+			if (f->chip_id == id)
+				break;
+		}
+
+		if (i == ntypes) {
+			dev_err(&info->pdev->dev, "Error: timings not found\n");
+			return -EINVAL;
+		}
+
+		pxa3xx_nand_set_timing(host, f->timing);
+
+		if (f->flash_width == 16) {
+			info->reg_ndcr |= NDCR_DWIDTH_M;
+			chip->options |= NAND_BUSWIDTH_16;
+		}
+
+		info->reg_ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
+	} else {
+		mode = fls(mode) - 1;
+		if (mode < 0)
+			mode = 0;
+
+		timings = onfi_async_timing_mode_to_sdr_timings(mode);
+		if (IS_ERR(timings))
+			return PTR_ERR(timings);
+
+		pxa3xx_nand_set_sdr_timing(host, timings);
+	}
+
+	return 0;
+}
+
 /*
  * Set the data and OOB size, depending on the selected
  * spare and ECC configuration.
@@ -1185,48 +1267,25 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
 	return NAND_STATUS_READY;
 }
 
-static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
-				    const struct pxa3xx_nand_flash *f)
+static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info)
 {
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct pxa3xx_nand_host *host = info->host[info->cs];
+	struct mtd_info *mtd = host->mtd;
+	struct nand_chip *chip = mtd->priv;
 	uint32_t ndcr = 0x0; /* enable all interrupts */
 
-	if (f->page_size != 2048 && f->page_size != 512) {
-		dev_err(&pdev->dev, "Current only support 2048 and 512 size\n");
-		return -EINVAL;
-	}
-
-	if (f->flash_width != 16 && f->flash_width != 8) {
-		dev_err(&pdev->dev, "Only support 8bit and 16 bit!\n");
-		return -EINVAL;
-	}
-
-	/* calculate flash information */
-	host->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
-
-	/* calculate addressing information */
-	host->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
-
-	if (f->num_blocks * f->page_per_block > 65536)
-		host->row_addr_cycles = 3;
-	else
-		host->row_addr_cycles = 2;
-
 	ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
 	ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
-	ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
-	ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
-	ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
-	ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
+	ndcr |= (chip->page_shift == 6) ? NDCR_PG_PER_BLK : 0;
+	ndcr |= (mtd->writesize == 2048) ? NDCR_PAGE_SZ : 0;
 
 	ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes);
 	ndcr |= NDCR_SPARE_EN; /* enable spare by default */
 
 	info->reg_ndcr = ndcr;
 
-	pxa3xx_nand_set_timing(host, f->timing);
 	return 0;
 }
 
@@ -1321,20 +1380,28 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
 }
 #endif
 
-static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
+static int pxa3xx_nand_sensing(struct pxa3xx_nand_host *host)
 {
+	struct pxa3xx_nand_info *info = host->info_data;
 	struct mtd_info *mtd;
 	struct nand_chip *chip;
+	const struct nand_sdr_timings *timings;
 	int ret;
 
 	mtd = info->host[info->cs]->mtd;
 	chip = mtd->priv;
 
-	/* use the common timing to make a try */
-	ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
+	ret = pxa3xx_nand_config_flash(info);
 	if (ret)
 		return ret;
 
+	/* use the common timing to make a try */
+	timings = onfi_async_timing_mode_to_sdr_timings(0);
+	if (IS_ERR(timings))
+		return PTR_ERR(timings);
+
+	pxa3xx_nand_set_sdr_timing(host, timings);
+
 	chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
 	ret = chip->waitfunc(mtd, chip);
 	if (ret & NAND_STATUS_FAIL)
@@ -1418,12 +1485,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	struct pxa3xx_nand_info *info = host->info_data;
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
-	struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
-	const struct pxa3xx_nand_flash *f = NULL;
 	struct nand_chip *chip = mtd->priv;
-	uint32_t id = -1;
-	uint64_t chipsize;
-	int i, ret, num;
+	int ret;
 	uint16_t ecc_strength, ecc_step;
 
 	if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
@@ -1432,7 +1495,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	/* Set a default chunk size */
 	info->chunk_size = 512;
 
-	ret = pxa3xx_nand_sensing(info);
+	ret = pxa3xx_nand_sensing(host);
 	if (ret) {
 		dev_info(&info->pdev->dev, "There is no chip on cs %d!\n",
 			 info->cs);
@@ -1440,64 +1503,20 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 		return ret;
 	}
 
-	chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
-	id = *((uint16_t *)(info->data_buff));
-	if (id != 0)
-		dev_info(&info->pdev->dev, "Detect a flash id %x\n", id);
-	else {
-		dev_warn(&info->pdev->dev,
-			 "Read out ID 0, potential timing set wrong!!\n");
-
-		return -EINVAL;
-	}
-
-	num = ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1;
-	for (i = 0; i < num; i++) {
-		if (i < pdata->num_flash)
-			f = pdata->flash + i;
-		else
-			f = &builtin_flash_types[i - pdata->num_flash + 1];
-
-		/* find the chip in default list */
-		if (f->chip_id == id)
-			break;
-	}
-
-	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
-		dev_err(&info->pdev->dev, "ERROR!! flash not defined!!!\n");
-
-		return -EINVAL;
-	}
-
-	ret = pxa3xx_nand_config_flash(info, f);
-	if (ret) {
-		dev_err(&info->pdev->dev, "ERROR! Configure failed\n");
-		return ret;
-	}
-
-	memset(pxa3xx_flash_ids, 0, sizeof(pxa3xx_flash_ids));
-
-	pxa3xx_flash_ids[0].name = f->name;
-	pxa3xx_flash_ids[0].dev_id = (f->chip_id >> 8) & 0xffff;
-	pxa3xx_flash_ids[0].pagesize = f->page_size;
-	chipsize = (uint64_t)f->num_blocks * f->page_per_block * f->page_size;
-	pxa3xx_flash_ids[0].chipsize = chipsize >> 20;
-	pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block;
-	if (f->flash_width == 16)
-		pxa3xx_flash_ids[0].options = NAND_BUSWIDTH_16;
-	pxa3xx_flash_ids[1].name = NULL;
-	def = pxa3xx_flash_ids;
 KEEP_CONFIG:
-	if (info->reg_ndcr & NDCR_DWIDTH_M)
-		chip->options |= NAND_BUSWIDTH_16;
-
 	/* Device detection must be done with ECC disabled */
 	if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
 		nand_writel(info, NDECCCTRL, 0x0);
 
-	if (nand_scan_ident(mtd, 1, def))
+	if (nand_scan_ident(mtd, 1, NULL))
 		return -ENODEV;
 
+	ret = pxa3xx_nand_init_timings(host);
+	if (ret) {
+		dev_err(&info->pdev->dev, "Failed to set timings: %d\n", ret);
+		return ret;
+	}
+
 	if (pdata->flash_bbt) {
 		/*
 		 * We'll use a bad block table stored in-flash and don't
@@ -1593,6 +1612,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
 		host->mtd = mtd;
 		host->cs = cs;
 		host->info_data = info;
+		host->read_id_bytes = 4;
 		mtd->priv = host;
 		mtd->owner = THIS_MODULE;
 
diff --git a/include/linux/platform_data/mtd-nand-pxa3xx.h b/include/linux/platform_data/mtd-nand-pxa3xx.h
index ac4ea2e641c7..25538cfeee26 100644
--- a/include/linux/platform_data/mtd-nand-pxa3xx.h
+++ b/include/linux/platform_data/mtd-nand-pxa3xx.h
@@ -17,15 +17,10 @@ struct pxa3xx_nand_timing {
 };
 
 struct pxa3xx_nand_flash {
-	char		*name;
 	uint32_t	chip_id;
-	unsigned int	page_per_block; /* Pages per block (PG_PER_BLK) */
-	unsigned int	page_size;	/* Page size in bytes (PAGE_SZ) */
-	unsigned int	flash_width;	/* Width of Flash memory (DWIDTH_M) */
-	unsigned int	dfc_width;	/* Width of flash controller(DWIDTH_C) */
-	unsigned int	num_blocks;	/* Number of physical blocks in Flash */
-
-	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
+	unsigned int	flash_width;    /* Width of Flash memory (DWIDTH_M) */
+	unsigned int	dfc_width;      /* Width of flash controller(DWIDTH_C) */
+	struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
 };
 
 /*
-- 
2.3.5


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

* [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: zmxu, boris.brezillon, Antoine Tenart, linux-kernel, linux-mtd,
	jszhang, linux-arm-kernel

Rework the pxa3xx_nand driver to allow using functions exported by the
nand framework to detect the flash and to configure the timings.

Because this driver supports some non-ONFI devices, we also keep the
custom timing setup of this driver so these devices won't break.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/pxa3xx_nand.c                | 220 ++++++++++++++------------
 include/linux/platform_data/mtd-nand-pxa3xx.h |  11 +-
 2 files changed, 123 insertions(+), 108 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index dc0edbc406bb..438770c56bd3 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -251,15 +251,14 @@ static struct pxa3xx_nand_timing timing[] = {
 };
 
 static struct pxa3xx_nand_flash builtin_flash_types[] = {
-{ "DEFAULT FLASH",      0,   0, 2048,  8,  8,    0, &timing[0] },
-{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, &timing[1] },
-{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, &timing[1] },
-{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, &timing[1] },
-{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, &timing[2] },
-{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, &timing[2] },
-{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, 4096, &timing[2] },
-{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, 4096, &timing[2] },
-{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3] },
+	{ 0x46ec, 16, 16, &timing[1] },
+	{ 0xdaec,  8,  8, &timing[1] },
+	{ 0xd7ec,  8,  8, &timing[1] },
+	{ 0xa12c,  8,  8, &timing[2] },
+	{ 0xb12c, 16, 16, &timing[2] },
+	{ 0xdc2c,  8,  8, &timing[2] },
+	{ 0xcc2c, 16, 16, &timing[2] },
+	{ 0xba20, 16, 16, &timing[3] },
 };
 
 static u8 bbt_pattern[] = {'M', 'V', 'B', 'b', 't', '0' };
@@ -320,9 +319,6 @@ static struct nand_ecclayout ecc_layout_4KB_bch8bit = {
 	.oobfree = { }
 };
 
-/* Define a default flash type setting serve as flash detecting only */
-#define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
-
 #define NDTR0_tCH(c)	(min((c), 7) << 19)
 #define NDTR0_tCS(c)	(min((c), 7) << 16)
 #define NDTR0_tWH(c)	(min((c), 7) << 11)
@@ -384,6 +380,92 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
 	nand_writel(info, NDTR1CS0, ndtr1);
 }
 
+static void pxa3xx_nand_set_sdr_timing(struct pxa3xx_nand_host *host,
+				       const struct nand_sdr_timings *t)
+{
+	struct pxa3xx_nand_info *info = host->info_data;
+	unsigned long nand_clk = clk_get_rate(info->clk);
+	uint32_t ndtr0, ndtr1;
+
+	u32 tCH_min = DIV_ROUND_UP(t->tCH_min, 1000);
+	u32 tCS_min = DIV_ROUND_UP(t->tCS_min, 1000);
+	u32 tWH_min = DIV_ROUND_UP(t->tWH_min, 1000);
+	u32 tWP_min = DIV_ROUND_UP(t->tWP_min, 1000);
+	u32 tREH_min = DIV_ROUND_UP(t->tREH_min, 1000);
+	u32 tRP_min = DIV_ROUND_UP(t->tRP_min, 1000);
+	u32 tRST_max = DIV_ROUND_UP_ULL(t->tRST_max, 1000);
+	u32 tWHR_min = DIV_ROUND_UP(t->tWHR_min, 1000);
+	u32 tAR_min = DIV_ROUND_UP(t->tAR_min, 1000);
+
+	ndtr0 = NDTR0_tCH(ns2cycle(tCH_min, nand_clk)) |
+		NDTR0_tCS(ns2cycle(tCS_min, nand_clk)) |
+		NDTR0_tWH(ns2cycle(tWH_min, nand_clk)) |
+		NDTR0_tWP(ns2cycle(tWP_min, nand_clk)) |
+		NDTR0_tRH(ns2cycle(tREH_min, nand_clk)) |
+		NDTR0_tRP(ns2cycle(tRP_min, nand_clk));
+
+	ndtr1 = NDTR1_tR(ns2cycle(tRST_max, nand_clk)) |
+		NDTR1_tWHR(ns2cycle(tWHR_min, nand_clk)) |
+		NDTR1_tAR(ns2cycle(tAR_min, nand_clk));
+
+	info->ndtr0cs0 = ndtr0;
+	info->ndtr1cs0 = ndtr1;
+	nand_writel(info, NDTR0CS0, ndtr0);
+	nand_writel(info, NDTR1CS0, ndtr1);
+}
+
+static int pxa3xx_nand_init_timings(struct pxa3xx_nand_host *host)
+{
+	const struct nand_sdr_timings *timings;
+	struct nand_chip *chip = &host->chip;
+	struct pxa3xx_nand_info *info = host->info_data;
+	const struct pxa3xx_nand_flash *f = NULL;
+	int mode, id, ntypes, i;
+
+	mode = onfi_get_async_timing_mode(chip);
+	if (mode == ONFI_TIMING_MODE_UNKNOWN) {
+		ntypes = ARRAY_SIZE(builtin_flash_types);
+
+		chip->cmdfunc(host->mtd, NAND_CMD_READID, 0x00, -1);
+
+		id = chip->read_byte(host->mtd);
+		id |= chip->read_byte(host->mtd) << 0x8;
+
+		for (i = 0; i < ntypes; i++) {
+			f = &builtin_flash_types[i];
+
+			if (f->chip_id == id)
+				break;
+		}
+
+		if (i == ntypes) {
+			dev_err(&info->pdev->dev, "Error: timings not found\n");
+			return -EINVAL;
+		}
+
+		pxa3xx_nand_set_timing(host, f->timing);
+
+		if (f->flash_width == 16) {
+			info->reg_ndcr |= NDCR_DWIDTH_M;
+			chip->options |= NAND_BUSWIDTH_16;
+		}
+
+		info->reg_ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
+	} else {
+		mode = fls(mode) - 1;
+		if (mode < 0)
+			mode = 0;
+
+		timings = onfi_async_timing_mode_to_sdr_timings(mode);
+		if (IS_ERR(timings))
+			return PTR_ERR(timings);
+
+		pxa3xx_nand_set_sdr_timing(host, timings);
+	}
+
+	return 0;
+}
+
 /*
  * Set the data and OOB size, depending on the selected
  * spare and ECC configuration.
@@ -1185,48 +1267,25 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
 	return NAND_STATUS_READY;
 }
 
-static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
-				    const struct pxa3xx_nand_flash *f)
+static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info)
 {
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct pxa3xx_nand_host *host = info->host[info->cs];
+	struct mtd_info *mtd = host->mtd;
+	struct nand_chip *chip = mtd->priv;
 	uint32_t ndcr = 0x0; /* enable all interrupts */
 
-	if (f->page_size != 2048 && f->page_size != 512) {
-		dev_err(&pdev->dev, "Current only support 2048 and 512 size\n");
-		return -EINVAL;
-	}
-
-	if (f->flash_width != 16 && f->flash_width != 8) {
-		dev_err(&pdev->dev, "Only support 8bit and 16 bit!\n");
-		return -EINVAL;
-	}
-
-	/* calculate flash information */
-	host->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
-
-	/* calculate addressing information */
-	host->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
-
-	if (f->num_blocks * f->page_per_block > 65536)
-		host->row_addr_cycles = 3;
-	else
-		host->row_addr_cycles = 2;
-
 	ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
 	ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
-	ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
-	ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
-	ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
-	ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
+	ndcr |= (chip->page_shift == 6) ? NDCR_PG_PER_BLK : 0;
+	ndcr |= (mtd->writesize == 2048) ? NDCR_PAGE_SZ : 0;
 
 	ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes);
 	ndcr |= NDCR_SPARE_EN; /* enable spare by default */
 
 	info->reg_ndcr = ndcr;
 
-	pxa3xx_nand_set_timing(host, f->timing);
 	return 0;
 }
 
@@ -1321,20 +1380,28 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
 }
 #endif
 
-static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
+static int pxa3xx_nand_sensing(struct pxa3xx_nand_host *host)
 {
+	struct pxa3xx_nand_info *info = host->info_data;
 	struct mtd_info *mtd;
 	struct nand_chip *chip;
+	const struct nand_sdr_timings *timings;
 	int ret;
 
 	mtd = info->host[info->cs]->mtd;
 	chip = mtd->priv;
 
-	/* use the common timing to make a try */
-	ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
+	ret = pxa3xx_nand_config_flash(info);
 	if (ret)
 		return ret;
 
+	/* use the common timing to make a try */
+	timings = onfi_async_timing_mode_to_sdr_timings(0);
+	if (IS_ERR(timings))
+		return PTR_ERR(timings);
+
+	pxa3xx_nand_set_sdr_timing(host, timings);
+
 	chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
 	ret = chip->waitfunc(mtd, chip);
 	if (ret & NAND_STATUS_FAIL)
@@ -1418,12 +1485,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	struct pxa3xx_nand_info *info = host->info_data;
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
-	struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
-	const struct pxa3xx_nand_flash *f = NULL;
 	struct nand_chip *chip = mtd->priv;
-	uint32_t id = -1;
-	uint64_t chipsize;
-	int i, ret, num;
+	int ret;
 	uint16_t ecc_strength, ecc_step;
 
 	if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
@@ -1432,7 +1495,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	/* Set a default chunk size */
 	info->chunk_size = 512;
 
-	ret = pxa3xx_nand_sensing(info);
+	ret = pxa3xx_nand_sensing(host);
 	if (ret) {
 		dev_info(&info->pdev->dev, "There is no chip on cs %d!\n",
 			 info->cs);
@@ -1440,64 +1503,20 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 		return ret;
 	}
 
-	chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
-	id = *((uint16_t *)(info->data_buff));
-	if (id != 0)
-		dev_info(&info->pdev->dev, "Detect a flash id %x\n", id);
-	else {
-		dev_warn(&info->pdev->dev,
-			 "Read out ID 0, potential timing set wrong!!\n");
-
-		return -EINVAL;
-	}
-
-	num = ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1;
-	for (i = 0; i < num; i++) {
-		if (i < pdata->num_flash)
-			f = pdata->flash + i;
-		else
-			f = &builtin_flash_types[i - pdata->num_flash + 1];
-
-		/* find the chip in default list */
-		if (f->chip_id == id)
-			break;
-	}
-
-	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
-		dev_err(&info->pdev->dev, "ERROR!! flash not defined!!!\n");
-
-		return -EINVAL;
-	}
-
-	ret = pxa3xx_nand_config_flash(info, f);
-	if (ret) {
-		dev_err(&info->pdev->dev, "ERROR! Configure failed\n");
-		return ret;
-	}
-
-	memset(pxa3xx_flash_ids, 0, sizeof(pxa3xx_flash_ids));
-
-	pxa3xx_flash_ids[0].name = f->name;
-	pxa3xx_flash_ids[0].dev_id = (f->chip_id >> 8) & 0xffff;
-	pxa3xx_flash_ids[0].pagesize = f->page_size;
-	chipsize = (uint64_t)f->num_blocks * f->page_per_block * f->page_size;
-	pxa3xx_flash_ids[0].chipsize = chipsize >> 20;
-	pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block;
-	if (f->flash_width == 16)
-		pxa3xx_flash_ids[0].options = NAND_BUSWIDTH_16;
-	pxa3xx_flash_ids[1].name = NULL;
-	def = pxa3xx_flash_ids;
 KEEP_CONFIG:
-	if (info->reg_ndcr & NDCR_DWIDTH_M)
-		chip->options |= NAND_BUSWIDTH_16;
-
 	/* Device detection must be done with ECC disabled */
 	if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
 		nand_writel(info, NDECCCTRL, 0x0);
 
-	if (nand_scan_ident(mtd, 1, def))
+	if (nand_scan_ident(mtd, 1, NULL))
 		return -ENODEV;
 
+	ret = pxa3xx_nand_init_timings(host);
+	if (ret) {
+		dev_err(&info->pdev->dev, "Failed to set timings: %d\n", ret);
+		return ret;
+	}
+
 	if (pdata->flash_bbt) {
 		/*
 		 * We'll use a bad block table stored in-flash and don't
@@ -1593,6 +1612,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
 		host->mtd = mtd;
 		host->cs = cs;
 		host->info_data = info;
+		host->read_id_bytes = 4;
 		mtd->priv = host;
 		mtd->owner = THIS_MODULE;
 
diff --git a/include/linux/platform_data/mtd-nand-pxa3xx.h b/include/linux/platform_data/mtd-nand-pxa3xx.h
index ac4ea2e641c7..25538cfeee26 100644
--- a/include/linux/platform_data/mtd-nand-pxa3xx.h
+++ b/include/linux/platform_data/mtd-nand-pxa3xx.h
@@ -17,15 +17,10 @@ struct pxa3xx_nand_timing {
 };
 
 struct pxa3xx_nand_flash {
-	char		*name;
 	uint32_t	chip_id;
-	unsigned int	page_per_block; /* Pages per block (PG_PER_BLK) */
-	unsigned int	page_size;	/* Page size in bytes (PAGE_SZ) */
-	unsigned int	flash_width;	/* Width of Flash memory (DWIDTH_M) */
-	unsigned int	dfc_width;	/* Width of flash controller(DWIDTH_C) */
-	unsigned int	num_blocks;	/* Number of physical blocks in Flash */
-
-	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
+	unsigned int	flash_width;    /* Width of Flash memory (DWIDTH_M) */
+	unsigned int	dfc_width;      /* Width of flash controller(DWIDTH_C) */
+	struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
 };
 
 /*
-- 
2.3.5

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

* [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: linux-arm-kernel

Rework the pxa3xx_nand driver to allow using functions exported by the
nand framework to detect the flash and to configure the timings.

Because this driver supports some non-ONFI devices, we also keep the
custom timing setup of this driver so these devices won't break.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/pxa3xx_nand.c                | 220 ++++++++++++++------------
 include/linux/platform_data/mtd-nand-pxa3xx.h |  11 +-
 2 files changed, 123 insertions(+), 108 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index dc0edbc406bb..438770c56bd3 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -251,15 +251,14 @@ static struct pxa3xx_nand_timing timing[] = {
 };
 
 static struct pxa3xx_nand_flash builtin_flash_types[] = {
-{ "DEFAULT FLASH",      0,   0, 2048,  8,  8,    0, &timing[0] },
-{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, &timing[1] },
-{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, &timing[1] },
-{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, &timing[1] },
-{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, &timing[2] },
-{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, &timing[2] },
-{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, 4096, &timing[2] },
-{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, 4096, &timing[2] },
-{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3] },
+	{ 0x46ec, 16, 16, &timing[1] },
+	{ 0xdaec,  8,  8, &timing[1] },
+	{ 0xd7ec,  8,  8, &timing[1] },
+	{ 0xa12c,  8,  8, &timing[2] },
+	{ 0xb12c, 16, 16, &timing[2] },
+	{ 0xdc2c,  8,  8, &timing[2] },
+	{ 0xcc2c, 16, 16, &timing[2] },
+	{ 0xba20, 16, 16, &timing[3] },
 };
 
 static u8 bbt_pattern[] = {'M', 'V', 'B', 'b', 't', '0' };
@@ -320,9 +319,6 @@ static struct nand_ecclayout ecc_layout_4KB_bch8bit = {
 	.oobfree = { }
 };
 
-/* Define a default flash type setting serve as flash detecting only */
-#define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
-
 #define NDTR0_tCH(c)	(min((c), 7) << 19)
 #define NDTR0_tCS(c)	(min((c), 7) << 16)
 #define NDTR0_tWH(c)	(min((c), 7) << 11)
@@ -384,6 +380,92 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
 	nand_writel(info, NDTR1CS0, ndtr1);
 }
 
+static void pxa3xx_nand_set_sdr_timing(struct pxa3xx_nand_host *host,
+				       const struct nand_sdr_timings *t)
+{
+	struct pxa3xx_nand_info *info = host->info_data;
+	unsigned long nand_clk = clk_get_rate(info->clk);
+	uint32_t ndtr0, ndtr1;
+
+	u32 tCH_min = DIV_ROUND_UP(t->tCH_min, 1000);
+	u32 tCS_min = DIV_ROUND_UP(t->tCS_min, 1000);
+	u32 tWH_min = DIV_ROUND_UP(t->tWH_min, 1000);
+	u32 tWP_min = DIV_ROUND_UP(t->tWP_min, 1000);
+	u32 tREH_min = DIV_ROUND_UP(t->tREH_min, 1000);
+	u32 tRP_min = DIV_ROUND_UP(t->tRP_min, 1000);
+	u32 tRST_max = DIV_ROUND_UP_ULL(t->tRST_max, 1000);
+	u32 tWHR_min = DIV_ROUND_UP(t->tWHR_min, 1000);
+	u32 tAR_min = DIV_ROUND_UP(t->tAR_min, 1000);
+
+	ndtr0 = NDTR0_tCH(ns2cycle(tCH_min, nand_clk)) |
+		NDTR0_tCS(ns2cycle(tCS_min, nand_clk)) |
+		NDTR0_tWH(ns2cycle(tWH_min, nand_clk)) |
+		NDTR0_tWP(ns2cycle(tWP_min, nand_clk)) |
+		NDTR0_tRH(ns2cycle(tREH_min, nand_clk)) |
+		NDTR0_tRP(ns2cycle(tRP_min, nand_clk));
+
+	ndtr1 = NDTR1_tR(ns2cycle(tRST_max, nand_clk)) |
+		NDTR1_tWHR(ns2cycle(tWHR_min, nand_clk)) |
+		NDTR1_tAR(ns2cycle(tAR_min, nand_clk));
+
+	info->ndtr0cs0 = ndtr0;
+	info->ndtr1cs0 = ndtr1;
+	nand_writel(info, NDTR0CS0, ndtr0);
+	nand_writel(info, NDTR1CS0, ndtr1);
+}
+
+static int pxa3xx_nand_init_timings(struct pxa3xx_nand_host *host)
+{
+	const struct nand_sdr_timings *timings;
+	struct nand_chip *chip = &host->chip;
+	struct pxa3xx_nand_info *info = host->info_data;
+	const struct pxa3xx_nand_flash *f = NULL;
+	int mode, id, ntypes, i;
+
+	mode = onfi_get_async_timing_mode(chip);
+	if (mode == ONFI_TIMING_MODE_UNKNOWN) {
+		ntypes = ARRAY_SIZE(builtin_flash_types);
+
+		chip->cmdfunc(host->mtd, NAND_CMD_READID, 0x00, -1);
+
+		id = chip->read_byte(host->mtd);
+		id |= chip->read_byte(host->mtd) << 0x8;
+
+		for (i = 0; i < ntypes; i++) {
+			f = &builtin_flash_types[i];
+
+			if (f->chip_id == id)
+				break;
+		}
+
+		if (i == ntypes) {
+			dev_err(&info->pdev->dev, "Error: timings not found\n");
+			return -EINVAL;
+		}
+
+		pxa3xx_nand_set_timing(host, f->timing);
+
+		if (f->flash_width == 16) {
+			info->reg_ndcr |= NDCR_DWIDTH_M;
+			chip->options |= NAND_BUSWIDTH_16;
+		}
+
+		info->reg_ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
+	} else {
+		mode = fls(mode) - 1;
+		if (mode < 0)
+			mode = 0;
+
+		timings = onfi_async_timing_mode_to_sdr_timings(mode);
+		if (IS_ERR(timings))
+			return PTR_ERR(timings);
+
+		pxa3xx_nand_set_sdr_timing(host, timings);
+	}
+
+	return 0;
+}
+
 /*
  * Set the data and OOB size, depending on the selected
  * spare and ECC configuration.
@@ -1185,48 +1267,25 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
 	return NAND_STATUS_READY;
 }
 
-static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
-				    const struct pxa3xx_nand_flash *f)
+static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info)
 {
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct pxa3xx_nand_host *host = info->host[info->cs];
+	struct mtd_info *mtd = host->mtd;
+	struct nand_chip *chip = mtd->priv;
 	uint32_t ndcr = 0x0; /* enable all interrupts */
 
-	if (f->page_size != 2048 && f->page_size != 512) {
-		dev_err(&pdev->dev, "Current only support 2048 and 512 size\n");
-		return -EINVAL;
-	}
-
-	if (f->flash_width != 16 && f->flash_width != 8) {
-		dev_err(&pdev->dev, "Only support 8bit and 16 bit!\n");
-		return -EINVAL;
-	}
-
-	/* calculate flash information */
-	host->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
-
-	/* calculate addressing information */
-	host->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
-
-	if (f->num_blocks * f->page_per_block > 65536)
-		host->row_addr_cycles = 3;
-	else
-		host->row_addr_cycles = 2;
-
 	ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
 	ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
-	ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
-	ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
-	ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
-	ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
+	ndcr |= (chip->page_shift == 6) ? NDCR_PG_PER_BLK : 0;
+	ndcr |= (mtd->writesize == 2048) ? NDCR_PAGE_SZ : 0;
 
 	ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes);
 	ndcr |= NDCR_SPARE_EN; /* enable spare by default */
 
 	info->reg_ndcr = ndcr;
 
-	pxa3xx_nand_set_timing(host, f->timing);
 	return 0;
 }
 
@@ -1321,20 +1380,28 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
 }
 #endif
 
-static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
+static int pxa3xx_nand_sensing(struct pxa3xx_nand_host *host)
 {
+	struct pxa3xx_nand_info *info = host->info_data;
 	struct mtd_info *mtd;
 	struct nand_chip *chip;
+	const struct nand_sdr_timings *timings;
 	int ret;
 
 	mtd = info->host[info->cs]->mtd;
 	chip = mtd->priv;
 
-	/* use the common timing to make a try */
-	ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
+	ret = pxa3xx_nand_config_flash(info);
 	if (ret)
 		return ret;
 
+	/* use the common timing to make a try */
+	timings = onfi_async_timing_mode_to_sdr_timings(0);
+	if (IS_ERR(timings))
+		return PTR_ERR(timings);
+
+	pxa3xx_nand_set_sdr_timing(host, timings);
+
 	chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
 	ret = chip->waitfunc(mtd, chip);
 	if (ret & NAND_STATUS_FAIL)
@@ -1418,12 +1485,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	struct pxa3xx_nand_info *info = host->info_data;
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
-	struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
-	const struct pxa3xx_nand_flash *f = NULL;
 	struct nand_chip *chip = mtd->priv;
-	uint32_t id = -1;
-	uint64_t chipsize;
-	int i, ret, num;
+	int ret;
 	uint16_t ecc_strength, ecc_step;
 
 	if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
@@ -1432,7 +1495,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	/* Set a default chunk size */
 	info->chunk_size = 512;
 
-	ret = pxa3xx_nand_sensing(info);
+	ret = pxa3xx_nand_sensing(host);
 	if (ret) {
 		dev_info(&info->pdev->dev, "There is no chip on cs %d!\n",
 			 info->cs);
@@ -1440,64 +1503,20 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 		return ret;
 	}
 
-	chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
-	id = *((uint16_t *)(info->data_buff));
-	if (id != 0)
-		dev_info(&info->pdev->dev, "Detect a flash id %x\n", id);
-	else {
-		dev_warn(&info->pdev->dev,
-			 "Read out ID 0, potential timing set wrong!!\n");
-
-		return -EINVAL;
-	}
-
-	num = ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1;
-	for (i = 0; i < num; i++) {
-		if (i < pdata->num_flash)
-			f = pdata->flash + i;
-		else
-			f = &builtin_flash_types[i - pdata->num_flash + 1];
-
-		/* find the chip in default list */
-		if (f->chip_id == id)
-			break;
-	}
-
-	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
-		dev_err(&info->pdev->dev, "ERROR!! flash not defined!!!\n");
-
-		return -EINVAL;
-	}
-
-	ret = pxa3xx_nand_config_flash(info, f);
-	if (ret) {
-		dev_err(&info->pdev->dev, "ERROR! Configure failed\n");
-		return ret;
-	}
-
-	memset(pxa3xx_flash_ids, 0, sizeof(pxa3xx_flash_ids));
-
-	pxa3xx_flash_ids[0].name = f->name;
-	pxa3xx_flash_ids[0].dev_id = (f->chip_id >> 8) & 0xffff;
-	pxa3xx_flash_ids[0].pagesize = f->page_size;
-	chipsize = (uint64_t)f->num_blocks * f->page_per_block * f->page_size;
-	pxa3xx_flash_ids[0].chipsize = chipsize >> 20;
-	pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block;
-	if (f->flash_width == 16)
-		pxa3xx_flash_ids[0].options = NAND_BUSWIDTH_16;
-	pxa3xx_flash_ids[1].name = NULL;
-	def = pxa3xx_flash_ids;
 KEEP_CONFIG:
-	if (info->reg_ndcr & NDCR_DWIDTH_M)
-		chip->options |= NAND_BUSWIDTH_16;
-
 	/* Device detection must be done with ECC disabled */
 	if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
 		nand_writel(info, NDECCCTRL, 0x0);
 
-	if (nand_scan_ident(mtd, 1, def))
+	if (nand_scan_ident(mtd, 1, NULL))
 		return -ENODEV;
 
+	ret = pxa3xx_nand_init_timings(host);
+	if (ret) {
+		dev_err(&info->pdev->dev, "Failed to set timings: %d\n", ret);
+		return ret;
+	}
+
 	if (pdata->flash_bbt) {
 		/*
 		 * We'll use a bad block table stored in-flash and don't
@@ -1593,6 +1612,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
 		host->mtd = mtd;
 		host->cs = cs;
 		host->info_data = info;
+		host->read_id_bytes = 4;
 		mtd->priv = host;
 		mtd->owner = THIS_MODULE;
 
diff --git a/include/linux/platform_data/mtd-nand-pxa3xx.h b/include/linux/platform_data/mtd-nand-pxa3xx.h
index ac4ea2e641c7..25538cfeee26 100644
--- a/include/linux/platform_data/mtd-nand-pxa3xx.h
+++ b/include/linux/platform_data/mtd-nand-pxa3xx.h
@@ -17,15 +17,10 @@ struct pxa3xx_nand_timing {
 };
 
 struct pxa3xx_nand_flash {
-	char		*name;
 	uint32_t	chip_id;
-	unsigned int	page_per_block; /* Pages per block (PG_PER_BLK) */
-	unsigned int	page_size;	/* Page size in bytes (PAGE_SZ) */
-	unsigned int	flash_width;	/* Width of Flash memory (DWIDTH_M) */
-	unsigned int	dfc_width;	/* Width of flash controller(DWIDTH_C) */
-	unsigned int	num_blocks;	/* Number of physical blocks in Flash */
-
-	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
+	unsigned int	flash_width;    /* Width of Flash memory (DWIDTH_M) */
+	unsigned int	dfc_width;      /* Width of flash controller(DWIDTH_C) */
+	struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
 };
 
 /*
-- 
2.3.5

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

* [PATCH v4 05/10] mtd: nand: add Samsung K9GBG08U0A-M to nand_ids table
  2015-04-15 17:23 ` Antoine Tenart
  (?)
@ 2015-04-15 17:24   ` Antoine Tenart
  -1 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: Antoine Tenart, boris.brezillon, zmxu, jszhang, linux-arm-kernel,
	linux-mtd, linux-kernel

Add the full description of the Samsung K9GBG08U0A-M nand chip in the
nand_ids table.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/nand_ids.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index dd620c19c619..500c33e1db06 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -50,6 +50,10 @@ struct nand_flash_dev nand_flash_ids[] = {
 		{ .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} },
 		  SZ_8K, SZ_8K, SZ_2M, 0, 6, 640, NAND_ECC_INFO(40, SZ_1K),
 		  4 },
+	{"NAND 4GiB 3,3V 8-bit",
+		{ .id = {0xec, 0xd7, 0x94, 0x76, 0x64, 0x43}, },
+		  8192, 4096, SZ_1M, LP_OPTIONS, 0, 0, NAND_ECC_INFO(40, SZ_1K),
+		  4 },
 
 	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),
 	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),
-- 
2.3.5


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

* [PATCH v4 05/10] mtd: nand: add Samsung K9GBG08U0A-M to nand_ids table
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: zmxu, boris.brezillon, Antoine Tenart, linux-kernel, linux-mtd,
	jszhang, linux-arm-kernel

Add the full description of the Samsung K9GBG08U0A-M nand chip in the
nand_ids table.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/nand_ids.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index dd620c19c619..500c33e1db06 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -50,6 +50,10 @@ struct nand_flash_dev nand_flash_ids[] = {
 		{ .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} },
 		  SZ_8K, SZ_8K, SZ_2M, 0, 6, 640, NAND_ECC_INFO(40, SZ_1K),
 		  4 },
+	{"NAND 4GiB 3,3V 8-bit",
+		{ .id = {0xec, 0xd7, 0x94, 0x76, 0x64, 0x43}, },
+		  8192, 4096, SZ_1M, LP_OPTIONS, 0, 0, NAND_ECC_INFO(40, SZ_1K),
+		  4 },
 
 	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),
 	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),
-- 
2.3.5

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

* [PATCH v4 05/10] mtd: nand: add Samsung K9GBG08U0A-M to nand_ids table
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: linux-arm-kernel

Add the full description of the Samsung K9GBG08U0A-M nand chip in the
nand_ids table.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/nand_ids.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index dd620c19c619..500c33e1db06 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -50,6 +50,10 @@ struct nand_flash_dev nand_flash_ids[] = {
 		{ .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} },
 		  SZ_8K, SZ_8K, SZ_2M, 0, 6, 640, NAND_ECC_INFO(40, SZ_1K),
 		  4 },
+	{"NAND 4GiB 3,3V 8-bit",
+		{ .id = {0xec, 0xd7, 0x94, 0x76, 0x64, 0x43}, },
+		  8192, 4096, SZ_1M, LP_OPTIONS, 0, 0, NAND_ECC_INFO(40, SZ_1K),
+		  4 },
 
 	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),
 	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),
-- 
2.3.5

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

* [PATCH v4 06/10] mtd: pxa3xx_nand: add support for the Marvell Berlin nand controller
  2015-04-15 17:23 ` Antoine Tenart
  (?)
@ 2015-04-15 17:24   ` Antoine Tenart
  -1 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: Antoine Tenart, boris.brezillon, zmxu, jszhang, linux-arm-kernel,
	linux-mtd, linux-kernel

The nand controller on Marvell Berlin SoC reuse the pxa3xx nand driver
as it quite close. The process of sending commands can be compared to
the one of the Marvell armada 370: read and write commands are done in
chunks.

But the Berlin nand controller has some other specificities which
require some modifications of the pxa3xx nand driver:
- there are no IRQ available so we need to poll the status register: we
  have to use our own cmdfunc Berlin function, and early on the probing
  function.
- PAGEPROG are very different from the one used in the pxa3xx driver,
  so we're using a specific process for this one
- the SEQIN command is equivalent to a READ0 command

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/pxa3xx_nand.c | 179 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 169 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 438770c56bd3..544c8058417f 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -109,6 +109,8 @@
 #define NDCB0_EXT_CMD_TYPE(x)	(((x) << 29) & NDCB0_EXT_CMD_TYPE_MASK)
 #define NDCB0_CMD_TYPE_MASK	(0x7 << 21)
 #define NDCB0_CMD_TYPE(x)	(((x) << 21) & NDCB0_CMD_TYPE_MASK)
+#define NDCB0_CMD_XTYPE_MASK	(0x7 << 29)
+#define NDCB0_CMD_XTYPE(x)	(((x) << 29) & NDCB0_CMD_XTYPE_MASK)
 #define NDCB0_NC		(0x1 << 20)
 #define NDCB0_DBC		(0x1 << 19)
 #define NDCB0_ADDR_CYC_MASK	(0x7 << 16)
@@ -117,13 +119,15 @@
 #define NDCB0_CMD1_MASK		(0xff)
 #define NDCB0_ADDR_CYC_SHIFT	(16)
 
-#define EXT_CMD_TYPE_DISPATCH	6 /* Command dispatch */
-#define EXT_CMD_TYPE_NAKED_RW	5 /* Naked read or Naked write */
-#define EXT_CMD_TYPE_READ	4 /* Read */
-#define EXT_CMD_TYPE_DISP_WR	4 /* Command dispatch with write */
-#define EXT_CMD_TYPE_FINAL	3 /* Final command */
-#define EXT_CMD_TYPE_LAST_RW	1 /* Last naked read/write */
-#define EXT_CMD_TYPE_MONO	0 /* Monolithic read/write */
+#define EXT_CMD_TYPE_LAST_PAGEPROG	8
+#define EXT_CMD_TYPE_CHUNK_PAGEPROG	7
+#define EXT_CMD_TYPE_DISPATCH		6 /* Command dispatch */
+#define EXT_CMD_TYPE_NAKED_RW		5 /* Naked read or Naked write */
+#define EXT_CMD_TYPE_READ		4 /* Read */
+#define EXT_CMD_TYPE_DISP_WR		4 /* Command dispatch with write */
+#define EXT_CMD_TYPE_FINAL		3 /* Final command */
+#define EXT_CMD_TYPE_LAST_RW		1 /* Last naked read/write */
+#define EXT_CMD_TYPE_MONO		0 /* Monolithic read/write */
 
 /* macros for registers read/write */
 #define nand_writel(info, off, val)	\
@@ -158,6 +162,7 @@ enum {
 enum pxa3xx_nand_variant {
 	PXA3XX_NAND_VARIANT_PXA,
 	PXA3XX_NAND_VARIANT_ARMADA370,
+	PXA3XX_NAND_VARIANT_BERLIN2,
 };
 
 struct pxa3xx_nand_host {
@@ -319,6 +324,18 @@ static struct nand_ecclayout ecc_layout_4KB_bch8bit = {
 	.oobfree = { }
 };
 
+static struct nand_ecclayout ecc_layout_oob_128 = {
+	.eccbytes = 48,
+	.eccpos = {
+		80, 81, 82, 83, 84, 85, 86, 87,
+		88, 89, 90, 91, 92, 93, 94, 95,
+		96, 97, 98, 99, 100, 101, 102, 103,
+		104, 105, 106, 107, 108, 109, 110, 111,
+		112, 113, 114, 115, 116, 117, 118, 119,
+		120, 121, 122, 123, 124, 125, 126, 127},
+	.oobfree = { {.offset = 2, .length = 78} }
+};
+
 #define NDTR0_tCH(c)	(min((c), 7) << 19)
 #define NDTR0_tCS(c)	(min((c), 7) << 16)
 #define NDTR0_tWH(c)	(min((c), 7) << 11)
@@ -342,6 +359,10 @@ static const struct of_device_id pxa3xx_nand_dt_ids[] = {
 		.compatible = "marvell,armada370-nand",
 		.data       = (void *)PXA3XX_NAND_VARIANT_ARMADA370,
 	},
+	{
+		.compatible = "marvell,berlin2-nand",
+		.data       = (void *)PXA3XX_NAND_VARIANT_BERLIN2,
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids);
@@ -727,7 +748,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 		nand_writel(info, NDCB0, info->ndcb2);
 
 		/* NDCB3 register is available in NFCv2 (Armada 370/XP SoC) */
-		if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
+		if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 ||
+				info->variant == PXA3XX_NAND_VARIANT_BERLIN2)
 			nand_writel(info, NDCB0, info->ndcb3);
 	}
 
@@ -837,6 +859,16 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
 	if (command == NAND_CMD_SEQIN)
 		exec_cmd = 0;
 
+	/* Berlin specific */
+	if (info->variant == PXA3XX_NAND_VARIANT_BERLIN2) {
+		if ((command == NAND_CMD_READ0 && !ext_cmd_type) ||
+				command == NAND_CMD_READOOB)
+			exec_cmd = 0;
+
+		if (command == NAND_CMD_SEQIN)
+			command = NAND_CMD_READ0;
+	}
+
 	addr_cycle = NDCB0_ADDR_CYC(host->row_addr_cycles
 				    + host->col_addr_cycles);
 
@@ -896,6 +928,37 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
 			break;
 		}
 
+		if (info->variant == PXA3XX_NAND_VARIANT_BERLIN2) {
+			if (ext_cmd_type == EXT_CMD_TYPE_LAST_PAGEPROG) {
+				info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+						| NDCB0_CMD_XTYPE(0x3)
+						| NDCB0_ST_ROW_EN
+						| NDCB0_DBC
+						| (NAND_CMD_PAGEPROG << 8);
+			} else if (ext_cmd_type == EXT_CMD_TYPE_CHUNK_PAGEPROG) {
+				info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+						| NDCB0_CMD_XTYPE(0x5)
+						| NDCB0_NC
+						| NDCB0_AUTO_RS
+						| NDCB0_LEN_OVRD
+						| (NAND_CMD_PAGEPROG << 8)
+						| NAND_CMD_SEQIN;
+				info->ndcb3 = info->chunk_size;
+			} else {
+				info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+						| NDCB0_CMD_XTYPE(0x4)
+						| NDCB0_NC
+						| NDCB0_AUTO_RS
+						| NDCB0_LEN_OVRD
+						| addr_cycle
+						| (NAND_CMD_PAGEPROG << 8)
+						| NAND_CMD_SEQIN;
+				info->ndcb3 = info->chunk_size;
+			}
+
+			break;
+		}
+
 		/* Second command setting for large pages */
 		if (mtd->writesize > PAGE_CHUNK_SIZE) {
 			/*
@@ -952,6 +1015,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
 
 		info->data_size = 8;
 		break;
+
 	case NAND_CMD_STATUS:
 		info->buf_count = 1;
 		info->ndcb0 |= NDCB0_CMD_TYPE(4)
@@ -960,7 +1024,6 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
 
 		info->data_size = 8;
 		break;
-
 	case NAND_CMD_ERASE1:
 		info->ndcb0 |= NDCB0_CMD_TYPE(2)
 				| NDCB0_AUTO_RS
@@ -1160,6 +1223,89 @@ static int pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
 	return 0;
 }
 
+static void nand_cmdfunc_berlin(struct mtd_info *mtd, const unsigned command,
+		int column, int page_addr)
+{
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
+	unsigned long timeout;
+	int exec_cmd, ext_cmd_type = 0;
+	unsigned cmd = command;
+
+	if (info->reg_ndcr & NDCR_DWIDTH_M)
+		column /= 2;
+
+	/*
+	 * There may be different NAND chip hooked to
+	 * different chip select, so check whether
+	 * chip select has been changed, if yes, reset the timing
+	 */
+	if (info->cs != host->cs) {
+		info->cs = host->cs;
+		nand_writel(info, NDTR0CS0, info->ndtr0cs0);
+		nand_writel(info, NDTR1CS0, info->ndtr1cs0);
+	}
+
+	prepare_start_command(info, cmd);
+
+	info->need_wait = 1;
+	init_completion(&info->dev_ready);
+
+	pxa3xx_nand_start(info);
+
+	do {
+		init_completion(&info->cmd_complete);
+		info->state = STATE_PREPARED;
+		exec_cmd = prepare_set_command(info, cmd, ext_cmd_type,
+				column, page_addr);
+
+		if (cmd == NAND_CMD_READ0 && !ext_cmd_type) {
+			ext_cmd_type = NDCB0_CMD_XTYPE(0x5);
+			continue;
+		}
+
+		if (!exec_cmd) {
+			info->need_wait = 0;
+			complete(&info->dev_ready);
+			break;
+		}
+
+		/* no IRQ, poll */
+		timeout = jiffies + CHIP_DELAY_TIMEOUT;
+		do {
+			pxa3xx_nand_irq(0, info);
+
+			if (cmd == NAND_CMD_PAGEPROG &&
+					ext_cmd_type != EXT_CMD_TYPE_LAST_PAGEPROG)
+				break;
+
+			if (time_after(jiffies, timeout))
+				goto berlin_timeout;
+		} while (!completion_done(&info->cmd_complete));
+
+		/* sequence completed */
+		if (info->data_size == 0)
+			break;
+
+		if (cmd == NAND_CMD_PAGEPROG &&
+				ext_cmd_type == EXT_CMD_TYPE_LAST_PAGEPROG) {
+			complete(&info->dev_ready);
+			break;
+		}
+
+		if (cmd == NAND_CMD_PAGEPROG) {
+			/* last command */
+			if (info->data_size == info->chunk_size * 2)
+				ext_cmd_type = EXT_CMD_TYPE_LAST_PAGEPROG;
+			else
+				ext_cmd_type = EXT_CMD_TYPE_CHUNK_PAGEPROG;
+		}
+	} while (1);
+
+berlin_timeout:
+	info->state = STATE_IDLE;
+}
+
 static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
 		struct nand_chip *chip, uint8_t *buf, int oob_required,
 		int page)
@@ -1467,6 +1613,16 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info,
 		ecc->size = info->chunk_size;
 		ecc->layout = &ecc_layout_4KB_bch8bit;
 		ecc->strength = 16;
+	} else if (strength == 48 && ecc_stepsize == 1024 &&
+			page_size == 8192) {
+		info->ecc_bch = 1;
+		info->chunk_size = 2048;
+		info->spare_size = 0;
+		info->ecc_size = 32;
+		ecc->mode = NAND_ECC_HW;
+		ecc->size = info->chunk_size;
+		ecc->layout = &ecc_layout_oob_128;
+		ecc->strength = 48;
 	} else {
 		dev_err(&info->pdev->dev,
 			"ECC strength %d at page size %d is not supported\n",
@@ -1495,6 +1651,9 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	/* Set a default chunk size */
 	info->chunk_size = 512;
 
+	if (info->variant == PXA3XX_NAND_VARIANT_BERLIN2)
+		chip->cmdfunc = nand_cmdfunc_berlin;
+
 	ret = pxa3xx_nand_sensing(host);
 	if (ret) {
 		dev_info(&info->pdev->dev, "There is no chip on cs %d!\n",
@@ -1536,7 +1695,7 @@ KEEP_CONFIG:
 	if (mtd->writesize > PAGE_CHUNK_SIZE) {
 		if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) {
 			chip->cmdfunc = nand_cmdfunc_extended;
-		} else {
+		} else if (info->variant != PXA3XX_NAND_VARIANT_BERLIN2) {
 			dev_err(&info->pdev->dev,
 				"unsupported page size on this variant\n");
 			return -ENODEV;
-- 
2.3.5


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

* [PATCH v4 06/10] mtd: pxa3xx_nand: add support for the Marvell Berlin nand controller
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: zmxu, boris.brezillon, Antoine Tenart, linux-kernel, linux-mtd,
	jszhang, linux-arm-kernel

The nand controller on Marvell Berlin SoC reuse the pxa3xx nand driver
as it quite close. The process of sending commands can be compared to
the one of the Marvell armada 370: read and write commands are done in
chunks.

But the Berlin nand controller has some other specificities which
require some modifications of the pxa3xx nand driver:
- there are no IRQ available so we need to poll the status register: we
  have to use our own cmdfunc Berlin function, and early on the probing
  function.
- PAGEPROG are very different from the one used in the pxa3xx driver,
  so we're using a specific process for this one
- the SEQIN command is equivalent to a READ0 command

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/pxa3xx_nand.c | 179 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 169 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 438770c56bd3..544c8058417f 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -109,6 +109,8 @@
 #define NDCB0_EXT_CMD_TYPE(x)	(((x) << 29) & NDCB0_EXT_CMD_TYPE_MASK)
 #define NDCB0_CMD_TYPE_MASK	(0x7 << 21)
 #define NDCB0_CMD_TYPE(x)	(((x) << 21) & NDCB0_CMD_TYPE_MASK)
+#define NDCB0_CMD_XTYPE_MASK	(0x7 << 29)
+#define NDCB0_CMD_XTYPE(x)	(((x) << 29) & NDCB0_CMD_XTYPE_MASK)
 #define NDCB0_NC		(0x1 << 20)
 #define NDCB0_DBC		(0x1 << 19)
 #define NDCB0_ADDR_CYC_MASK	(0x7 << 16)
@@ -117,13 +119,15 @@
 #define NDCB0_CMD1_MASK		(0xff)
 #define NDCB0_ADDR_CYC_SHIFT	(16)
 
-#define EXT_CMD_TYPE_DISPATCH	6 /* Command dispatch */
-#define EXT_CMD_TYPE_NAKED_RW	5 /* Naked read or Naked write */
-#define EXT_CMD_TYPE_READ	4 /* Read */
-#define EXT_CMD_TYPE_DISP_WR	4 /* Command dispatch with write */
-#define EXT_CMD_TYPE_FINAL	3 /* Final command */
-#define EXT_CMD_TYPE_LAST_RW	1 /* Last naked read/write */
-#define EXT_CMD_TYPE_MONO	0 /* Monolithic read/write */
+#define EXT_CMD_TYPE_LAST_PAGEPROG	8
+#define EXT_CMD_TYPE_CHUNK_PAGEPROG	7
+#define EXT_CMD_TYPE_DISPATCH		6 /* Command dispatch */
+#define EXT_CMD_TYPE_NAKED_RW		5 /* Naked read or Naked write */
+#define EXT_CMD_TYPE_READ		4 /* Read */
+#define EXT_CMD_TYPE_DISP_WR		4 /* Command dispatch with write */
+#define EXT_CMD_TYPE_FINAL		3 /* Final command */
+#define EXT_CMD_TYPE_LAST_RW		1 /* Last naked read/write */
+#define EXT_CMD_TYPE_MONO		0 /* Monolithic read/write */
 
 /* macros for registers read/write */
 #define nand_writel(info, off, val)	\
@@ -158,6 +162,7 @@ enum {
 enum pxa3xx_nand_variant {
 	PXA3XX_NAND_VARIANT_PXA,
 	PXA3XX_NAND_VARIANT_ARMADA370,
+	PXA3XX_NAND_VARIANT_BERLIN2,
 };
 
 struct pxa3xx_nand_host {
@@ -319,6 +324,18 @@ static struct nand_ecclayout ecc_layout_4KB_bch8bit = {
 	.oobfree = { }
 };
 
+static struct nand_ecclayout ecc_layout_oob_128 = {
+	.eccbytes = 48,
+	.eccpos = {
+		80, 81, 82, 83, 84, 85, 86, 87,
+		88, 89, 90, 91, 92, 93, 94, 95,
+		96, 97, 98, 99, 100, 101, 102, 103,
+		104, 105, 106, 107, 108, 109, 110, 111,
+		112, 113, 114, 115, 116, 117, 118, 119,
+		120, 121, 122, 123, 124, 125, 126, 127},
+	.oobfree = { {.offset = 2, .length = 78} }
+};
+
 #define NDTR0_tCH(c)	(min((c), 7) << 19)
 #define NDTR0_tCS(c)	(min((c), 7) << 16)
 #define NDTR0_tWH(c)	(min((c), 7) << 11)
@@ -342,6 +359,10 @@ static const struct of_device_id pxa3xx_nand_dt_ids[] = {
 		.compatible = "marvell,armada370-nand",
 		.data       = (void *)PXA3XX_NAND_VARIANT_ARMADA370,
 	},
+	{
+		.compatible = "marvell,berlin2-nand",
+		.data       = (void *)PXA3XX_NAND_VARIANT_BERLIN2,
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids);
@@ -727,7 +748,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 		nand_writel(info, NDCB0, info->ndcb2);
 
 		/* NDCB3 register is available in NFCv2 (Armada 370/XP SoC) */
-		if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
+		if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 ||
+				info->variant == PXA3XX_NAND_VARIANT_BERLIN2)
 			nand_writel(info, NDCB0, info->ndcb3);
 	}
 
@@ -837,6 +859,16 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
 	if (command == NAND_CMD_SEQIN)
 		exec_cmd = 0;
 
+	/* Berlin specific */
+	if (info->variant == PXA3XX_NAND_VARIANT_BERLIN2) {
+		if ((command == NAND_CMD_READ0 && !ext_cmd_type) ||
+				command == NAND_CMD_READOOB)
+			exec_cmd = 0;
+
+		if (command == NAND_CMD_SEQIN)
+			command = NAND_CMD_READ0;
+	}
+
 	addr_cycle = NDCB0_ADDR_CYC(host->row_addr_cycles
 				    + host->col_addr_cycles);
 
@@ -896,6 +928,37 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
 			break;
 		}
 
+		if (info->variant == PXA3XX_NAND_VARIANT_BERLIN2) {
+			if (ext_cmd_type == EXT_CMD_TYPE_LAST_PAGEPROG) {
+				info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+						| NDCB0_CMD_XTYPE(0x3)
+						| NDCB0_ST_ROW_EN
+						| NDCB0_DBC
+						| (NAND_CMD_PAGEPROG << 8);
+			} else if (ext_cmd_type == EXT_CMD_TYPE_CHUNK_PAGEPROG) {
+				info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+						| NDCB0_CMD_XTYPE(0x5)
+						| NDCB0_NC
+						| NDCB0_AUTO_RS
+						| NDCB0_LEN_OVRD
+						| (NAND_CMD_PAGEPROG << 8)
+						| NAND_CMD_SEQIN;
+				info->ndcb3 = info->chunk_size;
+			} else {
+				info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+						| NDCB0_CMD_XTYPE(0x4)
+						| NDCB0_NC
+						| NDCB0_AUTO_RS
+						| NDCB0_LEN_OVRD
+						| addr_cycle
+						| (NAND_CMD_PAGEPROG << 8)
+						| NAND_CMD_SEQIN;
+				info->ndcb3 = info->chunk_size;
+			}
+
+			break;
+		}
+
 		/* Second command setting for large pages */
 		if (mtd->writesize > PAGE_CHUNK_SIZE) {
 			/*
@@ -952,6 +1015,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
 
 		info->data_size = 8;
 		break;
+
 	case NAND_CMD_STATUS:
 		info->buf_count = 1;
 		info->ndcb0 |= NDCB0_CMD_TYPE(4)
@@ -960,7 +1024,6 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
 
 		info->data_size = 8;
 		break;
-
 	case NAND_CMD_ERASE1:
 		info->ndcb0 |= NDCB0_CMD_TYPE(2)
 				| NDCB0_AUTO_RS
@@ -1160,6 +1223,89 @@ static int pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
 	return 0;
 }
 
+static void nand_cmdfunc_berlin(struct mtd_info *mtd, const unsigned command,
+		int column, int page_addr)
+{
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
+	unsigned long timeout;
+	int exec_cmd, ext_cmd_type = 0;
+	unsigned cmd = command;
+
+	if (info->reg_ndcr & NDCR_DWIDTH_M)
+		column /= 2;
+
+	/*
+	 * There may be different NAND chip hooked to
+	 * different chip select, so check whether
+	 * chip select has been changed, if yes, reset the timing
+	 */
+	if (info->cs != host->cs) {
+		info->cs = host->cs;
+		nand_writel(info, NDTR0CS0, info->ndtr0cs0);
+		nand_writel(info, NDTR1CS0, info->ndtr1cs0);
+	}
+
+	prepare_start_command(info, cmd);
+
+	info->need_wait = 1;
+	init_completion(&info->dev_ready);
+
+	pxa3xx_nand_start(info);
+
+	do {
+		init_completion(&info->cmd_complete);
+		info->state = STATE_PREPARED;
+		exec_cmd = prepare_set_command(info, cmd, ext_cmd_type,
+				column, page_addr);
+
+		if (cmd == NAND_CMD_READ0 && !ext_cmd_type) {
+			ext_cmd_type = NDCB0_CMD_XTYPE(0x5);
+			continue;
+		}
+
+		if (!exec_cmd) {
+			info->need_wait = 0;
+			complete(&info->dev_ready);
+			break;
+		}
+
+		/* no IRQ, poll */
+		timeout = jiffies + CHIP_DELAY_TIMEOUT;
+		do {
+			pxa3xx_nand_irq(0, info);
+
+			if (cmd == NAND_CMD_PAGEPROG &&
+					ext_cmd_type != EXT_CMD_TYPE_LAST_PAGEPROG)
+				break;
+
+			if (time_after(jiffies, timeout))
+				goto berlin_timeout;
+		} while (!completion_done(&info->cmd_complete));
+
+		/* sequence completed */
+		if (info->data_size == 0)
+			break;
+
+		if (cmd == NAND_CMD_PAGEPROG &&
+				ext_cmd_type == EXT_CMD_TYPE_LAST_PAGEPROG) {
+			complete(&info->dev_ready);
+			break;
+		}
+
+		if (cmd == NAND_CMD_PAGEPROG) {
+			/* last command */
+			if (info->data_size == info->chunk_size * 2)
+				ext_cmd_type = EXT_CMD_TYPE_LAST_PAGEPROG;
+			else
+				ext_cmd_type = EXT_CMD_TYPE_CHUNK_PAGEPROG;
+		}
+	} while (1);
+
+berlin_timeout:
+	info->state = STATE_IDLE;
+}
+
 static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
 		struct nand_chip *chip, uint8_t *buf, int oob_required,
 		int page)
@@ -1467,6 +1613,16 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info,
 		ecc->size = info->chunk_size;
 		ecc->layout = &ecc_layout_4KB_bch8bit;
 		ecc->strength = 16;
+	} else if (strength == 48 && ecc_stepsize == 1024 &&
+			page_size == 8192) {
+		info->ecc_bch = 1;
+		info->chunk_size = 2048;
+		info->spare_size = 0;
+		info->ecc_size = 32;
+		ecc->mode = NAND_ECC_HW;
+		ecc->size = info->chunk_size;
+		ecc->layout = &ecc_layout_oob_128;
+		ecc->strength = 48;
 	} else {
 		dev_err(&info->pdev->dev,
 			"ECC strength %d at page size %d is not supported\n",
@@ -1495,6 +1651,9 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	/* Set a default chunk size */
 	info->chunk_size = 512;
 
+	if (info->variant == PXA3XX_NAND_VARIANT_BERLIN2)
+		chip->cmdfunc = nand_cmdfunc_berlin;
+
 	ret = pxa3xx_nand_sensing(host);
 	if (ret) {
 		dev_info(&info->pdev->dev, "There is no chip on cs %d!\n",
@@ -1536,7 +1695,7 @@ KEEP_CONFIG:
 	if (mtd->writesize > PAGE_CHUNK_SIZE) {
 		if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) {
 			chip->cmdfunc = nand_cmdfunc_extended;
-		} else {
+		} else if (info->variant != PXA3XX_NAND_VARIANT_BERLIN2) {
 			dev_err(&info->pdev->dev,
 				"unsupported page size on this variant\n");
 			return -ENODEV;
-- 
2.3.5

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

* [PATCH v4 06/10] mtd: pxa3xx_nand: add support for the Marvell Berlin nand controller
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: linux-arm-kernel

The nand controller on Marvell Berlin SoC reuse the pxa3xx nand driver
as it quite close. The process of sending commands can be compared to
the one of the Marvell armada 370: read and write commands are done in
chunks.

But the Berlin nand controller has some other specificities which
require some modifications of the pxa3xx nand driver:
- there are no IRQ available so we need to poll the status register: we
  have to use our own cmdfunc Berlin function, and early on the probing
  function.
- PAGEPROG are very different from the one used in the pxa3xx driver,
  so we're using a specific process for this one
- the SEQIN command is equivalent to a READ0 command

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/pxa3xx_nand.c | 179 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 169 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 438770c56bd3..544c8058417f 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -109,6 +109,8 @@
 #define NDCB0_EXT_CMD_TYPE(x)	(((x) << 29) & NDCB0_EXT_CMD_TYPE_MASK)
 #define NDCB0_CMD_TYPE_MASK	(0x7 << 21)
 #define NDCB0_CMD_TYPE(x)	(((x) << 21) & NDCB0_CMD_TYPE_MASK)
+#define NDCB0_CMD_XTYPE_MASK	(0x7 << 29)
+#define NDCB0_CMD_XTYPE(x)	(((x) << 29) & NDCB0_CMD_XTYPE_MASK)
 #define NDCB0_NC		(0x1 << 20)
 #define NDCB0_DBC		(0x1 << 19)
 #define NDCB0_ADDR_CYC_MASK	(0x7 << 16)
@@ -117,13 +119,15 @@
 #define NDCB0_CMD1_MASK		(0xff)
 #define NDCB0_ADDR_CYC_SHIFT	(16)
 
-#define EXT_CMD_TYPE_DISPATCH	6 /* Command dispatch */
-#define EXT_CMD_TYPE_NAKED_RW	5 /* Naked read or Naked write */
-#define EXT_CMD_TYPE_READ	4 /* Read */
-#define EXT_CMD_TYPE_DISP_WR	4 /* Command dispatch with write */
-#define EXT_CMD_TYPE_FINAL	3 /* Final command */
-#define EXT_CMD_TYPE_LAST_RW	1 /* Last naked read/write */
-#define EXT_CMD_TYPE_MONO	0 /* Monolithic read/write */
+#define EXT_CMD_TYPE_LAST_PAGEPROG	8
+#define EXT_CMD_TYPE_CHUNK_PAGEPROG	7
+#define EXT_CMD_TYPE_DISPATCH		6 /* Command dispatch */
+#define EXT_CMD_TYPE_NAKED_RW		5 /* Naked read or Naked write */
+#define EXT_CMD_TYPE_READ		4 /* Read */
+#define EXT_CMD_TYPE_DISP_WR		4 /* Command dispatch with write */
+#define EXT_CMD_TYPE_FINAL		3 /* Final command */
+#define EXT_CMD_TYPE_LAST_RW		1 /* Last naked read/write */
+#define EXT_CMD_TYPE_MONO		0 /* Monolithic read/write */
 
 /* macros for registers read/write */
 #define nand_writel(info, off, val)	\
@@ -158,6 +162,7 @@ enum {
 enum pxa3xx_nand_variant {
 	PXA3XX_NAND_VARIANT_PXA,
 	PXA3XX_NAND_VARIANT_ARMADA370,
+	PXA3XX_NAND_VARIANT_BERLIN2,
 };
 
 struct pxa3xx_nand_host {
@@ -319,6 +324,18 @@ static struct nand_ecclayout ecc_layout_4KB_bch8bit = {
 	.oobfree = { }
 };
 
+static struct nand_ecclayout ecc_layout_oob_128 = {
+	.eccbytes = 48,
+	.eccpos = {
+		80, 81, 82, 83, 84, 85, 86, 87,
+		88, 89, 90, 91, 92, 93, 94, 95,
+		96, 97, 98, 99, 100, 101, 102, 103,
+		104, 105, 106, 107, 108, 109, 110, 111,
+		112, 113, 114, 115, 116, 117, 118, 119,
+		120, 121, 122, 123, 124, 125, 126, 127},
+	.oobfree = { {.offset = 2, .length = 78} }
+};
+
 #define NDTR0_tCH(c)	(min((c), 7) << 19)
 #define NDTR0_tCS(c)	(min((c), 7) << 16)
 #define NDTR0_tWH(c)	(min((c), 7) << 11)
@@ -342,6 +359,10 @@ static const struct of_device_id pxa3xx_nand_dt_ids[] = {
 		.compatible = "marvell,armada370-nand",
 		.data       = (void *)PXA3XX_NAND_VARIANT_ARMADA370,
 	},
+	{
+		.compatible = "marvell,berlin2-nand",
+		.data       = (void *)PXA3XX_NAND_VARIANT_BERLIN2,
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids);
@@ -727,7 +748,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 		nand_writel(info, NDCB0, info->ndcb2);
 
 		/* NDCB3 register is available in NFCv2 (Armada 370/XP SoC) */
-		if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
+		if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 ||
+				info->variant == PXA3XX_NAND_VARIANT_BERLIN2)
 			nand_writel(info, NDCB0, info->ndcb3);
 	}
 
@@ -837,6 +859,16 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
 	if (command == NAND_CMD_SEQIN)
 		exec_cmd = 0;
 
+	/* Berlin specific */
+	if (info->variant == PXA3XX_NAND_VARIANT_BERLIN2) {
+		if ((command == NAND_CMD_READ0 && !ext_cmd_type) ||
+				command == NAND_CMD_READOOB)
+			exec_cmd = 0;
+
+		if (command == NAND_CMD_SEQIN)
+			command = NAND_CMD_READ0;
+	}
+
 	addr_cycle = NDCB0_ADDR_CYC(host->row_addr_cycles
 				    + host->col_addr_cycles);
 
@@ -896,6 +928,37 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
 			break;
 		}
 
+		if (info->variant == PXA3XX_NAND_VARIANT_BERLIN2) {
+			if (ext_cmd_type == EXT_CMD_TYPE_LAST_PAGEPROG) {
+				info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+						| NDCB0_CMD_XTYPE(0x3)
+						| NDCB0_ST_ROW_EN
+						| NDCB0_DBC
+						| (NAND_CMD_PAGEPROG << 8);
+			} else if (ext_cmd_type == EXT_CMD_TYPE_CHUNK_PAGEPROG) {
+				info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+						| NDCB0_CMD_XTYPE(0x5)
+						| NDCB0_NC
+						| NDCB0_AUTO_RS
+						| NDCB0_LEN_OVRD
+						| (NAND_CMD_PAGEPROG << 8)
+						| NAND_CMD_SEQIN;
+				info->ndcb3 = info->chunk_size;
+			} else {
+				info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+						| NDCB0_CMD_XTYPE(0x4)
+						| NDCB0_NC
+						| NDCB0_AUTO_RS
+						| NDCB0_LEN_OVRD
+						| addr_cycle
+						| (NAND_CMD_PAGEPROG << 8)
+						| NAND_CMD_SEQIN;
+				info->ndcb3 = info->chunk_size;
+			}
+
+			break;
+		}
+
 		/* Second command setting for large pages */
 		if (mtd->writesize > PAGE_CHUNK_SIZE) {
 			/*
@@ -952,6 +1015,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
 
 		info->data_size = 8;
 		break;
+
 	case NAND_CMD_STATUS:
 		info->buf_count = 1;
 		info->ndcb0 |= NDCB0_CMD_TYPE(4)
@@ -960,7 +1024,6 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
 
 		info->data_size = 8;
 		break;
-
 	case NAND_CMD_ERASE1:
 		info->ndcb0 |= NDCB0_CMD_TYPE(2)
 				| NDCB0_AUTO_RS
@@ -1160,6 +1223,89 @@ static int pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
 	return 0;
 }
 
+static void nand_cmdfunc_berlin(struct mtd_info *mtd, const unsigned command,
+		int column, int page_addr)
+{
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
+	unsigned long timeout;
+	int exec_cmd, ext_cmd_type = 0;
+	unsigned cmd = command;
+
+	if (info->reg_ndcr & NDCR_DWIDTH_M)
+		column /= 2;
+
+	/*
+	 * There may be different NAND chip hooked to
+	 * different chip select, so check whether
+	 * chip select has been changed, if yes, reset the timing
+	 */
+	if (info->cs != host->cs) {
+		info->cs = host->cs;
+		nand_writel(info, NDTR0CS0, info->ndtr0cs0);
+		nand_writel(info, NDTR1CS0, info->ndtr1cs0);
+	}
+
+	prepare_start_command(info, cmd);
+
+	info->need_wait = 1;
+	init_completion(&info->dev_ready);
+
+	pxa3xx_nand_start(info);
+
+	do {
+		init_completion(&info->cmd_complete);
+		info->state = STATE_PREPARED;
+		exec_cmd = prepare_set_command(info, cmd, ext_cmd_type,
+				column, page_addr);
+
+		if (cmd == NAND_CMD_READ0 && !ext_cmd_type) {
+			ext_cmd_type = NDCB0_CMD_XTYPE(0x5);
+			continue;
+		}
+
+		if (!exec_cmd) {
+			info->need_wait = 0;
+			complete(&info->dev_ready);
+			break;
+		}
+
+		/* no IRQ, poll */
+		timeout = jiffies + CHIP_DELAY_TIMEOUT;
+		do {
+			pxa3xx_nand_irq(0, info);
+
+			if (cmd == NAND_CMD_PAGEPROG &&
+					ext_cmd_type != EXT_CMD_TYPE_LAST_PAGEPROG)
+				break;
+
+			if (time_after(jiffies, timeout))
+				goto berlin_timeout;
+		} while (!completion_done(&info->cmd_complete));
+
+		/* sequence completed */
+		if (info->data_size == 0)
+			break;
+
+		if (cmd == NAND_CMD_PAGEPROG &&
+				ext_cmd_type == EXT_CMD_TYPE_LAST_PAGEPROG) {
+			complete(&info->dev_ready);
+			break;
+		}
+
+		if (cmd == NAND_CMD_PAGEPROG) {
+			/* last command */
+			if (info->data_size == info->chunk_size * 2)
+				ext_cmd_type = EXT_CMD_TYPE_LAST_PAGEPROG;
+			else
+				ext_cmd_type = EXT_CMD_TYPE_CHUNK_PAGEPROG;
+		}
+	} while (1);
+
+berlin_timeout:
+	info->state = STATE_IDLE;
+}
+
 static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
 		struct nand_chip *chip, uint8_t *buf, int oob_required,
 		int page)
@@ -1467,6 +1613,16 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info,
 		ecc->size = info->chunk_size;
 		ecc->layout = &ecc_layout_4KB_bch8bit;
 		ecc->strength = 16;
+	} else if (strength == 48 && ecc_stepsize == 1024 &&
+			page_size == 8192) {
+		info->ecc_bch = 1;
+		info->chunk_size = 2048;
+		info->spare_size = 0;
+		info->ecc_size = 32;
+		ecc->mode = NAND_ECC_HW;
+		ecc->size = info->chunk_size;
+		ecc->layout = &ecc_layout_oob_128;
+		ecc->strength = 48;
 	} else {
 		dev_err(&info->pdev->dev,
 			"ECC strength %d at page size %d is not supported\n",
@@ -1495,6 +1651,9 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	/* Set a default chunk size */
 	info->chunk_size = 512;
 
+	if (info->variant == PXA3XX_NAND_VARIANT_BERLIN2)
+		chip->cmdfunc = nand_cmdfunc_berlin;
+
 	ret = pxa3xx_nand_sensing(host);
 	if (ret) {
 		dev_info(&info->pdev->dev, "There is no chip on cs %d!\n",
@@ -1536,7 +1695,7 @@ KEEP_CONFIG:
 	if (mtd->writesize > PAGE_CHUNK_SIZE) {
 		if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) {
 			chip->cmdfunc = nand_cmdfunc_extended;
-		} else {
+		} else if (info->variant != PXA3XX_NAND_VARIANT_BERLIN2) {
 			dev_err(&info->pdev->dev,
 				"unsupported page size on this variant\n");
 			return -ENODEV;
-- 
2.3.5

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

* [PATCH v4 07/10] Documentation: bindings: add the Berlin nand controller compatible
  2015-04-15 17:23 ` Antoine Tenart
  (?)
@ 2015-04-15 17:24   ` Antoine Tenart
  -1 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: Antoine Tenart, boris.brezillon, zmxu, jszhang, linux-arm-kernel,
	linux-mtd, linux-kernel

The Berlin nand controller support was introduced using the existing
pxa3xx nand driver. Add the Berlin specific compatible into the
documentation.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
index ecd1fc071f81..f33ee0aa0a2e 100644
--- a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
@@ -5,6 +5,7 @@ Required properties:
  - compatible:		Should be set to one of the following:
 			marvell,pxa3xx-nand
 			marvell,armada370-nand
+			marvell,berlin2-nand
  - reg: 		The register base for the controller
  - interrupts:		The interrupt to map
  - #address-cells:	Set to <1> if the node includes partitions
-- 
2.3.5


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

* [PATCH v4 07/10] Documentation: bindings: add the Berlin nand controller compatible
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: zmxu, boris.brezillon, Antoine Tenart, linux-kernel, linux-mtd,
	jszhang, linux-arm-kernel

The Berlin nand controller support was introduced using the existing
pxa3xx nand driver. Add the Berlin specific compatible into the
documentation.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
index ecd1fc071f81..f33ee0aa0a2e 100644
--- a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
@@ -5,6 +5,7 @@ Required properties:
  - compatible:		Should be set to one of the following:
 			marvell,pxa3xx-nand
 			marvell,armada370-nand
+			marvell,berlin2-nand
  - reg: 		The register base for the controller
  - interrupts:		The interrupt to map
  - #address-cells:	Set to <1> if the node includes partitions
-- 
2.3.5

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

* [PATCH v4 07/10] Documentation: bindings: add the Berlin nand controller compatible
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: linux-arm-kernel

The Berlin nand controller support was introduced using the existing
pxa3xx nand driver. Add the Berlin specific compatible into the
documentation.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
index ecd1fc071f81..f33ee0aa0a2e 100644
--- a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
@@ -5,6 +5,7 @@ Required properties:
  - compatible:		Should be set to one of the following:
 			marvell,pxa3xx-nand
 			marvell,armada370-nand
+			marvell,berlin2-nand
  - reg: 		The register base for the controller
  - interrupts:		The interrupt to map
  - #address-cells:	Set to <1> if the node includes partitions
-- 
2.3.5

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

* [PATCH v4 08/10] mtd: nand: let Marvell Berlin SoCs select the pxa3xx driver
  2015-04-15 17:23 ` Antoine Tenart
  (?)
@ 2015-04-15 17:24   ` Antoine Tenart
  -1 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: Antoine Tenart, boris.brezillon, zmxu, jszhang, linux-arm-kernel,
	linux-mtd, linux-kernel

Marvell Berlin nand controller support has been added in the pxa3xx nand
driver. Let these SoCs select the driver.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/Kconfig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 5b76a173cd95..acca044da603 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -331,8 +331,8 @@ config MTD_NAND_ATMEL
 	  on Atmel AT91 and AVR32 processors.
 
 config MTD_NAND_PXA3xx
-	tristate "NAND support on PXA3xx and Armada 370/XP"
-	depends on PXA3xx || ARCH_MMP || PLAT_ORION
+	tristate "NAND support on PXA3xx, Armada 370/XP and Marvell Berlin"
+	depends on PXA3xx || ARCH_MMP || PLAT_ORION || ARCH_BERLIN
 	help
 	  This enables the driver for the NAND flash device found on
 	  PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2).
-- 
2.3.5


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

* [PATCH v4 08/10] mtd: nand: let Marvell Berlin SoCs select the pxa3xx driver
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: zmxu, boris.brezillon, Antoine Tenart, linux-kernel, linux-mtd,
	jszhang, linux-arm-kernel

Marvell Berlin nand controller support has been added in the pxa3xx nand
driver. Let these SoCs select the driver.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/Kconfig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 5b76a173cd95..acca044da603 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -331,8 +331,8 @@ config MTD_NAND_ATMEL
 	  on Atmel AT91 and AVR32 processors.
 
 config MTD_NAND_PXA3xx
-	tristate "NAND support on PXA3xx and Armada 370/XP"
-	depends on PXA3xx || ARCH_MMP || PLAT_ORION
+	tristate "NAND support on PXA3xx, Armada 370/XP and Marvell Berlin"
+	depends on PXA3xx || ARCH_MMP || PLAT_ORION || ARCH_BERLIN
 	help
 	  This enables the driver for the NAND flash device found on
 	  PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2).
-- 
2.3.5

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

* [PATCH v4 08/10] mtd: nand: let Marvell Berlin SoCs select the pxa3xx driver
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: linux-arm-kernel

Marvell Berlin nand controller support has been added in the pxa3xx nand
driver. Let these SoCs select the driver.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 drivers/mtd/nand/Kconfig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 5b76a173cd95..acca044da603 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -331,8 +331,8 @@ config MTD_NAND_ATMEL
 	  on Atmel AT91 and AVR32 processors.
 
 config MTD_NAND_PXA3xx
-	tristate "NAND support on PXA3xx and Armada 370/XP"
-	depends on PXA3xx || ARCH_MMP || PLAT_ORION
+	tristate "NAND support on PXA3xx, Armada 370/XP and Marvell Berlin"
+	depends on PXA3xx || ARCH_MMP || PLAT_ORION || ARCH_BERLIN
 	help
 	  This enables the driver for the NAND flash device found on
 	  PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2).
-- 
2.3.5

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

* [PATCH v4 09/10] ARM: berlin: add BG2Q node for the nand
  2015-04-15 17:23 ` Antoine Tenart
  (?)
@ 2015-04-15 17:24   ` Antoine Tenart
  -1 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: Antoine Tenart, boris.brezillon, zmxu, jszhang, linux-arm-kernel,
	linux-mtd, linux-kernel

Add a node describing the nand controller of the Marvell Berlin BG2Q
SoC. It uses the pxa3xx nand driver, with a dedicated compatible.

Also add the corresponding pinmuxing configuration.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 arch/arm/boot/dts/berlin2q.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/berlin2q.dtsi
index be5397288d24..aeb3a0ea0540 100644
--- a/arch/arm/boot/dts/berlin2q.dtsi
+++ b/arch/arm/boot/dts/berlin2q.dtsi
@@ -437,6 +437,19 @@
 			status = "disabled";
 		};
 
+		nand0: nand@f00000 {
+			compatible = "marvell,berlin2-nand";
+			reg = <0xf00000 0x10000>;
+			interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&chip CLKID_NFC>,
+				 <&chip CLKID_NFC_ECC>;
+			clock-names = "nfc", "ecc";
+
+			#address-cells = <1>;
+
+			status = "disabled";
+		};
+
 		apb@fc0000 {
 			compatible = "simple-bus";
 			#address-cells = <1>;
-- 
2.3.5


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

* [PATCH v4 09/10] ARM: berlin: add BG2Q node for the nand
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: zmxu, boris.brezillon, Antoine Tenart, linux-kernel, linux-mtd,
	jszhang, linux-arm-kernel

Add a node describing the nand controller of the Marvell Berlin BG2Q
SoC. It uses the pxa3xx nand driver, with a dedicated compatible.

Also add the corresponding pinmuxing configuration.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 arch/arm/boot/dts/berlin2q.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/berlin2q.dtsi
index be5397288d24..aeb3a0ea0540 100644
--- a/arch/arm/boot/dts/berlin2q.dtsi
+++ b/arch/arm/boot/dts/berlin2q.dtsi
@@ -437,6 +437,19 @@
 			status = "disabled";
 		};
 
+		nand0: nand@f00000 {
+			compatible = "marvell,berlin2-nand";
+			reg = <0xf00000 0x10000>;
+			interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&chip CLKID_NFC>,
+				 <&chip CLKID_NFC_ECC>;
+			clock-names = "nfc", "ecc";
+
+			#address-cells = <1>;
+
+			status = "disabled";
+		};
+
 		apb@fc0000 {
 			compatible = "simple-bus";
 			#address-cells = <1>;
-- 
2.3.5

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

* [PATCH v4 09/10] ARM: berlin: add BG2Q node for the nand
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: linux-arm-kernel

Add a node describing the nand controller of the Marvell Berlin BG2Q
SoC. It uses the pxa3xx nand driver, with a dedicated compatible.

Also add the corresponding pinmuxing configuration.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 arch/arm/boot/dts/berlin2q.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/berlin2q.dtsi
index be5397288d24..aeb3a0ea0540 100644
--- a/arch/arm/boot/dts/berlin2q.dtsi
+++ b/arch/arm/boot/dts/berlin2q.dtsi
@@ -437,6 +437,19 @@
 			status = "disabled";
 		};
 
+		nand0: nand at f00000 {
+			compatible = "marvell,berlin2-nand";
+			reg = <0xf00000 0x10000>;
+			interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&chip CLKID_NFC>,
+				 <&chip CLKID_NFC_ECC>;
+			clock-names = "nfc", "ecc";
+
+			#address-cells = <1>;
+
+			status = "disabled";
+		};
+
 		apb at fc0000 {
 			compatible = "simple-bus";
 			#address-cells = <1>;
-- 
2.3.5

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

* [PATCH v4 10/10] ARM: berlin: enable flash on the BG2Q DMP
  2015-04-15 17:23 ` Antoine Tenart
  (?)
@ 2015-04-15 17:24   ` Antoine Tenart
  -1 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: Antoine Tenart, boris.brezillon, zmxu, jszhang, linux-arm-kernel,
	linux-mtd, linux-kernel

The BG2Q DMP has a nand controller. Add the corresponding node, but do
not enable it by default because the nand is only available on some BG2Q
DMP.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 arch/arm/boot/dts/berlin2q-marvell-dmp.dts | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
index a98ac1bd8f65..4157258a6fb0 100644
--- a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
+++ b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
@@ -112,3 +112,28 @@
 &sata_phy {
 	status = "okay";
 };
+
+&chip {
+	nand_pmux: nand-pmux {
+		groups = "G0", "G1";
+		function = "nand";
+	};
+};
+
+&nand0 {
+	pinctrl-0 = <&nand_pmux>;
+	pinctrl-names = "default";
+
+	marvell,nand-enable-arbiter;
+	nand-ecc-strength = <48>;
+	nand-ecc-step-size = <1024>;
+
+	num-cs = <1>;
+
+	/*
+	 * Two kinds of BG2Q DMP are available: one with emmc and
+	 * one with a nand. The latter is not widespread. Because
+	 * of this, disable the nand by default.
+	 */
+	status = "disabled";
+};
-- 
2.3.5


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

* [PATCH v4 10/10] ARM: berlin: enable flash on the BG2Q DMP
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: sebastian.hesselbarth, ezequiel.garcia, dwmw2, computersforpeace
  Cc: zmxu, boris.brezillon, Antoine Tenart, linux-kernel, linux-mtd,
	jszhang, linux-arm-kernel

The BG2Q DMP has a nand controller. Add the corresponding node, but do
not enable it by default because the nand is only available on some BG2Q
DMP.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 arch/arm/boot/dts/berlin2q-marvell-dmp.dts | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
index a98ac1bd8f65..4157258a6fb0 100644
--- a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
+++ b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
@@ -112,3 +112,28 @@
 &sata_phy {
 	status = "okay";
 };
+
+&chip {
+	nand_pmux: nand-pmux {
+		groups = "G0", "G1";
+		function = "nand";
+	};
+};
+
+&nand0 {
+	pinctrl-0 = <&nand_pmux>;
+	pinctrl-names = "default";
+
+	marvell,nand-enable-arbiter;
+	nand-ecc-strength = <48>;
+	nand-ecc-step-size = <1024>;
+
+	num-cs = <1>;
+
+	/*
+	 * Two kinds of BG2Q DMP are available: one with emmc and
+	 * one with a nand. The latter is not widespread. Because
+	 * of this, disable the nand by default.
+	 */
+	status = "disabled";
+};
-- 
2.3.5

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

* [PATCH v4 10/10] ARM: berlin: enable flash on the BG2Q DMP
@ 2015-04-15 17:24   ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-15 17:24 UTC (permalink / raw)
  To: linux-arm-kernel

The BG2Q DMP has a nand controller. Add the corresponding node, but do
not enable it by default because the nand is only available on some BG2Q
DMP.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---
 arch/arm/boot/dts/berlin2q-marvell-dmp.dts | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
index a98ac1bd8f65..4157258a6fb0 100644
--- a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
+++ b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
@@ -112,3 +112,28 @@
 &sata_phy {
 	status = "okay";
 };
+
+&chip {
+	nand_pmux: nand-pmux {
+		groups = "G0", "G1";
+		function = "nand";
+	};
+};
+
+&nand0 {
+	pinctrl-0 = <&nand_pmux>;
+	pinctrl-names = "default";
+
+	marvell,nand-enable-arbiter;
+	nand-ecc-strength = <48>;
+	nand-ecc-step-size = <1024>;
+
+	num-cs = <1>;
+
+	/*
+	 * Two kinds of BG2Q DMP are available: one with emmc and
+	 * one with a nand. The latter is not widespread. Because
+	 * of this, disable the nand by default.
+	 */
+	status = "disabled";
+};
-- 
2.3.5

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

* Re: [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
  2015-04-15 17:24   ` Antoine Tenart
  (?)
@ 2015-04-15 19:11     ` Sebastian Hesselbarth
  -1 siblings, 0 replies; 57+ messages in thread
From: Sebastian Hesselbarth @ 2015-04-15 19:11 UTC (permalink / raw)
  To: Antoine Tenart, ezequiel.garcia, dwmw2, computersforpeace
  Cc: boris.brezillon, zmxu, jszhang, linux-arm-kernel, linux-mtd,
	linux-kernel

On 15.04.2015 19:24, Antoine Tenart wrote:
> Rework the pxa3xx_nand driver to allow using functions exported by the
> nand framework to detect the flash and to configure the timings.
>
> Because this driver supports some non-ONFI devices, we also keep the
> custom timing setup of this driver so these devices won't break.
>
> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
> ---
[...]

Antoine,

there are some issues with this patch.

> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index dc0edbc406bb..438770c56bd3 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c
> @@ -251,15 +251,14 @@ static struct pxa3xx_nand_timing timing[] = {
>   };
>
>   static struct pxa3xx_nand_flash builtin_flash_types[] = {
> -{ "DEFAULT FLASH",      0,   0, 2048,  8,  8,    0, &timing[0] },
> -{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, &timing[1] },
> -{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, &timing[1] },
> -{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, &timing[1] },
> -{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, &timing[2] },
> -{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, &timing[2] },
> -{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, 4096, &timing[2] },
> -{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, 4096, &timing[2] },
> -{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3] },
> +	{ 0x46ec, 16, 16, &timing[1] },
> +	{ 0xdaec,  8,  8, &timing[1] },
> +	{ 0xd7ec,  8,  8, &timing[1] },
> +	{ 0xa12c,  8,  8, &timing[2] },
> +	{ 0xb12c, 16, 16, &timing[2] },
> +	{ 0xdc2c,  8,  8, &timing[2] },
> +	{ 0xcc2c, 16, 16, &timing[2] },
> +	{ 0xba20, 16, 16, &timing[3] },

How about we get rid of the driver specific timings completely
and pick up the best onfi timing match instead? The nand_ids table
allows for a default_onfi_timing parameter even if onfi itself is
not supported.

For generic flash, i.e. no specific entry in the nand_ids table,
we either choose onfi mode 0 (most conservative) or an even slower
one.

[...]
> +static void pxa3xx_nand_set_sdr_timing(struct pxa3xx_nand_host *host,
> +				       const struct nand_sdr_timings *t)
> +{
> +	struct pxa3xx_nand_info *info = host->info_data;
> +	unsigned long nand_clk = clk_get_rate(info->clk);
> +	uint32_t ndtr0, ndtr1;
> +
> +	u32 tCH_min = DIV_ROUND_UP(t->tCH_min, 1000);
> +	u32 tCS_min = DIV_ROUND_UP(t->tCS_min, 1000);
> +	u32 tWH_min = DIV_ROUND_UP(t->tWH_min, 1000);
> +	u32 tWP_min = DIV_ROUND_UP(t->tWP_min, 1000);

While tWH_min is the minimum hold time of WE_n and tWP_min
the minimum pulse width, the sum of the two rounded values
may well exceed the minimum WE_n cycle width tWC_min.

How about we do below instead?

u32 tWH_min = DIV_ROUND_UP(t->tWH_min, 1000);
u32 tWP_min = DIV_ROUND_UP(t->tWC_min - tWH_min, 1000);
(note the missing t-> in front of tWH_min)

> +	u32 tREH_min = DIV_ROUND_UP(t->tREH_min, 1000);
> +	u32 tRP_min = DIV_ROUND_UP(t->tRP_min, 1000);

Same applies to tRH and tRP.	

> +	u32 tRST_max = DIV_ROUND_UP_ULL(t->tRST_max, 1000);
> +	u32 tWHR_min = DIV_ROUND_UP(t->tWHR_min, 1000);
> +	u32 tAR_min = DIV_ROUND_UP(t->tAR_min, 1000);
> +
> +	ndtr0 = NDTR0_tCH(ns2cycle(tCH_min, nand_clk)) |
> +		NDTR0_tCS(ns2cycle(tCS_min, nand_clk)) |
> +		NDTR0_tWH(ns2cycle(tWH_min, nand_clk)) |
> +		NDTR0_tWP(ns2cycle(tWP_min, nand_clk)) |
> +		NDTR0_tRH(ns2cycle(tREH_min, nand_clk)) |
> +		NDTR0_tRP(ns2cycle(tRP_min, nand_clk));
> +
> +	ndtr1 = NDTR1_tR(ns2cycle(tRST_max, nand_clk)) |

Well, tRST (max reset duration) is not tR (max page read
time) but much higher. I see that the onfi timings do not
directly encode tR but have extra timings for tPROG, tBERS,
tR, and tCCS.

I guess we'll have to amend sdr_timings for non-onfi devices
then.

Also, if you check the armada370 functional spec, there is
several meanings for tR register. Currently, pxa3xx nfc driver
does not use WAIT_MODE which is supported for NFCv2 (non-pxa3xx
SoCs). That will allow the controller to use R/Bn signal instead.

Anyways, timing conversion is already tricky enough, let's start
with 1:1 conversion and add additional modes later.

> +		NDTR1_tWHR(ns2cycle(tWHR_min, nand_clk)) |
> +		NDTR1_tAR(ns2cycle(tAR_min, nand_clk));
> +
> +	info->ndtr0cs0 = ndtr0;
> +	info->ndtr1cs0 = ndtr1;
> +	nand_writel(info, NDTR0CS0, ndtr0);
> +	nand_writel(info, NDTR1CS0, ndtr1);
> +}
> +
> +static int pxa3xx_nand_init_timings(struct pxa3xx_nand_host *host)
> +{
> +	const struct nand_sdr_timings *timings;
> +	struct nand_chip *chip = &host->chip;
> +	struct pxa3xx_nand_info *info = host->info_data;
> +	const struct pxa3xx_nand_flash *f = NULL;
> +	int mode, id, ntypes, i;
> +
> +	mode = onfi_get_async_timing_mode(chip);
> +	if (mode == ONFI_TIMING_MODE_UNKNOWN) {
> +		ntypes = ARRAY_SIZE(builtin_flash_types);
> +
> +		chip->cmdfunc(host->mtd, NAND_CMD_READID, 0x00, -1);
> +
> +		id = chip->read_byte(host->mtd);
> +		id |= chip->read_byte(host->mtd) << 0x8;
> +
> +		for (i = 0; i < ntypes; i++) {
> +			f = &builtin_flash_types[i];
> +
> +			if (f->chip_id == id)
> +				break;
> +		}
> +
> +		if (i == ntypes) {
> +			dev_err(&info->pdev->dev, "Error: timings not found\n");
> +			return -EINVAL;
> +		}
> +
> +		pxa3xx_nand_set_timing(host, f->timing);
> +
> +		if (f->flash_width == 16) {
> +			info->reg_ndcr |= NDCR_DWIDTH_M;
> +			chip->options |= NAND_BUSWIDTH_16;
> +		}
> +
> +		info->reg_ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
> +	} else {
> +		mode = fls(mode) - 1;
> +		if (mode < 0)
> +			mode = 0;

Is mode really a bitmap? If so, the name of onfi_get_async_timing_mode()
is _very_ misleading. I would expect it to return the highest supported
mode number instead of a bitmap of the supported modes.

I'll have a deeper look into the patches later.

Sebastian

> +		timings = onfi_async_timing_mode_to_sdr_timings(mode);
> +		if (IS_ERR(timings))
> +			return PTR_ERR(timings);
> +
> +		pxa3xx_nand_set_sdr_timing(host, timings);
> +	}
> +
> +	return 0;
> +}


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

* Re: [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
@ 2015-04-15 19:11     ` Sebastian Hesselbarth
  0 siblings, 0 replies; 57+ messages in thread
From: Sebastian Hesselbarth @ 2015-04-15 19:11 UTC (permalink / raw)
  To: Antoine Tenart, ezequiel.garcia, dwmw2, computersforpeace
  Cc: zmxu, boris.brezillon, linux-kernel, linux-mtd, jszhang,
	linux-arm-kernel

On 15.04.2015 19:24, Antoine Tenart wrote:
> Rework the pxa3xx_nand driver to allow using functions exported by the
> nand framework to detect the flash and to configure the timings.
>
> Because this driver supports some non-ONFI devices, we also keep the
> custom timing setup of this driver so these devices won't break.
>
> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
> ---
[...]

Antoine,

there are some issues with this patch.

> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index dc0edbc406bb..438770c56bd3 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c
> @@ -251,15 +251,14 @@ static struct pxa3xx_nand_timing timing[] = {
>   };
>
>   static struct pxa3xx_nand_flash builtin_flash_types[] = {
> -{ "DEFAULT FLASH",      0,   0, 2048,  8,  8,    0, &timing[0] },
> -{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, &timing[1] },
> -{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, &timing[1] },
> -{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, &timing[1] },
> -{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, &timing[2] },
> -{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, &timing[2] },
> -{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, 4096, &timing[2] },
> -{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, 4096, &timing[2] },
> -{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3] },
> +	{ 0x46ec, 16, 16, &timing[1] },
> +	{ 0xdaec,  8,  8, &timing[1] },
> +	{ 0xd7ec,  8,  8, &timing[1] },
> +	{ 0xa12c,  8,  8, &timing[2] },
> +	{ 0xb12c, 16, 16, &timing[2] },
> +	{ 0xdc2c,  8,  8, &timing[2] },
> +	{ 0xcc2c, 16, 16, &timing[2] },
> +	{ 0xba20, 16, 16, &timing[3] },

How about we get rid of the driver specific timings completely
and pick up the best onfi timing match instead? The nand_ids table
allows for a default_onfi_timing parameter even if onfi itself is
not supported.

For generic flash, i.e. no specific entry in the nand_ids table,
we either choose onfi mode 0 (most conservative) or an even slower
one.

[...]
> +static void pxa3xx_nand_set_sdr_timing(struct pxa3xx_nand_host *host,
> +				       const struct nand_sdr_timings *t)
> +{
> +	struct pxa3xx_nand_info *info = host->info_data;
> +	unsigned long nand_clk = clk_get_rate(info->clk);
> +	uint32_t ndtr0, ndtr1;
> +
> +	u32 tCH_min = DIV_ROUND_UP(t->tCH_min, 1000);
> +	u32 tCS_min = DIV_ROUND_UP(t->tCS_min, 1000);
> +	u32 tWH_min = DIV_ROUND_UP(t->tWH_min, 1000);
> +	u32 tWP_min = DIV_ROUND_UP(t->tWP_min, 1000);

While tWH_min is the minimum hold time of WE_n and tWP_min
the minimum pulse width, the sum of the two rounded values
may well exceed the minimum WE_n cycle width tWC_min.

How about we do below instead?

u32 tWH_min = DIV_ROUND_UP(t->tWH_min, 1000);
u32 tWP_min = DIV_ROUND_UP(t->tWC_min - tWH_min, 1000);
(note the missing t-> in front of tWH_min)

> +	u32 tREH_min = DIV_ROUND_UP(t->tREH_min, 1000);
> +	u32 tRP_min = DIV_ROUND_UP(t->tRP_min, 1000);

Same applies to tRH and tRP.	

> +	u32 tRST_max = DIV_ROUND_UP_ULL(t->tRST_max, 1000);
> +	u32 tWHR_min = DIV_ROUND_UP(t->tWHR_min, 1000);
> +	u32 tAR_min = DIV_ROUND_UP(t->tAR_min, 1000);
> +
> +	ndtr0 = NDTR0_tCH(ns2cycle(tCH_min, nand_clk)) |
> +		NDTR0_tCS(ns2cycle(tCS_min, nand_clk)) |
> +		NDTR0_tWH(ns2cycle(tWH_min, nand_clk)) |
> +		NDTR0_tWP(ns2cycle(tWP_min, nand_clk)) |
> +		NDTR0_tRH(ns2cycle(tREH_min, nand_clk)) |
> +		NDTR0_tRP(ns2cycle(tRP_min, nand_clk));
> +
> +	ndtr1 = NDTR1_tR(ns2cycle(tRST_max, nand_clk)) |

Well, tRST (max reset duration) is not tR (max page read
time) but much higher. I see that the onfi timings do not
directly encode tR but have extra timings for tPROG, tBERS,
tR, and tCCS.

I guess we'll have to amend sdr_timings for non-onfi devices
then.

Also, if you check the armada370 functional spec, there is
several meanings for tR register. Currently, pxa3xx nfc driver
does not use WAIT_MODE which is supported for NFCv2 (non-pxa3xx
SoCs). That will allow the controller to use R/Bn signal instead.

Anyways, timing conversion is already tricky enough, let's start
with 1:1 conversion and add additional modes later.

> +		NDTR1_tWHR(ns2cycle(tWHR_min, nand_clk)) |
> +		NDTR1_tAR(ns2cycle(tAR_min, nand_clk));
> +
> +	info->ndtr0cs0 = ndtr0;
> +	info->ndtr1cs0 = ndtr1;
> +	nand_writel(info, NDTR0CS0, ndtr0);
> +	nand_writel(info, NDTR1CS0, ndtr1);
> +}
> +
> +static int pxa3xx_nand_init_timings(struct pxa3xx_nand_host *host)
> +{
> +	const struct nand_sdr_timings *timings;
> +	struct nand_chip *chip = &host->chip;
> +	struct pxa3xx_nand_info *info = host->info_data;
> +	const struct pxa3xx_nand_flash *f = NULL;
> +	int mode, id, ntypes, i;
> +
> +	mode = onfi_get_async_timing_mode(chip);
> +	if (mode == ONFI_TIMING_MODE_UNKNOWN) {
> +		ntypes = ARRAY_SIZE(builtin_flash_types);
> +
> +		chip->cmdfunc(host->mtd, NAND_CMD_READID, 0x00, -1);
> +
> +		id = chip->read_byte(host->mtd);
> +		id |= chip->read_byte(host->mtd) << 0x8;
> +
> +		for (i = 0; i < ntypes; i++) {
> +			f = &builtin_flash_types[i];
> +
> +			if (f->chip_id == id)
> +				break;
> +		}
> +
> +		if (i == ntypes) {
> +			dev_err(&info->pdev->dev, "Error: timings not found\n");
> +			return -EINVAL;
> +		}
> +
> +		pxa3xx_nand_set_timing(host, f->timing);
> +
> +		if (f->flash_width == 16) {
> +			info->reg_ndcr |= NDCR_DWIDTH_M;
> +			chip->options |= NAND_BUSWIDTH_16;
> +		}
> +
> +		info->reg_ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
> +	} else {
> +		mode = fls(mode) - 1;
> +		if (mode < 0)
> +			mode = 0;

Is mode really a bitmap? If so, the name of onfi_get_async_timing_mode()
is _very_ misleading. I would expect it to return the highest supported
mode number instead of a bitmap of the supported modes.

I'll have a deeper look into the patches later.

Sebastian

> +		timings = onfi_async_timing_mode_to_sdr_timings(mode);
> +		if (IS_ERR(timings))
> +			return PTR_ERR(timings);
> +
> +		pxa3xx_nand_set_sdr_timing(host, timings);
> +	}
> +
> +	return 0;
> +}

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

* [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
@ 2015-04-15 19:11     ` Sebastian Hesselbarth
  0 siblings, 0 replies; 57+ messages in thread
From: Sebastian Hesselbarth @ 2015-04-15 19:11 UTC (permalink / raw)
  To: linux-arm-kernel

On 15.04.2015 19:24, Antoine Tenart wrote:
> Rework the pxa3xx_nand driver to allow using functions exported by the
> nand framework to detect the flash and to configure the timings.
>
> Because this driver supports some non-ONFI devices, we also keep the
> custom timing setup of this driver so these devices won't break.
>
> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
> ---
[...]

Antoine,

there are some issues with this patch.

> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index dc0edbc406bb..438770c56bd3 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c
> @@ -251,15 +251,14 @@ static struct pxa3xx_nand_timing timing[] = {
>   };
>
>   static struct pxa3xx_nand_flash builtin_flash_types[] = {
> -{ "DEFAULT FLASH",      0,   0, 2048,  8,  8,    0, &timing[0] },
> -{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, &timing[1] },
> -{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, &timing[1] },
> -{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, &timing[1] },
> -{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, &timing[2] },
> -{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, &timing[2] },
> -{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, 4096, &timing[2] },
> -{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, 4096, &timing[2] },
> -{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3] },
> +	{ 0x46ec, 16, 16, &timing[1] },
> +	{ 0xdaec,  8,  8, &timing[1] },
> +	{ 0xd7ec,  8,  8, &timing[1] },
> +	{ 0xa12c,  8,  8, &timing[2] },
> +	{ 0xb12c, 16, 16, &timing[2] },
> +	{ 0xdc2c,  8,  8, &timing[2] },
> +	{ 0xcc2c, 16, 16, &timing[2] },
> +	{ 0xba20, 16, 16, &timing[3] },

How about we get rid of the driver specific timings completely
and pick up the best onfi timing match instead? The nand_ids table
allows for a default_onfi_timing parameter even if onfi itself is
not supported.

For generic flash, i.e. no specific entry in the nand_ids table,
we either choose onfi mode 0 (most conservative) or an even slower
one.

[...]
> +static void pxa3xx_nand_set_sdr_timing(struct pxa3xx_nand_host *host,
> +				       const struct nand_sdr_timings *t)
> +{
> +	struct pxa3xx_nand_info *info = host->info_data;
> +	unsigned long nand_clk = clk_get_rate(info->clk);
> +	uint32_t ndtr0, ndtr1;
> +
> +	u32 tCH_min = DIV_ROUND_UP(t->tCH_min, 1000);
> +	u32 tCS_min = DIV_ROUND_UP(t->tCS_min, 1000);
> +	u32 tWH_min = DIV_ROUND_UP(t->tWH_min, 1000);
> +	u32 tWP_min = DIV_ROUND_UP(t->tWP_min, 1000);

While tWH_min is the minimum hold time of WE_n and tWP_min
the minimum pulse width, the sum of the two rounded values
may well exceed the minimum WE_n cycle width tWC_min.

How about we do below instead?

u32 tWH_min = DIV_ROUND_UP(t->tWH_min, 1000);
u32 tWP_min = DIV_ROUND_UP(t->tWC_min - tWH_min, 1000);
(note the missing t-> in front of tWH_min)

> +	u32 tREH_min = DIV_ROUND_UP(t->tREH_min, 1000);
> +	u32 tRP_min = DIV_ROUND_UP(t->tRP_min, 1000);

Same applies to tRH and tRP.	

> +	u32 tRST_max = DIV_ROUND_UP_ULL(t->tRST_max, 1000);
> +	u32 tWHR_min = DIV_ROUND_UP(t->tWHR_min, 1000);
> +	u32 tAR_min = DIV_ROUND_UP(t->tAR_min, 1000);
> +
> +	ndtr0 = NDTR0_tCH(ns2cycle(tCH_min, nand_clk)) |
> +		NDTR0_tCS(ns2cycle(tCS_min, nand_clk)) |
> +		NDTR0_tWH(ns2cycle(tWH_min, nand_clk)) |
> +		NDTR0_tWP(ns2cycle(tWP_min, nand_clk)) |
> +		NDTR0_tRH(ns2cycle(tREH_min, nand_clk)) |
> +		NDTR0_tRP(ns2cycle(tRP_min, nand_clk));
> +
> +	ndtr1 = NDTR1_tR(ns2cycle(tRST_max, nand_clk)) |

Well, tRST (max reset duration) is not tR (max page read
time) but much higher. I see that the onfi timings do not
directly encode tR but have extra timings for tPROG, tBERS,
tR, and tCCS.

I guess we'll have to amend sdr_timings for non-onfi devices
then.

Also, if you check the armada370 functional spec, there is
several meanings for tR register. Currently, pxa3xx nfc driver
does not use WAIT_MODE which is supported for NFCv2 (non-pxa3xx
SoCs). That will allow the controller to use R/Bn signal instead.

Anyways, timing conversion is already tricky enough, let's start
with 1:1 conversion and add additional modes later.

> +		NDTR1_tWHR(ns2cycle(tWHR_min, nand_clk)) |
> +		NDTR1_tAR(ns2cycle(tAR_min, nand_clk));
> +
> +	info->ndtr0cs0 = ndtr0;
> +	info->ndtr1cs0 = ndtr1;
> +	nand_writel(info, NDTR0CS0, ndtr0);
> +	nand_writel(info, NDTR1CS0, ndtr1);
> +}
> +
> +static int pxa3xx_nand_init_timings(struct pxa3xx_nand_host *host)
> +{
> +	const struct nand_sdr_timings *timings;
> +	struct nand_chip *chip = &host->chip;
> +	struct pxa3xx_nand_info *info = host->info_data;
> +	const struct pxa3xx_nand_flash *f = NULL;
> +	int mode, id, ntypes, i;
> +
> +	mode = onfi_get_async_timing_mode(chip);
> +	if (mode == ONFI_TIMING_MODE_UNKNOWN) {
> +		ntypes = ARRAY_SIZE(builtin_flash_types);
> +
> +		chip->cmdfunc(host->mtd, NAND_CMD_READID, 0x00, -1);
> +
> +		id = chip->read_byte(host->mtd);
> +		id |= chip->read_byte(host->mtd) << 0x8;
> +
> +		for (i = 0; i < ntypes; i++) {
> +			f = &builtin_flash_types[i];
> +
> +			if (f->chip_id == id)
> +				break;
> +		}
> +
> +		if (i == ntypes) {
> +			dev_err(&info->pdev->dev, "Error: timings not found\n");
> +			return -EINVAL;
> +		}
> +
> +		pxa3xx_nand_set_timing(host, f->timing);
> +
> +		if (f->flash_width == 16) {
> +			info->reg_ndcr |= NDCR_DWIDTH_M;
> +			chip->options |= NAND_BUSWIDTH_16;
> +		}
> +
> +		info->reg_ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
> +	} else {
> +		mode = fls(mode) - 1;
> +		if (mode < 0)
> +			mode = 0;

Is mode really a bitmap? If so, the name of onfi_get_async_timing_mode()
is _very_ misleading. I would expect it to return the highest supported
mode number instead of a bitmap of the supported modes.

I'll have a deeper look into the patches later.

Sebastian

> +		timings = onfi_async_timing_mode_to_sdr_timings(mode);
> +		if (IS_ERR(timings))
> +			return PTR_ERR(timings);
> +
> +		pxa3xx_nand_set_sdr_timing(host, timings);
> +	}
> +
> +	return 0;
> +}

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

* Re: [PATCH v4 05/10] mtd: nand: add Samsung K9GBG08U0A-M to nand_ids table
  2015-04-15 17:24   ` Antoine Tenart
  (?)
@ 2015-04-15 21:38     ` Sebastian Hesselbarth
  -1 siblings, 0 replies; 57+ messages in thread
From: Sebastian Hesselbarth @ 2015-04-15 21:38 UTC (permalink / raw)
  To: Antoine Tenart, ezequiel.garcia, dwmw2, computersforpeace
  Cc: boris.brezillon, zmxu, jszhang, linux-arm-kernel, linux-mtd,
	linux-kernel

On 15.04.2015 19:24, Antoine Tenart wrote:
> Add the full description of the Samsung K9GBG08U0A-M nand chip in the
> nand_ids table.
>
> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
> ---
>   drivers/mtd/nand/nand_ids.c | 4 ++++
>   1 file changed, 4 insertions(+)
>
> diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
> index dd620c19c619..500c33e1db06 100644
> --- a/drivers/mtd/nand/nand_ids.c
> +++ b/drivers/mtd/nand/nand_ids.c
> @@ -50,6 +50,10 @@ struct nand_flash_dev nand_flash_ids[] = {
>   		{ .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} },
>   		  SZ_8K, SZ_8K, SZ_2M, 0, 6, 640, NAND_ECC_INFO(40, SZ_1K),
>   		  4 },
> +	{"NAND 4GiB 3,3V 8-bit",
> +		{ .id = {0xec, 0xd7, 0x94, 0x76, 0x64, 0x43}, },
> +		  8192, 4096, SZ_1M, LP_OPTIONS, 0, 0, NAND_ECC_INFO(40, SZ_1K),
> +		  4 },

According to the datasheet p.50, ECC_INFO() could also be parsed from
byte 5 bits [6:4] of EXT_ID.

I tried to catch up with the onfi_timing_mode_default discussion but
failed. Can someone please put me in the picture if we are going to add
full_id chips just because of the equivalent onfi timing mode? Or is it
safe to assume that all 0xd7 chips are mode 4 compatible?

Sebastian

>
>   	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),
>   	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),
>


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

* Re: [PATCH v4 05/10] mtd: nand: add Samsung K9GBG08U0A-M to nand_ids table
@ 2015-04-15 21:38     ` Sebastian Hesselbarth
  0 siblings, 0 replies; 57+ messages in thread
From: Sebastian Hesselbarth @ 2015-04-15 21:38 UTC (permalink / raw)
  To: Antoine Tenart, ezequiel.garcia, dwmw2, computersforpeace
  Cc: zmxu, boris.brezillon, linux-kernel, linux-mtd, jszhang,
	linux-arm-kernel

On 15.04.2015 19:24, Antoine Tenart wrote:
> Add the full description of the Samsung K9GBG08U0A-M nand chip in the
> nand_ids table.
>
> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
> ---
>   drivers/mtd/nand/nand_ids.c | 4 ++++
>   1 file changed, 4 insertions(+)
>
> diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
> index dd620c19c619..500c33e1db06 100644
> --- a/drivers/mtd/nand/nand_ids.c
> +++ b/drivers/mtd/nand/nand_ids.c
> @@ -50,6 +50,10 @@ struct nand_flash_dev nand_flash_ids[] = {
>   		{ .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} },
>   		  SZ_8K, SZ_8K, SZ_2M, 0, 6, 640, NAND_ECC_INFO(40, SZ_1K),
>   		  4 },
> +	{"NAND 4GiB 3,3V 8-bit",
> +		{ .id = {0xec, 0xd7, 0x94, 0x76, 0x64, 0x43}, },
> +		  8192, 4096, SZ_1M, LP_OPTIONS, 0, 0, NAND_ECC_INFO(40, SZ_1K),
> +		  4 },

According to the datasheet p.50, ECC_INFO() could also be parsed from
byte 5 bits [6:4] of EXT_ID.

I tried to catch up with the onfi_timing_mode_default discussion but
failed. Can someone please put me in the picture if we are going to add
full_id chips just because of the equivalent onfi timing mode? Or is it
safe to assume that all 0xd7 chips are mode 4 compatible?

Sebastian

>
>   	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),
>   	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),
>

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

* [PATCH v4 05/10] mtd: nand: add Samsung K9GBG08U0A-M to nand_ids table
@ 2015-04-15 21:38     ` Sebastian Hesselbarth
  0 siblings, 0 replies; 57+ messages in thread
From: Sebastian Hesselbarth @ 2015-04-15 21:38 UTC (permalink / raw)
  To: linux-arm-kernel

On 15.04.2015 19:24, Antoine Tenart wrote:
> Add the full description of the Samsung K9GBG08U0A-M nand chip in the
> nand_ids table.
>
> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
> ---
>   drivers/mtd/nand/nand_ids.c | 4 ++++
>   1 file changed, 4 insertions(+)
>
> diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
> index dd620c19c619..500c33e1db06 100644
> --- a/drivers/mtd/nand/nand_ids.c
> +++ b/drivers/mtd/nand/nand_ids.c
> @@ -50,6 +50,10 @@ struct nand_flash_dev nand_flash_ids[] = {
>   		{ .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} },
>   		  SZ_8K, SZ_8K, SZ_2M, 0, 6, 640, NAND_ECC_INFO(40, SZ_1K),
>   		  4 },
> +	{"NAND 4GiB 3,3V 8-bit",
> +		{ .id = {0xec, 0xd7, 0x94, 0x76, 0x64, 0x43}, },
> +		  8192, 4096, SZ_1M, LP_OPTIONS, 0, 0, NAND_ECC_INFO(40, SZ_1K),
> +		  4 },

According to the datasheet p.50, ECC_INFO() could also be parsed from
byte 5 bits [6:4] of EXT_ID.

I tried to catch up with the onfi_timing_mode_default discussion but
failed. Can someone please put me in the picture if we are going to add
full_id chips just because of the equivalent onfi timing mode? Or is it
safe to assume that all 0xd7 chips are mode 4 compatible?

Sebastian

>
>   	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),
>   	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),
>

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

* Re: [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
  2015-04-15 19:11     ` Sebastian Hesselbarth
  (?)
@ 2015-04-16 13:10       ` Ezequiel Garcia
  -1 siblings, 0 replies; 57+ messages in thread
From: Ezequiel Garcia @ 2015-04-16 13:10 UTC (permalink / raw)
  To: Sebastian Hesselbarth, Antoine Tenart, dwmw2, computersforpeace
  Cc: boris.brezillon, zmxu, jszhang, linux-arm-kernel, linux-mtd,
	linux-kernel, Robert Jarzmik

On 04/15/2015 04:11 PM, Sebastian Hesselbarth wrote:
> On 15.04.2015 19:24, Antoine Tenart wrote:
>> Rework the pxa3xx_nand driver to allow using functions exported by the
>> nand framework to detect the flash and to configure the timings.
>>
>> Because this driver supports some non-ONFI devices, we also keep the
>> custom timing setup of this driver so these devices won't break.
>>
>> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
>> ---
> [...]
> 
> Antoine,
> 
> there are some issues with this patch.
> 
>> diff --git a/drivers/mtd/nand/pxa3xx_nand.c
>> b/drivers/mtd/nand/pxa3xx_nand.c
>> index dc0edbc406bb..438770c56bd3 100644
>> --- a/drivers/mtd/nand/pxa3xx_nand.c
>> +++ b/drivers/mtd/nand/pxa3xx_nand.c
>> @@ -251,15 +251,14 @@ static struct pxa3xx_nand_timing timing[] = {
>>   };
>>
>>   static struct pxa3xx_nand_flash builtin_flash_types[] = {
>> -{ "DEFAULT FLASH",      0,   0, 2048,  8,  8,    0, &timing[0] },
>> -{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, &timing[1] },
>> -{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, &timing[1] },
>> -{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, &timing[1] },
>> -{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, &timing[2] },
>> -{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, &timing[2] },
>> -{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, 4096, &timing[2] },
>> -{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, 4096, &timing[2] },
>> -{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3] },
>> +    { 0x46ec, 16, 16, &timing[1] },
>> +    { 0xdaec,  8,  8, &timing[1] },
>> +    { 0xd7ec,  8,  8, &timing[1] },
>> +    { 0xa12c,  8,  8, &timing[2] },
>> +    { 0xb12c, 16, 16, &timing[2] },
>> +    { 0xdc2c,  8,  8, &timing[2] },
>> +    { 0xcc2c, 16, 16, &timing[2] },
>> +    { 0xba20, 16, 16, &timing[3] },
> 
> How about we get rid of the driver specific timings completely
> and pick up the best onfi timing match instead? The nand_ids table
> allows for a default_onfi_timing parameter even if onfi itself is
> not supported.
> 
> For generic flash, i.e. no specific entry in the nand_ids table,
> we either choose onfi mode 0 (most conservative) or an even slower
> one.
> 

I think Robert mentioned [1] that using "ONFI default timings" on
non-ONFI devices didn't work for him.

[1] https://lkml.org/lkml/2015/3/8/124
-- 
Ezequiel García, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

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

* Re: [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
@ 2015-04-16 13:10       ` Ezequiel Garcia
  0 siblings, 0 replies; 57+ messages in thread
From: Ezequiel Garcia @ 2015-04-16 13:10 UTC (permalink / raw)
  To: Sebastian Hesselbarth, Antoine Tenart, dwmw2, computersforpeace
  Cc: zmxu, boris.brezillon, linux-kernel, linux-mtd, jszhang,
	Robert Jarzmik, linux-arm-kernel

On 04/15/2015 04:11 PM, Sebastian Hesselbarth wrote:
> On 15.04.2015 19:24, Antoine Tenart wrote:
>> Rework the pxa3xx_nand driver to allow using functions exported by the
>> nand framework to detect the flash and to configure the timings.
>>
>> Because this driver supports some non-ONFI devices, we also keep the
>> custom timing setup of this driver so these devices won't break.
>>
>> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
>> ---
> [...]
> 
> Antoine,
> 
> there are some issues with this patch.
> 
>> diff --git a/drivers/mtd/nand/pxa3xx_nand.c
>> b/drivers/mtd/nand/pxa3xx_nand.c
>> index dc0edbc406bb..438770c56bd3 100644
>> --- a/drivers/mtd/nand/pxa3xx_nand.c
>> +++ b/drivers/mtd/nand/pxa3xx_nand.c
>> @@ -251,15 +251,14 @@ static struct pxa3xx_nand_timing timing[] = {
>>   };
>>
>>   static struct pxa3xx_nand_flash builtin_flash_types[] = {
>> -{ "DEFAULT FLASH",      0,   0, 2048,  8,  8,    0, &timing[0] },
>> -{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, &timing[1] },
>> -{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, &timing[1] },
>> -{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, &timing[1] },
>> -{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, &timing[2] },
>> -{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, &timing[2] },
>> -{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, 4096, &timing[2] },
>> -{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, 4096, &timing[2] },
>> -{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3] },
>> +    { 0x46ec, 16, 16, &timing[1] },
>> +    { 0xdaec,  8,  8, &timing[1] },
>> +    { 0xd7ec,  8,  8, &timing[1] },
>> +    { 0xa12c,  8,  8, &timing[2] },
>> +    { 0xb12c, 16, 16, &timing[2] },
>> +    { 0xdc2c,  8,  8, &timing[2] },
>> +    { 0xcc2c, 16, 16, &timing[2] },
>> +    { 0xba20, 16, 16, &timing[3] },
> 
> How about we get rid of the driver specific timings completely
> and pick up the best onfi timing match instead? The nand_ids table
> allows for a default_onfi_timing parameter even if onfi itself is
> not supported.
> 
> For generic flash, i.e. no specific entry in the nand_ids table,
> we either choose onfi mode 0 (most conservative) or an even slower
> one.
> 

I think Robert mentioned [1] that using "ONFI default timings" on
non-ONFI devices didn't work for him.

[1] https://lkml.org/lkml/2015/3/8/124
-- 
Ezequiel García, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

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

* [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
@ 2015-04-16 13:10       ` Ezequiel Garcia
  0 siblings, 0 replies; 57+ messages in thread
From: Ezequiel Garcia @ 2015-04-16 13:10 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/15/2015 04:11 PM, Sebastian Hesselbarth wrote:
> On 15.04.2015 19:24, Antoine Tenart wrote:
>> Rework the pxa3xx_nand driver to allow using functions exported by the
>> nand framework to detect the flash and to configure the timings.
>>
>> Because this driver supports some non-ONFI devices, we also keep the
>> custom timing setup of this driver so these devices won't break.
>>
>> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
>> ---
> [...]
> 
> Antoine,
> 
> there are some issues with this patch.
> 
>> diff --git a/drivers/mtd/nand/pxa3xx_nand.c
>> b/drivers/mtd/nand/pxa3xx_nand.c
>> index dc0edbc406bb..438770c56bd3 100644
>> --- a/drivers/mtd/nand/pxa3xx_nand.c
>> +++ b/drivers/mtd/nand/pxa3xx_nand.c
>> @@ -251,15 +251,14 @@ static struct pxa3xx_nand_timing timing[] = {
>>   };
>>
>>   static struct pxa3xx_nand_flash builtin_flash_types[] = {
>> -{ "DEFAULT FLASH",      0,   0, 2048,  8,  8,    0, &timing[0] },
>> -{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, &timing[1] },
>> -{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, &timing[1] },
>> -{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, &timing[1] },
>> -{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, &timing[2] },
>> -{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, &timing[2] },
>> -{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, 4096, &timing[2] },
>> -{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, 4096, &timing[2] },
>> -{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3] },
>> +    { 0x46ec, 16, 16, &timing[1] },
>> +    { 0xdaec,  8,  8, &timing[1] },
>> +    { 0xd7ec,  8,  8, &timing[1] },
>> +    { 0xa12c,  8,  8, &timing[2] },
>> +    { 0xb12c, 16, 16, &timing[2] },
>> +    { 0xdc2c,  8,  8, &timing[2] },
>> +    { 0xcc2c, 16, 16, &timing[2] },
>> +    { 0xba20, 16, 16, &timing[3] },
> 
> How about we get rid of the driver specific timings completely
> and pick up the best onfi timing match instead? The nand_ids table
> allows for a default_onfi_timing parameter even if onfi itself is
> not supported.
> 
> For generic flash, i.e. no specific entry in the nand_ids table,
> we either choose onfi mode 0 (most conservative) or an even slower
> one.
> 

I think Robert mentioned [1] that using "ONFI default timings" on
non-ONFI devices didn't work for him.

[1] https://lkml.org/lkml/2015/3/8/124
-- 
Ezequiel Garc?a, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

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

* Re: [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
  2015-04-16 13:10       ` Ezequiel Garcia
  (?)
@ 2015-04-16 13:41         ` Sebastian Hesselbarth
  -1 siblings, 0 replies; 57+ messages in thread
From: Sebastian Hesselbarth @ 2015-04-16 13:41 UTC (permalink / raw)
  To: Ezequiel Garcia, Antoine Tenart, dwmw2, computersforpeace
  Cc: boris.brezillon, zmxu, jszhang, linux-arm-kernel, linux-mtd,
	linux-kernel, Robert Jarzmik

On 04/16/2015 03:10 PM, Ezequiel Garcia wrote:
> On 04/15/2015 04:11 PM, Sebastian Hesselbarth wrote:
>> On 15.04.2015 19:24, Antoine Tenart wrote:
>>> Rework the pxa3xx_nand driver to allow using functions exported by the
>>> nand framework to detect the flash and to configure the timings.
>>>
>>> Because this driver supports some non-ONFI devices, we also keep the
>>> custom timing setup of this driver so these devices won't break.
>>>
>>> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
>>> ---
>> [...]
>> How about we get rid of the driver specific timings completely
>> and pick up the best onfi timing match instead? The nand_ids table
>> allows for a default_onfi_timing parameter even if onfi itself is
>> not supported.
>>
>> For generic flash, i.e. no specific entry in the nand_ids table,
>> we either choose onfi mode 0 (most conservative) or an even slower
>> one.
>>
>
> I think Robert mentioned [1] that using "ONFI default timings" on
> non-ONFI devices didn't work for him.
>
> [1] https://lkml.org/lkml/2015/3/8/124

Ok, I see. But there is still the option to pass board specific
timings with driver's platform_data. We could use

(a) pdata timings if passed
(b) onfi timings if available
(c) equivalent onfi timings if set
(d) conservative equivalent onfi timings otherwise

All we need is a function to convert sdr_timings to sane driver
timings. And we really need to split this patch into tiny pieces
otherwise it is not reviewable - or at least I need a full overview
about the driver first.

Also, as soon as Robert moves pxa3xx boards fully to DT, we'll loose
the pdata timings option above. *sigh*

Thoughts?

Sebastian

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

* Re: [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
@ 2015-04-16 13:41         ` Sebastian Hesselbarth
  0 siblings, 0 replies; 57+ messages in thread
From: Sebastian Hesselbarth @ 2015-04-16 13:41 UTC (permalink / raw)
  To: Ezequiel Garcia, Antoine Tenart, dwmw2, computersforpeace
  Cc: zmxu, boris.brezillon, linux-kernel, linux-mtd, jszhang,
	Robert Jarzmik, linux-arm-kernel

On 04/16/2015 03:10 PM, Ezequiel Garcia wrote:
> On 04/15/2015 04:11 PM, Sebastian Hesselbarth wrote:
>> On 15.04.2015 19:24, Antoine Tenart wrote:
>>> Rework the pxa3xx_nand driver to allow using functions exported by the
>>> nand framework to detect the flash and to configure the timings.
>>>
>>> Because this driver supports some non-ONFI devices, we also keep the
>>> custom timing setup of this driver so these devices won't break.
>>>
>>> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
>>> ---
>> [...]
>> How about we get rid of the driver specific timings completely
>> and pick up the best onfi timing match instead? The nand_ids table
>> allows for a default_onfi_timing parameter even if onfi itself is
>> not supported.
>>
>> For generic flash, i.e. no specific entry in the nand_ids table,
>> we either choose onfi mode 0 (most conservative) or an even slower
>> one.
>>
>
> I think Robert mentioned [1] that using "ONFI default timings" on
> non-ONFI devices didn't work for him.
>
> [1] https://lkml.org/lkml/2015/3/8/124

Ok, I see. But there is still the option to pass board specific
timings with driver's platform_data. We could use

(a) pdata timings if passed
(b) onfi timings if available
(c) equivalent onfi timings if set
(d) conservative equivalent onfi timings otherwise

All we need is a function to convert sdr_timings to sane driver
timings. And we really need to split this patch into tiny pieces
otherwise it is not reviewable - or at least I need a full overview
about the driver first.

Also, as soon as Robert moves pxa3xx boards fully to DT, we'll loose
the pdata timings option above. *sigh*

Thoughts?

Sebastian

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

* [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
@ 2015-04-16 13:41         ` Sebastian Hesselbarth
  0 siblings, 0 replies; 57+ messages in thread
From: Sebastian Hesselbarth @ 2015-04-16 13:41 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/16/2015 03:10 PM, Ezequiel Garcia wrote:
> On 04/15/2015 04:11 PM, Sebastian Hesselbarth wrote:
>> On 15.04.2015 19:24, Antoine Tenart wrote:
>>> Rework the pxa3xx_nand driver to allow using functions exported by the
>>> nand framework to detect the flash and to configure the timings.
>>>
>>> Because this driver supports some non-ONFI devices, we also keep the
>>> custom timing setup of this driver so these devices won't break.
>>>
>>> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
>>> ---
>> [...]
>> How about we get rid of the driver specific timings completely
>> and pick up the best onfi timing match instead? The nand_ids table
>> allows for a default_onfi_timing parameter even if onfi itself is
>> not supported.
>>
>> For generic flash, i.e. no specific entry in the nand_ids table,
>> we either choose onfi mode 0 (most conservative) or an even slower
>> one.
>>
>
> I think Robert mentioned [1] that using "ONFI default timings" on
> non-ONFI devices didn't work for him.
>
> [1] https://lkml.org/lkml/2015/3/8/124

Ok, I see. But there is still the option to pass board specific
timings with driver's platform_data. We could use

(a) pdata timings if passed
(b) onfi timings if available
(c) equivalent onfi timings if set
(d) conservative equivalent onfi timings otherwise

All we need is a function to convert sdr_timings to sane driver
timings. And we really need to split this patch into tiny pieces
otherwise it is not reviewable - or at least I need a full overview
about the driver first.

Also, as soon as Robert moves pxa3xx boards fully to DT, we'll loose
the pdata timings option above. *sigh*

Thoughts?

Sebastian

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

* Re: [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
  2015-04-16 13:41         ` Sebastian Hesselbarth
  (?)
@ 2015-04-16 16:59           ` Ezequiel Garcia
  -1 siblings, 0 replies; 57+ messages in thread
From: Ezequiel Garcia @ 2015-04-16 16:59 UTC (permalink / raw)
  To: Sebastian Hesselbarth, Antoine Tenart, dwmw2, computersforpeace
  Cc: boris.brezillon, zmxu, jszhang, linux-arm-kernel, linux-mtd,
	linux-kernel, Robert Jarzmik

On 04/16/2015 10:41 AM, Sebastian Hesselbarth wrote:
> On 04/16/2015 03:10 PM, Ezequiel Garcia wrote:
>> On 04/15/2015 04:11 PM, Sebastian Hesselbarth wrote:
>>> On 15.04.2015 19:24, Antoine Tenart wrote:
>>>> Rework the pxa3xx_nand driver to allow using functions exported by the
>>>> nand framework to detect the flash and to configure the timings.
>>>>
>>>> Because this driver supports some non-ONFI devices, we also keep the
>>>> custom timing setup of this driver so these devices won't break.
>>>>
>>>> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
>>>> ---
>>> [...]
>>> How about we get rid of the driver specific timings completely
>>> and pick up the best onfi timing match instead? The nand_ids table
>>> allows for a default_onfi_timing parameter even if onfi itself is
>>> not supported.
>>>
>>> For generic flash, i.e. no specific entry in the nand_ids table,
>>> we either choose onfi mode 0 (most conservative) or an even slower
>>> one.
>>>
>>
>> I think Robert mentioned [1] that using "ONFI default timings" on
>> non-ONFI devices didn't work for him.
>>
>> [1] https://lkml.org/lkml/2015/3/8/124
> 
> Ok, I see. But there is still the option to pass board specific
> timings with driver's platform_data. We could use
> 
> (a) pdata timings if passed
> (b) onfi timings if available
> (c) equivalent onfi timings if set
> (d) conservative equivalent onfi timings otherwise
> 

Right, using platform_data sounds like a nice compromise solution.
I'm willing to accept this series with the current timing rework; and
leave the timing setup in-driver replacement for followup patches.

> All we need is a function to convert sdr_timings to sane driver
> timings. And we really need to split this patch into tiny pieces
> otherwise it is not reviewable - or at least I need a full overview
> about the driver first.
> 

I think that's a bit of a different issue. This patch seems to be doing
two things: it removes the in-driver flash detection *and* reworks
timing setup.

How about we split this in two or even three patches? Along these lines:
1) introduce timing helpers, 2) rework timing setup, 3) remove in-driver
flash detection. Not sure how feasible it is.

> Also, as soon as Robert moves pxa3xx boards fully to DT, we'll loose
> the pdata timings option above. *sigh*
> 

Well, such move would include proper timing DT properties for non-ONFI
devices.
-- 
Ezequiel García, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

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

* Re: [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
@ 2015-04-16 16:59           ` Ezequiel Garcia
  0 siblings, 0 replies; 57+ messages in thread
From: Ezequiel Garcia @ 2015-04-16 16:59 UTC (permalink / raw)
  To: Sebastian Hesselbarth, Antoine Tenart, dwmw2, computersforpeace
  Cc: zmxu, boris.brezillon, linux-kernel, linux-mtd, jszhang,
	Robert Jarzmik, linux-arm-kernel

On 04/16/2015 10:41 AM, Sebastian Hesselbarth wrote:
> On 04/16/2015 03:10 PM, Ezequiel Garcia wrote:
>> On 04/15/2015 04:11 PM, Sebastian Hesselbarth wrote:
>>> On 15.04.2015 19:24, Antoine Tenart wrote:
>>>> Rework the pxa3xx_nand driver to allow using functions exported by the
>>>> nand framework to detect the flash and to configure the timings.
>>>>
>>>> Because this driver supports some non-ONFI devices, we also keep the
>>>> custom timing setup of this driver so these devices won't break.
>>>>
>>>> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
>>>> ---
>>> [...]
>>> How about we get rid of the driver specific timings completely
>>> and pick up the best onfi timing match instead? The nand_ids table
>>> allows for a default_onfi_timing parameter even if onfi itself is
>>> not supported.
>>>
>>> For generic flash, i.e. no specific entry in the nand_ids table,
>>> we either choose onfi mode 0 (most conservative) or an even slower
>>> one.
>>>
>>
>> I think Robert mentioned [1] that using "ONFI default timings" on
>> non-ONFI devices didn't work for him.
>>
>> [1] https://lkml.org/lkml/2015/3/8/124
> 
> Ok, I see. But there is still the option to pass board specific
> timings with driver's platform_data. We could use
> 
> (a) pdata timings if passed
> (b) onfi timings if available
> (c) equivalent onfi timings if set
> (d) conservative equivalent onfi timings otherwise
> 

Right, using platform_data sounds like a nice compromise solution.
I'm willing to accept this series with the current timing rework; and
leave the timing setup in-driver replacement for followup patches.

> All we need is a function to convert sdr_timings to sane driver
> timings. And we really need to split this patch into tiny pieces
> otherwise it is not reviewable - or at least I need a full overview
> about the driver first.
> 

I think that's a bit of a different issue. This patch seems to be doing
two things: it removes the in-driver flash detection *and* reworks
timing setup.

How about we split this in two or even three patches? Along these lines:
1) introduce timing helpers, 2) rework timing setup, 3) remove in-driver
flash detection. Not sure how feasible it is.

> Also, as soon as Robert moves pxa3xx boards fully to DT, we'll loose
> the pdata timings option above. *sigh*
> 

Well, such move would include proper timing DT properties for non-ONFI
devices.
-- 
Ezequiel García, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

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

* [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
@ 2015-04-16 16:59           ` Ezequiel Garcia
  0 siblings, 0 replies; 57+ messages in thread
From: Ezequiel Garcia @ 2015-04-16 16:59 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/16/2015 10:41 AM, Sebastian Hesselbarth wrote:
> On 04/16/2015 03:10 PM, Ezequiel Garcia wrote:
>> On 04/15/2015 04:11 PM, Sebastian Hesselbarth wrote:
>>> On 15.04.2015 19:24, Antoine Tenart wrote:
>>>> Rework the pxa3xx_nand driver to allow using functions exported by the
>>>> nand framework to detect the flash and to configure the timings.
>>>>
>>>> Because this driver supports some non-ONFI devices, we also keep the
>>>> custom timing setup of this driver so these devices won't break.
>>>>
>>>> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
>>>> ---
>>> [...]
>>> How about we get rid of the driver specific timings completely
>>> and pick up the best onfi timing match instead? The nand_ids table
>>> allows for a default_onfi_timing parameter even if onfi itself is
>>> not supported.
>>>
>>> For generic flash, i.e. no specific entry in the nand_ids table,
>>> we either choose onfi mode 0 (most conservative) or an even slower
>>> one.
>>>
>>
>> I think Robert mentioned [1] that using "ONFI default timings" on
>> non-ONFI devices didn't work for him.
>>
>> [1] https://lkml.org/lkml/2015/3/8/124
> 
> Ok, I see. But there is still the option to pass board specific
> timings with driver's platform_data. We could use
> 
> (a) pdata timings if passed
> (b) onfi timings if available
> (c) equivalent onfi timings if set
> (d) conservative equivalent onfi timings otherwise
> 

Right, using platform_data sounds like a nice compromise solution.
I'm willing to accept this series with the current timing rework; and
leave the timing setup in-driver replacement for followup patches.

> All we need is a function to convert sdr_timings to sane driver
> timings. And we really need to split this patch into tiny pieces
> otherwise it is not reviewable - or at least I need a full overview
> about the driver first.
> 

I think that's a bit of a different issue. This patch seems to be doing
two things: it removes the in-driver flash detection *and* reworks
timing setup.

How about we split this in two or even three patches? Along these lines:
1) introduce timing helpers, 2) rework timing setup, 3) remove in-driver
flash detection. Not sure how feasible it is.

> Also, as soon as Robert moves pxa3xx boards fully to DT, we'll loose
> the pdata timings option above. *sigh*
> 

Well, such move would include proper timing DT properties for non-ONFI
devices.
-- 
Ezequiel Garc?a, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

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

* Re: [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
  2015-04-16 16:59           ` Ezequiel Garcia
  (?)
@ 2015-04-17 19:52             ` Robert Jarzmik
  -1 siblings, 0 replies; 57+ messages in thread
From: Robert Jarzmik @ 2015-04-17 19:52 UTC (permalink / raw)
  To: Ezequiel Garcia
  Cc: Sebastian Hesselbarth, Antoine Tenart, dwmw2, computersforpeace,
	boris.brezillon, zmxu, jszhang, linux-arm-kernel, linux-mtd,
	linux-kernel

Ezequiel Garcia <ezequiel.garcia@free-electrons.com> writes:

>> Also, as soon as Robert moves pxa3xx boards fully to DT, we'll loose
>> the pdata timings option above. *sigh*
>> 
> Well, such move would include proper timing DT properties for non-ONFI
> devices.
I will move several boards to DT, including several pxa3x boards, but not _all_
the boards.

For reference, I said in [1] this :
> Actually, this deserves another discussion alltogether. My plan was not to
> convert all pxa board files to dt support, but all internal SoC IPs drivers +
> mach/plat support.
> 
> Or put another way at the end :
>  - there will be at least one pxa25x board which is fully DT converted
>  - there will be at least one pxa27x board which is fully DT converted
>  - there will be at least one pxa3xx board which is fully DT converted
> 
>  - there will be at least one pxa25x board which is not DT converted
>  - there will be at least one pxa27x board which is not DT converted
>  - there will be at least one pxa3xx board which is not DT converted
> 
> I want to keep the support for both legacy platform_data and DT for pxa
> architecture. The idea I had was that only fully DT converted machines will
> benefit from multiplatform support.

And as you said Ezequiel, the problem will arise regardless of being DT or not,
it's a lack of conformance of the zylonite board's nand amongst others.

So the timings will have to survive somewhere, whichever place is seen fit.

Cheers.

-- 
Robert

[1] http://lists.openwall.net/linux-kernel/2015/03/24/101

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

* Re: [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
@ 2015-04-17 19:52             ` Robert Jarzmik
  0 siblings, 0 replies; 57+ messages in thread
From: Robert Jarzmik @ 2015-04-17 19:52 UTC (permalink / raw)
  To: Ezequiel Garcia
  Cc: zmxu, boris.brezillon, Antoine Tenart, linux-kernel, linux-mtd,
	jszhang, computersforpeace, dwmw2, linux-arm-kernel,
	Sebastian Hesselbarth

Ezequiel Garcia <ezequiel.garcia@free-electrons.com> writes:

>> Also, as soon as Robert moves pxa3xx boards fully to DT, we'll loose
>> the pdata timings option above. *sigh*
>> 
> Well, such move would include proper timing DT properties for non-ONFI
> devices.
I will move several boards to DT, including several pxa3x boards, but not _all_
the boards.

For reference, I said in [1] this :
> Actually, this deserves another discussion alltogether. My plan was not to
> convert all pxa board files to dt support, but all internal SoC IPs drivers +
> mach/plat support.
> 
> Or put another way at the end :
>  - there will be at least one pxa25x board which is fully DT converted
>  - there will be at least one pxa27x board which is fully DT converted
>  - there will be at least one pxa3xx board which is fully DT converted
> 
>  - there will be at least one pxa25x board which is not DT converted
>  - there will be at least one pxa27x board which is not DT converted
>  - there will be at least one pxa3xx board which is not DT converted
> 
> I want to keep the support for both legacy platform_data and DT for pxa
> architecture. The idea I had was that only fully DT converted machines will
> benefit from multiplatform support.

And as you said Ezequiel, the problem will arise regardless of being DT or not,
it's a lack of conformance of the zylonite board's nand amongst others.

So the timings will have to survive somewhere, whichever place is seen fit.

Cheers.

-- 
Robert

[1] http://lists.openwall.net/linux-kernel/2015/03/24/101

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

* [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
@ 2015-04-17 19:52             ` Robert Jarzmik
  0 siblings, 0 replies; 57+ messages in thread
From: Robert Jarzmik @ 2015-04-17 19:52 UTC (permalink / raw)
  To: linux-arm-kernel

Ezequiel Garcia <ezequiel.garcia@free-electrons.com> writes:

>> Also, as soon as Robert moves pxa3xx boards fully to DT, we'll loose
>> the pdata timings option above. *sigh*
>> 
> Well, such move would include proper timing DT properties for non-ONFI
> devices.
I will move several boards to DT, including several pxa3x boards, but not _all_
the boards.

For reference, I said in [1] this :
> Actually, this deserves another discussion alltogether. My plan was not to
> convert all pxa board files to dt support, but all internal SoC IPs drivers +
> mach/plat support.
> 
> Or put another way at the end :
>  - there will be at least one pxa25x board which is fully DT converted
>  - there will be at least one pxa27x board which is fully DT converted
>  - there will be at least one pxa3xx board which is fully DT converted
> 
>  - there will be at least one pxa25x board which is not DT converted
>  - there will be at least one pxa27x board which is not DT converted
>  - there will be at least one pxa3xx board which is not DT converted
> 
> I want to keep the support for both legacy platform_data and DT for pxa
> architecture. The idea I had was that only fully DT converted machines will
> benefit from multiplatform support.

And as you said Ezequiel, the problem will arise regardless of being DT or not,
it's a lack of conformance of the zylonite board's nand amongst others.

So the timings will have to survive somewhere, whichever place is seen fit.

Cheers.

-- 
Robert

[1] http://lists.openwall.net/linux-kernel/2015/03/24/101

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

* Re: [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
  2015-04-16 16:59           ` Ezequiel Garcia
  (?)
@ 2015-04-30 14:31             ` Antoine Tenart
  -1 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-30 14:31 UTC (permalink / raw)
  To: Ezequiel Garcia
  Cc: Sebastian Hesselbarth, Antoine Tenart, dwmw2, computersforpeace,
	boris.brezillon, zmxu, jszhang, linux-arm-kernel, linux-mtd,
	linux-kernel, Robert Jarzmik

On Thu, Apr 16, 2015 at 01:59:32PM -0300, Ezequiel Garcia wrote:
> On 04/16/2015 10:41 AM, Sebastian Hesselbarth wrote:
> 
> > All we need is a function to convert sdr_timings to sane driver
> > timings. And we really need to split this patch into tiny pieces
> > otherwise it is not reviewable - or at least I need a full overview
> > about the driver first.
> > 
> 
> I think that's a bit of a different issue. This patch seems to be doing
> two things: it removes the in-driver flash detection *and* reworks
> timing setup.
> 
> How about we split this in two or even three patches? Along these lines:
> 1) introduce timing helpers, 2) rework timing setup, 3) remove in-driver
> flash detection. Not sure how feasible it is.

That's quite difficult, as you cannot have 1) without having the changes
made in 2). Flash detection and timing reworks are linked and I'm not
sure we can have this split into 2 or 3 patches without having a state
where the driver does not work.

Antoine

-- 
Antoine Ténart, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

* Re: [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
@ 2015-04-30 14:31             ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-30 14:31 UTC (permalink / raw)
  To: Ezequiel Garcia
  Cc: zmxu, boris.brezillon, Robert Jarzmik, Antoine Tenart,
	linux-kernel, linux-mtd, jszhang, computersforpeace, dwmw2,
	linux-arm-kernel, Sebastian Hesselbarth

On Thu, Apr 16, 2015 at 01:59:32PM -0300, Ezequiel Garcia wrote:
> On 04/16/2015 10:41 AM, Sebastian Hesselbarth wrote:
> 
> > All we need is a function to convert sdr_timings to sane driver
> > timings. And we really need to split this patch into tiny pieces
> > otherwise it is not reviewable - or at least I need a full overview
> > about the driver first.
> > 
> 
> I think that's a bit of a different issue. This patch seems to be doing
> two things: it removes the in-driver flash detection *and* reworks
> timing setup.
> 
> How about we split this in two or even three patches? Along these lines:
> 1) introduce timing helpers, 2) rework timing setup, 3) remove in-driver
> flash detection. Not sure how feasible it is.

That's quite difficult, as you cannot have 1) without having the changes
made in 2). Flash detection and timing reworks are linked and I'm not
sure we can have this split into 2 or 3 patches without having a state
where the driver does not work.

Antoine

-- 
Antoine Ténart, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

* [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
@ 2015-04-30 14:31             ` Antoine Tenart
  0 siblings, 0 replies; 57+ messages in thread
From: Antoine Tenart @ 2015-04-30 14:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 16, 2015 at 01:59:32PM -0300, Ezequiel Garcia wrote:
> On 04/16/2015 10:41 AM, Sebastian Hesselbarth wrote:
> 
> > All we need is a function to convert sdr_timings to sane driver
> > timings. And we really need to split this patch into tiny pieces
> > otherwise it is not reviewable - or at least I need a full overview
> > about the driver first.
> > 
> 
> I think that's a bit of a different issue. This patch seems to be doing
> two things: it removes the in-driver flash detection *and* reworks
> timing setup.
> 
> How about we split this in two or even three patches? Along these lines:
> 1) introduce timing helpers, 2) rework timing setup, 3) remove in-driver
> flash detection. Not sure how feasible it is.

That's quite difficult, as you cannot have 1) without having the changes
made in 2). Flash detection and timing reworks are linked and I'm not
sure we can have this split into 2 or 3 patches without having a state
where the driver does not work.

Antoine

-- 
Antoine T?nart, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

* Re: [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
  2015-04-30 14:31             ` Antoine Tenart
  (?)
@ 2015-04-30 17:52               ` Sebastian Hesselbarth
  -1 siblings, 0 replies; 57+ messages in thread
From: Sebastian Hesselbarth @ 2015-04-30 17:52 UTC (permalink / raw)
  To: Antoine Tenart, Ezequiel Garcia
  Cc: dwmw2, computersforpeace, boris.brezillon, zmxu, jszhang,
	linux-arm-kernel, linux-mtd, linux-kernel, Robert Jarzmik

On 30.04.2015 16:31, Antoine Tenart wrote:
> On Thu, Apr 16, 2015 at 01:59:32PM -0300, Ezequiel Garcia wrote:
>> On 04/16/2015 10:41 AM, Sebastian Hesselbarth wrote:
>>
>>> All we need is a function to convert sdr_timings to sane driver
>>> timings. And we really need to split this patch into tiny pieces
>>> otherwise it is not reviewable - or at least I need a full overview
>>> about the driver first.
>>>
>>
>> I think that's a bit of a different issue. This patch seems to be doing
>> two things: it removes the in-driver flash detection *and* reworks
>> timing setup.
>>
>> How about we split this in two or even three patches? Along these lines:
>> 1) introduce timing helpers, 2) rework timing setup, 3) remove in-driver
>> flash detection. Not sure how feasible it is.
>
> That's quite difficult, as you cannot have 1) without having the changes
> made in 2). Flash detection and timing reworks are linked and I'm not
> sure we can have this split into 2 or 3 patches without having a state
> where the driver does not work.

Antoine,

functionally you are right. But splitting the patch into the three
pieces above will heavily reduce the diff-per-patch significantly.
For example, if you introduce 1) without using it, we can only look at
the helper. Then in 2) you actually use that helper and 3) will clean
the mess up.

BTW, I am fine with running the flash on mach-berlin boards with some
default timing for now until we worked out how mtd will deal with
protocol and array timings.

Sebastian

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

* Re: [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
@ 2015-04-30 17:52               ` Sebastian Hesselbarth
  0 siblings, 0 replies; 57+ messages in thread
From: Sebastian Hesselbarth @ 2015-04-30 17:52 UTC (permalink / raw)
  To: Antoine Tenart, Ezequiel Garcia
  Cc: zmxu, boris.brezillon, Robert Jarzmik, linux-kernel, linux-mtd,
	jszhang, computersforpeace, dwmw2, linux-arm-kernel

On 30.04.2015 16:31, Antoine Tenart wrote:
> On Thu, Apr 16, 2015 at 01:59:32PM -0300, Ezequiel Garcia wrote:
>> On 04/16/2015 10:41 AM, Sebastian Hesselbarth wrote:
>>
>>> All we need is a function to convert sdr_timings to sane driver
>>> timings. And we really need to split this patch into tiny pieces
>>> otherwise it is not reviewable - or at least I need a full overview
>>> about the driver first.
>>>
>>
>> I think that's a bit of a different issue. This patch seems to be doing
>> two things: it removes the in-driver flash detection *and* reworks
>> timing setup.
>>
>> How about we split this in two or even three patches? Along these lines:
>> 1) introduce timing helpers, 2) rework timing setup, 3) remove in-driver
>> flash detection. Not sure how feasible it is.
>
> That's quite difficult, as you cannot have 1) without having the changes
> made in 2). Flash detection and timing reworks are linked and I'm not
> sure we can have this split into 2 or 3 patches without having a state
> where the driver does not work.

Antoine,

functionally you are right. But splitting the patch into the three
pieces above will heavily reduce the diff-per-patch significantly.
For example, if you introduce 1) without using it, we can only look at
the helper. Then in 2) you actually use that helper and 3) will clean
the mess up.

BTW, I am fine with running the flash on mach-berlin boards with some
default timing for now until we worked out how mtd will deal with
protocol and array timings.

Sebastian

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

* [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup
@ 2015-04-30 17:52               ` Sebastian Hesselbarth
  0 siblings, 0 replies; 57+ messages in thread
From: Sebastian Hesselbarth @ 2015-04-30 17:52 UTC (permalink / raw)
  To: linux-arm-kernel

On 30.04.2015 16:31, Antoine Tenart wrote:
> On Thu, Apr 16, 2015 at 01:59:32PM -0300, Ezequiel Garcia wrote:
>> On 04/16/2015 10:41 AM, Sebastian Hesselbarth wrote:
>>
>>> All we need is a function to convert sdr_timings to sane driver
>>> timings. And we really need to split this patch into tiny pieces
>>> otherwise it is not reviewable - or at least I need a full overview
>>> about the driver first.
>>>
>>
>> I think that's a bit of a different issue. This patch seems to be doing
>> two things: it removes the in-driver flash detection *and* reworks
>> timing setup.
>>
>> How about we split this in two or even three patches? Along these lines:
>> 1) introduce timing helpers, 2) rework timing setup, 3) remove in-driver
>> flash detection. Not sure how feasible it is.
>
> That's quite difficult, as you cannot have 1) without having the changes
> made in 2). Flash detection and timing reworks are linked and I'm not
> sure we can have this split into 2 or 3 patches without having a state
> where the driver does not work.

Antoine,

functionally you are right. But splitting the patch into the three
pieces above will heavily reduce the diff-per-patch significantly.
For example, if you introduce 1) without using it, we can only look at
the helper. Then in 2) you actually use that helper and 3) will clean
the mess up.

BTW, I am fine with running the flash on mach-berlin boards with some
default timing for now until we worked out how mtd will deal with
protocol and array timings.

Sebastian

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

end of thread, other threads:[~2015-04-30 17:52 UTC | newest]

Thread overview: 57+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-15 17:23 [PATCH v4 00/10] ARM: berlin: add nand support Antoine Tenart
2015-04-15 17:23 ` Antoine Tenart
2015-04-15 17:23 ` Antoine Tenart
2015-04-15 17:23 ` [PATCH v4 01/10] mtd: pxa3xx_nand: add a non mandatory ECC clock Antoine Tenart
2015-04-15 17:23   ` Antoine Tenart
2015-04-15 17:23   ` Antoine Tenart
2015-04-15 17:24 ` [PATCH v4 02/10] Documentation: bindings: document the clocks for pxa3xx-nand Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart
2015-04-15 17:24 ` [PATCH v4 03/10] mtd: pxa3xx_nand: add a default chunk size Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart
2015-04-15 17:24 ` [PATCH v4 04/10] mtd: pxa3xx_nand: rework flash detection and timing setup Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart
2015-04-15 19:11   ` Sebastian Hesselbarth
2015-04-15 19:11     ` Sebastian Hesselbarth
2015-04-15 19:11     ` Sebastian Hesselbarth
2015-04-16 13:10     ` Ezequiel Garcia
2015-04-16 13:10       ` Ezequiel Garcia
2015-04-16 13:10       ` Ezequiel Garcia
2015-04-16 13:41       ` Sebastian Hesselbarth
2015-04-16 13:41         ` Sebastian Hesselbarth
2015-04-16 13:41         ` Sebastian Hesselbarth
2015-04-16 16:59         ` Ezequiel Garcia
2015-04-16 16:59           ` Ezequiel Garcia
2015-04-16 16:59           ` Ezequiel Garcia
2015-04-17 19:52           ` Robert Jarzmik
2015-04-17 19:52             ` Robert Jarzmik
2015-04-17 19:52             ` Robert Jarzmik
2015-04-30 14:31           ` Antoine Tenart
2015-04-30 14:31             ` Antoine Tenart
2015-04-30 14:31             ` Antoine Tenart
2015-04-30 17:52             ` Sebastian Hesselbarth
2015-04-30 17:52               ` Sebastian Hesselbarth
2015-04-30 17:52               ` Sebastian Hesselbarth
2015-04-15 17:24 ` [PATCH v4 05/10] mtd: nand: add Samsung K9GBG08U0A-M to nand_ids table Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart
2015-04-15 21:38   ` Sebastian Hesselbarth
2015-04-15 21:38     ` Sebastian Hesselbarth
2015-04-15 21:38     ` Sebastian Hesselbarth
2015-04-15 17:24 ` [PATCH v4 06/10] mtd: pxa3xx_nand: add support for the Marvell Berlin nand controller Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart
2015-04-15 17:24 ` [PATCH v4 07/10] Documentation: bindings: add the Berlin nand controller compatible Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart
2015-04-15 17:24 ` [PATCH v4 08/10] mtd: nand: let Marvell Berlin SoCs select the pxa3xx driver Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart
2015-04-15 17:24 ` [PATCH v4 09/10] ARM: berlin: add BG2Q node for the nand Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart
2015-04-15 17:24 ` [PATCH v4 10/10] ARM: berlin: enable flash on the BG2Q DMP Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart
2015-04-15 17:24   ` Antoine Tenart

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.