linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] mtd: gpmi: set the Golois Field bit for mx6q's BCH
@ 2013-01-25  6:04 Huang Shijie
  2013-01-25  6:04 ` [PATCH 2/2] mtd: gpmi: add sanity check for the ECC strength Huang Shijie
  2013-02-04  8:31 ` [PATCH 1/2] mtd: gpmi: set the Golois Field bit for mx6q's BCH Artem Bityutskiy
  0 siblings, 2 replies; 5+ messages in thread
From: Huang Shijie @ 2013-01-25  6:04 UTC (permalink / raw)
  To: linux-arm-kernel

The GF13 can be only used in the following case:
    The ECC data chunk is less then 1K bytes.

In mx23/mx28, the ecc data chunk is 512 bytes. So it is okay.

But in mx6q, we begin to use some large nand chip whose ecc
data chunk maybe 1K bytes long.  So when the data chunk is 1K bytes,
we have to use the GF14.

This patch sets the Golois Field bit when the GF14 is needed.

Signed-off-by: Huang Shijie <b32955@freescale.com>
---
 drivers/mtd/nand/gpmi-nand/bch-regs.h  |   20 ++++++++++++++++++++
 drivers/mtd/nand/gpmi-nand/gpmi-lib.c  |    4 ++++
 drivers/mtd/nand/gpmi-nand/gpmi-nand.c |    6 ++++--
 3 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/gpmi-nand/bch-regs.h b/drivers/mtd/nand/gpmi-nand/bch-regs.h
index d67bca5..588f537 100644
--- a/drivers/mtd/nand/gpmi-nand/bch-regs.h
+++ b/drivers/mtd/nand/gpmi-nand/bch-regs.h
@@ -61,6 +61,16 @@
 			& BM_BCH_FLASH0LAYOUT0_ECC0)		\
 	)
 
+#define MX6Q_BP_BCH_FLASH0LAYOUT0_GF_13_14	10
+#define MX6Q_BM_BCH_FLASH0LAYOUT0_GF_13_14			\
+				(0x1 << MX6Q_BP_BCH_FLASH0LAYOUT0_GF_13_14)
+#define BF_BCH_FLASH0LAYOUT0_GF(v, x)				\
+	((GPMI_IS_MX6Q(x) && ((v) == 14))			\
+		? (((1) << MX6Q_BP_BCH_FLASH0LAYOUT0_GF_13_14)	\
+			& MX6Q_BM_BCH_FLASH0LAYOUT0_GF_13_14)	\
+		: 0						\
+	)
+
 #define BP_BCH_FLASH0LAYOUT0_DATA0_SIZE		0
 #define BM_BCH_FLASH0LAYOUT0_DATA0_SIZE		\
 			(0xfff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE)
@@ -93,6 +103,16 @@
 			& BM_BCH_FLASH0LAYOUT1_ECCN)		\
 	)
 
+#define MX6Q_BP_BCH_FLASH0LAYOUT1_GF_13_14	10
+#define MX6Q_BM_BCH_FLASH0LAYOUT1_GF_13_14			\
+				(0x1 << MX6Q_BP_BCH_FLASH0LAYOUT1_GF_13_14)
+#define BF_BCH_FLASH0LAYOUT1_GF(v, x)				\
+	((GPMI_IS_MX6Q(x) && ((v) == 14))			\
+		? (((1) << MX6Q_BP_BCH_FLASH0LAYOUT1_GF_13_14)	\
+			& MX6Q_BM_BCH_FLASH0LAYOUT1_GF_13_14)	\
+		: 0						\
+	)
+
 #define BP_BCH_FLASH0LAYOUT1_DATAN_SIZE		0
 #define BM_BCH_FLASH0LAYOUT1_DATAN_SIZE		\
 			(0xfff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE)
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
index 01cc570..4f8857f 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
@@ -237,6 +237,7 @@ int bch_set_geometry(struct gpmi_nand_data *this)
 	unsigned int metadata_size;
 	unsigned int ecc_strength;
 	unsigned int page_size;
+	unsigned int gf_len;
 	int ret;
 
 	if (common_nfc_set_geometry(this))
