diff options
author | Alexander Shiyan <shc_work@mail.ru> | 2014-04-03 17:50:00 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-03 19:21:21 -0400 |
commit | 12de362108d5ec24cce1bbe520570dc8fdccca9c (patch) | |
tree | 04de7d96005b26d239f376e587f8d3526d8e34c7 /drivers/rtc | |
parent | fb1bd9a22da3d0f2436ffa95fdc0382b89659288 (diff) |
rtc: mc13xxx: change RTC validation scheme
Datasheet says: "When the VSRTC voltage drops to the range of 0.9 - 0.8V,
the RTCPORB reset signal is generated and the contents of the RTC will
be reset. <skip>. To inform the processor that the contents of the RTC
are no longer valid due to the reset, a timer reset interrupt function
is implemented with the RTCRSTI bit." This patch makes the RTC valid by
default until RTCRST interrupt occurs.
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Cc: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Cc: Sascha Hauer <kernel@pengutronix.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-mc13xxx.c | 32 |
1 files changed, 14 insertions, 18 deletions
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c index 0d60dd5273d1..7b39852eb542 100644 --- a/drivers/rtc/rtc-mc13xxx.c +++ b/drivers/rtc/rtc-mc13xxx.c | |||
@@ -64,12 +64,10 @@ static int mc13xxx_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
64 | unsigned long s1970; | 64 | unsigned long s1970; |
65 | int ret; | 65 | int ret; |
66 | 66 | ||
67 | mc13xxx_lock(priv->mc13xxx); | 67 | if (!priv->valid) |
68 | return -ENODATA; | ||
68 | 69 | ||
69 | if (!priv->valid) { | 70 | mc13xxx_lock(priv->mc13xxx); |
70 | ret = -ENODATA; | ||
71 | goto out; | ||
72 | } | ||
73 | 71 | ||
74 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days1); | 72 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days1); |
75 | if (unlikely(ret)) | 73 | if (unlikely(ret)) |
@@ -154,11 +152,14 @@ static int mc13xxx_rtc_set_mmss(struct device *dev, unsigned long secs) | |||
154 | goto out; | 152 | goto out; |
155 | } | 153 | } |
156 | 154 | ||
157 | ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_RTCRST); | 155 | if (!priv->valid) { |
158 | if (unlikely(ret)) | 156 | ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_RTCRST); |
159 | goto out; | 157 | if (unlikely(ret)) |
158 | goto out; | ||
159 | |||
160 | ret = mc13xxx_irq_unmask(priv->mc13xxx, MC13XXX_IRQ_RTCRST); | ||
161 | } | ||
160 | 162 | ||
161 | ret = mc13xxx_irq_unmask(priv->mc13xxx, MC13XXX_IRQ_RTCRST); | ||
162 | out: | 163 | out: |
163 | priv->valid = !ret; | 164 | priv->valid = !ret; |
164 | 165 | ||
@@ -295,7 +296,7 @@ static irqreturn_t mc13xxx_rtc_reset_handler(int irq, void *dev) | |||
295 | struct mc13xxx_rtc *priv = dev; | 296 | struct mc13xxx_rtc *priv = dev; |
296 | struct mc13xxx *mc13xxx = priv->mc13xxx; | 297 | struct mc13xxx *mc13xxx = priv->mc13xxx; |
297 | 298 | ||
298 | dev_dbg(&priv->rtc->dev, "RTCRST\n"); | 299 | dev_warn(&priv->rtc->dev, "Contents of the RTC are no longer valid\n"); |
299 | priv->valid = 0; | 300 | priv->valid = 0; |
300 | 301 | ||
301 | mc13xxx_irq_mask(mc13xxx, irq); | 302 | mc13xxx_irq_mask(mc13xxx, irq); |
@@ -308,7 +309,6 @@ static int __init mc13xxx_rtc_probe(struct platform_device *pdev) | |||
308 | int ret; | 309 | int ret; |
309 | struct mc13xxx_rtc *priv; | 310 | struct mc13xxx_rtc *priv; |
310 | struct mc13xxx *mc13xxx; | 311 | struct mc13xxx *mc13xxx; |
311 | int rtcrst_pending; | ||
312 | 312 | ||
313 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | 313 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); |
314 | if (!priv) | 314 | if (!priv) |
@@ -316,6 +316,7 @@ static int __init mc13xxx_rtc_probe(struct platform_device *pdev) | |||
316 | 316 | ||
317 | mc13xxx = dev_get_drvdata(pdev->dev.parent); | 317 | mc13xxx = dev_get_drvdata(pdev->dev.parent); |
318 | priv->mc13xxx = mc13xxx; | 318 | priv->mc13xxx = mc13xxx; |
319 | priv->valid = 1; | ||
319 | 320 | ||
320 | platform_set_drvdata(pdev, priv); | 321 | platform_set_drvdata(pdev, priv); |
321 | 322 | ||
@@ -326,18 +327,13 @@ static int __init mc13xxx_rtc_probe(struct platform_device *pdev) | |||
326 | 327 | ||
327 | mc13xxx_lock(mc13xxx); | 328 | mc13xxx_lock(mc13xxx); |
328 | 329 | ||
330 | mc13xxx_irq_ack(mc13xxx, MC13XXX_IRQ_RTCRST); | ||
331 | |||
329 | ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_RTCRST, | 332 | ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_RTCRST, |
330 | mc13xxx_rtc_reset_handler, DRIVER_NAME, priv); | 333 | mc13xxx_rtc_reset_handler, DRIVER_NAME, priv); |
331 | if (ret) | 334 | if (ret) |
332 | goto err_reset_irq_request; | 335 | goto err_reset_irq_request; |
333 | 336 | ||
334 | ret = mc13xxx_irq_status(mc13xxx, MC13XXX_IRQ_RTCRST, | ||
335 | NULL, &rtcrst_pending); | ||
336 | if (ret) | ||
337 | goto err_reset_irq_status; | ||
338 | |||
339 | priv->valid = !rtcrst_pending; | ||
340 | |||
341 | ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_1HZ, | 337 | ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_1HZ, |
342 | mc13xxx_rtc_update_handler, DRIVER_NAME, priv); | 338 | mc13xxx_rtc_update_handler, DRIVER_NAME, priv); |
343 | if (ret) | 339 | if (ret) |