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