xref: /optee_os/core/drivers/stm32_rtc.c (revision e419bc7f385ca2fdf46975518a20b131590510fd)
1*e419bc7fSGatien Chevallier // SPDX-License-Identifier: BSD-2-Clause
2*e419bc7fSGatien Chevallier /*
3*e419bc7fSGatien Chevallier  * Copyright (C) 2018-2024, STMicroelectronics
4*e419bc7fSGatien Chevallier  */
5*e419bc7fSGatien Chevallier #include <assert.h>
6*e419bc7fSGatien Chevallier #include <drivers/clk.h>
7*e419bc7fSGatien Chevallier #include <drivers/clk_dt.h>
8*e419bc7fSGatien Chevallier #include <drivers/rtc.h>
9*e419bc7fSGatien Chevallier #include <drivers/stm32_rif.h>
10*e419bc7fSGatien Chevallier #include <io.h>
11*e419bc7fSGatien Chevallier #include <kernel/dt.h>
12*e419bc7fSGatien Chevallier #include <kernel/dt_driver.h>
13*e419bc7fSGatien Chevallier #include <kernel/panic.h>
14*e419bc7fSGatien Chevallier #include <libfdt.h>
15*e419bc7fSGatien Chevallier #include <mm/core_memprot.h>
16*e419bc7fSGatien Chevallier 
17*e419bc7fSGatien Chevallier /*
18*e419bc7fSGatien Chevallier  * Registers
19*e419bc7fSGatien Chevallier  */
20*e419bc7fSGatien Chevallier #define RTC_TR				U(0x00)
21*e419bc7fSGatien Chevallier #define RTC_DR				U(0x04)
22*e419bc7fSGatien Chevallier #define RTC_SSR				U(0x08)
23*e419bc7fSGatien Chevallier #define RTC_ICSR			U(0x0C)
24*e419bc7fSGatien Chevallier #define RTC_PRER			U(0x10)
25*e419bc7fSGatien Chevallier #define RTC_WUTR			U(0x14)
26*e419bc7fSGatien Chevallier #define RTC_CR				U(0x18)
27*e419bc7fSGatien Chevallier #define RTC_PRIVCFGR			U(0x1C)
28*e419bc7fSGatien Chevallier /* RTC_SMCR is linked to RTC3v1_2 */
29*e419bc7fSGatien Chevallier #define RTC_SMCR			U(0x20)
30*e419bc7fSGatien Chevallier /* RTC_SECCFGR is linked to RTC3v3_2 and above */
31*e419bc7fSGatien Chevallier #define RTC_SECCFGR			U(0x20)
32*e419bc7fSGatien Chevallier #define RTC_WPR				U(0x24)
33*e419bc7fSGatien Chevallier #define RTC_CALR			U(0x28)
34*e419bc7fSGatien Chevallier #define RTC_SHIFTR			U(0x2C)
35*e419bc7fSGatien Chevallier #define RTC_TSTR			U(0x30)
36*e419bc7fSGatien Chevallier #define RTC_TSDR			U(0x34)
37*e419bc7fSGatien Chevallier #define RTC_TSSSR			U(0x38)
38*e419bc7fSGatien Chevallier #define RTC_ALRMAR			U(0x40)
39*e419bc7fSGatien Chevallier #define RTC_ALRMASSR			U(0x44)
40*e419bc7fSGatien Chevallier #define RTC_ALRMBR			U(0x48)
41*e419bc7fSGatien Chevallier #define RTC_ALRMBSSR			U(0x4C)
42*e419bc7fSGatien Chevallier #define RTC_SR				U(0x50)
43*e419bc7fSGatien Chevallier #define RTC_SCR				U(0x5C)
44*e419bc7fSGatien Chevallier #define RTC_OR				U(0x60)
45*e419bc7fSGatien Chevallier #define RTC_CIDCFGR(x)			(U(0x80) + U(0x4) * (x))
46*e419bc7fSGatien Chevallier 
47*e419bc7fSGatien Chevallier #define RTC_TR_SU_MASK			GENMASK_32(3, 0)
48*e419bc7fSGatien Chevallier #define RTC_TR_ST_MASK			GENMASK_32(6, 4)
49*e419bc7fSGatien Chevallier #define RTC_TR_ST_SHIFT			U(4)
50*e419bc7fSGatien Chevallier #define RTC_TR_MNU_MASK			GENMASK_32(11, 8)
51*e419bc7fSGatien Chevallier #define RTC_TR_MNU_SHIFT		U(8)
52*e419bc7fSGatien Chevallier #define RTC_TR_MNT_MASK			GENMASK_32(14, 12)
53*e419bc7fSGatien Chevallier #define RTC_TR_MNT_SHIFT		U(12)
54*e419bc7fSGatien Chevallier #define RTC_TR_HU_MASK			GENMASK_32(19, 16)
55*e419bc7fSGatien Chevallier #define RTC_TR_HU_SHIFT			U(16)
56*e419bc7fSGatien Chevallier #define RTC_TR_HT_MASK			GENMASK_32(21, 20)
57*e419bc7fSGatien Chevallier #define RTC_TR_HT_SHIFT			U(20)
58*e419bc7fSGatien Chevallier #define RTC_TR_PM			BIT(22)
59*e419bc7fSGatien Chevallier 
60*e419bc7fSGatien Chevallier #define RTC_DR_DU_MASK			GENMASK_32(3, 0)
61*e419bc7fSGatien Chevallier #define RTC_DR_DT_MASK			GENMASK_32(5, 4)
62*e419bc7fSGatien Chevallier #define RTC_DR_DT_SHIFT			U(4)
63*e419bc7fSGatien Chevallier #define RTC_DR_MU_MASK			GENMASK_32(11, 8)
64*e419bc7fSGatien Chevallier #define RTC_DR_MU_SHIFT			U(8)
65*e419bc7fSGatien Chevallier #define RTC_DR_MT_MASK			BIT(12)
66*e419bc7fSGatien Chevallier #define RTC_DR_MT_SHIFT			U(12)
67*e419bc7fSGatien Chevallier #define RTC_DR_WDU_MASK			GENMASK_32(15, 13)
68*e419bc7fSGatien Chevallier #define RTC_DR_WDU_SHIFT		U(13)
69*e419bc7fSGatien Chevallier #define RTC_DR_YU_MASK			GENMASK_32(19, 16)
70*e419bc7fSGatien Chevallier #define RTC_DR_YU_SHIFT			U(16)
71*e419bc7fSGatien Chevallier #define RTC_DR_YT_MASK			GENMASK_32(23, 20)
72*e419bc7fSGatien Chevallier #define RTC_DR_YT_SHIFT			U(20)
73*e419bc7fSGatien Chevallier 
74*e419bc7fSGatien Chevallier #define RTC_SSR_SS_MASK			GENMASK_32(15, 0)
75*e419bc7fSGatien Chevallier 
76*e419bc7fSGatien Chevallier #define RTC_ICSR_RSF			BIT(5)
77*e419bc7fSGatien Chevallier #define RTC_ICSR_INITF			BIT(6)
78*e419bc7fSGatien Chevallier #define RTC_ICSR_INIT			BIT(7)
79*e419bc7fSGatien Chevallier 
80*e419bc7fSGatien Chevallier #define RTC_PRER_PREDIV_S_MASK		GENMASK_32(14, 0)
81*e419bc7fSGatien Chevallier 
82*e419bc7fSGatien Chevallier #define RTC_CR_BYPSHAD			BIT(5)
83*e419bc7fSGatien Chevallier #define RTC_CR_BYPSHAD_SHIFT		U(5)
84*e419bc7fSGatien Chevallier #define RTC_CR_TAMPTS			BIT(25)
85*e419bc7fSGatien Chevallier 
86*e419bc7fSGatien Chevallier #define RTC_PRIVCFGR_VALUES		GENMASK_32(3, 0)
87*e419bc7fSGatien Chevallier #define RTC_PRIVCFGR_VALUES_TO_SHIFT	GENMASK_32(5, 4)
88*e419bc7fSGatien Chevallier #define RTC_PRIVCFGR_SHIFT		U(9)
89*e419bc7fSGatien Chevallier #define RTC_PRIVCFGR_MASK		(GENMASK_32(14, 13) | GENMASK_32(3, 0))
90*e419bc7fSGatien Chevallier #define RTC_PRIVCFGR_FULL_PRIV		BIT(15)
91*e419bc7fSGatien Chevallier 
92*e419bc7fSGatien Chevallier #define RTC_SMCR_TS_DPROT		BIT(3)
93*e419bc7fSGatien Chevallier 
94*e419bc7fSGatien Chevallier #define RTC_SECCFGR_VALUES		GENMASK_32(3, 0)
95*e419bc7fSGatien Chevallier #define RTC_SECCFGR_TS_SEC		BIT(3)
96*e419bc7fSGatien Chevallier #define RTC_SECCFGR_VALUES_TO_SHIFT	GENMASK_32(5, 4)
97*e419bc7fSGatien Chevallier #define RTC_SECCFGR_SHIFT		U(9)
98*e419bc7fSGatien Chevallier #define RTC_SECCFGR_MASK		(GENMASK_32(14, 13) | GENMASK_32(3, 0))
99*e419bc7fSGatien Chevallier #define RTC_SECCFGR_FULL_SEC		BIT(15)
100*e419bc7fSGatien Chevallier 
101*e419bc7fSGatien Chevallier #define RTC_WPR_KEY1			U(0xCA)
102*e419bc7fSGatien Chevallier #define RTC_WPR_KEY2			U(0x53)
103*e419bc7fSGatien Chevallier #define RTC_WPR_KEY_LOCK		U(0xFF)
104*e419bc7fSGatien Chevallier 
105*e419bc7fSGatien Chevallier #define RTC_TSDR_MU_MASK		GENMASK_32(11, 8)
106*e419bc7fSGatien Chevallier #define RTC_TSDR_MU_SHIFT		U(8)
107*e419bc7fSGatien Chevallier #define RTC_TSDR_DT_MASK		GENMASK_32(5, 4)
108*e419bc7fSGatien Chevallier #define RTC_TSDR_DT_SHIFT		U(4)
109*e419bc7fSGatien Chevallier #define RTC_TSDR_DU_MASK		GENMASK_32(3, 0)
110*e419bc7fSGatien Chevallier #define RTC_TSDR_DU_SHIFT		U(0)
111*e419bc7fSGatien Chevallier 
112*e419bc7fSGatien Chevallier #define RTC_SR_TSF			BIT(3)
113*e419bc7fSGatien Chevallier #define RTC_SR_TSOVF			BIT(4)
114*e419bc7fSGatien Chevallier 
115*e419bc7fSGatien Chevallier #define RTC_SCR_CTSF			BIT(3)
116*e419bc7fSGatien Chevallier #define RTC_SCR_CTSOVF			BIT(4)
117*e419bc7fSGatien Chevallier 
118*e419bc7fSGatien Chevallier #define RTC_CIDCFGR_SCID_MASK		GENMASK_32(6, 4)
119*e419bc7fSGatien Chevallier #define RTC_CIDCFGR_SCID_MASK_SHIFT	U(4)
120*e419bc7fSGatien Chevallier #define RTC_CIDCFGR_CONF_MASK		(_CIDCFGR_CFEN |	 \
121*e419bc7fSGatien Chevallier 					 RTC_CIDCFGR_SCID_MASK)
122*e419bc7fSGatien Chevallier 
123*e419bc7fSGatien Chevallier /*
124*e419bc7fSGatien Chevallier  * RIF miscellaneous
125*e419bc7fSGatien Chevallier  */
126*e419bc7fSGatien Chevallier #define RTC_NB_RIF_RESOURCES		U(6)
127*e419bc7fSGatien Chevallier 
128*e419bc7fSGatien Chevallier #define RTC_RIF_FULL_PRIVILEGED		U(0x3F)
129*e419bc7fSGatien Chevallier #define RTC_RIF_FULL_SECURED		U(0x3F)
130*e419bc7fSGatien Chevallier 
131*e419bc7fSGatien Chevallier #define RTC_NB_MAX_CID_SUPPORTED	U(7)
132*e419bc7fSGatien Chevallier 
133*e419bc7fSGatien Chevallier /*
134*e419bc7fSGatien Chevallier  * Driver miscellaneous
135*e419bc7fSGatien Chevallier  */
136*e419bc7fSGatien Chevallier #define RTC_RES_TIMESTAMP		U(3)
137*e419bc7fSGatien Chevallier #define RTC_RES_CALIBRATION		U(4)
138*e419bc7fSGatien Chevallier #define RTC_RES_INITIALIZATION		U(5)
139*e419bc7fSGatien Chevallier 
140*e419bc7fSGatien Chevallier #define RTC_FLAGS_READ_TWICE		BIT(0)
141*e419bc7fSGatien Chevallier 
142*e419bc7fSGatien Chevallier #define TIMEOUT_US_RTC_SHADOW		U(10000)
143*e419bc7fSGatien Chevallier #define TIMEOUT_US_RTC_GENERIC		U(100000)
144*e419bc7fSGatien Chevallier 
145*e419bc7fSGatien Chevallier #define YEAR_REF			ULL(2000)
146*e419bc7fSGatien Chevallier #define YEAR_MAX			(YEAR_REF + ULL(99))
147*e419bc7fSGatien Chevallier 
148*e419bc7fSGatien Chevallier struct rtc_compat {
149*e419bc7fSGatien Chevallier 	bool has_seccfgr;
150*e419bc7fSGatien Chevallier 	bool has_rif_support;
151*e419bc7fSGatien Chevallier };
152*e419bc7fSGatien Chevallier 
153*e419bc7fSGatien Chevallier /*
154*e419bc7fSGatien Chevallier  * struct rtc_device - RTC device data
155*e419bc7fSGatien Chevallier  * @base: RTC IOMEM base address
156*e419bc7fSGatien Chevallier  * @compat: RTC compatible data
157*e419bc7fSGatien Chevallier  * @pclk: RTC bus clock
158*e419bc7fSGatien Chevallier  * @rtc_ck: RTC kernel clock
159*e419bc7fSGatien Chevallier  * @conf_data: RTC RIF configuration data, when supported
160*e419bc7fSGatien Chevallier  * @nb_res: Number of protectible RTC resources
161*e419bc7fSGatien Chevallier  * @flags: RTC driver flags
162*e419bc7fSGatien Chevallier  * @is_secured: True if the RTC is fully secured
163*e419bc7fSGatien Chevallier  */
164*e419bc7fSGatien Chevallier struct rtc_device {
165*e419bc7fSGatien Chevallier 	struct io_pa_va base;
166*e419bc7fSGatien Chevallier 	const struct rtc_compat *compat;
167*e419bc7fSGatien Chevallier 	struct clk *pclk;
168*e419bc7fSGatien Chevallier 	struct clk *rtc_ck;
169*e419bc7fSGatien Chevallier 	struct rif_conf_data *conf_data;
170*e419bc7fSGatien Chevallier 	unsigned int nb_res;
171*e419bc7fSGatien Chevallier 	uint8_t flags;
172*e419bc7fSGatien Chevallier 	bool is_secured;
173*e419bc7fSGatien Chevallier };
174*e419bc7fSGatien Chevallier 
175*e419bc7fSGatien Chevallier /* Expect a single RTC instance */
176*e419bc7fSGatien Chevallier static struct rtc_device rtc_dev;
177*e419bc7fSGatien Chevallier 
178*e419bc7fSGatien Chevallier static vaddr_t get_base(void)
179*e419bc7fSGatien Chevallier {
180*e419bc7fSGatien Chevallier 	assert(rtc_dev.base.pa);
181*e419bc7fSGatien Chevallier 
182*e419bc7fSGatien Chevallier 	return io_pa_or_va(&rtc_dev.base, 1);
183*e419bc7fSGatien Chevallier }
184*e419bc7fSGatien Chevallier 
185*e419bc7fSGatien Chevallier static void stm32_rtc_write_unprotect(void)
186*e419bc7fSGatien Chevallier {
187*e419bc7fSGatien Chevallier 	vaddr_t rtc_base = get_base();
188*e419bc7fSGatien Chevallier 
189*e419bc7fSGatien Chevallier 	io_write32(rtc_base + RTC_WPR, RTC_WPR_KEY1);
190*e419bc7fSGatien Chevallier 	io_write32(rtc_base + RTC_WPR, RTC_WPR_KEY2);
191*e419bc7fSGatien Chevallier }
192*e419bc7fSGatien Chevallier 
193*e419bc7fSGatien Chevallier static void stm32_rtc_write_protect(void)
194*e419bc7fSGatien Chevallier {
195*e419bc7fSGatien Chevallier 	vaddr_t rtc_base = get_base();
196*e419bc7fSGatien Chevallier 
197*e419bc7fSGatien Chevallier 	io_write32(rtc_base + RTC_WPR, RTC_WPR_KEY_LOCK);
198*e419bc7fSGatien Chevallier }
199*e419bc7fSGatien Chevallier 
200*e419bc7fSGatien Chevallier static bool stm32_rtc_get_bypshad(void)
201*e419bc7fSGatien Chevallier {
202*e419bc7fSGatien Chevallier 	return io_read32(get_base() + RTC_CR) & RTC_CR_BYPSHAD;
203*e419bc7fSGatien Chevallier }
204*e419bc7fSGatien Chevallier 
205*e419bc7fSGatien Chevallier /* Get the subsecond value. */
206*e419bc7fSGatien Chevallier static uint32_t stm32_rtc_get_subsecond(uint32_t ssr)
207*e419bc7fSGatien Chevallier {
208*e419bc7fSGatien Chevallier 	uint32_t prediv_s = io_read32(get_base() + RTC_PRER) &
209*e419bc7fSGatien Chevallier 			    RTC_PRER_PREDIV_S_MASK;
210*e419bc7fSGatien Chevallier 
211*e419bc7fSGatien Chevallier 	return prediv_s - ssr;
212*e419bc7fSGatien Chevallier }
213*e419bc7fSGatien Chevallier 
214*e419bc7fSGatien Chevallier /*
215*e419bc7fSGatien Chevallier  * Get the subsecond scale.
216*e419bc7fSGatien Chevallier  *
217*e419bc7fSGatien Chevallier  * Number of subseconds in a second is linked to RTC PREDIV_S value.
218*e419bc7fSGatien Chevallier  * The higher PREDIV_S is, the more subsecond is precise.
219*e419bc7fSGatien Chevallier  */
220*e419bc7fSGatien Chevallier static uint32_t stm32_rtc_get_subsecond_scale(void)
221*e419bc7fSGatien Chevallier {
222*e419bc7fSGatien Chevallier 	return (io_read32(get_base() + RTC_PRER) & RTC_PRER_PREDIV_S_MASK) + 1;
223*e419bc7fSGatien Chevallier }
224*e419bc7fSGatien Chevallier 
225*e419bc7fSGatien Chevallier static bool cid1_has_access(unsigned int resource)
226*e419bc7fSGatien Chevallier {
227*e419bc7fSGatien Chevallier 	uint32_t cidcfgr = io_read32(get_base() + RTC_CIDCFGR(resource));
228*e419bc7fSGatien Chevallier 
229*e419bc7fSGatien Chevallier 	return !(cidcfgr & _CIDCFGR_CFEN) ||
230*e419bc7fSGatien Chevallier 	       get_field_u32(cidcfgr, RTC_CIDCFGR_SCID_MASK) == RIF_CID1;
231*e419bc7fSGatien Chevallier }
232*e419bc7fSGatien Chevallier 
233*e419bc7fSGatien Chevallier static TEE_Result check_rif_config(void)
234*e419bc7fSGatien Chevallier {
235*e419bc7fSGatien Chevallier 	if (!cid1_has_access(RTC_RES_TIMESTAMP) ||
236*e419bc7fSGatien Chevallier 	    !cid1_has_access(RTC_RES_CALIBRATION) ||
237*e419bc7fSGatien Chevallier 	    !cid1_has_access(RTC_RES_INITIALIZATION))
238*e419bc7fSGatien Chevallier 		return TEE_ERROR_ACCESS_DENIED;
239*e419bc7fSGatien Chevallier 
240*e419bc7fSGatien Chevallier 	return TEE_SUCCESS;
241*e419bc7fSGatien Chevallier }
242*e419bc7fSGatien Chevallier 
243*e419bc7fSGatien Chevallier static void apply_rif_config(bool is_tdcid)
244*e419bc7fSGatien Chevallier {
245*e419bc7fSGatien Chevallier 	vaddr_t base = get_base();
246*e419bc7fSGatien Chevallier 	unsigned int shifted_values = 0;
247*e419bc7fSGatien Chevallier 	uint32_t seccfgr = 0;
248*e419bc7fSGatien Chevallier 	uint32_t privcfgr = 0;
249*e419bc7fSGatien Chevallier 	uint32_t access_mask_reg = 0;
250*e419bc7fSGatien Chevallier 	unsigned int i = 0;
251*e419bc7fSGatien Chevallier 
252*e419bc7fSGatien Chevallier 	if (!rtc_dev.conf_data)
253*e419bc7fSGatien Chevallier 		return;
254*e419bc7fSGatien Chevallier 
255*e419bc7fSGatien Chevallier 	/* Build access mask for RTC_SECCFGR and RTC_PRIVCFGR */
256*e419bc7fSGatien Chevallier 	for (i = 0; i < RTC_NB_RIF_RESOURCES; i++) {
257*e419bc7fSGatien Chevallier 		if (rtc_dev.conf_data->access_mask[0] & BIT(i)) {
258*e419bc7fSGatien Chevallier 			if (i <= RTC_RES_TIMESTAMP)
259*e419bc7fSGatien Chevallier 				access_mask_reg |= BIT(i);
260*e419bc7fSGatien Chevallier 			else
261*e419bc7fSGatien Chevallier 				access_mask_reg |= BIT(i) << RTC_SECCFGR_SHIFT;
262*e419bc7fSGatien Chevallier 		}
263*e419bc7fSGatien Chevallier 	}
264*e419bc7fSGatien Chevallier 
265*e419bc7fSGatien Chevallier 	for (i = 0; i < RTC_NB_RIF_RESOURCES; i++) {
266*e419bc7fSGatien Chevallier 		if (!(BIT(i) & rtc_dev.conf_data->access_mask[0]))
267*e419bc7fSGatien Chevallier 			continue;
268*e419bc7fSGatien Chevallier 
269*e419bc7fSGatien Chevallier 		/*
270*e419bc7fSGatien Chevallier 		 * When TDCID, OP-TEE should be the one to set the CID filtering
271*e419bc7fSGatien Chevallier 		 * configuration. Clearing previous configuration prevents
272*e419bc7fSGatien Chevallier 		 * undesired events during the only legitimate configuration.
273*e419bc7fSGatien Chevallier 		 */
274*e419bc7fSGatien Chevallier 		if (is_tdcid)
275*e419bc7fSGatien Chevallier 			io_clrbits32(base + RTC_CIDCFGR(i),
276*e419bc7fSGatien Chevallier 				     RTC_CIDCFGR_CONF_MASK);
277*e419bc7fSGatien Chevallier 	}
278*e419bc7fSGatien Chevallier 
279*e419bc7fSGatien Chevallier 	/* Security RIF configuration */
280*e419bc7fSGatien Chevallier 	seccfgr = rtc_dev.conf_data->sec_conf[0];
281*e419bc7fSGatien Chevallier 
282*e419bc7fSGatien Chevallier 	/* Check if all resources must be secured */
283*e419bc7fSGatien Chevallier 	if (seccfgr == RTC_RIF_FULL_SECURED) {
284*e419bc7fSGatien Chevallier 		io_setbits32(base + RTC_SECCFGR, RTC_SECCFGR_FULL_SEC);
285*e419bc7fSGatien Chevallier 		rtc_dev.is_secured = true;
286*e419bc7fSGatien Chevallier 
287*e419bc7fSGatien Chevallier 		if (!(io_read32(base + RTC_SECCFGR) & RTC_SECCFGR_FULL_SEC))
288*e419bc7fSGatien Chevallier 			panic("Bad RTC seccfgr configuration");
289*e419bc7fSGatien Chevallier 	}
290*e419bc7fSGatien Chevallier 
291*e419bc7fSGatien Chevallier 	/* Shift some values to align with the register */
292*e419bc7fSGatien Chevallier 	shifted_values = SHIFT_U32(seccfgr & RTC_SECCFGR_VALUES_TO_SHIFT,
293*e419bc7fSGatien Chevallier 				   RTC_SECCFGR_SHIFT);
294*e419bc7fSGatien Chevallier 	seccfgr = (seccfgr & RTC_SECCFGR_VALUES) + shifted_values;
295*e419bc7fSGatien Chevallier 
296*e419bc7fSGatien Chevallier 	io_clrsetbits32(base + RTC_SECCFGR,
297*e419bc7fSGatien Chevallier 			RTC_SECCFGR_MASK & access_mask_reg, seccfgr);
298*e419bc7fSGatien Chevallier 
299*e419bc7fSGatien Chevallier 	/* Privilege RIF configuration */
300*e419bc7fSGatien Chevallier 	privcfgr = rtc_dev.conf_data->priv_conf[0];
301*e419bc7fSGatien Chevallier 
302*e419bc7fSGatien Chevallier 	/* Check if all resources must be privileged */
303*e419bc7fSGatien Chevallier 	if (privcfgr == RTC_RIF_FULL_PRIVILEGED) {
304*e419bc7fSGatien Chevallier 		io_setbits32(base + RTC_PRIVCFGR, RTC_PRIVCFGR_FULL_PRIV);
305*e419bc7fSGatien Chevallier 
306*e419bc7fSGatien Chevallier 		if (!(io_read32(base + RTC_PRIVCFGR) & RTC_PRIVCFGR_FULL_PRIV))
307*e419bc7fSGatien Chevallier 			panic("Bad RTC privcfgr configuration");
308*e419bc7fSGatien Chevallier 	}
309*e419bc7fSGatien Chevallier 
310*e419bc7fSGatien Chevallier 	/* Shift some values to align with the register */
311*e419bc7fSGatien Chevallier 	shifted_values = SHIFT_U32(privcfgr & RTC_PRIVCFGR_VALUES_TO_SHIFT,
312*e419bc7fSGatien Chevallier 				   RTC_PRIVCFGR_SHIFT);
313*e419bc7fSGatien Chevallier 	privcfgr = (privcfgr & RTC_PRIVCFGR_VALUES) + shifted_values;
314*e419bc7fSGatien Chevallier 
315*e419bc7fSGatien Chevallier 	io_clrsetbits32(base + RTC_PRIVCFGR,
316*e419bc7fSGatien Chevallier 			RTC_PRIVCFGR_MASK & access_mask_reg, privcfgr);
317*e419bc7fSGatien Chevallier 
318*e419bc7fSGatien Chevallier 	if (!is_tdcid)
319*e419bc7fSGatien Chevallier 		return;
320*e419bc7fSGatien Chevallier 
321*e419bc7fSGatien Chevallier 	for (i = 0; i < RTC_NB_RIF_RESOURCES; i++) {
322*e419bc7fSGatien Chevallier 		if (!(BIT(i) & rtc_dev.conf_data->access_mask[0]))
323*e419bc7fSGatien Chevallier 			continue;
324*e419bc7fSGatien Chevallier 		/*
325*e419bc7fSGatien Chevallier 		 * When at least one resource has CID filtering enabled,
326*e419bc7fSGatien Chevallier 		 * the RTC_PRIVCFGR_FULL_PRIV and RTC_SECCFGR_FULL_SEC bits are
327*e419bc7fSGatien Chevallier 		 * cleared.
328*e419bc7fSGatien Chevallier 		 */
329*e419bc7fSGatien Chevallier 		io_clrsetbits32(base + RTC_CIDCFGR(i),
330*e419bc7fSGatien Chevallier 				RTC_CIDCFGR_CONF_MASK,
331*e419bc7fSGatien Chevallier 				rtc_dev.conf_data->cid_confs[i]);
332*e419bc7fSGatien Chevallier 	}
333*e419bc7fSGatien Chevallier }
334*e419bc7fSGatien Chevallier 
335*e419bc7fSGatien Chevallier static TEE_Result parse_dt(const void *fdt, int node)
336*e419bc7fSGatien Chevallier {
337*e419bc7fSGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
338*e419bc7fSGatien Chevallier 	const fdt32_t *cuint = NULL;
339*e419bc7fSGatien Chevallier 	size_t reg_size = 0;
340*e419bc7fSGatien Chevallier 	unsigned int i = 0;
341*e419bc7fSGatien Chevallier 	int lenp = 0;
342*e419bc7fSGatien Chevallier 
343*e419bc7fSGatien Chevallier 	if (fdt_reg_info(fdt, node, &rtc_dev.base.pa, &reg_size))
344*e419bc7fSGatien Chevallier 		panic();
345*e419bc7fSGatien Chevallier 
346*e419bc7fSGatien Chevallier 	io_pa_or_va(&rtc_dev.base, reg_size);
347*e419bc7fSGatien Chevallier 	assert(rtc_dev.base.va);
348*e419bc7fSGatien Chevallier 
349*e419bc7fSGatien Chevallier 	res = clk_dt_get_by_name(fdt, node, "pclk", &rtc_dev.pclk);
350*e419bc7fSGatien Chevallier 	if (res)
351*e419bc7fSGatien Chevallier 		return res;
352*e419bc7fSGatien Chevallier 
353*e419bc7fSGatien Chevallier 	res = clk_dt_get_by_name(fdt, node, "rtc_ck", &rtc_dev.rtc_ck);
354*e419bc7fSGatien Chevallier 	if (res)
355*e419bc7fSGatien Chevallier 		return res;
356*e419bc7fSGatien Chevallier 
357*e419bc7fSGatien Chevallier 	if (!rtc_dev.compat->has_rif_support)
358*e419bc7fSGatien Chevallier 		return TEE_SUCCESS;
359*e419bc7fSGatien Chevallier 
360*e419bc7fSGatien Chevallier 	cuint = fdt_getprop(fdt, node, "st,protreg", &lenp);
361*e419bc7fSGatien Chevallier 	if (!cuint) {
362*e419bc7fSGatien Chevallier 		DMSG("No RIF configuration available");
363*e419bc7fSGatien Chevallier 		return TEE_SUCCESS;
364*e419bc7fSGatien Chevallier 	}
365*e419bc7fSGatien Chevallier 
366*e419bc7fSGatien Chevallier 	rtc_dev.conf_data = calloc(1, sizeof(*rtc_dev.conf_data));
367*e419bc7fSGatien Chevallier 	if (!rtc_dev.conf_data)
368*e419bc7fSGatien Chevallier 		panic();
369*e419bc7fSGatien Chevallier 
370*e419bc7fSGatien Chevallier 	rtc_dev.nb_res = (unsigned int)(lenp / sizeof(uint32_t));
371*e419bc7fSGatien Chevallier 	assert(rtc_dev.nb_res <= RTC_NB_RIF_RESOURCES);
372*e419bc7fSGatien Chevallier 
373*e419bc7fSGatien Chevallier 	rtc_dev.conf_data->cid_confs = calloc(RTC_NB_RIF_RESOURCES,
374*e419bc7fSGatien Chevallier 					      sizeof(uint32_t));
375*e419bc7fSGatien Chevallier 	rtc_dev.conf_data->sec_conf = calloc(1, sizeof(uint32_t));
376*e419bc7fSGatien Chevallier 	rtc_dev.conf_data->priv_conf = calloc(1, sizeof(uint32_t));
377*e419bc7fSGatien Chevallier 	rtc_dev.conf_data->access_mask = calloc(1, sizeof(uint32_t));
378*e419bc7fSGatien Chevallier 	if (!rtc_dev.conf_data->cid_confs || !rtc_dev.conf_data->sec_conf ||
379*e419bc7fSGatien Chevallier 	    !rtc_dev.conf_data->priv_conf || !rtc_dev.conf_data->access_mask)
380*e419bc7fSGatien Chevallier 		panic("Not enough memory capacity for RTC RIF config");
381*e419bc7fSGatien Chevallier 
382*e419bc7fSGatien Chevallier 	for (i = 0; i < rtc_dev.nb_res; i++)
383*e419bc7fSGatien Chevallier 		stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), rtc_dev.conf_data,
384*e419bc7fSGatien Chevallier 				    RTC_NB_RIF_RESOURCES);
385*e419bc7fSGatien Chevallier 
386*e419bc7fSGatien Chevallier 	return TEE_SUCCESS;
387*e419bc7fSGatien Chevallier }
388*e419bc7fSGatien Chevallier 
389*e419bc7fSGatien Chevallier static TEE_Result stm32_rtc_enter_init_mode(void)
390*e419bc7fSGatien Chevallier {
391*e419bc7fSGatien Chevallier 	vaddr_t base = get_base();
392*e419bc7fSGatien Chevallier 	uint32_t icsr = io_read32(base + RTC_ICSR);
393*e419bc7fSGatien Chevallier 	uint32_t value = 0;
394*e419bc7fSGatien Chevallier 
395*e419bc7fSGatien Chevallier 	if (!(icsr & RTC_ICSR_INITF)) {
396*e419bc7fSGatien Chevallier 		icsr |= RTC_ICSR_INIT;
397*e419bc7fSGatien Chevallier 		io_write32(base + RTC_ICSR, icsr);
398*e419bc7fSGatien Chevallier 
399*e419bc7fSGatien Chevallier 		if (IO_READ32_POLL_TIMEOUT(base + RTC_ICSR, value,
400*e419bc7fSGatien Chevallier 					   value & RTC_ICSR_INITF,
401*e419bc7fSGatien Chevallier 					   10, TIMEOUT_US_RTC_GENERIC))
402*e419bc7fSGatien Chevallier 			return TEE_ERROR_BUSY;
403*e419bc7fSGatien Chevallier 	}
404*e419bc7fSGatien Chevallier 
405*e419bc7fSGatien Chevallier 	return TEE_SUCCESS;
406*e419bc7fSGatien Chevallier }
407*e419bc7fSGatien Chevallier 
408*e419bc7fSGatien Chevallier static void stm32_rtc_exit_init_mode(void)
409*e419bc7fSGatien Chevallier {
410*e419bc7fSGatien Chevallier 	io_clrbits32(get_base() + RTC_ICSR, RTC_ICSR_INIT);
411*e419bc7fSGatien Chevallier 	dsb();
412*e419bc7fSGatien Chevallier }
413*e419bc7fSGatien Chevallier 
414*e419bc7fSGatien Chevallier static TEE_Result stm32_rtc_wait_sync(void)
415*e419bc7fSGatien Chevallier {
416*e419bc7fSGatien Chevallier 	vaddr_t base = get_base();
417*e419bc7fSGatien Chevallier 	uint32_t value = 0;
418*e419bc7fSGatien Chevallier 
419*e419bc7fSGatien Chevallier 	io_clrbits32(base + RTC_ICSR, RTC_ICSR_RSF);
420*e419bc7fSGatien Chevallier 
421*e419bc7fSGatien Chevallier 	if (IO_READ32_POLL_TIMEOUT(base + RTC_ICSR, value,
422*e419bc7fSGatien Chevallier 				   value & RTC_ICSR_RSF, 10,
423*e419bc7fSGatien Chevallier 				   TIMEOUT_US_RTC_GENERIC))
424*e419bc7fSGatien Chevallier 		return TEE_ERROR_BUSY;
425*e419bc7fSGatien Chevallier 
426*e419bc7fSGatien Chevallier 	return TEE_SUCCESS;
427*e419bc7fSGatien Chevallier }
428*e419bc7fSGatien Chevallier 
429*e419bc7fSGatien Chevallier static TEE_Result stm32_rtc_get_time(struct rtc *rtc __unused,
430*e419bc7fSGatien Chevallier 				     struct optee_rtc_time *tm)
431*e419bc7fSGatien Chevallier {
432*e419bc7fSGatien Chevallier 	vaddr_t base = get_base();
433*e419bc7fSGatien Chevallier 	uint32_t ssr = 0;
434*e419bc7fSGatien Chevallier 	uint32_t dr = 0;
435*e419bc7fSGatien Chevallier 	uint32_t tr = 0;
436*e419bc7fSGatien Chevallier 
437*e419bc7fSGatien Chevallier 	if (!stm32_rtc_get_bypshad()) {
438*e419bc7fSGatien Chevallier 		uint32_t icsr = 0;
439*e419bc7fSGatien Chevallier 
440*e419bc7fSGatien Chevallier 		/* Wait calendar registers are ready */
441*e419bc7fSGatien Chevallier 		io_clrbits32(base + RTC_ICSR, RTC_ICSR_RSF);
442*e419bc7fSGatien Chevallier 
443*e419bc7fSGatien Chevallier 		if (IO_READ32_POLL_TIMEOUT(base + RTC_ICSR, icsr,
444*e419bc7fSGatien Chevallier 					   icsr & RTC_ICSR_RSF, 0,
445*e419bc7fSGatien Chevallier 					   TIMEOUT_US_RTC_SHADOW))
446*e419bc7fSGatien Chevallier 			panic();
447*e419bc7fSGatien Chevallier 	}
448*e419bc7fSGatien Chevallier 
449*e419bc7fSGatien Chevallier 	/*
450*e419bc7fSGatien Chevallier 	 * In our RTC we start :
451*e419bc7fSGatien Chevallier 	 * - year at 0
452*e419bc7fSGatien Chevallier 	 * - month at 1
453*e419bc7fSGatien Chevallier 	 * - day at 1
454*e419bc7fSGatien Chevallier 	 * - weekday at Monday = 1
455*e419bc7fSGatien Chevallier 	 * Change month value so it becomes 0=January, 1 = February, ...
456*e419bc7fSGatien Chevallier 	 * Change week day value so it becomes 0=Sunday, 1 = Monday, ...
457*e419bc7fSGatien Chevallier 	 */
458*e419bc7fSGatien Chevallier 
459*e419bc7fSGatien Chevallier 	ssr = io_read32(base + RTC_SSR);
460*e419bc7fSGatien Chevallier 	tr = io_read32(base + RTC_TR);
461*e419bc7fSGatien Chevallier 	dr = io_read32(base + RTC_DR);
462*e419bc7fSGatien Chevallier 
463*e419bc7fSGatien Chevallier 	tm->tm_hour = ((tr & RTC_TR_HT_MASK) >> RTC_TR_HT_SHIFT) * 10 +
464*e419bc7fSGatien Chevallier 		      ((tr & RTC_TR_HU_MASK) >> RTC_TR_HU_SHIFT);
465*e419bc7fSGatien Chevallier 
466*e419bc7fSGatien Chevallier 	if (tr & RTC_TR_PM)
467*e419bc7fSGatien Chevallier 		tm->tm_hour += 12;
468*e419bc7fSGatien Chevallier 
469*e419bc7fSGatien Chevallier 	tm->tm_ms = (stm32_rtc_get_subsecond(ssr) * MS_PER_SEC) /
470*e419bc7fSGatien Chevallier 		    stm32_rtc_get_subsecond_scale();
471*e419bc7fSGatien Chevallier 
472*e419bc7fSGatien Chevallier 	tm->tm_sec = ((tr & RTC_TR_ST_MASK) >> RTC_TR_ST_SHIFT) * 10 +
473*e419bc7fSGatien Chevallier 		     (tr & RTC_TR_SU_MASK);
474*e419bc7fSGatien Chevallier 
475*e419bc7fSGatien Chevallier 	tm->tm_min = ((tr & RTC_TR_MNT_MASK) >> RTC_TR_MNT_SHIFT) * 10 +
476*e419bc7fSGatien Chevallier 		     ((tr & RTC_TR_MNU_MASK) >> RTC_TR_MNU_SHIFT);
477*e419bc7fSGatien Chevallier 
478*e419bc7fSGatien Chevallier 	tm->tm_wday = ((dr & RTC_DR_WDU_MASK) >> RTC_DR_WDU_SHIFT) % 7;
479*e419bc7fSGatien Chevallier 
480*e419bc7fSGatien Chevallier 	tm->tm_mday = ((dr & RTC_DR_DT_MASK) >> RTC_DR_DT_SHIFT) * 10 +
481*e419bc7fSGatien Chevallier 		      (dr & RTC_DR_DU_MASK);
482*e419bc7fSGatien Chevallier 
483*e419bc7fSGatien Chevallier 	tm->tm_mon = ((dr & RTC_DR_MT_MASK) >> RTC_DR_MT_SHIFT) * 10 +
484*e419bc7fSGatien Chevallier 		     ((dr & RTC_DR_MU_MASK) >> RTC_DR_MU_SHIFT) - 1;
485*e419bc7fSGatien Chevallier 
486*e419bc7fSGatien Chevallier 	tm->tm_year = ((dr & RTC_DR_YT_MASK) >> RTC_DR_YT_SHIFT) * 10 +
487*e419bc7fSGatien Chevallier 		      ((dr & RTC_DR_YU_MASK) >> RTC_DR_YU_SHIFT) + YEAR_REF;
488*e419bc7fSGatien Chevallier 
489*e419bc7fSGatien Chevallier 	return TEE_SUCCESS;
490*e419bc7fSGatien Chevallier }
491*e419bc7fSGatien Chevallier 
492*e419bc7fSGatien Chevallier static TEE_Result stm32_rtc_set_time(struct rtc *rtc, struct optee_rtc_time *tm)
493*e419bc7fSGatien Chevallier {
494*e419bc7fSGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
495*e419bc7fSGatien Chevallier 	vaddr_t rtc_base = get_base();
496*e419bc7fSGatien Chevallier 	uint32_t tr = 0;
497*e419bc7fSGatien Chevallier 	uint32_t dr = 0;
498*e419bc7fSGatien Chevallier 
499*e419bc7fSGatien Chevallier 	/*
500*e419bc7fSGatien Chevallier 	 * In our RTC we start :
501*e419bc7fSGatien Chevallier 	 * - year at 0
502*e419bc7fSGatien Chevallier 	 * - month at 1
503*e419bc7fSGatien Chevallier 	 * - day at 1
504*e419bc7fSGatien Chevallier 	 * - weekday at Monday = 1
505*e419bc7fSGatien Chevallier 	 * Change month value so it becomes 1=January, 2 = February, ...
506*e419bc7fSGatien Chevallier 	 * Change week day value so it becomes 7=Sunday, 1 = Monday, ...
507*e419bc7fSGatien Chevallier 	 */
508*e419bc7fSGatien Chevallier 	tr = ((tm->tm_sec % 10) & RTC_TR_SU_MASK) |
509*e419bc7fSGatien Chevallier 	     (SHIFT_U32(tm->tm_sec / 10, RTC_TR_ST_SHIFT) & RTC_TR_ST_MASK) |
510*e419bc7fSGatien Chevallier 	     (SHIFT_U32(tm->tm_min % 10, RTC_TR_MNU_SHIFT) & RTC_TR_MNU_MASK) |
511*e419bc7fSGatien Chevallier 	     (SHIFT_U32(tm->tm_min / 10, RTC_TR_MNT_SHIFT) & RTC_TR_MNT_MASK) |
512*e419bc7fSGatien Chevallier 	     (SHIFT_U32(tm->tm_hour % 10, RTC_TR_HU_SHIFT) & RTC_TR_HU_MASK) |
513*e419bc7fSGatien Chevallier 	     (SHIFT_U32(tm->tm_hour / 10, RTC_TR_HT_SHIFT) & RTC_TR_HT_MASK);
514*e419bc7fSGatien Chevallier 
515*e419bc7fSGatien Chevallier 	dr = ((tm->tm_mday % 10) & RTC_DR_DU_MASK) |
516*e419bc7fSGatien Chevallier 	     (SHIFT_U32(tm->tm_mday / 10, RTC_DR_DT_SHIFT) & RTC_DR_DT_MASK) |
517*e419bc7fSGatien Chevallier 	     (SHIFT_U32((tm->tm_mon + 1) % 10, RTC_DR_MU_SHIFT) &
518*e419bc7fSGatien Chevallier 	      RTC_DR_MU_MASK) |
519*e419bc7fSGatien Chevallier 	     (SHIFT_U32((tm->tm_mon + 1) / 10, RTC_DR_MT_SHIFT) &
520*e419bc7fSGatien Chevallier 	      RTC_DR_MT_MASK) |
521*e419bc7fSGatien Chevallier 	     (SHIFT_U32(tm->tm_wday ? tm->tm_wday : 7, RTC_DR_WDU_SHIFT) &
522*e419bc7fSGatien Chevallier 	      RTC_DR_WDU_MASK) |
523*e419bc7fSGatien Chevallier 	     (SHIFT_U32((tm->tm_year - rtc->range_min.tm_year) % 10,
524*e419bc7fSGatien Chevallier 			RTC_DR_YU_SHIFT) & RTC_DR_YU_MASK) |
525*e419bc7fSGatien Chevallier 	     (SHIFT_U32((tm->tm_year - rtc->range_min.tm_year) / 10,
526*e419bc7fSGatien Chevallier 			RTC_DR_YT_SHIFT) & RTC_DR_YT_MASK);
527*e419bc7fSGatien Chevallier 
528*e419bc7fSGatien Chevallier 	stm32_rtc_write_unprotect();
529*e419bc7fSGatien Chevallier 
530*e419bc7fSGatien Chevallier 	res = stm32_rtc_enter_init_mode();
531*e419bc7fSGatien Chevallier 	if (res)
532*e419bc7fSGatien Chevallier 		goto end;
533*e419bc7fSGatien Chevallier 
534*e419bc7fSGatien Chevallier 	io_write32(rtc_base + RTC_TR, tr);
535*e419bc7fSGatien Chevallier 	io_write32(rtc_base + RTC_DR, dr);
536*e419bc7fSGatien Chevallier 
537*e419bc7fSGatien Chevallier 	stm32_rtc_exit_init_mode();
538*e419bc7fSGatien Chevallier 
539*e419bc7fSGatien Chevallier 	res = stm32_rtc_wait_sync();
540*e419bc7fSGatien Chevallier end:
541*e419bc7fSGatien Chevallier 	stm32_rtc_write_protect();
542*e419bc7fSGatien Chevallier 
543*e419bc7fSGatien Chevallier 	return res;
544*e419bc7fSGatien Chevallier }
545*e419bc7fSGatien Chevallier 
546*e419bc7fSGatien Chevallier static const struct rtc_ops stm32_rtc_ops = {
547*e419bc7fSGatien Chevallier 	.get_time = stm32_rtc_get_time,
548*e419bc7fSGatien Chevallier 	.set_time = stm32_rtc_set_time,
549*e419bc7fSGatien Chevallier };
550*e419bc7fSGatien Chevallier 
551*e419bc7fSGatien Chevallier static struct rtc stm32_rtc = {
552*e419bc7fSGatien Chevallier 	.ops = &stm32_rtc_ops,
553*e419bc7fSGatien Chevallier 	.range_min = RTC_TIME(YEAR_REF, 0, 1, 0, 0, 0, 0, 0),
554*e419bc7fSGatien Chevallier 	.range_max = RTC_TIME(YEAR_MAX, 11, 31, 4, 23, 59, 59, 999),
555*e419bc7fSGatien Chevallier };
556*e419bc7fSGatien Chevallier 
557*e419bc7fSGatien Chevallier static TEE_Result stm32_rtc_probe(const void *fdt, int node,
558*e419bc7fSGatien Chevallier 				  const void *compat_data)
559*e419bc7fSGatien Chevallier {
560*e419bc7fSGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
561*e419bc7fSGatien Chevallier 	bool is_tdcid = false;
562*e419bc7fSGatien Chevallier 
563*e419bc7fSGatien Chevallier 	rtc_dev.compat = compat_data;
564*e419bc7fSGatien Chevallier 
565*e419bc7fSGatien Chevallier 	if (rtc_dev.compat->has_rif_support) {
566*e419bc7fSGatien Chevallier 		res = stm32_rifsc_check_tdcid(&is_tdcid);
567*e419bc7fSGatien Chevallier 		if (res)
568*e419bc7fSGatien Chevallier 			return res;
569*e419bc7fSGatien Chevallier 	}
570*e419bc7fSGatien Chevallier 
571*e419bc7fSGatien Chevallier 	res = parse_dt(fdt, node);
572*e419bc7fSGatien Chevallier 	if (res) {
573*e419bc7fSGatien Chevallier 		memset(&rtc_dev, 0, sizeof(rtc_dev));
574*e419bc7fSGatien Chevallier 		return res;
575*e419bc7fSGatien Chevallier 	}
576*e419bc7fSGatien Chevallier 
577*e419bc7fSGatien Chevallier 	/* Unbalanced clock enable to ensure RTC core clock is always on */
578*e419bc7fSGatien Chevallier 	res = clk_enable(rtc_dev.rtc_ck);
579*e419bc7fSGatien Chevallier 	if (res)
580*e419bc7fSGatien Chevallier 		panic("Couldn't enable RTC clock");
581*e419bc7fSGatien Chevallier 
582*e419bc7fSGatien Chevallier 	if (clk_get_rate(rtc_dev.pclk) < (clk_get_rate(rtc_dev.rtc_ck) * 7))
583*e419bc7fSGatien Chevallier 		rtc_dev.flags |= RTC_FLAGS_READ_TWICE;
584*e419bc7fSGatien Chevallier 
585*e419bc7fSGatien Chevallier 	if (rtc_dev.compat->has_rif_support) {
586*e419bc7fSGatien Chevallier 		res = clk_enable(rtc_dev.pclk);
587*e419bc7fSGatien Chevallier 		if (res)
588*e419bc7fSGatien Chevallier 			panic("Could not enable RTC bus clock");
589*e419bc7fSGatien Chevallier 
590*e419bc7fSGatien Chevallier 		apply_rif_config(is_tdcid);
591*e419bc7fSGatien Chevallier 
592*e419bc7fSGatien Chevallier 		/*
593*e419bc7fSGatien Chevallier 		 * Verify if applied RIF config will not disable
594*e419bc7fSGatien Chevallier 		 * other functionalities of this driver.
595*e419bc7fSGatien Chevallier 		 */
596*e419bc7fSGatien Chevallier 		res = check_rif_config();
597*e419bc7fSGatien Chevallier 		if (res)
598*e419bc7fSGatien Chevallier 			panic("Incompatible RTC RIF configuration");
599*e419bc7fSGatien Chevallier 
600*e419bc7fSGatien Chevallier 		clk_disable(rtc_dev.pclk);
601*e419bc7fSGatien Chevallier 	}
602*e419bc7fSGatien Chevallier 
603*e419bc7fSGatien Chevallier 	rtc_register(&stm32_rtc);
604*e419bc7fSGatien Chevallier 
605*e419bc7fSGatien Chevallier 	return res;
606*e419bc7fSGatien Chevallier }
607*e419bc7fSGatien Chevallier 
608*e419bc7fSGatien Chevallier static const struct rtc_compat mp25_compat = {
609*e419bc7fSGatien Chevallier 	.has_seccfgr = true,
610*e419bc7fSGatien Chevallier 	.has_rif_support = true,
611*e419bc7fSGatien Chevallier };
612*e419bc7fSGatien Chevallier 
613*e419bc7fSGatien Chevallier static const struct rtc_compat mp15_compat = {
614*e419bc7fSGatien Chevallier 	.has_seccfgr = false,
615*e419bc7fSGatien Chevallier 	.has_rif_support = false,
616*e419bc7fSGatien Chevallier };
617*e419bc7fSGatien Chevallier 
618*e419bc7fSGatien Chevallier static const struct rtc_compat mp13_compat = {
619*e419bc7fSGatien Chevallier 	.has_seccfgr = true,
620*e419bc7fSGatien Chevallier 	.has_rif_support = false,
621*e419bc7fSGatien Chevallier };
622*e419bc7fSGatien Chevallier 
623*e419bc7fSGatien Chevallier static const struct dt_device_match stm32_rtc_match_table[] = {
624*e419bc7fSGatien Chevallier 	{
625*e419bc7fSGatien Chevallier 		.compatible = "st,stm32mp25-rtc",
626*e419bc7fSGatien Chevallier 		.compat_data = &mp25_compat,
627*e419bc7fSGatien Chevallier 	},
628*e419bc7fSGatien Chevallier 	{
629*e419bc7fSGatien Chevallier 		.compatible = "st,stm32mp1-rtc",
630*e419bc7fSGatien Chevallier 		.compat_data = &mp15_compat,
631*e419bc7fSGatien Chevallier 	},
632*e419bc7fSGatien Chevallier 	{
633*e419bc7fSGatien Chevallier 		.compatible = "st,stm32mp13-rtc",
634*e419bc7fSGatien Chevallier 		.compat_data = &mp13_compat,
635*e419bc7fSGatien Chevallier 	},
636*e419bc7fSGatien Chevallier 	{ }
637*e419bc7fSGatien Chevallier };
638*e419bc7fSGatien Chevallier 
639*e419bc7fSGatien Chevallier DEFINE_DT_DRIVER(stm32_rtc_dt_driver) = {
640*e419bc7fSGatien Chevallier 	.name = "stm32-rtc",
641*e419bc7fSGatien Chevallier 	.match_table = stm32_rtc_match_table,
642*e419bc7fSGatien Chevallier 	.probe = stm32_rtc_probe,
643*e419bc7fSGatien Chevallier };
644