[PATCH 00/11] Add STM32 FMC2 EBI controller driver

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

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;

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

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

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;

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

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

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;

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);
if (ret < 0) { pr_err("Ham timeout\n"); return ret;sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
@@ -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);
if (ret < 0) { pr_err("Bch timeout\n"); return ret;bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
@@ -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);
if (ret < 0) { pr_err("Bch timeout\n"); return ret;bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
Reviewed-by: Patrice Chotard patrice.chotard@st.com
Thanks
Patrice

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);
if (ret < 0) { pr_err("Ham timeout\n"); return ret;sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
@@ -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);
if (ret < 0) { pr_err("Bch timeout\n"); return ret;bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
@@ -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);
if (ret < 0) { pr_err("Bch timeout\n"); return ret;bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
Reviewed-by: Patrice Chotard patrice.chotard@st.com
Thanks
Patrice

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); }

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]);
return; }writeb(cmd, nfc->cmd_base[nfc->cs_sel]);
- 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);
ecc[8] = bchpbr; ecc[9] = bchpbr >> 8; ecc[10] = bchpbr >> 16; ecc[11] = bchpbr >> 24;bchpbr = readl(nfc->io_base + FMC2_BCHPBR3);
bchpbr = readl(fmc2->io_base + FMC2_BCHPBR4);
ecc[12] = bchpbr; }bchpbr = readl(nfc->io_base + FMC2_BCHPBR4);
- 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]);
nand->cs_used[i] = cs[i]; }nfc->cs_assigned |= BIT(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);
if (ret) return ret; }ret = stm32_fmc2_nfc_parse_child(nfc, child);
@@ -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),
if (ret && ret != -ENODEV)DM_GET_DRIVER(stm32_fmc2_nfc), &dev);
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

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]);
return; }writeb(cmd, nfc->cmd_base[nfc->cs_sel]);
- 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);
ecc[8] = bchpbr; ecc[9] = bchpbr >> 8; ecc[10] = bchpbr >> 16; ecc[11] = bchpbr >> 24;bchpbr = readl(nfc->io_base + FMC2_BCHPBR3);
bchpbr = readl(fmc2->io_base + FMC2_BCHPBR4);
ecc[12] = bchpbr; }bchpbr = readl(nfc->io_base + FMC2_BCHPBR4);
- 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]);
nand->cs_used[i] = cs[i]; }nfc->cs_assigned |= BIT(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);
if (ret) return ret; }ret = stm32_fmc2_nfc_parse_child(nfc, child);
@@ -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),
if (ret && ret != -ENODEV)DM_GET_DRIVER(stm32_fmc2_nfc), &dev);
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);
}

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;

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);
writel(pcr, nfc->io_base + FMC2_PCR);pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
}
@@ -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

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);
writel(pcr, nfc->io_base + FMC2_PCR);pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
}
@@ -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

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);

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

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

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, ®); + 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, ®); + 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, ®); + 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, ®); + 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, ®); + 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, ®); + 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, +};

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, ®);
- 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, ®);
- 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, ®);
- 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, ®);
- 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, ®);
- 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, ®);
- 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

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, ®);
- 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, ®);
- 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, ®);
- 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, ®);
- 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, ®);
- 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, ®);
- 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

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 */ } };

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

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

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

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, },
}; fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));{ "st,stm32mp1-fmc2-nfc", MTD_DEV_TYPE_NAND, },
#endif
Reviewed-by: Patrice Chotard patrice.chotard@st.com
Thanks
Patrice

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

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

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

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@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@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@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@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@0 { - reg = <0>; - nand-on-flash-bbt; - #address-cells = <1>; - #size-cells = <1>; + nand-controller@4,0 { + status = "okay"; + + nand@0 { + reg = <0>; + nand-on-flash-bbt; + #address-cells = <1>; + #size-cells = <1>; + }; }; };

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@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@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@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@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@0 {
reg = <0>;
nand-on-flash-bbt;
#address-cells = <1>;
#size-cells = <1>;
- nand-controller@4,0 {
status = "okay";
nand@0 {
reg = <0>;
nand-on-flash-bbt;
#address-cells = <1>;
#size-cells = <1>;
};};
};
Reviewed-by: Patrice Chotard patrice.chotard@st.com
Thanks
Patrice

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@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@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@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@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@0 {
reg = <0>;
nand-on-flash-bbt;
#address-cells = <1>;
#size-cells = <1>;
- nand-controller@4,0 {
status = "okay";
nand@0 {
reg = <0>;
nand-on-flash-bbt;
#address-cells = <1>;
#size-cells = <1>;
};};
};
Reviewed-by: Patrice Chotard patrice.chotard@st.com
Thanks
Patrice
participants (2)
-
Christophe Kerello
-
Patrice CHOTARD