blob: 319bb5d445ea8177d39e4ee48c69c4e037ef4d33 [file] [log] [blame]
Kyle McMartin9eb16862008-09-10 14:24:07 +00001/* rtc-parisc: RTC for HP PA-RISC firmware
2 *
3 * Copyright (C) 2008 Kyle McMartin <kyle@mcmartin.ca>
4 */
5
6#include <linux/kernel.h>
7#include <linux/module.h>
8#include <linux/time.h>
9#include <linux/platform_device.h>
dann frazier93d456d2009-03-31 15:24:49 -070010#include <linux/rtc.h>
Kyle McMartin9eb16862008-09-10 14:24:07 +000011
12#include <asm/rtc.h>
13
14/* as simple as can be, and no simpler. */
15struct parisc_rtc {
16 struct rtc_device *rtc;
17 spinlock_t lock;
18};
19
20static int parisc_get_time(struct device *dev, struct rtc_time *tm)
21{
22 struct parisc_rtc *p = dev_get_drvdata(dev);
23 unsigned long flags, ret;
24
25 spin_lock_irqsave(&p->lock, flags);
26 ret = get_rtc_time(tm);
27 spin_unlock_irqrestore(&p->lock, flags);
28
29 if (ret & RTC_BATT_BAD)
30 return -EOPNOTSUPP;
31
32 return 0;
33}
34
35static int parisc_set_time(struct device *dev, struct rtc_time *tm)
36{
37 struct parisc_rtc *p = dev_get_drvdata(dev);
Roel Kluin022b7692008-12-03 04:16:04 +000038 unsigned long flags;
39 int ret;
Kyle McMartin9eb16862008-09-10 14:24:07 +000040
41 spin_lock_irqsave(&p->lock, flags);
42 ret = set_rtc_time(tm);
43 spin_unlock_irqrestore(&p->lock, flags);
44
45 if (ret < 0)
46 return -EOPNOTSUPP;
47
48 return 0;
49}
50
51static const struct rtc_class_ops parisc_rtc_ops = {
52 .read_time = parisc_get_time,
53 .set_time = parisc_set_time,
54};
55
56static int __devinit parisc_rtc_probe(struct platform_device *dev)
57{
58 struct parisc_rtc *p;
59
60 p = kzalloc(sizeof (*p), GFP_KERNEL);
61 if (!p)
62 return -ENOMEM;
63
64 spin_lock_init(&p->lock);
65
66 p->rtc = rtc_device_register("rtc-parisc", &dev->dev, &parisc_rtc_ops,
67 THIS_MODULE);
68 if (IS_ERR(p->rtc)) {
69 int err = PTR_ERR(p->rtc);
70 kfree(p);
71 return err;
72 }
73
74 platform_set_drvdata(dev, p);
75
76 return 0;
77}
78
79static int __devexit parisc_rtc_remove(struct platform_device *dev)
80{
81 struct parisc_rtc *p = platform_get_drvdata(dev);
82
83 rtc_device_unregister(p->rtc);
84 kfree(p);
85
86 return 0;
87}
88
89static struct platform_driver parisc_rtc_driver = {
90 .driver = {
91 .name = "rtc-parisc",
92 .owner = THIS_MODULE,
93 },
94 .probe = parisc_rtc_probe,
95 .remove = __devexit_p(parisc_rtc_remove),
96};
97
98static int __init parisc_rtc_init(void)
99{
100 return platform_driver_register(&parisc_rtc_driver);
101}
102
103static void __exit parisc_rtc_fini(void)
104{
105 platform_driver_unregister(&parisc_rtc_driver);
106}
107
108module_init(parisc_rtc_init);
109module_exit(parisc_rtc_fini);
110
111MODULE_AUTHOR("Kyle McMartin <kyle@mcmartin.ca>");
112MODULE_LICENSE("GPL");
113MODULE_DESCRIPTION("HP PA-RISC RTC driver");