diff mbox series

[v2,13/22] mtd: rawnand: Pass the CS line to be selected in struct nand_operation

Message ID 20181106150810.9569-14-boris.brezillon@bootlin.com
State Changes Requested
Delegated to: Miquel Raynal
Headers show
Series mtd: rawnand: 3rd batch of cleanup | expand

Commit Message

Boris Brezillon Nov. 6, 2018, 3:08 p.m. UTC
In order to deprecate the ->select_chip hook we need to pass the CS
line a NAND operations are targeting. This is done through the
addition of a cs field to the nand_operation struct.

We also need to keep track of the currently selected target to
properly initialize op->cs, hence the ->cur_cs field addition to the
nand_chip struct.

Note that op->cs is not assigned in nand_exec_op() because we might
rework the way we execute NAND operations in the future (adopt a
queuing mechanism instead of the serialization we have right now).

Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
---
Changes in v2:
- Initialize ->cur_cs
---
 drivers/mtd/nand/raw/internals.h  |  3 +++
 drivers/mtd/nand/raw/nand_base.c  | 39 +++++++++++++++++--------------
 drivers/mtd/nand/raw/nand_hynix.c |  4 ++--
 include/linux/mtd/rawnand.h       | 11 ++++++++-
 4 files changed, 37 insertions(+), 20 deletions(-)

Comments

Janusz Krzysztofik Nov. 10, 2018, 1:30 a.m. UTC | #1
Hi Boris,

