On 3/6/24 10:50, Christophe Kerello wrote: > Add the support of the revision 2 of FMC2 IP. > - PCSCNTR register has been removed, > - CFGR register has been added, > - the bit used to enable the IP has moved from BCR1 to CFGR, > - the timeout for CEx deassertion has moved from PCSCNTR to BCRx, > - the continuous clock enable has moved from BCR1 to CFGR, > - the clk divide ratio has moved from BCR1 to CFGR. > > The MP1 SoCs have only one signal to manage all the controllers (NWAIT). > The MP25 SOC has one RNB signal for the NAND controller and one NWAIT > signal for the memory controller. > > Let's use a platform data structure for parameters that will differ > between MP1 and MP25. > > Signed-off-by: Christophe Kerello <christophe.kere...@foss.st.com> > > --- > > drivers/memory/stm32-fmc2-ebi.c | 313 ++++++++++++++++++++++++++++++-- > 1 file changed, 301 insertions(+), 12 deletions(-) > > diff --git a/drivers/memory/stm32-fmc2-ebi.c b/drivers/memory/stm32-fmc2-ebi.c > index a722a3836f7..c7db16463e8 100644 > --- a/drivers/memory/stm32-fmc2-ebi.c > +++ b/drivers/memory/stm32-fmc2-ebi.c > @@ -22,6 +22,7 @@ > #define FMC2_BCR(x) ((x) * 0x8 + FMC2_BCR1) > #define FMC2_BTR(x) ((x) * 0x8 + FMC2_BTR1) > #define FMC2_PCSCNTR 0x20 > +#define FMC2_CFGR 0x20 > #define FMC2_BWTR1 0x104 > #define FMC2_BWTR(x) ((x) * 0x8 + FMC2_BWTR1) > > @@ -44,6 +45,7 @@ > #define FMC2_BCR_ASYNCWAIT BIT(15) > #define FMC2_BCR_CPSIZE GENMASK(18, 16) > #define FMC2_BCR_CBURSTRW BIT(19) > +#define FMC2_BCR_CSCOUNT GENMASK(21, 20) > #define FMC2_BCR_NBLSET GENMASK(23, 22) > > /* Register: FMC2_BTRx/FMC2_BWTRx */ > @@ -60,6 +62,11 @@ > #define FMC2_PCSCNTR_CSCOUNT GENMASK(15, 0) > #define FMC2_PCSCNTR_CNTBEN(x) BIT((x) + 16) > > +/* Register: FMC2_CFGR */ > +#define FMC2_CFGR_CLKDIV GENMASK(19, 16) > +#define FMC2_CFGR_CCLKEN BIT(20) > +#define FMC2_CFGR_FMC2EN BIT(31) > + > #define FMC2_MAX_EBI_CE 4 > #define FMC2_MAX_BANKS 5 > > @@ -76,6 +83,11 @@ > #define FMC2_BCR_MTYP_PSRAM 0x1 > #define FMC2_BCR_MTYP_NOR 0x2 > > +#define FMC2_BCR_CSCOUNT_0 0x0 > +#define FMC2_BCR_CSCOUNT_1 0x1 > +#define FMC2_BCR_CSCOUNT_64 0x2 > +#define FMC2_BCR_CSCOUNT_256 0x3 > + > #define FMC2_BXTR_EXTMOD_A 0x0 > #define FMC2_BXTR_EXTMOD_B 0x1 > #define FMC2_BXTR_EXTMOD_C 0x2 > @@ -90,6 +102,7 @@ > #define FMC2_BTR_CLKDIV_MAX 0xf > #define FMC2_BTR_DATLAT_MAX 0xf > #define FMC2_PCSCNTR_CSCOUNT_MAX 0xff > +#define FMC2_CFGR_CLKDIV_MAX 0xf > > enum stm32_fmc2_ebi_bank { > FMC2_EBI1 = 0, > @@ -103,7 +116,8 @@ enum stm32_fmc2_ebi_register_type { > FMC2_REG_BCR = 1, > FMC2_REG_BTR, > FMC2_REG_BWTR, > - FMC2_REG_PCSCNTR > + FMC2_REG_PCSCNTR, > + FMC2_REG_CFGR > }; > > enum stm32_fmc2_ebi_transaction_type { > @@ -134,9 +148,27 @@ enum stm32_fmc2_ebi_cpsize { > FMC2_CPSIZE_1024 = 1024 > }; > > +enum stm32_fmc2_ebi_cscount { > + FMC2_CSCOUNT_0 = 0, > + FMC2_CSCOUNT_1 = 1, > + FMC2_CSCOUNT_64 = 64, > + FMC2_CSCOUNT_256 = 256 > +}; > + > +struct stm32_fmc2_ebi; > + > +struct stm32_fmc2_ebi_data { > + const struct stm32_fmc2_prop *child_props; > + unsigned int nb_child_props; > + u32 fmc2_enable_reg; > + u32 fmc2_enable_bit; > + int (*nwait_used_by_ctrls)(struct stm32_fmc2_ebi *ebi); > +}; > + > struct stm32_fmc2_ebi { > struct clk clk; > fdt_addr_t io_base; > + const struct stm32_fmc2_ebi_data *data; > u8 bank_assigned; > }; > > @@ -296,6 +328,24 @@ static u32 stm32_fmc2_ebi_ns_to_clk_period(struct > stm32_fmc2_ebi *ebi, > return DIV_ROUND_UP(nb_clk_cycles, clk_period); > } > > +static u32 stm32_fmc2_ebi_mp25_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 cfgr = readl(ebi->io_base + FMC2_CFGR); > + u32 clk_period; > + > + if (cfgr & FMC2_CFGR_CCLKEN) { > + clk_period = FIELD_GET(FMC2_CFGR_CLKDIV, cfgr) + 1; > + } else { > + u32 btr = readl(ebi->io_base + FMC2_BTR(cs)); > + > + 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) { > @@ -311,6 +361,9 @@ static int stm32_fmc2_ebi_get_reg(int reg_type, int cs, > u32 *reg) > case FMC2_REG_PCSCNTR: > *reg = FMC2_PCSCNTR; > break; > + case FMC2_REG_CFGR: > + *reg = FMC2_CFGR; > + break; > default: > return -EINVAL; > } > @@ -649,6 +702,26 @@ static int stm32_fmc2_ebi_set_clk_period(struct > stm32_fmc2_ebi *ebi, > return 0; > } > > +static int stm32_fmc2_ebi_mp25_set_clk_period(struct stm32_fmc2_ebi *ebi, > + const struct stm32_fmc2_prop > *prop, > + int cs, u32 setup) > +{ > + u32 cfgr = readl(ebi->io_base + FMC2_CFGR); > + u32 val; > + > + if (cfgr & FMC2_CFGR_CCLKEN) { > + val = setup ? clamp_val(setup - 1, 1, FMC2_CFGR_CLKDIV_MAX) : 1; > + val = FIELD_PREP(FMC2_CFGR_CLKDIV, val); > + clrsetbits_le32(ebi->io_base + FMC2_CFGR, FMC2_CFGR_CLKDIV, > val); > + } else { > + 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) > @@ -689,6 +762,27 @@ static int stm32_fmc2_ebi_set_max_low_pulse(struct > stm32_fmc2_ebi *ebi, > return 0; > } > > +static int stm32_fmc2_ebi_mp25_set_max_low_pulse(struct stm32_fmc2_ebi *ebi, > + const struct stm32_fmc2_prop > *prop, > + int cs, u32 setup) > +{ > + u32 val; > + > + if (setup == FMC2_CSCOUNT_0) > + val = FIELD_PREP(FMC2_BCR_CSCOUNT, FMC2_BCR_CSCOUNT_0); > + else if (setup == FMC2_CSCOUNT_1) > + val = FIELD_PREP(FMC2_BCR_CSCOUNT, FMC2_BCR_CSCOUNT_1); > + else if (setup <= FMC2_CSCOUNT_64) > + val = FIELD_PREP(FMC2_BCR_CSCOUNT, FMC2_BCR_CSCOUNT_64); > + else > + val = FIELD_PREP(FMC2_BCR_CSCOUNT, FMC2_BCR_CSCOUNT_256); > + > + clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), > + FMC2_BCR_CSCOUNT, val); > + > + return 0; > +} > + > static const struct stm32_fmc2_prop stm32_fmc2_child_props[] = { > /* st,fmc2-ebi-cs-trans-type must be the first property */ > { > @@ -854,6 +948,171 @@ static const struct stm32_fmc2_prop > stm32_fmc2_child_props[] = { > }, > }; > > +static const struct stm32_fmc2_prop stm32_fmc2_mp25_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_CFGR, > + .reg_mask = FMC2_CFGR_CCLKEN, > + .check = stm32_fmc2_ebi_check_sync_trans, > + .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_CFGR_CLKDIV_MAX + 1, > + .check = stm32_fmc2_ebi_check_sync_trans, > + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, > + .set = stm32_fmc2_ebi_mp25_set_clk_period, > + }, > + { > + .name = "st,fmc2-ebi-cs-data-latency-ns", > + .check = stm32_fmc2_ebi_check_sync_trans, > + .calculate = stm32_fmc2_ebi_mp25_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_mp25_set_max_low_pulse, > + }, > +}; > + > static int stm32_fmc2_ebi_parse_prop(struct stm32_fmc2_ebi *ebi, > ofnode node, > const struct stm32_fmc2_prop *prop, > @@ -915,7 +1174,7 @@ static void stm32_fmc2_ebi_disable_bank(struct > stm32_fmc2_ebi *ebi, int cs) > } > > /* 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) > +static int stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi) > { > unsigned int cs; > u32 bcr; > @@ -926,16 +1185,19 @@ static bool stm32_fmc2_ebi_nwait_used_by_ctrls(struct > stm32_fmc2_ebi *ebi) > > 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; > + ebi->bank_assigned & BIT(FMC2_NAND)) { > + log_err("NWAIT signal connected to EBI and NAND > controllers\n"); > + return -EINVAL; > + } > } > > - return false; > + return 0; > } > > static void stm32_fmc2_ebi_enable(struct stm32_fmc2_ebi *ebi) > { > - setbits_le32(ebi->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN); > + setbits_le32(ebi->io_base + ebi->data->fmc2_enable_reg, > + ebi->data->fmc2_enable_bit); > } > > static int stm32_fmc2_ebi_setup_cs(struct stm32_fmc2_ebi *ebi, > @@ -946,8 +1208,8 @@ static int stm32_fmc2_ebi_setup_cs(struct stm32_fmc2_ebi > *ebi, > > 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]; > + for (i = 0; i < ebi->data->nb_child_props; i++) { > + const struct stm32_fmc2_prop *p = &ebi->data->child_props[i]; > > ret = stm32_fmc2_ebi_parse_prop(ebi, node, p, cs); > if (ret) { > @@ -1004,9 +1266,10 @@ static int stm32_fmc2_ebi_parse_dt(struct udevice *dev, > return -ENODEV; > } > > - if (stm32_fmc2_ebi_nwait_used_by_ctrls(ebi)) { > - dev_err(dev, "NWAIT signal connected to EBI and NAND > controllers\n"); > - return -EINVAL; > + if (ebi->data->nwait_used_by_ctrls) { > + ret = ebi->data->nwait_used_by_ctrls(ebi); > + if (ret) > + return ret; > } > > stm32_fmc2_ebi_enable(ebi); > @@ -1020,6 +1283,10 @@ static int stm32_fmc2_ebi_probe(struct udevice *dev) > struct reset_ctl reset; > int ret; > > + ebi->data = (void *)dev_get_driver_data(dev); > + if (!ebi->data) > + return -EINVAL; > + > ebi->io_base = dev_read_addr(dev); > if (ebi->io_base == FDT_ADDR_T_NONE) > return -EINVAL; > @@ -1042,8 +1309,30 @@ static int stm32_fmc2_ebi_probe(struct udevice *dev) > return stm32_fmc2_ebi_parse_dt(dev, ebi); > } > > +static const struct stm32_fmc2_ebi_data stm32_fmc2_ebi_mp1_data = { > + .child_props = stm32_fmc2_child_props, > + .nb_child_props = ARRAY_SIZE(stm32_fmc2_child_props), > + .fmc2_enable_reg = FMC2_BCR1, > + .fmc2_enable_bit = FMC2_BCR1_FMC2EN, > + .nwait_used_by_ctrls = stm32_fmc2_ebi_nwait_used_by_ctrls, > +}; > + > +static const struct stm32_fmc2_ebi_data stm32_fmc2_ebi_mp25_data = { > + .child_props = stm32_fmc2_mp25_child_props, > + .nb_child_props = ARRAY_SIZE(stm32_fmc2_mp25_child_props), > + .fmc2_enable_reg = FMC2_CFGR, > + .fmc2_enable_bit = FMC2_CFGR_FMC2EN, > +}; > + > static const struct udevice_id stm32_fmc2_ebi_match[] = { > - {.compatible = "st,stm32mp1-fmc2-ebi"}, > + { > + .compatible = "st,stm32mp1-fmc2-ebi", > + .data = (ulong)&stm32_fmc2_ebi_mp1_data, > + }, > + { > + .compatible = "st,stm32mp25-fmc2-ebi", > + .data = (ulong)&stm32_fmc2_ebi_mp25_data, > + }, > { /* Sentinel */ } > }; > Applied on u-boot-stm32/master