diff mbox series

[U-Boot,4/8] spl: nand: sunxi: Enhancements and cleaning

Message ID 20180124004454.5759-5-miquel.raynal@free-electrons.com
State Changes Requested
Delegated to: Jagannadha Sutradharudu Teki
Headers show
Series Bring NAND support to Nintendo NES Classic | expand

Commit Message

Miquel Raynal Jan. 24, 2018, 12:44 a.m. UTC
Do some cleaning in sunxi NAND SPL driver like adding helpers and
clearing flags at the right spot

Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
---
 drivers/mtd/nand/sunxi_nand_spl.c | 64 +++++++++++++++++++++++++--------------
 1 file changed, 41 insertions(+), 23 deletions(-)

Comments

Maxime Ripard Jan. 24, 2018, 7:56 a.m. UTC | #1
Hi,

On Wed, Jan 24, 2018 at 01:44:50AM +0100, Miquel Raynal wrote:
> Do some cleaning in sunxi NAND SPL driver like adding helpers and
> clearing flags at the right spot
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>

I'm not really fond of these kind of wildcard patches, especially
since..

> ---
>  drivers/mtd/nand/sunxi_nand_spl.c | 64 +++++++++++++++++++++++++--------------
>  1 file changed, 41 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/mtd/nand/sunxi_nand_spl.c b/drivers/mtd/nand/sunxi_nand_spl.c
> index 06695fc15f..2488d5cb51 100644
> --- a/drivers/mtd/nand/sunxi_nand_spl.c
> +++ b/drivers/mtd/nand/sunxi_nand_spl.c
> @@ -55,8 +55,8 @@
>  
>  
>  #define NFC_ADDR_NUM_OFFSET        16
> -#define NFC_SEND_ADR               (1 << 19)
>  #define NFC_ACCESS_DIR             (1 << 20)
> +#define NFC_SEND_ADDR              (1 << 19)
>  #define NFC_DATA_TRANS             (1 << 21)
>  #define NFC_SEND_CMD1              (1 << 22)
>  #define NFC_WAIT_FLAG              (1 << 23)

... here you reorder a single value, which means that the set of these
values is not sorted anymore ...

> @@ -155,6 +155,30 @@ 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,
> +			 DEFAULT_TIMEOUT_US)) {
> +		printf("nand: timeout waiting for interruption\n");
> +		return -ETIMEDOUT;
> +	}
> +
> +	udelay(1);
> +
> +	return 0;
> +}
> +

... here you add the helpers that you talked about in your commit log,
good. but ...

>  void nand_init(void)
>  {
>  	uint32_t val;
> @@ -172,22 +196,21 @@ void nand_init(void)
>  	}
>  
>  	/* reset NAND */
> +	nand_wait_cmd_fifo_empty();
> +

... here you call one of these helpers where you didn't have that code
before, and that's not mentionned or explained in your commit log.

>  	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);
>  
> -	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)
>  {
>  	u32 val;
>  
> +	nand_wait_cmd_fifo_empty();
> +

Ditto.

>  	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),
> @@ -200,6 +223,8 @@ static int nand_load_page(const struct nfc_config *conf, u32 offs)
>  {
>  	int page = offs / conf->page_size;
>  
> +	nand_wait_cmd_fifo_empty();
> +

Ditto.

>  	writel((NFC_CMD_RNDOUTSTART << NFC_RANDOM_READ_CMD1_OFFSET) |
>  	       (NFC_CMD_RNDOUT << NFC_RANDOM_READ_CMD0_OFFSET) |
>  	       (NFC_CMD_READSTART << NFC_READ_CMD_OFFSET),
> @@ -208,38 +233,32 @@ 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,

I guess it was a typo fix then?

>  	       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)
>  {
> +	nand_wait_cmd_fifo_empty();
> +

Not mentionned or explained in your commit log.

>  	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);

Ditto

>  	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,
> -			 DEFAULT_TIMEOUT_US)) {
> -		printf("Error while initializing dma interrupt\n");
> -		return -1;
> -	}
> +	return nand_wait_int();
>  
> -	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)
>  {
> @@ -327,7 +346,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 };


Ditto.

Overall, I think it would be great to split that patch into 4:
  - the first one to fix the ADR vs ADDR typo (without changing the order)
  - the second one to introduce the nand_wait_int helper
  - the third one to introduce the nand_wait_cmd_fifo_empty, with a
    proper commit log explaining why this needs to be done and which
    issues is it fixing
  - And maybe if justified moving the ecc_bytes array to global scope

Thanks!
Maxime
Boris Brezillon Jan. 24, 2018, 8:06 a.m. UTC | #2
On Wed, 24 Jan 2018 01:44:50 +0100
Miquel Raynal <miquel.raynal@free-electrons.com> wrote:

