Skip to content

Commit efa9c5b

Browse files
VCASTMalexandrebelloni
authored andcommitted
rtc: stm32: add new st,stm32mp25-rtc compatible and check RIF configuration
Introduce new st,stm32mp25-rtc compatible. It is based on st,stm32mp1-rtc. Difference is that stm32mp25 soc implements a triple protection on RTC registers: - Secure bit based protection - Privileged context based protection - Compartment ID filtering based protection This driver will now check theses configurations before probing to avoid exceptions and fake reads on register. At this time, driver needs only to check two resources: INIT and ALARM_A. Other resources are not used. Resource isolation framework (RIF) is a comprehensive set of hardware blocks designed to enforce and manage isolation of STM32 hardware resources, like memory and peripherals. Link: https://www.st.com/resource/en/reference_manual/rm0457-stm32mp25xx-advanced-armbased-3264bit-mpus-stmicroelectronics.pdf#page=4081 Signed-off-by: Valentin Caron <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexandre Belloni <[email protected]>
1 parent 1746a61 commit efa9c5b

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

drivers/rtc/rtc-stm32.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#include <linux/bcd.h>
8+
#include <linux/bitfield.h>
89
#include <linux/clk.h>
910
#include <linux/errno.h>
1011
#include <linux/iopoll.h>
@@ -83,6 +84,18 @@
8384
#define STM32_RTC_VERR_MAJREV_SHIFT 4
8485
#define STM32_RTC_VERR_MAJREV GENMASK(7, 4)
8586

87+
/* STM32_RTC_SECCFGR bit fields */
88+
#define STM32_RTC_SECCFGR 0x20
89+
#define STM32_RTC_SECCFGR_ALRA_SEC BIT(0)
90+
#define STM32_RTC_SECCFGR_INIT_SEC BIT(14)
91+
#define STM32_RTC_SECCFGR_SEC BIT(15)
92+
93+
/* STM32_RTC_RXCIDCFGR bit fields */
94+
#define STM32_RTC_RXCIDCFGR(x) (0x80 + 0x4 * (x))
95+
#define STM32_RTC_RXCIDCFGR_CFEN BIT(0)
96+
#define STM32_RTC_RXCIDCFGR_CID GENMASK(6, 4)
97+
#define STM32_RTC_RXCIDCFGR_CID1 1
98+
8699
/* STM32_RTC_WPR key constants */
87100
#define RTC_WPR_1ST_KEY 0xCA
88101
#define RTC_WPR_2ND_KEY 0x53
@@ -120,6 +133,7 @@ struct stm32_rtc_data {
120133
bool has_pclk;
121134
bool need_dbp;
122135
bool need_accuracy;
136+
bool rif_protected;
123137
};
124138

