All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] Add STM32 FMC2 EBI controller driver
@ 2020-07-31  7:53 Christophe Kerello
  2020-07-31  7:53 ` [PATCH 01/11] mtd: rawnand: stm32_fmc2: fix a buffer overflow Christophe Kerello
                   ` (10 more replies)
  0 siblings, 11 replies; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31  7:53 UTC (permalink / raw)
  To: u-boot


The FMC2 functional block makes the interface with: synchronous and
asynchronous static devices (such as PSNOR, PSRAM or other memory-mapped
peripherals) and NAND flash memories.
Its main purposes are:
  - to translate AXI transactions into the appropriate external device
    protocol
  - to meet the access time requirements of the external devices
All external devices share the addresses, data and control signals with the
controller. Each external device is accessed by means of a unique Chip
Select. The FMC2 performs only one access at a time to an external device.


Christophe Kerello (11):
  mtd: rawnand: stm32_fmc2: fix a buffer overflow
  mtd: rawnand: stm32_fmc2: remove useless inline comments
  mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_5S for timeouts
  mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2
    where relevant
  mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros
  mtd: rawnand: stm32_fmc2: use clrsetbits_le32
  memory: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver
  mtd: rawnand: stm32_fmc2: get resources from parent node
  board: stm32mp1: update fdt fixup partitions table
  configs: stm32mp: add CONFIG_STM32_FMC2_EBI
  ARM: dts: stm32: add FMC2 EBI support for stm32mp157c

 arch/arm/dts/stm32mp151.dtsi           |   43 +-
 arch/arm/dts/stm32mp157c-ev1.dts       |   16 +-
 board/st/stm32mp1/stm32mp1.c           |    1 +
 configs/stm32mp15_basic_defconfig      |    1 +
 configs/stm32mp15_trusted_defconfig    |    1 +
 drivers/memory/Kconfig                 |    9 +
 drivers/memory/Makefile                |    1 +
 drivers/memory/stm32-fmc2-ebi.c        | 1056 ++++++++++++++++++++++++++++++++
 drivers/mtd/nand/raw/stm32_fmc2_nand.c |  499 ++++++++-------
 9 files changed, 1349 insertions(+), 278 deletions(-)
 create mode 100644 drivers/memory/stm32-fmc2-ebi.c

-- 
1.9.1

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 01/11] mtd: rawnand: stm32_fmc2: fix a buffer overflow
  2020-07-31  7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
@ 2020-07-31  7:53 ` Christophe Kerello
  2020-08-13  7:27   ` Patrice CHOTARD
  2020-07-31  7:53 ` [PATCH 02/11] mtd: rawnand: stm32_fmc2: remove useless inline comments Christophe Kerello
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31  7:53 UTC (permalink / raw)
  To: u-boot

The chip select defined in the device tree could only be 0 or 1.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---

 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 3306bd8..2929acf 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -846,7 +846,7 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
 	}
 
 	for (i = 0; i < nand->ncs; i++) {
-		if (cs[i] > FMC2_MAX_CE) {
+		if (cs[i] >= FMC2_MAX_CE) {
 			pr_err("Invalid reg value: %d\n",
 			       nand->cs_used[i]);
 			return -EINVAL;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 02/11] mtd: rawnand: stm32_fmc2: remove useless inline comments
  2020-07-31  7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
  2020-07-31  7:53 ` [PATCH 01/11] mtd: rawnand: stm32_fmc2: fix a buffer overflow Christophe Kerello
@ 2020-07-31  7:53 ` Christophe Kerello
  2020-08-13  7:28   ` Patrice CHOTARD
  2020-07-31  7:53 ` [PATCH 03/11] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_5S for timeouts Christophe Kerello
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31  7:53 UTC (permalink / raw)
  To: u-boot

Remove inline comments that are useless since function label are
self explanatory.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---

 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 25 -------------------------
 1 file changed, 25 deletions(-)

diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 2929acf..f43e3ec 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -179,7 +179,6 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_hw_control *base)
 	return container_of(base, struct stm32_fmc2_nfc, base);
 }
 
-/* Timings configuration */
 static void stm32_fmc2_timings_init(struct nand_chip *chip)
 {
 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
@@ -211,7 +210,6 @@ static void stm32_fmc2_timings_init(struct nand_chip *chip)
 	writel(patt, fmc2->io_base + FMC2_PATT);
 }
 
-/* Controller configuration */
 static void stm32_fmc2_setup(struct nand_chip *chip)
 {
 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
@@ -239,7 +237,6 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
 	writel(pcr, fmc2->io_base + FMC2_PCR);
 }
 
-/* Select target */
 static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
@@ -256,14 +253,10 @@ static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
 	chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel];
 	chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel];
 
-	/* FMC2 setup routine */
 	stm32_fmc2_setup(chip);
-
-	/* Apply timings */
 	stm32_fmc2_timings_init(chip);
 }
 
-/* Set bus width to 16-bit or 8-bit */
 static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
 {
 	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
@@ -274,7 +267,6 @@ static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
 	writel(pcr, fmc2->io_base + FMC2_PCR);
 }
 
-/* Enable/disable ECC */
 static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
 {
 	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
@@ -285,13 +277,11 @@ static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
 	writel(pcr, fmc2->io_base + FMC2_PCR);
 }
 
-/* Clear irq sources in case of bch is used */
 static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
 {
 	writel(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
 }
 
-/* Send command and address cycles */
 static void stm32_fmc2_cmd_ctrl(struct mtd_info *mtd, int cmd,
 				unsigned int ctrl)
 {
@@ -361,7 +351,6 @@ static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
 	ecc[1] = heccr >> 8;
 	ecc[2] = heccr >> 16;
 
-	/* Disable ecc */
 	stm32_fmc2_set_ecc(fmc2, false);
 
 	return 0;
@@ -466,13 +455,11 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
 		ecc[12] = bchpbr;
 	}
 
-	/* Disable ecc */
 	stm32_fmc2_set_ecc(fmc2, false);
 
 	return 0;
 }
 
-/* BCH algorithm correction */
 static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
 				  u8 *read_ecc, u8 *calc_ecc)
 {
@@ -497,7 +484,6 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
 	bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3);
 	bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4);
 
-	/* Disable ECC */
 	stm32_fmc2_set_ecc(fmc2, false);
 
 	/* No errors found */
@@ -579,7 +565,6 @@ static int stm32_fmc2_read_page(struct mtd_info *mtd,
 	return max_bitflips;
 }
 
-/* Controller initialization */
 static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
 {
 	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
@@ -622,7 +607,6 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
 	writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
 }
 
-/* Controller timings */
 static void stm32_fmc2_calc_timings(struct nand_chip *chip,
 				    const struct nand_sdr_timings *sdrt)
 {
@@ -768,13 +752,11 @@ static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr,
 
 	stm32_fmc2_calc_timings(chip, sdrt);
 
-	/* Apply timings */
 	stm32_fmc2_timings_init(chip);
 
 	return 0;
 }
 
-/* NAND callbacks setup */
 static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
 {
 	chip->ecc.hwctl = stm32_fmc2_hwctl;
@@ -803,7 +785,6 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
 		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
 }
 
-/* FMC2 caps */
 static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
 {
 	/* Hamming */
@@ -822,7 +803,6 @@ NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
 		     FMC2_ECC_STEP_SIZE,
 		     FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
 
-/* FMC2 probe */
 static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
 				  ofnode node)
 {
@@ -969,7 +949,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
 		reset_deassert(&reset);
 	}
 
-	/* FMC2 init routine */
 	stm32_fmc2_init(fmc2);
 
 	chip->controller = &fmc2->base;
@@ -985,7 +964,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
 	chip->ecc.size = FMC2_ECC_STEP_SIZE;
 	chip->ecc.strength = FMC2_ECC_BCH8;
 
-	/* Scan to find existence of the device */
 	ret = nand_scan_ident(mtd, nand->ncs, NULL);
 	if (ret)
 		return ret;
@@ -1012,7 +990,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
 	if (chip->bbt_options & NAND_BBT_USE_FLASH)
 		chip->bbt_options |= NAND_BBT_NO_OOB;
 
-	/* NAND callbacks setup */
 	stm32_fmc2_nand_callbacks_setup(chip);
 
 	/* Define ECC layout */
@@ -1026,11 +1003,9 @@ static int stm32_fmc2_probe(struct udevice *dev)
 	ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
 	chip->ecc.layout = ecclayout;
 
-	/* Configure bus width to 16-bit */
 	if (chip->options & NAND_BUSWIDTH_16)
 		stm32_fmc2_set_buswidth_16(fmc2, true);
 
-	/* Scan the device to fill MTD data-structures */
 	ret = nand_scan_tail(mtd);
 	if (ret)
 		return ret;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 03/11] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_5S for timeouts
  2020-07-31  7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
  2020-07-31  7:53 ` [PATCH 01/11] mtd: rawnand: stm32_fmc2: fix a buffer overflow Christophe Kerello
  2020-07-31  7:53 ` [PATCH 02/11] mtd: rawnand: stm32_fmc2: remove useless inline comments Christophe Kerello
@ 2020-07-31  7:53 ` Christophe Kerello
  2020-08-13  7:29   ` Patrice CHOTARD
  2020-07-31  7:53 ` [PATCH 04/11] mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2 where relevant Christophe Kerello
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31  7:53 UTC (permalink / raw)
  To: u-boot

FMC2_TIMEOUT_5S will be used each time that we need to wait.
It was seen, during stress tests in an overloaded system,
that we could be close to 1 second, even if we never met this
value. To be safe, FMC2_TIMEOUT_MS is set to 5 seconds.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---

 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index f43e3ec..2e947a3 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -131,6 +131,8 @@
 
 #define FMC2_NSEC_PER_SEC		1000000000L
 
+#define FMC2_TIMEOUT_5S			5000000
+
 enum stm32_fmc2_ecc {
 	FMC2_ECC_HAM = 1,
 	FMC2_ECC_BCH4 = 4,
@@ -339,7 +341,7 @@ static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
 	int ret;
 
 	ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr,
-				 sr & FMC2_SR_NWRF, 10000);
+				 sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
 	if (ret < 0) {
 		pr_err("Ham timeout\n");
 		return ret;
@@ -424,7 +426,7 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
 
 	/* Wait until the BCH code is ready */
 	ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
-				 bchisr & FMC2_BCHISR_EPBRF, 10000);
+				 bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
 	if (ret < 0) {
 		pr_err("Bch timeout\n");
 		return ret;
@@ -472,7 +474,7 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
 
 	/* Wait until the decoding error is ready */
 	ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
-				 bchisr & FMC2_BCHISR_DERF, 10000);
+				 bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
 	if (ret < 0) {
 		pr_err("Bch timeout\n");
 		return ret;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 04/11] mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2 where relevant
  2020-07-31  7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
                   ` (2 preceding siblings ...)
  2020-07-31  7:53 ` [PATCH 03/11] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_5S for timeouts Christophe Kerello
@ 2020-07-31  7:53 ` Christophe Kerello
  2020-08-13  7:29   ` Patrice CHOTARD
  2020-08-13  9:57   ` Patrice CHOTARD
  2020-07-31  7:53 ` [PATCH 05/11] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros Christophe Kerello
                   ` (6 subsequent siblings)
  10 siblings, 2 replies; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31  7:53 UTC (permalink / raw)
  To: u-boot

This patch renames functions and local variables.
This cleanup is done to get all functions starting by stm32_fmc2_nfc
in the FMC2 raw NAND driver when all functions will start by
stm32_fmc2_ebi in the FMC2 EBI driver.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---

 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 263 ++++++++++++++++-----------------
 1 file changed, 131 insertions(+), 132 deletions(-)

diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 2e947a3..9718bae 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -181,12 +181,12 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_hw_control *base)
 	return container_of(base, struct stm32_fmc2_nfc, base);
 }
 
-static void stm32_fmc2_timings_init(struct nand_chip *chip)
+static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
 	struct stm32_fmc2_timings *timings = &nand->timings;
-	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+	u32 pcr = readl(nfc->io_base + FMC2_PCR);
 	u32 pmem, patt;
 
 	/* Set tclr/tar timings */
@@ -207,15 +207,15 @@ static void stm32_fmc2_timings_init(struct nand_chip *chip)
 	patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
 	patt |= FMC2_PATT_ATTHIZ(timings->thiz);
 
-	writel(pcr, fmc2->io_base + FMC2_PCR);
-	writel(pmem, fmc2->io_base + FMC2_PMEM);
-	writel(patt, fmc2->io_base + FMC2_PATT);
+	writel(pcr, nfc->io_base + FMC2_PCR);
+	writel(pmem, nfc->io_base + FMC2_PMEM);
+	writel(patt, nfc->io_base + FMC2_PATT);
 }
 
-static void stm32_fmc2_setup(struct nand_chip *chip)
+static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
-	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	u32 pcr = readl(nfc->io_base + FMC2_PCR);
 
 	/* Configure ECC algorithm (default configuration is Hamming) */
 	pcr &= ~FMC2_PCR_ECCALG;
@@ -236,95 +236,96 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
 	pcr &= ~FMC2_PCR_ECCSS_MASK;
 	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
 
-	writel(pcr, fmc2->io_base + FMC2_PCR);
+	writel(pcr, nfc->io_base + FMC2_PCR);
 }
 
-static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
+static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
 
 	if (chipnr < 0 || chipnr >= nand->ncs)
 		return;
 
-	if (nand->cs_used[chipnr] == fmc2->cs_sel)
+	if (nand->cs_used[chipnr] == nfc->cs_sel)
 		return;
 
-	fmc2->cs_sel = nand->cs_used[chipnr];
-	chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel];
-	chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel];
+	nfc->cs_sel = nand->cs_used[chipnr];
+	chip->IO_ADDR_R = nfc->data_base[nfc->cs_sel];
+	chip->IO_ADDR_W = nfc->data_base[nfc->cs_sel];
 
-	stm32_fmc2_setup(chip);
-	stm32_fmc2_timings_init(chip);
+	stm32_fmc2_nfc_setup(chip);
+	stm32_fmc2_nfc_timings_init(chip);
 }
 
-static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
+static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
+					   bool set)
 {
-	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+	u32 pcr = readl(nfc->io_base + FMC2_PCR);
 
 	pcr &= ~FMC2_PCR_PWID_MASK;
 	if (set)
 		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
-	writel(pcr, fmc2->io_base + FMC2_PCR);
+	writel(pcr, nfc->io_base + FMC2_PCR);
 }
 
-static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
+static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
 {
-	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+	u32 pcr = readl(nfc->io_base + FMC2_PCR);
 
 	pcr &= ~FMC2_PCR_ECCEN;
 	if (enable)
 		pcr |= FMC2_PCR_ECCEN;
-	writel(pcr, fmc2->io_base + FMC2_PCR);
+	writel(pcr, nfc->io_base + FMC2_PCR);
 }
 
-static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
+static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
 {
-	writel(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
+	writel(FMC2_BCHICR_CLEAR_IRQ, nfc->io_base + FMC2_BCHICR);
 }
 
-static void stm32_fmc2_cmd_ctrl(struct mtd_info *mtd, int cmd,
-				unsigned int ctrl)
+static void stm32_fmc2_nfc_cmd_ctrl(struct mtd_info *mtd, int cmd,
+				    unsigned int ctrl)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 
 	if (cmd == NAND_CMD_NONE)
 		return;
 
 	if (ctrl & NAND_CLE) {
-		writeb(cmd, fmc2->cmd_base[fmc2->cs_sel]);
+		writeb(cmd, nfc->cmd_base[nfc->cs_sel]);
 		return;
 	}
 
-	writeb(cmd, fmc2->addr_base[fmc2->cs_sel]);
+	writeb(cmd, nfc->addr_base[nfc->cs_sel]);
 }
 
 /*
  * Enable ECC logic and reset syndrome/parity bits previously calculated
  * Syndrome/parity bits is cleared by setting the ECCEN bit to 0
  */
-static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
+static void stm32_fmc2_nfc_hwctl(struct mtd_info *mtd, int mode)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 
-	stm32_fmc2_set_ecc(fmc2, false);
+	stm32_fmc2_nfc_set_ecc(nfc, false);
 
 	if (chip->ecc.strength != FMC2_ECC_HAM) {
-		u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+		u32 pcr = readl(nfc->io_base + FMC2_PCR);
 
 		if (mode == NAND_ECC_WRITE)
 			pcr |= FMC2_PCR_WEN;
 		else
 			pcr &= ~FMC2_PCR_WEN;
-		writel(pcr, fmc2->io_base + FMC2_PCR);
+		writel(pcr, nfc->io_base + FMC2_PCR);
 
-		stm32_fmc2_clear_bch_irq(fmc2);
+		stm32_fmc2_nfc_clear_bch_irq(nfc);
 	}
 
-	stm32_fmc2_set_ecc(fmc2, true);
+	stm32_fmc2_nfc_set_ecc(nfc, true);
 }
 
 /*
@@ -332,34 +333,34 @@ static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
  * ECC is 3 bytes for 512 bytes of data (supports error correction up to
  * max of 1-bit)
  */
-static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
-				    u8 *ecc)
+static int stm32_fmc2_nfc_ham_calculate(struct mtd_info *mtd, const u8 *data,
+					u8 *ecc)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	u32 heccr, sr;
 	int ret;
 
-	ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr,
+	ret = readl_poll_timeout(nfc->io_base + FMC2_SR, sr,
 				 sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
 	if (ret < 0) {
 		pr_err("Ham timeout\n");
 		return ret;
 	}
 
-	heccr = readl(fmc2->io_base + FMC2_HECCR);
+	heccr = readl(nfc->io_base + FMC2_HECCR);
 
 	ecc[0] = heccr;
 	ecc[1] = heccr >> 8;
 	ecc[2] = heccr >> 16;
 
-	stm32_fmc2_set_ecc(fmc2, false);
+	stm32_fmc2_nfc_set_ecc(nfc, false);
 
 	return 0;
 }
 
-static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
-				  u8 *read_ecc, u8 *calc_ecc)
+static int stm32_fmc2_nfc_ham_correct(struct mtd_info *mtd, u8 *dat,
+				      u8 *read_ecc, u8 *calc_ecc)
 {
 	u8 bit_position = 0, b0, b1, b2;
 	u32 byte_addr = 0, b;
@@ -416,16 +417,16 @@ static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
  * max of 4-bit/8-bit)
  */
 
-static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
-				    u8 *ecc)
+static int stm32_fmc2_nfc_bch_calculate(struct mtd_info *mtd, const u8 *data,
+					u8 *ecc)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	u32 bchpbr, bchisr;
 	int ret;
 
 	/* Wait until the BCH code is ready */
-	ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
+	ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
 				 bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
 	if (ret < 0) {
 		pr_err("Bch timeout\n");
@@ -433,13 +434,13 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
 	}
 
 	/* Read parity bits */
-	bchpbr = readl(fmc2->io_base + FMC2_BCHPBR1);
+	bchpbr = readl(nfc->io_base + FMC2_BCHPBR1);
 	ecc[0] = bchpbr;
 	ecc[1] = bchpbr >> 8;
 	ecc[2] = bchpbr >> 16;
 	ecc[3] = bchpbr >> 24;
 
-	bchpbr = readl(fmc2->io_base + FMC2_BCHPBR2);
+	bchpbr = readl(nfc->io_base + FMC2_BCHPBR2);
 	ecc[4] = bchpbr;
 	ecc[5] = bchpbr >> 8;
 	ecc[6] = bchpbr >> 16;
@@ -447,46 +448,46 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
 	if (chip->ecc.strength == FMC2_ECC_BCH8) {
 		ecc[7] = bchpbr >> 24;
 
-		bchpbr = readl(fmc2->io_base + FMC2_BCHPBR3);
+		bchpbr = readl(nfc->io_base + FMC2_BCHPBR3);
 		ecc[8] = bchpbr;
 		ecc[9] = bchpbr >> 8;
 		ecc[10] = bchpbr >> 16;
 		ecc[11] = bchpbr >> 24;
 
-		bchpbr = readl(fmc2->io_base + FMC2_BCHPBR4);
+		bchpbr = readl(nfc->io_base + FMC2_BCHPBR4);
 		ecc[12] = bchpbr;
 	}
 
-	stm32_fmc2_set_ecc(fmc2, false);
+	stm32_fmc2_nfc_set_ecc(nfc, false);
 
 	return 0;
 }
 
-static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
-				  u8 *read_ecc, u8 *calc_ecc)
+static int stm32_fmc2_nfc_bch_correct(struct mtd_info *mtd, u8 *dat,
+				      u8 *read_ecc, u8 *calc_ecc)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	u32 bchdsr0, bchdsr1, bchdsr2, bchdsr3, bchdsr4, bchisr;
 	u16 pos[8];
 	int i, ret, den, eccsize = chip->ecc.size;
 	unsigned int nb_errs = 0;
 
 	/* Wait until the decoding error is ready */
-	ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
+	ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
 				 bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
 	if (ret < 0) {
 		pr_err("Bch timeout\n");
 		return ret;
 	}
 
-	bchdsr0 = readl(fmc2->io_base + FMC2_BCHDSR0);
-	bchdsr1 = readl(fmc2->io_base + FMC2_BCHDSR1);
-	bchdsr2 = readl(fmc2->io_base + FMC2_BCHDSR2);
-	bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3);
-	bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4);
+	bchdsr0 = readl(nfc->io_base + FMC2_BCHDSR0);
+	bchdsr1 = readl(nfc->io_base + FMC2_BCHDSR1);
+	bchdsr2 = readl(nfc->io_base + FMC2_BCHDSR2);
+	bchdsr3 = readl(nfc->io_base + FMC2_BCHDSR3);
+	bchdsr4 = readl(nfc->io_base + FMC2_BCHDSR4);
 
-	stm32_fmc2_set_ecc(fmc2, false);
+	stm32_fmc2_nfc_set_ecc(nfc, false);
 
 	/* No errors found */
 	if (likely(!(bchdsr0 & FMC2_BCHDSR0_DEF)))
@@ -516,9 +517,9 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
 	return nb_errs;
 }
 
-static int stm32_fmc2_read_page(struct mtd_info *mtd,
-				struct nand_chip *chip, u8 *buf,
-				int oob_required, int page)
+static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
+				    struct nand_chip *chip, u8 *buf,
+				    int oob_required, int page)
 {
 	int i, s, stat, eccsize = chip->ecc.size;
 	int eccbytes = chip->ecc.bytes;
@@ -567,13 +568,13 @@ static int stm32_fmc2_read_page(struct mtd_info *mtd,
 	return max_bitflips;
 }
 
-static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
+static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
 {
-	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
-	u32 bcr1 = readl(fmc2->io_base + FMC2_BCR1);
+	u32 pcr = readl(nfc->io_base + FMC2_PCR);
+	u32 bcr1 = readl(nfc->io_base + FMC2_BCR1);
 
 	/* Set CS used to undefined */
-	fmc2->cs_sel = -1;
+	nfc->cs_sel = -1;
 
 	/* Enable wait feature and nand flash memory bank */
 	pcr |= FMC2_PCR_PWAITEN;
@@ -603,19 +604,19 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
 	/* Enable FMC2 controller */
 	bcr1 |= FMC2_BCR1_FMC2EN;
 
-	writel(bcr1, fmc2->io_base + FMC2_BCR1);
-	writel(pcr, fmc2->io_base + FMC2_PCR);
-	writel(FMC2_PMEM_DEFAULT, fmc2->io_base + FMC2_PMEM);
-	writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
+	writel(bcr1, nfc->io_base + FMC2_BCR1);
+	writel(pcr, nfc->io_base + FMC2_PCR);
+	writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
+	writel(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);
 }
 
-static void stm32_fmc2_calc_timings(struct nand_chip *chip,
-				    const struct nand_sdr_timings *sdrt)
+static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip,
+					const struct nand_sdr_timings *sdrt)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
 	struct stm32_fmc2_timings *tims = &nand->timings;
-	unsigned long hclk = clk_get_rate(&fmc2->clk);
+	unsigned long hclk = clk_get_rate(&nfc->clk);
 	unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
 	unsigned long timing, tar, tclr, thiz, twait;
 	unsigned long tset_mem, tset_att, thold_mem, thold_att;
@@ -739,29 +740,28 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
 	tims->thold_att = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
 }
 
-static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr,
-				      const struct nand_data_interface *conf)
+static int stm32_fmc2_nfc_setup_interface(struct mtd_info *mtd, int chipnr,
+					  const struct nand_data_interface *cf)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	const struct nand_sdr_timings *sdrt;
 
-	sdrt = nand_get_sdr_timings(conf);
+	sdrt = nand_get_sdr_timings(cf);
 	if (IS_ERR(sdrt))
 		return PTR_ERR(sdrt);
 
 	if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
 		return 0;
 
-	stm32_fmc2_calc_timings(chip, sdrt);
-
-	stm32_fmc2_timings_init(chip);
+	stm32_fmc2_nfc_calc_timings(chip, sdrt);
+	stm32_fmc2_nfc_timings_init(chip);
 
 	return 0;
 }
 
-static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
+static void stm32_fmc2_nfc_nand_callbacks_setup(struct nand_chip *chip)
 {
-	chip->ecc.hwctl = stm32_fmc2_hwctl;
+	chip->ecc.hwctl = stm32_fmc2_nfc_hwctl;
 
 	/*
 	 * Specific callbacks to read/write a page depending on
@@ -769,17 +769,17 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
 	 */
 	if (chip->ecc.strength == FMC2_ECC_HAM) {
 		/* Hamming is used */
-		chip->ecc.calculate = stm32_fmc2_ham_calculate;
-		chip->ecc.correct = stm32_fmc2_ham_correct;
+		chip->ecc.calculate = stm32_fmc2_nfc_ham_calculate;
+		chip->ecc.correct = stm32_fmc2_nfc_ham_correct;
 		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 4 : 3;
 		chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK;
 		return;
 	}
 
 	/* BCH is used */
-	chip->ecc.read_page = stm32_fmc2_read_page;
-	chip->ecc.calculate = stm32_fmc2_bch_calculate;
-	chip->ecc.correct = stm32_fmc2_bch_correct;
+	chip->ecc.read_page = stm32_fmc2_nfc_read_page;
+	chip->ecc.calculate = stm32_fmc2_nfc_bch_calculate;
+	chip->ecc.correct = stm32_fmc2_nfc_bch_correct;
 
 	if (chip->ecc.strength == FMC2_ECC_BCH8)
 		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 14 : 13;
@@ -787,7 +787,7 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
 		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
 }
 
-static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
+static int stm32_fmc2_nfc_calc_ecc_bytes(int step_size, int strength)
 {
 	/* Hamming */
 	if (strength == FMC2_ECC_HAM)
@@ -801,14 +801,13 @@ static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
 	return 8;
 }
 
-NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
+NAND_ECC_CAPS_SINGLE(stm32_fmc2_nfc_ecc_caps, stm32_fmc2_nfc_calc_ecc_bytes,
 		     FMC2_ECC_STEP_SIZE,
 		     FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
 
-static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
-				  ofnode node)
+static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, ofnode node)
 {
-	struct stm32_fmc2_nand *nand = &fmc2->nand;
+	struct stm32_fmc2_nand *nand = &nfc->nand;
 	u32 cs[FMC2_MAX_CE];
 	int ret, i;
 
@@ -834,13 +833,13 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
 			return -EINVAL;
 		}
 
-		if (fmc2->cs_assigned & BIT(cs[i])) {
+		if (nfc->cs_assigned & BIT(cs[i])) {
 			pr_err("Cs already assigned: %d\n",
 			       nand->cs_used[i]);
 			return -EINVAL;
 		}
 
-		fmc2->cs_assigned |= BIT(cs[i]);
+		nfc->cs_assigned |= BIT(cs[i]);
 		nand->cs_used[i] = cs[i];
 	}
 
@@ -849,8 +848,8 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
 	return 0;
 }
 
-static int stm32_fmc2_parse_dt(struct udevice *dev,
-			       struct stm32_fmc2_nfc *fmc2)
+static int stm32_fmc2_nfc_parse_dt(struct udevice *dev,
+				   struct stm32_fmc2_nfc *nfc)
 {
 	ofnode child;
 	int ret, nchips = 0;
@@ -869,7 +868,7 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
 	}
 
 	dev_for_each_subnode(child, dev) {
-		ret = stm32_fmc2_parse_child(fmc2, child);
+		ret = stm32_fmc2_nfc_parse_child(nfc, child);
 		if (ret)
 			return ret;
 	}
@@ -877,10 +876,10 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
 	return 0;
 }
 
-static int stm32_fmc2_probe(struct udevice *dev)
+static int stm32_fmc2_nfc_probe(struct udevice *dev)
 {
-	struct stm32_fmc2_nfc *fmc2 = dev_get_priv(dev);
-	struct stm32_fmc2_nand *nand = &fmc2->nand;
+	struct stm32_fmc2_nfc *nfc = dev_get_priv(dev);
+	struct stm32_fmc2_nand *nand = &nfc->nand;
 	struct nand_chip *chip = &nand->chip;
 	struct mtd_info *mtd = &chip->mtd;
 	struct nand_ecclayout *ecclayout;
@@ -889,10 +888,10 @@ static int stm32_fmc2_probe(struct udevice *dev)
 	int oob_index, chip_cs, mem_region, ret;
 	unsigned int i;
 
-	spin_lock_init(&fmc2->controller.lock);
-	init_waitqueue_head(&fmc2->controller.wq);
+	spin_lock_init(&nfc->controller.lock);
+	init_waitqueue_head(&nfc->controller.wq);
 
-	ret = stm32_fmc2_parse_dt(dev, fmc2);
+	ret = stm32_fmc2_nfc_parse_dt(dev, nfc);
 	if (ret)
 		return ret;
 
@@ -902,11 +901,11 @@ static int stm32_fmc2_probe(struct udevice *dev)
 		pr_err("Resource io_base not found");
 		return ret;
 	}
-	fmc2->io_base = (void __iomem *)resource.start;
+	nfc->io_base = (void __iomem *)resource.start;
 
 	for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
 	     chip_cs++, mem_region += 3) {
-		if (!(fmc2->cs_assigned & BIT(chip_cs)))
+		if (!(nfc->cs_assigned & BIT(chip_cs)))
 			continue;
 
 		ret = dev_read_resource(dev, mem_region, &resource);
@@ -915,7 +914,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
 			       chip_cs);
 			return ret;
 		}
-		fmc2->data_base[chip_cs] = (void __iomem *)resource.start;
+		nfc->data_base[chip_cs] = (void __iomem *)resource.start;
 
 		ret = dev_read_resource(dev, mem_region + 1, &resource);
 		if (ret) {
@@ -923,7 +922,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
 			       chip_cs);
 			return ret;
 		}
-		fmc2->cmd_base[chip_cs] = (void __iomem *)resource.start;
+		nfc->cmd_base[chip_cs] = (void __iomem *)resource.start;
 
 		ret = dev_read_resource(dev, mem_region + 2, &resource);
 		if (ret) {
@@ -931,15 +930,15 @@ static int stm32_fmc2_probe(struct udevice *dev)
 			       chip_cs);
 			return ret;
 		}
-		fmc2->addr_base[chip_cs] = (void __iomem *)resource.start;
+		nfc->addr_base[chip_cs] = (void __iomem *)resource.start;
 	}
 
 	/* Enable the clock */
-	ret = clk_get_by_index(dev, 0, &fmc2->clk);
+	ret = clk_get_by_index(dev, 0, &nfc->clk);
 	if (ret)
 		return ret;
 
-	ret = clk_enable(&fmc2->clk);
+	ret = clk_enable(&nfc->clk);
 	if (ret)
 		return ret;
 
@@ -951,12 +950,12 @@ static int stm32_fmc2_probe(struct udevice *dev)
 		reset_deassert(&reset);
 	}
 
-	stm32_fmc2_init(fmc2);
+	stm32_fmc2_nfc_init(nfc);
 
-	chip->controller = &fmc2->base;
-	chip->select_chip = stm32_fmc2_select_chip;
-	chip->setup_data_interface = stm32_fmc2_setup_interface;
-	chip->cmd_ctrl = stm32_fmc2_cmd_ctrl;
+	chip->controller = &nfc->base;
+	chip->select_chip = stm32_fmc2_nfc_select_chip;
+	chip->setup_data_interface = stm32_fmc2_nfc_setup_interface;
+	chip->cmd_ctrl = stm32_fmc2_nfc_cmd_ctrl;
 	chip->chip_delay = FMC2_RB_DELAY_US;
 	chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE |
 			 NAND_USE_BOUNCE_BUFFER;
@@ -982,7 +981,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
 		return -EINVAL;
 	}
 
-	ret = nand_check_ecc_caps(chip, &stm32_fmc2_ecc_caps,
+	ret = nand_check_ecc_caps(chip, &stm32_fmc2_nfc_ecc_caps,
 				  mtd->oobsize - FMC2_BBM_LEN);
 	if (ret) {
 		pr_err("No valid ECC settings set\n");
@@ -992,10 +991,10 @@ static int stm32_fmc2_probe(struct udevice *dev)
 	if (chip->bbt_options & NAND_BBT_USE_FLASH)
 		chip->bbt_options |= NAND_BBT_NO_OOB;
 
-	stm32_fmc2_nand_callbacks_setup(chip);
+	stm32_fmc2_nfc_nand_callbacks_setup(chip);
 
 	/* Define ECC layout */
-	ecclayout = &fmc2->ecclayout;
+	ecclayout = &nfc->ecclayout;
 	ecclayout->eccbytes = chip->ecc.bytes *
 			      (mtd->writesize / chip->ecc.size);
 	oob_index = FMC2_BBM_LEN;
@@ -1006,7 +1005,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
 	chip->ecc.layout = ecclayout;
 
 	if (chip->options & NAND_BUSWIDTH_16)
-		stm32_fmc2_set_buswidth_16(fmc2, true);
+		stm32_fmc2_nfc_set_buswidth_16(nfc, true);
 
 	ret = nand_scan_tail(mtd);
 	if (ret)
@@ -1015,16 +1014,16 @@ static int stm32_fmc2_probe(struct udevice *dev)
 	return nand_register(0, mtd);
 }
 
-static const struct udevice_id stm32_fmc2_match[] = {
+static const struct udevice_id stm32_fmc2_nfc_match[] = {
 	{ .compatible = "st,stm32mp15-fmc2" },
 	{ /* Sentinel */ }
 };
 
-U_BOOT_DRIVER(stm32_fmc2_nand) = {
-	.name = "stm32_fmc2_nand",
+U_BOOT_DRIVER(stm32_fmc2_nfc) = {
+	.name = "stm32_fmc2_nfc",
 	.id = UCLASS_MTD,
-	.of_match = stm32_fmc2_match,
-	.probe = stm32_fmc2_probe,
+	.of_match = stm32_fmc2_nfc_match,
+	.probe = stm32_fmc2_nfc_probe,
 	.priv_auto_alloc_size = sizeof(struct stm32_fmc2_nfc),
 };
 
@@ -1034,9 +1033,9 @@ void board_nand_init(void)
 	int ret;
 
 	ret = uclass_get_device_by_driver(UCLASS_MTD,
-					  DM_GET_DRIVER(stm32_fmc2_nand),
+					  DM_GET_DRIVER(stm32_fmc2_nfc),
 					  &dev);
 	if (ret && ret != -ENODEV)
-		pr_err("Failed to initialize STM32 FMC2 NAND controller. (error %d)\n",
+		pr_err("Failed to initialize STM32 FMC2 NFC controller. (error %d)\n",
 		       ret);
 }
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 05/11] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros
  2020-07-31  7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
                   ` (3 preceding siblings ...)
  2020-07-31  7:53 ` [PATCH 04/11] mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2 where relevant Christophe Kerello
@ 2020-07-31  7:53 ` Christophe Kerello
  2020-08-13  7:29   ` Patrice CHOTARD
  2020-07-31  7:53 ` [PATCH 06/11] mtd: rawnand: stm32_fmc2: use clrsetbits_le32 Christophe Kerello
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31  7:53 UTC (permalink / raw)
  To: u-boot

This patch removes custom macros and uses FIELD_PREP and FIELD_GET macros.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---

 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 120 +++++++++++++++------------------
 1 file changed, 56 insertions(+), 64 deletions(-)

diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 9718bae..eba1ded 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -10,6 +10,7 @@
 #include <log.h>
 #include <nand.h>
 #include <reset.h>
+#include <linux/bitfield.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/err.h>
@@ -60,20 +61,16 @@
 /* Register: FMC2_PCR */
 #define FMC2_PCR_PWAITEN		BIT(1)
 #define FMC2_PCR_PBKEN			BIT(2)
-#define FMC2_PCR_PWID_MASK		GENMASK(5, 4)
-#define FMC2_PCR_PWID(x)		(((x) & 0x3) << 4)
+#define FMC2_PCR_PWID			GENMASK(5, 4)
 #define FMC2_PCR_PWID_BUSWIDTH_8	0
 #define FMC2_PCR_PWID_BUSWIDTH_16	1
 #define FMC2_PCR_ECCEN			BIT(6)
 #define FMC2_PCR_ECCALG			BIT(8)
-#define FMC2_PCR_TCLR_MASK		GENMASK(12, 9)
-#define FMC2_PCR_TCLR(x)		(((x) & 0xf) << 9)
+#define FMC2_PCR_TCLR			GENMASK(12, 9)
 #define FMC2_PCR_TCLR_DEFAULT		0xf
-#define FMC2_PCR_TAR_MASK		GENMASK(16, 13)
-#define FMC2_PCR_TAR(x)			(((x) & 0xf) << 13)
+#define FMC2_PCR_TAR			GENMASK(16, 13)
 #define FMC2_PCR_TAR_DEFAULT		0xf
-#define FMC2_PCR_ECCSS_MASK		GENMASK(19, 17)
-#define FMC2_PCR_ECCSS(x)		(((x) & 0x7) << 17)
+#define FMC2_PCR_ECCSS			GENMASK(19, 17)
 #define FMC2_PCR_ECCSS_512		1
 #define FMC2_PCR_ECCSS_2048		3
 #define FMC2_PCR_BCHECC			BIT(24)
@@ -83,17 +80,17 @@
 #define FMC2_SR_NWRF			BIT(6)
 
 /* Register: FMC2_PMEM */
-#define FMC2_PMEM_MEMSET(x)		(((x) & 0xff) << 0)
-#define FMC2_PMEM_MEMWAIT(x)		(((x) & 0xff) << 8)
-#define FMC2_PMEM_MEMHOLD(x)		(((x) & 0xff) << 16)
-#define FMC2_PMEM_MEMHIZ(x)		(((x) & 0xff) << 24)
+#define FMC2_PMEM_MEMSET		GENMASK(7, 0)
+#define FMC2_PMEM_MEMWAIT		GENMASK(15, 8)
+#define FMC2_PMEM_MEMHOLD		GENMASK(23, 16)
+#define FMC2_PMEM_MEMHIZ		GENMASK(31, 24)
 #define FMC2_PMEM_DEFAULT		0x0a0a0a0a
 
 /* Register: FMC2_PATT */
-#define FMC2_PATT_ATTSET(x)		(((x) & 0xff) << 0)
-#define FMC2_PATT_ATTWAIT(x)		(((x) & 0xff) << 8)
-#define FMC2_PATT_ATTHOLD(x)		(((x) & 0xff) << 16)
-#define FMC2_PATT_ATTHIZ(x)		(((x) & 0xff) << 24)
+#define FMC2_PATT_ATTSET		GENMASK(7, 0)
+#define FMC2_PATT_ATTWAIT		GENMASK(15, 8)
+#define FMC2_PATT_ATTHOLD		GENMASK(23, 16)
+#define FMC2_PATT_ATTHIZ		GENMASK(31, 24)
 #define FMC2_PATT_DEFAULT		0x0a0a0a0a
 
 /* Register: FMC2_BCHISR */
@@ -106,28 +103,23 @@
 /* Register: FMC2_BCHDSR0 */
 #define FMC2_BCHDSR0_DUE		BIT(0)
 #define FMC2_BCHDSR0_DEF		BIT(1)
-#define FMC2_BCHDSR0_DEN_MASK		GENMASK(7, 4)
-#define FMC2_BCHDSR0_DEN_SHIFT		4
+#define FMC2_BCHDSR0_DEN		GENMASK(7, 4)
 
 /* Register: FMC2_BCHDSR1 */
-#define FMC2_BCHDSR1_EBP1_MASK		GENMASK(12, 0)
-#define FMC2_BCHDSR1_EBP2_MASK		GENMASK(28, 16)
-#define FMC2_BCHDSR1_EBP2_SHIFT		16
+#define FMC2_BCHDSR1_EBP1		GENMASK(12, 0)
+#define FMC2_BCHDSR1_EBP2		GENMASK(28, 16)
 
 /* Register: FMC2_BCHDSR2 */
-#define FMC2_BCHDSR2_EBP3_MASK		GENMASK(12, 0)
-#define FMC2_BCHDSR2_EBP4_MASK		GENMASK(28, 16)
-#define FMC2_BCHDSR2_EBP4_SHIFT		16
+#define FMC2_BCHDSR2_EBP3		GENMASK(12, 0)
+#define FMC2_BCHDSR2_EBP4		GENMASK(28, 16)
 
 /* Register: FMC2_BCHDSR3 */
-#define FMC2_BCHDSR3_EBP5_MASK		GENMASK(12, 0)
-#define FMC2_BCHDSR3_EBP6_MASK		GENMASK(28, 16)
-#define FMC2_BCHDSR3_EBP6_SHIFT		16
+#define FMC2_BCHDSR3_EBP5		GENMASK(12, 0)
+#define FMC2_BCHDSR3_EBP6		GENMASK(28, 16)
 
 /* Register: FMC2_BCHDSR4 */
-#define FMC2_BCHDSR4_EBP7_MASK		GENMASK(12, 0)
-#define FMC2_BCHDSR4_EBP8_MASK		GENMASK(28, 16)
-#define FMC2_BCHDSR4_EBP8_SHIFT		16
+#define FMC2_BCHDSR4_EBP7		GENMASK(12, 0)
+#define FMC2_BCHDSR4_EBP8		GENMASK(28, 16)
 
 #define FMC2_NSEC_PER_SEC		1000000000L
 
@@ -190,22 +182,22 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
 	u32 pmem, patt;
 
 	/* Set tclr/tar timings */
-	pcr &= ~FMC2_PCR_TCLR_MASK;
-	pcr |= FMC2_PCR_TCLR(timings->tclr);
-	pcr &= ~FMC2_PCR_TAR_MASK;
-	pcr |= FMC2_PCR_TAR(timings->tar);
+	pcr &= ~FMC2_PCR_TCLR;
+	pcr |= FIELD_PREP(FMC2_PCR_TCLR, timings->tclr);
+	pcr &= ~FMC2_PCR_TAR;
+	pcr |= FIELD_PREP(FMC2_PCR_TAR, timings->tar);
 
 	/* Set tset/twait/thold/thiz timings in common bank */
-	pmem = FMC2_PMEM_MEMSET(timings->tset_mem);
-	pmem |= FMC2_PMEM_MEMWAIT(timings->twait);
-	pmem |= FMC2_PMEM_MEMHOLD(timings->thold_mem);
-	pmem |= FMC2_PMEM_MEMHIZ(timings->thiz);
+	pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
+	pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
+	pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
+	pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
 
 	/* Set tset/twait/thold/thiz timings in attribut bank */
-	patt = FMC2_PATT_ATTSET(timings->tset_att);
-	patt |= FMC2_PATT_ATTWAIT(timings->twait);
-	patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
-	patt |= FMC2_PATT_ATTHIZ(timings->thiz);
+	patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
+	patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
+	patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
+	patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
 
 	writel(pcr, nfc->io_base + FMC2_PCR);
 	writel(pmem, nfc->io_base + FMC2_PMEM);
@@ -228,13 +220,13 @@ static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
 	}
 
 	/* Set buswidth */
-	pcr &= ~FMC2_PCR_PWID_MASK;
+	pcr &= ~FMC2_PCR_PWID;
 	if (chip->options & NAND_BUSWIDTH_16)
-		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
+		pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
 
 	/* Set ECC sector size */
-	pcr &= ~FMC2_PCR_ECCSS_MASK;
-	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
+	pcr &= ~FMC2_PCR_ECCSS;
+	pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
 
 	writel(pcr, nfc->io_base + FMC2_PCR);
 }
@@ -264,9 +256,9 @@ static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
 {
 	u32 pcr = readl(nfc->io_base + FMC2_PCR);
 
-	pcr &= ~FMC2_PCR_PWID_MASK;
+	pcr &= ~FMC2_PCR_PWID;
 	if (set)
-		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
+		pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
 	writel(pcr, nfc->io_base + FMC2_PCR);
 }
 
@@ -497,16 +489,16 @@ static int stm32_fmc2_nfc_bch_correct(struct mtd_info *mtd, u8 *dat,
 	if (unlikely(bchdsr0 & FMC2_BCHDSR0_DUE))
 		return -EBADMSG;
 
-	pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK;
-	pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT;
-	pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK;
-	pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT;
-	pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK;
-	pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT;
-	pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK;
-	pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT;
+	pos[0] = FIELD_GET(FMC2_BCHDSR1_EBP1, bchdsr1);
+	pos[1] = FIELD_GET(FMC2_BCHDSR1_EBP2, bchdsr1);
+	pos[2] = FIELD_GET(FMC2_BCHDSR2_EBP3, bchdsr2);
+	pos[3] = FIELD_GET(FMC2_BCHDSR2_EBP4, bchdsr2);
+	pos[4] = FIELD_GET(FMC2_BCHDSR3_EBP5, bchdsr3);
+	pos[5] = FIELD_GET(FMC2_BCHDSR3_EBP6, bchdsr3);
+	pos[6] = FIELD_GET(FMC2_BCHDSR4_EBP7, bchdsr4);
+	pos[7] = FIELD_GET(FMC2_BCHDSR4_EBP8, bchdsr4);
 
-	den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT;
+	den = FIELD_GET(FMC2_BCHDSR0_DEN, bchdsr0);
 	for (i = 0; i < den; i++) {
 		if (pos[i] < eccsize * 8) {
 			__change_bit(pos[i], (unsigned long *)dat);
@@ -581,7 +573,7 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
 	pcr |= FMC2_PCR_PBKEN;
 
 	/* Set buswidth to 8 bits mode for identification */
-	pcr &= ~FMC2_PCR_PWID_MASK;
+	pcr &= ~FMC2_PCR_PWID;
 
 	/* ECC logic is disabled */
 	pcr &= ~FMC2_PCR_ECCEN;
@@ -592,14 +584,14 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
 	pcr &= ~FMC2_PCR_WEN;
 
 	/* Set default ECC sector size */
-	pcr &= ~FMC2_PCR_ECCSS_MASK;
-	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048);
+	pcr &= ~FMC2_PCR_ECCSS;
+	pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_2048);
 
 	/* Set default tclr/tar timings */
-	pcr &= ~FMC2_PCR_TCLR_MASK;
-	pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT);
-	pcr &= ~FMC2_PCR_TAR_MASK;
-	pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT);
+	pcr &= ~FMC2_PCR_TCLR;
+	pcr |= FIELD_PREP(FMC2_PCR_TCLR, FMC2_PCR_TCLR_DEFAULT);
+	pcr &= ~FMC2_PCR_TAR;
+	pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
 
 	/* Enable FMC2 controller */
 	bcr1 |= FMC2_BCR1_FMC2EN;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 06/11] mtd: rawnand: stm32_fmc2: use clrsetbits_le32
  2020-07-31  7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
                   ` (4 preceding siblings ...)
  2020-07-31  7:53 ` [PATCH 05/11] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros Christophe Kerello
@ 2020-07-31  7:53 ` Christophe Kerello
  2020-08-13  7:30   ` Patrice CHOTARD
  2020-07-31  7:53 ` [PATCH 07/11] memory: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver Christophe Kerello
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31  7:53 UTC (permalink / raw)
  To: u-boot

This patch uses clrsetbits_le32 function instead of multiple instructions.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---

 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 56 +++++++++++++---------------------
 1 file changed, 21 insertions(+), 35 deletions(-)

diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index eba1ded..1e4d757 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -178,40 +178,37 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
 	struct stm32_fmc2_timings *timings = &nand->timings;
-	u32 pcr = readl(nfc->io_base + FMC2_PCR);
 	u32 pmem, patt;
 
 	/* Set tclr/tar timings */
-	pcr &= ~FMC2_PCR_TCLR;
-	pcr |= FIELD_PREP(FMC2_PCR_TCLR, timings->tclr);
-	pcr &= ~FMC2_PCR_TAR;
-	pcr |= FIELD_PREP(FMC2_PCR_TAR, timings->tar);
+	clrsetbits_le32(nfc->io_base + FMC2_PCR,
+			FMC2_PCR_TCLR | FMC2_PCR_TAR,
+			FIELD_PREP(FMC2_PCR_TCLR, timings->tclr) |
+			FIELD_PREP(FMC2_PCR_TAR, timings->tar));
 
 	/* Set tset/twait/thold/thiz timings in common bank */
 	pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
 	pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
 	pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
 	pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
+	writel(pmem, nfc->io_base + FMC2_PMEM);
 
 	/* Set tset/twait/thold/thiz timings in attribut bank */
 	patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
 	patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
 	patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
 	patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
-
-	writel(pcr, nfc->io_base + FMC2_PCR);
-	writel(pmem, nfc->io_base + FMC2_PMEM);
 	writel(patt, nfc->io_base + FMC2_PATT);
 }
 
 static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
-	u32 pcr = readl(nfc->io_base + FMC2_PCR);
+	u32 pcr = 0, pcr_mask;
 
 	/* Configure ECC algorithm (default configuration is Hamming) */
-	pcr &= ~FMC2_PCR_ECCALG;
-	pcr &= ~FMC2_PCR_BCHECC;
+	pcr_mask = FMC2_PCR_ECCALG;
+	pcr_mask |= FMC2_PCR_BCHECC;
 	if (chip->ecc.strength == FMC2_ECC_BCH8) {
 		pcr |= FMC2_PCR_ECCALG;
 		pcr |= FMC2_PCR_BCHECC;
@@ -220,15 +217,15 @@ static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
 	}
 
 	/* Set buswidth */
-	pcr &= ~FMC2_PCR_PWID;
+	pcr_mask |= FMC2_PCR_PWID;
 	if (chip->options & NAND_BUSWIDTH_16)
 		pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
 
 	/* Set ECC sector size */
-	pcr &= ~FMC2_PCR_ECCSS;
+	pcr_mask |= FMC2_PCR_ECCSS;
 	pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
 
-	writel(pcr, nfc->io_base + FMC2_PCR);
+	clrsetbits_le32(nfc->io_base + FMC2_PCR, pcr_mask, pcr);
 }
 
 static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
@@ -254,22 +251,18 @@ static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
 static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
 					   bool set)
 {
-	u32 pcr = readl(nfc->io_base + FMC2_PCR);
+	u32 pcr;
 
-	pcr &= ~FMC2_PCR_PWID;
-	if (set)
-		pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
-	writel(pcr, nfc->io_base + FMC2_PCR);
+	pcr = set ? FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16) :
+		    FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_8);
+
+	clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_PWID, pcr);
 }
 
 static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
 {
-	u32 pcr = readl(nfc->io_base + FMC2_PCR);
-
-	pcr &= ~FMC2_PCR_ECCEN;
-	if (enable)
-		pcr |= FMC2_PCR_ECCEN;
-	writel(pcr, nfc->io_base + FMC2_PCR);
+	clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_ECCEN,
+			enable ? FMC2_PCR_ECCEN : 0);
 }
 
 static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
@@ -306,13 +299,8 @@ static void stm32_fmc2_nfc_hwctl(struct mtd_info *mtd, int mode)
 	stm32_fmc2_nfc_set_ecc(nfc, false);
 
 	if (chip->ecc.strength != FMC2_ECC_HAM) {
-		u32 pcr = readl(nfc->io_base + FMC2_PCR);
-
-		if (mode == NAND_ECC_WRITE)
-			pcr |= FMC2_PCR_WEN;
-		else
-			pcr &= ~FMC2_PCR_WEN;
-		writel(pcr, nfc->io_base + FMC2_PCR);
+		clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_WEN,
+				mode == NAND_ECC_WRITE ? FMC2_PCR_WEN : 0);
 
 		stm32_fmc2_nfc_clear_bch_irq(nfc);
 	}
@@ -563,7 +551,6 @@ static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
 static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
 {
 	u32 pcr = readl(nfc->io_base + FMC2_PCR);
-	u32 bcr1 = readl(nfc->io_base + FMC2_BCR1);
 
 	/* Set CS used to undefined */
 	nfc->cs_sel = -1;
@@ -594,9 +581,8 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
 	pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
 
 	/* Enable FMC2 controller */
-	bcr1 |= FMC2_BCR1_FMC2EN;
+	setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
 
-	writel(bcr1, nfc->io_base + FMC2_BCR1);
 	writel(pcr, nfc->io_base + FMC2_PCR);
 	writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
 	writel(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 07/11] memory: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver
  2020-07-31  7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
                   ` (5 preceding siblings ...)
  2020-07-31  7:53 ` [PATCH 06/11] mtd: rawnand: stm32_fmc2: use clrsetbits_le32 Christophe Kerello
@ 2020-07-31  7:53 ` Christophe Kerello
  2020-08-13  7:31   ` Patrice CHOTARD
  2020-07-31  7:53 ` [PATCH 08/11] mtd: rawnand: stm32_fmc2: get resources from parent node Christophe Kerello
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31  7:53 UTC (permalink / raw)
  To: u-boot

The driver adds the support for the STMicroelectronics FMC2 EBI controller
found on STM32MP SOCs.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---

 drivers/memory/Kconfig          |    9 +
 drivers/memory/Makefile         |    1 +
 drivers/memory/stm32-fmc2-ebi.c | 1056 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 1066 insertions(+)
 create mode 100644 drivers/memory/stm32-fmc2-ebi.c

diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 4fbb5aa..7271892 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -4,6 +4,15 @@
 
 menu "Memory Controller drivers"
 
+config STM32_FMC2_EBI
+	bool "Support for FMC2 External Bus Interface on STM32MP SoCs"
+	depends on ARCH_STM32MP
+	help
+	  Select this option to enable the STM32 FMC2 External Bus Interface
+	  controller. This driver configures the transactions with external
+	  devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on
+	  SOCs containing the FMC2 External Bus Interface.
+
 config TI_AEMIF
 	tristate "Texas Instruments AEMIF driver"
 	depends on ARCH_KEYSTONE
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 238add0..fec52ef 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -1,2 +1,3 @@
 
+obj-$(CONFIG_STM32_FMC2_EBI) += stm32-fmc2-ebi.o
 obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
diff --git a/drivers/memory/stm32-fmc2-ebi.c b/drivers/memory/stm32-fmc2-ebi.c
new file mode 100644
index 0000000..d887a1e
--- /dev/null
+++ b/drivers/memory/stm32-fmc2-ebi.c
@@ -0,0 +1,1056 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) STMicroelectronics 2020
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <reset.h>
+#include <linux/bitfield.h>
+#include <linux/err.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+
+/* FMC2 Controller Registers */
+#define FMC2_BCR1			0x0
+#define FMC2_BTR1			0x4
+#define FMC2_BCR(x)			((x) * 0x8 + FMC2_BCR1)
+#define FMC2_BTR(x)			((x) * 0x8 + FMC2_BTR1)
+#define FMC2_PCSCNTR			0x20
+#define FMC2_BWTR1			0x104
+#define FMC2_BWTR(x)			((x) * 0x8 + FMC2_BWTR1)
+
+/* Register: FMC2_BCR1 */
+#define FMC2_BCR1_CCLKEN		BIT(20)
+#define FMC2_BCR1_FMC2EN		BIT(31)
+
+/* Register: FMC2_BCRx */
+#define FMC2_BCR_MBKEN			BIT(0)
+#define FMC2_BCR_MUXEN			BIT(1)
+#define FMC2_BCR_MTYP			GENMASK(3, 2)
+#define FMC2_BCR_MWID			GENMASK(5, 4)
+#define FMC2_BCR_FACCEN			BIT(6)
+#define FMC2_BCR_BURSTEN		BIT(8)
+#define FMC2_BCR_WAITPOL		BIT(9)
+#define FMC2_BCR_WAITCFG		BIT(11)
+#define FMC2_BCR_WREN			BIT(12)
+#define FMC2_BCR_WAITEN			BIT(13)
+#define FMC2_BCR_EXTMOD			BIT(14)
+#define FMC2_BCR_ASYNCWAIT		BIT(15)
+#define FMC2_BCR_CPSIZE			GENMASK(18, 16)
+#define FMC2_BCR_CBURSTRW		BIT(19)
+#define FMC2_BCR_NBLSET			GENMASK(23, 22)
+
+/* Register: FMC2_BTRx/FMC2_BWTRx */
+#define FMC2_BXTR_ADDSET		GENMASK(3, 0)
+#define FMC2_BXTR_ADDHLD		GENMASK(7, 4)
+#define FMC2_BXTR_DATAST		GENMASK(15, 8)
+#define FMC2_BXTR_BUSTURN		GENMASK(19, 16)
+#define FMC2_BTR_CLKDIV			GENMASK(23, 20)
+#define FMC2_BTR_DATLAT			GENMASK(27, 24)
+#define FMC2_BXTR_ACCMOD		GENMASK(29, 28)
+#define FMC2_BXTR_DATAHLD		GENMASK(31, 30)
+
+/* Register: FMC2_PCSCNTR */
+#define FMC2_PCSCNTR_CSCOUNT		GENMASK(15, 0)
+#define FMC2_PCSCNTR_CNTBEN(x)		BIT((x) + 16)
+
+#define FMC2_MAX_EBI_CE			4
+#define FMC2_MAX_BANKS			5
+
+#define FMC2_BCR_CPSIZE_0		0x0
+#define FMC2_BCR_CPSIZE_128		0x1
+#define FMC2_BCR_CPSIZE_256		0x2
+#define FMC2_BCR_CPSIZE_512		0x3
+#define FMC2_BCR_CPSIZE_1024		0x4
+
+#define FMC2_BCR_MWID_8			0x0
+#define FMC2_BCR_MWID_16		0x1
+
+#define FMC2_BCR_MTYP_SRAM		0x0
+#define FMC2_BCR_MTYP_PSRAM		0x1
+#define FMC2_BCR_MTYP_NOR		0x2
+
+#define FMC2_BXTR_EXTMOD_A		0x0
+#define FMC2_BXTR_EXTMOD_B		0x1
+#define FMC2_BXTR_EXTMOD_C		0x2
+#define FMC2_BXTR_EXTMOD_D		0x3
+
+#define FMC2_BCR_NBLSET_MAX		0x3
+#define FMC2_BXTR_ADDSET_MAX		0xf
+#define FMC2_BXTR_ADDHLD_MAX		0xf
+#define FMC2_BXTR_DATAST_MAX		0xff
+#define FMC2_BXTR_BUSTURN_MAX		0xf
+#define FMC2_BXTR_DATAHLD_MAX		0x3
+#define FMC2_BTR_CLKDIV_MAX		0xf
+#define FMC2_BTR_DATLAT_MAX		0xf
+#define FMC2_PCSCNTR_CSCOUNT_MAX	0xff
+
+#define FMC2_NSEC_PER_SEC		1000000000L
+
+enum stm32_fmc2_ebi_bank {
+	FMC2_EBI1 = 0,
+	FMC2_EBI2,
+	FMC2_EBI3,
+	FMC2_EBI4,
+	FMC2_NAND
+};
+
+enum stm32_fmc2_ebi_register_type {
+	FMC2_REG_BCR = 1,
+	FMC2_REG_BTR,
+	FMC2_REG_BWTR,
+	FMC2_REG_PCSCNTR
+};
+
+enum stm32_fmc2_ebi_transaction_type {
+	FMC2_ASYNC_MODE_1_SRAM = 0,
+	FMC2_ASYNC_MODE_1_PSRAM,
+	FMC2_ASYNC_MODE_A_SRAM,
+	FMC2_ASYNC_MODE_A_PSRAM,
+	FMC2_ASYNC_MODE_2_NOR,
+	FMC2_ASYNC_MODE_B_NOR,
+	FMC2_ASYNC_MODE_C_NOR,
+	FMC2_ASYNC_MODE_D_NOR,
+	FMC2_SYNC_READ_SYNC_WRITE_PSRAM,
+	FMC2_SYNC_READ_ASYNC_WRITE_PSRAM,
+	FMC2_SYNC_READ_SYNC_WRITE_NOR,
+	FMC2_SYNC_READ_ASYNC_WRITE_NOR
+};
+
+enum stm32_fmc2_ebi_buswidth {
+	FMC2_BUSWIDTH_8 = 8,
+	FMC2_BUSWIDTH_16 = 16
+};
+
+enum stm32_fmc2_ebi_cpsize {
+	FMC2_CPSIZE_0 = 0,
+	FMC2_CPSIZE_128 = 128,
+	FMC2_CPSIZE_256 = 256,
+	FMC2_CPSIZE_512 = 512,
+	FMC2_CPSIZE_1024 = 1024
+};
+
+struct stm32_fmc2_ebi {
+	struct clk clk;
+	fdt_addr_t io_base;
+	u8 bank_assigned;
+};
+
+/*
+ * struct stm32_fmc2_prop - STM32 FMC2 EBI property
+ * @name: the device tree binding name of the property
+ * @bprop: indicate that it is a boolean property
+ * @mprop: indicate that it is a mandatory property
+ * @reg_type: the register that have to be modified
+ * @reg_mask: the bit that have to be modified in the selected register
+ *            in case of it is a boolean property
+ * @reset_val: the default value that have to be set in case the property
+ *             has not been defined in the device tree
+ * @check: this callback ckecks that the property is compliant with the
+ *         transaction type selected
+ * @calculate: this callback is called to calculate for exemple a timing
+ *             set in nanoseconds in the device tree in clock cycles or in
+ *             clock period
+ * @set: this callback applies the values in the registers
+ */
+struct stm32_fmc2_prop {
+	const char *name;
+	bool bprop;
+	bool mprop;
+	int reg_type;
+	u32 reg_mask;
+	u32 reset_val;
+	int (*check)(struct stm32_fmc2_ebi *ebi,
+		     const struct stm32_fmc2_prop *prop, int cs);
+	u32 (*calculate)(struct stm32_fmc2_ebi *ebi, int cs, u32 setup);
+	int (*set)(struct stm32_fmc2_ebi *ebi,
+		   const struct stm32_fmc2_prop *prop,
+		   int cs, u32 setup);
+};
+
+static int stm32_fmc2_ebi_check_mux(struct stm32_fmc2_ebi *ebi,
+				    const struct stm32_fmc2_prop *prop,
+				    int cs)
+{
+	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+
+	if (bcr & FMC2_BCR_MTYP)
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_waitcfg(struct stm32_fmc2_ebi *ebi,
+					const struct stm32_fmc2_prop *prop,
+					int cs)
+{
+	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+	u32 val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+
+	if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_sync_trans(struct stm32_fmc2_ebi *ebi,
+					   const struct stm32_fmc2_prop *prop,
+					   int cs)
+{
+	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+
+	if (bcr & FMC2_BCR_BURSTEN)
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2_ebi *ebi,
+					    const struct stm32_fmc2_prop *prop,
+					    int cs)
+{
+	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+
+	if (!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW))
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_cpsize(struct stm32_fmc2_ebi *ebi,
+				       const struct stm32_fmc2_prop *prop,
+				       int cs)
+{
+	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+	u32 val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+
+	if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_address_hold(struct stm32_fmc2_ebi *ebi,
+					     const struct stm32_fmc2_prop *prop,
+					     int cs)
+{
+	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+	u32 bxtr = prop->reg_type == FMC2_REG_BWTR ?
+		   readl(ebi->io_base + FMC2_BWTR(cs)) :
+		   readl(ebi->io_base + FMC2_BTR(cs));
+	u32 val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
+
+	if ((!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW)) &&
+	    ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN))
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_clk_period(struct stm32_fmc2_ebi *ebi,
+					   const struct stm32_fmc2_prop *prop,
+					   int cs)
+{
+	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+	u32 bcr1 = cs ? readl(ebi->io_base + FMC2_BCR1) : bcr;
+
+	if (bcr & FMC2_BCR_BURSTEN && (!cs || !(bcr1 & FMC2_BCR1_CCLKEN)))
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_cclk(struct stm32_fmc2_ebi *ebi,
+				     const struct stm32_fmc2_prop *prop,
+				     int cs)
+{
+	if (cs)
+		return -EINVAL;
+
+	return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs);
+}
+
+static u32 stm32_fmc2_ebi_ns_to_clock_cycles(struct stm32_fmc2_ebi *ebi,
+					     int cs, u32 setup)
+{
+	unsigned long hclk = clk_get_rate(&ebi->clk);
+	unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
+
+	return DIV_ROUND_UP(setup * 1000, hclkp);
+}
+
+static u32 stm32_fmc2_ebi_ns_to_clk_period(struct stm32_fmc2_ebi *ebi,
+					   int cs, u32 setup)
+{
+	u32 nb_clk_cycles = stm32_fmc2_ebi_ns_to_clock_cycles(ebi, cs, setup);
+	u32 bcr = readl(ebi->io_base + FMC2_BCR1);
+	u32 btr = bcr & FMC2_BCR1_CCLKEN || !cs ?
+		  readl(ebi->io_base + FMC2_BTR1) :
+		  readl(ebi->io_base + FMC2_BTR(cs));
+	u32 clk_period = FIELD_GET(FMC2_BTR_CLKDIV, btr) + 1;
+
+	return DIV_ROUND_UP(nb_clk_cycles, clk_period);
+}
+
+static int stm32_fmc2_ebi_get_reg(int reg_type, int cs, u32 *reg)
+{
+	switch (reg_type) {
+	case FMC2_REG_BCR:
+		*reg = FMC2_BCR(cs);
+		break;
+	case FMC2_REG_BTR:
+		*reg = FMC2_BTR(cs);
+		break;
+	case FMC2_REG_BWTR:
+		*reg = FMC2_BWTR(cs);
+		break;
+	case FMC2_REG_PCSCNTR:
+		*reg = FMC2_PCSCNTR;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_bit_field(struct stm32_fmc2_ebi *ebi,
+					const struct stm32_fmc2_prop *prop,
+					int cs, u32 setup)
+{
+	u32 reg;
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	clrsetbits_le32(ebi->io_base + reg, prop->reg_mask,
+			setup ? prop->reg_mask : 0);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_trans_type(struct stm32_fmc2_ebi *ebi,
+					 const struct stm32_fmc2_prop *prop,
+					 int cs, u32 setup)
+{
+	u32 bcr_mask, bcr = FMC2_BCR_WREN;
+	u32 btr_mask, btr = 0;
+	u32 bwtr_mask, bwtr = 0;
+
+	bwtr_mask = FMC2_BXTR_ACCMOD;
+	btr_mask = FMC2_BXTR_ACCMOD;
+	bcr_mask = FMC2_BCR_MUXEN | FMC2_BCR_MTYP | FMC2_BCR_FACCEN |
+		   FMC2_BCR_WREN | FMC2_BCR_WAITEN | FMC2_BCR_BURSTEN |
+		   FMC2_BCR_EXTMOD | FMC2_BCR_CBURSTRW;
+
+	switch (setup) {
+	case FMC2_ASYNC_MODE_1_SRAM:
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM);
+		/*
+		 * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+		 */
+		break;
+	case FMC2_ASYNC_MODE_1_PSRAM:
+		/*
+		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+		break;
+	case FMC2_ASYNC_MODE_A_SRAM:
+		/*
+		 * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM);
+		bcr |= FMC2_BCR_EXTMOD;
+		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
+		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
+		break;
+	case FMC2_ASYNC_MODE_A_PSRAM:
+		/*
+		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+		bcr |= FMC2_BCR_EXTMOD;
+		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
+		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
+		break;
+	case FMC2_ASYNC_MODE_2_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN;
+		break;
+	case FMC2_ASYNC_MODE_B_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 1
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
+		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B);
+		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B);
+		break;
+	case FMC2_ASYNC_MODE_C_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 2
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
+		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C);
+		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C);
+		break;
+	case FMC2_ASYNC_MODE_D_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 3
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
+		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
+		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
+		break;
+	case FMC2_SYNC_READ_SYNC_WRITE_PSRAM:
+		/*
+		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+		bcr |= FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW;
+		break;
+	case FMC2_SYNC_READ_ASYNC_WRITE_PSRAM:
+		/*
+		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+		bcr |= FMC2_BCR_BURSTEN;
+		break;
+	case FMC2_SYNC_READ_SYNC_WRITE_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW;
+		break;
+	case FMC2_SYNC_READ_ASYNC_WRITE_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN;
+		break;
+	default:
+		/* Type of transaction not supported */
+		return -EINVAL;
+	}
+
+	if (bcr & FMC2_BCR_EXTMOD)
+		clrsetbits_le32(ebi->io_base + FMC2_BWTR(cs),
+				bwtr_mask, bwtr);
+	clrsetbits_le32(ebi->io_base + FMC2_BTR(cs), btr_mask, btr);
+	clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), bcr_mask, bcr);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_buswidth(struct stm32_fmc2_ebi *ebi,
+				       const struct stm32_fmc2_prop *prop,
+				       int cs, u32 setup)
+{
+	u32 val;
+
+	switch (setup) {
+	case FMC2_BUSWIDTH_8:
+		val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_8);
+		break;
+	case FMC2_BUSWIDTH_16:
+		val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_16);
+		break;
+	default:
+		/* Buswidth not supported */
+		return -EINVAL;
+	}
+
+	clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_MWID, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_cpsize(struct stm32_fmc2_ebi *ebi,
+				     const struct stm32_fmc2_prop *prop,
+				     int cs, u32 setup)
+{
+	u32 val;
+
+	switch (setup) {
+	case FMC2_CPSIZE_0:
+		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_0);
+		break;
+	case FMC2_CPSIZE_128:
+		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_128);
+		break;
+	case FMC2_CPSIZE_256:
+		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_256);
+		break;
+	case FMC2_CPSIZE_512:
+		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_512);
+		break;
+	case FMC2_CPSIZE_1024:
+		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_1024);
+		break;
+	default:
+		/* Cpsize not supported */
+		return -EINVAL;
+	}
+
+	clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_CPSIZE, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_bl_setup(struct stm32_fmc2_ebi *ebi,
+				       const struct stm32_fmc2_prop *prop,
+				       int cs, u32 setup)
+{
+	u32 val;
+
+	val = min_t(u32, setup, FMC2_BCR_NBLSET_MAX);
+	val = FIELD_PREP(FMC2_BCR_NBLSET, val);
+	clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_NBLSET, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_address_setup(struct stm32_fmc2_ebi *ebi,
+					    const struct stm32_fmc2_prop *prop,
+					    int cs, u32 setup)
+{
+	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+	u32 bxtr = prop->reg_type == FMC2_REG_BWTR ?
+		   readl(ebi->io_base + FMC2_BWTR(cs)) :
+		   readl(ebi->io_base + FMC2_BTR(cs));
+	u32 reg, val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	if ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN)
+		val = clamp_val(setup, 1, FMC2_BXTR_ADDSET_MAX);
+	else
+		val = min_t(u32, setup, FMC2_BXTR_ADDSET_MAX);
+	val = FIELD_PREP(FMC2_BXTR_ADDSET, val);
+	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_ADDSET, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_address_hold(struct stm32_fmc2_ebi *ebi,
+					   const struct stm32_fmc2_prop *prop,
+					   int cs, u32 setup)
+{
+	u32 val, reg;
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	val = clamp_val(setup, 1, FMC2_BXTR_ADDHLD_MAX);
+	val = FIELD_PREP(FMC2_BXTR_ADDHLD, val);
+	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_ADDHLD, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_data_setup(struct stm32_fmc2_ebi *ebi,
+					 const struct stm32_fmc2_prop *prop,
+					 int cs, u32 setup)
+{
+	u32 val, reg;
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	val = clamp_val(setup, 1, FMC2_BXTR_DATAST_MAX);
+	val = FIELD_PREP(FMC2_BXTR_DATAST, val);
+	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_DATAST, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_bus_turnaround(struct stm32_fmc2_ebi *ebi,
+					     const struct stm32_fmc2_prop *prop,
+					     int cs, u32 setup)
+{
+	u32 val, reg;
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	val = setup ? min_t(u32, setup - 1, FMC2_BXTR_BUSTURN_MAX) : 0;
+	val = FIELD_PREP(FMC2_BXTR_BUSTURN, val);
+	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_BUSTURN, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_data_hold(struct stm32_fmc2_ebi *ebi,
+					const struct stm32_fmc2_prop *prop,
+					int cs, u32 setup)
+{
+	u32 val, reg;
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	if (prop->reg_type == FMC2_REG_BWTR)
+		val = setup ? min_t(u32, setup - 1, FMC2_BXTR_DATAHLD_MAX) : 0;
+	else
+		val = min_t(u32, setup, FMC2_BXTR_DATAHLD_MAX);
+	val = FIELD_PREP(FMC2_BXTR_DATAHLD, val);
+	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_DATAHLD, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_clk_period(struct stm32_fmc2_ebi *ebi,
+					 const struct stm32_fmc2_prop *prop,
+					 int cs, u32 setup)
+{
+	u32 val;
+
+	val = setup ? clamp_val(setup - 1, 1, FMC2_BTR_CLKDIV_MAX) : 1;
+	val = FIELD_PREP(FMC2_BTR_CLKDIV, val);
+	clrsetbits_le32(ebi->io_base + FMC2_BTR(cs), FMC2_BTR_CLKDIV, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_data_latency(struct stm32_fmc2_ebi *ebi,
+					   const struct stm32_fmc2_prop *prop,
+					   int cs, u32 setup)
+{
+	u32 val;
+
+	val = setup > 1 ? min_t(u32, setup - 2, FMC2_BTR_DATLAT_MAX) : 0;
+	val = FIELD_PREP(FMC2_BTR_DATLAT, val);
+	clrsetbits_le32(ebi->io_base + FMC2_BTR(cs), FMC2_BTR_DATLAT, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_max_low_pulse(struct stm32_fmc2_ebi *ebi,
+					    const struct stm32_fmc2_prop *prop,
+					    int cs, u32 setup)
+{
+	u32 old_val, new_val, pcscntr;
+
+	if (setup < 1)
+		return 0;
+
+	pcscntr = readl(ebi->io_base + FMC2_PCSCNTR);
+
+	/* Enable counter for the bank */
+	setbits_le32(ebi->io_base + FMC2_PCSCNTR, FMC2_PCSCNTR_CNTBEN(cs));
+
+	new_val = min_t(u32, setup - 1, FMC2_PCSCNTR_CSCOUNT_MAX);
+	old_val = FIELD_GET(FMC2_PCSCNTR_CSCOUNT, pcscntr);
+	if (old_val && new_val > old_val)
+		/* Keep current counter value */
+		return 0;
+
+	new_val = FIELD_PREP(FMC2_PCSCNTR_CSCOUNT, new_val);
+	clrsetbits_le32(ebi->io_base + FMC2_PCSCNTR,
+			FMC2_PCSCNTR_CSCOUNT, new_val);
+
+	return 0;
+}
+
+static const struct stm32_fmc2_prop stm32_fmc2_child_props[] = {
+	/* st,fmc2-ebi-cs-trans-type must be the first property */
+	{
+		.name = "st,fmc2-ebi-cs-transaction-type",
+		.mprop = true,
+		.set = stm32_fmc2_ebi_set_trans_type,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-cclk-enable",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR1_CCLKEN,
+		.check = stm32_fmc2_ebi_check_cclk,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-mux-enable",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR_MUXEN,
+		.check = stm32_fmc2_ebi_check_mux,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-buswidth",
+		.reset_val = FMC2_BUSWIDTH_16,
+		.set = stm32_fmc2_ebi_set_buswidth,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-waitpol-high",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR_WAITPOL,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-waitcfg-enable",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR_WAITCFG,
+		.check = stm32_fmc2_ebi_check_waitcfg,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-wait-enable",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR_WAITEN,
+		.check = stm32_fmc2_ebi_check_sync_trans,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-asyncwait-enable",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR_ASYNCWAIT,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-cpsize",
+		.check = stm32_fmc2_ebi_check_cpsize,
+		.set = stm32_fmc2_ebi_set_cpsize,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-byte-lane-setup-ns",
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_bl_setup,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-address-setup-ns",
+		.reg_type = FMC2_REG_BTR,
+		.reset_val = FMC2_BXTR_ADDSET_MAX,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_address_setup,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-address-hold-ns",
+		.reg_type = FMC2_REG_BTR,
+		.reset_val = FMC2_BXTR_ADDHLD_MAX,
+		.check = stm32_fmc2_ebi_check_address_hold,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_address_hold,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-data-setup-ns",
+		.reg_type = FMC2_REG_BTR,
+		.reset_val = FMC2_BXTR_DATAST_MAX,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_data_setup,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-bus-turnaround-ns",
+		.reg_type = FMC2_REG_BTR,
+		.reset_val = FMC2_BXTR_BUSTURN_MAX + 1,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_bus_turnaround,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-data-hold-ns",
+		.reg_type = FMC2_REG_BTR,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_data_hold,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-clk-period-ns",
+		.reset_val = FMC2_BTR_CLKDIV_MAX + 1,
+		.check = stm32_fmc2_ebi_check_clk_period,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_clk_period,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-data-latency-ns",
+		.check = stm32_fmc2_ebi_check_sync_trans,
+		.calculate = stm32_fmc2_ebi_ns_to_clk_period,
+		.set = stm32_fmc2_ebi_set_data_latency,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-write-address-setup-ns",
+		.reg_type = FMC2_REG_BWTR,
+		.reset_val = FMC2_BXTR_ADDSET_MAX,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_address_setup,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-write-address-hold-ns",
+		.reg_type = FMC2_REG_BWTR,
+		.reset_val = FMC2_BXTR_ADDHLD_MAX,
+		.check = stm32_fmc2_ebi_check_address_hold,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_address_hold,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-write-data-setup-ns",
+		.reg_type = FMC2_REG_BWTR,
+		.reset_val = FMC2_BXTR_DATAST_MAX,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_data_setup,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-write-bus-turnaround-ns",
+		.reg_type = FMC2_REG_BWTR,
+		.reset_val = FMC2_BXTR_BUSTURN_MAX + 1,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_bus_turnaround,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-write-data-hold-ns",
+		.reg_type = FMC2_REG_BWTR,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_data_hold,
+	},
+	{
+		.name = "st,fmc2-ebi-cs-max-low-pulse-ns",
+		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_max_low_pulse,
+	},
+};
+
+static int stm32_fmc2_ebi_parse_prop(struct stm32_fmc2_ebi *ebi,
+				     ofnode node,
+				     const struct stm32_fmc2_prop *prop,
+				     int cs)
+{
+	u32 setup = 0;
+
+	if (!prop->set) {
+		pr_err("property %s is not well defined\n", prop->name);
+		return -EINVAL;
+	}
+
+	if (prop->check && prop->check(ebi, prop, cs))
+		/* Skip this property */
+		return 0;
+
+	if (prop->bprop) {
+		bool bprop;
+
+		bprop = ofnode_read_bool(node, prop->name);
+		if (prop->mprop && !bprop) {
+			pr_err("mandatory property %s not defined in the device tree\n",
+			       prop->name);
+			return -EINVAL;
+		}
+
+		if (bprop)
+			setup = 1;
+	} else {
+		u32 val;
+		int ret;
+
+		ret = ofnode_read_u32(node, prop->name, &val);
+		if (prop->mprop && ret) {
+			pr_err("mandatory property %s not defined in the device tree\n",
+			       prop->name);
+			return ret;
+		}
+
+		if (ret)
+			setup = prop->reset_val;
+		else if (prop->calculate)
+			setup = prop->calculate(ebi, cs, val);
+		else
+			setup = val;
+	}
+
+	return prop->set(ebi, prop, cs, setup);
+}
+
+static void stm32_fmc2_ebi_enable_bank(struct stm32_fmc2_ebi *ebi, int cs)
+{
+	setbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_MBKEN);
+}
+
+static void stm32_fmc2_ebi_disable_bank(struct stm32_fmc2_ebi *ebi, int cs)
+{
+	clrbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_MBKEN);
+}
+
+/* NWAIT signal can not be connected to EBI controller and NAND controller */
+static bool stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi)
+{
+	unsigned int cs;
+	u32 bcr;
+
+	for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) {
+		if (!(ebi->bank_assigned & BIT(cs)))
+			continue;
+
+		bcr = readl(ebi->io_base + FMC2_BCR(cs));
+		if ((bcr & FMC2_BCR_WAITEN || bcr & FMC2_BCR_ASYNCWAIT) &&
+		    ebi->bank_assigned & BIT(FMC2_NAND))
+			return true;
+	}
+
+	return false;
+}
+
+static void stm32_fmc2_ebi_enable(struct stm32_fmc2_ebi *ebi)
+{
+	setbits_le32(ebi->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
+}
+
+static int stm32_fmc2_ebi_setup_cs(struct stm32_fmc2_ebi *ebi,
+				   ofnode node, u32 cs)
+{
+	unsigned int i;
+	int ret;
+
+	stm32_fmc2_ebi_disable_bank(ebi, cs);
+
+	for (i = 0; i < ARRAY_SIZE(stm32_fmc2_child_props); i++) {
+		const struct stm32_fmc2_prop *p = &stm32_fmc2_child_props[i];
+
+		ret = stm32_fmc2_ebi_parse_prop(ebi, node, p, cs);
+		if (ret) {
+			pr_err("property %s could not be set: %d\n",
+			       p->name, ret);
+			return ret;
+		}
+	}
+
+	stm32_fmc2_ebi_enable_bank(ebi, cs);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_parse_dt(struct udevice *dev,
+				   struct stm32_fmc2_ebi *ebi)
+{
+	ofnode child;
+	bool child_found = false;
+	u32 bank;
+	int ret;
+
+	dev_for_each_subnode(child, dev) {
+		ret = ofnode_read_u32(child, "reg", &bank);
+		if (ret) {
+			pr_err("could not retrieve reg property: %d\n", ret);
+			return ret;
+		}
+
+		if (bank >= FMC2_MAX_BANKS) {
+			pr_err("invalid reg value: %d\n", bank);
+			return -EINVAL;
+		}
+
+		if (ebi->bank_assigned & BIT(bank)) {
+			pr_err("bank already assigned: %d\n", bank);
+			return -EINVAL;
+		}
+
+		if (bank < FMC2_MAX_EBI_CE) {
+			ret = stm32_fmc2_ebi_setup_cs(ebi, child, bank);
+			if (ret) {
+				pr_err("setup chip select %d failed: %d\n",
+				       bank, ret);
+				return ret;
+			}
+		}
+
+		ebi->bank_assigned |= BIT(bank);
+		child_found = true;
+	}
+
+	if (!child_found) {
+		pr_warn("no subnodes found, disable the driver.\n");
+		return -ENODEV;
+	}
+
+	if (stm32_fmc2_ebi_nwait_used_by_ctrls(ebi)) {
+		pr_err("NWAIT signal connected to EBI and NAND controllers\n");
+		return -EINVAL;
+	}
+
+	stm32_fmc2_ebi_enable(ebi);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_probe(struct udevice *dev)
+{
+	struct stm32_fmc2_ebi *ebi = dev_get_priv(dev);
+	struct reset_ctl reset;
+	int ret;
+
+	ebi->io_base = dev_read_addr(dev);
+	if (ebi->io_base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	ret = clk_get_by_index(dev, 0, &ebi->clk);
+	if (ret)
+		return ret;
+
+	ret = clk_enable(&ebi->clk);
+	if (ret)
+		return ret;
+
+	ret = reset_get_by_index(dev, 0, &reset);
+	if (!ret) {
+		reset_assert(&reset);
+		udelay(2);
+		reset_deassert(&reset);
+	}
+
+	return stm32_fmc2_ebi_parse_dt(dev, ebi);
+}
+
+static const struct udevice_id stm32_fmc2_ebi_match[] = {
+	{.compatible = "st,stm32mp1-fmc2-ebi"},
+	{ /* Sentinel */ }
+};
+
+U_BOOT_DRIVER(stm32_fmc2_ebi) = {
+	.name = "stm32_fmc2_ebi",
+	.id = UCLASS_NOP,
+	.of_match = stm32_fmc2_ebi_match,
+	.probe = stm32_fmc2_ebi_probe,
+	.priv_auto_alloc_size = sizeof(struct stm32_fmc2_ebi),
+	.bind = dm_scan_fdt_dev,
+};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 08/11] mtd: rawnand: stm32_fmc2: get resources from parent node
  2020-07-31  7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
                   ` (6 preceding siblings ...)
  2020-07-31  7:53 ` [PATCH 07/11] memory: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver Christophe Kerello
@ 2020-07-31  7:53 ` Christophe Kerello
  2020-08-13  7:33   ` Patrice CHOTARD
  2020-07-31  7:53 ` [PATCH 09/11] board: stm32mp1: update fdt fixup partitions table Christophe Kerello
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31  7:53 UTC (permalink / raw)
  To: u-boot

FMC2 EBI support has been added. Common resources (registers base
address and clock) can now be shared between the 2 drivers using
"st,stm32mp1-fmc2-nfc" compatible string. It means that the
common resources should now be found in the parent device when EBI
node is available.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---

 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 87 +++++++++++++++++++++++-----------
 1 file changed, 59 insertions(+), 28 deletions(-)

diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 1e4d757..47fe610 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -158,10 +158,10 @@ struct stm32_fmc2_nfc {
 	struct nand_hw_control base;
 	struct stm32_fmc2_nand nand;
 	struct nand_ecclayout ecclayout;
-	void __iomem *io_base;
-	void __iomem *data_base[FMC2_MAX_CE];
-	void __iomem *cmd_base[FMC2_MAX_CE];
-	void __iomem *addr_base[FMC2_MAX_CE];
+	fdt_addr_t io_base;
+	fdt_addr_t data_base[FMC2_MAX_CE];
+	fdt_addr_t cmd_base[FMC2_MAX_CE];
+	fdt_addr_t addr_base[FMC2_MAX_CE];
 	struct clk clk;
 
 	u8 cs_assigned;
@@ -241,8 +241,8 @@ static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
 		return;
 
 	nfc->cs_sel = nand->cs_used[chipnr];
-	chip->IO_ADDR_R = nfc->data_base[nfc->cs_sel];
-	chip->IO_ADDR_W = nfc->data_base[nfc->cs_sel];
+	chip->IO_ADDR_R = (void __iomem *)nfc->data_base[nfc->cs_sel];
+	chip->IO_ADDR_W = (void __iomem *)nfc->data_base[nfc->cs_sel];
 
 	stm32_fmc2_nfc_setup(chip);
 	stm32_fmc2_nfc_timings_init(chip);
@@ -548,7 +548,7 @@ static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
 	return max_bitflips;
 }
 
-static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
+static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc, bool has_parent)
 {
 	u32 pcr = readl(nfc->io_base + FMC2_PCR);
 
@@ -581,7 +581,8 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
 	pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
 
 	/* Enable FMC2 controller */
-	setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
+	if (!has_parent)
+		setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
 
 	writel(pcr, nfc->io_base + FMC2_PCR);
 	writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
@@ -854,6 +855,30 @@ static int stm32_fmc2_nfc_parse_dt(struct udevice *dev,
 	return 0;
 }
 
+static struct udevice *stm32_fmc2_nfc_get_cdev(struct udevice *dev)
+{
+	struct udevice *pdev = dev_get_parent(dev);
+	struct udevice *cdev = NULL;
+	bool ebi_found = false;
+
+	if (pdev && ofnode_device_is_compatible(dev_ofnode(pdev),
+						"st,stm32mp1-fmc2-ebi"))
+		ebi_found = true;
+
+	if (ofnode_device_is_compatible(dev_ofnode(dev),
+					"st,stm32mp1-fmc2-nfc")) {
+		if (ebi_found)
+			cdev = pdev;
+
+		return cdev;
+	}
+
+	if (!ebi_found)
+		cdev = dev;
+
+	return cdev;
+}
+
 static int stm32_fmc2_nfc_probe(struct udevice *dev)
 {
 	struct stm32_fmc2_nfc *nfc = dev_get_priv(dev);
@@ -861,58 +886,63 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
 	struct nand_chip *chip = &nand->chip;
 	struct mtd_info *mtd = &chip->mtd;
 	struct nand_ecclayout *ecclayout;
-	struct resource resource;
+	struct udevice *cdev;
 	struct reset_ctl reset;
 	int oob_index, chip_cs, mem_region, ret;
 	unsigned int i;
+	int start_region = 0;
+	fdt_addr_t addr;
 
 	spin_lock_init(&nfc->controller.lock);
 	init_waitqueue_head(&nfc->controller.wq);
 
+	cdev = stm32_fmc2_nfc_get_cdev(dev);
+	if (!cdev)
+		return -EINVAL;
+
 	ret = stm32_fmc2_nfc_parse_dt(dev, nfc);
 	if (ret)
 		return ret;
 
-	/* Get resources */
-	ret = dev_read_resource(dev, 0, &resource);
-	if (ret) {
-		pr_err("Resource io_base not found");
-		return ret;
-	}
-	nfc->io_base = (void __iomem *)resource.start;
+	nfc->io_base = dev_read_addr(cdev);
+	if (nfc->io_base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	if (dev == cdev)
+		start_region = 1;
 
-	for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
+	for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE;
 	     chip_cs++, mem_region += 3) {
 		if (!(nfc->cs_assigned & BIT(chip_cs)))
 			continue;
 
-		ret = dev_read_resource(dev, mem_region, &resource);
-		if (ret) {
+		addr = dev_read_addr_index(dev, mem_region);
+		if (addr == FDT_ADDR_T_NONE) {
 			pr_err("Resource data_base not found for cs%d",
 			       chip_cs);
 			return ret;
 		}
-		nfc->data_base[chip_cs] = (void __iomem *)resource.start;
+		nfc->data_base[chip_cs] = addr;
 
-		ret = dev_read_resource(dev, mem_region + 1, &resource);
-		if (ret) {
+		addr = dev_read_addr_index(dev, mem_region + 1);
+		if (addr == FDT_ADDR_T_NONE) {
 			pr_err("Resource cmd_base not found for cs%d",
 			       chip_cs);
 			return ret;
 		}
-		nfc->cmd_base[chip_cs] = (void __iomem *)resource.start;
+		nfc->cmd_base[chip_cs] = addr;
 
-		ret = dev_read_resource(dev, mem_region + 2, &resource);
-		if (ret) {
+		addr = dev_read_addr_index(dev, mem_region + 2);
+		if (addr == FDT_ADDR_T_NONE) {
 			pr_err("Resource addr_base not found for cs%d",
 			       chip_cs);
 			return ret;
 		}
-		nfc->addr_base[chip_cs] = (void __iomem *)resource.start;
+		nfc->addr_base[chip_cs] = addr;
 	}
 
 	/* Enable the clock */
-	ret = clk_get_by_index(dev, 0, &nfc->clk);
+	ret = clk_get_by_index(cdev, 0, &nfc->clk);
 	if (ret)
 		return ret;
 
@@ -928,7 +958,7 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
 		reset_deassert(&reset);
 	}
 
-	stm32_fmc2_nfc_init(nfc);
+	stm32_fmc2_nfc_init(nfc, dev != cdev);
 
 	chip->controller = &nfc->base;
 	chip->select_chip = stm32_fmc2_nfc_select_chip;
@@ -994,6 +1024,7 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
 
 static const struct udevice_id stm32_fmc2_nfc_match[] = {
 	{ .compatible = "st,stm32mp15-fmc2" },
+	{ .compatible = "st,stm32mp1-fmc2-nfc" },
 	{ /* Sentinel */ }
 };
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 09/11] board: stm32mp1: update fdt fixup partitions table
  2020-07-31  7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
                   ` (7 preceding siblings ...)
  2020-07-31  7:53 ` [PATCH 08/11] mtd: rawnand: stm32_fmc2: get resources from parent node Christophe Kerello
@ 2020-07-31  7:53 ` Christophe Kerello
  2020-08-13  7:34   ` Patrice CHOTARD
  2020-07-31  7:53 ` [PATCH 10/11] configs: stm32mp: add CONFIG_STM32_FMC2_EBI Christophe Kerello
  2020-07-31  7:53 ` [PATCH 11/11] ARM: dts: stm32: add FMC2 EBI support for stm32mp157c Christophe Kerello
  10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31  7:53 UTC (permalink / raw)
  To: u-boot

This patch adds "st,stm32mp1-fmc2-nfc" compatible string in the
fdt fixup partitions table.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---

 board/st/stm32mp1/stm32mp1.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index 1d274c3..f2f6c99 100644
--- a/board/st/stm32mp1/stm32mp1.c
+++ b/board/st/stm32mp1/stm32mp1.c
@@ -851,6 +851,7 @@ int ft_board_setup(void *blob, struct bd_info *bd)
 		{ "st,stm32f469-qspi",		MTD_DEV_TYPE_NOR,  },
 		{ "st,stm32f469-qspi",		MTD_DEV_TYPE_SPINAND},
 		{ "st,stm32mp15-fmc2",		MTD_DEV_TYPE_NAND, },
+		{ "st,stm32mp1-fmc2-nfc",	MTD_DEV_TYPE_NAND, },
 	};
 	fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
 #endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 10/11] configs: stm32mp: add CONFIG_STM32_FMC2_EBI
  2020-07-31  7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
                   ` (8 preceding siblings ...)
  2020-07-31  7:53 ` [PATCH 09/11] board: stm32mp1: update fdt fixup partitions table Christophe Kerello
@ 2020-07-31  7:53 ` Christophe Kerello
  2020-08-13  7:35   ` Patrice CHOTARD
  2020-07-31  7:53 ` [PATCH 11/11] ARM: dts: stm32: add FMC2 EBI support for stm32mp157c Christophe Kerello
  10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31  7:53 UTC (permalink / raw)
  To: u-boot

This patch enables the support of FMC2 EBI.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---

 configs/stm32mp15_basic_defconfig   | 1 +
 configs/stm32mp15_trusted_defconfig | 1 +
 2 files changed, 2 insertions(+)

diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig
index 5c500a1..2094183 100644
--- a/configs/stm32mp15_basic_defconfig
+++ b/configs/stm32mp15_basic_defconfig
@@ -88,6 +88,7 @@ CONFIG_LED=y
 CONFIG_LED_GPIO=y
 CONFIG_DM_MAILBOX=y
 CONFIG_STM32_IPCC=y
+CONFIG_STM32_FMC2_EBI=y
 CONFIG_DM_MMC=y
 CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_STM32_SDMMC2=y
diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig
index 98680cb..8d59d84 100644
--- a/configs/stm32mp15_trusted_defconfig
+++ b/configs/stm32mp15_trusted_defconfig
@@ -68,6 +68,7 @@ CONFIG_LED=y
 CONFIG_LED_GPIO=y
 CONFIG_DM_MAILBOX=y
 CONFIG_STM32_IPCC=y
+CONFIG_STM32_FMC2_EBI=y
 CONFIG_DM_MMC=y
 CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_STM32_SDMMC2=y
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 11/11] ARM: dts: stm32: add FMC2 EBI support for stm32mp157c
  2020-07-31  7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
                   ` (9 preceding siblings ...)
  2020-07-31  7:53 ` [PATCH 10/11] configs: stm32mp: add CONFIG_STM32_FMC2_EBI Christophe Kerello
@ 2020-07-31  7:53 ` Christophe Kerello
  2020-08-13  7:37   ` Patrice CHOTARD
  10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31  7:53 UTC (permalink / raw)
  To: u-boot

This patch adds FMC2 External Bus Interface support on stm32mp157c.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---

 arch/arm/dts/stm32mp151.dtsi     | 43 +++++++++++++++++++++++++++-------------
 arch/arm/dts/stm32mp157c-ev1.dts | 16 ++++++++-------
 2 files changed, 38 insertions(+), 21 deletions(-)

diff --git a/arch/arm/dts/stm32mp151.dtsi b/arch/arm/dts/stm32mp151.dtsi
index 0d97f56..39d9e54 100644
--- a/arch/arm/dts/stm32mp151.dtsi
+++ b/arch/arm/dts/stm32mp151.dtsi
@@ -1328,23 +1328,38 @@
 			dma-requests = <48>;
 		};
 
-		fmc: nand-controller at 58002000 {
-			compatible = "st,stm32mp15-fmc2";
-			reg = <0x58002000 0x1000>,
-			      <0x80000000 0x1000>,
-			      <0x88010000 0x1000>,
-			      <0x88020000 0x1000>,
-			      <0x81000000 0x1000>,
-			      <0x89010000 0x1000>,
-			      <0x89020000 0x1000>;
-			interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
-			dmas = <&mdma1 20 0x10 0x12000a02 0x0 0x0>,
-			       <&mdma1 20 0x10 0x12000a08 0x0 0x0>,
-			       <&mdma1 21 0x10 0x12000a0a 0x0 0x0>;
-			dma-names = "tx", "rx", "ecc";
+		fmc: memory-controller at 58002000 {
+			#address-cells = <2>;
+			#size-cells = <1>;
+			compatible = "st,stm32mp1-fmc2-ebi";
+			reg = <0x58002000 0x1000>;
 			clocks = <&rcc FMC_K>;
 			resets = <&rcc FMC_R>;
 			status = "disabled";
+
+			ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */
+				 <1 0 0x64000000 0x04000000>, /* EBI CS 2 */
+				 <2 0 0x68000000 0x04000000>, /* EBI CS 3 */
+				 <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */
+				 <4 0 0x80000000 0x10000000>; /* NAND */
+
+			nand-controller at 4,0 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32mp1-fmc2-nfc";
+				reg = <4 0x00000000 0x1000>,
+				      <4 0x08010000 0x1000>,
+				      <4 0x08020000 0x1000>,
+				      <4 0x01000000 0x1000>,
+				      <4 0x09010000 0x1000>,
+				      <4 0x09020000 0x1000>;
+				interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
+				       <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
+				       <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
+				dma-names = "tx", "rx", "ecc";
+				status = "disabled";
+			};
 		};
 
 		qspi: spi at 58003000 {
diff --git a/arch/arm/dts/stm32mp157c-ev1.dts b/arch/arm/dts/stm32mp157c-ev1.dts
index b190565..46f81ce 100644
--- a/arch/arm/dts/stm32mp157c-ev1.dts
+++ b/arch/arm/dts/stm32mp157c-ev1.dts
@@ -157,14 +157,16 @@
 	pinctrl-0 = <&fmc_pins_a>;
 	pinctrl-1 = <&fmc_sleep_pins_a>;
 	status = "okay";
-	#address-cells = <1>;
-	#size-cells = <0>;
 
-	nand at 0 {
-		reg = <0>;
-		nand-on-flash-bbt;
-		#address-cells = <1>;
-		#size-cells = <1>;
+	nand-controller at 4,0 {
+		status = "okay";
+
+		nand at 0 {
+			reg = <0>;
+			nand-on-flash-bbt;
+			#address-cells = <1>;
+			#size-cells = <1>;
+		};
 	};
 };
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 01/11] mtd: rawnand: stm32_fmc2: fix a buffer overflow
  2020-07-31  7:53 ` [PATCH 01/11] mtd: rawnand: stm32_fmc2: fix a buffer overflow Christophe Kerello
@ 2020-08-13  7:27   ` Patrice CHOTARD
  2020-08-13  9:56     ` Patrice CHOTARD
  0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  7:27 UTC (permalink / raw)
  To: u-boot

Hi Christpohe

On 7/31/20 9:53 AM, Christophe Kerello wrote:
> The chip select defined in the device tree could only be 0 or 1.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index 3306bd8..2929acf 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -846,7 +846,7 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
>  	}
>  
>  	for (i = 0; i < nand->ncs; i++) {
> -		if (cs[i] > FMC2_MAX_CE) {
> +		if (cs[i] >= FMC2_MAX_CE) {
>  			pr_err("Invalid reg value: %d\n",
>  			       nand->cs_used[i]);
>  			return -EINVAL;

Reviewed-by: Patrice Chotard <patrice.chotard@st.com>

Thanks

Patrice

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 02/11] mtd: rawnand: stm32_fmc2: remove useless inline comments
  2020-07-31  7:53 ` [PATCH 02/11] mtd: rawnand: stm32_fmc2: remove useless inline comments Christophe Kerello
@ 2020-08-13  7:28   ` Patrice CHOTARD
  2020-08-13  9:56     ` Patrice CHOTARD
  0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  7:28 UTC (permalink / raw)
  To: u-boot

Hi Christophe

On 7/31/20 9:53 AM, Christophe Kerello wrote:
> Remove inline comments that are useless since function label are
> self explanatory.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 25 -------------------------
>  1 file changed, 25 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index 2929acf..f43e3ec 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -179,7 +179,6 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_hw_control *base)
>  	return container_of(base, struct stm32_fmc2_nfc, base);
>  }
>  
> -/* Timings configuration */
>  static void stm32_fmc2_timings_init(struct nand_chip *chip)
>  {
>  	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> @@ -211,7 +210,6 @@ static void stm32_fmc2_timings_init(struct nand_chip *chip)
>  	writel(patt, fmc2->io_base + FMC2_PATT);
>  }
>  
> -/* Controller configuration */
>  static void stm32_fmc2_setup(struct nand_chip *chip)
>  {
>  	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> @@ -239,7 +237,6 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
>  	writel(pcr, fmc2->io_base + FMC2_PCR);
>  }
>  
> -/* Select target */
>  static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
> @@ -256,14 +253,10 @@ static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
>  	chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel];
>  	chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel];
>  
> -	/* FMC2 setup routine */
>  	stm32_fmc2_setup(chip);
> -
> -	/* Apply timings */
>  	stm32_fmc2_timings_init(chip);
>  }
>  
> -/* Set bus width to 16-bit or 8-bit */
>  static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
>  {
>  	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> @@ -274,7 +267,6 @@ static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
>  	writel(pcr, fmc2->io_base + FMC2_PCR);
>  }
>  
> -/* Enable/disable ECC */
>  static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
>  {
>  	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> @@ -285,13 +277,11 @@ static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
>  	writel(pcr, fmc2->io_base + FMC2_PCR);
>  }
>  
> -/* Clear irq sources in case of bch is used */
>  static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
>  {
>  	writel(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
>  }
>  
> -/* Send command and address cycles */
>  static void stm32_fmc2_cmd_ctrl(struct mtd_info *mtd, int cmd,
>  				unsigned int ctrl)
>  {
> @@ -361,7 +351,6 @@ static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
>  	ecc[1] = heccr >> 8;
>  	ecc[2] = heccr >> 16;
>  
> -	/* Disable ecc */
>  	stm32_fmc2_set_ecc(fmc2, false);
>  
>  	return 0;
> @@ -466,13 +455,11 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
>  		ecc[12] = bchpbr;
>  	}
>  
> -	/* Disable ecc */
>  	stm32_fmc2_set_ecc(fmc2, false);
>  
>  	return 0;
>  }
>  
> -/* BCH algorithm correction */
>  static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
>  				  u8 *read_ecc, u8 *calc_ecc)
>  {
> @@ -497,7 +484,6 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
>  	bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3);
>  	bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4);
>  
> -	/* Disable ECC */
>  	stm32_fmc2_set_ecc(fmc2, false);
>  
>  	/* No errors found */
> @@ -579,7 +565,6 @@ static int stm32_fmc2_read_page(struct mtd_info *mtd,
>  	return max_bitflips;
>  }
>  
> -/* Controller initialization */
>  static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
>  {
>  	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> @@ -622,7 +607,6 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
>  	writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
>  }
>  
> -/* Controller timings */
>  static void stm32_fmc2_calc_timings(struct nand_chip *chip,
>  				    const struct nand_sdr_timings *sdrt)
>  {
> @@ -768,13 +752,11 @@ static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr,
>  
>  	stm32_fmc2_calc_timings(chip, sdrt);
>  
> -	/* Apply timings */
>  	stm32_fmc2_timings_init(chip);
>  
>  	return 0;
>  }
>  
> -/* NAND callbacks setup */
>  static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
>  {
>  	chip->ecc.hwctl = stm32_fmc2_hwctl;
> @@ -803,7 +785,6 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
>  		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
>  }
>  
> -/* FMC2 caps */
>  static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
>  {
>  	/* Hamming */
> @@ -822,7 +803,6 @@ NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
>  		     FMC2_ECC_STEP_SIZE,
>  		     FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
>  
> -/* FMC2 probe */
>  static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
>  				  ofnode node)
>  {
> @@ -969,7 +949,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  		reset_deassert(&reset);
>  	}
>  
> -	/* FMC2 init routine */
>  	stm32_fmc2_init(fmc2);
>  
>  	chip->controller = &fmc2->base;
> @@ -985,7 +964,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  	chip->ecc.size = FMC2_ECC_STEP_SIZE;
>  	chip->ecc.strength = FMC2_ECC_BCH8;
>  
> -	/* Scan to find existence of the device */
>  	ret = nand_scan_ident(mtd, nand->ncs, NULL);
>  	if (ret)
>  		return ret;
> @@ -1012,7 +990,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  	if (chip->bbt_options & NAND_BBT_USE_FLASH)
>  		chip->bbt_options |= NAND_BBT_NO_OOB;
>  
> -	/* NAND callbacks setup */
>  	stm32_fmc2_nand_callbacks_setup(chip);
>  
>  	/* Define ECC layout */
> @@ -1026,11 +1003,9 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  	ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
>  	chip->ecc.layout = ecclayout;
>  
> -	/* Configure bus width to 16-bit */
>  	if (chip->options & NAND_BUSWIDTH_16)
>  		stm32_fmc2_set_buswidth_16(fmc2, true);
>  
> -	/* Scan the device to fill MTD data-structures */
>  	ret = nand_scan_tail(mtd);
>  	if (ret)
>  		return ret;

Reviewed-by: Patrice Chotard <patrice.chotard@st.com>

Thanks

Patrice

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 03/11] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_5S for timeouts
  2020-07-31  7:53 ` [PATCH 03/11] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_5S for timeouts Christophe Kerello
@ 2020-08-13  7:29   ` Patrice CHOTARD
  2020-08-13  9:57     ` Patrice CHOTARD
  0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  7:29 UTC (permalink / raw)
  To: u-boot

Hi Christophe

On 7/31/20 9:53 AM, Christophe Kerello wrote:
> FMC2_TIMEOUT_5S will be used each time that we need to wait.
> It was seen, during stress tests in an overloaded system,
> that we could be close to 1 second, even if we never met this
> value. To be safe, FMC2_TIMEOUT_MS is set to 5 seconds.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index f43e3ec..2e947a3 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -131,6 +131,8 @@
>  
>  #define FMC2_NSEC_PER_SEC		1000000000L
>  
> +#define FMC2_TIMEOUT_5S			5000000
> +
>  enum stm32_fmc2_ecc {
>  	FMC2_ECC_HAM = 1,
>  	FMC2_ECC_BCH4 = 4,
> @@ -339,7 +341,7 @@ static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
>  	int ret;
>  
>  	ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr,
> -				 sr & FMC2_SR_NWRF, 10000);
> +				 sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
>  	if (ret < 0) {
>  		pr_err("Ham timeout\n");
>  		return ret;
> @@ -424,7 +426,7 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
>  
>  	/* Wait until the BCH code is ready */
>  	ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
> -				 bchisr & FMC2_BCHISR_EPBRF, 10000);
> +				 bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
>  	if (ret < 0) {
>  		pr_err("Bch timeout\n");
>  		return ret;
> @@ -472,7 +474,7 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
>  
>  	/* Wait until the decoding error is ready */
>  	ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
> -				 bchisr & FMC2_BCHISR_DERF, 10000);
> +				 bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
>  	if (ret < 0) {
>  		pr_err("Bch timeout\n");
>  		return ret;

Reviewed-by: Patrice Chotard <patrice.chotard@st.com>

Thanks

Patrice

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 04/11] mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2 where relevant
  2020-07-31  7:53 ` [PATCH 04/11] mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2 where relevant Christophe Kerello
@ 2020-08-13  7:29   ` Patrice CHOTARD
  2020-08-13  9:57   ` Patrice CHOTARD
  1 sibling, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  7:29 UTC (permalink / raw)
  To: u-boot

Hi CHristophe

On 7/31/20 9:53 AM, Christophe Kerello wrote:
> This patch renames functions and local variables.
> This cleanup is done to get all functions starting by stm32_fmc2_nfc
> in the FMC2 raw NAND driver when all functions will start by
> stm32_fmc2_ebi in the FMC2 EBI driver.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 263 ++++++++++++++++-----------------
>  1 file changed, 131 insertions(+), 132 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index 2e947a3..9718bae 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -181,12 +181,12 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_hw_control *base)
>  	return container_of(base, struct stm32_fmc2_nfc, base);
>  }
>  
> -static void stm32_fmc2_timings_init(struct nand_chip *chip)
> +static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
>  {
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>  	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
>  	struct stm32_fmc2_timings *timings = &nand->timings;
> -	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> +	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>  	u32 pmem, patt;
>  
>  	/* Set tclr/tar timings */
> @@ -207,15 +207,15 @@ static void stm32_fmc2_timings_init(struct nand_chip *chip)
>  	patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
>  	patt |= FMC2_PATT_ATTHIZ(timings->thiz);
>  
> -	writel(pcr, fmc2->io_base + FMC2_PCR);
> -	writel(pmem, fmc2->io_base + FMC2_PMEM);
> -	writel(patt, fmc2->io_base + FMC2_PATT);
> +	writel(pcr, nfc->io_base + FMC2_PCR);
> +	writel(pmem, nfc->io_base + FMC2_PMEM);
> +	writel(patt, nfc->io_base + FMC2_PATT);
>  }
>  
> -static void stm32_fmc2_setup(struct nand_chip *chip)
> +static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
>  {
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> -	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> +	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>  
>  	/* Configure ECC algorithm (default configuration is Hamming) */
>  	pcr &= ~FMC2_PCR_ECCALG;
> @@ -236,95 +236,96 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
>  	pcr &= ~FMC2_PCR_ECCSS_MASK;
>  	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
>  
> -	writel(pcr, fmc2->io_base + FMC2_PCR);
> +	writel(pcr, nfc->io_base + FMC2_PCR);
>  }
>  
> -static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
> +static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>  	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
>  
>  	if (chipnr < 0 || chipnr >= nand->ncs)
>  		return;
>  
> -	if (nand->cs_used[chipnr] == fmc2->cs_sel)
> +	if (nand->cs_used[chipnr] == nfc->cs_sel)
>  		return;
>  
> -	fmc2->cs_sel = nand->cs_used[chipnr];
> -	chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel];
> -	chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel];
> +	nfc->cs_sel = nand->cs_used[chipnr];
> +	chip->IO_ADDR_R = nfc->data_base[nfc->cs_sel];
> +	chip->IO_ADDR_W = nfc->data_base[nfc->cs_sel];
>  
> -	stm32_fmc2_setup(chip);
> -	stm32_fmc2_timings_init(chip);
> +	stm32_fmc2_nfc_setup(chip);
> +	stm32_fmc2_nfc_timings_init(chip);
>  }
>  
> -static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
> +static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
> +					   bool set)
>  {
> -	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> +	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>  
>  	pcr &= ~FMC2_PCR_PWID_MASK;
>  	if (set)
>  		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
> -	writel(pcr, fmc2->io_base + FMC2_PCR);
> +	writel(pcr, nfc->io_base + FMC2_PCR);
>  }
>  
> -static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
> +static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
>  {
> -	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> +	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>  
>  	pcr &= ~FMC2_PCR_ECCEN;
>  	if (enable)
>  		pcr |= FMC2_PCR_ECCEN;
> -	writel(pcr, fmc2->io_base + FMC2_PCR);
> +	writel(pcr, nfc->io_base + FMC2_PCR);
>  }
>  
> -static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
> +static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
>  {
> -	writel(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
> +	writel(FMC2_BCHICR_CLEAR_IRQ, nfc->io_base + FMC2_BCHICR);
>  }
>  
> -static void stm32_fmc2_cmd_ctrl(struct mtd_info *mtd, int cmd,
> -				unsigned int ctrl)
> +static void stm32_fmc2_nfc_cmd_ctrl(struct mtd_info *mtd, int cmd,
> +				    unsigned int ctrl)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>  
>  	if (cmd == NAND_CMD_NONE)
>  		return;
>  
>  	if (ctrl & NAND_CLE) {
> -		writeb(cmd, fmc2->cmd_base[fmc2->cs_sel]);
> +		writeb(cmd, nfc->cmd_base[nfc->cs_sel]);
>  		return;
>  	}
>  
> -	writeb(cmd, fmc2->addr_base[fmc2->cs_sel]);
> +	writeb(cmd, nfc->addr_base[nfc->cs_sel]);
>  }
>  
>  /*
>   * Enable ECC logic and reset syndrome/parity bits previously calculated
>   * Syndrome/parity bits is cleared by setting the ECCEN bit to 0
>   */
> -static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
> +static void stm32_fmc2_nfc_hwctl(struct mtd_info *mtd, int mode)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>  
> -	stm32_fmc2_set_ecc(fmc2, false);
> +	stm32_fmc2_nfc_set_ecc(nfc, false);
>  
>  	if (chip->ecc.strength != FMC2_ECC_HAM) {
> -		u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> +		u32 pcr = readl(nfc->io_base + FMC2_PCR);
>  
>  		if (mode == NAND_ECC_WRITE)
>  			pcr |= FMC2_PCR_WEN;
>  		else
>  			pcr &= ~FMC2_PCR_WEN;
> -		writel(pcr, fmc2->io_base + FMC2_PCR);
> +		writel(pcr, nfc->io_base + FMC2_PCR);
>  
> -		stm32_fmc2_clear_bch_irq(fmc2);
> +		stm32_fmc2_nfc_clear_bch_irq(nfc);
>  	}
>  
> -	stm32_fmc2_set_ecc(fmc2, true);
> +	stm32_fmc2_nfc_set_ecc(nfc, true);
>  }
>  
>  /*
> @@ -332,34 +333,34 @@ static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
>   * ECC is 3 bytes for 512 bytes of data (supports error correction up to
>   * max of 1-bit)
>   */
> -static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
> -				    u8 *ecc)
> +static int stm32_fmc2_nfc_ham_calculate(struct mtd_info *mtd, const u8 *data,
> +					u8 *ecc)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>  	u32 heccr, sr;
>  	int ret;
>  
> -	ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr,
> +	ret = readl_poll_timeout(nfc->io_base + FMC2_SR, sr,
>  				 sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
>  	if (ret < 0) {
>  		pr_err("Ham timeout\n");
>  		return ret;
>  	}
>  
> -	heccr = readl(fmc2->io_base + FMC2_HECCR);
> +	heccr = readl(nfc->io_base + FMC2_HECCR);
>  
>  	ecc[0] = heccr;
>  	ecc[1] = heccr >> 8;
>  	ecc[2] = heccr >> 16;
>  
> -	stm32_fmc2_set_ecc(fmc2, false);
> +	stm32_fmc2_nfc_set_ecc(nfc, false);
>  
>  	return 0;
>  }
>  
> -static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
> -				  u8 *read_ecc, u8 *calc_ecc)
> +static int stm32_fmc2_nfc_ham_correct(struct mtd_info *mtd, u8 *dat,
> +				      u8 *read_ecc, u8 *calc_ecc)
>  {
>  	u8 bit_position = 0, b0, b1, b2;
>  	u32 byte_addr = 0, b;
> @@ -416,16 +417,16 @@ static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
>   * max of 4-bit/8-bit)
>   */
>  
> -static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
> -				    u8 *ecc)
> +static int stm32_fmc2_nfc_bch_calculate(struct mtd_info *mtd, const u8 *data,
> +					u8 *ecc)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>  	u32 bchpbr, bchisr;
>  	int ret;
>  
>  	/* Wait until the BCH code is ready */
> -	ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
> +	ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
>  				 bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
>  	if (ret < 0) {
>  		pr_err("Bch timeout\n");
> @@ -433,13 +434,13 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
>  	}
>  
>  	/* Read parity bits */
> -	bchpbr = readl(fmc2->io_base + FMC2_BCHPBR1);
> +	bchpbr = readl(nfc->io_base + FMC2_BCHPBR1);
>  	ecc[0] = bchpbr;
>  	ecc[1] = bchpbr >> 8;
>  	ecc[2] = bchpbr >> 16;
>  	ecc[3] = bchpbr >> 24;
>  
> -	bchpbr = readl(fmc2->io_base + FMC2_BCHPBR2);
> +	bchpbr = readl(nfc->io_base + FMC2_BCHPBR2);
>  	ecc[4] = bchpbr;
>  	ecc[5] = bchpbr >> 8;
>  	ecc[6] = bchpbr >> 16;
> @@ -447,46 +448,46 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
>  	if (chip->ecc.strength == FMC2_ECC_BCH8) {
>  		ecc[7] = bchpbr >> 24;
>  
> -		bchpbr = readl(fmc2->io_base + FMC2_BCHPBR3);
> +		bchpbr = readl(nfc->io_base + FMC2_BCHPBR3);
>  		ecc[8] = bchpbr;
>  		ecc[9] = bchpbr >> 8;
>  		ecc[10] = bchpbr >> 16;
>  		ecc[11] = bchpbr >> 24;
>  
> -		bchpbr = readl(fmc2->io_base + FMC2_BCHPBR4);
> +		bchpbr = readl(nfc->io_base + FMC2_BCHPBR4);
>  		ecc[12] = bchpbr;
>  	}
>  
> -	stm32_fmc2_set_ecc(fmc2, false);
> +	stm32_fmc2_nfc_set_ecc(nfc, false);
>  
>  	return 0;
>  }
>  
> -static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
> -				  u8 *read_ecc, u8 *calc_ecc)
> +static int stm32_fmc2_nfc_bch_correct(struct mtd_info *mtd, u8 *dat,
> +				      u8 *read_ecc, u8 *calc_ecc)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>  	u32 bchdsr0, bchdsr1, bchdsr2, bchdsr3, bchdsr4, bchisr;
>  	u16 pos[8];
>  	int i, ret, den, eccsize = chip->ecc.size;
>  	unsigned int nb_errs = 0;
>  
>  	/* Wait until the decoding error is ready */
> -	ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
> +	ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
>  				 bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
>  	if (ret < 0) {
>  		pr_err("Bch timeout\n");
>  		return ret;
>  	}
>  
> -	bchdsr0 = readl(fmc2->io_base + FMC2_BCHDSR0);
> -	bchdsr1 = readl(fmc2->io_base + FMC2_BCHDSR1);
> -	bchdsr2 = readl(fmc2->io_base + FMC2_BCHDSR2);
> -	bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3);
> -	bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4);
> +	bchdsr0 = readl(nfc->io_base + FMC2_BCHDSR0);
> +	bchdsr1 = readl(nfc->io_base + FMC2_BCHDSR1);
> +	bchdsr2 = readl(nfc->io_base + FMC2_BCHDSR2);
> +	bchdsr3 = readl(nfc->io_base + FMC2_BCHDSR3);
> +	bchdsr4 = readl(nfc->io_base + FMC2_BCHDSR4);
>  
> -	stm32_fmc2_set_ecc(fmc2, false);
> +	stm32_fmc2_nfc_set_ecc(nfc, false);
>  
>  	/* No errors found */
>  	if (likely(!(bchdsr0 & FMC2_BCHDSR0_DEF)))
> @@ -516,9 +517,9 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
>  	return nb_errs;
>  }
>  
> -static int stm32_fmc2_read_page(struct mtd_info *mtd,
> -				struct nand_chip *chip, u8 *buf,
> -				int oob_required, int page)
> +static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
> +				    struct nand_chip *chip, u8 *buf,
> +				    int oob_required, int page)
>  {
>  	int i, s, stat, eccsize = chip->ecc.size;
>  	int eccbytes = chip->ecc.bytes;
> @@ -567,13 +568,13 @@ static int stm32_fmc2_read_page(struct mtd_info *mtd,
>  	return max_bitflips;
>  }
>  
> -static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
> +static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>  {
> -	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> -	u32 bcr1 = readl(fmc2->io_base + FMC2_BCR1);
> +	u32 pcr = readl(nfc->io_base + FMC2_PCR);
> +	u32 bcr1 = readl(nfc->io_base + FMC2_BCR1);
>  
>  	/* Set CS used to undefined */
> -	fmc2->cs_sel = -1;
> +	nfc->cs_sel = -1;
>  
>  	/* Enable wait feature and nand flash memory bank */
>  	pcr |= FMC2_PCR_PWAITEN;
> @@ -603,19 +604,19 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
>  	/* Enable FMC2 controller */
>  	bcr1 |= FMC2_BCR1_FMC2EN;
>  
> -	writel(bcr1, fmc2->io_base + FMC2_BCR1);
> -	writel(pcr, fmc2->io_base + FMC2_PCR);
> -	writel(FMC2_PMEM_DEFAULT, fmc2->io_base + FMC2_PMEM);
> -	writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
> +	writel(bcr1, nfc->io_base + FMC2_BCR1);
> +	writel(pcr, nfc->io_base + FMC2_PCR);
> +	writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
> +	writel(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);
>  }
>  
> -static void stm32_fmc2_calc_timings(struct nand_chip *chip,
> -				    const struct nand_sdr_timings *sdrt)
> +static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip,
> +					const struct nand_sdr_timings *sdrt)
>  {
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>  	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
>  	struct stm32_fmc2_timings *tims = &nand->timings;
> -	unsigned long hclk = clk_get_rate(&fmc2->clk);
> +	unsigned long hclk = clk_get_rate(&nfc->clk);
>  	unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
>  	unsigned long timing, tar, tclr, thiz, twait;
>  	unsigned long tset_mem, tset_att, thold_mem, thold_att;
> @@ -739,29 +740,28 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
>  	tims->thold_att = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
>  }
>  
> -static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr,
> -				      const struct nand_data_interface *conf)
> +static int stm32_fmc2_nfc_setup_interface(struct mtd_info *mtd, int chipnr,
> +					  const struct nand_data_interface *cf)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
>  	const struct nand_sdr_timings *sdrt;
>  
> -	sdrt = nand_get_sdr_timings(conf);
> +	sdrt = nand_get_sdr_timings(cf);
>  	if (IS_ERR(sdrt))
>  		return PTR_ERR(sdrt);
>  
>  	if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
>  		return 0;
>  
> -	stm32_fmc2_calc_timings(chip, sdrt);
> -
> -	stm32_fmc2_timings_init(chip);
> +	stm32_fmc2_nfc_calc_timings(chip, sdrt);
> +	stm32_fmc2_nfc_timings_init(chip);
>  
>  	return 0;
>  }
>  
> -static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
> +static void stm32_fmc2_nfc_nand_callbacks_setup(struct nand_chip *chip)
>  {
> -	chip->ecc.hwctl = stm32_fmc2_hwctl;
> +	chip->ecc.hwctl = stm32_fmc2_nfc_hwctl;
>  
>  	/*
>  	 * Specific callbacks to read/write a page depending on
> @@ -769,17 +769,17 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
>  	 */
>  	if (chip->ecc.strength == FMC2_ECC_HAM) {
>  		/* Hamming is used */
> -		chip->ecc.calculate = stm32_fmc2_ham_calculate;
> -		chip->ecc.correct = stm32_fmc2_ham_correct;
> +		chip->ecc.calculate = stm32_fmc2_nfc_ham_calculate;
> +		chip->ecc.correct = stm32_fmc2_nfc_ham_correct;
>  		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 4 : 3;
>  		chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK;
>  		return;
>  	}
>  
>  	/* BCH is used */
> -	chip->ecc.read_page = stm32_fmc2_read_page;
> -	chip->ecc.calculate = stm32_fmc2_bch_calculate;
> -	chip->ecc.correct = stm32_fmc2_bch_correct;
> +	chip->ecc.read_page = stm32_fmc2_nfc_read_page;
> +	chip->ecc.calculate = stm32_fmc2_nfc_bch_calculate;
> +	chip->ecc.correct = stm32_fmc2_nfc_bch_correct;
>  
>  	if (chip->ecc.strength == FMC2_ECC_BCH8)
>  		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 14 : 13;
> @@ -787,7 +787,7 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
>  		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
>  }
>  
> -static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
> +static int stm32_fmc2_nfc_calc_ecc_bytes(int step_size, int strength)
>  {
>  	/* Hamming */
>  	if (strength == FMC2_ECC_HAM)
> @@ -801,14 +801,13 @@ static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
>  	return 8;
>  }
>  
> -NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
> +NAND_ECC_CAPS_SINGLE(stm32_fmc2_nfc_ecc_caps, stm32_fmc2_nfc_calc_ecc_bytes,
>  		     FMC2_ECC_STEP_SIZE,
>  		     FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
>  
> -static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
> -				  ofnode node)
> +static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, ofnode node)
>  {
> -	struct stm32_fmc2_nand *nand = &fmc2->nand;
> +	struct stm32_fmc2_nand *nand = &nfc->nand;
>  	u32 cs[FMC2_MAX_CE];
>  	int ret, i;
>  
> @@ -834,13 +833,13 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
>  			return -EINVAL;
>  		}
>  
> -		if (fmc2->cs_assigned & BIT(cs[i])) {
> +		if (nfc->cs_assigned & BIT(cs[i])) {
>  			pr_err("Cs already assigned: %d\n",
>  			       nand->cs_used[i]);
>  			return -EINVAL;
>  		}
>  
> -		fmc2->cs_assigned |= BIT(cs[i]);
> +		nfc->cs_assigned |= BIT(cs[i]);
>  		nand->cs_used[i] = cs[i];
>  	}
>  
> @@ -849,8 +848,8 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
>  	return 0;
>  }
>  
> -static int stm32_fmc2_parse_dt(struct udevice *dev,
> -			       struct stm32_fmc2_nfc *fmc2)
> +static int stm32_fmc2_nfc_parse_dt(struct udevice *dev,
> +				   struct stm32_fmc2_nfc *nfc)
>  {
>  	ofnode child;
>  	int ret, nchips = 0;
> @@ -869,7 +868,7 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
>  	}
>  
>  	dev_for_each_subnode(child, dev) {
> -		ret = stm32_fmc2_parse_child(fmc2, child);
> +		ret = stm32_fmc2_nfc_parse_child(nfc, child);
>  		if (ret)
>  			return ret;
>  	}
> @@ -877,10 +876,10 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
>  	return 0;
>  }
>  
> -static int stm32_fmc2_probe(struct udevice *dev)
> +static int stm32_fmc2_nfc_probe(struct udevice *dev)
>  {
> -	struct stm32_fmc2_nfc *fmc2 = dev_get_priv(dev);
> -	struct stm32_fmc2_nand *nand = &fmc2->nand;
> +	struct stm32_fmc2_nfc *nfc = dev_get_priv(dev);
> +	struct stm32_fmc2_nand *nand = &nfc->nand;
>  	struct nand_chip *chip = &nand->chip;
>  	struct mtd_info *mtd = &chip->mtd;
>  	struct nand_ecclayout *ecclayout;
> @@ -889,10 +888,10 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  	int oob_index, chip_cs, mem_region, ret;
>  	unsigned int i;
>  
> -	spin_lock_init(&fmc2->controller.lock);
> -	init_waitqueue_head(&fmc2->controller.wq);
> +	spin_lock_init(&nfc->controller.lock);
> +	init_waitqueue_head(&nfc->controller.wq);
>  
> -	ret = stm32_fmc2_parse_dt(dev, fmc2);
> +	ret = stm32_fmc2_nfc_parse_dt(dev, nfc);
>  	if (ret)
>  		return ret;
>  
> @@ -902,11 +901,11 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  		pr_err("Resource io_base not found");
>  		return ret;
>  	}
> -	fmc2->io_base = (void __iomem *)resource.start;
> +	nfc->io_base = (void __iomem *)resource.start;
>  
>  	for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
>  	     chip_cs++, mem_region += 3) {
> -		if (!(fmc2->cs_assigned & BIT(chip_cs)))
> +		if (!(nfc->cs_assigned & BIT(chip_cs)))
>  			continue;
>  
>  		ret = dev_read_resource(dev, mem_region, &resource);
> @@ -915,7 +914,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  			       chip_cs);
>  			return ret;
>  		}
> -		fmc2->data_base[chip_cs] = (void __iomem *)resource.start;
> +		nfc->data_base[chip_cs] = (void __iomem *)resource.start;
>  
>  		ret = dev_read_resource(dev, mem_region + 1, &resource);
>  		if (ret) {
> @@ -923,7 +922,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  			       chip_cs);
>  			return ret;
>  		}
> -		fmc2->cmd_base[chip_cs] = (void __iomem *)resource.start;
> +		nfc->cmd_base[chip_cs] = (void __iomem *)resource.start;
>  
>  		ret = dev_read_resource(dev, mem_region + 2, &resource);
>  		if (ret) {
> @@ -931,15 +930,15 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  			       chip_cs);
>  			return ret;
>  		}
> -		fmc2->addr_base[chip_cs] = (void __iomem *)resource.start;
> +		nfc->addr_base[chip_cs] = (void __iomem *)resource.start;
>  	}
>  
>  	/* Enable the clock */
> -	ret = clk_get_by_index(dev, 0, &fmc2->clk);
> +	ret = clk_get_by_index(dev, 0, &nfc->clk);
>  	if (ret)
>  		return ret;
>  
> -	ret = clk_enable(&fmc2->clk);
> +	ret = clk_enable(&nfc->clk);
>  	if (ret)
>  		return ret;
>  
> @@ -951,12 +950,12 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  		reset_deassert(&reset);
>  	}
>  
> -	stm32_fmc2_init(fmc2);
> +	stm32_fmc2_nfc_init(nfc);
>  
> -	chip->controller = &fmc2->base;
> -	chip->select_chip = stm32_fmc2_select_chip;
> -	chip->setup_data_interface = stm32_fmc2_setup_interface;
> -	chip->cmd_ctrl = stm32_fmc2_cmd_ctrl;
> +	chip->controller = &nfc->base;
> +	chip->select_chip = stm32_fmc2_nfc_select_chip;
> +	chip->setup_data_interface = stm32_fmc2_nfc_setup_interface;
> +	chip->cmd_ctrl = stm32_fmc2_nfc_cmd_ctrl;
>  	chip->chip_delay = FMC2_RB_DELAY_US;
>  	chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE |
>  			 NAND_USE_BOUNCE_BUFFER;
> @@ -982,7 +981,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  		return -EINVAL;
>  	}
>  
> -	ret = nand_check_ecc_caps(chip, &stm32_fmc2_ecc_caps,
> +	ret = nand_check_ecc_caps(chip, &stm32_fmc2_nfc_ecc_caps,
>  				  mtd->oobsize - FMC2_BBM_LEN);
>  	if (ret) {
>  		pr_err("No valid ECC settings set\n");
> @@ -992,10 +991,10 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  	if (chip->bbt_options & NAND_BBT_USE_FLASH)
>  		chip->bbt_options |= NAND_BBT_NO_OOB;
>  
> -	stm32_fmc2_nand_callbacks_setup(chip);
> +	stm32_fmc2_nfc_nand_callbacks_setup(chip);
>  
>  	/* Define ECC layout */
> -	ecclayout = &fmc2->ecclayout;
> +	ecclayout = &nfc->ecclayout;
>  	ecclayout->eccbytes = chip->ecc.bytes *
>  			      (mtd->writesize / chip->ecc.size);
>  	oob_index = FMC2_BBM_LEN;
> @@ -1006,7 +1005,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  	chip->ecc.layout = ecclayout;
>  
>  	if (chip->options & NAND_BUSWIDTH_16)
> -		stm32_fmc2_set_buswidth_16(fmc2, true);
> +		stm32_fmc2_nfc_set_buswidth_16(nfc, true);
>  
>  	ret = nand_scan_tail(mtd);
>  	if (ret)
> @@ -1015,16 +1014,16 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  	return nand_register(0, mtd);
>  }
>  
> -static const struct udevice_id stm32_fmc2_match[] = {
> +static const struct udevice_id stm32_fmc2_nfc_match[] = {
>  	{ .compatible = "st,stm32mp15-fmc2" },
>  	{ /* Sentinel */ }
>  };
>  
> -U_BOOT_DRIVER(stm32_fmc2_nand) = {
> -	.name = "stm32_fmc2_nand",
> +U_BOOT_DRIVER(stm32_fmc2_nfc) = {
> +	.name = "stm32_fmc2_nfc",
>  	.id = UCLASS_MTD,
> -	.of_match = stm32_fmc2_match,
> -	.probe = stm32_fmc2_probe,
> +	.of_match = stm32_fmc2_nfc_match,
> +	.probe = stm32_fmc2_nfc_probe,
>  	.priv_auto_alloc_size = sizeof(struct stm32_fmc2_nfc),
>  };
>  
> @@ -1034,9 +1033,9 @@ void board_nand_init(void)
>  	int ret;
>  
>  	ret = uclass_get_device_by_driver(UCLASS_MTD,
> -					  DM_GET_DRIVER(stm32_fmc2_nand),
> +					  DM_GET_DRIVER(stm32_fmc2_nfc),
>  					  &dev);
>  	if (ret && ret != -ENODEV)
> -		pr_err("Failed to initialize STM32 FMC2 NAND controller. (error %d)\n",
> +		pr_err("Failed to initialize STM32 FMC2 NFC controller. (error %d)\n",
>  		       ret);
>  }

Reviewed-by: Patrice Chotard <patrice.chotard@st.com>

Thanks

Patrice

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 05/11] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros
  2020-07-31  7:53 ` [PATCH 05/11] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros Christophe Kerello
@ 2020-08-13  7:29   ` Patrice CHOTARD
  2020-08-13  9:58     ` Patrice CHOTARD
  0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  7:29 UTC (permalink / raw)
  To: u-boot

Hi Christophe

On 7/31/20 9:53 AM, Christophe Kerello wrote:
> This patch removes custom macros and uses FIELD_PREP and FIELD_GET macros.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 120 +++++++++++++++------------------
>  1 file changed, 56 insertions(+), 64 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index 9718bae..eba1ded 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -10,6 +10,7 @@
>  #include <log.h>
>  #include <nand.h>
>  #include <reset.h>
> +#include <linux/bitfield.h>
>  #include <linux/bitops.h>
>  #include <linux/delay.h>
>  #include <linux/err.h>
> @@ -60,20 +61,16 @@
>  /* Register: FMC2_PCR */
>  #define FMC2_PCR_PWAITEN		BIT(1)
>  #define FMC2_PCR_PBKEN			BIT(2)
> -#define FMC2_PCR_PWID_MASK		GENMASK(5, 4)
> -#define FMC2_PCR_PWID(x)		(((x) & 0x3) << 4)
> +#define FMC2_PCR_PWID			GENMASK(5, 4)
>  #define FMC2_PCR_PWID_BUSWIDTH_8	0
>  #define FMC2_PCR_PWID_BUSWIDTH_16	1
>  #define FMC2_PCR_ECCEN			BIT(6)
>  #define FMC2_PCR_ECCALG			BIT(8)
> -#define FMC2_PCR_TCLR_MASK		GENMASK(12, 9)
> -#define FMC2_PCR_TCLR(x)		(((x) & 0xf) << 9)
> +#define FMC2_PCR_TCLR			GENMASK(12, 9)
>  #define FMC2_PCR_TCLR_DEFAULT		0xf
> -#define FMC2_PCR_TAR_MASK		GENMASK(16, 13)
> -#define FMC2_PCR_TAR(x)			(((x) & 0xf) << 13)
> +#define FMC2_PCR_TAR			GENMASK(16, 13)
>  #define FMC2_PCR_TAR_DEFAULT		0xf
> -#define FMC2_PCR_ECCSS_MASK		GENMASK(19, 17)
> -#define FMC2_PCR_ECCSS(x)		(((x) & 0x7) << 17)
> +#define FMC2_PCR_ECCSS			GENMASK(19, 17)
>  #define FMC2_PCR_ECCSS_512		1
>  #define FMC2_PCR_ECCSS_2048		3
>  #define FMC2_PCR_BCHECC			BIT(24)
> @@ -83,17 +80,17 @@
>  #define FMC2_SR_NWRF			BIT(6)
>  
>  /* Register: FMC2_PMEM */
> -#define FMC2_PMEM_MEMSET(x)		(((x) & 0xff) << 0)
> -#define FMC2_PMEM_MEMWAIT(x)		(((x) & 0xff) << 8)
> -#define FMC2_PMEM_MEMHOLD(x)		(((x) & 0xff) << 16)
> -#define FMC2_PMEM_MEMHIZ(x)		(((x) & 0xff) << 24)
> +#define FMC2_PMEM_MEMSET		GENMASK(7, 0)
> +#define FMC2_PMEM_MEMWAIT		GENMASK(15, 8)
> +#define FMC2_PMEM_MEMHOLD		GENMASK(23, 16)
> +#define FMC2_PMEM_MEMHIZ		GENMASK(31, 24)
>  #define FMC2_PMEM_DEFAULT		0x0a0a0a0a
>  
>  /* Register: FMC2_PATT */
> -#define FMC2_PATT_ATTSET(x)		(((x) & 0xff) << 0)
> -#define FMC2_PATT_ATTWAIT(x)		(((x) & 0xff) << 8)
> -#define FMC2_PATT_ATTHOLD(x)		(((x) & 0xff) << 16)
> -#define FMC2_PATT_ATTHIZ(x)		(((x) & 0xff) << 24)
> +#define FMC2_PATT_ATTSET		GENMASK(7, 0)
> +#define FMC2_PATT_ATTWAIT		GENMASK(15, 8)
> +#define FMC2_PATT_ATTHOLD		GENMASK(23, 16)
> +#define FMC2_PATT_ATTHIZ		GENMASK(31, 24)
>  #define FMC2_PATT_DEFAULT		0x0a0a0a0a
>  
>  /* Register: FMC2_BCHISR */
> @@ -106,28 +103,23 @@
>  /* Register: FMC2_BCHDSR0 */
>  #define FMC2_BCHDSR0_DUE		BIT(0)
>  #define FMC2_BCHDSR0_DEF		BIT(1)
> -#define FMC2_BCHDSR0_DEN_MASK		GENMASK(7, 4)
> -#define FMC2_BCHDSR0_DEN_SHIFT		4
> +#define FMC2_BCHDSR0_DEN		GENMASK(7, 4)
>  
>  /* Register: FMC2_BCHDSR1 */
> -#define FMC2_BCHDSR1_EBP1_MASK		GENMASK(12, 0)
> -#define FMC2_BCHDSR1_EBP2_MASK		GENMASK(28, 16)
> -#define FMC2_BCHDSR1_EBP2_SHIFT		16
> +#define FMC2_BCHDSR1_EBP1		GENMASK(12, 0)
> +#define FMC2_BCHDSR1_EBP2		GENMASK(28, 16)
>  
>  /* Register: FMC2_BCHDSR2 */
> -#define FMC2_BCHDSR2_EBP3_MASK		GENMASK(12, 0)
> -#define FMC2_BCHDSR2_EBP4_MASK		GENMASK(28, 16)
> -#define FMC2_BCHDSR2_EBP4_SHIFT		16
> +#define FMC2_BCHDSR2_EBP3		GENMASK(12, 0)
> +#define FMC2_BCHDSR2_EBP4		GENMASK(28, 16)
>  
>  /* Register: FMC2_BCHDSR3 */
> -#define FMC2_BCHDSR3_EBP5_MASK		GENMASK(12, 0)
> -#define FMC2_BCHDSR3_EBP6_MASK		GENMASK(28, 16)
> -#define FMC2_BCHDSR3_EBP6_SHIFT		16
> +#define FMC2_BCHDSR3_EBP5		GENMASK(12, 0)
> +#define FMC2_BCHDSR3_EBP6		GENMASK(28, 16)
>  
>  /* Register: FMC2_BCHDSR4 */
> -#define FMC2_BCHDSR4_EBP7_MASK		GENMASK(12, 0)
> -#define FMC2_BCHDSR4_EBP8_MASK		GENMASK(28, 16)
> -#define FMC2_BCHDSR4_EBP8_SHIFT		16
> +#define FMC2_BCHDSR4_EBP7		GENMASK(12, 0)
> +#define FMC2_BCHDSR4_EBP8		GENMASK(28, 16)
>  
>  #define FMC2_NSEC_PER_SEC		1000000000L
>  
> @@ -190,22 +182,22 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
>  	u32 pmem, patt;
>  
>  	/* Set tclr/tar timings */
> -	pcr &= ~FMC2_PCR_TCLR_MASK;
> -	pcr |= FMC2_PCR_TCLR(timings->tclr);
> -	pcr &= ~FMC2_PCR_TAR_MASK;
> -	pcr |= FMC2_PCR_TAR(timings->tar);
> +	pcr &= ~FMC2_PCR_TCLR;
> +	pcr |= FIELD_PREP(FMC2_PCR_TCLR, timings->tclr);
> +	pcr &= ~FMC2_PCR_TAR;
> +	pcr |= FIELD_PREP(FMC2_PCR_TAR, timings->tar);
>  
>  	/* Set tset/twait/thold/thiz timings in common bank */
> -	pmem = FMC2_PMEM_MEMSET(timings->tset_mem);
> -	pmem |= FMC2_PMEM_MEMWAIT(timings->twait);
> -	pmem |= FMC2_PMEM_MEMHOLD(timings->thold_mem);
> -	pmem |= FMC2_PMEM_MEMHIZ(timings->thiz);
> +	pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
> +	pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
> +	pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
> +	pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
>  
>  	/* Set tset/twait/thold/thiz timings in attribut bank */
> -	patt = FMC2_PATT_ATTSET(timings->tset_att);
> -	patt |= FMC2_PATT_ATTWAIT(timings->twait);
> -	patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
> -	patt |= FMC2_PATT_ATTHIZ(timings->thiz);
> +	patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
> +	patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
> +	patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
> +	patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
>  
>  	writel(pcr, nfc->io_base + FMC2_PCR);
>  	writel(pmem, nfc->io_base + FMC2_PMEM);
> @@ -228,13 +220,13 @@ static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
>  	}
>  
>  	/* Set buswidth */
> -	pcr &= ~FMC2_PCR_PWID_MASK;
> +	pcr &= ~FMC2_PCR_PWID;
>  	if (chip->options & NAND_BUSWIDTH_16)
> -		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
> +		pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
>  
>  	/* Set ECC sector size */
> -	pcr &= ~FMC2_PCR_ECCSS_MASK;
> -	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
> +	pcr &= ~FMC2_PCR_ECCSS;
> +	pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
>  
>  	writel(pcr, nfc->io_base + FMC2_PCR);
>  }
> @@ -264,9 +256,9 @@ static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
>  {
>  	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>  
> -	pcr &= ~FMC2_PCR_PWID_MASK;
> +	pcr &= ~FMC2_PCR_PWID;
>  	if (set)
> -		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
> +		pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
>  	writel(pcr, nfc->io_base + FMC2_PCR);
>  }
>  
> @@ -497,16 +489,16 @@ static int stm32_fmc2_nfc_bch_correct(struct mtd_info *mtd, u8 *dat,
>  	if (unlikely(bchdsr0 & FMC2_BCHDSR0_DUE))
>  		return -EBADMSG;
>  
> -	pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK;
> -	pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT;
> -	pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK;
> -	pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT;
> -	pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK;
> -	pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT;
> -	pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK;
> -	pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT;
> +	pos[0] = FIELD_GET(FMC2_BCHDSR1_EBP1, bchdsr1);
> +	pos[1] = FIELD_GET(FMC2_BCHDSR1_EBP2, bchdsr1);
> +	pos[2] = FIELD_GET(FMC2_BCHDSR2_EBP3, bchdsr2);
> +	pos[3] = FIELD_GET(FMC2_BCHDSR2_EBP4, bchdsr2);
> +	pos[4] = FIELD_GET(FMC2_BCHDSR3_EBP5, bchdsr3);
> +	pos[5] = FIELD_GET(FMC2_BCHDSR3_EBP6, bchdsr3);
> +	pos[6] = FIELD_GET(FMC2_BCHDSR4_EBP7, bchdsr4);
> +	pos[7] = FIELD_GET(FMC2_BCHDSR4_EBP8, bchdsr4);
>  
> -	den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT;
> +	den = FIELD_GET(FMC2_BCHDSR0_DEN, bchdsr0);
>  	for (i = 0; i < den; i++) {
>  		if (pos[i] < eccsize * 8) {
>  			__change_bit(pos[i], (unsigned long *)dat);
> @@ -581,7 +573,7 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>  	pcr |= FMC2_PCR_PBKEN;
>  
>  	/* Set buswidth to 8 bits mode for identification */
> -	pcr &= ~FMC2_PCR_PWID_MASK;
> +	pcr &= ~FMC2_PCR_PWID;
>  
>  	/* ECC logic is disabled */
>  	pcr &= ~FMC2_PCR_ECCEN;
> @@ -592,14 +584,14 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>  	pcr &= ~FMC2_PCR_WEN;
>  
>  	/* Set default ECC sector size */
> -	pcr &= ~FMC2_PCR_ECCSS_MASK;
> -	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048);
> +	pcr &= ~FMC2_PCR_ECCSS;
> +	pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_2048);
>  
>  	/* Set default tclr/tar timings */
> -	pcr &= ~FMC2_PCR_TCLR_MASK;
> -	pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT);
> -	pcr &= ~FMC2_PCR_TAR_MASK;
> -	pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT);
> +	pcr &= ~FMC2_PCR_TCLR;
> +	pcr |= FIELD_PREP(FMC2_PCR_TCLR, FMC2_PCR_TCLR_DEFAULT);
> +	pcr &= ~FMC2_PCR_TAR;
> +	pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
>  
>  	/* Enable FMC2 controller */
>  	bcr1 |= FMC2_BCR1_FMC2EN;

Reviewed-by: Patrice Chotard <patrice.chotard@st.com>

Thanks

Patrice

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 06/11] mtd: rawnand: stm32_fmc2: use clrsetbits_le32
  2020-07-31  7:53 ` [PATCH 06/11] mtd: rawnand: stm32_fmc2: use clrsetbits_le32 Christophe Kerello
@ 2020-08-13  7:30   ` Patrice CHOTARD
  2020-08-13  9:58     ` Patrice CHOTARD
  0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  7:30 UTC (permalink / raw)
  To: u-boot

Hi Christophe

On 7/31/20 9:53 AM, Christophe Kerello wrote:
> This patch uses clrsetbits_le32 function instead of multiple instructions.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 56 +++++++++++++---------------------
>  1 file changed, 21 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index eba1ded..1e4d757 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -178,40 +178,37 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
>  	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>  	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
>  	struct stm32_fmc2_timings *timings = &nand->timings;
> -	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>  	u32 pmem, patt;
>  
>  	/* Set tclr/tar timings */
> -	pcr &= ~FMC2_PCR_TCLR;
> -	pcr |= FIELD_PREP(FMC2_PCR_TCLR, timings->tclr);
> -	pcr &= ~FMC2_PCR_TAR;
> -	pcr |= FIELD_PREP(FMC2_PCR_TAR, timings->tar);
> +	clrsetbits_le32(nfc->io_base + FMC2_PCR,
> +			FMC2_PCR_TCLR | FMC2_PCR_TAR,
> +			FIELD_PREP(FMC2_PCR_TCLR, timings->tclr) |
> +			FIELD_PREP(FMC2_PCR_TAR, timings->tar));
>  
>  	/* Set tset/twait/thold/thiz timings in common bank */
>  	pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
>  	pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
>  	pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
>  	pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
> +	writel(pmem, nfc->io_base + FMC2_PMEM);
>  
>  	/* Set tset/twait/thold/thiz timings in attribut bank */
>  	patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
>  	patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
>  	patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
>  	patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
> -
> -	writel(pcr, nfc->io_base + FMC2_PCR);
> -	writel(pmem, nfc->io_base + FMC2_PMEM);
>  	writel(patt, nfc->io_base + FMC2_PATT);
>  }
>  
>  static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
>  {
>  	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> -	u32 pcr = readl(nfc->io_base + FMC2_PCR);
> +	u32 pcr = 0, pcr_mask;
>  
>  	/* Configure ECC algorithm (default configuration is Hamming) */
> -	pcr &= ~FMC2_PCR_ECCALG;
> -	pcr &= ~FMC2_PCR_BCHECC;
> +	pcr_mask = FMC2_PCR_ECCALG;
> +	pcr_mask |= FMC2_PCR_BCHECC;
>  	if (chip->ecc.strength == FMC2_ECC_BCH8) {
>  		pcr |= FMC2_PCR_ECCALG;
>  		pcr |= FMC2_PCR_BCHECC;
> @@ -220,15 +217,15 @@ static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
>  	}
>  
>  	/* Set buswidth */
> -	pcr &= ~FMC2_PCR_PWID;
> +	pcr_mask |= FMC2_PCR_PWID;
>  	if (chip->options & NAND_BUSWIDTH_16)
>  		pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
>  
>  	/* Set ECC sector size */
> -	pcr &= ~FMC2_PCR_ECCSS;
> +	pcr_mask |= FMC2_PCR_ECCSS;
>  	pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
>  
> -	writel(pcr, nfc->io_base + FMC2_PCR);
> +	clrsetbits_le32(nfc->io_base + FMC2_PCR, pcr_mask, pcr);
>  }
>  
>  static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
> @@ -254,22 +251,18 @@ static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
>  static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
>  					   bool set)
>  {
> -	u32 pcr = readl(nfc->io_base + FMC2_PCR);
> +	u32 pcr;
>  
> -	pcr &= ~FMC2_PCR_PWID;
> -	if (set)
> -		pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
> -	writel(pcr, nfc->io_base + FMC2_PCR);
> +	pcr = set ? FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16) :
> +		    FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_8);
> +
> +	clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_PWID, pcr);
>  }
>  
>  static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
>  {
> -	u32 pcr = readl(nfc->io_base + FMC2_PCR);
> -
> -	pcr &= ~FMC2_PCR_ECCEN;
> -	if (enable)
> -		pcr |= FMC2_PCR_ECCEN;
> -	writel(pcr, nfc->io_base + FMC2_PCR);
> +	clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_ECCEN,
> +			enable ? FMC2_PCR_ECCEN : 0);
>  }
>  
>  static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
> @@ -306,13 +299,8 @@ static void stm32_fmc2_nfc_hwctl(struct mtd_info *mtd, int mode)
>  	stm32_fmc2_nfc_set_ecc(nfc, false);
>  
>  	if (chip->ecc.strength != FMC2_ECC_HAM) {
> -		u32 pcr = readl(nfc->io_base + FMC2_PCR);
> -
> -		if (mode == NAND_ECC_WRITE)
> -			pcr |= FMC2_PCR_WEN;
> -		else
> -			pcr &= ~FMC2_PCR_WEN;
> -		writel(pcr, nfc->io_base + FMC2_PCR);
> +		clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_WEN,
> +				mode == NAND_ECC_WRITE ? FMC2_PCR_WEN : 0);
>  
>  		stm32_fmc2_nfc_clear_bch_irq(nfc);
>  	}
> @@ -563,7 +551,6 @@ static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
>  static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>  {
>  	u32 pcr = readl(nfc->io_base + FMC2_PCR);
> -	u32 bcr1 = readl(nfc->io_base + FMC2_BCR1);
>  
>  	/* Set CS used to undefined */
>  	nfc->cs_sel = -1;
> @@ -594,9 +581,8 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>  	pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
>  
>  	/* Enable FMC2 controller */
> -	bcr1 |= FMC2_BCR1_FMC2EN;
> +	setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
>  
> -	writel(bcr1, nfc->io_base + FMC2_BCR1);
>  	writel(pcr, nfc->io_base + FMC2_PCR);
>  	writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
>  	writel(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);

Reviewed-by: Patrice Chotard <patrice.chotard@st.com>

Thanks

Patrice

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 07/11] memory: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver
  2020-07-31  7:53 ` [PATCH 07/11] memory: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver Christophe Kerello
@ 2020-08-13  7:31   ` Patrice CHOTARD
  2020-08-13  9:58     ` Patrice CHOTARD
  0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  7:31 UTC (permalink / raw)
  To: u-boot

Hi Christophe

On 7/31/20 9:53 AM, Christophe Kerello wrote:
> The driver adds the support for the STMicroelectronics FMC2 EBI controller
> found on STM32MP SOCs.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
>  drivers/memory/Kconfig          |    9 +
>  drivers/memory/Makefile         |    1 +
>  drivers/memory/stm32-fmc2-ebi.c | 1056 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 1066 insertions(+)
>  create mode 100644 drivers/memory/stm32-fmc2-ebi.c
>
> diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
> index 4fbb5aa..7271892 100644
> --- a/drivers/memory/Kconfig
> +++ b/drivers/memory/Kconfig
> @@ -4,6 +4,15 @@
>  
>  menu "Memory Controller drivers"
>  
> +config STM32_FMC2_EBI
> +	bool "Support for FMC2 External Bus Interface on STM32MP SoCs"
> +	depends on ARCH_STM32MP
> +	help
> +	  Select this option to enable the STM32 FMC2 External Bus Interface
> +	  controller. This driver configures the transactions with external
> +	  devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on
> +	  SOCs containing the FMC2 External Bus Interface.
> +
>  config TI_AEMIF
>  	tristate "Texas Instruments AEMIF driver"
>  	depends on ARCH_KEYSTONE
> diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
> index 238add0..fec52ef 100644
> --- a/drivers/memory/Makefile
> +++ b/drivers/memory/Makefile
> @@ -1,2 +1,3 @@
>  
> +obj-$(CONFIG_STM32_FMC2_EBI) += stm32-fmc2-ebi.o
>  obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
> diff --git a/drivers/memory/stm32-fmc2-ebi.c b/drivers/memory/stm32-fmc2-ebi.c
> new file mode 100644
> index 0000000..d887a1e
> --- /dev/null
> +++ b/drivers/memory/stm32-fmc2-ebi.c
> @@ -0,0 +1,1056 @@
> +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
> +/*
> + * Copyright (C) STMicroelectronics 2020
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <reset.h>
> +#include <linux/bitfield.h>
> +#include <linux/err.h>
> +#include <linux/iopoll.h>
> +#include <linux/ioport.h>
> +
> +/* FMC2 Controller Registers */
> +#define FMC2_BCR1			0x0
> +#define FMC2_BTR1			0x4
> +#define FMC2_BCR(x)			((x) * 0x8 + FMC2_BCR1)
> +#define FMC2_BTR(x)			((x) * 0x8 + FMC2_BTR1)
> +#define FMC2_PCSCNTR			0x20
> +#define FMC2_BWTR1			0x104
> +#define FMC2_BWTR(x)			((x) * 0x8 + FMC2_BWTR1)
> +
> +/* Register: FMC2_BCR1 */
> +#define FMC2_BCR1_CCLKEN		BIT(20)
> +#define FMC2_BCR1_FMC2EN		BIT(31)
> +
> +/* Register: FMC2_BCRx */
> +#define FMC2_BCR_MBKEN			BIT(0)
> +#define FMC2_BCR_MUXEN			BIT(1)
> +#define FMC2_BCR_MTYP			GENMASK(3, 2)
> +#define FMC2_BCR_MWID			GENMASK(5, 4)
> +#define FMC2_BCR_FACCEN			BIT(6)
> +#define FMC2_BCR_BURSTEN		BIT(8)
> +#define FMC2_BCR_WAITPOL		BIT(9)
> +#define FMC2_BCR_WAITCFG		BIT(11)
> +#define FMC2_BCR_WREN			BIT(12)
> +#define FMC2_BCR_WAITEN			BIT(13)
> +#define FMC2_BCR_EXTMOD			BIT(14)
> +#define FMC2_BCR_ASYNCWAIT		BIT(15)
> +#define FMC2_BCR_CPSIZE			GENMASK(18, 16)
> +#define FMC2_BCR_CBURSTRW		BIT(19)
> +#define FMC2_BCR_NBLSET			GENMASK(23, 22)
> +
> +/* Register: FMC2_BTRx/FMC2_BWTRx */
> +#define FMC2_BXTR_ADDSET		GENMASK(3, 0)
> +#define FMC2_BXTR_ADDHLD		GENMASK(7, 4)
> +#define FMC2_BXTR_DATAST		GENMASK(15, 8)
> +#define FMC2_BXTR_BUSTURN		GENMASK(19, 16)
> +#define FMC2_BTR_CLKDIV			GENMASK(23, 20)
> +#define FMC2_BTR_DATLAT			GENMASK(27, 24)
> +#define FMC2_BXTR_ACCMOD		GENMASK(29, 28)
> +#define FMC2_BXTR_DATAHLD		GENMASK(31, 30)
> +
> +/* Register: FMC2_PCSCNTR */
> +#define FMC2_PCSCNTR_CSCOUNT		GENMASK(15, 0)
> +#define FMC2_PCSCNTR_CNTBEN(x)		BIT((x) + 16)
> +
> +#define FMC2_MAX_EBI_CE			4
> +#define FMC2_MAX_BANKS			5
> +
> +#define FMC2_BCR_CPSIZE_0		0x0
> +#define FMC2_BCR_CPSIZE_128		0x1
> +#define FMC2_BCR_CPSIZE_256		0x2
> +#define FMC2_BCR_CPSIZE_512		0x3
> +#define FMC2_BCR_CPSIZE_1024		0x4
> +
> +#define FMC2_BCR_MWID_8			0x0
> +#define FMC2_BCR_MWID_16		0x1
> +
> +#define FMC2_BCR_MTYP_SRAM		0x0
> +#define FMC2_BCR_MTYP_PSRAM		0x1
> +#define FMC2_BCR_MTYP_NOR		0x2
> +
> +#define FMC2_BXTR_EXTMOD_A		0x0
> +#define FMC2_BXTR_EXTMOD_B		0x1
> +#define FMC2_BXTR_EXTMOD_C		0x2
> +#define FMC2_BXTR_EXTMOD_D		0x3
> +
> +#define FMC2_BCR_NBLSET_MAX		0x3
> +#define FMC2_BXTR_ADDSET_MAX		0xf
> +#define FMC2_BXTR_ADDHLD_MAX		0xf
> +#define FMC2_BXTR_DATAST_MAX		0xff
> +#define FMC2_BXTR_BUSTURN_MAX		0xf
> +#define FMC2_BXTR_DATAHLD_MAX		0x3
> +#define FMC2_BTR_CLKDIV_MAX		0xf
> +#define FMC2_BTR_DATLAT_MAX		0xf
> +#define FMC2_PCSCNTR_CSCOUNT_MAX	0xff
> +
> +#define FMC2_NSEC_PER_SEC		1000000000L
> +
> +enum stm32_fmc2_ebi_bank {
> +	FMC2_EBI1 = 0,
> +	FMC2_EBI2,
> +	FMC2_EBI3,
> +	FMC2_EBI4,
> +	FMC2_NAND
> +};
> +
> +enum stm32_fmc2_ebi_register_type {
> +	FMC2_REG_BCR = 1,
> +	FMC2_REG_BTR,
> +	FMC2_REG_BWTR,
> +	FMC2_REG_PCSCNTR
> +};
> +
> +enum stm32_fmc2_ebi_transaction_type {
> +	FMC2_ASYNC_MODE_1_SRAM = 0,
> +	FMC2_ASYNC_MODE_1_PSRAM,
> +	FMC2_ASYNC_MODE_A_SRAM,
> +	FMC2_ASYNC_MODE_A_PSRAM,
> +	FMC2_ASYNC_MODE_2_NOR,
> +	FMC2_ASYNC_MODE_B_NOR,
> +	FMC2_ASYNC_MODE_C_NOR,
> +	FMC2_ASYNC_MODE_D_NOR,
> +	FMC2_SYNC_READ_SYNC_WRITE_PSRAM,
> +	FMC2_SYNC_READ_ASYNC_WRITE_PSRAM,
> +	FMC2_SYNC_READ_SYNC_WRITE_NOR,
> +	FMC2_SYNC_READ_ASYNC_WRITE_NOR
> +};
> +
> +enum stm32_fmc2_ebi_buswidth {
> +	FMC2_BUSWIDTH_8 = 8,
> +	FMC2_BUSWIDTH_16 = 16
> +};
> +
> +enum stm32_fmc2_ebi_cpsize {
> +	FMC2_CPSIZE_0 = 0,
> +	FMC2_CPSIZE_128 = 128,
> +	FMC2_CPSIZE_256 = 256,
> +	FMC2_CPSIZE_512 = 512,
> +	FMC2_CPSIZE_1024 = 1024
> +};
> +
> +struct stm32_fmc2_ebi {
> +	struct clk clk;
> +	fdt_addr_t io_base;
> +	u8 bank_assigned;
> +};
> +
> +/*
> + * struct stm32_fmc2_prop - STM32 FMC2 EBI property
> + * @name: the device tree binding name of the property
> + * @bprop: indicate that it is a boolean property
> + * @mprop: indicate that it is a mandatory property
> + * @reg_type: the register that have to be modified
> + * @reg_mask: the bit that have to be modified in the selected register
> + *            in case of it is a boolean property
> + * @reset_val: the default value that have to be set in case the property
> + *             has not been defined in the device tree
> + * @check: this callback ckecks that the property is compliant with the
> + *         transaction type selected
> + * @calculate: this callback is called to calculate for exemple a timing
> + *             set in nanoseconds in the device tree in clock cycles or in
> + *             clock period
> + * @set: this callback applies the values in the registers
> + */
> +struct stm32_fmc2_prop {
> +	const char *name;
> +	bool bprop;
> +	bool mprop;
> +	int reg_type;
> +	u32 reg_mask;
> +	u32 reset_val;
> +	int (*check)(struct stm32_fmc2_ebi *ebi,
> +		     const struct stm32_fmc2_prop *prop, int cs);
> +	u32 (*calculate)(struct stm32_fmc2_ebi *ebi, int cs, u32 setup);
> +	int (*set)(struct stm32_fmc2_ebi *ebi,
> +		   const struct stm32_fmc2_prop *prop,
> +		   int cs, u32 setup);
> +};
> +
> +static int stm32_fmc2_ebi_check_mux(struct stm32_fmc2_ebi *ebi,
> +				    const struct stm32_fmc2_prop *prop,
> +				    int cs)
> +{
> +	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
> +
> +	if (bcr & FMC2_BCR_MTYP)
> +		return 0;
> +
> +	return -EINVAL;
> +}
> +
> +static int stm32_fmc2_ebi_check_waitcfg(struct stm32_fmc2_ebi *ebi,
> +					const struct stm32_fmc2_prop *prop,
> +					int cs)
> +{
> +	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
> +	u32 val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
> +
> +	if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
> +		return 0;
> +
> +	return -EINVAL;
> +}
> +
> +static int stm32_fmc2_ebi_check_sync_trans(struct stm32_fmc2_ebi *ebi,
> +					   const struct stm32_fmc2_prop *prop,
> +					   int cs)
> +{
> +	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
> +
> +	if (bcr & FMC2_BCR_BURSTEN)
> +		return 0;
> +
> +	return -EINVAL;
> +}
> +
> +static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2_ebi *ebi,
> +					    const struct stm32_fmc2_prop *prop,
> +					    int cs)
> +{
> +	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
> +
> +	if (!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW))
> +		return 0;
> +
> +	return -EINVAL;
> +}
> +
> +static int stm32_fmc2_ebi_check_cpsize(struct stm32_fmc2_ebi *ebi,
> +				       const struct stm32_fmc2_prop *prop,
> +				       int cs)
> +{
> +	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
> +	u32 val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
> +
> +	if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
> +		return 0;
> +
> +	return -EINVAL;
> +}
> +
> +static int stm32_fmc2_ebi_check_address_hold(struct stm32_fmc2_ebi *ebi,
> +					     const struct stm32_fmc2_prop *prop,
> +					     int cs)
> +{
> +	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
> +	u32 bxtr = prop->reg_type == FMC2_REG_BWTR ?
> +		   readl(ebi->io_base + FMC2_BWTR(cs)) :
> +		   readl(ebi->io_base + FMC2_BTR(cs));
> +	u32 val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
> +
> +	if ((!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW)) &&
> +	    ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN))
> +		return 0;
> +
> +	return -EINVAL;
> +}
> +
> +static int stm32_fmc2_ebi_check_clk_period(struct stm32_fmc2_ebi *ebi,
> +					   const struct stm32_fmc2_prop *prop,
> +					   int cs)
> +{
> +	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
> +	u32 bcr1 = cs ? readl(ebi->io_base + FMC2_BCR1) : bcr;
> +
> +	if (bcr & FMC2_BCR_BURSTEN && (!cs || !(bcr1 & FMC2_BCR1_CCLKEN)))
> +		return 0;
> +
> +	return -EINVAL;
> +}
> +
> +static int stm32_fmc2_ebi_check_cclk(struct stm32_fmc2_ebi *ebi,
> +				     const struct stm32_fmc2_prop *prop,
> +				     int cs)
> +{
> +	if (cs)
> +		return -EINVAL;
> +
> +	return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs);
> +}
> +
> +static u32 stm32_fmc2_ebi_ns_to_clock_cycles(struct stm32_fmc2_ebi *ebi,
> +					     int cs, u32 setup)
> +{
> +	unsigned long hclk = clk_get_rate(&ebi->clk);
> +	unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
> +
> +	return DIV_ROUND_UP(setup * 1000, hclkp);
> +}
> +
> +static u32 stm32_fmc2_ebi_ns_to_clk_period(struct stm32_fmc2_ebi *ebi,
> +					   int cs, u32 setup)
> +{
> +	u32 nb_clk_cycles = stm32_fmc2_ebi_ns_to_clock_cycles(ebi, cs, setup);
> +	u32 bcr = readl(ebi->io_base + FMC2_BCR1);
> +	u32 btr = bcr & FMC2_BCR1_CCLKEN || !cs ?
> +		  readl(ebi->io_base + FMC2_BTR1) :
> +		  readl(ebi->io_base + FMC2_BTR(cs));
> +	u32 clk_period = FIELD_GET(FMC2_BTR_CLKDIV, btr) + 1;
> +
> +	return DIV_ROUND_UP(nb_clk_cycles, clk_period);
> +}
> +
> +static int stm32_fmc2_ebi_get_reg(int reg_type, int cs, u32 *reg)
> +{
> +	switch (reg_type) {
> +	case FMC2_REG_BCR:
> +		*reg = FMC2_BCR(cs);
> +		break;
> +	case FMC2_REG_BTR:
> +		*reg = FMC2_BTR(cs);
> +		break;
> +	case FMC2_REG_BWTR:
> +		*reg = FMC2_BWTR(cs);
> +		break;
> +	case FMC2_REG_PCSCNTR:
> +		*reg = FMC2_PCSCNTR;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int stm32_fmc2_ebi_set_bit_field(struct stm32_fmc2_ebi *ebi,
> +					const struct stm32_fmc2_prop *prop,
> +					int cs, u32 setup)
> +{
> +	u32 reg;
> +	int ret;
> +
> +	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
> +	if (ret)
> +		return ret;
> +
> +	clrsetbits_le32(ebi->io_base + reg, prop->reg_mask,
> +			setup ? prop->reg_mask : 0);
> +
> +	return 0;
> +}
> +
> +static int stm32_fmc2_ebi_set_trans_type(struct stm32_fmc2_ebi *ebi,
> +					 const struct stm32_fmc2_prop *prop,
> +					 int cs, u32 setup)
> +{
> +	u32 bcr_mask, bcr = FMC2_BCR_WREN;
> +	u32 btr_mask, btr = 0;
> +	u32 bwtr_mask, bwtr = 0;
> +
> +	bwtr_mask = FMC2_BXTR_ACCMOD;
> +	btr_mask = FMC2_BXTR_ACCMOD;
> +	bcr_mask = FMC2_BCR_MUXEN | FMC2_BCR_MTYP | FMC2_BCR_FACCEN |
> +		   FMC2_BCR_WREN | FMC2_BCR_WAITEN | FMC2_BCR_BURSTEN |
> +		   FMC2_BCR_EXTMOD | FMC2_BCR_CBURSTRW;
> +
> +	switch (setup) {
> +	case FMC2_ASYNC_MODE_1_SRAM:
> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM);
> +		/*
> +		 * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
> +		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
> +		 */
> +		break;
> +	case FMC2_ASYNC_MODE_1_PSRAM:
> +		/*
> +		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
> +		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
> +		 */
> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
> +		break;
> +	case FMC2_ASYNC_MODE_A_SRAM:
> +		/*
> +		 * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
> +		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0
> +		 */
> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM);
> +		bcr |= FMC2_BCR_EXTMOD;
> +		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
> +		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
> +		break;
> +	case FMC2_ASYNC_MODE_A_PSRAM:
> +		/*
> +		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
> +		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0
> +		 */
> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
> +		bcr |= FMC2_BCR_EXTMOD;
> +		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
> +		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
> +		break;
> +	case FMC2_ASYNC_MODE_2_NOR:
> +		/*
> +		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
> +		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
> +		 */
> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
> +		bcr |= FMC2_BCR_FACCEN;
> +		break;
> +	case FMC2_ASYNC_MODE_B_NOR:
> +		/*
> +		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
> +		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 1
> +		 */
> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
> +		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
> +		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B);
> +		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B);
> +		break;
> +	case FMC2_ASYNC_MODE_C_NOR:
> +		/*
> +		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
> +		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 2
> +		 */
> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
> +		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
> +		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C);
> +		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C);
> +		break;
> +	case FMC2_ASYNC_MODE_D_NOR:
> +		/*
> +		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
> +		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 3
> +		 */
> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
> +		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
> +		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
> +		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
> +		break;
> +	case FMC2_SYNC_READ_SYNC_WRITE_PSRAM:
> +		/*
> +		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0,
> +		 * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0
> +		 */
> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
> +		bcr |= FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW;
> +		break;
> +	case FMC2_SYNC_READ_ASYNC_WRITE_PSRAM:
> +		/*
> +		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0,
> +		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
> +		 */
> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
> +		bcr |= FMC2_BCR_BURSTEN;
> +		break;
> +	case FMC2_SYNC_READ_SYNC_WRITE_NOR:
> +		/*
> +		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0,
> +		 * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0
> +		 */
> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
> +		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW;
> +		break;
> +	case FMC2_SYNC_READ_ASYNC_WRITE_NOR:
> +		/*
> +		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0,
> +		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
> +		 */
> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
> +		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN;
> +		break;
> +	default:
> +		/* Type of transaction not supported */
> +		return -EINVAL;
> +	}
> +
> +	if (bcr & FMC2_BCR_EXTMOD)
> +		clrsetbits_le32(ebi->io_base + FMC2_BWTR(cs),
> +				bwtr_mask, bwtr);
> +	clrsetbits_le32(ebi->io_base + FMC2_BTR(cs), btr_mask, btr);
> +	clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), bcr_mask, bcr);
> +
> +	return 0;
> +}
> +
> +static int stm32_fmc2_ebi_set_buswidth(struct stm32_fmc2_ebi *ebi,
> +				       const struct stm32_fmc2_prop *prop,
> +				       int cs, u32 setup)
> +{
> +	u32 val;
> +
> +	switch (setup) {
> +	case FMC2_BUSWIDTH_8:
> +		val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_8);
> +		break;
> +	case FMC2_BUSWIDTH_16:
> +		val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_16);
> +		break;
> +	default:
> +		/* Buswidth not supported */
> +		return -EINVAL;
> +	}
> +
> +	clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_MWID, val);
> +
> +	return 0;
> +}
> +
> +static int stm32_fmc2_ebi_set_cpsize(struct stm32_fmc2_ebi *ebi,
> +				     const struct stm32_fmc2_prop *prop,
> +				     int cs, u32 setup)
> +{
> +	u32 val;
> +
> +	switch (setup) {
> +	case FMC2_CPSIZE_0:
> +		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_0);
> +		break;
> +	case FMC2_CPSIZE_128:
> +		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_128);
> +		break;
> +	case FMC2_CPSIZE_256:
> +		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_256);
> +		break;
> +	case FMC2_CPSIZE_512:
> +		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_512);
> +		break;
> +	case FMC2_CPSIZE_1024:
> +		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_1024);
> +		break;
> +	default:
> +		/* Cpsize not supported */
> +		return -EINVAL;
> +	}
> +
> +	clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_CPSIZE, val);
> +
> +	return 0;
> +}
> +
> +static int stm32_fmc2_ebi_set_bl_setup(struct stm32_fmc2_ebi *ebi,
> +				       const struct stm32_fmc2_prop *prop,
> +				       int cs, u32 setup)
> +{
> +	u32 val;
> +
> +	val = min_t(u32, setup, FMC2_BCR_NBLSET_MAX);
> +	val = FIELD_PREP(FMC2_BCR_NBLSET, val);
> +	clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_NBLSET, val);
> +
> +	return 0;
> +}
> +
> +static int stm32_fmc2_ebi_set_address_setup(struct stm32_fmc2_ebi *ebi,
> +					    const struct stm32_fmc2_prop *prop,
> +					    int cs, u32 setup)
> +{
> +	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
> +	u32 bxtr = prop->reg_type == FMC2_REG_BWTR ?
> +		   readl(ebi->io_base + FMC2_BWTR(cs)) :
> +		   readl(ebi->io_base + FMC2_BTR(cs));
> +	u32 reg, val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
> +	int ret;
> +
> +	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
> +	if (ret)
> +		return ret;
> +
> +	if ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN)
> +		val = clamp_val(setup, 1, FMC2_BXTR_ADDSET_MAX);
> +	else
> +		val = min_t(u32, setup, FMC2_BXTR_ADDSET_MAX);
> +	val = FIELD_PREP(FMC2_BXTR_ADDSET, val);
> +	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_ADDSET, val);
> +
> +	return 0;
> +}
> +
> +static int stm32_fmc2_ebi_set_address_hold(struct stm32_fmc2_ebi *ebi,
> +					   const struct stm32_fmc2_prop *prop,
> +					   int cs, u32 setup)
> +{
> +	u32 val, reg;
> +	int ret;
> +
> +	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
> +	if (ret)
> +		return ret;
> +
> +	val = clamp_val(setup, 1, FMC2_BXTR_ADDHLD_MAX);
> +	val = FIELD_PREP(FMC2_BXTR_ADDHLD, val);
> +	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_ADDHLD, val);
> +
> +	return 0;
> +}
> +
> +static int stm32_fmc2_ebi_set_data_setup(struct stm32_fmc2_ebi *ebi,
> +					 const struct stm32_fmc2_prop *prop,
> +					 int cs, u32 setup)
> +{
> +	u32 val, reg;
> +	int ret;
> +
> +	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
> +	if (ret)
> +		return ret;
> +
> +	val = clamp_val(setup, 1, FMC2_BXTR_DATAST_MAX);
> +	val = FIELD_PREP(FMC2_BXTR_DATAST, val);
> +	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_DATAST, val);
> +
> +	return 0;
> +}
> +
> +static int stm32_fmc2_ebi_set_bus_turnaround(struct stm32_fmc2_ebi *ebi,
> +					     const struct stm32_fmc2_prop *prop,
> +					     int cs, u32 setup)
> +{
> +	u32 val, reg;
> +	int ret;
> +
> +	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
> +	if (ret)
> +		return ret;
> +
> +	val = setup ? min_t(u32, setup - 1, FMC2_BXTR_BUSTURN_MAX) : 0;
> +	val = FIELD_PREP(FMC2_BXTR_BUSTURN, val);
> +	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_BUSTURN, val);
> +
> +	return 0;
> +}
> +
> +static int stm32_fmc2_ebi_set_data_hold(struct stm32_fmc2_ebi *ebi,
> +					const struct stm32_fmc2_prop *prop,
> +					int cs, u32 setup)
> +{
> +	u32 val, reg;
> +	int ret;
> +
> +	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
> +	if (ret)
> +		return ret;
> +
> +	if (prop->reg_type == FMC2_REG_BWTR)
> +		val = setup ? min_t(u32, setup - 1, FMC2_BXTR_DATAHLD_MAX) : 0;
> +	else
> +		val = min_t(u32, setup, FMC2_BXTR_DATAHLD_MAX);
> +	val = FIELD_PREP(FMC2_BXTR_DATAHLD, val);
> +	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_DATAHLD, val);
> +
> +	return 0;
> +}
> +
> +static int stm32_fmc2_ebi_set_clk_period(struct stm32_fmc2_ebi *ebi,
> +					 const struct stm32_fmc2_prop *prop,
> +					 int cs, u32 setup)
> +{
> +	u32 val;
> +
> +	val = setup ? clamp_val(setup - 1, 1, FMC2_BTR_CLKDIV_MAX) : 1;
> +	val = FIELD_PREP(FMC2_BTR_CLKDIV, val);
> +	clrsetbits_le32(ebi->io_base + FMC2_BTR(cs), FMC2_BTR_CLKDIV, val);
> +
> +	return 0;
> +}
> +
> +static int stm32_fmc2_ebi_set_data_latency(struct stm32_fmc2_ebi *ebi,
> +					   const struct stm32_fmc2_prop *prop,
> +					   int cs, u32 setup)
> +{
> +	u32 val;
> +
> +	val = setup > 1 ? min_t(u32, setup - 2, FMC2_BTR_DATLAT_MAX) : 0;
> +	val = FIELD_PREP(FMC2_BTR_DATLAT, val);
> +	clrsetbits_le32(ebi->io_base + FMC2_BTR(cs), FMC2_BTR_DATLAT, val);
> +
> +	return 0;
> +}
> +
> +static int stm32_fmc2_ebi_set_max_low_pulse(struct stm32_fmc2_ebi *ebi,
> +					    const struct stm32_fmc2_prop *prop,
> +					    int cs, u32 setup)
> +{
> +	u32 old_val, new_val, pcscntr;
> +
> +	if (setup < 1)
> +		return 0;
> +
> +	pcscntr = readl(ebi->io_base + FMC2_PCSCNTR);
> +
> +	/* Enable counter for the bank */
> +	setbits_le32(ebi->io_base + FMC2_PCSCNTR, FMC2_PCSCNTR_CNTBEN(cs));
> +
> +	new_val = min_t(u32, setup - 1, FMC2_PCSCNTR_CSCOUNT_MAX);
> +	old_val = FIELD_GET(FMC2_PCSCNTR_CSCOUNT, pcscntr);
> +	if (old_val && new_val > old_val)
> +		/* Keep current counter value */
> +		return 0;
> +
> +	new_val = FIELD_PREP(FMC2_PCSCNTR_CSCOUNT, new_val);
> +	clrsetbits_le32(ebi->io_base + FMC2_PCSCNTR,
> +			FMC2_PCSCNTR_CSCOUNT, new_val);
> +
> +	return 0;
> +}
> +
> +static const struct stm32_fmc2_prop stm32_fmc2_child_props[] = {
> +	/* st,fmc2-ebi-cs-trans-type must be the first property */
> +	{
> +		.name = "st,fmc2-ebi-cs-transaction-type",
> +		.mprop = true,
> +		.set = stm32_fmc2_ebi_set_trans_type,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-cclk-enable",
> +		.bprop = true,
> +		.reg_type = FMC2_REG_BCR,
> +		.reg_mask = FMC2_BCR1_CCLKEN,
> +		.check = stm32_fmc2_ebi_check_cclk,
> +		.set = stm32_fmc2_ebi_set_bit_field,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-mux-enable",
> +		.bprop = true,
> +		.reg_type = FMC2_REG_BCR,
> +		.reg_mask = FMC2_BCR_MUXEN,
> +		.check = stm32_fmc2_ebi_check_mux,
> +		.set = stm32_fmc2_ebi_set_bit_field,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-buswidth",
> +		.reset_val = FMC2_BUSWIDTH_16,
> +		.set = stm32_fmc2_ebi_set_buswidth,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-waitpol-high",
> +		.bprop = true,
> +		.reg_type = FMC2_REG_BCR,
> +		.reg_mask = FMC2_BCR_WAITPOL,
> +		.set = stm32_fmc2_ebi_set_bit_field,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-waitcfg-enable",
> +		.bprop = true,
> +		.reg_type = FMC2_REG_BCR,
> +		.reg_mask = FMC2_BCR_WAITCFG,
> +		.check = stm32_fmc2_ebi_check_waitcfg,
> +		.set = stm32_fmc2_ebi_set_bit_field,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-wait-enable",
> +		.bprop = true,
> +		.reg_type = FMC2_REG_BCR,
> +		.reg_mask = FMC2_BCR_WAITEN,
> +		.check = stm32_fmc2_ebi_check_sync_trans,
> +		.set = stm32_fmc2_ebi_set_bit_field,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-asyncwait-enable",
> +		.bprop = true,
> +		.reg_type = FMC2_REG_BCR,
> +		.reg_mask = FMC2_BCR_ASYNCWAIT,
> +		.check = stm32_fmc2_ebi_check_async_trans,
> +		.set = stm32_fmc2_ebi_set_bit_field,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-cpsize",
> +		.check = stm32_fmc2_ebi_check_cpsize,
> +		.set = stm32_fmc2_ebi_set_cpsize,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-byte-lane-setup-ns",
> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
> +		.set = stm32_fmc2_ebi_set_bl_setup,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-address-setup-ns",
> +		.reg_type = FMC2_REG_BTR,
> +		.reset_val = FMC2_BXTR_ADDSET_MAX,
> +		.check = stm32_fmc2_ebi_check_async_trans,
> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
> +		.set = stm32_fmc2_ebi_set_address_setup,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-address-hold-ns",
> +		.reg_type = FMC2_REG_BTR,
> +		.reset_val = FMC2_BXTR_ADDHLD_MAX,
> +		.check = stm32_fmc2_ebi_check_address_hold,
> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
> +		.set = stm32_fmc2_ebi_set_address_hold,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-data-setup-ns",
> +		.reg_type = FMC2_REG_BTR,
> +		.reset_val = FMC2_BXTR_DATAST_MAX,
> +		.check = stm32_fmc2_ebi_check_async_trans,
> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
> +		.set = stm32_fmc2_ebi_set_data_setup,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-bus-turnaround-ns",
> +		.reg_type = FMC2_REG_BTR,
> +		.reset_val = FMC2_BXTR_BUSTURN_MAX + 1,
> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
> +		.set = stm32_fmc2_ebi_set_bus_turnaround,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-data-hold-ns",
> +		.reg_type = FMC2_REG_BTR,
> +		.check = stm32_fmc2_ebi_check_async_trans,
> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
> +		.set = stm32_fmc2_ebi_set_data_hold,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-clk-period-ns",
> +		.reset_val = FMC2_BTR_CLKDIV_MAX + 1,
> +		.check = stm32_fmc2_ebi_check_clk_period,
> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
> +		.set = stm32_fmc2_ebi_set_clk_period,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-data-latency-ns",
> +		.check = stm32_fmc2_ebi_check_sync_trans,
> +		.calculate = stm32_fmc2_ebi_ns_to_clk_period,
> +		.set = stm32_fmc2_ebi_set_data_latency,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-write-address-setup-ns",
> +		.reg_type = FMC2_REG_BWTR,
> +		.reset_val = FMC2_BXTR_ADDSET_MAX,
> +		.check = stm32_fmc2_ebi_check_async_trans,
> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
> +		.set = stm32_fmc2_ebi_set_address_setup,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-write-address-hold-ns",
> +		.reg_type = FMC2_REG_BWTR,
> +		.reset_val = FMC2_BXTR_ADDHLD_MAX,
> +		.check = stm32_fmc2_ebi_check_address_hold,
> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
> +		.set = stm32_fmc2_ebi_set_address_hold,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-write-data-setup-ns",
> +		.reg_type = FMC2_REG_BWTR,
> +		.reset_val = FMC2_BXTR_DATAST_MAX,
> +		.check = stm32_fmc2_ebi_check_async_trans,
> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
> +		.set = stm32_fmc2_ebi_set_data_setup,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-write-bus-turnaround-ns",
> +		.reg_type = FMC2_REG_BWTR,
> +		.reset_val = FMC2_BXTR_BUSTURN_MAX + 1,
> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
> +		.set = stm32_fmc2_ebi_set_bus_turnaround,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-write-data-hold-ns",
> +		.reg_type = FMC2_REG_BWTR,
> +		.check = stm32_fmc2_ebi_check_async_trans,
> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
> +		.set = stm32_fmc2_ebi_set_data_hold,
> +	},
> +	{
> +		.name = "st,fmc2-ebi-cs-max-low-pulse-ns",
> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
> +		.set = stm32_fmc2_ebi_set_max_low_pulse,
> +	},
> +};
> +
> +static int stm32_fmc2_ebi_parse_prop(struct stm32_fmc2_ebi *ebi,
> +				     ofnode node,
> +				     const struct stm32_fmc2_prop *prop,
> +				     int cs)
> +{
> +	u32 setup = 0;
> +
> +	if (!prop->set) {
> +		pr_err("property %s is not well defined\n", prop->name);
> +		return -EINVAL;
> +	}
> +
> +	if (prop->check && prop->check(ebi, prop, cs))
> +		/* Skip this property */
> +		return 0;
> +
> +	if (prop->bprop) {
> +		bool bprop;
> +
> +		bprop = ofnode_read_bool(node, prop->name);
> +		if (prop->mprop && !bprop) {
> +			pr_err("mandatory property %s not defined in the device tree\n",
> +			       prop->name);
> +			return -EINVAL;
> +		}
> +
> +		if (bprop)
> +			setup = 1;
> +	} else {
> +		u32 val;
> +		int ret;
> +
> +		ret = ofnode_read_u32(node, prop->name, &val);
> +		if (prop->mprop && ret) {
> +			pr_err("mandatory property %s not defined in the device tree\n",
> +			       prop->name);
> +			return ret;
> +		}
> +
> +		if (ret)
> +			setup = prop->reset_val;
> +		else if (prop->calculate)
> +			setup = prop->calculate(ebi, cs, val);
> +		else
> +			setup = val;
> +	}
> +
> +	return prop->set(ebi, prop, cs, setup);
> +}
> +
> +static void stm32_fmc2_ebi_enable_bank(struct stm32_fmc2_ebi *ebi, int cs)
> +{
> +	setbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_MBKEN);
> +}
> +
> +static void stm32_fmc2_ebi_disable_bank(struct stm32_fmc2_ebi *ebi, int cs)
> +{
> +	clrbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_MBKEN);
> +}
> +
> +/* NWAIT signal can not be connected to EBI controller and NAND controller */
> +static bool stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi)
> +{
> +	unsigned int cs;
> +	u32 bcr;
> +
> +	for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) {
> +		if (!(ebi->bank_assigned & BIT(cs)))
> +			continue;
> +
> +		bcr = readl(ebi->io_base + FMC2_BCR(cs));
> +		if ((bcr & FMC2_BCR_WAITEN || bcr & FMC2_BCR_ASYNCWAIT) &&
> +		    ebi->bank_assigned & BIT(FMC2_NAND))
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
> +static void stm32_fmc2_ebi_enable(struct stm32_fmc2_ebi *ebi)
> +{
> +	setbits_le32(ebi->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
> +}
> +
> +static int stm32_fmc2_ebi_setup_cs(struct stm32_fmc2_ebi *ebi,
> +				   ofnode node, u32 cs)
> +{
> +	unsigned int i;
> +	int ret;
> +
> +	stm32_fmc2_ebi_disable_bank(ebi, cs);
> +
> +	for (i = 0; i < ARRAY_SIZE(stm32_fmc2_child_props); i++) {
> +		const struct stm32_fmc2_prop *p = &stm32_fmc2_child_props[i];
> +
> +		ret = stm32_fmc2_ebi_parse_prop(ebi, node, p, cs);
> +		if (ret) {
> +			pr_err("property %s could not be set: %d\n",
> +			       p->name, ret);
> +			return ret;
> +		}
> +	}
> +
> +	stm32_fmc2_ebi_enable_bank(ebi, cs);
> +
> +	return 0;
> +}
> +
> +static int stm32_fmc2_ebi_parse_dt(struct udevice *dev,
> +				   struct stm32_fmc2_ebi *ebi)
> +{
> +	ofnode child;
> +	bool child_found = false;
> +	u32 bank;
> +	int ret;
> +
> +	dev_for_each_subnode(child, dev) {
> +		ret = ofnode_read_u32(child, "reg", &bank);
> +		if (ret) {
> +			pr_err("could not retrieve reg property: %d\n", ret);
> +			return ret;
> +		}
> +
> +		if (bank >= FMC2_MAX_BANKS) {
> +			pr_err("invalid reg value: %d\n", bank);
> +			return -EINVAL;
> +		}
> +
> +		if (ebi->bank_assigned & BIT(bank)) {
> +			pr_err("bank already assigned: %d\n", bank);
> +			return -EINVAL;
> +		}
> +
> +		if (bank < FMC2_MAX_EBI_CE) {
> +			ret = stm32_fmc2_ebi_setup_cs(ebi, child, bank);
> +			if (ret) {
> +				pr_err("setup chip select %d failed: %d\n",
> +				       bank, ret);
> +				return ret;
> +			}
> +		}
> +
> +		ebi->bank_assigned |= BIT(bank);
> +		child_found = true;
> +	}
> +
> +	if (!child_found) {
> +		pr_warn("no subnodes found, disable the driver.\n");
> +		return -ENODEV;
> +	}
> +
> +	if (stm32_fmc2_ebi_nwait_used_by_ctrls(ebi)) {
> +		pr_err("NWAIT signal connected to EBI and NAND controllers\n");
> +		return -EINVAL;
> +	}
> +
> +	stm32_fmc2_ebi_enable(ebi);
> +
> +	return 0;
> +}
> +
> +static int stm32_fmc2_ebi_probe(struct udevice *dev)
> +{
> +	struct stm32_fmc2_ebi *ebi = dev_get_priv(dev);
> +	struct reset_ctl reset;
> +	int ret;
> +
> +	ebi->io_base = dev_read_addr(dev);
> +	if (ebi->io_base == FDT_ADDR_T_NONE)
> +		return -EINVAL;
> +
> +	ret = clk_get_by_index(dev, 0, &ebi->clk);
> +	if (ret)
> +		return ret;
> +
> +	ret = clk_enable(&ebi->clk);
> +	if (ret)
> +		return ret;
> +
> +	ret = reset_get_by_index(dev, 0, &reset);
> +	if (!ret) {
> +		reset_assert(&reset);
> +		udelay(2);
> +		reset_deassert(&reset);
> +	}
> +
> +	return stm32_fmc2_ebi_parse_dt(dev, ebi);
> +}
> +
> +static const struct udevice_id stm32_fmc2_ebi_match[] = {
> +	{.compatible = "st,stm32mp1-fmc2-ebi"},
> +	{ /* Sentinel */ }
> +};
> +
> +U_BOOT_DRIVER(stm32_fmc2_ebi) = {
> +	.name = "stm32_fmc2_ebi",
> +	.id = UCLASS_NOP,
> +	.of_match = stm32_fmc2_ebi_match,
> +	.probe = stm32_fmc2_ebi_probe,
> +	.priv_auto_alloc_size = sizeof(struct stm32_fmc2_ebi),
> +	.bind = dm_scan_fdt_dev,
> +};

Reviewed-by: Patrice Chotard <patrice.chotard@st.com>

Thanks

Patrice

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 08/11] mtd: rawnand: stm32_fmc2: get resources from parent node
  2020-07-31  7:53 ` [PATCH 08/11] mtd: rawnand: stm32_fmc2: get resources from parent node Christophe Kerello
@ 2020-08-13  7:33   ` Patrice CHOTARD
  2020-08-13  9:58     ` Patrice CHOTARD
  0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  7:33 UTC (permalink / raw)
  To: u-boot

Hi Christophe

On 7/31/20 9:53 AM, Christophe Kerello wrote:
> FMC2 EBI support has been added. Common resources (registers base
> address and clock) can now be shared between the 2 drivers using
> "st,stm32mp1-fmc2-nfc" compatible string. It means that the
> common resources should now be found in the parent device when EBI
> node is available.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 87 +++++++++++++++++++++++-----------
>  1 file changed, 59 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index 1e4d757..47fe610 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -158,10 +158,10 @@ struct stm32_fmc2_nfc {
>  	struct nand_hw_control base;
>  	struct stm32_fmc2_nand nand;
>  	struct nand_ecclayout ecclayout;
> -	void __iomem *io_base;
> -	void __iomem *data_base[FMC2_MAX_CE];
> -	void __iomem *cmd_base[FMC2_MAX_CE];
> -	void __iomem *addr_base[FMC2_MAX_CE];
> +	fdt_addr_t io_base;
> +	fdt_addr_t data_base[FMC2_MAX_CE];
> +	fdt_addr_t cmd_base[FMC2_MAX_CE];
> +	fdt_addr_t addr_base[FMC2_MAX_CE];
>  	struct clk clk;
>  
>  	u8 cs_assigned;
> @@ -241,8 +241,8 @@ static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
>  		return;
>  
>  	nfc->cs_sel = nand->cs_used[chipnr];
> -	chip->IO_ADDR_R = nfc->data_base[nfc->cs_sel];
> -	chip->IO_ADDR_W = nfc->data_base[nfc->cs_sel];
> +	chip->IO_ADDR_R = (void __iomem *)nfc->data_base[nfc->cs_sel];
> +	chip->IO_ADDR_W = (void __iomem *)nfc->data_base[nfc->cs_sel];
>  
>  	stm32_fmc2_nfc_setup(chip);
>  	stm32_fmc2_nfc_timings_init(chip);
> @@ -548,7 +548,7 @@ static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
>  	return max_bitflips;
>  }
>  
> -static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
> +static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc, bool has_parent)
>  {
>  	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>  
> @@ -581,7 +581,8 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>  	pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
>  
>  	/* Enable FMC2 controller */
> -	setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
> +	if (!has_parent)
> +		setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
>  
>  	writel(pcr, nfc->io_base + FMC2_PCR);
>  	writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
> @@ -854,6 +855,30 @@ static int stm32_fmc2_nfc_parse_dt(struct udevice *dev,
>  	return 0;
>  }
>  
> +static struct udevice *stm32_fmc2_nfc_get_cdev(struct udevice *dev)
> +{
> +	struct udevice *pdev = dev_get_parent(dev);
> +	struct udevice *cdev = NULL;
> +	bool ebi_found = false;
> +
> +	if (pdev && ofnode_device_is_compatible(dev_ofnode(pdev),
> +						"st,stm32mp1-fmc2-ebi"))
> +		ebi_found = true;
> +
> +	if (ofnode_device_is_compatible(dev_ofnode(dev),
> +					"st,stm32mp1-fmc2-nfc")) {
> +		if (ebi_found)
> +			cdev = pdev;
> +
> +		return cdev;
> +	}
> +
> +	if (!ebi_found)
> +		cdev = dev;
> +
> +	return cdev;
> +}
> +
>  static int stm32_fmc2_nfc_probe(struct udevice *dev)
>  {
>  	struct stm32_fmc2_nfc *nfc = dev_get_priv(dev);
> @@ -861,58 +886,63 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
>  	struct nand_chip *chip = &nand->chip;
>  	struct mtd_info *mtd = &chip->mtd;
>  	struct nand_ecclayout *ecclayout;
> -	struct resource resource;
> +	struct udevice *cdev;
>  	struct reset_ctl reset;
>  	int oob_index, chip_cs, mem_region, ret;
>  	unsigned int i;
> +	int start_region = 0;
> +	fdt_addr_t addr;
>  
>  	spin_lock_init(&nfc->controller.lock);
>  	init_waitqueue_head(&nfc->controller.wq);
>  
> +	cdev = stm32_fmc2_nfc_get_cdev(dev);
> +	if (!cdev)
> +		return -EINVAL;
> +
>  	ret = stm32_fmc2_nfc_parse_dt(dev, nfc);
>  	if (ret)
>  		return ret;
>  
> -	/* Get resources */
> -	ret = dev_read_resource(dev, 0, &resource);
> -	if (ret) {
> -		pr_err("Resource io_base not found");
> -		return ret;
> -	}
> -	nfc->io_base = (void __iomem *)resource.start;
> +	nfc->io_base = dev_read_addr(cdev);
> +	if (nfc->io_base == FDT_ADDR_T_NONE)
> +		return -EINVAL;
> +
> +	if (dev == cdev)
> +		start_region = 1;
>  
> -	for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
> +	for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE;
>  	     chip_cs++, mem_region += 3) {
>  		if (!(nfc->cs_assigned & BIT(chip_cs)))
>  			continue;
>  
> -		ret = dev_read_resource(dev, mem_region, &resource);
> -		if (ret) {
> +		addr = dev_read_addr_index(dev, mem_region);
> +		if (addr == FDT_ADDR_T_NONE) {
>  			pr_err("Resource data_base not found for cs%d",
>  			       chip_cs);
>  			return ret;
>  		}
> -		nfc->data_base[chip_cs] = (void __iomem *)resource.start;
> +		nfc->data_base[chip_cs] = addr;
>  
> -		ret = dev_read_resource(dev, mem_region + 1, &resource);
> -		if (ret) {
> +		addr = dev_read_addr_index(dev, mem_region + 1);
> +		if (addr == FDT_ADDR_T_NONE) {
>  			pr_err("Resource cmd_base not found for cs%d",
>  			       chip_cs);
>  			return ret;
>  		}
> -		nfc->cmd_base[chip_cs] = (void __iomem *)resource.start;
> +		nfc->cmd_base[chip_cs] = addr;
>  
> -		ret = dev_read_resource(dev, mem_region + 2, &resource);
> -		if (ret) {
> +		addr = dev_read_addr_index(dev, mem_region + 2);
> +		if (addr == FDT_ADDR_T_NONE) {
>  			pr_err("Resource addr_base not found for cs%d",
>  			       chip_cs);
>  			return ret;
>  		}
> -		nfc->addr_base[chip_cs] = (void __iomem *)resource.start;
> +		nfc->addr_base[chip_cs] = addr;
>  	}
>  
>  	/* Enable the clock */
> -	ret = clk_get_by_index(dev, 0, &nfc->clk);
> +	ret = clk_get_by_index(cdev, 0, &nfc->clk);
>  	if (ret)
>  		return ret;
>  
> @@ -928,7 +958,7 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
>  		reset_deassert(&reset);
>  	}
>  
> -	stm32_fmc2_nfc_init(nfc);
> +	stm32_fmc2_nfc_init(nfc, dev != cdev);
>  
>  	chip->controller = &nfc->base;
>  	chip->select_chip = stm32_fmc2_nfc_select_chip;
> @@ -994,6 +1024,7 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
>  
>  static const struct udevice_id stm32_fmc2_nfc_match[] = {
>  	{ .compatible = "st,stm32mp15-fmc2" },
> +	{ .compatible = "st,stm32mp1-fmc2-nfc" },
>  	{ /* Sentinel */ }
>  };
>  

Reviewed-by: Patrice Chotard <patrice.chotard@st.com>

Thanks

Patrice

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 09/11] board: stm32mp1: update fdt fixup partitions table
  2020-07-31  7:53 ` [PATCH 09/11] board: stm32mp1: update fdt fixup partitions table Christophe Kerello
@ 2020-08-13  7:34   ` Patrice CHOTARD
  0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  7:34 UTC (permalink / raw)
  To: u-boot

Hi Christophe

On 7/31/20 9:53 AM, Christophe Kerello wrote:
> This patch adds "st,stm32mp1-fmc2-nfc" compatible string in the
> fdt fixup partitions table.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
>  board/st/stm32mp1/stm32mp1.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
> index 1d274c3..f2f6c99 100644
> --- a/board/st/stm32mp1/stm32mp1.c
> +++ b/board/st/stm32mp1/stm32mp1.c
> @@ -851,6 +851,7 @@ int ft_board_setup(void *blob, struct bd_info *bd)
>  		{ "st,stm32f469-qspi",		MTD_DEV_TYPE_NOR,  },
>  		{ "st,stm32f469-qspi",		MTD_DEV_TYPE_SPINAND},
>  		{ "st,stm32mp15-fmc2",		MTD_DEV_TYPE_NAND, },
> +		{ "st,stm32mp1-fmc2-nfc",	MTD_DEV_TYPE_NAND, },
>  	};
>  	fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
>  #endif

Reviewed-by: Patrice Chotard <patrice.chotard@st.com>

Thanks

Patrice

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 10/11] configs: stm32mp: add CONFIG_STM32_FMC2_EBI
  2020-07-31  7:53 ` [PATCH 10/11] configs: stm32mp: add CONFIG_STM32_FMC2_EBI Christophe Kerello
@ 2020-08-13  7:35   ` Patrice CHOTARD
  2020-08-13  9:59     ` Patrice CHOTARD
  0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  7:35 UTC (permalink / raw)
  To: u-boot

Hi Christophe

On 7/31/20 9:53 AM, Christophe Kerello wrote:
> This patch enables the support of FMC2 EBI.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
>  configs/stm32mp15_basic_defconfig   | 1 +
>  configs/stm32mp15_trusted_defconfig | 1 +
>  2 files changed, 2 insertions(+)
>
> diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig
> index 5c500a1..2094183 100644
> --- a/configs/stm32mp15_basic_defconfig
> +++ b/configs/stm32mp15_basic_defconfig
> @@ -88,6 +88,7 @@ CONFIG_LED=y
>  CONFIG_LED_GPIO=y
>  CONFIG_DM_MAILBOX=y
>  CONFIG_STM32_IPCC=y
> +CONFIG_STM32_FMC2_EBI=y
>  CONFIG_DM_MMC=y
>  CONFIG_SUPPORT_EMMC_BOOT=y
>  CONFIG_STM32_SDMMC2=y
> diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig
> index 98680cb..8d59d84 100644
> --- a/configs/stm32mp15_trusted_defconfig
> +++ b/configs/stm32mp15_trusted_defconfig
> @@ -68,6 +68,7 @@ CONFIG_LED=y
>  CONFIG_LED_GPIO=y
>  CONFIG_DM_MAILBOX=y
>  CONFIG_STM32_IPCC=y
> +CONFIG_STM32_FMC2_EBI=y
>  CONFIG_DM_MMC=y
>  CONFIG_SUPPORT_EMMC_BOOT=y
>  CONFIG_STM32_SDMMC2=y

Reviewed-by: Patrice Chotard <patrice.chotard@st.com>

Thanks

Patrice

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 11/11] ARM: dts: stm32: add FMC2 EBI support for stm32mp157c
  2020-07-31  7:53 ` [PATCH 11/11] ARM: dts: stm32: add FMC2 EBI support for stm32mp157c Christophe Kerello
@ 2020-08-13  7:37   ` Patrice CHOTARD
  2020-08-13  9:59     ` Patrice CHOTARD
  0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  7:37 UTC (permalink / raw)
  To: u-boot

Hi Christophe

On 7/31/20 9:53 AM, Christophe Kerello wrote:
> This patch adds FMC2 External Bus Interface support on stm32mp157c.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
>  arch/arm/dts/stm32mp151.dtsi     | 43 +++++++++++++++++++++++++++-------------
>  arch/arm/dts/stm32mp157c-ev1.dts | 16 ++++++++-------
>  2 files changed, 38 insertions(+), 21 deletions(-)
>
> diff --git a/arch/arm/dts/stm32mp151.dtsi b/arch/arm/dts/stm32mp151.dtsi
> index 0d97f56..39d9e54 100644
> --- a/arch/arm/dts/stm32mp151.dtsi
> +++ b/arch/arm/dts/stm32mp151.dtsi
> @@ -1328,23 +1328,38 @@
>  			dma-requests = <48>;
>  		};
>  
> -		fmc: nand-controller at 58002000 {
> -			compatible = "st,stm32mp15-fmc2";
> -			reg = <0x58002000 0x1000>,
> -			      <0x80000000 0x1000>,
> -			      <0x88010000 0x1000>,
> -			      <0x88020000 0x1000>,
> -			      <0x81000000 0x1000>,
> -			      <0x89010000 0x1000>,
> -			      <0x89020000 0x1000>;
> -			interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
> -			dmas = <&mdma1 20 0x10 0x12000a02 0x0 0x0>,
> -			       <&mdma1 20 0x10 0x12000a08 0x0 0x0>,
> -			       <&mdma1 21 0x10 0x12000a0a 0x0 0x0>;
> -			dma-names = "tx", "rx", "ecc";
> +		fmc: memory-controller at 58002000 {
> +			#address-cells = <2>;
> +			#size-cells = <1>;
> +			compatible = "st,stm32mp1-fmc2-ebi";
> +			reg = <0x58002000 0x1000>;
>  			clocks = <&rcc FMC_K>;
>  			resets = <&rcc FMC_R>;
>  			status = "disabled";
> +
> +			ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */
> +				 <1 0 0x64000000 0x04000000>, /* EBI CS 2 */
> +				 <2 0 0x68000000 0x04000000>, /* EBI CS 3 */
> +				 <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */
> +				 <4 0 0x80000000 0x10000000>; /* NAND */
> +
> +			nand-controller at 4,0 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				compatible = "st,stm32mp1-fmc2-nfc";
> +				reg = <4 0x00000000 0x1000>,
> +				      <4 0x08010000 0x1000>,
> +				      <4 0x08020000 0x1000>,
> +				      <4 0x01000000 0x1000>,
> +				      <4 0x09010000 0x1000>,
> +				      <4 0x09020000 0x1000>;
> +				interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
> +				dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
> +				       <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
> +				       <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
> +				dma-names = "tx", "rx", "ecc";
> +				status = "disabled";
> +			};
>  		};
>  
>  		qspi: spi at 58003000 {
> diff --git a/arch/arm/dts/stm32mp157c-ev1.dts b/arch/arm/dts/stm32mp157c-ev1.dts
> index b190565..46f81ce 100644
> --- a/arch/arm/dts/stm32mp157c-ev1.dts
> +++ b/arch/arm/dts/stm32mp157c-ev1.dts
> @@ -157,14 +157,16 @@
>  	pinctrl-0 = <&fmc_pins_a>;
>  	pinctrl-1 = <&fmc_sleep_pins_a>;
>  	status = "okay";
> -	#address-cells = <1>;
> -	#size-cells = <0>;
>  
> -	nand at 0 {
> -		reg = <0>;
> -		nand-on-flash-bbt;
> -		#address-cells = <1>;
> -		#size-cells = <1>;
> +	nand-controller at 4,0 {
> +		status = "okay";
> +
> +		nand at 0 {
> +			reg = <0>;
> +			nand-on-flash-bbt;
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +		};
>  	};
>  };
>  

Reviewed-by: Patrice Chotard <patrice.chotard@st.com>

Thanks

Patrice

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 01/11] mtd: rawnand: stm32_fmc2: fix a buffer overflow
  2020-08-13  7:27   ` Patrice CHOTARD
@ 2020-08-13  9:56     ` Patrice CHOTARD
  0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  9:56 UTC (permalink / raw)
  To: u-boot


On 8/13/20 9:27 AM, Patrice CHOTARD wrote:
> Hi Christpohe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> The chip select defined in the device tree could only be 0 or 1.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied on u-boot-stm/master

Thanks

>>
>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> index 3306bd8..2929acf 100644
>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> @@ -846,7 +846,7 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
>>  	}
>>  
>>  	for (i = 0; i < nand->ncs; i++) {
>> -		if (cs[i] > FMC2_MAX_CE) {
>> +		if (cs[i] >= FMC2_MAX_CE) {
>>  			pr_err("Invalid reg value: %d\n",
>>  			       nand->cs_used[i]);
>>  			return -EINVAL;
> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
>
> Thanks
>
> Patrice
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 02/11] mtd: rawnand: stm32_fmc2: remove useless inline comments
  2020-08-13  7:28   ` Patrice CHOTARD
@ 2020-08-13  9:56     ` Patrice CHOTARD
  0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  9:56 UTC (permalink / raw)
  To: u-boot


On 8/13/20 9:28 AM, Patrice CHOTARD wrote:
> Hi Christophe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> Remove inline comments that are useless since function label are
>> self explanatory.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 25 -------------------------
>>  1 file changed, 25 deletions(-)

Applied on u-boot-stm/master

Thanks

>>
>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> index 2929acf..f43e3ec 100644
>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> @@ -179,7 +179,6 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_hw_control *base)
>>  	return container_of(base, struct stm32_fmc2_nfc, base);
>>  }
>>  
>> -/* Timings configuration */
>>  static void stm32_fmc2_timings_init(struct nand_chip *chip)
>>  {
>>  	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
>> @@ -211,7 +210,6 @@ static void stm32_fmc2_timings_init(struct nand_chip *chip)
>>  	writel(patt, fmc2->io_base + FMC2_PATT);
>>  }
>>  
>> -/* Controller configuration */
>>  static void stm32_fmc2_setup(struct nand_chip *chip)
>>  {
>>  	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
>> @@ -239,7 +237,6 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
>>  	writel(pcr, fmc2->io_base + FMC2_PCR);
>>  }
>>  
>> -/* Select target */
>>  static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
>>  {
>>  	struct nand_chip *chip = mtd_to_nand(mtd);
>> @@ -256,14 +253,10 @@ static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
>>  	chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel];
>>  	chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel];
>>  
>> -	/* FMC2 setup routine */
>>  	stm32_fmc2_setup(chip);
>> -
>> -	/* Apply timings */
>>  	stm32_fmc2_timings_init(chip);
>>  }
>>  
>> -/* Set bus width to 16-bit or 8-bit */
>>  static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
>>  {
>>  	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
>> @@ -274,7 +267,6 @@ static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
>>  	writel(pcr, fmc2->io_base + FMC2_PCR);
>>  }
>>  
>> -/* Enable/disable ECC */
>>  static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
>>  {
>>  	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
>> @@ -285,13 +277,11 @@ static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
>>  	writel(pcr, fmc2->io_base + FMC2_PCR);
>>  }
>>  
>> -/* Clear irq sources in case of bch is used */
>>  static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
>>  {
>>  	writel(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
>>  }
>>  
>> -/* Send command and address cycles */
>>  static void stm32_fmc2_cmd_ctrl(struct mtd_info *mtd, int cmd,
>>  				unsigned int ctrl)
>>  {
>> @@ -361,7 +351,6 @@ static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
>>  	ecc[1] = heccr >> 8;
>>  	ecc[2] = heccr >> 16;
>>  
>> -	/* Disable ecc */
>>  	stm32_fmc2_set_ecc(fmc2, false);
>>  
>>  	return 0;
>> @@ -466,13 +455,11 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
>>  		ecc[12] = bchpbr;
>>  	}
>>  
>> -	/* Disable ecc */
>>  	stm32_fmc2_set_ecc(fmc2, false);
>>  
>>  	return 0;
>>  }
>>  
>> -/* BCH algorithm correction */
>>  static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
>>  				  u8 *read_ecc, u8 *calc_ecc)
>>  {
>> @@ -497,7 +484,6 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
>>  	bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3);
>>  	bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4);
>>  
>> -	/* Disable ECC */
>>  	stm32_fmc2_set_ecc(fmc2, false);
>>  
>>  	/* No errors found */
>> @@ -579,7 +565,6 @@ static int stm32_fmc2_read_page(struct mtd_info *mtd,
>>  	return max_bitflips;
>>  }
>>  
>> -/* Controller initialization */
>>  static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
>>  {
>>  	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
>> @@ -622,7 +607,6 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
>>  	writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
>>  }
>>  
>> -/* Controller timings */
>>  static void stm32_fmc2_calc_timings(struct nand_chip *chip,
>>  				    const struct nand_sdr_timings *sdrt)
>>  {
>> @@ -768,13 +752,11 @@ static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr,
>>  
>>  	stm32_fmc2_calc_timings(chip, sdrt);
>>  
>> -	/* Apply timings */
>>  	stm32_fmc2_timings_init(chip);
>>  
>>  	return 0;
>>  }
>>  
>> -/* NAND callbacks setup */
>>  static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
>>  {
>>  	chip->ecc.hwctl = stm32_fmc2_hwctl;
>> @@ -803,7 +785,6 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
>>  		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
>>  }
>>  
>> -/* FMC2 caps */
>>  static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
>>  {
>>  	/* Hamming */
>> @@ -822,7 +803,6 @@ NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
>>  		     FMC2_ECC_STEP_SIZE,
>>  		     FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
>>  
>> -/* FMC2 probe */
>>  static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
>>  				  ofnode node)
>>  {
>> @@ -969,7 +949,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
>>  		reset_deassert(&reset);
>>  	}
>>  
>> -	/* FMC2 init routine */
>>  	stm32_fmc2_init(fmc2);
>>  
>>  	chip->controller = &fmc2->base;
>> @@ -985,7 +964,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
>>  	chip->ecc.size = FMC2_ECC_STEP_SIZE;
>>  	chip->ecc.strength = FMC2_ECC_BCH8;
>>  
>> -	/* Scan to find existence of the device */
>>  	ret = nand_scan_ident(mtd, nand->ncs, NULL);
>>  	if (ret)
>>  		return ret;
>> @@ -1012,7 +990,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
>>  	if (chip->bbt_options & NAND_BBT_USE_FLASH)
>>  		chip->bbt_options |= NAND_BBT_NO_OOB;
>>  
>> -	/* NAND callbacks setup */
>>  	stm32_fmc2_nand_callbacks_setup(chip);
>>  
>>  	/* Define ECC layout */
>> @@ -1026,11 +1003,9 @@ static int stm32_fmc2_probe(struct udevice *dev)
>>  	ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
>>  	chip->ecc.layout = ecclayout;
>>  
>> -	/* Configure bus width to 16-bit */
>>  	if (chip->options & NAND_BUSWIDTH_16)
>>  		stm32_fmc2_set_buswidth_16(fmc2, true);
>>  
>> -	/* Scan the device to fill MTD data-structures */
>>  	ret = nand_scan_tail(mtd);
>>  	if (ret)
>>  		return ret;
> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
>
> Thanks
>
> Patrice
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 04/11] mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2 where relevant
  2020-07-31  7:53 ` [PATCH 04/11] mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2 where relevant Christophe Kerello
  2020-08-13  7:29   ` Patrice CHOTARD
@ 2020-08-13  9:57   ` Patrice CHOTARD
  1 sibling, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  9:57 UTC (permalink / raw)
  To: u-boot


On 7/31/20 9:53 AM, Christophe Kerello wrote:
> This patch renames functions and local variables.
> This cleanup is done to get all functions starting by stm32_fmc2_nfc
> in the FMC2 raw NAND driver when all functions will start by
> stm32_fmc2_ebi in the FMC2 EBI driver.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 263 ++++++++++++++++-----------------
>  1 file changed, 131 insertions(+), 132 deletions(-)

Applied on u-boot-stm/master

Thanks

>
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index 2e947a3..9718bae 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -181,12 +181,12 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_hw_control *base)
>  	return container_of(base, struct stm32_fmc2_nfc, base);
>  }
>  
> -static void stm32_fmc2_timings_init(struct nand_chip *chip)
> +static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
>  {
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>  	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
>  	struct stm32_fmc2_timings *timings = &nand->timings;
> -	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> +	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>  	u32 pmem, patt;
>  
>  	/* Set tclr/tar timings */
> @@ -207,15 +207,15 @@ static void stm32_fmc2_timings_init(struct nand_chip *chip)
>  	patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
>  	patt |= FMC2_PATT_ATTHIZ(timings->thiz);
>  
> -	writel(pcr, fmc2->io_base + FMC2_PCR);
> -	writel(pmem, fmc2->io_base + FMC2_PMEM);
> -	writel(patt, fmc2->io_base + FMC2_PATT);
> +	writel(pcr, nfc->io_base + FMC2_PCR);
> +	writel(pmem, nfc->io_base + FMC2_PMEM);
> +	writel(patt, nfc->io_base + FMC2_PATT);
>  }
>  
> -static void stm32_fmc2_setup(struct nand_chip *chip)
> +static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
>  {
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> -	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> +	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>  
>  	/* Configure ECC algorithm (default configuration is Hamming) */
>  	pcr &= ~FMC2_PCR_ECCALG;
> @@ -236,95 +236,96 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
>  	pcr &= ~FMC2_PCR_ECCSS_MASK;
>  	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
>  
> -	writel(pcr, fmc2->io_base + FMC2_PCR);
> +	writel(pcr, nfc->io_base + FMC2_PCR);
>  }
>  
> -static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
> +static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>  	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
>  
>  	if (chipnr < 0 || chipnr >= nand->ncs)
>  		return;
>  
> -	if (nand->cs_used[chipnr] == fmc2->cs_sel)
> +	if (nand->cs_used[chipnr] == nfc->cs_sel)
>  		return;
>  
> -	fmc2->cs_sel = nand->cs_used[chipnr];
> -	chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel];
> -	chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel];
> +	nfc->cs_sel = nand->cs_used[chipnr];
> +	chip->IO_ADDR_R = nfc->data_base[nfc->cs_sel];
> +	chip->IO_ADDR_W = nfc->data_base[nfc->cs_sel];
>  
> -	stm32_fmc2_setup(chip);
> -	stm32_fmc2_timings_init(chip);
> +	stm32_fmc2_nfc_setup(chip);
> +	stm32_fmc2_nfc_timings_init(chip);
>  }
>  
> -static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
> +static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
> +					   bool set)
>  {
> -	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> +	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>  
>  	pcr &= ~FMC2_PCR_PWID_MASK;
>  	if (set)
>  		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
> -	writel(pcr, fmc2->io_base + FMC2_PCR);
> +	writel(pcr, nfc->io_base + FMC2_PCR);
>  }
>  
> -static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
> +static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
>  {
> -	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> +	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>  
>  	pcr &= ~FMC2_PCR_ECCEN;
>  	if (enable)
>  		pcr |= FMC2_PCR_ECCEN;
> -	writel(pcr, fmc2->io_base + FMC2_PCR);
> +	writel(pcr, nfc->io_base + FMC2_PCR);
>  }
>  
> -static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
> +static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
>  {
> -	writel(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
> +	writel(FMC2_BCHICR_CLEAR_IRQ, nfc->io_base + FMC2_BCHICR);
>  }
>  
> -static void stm32_fmc2_cmd_ctrl(struct mtd_info *mtd, int cmd,
> -				unsigned int ctrl)
> +static void stm32_fmc2_nfc_cmd_ctrl(struct mtd_info *mtd, int cmd,
> +				    unsigned int ctrl)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>  
>  	if (cmd == NAND_CMD_NONE)
>  		return;
>  
>  	if (ctrl & NAND_CLE) {
> -		writeb(cmd, fmc2->cmd_base[fmc2->cs_sel]);
> +		writeb(cmd, nfc->cmd_base[nfc->cs_sel]);
>  		return;
>  	}
>  
> -	writeb(cmd, fmc2->addr_base[fmc2->cs_sel]);
> +	writeb(cmd, nfc->addr_base[nfc->cs_sel]);
>  }
>  
>  /*
>   * Enable ECC logic and reset syndrome/parity bits previously calculated
>   * Syndrome/parity bits is cleared by setting the ECCEN bit to 0
>   */
> -static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
> +static void stm32_fmc2_nfc_hwctl(struct mtd_info *mtd, int mode)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>  
> -	stm32_fmc2_set_ecc(fmc2, false);
> +	stm32_fmc2_nfc_set_ecc(nfc, false);
>  
>  	if (chip->ecc.strength != FMC2_ECC_HAM) {
> -		u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> +		u32 pcr = readl(nfc->io_base + FMC2_PCR);
>  
>  		if (mode == NAND_ECC_WRITE)
>  			pcr |= FMC2_PCR_WEN;
>  		else
>  			pcr &= ~FMC2_PCR_WEN;
> -		writel(pcr, fmc2->io_base + FMC2_PCR);
> +		writel(pcr, nfc->io_base + FMC2_PCR);
>  
> -		stm32_fmc2_clear_bch_irq(fmc2);
> +		stm32_fmc2_nfc_clear_bch_irq(nfc);
>  	}
>  
> -	stm32_fmc2_set_ecc(fmc2, true);
> +	stm32_fmc2_nfc_set_ecc(nfc, true);
>  }
>  
>  /*
> @@ -332,34 +333,34 @@ static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
>   * ECC is 3 bytes for 512 bytes of data (supports error correction up to
>   * max of 1-bit)
>   */
> -static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
> -				    u8 *ecc)
> +static int stm32_fmc2_nfc_ham_calculate(struct mtd_info *mtd, const u8 *data,
> +					u8 *ecc)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>  	u32 heccr, sr;
>  	int ret;
>  
> -	ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr,
> +	ret = readl_poll_timeout(nfc->io_base + FMC2_SR, sr,
>  				 sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
>  	if (ret < 0) {
>  		pr_err("Ham timeout\n");
>  		return ret;
>  	}
>  
> -	heccr = readl(fmc2->io_base + FMC2_HECCR);
> +	heccr = readl(nfc->io_base + FMC2_HECCR);
>  
>  	ecc[0] = heccr;
>  	ecc[1] = heccr >> 8;
>  	ecc[2] = heccr >> 16;
>  
> -	stm32_fmc2_set_ecc(fmc2, false);
> +	stm32_fmc2_nfc_set_ecc(nfc, false);
>  
>  	return 0;
>  }
>  
> -static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
> -				  u8 *read_ecc, u8 *calc_ecc)
> +static int stm32_fmc2_nfc_ham_correct(struct mtd_info *mtd, u8 *dat,
> +				      u8 *read_ecc, u8 *calc_ecc)
>  {
>  	u8 bit_position = 0, b0, b1, b2;
>  	u32 byte_addr = 0, b;
> @@ -416,16 +417,16 @@ static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
>   * max of 4-bit/8-bit)
>   */
>  
> -static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
> -				    u8 *ecc)
> +static int stm32_fmc2_nfc_bch_calculate(struct mtd_info *mtd, const u8 *data,
> +					u8 *ecc)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>  	u32 bchpbr, bchisr;
>  	int ret;
>  
>  	/* Wait until the BCH code is ready */
> -	ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
> +	ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
>  				 bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
>  	if (ret < 0) {
>  		pr_err("Bch timeout\n");
> @@ -433,13 +434,13 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
>  	}
>  
>  	/* Read parity bits */
> -	bchpbr = readl(fmc2->io_base + FMC2_BCHPBR1);
> +	bchpbr = readl(nfc->io_base + FMC2_BCHPBR1);
>  	ecc[0] = bchpbr;
>  	ecc[1] = bchpbr >> 8;
>  	ecc[2] = bchpbr >> 16;
>  	ecc[3] = bchpbr >> 24;
>  
> -	bchpbr = readl(fmc2->io_base + FMC2_BCHPBR2);
> +	bchpbr = readl(nfc->io_base + FMC2_BCHPBR2);
>  	ecc[4] = bchpbr;
>  	ecc[5] = bchpbr >> 8;
>  	ecc[6] = bchpbr >> 16;
> @@ -447,46 +448,46 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
>  	if (chip->ecc.strength == FMC2_ECC_BCH8) {
>  		ecc[7] = bchpbr >> 24;
>  
> -		bchpbr = readl(fmc2->io_base + FMC2_BCHPBR3);
> +		bchpbr = readl(nfc->io_base + FMC2_BCHPBR3);
>  		ecc[8] = bchpbr;
>  		ecc[9] = bchpbr >> 8;
>  		ecc[10] = bchpbr >> 16;
>  		ecc[11] = bchpbr >> 24;
>  
> -		bchpbr = readl(fmc2->io_base + FMC2_BCHPBR4);
> +		bchpbr = readl(nfc->io_base + FMC2_BCHPBR4);
>  		ecc[12] = bchpbr;
>  	}
>  
> -	stm32_fmc2_set_ecc(fmc2, false);
> +	stm32_fmc2_nfc_set_ecc(nfc, false);
>  
>  	return 0;
>  }
>  
> -static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
> -				  u8 *read_ecc, u8 *calc_ecc)
> +static int stm32_fmc2_nfc_bch_correct(struct mtd_info *mtd, u8 *dat,
> +				      u8 *read_ecc, u8 *calc_ecc)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>  	u32 bchdsr0, bchdsr1, bchdsr2, bchdsr3, bchdsr4, bchisr;
>  	u16 pos[8];
>  	int i, ret, den, eccsize = chip->ecc.size;
>  	unsigned int nb_errs = 0;
>  
>  	/* Wait until the decoding error is ready */
> -	ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
> +	ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
>  				 bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
>  	if (ret < 0) {
>  		pr_err("Bch timeout\n");
>  		return ret;
>  	}
>  
> -	bchdsr0 = readl(fmc2->io_base + FMC2_BCHDSR0);
> -	bchdsr1 = readl(fmc2->io_base + FMC2_BCHDSR1);
> -	bchdsr2 = readl(fmc2->io_base + FMC2_BCHDSR2);
> -	bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3);
> -	bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4);
> +	bchdsr0 = readl(nfc->io_base + FMC2_BCHDSR0);
> +	bchdsr1 = readl(nfc->io_base + FMC2_BCHDSR1);
> +	bchdsr2 = readl(nfc->io_base + FMC2_BCHDSR2);
> +	bchdsr3 = readl(nfc->io_base + FMC2_BCHDSR3);
> +	bchdsr4 = readl(nfc->io_base + FMC2_BCHDSR4);
>  
> -	stm32_fmc2_set_ecc(fmc2, false);
> +	stm32_fmc2_nfc_set_ecc(nfc, false);
>  
>  	/* No errors found */
>  	if (likely(!(bchdsr0 & FMC2_BCHDSR0_DEF)))
> @@ -516,9 +517,9 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
>  	return nb_errs;
>  }
>  
> -static int stm32_fmc2_read_page(struct mtd_info *mtd,
> -				struct nand_chip *chip, u8 *buf,
> -				int oob_required, int page)
> +static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
> +				    struct nand_chip *chip, u8 *buf,
> +				    int oob_required, int page)
>  {
>  	int i, s, stat, eccsize = chip->ecc.size;
>  	int eccbytes = chip->ecc.bytes;
> @@ -567,13 +568,13 @@ static int stm32_fmc2_read_page(struct mtd_info *mtd,
>  	return max_bitflips;
>  }
>  
> -static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
> +static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>  {
> -	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> -	u32 bcr1 = readl(fmc2->io_base + FMC2_BCR1);
> +	u32 pcr = readl(nfc->io_base + FMC2_PCR);
> +	u32 bcr1 = readl(nfc->io_base + FMC2_BCR1);
>  
>  	/* Set CS used to undefined */
> -	fmc2->cs_sel = -1;
> +	nfc->cs_sel = -1;
>  
>  	/* Enable wait feature and nand flash memory bank */
>  	pcr |= FMC2_PCR_PWAITEN;
> @@ -603,19 +604,19 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
>  	/* Enable FMC2 controller */
>  	bcr1 |= FMC2_BCR1_FMC2EN;
>  
> -	writel(bcr1, fmc2->io_base + FMC2_BCR1);
> -	writel(pcr, fmc2->io_base + FMC2_PCR);
> -	writel(FMC2_PMEM_DEFAULT, fmc2->io_base + FMC2_PMEM);
> -	writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
> +	writel(bcr1, nfc->io_base + FMC2_BCR1);
> +	writel(pcr, nfc->io_base + FMC2_PCR);
> +	writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
> +	writel(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);
>  }
>  
> -static void stm32_fmc2_calc_timings(struct nand_chip *chip,
> -				    const struct nand_sdr_timings *sdrt)
> +static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip,
> +					const struct nand_sdr_timings *sdrt)
>  {
> -	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> +	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>  	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
>  	struct stm32_fmc2_timings *tims = &nand->timings;
> -	unsigned long hclk = clk_get_rate(&fmc2->clk);
> +	unsigned long hclk = clk_get_rate(&nfc->clk);
>  	unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
>  	unsigned long timing, tar, tclr, thiz, twait;
>  	unsigned long tset_mem, tset_att, thold_mem, thold_att;
> @@ -739,29 +740,28 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
>  	tims->thold_att = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
>  }
>  
> -static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr,
> -				      const struct nand_data_interface *conf)
> +static int stm32_fmc2_nfc_setup_interface(struct mtd_info *mtd, int chipnr,
> +					  const struct nand_data_interface *cf)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
>  	const struct nand_sdr_timings *sdrt;
>  
> -	sdrt = nand_get_sdr_timings(conf);
> +	sdrt = nand_get_sdr_timings(cf);
>  	if (IS_ERR(sdrt))
>  		return PTR_ERR(sdrt);
>  
>  	if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
>  		return 0;
>  
> -	stm32_fmc2_calc_timings(chip, sdrt);
> -
> -	stm32_fmc2_timings_init(chip);
> +	stm32_fmc2_nfc_calc_timings(chip, sdrt);
> +	stm32_fmc2_nfc_timings_init(chip);
>  
>  	return 0;
>  }
>  
> -static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
> +static void stm32_fmc2_nfc_nand_callbacks_setup(struct nand_chip *chip)
>  {
> -	chip->ecc.hwctl = stm32_fmc2_hwctl;
> +	chip->ecc.hwctl = stm32_fmc2_nfc_hwctl;
>  
>  	/*
>  	 * Specific callbacks to read/write a page depending on
> @@ -769,17 +769,17 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
>  	 */
>  	if (chip->ecc.strength == FMC2_ECC_HAM) {
>  		/* Hamming is used */
> -		chip->ecc.calculate = stm32_fmc2_ham_calculate;
> -		chip->ecc.correct = stm32_fmc2_ham_correct;
> +		chip->ecc.calculate = stm32_fmc2_nfc_ham_calculate;
> +		chip->ecc.correct = stm32_fmc2_nfc_ham_correct;
>  		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 4 : 3;
>  		chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK;
>  		return;
>  	}
>  
>  	/* BCH is used */
> -	chip->ecc.read_page = stm32_fmc2_read_page;
> -	chip->ecc.calculate = stm32_fmc2_bch_calculate;
> -	chip->ecc.correct = stm32_fmc2_bch_correct;
> +	chip->ecc.read_page = stm32_fmc2_nfc_read_page;
> +	chip->ecc.calculate = stm32_fmc2_nfc_bch_calculate;
> +	chip->ecc.correct = stm32_fmc2_nfc_bch_correct;
>  
>  	if (chip->ecc.strength == FMC2_ECC_BCH8)
>  		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 14 : 13;
> @@ -787,7 +787,7 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
>  		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
>  }
>  
> -static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
> +static int stm32_fmc2_nfc_calc_ecc_bytes(int step_size, int strength)
>  {
>  	/* Hamming */
>  	if (strength == FMC2_ECC_HAM)
> @@ -801,14 +801,13 @@ static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
>  	return 8;
>  }
>  
> -NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
> +NAND_ECC_CAPS_SINGLE(stm32_fmc2_nfc_ecc_caps, stm32_fmc2_nfc_calc_ecc_bytes,
>  		     FMC2_ECC_STEP_SIZE,
>  		     FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
>  
> -static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
> -				  ofnode node)
> +static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, ofnode node)
>  {
> -	struct stm32_fmc2_nand *nand = &fmc2->nand;
> +	struct stm32_fmc2_nand *nand = &nfc->nand;
>  	u32 cs[FMC2_MAX_CE];
>  	int ret, i;
>  
> @@ -834,13 +833,13 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
>  			return -EINVAL;
>  		}
>  
> -		if (fmc2->cs_assigned & BIT(cs[i])) {
> +		if (nfc->cs_assigned & BIT(cs[i])) {
>  			pr_err("Cs already assigned: %d\n",
>  			       nand->cs_used[i]);
>  			return -EINVAL;
>  		}
>  
> -		fmc2->cs_assigned |= BIT(cs[i]);
> +		nfc->cs_assigned |= BIT(cs[i]);
>  		nand->cs_used[i] = cs[i];
>  	}
>  
> @@ -849,8 +848,8 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
>  	return 0;
>  }
>  
> -static int stm32_fmc2_parse_dt(struct udevice *dev,
> -			       struct stm32_fmc2_nfc *fmc2)
> +static int stm32_fmc2_nfc_parse_dt(struct udevice *dev,
> +				   struct stm32_fmc2_nfc *nfc)
>  {
>  	ofnode child;
>  	int ret, nchips = 0;
> @@ -869,7 +868,7 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
>  	}
>  
>  	dev_for_each_subnode(child, dev) {
> -		ret = stm32_fmc2_parse_child(fmc2, child);
> +		ret = stm32_fmc2_nfc_parse_child(nfc, child);
>  		if (ret)
>  			return ret;
>  	}
> @@ -877,10 +876,10 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
>  	return 0;
>  }
>  
> -static int stm32_fmc2_probe(struct udevice *dev)
> +static int stm32_fmc2_nfc_probe(struct udevice *dev)
>  {
> -	struct stm32_fmc2_nfc *fmc2 = dev_get_priv(dev);
> -	struct stm32_fmc2_nand *nand = &fmc2->nand;
> +	struct stm32_fmc2_nfc *nfc = dev_get_priv(dev);
> +	struct stm32_fmc2_nand *nand = &nfc->nand;
>  	struct nand_chip *chip = &nand->chip;
>  	struct mtd_info *mtd = &chip->mtd;
>  	struct nand_ecclayout *ecclayout;
> @@ -889,10 +888,10 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  	int oob_index, chip_cs, mem_region, ret;
>  	unsigned int i;
>  
> -	spin_lock_init(&fmc2->controller.lock);
> -	init_waitqueue_head(&fmc2->controller.wq);
> +	spin_lock_init(&nfc->controller.lock);
> +	init_waitqueue_head(&nfc->controller.wq);
>  
> -	ret = stm32_fmc2_parse_dt(dev, fmc2);
> +	ret = stm32_fmc2_nfc_parse_dt(dev, nfc);
>  	if (ret)
>  		return ret;
>  
> @@ -902,11 +901,11 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  		pr_err("Resource io_base not found");
>  		return ret;
>  	}
> -	fmc2->io_base = (void __iomem *)resource.start;
> +	nfc->io_base = (void __iomem *)resource.start;
>  
>  	for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
>  	     chip_cs++, mem_region += 3) {
> -		if (!(fmc2->cs_assigned & BIT(chip_cs)))
> +		if (!(nfc->cs_assigned & BIT(chip_cs)))
>  			continue;
>  
>  		ret = dev_read_resource(dev, mem_region, &resource);
> @@ -915,7 +914,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  			       chip_cs);
>  			return ret;
>  		}
> -		fmc2->data_base[chip_cs] = (void __iomem *)resource.start;
> +		nfc->data_base[chip_cs] = (void __iomem *)resource.start;
>  
>  		ret = dev_read_resource(dev, mem_region + 1, &resource);
>  		if (ret) {
> @@ -923,7 +922,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  			       chip_cs);
>  			return ret;
>  		}
> -		fmc2->cmd_base[chip_cs] = (void __iomem *)resource.start;
> +		nfc->cmd_base[chip_cs] = (void __iomem *)resource.start;
>  
>  		ret = dev_read_resource(dev, mem_region + 2, &resource);
>  		if (ret) {
> @@ -931,15 +930,15 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  			       chip_cs);
>  			return ret;
>  		}
> -		fmc2->addr_base[chip_cs] = (void __iomem *)resource.start;
> +		nfc->addr_base[chip_cs] = (void __iomem *)resource.start;
>  	}
>  
>  	/* Enable the clock */
> -	ret = clk_get_by_index(dev, 0, &fmc2->clk);
> +	ret = clk_get_by_index(dev, 0, &nfc->clk);
>  	if (ret)
>  		return ret;
>  
> -	ret = clk_enable(&fmc2->clk);
> +	ret = clk_enable(&nfc->clk);
>  	if (ret)
>  		return ret;
>  
> @@ -951,12 +950,12 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  		reset_deassert(&reset);
>  	}
>  
> -	stm32_fmc2_init(fmc2);
> +	stm32_fmc2_nfc_init(nfc);
>  
> -	chip->controller = &fmc2->base;
> -	chip->select_chip = stm32_fmc2_select_chip;
> -	chip->setup_data_interface = stm32_fmc2_setup_interface;
> -	chip->cmd_ctrl = stm32_fmc2_cmd_ctrl;
> +	chip->controller = &nfc->base;
> +	chip->select_chip = stm32_fmc2_nfc_select_chip;
> +	chip->setup_data_interface = stm32_fmc2_nfc_setup_interface;
> +	chip->cmd_ctrl = stm32_fmc2_nfc_cmd_ctrl;
>  	chip->chip_delay = FMC2_RB_DELAY_US;
>  	chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE |
>  			 NAND_USE_BOUNCE_BUFFER;
> @@ -982,7 +981,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  		return -EINVAL;
>  	}
>  
> -	ret = nand_check_ecc_caps(chip, &stm32_fmc2_ecc_caps,
> +	ret = nand_check_ecc_caps(chip, &stm32_fmc2_nfc_ecc_caps,
>  				  mtd->oobsize - FMC2_BBM_LEN);
>  	if (ret) {
>  		pr_err("No valid ECC settings set\n");
> @@ -992,10 +991,10 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  	if (chip->bbt_options & NAND_BBT_USE_FLASH)
>  		chip->bbt_options |= NAND_BBT_NO_OOB;
>  
> -	stm32_fmc2_nand_callbacks_setup(chip);
> +	stm32_fmc2_nfc_nand_callbacks_setup(chip);
>  
>  	/* Define ECC layout */
> -	ecclayout = &fmc2->ecclayout;
> +	ecclayout = &nfc->ecclayout;
>  	ecclayout->eccbytes = chip->ecc.bytes *
>  			      (mtd->writesize / chip->ecc.size);
>  	oob_index = FMC2_BBM_LEN;
> @@ -1006,7 +1005,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  	chip->ecc.layout = ecclayout;
>  
>  	if (chip->options & NAND_BUSWIDTH_16)
> -		stm32_fmc2_set_buswidth_16(fmc2, true);
> +		stm32_fmc2_nfc_set_buswidth_16(nfc, true);
>  
>  	ret = nand_scan_tail(mtd);
>  	if (ret)
> @@ -1015,16 +1014,16 @@ static int stm32_fmc2_probe(struct udevice *dev)
>  	return nand_register(0, mtd);
>  }
>  
> -static const struct udevice_id stm32_fmc2_match[] = {
> +static const struct udevice_id stm32_fmc2_nfc_match[] = {
>  	{ .compatible = "st,stm32mp15-fmc2" },
>  	{ /* Sentinel */ }
>  };
>  
> -U_BOOT_DRIVER(stm32_fmc2_nand) = {
> -	.name = "stm32_fmc2_nand",
> +U_BOOT_DRIVER(stm32_fmc2_nfc) = {
> +	.name = "stm32_fmc2_nfc",
>  	.id = UCLASS_MTD,
> -	.of_match = stm32_fmc2_match,
> -	.probe = stm32_fmc2_probe,
> +	.of_match = stm32_fmc2_nfc_match,
> +	.probe = stm32_fmc2_nfc_probe,
>  	.priv_auto_alloc_size = sizeof(struct stm32_fmc2_nfc),
>  };
>  
> @@ -1034,9 +1033,9 @@ void board_nand_init(void)
>  	int ret;
>  
>  	ret = uclass_get_device_by_driver(UCLASS_MTD,
> -					  DM_GET_DRIVER(stm32_fmc2_nand),
> +					  DM_GET_DRIVER(stm32_fmc2_nfc),
>  					  &dev);
>  	if (ret && ret != -ENODEV)
> -		pr_err("Failed to initialize STM32 FMC2 NAND controller. (error %d)\n",
> +		pr_err("Failed to initialize STM32 FMC2 NFC controller. (error %d)\n",
>  		       ret);
>  }

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 03/11] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_5S for timeouts
  2020-08-13  7:29   ` Patrice CHOTARD
@ 2020-08-13  9:57     ` Patrice CHOTARD
  0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  9:57 UTC (permalink / raw)
  To: u-boot


On 8/13/20 9:29 AM, Patrice CHOTARD wrote:
> Hi Christophe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> FMC2_TIMEOUT_5S will be used each time that we need to wait.
>> It was seen, during stress tests in an overloaded system,
>> that we could be close to 1 second, even if we never met this
>> value. To be safe, FMC2_TIMEOUT_MS is set to 5 seconds.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 8 +++++---
>>  1 file changed, 5 insertions(+), 3 deletions(-)

Applied on u-boot-stm/master

Thanks

>>
>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> index f43e3ec..2e947a3 100644
>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> @@ -131,6 +131,8 @@
>>  
>>  #define FMC2_NSEC_PER_SEC		1000000000L
>>  
>> +#define FMC2_TIMEOUT_5S			5000000
>> +
>>  enum stm32_fmc2_ecc {
>>  	FMC2_ECC_HAM = 1,
>>  	FMC2_ECC_BCH4 = 4,
>> @@ -339,7 +341,7 @@ static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
>>  	int ret;
>>  
>>  	ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr,
>> -				 sr & FMC2_SR_NWRF, 10000);
>> +				 sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
>>  	if (ret < 0) {
>>  		pr_err("Ham timeout\n");
>>  		return ret;
>> @@ -424,7 +426,7 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
>>  
>>  	/* Wait until the BCH code is ready */
>>  	ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
>> -				 bchisr & FMC2_BCHISR_EPBRF, 10000);
>> +				 bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
>>  	if (ret < 0) {
>>  		pr_err("Bch timeout\n");
>>  		return ret;
>> @@ -472,7 +474,7 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
>>  
>>  	/* Wait until the decoding error is ready */
>>  	ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
>> -				 bchisr & FMC2_BCHISR_DERF, 10000);
>> +				 bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
>>  	if (ret < 0) {
>>  		pr_err("Bch timeout\n");
>>  		return ret;
> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
>
> Thanks
>
> Patrice
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 05/11] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros
  2020-08-13  7:29   ` Patrice CHOTARD
@ 2020-08-13  9:58     ` Patrice CHOTARD
  0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  9:58 UTC (permalink / raw)
  To: u-boot


On 8/13/20 9:29 AM, Patrice CHOTARD wrote:
> Hi Christophe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> This patch removes custom macros and uses FIELD_PREP and FIELD_GET macros.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 120 +++++++++++++++------------------
>>  1 file changed, 56 insertions(+), 64 deletions(-)

Applied on u-boot-stm/master

Thanks

>>
>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> index 9718bae..eba1ded 100644
>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> @@ -10,6 +10,7 @@
>>  #include <log.h>
>>  #include <nand.h>
>>  #include <reset.h>
>> +#include <linux/bitfield.h>
>>  #include <linux/bitops.h>
>>  #include <linux/delay.h>
>>  #include <linux/err.h>
>> @@ -60,20 +61,16 @@
>>  /* Register: FMC2_PCR */
>>  #define FMC2_PCR_PWAITEN		BIT(1)
>>  #define FMC2_PCR_PBKEN			BIT(2)
>> -#define FMC2_PCR_PWID_MASK		GENMASK(5, 4)
>> -#define FMC2_PCR_PWID(x)		(((x) & 0x3) << 4)
>> +#define FMC2_PCR_PWID			GENMASK(5, 4)
>>  #define FMC2_PCR_PWID_BUSWIDTH_8	0
>>  #define FMC2_PCR_PWID_BUSWIDTH_16	1
>>  #define FMC2_PCR_ECCEN			BIT(6)
>>  #define FMC2_PCR_ECCALG			BIT(8)
>> -#define FMC2_PCR_TCLR_MASK		GENMASK(12, 9)
>> -#define FMC2_PCR_TCLR(x)		(((x) & 0xf) << 9)
>> +#define FMC2_PCR_TCLR			GENMASK(12, 9)
>>  #define FMC2_PCR_TCLR_DEFAULT		0xf
>> -#define FMC2_PCR_TAR_MASK		GENMASK(16, 13)
>> -#define FMC2_PCR_TAR(x)			(((x) & 0xf) << 13)
>> +#define FMC2_PCR_TAR			GENMASK(16, 13)
>>  #define FMC2_PCR_TAR_DEFAULT		0xf
>> -#define FMC2_PCR_ECCSS_MASK		GENMASK(19, 17)
>> -#define FMC2_PCR_ECCSS(x)		(((x) & 0x7) << 17)
>> +#define FMC2_PCR_ECCSS			GENMASK(19, 17)
>>  #define FMC2_PCR_ECCSS_512		1
>>  #define FMC2_PCR_ECCSS_2048		3
>>  #define FMC2_PCR_BCHECC			BIT(24)
>> @@ -83,17 +80,17 @@
>>  #define FMC2_SR_NWRF			BIT(6)
>>  
>>  /* Register: FMC2_PMEM */
>> -#define FMC2_PMEM_MEMSET(x)		(((x) & 0xff) << 0)
>> -#define FMC2_PMEM_MEMWAIT(x)		(((x) & 0xff) << 8)
>> -#define FMC2_PMEM_MEMHOLD(x)		(((x) & 0xff) << 16)
>> -#define FMC2_PMEM_MEMHIZ(x)		(((x) & 0xff) << 24)
>> +#define FMC2_PMEM_MEMSET		GENMASK(7, 0)
>> +#define FMC2_PMEM_MEMWAIT		GENMASK(15, 8)
>> +#define FMC2_PMEM_MEMHOLD		GENMASK(23, 16)
>> +#define FMC2_PMEM_MEMHIZ		GENMASK(31, 24)
>>  #define FMC2_PMEM_DEFAULT		0x0a0a0a0a
>>  
>>  /* Register: FMC2_PATT */
>> -#define FMC2_PATT_ATTSET(x)		(((x) & 0xff) << 0)
>> -#define FMC2_PATT_ATTWAIT(x)		(((x) & 0xff) << 8)
>> -#define FMC2_PATT_ATTHOLD(x)		(((x) & 0xff) << 16)
>> -#define FMC2_PATT_ATTHIZ(x)		(((x) & 0xff) << 24)
>> +#define FMC2_PATT_ATTSET		GENMASK(7, 0)
>> +#define FMC2_PATT_ATTWAIT		GENMASK(15, 8)
>> +#define FMC2_PATT_ATTHOLD		GENMASK(23, 16)
>> +#define FMC2_PATT_ATTHIZ		GENMASK(31, 24)
>>  #define FMC2_PATT_DEFAULT		0x0a0a0a0a
>>  
>>  /* Register: FMC2_BCHISR */
>> @@ -106,28 +103,23 @@
>>  /* Register: FMC2_BCHDSR0 */
>>  #define FMC2_BCHDSR0_DUE		BIT(0)
>>  #define FMC2_BCHDSR0_DEF		BIT(1)
>> -#define FMC2_BCHDSR0_DEN_MASK		GENMASK(7, 4)
>> -#define FMC2_BCHDSR0_DEN_SHIFT		4
>> +#define FMC2_BCHDSR0_DEN		GENMASK(7, 4)
>>  
>>  /* Register: FMC2_BCHDSR1 */
>> -#define FMC2_BCHDSR1_EBP1_MASK		GENMASK(12, 0)
>> -#define FMC2_BCHDSR1_EBP2_MASK		GENMASK(28, 16)
>> -#define FMC2_BCHDSR1_EBP2_SHIFT		16
>> +#define FMC2_BCHDSR1_EBP1		GENMASK(12, 0)
>> +#define FMC2_BCHDSR1_EBP2		GENMASK(28, 16)
>>  
>>  /* Register: FMC2_BCHDSR2 */
>> -#define FMC2_BCHDSR2_EBP3_MASK		GENMASK(12, 0)
>> -#define FMC2_BCHDSR2_EBP4_MASK		GENMASK(28, 16)
>> -#define FMC2_BCHDSR2_EBP4_SHIFT		16
>> +#define FMC2_BCHDSR2_EBP3		GENMASK(12, 0)
>> +#define FMC2_BCHDSR2_EBP4		GENMASK(28, 16)
>>  
>>  /* Register: FMC2_BCHDSR3 */
>> -#define FMC2_BCHDSR3_EBP5_MASK		GENMASK(12, 0)
>> -#define FMC2_BCHDSR3_EBP6_MASK		GENMASK(28, 16)
>> -#define FMC2_BCHDSR3_EBP6_SHIFT		16
>> +#define FMC2_BCHDSR3_EBP5		GENMASK(12, 0)
>> +#define FMC2_BCHDSR3_EBP6		GENMASK(28, 16)
>>  
>>  /* Register: FMC2_BCHDSR4 */
>> -#define FMC2_BCHDSR4_EBP7_MASK		GENMASK(12, 0)
>> -#define FMC2_BCHDSR4_EBP8_MASK		GENMASK(28, 16)
>> -#define FMC2_BCHDSR4_EBP8_SHIFT		16
>> +#define FMC2_BCHDSR4_EBP7		GENMASK(12, 0)
>> +#define FMC2_BCHDSR4_EBP8		GENMASK(28, 16)
>>  
>>  #define FMC2_NSEC_PER_SEC		1000000000L
>>  
>> @@ -190,22 +182,22 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
>>  	u32 pmem, patt;
>>  
>>  	/* Set tclr/tar timings */
>> -	pcr &= ~FMC2_PCR_TCLR_MASK;
>> -	pcr |= FMC2_PCR_TCLR(timings->tclr);
>> -	pcr &= ~FMC2_PCR_TAR_MASK;
>> -	pcr |= FMC2_PCR_TAR(timings->tar);
>> +	pcr &= ~FMC2_PCR_TCLR;
>> +	pcr |= FIELD_PREP(FMC2_PCR_TCLR, timings->tclr);
>> +	pcr &= ~FMC2_PCR_TAR;
>> +	pcr |= FIELD_PREP(FMC2_PCR_TAR, timings->tar);
>>  
>>  	/* Set tset/twait/thold/thiz timings in common bank */
>> -	pmem = FMC2_PMEM_MEMSET(timings->tset_mem);
>> -	pmem |= FMC2_PMEM_MEMWAIT(timings->twait);
>> -	pmem |= FMC2_PMEM_MEMHOLD(timings->thold_mem);
>> -	pmem |= FMC2_PMEM_MEMHIZ(timings->thiz);
>> +	pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
>> +	pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
>> +	pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
>> +	pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
>>  
>>  	/* Set tset/twait/thold/thiz timings in attribut bank */
>> -	patt = FMC2_PATT_ATTSET(timings->tset_att);
>> -	patt |= FMC2_PATT_ATTWAIT(timings->twait);
>> -	patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
>> -	patt |= FMC2_PATT_ATTHIZ(timings->thiz);
>> +	patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
>> +	patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
>> +	patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
>> +	patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
>>  
>>  	writel(pcr, nfc->io_base + FMC2_PCR);
>>  	writel(pmem, nfc->io_base + FMC2_PMEM);
>> @@ -228,13 +220,13 @@ static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
>>  	}
>>  
>>  	/* Set buswidth */
>> -	pcr &= ~FMC2_PCR_PWID_MASK;
>> +	pcr &= ~FMC2_PCR_PWID;
>>  	if (chip->options & NAND_BUSWIDTH_16)
>> -		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
>> +		pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
>>  
>>  	/* Set ECC sector size */
>> -	pcr &= ~FMC2_PCR_ECCSS_MASK;
>> -	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
>> +	pcr &= ~FMC2_PCR_ECCSS;
>> +	pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
>>  
>>  	writel(pcr, nfc->io_base + FMC2_PCR);
>>  }
>> @@ -264,9 +256,9 @@ static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
>>  {
>>  	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>>  
>> -	pcr &= ~FMC2_PCR_PWID_MASK;
>> +	pcr &= ~FMC2_PCR_PWID;
>>  	if (set)
>> -		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
>> +		pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
>>  	writel(pcr, nfc->io_base + FMC2_PCR);
>>  }
>>  
>> @@ -497,16 +489,16 @@ static int stm32_fmc2_nfc_bch_correct(struct mtd_info *mtd, u8 *dat,
>>  	if (unlikely(bchdsr0 & FMC2_BCHDSR0_DUE))
>>  		return -EBADMSG;
>>  
>> -	pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK;
>> -	pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT;
>> -	pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK;
>> -	pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT;
>> -	pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK;
>> -	pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT;
>> -	pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK;
>> -	pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT;
>> +	pos[0] = FIELD_GET(FMC2_BCHDSR1_EBP1, bchdsr1);
>> +	pos[1] = FIELD_GET(FMC2_BCHDSR1_EBP2, bchdsr1);
>> +	pos[2] = FIELD_GET(FMC2_BCHDSR2_EBP3, bchdsr2);
>> +	pos[3] = FIELD_GET(FMC2_BCHDSR2_EBP4, bchdsr2);
>> +	pos[4] = FIELD_GET(FMC2_BCHDSR3_EBP5, bchdsr3);
>> +	pos[5] = FIELD_GET(FMC2_BCHDSR3_EBP6, bchdsr3);
>> +	pos[6] = FIELD_GET(FMC2_BCHDSR4_EBP7, bchdsr4);
>> +	pos[7] = FIELD_GET(FMC2_BCHDSR4_EBP8, bchdsr4);
>>  
>> -	den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT;
>> +	den = FIELD_GET(FMC2_BCHDSR0_DEN, bchdsr0);
>>  	for (i = 0; i < den; i++) {
>>  		if (pos[i] < eccsize * 8) {
>>  			__change_bit(pos[i], (unsigned long *)dat);
>> @@ -581,7 +573,7 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>>  	pcr |= FMC2_PCR_PBKEN;
>>  
>>  	/* Set buswidth to 8 bits mode for identification */
>> -	pcr &= ~FMC2_PCR_PWID_MASK;
>> +	pcr &= ~FMC2_PCR_PWID;
>>  
>>  	/* ECC logic is disabled */
>>  	pcr &= ~FMC2_PCR_ECCEN;
>> @@ -592,14 +584,14 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>>  	pcr &= ~FMC2_PCR_WEN;
>>  
>>  	/* Set default ECC sector size */
>> -	pcr &= ~FMC2_PCR_ECCSS_MASK;
>> -	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048);
>> +	pcr &= ~FMC2_PCR_ECCSS;
>> +	pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_2048);
>>  
>>  	/* Set default tclr/tar timings */
>> -	pcr &= ~FMC2_PCR_TCLR_MASK;
>> -	pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT);
>> -	pcr &= ~FMC2_PCR_TAR_MASK;
>> -	pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT);
>> +	pcr &= ~FMC2_PCR_TCLR;
>> +	pcr |= FIELD_PREP(FMC2_PCR_TCLR, FMC2_PCR_TCLR_DEFAULT);
>> +	pcr &= ~FMC2_PCR_TAR;
>> +	pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
>>  
>>  	/* Enable FMC2 controller */
>>  	bcr1 |= FMC2_BCR1_FMC2EN;
> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
>
> Thanks
>
> Patrice
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 06/11] mtd: rawnand: stm32_fmc2: use clrsetbits_le32
  2020-08-13  7:30   ` Patrice CHOTARD
@ 2020-08-13  9:58     ` Patrice CHOTARD
  0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  9:58 UTC (permalink / raw)
  To: u-boot


On 8/13/20 9:30 AM, Patrice CHOTARD wrote:
> Hi Christophe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> This patch uses clrsetbits_le32 function instead of multiple instructions.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 56 +++++++++++++---------------------
>>  1 file changed, 21 insertions(+), 35 deletions(-)

Applied on u-boot-stm/master

Thanks


>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> index eba1ded..1e4d757 100644
>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> @@ -178,40 +178,37 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
>>  	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>>  	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
>>  	struct stm32_fmc2_timings *timings = &nand->timings;
>> -	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>>  	u32 pmem, patt;
>>  
>>  	/* Set tclr/tar timings */
>> -	pcr &= ~FMC2_PCR_TCLR;
>> -	pcr |= FIELD_PREP(FMC2_PCR_TCLR, timings->tclr);
>> -	pcr &= ~FMC2_PCR_TAR;
>> -	pcr |= FIELD_PREP(FMC2_PCR_TAR, timings->tar);
>> +	clrsetbits_le32(nfc->io_base + FMC2_PCR,
>> +			FMC2_PCR_TCLR | FMC2_PCR_TAR,
>> +			FIELD_PREP(FMC2_PCR_TCLR, timings->tclr) |
>> +			FIELD_PREP(FMC2_PCR_TAR, timings->tar));
>>  
>>  	/* Set tset/twait/thold/thiz timings in common bank */
>>  	pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
>>  	pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
>>  	pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
>>  	pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
>> +	writel(pmem, nfc->io_base + FMC2_PMEM);
>>  
>>  	/* Set tset/twait/thold/thiz timings in attribut bank */
>>  	patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
>>  	patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
>>  	patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
>>  	patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
>> -
>> -	writel(pcr, nfc->io_base + FMC2_PCR);
>> -	writel(pmem, nfc->io_base + FMC2_PMEM);
>>  	writel(patt, nfc->io_base + FMC2_PATT);
>>  }
>>  
>>  static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
>>  {
>>  	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>> -	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>> +	u32 pcr = 0, pcr_mask;
>>  
>>  	/* Configure ECC algorithm (default configuration is Hamming) */
>> -	pcr &= ~FMC2_PCR_ECCALG;
>> -	pcr &= ~FMC2_PCR_BCHECC;
>> +	pcr_mask = FMC2_PCR_ECCALG;
>> +	pcr_mask |= FMC2_PCR_BCHECC;
>>  	if (chip->ecc.strength == FMC2_ECC_BCH8) {
>>  		pcr |= FMC2_PCR_ECCALG;
>>  		pcr |= FMC2_PCR_BCHECC;
>> @@ -220,15 +217,15 @@ static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
>>  	}
>>  
>>  	/* Set buswidth */
>> -	pcr &= ~FMC2_PCR_PWID;
>> +	pcr_mask |= FMC2_PCR_PWID;
>>  	if (chip->options & NAND_BUSWIDTH_16)
>>  		pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
>>  
>>  	/* Set ECC sector size */
>> -	pcr &= ~FMC2_PCR_ECCSS;
>> +	pcr_mask |= FMC2_PCR_ECCSS;
>>  	pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
>>  
>> -	writel(pcr, nfc->io_base + FMC2_PCR);
>> +	clrsetbits_le32(nfc->io_base + FMC2_PCR, pcr_mask, pcr);
>>  }
>>  
>>  static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
>> @@ -254,22 +251,18 @@ static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
>>  static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
>>  					   bool set)
>>  {
>> -	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>> +	u32 pcr;
>>  
>> -	pcr &= ~FMC2_PCR_PWID;
>> -	if (set)
>> -		pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
>> -	writel(pcr, nfc->io_base + FMC2_PCR);
>> +	pcr = set ? FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16) :
>> +		    FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_8);
>> +
>> +	clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_PWID, pcr);
>>  }
>>  
>>  static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
>>  {
>> -	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>> -
>> -	pcr &= ~FMC2_PCR_ECCEN;
>> -	if (enable)
>> -		pcr |= FMC2_PCR_ECCEN;
>> -	writel(pcr, nfc->io_base + FMC2_PCR);
>> +	clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_ECCEN,
>> +			enable ? FMC2_PCR_ECCEN : 0);
>>  }
>>  
>>  static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
>> @@ -306,13 +299,8 @@ static void stm32_fmc2_nfc_hwctl(struct mtd_info *mtd, int mode)
>>  	stm32_fmc2_nfc_set_ecc(nfc, false);
>>  
>>  	if (chip->ecc.strength != FMC2_ECC_HAM) {
>> -		u32 pcr = readl(nfc->io_base + FMC2_PCR);
>> -
>> -		if (mode == NAND_ECC_WRITE)
>> -			pcr |= FMC2_PCR_WEN;
>> -		else
>> -			pcr &= ~FMC2_PCR_WEN;
>> -		writel(pcr, nfc->io_base + FMC2_PCR);
>> +		clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_WEN,
>> +				mode == NAND_ECC_WRITE ? FMC2_PCR_WEN : 0);
>>  
>>  		stm32_fmc2_nfc_clear_bch_irq(nfc);
>>  	}
>> @@ -563,7 +551,6 @@ static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
>>  static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>>  {
>>  	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>> -	u32 bcr1 = readl(nfc->io_base + FMC2_BCR1);
>>  
>>  	/* Set CS used to undefined */
>>  	nfc->cs_sel = -1;
>> @@ -594,9 +581,8 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>>  	pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
>>  
>>  	/* Enable FMC2 controller */
>> -	bcr1 |= FMC2_BCR1_FMC2EN;
>> +	setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
>>  
>> -	writel(bcr1, nfc->io_base + FMC2_BCR1);
>>  	writel(pcr, nfc->io_base + FMC2_PCR);
>>  	writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
>>  	writel(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);
> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
>
> Thanks
>
> Patrice
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 07/11] memory: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver
  2020-08-13  7:31   ` Patrice CHOTARD
@ 2020-08-13  9:58     ` Patrice CHOTARD
  0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  9:58 UTC (permalink / raw)
  To: u-boot


On 8/13/20 9:31 AM, Patrice CHOTARD wrote:
> Hi Christophe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> The driver adds the support for the STMicroelectronics FMC2 EBI controller
>> found on STM32MP SOCs.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>>  drivers/memory/Kconfig          |    9 +
>>  drivers/memory/Makefile         |    1 +
>>  drivers/memory/stm32-fmc2-ebi.c | 1056 +++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 1066 insertions(+)
>>  create mode 100644 drivers/memory/stm32-fmc2-ebi.c

Applied on u-boot-stm/master

Thanks

>>
>> diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
>> index 4fbb5aa..7271892 100644
>> --- a/drivers/memory/Kconfig
>> +++ b/drivers/memory/Kconfig
>> @@ -4,6 +4,15 @@
>>  
>>  menu "Memory Controller drivers"
>>  
>> +config STM32_FMC2_EBI
>> +	bool "Support for FMC2 External Bus Interface on STM32MP SoCs"
>> +	depends on ARCH_STM32MP
>> +	help
>> +	  Select this option to enable the STM32 FMC2 External Bus Interface
>> +	  controller. This driver configures the transactions with external
>> +	  devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on
>> +	  SOCs containing the FMC2 External Bus Interface.
>> +
>>  config TI_AEMIF
>>  	tristate "Texas Instruments AEMIF driver"
>>  	depends on ARCH_KEYSTONE
>> diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
>> index 238add0..fec52ef 100644
>> --- a/drivers/memory/Makefile
>> +++ b/drivers/memory/Makefile
>> @@ -1,2 +1,3 @@
>>  
>> +obj-$(CONFIG_STM32_FMC2_EBI) += stm32-fmc2-ebi.o
>>  obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
>> diff --git a/drivers/memory/stm32-fmc2-ebi.c b/drivers/memory/stm32-fmc2-ebi.c
>> new file mode 100644
>> index 0000000..d887a1e
>> --- /dev/null
>> +++ b/drivers/memory/stm32-fmc2-ebi.c
>> @@ -0,0 +1,1056 @@
>> +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
>> +/*
>> + * Copyright (C) STMicroelectronics 2020
>> + */
>> +
>> +#include <common.h>
>> +#include <clk.h>
>> +#include <dm.h>
>> +#include <reset.h>
>> +#include <linux/bitfield.h>
>> +#include <linux/err.h>
>> +#include <linux/iopoll.h>
>> +#include <linux/ioport.h>
>> +
>> +/* FMC2 Controller Registers */
>> +#define FMC2_BCR1			0x0
>> +#define FMC2_BTR1			0x4
>> +#define FMC2_BCR(x)			((x) * 0x8 + FMC2_BCR1)
>> +#define FMC2_BTR(x)			((x) * 0x8 + FMC2_BTR1)
>> +#define FMC2_PCSCNTR			0x20
>> +#define FMC2_BWTR1			0x104
>> +#define FMC2_BWTR(x)			((x) * 0x8 + FMC2_BWTR1)
>> +
>> +/* Register: FMC2_BCR1 */
>> +#define FMC2_BCR1_CCLKEN		BIT(20)
>> +#define FMC2_BCR1_FMC2EN		BIT(31)
>> +
>> +/* Register: FMC2_BCRx */
>> +#define FMC2_BCR_MBKEN			BIT(0)
>> +#define FMC2_BCR_MUXEN			BIT(1)
>> +#define FMC2_BCR_MTYP			GENMASK(3, 2)
>> +#define FMC2_BCR_MWID			GENMASK(5, 4)
>> +#define FMC2_BCR_FACCEN			BIT(6)
>> +#define FMC2_BCR_BURSTEN		BIT(8)
>> +#define FMC2_BCR_WAITPOL		BIT(9)
>> +#define FMC2_BCR_WAITCFG		BIT(11)
>> +#define FMC2_BCR_WREN			BIT(12)
>> +#define FMC2_BCR_WAITEN			BIT(13)
>> +#define FMC2_BCR_EXTMOD			BIT(14)
>> +#define FMC2_BCR_ASYNCWAIT		BIT(15)
>> +#define FMC2_BCR_CPSIZE			GENMASK(18, 16)
>> +#define FMC2_BCR_CBURSTRW		BIT(19)
>> +#define FMC2_BCR_NBLSET			GENMASK(23, 22)
>> +
>> +/* Register: FMC2_BTRx/FMC2_BWTRx */
>> +#define FMC2_BXTR_ADDSET		GENMASK(3, 0)
>> +#define FMC2_BXTR_ADDHLD		GENMASK(7, 4)
>> +#define FMC2_BXTR_DATAST		GENMASK(15, 8)
>> +#define FMC2_BXTR_BUSTURN		GENMASK(19, 16)
>> +#define FMC2_BTR_CLKDIV			GENMASK(23, 20)
>> +#define FMC2_BTR_DATLAT			GENMASK(27, 24)
>> +#define FMC2_BXTR_ACCMOD		GENMASK(29, 28)
>> +#define FMC2_BXTR_DATAHLD		GENMASK(31, 30)
>> +
>> +/* Register: FMC2_PCSCNTR */
>> +#define FMC2_PCSCNTR_CSCOUNT		GENMASK(15, 0)
>> +#define FMC2_PCSCNTR_CNTBEN(x)		BIT((x) + 16)
>> +
>> +#define FMC2_MAX_EBI_CE			4
>> +#define FMC2_MAX_BANKS			5
>> +
>> +#define FMC2_BCR_CPSIZE_0		0x0
>> +#define FMC2_BCR_CPSIZE_128		0x1
>> +#define FMC2_BCR_CPSIZE_256		0x2
>> +#define FMC2_BCR_CPSIZE_512		0x3
>> +#define FMC2_BCR_CPSIZE_1024		0x4
>> +
>> +#define FMC2_BCR_MWID_8			0x0
>> +#define FMC2_BCR_MWID_16		0x1
>> +
>> +#define FMC2_BCR_MTYP_SRAM		0x0
>> +#define FMC2_BCR_MTYP_PSRAM		0x1
>> +#define FMC2_BCR_MTYP_NOR		0x2
>> +
>> +#define FMC2_BXTR_EXTMOD_A		0x0
>> +#define FMC2_BXTR_EXTMOD_B		0x1
>> +#define FMC2_BXTR_EXTMOD_C		0x2
>> +#define FMC2_BXTR_EXTMOD_D		0x3
>> +
>> +#define FMC2_BCR_NBLSET_MAX		0x3
>> +#define FMC2_BXTR_ADDSET_MAX		0xf
>> +#define FMC2_BXTR_ADDHLD_MAX		0xf
>> +#define FMC2_BXTR_DATAST_MAX		0xff
>> +#define FMC2_BXTR_BUSTURN_MAX		0xf
>> +#define FMC2_BXTR_DATAHLD_MAX		0x3
>> +#define FMC2_BTR_CLKDIV_MAX		0xf
>> +#define FMC2_BTR_DATLAT_MAX		0xf
>> +#define FMC2_PCSCNTR_CSCOUNT_MAX	0xff
>> +
>> +#define FMC2_NSEC_PER_SEC		1000000000L
>> +
>> +enum stm32_fmc2_ebi_bank {
>> +	FMC2_EBI1 = 0,
>> +	FMC2_EBI2,
>> +	FMC2_EBI3,
>> +	FMC2_EBI4,
>> +	FMC2_NAND
>> +};
>> +
>> +enum stm32_fmc2_ebi_register_type {
>> +	FMC2_REG_BCR = 1,
>> +	FMC2_REG_BTR,
>> +	FMC2_REG_BWTR,
>> +	FMC2_REG_PCSCNTR
>> +};
>> +
>> +enum stm32_fmc2_ebi_transaction_type {
>> +	FMC2_ASYNC_MODE_1_SRAM = 0,
>> +	FMC2_ASYNC_MODE_1_PSRAM,
>> +	FMC2_ASYNC_MODE_A_SRAM,
>> +	FMC2_ASYNC_MODE_A_PSRAM,
>> +	FMC2_ASYNC_MODE_2_NOR,
>> +	FMC2_ASYNC_MODE_B_NOR,
>> +	FMC2_ASYNC_MODE_C_NOR,
>> +	FMC2_ASYNC_MODE_D_NOR,
>> +	FMC2_SYNC_READ_SYNC_WRITE_PSRAM,
>> +	FMC2_SYNC_READ_ASYNC_WRITE_PSRAM,
>> +	FMC2_SYNC_READ_SYNC_WRITE_NOR,
>> +	FMC2_SYNC_READ_ASYNC_WRITE_NOR
>> +};
>> +
>> +enum stm32_fmc2_ebi_buswidth {
>> +	FMC2_BUSWIDTH_8 = 8,
>> +	FMC2_BUSWIDTH_16 = 16
>> +};
>> +
>> +enum stm32_fmc2_ebi_cpsize {
>> +	FMC2_CPSIZE_0 = 0,
>> +	FMC2_CPSIZE_128 = 128,
>> +	FMC2_CPSIZE_256 = 256,
>> +	FMC2_CPSIZE_512 = 512,
>> +	FMC2_CPSIZE_1024 = 1024
>> +};
>> +
>> +struct stm32_fmc2_ebi {
>> +	struct clk clk;
>> +	fdt_addr_t io_base;
>> +	u8 bank_assigned;
>> +};
>> +
>> +/*
>> + * struct stm32_fmc2_prop - STM32 FMC2 EBI property
>> + * @name: the device tree binding name of the property
>> + * @bprop: indicate that it is a boolean property
>> + * @mprop: indicate that it is a mandatory property
>> + * @reg_type: the register that have to be modified
>> + * @reg_mask: the bit that have to be modified in the selected register
>> + *            in case of it is a boolean property
>> + * @reset_val: the default value that have to be set in case the property
>> + *             has not been defined in the device tree
>> + * @check: this callback ckecks that the property is compliant with the
>> + *         transaction type selected
>> + * @calculate: this callback is called to calculate for exemple a timing
>> + *             set in nanoseconds in the device tree in clock cycles or in
>> + *             clock period
>> + * @set: this callback applies the values in the registers
>> + */
>> +struct stm32_fmc2_prop {
>> +	const char *name;
>> +	bool bprop;
>> +	bool mprop;
>> +	int reg_type;
>> +	u32 reg_mask;
>> +	u32 reset_val;
>> +	int (*check)(struct stm32_fmc2_ebi *ebi,
>> +		     const struct stm32_fmc2_prop *prop, int cs);
>> +	u32 (*calculate)(struct stm32_fmc2_ebi *ebi, int cs, u32 setup);
>> +	int (*set)(struct stm32_fmc2_ebi *ebi,
>> +		   const struct stm32_fmc2_prop *prop,
>> +		   int cs, u32 setup);
>> +};
>> +
>> +static int stm32_fmc2_ebi_check_mux(struct stm32_fmc2_ebi *ebi,
>> +				    const struct stm32_fmc2_prop *prop,
>> +				    int cs)
>> +{
>> +	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
>> +
>> +	if (bcr & FMC2_BCR_MTYP)
>> +		return 0;
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +static int stm32_fmc2_ebi_check_waitcfg(struct stm32_fmc2_ebi *ebi,
>> +					const struct stm32_fmc2_prop *prop,
>> +					int cs)
>> +{
>> +	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
>> +	u32 val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
>> +
>> +	if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
>> +		return 0;
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +static int stm32_fmc2_ebi_check_sync_trans(struct stm32_fmc2_ebi *ebi,
>> +					   const struct stm32_fmc2_prop *prop,
>> +					   int cs)
>> +{
>> +	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
>> +
>> +	if (bcr & FMC2_BCR_BURSTEN)
>> +		return 0;
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2_ebi *ebi,
>> +					    const struct stm32_fmc2_prop *prop,
>> +					    int cs)
>> +{
>> +	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
>> +
>> +	if (!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW))
>> +		return 0;
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +static int stm32_fmc2_ebi_check_cpsize(struct stm32_fmc2_ebi *ebi,
>> +				       const struct stm32_fmc2_prop *prop,
>> +				       int cs)
>> +{
>> +	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
>> +	u32 val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
>> +
>> +	if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
>> +		return 0;
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +static int stm32_fmc2_ebi_check_address_hold(struct stm32_fmc2_ebi *ebi,
>> +					     const struct stm32_fmc2_prop *prop,
>> +					     int cs)
>> +{
>> +	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
>> +	u32 bxtr = prop->reg_type == FMC2_REG_BWTR ?
>> +		   readl(ebi->io_base + FMC2_BWTR(cs)) :
>> +		   readl(ebi->io_base + FMC2_BTR(cs));
>> +	u32 val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
>> +
>> +	if ((!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW)) &&
>> +	    ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN))
>> +		return 0;
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +static int stm32_fmc2_ebi_check_clk_period(struct stm32_fmc2_ebi *ebi,
>> +					   const struct stm32_fmc2_prop *prop,
>> +					   int cs)
>> +{
>> +	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
>> +	u32 bcr1 = cs ? readl(ebi->io_base + FMC2_BCR1) : bcr;
>> +
>> +	if (bcr & FMC2_BCR_BURSTEN && (!cs || !(bcr1 & FMC2_BCR1_CCLKEN)))
>> +		return 0;
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +static int stm32_fmc2_ebi_check_cclk(struct stm32_fmc2_ebi *ebi,
>> +				     const struct stm32_fmc2_prop *prop,
>> +				     int cs)
>> +{
>> +	if (cs)
>> +		return -EINVAL;
>> +
>> +	return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs);
>> +}
>> +
>> +static u32 stm32_fmc2_ebi_ns_to_clock_cycles(struct stm32_fmc2_ebi *ebi,
>> +					     int cs, u32 setup)
>> +{
>> +	unsigned long hclk = clk_get_rate(&ebi->clk);
>> +	unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
>> +
>> +	return DIV_ROUND_UP(setup * 1000, hclkp);
>> +}
>> +
>> +static u32 stm32_fmc2_ebi_ns_to_clk_period(struct stm32_fmc2_ebi *ebi,
>> +					   int cs, u32 setup)
>> +{
>> +	u32 nb_clk_cycles = stm32_fmc2_ebi_ns_to_clock_cycles(ebi, cs, setup);
>> +	u32 bcr = readl(ebi->io_base + FMC2_BCR1);
>> +	u32 btr = bcr & FMC2_BCR1_CCLKEN || !cs ?
>> +		  readl(ebi->io_base + FMC2_BTR1) :
>> +		  readl(ebi->io_base + FMC2_BTR(cs));
>> +	u32 clk_period = FIELD_GET(FMC2_BTR_CLKDIV, btr) + 1;
>> +
>> +	return DIV_ROUND_UP(nb_clk_cycles, clk_period);
>> +}
>> +
>> +static int stm32_fmc2_ebi_get_reg(int reg_type, int cs, u32 *reg)
>> +{
>> +	switch (reg_type) {
>> +	case FMC2_REG_BCR:
>> +		*reg = FMC2_BCR(cs);
>> +		break;
>> +	case FMC2_REG_BTR:
>> +		*reg = FMC2_BTR(cs);
>> +		break;
>> +	case FMC2_REG_BWTR:
>> +		*reg = FMC2_BWTR(cs);
>> +		break;
>> +	case FMC2_REG_PCSCNTR:
>> +		*reg = FMC2_PCSCNTR;
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_fmc2_ebi_set_bit_field(struct stm32_fmc2_ebi *ebi,
>> +					const struct stm32_fmc2_prop *prop,
>> +					int cs, u32 setup)
>> +{
>> +	u32 reg;
>> +	int ret;
>> +
>> +	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
>> +	if (ret)
>> +		return ret;
>> +
>> +	clrsetbits_le32(ebi->io_base + reg, prop->reg_mask,
>> +			setup ? prop->reg_mask : 0);
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_fmc2_ebi_set_trans_type(struct stm32_fmc2_ebi *ebi,
>> +					 const struct stm32_fmc2_prop *prop,
>> +					 int cs, u32 setup)
>> +{
>> +	u32 bcr_mask, bcr = FMC2_BCR_WREN;
>> +	u32 btr_mask, btr = 0;
>> +	u32 bwtr_mask, bwtr = 0;
>> +
>> +	bwtr_mask = FMC2_BXTR_ACCMOD;
>> +	btr_mask = FMC2_BXTR_ACCMOD;
>> +	bcr_mask = FMC2_BCR_MUXEN | FMC2_BCR_MTYP | FMC2_BCR_FACCEN |
>> +		   FMC2_BCR_WREN | FMC2_BCR_WAITEN | FMC2_BCR_BURSTEN |
>> +		   FMC2_BCR_EXTMOD | FMC2_BCR_CBURSTRW;
>> +
>> +	switch (setup) {
>> +	case FMC2_ASYNC_MODE_1_SRAM:
>> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM);
>> +		/*
>> +		 * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
>> +		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
>> +		 */
>> +		break;
>> +	case FMC2_ASYNC_MODE_1_PSRAM:
>> +		/*
>> +		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
>> +		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
>> +		 */
>> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
>> +		break;
>> +	case FMC2_ASYNC_MODE_A_SRAM:
>> +		/*
>> +		 * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
>> +		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0
>> +		 */
>> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM);
>> +		bcr |= FMC2_BCR_EXTMOD;
>> +		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
>> +		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
>> +		break;
>> +	case FMC2_ASYNC_MODE_A_PSRAM:
>> +		/*
>> +		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
>> +		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0
>> +		 */
>> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
>> +		bcr |= FMC2_BCR_EXTMOD;
>> +		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
>> +		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
>> +		break;
>> +	case FMC2_ASYNC_MODE_2_NOR:
>> +		/*
>> +		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
>> +		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
>> +		 */
>> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
>> +		bcr |= FMC2_BCR_FACCEN;
>> +		break;
>> +	case FMC2_ASYNC_MODE_B_NOR:
>> +		/*
>> +		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
>> +		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 1
>> +		 */
>> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
>> +		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
>> +		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B);
>> +		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B);
>> +		break;
>> +	case FMC2_ASYNC_MODE_C_NOR:
>> +		/*
>> +		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
>> +		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 2
>> +		 */
>> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
>> +		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
>> +		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C);
>> +		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C);
>> +		break;
>> +	case FMC2_ASYNC_MODE_D_NOR:
>> +		/*
>> +		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
>> +		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 3
>> +		 */
>> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
>> +		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
>> +		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
>> +		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
>> +		break;
>> +	case FMC2_SYNC_READ_SYNC_WRITE_PSRAM:
>> +		/*
>> +		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0,
>> +		 * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0
>> +		 */
>> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
>> +		bcr |= FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW;
>> +		break;
>> +	case FMC2_SYNC_READ_ASYNC_WRITE_PSRAM:
>> +		/*
>> +		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0,
>> +		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
>> +		 */
>> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
>> +		bcr |= FMC2_BCR_BURSTEN;
>> +		break;
>> +	case FMC2_SYNC_READ_SYNC_WRITE_NOR:
>> +		/*
>> +		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0,
>> +		 * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0
>> +		 */
>> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
>> +		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW;
>> +		break;
>> +	case FMC2_SYNC_READ_ASYNC_WRITE_NOR:
>> +		/*
>> +		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0,
>> +		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
>> +		 */
>> +		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
>> +		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN;
>> +		break;
>> +	default:
>> +		/* Type of transaction not supported */
>> +		return -EINVAL;
>> +	}
>> +
>> +	if (bcr & FMC2_BCR_EXTMOD)
>> +		clrsetbits_le32(ebi->io_base + FMC2_BWTR(cs),
>> +				bwtr_mask, bwtr);
>> +	clrsetbits_le32(ebi->io_base + FMC2_BTR(cs), btr_mask, btr);
>> +	clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), bcr_mask, bcr);
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_fmc2_ebi_set_buswidth(struct stm32_fmc2_ebi *ebi,
>> +				       const struct stm32_fmc2_prop *prop,
>> +				       int cs, u32 setup)
>> +{
>> +	u32 val;
>> +
>> +	switch (setup) {
>> +	case FMC2_BUSWIDTH_8:
>> +		val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_8);
>> +		break;
>> +	case FMC2_BUSWIDTH_16:
>> +		val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_16);
>> +		break;
>> +	default:
>> +		/* Buswidth not supported */
>> +		return -EINVAL;
>> +	}
>> +
>> +	clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_MWID, val);
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_fmc2_ebi_set_cpsize(struct stm32_fmc2_ebi *ebi,
>> +				     const struct stm32_fmc2_prop *prop,
>> +				     int cs, u32 setup)
>> +{
>> +	u32 val;
>> +
>> +	switch (setup) {
>> +	case FMC2_CPSIZE_0:
>> +		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_0);
>> +		break;
>> +	case FMC2_CPSIZE_128:
>> +		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_128);
>> +		break;
>> +	case FMC2_CPSIZE_256:
>> +		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_256);
>> +		break;
>> +	case FMC2_CPSIZE_512:
>> +		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_512);
>> +		break;
>> +	case FMC2_CPSIZE_1024:
>> +		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_1024);
>> +		break;
>> +	default:
>> +		/* Cpsize not supported */
>> +		return -EINVAL;
>> +	}
>> +
>> +	clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_CPSIZE, val);
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_fmc2_ebi_set_bl_setup(struct stm32_fmc2_ebi *ebi,
>> +				       const struct stm32_fmc2_prop *prop,
>> +				       int cs, u32 setup)
>> +{
>> +	u32 val;
>> +
>> +	val = min_t(u32, setup, FMC2_BCR_NBLSET_MAX);
>> +	val = FIELD_PREP(FMC2_BCR_NBLSET, val);
>> +	clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_NBLSET, val);
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_fmc2_ebi_set_address_setup(struct stm32_fmc2_ebi *ebi,
>> +					    const struct stm32_fmc2_prop *prop,
>> +					    int cs, u32 setup)
>> +{
>> +	u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
>> +	u32 bxtr = prop->reg_type == FMC2_REG_BWTR ?
>> +		   readl(ebi->io_base + FMC2_BWTR(cs)) :
>> +		   readl(ebi->io_base + FMC2_BTR(cs));
>> +	u32 reg, val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
>> +	int ret;
>> +
>> +	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
>> +	if (ret)
>> +		return ret;
>> +
>> +	if ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN)
>> +		val = clamp_val(setup, 1, FMC2_BXTR_ADDSET_MAX);
>> +	else
>> +		val = min_t(u32, setup, FMC2_BXTR_ADDSET_MAX);
>> +	val = FIELD_PREP(FMC2_BXTR_ADDSET, val);
>> +	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_ADDSET, val);
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_fmc2_ebi_set_address_hold(struct stm32_fmc2_ebi *ebi,
>> +					   const struct stm32_fmc2_prop *prop,
>> +					   int cs, u32 setup)
>> +{
>> +	u32 val, reg;
>> +	int ret;
>> +
>> +	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
>> +	if (ret)
>> +		return ret;
>> +
>> +	val = clamp_val(setup, 1, FMC2_BXTR_ADDHLD_MAX);
>> +	val = FIELD_PREP(FMC2_BXTR_ADDHLD, val);
>> +	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_ADDHLD, val);
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_fmc2_ebi_set_data_setup(struct stm32_fmc2_ebi *ebi,
>> +					 const struct stm32_fmc2_prop *prop,
>> +					 int cs, u32 setup)
>> +{
>> +	u32 val, reg;
>> +	int ret;
>> +
>> +	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
>> +	if (ret)
>> +		return ret;
>> +
>> +	val = clamp_val(setup, 1, FMC2_BXTR_DATAST_MAX);
>> +	val = FIELD_PREP(FMC2_BXTR_DATAST, val);
>> +	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_DATAST, val);
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_fmc2_ebi_set_bus_turnaround(struct stm32_fmc2_ebi *ebi,
>> +					     const struct stm32_fmc2_prop *prop,
>> +					     int cs, u32 setup)
>> +{
>> +	u32 val, reg;
>> +	int ret;
>> +
>> +	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
>> +	if (ret)
>> +		return ret;
>> +
>> +	val = setup ? min_t(u32, setup - 1, FMC2_BXTR_BUSTURN_MAX) : 0;
>> +	val = FIELD_PREP(FMC2_BXTR_BUSTURN, val);
>> +	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_BUSTURN, val);
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_fmc2_ebi_set_data_hold(struct stm32_fmc2_ebi *ebi,
>> +					const struct stm32_fmc2_prop *prop,
>> +					int cs, u32 setup)
>> +{
>> +	u32 val, reg;
>> +	int ret;
>> +
>> +	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
>> +	if (ret)
>> +		return ret;
>> +
>> +	if (prop->reg_type == FMC2_REG_BWTR)
>> +		val = setup ? min_t(u32, setup - 1, FMC2_BXTR_DATAHLD_MAX) : 0;
>> +	else
>> +		val = min_t(u32, setup, FMC2_BXTR_DATAHLD_MAX);
>> +	val = FIELD_PREP(FMC2_BXTR_DATAHLD, val);
>> +	clrsetbits_le32(ebi->io_base + reg, FMC2_BXTR_DATAHLD, val);
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_fmc2_ebi_set_clk_period(struct stm32_fmc2_ebi *ebi,
>> +					 const struct stm32_fmc2_prop *prop,
>> +					 int cs, u32 setup)
>> +{
>> +	u32 val;
>> +
>> +	val = setup ? clamp_val(setup - 1, 1, FMC2_BTR_CLKDIV_MAX) : 1;
>> +	val = FIELD_PREP(FMC2_BTR_CLKDIV, val);
>> +	clrsetbits_le32(ebi->io_base + FMC2_BTR(cs), FMC2_BTR_CLKDIV, val);
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_fmc2_ebi_set_data_latency(struct stm32_fmc2_ebi *ebi,
>> +					   const struct stm32_fmc2_prop *prop,
>> +					   int cs, u32 setup)
>> +{
>> +	u32 val;
>> +
>> +	val = setup > 1 ? min_t(u32, setup - 2, FMC2_BTR_DATLAT_MAX) : 0;
>> +	val = FIELD_PREP(FMC2_BTR_DATLAT, val);
>> +	clrsetbits_le32(ebi->io_base + FMC2_BTR(cs), FMC2_BTR_DATLAT, val);
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_fmc2_ebi_set_max_low_pulse(struct stm32_fmc2_ebi *ebi,
>> +					    const struct stm32_fmc2_prop *prop,
>> +					    int cs, u32 setup)
>> +{
>> +	u32 old_val, new_val, pcscntr;
>> +
>> +	if (setup < 1)
>> +		return 0;
>> +
>> +	pcscntr = readl(ebi->io_base + FMC2_PCSCNTR);
>> +
>> +	/* Enable counter for the bank */
>> +	setbits_le32(ebi->io_base + FMC2_PCSCNTR, FMC2_PCSCNTR_CNTBEN(cs));
>> +
>> +	new_val = min_t(u32, setup - 1, FMC2_PCSCNTR_CSCOUNT_MAX);
>> +	old_val = FIELD_GET(FMC2_PCSCNTR_CSCOUNT, pcscntr);
>> +	if (old_val && new_val > old_val)
>> +		/* Keep current counter value */
>> +		return 0;
>> +
>> +	new_val = FIELD_PREP(FMC2_PCSCNTR_CSCOUNT, new_val);
>> +	clrsetbits_le32(ebi->io_base + FMC2_PCSCNTR,
>> +			FMC2_PCSCNTR_CSCOUNT, new_val);
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct stm32_fmc2_prop stm32_fmc2_child_props[] = {
>> +	/* st,fmc2-ebi-cs-trans-type must be the first property */
>> +	{
>> +		.name = "st,fmc2-ebi-cs-transaction-type",
>> +		.mprop = true,
>> +		.set = stm32_fmc2_ebi_set_trans_type,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-cclk-enable",
>> +		.bprop = true,
>> +		.reg_type = FMC2_REG_BCR,
>> +		.reg_mask = FMC2_BCR1_CCLKEN,
>> +		.check = stm32_fmc2_ebi_check_cclk,
>> +		.set = stm32_fmc2_ebi_set_bit_field,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-mux-enable",
>> +		.bprop = true,
>> +		.reg_type = FMC2_REG_BCR,
>> +		.reg_mask = FMC2_BCR_MUXEN,
>> +		.check = stm32_fmc2_ebi_check_mux,
>> +		.set = stm32_fmc2_ebi_set_bit_field,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-buswidth",
>> +		.reset_val = FMC2_BUSWIDTH_16,
>> +		.set = stm32_fmc2_ebi_set_buswidth,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-waitpol-high",
>> +		.bprop = true,
>> +		.reg_type = FMC2_REG_BCR,
>> +		.reg_mask = FMC2_BCR_WAITPOL,
>> +		.set = stm32_fmc2_ebi_set_bit_field,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-waitcfg-enable",
>> +		.bprop = true,
>> +		.reg_type = FMC2_REG_BCR,
>> +		.reg_mask = FMC2_BCR_WAITCFG,
>> +		.check = stm32_fmc2_ebi_check_waitcfg,
>> +		.set = stm32_fmc2_ebi_set_bit_field,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-wait-enable",
>> +		.bprop = true,
>> +		.reg_type = FMC2_REG_BCR,
>> +		.reg_mask = FMC2_BCR_WAITEN,
>> +		.check = stm32_fmc2_ebi_check_sync_trans,
>> +		.set = stm32_fmc2_ebi_set_bit_field,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-asyncwait-enable",
>> +		.bprop = true,
>> +		.reg_type = FMC2_REG_BCR,
>> +		.reg_mask = FMC2_BCR_ASYNCWAIT,
>> +		.check = stm32_fmc2_ebi_check_async_trans,
>> +		.set = stm32_fmc2_ebi_set_bit_field,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-cpsize",
>> +		.check = stm32_fmc2_ebi_check_cpsize,
>> +		.set = stm32_fmc2_ebi_set_cpsize,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-byte-lane-setup-ns",
>> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
>> +		.set = stm32_fmc2_ebi_set_bl_setup,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-address-setup-ns",
>> +		.reg_type = FMC2_REG_BTR,
>> +		.reset_val = FMC2_BXTR_ADDSET_MAX,
>> +		.check = stm32_fmc2_ebi_check_async_trans,
>> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
>> +		.set = stm32_fmc2_ebi_set_address_setup,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-address-hold-ns",
>> +		.reg_type = FMC2_REG_BTR,
>> +		.reset_val = FMC2_BXTR_ADDHLD_MAX,
>> +		.check = stm32_fmc2_ebi_check_address_hold,
>> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
>> +		.set = stm32_fmc2_ebi_set_address_hold,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-data-setup-ns",
>> +		.reg_type = FMC2_REG_BTR,
>> +		.reset_val = FMC2_BXTR_DATAST_MAX,
>> +		.check = stm32_fmc2_ebi_check_async_trans,
>> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
>> +		.set = stm32_fmc2_ebi_set_data_setup,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-bus-turnaround-ns",
>> +		.reg_type = FMC2_REG_BTR,
>> +		.reset_val = FMC2_BXTR_BUSTURN_MAX + 1,
>> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
>> +		.set = stm32_fmc2_ebi_set_bus_turnaround,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-data-hold-ns",
>> +		.reg_type = FMC2_REG_BTR,
>> +		.check = stm32_fmc2_ebi_check_async_trans,
>> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
>> +		.set = stm32_fmc2_ebi_set_data_hold,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-clk-period-ns",
>> +		.reset_val = FMC2_BTR_CLKDIV_MAX + 1,
>> +		.check = stm32_fmc2_ebi_check_clk_period,
>> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
>> +		.set = stm32_fmc2_ebi_set_clk_period,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-data-latency-ns",
>> +		.check = stm32_fmc2_ebi_check_sync_trans,
>> +		.calculate = stm32_fmc2_ebi_ns_to_clk_period,
>> +		.set = stm32_fmc2_ebi_set_data_latency,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-write-address-setup-ns",
>> +		.reg_type = FMC2_REG_BWTR,
>> +		.reset_val = FMC2_BXTR_ADDSET_MAX,
>> +		.check = stm32_fmc2_ebi_check_async_trans,
>> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
>> +		.set = stm32_fmc2_ebi_set_address_setup,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-write-address-hold-ns",
>> +		.reg_type = FMC2_REG_BWTR,
>> +		.reset_val = FMC2_BXTR_ADDHLD_MAX,
>> +		.check = stm32_fmc2_ebi_check_address_hold,
>> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
>> +		.set = stm32_fmc2_ebi_set_address_hold,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-write-data-setup-ns",
>> +		.reg_type = FMC2_REG_BWTR,
>> +		.reset_val = FMC2_BXTR_DATAST_MAX,
>> +		.check = stm32_fmc2_ebi_check_async_trans,
>> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
>> +		.set = stm32_fmc2_ebi_set_data_setup,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-write-bus-turnaround-ns",
>> +		.reg_type = FMC2_REG_BWTR,
>> +		.reset_val = FMC2_BXTR_BUSTURN_MAX + 1,
>> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
>> +		.set = stm32_fmc2_ebi_set_bus_turnaround,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-write-data-hold-ns",
>> +		.reg_type = FMC2_REG_BWTR,
>> +		.check = stm32_fmc2_ebi_check_async_trans,
>> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
>> +		.set = stm32_fmc2_ebi_set_data_hold,
>> +	},
>> +	{
>> +		.name = "st,fmc2-ebi-cs-max-low-pulse-ns",
>> +		.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
>> +		.set = stm32_fmc2_ebi_set_max_low_pulse,
>> +	},
>> +};
>> +
>> +static int stm32_fmc2_ebi_parse_prop(struct stm32_fmc2_ebi *ebi,
>> +				     ofnode node,
>> +				     const struct stm32_fmc2_prop *prop,
>> +				     int cs)
>> +{
>> +	u32 setup = 0;
>> +
>> +	if (!prop->set) {
>> +		pr_err("property %s is not well defined\n", prop->name);
>> +		return -EINVAL;
>> +	}
>> +
>> +	if (prop->check && prop->check(ebi, prop, cs))
>> +		/* Skip this property */
>> +		return 0;
>> +
>> +	if (prop->bprop) {
>> +		bool bprop;
>> +
>> +		bprop = ofnode_read_bool(node, prop->name);
>> +		if (prop->mprop && !bprop) {
>> +			pr_err("mandatory property %s not defined in the device tree\n",
>> +			       prop->name);
>> +			return -EINVAL;
>> +		}
>> +
>> +		if (bprop)
>> +			setup = 1;
>> +	} else {
>> +		u32 val;
>> +		int ret;
>> +
>> +		ret = ofnode_read_u32(node, prop->name, &val);
>> +		if (prop->mprop && ret) {
>> +			pr_err("mandatory property %s not defined in the device tree\n",
>> +			       prop->name);
>> +			return ret;
>> +		}
>> +
>> +		if (ret)
>> +			setup = prop->reset_val;
>> +		else if (prop->calculate)
>> +			setup = prop->calculate(ebi, cs, val);
>> +		else
>> +			setup = val;
>> +	}
>> +
>> +	return prop->set(ebi, prop, cs, setup);
>> +}
>> +
>> +static void stm32_fmc2_ebi_enable_bank(struct stm32_fmc2_ebi *ebi, int cs)
>> +{
>> +	setbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_MBKEN);
>> +}
>> +
>> +static void stm32_fmc2_ebi_disable_bank(struct stm32_fmc2_ebi *ebi, int cs)
>> +{
>> +	clrbits_le32(ebi->io_base + FMC2_BCR(cs), FMC2_BCR_MBKEN);
>> +}
>> +
>> +/* NWAIT signal can not be connected to EBI controller and NAND controller */
>> +static bool stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi)
>> +{
>> +	unsigned int cs;
>> +	u32 bcr;
>> +
>> +	for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) {
>> +		if (!(ebi->bank_assigned & BIT(cs)))
>> +			continue;
>> +
>> +		bcr = readl(ebi->io_base + FMC2_BCR(cs));
>> +		if ((bcr & FMC2_BCR_WAITEN || bcr & FMC2_BCR_ASYNCWAIT) &&
>> +		    ebi->bank_assigned & BIT(FMC2_NAND))
>> +			return true;
>> +	}
>> +
>> +	return false;
>> +}
>> +
>> +static void stm32_fmc2_ebi_enable(struct stm32_fmc2_ebi *ebi)
>> +{
>> +	setbits_le32(ebi->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
>> +}
>> +
>> +static int stm32_fmc2_ebi_setup_cs(struct stm32_fmc2_ebi *ebi,
>> +				   ofnode node, u32 cs)
>> +{
>> +	unsigned int i;
>> +	int ret;
>> +
>> +	stm32_fmc2_ebi_disable_bank(ebi, cs);
>> +
>> +	for (i = 0; i < ARRAY_SIZE(stm32_fmc2_child_props); i++) {
>> +		const struct stm32_fmc2_prop *p = &stm32_fmc2_child_props[i];
>> +
>> +		ret = stm32_fmc2_ebi_parse_prop(ebi, node, p, cs);
>> +		if (ret) {
>> +			pr_err("property %s could not be set: %d\n",
>> +			       p->name, ret);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	stm32_fmc2_ebi_enable_bank(ebi, cs);
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_fmc2_ebi_parse_dt(struct udevice *dev,
>> +				   struct stm32_fmc2_ebi *ebi)
>> +{
>> +	ofnode child;
>> +	bool child_found = false;
>> +	u32 bank;
>> +	int ret;
>> +
>> +	dev_for_each_subnode(child, dev) {
>> +		ret = ofnode_read_u32(child, "reg", &bank);
>> +		if (ret) {
>> +			pr_err("could not retrieve reg property: %d\n", ret);
>> +			return ret;
>> +		}
>> +
>> +		if (bank >= FMC2_MAX_BANKS) {
>> +			pr_err("invalid reg value: %d\n", bank);
>> +			return -EINVAL;
>> +		}
>> +
>> +		if (ebi->bank_assigned & BIT(bank)) {
>> +			pr_err("bank already assigned: %d\n", bank);
>> +			return -EINVAL;
>> +		}
>> +
>> +		if (bank < FMC2_MAX_EBI_CE) {
>> +			ret = stm32_fmc2_ebi_setup_cs(ebi, child, bank);
>> +			if (ret) {
>> +				pr_err("setup chip select %d failed: %d\n",
>> +				       bank, ret);
>> +				return ret;
>> +			}
>> +		}
>> +
>> +		ebi->bank_assigned |= BIT(bank);
>> +		child_found = true;
>> +	}
>> +
>> +	if (!child_found) {
>> +		pr_warn("no subnodes found, disable the driver.\n");
>> +		return -ENODEV;
>> +	}
>> +
>> +	if (stm32_fmc2_ebi_nwait_used_by_ctrls(ebi)) {
>> +		pr_err("NWAIT signal connected to EBI and NAND controllers\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	stm32_fmc2_ebi_enable(ebi);
>> +
>> +	return 0;
>> +}
>> +
>> +static int stm32_fmc2_ebi_probe(struct udevice *dev)
>> +{
>> +	struct stm32_fmc2_ebi *ebi = dev_get_priv(dev);
>> +	struct reset_ctl reset;
>> +	int ret;
>> +
>> +	ebi->io_base = dev_read_addr(dev);
>> +	if (ebi->io_base == FDT_ADDR_T_NONE)
>> +		return -EINVAL;
>> +
>> +	ret = clk_get_by_index(dev, 0, &ebi->clk);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = clk_enable(&ebi->clk);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = reset_get_by_index(dev, 0, &reset);
>> +	if (!ret) {
>> +		reset_assert(&reset);
>> +		udelay(2);
>> +		reset_deassert(&reset);
>> +	}
>> +
>> +	return stm32_fmc2_ebi_parse_dt(dev, ebi);
>> +}
>> +
>> +static const struct udevice_id stm32_fmc2_ebi_match[] = {
>> +	{.compatible = "st,stm32mp1-fmc2-ebi"},
>> +	{ /* Sentinel */ }
>> +};
>> +
>> +U_BOOT_DRIVER(stm32_fmc2_ebi) = {
>> +	.name = "stm32_fmc2_ebi",
>> +	.id = UCLASS_NOP,
>> +	.of_match = stm32_fmc2_ebi_match,
>> +	.probe = stm32_fmc2_ebi_probe,
>> +	.priv_auto_alloc_size = sizeof(struct stm32_fmc2_ebi),
>> +	.bind = dm_scan_fdt_dev,
>> +};
> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
>
> Thanks
>
> Patrice
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 08/11] mtd: rawnand: stm32_fmc2: get resources from parent node
  2020-08-13  7:33   ` Patrice CHOTARD
@ 2020-08-13  9:58     ` Patrice CHOTARD
  0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  9:58 UTC (permalink / raw)
  To: u-boot


On 8/13/20 9:33 AM, Patrice CHOTARD wrote:
> Hi Christophe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> FMC2 EBI support has been added. Common resources (registers base
>> address and clock) can now be shared between the 2 drivers using
>> "st,stm32mp1-fmc2-nfc" compatible string. It means that the
>> common resources should now be found in the parent device when EBI
>> node is available.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 87 +++++++++++++++++++++++-----------
>>  1 file changed, 59 insertions(+), 28 deletions(-)

Applied on u-boot-stm/master

Thanks

>>
>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> index 1e4d757..47fe610 100644
>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> @@ -158,10 +158,10 @@ struct stm32_fmc2_nfc {
>>  	struct nand_hw_control base;
>>  	struct stm32_fmc2_nand nand;
>>  	struct nand_ecclayout ecclayout;
>> -	void __iomem *io_base;
>> -	void __iomem *data_base[FMC2_MAX_CE];
>> -	void __iomem *cmd_base[FMC2_MAX_CE];
>> -	void __iomem *addr_base[FMC2_MAX_CE];
>> +	fdt_addr_t io_base;
>> +	fdt_addr_t data_base[FMC2_MAX_CE];
>> +	fdt_addr_t cmd_base[FMC2_MAX_CE];
>> +	fdt_addr_t addr_base[FMC2_MAX_CE];
>>  	struct clk clk;
>>  
>>  	u8 cs_assigned;
>> @@ -241,8 +241,8 @@ static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
>>  		return;
>>  
>>  	nfc->cs_sel = nand->cs_used[chipnr];
>> -	chip->IO_ADDR_R = nfc->data_base[nfc->cs_sel];
>> -	chip->IO_ADDR_W = nfc->data_base[nfc->cs_sel];
>> +	chip->IO_ADDR_R = (void __iomem *)nfc->data_base[nfc->cs_sel];
>> +	chip->IO_ADDR_W = (void __iomem *)nfc->data_base[nfc->cs_sel];
>>  
>>  	stm32_fmc2_nfc_setup(chip);
>>  	stm32_fmc2_nfc_timings_init(chip);
>> @@ -548,7 +548,7 @@ static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
>>  	return max_bitflips;
>>  }
>>  
>> -static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>> +static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc, bool has_parent)
>>  {
>>  	u32 pcr = readl(nfc->io_base + FMC2_PCR);
>>  
>> @@ -581,7 +581,8 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>>  	pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
>>  
>>  	/* Enable FMC2 controller */
>> -	setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
>> +	if (!has_parent)
>> +		setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
>>  
>>  	writel(pcr, nfc->io_base + FMC2_PCR);
>>  	writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
>> @@ -854,6 +855,30 @@ static int stm32_fmc2_nfc_parse_dt(struct udevice *dev,
>>  	return 0;
>>  }
>>  
>> +static struct udevice *stm32_fmc2_nfc_get_cdev(struct udevice *dev)
>> +{
>> +	struct udevice *pdev = dev_get_parent(dev);
>> +	struct udevice *cdev = NULL;
>> +	bool ebi_found = false;
>> +
>> +	if (pdev && ofnode_device_is_compatible(dev_ofnode(pdev),
>> +						"st,stm32mp1-fmc2-ebi"))
>> +		ebi_found = true;
>> +
>> +	if (ofnode_device_is_compatible(dev_ofnode(dev),
>> +					"st,stm32mp1-fmc2-nfc")) {
>> +		if (ebi_found)
>> +			cdev = pdev;
>> +
>> +		return cdev;
>> +	}
>> +
>> +	if (!ebi_found)
>> +		cdev = dev;
>> +
>> +	return cdev;
>> +}
>> +
>>  static int stm32_fmc2_nfc_probe(struct udevice *dev)
>>  {
>>  	struct stm32_fmc2_nfc *nfc = dev_get_priv(dev);
>> @@ -861,58 +886,63 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
>>  	struct nand_chip *chip = &nand->chip;
>>  	struct mtd_info *mtd = &chip->mtd;
>>  	struct nand_ecclayout *ecclayout;
>> -	struct resource resource;
>> +	struct udevice *cdev;
>>  	struct reset_ctl reset;
>>  	int oob_index, chip_cs, mem_region, ret;
>>  	unsigned int i;
>> +	int start_region = 0;
>> +	fdt_addr_t addr;
>>  
>>  	spin_lock_init(&nfc->controller.lock);
>>  	init_waitqueue_head(&nfc->controller.wq);
>>  
>> +	cdev = stm32_fmc2_nfc_get_cdev(dev);
>> +	if (!cdev)
>> +		return -EINVAL;
>> +
>>  	ret = stm32_fmc2_nfc_parse_dt(dev, nfc);
>>  	if (ret)
>>  		return ret;
>>  
>> -	/* Get resources */
>> -	ret = dev_read_resource(dev, 0, &resource);
>> -	if (ret) {
>> -		pr_err("Resource io_base not found");
>> -		return ret;
>> -	}
>> -	nfc->io_base = (void __iomem *)resource.start;
>> +	nfc->io_base = dev_read_addr(cdev);
>> +	if (nfc->io_base == FDT_ADDR_T_NONE)
>> +		return -EINVAL;
>> +
>> +	if (dev == cdev)
>> +		start_region = 1;
>>  
>> -	for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
>> +	for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE;
>>  	     chip_cs++, mem_region += 3) {
>>  		if (!(nfc->cs_assigned & BIT(chip_cs)))
>>  			continue;
>>  
>> -		ret = dev_read_resource(dev, mem_region, &resource);
>> -		if (ret) {
>> +		addr = dev_read_addr_index(dev, mem_region);
>> +		if (addr == FDT_ADDR_T_NONE) {
>>  			pr_err("Resource data_base not found for cs%d",
>>  			       chip_cs);
>>  			return ret;
>>  		}
>> -		nfc->data_base[chip_cs] = (void __iomem *)resource.start;
>> +		nfc->data_base[chip_cs] = addr;
>>  
>> -		ret = dev_read_resource(dev, mem_region + 1, &resource);
>> -		if (ret) {
>> +		addr = dev_read_addr_index(dev, mem_region + 1);
>> +		if (addr == FDT_ADDR_T_NONE) {
>>  			pr_err("Resource cmd_base not found for cs%d",
>>  			       chip_cs);
>>  			return ret;
>>  		}
>> -		nfc->cmd_base[chip_cs] = (void __iomem *)resource.start;
>> +		nfc->cmd_base[chip_cs] = addr;
>>  
>> -		ret = dev_read_resource(dev, mem_region + 2, &resource);
>> -		if (ret) {
>> +		addr = dev_read_addr_index(dev, mem_region + 2);
>> +		if (addr == FDT_ADDR_T_NONE) {
>>  			pr_err("Resource addr_base not found for cs%d",
>>  			       chip_cs);
>>  			return ret;
>>  		}
>> -		nfc->addr_base[chip_cs] = (void __iomem *)resource.start;
>> +		nfc->addr_base[chip_cs] = addr;
>>  	}
>>  
>>  	/* Enable the clock */
>> -	ret = clk_get_by_index(dev, 0, &nfc->clk);
>> +	ret = clk_get_by_index(cdev, 0, &nfc->clk);
>>  	if (ret)
>>  		return ret;
>>  
>> @@ -928,7 +958,7 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
>>  		reset_deassert(&reset);
>>  	}
>>  
>> -	stm32_fmc2_nfc_init(nfc);
>> +	stm32_fmc2_nfc_init(nfc, dev != cdev);
>>  
>>  	chip->controller = &nfc->base;
>>  	chip->select_chip = stm32_fmc2_nfc_select_chip;
>> @@ -994,6 +1024,7 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
>>  
>>  static const struct udevice_id stm32_fmc2_nfc_match[] = {
>>  	{ .compatible = "st,stm32mp15-fmc2" },
>> +	{ .compatible = "st,stm32mp1-fmc2-nfc" },
>>  	{ /* Sentinel */ }
>>  };
>>  
> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
>
> Thanks
>
> Patrice
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 10/11] configs: stm32mp: add CONFIG_STM32_FMC2_EBI
  2020-08-13  7:35   ` Patrice CHOTARD
@ 2020-08-13  9:59     ` Patrice CHOTARD
  0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  9:59 UTC (permalink / raw)
  To: u-boot


On 8/13/20 9:35 AM, Patrice CHOTARD wrote:
> Hi Christophe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> This patch enables the support of FMC2 EBI.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>>  configs/stm32mp15_basic_defconfig   | 1 +
>>  configs/stm32mp15_trusted_defconfig | 1 +
>>  2 files changed, 2 insertions(+)

Applied on u-boot-stm/master

Thanks

>>
>> diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig
>> index 5c500a1..2094183 100644
>> --- a/configs/stm32mp15_basic_defconfig
>> +++ b/configs/stm32mp15_basic_defconfig
>> @@ -88,6 +88,7 @@ CONFIG_LED=y
>>  CONFIG_LED_GPIO=y
>>  CONFIG_DM_MAILBOX=y
>>  CONFIG_STM32_IPCC=y
>> +CONFIG_STM32_FMC2_EBI=y
>>  CONFIG_DM_MMC=y
>>  CONFIG_SUPPORT_EMMC_BOOT=y
>>  CONFIG_STM32_SDMMC2=y
>> diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig
>> index 98680cb..8d59d84 100644
>> --- a/configs/stm32mp15_trusted_defconfig
>> +++ b/configs/stm32mp15_trusted_defconfig
>> @@ -68,6 +68,7 @@ CONFIG_LED=y
>>  CONFIG_LED_GPIO=y
>>  CONFIG_DM_MAILBOX=y
>>  CONFIG_STM32_IPCC=y
>> +CONFIG_STM32_FMC2_EBI=y
>>  CONFIG_DM_MMC=y
>>  CONFIG_SUPPORT_EMMC_BOOT=y
>>  CONFIG_STM32_SDMMC2=y
> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
>
> Thanks
>
> Patrice
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 11/11] ARM: dts: stm32: add FMC2 EBI support for stm32mp157c
  2020-08-13  7:37   ` Patrice CHOTARD
@ 2020-08-13  9:59     ` Patrice CHOTARD
  0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13  9:59 UTC (permalink / raw)
  To: u-boot


On 8/13/20 9:36 AM, Patrice CHOTARD wrote:
> Hi Christophe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> This patch adds FMC2 External Bus Interface support on stm32mp157c.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>>  arch/arm/dts/stm32mp151.dtsi     | 43 +++++++++++++++++++++++++++-------------
>>  arch/arm/dts/stm32mp157c-ev1.dts | 16 ++++++++-------
>>  2 files changed, 38 insertions(+), 21 deletions(-)

Applied on u-boot-stm/master

Thanks

>>
>> diff --git a/arch/arm/dts/stm32mp151.dtsi b/arch/arm/dts/stm32mp151.dtsi
>> index 0d97f56..39d9e54 100644
>> --- a/arch/arm/dts/stm32mp151.dtsi
>> +++ b/arch/arm/dts/stm32mp151.dtsi
>> @@ -1328,23 +1328,38 @@
>>  			dma-requests = <48>;
>>  		};
>>  
>> -		fmc: nand-controller at 58002000 {
>> -			compatible = "st,stm32mp15-fmc2";
>> -			reg = <0x58002000 0x1000>,
>> -			      <0x80000000 0x1000>,
>> -			      <0x88010000 0x1000>,
>> -			      <0x88020000 0x1000>,
>> -			      <0x81000000 0x1000>,
>> -			      <0x89010000 0x1000>,
>> -			      <0x89020000 0x1000>;
>> -			interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
>> -			dmas = <&mdma1 20 0x10 0x12000a02 0x0 0x0>,
>> -			       <&mdma1 20 0x10 0x12000a08 0x0 0x0>,
>> -			       <&mdma1 21 0x10 0x12000a0a 0x0 0x0>;
>> -			dma-names = "tx", "rx", "ecc";
>> +		fmc: memory-controller at 58002000 {
>> +			#address-cells = <2>;
>> +			#size-cells = <1>;
>> +			compatible = "st,stm32mp1-fmc2-ebi";
>> +			reg = <0x58002000 0x1000>;
>>  			clocks = <&rcc FMC_K>;
>>  			resets = <&rcc FMC_R>;
>>  			status = "disabled";
>> +
>> +			ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */
>> +				 <1 0 0x64000000 0x04000000>, /* EBI CS 2 */
>> +				 <2 0 0x68000000 0x04000000>, /* EBI CS 3 */
>> +				 <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */
>> +				 <4 0 0x80000000 0x10000000>; /* NAND */
>> +
>> +			nand-controller at 4,0 {
>> +				#address-cells = <1>;
>> +				#size-cells = <0>;
>> +				compatible = "st,stm32mp1-fmc2-nfc";
>> +				reg = <4 0x00000000 0x1000>,
>> +				      <4 0x08010000 0x1000>,
>> +				      <4 0x08020000 0x1000>,
>> +				      <4 0x01000000 0x1000>,
>> +				      <4 0x09010000 0x1000>,
>> +				      <4 0x09020000 0x1000>;
>> +				interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
>> +				dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
>> +				       <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
>> +				       <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
>> +				dma-names = "tx", "rx", "ecc";
>> +				status = "disabled";
>> +			};
>>  		};
>>  
>>  		qspi: spi at 58003000 {
>> diff --git a/arch/arm/dts/stm32mp157c-ev1.dts b/arch/arm/dts/stm32mp157c-ev1.dts
>> index b190565..46f81ce 100644
>> --- a/arch/arm/dts/stm32mp157c-ev1.dts
>> +++ b/arch/arm/dts/stm32mp157c-ev1.dts
>> @@ -157,14 +157,16 @@
>>  	pinctrl-0 = <&fmc_pins_a>;
>>  	pinctrl-1 = <&fmc_sleep_pins_a>;
>>  	status = "okay";
>> -	#address-cells = <1>;
>> -	#size-cells = <0>;
>>  
>> -	nand at 0 {
>> -		reg = <0>;
>> -		nand-on-flash-bbt;
>> -		#address-cells = <1>;
>> -		#size-cells = <1>;
>> +	nand-controller at 4,0 {
>> +		status = "okay";
>> +
>> +		nand at 0 {
>> +			reg = <0>;
>> +			nand-on-flash-bbt;
>> +			#address-cells = <1>;
>> +			#size-cells = <1>;
>> +		};
>>  	};
>>  };
>>  
> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
>
> Thanks
>
> Patrice
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2020-08-13  9:59 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-31  7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
2020-07-31  7:53 ` [PATCH 01/11] mtd: rawnand: stm32_fmc2: fix a buffer overflow Christophe Kerello
2020-08-13  7:27   ` Patrice CHOTARD
2020-08-13  9:56     ` Patrice CHOTARD
2020-07-31  7:53 ` [PATCH 02/11] mtd: rawnand: stm32_fmc2: remove useless inline comments Christophe Kerello
2020-08-13  7:28   ` Patrice CHOTARD
2020-08-13  9:56     ` Patrice CHOTARD
2020-07-31  7:53 ` [PATCH 03/11] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_5S for timeouts Christophe Kerello
2020-08-13  7:29   ` Patrice CHOTARD
2020-08-13  9:57     ` Patrice CHOTARD
2020-07-31  7:53 ` [PATCH 04/11] mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2 where relevant Christophe Kerello
2020-08-13  7:29   ` Patrice CHOTARD
2020-08-13  9:57   ` Patrice CHOTARD
2020-07-31  7:53 ` [PATCH 05/11] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros Christophe Kerello
2020-08-13  7:29   ` Patrice CHOTARD
2020-08-13  9:58     ` Patrice CHOTARD
2020-07-31  7:53 ` [PATCH 06/11] mtd: rawnand: stm32_fmc2: use clrsetbits_le32 Christophe Kerello
2020-08-13  7:30   ` Patrice CHOTARD
2020-08-13  9:58     ` Patrice CHOTARD
2020-07-31  7:53 ` [PATCH 07/11] memory: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver Christophe Kerello
2020-08-13  7:31   ` Patrice CHOTARD
2020-08-13  9:58     ` Patrice CHOTARD
2020-07-31  7:53 ` [PATCH 08/11] mtd: rawnand: stm32_fmc2: get resources from parent node Christophe Kerello
2020-08-13  7:33   ` Patrice CHOTARD
2020-08-13  9:58     ` Patrice CHOTARD
2020-07-31  7:53 ` [PATCH 09/11] board: stm32mp1: update fdt fixup partitions table Christophe Kerello
2020-08-13  7:34   ` Patrice CHOTARD
2020-07-31  7:53 ` [PATCH 10/11] configs: stm32mp: add CONFIG_STM32_FMC2_EBI Christophe Kerello
2020-08-13  7:35   ` Patrice CHOTARD
2020-08-13  9:59     ` Patrice CHOTARD
2020-07-31  7:53 ` [PATCH 11/11] ARM: dts: stm32: add FMC2 EBI support for stm32mp157c Christophe Kerello
2020-08-13  7:37   ` Patrice CHOTARD
2020-08-13  9:59     ` Patrice CHOTARD

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.