in rtc-pcf2127.c [633:785]
static int pcf2127_probe(struct device *dev, struct regmap *regmap,
int alarm_irq, const char *name, bool is_pcf2127)
{
struct pcf2127 *pcf2127;
int ret = 0;
unsigned int val;
dev_dbg(dev, "%s\n", __func__);
pcf2127 = devm_kzalloc(dev, sizeof(*pcf2127), GFP_KERNEL);
if (!pcf2127)
return -ENOMEM;
pcf2127->regmap = regmap;
dev_set_drvdata(dev, pcf2127);
pcf2127->rtc = devm_rtc_allocate_device(dev);
if (IS_ERR(pcf2127->rtc))
return PTR_ERR(pcf2127->rtc);
pcf2127->rtc->ops = &pcf2127_rtc_ops;
pcf2127->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
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,
pcf2127_rtc_irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
dev_name(dev), dev);
if (ret) {
dev_err(dev, "failed to request alarm irq\n");
return ret;
}
pcf2127->irq_enabled = true;
}
if (alarm_irq > 0 || device_property_read_bool(dev, "wakeup-source")) {
device_init_wakeup(dev, true);
set_bit(RTC_FEATURE_ALARM, pcf2127->rtc->features);
}
if (is_pcf2127) {
struct nvmem_config nvmem_cfg = {
.priv = pcf2127,
.reg_read = pcf2127_nvmem_read,
.reg_write = pcf2127_nvmem_write,
.size = 512,
};
ret = devm_rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg);
}
/*
* 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 |
PCF2127_BIT_WD_CTL_CD0 |
PCF2127_BIT_WD_CTL_TF1 |
PCF2127_BIT_WD_CTL_TF0,
PCF2127_BIT_WD_CTL_CD1 |
(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__);
return ret;
}
pcf2127_watchdog_init(dev, pcf2127);
/*
* Disable battery low/switch-over timestamp and interrupts.
* Clear battery interrupt flags which can block new trigger events.
* Note: This is the default chip behaviour but added to ensure
* correct tamper timestamp and interrupt function.
*/
ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3,
PCF2127_BIT_CTRL3_BTSE |
PCF2127_BIT_CTRL3_BIE |
PCF2127_BIT_CTRL3_BLIE, 0);
if (ret) {
dev_err(dev, "%s: interrupt config (ctrl3) failed\n",
__func__);
return ret;
}
/*
* Enable timestamp function and store timestamp of first trigger
* event until TSF1 and TFS2 interrupt flags are cleared.
*/
ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_TS_CTRL,
PCF2127_BIT_TS_CTRL_TSOFF |
PCF2127_BIT_TS_CTRL_TSM,
PCF2127_BIT_TS_CTRL_TSM);
if (ret) {
dev_err(dev, "%s: tamper detection config (ts_ctrl) failed\n",
__func__);
return ret;
}
/*
* Enable interrupt generation when TSF1 or TSF2 timestamp flags
* are set. Interrupt signal is an open-drain output and can be
* left floating if unused.
*/
ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
PCF2127_BIT_CTRL2_TSIE,
PCF2127_BIT_CTRL2_TSIE);
if (ret) {
dev_err(dev, "%s: tamper detection config (ctrl2) failed\n",
__func__);
return ret;
}
ret = rtc_add_group(pcf2127->rtc, &pcf2127_attr_group);
if (ret) {
dev_err(dev, "%s: tamper sysfs registering failed\n",
__func__);
return ret;
}
return devm_rtc_register_device(pcf2127->rtc);
}