125139
struct stm32_rtc {
@@ -134,6 +148,14 @@ struct stm32_rtc {
134148
int irq_alarm;
135149
};
136150

151+
struct stm32_rtc_rif_resource {
152+
unsigned int num;
153+
u32 bit;
154+
};
155+
156+
static const struct stm32_rtc_rif_resource STM32_RTC_RES_ALRA = {0, STM32_RTC_SECCFGR_ALRA_SEC};
157+
static const struct stm32_rtc_rif_resource STM32_RTC_RES_INIT = {5, STM32_RTC_SECCFGR_INIT_SEC};
158+
137159
static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc)
138160
{
139161
const struct stm32_rtc_registers *regs = &rtc->data->regs;
@@ -553,6 +575,7 @@ static const struct stm32_rtc_data stm32_rtc_data = {
553575
.has_pclk = false,
554576
.need_dbp = true,
555577
.need_accuracy = false,
578+
.rif_protected = false,
556579
.regs = {
557580
.tr = 0x00,
558581
.dr = 0x04,
@@ -575,6 +598,7 @@ static const struct stm32_rtc_data stm32h7_rtc_data = {
575598
.has_pclk = true,
576599
.need_dbp = true,
577600
.need_accuracy = false,
601+
.rif_protected = false,
578602
.regs = {
579603
.tr = 0x00,
580604
.dr = 0x04,
@@ -606,6 +630,7 @@ static const struct stm32_rtc_data stm32mp1_data = {
606630
.has_pclk = true,
607631
.need_dbp = false,
608632
.need_accuracy = true,
633+
.rif_protected = false,
609634
.regs = {
610635
.tr = 0x00,
611636
.dr = 0x04,
@@ -624,14 +649,57 @@ static const struct stm32_rtc_data stm32mp1_data = {
624649
.clear_events = stm32mp1_rtc_clear_events,
625650
};
626651

652+
static const struct stm32_rtc_data stm32mp25_data = {
653+
.has_pclk = true,
654+
.need_dbp = false,
655+
.need_accuracy = true,
656+
.rif_protected = true,
657+
.regs = {
658+
.tr = 0x00,
659+
.dr = 0x04,
660+
.cr = 0x18,
661+
.isr = 0x0C, /* named RTC_ICSR on stm32mp25 */
662+
.prer = 0x10,
663+
.alrmar = 0x40,
664+
.wpr = 0x24,
665+
.sr = 0x50,
666+
.scr = 0x5C,
667+
.verr = 0x3F4,
668+
},
669+
.events = {
670+
.alra = STM32_RTC_SR_ALRA,
671+
},
672+
.clear_events = stm32mp1_rtc_clear_events,
673+
};
674+
627675
static const struct of_device_id stm32_rtc_of_match[] = {
628676
{ .compatible = "st,stm32-rtc", .data = &stm32_rtc_data },
629677
{ .compatible = "st,stm32h7-rtc", .data = &stm32h7_rtc_data },
630678
{ .compatible = "st,stm32mp1-rtc", .data = &stm32mp1_data },
679+
{ .compatible = "st,stm32mp25-rtc", .data = &stm32mp25_data },
631680
{}
632681
};
633682
MODULE_DEVICE_TABLE(of, stm32_rtc_of_match);
634683

684+
static int stm32_rtc_check_rif(struct stm32_rtc *stm32_rtc,
685+
struct stm32_rtc_rif_resource res)
686+
{
687+
u32 rxcidcfgr = readl_relaxed(stm32_rtc->base + STM32_RTC_RXCIDCFGR(res.num));
688+
u32 seccfgr;
689+
690+
/* Check if RTC available for our CID */
691+
if ((rxcidcfgr & STM32_RTC_RXCIDCFGR_CFEN) &&
692+
(FIELD_GET(STM32_RTC_RXCIDCFGR_CID, rxcidcfgr) != STM32_RTC_RXCIDCFGR_CID1))
693+
return -EACCES;
694+
695+
/* Check if RTC available for non secure world */
696+
seccfgr = readl_relaxed(stm32_rtc->base + STM32_RTC_SECCFGR);
697+
if ((seccfgr & STM32_RTC_SECCFGR_SEC) | (seccfgr & res.bit))
698+
return -EACCES;
699+
700+
return 0;
701+
}
702+
635703
static int stm32_rtc_init(struct platform_device *pdev,
636704
struct stm32_rtc *rtc)
637705
{
@@ -787,6 +855,16 @@ static int stm32_rtc_probe(struct platform_device *pdev)
787855
regmap_update_bits(rtc->dbp, rtc->dbp_reg,
788856
rtc->dbp_mask, rtc->dbp_mask);
789857

858+
if (rtc->data->rif_protected) {
859+
ret = stm32_rtc_check_rif(rtc, STM32_RTC_RES_INIT);
860+
if (!ret)
861+
ret = stm32_rtc_check_rif(rtc, STM32_RTC_RES_ALRA);
862+
if (ret) {
863+
dev_err(&pdev->dev, "Failed to probe RTC due to RIF configuration\n");
864+
goto err;
865+
}
866+
}
867+
790868
/*
791869
* After a system reset, RTC_ISR.INITS flag can be read to check if
792870
* the calendar has been initialized or not. INITS flag is reset by a

0 commit comments

Comments
 (0)