Skip to content

Commit cc7d5cf

Browse files
Christophe Kerellokrzk
authored andcommitted
memory: stm32-fmc2-ebi: add MP25 RIF support
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Krzysztof Kozlowski <[email protected]>
1 parent 2ff761f commit cc7d5cf

File tree

1 file changed

+220
-4
lines changed

1 file changed

+220
-4
lines changed

drivers/memory/stm32-fmc2-ebi.c

Lines changed: 220 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,14 @@
2121
#define FMC2_BTR(x) ((x) * 0x8 + FMC2_BTR1)
2222
#define FMC2_PCSCNTR 0x20
2323
#define FMC2_CFGR 0x20
24+
#define FMC2_SR 0x84
2425
#define FMC2_BWTR1 0x104
2526
#define FMC2_BWTR(x) ((x) * 0x8 + FMC2_BWTR1)
27+
#define FMC2_SECCFGR 0x300
28+
#define FMC2_CIDCFGR0 0x30c
29+
#define FMC2_CIDCFGR(x) ((x) * 0x8 + FMC2_CIDCFGR0)
30+
#define FMC2_SEMCR0 0x310
31+
#define FMC2_SEMCR(x) ((x) * 0x8 + FMC2_SEMCR0)
2632

2733
/* Register: FMC2_BCR1 */
2834
#define FMC2_BCR1_CCLKEN BIT(20)
@@ -65,8 +71,23 @@
6571
#define FMC2_CFGR_CCLKEN BIT(20)
6672
#define FMC2_CFGR_FMC2EN BIT(31)
6773

74+
/* Register: FMC2_SR */
75+
#define FMC2_SR_ISOST GENMASK(1, 0)
76+
77+
/* Register: FMC2_CIDCFGR */
78+
#define FMC2_CIDCFGR_CFEN BIT(0)
79+
#define FMC2_CIDCFGR_SEMEN BIT(1)
80+
#define FMC2_CIDCFGR_SCID GENMASK(6, 4)
81+
#define FMC2_CIDCFGR_SEMWLC1 BIT(17)
82+
83+
/* Register: FMC2_SEMCR */
84+
#define FMC2_SEMCR_SEM_MUTEX BIT(0)
85+
#define FMC2_SEMCR_SEMCID GENMASK(6, 4)
86+
6887
#define FMC2_MAX_EBI_CE 4
6988
#define FMC2_MAX_BANKS 5
89+
#define FMC2_MAX_RESOURCES 6
90+
#define FMC2_CID1 1
7091

7192
#define FMC2_BCR_CPSIZE_0 0x0
7293
#define FMC2_BCR_CPSIZE_128 0x1
@@ -163,6 +184,9 @@ struct stm32_fmc2_ebi_data {
163184
int (*nwait_used_by_ctrls)(struct stm32_fmc2_ebi *ebi);
164185
void (*set_setup)(struct stm32_fmc2_ebi *ebi);
165186
int (*save_setup)(struct stm32_fmc2_ebi *ebi);
187+
int (*check_rif)(struct stm32_fmc2_ebi *ebi, u32 resource);
188+
void (*put_sems)(struct stm32_fmc2_ebi *ebi);
189+
void (*get_sems)(struct stm32_fmc2_ebi *ebi);
166190
};
167191

