2022-10-19 08:32:01

by Vadym Kochan

[permalink] [raw]
Subject: [PATCH 0/3] mtd: rawnand: marvell: add support for AC5 SoC

This series adds support for AC5 SoC.

The following changes were made to add AC5 support:

1) Modify Marvell nand NFC timing set for mode 0

2) fix validation in AC5 Nand driver for ONFI timings values modes 1 and 3

3) remove unnecessary nand timing-mode in device tree of ac5.dtsi

4) add nand missing AC5X layouts , add option to use ndtr predefined values

5) Zero steps and total fields of ecc in ecc controller initialization so
nand_scan_tail() will calculate these two fields, otherwise
NAND initialization will fail with kernel 5.15 and above.

Aviram Dali (2):
dt-bindings: mtd: Add AC5 specific binding
mtd: rawnand: marvell: add support for AC5 SoC

Vadym Kochan (1):
mtd: rawnand: Partially revert 4114f97c41cd ("mtd: rawnand: Get rid of
a few unused definitions")

.../devicetree/bindings/mtd/marvell-nand.txt | 1 +
drivers/mtd/nand/raw/Kconfig | 2 +-
drivers/mtd/nand/raw/marvell_nand.c | 277 ++++++++++++++++--
drivers/mtd/nand/raw/nand_timings.c | 14 +
include/linux/mtd/rawnand.h | 3 +
5 files changed, 264 insertions(+), 33 deletions(-)

--
2.17.1


2022-10-19 08:33:15

by Vadym Kochan

[permalink] [raw]
Subject: [PATCH 2/3] dt-bindings: mtd: Add AC5 specific binding

From: Aviram Dali <[email protected]>

Add binding for AC5 SoC which have its special way of handing
NAND layout.

Signed-off-by: Aviram Dali <[email protected]>
Signed-off-by: Vadym Kochan <[email protected]>
---
Documentation/devicetree/bindings/mtd/marvell-nand.txt | 1 +
1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/mtd/marvell-nand.txt b/Documentation/devicetree/bindings/mtd/marvell-nand.txt
index a2d9a0f2b683..293551ec7350 100644
--- a/Documentation/devicetree/bindings/mtd/marvell-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/marvell-nand.txt
@@ -2,6 +2,7 @@ Marvell NAND Flash Controller (NFC)

Required properties:
- compatible: can be one of the following:
+ * "marvell,ac5-nand-controller"
* "marvell,armada-8k-nand-controller"
* "marvell,armada370-nand-controller"
* "marvell,pxa3xx-nand-controller"
--
2.17.1

2022-10-19 09:20:46

by Vadym Kochan

[permalink] [raw]
Subject: [PATCH 3/3] mtd: rawnand: marvell: add support for AC5 SoC

From: Aviram Dali <[email protected]>

The following changes were made to add AC5 support:

1) Modify Marvell nand NFC timing set for mode 0

2) fix validation in AC5 Nand driver for ONFI timings values modes 1 and 3

3) remove unnecessary nand timing-mode in device tree of ac5.dtsi

4) add nand missing AC5X layouts , add option to use ndtr predefined values

5) Zero steps and total fields of ecc in ecc controller initialization so
nand_scan_tail() will calculate these two fields, otherwise
NAND initialization will fail with kernel 5.15 and above.

Signed-off-by: Aviram Dali <[email protected]>
Signed-off-by: Vadym Kochan <[email protected]>
---
drivers/mtd/nand/raw/Kconfig | 2 +-
drivers/mtd/nand/raw/marvell_nand.c | 277 ++++++++++++++++++++++++----
2 files changed, 246 insertions(+), 33 deletions(-)

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 4cd40af362de..b7bb62f27e02 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -160,7 +160,7 @@ config MTD_NAND_MARVELL
including:
- PXA3xx processors (NFCv1)
- 32-bit Armada platforms (XP, 37x, 38x, 39x) (NFCv2)
- - 64-bit Aramda platforms (7k, 8k) (NFCv2)
+ - 64-bit Aramda platforms (7k, 8k, ac5) (NFCv2)

config MTD_NAND_SLC_LPC32XX
tristate "NXP LPC32xx SLC NAND controller"
diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c
index b9d1e96e3334..940a89115782 100644
--- a/drivers/mtd/nand/raw/marvell_nand.c
+++ b/drivers/mtd/nand/raw/marvell_nand.c
@@ -226,6 +226,20 @@
#define XTYPE_COMMAND_DISPATCH 6
#define XTYPE_MASK 7