@@ -247,6 +248,7 @@ int bch_set_geometry(struct gpmi_nand_data *this)
 	metadata_size = bch_geo->metadata_size;
 	ecc_strength  = bch_geo->ecc_strength >> 1;
 	page_size     = bch_geo->page_size;
+	gf_len        = bch_geo->gf_len;
 
 	ret = gpmi_enable_clk(this);
 	if (ret)
@@ -268,11 +270,13 @@ int bch_set_geometry(struct gpmi_nand_data *this)
 	writel(BF_BCH_FLASH0LAYOUT0_NBLOCKS(block_count)
 			| BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size)
 			| BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength, this)
+			| BF_BCH_FLASH0LAYOUT0_GF(gf_len, this)
 			| BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size, this),
 			r->bch_regs + HW_BCH_FLASH0LAYOUT0);
 
 	writel(BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size)
 			| BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength, this)
+			| BF_BCH_FLASH0LAYOUT1_GF(gf_len, this)
 			| BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size, this),
 			r->bch_regs + HW_BCH_FLASH0LAYOUT1);
 
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index 38c8b8b..2521678 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -112,10 +112,12 @@ int common_nfc_set_geometry(struct gpmi_nand_data *this)
 	/* The default for the length of Galois Field. */
 	geo->gf_len = 13;
 
-	/* The default for chunk size. There is no oobsize greater then 512. */
+	/* The default for chunk size. */
 	geo->ecc_chunk_size = 512;
-	while (geo->ecc_chunk_size < mtd->oobsize)
+	while (geo->ecc_chunk_size < mtd->oobsize) {
 		geo->ecc_chunk_size *= 2; /* keep C >= O */
+		geo->gf_len = 14;
+	}
 
 	geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
 
-- 
1.7.0.4

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

* [PATCH 2/2] mtd: gpmi: add sanity check for the ECC strength
  2013-01-25  6:04 [PATCH 1/2] mtd: gpmi: set the Golois Field bit for mx6q's BCH Huang Shijie
@ 2013-01-25  6:04 ` Huang Shijie
  2013-01-29  1:23   ` [PATCH v2] mtd: gpmi: add sanity check for the ECC Huang Shijie
  2013-02-04  8:31 ` [PATCH 1/2] mtd: gpmi: set the Golois Field bit for mx6q's BCH Artem Bityutskiy
  1 sibling, 1 reply; 5+ messages in thread
From: Huang Shijie @ 2013-01-25  6:04 UTC (permalink / raw)
  To: linux-arm-kernel

The mx23/mx28 can only support 20-bits ECC, while the mx6
can supports 40-bits ECC.

Some new nand chips may require 40-bits ECC. So we should
add the sanity check for the ECC strength. If we can not
support this nand chip, we should quit.

Signed-off-by: Huang Shijie <b32955@freescale.com>
---
 drivers/mtd/nand/gpmi-nand/gpmi-nand.c |   23 +++++++++++++++++++++--
 drivers/mtd/nand/gpmi-nand/gpmi-nand.h |    4 ++++
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index 2521678..a19c42a 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -94,6 +94,20 @@ static inline int get_ecc_strength(struct gpmi_nand_data *this)
 	return round_down(ecc_strength, 2);
 }
 
+static inline bool check_ecc_strength(struct gpmi_nand_data *this,
+				int ecc_strength)
+{
+	/* Do the sanity check. */
+	if (GPMI_IS_MX23(this) || GPMI_IS_MX28(this)) {
+		if (ecc_strength > MXS_ECC_STRENGTH_MAX)
+			return false;
+	} else if (GPMI_IS_MX6Q(this)) {
+		if (ecc_strength > MX6_ECC_STRENGTH_MAX)
+			return false;
+	}
+	return true;
+}
+
 int common_nfc_set_geometry(struct gpmi_nand_data *this)
 {
 	struct bch_geometry *geo = &this->bch_geometry;
@@ -123,8 +137,13 @@ int common_nfc_set_geometry(struct gpmi_nand_data *this)
 
 	/* We use the same ECC strength for all chunks. */
 	geo->ecc_strength = get_ecc_strength(this);
-	if (!geo->ecc_strength) {
-		pr_err("wrong ECC strength.\n");
+	if (!check_ecc_strength(this, geo->ecc_strength)) {
+		dev_err(this->dev,
+			"We can not support this nand chip."
+			" Its required ecc strength(%d) is beyond our"
+			" capability(%d).\n", geo->ecc_strength,
+			(GPMI_IS_MX6Q(this) ? MX6_ECC_STRENGTH_MAX
+					: MXS_ECC_STRENGTH_MAX));
 		return -EINVAL;
 	}
 
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
index 3d93a5e..0729477 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
@@ -284,6 +284,10 @@ extern int gpmi_read_page(struct gpmi_nand_data *,
 #define STATUS_ERASED		0xff
 #define STATUS_UNCORRECTABLE	0xfe
 
+/* BCH's bit correction capability. */
+#define MXS_ECC_STRENGTH_MAX	20	/* mx23 and mx28 */
+#define MX6_ECC_STRENGTH_MAX	40
+
 /* Use the platform_id to distinguish different Archs. */
 #define IS_MX23			0x0
 #define IS_MX28			0x1
-- 
1.7.0.4

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

* [PATCH v2] mtd: gpmi: add sanity check for the ECC
  2013-01-25  6:04 ` [PATCH 2/2] mtd: gpmi: add sanity check for the ECC strength Huang Shijie