168192
struct stm32_fmc2_ebi {
@@ -171,6 +195,8 @@ struct stm32_fmc2_ebi {
171195
struct regmap *regmap;
172196
const struct stm32_fmc2_ebi_data *data;
173197
u8 bank_assigned;
198+
u8 sem_taken;
199+
bool access_granted;
174200

175201
u32 bcr[FMC2_MAX_EBI_CE];
176202
u32 btr[FMC2_MAX_EBI_CE];
@@ -262,6 +288,33 @@ static int stm32_fmc2_ebi_check_sync_trans(struct stm32_fmc2_ebi *ebi,
262288
return -EINVAL;
263289
}
264290

291+
static int stm32_fmc2_ebi_mp25_check_cclk(struct stm32_fmc2_ebi *ebi,
292+
const struct stm32_fmc2_prop *prop,
293+
int cs)
294+
{
295+
if (!ebi->access_granted)
296+
return -EACCES;
297+
298+
return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs);
299+
}
300+
301+
static int stm32_fmc2_ebi_mp25_check_clk_period(struct stm32_fmc2_ebi *ebi,
302+
const struct stm32_fmc2_prop *prop,
303+
int cs)
304+
{
305+
u32 cfgr;
306+
int ret;
307+
308+
ret = regmap_read(ebi->regmap, FMC2_CFGR, &cfgr);
309+
if (ret)
310+
return ret;
311+
312+
if (cfgr & FMC2_CFGR_CCLKEN && !ebi->access_granted)
313+
return -EACCES;
314+
315+
return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs);
316+
}
317+
265318
static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2_ebi *ebi,
266319
const struct stm32_fmc2_prop *prop,
267320
int cs)
@@ -1043,7 +1096,7 @@ static const struct stm32_fmc2_prop stm32_fmc2_mp25_child_props[] = {
10431096
.bprop = true,
10441097
.reg_type = FMC2_REG_CFGR,
10451098
.reg_mask = FMC2_CFGR_CCLKEN,
1046-
.check = stm32_fmc2_ebi_check_sync_trans,
1099+
.check = stm32_fmc2_ebi_mp25_check_cclk,
10471100
.set = stm32_fmc2_ebi_set_bit_field,
10481101
},
10491102
{
@@ -1141,7 +1194,7 @@ static const struct stm32_fmc2_prop stm32_fmc2_mp25_child_props[] = {
11411194
{
11421195
.name = "st,fmc2-ebi-cs-clk-period-ns",
11431196
.reset_val = FMC2_CFGR_CLKDIV_MAX + 1,
1144-
.check = stm32_fmc2_ebi_check_sync_trans,
1197+
.check = stm32_fmc2_ebi_mp25_check_clk_period,
11451198
.calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
11461199
.set = stm32_fmc2_ebi_mp25_set_clk_period,
11471200
},
@@ -1196,6 +1249,110 @@ static const struct stm32_fmc2_prop stm32_fmc2_mp25_child_props[] = {
11961249
},
11971250
};
11981251

1252+
static int stm32_fmc2_ebi_mp25_check_rif(struct stm32_fmc2_ebi *ebi, u32 resource)
1253+
{
1254+
u32 seccfgr, cidcfgr, semcr;
1255+
int cid, ret;
1256+
1257+
if (resource >= FMC2_MAX_RESOURCES)
1258+
return -EINVAL;
1259+
1260+
ret = regmap_read(ebi->regmap, FMC2_SECCFGR, &seccfgr);
1261+
if (ret)
1262+
return ret;
1263+
1264+
if (seccfgr & BIT(resource)) {
1265+
if (resource)
1266+
dev_err(ebi->dev, "resource %d is configured as secure\n",
1267+
resource);
1268+
1269+
return -EACCES;
1270+
}
1271+
1272+
ret = regmap_read(ebi->regmap, FMC2_CIDCFGR(resource), &cidcfgr);
1273+
if (ret)
1274+
return ret;
1275+
1276+
if (!(cidcfgr & FMC2_CIDCFGR_CFEN))
1277+
/* CID filtering is turned off: access granted */
1278+
return 0;
1279+
1280+
if (!(cidcfgr & FMC2_CIDCFGR_SEMEN)) {
1281+
/* Static CID mode */
1282+
cid = FIELD_GET(FMC2_CIDCFGR_SCID, cidcfgr);
1283+
if (cid != FMC2_CID1) {
1284+
if (resource)
1285+
dev_err(ebi->dev, "static CID%d set for resource %d\n",
1286+
cid, resource);
1287+
1288+
return -EACCES;
1289+
}
1290+
1291+
return 0;
1292+
}
1293+
1294+
/* Pass-list with semaphore mode */
1295+
if (!(cidcfgr & FMC2_CIDCFGR_SEMWLC1)) {
1296+
if (resource)
1297+
dev_err(ebi->dev, "CID1 is block-listed for resource %d\n",
1298+
resource);
1299+
1300+
return -EACCES;
1301+
}
1302+
1303+
ret = regmap_read(ebi->regmap, FMC2_SEMCR(resource), &semcr);
1304+
if (ret)
1305+
return ret;
1306+
1307+
if (!(semcr & FMC2_SEMCR_SEM_MUTEX)) {
1308+
regmap_update_bits(ebi->regmap, FMC2_SEMCR(resource),
1309+
FMC2_SEMCR_SEM_MUTEX, FMC2_SEMCR_SEM_MUTEX);
1310+
1311+
ret = regmap_read(ebi->regmap, FMC2_SEMCR(resource), &semcr);
1312+
if (ret)
1313+
return ret;
1314+
}
1315+
1316+
cid = FIELD_GET(FMC2_SEMCR_SEMCID, semcr);
1317+
if (cid != FMC2_CID1) {
1318+
if (resource)
1319+
dev_err(ebi->dev, "resource %d is already used by CID%d\n",
1320+
resource, cid);
1321+
1322+
return -EACCES;
1323+
}
1324+
1325+
ebi->sem_taken |= BIT(resource);
1326+
1327+
return 0;
1328+
}
1329+
1330+
static void stm32_fmc2_ebi_mp25_put_sems(struct stm32_fmc2_ebi *ebi)
1331+
{
1332+
unsigned int resource;
1333+
1334+
for (resource = 0; resource < FMC2_MAX_RESOURCES; resource++) {
1335+
if (!(ebi->sem_taken & BIT(resource)))
1336+
continue;
1337+
1338+
regmap_update_bits(ebi->regmap, FMC2_SEMCR(resource),
1339+
FMC2_SEMCR_SEM_MUTEX, 0);
1340+
}
1341+
}
1342+
1343+
static void stm32_fmc2_ebi_mp25_get_sems(struct stm32_fmc2_ebi *ebi)
1344+
{
1345+
unsigned int resource;
1346+
1347+
for (resource = 0; resource < FMC2_MAX_RESOURCES; resource++) {
1348+
if (!(ebi->sem_taken & BIT(resource)))
1349+
continue;
1350+
1351+
regmap_update_bits(ebi->regmap, FMC2_SEMCR(resource),
1352+
FMC2_SEMCR_SEM_MUTEX, FMC2_SEMCR_SEM_MUTEX);
1353+
}
1354+
}
1355+
11991356
static int stm32_fmc2_ebi_parse_prop(struct stm32_fmc2_ebi *ebi,
12001357
struct device_node *dev_node,
12011358
const struct stm32_fmc2_prop *prop,
@@ -1264,6 +1421,9 @@ static int stm32_fmc2_ebi_save_setup(struct stm32_fmc2_ebi *ebi)
12641421
int ret;
12651422

12661423
for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) {
1424+
if (!(ebi->bank_assigned & BIT(cs)))
1425+
continue;
1426+
12671427
ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &ebi->bcr[cs]);
12681428
ret |= regmap_read(ebi->regmap, FMC2_BTR(cs), &ebi->btr[cs]);
12691429
ret |= regmap_read(ebi->regmap, FMC2_BWTR(cs), &ebi->bwtr[cs]);
@@ -1293,14 +1453,20 @@ static int stm32_fmc2_ebi_mp25_save_setup(struct stm32_fmc2_ebi *ebi)
12931453
if (ret)
12941454
return ret;
12951455

1296-
return regmap_read(ebi->regmap, FMC2_CFGR, &ebi->cfgr);
1456+
if (ebi->access_granted)
1457+
ret = regmap_read(ebi->regmap, FMC2_CFGR, &ebi->cfgr);
1458+
1459+
return ret;
12971460
}
12981461