On Tuesday, November 6, 2018 4:08:01 PM CET Boris Brezillon wrote:
> In order to deprecate the ->select_chip hook we need to pass the CS
> line a NAND operations are targeting. This is done through the
> addition of a cs field to the nand_operation struct.
> 
> We also need to keep track of the currently selected target to
> properly initialize op->cs, hence the ->cur_cs field addition to the
> nand_chip struct.
> 
> Note that op->cs is not assigned in nand_exec_op() because we might
> rework the way we execute NAND operations in the future (adopt a
> queuing mechanism instead of the serialization we have right now).
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
> ---
> Changes in v2:
> - Initialize ->cur_cs
> ---
>  drivers/mtd/nand/raw/internals.h  |  3 +++
>  drivers/mtd/nand/raw/nand_base.c  | 39 +++++++++++++++++--------------
>  drivers/mtd/nand/raw/nand_hynix.c |  4 ++--
>  include/linux/mtd/rawnand.h       | 11 ++++++++-
>  4 files changed, 37 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
> index 6e2f61fbc5f0..b62728d5884b 100644
> --- a/drivers/mtd/nand/raw/internals.h
> +++ b/drivers/mtd/nand/raw/internals.h
> @@ -101,6 +101,9 @@ static inline int nand_exec_op(struct nand_chip *chip,
>  	if (!chip->exec_op)
>  		return -ENOTSUPP;
>  
> +	if (WARN_ON(op->cs >= chip->numchips))
> +		return -EINVAL;

This needs a fix to nand_scan_ident() like the following:

--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -5034,10 +5034,11 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
 
 	/* Set the default functions */
 	nand_set_defaults(chip);
 
 	/* Read the flash type */
+	chip->numchips = 1;
 	ret = nand_detect(chip, table);
 	if (ret) {
 		if (!(chip->options & NAND_SCAN_SILENT_NODEV))
 			pr_warn("No NAND device found\n");
 		nand_deselect_target(chip);


Otherwise nand_detect() fails for me in nand_exec_op() called from the very 
first nand_reset_op():

    WARNING: CPU: 0 PID: 1 at drivers/mtd/nand/raw/internals.h:104 nand_reset_op+0x100/0x17c
    ...
    nand: No NAND device found

With that issue fixed one way or another, you can add my:

	Tested-by: Janusz Krzysztofik <jmkrzyszt@gmail.com>

to your whole series.

Thanks,
Janusz


PS.
I'm ready to submit a series which converts ams-delta-nand to use GPIO 
API for data I/O.  My only concerns is which branch should I rebase it on.
Boris Brezillon Nov. 10, 2018, 8:04 a.m. UTC | #2
Hi Janusz,

On Sat, 10 Nov 2018 02:30:04 +0100
Janusz Krzysztofik <jmkrzyszt@gmail.com> wrote:

> Hi Boris,
> 
> On Tuesday, November 6, 2018 4:08:01 PM CET Boris Brezillon wrote:
> > In order to deprecate the ->select_chip hook we need to pass the CS
> > line a NAND operations are targeting. This is done through the
> > addition of a cs field to the nand_operation struct.
> > 
> > We also need to keep track of the currently selected target to
> > properly initialize op->cs, hence the ->cur_cs field addition to the
> > nand_chip struct.
> > 
> > Note that op->cs is not assigned in nand_exec_op() because we might
> > rework the way we execute NAND operations in the future (adopt a
> > queuing mechanism instead of the serialization we have right now).
> > 
> > Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
> > ---
> > Changes in v2:
> > - Initialize ->cur_cs
> > ---
> >  drivers/mtd/nand/raw/internals.h  |  3 +++
> >  drivers/mtd/nand/raw/nand_base.c  | 39 +++++++++++++++++--------------
> >  drivers/mtd/nand/raw/nand_hynix.c |  4 ++--
> >  include/linux/mtd/rawnand.h       | 11 ++++++++-
> >  4 files changed, 37 insertions(+), 20 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
> > index 6e2f61fbc5f0..b62728d5884b 100644
> > --- a/drivers/mtd/nand/raw/internals.h
> > +++ b/drivers/mtd/nand/raw/internals.h
> > @@ -101,6 +101,9 @@ static inline int nand_exec_op(struct nand_chip *chip,
> >  	if (!chip->exec_op)
> >  		return -ENOTSUPP;
> >  
> > +	if (WARN_ON(op->cs >= chip->numchips))
> > +		return -EINVAL;  
> 
> This needs a fix to nand_scan_ident() like the following:
> 
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -5034,10 +5034,11 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
>  
>  	/* Set the default functions */
>  	nand_set_defaults(chip);
>  
>  	/* Read the flash type */
> +	chip->numchips = 1;

Oh, you're right. Actually it should be

	chip->numchips = maxchips;

and should be done in patch 12.

>  	ret = nand_detect(chip, table);
>  	if (ret) {
>  		if (!(chip->options & NAND_SCAN_SILENT_NODEV))
>  			pr_warn("No NAND device found\n");
>  		nand_deselect_target(chip);
> 
> 
> Otherwise nand_detect() fails for me in nand_exec_op() called from the very 
> first nand_reset_op():
> 
>     WARNING: CPU: 0 PID: 1 at drivers/mtd/nand/raw/internals.h:104 nand_reset_op+0x100/0x17c
>     ...
>     nand: No NAND device found
> 
> With that issue fixed one way or another, you can add my:
> 
> 	Tested-by: Janusz Krzysztofik <jmkrzyszt@gmail.com>
> 
> to your whole series.

Thanks for testing.

> 
> Thanks,
> Janusz
> 
> 
> PS.
> I'm ready to submit a series which converts ams-delta-nand to use GPIO 
> API for data I/O.  My only concerns is which branch should I rebase it on.

I'd say nand/next, unless you have dependencies on new GPIO stuff that
are not in 4.20-rc1.

Regards,

Boris
Janusz Krzysztofik Nov. 10, 2018, 9:33 a.m. UTC | #3
Hi Boris,

On Saturday, November 10, 2018 9:04:59 AM CET Boris Brezillon wrote:
> Hi Janusz,
> 
> On Sat, 10 Nov 2018 02:30:04 +0100
> Janusz Krzysztofik <jmkrzyszt@gmail.com> wrote:
> 
> > Hi Boris,
> > 
> > On Tuesday, November 6, 2018 4:08:01 PM CET Boris Brezillon wrote:
> > > In order to deprecate the ->select_chip hook we need to pass the CS
> > > line a NAND operations are targeting. This is done through the
> > > addition of a cs field to the nand_operation struct.
> > > 
> > > We also need to keep track of the currently selected target to
> > > properly initialize op->cs, hence the ->cur_cs field addition to the
> > > nand_chip struct.
> > > 
> > > Note that op->cs is not assigned in nand_exec_op() because we might
> > > rework the way we execute NAND operations in the future (adopt a
> > > queuing mechanism instead of the serialization we have right now).
> > > 
> > > Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
> > > ---
> > > Changes in v2:
> > > - Initialize ->cur_cs
> > > ---
> > >  drivers/mtd/nand/raw/internals.h  |  3 +++
> > >  drivers/mtd/nand/raw/nand_base.c  | 39 +++++++++++++++++--------------
> > >  drivers/mtd/nand/raw/nand_hynix.c |  4 ++--
> > >  include/linux/mtd/rawnand.h       | 11 ++++++++-
> > >  4 files changed, 37 insertions(+), 20 deletions(-)
> > > 
> > > diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
> > > index 6e2f61fbc5f0..b62728d5884b 100644
> > > --- a/drivers/mtd/nand/raw/internals.h
> > > +++ b/drivers/mtd/nand/raw/internals.h
> > > @@ -101,6 +101,9 @@ static inline int nand_exec_op(struct nand_chip *chip,
> > >  	if (!chip->exec_op)
> > >  		return -ENOTSUPP;
> > >  
> > > +	if (WARN_ON(op->cs >= chip->numchips))
> > > +		return -EINVAL;  
> > 
> > This needs a fix to nand_scan_ident() like the following:
> > 
> > --- a/drivers/mtd/nand/raw/nand_base.c
> > +++ b/drivers/mtd/nand/raw/nand_base.c
> > @@ -5034,10 +5034,11 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
> >  
> >  	/* Set the default functions */
> >  	nand_set_defaults(chip);
> >  
> >  	/* Read the flash type */
> > +	chip->numchips = 1;
> 
> Oh, you're right. Actually it should be
> 
> 	chip->numchips = maxchips;

Indeed, setting it to 1 would probably result in chips beyond the first one 
never detected, which is not my case.

> ... 
> > PS.
> > I'm ready to submit a series which converts ams-delta-nand to use GPIO 
> > API for data I/O.  My only concerns is which branch should I rebase it on.
> 
> I'd say nand/next, unless you have dependencies on new GPIO stuff that
> are not in 4.20-rc1.

All GPIO dependencies are already in 4..20-rc1.   My concern was rather 
related to a future merge with this series which will raise some conflicts 
against mine.

Thanks,
Janusz
diff mbox series

Patch

diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
index 6e2f61fbc5f0..b62728d5884b 100644
--- a/drivers/mtd/nand/raw/internals.h
+++ b/drivers/mtd/nand/raw/internals.h
@@ -101,6 +101,9 @@  static inline int nand_exec_op(struct nand_chip *chip,
 	if (!chip->exec_op)
 		return -ENOTSUPP;
 
+	if (WARN_ON(op->cs >= chip->numchips))
+		return -EINVAL;
+
 	return chip->exec_op(chip, op, false);
 }
 
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index c684beab8f34..26e7bfb22a58 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -246,6 +246,7 @@  void nand_select_target(struct nand_chip *chip, unsigned int cs)
 	if (WARN_ON(cs > chip->numchips))
 		return;
 
+	chip->cur_cs = cs;
 	chip->select_chip(chip, cs);
 }
 EXPORT_SYMBOL_GPL(nand_select_target);
@@ -260,6 +261,7 @@  EXPORT_SYMBOL_GPL(nand_select_target);
 void nand_deselect_target(struct nand_chip *chip)
 {
 	chip->select_chip(chip, -1);
+	chip->cur_cs = -1;
 }
 EXPORT_SYMBOL_GPL(nand_deselect_target);
 
@@ -1022,7 +1024,7 @@  static int nand_sp_exec_read_page_op(struct nand_chip *chip, unsigned int page,
 				 PSEC_TO_NSEC(sdr->tRR_min)),
 		NAND_OP_DATA_IN(len, buf, 0),
 	};
-	struct nand_operation op = NAND_OPERATION(instrs);
+	struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 	int ret;
 
 	/* Drop the DATA_IN instruction if len is set to 0. */
@@ -1065,7 +1067,7 @@  static int nand_lp_exec_read_page_op(struct nand_chip *chip, unsigned int page,
 				 PSEC_TO_NSEC(sdr->tRR_min)),
 		NAND_OP_DATA_IN(len, buf, 0),
 	};
-	struct nand_operation op = NAND_OPERATION(instrs);
+	struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 	int ret;
 
 	/* Drop the DATA_IN instruction if len is set to 0. */
@@ -1160,7 +1162,7 @@  int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf,
 					 PSEC_TO_NSEC(sdr->tRR_min)),
 			NAND_OP_8BIT_DATA_IN(len, buf, 0),
 		};