@ 2013-01-29  1:23   ` Huang Shijie
  0 siblings, 0 replies; 5+ messages in thread
From: Huang Shijie @ 2013-01-29  1:23 UTC (permalink / raw)
  To: linux-arm-kernel

We do the check based on the following two facts:

[1] The mx23/mx28 can only support 20-bits ECC, while the mx6
    can supports 40-bits ECC.

[2] The mx23/mx28 can only support the GF13, while the mx6
    can supports GF13 and GF14.

Signed-off-by: Huang Shijie <b32955@freescale.com>
---
v1 --> v2:
     [1] add the Golois Field check.
     [2] change the comments.

---
 drivers/mtd/nand/gpmi-nand/gpmi-nand.c |   28 ++++++++++++++++++++++++++--
 drivers/mtd/nand/gpmi-nand/gpmi-nand.h |    4 ++++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index 2521678..717881a 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -94,6 +94,25 @@ static inline int get_ecc_strength(struct gpmi_nand_data *this)
 	return round_down(ecc_strength, 2);
 }
 
+static inline bool gpmi_check_ecc(struct gpmi_nand_data *this)
+{
+	struct bch_geometry *geo = &this->bch_geometry;
+
+	/* Do the sanity check. */
+	if (GPMI_IS_MX23(this) || GPMI_IS_MX28(this)) {
+		/* The mx23/mx28 only support the GF13. */
+		if (geo->gf_len == 14)
+			return false;
+
+		if (geo->ecc_strength > MXS_ECC_STRENGTH_MAX)
+			return false;
+	} else if (GPMI_IS_MX6Q(this)) {
+		if (geo->ecc_strength > MX6_ECC_STRENGTH_MAX)
+			return false;
+	}
+	return true;
+}
+
 int common_nfc_set_geometry(struct gpmi_nand_data *this)
 {
 	struct bch_geometry *geo = &this->bch_geometry;
@@ -123,8 +142,13 @@ int common_nfc_set_geometry(struct gpmi_nand_data *this)
 
 	/* We use the same ECC strength for all chunks. */
 	geo->ecc_strength = get_ecc_strength(this);
-	if (!geo->ecc_strength) {
-		pr_err("wrong ECC strength.\n");
+	if (!gpmi_check_ecc(this)) {
+		dev_err(this->dev,
+			"We can not support this nand chip."
+			" Its required ecc strength(%d) is beyond our"
+			" capability(%d).\n", geo->ecc_strength,
+			(GPMI_IS_MX6Q(this) ? MX6_ECC_STRENGTH_MAX
+					: MXS_ECC_STRENGTH_MAX));
 		return -EINVAL;
 	}
 
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
index 3d93a5e..0729477 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
@@ -284,6 +284,10 @@ extern int gpmi_read_page(struct gpmi_nand_data *,
 #define STATUS_ERASED		0xff
 #define STATUS_UNCORRECTABLE	0xfe
 
+/* BCH's bit correction capability. */
+#define MXS_ECC_STRENGTH_MAX	20	/* mx23 and mx28 */
+#define MX6_ECC_STRENGTH_MAX	40
+
 /* Use the platform_id to distinguish different Archs. */
 #define IS_MX23			0x0
 #define IS_MX28			0x1
-- 
1.7.0.4

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

* [PATCH 1/2] mtd: gpmi: set the Golois Field bit for mx6q's BCH
  2013-01-25  6:04 [PATCH 1/2] mtd: gpmi: set the Golois Field bit for mx6q's BCH Huang Shijie
  2013-01-25  6:04 ` [PATCH 2/2] mtd: gpmi: add sanity check for the ECC strength Huang Shijie
