diff mbox series

[v1,2/2] memory: stm32-fmc2-ebi: add MP25 RIF support

Message ID 20240306095048.314546-3-christophe.kerello@foss.st.com
State Accepted
Commit a10ee1322ae4aff1d9e1a283e89a90ce230e3aa8
Delegated to: Patrice Chotard
Headers show
Series memory: stm32-fmc2-ebi: Add MP25 FMC2 support | expand

Commit Message

Christophe Kerello March 6, 2024, 9:50 a.m. UTC
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.kerello@foss.st.com>
---

 drivers/memory/stm32-fmc2-ebi.c | 140 +++++++++++++++++++++++++++++++-
 1 file changed, 138 insertions(+), 2 deletions(-)

Comments

Patrice CHOTARD March 8, 2024, 11:16 a.m. UTC | #1
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.kerello@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.chotard@foss.st.com>

Thanks
Patrice
Patrice CHOTARD April 19, 2024, 12:13 p.m. UTC | #2
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.kerello@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[] = {

Applied on u-boot-stm32/master
diff mbox series

Patch

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[] = {