]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/linux/openslug-kernel-2.6.11.2/x1205-rtc.c
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / linux / openslug-kernel-2.6.11.2 / x1205-rtc.c
1 /*
2     x1205 - an 12c driver for the Xicor X1205 RTC
3     Copyright 2004 Karen Spearel
4
5     please send all reports to:
6         kas11 at tampabay dot rr dot com
7       
8     based on linux/drivers/acron/char/pcf8583.h
9     Copyright (C) 2000 Russell King
10     
11     This program is free software; you can redistribute it and/or modify
12     it under the terms of the GNU General Public License as published by
13     the Free Software Foundation; either version 2 of the License, or
14     (at your option) any later version.
15
16     This program is distributed in the hope that it will be useful,
17     but WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     GNU General Public License for more details.
20
21     You should have received a copy of the GNU General Public License
22     along with this program; if not, write to the Free Software
23     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25 /*
26
27  * i2c_adapter is the structure used to identify a physical i2c bus along
28  * with the access algorithms necessary to access it.
29
30 struct i2c_adapter {
31         struct module *owner;
32         unsigned int id;  == is algo->id | hwdep.struct->id, for registered values see below
33         unsigned int class;
34         struct i2c_algorithm *algo; the algorithm to access the bus
35         void *algo_data;
36
37         --- administration stuff.
38         int (*client_register)(struct i2c_client *);
39         int (*client_unregister)(struct i2c_client *);
40
41          data fields that are valid for all devices
42         struct semaphore bus_lock;
43         struct semaphore clist_lock;
44
45         int timeout;
46         int retries;
47         struct device dev;              the adapter device 
48         struct class_device class_dev;  the class device
49
50 #ifdef CONFIG_PROC_FS 
51         No need to set this when you initialize the adapter
52         int inode;
53 #endif def CONFIG_PROC_FS
54
55         int nr;
56         struct list_head clients;
57         struct list_head list;
58         char name[I2C_NAME_SIZE];
59         struct completion dev_released;
60         struct completion class_dev_released;
61 };
62 */
63
64
65 /*========== Driver for the X1205 on the Linksys NSLU2 ==================*/
66
67 #include <linux/init.h>
68 #include <linux/i2c.h>
69 #include <linux/slab.h>
70 #include <linux/string.h>
71 #include <linux/errno.h>
72 #include <linux/bcd.h>
73 #include <linux/rtc.h>
74 #include <linux/fs.h>
75 #include <linux/proc_fs.h>
76 #include <linux/miscdevice.h>
77 #include <linux/device.h>
78 #include <asm/uaccess.h>
79 #include <asm/system.h>
80 #include <linux/moduleparam.h>
81
82 #define         RTC_GETDATETIME         0
83 #define         RTC_SETTIME             1
84 #define         RTC_SETDATETIME         2
85
86 #define         I2C_M_WR                0       // just for consistancy
87
88 //  offsets into read buf - add 2 for write buf
89 #define         CCR_SEC                 0
90 #define         CCR_MIN                 1
91 #define         CCR_HOUR                2
92 #define         CCR_MDAY                3
93 #define         CCR_MONTH               4
94 #define         CCR_YEAR                5
95 #define         CCR_WDAY                6
96 #define         CCR_Y2K                 7
97
98 #define         X1205_I2C_BUS_ADDR      0x6f    // hardwired into x1205
99 #define         X1205_ALM0_BASE         0x00    // Base address of the ALM0
100 #define         X1205_CCR_BASE          0x30    // Base address of the CCR
101 #define         X1205_SR_ADDR           0x3f    // Status Register
102 #define         X1205_SR_WEL            0x02    // Write Enable Latch bit
103 #define         X1205_SR_RWEL           0x04    // Register Write Enable Bit
104 #define         X1205_MILBIT            0x80    // this bit set in ccr.hour for 24 hr mode
105 #define         NOERR                   0
106 #define         RTC_NODATE              0
107 #define         RTC_DATETOO             1
108
109 // comment out next line is your x1205 can't do page writes
110 //#define       X1205PAGEWRITE          1
111 #ifdef X1205PAGEWRITE
112 #define         DRIVERNAME              "Xicor x1205 RTC Driver v0.9.3.3"
113 #else
114 #define         DRIVERNAME              "Xicor x1205 RTC Dvr v0.9.3.3NPW"
115 #endif
116
117 #define         DEBUG                   KERN_DEBUG
118 /* This, if defined to 1, turns on a lot of debugging meessages. */
119 #if X1205_DEBUG
120 #define x1205_debug(args) printk args
121 #else
122 #define x1205_debug(args) ((void)0)
123 #endif
124
125
126 static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm, u8 reg_base);
127 static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, int datetoo, u8 reg_base);
128 static int x1205_attach(struct i2c_adapter *adapter);
129 static int x1205_detach(struct i2c_client *client);
130 static int x1205_validate_tm(struct rtc_time *tm, int datetoo);
131 static int x1205_command(struct i2c_client *client, unsigned int cmd, void *arg);
132 static int x1205_sync_rtc(void);
133 static int x1205_read(struct file *file, char *buf, size_t count, loff_t *ptr);
134 static int x1205_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
135 static int x1205_read_proc(char *buf, char **start, off_t off, int len, int *eof, void *data);
136
137 static struct i2c_driver x1205_driver = {
138         .owner          = THIS_MODULE,
139         .name           = DRIVERNAME,
140         .id             = I2C_DRIVERID_X1205,
141         .flags          = I2C_DF_NOTIFY,
142         .attach_adapter = &x1205_attach,                //we don't need to probe...x1205 is hardwired @ 0x6f
143         .detach_client  = &x1205_detach,
144         .command        = &x1205_command,               //this prolly never gets called...used internally tho
145 };
146
147 static struct i2c_client x1205_i2c_client = {
148         .id             =       I2C_DRIVERID_X1205,
149         .flags          =       0,
150         .addr           =       X1205_I2C_BUS_ADDR,     // chip address - NOTE: 7bit
151         .adapter        =       NULL,                   // the adapter we sit on assigned in attach
152         .driver         =       &x1205_driver,          // and our access routines
153         .usage_count    =       0,                      // How many accesses currently to this client
154         .dev            =       {},                     // the device structure
155         .list           =       {},
156         .name           =       DRIVERNAME,
157         .released       =       {},
158 };
159
160 static struct file_operations rtc_fops = {
161         owner:          THIS_MODULE,
162         ioctl:          x1205_ioctl,
163         read:           x1205_read,
164 };
165
166 static struct miscdevice x1205_miscdev = {
167         .minor          = RTC_MINOR,
168         .name           = "rtc",
169         .fops           = &rtc_fops,
170 };
171 extern int (*set_rtc)(void);
172 static unsigned epoch = 1900;           //coresponds to year 0
173 static unsigned  rtc_epoch = 2000;
174 static const unsigned char days_in_mo[] = 
175 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
176
177 //===================================CODE======================================
178 // in the routines that deal directly with the x1205 hardware, we use
179 // rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
180 // Epoch is inited as 2000. Time is set to UT
181 //=============================================================================   
182 static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm, u8 reg_base)
183 {
184         static unsigned char addr[2] = { 0,} ;
185         unsigned char buf[8];   
186         struct i2c_msg msgs[2] = {
187                 { client->addr, I2C_M_WR, 2, addr },    //msg 1 = send base address
188                 { client->addr, I2C_M_RD, 8, buf },     //msg 2 = read sequential data
189         };
190         addr[1] = reg_base;
191         if ((i2c_transfer(client->adapter, msgs, 2)) == 2) {    //did we read 2 messages?
192                 x1205_debug((KERN_DEBUG "raw x1205 read data  - sec-%02x min-%02x hr-%02x mday-%02x mon-%02x year-%02x wday-%02x y2k-%02x\n", 
193                         buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6], buf[7]));
194                 tm->tm_sec  = BCD2BIN(buf[CCR_SEC]);
195                 tm->tm_min  = BCD2BIN(buf[CCR_MIN]);
196                 buf[CCR_HOUR] &= ~X1205_MILBIT;
197                 tm->tm_hour = BCD2BIN(buf[CCR_HOUR]);           //hr is 0-23
198                 tm->tm_mday = BCD2BIN(buf[CCR_MDAY]);
199                 tm->tm_mon  = BCD2BIN(buf[CCR_MONTH]);
200                 rtc_epoch   = BCD2BIN(buf[CCR_Y2K]) * 100;
201                 tm->tm_year = BCD2BIN(buf[CCR_YEAR]) + rtc_epoch - epoch;
202                 tm->tm_wday = buf[CCR_WDAY];
203                 x1205_debug((KERN_DEBUG "rtc_time output data - sec-%02d min-%02d hr-%02d mday-%02d mon-%02d year-%02d wday-%02d epoch-%d rtc_epoch-%d\n",
204                         tm->tm_sec,tm->tm_min,tm->tm_hour,tm->tm_mday,tm->tm_mon,tm->tm_year,tm->tm_wday,epoch, rtc_epoch));
205         } else {
206                 printk(KERN_DEBUG "i2c_transfer Read Error\n");
207                 return -EIO;
208         }               
209         
210         return NOERR;
211 }
212 // x1205pagewrite allows writing a block of registers in msg3 even though the x1205 says
213 // nothing about this in its spec. 
214 // it needs more testing as it is possible some x1205s are actually not-completely-
215 // functional x1226s and there is a reason for the multiple write to not be in the spec.
216 // anyhow, it is enabled for the time being...and we even push out luck by sending 10 bytes
217
218 static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, int datetoo, u8 reg_base)
219 {
220         static unsigned char wel[3]   = { 0, X1205_SR_ADDR, X1205_SR_WEL };
221         static unsigned char rwel[3]  = { 0, X1205_SR_ADDR, X1205_SR_WEL | X1205_SR_RWEL };
222         static unsigned char diswe[3] = { 0, X1205_SR_ADDR, 0 };
223
224 #ifdef X1205PAGEWRITE
225
226         static unsigned char buf[10]   = { 0, X1205_CCR_BASE, };                
227         struct i2c_msg msgs[4] = {
228                 { client->addr, I2C_M_WR, 3, wel   },   //msg 1 = write WEL to to ccr sr
229                 { client->addr, I2C_M_WR, 3, rwel  },   //msg 2 = write RWEL to ccr sr
230                 { client->addr, I2C_M_WR, 10, buf   },  //msg 3 = write ccr base addr +seq data
231                 { client->addr, I2C_M_WR, 3, diswe },   //msg 4 = 0 to ccr sr to disable writes
232         };
233
234         msgs[2].len = 5;                                        // 5 bytes + addr to set time only
235         buf [1] = reg_base;
236         buf[CCR_SEC+2]  = BIN2BCD(tm->tm_sec);
237         buf[CCR_MIN+2]  = BIN2BCD(tm->tm_min);
238         buf[CCR_HOUR+2] = BIN2BCD(tm->tm_hour) | X1205_MILBIT; // set 24 hour format
239         if (datetoo == 1) {
240                 buf[CCR_MDAY+2]  = BIN2BCD(tm->tm_mday);
241                 buf[CCR_MONTH+2] = BIN2BCD(tm->tm_mon);         // input is 0-11        
242                 buf[CCR_YEAR+2]  = BIN2BCD((tm->tm_year + epoch - rtc_epoch));  // input is yrs since 1900
243                 buf[CCR_WDAY+2]  = tm->tm_wday & 7;
244                 buf[CCR_Y2K+2]   = BIN2BCD((rtc_epoch/100));
245                 msgs[2].len += 5;                               //5 more bytes to set date
246         }
247         x1205_debug((KERN_DEBUG "rtc_time input - sec-%02d min-%02d hour-%02d mday-%02d mon-%02d year-%02d wday-%02d epoch-%d rtc_epoch-%d\n",
248                 tm->tm_sec,tm->tm_min,tm->tm_hour,tm->tm_mday,tm->tm_mon,tm->tm_year,tm->tm_wday, epoch, rtc_epoch));
249         x1205_debug((KERN_DEBUG "BCD write data - sec-%02x min-%02x hour-%02x mday-%02x mon-%02x year-%02x wday-%02x y2k-%02x\n",
250                 buf[2],buf[3],buf[4],buf[5],buf[6], buf[7], buf[8], buf[9]));
251
252         if ((i2c_transfer(client->adapter, msgs, 4)) != 4)
253                 return -EIO;
254         return NOERR;
255         
256 #else           //do this if page writes aren't working
257
258         int i,xfer,count;
259         static unsigned char data[3]  = { 0,};
260         static unsigned char buf[8];
261
262         buf[CCR_SEC]  = BIN2BCD(tm->tm_sec);
263         buf[CCR_MIN]  = BIN2BCD(tm->tm_min);
264         buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_MILBIT; // set 24 hour format
265         count = CCR_HOUR+1;
266         if (datetoo == 1) {
267                 buf[CCR_MDAY]  = BIN2BCD(tm->tm_mday);
268                 buf[CCR_MONTH] = BIN2BCD(tm->tm_mon);           // input is 0-11        
269                 buf[CCR_YEAR]  = BIN2BCD((tm->tm_year + epoch - rtc_epoch));    // input is yrs since 1900
270                 buf[CCR_WDAY]  = tm->tm_wday & 7;
271                 buf[CCR_Y2K]   = BIN2BCD((rtc_epoch/100));
272                 count = CCR_Y2K+1;
273         }
274         x1205_debug((KERN_DEBUG "rtc_time input - sec-%02d min-%02d hour-%02d mday-%02d mon-%02d year-%02d wday-%02d epoch-%d rtc_epoch-%d\n",
275                 tm->tm_sec,tm->tm_min,tm->tm_hour,tm->tm_mday,tm->tm_mon,tm->tm_year,tm->tm_wday, epoch, rtc_epoch));
276
277         xfer = i2c_master_send(client, wel, 3);
278         x1205_debug((KERN_DEBUG "wen - %x\n", xfer));
279         if (xfer != 3)
280                 return -EIO;
281
282         xfer = i2c_master_send(client, rwel, 3);
283         x1205_debug((KERN_DEBUG "wenb - %x\n", xfer));
284         if (xfer != 3)
285                 return -EIO;
286
287         for (i = 0; i < count; i++) {
288                 data[1] = i + reg_base;
289                 data[2] =  buf[i];
290                 xfer = i2c_master_send(client, data, 3);
291                 x1205_debug((KERN_DEBUG "xfer - %d addr - %02x  data - %02x\n", xfer, data[1], data[2]));
292                 if (xfer != 3)
293                         return -EIO;
294         };
295
296         xfer = i2c_master_send(client, diswe, 3);
297         x1205_debug((KERN_DEBUG "wdis - %x\n", xfer));
298         if (xfer != 3)
299                 return -EIO;
300         return NOERR;
301 #endif
302 }
303 //=============================================================================
304
305 static int x1205_attach(struct i2c_adapter *adapter)
306 {
307         struct rtc_time tm;
308         struct timespec tv;
309         int errno;
310                 
311         x1205_i2c_client.adapter = adapter;
312         x1205_i2c_client.id++;
313
314         if ((x1205_get_datetime(&x1205_i2c_client, &tm, X1205_CCR_BASE)) != NOERR)      //test for functional driver 
315                 return -EIO;
316         
317         if ((errno = i2c_attach_client(&x1205_i2c_client)) != NOERR)
318                 return errno;
319
320         /* IMPORTANT: the RTC only stores whole seconds.  It is arbitrary whether
321          * it stores the most close value or the value with partial seconds
322          * truncated, however it is important for x1205_sync_rtc that it be
323          * defined to store the truncated value.  This is because otherwise it
324          * is necessary to read both xtime.tv_sec and xtime.tv_nsec in the
325          * sync function, and atomic reads of >32bits on ARM are not possible.
326          * So storing the most close value would slow down the sync API.  So
327          * Here we have the truncated value and the best guess is to add 0.5s
328          */
329         tv.tv_nsec = NSEC_PER_SEC >> 1;
330         /* WARNING: this is not the C library 'mktime' call, it is a built in
331          * inline function from include/linux/time.h.  It expects (requires)
332          * the month to be in the range 1-12
333          */
334         tv.tv_sec  = mktime(tm.tm_year+epoch, tm.tm_mon+1, tm.tm_mday, tm.tm_hour,
335                                                 tm.tm_min, tm.tm_sec);
336         do_settimeofday(&tv);
337         set_rtc = x1205_sync_rtc;
338         
339         printk(KERN_DEBUG "%s attached on adapter %s\n",x1205_i2c_client.name,
340                 x1205_i2c_client.adapter->name); //why is this name a null string?
341
342         return NOERR;
343 }
344
345 static int x1205_detach(struct i2c_client *client)
346 {
347         int errno;
348         
349         if ((errno = i2c_detach_client(client)) != 0) {
350                 printk(KERN_DEBUG "i2c_detach failed - errno = %d\n", errno);
351                 return errno;
352         }
353
354         return NOERR;
355 }
356
357 // make sure the rtc_time values are in bounds
358 static int x1205_validate_tm(struct rtc_time *tm, int datetoo)
359 {
360         if (datetoo) {
361                 /* This used to be 1900, not epoch, but all the read APIs subtract
362                  * epoch, not 1900, and the result of these APIs *is* fed back in
363                  * to x1205_command (which calls this.)
364                  */
365                 tm->tm_year += epoch;
366
367                 /* The RTC uses a byte containing a BCD year value, so this is
368                  * limited to the range 0..99 from rtc_epoch.
369                  */
370                 if ((tm->tm_year < rtc_epoch || tm->tm_year > rtc_epoch + 99) ||
371                         ((tm->tm_mon > 11) || tm->tm_mon < 0 || (tm->tm_mday <= 0)) ||
372                         (tm->tm_mday > (days_in_mo[tm->tm_mon] + ( (tm->tm_mon == 1) && 
373                         ((!(tm->tm_year % 4) && (tm->tm_year % 100) ) || !(tm->tm_year % 400)))))
374                         ) {
375                         printk(KERN_DEBUG "x1205_validate_tm: invalid date:\t%04d,%02d,%02d\n",
376                                         tm->tm_year, tm->tm_mon, tm->tm_mday);
377                         return -EINVAL;
378                 }
379
380                 tm->tm_year -= epoch;
381         }
382
383         if (((tm->tm_hour < 0) || (tm->tm_min < 0) || (tm->tm_sec < 0)) ||
384                 ((tm->tm_hour >= 24) || (tm->tm_min >= 60) || (tm->tm_sec >= 60))) {
385                 printk(KERN_DEBUG "x1205_validate_tm: invalid time:\t%02d,%02d,%02d\n",
386                         tm->tm_hour, tm->tm_min, tm->tm_sec);
387                 return -EINVAL;
388         }
389
390         return NOERR;
391 }
392
393 static int x1205_command(struct i2c_client *client, unsigned int cmd, void *tm)
394 {
395         int errno, dodate = RTC_DATETOO;
396
397         if (client == NULL || tm == NULL)
398                 return -EINVAL;
399         if (!capable(CAP_SYS_TIME))
400                 return -EACCES;
401
402         x1205_debug((KERN_DEBUG "x1205_command %d\n", cmd));
403
404         switch (cmd) {
405         case RTC_GETDATETIME:
406                 return x1205_get_datetime(client, tm, X1205_CCR_BASE);
407
408         case RTC_SETTIME:               // note fall thru
409                 dodate = RTC_NODATE;
410         case RTC_SETDATETIME:
411                 if ((errno = x1205_validate_tm(tm, dodate)) < NOERR)
412                         return errno;
413                 return x1205_set_datetime(client, tm, dodate, X1205_CCR_BASE);
414
415         default:
416                 return -EINVAL;
417         }
418 }
419
420 static int x1205_sync_rtc(void)
421 {
422         /* sync to xtime, tv_nsec is ignored (see the command above about
423          * use of the truncated value) so this is pretty easy.  kas11's
424          * code took are to do RTC_SETTIME - i.e. not set the date.  My
425          * assumption is that this may be because date setting is slow, so
426          * this feature is retained.  NTP does a sync when the time is
427          * changed, including significant changes.  The sync needs to
428          * set the date correctly if necessary.
429          */
430         struct rtc_time tm;
431         time_t new_s, old_s, div, rem;
432         unsigned int cmd;
433
434         x1205_debug((KERN_DEBUG "x1205_sync_rtc entry\n"));
435
436         {
437                 int err = x1205_command(&x1205_i2c_client, RTC_GETDATETIME, &tm);
438                 if (err != NOERR) {
439                         printk(KERN_DEBUG "x1205_sync_rtc exit (failed to get date)\n");
440                         return err;
441                 }
442         }
443
444         old_s = mktime(tm.tm_year+epoch, tm.tm_mon+1, tm.tm_mday,
445                         tm.tm_hour, tm.tm_min, tm.tm_sec);
446         new_s = xtime.tv_sec;
447
448         /* Optimisation, the clock only stores seconds so it's pointless
449          * to reset it if it is within 1s of now.
450          */
451         if (old_s - 1 <= new_s && new_s <= old_s + 1) {
452                 x1205_debug((KERN_DEBUG "x1205_sync_rtc exit (RTC in sync)\n"));
453                 return NOERR;
454         }
455
456         div = new_s / 60;
457         tm.tm_sec = new_s - div*60;
458         rem = div;
459         div /= 60;
460         tm.tm_min = rem - div*60;
461         rem = div;
462         div /= 24;
463         tm.tm_hour = rem - div*24;
464
465         /* Now subtract the result from the original 'new' value.  This
466          * should be zero, if not an mday change is required.  Notice
467          * that this will tend to fire for small drifts close to UTC midnight.
468          */
469         cmd = RTC_SETTIME;
470         rem = new_s - mktime(tm.tm_year+epoch, tm.tm_mon+1, tm.tm_mday,
471                                 tm.tm_hour, tm.tm_min, tm.tm_sec);
472         if (rem != 0) {
473                 int dif;
474
475                 /* Make an approximation to year/month/day. */
476                 rem = div;
477                 div = (2*div)/61;  // 30.5 days/month
478                 tm.tm_mday = 1 + rem - (div*61)/2;
479                 rem = div;
480                 div /= 12;
481                 rem -= 12*div;
482                 while (tm.tm_mday > days_in_mo[rem]) {
483                         tm.tm_mday -= days_in_mo[rem];
484                         if (++rem >= 12) {
485                                 rem -= 12;
486                                 ++div;
487                         }
488                 }
489                 tm.tm_mon = rem;
490                 div += 1970;       // base of tv_sec
491
492                 /* Calculate the error in the approximation as a signed
493                  * int value.
494                  */
495                 dif = new_s - mktime(div, tm.tm_mon+1, tm.tm_mday,
496                                 tm.tm_hour, tm.tm_min, tm.tm_sec);
497                 while (dif < 0) {
498                         --(tm.tm_mday);
499                         dif += 86400;
500                 }
501                 while (dif >= 86400) {
502                         ++(tm.tm_mday);
503                         dif -= 86400;
504                 }
505                 if (dif != 0)
506                         printk(KERN_ERR "x1205_sync_rtc (error in date %d)\n", dif);
507
508                 /* Normalise the result. */
509                 while (tm.tm_mday <= 0) {
510                         if (--(tm.tm_mon) < 0) {
511                                 tm.tm_mon += 12;
512                                 --div;
513                         }
514                         tm.tm_mday += days_in_mo[tm.tm_mon] + (tm.tm_mon==1 &&
515                                 ((!(div % 4) && (div % 100) ) || !(div % 400)));
516                 }
517
518                 do {
519                         rem = days_in_mo[tm.tm_mon] + (tm.tm_mon==1 &&
520                                 ((!(div % 4) && (div % 100) ) || !(div % 400)));
521                         if (tm.tm_mday > rem) {
522                                 tm.tm_mday -= rem;
523                                 if (++(tm.tm_mon) >= 12) {
524                                         tm.tm_mon -= 12;
525                                         ++div;
526                                 }
527                         } else {
528                                 break;
529                         }
530                 } while (1);
531
532                 tm.tm_year = div-epoch;
533                 cmd = RTC_SETDATETIME;
534                 printk(KERN_DEBUG "x1205_sync_rtc exit (change date %d)\n", new_s-old_s);
535         } else {
536                 printk(KERN_DEBUG "x1205_sync_rtc exit (change seconds %d)\n", new_s-old_s);
537                 /* But avoid the race condition when the date is about to
538                  * change.
539                  */
540                 if (tm.tm_min == 59 && tm.tm_hour == 23)
541                         cmd = RTC_SETDATETIME;
542         }
543
544         return x1205_command(&x1205_i2c_client, cmd, &tm);
545 }
546
547 static int x1205_read(struct file *file, char *buf, size_t count, loff_t *ptr)
548 {
549         struct rtc_time tm;
550
551         if ((x1205_get_datetime(&x1205_i2c_client, &tm, X1205_CCR_BASE)) < NOERR)
552                 return -EIO;
553         return copy_to_user(buf, &tm, sizeof(tm)) ? -EFAULT : NOERR;
554 }
555
556 //==============================================================================
557
558 static int x1205_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
559                      unsigned long arg)
560 {
561         struct rtc_time tm;
562         int errno;
563
564         x1205_debug((KERN_DEBUG "ioctl = %x\n", cmd));
565         
566         switch (cmd) {
567         case RTC_RD_TIME:
568                 if ((x1205_get_datetime(&x1205_i2c_client, &tm, X1205_CCR_BASE)) < NOERR)
569                         return -EIO;
570                 break;
571                 
572         case RTC_SET_TIME:
573                 if (!capable(CAP_SYS_TIME))
574                         return -EACCES;
575
576                 if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof(struct rtc_time))) 
577                         return -EFAULT;
578                 if ((errno = x1205_validate_tm(&tm, RTC_DATETOO)) < NOERR)
579                         return errno;
580                 return x1205_set_datetime(&x1205_i2c_client, &tm, RTC_DATETOO, X1205_CCR_BASE);
581
582         case RTC_ALM_SET:                                               //FIXME: set Control Regs
583                 if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof(struct rtc_time))) 
584                         return -EFAULT;
585                 return x1205_set_datetime(&x1205_i2c_client, &tm, RTC_DATETOO, X1205_ALM0_BASE);
586
587         case RTC_ALM_READ:
588                 if ((x1205_get_datetime(&x1205_i2c_client, &tm, X1205_ALM0_BASE)) < NOERR)
589                         return -EIO;
590                 break;
591
592         case RTC_EPOCH_READ:
593
594                 return put_user (epoch, (unsigned long __user *)arg);
595
596         case RTC_EPOCH_SET:
597                 if (arg < 1900)
598                         return -EINVAL;
599
600                 if (!capable(CAP_SYS_TIME))
601                         return -EACCES;
602
603                 epoch = arg;
604                 return 0;
605
606         default:
607                 return -ENOTTY;
608         }
609         return copy_to_user((void __user *)arg, &tm, sizeof tm) ? -EFAULT : 0;
610
611 }
612
613 static int x1205_read_proc(char *buf, char **start, off_t off, int len, int *eof, void *data)
614 {
615         struct rtc_time tm;
616         int slen, errno;
617
618         if ((errno = x1205_get_datetime(&x1205_i2c_client, &tm, X1205_CCR_BASE)) < NOERR)
619                 return errno;
620
621 //      here we return the real year and the month as 1-12 since it is human-readable
622         slen = sprintf(buf, "rtc_time\t: %02d:%02d:%02d\nrtc_date\t: %04d-%02d-%02d\n",
623                 tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_year + 1900, tm.tm_mon+1, tm.tm_mday);
624         x1205_debug((KERN_DEBUG "raw rtc_time\t: %02d:%02d:%02d\nraw rtc_date\t: %04d-%02d-%02d\n",
625                 tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_year, tm.tm_mon, tm.tm_mday));
626
627         if (slen <= off + len)
628                 *eof = 1;
629         *start = buf + off;
630         slen -= off;
631         if (slen > len)
632                 slen = len;
633         if ( slen < 0 )
634                 slen = 0;
635
636         return slen;
637 }
638
639 static int __init x1205_init(void)
640 {
641         struct  rtc_time tm;
642         int errno;
643         printk(KERN_INFO "LOADED %s\n", DRIVERNAME);
644
645         if ((errno = i2c_add_driver(&x1205_driver)) != NOERR) {
646                 dev_dbg(x1205_i2c_client.dev, "x1205_init failed - errno = %d\n", errno);
647                 return (errno);
648         }
649         if ((errno = misc_register(&x1205_miscdev)) != NOERR) {
650                 dev_dbg(x1205_i2c_client.dev, "Register Misc Driver failed - errno = %d\n", errno);
651                 i2c_del_driver(&x1205_driver);
652                 return errno; 
653         }
654         if (create_proc_read_entry("driver/rtc", 0, NULL, x1205_read_proc, NULL) < NOERR)
655                 return -ENOMEM;
656         if ((x1205_get_datetime(&x1205_i2c_client, &tm, X1205_CCR_BASE)) != NOERR)      //test for functionality
657                 return -EIO;
658
659         return NOERR;   
660 }
661
662 static void __exit x1205_exit(void)
663 {
664         remove_proc_entry("driver/rtc", NULL);
665         misc_deregister(&x1205_miscdev);
666         i2c_del_driver(&x1205_driver);
667         set_rtc = NULL;
668 }
669
670 MODULE_AUTHOR("Karen Spearel <kas11@tampabay.rr.com>");
671 MODULE_DESCRIPTION("Xicor X1205-RTC Driver");
672 MODULE_LICENSE("GPL");
673 static int debug = 7;
674 module_param(debug, bool, 0644);
675 MODULE_PARM_DESC(debug, "Debugging enabled = 1");
676
677 module_init(x1205_init);
678 module_exit(x1205_exit);