> Do some cleaning in sunxi NAND SPL driver like adding helpers and
> clearing flags at the right spot
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
> ---
>  drivers/mtd/nand/sunxi_nand_spl.c | 64 +++++++++++++++++++++++++--------------
>  1 file changed, 41 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/mtd/nand/sunxi_nand_spl.c b/drivers/mtd/nand/sunxi_nand_spl.c
> index 06695fc15f..2488d5cb51 100644
> --- a/drivers/mtd/nand/sunxi_nand_spl.c
> +++ b/drivers/mtd/nand/sunxi_nand_spl.c
> @@ -55,8 +55,8 @@
>  
>  
>  #define NFC_ADDR_NUM_OFFSET        16
> -#define NFC_SEND_ADR               (1 << 19)
>  #define NFC_ACCESS_DIR             (1 << 20)
> +#define NFC_SEND_ADDR              (1 << 19)

This typo fix probably deserves a separate patch.

>  #define NFC_DATA_TRANS             (1 << 21)
>  #define NFC_SEND_CMD1              (1 << 22)
>  #define NFC_WAIT_FLAG              (1 << 23)
> @@ -155,6 +155,30 @@ 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,
> +			 DEFAULT_TIMEOUT_US)) {
> +		printf("nand: timeout waiting for interruption\n");
> +		return -ETIMEDOUT;
> +	}
> +
> +	udelay(1);

I'm pretty sure this udelay() is not required. Probably some leftover
of your debug session ;-).

> +
> +	return 0;
> +}
> +
>  void nand_init(void)
>  {
>  	uint32_t val;
> @@ -172,22 +196,21 @@ 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);
>  
> -	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();

I would go even further and create an helper that takes care of the
'wait_fifo_empty+clear_int+write_cmd+wait_int' sequence:

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();
}

>  }
>  
>  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),
> @@ -200,6 +223,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),
> @@ -208,38 +233,32 @@ 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,
> -			 DEFAULT_TIMEOUT_US)) {
> -		printf("Error while initializing dma interrupt\n");
> -		return -EIO;
> -	}
> -
> -	return 0;
> +	return nand_wait_int();
>  }
>  
>  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_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,
> -			 DEFAULT_TIMEOUT_US)) {
> -		printf("Error while initializing dma interrupt\n");
> -		return -1;
> -	}
> +	return nand_wait_int();

Here, I think you should wait, just to make sure we don't read data
before tCCS. udelay(1) should be enough.

>  
> -	return 0;
>  }
>  
> +static const int ecc_bytes[] = {32, 46, 54, 60, 74, 88, 102, 110, 116};
> +

Putting ecc_bytes out of nand_max_ecc_strength() is not really related
to this patch, and should probably go in patch 5.

>  static int nand_read_page(const struct nfc_config *conf, u32 offs,
>  			  void *dest, int len)
>  {
> @@ -327,7 +346,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;
Miquel Raynal Jan. 25, 2018, 11:34 p.m. UTC | #3
Hi Maxime,

On Wed, 24 Jan 2018 08:56:38 +0100
Maxime Ripard <maxime.ripard@free-electrons.com> wrote:

> Hi,
> 
> On Wed, Jan 24, 2018 at 01:44:50AM +0100, Miquel Raynal wrote:
> > Do some cleaning in sunxi NAND SPL driver like adding helpers and
> > clearing flags at the right spot
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>  
> 
> I'm not really fond of these kind of wildcard patches, especially
> since..
> 

[...]

> 
> Overall, I think it would be great to split that patch into 4:
>   - the first one to fix the ADR vs ADDR typo (without changing the order)
>   - the second one to introduce the nand_wait_int helper
>   - the third one to introduce the nand_wait_cmd_fifo_empty, with a
>     proper commit log explaining why this needs to be done and which
>     issues is it fixing
>   - And maybe if justified moving the ecc_bytes array to global scope

I split this patch into 4 logical peaces, as requested.

Thanks,
Miquèl
Miquel Raynal Jan. 25, 2018, 11:37 p.m. UTC | #4
Hi Boris,

On Wed, 24 Jan 2018 09:06:38 +0100
Boris Brezillon <boris.brezillon@free-electrons.com> wrote:

> On Wed, 24 Jan 2018 01:44:50 +0100
> Miquel Raynal <miquel.raynal@free-electrons.com> wrote:
> 
> > Do some cleaning in sunxi NAND SPL driver like adding helpers and
> > clearing flags at the right spot
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
> > ---
> >  drivers/mtd/nand/sunxi_nand_spl.c | 64 +++++++++++++++++++++++++--------------
> >  1 file changed, 41 insertions(+), 23 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/sunxi_nand_spl.c b/drivers/mtd/nand/sunxi_nand_spl.c
> > index 06695fc15f..2488d5cb51 100644
> > --- a/drivers/mtd/nand/sunxi_nand_spl.c
> > +++ b/drivers/mtd/nand/sunxi_nand_spl.c
> > @@ -55,8 +55,8 @@
> >  
> >  
> >  #define NFC_ADDR_NUM_OFFSET        16
> > -#define NFC_SEND_ADR               (1 << 19)
> >  #define NFC_ACCESS_DIR             (1 << 20)
> > +#define NFC_SEND_ADDR              (1 << 19)  
> 
> This typo fix probably deserves a separate patch.

Indeed.

> 
> >  #define NFC_DATA_TRANS             (1 << 21)
> >  #define NFC_SEND_CMD1              (1 << 22)
> >  #define NFC_WAIT_FLAG              (1 << 23)
> > @@ -155,6 +155,30 @@ 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,
> > +			 DEFAULT_TIMEOUT_US)) {
> > +		printf("nand: timeout waiting for interruption\n");
> > +		return -ETIMEDOUT;
> > +	}
> > +
> > +	udelay(1);  
> 
> I'm pretty sure this udelay() is not required. Probably some leftover
> of your debug session ;-).

