2022-01-20 04:21:45

by Dario Binacchi

[permalink] [raw]
Subject: [PATCH 0/4] Fix and improve gpmi nand on mx28

Starting from [1], the series fixes the timings setting of the gpmi
controller for the mx28 architecture, also adding support for fast
edo mode timings. The whole series has been heavily tested with the
mtd kernel test modules, and with repeated write cycles on nand.

The whole series has been tested and reviewed by Sascha Hauer <[email protected]>,
so I removed the RFC prefix and re-submitted it as a regular patch
set by adding the 'Tested-by' and 'Review-by' tags to every single patch.

[1] https://lore.kernel.org/r/[email protected]


Dario Binacchi (4):
ARM: dts: imx28: reparent gpmi clock to ref_gpmi
mtd: rawnand: gpmi: fix controller timings setting
mtd: rawnand: gpmi: validate controller clock rate
mtd: rawnand: gpmi: support fast edo timings for mx28

arch/arm/boot/dts/imx28.dtsi | 2 ++
drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 27 ++++++++++++++++++----
2 files changed, 24 insertions(+), 5 deletions(-)

--
2.32.0


2022-01-20 04:26:14

by Dario Binacchi

[permalink] [raw]
Subject: [PATCH 1/4] ARM: dts: imx28: reparent gpmi clock to ref_gpmi

Since ref_gpmi is sourced from pll0 (480MHz), It allows the GPMI
controller to manage High-Speed ​​NAND Timing (edo mode 3,4 and 5).

Co-developed-by: Michael Trimarchi <[email protected]>
Signed-off-by: Michael Trimarchi <[email protected]>
Signed-off-by: Dario Binacchi <[email protected]>
Tested-by: Sascha Hauer <[email protected]>
Reviewed-by: Sascha Hauer <[email protected]>

---

arch/arm/boot/dts/imx28.dtsi | 2 ++
1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index 84d0176d5193..130b4145af82 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -110,6 +110,8 @@ gpmi: nand-controller@8000c000 {
interrupt-names = "bch";
clocks = <&clks 50>;
clock-names = "gpmi_io";
+ assigned-clocks = <&clks 13>;
+ assigned-clock-parents = <&clks 10>;
dmas = <&dma_apbh 4>;
dma-names = "rx-tx";
status = "disabled";
--
2.32.0

2022-01-20 04:26:14

by Dario Binacchi

[permalink] [raw]
Subject: [PATCH 2/4] mtd: rawnand: gpmi: fix controller timings setting

Set the controller registers according to the real clock rate. The
controller registers configuration (setup, hold, timeout, ... cycles)
depends on the clock rate of the GPMI. Using the real rate instead of
the ideal one, avoids that this inaccuracy (required_rate - real_rate)
affects the registers setting.

This patch has been tested on two custom boards with i.MX28 and i.MX6
SOCs:
- i.MX28:
required rate 100MHz, real rate 99.3MHz
- i.MX6
required rate 100MHz, real rate 99MHz

Fixes: b1206122069a ("mtd: rawnand: gpmi: use core timings instead of an empirical derivation")
Co-developed-by: Michael Trimarchi <[email protected]>
Signed-off-by: Michael Trimarchi <[email protected]>
Signed-off-by: Dario Binacchi <[email protected]>
Tested-by: Sascha Hauer <[email protected]>
Reviewed-by: Sascha Hauer <[email protected]>
---

drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index 1b64c5a5140d..73c3bf59b55e 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -648,6 +648,7 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
const struct nand_sdr_timings *sdr)
{
struct gpmi_nfc_hardware_timing *hw = &this->hw;
+ struct resources *r = &this->resources;
unsigned int dll_threshold_ps = this->devdata->max_chain_delay;
unsigned int period_ps, reference_period_ps;
unsigned int data_setup_cycles, data_hold_cycles, addr_setup_cycles;
@@ -671,6 +672,8 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
}

+ hw->clk_rate = clk_round_rate(r->clock[0], hw->clk_rate);
+
/* SDR core timings are given in picoseconds */
period_ps = div_u64((u64)NSEC_PER_SEC * 1000, hw->clk_rate);

--
2.32.0

2022-01-20 04:27:01

by Dario Binacchi

[permalink] [raw]
Subject: [PATCH 4/4] mtd: rawnand: gpmi: support fast edo timings for mx28

