1 /*
2  * Copyright (c) 2019-2023 Henrik Brix Andersen <henrik@brixandersen.dk>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nxp_pcf8523
8 
9 #include <zephyr/drivers/gpio.h>
10 #include <zephyr/drivers/i2c.h>
11 #include <zephyr/drivers/rtc.h>
12 #include <zephyr/logging/log.h>
13 #include <zephyr/pm/device.h>
14 #include <zephyr/sys/util.h>
15 
16 LOG_MODULE_REGISTER(pcf8523, CONFIG_RTC_LOG_LEVEL);
17 
18 /* PCF8523 register addresses */
19 #define PCF8523_CONTROL_1	0x00U
20 #define PCF8523_CONTROL_2	0x01U
21 #define PCF8523_CONTROL_3	0x02U
22 #define PCF8523_SECONDS		0x03U
23 #define PCF8523_MINUTES		0x04U
24 #define PCF8523_HOURS		0x05U
25 #define PCF8523_DAYS		0x06U
26 #define PCF8523_WEEKDAYS	0x07U
27 #define PCF8523_MONTHS		0x08U
28 #define PCF8523_YEARS		0x09U
29 #define PCF8523_MINUTE_ALARM	0x0aU
30 #define PCF8523_HOUR_ALARM	0x0bU
31 #define PCF8523_DAY_ALARM	0x0cU
32 #define PCF8523_WEEKDAY_ALARM	0x0dU
33 #define PCF8523_OFFSET		0x0eU
34 #define PCF8523_TMR_CLKOUT_CTRL 0x0fU
35 #define PCF8523_TMR_A_FREQ_CTRL 0x10U
36 #define PCF8523_TMR_A_REG	0x11U
37 #define PCF8523_TMR_B_FREQ_CTRL 0x12U
38 #define PCF8523_TMR_B_REG	0x13U
39 
40 /* Control register bits */
41 #define PCF8523_CONTROL_1_CAP_SEL BIT(7)
42 #define PCF8523_CONTROL_1_T	  BIT(6)
43 #define PCF8523_CONTROL_1_STOP	  BIT(5)
44 #define PCF8523_CONTROL_1_SR	  BIT(4)
45 #define PCF8523_CONTROL_1_12_24	  BIT(3)
46 #define PCF8523_CONTROL_1_SIE	  BIT(2)
47 #define PCF8523_CONTROL_1_AIE	  BIT(1)
48 #define PCF8523_CONTROL_1_CIE	  BIT(0)
49 #define PCF8523_CONTROL_2_WTAF	  BIT(7)
50 #define PCF8523_CONTROL_2_CTAF	  BIT(6)
51 #define PCF8523_CONTROL_2_CTBF	  BIT(5)
52 #define PCF8523_CONTROL_2_SF	  BIT(4)
53 #define PCF8523_CONTROL_2_AF	  BIT(3)
54 #define PCF8523_CONTROL_2_WTAIE	  BIT(2)
55 #define PCF8523_CONTROL_2_CTAIE	  BIT(1)
56 #define PCF8523_CONTROL_2_CTBIE	  BIT(0)
57 #define PCF8523_CONTROL_3_PM_MASK GENMASK(7, 5)
58 #define PCF8523_CONTROL_3_BSF	  BIT(3)
59 #define PCF8523_CONTROL_3_BLF	  BIT(2)
60 #define PCF8523_CONTROL_3_BSIE	  BIT(1)
61 #define PCF8523_CONTROL_3_BLIE	  BIT(0)
62 
63 /* Time and date register bits */
64 #define PCF8523_SECONDS_OS     BIT(7)
65 #define PCF8523_SECONDS_MASK   GENMASK(6, 0)
66 #define PCF8523_MINUTES_MASK   GENMASK(6, 0)
67 #define PCF8523_HOURS_AMPM     BIT(5)
68 #define PCF8523_HOURS_12H_MASK GENMASK(4, 0)
69 #define PCF8523_HOURS_24H_MASK GENMASK(5, 0)
70 #define PCF8523_DAYS_MASK      GENMASK(5, 0)
71 #define PCF8523_WEEKDAYS_MASK  GENMASK(2, 0)
72 #define PCF8523_MONTHS_MASK    GENMASK(4, 0)
73 #define PCF8523_YEARS_MASK     GENMASK(7, 0)
74 
75 /* Alarm register bits */
76 #define PCF8523_MINUTE_ALARM_AEN_M  BIT(7)
77 #define PCF8523_MINUTE_ALARM_MASK   GENMASK(6, 0)
78 #define PCF8523_HOUR_ALARM_AEN_H    BIT(7)
79 #define PCF8523_HOUR_ALARM_AMPM	    BIT(5)
80 #define PCF8523_HOUR_ALARM_12H_MASK GENMASK(4, 0)
81 #define PCF8523_HOUR_ALARM_24H_MASK GENMASK(5, 0)
82 #define PCF8523_DAY_ALARM_AEN_D	    BIT(7)
83 #define PCF8523_DAY_ALARM_MASK	    GENMASK(5, 0)
84 #define PCF8523_WEEKDAY_ALARM_AEN_W BIT(7)
85 #define PCF8523_WEEKDAY_ALARM_MASK  GENMASK(5, 0)
86 
87 /* Timer register bits */
88 #define PCF8523_TMR_CLKOUT_CTRL_TAM	 BIT(7)
89 #define PCF8523_TMR_CLKOUT_CTRL_TBM	 BIT(6)
90 #define PCF8523_TMR_CLKOUT_CTRL_COF_MASK GENMASK(5, 3)
91 #define PCF8523_TMR_CLKOUT_CTRL_TAC_MASK GENMASK(2, 1)
92 #define PCF8523_TMR_CLKOUT_CTRL_TBC	 BIT(0)
93 #define PCF8523_TMR_A_FREQ_CTRL_TAQ_MASK GENMASK(2, 0)
94 #define PCF8523_TMR_A_REG_T_A_MASK	 GENMASK(7, 0)
95 #define PCF8523_TMR_B_FREQ_CTRL_TBW_MASK GENMASK(6, 4)
96 #define PCF8523_TMR_B_FREQ_CTRL_TBQ_MASK GENMASK(2, 0)
97 #define PCF8523_TMR_B_REG_T_B_MASK	 GENMASK(7, 0)
98 
99 /* Offset register bits */
100 #define PCF8523_OFFSET_MODE BIT(7)
101 #define PCF8523_OFFSET_MASK GENMASK(6, 0)
102 
103 /* RTC alarm time fields supported by the PCF8523 */
104 #define PCF8523_RTC_ALARM_TIME_MASK                                                                \
105 	(RTC_ALARM_TIME_MASK_MINUTE | RTC_ALARM_TIME_MASK_HOUR | RTC_ALARM_TIME_MASK_MONTHDAY |    \
106 	 RTC_ALARM_TIME_MASK_WEEKDAY)
107 
108 /* The PCF8523 only supports two-digit years, calculate offset to use */
109 #define PCF8523_YEARS_OFFSET (2000 - 1900)
110 
111 /* The PCF8523 enumerates months 1 to 12, RTC API uses 0 to 11 */
112 #define PCF8523_MONTHS_OFFSET 1
113 
114 /* Helper macro to guard int1-gpios related code */
115 #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int1_gpios) &&                                                \
116 	(defined(CONFIG_RTC_ALARM) || defined(CONFIG_RTC_UPDATE))
117 #define PCF8523_INT1_GPIOS_IN_USE 1
118 #endif
119 
120 struct pcf8523_config {
121 	const struct i2c_dt_spec i2c;
122 #ifdef PCF8523_INT1_GPIOS_IN_USE
123 	struct gpio_dt_spec int1;
124 #endif /* PCF8523_INT1_GPIOS_IN_USE */
125 	uint8_t cof;
126 	uint8_t pm;
127 	bool cap_sel;
128 	bool wakeup_source;
129 };
130 
131 struct pcf8523_data {
132 	struct k_mutex lock;
133 #if PCF8523_INT1_GPIOS_IN_USE
134 	struct gpio_callback int1_callback;
135 	struct k_thread int1_thread;
136 	struct k_sem int1_sem;
137 
138 	K_KERNEL_STACK_MEMBER(int1_stack, CONFIG_RTC_PCF8523_THREAD_STACK_SIZE);
139 #ifdef CONFIG_RTC_ALARM
140 	rtc_alarm_callback alarm_callback;
141 	void *alarm_user_data;
142 #endif /* CONFIG_RTC_ALARM */
143 #ifdef CONFIG_RTC_UPDATE
144 	rtc_update_callback update_callback;
145 	void *update_user_data;
146 #endif /* CONFIG_RTC_UPDATE */
147 #endif /* PCF8523_INT1_GPIOS_IN_USE */
148 };
149 
pcf8523_read_regs(const struct device * dev,uint8_t addr,void * buf,size_t len)150 static int pcf8523_read_regs(const struct device *dev, uint8_t addr, void *buf, size_t len)
151 {
152 	const struct pcf8523_config *config = dev->config;
153 	int err;
154 
155 	err = i2c_write_read_dt(&config->i2c, &addr, sizeof(addr), buf, len);
156 	if (err != 0) {
157 		LOG_ERR("failed to read reg addr 0x%02x, len %d (err %d)", addr, len, err);
158 		return err;
159 	}
160 
161 	return 0;
162 }
163 
pcf8523_read_reg8(const struct device * dev,uint8_t addr,uint8_t * val)164 static int pcf8523_read_reg8(const struct device *dev, uint8_t addr, uint8_t *val)
165 {
166 	return pcf8523_read_regs(dev, addr, val, sizeof(*val));
167 }
168 
pcf8523_write_regs(const struct device * dev,uint8_t addr,void * buf,size_t len)169 static int pcf8523_write_regs(const struct device *dev, uint8_t addr, void *buf, size_t len)
170 {
171 	const struct pcf8523_config *config = dev->config;
172 	uint8_t block[sizeof(addr) + len];
173 	int err;
174 
175 	block[0] = addr;
176 	memcpy(&block[1], buf, len);
177 
178 	err = i2c_write_dt(&config->i2c, block, sizeof(block));
179 	if (err != 0) {
180 		LOG_ERR("failed to write reg addr 0x%02x, len %d (err %d)", addr, len, err);
181 		return err;
182 	}
183 
184 	return 0;
185 }
186 
pcf8523_write_reg8(const struct device * dev,uint8_t addr,uint8_t val)187 static int pcf8523_write_reg8(const struct device *dev, uint8_t addr, uint8_t val)
188 {
189 	return pcf8523_write_regs(dev, addr, &val, sizeof(val));
190 }
191 
pcf8523_write_stop_bit_unlocked(const struct device * dev,bool value)192 static int pcf8523_write_stop_bit_unlocked(const struct device *dev, bool value)
193 {
194 	uint8_t control_1;
195 	int err;
196 
197 	err = pcf8523_read_reg8(dev, PCF8523_CONTROL_1, &control_1);
198 	if (err != 0) {
199 		return err;
200 	}
201 
202 	if (value) {
203 		control_1 |= PCF8523_CONTROL_1_STOP;
204 	} else {
205 		control_1 &= ~(PCF8523_CONTROL_1_STOP);
206 	}
207 
208 	err = pcf8523_write_reg8(dev, PCF8523_CONTROL_1, control_1);
209 	if (err != 0) {
210 		return err;
211 	}
212 
213 	return 0;
214 }
215 
216 #if PCF8523_INT1_GPIOS_IN_USE
pcf8523_int1_enable_unlocked(const struct device * dev,bool enable)217 static int pcf8523_int1_enable_unlocked(const struct device *dev, bool enable)
218 {
219 	const struct pcf8523_config *config = dev->config;
220 	uint8_t tmr_clkout_ctrl;
221 	int err;
222 
223 	if (!config->wakeup_source) {
224 		/* Only change COF if not configured as wakeup-source */
225 		err = pcf8523_read_reg8(dev, PCF8523_TMR_CLKOUT_CTRL, &tmr_clkout_ctrl);
226 		if (err != 0) {
227 			return err;
228 		}
229 
230 		if (enable) {
231 			/* Disable CLKOUT */
232 			tmr_clkout_ctrl |= PCF8523_TMR_CLKOUT_CTRL_COF_MASK;
233 		} else if (!config->wakeup_source) {
234 			/* Enable CLKOUT */
235 			tmr_clkout_ctrl &= ~(PCF8523_TMR_CLKOUT_CTRL_COF_MASK);
236 			tmr_clkout_ctrl |=
237 				FIELD_PREP(PCF8523_TMR_CLKOUT_CTRL_COF_MASK, config->cof);
238 		}
239 
240 		err = pcf8523_write_reg8(dev, PCF8523_TMR_CLKOUT_CTRL, tmr_clkout_ctrl);
241 		if (err != 0) {
242 			return err;
243 		}
244 	}
245 
246 	/* Use edge interrupts to avoid multiple GPIO IRQs while servicing the IRQ in the thread */
247 	err = gpio_pin_interrupt_configure_dt(&config->int1,
248 					      enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE);
249 	if (err != 0) {
250 		LOG_ERR("failed to %s GPIO IRQ (err %d)", enable ? "enable" : "disable", err);
251 		return err;
252 	}
253 
254 	return 0;
255 }
256 
pcf8523_int1_thread(void * p1,void * p2,void * p3)257 static void pcf8523_int1_thread(void *p1, void *p2, void *p3)
258 {
259 	ARG_UNUSED(p2);
260 	ARG_UNUSED(p3);
261 
262 	const struct device *dev = p1;
263 	struct pcf8523_data *data = dev->data;
264 	rtc_alarm_callback alarm_callback = NULL;
265 	void *alarm_user_data = NULL;
266 	rtc_update_callback update_callback = NULL;
267 	void *update_user_data = NULL;
268 	uint8_t control_2;
269 	int err;
270 
271 	while (true) {
272 		k_sem_take(&data->int1_sem, K_FOREVER);
273 		k_mutex_lock(&data->lock, K_FOREVER);
274 
275 		err = pcf8523_read_reg8(dev, PCF8523_CONTROL_2, &control_2);
276 		if (err != 0) {
277 			goto unlock;
278 		}
279 
280 #ifdef CONFIG_RTC_ALARM
281 		if ((control_2 & PCF8523_CONTROL_2_AF) != 0 && data->alarm_callback != NULL) {
282 			control_2 &= ~(PCF8523_CONTROL_2_AF);
283 			alarm_callback = data->alarm_callback;
284 			alarm_user_data = data->alarm_user_data;
285 		}
286 #endif /* CONFIG_RTC_ALARM */
287 
288 #ifdef CONFIG_RTC_UPDATE
289 		if ((control_2 & PCF8523_CONTROL_2_SF) != 0) {
290 			control_2 &= ~(PCF8523_CONTROL_2_SF);
291 			update_callback = data->update_callback;
292 			update_user_data = data->update_user_data;
293 		}
294 #endif /* CONFIG_RTC_UPDATE */
295 
296 		control_2 |= PCF8523_CONTROL_2_CTAF | PCF8523_CONTROL_2_CTBF;
297 
298 		err = pcf8523_write_reg8(dev, PCF8523_CONTROL_2, control_2);
299 		if (err != 0) {
300 			goto unlock;
301 		}
302 
303 		/* Check if interrupt occurred between CONTROL_2 read/write */
304 		err = pcf8523_read_reg8(dev, PCF8523_CONTROL_2, &control_2);
305 		if (err != 0) {
306 			goto unlock;
307 		}
308 
309 		if (((control_2 & PCF8523_CONTROL_2_AF) != 0U && alarm_callback != NULL) ||
310 		    ((control_2 & PCF8523_CONTROL_2_SF) != 0U)) {
311 			/*
312 			 * Another interrupt occurred while servicing this one, process current
313 			 * callback(s) and yield.
314 			 */
315 			k_sem_give(&data->int1_sem);
316 		}
317 
318 unlock:
319 		k_mutex_unlock(&data->lock);
320 
321 		if (alarm_callback != NULL) {
322 			alarm_callback(dev, 0U, alarm_user_data);
323 			alarm_callback = NULL;
324 		}
325 
326 		if (update_callback != NULL) {
327 			update_callback(dev, update_user_data);
328 			update_callback = NULL;
329 		}
330 	}
331 }
332 
pcf8523_int1_callback_handler(const struct device * port,struct gpio_callback * cb,gpio_port_pins_t pins)333 static void pcf8523_int1_callback_handler(const struct device *port, struct gpio_callback *cb,
334 					  gpio_port_pins_t pins)
335 {
336 	struct pcf8523_data *data = CONTAINER_OF(cb, struct pcf8523_data, int1_callback);
337 
338 	ARG_UNUSED(port);
339 	ARG_UNUSED(pins);
340 
341 	k_sem_give(&data->int1_sem);
342 }
343 #endif /* PCF8523_INT1_GPIOS_IN_USE */
344 
pcf8523_set_time(const struct device * dev,const struct rtc_time * timeptr)345 static int pcf8523_set_time(const struct device *dev, const struct rtc_time *timeptr)
346 {
347 	struct pcf8523_data *data = dev->data;
348 	uint8_t regs[7];
349 	int err;
350 
351 	if (timeptr->tm_year < PCF8523_YEARS_OFFSET ||
352 	    timeptr->tm_year > PCF8523_YEARS_OFFSET + 99) {
353 		return -EINVAL;
354 	}
355 
356 	k_mutex_lock(&data->lock, K_FOREVER);
357 
358 	/* Freeze the time circuits */
359 	err = pcf8523_write_stop_bit_unlocked(dev, true);
360 	if (err != 0) {
361 		goto unlock;
362 	}
363 
364 	LOG_DBG("set time: year = %d, mon = %d, mday = %d, wday = %d, hour = %d, "
365 		"min = %d, sec = %d",
366 		timeptr->tm_year, timeptr->tm_mon, timeptr->tm_mday, timeptr->tm_wday,
367 		timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec);
368 
369 	regs[0] = bin2bcd(timeptr->tm_sec) & PCF8523_SECONDS_MASK;
370 	regs[1] = bin2bcd(timeptr->tm_min) & PCF8523_MINUTES_MASK;
371 	regs[2] = bin2bcd(timeptr->tm_hour) & PCF8523_HOURS_24H_MASK;
372 	regs[3] = bin2bcd(timeptr->tm_mday) & PCF8523_DAYS_MASK;
373 	regs[4] = bin2bcd(timeptr->tm_wday) & PCF8523_WEEKDAYS_MASK;
374 	regs[5] = bin2bcd(timeptr->tm_mon + PCF8523_MONTHS_OFFSET) & PCF8523_MONTHS_MASK;
375 	regs[6] = bin2bcd(timeptr->tm_year - PCF8523_YEARS_OFFSET) & PCF8523_YEARS_MASK;
376 
377 	/* Write registers PCF8523_SECONDS through PCF8523_YEARS */
378 	err = pcf8523_write_regs(dev, PCF8523_SECONDS, &regs, sizeof(regs));
379 	if (err != 0) {
380 		goto unlock;
381 	}
382 
383 	/* Unfreeze time circuits */
384 	err = pcf8523_write_stop_bit_unlocked(dev, false);
385 	if (err != 0) {
386 		goto unlock;
387 	}
388 
389 unlock:
390 	k_mutex_unlock(&data->lock);
391 
392 	return err;
393 }
394 
pcf8523_get_time(const struct device * dev,struct rtc_time * timeptr)395 static int pcf8523_get_time(const struct device *dev, struct rtc_time *timeptr)
396 {
397 	uint8_t regs[10];
398 	int err;
399 
400 	/* Read registers PCF8523_CONTROL_1 through PCF8523_YEARS */
401 	err = pcf8523_read_regs(dev, PCF8523_CONTROL_1, &regs, sizeof(regs));
402 	if (err != 0) {
403 		return err;
404 	}
405 
406 	if ((regs[0] & PCF8523_CONTROL_1_STOP) != 0) {
407 		LOG_WRN("time circuits frozen");
408 		return -ENODATA;
409 	}
410 
411 	if ((regs[3] & PCF8523_SECONDS_OS) != 0) {
412 		LOG_WRN("oscillator stopped or interrupted");
413 		return -ENODATA;
414 	}
415 
416 	memset(timeptr, 0U, sizeof(*timeptr));
417 	timeptr->tm_sec = bcd2bin(regs[3] & PCF8523_SECONDS_MASK);
418 	timeptr->tm_min = bcd2bin(regs[4] & PCF8523_MINUTES_MASK);
419 	timeptr->tm_hour = bcd2bin(regs[5] & PCF8523_HOURS_24H_MASK);
420 	timeptr->tm_mday = bcd2bin(regs[6] & PCF8523_DAYS_MASK);
421 	timeptr->tm_wday = bcd2bin(regs[7] & PCF8523_WEEKDAYS_MASK);
422 	timeptr->tm_mon = bcd2bin(regs[8] & PCF8523_MONTHS_MASK) - PCF8523_MONTHS_OFFSET;
423 	timeptr->tm_year = bcd2bin(regs[9] & PCF8523_YEARS_MASK) + PCF8523_YEARS_OFFSET;
424 	timeptr->tm_yday = -1;
425 	timeptr->tm_isdst = -1;
426 
427 	LOG_DBG("get time: year = %d, mon = %d, mday = %d, wday = %d, hour = %d, "
428 		"min = %d, sec = %d",
429 		timeptr->tm_year, timeptr->tm_mon, timeptr->tm_mday, timeptr->tm_wday,
430 		timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec);
431 
432 	return 0;
433 }
434 
435 #ifdef CONFIG_RTC_ALARM
pcf8523_alarm_get_supported_fields(const struct device * dev,uint16_t id,uint16_t * mask)436 static int pcf8523_alarm_get_supported_fields(const struct device *dev, uint16_t id, uint16_t *mask)
437 {
438 	ARG_UNUSED(dev);
439 
440 	if (id != 0U) {
441 		LOG_ERR("invalid ID %d", id);
442 		return -EINVAL;
443 	}
444 
445 	*mask = PCF8523_RTC_ALARM_TIME_MASK;
446 
447 	return 0;
448 }
449 
pcf8523_alarm_set_time(const struct device * dev,uint16_t id,uint16_t mask,const struct rtc_time * timeptr)450 static int pcf8523_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask,
451 				  const struct rtc_time *timeptr)
452 {
453 	uint8_t regs[4];
454 
455 	if (id != 0U) {
456 		LOG_ERR("invalid ID %d", id);
457 		return -EINVAL;
458 	}
459 
460 	if ((mask & ~(PCF8523_RTC_ALARM_TIME_MASK)) != 0U) {
461 		LOG_ERR("unsupported alarm field mask 0x%04x", mask);
462 		return -EINVAL;
463 	}
464 
465 	if ((mask & RTC_ALARM_TIME_MASK_MINUTE) != 0U) {
466 		regs[0] = bin2bcd(timeptr->tm_min) & PCF8523_MINUTE_ALARM_MASK;
467 	} else {
468 		regs[0] = PCF8523_MINUTE_ALARM_AEN_M;
469 	}
470 
471 	if ((mask & RTC_ALARM_TIME_MASK_HOUR) != 0U) {
472 		regs[1] = bin2bcd(timeptr->tm_hour) & PCF8523_HOUR_ALARM_24H_MASK;
473 	} else {
474 		regs[1] = PCF8523_HOUR_ALARM_AEN_H;
475 	}
476 
477 	if ((mask & RTC_ALARM_TIME_MASK_MONTHDAY) != 0U) {
478 		regs[2] = bin2bcd(timeptr->tm_mday) & PCF8523_DAY_ALARM_MASK;
479 	} else {
480 		regs[2] = PCF8523_DAY_ALARM_AEN_D;
481 	}
482 
483 	if ((mask & RTC_ALARM_TIME_MASK_WEEKDAY) != 0U) {
484 		regs[3] = bin2bcd(timeptr->tm_wday) & PCF8523_WEEKDAY_ALARM_MASK;
485 	} else {
486 		regs[3] = PCF8523_WEEKDAY_ALARM_AEN_W;
487 	}
488 
489 	LOG_DBG("set alarm: year = %d, mon = %d, mday = %d, hour = %d, min = %d, mask = 0x%04x",
490 		timeptr->tm_year, timeptr->tm_mon, timeptr->tm_mday, timeptr->tm_hour,
491 		timeptr->tm_min, mask);
492 
493 	/* Write registers PCF8523_MINUTE_ALARM through PCF8523_WEEKDAY_ALARM */
494 	return pcf8523_write_regs(dev, PCF8523_MINUTE_ALARM, &regs, sizeof(regs));
495 }
496 
pcf8523_alarm_get_time(const struct device * dev,uint16_t id,uint16_t * mask,struct rtc_time * timeptr)497 static int pcf8523_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask,
498 				  struct rtc_time *timeptr)
499 {
500 	uint8_t regs[4];
501 	int err;
502 
503 	if (id != 0U) {
504 		LOG_ERR("invalid ID %d", id);
505 		return -EINVAL;
506 	}
507 
508 	/* Read registers PCF8523_MINUTE_ALARM through PCF8523_WEEKDAY_ALARM */
509 	err = pcf8523_read_regs(dev, PCF8523_MINUTE_ALARM, &regs, sizeof(regs));
510 	if (err != 0) {
511 		return err;
512 	}
513 
514 	memset(timeptr, 0U, sizeof(*timeptr));
515 	*mask = 0U;
516 
517 	if ((regs[0] & PCF8523_MINUTE_ALARM_AEN_M) == 0) {
518 		timeptr->tm_min = bcd2bin(regs[0] & PCF8523_MINUTE_ALARM_MASK);
519 		*mask |= RTC_ALARM_TIME_MASK_MINUTE;
520 	}
521 
522 	if ((regs[1] & PCF8523_HOUR_ALARM_AEN_H) == 0) {
523 		timeptr->tm_hour = bcd2bin(regs[1] & PCF8523_HOUR_ALARM_24H_MASK);
524 		*mask |= RTC_ALARM_TIME_MASK_HOUR;
525 	}
526 
527 	if ((regs[2] & PCF8523_DAY_ALARM_AEN_D) == 0) {
528 		timeptr->tm_mday = bcd2bin(regs[2] & PCF8523_DAY_ALARM_MASK);
529 		*mask |= RTC_ALARM_TIME_MASK_MONTHDAY;
530 	}
531 
532 	if ((regs[3] & PCF8523_WEEKDAY_ALARM_AEN_W) == 0) {
533 		timeptr->tm_wday = bcd2bin(regs[3] & PCF8523_WEEKDAY_ALARM_MASK);
534 		*mask |= RTC_ALARM_TIME_MASK_WEEKDAY;
535 	}
536 
537 	LOG_DBG("get alarm: year = %d, mon = %d, mday = %d, hour = %d, min = %d, mask = 0x%04x",
538 		timeptr->tm_year, timeptr->tm_mon, timeptr->tm_mday, timeptr->tm_hour,
539 		timeptr->tm_min, *mask);
540 
541 	return 0;
542 }
543 
pcf8523_alarm_is_pending(const struct device * dev,uint16_t id)544 static int pcf8523_alarm_is_pending(const struct device *dev, uint16_t id)
545 {
546 	struct pcf8523_data *data = dev->data;
547 	uint8_t control_2;
548 	int err;
549 
550 	if (id != 0U) {
551 		LOG_ERR("invalid ID %d", id);
552 		return -EINVAL;
553 	}
554 
555 	k_mutex_lock(&data->lock, K_FOREVER);
556 
557 	err = pcf8523_read_reg8(dev, PCF8523_CONTROL_2, &control_2);
558 	if (err != 0) {
559 		goto unlock;
560 	}
561 
562 	if ((control_2 & PCF8523_CONTROL_2_AF) != 0) {
563 		/* Clear alarm flag */
564 		control_2 &= ~(PCF8523_CONTROL_2_AF);
565 
566 		/* Ensure other flags are left unchanged (PCF8523 performs logic AND at write) */
567 		control_2 |= PCF8523_CONTROL_2_CTAF | PCF8523_CONTROL_2_CTBF | PCF8523_CONTROL_2_SF;
568 
569 		err = pcf8523_write_reg8(dev, PCF8523_CONTROL_2, control_2);
570 		if (err != 0) {
571 			goto unlock;
572 		}
573 
574 		/* Alarm pending */
575 		err = 1;
576 	}
577 
578 unlock:
579 	k_mutex_unlock(&data->lock);
580 
581 	return err;
582 }
583 
pcf8523_alarm_set_callback(const struct device * dev,uint16_t id,rtc_alarm_callback callback,void * user_data)584 static int pcf8523_alarm_set_callback(const struct device *dev, uint16_t id,
585 				      rtc_alarm_callback callback, void *user_data)
586 {
587 #ifndef PCF8523_INT1_GPIOS_IN_USE
588 	ARG_UNUSED(dev);
589 	ARG_UNUSED(id);
590 	ARG_UNUSED(callback);
591 	ARG_UNUSED(user_data);
592 
593 	return -ENOTSUP;
594 #else
595 	const struct pcf8523_config *config = dev->config;
596 	struct pcf8523_data *data = dev->data;
597 	uint8_t control_1;
598 	int err = 0;
599 
600 	if (config->int1.port == NULL) {
601 		return -ENOTSUP;
602 	}
603 
604 	if (id != 0U) {
605 		LOG_ERR("invalid ID %d", id);
606 		return -EINVAL;
607 	}
608 
609 	k_mutex_lock(&data->lock, K_FOREVER);
610 
611 	data->alarm_callback = callback;
612 	data->alarm_user_data = user_data;
613 
614 	if (!config->wakeup_source) {
615 		/* Only change AIE if not configured as wakeup-source */
616 		err = pcf8523_read_reg8(dev, PCF8523_CONTROL_1, &control_1);
617 		if (err != 0) {
618 			goto unlock;
619 		}
620 
621 		if (callback != NULL) {
622 			control_1 |= PCF8523_CONTROL_1_AIE;
623 		} else {
624 			control_1 &= ~(PCF8523_CONTROL_1_AIE);
625 		}
626 
627 		if ((control_1 & PCF8523_CONTROL_1_SIE) == 0U) {
628 			/* Only change INT1 GPIO if seconds timer interrupt not enabled */
629 			err = pcf8523_int1_enable_unlocked(dev, callback != NULL);
630 			if (err != 0) {
631 				goto unlock;
632 			}
633 		}
634 
635 		err = pcf8523_write_reg8(dev, PCF8523_CONTROL_1, control_1);
636 		if (err != 0) {
637 			goto unlock;
638 		}
639 	}
640 
641 unlock:
642 	k_mutex_unlock(&data->lock);
643 
644 	/* Wake up the INT1 thread since the alarm flag may already be set */
645 	k_sem_give(&data->int1_sem);
646 
647 	return err;
648 #endif /* PCF8523_INT1_GPIOS_IN_USE */
649 }
650 #endif /* CONFIG_RTC_ALARM */
651 
652 #if PCF8523_INT1_GPIOS_IN_USE && defined(CONFIG_RTC_UPDATE)
pcf8523_update_set_callback(const struct device * dev,rtc_update_callback callback,void * user_data)653 static int pcf8523_update_set_callback(const struct device *dev, rtc_update_callback callback,
654 				       void *user_data)
655 {
656 	const struct pcf8523_config *config = dev->config;
657 	struct pcf8523_data *data = dev->data;
658 	uint8_t control_1;
659 	int err;
660 
661 	if (config->int1.port == NULL) {
662 		return -ENOTSUP;
663 	}
664 
665 	k_mutex_lock(&data->lock, K_FOREVER);
666 
667 	data->update_callback = callback;
668 	data->update_user_data = user_data;
669 
670 	err = pcf8523_read_reg8(dev, PCF8523_CONTROL_1, &control_1);
671 	if (err != 0) {
672 		goto unlock;
673 	}
674 
675 	if (callback != NULL) {
676 		control_1 |= PCF8523_CONTROL_1_SIE;
677 	} else {
678 		control_1 &= ~(PCF8523_CONTROL_1_SIE);
679 	}
680 
681 	if ((control_1 & PCF8523_CONTROL_1_AIE) == 0U) {
682 		/* Only change INT1 GPIO if alarm interrupt not enabled */
683 		err = pcf8523_int1_enable_unlocked(dev, callback != NULL);
684 		if (err != 0) {
685 			goto unlock;
686 		}
687 	}
688 
689 	err = pcf8523_write_reg8(dev, PCF8523_CONTROL_1, control_1);
690 	if (err != 0) {
691 		goto unlock;
692 	}
693 
694 unlock:
695 	k_mutex_unlock(&data->lock);
696 
697 	/* Wake up the INT1 thread since the seconds flag may already be set */
698 	k_sem_give(&data->int1_sem);
699 
700 	return err;
701 }
702 #endif /* PCF8523_INT1_GPIOS_IN_USE && defined(CONFIG_RTC_UPDATE) */
703 
704 #ifdef CONFIG_RTC_CALIBRATION
705 
706 /* See PCF8523 data sheet table 29 */
707 #if defined(CONFIG_RTC_PCF8523_OFFSET_MODE_SLOW)
708 #define PCF8523_OFFSET_PPB_PER_LSB 4340
709 #elif defined(CONFIG_RTC_PCF8523_OFFSET_MODE_FAST)
710 #define PCF8523_OFFSET_PPB_PER_LSB 4069
711 #else
712 #error Unsupported offset mode
713 #endif
714 
715 #define PCF8523_OFFSET_PPB_MIN (-64 * PCF8523_OFFSET_PPB_PER_LSB)
716 #define PCF8523_OFFSET_PPB_MAX (63 * PCF8523_OFFSET_PPB_PER_LSB)
717 
pcf8523_set_calibration(const struct device * dev,int32_t freq_ppb)718 static int pcf8523_set_calibration(const struct device *dev, int32_t freq_ppb)
719 {
720 	int32_t period_ppb = freq_ppb * -1;
721 	int8_t offset;
722 
723 	if (period_ppb < PCF8523_OFFSET_PPB_MIN || period_ppb > PCF8523_OFFSET_PPB_MAX) {
724 		LOG_WRN("calibration value (%d ppb) out of range", freq_ppb);
725 		return -EINVAL;
726 	}
727 
728 	offset = period_ppb / PCF8523_OFFSET_PPB_PER_LSB;
729 
730 	if (IS_ENABLED(CONFIG_RTC_PCF8523_OFFSET_MODE_FAST)) {
731 		offset |= PCF8523_OFFSET_MODE;
732 	}
733 
734 	LOG_DBG("freq_ppb = %d, period_ppb = %d, offset = %d", freq_ppb, period_ppb, offset);
735 
736 	return pcf8523_write_reg8(dev, PCF8523_OFFSET, offset);
737 }
738 
pcf8523_get_calibration(const struct device * dev,int32_t * freq_ppb)739 static int pcf8523_get_calibration(const struct device *dev, int32_t *freq_ppb)
740 {
741 	int32_t period_ppb;
742 	int8_t offset;
743 	int err;
744 
745 	err = pcf8523_read_reg8(dev, PCF8523_OFFSET, &offset);
746 	if (err != 0) {
747 		return err;
748 	}
749 
750 	/* Clear mode bit and sign extend the offset */
751 	period_ppb = (offset << 1U) >> 1U;
752 
753 	period_ppb = period_ppb * PCF8523_OFFSET_PPB_PER_LSB;
754 	*freq_ppb = period_ppb * -1;
755 
756 	LOG_DBG("freq_ppb = %d, period_ppb = %d, offset = %d", *freq_ppb, period_ppb, offset);
757 
758 	return 0;
759 }
760 #endif /* CONFIG_RTC_CALIBRATION */
761 
pcf8523_init(const struct device * dev)762 static int pcf8523_init(const struct device *dev)
763 {
764 	const struct pcf8523_config *config = dev->config;
765 	struct pcf8523_data *data = dev->data;
766 	uint8_t tmr_clkout_ctrl;
767 	uint8_t regs[3];
768 	int err;
769 
770 	k_mutex_init(&data->lock);
771 
772 	if (!i2c_is_ready_dt(&config->i2c)) {
773 		LOG_ERR("I2C bus not ready");
774 		return -ENODEV;
775 	}
776 
777 #if PCF8523_INT1_GPIOS_IN_USE
778 	k_tid_t tid;
779 
780 	if (config->int1.port != NULL) {
781 		k_sem_init(&data->int1_sem, 0, INT_MAX);
782 
783 		if (!gpio_is_ready_dt(&config->int1)) {
784 			LOG_ERR("GPIO not ready");
785 			return -ENODEV;
786 		}
787 
788 		err = gpio_pin_configure_dt(&config->int1, GPIO_INPUT);
789 		if (err != 0) {
790 			LOG_ERR("failed to configure GPIO (err %d)", err);
791 			return -ENODEV;
792 		}
793 
794 		gpio_init_callback(&data->int1_callback, pcf8523_int1_callback_handler,
795 				   BIT(config->int1.pin));
796 
797 		err = gpio_add_callback_dt(&config->int1, &data->int1_callback);
798 		if (err != 0) {
799 			LOG_ERR("failed to add GPIO callback (err %d)", err);
800 			return -ENODEV;
801 		}
802 
803 		tid = k_thread_create(&data->int1_thread, data->int1_stack,
804 				      K_THREAD_STACK_SIZEOF(data->int1_stack),
805 				      pcf8523_int1_thread, (void *)dev, NULL,
806 				      NULL, CONFIG_RTC_PCF8523_THREAD_PRIO, 0, K_NO_WAIT);
807 		k_thread_name_set(tid, "pcf8523");
808 
809 		/*
810 		 * Defer GPIO interrupt configuration due to INT1/CLKOUT pin sharing. This allows
811 		 * using the CLKOUT square-wave signal for RTC calibration when no alarm/update
812 		 * callbacks are enabled (and not configured as a wakeup-source).
813 		 */
814 	}
815 #endif /* PCF8523_INT1_GPIOS_IN_USE */
816 
817 	/*
818 	 * Manually initialize the required PCF8523 registers as performing a software reset will
819 	 * reset the time circuits.
820 	 */
821 
822 	/* Read registers PCF8523_CONTROL_1 through PCF8523_CONTROL_3 */
823 	err = pcf8523_read_regs(dev, PCF8523_CONTROL_1, &regs, sizeof(regs));
824 	if (err != 0) {
825 		return -ENODEV;
826 	}
827 
828 	/* Set quartz crystal load capacitance */
829 	if (config->cap_sel) {
830 		regs[0] |= PCF8523_CONTROL_1_CAP_SEL;
831 	} else {
832 		regs[0] &= ~(PCF8523_CONTROL_1_CAP_SEL);
833 	}
834 
835 	/* Use 24h time format */
836 	regs[0] &= ~(PCF8523_CONTROL_1_12_24);
837 
838 	/* Disable second, alarm, and correction interrupts */
839 	regs[0] &= ~(PCF8523_CONTROL_1_SIE | PCF8523_CONTROL_1_AIE | PCF8523_CONTROL_1_CIE);
840 
841 	if (config->wakeup_source) {
842 		/*
843 		 * Always set AIE if wakeup-source. This allows the RTC to wake up the system even
844 		 * if the INT1 interrupt output is not directly connected to a GPIO (i.e. if
845 		 * connected to a PMIC input).
846 		 */
847 		regs[0] |= PCF8523_CONTROL_1_AIE;
848 	}
849 
850 	/* Clear interrupt flags (except alarm flag, as a wake-up alarm may be pending) */
851 	regs[1] &= ~(PCF8523_CONTROL_2_CTAF | PCF8523_CONTROL_2_CTBF | PCF8523_CONTROL_2_SF);
852 
853 	/* Disable watchdog, timer A, and timer B interrupts */
854 	regs[1] &= ~(PCF8523_CONTROL_2_WTAIE | PCF8523_CONTROL_2_CTAIE | PCF8523_CONTROL_2_CTBIE);
855 
856 	/* Configure battery switch-over function */
857 	regs[2] &= ~(PCF8523_CONTROL_3_PM_MASK);
858 	regs[2] |= FIELD_PREP(PCF8523_CONTROL_3_PM_MASK, config->pm);
859 
860 	/* Clear battery status interrupt flag */
861 	regs[2] &= ~(PCF8523_CONTROL_3_BSF);
862 
863 	/* Disable battery status interrupts */
864 	regs[2] &= ~(PCF8523_CONTROL_3_BSIE | PCF8523_CONTROL_3_BLIE);
865 
866 	/* Write registers PCF8523_CONTROL_1 through PCF8523_CONTROL_3 */
867 	err = pcf8523_write_regs(dev, PCF8523_CONTROL_1, &regs, sizeof(regs));
868 	if (err != 0) {
869 		return -ENODEV;
870 	}
871 
872 	/* Disable watchdog and countdown timers, configure IRQ level*/
873 	tmr_clkout_ctrl = 0U;
874 
875 	if (config->wakeup_source) {
876 		/* Disable CLKOUT */
877 		tmr_clkout_ctrl |= PCF8523_TMR_CLKOUT_CTRL_COF_MASK;
878 	} else {
879 		/* Configure CLKOUT frequency */
880 		tmr_clkout_ctrl |= FIELD_PREP(PCF8523_TMR_CLKOUT_CTRL_COF_MASK, config->cof);
881 	}
882 
883 	err = pcf8523_write_reg8(dev, PCF8523_TMR_CLKOUT_CTRL, tmr_clkout_ctrl);
884 	if (err != 0) {
885 		return -ENODEV;
886 	}
887 
888 	return 0;
889 }
890 
891 /* Mapping from DT battery-switch-over enum to CONTROL_3 PM field value */
892 #define PCF8523_PM_STANDARD 4U
893 #define PCF8523_PM_DIRECT   5U
894 #define PCF8523_PM_DISABLED 7U
895 
896 #ifdef CONFIG_PM_DEVICE
pcf8523_pm_action(const struct device * dev,enum pm_device_action action)897 static int pcf8523_pm_action(const struct device *dev, enum pm_device_action action)
898 {
899 	const struct pcf8523_config *config = dev->config;
900 	uint8_t control_3;
901 	int err;
902 
903 	if (config->pm == PCF8523_PM_DISABLED) {
904 		/* Only one power supply */
905 		return -ENOTSUP;
906 	}
907 
908 	switch (action) {
909 	case PM_DEVICE_ACTION_SUSPEND:
910 		/* Disable battery switch-over function */
911 		control_3 = FIELD_PREP(PCF8523_CONTROL_3_PM_MASK, PCF8523_PM_DISABLED);
912 		break;
913 	case PM_DEVICE_ACTION_RESUME:
914 		/* Re-enable battery switch-over function */
915 		control_3 = FIELD_PREP(PCF8523_CONTROL_3_PM_MASK, config->pm);
916 		break;
917 	default:
918 		return -ENOTSUP;
919 	}
920 
921 	err = pcf8523_write_reg8(dev, PCF8523_CONTROL_3, control_3);
922 	if (err != 0) {
923 		return -EIO;
924 	}
925 
926 	return 0;
927 }
928 #endif /* CONFIG_PM_DEVICE */
929 
930 static DEVICE_API(rtc, pcf8523_driver_api) = {
931 	.set_time = pcf8523_set_time,
932 	.get_time = pcf8523_get_time,
933 #ifdef CONFIG_RTC_ALARM
934 	.alarm_get_supported_fields = pcf8523_alarm_get_supported_fields,
935 	.alarm_set_time = pcf8523_alarm_set_time,
936 	.alarm_get_time = pcf8523_alarm_get_time,
937 	.alarm_is_pending = pcf8523_alarm_is_pending,
938 	.alarm_set_callback = pcf8523_alarm_set_callback,
939 #endif /* CONFIG_RTC_ALARM */
940 #if PCF8523_INT1_GPIOS_IN_USE && defined(CONFIG_RTC_UPDATE)
941 	.update_set_callback = pcf8523_update_set_callback,
942 #endif /* PCF8523_INT1_GPIOS_IN_USE && defined(CONFIG_RTC_UPDATE) */
943 #ifdef CONFIG_RTC_CALIBRATION
944 	.set_calibration = pcf8523_set_calibration,
945 	.get_calibration = pcf8523_get_calibration,
946 #endif /* CONFIG_RTC_CALIBRATION */
947 };
948 
949 #define PCF8523_PM_FROM_DT_INST(inst)                                                              \
950 	UTIL_CAT(PCF8523_PM_, DT_INST_STRING_UPPER_TOKEN(inst, battery_switch_over))
951 #define PCF8523_CAP_SEL_FROM_DT_INST(inst) (DT_INST_PROP(inst, quartz_load_femtofarads) == 12500)
952 
953 #define PCF8523_INIT(inst)                                                                         \
954 	static const struct pcf8523_config pcf8523_config_##inst = {                               \
955 		.i2c = I2C_DT_SPEC_INST_GET(inst),                                                 \
956 		.cof = DT_INST_ENUM_IDX(inst, clkout_frequency),                                   \
957 		.pm = PCF8523_PM_FROM_DT_INST(inst),                                               \
958 		.cap_sel = PCF8523_CAP_SEL_FROM_DT_INST(inst),                                     \
959 		.wakeup_source = DT_INST_PROP(inst, wakeup_source),                                \
960 		IF_ENABLED(PCF8523_INT1_GPIOS_IN_USE,                                              \
961 			   (.int1 = GPIO_DT_SPEC_INST_GET_OR(inst, int1_gpios, {0})))};            \
962                                                                                                    \
963 	static struct pcf8523_data pcf8523_data_##inst;                                            \
964                                                                                                    \
965 	PM_DEVICE_DT_INST_DEFINE(inst, pcf8523_pm_action);                                         \
966                                                                                                    \
967 	DEVICE_DT_INST_DEFINE(inst, &pcf8523_init, PM_DEVICE_DT_INST_GET(inst),                    \
968 			      &pcf8523_data_##inst, &pcf8523_config_##inst, POST_KERNEL,           \
969 			      CONFIG_RTC_INIT_PRIORITY, &pcf8523_driver_api);
970 
971 DT_INST_FOREACH_STATUS_OKAY(PCF8523_INIT)
972