Merge branch 'sched/urgent'; commit 'v2.6.28' into sched/core
[linux-2.6] / drivers / rtc / rtc-parisc.c
1 /* 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>
10
11 #include <asm/rtc.h>
12
13 /* as simple as can be, and no simpler. */
14 struct parisc_rtc {
15         struct rtc_device *rtc;
16         spinlock_t lock;
17 };
18
19 static int parisc_get_time(struct device *dev, struct rtc_time *tm)
20 {
21         struct parisc_rtc *p = dev_get_drvdata(dev);
22         unsigned long flags, ret;
23
24         spin_lock_irqsave(&p->lock, flags);
25         ret = get_rtc_time(tm);
26         spin_unlock_irqrestore(&p->lock, flags);
27
28         if (ret & RTC_BATT_BAD)
29                 return -EOPNOTSUPP;
30
31         return 0;
32 }
33
34 static int parisc_set_time(struct device *dev, struct rtc_time *tm)
35 {
36         struct parisc_rtc *p = dev_get_drvdata(dev);
37         unsigned long flags, ret;
38
39         spin_lock_irqsave(&p->lock, flags);
40         ret = set_rtc_time(tm);
41         spin_unlock_irqrestore(&p->lock, flags);
42
43         if (ret < 0)
44                 return -EOPNOTSUPP;
45
46         return 0;
47 }
48
49 static const struct rtc_class_ops parisc_rtc_ops = {
50         .read_time = parisc_get_time,
51         .set_time = parisc_set_time,
52 };
53
54 static int __devinit parisc_rtc_probe(struct platform_device *dev)
55 {
56         struct parisc_rtc *p;
57
58         p = kzalloc(sizeof (*p), GFP_KERNEL);
59         if (!p)
60                 return -ENOMEM;
61
62         spin_lock_init(&p->lock);
63
64         p->rtc = rtc_device_register("rtc-parisc", &dev->dev, &parisc_rtc_ops,
65                                         THIS_MODULE);
66         if (IS_ERR(p->rtc)) {
67                 int err = PTR_ERR(p->rtc);
68                 kfree(p);
69                 return err;
70         }
71
72         platform_set_drvdata(dev, p);
73
74         return 0;
75 }
76
77 static int __devexit parisc_rtc_remove(struct platform_device *dev)
78 {
79         struct parisc_rtc *p = platform_get_drvdata(dev);
80
81         rtc_device_unregister(p->rtc);
82         kfree(p);
83
84         return 0;
85 }
86
87 static struct platform_driver parisc_rtc_driver = {
88         .driver = {
89                 .name = "rtc-parisc",
90                 .owner = THIS_MODULE,
91         },
92         .probe = parisc_rtc_probe,
93         .remove = __devexit_p(parisc_rtc_remove),
94 };
95
96 static int __init parisc_rtc_init(void)
97 {
98         return platform_driver_register(&parisc_rtc_driver);
99 }
100
101 static void __exit parisc_rtc_fini(void)
102 {
103         platform_driver_unregister(&parisc_rtc_driver);
104 }
105
106 module_init(parisc_rtc_init);
107 module_exit(parisc_rtc_fini);
108
109 MODULE_AUTHOR("Kyle McMartin <kyle@mcmartin.ca>");
110 MODULE_LICENSE("GPL");
111 MODULE_DESCRIPTION("HP PA-RISC RTC driver");