Message ID | 1365155570-21549-1-git-send-email-andreas.devel@googlemail.com |
---|---|
State | Accepted |
Delegated to: | Tom Rini |
Headers | show |
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;
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 --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;
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(-)