diff mbox series

[U-Boot] mtd: nand: fsl-ifc: fix support of multiple NAND devices

Message ID 20171017080045.18950-1-kurt@linutronix.de
State Superseded
Delegated to: York Sun
Headers show
Series [U-Boot] mtd: nand: fsl-ifc: fix support of multiple NAND devices | expand

Commit Message

Kurt Kanzenbach Oct. 17, 2017, 8 a.m. UTC
Currently the chipselect used to identify the corresponding NAND chip is stored
at the controller and only set during fsl_ifc_chip_init(). This way, only the
last NAND chip is working, as the previous value of cs_nand gets overwritten.

In order to solve this issue the chipselect is moved from the controller to the
NAND chip structure. Thus, the correct chipselect for each NAND chip operation
is used.

Tested on hardware with two NAND chips connected to the IFC controller.

Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
---
 drivers/mtd/nand/fsl_ifc_nand.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

Comments

Crystal Wood Oct. 20, 2017, 2:30 a.m. UTC | #1
On Tue, Oct 17, 2017 at 10:00:45AM +0200, Kurt Kanzenbach wrote:
> Currently the chipselect used to identify the corresponding NAND chip is stored
> at the controller and only set during fsl_ifc_chip_init(). This way, only the
> last NAND chip is working, as the previous value of cs_nand gets overwritten.
> 
> In order to solve this issue the chipselect is moved from the controller to the
> NAND chip structure. Thus, the correct chipselect for each NAND chip operation
> is used.
> 
> Tested on hardware with two NAND chips connected to the IFC controller.
> 
> Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
> ---
>  drivers/mtd/nand/fsl_ifc_nand.c | 16 +++++++++-------
>  1 file changed, 9 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
> index bc6bdc9b2c..57737dbe94 100644
> --- a/drivers/mtd/nand/fsl_ifc_nand.c
> +++ b/drivers/mtd/nand/fsl_ifc_nand.c
> @@ -36,6 +36,7 @@ struct fsl_ifc_mtd {
>  
>  	struct device *dev;
>  	int bank;               /* Chip select bank number                */
> +	unsigned int cs_nand;   /* On which chipsel NAND is connected	  */

This is redundant with "bank" -- just do like the Linux driver does
and write "priv->bank << IFC_NAND_CSEL_SHIFT" directly to the register
when needed.

> -static int fsl_ifc_sram_init(uint32_t ver)
> +static int fsl_ifc_sram_init(struct mtd_info *mtd, uint32_t ver)
>  {
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);

Could pass in priv instead of mtd to make it more like the Linux driver. 
It's best to avoid gratuitous differences.

-Scott
Kurt Kanzenbach Oct. 20, 2017, 8:52 a.m. UTC | #2
On Thu, Oct 19, 2017 at 09:30:09PM -0500, Scott Wood wrote:
> On Tue, Oct 17, 2017 at 10:00:45AM +0200, Kurt Kanzenbach wrote:
> > Currently the chipselect used to identify the corresponding NAND chip is stored
> > at the controller and only set during fsl_ifc_chip_init(). This way, only the
> > last NAND chip is working, as the previous value of cs_nand gets overwritten.
> >
> > In order to solve this issue the chipselect is moved from the controller to the
> > NAND chip structure. Thus, the correct chipselect for each NAND chip operation
> > is used.
> >
> > Tested on hardware with two NAND chips connected to the IFC controller.
> >
> > Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
> > ---
> >  drivers/mtd/nand/fsl_ifc_nand.c | 16 +++++++++-------
> >  1 file changed, 9 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
> > index bc6bdc9b2c..57737dbe94 100644
> > --- a/drivers/mtd/nand/fsl_ifc_nand.c
> > +++ b/drivers/mtd/nand/fsl_ifc_nand.c
> > @@ -36,6 +36,7 @@ struct fsl_ifc_mtd {
> >
> >  	struct device *dev;
> >  	int bank;               /* Chip select bank number                */
> > +	unsigned int cs_nand;   /* On which chipsel NAND is connected	  */
>
> This is redundant with "bank" -- just do like the Linux driver does
> and write "priv->bank << IFC_NAND_CSEL_SHIFT" directly to the register
> when needed.

Sure, no problem.

>
> > -static int fsl_ifc_sram_init(uint32_t ver)
> > +static int fsl_ifc_sram_init(struct mtd_info *mtd, uint32_t ver)
> >  {
> > +	struct nand_chip *chip = mtd_to_nand(mtd);
> > +	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
>
> Could pass in priv instead of mtd to make it more like the Linux driver.
> It's best to avoid gratuitous differences.

Makes sense. I'll send a v2.

Thanks,
Kurt

>
> -Scott
diff mbox series

Patch

diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index bc6bdc9b2c..57737dbe94 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -36,6 +36,7 @@  struct fsl_ifc_mtd {
 
 	struct device *dev;
 	int bank;               /* Chip select bank number                */
+	unsigned int cs_nand;   /* On which chipsel NAND is connected	  */
 	unsigned int bufnum_mask; /* bufnum = page & bufnum_mask */
 	u8 __iomem *vbase;      /* Chip select base virtual address       */
 };
@@ -48,7 +49,6 @@  struct fsl_ifc_ctrl {
 	/* device info */
 	struct fsl_ifc regs;
 	void __iomem *addr;      /* Address of assigned IFC buffer        */
-	unsigned int cs_nand;    /* On which chipsel NAND is connected	  */
 	unsigned int page;       /* Last page written to / read from      */
 	unsigned int read_bytes; /* Number of bytes read during command   */
 	unsigned int column;     /* Saved column from SEQIN               */
@@ -296,7 +296,7 @@  static int fsl_ifc_run_command(struct mtd_info *mtd)
 	int i;
 
 	/* set the chip select for NAND Transaction */
-	ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
+	ifc_out32(&ifc->ifc_nand.nand_csel, priv->cs_nand);
 
 	/* start read/write seq */
 	ifc_out32(&ifc->ifc_nand.nandseq_strt,
@@ -798,8 +798,10 @@  static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
 {
 }
 
-static int fsl_ifc_sram_init(uint32_t ver)
+static int fsl_ifc_sram_init(struct mtd_info *mtd, uint32_t ver)
 {
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_ifc_runtime *ifc = ifc_ctrl->regs.rregs;
 	uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0;
 	uint32_t ncfgr = 0;
@@ -823,7 +825,7 @@  static int fsl_ifc_sram_init(uint32_t ver)
 		return 1;
 	}
 
-	cs = ifc_ctrl->cs_nand >> IFC_NAND_CSEL_SHIFT;
+	cs = priv->cs_nand >> IFC_NAND_CSEL_SHIFT;
 
 	/* Save CSOR and CSOR_ext */
 	csor = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor);
@@ -850,7 +852,7 @@  static int fsl_ifc_sram_init(uint32_t ver)
 	ifc_out32(&ifc->ifc_nand.col0, 0x0);
 
 	/* set the chip select for NAND Transaction */
-	ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
+	ifc_out32(&ifc->ifc_nand.nand_csel, priv->cs_nand);
 
 	/* start read seq */
 	ifc_out32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
@@ -912,7 +914,7 @@  static int fsl_ifc_chip_init(int devnum, u8 *addr)
 
 		if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND &&
 		    (cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr)) {
-			ifc_ctrl->cs_nand = priv->bank << IFC_NAND_CSEL_SHIFT;
+			priv->cs_nand = priv->bank << IFC_NAND_CSEL_SHIFT;
 			break;
 		}
 	}
@@ -1029,7 +1031,7 @@  static int fsl_ifc_chip_init(int devnum, u8 *addr)
 
 	ver = ifc_in32(&gregs->ifc_rev);
 	if (ver >= FSL_IFC_V1_1_0)
-		ret = fsl_ifc_sram_init(ver);
+		ret = fsl_ifc_sram_init(mtd, ver);
 	if (ret)
 		return ret;