12991462
static void stm32_fmc2_ebi_set_setup(struct stm32_fmc2_ebi *ebi)
13001463
{
13011464
unsigned int cs;
13021465

13031466
for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) {
1467+
if (!(ebi->bank_assigned & BIT(cs)))
1468+
continue;
1469+
13041470
regmap_write(ebi->regmap, FMC2_BCR(cs), ebi->bcr[cs]);
13051471
regmap_write(ebi->regmap, FMC2_BTR(cs), ebi->btr[cs]);
13061472
regmap_write(ebi->regmap, FMC2_BWTR(cs), ebi->bwtr[cs]);
@@ -1316,7 +1482,9 @@ static void stm32_fmc2_ebi_mp1_set_setup(struct stm32_fmc2_ebi *ebi)
13161482
static void stm32_fmc2_ebi_mp25_set_setup(struct stm32_fmc2_ebi *ebi)
13171483
{
13181484
stm32_fmc2_ebi_set_setup(ebi);
1319-
regmap_write(ebi->regmap, FMC2_CFGR, ebi->cfgr);
1485+
1486+
if (ebi->access_granted)
1487+
regmap_write(ebi->regmap, FMC2_CFGR, ebi->cfgr);
13201488
}
13211489

13221490
static void stm32_fmc2_ebi_disable_banks(struct stm32_fmc2_ebi *ebi)
@@ -1359,13 +1527,19 @@ static int stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi)
13591527

13601528
static void stm32_fmc2_ebi_enable(struct stm32_fmc2_ebi *ebi)
13611529
{
1530+
if (!ebi->access_granted)
1531+
return;
1532+
13621533
regmap_update_bits(ebi->regmap, ebi->data->fmc2_enable_reg,
13631534
ebi->data->fmc2_enable_bit,
13641535
ebi->data->fmc2_enable_bit);
13651536
}
13661537

