aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig32
-rw-r--r--drivers/rtc/Makefile3
-rw-r--r--drivers/rtc/rtc-bq4802.c230
-rw-r--r--drivers/rtc/rtc-cmos.c5
-rw-r--r--drivers/rtc/rtc-m48t59.c68
-rw-r--r--drivers/rtc/rtc-starfire.c120
-rw-r--r--drivers/rtc/rtc-sun4v.c153
7 files changed, 590 insertions, 21 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 9a9755c92fad..b57fba5c6d02 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -329,7 +329,7 @@ comment "Platform RTC drivers"
329 329
330config RTC_DRV_CMOS 330config RTC_DRV_CMOS
331 tristate "PC-style 'CMOS'" 331 tristate "PC-style 'CMOS'"
332 depends on X86 || ALPHA || ARM || M32R || ATARI || PPC || MIPS 332 depends on X86 || ALPHA || ARM || M32R || ATARI || PPC || MIPS || SPARC64
333 default y if X86 333 default y if X86
334 help 334 help
335 Say "yes" here to get direct support for the real time clock 335 Say "yes" here to get direct support for the real time clock
@@ -406,14 +406,26 @@ config RTC_DRV_M48T86
406 will be called rtc-m48t86. 406 will be called rtc-m48t86.
407 407
408config RTC_DRV_M48T59 408config RTC_DRV_M48T59
409 tristate "ST M48T59" 409 tristate "ST M48T59/M48T08/M48T02"
410 help 410 help
411 If you say Y here you will get support for the 411 If you say Y here you will get support for the
412 ST M48T59 RTC chip. 412 ST M48T59 RTC chip and compatible ST M48T08 and M48T02.
413
414 These chips are usually found in Sun SPARC and UltraSPARC
415 workstations.
413 416
414 This driver can also be built as a module, if so, the module 417 This driver can also be built as a module, if so, the module
415 will be called "rtc-m48t59". 418 will be called "rtc-m48t59".
416 419
420config RTC_DRV_BQ4802
421 tristate "TI BQ4802"
422 help
423 If you say Y here you will get support for the TI
424 BQ4802 RTC chip.
425
426 This driver can also be built as a module. If so, the module
427 will be called rtc-bq4802.
428
417config RTC_DRV_V3020 429config RTC_DRV_V3020
418 tristate "EM Microelectronic V3020" 430 tristate "EM Microelectronic V3020"
419 help 431 help
@@ -583,4 +595,18 @@ config RTC_DRV_PPC
583 the RTC. This exposes that functionality through the generic RTC 595 the RTC. This exposes that functionality through the generic RTC
584 class. 596 class.
585 597
598config RTC_DRV_SUN4V
599 bool "SUN4V Hypervisor RTC"
600 depends on SPARC64
601 help
602 If you say Y here you will get support for the Hypervisor
603 based RTC on SUN4V systems.
604
605config RTC_DRV_STARFIRE
606 bool "Starfire RTC"
607 depends on SPARC64
608 help
609 If you say Y here you will get support for the RTC found on
610 Starfire systems.
611
586endif # RTC_CLASS 612endif # RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 18622ef84cab..10f41f85c38a 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -38,6 +38,9 @@ obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o
38obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o 38obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o
39obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o 39obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
40obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o 40obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
41obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o
42obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o
43obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o
41obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o 44obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
42obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o 45obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
43obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o 46obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c
new file mode 100644
index 000000000000..189a018bdf34
--- /dev/null
+++ b/drivers/rtc/rtc-bq4802.c
@@ -0,0 +1,230 @@
1/* rtc-bq4802.c: TI BQ4802 RTC driver.
2 *
3 * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
4 */
5
6#include <linux/kernel.h>
7#include <linux/module.h>
8#include <linux/init.h>
9#include <linux/io.h>
10#include <linux/platform_device.h>
11#include <linux/rtc.h>
12#include <linux/bcd.h>
13
14MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
15MODULE_DESCRIPTION("TI BQ4802 RTC driver");
16MODULE_LICENSE("GPL");
17
18struct bq4802 {
19 void __iomem *regs;
20 unsigned long ioport;
21 struct rtc_device *rtc;
22 spinlock_t lock;
23 struct resource *r;
24 u8 (*read)(struct bq4802 *, int);
25 void (*write)(struct bq4802 *, int, u8);
26};
27
28static u8 bq4802_read_io(struct bq4802 *p, int off)
29{
30 return inb(p->ioport + off);
31}
32
33static void bq4802_write_io(struct bq4802 *p, int off, u8 val)
34{
35 outb(val, p->ioport + off);
36}
37
38static u8 bq4802_read_mem(struct bq4802 *p, int off)
39{
40 return readb(p->regs + off);
41}
42
43static void bq4802_write_mem(struct bq4802 *p, int off, u8 val)
44{
45 writeb(val, p->regs + off);
46}
47
48static int bq4802_read_time(struct device *dev, struct rtc_time *tm)
49{
50 struct platform_device *pdev = to_platform_device(dev);
51 struct bq4802 *p = platform_get_drvdata(pdev);
52 unsigned long flags;
53 unsigned int century;
54 u8 val;
55
56 spin_lock_irqsave(&p->lock, flags);
57
58 val = p->read(p, 0x0e);
59 p->write(p, 0xe, val | 0x08);
60
61 tm->tm_sec = p->read(p, 0x00);
62 tm->tm_min = p->read(p, 0x02);
63 tm->tm_hour = p->read(p, 0x04);
64 tm->tm_mday = p->read(p, 0x06);
65 tm->tm_mon = p->read(p, 0x09);
66 tm->tm_year = p->read(p, 0x0a);
67 tm->tm_wday = p->read(p, 0x08);
68 century = p->read(p, 0x0f);
69
70 p->write(p, 0x0e, val);
71
72 spin_unlock_irqrestore(&p->lock, flags);
73
74 BCD_TO_BIN(tm->tm_sec);
75 BCD_TO_BIN(tm->tm_min);
76 BCD_TO_BIN(tm->tm_hour);
77 BCD_TO_BIN(tm->tm_mday);
78 BCD_TO_BIN(tm->tm_mon);
79 BCD_TO_BIN(tm->tm_year);
80 BCD_TO_BIN(tm->tm_wday);
81 BCD_TO_BIN(century);
82
83 tm->tm_year += (century * 100);
84 tm->tm_year -= 1900;
85
86 tm->tm_mon--;
87
88 return 0;
89}
90
91static int bq4802_set_time(struct device *dev, struct rtc_time *tm)
92{
93 struct platform_device *pdev = to_platform_device(dev);
94 struct bq4802 *p = platform_get_drvdata(pdev);
95 u8 sec, min, hrs, day, mon, yrs, century, val;
96 unsigned long flags;
97 unsigned int year;
98
99 year = tm->tm_year + 1900;
100 century = year / 100;
101 yrs = year % 100;
102
103 mon = tm->tm_mon + 1; /* tm_mon starts at zero */
104 day = tm->tm_mday;
105 hrs = tm->tm_hour;
106 min = tm->tm_min;
107 sec = tm->tm_sec;
108
109 BIN_TO_BCD(sec);
110 BIN_TO_BCD(min);
111 BIN_TO_BCD(hrs);
112 BIN_TO_BCD(day);
113 BIN_TO_BCD(mon);
114 BIN_TO_BCD(yrs);
115 BIN_TO_BCD(century);
116
117 spin_lock_irqsave(&p->lock, flags);
118
119 val = p->read(p, 0x0e);
120 p->write(p, 0x0e, val | 0x08);
121
122 p->write(p, 0x00, sec);
123 p->write(p, 0x02, min);
124 p->write(p, 0x04, hrs);
125 p->write(p, 0x06, day);
126 p->write(p, 0x09, mon);
127 p->write(p, 0x0a, yrs);
128 p->write(p, 0x0f, century);
129
130 p->write(p, 0x0e, val);
131
132 spin_unlock_irqrestore(&p->lock, flags);
133
134 return 0;
135}
136
137static const struct rtc_class_ops bq4802_ops = {
138 .read_time = bq4802_read_time,
139 .set_time = bq4802_set_time,
140};
141
142static int __devinit bq4802_probe(struct platform_device *pdev)
143{
144 struct bq4802 *p = kzalloc(sizeof(*p), GFP_KERNEL);
145 int err = -ENOMEM;
146
147 if (!p)
148 goto out;
149
150 spin_lock_init(&p->lock);
151
152 p->r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
153 if (!p->r) {
154 p->r = platform_get_resource(pdev, IORESOURCE_IO, 0);
155 err = -EINVAL;
156 if (!p->r)
157 goto out_free;
158 }
159 if (p->r->flags & IORESOURCE_IO) {
160 p->ioport = p->r->start;
161 p->read = bq4802_read_io;
162 p->write = bq4802_write_io;
163 } else if (p->r->flags & IORESOURCE_MEM) {
164 p->regs = ioremap(p->r->start, resource_size(p->r));
165 p->read = bq4802_read_mem;
166 p->write = bq4802_write_mem;
167 } else {
168 err = -EINVAL;
169 goto out_free;
170 }
171
172 p->rtc = rtc_device_register("bq4802", &pdev->dev,
173 &bq4802_ops, THIS_MODULE);
174 if (IS_ERR(p->rtc)) {
175 err = PTR_ERR(p->rtc);
176 goto out_iounmap;
177 }
178
179 platform_set_drvdata(pdev, p);
180 err = 0;
181out:
182 return err;
183
184out_iounmap:
185 if (p->r->flags & IORESOURCE_MEM)
186 iounmap(p->regs);
187out_free:
188 kfree(p);
189 goto out;
190}
191
192static int __devexit bq4802_remove(struct platform_device *pdev)
193{
194 struct bq4802 *p = platform_get_drvdata(pdev);
195
196 rtc_device_unregister(p->rtc);
197 if (p->r->flags & IORESOURCE_MEM)
198 iounmap(p->regs);
199
200 platform_set_drvdata(pdev, NULL);
201
202 kfree(p);
203
204 return 0;
205}
206
207/* work with hotplug and coldplug */
208MODULE_ALIAS("platform:rtc-bq4802");
209
210static struct platform_driver bq4802_driver = {
211 .driver = {
212 .name = "rtc-bq4802",
213 .owner = THIS_MODULE,
214 },
215 .probe = bq4802_probe,
216 .remove = __devexit_p(bq4802_remove),
217};
218
219static int __init bq4802_init(void)
220{
221 return platform_driver_register(&bq4802_driver);
222}
223
224static void __exit bq4802_exit(void)
225{
226 platform_driver_unregister(&bq4802_driver);
227}
228
229module_init(bq4802_init);
230module_exit(bq4802_exit);
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index b184367637d0..b23af0c2a869 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -636,7 +636,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
636 */ 636 */
637#if defined(CONFIG_ATARI) 637#if defined(CONFIG_ATARI)
638 address_space = 64; 638 address_space = 64;
639#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) 639#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__sparc__)
640 address_space = 128; 640 address_space = 128;
641#else 641#else
642#warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. 642#warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes.
@@ -699,7 +699,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
699 /* FIXME teach the alarm code how to handle binary mode; 699 /* FIXME teach the alarm code how to handle binary mode;
700 * <asm-generic/rtc.h> doesn't know 12-hour mode either. 700 * <asm-generic/rtc.h> doesn't know 12-hour mode either.
701 */ 701 */
702 if (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY))) { 702 if (is_valid_irq(rtc_irq) &&
703 (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY)))) {
703 dev_dbg(dev, "only 24-hr BCD mode supported\n"); 704 dev_dbg(dev, "only 24-hr BCD mode supported\n");
704 retval = -ENXIO; 705 retval = -ENXIO;
705 goto cleanup1; 706 goto cleanup1;
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 013e6c103b9c..ce4eff6a8d51 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -24,8 +24,9 @@
24#define NO_IRQ (-1) 24#define NO_IRQ (-1)
25#endif 25#endif
26 26
27#define M48T59_READ(reg) pdata->read_byte(dev, reg) 27#define M48T59_READ(reg) (pdata->read_byte(dev, pdata->offset + reg))
28#define M48T59_WRITE(val, reg) pdata->write_byte(dev, reg, val) 28#define M48T59_WRITE(val, reg) \
29 (pdata->write_byte(dev, pdata->offset + reg, val))
29 30
30#define M48T59_SET_BITS(mask, reg) \ 31#define M48T59_SET_BITS(mask, reg) \
31 M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg)) 32 M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg))
@@ -34,7 +35,6 @@
34 35
35struct m48t59_private { 36struct m48t59_private {
36 void __iomem *ioaddr; 37 void __iomem *ioaddr;
37 unsigned int size; /* iomem size */
38 int irq; 38 int irq;
39 struct rtc_device *rtc; 39 struct rtc_device *rtc;
40 spinlock_t lock; /* serialize the NVRAM and RTC access */ 40 spinlock_t lock; /* serialize the NVRAM and RTC access */
@@ -82,7 +82,8 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
82 tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_MDAY)); 82 tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_MDAY));
83 83
84 val = M48T59_READ(M48T59_WDAY); 84 val = M48T59_READ(M48T59_WDAY);
85 if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) { 85 if ((pdata->type == M48T59RTC_TYPE_M48T59) &&
86 (val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) {
86 dev_dbg(dev, "Century bit is enabled\n"); 87 dev_dbg(dev, "Century bit is enabled\n");
87 tm->tm_year += 100; /* one century */ 88 tm->tm_year += 100; /* one century */
88 } 89 }
@@ -126,7 +127,7 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
126 M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH); 127 M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH);
127 M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR); 128 M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR);
128 129
129 if (tm->tm_year/100) 130 if (pdata->type == M48T59RTC_TYPE_M48T59 && (tm->tm_year / 100))
130 val = (M48T59_WDAY_CEB | M48T59_WDAY_CB); 131 val = (M48T59_WDAY_CEB | M48T59_WDAY_CB);
131 val |= (BIN2BCD(tm->tm_wday) & 0x07); 132 val |= (BIN2BCD(tm->tm_wday) & 0x07);
132 M48T59_WRITE(val, M48T59_WDAY); 133 M48T59_WRITE(val, M48T59_WDAY);
@@ -310,6 +311,11 @@ static const struct rtc_class_ops m48t59_rtc_ops = {
310 .proc = m48t59_rtc_proc, 311 .proc = m48t59_rtc_proc,
311}; 312};
312 313
314static const struct rtc_class_ops m48t02_rtc_ops = {
315 .read_time = m48t59_rtc_read_time,
316 .set_time = m48t59_rtc_set_time,
317};
318
313static ssize_t m48t59_nvram_read(struct kobject *kobj, 319static ssize_t m48t59_nvram_read(struct kobject *kobj,
314 struct bin_attribute *bin_attr, 320 struct bin_attribute *bin_attr,
315 char *buf, loff_t pos, size_t size) 321 char *buf, loff_t pos, size_t size)
@@ -321,7 +327,7 @@ static ssize_t m48t59_nvram_read(struct kobject *kobj,
321 ssize_t cnt = 0; 327 ssize_t cnt = 0;
322 unsigned long flags; 328 unsigned long flags;
323 329
324 for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { 330 for (; size > 0 && pos < pdata->offset; cnt++, size--) {
325 spin_lock_irqsave(&m48t59->lock, flags); 331 spin_lock_irqsave(&m48t59->lock, flags);
326 *buf++ = M48T59_READ(cnt); 332 *buf++ = M48T59_READ(cnt);
327 spin_unlock_irqrestore(&m48t59->lock, flags); 333 spin_unlock_irqrestore(&m48t59->lock, flags);
@@ -341,7 +347,7 @@ static ssize_t m48t59_nvram_write(struct kobject *kobj,
341 ssize_t cnt = 0; 347 ssize_t cnt = 0;
342 unsigned long flags; 348 unsigned long flags;
343 349
344 for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { 350 for (; size > 0 && pos < pdata->offset; cnt++, size--) {
345 spin_lock_irqsave(&m48t59->lock, flags); 351 spin_lock_irqsave(&m48t59->lock, flags);
346 M48T59_WRITE(*buf++, cnt); 352 M48T59_WRITE(*buf++, cnt);
347 spin_unlock_irqrestore(&m48t59->lock, flags); 353 spin_unlock_irqrestore(&m48t59->lock, flags);
@@ -358,7 +364,6 @@ static struct bin_attribute m48t59_nvram_attr = {
358 }, 364 },
359 .read = m48t59_nvram_read, 365 .read = m48t59_nvram_read,
360 .write = m48t59_nvram_write, 366 .write = m48t59_nvram_write,
361 .size = M48T59_NVRAM_SIZE,
362}; 367};
363 368
364static int __devinit m48t59_rtc_probe(struct platform_device *pdev) 369static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
@@ -367,6 +372,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
367 struct m48t59_private *m48t59 = NULL; 372 struct m48t59_private *m48t59 = NULL;
368 struct resource *res; 373 struct resource *res;
369 int ret = -ENOMEM; 374 int ret = -ENOMEM;
375 char *name;
376 const struct rtc_class_ops *ops;
370 377
371 /* This chip could be memory-mapped or I/O-mapped */ 378 /* This chip could be memory-mapped or I/O-mapped */
372 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 379 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -391,6 +398,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
391 /* Ensure we only kmalloc platform data once */ 398 /* Ensure we only kmalloc platform data once */
392 pdev->dev.platform_data = pdata; 399 pdev->dev.platform_data = pdata;
393 } 400 }
401 if (!pdata->type)
402 pdata->type = M48T59RTC_TYPE_M48T59;
394 403
395 /* Try to use the generic memory read/write ops */ 404 /* Try to use the generic memory read/write ops */
396 if (!pdata->write_byte) 405 if (!pdata->write_byte)
@@ -403,10 +412,14 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
403 if (!m48t59) 412 if (!m48t59)
404 return -ENOMEM; 413 return -ENOMEM;
405 414
406 m48t59->size = res->end - res->start + 1; 415 m48t59->ioaddr = pdata->ioaddr;
407 m48t59->ioaddr = ioremap(res->start, m48t59->size); 416
408 if (!m48t59->ioaddr) 417 if (!m48t59->ioaddr) {
409 goto out; 418 /* ioaddr not mapped externally */
419 m48t59->ioaddr = ioremap(res->start, res->end - res->start + 1);
420 if (!m48t59->ioaddr)
421 goto out;
422 }
410 423
411 /* Try to get irq number. We also can work in 424 /* Try to get irq number. We also can work in
412 * the mode without IRQ. 425 * the mode without IRQ.
@@ -421,14 +434,36 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
421 if (ret) 434 if (ret)
422 goto out; 435 goto out;
423 } 436 }
437 switch (pdata->type) {
438 case M48T59RTC_TYPE_M48T59:
439 name = "m48t59";
440 ops = &m48t59_rtc_ops;
441 pdata->offset = 0x1ff0;
442 break;
443 case M48T59RTC_TYPE_M48T02:
444 name = "m48t02";
445 ops = &m48t02_rtc_ops;
446 pdata->offset = 0x7f0;
447 break;
448 case M48T59RTC_TYPE_M48T08:
449 name = "m48t08";
450 ops = &m48t02_rtc_ops;
451 pdata->offset = 0x1ff0;
452 break;
453 default:
454 dev_err(&pdev->dev, "Unknown RTC type\n");
455 ret = -ENODEV;
456 goto out;
457 }
424 458
425 m48t59->rtc = rtc_device_register("m48t59", &pdev->dev, 459 m48t59->rtc = rtc_device_register(name, &pdev->dev, ops, THIS_MODULE);
426 &m48t59_rtc_ops, THIS_MODULE);
427 if (IS_ERR(m48t59->rtc)) { 460 if (IS_ERR(m48t59->rtc)) {
428 ret = PTR_ERR(m48t59->rtc); 461 ret = PTR_ERR(m48t59->rtc);
429 goto out; 462 goto out;
430 } 463 }
431 464
465 m48t59_nvram_attr.size = pdata->offset;
466
432 ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); 467 ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
433 if (ret) 468 if (ret)
434 goto out; 469 goto out;
@@ -452,11 +487,12 @@ out:
452static int __devexit m48t59_rtc_remove(struct platform_device *pdev) 487static int __devexit m48t59_rtc_remove(struct platform_device *pdev)
453{ 488{
454 struct m48t59_private *m48t59 = platform_get_drvdata(pdev); 489 struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
490 struct m48t59_plat_data *pdata = pdev->dev.platform_data;
455 491
456 sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); 492 sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
457 if (!IS_ERR(m48t59->rtc)) 493 if (!IS_ERR(m48t59->rtc))
458 rtc_device_unregister(m48t59->rtc); 494 rtc_device_unregister(m48t59->rtc);
459 if (m48t59->ioaddr) 495 if (m48t59->ioaddr && !pdata->ioaddr)
460 iounmap(m48t59->ioaddr); 496 iounmap(m48t59->ioaddr);
461 if (m48t59->irq != NO_IRQ) 497 if (m48t59->irq != NO_IRQ)
462 free_irq(m48t59->irq, &pdev->dev); 498 free_irq(m48t59->irq, &pdev->dev);
@@ -491,5 +527,5 @@ module_init(m48t59_rtc_init);
491module_exit(m48t59_rtc_exit); 527module_exit(m48t59_rtc_exit);
492 528
493MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); 529MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>");
494MODULE_DESCRIPTION("M48T59 RTC driver"); 530MODULE_DESCRIPTION("M48T59/M48T02/M48T08 RTC driver");
495MODULE_LICENSE("GPL"); 531MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-starfire.c b/drivers/rtc/rtc-starfire.c
new file mode 100644
index 000000000000..7ccb0dd700af
--- /dev/null
+++ b/drivers/rtc/rtc-starfire.c
@@ -0,0 +1,120 @@
1/* rtc-starfire.c: Starfire platform RTC driver.
2 *
3 * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
4 */
5
6#include <linux/kernel.h>
7#include <linux/module.h>
8#include <linux/init.h>
9#include <linux/time.h>
10#include <linux/rtc.h>
11#include <linux/platform_device.h>
12
13#include <asm/oplib.h>
14
15MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
16MODULE_DESCRIPTION("Starfire RTC driver");
17MODULE_LICENSE("GPL");
18
19struct starfire_rtc {
20 struct rtc_device *rtc;
21 spinlock_t lock;
22};
23
24static u32 starfire_get_time(void)
25{
26 static char obp_gettod[32];
27 static u32 unix_tod;
28
29 sprintf(obp_gettod, "h# %08x unix-gettod",
30 (unsigned int) (long) &unix_tod);
31 prom_feval(obp_gettod);
32
33 return unix_tod;
34}
35
36static int starfire_read_time(struct device *dev, struct rtc_time *tm)
37{
38 struct starfire_rtc *p = dev_get_drvdata(dev);
39 unsigned long flags, secs;
40
41 spin_lock_irqsave(&p->lock, flags);
42 secs = starfire_get_time();
43 spin_unlock_irqrestore(&p->lock, flags);
44
45 rtc_time_to_tm(secs, tm);
46
47 return 0;
48}
49
50static int starfire_set_time(struct device *dev, struct rtc_time *tm)
51{
52 unsigned long secs;
53 int err;
54
55 err = rtc_tm_to_time(tm, &secs);
56 if (err)
57 return err;
58
59 /* Do nothing, time is set using the service processor
60 * console on this platform.
61 */
62 return 0;
63}
64
65static const struct rtc_class_ops starfire_rtc_ops = {
66 .read_time = starfire_read_time,
67 .set_time = starfire_set_time,
68};
69
70static int __devinit starfire_rtc_probe(struct platform_device *pdev)
71{
72 struct starfire_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL);
73
74 if (!p)
75 return -ENOMEM;
76
77 spin_lock_init(&p->lock);
78
79 p->rtc = rtc_device_register("starfire", &pdev->dev,
80 &starfire_rtc_ops, THIS_MODULE);
81 if (IS_ERR(p->rtc)) {
82 int err = PTR_ERR(p->rtc);
83 kfree(p);
84 return err;
85 }
86 platform_set_drvdata(pdev, p);
87 return 0;
88}
89
90static int __devexit starfire_rtc_remove(struct platform_device *pdev)
91{
92 struct starfire_rtc *p = platform_get_drvdata(pdev);
93
94 rtc_device_unregister(p->rtc);
95 kfree(p);
96
97 return 0;
98}
99
100static struct platform_driver starfire_rtc_driver = {
101 .driver = {
102 .name = "rtc-starfire",
103 .owner = THIS_MODULE,
104 },
105 .probe = starfire_rtc_probe,
106 .remove = __devexit_p(starfire_rtc_remove),
107};
108
109static int __init starfire_rtc_init(void)
110{
111 return platform_driver_register(&starfire_rtc_driver);
112}
113
114static void __exit starfire_rtc_exit(void)
115{
116 platform_driver_unregister(&starfire_rtc_driver);
117}
118
119module_init(starfire_rtc_init);
120module_exit(starfire_rtc_exit);
diff --git a/drivers/rtc/rtc-sun4v.c b/drivers/rtc/rtc-sun4v.c
new file mode 100644
index 000000000000..2012ccbb4a53
--- /dev/null
+++ b/drivers/rtc/rtc-sun4v.c
@@ -0,0 +1,153 @@
1/* rtc-sun4c.c: Hypervisor based RTC for SUN4V systems.
2 *
3 * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
4 */
5
6#include <linux/kernel.h>
7#include <linux/module.h>
8#include <linux/delay.h>
9#include <linux/init.h>
10#include <linux/time.h>
11#include <linux/rtc.h>
12#include <linux/platform_device.h>
13
14#include <asm/hypervisor.h>
15
16MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
17MODULE_DESCRIPTION("SUN4V RTC driver");
18MODULE_LICENSE("GPL");
19
20struct sun4v_rtc {
21 struct rtc_device *rtc;
22 spinlock_t lock;
23};
24
25static unsigned long hypervisor_get_time(void)
26{
27 unsigned long ret, time;
28 int retries = 10000;
29
30retry:
31 ret = sun4v_tod_get(&time);
32 if (ret == HV_EOK)
33 return time;
34 if (ret == HV_EWOULDBLOCK) {
35 if (--retries > 0) {
36 udelay(100);
37 goto retry;
38 }
39 printk(KERN_WARNING "SUN4V: tod_get() timed out.\n");
40 return 0;
41 }
42 printk(KERN_WARNING "SUN4V: tod_get() not supported.\n");
43 return 0;
44}
45
46static int sun4v_read_time(struct device *dev, struct rtc_time *tm)
47{
48 struct sun4v_rtc *p = dev_get_drvdata(dev);
49 unsigned long flags, secs;
50
51 spin_lock_irqsave(&p->lock, flags);
52 secs = hypervisor_get_time();
53 spin_unlock_irqrestore(&p->lock, flags);
54
55 rtc_time_to_tm(secs, tm);
56
57 return 0;
58}
59
60static int hypervisor_set_time(unsigned long secs)
61{
62 unsigned long ret;
63 int retries = 10000;
64
65retry:
66 ret = sun4v_tod_set(secs);
67 if (ret == HV_EOK)
68 return 0;
69 if (ret == HV_EWOULDBLOCK) {
70 if (--retries > 0) {
71 udelay(100);
72 goto retry;
73 }
74 printk(KERN_WARNING "SUN4V: tod_set() timed out.\n");
75 return -EAGAIN;
76 }
77 printk(KERN_WARNING "SUN4V: tod_set() not supported.\n");
78 return -EOPNOTSUPP;
79}
80
81static int sun4v_set_time(struct device *dev, struct rtc_time *tm)
82{
83 struct sun4v_rtc *p = dev_get_drvdata(dev);
84 unsigned long flags, secs;
85 int err;
86
87 err = rtc_tm_to_time(tm, &secs);
88 if (err)
89 return err;
90
91 spin_lock_irqsave(&p->lock, flags);
92 err = hypervisor_set_time(secs);
93 spin_unlock_irqrestore(&p->lock, flags);
94
95 return err;
96}
97
98static const struct rtc_class_ops sun4v_rtc_ops = {
99 .read_time = sun4v_read_time,
100 .set_time = sun4v_set_time,
101};
102
103static int __devinit sun4v_rtc_probe(struct platform_device *pdev)
104{
105 struct sun4v_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL);
106
107 if (!p)
108 return -ENOMEM;
109
110 spin_lock_init(&p->lock);
111
112 p->rtc = rtc_device_register("sun4v", &pdev->dev,
113 &sun4v_rtc_ops, THIS_MODULE);
114 if (IS_ERR(p->rtc)) {
115 int err = PTR_ERR(p->rtc);
116 kfree(p);
117 return err;
118 }
119 platform_set_drvdata(pdev, p);
120 return 0;
121}
122
123static int __devexit sun4v_rtc_remove(struct platform_device *pdev)
124{
125 struct sun4v_rtc *p = platform_get_drvdata(pdev);
126
127 rtc_device_unregister(p->rtc);
128 kfree(p);
129
130 return 0;
131}
132
133static struct platform_driver sun4v_rtc_driver = {
134 .driver = {
135 .name = "rtc-sun4v",
136 .owner = THIS_MODULE,
137 },
138 .probe = sun4v_rtc_probe,
139 .remove = __devexit_p(sun4v_rtc_remove),
140};
141
142static int __init sun4v_rtc_init(void)
143{
144 return platform_driver_register(&sun4v_rtc_driver);
145}
146
147static void __exit sun4v_rtc_exit(void)
148{
149 platform_driver_unregister(&sun4v_rtc_driver);
150}
151
152module_init(sun4v_rtc_init);
153module_exit(sun4v_rtc_exit);