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, ®s, 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, ®s, 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, ®s, 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, ®s, 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 584 #if PCF8523_INT1_GPIOS_IN_USE pcf8523_alarm_set_callback(const struct device * dev,uint16_t id,rtc_alarm_callback callback,void * user_data)585 static int pcf8523_alarm_set_callback(const struct device *dev, uint16_t id, 586 rtc_alarm_callback callback, void *user_data) 587 { 588 const struct pcf8523_config *config = dev->config; 589 struct pcf8523_data *data = dev->data; 590 uint8_t control_1; 591 int err = 0; 592 593 if (config->int1.port == NULL) { 594 return -ENOTSUP; 595 } 596 597 if (id != 0U) { 598 LOG_ERR("invalid ID %d", id); 599 return -EINVAL; 600 } 601 602 k_mutex_lock(&data->lock, K_FOREVER); 603 604 data->alarm_callback = callback; 605 data->alarm_user_data = user_data; 606 607 if (!config->wakeup_source) { 608 /* Only change AIE if not configured as wakeup-source */ 609 err = pcf8523_read_reg8(dev, PCF8523_CONTROL_1, &control_1); 610 if (err != 0) { 611 goto unlock; 612 } 613 614 if (callback != NULL) { 615 control_1 |= PCF8523_CONTROL_1_AIE; 616 } else { 617 control_1 &= ~(PCF8523_CONTROL_1_AIE); 618 } 619 620 if ((control_1 & PCF8523_CONTROL_1_SIE) == 0U) { 621 /* Only change INT1 GPIO if seconds timer interrupt not enabled */ 622 err = pcf8523_int1_enable_unlocked(dev, callback != NULL); 623 if (err != 0) { 624 goto unlock; 625 } 626 } 627 628 err = pcf8523_write_reg8(dev, PCF8523_CONTROL_1, control_1); 629 if (err != 0) { 630 goto unlock; 631 } 632 } 633 634 unlock: 635 k_mutex_unlock(&data->lock); 636 637 /* Wake up the INT1 thread since the alarm flag may already be set */ 638 k_sem_give(&data->int1_sem); 639 640 return err; 641 } 642 #endif /* PCF8523_INT1_GPIOS_IN_USE */ 643 #endif /* CONFIG_RTC_ALARM */ 644 645 #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)646 static int pcf8523_update_set_callback(const struct device *dev, rtc_update_callback callback, 647 void *user_data) 648 { 649 const struct pcf8523_config *config = dev->config; 650 struct pcf8523_data *data = dev->data; 651 uint8_t control_1; 652 int err; 653 654 if (config->int1.port == NULL) { 655 return -ENOTSUP; 656 } 657 658 k_mutex_lock(&data->lock, K_FOREVER); 659 660 data->update_callback = callback; 661 data->update_user_data = user_data; 662 663 err = pcf8523_read_reg8(dev, PCF8523_CONTROL_1, &control_1); 664 if (err != 0) { 665 goto unlock; 666 } 667 668 if (callback != NULL) { 669 control_1 |= PCF8523_CONTROL_1_SIE; 670 } else { 671 control_1 &= ~(PCF8523_CONTROL_1_SIE); 672 } 673 674 if ((control_1 & PCF8523_CONTROL_1_AIE) == 0U) { 675 /* Only change INT1 GPIO if alarm interrupt not enabled */ 676 err = pcf8523_int1_enable_unlocked(dev, callback != NULL); 677 if (err != 0) { 678 goto unlock; 679 } 680 } 681 682 err = pcf8523_write_reg8(dev, PCF8523_CONTROL_1, control_1); 683 if (err != 0) { 684 goto unlock; 685 } 686 687 unlock: 688 k_mutex_unlock(&data->lock); 689 690 /* Wake up the INT1 thread since the seconds flag may already be set */ 691 k_sem_give(&data->int1_sem); 692 693 return err; 694 } 695 #endif /* PCF8523_INT1_GPIOS_IN_USE && defined(CONFIG_RTC_UPDATE) */ 696 697 #ifdef CONFIG_RTC_CALIBRATION 698 699 /* See PCF8523 data sheet table 29 */ 700 #if defined(CONFIG_RTC_PCF8523_OFFSET_MODE_SLOW) 701 #define PCF8523_OFFSET_PPB_PER_LSB 4340 702 #elif defined(CONFIG_RTC_PCF8523_OFFSET_MODE_FAST) 703 #define PCF8523_OFFSET_PPB_PER_LSB 4069 704 #else 705 #error Unsupported offset mode 706 #endif 707 708 #define PCF8523_OFFSET_PPB_MIN (-64 * PCF8523_OFFSET_PPB_PER_LSB) 709 #define PCF8523_OFFSET_PPB_MAX (63 * PCF8523_OFFSET_PPB_PER_LSB) 710 pcf8523_set_calibration(const struct device * dev,int32_t freq_ppb)711 static int pcf8523_set_calibration(const struct device *dev, int32_t freq_ppb) 712 { 713 int32_t period_ppb = freq_ppb * -1; 714 int8_t offset; 715 716 if (period_ppb < PCF8523_OFFSET_PPB_MIN || period_ppb > PCF8523_OFFSET_PPB_MAX) { 717 LOG_WRN("calibration value (%d ppb) out of range", freq_ppb); 718 return -EINVAL; 719 } 720 721 offset = period_ppb / PCF8523_OFFSET_PPB_PER_LSB; 722 723 if (IS_ENABLED(CONFIG_RTC_PCF8523_OFFSET_MODE_FAST)) { 724 offset |= PCF8523_OFFSET_MODE; 725 } 726 727 LOG_DBG("freq_ppb = %d, period_ppb = %d, offset = %d", freq_ppb, period_ppb, offset); 728 729 return pcf8523_write_reg8(dev, PCF8523_OFFSET, offset); 730 } 731 pcf8523_get_calibration(const struct device * dev,int32_t * freq_ppb)732 static int pcf8523_get_calibration(const struct device *dev, int32_t *freq_ppb) 733 { 734 int32_t period_ppb; 735 int8_t offset; 736 int err; 737 738 err = pcf8523_read_reg8(dev, PCF8523_OFFSET, &offset); 739 if (err != 0) { 740 return err; 741 } 742 743 /* Clear mode bit and sign extend the offset */ 744 period_ppb = (offset << 1U) >> 1U; 745 746 period_ppb = period_ppb * PCF8523_OFFSET_PPB_PER_LSB; 747 *freq_ppb = period_ppb * -1; 748 749 LOG_DBG("freq_ppb = %d, period_ppb = %d, offset = %d", *freq_ppb, period_ppb, offset); 750 751 return 0; 752 } 753 #endif /* CONFIG_RTC_CALIBRATION */ 754 pcf8523_init(const struct device * dev)755 static int pcf8523_init(const struct device *dev) 756 { 757 const struct pcf8523_config *config = dev->config; 758 struct pcf8523_data *data = dev->data; 759 uint8_t tmr_clkout_ctrl; 760 uint8_t regs[3]; 761 int err; 762 763 k_mutex_init(&data->lock); 764 765 if (!i2c_is_ready_dt(&config->i2c)) { 766 LOG_ERR("I2C bus not ready"); 767 return -ENODEV; 768 } 769 770 #if PCF8523_INT1_GPIOS_IN_USE 771 k_tid_t tid; 772 773 if (config->int1.port != NULL) { 774 k_sem_init(&data->int1_sem, 0, INT_MAX); 775 776 if (!gpio_is_ready_dt(&config->int1)) { 777 LOG_ERR("GPIO not ready"); 778 return -ENODEV; 779 } 780 781 err = gpio_pin_configure_dt(&config->int1, GPIO_INPUT); 782 if (err != 0) { 783 LOG_ERR("failed to configure GPIO (err %d)", err); 784 return -ENODEV; 785 } 786 787 gpio_init_callback(&data->int1_callback, pcf8523_int1_callback_handler, 788 BIT(config->int1.pin)); 789 790 err = gpio_add_callback_dt(&config->int1, &data->int1_callback); 791 if (err != 0) { 792 LOG_ERR("failed to add GPIO callback (err %d)", err); 793 return -ENODEV; 794 } 795 796 tid = k_thread_create(&data->int1_thread, data->int1_stack, 797 K_THREAD_STACK_SIZEOF(data->int1_stack), 798 pcf8523_int1_thread, (void *)dev, NULL, 799 NULL, CONFIG_RTC_PCF8523_THREAD_PRIO, 0, K_NO_WAIT); 800 k_thread_name_set(tid, "pcf8523"); 801 802 /* 803 * Defer GPIO interrupt configuration due to INT1/CLKOUT pin sharing. This allows 804 * using the CLKOUT square-wave signal for RTC calibration when no alarm/update 805 * callbacks are enabled (and not configured as a wakeup-source). 806 */ 807 } 808 #endif /* PCF8523_INT1_GPIOS_IN_USE */ 809 810 /* 811 * Manually initialize the required PCF8523 registers as performing a software reset will 812 * reset the time circuits. 813 */ 814 815 /* Read registers PCF8523_CONTROL_1 through PCF8523_CONTROL_3 */ 816 err = pcf8523_read_regs(dev, PCF8523_CONTROL_1, ®s, sizeof(regs)); 817 if (err != 0) { 818 return -ENODEV; 819 } 820 821 /* Set quartz crystal load capacitance */ 822 if (config->cap_sel) { 823 regs[0] |= PCF8523_CONTROL_1_CAP_SEL; 824 } else { 825 regs[0] &= ~(PCF8523_CONTROL_1_CAP_SEL); 826 } 827 828 /* Use 24h time format */ 829 regs[0] &= ~(PCF8523_CONTROL_1_12_24); 830 831 /* Disable second, alarm, and correction interrupts */ 832 regs[0] &= ~(PCF8523_CONTROL_1_SIE | PCF8523_CONTROL_1_AIE | PCF8523_CONTROL_1_CIE); 833 834 if (config->wakeup_source) { 835 /* 836 * Always set AIE if wakeup-source. This allows the RTC to wake up the system even 837 * if the INT1 interrupt output is not directly connected to a GPIO (i.e. if 838 * connected to a PMIC input). 839 */ 840 regs[0] |= PCF8523_CONTROL_1_AIE; 841 } 842 843 /* Clear interrupt flags (except alarm flag, as a wake-up alarm may be pending) */ 844 regs[1] &= ~(PCF8523_CONTROL_2_CTAF | PCF8523_CONTROL_2_CTBF | PCF8523_CONTROL_2_SF); 845 846 /* Disable watchdog, timer A, and timer B interrupts */ 847 regs[1] &= ~(PCF8523_CONTROL_2_WTAIE | PCF8523_CONTROL_2_CTAIE | PCF8523_CONTROL_2_CTBIE); 848 849 /* Configure battery switch-over function */ 850 regs[2] &= ~(PCF8523_CONTROL_3_PM_MASK); 851 regs[2] |= FIELD_PREP(PCF8523_CONTROL_3_PM_MASK, config->pm); 852 853 /* Clear battery status interrupt flag */ 854 regs[2] &= ~(PCF8523_CONTROL_3_BSF); 855 856 /* Disable battery status interrupts */ 857 regs[2] &= ~(PCF8523_CONTROL_3_BSIE | PCF8523_CONTROL_3_BLIE); 858 859 /* Write registers PCF8523_CONTROL_1 through PCF8523_CONTROL_3 */ 860 err = pcf8523_write_regs(dev, PCF8523_CONTROL_1, ®s, sizeof(regs)); 861 if (err != 0) { 862 return -ENODEV; 863 } 864 865 /* Disable watchdog and countdown timers, configure IRQ level*/ 866 tmr_clkout_ctrl = 0U; 867 868 if (config->wakeup_source) { 869 /* Disable CLKOUT */ 870 tmr_clkout_ctrl |= PCF8523_TMR_CLKOUT_CTRL_COF_MASK; 871 } else { 872 /* Configure CLKOUT frequency */ 873 tmr_clkout_ctrl |= FIELD_PREP(PCF8523_TMR_CLKOUT_CTRL_COF_MASK, config->cof); 874 } 875 876 err = pcf8523_write_reg8(dev, PCF8523_TMR_CLKOUT_CTRL, tmr_clkout_ctrl); 877 if (err != 0) { 878 return -ENODEV; 879 } 880 881 return 0; 882 } 883 884 /* Mapping from DT battery-switch-over enum to CONTROL_3 PM field value */ 885 #define PCF8523_PM_STANDARD 4U 886 #define PCF8523_PM_DIRECT 5U 887 #define PCF8523_PM_DISABLED 7U 888 889 #ifdef CONFIG_PM_DEVICE pcf8523_pm_action(const struct device * dev,enum pm_device_action action)890 static int pcf8523_pm_action(const struct device *dev, enum pm_device_action action) 891 { 892 const struct pcf8523_config *config = dev->config; 893 uint8_t control_3; 894 int err; 895 896 if (config->pm == PCF8523_PM_DISABLED) { 897 /* Only one power supply */ 898 return -ENOTSUP; 899 } 900 901 switch (action) { 902 case PM_DEVICE_ACTION_SUSPEND: 903 /* Disable battery switch-over function */ 904 control_3 = FIELD_PREP(PCF8523_CONTROL_3_PM_MASK, PCF8523_PM_DISABLED); 905 break; 906 case PM_DEVICE_ACTION_RESUME: 907 /* Re-enable battery switch-over function */ 908 control_3 = FIELD_PREP(PCF8523_CONTROL_3_PM_MASK, config->pm); 909 break; 910 default: 911 return -ENOTSUP; 912 } 913 914 err = pcf8523_write_reg8(dev, PCF8523_CONTROL_3, control_3); 915 if (err != 0) { 916 return -EIO; 917 } 918 919 return 0; 920 } 921 #endif /* CONFIG_PM_DEVICE */ 922 923 static const struct rtc_driver_api pcf8523_driver_api = { 924 .set_time = pcf8523_set_time, 925 .get_time = pcf8523_get_time, 926 #ifdef CONFIG_RTC_ALARM 927 .alarm_get_supported_fields = pcf8523_alarm_get_supported_fields, 928 .alarm_set_time = pcf8523_alarm_set_time, 929 .alarm_get_time = pcf8523_alarm_get_time, 930 .alarm_is_pending = pcf8523_alarm_is_pending, 931 #if PCF8523_INT1_GPIOS_IN_USE 932 .alarm_set_callback = pcf8523_alarm_set_callback, 933 #endif /* PCF8523_INT1_GPIOS_IN_USE */ 934 #endif /* CONFIG_RTC_ALARM */ 935 #if PCF8523_INT1_GPIOS_IN_USE && defined(CONFIG_RTC_UPDATE) 936 .update_set_callback = pcf8523_update_set_callback, 937 #endif /* PCF8523_INT1_GPIOS_IN_USE && defined(CONFIG_RTC_UPDATE) */ 938 #ifdef CONFIG_RTC_CALIBRATION 939 .set_calibration = pcf8523_set_calibration, 940 .get_calibration = pcf8523_get_calibration, 941 #endif /* CONFIG_RTC_CALIBRATION */ 942 }; 943 944 #define PCF8523_PM_FROM_DT_INST(inst) \ 945 UTIL_CAT(PCF8523_PM_, DT_INST_STRING_UPPER_TOKEN(inst, battery_switch_over)) 946 #define PCF8523_CAP_SEL_FROM_DT_INST(inst) (DT_INST_PROP(inst, quartz_load_femtofarads) == 12500) 947 948 #define PCF8523_INIT(inst) \ 949 static const struct pcf8523_config pcf8523_config_##inst = { \ 950 .i2c = I2C_DT_SPEC_INST_GET(inst), \ 951 .cof = DT_INST_ENUM_IDX(inst, clkout_frequency), \ 952 .pm = PCF8523_PM_FROM_DT_INST(inst), \ 953 .cap_sel = PCF8523_CAP_SEL_FROM_DT_INST(inst), \ 954 .wakeup_source = DT_INST_PROP(inst, wakeup_source), \ 955 IF_ENABLED(PCF8523_INT1_GPIOS_IN_USE, \ 956 (.int1 = GPIO_DT_SPEC_INST_GET_OR(inst, int1_gpios, {0})))}; \ 957 \ 958 static struct pcf8523_data pcf8523_data_##inst; \ 959 \ 960 PM_DEVICE_DT_INST_DEFINE(inst, pcf8523_pm_action); \ 961 \ 962 DEVICE_DT_INST_DEFINE(inst, &pcf8523_init, PM_DEVICE_DT_INST_GET(inst), \ 963 &pcf8523_data_##inst, &pcf8523_config_##inst, POST_KERNEL, \ 964 CONFIG_RTC_INIT_PRIORITY, &pcf8523_driver_api); 965 966 DT_INST_FOREACH_STATUS_OKAY(PCF8523_INIT) 967