]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/rtc/rtc-m48t59.c
e085ab2c3dbe9bf17af3aadebbe12e129e80fe15
[linux-2.6-omap-h63xx.git] / drivers / rtc / rtc-m48t59.c
1 /*
2  * ST M48T59 RTC driver
3  *
4  * Copyright (c) 2007 Wind River Systems, Inc.
5  *
6  * Author: Mark Zhan <rongkai.zhan@windriver.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/io.h>
17 #include <linux/device.h>
18 #include <linux/platform_device.h>
19 #include <linux/rtc.h>
20 #include <linux/rtc/m48t59.h>
21 #include <linux/bcd.h>
22
23 #ifndef NO_IRQ
24 #define NO_IRQ  (-1)
25 #endif
26
27 #define M48T59_READ(reg)        pdata->read_byte(dev, reg)
28 #define M48T59_WRITE(val, reg)  pdata->write_byte(dev, reg, val)
29
30 #define M48T59_SET_BITS(mask, reg)      \
31         M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg))
32 #define M48T59_CLEAR_BITS(mask, reg)    \
33         M48T59_WRITE((M48T59_READ(reg) & ~(mask)), (reg))
34
35 struct m48t59_private {
36         void __iomem *ioaddr;
37         int irq;
38         struct rtc_device *rtc;
39         spinlock_t lock; /* serialize the NVRAM and RTC access */
40 };
41
42 /*
43  * This is the generic access method when the chip is memory-mapped
44  */
45 static void
46 m48t59_mem_writeb(struct device *dev, u32 ofs, u8 val)
47 {
48         struct platform_device *pdev = to_platform_device(dev);
49         struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
50
51         writeb(val, m48t59->ioaddr+ofs);
52 }
53
54 static u8
55 m48t59_mem_readb(struct device *dev, u32 ofs)
56 {
57         struct platform_device *pdev = to_platform_device(dev);
58         struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
59
60         return readb(m48t59->ioaddr+ofs);
61 }
62
63 /*
64  * NOTE: M48T59 only uses BCD mode
65  */
66 static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
67 {
68         struct platform_device *pdev = to_platform_device(dev);
69         struct m48t59_plat_data *pdata = pdev->dev.platform_data;
70         struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
71         unsigned long flags;
72         u8 val;
73
74         spin_lock_irqsave(&m48t59->lock, flags);
75         /* Issue the READ command */
76         M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
77
78         tm->tm_year     = BCD2BIN(M48T59_READ(M48T59_YEAR));
79         /* tm_mon is 0-11 */
80         tm->tm_mon      = BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1;
81         tm->tm_mday     = BCD2BIN(M48T59_READ(M48T59_MDAY));
82
83         val = M48T59_READ(M48T59_WDAY);
84         if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) {
85                 dev_dbg(dev, "Century bit is enabled\n");
86                 tm->tm_year += 100;     /* one century */
87         }
88
89         tm->tm_wday     = BCD2BIN(val & 0x07);
90         tm->tm_hour     = BCD2BIN(M48T59_READ(M48T59_HOUR) & 0x3F);
91         tm->tm_min      = BCD2BIN(M48T59_READ(M48T59_MIN) & 0x7F);
92         tm->tm_sec      = BCD2BIN(M48T59_READ(M48T59_SEC) & 0x7F);
93
94         /* Clear the READ bit */
95         M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
96         spin_unlock_irqrestore(&m48t59->lock, flags);
97
98         dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n",
99                 tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
100                 tm->tm_hour, tm->tm_min, tm->tm_sec);
101         return 0;
102 }
103
104 static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
105 {
106         struct platform_device *pdev = to_platform_device(dev);
107         struct m48t59_plat_data *pdata = pdev->dev.platform_data;
108         struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
109         unsigned long flags;
110         u8 val = 0;
111
112         dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d/%02d/%02d\n",
113                 tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
114                 tm->tm_hour, tm->tm_min, tm->tm_sec);
115
116         spin_lock_irqsave(&m48t59->lock, flags);
117         /* Issue the WRITE command */
118         M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
119
120         M48T59_WRITE((BIN2BCD(tm->tm_sec) & 0x7F), M48T59_SEC);
121         M48T59_WRITE((BIN2BCD(tm->tm_min) & 0x7F), M48T59_MIN);
122         M48T59_WRITE((BIN2BCD(tm->tm_hour) & 0x3F), M48T59_HOUR);
123         M48T59_WRITE((BIN2BCD(tm->tm_mday) & 0x3F), M48T59_MDAY);
124         /* tm_mon is 0-11 */
125         M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH);
126         M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR);
127
128         if (tm->tm_year/100)
129                 val = (M48T59_WDAY_CEB | M48T59_WDAY_CB);
130         val |= (BIN2BCD(tm->tm_wday) & 0x07);
131         M48T59_WRITE(val, M48T59_WDAY);
132
133         /* Clear the WRITE bit */
134         M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
135         spin_unlock_irqrestore(&m48t59->lock, flags);
136         return 0;
137 }
138
139 /*
140  * Read alarm time and date in RTC
141  */
142 static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
143 {
144         struct platform_device *pdev = to_platform_device(dev);
145         struct m48t59_plat_data *pdata = pdev->dev.platform_data;
146         struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
147         struct rtc_time *tm = &alrm->time;
148         unsigned long flags;
149         u8 val;
150
151         /* If no irq, we don't support ALARM */
152         if (m48t59->irq == NO_IRQ)
153                 return -EIO;
154
155         spin_lock_irqsave(&m48t59->lock, flags);
156         /* Issue the READ command */
157         M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
158
159         tm->tm_year = BCD2BIN(M48T59_READ(M48T59_YEAR));
160         /* tm_mon is 0-11 */
161         tm->tm_mon = BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1;
162
163         val = M48T59_READ(M48T59_WDAY);
164         if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB))
165                 tm->tm_year += 100;     /* one century */
166
167         tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_ALARM_DATE));
168         tm->tm_hour = BCD2BIN(M48T59_READ(M48T59_ALARM_HOUR));
169         tm->tm_min = BCD2BIN(M48T59_READ(M48T59_ALARM_MIN));
170         tm->tm_sec = BCD2BIN(M48T59_READ(M48T59_ALARM_SEC));
171
172         /* Clear the READ bit */
173         M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
174         spin_unlock_irqrestore(&m48t59->lock, flags);
175
176         dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d/%02d/%02d\n",
177                 tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
178                 tm->tm_hour, tm->tm_min, tm->tm_sec);
179         return 0;
180 }
181
182 /*
183  * Set alarm time and date in RTC
184  */
185 static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
186 {
187         struct platform_device *pdev = to_platform_device(dev);
188         struct m48t59_plat_data *pdata = pdev->dev.platform_data;
189         struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
190         struct rtc_time *tm = &alrm->time;
191         u8 mday, hour, min, sec;
192         unsigned long flags;
193
194         /* If no irq, we don't support ALARM */
195         if (m48t59->irq == NO_IRQ)
196                 return -EIO;
197
198         /*
199          * 0xff means "always match"
200          */
201         mday = tm->tm_mday;
202         mday = (mday >= 1 && mday <= 31) ? BIN2BCD(mday) : 0xff;
203         if (mday == 0xff)
204                 mday = M48T59_READ(M48T59_MDAY);
205
206         hour = tm->tm_hour;
207         hour = (hour < 24) ? BIN2BCD(hour) : 0x00;
208
209         min = tm->tm_min;
210         min = (min < 60) ? BIN2BCD(min) : 0x00;
211
212         sec = tm->tm_sec;
213         sec = (sec < 60) ? BIN2BCD(sec) : 0x00;
214
215         spin_lock_irqsave(&m48t59->lock, flags);
216         /* Issue the WRITE command */
217         M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
218
219         M48T59_WRITE(mday, M48T59_ALARM_DATE);
220         M48T59_WRITE(hour, M48T59_ALARM_HOUR);
221         M48T59_WRITE(min, M48T59_ALARM_MIN);
222         M48T59_WRITE(sec, M48T59_ALARM_SEC);
223
224         /* Clear the WRITE bit */
225         M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
226         spin_unlock_irqrestore(&m48t59->lock, flags);
227
228         dev_dbg(dev, "RTC set alarm time %04d-%02d-%02d %02d/%02d/%02d\n",
229                 tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
230                 tm->tm_hour, tm->tm_min, tm->tm_sec);
231         return 0;
232 }
233
234 /*
235  * Handle commands from user-space
236  */
237 static int m48t59_rtc_ioctl(struct device *dev, unsigned int cmd,
238                         unsigned long arg)
239 {
240         struct platform_device *pdev = to_platform_device(dev);
241         struct m48t59_plat_data *pdata = pdev->dev.platform_data;
242         struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
243         unsigned long flags;
244         int ret = 0;
245
246         spin_lock_irqsave(&m48t59->lock, flags);
247         switch (cmd) {
248         case RTC_AIE_OFF:       /* alarm interrupt off */
249                 M48T59_WRITE(0x00, M48T59_INTR);
250                 break;
251         case RTC_AIE_ON:        /* alarm interrupt on */
252                 M48T59_WRITE(M48T59_INTR_AFE, M48T59_INTR);
253                 break;
254         default:
255                 ret = -ENOIOCTLCMD;
256                 break;
257         }
258         spin_unlock_irqrestore(&m48t59->lock, flags);
259
260         return ret;
261 }
262
263 static int m48t59_rtc_proc(struct device *dev, struct seq_file *seq)
264 {
265         struct platform_device *pdev = to_platform_device(dev);
266         struct m48t59_plat_data *pdata = pdev->dev.platform_data;
267         struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
268         unsigned long flags;
269         u8 val;
270
271         spin_lock_irqsave(&m48t59->lock, flags);
272         val = M48T59_READ(M48T59_FLAGS);
273         spin_unlock_irqrestore(&m48t59->lock, flags);
274
275         seq_printf(seq, "battery\t\t: %s\n",
276                  (val & M48T59_FLAGS_BF) ? "low" : "normal");
277         return 0;
278 }
279
280 /*
281  * IRQ handler for the RTC
282  */
283 static irqreturn_t m48t59_rtc_interrupt(int irq, void *dev_id)
284 {
285         struct device *dev = (struct device *)dev_id;
286         struct platform_device *pdev = to_platform_device(dev);
287         struct m48t59_plat_data *pdata = pdev->dev.platform_data;
288         struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
289         u8 event;
290
291         spin_lock(&m48t59->lock);
292         event = M48T59_READ(M48T59_FLAGS);
293         spin_unlock(&m48t59->lock);
294
295         if (event & M48T59_FLAGS_AF) {
296                 rtc_update_irq(m48t59->rtc, 1, (RTC_AF | RTC_IRQF));
297                 return IRQ_HANDLED;
298         }
299
300         return IRQ_NONE;
301 }
302
303 static const struct rtc_class_ops m48t59_rtc_ops = {
304         .ioctl          = m48t59_rtc_ioctl,
305         .read_time      = m48t59_rtc_read_time,
306         .set_time       = m48t59_rtc_set_time,
307         .read_alarm     = m48t59_rtc_readalarm,
308         .set_alarm      = m48t59_rtc_setalarm,
309         .proc           = m48t59_rtc_proc,
310 };
311
312 static ssize_t m48t59_nvram_read(struct kobject *kobj,
313                                 struct bin_attribute *bin_attr,
314                                 char *buf, loff_t pos, size_t size)
315 {
316         struct device *dev = container_of(kobj, struct device, kobj);
317         struct platform_device *pdev = to_platform_device(dev);
318         struct m48t59_plat_data *pdata = pdev->dev.platform_data;
319         struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
320         ssize_t cnt = 0;
321         unsigned long flags;
322
323         for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) {
324                 spin_lock_irqsave(&m48t59->lock, flags);
325                 *buf++ = M48T59_READ(cnt);
326                 spin_unlock_irqrestore(&m48t59->lock, flags);
327         }
328
329         return cnt;
330 }
331
332 static ssize_t m48t59_nvram_write(struct kobject *kobj,
333                                 struct bin_attribute *bin_attr,
334                                 char *buf, loff_t pos, size_t size)
335 {
336         struct device *dev = container_of(kobj, struct device, kobj);
337         struct platform_device *pdev = to_platform_device(dev);
338         struct m48t59_plat_data *pdata = pdev->dev.platform_data;
339         struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
340         ssize_t cnt = 0;
341         unsigned long flags;
342
343         for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) {
344                 spin_lock_irqsave(&m48t59->lock, flags);
345                 M48T59_WRITE(*buf++, cnt);
346                 spin_unlock_irqrestore(&m48t59->lock, flags);
347         }
348
349         return cnt;
350 }
351
352 static struct bin_attribute m48t59_nvram_attr = {
353         .attr = {
354                 .name = "nvram",
355                 .mode = S_IRUGO | S_IWUSR,
356                 .owner = THIS_MODULE,
357         },
358         .read = m48t59_nvram_read,
359         .write = m48t59_nvram_write,
360         .size = M48T59_NVRAM_SIZE,
361 };
362
363 static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
364 {
365         struct m48t59_plat_data *pdata = pdev->dev.platform_data;
366         struct m48t59_private *m48t59 = NULL;
367         struct resource *res;
368         int ret = -ENOMEM;
369
370         /* This chip could be memory-mapped or I/O-mapped */
371         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
372         if (!res) {
373                 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
374                 if (!res)
375                         return -EINVAL;
376         }
377
378         if (res->flags & IORESOURCE_IO) {
379                 /* If we are I/O-mapped, the platform should provide
380                  * the operations accessing chip registers.
381                  */
382                 if (!pdata || !pdata->write_byte || !pdata->read_byte)
383                         return -EINVAL;
384         } else if (res->flags & IORESOURCE_MEM) {
385                 /* we are memory-mapped */
386                 if (!pdata) {
387                         pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
388                         if (!pdata)
389                                 return -ENOMEM;
390                         /* Ensure we only kmalloc platform data once */
391                         pdev->dev.platform_data = pdata;
392                 }
393
394                 /* Try to use the generic memory read/write ops */
395                 if (!pdata->write_byte)
396                         pdata->write_byte = m48t59_mem_writeb;
397                 if (!pdata->read_byte)
398                         pdata->read_byte = m48t59_mem_readb;
399         }
400
401         m48t59 = kzalloc(sizeof(*m48t59), GFP_KERNEL);
402         if (!m48t59)
403                 return -ENOMEM;
404
405         m48t59->ioaddr = ioremap(res->start, res->end - res->start + 1);
406         if (!m48t59->ioaddr)
407                 goto out;
408
409         /* Try to get irq number. We also can work in
410          * the mode without IRQ.
411          */
412         m48t59->irq = platform_get_irq(pdev, 0);
413         if (m48t59->irq < 0)
414                 m48t59->irq = NO_IRQ;
415
416         if (m48t59->irq != NO_IRQ) {
417                 ret = request_irq(m48t59->irq, m48t59_rtc_interrupt,
418                         IRQF_SHARED, "rtc-m48t59", &pdev->dev);
419                 if (ret)
420                         goto out;
421         }
422
423         m48t59->rtc = rtc_device_register("m48t59", &pdev->dev,
424                                 &m48t59_rtc_ops, THIS_MODULE);
425         if (IS_ERR(m48t59->rtc)) {
426                 ret = PTR_ERR(m48t59->rtc);
427                 goto out;
428         }
429
430         ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
431         if (ret)
432                 goto out;
433
434         spin_lock_init(&m48t59->lock);
435         platform_set_drvdata(pdev, m48t59);
436         return 0;
437
438 out:
439         if (!IS_ERR(m48t59->rtc))
440                 rtc_device_unregister(m48t59->rtc);
441         if (m48t59->irq != NO_IRQ)
442                 free_irq(m48t59->irq, &pdev->dev);
443         if (m48t59->ioaddr)
444                 iounmap(m48t59->ioaddr);
445         if (m48t59)
446                 kfree(m48t59);
447         return ret;
448 }
449
450 static int __devexit m48t59_rtc_remove(struct platform_device *pdev)
451 {
452         struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
453
454         sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
455         if (!IS_ERR(m48t59->rtc))
456                 rtc_device_unregister(m48t59->rtc);
457         if (m48t59->ioaddr)
458                 iounmap(m48t59->ioaddr);
459         if (m48t59->irq != NO_IRQ)
460                 free_irq(m48t59->irq, &pdev->dev);
461         platform_set_drvdata(pdev, NULL);
462         kfree(m48t59);
463         return 0;
464 }
465
466 /* work with hotplug and coldplug */
467 MODULE_ALIAS("platform:rtc-m48t59");
468
469 static struct platform_driver m48t59_rtc_driver = {
470         .driver         = {
471                 .name   = "rtc-m48t59",
472                 .owner  = THIS_MODULE,
473         },
474         .probe          = m48t59_rtc_probe,
475         .remove         = __devexit_p(m48t59_rtc_remove),
476 };
477
478 static int __init m48t59_rtc_init(void)
479 {
480         return platform_driver_register(&m48t59_rtc_driver);
481 }
482
483 static void __exit m48t59_rtc_exit(void)
484 {
485         platform_driver_unregister(&m48t59_rtc_driver);
486 }
487
488 module_init(m48t59_rtc_init);
489 module_exit(m48t59_rtc_exit);
490
491 MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>");
492 MODULE_DESCRIPTION("M48T59 RTC driver");
493 MODULE_LICENSE("GPL");