]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/rtc/rtc-bfin.c
Blackfin RTC driver: the frequency function is in units of Hz, not units of seconds...
[linux-2.6-omap-h63xx.git] / drivers / rtc / rtc-bfin.c
1 /*
2  * Blackfin On-Chip Real Time Clock Driver
3  *  Supports BF53[123]/BF53[467]/BF54[2489]
4  *
5  * Copyright 2004-2007 Analog Devices Inc.
6  *
7  * Enter bugs at http://blackfin.uclinux.org/
8  *
9  * Licensed under the GPL-2 or later.
10  */
11
12 /* The biggest issue we deal with in this driver is that register writes are
13  * synced to the RTC frequency of 1Hz.  So if you write to a register and
14  * attempt to write again before the first write has completed, the new write
15  * is simply discarded.  This can easily be troublesome if userspace disables
16  * one event (say periodic) and then right after enables an event (say alarm).
17  * Since all events are maintained in the same interrupt mask register, if
18  * we wrote to it to disable the first event and then wrote to it again to
19  * enable the second event, that second event would not be enabled as the
20  * write would be discarded and things quickly fall apart.
21  *
22  * To keep this delay from significantly degrading performance (we, in theory,
23  * would have to sleep for up to 1 second everytime we wanted to write a
24  * register), we only check the write pending status before we start to issue
25  * a new write.  We bank on the idea that it doesnt matter when the sync
26  * happens so long as we don't attempt another write before it does.  The only
27  * time userspace would take this penalty is when they try and do multiple
28  * operations right after another ... but in this case, they need to take the
29  * sync penalty, so we should be OK.
30  *
31  * Also note that the RTC_ISTAT register does not suffer this penalty; its
32  * writes to clear status registers complete immediately.
33  */
34
35 #include <linux/module.h>
36 #include <linux/kernel.h>
37 #include <linux/bcd.h>
38 #include <linux/rtc.h>
39 #include <linux/init.h>
40 #include <linux/platform_device.h>
41 #include <linux/seq_file.h>
42 #include <linux/interrupt.h>
43 #include <linux/spinlock.h>
44 #include <linux/delay.h>
45
46 #include <asm/blackfin.h>
47
48 #define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __FUNCTION__, __LINE__, ## args)
49 #define stampit() stamp("here i am")
50
51 struct bfin_rtc {
52         struct rtc_device *rtc_dev;
53         struct rtc_time rtc_alarm;
54         spinlock_t lock;
55 };
56
57 /* Bit values for the ISTAT / ICTL registers */
58 #define RTC_ISTAT_WRITE_COMPLETE  0x8000
59 #define RTC_ISTAT_WRITE_PENDING   0x4000
60 #define RTC_ISTAT_ALARM_DAY       0x0040
61 #define RTC_ISTAT_24HR            0x0020
62 #define RTC_ISTAT_HOUR            0x0010
63 #define RTC_ISTAT_MIN             0x0008
64 #define RTC_ISTAT_SEC             0x0004
65 #define RTC_ISTAT_ALARM           0x0002
66 #define RTC_ISTAT_STOPWATCH       0x0001
67
68 /* Shift values for RTC_STAT register */
69 #define DAY_BITS_OFF    17
70 #define HOUR_BITS_OFF   12
71 #define MIN_BITS_OFF    6
72 #define SEC_BITS_OFF    0
73
74 /* Some helper functions to convert between the common RTC notion of time
75  * and the internal Blackfin notion that is encoded in 32bits.
76  */
77 static inline u32 rtc_time_to_bfin(unsigned long now)
78 {
79         u32 sec  = (now % 60);
80         u32 min  = (now % (60 * 60)) / 60;
81         u32 hour = (now % (60 * 60 * 24)) / (60 * 60);
82         u32 days = (now / (60 * 60 * 24));
83         return (sec  << SEC_BITS_OFF) +
84                (min  << MIN_BITS_OFF) +
85                (hour << HOUR_BITS_OFF) +
86                (days << DAY_BITS_OFF);
87 }
88 static inline unsigned long rtc_bfin_to_time(u32 rtc_bfin)
89 {
90         return (((rtc_bfin >> SEC_BITS_OFF)  & 0x003F)) +
91                (((rtc_bfin >> MIN_BITS_OFF)  & 0x003F) * 60) +
92                (((rtc_bfin >> HOUR_BITS_OFF) & 0x001F) * 60 * 60) +
93                (((rtc_bfin >> DAY_BITS_OFF)  & 0x7FFF) * 60 * 60 * 24);
94 }
95 static inline void rtc_bfin_to_tm(u32 rtc_bfin, struct rtc_time *tm)
96 {
97         rtc_time_to_tm(rtc_bfin_to_time(rtc_bfin), tm);
98 }
99
100 /* Wait for the previous write to a RTC register to complete.
101  * Unfortunately, we can't sleep here as that introduces a race condition when
102  * turning on interrupt events.  Consider this:
103  *  - process sets alarm
104  *  - process enables alarm
105  *  - process sleeps while waiting for rtc write to sync
106  *  - interrupt fires while process is sleeping
107  *  - interrupt acks the event by writing to ISTAT
108  *  - interrupt sets the WRITE PENDING bit
109  *  - interrupt handler finishes
110  *  - process wakes up, sees WRITE PENDING bit set, goes to sleep
111  *  - interrupt fires while process is sleeping
112  * If anyone can point out the obvious solution here, i'm listening :).  This
113  * shouldn't be an issue on an SMP or preempt system as this function should
114  * only be called with the rtc lock held.
115  *
116  * Other options:
117  *  - disable PREN so the sync happens at 32.768kHZ ... but this changes the
118  *    inc rate for all RTC registers from 1HZ to 32.768kHZ ...
119  *  - use the write complete IRQ
120  */
121 static void rtc_bfin_sync_pending(void)
122 {
123         stampit();
124         while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_COMPLETE)) {
125                 if (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING))
126                         break;
127         }
128         bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE);
129 }
130
131 static void rtc_bfin_reset(struct bfin_rtc *rtc)
132 {
133         /* Initialize the RTC. Enable pre-scaler to scale RTC clock
134          * to 1Hz and clear interrupt/status registers. */
135         spin_lock_irq(&rtc->lock);
136         rtc_bfin_sync_pending();
137         bfin_write_RTC_PREN(0x1);
138         bfin_write_RTC_ICTL(0);
139         bfin_write_RTC_SWCNT(0);
140         bfin_write_RTC_ALARM(0);
141         bfin_write_RTC_ISTAT(0xFFFF);
142         spin_unlock_irq(&rtc->lock);
143 }
144
145 static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id)
146 {
147         struct platform_device *pdev = to_platform_device(dev_id);
148         struct bfin_rtc *rtc = platform_get_drvdata(pdev);
149         unsigned long events = 0;
150         u16 rtc_istat;
151
152         stampit();
153
154         spin_lock_irq(&rtc->lock);
155
156         rtc_istat = bfin_read_RTC_ISTAT();
157
158         if (rtc_istat & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) {
159                 bfin_write_RTC_ISTAT(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY);
160                 events |= RTC_AF | RTC_IRQF;
161         }
162
163         if (rtc_istat & RTC_ISTAT_STOPWATCH) {
164                 bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH);
165                 events |= RTC_PF | RTC_IRQF;
166                 bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq);
167         }
168
169         if (rtc_istat & RTC_ISTAT_SEC) {
170                 bfin_write_RTC_ISTAT(RTC_ISTAT_SEC);
171                 events |= RTC_UF | RTC_IRQF;
172         }
173
174         rtc_update_irq(rtc->rtc_dev, 1, events);
175
176         spin_unlock_irq(&rtc->lock);
177
178         return IRQ_HANDLED;
179 }
180
181 static int bfin_rtc_open(struct device *dev)
182 {
183         struct bfin_rtc *rtc = dev_get_drvdata(dev);
184         int ret;
185
186         stampit();
187
188         ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_DISABLED, "rtc-bfin", dev);
189         if (unlikely(ret)) {
190                 dev_err(dev, "request RTC IRQ failed with %d\n", ret);
191                 return ret;
192         }
193
194         rtc_bfin_reset(rtc);
195
196         return ret;
197 }
198
199 static void bfin_rtc_release(struct device *dev)
200 {
201         struct bfin_rtc *rtc = dev_get_drvdata(dev);
202         stampit();
203         rtc_bfin_reset(rtc);
204         free_irq(IRQ_RTC, dev);
205 }
206
207 static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
208 {
209         struct bfin_rtc *rtc = dev_get_drvdata(dev);
210
211         stampit();
212
213         switch (cmd) {
214         case RTC_PIE_ON:
215                 stampit();
216                 spin_lock_irq(&rtc->lock);
217                 rtc_bfin_sync_pending();
218                 bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH);
219                 bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq);
220                 bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | RTC_ISTAT_STOPWATCH);
221                 spin_unlock_irq(&rtc->lock);
222                 return 0;
223         case RTC_PIE_OFF:
224                 stampit();
225                 spin_lock_irq(&rtc->lock);
226                 rtc_bfin_sync_pending();
227                 bfin_write_RTC_SWCNT(0);
228                 bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~RTC_ISTAT_STOPWATCH);
229                 spin_unlock_irq(&rtc->lock);
230                 return 0;
231
232         case RTC_UIE_ON:
233                 stampit();
234                 spin_lock_irq(&rtc->lock);
235                 rtc_bfin_sync_pending();
236                 bfin_write_RTC_ISTAT(RTC_ISTAT_SEC);
237                 bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | RTC_ISTAT_SEC);
238                 spin_unlock_irq(&rtc->lock);
239                 return 0;
240         case RTC_UIE_OFF:
241                 stampit();
242                 spin_lock_irq(&rtc->lock);
243                 rtc_bfin_sync_pending();
244                 bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~RTC_ISTAT_SEC);
245                 spin_unlock_irq(&rtc->lock);
246                 return 0;
247
248         case RTC_AIE_ON: {
249                 unsigned long rtc_alarm;
250                 u16 which_alarm;
251                 int ret = 0;
252
253                 stampit();
254
255                 spin_lock_irq(&rtc->lock);
256
257                 rtc_bfin_sync_pending();
258                 if (rtc->rtc_alarm.tm_yday == -1) {
259                         struct rtc_time now;
260                         rtc_bfin_to_tm(bfin_read_RTC_STAT(), &now);
261                         now.tm_sec = rtc->rtc_alarm.tm_sec;
262                         now.tm_min = rtc->rtc_alarm.tm_min;
263                         now.tm_hour = rtc->rtc_alarm.tm_hour;
264                         ret = rtc_tm_to_time(&now, &rtc_alarm);
265                         which_alarm = RTC_ISTAT_ALARM;
266                 } else {
267                         ret = rtc_tm_to_time(&rtc->rtc_alarm, &rtc_alarm);
268                         which_alarm = RTC_ISTAT_ALARM_DAY;
269                 }
270                 if (ret == 0) {
271                         bfin_write_RTC_ISTAT(which_alarm);
272                         bfin_write_RTC_ALARM(rtc_time_to_bfin(rtc_alarm));
273                         bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | which_alarm);
274                 }
275
276                 spin_unlock_irq(&rtc->lock);
277
278                 return ret;
279         }
280         case RTC_AIE_OFF:
281                 stampit();
282                 spin_lock_irq(&rtc->lock);
283                 rtc_bfin_sync_pending();
284                 bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY));
285                 spin_unlock_irq(&rtc->lock);
286                 return 0;
287         }
288
289         return -ENOIOCTLCMD;
290 }
291
292 static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm)
293 {
294         struct bfin_rtc *rtc = dev_get_drvdata(dev);
295
296         stampit();
297
298         spin_lock_irq(&rtc->lock);
299         rtc_bfin_sync_pending();
300         rtc_bfin_to_tm(bfin_read_RTC_STAT(), tm);
301         spin_unlock_irq(&rtc->lock);
302
303         return 0;
304 }
305
306 static int bfin_rtc_set_time(struct device *dev, struct rtc_time *tm)
307 {
308         struct bfin_rtc *rtc = dev_get_drvdata(dev);
309         int ret;
310         unsigned long now;
311
312         stampit();
313
314         spin_lock_irq(&rtc->lock);
315
316         ret = rtc_tm_to_time(tm, &now);
317         if (ret == 0) {
318                 rtc_bfin_sync_pending();
319                 bfin_write_RTC_STAT(rtc_time_to_bfin(now));
320         }
321
322         spin_unlock_irq(&rtc->lock);
323
324         return ret;
325 }
326
327 static int bfin_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
328 {
329         struct bfin_rtc *rtc = dev_get_drvdata(dev);
330         stampit();
331         memcpy(&alrm->time, &rtc->rtc_alarm, sizeof(struct rtc_time));
332         alrm->pending = !!(bfin_read_RTC_ICTL() & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY));
333         return 0;
334 }
335
336 static int bfin_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
337 {
338         struct bfin_rtc *rtc = dev_get_drvdata(dev);
339         stampit();
340         memcpy(&rtc->rtc_alarm, &alrm->time, sizeof(struct rtc_time));
341         return 0;
342 }
343
344 static int bfin_rtc_proc(struct device *dev, struct seq_file *seq)
345 {
346 #define yesno(x) (x ? "yes" : "no")
347         u16 ictl = bfin_read_RTC_ICTL();
348         stampit();
349         seq_printf(seq, "alarm_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_ALARM));
350         seq_printf(seq, "wkalarm_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_ALARM_DAY));
351         seq_printf(seq, "seconds_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_SEC));
352         seq_printf(seq, "periodic_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_STOPWATCH));
353 #ifdef DEBUG
354         seq_printf(seq, "RTC_STAT\t: 0x%08X\n", bfin_read_RTC_STAT());
355         seq_printf(seq, "RTC_ICTL\t: 0x%04X\n", bfin_read_RTC_ICTL());
356         seq_printf(seq, "RTC_ISTAT\t: 0x%04X\n", bfin_read_RTC_ISTAT());
357         seq_printf(seq, "RTC_SWCNT\t: 0x%04X\n", bfin_read_RTC_SWCNT());
358         seq_printf(seq, "RTC_ALARM\t: 0x%08X\n", bfin_read_RTC_ALARM());
359         seq_printf(seq, "RTC_PREN\t: 0x%04X\n", bfin_read_RTC_PREN());
360 #endif
361         return 0;
362 }
363
364 /**
365  *      bfin_irq_set_freq - make sure hardware supports requested freq
366  *      @dev: pointer to RTC device structure
367  *      @freq: requested frequency rate
368  *
369  *      The Blackfin RTC can only generate periodic events at 1 per
370  *      second (1 Hz), so reject any attempt at changing it.
371  */
372 static int bfin_irq_set_freq(struct device *dev, int freq)
373 {
374         stampit();
375         return -ENOTTY;
376 }
377
378 static struct rtc_class_ops bfin_rtc_ops = {
379         .open          = bfin_rtc_open,
380         .release       = bfin_rtc_release,
381         .ioctl         = bfin_rtc_ioctl,
382         .read_time     = bfin_rtc_read_time,
383         .set_time      = bfin_rtc_set_time,
384         .read_alarm    = bfin_rtc_read_alarm,
385         .set_alarm     = bfin_rtc_set_alarm,
386         .proc          = bfin_rtc_proc,
387         .irq_set_freq  = bfin_irq_set_freq,
388 };
389
390 static int __devinit bfin_rtc_probe(struct platform_device *pdev)
391 {
392         struct bfin_rtc *rtc;
393         int ret = 0;
394
395         stampit();
396
397         rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
398         if (unlikely(!rtc))
399                 return -ENOMEM;
400
401         spin_lock_init(&rtc->lock);
402
403         rtc->rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &bfin_rtc_ops, THIS_MODULE);
404         if (unlikely(IS_ERR(rtc))) {
405                 ret = PTR_ERR(rtc->rtc_dev);
406                 goto err;
407         }
408         rtc->rtc_dev->irq_freq = 1;
409
410         platform_set_drvdata(pdev, rtc);
411
412         return 0;
413
414  err:
415         kfree(rtc);
416         return ret;
417 }
418
419 static int __devexit bfin_rtc_remove(struct platform_device *pdev)
420 {
421         struct bfin_rtc *rtc = platform_get_drvdata(pdev);
422
423         rtc_device_unregister(rtc->rtc_dev);
424         platform_set_drvdata(pdev, NULL);
425         kfree(rtc);
426
427         return 0;
428 }
429
430 static struct platform_driver bfin_rtc_driver = {
431         .driver         = {
432                 .name   = "rtc-bfin",
433                 .owner  = THIS_MODULE,
434         },
435         .probe          = bfin_rtc_probe,
436         .remove         = __devexit_p(bfin_rtc_remove),
437 };
438
439 static int __init bfin_rtc_init(void)
440 {
441         stampit();
442         return platform_driver_register(&bfin_rtc_driver);
443 }
444
445 static void __exit bfin_rtc_exit(void)
446 {
447         platform_driver_unregister(&bfin_rtc_driver);
448 }
449
450 module_init(bfin_rtc_init);
451 module_exit(bfin_rtc_exit);
452
453 MODULE_DESCRIPTION("Blackfin On-Chip Real Time Clock Driver");
454 MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
455 MODULE_LICENSE("GPL");