// SPDX-License-Identifier: GPL-2.0-only/* * An I2C and SPI driver for the NXP PCF2127/29/31 RTC * Copyright 2013 Til-Technologies * * Author: Renaud Cerrato <r.cerrato@til-technologies.fr> * * Watchdog and tamper functions * Author: Bruno Thomsen <bruno.thomsen@gmail.com> * * PCF2131 support * Author: Hugo Villeneuve <hvilleneuve@dimonoff.com> * * based on the other drivers in this same directory. * * Datasheets: https://www.nxp.com/docs/en/data-sheet/PCF2127.pdf * https://www.nxp.com/docs/en/data-sheet/PCF2131DS.pdf */ #include <linux/i2c.h>#include <linux/spi/spi.h>#include <linux/bcd.h>#include <linux/bitfield.h>#include <linux/rtc.h>#include <linux/slab.h>#include <linux/module.h>#include <linux/of.h>#include <linux/of_irq.h>#include <linux/of_device.h>#include <linux/regmap.h>#include <linux/watchdog.h> /* Control register 1 */#define PCF2127_REG_CTRL1 0x00#define PCF2127_BIT_CTRL1_POR_OVRD BIT(3)#define PCF2127_BIT_CTRL1_TSF1 BIT(4)#define PCF2127_BIT_CTRL1_STOP BIT(5)/* Control register 2 */#define PCF2127_REG_CTRL2 0x01#define PCF2127_BIT_CTRL2_AIE BIT(1)#define PCF2127_BIT_CTRL2_TSIE BIT(2)#define PCF2127_BIT_CTRL2_AF BIT(4)#define PCF2127_BIT_CTRL2_TSF2 BIT(5)#define PCF2127_BIT_CTRL2_WDTF BIT(6)#define PCF2127_BIT_CTRL2_MSF BIT(7)/* Control register 3 */#define PCF2127_REG_CTRL3 0x02#define PCF2127_BIT_CTRL3_BLIE BIT(0)#define PCF2127_BIT_CTRL3_BIE BIT(1)#define PCF2127_BIT_CTRL3_BLF BIT(2)#define PCF2127_BIT_CTRL3_BF BIT(3)#define PCF2127_BIT_CTRL3_BTSE BIT(4)#define PCF2127_CTRL3_PM GENMASK(7, 5)/* Time and date registers */#define PCF2127_REG_TIME_BASE 0x03#define PCF2127_BIT_SC_OSF BIT(7)/* Alarm registers */#define PCF2127_REG_ALARM_BASE 0x0A#define PCF2127_BIT_ALARM_AE BIT(7)/* CLKOUT control register */#define PCF2127_REG_CLKOUT 0x0f#define PCF2127_BIT_CLKOUT_OTPR BIT(5)/* Watchdog registers */#define PCF2127_REG_WD_CTL 0x10#define PCF2127_BIT_WD_CTL_TF0 BIT(0)#define PCF2127_BIT_WD_CTL_TF1 BIT(1)#define PCF2127_BIT_WD_CTL_CD0 BIT(6)#define PCF2127_BIT_WD_CTL_CD1 BIT(7)#define PCF2127_REG_WD_VAL 0x11/* Tamper timestamp1 registers */#define PCF2127_REG_TS1_BASE 0x12#define PCF2127_BIT_TS_CTRL_TSOFF BIT(6)#define PCF2127_BIT_TS_CTRL_TSM BIT(7)/* * RAM registers * PCF2127 has 512 bytes general-purpose static RAM (SRAM) that is * battery backed and can survive a power outage. * PCF2129/31 doesn't have this feature. */#define PCF2127_REG_RAM_ADDR_MSB 0x1A#define PCF2127_REG_RAM_WRT_CMD 0x1C#define PCF2127_REG_RAM_RD_CMD 0x1D /* Watchdog timer value constants */#define PCF2127_WD_VAL_STOP 0/* PCF2127/29 watchdog timer value constants */#define PCF2127_WD_CLOCK_HZ_X1000 1000 /* 1Hz */#define PCF2127_WD_MIN_HW_HEARTBEAT_MS 500/* PCF2131 watchdog timer value constants */#define PCF2131_WD_CLOCK_HZ_X1000 250 /* 1/4Hz */#define PCF2131_WD_MIN_HW_HEARTBEAT_MS 4000 #define PCF2127_WD_DEFAULT_TIMEOUT_S 60 /* Mask for currently enabled interrupts */#define PCF2127_CTRL1_IRQ_MASK (PCF2127_BIT_CTRL1_TSF1)#define PCF2127_CTRL2_IRQ_MASK ( \ PCF2127_BIT_CTRL2_AF | \ PCF2127_BIT_CTRL2_WDTF | \ PCF2127_BIT_CTRL2_TSF2 | \ PCF2127_BIT_CTRL2_MSF) #define PCF2127_MAX_TS_SUPPORTED 4 /* Control register 4 */#define PCF2131_REG_CTRL4 0x03#define PCF2131_BIT_CTRL4_TSF4 BIT(4)#define PCF2131_BIT_CTRL4_TSF3 BIT(5)#define PCF2131_BIT_CTRL4_TSF2 BIT(6)#define PCF2131_BIT_CTRL4_TSF1 BIT(7)/* Control register 5 */#define PCF2131_REG_CTRL5 0x04#define PCF2131_BIT_CTRL5_TSIE4 BIT(4)#define PCF2131_BIT_CTRL5_TSIE3 BIT(5)#define PCF2131_BIT_CTRL5_TSIE2 BIT(6)#define PCF2131_BIT_CTRL5_TSIE1 BIT(7)/* Software reset register */#define PCF2131_REG_SR_RESET 0x05#define PCF2131_SR_RESET_READ_PATTERN (BIT(2) | BIT(5))#define PCF2131_SR_RESET_CPR_CMD (PCF2131_SR_RESET_READ_PATTERN | BIT(7))/* Time and date registers */#define PCF2131_REG_TIME_BASE 0x07/* Alarm registers */#define PCF2131_REG_ALARM_BASE 0x0E/* CLKOUT control register */#define PCF2131_REG_CLKOUT 0x13/* Watchdog registers */#define PCF2131_REG_WD_CTL 0x35#define PCF2131_REG_WD_VAL 0x36/* Tamper timestamp1 registers */#define PCF2131_REG_TS1_BASE 0x14/* Tamper timestamp2 registers */#define PCF2131_REG_TS2_BASE 0x1B/* Tamper timestamp3 registers */#define PCF2131_REG_TS3_BASE 0x22/* Tamper timestamp4 registers */#define PCF2131_REG_TS4_BASE 0x29/* Interrupt mask registers */#define PCF2131_REG_INT_A_MASK1 0x31#define PCF2131_REG_INT_A_MASK2 0x32#define PCF2131_REG_INT_B_MASK1 0x33#define PCF2131_REG_INT_B_MASK2 0x34#define PCF2131_BIT_INT_BLIE BIT(0)#define PCF2131_BIT_INT_BIE BIT(1)#define PCF2131_BIT_INT_AIE BIT(2)#define PCF2131_BIT_INT_WD_CD BIT(3)#define PCF2131_BIT_INT_SI BIT(4)#define PCF2131_BIT_INT_MI BIT(5)#define PCF2131_CTRL2_IRQ_MASK ( \ PCF2127_BIT_CTRL2_AF | \ PCF2127_BIT_CTRL2_WDTF)#define PCF2131_CTRL4_IRQ_MASK ( \ PCF2131_BIT_CTRL4_TSF4 | \ PCF2131_BIT_CTRL4_TSF3 | \ PCF2131_BIT_CTRL4_TSF2 | \ PCF2131_BIT_CTRL4_TSF1) enum pcf21xx_type { PCF2127, PCF2129, PCF2131, PCF21XX_LAST_ID}; struct pcf21xx_ts_config { u8 reg_base; /* Base register to read timestamp values. */ /* * If the TS input pin is driven to GND, an interrupt can be generated * (supported by all variants). */ u8 gnd_detect_reg; /* Interrupt control register address. */ u8 gnd_detect_bit; /* Interrupt bit. */ /* * If the TS input pin is driven to an intermediate level between GND * and supply, an interrupt can be generated (optional feature depending * on variant). */ u8 inter_detect_reg; /* Interrupt control register address. */ u8 inter_detect_bit; /* Interrupt bit. */ u8 ie_reg; /* Interrupt enable control register. */ u8 ie_bit; /* Interrupt enable bit. */}; struct pcf21xx_config { int type; /* IC variant */ int max_register; unsigned int has_nvmem:1; unsigned int has_bit_wd_ctl_cd0:1; unsigned int wd_val_reg_readable:1; /* If watchdog value register can be read. */ unsigned int has_int_a_b:1; /* PCF2131 supports two interrupt outputs. */ u8 reg_time_base; /* Time/date base register. */ u8 regs_alarm_base; /* Alarm function base registers. */ u8 reg_wd_ctl; /* Watchdog control register. */ u8 reg_wd_val; /* Watchdog value register. */ u8 reg_clkout; /* Clkout register. */ int wdd_clock_hz_x1000; /* Watchdog clock in Hz multiplicated by 1000 */ int wdd_min_hw_heartbeat_ms; unsigned int ts_count; struct pcf21xx_ts_config ts[PCF2127_MAX_TS_SUPPORTED]; struct attribute_group attribute_group;}; struct pcf2127 { struct rtc_device *rtc; struct watchdog_device wdd; struct regmap *regmap; const struct pcf21xx_config *cfg; bool irq_enabled; time64_t ts[PCF2127_MAX_TS_SUPPORTED]; /* Timestamp values. */ bool ts_valid[PCF2127_MAX_TS_SUPPORTED]; /* Timestamp valid indication. */}; /* * In the routines that deal directly with the pcf2127 hardware, we use * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. */static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm){ struct pcf2127 *pcf2127 = dev_get_drvdata(dev); unsigned char buf[7]; int ret; /* * Avoid reading CTRL2 register as it causes WD_VAL register * value to reset to 0 which means watchdog is stopped. */ ret = regmap_bulk_read(pcf2127->regmap, pcf2127->cfg->reg_time_base, buf, sizeof(buf)); if (ret) { dev_err(dev, "%s: read error\n", __func__); return ret; } /* Clock integrity is not guaranteed when OSF flag is set. */ if (buf[0] & PCF2127_BIT_SC_OSF) { /* * no need clear the flag here, * it will be cleared once the new date is saved */ dev_warn(dev, "oscillator stop detected, date/time is not reliable\n"); return -EINVAL; } dev_dbg(dev, "%s: raw data is sec=%02x, min=%02x, hr=%02x, " "mday=%02x, wday=%02x, mon=%02x, year=%02x\n", __func__, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); tm->tm_sec = bcd2bin(buf[0] & 0x7F); tm->tm_min = bcd2bin(buf[1] & 0x7F); tm->tm_hour = bcd2bin(buf[2] & 0x3F); tm->tm_mday = bcd2bin(buf[3] & 0x3F); tm->tm_wday = buf[4] & 0x07; tm->tm_mon = bcd2bin(buf[5] & 0x1F) - 1; tm->tm_year = bcd2bin(buf[6]); tm->tm_year += 100; dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); return 0;} static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm){ struct pcf2127 *pcf2127 = dev_get_drvdata(dev); unsigned char buf[7]; int i = 0, err; dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); /* hours, minutes and seconds */ buf[i++] = bin2bcd(tm->tm_sec); /* this will also clear OSF flag */ buf[i++] = bin2bcd(tm->tm_min); buf[i++] = bin2bcd(tm->tm_hour); buf[i++] = bin2bcd(tm->tm_mday); buf[i++] = tm->tm_wday & 0x07; /* month, 1 - 12 */ buf[i++] = bin2bcd(tm->tm_mon + 1); /* year */ buf[i++] = bin2bcd(tm->tm_year - 100); /* Write access to time registers: * PCF2127/29: no special action required. * PCF2131: requires setting the STOP and CPR bits. STOP bit needs to * be cleared after time registers are updated. */ if (pcf2127->cfg->type == PCF2131) { err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, PCF2127_BIT_CTRL1_STOP, PCF2127_BIT_CTRL1_STOP); if (err) { dev_dbg(dev, "setting STOP bit failed\n"); return err; } err = regmap_write(pcf2127->regmap, PCF2131_REG_SR_RESET, PCF2131_SR_RESET_CPR_CMD); if (err) { dev_dbg(dev, "sending CPR cmd failed\n"); return err; } } /* write time register's data */ err = regmap_bulk_write(pcf2127->regmap, pcf2127->cfg->reg_time_base, buf, i); if (err) { dev_dbg(dev, "%s: err=%d", __func__, err); return err; } if (pcf2127->cfg->type == PCF2131) { /* Clear STOP bit (PCF2131 only) after write is completed. */ err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, PCF2127_BIT_CTRL1_STOP, 0); if (err) { dev_dbg(dev, "clearing STOP bit failed\n"); return err; } } return 0;} static int pcf2127_param_get(struct device *dev, struct rtc_param *param){ struct pcf2127 *pcf2127 = dev_get_drvdata(dev); u32 value; int ret; switch (param->param) { case RTC_PARAM_BACKUP_SWITCH_MODE: ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &value); if (ret < 0) return ret; value = FIELD_GET(PCF2127_CTRL3_PM, value); if (value < 0x3) param->uvalue = RTC_BSM_LEVEL; else if (value < 0x6) param->uvalue = RTC_BSM_DIRECT; else param->uvalue = RTC_BSM_DISABLED; break; default: return -EINVAL; } return 0;} static int pcf2127_param_set(struct device *dev, struct rtc_param *param){ struct pcf2127 *pcf2127 = dev_get_drvdata(dev); u8 mode = 0; u32 value; int ret; switch (param->param) { case RTC_PARAM_BACKUP_SWITCH_MODE: ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &value); if (ret < 0) return ret; value = FIELD_GET(PCF2127_CTRL3_PM, value); if (value > 5) value -= 5; else if (value > 2) value -= 3; switch (param->uvalue) { case RTC_BSM_LEVEL: break; case RTC_BSM_DIRECT: mode = 3; break; case RTC_BSM_DISABLED: if (value == 0) value = 1; mode = 5; break; default: return -EINVAL; } return regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3, PCF2127_CTRL3_PM, FIELD_PREP(PCF2127_CTRL3_PM, mode + value)); break; default: return -EINVAL; } return 0;} static int pcf2127_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg){ struct pcf2127 *pcf2127 = dev_get_drvdata(dev); int val, touser = 0; int ret; switch (cmd) { case RTC_VL_READ: ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &val); if (ret) return ret; if (val & PCF2127_BIT_CTRL3_BLF) touser |= RTC_VL_BACKUP_LOW; if (val & PCF2127_BIT_CTRL3_BF) touser |= RTC_VL_BACKUP_SWITCH; return put_user(touser, (unsigned int __user *)arg); case RTC_VL_CLR: return regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3, PCF2127_BIT_CTRL3_BF, 0); default: return -ENOIOCTLCMD; }} static int pcf2127_nvmem_read(void *priv, unsigned int offset, void *val, size_t bytes){ struct pcf2127 *pcf2127 = priv; int ret; unsigned char offsetbuf[] = { offset >> 8, offset }; ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_ADDR_MSB, offsetbuf, 2); if (ret) return ret; return regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_RD_CMD, val, bytes);} static int pcf2127_nvmem_write(void *priv, unsigned int offset, void *val, size_t bytes){ struct pcf2127 *pcf2127 = priv; int ret; unsigned char offsetbuf[] = { offset >> 8, offset }; ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_ADDR_MSB, offsetbuf, 2); if (ret) return ret; return regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_WRT_CMD, val, bytes);} /* watchdog driver */ static int pcf2127_wdt_ping(struct watchdog_device *wdd){ int wd_val; struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd); /* * Compute counter value of WATCHDG_TIM_VAL to obtain desired period * in seconds, depending on the source clock frequency. */ wd_val = ((wdd->timeout * pcf2127->cfg->wdd_clock_hz_x1000) / 1000) + 1; return regmap_write(pcf2127->regmap, pcf2127->cfg->reg_wd_val, wd_val);} /* * Restart watchdog timer if feature is active. * * Note: Reading CTRL2 register causes watchdog to stop which is unfortunate, * since register also contain control/status flags for other features. * Always call this function after reading CTRL2 register. */Lines 1–500 of 1631. Load more
// SPDX-License-Identifier: GPL-2.0-only /* * An I2C and SPI driver for the NXP PCF2127/29/31 RTC * Copyright 2013 Til-Technologies * * Author: Renaud Cerrato <r.cerrato@til-technologies.fr> * * Watchdog and tamper functions * Author: Bruno Thomsen <bruno.thomsen@gmail.com> * * PCF2131 support * Author: Hugo Villeneuve <hvilleneuve@dimonoff.com> * * based on the other drivers in this same directory. * * Datasheets: https://www.nxp.com/docs/en/data-sheet/PCF2127.pdf * https://www.nxp.com/docs/en/data-sheet/PCF2131DS.pdf */ #include <linux/i2c.h> #include <linux/spi/spi.h> #include <linux/bcd.h> #include <linux/bitfield.h> #include <linux/rtc.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_irq.h> #include <linux/of_device.h> #include <linux/regmap.h> #include <linux/watchdog.h> /* Control register 1 */ #define PCF2127_REG_CTRL1 0x00 #define PCF2127_BIT_CTRL1_POR_OVRD BIT(3) #define PCF2127_BIT_CTRL1_TSF1 BIT(4) #define PCF2127_BIT_CTRL1_STOP BIT(5) /* Control register 2 */ #define PCF2127_REG_CTRL2 0x01 #define PCF2127_BIT_CTRL2_AIE BIT(1) #define PCF2127_BIT_CTRL2_TSIE BIT(2) #define PCF2127_BIT_CTRL2_AF BIT(4) #define PCF2127_BIT_CTRL2_TSF2 BIT(5) #define PCF2127_BIT_CTRL2_WDTF BIT(6) #define PCF2127_BIT_CTRL2_MSF BIT(7) /* Control register 3 */ #define PCF2127_REG_CTRL3 0x02 #define PCF2127_BIT_CTRL3_BLIE BIT(0) #define PCF2127_BIT_CTRL3_BIE BIT(1) #define PCF2127_BIT_CTRL3_BLF BIT(2) #define PCF2127_BIT_CTRL3_BF BIT(3) #define PCF2127_BIT_CTRL3_BTSE BIT(4) #define PCF2127_CTRL3_PM GENMASK(7, 5) /* Time and date registers */ #define PCF2127_REG_TIME_BASE 0x03 #define PCF2127_BIT_SC_OSF BIT(7) /* Alarm registers */ #define PCF2127_REG_ALARM_BASE 0x0A #define PCF2127_BIT_ALARM_AE BIT(7) /* CLKOUT control register */ #define PCF2127_REG_CLKOUT 0x0f #define PCF2127_BIT_CLKOUT_OTPR BIT(5) /* Watchdog registers */ #define PCF2127_REG_WD_CTL 0x10 #define PCF2127_BIT_WD_CTL_TF0 BIT(0) #define PCF2127_BIT_WD_CTL_TF1 BIT(1) #define PCF2127_BIT_WD_CTL_CD0 BIT(6) #define PCF2127_BIT_WD_CTL_CD1 BIT(7) #define PCF2127_REG_WD_VAL 0x11 /* Tamper timestamp1 registers */ #define PCF2127_REG_TS1_BASE 0x12 #define PCF2127_BIT_TS_CTRL_TSOFF BIT(6) #define PCF2127_BIT_TS_CTRL_TSM BIT(7) /* * RAM registers * PCF2127 has 512 bytes general-purpose static RAM (SRAM) that is * battery backed and can survive a power outage. * PCF2129/31 doesn't have this feature. */ #define PCF2127_REG_RAM_ADDR_MSB 0x1A #define PCF2127_REG_RAM_WRT_CMD 0x1C #define PCF2127_REG_RAM_RD_CMD 0x1D /* Watchdog timer value constants */ #define PCF2127_WD_VAL_STOP 0 /* PCF2127/29 watchdog timer value constants */ #define PCF2127_WD_CLOCK_HZ_X1000 1000 /* 1Hz */ #define PCF2127_WD_MIN_HW_HEARTBEAT_MS 500 /* PCF2131 watchdog timer value constants */ #define PCF2131_WD_CLOCK_HZ_X1000 250 /* 1/4Hz */ #define PCF2131_WD_MIN_HW_HEARTBEAT_MS 4000 #define PCF2127_WD_DEFAULT_TIMEOUT_S 60 /* Mask for currently enabled interrupts */ #define PCF2127_CTRL1_IRQ_MASK (PCF2127_BIT_CTRL1_TSF1) #define PCF2127_CTRL2_IRQ_MASK ( \ PCF2127_BIT_CTRL2_AF | \ PCF2127_BIT_CTRL2_WDTF | \ PCF2127_BIT_CTRL2_TSF2 | \ PCF2127_BIT_CTRL2_MSF) #define PCF2127_MAX_TS_SUPPORTED 4 /* Control register 4 */ #define PCF2131_REG_CTRL4 0x03 #define PCF2131_BIT_CTRL4_TSF4 BIT(4) #define PCF2131_BIT_CTRL4_TSF3 BIT(5) #define PCF2131_BIT_CTRL4_TSF2 BIT(6) #define PCF2131_BIT_CTRL4_TSF1 BIT(7) /* Control register 5 */ #define PCF2131_REG_CTRL5 0x04 #define PCF2131_BIT_CTRL5_TSIE4 BIT(4) #define PCF2131_BIT_CTRL5_TSIE3 BIT(5) #define PCF2131_BIT_CTRL5_TSIE2 BIT(6) #define PCF2131_BIT_CTRL5_TSIE1 BIT(7) /* Software reset register */ #define PCF2131_REG_SR_RESET 0x05 #define PCF2131_SR_RESET_READ_PATTERN (BIT(2) | BIT(5)) #define PCF2131_SR_RESET_CPR_CMD (PCF2131_SR_RESET_READ_PATTERN | BIT(7)) /* Time and date registers */ #define PCF2131_REG_TIME_BASE 0x07 /* Alarm registers */ #define PCF2131_REG_ALARM_BASE 0x0E /* CLKOUT control register */ #define PCF2131_REG_CLKOUT 0x13 /* Watchdog registers */ #define PCF2131_REG_WD_CTL 0x35 #define PCF2131_REG_WD_VAL 0x36 /* Tamper timestamp1 registers */ #define PCF2131_REG_TS1_BASE 0x14 /* Tamper timestamp2 registers */ #define PCF2131_REG_TS2_BASE 0x1B /* Tamper timestamp3 registers */ #define PCF2131_REG_TS3_BASE 0x22 /* Tamper timestamp4 registers */ #define PCF2131_REG_TS4_BASE 0x29 /* Interrupt mask registers */ #define PCF2131_REG_INT_A_MASK1 0x31 #define PCF2131_REG_INT_A_MASK2 0x32 #define PCF2131_REG_INT_B_MASK1 0x33 #define PCF2131_REG_INT_B_MASK2 0x34 #define PCF2131_BIT_INT_BLIE BIT(0) #define PCF2131_BIT_INT_BIE BIT(1) #define PCF2131_BIT_INT_AIE BIT(2) #define PCF2131_BIT_INT_WD_CD BIT(3) #define PCF2131_BIT_INT_SI BIT(4) #define PCF2131_BIT_INT_MI BIT(5) #define PCF2131_CTRL2_IRQ_MASK ( \ PCF2127_BIT_CTRL2_AF | \ PCF2127_BIT_CTRL2_WDTF) #define PCF2131_CTRL4_IRQ_MASK ( \ PCF2131_BIT_CTRL4_TSF4 | \ PCF2131_BIT_CTRL4_TSF3 | \ PCF2131_BIT_CTRL4_TSF2 | \ PCF2131_BIT_CTRL4_TSF1) enum pcf21xx_type { PCF2127, PCF2129, PCF2131, PCF21XX_LAST_ID }; struct pcf21xx_ts_config { u8 reg_base; /* Base register to read timestamp values. */ /* * If the TS input pin is driven to GND, an interrupt can be generated * (supported by all variants). */ u8 gnd_detect_reg; /* Interrupt control register address. */ u8 gnd_detect_bit; /* Interrupt bit. */ /* * If the TS input pin is driven to an intermediate level between GND * and supply, an interrupt can be generated (optional feature depending * on variant). */ u8 inter_detect_reg; /* Interrupt control register address. */ u8 inter_detect_bit; /* Interrupt bit. */ u8 ie_reg; /* Interrupt enable control register. */ u8 ie_bit; /* Interrupt enable bit. */ }; struct pcf21xx_config { int type; /* IC variant */ int max_register; unsigned int has_nvmem:1; unsigned int has_bit_wd_ctl_cd0:1; unsigned int wd_val_reg_readable:1; /* If watchdog value register can be read. */ unsigned int has_int_a_b:1; /* PCF2131 supports two interrupt outputs. */ u8 reg_time_base; /* Time/date base register. */ u8 regs_alarm_base; /* Alarm function base registers. */ u8 reg_wd_ctl; /* Watchdog control register. */ u8 reg_wd_val; /* Watchdog value register. */ u8 reg_clkout; /* Clkout register. */ int wdd_clock_hz_x1000; /* Watchdog clock in Hz multiplicated by 1000 */ int wdd_min_hw_heartbeat_ms; unsigned int ts_count; struct pcf21xx_ts_config ts[PCF2127_MAX_TS_SUPPORTED]; struct attribute_group attribute_group; }; struct pcf2127 { struct rtc_device *rtc; struct watchdog_device wdd; struct regmap *regmap; const struct pcf21xx_config *cfg; bool irq_enabled; time64_t ts[PCF2127_MAX_TS_SUPPORTED]; /* Timestamp values. */ bool ts_valid[PCF2127_MAX_TS_SUPPORTED]; /* Timestamp valid indication. */ }; /* * In the routines that deal directly with the pcf2127 hardware, we use * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. */ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct pcf2127 *pcf2127 = dev_get_drvdata(dev); unsigned char buf[7]; int ret; /* * Avoid reading CTRL2 register as it causes WD_VAL register * value to reset to 0 which means watchdog is stopped. */ ret = regmap_bulk_read(pcf2127->regmap, pcf2127->cfg->reg_time_base, buf, sizeof(buf)); if (ret) { dev_err(dev, "%s: read error\n", __func__); return ret; } /* Clock integrity is not guaranteed when OSF flag is set. */ if (buf[0] & PCF2127_BIT_SC_OSF) { /* * no need clear the flag here, * it will be cleared once the new date is saved */ dev_warn(dev, "oscillator stop detected, date/time is not reliable\n"); return -EINVAL; } dev_dbg(dev, "%s: raw data is sec=%02x, min=%02x, hr=%02x, " "mday=%02x, wday=%02x, mon=%02x, year=%02x\n", __func__, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); tm->tm_sec = bcd2bin(buf[0] & 0x7F); tm->tm_min = bcd2bin(buf[1] & 0x7F); tm->tm_hour = bcd2bin(buf[2] & 0x3F); tm->tm_mday = bcd2bin(buf[3] & 0x3F); tm->tm_wday = buf[4] & 0x07; tm->tm_mon = bcd2bin(buf[5] & 0x1F) - 1; tm->tm_year = bcd2bin(buf[6]); tm->tm_year += 100; dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); return 0; } static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct pcf2127 *pcf2127 = dev_get_drvdata(dev); unsigned char buf[7]; int i = 0, err; dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); /* hours, minutes and seconds */ buf[i++] = bin2bcd(tm->tm_sec); /* this will also clear OSF flag */ buf[i++] = bin2bcd(tm->tm_min); buf[i++] = bin2bcd(tm->tm_hour); buf[i++] = bin2bcd(tm->tm_mday); buf[i++] = tm->tm_wday & 0x07; /* month, 1 - 12 */ buf[i++] = bin2bcd(tm->tm_mon + 1); /* year */ buf[i++] = bin2bcd(tm->tm_year - 100); /* Write access to time registers: * PCF2127/29: no special action required. * PCF2131: requires setting the STOP and CPR bits. STOP bit needs to * be cleared after time registers are updated. */ if (pcf2127->cfg->type == PCF2131) { err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, PCF2127_BIT_CTRL1_STOP, PCF2127_BIT_CTRL1_STOP); if (err) { dev_dbg(dev, "setting STOP bit failed\n"); return err; } err = regmap_write(pcf2127->regmap, PCF2131_REG_SR_RESET, PCF2131_SR_RESET_CPR_CMD); if (err) { dev_dbg(dev, "sending CPR cmd failed\n"); return err; } } /* write time register's data */ err = regmap_bulk_write(pcf2127->regmap, pcf2127->cfg->reg_time_base, buf, i); if (err) { dev_dbg(dev, "%s: err=%d", __func__, err); return err; } if (pcf2127->cfg->type == PCF2131) { /* Clear STOP bit (PCF2131 only) after write is completed. */ err = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, PCF2127_BIT_CTRL1_STOP, 0); if (err) { dev_dbg(dev, "clearing STOP bit failed\n"); return err; } } return 0; } static int pcf2127_param_get(struct device *dev, struct rtc_param *param) { struct pcf2127 *pcf2127 = dev_get_drvdata(dev); u32 value; int ret; switch (param->param) { case RTC_PARAM_BACKUP_SWITCH_MODE: ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &value); if (ret < 0) return ret; value = FIELD_GET(PCF2127_CTRL3_PM, value); if (value < 0x3) param->uvalue = RTC_BSM_LEVEL; else if (value < 0x6) param->uvalue = RTC_BSM_DIRECT; else param->uvalue = RTC_BSM_DISABLED; break; default: return -EINVAL; } return 0; } static int pcf2127_param_set(struct device *dev, struct rtc_param *param) { struct pcf2127 *pcf2127 = dev_get_drvdata(dev); u8 mode = 0; u32 value; int ret; switch (param->param) { case RTC_PARAM_BACKUP_SWITCH_MODE: ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &value); if (ret < 0) return ret; value = FIELD_GET(PCF2127_CTRL3_PM, value); if (value > 5) value -= 5; else if (value > 2) value -= 3; switch (param->uvalue) { case RTC_BSM_LEVEL: break; case RTC_BSM_DIRECT: mode = 3; break; case RTC_BSM_DISABLED: if (value == 0) value = 1; mode = 5; break; default: return -EINVAL; } return regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3, PCF2127_CTRL3_PM, FIELD_PREP(PCF2127_CTRL3_PM, mode + value)); break; default: return -EINVAL; } return 0; } static int pcf2127_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { struct pcf2127 *pcf2127 = dev_get_drvdata(dev); int val, touser = 0; int ret; switch (cmd) { case RTC_VL_READ: ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &val); if (ret) return ret; if (val & PCF2127_BIT_CTRL3_BLF) touser |= RTC_VL_BACKUP_LOW; if (val & PCF2127_BIT_CTRL3_BF) touser |= RTC_VL_BACKUP_SWITCH; return put_user(touser, (unsigned int __user *)arg); case RTC_VL_CLR: return regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3, PCF2127_BIT_CTRL3_BF, 0); default: return -ENOIOCTLCMD; } } static int pcf2127_nvmem_read(void *priv, unsigned int offset, void *val, size_t bytes) { struct pcf2127 *pcf2127 = priv; int ret; unsigned char offsetbuf[] = { offset >> 8, offset }; ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_ADDR_MSB, offsetbuf, 2); if (ret) return ret; return regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_RD_CMD, val, bytes); } static int pcf2127_nvmem_write(void *priv, unsigned int offset, void *val, size_t bytes) { struct pcf2127 *pcf2127 = priv; int ret; unsigned char offsetbuf[] = { offset >> 8, offset }; ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_ADDR_MSB, offsetbuf, 2); if (ret) return ret; return regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_WRT_CMD, val, bytes); } /* watchdog driver */ static int pcf2127_wdt_ping(struct watchdog_device *wdd) { int wd_val; struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd); /* * Compute counter value of WATCHDG_TIM_VAL to obtain desired period * in seconds, depending on the source clock frequency. */ wd_val = ((wdd->timeout * pcf2127->cfg->wdd_clock_hz_x1000) / 1000) + 1; return regmap_write(pcf2127->regmap, pcf2127->cfg->reg_wd_val, wd_val); } /* * Restart watchdog timer if feature is active. * * Note: Reading CTRL2 register causes watchdog to stop which is unfortunate, * since register also contain control/status flags for other features. * Always call this function after reading CTRL2 register. */