
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