-		struct nand_operation op = NAND_OPERATION(instrs);
+		struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 
 		/* Drop the DATA_IN instruction if len is set to 0. */
 		if (!len)
@@ -1216,7 +1218,7 @@  int nand_change_read_column_op(struct nand_chip *chip,
 				    PSEC_TO_NSEC(sdr->tCCS_min)),
 			NAND_OP_DATA_IN(len, buf, 0),
 		};
-		struct nand_operation op = NAND_OPERATION(instrs);
+		struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 		int ret;
 
 		ret = nand_fill_column_cycles(chip, addrs, offset_in_page);
@@ -1298,7 +1300,7 @@  static int nand_exec_prog_page_op(struct nand_chip *chip, unsigned int page,
 		NAND_OP_CMD(NAND_CMD_PAGEPROG, PSEC_TO_NSEC(sdr->tWB_max)),
 		NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tPROG_max), 0),
 	};
-	struct nand_operation op = NAND_OPERATION(instrs);
+	struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 	int naddrs = nand_fill_column_cycles(chip, addrs, offset_in_page);
 	int ret;
 	u8 status;
@@ -1412,7 +1414,7 @@  int nand_prog_page_end_op(struct nand_chip *chip)
 				    PSEC_TO_NSEC(sdr->tWB_max)),
 			NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tPROG_max), 0),
 		};
