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 

Reply via email to