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

Patrice CHOTARD patrice.chotard at foss.st.com
Fri Mar 8 12:16:13 CET 2024



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 at 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 at foss.st.com>

Thanks
Patrice


More information about the U-Boot mailing list