* [PATCH 00/11] Add STM32 FMC2 EBI controller driver
@ 2020-07-31 7:53 Christophe Kerello
2020-07-31 7:53 ` [PATCH 01/11] mtd: rawnand: stm32_fmc2: fix a buffer overflow Christophe Kerello
` (10 more replies)
0 siblings, 11 replies; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31 7:53 UTC (permalink / raw)
To: u-boot
The FMC2 functional block makes the interface with: synchronous and
asynchronous static devices (such as PSNOR, PSRAM or other memory-mapped
peripherals) and NAND flash memories.
Its main purposes are:
- to translate AXI transactions into the appropriate external device
protocol
- to meet the access time requirements of the external devices
All external devices share the addresses, data and control signals with the
controller. Each external device is accessed by means of a unique Chip
Select. The FMC2 performs only one access at a time to an external device.
Christophe Kerello (11):
mtd: rawnand: stm32_fmc2: fix a buffer overflow
mtd: rawnand: stm32_fmc2: remove useless inline comments
mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_5S for timeouts
mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2
where relevant
mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros
mtd: rawnand: stm32_fmc2: use clrsetbits_le32
memory: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver
mtd: rawnand: stm32_fmc2: get resources from parent node
board: stm32mp1: update fdt fixup partitions table
configs: stm32mp: add CONFIG_STM32_FMC2_EBI
ARM: dts: stm32: add FMC2 EBI support for stm32mp157c
arch/arm/dts/stm32mp151.dtsi | 43 +-
arch/arm/dts/stm32mp157c-ev1.dts | 16 +-
board/st/stm32mp1/stm32mp1.c | 1 +
configs/stm32mp15_basic_defconfig | 1 +
configs/stm32mp15_trusted_defconfig | 1 +
drivers/memory/Kconfig | 9 +
drivers/memory/Makefile | 1 +
drivers/memory/stm32-fmc2-ebi.c | 1056 ++++++++++++++++++++++++++++++++
drivers/mtd/nand/raw/stm32_fmc2_nand.c | 499 ++++++++-------
9 files changed, 1349 insertions(+), 278 deletions(-)
create mode 100644 drivers/memory/stm32-fmc2-ebi.c
--
1.9.1
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 01/11] mtd: rawnand: stm32_fmc2: fix a buffer overflow
2020-07-31 7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
@ 2020-07-31 7:53 ` Christophe Kerello
2020-08-13 7:27 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 02/11] mtd: rawnand: stm32_fmc2: remove useless inline comments Christophe Kerello
` (9 subsequent siblings)
10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31 7:53 UTC (permalink / raw)
To: u-boot
The chip select defined in the device tree could only be 0 or 1.
Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
drivers/mtd/nand/raw/stm32_fmc2_nand.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 3306bd8..2929acf 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -846,7 +846,7 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
}
for (i = 0; i < nand->ncs; i++) {
- if (cs[i] > FMC2_MAX_CE) {
+ if (cs[i] >= FMC2_MAX_CE) {
pr_err("Invalid reg value: %d\n",
nand->cs_used[i]);
return -EINVAL;
--
1.9.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 02/11] mtd: rawnand: stm32_fmc2: remove useless inline comments
2020-07-31 7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
2020-07-31 7:53 ` [PATCH 01/11] mtd: rawnand: stm32_fmc2: fix a buffer overflow Christophe Kerello
@ 2020-07-31 7:53 ` Christophe Kerello
2020-08-13 7:28 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 03/11] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_5S for timeouts Christophe Kerello
` (8 subsequent siblings)
10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31 7:53 UTC (permalink / raw)
To: u-boot
Remove inline comments that are useless since function label are
self explanatory.
Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
drivers/mtd/nand/raw/stm32_fmc2_nand.c | 25 -------------------------
1 file changed, 25 deletions(-)
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 2929acf..f43e3ec 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -179,7 +179,6 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_hw_control *base)
return container_of(base, struct stm32_fmc2_nfc, base);
}
-/* Timings configuration */
static void stm32_fmc2_timings_init(struct nand_chip *chip)
{
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
@@ -211,7 +210,6 @@ static void stm32_fmc2_timings_init(struct nand_chip *chip)
writel(patt, fmc2->io_base + FMC2_PATT);
}
-/* Controller configuration */
static void stm32_fmc2_setup(struct nand_chip *chip)
{
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
@@ -239,7 +237,6 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
writel(pcr, fmc2->io_base + FMC2_PCR);
}
-/* Select target */
static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
{
struct nand_chip *chip = mtd_to_nand(mtd);
@@ -256,14 +253,10 @@ static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel];
chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel];
- /* FMC2 setup routine */
stm32_fmc2_setup(chip);
-
- /* Apply timings */
stm32_fmc2_timings_init(chip);
}
-/* Set bus width to 16-bit or 8-bit */
static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
{
u32 pcr = readl(fmc2->io_base + FMC2_PCR);
@@ -274,7 +267,6 @@ static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
writel(pcr, fmc2->io_base + FMC2_PCR);
}
-/* Enable/disable ECC */
static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
{
u32 pcr = readl(fmc2->io_base + FMC2_PCR);
@@ -285,13 +277,11 @@ static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
writel(pcr, fmc2->io_base + FMC2_PCR);
}
-/* Clear irq sources in case of bch is used */
static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
{
writel(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
}
-/* Send command and address cycles */
static void stm32_fmc2_cmd_ctrl(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
{
@@ -361,7 +351,6 @@ static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
ecc[1] = heccr >> 8;
ecc[2] = heccr >> 16;
- /* Disable ecc */
stm32_fmc2_set_ecc(fmc2, false);
return 0;
@@ -466,13 +455,11 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
ecc[12] = bchpbr;
}
- /* Disable ecc */
stm32_fmc2_set_ecc(fmc2, false);
return 0;
}
-/* BCH algorithm correction */
static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
u8 *read_ecc, u8 *calc_ecc)
{
@@ -497,7 +484,6 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3);
bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4);
- /* Disable ECC */
stm32_fmc2_set_ecc(fmc2, false);
/* No errors found */
@@ -579,7 +565,6 @@ static int stm32_fmc2_read_page(struct mtd_info *mtd,
return max_bitflips;
}
-/* Controller initialization */
static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
{
u32 pcr = readl(fmc2->io_base + FMC2_PCR);
@@ -622,7 +607,6 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
}
-/* Controller timings */
static void stm32_fmc2_calc_timings(struct nand_chip *chip,
const struct nand_sdr_timings *sdrt)
{
@@ -768,13 +752,11 @@ static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr,
stm32_fmc2_calc_timings(chip, sdrt);
- /* Apply timings */
stm32_fmc2_timings_init(chip);
return 0;
}
-/* NAND callbacks setup */
static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
{
chip->ecc.hwctl = stm32_fmc2_hwctl;
@@ -803,7 +785,6 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
}
-/* FMC2 caps */
static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
{
/* Hamming */
@@ -822,7 +803,6 @@ NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
FMC2_ECC_STEP_SIZE,
FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
-/* FMC2 probe */
static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
ofnode node)
{
@@ -969,7 +949,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
reset_deassert(&reset);
}
- /* FMC2 init routine */
stm32_fmc2_init(fmc2);
chip->controller = &fmc2->base;
@@ -985,7 +964,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
chip->ecc.size = FMC2_ECC_STEP_SIZE;
chip->ecc.strength = FMC2_ECC_BCH8;
- /* Scan to find existence of the device */
ret = nand_scan_ident(mtd, nand->ncs, NULL);
if (ret)
return ret;
@@ -1012,7 +990,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
if (chip->bbt_options & NAND_BBT_USE_FLASH)
chip->bbt_options |= NAND_BBT_NO_OOB;
- /* NAND callbacks setup */
stm32_fmc2_nand_callbacks_setup(chip);
/* Define ECC layout */
@@ -1026,11 +1003,9 @@ static int stm32_fmc2_probe(struct udevice *dev)
ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
chip->ecc.layout = ecclayout;
- /* Configure bus width to 16-bit */
if (chip->options & NAND_BUSWIDTH_16)
stm32_fmc2_set_buswidth_16(fmc2, true);
- /* Scan the device to fill MTD data-structures */
ret = nand_scan_tail(mtd);
if (ret)
return ret;
--
1.9.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 03/11] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_5S for timeouts
2020-07-31 7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
2020-07-31 7:53 ` [PATCH 01/11] mtd: rawnand: stm32_fmc2: fix a buffer overflow Christophe Kerello
2020-07-31 7:53 ` [PATCH 02/11] mtd: rawnand: stm32_fmc2: remove useless inline comments Christophe Kerello
@ 2020-07-31 7:53 ` Christophe Kerello
2020-08-13 7:29 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 04/11] mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2 where relevant Christophe Kerello
` (7 subsequent siblings)
10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31 7:53 UTC (permalink / raw)
To: u-boot
FMC2_TIMEOUT_5S will be used each time that we need to wait.
It was seen, during stress tests in an overloaded system,
that we could be close to 1 second, even if we never met this
value. To be safe, FMC2_TIMEOUT_MS is set to 5 seconds.
Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
drivers/mtd/nand/raw/stm32_fmc2_nand.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index f43e3ec..2e947a3 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -131,6 +131,8 @@
#define FMC2_NSEC_PER_SEC 1000000000L
+#define FMC2_TIMEOUT_5S 5000000
+
enum stm32_fmc2_ecc {
FMC2_ECC_HAM = 1,
FMC2_ECC_BCH4 = 4,
@@ -339,7 +341,7 @@ static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
int ret;
ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr,
- sr & FMC2_SR_NWRF, 10000);
+ sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
if (ret < 0) {
pr_err("Ham timeout\n");
return ret;
@@ -424,7 +426,7 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
/* Wait until the BCH code is ready */
ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
- bchisr & FMC2_BCHISR_EPBRF, 10000);
+ bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
if (ret < 0) {
pr_err("Bch timeout\n");
return ret;
@@ -472,7 +474,7 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
/* Wait until the decoding error is ready */
ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
- bchisr & FMC2_BCHISR_DERF, 10000);
+ bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
if (ret < 0) {
pr_err("Bch timeout\n");
return ret;
--
1.9.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 04/11] mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2 where relevant
2020-07-31 7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
` (2 preceding siblings ...)
2020-07-31 7:53 ` [PATCH 03/11] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_5S for timeouts Christophe Kerello
@ 2020-07-31 7:53 ` Christophe Kerello
2020-08-13 7:29 ` Patrice CHOTARD
2020-08-13 9:57 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 05/11] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros Christophe Kerello
` (6 subsequent siblings)
10 siblings, 2 replies; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31 7:53 UTC (permalink / raw)
To: u-boot
This patch renames functions and local variables.
This cleanup is done to get all functions starting by stm32_fmc2_nfc
in the FMC2 raw NAND driver when all functions will start by
stm32_fmc2_ebi in the FMC2 EBI driver.
Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
drivers/mtd/nand/raw/stm32_fmc2_nand.c | 263 ++++++++++++++++-----------------
1 file changed, 131 insertions(+), 132 deletions(-)
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 2e947a3..9718bae 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -181,12 +181,12 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_hw_control *base)
return container_of(base, struct stm32_fmc2_nfc, base);
}
-static void stm32_fmc2_timings_init(struct nand_chip *chip)
+static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
{
- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
struct stm32_fmc2_timings *timings = &nand->timings;
- u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+ u32 pcr = readl(nfc->io_base + FMC2_PCR);
u32 pmem, patt;
/* Set tclr/tar timings */
@@ -207,15 +207,15 @@ static void stm32_fmc2_timings_init(struct nand_chip *chip)
patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
patt |= FMC2_PATT_ATTHIZ(timings->thiz);
- writel(pcr, fmc2->io_base + FMC2_PCR);
- writel(pmem, fmc2->io_base + FMC2_PMEM);
- writel(patt, fmc2->io_base + FMC2_PATT);
+ writel(pcr, nfc->io_base + FMC2_PCR);
+ writel(pmem, nfc->io_base + FMC2_PMEM);
+ writel(patt, nfc->io_base + FMC2_PATT);
}
-static void stm32_fmc2_setup(struct nand_chip *chip)
+static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
{
- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
- u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+ u32 pcr = readl(nfc->io_base + FMC2_PCR);
/* Configure ECC algorithm (default configuration is Hamming) */
pcr &= ~FMC2_PCR_ECCALG;
@@ -236,95 +236,96 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
pcr &= ~FMC2_PCR_ECCSS_MASK;
pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
- writel(pcr, fmc2->io_base + FMC2_PCR);
+ writel(pcr, nfc->io_base + FMC2_PCR);
}
-static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
+static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
{
struct nand_chip *chip = mtd_to_nand(mtd);
- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
if (chipnr < 0 || chipnr >= nand->ncs)
return;
- if (nand->cs_used[chipnr] == fmc2->cs_sel)
+ if (nand->cs_used[chipnr] == nfc->cs_sel)
return;
- fmc2->cs_sel = nand->cs_used[chipnr];
- chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel];
- chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel];
+ nfc->cs_sel = nand->cs_used[chipnr];
+ chip->IO_ADDR_R = nfc->data_base[nfc->cs_sel];
+ chip->IO_ADDR_W = nfc->data_base[nfc->cs_sel];
- stm32_fmc2_setup(chip);
- stm32_fmc2_timings_init(chip);
+ stm32_fmc2_nfc_setup(chip);
+ stm32_fmc2_nfc_timings_init(chip);
}
-static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
+static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
+ bool set)
{
- u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+ u32 pcr = readl(nfc->io_base + FMC2_PCR);
pcr &= ~FMC2_PCR_PWID_MASK;
if (set)
pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
- writel(pcr, fmc2->io_base + FMC2_PCR);
+ writel(pcr, nfc->io_base + FMC2_PCR);
}
-static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
+static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
{
- u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+ u32 pcr = readl(nfc->io_base + FMC2_PCR);
pcr &= ~FMC2_PCR_ECCEN;
if (enable)
pcr |= FMC2_PCR_ECCEN;
- writel(pcr, fmc2->io_base + FMC2_PCR);
+ writel(pcr, nfc->io_base + FMC2_PCR);
}
-static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
+static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
{
- writel(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
+ writel(FMC2_BCHICR_CLEAR_IRQ, nfc->io_base + FMC2_BCHICR);
}
-static void stm32_fmc2_cmd_ctrl(struct mtd_info *mtd, int cmd,
- unsigned int ctrl)
+static void stm32_fmc2_nfc_cmd_ctrl(struct mtd_info *mtd, int cmd,
+ unsigned int ctrl)
{
struct nand_chip *chip = mtd_to_nand(mtd);
- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
if (cmd == NAND_CMD_NONE)
return;
if (ctrl & NAND_CLE) {
- writeb(cmd, fmc2->cmd_base[fmc2->cs_sel]);
+ writeb(cmd, nfc->cmd_base[nfc->cs_sel]);
return;
}
- writeb(cmd, fmc2->addr_base[fmc2->cs_sel]);
+ writeb(cmd, nfc->addr_base[nfc->cs_sel]);
}
/*
* Enable ECC logic and reset syndrome/parity bits previously calculated
* Syndrome/parity bits is cleared by setting the ECCEN bit to 0
*/
-static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
+static void stm32_fmc2_nfc_hwctl(struct mtd_info *mtd, int mode)
{
struct nand_chip *chip = mtd_to_nand(mtd);
- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
- stm32_fmc2_set_ecc(fmc2, false);
+ stm32_fmc2_nfc_set_ecc(nfc, false);
if (chip->ecc.strength != FMC2_ECC_HAM) {
- u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+ u32 pcr = readl(nfc->io_base + FMC2_PCR);
if (mode == NAND_ECC_WRITE)
pcr |= FMC2_PCR_WEN;
else
pcr &= ~FMC2_PCR_WEN;
- writel(pcr, fmc2->io_base + FMC2_PCR);
+ writel(pcr, nfc->io_base + FMC2_PCR);
- stm32_fmc2_clear_bch_irq(fmc2);
+ stm32_fmc2_nfc_clear_bch_irq(nfc);
}
- stm32_fmc2_set_ecc(fmc2, true);
+ stm32_fmc2_nfc_set_ecc(nfc, true);
}
/*
@@ -332,34 +333,34 @@ static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
* ECC is 3 bytes for 512 bytes of data (supports error correction up to
* max of 1-bit)
*/
-static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
- u8 *ecc)
+static int stm32_fmc2_nfc_ham_calculate(struct mtd_info *mtd, const u8 *data,
+ u8 *ecc)
{
struct nand_chip *chip = mtd_to_nand(mtd);
- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
u32 heccr, sr;
int ret;
- ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr,
+ ret = readl_poll_timeout(nfc->io_base + FMC2_SR, sr,
sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
if (ret < 0) {
pr_err("Ham timeout\n");
return ret;
}
- heccr = readl(fmc2->io_base + FMC2_HECCR);
+ heccr = readl(nfc->io_base + FMC2_HECCR);
ecc[0] = heccr;
ecc[1] = heccr >> 8;
ecc[2] = heccr >> 16;
- stm32_fmc2_set_ecc(fmc2, false);
+ stm32_fmc2_nfc_set_ecc(nfc, false);
return 0;
}
-static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
- u8 *read_ecc, u8 *calc_ecc)
+static int stm32_fmc2_nfc_ham_correct(struct mtd_info *mtd, u8 *dat,
+ u8 *read_ecc, u8 *calc_ecc)
{
u8 bit_position = 0, b0, b1, b2;
u32 byte_addr = 0, b;
@@ -416,16 +417,16 @@ static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
* max of 4-bit/8-bit)
*/
-static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
- u8 *ecc)
+static int stm32_fmc2_nfc_bch_calculate(struct mtd_info *mtd, const u8 *data,
+ u8 *ecc)
{
struct nand_chip *chip = mtd_to_nand(mtd);
- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
u32 bchpbr, bchisr;
int ret;
/* Wait until the BCH code is ready */
- ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
+ ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
if (ret < 0) {
pr_err("Bch timeout\n");
@@ -433,13 +434,13 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
}
/* Read parity bits */
- bchpbr = readl(fmc2->io_base + FMC2_BCHPBR1);
+ bchpbr = readl(nfc->io_base + FMC2_BCHPBR1);
ecc[0] = bchpbr;
ecc[1] = bchpbr >> 8;
ecc[2] = bchpbr >> 16;
ecc[3] = bchpbr >> 24;
- bchpbr = readl(fmc2->io_base + FMC2_BCHPBR2);
+ bchpbr = readl(nfc->io_base + FMC2_BCHPBR2);
ecc[4] = bchpbr;
ecc[5] = bchpbr >> 8;
ecc[6] = bchpbr >> 16;
@@ -447,46 +448,46 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
if (chip->ecc.strength == FMC2_ECC_BCH8) {
ecc[7] = bchpbr >> 24;
- bchpbr = readl(fmc2->io_base + FMC2_BCHPBR3);
+ bchpbr = readl(nfc->io_base + FMC2_BCHPBR3);
ecc[8] = bchpbr;
ecc[9] = bchpbr >> 8;
ecc[10] = bchpbr >> 16;
ecc[11] = bchpbr >> 24;
- bchpbr = readl(fmc2->io_base + FMC2_BCHPBR4);
+ bchpbr = readl(nfc->io_base + FMC2_BCHPBR4);
ecc[12] = bchpbr;
}
- stm32_fmc2_set_ecc(fmc2, false);
+ stm32_fmc2_nfc_set_ecc(nfc, false);
return 0;
}
-static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
- u8 *read_ecc, u8 *calc_ecc)
+static int stm32_fmc2_nfc_bch_correct(struct mtd_info *mtd, u8 *dat,
+ u8 *read_ecc, u8 *calc_ecc)
{
struct nand_chip *chip = mtd_to_nand(mtd);
- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
u32 bchdsr0, bchdsr1, bchdsr2, bchdsr3, bchdsr4, bchisr;
u16 pos[8];
int i, ret, den, eccsize = chip->ecc.size;
unsigned int nb_errs = 0;
/* Wait until the decoding error is ready */
- ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
+ ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
if (ret < 0) {
pr_err("Bch timeout\n");
return ret;
}
- bchdsr0 = readl(fmc2->io_base + FMC2_BCHDSR0);
- bchdsr1 = readl(fmc2->io_base + FMC2_BCHDSR1);
- bchdsr2 = readl(fmc2->io_base + FMC2_BCHDSR2);
- bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3);
- bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4);
+ bchdsr0 = readl(nfc->io_base + FMC2_BCHDSR0);
+ bchdsr1 = readl(nfc->io_base + FMC2_BCHDSR1);
+ bchdsr2 = readl(nfc->io_base + FMC2_BCHDSR2);
+ bchdsr3 = readl(nfc->io_base + FMC2_BCHDSR3);
+ bchdsr4 = readl(nfc->io_base + FMC2_BCHDSR4);
- stm32_fmc2_set_ecc(fmc2, false);
+ stm32_fmc2_nfc_set_ecc(nfc, false);
/* No errors found */
if (likely(!(bchdsr0 & FMC2_BCHDSR0_DEF)))
@@ -516,9 +517,9 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
return nb_errs;
}
-static int stm32_fmc2_read_page(struct mtd_info *mtd,
- struct nand_chip *chip, u8 *buf,
- int oob_required, int page)
+static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
+ struct nand_chip *chip, u8 *buf,
+ int oob_required, int page)
{
int i, s, stat, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -567,13 +568,13 @@ static int stm32_fmc2_read_page(struct mtd_info *mtd,
return max_bitflips;
}
-static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
+static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
{
- u32 pcr = readl(fmc2->io_base + FMC2_PCR);
- u32 bcr1 = readl(fmc2->io_base + FMC2_BCR1);
+ u32 pcr = readl(nfc->io_base + FMC2_PCR);
+ u32 bcr1 = readl(nfc->io_base + FMC2_BCR1);
/* Set CS used to undefined */
- fmc2->cs_sel = -1;
+ nfc->cs_sel = -1;
/* Enable wait feature and nand flash memory bank */
pcr |= FMC2_PCR_PWAITEN;
@@ -603,19 +604,19 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
/* Enable FMC2 controller */
bcr1 |= FMC2_BCR1_FMC2EN;
- writel(bcr1, fmc2->io_base + FMC2_BCR1);
- writel(pcr, fmc2->io_base + FMC2_PCR);
- writel(FMC2_PMEM_DEFAULT, fmc2->io_base + FMC2_PMEM);
- writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
+ writel(bcr1, nfc->io_base + FMC2_BCR1);
+ writel(pcr, nfc->io_base + FMC2_PCR);
+ writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
+ writel(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);
}
-static void stm32_fmc2_calc_timings(struct nand_chip *chip,
- const struct nand_sdr_timings *sdrt)
+static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip,
+ const struct nand_sdr_timings *sdrt)
{
- struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+ struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
struct stm32_fmc2_timings *tims = &nand->timings;
- unsigned long hclk = clk_get_rate(&fmc2->clk);
+ unsigned long hclk = clk_get_rate(&nfc->clk);
unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
unsigned long timing, tar, tclr, thiz, twait;
unsigned long tset_mem, tset_att, thold_mem, thold_att;
@@ -739,29 +740,28 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
tims->thold_att = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
}
-static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr,
- const struct nand_data_interface *conf)
+static int stm32_fmc2_nfc_setup_interface(struct mtd_info *mtd, int chipnr,
+ const struct nand_data_interface *cf)
{
struct nand_chip *chip = mtd_to_nand(mtd);
const struct nand_sdr_timings *sdrt;
- sdrt = nand_get_sdr_timings(conf);
+ sdrt = nand_get_sdr_timings(cf);
if (IS_ERR(sdrt))
return PTR_ERR(sdrt);
if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
return 0;
- stm32_fmc2_calc_timings(chip, sdrt);
-
- stm32_fmc2_timings_init(chip);
+ stm32_fmc2_nfc_calc_timings(chip, sdrt);
+ stm32_fmc2_nfc_timings_init(chip);
return 0;
}
-static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
+static void stm32_fmc2_nfc_nand_callbacks_setup(struct nand_chip *chip)
{
- chip->ecc.hwctl = stm32_fmc2_hwctl;
+ chip->ecc.hwctl = stm32_fmc2_nfc_hwctl;
/*
* Specific callbacks to read/write a page depending on
@@ -769,17 +769,17 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
*/
if (chip->ecc.strength == FMC2_ECC_HAM) {
/* Hamming is used */
- chip->ecc.calculate = stm32_fmc2_ham_calculate;
- chip->ecc.correct = stm32_fmc2_ham_correct;
+ chip->ecc.calculate = stm32_fmc2_nfc_ham_calculate;
+ chip->ecc.correct = stm32_fmc2_nfc_ham_correct;
chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 4 : 3;
chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK;
return;
}
/* BCH is used */
- chip->ecc.read_page = stm32_fmc2_read_page;
- chip->ecc.calculate = stm32_fmc2_bch_calculate;
- chip->ecc.correct = stm32_fmc2_bch_correct;
+ chip->ecc.read_page = stm32_fmc2_nfc_read_page;
+ chip->ecc.calculate = stm32_fmc2_nfc_bch_calculate;
+ chip->ecc.correct = stm32_fmc2_nfc_bch_correct;
if (chip->ecc.strength == FMC2_ECC_BCH8)
chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 14 : 13;
@@ -787,7 +787,7 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
}
-static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
+static int stm32_fmc2_nfc_calc_ecc_bytes(int step_size, int strength)
{
/* Hamming */
if (strength == FMC2_ECC_HAM)
@@ -801,14 +801,13 @@ static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
return 8;
}
-NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
+NAND_ECC_CAPS_SINGLE(stm32_fmc2_nfc_ecc_caps, stm32_fmc2_nfc_calc_ecc_bytes,
FMC2_ECC_STEP_SIZE,
FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
-static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
- ofnode node)
+static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, ofnode node)
{
- struct stm32_fmc2_nand *nand = &fmc2->nand;
+ struct stm32_fmc2_nand *nand = &nfc->nand;
u32 cs[FMC2_MAX_CE];
int ret, i;
@@ -834,13 +833,13 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
return -EINVAL;
}
- if (fmc2->cs_assigned & BIT(cs[i])) {
+ if (nfc->cs_assigned & BIT(cs[i])) {
pr_err("Cs already assigned: %d\n",
nand->cs_used[i]);
return -EINVAL;
}
- fmc2->cs_assigned |= BIT(cs[i]);
+ nfc->cs_assigned |= BIT(cs[i]);
nand->cs_used[i] = cs[i];
}
@@ -849,8 +848,8 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
return 0;
}
-static int stm32_fmc2_parse_dt(struct udevice *dev,
- struct stm32_fmc2_nfc *fmc2)
+static int stm32_fmc2_nfc_parse_dt(struct udevice *dev,
+ struct stm32_fmc2_nfc *nfc)
{
ofnode child;
int ret, nchips = 0;
@@ -869,7 +868,7 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
}
dev_for_each_subnode(child, dev) {
- ret = stm32_fmc2_parse_child(fmc2, child);
+ ret = stm32_fmc2_nfc_parse_child(nfc, child);
if (ret)
return ret;
}
@@ -877,10 +876,10 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
return 0;
}
-static int stm32_fmc2_probe(struct udevice *dev)
+static int stm32_fmc2_nfc_probe(struct udevice *dev)
{
- struct stm32_fmc2_nfc *fmc2 = dev_get_priv(dev);
- struct stm32_fmc2_nand *nand = &fmc2->nand;
+ struct stm32_fmc2_nfc *nfc = dev_get_priv(dev);
+ struct stm32_fmc2_nand *nand = &nfc->nand;
struct nand_chip *chip = &nand->chip;
struct mtd_info *mtd = &chip->mtd;
struct nand_ecclayout *ecclayout;
@@ -889,10 +888,10 @@ static int stm32_fmc2_probe(struct udevice *dev)
int oob_index, chip_cs, mem_region, ret;
unsigned int i;
- spin_lock_init(&fmc2->controller.lock);
- init_waitqueue_head(&fmc2->controller.wq);
+ spin_lock_init(&nfc->controller.lock);
+ init_waitqueue_head(&nfc->controller.wq);
- ret = stm32_fmc2_parse_dt(dev, fmc2);
+ ret = stm32_fmc2_nfc_parse_dt(dev, nfc);
if (ret)
return ret;
@@ -902,11 +901,11 @@ static int stm32_fmc2_probe(struct udevice *dev)
pr_err("Resource io_base not found");
return ret;
}
- fmc2->io_base = (void __iomem *)resource.start;
+ nfc->io_base = (void __iomem *)resource.start;
for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
chip_cs++, mem_region += 3) {
- if (!(fmc2->cs_assigned & BIT(chip_cs)))
+ if (!(nfc->cs_assigned & BIT(chip_cs)))
continue;
ret = dev_read_resource(dev, mem_region, &resource);
@@ -915,7 +914,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
chip_cs);
return ret;
}
- fmc2->data_base[chip_cs] = (void __iomem *)resource.start;
+ nfc->data_base[chip_cs] = (void __iomem *)resource.start;
ret = dev_read_resource(dev, mem_region + 1, &resource);
if (ret) {
@@ -923,7 +922,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
chip_cs);
return ret;
}
- fmc2->cmd_base[chip_cs] = (void __iomem *)resource.start;
+ nfc->cmd_base[chip_cs] = (void __iomem *)resource.start;
ret = dev_read_resource(dev, mem_region + 2, &resource);
if (ret) {
@@ -931,15 +930,15 @@ static int stm32_fmc2_probe(struct udevice *dev)
chip_cs);
return ret;
}
- fmc2->addr_base[chip_cs] = (void __iomem *)resource.start;
+ nfc->addr_base[chip_cs] = (void __iomem *)resource.start;
}
/* Enable the clock */
- ret = clk_get_by_index(dev, 0, &fmc2->clk);
+ ret = clk_get_by_index(dev, 0, &nfc->clk);
if (ret)
return ret;
- ret = clk_enable(&fmc2->clk);
+ ret = clk_enable(&nfc->clk);
if (ret)
return ret;
@@ -951,12 +950,12 @@ static int stm32_fmc2_probe(struct udevice *dev)
reset_deassert(&reset);
}
- stm32_fmc2_init(fmc2);
+ stm32_fmc2_nfc_init(nfc);
- chip->controller = &fmc2->base;
- chip->select_chip = stm32_fmc2_select_chip;
- chip->setup_data_interface = stm32_fmc2_setup_interface;
- chip->cmd_ctrl = stm32_fmc2_cmd_ctrl;
+ chip->controller = &nfc->base;
+ chip->select_chip = stm32_fmc2_nfc_select_chip;
+ chip->setup_data_interface = stm32_fmc2_nfc_setup_interface;
+ chip->cmd_ctrl = stm32_fmc2_nfc_cmd_ctrl;
chip->chip_delay = FMC2_RB_DELAY_US;
chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE |
NAND_USE_BOUNCE_BUFFER;
@@ -982,7 +981,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
return -EINVAL;
}
- ret = nand_check_ecc_caps(chip, &stm32_fmc2_ecc_caps,
+ ret = nand_check_ecc_caps(chip, &stm32_fmc2_nfc_ecc_caps,
mtd->oobsize - FMC2_BBM_LEN);
if (ret) {
pr_err("No valid ECC settings set\n");
@@ -992,10 +991,10 @@ static int stm32_fmc2_probe(struct udevice *dev)
if (chip->bbt_options & NAND_BBT_USE_FLASH)
chip->bbt_options |= NAND_BBT_NO_OOB;
- stm32_fmc2_nand_callbacks_setup(chip);
+ stm32_fmc2_nfc_nand_callbacks_setup(chip);
/* Define ECC layout */
- ecclayout = &fmc2->ecclayout;
+ ecclayout = &nfc->ecclayout;
ecclayout->eccbytes = chip->ecc.bytes *
(mtd->writesize / chip->ecc.size);
oob_index = FMC2_BBM_LEN;
@@ -1006,7 +1005,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
chip->ecc.layout = ecclayout;
if (chip->options & NAND_BUSWIDTH_16)
- stm32_fmc2_set_buswidth_16(fmc2, true);
+ stm32_fmc2_nfc_set_buswidth_16(nfc, true);
ret = nand_scan_tail(mtd);
if (ret)
@@ -1015,16 +1014,16 @@ static int stm32_fmc2_probe(struct udevice *dev)
return nand_register(0, mtd);
}
-static const struct udevice_id stm32_fmc2_match[] = {
+static const struct udevice_id stm32_fmc2_nfc_match[] = {
{ .compatible = "st,stm32mp15-fmc2" },
{ /* Sentinel */ }
};
-U_BOOT_DRIVER(stm32_fmc2_nand) = {
- .name = "stm32_fmc2_nand",
+U_BOOT_DRIVER(stm32_fmc2_nfc) = {
+ .name = "stm32_fmc2_nfc",
.id = UCLASS_MTD,
- .of_match = stm32_fmc2_match,
- .probe = stm32_fmc2_probe,
+ .of_match = stm32_fmc2_nfc_match,
+ .probe = stm32_fmc2_nfc_probe,
.priv_auto_alloc_size = sizeof(struct stm32_fmc2_nfc),
};
@@ -1034,9 +1033,9 @@ void board_nand_init(void)
int ret;
ret = uclass_get_device_by_driver(UCLASS_MTD,
- DM_GET_DRIVER(stm32_fmc2_nand),
+ DM_GET_DRIVER(stm32_fmc2_nfc),
&dev);
if (ret && ret != -ENODEV)
- pr_err("Failed to initialize STM32 FMC2 NAND controller. (error %d)\n",
+ pr_err("Failed to initialize STM32 FMC2 NFC controller. (error %d)\n",
ret);
}
--
1.9.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 05/11] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros
2020-07-31 7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
` (3 preceding siblings ...)
2020-07-31 7:53 ` [PATCH 04/11] mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2 where relevant Christophe Kerello
@ 2020-07-31 7:53 ` Christophe Kerello
2020-08-13 7:29 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 06/11] mtd: rawnand: stm32_fmc2: use clrsetbits_le32 Christophe Kerello
` (5 subsequent siblings)
10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31 7:53 UTC (permalink / raw)
To: u-boot
This patch removes custom macros and uses FIELD_PREP and FIELD_GET macros.
Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
drivers/mtd/nand/raw/stm32_fmc2_nand.c | 120 +++++++++++++++------------------
1 file changed, 56 insertions(+), 64 deletions(-)
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 9718bae..eba1ded 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -10,6 +10,7 @@
#include <log.h>
#include <nand.h>
#include <reset.h>
+#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/err.h>
@@ -60,20 +61,16 @@
/* Register: FMC2_PCR */
#define FMC2_PCR_PWAITEN BIT(1)
#define FMC2_PCR_PBKEN BIT(2)
-#define FMC2_PCR_PWID_MASK GENMASK(5, 4)
-#define FMC2_PCR_PWID(x) (((x) & 0x3) << 4)
+#define FMC2_PCR_PWID GENMASK(5, 4)
#define FMC2_PCR_PWID_BUSWIDTH_8 0
#define FMC2_PCR_PWID_BUSWIDTH_16 1
#define FMC2_PCR_ECCEN BIT(6)
#define FMC2_PCR_ECCALG BIT(8)
-#define FMC2_PCR_TCLR_MASK GENMASK(12, 9)
-#define FMC2_PCR_TCLR(x) (((x) & 0xf) << 9)
+#define FMC2_PCR_TCLR GENMASK(12, 9)
#define FMC2_PCR_TCLR_DEFAULT 0xf
-#define FMC2_PCR_TAR_MASK GENMASK(16, 13)
-#define FMC2_PCR_TAR(x) (((x) & 0xf) << 13)
+#define FMC2_PCR_TAR GENMASK(16, 13)
#define FMC2_PCR_TAR_DEFAULT 0xf
-#define FMC2_PCR_ECCSS_MASK GENMASK(19, 17)
-#define FMC2_PCR_ECCSS(x) (((x) & 0x7) << 17)
+#define FMC2_PCR_ECCSS GENMASK(19, 17)
#define FMC2_PCR_ECCSS_512 1
#define FMC2_PCR_ECCSS_2048 3
#define FMC2_PCR_BCHECC BIT(24)
@@ -83,17 +80,17 @@
#define FMC2_SR_NWRF BIT(6)
/* Register: FMC2_PMEM */
-#define FMC2_PMEM_MEMSET(x) (((x) & 0xff) << 0)
-#define FMC2_PMEM_MEMWAIT(x) (((x) & 0xff) << 8)
-#define FMC2_PMEM_MEMHOLD(x) (((x) & 0xff) << 16)
-#define FMC2_PMEM_MEMHIZ(x) (((x) & 0xff) << 24)
+#define FMC2_PMEM_MEMSET GENMASK(7, 0)
+#define FMC2_PMEM_MEMWAIT GENMASK(15, 8)
+#define FMC2_PMEM_MEMHOLD GENMASK(23, 16)
+#define FMC2_PMEM_MEMHIZ GENMASK(31, 24)
#define FMC2_PMEM_DEFAULT 0x0a0a0a0a
/* Register: FMC2_PATT */
-#define FMC2_PATT_ATTSET(x) (((x) & 0xff) << 0)
-#define FMC2_PATT_ATTWAIT(x) (((x) & 0xff) << 8)
-#define FMC2_PATT_ATTHOLD(x) (((x) & 0xff) << 16)
-#define FMC2_PATT_ATTHIZ(x) (((x) & 0xff) << 24)
+#define FMC2_PATT_ATTSET GENMASK(7, 0)
+#define FMC2_PATT_ATTWAIT GENMASK(15, 8)
+#define FMC2_PATT_ATTHOLD GENMASK(23, 16)
+#define FMC2_PATT_ATTHIZ GENMASK(31, 24)
#define FMC2_PATT_DEFAULT 0x0a0a0a0a
/* Register: FMC2_BCHISR */
@@ -106,28 +103,23 @@
/* Register: FMC2_BCHDSR0 */
#define FMC2_BCHDSR0_DUE BIT(0)
#define FMC2_BCHDSR0_DEF BIT(1)
-#define FMC2_BCHDSR0_DEN_MASK GENMASK(7, 4)
-#define FMC2_BCHDSR0_DEN_SHIFT 4
+#define FMC2_BCHDSR0_DEN GENMASK(7, 4)
/* Register: FMC2_BCHDSR1 */
-#define FMC2_BCHDSR1_EBP1_MASK GENMASK(12, 0)
-#define FMC2_BCHDSR1_EBP2_MASK GENMASK(28, 16)
-#define FMC2_BCHDSR1_EBP2_SHIFT 16
+#define FMC2_BCHDSR1_EBP1 GENMASK(12, 0)
+#define FMC2_BCHDSR1_EBP2 GENMASK(28, 16)
/* Register: FMC2_BCHDSR2 */
-#define FMC2_BCHDSR2_EBP3_MASK GENMASK(12, 0)
-#define FMC2_BCHDSR2_EBP4_MASK GENMASK(28, 16)
-#define FMC2_BCHDSR2_EBP4_SHIFT 16
+#define FMC2_BCHDSR2_EBP3 GENMASK(12, 0)
+#define FMC2_BCHDSR2_EBP4 GENMASK(28, 16)
/* Register: FMC2_BCHDSR3 */
-#define FMC2_BCHDSR3_EBP5_MASK GENMASK(12, 0)
-#define FMC2_BCHDSR3_EBP6_MASK GENMASK(28, 16)
-#define FMC2_BCHDSR3_EBP6_SHIFT 16
+#define FMC2_BCHDSR3_EBP5 GENMASK(12, 0)
+#define FMC2_BCHDSR3_EBP6 GENMASK(28, 16)
/* Register: FMC2_BCHDSR4 */
-#define FMC2_BCHDSR4_EBP7_MASK GENMASK(12, 0)
-#define FMC2_BCHDSR4_EBP8_MASK GENMASK(28, 16)
-#define FMC2_BCHDSR4_EBP8_SHIFT 16
+#define FMC2_BCHDSR4_EBP7 GENMASK(12, 0)
+#define FMC2_BCHDSR4_EBP8 GENMASK(28, 16)
#define FMC2_NSEC_PER_SEC 1000000000L
@@ -190,22 +182,22 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
u32 pmem, patt;
/* Set tclr/tar timings */
- pcr &= ~FMC2_PCR_TCLR_MASK;
- pcr |= FMC2_PCR_TCLR(timings->tclr);
- pcr &= ~FMC2_PCR_TAR_MASK;
- pcr |= FMC2_PCR_TAR(timings->tar);
+ pcr &= ~FMC2_PCR_TCLR;
+ pcr |= FIELD_PREP(FMC2_PCR_TCLR, timings->tclr);
+ pcr &= ~FMC2_PCR_TAR;
+ pcr |= FIELD_PREP(FMC2_PCR_TAR, timings->tar);
/* Set tset/twait/thold/thiz timings in common bank */
- pmem = FMC2_PMEM_MEMSET(timings->tset_mem);
- pmem |= FMC2_PMEM_MEMWAIT(timings->twait);
- pmem |= FMC2_PMEM_MEMHOLD(timings->thold_mem);
- pmem |= FMC2_PMEM_MEMHIZ(timings->thiz);
+ pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
+ pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
+ pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
+ pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
/* Set tset/twait/thold/thiz timings in attribut bank */
- patt = FMC2_PATT_ATTSET(timings->tset_att);
- patt |= FMC2_PATT_ATTWAIT(timings->twait);
- patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
- patt |= FMC2_PATT_ATTHIZ(timings->thiz);
+ patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
+ patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
+ patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
+ patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
writel(pcr, nfc->io_base + FMC2_PCR);
writel(pmem, nfc->io_base + FMC2_PMEM);
@@ -228,13 +220,13 @@ static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
}
/* Set buswidth */
- pcr &= ~FMC2_PCR_PWID_MASK;
+ pcr &= ~FMC2_PCR_PWID;
if (chip->options & NAND_BUSWIDTH_16)
- pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
+ pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
/* Set ECC sector size */
- pcr &= ~FMC2_PCR_ECCSS_MASK;
- pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
+ pcr &= ~FMC2_PCR_ECCSS;
+ pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
writel(pcr, nfc->io_base + FMC2_PCR);
}
@@ -264,9 +256,9 @@ static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
{
u32 pcr = readl(nfc->io_base + FMC2_PCR);
- pcr &= ~FMC2_PCR_PWID_MASK;
+ pcr &= ~FMC2_PCR_PWID;
if (set)
- pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
+ pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
writel(pcr, nfc->io_base + FMC2_PCR);
}
@@ -497,16 +489,16 @@ static int stm32_fmc2_nfc_bch_correct(struct mtd_info *mtd, u8 *dat,
if (unlikely(bchdsr0 & FMC2_BCHDSR0_DUE))
return -EBADMSG;
- pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK;
- pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT;
- pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK;
- pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT;
- pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK;
- pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT;
- pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK;
- pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT;
+ pos[0] = FIELD_GET(FMC2_BCHDSR1_EBP1, bchdsr1);
+ pos[1] = FIELD_GET(FMC2_BCHDSR1_EBP2, bchdsr1);
+ pos[2] = FIELD_GET(FMC2_BCHDSR2_EBP3, bchdsr2);
+ pos[3] = FIELD_GET(FMC2_BCHDSR2_EBP4, bchdsr2);
+ pos[4] = FIELD_GET(FMC2_BCHDSR3_EBP5, bchdsr3);
+ pos[5] = FIELD_GET(FMC2_BCHDSR3_EBP6, bchdsr3);
+ pos[6] = FIELD_GET(FMC2_BCHDSR4_EBP7, bchdsr4);
+ pos[7] = FIELD_GET(FMC2_BCHDSR4_EBP8, bchdsr4);
- den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT;
+ den = FIELD_GET(FMC2_BCHDSR0_DEN, bchdsr0);
for (i = 0; i < den; i++) {
if (pos[i] < eccsize * 8) {
__change_bit(pos[i], (unsigned long *)dat);
@@ -581,7 +573,7 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
pcr |= FMC2_PCR_PBKEN;
/* Set buswidth to 8 bits mode for identification */
- pcr &= ~FMC2_PCR_PWID_MASK;
+ pcr &= ~FMC2_PCR_PWID;
/* ECC logic is disabled */
pcr &= ~FMC2_PCR_ECCEN;
@@ -592,14 +584,14 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
pcr &= ~FMC2_PCR_WEN;
/* Set default ECC sector size */
- pcr &= ~FMC2_PCR_ECCSS_MASK;
- pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048);
+ pcr &= ~FMC2_PCR_ECCSS;
+ pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_2048);
/* Set default tclr/tar timings */
- pcr &= ~FMC2_PCR_TCLR_MASK;
- pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT);
- pcr &= ~FMC2_PCR_TAR_MASK;
- pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT);
+ pcr &= ~FMC2_PCR_TCLR;
+ pcr |= FIELD_PREP(FMC2_PCR_TCLR, FMC2_PCR_TCLR_DEFAULT);
+ pcr &= ~FMC2_PCR_TAR;
+ pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
/* Enable FMC2 controller */
bcr1 |= FMC2_BCR1_FMC2EN;
--
1.9.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 06/11] mtd: rawnand: stm32_fmc2: use clrsetbits_le32
2020-07-31 7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
` (4 preceding siblings ...)
2020-07-31 7:53 ` [PATCH 05/11] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros Christophe Kerello
@ 2020-07-31 7:53 ` Christophe Kerello
2020-08-13 7:30 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 07/11] memory: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver Christophe Kerello
` (4 subsequent siblings)
10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31 7:53 UTC (permalink / raw)
To: u-boot
This patch uses clrsetbits_le32 function instead of multiple instructions.
Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
drivers/mtd/nand/raw/stm32_fmc2_nand.c | 56 +++++++++++++---------------------
1 file changed, 21 insertions(+), 35 deletions(-)
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index eba1ded..1e4d757 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -178,40 +178,37 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
struct stm32_fmc2_timings *timings = &nand->timings;
- u32 pcr = readl(nfc->io_base + FMC2_PCR);
u32 pmem, patt;
/* Set tclr/tar timings */
- pcr &= ~FMC2_PCR_TCLR;
- pcr |= FIELD_PREP(FMC2_PCR_TCLR, timings->tclr);
- pcr &= ~FMC2_PCR_TAR;
- pcr |= FIELD_PREP(FMC2_PCR_TAR, timings->tar);
+ clrsetbits_le32(nfc->io_base + FMC2_PCR,
+ FMC2_PCR_TCLR | FMC2_PCR_TAR,
+ FIELD_PREP(FMC2_PCR_TCLR, timings->tclr) |
+ FIELD_PREP(FMC2_PCR_TAR, timings->tar));
/* Set tset/twait/thold/thiz timings in common bank */
pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
+ writel(pmem, nfc->io_base + FMC2_PMEM);
/* Set tset/twait/thold/thiz timings in attribut bank */
patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
-
- writel(pcr, nfc->io_base + FMC2_PCR);
- writel(pmem, nfc->io_base + FMC2_PMEM);
writel(patt, nfc->io_base + FMC2_PATT);
}
static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
{
struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
- u32 pcr = readl(nfc->io_base + FMC2_PCR);
+ u32 pcr = 0, pcr_mask;
/* Configure ECC algorithm (default configuration is Hamming) */
- pcr &= ~FMC2_PCR_ECCALG;
- pcr &= ~FMC2_PCR_BCHECC;
+ pcr_mask = FMC2_PCR_ECCALG;
+ pcr_mask |= FMC2_PCR_BCHECC;
if (chip->ecc.strength == FMC2_ECC_BCH8) {
pcr |= FMC2_PCR_ECCALG;
pcr |= FMC2_PCR_BCHECC;
@@ -220,15 +217,15 @@ static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
}
/* Set buswidth */
- pcr &= ~FMC2_PCR_PWID;
+ pcr_mask |= FMC2_PCR_PWID;
if (chip->options & NAND_BUSWIDTH_16)
pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
/* Set ECC sector size */
- pcr &= ~FMC2_PCR_ECCSS;
+ pcr_mask |= FMC2_PCR_ECCSS;
pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
- writel(pcr, nfc->io_base + FMC2_PCR);
+ clrsetbits_le32(nfc->io_base + FMC2_PCR, pcr_mask, pcr);
}
static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
@@ -254,22 +251,18 @@ static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
bool set)
{
- u32 pcr = readl(nfc->io_base + FMC2_PCR);
+ u32 pcr;
- pcr &= ~FMC2_PCR_PWID;
- if (set)
- pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
- writel(pcr, nfc->io_base + FMC2_PCR);
+ pcr = set ? FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16) :
+ FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_8);
+
+ clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_PWID, pcr);
}
static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
{
- u32 pcr = readl(nfc->io_base + FMC2_PCR);
-
- pcr &= ~FMC2_PCR_ECCEN;
- if (enable)
- pcr |= FMC2_PCR_ECCEN;
- writel(pcr, nfc->io_base + FMC2_PCR);
+ clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_ECCEN,
+ enable ? FMC2_PCR_ECCEN : 0);
}
static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
@@ -306,13 +299,8 @@ static void stm32_fmc2_nfc_hwctl(struct mtd_info *mtd, int mode)
stm32_fmc2_nfc_set_ecc(nfc, false);
if (chip->ecc.strength != FMC2_ECC_HAM) {
- u32 pcr = readl(nfc->io_base + FMC2_PCR);
-
- if (mode == NAND_ECC_WRITE)
- pcr |= FMC2_PCR_WEN;
- else
- pcr &= ~FMC2_PCR_WEN;
- writel(pcr, nfc->io_base + FMC2_PCR);
+ clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_WEN,
+ mode == NAND_ECC_WRITE ? FMC2_PCR_WEN : 0);
stm32_fmc2_nfc_clear_bch_irq(nfc);
}
@@ -563,7 +551,6 @@ static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
{
u32 pcr = readl(nfc->io_base + FMC2_PCR);
- u32 bcr1 = readl(nfc->io_base + FMC2_BCR1);
/* Set CS used to undefined */
nfc->cs_sel = -1;
@@ -594,9 +581,8 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
/* Enable FMC2 controller */
- bcr1 |= FMC2_BCR1_FMC2EN;
+ setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
- writel(bcr1, nfc->io_base + FMC2_BCR1);
writel(pcr, nfc->io_base + FMC2_PCR);
writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
writel(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);
--
1.9.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 07/11] memory: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver
2020-07-31 7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
` (5 preceding siblings ...)
2020-07-31 7:53 ` [PATCH 06/11] mtd: rawnand: stm32_fmc2: use clrsetbits_le32 Christophe Kerello
@ 2020-07-31 7:53 ` Christophe Kerello
2020-08-13 7:31 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 08/11] mtd: rawnand: stm32_fmc2: get resources from parent node Christophe Kerello
` (3 subsequent siblings)
10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31 7:53 UTC (permalink / raw)
To: u-boot
The driver adds the support for the STMicroelectronics FMC2 EBI controller
found on STM32MP SOCs.
Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
drivers/memory/Kconfig | 9 +
drivers/memory/Makefile | 1 +
drivers/memory/stm32-fmc2-ebi.c | 1056 +++++++++++++++++++++++++++++++++++++++
3 files changed, 1066 insertions(+)
create mode 100644 drivers/memory/stm32-fmc2-ebi.c
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 4fbb5aa..7271892 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -4,6 +4,15 @@
menu "Memory Controller drivers"
+config STM32_FMC2_EBI
+ bool "Support for FMC2 External Bus Interface on STM32MP SoCs"
+ depends on ARCH_STM32MP
+ help
+ Select this option to enable the STM32 FMC2 External Bus Interface
+ controller. This driver configures the transactions with external
+ devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on
+ SOCs containing the FMC2 External Bus Interface.
+
config TI_AEMIF
tristate "Texas Instruments AEMIF driver"
depends on ARCH_KEYSTONE
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 238add0..fec52ef 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -1,2 +1,3 @@
+obj-$(CONFIG_STM32_FMC2_EBI) += stm32-fmc2-ebi.o
obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
diff --git a/drivers/memory/stm32-fmc2-ebi.c b/drivers/memory/stm32-fmc2-ebi.c
new file mode 100644
index 0000000..d887a1e
--- /dev/null
+++ b/drivers/memory/stm32-fmc2-ebi.c
@@ -0,0 +1,1056 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) STMicroelectronics 2020
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <reset.h>
+#include <linux/bitfield.h>
+#include <linux/err.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+
+/* FMC2 Controller Registers */
+#define FMC2_BCR1 0x0
+#define FMC2_BTR1 0x4
+#define FMC2_BCR(x) ((x) * 0x8 + FMC2_BCR1)
+#define FMC2_BTR(x) ((x) * 0x8 + FMC2_BTR1)
+#define FMC2_PCSCNTR 0x20
+#define FMC2_BWTR1 0x104
+#define FMC2_BWTR(x) ((x) * 0x8 + FMC2_BWTR1)
+
+/* Register: FMC2_BCR1 */
+#define FMC2_BCR1_CCLKEN BIT(20)
+#define FMC2_BCR1_FMC2EN BIT(31)
+
+/* Register: FMC2_BCRx */
+#define FMC2_BCR_MBKEN BIT(0)
+#define FMC2_BCR_MUXEN BIT(1)
+#define FMC2_BCR_MTYP GENMASK(3, 2)
+#define FMC2_BCR_MWID GENMASK(5, 4)
+#define FMC2_BCR_FACCEN BIT(6)
+#define FMC2_BCR_BURSTEN BIT(8)
+#define FMC2_BCR_WAITPOL BIT(9)
+#define FMC2_BCR_WAITCFG BIT(11)
+#define FMC2_BCR_WREN BIT(12)
+#define FMC2_BCR_WAITEN BIT(13)
+#define FMC2_BCR_EXTMOD BIT(14)
+#define FMC2_BCR_ASYNCWAIT BIT(15)
+#define FMC2_BCR_CPSIZE GENMASK(18, 16)
+#define FMC2_BCR_CBURSTRW BIT(19)
+#define FMC2_BCR_NBLSET GENMASK(23, 22)
+
+/* Register: FMC2_BTRx/FMC2_BWTRx */
+#define FMC2_BXTR_ADDSET GENMASK(3, 0)
+#define FMC2_BXTR_ADDHLD GENMASK(7, 4)
+#define FMC2_BXTR_DATAST GENMASK(15, 8)
+#define FMC2_BXTR_BUSTURN GENMASK(19, 16)
+#define FMC2_BTR_CLKDIV GENMASK(23, 20)
+#define FMC2_BTR_DATLAT GENMASK(27, 24)
+#define FMC2_BXTR_ACCMOD GENMASK(29, 28)
+#define FMC2_BXTR_DATAHLD GENMASK(31, 30)
+
+/* Register: FMC2_PCSCNTR */
+#define FMC2_PCSCNTR_CSCOUNT GENMASK(15, 0)
+#define FMC2_PCSCNTR_CNTBEN(x) BIT((x) + 16)
+
+#define FMC2_MAX_EBI_CE 4
+#define FMC2_MAX_BANKS 5
+
+#define FMC2_BCR_CPSIZE_0 0x0
+#define FMC2_BCR_CPSIZE_128 0x1
+#define FMC2_BCR_CPSIZE_256 0x2
+#define FMC2_BCR_CPSIZE_512 0x3
+#define FMC2_BCR_CPSIZE_1024 0x4
+
+#define FMC2_BCR_MWID_8 0x0
+#define FMC2_BCR_MWID_16 0x1
+
+#define FMC2_BCR_MTYP_SRAM 0x0
+#define FMC2_BCR_MTYP_PSRAM 0x1
+#define FMC2_BCR_MTYP_NOR 0x2
+
+#define FMC2_BXTR_EXTMOD_A 0x0
+#define FMC2_BXTR_EXTMOD_B 0x1
+#define FMC2_BXTR_EXTMOD_C 0x2
+#define FMC2_BXTR_EXTMOD_D 0x3
+
+#define FMC2_BCR_NBLSET_MAX 0x3
+#define FMC2_BXTR_ADDSET_MAX 0xf
+#define FMC2_BXTR_ADDHLD_MAX 0xf
+#define FMC2_BXTR_DATAST_MAX 0xff
+#define FMC2_BXTR_BUSTURN_MAX 0xf
+#define FMC2_BXTR_DATAHLD_MAX 0x3
+#define FMC2_BTR_CLKDIV_MAX 0xf
+#define FMC2_BTR_DATLAT_MAX 0xf
+#define FMC2_PCSCNTR_CSCOUNT_MAX 0xff
+
+#define FMC2_NSEC_PER_SEC 1000000000L
+
+enum stm32_fmc2_ebi_bank {
+ FMC2_EBI1 = 0,
+ FMC2_EBI2,
+ FMC2_EBI3,
+ FMC2_EBI4,
+ FMC2_NAND
+};
+
+enum stm32_fmc2_ebi_register_type {
+ FMC2_REG_BCR = 1,
+ FMC2_REG_BTR,
+ FMC2_REG_BWTR,
+ FMC2_REG_PCSCNTR
+};
+
+enum stm32_fmc2_ebi_transaction_type {
+ FMC2_ASYNC_MODE_1_SRAM = 0,
+ FMC2_ASYNC_MODE_1_PSRAM,
+ FMC2_ASYNC_MODE_A_SRAM,
+ FMC2_ASYNC_MODE_A_PSRAM,
+ FMC2_ASYNC_MODE_2_NOR,
+ FMC2_ASYNC_MODE_B_NOR,
+ FMC2_ASYNC_MODE_C_NOR,
+ FMC2_ASYNC_MODE_D_NOR,
+ FMC2_SYNC_READ_SYNC_WRITE_PSRAM,
+ FMC2_SYNC_READ_ASYNC_WRITE_PSRAM,
+ FMC2_SYNC_READ_SYNC_WRITE_NOR,
+ FMC2_SYNC_READ_ASYNC_WRITE_NOR
+};
+
+enum stm32_fmc2_ebi_buswidth {
+ FMC2_BUSWIDTH_8 = 8,
+ FMC2_BUSWIDTH_16 = 16
+};
+
+enum stm32_fmc2_ebi_cpsize {
+ FMC2_CPSIZE_0 = 0,
+ FMC2_CPSIZE_128 = 128,
+ FMC2_CPSIZE_256 = 256,
+ FMC2_CPSIZE_512 = 512,
+ FMC2_CPSIZE_1024 = 1024
+};
+
+struct stm32_fmc2_ebi {
+ struct clk clk;
+ fdt_addr_t io_base;
+ u8 bank_assigned;
+};
+
+/*
+ * struct stm32_fmc2_prop - STM32 FMC2 EBI property
+ * @name: the device tree binding name of the property
+ * @bprop: indicate that it is a boolean property
+ * @mprop: indicate that it is a mandatory property
+ * @reg_type: the register that have to be modified
+ * @reg_mask: the bit that have to be modified in the selected register
+ * in case of it is a boolean property
+ * @reset_val: the default value that have to be set in case the property
+ * has not been defined in the device tree
+ * @check: this callback ckecks that the property is compliant with the
+ * transaction type selected
+ * @calculate: this callback is called to calculate for exemple a timing
+ * set in nanoseconds in the device tree in clock cycles or in
+ * clock period
+ * @set: this callback applies the values in the registers
+ */
+struct stm32_fmc2_prop {
+ const char *name;
+ bool bprop;
+ bool mprop;
+ int reg_type;
+ u32 reg_mask;
+ u32 reset_val;
+ int (*check)(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop, int cs);
+ u32 (*calculate)(struct stm32_fmc2_ebi *ebi, int cs, u32 setup);
+ int (*set)(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs, u32 setup);
+};
+
+static int stm32_fmc2_ebi_check_mux(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs)
+{
+ u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+
+ if (bcr & FMC2_BCR_MTYP)
+ return 0;
+
+ return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_waitcfg(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs)
+{
+ u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+ u32 val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+
+ if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
+ return 0;
+
+ return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_sync_trans(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs)
+{
+ u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+
+ if (bcr & FMC2_BCR_BURSTEN)
+ return 0;
+
+ return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs)
+{
+ u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+
+ if (!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW))
+ return 0;
+
+ return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_cpsize(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs)
+{
+ u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+ u32 val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+
+ if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
+ return 0;
+
+ return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_address_hold(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs)
+{
+ u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+ u32 bxtr = prop->reg_type == FMC2_REG_BWTR ?
+ readl(ebi->io_base + FMC2_BWTR(cs)) :
+ readl(ebi->io_base + FMC2_BTR(cs));
+ u32 val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
+
+ if ((!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW)) &&
+ ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN))
+ return 0;
+
+ return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_clk_period(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs)
+{
+ u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
+ u32 bcr1 = cs ? readl(ebi->io_base + FMC2_BCR1) : bcr;
+
+ if (bcr & FMC2_BCR_BURSTEN && (!cs || !(bcr1 & FMC2_BCR1_CCLKEN)))
+ return 0;
+
+ return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_cclk(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs)
+{
+ if (cs)
+ return -EINVAL;
+
+ return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs);
+}
+
+static u32 stm32_fmc2_ebi_ns_to_clock_cycles(struct stm32_fmc2_ebi *ebi,
+ int cs, u32 setup)
+{
+ unsigned long hclk = clk_get_rate(&ebi->clk);
+ unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
+
+ return DIV_ROUND_UP(setup * 1000, hclkp);
+}
+
+static u32 stm32_fmc2_ebi_ns_to_clk_period(struct stm32_fmc2_ebi *ebi,
+ int cs, u32 setup)
+{
+ u32 nb_clk_cycles = stm32_fmc2_ebi_ns_to_clock_cycles(ebi, cs, setup);
+ u32 bcr = readl(ebi->io_base + FMC2_BCR1);
+ u32 btr = bcr & FMC2_BCR1_CCLKEN || !cs ?
+ readl(ebi->io_base + FMC2_BTR1) :
+ readl(ebi->io_base + FMC2_BTR(cs));
+ u32 clk_period = FIELD_GET(FMC2_BTR_CLKDIV, btr) + 1;
+
+ return DIV_ROUND_UP(nb_clk_cycles, clk_period);
+}
+
+static int stm32_fmc2_ebi_get_reg(int reg_type, int cs, u32 *reg)
+{
+ switch (reg_type) {
+ case FMC2_REG_BCR:
+ *reg = FMC2_BCR(cs);
+ break;
+ case FMC2_REG_BTR:
+ *reg = FMC2_BTR(cs);
+ break;
+ case FMC2_REG_BWTR:
+ *reg = FMC2_BWTR(cs);
+ break;
+ case FMC2_REG_PCSCNTR:
+ *reg = FMC2_PCSCNTR;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int stm32_fmc2_ebi_set_bit_field(struct stm32_fmc2_ebi *ebi,
+ const struct stm32_fmc2_prop *prop,
+ int cs, u32 setup)
+{
+ u32 reg;
+ int ret;
+
+ ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, ®);
+ 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,
+};
--
1.9.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 08/11] mtd: rawnand: stm32_fmc2: get resources from parent node
2020-07-31 7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
` (6 preceding siblings ...)
2020-07-31 7:53 ` [PATCH 07/11] memory: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver Christophe Kerello
@ 2020-07-31 7:53 ` Christophe Kerello
2020-08-13 7:33 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 09/11] board: stm32mp1: update fdt fixup partitions table Christophe Kerello
` (2 subsequent siblings)
10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31 7:53 UTC (permalink / raw)
To: u-boot
FMC2 EBI support has been added. Common resources (registers base
address and clock) can now be shared between the 2 drivers using
"st,stm32mp1-fmc2-nfc" compatible string. It means that the
common resources should now be found in the parent device when EBI
node is available.
Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
drivers/mtd/nand/raw/stm32_fmc2_nand.c | 87 +++++++++++++++++++++++-----------
1 file changed, 59 insertions(+), 28 deletions(-)
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 1e4d757..47fe610 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -158,10 +158,10 @@ struct stm32_fmc2_nfc {
struct nand_hw_control base;
struct stm32_fmc2_nand nand;
struct nand_ecclayout ecclayout;
- void __iomem *io_base;
- void __iomem *data_base[FMC2_MAX_CE];
- void __iomem *cmd_base[FMC2_MAX_CE];
- void __iomem *addr_base[FMC2_MAX_CE];
+ fdt_addr_t io_base;
+ fdt_addr_t data_base[FMC2_MAX_CE];
+ fdt_addr_t cmd_base[FMC2_MAX_CE];
+ fdt_addr_t addr_base[FMC2_MAX_CE];
struct clk clk;
u8 cs_assigned;
@@ -241,8 +241,8 @@ static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
return;
nfc->cs_sel = nand->cs_used[chipnr];
- chip->IO_ADDR_R = nfc->data_base[nfc->cs_sel];
- chip->IO_ADDR_W = nfc->data_base[nfc->cs_sel];
+ chip->IO_ADDR_R = (void __iomem *)nfc->data_base[nfc->cs_sel];
+ chip->IO_ADDR_W = (void __iomem *)nfc->data_base[nfc->cs_sel];
stm32_fmc2_nfc_setup(chip);
stm32_fmc2_nfc_timings_init(chip);
@@ -548,7 +548,7 @@ static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
return max_bitflips;
}
-static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
+static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc, bool has_parent)
{
u32 pcr = readl(nfc->io_base + FMC2_PCR);
@@ -581,7 +581,8 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
/* Enable FMC2 controller */
- setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
+ if (!has_parent)
+ setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
writel(pcr, nfc->io_base + FMC2_PCR);
writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
@@ -854,6 +855,30 @@ static int stm32_fmc2_nfc_parse_dt(struct udevice *dev,
return 0;
}
+static struct udevice *stm32_fmc2_nfc_get_cdev(struct udevice *dev)
+{
+ struct udevice *pdev = dev_get_parent(dev);
+ struct udevice *cdev = NULL;
+ bool ebi_found = false;
+
+ if (pdev && ofnode_device_is_compatible(dev_ofnode(pdev),
+ "st,stm32mp1-fmc2-ebi"))
+ ebi_found = true;
+
+ if (ofnode_device_is_compatible(dev_ofnode(dev),
+ "st,stm32mp1-fmc2-nfc")) {
+ if (ebi_found)
+ cdev = pdev;
+
+ return cdev;
+ }
+
+ if (!ebi_found)
+ cdev = dev;
+
+ return cdev;
+}
+
static int stm32_fmc2_nfc_probe(struct udevice *dev)
{
struct stm32_fmc2_nfc *nfc = dev_get_priv(dev);
@@ -861,58 +886,63 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
struct nand_chip *chip = &nand->chip;
struct mtd_info *mtd = &chip->mtd;
struct nand_ecclayout *ecclayout;
- struct resource resource;
+ struct udevice *cdev;
struct reset_ctl reset;
int oob_index, chip_cs, mem_region, ret;
unsigned int i;
+ int start_region = 0;
+ fdt_addr_t addr;
spin_lock_init(&nfc->controller.lock);
init_waitqueue_head(&nfc->controller.wq);
+ cdev = stm32_fmc2_nfc_get_cdev(dev);
+ if (!cdev)
+ return -EINVAL;
+
ret = stm32_fmc2_nfc_parse_dt(dev, nfc);
if (ret)
return ret;
- /* Get resources */
- ret = dev_read_resource(dev, 0, &resource);
- if (ret) {
- pr_err("Resource io_base not found");
- return ret;
- }
- nfc->io_base = (void __iomem *)resource.start;
+ nfc->io_base = dev_read_addr(cdev);
+ if (nfc->io_base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ if (dev == cdev)
+ start_region = 1;
- for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
+ for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE;
chip_cs++, mem_region += 3) {
if (!(nfc->cs_assigned & BIT(chip_cs)))
continue;
- ret = dev_read_resource(dev, mem_region, &resource);
- if (ret) {
+ addr = dev_read_addr_index(dev, mem_region);
+ if (addr == FDT_ADDR_T_NONE) {
pr_err("Resource data_base not found for cs%d",
chip_cs);
return ret;
}
- nfc->data_base[chip_cs] = (void __iomem *)resource.start;
+ nfc->data_base[chip_cs] = addr;
- ret = dev_read_resource(dev, mem_region + 1, &resource);
- if (ret) {
+ addr = dev_read_addr_index(dev, mem_region + 1);
+ if (addr == FDT_ADDR_T_NONE) {
pr_err("Resource cmd_base not found for cs%d",
chip_cs);
return ret;
}
- nfc->cmd_base[chip_cs] = (void __iomem *)resource.start;
+ nfc->cmd_base[chip_cs] = addr;
- ret = dev_read_resource(dev, mem_region + 2, &resource);
- if (ret) {
+ addr = dev_read_addr_index(dev, mem_region + 2);
+ if (addr == FDT_ADDR_T_NONE) {
pr_err("Resource addr_base not found for cs%d",
chip_cs);
return ret;
}
- nfc->addr_base[chip_cs] = (void __iomem *)resource.start;
+ nfc->addr_base[chip_cs] = addr;
}
/* Enable the clock */
- ret = clk_get_by_index(dev, 0, &nfc->clk);
+ ret = clk_get_by_index(cdev, 0, &nfc->clk);
if (ret)
return ret;
@@ -928,7 +958,7 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
reset_deassert(&reset);
}
- stm32_fmc2_nfc_init(nfc);
+ stm32_fmc2_nfc_init(nfc, dev != cdev);
chip->controller = &nfc->base;
chip->select_chip = stm32_fmc2_nfc_select_chip;
@@ -994,6 +1024,7 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
static const struct udevice_id stm32_fmc2_nfc_match[] = {
{ .compatible = "st,stm32mp15-fmc2" },
+ { .compatible = "st,stm32mp1-fmc2-nfc" },
{ /* Sentinel */ }
};
--
1.9.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 09/11] board: stm32mp1: update fdt fixup partitions table
2020-07-31 7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
` (7 preceding siblings ...)
2020-07-31 7:53 ` [PATCH 08/11] mtd: rawnand: stm32_fmc2: get resources from parent node Christophe Kerello
@ 2020-07-31 7:53 ` Christophe Kerello
2020-08-13 7:34 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 10/11] configs: stm32mp: add CONFIG_STM32_FMC2_EBI Christophe Kerello
2020-07-31 7:53 ` [PATCH 11/11] ARM: dts: stm32: add FMC2 EBI support for stm32mp157c Christophe Kerello
10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31 7:53 UTC (permalink / raw)
To: u-boot
This patch adds "st,stm32mp1-fmc2-nfc" compatible string in the
fdt fixup partitions table.
Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
board/st/stm32mp1/stm32mp1.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index 1d274c3..f2f6c99 100644
--- a/board/st/stm32mp1/stm32mp1.c
+++ b/board/st/stm32mp1/stm32mp1.c
@@ -851,6 +851,7 @@ int ft_board_setup(void *blob, struct bd_info *bd)
{ "st,stm32f469-qspi", MTD_DEV_TYPE_NOR, },
{ "st,stm32f469-qspi", MTD_DEV_TYPE_SPINAND},
{ "st,stm32mp15-fmc2", MTD_DEV_TYPE_NAND, },
+ { "st,stm32mp1-fmc2-nfc", MTD_DEV_TYPE_NAND, },
};
fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
#endif
--
1.9.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 10/11] configs: stm32mp: add CONFIG_STM32_FMC2_EBI
2020-07-31 7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
` (8 preceding siblings ...)
2020-07-31 7:53 ` [PATCH 09/11] board: stm32mp1: update fdt fixup partitions table Christophe Kerello
@ 2020-07-31 7:53 ` Christophe Kerello
2020-08-13 7:35 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 11/11] ARM: dts: stm32: add FMC2 EBI support for stm32mp157c Christophe Kerello
10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31 7:53 UTC (permalink / raw)
To: u-boot
This patch enables the support of FMC2 EBI.
Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
configs/stm32mp15_basic_defconfig | 1 +
configs/stm32mp15_trusted_defconfig | 1 +
2 files changed, 2 insertions(+)
diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig
index 5c500a1..2094183 100644
--- a/configs/stm32mp15_basic_defconfig
+++ b/configs/stm32mp15_basic_defconfig
@@ -88,6 +88,7 @@ CONFIG_LED=y
CONFIG_LED_GPIO=y
CONFIG_DM_MAILBOX=y
CONFIG_STM32_IPCC=y
+CONFIG_STM32_FMC2_EBI=y
CONFIG_DM_MMC=y
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_STM32_SDMMC2=y
diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig
index 98680cb..8d59d84 100644
--- a/configs/stm32mp15_trusted_defconfig
+++ b/configs/stm32mp15_trusted_defconfig
@@ -68,6 +68,7 @@ CONFIG_LED=y
CONFIG_LED_GPIO=y
CONFIG_DM_MAILBOX=y
CONFIG_STM32_IPCC=y
+CONFIG_STM32_FMC2_EBI=y
CONFIG_DM_MMC=y
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_STM32_SDMMC2=y
--
1.9.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 11/11] ARM: dts: stm32: add FMC2 EBI support for stm32mp157c
2020-07-31 7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
` (9 preceding siblings ...)
2020-07-31 7:53 ` [PATCH 10/11] configs: stm32mp: add CONFIG_STM32_FMC2_EBI Christophe Kerello
@ 2020-07-31 7:53 ` Christophe Kerello
2020-08-13 7:37 ` Patrice CHOTARD
10 siblings, 1 reply; 33+ messages in thread
From: Christophe Kerello @ 2020-07-31 7:53 UTC (permalink / raw)
To: u-boot
This patch adds FMC2 External Bus Interface support on stm32mp157c.
Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
arch/arm/dts/stm32mp151.dtsi | 43 +++++++++++++++++++++++++++-------------
arch/arm/dts/stm32mp157c-ev1.dts | 16 ++++++++-------
2 files changed, 38 insertions(+), 21 deletions(-)
diff --git a/arch/arm/dts/stm32mp151.dtsi b/arch/arm/dts/stm32mp151.dtsi
index 0d97f56..39d9e54 100644
--- a/arch/arm/dts/stm32mp151.dtsi
+++ b/arch/arm/dts/stm32mp151.dtsi
@@ -1328,23 +1328,38 @@
dma-requests = <48>;
};
- fmc: nand-controller at 58002000 {
- compatible = "st,stm32mp15-fmc2";
- reg = <0x58002000 0x1000>,
- <0x80000000 0x1000>,
- <0x88010000 0x1000>,
- <0x88020000 0x1000>,
- <0x81000000 0x1000>,
- <0x89010000 0x1000>,
- <0x89020000 0x1000>;
- interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&mdma1 20 0x10 0x12000a02 0x0 0x0>,
- <&mdma1 20 0x10 0x12000a08 0x0 0x0>,
- <&mdma1 21 0x10 0x12000a0a 0x0 0x0>;
- dma-names = "tx", "rx", "ecc";
+ fmc: memory-controller at 58002000 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "st,stm32mp1-fmc2-ebi";
+ reg = <0x58002000 0x1000>;
clocks = <&rcc FMC_K>;
resets = <&rcc FMC_R>;
status = "disabled";
+
+ ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */
+ <1 0 0x64000000 0x04000000>, /* EBI CS 2 */
+ <2 0 0x68000000 0x04000000>, /* EBI CS 3 */
+ <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */
+ <4 0 0x80000000 0x10000000>; /* NAND */
+
+ nand-controller at 4,0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32mp1-fmc2-nfc";
+ reg = <4 0x00000000 0x1000>,
+ <4 0x08010000 0x1000>,
+ <4 0x08020000 0x1000>,
+ <4 0x01000000 0x1000>,
+ <4 0x09010000 0x1000>,
+ <4 0x09020000 0x1000>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
+ <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
+ <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
+ dma-names = "tx", "rx", "ecc";
+ status = "disabled";
+ };
};
qspi: spi at 58003000 {
diff --git a/arch/arm/dts/stm32mp157c-ev1.dts b/arch/arm/dts/stm32mp157c-ev1.dts
index b190565..46f81ce 100644
--- a/arch/arm/dts/stm32mp157c-ev1.dts
+++ b/arch/arm/dts/stm32mp157c-ev1.dts
@@ -157,14 +157,16 @@
pinctrl-0 = <&fmc_pins_a>;
pinctrl-1 = <&fmc_sleep_pins_a>;
status = "okay";
- #address-cells = <1>;
- #size-cells = <0>;
- nand at 0 {
- reg = <0>;
- nand-on-flash-bbt;
- #address-cells = <1>;
- #size-cells = <1>;
+ nand-controller at 4,0 {
+ status = "okay";
+
+ nand at 0 {
+ reg = <0>;
+ nand-on-flash-bbt;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
};
};
--
1.9.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 01/11] mtd: rawnand: stm32_fmc2: fix a buffer overflow
2020-07-31 7:53 ` [PATCH 01/11] mtd: rawnand: stm32_fmc2: fix a buffer overflow Christophe Kerello
@ 2020-08-13 7:27 ` Patrice CHOTARD
2020-08-13 9:56 ` Patrice CHOTARD
0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 7:27 UTC (permalink / raw)
To: u-boot
Hi Christpohe
On 7/31/20 9:53 AM, Christophe Kerello wrote:
> The chip select defined in the device tree could only be 0 or 1.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
> drivers/mtd/nand/raw/stm32_fmc2_nand.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index 3306bd8..2929acf 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -846,7 +846,7 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
> }
>
> for (i = 0; i < nand->ncs; i++) {
> - if (cs[i] > FMC2_MAX_CE) {
> + if (cs[i] >= FMC2_MAX_CE) {
> pr_err("Invalid reg value: %d\n",
> nand->cs_used[i]);
> return -EINVAL;
Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
Thanks
Patrice
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 02/11] mtd: rawnand: stm32_fmc2: remove useless inline comments
2020-07-31 7:53 ` [PATCH 02/11] mtd: rawnand: stm32_fmc2: remove useless inline comments Christophe Kerello
@ 2020-08-13 7:28 ` Patrice CHOTARD
2020-08-13 9:56 ` Patrice CHOTARD
0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 7:28 UTC (permalink / raw)
To: u-boot
Hi Christophe
On 7/31/20 9:53 AM, Christophe Kerello wrote:
> Remove inline comments that are useless since function label are
> self explanatory.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
> drivers/mtd/nand/raw/stm32_fmc2_nand.c | 25 -------------------------
> 1 file changed, 25 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index 2929acf..f43e3ec 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -179,7 +179,6 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_hw_control *base)
> return container_of(base, struct stm32_fmc2_nfc, base);
> }
>
> -/* Timings configuration */
> static void stm32_fmc2_timings_init(struct nand_chip *chip)
> {
> struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> @@ -211,7 +210,6 @@ static void stm32_fmc2_timings_init(struct nand_chip *chip)
> writel(patt, fmc2->io_base + FMC2_PATT);
> }
>
> -/* Controller configuration */
> static void stm32_fmc2_setup(struct nand_chip *chip)
> {
> struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> @@ -239,7 +237,6 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
> writel(pcr, fmc2->io_base + FMC2_PCR);
> }
>
> -/* Select target */
> static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
> {
> struct nand_chip *chip = mtd_to_nand(mtd);
> @@ -256,14 +253,10 @@ static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
> chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel];
> chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel];
>
> - /* FMC2 setup routine */
> stm32_fmc2_setup(chip);
> -
> - /* Apply timings */
> stm32_fmc2_timings_init(chip);
> }
>
> -/* Set bus width to 16-bit or 8-bit */
> static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
> {
> u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> @@ -274,7 +267,6 @@ static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
> writel(pcr, fmc2->io_base + FMC2_PCR);
> }
>
> -/* Enable/disable ECC */
> static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
> {
> u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> @@ -285,13 +277,11 @@ static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
> writel(pcr, fmc2->io_base + FMC2_PCR);
> }
>
> -/* Clear irq sources in case of bch is used */
> static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
> {
> writel(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
> }
>
> -/* Send command and address cycles */
> static void stm32_fmc2_cmd_ctrl(struct mtd_info *mtd, int cmd,
> unsigned int ctrl)
> {
> @@ -361,7 +351,6 @@ static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
> ecc[1] = heccr >> 8;
> ecc[2] = heccr >> 16;
>
> - /* Disable ecc */
> stm32_fmc2_set_ecc(fmc2, false);
>
> return 0;
> @@ -466,13 +455,11 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
> ecc[12] = bchpbr;
> }
>
> - /* Disable ecc */
> stm32_fmc2_set_ecc(fmc2, false);
>
> return 0;
> }
>
> -/* BCH algorithm correction */
> static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
> u8 *read_ecc, u8 *calc_ecc)
> {
> @@ -497,7 +484,6 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
> bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3);
> bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4);
>
> - /* Disable ECC */
> stm32_fmc2_set_ecc(fmc2, false);
>
> /* No errors found */
> @@ -579,7 +565,6 @@ static int stm32_fmc2_read_page(struct mtd_info *mtd,
> return max_bitflips;
> }
>
> -/* Controller initialization */
> static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
> {
> u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> @@ -622,7 +607,6 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
> writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
> }
>
> -/* Controller timings */
> static void stm32_fmc2_calc_timings(struct nand_chip *chip,
> const struct nand_sdr_timings *sdrt)
> {
> @@ -768,13 +752,11 @@ static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr,
>
> stm32_fmc2_calc_timings(chip, sdrt);
>
> - /* Apply timings */
> stm32_fmc2_timings_init(chip);
>
> return 0;
> }
>
> -/* NAND callbacks setup */
> static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
> {
> chip->ecc.hwctl = stm32_fmc2_hwctl;
> @@ -803,7 +785,6 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
> chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
> }
>
> -/* FMC2 caps */
> static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
> {
> /* Hamming */
> @@ -822,7 +803,6 @@ NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
> FMC2_ECC_STEP_SIZE,
> FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
>
> -/* FMC2 probe */
> static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
> ofnode node)
> {
> @@ -969,7 +949,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
> reset_deassert(&reset);
> }
>
> - /* FMC2 init routine */
> stm32_fmc2_init(fmc2);
>
> chip->controller = &fmc2->base;
> @@ -985,7 +964,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
> chip->ecc.size = FMC2_ECC_STEP_SIZE;
> chip->ecc.strength = FMC2_ECC_BCH8;
>
> - /* Scan to find existence of the device */
> ret = nand_scan_ident(mtd, nand->ncs, NULL);
> if (ret)
> return ret;
> @@ -1012,7 +990,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
> if (chip->bbt_options & NAND_BBT_USE_FLASH)
> chip->bbt_options |= NAND_BBT_NO_OOB;
>
> - /* NAND callbacks setup */
> stm32_fmc2_nand_callbacks_setup(chip);
>
> /* Define ECC layout */
> @@ -1026,11 +1003,9 @@ static int stm32_fmc2_probe(struct udevice *dev)
> ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
> chip->ecc.layout = ecclayout;
>
> - /* Configure bus width to 16-bit */
> if (chip->options & NAND_BUSWIDTH_16)
> stm32_fmc2_set_buswidth_16(fmc2, true);
>
> - /* Scan the device to fill MTD data-structures */
> ret = nand_scan_tail(mtd);
> if (ret)
> return ret;
Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
Thanks
Patrice
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 03/11] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_5S for timeouts
2020-07-31 7:53 ` [PATCH 03/11] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_5S for timeouts Christophe Kerello
@ 2020-08-13 7:29 ` Patrice CHOTARD
2020-08-13 9:57 ` Patrice CHOTARD
0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 7:29 UTC (permalink / raw)
To: u-boot
Hi Christophe
On 7/31/20 9:53 AM, Christophe Kerello wrote:
> FMC2_TIMEOUT_5S will be used each time that we need to wait.
> It was seen, during stress tests in an overloaded system,
> that we could be close to 1 second, even if we never met this
> value. To be safe, FMC2_TIMEOUT_MS is set to 5 seconds.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
> drivers/mtd/nand/raw/stm32_fmc2_nand.c | 8 +++++---
> 1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index f43e3ec..2e947a3 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -131,6 +131,8 @@
>
> #define FMC2_NSEC_PER_SEC 1000000000L
>
> +#define FMC2_TIMEOUT_5S 5000000
> +
> enum stm32_fmc2_ecc {
> FMC2_ECC_HAM = 1,
> FMC2_ECC_BCH4 = 4,
> @@ -339,7 +341,7 @@ static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
> int ret;
>
> ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr,
> - sr & FMC2_SR_NWRF, 10000);
> + sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
> if (ret < 0) {
> pr_err("Ham timeout\n");
> return ret;
> @@ -424,7 +426,7 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
>
> /* Wait until the BCH code is ready */
> ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
> - bchisr & FMC2_BCHISR_EPBRF, 10000);
> + bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
> if (ret < 0) {
> pr_err("Bch timeout\n");
> return ret;
> @@ -472,7 +474,7 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
>
> /* Wait until the decoding error is ready */
> ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
> - bchisr & FMC2_BCHISR_DERF, 10000);
> + bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
> if (ret < 0) {
> pr_err("Bch timeout\n");
> return ret;
Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
Thanks
Patrice
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 04/11] mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2 where relevant
2020-07-31 7:53 ` [PATCH 04/11] mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2 where relevant Christophe Kerello
@ 2020-08-13 7:29 ` Patrice CHOTARD
2020-08-13 9:57 ` Patrice CHOTARD
1 sibling, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 7:29 UTC (permalink / raw)
To: u-boot
Hi CHristophe
On 7/31/20 9:53 AM, Christophe Kerello wrote:
> This patch renames functions and local variables.
> This cleanup is done to get all functions starting by stm32_fmc2_nfc
> in the FMC2 raw NAND driver when all functions will start by
> stm32_fmc2_ebi in the FMC2 EBI driver.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
> drivers/mtd/nand/raw/stm32_fmc2_nand.c | 263 ++++++++++++++++-----------------
> 1 file changed, 131 insertions(+), 132 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index 2e947a3..9718bae 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -181,12 +181,12 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_hw_control *base)
> return container_of(base, struct stm32_fmc2_nfc, base);
> }
>
> -static void stm32_fmc2_timings_init(struct nand_chip *chip)
> +static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
> {
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
> struct stm32_fmc2_timings *timings = &nand->timings;
> - u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> + u32 pcr = readl(nfc->io_base + FMC2_PCR);
> u32 pmem, patt;
>
> /* Set tclr/tar timings */
> @@ -207,15 +207,15 @@ static void stm32_fmc2_timings_init(struct nand_chip *chip)
> patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
> patt |= FMC2_PATT_ATTHIZ(timings->thiz);
>
> - writel(pcr, fmc2->io_base + FMC2_PCR);
> - writel(pmem, fmc2->io_base + FMC2_PMEM);
> - writel(patt, fmc2->io_base + FMC2_PATT);
> + writel(pcr, nfc->io_base + FMC2_PCR);
> + writel(pmem, nfc->io_base + FMC2_PMEM);
> + writel(patt, nfc->io_base + FMC2_PATT);
> }
>
> -static void stm32_fmc2_setup(struct nand_chip *chip)
> +static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
> {
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> - u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> + u32 pcr = readl(nfc->io_base + FMC2_PCR);
>
> /* Configure ECC algorithm (default configuration is Hamming) */
> pcr &= ~FMC2_PCR_ECCALG;
> @@ -236,95 +236,96 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
> pcr &= ~FMC2_PCR_ECCSS_MASK;
> pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
>
> - writel(pcr, fmc2->io_base + FMC2_PCR);
> + writel(pcr, nfc->io_base + FMC2_PCR);
> }
>
> -static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
> +static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
> {
> struct nand_chip *chip = mtd_to_nand(mtd);
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
>
> if (chipnr < 0 || chipnr >= nand->ncs)
> return;
>
> - if (nand->cs_used[chipnr] == fmc2->cs_sel)
> + if (nand->cs_used[chipnr] == nfc->cs_sel)
> return;
>
> - fmc2->cs_sel = nand->cs_used[chipnr];
> - chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel];
> - chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel];
> + nfc->cs_sel = nand->cs_used[chipnr];
> + chip->IO_ADDR_R = nfc->data_base[nfc->cs_sel];
> + chip->IO_ADDR_W = nfc->data_base[nfc->cs_sel];
>
> - stm32_fmc2_setup(chip);
> - stm32_fmc2_timings_init(chip);
> + stm32_fmc2_nfc_setup(chip);
> + stm32_fmc2_nfc_timings_init(chip);
> }
>
> -static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
> +static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
> + bool set)
> {
> - u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> + u32 pcr = readl(nfc->io_base + FMC2_PCR);
>
> pcr &= ~FMC2_PCR_PWID_MASK;
> if (set)
> pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
> - writel(pcr, fmc2->io_base + FMC2_PCR);
> + writel(pcr, nfc->io_base + FMC2_PCR);
> }
>
> -static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
> +static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
> {
> - u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> + u32 pcr = readl(nfc->io_base + FMC2_PCR);
>
> pcr &= ~FMC2_PCR_ECCEN;
> if (enable)
> pcr |= FMC2_PCR_ECCEN;
> - writel(pcr, fmc2->io_base + FMC2_PCR);
> + writel(pcr, nfc->io_base + FMC2_PCR);
> }
>
> -static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
> +static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
> {
> - writel(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
> + writel(FMC2_BCHICR_CLEAR_IRQ, nfc->io_base + FMC2_BCHICR);
> }
>
> -static void stm32_fmc2_cmd_ctrl(struct mtd_info *mtd, int cmd,
> - unsigned int ctrl)
> +static void stm32_fmc2_nfc_cmd_ctrl(struct mtd_info *mtd, int cmd,
> + unsigned int ctrl)
> {
> struct nand_chip *chip = mtd_to_nand(mtd);
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>
> if (cmd == NAND_CMD_NONE)
> return;
>
> if (ctrl & NAND_CLE) {
> - writeb(cmd, fmc2->cmd_base[fmc2->cs_sel]);
> + writeb(cmd, nfc->cmd_base[nfc->cs_sel]);
> return;
> }
>
> - writeb(cmd, fmc2->addr_base[fmc2->cs_sel]);
> + writeb(cmd, nfc->addr_base[nfc->cs_sel]);
> }
>
> /*
> * Enable ECC logic and reset syndrome/parity bits previously calculated
> * Syndrome/parity bits is cleared by setting the ECCEN bit to 0
> */
> -static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
> +static void stm32_fmc2_nfc_hwctl(struct mtd_info *mtd, int mode)
> {
> struct nand_chip *chip = mtd_to_nand(mtd);
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>
> - stm32_fmc2_set_ecc(fmc2, false);
> + stm32_fmc2_nfc_set_ecc(nfc, false);
>
> if (chip->ecc.strength != FMC2_ECC_HAM) {
> - u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> + u32 pcr = readl(nfc->io_base + FMC2_PCR);
>
> if (mode == NAND_ECC_WRITE)
> pcr |= FMC2_PCR_WEN;
> else
> pcr &= ~FMC2_PCR_WEN;
> - writel(pcr, fmc2->io_base + FMC2_PCR);
> + writel(pcr, nfc->io_base + FMC2_PCR);
>
> - stm32_fmc2_clear_bch_irq(fmc2);
> + stm32_fmc2_nfc_clear_bch_irq(nfc);
> }
>
> - stm32_fmc2_set_ecc(fmc2, true);
> + stm32_fmc2_nfc_set_ecc(nfc, true);
> }
>
> /*
> @@ -332,34 +333,34 @@ static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
> * ECC is 3 bytes for 512 bytes of data (supports error correction up to
> * max of 1-bit)
> */
> -static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
> - u8 *ecc)
> +static int stm32_fmc2_nfc_ham_calculate(struct mtd_info *mtd, const u8 *data,
> + u8 *ecc)
> {
> struct nand_chip *chip = mtd_to_nand(mtd);
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> u32 heccr, sr;
> int ret;
>
> - ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr,
> + ret = readl_poll_timeout(nfc->io_base + FMC2_SR, sr,
> sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
> if (ret < 0) {
> pr_err("Ham timeout\n");
> return ret;
> }
>
> - heccr = readl(fmc2->io_base + FMC2_HECCR);
> + heccr = readl(nfc->io_base + FMC2_HECCR);
>
> ecc[0] = heccr;
> ecc[1] = heccr >> 8;
> ecc[2] = heccr >> 16;
>
> - stm32_fmc2_set_ecc(fmc2, false);
> + stm32_fmc2_nfc_set_ecc(nfc, false);
>
> return 0;
> }
>
> -static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
> - u8 *read_ecc, u8 *calc_ecc)
> +static int stm32_fmc2_nfc_ham_correct(struct mtd_info *mtd, u8 *dat,
> + u8 *read_ecc, u8 *calc_ecc)
> {
> u8 bit_position = 0, b0, b1, b2;
> u32 byte_addr = 0, b;
> @@ -416,16 +417,16 @@ static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
> * max of 4-bit/8-bit)
> */
>
> -static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
> - u8 *ecc)
> +static int stm32_fmc2_nfc_bch_calculate(struct mtd_info *mtd, const u8 *data,
> + u8 *ecc)
> {
> struct nand_chip *chip = mtd_to_nand(mtd);
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> u32 bchpbr, bchisr;
> int ret;
>
> /* Wait until the BCH code is ready */
> - ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
> + ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
> bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
> if (ret < 0) {
> pr_err("Bch timeout\n");
> @@ -433,13 +434,13 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
> }
>
> /* Read parity bits */
> - bchpbr = readl(fmc2->io_base + FMC2_BCHPBR1);
> + bchpbr = readl(nfc->io_base + FMC2_BCHPBR1);
> ecc[0] = bchpbr;
> ecc[1] = bchpbr >> 8;
> ecc[2] = bchpbr >> 16;
> ecc[3] = bchpbr >> 24;
>
> - bchpbr = readl(fmc2->io_base + FMC2_BCHPBR2);
> + bchpbr = readl(nfc->io_base + FMC2_BCHPBR2);
> ecc[4] = bchpbr;
> ecc[5] = bchpbr >> 8;
> ecc[6] = bchpbr >> 16;
> @@ -447,46 +448,46 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
> if (chip->ecc.strength == FMC2_ECC_BCH8) {
> ecc[7] = bchpbr >> 24;
>
> - bchpbr = readl(fmc2->io_base + FMC2_BCHPBR3);
> + bchpbr = readl(nfc->io_base + FMC2_BCHPBR3);
> ecc[8] = bchpbr;
> ecc[9] = bchpbr >> 8;
> ecc[10] = bchpbr >> 16;
> ecc[11] = bchpbr >> 24;
>
> - bchpbr = readl(fmc2->io_base + FMC2_BCHPBR4);
> + bchpbr = readl(nfc->io_base + FMC2_BCHPBR4);
> ecc[12] = bchpbr;
> }
>
> - stm32_fmc2_set_ecc(fmc2, false);
> + stm32_fmc2_nfc_set_ecc(nfc, false);
>
> return 0;
> }
>
> -static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
> - u8 *read_ecc, u8 *calc_ecc)
> +static int stm32_fmc2_nfc_bch_correct(struct mtd_info *mtd, u8 *dat,
> + u8 *read_ecc, u8 *calc_ecc)
> {
> struct nand_chip *chip = mtd_to_nand(mtd);
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> u32 bchdsr0, bchdsr1, bchdsr2, bchdsr3, bchdsr4, bchisr;
> u16 pos[8];
> int i, ret, den, eccsize = chip->ecc.size;
> unsigned int nb_errs = 0;
>
> /* Wait until the decoding error is ready */
> - ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
> + ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
> bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
> if (ret < 0) {
> pr_err("Bch timeout\n");
> return ret;
> }
>
> - bchdsr0 = readl(fmc2->io_base + FMC2_BCHDSR0);
> - bchdsr1 = readl(fmc2->io_base + FMC2_BCHDSR1);
> - bchdsr2 = readl(fmc2->io_base + FMC2_BCHDSR2);
> - bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3);
> - bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4);
> + bchdsr0 = readl(nfc->io_base + FMC2_BCHDSR0);
> + bchdsr1 = readl(nfc->io_base + FMC2_BCHDSR1);
> + bchdsr2 = readl(nfc->io_base + FMC2_BCHDSR2);
> + bchdsr3 = readl(nfc->io_base + FMC2_BCHDSR3);
> + bchdsr4 = readl(nfc->io_base + FMC2_BCHDSR4);
>
> - stm32_fmc2_set_ecc(fmc2, false);
> + stm32_fmc2_nfc_set_ecc(nfc, false);
>
> /* No errors found */
> if (likely(!(bchdsr0 & FMC2_BCHDSR0_DEF)))
> @@ -516,9 +517,9 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
> return nb_errs;
> }
>
> -static int stm32_fmc2_read_page(struct mtd_info *mtd,
> - struct nand_chip *chip, u8 *buf,
> - int oob_required, int page)
> +static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
> + struct nand_chip *chip, u8 *buf,
> + int oob_required, int page)
> {
> int i, s, stat, eccsize = chip->ecc.size;
> int eccbytes = chip->ecc.bytes;
> @@ -567,13 +568,13 @@ static int stm32_fmc2_read_page(struct mtd_info *mtd,
> return max_bitflips;
> }
>
> -static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
> +static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
> {
> - u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> - u32 bcr1 = readl(fmc2->io_base + FMC2_BCR1);
> + u32 pcr = readl(nfc->io_base + FMC2_PCR);
> + u32 bcr1 = readl(nfc->io_base + FMC2_BCR1);
>
> /* Set CS used to undefined */
> - fmc2->cs_sel = -1;
> + nfc->cs_sel = -1;
>
> /* Enable wait feature and nand flash memory bank */
> pcr |= FMC2_PCR_PWAITEN;
> @@ -603,19 +604,19 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
> /* Enable FMC2 controller */
> bcr1 |= FMC2_BCR1_FMC2EN;
>
> - writel(bcr1, fmc2->io_base + FMC2_BCR1);
> - writel(pcr, fmc2->io_base + FMC2_PCR);
> - writel(FMC2_PMEM_DEFAULT, fmc2->io_base + FMC2_PMEM);
> - writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
> + writel(bcr1, nfc->io_base + FMC2_BCR1);
> + writel(pcr, nfc->io_base + FMC2_PCR);
> + writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
> + writel(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);
> }
>
> -static void stm32_fmc2_calc_timings(struct nand_chip *chip,
> - const struct nand_sdr_timings *sdrt)
> +static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip,
> + const struct nand_sdr_timings *sdrt)
> {
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
> struct stm32_fmc2_timings *tims = &nand->timings;
> - unsigned long hclk = clk_get_rate(&fmc2->clk);
> + unsigned long hclk = clk_get_rate(&nfc->clk);
> unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
> unsigned long timing, tar, tclr, thiz, twait;
> unsigned long tset_mem, tset_att, thold_mem, thold_att;
> @@ -739,29 +740,28 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
> tims->thold_att = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
> }
>
> -static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr,
> - const struct nand_data_interface *conf)
> +static int stm32_fmc2_nfc_setup_interface(struct mtd_info *mtd, int chipnr,
> + const struct nand_data_interface *cf)
> {
> struct nand_chip *chip = mtd_to_nand(mtd);
> const struct nand_sdr_timings *sdrt;
>
> - sdrt = nand_get_sdr_timings(conf);
> + sdrt = nand_get_sdr_timings(cf);
> if (IS_ERR(sdrt))
> return PTR_ERR(sdrt);
>
> if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
> return 0;
>
> - stm32_fmc2_calc_timings(chip, sdrt);
> -
> - stm32_fmc2_timings_init(chip);
> + stm32_fmc2_nfc_calc_timings(chip, sdrt);
> + stm32_fmc2_nfc_timings_init(chip);
>
> return 0;
> }
>
> -static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
> +static void stm32_fmc2_nfc_nand_callbacks_setup(struct nand_chip *chip)
> {
> - chip->ecc.hwctl = stm32_fmc2_hwctl;
> + chip->ecc.hwctl = stm32_fmc2_nfc_hwctl;
>
> /*
> * Specific callbacks to read/write a page depending on
> @@ -769,17 +769,17 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
> */
> if (chip->ecc.strength == FMC2_ECC_HAM) {
> /* Hamming is used */
> - chip->ecc.calculate = stm32_fmc2_ham_calculate;
> - chip->ecc.correct = stm32_fmc2_ham_correct;
> + chip->ecc.calculate = stm32_fmc2_nfc_ham_calculate;
> + chip->ecc.correct = stm32_fmc2_nfc_ham_correct;
> chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 4 : 3;
> chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK;
> return;
> }
>
> /* BCH is used */
> - chip->ecc.read_page = stm32_fmc2_read_page;
> - chip->ecc.calculate = stm32_fmc2_bch_calculate;
> - chip->ecc.correct = stm32_fmc2_bch_correct;
> + chip->ecc.read_page = stm32_fmc2_nfc_read_page;
> + chip->ecc.calculate = stm32_fmc2_nfc_bch_calculate;
> + chip->ecc.correct = stm32_fmc2_nfc_bch_correct;
>
> if (chip->ecc.strength == FMC2_ECC_BCH8)
> chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 14 : 13;
> @@ -787,7 +787,7 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
> chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
> }
>
> -static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
> +static int stm32_fmc2_nfc_calc_ecc_bytes(int step_size, int strength)
> {
> /* Hamming */
> if (strength == FMC2_ECC_HAM)
> @@ -801,14 +801,13 @@ static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
> return 8;
> }
>
> -NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
> +NAND_ECC_CAPS_SINGLE(stm32_fmc2_nfc_ecc_caps, stm32_fmc2_nfc_calc_ecc_bytes,
> FMC2_ECC_STEP_SIZE,
> FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
>
> -static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
> - ofnode node)
> +static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, ofnode node)
> {
> - struct stm32_fmc2_nand *nand = &fmc2->nand;
> + struct stm32_fmc2_nand *nand = &nfc->nand;
> u32 cs[FMC2_MAX_CE];
> int ret, i;
>
> @@ -834,13 +833,13 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
> return -EINVAL;
> }
>
> - if (fmc2->cs_assigned & BIT(cs[i])) {
> + if (nfc->cs_assigned & BIT(cs[i])) {
> pr_err("Cs already assigned: %d\n",
> nand->cs_used[i]);
> return -EINVAL;
> }
>
> - fmc2->cs_assigned |= BIT(cs[i]);
> + nfc->cs_assigned |= BIT(cs[i]);
> nand->cs_used[i] = cs[i];
> }
>
> @@ -849,8 +848,8 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
> return 0;
> }
>
> -static int stm32_fmc2_parse_dt(struct udevice *dev,
> - struct stm32_fmc2_nfc *fmc2)
> +static int stm32_fmc2_nfc_parse_dt(struct udevice *dev,
> + struct stm32_fmc2_nfc *nfc)
> {
> ofnode child;
> int ret, nchips = 0;
> @@ -869,7 +868,7 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
> }
>
> dev_for_each_subnode(child, dev) {
> - ret = stm32_fmc2_parse_child(fmc2, child);
> + ret = stm32_fmc2_nfc_parse_child(nfc, child);
> if (ret)
> return ret;
> }
> @@ -877,10 +876,10 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
> return 0;
> }
>
> -static int stm32_fmc2_probe(struct udevice *dev)
> +static int stm32_fmc2_nfc_probe(struct udevice *dev)
> {
> - struct stm32_fmc2_nfc *fmc2 = dev_get_priv(dev);
> - struct stm32_fmc2_nand *nand = &fmc2->nand;
> + struct stm32_fmc2_nfc *nfc = dev_get_priv(dev);
> + struct stm32_fmc2_nand *nand = &nfc->nand;
> struct nand_chip *chip = &nand->chip;
> struct mtd_info *mtd = &chip->mtd;
> struct nand_ecclayout *ecclayout;
> @@ -889,10 +888,10 @@ static int stm32_fmc2_probe(struct udevice *dev)
> int oob_index, chip_cs, mem_region, ret;
> unsigned int i;
>
> - spin_lock_init(&fmc2->controller.lock);
> - init_waitqueue_head(&fmc2->controller.wq);
> + spin_lock_init(&nfc->controller.lock);
> + init_waitqueue_head(&nfc->controller.wq);
>
> - ret = stm32_fmc2_parse_dt(dev, fmc2);
> + ret = stm32_fmc2_nfc_parse_dt(dev, nfc);
> if (ret)
> return ret;
>
> @@ -902,11 +901,11 @@ static int stm32_fmc2_probe(struct udevice *dev)
> pr_err("Resource io_base not found");
> return ret;
> }
> - fmc2->io_base = (void __iomem *)resource.start;
> + nfc->io_base = (void __iomem *)resource.start;
>
> for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
> chip_cs++, mem_region += 3) {
> - if (!(fmc2->cs_assigned & BIT(chip_cs)))
> + if (!(nfc->cs_assigned & BIT(chip_cs)))
> continue;
>
> ret = dev_read_resource(dev, mem_region, &resource);
> @@ -915,7 +914,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
> chip_cs);
> return ret;
> }
> - fmc2->data_base[chip_cs] = (void __iomem *)resource.start;
> + nfc->data_base[chip_cs] = (void __iomem *)resource.start;
>
> ret = dev_read_resource(dev, mem_region + 1, &resource);
> if (ret) {
> @@ -923,7 +922,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
> chip_cs);
> return ret;
> }
> - fmc2->cmd_base[chip_cs] = (void __iomem *)resource.start;
> + nfc->cmd_base[chip_cs] = (void __iomem *)resource.start;
>
> ret = dev_read_resource(dev, mem_region + 2, &resource);
> if (ret) {
> @@ -931,15 +930,15 @@ static int stm32_fmc2_probe(struct udevice *dev)
> chip_cs);
> return ret;
> }
> - fmc2->addr_base[chip_cs] = (void __iomem *)resource.start;
> + nfc->addr_base[chip_cs] = (void __iomem *)resource.start;
> }
>
> /* Enable the clock */
> - ret = clk_get_by_index(dev, 0, &fmc2->clk);
> + ret = clk_get_by_index(dev, 0, &nfc->clk);
> if (ret)
> return ret;
>
> - ret = clk_enable(&fmc2->clk);
> + ret = clk_enable(&nfc->clk);
> if (ret)
> return ret;
>
> @@ -951,12 +950,12 @@ static int stm32_fmc2_probe(struct udevice *dev)
> reset_deassert(&reset);
> }
>
> - stm32_fmc2_init(fmc2);
> + stm32_fmc2_nfc_init(nfc);
>
> - chip->controller = &fmc2->base;
> - chip->select_chip = stm32_fmc2_select_chip;
> - chip->setup_data_interface = stm32_fmc2_setup_interface;
> - chip->cmd_ctrl = stm32_fmc2_cmd_ctrl;
> + chip->controller = &nfc->base;
> + chip->select_chip = stm32_fmc2_nfc_select_chip;
> + chip->setup_data_interface = stm32_fmc2_nfc_setup_interface;
> + chip->cmd_ctrl = stm32_fmc2_nfc_cmd_ctrl;
> chip->chip_delay = FMC2_RB_DELAY_US;
> chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE |
> NAND_USE_BOUNCE_BUFFER;
> @@ -982,7 +981,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
> return -EINVAL;
> }
>
> - ret = nand_check_ecc_caps(chip, &stm32_fmc2_ecc_caps,
> + ret = nand_check_ecc_caps(chip, &stm32_fmc2_nfc_ecc_caps,
> mtd->oobsize - FMC2_BBM_LEN);
> if (ret) {
> pr_err("No valid ECC settings set\n");
> @@ -992,10 +991,10 @@ static int stm32_fmc2_probe(struct udevice *dev)
> if (chip->bbt_options & NAND_BBT_USE_FLASH)
> chip->bbt_options |= NAND_BBT_NO_OOB;
>
> - stm32_fmc2_nand_callbacks_setup(chip);
> + stm32_fmc2_nfc_nand_callbacks_setup(chip);
>
> /* Define ECC layout */
> - ecclayout = &fmc2->ecclayout;
> + ecclayout = &nfc->ecclayout;
> ecclayout->eccbytes = chip->ecc.bytes *
> (mtd->writesize / chip->ecc.size);
> oob_index = FMC2_BBM_LEN;
> @@ -1006,7 +1005,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
> chip->ecc.layout = ecclayout;
>
> if (chip->options & NAND_BUSWIDTH_16)
> - stm32_fmc2_set_buswidth_16(fmc2, true);
> + stm32_fmc2_nfc_set_buswidth_16(nfc, true);
>
> ret = nand_scan_tail(mtd);
> if (ret)
> @@ -1015,16 +1014,16 @@ static int stm32_fmc2_probe(struct udevice *dev)
> return nand_register(0, mtd);
> }
>
> -static const struct udevice_id stm32_fmc2_match[] = {
> +static const struct udevice_id stm32_fmc2_nfc_match[] = {
> { .compatible = "st,stm32mp15-fmc2" },
> { /* Sentinel */ }
> };
>
> -U_BOOT_DRIVER(stm32_fmc2_nand) = {
> - .name = "stm32_fmc2_nand",
> +U_BOOT_DRIVER(stm32_fmc2_nfc) = {
> + .name = "stm32_fmc2_nfc",
> .id = UCLASS_MTD,
> - .of_match = stm32_fmc2_match,
> - .probe = stm32_fmc2_probe,
> + .of_match = stm32_fmc2_nfc_match,
> + .probe = stm32_fmc2_nfc_probe,
> .priv_auto_alloc_size = sizeof(struct stm32_fmc2_nfc),
> };
>
> @@ -1034,9 +1033,9 @@ void board_nand_init(void)
> int ret;
>
> ret = uclass_get_device_by_driver(UCLASS_MTD,
> - DM_GET_DRIVER(stm32_fmc2_nand),
> + DM_GET_DRIVER(stm32_fmc2_nfc),
> &dev);
> if (ret && ret != -ENODEV)
> - pr_err("Failed to initialize STM32 FMC2 NAND controller. (error %d)\n",
> + pr_err("Failed to initialize STM32 FMC2 NFC controller. (error %d)\n",
> ret);
> }
Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
Thanks
Patrice
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 05/11] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros
2020-07-31 7:53 ` [PATCH 05/11] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros Christophe Kerello
@ 2020-08-13 7:29 ` Patrice CHOTARD
2020-08-13 9:58 ` Patrice CHOTARD
0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 7:29 UTC (permalink / raw)
To: u-boot
Hi Christophe
On 7/31/20 9:53 AM, Christophe Kerello wrote:
> This patch removes custom macros and uses FIELD_PREP and FIELD_GET macros.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
> drivers/mtd/nand/raw/stm32_fmc2_nand.c | 120 +++++++++++++++------------------
> 1 file changed, 56 insertions(+), 64 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index 9718bae..eba1ded 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -10,6 +10,7 @@
> #include <log.h>
> #include <nand.h>
> #include <reset.h>
> +#include <linux/bitfield.h>
> #include <linux/bitops.h>
> #include <linux/delay.h>
> #include <linux/err.h>
> @@ -60,20 +61,16 @@
> /* Register: FMC2_PCR */
> #define FMC2_PCR_PWAITEN BIT(1)
> #define FMC2_PCR_PBKEN BIT(2)
> -#define FMC2_PCR_PWID_MASK GENMASK(5, 4)
> -#define FMC2_PCR_PWID(x) (((x) & 0x3) << 4)
> +#define FMC2_PCR_PWID GENMASK(5, 4)
> #define FMC2_PCR_PWID_BUSWIDTH_8 0
> #define FMC2_PCR_PWID_BUSWIDTH_16 1
> #define FMC2_PCR_ECCEN BIT(6)
> #define FMC2_PCR_ECCALG BIT(8)
> -#define FMC2_PCR_TCLR_MASK GENMASK(12, 9)
> -#define FMC2_PCR_TCLR(x) (((x) & 0xf) << 9)
> +#define FMC2_PCR_TCLR GENMASK(12, 9)
> #define FMC2_PCR_TCLR_DEFAULT 0xf
> -#define FMC2_PCR_TAR_MASK GENMASK(16, 13)
> -#define FMC2_PCR_TAR(x) (((x) & 0xf) << 13)
> +#define FMC2_PCR_TAR GENMASK(16, 13)
> #define FMC2_PCR_TAR_DEFAULT 0xf
> -#define FMC2_PCR_ECCSS_MASK GENMASK(19, 17)
> -#define FMC2_PCR_ECCSS(x) (((x) & 0x7) << 17)
> +#define FMC2_PCR_ECCSS GENMASK(19, 17)
> #define FMC2_PCR_ECCSS_512 1
> #define FMC2_PCR_ECCSS_2048 3
> #define FMC2_PCR_BCHECC BIT(24)
> @@ -83,17 +80,17 @@
> #define FMC2_SR_NWRF BIT(6)
>
> /* Register: FMC2_PMEM */
> -#define FMC2_PMEM_MEMSET(x) (((x) & 0xff) << 0)
> -#define FMC2_PMEM_MEMWAIT(x) (((x) & 0xff) << 8)
> -#define FMC2_PMEM_MEMHOLD(x) (((x) & 0xff) << 16)
> -#define FMC2_PMEM_MEMHIZ(x) (((x) & 0xff) << 24)
> +#define FMC2_PMEM_MEMSET GENMASK(7, 0)
> +#define FMC2_PMEM_MEMWAIT GENMASK(15, 8)
> +#define FMC2_PMEM_MEMHOLD GENMASK(23, 16)
> +#define FMC2_PMEM_MEMHIZ GENMASK(31, 24)
> #define FMC2_PMEM_DEFAULT 0x0a0a0a0a
>
> /* Register: FMC2_PATT */
> -#define FMC2_PATT_ATTSET(x) (((x) & 0xff) << 0)
> -#define FMC2_PATT_ATTWAIT(x) (((x) & 0xff) << 8)
> -#define FMC2_PATT_ATTHOLD(x) (((x) & 0xff) << 16)
> -#define FMC2_PATT_ATTHIZ(x) (((x) & 0xff) << 24)
> +#define FMC2_PATT_ATTSET GENMASK(7, 0)
> +#define FMC2_PATT_ATTWAIT GENMASK(15, 8)
> +#define FMC2_PATT_ATTHOLD GENMASK(23, 16)
> +#define FMC2_PATT_ATTHIZ GENMASK(31, 24)
> #define FMC2_PATT_DEFAULT 0x0a0a0a0a
>
> /* Register: FMC2_BCHISR */
> @@ -106,28 +103,23 @@
> /* Register: FMC2_BCHDSR0 */
> #define FMC2_BCHDSR0_DUE BIT(0)
> #define FMC2_BCHDSR0_DEF BIT(1)
> -#define FMC2_BCHDSR0_DEN_MASK GENMASK(7, 4)
> -#define FMC2_BCHDSR0_DEN_SHIFT 4
> +#define FMC2_BCHDSR0_DEN GENMASK(7, 4)
>
> /* Register: FMC2_BCHDSR1 */
> -#define FMC2_BCHDSR1_EBP1_MASK GENMASK(12, 0)
> -#define FMC2_BCHDSR1_EBP2_MASK GENMASK(28, 16)
> -#define FMC2_BCHDSR1_EBP2_SHIFT 16
> +#define FMC2_BCHDSR1_EBP1 GENMASK(12, 0)
> +#define FMC2_BCHDSR1_EBP2 GENMASK(28, 16)
>
> /* Register: FMC2_BCHDSR2 */
> -#define FMC2_BCHDSR2_EBP3_MASK GENMASK(12, 0)
> -#define FMC2_BCHDSR2_EBP4_MASK GENMASK(28, 16)
> -#define FMC2_BCHDSR2_EBP4_SHIFT 16
> +#define FMC2_BCHDSR2_EBP3 GENMASK(12, 0)
> +#define FMC2_BCHDSR2_EBP4 GENMASK(28, 16)
>
> /* Register: FMC2_BCHDSR3 */
> -#define FMC2_BCHDSR3_EBP5_MASK GENMASK(12, 0)
> -#define FMC2_BCHDSR3_EBP6_MASK GENMASK(28, 16)
> -#define FMC2_BCHDSR3_EBP6_SHIFT 16
> +#define FMC2_BCHDSR3_EBP5 GENMASK(12, 0)
> +#define FMC2_BCHDSR3_EBP6 GENMASK(28, 16)
>
> /* Register: FMC2_BCHDSR4 */
> -#define FMC2_BCHDSR4_EBP7_MASK GENMASK(12, 0)
> -#define FMC2_BCHDSR4_EBP8_MASK GENMASK(28, 16)
> -#define FMC2_BCHDSR4_EBP8_SHIFT 16
> +#define FMC2_BCHDSR4_EBP7 GENMASK(12, 0)
> +#define FMC2_BCHDSR4_EBP8 GENMASK(28, 16)
>
> #define FMC2_NSEC_PER_SEC 1000000000L
>
> @@ -190,22 +182,22 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
> u32 pmem, patt;
>
> /* Set tclr/tar timings */
> - pcr &= ~FMC2_PCR_TCLR_MASK;
> - pcr |= FMC2_PCR_TCLR(timings->tclr);
> - pcr &= ~FMC2_PCR_TAR_MASK;
> - pcr |= FMC2_PCR_TAR(timings->tar);
> + pcr &= ~FMC2_PCR_TCLR;
> + pcr |= FIELD_PREP(FMC2_PCR_TCLR, timings->tclr);
> + pcr &= ~FMC2_PCR_TAR;
> + pcr |= FIELD_PREP(FMC2_PCR_TAR, timings->tar);
>
> /* Set tset/twait/thold/thiz timings in common bank */
> - pmem = FMC2_PMEM_MEMSET(timings->tset_mem);
> - pmem |= FMC2_PMEM_MEMWAIT(timings->twait);
> - pmem |= FMC2_PMEM_MEMHOLD(timings->thold_mem);
> - pmem |= FMC2_PMEM_MEMHIZ(timings->thiz);
> + pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
> + pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
> + pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
> + pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
>
> /* Set tset/twait/thold/thiz timings in attribut bank */
> - patt = FMC2_PATT_ATTSET(timings->tset_att);
> - patt |= FMC2_PATT_ATTWAIT(timings->twait);
> - patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
> - patt |= FMC2_PATT_ATTHIZ(timings->thiz);
> + patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
> + patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
> + patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
> + patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
>
> writel(pcr, nfc->io_base + FMC2_PCR);
> writel(pmem, nfc->io_base + FMC2_PMEM);
> @@ -228,13 +220,13 @@ static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
> }
>
> /* Set buswidth */
> - pcr &= ~FMC2_PCR_PWID_MASK;
> + pcr &= ~FMC2_PCR_PWID;
> if (chip->options & NAND_BUSWIDTH_16)
> - pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
> + pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
>
> /* Set ECC sector size */
> - pcr &= ~FMC2_PCR_ECCSS_MASK;
> - pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
> + pcr &= ~FMC2_PCR_ECCSS;
> + pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
>
> writel(pcr, nfc->io_base + FMC2_PCR);
> }
> @@ -264,9 +256,9 @@ static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
> {
> u32 pcr = readl(nfc->io_base + FMC2_PCR);
>
> - pcr &= ~FMC2_PCR_PWID_MASK;
> + pcr &= ~FMC2_PCR_PWID;
> if (set)
> - pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
> + pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
> writel(pcr, nfc->io_base + FMC2_PCR);
> }
>
> @@ -497,16 +489,16 @@ static int stm32_fmc2_nfc_bch_correct(struct mtd_info *mtd, u8 *dat,
> if (unlikely(bchdsr0 & FMC2_BCHDSR0_DUE))
> return -EBADMSG;
>
> - pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK;
> - pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT;
> - pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK;
> - pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT;
> - pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK;
> - pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT;
> - pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK;
> - pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT;
> + pos[0] = FIELD_GET(FMC2_BCHDSR1_EBP1, bchdsr1);
> + pos[1] = FIELD_GET(FMC2_BCHDSR1_EBP2, bchdsr1);
> + pos[2] = FIELD_GET(FMC2_BCHDSR2_EBP3, bchdsr2);
> + pos[3] = FIELD_GET(FMC2_BCHDSR2_EBP4, bchdsr2);
> + pos[4] = FIELD_GET(FMC2_BCHDSR3_EBP5, bchdsr3);
> + pos[5] = FIELD_GET(FMC2_BCHDSR3_EBP6, bchdsr3);
> + pos[6] = FIELD_GET(FMC2_BCHDSR4_EBP7, bchdsr4);
> + pos[7] = FIELD_GET(FMC2_BCHDSR4_EBP8, bchdsr4);
>
> - den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT;
> + den = FIELD_GET(FMC2_BCHDSR0_DEN, bchdsr0);
> for (i = 0; i < den; i++) {
> if (pos[i] < eccsize * 8) {
> __change_bit(pos[i], (unsigned long *)dat);
> @@ -581,7 +573,7 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
> pcr |= FMC2_PCR_PBKEN;
>
> /* Set buswidth to 8 bits mode for identification */
> - pcr &= ~FMC2_PCR_PWID_MASK;
> + pcr &= ~FMC2_PCR_PWID;
>
> /* ECC logic is disabled */
> pcr &= ~FMC2_PCR_ECCEN;
> @@ -592,14 +584,14 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
> pcr &= ~FMC2_PCR_WEN;
>
> /* Set default ECC sector size */
> - pcr &= ~FMC2_PCR_ECCSS_MASK;
> - pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048);
> + pcr &= ~FMC2_PCR_ECCSS;
> + pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_2048);
>
> /* Set default tclr/tar timings */
> - pcr &= ~FMC2_PCR_TCLR_MASK;
> - pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT);
> - pcr &= ~FMC2_PCR_TAR_MASK;
> - pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT);
> + pcr &= ~FMC2_PCR_TCLR;
> + pcr |= FIELD_PREP(FMC2_PCR_TCLR, FMC2_PCR_TCLR_DEFAULT);
> + pcr &= ~FMC2_PCR_TAR;
> + pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
>
> /* Enable FMC2 controller */
> bcr1 |= FMC2_BCR1_FMC2EN;
Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
Thanks
Patrice
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 06/11] mtd: rawnand: stm32_fmc2: use clrsetbits_le32
2020-07-31 7:53 ` [PATCH 06/11] mtd: rawnand: stm32_fmc2: use clrsetbits_le32 Christophe Kerello
@ 2020-08-13 7:30 ` Patrice CHOTARD
2020-08-13 9:58 ` Patrice CHOTARD
0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 7:30 UTC (permalink / raw)
To: u-boot
Hi Christophe
On 7/31/20 9:53 AM, Christophe Kerello wrote:
> This patch uses clrsetbits_le32 function instead of multiple instructions.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
> drivers/mtd/nand/raw/stm32_fmc2_nand.c | 56 +++++++++++++---------------------
> 1 file changed, 21 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index eba1ded..1e4d757 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -178,40 +178,37 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
> struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
> struct stm32_fmc2_timings *timings = &nand->timings;
> - u32 pcr = readl(nfc->io_base + FMC2_PCR);
> u32 pmem, patt;
>
> /* Set tclr/tar timings */
> - pcr &= ~FMC2_PCR_TCLR;
> - pcr |= FIELD_PREP(FMC2_PCR_TCLR, timings->tclr);
> - pcr &= ~FMC2_PCR_TAR;
> - pcr |= FIELD_PREP(FMC2_PCR_TAR, timings->tar);
> + clrsetbits_le32(nfc->io_base + FMC2_PCR,
> + FMC2_PCR_TCLR | FMC2_PCR_TAR,
> + FIELD_PREP(FMC2_PCR_TCLR, timings->tclr) |
> + FIELD_PREP(FMC2_PCR_TAR, timings->tar));
>
> /* Set tset/twait/thold/thiz timings in common bank */
> pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
> pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
> pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
> pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
> + writel(pmem, nfc->io_base + FMC2_PMEM);
>
> /* Set tset/twait/thold/thiz timings in attribut bank */
> patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
> patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
> patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
> patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
> -
> - writel(pcr, nfc->io_base + FMC2_PCR);
> - writel(pmem, nfc->io_base + FMC2_PMEM);
> writel(patt, nfc->io_base + FMC2_PATT);
> }
>
> static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
> {
> struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> - u32 pcr = readl(nfc->io_base + FMC2_PCR);
> + u32 pcr = 0, pcr_mask;
>
> /* Configure ECC algorithm (default configuration is Hamming) */
> - pcr &= ~FMC2_PCR_ECCALG;
> - pcr &= ~FMC2_PCR_BCHECC;
> + pcr_mask = FMC2_PCR_ECCALG;
> + pcr_mask |= FMC2_PCR_BCHECC;
> if (chip->ecc.strength == FMC2_ECC_BCH8) {
> pcr |= FMC2_PCR_ECCALG;
> pcr |= FMC2_PCR_BCHECC;
> @@ -220,15 +217,15 @@ static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
> }
>
> /* Set buswidth */
> - pcr &= ~FMC2_PCR_PWID;
> + pcr_mask |= FMC2_PCR_PWID;
> if (chip->options & NAND_BUSWIDTH_16)
> pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
>
> /* Set ECC sector size */
> - pcr &= ~FMC2_PCR_ECCSS;
> + pcr_mask |= FMC2_PCR_ECCSS;
> pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
>
> - writel(pcr, nfc->io_base + FMC2_PCR);
> + clrsetbits_le32(nfc->io_base + FMC2_PCR, pcr_mask, pcr);
> }
>
> static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
> @@ -254,22 +251,18 @@ static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
> static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
> bool set)
> {
> - u32 pcr = readl(nfc->io_base + FMC2_PCR);
> + u32 pcr;
>
> - pcr &= ~FMC2_PCR_PWID;
> - if (set)
> - pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
> - writel(pcr, nfc->io_base + FMC2_PCR);
> + pcr = set ? FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16) :
> + FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_8);
> +
> + clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_PWID, pcr);
> }
>
> static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
> {
> - u32 pcr = readl(nfc->io_base + FMC2_PCR);
> -
> - pcr &= ~FMC2_PCR_ECCEN;
> - if (enable)
> - pcr |= FMC2_PCR_ECCEN;
> - writel(pcr, nfc->io_base + FMC2_PCR);
> + clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_ECCEN,
> + enable ? FMC2_PCR_ECCEN : 0);
> }
>
> static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
> @@ -306,13 +299,8 @@ static void stm32_fmc2_nfc_hwctl(struct mtd_info *mtd, int mode)
> stm32_fmc2_nfc_set_ecc(nfc, false);
>
> if (chip->ecc.strength != FMC2_ECC_HAM) {
> - u32 pcr = readl(nfc->io_base + FMC2_PCR);
> -
> - if (mode == NAND_ECC_WRITE)
> - pcr |= FMC2_PCR_WEN;
> - else
> - pcr &= ~FMC2_PCR_WEN;
> - writel(pcr, nfc->io_base + FMC2_PCR);
> + clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_WEN,
> + mode == NAND_ECC_WRITE ? FMC2_PCR_WEN : 0);
>
> stm32_fmc2_nfc_clear_bch_irq(nfc);
> }
> @@ -563,7 +551,6 @@ static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
> static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
> {
> u32 pcr = readl(nfc->io_base + FMC2_PCR);
> - u32 bcr1 = readl(nfc->io_base + FMC2_BCR1);
>
> /* Set CS used to undefined */
> nfc->cs_sel = -1;
> @@ -594,9 +581,8 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
> pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
>
> /* Enable FMC2 controller */
> - bcr1 |= FMC2_BCR1_FMC2EN;
> + setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
>
> - writel(bcr1, nfc->io_base + FMC2_BCR1);
> writel(pcr, nfc->io_base + FMC2_PCR);
> writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
> writel(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);
Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
Thanks
Patrice
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 07/11] memory: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver
2020-07-31 7:53 ` [PATCH 07/11] memory: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver Christophe Kerello
@ 2020-08-13 7:31 ` Patrice CHOTARD
2020-08-13 9:58 ` Patrice CHOTARD
0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 7:31 UTC (permalink / raw)
To: u-boot
Hi Christophe
On 7/31/20 9:53 AM, Christophe Kerello wrote:
> The driver adds the support for the STMicroelectronics FMC2 EBI controller
> found on STM32MP SOCs.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
> drivers/memory/Kconfig | 9 +
> drivers/memory/Makefile | 1 +
> drivers/memory/stm32-fmc2-ebi.c | 1056 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 1066 insertions(+)
> create mode 100644 drivers/memory/stm32-fmc2-ebi.c
>
> diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
> index 4fbb5aa..7271892 100644
> --- a/drivers/memory/Kconfig
> +++ b/drivers/memory/Kconfig
> @@ -4,6 +4,15 @@
>
> menu "Memory Controller drivers"
>
> +config STM32_FMC2_EBI
> + bool "Support for FMC2 External Bus Interface on STM32MP SoCs"
> + depends on ARCH_STM32MP
> + help
> + Select this option to enable the STM32 FMC2 External Bus Interface
> + controller. This driver configures the transactions with external
> + devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on
> + SOCs containing the FMC2 External Bus Interface.
> +
> config TI_AEMIF
> tristate "Texas Instruments AEMIF driver"
> depends on ARCH_KEYSTONE
> diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
> index 238add0..fec52ef 100644
> --- a/drivers/memory/Makefile
> +++ b/drivers/memory/Makefile
> @@ -1,2 +1,3 @@
>
> +obj-$(CONFIG_STM32_FMC2_EBI) += stm32-fmc2-ebi.o
> obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
> diff --git a/drivers/memory/stm32-fmc2-ebi.c b/drivers/memory/stm32-fmc2-ebi.c
> new file mode 100644
> index 0000000..d887a1e
> --- /dev/null
> +++ b/drivers/memory/stm32-fmc2-ebi.c
> @@ -0,0 +1,1056 @@
> +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
> +/*
> + * Copyright (C) STMicroelectronics 2020
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <reset.h>
> +#include <linux/bitfield.h>
> +#include <linux/err.h>
> +#include <linux/iopoll.h>
> +#include <linux/ioport.h>
> +
> +/* FMC2 Controller Registers */
> +#define FMC2_BCR1 0x0
> +#define FMC2_BTR1 0x4
> +#define FMC2_BCR(x) ((x) * 0x8 + FMC2_BCR1)
> +#define FMC2_BTR(x) ((x) * 0x8 + FMC2_BTR1)
> +#define FMC2_PCSCNTR 0x20
> +#define FMC2_BWTR1 0x104
> +#define FMC2_BWTR(x) ((x) * 0x8 + FMC2_BWTR1)
> +
> +/* Register: FMC2_BCR1 */
> +#define FMC2_BCR1_CCLKEN BIT(20)
> +#define FMC2_BCR1_FMC2EN BIT(31)
> +
> +/* Register: FMC2_BCRx */
> +#define FMC2_BCR_MBKEN BIT(0)
> +#define FMC2_BCR_MUXEN BIT(1)
> +#define FMC2_BCR_MTYP GENMASK(3, 2)
> +#define FMC2_BCR_MWID GENMASK(5, 4)
> +#define FMC2_BCR_FACCEN BIT(6)
> +#define FMC2_BCR_BURSTEN BIT(8)
> +#define FMC2_BCR_WAITPOL BIT(9)
> +#define FMC2_BCR_WAITCFG BIT(11)
> +#define FMC2_BCR_WREN BIT(12)
> +#define FMC2_BCR_WAITEN BIT(13)
> +#define FMC2_BCR_EXTMOD BIT(14)
> +#define FMC2_BCR_ASYNCWAIT BIT(15)
> +#define FMC2_BCR_CPSIZE GENMASK(18, 16)
> +#define FMC2_BCR_CBURSTRW BIT(19)
> +#define FMC2_BCR_NBLSET GENMASK(23, 22)
> +
> +/* Register: FMC2_BTRx/FMC2_BWTRx */
> +#define FMC2_BXTR_ADDSET GENMASK(3, 0)
> +#define FMC2_BXTR_ADDHLD GENMASK(7, 4)
> +#define FMC2_BXTR_DATAST GENMASK(15, 8)
> +#define FMC2_BXTR_BUSTURN GENMASK(19, 16)
> +#define FMC2_BTR_CLKDIV GENMASK(23, 20)
> +#define FMC2_BTR_DATLAT GENMASK(27, 24)
> +#define FMC2_BXTR_ACCMOD GENMASK(29, 28)
> +#define FMC2_BXTR_DATAHLD GENMASK(31, 30)
> +
> +/* Register: FMC2_PCSCNTR */
> +#define FMC2_PCSCNTR_CSCOUNT GENMASK(15, 0)
> +#define FMC2_PCSCNTR_CNTBEN(x) BIT((x) + 16)
> +
> +#define FMC2_MAX_EBI_CE 4
> +#define FMC2_MAX_BANKS 5
> +
> +#define FMC2_BCR_CPSIZE_0 0x0
> +#define FMC2_BCR_CPSIZE_128 0x1
> +#define FMC2_BCR_CPSIZE_256 0x2
> +#define FMC2_BCR_CPSIZE_512 0x3
> +#define FMC2_BCR_CPSIZE_1024 0x4
> +
> +#define FMC2_BCR_MWID_8 0x0
> +#define FMC2_BCR_MWID_16 0x1
> +
> +#define FMC2_BCR_MTYP_SRAM 0x0
> +#define FMC2_BCR_MTYP_PSRAM 0x1
> +#define FMC2_BCR_MTYP_NOR 0x2
> +
> +#define FMC2_BXTR_EXTMOD_A 0x0
> +#define FMC2_BXTR_EXTMOD_B 0x1
> +#define FMC2_BXTR_EXTMOD_C 0x2
> +#define FMC2_BXTR_EXTMOD_D 0x3
> +
> +#define FMC2_BCR_NBLSET_MAX 0x3
> +#define FMC2_BXTR_ADDSET_MAX 0xf
> +#define FMC2_BXTR_ADDHLD_MAX 0xf
> +#define FMC2_BXTR_DATAST_MAX 0xff
> +#define FMC2_BXTR_BUSTURN_MAX 0xf
> +#define FMC2_BXTR_DATAHLD_MAX 0x3
> +#define FMC2_BTR_CLKDIV_MAX 0xf
> +#define FMC2_BTR_DATLAT_MAX 0xf
> +#define FMC2_PCSCNTR_CSCOUNT_MAX 0xff
> +
> +#define FMC2_NSEC_PER_SEC 1000000000L
> +
> +enum stm32_fmc2_ebi_bank {
> + FMC2_EBI1 = 0,
> + FMC2_EBI2,
> + FMC2_EBI3,
> + FMC2_EBI4,
> + FMC2_NAND
> +};
> +
> +enum stm32_fmc2_ebi_register_type {
> + FMC2_REG_BCR = 1,
> + FMC2_REG_BTR,
> + FMC2_REG_BWTR,
> + FMC2_REG_PCSCNTR
> +};
> +
> +enum stm32_fmc2_ebi_transaction_type {
> + FMC2_ASYNC_MODE_1_SRAM = 0,
> + FMC2_ASYNC_MODE_1_PSRAM,
> + FMC2_ASYNC_MODE_A_SRAM,
> + FMC2_ASYNC_MODE_A_PSRAM,
> + FMC2_ASYNC_MODE_2_NOR,
> + FMC2_ASYNC_MODE_B_NOR,
> + FMC2_ASYNC_MODE_C_NOR,
> + FMC2_ASYNC_MODE_D_NOR,
> + FMC2_SYNC_READ_SYNC_WRITE_PSRAM,
> + FMC2_SYNC_READ_ASYNC_WRITE_PSRAM,
> + FMC2_SYNC_READ_SYNC_WRITE_NOR,
> + FMC2_SYNC_READ_ASYNC_WRITE_NOR
> +};
> +
> +enum stm32_fmc2_ebi_buswidth {
> + FMC2_BUSWIDTH_8 = 8,
> + FMC2_BUSWIDTH_16 = 16
> +};
> +
> +enum stm32_fmc2_ebi_cpsize {
> + FMC2_CPSIZE_0 = 0,
> + FMC2_CPSIZE_128 = 128,
> + FMC2_CPSIZE_256 = 256,
> + FMC2_CPSIZE_512 = 512,
> + FMC2_CPSIZE_1024 = 1024
> +};
> +
> +struct stm32_fmc2_ebi {
> + struct clk clk;
> + fdt_addr_t io_base;
> + u8 bank_assigned;
> +};
> +
> +/*
> + * struct stm32_fmc2_prop - STM32 FMC2 EBI property
> + * @name: the device tree binding name of the property
> + * @bprop: indicate that it is a boolean property
> + * @mprop: indicate that it is a mandatory property
> + * @reg_type: the register that have to be modified
> + * @reg_mask: the bit that have to be modified in the selected register
> + * in case of it is a boolean property
> + * @reset_val: the default value that have to be set in case the property
> + * has not been defined in the device tree
> + * @check: this callback ckecks that the property is compliant with the
> + * transaction type selected
> + * @calculate: this callback is called to calculate for exemple a timing
> + * set in nanoseconds in the device tree in clock cycles or in
> + * clock period
> + * @set: this callback applies the values in the registers
> + */
> +struct stm32_fmc2_prop {
> + const char *name;
> + bool bprop;
> + bool mprop;
> + int reg_type;
> + u32 reg_mask;
> + u32 reset_val;
> + int (*check)(struct stm32_fmc2_ebi *ebi,
> + const struct stm32_fmc2_prop *prop, int cs);
> + u32 (*calculate)(struct stm32_fmc2_ebi *ebi, int cs, u32 setup);
> + int (*set)(struct stm32_fmc2_ebi *ebi,
> + const struct stm32_fmc2_prop *prop,
> + int cs, u32 setup);
> +};
> +
> +static int stm32_fmc2_ebi_check_mux(struct stm32_fmc2_ebi *ebi,
> + const struct stm32_fmc2_prop *prop,
> + int cs)
> +{
> + u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
> +
> + if (bcr & FMC2_BCR_MTYP)
> + return 0;
> +
> + return -EINVAL;
> +}
> +
> +static int stm32_fmc2_ebi_check_waitcfg(struct stm32_fmc2_ebi *ebi,
> + const struct stm32_fmc2_prop *prop,
> + int cs)
> +{
> + u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
> + u32 val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
> +
> + if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
> + return 0;
> +
> + return -EINVAL;
> +}
> +
> +static int stm32_fmc2_ebi_check_sync_trans(struct stm32_fmc2_ebi *ebi,
> + const struct stm32_fmc2_prop *prop,
> + int cs)
> +{
> + u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
> +
> + if (bcr & FMC2_BCR_BURSTEN)
> + return 0;
> +
> + return -EINVAL;
> +}
> +
> +static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2_ebi *ebi,
> + const struct stm32_fmc2_prop *prop,
> + int cs)
> +{
> + u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
> +
> + if (!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW))
> + return 0;
> +
> + return -EINVAL;
> +}
> +
> +static int stm32_fmc2_ebi_check_cpsize(struct stm32_fmc2_ebi *ebi,
> + const struct stm32_fmc2_prop *prop,
> + int cs)
> +{
> + u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
> + u32 val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
> +
> + if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
> + return 0;
> +
> + return -EINVAL;
> +}
> +
> +static int stm32_fmc2_ebi_check_address_hold(struct stm32_fmc2_ebi *ebi,
> + const struct stm32_fmc2_prop *prop,
> + int cs)
> +{
> + u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
> + u32 bxtr = prop->reg_type == FMC2_REG_BWTR ?
> + readl(ebi->io_base + FMC2_BWTR(cs)) :
> + readl(ebi->io_base + FMC2_BTR(cs));
> + u32 val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
> +
> + if ((!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW)) &&
> + ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN))
> + return 0;
> +
> + return -EINVAL;
> +}
> +
> +static int stm32_fmc2_ebi_check_clk_period(struct stm32_fmc2_ebi *ebi,
> + const struct stm32_fmc2_prop *prop,
> + int cs)
> +{
> + u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
> + u32 bcr1 = cs ? readl(ebi->io_base + FMC2_BCR1) : bcr;
> +
> + if (bcr & FMC2_BCR_BURSTEN && (!cs || !(bcr1 & FMC2_BCR1_CCLKEN)))
> + return 0;
> +
> + return -EINVAL;
> +}
> +
> +static int stm32_fmc2_ebi_check_cclk(struct stm32_fmc2_ebi *ebi,
> + const struct stm32_fmc2_prop *prop,
> + int cs)
> +{
> + if (cs)
> + return -EINVAL;
> +
> + return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs);
> +}
> +
> +static u32 stm32_fmc2_ebi_ns_to_clock_cycles(struct stm32_fmc2_ebi *ebi,
> + int cs, u32 setup)
> +{
> + unsigned long hclk = clk_get_rate(&ebi->clk);
> + unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
> +
> + return DIV_ROUND_UP(setup * 1000, hclkp);
> +}
> +
> +static u32 stm32_fmc2_ebi_ns_to_clk_period(struct stm32_fmc2_ebi *ebi,
> + int cs, u32 setup)
> +{
> + u32 nb_clk_cycles = stm32_fmc2_ebi_ns_to_clock_cycles(ebi, cs, setup);
> + u32 bcr = readl(ebi->io_base + FMC2_BCR1);
> + u32 btr = bcr & FMC2_BCR1_CCLKEN || !cs ?
> + readl(ebi->io_base + FMC2_BTR1) :
> + readl(ebi->io_base + FMC2_BTR(cs));
> + u32 clk_period = FIELD_GET(FMC2_BTR_CLKDIV, btr) + 1;
> +
> + return DIV_ROUND_UP(nb_clk_cycles, clk_period);
> +}
> +
> +static int stm32_fmc2_ebi_get_reg(int reg_type, int cs, u32 *reg)
> +{
> + switch (reg_type) {
> + case FMC2_REG_BCR:
> + *reg = FMC2_BCR(cs);
> + break;
> + case FMC2_REG_BTR:
> + *reg = FMC2_BTR(cs);
> + break;
> + case FMC2_REG_BWTR:
> + *reg = FMC2_BWTR(cs);
> + break;
> + case FMC2_REG_PCSCNTR:
> + *reg = FMC2_PCSCNTR;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int stm32_fmc2_ebi_set_bit_field(struct stm32_fmc2_ebi *ebi,
> + const struct stm32_fmc2_prop *prop,
> + int cs, u32 setup)
> +{
> + u32 reg;
> + int ret;
> +
> + ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, ®);
> + 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
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 08/11] mtd: rawnand: stm32_fmc2: get resources from parent node
2020-07-31 7:53 ` [PATCH 08/11] mtd: rawnand: stm32_fmc2: get resources from parent node Christophe Kerello
@ 2020-08-13 7:33 ` Patrice CHOTARD
2020-08-13 9:58 ` Patrice CHOTARD
0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 7:33 UTC (permalink / raw)
To: u-boot
Hi Christophe
On 7/31/20 9:53 AM, Christophe Kerello wrote:
> FMC2 EBI support has been added. Common resources (registers base
> address and clock) can now be shared between the 2 drivers using
> "st,stm32mp1-fmc2-nfc" compatible string. It means that the
> common resources should now be found in the parent device when EBI
> node is available.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
> drivers/mtd/nand/raw/stm32_fmc2_nand.c | 87 +++++++++++++++++++++++-----------
> 1 file changed, 59 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index 1e4d757..47fe610 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -158,10 +158,10 @@ struct stm32_fmc2_nfc {
> struct nand_hw_control base;
> struct stm32_fmc2_nand nand;
> struct nand_ecclayout ecclayout;
> - void __iomem *io_base;
> - void __iomem *data_base[FMC2_MAX_CE];
> - void __iomem *cmd_base[FMC2_MAX_CE];
> - void __iomem *addr_base[FMC2_MAX_CE];
> + fdt_addr_t io_base;
> + fdt_addr_t data_base[FMC2_MAX_CE];
> + fdt_addr_t cmd_base[FMC2_MAX_CE];
> + fdt_addr_t addr_base[FMC2_MAX_CE];
> struct clk clk;
>
> u8 cs_assigned;
> @@ -241,8 +241,8 @@ static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
> return;
>
> nfc->cs_sel = nand->cs_used[chipnr];
> - chip->IO_ADDR_R = nfc->data_base[nfc->cs_sel];
> - chip->IO_ADDR_W = nfc->data_base[nfc->cs_sel];
> + chip->IO_ADDR_R = (void __iomem *)nfc->data_base[nfc->cs_sel];
> + chip->IO_ADDR_W = (void __iomem *)nfc->data_base[nfc->cs_sel];
>
> stm32_fmc2_nfc_setup(chip);
> stm32_fmc2_nfc_timings_init(chip);
> @@ -548,7 +548,7 @@ static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
> return max_bitflips;
> }
>
> -static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
> +static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc, bool has_parent)
> {
> u32 pcr = readl(nfc->io_base + FMC2_PCR);
>
> @@ -581,7 +581,8 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
> pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
>
> /* Enable FMC2 controller */
> - setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
> + if (!has_parent)
> + setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
>
> writel(pcr, nfc->io_base + FMC2_PCR);
> writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
> @@ -854,6 +855,30 @@ static int stm32_fmc2_nfc_parse_dt(struct udevice *dev,
> return 0;
> }
>
> +static struct udevice *stm32_fmc2_nfc_get_cdev(struct udevice *dev)
> +{
> + struct udevice *pdev = dev_get_parent(dev);
> + struct udevice *cdev = NULL;
> + bool ebi_found = false;
> +
> + if (pdev && ofnode_device_is_compatible(dev_ofnode(pdev),
> + "st,stm32mp1-fmc2-ebi"))
> + ebi_found = true;
> +
> + if (ofnode_device_is_compatible(dev_ofnode(dev),
> + "st,stm32mp1-fmc2-nfc")) {
> + if (ebi_found)
> + cdev = pdev;
> +
> + return cdev;
> + }
> +
> + if (!ebi_found)
> + cdev = dev;
> +
> + return cdev;
> +}
> +
> static int stm32_fmc2_nfc_probe(struct udevice *dev)
> {
> struct stm32_fmc2_nfc *nfc = dev_get_priv(dev);
> @@ -861,58 +886,63 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
> struct nand_chip *chip = &nand->chip;
> struct mtd_info *mtd = &chip->mtd;
> struct nand_ecclayout *ecclayout;
> - struct resource resource;
> + struct udevice *cdev;
> struct reset_ctl reset;
> int oob_index, chip_cs, mem_region, ret;
> unsigned int i;
> + int start_region = 0;
> + fdt_addr_t addr;
>
> spin_lock_init(&nfc->controller.lock);
> init_waitqueue_head(&nfc->controller.wq);
>
> + cdev = stm32_fmc2_nfc_get_cdev(dev);
> + if (!cdev)
> + return -EINVAL;
> +
> ret = stm32_fmc2_nfc_parse_dt(dev, nfc);
> if (ret)
> return ret;
>
> - /* Get resources */
> - ret = dev_read_resource(dev, 0, &resource);
> - if (ret) {
> - pr_err("Resource io_base not found");
> - return ret;
> - }
> - nfc->io_base = (void __iomem *)resource.start;
> + nfc->io_base = dev_read_addr(cdev);
> + if (nfc->io_base == FDT_ADDR_T_NONE)
> + return -EINVAL;
> +
> + if (dev == cdev)
> + start_region = 1;
>
> - for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
> + for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE;
> chip_cs++, mem_region += 3) {
> if (!(nfc->cs_assigned & BIT(chip_cs)))
> continue;
>
> - ret = dev_read_resource(dev, mem_region, &resource);
> - if (ret) {
> + addr = dev_read_addr_index(dev, mem_region);
> + if (addr == FDT_ADDR_T_NONE) {
> pr_err("Resource data_base not found for cs%d",
> chip_cs);
> return ret;
> }
> - nfc->data_base[chip_cs] = (void __iomem *)resource.start;
> + nfc->data_base[chip_cs] = addr;
>
> - ret = dev_read_resource(dev, mem_region + 1, &resource);
> - if (ret) {
> + addr = dev_read_addr_index(dev, mem_region + 1);
> + if (addr == FDT_ADDR_T_NONE) {
> pr_err("Resource cmd_base not found for cs%d",
> chip_cs);
> return ret;
> }
> - nfc->cmd_base[chip_cs] = (void __iomem *)resource.start;
> + nfc->cmd_base[chip_cs] = addr;
>
> - ret = dev_read_resource(dev, mem_region + 2, &resource);
> - if (ret) {
> + addr = dev_read_addr_index(dev, mem_region + 2);
> + if (addr == FDT_ADDR_T_NONE) {
> pr_err("Resource addr_base not found for cs%d",
> chip_cs);
> return ret;
> }
> - nfc->addr_base[chip_cs] = (void __iomem *)resource.start;
> + nfc->addr_base[chip_cs] = addr;
> }
>
> /* Enable the clock */
> - ret = clk_get_by_index(dev, 0, &nfc->clk);
> + ret = clk_get_by_index(cdev, 0, &nfc->clk);
> if (ret)
> return ret;
>
> @@ -928,7 +958,7 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
> reset_deassert(&reset);
> }
>
> - stm32_fmc2_nfc_init(nfc);
> + stm32_fmc2_nfc_init(nfc, dev != cdev);
>
> chip->controller = &nfc->base;
> chip->select_chip = stm32_fmc2_nfc_select_chip;
> @@ -994,6 +1024,7 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
>
> static const struct udevice_id stm32_fmc2_nfc_match[] = {
> { .compatible = "st,stm32mp15-fmc2" },
> + { .compatible = "st,stm32mp1-fmc2-nfc" },
> { /* Sentinel */ }
> };
>
Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
Thanks
Patrice
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 09/11] board: stm32mp1: update fdt fixup partitions table
2020-07-31 7:53 ` [PATCH 09/11] board: stm32mp1: update fdt fixup partitions table Christophe Kerello
@ 2020-08-13 7:34 ` Patrice CHOTARD
0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 7:34 UTC (permalink / raw)
To: u-boot
Hi Christophe
On 7/31/20 9:53 AM, Christophe Kerello wrote:
> This patch adds "st,stm32mp1-fmc2-nfc" compatible string in the
> fdt fixup partitions table.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
> board/st/stm32mp1/stm32mp1.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
> index 1d274c3..f2f6c99 100644
> --- a/board/st/stm32mp1/stm32mp1.c
> +++ b/board/st/stm32mp1/stm32mp1.c
> @@ -851,6 +851,7 @@ int ft_board_setup(void *blob, struct bd_info *bd)
> { "st,stm32f469-qspi", MTD_DEV_TYPE_NOR, },
> { "st,stm32f469-qspi", MTD_DEV_TYPE_SPINAND},
> { "st,stm32mp15-fmc2", MTD_DEV_TYPE_NAND, },
> + { "st,stm32mp1-fmc2-nfc", MTD_DEV_TYPE_NAND, },
> };
> fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
> #endif
Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
Thanks
Patrice
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 10/11] configs: stm32mp: add CONFIG_STM32_FMC2_EBI
2020-07-31 7:53 ` [PATCH 10/11] configs: stm32mp: add CONFIG_STM32_FMC2_EBI Christophe Kerello
@ 2020-08-13 7:35 ` Patrice CHOTARD
2020-08-13 9:59 ` Patrice CHOTARD
0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 7:35 UTC (permalink / raw)
To: u-boot
Hi Christophe
On 7/31/20 9:53 AM, Christophe Kerello wrote:
> This patch enables the support of FMC2 EBI.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
> configs/stm32mp15_basic_defconfig | 1 +
> configs/stm32mp15_trusted_defconfig | 1 +
> 2 files changed, 2 insertions(+)
>
> diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig
> index 5c500a1..2094183 100644
> --- a/configs/stm32mp15_basic_defconfig
> +++ b/configs/stm32mp15_basic_defconfig
> @@ -88,6 +88,7 @@ CONFIG_LED=y
> CONFIG_LED_GPIO=y
> CONFIG_DM_MAILBOX=y
> CONFIG_STM32_IPCC=y
> +CONFIG_STM32_FMC2_EBI=y
> CONFIG_DM_MMC=y
> CONFIG_SUPPORT_EMMC_BOOT=y
> CONFIG_STM32_SDMMC2=y
> diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig
> index 98680cb..8d59d84 100644
> --- a/configs/stm32mp15_trusted_defconfig
> +++ b/configs/stm32mp15_trusted_defconfig
> @@ -68,6 +68,7 @@ CONFIG_LED=y
> CONFIG_LED_GPIO=y
> CONFIG_DM_MAILBOX=y
> CONFIG_STM32_IPCC=y
> +CONFIG_STM32_FMC2_EBI=y
> CONFIG_DM_MMC=y
> CONFIG_SUPPORT_EMMC_BOOT=y
> CONFIG_STM32_SDMMC2=y
Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
Thanks
Patrice
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 11/11] ARM: dts: stm32: add FMC2 EBI support for stm32mp157c
2020-07-31 7:53 ` [PATCH 11/11] ARM: dts: stm32: add FMC2 EBI support for stm32mp157c Christophe Kerello
@ 2020-08-13 7:37 ` Patrice CHOTARD
2020-08-13 9:59 ` Patrice CHOTARD
0 siblings, 1 reply; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 7:37 UTC (permalink / raw)
To: u-boot
Hi Christophe
On 7/31/20 9:53 AM, Christophe Kerello wrote:
> This patch adds FMC2 External Bus Interface support on stm32mp157c.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
> arch/arm/dts/stm32mp151.dtsi | 43 +++++++++++++++++++++++++++-------------
> arch/arm/dts/stm32mp157c-ev1.dts | 16 ++++++++-------
> 2 files changed, 38 insertions(+), 21 deletions(-)
>
> diff --git a/arch/arm/dts/stm32mp151.dtsi b/arch/arm/dts/stm32mp151.dtsi
> index 0d97f56..39d9e54 100644
> --- a/arch/arm/dts/stm32mp151.dtsi
> +++ b/arch/arm/dts/stm32mp151.dtsi
> @@ -1328,23 +1328,38 @@
> dma-requests = <48>;
> };
>
> - fmc: nand-controller at 58002000 {
> - compatible = "st,stm32mp15-fmc2";
> - reg = <0x58002000 0x1000>,
> - <0x80000000 0x1000>,
> - <0x88010000 0x1000>,
> - <0x88020000 0x1000>,
> - <0x81000000 0x1000>,
> - <0x89010000 0x1000>,
> - <0x89020000 0x1000>;
> - interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
> - dmas = <&mdma1 20 0x10 0x12000a02 0x0 0x0>,
> - <&mdma1 20 0x10 0x12000a08 0x0 0x0>,
> - <&mdma1 21 0x10 0x12000a0a 0x0 0x0>;
> - dma-names = "tx", "rx", "ecc";
> + fmc: memory-controller at 58002000 {
> + #address-cells = <2>;
> + #size-cells = <1>;
> + compatible = "st,stm32mp1-fmc2-ebi";
> + reg = <0x58002000 0x1000>;
> clocks = <&rcc FMC_K>;
> resets = <&rcc FMC_R>;
> status = "disabled";
> +
> + ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */
> + <1 0 0x64000000 0x04000000>, /* EBI CS 2 */
> + <2 0 0x68000000 0x04000000>, /* EBI CS 3 */
> + <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */
> + <4 0 0x80000000 0x10000000>; /* NAND */
> +
> + nand-controller at 4,0 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + compatible = "st,stm32mp1-fmc2-nfc";
> + reg = <4 0x00000000 0x1000>,
> + <4 0x08010000 0x1000>,
> + <4 0x08020000 0x1000>,
> + <4 0x01000000 0x1000>,
> + <4 0x09010000 0x1000>,
> + <4 0x09020000 0x1000>;
> + interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
> + dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
> + <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
> + <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
> + dma-names = "tx", "rx", "ecc";
> + status = "disabled";
> + };
> };
>
> qspi: spi at 58003000 {
> diff --git a/arch/arm/dts/stm32mp157c-ev1.dts b/arch/arm/dts/stm32mp157c-ev1.dts
> index b190565..46f81ce 100644
> --- a/arch/arm/dts/stm32mp157c-ev1.dts
> +++ b/arch/arm/dts/stm32mp157c-ev1.dts
> @@ -157,14 +157,16 @@
> pinctrl-0 = <&fmc_pins_a>;
> pinctrl-1 = <&fmc_sleep_pins_a>;
> status = "okay";
> - #address-cells = <1>;
> - #size-cells = <0>;
>
> - nand at 0 {
> - reg = <0>;
> - nand-on-flash-bbt;
> - #address-cells = <1>;
> - #size-cells = <1>;
> + nand-controller at 4,0 {
> + status = "okay";
> +
> + nand at 0 {
> + reg = <0>;
> + nand-on-flash-bbt;
> + #address-cells = <1>;
> + #size-cells = <1>;
> + };
> };
> };
>
Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
Thanks
Patrice
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 01/11] mtd: rawnand: stm32_fmc2: fix a buffer overflow
2020-08-13 7:27 ` Patrice CHOTARD
@ 2020-08-13 9:56 ` Patrice CHOTARD
0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 9:56 UTC (permalink / raw)
To: u-boot
On 8/13/20 9:27 AM, Patrice CHOTARD wrote:
> Hi Christpohe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> The chip select defined in the device tree could only be 0 or 1.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>> drivers/mtd/nand/raw/stm32_fmc2_nand.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
Applied on u-boot-stm/master
Thanks
>>
>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> index 3306bd8..2929acf 100644
>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> @@ -846,7 +846,7 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
>> }
>>
>> for (i = 0; i < nand->ncs; i++) {
>> - if (cs[i] > FMC2_MAX_CE) {
>> + if (cs[i] >= FMC2_MAX_CE) {
>> pr_err("Invalid reg value: %d\n",
>> nand->cs_used[i]);
>> return -EINVAL;
> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
>
> Thanks
>
> Patrice
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 02/11] mtd: rawnand: stm32_fmc2: remove useless inline comments
2020-08-13 7:28 ` Patrice CHOTARD
@ 2020-08-13 9:56 ` Patrice CHOTARD
0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 9:56 UTC (permalink / raw)
To: u-boot
On 8/13/20 9:28 AM, Patrice CHOTARD wrote:
> Hi Christophe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> Remove inline comments that are useless since function label are
>> self explanatory.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>> drivers/mtd/nand/raw/stm32_fmc2_nand.c | 25 -------------------------
>> 1 file changed, 25 deletions(-)
Applied on u-boot-stm/master
Thanks
>>
>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> index 2929acf..f43e3ec 100644
>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> @@ -179,7 +179,6 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_hw_control *base)
>> return container_of(base, struct stm32_fmc2_nfc, base);
>> }
>>
>> -/* Timings configuration */
>> static void stm32_fmc2_timings_init(struct nand_chip *chip)
>> {
>> struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
>> @@ -211,7 +210,6 @@ static void stm32_fmc2_timings_init(struct nand_chip *chip)
>> writel(patt, fmc2->io_base + FMC2_PATT);
>> }
>>
>> -/* Controller configuration */
>> static void stm32_fmc2_setup(struct nand_chip *chip)
>> {
>> struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
>> @@ -239,7 +237,6 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
>> writel(pcr, fmc2->io_base + FMC2_PCR);
>> }
>>
>> -/* Select target */
>> static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
>> {
>> struct nand_chip *chip = mtd_to_nand(mtd);
>> @@ -256,14 +253,10 @@ static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
>> chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel];
>> chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel];
>>
>> - /* FMC2 setup routine */
>> stm32_fmc2_setup(chip);
>> -
>> - /* Apply timings */
>> stm32_fmc2_timings_init(chip);
>> }
>>
>> -/* Set bus width to 16-bit or 8-bit */
>> static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
>> {
>> u32 pcr = readl(fmc2->io_base + FMC2_PCR);
>> @@ -274,7 +267,6 @@ static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
>> writel(pcr, fmc2->io_base + FMC2_PCR);
>> }
>>
>> -/* Enable/disable ECC */
>> static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
>> {
>> u32 pcr = readl(fmc2->io_base + FMC2_PCR);
>> @@ -285,13 +277,11 @@ static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
>> writel(pcr, fmc2->io_base + FMC2_PCR);
>> }
>>
>> -/* Clear irq sources in case of bch is used */
>> static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
>> {
>> writel(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
>> }
>>
>> -/* Send command and address cycles */
>> static void stm32_fmc2_cmd_ctrl(struct mtd_info *mtd, int cmd,
>> unsigned int ctrl)
>> {
>> @@ -361,7 +351,6 @@ static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
>> ecc[1] = heccr >> 8;
>> ecc[2] = heccr >> 16;
>>
>> - /* Disable ecc */
>> stm32_fmc2_set_ecc(fmc2, false);
>>
>> return 0;
>> @@ -466,13 +455,11 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
>> ecc[12] = bchpbr;
>> }
>>
>> - /* Disable ecc */
>> stm32_fmc2_set_ecc(fmc2, false);
>>
>> return 0;
>> }
>>
>> -/* BCH algorithm correction */
>> static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
>> u8 *read_ecc, u8 *calc_ecc)
>> {
>> @@ -497,7 +484,6 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
>> bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3);
>> bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4);
>>
>> - /* Disable ECC */
>> stm32_fmc2_set_ecc(fmc2, false);
>>
>> /* No errors found */
>> @@ -579,7 +565,6 @@ static int stm32_fmc2_read_page(struct mtd_info *mtd,
>> return max_bitflips;
>> }
>>
>> -/* Controller initialization */
>> static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
>> {
>> u32 pcr = readl(fmc2->io_base + FMC2_PCR);
>> @@ -622,7 +607,6 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
>> writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
>> }
>>
>> -/* Controller timings */
>> static void stm32_fmc2_calc_timings(struct nand_chip *chip,
>> const struct nand_sdr_timings *sdrt)
>> {
>> @@ -768,13 +752,11 @@ static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr,
>>
>> stm32_fmc2_calc_timings(chip, sdrt);
>>
>> - /* Apply timings */
>> stm32_fmc2_timings_init(chip);
>>
>> return 0;
>> }
>>
>> -/* NAND callbacks setup */
>> static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
>> {
>> chip->ecc.hwctl = stm32_fmc2_hwctl;
>> @@ -803,7 +785,6 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
>> chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
>> }
>>
>> -/* FMC2 caps */
>> static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
>> {
>> /* Hamming */
>> @@ -822,7 +803,6 @@ NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
>> FMC2_ECC_STEP_SIZE,
>> FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
>>
>> -/* FMC2 probe */
>> static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
>> ofnode node)
>> {
>> @@ -969,7 +949,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
>> reset_deassert(&reset);
>> }
>>
>> - /* FMC2 init routine */
>> stm32_fmc2_init(fmc2);
>>
>> chip->controller = &fmc2->base;
>> @@ -985,7 +964,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
>> chip->ecc.size = FMC2_ECC_STEP_SIZE;
>> chip->ecc.strength = FMC2_ECC_BCH8;
>>
>> - /* Scan to find existence of the device */
>> ret = nand_scan_ident(mtd, nand->ncs, NULL);
>> if (ret)
>> return ret;
>> @@ -1012,7 +990,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
>> if (chip->bbt_options & NAND_BBT_USE_FLASH)
>> chip->bbt_options |= NAND_BBT_NO_OOB;
>>
>> - /* NAND callbacks setup */
>> stm32_fmc2_nand_callbacks_setup(chip);
>>
>> /* Define ECC layout */
>> @@ -1026,11 +1003,9 @@ static int stm32_fmc2_probe(struct udevice *dev)
>> ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
>> chip->ecc.layout = ecclayout;
>>
>> - /* Configure bus width to 16-bit */
>> if (chip->options & NAND_BUSWIDTH_16)
>> stm32_fmc2_set_buswidth_16(fmc2, true);
>>
>> - /* Scan the device to fill MTD data-structures */
>> ret = nand_scan_tail(mtd);
>> if (ret)
>> return ret;
> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
>
> Thanks
>
> Patrice
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 04/11] mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2 where relevant
2020-07-31 7:53 ` [PATCH 04/11] mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2 where relevant Christophe Kerello
2020-08-13 7:29 ` Patrice CHOTARD
@ 2020-08-13 9:57 ` Patrice CHOTARD
1 sibling, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 9:57 UTC (permalink / raw)
To: u-boot
On 7/31/20 9:53 AM, Christophe Kerello wrote:
> This patch renames functions and local variables.
> This cleanup is done to get all functions starting by stm32_fmc2_nfc
> in the FMC2 raw NAND driver when all functions will start by
> stm32_fmc2_ebi in the FMC2 EBI driver.
>
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>
> drivers/mtd/nand/raw/stm32_fmc2_nand.c | 263 ++++++++++++++++-----------------
> 1 file changed, 131 insertions(+), 132 deletions(-)
Applied on u-boot-stm/master
Thanks
>
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index 2e947a3..9718bae 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -181,12 +181,12 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_hw_control *base)
> return container_of(base, struct stm32_fmc2_nfc, base);
> }
>
> -static void stm32_fmc2_timings_init(struct nand_chip *chip)
> +static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
> {
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
> struct stm32_fmc2_timings *timings = &nand->timings;
> - u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> + u32 pcr = readl(nfc->io_base + FMC2_PCR);
> u32 pmem, patt;
>
> /* Set tclr/tar timings */
> @@ -207,15 +207,15 @@ static void stm32_fmc2_timings_init(struct nand_chip *chip)
> patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
> patt |= FMC2_PATT_ATTHIZ(timings->thiz);
>
> - writel(pcr, fmc2->io_base + FMC2_PCR);
> - writel(pmem, fmc2->io_base + FMC2_PMEM);
> - writel(patt, fmc2->io_base + FMC2_PATT);
> + writel(pcr, nfc->io_base + FMC2_PCR);
> + writel(pmem, nfc->io_base + FMC2_PMEM);
> + writel(patt, nfc->io_base + FMC2_PATT);
> }
>
> -static void stm32_fmc2_setup(struct nand_chip *chip)
> +static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
> {
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> - u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> + u32 pcr = readl(nfc->io_base + FMC2_PCR);
>
> /* Configure ECC algorithm (default configuration is Hamming) */
> pcr &= ~FMC2_PCR_ECCALG;
> @@ -236,95 +236,96 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
> pcr &= ~FMC2_PCR_ECCSS_MASK;
> pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
>
> - writel(pcr, fmc2->io_base + FMC2_PCR);
> + writel(pcr, nfc->io_base + FMC2_PCR);
> }
>
> -static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
> +static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
> {
> struct nand_chip *chip = mtd_to_nand(mtd);
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
>
> if (chipnr < 0 || chipnr >= nand->ncs)
> return;
>
> - if (nand->cs_used[chipnr] == fmc2->cs_sel)
> + if (nand->cs_used[chipnr] == nfc->cs_sel)
> return;
>
> - fmc2->cs_sel = nand->cs_used[chipnr];
> - chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel];
> - chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel];
> + nfc->cs_sel = nand->cs_used[chipnr];
> + chip->IO_ADDR_R = nfc->data_base[nfc->cs_sel];
> + chip->IO_ADDR_W = nfc->data_base[nfc->cs_sel];
>
> - stm32_fmc2_setup(chip);
> - stm32_fmc2_timings_init(chip);
> + stm32_fmc2_nfc_setup(chip);
> + stm32_fmc2_nfc_timings_init(chip);
> }
>
> -static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
> +static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
> + bool set)
> {
> - u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> + u32 pcr = readl(nfc->io_base + FMC2_PCR);
>
> pcr &= ~FMC2_PCR_PWID_MASK;
> if (set)
> pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
> - writel(pcr, fmc2->io_base + FMC2_PCR);
> + writel(pcr, nfc->io_base + FMC2_PCR);
> }
>
> -static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
> +static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
> {
> - u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> + u32 pcr = readl(nfc->io_base + FMC2_PCR);
>
> pcr &= ~FMC2_PCR_ECCEN;
> if (enable)
> pcr |= FMC2_PCR_ECCEN;
> - writel(pcr, fmc2->io_base + FMC2_PCR);
> + writel(pcr, nfc->io_base + FMC2_PCR);
> }
>
> -static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
> +static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
> {
> - writel(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
> + writel(FMC2_BCHICR_CLEAR_IRQ, nfc->io_base + FMC2_BCHICR);
> }
>
> -static void stm32_fmc2_cmd_ctrl(struct mtd_info *mtd, int cmd,
> - unsigned int ctrl)
> +static void stm32_fmc2_nfc_cmd_ctrl(struct mtd_info *mtd, int cmd,
> + unsigned int ctrl)
> {
> struct nand_chip *chip = mtd_to_nand(mtd);
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>
> if (cmd == NAND_CMD_NONE)
> return;
>
> if (ctrl & NAND_CLE) {
> - writeb(cmd, fmc2->cmd_base[fmc2->cs_sel]);
> + writeb(cmd, nfc->cmd_base[nfc->cs_sel]);
> return;
> }
>
> - writeb(cmd, fmc2->addr_base[fmc2->cs_sel]);
> + writeb(cmd, nfc->addr_base[nfc->cs_sel]);
> }
>
> /*
> * Enable ECC logic and reset syndrome/parity bits previously calculated
> * Syndrome/parity bits is cleared by setting the ECCEN bit to 0
> */
> -static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
> +static void stm32_fmc2_nfc_hwctl(struct mtd_info *mtd, int mode)
> {
> struct nand_chip *chip = mtd_to_nand(mtd);
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>
> - stm32_fmc2_set_ecc(fmc2, false);
> + stm32_fmc2_nfc_set_ecc(nfc, false);
>
> if (chip->ecc.strength != FMC2_ECC_HAM) {
> - u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> + u32 pcr = readl(nfc->io_base + FMC2_PCR);
>
> if (mode == NAND_ECC_WRITE)
> pcr |= FMC2_PCR_WEN;
> else
> pcr &= ~FMC2_PCR_WEN;
> - writel(pcr, fmc2->io_base + FMC2_PCR);
> + writel(pcr, nfc->io_base + FMC2_PCR);
>
> - stm32_fmc2_clear_bch_irq(fmc2);
> + stm32_fmc2_nfc_clear_bch_irq(nfc);
> }
>
> - stm32_fmc2_set_ecc(fmc2, true);
> + stm32_fmc2_nfc_set_ecc(nfc, true);
> }
>
> /*
> @@ -332,34 +333,34 @@ static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
> * ECC is 3 bytes for 512 bytes of data (supports error correction up to
> * max of 1-bit)
> */
> -static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
> - u8 *ecc)
> +static int stm32_fmc2_nfc_ham_calculate(struct mtd_info *mtd, const u8 *data,
> + u8 *ecc)
> {
> struct nand_chip *chip = mtd_to_nand(mtd);
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> u32 heccr, sr;
> int ret;
>
> - ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr,
> + ret = readl_poll_timeout(nfc->io_base + FMC2_SR, sr,
> sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
> if (ret < 0) {
> pr_err("Ham timeout\n");
> return ret;
> }
>
> - heccr = readl(fmc2->io_base + FMC2_HECCR);
> + heccr = readl(nfc->io_base + FMC2_HECCR);
>
> ecc[0] = heccr;
> ecc[1] = heccr >> 8;
> ecc[2] = heccr >> 16;
>
> - stm32_fmc2_set_ecc(fmc2, false);
> + stm32_fmc2_nfc_set_ecc(nfc, false);
>
> return 0;
> }
>
> -static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
> - u8 *read_ecc, u8 *calc_ecc)
> +static int stm32_fmc2_nfc_ham_correct(struct mtd_info *mtd, u8 *dat,
> + u8 *read_ecc, u8 *calc_ecc)
> {
> u8 bit_position = 0, b0, b1, b2;
> u32 byte_addr = 0, b;
> @@ -416,16 +417,16 @@ static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
> * max of 4-bit/8-bit)
> */
>
> -static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
> - u8 *ecc)
> +static int stm32_fmc2_nfc_bch_calculate(struct mtd_info *mtd, const u8 *data,
> + u8 *ecc)
> {
> struct nand_chip *chip = mtd_to_nand(mtd);
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> u32 bchpbr, bchisr;
> int ret;
>
> /* Wait until the BCH code is ready */
> - ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
> + ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
> bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
> if (ret < 0) {
> pr_err("Bch timeout\n");
> @@ -433,13 +434,13 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
> }
>
> /* Read parity bits */
> - bchpbr = readl(fmc2->io_base + FMC2_BCHPBR1);
> + bchpbr = readl(nfc->io_base + FMC2_BCHPBR1);
> ecc[0] = bchpbr;
> ecc[1] = bchpbr >> 8;
> ecc[2] = bchpbr >> 16;
> ecc[3] = bchpbr >> 24;
>
> - bchpbr = readl(fmc2->io_base + FMC2_BCHPBR2);
> + bchpbr = readl(nfc->io_base + FMC2_BCHPBR2);
> ecc[4] = bchpbr;
> ecc[5] = bchpbr >> 8;
> ecc[6] = bchpbr >> 16;
> @@ -447,46 +448,46 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
> if (chip->ecc.strength == FMC2_ECC_BCH8) {
> ecc[7] = bchpbr >> 24;
>
> - bchpbr = readl(fmc2->io_base + FMC2_BCHPBR3);
> + bchpbr = readl(nfc->io_base + FMC2_BCHPBR3);
> ecc[8] = bchpbr;
> ecc[9] = bchpbr >> 8;
> ecc[10] = bchpbr >> 16;
> ecc[11] = bchpbr >> 24;
>
> - bchpbr = readl(fmc2->io_base + FMC2_BCHPBR4);
> + bchpbr = readl(nfc->io_base + FMC2_BCHPBR4);
> ecc[12] = bchpbr;
> }
>
> - stm32_fmc2_set_ecc(fmc2, false);
> + stm32_fmc2_nfc_set_ecc(nfc, false);
>
> return 0;
> }
>
> -static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
> - u8 *read_ecc, u8 *calc_ecc)
> +static int stm32_fmc2_nfc_bch_correct(struct mtd_info *mtd, u8 *dat,
> + u8 *read_ecc, u8 *calc_ecc)
> {
> struct nand_chip *chip = mtd_to_nand(mtd);
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> u32 bchdsr0, bchdsr1, bchdsr2, bchdsr3, bchdsr4, bchisr;
> u16 pos[8];
> int i, ret, den, eccsize = chip->ecc.size;
> unsigned int nb_errs = 0;
>
> /* Wait until the decoding error is ready */
> - ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
> + ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
> bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
> if (ret < 0) {
> pr_err("Bch timeout\n");
> return ret;
> }
>
> - bchdsr0 = readl(fmc2->io_base + FMC2_BCHDSR0);
> - bchdsr1 = readl(fmc2->io_base + FMC2_BCHDSR1);
> - bchdsr2 = readl(fmc2->io_base + FMC2_BCHDSR2);
> - bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3);
> - bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4);
> + bchdsr0 = readl(nfc->io_base + FMC2_BCHDSR0);
> + bchdsr1 = readl(nfc->io_base + FMC2_BCHDSR1);
> + bchdsr2 = readl(nfc->io_base + FMC2_BCHDSR2);
> + bchdsr3 = readl(nfc->io_base + FMC2_BCHDSR3);
> + bchdsr4 = readl(nfc->io_base + FMC2_BCHDSR4);
>
> - stm32_fmc2_set_ecc(fmc2, false);
> + stm32_fmc2_nfc_set_ecc(nfc, false);
>
> /* No errors found */
> if (likely(!(bchdsr0 & FMC2_BCHDSR0_DEF)))
> @@ -516,9 +517,9 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
> return nb_errs;
> }
>
> -static int stm32_fmc2_read_page(struct mtd_info *mtd,
> - struct nand_chip *chip, u8 *buf,
> - int oob_required, int page)
> +static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
> + struct nand_chip *chip, u8 *buf,
> + int oob_required, int page)
> {
> int i, s, stat, eccsize = chip->ecc.size;
> int eccbytes = chip->ecc.bytes;
> @@ -567,13 +568,13 @@ static int stm32_fmc2_read_page(struct mtd_info *mtd,
> return max_bitflips;
> }
>
> -static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
> +static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
> {
> - u32 pcr = readl(fmc2->io_base + FMC2_PCR);
> - u32 bcr1 = readl(fmc2->io_base + FMC2_BCR1);
> + u32 pcr = readl(nfc->io_base + FMC2_PCR);
> + u32 bcr1 = readl(nfc->io_base + FMC2_BCR1);
>
> /* Set CS used to undefined */
> - fmc2->cs_sel = -1;
> + nfc->cs_sel = -1;
>
> /* Enable wait feature and nand flash memory bank */
> pcr |= FMC2_PCR_PWAITEN;
> @@ -603,19 +604,19 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
> /* Enable FMC2 controller */
> bcr1 |= FMC2_BCR1_FMC2EN;
>
> - writel(bcr1, fmc2->io_base + FMC2_BCR1);
> - writel(pcr, fmc2->io_base + FMC2_PCR);
> - writel(FMC2_PMEM_DEFAULT, fmc2->io_base + FMC2_PMEM);
> - writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
> + writel(bcr1, nfc->io_base + FMC2_BCR1);
> + writel(pcr, nfc->io_base + FMC2_PCR);
> + writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
> + writel(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);
> }
>
> -static void stm32_fmc2_calc_timings(struct nand_chip *chip,
> - const struct nand_sdr_timings *sdrt)
> +static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip,
> + const struct nand_sdr_timings *sdrt)
> {
> - struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
> + struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
> struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
> struct stm32_fmc2_timings *tims = &nand->timings;
> - unsigned long hclk = clk_get_rate(&fmc2->clk);
> + unsigned long hclk = clk_get_rate(&nfc->clk);
> unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
> unsigned long timing, tar, tclr, thiz, twait;
> unsigned long tset_mem, tset_att, thold_mem, thold_att;
> @@ -739,29 +740,28 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
> tims->thold_att = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
> }
>
> -static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr,
> - const struct nand_data_interface *conf)
> +static int stm32_fmc2_nfc_setup_interface(struct mtd_info *mtd, int chipnr,
> + const struct nand_data_interface *cf)
> {
> struct nand_chip *chip = mtd_to_nand(mtd);
> const struct nand_sdr_timings *sdrt;
>
> - sdrt = nand_get_sdr_timings(conf);
> + sdrt = nand_get_sdr_timings(cf);
> if (IS_ERR(sdrt))
> return PTR_ERR(sdrt);
>
> if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
> return 0;
>
> - stm32_fmc2_calc_timings(chip, sdrt);
> -
> - stm32_fmc2_timings_init(chip);
> + stm32_fmc2_nfc_calc_timings(chip, sdrt);
> + stm32_fmc2_nfc_timings_init(chip);
>
> return 0;
> }
>
> -static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
> +static void stm32_fmc2_nfc_nand_callbacks_setup(struct nand_chip *chip)
> {
> - chip->ecc.hwctl = stm32_fmc2_hwctl;
> + chip->ecc.hwctl = stm32_fmc2_nfc_hwctl;
>
> /*
> * Specific callbacks to read/write a page depending on
> @@ -769,17 +769,17 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
> */
> if (chip->ecc.strength == FMC2_ECC_HAM) {
> /* Hamming is used */
> - chip->ecc.calculate = stm32_fmc2_ham_calculate;
> - chip->ecc.correct = stm32_fmc2_ham_correct;
> + chip->ecc.calculate = stm32_fmc2_nfc_ham_calculate;
> + chip->ecc.correct = stm32_fmc2_nfc_ham_correct;
> chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 4 : 3;
> chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK;
> return;
> }
>
> /* BCH is used */
> - chip->ecc.read_page = stm32_fmc2_read_page;
> - chip->ecc.calculate = stm32_fmc2_bch_calculate;
> - chip->ecc.correct = stm32_fmc2_bch_correct;
> + chip->ecc.read_page = stm32_fmc2_nfc_read_page;
> + chip->ecc.calculate = stm32_fmc2_nfc_bch_calculate;
> + chip->ecc.correct = stm32_fmc2_nfc_bch_correct;
>
> if (chip->ecc.strength == FMC2_ECC_BCH8)
> chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 14 : 13;
> @@ -787,7 +787,7 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
> chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
> }
>
> -static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
> +static int stm32_fmc2_nfc_calc_ecc_bytes(int step_size, int strength)
> {
> /* Hamming */
> if (strength == FMC2_ECC_HAM)
> @@ -801,14 +801,13 @@ static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
> return 8;
> }
>
> -NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
> +NAND_ECC_CAPS_SINGLE(stm32_fmc2_nfc_ecc_caps, stm32_fmc2_nfc_calc_ecc_bytes,
> FMC2_ECC_STEP_SIZE,
> FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
>
> -static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
> - ofnode node)
> +static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, ofnode node)
> {
> - struct stm32_fmc2_nand *nand = &fmc2->nand;
> + struct stm32_fmc2_nand *nand = &nfc->nand;
> u32 cs[FMC2_MAX_CE];
> int ret, i;
>
> @@ -834,13 +833,13 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
> return -EINVAL;
> }
>
> - if (fmc2->cs_assigned & BIT(cs[i])) {
> + if (nfc->cs_assigned & BIT(cs[i])) {
> pr_err("Cs already assigned: %d\n",
> nand->cs_used[i]);
> return -EINVAL;
> }
>
> - fmc2->cs_assigned |= BIT(cs[i]);
> + nfc->cs_assigned |= BIT(cs[i]);
> nand->cs_used[i] = cs[i];
> }
>
> @@ -849,8 +848,8 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
> return 0;
> }
>
> -static int stm32_fmc2_parse_dt(struct udevice *dev,
> - struct stm32_fmc2_nfc *fmc2)
> +static int stm32_fmc2_nfc_parse_dt(struct udevice *dev,
> + struct stm32_fmc2_nfc *nfc)
> {
> ofnode child;
> int ret, nchips = 0;
> @@ -869,7 +868,7 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
> }
>
> dev_for_each_subnode(child, dev) {
> - ret = stm32_fmc2_parse_child(fmc2, child);
> + ret = stm32_fmc2_nfc_parse_child(nfc, child);
> if (ret)
> return ret;
> }
> @@ -877,10 +876,10 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
> return 0;
> }
>
> -static int stm32_fmc2_probe(struct udevice *dev)
> +static int stm32_fmc2_nfc_probe(struct udevice *dev)
> {
> - struct stm32_fmc2_nfc *fmc2 = dev_get_priv(dev);
> - struct stm32_fmc2_nand *nand = &fmc2->nand;
> + struct stm32_fmc2_nfc *nfc = dev_get_priv(dev);
> + struct stm32_fmc2_nand *nand = &nfc->nand;
> struct nand_chip *chip = &nand->chip;
> struct mtd_info *mtd = &chip->mtd;
> struct nand_ecclayout *ecclayout;
> @@ -889,10 +888,10 @@ static int stm32_fmc2_probe(struct udevice *dev)
> int oob_index, chip_cs, mem_region, ret;
> unsigned int i;
>
> - spin_lock_init(&fmc2->controller.lock);
> - init_waitqueue_head(&fmc2->controller.wq);
> + spin_lock_init(&nfc->controller.lock);
> + init_waitqueue_head(&nfc->controller.wq);
>
> - ret = stm32_fmc2_parse_dt(dev, fmc2);
> + ret = stm32_fmc2_nfc_parse_dt(dev, nfc);
> if (ret)
> return ret;
>
> @@ -902,11 +901,11 @@ static int stm32_fmc2_probe(struct udevice *dev)
> pr_err("Resource io_base not found");
> return ret;
> }
> - fmc2->io_base = (void __iomem *)resource.start;
> + nfc->io_base = (void __iomem *)resource.start;
>
> for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
> chip_cs++, mem_region += 3) {
> - if (!(fmc2->cs_assigned & BIT(chip_cs)))
> + if (!(nfc->cs_assigned & BIT(chip_cs)))
> continue;
>
> ret = dev_read_resource(dev, mem_region, &resource);
> @@ -915,7 +914,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
> chip_cs);
> return ret;
> }
> - fmc2->data_base[chip_cs] = (void __iomem *)resource.start;
> + nfc->data_base[chip_cs] = (void __iomem *)resource.start;
>
> ret = dev_read_resource(dev, mem_region + 1, &resource);
> if (ret) {
> @@ -923,7 +922,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
> chip_cs);
> return ret;
> }
> - fmc2->cmd_base[chip_cs] = (void __iomem *)resource.start;
> + nfc->cmd_base[chip_cs] = (void __iomem *)resource.start;
>
> ret = dev_read_resource(dev, mem_region + 2, &resource);
> if (ret) {
> @@ -931,15 +930,15 @@ static int stm32_fmc2_probe(struct udevice *dev)
> chip_cs);
> return ret;
> }
> - fmc2->addr_base[chip_cs] = (void __iomem *)resource.start;
> + nfc->addr_base[chip_cs] = (void __iomem *)resource.start;
> }
>
> /* Enable the clock */
> - ret = clk_get_by_index(dev, 0, &fmc2->clk);
> + ret = clk_get_by_index(dev, 0, &nfc->clk);
> if (ret)
> return ret;
>
> - ret = clk_enable(&fmc2->clk);
> + ret = clk_enable(&nfc->clk);
> if (ret)
> return ret;
>
> @@ -951,12 +950,12 @@ static int stm32_fmc2_probe(struct udevice *dev)
> reset_deassert(&reset);
> }
>
> - stm32_fmc2_init(fmc2);
> + stm32_fmc2_nfc_init(nfc);
>
> - chip->controller = &fmc2->base;
> - chip->select_chip = stm32_fmc2_select_chip;
> - chip->setup_data_interface = stm32_fmc2_setup_interface;
> - chip->cmd_ctrl = stm32_fmc2_cmd_ctrl;
> + chip->controller = &nfc->base;
> + chip->select_chip = stm32_fmc2_nfc_select_chip;
> + chip->setup_data_interface = stm32_fmc2_nfc_setup_interface;
> + chip->cmd_ctrl = stm32_fmc2_nfc_cmd_ctrl;
> chip->chip_delay = FMC2_RB_DELAY_US;
> chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE |
> NAND_USE_BOUNCE_BUFFER;
> @@ -982,7 +981,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
> return -EINVAL;
> }
>
> - ret = nand_check_ecc_caps(chip, &stm32_fmc2_ecc_caps,
> + ret = nand_check_ecc_caps(chip, &stm32_fmc2_nfc_ecc_caps,
> mtd->oobsize - FMC2_BBM_LEN);
> if (ret) {
> pr_err("No valid ECC settings set\n");
> @@ -992,10 +991,10 @@ static int stm32_fmc2_probe(struct udevice *dev)
> if (chip->bbt_options & NAND_BBT_USE_FLASH)
> chip->bbt_options |= NAND_BBT_NO_OOB;
>
> - stm32_fmc2_nand_callbacks_setup(chip);
> + stm32_fmc2_nfc_nand_callbacks_setup(chip);
>
> /* Define ECC layout */
> - ecclayout = &fmc2->ecclayout;
> + ecclayout = &nfc->ecclayout;
> ecclayout->eccbytes = chip->ecc.bytes *
> (mtd->writesize / chip->ecc.size);
> oob_index = FMC2_BBM_LEN;
> @@ -1006,7 +1005,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
> chip->ecc.layout = ecclayout;
>
> if (chip->options & NAND_BUSWIDTH_16)
> - stm32_fmc2_set_buswidth_16(fmc2, true);
> + stm32_fmc2_nfc_set_buswidth_16(nfc, true);
>
> ret = nand_scan_tail(mtd);
> if (ret)
> @@ -1015,16 +1014,16 @@ static int stm32_fmc2_probe(struct udevice *dev)
> return nand_register(0, mtd);
> }
>
> -static const struct udevice_id stm32_fmc2_match[] = {
> +static const struct udevice_id stm32_fmc2_nfc_match[] = {
> { .compatible = "st,stm32mp15-fmc2" },
> { /* Sentinel */ }
> };
>
> -U_BOOT_DRIVER(stm32_fmc2_nand) = {
> - .name = "stm32_fmc2_nand",
> +U_BOOT_DRIVER(stm32_fmc2_nfc) = {
> + .name = "stm32_fmc2_nfc",
> .id = UCLASS_MTD,
> - .of_match = stm32_fmc2_match,
> - .probe = stm32_fmc2_probe,
> + .of_match = stm32_fmc2_nfc_match,
> + .probe = stm32_fmc2_nfc_probe,
> .priv_auto_alloc_size = sizeof(struct stm32_fmc2_nfc),
> };
>
> @@ -1034,9 +1033,9 @@ void board_nand_init(void)
> int ret;
>
> ret = uclass_get_device_by_driver(UCLASS_MTD,
> - DM_GET_DRIVER(stm32_fmc2_nand),
> + DM_GET_DRIVER(stm32_fmc2_nfc),
> &dev);
> if (ret && ret != -ENODEV)
> - pr_err("Failed to initialize STM32 FMC2 NAND controller. (error %d)\n",
> + pr_err("Failed to initialize STM32 FMC2 NFC controller. (error %d)\n",
> ret);
> }
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 03/11] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_5S for timeouts
2020-08-13 7:29 ` Patrice CHOTARD
@ 2020-08-13 9:57 ` Patrice CHOTARD
0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 9:57 UTC (permalink / raw)
To: u-boot
On 8/13/20 9:29 AM, Patrice CHOTARD wrote:
> Hi Christophe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> FMC2_TIMEOUT_5S will be used each time that we need to wait.
>> It was seen, during stress tests in an overloaded system,
>> that we could be close to 1 second, even if we never met this
>> value. To be safe, FMC2_TIMEOUT_MS is set to 5 seconds.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>> drivers/mtd/nand/raw/stm32_fmc2_nand.c | 8 +++++---
>> 1 file changed, 5 insertions(+), 3 deletions(-)
Applied on u-boot-stm/master
Thanks
>>
>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> index f43e3ec..2e947a3 100644
>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> @@ -131,6 +131,8 @@
>>
>> #define FMC2_NSEC_PER_SEC 1000000000L
>>
>> +#define FMC2_TIMEOUT_5S 5000000
>> +
>> enum stm32_fmc2_ecc {
>> FMC2_ECC_HAM = 1,
>> FMC2_ECC_BCH4 = 4,
>> @@ -339,7 +341,7 @@ static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
>> int ret;
>>
>> ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr,
>> - sr & FMC2_SR_NWRF, 10000);
>> + sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
>> if (ret < 0) {
>> pr_err("Ham timeout\n");
>> return ret;
>> @@ -424,7 +426,7 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
>>
>> /* Wait until the BCH code is ready */
>> ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
>> - bchisr & FMC2_BCHISR_EPBRF, 10000);
>> + bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
>> if (ret < 0) {
>> pr_err("Bch timeout\n");
>> return ret;
>> @@ -472,7 +474,7 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
>>
>> /* Wait until the decoding error is ready */
>> ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
>> - bchisr & FMC2_BCHISR_DERF, 10000);
>> + bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
>> if (ret < 0) {
>> pr_err("Bch timeout\n");
>> return ret;
> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
>
> Thanks
>
> Patrice
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 05/11] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros
2020-08-13 7:29 ` Patrice CHOTARD
@ 2020-08-13 9:58 ` Patrice CHOTARD
0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 9:58 UTC (permalink / raw)
To: u-boot
On 8/13/20 9:29 AM, Patrice CHOTARD wrote:
> Hi Christophe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> This patch removes custom macros and uses FIELD_PREP and FIELD_GET macros.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>> drivers/mtd/nand/raw/stm32_fmc2_nand.c | 120 +++++++++++++++------------------
>> 1 file changed, 56 insertions(+), 64 deletions(-)
Applied on u-boot-stm/master
Thanks
>>
>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> index 9718bae..eba1ded 100644
>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> @@ -10,6 +10,7 @@
>> #include <log.h>
>> #include <nand.h>
>> #include <reset.h>
>> +#include <linux/bitfield.h>
>> #include <linux/bitops.h>
>> #include <linux/delay.h>
>> #include <linux/err.h>
>> @@ -60,20 +61,16 @@
>> /* Register: FMC2_PCR */
>> #define FMC2_PCR_PWAITEN BIT(1)
>> #define FMC2_PCR_PBKEN BIT(2)
>> -#define FMC2_PCR_PWID_MASK GENMASK(5, 4)
>> -#define FMC2_PCR_PWID(x) (((x) & 0x3) << 4)
>> +#define FMC2_PCR_PWID GENMASK(5, 4)
>> #define FMC2_PCR_PWID_BUSWIDTH_8 0
>> #define FMC2_PCR_PWID_BUSWIDTH_16 1
>> #define FMC2_PCR_ECCEN BIT(6)
>> #define FMC2_PCR_ECCALG BIT(8)
>> -#define FMC2_PCR_TCLR_MASK GENMASK(12, 9)
>> -#define FMC2_PCR_TCLR(x) (((x) & 0xf) << 9)
>> +#define FMC2_PCR_TCLR GENMASK(12, 9)
>> #define FMC2_PCR_TCLR_DEFAULT 0xf
>> -#define FMC2_PCR_TAR_MASK GENMASK(16, 13)
>> -#define FMC2_PCR_TAR(x) (((x) & 0xf) << 13)
>> +#define FMC2_PCR_TAR GENMASK(16, 13)
>> #define FMC2_PCR_TAR_DEFAULT 0xf
>> -#define FMC2_PCR_ECCSS_MASK GENMASK(19, 17)
>> -#define FMC2_PCR_ECCSS(x) (((x) & 0x7) << 17)
>> +#define FMC2_PCR_ECCSS GENMASK(19, 17)
>> #define FMC2_PCR_ECCSS_512 1
>> #define FMC2_PCR_ECCSS_2048 3
>> #define FMC2_PCR_BCHECC BIT(24)
>> @@ -83,17 +80,17 @@
>> #define FMC2_SR_NWRF BIT(6)
>>
>> /* Register: FMC2_PMEM */
>> -#define FMC2_PMEM_MEMSET(x) (((x) & 0xff) << 0)
>> -#define FMC2_PMEM_MEMWAIT(x) (((x) & 0xff) << 8)
>> -#define FMC2_PMEM_MEMHOLD(x) (((x) & 0xff) << 16)
>> -#define FMC2_PMEM_MEMHIZ(x) (((x) & 0xff) << 24)
>> +#define FMC2_PMEM_MEMSET GENMASK(7, 0)
>> +#define FMC2_PMEM_MEMWAIT GENMASK(15, 8)
>> +#define FMC2_PMEM_MEMHOLD GENMASK(23, 16)
>> +#define FMC2_PMEM_MEMHIZ GENMASK(31, 24)
>> #define FMC2_PMEM_DEFAULT 0x0a0a0a0a
>>
>> /* Register: FMC2_PATT */
>> -#define FMC2_PATT_ATTSET(x) (((x) & 0xff) << 0)
>> -#define FMC2_PATT_ATTWAIT(x) (((x) & 0xff) << 8)
>> -#define FMC2_PATT_ATTHOLD(x) (((x) & 0xff) << 16)
>> -#define FMC2_PATT_ATTHIZ(x) (((x) & 0xff) << 24)
>> +#define FMC2_PATT_ATTSET GENMASK(7, 0)
>> +#define FMC2_PATT_ATTWAIT GENMASK(15, 8)
>> +#define FMC2_PATT_ATTHOLD GENMASK(23, 16)
>> +#define FMC2_PATT_ATTHIZ GENMASK(31, 24)
>> #define FMC2_PATT_DEFAULT 0x0a0a0a0a
>>
>> /* Register: FMC2_BCHISR */
>> @@ -106,28 +103,23 @@
>> /* Register: FMC2_BCHDSR0 */
>> #define FMC2_BCHDSR0_DUE BIT(0)
>> #define FMC2_BCHDSR0_DEF BIT(1)
>> -#define FMC2_BCHDSR0_DEN_MASK GENMASK(7, 4)
>> -#define FMC2_BCHDSR0_DEN_SHIFT 4
>> +#define FMC2_BCHDSR0_DEN GENMASK(7, 4)
>>
>> /* Register: FMC2_BCHDSR1 */
>> -#define FMC2_BCHDSR1_EBP1_MASK GENMASK(12, 0)
>> -#define FMC2_BCHDSR1_EBP2_MASK GENMASK(28, 16)
>> -#define FMC2_BCHDSR1_EBP2_SHIFT 16
>> +#define FMC2_BCHDSR1_EBP1 GENMASK(12, 0)
>> +#define FMC2_BCHDSR1_EBP2 GENMASK(28, 16)
>>
>> /* Register: FMC2_BCHDSR2 */
>> -#define FMC2_BCHDSR2_EBP3_MASK GENMASK(12, 0)
>> -#define FMC2_BCHDSR2_EBP4_MASK GENMASK(28, 16)
>> -#define FMC2_BCHDSR2_EBP4_SHIFT 16
>> +#define FMC2_BCHDSR2_EBP3 GENMASK(12, 0)
>> +#define FMC2_BCHDSR2_EBP4 GENMASK(28, 16)
>>
>> /* Register: FMC2_BCHDSR3 */
>> -#define FMC2_BCHDSR3_EBP5_MASK GENMASK(12, 0)
>> -#define FMC2_BCHDSR3_EBP6_MASK GENMASK(28, 16)
>> -#define FMC2_BCHDSR3_EBP6_SHIFT 16
>> +#define FMC2_BCHDSR3_EBP5 GENMASK(12, 0)
>> +#define FMC2_BCHDSR3_EBP6 GENMASK(28, 16)
>>
>> /* Register: FMC2_BCHDSR4 */
>> -#define FMC2_BCHDSR4_EBP7_MASK GENMASK(12, 0)
>> -#define FMC2_BCHDSR4_EBP8_MASK GENMASK(28, 16)
>> -#define FMC2_BCHDSR4_EBP8_SHIFT 16
>> +#define FMC2_BCHDSR4_EBP7 GENMASK(12, 0)
>> +#define FMC2_BCHDSR4_EBP8 GENMASK(28, 16)
>>
>> #define FMC2_NSEC_PER_SEC 1000000000L
>>
>> @@ -190,22 +182,22 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
>> u32 pmem, patt;
>>
>> /* Set tclr/tar timings */
>> - pcr &= ~FMC2_PCR_TCLR_MASK;
>> - pcr |= FMC2_PCR_TCLR(timings->tclr);
>> - pcr &= ~FMC2_PCR_TAR_MASK;
>> - pcr |= FMC2_PCR_TAR(timings->tar);
>> + pcr &= ~FMC2_PCR_TCLR;
>> + pcr |= FIELD_PREP(FMC2_PCR_TCLR, timings->tclr);
>> + pcr &= ~FMC2_PCR_TAR;
>> + pcr |= FIELD_PREP(FMC2_PCR_TAR, timings->tar);
>>
>> /* Set tset/twait/thold/thiz timings in common bank */
>> - pmem = FMC2_PMEM_MEMSET(timings->tset_mem);
>> - pmem |= FMC2_PMEM_MEMWAIT(timings->twait);
>> - pmem |= FMC2_PMEM_MEMHOLD(timings->thold_mem);
>> - pmem |= FMC2_PMEM_MEMHIZ(timings->thiz);
>> + pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
>> + pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
>> + pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
>> + pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
>>
>> /* Set tset/twait/thold/thiz timings in attribut bank */
>> - patt = FMC2_PATT_ATTSET(timings->tset_att);
>> - patt |= FMC2_PATT_ATTWAIT(timings->twait);
>> - patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
>> - patt |= FMC2_PATT_ATTHIZ(timings->thiz);
>> + patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
>> + patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
>> + patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
>> + patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
>>
>> writel(pcr, nfc->io_base + FMC2_PCR);
>> writel(pmem, nfc->io_base + FMC2_PMEM);
>> @@ -228,13 +220,13 @@ static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
>> }
>>
>> /* Set buswidth */
>> - pcr &= ~FMC2_PCR_PWID_MASK;
>> + pcr &= ~FMC2_PCR_PWID;
>> if (chip->options & NAND_BUSWIDTH_16)
>> - pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
>> + pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
>>
>> /* Set ECC sector size */
>> - pcr &= ~FMC2_PCR_ECCSS_MASK;
>> - pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
>> + pcr &= ~FMC2_PCR_ECCSS;
>> + pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
>>
>> writel(pcr, nfc->io_base + FMC2_PCR);
>> }
>> @@ -264,9 +256,9 @@ static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
>> {
>> u32 pcr = readl(nfc->io_base + FMC2_PCR);
>>
>> - pcr &= ~FMC2_PCR_PWID_MASK;
>> + pcr &= ~FMC2_PCR_PWID;
>> if (set)
>> - pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
>> + pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
>> writel(pcr, nfc->io_base + FMC2_PCR);
>> }
>>
>> @@ -497,16 +489,16 @@ static int stm32_fmc2_nfc_bch_correct(struct mtd_info *mtd, u8 *dat,
>> if (unlikely(bchdsr0 & FMC2_BCHDSR0_DUE))
>> return -EBADMSG;
>>
>> - pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK;
>> - pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT;
>> - pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK;
>> - pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT;
>> - pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK;
>> - pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT;
>> - pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK;
>> - pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT;
>> + pos[0] = FIELD_GET(FMC2_BCHDSR1_EBP1, bchdsr1);
>> + pos[1] = FIELD_GET(FMC2_BCHDSR1_EBP2, bchdsr1);
>> + pos[2] = FIELD_GET(FMC2_BCHDSR2_EBP3, bchdsr2);
>> + pos[3] = FIELD_GET(FMC2_BCHDSR2_EBP4, bchdsr2);
>> + pos[4] = FIELD_GET(FMC2_BCHDSR3_EBP5, bchdsr3);
>> + pos[5] = FIELD_GET(FMC2_BCHDSR3_EBP6, bchdsr3);
>> + pos[6] = FIELD_GET(FMC2_BCHDSR4_EBP7, bchdsr4);
>> + pos[7] = FIELD_GET(FMC2_BCHDSR4_EBP8, bchdsr4);
>>
>> - den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT;
>> + den = FIELD_GET(FMC2_BCHDSR0_DEN, bchdsr0);
>> for (i = 0; i < den; i++) {
>> if (pos[i] < eccsize * 8) {
>> __change_bit(pos[i], (unsigned long *)dat);
>> @@ -581,7 +573,7 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>> pcr |= FMC2_PCR_PBKEN;
>>
>> /* Set buswidth to 8 bits mode for identification */
>> - pcr &= ~FMC2_PCR_PWID_MASK;
>> + pcr &= ~FMC2_PCR_PWID;
>>
>> /* ECC logic is disabled */
>> pcr &= ~FMC2_PCR_ECCEN;
>> @@ -592,14 +584,14 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>> pcr &= ~FMC2_PCR_WEN;
>>
>> /* Set default ECC sector size */
>> - pcr &= ~FMC2_PCR_ECCSS_MASK;
>> - pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048);
>> + pcr &= ~FMC2_PCR_ECCSS;
>> + pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_2048);
>>
>> /* Set default tclr/tar timings */
>> - pcr &= ~FMC2_PCR_TCLR_MASK;
>> - pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT);
>> - pcr &= ~FMC2_PCR_TAR_MASK;
>> - pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT);
>> + pcr &= ~FMC2_PCR_TCLR;
>> + pcr |= FIELD_PREP(FMC2_PCR_TCLR, FMC2_PCR_TCLR_DEFAULT);
>> + pcr &= ~FMC2_PCR_TAR;
>> + pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
>>
>> /* Enable FMC2 controller */
>> bcr1 |= FMC2_BCR1_FMC2EN;
> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
>
> Thanks
>
> Patrice
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 06/11] mtd: rawnand: stm32_fmc2: use clrsetbits_le32
2020-08-13 7:30 ` Patrice CHOTARD
@ 2020-08-13 9:58 ` Patrice CHOTARD
0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 9:58 UTC (permalink / raw)
To: u-boot
On 8/13/20 9:30 AM, Patrice CHOTARD wrote:
> Hi Christophe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> This patch uses clrsetbits_le32 function instead of multiple instructions.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>> drivers/mtd/nand/raw/stm32_fmc2_nand.c | 56 +++++++++++++---------------------
>> 1 file changed, 21 insertions(+), 35 deletions(-)
Applied on u-boot-stm/master
Thanks
>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> index eba1ded..1e4d757 100644
>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> @@ -178,40 +178,37 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
>> struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>> struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
>> struct stm32_fmc2_timings *timings = &nand->timings;
>> - u32 pcr = readl(nfc->io_base + FMC2_PCR);
>> u32 pmem, patt;
>>
>> /* Set tclr/tar timings */
>> - pcr &= ~FMC2_PCR_TCLR;
>> - pcr |= FIELD_PREP(FMC2_PCR_TCLR, timings->tclr);
>> - pcr &= ~FMC2_PCR_TAR;
>> - pcr |= FIELD_PREP(FMC2_PCR_TAR, timings->tar);
>> + clrsetbits_le32(nfc->io_base + FMC2_PCR,
>> + FMC2_PCR_TCLR | FMC2_PCR_TAR,
>> + FIELD_PREP(FMC2_PCR_TCLR, timings->tclr) |
>> + FIELD_PREP(FMC2_PCR_TAR, timings->tar));
>>
>> /* Set tset/twait/thold/thiz timings in common bank */
>> pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
>> pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
>> pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
>> pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
>> + writel(pmem, nfc->io_base + FMC2_PMEM);
>>
>> /* Set tset/twait/thold/thiz timings in attribut bank */
>> patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
>> patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
>> patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
>> patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
>> -
>> - writel(pcr, nfc->io_base + FMC2_PCR);
>> - writel(pmem, nfc->io_base + FMC2_PMEM);
>> writel(patt, nfc->io_base + FMC2_PATT);
>> }
>>
>> static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
>> {
>> struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
>> - u32 pcr = readl(nfc->io_base + FMC2_PCR);
>> + u32 pcr = 0, pcr_mask;
>>
>> /* Configure ECC algorithm (default configuration is Hamming) */
>> - pcr &= ~FMC2_PCR_ECCALG;
>> - pcr &= ~FMC2_PCR_BCHECC;
>> + pcr_mask = FMC2_PCR_ECCALG;
>> + pcr_mask |= FMC2_PCR_BCHECC;
>> if (chip->ecc.strength == FMC2_ECC_BCH8) {
>> pcr |= FMC2_PCR_ECCALG;
>> pcr |= FMC2_PCR_BCHECC;
>> @@ -220,15 +217,15 @@ static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
>> }
>>
>> /* Set buswidth */
>> - pcr &= ~FMC2_PCR_PWID;
>> + pcr_mask |= FMC2_PCR_PWID;
>> if (chip->options & NAND_BUSWIDTH_16)
>> pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
>>
>> /* Set ECC sector size */
>> - pcr &= ~FMC2_PCR_ECCSS;
>> + pcr_mask |= FMC2_PCR_ECCSS;
>> pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
>>
>> - writel(pcr, nfc->io_base + FMC2_PCR);
>> + clrsetbits_le32(nfc->io_base + FMC2_PCR, pcr_mask, pcr);
>> }
>>
>> static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
>> @@ -254,22 +251,18 @@ static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
>> static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
>> bool set)
>> {
>> - u32 pcr = readl(nfc->io_base + FMC2_PCR);
>> + u32 pcr;
>>
>> - pcr &= ~FMC2_PCR_PWID;
>> - if (set)
>> - pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
>> - writel(pcr, nfc->io_base + FMC2_PCR);
>> + pcr = set ? FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16) :
>> + FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_8);
>> +
>> + clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_PWID, pcr);
>> }
>>
>> static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
>> {
>> - u32 pcr = readl(nfc->io_base + FMC2_PCR);
>> -
>> - pcr &= ~FMC2_PCR_ECCEN;
>> - if (enable)
>> - pcr |= FMC2_PCR_ECCEN;
>> - writel(pcr, nfc->io_base + FMC2_PCR);
>> + clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_ECCEN,
>> + enable ? FMC2_PCR_ECCEN : 0);
>> }
>>
>> static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
>> @@ -306,13 +299,8 @@ static void stm32_fmc2_nfc_hwctl(struct mtd_info *mtd, int mode)
>> stm32_fmc2_nfc_set_ecc(nfc, false);
>>
>> if (chip->ecc.strength != FMC2_ECC_HAM) {
>> - u32 pcr = readl(nfc->io_base + FMC2_PCR);
>> -
>> - if (mode == NAND_ECC_WRITE)
>> - pcr |= FMC2_PCR_WEN;
>> - else
>> - pcr &= ~FMC2_PCR_WEN;
>> - writel(pcr, nfc->io_base + FMC2_PCR);
>> + clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_WEN,
>> + mode == NAND_ECC_WRITE ? FMC2_PCR_WEN : 0);
>>
>> stm32_fmc2_nfc_clear_bch_irq(nfc);
>> }
>> @@ -563,7 +551,6 @@ static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
>> static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>> {
>> u32 pcr = readl(nfc->io_base + FMC2_PCR);
>> - u32 bcr1 = readl(nfc->io_base + FMC2_BCR1);
>>
>> /* Set CS used to undefined */
>> nfc->cs_sel = -1;
>> @@ -594,9 +581,8 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>> pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
>>
>> /* Enable FMC2 controller */
>> - bcr1 |= FMC2_BCR1_FMC2EN;
>> + setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
>>
>> - writel(bcr1, nfc->io_base + FMC2_BCR1);
>> writel(pcr, nfc->io_base + FMC2_PCR);
>> writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
>> writel(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);
> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
>
> Thanks
>
> Patrice
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 07/11] memory: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver
2020-08-13 7:31 ` Patrice CHOTARD
@ 2020-08-13 9:58 ` Patrice CHOTARD
0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 9:58 UTC (permalink / raw)
To: u-boot
On 8/13/20 9:31 AM, Patrice CHOTARD wrote:
> Hi Christophe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> The driver adds the support for the STMicroelectronics FMC2 EBI controller
>> found on STM32MP SOCs.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>> drivers/memory/Kconfig | 9 +
>> drivers/memory/Makefile | 1 +
>> drivers/memory/stm32-fmc2-ebi.c | 1056 +++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 1066 insertions(+)
>> create mode 100644 drivers/memory/stm32-fmc2-ebi.c
Applied on u-boot-stm/master
Thanks
>>
>> diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
>> index 4fbb5aa..7271892 100644
>> --- a/drivers/memory/Kconfig
>> +++ b/drivers/memory/Kconfig
>> @@ -4,6 +4,15 @@
>>
>> menu "Memory Controller drivers"
>>
>> +config STM32_FMC2_EBI
>> + bool "Support for FMC2 External Bus Interface on STM32MP SoCs"
>> + depends on ARCH_STM32MP
>> + help
>> + Select this option to enable the STM32 FMC2 External Bus Interface
>> + controller. This driver configures the transactions with external
>> + devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on
>> + SOCs containing the FMC2 External Bus Interface.
>> +
>> config TI_AEMIF
>> tristate "Texas Instruments AEMIF driver"
>> depends on ARCH_KEYSTONE
>> diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
>> index 238add0..fec52ef 100644
>> --- a/drivers/memory/Makefile
>> +++ b/drivers/memory/Makefile
>> @@ -1,2 +1,3 @@
>>
>> +obj-$(CONFIG_STM32_FMC2_EBI) += stm32-fmc2-ebi.o
>> obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
>> diff --git a/drivers/memory/stm32-fmc2-ebi.c b/drivers/memory/stm32-fmc2-ebi.c
>> new file mode 100644
>> index 0000000..d887a1e
>> --- /dev/null
>> +++ b/drivers/memory/stm32-fmc2-ebi.c
>> @@ -0,0 +1,1056 @@
>> +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
>> +/*
>> + * Copyright (C) STMicroelectronics 2020
>> + */
>> +
>> +#include <common.h>
>> +#include <clk.h>
>> +#include <dm.h>
>> +#include <reset.h>
>> +#include <linux/bitfield.h>
>> +#include <linux/err.h>
>> +#include <linux/iopoll.h>
>> +#include <linux/ioport.h>
>> +
>> +/* FMC2 Controller Registers */
>> +#define FMC2_BCR1 0x0
>> +#define FMC2_BTR1 0x4
>> +#define FMC2_BCR(x) ((x) * 0x8 + FMC2_BCR1)
>> +#define FMC2_BTR(x) ((x) * 0x8 + FMC2_BTR1)
>> +#define FMC2_PCSCNTR 0x20
>> +#define FMC2_BWTR1 0x104
>> +#define FMC2_BWTR(x) ((x) * 0x8 + FMC2_BWTR1)
>> +
>> +/* Register: FMC2_BCR1 */
>> +#define FMC2_BCR1_CCLKEN BIT(20)
>> +#define FMC2_BCR1_FMC2EN BIT(31)
>> +
>> +/* Register: FMC2_BCRx */
>> +#define FMC2_BCR_MBKEN BIT(0)
>> +#define FMC2_BCR_MUXEN BIT(1)
>> +#define FMC2_BCR_MTYP GENMASK(3, 2)
>> +#define FMC2_BCR_MWID GENMASK(5, 4)
>> +#define FMC2_BCR_FACCEN BIT(6)
>> +#define FMC2_BCR_BURSTEN BIT(8)
>> +#define FMC2_BCR_WAITPOL BIT(9)
>> +#define FMC2_BCR_WAITCFG BIT(11)
>> +#define FMC2_BCR_WREN BIT(12)
>> +#define FMC2_BCR_WAITEN BIT(13)
>> +#define FMC2_BCR_EXTMOD BIT(14)
>> +#define FMC2_BCR_ASYNCWAIT BIT(15)
>> +#define FMC2_BCR_CPSIZE GENMASK(18, 16)
>> +#define FMC2_BCR_CBURSTRW BIT(19)
>> +#define FMC2_BCR_NBLSET GENMASK(23, 22)
>> +
>> +/* Register: FMC2_BTRx/FMC2_BWTRx */
>> +#define FMC2_BXTR_ADDSET GENMASK(3, 0)
>> +#define FMC2_BXTR_ADDHLD GENMASK(7, 4)
>> +#define FMC2_BXTR_DATAST GENMASK(15, 8)
>> +#define FMC2_BXTR_BUSTURN GENMASK(19, 16)
>> +#define FMC2_BTR_CLKDIV GENMASK(23, 20)
>> +#define FMC2_BTR_DATLAT GENMASK(27, 24)
>> +#define FMC2_BXTR_ACCMOD GENMASK(29, 28)
>> +#define FMC2_BXTR_DATAHLD GENMASK(31, 30)
>> +
>> +/* Register: FMC2_PCSCNTR */
>> +#define FMC2_PCSCNTR_CSCOUNT GENMASK(15, 0)
>> +#define FMC2_PCSCNTR_CNTBEN(x) BIT((x) + 16)
>> +
>> +#define FMC2_MAX_EBI_CE 4
>> +#define FMC2_MAX_BANKS 5
>> +
>> +#define FMC2_BCR_CPSIZE_0 0x0
>> +#define FMC2_BCR_CPSIZE_128 0x1
>> +#define FMC2_BCR_CPSIZE_256 0x2
>> +#define FMC2_BCR_CPSIZE_512 0x3
>> +#define FMC2_BCR_CPSIZE_1024 0x4
>> +
>> +#define FMC2_BCR_MWID_8 0x0
>> +#define FMC2_BCR_MWID_16 0x1
>> +
>> +#define FMC2_BCR_MTYP_SRAM 0x0
>> +#define FMC2_BCR_MTYP_PSRAM 0x1
>> +#define FMC2_BCR_MTYP_NOR 0x2
>> +
>> +#define FMC2_BXTR_EXTMOD_A 0x0
>> +#define FMC2_BXTR_EXTMOD_B 0x1
>> +#define FMC2_BXTR_EXTMOD_C 0x2
>> +#define FMC2_BXTR_EXTMOD_D 0x3
>> +
>> +#define FMC2_BCR_NBLSET_MAX 0x3
>> +#define FMC2_BXTR_ADDSET_MAX 0xf
>> +#define FMC2_BXTR_ADDHLD_MAX 0xf
>> +#define FMC2_BXTR_DATAST_MAX 0xff
>> +#define FMC2_BXTR_BUSTURN_MAX 0xf
>> +#define FMC2_BXTR_DATAHLD_MAX 0x3
>> +#define FMC2_BTR_CLKDIV_MAX 0xf
>> +#define FMC2_BTR_DATLAT_MAX 0xf
>> +#define FMC2_PCSCNTR_CSCOUNT_MAX 0xff
>> +
>> +#define FMC2_NSEC_PER_SEC 1000000000L
>> +
>> +enum stm32_fmc2_ebi_bank {
>> + FMC2_EBI1 = 0,
>> + FMC2_EBI2,
>> + FMC2_EBI3,
>> + FMC2_EBI4,
>> + FMC2_NAND
>> +};
>> +
>> +enum stm32_fmc2_ebi_register_type {
>> + FMC2_REG_BCR = 1,
>> + FMC2_REG_BTR,
>> + FMC2_REG_BWTR,
>> + FMC2_REG_PCSCNTR
>> +};
>> +
>> +enum stm32_fmc2_ebi_transaction_type {
>> + FMC2_ASYNC_MODE_1_SRAM = 0,
>> + FMC2_ASYNC_MODE_1_PSRAM,
>> + FMC2_ASYNC_MODE_A_SRAM,
>> + FMC2_ASYNC_MODE_A_PSRAM,
>> + FMC2_ASYNC_MODE_2_NOR,
>> + FMC2_ASYNC_MODE_B_NOR,
>> + FMC2_ASYNC_MODE_C_NOR,
>> + FMC2_ASYNC_MODE_D_NOR,
>> + FMC2_SYNC_READ_SYNC_WRITE_PSRAM,
>> + FMC2_SYNC_READ_ASYNC_WRITE_PSRAM,
>> + FMC2_SYNC_READ_SYNC_WRITE_NOR,
>> + FMC2_SYNC_READ_ASYNC_WRITE_NOR
>> +};
>> +
>> +enum stm32_fmc2_ebi_buswidth {
>> + FMC2_BUSWIDTH_8 = 8,
>> + FMC2_BUSWIDTH_16 = 16
>> +};
>> +
>> +enum stm32_fmc2_ebi_cpsize {
>> + FMC2_CPSIZE_0 = 0,
>> + FMC2_CPSIZE_128 = 128,
>> + FMC2_CPSIZE_256 = 256,
>> + FMC2_CPSIZE_512 = 512,
>> + FMC2_CPSIZE_1024 = 1024
>> +};
>> +
>> +struct stm32_fmc2_ebi {
>> + struct clk clk;
>> + fdt_addr_t io_base;
>> + u8 bank_assigned;
>> +};
>> +
>> +/*
>> + * struct stm32_fmc2_prop - STM32 FMC2 EBI property
>> + * @name: the device tree binding name of the property
>> + * @bprop: indicate that it is a boolean property
>> + * @mprop: indicate that it is a mandatory property
>> + * @reg_type: the register that have to be modified
>> + * @reg_mask: the bit that have to be modified in the selected register
>> + * in case of it is a boolean property
>> + * @reset_val: the default value that have to be set in case the property
>> + * has not been defined in the device tree
>> + * @check: this callback ckecks that the property is compliant with the
>> + * transaction type selected
>> + * @calculate: this callback is called to calculate for exemple a timing
>> + * set in nanoseconds in the device tree in clock cycles or in
>> + * clock period
>> + * @set: this callback applies the values in the registers
>> + */
>> +struct stm32_fmc2_prop {
>> + const char *name;
>> + bool bprop;
>> + bool mprop;
>> + int reg_type;
>> + u32 reg_mask;
>> + u32 reset_val;
>> + int (*check)(struct stm32_fmc2_ebi *ebi,
>> + const struct stm32_fmc2_prop *prop, int cs);
>> + u32 (*calculate)(struct stm32_fmc2_ebi *ebi, int cs, u32 setup);
>> + int (*set)(struct stm32_fmc2_ebi *ebi,
>> + const struct stm32_fmc2_prop *prop,
>> + int cs, u32 setup);
>> +};
>> +
>> +static int stm32_fmc2_ebi_check_mux(struct stm32_fmc2_ebi *ebi,
>> + const struct stm32_fmc2_prop *prop,
>> + int cs)
>> +{
>> + u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
>> +
>> + if (bcr & FMC2_BCR_MTYP)
>> + return 0;
>> +
>> + return -EINVAL;
>> +}
>> +
>> +static int stm32_fmc2_ebi_check_waitcfg(struct stm32_fmc2_ebi *ebi,
>> + const struct stm32_fmc2_prop *prop,
>> + int cs)
>> +{
>> + u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
>> + u32 val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
>> +
>> + if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
>> + return 0;
>> +
>> + return -EINVAL;
>> +}
>> +
>> +static int stm32_fmc2_ebi_check_sync_trans(struct stm32_fmc2_ebi *ebi,
>> + const struct stm32_fmc2_prop *prop,
>> + int cs)
>> +{
>> + u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
>> +
>> + if (bcr & FMC2_BCR_BURSTEN)
>> + return 0;
>> +
>> + return -EINVAL;
>> +}
>> +
>> +static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2_ebi *ebi,
>> + const struct stm32_fmc2_prop *prop,
>> + int cs)
>> +{
>> + u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
>> +
>> + if (!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW))
>> + return 0;
>> +
>> + return -EINVAL;
>> +}
>> +
>> +static int stm32_fmc2_ebi_check_cpsize(struct stm32_fmc2_ebi *ebi,
>> + const struct stm32_fmc2_prop *prop,
>> + int cs)
>> +{
>> + u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
>> + u32 val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
>> +
>> + if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
>> + return 0;
>> +
>> + return -EINVAL;
>> +}
>> +
>> +static int stm32_fmc2_ebi_check_address_hold(struct stm32_fmc2_ebi *ebi,
>> + const struct stm32_fmc2_prop *prop,
>> + int cs)
>> +{
>> + u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
>> + u32 bxtr = prop->reg_type == FMC2_REG_BWTR ?
>> + readl(ebi->io_base + FMC2_BWTR(cs)) :
>> + readl(ebi->io_base + FMC2_BTR(cs));
>> + u32 val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
>> +
>> + if ((!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW)) &&
>> + ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN))
>> + return 0;
>> +
>> + return -EINVAL;
>> +}
>> +
>> +static int stm32_fmc2_ebi_check_clk_period(struct stm32_fmc2_ebi *ebi,
>> + const struct stm32_fmc2_prop *prop,
>> + int cs)
>> +{
>> + u32 bcr = readl(ebi->io_base + FMC2_BCR(cs));
>> + u32 bcr1 = cs ? readl(ebi->io_base + FMC2_BCR1) : bcr;
>> +
>> + if (bcr & FMC2_BCR_BURSTEN && (!cs || !(bcr1 & FMC2_BCR1_CCLKEN)))
>> + return 0;
>> +
>> + return -EINVAL;
>> +}
>> +
>> +static int stm32_fmc2_ebi_check_cclk(struct stm32_fmc2_ebi *ebi,
>> + const struct stm32_fmc2_prop *prop,
>> + int cs)
>> +{
>> + if (cs)
>> + return -EINVAL;
>> +
>> + return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs);
>> +}
>> +
>> +static u32 stm32_fmc2_ebi_ns_to_clock_cycles(struct stm32_fmc2_ebi *ebi,
>> + int cs, u32 setup)
>> +{
>> + unsigned long hclk = clk_get_rate(&ebi->clk);
>> + unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
>> +
>> + return DIV_ROUND_UP(setup * 1000, hclkp);
>> +}
>> +
>> +static u32 stm32_fmc2_ebi_ns_to_clk_period(struct stm32_fmc2_ebi *ebi,
>> + int cs, u32 setup)
>> +{
>> + u32 nb_clk_cycles = stm32_fmc2_ebi_ns_to_clock_cycles(ebi, cs, setup);
>> + u32 bcr = readl(ebi->io_base + FMC2_BCR1);
>> + u32 btr = bcr & FMC2_BCR1_CCLKEN || !cs ?
>> + readl(ebi->io_base + FMC2_BTR1) :
>> + readl(ebi->io_base + FMC2_BTR(cs));
>> + u32 clk_period = FIELD_GET(FMC2_BTR_CLKDIV, btr) + 1;
>> +
>> + return DIV_ROUND_UP(nb_clk_cycles, clk_period);
>> +}
>> +
>> +static int stm32_fmc2_ebi_get_reg(int reg_type, int cs, u32 *reg)
>> +{
>> + switch (reg_type) {
>> + case FMC2_REG_BCR:
>> + *reg = FMC2_BCR(cs);
>> + break;
>> + case FMC2_REG_BTR:
>> + *reg = FMC2_BTR(cs);
>> + break;
>> + case FMC2_REG_BWTR:
>> + *reg = FMC2_BWTR(cs);
>> + break;
>> + case FMC2_REG_PCSCNTR:
>> + *reg = FMC2_PCSCNTR;
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int stm32_fmc2_ebi_set_bit_field(struct stm32_fmc2_ebi *ebi,
>> + const struct stm32_fmc2_prop *prop,
>> + int cs, u32 setup)
>> +{
>> + u32 reg;
>> + int ret;
>> +
>> + ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, ®);
>> + 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
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 08/11] mtd: rawnand: stm32_fmc2: get resources from parent node
2020-08-13 7:33 ` Patrice CHOTARD
@ 2020-08-13 9:58 ` Patrice CHOTARD
0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 9:58 UTC (permalink / raw)
To: u-boot
On 8/13/20 9:33 AM, Patrice CHOTARD wrote:
> Hi Christophe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> FMC2 EBI support has been added. Common resources (registers base
>> address and clock) can now be shared between the 2 drivers using
>> "st,stm32mp1-fmc2-nfc" compatible string. It means that the
>> common resources should now be found in the parent device when EBI
>> node is available.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>> drivers/mtd/nand/raw/stm32_fmc2_nand.c | 87 +++++++++++++++++++++++-----------
>> 1 file changed, 59 insertions(+), 28 deletions(-)
Applied on u-boot-stm/master
Thanks
>>
>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> index 1e4d757..47fe610 100644
>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> @@ -158,10 +158,10 @@ struct stm32_fmc2_nfc {
>> struct nand_hw_control base;
>> struct stm32_fmc2_nand nand;
>> struct nand_ecclayout ecclayout;
>> - void __iomem *io_base;
>> - void __iomem *data_base[FMC2_MAX_CE];
>> - void __iomem *cmd_base[FMC2_MAX_CE];
>> - void __iomem *addr_base[FMC2_MAX_CE];
>> + fdt_addr_t io_base;
>> + fdt_addr_t data_base[FMC2_MAX_CE];
>> + fdt_addr_t cmd_base[FMC2_MAX_CE];
>> + fdt_addr_t addr_base[FMC2_MAX_CE];
>> struct clk clk;
>>
>> u8 cs_assigned;
>> @@ -241,8 +241,8 @@ static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
>> return;
>>
>> nfc->cs_sel = nand->cs_used[chipnr];
>> - chip->IO_ADDR_R = nfc->data_base[nfc->cs_sel];
>> - chip->IO_ADDR_W = nfc->data_base[nfc->cs_sel];
>> + chip->IO_ADDR_R = (void __iomem *)nfc->data_base[nfc->cs_sel];
>> + chip->IO_ADDR_W = (void __iomem *)nfc->data_base[nfc->cs_sel];
>>
>> stm32_fmc2_nfc_setup(chip);
>> stm32_fmc2_nfc_timings_init(chip);
>> @@ -548,7 +548,7 @@ static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
>> return max_bitflips;
>> }
>>
>> -static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>> +static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc, bool has_parent)
>> {
>> u32 pcr = readl(nfc->io_base + FMC2_PCR);
>>
>> @@ -581,7 +581,8 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
>> pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
>>
>> /* Enable FMC2 controller */
>> - setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
>> + if (!has_parent)
>> + setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
>>
>> writel(pcr, nfc->io_base + FMC2_PCR);
>> writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
>> @@ -854,6 +855,30 @@ static int stm32_fmc2_nfc_parse_dt(struct udevice *dev,
>> return 0;
>> }
>>
>> +static struct udevice *stm32_fmc2_nfc_get_cdev(struct udevice *dev)
>> +{
>> + struct udevice *pdev = dev_get_parent(dev);
>> + struct udevice *cdev = NULL;
>> + bool ebi_found = false;
>> +
>> + if (pdev && ofnode_device_is_compatible(dev_ofnode(pdev),
>> + "st,stm32mp1-fmc2-ebi"))
>> + ebi_found = true;
>> +
>> + if (ofnode_device_is_compatible(dev_ofnode(dev),
>> + "st,stm32mp1-fmc2-nfc")) {
>> + if (ebi_found)
>> + cdev = pdev;
>> +
>> + return cdev;
>> + }
>> +
>> + if (!ebi_found)
>> + cdev = dev;
>> +
>> + return cdev;
>> +}
>> +
>> static int stm32_fmc2_nfc_probe(struct udevice *dev)
>> {
>> struct stm32_fmc2_nfc *nfc = dev_get_priv(dev);
>> @@ -861,58 +886,63 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
>> struct nand_chip *chip = &nand->chip;
>> struct mtd_info *mtd = &chip->mtd;
>> struct nand_ecclayout *ecclayout;
>> - struct resource resource;
>> + struct udevice *cdev;
>> struct reset_ctl reset;
>> int oob_index, chip_cs, mem_region, ret;
>> unsigned int i;
>> + int start_region = 0;
>> + fdt_addr_t addr;
>>
>> spin_lock_init(&nfc->controller.lock);
>> init_waitqueue_head(&nfc->controller.wq);
>>
>> + cdev = stm32_fmc2_nfc_get_cdev(dev);
>> + if (!cdev)
>> + return -EINVAL;
>> +
>> ret = stm32_fmc2_nfc_parse_dt(dev, nfc);
>> if (ret)
>> return ret;
>>
>> - /* Get resources */
>> - ret = dev_read_resource(dev, 0, &resource);
>> - if (ret) {
>> - pr_err("Resource io_base not found");
>> - return ret;
>> - }
>> - nfc->io_base = (void __iomem *)resource.start;
>> + nfc->io_base = dev_read_addr(cdev);
>> + if (nfc->io_base == FDT_ADDR_T_NONE)
>> + return -EINVAL;
>> +
>> + if (dev == cdev)
>> + start_region = 1;
>>
>> - for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
>> + for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE;
>> chip_cs++, mem_region += 3) {
>> if (!(nfc->cs_assigned & BIT(chip_cs)))
>> continue;
>>
>> - ret = dev_read_resource(dev, mem_region, &resource);
>> - if (ret) {
>> + addr = dev_read_addr_index(dev, mem_region);
>> + if (addr == FDT_ADDR_T_NONE) {
>> pr_err("Resource data_base not found for cs%d",
>> chip_cs);
>> return ret;
>> }
>> - nfc->data_base[chip_cs] = (void __iomem *)resource.start;
>> + nfc->data_base[chip_cs] = addr;
>>
>> - ret = dev_read_resource(dev, mem_region + 1, &resource);
>> - if (ret) {
>> + addr = dev_read_addr_index(dev, mem_region + 1);
>> + if (addr == FDT_ADDR_T_NONE) {
>> pr_err("Resource cmd_base not found for cs%d",
>> chip_cs);
>> return ret;
>> }
>> - nfc->cmd_base[chip_cs] = (void __iomem *)resource.start;
>> + nfc->cmd_base[chip_cs] = addr;
>>
>> - ret = dev_read_resource(dev, mem_region + 2, &resource);
>> - if (ret) {
>> + addr = dev_read_addr_index(dev, mem_region + 2);
>> + if (addr == FDT_ADDR_T_NONE) {
>> pr_err("Resource addr_base not found for cs%d",
>> chip_cs);
>> return ret;
>> }
>> - nfc->addr_base[chip_cs] = (void __iomem *)resource.start;
>> + nfc->addr_base[chip_cs] = addr;
>> }
>>
>> /* Enable the clock */
>> - ret = clk_get_by_index(dev, 0, &nfc->clk);
>> + ret = clk_get_by_index(cdev, 0, &nfc->clk);
>> if (ret)
>> return ret;
>>
>> @@ -928,7 +958,7 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
>> reset_deassert(&reset);
>> }
>>
>> - stm32_fmc2_nfc_init(nfc);
>> + stm32_fmc2_nfc_init(nfc, dev != cdev);
>>
>> chip->controller = &nfc->base;
>> chip->select_chip = stm32_fmc2_nfc_select_chip;
>> @@ -994,6 +1024,7 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
>>
>> static const struct udevice_id stm32_fmc2_nfc_match[] = {
>> { .compatible = "st,stm32mp15-fmc2" },
>> + { .compatible = "st,stm32mp1-fmc2-nfc" },
>> { /* Sentinel */ }
>> };
>>
> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
>
> Thanks
>
> Patrice
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 10/11] configs: stm32mp: add CONFIG_STM32_FMC2_EBI
2020-08-13 7:35 ` Patrice CHOTARD
@ 2020-08-13 9:59 ` Patrice CHOTARD
0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 9:59 UTC (permalink / raw)
To: u-boot
On 8/13/20 9:35 AM, Patrice CHOTARD wrote:
> Hi Christophe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> This patch enables the support of FMC2 EBI.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>> configs/stm32mp15_basic_defconfig | 1 +
>> configs/stm32mp15_trusted_defconfig | 1 +
>> 2 files changed, 2 insertions(+)
Applied on u-boot-stm/master
Thanks
>>
>> diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig
>> index 5c500a1..2094183 100644
>> --- a/configs/stm32mp15_basic_defconfig
>> +++ b/configs/stm32mp15_basic_defconfig
>> @@ -88,6 +88,7 @@ CONFIG_LED=y
>> CONFIG_LED_GPIO=y
>> CONFIG_DM_MAILBOX=y
>> CONFIG_STM32_IPCC=y
>> +CONFIG_STM32_FMC2_EBI=y
>> CONFIG_DM_MMC=y
>> CONFIG_SUPPORT_EMMC_BOOT=y
>> CONFIG_STM32_SDMMC2=y
>> diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig
>> index 98680cb..8d59d84 100644
>> --- a/configs/stm32mp15_trusted_defconfig
>> +++ b/configs/stm32mp15_trusted_defconfig
>> @@ -68,6 +68,7 @@ CONFIG_LED=y
>> CONFIG_LED_GPIO=y
>> CONFIG_DM_MAILBOX=y
>> CONFIG_STM32_IPCC=y
>> +CONFIG_STM32_FMC2_EBI=y
>> CONFIG_DM_MMC=y
>> CONFIG_SUPPORT_EMMC_BOOT=y
>> CONFIG_STM32_SDMMC2=y
> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
>
> Thanks
>
> Patrice
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 11/11] ARM: dts: stm32: add FMC2 EBI support for stm32mp157c
2020-08-13 7:37 ` Patrice CHOTARD
@ 2020-08-13 9:59 ` Patrice CHOTARD
0 siblings, 0 replies; 33+ messages in thread
From: Patrice CHOTARD @ 2020-08-13 9:59 UTC (permalink / raw)
To: u-boot
On 8/13/20 9:36 AM, Patrice CHOTARD wrote:
> Hi Christophe
>
> On 7/31/20 9:53 AM, Christophe Kerello wrote:
>> This patch adds FMC2 External Bus Interface support on stm32mp157c.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>
>> arch/arm/dts/stm32mp151.dtsi | 43 +++++++++++++++++++++++++++-------------
>> arch/arm/dts/stm32mp157c-ev1.dts | 16 ++++++++-------
>> 2 files changed, 38 insertions(+), 21 deletions(-)
Applied on u-boot-stm/master
Thanks
>>
>> diff --git a/arch/arm/dts/stm32mp151.dtsi b/arch/arm/dts/stm32mp151.dtsi
>> index 0d97f56..39d9e54 100644
>> --- a/arch/arm/dts/stm32mp151.dtsi
>> +++ b/arch/arm/dts/stm32mp151.dtsi
>> @@ -1328,23 +1328,38 @@
>> dma-requests = <48>;
>> };
>>
>> - fmc: nand-controller at 58002000 {
>> - compatible = "st,stm32mp15-fmc2";
>> - reg = <0x58002000 0x1000>,
>> - <0x80000000 0x1000>,
>> - <0x88010000 0x1000>,
>> - <0x88020000 0x1000>,
>> - <0x81000000 0x1000>,
>> - <0x89010000 0x1000>,
>> - <0x89020000 0x1000>;
>> - interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
>> - dmas = <&mdma1 20 0x10 0x12000a02 0x0 0x0>,
>> - <&mdma1 20 0x10 0x12000a08 0x0 0x0>,
>> - <&mdma1 21 0x10 0x12000a0a 0x0 0x0>;
>> - dma-names = "tx", "rx", "ecc";
>> + fmc: memory-controller at 58002000 {
>> + #address-cells = <2>;
>> + #size-cells = <1>;
>> + compatible = "st,stm32mp1-fmc2-ebi";
>> + reg = <0x58002000 0x1000>;
>> clocks = <&rcc FMC_K>;
>> resets = <&rcc FMC_R>;
>> status = "disabled";
>> +
>> + ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */
>> + <1 0 0x64000000 0x04000000>, /* EBI CS 2 */
>> + <2 0 0x68000000 0x04000000>, /* EBI CS 3 */
>> + <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */
>> + <4 0 0x80000000 0x10000000>; /* NAND */
>> +
>> + nand-controller at 4,0 {
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + compatible = "st,stm32mp1-fmc2-nfc";
>> + reg = <4 0x00000000 0x1000>,
>> + <4 0x08010000 0x1000>,
>> + <4 0x08020000 0x1000>,
>> + <4 0x01000000 0x1000>,
>> + <4 0x09010000 0x1000>,
>> + <4 0x09020000 0x1000>;
>> + interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
>> + dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
>> + <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
>> + <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
>> + dma-names = "tx", "rx", "ecc";
>> + status = "disabled";
>> + };
>> };
>>
>> qspi: spi at 58003000 {
>> diff --git a/arch/arm/dts/stm32mp157c-ev1.dts b/arch/arm/dts/stm32mp157c-ev1.dts
>> index b190565..46f81ce 100644
>> --- a/arch/arm/dts/stm32mp157c-ev1.dts
>> +++ b/arch/arm/dts/stm32mp157c-ev1.dts
>> @@ -157,14 +157,16 @@
>> pinctrl-0 = <&fmc_pins_a>;
>> pinctrl-1 = <&fmc_sleep_pins_a>;
>> status = "okay";
>> - #address-cells = <1>;
>> - #size-cells = <0>;
>>
>> - nand at 0 {
>> - reg = <0>;
>> - nand-on-flash-bbt;
>> - #address-cells = <1>;
>> - #size-cells = <1>;
>> + nand-controller at 4,0 {
>> + status = "okay";
>> +
>> + nand at 0 {
>> + reg = <0>;
>> + nand-on-flash-bbt;
>> + #address-cells = <1>;
>> + #size-cells = <1>;
>> + };
>> };
>> };
>>
> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
>
> Thanks
>
> Patrice
>
^ permalink raw reply [flat|nested] 33+ messages in thread
end of thread, other threads:[~2020-08-13 9:59 UTC | newest]
Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-31 7:53 [PATCH 00/11] Add STM32 FMC2 EBI controller driver Christophe Kerello
2020-07-31 7:53 ` [PATCH 01/11] mtd: rawnand: stm32_fmc2: fix a buffer overflow Christophe Kerello
2020-08-13 7:27 ` Patrice CHOTARD
2020-08-13 9:56 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 02/11] mtd: rawnand: stm32_fmc2: remove useless inline comments Christophe Kerello
2020-08-13 7:28 ` Patrice CHOTARD
2020-08-13 9:56 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 03/11] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_5S for timeouts Christophe Kerello
2020-08-13 7:29 ` Patrice CHOTARD
2020-08-13 9:57 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 04/11] mtd: rawnand: stm32_fmc2: cosmetic change to use nfc instead of fmc2 where relevant Christophe Kerello
2020-08-13 7:29 ` Patrice CHOTARD
2020-08-13 9:57 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 05/11] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros Christophe Kerello
2020-08-13 7:29 ` Patrice CHOTARD
2020-08-13 9:58 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 06/11] mtd: rawnand: stm32_fmc2: use clrsetbits_le32 Christophe Kerello
2020-08-13 7:30 ` Patrice CHOTARD
2020-08-13 9:58 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 07/11] memory: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver Christophe Kerello
2020-08-13 7:31 ` Patrice CHOTARD
2020-08-13 9:58 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 08/11] mtd: rawnand: stm32_fmc2: get resources from parent node Christophe Kerello
2020-08-13 7:33 ` Patrice CHOTARD
2020-08-13 9:58 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 09/11] board: stm32mp1: update fdt fixup partitions table Christophe Kerello
2020-08-13 7:34 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 10/11] configs: stm32mp: add CONFIG_STM32_FMC2_EBI Christophe Kerello
2020-08-13 7:35 ` Patrice CHOTARD
2020-08-13 9:59 ` Patrice CHOTARD
2020-07-31 7:53 ` [PATCH 11/11] ARM: dts: stm32: add FMC2 EBI support for stm32mp157c Christophe Kerello
2020-08-13 7:37 ` Patrice CHOTARD
2020-08-13 9:59 ` Patrice CHOTARD
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.