In the i.MX28 manual (MCIMX28RM, Rev. 1, 2010) you can find an example
(15.2.4 High-Speed NAND Timing) of how to configure the GPMI controller
to manage High-Speed ​​NAND devices, so it was wrong to assume that only
i.MX6 can achieve EDO timings.

This patch has been tested on a 2048/64 byte NAND (Micron MT29F2G08ABAEAH4).
Kernel mtd tests:
- mtd_nandbiterrs
- mtd_nandecctest
- mtd_oobtest
- mtd_pagetest
- mtd_readtest
- mtd_speedtest
- mtd_stresstest
- mtd_subpagetest
- mtd_torturetest [cycles_count = 10000000]
run without errors.

Before this patch (mode 0):
---------------------------
eraseblock write speed is 2098 KiB/s
eraseblock read speed is 2680 KiB/s
page write speed is 1689 KiB/s
page read speed is 2522 KiB/s
2 page write speed is 1899 KiB/s
2 page read speed is 2579 KiB/s
erase speed is 128000 KiB/s
2x multi-block erase speed is 73142 KiB/s
4x multi-block erase speed is 204800 KiB/s
8x multi-block erase speed is 256000 KiB/s
16x multi-block erase speed is 256000 KiB/s
32x multi-block erase speed is 256000 KiB/s
64x multi-block erase speed is 256000 KiB/s

After this patch (mode 5):
-------------------------
eraseblock write speed is 3390 KiB/s
eraseblock read speed is 5688 KiB/s
page write speed is 2680 KiB/s
page read speed is 4876 KiB/s
2 page write speed is 2909 KiB/s
2 page read speed is 5224 KiB/s
erase speed is 170666 KiB/s
2x multi-block erase speed is 204800 KiB/s
4x multi-block erase speed is 256000 KiB/s
8x multi-block erase speed is 256000 KiB/s
16x multi-block erase speed is 256000 KiB/s
32x multi-block erase speed is 256000 KiB/s
64x multi-block erase speed is 256000 KiB/s

Co-developed-by: Michael Trimarchi <[email protected]>
Signed-off-by: Michael Trimarchi <[email protected]>
Signed-off-by: Dario Binacchi <[email protected]>
Tested-by: Sascha Hauer <[email protected]>
Reviewed-by: Sascha Hauer <[email protected]>

---

drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index cf35f4206030..d96899fa90b7 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -787,8 +787,8 @@ static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
if (IS_ERR(sdr))
return PTR_ERR(sdr);

- /* Only MX6 GPMI controller can reach EDO timings */
- if (sdr->tRC_min <= 25000 && !GPMI_IS_MX6(this))
+ /* Only MX28/MX6 GPMI controller can reach EDO timings */
+ if (sdr->tRC_min <= 25000 && !GPMI_IS_MX28(this) && !GPMI_IS_MX6(this))
return -ENOTSUPP;

/* Stop here if this call was just a check */
--
2.32.0

2022-01-20 04:27:02

by Dario Binacchi

[permalink] [raw]
Subject: [PATCH 3/4] mtd: rawnand: gpmi: validate controller clock rate

What to do when the real rate of the gpmi clock is not equal to the
required one? The solutions proposed in [1] did not lead to a conclusion
on how to validate the clock rate, so, inspired by the document [2], I
consider the rate correct only if not lower or equal to the rate of the
previous edo mode. In fact, in chapter 4.16.2 (NV-DDR) of the document [2],
it is written that "If the host selects timing mode n, then its clock
period shall be faster than the clock period of timing mode n-1 and
slower than or equal to the clock period of timing mode n.". I thought
that it could therefore also be used in this case, without therefore
having to define the valid rate ranges empirically.

For example, suppose that gpmi_nfc_compute_timings() is called to set
edo mode 5 (100MHz) but the rate returned by clk_round_rate() is 80MHz
(edo mode 4). In this case gpmi_nfc_compute_timings() will return error,
and will be called again to set edo mode 4, which this time will be
successful.

[1] https://lore.kernel.org/r/[email protected]
[2] http://www.onfi.org/-/media/client/onfi/specs/onfi_3_0_gold.pdf?la=en

