summaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-mc13xxx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-mc13xxx.c')
-rw-r--r--drivers/rtc/rtc-mc13xxx.c139
1 files changed, 51 insertions, 88 deletions
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c
index 77ea9896b5ba..0765606a2d14 100644
--- a/drivers/rtc/rtc-mc13xxx.c
+++ b/drivers/rtc/rtc-mc13xxx.c
@@ -23,6 +23,8 @@
#define MC13XXX_RTCDAY 22
#define MC13XXX_RTCDAYA 23
+#define SEC_PER_DAY (24 * 60 * 60)
+
struct mc13xxx_rtc {
struct rtc_device *rtc;
struct mc13xxx *mc13xxx;
@@ -42,15 +44,15 @@ static int mc13xxx_rtc_irq_enable_unlocked(struct device *dev,
return func(priv->mc13xxx, irq);
}
-static int mc13xxx_rtc_irq_enable(struct device *dev,
- unsigned int enabled, int irq)
+static int mc13xxx_rtc_alarm_irq_enable(struct device *dev,
+ unsigned int enabled)
{
struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
int ret;
mc13xxx_lock(priv->mc13xxx);
- ret = mc13xxx_rtc_irq_enable_unlocked(dev, enabled, irq);
+ ret = mc13xxx_rtc_irq_enable_unlocked(dev, enabled, MC13XXX_IRQ_TODA);
mc13xxx_unlock(priv->mc13xxx);
@@ -61,44 +63,27 @@ static int mc13xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
unsigned int seconds, days1, days2;
- unsigned long s1970;
- int ret;
-
- mc13xxx_lock(priv->mc13xxx);
-
- if (!priv->valid) {
- ret = -ENODATA;
- goto out;
- }
- ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days1);
- if (unlikely(ret))
- goto out;
-
- ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTOD, &seconds);
- if (unlikely(ret))
- goto out;
-
- ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days2);
-out:
- mc13xxx_unlock(priv->mc13xxx);
+ if (!priv->valid)
+ return -ENODATA;
- if (ret)
- return ret;
+ do {
+ int ret;
- if (days2 == days1 + 1) {
- if (seconds >= 86400 / 2)
- days2 = days1;
- else
- days1 = days2;
- }
+ ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days1);
+ if (ret)
+ return ret;
- if (days1 != days2)
- return -EIO;
+ ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTOD, &seconds);
+ if (ret)
+ return ret;
- s1970 = days1 * 86400 + seconds;
+ ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days2);
+ if (ret)
+ return ret;
+ } while (days1 != days2);
- rtc_time_to_tm(s1970, tm);
+ rtc_time_to_tm(days1 * SEC_PER_DAY + seconds, tm);
return rtc_valid_tm(tm);
}
@@ -110,8 +95,8 @@ static int mc13xxx_rtc_set_mmss(struct device *dev, unsigned long secs)
unsigned int alarmseconds;
int ret;
- seconds = secs % 86400;
- days = secs / 86400;
+ seconds = secs % SEC_PER_DAY;
+ days = secs / SEC_PER_DAY;
mc13xxx_lock(priv->mc13xxx);
@@ -123,7 +108,7 @@ static int mc13xxx_rtc_set_mmss(struct device *dev, unsigned long secs)
if (unlikely(ret))
goto out;
- if (alarmseconds < 86400) {
+ if (alarmseconds < SEC_PER_DAY) {
ret = mc13xxx_reg_write(priv->mc13xxx,
MC13XXX_RTCTODA, 0x1ffff);
if (unlikely(ret))
@@ -147,18 +132,21 @@ static int mc13xxx_rtc_set_mmss(struct device *dev, unsigned long secs)
goto out;
/* restore alarm */
- if (alarmseconds < 86400) {
+ if (alarmseconds < SEC_PER_DAY) {
ret = mc13xxx_reg_write(priv->mc13xxx,
MC13XXX_RTCTODA, alarmseconds);
if (unlikely(ret))
goto out;
}
- ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_RTCRST);
- if (unlikely(ret))
- goto out;
+ if (!priv->valid) {
+ ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_RTCRST);
+ if (unlikely(ret))
+ goto out;
+
+ ret = mc13xxx_irq_unmask(priv->mc13xxx, MC13XXX_IRQ_RTCRST);
+ }
- ret = mc13xxx_irq_unmask(priv->mc13xxx, MC13XXX_IRQ_RTCRST);
out:
priv->valid = !ret;
@@ -180,7 +168,7 @@ static int mc13xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &seconds);
if (unlikely(ret))
goto out;
- if (seconds >= 86400) {
+ if (seconds >= SEC_PER_DAY) {
ret = -ENODATA;
goto out;
}
@@ -201,7 +189,7 @@ out:
alarm->enabled = enabled;
alarm->pending = pending;
- s1970 = days * 86400 + seconds;
+ s1970 = days * SEC_PER_DAY + seconds;
rtc_time_to_tm(s1970, &alarm->time);
dev_dbg(dev, "%s: %lu\n", __func__, s1970);
@@ -239,8 +227,8 @@ static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
if (unlikely(ret))
goto out;
- seconds = s1970 % 86400;
- days = s1970 / 86400;
+ seconds = s1970 % SEC_PER_DAY;
+ days = s1970 / SEC_PER_DAY;
ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAYA, days);
if (unlikely(ret))
@@ -259,8 +247,6 @@ static irqreturn_t mc13xxx_rtc_alarm_handler(int irq, void *dev)
struct mc13xxx_rtc *priv = dev;
struct mc13xxx *mc13xxx = priv->mc13xxx;
- dev_dbg(&priv->rtc->dev, "Alarm\n");
-
rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF);
mc13xxx_irq_ack(mc13xxx, irq);
@@ -273,8 +259,6 @@ static irqreturn_t mc13xxx_rtc_update_handler(int irq, void *dev)
struct mc13xxx_rtc *priv = dev;
struct mc13xxx *mc13xxx = priv->mc13xxx;
- dev_dbg(&priv->rtc->dev, "1HZ\n");
-
rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF);
mc13xxx_irq_ack(mc13xxx, irq);
@@ -282,12 +266,6 @@ static irqreturn_t mc13xxx_rtc_update_handler(int irq, void *dev)
return IRQ_HANDLED;
}
-static int mc13xxx_rtc_alarm_irq_enable(struct device *dev,
- unsigned int enabled)
-{
- return mc13xxx_rtc_irq_enable(dev, enabled, MC13XXX_IRQ_TODA);
-}
-
static const struct rtc_class_ops mc13xxx_rtc_ops = {
.read_time = mc13xxx_rtc_read_time,
.set_mmss = mc13xxx_rtc_set_mmss,
@@ -301,7 +279,6 @@ static irqreturn_t mc13xxx_rtc_reset_handler(int irq, void *dev)
struct mc13xxx_rtc *priv = dev;
struct mc13xxx *mc13xxx = priv->mc13xxx;
- dev_dbg(&priv->rtc->dev, "RTCRST\n");
priv->valid = 0;
mc13xxx_irq_mask(mc13xxx, irq);
@@ -314,7 +291,6 @@ static int __init mc13xxx_rtc_probe(struct platform_device *pdev)
int ret;
struct mc13xxx_rtc *priv;
struct mc13xxx *mc13xxx;
- int rtcrst_pending;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -322,60 +298,47 @@ static int __init mc13xxx_rtc_probe(struct platform_device *pdev)
mc13xxx = dev_get_drvdata(pdev->dev.parent);
priv->mc13xxx = mc13xxx;
+ priv->valid = 1;
platform_set_drvdata(pdev, priv);
mc13xxx_lock(mc13xxx);
+ mc13xxx_irq_ack(mc13xxx, MC13XXX_IRQ_RTCRST);
+
ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_RTCRST,
mc13xxx_rtc_reset_handler, DRIVER_NAME, priv);
if (ret)
- goto err_reset_irq_request;
-
- ret = mc13xxx_irq_status(mc13xxx, MC13XXX_IRQ_RTCRST,
- NULL, &rtcrst_pending);
- if (ret)
- goto err_reset_irq_status;
-
- priv->valid = !rtcrst_pending;
+ goto err_irq_request;
- ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_1HZ,
+ ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_1HZ,
mc13xxx_rtc_update_handler, DRIVER_NAME, priv);
if (ret)
- goto err_update_irq_request;
+ goto err_irq_request;
ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_TODA,
mc13xxx_rtc_alarm_handler, DRIVER_NAME, priv);
if (ret)
- goto err_alarm_irq_request;
+ goto err_irq_request;
mc13xxx_unlock(mc13xxx);
priv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
- &mc13xxx_rtc_ops, THIS_MODULE);
- if (IS_ERR(priv->rtc)) {
- ret = PTR_ERR(priv->rtc);
+ &mc13xxx_rtc_ops, THIS_MODULE);
- mc13xxx_lock(mc13xxx);
-
- mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_TODA, priv);
-err_alarm_irq_request:
-
- mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_1HZ, priv);
-err_update_irq_request:
-
-err_reset_irq_status:
+ return 0;
- mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv);
-err_reset_irq_request:
+err_irq_request:
+ mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_TODA, priv);
+ mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_1HZ, priv);
+ mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv);
- mc13xxx_unlock(mc13xxx);
- }
+ mc13xxx_unlock(mc13xxx);
return ret;
}
-static int __exit mc13xxx_rtc_remove(struct platform_device *pdev)
+static int mc13xxx_rtc_remove(struct platform_device *pdev)
{
struct mc13xxx_rtc *priv = platform_get_drvdata(pdev);
@@ -404,7 +367,7 @@ MODULE_DEVICE_TABLE(platform, mc13xxx_rtc_idtable);
static struct platform_driver mc13xxx_rtc_driver = {
.id_table = mc13xxx_rtc_idtable,
- .remove = __exit_p(mc13xxx_rtc_remove),
+ .remove = mc13xxx_rtc_remove,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,