File: /usr/src/linux/arch/cris/drivers/ds1302.c
1 /*!***************************************************************************
2 *!
3 *! FILE NAME : ds1302.c
4 *!
5 *! DESCRIPTION: Implements an interface for the DS1302 RTC through Etrax I/O
6 *!
7 *! Functions exported: ds1302_readreg, ds1302_writereg, ds1302_init, get_rtc_status
8 *!
9 *! $Log: ds1302.c,v $
10 *! Revision 1.11 2001/06/14 12:35:52 jonashg
11 *! The ATA hack is back. It is unfortunately the only way to set g27 to output.
12 *!
13 *! Revision 1.9 2001/06/14 10:00:14 jonashg
14 *! No need for tempudelay to be inline anymore (had to adjust the usec to
15 *! loops conversion because of this to make it slow enough to be a udelay).
16 *!
17 *! Revision 1.8 2001/06/14 08:06:32 jonashg
18 *! Made tempudelay delay usecs (well, just a tad more).
19 *!
20 *! Revision 1.7 2001/06/13 14:18:11 jonashg
21 *! Only allow processes with SYS_TIME capability to set time and charge.
22 *!
23 *! Revision 1.6 2001/06/12 15:22:07 jonashg
24 *! * Made init function __init.
25 *! * Parameter to out_byte() is unsigned char.
26 *! * The magic number 42 has got a name.
27 *! * Removed comment about /proc (nothing is exported there).
28 *!
29 *! Revision 1.5 2001/06/12 14:35:13 jonashg
30 *! Gave the module a name and added it to printk's.
31 *!
32 *! Revision 1.4 2001/05/31 14:53:40 jonashg
33 *! Made tempudelay() inline so that the watchdog doesn't reset (see
34 *! function comment).
35 *!
36 *! Revision 1.3 2001/03/26 16:03:06 bjornw
37 *! Needs linux/config.h
38 *!
39 *! Revision 1.2 2001/03/20 19:42:00 bjornw
40 *! Use the ETRAX prefix on the DS1302 options
41 *!
42 *! Revision 1.1 2001/03/20 09:13:50 magnusmn
43 *! Linux 2.4 port
44 *!
45 *! Revision 1.10 2000/07/05 15:38:23 bjornw
46 *! Dont update kernel time when a RTC_SET_TIME is done
47 *!
48 *! Revision 1.9 2000/03/02 15:42:59 macce
49 *! * Hack to make RTC work on all 2100/2400
50 *!
51 *! Revision 1.8 2000/02/23 16:59:18 torbjore
52 *! added setup of R_GEN_CONFIG when RTC is connected to the generic port.
53 *!
54 *! Revision 1.7 2000/01/17 15:51:43 johana
55 *! Added RTC_SET_CHARGE ioctl to enable trickle charger.
56 *!
57 *! Revision 1.6 1999/10/27 13:19:47 bjornw
58 *! Added update_xtime_from_cmos which reads back the updated RTC into the kernel.
59 *! /dev/rtc calls it now.
60 *!
61 *! Revision 1.5 1999/10/27 12:39:37 bjornw
62 *! Disabled superuser check. Anyone can now set the time.
63 *!
64 *! Revision 1.4 1999/09/02 13:27:46 pkj
65 *! Added shadow for R_PORT_PB_CONFIG.
66 *! Renamed port_g_shadow to port_g_data_shadow.
67 *!
68 *! Revision 1.3 1999/09/02 08:28:06 pkj
69 *! Made it possible to select either port PB or the generic port for the RST
70 *! signal line to the DS1302 RTC.
71 *! Also make sure the RST bit is configured as output on Port PB (if used).
72 *!
73 *! Revision 1.2 1999/09/01 14:47:20 bjornw
74 *! Added support for /dev/rtc operations with ioctl RD_TIME and SET_TIME to read
75 *! and set the date. Register as major 121.
76 *!
77 *! Revision 1.1 1999/09/01 09:45:29 bjornw
78 *! Implemented a DS1302 RTC driver.
79 *!
80 *!
81 *! ---------------------------------------------------------------------------
82 *!
83 *! (C) Copyright 1999, 2000, 2001 Axis Communications AB, LUND, SWEDEN
84 *!
85 *! $Id: ds1302.c,v 1.11 2001/06/14 12:35:52 jonashg Exp $
86 *!
87 *!***************************************************************************/
88
89 #include <linux/config.h>
90
91 #include <linux/fs.h>
92 #include <linux/init.h>
93 #include <linux/mm.h>
94 #include <linux/module.h>
95 #include <linux/miscdevice.h>
96 #include <linux/delay.h>
97
98 #include <asm/uaccess.h>
99 #include <asm/system.h>
100 #include <asm/svinto.h>
101 #include <asm/io.h>
102 #include <asm/rtc.h>
103
104 #define RTC_MAJOR_NR 121 /* local major, change later */
105
106 static const char ds1302_name[] = "ds1302";
107
108 /* The DS1302 might be connected to different bits on different products.
109 * It has three signals - SDA, SCL and RST. RST and SCL are always outputs,
110 * but SDA can have a selected direction.
111 * For now, only PORT_PB is hardcoded.
112 */
113
114 /* The RST bit may be on either the Generic Port or Port PB. */
115 #ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
116 #define TK_RST_OUT(x) REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, CONFIG_ETRAX_DS1302_RSTBIT, x)
117 #define TK_RST_DIR(x)
118 #else
119 #define TK_RST_OUT(x) REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_DS1302_RSTBIT, x)
120 #define TK_RST_DIR(x) REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, CONFIG_ETRAX_DS1302_RSTBIT, x)
121 #endif
122
123
124 #define TK_SDA_OUT(x) REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_DS1302_SDABIT, x)
125 #define TK_SCL_OUT(x) REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_DS1302_SCLBIT, x)
126
127 #define TK_SDA_IN() ((*R_PORT_PB_READ >> CONFIG_ETRAX_DS1302_SDABIT) & 1)
128 /* 1 is out, 0 is in */
129 #define TK_SDA_DIR(x) REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, CONFIG_ETRAX_DS1302_SDABIT, x)
130 #define TK_SCL_DIR(x) REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, CONFIG_ETRAX_DS1302_SCLBIT, x)
131
132
133 /*
134 * The reason for tempudelay and not udelay is that loops_per_usec
135 * (used in udelay) is not set when functions here are called from time.c
136 */
137
138 static void tempudelay(int usecs)
139 {
140 volatile int loops;
141
142 for(loops = usecs * 12; loops > 0; loops--)
143 /* nothing */;
144 }
145
146
147 /* Send 8 bits. */
148 static void
149 out_byte(unsigned char x)
150 {
151 int i;
152 TK_SDA_DIR(1);
153 for (i = 8; i--;) {
154 /* The chip latches incoming bits on the rising edge of SCL. */
155 TK_SCL_OUT(0);
156 TK_SDA_OUT(x & 1);
157 tempudelay(1);
158 TK_SCL_OUT(1);
159 tempudelay(1);
160 x >>= 1;
161 }
162 TK_SDA_DIR(0);
163 }
164
165 static unsigned char
166 in_byte(void)
167 {
168 unsigned char x = 0;
169 int i;
170
171 /* Read byte. Bits come LSB first, on the falling edge of SCL.
172 * Assume SDA is in input direction already.
173 */
174 TK_SDA_DIR(0);
175
176 for (i = 8; i--;) {
177 TK_SCL_OUT(0);
178 tempudelay(1);
179 x >>= 1;
180 x |= (TK_SDA_IN() << 7);
181 TK_SCL_OUT(1);
182 tempudelay(1);
183 }
184
185 return x;
186 }
187
188 /* Prepares for a transaction by de-activating RST (active-low). */
189
190 static void
191 start(void)
192 {
193 TK_SCL_OUT(0);
194 tempudelay(1);
195 TK_RST_OUT(0);
196 tempudelay(5);
197 TK_RST_OUT(1);
198 }
199
200 /* Ends a transaction by taking RST active again. */
201
202 static void
203 stop(void)
204 {
205 tempudelay(2);
206 TK_RST_OUT(0);
207 }
208
209 /* Enable writing. */
210
211 static void
212 ds1302_wenable(void)
213 {
214 start();
215 out_byte(0x8e); /* Write control register */
216 out_byte(0x00); /* Disable write protect bit 7 = 0 */
217 stop();
218 }
219
220 /* Disable writing. */
221
222 static void
223 ds1302_wdisable(void)
224 {
225 start();
226 out_byte(0x8e); /* Write control register */
227 out_byte(0x80); /* Disable write protect bit 7 = 0 */
228 stop();
229 }
230
231 /* Probe for the chip by writing something to its RAM and try reading it back. */
232
233 #define MAGIC_PATTERN 0x42
234
235 static int
236 ds1302_probe(void)
237 {
238 int retval, res;
239
240 TK_RST_DIR(1);
241 TK_SCL_DIR(1);
242 TK_SDA_DIR(0);
243
244 /* Try to talk to timekeeper. */
245
246 ds1302_wenable();
247 start();
248 out_byte(0xc0); /* write RAM byte 0 */
249 out_byte(MAGIC_PATTERN); /* write something magic */
250 start();
251 out_byte(0xc1); /* read RAM byte 0 */
252
253 if((res = in_byte()) == MAGIC_PATTERN) {
254 char buf[100];
255 stop();
256 ds1302_wdisable();
257 printk("%s: RTC found.\n", ds1302_name);
258 printk("%s: SDA, SCL, RST on PB%i, PB%i, %s%i\n",
259 ds1302_name,
260 CONFIG_ETRAX_DS1302_SDABIT,
261 CONFIG_ETRAX_DS1302_SCLBIT,
262 #ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
263 "GENIO",
264 #else
265 "PB",
266 #endif
267 CONFIG_ETRAX_DS1302_RSTBIT);
268 get_rtc_status(buf);
269 printk(buf);
270 retval = 1;
271 } else {
272 stop();
273 printk("%s: RTC not found.\n", ds1302_name);
274 retval = 0;
275 }
276
277 return retval;
278 }
279
280
281 /* Read a byte from the selected register in the DS1302. */
282
283 unsigned char
284 ds1302_readreg(int reg)
285 {
286 unsigned char x;
287
288 start();
289 out_byte(0x81 | (reg << 1)); /* read register */
290 x = in_byte();
291 stop();
292
293 return x;
294 }
295
296 /* Write a byte to the selected register. */
297
298 void
299 ds1302_writereg(int reg, unsigned char val)
300 {
301 ds1302_wenable();
302 start();
303 out_byte(0x80 | (reg << 1)); /* write register */
304 out_byte(val);
305 stop();
306 ds1302_wdisable();
307 }
308
309 void
310 get_rtc_time(struct rtc_time *rtc_tm)
311 {
312 unsigned long flags;
313
314 save_flags(flags);
315 cli();
316
317 rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
318 rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
319 rtc_tm->tm_hour = CMOS_READ(RTC_HOURS);
320 rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
321 rtc_tm->tm_mon = CMOS_READ(RTC_MONTH);
322 rtc_tm->tm_year = CMOS_READ(RTC_YEAR);
323
324 restore_flags(flags);
325
326 BCD_TO_BIN(rtc_tm->tm_sec);
327 BCD_TO_BIN(rtc_tm->tm_min);
328 BCD_TO_BIN(rtc_tm->tm_hour);
329 BCD_TO_BIN(rtc_tm->tm_mday);
330 BCD_TO_BIN(rtc_tm->tm_mon);
331 BCD_TO_BIN(rtc_tm->tm_year);
332
333 /*
334 * Account for differences between how the RTC uses the values
335 * and how they are defined in a struct rtc_time;
336 */
337
338 if (rtc_tm->tm_year <= 69)
339 rtc_tm->tm_year += 100;
340
341 rtc_tm->tm_mon--;
342 }
343
344 static unsigned char days_in_mo[] =
345 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
346
347 /* ioctl that supports RTC_RD_TIME and RTC_SET_TIME (read and set time/date). */
348
349 static int
350 rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
351 unsigned long arg)
352 {
353 unsigned long flags;
354
355 switch(cmd) {
356 case RTC_RD_TIME: /* read the time/date from RTC */
357 {
358 struct rtc_time rtc_tm;
359
360 get_rtc_time(&rtc_tm);
361 if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time)))
362 return -EFAULT;
363 return 0;
364 }
365
366 case RTC_SET_TIME: /* set the RTC */
367 {
368 struct rtc_time rtc_tm;
369 unsigned char mon, day, hrs, min, sec, leap_yr;
370 unsigned char save_control, save_freq_select;
371 unsigned int yrs;
372
373 if (!capable(CAP_SYS_TIME))
374 return -EPERM;
375
376 if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))
377 return -EFAULT;
378
379 yrs = rtc_tm.tm_year + 1900;
380 mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
381 day = rtc_tm.tm_mday;
382 hrs = rtc_tm.tm_hour;
383 min = rtc_tm.tm_min;
384 sec = rtc_tm.tm_sec;
385
386
387 if ((yrs < 1970) || (yrs > 2069))
388 return -EINVAL;
389
390 leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
391
392 if ((mon > 12) || (day == 0))
393 return -EINVAL;
394
395 if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
396 return -EINVAL;
397
398 if ((hrs >= 24) || (min >= 60) || (sec >= 60))
399 return -EINVAL;
400
401 if (yrs >= 2000)
402 yrs -= 2000; /* RTC (0, 1, ... 69) */
403 else
404 yrs -= 1900; /* RTC (70, 71, ... 99) */
405
406 BIN_TO_BCD(sec);
407 BIN_TO_BCD(min);
408 BIN_TO_BCD(hrs);
409 BIN_TO_BCD(day);
410 BIN_TO_BCD(mon);
411 BIN_TO_BCD(yrs);
412
413 save_flags(flags);
414 cli();
415 CMOS_WRITE(yrs, RTC_YEAR);
416 CMOS_WRITE(mon, RTC_MONTH);
417 CMOS_WRITE(day, RTC_DAY_OF_MONTH);
418 CMOS_WRITE(hrs, RTC_HOURS);
419 CMOS_WRITE(min, RTC_MINUTES);
420 CMOS_WRITE(sec, RTC_SECONDS);
421 restore_flags(flags);
422
423 /* Notice that at this point, the RTC is updated but
424 * the kernel is still running with the old time.
425 * You need to set that separately with settimeofday
426 * or adjtimex.
427 */
428 return 0;
429 }
430
431 case RTC_SET_CHARGE: /* set the RTC TRICKLE CHARGE register */
432 {
433 int tcs_val;
434 unsigned char save_control, save_freq_select;
435
436 if (!capable(CAP_SYS_TIME))
437 return -EPERM;
438
439 if(copy_from_user(&tcs_val, (int*)arg, sizeof(int)))
440 return -EFAULT;
441
442 tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F);
443 ds1302_writereg(RTC_TRICKLECHARGER, tcs_val);
444 return 0;
445 }
446 default:
447 return -ENOIOCTLCMD;
448 }
449 }
450
451 int
452 get_rtc_status(char *buf)
453 {
454 char *p;
455 struct rtc_time tm;
456
457 p = buf;
458
459 get_rtc_time(&tm);
460
461 /*
462 * There is no way to tell if the luser has the RTC set for local
463 * time or for Universal Standard Time (GMT). Probably local though.
464 */
465
466 p += sprintf(p,
467 "rtc_time\t: %02d:%02d:%02d\n"
468 "rtc_date\t: %04d-%02d-%02d\n",
469 tm.tm_hour, tm.tm_min, tm.tm_sec,
470 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
471
472 return p - buf;
473 }
474
475
476 /* The various file operations we support. */
477
478 static struct file_operations rtc_fops = {
479 owner: THIS_MODULE,
480 ioctl: rtc_ioctl,
481 };
482
483 /* Just probe for the RTC and register the device to handle the ioctl needed. */
484
485 int __init
486 ds1302_init(void)
487 {
488 if (!ds1302_probe()) {
489 #ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
490 /*
491 * The only way to set g27 to output is to enable ATA.
492 *
493 * Make sure that R_GEN_CONFIG is setup correct.
494 */
495 genconfig_shadow = ((genconfig_shadow &
496 ~IO_MASK(R_GEN_CONFIG, ata))
497 |
498 (IO_STATE(R_GEN_CONFIG, ata, select)));
499 *R_GEN_CONFIG = genconfig_shadow;
500 if (!ds1302_probe())
501 return -1;
502 #else
503 return -1;
504 #endif
505 }
506
507 if (register_chrdev(RTC_MAJOR_NR, ds1302_name, &rtc_fops)) {
508 printk(KERN_INFO "%s: unable to get major %d for rtc\n",
509 ds1302_name, RTC_MAJOR_NR);
510 return -1;
511 }
512 return 0;
513 }
514