mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 15:14:43 +00:00
mtd: rawnand: stm32_fmc2: get resources from parent node
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> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
This commit is contained in:
parent
6d47598629
commit
82bf7729a2
1 changed files with 59 additions and 28 deletions
|
@ -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;
|
||||
|
||||
for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
|
||||
if (dev == cdev)
|
||||
start_region = 1;
|
||||
|
||||
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 */ }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue