rtc-pcf2127.c (05909cd9a0c8811731b38697af13075e8954314f) rtc-pcf2127.c (3a905c2d9544a418953d6c18668f0f853fbd9be9)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * An I2C and SPI driver for the NXP PCF2127/29 RTC
4 * Copyright 2013 Til-Technologies
5 *
6 * Author: Renaud Cerrato <r.cerrato@til-technologies.fr>
7 *
8 * Watchdog and tamper functions

--- 229 unchanged lines hidden (view full) ---

238 int ret;
239 unsigned char offsetbuf[] = { offset >> 8, offset };
240
241 ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_ADDR_MSB,
242 offsetbuf, 2);
243 if (ret)
244 return ret;
245
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * An I2C and SPI driver for the NXP PCF2127/29 RTC
4 * Copyright 2013 Til-Technologies
5 *
6 * Author: Renaud Cerrato <r.cerrato@til-technologies.fr>
7 *
8 * Watchdog and tamper functions

--- 229 unchanged lines hidden (view full) ---

238 int ret;
239 unsigned char offsetbuf[] = { offset >> 8, offset };
240
241 ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_ADDR_MSB,
242 offsetbuf, 2);
243 if (ret)
244 return ret;
245
246 ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_RD_CMD,
247 val, bytes);
248
249 return ret ?: bytes;
246 return regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_RD_CMD,
247 val, bytes);
250}
251
252static int pcf2127_nvmem_write(void *priv, unsigned int offset,
253 void *val, size_t bytes)
254{
255 struct pcf2127 *pcf2127 = priv;
256 int ret;
257 unsigned char offsetbuf[] = { offset >> 8, offset };
258
259 ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_ADDR_MSB,
260 offsetbuf, 2);
261 if (ret)
262 return ret;
263
248}
249
250static int pcf2127_nvmem_write(void *priv, unsigned int offset,
251 void *val, size_t bytes)
252{
253 struct pcf2127 *pcf2127 = priv;
254 int ret;
255 unsigned char offsetbuf[] = { offset >> 8, offset };
256
257 ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_ADDR_MSB,
258 offsetbuf, 2);
259 if (ret)
260 return ret;
261
264 ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_WRT_CMD,
265 val, bytes);
266
267 return ret ?: bytes;
262 return regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_WRT_CMD,
263 val, bytes);
268}
269
270/* watchdog driver */
271
272static int pcf2127_wdt_ping(struct watchdog_device *wdd)
273{
274 struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd);
275

--- 54 unchanged lines hidden (view full) ---

330static const struct watchdog_ops pcf2127_watchdog_ops = {
331 .owner = THIS_MODULE,
332 .start = pcf2127_wdt_start,
333 .stop = pcf2127_wdt_stop,
334 .ping = pcf2127_wdt_ping,
335 .set_timeout = pcf2127_wdt_set_timeout,
336};
337
264}
265
266/* watchdog driver */
267
268static int pcf2127_wdt_ping(struct watchdog_device *wdd)
269{
270 struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd);
271

--- 54 unchanged lines hidden (view full) ---

326static const struct watchdog_ops pcf2127_watchdog_ops = {
327 .owner = THIS_MODULE,
328 .start = pcf2127_wdt_start,
329 .stop = pcf2127_wdt_stop,
330 .ping = pcf2127_wdt_ping,
331 .set_timeout = pcf2127_wdt_set_timeout,
332};
333
334static int pcf2127_watchdog_init(struct device *dev, struct pcf2127 *pcf2127)
335{
336 u32 wdd_timeout;
337 int ret;
338
339 if (!IS_ENABLED(CONFIG_WATCHDOG))
340 return 0;
341
342 pcf2127->wdd.parent = dev;
343 pcf2127->wdd.info = &pcf2127_wdt_info;
344 pcf2127->wdd.ops = &pcf2127_watchdog_ops;
345 pcf2127->wdd.min_timeout = PCF2127_WD_VAL_MIN;
346 pcf2127->wdd.max_timeout = PCF2127_WD_VAL_MAX;
347 pcf2127->wdd.timeout = PCF2127_WD_VAL_DEFAULT;
348 pcf2127->wdd.min_hw_heartbeat_ms = 500;
349 pcf2127->wdd.status = WATCHDOG_NOWAYOUT_INIT_STATUS;
350
351 watchdog_set_drvdata(&pcf2127->wdd, pcf2127);
352
353 /* Test if watchdog timer is started by bootloader */
354 ret = regmap_read(pcf2127->regmap, PCF2127_REG_WD_VAL, &wdd_timeout);
355 if (ret)
356 return ret;
357
358 if (wdd_timeout)
359 set_bit(WDOG_HW_RUNNING, &pcf2127->wdd.status);
360
361 return devm_watchdog_register_device(dev, &pcf2127->wdd);
362}
363
338/* Alarm */
339static int pcf2127_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
340{
341 struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
342 unsigned int buf[5], ctrl2;
343 int ret;
344
345 ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL2, &ctrl2);

--- 185 unchanged lines hidden (view full) ---

531static const struct attribute_group pcf2127_attr_group = {
532 .attrs = pcf2127_attrs,
533};
534
535static int pcf2127_probe(struct device *dev, struct regmap *regmap,
536 int alarm_irq, const char *name, bool has_nvmem)
537{
538 struct pcf2127 *pcf2127;
364/* Alarm */
365static int pcf2127_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
366{
367 struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
368 unsigned int buf[5], ctrl2;
369 int ret;
370
371 ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL2, &ctrl2);

--- 185 unchanged lines hidden (view full) ---

557static const struct attribute_group pcf2127_attr_group = {
558 .attrs = pcf2127_attrs,
559};
560
561static int pcf2127_probe(struct device *dev, struct regmap *regmap,
562 int alarm_irq, const char *name, bool has_nvmem)
563{
564 struct pcf2127 *pcf2127;
539 u32 wdd_timeout;
540 int ret = 0;
541
542 dev_dbg(dev, "%s\n", __func__);
543
544 pcf2127 = devm_kzalloc(dev, sizeof(*pcf2127), GFP_KERNEL);
545 if (!pcf2127)
546 return -ENOMEM;
547

--- 6 unchanged lines hidden (view full) ---

554 return PTR_ERR(pcf2127->rtc);
555
556 pcf2127->rtc->ops = &pcf2127_rtc_ops;
557 pcf2127->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
558 pcf2127->rtc->range_max = RTC_TIMESTAMP_END_2099;
559 pcf2127->rtc->set_start_time = true; /* Sets actual start to 1970 */
560 pcf2127->rtc->uie_unsupported = 1;
561
565 int ret = 0;
566
567 dev_dbg(dev, "%s\n", __func__);
568
569 pcf2127 = devm_kzalloc(dev, sizeof(*pcf2127), GFP_KERNEL);
570 if (!pcf2127)
571 return -ENOMEM;
572

--- 6 unchanged lines hidden (view full) ---

579 return PTR_ERR(pcf2127->rtc);
580
581 pcf2127->rtc->ops = &pcf2127_rtc_ops;
582 pcf2127->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
583 pcf2127->rtc->range_max = RTC_TIMESTAMP_END_2099;
584 pcf2127->rtc->set_start_time = true; /* Sets actual start to 1970 */
585 pcf2127->rtc->uie_unsupported = 1;
586
562 if (alarm_irq >= 0) {
587 if (alarm_irq > 0) {
563 ret = devm_request_threaded_irq(dev, alarm_irq, NULL,
564 pcf2127_rtc_irq,
565 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
566 dev_name(dev), dev);
567 if (ret) {
568 dev_err(dev, "failed to request alarm irq\n");
569 return ret;
570 }
571 }
572
588 ret = devm_request_threaded_irq(dev, alarm_irq, NULL,
589 pcf2127_rtc_irq,
590 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
591 dev_name(dev), dev);
592 if (ret) {
593 dev_err(dev, "failed to request alarm irq\n");
594 return ret;
595 }
596 }
597
573 if (alarm_irq >= 0 || device_property_read_bool(dev, "wakeup-source")) {
598 if (alarm_irq > 0 || device_property_read_bool(dev, "wakeup-source")) {
574 device_init_wakeup(dev, true);
575 pcf2127->rtc->ops = &pcf2127_rtc_alrm_ops;
576 }
577
599 device_init_wakeup(dev, true);
600 pcf2127->rtc->ops = &pcf2127_rtc_alrm_ops;
601 }
602
578 pcf2127->wdd.parent = dev;
579 pcf2127->wdd.info = &pcf2127_wdt_info;
580 pcf2127->wdd.ops = &pcf2127_watchdog_ops;
581 pcf2127->wdd.min_timeout = PCF2127_WD_VAL_MIN;
582 pcf2127->wdd.max_timeout = PCF2127_WD_VAL_MAX;
583 pcf2127->wdd.timeout = PCF2127_WD_VAL_DEFAULT;
584 pcf2127->wdd.min_hw_heartbeat_ms = 500;
585 pcf2127->wdd.status = WATCHDOG_NOWAYOUT_INIT_STATUS;
586
587 watchdog_set_drvdata(&pcf2127->wdd, pcf2127);
588
589 if (has_nvmem) {
590 struct nvmem_config nvmem_cfg = {
591 .priv = pcf2127,
592 .reg_read = pcf2127_nvmem_read,
593 .reg_write = pcf2127_nvmem_write,
594 .size = 512,
595 };
596
603 if (has_nvmem) {
604 struct nvmem_config nvmem_cfg = {
605 .priv = pcf2127,
606 .reg_read = pcf2127_nvmem_read,
607 .reg_write = pcf2127_nvmem_write,
608 .size = 512,
609 };
610
597 ret = rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg);
611 ret = devm_rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg);
598 }
599
600 /*
601 * Watchdog timer enabled and reset pin /RST activated when timed out.
602 * Select 1Hz clock source for watchdog timer.
603 * Note: Countdown timer disabled and not available.
604 */
605 ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_WD_CTL,

--- 4 unchanged lines hidden (view full) ---

610 PCF2127_BIT_WD_CTL_CD1 |
611 PCF2127_BIT_WD_CTL_CD0 |
612 PCF2127_BIT_WD_CTL_TF1);
613 if (ret) {
614 dev_err(dev, "%s: watchdog config (wd_ctl) failed\n", __func__);
615 return ret;
616 }
617
612 }
613
614 /*
615 * Watchdog timer enabled and reset pin /RST activated when timed out.
616 * Select 1Hz clock source for watchdog timer.
617 * Note: Countdown timer disabled and not available.
618 */
619 ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_WD_CTL,

