diff mbox

[U-Boot,v4,4/6] omap_gpmc: change nandecc command

Message ID 1365155570-21549-1-git-send-email-andreas.devel@googlemail.com
State Accepted
Delegated to: Tom Rini
Headers show

Commit Message

Andreas Bießmann April 5, 2013, 9:52 a.m. UTC
With uppcoming BCH support on OMAP devices we need to decide between differnt
algorithms when switching the ECC engine.  Currently we support 1-bit hammign
and 8-bit BCH on HW backend.

In order to switch between differnet ECC algorithms we need to change the
interface of omap_nand_switch_ecc() also.

Signed-off-by: Andreas Bießmann <andreas.devel@googlemail.com>
Cc: Tom Rini <trini@ti.com>
Cc: Thomas Weber <thomas.weber.linux@googlemail.com>
---
new in v2

since v2:
 * use void omap_nand_switch_ecc(bool, uint32_t)
 * print warning if unknown HW ecc strengs choosen
 * fix alignment in help test

since v3:
 * reset ecc.mode to NAND_ECC_NONE to prevent a BUG() on wrong eccstrength
   input to changed omap_nand_switch_ecc();
   With this change a user has the chance to switch back to another ECC mode
   via nandecc command.
   Many thanks to Thomas Weber for reporting this.

 arch/arm/cpu/armv7/omap3/board.c             |   31 ++++++++++----
 arch/arm/include/asm/arch-am33xx/sys_proto.h |    2 +-
 arch/arm/include/asm/arch-omap3/sys_proto.h  |    2 +-
 drivers/mtd/nand/omap_gpmc.c                 |   57 ++++++++++++++------------
 4 files changed, 56 insertions(+), 36 deletions(-)

Comments

Thomas Weber April 5, 2013, 11:48 a.m. UTC | #1
Hello Andreas,

this patch fixes the reported BUG().

The output is now:

-----8<---------
OMAP3 DevKit8000 # nandecc hw hamming
1-bit hamming HW ECC selected
OMAP3 DevKit8000 # nandecc hw bch8
Unsupported HW ECC algorithm
NAND_ECC_NONE selected by board driver. This is not recommended !!
OMAP3 DevKit8000 #
----->8---------

Thomas

