aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-10-15 13:22:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-15 13:22:21 -0400
commit04ab591808565f968d4406f6435090ad671ebdab (patch)
tree60aebaba3ae0911641ce18c6f04a361a278bc60a /drivers
parent7c3b1dcf13d5660152e02c6dea47b0bd9fd5d871 (diff)
parent08da6f1bdddca14ba0fe28a5f6c41aa163aa27d3 (diff)
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: MIPS: Kill unused <asm/debug.h> inclusions MIPS: IP32: Add platform device for CMOS RTC; remove dead code RTC: M48T35: new RTC driver MIPS: IP27: Switch over to RTC class driver MIPS: DS1286: New RTC driver MIPS: IP22/28: Switch over to RTC class driver MIPS: PCI: Scan busses when they are registered MIPS: WGT634U: Add reset button support MIPS: BCM47xx: Use the new SSB GPIO API MIPS: BCM47xx: Remove references to BCM947XX MIPS: WGT634U: Add machine detection message MIPS: Align .data.cacheline_aligned based on CONFIG_MIPS_L1_CACHE_SHIFT MIPS: show_cpuinfo prints the type of the calling CPU MIPS: Fix wrong branch target in new spin_lock code. MIPS: Have a heart for a lonely, lost header file ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/rtc/Kconfig14
-rw-r--r--drivers/rtc/Makefile2
-rw-r--r--drivers/rtc/rtc-ds1286.c409
-rw-r--r--drivers/rtc/rtc-m48t35.c234
4 files changed, 659 insertions, 0 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index b57fba5c6d02..f3d7fd3406a6 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
@@ -405,6 +410,15 @@ config RTC_DRV_M48T86
405 This driver can also be built as a module. If so, the module 410 This driver can also be built as a module. If so, the module
406 will be called rtc-m48t86. 411 will be called rtc-m48t86.
407 412
413config RTC_DRV_M48T35
414 tristate "ST M48T35"
415 help
416 If you say Y here you will get support for the
417 ST M48T35 RTC chip.
418
419 This driver can also be built as a module, if so, the module
420 will be called "rtc-m48t35".
421
408config RTC_DRV_M48T59 422config RTC_DRV_M48T59
409 tristate "ST M48T59/M48T08/M48T02" 423 tristate "ST M48T59/M48T08/M48T02"
410 help 424 help
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 10f41f85c38a..37a71b727262 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
@@ -36,6 +37,7 @@ obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o
36obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o 37obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
37obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o 38obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o
38obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o 39obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o
40obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o
39obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o 41obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
40obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o 42obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
41obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o 43obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.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);
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c
new file mode 100644
index 000000000000..b9c1fe4a198e
--- /dev/null
+++ b/drivers/rtc/rtc-m48t35.c
@@ -0,0 +1,234 @@
1/*
2 * Driver for the SGS-Thomson M48T35 Timekeeper RAM chip
3 *
4 * Copyright (C) 2000 Silicon Graphics, Inc.
5 * Written by Ulf Carlsson (ulfc@engr.sgi.com)
6 *
7 * Copyright (C) 2008 Thomas Bogendoerfer
8 *
9 * Based on code written by Paul Gortmaker.
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 */
16
17#include <linux/module.h>
18#include <linux/rtc.h>
19#include <linux/platform_device.h>
20#include <linux/bcd.h>
21
22#define DRV_VERSION "1.0"
23
24struct m48t35_rtc {
25 u8 pad[0x7ff8]; /* starts at 0x7ff8 */
26 u8 control;
27 u8 sec;
28 u8 min;
29 u8 hour;
30 u8 day;
31 u8 date;
32 u8 month;
33 u8 year;
34};
35
36#define M48T35_RTC_SET 0x80
37#define M48T35_RTC_READ 0x40
38
39struct m48t35_priv {
40 struct rtc_device *rtc;
41 struct m48t35_rtc __iomem *reg;
42 size_t size;
43 unsigned long baseaddr;
44 spinlock_t lock;
45};
46
47static int m48t35_read_time(struct device *dev, struct rtc_time *tm)
48{
49 struct m48t35_priv *priv = dev_get_drvdata(dev);
50 u8 control;
51
52 /*
53 * Only the values that we read from the RTC are set. We leave
54 * tm_wday, tm_yday and tm_isdst untouched. Even though the
55 * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
56 * by the RTC when initially set to a non-zero value.
57 */
58 spin_lock_irq(&priv->lock);
59 control = readb(&priv->reg->control);
60 writeb(control | M48T35_RTC_READ, &priv->reg->control);
61 tm->tm_sec = readb(&priv->reg->sec);
62 tm->tm_min = readb(&priv->reg->min);
63 tm->tm_hour = readb(&priv->reg->hour);
64 tm->tm_mday = readb(&priv->reg->date);
65 tm->tm_mon = readb(&priv->reg->month);
66 tm->tm_year = readb(&priv->reg->year);
67 writeb(control, &priv->reg->control);
68 spin_unlock_irq(&priv->lock);
69
70 tm->tm_sec = bcd2bin(tm->tm_sec);
71 tm->tm_min = bcd2bin(tm->tm_min);
72 tm->tm_hour = bcd2bin(tm->tm_hour);
73 tm->tm_mday = bcd2bin(tm->tm_mday);
74 tm->tm_mon = bcd2bin(tm->tm_mon);
75 tm->tm_year = bcd2bin(tm->tm_year);
76
77 /*
78 * Account for differences between how the RTC uses the values
79 * and how they are defined in a struct rtc_time;
80 */
81 tm->tm_year += 70;
82 if (tm->tm_year <= 69)
83 tm->tm_year += 100;
84
85 tm->tm_mon--;
86 return rtc_valid_tm(tm);
87}
88
89static int m48t35_set_time(struct device *dev, struct rtc_time *tm)
90{
91 struct m48t35_priv *priv = dev_get_drvdata(dev);
92 unsigned char mon, day, hrs, min, sec;
93 unsigned int yrs;
94 u8 control;
95
96 yrs = tm->tm_year + 1900;
97 mon = tm->tm_mon + 1; /* tm_mon starts at zero */
98 day = tm->tm_mday;
99 hrs = tm->tm_hour;
100 min = tm->tm_min;
101 sec = tm->tm_sec;
102
103 if (yrs < 1970)
104 return -EINVAL;
105
106 yrs -= 1970;
107 if (yrs > 255) /* They are unsigned */
108 return -EINVAL;
109
110 if (yrs > 169)
111 return -EINVAL;
112
113 if (yrs >= 100)
114 yrs -= 100;
115
116 sec = bin2bcd(sec);
117 min = bin2bcd(min);
118 hrs = bin2bcd(hrs);
119 day = bin2bcd(day);
120 mon = bin2bcd(mon);
121 yrs = bin2bcd(yrs);
122
123 spin_lock_irq(&priv->lock);
124 control = readb(&priv->reg->control);
125 writeb(control | M48T35_RTC_SET, &priv->reg->control);
126 writeb(yrs, &priv->reg->year);
127 writeb(mon, &priv->reg->month);
128 writeb(day, &priv->reg->date);
129 writeb(hrs, &priv->reg->hour);
130 writeb(min, &priv->reg->min);
131 writeb(sec, &priv->reg->sec);
132 writeb(control, &priv->reg->control);
133 spin_unlock_irq(&priv->lock);
134 return 0;
135}
136
137static const struct rtc_class_ops m48t35_ops = {
138 .read_time = m48t35_read_time,
139 .set_time = m48t35_set_time,
140};
141
142static int __devinit m48t35_probe(struct platform_device *pdev)
143{
144 struct rtc_device *rtc;
145 struct resource *res;
146 struct m48t35_priv *priv;
147 int ret = 0;
148
149 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
150 if (!res)
151 return -ENODEV;
152 priv = kzalloc(sizeof(struct m48t35_priv), GFP_KERNEL);
153 if (!priv)
154 return -ENOMEM;
155
156 priv->size = res->end - res->start + 1;
157 /*
158 * kludge: remove the #ifndef after ioc3 resource
159 * conflicts are resolved
160 */
161#ifndef CONFIG_SGI_IP27
162 if (!request_mem_region(res->start, priv->size, pdev->name)) {
163 ret = -EBUSY;
164 goto out;
165 }
166#endif
167 priv->baseaddr = res->start;
168 priv->reg = ioremap(priv->baseaddr, priv->size);
169 if (!priv->reg) {
170 ret = -ENOMEM;
171 goto out;
172 }
173 spin_lock_init(&priv->lock);
174 rtc = rtc_device_register("m48t35", &pdev->dev,
175 &m48t35_ops, THIS_MODULE);
176 if (IS_ERR(rtc)) {
177 ret = PTR_ERR(rtc);
178 goto out;
179 }
180 priv->rtc = rtc;
181 platform_set_drvdata(pdev, priv);
182 return 0;
183
184out:
185 if (priv->rtc)
186 rtc_device_unregister(priv->rtc);
187 if (priv->reg)
188 iounmap(priv->reg);
189 if (priv->baseaddr)
190 release_mem_region(priv->baseaddr, priv->size);
191 kfree(priv);
192 return ret;
193}
194
195static int __devexit m48t35_remove(struct platform_device *pdev)
196{
197 struct m48t35_priv *priv = platform_get_drvdata(pdev);
198
199 rtc_device_unregister(priv->rtc);
200 iounmap(priv->reg);
201#ifndef CONFIG_SGI_IP27
202 release_mem_region(priv->baseaddr, priv->size);
203#endif
204 kfree(priv);
205 return 0;
206}
207
208static struct platform_driver m48t35_platform_driver = {
209 .driver = {
210 .name = "rtc-m48t35",
211 .owner = THIS_MODULE,
212 },
213 .probe = m48t35_probe,
214 .remove = __devexit_p(m48t35_remove),
215};
216
217static int __init m48t35_init(void)
218{
219 return platform_driver_register(&m48t35_platform_driver);
220}
221
222static void __exit m48t35_exit(void)
223{
224 platform_driver_unregister(&m48t35_platform_driver);
225}
226
227MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
228MODULE_DESCRIPTION("M48T35 RTC driver");
229MODULE_LICENSE("GPL");
230MODULE_VERSION(DRV_VERSION);
231MODULE_ALIAS("platform:rtc-m48t35");
232
233module_init(m48t35_init);
234module_exit(m48t35_exit);