1 /* Copyright (c) 2024 Daniel Kampert
2  * Author: Daniel Kampert <DanielKampert@kampis-Elektroecke.de>
3  */
4 
5 #include <zephyr/device.h>
6 #include <zephyr/devicetree.h>
7 #include <zephyr/drivers/i2c.h>
8 #include <zephyr/drivers/gpio.h>
9 #include <zephyr/drivers/rtc.h>
10 #include <zephyr/logging/log.h>
11 #include <zephyr/sys/byteorder.h>
12 #include "rtc_utils.h"
13 
14 #define RV8263C8_REGISTER_CONTROL_1     0x00
15 #define RV8263C8_REGISTER_CONTROL_2     0x01
16 #define RV8263C8_REGISTER_OFFSET        0x02
17 #define RV8263C8_REGISTER_RAM           0x03
18 #define RV8263C8_REGISTER_SECONDS       0x04
19 #define RV8263C8_REGISTER_MINUTES       0x05
20 #define RV8263C8_REGISTER_HOURS         0x06
21 #define RV8263C8_REGISTER_DATE          0x07
22 #define RV8263C8_REGISTER_WEEKDAY       0x08
23 #define RV8263C8_REGISTER_MONTH         0x09
24 #define RV8263C8_REGISTER_YEAR          0x0A
25 #define RV8263C8_REGISTER_SECONDS_ALARM 0x0B
26 #define RV8263C8_REGISTER_MINUTES_ALARM 0x0C
27 #define RV8263C8_REGISTER_HOURS_ALARM   0x0D
28 #define RV8263C8_REGISTER_DATE_ALARM    0x0E
29 #define RV8263C8_REGISTER_WEEKDAY_ALARM 0x0F
30 #define RV8263C8_REGISTER_TIMER_VALUE   0x10
31 #define RV8263C8_REGISTER_TIMER_MODE    0x11
32 
33 #define RV8263_BM_FAST_MODE                 (0x01 << 7)
34 #define RV8263_BM_NORMAL_MODE               (0x00 << 7)
35 #define RV8263C8_BM_24H_MODE_ENABLE         (0x00 << 1)
36 #define RV8263C8_BM_24H_MODE_DISABLE        (0x00 << 1)
37 #define RV8263C8_BM_CLOCK_ENABLE            (0x00 << 5)
38 #define RV8263C8_BM_CLOCK_DISABLE           (0x01 << 5)
39 #define RV8263C8_BM_ALARM_INT_ENABLE        (0x01 << 7)
40 #define RV8263C8_BM_ALARM_INT_DISABLE       (0x00 << 7)
41 #define RV8263C8_BM_MINUTE_INT_ENABLE       (0x01 << 5)
42 #define RV8263C8_BM_MINUTE_INT_DISABLE      (0x00 << 5)
43 #define RV8263C8_BM_HALF_MINUTE_INT_ENABLE  (0x01 << 4)
44 #define RV8263C8_BM_HALF_MINUTE_INT_DISABLE (0x00 << 4)
45 #define RV8263C8_BM_ALARM_ENABLE            (0x00 << 7)
46 #define RV8263C8_BM_ALARM_DISABLE           (0x01 << 7)
47 #define RV8263C8_BM_AF                      (0x01 << 6)
48 #define RV8263C8_BM_TF                      (0x01 << 3)
49 #define RV8263_BM_MODE                      (0x01 << 7)
50 #define RV8263_BM_TD_1HZ                    (0x02 << 3)
51 #define RV8263_BM_TE_ENABLE                 (0x01 << 2)
52 #define RV8263_BM_TIE_ENABLE                (0x01 << 1)
53 #define RV8263_BM_TI_TP_PULSE               (0x01 << 0)
54 #define RV8263_BM_OS                        (0x01 << 7)
55 #define RV8263C8_BM_SOFTWARE_RESET          (0x58)
56 #define RV8263C8_BM_REGISTER_OFFSET         0x7F
57 #define RV8263_YEAR_OFFSET                  (2000 - 1900)
58 
59 #define SECONDS_BITS  GENMASK(6, 0)
60 #define MINUTES_BITS  GENMASK(7, 0)
61 #define HOURS_BITS    GENMASK(5, 0)
62 #define DATE_BITS     GENMASK(5, 0)
63 #define MONTHS_BITS   GENMASK(4, 0)
64 #define WEEKDAY_BITS  GENMASK(2, 0)
65 #define YEAR_BITS     GENMASK(7, 0)
66 #define VALIDATE_24HR BIT(6)
67 
68 #define DT_DRV_COMPAT microcrystal_rv_8263_c8
69 
70 LOG_MODULE_REGISTER(microcrystal_rv8263c8, CONFIG_RTC_LOG_LEVEL);
71 
72 struct rv8263c8_config {
73 	struct i2c_dt_spec i2c_bus;
74 	uint32_t clkout;
75 
76 #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
77 	struct gpio_dt_spec int_gpio;
78 #endif
79 };
80 
81 struct rv8263c8_data {
82 	struct k_sem lock;
83 
84 #if (CONFIG_RTC_ALARM || CONFIG_RTC_UPDATE) && DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
85 	const struct device *dev;
86 	struct gpio_callback gpio_cb;
87 #endif
88 
89 #if (CONFIG_RTC_ALARM || CONFIG_RTC_UPDATE) && DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
90 	struct k_work interrupt_work;
91 #endif
92 
93 #if CONFIG_RTC_ALARM && DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
94 	rtc_alarm_callback alarm_cb;
95 	void *alarm_cb_data;
96 #endif
97 
98 #if CONFIG_RTC_UPDATE && DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
99 	rtc_update_callback update_cb;
100 	void *update_cb_data;
101 #endif
102 };
103 
rv8263c8_update_disable_timer(const struct device * dev)104 static int rv8263c8_update_disable_timer(const struct device *dev)
105 {
106 	int err;
107 	uint8_t buf[2];
108 	const struct rv8263c8_config *config = dev->config;
109 
110 	/* Value 0 disables the timer. */
111 	buf[0] = RV8263C8_REGISTER_TIMER_VALUE;
112 	buf[1] = 0;
113 	err = i2c_write_dt(&config->i2c_bus, buf, 2);
114 	if (err < 0) {
115 		return err;
116 	}
117 
118 	buf[0] = RV8263C8_REGISTER_TIMER_MODE;
119 	return i2c_write_dt(&config->i2c_bus, buf, 2);
120 }
121 
122 #if (CONFIG_RTC_ALARM || CONFIG_RTC_UPDATE) && DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
rv8263c8_gpio_callback_handler(const struct device * p_port,struct gpio_callback * p_cb,gpio_port_pins_t pins)123 static void rv8263c8_gpio_callback_handler(const struct device *p_port, struct gpio_callback *p_cb,
124 					   gpio_port_pins_t pins)
125 {
126 	ARG_UNUSED(pins);
127 	ARG_UNUSED(p_port);
128 
129 	struct rv8263c8_data *data = CONTAINER_OF(p_cb, struct rv8263c8_data, gpio_cb);
130 
131 #if CONFIG_RTC_ALARM || CONFIG_RTC_UPDATE
132 	k_work_submit(&data->interrupt_work);
133 #endif
134 }
135 #endif
136 
137 #if CONFIG_RTC_UPDATE && DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
rv8263c8_update_enable_timer(const struct device * dev)138 static int rv8263c8_update_enable_timer(const struct device *dev)
139 {
140 	int err;
141 	const struct rv8263c8_config *config = dev->config;
142 	uint8_t buf[2];
143 
144 	/* Set the timer preload value for 1 second. */
145 	buf[0] = RV8263C8_REGISTER_TIMER_VALUE;
146 	buf[1] = 1;
147 	err = i2c_write_dt(&config->i2c_bus, buf, 2);
148 	if (err < 0) {
149 		return err;
150 	}
151 
152 	buf[0] = RV8263C8_REGISTER_TIMER_MODE;
153 	buf[1] = RV8263_BM_TD_1HZ | RV8263_BM_TE_ENABLE | RV8263_BM_TIE_ENABLE |
154 		 RV8263_BM_TI_TP_PULSE;
155 	return i2c_write_dt(&config->i2c_bus, buf, 2);
156 }
157 #endif
158 
159 #if (CONFIG_RTC_ALARM || CONFIG_RTC_UPDATE) && DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
rv8263c8_interrupt_worker(struct k_work * p_work)160 static void rv8263c8_interrupt_worker(struct k_work *p_work)
161 {
162 	uint8_t reg;
163 	struct rv8263c8_data *data = CONTAINER_OF(p_work, struct rv8263c8_data, interrupt_work);
164 	const struct rv8263c8_config *config = data->dev->config;
165 
166 	(void)i2c_reg_read_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_CONTROL_2, &reg);
167 
168 #if CONFIG_RTC_ALARM
169 	/* An alarm interrupt occurs. Clear the timer flag, */
170 	/* and call the callback. */
171 	if (reg & RV8263C8_BM_AF) {
172 		LOG_DBG("Process alarm interrupt");
173 		reg &= ~RV8263C8_BM_AF;
174 
175 		if (data->alarm_cb != NULL) {
176 			LOG_DBG("Calling alarm callback");
177 			data->alarm_cb(data->dev, 0, data->alarm_cb_data);
178 		}
179 	}
180 #endif
181 
182 #if CONFIG_RTC_UPDATE
183 	/* A timer interrupt occurs. Clear the timer flag, */
184 	/* enable the timer again and call the callback. */
185 	if (reg & RV8263C8_BM_TF) {
186 		LOG_DBG("Process update interrupt");
187 		reg &= ~RV8263C8_BM_TF;
188 
189 		if (data->update_cb != NULL) {
190 			LOG_DBG("Calling update callback");
191 			data->update_cb(data->dev, data->update_cb_data);
192 		}
193 
194 		rv8263c8_update_enable_timer(data->dev);
195 	}
196 #endif
197 
198 	i2c_reg_write_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_CONTROL_2, reg);
199 }
200 #endif
201 
rv8263c8_time_set(const struct device * dev,const struct rtc_time * timeptr)202 static int rv8263c8_time_set(const struct device *dev, const struct rtc_time *timeptr)
203 {
204 	uint8_t regs[8];
205 	const struct rv8263c8_config *config = dev->config;
206 
207 	if (timeptr == NULL || (timeptr->tm_year < RV8263_YEAR_OFFSET)) {
208 		LOG_ERR("invalid time");
209 		return -EINVAL;
210 	}
211 
212 	LOG_DBG("Set time: year = %u, mon = %u, mday = %u, wday = %u, hour = %u, min = %u, sec = "
213 		"%u",
214 		timeptr->tm_year, timeptr->tm_mon, timeptr->tm_mday, timeptr->tm_wday,
215 		timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec);
216 
217 	regs[0] = RV8263C8_REGISTER_SECONDS;
218 	regs[1] = bin2bcd(timeptr->tm_sec) & SECONDS_BITS;
219 	regs[2] = bin2bcd(timeptr->tm_min) & MINUTES_BITS;
220 	regs[3] = bin2bcd(timeptr->tm_hour) & HOURS_BITS;
221 	regs[4] = bin2bcd(timeptr->tm_mday) & DATE_BITS;
222 	regs[5] = bin2bcd(timeptr->tm_wday) & WEEKDAY_BITS;
223 	regs[6] = (bin2bcd(timeptr->tm_mon) & MONTHS_BITS) + 1;
224 	regs[7] = bin2bcd(timeptr->tm_year - RV8263_YEAR_OFFSET) & YEAR_BITS;
225 
226 	return i2c_write_dt(&config->i2c_bus, regs, sizeof(regs));
227 }
228 
rv8263c8_time_get(const struct device * dev,struct rtc_time * timeptr)229 static int rv8263c8_time_get(const struct device *dev, struct rtc_time *timeptr)
230 {
231 	int err;
232 	uint8_t regs[7];
233 	const struct rv8263c8_config *config = dev->config;
234 
235 	if (timeptr == NULL) {
236 		return -EINVAL;
237 	}
238 
239 	err = i2c_burst_read_dt(&config->i2c_bus, RV8263C8_REGISTER_SECONDS, regs, sizeof(regs));
240 	if (err < 0) {
241 		return err;
242 	}
243 
244 	/* Return an error when the oscillator is stopped. */
245 	if (regs[0] & RV8263_BM_OS) {
246 		return -ENODATA;
247 	}
248 
249 	timeptr->tm_sec = bcd2bin(regs[0] & SECONDS_BITS);
250 	timeptr->tm_min = bcd2bin(regs[1] & MINUTES_BITS);
251 	timeptr->tm_hour = bcd2bin(regs[2] & HOURS_BITS);
252 	timeptr->tm_mday = bcd2bin(regs[3] & DATE_BITS);
253 	timeptr->tm_wday = bcd2bin(regs[4] & WEEKDAY_BITS);
254 	timeptr->tm_mon = bcd2bin(regs[5] & MONTHS_BITS) - 1;
255 	timeptr->tm_year = bcd2bin(regs[6] & YEAR_BITS) + RV8263_YEAR_OFFSET;
256 
257 	/* Unused. */
258 	timeptr->tm_nsec = 0;
259 	timeptr->tm_isdst = -1;
260 	timeptr->tm_yday = -1;
261 
262 	/* Validate the chip in 24hr mode. */
263 	if (regs[2] & VALIDATE_24HR) {
264 		return -ENODATA;
265 	}
266 
267 	LOG_DBG("Get time: year = %u, mon = %u, mday = %u, wday = %u, hour = %u, min = %u, sec = "
268 		"%u",
269 		timeptr->tm_year, timeptr->tm_mon, timeptr->tm_mday, timeptr->tm_wday,
270 		timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec);
271 
272 	return 0;
273 }
274 
rv8263c8_init(const struct device * dev)275 static int rv8263c8_init(const struct device *dev)
276 {
277 	int err;
278 	int temp;
279 	struct rv8263c8_data *data = dev->data;
280 	const struct rv8263c8_config *config = dev->config;
281 
282 #if (CONFIG_RTC_ALARM || CONFIG_RTC_UPDATE) && DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
283 	if (config->int_gpio.port == NULL) {
284 		return -EINVAL;
285 	}
286 #endif
287 
288 	if (!i2c_is_ready_dt(&config->i2c_bus)) {
289 		LOG_ERR("I2C bus not ready!");
290 		return -ENODEV;
291 	}
292 
293 	k_sem_init(&data->lock, 1, 1);
294 
295 	err = rv8263c8_update_disable_timer(dev);
296 	if (err < 0) {
297 		LOG_ERR("Error while disabling the timer! Error: %i", err);
298 		return err;
299 	}
300 
301 	err = i2c_reg_write_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_CONTROL_1,
302 				    RV8263C8_BM_24H_MODE_DISABLE | RV8263C8_BM_CLOCK_ENABLE);
303 	if (err < 0) {
304 		LOG_ERR("Error while writing CONTROL_1! Error: %i", err);
305 		return err;
306 	}
307 
308 	temp = config->clkout;
309 	LOG_DBG("Configure ClkOut: %u", temp);
310 
311 	err = i2c_reg_write_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_CONTROL_2,
312 				    RV8263C8_BM_AF | temp);
313 	if (err < 0) {
314 		LOG_ERR("Error while writing CONTROL_2! Error: %i", err);
315 		return err;
316 	}
317 
318 	LOG_DBG("Configure ClkOut: %u", temp);
319 
320 #if CONFIG_RTC_UPDATE && DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
321 	uint8_t buf[2];
322 
323 	buf[0] = RV8263C8_REGISTER_TIMER_MODE;
324 	buf[1] = 0;
325 	err = i2c_write_dt(&config->i2c_bus, buf, 2);
326 	if (err < 0) {
327 		LOG_ERR("Error while writing CONTROL2! Error: %i", err);
328 		return err;
329 	}
330 #endif
331 
332 #if (CONFIG_RTC_ALARM || CONFIG_RTC_UPDATE) && DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
333 	LOG_DBG("Configure interrupt pin");
334 	if (!gpio_is_ready_dt(&config->int_gpio)) {
335 		LOG_ERR("GPIO not ready!");
336 		return err;
337 	}
338 
339 	err = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT);
340 	if (err < 0) {
341 		LOG_ERR("Failed to configure GPIO! Error: %u", err);
342 		return err;
343 	}
344 
345 	err = gpio_pin_interrupt_configure_dt(&config->int_gpio, GPIO_INT_EDGE_FALLING);
346 	if (err < 0) {
347 		LOG_ERR("Failed to configure interrupt! Error: %u", err);
348 		return err;
349 	}
350 
351 	gpio_init_callback(&data->gpio_cb, rv8263c8_gpio_callback_handler,
352 			   BIT(config->int_gpio.pin));
353 
354 	err = gpio_add_callback_dt(&config->int_gpio, &data->gpio_cb);
355 	if (err < 0) {
356 		LOG_ERR("Failed to add GPIO callback! Error: %u", err);
357 		return err;
358 	}
359 #endif
360 
361 	(void)k_sem_take(&data->lock, K_FOREVER);
362 #if (CONFIG_RTC_ALARM || CONFIG_RTC_UPDATE) && DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
363 	data->interrupt_work.handler = rv8263c8_interrupt_worker;
364 #endif
365 
366 #if (CONFIG_RTC_ALARM || CONFIG_RTC_UPDATE) && DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
367 	data->dev = dev;
368 #endif
369 	k_sem_give(&data->lock);
370 	LOG_DBG("Done");
371 
372 	return 0;
373 }
374 
375 #if CONFIG_RTC_ALARM
rv8263c8_alarm_get_supported_fields(const struct device * dev,uint16_t id,uint16_t * p_mask)376 static int rv8263c8_alarm_get_supported_fields(const struct device *dev, uint16_t id,
377 					       uint16_t *p_mask)
378 {
379 	ARG_UNUSED(dev);
380 	ARG_UNUSED(id);
381 
382 	(*p_mask) = (RTC_ALARM_TIME_MASK_SECOND | RTC_ALARM_TIME_MASK_MINUTE |
383 		     RTC_ALARM_TIME_MASK_HOUR | RTC_ALARM_TIME_MASK_MONTHDAY |
384 		     RTC_ALARM_TIME_MASK_WEEKDAY);
385 
386 	return 0;
387 }
388 
rv8263c8_alarm_set_time(const struct device * dev,uint16_t id,uint16_t mask,const struct rtc_time * timeptr)389 static int rv8263c8_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask,
390 				   const struct rtc_time *timeptr)
391 {
392 	int err;
393 	uint8_t regs[6];
394 	const struct rv8263c8_config *config = dev->config;
395 
396 	ARG_UNUSED(id);
397 
398 	if ((mask > 0) && (timeptr == NULL)) {
399 		return -EINVAL;
400 	}
401 
402 	if (!rtc_utils_validate_rtc_time(timeptr, mask)) {
403 		LOG_ERR("Invalid mask!");
404 		return -EINVAL;
405 	}
406 
407 	if (mask == 0) {
408 		err = i2c_reg_update_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_CONTROL_2,
409 					     RV8263C8_BM_ALARM_INT_ENABLE | RV8263C8_BM_AF,
410 					     RV8263C8_BM_ALARM_INT_DISABLE);
411 	} else {
412 		/* Clear the AIE and AF bit to prevent false triggering of the alarm. */
413 		err = i2c_reg_update_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_CONTROL_2,
414 					     RV8263C8_BM_ALARM_INT_ENABLE | RV8263C8_BM_AF, 0);
415 	}
416 
417 	if (err < 0) {
418 		LOG_ERR("Error while enabling alarm! Error: %i", err);
419 		return err;
420 	}
421 
422 	regs[0] = RV8263C8_REGISTER_SECONDS_ALARM;
423 
424 	if (mask & RTC_ALARM_TIME_MASK_SECOND) {
425 		regs[1] = bin2bcd(timeptr->tm_sec) & SECONDS_BITS;
426 	} else {
427 		regs[1] = RV8263C8_BM_ALARM_DISABLE;
428 	}
429 
430 	if (mask & RTC_ALARM_TIME_MASK_MINUTE) {
431 		regs[2] = bin2bcd(timeptr->tm_min) & MINUTES_BITS;
432 	} else {
433 		regs[2] = RV8263C8_BM_ALARM_DISABLE;
434 	}
435 
436 	if (mask & RTC_ALARM_TIME_MASK_HOUR) {
437 		regs[3] = bin2bcd(timeptr->tm_hour) & HOURS_BITS;
438 	} else {
439 		regs[3] = RV8263C8_BM_ALARM_DISABLE;
440 	}
441 
442 	if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) {
443 		regs[4] = bin2bcd(timeptr->tm_mday) & DATE_BITS;
444 	} else {
445 		regs[4] = RV8263C8_BM_ALARM_DISABLE;
446 	}
447 
448 	if (mask & RTC_ALARM_TIME_MASK_WEEKDAY) {
449 		regs[5] = bin2bcd(timeptr->tm_wday) & WEEKDAY_BITS;
450 	} else {
451 		regs[5] = RV8263C8_BM_ALARM_DISABLE;
452 	}
453 
454 	err = i2c_write_dt(&config->i2c_bus, regs, sizeof(regs));
455 	if (err < 0) {
456 		LOG_ERR("Error while setting alarm time! Error: %i", err);
457 		return err;
458 	}
459 
460 	if (mask != 0) {
461 		/* Enable the alarm interrupt */
462 		err = i2c_reg_update_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_CONTROL_2,
463 					     RV8263C8_BM_ALARM_INT_ENABLE,
464 					     RV8263C8_BM_ALARM_INT_ENABLE);
465 	}
466 
467 	return err;
468 }
469 
rv8263c8_alarm_get_time(const struct device * dev,uint16_t id,uint16_t * p_mask,struct rtc_time * timeptr)470 static int rv8263c8_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *p_mask,
471 				   struct rtc_time *timeptr)
472 {
473 	int err;
474 	const struct rv8263c8_config *config = dev->config;
475 	uint8_t value[5];
476 
477 	ARG_UNUSED(id);
478 
479 	if (timeptr == NULL) {
480 		return -EINVAL;
481 	}
482 
483 	(*p_mask) = 0;
484 
485 	err = i2c_burst_read_dt(&config->i2c_bus, RV8263C8_REGISTER_SECONDS_ALARM, value,
486 				sizeof(value));
487 	if (err < 0) {
488 		LOG_ERR("Error while reading alarm! Error: %i", err);
489 		return err;
490 	}
491 
492 	/* Check if the highest bit is not set. If so the alarm is enabled. */
493 	if ((value[0] & RV8263C8_BM_ALARM_DISABLE) == 0) {
494 		timeptr->tm_sec = bcd2bin(value[0]) & SECONDS_BITS;
495 		(*p_mask) |= RTC_ALARM_TIME_MASK_SECOND;
496 	}
497 
498 	if ((value[1] & RV8263C8_BM_ALARM_DISABLE) == 0) {
499 		timeptr->tm_min = bcd2bin(value[1]) & MINUTES_BITS;
500 		(*p_mask) |= RTC_ALARM_TIME_MASK_MINUTE;
501 	}
502 
503 	if ((value[2] & RV8263C8_BM_ALARM_DISABLE) == 0) {
504 		timeptr->tm_hour = bcd2bin(value[2]) & HOURS_BITS;
505 		(*p_mask) |= RTC_ALARM_TIME_MASK_HOUR;
506 	}
507 
508 	if ((value[3] & RV8263C8_BM_ALARM_DISABLE) == 0) {
509 		timeptr->tm_mday = bcd2bin(value[3]) & DATE_BITS;
510 		(*p_mask) |= RTC_ALARM_TIME_MASK_MONTHDAY;
511 	}
512 
513 	if ((value[4] & RV8263C8_BM_ALARM_DISABLE) == 0) {
514 		timeptr->tm_wday = bcd2bin(value[4]) & WEEKDAY_BITS;
515 		(*p_mask) |= RTC_ALARM_TIME_MASK_WEEKDAY;
516 	}
517 
518 	return 0;
519 }
520 
rv8263c8_alarm_set_callback(const struct device * dev,uint16_t id,rtc_alarm_callback callback,void * user_data)521 static int rv8263c8_alarm_set_callback(const struct device *dev, uint16_t id,
522 				       rtc_alarm_callback callback, void *user_data)
523 {
524 	const struct rv8263c8_config *config = dev->config;
525 
526 #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
527 	struct rv8263c8_data *data = dev->data;
528 #endif
529 
530 	ARG_UNUSED(id);
531 
532 #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
533 	if (config->int_gpio.port == NULL) {
534 		return -ENOTSUP;
535 	}
536 
537 	(void)k_sem_take(&data->lock, K_FOREVER);
538 	data->alarm_cb = callback;
539 	data->alarm_cb_data = user_data;
540 	k_sem_give(&data->lock);
541 #else
542 	return -ENOTSUP;
543 #endif
544 
545 	return 0;
546 }
547 
rv8263c8_alarm_is_pending(const struct device * dev,uint16_t id)548 static int rv8263c8_alarm_is_pending(const struct device *dev, uint16_t id)
549 {
550 	int err;
551 	uint8_t reg;
552 	const struct rv8263c8_config *config = dev->config;
553 
554 	ARG_UNUSED(id);
555 
556 	err = i2c_reg_read_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_CONTROL_2, &reg);
557 	if (err) {
558 		return err;
559 	}
560 
561 	if (reg & RV8263C8_BM_AF) {
562 		reg &= ~RV8263C8_BM_AF;
563 		err = i2c_reg_write_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_CONTROL_2, reg);
564 		if (err) {
565 			return err;
566 		}
567 
568 		return 1;
569 	}
570 
571 	return 0;
572 }
573 #endif
574 
575 #if CONFIG_RTC_UPDATE && DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
rv8263_update_callback(const struct device * dev,rtc_update_callback callback,void * user_data)576 int rv8263_update_callback(const struct device *dev, rtc_update_callback callback, void *user_data)
577 {
578 	struct rv8263c8_data *const data = dev->data;
579 
580 	(void)k_sem_take(&data->lock, K_FOREVER);
581 	data->update_cb = callback;
582 	data->update_cb_data = user_data;
583 	k_sem_give(&data->lock);
584 
585 	/* Disable the update callback. */
586 	if ((callback == NULL) && (user_data == NULL)) {
587 		return rv8263c8_update_disable_timer(dev);
588 	}
589 
590 	return rv8263c8_update_enable_timer(dev);
591 }
592 #endif
593 
594 #ifdef CONFIG_RTC_CALIBRATION
rv8263c8_calibration_set(const struct device * dev,int32_t calibration)595 int rv8263c8_calibration_set(const struct device *dev, int32_t calibration)
596 {
597 	int8_t offset;
598 	int32_t test_mode0;
599 	int32_t test_mode1;
600 	int32_t offset_ppm_mode0;
601 	int32_t offset_ppm_mode1;
602 	const struct rv8263c8_config *config = dev->config;
603 
604 	/* NOTE: The RTC API is using a PPB (Parts Per Billion) value. The RTC is using PPM.
605 	 * Here we calculate the offset when using MODE = 0.
606 	 *  Formula from the application manual:
607 	 *  Offset [ppm] = (calibration [ppb] / (4.34 [ppm] x 1000))
608 	 */
609 	offset_ppm_mode0 = calibration / 4340;
610 
611 	/* Here we calculate the offset when using MODE = 1.
612 	 *  Formula from the application manual:
613 	 *  Offset [ppm] = (calibration [ppb] / (4.069 [ppm] x 1000))
614 	 */
615 	offset_ppm_mode1 = calibration / 4069;
616 
617 	LOG_DBG("Offset Mode = 0: %i", offset_ppm_mode0);
618 	LOG_DBG("Offset Mode = 1: %i", offset_ppm_mode1);
619 
620 	test_mode0 = offset_ppm_mode0 * 4340;
621 	test_mode0 = calibration - test_mode0;
622 	test_mode1 = offset_ppm_mode1 * 4069;
623 	test_mode1 = calibration - test_mode1;
624 
625 	/* Compare the values and select the value with the smallest error. */
626 	test_mode0 = test_mode0 < 0 ? -test_mode0 : test_mode0;
627 	test_mode1 = test_mode1 < 0 ? -test_mode1 : test_mode1;
628 	if (test_mode0 > test_mode1) {
629 		LOG_DBG("Use fast mode (Mode = 1)");
630 
631 		/* Error with MODE = 1 is smaller -> Use MODE = 1. */
632 		offset = RV8263_BM_FAST_MODE | (offset_ppm_mode1 & GENMASK(7, 0));
633 	} else {
634 		LOG_DBG("Use normal mode (Mode = 0)");
635 
636 		/* Error with MODE = 0 is smaller -> Use MODE = 0. */
637 		offset = RV8263_BM_NORMAL_MODE | (offset_ppm_mode0 & GENMASK(7, 0));
638 	}
639 
640 	LOG_DBG("Set offset value: %i", (offset & RV8263C8_BM_REGISTER_OFFSET));
641 
642 	return i2c_reg_write_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_OFFSET, offset);
643 }
644 
rv8263c8_calibration_get(const struct device * dev,int32_t * calibration)645 int rv8263c8_calibration_get(const struct device *dev, int32_t *calibration)
646 {
647 	int err;
648 	int32_t temp;
649 	int8_t offset;
650 	const struct rv8263c8_config *config = dev->config;
651 
652 	if (calibration == NULL) {
653 		return -EINVAL;
654 	}
655 
656 	err = i2c_reg_read_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_OFFSET, &offset);
657 	if (err) {
658 		return err;
659 	}
660 
661 	/* Convert the signed 7 bit into a signed 8 bit value. */
662 	if (offset & (0x01 << 6)) {
663 		temp = offset | (0x01 << 7);
664 	} else {
665 		temp = offset & (0x3F);
666 		temp &= ~(0x01 << 7);
667 	}
668 
669 	LOG_DBG("Read offset: %i", temp);
670 
671 	if (offset & RV8263_BM_FAST_MODE) {
672 		temp = temp * 4340L;
673 	} else {
674 		temp = temp * 4069L;
675 	}
676 
677 	*calibration = temp;
678 
679 	return 0;
680 }
681 #endif
682 
683 static DEVICE_API(rtc, rv8263c8_driver_api) = {
684 	.set_time = rv8263c8_time_set,
685 	.get_time = rv8263c8_time_get,
686 #if CONFIG_RTC_ALARM
687 	.alarm_get_supported_fields = rv8263c8_alarm_get_supported_fields,
688 	.alarm_set_time = rv8263c8_alarm_set_time,
689 	.alarm_get_time = rv8263c8_alarm_get_time,
690 	.alarm_is_pending = rv8263c8_alarm_is_pending,
691 	.alarm_set_callback = rv8263c8_alarm_set_callback,
692 #endif
693 #if CONFIG_RTC_UPDATE && DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios)
694 	.update_set_callback = rv8263_update_callback,
695 #endif
696 #ifdef CONFIG_RTC_CALIBRATION
697 	.set_calibration = rv8263c8_calibration_set,
698 	.get_calibration = rv8263c8_calibration_get,
699 #endif
700 };
701 
702 #define RV8263_DEFINE(inst)                                                                        \
703 	static struct rv8263c8_data rv8263c8_data_##inst;                                          \
704 	static const struct rv8263c8_config rv8263c8_config_##inst = {                             \
705 		.i2c_bus = I2C_DT_SPEC_INST_GET(inst),                                             \
706 		.clkout = DT_INST_ENUM_IDX(inst, clkout),                                          \
707 		IF_ENABLED(DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios),                            \
708 			   (.int_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, {0})))};         \
709 	DEVICE_DT_INST_DEFINE(inst, &rv8263c8_init, NULL, &rv8263c8_data_##inst,                   \
710 			      &rv8263c8_config_##inst, POST_KERNEL, CONFIG_RTC_INIT_PRIORITY,      \
711 			      &rv8263c8_driver_api);
712 
713 DT_INST_FOREACH_STATUS_OKAY(RV8263_DEFINE)
714