1 /*
2 * Copyright (c) 2023 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT motorola_mc146818
8
9 #include <errno.h>
10 #include <zephyr/device.h>
11 #include <zephyr/kernel.h>
12 #include <zephyr/init.h>
13 #include <zephyr/sys/util.h>
14 #include <zephyr/spinlock.h>
15 #include <zephyr/devicetree.h>
16 #include <zephyr/drivers/rtc.h>
17 #include <zephyr/sys/sys_io.h>
18
19 #define RTC_STD_INDEX (DT_INST_REG_ADDR_BY_IDX(0, 0))
20 #define RTC_STD_TARGET (DT_INST_REG_ADDR_BY_IDX(0, 1))
21
22 /* Time indices in RTC RAM */
23 #define RTC_SEC 0x00
24 #define RTC_MIN 0x02
25 #define RTC_HOUR 0x04
26
27 /* Day of week index in RTC RAM */
28 #define RTC_WDAY 0x06
29
30 /* Day of month index in RTC RAM */
31 #define RTC_MDAY 0x07
32
33 /* Month and year index in RTC RAM */
34 #define RTC_MONTH 0x08
35 #define RTC_YEAR 0x09
36
37 /* Y2K Bugfix */
38 #define RTC_CENTURY 0x32
39
40 /* Alarm time indices in RTC RAM */
41 #define RTC_ALARM_SEC 0x01
42 #define RTC_ALARM_MIN 0x03
43 #define RTC_ALARM_HOUR 0x05
44
45 /* Registers A-D indeces in RTC RAM */
46 #define RTC_REG_A 0x0A
47 #define RTC_REG_B 0x0B
48 #define RTC_REG_C 0x0C
49 #define RTC_REG_D 0x0D
50
51 #define RTC_UIP RTC_REG_A
52 #define RTC_DATA RTC_REG_B
53 #define RTC_FLAG RTC_REG_C
54
55 /* Alarm don't case state */
56 #define RTC_ALARM_DC 0xFF
57
58 /* Update In Progress bit in REG_A */
59 #define RTC_UIP_BIT BIT(7)
60
61 /* Update Cycle Inhibit bit in REG_B */
62 #define RTC_UCI_BIT BIT(7)
63
64 /* Periodic Interrupt Enable bit in REG_B */
65 #define RTC_PIE_BIT BIT(6)
66
67 /* Alarm Interrupt Enable bit in REG_B */
68 #define RTC_AIE_BIT BIT(5)
69
70 /* Update-ended Interrupt Enable bit in REG_B */
71 #define RTC_UIE_BIT BIT(4)
72
73 /* Data mode bit in REG_B */
74 #define RTC_DMODE_BIT BIT(2)
75
76 /* Hour Format bit in REG_B */
77 #define RTC_HFORMAT_BIT BIT(1)
78
79 /* Daylight Savings Enable Format bit in REG_B */
80 #define RTC_DSE_BIT BIT(0)
81
82 /* Interrupt Request Flag bit in REG_C */
83 #define RTC_IRF_BIT BIT(7)
84
85 /* Periodic Flag bit in REG_C */
86 #define RTC_PF_BIT BIT(6)
87
88 /* Alarm Flag bit in REG_C */
89 #define RTC_AF_BIT BIT(5)
90
91 /* Update-end Flag bit in REG_C */
92 #define RTC_UEF_BIT BIT(4)
93
94 /* VRT bit in REG_D */
95 #define RTC_VRT_BIT BIT(7)
96
97 /* Month day Alarm bits in REG_D */
98 #define RTC_MDAY_ALARM BIT_MASK(5)
99
100 /* Maximum and Minimum values of time */
101 #define MIN_SEC 0
102 #define MAX_SEC 59
103 #define MIN_MIN 0
104 #define MAX_MIN 59
105 #define MIN_HOUR 0
106 #define MAX_HOUR 23
107 #define MAX_WDAY 7
108 #define MIN_WDAY 1
109 #define MAX_MDAY 31
110 #define MIN_MDAY 1
111 #define MAX_MON 12
112 #define MIN_MON 1
113 #define MIN_YEAR_DIFF 0 /* YEAR - 1900 */
114 #define MAX_YEAR_DIFF 99 /* YEAR - 1999 */
115
116 /* Input clock frequency mapped to divider bits */
117 #define RTC_IN_CLK_DIV_BITS_4194304 (0)
118 #define RTC_IN_CLK_DIV_BITS_1048576 (1 << 4)
119 #define RTC_IN_CLK_DIV_BITS_32768 (2 << 4)
120
121 struct rtc_mc146818_data {
122 struct k_spinlock lock;
123 bool alarm_pending;
124 rtc_alarm_callback cb;
125 void *cb_data;
126 rtc_update_callback update_cb;
127 void *update_cb_data;
128 };
129
rtc_read(int reg)130 static uint8_t rtc_read(int reg)
131 {
132 uint8_t value;
133
134 sys_out8(reg, RTC_STD_INDEX);
135 value = sys_in8(RTC_STD_TARGET);
136
137 return value;
138 }
139
rtc_write(int reg,uint8_t value)140 static void rtc_write(int reg, uint8_t value)
141 {
142 sys_out8(reg, RTC_STD_INDEX);
143 sys_out8(value, RTC_STD_TARGET);
144 }
145
rtc_mc146818_validate_time(const struct rtc_time * timeptr)146 static bool rtc_mc146818_validate_time(const struct rtc_time *timeptr)
147 {
148 if (timeptr->tm_sec < MIN_SEC || timeptr->tm_sec > MAX_SEC) {
149 return false;
150 }
151 if (timeptr->tm_min < MIN_MIN || timeptr->tm_min > MAX_MIN) {
152 return false;
153 }
154 if (timeptr->tm_hour < MIN_HOUR || timeptr->tm_hour > MAX_HOUR) {
155 return false;
156 }
157 if (timeptr->tm_wday + 1 < MIN_WDAY || timeptr->tm_wday + 1 > MAX_WDAY) {
158 return false;
159 }
160 if (timeptr->tm_mday < MIN_MDAY || timeptr->tm_mday > MAX_MDAY) {
161 return false;
162 }
163 if (timeptr->tm_mon + 1 < MIN_MON || timeptr->tm_mon + 1 > MAX_MON) {
164 return false;
165 }
166 if (timeptr->tm_year - 70 < MIN_YEAR_DIFF || timeptr->tm_year - 70 > MAX_YEAR_DIFF) {
167 return false;
168 }
169 return true;
170 }
171
rtc_mc146818_set_time(const struct device * dev,const struct rtc_time * timeptr)172 static int rtc_mc146818_set_time(const struct device *dev, const struct rtc_time *timeptr)
173 {
174 struct rtc_mc146818_data * const dev_data = dev->data;
175 uint8_t value;
176 int year;
177 int cent;
178 int ret;
179
180 k_spinlock_key_t key = k_spin_lock(&dev_data->lock);
181
182 if (timeptr == NULL) {
183 ret = -EINVAL;
184 goto out;
185 }
186
187 /* Check time valid */
188 if (!rtc_mc146818_validate_time(timeptr)) {
189 ret = -EINVAL;
190 goto out;
191 }
192
193 value = rtc_read(RTC_DATA);
194 rtc_write(RTC_DATA, value | RTC_UCI_BIT);
195
196 year = (1900 + timeptr->tm_year) % 100;
197 cent = (1900 + timeptr->tm_year) / 100;
198
199 rtc_write(RTC_SEC, (uint8_t)timeptr->tm_sec);
200 rtc_write(RTC_MIN, (uint8_t)timeptr->tm_min);
201 rtc_write(RTC_HOUR, (uint8_t)timeptr->tm_hour);
202 rtc_write(RTC_WDAY, (uint8_t)timeptr->tm_wday);
203 rtc_write(RTC_MDAY, (uint8_t)timeptr->tm_mday);
204 rtc_write(RTC_MONTH, (uint8_t)timeptr->tm_mon + 1);
205 rtc_write(RTC_YEAR, year);
206 rtc_write(RTC_CENTURY, cent);
207
208 value &= (~RTC_UCI_BIT);
209 rtc_write(RTC_DATA, value);
210 ret = 0;
211 out:
212 k_spin_unlock(&dev_data->lock, key);
213 return ret;
214 }
215
rtc_mc146818_get_time(const struct device * dev,struct rtc_time * timeptr)216 static int rtc_mc146818_get_time(const struct device *dev, struct rtc_time *timeptr)
217 {
218 struct rtc_mc146818_data * const dev_data = dev->data;
219 int ret;
220 uint8_t cent;
221 uint8_t year;
222 uint8_t value;
223
224 k_spinlock_key_t key = k_spin_lock(&dev_data->lock);
225
226 /* Validate arguments */
227 if (timeptr == NULL) {
228 ret = -EINVAL;
229 goto out;
230 }
231
232 if (!(rtc_read(RTC_REG_D) & RTC_VRT_BIT)) {
233 ret = -ENODATA;
234 goto out;
235 }
236
237 while (rtc_read(RTC_UIP) & RTC_UIP_BIT) {
238 continue;
239 }
240
241 cent = rtc_read(RTC_CENTURY);
242 year = rtc_read(RTC_YEAR);
243 timeptr->tm_mon = rtc_read(RTC_MONTH) - 1;
244 timeptr->tm_mday = rtc_read(RTC_MDAY);
245 timeptr->tm_wday = rtc_read(RTC_WDAY) - 1;
246 timeptr->tm_hour = rtc_read(RTC_HOUR);
247 timeptr->tm_min = rtc_read(RTC_MIN);
248 timeptr->tm_sec = rtc_read(RTC_SEC);
249
250 timeptr->tm_year = 100 * (int)cent + year - 1900;
251
252 timeptr->tm_nsec = 0;
253 timeptr->tm_yday = 0;
254 value = rtc_read(RTC_DATA);
255
256 /* Check time valid */
257 if (!rtc_mc146818_validate_time(timeptr)) {
258 ret = -ENODATA;
259 goto out;
260 }
261 ret = 0;
262 out:
263 k_spin_unlock(&dev_data->lock, key);
264 return ret;
265 }
266
267 #if defined(CONFIG_RTC_ALARM)
rtc_mc146818_validate_alarm(const struct rtc_time * timeptr,uint32_t mask)268 static bool rtc_mc146818_validate_alarm(const struct rtc_time *timeptr, uint32_t mask)
269 {
270 if ((mask & RTC_ALARM_TIME_MASK_SECOND) &&
271 (timeptr->tm_sec < MIN_SEC || timeptr->tm_sec > MAX_SEC)) {
272 return false;
273 }
274
275 if ((mask & RTC_ALARM_TIME_MASK_MINUTE) &&
276 (timeptr->tm_min < MIN_MIN || timeptr->tm_min > MAX_MIN)) {
277 return false;
278 }
279
280 if ((mask & RTC_ALARM_TIME_MASK_HOUR) &&
281 (timeptr->tm_hour < MIN_HOUR || timeptr->tm_hour > MAX_HOUR)) {
282 return false;
283 }
284
285 return true;
286 }
287
rtc_mc146818_alarm_get_supported_fields(const struct device * dev,uint16_t id,uint16_t * mask)288 static int rtc_mc146818_alarm_get_supported_fields(const struct device *dev, uint16_t id,
289 uint16_t *mask)
290 {
291 ARG_UNUSED(dev);
292
293 if (id != 0) {
294 return -EINVAL;
295 }
296
297 (*mask) = (RTC_ALARM_TIME_MASK_SECOND
298 | RTC_ALARM_TIME_MASK_MINUTE
299 | RTC_ALARM_TIME_MASK_HOUR);
300
301 return 0;
302 }
303
rtc_mc146818_alarm_set_time(const struct device * dev,uint16_t id,uint16_t mask,const struct rtc_time * timeptr)304 static int rtc_mc146818_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask,
305 const struct rtc_time *timeptr)
306 {
307 struct rtc_mc146818_data * const dev_data = dev->data;
308 int ret;
309
310 k_spinlock_key_t key = k_spin_lock(&dev_data->lock);
311
312 if (id != 0) {
313 ret = -EINVAL;
314 goto out;
315 }
316
317 if ((mask > 0) && (timeptr == NULL)) {
318 ret = -EINVAL;
319 goto out;
320 }
321
322 /* Check time valid */
323 if (!rtc_mc146818_validate_alarm(timeptr, mask)) {
324 ret = -EINVAL;
325 goto out;
326 }
327
328 if (mask & RTC_ALARM_TIME_MASK_SECOND) {
329 rtc_write(RTC_ALARM_SEC, timeptr->tm_sec);
330 } else {
331 rtc_write(RTC_ALARM_SEC, RTC_ALARM_DC);
332 }
333
334 if (mask & RTC_ALARM_TIME_MASK_MINUTE) {
335 rtc_write(RTC_ALARM_MIN, timeptr->tm_min);
336 } else {
337 rtc_write(RTC_ALARM_SEC, RTC_ALARM_DC);
338 }
339 if (mask & RTC_ALARM_TIME_MASK_HOUR) {
340 rtc_write(RTC_ALARM_HOUR, timeptr->tm_hour);
341 } else {
342 rtc_write(RTC_ALARM_SEC, RTC_ALARM_DC);
343 }
344
345 rtc_write(RTC_DATA, rtc_read(RTC_DATA) | RTC_AIE_BIT);
346 ret = 0;
347 out:
348 k_spin_unlock(&dev_data->lock, key);
349 return ret;
350 }
351
rtc_mc146818_alarm_get_time(const struct device * dev,uint16_t id,uint16_t * mask,struct rtc_time * timeptr)352 static int rtc_mc146818_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask,
353 struct rtc_time *timeptr)
354 {
355 struct rtc_mc146818_data * const dev_data = dev->data;
356 uint8_t value;
357 int ret;
358
359 k_spinlock_key_t key = k_spin_lock(&dev_data->lock);
360
361 if (id != 0) {
362 ret = -EINVAL;
363 goto out;
364 }
365
366 if (timeptr == NULL) {
367 ret = -EINVAL;
368 goto out;
369 }
370
371 (*mask) = 0;
372
373 value = rtc_read(RTC_ALARM_SEC);
374 if (value <= MAX_SEC) {
375 timeptr->tm_sec = value;
376 (*mask) |= RTC_ALARM_TIME_MASK_SECOND;
377 }
378
379 value = rtc_read(RTC_ALARM_MIN);
380 if (value <= MAX_SEC) {
381 timeptr->tm_min = value;
382 (*mask) |= RTC_ALARM_TIME_MASK_MINUTE;
383 }
384
385 value = rtc_read(RTC_ALARM_HOUR);
386 if (value <= MAX_SEC) {
387 timeptr->tm_hour = value;
388 (*mask) |= RTC_ALARM_TIME_MASK_HOUR;
389 }
390
391 ret = 0;
392 out:
393 k_spin_unlock(&dev_data->lock, key);
394 return ret;
395 }
396
rtc_mc146818_alarm_set_callback(const struct device * dev,uint16_t id,rtc_alarm_callback callback,void * user_data)397 static int rtc_mc146818_alarm_set_callback(const struct device *dev, uint16_t id,
398 rtc_alarm_callback callback, void *user_data)
399 {
400 struct rtc_mc146818_data * const dev_data = dev->data;
401
402 if (id != 0) {
403 return -EINVAL;
404 }
405
406 k_spinlock_key_t key = k_spin_lock(&dev_data->lock);
407
408 dev_data->cb = callback;
409 dev_data->cb_data = user_data;
410
411 if (callback != NULL) {
412 /* Enable Alarm callback */
413 rtc_write(RTC_DATA, (rtc_read(RTC_DATA) | RTC_AIE_BIT));
414 } else {
415 /* Disable Alarm callback */
416 rtc_write(RTC_DATA, (rtc_read(RTC_DATA) & (~RTC_AIE_BIT)));
417 }
418
419 k_spin_unlock(&dev_data->lock, key);
420 return 0;
421 }
422
rtc_mc146818_alarm_is_pending(const struct device * dev,uint16_t id)423 static int rtc_mc146818_alarm_is_pending(const struct device *dev, uint16_t id)
424 {
425 struct rtc_mc146818_data * const dev_data = dev->data;
426 int ret;
427
428 if (id != 0) {
429 return -EINVAL;
430 }
431
432 k_spinlock_key_t key = k_spin_lock(&dev_data->lock);
433
434 ret = dev_data->alarm_pending ? 1 : 0;
435 dev_data->alarm_pending = false;
436
437 k_spin_unlock(&dev_data->lock, key);
438 return ret;
439 }
440 #endif /* CONFIG_RTC_ALARM */
441
442 #if defined(CONFIG_RTC_UPDATE)
rtc_mc146818_update_set_callback(const struct device * dev,rtc_update_callback callback,void * user_data)443 static int rtc_mc146818_update_set_callback(const struct device *dev,
444 rtc_update_callback callback, void *user_data)
445 {
446 struct rtc_mc146818_data * const dev_data = dev->data;
447
448 k_spinlock_key_t key = k_spin_lock(&dev_data->lock);
449
450 dev_data->update_cb = callback;
451 dev_data->update_cb_data = user_data;
452
453 if (callback != NULL) {
454 /* Enable update callback */
455 rtc_write(RTC_DATA, (rtc_read(RTC_DATA) | RTC_UIE_BIT));
456 } else {
457 /* Disable update callback */
458 rtc_write(RTC_DATA, (rtc_read(RTC_DATA) & (~RTC_UIE_BIT)));
459 }
460
461
462 k_spin_unlock(&dev_data->lock, key);
463 return 0;
464 }
465
466 #endif /* CONFIG_RTC_UPDATE */
467
rtc_mc146818_isr(const struct device * dev)468 static void rtc_mc146818_isr(const struct device *dev)
469 {
470 struct rtc_mc146818_data * const dev_data = dev->data;
471 uint8_t regc;
472
473 ARG_UNUSED(dev_data);
474
475 /* Read register, which clears the register */
476 regc = rtc_read(RTC_FLAG);
477
478 #if defined(CONFIG_RTC_ALARM)
479 if (regc & RTC_AF_BIT) {
480 if (dev_data->cb) {
481 dev_data->cb(dev, 0, dev_data->cb_data);
482 dev_data->alarm_pending = false;
483 } else {
484 dev_data->alarm_pending = true;
485 }
486 }
487 #endif
488
489 #if defined(CONFIG_RTC_UPDATE)
490 if (regc & RTC_UEF_BIT) {
491 if (dev_data->update_cb) {
492 dev_data->update_cb(dev, dev_data->update_cb_data);
493 }
494 }
495 #endif
496 }
497
498 static const struct rtc_driver_api rtc_mc146818_driver_api = {
499 .set_time = rtc_mc146818_set_time,
500 .get_time = rtc_mc146818_get_time,
501 #if defined(CONFIG_RTC_ALARM)
502 .alarm_get_supported_fields = rtc_mc146818_alarm_get_supported_fields,
503 .alarm_set_time = rtc_mc146818_alarm_set_time,
504 .alarm_get_time = rtc_mc146818_alarm_get_time,
505 .alarm_is_pending = rtc_mc146818_alarm_is_pending,
506 .alarm_set_callback = rtc_mc146818_alarm_set_callback,
507 #endif /* CONFIG_RTC_ALARM */
508
509 #if defined(CONFIG_RTC_UPDATE)
510 .update_set_callback = rtc_mc146818_update_set_callback,
511 #endif /* CONFIG_RTC_UPDATE */
512 };
513
514 #define RTC_MC146818_INIT_FN_DEFINE(n) \
515 static int rtc_mc146818_init##n(const struct device *dev) \
516 { \
517 rtc_write(RTC_REG_A, \
518 _CONCAT(RTC_IN_CLK_DIV_BITS_, \
519 DT_INST_PROP(n, clock_frequency))); \
520 \
521 rtc_write(RTC_REG_B, RTC_DMODE_BIT | RTC_HFORMAT_BIT); \
522 \
523 IRQ_CONNECT(DT_INST_IRQN(0), \
524 DT_INST_IRQ(0, priority), \
525 rtc_mc146818_isr, DEVICE_DT_INST_GET(n), \
526 DT_INST_IRQ(0, sense)); \
527 \
528 irq_enable(DT_INST_IRQN(0)); \
529 \
530 return 0; \
531 }
532
533 #define RTC_MC146818_DEV_CFG(inst) \
534 struct rtc_mc146818_data rtc_mc146818_data##inst; \
535 \
536 RTC_MC146818_INIT_FN_DEFINE(inst) \
537 \
538 DEVICE_DT_INST_DEFINE(inst, &rtc_mc146818_init##inst, NULL, \
539 &rtc_mc146818_data##inst, NULL, POST_KERNEL, \
540 CONFIG_RTC_INIT_PRIORITY, \
541 &rtc_mc146818_driver_api); \
542
543 DT_INST_FOREACH_STATUS_OKAY(RTC_MC146818_DEV_CFG)
544