]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/cbus/retu-rtc.c
6471e7ed0c34102dcac1e0982be418ff9c918407
[linux-2.6-omap-h63xx.git] / drivers / cbus / retu-rtc.c
1 /**
2  * drivers/cbus/retu-rtc.c
3  *
4  * Support for Retu RTC
5  *
6  * Copyright (C) 2004, 2005 Nokia Corporation
7  *
8  * Written by Paul Mundt <paul.mundt@nokia.com> and
9  *            Igor Stoppa <igor.stoppa@nokia.com>
10  *
11  * The Retu RTC is essentially a partial read-only RTC that gives us Retu's
12  * idea of what time actually is. It's left as a userspace excercise to map
13  * this back to time in the real world and ensure that calibration settings
14  * are sane to compensate for any horrible drift (on account of not being able
15  * to set the clock to anything).
16  *
17  * Days are semi-writeable. Namely, Retu will only track 255 days for us
18  * consecutively, after which the counter is explicitly stuck at 255 until
19  * someone comes along and clears it with a write. In the event that no one
20  * comes along and clears it, we no longer have any idea what day it is.
21  *
22  * This file is subject to the terms and conditions of the GNU General
23  * Public License. See the file "COPYING" in the main directory of this
24  * archive for more details.
25  *
26  * This program is distributed in the hope that it will be useful,
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29  * GNU General Public License for more details.
30  *
31  * You should have received a copy of the GNU General Public License
32  * along with this program; if not, write to the Free Software
33  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
34  */
35
36 #include <linux/device.h>
37 #include <linux/init.h>
38 #include <linux/kernel.h>
39 #include <linux/module.h>
40 #include <linux/completion.h>
41 #include <linux/platform_device.h>
42 #include <asm/semaphore.h>
43
44 #include "cbus.h"
45 #include "retu.h"
46
47 static struct semaphore retu_rtc_sem;
48 static u16 retu_rtc_alarm_expired;
49 static u16 retu_rtc_reset_occurred;
50
51 static DECLARE_COMPLETION(retu_rtc_exited);
52 static DECLARE_COMPLETION(retu_rtc_sync);
53
54 static void retu_rtc_barrier(void);
55
56 static void retu_rtc_device_release(struct device *dev)
57 {
58         complete(&retu_rtc_exited);
59 }
60
61 static ssize_t retu_rtc_time_show(struct device *dev, struct device_attribute *attr,
62                                   char *buf)
63 {
64         u16 dsr, hmr, dsr2;
65
66         down(&retu_rtc_sem);
67
68         do {
69                 u16 dummy;
70
71                 /*
72                  * Not being in_interrupt() for a retu rtc IRQ, we need to
73                  * read twice for consistency..
74                  */
75                 dummy   = retu_read_reg(RETU_REG_RTCDSR);
76                 dsr     = retu_read_reg(RETU_REG_RTCDSR);
77
78                 dummy   = retu_read_reg(RETU_REG_RTCHMR);
79                 hmr     = retu_read_reg(RETU_REG_RTCHMR);
80
81                 dummy   = retu_read_reg(RETU_REG_RTCDSR);
82                 dsr2    = retu_read_reg(RETU_REG_RTCDSR);
83         } while ((dsr != dsr2));
84
85         up(&retu_rtc_sem);
86
87         /*
88          * Format a 32-bit date-string for userspace
89          *
90          * days | hours | minutes | seconds
91          *
92          * 8 bits for each.
93          *
94          * This mostly sucks because days and seconds are tracked in RTCDSR
95          * while hours and minutes are tracked in RTCHMR. And yes, there
96          * really are no words that can describe an 8 bit day register (or
97          * rather, none that will be reprinted here).
98          */
99         return sprintf(buf, "0x%08x\n", (((dsr >> 8) & 0xff) << 24) |
100                                         (((hmr >> 8) & 0x1f) << 16) |
101                                          ((hmr & 0x3f) << 8) | (dsr & 0x3f));
102 }
103
104 static ssize_t retu_rtc_time_store(struct device *dev, struct device_attribute *attr,
105                                    const char *buf, size_t count)
106 {
107         down(&retu_rtc_sem);
108         /*
109          * Writing anything to the day counter forces it to 0
110          * The seconds counter would be cleared by resetting the minutes counter,
111          * however this won't happen, since we are using the hh:mm counters as
112          * a set of free running counters and the day counter as a multiple
113          * overflow holder.
114          */
115
116         /* Reset day counter, but keep Temperature Shutdown state */
117         retu_write_reg(RETU_REG_RTCDSR,
118                        retu_read_reg(RETU_REG_RTCDSR) & (1 << 6));
119
120         up(&retu_rtc_sem);
121
122         return count;
123 }
124
125 static DEVICE_ATTR(time, S_IRUGO | S_IWUSR, retu_rtc_time_show,
126                    retu_rtc_time_store);
127
128
129 static ssize_t retu_rtc_reset_show(struct device *dev, struct device_attribute *attr, char *buf)
130 {
131         /*
132          * Returns the status of the rtc
133          *
134          * 0: no reset has occurred or the status has been cleared
135          * 1: a reset has occurred
136          *
137          * RTC needs to be reset only when both main battery
138          * _AND_ backup battery are discharged
139          */
140         return sprintf(buf, "%u\n", retu_rtc_reset_occurred);
141 }
142
143 static void retu_rtc_do_reset(void)
144 {
145         u16 ccr1;
146
147         ccr1 = retu_read_reg(RETU_REG_CC1);
148         /* RTC in reset */
149         retu_write_reg(RETU_REG_CC1, ccr1 | 0x0001);
150         /* RTC in normal operating mode */
151         retu_write_reg(RETU_REG_CC1, ccr1 & ~0x0001);
152
153         retu_rtc_barrier();
154         /* Disable alarm and RTC WD */
155         retu_write_reg(RETU_REG_RTCHMAR, 0x7f3f);
156         /* Set Calibration register to default value */
157         retu_write_reg(RETU_REG_RTCCALR, 0x00c0);
158
159         retu_rtc_alarm_expired = 0;
160         retu_rtc_reset_occurred = 1;
161 }
162
163 static ssize_t retu_rtc_reset_store(struct device *dev, struct device_attribute *attr,
164                                     const char *buf, size_t count)
165 {
166         unsigned choice;
167
168         if(sscanf(buf, "%u", &choice) != 1)
169                 return count;
170         down(&retu_rtc_sem);
171         if (choice == 0)
172                 retu_rtc_reset_occurred = 0;
173         else if (choice == 1)
174                 retu_rtc_do_reset();
175         up(&retu_rtc_sem);
176         return count;
177 }
178
179 static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, retu_rtc_reset_show,
180                    retu_rtc_reset_store);
181
182 static ssize_t retu_rtc_alarm_show(struct device *dev, struct device_attribute *attr,
183                                    char *buf)
184 {
185         u16 chmar;
186         ssize_t retval;
187
188         down(&retu_rtc_sem);
189         /*
190          * Format a 16-bit date-string for userspace
191          *
192          * hours | minutes
193          * 8 bits for each.
194          */
195         chmar = retu_read_reg(RETU_REG_RTCHMAR);
196         /* No shifting needed, only masking unrelated bits */
197         retval = sprintf(buf, "0x%04x\n", chmar & 0x1f3f);
198         up(&retu_rtc_sem);
199
200         return retval;
201 }
202
203 static ssize_t retu_rtc_alarm_store(struct device *dev, struct device_attribute *attr,
204                                     const char *buf, size_t count)
205 {
206         u16 chmar;
207         unsigned alrm;
208         unsigned hours;
209         unsigned minutes;
210
211         down(&retu_rtc_sem);
212
213         if(sscanf(buf, "%x", &alrm) != 1)
214                 return count;
215         hours = (alrm >> 8) & 0x001f;
216         minutes = (alrm >> 0) & 0x003f;
217         if ((hours < 24 && minutes < 60) || (hours == 24 && minutes == 60)) {
218                 /*
219                  * OK, the time format for the alarm is valid (including the
220                  * disabling values)
221                  */
222                 /* Keeps the RTC watchdog status */
223                 chmar = retu_read_reg(RETU_REG_RTCHMAR) & 0x6000;
224                 chmar |= alrm & 0x1f3f; /* Stores the requested alarm */
225                 retu_rtc_barrier();
226                 retu_write_reg(RETU_REG_RTCHMAR, chmar);
227                 /* If the alarm is being disabled */
228                 if (hours == 24 && minutes == 60) {
229                         /* disable the interrupt */
230                         retu_disable_irq(RETU_INT_RTCA);
231                         retu_rtc_alarm_expired = 0;
232                 } else
233                         /* enable the interrupt */
234                         retu_enable_irq(RETU_INT_RTCA);
235         }
236         up(&retu_rtc_sem);
237
238         return count;
239 }
240
241 static DEVICE_ATTR(alarm, S_IRUGO | S_IWUSR, retu_rtc_alarm_show,
242                    retu_rtc_alarm_store);
243
244 static ssize_t retu_rtc_alarm_expired_show(struct device *dev, struct device_attribute *attr,
245                                            char *buf)
246 {
247         ssize_t retval;
248
249         retval = sprintf(buf, "%u\n", retu_rtc_alarm_expired);
250
251         return retval;
252 }
253
254 static ssize_t retu_rtc_alarm_expired_store(struct device *dev, struct device_attribute *attr,
255                                             const char *buf, size_t count)
256 {
257         retu_rtc_alarm_expired = 0;
258
259         return count;
260 }
261
262 static DEVICE_ATTR(alarm_expired, S_IRUGO | S_IWUSR, retu_rtc_alarm_expired_show,
263                    retu_rtc_alarm_expired_store);
264
265
266 static ssize_t retu_rtc_cal_show(struct device *dev, struct device_attribute *attr,
267                                  char *buf)
268 {
269         u16 rtccalr1;
270
271         down(&retu_rtc_sem);
272         rtccalr1 = retu_read_reg(RETU_REG_RTCCALR);
273         up(&retu_rtc_sem);
274
275         /*
276          * Shows the status of the Calibration Register.
277          *
278          * Default, after power loss: 0x0000
279          * Default, for R&D: 0x00C0
280          * Default, for factory: 0x00??
281          *
282          */
283         return sprintf(buf, "0x%04x\n", rtccalr1 & 0x00ff);
284 }
285
286 static ssize_t retu_rtc_cal_store(struct device *dev, struct device_attribute *attr,
287                                   const char *buf, size_t count)
288 {
289         unsigned calibration_value;
290
291         if (sscanf(buf, "%x", &calibration_value) != 1)
292                 return count;
293
294         down(&retu_rtc_sem);
295         retu_rtc_barrier();
296         retu_write_reg(RETU_REG_RTCCALR, calibration_value & 0x00ff);
297         up(&retu_rtc_sem);
298
299         return count;
300 }
301
302 static DEVICE_ATTR(cal, S_IRUGO | S_IWUSR, retu_rtc_cal_show,
303                    retu_rtc_cal_store);
304
305 static struct device_driver retu_rtc_driver;
306
307 static void retu_rtca_disable(void)
308 {
309         retu_disable_irq(RETU_INT_RTCA);
310         retu_rtc_alarm_expired = 1;
311         retu_rtc_barrier();
312         retu_write_reg(RETU_REG_RTCHMAR, (24 << 8) | 60);
313 }
314
315 static void retu_rtca_expired(void *data)
316 {
317         retu_rtca_disable();
318         kobject_uevent(&retu_rtc_driver.kobj, KOBJ_CHANGE);
319 }
320
321 DECLARE_WORK(retu_rtca_work, retu_rtca_expired, NULL);
322
323 /*
324  * RTCHMR RTCHMAR RTCCAL must be accessed within 0.9 s since the seconds
325  * interrupt has been signaled in the IDR register
326  */
327 static void retu_rtcs_interrupt(unsigned long unused)
328 {
329         retu_ack_irq(RETU_INT_RTCS);
330         complete(&retu_rtc_sync);
331 }
332
333 static void retu_rtca_interrupt(unsigned long unused)
334 {
335         retu_ack_irq(RETU_INT_RTCA);
336         schedule_work(&retu_rtca_work);
337 }
338
339 static int retu_rtc_init_irq(void)
340 {
341         int ret;
342
343         ret = retu_request_irq(RETU_INT_RTCS, retu_rtcs_interrupt, 0, "RTCS");
344         if (ret != 0)
345                 return ret;
346         /*
347          * We will take care of enabling and disabling the interrupt
348          * elsewhere, so leave it off by default..
349          */
350         retu_disable_irq(RETU_INT_RTCS);
351
352         ret = retu_request_irq(RETU_INT_RTCA, retu_rtca_interrupt, 0, "RTCA");
353         if (ret != 0) {
354                 retu_free_irq(RETU_INT_RTCS);
355                 return ret;
356         }
357         retu_disable_irq(RETU_INT_RTCA);
358
359         return 0;
360 }
361
362
363 static int __devinit retu_rtc_probe(struct device *dev)
364 {
365         int r;
366
367         retu_rtc_alarm_expired = retu_read_reg(RETU_REG_IDR) &
368                                                (0x1 << RETU_INT_RTCA);
369
370         if ((r = retu_rtc_init_irq()) != 0)
371                 return r;
372
373         init_MUTEX(&retu_rtc_sem);
374
375         /* If the calibration register is zero, we've probably lost
376          * power */
377         if (retu_read_reg(RETU_REG_RTCCALR) & 0x00ff)
378                 retu_rtc_reset_occurred = 0;
379         else
380                 retu_rtc_do_reset();
381
382         if ((r = device_create_file(dev, &dev_attr_time)) != 0)
383                 return r;
384         else if ((r = device_create_file(dev, &dev_attr_reset)) != 0)
385                 goto err_unregister_time;
386         else if ((r = device_create_file(dev, &dev_attr_alarm)) != 0)
387                 goto err_unregister_reset;
388         else if ((r = device_create_file(dev, &dev_attr_alarm_expired)) != 0)
389                 goto err_unregister_alarm;
390         else if ((r = device_create_file(dev, &dev_attr_cal)) != 0)
391                 goto err_unregister_alarm_expired;
392         else
393                 return r;
394
395 err_unregister_alarm_expired:
396         device_remove_file(dev, &dev_attr_alarm_expired);
397 err_unregister_alarm:
398         device_remove_file(dev, &dev_attr_alarm);
399 err_unregister_reset:
400         device_remove_file(dev, &dev_attr_reset);
401 err_unregister_time:
402         device_remove_file(dev, &dev_attr_time);
403         return r;
404 }
405
406 static int __devexit retu_rtc_remove(struct device *dev)
407 {
408         retu_disable_irq(RETU_INT_RTCS);
409         retu_free_irq(RETU_INT_RTCS);
410         retu_free_irq(RETU_INT_RTCA);
411         device_remove_file(dev, &dev_attr_cal);
412         device_remove_file(dev, &dev_attr_alarm_expired);
413         device_remove_file(dev, &dev_attr_alarm);
414         device_remove_file(dev, &dev_attr_reset);
415         device_remove_file(dev, &dev_attr_time);
416         return 0;
417 }
418
419 static struct device_driver retu_rtc_driver = {
420         .name           = "retu-rtc",
421         .bus            = &platform_bus_type,
422         .probe          = retu_rtc_probe,
423         .remove         = __devexit_p(retu_rtc_remove),
424 };
425
426 static struct platform_device retu_rtc_device = {
427         .name           = "retu-rtc",
428         .id             = -1,
429         .dev            = {
430                 .release        = retu_rtc_device_release,
431         },
432 };
433
434 /* This function provides syncronization with the RTCS interrupt handler */
435 static void retu_rtc_barrier(void)
436 {
437         init_completion(&retu_rtc_sync);
438         retu_ack_irq(RETU_INT_RTCS);
439         retu_enable_irq(RETU_INT_RTCS);
440         wait_for_completion(&retu_rtc_sync);
441         retu_disable_irq(RETU_INT_RTCS);
442 }
443
444 static int __init retu_rtc_init(void)
445 {
446         int ret;
447
448         init_completion(&retu_rtc_exited);
449
450         if ((ret = driver_register(&retu_rtc_driver)) != 0)
451                 return ret;
452
453         if ((ret = platform_device_register(&retu_rtc_device)) != 0)
454                 goto err_unregister_driver;
455
456         return 0;
457
458 err_unregister_driver:
459         driver_unregister(&retu_rtc_driver);
460         return ret;
461 }
462
463 static void __exit retu_rtc_exit(void)
464 {
465         platform_device_unregister(&retu_rtc_device);
466         driver_unregister(&retu_rtc_driver);
467
468         wait_for_completion(&retu_rtc_exited);
469 }
470
471 module_init(retu_rtc_init);
472 module_exit(retu_rtc_exit);
473
474 MODULE_DESCRIPTION("Retu RTC");
475 MODULE_LICENSE("GPL");
476 MODULE_AUTHOR("Paul Mundt and Igor Stoppa");