Bring NAND support to Nintendo NES Classic
Subsystems (4)
Miquel Raynal
maintainerv3 cover Bring NAND support to Nintendo NES Classic
Hello,
This series first adds fixes and enhancements to sunxi NAND drivers (SPL and U-Boot). Once this is done, the SPL NAND driver is converted to use PIO instead of DMA with the goal to support all SoCs with this IP without the need for DMA-related code. Finally, NAND support is added to Nintendo NES Classic through Kconfig and DT additions.
Thanks,
Miquèl
Changes since v2:
=================
- Added Boris and Maxime Acked-by tags.
- Removed extra space in nand_reset_column()
- Fixed the useless wait period on failure in nand_change_column().
- Changed the title "sunxi: allow NAND support to be compiled for..." (removed the "in SPL" precision which is wrong).
- Enbraced the deassertion of the reset line by #if statements about the SoCs in use. Wolfgang Denk made a comment on my proposal but I could not find a better solution, so I kept it for now.
- s/alwinner,[pin,functions]/[pin,functions]/ in the DT.
- Change Alwinner-specific parts in the SPL to generic sentences.
Changes since v1:
=================
All:
----
- Enhance all commit messages.
- Rebased on top of master branch (I should have done that earlier but I forgot I was on an old revision).
Fix binman_sym output check
---------------------------
- SPL seems to be broken for a few weeks when using raw NAND, fix it by changing the error condition.
Fix strength
------------
- Add comment explaining the added line and moved the line for clarification on why it is needed.
- Add forgotten Boris' Suggested-by tag.
Fix second case of modulo by zero error
----------------------------------------
- Added a reference to the first occurence of this issue.
Allow SPL to be compiled for sun8i platforms
--------------------------------------------
- This commit is not about compiling the SPL, but the NAND support in the SPL, as corrected by Maxime.
Enhancements and cleaning
-------------------------
- Patch split into several logical chunks, as requested.
- Removed useless udelay(1), that was added for debugging purpose.
- Introduced the nand_exec_cmd() helper to mutualize code one step further.
- Add an udelay(1) after changing the column to respect the minimum tCCS delay (Change Column Setup time).
- Canceled moving to global scope the ecc_strength array.
Use PIO instead of DMA
----------------------
- Change commit message/title.
- Cancel removing NFC related definitions: they can be useful as the this IP is quite under-documented.
- Merge nand_reset_column and nand_change_column (in another patch).
- Moved the copy of the data after the check of the ECC status.
- ECC chunks are read manually, return if the first chunk is empty only (needed for configuration research), otherwise it should not be treated as an error.
Add NAND node to sun8i
----------------------
- U-Boot master branch already has this node, remove the patch.
Enable NAND on NES classic
--------------------------
- Change the DT cells size from 2 to 1.
Add NAND support for NES classic
--------------------------------
- Split in several patches, moving SPL_NAND_SUPPORT and NAND_SUNXI out of the defconfig files (NES and CHIP pro) to be automatically selected depending on NAND_SUNXI and ARCH_SUNXI.
- Moved the NAND parameters to Kconfig (only for SUNXI because the tool did not work as expected, maybe due to some definitions that are not "numbers" but multiplications and sometimes use other definitions (NAND page size, 2K_SZ, etc).
Miquel Raynal (20):
spl: fix binman_sym output check
mtd: nand: sunxi: fix ECC strength choice
spl: nand: sunxi: fix second case of modulo by zero error
spl: nand: sunxi: fix typo on register name
spl: nand: sunxi: introduce the nand_wait_int() helper
spl: nand: sunxi: introduce the nand_wait_cmd_fifo_empty() helper
spl: nand: sunxi: add missing status clear
spl: nand: sunxi: create an helper to handle command execution
spl: nand: sunxi: ensure enough time has passed after changing the
column
spl: nand: sunxi: make the reset column helper more generic
sunxi: spl: deassert the NAND controller reset line
spl: nand: sunxi: declare the ecc_bytes array globally
spl: nand: sunxi: use PIO instead of DMA
sunxi: spl: remove DMA related settings of the NAND controller
sunxi: allow NAND support to be compiled for sun8i platforms
sunxi: dts: enable NAND on NES classic
sunxi: automatically select SPL_NAND_SUPPORT in Kconfig
sunxi: make NAND_SUNXI use ARCH_SUNXI as default in Kconfig
sunxi: move the NAND parameters to Kconfig
configs: add NAND support for NES Classic
arch/arm/dts/sun8i-a23-a33.dtsi | 17 ++ .../dts/sun8i-r16-nintendo-nes-classic-edition.dts | 14 ++ arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 6 + board/sunxi/board.c | 7 +- common/spl/spl.c | 10 +- configs/CHIP_pro_defconfig | 6 +- configs/Nintendo_NES_Classic_Edition_defconfig | 4 + drivers/mtd/nand/Kconfig | 26 ++- drivers/mtd/nand/sunxi_nand.c | 8 +- drivers/mtd/nand/sunxi_nand_spl.c | 242 ++++++++++----------- 10 files changed, 208 insertions(+), 132 deletions(-)
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 1/20 spl: fix binman_sym output check
A previous commit introduced the use of binman in the SPL.
After the binman_sym call over the 'pos' symbol, the output value is checked against BINMAN_SYM_MISSING (-1UL). According to the documentation (tools/binman/README), when it comes to the 'pos' attribute:
pos:
This sets the position of an entry within the image. The first byte of the image is normally at position 0. If 'pos' is not provided, binman sets it to the end of the previous region, or the start of the image's entry area (normally 0) if there is no previous region.
So instead of checking if the return value is BINMAN_SYM_MISSING, we should also check if the value is not null.
The failure happens when using both the SPL file and the U-Boot file independently instead of the concatenated file (SPL + padding + U-Boot). This is because the U-Boot binary file alone does not have the U-Boot header while it is present in the concatenation file. Not having the header forces the SPL to discover where it should load U-Boot. The binman_sym call is supposed to do that but fails. Because of the wrong check, the destination address was set to 0 while it should have been somewhere in RAM. This, obviously, stalls the board.
--- common/spl/spl.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
common/spl/spl.c +8 -2
@@ -127,8 +127,14 @@ void spl_set_header_raw_uboot(struct spl_image_info *spl_image)ulong u_boot_pos =binman_sym (ulong, u_boot_any, pos); spl_image->size =CONFIG_SYS_MONITOR_LEN ; -if (u_boot_pos !=BINMAN_SYM_MISSING ) { -/* biman does not support separate entry addresses at present */ + +/* +* Binman error cases: address of the end of the previous region or the +* start of the image's entry area (usually 0) if there is no previous +* region. +*/ +if (u_boot_pos && u_boot_pos !=BINMAN_SYM_MISSING ) { +/* Binman does not support separated entry addresses */ spl_image->entry_point = u_boot_pos; spl_image->load_addr = u_boot_pos; }else {
Signature · 1 line
2.14.1
PATCH v3 1/20 spl: fix binman_sym output check
Hi Simon,
Quoted 26 lines · Miquel Raynal
A previous commit introduced the use of binman in the SPL.
After the
binman_symcall over the 'pos' symbol, the output value is checked againstBINMAN_SYM_MISSING(-1UL). According to the documentation (tools/binman/README), when it comes to the 'pos' attribute:pos:
This sets the position of an entry within the image. The first byte of the image is normally at position 0. If 'pos' is not provided, binman sets it to the end of the previous region, or the start of the image's entry area (normally 0) if there is no previous region.So instead of checking if the return value is
BINMAN_SYM_MISSING, we should also check if the value is not null.The failure happens when using both the SPL file and the U-Boot file independently instead of the concatenated file (SPL + padding + U-Boot). This is because the U-Boot binary file alone does not have the U-Boot header while it is present in the concatenation file. Not having the header forces the SPL to discover where it should load U-Boot. The
binman_symcall is supposed to do that but fails. Because of the wrong check, the destination address was set to 0 while it should have been somewhere in RAM. This, obviously, stalls the board.
Quoted 2 lines
Fixes 8bee2d251afb ("binman: Add binman symbol support to SPL")Signed-off-by Miquel Raynal <[email protected]>
I'm not sure why it wasn't sent to you, but could you please have a look at that patch?
Thanks!
Maxime
Quoted 28 lines
--- common/spl/spl.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)common/spl/spl.c +8
-2@@ -127,8 +127,14 @@ void spl_set_header_raw_uboot(struct spl_image_info *spl_image)ulong u_boot_pos =binman_sym (ulong, u_boot_any, pos); spl_image->size =CONFIG_SYS_MONITOR_LEN ; -if (u_boot_pos !=BINMAN_SYM_MISSING ) { -/* biman does not support separate entry addresses at present */ + +/* +* Binman error cases: address of the end of the previous region or the +* start of the image's entry area (usually 0) if there is no previous +* region. +*/ +if (u_boot_pos && u_boot_pos !=BINMAN_SYM_MISSING ) { +/* Binman does not support separated entry addresses */ spl_image->entry_point = u_boot_pos; spl_image->load_addr = u_boot_pos; }else {Signature · 1 line
2.14.1
Signature · 10 lines
Maxime Ripard, Bootlin (formerly Free Electrons) Embedded Linux and Kernel engineering https://bootlin.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180313/94202066/attachment.sig>
PATCH v3 1/20 spl: fix binman_sym output check
Quoted 29 lines · Maxime Ripard
Hi Simon,
Quoted 26 lines · Miquel Raynal
A previous commit introduced the use of binman in the SPL.
After the
binman_symcall over the 'pos' symbol, the output value is checked againstBINMAN_SYM_MISSING(-1UL). According to the documentation (tools/binman/README), when it comes to the 'pos' attribute:pos:
This sets the position of an entry within the image. The first byte of the image is normally at position 0. If 'pos' is not provided, binman sets it to the end of the previous region, or the start of the image's entry area (normally 0) if there is no previous region.So instead of checking if the return value is
BINMAN_SYM_MISSING, we should also check if the value is not null.The failure happens when using both the SPL file and the U-Boot file independently instead of the concatenated file (SPL + padding + U-Boot). This is because the U-Boot binary file alone does not have the U-Boot header while it is present in the concatenation file. Not having the header forces the SPL to discover where it should load U-Boot. The
binman_symcall is supposed to do that but fails. Because of the wrong check, the destination address was set to 0 while it should have been somewhere in RAM. This, obviously, stalls the board.
Quoted 5 lines
Quoted 2 lines
Fixes 8bee2d251afb ("binman: Add binman symbol support to SPL")Signed-off-by Miquel Raynal <[email protected]>I'm not sure why it wasn't sent to you, but could you please have a look at that patch?
Ping?
Signature · 3 lines
Maxime Ripard, Bootlin (formerly Free Electrons) Embedded Linux and Kernel engineering https://bootlin.com
PATCH v3 1/20 spl: fix binman_sym output check
In reply to Maxime RipardQuoted 29 lines · Maxime Ripard
Hi Simon,
Quoted 26 lines · Miquel Raynal
A previous commit introduced the use of binman in the SPL.
After the
binman_symcall over the 'pos' symbol, the output value is checked againstBINMAN_SYM_MISSING(-1UL). According to the documentation (tools/binman/README), when it comes to the 'pos' attribute:pos:
This sets the position of an entry within the image. The first byte of the image is normally at position 0. If 'pos' is not provided, binman sets it to the end of the previous region, or the start of the image's entry area (normally 0) if there is no previous region.So instead of checking if the return value is
BINMAN_SYM_MISSING, we should also check if the value is not null.The failure happens when using both the SPL file and the U-Boot file independently instead of the concatenated file (SPL + padding + U-Boot). This is because the U-Boot binary file alone does not have the U-Boot header while it is present in the concatenation file. Not having the header forces the SPL to discover where it should load U-Boot. The
binman_symcall is supposed to do that but fails. Because of the wrong check, the destination address was set to 0 while it should have been somewhere in RAM. This, obviously, stalls the board.
Quoted 12 lines
Quoted 2 lines
Fixes 8bee2d251afb ("binman: Add binman symbol support to SPL")Signed-off-by Miquel Raynal <[email protected]>I'm not sure why it wasn't sent to you, but could you please have a look at that patch?
Thanks!
MaximeQuoted 3 lines
--- common/spl/spl.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
Miquel Raynal
maintainerPATCH v3 2/20 mtd: nand: sunxi: fix ECC strength choice
In reply to Miquel RaynalWhen the requested ECC strength does not exactly match the strengths supported by the ECC engine, the driver is selecting the closest strength meeting the 'selected_strength > requested_strength' constraint. Fix the fact that, in this particular case, ecc->strength value was not updated to match the 'selected_strength'.
For instance, one can encounter this issue when no ECC requirement is filled in the device tree while the NAND chip minimum requirement is not a strength/step_size combo natively supported by the ECC engine.
--- drivers/mtd/nand/sunxi_nand.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/mtd/nand/sunxi_nand.c +7 -1
@@ -1407,8 +1407,14 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,/* Add ECC info retrieval from DT */ for (i =0 ; i <ARRAY_SIZE (strengths); i++) { -if (ecc->strength <= strengths[i]) +if (ecc->strength <= strengths[i]) { +/* +* Update ecc->strength value with the actual strength +* that will be used by the ECC engine. +*/ + ecc->strength = strengths[i];break ; + } }if (i >=ARRAY_SIZE (strengths)) {
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 3/20 spl: nand: sunxi: fix second case of modulo by zero error
In reply to Miquel RaynalIn the nand_read_buffer() step, the seed is calculated by doing a modulo by conf->nseeds which is always zero when not using the randomizer (most of SLC NANDs).
This situation turns out to lead to a run time freeze with certain toolchains.
Derive this seed only when the randomizer is enabled (and conf->nseeds logically not zero), exactly like what has been done before with an identical situation, see commit ea3f750c73e3 ("nand: sunxi: Fix modulo by zero error").
--- drivers/mtd/nand/sunxi_nand_spl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/mtd/nand/sunxi_nand_spl.c +3 -2
@@ -475,11 +475,12 @@ static int nand_detect_config(struct nfc_config *conf, u32 offs, void *dest)static int nand_read_buffer (struct nfc_config *conf,uint32_t offs,unsigned int size,void *dest) { -int first_seed, page, ret; +int first_seed =0 , page, ret; size =ALIGN (size, conf->page_size); page = offs / conf->page_size; - first_seed = page % conf->nseeds; +if (conf->randomize) + first_seed = page % conf->nseeds;for (; size; size -= conf->page_size) {if (nand_load_page (conf, offs))
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 4/20 spl: nand: sunxi: fix typo on register name
In reply to Miquel RaynalChange NFC_SEND_ADR to NFC_SEND_ADDR.
--- drivers/mtd/nand/sunxi_nand_spl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/mtd/nand/sunxi_nand_spl.c +3 -3
@@ -55,7 +55,7 @@#define NFC_ADDR_NUM_OFFSET 16 -#define NFC_SEND_ADR (1 << 19) +#define NFC_SEND_ADDR (1 << 19)#define NFC_ACCESS_DIR (1 << 20)#define NFC_DATA_TRANS (1 << 21)#define NFC_SEND_CMD1 (1 << 22)
@@ -208,7 +208,7 @@ static int nand_load_page(const struct nfc_config *conf, u32 offs)writel ((page >>16 ) &0xFF ,SUNXI_NFC_BASE +NFC_ADDR_HIGH );writel (NFC_ST_CMD_INT_FLAG ,SUNXI_NFC_BASE +NFC_ST );writel (NFC_SEND_CMD1 |NFC_SEND_CMD2 |NFC_RAW_CMD |NFC_WAIT_FLAG | - ((conf->addr_cycles -1 ) <<NFC_ADDR_NUM_OFFSET ) |NFC_SEND_ADR , + ((conf->addr_cycles -1 ) <<NFC_ADDR_NUM_OFFSET ) |NFC_SEND_ADDR ,SUNXI_NFC_BASE +NFC_CMD ); if (!check_value(SUNXI_NFC_BASE + NFC_ST, NFC_ST_CMD_INT_FLAG,
@@ -228,7 +228,7 @@ static int nand_reset_column(void) SUNXI_NFC_BASE + NFC_RCMD_SET);writel (0 ,SUNXI_NFC_BASE +NFC_ADDR_LOW );writel (NFC_SEND_CMD1 |NFC_SEND_CMD2 |NFC_RAW_CMD | - (1 <<NFC_ADDR_NUM_OFFSET ) |NFC_SEND_ADR |NFC_CMD_RNDOUT , + (1 <<NFC_ADDR_NUM_OFFSET ) |NFC_SEND_ADDR |NFC_CMD_RNDOUT ,SUNXI_NFC_BASE +NFC_CMD ); if (!check_value(SUNXI_NFC_BASE + NFC_ST, NFC_ST_CMD_INT_FLAG,
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 5/20 spl: nand: sunxi: introduce the nand_wait_int() helper
In reply to Miquel RaynalThe pattern of polling on a status register until a bit is set or a timeout occurs is repeated multiple times in the driver. Mutualize the code by introducing the nand_wait_int() helper that does wait for the bit to flip or returns an error in case of timeout.
--- drivers/mtd/nand/sunxi_nand_spl.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-)
drivers/mtd/nand/sunxi_nand_spl.c +14 -20
@@ -155,6 +155,17 @@ static inline int check_value_negated(int offset, int unexpected_bits,return check_value_inner (offset, unexpected_bits, timeout_us,1 ); } +static int nand_wait_int (void ) +{ +if (!check_value (SUNXI_NFC_BASE +NFC_ST ,NFC_ST_CMD_INT_FLAG , +DEFAULT_TIMEOUT_US )) { +printf ("nand: timeout waiting for interruption\n" ); +return -ETIMEDOUT ; + } + +return 0 ; +} +void nand_init (void ) {uint32_t val;
@@ -176,12 +187,7 @@ void nand_init(void)writel (NFC_SEND_CMD1 |NFC_WAIT_FLAG |NAND_CMD_RESET ,SUNXI_NFC_BASE +NFC_CMD ); -if (!check_value (SUNXI_NFC_BASE +NFC_ST ,NFC_ST_CMD_INT_FLAG , -DEFAULT_TIMEOUT_US )) { -printf ("Error timeout waiting for nand reset\n" ); -return ; - } -writel (NFC_ST_CMD_INT_FLAG ,SUNXI_NFC_BASE +NFC_ST ); +nand_wait_int (); }static void nand_apply_config (const struct nfc_config *conf)
@@ -211,13 +217,7 @@ static int nand_load_page(const struct nfc_config *conf, u32 offs) ((conf->addr_cycles -1 ) <<NFC_ADDR_NUM_OFFSET ) |NFC_SEND_ADDR , SUNXI_NFC_BASE + NFC_CMD); -if (!check_value (SUNXI_NFC_BASE +NFC_ST ,NFC_ST_CMD_INT_FLAG , -DEFAULT_TIMEOUT_US )) { -printf ("Error while initializing dma interrupt\n" ); -return -EIO ; - } - -return 0 ; +return nand_wait_int (); }static int nand_reset_column (void )
@@ -231,13 +231,7 @@ static int nand_reset_column(void) (1 <<NFC_ADDR_NUM_OFFSET ) |NFC_SEND_ADDR |NFC_CMD_RNDOUT , SUNXI_NFC_BASE + NFC_CMD); -if (!check_value (SUNXI_NFC_BASE +NFC_ST ,NFC_ST_CMD_INT_FLAG , -DEFAULT_TIMEOUT_US )) { -printf ("Error while initializing dma interrupt\n" ); -return -1 ; - } - -return 0 ; +return nand_wait_int (); } static int nand_read_page(const struct nfc_config *conf, u32 offs,
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 6/20 spl: nand: sunxi: introduce the nand_wait_cmd_fifo_empty() helper
In reply to Miquel RaynalOne bit in the control registers indicates if the NAND controller is ready to receive a new command. Otherwise, the command FIFO is full and we should wait for this bit to flip. It then states that the last command has been processed and the FIFO is now free to welcome another command.
Add this sanity check before starting any new command.
--- drivers/mtd/nand/sunxi_nand_spl.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
drivers/mtd/nand/sunxi_nand_spl.c +19 -0
@@ -155,6 +155,17 @@ static inline int check_value_negated(int offset, int unexpected_bits,return check_value_inner (offset, unexpected_bits, timeout_us,1 ); } +static int nand_wait_cmd_fifo_empty (void ) +{ +if (!check_value_negated (SUNXI_NFC_BASE +NFC_ST ,NFC_ST_CMD_FIFO_STAT , +DEFAULT_TIMEOUT_US )) { +printf ("nand: timeout waiting for empty cmd FIFO\n" ); +return -ETIMEDOUT ; + } + +return 0 ; +} + static int nand_wait_int(void) { if (!check_value(SUNXI_NFC_BASE + NFC_ST, NFC_ST_CMD_INT_FLAG,
@@ -183,6 +194,8 @@ void nand_init(void) }/* reset NAND */ +nand_wait_cmd_fifo_empty (); +writel (NFC_ST_CMD_INT_FLAG ,SUNXI_NFC_BASE +NFC_ST );writel (NFC_SEND_CMD1 |NFC_WAIT_FLAG |NAND_CMD_RESET ,SUNXI_NFC_BASE +NFC_CMD );
@@ -194,6 +207,8 @@ static void nand_apply_config(const struct nfc_config *conf) {u32 val; +nand_wait_cmd_fifo_empty (); + val =readl (SUNXI_NFC_BASE +NFC_CTL ); val &= ~NFC_CTL_PAGE_SIZE_MASK ; writel(val | NFC_CTL_RAM_METHOD | NFC_CTL_PAGE_SIZE(conf->page_size),
@@ -206,6 +221,8 @@ static int nand_load_page(const struct nfc_config *conf, u32 offs) {int page = offs / conf->page_size; +nand_wait_cmd_fifo_empty (); + writel((NFC_CMD_RNDOUTSTART << NFC_RANDOM_READ_CMD1_OFFSET) | (NFC_CMD_RNDOUT << NFC_RANDOM_READ_CMD0_OFFSET) | (NFC_CMD_READSTART << NFC_READ_CMD_OFFSET),
@@ -222,6 +239,8 @@ static int nand_load_page(const struct nfc_config *conf, u32 offs)static int nand_reset_column (void ) { +nand_wait_cmd_fifo_empty (); + writel((NFC_CMD_RNDOUTSTART << NFC_RANDOM_READ_CMD1_OFFSET) | (NFC_CMD_RNDOUT << NFC_RANDOM_READ_CMD0_OFFSET) | (NFC_CMD_RNDOUTSTART << NFC_READ_CMD_OFFSET),
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 7/20 spl: nand: sunxi: add missing status clear
In reply to Miquel RaynalIt is best practice to always clear the status register before executing a command to be sure that the status read afterwards is relevant.
--- drivers/mtd/nand/sunxi_nand_spl.c | 1 + 1 file changed, 1 insertion(+)
drivers/mtd/nand/sunxi_nand_spl.c +1 -0
@@ -245,6 +245,7 @@ static int nand_reset_column(void) (NFC_CMD_RNDOUT <<NFC_RANDOM_READ_CMD0_OFFSET ) | (NFC_CMD_RNDOUTSTART <<NFC_READ_CMD_OFFSET ), SUNXI_NFC_BASE + NFC_RCMD_SET); +writel (NFC_ST_CMD_INT_FLAG ,SUNXI_NFC_BASE +NFC_ST );writel (0 ,SUNXI_NFC_BASE +NFC_ADDR_LOW ); writel(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_RAW_CMD | (1 << NFC_ADDR_NUM_OFFSET) | NFC_SEND_ADDR | NFC_CMD_RNDOUT,
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 8/20 spl: nand: sunxi: create an helper to handle command execution
In reply to Miquel RaynalExecuting a command is matter of always doing the following sequence:
* Waiting for the FIFO to be empty so we can fill it with the new command.
* Clearing the status register.
* Writing the command in the FIFO.
* Waiting for the command to finish.
Add a nand_exec_cmd() helper to handle this instead of repeating the logic through the various functions.
--- drivers/mtd/nand/sunxi_nand_spl.c | 42 +++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-)
drivers/mtd/nand/sunxi_nand_spl.c +21 -21
@@ -177,6 +177,20 @@ static int nand_wait_int(void)return 0 ; } +static int nand_exec_cmd (u32 cmd) +{ +int ret; + + ret =nand_wait_cmd_fifo_empty (); +if (ret) +return ret; + +writel (NFC_ST_CMD_INT_FLAG ,SUNXI_NFC_BASE +NFC_ST ); +writel (cmd,SUNXI_NFC_BASE +NFC_CMD ); + +return nand_wait_int (); +} +void nand_init (void ) {uint32_t val;
@@ -194,13 +208,7 @@ void nand_init(void) }/* reset NAND */ -nand_wait_cmd_fifo_empty (); - -writel (NFC_ST_CMD_INT_FLAG ,SUNXI_NFC_BASE +NFC_ST ); -writel (NFC_SEND_CMD1 |NFC_WAIT_FLAG |NAND_CMD_RESET , -SUNXI_NFC_BASE +NFC_CMD ); - -nand_wait_int (); +nand_exec_cmd (NFC_SEND_CMD1 |NFC_WAIT_FLAG |NAND_CMD_RESET ); }static void nand_apply_config (const struct nfc_config *conf)
@@ -221,37 +229,29 @@ static int nand_load_page(const struct nfc_config *conf, u32 offs) {int page = offs / conf->page_size; -nand_wait_cmd_fifo_empty (); -writel ((NFC_CMD_RNDOUTSTART <<NFC_RANDOM_READ_CMD1_OFFSET ) | (NFC_CMD_RNDOUT <<NFC_RANDOM_READ_CMD0_OFFSET ) | (NFC_CMD_READSTART <<NFC_READ_CMD_OFFSET ),SUNXI_NFC_BASE +NFC_RCMD_SET );writel (((page &0xFFFF ) <<16 ),SUNXI_NFC_BASE +NFC_ADDR_LOW );writel ((page >>16 ) &0xFF ,SUNXI_NFC_BASE +NFC_ADDR_HIGH ); -writel (NFC_ST_CMD_INT_FLAG ,SUNXI_NFC_BASE +NFC_ST ); -writel (NFC_SEND_CMD1 |NFC_SEND_CMD2 |NFC_RAW_CMD |NFC_WAIT_FLAG | - ((conf->addr_cycles -1 ) <<NFC_ADDR_NUM_OFFSET ) |NFC_SEND_ADDR , -SUNXI_NFC_BASE +NFC_CMD ); -return nand_wait_int (); +return nand_exec_cmd (NFC_SEND_CMD1 |NFC_SEND_CMD2 |NFC_RAW_CMD | +NFC_SEND_ADDR |NFC_WAIT_FLAG | + ((conf->addr_cycles -1 ) <<NFC_ADDR_NUM_OFFSET )); }static int nand_reset_column (void ) { -nand_wait_cmd_fifo_empty (); -writel ((NFC_CMD_RNDOUTSTART <<NFC_RANDOM_READ_CMD1_OFFSET ) | (NFC_CMD_RNDOUT <<NFC_RANDOM_READ_CMD0_OFFSET ) | (NFC_CMD_RNDOUTSTART <<NFC_READ_CMD_OFFSET ),SUNXI_NFC_BASE +NFC_RCMD_SET ); -writel (NFC_ST_CMD_INT_FLAG ,SUNXI_NFC_BASE +NFC_ST );writel (0 ,SUNXI_NFC_BASE +NFC_ADDR_LOW ); -writel (NFC_SEND_CMD1 |NFC_SEND_CMD2 |NFC_RAW_CMD | - (1 <<NFC_ADDR_NUM_OFFSET ) |NFC_SEND_ADDR |NFC_CMD_RNDOUT , -SUNXI_NFC_BASE +NFC_CMD ); -return nand_wait_int (); +return nand_exec_cmd (NFC_SEND_CMD1 |NFC_SEND_CMD2 |NFC_RAW_CMD | + (1 <<NFC_ADDR_NUM_OFFSET ) |NFC_SEND_ADDR | +NFC_CMD_RNDOUT ); } static int nand_read_page(const struct nfc_config *conf, u32 offs,
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 9/20 spl: nand: sunxi: ensure enough time has passed after changing the column
In reply to Miquel RaynalWhen changing the column, the ONFI specification states that a minimum time of tCCS (Change Column Setup time) must elapse between the last address cycle is asserted on the bus and the first data cycle is clocked. An usual value for average NANDs is 500 nanoseconds. Round it up to 1 microsecond to be safe.
--- drivers/mtd/nand/sunxi_nand_spl.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
drivers/mtd/nand/sunxi_nand_spl.c +12 -3
@@ -243,15 +243,24 @@ static int nand_load_page(const struct nfc_config *conf, u32 offs)static int nand_reset_column (void ) { +int ret; +writel ((NFC_CMD_RNDOUTSTART <<NFC_RANDOM_READ_CMD1_OFFSET ) | (NFC_CMD_RNDOUT <<NFC_RANDOM_READ_CMD0_OFFSET ) | (NFC_CMD_RNDOUTSTART <<NFC_READ_CMD_OFFSET ),SUNXI_NFC_BASE +NFC_RCMD_SET );writel (0 ,SUNXI_NFC_BASE +NFC_ADDR_LOW ); -return nand_exec_cmd (NFC_SEND_CMD1 |NFC_SEND_CMD2 |NFC_RAW_CMD | - (1 <<NFC_ADDR_NUM_OFFSET ) |NFC_SEND_ADDR | -NFC_CMD_RNDOUT ); + ret =nand_exec_cmd (NFC_SEND_CMD1 |NFC_SEND_CMD2 |NFC_RAW_CMD | + (1 <<NFC_ADDR_NUM_OFFSET ) |NFC_SEND_ADDR | +NFC_CMD_RNDOUT ); +if (ret) +return ret; + +/* Ensure tCCS has passed before reading data */ +udelay (1 ); + +return 0 ; } static int nand_read_page(const struct nfc_config *conf, u32 offs,
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 10/20 spl: nand: sunxi: make the reset column helper more generic
In reply to Miquel RaynalPrepare the future use of an helper to move the data pointer (the column) of the NAND chip by renaming nand_reset_column() to nand_change_column(). Resetting the column is just a matter of giving 0 as argument.
--- drivers/mtd/nand/sunxi_nand_spl.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/mtd/nand/sunxi_nand_spl.c +5 -5
@@ -241,7 +241,7 @@ static int nand_load_page(const struct nfc_config *conf, u32 offs) ((conf->addr_cycles - 1) << NFC_ADDR_NUM_OFFSET)); } -static int nand_reset_column (void ) +static int nand_change_column (u16 column) {int ret;
@@ -249,7 +249,7 @@ static int nand_reset_column(void) (NFC_CMD_RNDOUT <<NFC_RANDOM_READ_CMD0_OFFSET ) | (NFC_CMD_RNDOUTSTART <<NFC_READ_CMD_OFFSET ), SUNXI_NFC_BASE + NFC_RCMD_SET); -writel (0 ,SUNXI_NFC_BASE +NFC_ADDR_LOW ); +writel (column,SUNXI_NFC_BASE +NFC_ADDR_LOW ); ret = nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_RAW_CMD | (1 << NFC_ADDR_NUM_OFFSET) | NFC_SEND_ADDR |
@@ -416,7 +416,7 @@ static int nand_detect_ecc_config(struct nfc_config *conf, u32 offs, conf->ecc_strength >=0 ; conf->ecc_strength--) { conf->randomize = false; -if (nand_reset_column ()) +if (nand_change_column (0 ))return -EIO ;/*
@@ -436,7 +436,7 @@ static int nand_detect_ecc_config(struct nfc_config *conf, u32 offs, conf->randomize = true; conf->nseeds =ARRAY_SIZE (random_seed); do { - if (nand_reset_column()) + if (nand_change_column(0)) return -EIO; if (!nand_read_page(conf, offs, dest,
@@ -528,7 +528,7 @@ static int nand_read_buffer(struct nfc_config *conf, uint32_t offs,/* Try to adjust ->nseeds and read the page again... */ conf->nseeds = cur_seed; -if (nand_reset_column ()) +if (nand_change_column (0 ))return -EIO ;/* ... it still fails => it's a real corruption. */
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 11/20 sunxi: spl: deassert the NAND controller reset line
In reply to Miquel RaynalEnsure the NAND controller reset line is deasserted before use.
--- board/sunxi/board.c | 4 ++++ 1 file changed, 4 insertions(+)
board/sunxi/board.c +4 -0
@@ -286,6 +286,10 @@ static void nand_clock_setup(void) (struct sunxi_ccm_reg *)SUNXI_CCM_BASE ;setbits_le32 (&ccm->ahb_gate0, (CLK_GATE_OPEN <<AHB_GATE_OFFSET_NAND0 )); +#if definedCONFIG_MACH_SUN6I || definedCONFIG_MACH_SUN8I || \ + definedCONFIG_MACH_SUN9I || definedCONFIG_MACH_SUN50I +setbits_le32 (&ccm->ahb_reset0_cfg, (1 <<AHB_GATE_OFFSET_NAND0 )); +#endif #ifdef CONFIG_MACH_SUN9I setbits_le32 (&ccm->ahb_gate1, (1 <<AHB_GATE_OFFSET_DMA ));#else
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 12/20 spl: nand: sunxi: declare the ecc_bytes array globally
In reply to Miquel RaynalMove the ecc_bytes array out of nand_max_ecc_strength() for future use by nand_read_page().
--- drivers/mtd/nand/sunxi_nand_spl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/mtd/nand/sunxi_nand_spl.c +2 -1
@@ -263,6 +263,8 @@ static int nand_change_column(u16 column)return 0 ; } +static const int ecc_bytes[] = {32 ,46 ,54 ,60 ,74 ,88 ,102 ,110 ,116 }; +static int nand_read_page (const struct nfc_config *conf,u32 offs,void *dest,int len) {
@@ -350,7 +352,6 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,static int nand_max_ecc_strength (struct nfc_config *conf) { -static const int ecc_bytes[] = {32 ,46 ,54 ,60 ,74 ,88 ,102 ,110 ,116 };int max_oobsize, max_ecc_bytes;int nsectors = conf->page_size / conf->ecc_size;int i;
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 13/20 spl: nand: sunxi: use PIO instead of DMA
In reply to Miquel RaynalSPL support was first written to support only the earlier generations of Allwinner SoCs, and was only really enabled on the A13 / GR8. However, those old SoCs had a DMA engine that has been replaced since the A31 by another DMA controller that is no longer compatible.
Since the code directly uses that DMA controller, it cannot operate properly on the later SoCs, while the NAND controller has not changed.
There's two paths forward, the first one would have been to add support for that DMA controller too, the second to just remove the DMA usage entirely and rely on PIO.
The later has been chosen because CPU overload at this stage is not an issue and it makes the driver more generic, and easier to understand.
--- drivers/mtd/nand/sunxi_nand_spl.c | 141 ++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 83 deletions(-)
drivers/mtd/nand/sunxi_nand_spl.c +58 -83
@@ -10,6 +10,7 @@#include <common.h> #include <config.h> #include <nand.h> +#include <linux/ctype.h> /* registers */ #define NFC_CTL 0x00000000
@@ -67,10 +68,12 @@#define NFC_SEND_CMD3 (1 << 28)#define NFC_SEND_CMD4 (1 << 29)#define NFC_RAW_CMD (0 << 30) +#define NFC_ECC_CMD (1 << 30)#define NFC_PAGE_CMD (2 << 30)#define NFC_ST_CMD_INT_FLAG (1 << 1)#define NFC_ST_DMA_INT_FLAG (1 << 2) +#define NFC_ST_CMD_FIFO_STAT (1 << 3)#define NFC_READ_CMD_OFFSET 0#define NFC_RANDOM_READ_CMD0_OFFSET 8
@@ -80,22 +83,6 @@#define NFC_CMD_RNDOUT 0x05#define NFC_CMD_READSTART 0x30 -#define SUNXI_DMA_CFG_REG0 0x300 -#define SUNXI_DMA_SRC_START_ADDR_REG0 0x304 -#define SUNXI_DMA_DEST_START_ADDRR_REG0 0x308 -#define SUNXI_DMA_DDMA_BC_REG0 0x30C -#define SUNXI_DMA_DDMA_PARA_REG0 0x318 - -#define SUNXI_DMA_DDMA_CFG_REG_LOADING (1 << 31) -#define SUNXI_DMA_DDMA_CFG_REG_DMA_DEST_DATA_WIDTH_32 (2 << 25) -#define SUNXI_DMA_DDMA_CFG_REG_DDMA_DST_DRQ_TYPE_DRAM (1 << 16) -#define SUNXI_DMA_DDMA_CFG_REG_DMA_SRC_DATA_WIDTH_32 (2 << 9) -#define SUNXI_DMA_DDMA_CFG_REG_DMA_SRC_ADDR_MODE_IO (1 << 5) -#define SUNXI_DMA_DDMA_CFG_REG_DDMA_SRC_DRQ_TYPE_NFC (3 << 0) - -#define SUNXI_DMA_DDMA_PARA_REG_SRC_WAIT_CYC (0x0F << 0) -#define SUNXI_DMA_DDMA_PARA_REG_SRC_BLK_SIZE (0x7F << 8) -struct nfc_config {int page_size;int ecc_strength;
@@ -268,86 +255,74 @@ static const int ecc_bytes[] = {32, 46, 54, 60, 74, 88, 102, 110, 116};static int nand_read_page (const struct nfc_config *conf,u32 offs,void *dest,int len) { -dma_addr_t dst = (dma_addr_t )dest;int nsectors = len / conf->ecc_size;u16 rand_seed =0 ; -u32 val; -int page; - - page = offs / conf->page_size; +int oob_chunk_sz = ecc_bytes[conf->ecc_strength]; +int page = offs / conf->page_size; +u32 ecc_st; +int i;if (offs % conf->page_size || len % conf->ecc_size || len > conf->page_size || len <0 )return -EINVAL ; -/* clear ecc status */ -writel (0 ,SUNXI_NFC_BASE +NFC_ECC_ST ); -/* Choose correct seed if randomized */ if (conf->randomize) rand_seed = random_seed[page % conf->nseeds]; -writel ((rand_seed <<16 ) | (conf->ecc_strength <<12 ) | - (conf->randomize ?NFC_ECC_RANDOM_EN :0 ) | - (conf->ecc_size ==512 ?NFC_ECC_BLOCK_SIZE :0 ) | -NFC_ECC_EN |NFC_ECC_PIPELINE |NFC_ECC_EXCEPTION , -SUNXI_NFC_BASE +NFC_ECC_CTL ); - -flush_dcache_range (dst,ALIGN (dst + conf->ecc_size,ARCH_DMA_MINALIGN )); - -/* SUNXI_DMA */ -writel (0x0 ,SUNXI_DMA_BASE +SUNXI_DMA_CFG_REG0 );/* clr dma cmd */ -/* read from REG_IO_DATA */ -writel (SUNXI_NFC_BASE +NFC_IO_DATA , -SUNXI_DMA_BASE +SUNXI_DMA_SRC_START_ADDR_REG0 ); -/* read to RAM */ -writel (dst,SUNXI_DMA_BASE +SUNXI_DMA_DEST_START_ADDRR_REG0 ); -writel (SUNXI_DMA_DDMA_PARA_REG_SRC_WAIT_CYC | -SUNXI_DMA_DDMA_PARA_REG_SRC_BLK_SIZE , -SUNXI_DMA_BASE +SUNXI_DMA_DDMA_PARA_REG0 ); -writel (len,SUNXI_DMA_BASE +SUNXI_DMA_DDMA_BC_REG0 ); -writel (SUNXI_DMA_DDMA_CFG_REG_LOADING | -SUNXI_DMA_DDMA_CFG_REG_DMA_DEST_DATA_WIDTH_32 | -SUNXI_DMA_DDMA_CFG_REG_DDMA_DST_DRQ_TYPE_DRAM | -SUNXI_DMA_DDMA_CFG_REG_DMA_SRC_DATA_WIDTH_32 | -SUNXI_DMA_DDMA_CFG_REG_DMA_SRC_ADDR_MODE_IO | -SUNXI_DMA_DDMA_CFG_REG_DDMA_SRC_DRQ_TYPE_NFC , -SUNXI_DMA_BASE +SUNXI_DMA_CFG_REG0 ); - -writel (nsectors,SUNXI_NFC_BASE +NFC_SECTOR_NUM ); -writel (NFC_ST_DMA_INT_FLAG ,SUNXI_NFC_BASE +NFC_ST ); -writel (NFC_DATA_TRANS |NFC_PAGE_CMD |NFC_DATA_SWAP_METHOD , -SUNXI_NFC_BASE +NFC_CMD ); - -if (!check_value (SUNXI_NFC_BASE +NFC_ST ,NFC_ST_DMA_INT_FLAG , -DEFAULT_TIMEOUT_US )) { -printf ("Error while initializing dma interrupt\n" ); -return -EIO ; +/* Retrieve data from SRAM (PIO) */ +for (i =0 ; i < nsectors; i++) { +int data_off = i * conf->ecc_size; +int oob_off = conf->page_size + (i * oob_chunk_sz); +u8 *data = dest + data_off; + +/* Clear ECC status and restart ECC engine */ +writel (0 ,SUNXI_NFC_BASE +NFC_ECC_ST ); +writel ((rand_seed <<16 ) | (conf->ecc_strength <<12 ) | + (conf->randomize ?NFC_ECC_RANDOM_EN :0 ) | + (conf->ecc_size ==512 ?NFC_ECC_BLOCK_SIZE :0 ) | +NFC_ECC_EN |NFC_ECC_EXCEPTION , +SUNXI_NFC_BASE +NFC_ECC_CTL ); + +/* Move the data in SRAM */ +nand_change_column (data_off); +writel (conf->ecc_size,SUNXI_NFC_BASE +NFC_CNT ); +nand_exec_cmd (NFC_DATA_TRANS ); + +/* +* Let the ECC engine consume the ECC bytes and possibly correct +* the data. +*/ +nand_change_column (oob_off); +nand_exec_cmd (NFC_DATA_TRANS |NFC_ECC_CMD ); + +/* Get the ECC status */ + ecc_st =readl (SUNXI_NFC_BASE +NFC_ECC_ST ); + +/* ECC error detected. */ +if (ecc_st &0xffff ) +return -EIO ; + +/* +* Return 1 if the first chunk is empty (needed for +* configuration detection). +*/ +if (!i && (ecc_st &0x10000 )) +return 1 ; + +/* Retrieve the data from SRAM */ +memcpy_fromio (data,SUNXI_NFC_BASE +NFC_RAM0_BASE , + conf->ecc_size); + +/* Stop the ECC engine */ +writel (readl (SUNXI_NFC_BASE +NFC_ECC_CTL ) & ~NFC_ECC_EN , +SUNXI_NFC_BASE +NFC_ECC_CTL ); + +if (data_off + conf->ecc_size >= len) +break ; } -writel (NFC_ST_DMA_INT_FLAG ,SUNXI_NFC_BASE +NFC_ST ); -if (!check_value_negated (SUNXI_DMA_BASE +SUNXI_DMA_CFG_REG0 , -SUNXI_DMA_DDMA_CFG_REG_LOADING , -DEFAULT_TIMEOUT_US )) { -printf ("Error while waiting for dma transfer to finish\n" ); -return -EIO ; - } - -invalidate_dcache_range (dst, -ALIGN (dst + conf->ecc_size,ARCH_DMA_MINALIGN )); - - val =readl (SUNXI_NFC_BASE +NFC_ECC_ST ); - -/* ECC error detected. */ -if (val &0xffff ) -return -EIO ; - -/* -* Return 1 if the page is empty. -* We consider the page as empty if the first ECC block is marked -* empty. -*/ -return (val &0x10000 ) ?1 :0 ; +return 0 ; }static int nand_max_ecc_strength (struct nfc_config *conf)
Signature · 1 line
2.14.1
Re: [U-Boot] [PATCH v3 13/20] spl: nand: sunxi: use PIO instead of DMA
Hi Miquel,
Quoted 12 lines · Miquel Raynal
SPL support was first written to support only the earlier generations of Allwinner SoCs, and was only really enabled on the A13 / GR8. However, those old SoCs had a DMA engine that has been replaced since the A31 by another DMA controller that is no longer compatible.
Since the code directly uses that DMA controller, it cannot operate properly on the later SoCs, while the NAND controller has not changed.
There's two paths forward, the first one would have been to add support for that DMA controller too, the second to just remove the DMA usage entirely and rely on PIO.
Quoted 5 lines
The later has been chosen because CPU overload at this stage is not an issue and it makes the driver more generic, and easier to understand.
Signed-off-by Miquel Raynal <[email protected]>Acked-by Boris Brezillon <[email protected]>
I'm a bit late to the party, but this bricks the CHIP Pro too. While U-Boot proper seems to be flashed properly (re-reading it from the NAND after flashing brings up the same CRC than the original image), the SPL will only read 0s.
The transfer does complete though, so maybe it's just the copy from the SRAM to the main memory that doesn't work?
The offset looks correct though, so I'm not sure.
Maxime
Miquel Raynal
maintainerRe: [U-Boot] [PATCH v3 13/20] spl: nand: sunxi: use PIO instead of DMA
Hi Maxime,
Maxime Ripard <[email protected]> wrote on Thu, 24 Jun 2021 14:05:40 +0200:
Quoted 26 lines
Hi Miquel,
Quoted 12 lines · Miquel Raynal
SPL support was first written to support only the earlier generations of Allwinner SoCs, and was only really enabled on the A13 / GR8. However, those old SoCs had a DMA engine that has been replaced since the A31 by another DMA controller that is no longer compatible.
Since the code directly uses that DMA controller, it cannot operate properly on the later SoCs, while the NAND controller has not changed.
There's two paths forward, the first one would have been to add support for that DMA controller too, the second to just remove the DMA usage entirely and rely on PIO.
Quoted 5 lines
The later has been chosen because CPU overload at this stage is not an issue and it makes the driver more generic, and easier to understand.
Signed-off-by Miquel Raynal <[email protected]>Acked-by Boris Brezillon <[email protected]>I'm a bit late to the party, but this bricks the CHIP Pro too. While U-Boot proper seems to be flashed properly (re-reading it from the NAND after flashing brings up the same CRC than the original image), the SPL will only read 0s.
Quoted 4 lines
The transfer does complete though, so maybe it's just the copy from the SRAM to the main memory that doesn't work?
The offset looks correct though, so I'm not sure.
Strange... I really have no idea what's going on here and especially I don't have any suitable board with me these days to troubleshoot this.
Sorry for not being helpful at all on this one :-)
Thanks,
Miquèl
Re: [U-Boot] [PATCH v3 13/20] spl: nand: sunxi: use PIO instead of DMA
Hi,
Quoted 34 lines · Miquel Raynal
Hi Maxime,
Maxime Ripard <[email protected]> wrote on Thu, 24 Jun 2021 14:05:40 +0200:
Quoted 29 lines
Hi Miquel,
Quoted 12 lines · Miquel Raynal
SPL support was first written to support only the earlier generations of Allwinner SoCs, and was only really enabled on the A13 / GR8. However, those old SoCs had a DMA engine that has been replaced since the A31 by another DMA controller that is no longer compatible.
Since the code directly uses that DMA controller, it cannot operate properly on the later SoCs, while the NAND controller has not changed.
There's two paths forward, the first one would have been to add support for that DMA controller too, the second to just remove the DMA usage entirely and rely on PIO.
Quoted 5 lines
The later has been chosen because CPU overload at this stage is not an issue and it makes the driver more generic, and easier to understand.
Signed-off-by Miquel Raynal <[email protected]>Acked-by Boris Brezillon <[email protected]>I'm a bit late to the party, but this bricks the CHIP Pro too. While U-Boot proper seems to be flashed properly (re-reading it from the NAND after flashing brings up the same CRC than the original image), the SPL will only read 0s.
The transfer does complete though, so maybe it's just the copy from the SRAM to the main memory that doesn't work?
Quoted 6 lines
Quoted 1 line
The offset looks correct though, so I'm not sure.
Strange... I really have no idea what's going on here and especially I don't have any suitable board with me these days to troubleshoot this.
Sorry for not being helpful at all on this one :-)
Paul has two CHIP Pro, and there might be more at the Bootlin office
Maxime
Miquel Raynal
maintainerPATCH v3 14/20 sunxi: spl: remove DMA related settings of the NAND controller
In reply to Miquel RaynalCode has been changed to do not use DMA anymore with the NAND controller, instead PIO is used. Then, DMA-specific initialization may be dropped.
--- board/sunxi/board.c | 5 ----- 1 file changed, 5 deletions(-)
board/sunxi/board.c +0 -5
@@ -289,11 +289,6 @@ static void nand_clock_setup(void)#if definedCONFIG_MACH_SUN6I || definedCONFIG_MACH_SUN8I || \ definedCONFIG_MACH_SUN9I || definedCONFIG_MACH_SUN50I setbits_le32 (&ccm->ahb_reset0_cfg, (1 <<AHB_GATE_OFFSET_NAND0 )); -#endif -#ifdef CONFIG_MACH_SUN9I -setbits_le32 (&ccm->ahb_gate1, (1 <<AHB_GATE_OFFSET_DMA )); -#else -setbits_le32 (&ccm->ahb_gate0, (1 <<AHB_GATE_OFFSET_DMA ));#endif setbits_le32 (&ccm->nand0_clk_cfg,CCM_NAND_CTRL_ENABLE |AHB_DIV_1 ); }
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 15/20 sunxi: allow NAND support to be compiled for sun8i platforms
In reply to Miquel RaynalAdd some clocks/PLL definitions as well as the dependency on MACH_SUN8I in Kconfig.
--- arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 6 ++++++ drivers/mtd/nand/Kconfig | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-)
arch/arm/include/asm/arch-sunxi/clock_sun6i.h +6 -0
@@ -192,6 +192,7 @@ struct sunxi_ccm_reg {#define ATB_DIV_1 0#define ATB_DIV_2 1#define ATB_DIV_4 2 +#define AHB_DIV_1 0#define CPU_CLK_SRC_OSC24M 1#define CPU_CLK_SRC_PLL1 2
@@ -317,6 +318,11 @@ struct sunxi_ccm_reg {#define AHB_GATE_OFFSET_LCD0 3#endif +#define CCM_NAND_CTRL_M (x) ((x) - 1) +#define CCM_NAND_CTRL_N (x) ((x) << 16) +#define CCM_NAND_CTRL_PLL6 (0x1 << 24) +#define CCM_NAND_CTRL_ENABLE (0x1 << 31) +#define CCM_MMC_CTRL_M (x) ((x) - 1)#define CCM_MMC_CTRL_OCLK_DLY (x) ((x) << 8)#define CCM_MMC_CTRL_N (x) ((x) << 16)
drivers/mtd/nand/Kconfig +1 -1
@@ -95,7 +95,7 @@ config NAND_PXA3XX config NAND_SUNXI bool "Support for NAND on Allwinner SoCs" - depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I + depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUN8I select SYS_NAND_SELF_INIT select SYS_NAND_U_BOOT_LOCATIONS imply CMD_NAND
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 16/20 sunxi: dts: enable NAND on NES classic
In reply to Miquel RaynalLet the Nintendo NES Classic use the Macronix NAND chip on it.
--- arch/arm/dts/sun8i-a23-a33.dtsi | 17 +++++++++++++++++ arch/arm/dts/sun8i-r16-nintendo-nes-classic-edition.dts | 14 ++++++++++++++ 2 files changed, 31 insertions(+)
arch/arm/dts/sun8i-a23-a33.dtsi +17 -0
@@ -289,6 +289,23 @@ function = "uart1"; }; + nand_pins_a: nand-base0 at 0 { + pins = "PC0", "PC1", "PC2", "PC5", + "PC8", "PC9", "PC10", "PC11", + "PC12", "PC13", "PC14", "PC15"; + function = "nand0"; + }; + + nand_cs0_pins_a: nand-cs at 0 { + pins = "PC4"; + function = "nand0"; + }; + + nand_rb0_pins_a: nand-rb at 0 { + pins = "PC6"; + function = "nand0"; + }; + mmc0_pins_a: mmc0 at 0 { pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5";
arch/arm/dts/sun8i-r16-nintendo-nes-classic-edition.dts +14 -0
@@ -61,3 +61,17 @@ pinctrl-0 = <&uart0_pins_a>; status = "okay"; }; + +&nfc { + pinctrl-names = "default"; + pinctrl-0 = <&nand_pins_a &nand_cs0_pins_a &nand_rb0_pins_a>; + status = "okay"; + + nand at 0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + allwinner,rb = <0>; + nand-ecc-mode = "hw"; + }; +};
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 17/20 sunxi: automatically select SPL_NAND_SUPPORT in Kconfig
In reply to Miquel RaynalMake SUNXI_NAND select SPL_NAND_SUPPORT in Kconfig, this limit the number of entries to add in defconfig files when adding NAND support.
For now, the only board using it is the CHIP pro.
--- configs/CHIP_pro_defconfig | 1 - drivers/mtd/nand/Kconfig | 1 + 2 files changed, 1 insertion(+), 1 deletion(-)
configs/CHIP_pro_defconfig +0 -1
@@ -1,7 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_SUNXI=y CONFIG_SYS_TEXT_BASE=0x4a000000 -CONFIG_SPL_NAND_SUPPORT=y CONFIG_MACH_SUN5I=y CONFIG_DRAM_TIMINGS_DDR3_800E_1066G_1333J=y CONFIG_USB0_VBUS_PIN="PB10"
drivers/mtd/nand/Kconfig +1 -0
@@ -98,6 +98,7 @@ config NAND_SUNXI depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUN8I select SYS_NAND_SELF_INIT select SYS_NAND_U_BOOT_LOCATIONS + select SPL_NAND_SUPPORT imply CMD_NAND ---help--- Enable support for NAND. This option enables the standard and
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 18/20 sunxi: make NAND_SUNXI use ARCH_SUNXI as default in Kconfig
In reply to Miquel RaynalRemove NAND_SUNXI from the CHIP pro defconfig to be automatically selected depending on the state of ARCH_SUNXI.
--- configs/CHIP_pro_defconfig | 1 - drivers/mtd/nand/Kconfig | 1 + 2 files changed, 1 insertion(+), 1 deletion(-)
configs/CHIP_pro_defconfig +0 -1
@@ -16,7 +16,6 @@ CONFIG_ENV_UBI_PART="UBI" CONFIG_ENV_UBI_VOLUME="uboot-env" # CONFIG_MMC is not set CONFIG_NAND=y -CONFIG_NAND_SUNXI=y CONFIG_AXP_ALDO3_VOLT=3300 CONFIG_AXP_ALDO4_VOLT=3300 CONFIG_USB_EHCI_HCD=y
drivers/mtd/nand/Kconfig +1 -0
@@ -95,6 +95,7 @@ config NAND_PXA3XX config NAND_SUNXI bool "Support for NAND on Allwinner SoCs" + default ARCH_SUNXI depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUN8I select SYS_NAND_SELF_INIT select SYS_NAND_U_BOOT_LOCATIONS
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 19/20 sunxi: move the NAND parameters to Kconfig
In reply to Miquel RaynalMove the NAND parameters from defconfig files to Kconfig for SUNXI architecture only. Fort now only the CHIP pro is migrated.
It would have been better to convert this defconfig entry to Kconfig for all supported machines/architectures but it has been abandoned due to a fairly high amount of errors reported by the moveconfig.py tool. This is due to defines quite often being multiplications of values/other defines not correctly handled.
--- configs/CHIP_pro_defconfig | 4 +++- drivers/mtd/nand/Kconfig | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-)
configs/CHIP_pro_defconfig +3 -1
@@ -5,7 +5,9 @@ CONFIG_MACH_SUN5I=y CONFIG_DRAM_TIMINGS_DDR3_800E_1066G_1333J=y CONFIG_USB0_VBUS_PIN="PB10" CONFIG_DEFAULT_DEVICE_TREE="sun5i-gr8-chip-pro" -CONFIG_SYS_EXTRA_OPTIONS="SYS_NAND_BLOCK_SIZE=0x40000,SYS_NAND_PAGE_SIZE=4096,SYS_NAND_OOBSIZE=256" +CONFIG_SYS_NAND_BLOCK_SIZE=0x40000 +CONFIG_SYS_NAND_OOBSIZE=0x1000 +CONFIG_SYS_NAND_OOBSIZE=0x100 CONFIG_SPL=y CONFIG_SPL_I2C_SUPPORT=y # CONFIG_CMD_FLASH is not set
drivers/mtd/nand/Kconfig +22 -0
@@ -168,6 +168,28 @@ config NAND_ZYNQ_USE_BOOTLOADER1_TIMINGS comment "Generic NAND options" +config SYS_NAND_BLOCK_SIZE + hex "NAND chip eraseblock size" + depends on ARCH_SUNXI + help + Number of data bytes in one eraseblock for the NAND chip on the + board. This is the multiple of NAND_PAGE_SIZE and the number of + pages. + +config SYS_NAND_PAGE_SIZE + hex "NAND chip page size" + depends on ARCH_SUNXI + help + Number of data bytes in one page for the NAND chip on the + board, not including the OOB area. + +config SYS_NAND_OOBSIZE + hex "NAND chip OOB size" + depends on ARCH_SUNXI + help + Number of bytes in the Out-Of-Band area for the NAND chip on + the board. + # Enhance depends when converting drivers to Kconfig which use this config # option (mxc_nand, ndfc, omap_gpmc). config SYS_NAND_BUSWIDTH_16BIT
Signature · 1 line
2.14.1
Miquel Raynal
maintainerPATCH v3 20/20 configs: add NAND support for NES Classic
In reply to Miquel RaynalAdd NAND parameters to the Nintendo NES Classic configuration file which features a Macronix NAND flash chip with 128kiB blocks of 2kiB pages plus 64 OOB bytes.
--- configs/Nintendo_NES_Classic_Edition_defconfig | 4 ++++ 1 file changed, 4 insertions(+)
configs/Nintendo_NES_Classic_Edition_defconfig +4 -0
@@ -10,6 +10,10 @@ CONFIG_AXP_GPIO=y CONFIG_DEFAULT_DEVICE_TREE="sun8i-r16-nintendo-nes-classic-edition" # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL=y +CONFIG_NAND=y +CONFIG_SYS_NAND_BLOCK_SIZE=0x20000 +CONFIG_SYS_NAND_PAGE_SIZE=0x800 +CONFIG_SYS_NAND_OOBSIZE=0x40 # CONFIG_CMD_FLASH is not set # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_ISO_PARTITION is not set
Signature · 1 line
2.14.1
v3 cover Bring NAND support to Nintendo NES Classic
In reply to Miquel RaynalHi,
Quoted 5 lines · Miquel Raynal
This series first adds fixes and enhancements to sunxi NAND drivers (SPL and U-Boot). Once this is done, the SPL NAND driver is converted to use PIO instead of DMA with the goal to support all SoCs with this IP without the need for DMA-related code. Finally, NAND support is added to Nintendo NES Classic through
Kconfigand DT additions.
For the whole serie,
Thanks!
Maxime
Signature · 10 lines
Maxime Ripard, Bootlin (formerly Free Electrons) Embedded Linux and Kernel engineering https://bootlin.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180301/7d5caea3/attachment.sig>
v3 cover Bring NAND support to Nintendo NES Classic
In reply to Miquel RaynalHi Scott,
Quoted 5 lines · Miquel Raynal
This series first adds fixes and enhancements to sunxi NAND drivers (SPL and U-Boot). Once this is done, the SPL NAND driver is converted to use PIO instead of DMA with the goal to support all SoCs with this IP without the need for DMA-related code. Finally, NAND support is added to Nintendo NES Classic through
Kconfigand DT additions.
Should we merge it through the sunxi tree, or do you want to merge these changes through yours?
Thanks!
Maxime
Signature · 10 lines
Maxime Ripard, Bootlin (formerly Free Electrons) Embedded Linux and Kernel engineering https://bootlin.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180307/cd8ea5d5/attachment.sig>
v3 cover Bring NAND support to Nintendo NES Classic
Quoted 11 lines · Maxime Ripard
Hi Scott,
Quoted 5 lines · Miquel Raynal
This series first adds fixes and enhancements to sunxi NAND drivers (SPL and U-Boot). Once this is done, the SPL NAND driver is converted to use PIO instead of DMA with the goal to support all SoCs with this IP without the need for DMA-related code. Finally, NAND support is added to Nintendo NES Classic through
Kconfigand DT additions.Should we merge it through the sunxi tree, or do you want to merge these changes through yours?
The sunxi tree. I'm not really involved much with U-Boot these days.
-Scott
v3 cover Bring NAND support to Nintendo NES Classic
Quoted 10 lines · Scott Wood
Quoted 9 lines · Maxime Ripard
Hi Scott,
Quoted 5 lines · Miquel Raynal
This series first adds fixes and enhancements to sunxi NAND drivers (SPL and U-Boot). Once this is done, the SPL NAND driver is converted to use PIO instead of DMA with the goal to support all SoCs with this IP without the need for DMA-related code. Finally, NAND support is added to Nintendo NES Classic through
Kconfigand DT additions.
Quoted 4 lines
Quoted 2 lines
Should we merge it through the sunxi tree, or do you want to merge these changes through yours?
The sunxi tree. I'm not really involved much with U-Boot these days.
Ok, that works for me, thanks!
Maxime
Signature · 10 lines
Maxime Ripard, Bootlin (formerly Free Electrons) Embedded Linux and Kernel engineering https://bootlin.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180313/394c6d5d/attachment.sig>
v3 cover Bring NAND support to Nintendo NES Classic
In reply to Miquel RaynalQuoted 10 lines · Miquel Raynal
Hello,
This series first adds fixes and enhancements to sunxi NAND drivers (SPL and U-Boot). Once this is done, the SPL NAND driver is converted to use PIO instead of DMA with the goal to support all SoCs with this IP without the need for DMA-related code. Finally, NAND support is added to Nintendo NES Classic through
Kconfigand DT additions.Thanks,
Miquèl
Merged every thing, thanks for your stubborn^W patience on this one :)
Maxime
Signature · 10 lines
Maxime Ripard, Bootlin (formerly Free Electrons) Embedded Linux and Kernel engineering https://bootlin.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180403/8c2b38f2/attachment.sig>