That is right -> removed.

> 
> > +
> > +	return 0;
> > +}
> > +
> >  void nand_init(void)
> >  {
> >  	uint32_t val;
> > @@ -172,22 +196,21 @@ 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);
> >  
> > -	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();  
> 
> I would go even further and create an helper that takes care of the
> 'wait_fifo_empty+clear_int+write_cmd+wait_int' sequence:
> 
> 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();
> }

It makes sense, I added another patch to introduce this helper.

> 
> >  }
> >  
> >  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),
> > @@ -200,6 +223,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),
> > @@ -208,38 +233,32 @@ 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,
> > -			 DEFAULT_TIMEOUT_US)) {
> > -		printf("Error while initializing dma interrupt\n");
> > -		return -EIO;
> > -	}
> > -
> > -	return 0;
> > +	return nand_wait_int();
> >  }
> >  
> >  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_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,
> > -			 DEFAULT_TIMEOUT_US)) {
> > -		printf("Error while initializing dma interrupt\n");
> > -		return -1;
> > -	}
> > +	return nand_wait_int();  
> 
> Here, I think you should wait, just to make sure we don't read data
> before tCCS. udelay(1) should be enough.

Done and explained in another patch.

> 
> >  
> > -	return 0;
> >  }
> >  
> > +static const int ecc_bytes[] = {32, 46, 54, 60, 74, 88, 102, 110, 116};
> > +  
> 
> Putting ecc_bytes out of nand_max_ecc_strength() is not really related
> to this patch, and should probably go in patch 5.

Right, I will move this to the patch where it belongs.

> 
> >  static int nand_read_page(const struct nfc_config *conf, u32 offs,
> >  			  void *dest, int len)
> >  {
> > @@ -327,7 +346,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;  
> 

Thanks,
Miquèl
diff mbox series

Patch

diff --git a/drivers/mtd/nand/sunxi_nand_spl.c b/drivers/mtd/nand/sunxi_nand_spl.c
index 06695fc15f..2488d5cb51 100644
--- a/drivers/mtd/nand/sunxi_nand_spl.c
+++ b/drivers/mtd/nand/sunxi_nand_spl.c
@@ -55,8 +55,8 @@ 
 
 
 #define NFC_ADDR_NUM_OFFSET        16
-#define NFC_SEND_ADR               (1 << 19)
 #define NFC_ACCESS_DIR             (1 << 20)
+#define NFC_SEND_ADDR              (1 << 19)
 #define NFC_DATA_TRANS             (1 << 21)
 #define NFC_SEND_CMD1              (1 << 22)
 #define NFC_WAIT_FLAG              (1 << 23)
@@ -155,6 +155,30 @@  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,
+			 DEFAULT_TIMEOUT_US)) {
+		printf("nand: timeout waiting for interruption\n");
+		return -ETIMEDOUT;
+	}
+
+	udelay(1);
+
+	return 0;
+}
+
 void nand_init(void)
 {
 	uint32_t val;
@@ -172,22 +196,21 @@  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);
 
-	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)
 {
 	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),
@@ -200,6 +223,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),
@@ -208,38 +233,32 @@  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,
-			 DEFAULT_TIMEOUT_US)) {
-		printf("Error while initializing dma interrupt\n");
-		return -EIO;
-	}
-
-	return 0;
+	return nand_wait_int();
 }
 
 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_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,
-			 DEFAULT_TIMEOUT_US)) {
-		printf("Error while initializing dma interrupt\n");
-		return -1;
-	}
+	return nand_wait_int();
 
-	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)
 {
@@ -327,7 +346,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;