On 3/6/24 10:50, Christophe Kerello wrote:
> The FMC2 revision 2 supports security and isolation compliant with
> the Resource Isolation Framework (RIF). From RIF point of view,
> the FMC2 is composed of several independent resources, listed below,
> which can be assigned to different security and compartment domains:
>  - 0: Common FMC_CFGR register.
>  - 1: EBI controller for Chip Select 1.
>  - 2: EBI controller for Chip Select 2.
>  - 3: EBI controller for Chip Select 3.
>  - 4: EBI controller for Chip Select 4.
>  - 5: NAND controller.
> 
> Signed-off-by: Christophe Kerello <christophe.kere...@foss.st.com>
> ---
> 
>  drivers/memory/stm32-fmc2-ebi.c | 140 +++++++++++++++++++++++++++++++-
>  1 file changed, 138 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/memory/stm32-fmc2-ebi.c b/drivers/memory/stm32-fmc2-ebi.c
> index c7db16463e8..1ce96077858 100644
> --- a/drivers/memory/stm32-fmc2-ebi.c
> +++ b/drivers/memory/stm32-fmc2-ebi.c
> @@ -23,8 +23,14 @@
>  #define FMC2_BTR(x)                  ((x) * 0x8 + FMC2_BTR1)
>  #define FMC2_PCSCNTR                 0x20
>  #define FMC2_CFGR                    0x20
> +#define FMC2_SR                              0x84
>  #define FMC2_BWTR1                   0x104
>  #define FMC2_BWTR(x)                 ((x) * 0x8 + FMC2_BWTR1)
> +#define FMC2_SECCFGR                 0x300
> +#define FMC2_CIDCFGR0                        0x30c
> +#define FMC2_CIDCFGR(x)                      ((x) * 0x8 + FMC2_CIDCFGR0)
> +#define FMC2_SEMCR0                  0x310
> +#define FMC2_SEMCR(x)                        ((x) * 0x8 + FMC2_SEMCR0)
>  
>  /* Register: FMC2_BCR1 */
>  #define FMC2_BCR1_CCLKEN             BIT(20)
> @@ -67,8 +73,23 @@
>  #define FMC2_CFGR_CCLKEN             BIT(20)
>  #define FMC2_CFGR_FMC2EN             BIT(31)
>  
> +/* Register: FMC2_SR */
> +#define FMC2_SR_ISOST                        GENMASK(1, 0)
> +
> +/* Register: FMC2_CIDCFGR */
> +#define FMC2_CIDCFGR_CFEN            BIT(0)
> +#define FMC2_CIDCFGR_SEMEN           BIT(1)
> +#define FMC2_CIDCFGR_SCID            GENMASK(6, 4)
> +#define FMC2_CIDCFGR_SEMWLC1         BIT(17)
> +
> +/* Register: FMC2_SEMCR */
> +#define FMC2_SEMCR_SEM_MUTEX         BIT(0)
> +#define FMC2_SEMCR_SEMCID            GENMASK(6, 4)
> +
>  #define FMC2_MAX_EBI_CE                      4
>  #define FMC2_MAX_BANKS                       5
> +#define FMC2_MAX_RESOURCES           6
> +#define FMC2_CID1                    1
>  
>  #define FMC2_BCR_CPSIZE_0            0x0
>  #define FMC2_BCR_CPSIZE_128          0x1
> @@ -163,6 +184,7 @@ struct stm32_fmc2_ebi_data {
>       u32 fmc2_enable_reg;
>       u32 fmc2_enable_bit;
>       int (*nwait_used_by_ctrls)(struct stm32_fmc2_ebi *ebi);
> +     int (*check_rif)(struct stm32_fmc2_ebi *ebi, u32 resource);
>  };
>  
>  struct stm32_fmc2_ebi {
> @@ -170,6 +192,7 @@ struct stm32_fmc2_ebi {
>       fdt_addr_t io_base;
>       const struct stm32_fmc2_ebi_data *data;
>       u8 bank_assigned;
> +     bool access_granted;
>  };
>  
>  /*
> @@ -241,6 +264,28 @@ static int stm32_fmc2_ebi_check_sync_trans(struct 
> stm32_fmc2_ebi *ebi,
>       return -EINVAL;
>  }
>  
> +static int stm32_fmc2_ebi_mp25_check_cclk(struct stm32_fmc2_ebi *ebi,
> +                                       const struct stm32_fmc2_prop *prop,
> +                                       int cs)
> +{
> +     if (!ebi->access_granted)
> +             return -EACCES;
> +
> +     return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs);
> +}
> +
> +static int stm32_fmc2_ebi_mp25_check_clk_period(struct stm32_fmc2_ebi *ebi,
> +                                             const struct stm32_fmc2_prop 
> *prop,
> +                                             int cs)
> +{
> +     u32 cfgr = readl(ebi->io_base + FMC2_CFGR);
> +
> +     if (cfgr & FMC2_CFGR_CCLKEN && !ebi->access_granted)
> +             return -EACCES;
> +
> +     return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs);
> +}
> +
>  static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2_ebi *ebi,
>                                           const struct stm32_fmc2_prop *prop,
>                                           int cs)
> @@ -960,7 +1005,7 @@ static const struct stm32_fmc2_prop 
> stm32_fmc2_mp25_child_props[] = {
>               .bprop = true,
>               .reg_type = FMC2_REG_CFGR,
>               .reg_mask = FMC2_CFGR_CCLKEN,
> -             .check = stm32_fmc2_ebi_check_sync_trans,
> +             .check = stm32_fmc2_ebi_mp25_check_cclk,
>               .set = stm32_fmc2_ebi_set_bit_field,
>       },
>       {
> @@ -1058,7 +1103,7 @@ static const struct stm32_fmc2_prop 
> stm32_fmc2_mp25_child_props[] = {
>       {
>               .name = "st,fmc2-ebi-cs-clk-period-ns",
>               .reset_val = FMC2_CFGR_CLKDIV_MAX + 1,
> -             .check = stm32_fmc2_ebi_check_sync_trans,
> +             .check = stm32_fmc2_ebi_mp25_check_clk_period,
>               .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
>               .set = stm32_fmc2_ebi_mp25_set_clk_period,
>       },
> @@ -1113,6 +1158,70 @@ static const struct stm32_fmc2_prop 
> stm32_fmc2_mp25_child_props[] = {
>       },
>  };
>  
> +static int stm32_fmc2_ebi_mp25_check_rif(struct stm32_fmc2_ebi *ebi, u32 
> resource)
> +{
> +     u32 seccfgr, cidcfgr, semcr;
> +     int cid;
> +
> +     if (resource >= FMC2_MAX_RESOURCES)
> +             return -EINVAL;
> +
> +     seccfgr = readl(ebi->io_base + FMC2_SECCFGR);
> +     if (seccfgr & BIT(resource)) {
> +             if (resource)
> +                     log_err("resource %d is configured as secure\n",
> +                             resource);
> +
> +             return -EACCES;
> +     }
> +
> +     cidcfgr = readl(ebi->io_base + FMC2_CIDCFGR(resource));
> +     if (!(cidcfgr & FMC2_CIDCFGR_CFEN))
> +             /* CID filtering is turned off: access granted */
> +             return 0;
> +
> +     if (!(cidcfgr & FMC2_CIDCFGR_SEMEN)) {
> +             /* Static CID mode */
> +             cid = FIELD_GET(FMC2_CIDCFGR_SCID, cidcfgr);
> +             if (cid != FMC2_CID1) {
> +                     if (resource)
> +                             log_err("static CID%d set for resource %d\n",
> +                                     cid, resource);
> +
> +                     return -EACCES;
> +             }
> +
> +             return 0;
> +     }
> +
> +     /* Pass-list with semaphore mode */
> +     if (!(cidcfgr & FMC2_CIDCFGR_SEMWLC1)) {
> +             if (resource)
> +                     log_err("CID1 is block-listed for resource %d\n",
> +                             resource);
> +
> +             return -EACCES;
> +     }
> +
> +     semcr = readl(ebi->io_base + FMC2_SEMCR(resource));
> +     if (!(semcr & FMC2_SEMCR_SEM_MUTEX)) {
> +             setbits_le32(ebi->io_base + FMC2_SEMCR(resource),
> +                          FMC2_SEMCR_SEM_MUTEX);
> +             semcr = readl(ebi->io_base + FMC2_SEMCR(resource));
> +     }
> +
> +     cid = FIELD_GET(FMC2_SEMCR_SEMCID, semcr);
> +     if (cid != FMC2_CID1) {
> +             if (resource)
> +                     log_err("resource %d is already used by CID%d\n",
> +                             resource, cid);
> +
> +             return -EACCES;
> +     }
> +
> +     return 0;
> +}
> +
>  static int stm32_fmc2_ebi_parse_prop(struct stm32_fmc2_ebi *ebi,
>                                    ofnode node,
>                                    const struct stm32_fmc2_prop *prop,
> @@ -1196,6 +1305,9 @@ static int stm32_fmc2_ebi_nwait_used_by_ctrls(struct 
> stm32_fmc2_ebi *ebi)
>  
>  static void stm32_fmc2_ebi_enable(struct stm32_fmc2_ebi *ebi)
>  {
> +     if (!ebi->access_granted)
> +             return;
> +
>       setbits_le32(ebi->io_base + ebi->data->fmc2_enable_reg,
>                    ebi->data->fmc2_enable_bit);
>  }
> @@ -1249,6 +1361,14 @@ static int stm32_fmc2_ebi_parse_dt(struct udevice *dev,
>                       return -EINVAL;
>               }
>  
> +             if (ebi->data->check_rif) {
> +                     ret = ebi->data->check_rif(ebi, bank + 1);
> +                     if (ret) {
> +                             dev_err(dev, "bank access failed: %d\n", bank);
> +                             return ret;
> +                     }
> +             }
> +
>               if (bank < FMC2_MAX_EBI_CE) {
>                       ret = stm32_fmc2_ebi_setup_cs(ebi, child, bank);
>                       if (ret) {
> @@ -1306,6 +1426,21 @@ static int stm32_fmc2_ebi_probe(struct udevice *dev)
>               reset_deassert(&reset);
>       }
>  
> +     /* Check if CFGR register can be modified */
> +     ebi->access_granted = true;
> +     if (ebi->data->check_rif) {
> +             ret = ebi->data->check_rif(ebi, 0);
> +             if (ret) {
> +                     ebi->access_granted = false;
> +
> +                     /* In case of CFGR is secure, just check that the FMC2 
> is enabled */
> +                     if (readl(ebi->io_base + FMC2_SR) & FMC2_SR_ISOST) {
> +                             dev_err(dev, "FMC2 is not ready to be used.\n");
> +                             return -EACCES;
> +                     }
> +             }
> +     }
> +
>       return stm32_fmc2_ebi_parse_dt(dev, ebi);
>  }
>  
> @@ -1322,6 +1457,7 @@ static const struct stm32_fmc2_ebi_data 
> stm32_fmc2_ebi_mp25_data = {
>       .nb_child_props = ARRAY_SIZE(stm32_fmc2_mp25_child_props),
>       .fmc2_enable_reg = FMC2_CFGR,
>       .fmc2_enable_bit = FMC2_CFGR_FMC2EN,
> +     .check_rif = stm32_fmc2_ebi_mp25_check_rif,
>  };
>  
>  static const struct udevice_id stm32_fmc2_ebi_match[] = {
Reviewed-by: Patrice Chotard <patrice.chot...@foss.st.com>

Thanks
Patrice

Reply via email to