On 04/05/2013 11:52 AM, Andreas Bießmann wrote:
> With uppcoming BCH support on OMAP devices we need to decide between differnt
> algorithms when switching the ECC engine.  Currently we support 1-bit hammign
> and 8-bit BCH on HW backend.
>
> In order to switch between differnet ECC algorithms we need to change the
> interface of omap_nand_switch_ecc() also.
>
> Signed-off-by: Andreas Bießmann <andreas.devel@googlemail.com>
> Cc: Tom Rini <trini@ti.com>
> Cc: Thomas Weber <thomas.weber.linux@googlemail.com>
> ---
> new in v2
>
> since v2:
>  * use void omap_nand_switch_ecc(bool, uint32_t)
>  * print warning if unknown HW ecc strengs choosen
>  * fix alignment in help test
>
> since v3:
>  * reset ecc.mode to NAND_ECC_NONE to prevent a BUG() on wrong eccstrength
>    input to changed omap_nand_switch_ecc();
>    With this change a user has the chance to switch back to another ECC mode
>    via nandecc command.
>    Many thanks to Thomas Weber for reporting this.
>
>  arch/arm/cpu/armv7/omap3/board.c             |   31 ++++++++++----
>  arch/arm/include/asm/arch-am33xx/sys_proto.h |    2 +-
>  arch/arm/include/asm/arch-omap3/sys_proto.h  |    2 +-
>  drivers/mtd/nand/omap_gpmc.c                 |   57 ++++++++++++++------------
>  4 files changed, 56 insertions(+), 36 deletions(-)
>
> diff --git a/arch/arm/cpu/armv7/omap3/board.c b/arch/arm/cpu/armv7/omap3/board.c
> index c6d9a42..b72fadc 100644
> --- a/arch/arm/cpu/armv7/omap3/board.c
> +++ b/arch/arm/cpu/armv7/omap3/board.c
> @@ -328,14 +328,25 @@ void abort(void)
>   *****************************************************************************/
>  static int do_switch_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
>  {
> -	if (argc != 2)
> +	if (argc < 2 || argc > 3)
>  		goto usage;
> -	if (strncmp(argv[1], "hw", 2) == 0)
> -		omap_nand_switch_ecc(1);
> -	else if (strncmp(argv[1], "sw", 2) == 0)
> -		omap_nand_switch_ecc(0);
> -	else
> +
> +	if (strncmp(argv[1], "hw", 2) == 0) {
> +		if (argc == 2) {
> +			omap_nand_switch_ecc(1, 1);
> +		} else {
> +			if (strncmp(argv[2], "hamming", 7) == 0)
> +				omap_nand_switch_ecc(1, 1);
> +			else if (strncmp(argv[2], "bch8", 4) == 0)
> +				omap_nand_switch_ecc(1, 8);
> +			else
> +				goto usage;
> +		}
> +	} else if (strncmp(argv[1], "sw", 2) == 0) {
> +		omap_nand_switch_ecc(0, 0);
> +	} else {
>  		goto usage;
> +	}
>  
>  	return 0;
>  
> @@ -345,9 +356,13 @@ usage:
>  }
>  
>  U_BOOT_CMD(
> -	nandecc, 2, 1,	do_switch_ecc,
> +	nandecc, 3, 1,	do_switch_ecc,
>  	"switch OMAP3 NAND ECC calculation algorithm",
> -	"[hw/sw] - Switch between NAND hardware (hw) or software (sw) ecc algorithm"
> +	"hw [hamming|bch8] - Switch between NAND hardware 1-bit hamming and"
> +	" 8-bit BCH\n"
> +	"                           ecc calculation (second parameter may"
> +	" be omitted).\n"
> +	"nandecc sw               - Switch to NAND software ecc algorithm."
>  );
>  
>  #endif /* CONFIG_NAND_OMAP_GPMC & !CONFIG_SPL_BUILD */
> diff --git a/arch/arm/include/asm/arch-am33xx/sys_proto.h b/arch/arm/include/asm/arch-am33xx/sys_proto.h
> index 0910a94..c913b5f 100644
> --- a/arch/arm/include/asm/arch-am33xx/sys_proto.h
> +++ b/arch/arm/include/asm/arch-am33xx/sys_proto.h
> @@ -39,5 +39,5 @@ struct gpmc_cs;
>  void gpmc_init(void);
>  void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base,
>  			u32 size);
> -void omap_nand_switch_ecc(int);
> +void omap_nand_switch_ecc(uint32_t, uint32_t);
>  #endif
> diff --git a/arch/arm/include/asm/arch-omap3/sys_proto.h b/arch/arm/include/asm/arch-omap3/sys_proto.h
> index d60f2ad..dae1312 100644
> --- a/arch/arm/include/asm/arch-omap3/sys_proto.h
> +++ b/arch/arm/include/asm/arch-omap3/sys_proto.h
> @@ -78,7 +78,7 @@ void sr32(void *, u32, u32, u32);
>  u32 wait_on_value(u32, u32, void *, u32);
>  void sdelay(unsigned long);
>  void make_cs1_contiguous(void);
> -void omap_nand_switch_ecc(int);
> +void omap_nand_switch_ecc(uint32_t, uint32_t);
>  void power_init_r(void);
>  void dieid_num_r(void);
>  void do_omap3_emu_romcode_call(u32 service_id, u32 parameters);
> diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
> index c7d4999..3468c78 100644
> --- a/drivers/mtd/nand/omap_gpmc.c
> +++ b/drivers/mtd/nand/omap_gpmc.c
> @@ -604,13 +604,14 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
>  
>  #ifndef CONFIG_SPL_BUILD
>  /*
> - * omap_nand_switch_ecc - switch the ECC operation b/w h/w ecc and s/w ecc.
> - * The default is to come up on s/w ecc
> - *
> - * @hardware - 1 -switch to h/w ecc, 0 - s/w ecc
> + * omap_nand_switch_ecc - switch the ECC operation between different engines
> + * (h/w and s/w) and different algorithms (hamming and BCHx)
>   *
> + * @hardware		- true if one of the HW engines should be used
> + * @eccstrength		- the number of bits that could be corrected
> + *			  (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16)
>   */
> -void omap_nand_switch_ecc(int32_t hardware)
> +void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
>  {
>  	struct nand_chip *nand;
>  	struct mtd_info *mtd;
> @@ -628,6 +629,7 @@ void omap_nand_switch_ecc(int32_t hardware)
>  	nand->options |= NAND_OWN_BUFFERS;
>  
>  	/* Reset ecc interface */
> +	nand->ecc.mode = NAND_ECC_NONE;
>  	nand->ecc.read_page = NULL;
>  	nand->ecc.write_page = NULL;
>  	nand->ecc.read_oob = NULL;
> @@ -637,28 +639,31 @@ void omap_nand_switch_ecc(int32_t hardware)
>  	nand->ecc.calculate = NULL;
>  
>  	/* Setup the ecc configurations again */
> -	if (hardware == 1) {
> -		nand->ecc.mode = NAND_ECC_HW;
> -		nand->ecc.layout = &hw_nand_oob;
> -		nand->ecc.size = 512;
> -		nand->ecc.bytes = 3;
> -		nand->ecc.hwctl = omap_enable_hwecc;
> -		nand->ecc.correct = omap_correct_data;
> -		nand->ecc.calculate = omap_calculate_ecc;
> -		omap_hwecc_init(nand);
> -		printf("HW ECC selected\n");
> +	if (hardware) {
> +		if (eccstrength == 1) {
> +			nand->ecc.mode = NAND_ECC_HW;
> +			nand->ecc.layout = &hw_nand_oob;
> +			nand->ecc.size = 512;
> +			nand->ecc.bytes = 3;
> +			nand->ecc.hwctl = omap_enable_hwecc;
> +			nand->ecc.correct = omap_correct_data;
> +			nand->ecc.calculate = omap_calculate_ecc;
> +			omap_hwecc_init(nand);
> +			printf("1-bit hamming HW ECC selected\n");
> +		}
>  #ifdef CONFIG_AM33XX
> -	} else if (hardware == 2) {
> -		nand->ecc.mode = NAND_ECC_HW;
> -		nand->ecc.layout = &hw_bch8_nand_oob;
> -		nand->ecc.size = 512;
> -		nand->ecc.bytes = 14;
> -		nand->ecc.read_page = omap_read_page_bch;
> -		nand->ecc.hwctl = omap_enable_ecc_bch;
> -		nand->ecc.correct = omap_correct_data_bch;
> -		nand->ecc.calculate = omap_calculate_ecc_bch;
> -		omap_hwecc_init_bch(nand, NAND_ECC_READ);
> -		printf("HW BCH8 selected\n");
> +		else if (eccstrength == 8) {
> +			nand->ecc.mode = NAND_ECC_HW;
> +			nand->ecc.layout = &hw_bch8_nand_oob;
> +			nand->ecc.size = 512;
> +			nand->ecc.bytes = 14;
> +			nand->ecc.read_page = omap_read_page_bch;
> +			nand->ecc.hwctl = omap_enable_ecc_bch;
> +			nand->ecc.correct = omap_correct_data_bch;
> +			nand->ecc.calculate = omap_calculate_ecc_bch;
> +			omap_hwecc_init_bch(nand, NAND_ECC_READ);
> +			printf("8-bit BCH HW ECC selected\n");
> +		}
>  #endif
>  	} else {
>  		nand->ecc.mode = NAND_ECC_SOFT;
Andreas Bießmann April 5, 2013, 1:39 p.m. UTC | #2
Dear Thomas Weber,

On 04/05/2013 01:48 PM, Thomas Weber wrote:
> Hello Andreas,
> 
> this patch fixes the reported BUG().
> 
> The output is now:
> 
> -----8<---------
> OMAP3 DevKit8000 # nandecc hw hamming
> 1-bit hamming HW ECC selected
> OMAP3 DevKit8000 # nandecc hw bch8
> Unsupported HW ECC algorithm
> NAND_ECC_NONE selected by board driver. This is not recommended !!
> OMAP3 DevKit8000 #
> ----->8---------

as expected. It is up to the user to choose the correct setup. Now he
has the opportunity to switch back to hamming for example.

Best regards

Andreas Bießmann
diff mbox

Patch

diff --git a/arch/arm/cpu/armv7/omap3/board.c b/arch/arm/cpu/armv7/omap3/board.c
index c6d9a42..b72fadc 100644
--- a/arch/arm/cpu/armv7/omap3/board.c
+++ b/arch/arm/cpu/armv7/omap3/board.c
@@ -328,14 +328,25 @@  void abort(void)
  *****************************************************************************/
 static int do_switch_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 {
-	if (argc != 2)
+	if (argc < 2 || argc > 3)
 		goto usage;
-	if (strncmp(argv[1], "hw", 2) == 0)
-		omap_nand_switch_ecc(1);
-	else if (strncmp(argv[1], "sw", 2) == 0)
-		omap_nand_switch_ecc(0);
-	else
+
+	if (strncmp(argv[1], "hw", 2) == 0) {
+		if (argc == 2) {
+			omap_nand_switch_ecc(1, 1);
+		} else {
+			if (strncmp(argv[2], "hamming", 7) == 0)
+				omap_nand_switch_ecc(1, 1);
+			else if (strncmp(argv[2], "bch8", 4) == 0)
+				omap_nand_switch_ecc(1, 8);
+			else
+				goto usage;
+		}
+	} else if (strncmp(argv[1], "sw", 2) == 0) {
+		omap_nand_switch_ecc(0, 0);
+	} else {
 		goto usage;
+	}
 
 	return 0;
 
@@ -345,9 +356,13 @@  usage:
 }
 
 U_BOOT_CMD(
-	nandecc, 2, 1,	do_switch_ecc,
+	nandecc, 3, 1,	do_switch_ecc,
 	"switch OMAP3 NAND ECC calculation algorithm",
-	"[hw/sw] - Switch between NAND hardware (hw) or software (sw) ecc algorithm"
+	"hw [hamming|bch8] - Switch between NAND hardware 1-bit hamming and"
+	" 8-bit BCH\n"
+	"                           ecc calculation (second parameter may"
+	" be omitted).\n"
+	"nandecc sw               - Switch to NAND software ecc algorithm."
 );
 
 #endif /* CONFIG_NAND_OMAP_GPMC & !CONFIG_SPL_BUILD */
diff --git a/arch/arm/include/asm/arch-am33xx/sys_proto.h b/arch/arm/include/asm/arch-am33xx/sys_proto.h
index 0910a94..c913b5f 100644
--- a/arch/arm/include/asm/arch-am33xx/sys_proto.h
+++ b/arch/arm/include/asm/arch-am33xx/sys_proto.h
@@ -39,5 +39,5 @@  struct gpmc_cs;
 void gpmc_init(void);
 void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base,
 			u32 size);
-void omap_nand_switch_ecc(int);
+void omap_nand_switch_ecc(uint32_t, uint32_t);
 #endif
diff --git a/arch/arm/include/asm/arch-omap3/sys_proto.h b/arch/arm/include/asm/arch-omap3/sys_proto.h
index d60f2ad..dae1312 100644
--- a/arch/arm/include/asm/arch-omap3/sys_proto.h
+++ b/arch/arm/include/asm/arch-omap3/sys_proto.h
@@ -78,7 +78,7 @@  void sr32(void *, u32, u32, u32);
 u32 wait_on_value(u32, u32, void *, u32);
 void sdelay(unsigned long);
 void make_cs1_contiguous(void);
-void omap_nand_switch_ecc(int);
+void omap_nand_switch_ecc(uint32_t, uint32_t);
 void power_init_r(void);
 void dieid_num_r(void);
 void do_omap3_emu_romcode_call(u32 service_id, u32 parameters);
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index c7d4999..3468c78 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -604,13 +604,14 @@  static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
 
 #ifndef CONFIG_SPL_BUILD
 /*
- * omap_nand_switch_ecc - switch the ECC operation b/w h/w ecc and s/w ecc.
- * The default is to come up on s/w ecc
- *
- * @hardware - 1 -switch to h/w ecc, 0 - s/w ecc
+ * omap_nand_switch_ecc - switch the ECC operation between different engines
+ * (h/w and s/w) and different algorithms (hamming and BCHx)
  *
+ * @hardware		- true if one of the HW engines should be used
+ * @eccstrength		- the number of bits that could be corrected
+ *			  (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16)
  */
-void omap_nand_switch_ecc(int32_t hardware)
+void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
 {
 	struct nand_chip *nand;
 	struct mtd_info *mtd;
@@ -628,6 +629,7 @@  void omap_nand_switch_ecc(int32_t hardware)
 	nand->options |= NAND_OWN_BUFFERS;
 
 	/* Reset ecc interface */
+	nand->ecc.mode = NAND_ECC_NONE;
 	nand->ecc.read_page = NULL;
 	nand->ecc.write_page = NULL;
 	nand->ecc.read_oob = NULL;
@@ -637,28 +639,31 @@  void omap_nand_switch_ecc(int32_t hardware)
 	nand->ecc.calculate = NULL;
 
 	/* Setup the ecc configurations again */
-	if (hardware == 1) {
-		nand->ecc.mode = NAND_ECC_HW;
-		nand->ecc.layout = &hw_nand_oob;
-		nand->ecc.size = 512;
-		nand->ecc.bytes = 3;
-		nand->ecc.hwctl = omap_enable_hwecc;
-		nand->ecc.correct = omap_correct_data;
-		nand->ecc.calculate = omap_calculate_ecc;
-		omap_hwecc_init(nand);
-		printf("HW ECC selected\n");
+	if (hardware) {
+		if (eccstrength == 1) {
+			nand->ecc.mode = NAND_ECC_HW;
+			nand->ecc.layout = &hw_nand_oob;
+			nand->ecc.size = 512;
+			nand->ecc.bytes = 3;
+			nand->ecc.hwctl = omap_enable_hwecc;
+			nand->ecc.correct = omap_correct_data;
+			nand->ecc.calculate = omap_calculate_ecc;
+			omap_hwecc_init(nand);
+			printf("1-bit hamming HW ECC selected\n");
+		}
 #ifdef CONFIG_AM33XX
-	} else if (hardware == 2) {
-		nand->ecc.mode = NAND_ECC_HW;
-		nand->ecc.layout = &hw_bch8_nand_oob;
-		nand->ecc.size = 512;
-		nand->ecc.bytes = 14;
-		nand->ecc.read_page = omap_read_page_bch;
-		nand->ecc.hwctl = omap_enable_ecc_bch;
-		nand->ecc.correct = omap_correct_data_bch;
-		nand->ecc.calculate = omap_calculate_ecc_bch;
-		omap_hwecc_init_bch(nand, NAND_ECC_READ);
-		printf("HW BCH8 selected\n");
+		else if (eccstrength == 8) {
+			nand->ecc.mode = NAND_ECC_HW;
+			nand->ecc.layout = &hw_bch8_nand_oob;
+			nand->ecc.size = 512;
+			nand->ecc.bytes = 14;
+			nand->ecc.read_page = omap_read_page_bch;
+			nand->ecc.hwctl = omap_enable_ecc_bch;
+			nand->ecc.correct = omap_correct_data_bch;
+			nand->ecc.calculate = omap_calculate_ecc_bch;
+			omap_hwecc_init_bch(nand, NAND_ECC_READ);
+			printf("8-bit BCH HW ECC selected\n");
+		}
 #endif
 	} else {
 		nand->ecc.mode = NAND_ECC_SOFT;