summaryrefslogtreecommitdiff
path: root/drivers/rtc/rtc-pcf2127.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-pcf2127.c')
-rw-r--r--drivers/rtc/rtc-pcf2127.c46
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__);