aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-ab-b5ze-s3.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-ab-b5ze-s3.c')
-rw-r--r--drivers/rtc/rtc-ab-b5ze-s3.c189
1 files changed, 63 insertions, 126 deletions
diff --git a/drivers/rtc/rtc-ab-b5ze-s3.c b/drivers/rtc/rtc-ab-b5ze-s3.c
index 2233601761ac..cdad6f00debf 100644
--- a/drivers/rtc/rtc-ab-b5ze-s3.c
+++ b/drivers/rtc/rtc-ab-b5ze-s3.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* rtc-ab-b5ze-s3 - Driver for Abracon AB-RTCMC-32.768Khz-B5ZE-S3
* I2C RTC / Alarm chip
@@ -10,19 +11,9 @@
*
* This work is based on ISL12057 driver (drivers/rtc/rtc-isl12057.c).
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <linux/module.h>
-#include <linux/mutex.h>
#include <linux/rtc.h>
#include <linux/i2c.h>
#include <linux/bcd.h>
@@ -128,7 +119,6 @@
struct abb5zes3_rtc_data {
struct rtc_device *rtc;
struct regmap *regmap;
- struct mutex lock;
int irq;
@@ -138,8 +128,7 @@ struct abb5zes3_rtc_data {
/*
* Try and match register bits w/ fixed null values to see whether we
- * are dealing with an ABB5ZES3. Note: this function is called early
- * during init and hence does need mutex protection.
+ * are dealing with an ABB5ZES3.
*/
static int abb5zes3_i2c_validate_chip(struct regmap *regmap)
{
@@ -230,14 +219,12 @@ static int _abb5zes3_rtc_read_time(struct device *dev, struct rtc_time *tm)
if (ret) {
dev_err(dev, "%s: reading RTC time failed (%d)\n",
__func__, ret);
- goto err;
+ return ret;
}
/* If clock integrity is not guaranteed, do not return a time value */
- if (regs[ABB5ZES3_REG_RTC_SC] & ABB5ZES3_REG_RTC_SC_OSC) {
- ret = -ENODATA;
- goto err;
- }
+ if (regs[ABB5ZES3_REG_RTC_SC] & ABB5ZES3_REG_RTC_SC_OSC)
+ return -ENODATA;
tm->tm_sec = bcd2bin(regs[ABB5ZES3_REG_RTC_SC] & 0x7F);
tm->tm_min = bcd2bin(regs[ABB5ZES3_REG_RTC_MN]);
@@ -255,7 +242,6 @@ static int _abb5zes3_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_mon = bcd2bin(regs[ABB5ZES3_REG_RTC_MO]) - 1; /* starts at 1 */
tm->tm_year = bcd2bin(regs[ABB5ZES3_REG_RTC_YR]) + 100;
-err:
return ret;
}
@@ -273,12 +259,9 @@ static int abb5zes3_rtc_set_time(struct device *dev, struct rtc_time *tm)
regs[ABB5ZES3_REG_RTC_MO] = bin2bcd(tm->tm_mon + 1);
regs[ABB5ZES3_REG_RTC_YR] = bin2bcd(tm->tm_year - 100);
- mutex_lock(&data->lock);
ret = regmap_bulk_write(data->regmap, ABB5ZES3_REG_RTC_SC,
regs + ABB5ZES3_REG_RTC_SC,
ABB5ZES3_RTC_SEC_LEN);
- mutex_unlock(&data->lock);
-
return ret;
}
@@ -332,38 +315,35 @@ static int _abb5zes3_rtc_read_timer(struct device *dev,
if (ret) {
dev_err(dev, "%s: reading Timer A section failed (%d)\n",
__func__, ret);
- goto err;
+ return ret;
}
/* get current time ... */
ret = _abb5zes3_rtc_read_time(dev, &rtc_tm);
if (ret)
- goto err;
+ return ret;
/* ... convert to seconds ... */
- ret = rtc_tm_to_time(&rtc_tm, &rtc_secs);
- if (ret)
- goto err;
+ rtc_secs = rtc_tm_to_time64(&rtc_tm);
/* ... add remaining timer A time ... */
ret = sec_from_timer_a(&timer_secs, regs[1], regs[2]);
if (ret)
- goto err;
+ return ret;
/* ... and convert back. */
- rtc_time_to_tm(rtc_secs + timer_secs, alarm_tm);
+ rtc_time64_to_tm(rtc_secs + timer_secs, alarm_tm);
ret = regmap_read(data->regmap, ABB5ZES3_REG_CTRL2, &reg);
if (ret) {
dev_err(dev, "%s: reading ctrl reg failed (%d)\n",
__func__, ret);
- goto err;
+ return ret;
}
alarm->enabled = !!(reg & ABB5ZES3_REG_CTRL2_WTAIE);
-err:
- return ret;
+ return 0;
}
/* Read alarm currently configured via a RTC alarm registers. */
@@ -382,7 +362,7 @@ static int _abb5zes3_rtc_read_alarm(struct device *dev,
if (ret) {
dev_err(dev, "%s: reading alarm section failed (%d)\n",
__func__, ret);
- goto err;
+ return ret;
}
alarm_tm->tm_sec = 0;
@@ -398,18 +378,13 @@ static int _abb5zes3_rtc_read_alarm(struct device *dev,
*/
ret = _abb5zes3_rtc_read_time(dev, &rtc_tm);
if (ret)
- goto err;
+ return ret;
alarm_tm->tm_year = rtc_tm.tm_year;
alarm_tm->tm_mon = rtc_tm.tm_mon;
- ret = rtc_tm_to_time(&rtc_tm, &rtc_secs);
- if (ret)
- goto err;
-
- ret = rtc_tm_to_time(alarm_tm, &alarm_secs);
- if (ret)
- goto err;
+ rtc_secs = rtc_tm_to_time64(&rtc_tm);
+ alarm_secs = rtc_tm_to_time64(alarm_tm);
if (alarm_secs < rtc_secs) {
if (alarm_tm->tm_mon == 11) {
@@ -424,13 +399,12 @@ static int _abb5zes3_rtc_read_alarm(struct device *dev,
if (ret) {
dev_err(dev, "%s: reading ctrl reg failed (%d)\n",
__func__, ret);
- goto err;
+ return ret;
}
alarm->enabled = !!(reg & ABB5ZES3_REG_CTRL1_AIE);
-err:
- return ret;
+ return 0;
}
/*
@@ -447,12 +421,10 @@ static int abb5zes3_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
struct abb5zes3_rtc_data *data = dev_get_drvdata(dev);
int ret;
- mutex_lock(&data->lock);
if (data->timer_alarm)
ret = _abb5zes3_rtc_read_timer(dev, alarm);
else
ret = _abb5zes3_rtc_read_alarm(dev, alarm);
- mutex_unlock(&data->lock);
return ret;
}
@@ -466,33 +438,25 @@ static int _abb5zes3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
struct abb5zes3_rtc_data *data = dev_get_drvdata(dev);
struct rtc_time *alarm_tm = &alarm->time;
- unsigned long rtc_secs, alarm_secs;
u8 regs[ABB5ZES3_ALRM_SEC_LEN];
struct rtc_time rtc_tm;
int ret, enable = 1;
- ret = _abb5zes3_rtc_read_time(dev, &rtc_tm);
- if (ret)
- goto err;
-
- ret = rtc_tm_to_time(&rtc_tm, &rtc_secs);
- if (ret)
- goto err;
-
- ret = rtc_tm_to_time(alarm_tm, &alarm_secs);
- if (ret)
- goto err;
-
- /* If alarm time is before current time, disable the alarm */
- if (!alarm->enabled || alarm_secs <= rtc_secs) {
+ if (!alarm->enabled) {
enable = 0;
} else {
+ unsigned long rtc_secs, alarm_secs;
+
/*
* Chip only support alarms up to one month in the future. Let's
* return an error if we get something after that limit.
* Comparison is done by incrementing rtc_tm month field by one
* and checking alarm value is still below.
*/
+ ret = _abb5zes3_rtc_read_time(dev, &rtc_tm);
+ if (ret)
+ return ret;
+
if (rtc_tm.tm_mon == 11) { /* handle year wrapping */
rtc_tm.tm_mon = 0;
rtc_tm.tm_year += 1;
@@ -500,15 +464,13 @@ static int _abb5zes3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
rtc_tm.tm_mon += 1;
}
- ret = rtc_tm_to_time(&rtc_tm, &rtc_secs);
- if (ret)
- goto err;
+ rtc_secs = rtc_tm_to_time64(&rtc_tm);
+ alarm_secs = rtc_tm_to_time64(alarm_tm);
if (alarm_secs > rtc_secs) {
- dev_err(dev, "%s: alarm maximum is one month in the "
- "future (%d)\n", __func__, ret);
- ret = -EINVAL;
- goto err;
+ dev_err(dev, "%s: alarm maximum is one month in the future (%d)\n",
+ __func__, ret);
+ return -EINVAL;
}
}
@@ -526,17 +488,14 @@ static int _abb5zes3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
if (ret < 0) {
dev_err(dev, "%s: writing ALARM section failed (%d)\n",
__func__, ret);
- goto err;
+ return ret;
}
/* Record currently configured alarm is not a timer */
data->timer_alarm = 0;
/* Enable or disable alarm interrupt generation */
- ret = _abb5zes3_rtc_update_alarm(dev, enable);
-
-err:
- return ret;
+ return _abb5zes3_rtc_update_alarm(dev, enable);
}
/*
@@ -557,7 +516,7 @@ static int _abb5zes3_rtc_set_timer(struct device *dev, struct rtc_wkalrm *alarm,
ABB5ZES3_TIMA_SEC_LEN);
if (ret < 0) {
dev_err(dev, "%s: writing timer section failed\n", __func__);
- goto err;
+ return ret;
}
/* Configure Timer A as a watchdog timer */
@@ -570,10 +529,7 @@ static int _abb5zes3_rtc_set_timer(struct device *dev, struct rtc_wkalrm *alarm,
data->timer_alarm = 1;
/* Enable or disable timer interrupt generation */
- ret = _abb5zes3_rtc_update_timer(dev, alarm->enabled);
-
-err:
- return ret;
+ return _abb5zes3_rtc_update_timer(dev, alarm->enabled);
}
/*
@@ -590,31 +546,25 @@ static int abb5zes3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
struct rtc_time rtc_tm;
int ret;
- mutex_lock(&data->lock);
ret = _abb5zes3_rtc_read_time(dev, &rtc_tm);
if (ret)
- goto err;
+ return ret;
- ret = rtc_tm_to_time(&rtc_tm, &rtc_secs);
- if (ret)
- goto err;
-
- ret = rtc_tm_to_time(alarm_tm, &alarm_secs);
- if (ret)
- goto err;
+ rtc_secs = rtc_tm_to_time64(&rtc_tm);
+ alarm_secs = rtc_tm_to_time64(alarm_tm);
/* Let's first disable both the alarm and the timer interrupts */
ret = _abb5zes3_rtc_update_alarm(dev, false);
if (ret < 0) {
dev_err(dev, "%s: unable to disable alarm (%d)\n", __func__,
ret);
- goto err;
+ return ret;
}
ret = _abb5zes3_rtc_update_timer(dev, false);
if (ret < 0) {
dev_err(dev, "%s: unable to disable timer (%d)\n", __func__,
ret);
- goto err;
+ return ret;
}
data->timer_alarm = 0;
@@ -629,9 +579,6 @@ static int abb5zes3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
else
ret = _abb5zes3_rtc_set_alarm(dev, alarm);
- err:
- mutex_unlock(&data->lock);
-
if (ret)
dev_err(dev, "%s: unable to configure alarm (%d)\n", __func__,
ret);
@@ -650,8 +597,7 @@ static inline int _abb5zes3_rtc_battery_low_irq_enable(struct regmap *regmap,
/*
* Check current RTC status and enable/disable what needs to be. Return 0 if
- * everything went ok and a negative value upon error. Note: this function
- * is called early during init and hence does need mutex protection.
+ * everything went ok and a negative value upon error.
*/
static int abb5zes3_rtc_check_setup(struct device *dev)
{
@@ -675,8 +621,9 @@ static int abb5zes3_rtc_check_setup(struct device *dev)
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);
+ 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);
@@ -729,9 +676,9 @@ static int abb5zes3_rtc_check_setup(struct device *dev)
* 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);
+ 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",
@@ -748,10 +695,8 @@ static int abb5zes3_rtc_check_setup(struct device *dev)
}
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");
+ 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");
}
/*
@@ -769,13 +714,12 @@ static int abb5zes3_rtc_check_setup(struct device *dev)
data->battery_low = reg & ABB5ZES3_REG_CTRL3_BLF;
if (data->battery_low) {
- dev_err(dev, "RTC battery is low; please, consider "
- "changing it!\n");
+ 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);
+ dev_err(dev, "%s: disabling battery low interrupt generation failed (%d)\n",
+ __func__, ret);
}
return ret;
@@ -788,12 +732,10 @@ static int abb5zes3_rtc_alarm_irq_enable(struct device *dev,
int ret = 0;
if (rtc_data->irq) {
- mutex_lock(&rtc_data->lock);
if (rtc_data->timer_alarm)
ret = _abb5zes3_rtc_update_timer(dev, enable);
else
ret = _abb5zes3_rtc_update_alarm(dev, enable);
- mutex_unlock(&rtc_data->lock);
}
return ret;
@@ -885,49 +827,44 @@ static int abb5zes3_probe(struct i2c_client *client,
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
I2C_FUNC_SMBUS_BYTE_DATA |
- I2C_FUNC_SMBUS_I2C_BLOCK)) {
- ret = -ENODEV;
- goto err;
- }
+ I2C_FUNC_SMBUS_I2C_BLOCK))
+ return -ENODEV;
regmap = devm_regmap_init_i2c(client, &abb5zes3_rtc_regmap_config);
if (IS_ERR(regmap)) {
ret = PTR_ERR(regmap);
dev_err(dev, "%s: regmap allocation failed: %d\n",
__func__, ret);
- goto err;
+ return ret;
}
ret = abb5zes3_i2c_validate_chip(regmap);
if (ret)
- goto err;
+ return ret;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
- if (!data) {
- ret = -ENOMEM;
- goto err;
- }
+ if (!data)
+ return -ENOMEM;
- mutex_init(&data->lock);
data->regmap = regmap;
dev_set_drvdata(dev, data);
ret = abb5zes3_rtc_check_setup(dev);
if (ret)
- goto err;
+ return ret;
data->rtc = devm_rtc_allocate_device(dev);
ret = PTR_ERR_OR_ZERO(data->rtc);
if (ret) {
dev_err(dev, "%s: unable to allocate RTC device (%d)\n",
__func__, ret);
- goto err;
+ return ret;
}
if (client->irq > 0) {
ret = devm_request_threaded_irq(dev, client->irq, NULL,
_abb5zes3_rtc_interrupt,
- IRQF_SHARED|IRQF_ONESHOT,
+ IRQF_SHARED | IRQF_ONESHOT,
DRV_NAME, client);
if (!ret) {
device_init_wakeup(dev, true);
@@ -949,8 +886,8 @@ static int abb5zes3_probe(struct i2c_client *client,
if (!data->battery_low && data->irq) {
ret = _abb5zes3_rtc_battery_low_irq_enable(regmap, true);
if (ret) {
- dev_err(dev, "%s: enabling battery low interrupt "
- "generation failed (%d)\n", __func__, ret);
+ dev_err(dev, "%s: enabling battery low interrupt generation failed (%d)\n",
+ __func__, ret);
goto err;
}
}
@@ -958,7 +895,7 @@ static int abb5zes3_probe(struct i2c_client *client,
ret = rtc_register_device(data->rtc);
err:
- if (ret && data && data->irq)
+ if (ret && data->irq)
device_init_wakeup(dev, false);
return ret;
}