+/* use tRP_min, tWC_min and tWP_min to distinct across timings modes */
+#define IS_TIMINGS_EQUAL(t1, t2) \
+ ((t1->tRP_min == t2->tRP_min &&\
+ t1->tWC_min == t2->tWC_min &&\
+ t1->tWP_min == t2->tWP_min) ? true : false)
+
+/* ndtr0,1 set , each set has few modes level */
+typedef enum marvell_nfc_timing_mode_set {
+ MARVELL_NFC_NDTR_SET_0, /* tested with ac5 */
+
+ MARVELL_NFC_NDTR_NUM_OF_SET,
+ MARVELL_NFC_NDTR_SET_NON = MARVELL_NFC_NDTR_NUM_OF_SET
+} marvell_nfc_timing_mode_set_t;
+
/**
* struct marvell_hw_ecc_layout - layout of Marvell ECC
*
@@ -283,14 +297,21 @@ struct marvell_hw_ecc_layout {

/* Layouts explained in AN-379_Marvell_SoC_NFC_ECC */
static const struct marvell_hw_ecc_layout marvell_nfc_layouts[] = {
- MARVELL_LAYOUT( 512, 512, 1, 1, 1, 512, 8, 8, 0, 0, 0),
- MARVELL_LAYOUT( 2048, 512, 1, 1, 1, 2048, 40, 24, 0, 0, 0),
- MARVELL_LAYOUT( 2048, 512, 4, 1, 1, 2048, 32, 30, 0, 0, 0),
- MARVELL_LAYOUT( 2048, 512, 8, 2, 1, 1024, 0, 30,1024,32, 30),
- MARVELL_LAYOUT( 4096, 512, 4, 2, 2, 2048, 32, 30, 0, 0, 0),
- MARVELL_LAYOUT( 4096, 512, 8, 5, 4, 1024, 0, 30, 0, 64, 30),
- MARVELL_LAYOUT( 8192, 512, 4, 4, 4, 2048, 0, 30, 0, 0, 0),
- MARVELL_LAYOUT( 8192, 512, 8, 9, 8, 1024, 0, 30, 0, 160, 30),
+ MARVELL_LAYOUT(512, 512, 1, 1, 1, 512, 8, 8, 0, 0, 0),
+ MARVELL_LAYOUT(2048, 512, 1, 1, 1, 2048, 40, 24, 0, 0, 0),
+ MARVELL_LAYOUT(2048, 512, 4, 1, 1, 2048, 32, 30, 0, 0, 0),
+ MARVELL_LAYOUT(2048, 512, 8, 2, 1, 1024, 0, 30, 1024, 32, 30),
+ MARVELL_LAYOUT(2048, 512, 8, 2, 1, 1024, 0, 30, 1024, 64, 30),
+ MARVELL_LAYOUT(2048, 512, 12, 3, 2, 704, 0, 30, 640, 0, 30),
+ MARVELL_LAYOUT(2048, 512, 16, 5, 4, 512, 0, 30, 0, 32, 30),
+ MARVELL_LAYOUT(4096, 512, 4, 2, 2, 2048, 32, 30, 0, 0, 0),
+ MARVELL_LAYOUT(4096, 512, 8, 5, 4, 1024, 0, 30, 0, 64, 30),
+ MARVELL_LAYOUT(4096, 512, 12, 6, 5, 704, 0, 30, 576, 32, 30),
+ MARVELL_LAYOUT(4096, 512, 16, 9, 8, 512, 0, 30, 0, 32, 30),
+ MARVELL_LAYOUT(8192, 512, 4, 4, 4, 2048, 0, 30, 0, 0, 0),
+ MARVELL_LAYOUT(8192, 512, 8, 9, 8, 1024, 0, 30, 0, 160, 30),
+ MARVELL_LAYOUT(8192, 512, 12, 12, 11, 704, 0, 30, 448, 64, 30),
+ MARVELL_LAYOUT(8192, 512, 16, 17, 16, 512, 0, 30, 0, 32, 30),
};

