aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorSanchayan Maity <maitysanchayan@gmail.com>2014-12-10 18:54:17 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-10 20:41:16 -0500
commit7f899399541060a2888cd99ec9f15abd643b4c54 (patch)
treee4227adab66dee9b2a019bad7e69224f7dbb32e0 /drivers/rtc
parent094d3ee3ce8c30756446518cc1895b6bbbca12ef (diff)
drivers/rtc/rtc-snvs: add clock support
Add clock enable and disable support for the SNVS peripheral, which is required for using the RTC within the SNVS block. The clock is not strictly enforced, as this would break the i.MX devices. The clocking for the i.MX devices seems to be enabled elsewhere and enabling RTC SNVS for Vybrid results in a crash. This patch adds the clock support but also makes it optional so Vybrid platform can use the clock if defined while making sure not to break i.MX. Signed-off-by: Sanchayan Maity <maitysanchayan@gmail.com> Cc: Shawn Guo <shawn.guo@linaro.org> Acked-by: Stefan Agner <stefan@agner.ch> Acked-by: Alessandro Zummo <a.zummo@towertech.it> 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-snvs.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
index fa384fe28988..d4a651268174 100644
--- a/drivers/rtc/rtc-snvs.c
+++ b/drivers/rtc/rtc-snvs.c
@@ -17,6 +17,7 @@
17#include <linux/of_device.h> 17#include <linux/of_device.h>
18#include <linux/platform_device.h> 18#include <linux/platform_device.h>
19#include <linux/rtc.h> 19#include <linux/rtc.h>
20#include <linux/clk.h>
20 21
21/* These register offsets are relative to LP (Low Power) range */ 22/* These register offsets are relative to LP (Low Power) range */
22#define SNVS_LPCR 0x04 23#define SNVS_LPCR 0x04
@@ -39,6 +40,7 @@ struct snvs_rtc_data {
39 void __iomem *ioaddr; 40 void __iomem *ioaddr;
40 int irq; 41 int irq;
41 spinlock_t lock; 42 spinlock_t lock;
43 struct clk *clk;
42}; 44};
43 45
44static u32 rtc_read_lp_counter(void __iomem *ioaddr) 46static u32 rtc_read_lp_counter(void __iomem *ioaddr)
@@ -260,6 +262,18 @@ static int snvs_rtc_probe(struct platform_device *pdev)
260 if (data->irq < 0) 262 if (data->irq < 0)
261 return data->irq; 263 return data->irq;
262 264
265 data->clk = devm_clk_get(&pdev->dev, "snvs-rtc");
266 if (IS_ERR(data->clk)) {
267 data->clk = NULL;
268 } else {
269 ret = clk_prepare_enable(data->clk);
270 if (ret) {
271 dev_err(&pdev->dev,
272 "Could not prepare or enable the snvs clock\n");
273 return ret;
274 }
275 }
276
263 platform_set_drvdata(pdev, data); 277 platform_set_drvdata(pdev, data);
264 278
265 spin_lock_init(&data->lock); 279 spin_lock_init(&data->lock);
@@ -280,7 +294,7 @@ static int snvs_rtc_probe(struct platform_device *pdev)
280 if (ret) { 294 if (ret) {
281 dev_err(&pdev->dev, "failed to request irq %d: %d\n", 295 dev_err(&pdev->dev, "failed to request irq %d: %d\n",
282 data->irq, ret); 296 data->irq, ret);
283 return ret; 297 goto error_rtc_device_register;
284 } 298 }
285 299
286 data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 300 data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
@@ -288,10 +302,16 @@ static int snvs_rtc_probe(struct platform_device *pdev)
288 if (IS_ERR(data->rtc)) { 302 if (IS_ERR(data->rtc)) {
289 ret = PTR_ERR(data->rtc); 303 ret = PTR_ERR(data->rtc);
290 dev_err(&pdev->dev, "failed to register rtc: %d\n", ret); 304 dev_err(&pdev->dev, "failed to register rtc: %d\n", ret);
291 return ret; 305 goto error_rtc_device_register;
292 } 306 }
293 307
294 return 0; 308 return 0;
309
310error_rtc_device_register:
311 if (data->clk)
312 clk_disable_unprepare(data->clk);
313
314 return ret;
295} 315}
296 316
297#ifdef CONFIG_PM_SLEEP 317#ifdef CONFIG_PM_SLEEP
@@ -302,16 +322,26 @@ static int snvs_rtc_suspend(struct device *dev)
302 if (device_may_wakeup(dev)) 322 if (device_may_wakeup(dev))
303 enable_irq_wake(data->irq); 323 enable_irq_wake(data->irq);
304 324
325 if (data->clk)
326 clk_disable_unprepare(data->clk);
327
305 return 0; 328 return 0;
306} 329}
307 330
308static int snvs_rtc_resume(struct device *dev) 331static int snvs_rtc_resume(struct device *dev)
309{ 332{
310 struct snvs_rtc_data *data = dev_get_drvdata(dev); 333 struct snvs_rtc_data *data = dev_get_drvdata(dev);
334 int ret;
311 335
312 if (device_may_wakeup(dev)) 336 if (device_may_wakeup(dev))
313 disable_irq_wake(data->irq); 337 disable_irq_wake(data->irq);
314 338
339 if (data->clk) {
340 ret = clk_prepare_enable(data->clk);
341 if (ret)
342 return ret;
343 }
344
315 return 0; 345 return 0;
316} 346}
317#endif 347#endif