aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorThomas Bogendoerfer <tsbogend@alpha.franken.de>2008-10-14 11:16:59 -0400
committerRalf Baechle <ralf@linux-mips.org>2008-10-15 07:46:51 -0400
commit5f119f29063c9a9bf1ab40112c02710c2db84f29 (patch)
tree0bbaad32a7a039475f6a53eadbd8be44b320d525 /drivers/rtc
parent7d81a5e03ddbb44d05a32cad4a46a23577216497 (diff)
MIPS: DS1286: New RTC driver
This driver replaces the broken DS1286 driver in drivers/char and gives back RTC support for SGI IP22 and IP28 machines. Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de> Acked-by: Alessandro Zummo <alessandro.zummo@towertech.it> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig5
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-ds1286.c409
3 files changed, 415 insertions, 0 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index b57fba5c6d02..24217008aa35 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -352,6 +352,11 @@ config RTC_DRV_DS1216
352 help 352 help
353 If you say yes here you get support for the Dallas DS1216 RTC chips. 353 If you say yes here you get support for the Dallas DS1216 RTC chips.
354 354
355config RTC_DRV_DS1286
356 tristate "Dallas DS1286"
357 help
358 If you say yes here you get support for the Dallas DS1286 RTC chips.
359
355config RTC_DRV_DS1302 360config RTC_DRV_DS1302
356 tristate "Dallas DS1302" 361 tristate "Dallas DS1302"
357 depends on SH_SECUREEDGE5410 362 depends on SH_SECUREEDGE5410
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 10f41f85c38a..a3208082565c 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o
23obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o 23obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o
24obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o 24obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
25obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o 25obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o
26obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o
26obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o 27obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
27obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o 28obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o
28obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o 29obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c
new file mode 100644
index 000000000000..4b4c1b6a4187
--- /dev/null
+++ b/drivers/rtc/rtc-ds1286.c
@@ -0,0 +1,409 @@
1/*
2 * DS1286 Real Time Clock interface for Linux
3 *
4 * Copyright (C) 1998, 1999, 2000 Ralf Baechle
5 * Copyright (C) 2008 Thomas Bogendoerfer
6 *
7 * Based on code written by Paul Gortmaker.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 */
14
15#include <linux/module.h>
16#include <linux/rtc.h>
17#include <linux/platform_device.h>
18#include <linux/bcd.h>
19#include <linux/ds1286.h>
20
21#define DRV_VERSION "1.0"
22
23struct ds1286_priv {
24 struct rtc_device *rtc;
25 u32 __iomem *rtcregs;
26 size_t size;
27 unsigned long baseaddr;
28 spinlock_t lock;
29};
30
31static inline u8 ds1286_rtc_read(struct ds1286_priv *priv, int reg)
32{
33 return __raw_readl(&priv->rtcregs[reg]) & 0xff;
34}
35
36static inline void ds1286_rtc_write(struct ds1286_priv *priv, u8 data, int reg)
37{
38 __raw_writel(data, &priv->rtcregs[reg]);
39}
40
41#ifdef CONFIG_RTC_INTF_DEV
42
43static int ds1286_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
44{
45 struct ds1286_priv *priv = dev_get_drvdata(dev);
46 unsigned long flags;
47 unsigned char val;
48
49 switch (cmd) {
50 case RTC_AIE_OFF:
51 /* Mask alarm int. enab. bit */
52 spin_lock_irqsave(&priv->lock, flags);
53 val = ds1286_rtc_read(priv, RTC_CMD);
54 val |= RTC_TDM;
55 ds1286_rtc_write(priv, val, RTC_CMD);
56 spin_unlock_irqrestore(&priv->lock, flags);
57 break;
58 case RTC_AIE_ON:
59 /* Allow alarm interrupts. */
60 spin_lock_irqsave(&priv->lock, flags);
61 val = ds1286_rtc_read(priv, RTC_CMD);
62 val &= ~RTC_TDM;
63 ds1286_rtc_write(priv, val, RTC_CMD);
64 spin_unlock_irqrestore(&priv->lock, flags);
65 break;
66 case RTC_WIE_OFF:
67 /* Mask watchdog int. enab. bit */
68 spin_lock_irqsave(&priv->lock, flags);
69 val = ds1286_rtc_read(priv, RTC_CMD);
70 val |= RTC_WAM;
71 ds1286_rtc_write(priv, val, RTC_CMD);
72 spin_unlock_irqrestore(&priv->lock, flags);
73 break;
74 case RTC_WIE_ON:
75 /* Allow watchdog interrupts. */
76 spin_lock_irqsave(&priv->lock, flags);
77 val = ds1286_rtc_read(priv, RTC_CMD);
78 val &= ~RTC_WAM;
79 ds1286_rtc_write(priv, val, RTC_CMD);
80 spin_unlock_irqrestore(&priv->lock, flags);
81 break;
82 default:
83 return -ENOIOCTLCMD;
84 }
85 return 0;
86}
87
88#else
89#define ds1286_ioctl NULL
90#endif
91
92#ifdef CONFIG_PROC_FS
93
94static int ds1286_proc(struct device *dev, struct seq_file *seq)
95{
96 struct ds1286_priv *priv = dev_get_drvdata(dev);
97 unsigned char month, cmd, amode;
98 const char *s;
99
100 month = ds1286_rtc_read(priv, RTC_MONTH);
101 seq_printf(seq,
102 "oscillator\t: %s\n"
103 "square_wave\t: %s\n",
104 (month & RTC_EOSC) ? "disabled" : "enabled",
105 (month & RTC_ESQW) ? "disabled" : "enabled");
106
107 amode = ((ds1286_rtc_read(priv, RTC_MINUTES_ALARM) & 0x80) >> 5) |
108 ((ds1286_rtc_read(priv, RTC_HOURS_ALARM) & 0x80) >> 6) |
109 ((ds1286_rtc_read(priv, RTC_DAY_ALARM) & 0x80) >> 7);
110 switch (amode) {
111 case 7:
112 s = "each minute";
113 break;
114 case 3:
115 s = "minutes match";
116 break;
117 case 1:
118 s = "hours and minutes match";
119 break;
120 case 0:
121 s = "days, hours and minutes match";
122 break;
123 default:
124 s = "invalid";
125 break;
126 }
127 seq_printf(seq, "alarm_mode\t: %s\n", s);
128
129 cmd = ds1286_rtc_read(priv, RTC_CMD);
130 seq_printf(seq,
131 "alarm_enable\t: %s\n"
132 "wdog_alarm\t: %s\n"
133 "alarm_mask\t: %s\n"
134 "wdog_alarm_mask\t: %s\n"
135 "interrupt_mode\t: %s\n"
136 "INTB_mode\t: %s_active\n"
137 "interrupt_pins\t: %s\n",
138 (cmd & RTC_TDF) ? "yes" : "no",
139 (cmd & RTC_WAF) ? "yes" : "no",
140 (cmd & RTC_TDM) ? "disabled" : "enabled",
141 (cmd & RTC_WAM) ? "disabled" : "enabled",
142 (cmd & RTC_PU_LVL) ? "pulse" : "level",
143 (cmd & RTC_IBH_LO) ? "low" : "high",
144 (cmd & RTC_IPSW) ? "unswapped" : "swapped");
145 return 0;
146}
147
148#else
149#define ds1286_proc NULL
150#endif
151
152static int ds1286_read_time(struct device *dev, struct rtc_time *tm)
153{
154 struct ds1286_priv *priv = dev_get_drvdata(dev);
155 unsigned char save_control;
156 unsigned long flags;
157 unsigned long uip_watchdog = jiffies;
158
159 /*
160 * read RTC once any update in progress is done. The update
161 * can take just over 2ms. We wait 10 to 20ms. There is no need to
162 * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
163 * If you need to know *exactly* when a second has started, enable
164 * periodic update complete interrupts, (via ioctl) and then
165 * immediately read /dev/rtc which will block until you get the IRQ.
166 * Once the read clears, read the RTC time (again via ioctl). Easy.
167 */
168
169 if (ds1286_rtc_read(priv, RTC_CMD) & RTC_TE)
170 while (time_before(jiffies, uip_watchdog + 2*HZ/100))
171 barrier();
172
173 /*
174 * Only the values that we read from the RTC are set. We leave
175 * tm_wday, tm_yday and tm_isdst untouched. Even though the
176 * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
177 * by the RTC when initially set to a non-zero value.
178 */
179 spin_lock_irqsave(&priv->lock, flags);
180 save_control = ds1286_rtc_read(priv, RTC_CMD);
181 ds1286_rtc_write(priv, (save_control|RTC_TE), RTC_CMD);
182
183 tm->tm_sec = ds1286_rtc_read(priv, RTC_SECONDS);
184 tm->tm_min = ds1286_rtc_read(priv, RTC_MINUTES);
185 tm->tm_hour = ds1286_rtc_read(priv, RTC_HOURS) & 0x3f;
186 tm->tm_mday = ds1286_rtc_read(priv, RTC_DATE);
187 tm->tm_mon = ds1286_rtc_read(priv, RTC_MONTH) & 0x1f;
188 tm->tm_year = ds1286_rtc_read(priv, RTC_YEAR);
189
190 ds1286_rtc_write(priv, save_control, RTC_CMD);
191 spin_unlock_irqrestore(&priv->lock, flags);
192
193 tm->tm_sec = bcd2bin(tm->tm_sec);
194 tm->tm_min = bcd2bin(tm->tm_min);
195 tm->tm_hour = bcd2bin(tm->tm_hour);
196 tm->tm_mday = bcd2bin(tm->tm_mday);
197 tm->tm_mon = bcd2bin(tm->tm_mon);
198 tm->tm_year = bcd2bin(tm->tm_year);
199
200 /*
201 * Account for differences between how the RTC uses the values
202 * and how they are defined in a struct rtc_time;
203 */
204 if (tm->tm_year < 45)
205 tm->tm_year += 30;
206 tm->tm_year += 40;
207 if (tm->tm_year < 70)
208 tm->tm_year += 100;
209
210 tm->tm_mon--;
211
212 return rtc_valid_tm(tm);
213}
214
215static int ds1286_set_time(struct device *dev, struct rtc_time *tm)
216{
217 struct ds1286_priv *priv = dev_get_drvdata(dev);
218 unsigned char mon, day, hrs, min, sec;
219 unsigned char save_control;
220 unsigned int yrs;
221 unsigned long flags;
222
223 yrs = tm->tm_year + 1900;
224 mon = tm->tm_mon + 1; /* tm_mon starts at zero */
225 day = tm->tm_mday;
226 hrs = tm->tm_hour;
227 min = tm->tm_min;
228 sec = tm->tm_sec;
229
230 if (yrs < 1970)
231 return -EINVAL;
232
233 yrs -= 1940;
234 if (yrs > 255) /* They are unsigned */
235 return -EINVAL;
236
237 if (yrs >= 100)
238 yrs -= 100;
239
240 sec = bin2bcd(sec);
241 min = bin2bcd(min);
242 hrs = bin2bcd(hrs);
243 day = bin2bcd(day);
244 mon = bin2bcd(mon);
245 yrs = bin2bcd(yrs);
246
247 spin_lock_irqsave(&priv->lock, flags);
248 save_control = ds1286_rtc_read(priv, RTC_CMD);
249 ds1286_rtc_write(priv, (save_control|RTC_TE), RTC_CMD);
250
251 ds1286_rtc_write(priv, yrs, RTC_YEAR);
252 ds1286_rtc_write(priv, mon, RTC_MONTH);
253 ds1286_rtc_write(priv, day, RTC_DATE);
254 ds1286_rtc_write(priv, hrs, RTC_HOURS);
255 ds1286_rtc_write(priv, min, RTC_MINUTES);
256 ds1286_rtc_write(priv, sec, RTC_SECONDS);
257 ds1286_rtc_write(priv, 0, RTC_HUNDREDTH_SECOND);
258
259 ds1286_rtc_write(priv, save_control, RTC_CMD);
260 spin_unlock_irqrestore(&priv->lock, flags);
261 return 0;
262}
263
264static int ds1286_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
265{
266 struct ds1286_priv *priv = dev_get_drvdata(dev);
267 unsigned char cmd;
268 unsigned long flags;
269
270 /*
271 * Only the values that we read from the RTC are set. That
272 * means only tm_wday, tm_hour, tm_min.
273 */
274 spin_lock_irqsave(&priv->lock, flags);
275 alm->time.tm_min = ds1286_rtc_read(priv, RTC_MINUTES_ALARM) & 0x7f;
276 alm->time.tm_hour = ds1286_rtc_read(priv, RTC_HOURS_ALARM) & 0x1f;
277 alm->time.tm_wday = ds1286_rtc_read(priv, RTC_DAY_ALARM) & 0x07;
278 cmd = ds1286_rtc_read(priv, RTC_CMD);
279 spin_unlock_irqrestore(&priv->lock, flags);
280
281 alm->time.tm_min = bcd2bin(alm->time.tm_min);
282 alm->time.tm_hour = bcd2bin(alm->time.tm_hour);
283 alm->time.tm_sec = 0;
284 return 0;
285}
286
287static int ds1286_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
288{
289 struct ds1286_priv *priv = dev_get_drvdata(dev);
290 unsigned char hrs, min, sec;
291
292 hrs = alm->time.tm_hour;
293 min = alm->time.tm_min;
294 sec = alm->time.tm_sec;
295
296 if (hrs >= 24)
297 hrs = 0xff;
298
299 if (min >= 60)
300 min = 0xff;
301
302 if (sec != 0)
303 return -EINVAL;
304
305 min = bin2bcd(min);
306 hrs = bin2bcd(hrs);
307
308 spin_lock(&priv->lock);
309 ds1286_rtc_write(priv, hrs, RTC_HOURS_ALARM);
310 ds1286_rtc_write(priv, min, RTC_MINUTES_ALARM);
311 spin_unlock(&priv->lock);
312
313 return 0;
314}
315
316static const struct rtc_class_ops ds1286_ops = {
317 .ioctl = ds1286_ioctl,
318 .proc = ds1286_proc,
319 .read_time = ds1286_read_time,
320 .set_time = ds1286_set_time,
321 .read_alarm = ds1286_read_alarm,
322 .set_alarm = ds1286_set_alarm,
323};
324
325static int __devinit ds1286_probe(struct platform_device *pdev)
326{
327 struct rtc_device *rtc;
328 struct resource *res;
329 struct ds1286_priv *priv;
330 int ret = 0;
331
332 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
333 if (!res)
334 return -ENODEV;
335 priv = kzalloc(sizeof(struct ds1286_priv), GFP_KERNEL);
336 if (!priv)
337 return -ENOMEM;
338
339 priv->size = res->end - res->start + 1;
340 if (!request_mem_region(res->start, priv->size, pdev->name)) {
341 ret = -EBUSY;
342 goto out;
343 }
344 priv->baseaddr = res->start;
345 priv->rtcregs = ioremap(priv->baseaddr, priv->size);
346 if (!priv->rtcregs) {
347 ret = -ENOMEM;
348 goto out;
349 }
350 spin_lock_init(&priv->lock);
351 rtc = rtc_device_register("ds1286", &pdev->dev,
352 &ds1286_ops, THIS_MODULE);
353 if (IS_ERR(rtc)) {
354 ret = PTR_ERR(rtc);
355 goto out;
356 }
357 priv->rtc = rtc;
358 platform_set_drvdata(pdev, priv);
359 return 0;
360
361out:
362 if (priv->rtc)
363 rtc_device_unregister(priv->rtc);
364 if (priv->rtcregs)
365 iounmap(priv->rtcregs);
366 if (priv->baseaddr)
367 release_mem_region(priv->baseaddr, priv->size);
368 kfree(priv);
369 return ret;
370}
371
372static int __devexit ds1286_remove(struct platform_device *pdev)
373{
374 struct ds1286_priv *priv = platform_get_drvdata(pdev);
375
376 rtc_device_unregister(priv->rtc);
377 iounmap(priv->rtcregs);
378 release_mem_region(priv->baseaddr, priv->size);
379 kfree(priv);
380 return 0;
381}
382
383static struct platform_driver ds1286_platform_driver = {
384 .driver = {
385 .name = "rtc-ds1286",
386 .owner = THIS_MODULE,
387 },
388 .probe = ds1286_probe,
389 .remove = __devexit_p(ds1286_remove),
390};
391
392static int __init ds1286_init(void)
393{
394 return platform_driver_register(&ds1286_platform_driver);
395}
396
397static void __exit ds1286_exit(void)
398{
399 platform_driver_unregister(&ds1286_platform_driver);
400}
401
402MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
403MODULE_DESCRIPTION("DS1286 RTC driver");
404MODULE_LICENSE("GPL");
405MODULE_VERSION(DRV_VERSION);
406MODULE_ALIAS("platform:rtc-ds1286");
407
408module_init(ds1286_init);
409module_exit(ds1286_exit);