/**
@@ -328,6 +349,7 @@ struct marvell_nand_chip_sel {
* @selected_die: Current active CS
* @nsels: Number of CS lines required by the NAND chip
* @sels: Array of CS lines descriptions
+ * @nand_timing_mode: nand-timing-mode from dts
*/
struct marvell_nand_chip {
struct nand_chip chip;
@@ -339,6 +361,7 @@ struct marvell_nand_chip {
int addr_cyc;
int selected_die;
unsigned int nsels;
+ int nand_timing_mode;
struct marvell_nand_chip_sel sels[];
};

@@ -367,6 +390,10 @@ static inline struct marvell_nand_chip_sel *to_nand_sel(struct marvell_nand_chip
* BCH error detection and correction algorithm,
* NDCB3 register has been added
* @use_dma: Use dma for data transfers
+ * @is_marvell_timing_modes: use marvell predefined register values per mode
+ * @max_mode_number: supported mode by NFC (max mode that supported)
+ * @timing_mode_set: which set to use from predefined array of sets
+ each set has few modes
*/
struct marvell_nfc_caps {
unsigned int max_cs_nb;
@@ -375,6 +402,9 @@ struct marvell_nfc_caps {
bool legacy_of_bindings;
bool is_nfcv2;
bool use_dma;
+ bool is_marvell_timing_modes;
+ unsigned int max_mode_number;
+ marvell_nfc_timing_mode_set_t timing_mode_set;
};

/**
@@ -485,6 +515,118 @@ struct marvell_nfc_op {
const struct nand_op_instr *data_instr;
};

+/* NFC ndtr0 */
+typedef union marvell_nand_ndtr0 {
+ struct {
+ unsigned int tRP :3; /* 0-2 */
+ unsigned int tRH :3; /* 3-5 */
+ unsigned int tRPE :1; /* 6 */
+ unsigned int tRE_edge :1; /* 7 */
+ unsigned int tWP :3; /* 8-10 */
+ unsigned int tWH :3; /* 11-13 */
+ unsigned int reserved :2; /* 14-15 */
+ unsigned int tCS :3; /* 16-18 */
+ unsigned int tCH :3; /* 19-21 */
+ unsigned int Rd_Cnt_Del :4; /* 22-25 */
+ unsigned int selCnrl :1; /* 26 */
+ unsigned int tADL :5; /* 27-31 */
+ } fields;
+ unsigned int regValue;
+} marvell_nfc_ndtr0_t;
+
+/* NFC ndtr1 */
+typedef union marvell_nand_ndtr1 {
+ struct {
+ unsigned int tAR :4; /* 0-3 */
+ unsigned int tWHR :4; /* 4-7 */
+ unsigned int tRHW :2; /* 8-9 */
+ unsigned int reserved :4; /* 10-13 */
+ unsigned int Prescale :1; /* 14 */
+ unsigned int wait_mode :1; /* 15 */
+ unsigned int tR :16; /* 16-31 */
+ } fields;
+ unsigned int regValue;
+} marvell_nfc_ndtr1_t;
+
+#define NUM_OF_TIMING_MODES 6
+
+/* arrays of NFC timings modes */
+typedef marvell_nfc_ndtr0_t marvell_nfc_ndtr0_arr[NUM_OF_TIMING_MODES];
+typedef marvell_nfc_ndtr1_t marvell_nfc_ndtr1_arr[NUM_OF_TIMING_MODES];
+
+#define MARVELL_NTDR0(trp, trh, trpe, tre_edge, twp, twh, resrv, tcs, tch, rd_cnt_del, selcnrl, tadl) \
+ {\
+ .fields = {\
+ .tRP = trp, /* 0-2 */\
+ .tRH = trh, /* 3-5 */\
+ .tRPE = trpe, /* 6 */\
+ .tRE_edge = tre_edge, /* 7 */\
+ .tWP = twp, /* 8-10 */\
+ .tWH = twh, /* 11-13 */\
+ .reserved = resrv, /* 14-15 */\
+ .tCS = tcs, /* 16-18 */\
+ .tCH = tch, /* 19-21 */\
+ .Rd_Cnt_Del = rd_cnt_del, /* 22-25 */\
+ .selCnrl = selcnrl, /* 26 */\
+ .tADL = tadl, /* 27-31 */\
+ } \
+ }
+
+#define MARVELL_NTDR1(tar, twhr, trhw, resrv, prescale, waiting_mode, tr) \
+ {\
+ .fields = {\
+ .tAR = tar, /* 0-3 */\
+ .tWHR = twhr, /* 4-7 */\
+ .tRHW = trhw, /* 8-9 */\
+ .reserved = resrv, /* 10-13 */\
+ .Prescale = prescale, /* 14 */\
+ .wait_mode = waiting_mode, /* 15 */\
+ .tR = tr, /* 16-31 */\
+ } \
+ }
+
+/* ndtr0_modes and ndtr1_modes are arrays of modes with optimal values
+ * that were tested with Marvell NFC with correlation to ONFI timings mode
+ * each entry in the array presents different set of modes , for example ac5
+ * is entry 0.
+ */
+/* todo: add more modes ASAP */
+
+/* Layouts explained in AN-379_Marvell_SoC_NFC_ECC */
+marvell_nfc_ndtr0_arr ndtr0_modes[MARVELL_NFC_NDTR_NUM_OF_SET] = {
+
+ /* value tested with AC5 */
+ {
+ MARVELL_NTDR0(7, 7, 1, 1, 7, 7, 0, 7, 7, 12, 1, 31),
+ MARVELL_NTDR0(6, 3, 0, 0, 5, 4, 0, 7, 7, 1, 1, 15),
+ MARVELL_NTDR0(4, 3, 0, 0, 3, 3, 0, 7, 7, 2, 1, 15),
+ MARVELL_NTDR0(3, 2, 0, 0, 3, 2, 0, 1, 0, 2, 1, 15)
+ }
+};
+
+marvell_nfc_ndtr1_arr ndtr1_modes[MARVELL_NFC_NDTR_NUM_OF_SET] = {
+
+ /* value tested with AC5 */
+ {
+ MARVELL_NTDR1(15, 15, 3, 0, 0, 1, 50),
+ MARVELL_NTDR1(15, 15, 3, 0, 0, 1, 25),
+ MARVELL_NTDR1(15, 15, 3, 0, 0, 1, 25),
+ MARVELL_NTDR1(11, 11, 2, 0, 0, 1, 25)
+ }
+};
+
+/*
+ * get nand timing-mode from device tree
+ */
+static int get_nand_timing_mode(struct device_node *np)
+{
+ int ret;
+ u32 val;
+
+ ret = of_property_read_u32(np, "nand-timing-mode", &val);
+ return ret ? ret : val;
+}
+
/*
* Internal helper to conditionnally apply a delay (from the above structure,
* most of the time).
@@ -2257,9 +2399,21 @@ static int marvell_nand_hw_ecc_controller_init(struct mtd_info *mtd,
}

mtd_set_ooblayout(mtd, &marvell_nand_ooblayout_ops);
- ecc->steps = l->nchunks;
ecc->size = l->data_bytes;

+ /* nand_scan_tail func perform validity tests for ECC strength, and it
+ * assumes that all chunks are with same size. in our case when ecc is 12
+ * the chunk size is 704 but the last chunk is with different size so
+ * we cheat it nand_scan_tail validity tests by set info->ecc_size value to
+ * 512.
+ */
+ if (ecc->strength == 12)
+ ecc->size = 512;
+
+ /* let nand_scan_tail() calculate these two fields */
+ ecc->steps = 0;
+ ecc->total = 0;
+
if (ecc->strength == 1) {
chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
ecc->read_page_raw = marvell_nfc_hw_ecc_hmg_read_page_raw;
@@ -2360,9 +2514,11 @@ static int marvell_nfc_setup_interface(struct nand_chip *chip, int chipnr,
struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip);
struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
unsigned int period_ns = 1000000000 / clk_get_rate(nfc->core_clk) * 2;
- const struct nand_sdr_timings *sdr;
+ const struct nand_sdr_timings *sdr, *timings;
struct marvell_nfc_timings nfc_tmg;
int read_delay;
+ marvell_nfc_timing_mode_set_t modes_set;
+ int mode = 0;

sdr = nand_get_sdr_timings(conf);
if (IS_ERR(sdr))
@@ -2421,32 +2577,71 @@ static int marvell_nfc_setup_interface(struct nand_chip *chip, int chipnr,
nfc_tmg.tR = 0;
}

- if (chipnr < 0)
- return 0;

- marvell_nand->ndtr0 =
- NDTR0_TRP(nfc_tmg.tRP) |
- NDTR0_TRH(nfc_tmg.tRH) |
- NDTR0_ETRP(nfc_tmg.tRP) |
- NDTR0_TWP(nfc_tmg.tWP) |
- NDTR0_TWH(nfc_tmg.tWH) |
- NDTR0_TCS(nfc_tmg.tCS) |
- NDTR0_TCH(nfc_tmg.tCH);
+ /* get the timing modes from predefined values according to its compatibility */
+ if (nfc->caps->is_marvell_timing_modes) {
+ /* get the mode set */
+ modes_set = nfc->caps->timing_mode_set;
+ if (modes_set >= MARVELL_NFC_NDTR_SET_NON) {
+ dev_warn(nfc->dev,
+ "Warning: not supported timing registers set,use set number 0 by default\n");

- marvell_nand->ndtr1 =
- NDTR1_TAR(nfc_tmg.tAR) |
- NDTR1_TWHR(nfc_tmg.tWHR) |
- NDTR1_TR(nfc_tmg.tR);
+ modes_set = MARVELL_NFC_NDTR_SET_0;
+ }

- if (nfc->caps->is_nfcv2) {
- marvell_nand->ndtr0 |=
- NDTR0_RD_CNT_DEL(read_delay) |
- NDTR0_SELCNTR |
- NDTR0_TADL(nfc_tmg.tADL);
+ /* find the caller mode according to timings values */
+ /* if exit on error it means no more modes; not suppose to happen */
+ do {
+ timings = onfi_async_timing_mode_to_sdr_timings(mode);
+ if (IS_TIMINGS_EQUAL(timings, sdr))
+ break;
+ mode++;
+ } while (!IS_ERR(timings));
+
+ /* if mode is not supported by NFC, return false or if nand-timing-mode that
+ * exists in device tree greater then caller mode also return false and wait
+ * for caller to try with next mode (mode-1). we want the nand feature to be
+ * configured with nand-timing-mode value.
+ */
+ if (mode > nfc->caps->max_mode_number ||
+ ((marvell_nand->nand_timing_mode) >= 0 &&
+ (mode > marvell_nand->nand_timing_mode)))
+ return -EOPNOTSUPP;
+
+ /* just checking NFC capabilities no need to set the registers */
+ if (chipnr < 0)
+ return 0;

- marvell_nand->ndtr1 |=
- NDTR1_TRHW(nfc_tmg.tRHW) |
- NDTR1_WAIT_MODE;
+ marvell_nand->ndtr0 = ndtr0_modes[modes_set][mode].regValue;
+ marvell_nand->ndtr1 = ndtr1_modes[modes_set][mode].regValue;
+ } else {
+ if (chipnr < 0)
+ return 0;
+
+ marvell_nand->ndtr0 =
+ NDTR0_TRP(nfc_tmg.tRP) |
+ NDTR0_TRH(nfc_tmg.tRH) |
+ NDTR0_ETRP(nfc_tmg.tRP) |
+ NDTR0_TWP(nfc_tmg.tWP) |
+ NDTR0_TWH(nfc_tmg.tWH) |
+ NDTR0_TCS(nfc_tmg.tCS) |
+ NDTR0_TCH(nfc_tmg.tCH);
+
+ marvell_nand->ndtr1 =
+ NDTR1_TAR(nfc_tmg.tAR) |
+ NDTR1_TWHR(nfc_tmg.tWHR) |
+ NDTR1_TR(nfc_tmg.tR);
+
+ if (nfc->caps->is_nfcv2) {
+ marvell_nand->ndtr0 |=
+ NDTR0_RD_CNT_DEL(read_delay) |
+ NDTR0_SELCNTR |
+ NDTR0_TADL(nfc_tmg.tADL);
+
+ marvell_nand->ndtr1 |=
+ NDTR1_TRHW(nfc_tmg.tRHW) |
+ NDTR1_WAIT_MODE;
+ }
}

return 0;
@@ -2568,6 +2763,7 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
struct nand_chip *chip;
int nsels, ret, i;
u32 cs, rb;
+ struct device_node *dn;

/*
* The legacy "num-cs" property indicates the number of CS on the only
@@ -2681,6 +2877,10 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
if (of_property_read_bool(np, "marvell,nand-keep-config"))
chip->options |= NAND_KEEP_TIMINGS;

+ /* read the mode from device tree */
+ dn = nand_get_flash_node(chip);
+ marvell_nand->nand_timing_mode = get_nand_timing_mode(dn);
+
mtd = nand_to_mtd(chip);
mtd->dev.parent = dev;

@@ -3064,6 +3264,15 @@ static const struct marvell_nfc_caps marvell_armada_8k_nfc_caps = {
.is_nfcv2 = true,
};

+static const struct marvell_nfc_caps marvell_ac5_caps = {
+ .max_cs_nb = 2,
+ .max_rb_nb = 1,
+ .is_nfcv2 = true,
+ .is_marvell_timing_modes = true,
+ .max_mode_number = 3,
+ .timing_mode_set = MARVELL_NFC_NDTR_SET_0,
+};
+
static const struct marvell_nfc_caps marvell_armada370_nfc_caps = {
.max_cs_nb = 4,
.max_rb_nb = 2,
@@ -3112,6 +3321,10 @@ static const struct of_device_id marvell_nfc_of_ids[] = {
.compatible = "marvell,armada-8k-nand-controller",
.data = &marvell_armada_8k_nfc_caps,
},
+ {
+ .compatible = "marvell,ac5-nand-controller",
+ .data = &marvell_ac5_caps,
+ },
{
.compatible = "marvell,armada370-nand-controller",
.data = &marvell_armada370_nfc_caps,
--
2.17.1

2022-10-19 09:32:45

by Vadym Kochan

[permalink] [raw]
Subject: [PATCH 1/3] mtd: rawnand: Partially revert 4114f97c41cd ("mtd: rawnand: Get rid of a few unused definitions")

onfi_async_timing_mode_to_sdr_timings is required for ac5 support in marvell_nand.c

Signed-off-by: Vadym Kochan <[email protected]>
---
drivers/mtd/nand/raw/nand_timings.c | 14 ++++++++++++++
include/linux/mtd/rawnand.h | 3 +++
2 files changed, 17 insertions(+)

diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
index 7b41afc372d2..5604e3dc632c 100644
--- a/drivers/mtd/nand/raw/nand_timings.c
+++ b/drivers/mtd/nand/raw/nand_timings.c
@@ -642,6 +642,20 @@ onfi_find_closest_nvddr_mode(const struct nand_nvddr_timings *spec_timings)
return 0;
}

+/**
+ * onfi_async_timing_mode_to_sdr_timings - [NAND Interface] Retrieve NAND
+ * timings according to the given ONFI timing mode
+ * @mode: ONFI timing mode
+ */
+const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode)
+{
+ if (mode < 0 || mode >= ARRAY_SIZE(onfi_sdr_timings))
+ return ERR_PTR(-EINVAL);
+
+ return &onfi_sdr_timings[mode].timings.sdr;
+}
+EXPORT_SYMBOL(onfi_async_timing_mode_to_sdr_timings);
+
/*
* onfi_fill_sdr_interface_config - Initialize a SDR interface config from a
* given ONFI mode
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index dcf90144d70b..7702abf9e1f0 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1481,6 +1481,9 @@ int rawnand_sw_bch_correct(struct nand_chip *chip, unsigned char *buf,
unsigned char *read_ecc, unsigned char *calc_ecc);
void rawnand_sw_bch_cleanup(struct nand_chip *chip);

+/* get timing characteristics from ONFI timing mode. */
+const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode);
+
int nand_check_erased_ecc_chunk(void *data, int datalen,
void *ecc, int ecclen,
void *extraoob, int extraooblen,
--
2.17.1

2022-10-19 09:36:09

by Miquel Raynal

[permalink] [raw]
Subject: Re: [PATCH 3/3] mtd: rawnand: marvell: add support for AC5 SoC

Hi Vadym,

[email protected] wrote on Wed, 19 Oct 2022 11:20:40 +0300:

> From: Aviram Dali <[email protected]>
>
> The following changes were made to add AC5 support:
>
> 1) Modify Marvell nand NFC timing set for mode 0
>
> 2) fix validation in AC5 Nand driver for ONFI timings values modes 1 and 3
>
> 3) remove unnecessary nand timing-mode in device tree of ac5.dtsi
>
> 4) add nand missing AC5X layouts , add option to use ndtr predefined values
>
> 5) Zero steps and total fields of ecc in ecc controller initialization so
> nand_scan_tail() will calculate these two fields, otherwise
> NAND initialization will fail with kernel 5.15 and above.
>
> Signed-off-by: Aviram Dali <[email protected]>
> Signed-off-by: Vadym Kochan <[email protected]>
> ---
> drivers/mtd/nand/raw/Kconfig | 2 +-
> drivers/mtd/nand/raw/marvell_nand.c | 277 ++++++++++++++++++++++++----
> 2 files changed, 246 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
> index 4cd40af362de..b7bb62f27e02 100644
> --- a/drivers/mtd/nand/raw/Kconfig
> +++ b/drivers/mtd/nand/raw/Kconfig
> @@ -160,7 +160,7 @@ config MTD_NAND_MARVELL
> including:
> - PXA3xx processors (NFCv1)
> - 32-bit Armada platforms (XP, 37x, 38x, 39x) (NFCv2)
> - - 64-bit Aramda platforms (7k, 8k) (NFCv2)
> + - 64-bit Aramda platforms (7k, 8k, ac5) (NFCv2)
>
> config MTD_NAND_SLC_LPC32XX
> tristate "NXP LPC32xx SLC NAND controller"
> diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c
> index b9d1e96e3334..940a89115782 100644
> --- a/drivers/mtd/nand/raw/marvell_nand.c
> +++ b/drivers/mtd/nand/raw/marvell_nand.c
> @@ -226,6 +226,20 @@
> #define XTYPE_COMMAND_DISPATCH 6
> #define XTYPE_MASK 7
>
> +/* use tRP_min, tWC_min and tWP_min to distinct across timings modes */
> +#define IS_TIMINGS_EQUAL(t1, t2) \
> + ((t1->tRP_min == t2->tRP_min &&\
> + t1->tWC_min == t2->tWC_min &&\
> + t1->tWP_min == t2->tWP_min) ? true : false)
> +
> +/* ndtr0,1 set , each set has few modes level */
> +typedef enum marvell_nfc_timing_mode_set {
> + MARVELL_NFC_NDTR_SET_0, /* tested with ac5 */
> +
> + MARVELL_NFC_NDTR_NUM_OF_SET,
> + MARVELL_NFC_NDTR_SET_NON = MARVELL_NFC_NDTR_NUM_OF_SET
> +} marvell_nfc_timing_mode_set_t;
> +
> /**
> * struct marvell_hw_ecc_layout - layout of Marvell ECC
> *
> @@ -283,14 +297,21 @@ struct marvell_hw_ecc_layout {
>
> /* Layouts explained in AN-379_Marvell_SoC_NFC_ECC */
> static const struct marvell_hw_ecc_layout marvell_nfc_layouts[] = {
> - MARVELL_LAYOUT( 512, 512, 1, 1, 1, 512, 8, 8, 0, 0, 0),
> - MARVELL_LAYOUT( 2048, 512, 1, 1, 1, 2048, 40, 24, 0, 0, 0),
> - MARVELL_LAYOUT( 2048, 512, 4, 1, 1, 2048, 32, 30, 0, 0, 0),
> - MARVELL_LAYOUT( 2048, 512, 8, 2, 1, 1024, 0, 30,1024,32, 30),
> - MARVELL_LAYOUT( 4096, 512, 4, 2, 2, 2048, 32, 30, 0, 0, 0),
> - MARVELL_LAYOUT( 4096, 512, 8, 5, 4, 1024, 0, 30, 0, 64, 30),
> - MARVELL_LAYOUT( 8192, 512, 4, 4, 4, 2048, 0, 30, 0, 0, 0),
> - MARVELL_LAYOUT( 8192, 512, 8, 9, 8, 1024, 0, 30, 0, 160, 30),
> + MARVELL_LAYOUT(512, 512, 1, 1, 1, 512, 8, 8, 0, 0, 0),
> + MARVELL_LAYOUT(2048, 512, 1, 1, 1, 2048, 40, 24, 0, 0, 0),
> + MARVELL_LAYOUT(2048, 512, 4, 1, 1, 2048, 32, 30, 0, 0, 0),
> + MARVELL_LAYOUT(2048, 512, 8, 2, 1, 1024, 0, 30, 1024, 32, 30),
> + MARVELL_LAYOUT(2048, 512, 8, 2, 1, 1024, 0, 30, 1024, 64, 30),
> + MARVELL_LAYOUT(2048, 512, 12, 3, 2, 704, 0, 30, 640, 0, 30),
> + MARVELL_LAYOUT(2048, 512, 16, 5, 4, 512, 0, 30, 0, 32, 30),
> + MARVELL_LAYOUT(4096, 512, 4, 2, 2, 2048, 32, 30, 0, 0, 0),
> + MARVELL_LAYOUT(4096, 512, 8, 5, 4, 1024, 0, 30, 0, 64, 30),
> + MARVELL_LAYOUT(4096, 512, 12, 6, 5, 704, 0, 30, 576, 32, 30),
> + MARVELL_LAYOUT(4096, 512, 16, 9, 8, 512, 0, 30, 0, 32, 30),
> + MARVELL_LAYOUT(8192, 512, 4, 4, 4, 2048, 0, 30, 0, 0, 0),
> + MARVELL_LAYOUT(8192, 512, 8, 9, 8, 1024, 0, 30, 0, 160, 30),
> + MARVELL_LAYOUT(8192, 512, 12, 12, 11, 704, 0, 30, 448, 64, 30),
> + MARVELL_LAYOUT(8192, 512, 16, 17, 16, 512, 0, 30, 0, 32, 30),
> };

