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