in rtc-ab-b5ze-s3.c [602:726]
static int abb5zes3_rtc_check_setup(struct device *dev)
{
struct abb5zes3_rtc_data *data = dev_get_drvdata(dev);
struct regmap *regmap = data->regmap;
unsigned int reg;
int ret;
u8 mask;
/*
* By default, the devices generates a 32.768KHz signal on IRQ#1 pin. It
* is disabled here to prevent polluting the interrupt line and
* uselessly triggering the IRQ handler we install for alarm and battery
* low events. Note: this is done before clearing int. status below
* in this function.
* We also disable all timers and set timer interrupt to permanent (not
* pulsed).
*/
mask = (ABB5ZES3_REG_TIM_CLK_TBC | ABB5ZES3_REG_TIM_CLK_TAC0 |
ABB5ZES3_REG_TIM_CLK_TAC1 | ABB5ZES3_REG_TIM_CLK_COF0 |
ABB5ZES3_REG_TIM_CLK_COF1 | ABB5ZES3_REG_TIM_CLK_COF2 |
ABB5ZES3_REG_TIM_CLK_TBM | ABB5ZES3_REG_TIM_CLK_TAM);
ret = regmap_update_bits(regmap, ABB5ZES3_REG_TIM_CLK, mask,
ABB5ZES3_REG_TIM_CLK_COF0 |
ABB5ZES3_REG_TIM_CLK_COF1 |
ABB5ZES3_REG_TIM_CLK_COF2);
if (ret < 0) {
dev_err(dev, "%s: unable to initialize clkout register (%d)\n",
__func__, ret);
return ret;
}
/*
* Each component of the alarm (MN, HR, DT, DW) can be enabled/disabled
* individually by clearing/setting MSB of each associated register. So,
* we set all alarm enable bits to disable current alarm setting.
*/
mask = (ABB5ZES3_REG_ALRM_MN_AE | ABB5ZES3_REG_ALRM_HR_AE |
ABB5ZES3_REG_ALRM_DT_AE | ABB5ZES3_REG_ALRM_DW_AE);
ret = regmap_update_bits(regmap, ABB5ZES3_REG_CTRL2, mask, mask);
if (ret < 0) {
dev_err(dev, "%s: unable to disable alarm setting (%d)\n",
__func__, ret);
return ret;
}
/* Set Control 1 register (RTC enabled, 24hr mode, all int. disabled) */
mask = (ABB5ZES3_REG_CTRL1_CIE | ABB5ZES3_REG_CTRL1_AIE |
ABB5ZES3_REG_CTRL1_SIE | ABB5ZES3_REG_CTRL1_PM |
ABB5ZES3_REG_CTRL1_CAP | ABB5ZES3_REG_CTRL1_STOP);
ret = regmap_update_bits(regmap, ABB5ZES3_REG_CTRL1, mask, 0);
if (ret < 0) {
dev_err(dev, "%s: unable to initialize CTRL1 register (%d)\n",
__func__, ret);
return ret;
}
/*
* Set Control 2 register (timer int. disabled, alarm status cleared).
* WTAF is read-only and cleared automatically by reading the register.
*/
mask = (ABB5ZES3_REG_CTRL2_CTBIE | ABB5ZES3_REG_CTRL2_CTAIE |
ABB5ZES3_REG_CTRL2_WTAIE | ABB5ZES3_REG_CTRL2_AF |
ABB5ZES3_REG_CTRL2_SF | ABB5ZES3_REG_CTRL2_CTBF |
ABB5ZES3_REG_CTRL2_CTAF);
ret = regmap_update_bits(regmap, ABB5ZES3_REG_CTRL2, mask, 0);
if (ret < 0) {
dev_err(dev, "%s: unable to initialize CTRL2 register (%d)\n",
__func__, ret);
return ret;
}
/*
* Enable battery low detection function and battery switchover function
* (standard mode). Disable associated interrupts. Clear battery
* switchover flag but not battery low flag. The latter is checked
* later below.
*/
mask = (ABB5ZES3_REG_CTRL3_PM0 | ABB5ZES3_REG_CTRL3_PM1 |
ABB5ZES3_REG_CTRL3_PM2 | ABB5ZES3_REG_CTRL3_BLIE |
ABB5ZES3_REG_CTRL3_BSIE | ABB5ZES3_REG_CTRL3_BSF);
ret = regmap_update_bits(regmap, ABB5ZES3_REG_CTRL3, mask, 0);
if (ret < 0) {
dev_err(dev, "%s: unable to initialize CTRL3 register (%d)\n",
__func__, ret);
return ret;
}
/* Check oscillator integrity flag */
ret = regmap_read(regmap, ABB5ZES3_REG_RTC_SC, ®);
if (ret < 0) {
dev_err(dev, "%s: unable to read osc. integrity flag (%d)\n",
__func__, ret);
return ret;
}
if (reg & ABB5ZES3_REG_RTC_SC_OSC) {
dev_err(dev, "clock integrity not guaranteed. Osc. has stopped or has been interrupted.\n");
dev_err(dev, "change battery (if not already done) and then set time to reset osc. failure flag.\n");
}
/*
* Check battery low flag at startup: this allows reporting battery
* is low at startup when IRQ line is not connected. Note: we record
* current status to avoid reenabling this interrupt later in probe
* function if battery is low.
*/
ret = regmap_read(regmap, ABB5ZES3_REG_CTRL3, ®);
if (ret < 0) {
dev_err(dev, "%s: unable to read battery low flag (%d)\n",
__func__, ret);
return ret;
}
data->battery_low = reg & ABB5ZES3_REG_CTRL3_BLF;
if (data->battery_low) {
dev_err(dev, "RTC battery is low; please, consider changing it!\n");
ret = _abb5zes3_rtc_battery_low_irq_enable(regmap, false);
if (ret)
dev_err(dev, "%s: disabling battery low interrupt generation failed (%d)\n",
__func__, ret);
}
return ret;
}