Lines Matching +full:pmic +full:- +full:int +full:- +full:pin

2  * Copyright (c) 2019-2023 Henrik Brix Andersen <henrik@brixandersen.dk>
4 * SPDX-License-Identifier: Apache-2.0
108 /* The PCF8523 only supports two-digit years, calculate offset to use */
109 #define PCF8523_YEARS_OFFSET (2000 - 1900)
114 /* Helper macro to guard int1-gpios related code */
150 static int pcf8523_read_regs(const struct device *dev, uint8_t addr, void *buf, size_t len) in pcf8523_read_regs()
152 const struct pcf8523_config *config = dev->config; in pcf8523_read_regs()
153 int err; in pcf8523_read_regs()
155 err = i2c_write_read_dt(&config->i2c, &addr, sizeof(addr), buf, len); in pcf8523_read_regs()
164 static int pcf8523_read_reg8(const struct device *dev, uint8_t addr, uint8_t *val) in pcf8523_read_reg8()
169 static int pcf8523_write_regs(const struct device *dev, uint8_t addr, void *buf, size_t len) in pcf8523_write_regs()
171 const struct pcf8523_config *config = dev->config; in pcf8523_write_regs()
173 int err; in pcf8523_write_regs()
178 err = i2c_write_dt(&config->i2c, block, sizeof(block)); in pcf8523_write_regs()
187 static int pcf8523_write_reg8(const struct device *dev, uint8_t addr, uint8_t val) in pcf8523_write_reg8()
192 static int pcf8523_write_stop_bit_unlocked(const struct device *dev, bool value) in pcf8523_write_stop_bit_unlocked()
195 int err; in pcf8523_write_stop_bit_unlocked()
217 static int pcf8523_int1_enable_unlocked(const struct device *dev, bool enable) in pcf8523_int1_enable_unlocked()
219 const struct pcf8523_config *config = dev->config; in pcf8523_int1_enable_unlocked()
221 int err; in pcf8523_int1_enable_unlocked()
223 if (!config->wakeup_source) { in pcf8523_int1_enable_unlocked()
224 /* Only change COF if not configured as wakeup-source */ in pcf8523_int1_enable_unlocked()
233 } else if (!config->wakeup_source) { in pcf8523_int1_enable_unlocked()
237 FIELD_PREP(PCF8523_TMR_CLKOUT_CTRL_COF_MASK, config->cof); in pcf8523_int1_enable_unlocked()
247 err = gpio_pin_interrupt_configure_dt(&config->int1, in pcf8523_int1_enable_unlocked()
263 struct pcf8523_data *data = dev->data; in pcf8523_int1_thread()
269 int err; in pcf8523_int1_thread()
272 k_sem_take(&data->int1_sem, K_FOREVER); in pcf8523_int1_thread()
273 k_mutex_lock(&data->lock, K_FOREVER); in pcf8523_int1_thread()
281 if ((control_2 & PCF8523_CONTROL_2_AF) != 0 && data->alarm_callback != NULL) { in pcf8523_int1_thread()
283 alarm_callback = data->alarm_callback; in pcf8523_int1_thread()
284 alarm_user_data = data->alarm_user_data; in pcf8523_int1_thread()
291 update_callback = data->update_callback; in pcf8523_int1_thread()
292 update_user_data = data->update_user_data; in pcf8523_int1_thread()
315 k_sem_give(&data->int1_sem); in pcf8523_int1_thread()
319 k_mutex_unlock(&data->lock); in pcf8523_int1_thread()
341 k_sem_give(&data->int1_sem); in pcf8523_int1_callback_handler()
345 static int pcf8523_set_time(const struct device *dev, const struct rtc_time *timeptr) in pcf8523_set_time()
347 struct pcf8523_data *data = dev->data; in pcf8523_set_time()
349 int err; in pcf8523_set_time()
351 if (timeptr->tm_year < PCF8523_YEARS_OFFSET || in pcf8523_set_time()
352 timeptr->tm_year > PCF8523_YEARS_OFFSET + 99) { in pcf8523_set_time()
353 return -EINVAL; in pcf8523_set_time()
356 k_mutex_lock(&data->lock, K_FOREVER); in pcf8523_set_time()
366 timeptr->tm_year, timeptr->tm_mon, timeptr->tm_mday, timeptr->tm_wday, in pcf8523_set_time()
367 timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec); in pcf8523_set_time()
369 regs[0] = bin2bcd(timeptr->tm_sec) & PCF8523_SECONDS_MASK; in pcf8523_set_time()
370 regs[1] = bin2bcd(timeptr->tm_min) & PCF8523_MINUTES_MASK; in pcf8523_set_time()
371 regs[2] = bin2bcd(timeptr->tm_hour) & PCF8523_HOURS_24H_MASK; in pcf8523_set_time()
372 regs[3] = bin2bcd(timeptr->tm_mday) & PCF8523_DAYS_MASK; in pcf8523_set_time()
373 regs[4] = bin2bcd(timeptr->tm_wday) & PCF8523_WEEKDAYS_MASK; in pcf8523_set_time()
374 regs[5] = bin2bcd(timeptr->tm_mon + PCF8523_MONTHS_OFFSET) & PCF8523_MONTHS_MASK; in pcf8523_set_time()
375 regs[6] = bin2bcd(timeptr->tm_year - PCF8523_YEARS_OFFSET) & PCF8523_YEARS_MASK; in pcf8523_set_time()
390 k_mutex_unlock(&data->lock); in pcf8523_set_time()
395 static int pcf8523_get_time(const struct device *dev, struct rtc_time *timeptr) in pcf8523_get_time()
398 int err; in pcf8523_get_time()
408 return -ENODATA; in pcf8523_get_time()
413 return -ENODATA; in pcf8523_get_time()
417 timeptr->tm_sec = bcd2bin(regs[3] & PCF8523_SECONDS_MASK); in pcf8523_get_time()
418 timeptr->tm_min = bcd2bin(regs[4] & PCF8523_MINUTES_MASK); in pcf8523_get_time()
419 timeptr->tm_hour = bcd2bin(regs[5] & PCF8523_HOURS_24H_MASK); in pcf8523_get_time()
420 timeptr->tm_mday = bcd2bin(regs[6] & PCF8523_DAYS_MASK); in pcf8523_get_time()
421 timeptr->tm_wday = bcd2bin(regs[7] & PCF8523_WEEKDAYS_MASK); in pcf8523_get_time()
422 timeptr->tm_mon = bcd2bin(regs[8] & PCF8523_MONTHS_MASK) - PCF8523_MONTHS_OFFSET; in pcf8523_get_time()
423 timeptr->tm_year = bcd2bin(regs[9] & PCF8523_YEARS_MASK) + PCF8523_YEARS_OFFSET; in pcf8523_get_time()
424 timeptr->tm_yday = -1; in pcf8523_get_time()
425 timeptr->tm_isdst = -1; in pcf8523_get_time()
429 timeptr->tm_year, timeptr->tm_mon, timeptr->tm_mday, timeptr->tm_wday, in pcf8523_get_time()
430 timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec); in pcf8523_get_time()
436 static int pcf8523_alarm_get_supported_fields(const struct device *dev, uint16_t id, uint16_t *mask) in pcf8523_alarm_get_supported_fields()
442 return -EINVAL; in pcf8523_alarm_get_supported_fields()
450 static int pcf8523_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask, in pcf8523_alarm_set_time()
457 return -EINVAL; in pcf8523_alarm_set_time()
462 return -EINVAL; in pcf8523_alarm_set_time()
466 regs[0] = bin2bcd(timeptr->tm_min) & PCF8523_MINUTE_ALARM_MASK; in pcf8523_alarm_set_time()
472 regs[1] = bin2bcd(timeptr->tm_hour) & PCF8523_HOUR_ALARM_24H_MASK; in pcf8523_alarm_set_time()
478 regs[2] = bin2bcd(timeptr->tm_mday) & PCF8523_DAY_ALARM_MASK; in pcf8523_alarm_set_time()
484 regs[3] = bin2bcd(timeptr->tm_wday) & PCF8523_WEEKDAY_ALARM_MASK; in pcf8523_alarm_set_time()
490 timeptr->tm_year, timeptr->tm_mon, timeptr->tm_mday, timeptr->tm_hour, in pcf8523_alarm_set_time()
491 timeptr->tm_min, mask); in pcf8523_alarm_set_time()
497 static int pcf8523_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask, in pcf8523_alarm_get_time()
501 int err; in pcf8523_alarm_get_time()
505 return -EINVAL; in pcf8523_alarm_get_time()
518 timeptr->tm_min = bcd2bin(regs[0] & PCF8523_MINUTE_ALARM_MASK); in pcf8523_alarm_get_time()
523 timeptr->tm_hour = bcd2bin(regs[1] & PCF8523_HOUR_ALARM_24H_MASK); in pcf8523_alarm_get_time()
528 timeptr->tm_mday = bcd2bin(regs[2] & PCF8523_DAY_ALARM_MASK); in pcf8523_alarm_get_time()
533 timeptr->tm_wday = bcd2bin(regs[3] & PCF8523_WEEKDAY_ALARM_MASK); in pcf8523_alarm_get_time()
538 timeptr->tm_year, timeptr->tm_mon, timeptr->tm_mday, timeptr->tm_hour, in pcf8523_alarm_get_time()
539 timeptr->tm_min, *mask); in pcf8523_alarm_get_time()
544 static int pcf8523_alarm_is_pending(const struct device *dev, uint16_t id) in pcf8523_alarm_is_pending()
546 struct pcf8523_data *data = dev->data; in pcf8523_alarm_is_pending()
548 int err; in pcf8523_alarm_is_pending()
552 return -EINVAL; in pcf8523_alarm_is_pending()
555 k_mutex_lock(&data->lock, K_FOREVER); in pcf8523_alarm_is_pending()
579 k_mutex_unlock(&data->lock); in pcf8523_alarm_is_pending()
584 static int pcf8523_alarm_set_callback(const struct device *dev, uint16_t id, in pcf8523_alarm_set_callback()
593 return -ENOTSUP; in pcf8523_alarm_set_callback()
595 const struct pcf8523_config *config = dev->config; in pcf8523_alarm_set_callback()
596 struct pcf8523_data *data = dev->data; in pcf8523_alarm_set_callback()
598 int err = 0; in pcf8523_alarm_set_callback()
600 if (config->int1.port == NULL) { in pcf8523_alarm_set_callback()
601 return -ENOTSUP; in pcf8523_alarm_set_callback()
606 return -EINVAL; in pcf8523_alarm_set_callback()
609 k_mutex_lock(&data->lock, K_FOREVER); in pcf8523_alarm_set_callback()
611 data->alarm_callback = callback; in pcf8523_alarm_set_callback()
612 data->alarm_user_data = user_data; in pcf8523_alarm_set_callback()
614 if (!config->wakeup_source) { in pcf8523_alarm_set_callback()
615 /* Only change AIE if not configured as wakeup-source */ in pcf8523_alarm_set_callback()
642 k_mutex_unlock(&data->lock); in pcf8523_alarm_set_callback()
645 k_sem_give(&data->int1_sem); in pcf8523_alarm_set_callback()
653 static int pcf8523_update_set_callback(const struct device *dev, rtc_update_callback callback, in pcf8523_update_set_callback()
656 const struct pcf8523_config *config = dev->config; in pcf8523_update_set_callback()
657 struct pcf8523_data *data = dev->data; in pcf8523_update_set_callback()
659 int err; in pcf8523_update_set_callback()
661 if (config->int1.port == NULL) { in pcf8523_update_set_callback()
662 return -ENOTSUP; in pcf8523_update_set_callback()
665 k_mutex_lock(&data->lock, K_FOREVER); in pcf8523_update_set_callback()
667 data->update_callback = callback; in pcf8523_update_set_callback()
668 data->update_user_data = user_data; in pcf8523_update_set_callback()
695 k_mutex_unlock(&data->lock); in pcf8523_update_set_callback()
698 k_sem_give(&data->int1_sem); in pcf8523_update_set_callback()
715 #define PCF8523_OFFSET_PPB_MIN (-64 * PCF8523_OFFSET_PPB_PER_LSB)
718 static int pcf8523_set_calibration(const struct device *dev, int32_t freq_ppb) in pcf8523_set_calibration()
720 int32_t period_ppb = freq_ppb * -1; in pcf8523_set_calibration()
725 return -EINVAL; in pcf8523_set_calibration()
739 static int pcf8523_get_calibration(const struct device *dev, int32_t *freq_ppb) in pcf8523_get_calibration()
743 int err; in pcf8523_get_calibration()
754 *freq_ppb = period_ppb * -1; in pcf8523_get_calibration()
762 static int pcf8523_init(const struct device *dev) in pcf8523_init()
764 const struct pcf8523_config *config = dev->config; in pcf8523_init()
765 struct pcf8523_data *data = dev->data; in pcf8523_init()
768 int err; in pcf8523_init()
770 k_mutex_init(&data->lock); in pcf8523_init()
772 if (!i2c_is_ready_dt(&config->i2c)) { in pcf8523_init()
774 return -ENODEV; in pcf8523_init()
780 if (config->int1.port != NULL) { in pcf8523_init()
781 k_sem_init(&data->int1_sem, 0, INT_MAX); in pcf8523_init()
783 if (!gpio_is_ready_dt(&config->int1)) { in pcf8523_init()
785 return -ENODEV; in pcf8523_init()
788 err = gpio_pin_configure_dt(&config->int1, GPIO_INPUT); in pcf8523_init()
791 return -ENODEV; in pcf8523_init()
794 gpio_init_callback(&data->int1_callback, pcf8523_int1_callback_handler, in pcf8523_init()
795 BIT(config->int1.pin)); in pcf8523_init()
797 err = gpio_add_callback_dt(&config->int1, &data->int1_callback); in pcf8523_init()
800 return -ENODEV; in pcf8523_init()
803 tid = k_thread_create(&data->int1_thread, data->int1_stack, in pcf8523_init()
804 K_THREAD_STACK_SIZEOF(data->int1_stack), in pcf8523_init()
810 * Defer GPIO interrupt configuration due to INT1/CLKOUT pin sharing. This allows in pcf8523_init()
811 * using the CLKOUT square-wave signal for RTC calibration when no alarm/update in pcf8523_init()
812 * callbacks are enabled (and not configured as a wakeup-source). in pcf8523_init()
825 return -ENODEV; in pcf8523_init()
829 if (config->cap_sel) { in pcf8523_init()
841 if (config->wakeup_source) { in pcf8523_init()
843 * Always set AIE if wakeup-source. This allows the RTC to wake up the system even in pcf8523_init()
845 * connected to a PMIC input). in pcf8523_init()
850 /* Clear interrupt flags (except alarm flag, as a wake-up alarm may be pending) */ in pcf8523_init()
856 /* Configure battery switch-over function */ in pcf8523_init()
858 regs[2] |= FIELD_PREP(PCF8523_CONTROL_3_PM_MASK, config->pm); in pcf8523_init()
869 return -ENODEV; in pcf8523_init()
875 if (config->wakeup_source) { in pcf8523_init()
880 tmr_clkout_ctrl |= FIELD_PREP(PCF8523_TMR_CLKOUT_CTRL_COF_MASK, config->cof); in pcf8523_init()
885 return -ENODEV; in pcf8523_init()
891 /* Mapping from DT battery-switch-over enum to CONTROL_3 PM field value */
897 static int pcf8523_pm_action(const struct device *dev, enum pm_device_action action) in pcf8523_pm_action()
899 const struct pcf8523_config *config = dev->config; in pcf8523_pm_action()
901 int err; in pcf8523_pm_action()
903 if (config->pm == PCF8523_PM_DISABLED) { in pcf8523_pm_action()
905 return -ENOTSUP; in pcf8523_pm_action()
910 /* Disable battery switch-over function */ in pcf8523_pm_action()
914 /* Re-enable battery switch-over function */ in pcf8523_pm_action()
915 control_3 = FIELD_PREP(PCF8523_CONTROL_3_PM_MASK, config->pm); in pcf8523_pm_action()
918 return -ENOTSUP; in pcf8523_pm_action()
923 return -EIO; in pcf8523_pm_action()