diff options
Diffstat (limited to 'drivers/rtc/rtc-pcf2127.c')
-rw-r--r-- | drivers/rtc/rtc-pcf2127.c | 46 |
1 files changed, 35 insertions, 11 deletions
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index 39a7b5116aa4..d13c20a2adf7 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -26,6 +26,7 @@ /* Control register 1 */ #define PCF2127_REG_CTRL1 0x00 +#define PCF2127_BIT_CTRL1_POR_OVRD BIT(3) #define PCF2127_BIT_CTRL1_TSF1 BIT(4) /* Control register 2 */ #define PCF2127_REG_CTRL2 0x01 @@ -57,6 +58,9 @@ #define PCF2127_REG_ALARM_DM 0x0D #define PCF2127_REG_ALARM_DW 0x0E #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) @@ -225,12 +229,6 @@ static int pcf2127_rtc_ioctl(struct device *dev, } } -static const struct rtc_class_ops pcf2127_rtc_ops = { - .ioctl = pcf2127_rtc_ioctl, - .read_time = pcf2127_rtc_read_time, - .set_time = pcf2127_rtc_set_time, -}; - static int pcf2127_nvmem_read(void *priv, unsigned int offset, void *val, size_t bytes) { @@ -459,7 +457,7 @@ static irqreturn_t pcf2127_rtc_irq(int irq, void *dev) return IRQ_HANDLED; } -static const struct rtc_class_ops pcf2127_rtc_alrm_ops = { +static const struct rtc_class_ops pcf2127_rtc_ops = { .ioctl = pcf2127_rtc_ioctl, .read_time = pcf2127_rtc_read_time, .set_time = pcf2127_rtc_set_time, @@ -560,10 +558,11 @@ static const struct attribute_group pcf2127_attr_group = { }; static int pcf2127_probe(struct device *dev, struct regmap *regmap, - int alarm_irq, const char *name, bool has_nvmem) + int alarm_irq, const char *name, bool is_pcf2127) { struct pcf2127 *pcf2127; int ret = 0; + unsigned int val; dev_dbg(dev, "%s\n", __func__); @@ -584,6 +583,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap, pcf2127->rtc->range_max = RTC_TIMESTAMP_END_2099; pcf2127->rtc->set_start_time = true; /* Sets actual start to 1970 */ pcf2127->rtc->uie_unsupported = 1; + clear_bit(RTC_FEATURE_ALARM, pcf2127->rtc->features); if (alarm_irq > 0) { ret = devm_request_threaded_irq(dev, alarm_irq, NULL, @@ -598,10 +598,10 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap, if (alarm_irq > 0 || device_property_read_bool(dev, "wakeup-source")) { device_init_wakeup(dev, true); - pcf2127->rtc->ops = &pcf2127_rtc_alrm_ops; + set_bit(RTC_FEATURE_ALARM, pcf2127->rtc->features); } - if (has_nvmem) { + if (is_pcf2127) { struct nvmem_config nvmem_cfg = { .priv = pcf2127, .reg_read = pcf2127_nvmem_read, @@ -613,9 +613,33 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap, } /* + * The "Power-On Reset Override" facility prevents the RTC to do a reset + * after power on. For normal operation the PORO must be disabled. + */ + regmap_clear_bits(pcf2127->regmap, PCF2127_REG_CTRL1, + PCF2127_BIT_CTRL1_POR_OVRD); + + ret = regmap_read(pcf2127->regmap, PCF2127_REG_CLKOUT, &val); + if (ret < 0) + return ret; + + if (!(val & PCF2127_BIT_CLKOUT_OTPR)) { + ret = regmap_set_bits(pcf2127->regmap, PCF2127_REG_CLKOUT, + PCF2127_BIT_CLKOUT_OTPR); + if (ret < 0) + return ret; + + msleep(100); + } + + /* * Watchdog timer enabled and reset pin /RST activated when timed out. * Select 1Hz clock source for watchdog timer. * Note: Countdown timer disabled and not available. + * For pca2129, pcf2129, only bit[7] is for Symbol WD_CD + * of register watchdg_tim_ctl. The bit[6] is labeled + * as T. Bits labeled as T must always be written with + * logic 0. */ ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_WD_CTL, PCF2127_BIT_WD_CTL_CD1 | @@ -623,7 +647,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap, PCF2127_BIT_WD_CTL_TF1 | PCF2127_BIT_WD_CTL_TF0, PCF2127_BIT_WD_CTL_CD1 | - PCF2127_BIT_WD_CTL_CD0 | + (is_pcf2127 ? PCF2127_BIT_WD_CTL_CD0 : 0) | PCF2127_BIT_WD_CTL_TF1); if (ret) { dev_err(dev, "%s: watchdog config (wd_ctl) failed\n", __func__); |