@ 2013-02-04  8:31 ` Artem Bityutskiy
  2013-02-04  9:11   ` Huang Shijie
  1 sibling, 1 reply; 5+ messages in thread
From: Artem Bityutskiy @ 2013-02-04  8:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2013-01-25 at 14:04 +0800, Huang Shijie wrote:
> +#define BF_BCH_FLASH0LAYOUT0_GF(v, x)				\
> +	((GPMI_IS_MX6Q(x) && ((v) == 14))			\
> +		? (((1) << MX6Q_BP_BCH_FLASH0LAYOUT0_GF_13_14)	\
> +			& MX6Q_BM_BCH_FLASH0LAYOUT0_GF_13_14)	\
> +		: 0						\
> +	)

Did you consider using static inline functions instead of macro
definitions? The added value would be at least type-checking. You would
also probably use names better than "v" and "x", you could even have
commentaries. Please, consider doing this.

Anyway, pushed to l2-mtd.git, thanks!

-- 
Best Regards,
Artem Bityutskiy
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130204/e454a403/attachment.sig>

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

* [PATCH 1/2] mtd: gpmi: set the Golois Field bit for mx6q's BCH
  2013-02-04  8:31 ` [PATCH 1/2] mtd: gpmi: set the Golois Field bit for mx6q's BCH Artem Bityutskiy
@ 2013-02-04  9:11   ` Huang Shijie
  0 siblings, 0 replies; 5+ messages in thread
From: Huang Shijie @ 2013-02-04  9:11 UTC (permalink / raw)
  To: linux-arm-kernel

? 2013?02?04? 16:31, Artem Bityutskiy ??:
> On Fri, 2013-01-25 at 14:04 +0800, Huang Shijie wrote:
>> +#define BF_BCH_FLASH0LAYOUT0_GF(v, x)				\
>> +	((GPMI_IS_MX6Q(x)&&  ((v) == 14))			\
>> +		? (((1)<<  MX6Q_BP_BCH_FLASH0LAYOUT0_GF_13_14)	\
>> +			&  MX6Q_BM_BCH_FLASH0LAYOUT0_GF_13_14)	\
>> +		: 0						\
>> +	)
> Did you consider using static inline functions instead of macro
These macros are only used  when the different archs have different 
definitions about
the some registers. Yes, it's ok to use the functions to replace them.

I am not sure if there is still a need to add the similar macros, if it 
does, i can change to use
the inline functions.

thanks
Huang Shijie

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

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

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-01-25  6:04 [PATCH 1/2] mtd: gpmi: set the Golois Field bit for mx6q's BCH Huang Shijie
2013-01-25  6:04 ` [PATCH 2/2] mtd: gpmi: add sanity check for the ECC strength Huang Shijie
2013-01-29  1:23   ` [PATCH v2] mtd: gpmi: add sanity check for the ECC Huang Shijie
2013-02-04  8:31 ` [PATCH 1/2] mtd: gpmi: set the Golois Field bit for mx6q's BCH Artem Bityutskiy
2013-02-04  9:11   ` Huang Shijie

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