diff mbox series

[1/4] mtd: nand: denali: allow to override corrupted revision register

Message ID 1505479402-17945-1-git-send-email-yamada.masahiro@socionext.com
State Accepted
Commit 6c71b6f45474e58cb85370951f4c144495778e0b
Headers show
Series [1/4] mtd: nand: denali: allow to override corrupted revision register | expand

Commit Message

Masahiro Yamada Sept. 15, 2017, 12:43 p.m. UTC
The Denali IP does not update the revision register properly.
Allow to override it with SoC data associated with compatible.

Linux had already finished big surgery of this driver, but I need
to prepare the NAND core before the full sync of the driver.
For now, I am fixing the most fatal problem on UniPhier platform.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

 drivers/mtd/nand/denali.c    | 27 +++++++++++++++------------
 drivers/mtd/nand/denali.h    |  7 +++++--
 drivers/mtd/nand/denali_dt.c | 30 ++++++++++++++++++++++++++++++
 3 files changed, 50 insertions(+), 14 deletions(-)

Comments

Masahiro Yamada Sept. 18, 2017, 11:29 a.m. UTC | #1
2017-09-15 21:43 GMT+09:00 Masahiro Yamada <yamada.masahiro@socionext.com>:
> The Denali IP does not update the revision register properly.
> Allow to override it with SoC data associated with compatible.
>
> Linux had already finished big surgery of this driver, but I need
> to prepare the NAND core before the full sync of the driver.
> For now, I am fixing the most fatal problem on UniPhier platform.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
> ---
>

Series, applied to u-boot-uniphier/master.
diff mbox series

Patch

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 47cf37d..54718f4 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -10,7 +10,7 @@ 
 #include <malloc.h>
 #include <nand.h>
 #include <linux/errno.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 #include "denali.h"
 
@@ -433,17 +433,13 @@  static void find_valid_banks(struct denali_nand_info *denali)
  */
 static void detect_max_banks(struct denali_nand_info *denali)
 {
-	uint32_t features = readl(denali->flash_reg + FEATURES);
-	/*
-	 * Read the revision register, so we can calculate the max_banks
-	 * properly: the encoding changed from rev 5.0 to 5.1
-	 */
-	u32 revision = MAKE_COMPARABLE_REVISION(
-				readl(denali->flash_reg + REVISION));
-	if (revision < REVISION_5_1)
-		denali->max_banks = 2 << (features & FEATURES__N_BANKS);
-	else
-		denali->max_banks = 1 << (features & FEATURES__N_BANKS);
+	uint32_t features = ioread32(denali->flash_reg + FEATURES);
+
+	denali->max_banks = 1 << (features & FEATURES__N_BANKS);
+
+	/* the encoding changed from rev 5.0 to 5.1 */
+	if (denali->revision < 0x0501)
+		denali->max_banks <<= 1;
 }
 
 static void detect_partition_feature(struct denali_nand_info *denali)
@@ -1154,6 +1150,13 @@  static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col,
 static void denali_hw_init(struct denali_nand_info *denali)
 {
 	/*
+	 * The REVISION register may not be reliable.  Platforms are allowed to
+	 * override it.
+	 */
+	if (!denali->revision)
+		denali->revision = swab16(ioread32(denali->flash_reg + REVISION));
+
+	/*
 	 * tell driver how many bit controller will skip before writing
 	 * ECC code in OOB. This is normally used for bad block marker
 	 */
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index 694bce5..08db488 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -166,8 +166,6 @@ 
 
 #define REVISION				0x370
 #define     REVISION__VALUE				0xffff
-#define MAKE_COMPARABLE_REVISION(x)		swab16((x) & REVISION__VALUE)
-#define REVISION_5_1				0x00000501
 
 #define ONFI_DEVICE_FEATURES			0x380
 #define     ONFI_DEVICE_FEATURES__VALUE			0x003f
@@ -462,8 +460,13 @@  struct denali_nand_info {
 	uint32_t blksperchip;
 	uint32_t bbtskipbytes;
 	uint32_t max_banks;
+	unsigned int revision;
+	unsigned int caps;
 };
 
+#define DENALI_CAP_HW_ECC_FIXUP			BIT(0)
+#define DENALI_CAP_DMA_64BIT			BIT(1)
+
 int denali_init(struct denali_nand_info *denali);
 
 #endif /* __DENALI_H__ */
diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c
index 0a6155c..4afd679 100644
--- a/drivers/mtd/nand/denali_dt.c
+++ b/drivers/mtd/nand/denali_dt.c
@@ -12,15 +12,38 @@ 
 
 #include "denali.h"
 
+struct denali_dt_data {
+	unsigned int revision;
+	unsigned int caps;
+};
+
+static const struct denali_dt_data denali_socfpga_data = {
+	.caps = DENALI_CAP_HW_ECC_FIXUP,
+};
+
+static const struct denali_dt_data denali_uniphier_v5a_data = {
+	.caps = DENALI_CAP_HW_ECC_FIXUP |
+		DENALI_CAP_DMA_64BIT,
+};
+
+static const struct denali_dt_data denali_uniphier_v5b_data = {
+	.revision = 0x0501,
+	.caps = DENALI_CAP_HW_ECC_FIXUP |
+		DENALI_CAP_DMA_64BIT,
+};
+
 static const struct udevice_id denali_nand_dt_ids[] = {
 	{
 		.compatible = "altr,socfpga-denali-nand",
+		.data = (unsigned long)&denali_socfpga_data,
 	},
 	{
 		.compatible = "socionext,uniphier-denali-nand-v5a",
+		.data = (unsigned long)&denali_uniphier_v5a_data,
 	},
 	{
 		.compatible = "socionext,uniphier-denali-nand-v5b",
+		.data = (unsigned long)&denali_uniphier_v5b_data,
 	},
 	{ /* sentinel */ }
 };
@@ -28,9 +51,16 @@  static const struct udevice_id denali_nand_dt_ids[] = {
 static int denali_dt_probe(struct udevice *dev)
 {
 	struct denali_nand_info *denali = dev_get_priv(dev);
+	const struct denali_dt_data *data;
 	struct resource res;
 	int ret;
 
+	data = (void *)dev_get_driver_data(dev);
+	if (data) {
+		denali->revision = data->revision;
+		denali->caps = data->caps;
+	}
+
 	ret = dev_read_resource_byname(dev, "denali_reg", &res);
 	if (ret)
 		return ret;