at91: 9x5: Enable PMECC(Programmable Multibit ECC controller) support
v3 cover at91: 9x5: Enable PMECC(Programmable Multibit ECC controller) support
This patch series will add PMECC support for atmel at91sam9x5ek in u-boot.
The NAND flash driver patch is ported from kernel patch. The main different from kernel patch is the modification about registers access part. in this version it via a register structure to access.
It is tested in atmel AT919G25EK board.
Changes since v2:
adapt atmel nand driver to CONFIG_SYS_NAND_SELF_INIT. It use a new
board_nand_init(void) function.
Add README doc for Atmel PMECC.
Add timeout for PMECC read hw status.
refine code according to Andreas and Scott's comments.
Josh Wu (5):
at91: atmel_nand: extract HWECC initialization code into one
function: atmel_hw_nand_init_param().
at91: atmel_nand: remove unused variables.
at91: atmel_nand: Update driver to support Programmable Multibit ECC
controller
at91: 9x5: change SMC config timing that both works for PMECC &
non-PMECC.
at91: 9x5: Enable PMECC for 5series ek board.
board/atmel/at91sam9x5ek/at91sam9x5ek.c | 12 +- doc/README.atmel_pmecc | 44 ++ drivers/mtd/nand/atmel_nand.c | 828 ++++++++++++++++++++++++++++--- drivers/mtd/nand/atmel_nand_ecc.h | 113 +++++ include/configs/at91sam9x5ek.h | 7 + include/nand.h | 2 +- 6 files changed, 938 insertions(+), 68 deletions(-) create mode 100644 doc/README.atmel_pmecc
Signature · 1 line
1.7.9.5
PATCH v3 1/5 at91: atmel_nand: extract HWECC initialization code into one function: atmel_hw_nand_init_param().
This patch
1. extract the hwecc initialization code into one function. It is a preparation for adding atmel PMECC support.
2. enable CONFIG_SYS_NAND_SELF_INIT. Which make us can configurate the ecc parameters between nand_scan_ident() and nand_scan_tail().
---
Changes since v2:
adapt to CONFIG_SYS_NAND_SELF_INIT.
drivers/mtd/nand/atmel_nand.c | 145 ++++++++++++++++++++++++----------------- include/nand.h | 2 +- 2 files changed, 88 insertions(+), 59 deletions(-)
drivers/mtd/nand/atmel_nand.c +87 -58
@@ -232,6 +232,60 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,static void atmel_nand_hwctl (struct mtd_info *mtd,int mode) { } + +int atmel_hwecc_nand_init_param (struct nand_chip *nand,struct mtd_info *mtd) +{ + nand->ecc.mode =NAND_ECC_HW ; + nand->ecc.calculate = atmel_nand_calculate; + nand->ecc.correct = atmel_nand_correct; + nand->ecc.hwctl = atmel_nand_hwctl; + nand->ecc.read_page = atmel_nand_read_page; + nand->ecc.bytes =4 ; + +if (nand->ecc.mode ==NAND_ECC_HW ) { +/* ECC is calculated for the whole page (1 step) */ + nand->ecc.size = mtd->writesize; + +/* set ECC page size and oob layout */ +switch (mtd->writesize) { +case 512 : + nand->ecc.layout = &atmel_oobinfo_small; +ecc_writel (CONFIG_SYS_NAND_ECC_BASE ,MR , +ATMEL_ECC_PAGESIZE_528 ); +break ; +case 1024 : + nand->ecc.layout = &atmel_oobinfo_large; +ecc_writel (CONFIG_SYS_NAND_ECC_BASE ,MR , +ATMEL_ECC_PAGESIZE_1056 ); +break ; +case 2048 : + nand->ecc.layout = &atmel_oobinfo_large; +ecc_writel (CONFIG_SYS_NAND_ECC_BASE ,MR , +ATMEL_ECC_PAGESIZE_2112 ); +break ; +case 4096 : + nand->ecc.layout = &atmel_oobinfo_large; +ecc_writel (CONFIG_SYS_NAND_ECC_BASE ,MR , +ATMEL_ECC_PAGESIZE_4224 ); +break ; +default : +/* page size not handled by HW ECC */ +/* switching back to soft ECC */ + nand->ecc.mode =NAND_ECC_SOFT ; + nand->ecc.calculate =NULL ; + nand->ecc.correct =NULL ; + nand->ecc.hwctl =NULL ; + nand->ecc.read_page =NULL ; + nand->ecc.postpad =0 ; + nand->ecc.prepad =0 ; + nand->ecc.bytes =0 ; +break ; + } + } + +return 0 ; +} +#endif static void at91_nand_hwcontrol(struct mtd_info *mtd,
@@ -267,12 +321,20 @@ static int at91_nand_ready(struct mtd_info *mtd) }#endif -int board_nand_init (struct nand_chip *nand) -{ -#ifdef CONFIG_ATMEL_NAND_HWECC -static int chip_nr =0 ; -struct mtd_info *mtd; +#ifndef CONFIG_SYS_NAND_BASE_LIST +#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }#endif +static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE ]; +static ulong base_addr[CONFIG_SYS_MAX_NAND_DEVICE ] =CONFIG_SYS_NAND_BASE_LIST ; + +int atmel_nand_chip_init (int devnum,ulong base_addr) +{ +int ret; +struct mtd_info *mtd = &nand_info[devnum]; +struct nand_chip *nand = &nand_chip[devnum]; + + mtd->priv = nand; + nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr; nand->ecc.mode =NAND_ECC_SOFT ;#ifdef CONFIG_SYS_NAND_DBW_16
@@ -284,62 +346,29 @@ int board_nand_init(struct nand_chip *nand)#endif nand->chip_delay =20 ; -#ifdef CONFIG_ATMEL_NAND_HWECC - nand->ecc.mode =NAND_ECC_HW ; - nand->ecc.calculate = atmel_nand_calculate; - nand->ecc.correct = atmel_nand_correct; - nand->ecc.hwctl = atmel_nand_hwctl; - nand->ecc.read_page = atmel_nand_read_page; - nand->ecc.bytes =4 ; -#endif + ret =nand_scan_ident (mtd,CONFIG_SYS_NAND_MAX_CHIPS ,NULL ); +if (ret) +return ret;#ifdef CONFIG_ATMEL_NAND_HWECC - mtd = &nand_info[chip_nr++]; - mtd->priv = nand; + ret =atmel_hwecc_nand_init_param (nand, mtd); +#endif +if (ret) +return ret; -/* Detect NAND chips */ -if (nand_scan_ident (mtd,1 ,NULL )) { -printk (KERN_WARNING "NAND Flash not found !\n" ); -return -ENXIO ; - } + ret =nand_scan_tail (mtd); +if (!ret) +nand_register (devnum); -if (nand->ecc.mode ==NAND_ECC_HW ) { -/* ECC is calculated for the whole page (1 step) */ - nand->ecc.size = mtd->writesize; - -/* set ECC page size and oob layout */ -switch (mtd->writesize) { -case 512 : - nand->ecc.layout = &atmel_oobinfo_small; -ecc_writel (CONFIG_SYS_NAND_ECC_BASE ,MR ,ATMEL_ECC_PAGESIZE_528 ); -break ; -case 1024 : - nand->ecc.layout = &atmel_oobinfo_large; -ecc_writel (CONFIG_SYS_NAND_ECC_BASE ,MR ,ATMEL_ECC_PAGESIZE_1056 ); -break ; -case 2048 : - nand->ecc.layout = &atmel_oobinfo_large; -ecc_writel (CONFIG_SYS_NAND_ECC_BASE ,MR ,ATMEL_ECC_PAGESIZE_2112 ); -break ; -case 4096 : - nand->ecc.layout = &atmel_oobinfo_large; -ecc_writel (CONFIG_SYS_NAND_ECC_BASE ,MR ,ATMEL_ECC_PAGESIZE_4224 ); -break ; -default : -/* page size not handled by HW ECC */ -/* switching back to soft ECC */ - nand->ecc.mode =NAND_ECC_SOFT ; - nand->ecc.calculate =NULL ; - nand->ecc.correct =NULL ; - nand->ecc.hwctl =NULL ; - nand->ecc.read_page =NULL ; - nand->ecc.postpad =0 ; - nand->ecc.prepad =0 ; - nand->ecc.bytes =0 ; -break ; - } - } -#endif +return ret; +} -return 0 ; +void board_nand_init (void ) +{ +int i; +for (i =0 ; i <CONFIG_SYS_MAX_NAND_DEVICE ; i++) +if (atmel_nand_chip_init (i, base_addr[i])) +printk (KERN_ERR "atmel_nand: Fail to initialize #%d chip" , + i); } +
include/nand.h +1 -1
@@ -31,7 +31,7 @@*@the same time, so do it here. When all drivers are * converted, this will go away. */ -#if defined(CONFIG_NAND_FSL_ELBC ) +#if defined(CONFIG_NAND_FSL_ELBC ) || defined(CONFIG_NAND_ATMEL )#define CONFIG_SYS_NAND_SELF_INIT #endif
Signature · 1 line
1.7.9.5
PATCH v3 1/5 at91: atmel_nand: extract HWECC initialization code into one function: atmel_hw_nand_init_param().
Dear Josh Wu,
Quoted 6 lines · Josh Wu
This patch
1. extract the hwecc initialization code into one function. It is a preparation for adding atmel PMECC support.
2. enableCONFIG_SYS_NAND_SELF_INIT. Which make us can configurate the ecc parameters betweennand_scan_ident()andnand_scan_tail().Signed-off-by Josh Wu <[email protected]>---
applied to u-boot-atmel/master with two minor changes (read on).
Quoted 111 lines
Changes since v2:
adapt toCONFIG_SYS_NAND_SELF_INIT.drivers/mtd/nand/atmel_nand.c | 145 ++++++++++++++++++++++++----------------- include/nand.h | 2 +- 2 files changed, 88 insertions(+), 59 deletions(-)drivers/mtd/nand/atmel_nand.c +68
-13@@ -232,6 +232,60 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,static void atmel_nand_hwctl (struct mtd_info *mtd,int mode) { } + +int atmel_hwecc_nand_init_param (struct nand_chip *nand,struct mtd_info *mtd) +{ + nand->ecc.mode =NAND_ECC_HW ; + nand->ecc.calculate = atmel_nand_calculate; + nand->ecc.correct = atmel_nand_correct; + nand->ecc.hwctl = atmel_nand_hwctl; + nand->ecc.read_page = atmel_nand_read_page; + nand->ecc.bytes =4 ; + +if (nand->ecc.mode ==NAND_ECC_HW ) { +/* ECC is calculated for the whole page (1 step) */ + nand->ecc.size = mtd->writesize; + +/* set ECC page size and oob layout */ +switch (mtd->writesize) { +case 512 : + nand->ecc.layout = &atmel_oobinfo_small; +ecc_writel (CONFIG_SYS_NAND_ECC_BASE ,MR , +ATMEL_ECC_PAGESIZE_528 ); +break ; +case 1024 : + nand->ecc.layout = &atmel_oobinfo_large; +ecc_writel (CONFIG_SYS_NAND_ECC_BASE ,MR , +ATMEL_ECC_PAGESIZE_1056 ); +break ; +case 2048 : + nand->ecc.layout = &atmel_oobinfo_large; +ecc_writel (CONFIG_SYS_NAND_ECC_BASE ,MR , +ATMEL_ECC_PAGESIZE_2112 ); +break ; +case 4096 : + nand->ecc.layout = &atmel_oobinfo_large; +ecc_writel (CONFIG_SYS_NAND_ECC_BASE ,MR , +ATMEL_ECC_PAGESIZE_4224 ); +break ; +default : +/* page size not handled by HW ECC */ +/* switching back to soft ECC */ + nand->ecc.mode =NAND_ECC_SOFT ; + nand->ecc.calculate =NULL ; + nand->ecc.correct =NULL ; + nand->ecc.hwctl =NULL ; + nand->ecc.read_page =NULL ; + nand->ecc.postpad =0 ; + nand->ecc.prepad =0 ; + nand->ecc.bytes =0 ; +break ; + } + } + +return 0 ; +} +#endif static void at91_nand_hwcontrol(struct mtd_info *mtd,@@ -267,12 +321,20 @@ static int at91_nand_ready(struct mtd_info *mtd) }#endif -int board_nand_init (struct nand_chip *nand) -{ -#ifdef CONFIG_ATMEL_NAND_HWECC -static int chip_nr =0 ; -struct mtd_info *mtd; +#ifndef CONFIG_SYS_NAND_BASE_LIST +#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }#endif +static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE ]; +static ulong base_addr[CONFIG_SYS_MAX_NAND_DEVICE ] =CONFIG_SYS_NAND_BASE_LIST ; + +int atmel_nand_chip_init (int devnum,ulong base_addr) +{ +int ret; +struct mtd_info *mtd = &nand_info[devnum]; +struct nand_chip *nand = &nand_chip[devnum]; + + mtd->priv = nand; + nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr; nand->ecc.mode =NAND_ECC_SOFT ;#ifdef CONFIG_SYS_NAND_DBW_16 @@ -284,62 +346,29 @@ int board_nand_init(struct nand_chip *nand)#endif nand->chip_delay =20 ; -#ifdef CONFIG_ATMEL_NAND_HWECC - nand->ecc.mode =NAND_ECC_HW ; - nand->ecc.calculate = atmel_nand_calculate; - nand->ecc.correct = atmel_nand_correct; - nand->ecc.hwctl = atmel_nand_hwctl; - nand->ecc.read_page = atmel_nand_read_page; - nand->ecc.bytes =4 ; -#endif + ret =nand_scan_ident (mtd,CONFIG_SYS_NAND_MAX_CHIPS ,NULL );
drivers/mtd/nand/atmel_nand.c int board_nand_init(struct nand_chip *nand) · line 357
Quoted 10 lines
drivers/mtd/nand/atmel_nand.c +6
-2+if (ret) +return ret;#ifdef CONFIG_ATMEL_NAND_HWECC - mtd = &nand_info[chip_nr++]; - mtd->priv = nand; + ret =atmel_hwecc_nand_init_param (nand, mtd); +#endif +if (ret) +return ret;
put this return value check into the ifdef, run time tested on at91sam9260ek with HWECC enabled in board config.
Quoted 50 lines
drivers/mtd/nand/atmel_nand.c +5
-42-/* Detect NAND chips */ -if (nand_scan_ident (mtd,1 ,NULL )) { -printk (KERN_WARNING "NAND Flash not found !\n" ); -return -ENXIO ; - } + ret =nand_scan_tail (mtd); +if (!ret) +nand_register (devnum); -if (nand->ecc.mode ==NAND_ECC_HW ) { -/* ECC is calculated for the whole page (1 step) */ - nand->ecc.size = mtd->writesize; - -/* set ECC page size and oob layout */ -switch (mtd->writesize) { -case 512 : - nand->ecc.layout = &atmel_oobinfo_small; -ecc_writel (CONFIG_SYS_NAND_ECC_BASE ,MR ,ATMEL_ECC_PAGESIZE_528 ); -break ; -case 1024 : - nand->ecc.layout = &atmel_oobinfo_large; -ecc_writel (CONFIG_SYS_NAND_ECC_BASE ,MR ,ATMEL_ECC_PAGESIZE_1056 ); -break ; -case 2048 : - nand->ecc.layout = &atmel_oobinfo_large; -ecc_writel (CONFIG_SYS_NAND_ECC_BASE ,MR ,ATMEL_ECC_PAGESIZE_2112 ); -break ; -case 4096 : - nand->ecc.layout = &atmel_oobinfo_large; -ecc_writel (CONFIG_SYS_NAND_ECC_BASE ,MR ,ATMEL_ECC_PAGESIZE_4224 ); -break ; -default : -/* page size not handled by HW ECC */ -/* switching back to soft ECC */ - nand->ecc.mode =NAND_ECC_SOFT ; - nand->ecc.calculate =NULL ; - nand->ecc.correct =NULL ; - nand->ecc.hwctl =NULL ; - nand->ecc.read_page =NULL ; - nand->ecc.postpad =0 ; - nand->ecc.prepad =0 ; - nand->ecc.bytes =0 ; -break ; - } - } -#endif +return ret; +}
drivers/mtd/nand/atmel_nand.c int board_nand_init(struct nand_chip *nand) · line 374
Quoted 10 lines
drivers/mtd/nand/atmel_nand.c +8
-1-return 0 ; +void board_nand_init (void ) +{ +int i; +for (i =0 ; i <CONFIG_SYS_MAX_NAND_DEVICE ; i++) +if (atmel_nand_chip_init (i, base_addr[i])) +printk (KERN_ERR "atmel_nand: Fail to initialize #%d chip" , + i); } +
removed this empty newline at EOF.
Quoted 6 lines
include/nand.h +0
-0
include/nand.h line 37
Quoted 8 lines
include/nand.h +1
-1@@ -31,7 +31,7 @@* at the same time, so do it here. When all drivers are * converted, this will go away. */ -#if defined(CONFIG_NAND_FSL_ELBC ) +#if defined(CONFIG_NAND_FSL_ELBC ) || defined(CONFIG_NAND_ATMEL )#define CONFIG_SYS_NAND_SELF_INIT #endif
Best regards
Andreas Bie?mann
PATCH v3 2/5 at91: atmel_nand: remove unused variables.
In reply to Josh Wu--- drivers/mtd/nand/atmel_nand.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/mtd/nand/atmel_nand.c +1 -2
@@ -79,7 +79,6 @@ static struct nand_ecclayout atmel_oobinfo_small = {static int atmel_nand_calculate (struct mtd_info *mtd,const u_char *dat,unsigned char *ecc_code) { -struct nand_chip *nand_chip = mtd->priv;unsigned int ecc_value;/* get the first 2 ECC bytes */
@@ -167,7 +166,7 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *isnull) {struct nand_chip *nand_chip = mtd->priv; -unsigned int ecc_status, ecc_parity, ecc_mode; +unsigned int ecc_status;unsigned int ecc_word, ecc_bit;/* get the status from the Status Register */
Signature · 1 line
1.7.9.5
PATCH v3 2/5 at91: atmel_nand: remove unused variables.
Dear Josh Wu,
Quoted 3 lines · Josh Wu
Signed-off-by Josh Wu <[email protected]>Acked-by Scott Wood <[email protected]>---
applied to u-boot-atmel/master, thanks!
Best regards
Andreas Bie?mann
PATCH v3 3/5 at91: atmel_nand: Update driver to support Programmable Multibit ECC controller
In reply to Josh WuThe Programmable Multibit ECC (PMECC) controller is a programmable binary BCH(Bose, Chaudhuri and Hocquenghem) encoder and decoder. This controller can be used to support both SLC and MLC NAND Flash devices. It supports to generate ECC to correct 2, 4, 8, 12 or 24 bits of error per sector of data.
To use PMECC in this driver, the user needs to set the PMECC correction capability, the sector size and ROM lookup table offsets in board config file.
This driver is ported from Linux kernel atmel_nand PMECC patch. The main difference is in this version it uses registers structure access hardware instead of using macros. It is tested in 9x5 serial boards.
---
Changes since v2:
add timeout when read hardware register.
add README document for atmel pmecc.
according to Scott and Andreas' suggestion, refined the pmecc_get_sigma()
function and add more comments for the function.
doc/README.atmel_pmecc | 44 +++ drivers/mtd/nand/atmel_nand.c | 680 ++++++++++++++++++++++++++++++++++++- drivers/mtd/nand/atmel_nand_ecc.h | 113 ++++++ 3 files changed, 836 insertions(+), 1 deletion(-) create mode 100644 doc/README.atmel_pmecc
doc/README.atmel_pmecc new file +44 -0
@@ -0,0 +1,44 @@ +How to enable PMECC(Programmable Multibit ECC) for nand on Atmel SoCs +----------------------------------------------------------- +2012-08-22 Josh Wu <[email protected]> + +The Programmable Multibit ECC (PMECC) controller is a programmable binary +BCH(Bose, Chaudhuri and Hocquenghem) encoder and decoder. This controller +can be used to support both SLC and MLC NAND Flash devices. It supports to +generate ECC to correct 2, 4, 8, 12 or 24 bits of error per sector (512 or +1024 bytes) of data. + +Following Atmel AT91 products support PMECC. +- AT91SAM9X25, X35, G25, G15, G35 (tested) +- AT91SAM9N12 (not tested, Should work) + +As soon as your nand flash software ECC works, you can enable PMECC. + +To use PMECC in this driver, the user needs to set: + 1. the PMECC correction error bits capability: CONFIG_PMECC_CAP. + It can be 2, 4, 8, 12 or 24. + 2. The PMECC sector size: CONFIG_PMECC_SECTOR_SIZE. + It only can be 512 or 1024. + 3. The PMECC index lookup table's offsets in ROM code: CONFIG_PMECC_INDEX_TABLE_OFFSET. + In the chip datasheet section "Boot Stragegies", you can find + two Galois Field Table in the ROM code. One table is for 512-bytes + sector. Another is for 1024-byte sector. Each Galois Field includes + two sub-table: indext table & alpha table. + In the beginning of each Galois Field Table is the index table, + Alpha table is in the following. + So the index table's offset is same as the Galois Field Table. + + Please set CONFIG_PMECC_INDEX_TABLE_OFFSET correctly according the + Galois Field Table's offset base on the sector size you used. + +Take AT91SAM9X5EK as an example, the board definition file likes: + +/* PMECC & PMERRLOC */ +#define CONFIG_ATMEL_NAND_HWECC 1 +#define CONFIG_ATMEL_NAND_HW_PMECC 1 +#define CONFIG_PMECC_CAP 2 +#define CONFIG_PMECC_SECTOR_SIZE 512 +#define CONFIG_PMECC_INDEX_TABLE_OFFSET 0x8000 + +NOTE: If you use 1024 as the sector size, then need set 0x10000 as the + CONFIG_PMECC_INDEX_TABLE_OFFSET
drivers/mtd/nand/atmel_nand.c +679 -1
712 lines not on this page · raw message
drivers/mtd/nand/atmel_nand_ecc.h +113 -0
117 lines not on this page · raw message
Signature · 1 line
1.7.9.5
PATCH v3 3/5 at91: atmel_nand: Update driver to support Programmable Multibit ECC controller
Dear Josh Wu,
Quoted 8 lines · Josh Wu
The Programmable Multibit ECC (PMECC) controller is a programmable binary
BCH(Bose, Chaudhuri and Hocquenghem)encoder and decoder. This controller can be used to support both SLC and MLC NAND Flash devices. It supports to generate ECC to correct 2, 4, 8, 12 or 24 bits of error per sector of data.To use PMECC in this driver, the user needs to set the PMECC correction capability, the sector size and ROM lookup table offsets in board config file.
Quoted 6 lines
This driver is ported from Linux kernel
atmel_nandPMECC patch. The main difference is in this version it uses registers structure access hardware instead of using macros. It is tested in 9x5 serial boards.Signed-off-by Josh Wu <[email protected]>---
applied to u-boot-atmel/master (slightly modified due to required rebase cause of change in 1/5), thanks!
Best regards
Andreas Bie?mann
PATCH v3 4/5 at91: 9x5: change SMC config timing that both works for PMECC & non-PMECC.
In reply to Josh Wu--- board/atmel/at91sam9x5ek/at91sam9x5ek.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
board/atmel/at91sam9x5ek/at91sam9x5ek.c +6 -6
@@ -65,13 +65,13 @@ static void at91sam9x5ek_nand_hw_init(void)writel (csa, &matrix->ebicsa);/* Configure SMC CS3 for NAND/SmartMedia */ -writel (AT91_SMC_SETUP_NWE (2 ) |AT91_SMC_SETUP_NCS_WR (0 ) | -AT91_SMC_SETUP_NRD (2 ) |AT91_SMC_SETUP_NCS_RD (0 ), +writel (AT91_SMC_SETUP_NWE (1 ) |AT91_SMC_SETUP_NCS_WR (0 ) | +AT91_SMC_SETUP_NRD (1 ) |AT91_SMC_SETUP_NCS_RD (0 ), &smc->cs[3 ].setup); -writel (AT91_SMC_PULSE_NWE (4 ) |AT91_SMC_PULSE_NCS_WR (4 ) | -AT91_SMC_PULSE_NRD (4 ) |AT91_SMC_PULSE_NCS_RD (4 ), +writel (AT91_SMC_PULSE_NWE (3 ) |AT91_SMC_PULSE_NCS_WR (5 ) | +AT91_SMC_PULSE_NRD (4 ) |AT91_SMC_PULSE_NCS_RD (6 ), &smc->cs[3 ].pulse); -writel (AT91_SMC_CYCLE_NWE (7 ) |AT91_SMC_CYCLE_NRD (7 ), +writel (AT91_SMC_CYCLE_NWE (5 ) |AT91_SMC_CYCLE_NRD (6 ), &smc->cs[3 ].cycle); writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_WM_NWE | AT91_SMC_MODE_EXNW_DISABLE |
@@ -80,7 +80,7 @@ static void at91sam9x5ek_nand_hw_init(void)#else /* CONFIG_SYS_NAND_DBW_8 */ AT91_SMC_MODE_DBW_8 | #endif -AT91_SMC_MODE_TDF_CYCLE (3 ), +AT91_SMC_MODE_TDF_CYCLE (1 ), &smc->cs[3].mode);writel (1 <<ATMEL_ID_PIOCD , &pmc->pcer);
Signature · 1 line
1.7.9.5
PATCH v3 4/5 at91: 9x5: change SMC config timing that both works for PMECC & non-PMECC.
Hi Josh,
Quoted 29 lines · Josh Wu
Signed-off-by Josh Wu <[email protected]>--- board/atmel/at91sam9x5ek/at91sam9x5ek.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)board/atmel/at91sam9x5ek/at91sam9x5ek.c +5
-5@@ -65,13 +65,13 @@ static void at91sam9x5ek_nand_hw_init(void)writel (csa, &matrix->ebicsa);/* Configure SMC CS3 for NAND/SmartMedia */ -writel (AT91_SMC_SETUP_NWE (2 ) |AT91_SMC_SETUP_NCS_WR (0 ) | -AT91_SMC_SETUP_NRD (2 ) |AT91_SMC_SETUP_NCS_RD (0 ), +writel (AT91_SMC_SETUP_NWE (1 ) |AT91_SMC_SETUP_NCS_WR (0 ) | +AT91_SMC_SETUP_NRD (1 ) |AT91_SMC_SETUP_NCS_RD (0 ), &smc->cs[3 ].setup); -writel (AT91_SMC_PULSE_NWE (4 ) |AT91_SMC_PULSE_NCS_WR (4 ) | -AT91_SMC_PULSE_NRD (4 ) |AT91_SMC_PULSE_NCS_RD (4 ), +writel (AT91_SMC_PULSE_NWE (3 ) |AT91_SMC_PULSE_NCS_WR (5 ) | +AT91_SMC_PULSE_NRD (4 ) |AT91_SMC_PULSE_NCS_RD (6 ), &smc->cs[3 ].pulse); -writel (AT91_SMC_CYCLE_NWE (7 ) |AT91_SMC_CYCLE_NRD (7 ), +writel (AT91_SMC_CYCLE_NWE (5 ) |AT91_SMC_CYCLE_NRD (6 ), &smc->cs[3 ].cycle); writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_WM_NWE | AT91_SMC_MODE_EXNW_DISABLE |
board/atmel/at91sam9x5ek/at91sam9x5ek.c static void at91sam9x5ek_nand_hw_init(void) · line 84
Quoted 6 lines
board/atmel/at91sam9x5ek/at91sam9x5ek.c +1
-1@@ -80,7 +80,7 @@ static void at91sam9x5ek_nand_hw_init(void)#else /* CONFIG_SYS_NAND_DBW_8 */ AT91_SMC_MODE_DBW_8 | #endif -AT91_SMC_MODE_TDF_CYCLE (3 ), +AT91_SMC_MODE_TDF_CYCLE (1 ), &smc->cs[3].mode);
Test these parameters for NAND using software ECC. It works well.
Quoted 3 lines
board/atmel/at91sam9x5ek/at91sam9x5ek.c +0
-0writel (1 <<ATMEL_ID_PIOCD , &pmc->pcer);
PATCH v3 4/5 at91: 9x5: change SMC config timing that both works for PMECC & non-PMECC.
In reply to Josh WuDear Josh Wu,
Quoted 2 lines · Josh Wu
Signed-off-by Josh Wu <[email protected]>---
applied to u-boot-atmel/master, thnaks!
Best regards
Andreas Bie?mann
PATCH v3 5/5 at91: 9x5: Enable PMECC for 5series ek board.
In reply to Josh Wu--- include/configs/at91sam9x5ek.h | 7 +++++++ 1 file changed, 7 insertions(+)
include/configs/at91sam9x5ek.h +7 -0
@@ -120,6 +120,13 @@#define CONFIG_SYS_NAND_ENABLE_PIN AT91_PIN_PD4#define CONFIG_SYS_NAND_READY_PIN AT91_PIN_PD5 +/* PMECC & PMERRLOC */ +#define CONFIG_ATMEL_NAND_HWECC 1 +#define CONFIG_ATMEL_NAND_HW_PMECC 1 +#define CONFIG_PMECC_CAP 2 +#define CONFIG_PMECC_SECTOR_SIZE 512 +#define CONFIG_PMECC_INDEX_TABLE_OFFSET 0x8000 +#define CONFIG_MTD_DEVICE #define CONFIG_CMD_MTDPARTS #define CONFIG_MTD_PARTITIONS
Signature · 1 line
1.7.9.5
PATCH v3 5/5 at91: 9x5: Enable PMECC for 5series ek board.
Dear Josh Wu,
Quoted 2 lines · Josh Wu
Signed-off-by Josh Wu <[email protected]>---
applied to u-boot-atmel/master, thanks!
Best regards
Andreas Bie?mann
v3 cover at91: 9x5: Enable PMECC(Programmable Multibit ECC controller) support
In reply to Josh WuHi, All
Is any feedback for this rev3 patch series.
Best Regards,
Josh Wu
Quoted 33 lines · Josh Wu
This patch series will add PMECC support for atmel at91sam9x5ek in u-boot.
The NAND flash driver patch is ported from kernel patch. The main different from kernel patch is the modification about registers access part. in this version it via a register structure to access.
It is tested in atmel AT919G25EK board.
Changes since v2:
adapt atmel nand driver toCONFIG_SYS_NAND_SELF_INIT. It use a new
board_nand_init(void)function.
Add README doc for Atmel PMECC.
Add timeout for PMECC read hw status.
refine code according to Andreas and Scott's comments.Josh Wu (5):
at91:atmel_nand: extract HWECC initialization code into one
function:atmel_hw_nand_init_param().
at91:atmel_nand: remove unused variables.
at91:atmel_nand: Update driver to support Programmable Multibit ECC
controller
at91: 9x5: change SMC config timing that both works for PMECC &
non-PMECC.
at91: 9x5: Enable PMECC for 5series ek board.board/atmel/at91sam9x5ek/at91sam9x5ek.c | 12 +- doc/README.atmel_pmecc | 44 ++ drivers/mtd/nand/atmel_nand.c | 828 ++++++++++++++++++++++++++++--- drivers/mtd/nand/atmel_nand_ecc.h | 113 +++++ include/configs/at91sam9x5ek.h | 7 + include/nand.h | 2 +- 6 files changed, 938 insertions(+), 68 deletions(-)create mode 100644 doc/README.atmel_pmecc
v3 cover at91: 9x5: Enable PMECC(Programmable Multibit ECC controller) support
Dear Josh Wu,
Quoted 3 lines · Josh Wu
Hi, All
Is any feedback for this rev3 patch series.
sorry, had no time yet, I will send feedback this evening (CEST).
Best regards
Andreas Bie?mann