If you don't like the layout, it's fine, but you must do it in a
separate commit.

[...]

> +/*
> + * get nand timing-mode from device tree
> + */
> +static int get_nand_timing_mode(struct device_node *np)
> +{
> + int ret;
> + u32 val;
> +
> + ret = of_property_read_u32(np, "nand-timing-mode", &val);
> + return ret ? ret : val;
> +}
> +
> /*
> * Internal helper to conditionnally apply a delay (from the above structure,
> * most of the time).
> @@ -2257,9 +2399,21 @@ static int marvell_nand_hw_ecc_controller_init(struct mtd_info *mtd,
> }
>
> mtd_set_ooblayout(mtd, &marvell_nand_ooblayout_ops);
> - ecc->steps = l->nchunks;
> ecc->size = l->data_bytes;
>
> + /* nand_scan_tail func perform validity tests for ECC strength, and it
> + * assumes that all chunks are with same size. in our case when ecc is 12
> + * the chunk size is 704 but the last chunk is with different size so
> + * we cheat it nand_scan_tail validity tests by set info->ecc_size value to
> + * 512.

The driver already supports this, trying to cheat the core is bad. See
the last members of struct marvell_hw_ecc_layout.

> + */
> + if (ecc->strength == 12)
> + ecc->size = 512;
> +
> + /* let nand_scan_tail() calculate these two fields */
> + ecc->steps = 0;
> + ecc->total = 0;
> +
> if (ecc->strength == 1) {
> chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
> ecc->read_page_raw = marvell_nfc_hw_ecc_hmg_read_page_raw;
> @@ -2360,9 +2514,11 @@ static int marvell_nfc_setup_interface(struct nand_chip *chip, int chipnr,
> struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip);
> struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
> unsigned int period_ns = 1000000000 / clk_get_rate(nfc->core_clk) * 2;
> - const struct nand_sdr_timings *sdr;
> + const struct nand_sdr_timings *sdr, *timings;
> struct marvell_nfc_timings nfc_tmg;
> int read_delay;
> + marvell_nfc_timing_mode_set_t modes_set;
> + int mode = 0;
>
> sdr = nand_get_sdr_timings(conf);
> if (IS_ERR(sdr))
> @@ -2421,32 +2577,71 @@ static int marvell_nfc_setup_interface(struct nand_chip *chip, int chipnr,
> nfc_tmg.tR = 0;
> }
>
> - if (chipnr < 0)
> - return 0;
>
> - marvell_nand->ndtr0 =
> - NDTR0_TRP(nfc_tmg.tRP) |
> - NDTR0_TRH(nfc_tmg.tRH) |
> - NDTR0_ETRP(nfc_tmg.tRP) |
> - NDTR0_TWP(nfc_tmg.tWP) |
> - NDTR0_TWH(nfc_tmg.tWH) |
> - NDTR0_TCS(nfc_tmg.tCS) |
> - NDTR0_TCH(nfc_tmg.tCH);
> + /* get the timing modes from predefined values according to its compatibility */
> + if (nfc->caps->is_marvell_timing_modes) {
> + /* get the mode set */
> + modes_set = nfc->caps->timing_mode_set;
> + if (modes_set >= MARVELL_NFC_NDTR_SET_NON) {
> + dev_warn(nfc->dev,
> + "Warning: not supported timing registers set,use set number 0 by default\n");
>
> - marvell_nand->ndtr1 =
> - NDTR1_TAR(nfc_tmg.tAR) |
> - NDTR1_TWHR(nfc_tmg.tWHR) |
> - NDTR1_TR(nfc_tmg.tR);
> + modes_set = MARVELL_NFC_NDTR_SET_0;
> + }
>
> - if (nfc->caps->is_nfcv2) {
> - marvell_nand->ndtr0 |=
> - NDTR0_RD_CNT_DEL(read_delay) |
> - NDTR0_SELCNTR |
> - NDTR0_TADL(nfc_tmg.tADL);
> + /* find the caller mode according to timings values */
> + /* if exit on error it means no more modes; not suppose to happen */
> + do {
> + timings = onfi_async_timing_mode_to_sdr_timings(mode);

The timing negotiation is handled by the core, I don't see why you
would need this.

> + if (IS_TIMINGS_EQUAL(timings, sdr))
> + break;
> + mode++;
> + } while (!IS_ERR(timings));
> +
> + /* if mode is not supported by NFC, return false or if nand-timing-mode that
> + * exists in device tree greater then caller mode also return false and wait
> + * for caller to try with next mode (mode-1). we want the nand feature to be
> + * configured with nand-timing-mode value.
> + */
> + if (mode > nfc->caps->max_mode_number ||
> + ((marvell_nand->nand_timing_mode) >= 0 &&
> + (mode > marvell_nand->nand_timing_mode)))
> + return -EOPNOTSUPP;

[...]

> @@ -2681,6 +2877,10 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
> if (of_property_read_bool(np, "marvell,nand-keep-config"))
> chip->options |= NAND_KEEP_TIMINGS;
>
> + /* read the mode from device tree */
> + dn = nand_get_flash_node(chip);
> + marvell_nand->nand_timing_mode = get_nand_timing_mode(dn);

I'm sorry but unless you give me a really convincing explanation, this
is not gonna work. The timing mode should be negotiated between the
controller and the chip, then the controller needs to configure its own
registers to fit these timings. There is no way the timing mode should
be hardcoded in the device tree.

> +
> mtd = nand_to_mtd(chip);
> mtd->dev.parent = dev;
>

Thanks,
Miquèl

2022-10-19 11:17:34

by Miquel Raynal

[permalink] [raw]
Subject: Re: [PATCH 2/3] dt-bindings: mtd: Add AC5 specific binding

Hi Vadym,

[email protected] wrote on Wed, 19 Oct 2022 11:20:39 +0300:

> From: Aviram Dali <[email protected]>
>
> Add binding for AC5 SoC which have its special way of handing
> NAND layout.
>
> Signed-off-by: Aviram Dali <[email protected]>
> Signed-off-by: Vadym Kochan <[email protected]>
> ---
> Documentation/devicetree/bindings/mtd/marvell-nand.txt | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/mtd/marvell-nand.txt b/Documentation/devicetree/bindings/mtd/marvell-nand.txt
> index a2d9a0f2b683..293551ec7350 100644
> --- a/Documentation/devicetree/bindings/mtd/marvell-nand.txt
> +++ b/Documentation/devicetree/bindings/mtd/marvell-nand.txt
> @@ -2,6 +2,7 @@ Marvell NAND Flash Controller (NFC)
>
> Required properties:
> - compatible: can be one of the following:
> + * "marvell,ac5-nand-controller"
> * "marvell,armada-8k-nand-controller"
> * "marvell,armada370-nand-controller"
> * "marvell,pxa3xx-nand-controller"

Could you please do the yaml conversion first?

Thanks,
Miquèl

2022-10-20 14:04:47

by Vadym Kochan

[permalink] [raw]
Subject: Re: [PATCH 2/3] dt-bindings: mtd: Add AC5 specific binding

Hi Miquel,

> Could you please do the yaml conversion first?

Sure, will try.

Thanks,
Vadym

2022-10-20 23:22:39

by Chris Packham

[permalink] [raw]
Subject: Re: [PATCH 2/3] dt-bindings: mtd: Add AC5 specific binding

Hi Vadym,

On 19/10/22 21:46, Miquel Raynal wrote:
> Hi Vadym,
>
> [email protected] wrote on Wed, 19 Oct 2022 11:20:39 +0300:
>
>> From: Aviram Dali <[email protected]>
>>
>> Add binding for AC5 SoC which have its special way of handing
>> NAND layout.
>>
>> Signed-off-by: Aviram Dali <[email protected]>
>> Signed-off-by: Vadym Kochan <[email protected]>
>> ---
>> Documentation/devicetree/bindings/mtd/marvell-nand.txt | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/Documentation/devicetree/bindings/mtd/marvell-nand.txt b/Documentation/devicetree/bindings/mtd/marvell-nand.txt
>> index a2d9a0f2b683..293551ec7350 100644
>> --- a/Documentation/devicetree/bindings/mtd/marvell-nand.txt
>> +++ b/Documentation/devicetree/bindings/mtd/marvell-nand.txt
>> @@ -2,6 +2,7 @@ Marvell NAND Flash Controller (NFC)
>>
>> Required properties:
>> - compatible: can be one of the following:
>> + * "marvell,ac5-nand-controller"
>> * "marvell,armada-8k-nand-controller"
>> * "marvell,armada370-nand-controller"
>> * "marvell,pxa3xx-nand-controller"
> Could you please do the yaml conversion first?
If it helps I've done a few of these conversions in the past. I'd be
happy to help you out with doing the conversion if it helps you move the
rest of the series forward.
>
> Thanks,
> Miquèl

2022-10-21 20:07:45

by Vadym Kochan

[permalink] [raw]
Subject: Re: [PATCH 2/3] dt-bindings: mtd: Add AC5 specific binding

Hi Chris,

>> [email protected] wrote on Wed, 19 Oct 2022 11:20:39 +0300:
>>
>>> From: Aviram Dali <[email protected]>
>>>
>>> Add binding for AC5 SoC which have its special way of handing
>>> NAND layout.
>>>
>>> Signed-off-by: Aviram Dali <[email protected]>
>>> Signed-off-by: Vadym Kochan <[email protected]>
>>> ---
>>> Documentation/devicetree/bindings/mtd/marvell-nand.txt | 1 +
>>> 1 file changed, 1 insertion(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/mtd/marvell-nand.txt b/Documentation/devicetree/bindings/mtd/marvell-nand.txt
>>> index a2d9a0f2b683..293551ec7350 100644
>>> --- a/Documentation/devicetree/bindings/mtd/marvell-nand.txt
>>> +++ b/Documentation/devicetree/bindings/mtd/marvell-nand.txt
>>> @@ -2,6 +2,7 @@ Marvell NAND Flash Controller (NFC)
>>>
>>> Required properties:
>>> - compatible: can be one of the following:
>>> + * "marvell,ac5-nand-controller"
>>> * "marvell,armada-8k-nand-controller"
>>> * "marvell,armada370-nand-controller"
>>> * "marvell,pxa3xx-nand-controller"
>> Could you please do the yaml conversion first?
>If it helps I've done a few of these conversions in the past. I'd be
>happy to help you out with doing the conversion if it helps you move the
>rest of the series forward.

Thanks for your proposal to help, I already sent the separate series
just for YAML conversion, actually it is my first YAML experience.

Regards,
Vadym

2023-05-25 01:21:44

by Chris Packham

[permalink] [raw]
Subject: Re: [PATCH 0/3] mtd: rawnand: marvell: add support for AC5 SoC

Hi Vadym,

On 19/10/22 21:20, Vadym Kochan wrote:
> This series adds support for AC5 SoC.
>
> The following changes were made to add AC5 support:
>
> 1) Modify Marvell nand NFC timing set for mode 0
>
> 2) fix validation in AC5 Nand driver for ONFI timings values modes 1 and 3
>
> 3) remove unnecessary nand timing-mode in device tree of ac5.dtsi
>
> 4) add nand missing AC5X layouts , add option to use ndtr predefined values
>
> 5) Zero steps and total fields of ecc in ecc controller initialization so
> nand_scan_tail() will calculate these two fields, otherwise
> NAND initialization will fail with kernel 5.15 and above.
>
> Aviram Dali (2):
> dt-bindings: mtd: Add AC5 specific binding
> mtd: rawnand: marvell: add support for AC5 SoC

