All of lore.kernel.org
 help / color / mirror / Atom feed
From: Baruch Siach <baruch@tkos.co.il>
To: Boris Brezillon <boris.brezillon@free-electrons.com>
Cc: devicetree@vger.kernel.org,
	Brian Norris <computersforpeace@gmail.com>,
	David Woodhouse <dwmw2@infradead.org>,
	linux-arm-kernel@lists.infradead.org,
	linux-mtd@lists.infradead.org
Subject: Re: [PATCH 2/2] mtd: nand: driver for Conexant Digicolor NAND Flash Controller
Date: Sun, 22 Feb 2015 10:19:23 +0200	[thread overview]
Message-ID: <20150222081923.GB2402@tarshish> (raw)
In-Reply-To: <20150219115223.40378b17@bbrezillon>

Hi Boris,

On Thu, Feb 19, 2015 at 11:52:23AM +0100, Boris Brezillon wrote:
> On Thu, 19 Feb 2015 11:43:01 +0200
> Baruch Siach <baruch@tkos.co.il> wrote:
> > On Thu, Feb 19, 2015 at 12:17:04AM +0100, Boris Brezillon wrote:
> > > On Thu, 12 Feb 2015 13:10:19 +0200
> > > Baruch Siach <baruch@tkos.co.il> wrote:
> > I understand you concern. However, since I don't have the needed hardware 
> > to test the multi nand chip setup I want to keep the code simple. These 
> > two fields are separated from the others by a blank line on purpose, and 
> > I'll also add a comment to explain that these are per nand chip files.
> 
> I'm not asking you to support multiple chips right now.
> What I'm asking here is to dispatch NFC and NAND fields in different
> structures:
> 
> struct digicolor_nand {
> 	struct mtd_info		mtd;
> 	struct nand_chip	nand;
> 
> 	u32 nand_cs;
> 	int t_ccs;
> }
> 
> struct digicolor_nfc {
> 	struct nand_hw_control	base;
> 	void __iomem		*regs;
> 	struct device		*dev;
> 
> 	unsigned long		clk_rate;
> 
> 	u32 ale_cmd;
> 	u32 ale_data;
> 	int ale_data_bytes;
> 
> 	/* Only support one NAND for now */
> 	struct digicolor_nand	nand;
> };
> 
> You'll keep the same logic except that this separation will be clearly
> visible.

Sounds reasonable. Will do.

[...]

> > It's just that the INT flag name is quite long, and it make the code using 
> > it less readable IMO. Maybe some macro trickery would do the job here.
> 
> Yep, if that's about avoiding over 80 character lines you could define
> such a macro:
> 
> #define NFC_RDY(flag)		NFC_INT_ ## flag ## _READY

Thanks for the tip. Will do.

[...]

