1 /*
2 * Copyright 2024 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT nxp_irtc
8
9 #include <zephyr/devicetree.h>
10 #include <zephyr/drivers/rtc.h>
11 #include <zephyr/irq.h>
12 #include "rtc_utils.h"
13
14 struct nxp_irtc_config {
15 RTC_Type *base;
16 void (*irq_config_func)(const struct device *dev);
17 bool is_output_clock_enabled;
18 uint8_t clock_src;
19 uint8_t alarm_match_flag;
20 };
21
22 struct nxp_irtc_data {
23 bool is_dst_enabled;
24 #ifdef CONFIG_RTC_ALARM
25 rtc_alarm_callback alarm_callback;
26 void *alarm_user_data;
27 uint16_t alarm_mask;
28 #endif /* CONFIG_RTC_ALARM */
29 };
30
31 /* The IRTC Offset is 2112 instead of 1900 [2112 - 1900] -> [212] */
32 #define RTC_NXP_IRTC_YEAR_OFFSET 212
33
34 #define RTC_NXP_GET_REG_FIELD(_reg, _name, _field) \
35 ((_reg->_name & RTC_##_name##_##_field##_MASK) >> \
36 RTC_##_name##_##_field##_SHIFT)
37
38 /*
39 * The runtime where this is accessed is unknown so we force a lock on the registers then force an
40 * unlock to guarantee 2 seconds of write time
41 */
nxp_irtc_unlock_registers(RTC_Type * reg)42 static void nxp_irtc_unlock_registers(RTC_Type *reg)
43 {
44 /* Lock the regsiters */
45 while ((reg->STATUS & (uint16_t)RTC_STATUS_WRITE_PROT_EN_MASK) == 0) {
46 *(uint8_t *)(®->STATUS) |= RTC_STATUS_WE(0x2);
47 }
48 /* Unlock the registers */
49 while ((reg->STATUS & (int16_t)RTC_STATUS_WRITE_PROT_EN_MASK) != 0) {
50 /*
51 * The casting is required for writing only a single Byte to the STATUS Register,
52 * the pattern here unlocks all RTC registers for writing. When unlocked if a 0x20
53 * if written to the STATUS register the RTC registers will lock again and the next
54 * write will lead to a fault.
55 */
56 *(volatile uint8_t *)(®->STATUS) = 0x00;
57 *(volatile uint8_t *)(®->STATUS) = 0x40;
58 *(volatile uint8_t *)(®->STATUS) = 0xC0;
59 *(volatile uint8_t *)(®->STATUS) = 0x80;
60 }
61 }
62
nxp_irtc_set_time(const struct device * dev,const struct rtc_time * timeptr)63 static int nxp_irtc_set_time(const struct device *dev, const struct rtc_time *timeptr)
64 {
65 const struct nxp_irtc_config *config = dev->config;
66 struct nxp_irtc_data *data = dev->data;
67 RTC_Type *irtc_reg = config->base;
68
69 if (!timeptr || !rtc_utils_validate_rtc_time(timeptr, 0)) {
70 return -EINVAL;
71 }
72
73 int calc_year = timeptr->tm_year - RTC_NXP_IRTC_YEAR_OFFSET;
74 /* The IRTC Month Index starts at 1 instead of 0 */
75 int calc_month = timeptr->tm_mon + 1;
76
77 uint32_t key = irq_lock();
78
79 nxp_irtc_unlock_registers(irtc_reg);
80 irtc_reg->SECONDS = RTC_SECONDS_SEC_CNT(timeptr->tm_sec);
81
82 irtc_reg->HOURMIN = RTC_HOURMIN_MIN_CNT(timeptr->tm_min) |
83 RTC_HOURMIN_HOUR_CNT(timeptr->tm_hour);
84
85 /* 1 is valid for rtc_time.tm_wday property but is out of bounds for IRTC registers */
86 irtc_reg->DAYS = RTC_DAYS_DAY_CNT(timeptr->tm_mday) |
87 (timeptr->tm_wday == -1 ? 0 : RTC_DAYS_DOW(timeptr->tm_wday));
88
89 irtc_reg->YEARMON = RTC_YEARMON_MON_CNT(calc_month) | RTC_YEARMON_YROFST(calc_year);
90
91 if (timeptr->tm_isdst != -1) {
92 irtc_reg->CTRL |= RTC_CTRL_DST_EN(timeptr->tm_isdst);
93 data->is_dst_enabled = true;
94 }
95
96 irq_unlock(key);
97
98 return 0;
99 }
100
nxp_irtc_get_time(const struct device * dev,struct rtc_time * timeptr)101 static int nxp_irtc_get_time(const struct device *dev, struct rtc_time *timeptr)
102 {
103 const struct nxp_irtc_config *config = dev->config;
104 struct nxp_irtc_data *data = dev->data;
105 RTC_Type *irtc_reg = config->base;
106
107 __ASSERT(timeptr != 0, "timeptr has not been set");
108
109 timeptr->tm_sec = RTC_NXP_GET_REG_FIELD(irtc_reg, SECONDS, SEC_CNT);
110 timeptr->tm_min = RTC_NXP_GET_REG_FIELD(irtc_reg, HOURMIN, MIN_CNT);
111 timeptr->tm_hour = RTC_NXP_GET_REG_FIELD(irtc_reg, HOURMIN, HOUR_CNT);
112 timeptr->tm_wday = RTC_NXP_GET_REG_FIELD(irtc_reg, DAYS, DOW);
113 timeptr->tm_mday = RTC_NXP_GET_REG_FIELD(irtc_reg, DAYS, DAY_CNT);
114 timeptr->tm_mon = RTC_NXP_GET_REG_FIELD(irtc_reg, YEARMON, MON_CNT) - 1;
115 timeptr->tm_year = (int8_t)RTC_NXP_GET_REG_FIELD(irtc_reg, YEARMON, YROFST) +
116 RTC_NXP_IRTC_YEAR_OFFSET;
117 if (data->is_dst_enabled) {
118 timeptr->tm_isdst =
119 ((irtc_reg->CTRL & RTC_CTRL_DST_EN_MASK) >> RTC_CTRL_DST_EN_SHIFT);
120 }
121
122 /* There is no nano second support for IRTC */
123 timeptr->tm_nsec = 0;
124 /* There is no day of the year support for IRTC */
125 timeptr->tm_yday = -1;
126
127 return 0;
128 }
129
130 #if defined(CONFIG_RTC_ALARM)
nxp_irtc_alarm_get_supported_fields(const struct device * dev,uint16_t id,uint16_t * mask)131 static int nxp_irtc_alarm_get_supported_fields(const struct device *dev, uint16_t id,
132 uint16_t *mask)
133 {
134 ARG_UNUSED(dev);
135
136 if (id != 0) {
137 return -EINVAL;
138 }
139
140 *mask = (RTC_ALARM_TIME_MASK_SECOND | RTC_ALARM_TIME_MASK_MINUTE |
141 RTC_ALARM_TIME_MASK_HOUR | RTC_ALARM_TIME_MASK_MONTHDAY |
142 RTC_ALARM_TIME_MASK_MONTH | RTC_ALARM_TIME_MASK_YEAR);
143
144 return 0;
145 }
146
nxp_irtc_alarm_set_time(const struct device * dev,uint16_t id,uint16_t mask,const struct rtc_time * timeptr)147 static int nxp_irtc_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask,
148 const struct rtc_time *timeptr)
149 {
150 const struct nxp_irtc_config *config = dev->config;
151 struct nxp_irtc_data *data = dev->data;
152 RTC_Type *irtc_reg = config->base;
153
154 if (id != 0 || (mask && (timeptr == 0)) ||
155 (timeptr && !rtc_utils_validate_rtc_time(timeptr, mask))) {
156 return -EINVAL;
157 }
158
159 uint32_t key = irq_lock();
160
161 nxp_irtc_unlock_registers(irtc_reg);
162
163 if (mask & RTC_ALARM_TIME_MASK_SECOND) {
164 irtc_reg->ALM_SECONDS = RTC_ALM_SECONDS_ALM_SEC(timeptr->tm_sec);
165 }
166
167 if (mask & RTC_ALARM_TIME_MASK_MINUTE) {
168 irtc_reg->ALM_HOURMIN = RTC_ALM_HOURMIN_ALM_MIN(timeptr->tm_min);
169 }
170
171 if (mask & RTC_ALARM_TIME_MASK_HOUR) {
172 irtc_reg->ALM_HOURMIN |= RTC_ALM_HOURMIN_ALM_HOUR(timeptr->tm_hour);
173 }
174
175 if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) {
176 irtc_reg->ALM_DAYS = RTC_ALM_DAYS_ALM_DAY(timeptr->tm_mday);
177 }
178
179 if (mask & RTC_ALARM_TIME_MASK_MONTH) {
180 irtc_reg->ALM_YEARMON = RTC_ALM_YEARMON_ALM_MON(timeptr->tm_mon + 1);
181 }
182
183 if (mask & RTC_ALARM_TIME_MASK_YEAR) {
184 irtc_reg->ALM_YEARMON |=
185 RTC_ALM_YEARMON_ALM_YEAR(timeptr->tm_year - RTC_NXP_IRTC_YEAR_OFFSET);
186 }
187
188 /* Clearing out the ALARM Flag Field then setting the correct value */
189 irtc_reg->CTRL &= ~(0xC);
190 switch (mask) {
191 case 0x0F:
192 irtc_reg->CTRL |= RTC_CTRL_ALM_MATCH(0x4);
193 break;
194 case 0x1F:
195 irtc_reg->CTRL |= RTC_CTRL_ALM_MATCH(0x8);
196 break;
197 case 0x3F:
198 irtc_reg->CTRL |= RTC_CTRL_ALM_MATCH(0xC);
199 break;
200 default:
201 irtc_reg->CTRL |= RTC_CTRL_ALM_MATCH(0x0);
202 }
203
204 /* Enabling Alarm Interrupts */
205 irtc_reg->IER |= RTC_ISR_ALM_IS_MASK;
206 data->alarm_mask = mask;
207
208 irq_unlock(key);
209
210 return 0;
211 }
212
nxp_irtc_alarm_get_time(const struct device * dev,uint16_t id,uint16_t * mask,struct rtc_time * timeptr)213 static int nxp_irtc_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask,
214 struct rtc_time *timeptr)
215 {
216 const struct nxp_irtc_config *config = dev->config;
217 struct nxp_irtc_data *data = dev->data;
218 RTC_Type *irtc_reg = config->base;
219 uint16_t curr_alarm_mask = data->alarm_mask;
220 uint16_t return_mask = 0;
221
222 if (id != 0 || !timeptr) {
223 return -EINVAL;
224 }
225
226 if (curr_alarm_mask & RTC_ALARM_TIME_MASK_SECOND) {
227 timeptr->tm_sec = RTC_NXP_GET_REG_FIELD(irtc_reg, ALM_SECONDS, ALM_SEC);
228 return_mask |= RTC_ALARM_TIME_MASK_SECOND;
229 }
230
231 if (curr_alarm_mask & RTC_ALARM_TIME_MASK_MINUTE) {
232 timeptr->tm_min = RTC_NXP_GET_REG_FIELD(irtc_reg, HOURMIN, MIN_CNT);
233 return_mask |= RTC_ALARM_TIME_MASK_MINUTE;
234 }
235
236 if (curr_alarm_mask & RTC_ALARM_TIME_MASK_HOUR) {
237 timeptr->tm_hour = RTC_NXP_GET_REG_FIELD(irtc_reg, HOURMIN, HOUR_CNT);
238 return_mask |= RTC_ALARM_TIME_MASK_HOUR;
239 }
240
241 if (curr_alarm_mask & RTC_ALARM_TIME_MASK_MONTHDAY) {
242 timeptr->tm_mday = RTC_NXP_GET_REG_FIELD(irtc_reg, DAYS, DAY_CNT);
243 return_mask |= RTC_ALARM_TIME_MASK_MONTHDAY;
244 }
245
246 if (curr_alarm_mask & RTC_ALARM_TIME_MASK_MONTH) {
247 timeptr->tm_mon = RTC_NXP_GET_REG_FIELD(irtc_reg, YEARMON, MON_CNT) - 1;
248 return_mask |= RTC_ALARM_TIME_MASK_MONTH;
249 }
250
251 if (curr_alarm_mask & RTC_ALARM_TIME_MASK_YEAR) {
252 timeptr->tm_year = (int8_t)RTC_NXP_GET_REG_FIELD(irtc_reg, YEARMON, YROFST) +
253 RTC_NXP_IRTC_YEAR_OFFSET;
254 return_mask |= RTC_ALARM_TIME_MASK_YEAR;
255 }
256
257 *mask = return_mask;
258
259 return 0;
260 }
261
nxp_irtc_alarm_is_pending(const struct device * dev,uint16_t id)262 static int nxp_irtc_alarm_is_pending(const struct device *dev, uint16_t id)
263 {
264 struct nxp_irtc_data *data = dev->data;
265 RTC_Type *irtc_reg = config->base;
266
267 if (id != 0) {
268 return -EINVAL;
269 }
270
271 return RTC_ISR_ALM_IS(0x4);
272 }
273
nxp_irtc_alarm_set_callback(const struct device * dev,uint16_t id,rtc_alarm_callback callback,void * user_data)274 static int nxp_irtc_alarm_set_callback(const struct device *dev, uint16_t id,
275 rtc_alarm_callback callback, void *user_data)
276 {
277 struct nxp_irtc_data *data = dev->data;
278
279 if (id != 0) {
280 return -EINVAL;
281 }
282
283 uint32_t key = irq_lock();
284
285 data->alarm_callback = callback;
286 data->alarm_user_data = user_data;
287
288 irq_unlock(key);
289
290 return 0;
291 }
292
293 #endif /* CONFIG_RTC_ALARM */
294 #if defined(CONFIG_RTC_UPDATE)
295
nxp_irtc_update_set_callback(const struct device * dev,rtc_update_callback callback,void * user_data)296 static int nxp_irtc_update_set_callback(const struct device *dev, rtc_update_callback callback,
297 void *user_data)
298 {
299 ARG_UNUSED(dev);
300 ARG_UNUSED(calibration);
301 ARG_UNUSED(user_data);
302 return -ENOTSUP;
303 }
304
305 #endif /* CONFIG_RTC_UPDATE */
306 #if defined(CONFIG_RTC_CALIBRATION)
307
nxp_irtc_set_calibration(const struct device * dev,int32_t calibration)308 static int nxp_irtc_set_calibration(const struct device *dev, int32_t calibration)
309 {
310 ARG_UNUSED(dev);
311 ARG_UNUSED(calibration);
312 return -ENOTSUP;
313 }
314
nxp_irtc_get_calibration(const struct device * dev,int32_t * calibration)315 static int nxp_irtc_get_calibration(const struct device *dev, int32_t *calibration)
316 {
317 ARG_UNUSED(dev);
318 ARG_UNUSED(calibration);
319 return -ENOTSUP;
320 }
321
322 #endif /* CONFIG_RTC_CALIBRATION */
323
nxp_irtc_init(const struct device * dev)324 static int nxp_irtc_init(const struct device *dev)
325 {
326 const struct nxp_irtc_config *config = dev->config;
327 RTC_Type *irtc_reg = config->base;
328
329 nxp_irtc_unlock_registers(irtc_reg);
330
331 /* set the control register bits */
332 irtc_reg->CTRL = RTC_CTRL_CLK_SEL(config->clock_src) |
333 RTC_CTRL_CLKO_DIS(!config->is_output_clock_enabled);
334
335 config->irq_config_func(dev);
336
337 return 0;
338 }
339
nxp_irtc_isr(const struct device * dev)340 static void nxp_irtc_isr(const struct device *dev)
341 {
342 #ifdef CONFIG_RTC_ALARM
343 const struct nxp_irtc_config *config = dev->config;
344 RTC_Type *irtc_reg = config->base;
345 struct nxp_irtc_data *data = dev->data;
346 uint32_t key = irq_lock();
347
348 nxp_irtc_unlock_registers(irtc_reg);
349 /* Clearing ISR Register since w1c */
350 irtc_reg->ISR = irtc_reg->ISR;
351
352 if (data->alarm_callback) {
353 data->alarm_callback(dev, 0, data->alarm_user_data);
354 }
355 irq_unlock(key);
356 #endif /* CONFIG_RTC_ALARM */
357 }
358
359 static DEVICE_API(rtc, rtc_nxp_irtc_driver_api) = {
360 .set_time = nxp_irtc_set_time,
361 .get_time = nxp_irtc_get_time,
362 #if defined(CONFIG_RTC_ALARM)
363 .alarm_get_supported_fields = nxp_irtc_alarm_get_supported_fields,
364 .alarm_set_time = nxp_irtc_alarm_set_time,
365 .alarm_get_time = nxp_irtc_alarm_get_time,
366 .alarm_is_pending = nxp_irtc_alarm_is_pending,
367 .alarm_set_callback = nxp_irtc_alarm_set_callback,
368 #endif /* CONFIG_RTC_ALARM */
369 #if defined(CONFIG_RTC_UPDATE)
370 .update_set_callback = nxp_irtc_update_set_callback,
371 #endif /* CONFIG_RTC_UPDATE */
372 #if defined(CONFIG_RTC_CALIBRATION)
373 .set_calibration = nxp_irtc_set_calibration,
374 .get_calibration = nxp_irtc_get_calibration,
375 #endif /* CONFIG_RTC_CALIBRATION */
376 };
377
378 #define RTC_NXP_IRTC_DEVICE_INIT(n) \
379 static void nxp_irtc_config_func_##n(const struct device *dev) \
380 { \
381 IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), nxp_irtc_isr, \
382 DEVICE_DT_INST_GET(n), 0); \
383 irq_enable(DT_INST_IRQN(n)); \
384 } \
385 static const struct nxp_irtc_config nxp_irtc_config_##n = { \
386 .base = (RTC_Type *)DT_INST_REG_ADDR(n), \
387 .clock_src = DT_INST_PROP(n, clock_src), \
388 .is_output_clock_enabled = DT_INST_PROP(n, output_clk_en), \
389 .irq_config_func = nxp_irtc_config_func_##n, \
390 }; \
391 \
392 static struct nxp_irtc_data nxp_irtc_data_##n; \
393 \
394 DEVICE_DT_INST_DEFINE(n, nxp_irtc_init, NULL, &nxp_irtc_data_##n, &nxp_irtc_config_##n, \
395 PRE_KERNEL_1, CONFIG_RTC_INIT_PRIORITY, &rtc_nxp_irtc_driver_api);
396
397 DT_INST_FOREACH_STATUS_OKAY(RTC_NXP_IRTC_DEVICE_INIT)
398