-		struct nand_operation op = NAND_OPERATION(instrs);
+		struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 
 		ret = nand_exec_op(chip, &op);
 		if (ret)
@@ -1520,7 +1522,7 @@  int nand_change_write_column_op(struct nand_chip *chip,
 			NAND_OP_ADDR(2, addrs, PSEC_TO_NSEC(sdr->tCCS_min)),
 			NAND_OP_DATA_OUT(len, buf, 0),
 		};
-		struct nand_operation op = NAND_OPERATION(instrs);
+		struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 		int ret;
 
 		ret = nand_fill_column_cycles(chip, addrs, offset_in_page);
@@ -1574,7 +1576,7 @@  int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf,
 			NAND_OP_ADDR(1, &addr, PSEC_TO_NSEC(sdr->tADL_min)),
 			NAND_OP_8BIT_DATA_IN(len, buf, 0),
 		};
-		struct nand_operation op = NAND_OPERATION(instrs);
+		struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 
 		/* Drop the DATA_IN instruction if len is set to 0. */
 		if (!len)
@@ -1613,7 +1615,7 @@  int nand_status_op(struct nand_chip *chip, u8 *status)
 				    PSEC_TO_NSEC(sdr->tADL_min)),
 			NAND_OP_8BIT_DATA_IN(1, status, 0),
 		};
-		struct nand_operation op = NAND_OPERATION(instrs);
+		struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 
 		if (!status)
 			op.ninstrs--;
@@ -1646,7 +1648,7 @@  int nand_exit_status_op(struct nand_chip *chip)
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(NAND_CMD_READ0, 0),
 		};
-		struct nand_operation op = NAND_OPERATION(instrs);
+		struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 
 		return nand_exec_op(chip, &op);
 	}
@@ -1685,7 +1687,7 @@  int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock)
 				    PSEC_TO_MSEC(sdr->tWB_max)),
 			NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tBERS_max), 0),
 		};
-		struct nand_operation op = NAND_OPERATION(instrs);
+		struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 
 		if (chip->options & NAND_ROW_ADDR_3)
 			instrs[1].ctx.addr.naddrs++;
@@ -1743,7 +1745,7 @@  static int nand_set_features_op(struct nand_chip *chip, u8 feature,
 					      PSEC_TO_NSEC(sdr->tWB_max)),
 			NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tFEAT_max), 0),
 		};
-		struct nand_operation op = NAND_OPERATION(instrs);
+		struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 
 		return nand_exec_op(chip, &op);
 	}
@@ -1791,7 +1793,7 @@  static int nand_get_features_op(struct nand_chip *chip, u8 feature,
 			NAND_OP_8BIT_DATA_IN(ONFI_SUBFEATURE_PARAM_LEN,
 					     data, 0),
 		};
-		struct nand_operation op = NAND_OPERATION(instrs);
+		struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 
 		return nand_exec_op(chip, &op);
 	}
@@ -1811,7 +1813,7 @@  static int nand_wait_rdy_op(struct nand_chip *chip, unsigned int timeout_ms,
 			NAND_OP_WAIT_RDY(PSEC_TO_MSEC(timeout_ms),
 					 PSEC_TO_NSEC(delay_ns)),
 		};
