Commit 9eb1686423756f4dfb0ad8bfb02bb8bf1b89e50a
Committed by
Kyle McMartin
1 parent
f0514ae323
Exists in
master
and in
7 other branches
parisc: add rtc platform driver
Signed-off-by: Kyle McMartin <kyle@mcmartin.ca>
Showing 5 changed files with 141 additions and 1 deletions Side-by-side Diff
arch/parisc/Kconfig
arch/parisc/kernel/time.c
... | ... | @@ -23,6 +23,7 @@ |
23 | 23 | #include <linux/smp.h> |
24 | 24 | #include <linux/profile.h> |
25 | 25 | #include <linux/clocksource.h> |
26 | +#include <linux/platform_device.h> | |
26 | 27 | |
27 | 28 | #include <asm/uaccess.h> |
28 | 29 | #include <asm/io.h> |
... | ... | @@ -214,6 +215,24 @@ |
214 | 215 | |
215 | 216 | cpu_data[cpu].it_value = next_tick; |
216 | 217 | } |
218 | + | |
219 | +struct platform_device rtc_parisc_dev = { | |
220 | + .name = "rtc-parisc", | |
221 | + .id = -1, | |
222 | +}; | |
223 | + | |
224 | +static int __init rtc_init(void) | |
225 | +{ | |
226 | + int ret; | |
227 | + | |
228 | + ret = platform_device_register(&rtc_parisc_dev); | |
229 | + if (ret < 0) | |
230 | + printk(KERN_ERR "unable to register rtc device...\n"); | |
231 | + | |
232 | + /* not necessarily an error */ | |
233 | + return 0; | |
234 | +} | |
235 | +module_init(rtc_init); | |
217 | 236 | |
218 | 237 | void __init time_init(void) |
219 | 238 | { |
drivers/rtc/Kconfig
... | ... | @@ -575,6 +575,14 @@ |
575 | 575 | help |
576 | 576 | If you say yes here you get support for the Ricoh RS5C313 RTC chips. |
577 | 577 | |
578 | +config RTC_DRV_PARISC | |
579 | + tristate "PA-RISC firmware RTC support" | |
580 | + depends on PARISC | |
581 | + help | |
582 | + Say Y or M here to enable RTC support on PA-RISC systems using | |
583 | + firmware calls. If you do not know what you are doing, you should | |
584 | + just say Y. | |
585 | + | |
578 | 586 | config RTC_DRV_PPC |
579 | 587 | tristate "PowerPC machine dependent RTC support" |
580 | 588 | depends on PPC_MERGE |
drivers/rtc/Makefile
... | ... | @@ -45,6 +45,7 @@ |
45 | 45 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o |
46 | 46 | obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o |
47 | 47 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o |
48 | +obj-$(CONFIG_RTC_DRV_PARISC) += rtc-parisc.o | |
48 | 49 | obj-$(CONFIG_RTC_DRV_PPC) += rtc-ppc.o |
49 | 50 | obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o |
50 | 51 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o |
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"); |