> > I have no control of that. This command goes into a pipe that is managed 
> > at the hardware level. If the nand device does not activate the ready/busy 
> > signal, the pipe will just stall, and the command FIFO will overflow (the 
> > command FIFO has 8 entries). So you will notice the error eventually.
> 
> My point is: you should not return 1 if the NAND is not ready,
> waiting forever is not what I'm suggesting here, but you should find a
> way to return the actual NAND chip R/B status.
> If you don't have any solution to do that from your controller then you
> might consider relying on the default dev_ready implementation which is
> sending a NAND STATUS command to retrieve the R/B status.
> 
> What I'll say is in contradiction with what's done in the sunxi
> driver :-) (actually I'm considering fixing that), but after taking a
> closer look, dev_ready should only return the status of the NAND, and
> not wait for the NAND to be ready.
> The function responsible for waiting is waitfunc, maybe this is the one
> you should overload.

OK. I'll look into overloading waitfunc.

[...]

> > > > +static void digicolor_nfc_cmd_ctrl(struct mtd_info *mtd, int cmd,
> > > > +				   unsigned int ctrl)
> > > > +{
> > > > +	struct nand_chip *chip = mtd->priv;
> > > > +	struct digicolor_nfc *nfc = chip->priv;
> > > > +	u32 cs = nfc->nand_cs;
> > > > +
> > > > +	if (ctrl & NAND_CLE) {
> > > > +		digicolor_nfc_cmd_write(nfc,
> > > > +					CMD_CLE | CMD_CHIP_ENABLE(cs) | cmd);
> > > > +		if (cmd == NAND_CMD_RNDOUTSTART || cmd == NAND_CMD_RNDIN) {
> > > > +			digicolor_nfc_wait_ns(nfc, nfc->t_ccs);
> > > > +		} else if (cmd == NAND_CMD_RESET) {
> > > > +			digicolor_nfc_wait_ns(nfc, 200);
> > > > +			digicolor_nfc_dev_ready(mtd);
> > > > +		}
> > > 
> > > These wait and dev_ready calls are supposed to be part of the generic
> > > cmdfunc implementation, did you encounter any issues when relying on the
> > > default implementation ?
> > 
> > The generic code just waits. This doesn't help here. Hardware does all the 
> > command processing in its own schedule. To make the hardware wait I must 
> > explicitly insert a wait command into the pipe.
> 
> I'm not sure to understand here.
> There's a difference between:
> 1/ waiting for a NAND command to be send on the NAND bus
> 2/ waiting for the NAND to be ready (for DATA read or after a PROGRAM
>    operation)
> 
> NAND core is taking care of the 2/, but 1/ is your responsibility
> (and this is what you have to wait for here).

The generic code in nand_command_lp() sends NAND_CMD_STATUS immediately after 
NAND_CMD_RESET. According to the datasheet you must wait tWB (200ns max) 
before sending any command, including NAND_CMD_STATUS. Setting chip_delay is 
not enough as I explain above. That's way I added digicolor_nfc_wait_ns(). 
That timed wait is what I referred to. You are right that the 
digicolor_nfc_dev_ready() call is not needed here. Will remove.

[...]

> > > > +	while (len >= 4) {
> > > > +		if (digicolor_nfc_wait_ready(nfc, op))
> > > > +			return;
> > > > +		if (op == DATA_READ)
> > > > +			*pr++ = readl_relaxed(nfc->regs + NFC_DATA);
> > > > +		else
> > > > +			writel_relaxed(*pw++, nfc->regs + NFC_DATA);
> > > > +		len -= 4;
> > > > +	}
> > > 
> > > How about using readsl/writesl here (instead of this loop) ?
> > 
> > How can I add the wait condition in readsl/writesl?
> 
> Are you sure you have to wait after each readl access (is NFC_DATA
> interfaced with a FIFO or directly doing PIO access) ?

That's what the datasheet says. There is no mention of data FIFO in the 
datasheet.

[...]

> > > > +	/*
> > > > +	 * Maximum assert/deassert time; asynchronous SDR mode 0
> > > > +	 * Deassert time = max(tWH,tREH) = 30ns
> > > > +	 * Assert time = max(tRC,tRP,tWC,tWP) = 100ns
> > > > +	 * Sample time = 0
> > > > +	 */
> > > > +	timing |= TIMING_DEASSERT(DIV_ROUND_UP(30, ns_per_clk));
> > > > +	timing |= TIMING_ASSERT(DIV_ROUND_UP(100, ns_per_clk));
> > > > +	timing |= TIMING_SAMPLE(0);
> > > > +	writel_relaxed(timing, nfc->regs + NFC_TIMING_CONFIG);
> > > > +	writel_relaxed(NFC_CONTROL_ENABLE, nfc->regs + NFC_CONTROL);
> > > 
> > > Helper functions are provided to extract timings from ONFI timing modes
> > > (either those defined by the chip if it supports ONFI commands, or
> > > those extracted from the datasheet):
> > > 
> > > http://lxr.free-electrons.com/source/include/linux/mtd/nand.h#L976
> > 
> > I wanted to keep that for future improvement. The NAND chip on the EVK board 
> > is actually an old style one, neither ONFI nor JEDEC. I expect to test this 
> > driver on our target hardware that should have something newer.
> 
> Timings are not only related to ONFI chips, and
> onfi_timing_mode_default is extracted from the nand_ids table which is
> describing non-ONFI chips.
> 
> This is not my call to make, but IMHO, dynamic NAND timing
> configuration should be mandatory for new drivers.

I'll look into this for v2.

> > > > +static int digicolor_nfc_ecc_init(struct digicolor_nfc *nfc,
> > > > +				  struct device_node *np)
> > > > +{
> > > > +	struct mtd_info *mtd = &nfc->mtd;
> > > > +	struct nand_chip *chip = &nfc->nand;
> > > > +	int bch_data_range, bch_t, steps, mode, i;
> > > > +	u32 ctrl = NFC_CONTROL_ENABLE | NFC_CONTROL_BCH_KCONFIG;
> > > > +	struct nand_ecclayout *layout;
> > > > +
> > > > +	mode = of_get_nand_ecc_mode(np);
> > > > +	if (mode < 0)
> > > > +		return mode;
> > > > +	if (mode != NAND_ECC_HW_SYNDROME) {
> > > > +		dev_err(nfc->dev, "unsupported ECC mode\n");
> > > > +		return -EINVAL;
> > > > +	}
> > > > +
> > > > +	bch_data_range = of_get_nand_ecc_step_size(np);
> > > > +	if (bch_data_range < 0)
> > > > +		return bch_data_range;
> > > > +	if (bch_data_range != 512 && bch_data_range != 1024) {
> > > > +		dev_err(nfc->dev, "unsupported nand-ecc-step-size value\n");
> > > > +		return -EINVAL;
> > > > +	}
> > > > +	if (bch_data_range == 1024)
> > > > +		ctrl |= NFC_CONTROL_BCH_DATA_FIELD_RANGE_1024;
> > > > +	steps = mtd->writesize / bch_data_range;
> > > > +
> > > > +	bch_t = of_get_nand_ecc_strength(np);
> > > > +	if (bch_t < 0)
> > > > +		return bch_t;
> > > 
> > > You should fallback to datasheet values (ecc_strength_ds and
> > > ecc_step_ds) if ECC strength and step are not specified in the DT.
> > 
> > I can only choose from a fix number of strength configuration alternatives. 
> > Should I choose the lowest value that is larger than ecc_strength_ds?
> 
> Yep, this applies to both cases (information extracted from the DT and
> _ds values).

OK. Will do.

Thanks again for your valuable feedback,
baruch

-- 
     http://baruch.siach.name/blog/                  ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch@tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -

WARNING: multiple messages have this Message-ID (diff)
From: baruch@tkos.co.il (Baruch Siach)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 2/2] mtd: nand: driver for Conexant Digicolor NAND Flash Controller
Date: Sun, 22 Feb 2015 10:19:23 +0200	[thread overview]
Message-ID: <20150222081923.GB2402@tarshish> (raw)
In-Reply-To: <20150219115223.40378b17@bbrezillon>

Hi Boris,

On Thu, Feb 19, 2015 at 11:52:23AM +0100, Boris Brezillon wrote:
> On Thu, 19 Feb 2015 11:43:01 +0200
> Baruch Siach <baruch@tkos.co.il> wrote:
> > On Thu, Feb 19, 2015 at 12:17:04AM +0100, Boris Brezillon wrote:
> > > On Thu, 12 Feb 2015 13:10:19 +0200
> > > Baruch Siach <baruch@tkos.co.il> wrote:
> > I understand you concern. However, since I don't have the needed hardware 
> > to test the multi nand chip setup I want to keep the code simple. These 
> > two fields are separated from the others by a blank line on purpose, and 
> > I'll also add a comment to explain that these are per nand chip files.
> 
> I'm not asking you to support multiple chips right now.
> What I'm asking here is to dispatch NFC and NAND fields in different
> structures:
> 
> struct digicolor_nand {
> 	struct mtd_info		mtd;
> 	struct nand_chip	nand;
> 
> 	u32 nand_cs;
> 	int t_ccs;
> }
> 
> struct digicolor_nfc {
> 	struct nand_hw_control	base;
> 	void __iomem		*regs;
> 	struct device		*dev;
> 
> 	unsigned long		clk_rate;
> 
> 	u32 ale_cmd;
> 	u32 ale_data;
> 	int ale_data_bytes;
> 
> 	/* Only support one NAND for now */
> 	struct digicolor_nand	nand;
> };
> 
> You'll keep the same logic except that this separation will be clearly
> visible.

Sounds reasonable. Will do.

[...]

> > It's just that the INT flag name is quite long, and it make the code using 
> > it less readable IMO. Maybe some macro trickery would do the job here.
> 
> Yep, if that's about avoiding over 80 character lines you could define
> such a macro:
> 
> #define NFC_RDY(flag)		NFC_INT_ ## flag ## _READY

Thanks for the tip. Will do.

[...]

> > I have no control of that. This command goes into a pipe that is managed 
> > at the hardware level. If the nand device does not activate the ready/busy 
> > signal, the pipe will just stall, and the command FIFO will overflow (the 
> > command FIFO has 8 entries). So you will notice the error eventually.
> 
> My point is: you should not return 1 if the NAND is not ready,
> waiting forever is not what I'm suggesting here, but you should find a
> way to return the actual NAND chip R/B status.
> If you don't have any solution to do that from your controller then you
> might consider relying on the default dev_ready implementation which is
> sending a NAND STATUS command to retrieve the R/B status.
> 
> What I'll say is in contradiction with what's done in the sunxi
> driver :-) (actually I'm considering fixing that), but after taking a
> closer look, dev_ready should only return the status of the NAND, and
> not wait for the NAND to be ready.
> The function responsible for waiting is waitfunc, maybe this is the one
> you should overload.

OK. I'll look into overloading waitfunc.

[...]

> > > > +static void digicolor_nfc_cmd_ctrl(struct mtd_info *mtd, int cmd,
> > > > +				   unsigned int ctrl)
> > > > +{
> > > > +	struct nand_chip *chip = mtd->priv;
> > > > +	struct digicolor_nfc *nfc = chip->priv;
> > > > +	u32 cs = nfc->nand_cs;
> > > > +
> > > > +	if (ctrl & NAND_CLE) {
> > > > +		digicolor_nfc_cmd_write(nfc,
> > > > +					CMD_CLE | CMD_CHIP_ENABLE(cs) | cmd);
> > > > +		if (cmd == NAND_CMD_RNDOUTSTART || cmd == NAND_CMD_RNDIN) {
> > > > +			digicolor_nfc_wait_ns(nfc, nfc->t_ccs);
> > > > +		} else if (cmd == NAND_CMD_RESET) {
> > > > +			digicolor_nfc_wait_ns(nfc, 200);
> > > > +			digicolor_nfc_dev_ready(mtd);
> > > > +		}
> > > 
> > > These wait and dev_ready calls are supposed to be part of the generic
> > > cmdfunc implementation, did you encounter any issues when relying on the
> > > default implementation ?
> > 
> > The generic code just waits. This doesn't help here. Hardware does all the 
> > command processing in its own schedule. To make the hardware wait I must 
> > explicitly insert a wait command into the pipe.
> 
> I'm not sure to understand here.
> There's a difference between:
> 1/ waiting for a NAND command to be send on the NAND bus
> 2/ waiting for the NAND to be ready (for DATA read or after a PROGRAM
>    operation)
> 
> NAND core is taking care of the 2/, but 1/ is your responsibility
> (and this is what you have to wait for here).

The generic code in nand_command_lp() sends NAND_CMD_STATUS immediately after 
NAND_CMD_RESET. According to the datasheet you must wait tWB (200ns max) 
before sending any command, including NAND_CMD_STATUS. Setting chip_delay is 
not enough as I explain above. That's way I added digicolor_nfc_wait_ns(). 
That timed wait is what I referred to. You are right that the 
digicolor_nfc_dev_ready() call is not needed here. Will remove.

[...]

> > > > +	while (len >= 4) {
> > > > +		if (digicolor_nfc_wait_ready(nfc, op))
> > > > +			return;
> > > > +		if (op == DATA_READ)
> > > > +			*pr++ = readl_relaxed(nfc->regs + NFC_DATA);
> > > > +		else
> > > > +			writel_relaxed(*pw++, nfc->regs + NFC_DATA);
> > > > +		len -= 4;
> > > > +	}
> > > 
> > > How about using readsl/writesl here (instead of this loop) ?
> > 
> > How can I add the wait condition in readsl/writesl?
> 
> Are you sure you have to wait after each readl access (is NFC_DATA
> interfaced with a FIFO or directly doing PIO access) ?

That's what the datasheet says. There is no mention of data FIFO in the 
datasheet.

[...]

> > > > +	/*
> > > > +	 * Maximum assert/deassert time; asynchronous SDR mode 0
> > > > +	 * Deassert time = max(tWH,tREH) = 30ns
> > > > +	 * Assert time = max(tRC,tRP,tWC,tWP) = 100ns
> > > > +	 * Sample time = 0
> > > > +	 */
> > > > +	timing |= TIMING_DEASSERT(DIV_ROUND_UP(30, ns_per_clk));
> > > > +	timing |= TIMING_ASSERT(DIV_ROUND_UP(100, ns_per_clk));
> > > > +	timing |= TIMING_SAMPLE(0);
> > > > +	writel_relaxed(timing, nfc->regs + NFC_TIMING_CONFIG);
> > > > +	writel_relaxed(NFC_CONTROL_ENABLE, nfc->regs + NFC_CONTROL);
> > > 
> > > Helper functions are provided to extract timings from ONFI timing modes
> > > (either those defined by the chip if it supports ONFI commands, or
> > > those extracted from the datasheet):
> > > 
> > > http://lxr.free-electrons.com/source/include/linux/mtd/nand.h#L976
> > 
> > I wanted to keep that for future improvement. The NAND chip on the EVK board 
> > is actually an old style one, neither ONFI nor JEDEC. I expect to test this 
> > driver on our target hardware that should have something newer.
> 
> Timings are not only related to ONFI chips, and
> onfi_timing_mode_default is extracted from the nand_ids table which is
> describing non-ONFI chips.
> 
> This is not my call to make, but IMHO, dynamic NAND timing
> configuration should be mandatory for new drivers.

I'll look into this for v2.

> > > > +static int digicolor_nfc_ecc_init(struct digicolor_nfc *nfc,
> > > > +				  struct device_node *np)
> > > > +{
> > > > +	struct mtd_info *mtd = &nfc->mtd;
> > > > +	struct nand_chip *chip = &nfc->nand;
> > > > +	int bch_data_range, bch_t, steps, mode, i;
> > > > +	u32 ctrl = NFC_CONTROL_ENABLE | NFC_CONTROL_BCH_KCONFIG;
> > > > +	struct nand_ecclayout *layout;
> > > > +
> > > > +	mode = of_get_nand_ecc_mode(np);
> > > > +	if (mode < 0)
> > > > +		return mode;
> > > > +	if (mode != NAND_ECC_HW_SYNDROME) {
> > > > +		dev_err(nfc->dev, "unsupported ECC mode\n");
> > > > +		return -EINVAL;
> > > > +	}
> > > > +
> > > > +	bch_data_range = of_get_nand_ecc_step_size(np);
> > > > +	if (bch_data_range < 0)
> > > > +		return bch_data_range;
> > > > +	if (bch_data_range != 512 && bch_data_range != 1024) {
> > > > +		dev_err(nfc->dev, "unsupported nand-ecc-step-size value\n");
> > > > +		return -EINVAL;
> > > > +	}
> > > > +	if (bch_data_range == 1024)
> > > > +		ctrl |= NFC_CONTROL_BCH_DATA_FIELD_RANGE_1024;
> > > > +	steps = mtd->writesize / bch_data_range;
> > > > +
> > > > +	bch_t = of_get_nand_ecc_strength(np);
> > > > +	if (bch_t < 0)
> > > > +		return bch_t;
> > > 
> > > You should fallback to datasheet values (ecc_strength_ds and
> > > ecc_step_ds) if ECC strength and step are not specified in the DT.
> > 
> > I can only choose from a fix number of strength configuration alternatives. 
> > Should I choose the lowest value that is larger than ecc_strength_ds?
> 
> Yep, this applies to both cases (information extracted from the DT and
> _ds values).

OK. Will do.

Thanks again for your valuable feedback,
baruch

-- 
     http://baruch.siach.name/blog/                  ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -

WARNING: multiple messages have this Message-ID (diff)
From: Baruch Siach <baruch-NswTu9S1W3P6gbPvEgmw2w@public.gmane.org>
To: Boris Brezillon
	<boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Cc: David Woodhouse <dwmw2-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org>,
	Brian Norris
	<computersforpeace-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
Subject: Re: [PATCH 2/2] mtd: nand: driver for Conexant Digicolor NAND Flash Controller
Date: Sun, 22 Feb 2015 10:19:23 +0200	[thread overview]
Message-ID: <20150222081923.GB2402@tarshish> (raw)
In-Reply-To: <20150219115223.40378b17@bbrezillon>

Hi Boris,

On Thu, Feb 19, 2015 at 11:52:23AM +0100, Boris Brezillon wrote:
> On Thu, 19 Feb 2015 11:43:01 +0200
> Baruch Siach <baruch-NswTu9S1W3P6gbPvEgmw2w@public.gmane.org> wrote:
> > On Thu, Feb 19, 2015 at 12:17:04AM +0100, Boris Brezillon wrote:
> > > On Thu, 12 Feb 2015 13:10:19 +0200
> > > Baruch Siach <baruch-NswTu9S1W3P6gbPvEgmw2w@public.gmane.org> wrote:
> > I understand you concern. However, since I don't have the needed hardware 
> > to test the multi nand chip setup I want to keep the code simple. These 
> > two fields are separated from the others by a blank line on purpose, and 
> > I'll also add a comment to explain that these are per nand chip files.
> 
> I'm not asking you to support multiple chips right now.
> What I'm asking here is to dispatch NFC and NAND fields in different
> structures:
> 
> struct digicolor_nand {
> 	struct mtd_info		mtd;
> 	struct nand_chip	nand;
> 
> 	u32 nand_cs;
> 	int t_ccs;
> }
> 
> struct digicolor_nfc {
> 	struct nand_hw_control	base;
> 	void __iomem		*regs;
> 	struct device		*dev;
> 
> 	unsigned long		clk_rate;
> 
> 	u32 ale_cmd;
> 	u32 ale_data;
> 	int ale_data_bytes;
> 
> 	/* Only support one NAND for now */
> 	struct digicolor_nand	nand;
> };
> 
> You'll keep the same logic except that this separation will be clearly
> visible.

Sounds reasonable. Will do.

[...]

> > It's just that the INT flag name is quite long, and it make the code using 
> > it less readable IMO. Maybe some macro trickery would do the job here.
> 
> Yep, if that's about avoiding over 80 character lines you could define
> such a macro:
> 
> #define NFC_RDY(flag)		NFC_INT_ ## flag ## _READY

Thanks for the tip. Will do.

[...]

> > I have no control of that. This command goes into a pipe that is managed 
> > at the hardware level. If the nand device does not activate the ready/busy 
> > signal, the pipe will just stall, and the command FIFO will overflow (the 
> > command FIFO has 8 entries). So you will notice the error eventually.
> 
> My point is: you should not return 1 if the NAND is not ready,
> waiting forever is not what I'm suggesting here, but you should find a
> way to return the actual NAND chip R/B status.
> If you don't have any solution to do that from your controller then you
> might consider relying on the default dev_ready implementation which is
> sending a NAND STATUS command to retrieve the R/B status.
> 
> What I'll say is in contradiction with what's done in the sunxi
> driver :-) (actually I'm considering fixing that), but after taking a
> closer look, dev_ready should only return the status of the NAND, and
> not wait for the NAND to be ready.
> The function responsible for waiting is waitfunc, maybe this is the one
> you should overload.

OK. I'll look into overloading waitfunc.

[...]

> > > > +static void digicolor_nfc_cmd_ctrl(struct mtd_info *mtd, int cmd,
> > > > +				   unsigned int ctrl)
> > > > +{
> > > > +	struct nand_chip *chip = mtd->priv;
> > > > +	struct digicolor_nfc *nfc = chip->priv;
> > > > +	u32 cs = nfc->nand_cs;
> > > > +
> > > > +	if (ctrl & NAND_CLE) {
> > > > +		digicolor_nfc_cmd_write(nfc,
> > > > +					CMD_CLE | CMD_CHIP_ENABLE(cs) | cmd);
> > > > +		if (cmd == NAND_CMD_RNDOUTSTART || cmd == NAND_CMD_RNDIN) {
> > > > +			digicolor_nfc_wait_ns(nfc, nfc->t_ccs);
> > > > +		} else if (cmd == NAND_CMD_RESET) {
> > > > +			digicolor_nfc_wait_ns(nfc, 200);
> > > > +			digicolor_nfc_dev_ready(mtd);
> > > > +		}
> > > 
> > > These wait and dev_ready calls are supposed to be part of the generic
> > > cmdfunc implementation, did you encounter any issues when relying on the
> > > default implementation ?
> > 
> > The generic code just waits. This doesn't help here. Hardware does all the 
> > command processing in its own schedule. To make the hardware wait I must 
> > explicitly insert a wait command into the pipe.
> 
> I'm not sure to understand here.
> There's a difference between:
> 1/ waiting for a NAND command to be send on the NAND bus
> 2/ waiting for the NAND to be ready (for DATA read or after a PROGRAM
>    operation)
> 
> NAND core is taking care of the 2/, but 1/ is your responsibility
> (and this is what you have to wait for here).

The generic code in nand_command_lp() sends NAND_CMD_STATUS immediately after 
NAND_CMD_RESET. According to the datasheet you must wait tWB (200ns max) 
before sending any command, including NAND_CMD_STATUS. Setting chip_delay is 
not enough as I explain above. That's way I added digicolor_nfc_wait_ns(). 
That timed wait is what I referred to. You are right that the 
digicolor_nfc_dev_ready() call is not needed here. Will remove.

[...]

> > > > +	while (len >= 4) {
> > > > +		if (digicolor_nfc_wait_ready(nfc, op))
> > > > +			return;
> > > > +		if (op == DATA_READ)
> > > > +			*pr++ = readl_relaxed(nfc->regs + NFC_DATA);
> > > > +		else
> > > > +			writel_relaxed(*pw++, nfc->regs + NFC_DATA);
> > > > +		len -= 4;
> > > > +	}
> > > 
> > > How about using readsl/writesl here (instead of this loop) ?
> > 
> > How can I add the wait condition in readsl/writesl?
> 
> Are you sure you have to wait after each readl access (is NFC_DATA
> interfaced with a FIFO or directly doing PIO access) ?

That's what the datasheet says. There is no mention of data FIFO in the 
datasheet.

[...]

> > > > +	/*
> > > > +	 * Maximum assert/deassert time; asynchronous SDR mode 0
> > > > +	 * Deassert time = max(tWH,tREH) = 30ns
> > > > +	 * Assert time = max(tRC,tRP,tWC,tWP) = 100ns
> > > > +	 * Sample time = 0
> > > > +	 */
> > > > +	timing |= TIMING_DEASSERT(DIV_ROUND_UP(30, ns_per_clk));
> > > > +	timing |= TIMING_ASSERT(DIV_ROUND_UP(100, ns_per_clk));
> > > > +	timing |= TIMING_SAMPLE(0);
> > > > +	writel_relaxed(timing, nfc->regs + NFC_TIMING_CONFIG);
> > > > +	writel_relaxed(NFC_CONTROL_ENABLE, nfc->regs + NFC_CONTROL);
> > > 
> > > Helper functions are provided to extract timings from ONFI timing modes
> > > (either those defined by the chip if it supports ONFI commands, or
> > > those extracted from the datasheet):
> > > 
> > > http://lxr.free-electrons.com/source/include/linux/mtd/nand.h#L976
> > 
> > I wanted to keep that for future improvement. The NAND chip on the EVK board 
> > is actually an old style one, neither ONFI nor JEDEC. I expect to test this 
> > driver on our target hardware that should have something newer.
> 
> Timings are not only related to ONFI chips, and
> onfi_timing_mode_default is extracted from the nand_ids table which is
> describing non-ONFI chips.
> 
> This is not my call to make, but IMHO, dynamic NAND timing
> configuration should be mandatory for new drivers.

I'll look into this for v2.

> > > > +static int digicolor_nfc_ecc_init(struct digicolor_nfc *nfc,
> > > > +				  struct device_node *np)
> > > > +{
> > > > +	struct mtd_info *mtd = &nfc->mtd;
> > > > +	struct nand_chip *chip = &nfc->nand;
> > > > +	int bch_data_range, bch_t, steps, mode, i;
> > > > +	u32 ctrl = NFC_CONTROL_ENABLE | NFC_CONTROL_BCH_KCONFIG;
> > > > +	struct nand_ecclayout *layout;
> > > > +
> > > > +	mode = of_get_nand_ecc_mode(np);
> > > > +	if (mode < 0)
> > > > +		return mode;
> > > > +	if (mode != NAND_ECC_HW_SYNDROME) {
> > > > +		dev_err(nfc->dev, "unsupported ECC mode\n");
> > > > +		return -EINVAL;
> > > > +	}
> > > > +
> > > > +	bch_data_range = of_get_nand_ecc_step_size(np);
> > > > +	if (bch_data_range < 0)
> > > > +		return bch_data_range;
> > > > +	if (bch_data_range != 512 && bch_data_range != 1024) {
> > > > +		dev_err(nfc->dev, "unsupported nand-ecc-step-size value\n");
> > > > +		return -EINVAL;
> > > > +	}
> > > > +	if (bch_data_range == 1024)
> > > > +		ctrl |= NFC_CONTROL_BCH_DATA_FIELD_RANGE_1024;
> > > > +	steps = mtd->writesize / bch_data_range;
> > > > +
> > > > +	bch_t = of_get_nand_ecc_strength(np);
> > > > +	if (bch_t < 0)
> > > > +		return bch_t;
> > > 
> > > You should fallback to datasheet values (ecc_strength_ds and
> > > ecc_step_ds) if ECC strength and step are not specified in the DT.
> > 
> > I can only choose from a fix number of strength configuration alternatives. 
> > Should I choose the lowest value that is larger than ecc_strength_ds?
> 
> Yep, this applies to both cases (information extracted from the DT and
> _ds values).

OK. Will do.

Thanks again for your valuable feedback,
baruch

-- 
     http://baruch.siach.name/blog/                  ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch-NswTu9S1W3P6gbPvEgmw2w@public.gmane.org - tel: +972.2.679.5364, http://www.tkos.co.il -
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

  reply	other threads:[~2015-02-22  8:19 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-02-12 11:10 [PATCH 1/2] mtd: nand: dt binding documentation for digicolor NFC Baruch Siach
2015-02-12 11:10 ` Baruch Siach
2015-02-12 11:10 ` Baruch Siach
2015-02-12 11:10 ` [PATCH 2/2] mtd: nand: driver for Conexant Digicolor NAND Flash Controller Baruch Siach
2015-02-12 11:10   ` Baruch Siach
2015-02-12 11:10   ` Baruch Siach
2015-02-18 23:17   ` Boris Brezillon
2015-02-18 23:17     ` Boris Brezillon
2015-02-18 23:17     ` Boris Brezillon
2015-02-19  9:43     ` Baruch Siach
2015-02-19  9:43       ` Baruch Siach
2015-02-19  9:43       ` Baruch Siach
2015-02-19 10:52       ` Boris Brezillon
2015-02-19 10:52         ` Boris Brezillon
2015-02-19 10:52         ` Boris Brezillon
2015-02-22  8:19         ` Baruch Siach [this message]
2015-02-22  8:19           ` Baruch Siach
2015-02-22  8:19           ` Baruch Siach

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150222081923.GB2402@tarshish \
    --to=baruch@tkos.co.il \
    --cc=boris.brezillon@free-electrons.com \
    --cc=computersforpeace@gmail.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dwmw2@infradead.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-mtd@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.