xref: /optee_os/core/drivers/atmel_rtc.c (revision e231582fca25178ed521995577f537580ed47a41)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2022 Microchip
4  *
5  * Driver for AT91 RTC
6  */
7 
8 #include <assert.h>
9 #include <drivers/rtc.h>
10 #include <io.h>
11 #include <kernel/dt.h>
12 #include <matrix.h>
13 #include <mm/core_memprot.h>
14 #include <sama5d2.h>
15 
16 #define RTC_VAL(reg, val)	(((val) >> RTC_## reg ## _SHIFT) & \
17 				 RTC_## reg ##_MASK)
18 
19 #define RTC_SET_VAL(reg, val)	SHIFT_U32((val) & RTC_## reg ##_MASK, \
20 					  RTC_## reg ## _SHIFT)
21 
22 #define RTC_CR			0x0
23 #define RTC_CR_UPDCAL		BIT(1)
24 #define RTC_CR_UPDTIM		BIT(0)
25 
26 #define RTC_MR			0x4
27 #define RTC_MR_HR_MODE		BIT(0)
28 #define RTC_MR_PERSIAN		BIT(1)
29 #define RTC_MR_UTC		BIT(2)
30 #define RTC_MR_NEGPPM		BIT(4)
31 #define RTC_MR_CORR_SHIFT	8
32 #define RTC_MR_CORR_MASK	GENMASK_32(6, 0)
33 #define RTC_MR_CORR(val)	RTC_VAL(val, MR_CORR)
34 #define RTC_MR_HIGHPPM		BIT(15)
35 
36 #define RTC_TIMR		0x8
37 #define RTC_CALR		0xC
38 
39 #define RTC_SR			0x18
40 #define RTC_SR_ACKUPD		BIT(0)
41 #define RTC_SR_SEC		BIT(2)
42 
43 #define RTC_SCCR		0x1C
44 #define RTC_SCCR_ACKCLR		BIT(0)
45 #define RTC_SCCR_SECCLR		BIT(2)
46 
47 #define RTC_VER			0x2C
48 #define RTC_VER_NVTIM		BIT(0)
49 #define RTC_VER_NVCAL		BIT(1)
50 
51 #define RTC_TSTR0		0xB0
52 #define RTC_TSDR0		0xB4
53 
54 #define RTC_TSSR0		0xB8
55 #define RTC_TSSR_DET_OFFSET	16
56 #define RTC_TSSR_DET_COUNT	8
57 #define RTC_TSSR_TST_PIN	BIT(2)
58 #define RTC_TSSR_JTAG		BIT(3)
59 
60 /* Layout of Time registers */
61 #define RTC_TIME_BACKUP	BIT(31)
62 #define RTC_TIME_HOUR_SHIFT	16
63 #define RTC_TIME_HOUR_MASK	GENMASK_32(5, 0)
64 #define RTC_TIME_MIN_SHIFT	8
65 #define RTC_TIME_MIN_MASK	GENMASK_32(6, 0)
66 #define RTC_TIME_SEC_SHIFT	0
67 #define RTC_TIME_SEC_MASK	GENMASK_32(6, 0)
68 
69 /* Layout of Calendar registers */
70 #define RTC_CAL_DATE_SHIFT	24
71 #define RTC_CAL_DATE_MASK	GENMASK_32(5, 0)
72 #define RTC_CAL_DAY_SHIFT	21
73 #define RTC_CAL_DAY_MASK	GENMASK_32(2, 0)
74 #define RTC_CAL_MONTH_SHIFT	16
75 #define RTC_CAL_MONTH_MASK	GENMASK_32(4, 0)
76 #define RTC_CAL_YEAR_SHIFT	8
77 #define RTC_CAL_YEAR_MASK	GENMASK_32(7, 0)
78 #define RTC_CAL_CENT_SHIFT	0
79 #define RTC_CAL_CENT_MASK	GENMASK_32(6, 0)
80 
81 #define ATMEL_RTC_CORR_DIVIDEND		3906000
82 #define ATMEL_RTC_CORR_LOW_RATIO	20
83 
84 static vaddr_t rtc_base;
85 
86 static uint8_t bcd_decode(uint8_t dcb_val)
87 {
88 	return (dcb_val & 0xF) + (dcb_val >> 4) * 10;
89 }
90 
91 static uint8_t bcd_encode(uint32_t value)
92 {
93 	return ((value / 10) << 4) + value % 10;
94 }
95 
96 static uint32_t atmel_rtc_read(unsigned int offset)
97 {
98 	return io_read32(rtc_base + offset);
99 }
100 
101 static void atmel_rtc_write(unsigned int offset, uint32_t val)
102 {
103 	return io_write32(rtc_base + offset, val);
104 }
105 
106 static void atmel_decode_date(unsigned int time_reg, unsigned int cal_reg,
107 			      struct optee_rtc_time *tm)
108 {
109 	uint32_t time = 0;
110 	uint32_t date = 0;
111 
112 	/* Must read twice in case it changes */
113 	do {
114 		time = atmel_rtc_read(time_reg);
115 		date = atmel_rtc_read(cal_reg);
116 	} while ((time != atmel_rtc_read(time_reg)) ||
117 		 (date != atmel_rtc_read(cal_reg)));
118 
119 	tm->tm_wday = bcd_decode(RTC_VAL(CAL_DAY, date)) - 1;
120 	tm->tm_mday = bcd_decode(RTC_VAL(CAL_DATE, date));
121 	tm->tm_mon = bcd_decode(RTC_VAL(CAL_MONTH, date)) - 1;
122 	tm->tm_year = bcd_decode(RTC_VAL(CAL_CENT, date)) * 100;
123 	tm->tm_year += bcd_decode(RTC_VAL(CAL_YEAR, date));
124 
125 	tm->tm_hour = bcd_decode(RTC_VAL(TIME_HOUR, time));
126 	tm->tm_min = bcd_decode(RTC_VAL(TIME_MIN, time));
127 	tm->tm_sec = bcd_decode(RTC_VAL(TIME_SEC, time));
128 }
129 
130 static TEE_Result atmel_rtc_get_time(struct rtc *rtc __unused,
131 				     struct optee_rtc_time *tm)
132 {
133 	atmel_decode_date(RTC_TIMR, RTC_CALR, tm);
134 
135 	return TEE_SUCCESS;
136 }
137 
138 static TEE_Result atmel_rtc_set_time(struct rtc *rtc __unused,
139 				     struct optee_rtc_time *tm)
140 {
141 	uint32_t cr = 0;
142 	uint32_t sr = 0;
143 	uint32_t err = 0;
144 
145 	/* First, wait for UPDCAL/UPDTIM to be 0 */
146 	do {
147 		cr = atmel_rtc_read(RTC_CR);
148 	} while (cr & (RTC_CR_UPDCAL | RTC_CR_UPDTIM));
149 
150 	/* Stop Time/Calendar for update */
151 	atmel_rtc_write(RTC_CR, cr | RTC_CR_UPDCAL | RTC_CR_UPDTIM);
152 
153 	do {
154 		sr = atmel_rtc_read(RTC_SR);
155 	} while (!(sr & RTC_SR_ACKUPD));
156 
157 	atmel_rtc_write(RTC_SCCR, RTC_SCCR_ACKCLR);
158 
159 	atmel_rtc_write(RTC_TIMR,
160 			RTC_SET_VAL(TIME_SEC, bcd_encode(tm->tm_sec)) |
161 			RTC_SET_VAL(TIME_MIN, bcd_encode(tm->tm_min)) |
162 			RTC_SET_VAL(TIME_HOUR, bcd_encode(tm->tm_hour)));
163 
164 	atmel_rtc_write(RTC_CALR,
165 			RTC_SET_VAL(CAL_CENT,
166 				    bcd_encode(tm->tm_year / 100)) |
167 			RTC_SET_VAL(CAL_YEAR, bcd_encode(tm->tm_year % 100)) |
168 			RTC_SET_VAL(CAL_MONTH, bcd_encode(tm->tm_mon + 1)) |
169 			RTC_SET_VAL(CAL_DAY, bcd_encode(tm->tm_wday + 1)) |
170 			RTC_SET_VAL(CAL_DATE, bcd_encode(tm->tm_mday)));
171 
172 	err = atmel_rtc_read(RTC_VER);
173 	if (err) {
174 		if (err & RTC_VER_NVTIM)
175 			DMSG("Invalid time programmed");
176 		if (err & RTC_VER_NVCAL)
177 			DMSG("Invalid date programmed");
178 
179 		return TEE_ERROR_BAD_PARAMETERS;
180 	}
181 
182 	/* Restart Time/Calendar */
183 	atmel_rtc_write(RTC_CR, cr);
184 
185 	return TEE_SUCCESS;
186 }
187 
188 static TEE_Result atmel_rtc_get_offset(struct rtc *rtc __unused, long *offset)
189 {
190 	uint32_t mr = atmel_rtc_read(RTC_MR);
191 	long val = RTC_VAL(MR_CORR, mr);
192 
193 	if (!val) {
194 		*offset = 0;
195 		return TEE_SUCCESS;
196 	}
197 
198 	val++;
199 
200 	if (!(mr & RTC_MR_HIGHPPM))
201 		val *= ATMEL_RTC_CORR_LOW_RATIO;
202 
203 	val = UDIV_ROUND_NEAREST(ATMEL_RTC_CORR_DIVIDEND, val);
204 
205 	if (!(mr & RTC_MR_NEGPPM))
206 		val = -val;
207 
208 	*offset = val;
209 
210 	return TEE_SUCCESS;
211 }
212 
213 static TEE_Result atmel_rtc_set_offset(struct rtc *rtc  __unused, long offset)
214 {
215 	long corr = 0;
216 	uint32_t mr = 0;
217 
218 	if (offset > ATMEL_RTC_CORR_DIVIDEND / 2)
219 		return TEE_ERROR_BAD_PARAMETERS;
220 	if (offset < -ATMEL_RTC_CORR_DIVIDEND / 2)
221 		return TEE_ERROR_BAD_PARAMETERS;
222 
223 	mr = atmel_rtc_read(RTC_MR);
224 	mr &= ~(RTC_MR_NEGPPM | RTC_MR_CORR_MASK | RTC_MR_HIGHPPM);
225 
226 	if (offset > 0)
227 		mr |= RTC_MR_NEGPPM;
228 	else
229 		offset = -offset;
230 
231 	/* offset less than 764 ppb, disable correction */
232 	if (offset < 764) {
233 		atmel_rtc_write(RTC_MR, mr & ~RTC_MR_NEGPPM);
234 
235 		return TEE_SUCCESS;
236 	}
237 
238 	/*
239 	 * 29208 ppb is the perfect cutoff between low range and high range
240 	 * low range values are never better than high range value after that.
241 	 */
242 	if (offset < 29208) {
243 		corr = UDIV_ROUND_NEAREST(ATMEL_RTC_CORR_DIVIDEND,
244 					  offset * ATMEL_RTC_CORR_LOW_RATIO);
245 	} else {
246 		corr = UDIV_ROUND_NEAREST(ATMEL_RTC_CORR_DIVIDEND, offset);
247 		mr |= RTC_MR_HIGHPPM;
248 	}
249 
250 	corr = MIN(corr, 128);
251 
252 	mr |= ((corr - 1) & RTC_MR_CORR_MASK) << RTC_MR_CORR_SHIFT;
253 
254 	atmel_rtc_write(RTC_MR, mr);
255 
256 	return TEE_SUCCESS;
257 }
258 
259 static const struct rtc_ops atmel_rtc_ops = {
260 	.get_time = atmel_rtc_get_time,
261 	.set_time = atmel_rtc_set_time,
262 	.get_offset = atmel_rtc_get_offset,
263 	.set_offset = atmel_rtc_set_offset,
264 };
265 
266 static struct rtc atmel_rtc = {
267 	.ops = &atmel_rtc_ops,
268 	.range_min = { 1900, 1, 1, 0, 0, 0, 0 },
269 	.range_max = { 2099, 12, 31, 23, 59, 59, 0 },
270 };
271 
272 static TEE_Result atmel_rtc_probe(const void *fdt, int node,
273 				  const void *compat_data __unused)
274 {
275 	size_t size = 0;
276 
277 	if (rtc_base)
278 		return TEE_ERROR_GENERIC;
279 
280 	if (_fdt_get_status(fdt, node) != DT_STATUS_OK_SEC)
281 		return TEE_ERROR_BAD_PARAMETERS;
282 
283 	matrix_configure_periph_secure(AT91C_ID_SYS);
284 
285 	if (dt_map_dev(fdt, node, &rtc_base, &size) < 0)
286 		return TEE_ERROR_GENERIC;
287 
288 	atmel_rtc_write(RTC_CR, 0);
289 	/* Enable 24 hours Gregorian mode (this is a clear bits operation !) */
290 	io_clrbits32(rtc_base + RTC_MR, RTC_MR_PERSIAN | RTC_MR_UTC |
291 		     RTC_MR_HR_MODE);
292 
293 	rtc_register(&atmel_rtc);
294 
295 	return TEE_SUCCESS;
296 }
297 
298 static const struct dt_device_match atmel_rtc_match_table[] = {
299 	{ .compatible = "atmel,sama5d2-rtc" },
300 	{ }
301 };
302 
303 DEFINE_DT_DRIVER(atmel_rtc_dt_driver) = {
304 	.name = "atmel_rtc",
305 	.type = DT_DRIVER_NOTYPE,
306 	.match_table = atmel_rtc_match_table,
307 	.probe = atmel_rtc_probe,
308 };
309 
310