Lines Matching +full:battery +full:- +full:backed

1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright 2013 Til-Technologies
6 * Author: Renaud Cerrato <r.cerrato@til-technologies.fr>
16 * Datasheets: https://www.nxp.com/docs/en/data-sheet/PCF2127.pdf
17 * https://www.nxp.com/docs/en/data-sheet/PCF2131DS.pdf
75 * PCF2127 has 512 bytes general-purpose static RAM (SRAM) that is
76 * battery backed and can survive a power outage.
216 * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
228 ret = regmap_bulk_read(pcf2127->regmap, pcf2127->cfg->reg_time_base, in pcf2127_rtc_read_time()
243 return -EINVAL; in pcf2127_rtc_read_time()
251 tm->tm_sec = bcd2bin(buf[0] & 0x7F); in pcf2127_rtc_read_time()
252 tm->tm_min = bcd2bin(buf[1] & 0x7F); in pcf2127_rtc_read_time()
253 tm->tm_hour = bcd2bin(buf[2] & 0x3F); in pcf2127_rtc_read_time()
254 tm->tm_mday = bcd2bin(buf[3] & 0x3F); in pcf2127_rtc_read_time()
255 tm->tm_wday = buf[4] & 0x07; in pcf2127_rtc_read_time()
256 tm->tm_mon = bcd2bin(buf[5] & 0x1F) - 1; in pcf2127_rtc_read_time()
257 tm->tm_year = bcd2bin(buf[6]); in pcf2127_rtc_read_time()
258 tm->tm_year += 100; in pcf2127_rtc_read_time()
263 tm->tm_sec, tm->tm_min, tm->tm_hour, in pcf2127_rtc_read_time()
264 tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); in pcf2127_rtc_read_time()
278 tm->tm_sec, tm->tm_min, tm->tm_hour, in pcf2127_rtc_set_time()
279 tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); in pcf2127_rtc_set_time()
282 buf[i++] = bin2bcd(tm->tm_sec); /* this will also clear OSF flag */ in pcf2127_rtc_set_time()
283 buf[i++] = bin2bcd(tm->tm_min); in pcf2127_rtc_set_time()
284 buf[i++] = bin2bcd(tm->tm_hour); in pcf2127_rtc_set_time()
285 buf[i++] = bin2bcd(tm->tm_mday); in pcf2127_rtc_set_time()
286 buf[i++] = tm->tm_wday & 0x07; in pcf2127_rtc_set_time()
288 /* month, 1 - 12 */ in pcf2127_rtc_set_time()
289 buf[i++] = bin2bcd(tm->tm_mon + 1); in pcf2127_rtc_set_time()
292 buf[i++] = bin2bcd(tm->tm_year - 100); in pcf2127_rtc_set_time()
299 if (pcf2127->cfg->type == PCF2131) { in pcf2127_rtc_set_time()
300 err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, in pcf2127_rtc_set_time()
308 err = regmap_write(pcf2127->regmap, PCF2131_REG_SR_RESET, in pcf2127_rtc_set_time()
317 err = regmap_bulk_write(pcf2127->regmap, pcf2127->cfg->reg_time_base, buf, i); in pcf2127_rtc_set_time()
323 if (pcf2127->cfg->type == PCF2131) { in pcf2127_rtc_set_time()
325 err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, in pcf2127_rtc_set_time()
342 switch (param->param) { in pcf2127_param_get()
344 ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &value); in pcf2127_param_get()
351 param->uvalue = RTC_BSM_LEVEL; in pcf2127_param_get()
353 param->uvalue = RTC_BSM_DIRECT; in pcf2127_param_get()
355 param->uvalue = RTC_BSM_DISABLED; in pcf2127_param_get()
360 return -EINVAL; in pcf2127_param_get()
373 switch (param->param) { in pcf2127_param_set()
375 ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &value); in pcf2127_param_set()
382 value -= 5; in pcf2127_param_set()
384 value -= 3; in pcf2127_param_set()
386 switch (param->uvalue) { in pcf2127_param_set()
398 return -EINVAL; in pcf2127_param_set()
401 return regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3, in pcf2127_param_set()
408 return -EINVAL; in pcf2127_param_set()
423 ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &val); in pcf2127_rtc_ioctl()
436 return regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3, in pcf2127_rtc_ioctl()
440 return -ENOIOCTLCMD; in pcf2127_rtc_ioctl()
451 ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_ADDR_MSB, in pcf2127_nvmem_read()
456 return regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_RD_CMD, in pcf2127_nvmem_read()
467 ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_ADDR_MSB, in pcf2127_nvmem_write()
472 return regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_WRT_CMD, in pcf2127_nvmem_write()
487 wd_val = ((wdd->timeout * pcf2127->cfg->wdd_clock_hz_x1000) / 1000) + 1; in pcf2127_wdt_ping()
489 return regmap_write(pcf2127->regmap, pcf2127->cfg->reg_wd_val, wd_val); in pcf2127_wdt_ping()
506 dev_err(wdd->parent, in pcf2127_wdt_active_ping()
523 return regmap_write(pcf2127->regmap, pcf2127->cfg->reg_wd_val, in pcf2127_wdt_stop()
530 dev_dbg(wdd->parent, "new watchdog timeout: %is (old: %is)\n", in pcf2127_wdt_set_timeout()
531 new_timeout, wdd->timeout); in pcf2127_wdt_set_timeout()
533 wdd->timeout = new_timeout; in pcf2127_wdt_set_timeout()
558 * t = (n - 1) / f
565 return (1000 * (n - 1)) / f1000; in pcf2127_watchdog_get_period()
573 !device_property_read_bool(dev, "reset-source")) in pcf2127_watchdog_init()
576 pcf2127->wdd.parent = dev; in pcf2127_watchdog_init()
577 pcf2127->wdd.info = &pcf2127_wdt_info; in pcf2127_watchdog_init()
578 pcf2127->wdd.ops = &pcf2127_watchdog_ops; in pcf2127_watchdog_init()
580 pcf2127->wdd.min_timeout = in pcf2127_watchdog_init()
582 2, pcf2127->cfg->wdd_clock_hz_x1000); in pcf2127_watchdog_init()
583 pcf2127->wdd.max_timeout = in pcf2127_watchdog_init()
585 255, pcf2127->cfg->wdd_clock_hz_x1000); in pcf2127_watchdog_init()
586 pcf2127->wdd.timeout = PCF2127_WD_DEFAULT_TIMEOUT_S; in pcf2127_watchdog_init()
589 pcf2127->cfg->wdd_clock_hz_x1000); in pcf2127_watchdog_init()
591 pcf2127->wdd.min_hw_heartbeat_ms = pcf2127->cfg->wdd_min_hw_heartbeat_ms; in pcf2127_watchdog_init()
592 pcf2127->wdd.status = WATCHDOG_NOWAYOUT_INIT_STATUS; in pcf2127_watchdog_init()
594 watchdog_set_drvdata(&pcf2127->wdd, pcf2127); in pcf2127_watchdog_init()
597 if (pcf2127->cfg->wd_val_reg_readable) { in pcf2127_watchdog_init()
600 ret = regmap_read(pcf2127->regmap, pcf2127->cfg->reg_wd_val, in pcf2127_watchdog_init()
606 set_bit(WDOG_HW_RUNNING, &pcf2127->wdd.status); in pcf2127_watchdog_init()
609 return devm_watchdog_register_device(dev, &pcf2127->wdd); in pcf2127_watchdog_init()
620 ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL2, &ctrl2); in pcf2127_rtc_read_alarm()
624 ret = pcf2127_wdt_active_ping(&pcf2127->wdd); in pcf2127_rtc_read_alarm()
628 ret = regmap_bulk_read(pcf2127->regmap, pcf2127->cfg->regs_alarm_base, in pcf2127_rtc_read_alarm()
633 alrm->enabled = ctrl2 & PCF2127_BIT_CTRL2_AIE; in pcf2127_rtc_read_alarm()
634 alrm->pending = ctrl2 & PCF2127_BIT_CTRL2_AF; in pcf2127_rtc_read_alarm()
636 alrm->time.tm_sec = bcd2bin(buf[0] & 0x7F); in pcf2127_rtc_read_alarm()
637 alrm->time.tm_min = bcd2bin(buf[1] & 0x7F); in pcf2127_rtc_read_alarm()
638 alrm->time.tm_hour = bcd2bin(buf[2] & 0x3F); in pcf2127_rtc_read_alarm()
639 alrm->time.tm_mday = bcd2bin(buf[3] & 0x3F); in pcf2127_rtc_read_alarm()
649 ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2, in pcf2127_rtc_alarm_irq_enable()
655 return pcf2127_wdt_active_ping(&pcf2127->wdd); in pcf2127_rtc_alarm_irq_enable()
664 ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2, in pcf2127_rtc_set_alarm()
669 ret = pcf2127_wdt_active_ping(&pcf2127->wdd); in pcf2127_rtc_set_alarm()
673 buf[0] = bin2bcd(alrm->time.tm_sec); in pcf2127_rtc_set_alarm()
674 buf[1] = bin2bcd(alrm->time.tm_min); in pcf2127_rtc_set_alarm()
675 buf[2] = bin2bcd(alrm->time.tm_hour); in pcf2127_rtc_set_alarm()
676 buf[3] = bin2bcd(alrm->time.tm_mday); in pcf2127_rtc_set_alarm()
679 ret = regmap_bulk_write(pcf2127->regmap, pcf2127->cfg->regs_alarm_base, in pcf2127_rtc_set_alarm()
684 return pcf2127_rtc_alarm_irq_enable(dev, alrm->enabled); in pcf2127_rtc_set_alarm()
699 ret = regmap_bulk_read(pcf2127->regmap, pcf2127->cfg->ts[ts_id].reg_base, in pcf2127_rtc_ts_read()
714 /* TS_MO register (month) value range: 1-12 */ in pcf2127_rtc_ts_read()
715 tm.tm_mon = bcd2bin(data[5] & 0x1F) - 1; in pcf2127_rtc_ts_read()
735 if (ts_id >= pcf2127->cfg->ts_count) in pcf2127_rtc_ts_snapshot()
739 if (pcf2127->ts_valid[ts_id]) in pcf2127_rtc_ts_snapshot()
742 ret = pcf2127_rtc_ts_read(dev, &pcf2127->ts[ts_id], ts_id); in pcf2127_rtc_ts_snapshot()
744 pcf2127->ts_valid[ts_id] = true; in pcf2127_rtc_ts_snapshot()
753 ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL2, &ctrl2); in pcf2127_rtc_irq()
757 if (pcf2127->cfg->ts_count == 1) { in pcf2127_rtc_irq()
761 ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL1, &ctrl1); in pcf2127_rtc_irq()
772 regmap_write(pcf2127->regmap, PCF2127_REG_CTRL1, in pcf2127_rtc_irq()
776 regmap_write(pcf2127->regmap, PCF2127_REG_CTRL2, in pcf2127_rtc_irq()
782 ret = regmap_read(pcf2127->regmap, PCF2131_REG_CTRL4, &ctrl4); in pcf2127_rtc_irq()
793 for (i = 0; i < pcf2127->cfg->ts_count; i++) { in pcf2127_rtc_irq()
800 regmap_write(pcf2127->regmap, PCF2131_REG_CTRL4, in pcf2127_rtc_irq()
805 regmap_write(pcf2127->regmap, PCF2127_REG_CTRL2, in pcf2127_rtc_irq()
810 rtc_update_irq(pcf2127->rtc, 1, RTC_IRQF | RTC_AF); in pcf2127_rtc_irq()
812 pcf2127_wdt_active_ping(&pcf2127->wdd); in pcf2127_rtc_irq()
834 struct pcf2127 *pcf2127 = dev_get_drvdata(dev->parent); in timestamp_store()
837 if (ts_id >= pcf2127->cfg->ts_count) in timestamp_store()
840 if (pcf2127->irq_enabled) { in timestamp_store()
841 pcf2127->ts_valid[ts_id] = false; in timestamp_store()
844 ret = regmap_update_bits(pcf2127->regmap, in timestamp_store()
845 pcf2127->cfg->ts[ts_id].gnd_detect_reg, in timestamp_store()
846 pcf2127->cfg->ts[ts_id].gnd_detect_bit, in timestamp_store()
854 if (pcf2127->cfg->ts[ts_id].inter_detect_bit) { in timestamp_store()
856 ret = regmap_update_bits(pcf2127->regmap, in timestamp_store()
857 pcf2127->cfg->ts[ts_id].inter_detect_reg, in timestamp_store()
858 pcf2127->cfg->ts[ts_id].inter_detect_bit, in timestamp_store()
867 ret = pcf2127_wdt_active_ping(&pcf2127->wdd); in timestamp_store()
907 struct pcf2127 *pcf2127 = dev_get_drvdata(dev->parent); in timestamp_show()
911 if (ts_id >= pcf2127->cfg->ts_count) in timestamp_show()
914 if (pcf2127->irq_enabled) { in timestamp_show()
915 if (!pcf2127->ts_valid[ts_id]) in timestamp_show()
917 ts = pcf2127->ts[ts_id]; in timestamp_show()
926 ret = regmap_read(pcf2127->regmap, in timestamp_show()
927 pcf2127->cfg->ts[ts_id].gnd_detect_reg, in timestamp_show()
932 valid_low = ctrl & pcf2127->cfg->ts[ts_id].gnd_detect_bit; in timestamp_show()
934 if (pcf2127->cfg->ts[ts_id].inter_detect_bit) { in timestamp_show()
938 ret = regmap_read(pcf2127->regmap, in timestamp_show()
939 pcf2127->cfg->ts[ts_id].inter_detect_reg, in timestamp_show()
944 valid_inter = ctrl & pcf2127->cfg->ts[ts_id].inter_detect_bit; in timestamp_show()
950 ret = pcf2127_rtc_ts_read(dev->parent, &ts, ts_id); in timestamp_show()
954 ret = pcf2127_wdt_active_ping(&pcf2127->wdd); in timestamp_show()
1121 if (ts_id >= pcf2127->cfg->ts_count) { in pcf2127_enable_ts()
1124 return -EINVAL; in pcf2127_enable_ts()
1128 ret = regmap_update_bits(pcf2127->regmap, in pcf2127_enable_ts()
1129 pcf2127->cfg->ts[ts_id].reg_base, in pcf2127_enable_ts()
1141 * Interrupt signals are open-drain outputs and can be left floating if in pcf2127_enable_ts()
1144 ret = regmap_update_bits(pcf2127->regmap, pcf2127->cfg->ts[ts_id].ie_reg, in pcf2127_enable_ts()
1145 pcf2127->cfg->ts[ts_id].ie_bit, in pcf2127_enable_ts()
1146 pcf2127->cfg->ts[ts_id].ie_bit); in pcf2127_enable_ts()
1165 ret = regmap_write(pcf2127->regmap, in pcf2127_configure_interrupt_pins()
1170 ret = regmap_write(pcf2127->regmap, in pcf2127_configure_interrupt_pins()
1189 return -ENOMEM; in pcf2127_probe()
1191 pcf2127->regmap = regmap; in pcf2127_probe()
1192 pcf2127->cfg = config; in pcf2127_probe()
1196 pcf2127->rtc = devm_rtc_allocate_device(dev); in pcf2127_probe()
1197 if (IS_ERR(pcf2127->rtc)) in pcf2127_probe()
1198 return PTR_ERR(pcf2127->rtc); in pcf2127_probe()
1200 pcf2127->rtc->ops = &pcf2127_rtc_ops; in pcf2127_probe()
1201 pcf2127->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; in pcf2127_probe()
1202 pcf2127->rtc->range_max = RTC_TIMESTAMP_END_2099; in pcf2127_probe()
1203 pcf2127->rtc->set_start_time = true; /* Sets actual start to 1970 */ in pcf2127_probe()
1209 if (pcf2127->cfg->type == PCF2127 || pcf2127->cfg->type == PCF2129) { in pcf2127_probe()
1210 set_bit(RTC_FEATURE_ALARM_RES_2S, pcf2127->rtc->features); in pcf2127_probe()
1211 clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, pcf2127->rtc->features); in pcf2127_probe()
1214 clear_bit(RTC_FEATURE_ALARM, pcf2127->rtc->features); in pcf2127_probe()
1236 pcf2127->irq_enabled = true; in pcf2127_probe()
1239 if (alarm_irq > 0 || device_property_read_bool(dev, "wakeup-source")) { in pcf2127_probe()
1241 set_bit(RTC_FEATURE_ALARM, pcf2127->rtc->features); in pcf2127_probe()
1244 if (pcf2127->cfg->has_int_a_b) { in pcf2127_probe()
1253 if (pcf2127->cfg->has_nvmem) { in pcf2127_probe()
1261 ret = devm_rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg); in pcf2127_probe()
1265 * The "Power-On Reset Override" facility prevents the RTC to do a reset in pcf2127_probe()
1268 ret = regmap_clear_bits(pcf2127->regmap, PCF2127_REG_CTRL1, in pcf2127_probe()
1273 ret = regmap_read(pcf2127->regmap, pcf2127->cfg->reg_clkout, &val); in pcf2127_probe()
1278 ret = regmap_set_bits(pcf2127->regmap, pcf2127->cfg->reg_clkout, in pcf2127_probe()
1295 ret = regmap_update_bits(pcf2127->regmap, pcf2127->cfg->reg_wd_ctl, in pcf2127_probe()
1301 (pcf2127->cfg->has_bit_wd_ctl_cd0 ? PCF2127_BIT_WD_CTL_CD0 : 0) | in pcf2127_probe()
1311 * Disable battery low/switch-over timestamp and interrupts. in pcf2127_probe()
1312 * Clear battery interrupt flags which can block new trigger events. in pcf2127_probe()
1316 ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3, in pcf2127_probe()
1329 for (int i = 0; i < pcf2127->cfg->ts_count; i++) { in pcf2127_probe()
1335 ret = rtc_add_group(pcf2127->rtc, &pcf2127->cfg->attribute_group); in pcf2127_probe()
1342 return devm_rtc_register_device(pcf2127->rtc); in pcf2127_probe()
1366 return ret < 0 ? ret : -EIO; in pcf2127_i2c_write()
1381 return -EINVAL; in pcf2127_i2c_gather_write()
1385 return -ENOMEM; in pcf2127_i2c_gather_write()
1395 return ret < 0 ? ret : -EIO; in pcf2127_i2c_gather_write()
1408 return -EINVAL; in pcf2127_i2c_read()
1412 return ret < 0 ? ret : -EIO; in pcf2127_i2c_read()
1416 return ret < 0 ? ret : -EIO; in pcf2127_i2c_read()
1452 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) in pcf2127_i2c_probe()
1453 return -ENODEV; in pcf2127_i2c_probe()
1455 if (client->dev.of_node) { in pcf2127_i2c_probe()
1456 variant = of_device_get_match_data(&client->dev); in pcf2127_i2c_probe()
1458 return -ENODEV; in pcf2127_i2c_probe()
1461 i2c_match_id(pcf2127_i2c_id, client)->driver_data; in pcf2127_i2c_probe()
1464 return -ENODEV; in pcf2127_i2c_probe()
1468 config.max_register = variant->max_register, in pcf2127_i2c_probe()
1470 regmap = devm_regmap_init(&client->dev, &pcf2127_i2c_regmap, in pcf2127_i2c_probe()
1471 &client->dev, &config); in pcf2127_i2c_probe()
1473 dev_err(&client->dev, "%s: regmap allocation failed: %ld\n", in pcf2127_i2c_probe()
1478 return pcf2127_probe(&client->dev, regmap, client->irq, variant); in pcf2127_i2c_probe()
1483 .name = "rtc-pcf2127-i2c",
1529 if (spi->dev.of_node) { in pcf2127_spi_probe()
1530 variant = of_device_get_match_data(&spi->dev); in pcf2127_spi_probe()
1532 return -ENODEV; in pcf2127_spi_probe()
1534 enum pcf21xx_type type = spi_get_device_id(spi)->driver_data; in pcf2127_spi_probe()
1537 return -ENODEV; in pcf2127_spi_probe()
1541 config.max_register = variant->max_register, in pcf2127_spi_probe()
1545 dev_err(&spi->dev, "%s: regmap allocation failed: %ld\n", in pcf2127_spi_probe()
1550 return pcf2127_probe(&spi->dev, regmap, spi->irq, variant); in pcf2127_spi_probe()
1564 .name = "rtc-pcf2127-spi",
1621 MODULE_AUTHOR("Renaud Cerrato <r.cerrato@til-technologies.fr>");