Co-developed-by: Michael Trimarchi <[email protected]>
Signed-off-by: Michael Trimarchi <[email protected]>
Signed-off-by: Dario Binacchi <[email protected]>
Tested-by: Sascha Hauer <[email protected]>
Reviewed-by: Sascha Hauer <[email protected]>
---

drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index 73c3bf59b55e..cf35f4206030 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -644,8 +644,8 @@ static int bch_set_geometry(struct gpmi_nand_data *this)
* RDN_DELAY = ----------------------- {3}
* RP
*/
-static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
- const struct nand_sdr_timings *sdr)
+static int gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
+ const struct nand_sdr_timings *sdr)
{
struct gpmi_nfc_hardware_timing *hw = &this->hw;
struct resources *r = &this->resources;
@@ -657,23 +657,33 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
int sample_delay_ps, sample_delay_factor;
u16 busy_timeout_cycles;
u8 wrn_dly_sel;
+ unsigned long clk_rate, min_rate;

if (sdr->tRC_min >= 30000) {
/* ONFI non-EDO modes [0-3] */
hw->clk_rate = 22000000;
+ min_rate = 0;
wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_4_TO_8NS;
} else if (sdr->tRC_min >= 25000) {
/* ONFI EDO mode 4 */
hw->clk_rate = 80000000;
+ min_rate = 22000000;
wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
} else {
/* ONFI EDO mode 5 */
hw->clk_rate = 100000000;
+ min_rate = 80000000;
wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
}

- hw->clk_rate = clk_round_rate(r->clock[0], hw->clk_rate);
+ clk_rate = clk_round_rate(r->clock[0], hw->clk_rate);
+ if (clk_rate <= min_rate) {
+ dev_err(this->dev, "clock setting: expected %ld, got %ld\n",
+ hw->clk_rate, clk_rate);
+ return -ENOTSUPP;
+ }

+ hw->clk_rate = clk_rate;
/* SDR core timings are given in picoseconds */
period_ps = div_u64((u64)NSEC_PER_SEC * 1000, hw->clk_rate);

@@ -714,6 +724,7 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
hw->ctrl1n |= BF_GPMI_CTRL1_RDN_DELAY(sample_delay_factor) |
BM_GPMI_CTRL1_DLL_ENABLE |
(use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD : 0);
+ return 0;
}

