[PATCH v1 2/2] memory: stm32-fmc2-ebi: add MP25 RIF support
Patrice CHOTARD
patrice.chotard at foss.st.com
Fri Apr 19 14:13:27 CEST 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[] = {
Applied on u-boot-stm32/master
More information about the U-Boot
mailing list