-		struct nand_operation op = NAND_OPERATION(instrs);
+		struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 
 		return nand_exec_op(chip, &op);
 	}
@@ -1844,7 +1846,7 @@  int nand_reset_op(struct nand_chip *chip)
 			NAND_OP_CMD(NAND_CMD_RESET, PSEC_TO_NSEC(sdr->tWB_max)),
 			NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tRST_max), 0),
 		};
-		struct nand_operation op = NAND_OPERATION(instrs);
+		struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 
 		return nand_exec_op(chip, &op);
 	}
@@ -1878,7 +1880,7 @@  int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
 		struct nand_op_instr instrs[] = {
 			NAND_OP_DATA_IN(len, buf, 0),
 		};
-		struct nand_operation op = NAND_OPERATION(instrs);
+		struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 
 		instrs[0].ctx.data.force_8bit = force_8bit;
 
@@ -1922,7 +1924,7 @@  int nand_write_data_op(struct nand_chip *chip, const void *buf,
 		struct nand_op_instr instrs[] = {
 			NAND_OP_DATA_OUT(len, buf, 0),
 		};
-		struct nand_operation op = NAND_OPERATION(instrs);
+		struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 
 		instrs[0].ctx.data.force_8bit = force_8bit;
 
@@ -5006,6 +5008,9 @@  static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
 	unsigned int i;
 	int ret;
 
+	/* Assume all dies are deselected when we enter nand_scan_ident(). */
+	chip->cur_cs = -1;
+
 	/* Enforce the right timings for reset/detection */
 	onfi_fill_data_interface(chip, NAND_SDR_IFACE, 0);
 
diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
index ac1b5c103968..1e4499d01e14 100644
--- a/drivers/mtd/nand/raw/nand_hynix.c
+++ b/drivers/mtd/nand/raw/nand_hynix.c
@@ -84,7 +84,7 @@  static int hynix_nand_cmd_op(struct nand_chip *chip, u8 cmd)
 		struct nand_op_instr instrs[] = {
 			NAND_OP_CMD(cmd, 0),
 		};
-		struct nand_operation op = NAND_OPERATION(instrs);
+		struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 
 		return nand_exec_op(chip, &op);
 	}
@@ -103,7 +103,7 @@  static int hynix_nand_reg_write_op(struct nand_chip *chip, u8 addr, u8 val)
 			NAND_OP_ADDR(1, &addr, 0),
 			NAND_OP_8BIT_DATA_OUT(1, &val, 0),
 		};
-		struct nand_operation op = NAND_OPERATION(instrs);
+		struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
 
 		return nand_exec_op(chip, &op);
 	}
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index def6dff11e8b..aa1512df38a9 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -875,18 +875,21 @@  struct nand_op_parser {
 
 /**
  * struct nand_operation - NAND operation descriptor
+ * @cs: the CS line to select for this NAND operation
  * @instrs: array of instructions to execute
  * @ninstrs: length of the @instrs array
  *
  * The actual operation structure that will be passed to chip->exec_op().
  */
 struct nand_operation {
+	unsigned int cs;
 	const struct nand_op_instr *instrs;
 	unsigned int ninstrs;
 };
 
-#define NAND_OPERATION(_instrs)					\
+#define NAND_OPERATION(_cs, _instrs)				\
 	{							\
+		.cs = _cs,					\
 		.instrs = _instrs,				\
 		.ninstrs = ARRAY_SIZE(_instrs),			\
 	}
@@ -1008,6 +1011,10 @@  struct nand_legacy {
  *			this nand device will encounter their life times.
  * @blocks_per_die:	[INTERN] The number of PEBs in a die
  * @data_interface:	[INTERN] NAND interface timing information
+ * @cur_cs:		currently selected target. -1 means no target selected,
+ *			otherwise we should always have cur_cs >= 0 &&
+ *			cur_cs < numchips. NAND Controller drivers should not
+ *			modify this value, but they're allowed to read it.
  * @read_retries:	[INTERN] the number of read retry modes supported
  * @setup_data_interface: [OPTIONAL] setup the data interface and timing. If
  *			  chipnr is set to %NAND_DATA_IFACE_CHECK_ONLY this
@@ -1069,6 +1076,8 @@  struct nand_chip {
 
 	struct nand_data_interface data_interface;
 
+	int cur_cs;
+
 	int read_retries;
 
 	flstate_t state;