--- 4 unchanged lines hidden (view full) ---

624 PCF2127_BIT_WD_CTL_CD1 |
625 PCF2127_BIT_WD_CTL_CD0 |
626 PCF2127_BIT_WD_CTL_TF1);
627 if (ret) {
628 dev_err(dev, "%s: watchdog config (wd_ctl) failed\n", __func__);
629 return ret;
630 }
631
618 /* Test if watchdog timer is started by bootloader */
619 ret = regmap_read(pcf2127->regmap, PCF2127_REG_WD_VAL, &wdd_timeout);
620 if (ret)
621 return ret;
632 pcf2127_watchdog_init(dev, pcf2127);
622
633
623 if (wdd_timeout)
624 set_bit(WDOG_HW_RUNNING, &pcf2127->wdd.status);
625
626#ifdef CONFIG_WATCHDOG
627 ret = devm_watchdog_register_device(dev, &pcf2127->wdd);
628 if (ret)
629 return ret;
630#endif /* CONFIG_WATCHDOG */
631
632 /*
633 * Disable battery low/switch-over timestamp and interrupts.
634 * Clear battery interrupt flags which can block new trigger events.
635 * Note: This is the default chip behaviour but added to ensure
636 * correct tamper timestamp and interrupt function.
637 */
638 ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3,
639 PCF2127_BIT_CTRL3_BTSE |

--- 296 unchanged lines hidden ---
634 /*
635 * Disable battery low/switch-over timestamp and interrupts.
636 * Clear battery interrupt flags which can block new trigger events.
637 * Note: This is the default chip behaviour but added to ensure
638 * correct tamper timestamp and interrupt function.
639 */
640 ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3,
641 PCF2127_BIT_CTRL3_BTSE |

--- 296 unchanged lines hidden ---