Are you still looking into this series? I see one part made it upstream
as commit 68c18dae6888 ("mtd: rawnand: marvell: add missing layouts")
and there was an off-shoot series around converting the DT binding.

> Vadym Kochan (1):
> mtd: rawnand: Partially revert 4114f97c41cd ("mtd: rawnand: Get rid of
> a few unused definitions")
>
> .../devicetree/bindings/mtd/marvell-nand.txt | 1 +
> drivers/mtd/nand/raw/Kconfig | 2 +-
> drivers/mtd/nand/raw/marvell_nand.c | 277 ++++++++++++++++--
> drivers/mtd/nand/raw/nand_timings.c | 14 +
> include/linux/mtd/rawnand.h | 3 +
> 5 files changed, 264 insertions(+), 33 deletions(-)
>

2023-05-26 12:13:12

by Vadym Kochan

[permalink] [raw]
Subject: Re: [PATCH 0/3] mtd: rawnand: marvell: add support for AC5 SoC

Hi Chris,

Sorry for the delay.

Currently I do not work with Marvell, so I can't do anything with that.

Regards,
Vadym

________________________________________
???: Chris Packham <[email protected]>
??Ħ?????: 25 ?????? 2023 ?. 3:53
????: Vadym Kochan; Miquel Raynal; Richard Weinberger; Vignesh Raghavendra; Rob Herring; Krzysztof Kozlowski; Roger Quadros; Florian Fainelli; Wolfram Sang; Liang Yang; Thomas Bogendoerfer; Aviram Dali; [email protected]; [email protected]; [email protected]
??Ц?: Elad Nachman
????: Re: [PATCH 0/3] mtd: rawnand: marvell: add support for AC5 SoC

Hi Vadym,

On 19/10/22 21:20, Vadym Kochan wrote:
> This series adds support for AC5 SoC.
>
> The following changes were made to add AC5 support:
>
> 1) Modify Marvell nand NFC timing set for mode 0
>
> 2) fix validation in AC5 Nand driver for ONFI timings values modes 1 and 3
>
> 3) remove unnecessary nand timing-mode in device tree of ac5.dtsi
>
> 4) add nand missing AC5X layouts , add option to use ndtr predefined values
>
> 5) Zero steps and total fields of ecc in ecc controller initialization so
> nand_scan_tail() will calculate these two fields, otherwise
> NAND initialization will fail with kernel 5.15 and above.
>
> Aviram Dali (2):
> dt-bindings: mtd: Add AC5 specific binding
> mtd: rawnand: marvell: add support for AC5 SoC

Are you still looking into this series? I see one part made it upstream
as commit 68c18dae6888 ("mtd: rawnand: marvell: add missing layouts")
and there was an off-shoot series around converting the DT binding.

> Vadym Kochan (1):
> mtd: rawnand: Partially revert 4114f97c41cd ("mtd: rawnand: Get rid of
> a few unused definitions")
>
> .../devicetree/bindings/mtd/marvell-nand.txt | 1 +
> drivers/mtd/nand/raw/Kconfig | 2 +-
> drivers/mtd/nand/raw/marvell_nand.c | 277 ++++++++++++++++--
> drivers/mtd/nand/raw/nand_timings.c | 14 +
> include/linux/mtd/rawnand.h | 3 +
> 5 files changed, 264 insertions(+), 33 deletions(-)
>