static int gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
@@ -769,6 +780,7 @@ static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
{
struct gpmi_nand_data *this = nand_get_controller_data(chip);
const struct nand_sdr_timings *sdr;
+ int ret;

/* Retrieve required NAND timings */
sdr = nand_get_sdr_timings(conf);
@@ -784,7 +796,9 @@ static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
return 0;

/* Do the actual derivation of the controller timings */
- gpmi_nfc_compute_timings(this, sdr);
+ ret = gpmi_nfc_compute_timings(this, sdr);
+ if (ret)
+ return ret;

this->hw.must_apply_timings = true;

--
2.32.0

2022-01-24 09:14:49

by Miquel Raynal

[permalink] [raw]
Subject: Re: [PATCH 2/4] mtd: rawnand: gpmi: fix controller timings setting

On Tue, 2022-01-18 at 09:54:32 UTC, Dario Binacchi wrote:
> Set the controller registers according to the real clock rate. The
> controller registers configuration (setup, hold, timeout, ... cycles)
> depends on the clock rate of the GPMI. Using the real rate instead of
> the ideal one, avoids that this inaccuracy (required_rate - real_rate)
> affects the registers setting.
>
> This patch has been tested on two custom boards with i.MX28 and i.MX6
> SOCs:
> - i.MX28:
> required rate 100MHz, real rate 99.3MHz
> - i.MX6
> required rate 100MHz, real rate 99MHz
>
> Fixes: b1206122069a ("mtd: rawnand: gpmi: use core timings instead of an empirical derivation")
> Co-developed-by: Michael Trimarchi <[email protected]>
> Signed-off-by: Michael Trimarchi <[email protected]>
> Signed-off-by: Dario Binacchi <[email protected]>
> Tested-by: Sascha Hauer <[email protected]>
> Reviewed-by: Sascha Hauer <[email protected]>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next, thanks.

Miquel

2022-01-24 09:44:02

by Miquel Raynal

[permalink] [raw]
Subject: Re: [PATCH 4/4] mtd: rawnand: gpmi: support fast edo timings for mx28

On Tue, 2022-01-18 at 09:54:34 UTC, Dario Binacchi wrote:
> In the i.MX28 manual (MCIMX28RM, Rev. 1, 2010) you can find an example
> (15.2.4 High-Speed NAND Timing) of how to configure the GPMI controller
> to manage High-Speed ​​NAND devices, so it was wrong to assume that only
> i.MX6 can achieve EDO timings.
>
> This patch has been tested on a 2048/64 byte NAND (Micron MT29F2G08ABAEAH4).
> Kernel mtd tests:
> - mtd_nandbiterrs
> - mtd_nandecctest
> - mtd_oobtest
> - mtd_pagetest
> - mtd_readtest
> - mtd_speedtest
> - mtd_stresstest
> - mtd_subpagetest
> - mtd_torturetest [cycles_count = 10000000]
> run without errors.
>
> Before this patch (mode 0):
> ---------------------------
> eraseblock write speed is 2098 KiB/s
> eraseblock read speed is 2680 KiB/s
> page write speed is 1689 KiB/s
> page read speed is 2522 KiB/s
> 2 page write speed is 1899 KiB/s
> 2 page read speed is 2579 KiB/s
> erase speed is 128000 KiB/s
> 2x multi-block erase speed is 73142 KiB/s
> 4x multi-block erase speed is 204800 KiB/s
> 8x multi-block erase speed is 256000 KiB/s
> 16x multi-block erase speed is 256000 KiB/s
> 32x multi-block erase speed is 256000 KiB/s
> 64x multi-block erase speed is 256000 KiB/s
>
> After this patch (mode 5):
> -------------------------
> eraseblock write speed is 3390 KiB/s
> eraseblock read speed is 5688 KiB/s
> page write speed is 2680 KiB/s
> page read speed is 4876 KiB/s
> 2 page write speed is 2909 KiB/s
> 2 page read speed is 5224 KiB/s
> erase speed is 170666 KiB/s
> 2x multi-block erase speed is 204800 KiB/s
> 4x multi-block erase speed is 256000 KiB/s
> 8x multi-block erase speed is 256000 KiB/s
> 16x multi-block erase speed is 256000 KiB/s
> 32x multi-block erase speed is 256000 KiB/s
> 64x multi-block erase speed is 256000 KiB/s
>
> Co-developed-by: Michael Trimarchi <[email protected]>
> Signed-off-by: Michael Trimarchi <[email protected]>
> Signed-off-by: Dario Binacchi <[email protected]>
> Tested-by: Sascha Hauer <[email protected]>
> Reviewed-by: Sascha Hauer <[email protected]>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next, thanks.

Miquel

2022-01-24 09:44:15

by Miquel Raynal

[permalink] [raw]
Subject: Re: [PATCH 3/4] mtd: rawnand: gpmi: validate controller clock rate

On Tue, 2022-01-18 at 09:54:33 UTC, Dario Binacchi wrote:
> What to do when the real rate of the gpmi clock is not equal to the
> required one? The solutions proposed in [1] did not lead to a conclusion
> on how to validate the clock rate, so, inspired by the document [2], I
> consider the rate correct only if not lower or equal to the rate of the
> previous edo mode. In fact, in chapter 4.16.2 (NV-DDR) of the document [2],
> it is written that "If the host selects timing mode n, then its clock
> period shall be faster than the clock period of timing mode n-1 and
> slower than or equal to the clock period of timing mode n.". I thought
> that it could therefore also be used in this case, without therefore
> having to define the valid rate ranges empirically.
>
> For example, suppose that gpmi_nfc_compute_timings() is called to set
> edo mode 5 (100MHz) but the rate returned by clk_round_rate() is 80MHz
> (edo mode 4). In this case gpmi_nfc_compute_timings() will return error,
> and will be called again to set edo mode 4, which this time will be
> successful.
>
> [1] https://lore.kernel.org/r/[email protected]
> [2] http://www.onfi.org/-/media/client/onfi/specs/onfi_3_0_gold.pdf?la=en
>
> Co-developed-by: Michael Trimarchi <[email protected]>
> Signed-off-by: Michael Trimarchi <[email protected]>
> Signed-off-by: Dario Binacchi <[email protected]>
> Tested-by: Sascha Hauer <[email protected]>
> Reviewed-by: Sascha Hauer <[email protected]>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next, thanks.

Miquel