13671538
static void stm32_fmc2_ebi_disable(struct stm32_fmc2_ebi *ebi)
13681539
{
1540+
if (!ebi->access_granted)
1541+
return;
1542+
13691543
regmap_update_bits(ebi->regmap, ebi->data->fmc2_enable_reg,
13701544
ebi->data->fmc2_enable_bit, 0);
13711545
}
@@ -1424,6 +1598,15 @@ static int stm32_fmc2_ebi_parse_dt(struct stm32_fmc2_ebi *ebi)
14241598
return -EINVAL;
14251599
}
14261600

1601+
if (ebi->data->check_rif) {
1602+
ret = ebi->data->check_rif(ebi, bank + 1);
1603+
if (ret) {
1604+
dev_err(dev, "bank access failed: %d\n", bank);
1605+
of_node_put(child);
1606+
return ret;
1607+
}
1608+
}
1609+
14271610
if (bank < FMC2_MAX_EBI_CE) {
14281611
ret = stm32_fmc2_ebi_setup_cs(ebi, child, bank);
14291612
if (ret) {
@@ -1492,6 +1675,28 @@ static int stm32_fmc2_ebi_probe(struct platform_device *pdev)
14921675
reset_control_deassert(rstc);
14931676
}
14941677

1678+
/* Check if CFGR register can be modified */
1679+
ebi->access_granted = true;
1680+
if (ebi->data->check_rif) {
1681+
ret = ebi->data->check_rif(ebi, 0);
1682+
if (ret) {
1683+
u32 sr;
1684+
1685+
ebi->access_granted = false;
1686+
1687+
ret = regmap_read(ebi->regmap, FMC2_SR, &sr);
1688+
if (ret)
1689+
goto err_release;
1690+
1691+
/* In case of CFGR is secure, just check that the FMC2 is enabled */
1692+
if (sr & FMC2_SR_ISOST) {
1693+
dev_err(dev, "FMC2 is not ready to be used.\n");
1694+
ret = -EACCES;
1695+
goto err_release;
1696+
}
1697+
}
1698+
}
1699+
14951700
ret = stm32_fmc2_ebi_parse_dt(ebi);
14961701
if (ret)
14971702
goto err_release;
@@ -1507,6 +1712,8 @@ static int stm32_fmc2_ebi_probe(struct platform_device *pdev)
15071712
err_release:
15081713
stm32_fmc2_ebi_disable_banks(ebi);
15091714
stm32_fmc2_ebi_disable(ebi);
1715+
if (ebi->data->put_sems)
1716+
ebi->data->put_sems(ebi);
15101717
clk_disable_unprepare(ebi->clk);
15111718

15121719
return ret;
@@ -1519,6 +1726,8 @@ static void stm32_fmc2_ebi_remove(struct platform_device *pdev)
15191726
of_platform_depopulate(&pdev->dev);
15201727
stm32_fmc2_ebi_disable_banks(ebi);
15211728
stm32_fmc2_ebi_disable(ebi);
1729+
if (ebi->data->put_sems)
1730+
ebi->data->put_sems(ebi);
15221731
clk_disable_unprepare(ebi->clk);
15231732
}
15241733

@@ -1527,6 +1736,8 @@ static int __maybe_unused stm32_fmc2_ebi_suspend(struct device *dev)
15271736
struct stm32_fmc2_ebi *ebi = dev_get_drvdata(dev);
15281737

15291738
stm32_fmc2_ebi_disable(ebi);
1739+
if (ebi->data->put_sems)
1740+
ebi->data->put_sems(ebi);
15301741
clk_disable_unprepare(ebi->clk);
15311742
pinctrl_pm_select_sleep_state(dev);
15321743

@@ -1544,6 +1755,8 @@ static int __maybe_unused stm32_fmc2_ebi_resume(struct device *dev)
15441755
if (ret)
15451756
return ret;
15461757

1758+
if (ebi->data->get_sems)
1759+
ebi->data->get_sems(ebi);
15471760
ebi->data->set_setup(ebi);
15481761
stm32_fmc2_ebi_enable(ebi);
15491762

@@ -1570,6 +1783,9 @@ static const struct stm32_fmc2_ebi_data stm32_fmc2_ebi_mp25_data = {
15701783
.fmc2_enable_bit = FMC2_CFGR_FMC2EN,
15711784
.set_setup = stm32_fmc2_ebi_mp25_set_setup,
15721785
.save_setup = stm32_fmc2_ebi_mp25_save_setup,
1786+
.check_rif = stm32_fmc2_ebi_mp25_check_rif,
1787+
.put_sems = stm32_fmc2_ebi_mp25_put_sems,
1788+
.get_sems = stm32_fmc2_ebi_mp25_get_sems,
15731789
};
15741790

15751791
static const struct of_device_id stm32_fmc2_ebi_match[] = {

0 commit comments

Comments
 (0)