2 * I2C client/driver for the ST M41T62 family of i2c rtc chips.
\r
4 * Author: lhh <lhh@rock-chips.com>
\r
7 * Based on m41t00.c by Mark A. Greer <mgreer@mvista.com>
\r
11 * This program is free software; you can redistribute it and/or modify
\r
12 * it under the terms of the GNU General Public License version 2 as
\r
13 * published by the Free Software Foundation.
\r
17 #include <linux/bcd.h>
\r
18 #include <linux/i2c.h>
\r
19 #include <linux/init.h>
\r
20 #include <linux/kernel.h>
\r
21 #include <linux/module.h>
\r
22 #include <linux/rtc.h>
\r
23 #include <linux/slab.h>
\r
24 #include <linux/smp_lock.h>
\r
25 #include <linux/string.h>
\r
28 #include <linux/i2c.h>
\r
29 #include <linux/bcd.h>
\r
30 #include <linux/rtc.h>
\r
31 #include <linux/delay.h>
\r
32 #include <linux/wakelock.h>
\r
33 #include <mach/gpio.h>
\r
34 #include <mach/iomux.h>
\r
39 #define M41T62_REG_SSEC 0
\r
40 #define M41T62_REG_SEC 1
\r
41 #define M41T62_REG_MIN 2
\r
42 #define M41T62_REG_HOUR 3
\r
43 #define M41T62_REG_SQWDAY 4
\r
44 #define M41T62_REG_DAY 5
\r
45 #define M41T62_REG_MON 6
\r
46 #define M41T62_REG_YEAR 7
\r
47 #define M41T62_REG_ALARM_MON 0xa
\r
48 #define M41T62_REG_ALARM_DAY 0xb
\r
49 #define M41T62_REG_ALARM_HOUR 0xc
\r
50 #define M41T62_REG_ALARM_MIN 0xd
\r
51 #define M41T62_REG_ALARM_SEC 0xe
\r
52 #define M41T62_REG_FLAGS 0xf
\r
53 #define M41T62_REG_SQW 0x13
\r
55 #define M41T62_REG_SEC_INDEX (M41T62_REG_SEC - 1)
\r
56 #define M41T62_REG_MIN_INDEX (M41T62_REG_MIN - 1)
\r
57 #define M41T62_REG_HOUR_INDEX (M41T62_REG_HOUR - 1)
\r
58 #define M41T62_REG_SQWDAY_INDEX (M41T62_REG_SQWDAY - 1)
\r
59 #define M41T62_REG_DAY_INDEX (M41T62_REG_DAY - 1)
\r
60 #define M41T62_REG_MON_INDEX (M41T62_REG_MON - 1)
\r
61 #define M41T62_REG_YEAR_INDEX (M41T62_REG_YEAR - 1)
\r
63 #define M41T62_DATETIME_REG_SIZE (M41T62_REG_YEAR )
\r
65 #define M41T62_REG_ALARM_MON_INDEX (M41T62_REG_ALARM_MON-0x0a)
\r
66 #define M41T62_REG_ALARM_DAY_INDEX (M41T62_REG_ALARM_DAY-0x0a)
\r
67 #define M41T62_REG_ALARM_HOUR_INDEX (M41T62_REG_ALARM_HOUR-0x0a)
\r
68 #define M41T62_REG_ALARM_MIN_INDEX (M41T62_REG_ALARM_MIN-0x0a)
\r
69 #define M41T62_REG_ALARM_SEC_INDEX (M41T62_REG_ALARM_SEC-0x0a)
\r
70 #define M41T62_REG_FLAGS_INDEX (M41T62_REG_FLAGS-0x0a)
\r
73 #define M41T62_ALARM_REG_SIZE \
\r
74 (M41T62_REG_FLAGS + 1 - M41T62_REG_ALARM_MON)
\r
77 #define M41T62_SEC_ST (1 << 7) /* ST: Stop Bit */
\r
78 #define M41T62_ALMON_AFE (1 << 7) /* AFE: alarm flag Enable Bit */
\r
79 #define M41T62_ALMON_SQWE (1 << 6) /* SQWE: SQW Enable Bit */
\r
80 //#define M41T62_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */
\r
81 #define M41T62_FLAGS_AF (1 << 6) /* AF: Alarm Flag Bit */
\r
82 //#define M41T62_FLAGS_BATT_LOW (1 << 4) /* BL: Battery Low Bit */
\r
83 #define M41T62_WATCHDOG_RB2 (1 << 7) /* RB: Watchdog resolution */
\r
84 #define M41T62_WATCHDOG_RB1 (1 << 1) /* RB: Watchdog resolution */
\r
85 #define M41T62_WATCHDOG_RB0 (1 << 0) /* RB: Watchdog resolution */
\r
87 //#define M41T62_FEATURE_HT (1 << 0) /* Halt feature */
\r
88 //#define M41T62_FEATURE_BL (1 << 1) /* Battery low indicator */
\r
89 //#define M41T62_FEATURE_SQ (1 << 2) /* Squarewave feature */
\r
90 //#define M41T62_FEATURE_WD (1 << 3) /* Extra watchdog resolution */
\r
91 //#define M41T62_FEATURE_SQ_ALT (1 << 4) /* RSx bits are in reg 4 */
\r
93 #define REPEAT_SEC 5
\r
94 #define REPEAT_MIN 4
\r
95 #define REPEAT_HOUR 3
\r
96 #define REPEAT_DAY 2
\r
97 #define REPEAT_MON 1
\r
98 #define REPEAT_YEAR 0
\r
99 #define RTC_SPEED 100 * 1000
\r
103 #define DRV_VERSION "0.05"
\r
104 #define DRV_NAME "rtc-M41T66"
\r
106 #define DBG printk//(x...) printk(KERN_INFO "rtc-M41T62:" x)
\r
111 //static struct semaphore rtc_sem;//Ryan
\r
116 struct i2c_client *client;
\r
117 struct work_struct work;
\r
118 struct mutex mutex;
\r
119 struct rtc_device *rtc;
\r
121 struct rtc_wkalrm alarm;
\r
122 struct wake_lock wake_lock;
\r
126 static int rtc_alarm_repeat_set(int mod)
\r
132 static irqreturn_t rtc_wakeup_irq(int irq, void *dev_id)
\r
134 struct rock_rtc *rk_rtc = (struct rock_rtc *)dev_id;
\r
135 DBG("enter %s\n",__func__);
\r
136 disable_irq_nosync(irq);
\r
137 schedule_work(&rk_rtc->work);
\r
138 return IRQ_HANDLED;
\r
142 static int m41t62_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[], unsigned len)
\r
147 ret = i2c_master_reg8_recv(client, reg, buf, len, RTC_SPEED);
\r
150 printk("%s:rtc m41t62 read reg error\n\n\n",__func__);
\r
156 static int m41t62_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[], __u16 len)
\r
159 ret = i2c_master_reg8_send(client, reg, buf, (int)len, RTC_SPEED);
\r
162 printk("%s error>>>>>\n",__func__);
\r
167 static int m41t62_init_device(struct i2c_client *client)
\r
169 //DBG("%s\n",__func__);
\r
171 u8 alarmbuf[M41T62_ALARM_REG_SIZE];
\r
174 //read alarm register current value
\r
175 m41t62_i2c_read_regs(client,M41T62_REG_ALARM_MON,alarmbuf,M41T62_ALARM_REG_SIZE);
\r
178 /*DBG("init alarm mon=0x%x, day=0x%x, hour=0x%x, min=0x%x, sec=0x%x, flags=0x%x\n",
\r
179 alarmbuf[M41T62_REG_ALARM_MON_INDEX],
\r
180 alarmbuf[M41T62_REG_ALARM_DAY_INDEX],
\r
181 alarmbuf[M41T62_REG_ALARM_HOUR_INDEX],
\r
182 alarmbuf[M41T62_REG_ALARM_MIN_INDEX],
\r
183 alarmbuf[M41T62_REG_ALARM_SEC_INDEX],
\r
184 alarmbuf[M41T62_REG_FLAGS_INDEX]);*/
\r
186 //clear alarm register
\r
187 alarmbuf[M41T62_REG_ALARM_MON_INDEX] &= ~(0x1f | M41T62_ALMON_AFE);
\r
188 alarmbuf[M41T62_REG_ALARM_DAY_INDEX] = 0;
\r
189 alarmbuf[M41T62_REG_ALARM_HOUR_INDEX] = 0;
\r
190 alarmbuf[M41T62_REG_ALARM_MIN_INDEX] = 0;
\r
191 alarmbuf[M41T62_REG_ALARM_SEC_INDEX] = 0;
\r
192 alarmbuf[M41T62_REG_FLAGS_INDEX] = 0;
\r
194 //write alarm register
\r
195 m41t62_i2c_set_regs(client,M41T62_REG_ALARM_MON,alarmbuf,M41T62_ALARM_REG_SIZE);
\r
197 //set outclk to 32768HZ
\r
198 m41t62_i2c_read_regs(client,M41T62_REG_SQWDAY,&sqwdayreg,1);
\r
199 sqwdayreg =(sqwdayreg|0x10)&0x1f;
\r
200 m41t62_i2c_set_regs(client,M41T62_REG_SQWDAY,&sqwdayreg,1);
\r
201 //m41t62_i2c_read_regs(client,M41T62_REG_SQWDAY,&sqwdayreg,1);
\r
202 //printk("sqwdayreg:0x%x\n",sqwdayreg);
\r
205 m41t62_i2c_read_regs(client,M41T62_REG_FLAGS,&sqwdayreg,1); //YLZ++
\r
207 printk("%s:rtc m41t2 flag_reg = 0x%x\n",__func__,sqwdayreg);
\r
208 // if(sqwdayreg & 0x04)
\r
211 m41t62_i2c_read_regs(client,M41T62_REG_SEC,&sqwdayreg,1); //YLZ++
\r
212 printk("%s:rtc m41t2 sec_reg = 0x%x\n",__func__,sqwdayreg);
\r
213 sqwdayreg |= 0x80;
\r
214 m41t62_i2c_set_regs(client,M41T62_REG_SEC,&sqwdayreg,1);
\r
216 m41t62_i2c_set_regs(client,M41T62_REG_SEC,&sqwdayreg,1);
\r
217 m41t62_i2c_read_regs(client,M41T62_REG_SEC,&sqwdayreg,1); //YLZ++
\r
218 printk("%s:rtc m41t2 sec_reg = 0x%x\n",__func__,sqwdayreg);
\r
223 m41t62_i2c_read_regs(client,M41T62_REG_FLAGS,&sqwdayreg,1); //YLZ++
\r
224 printk("%s:rtc m41t2 atfer flag_reg = 0x%x\n",__func__,sqwdayreg);
\r
230 static int m41t62_get_datetime(struct i2c_client *client,
\r
231 struct rtc_time *tm)
\r
235 struct rock_rtc *rk_rtc = i2c_get_clientdata(client);
\r
236 u8 datetime[M41T62_DATETIME_REG_SIZE];
\r
239 mutex_lock(&rk_rtc->mutex);
\r
240 ret = m41t62_i2c_read_regs(client,M41T62_REG_SEC,datetime,M41T62_DATETIME_REG_SIZE);
\r
243 printk("%s:read date time from rtc m41t2 error\n",__func__);
\r
249 mutex_unlock(&rk_rtc->mutex);
\r
250 /*DBG("-------M41T62_REG_SEC=%x--",datetime[M41T62_REG_SEC_INDEX]);
\r
251 DBG("-------M41T62_REG_MIN=%x--",datetime[M41T62_REG_MIN_INDEX]);
\r
252 DBG("-------M41T62_REG_HOUR=%x--",datetime[M41T62_REG_HOUR_INDEX]);
\r
253 DBG("-------M41T62_REG_SQWDAY=%x--",datetime[M41T62_REG_SQWDAY_INDEX]);
\r
254 DBG("-------M41T62_REG_DAY=%x--",datetime[M41T62_REG_DAY_INDEX]);
\r
255 DBG("-------M41T62_REG_MON=%x--",datetime[M41T62_REG_MON_INDEX]);
\r
256 DBG("-------M41T62_REG_YEAR=%x--",datetime[M41T62_REG_YEAR_INDEX]);*/
\r
258 tm->tm_sec = bcd2bin(datetime[M41T62_REG_SEC_INDEX]& 0x7f);
\r
259 tm->tm_min = bcd2bin(datetime[M41T62_REG_MIN_INDEX] & 0x7f);
\r
260 tm->tm_hour = bcd2bin(datetime[M41T62_REG_HOUR_INDEX] & 0x3f);
\r
261 tm->tm_mday = bcd2bin(datetime[M41T62_REG_DAY_INDEX] & 0x3f);
\r
262 tm->tm_wday = bcd2bin(datetime[M41T62_REG_SQWDAY_INDEX] & 0x07);
\r
263 tm->tm_mon = bcd2bin(datetime[M41T62_REG_MON_INDEX] & 0x1f) - 1;
\r
264 // assume 20YY not 19YY, and ignore the Century Bit
\r
265 tm->tm_year = bcd2bin(datetime[M41T62_REG_YEAR_INDEX]) + 100;
\r
266 DBG("%s>>>>%4d-%02d-%02d>>wday:%d>>%02d:%02d:%02d>>\n",
\r
267 __func__,tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_wday,
\r
268 tm->tm_hour,tm->tm_min,tm->tm_sec);
\r
270 if(tm->tm_year < 100)
\r
272 printk(KERN_INFO "%s:the time read from the rtc M41T62 is illegal ,\
\r
273 we will use the default time:2010.8.2\n",__func__);
\r
287 /* Sets the given date and time to the real time clock. */
\r
288 static int m41t62_set_datetime(struct i2c_client *client, struct rtc_time *tm)
\r
291 struct rock_rtc *rk_rtc = i2c_get_clientdata(client);
\r
293 u8 datetime[M41T62_DATETIME_REG_SIZE];
\r
295 datetime[M41T62_REG_SEC_INDEX] = bin2bcd(tm->tm_sec);
\r
296 datetime[M41T62_REG_MIN_INDEX] = bin2bcd(tm->tm_min);
\r
297 datetime[M41T62_REG_HOUR_INDEX] =bin2bcd(tm->tm_hour) ;
\r
298 datetime[M41T62_REG_SQWDAY_INDEX] =(tm->tm_wday & 0x07) |0x10;
\r
299 datetime[M41T62_REG_DAY_INDEX] = bin2bcd(tm->tm_mday);
\r
300 datetime[M41T62_REG_MON_INDEX] = bin2bcd(tm->tm_mon + 1) ;
\r
301 /* assume 20YY not 19YY */
\r
302 datetime[M41T62_REG_YEAR_INDEX] = bin2bcd(tm->tm_year % 100);
\r
303 printk(KERN_INFO "%s:set time %4d-%02d-%02d %02d:%02d:%02d to rtc \n",__func__,
\r
304 tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);
\r
306 mutex_lock(&rk_rtc->mutex);
\r
307 ret = m41t62_i2c_set_regs(client,M41T62_REG_SEC,datetime, M41T62_DATETIME_REG_SIZE);
\r
310 printk(KERN_INFO "%s:set time to rtc m41t62 error\n",__func__);
\r
317 mutex_unlock(&rk_rtc->mutex);
\r
322 static int m41t62_rtc_read_time(struct device *dev, struct rtc_time *tm)
\r
324 //DBG("%s>>>>>>>>>>>\n",__func__);
\r
325 return m41t62_get_datetime(to_i2c_client(dev), tm);
\r
328 static int m41t62_rtc_set_time(struct device *dev, struct rtc_time *tm)
\r
330 //DBG("%s\n",__func__);
\r
331 return m41t62_set_datetime(to_i2c_client(dev), tm);
\r
334 #if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE)
\r
335 static int m41t62_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
\r
338 struct i2c_client *client = to_i2c_client(dev);
\r
340 DBG("%s>>>>>>>>>%d\n",__func__ ,cmd);
\r
346 DBG("RTC func m41t62_rtc_ioctl -ENOIOCTLCMD\n");
\r
347 return -ENOIOCTLCMD;
\r
349 DBG("RTC func m41t62_rtc_ioctl 1\n");
\r
350 rc = i2c_smbus_read_byte_data(client, M41T62_REG_ALARM_MON);
\r
355 rc &= ~M41T62_ALMON_AFE;
\r
358 rc |= M41T62_ALMON_AFE;
\r
361 DBG("\n@@@@@@@@@@@RTC func m41t62_rtc_ioctl 2@@@@@@@@@@@@@\n");
\r
362 if (i2c_smbus_write_byte_data(client, M41T62_REG_ALARM_MON, rc) < 0)
\r
364 DBG("\n@@@@@@@@@@@RTC func m41t62_rtc_ioctl 3@@@@@@@@@@@@@\n");
\r
370 #define m41t62_rtc_ioctl NULL
\r
373 static int m41t62_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
\r
375 //DBG("%s>>>>>>>>>>>>\n",__func__);
\r
376 struct i2c_client *client = to_i2c_client(dev);
\r
377 struct rock_rtc *rk_rtc = i2c_get_clientdata(client);
\r
378 struct rtc_time current_time ;
\r
379 u8 alarmbuf[M41T62_ALARM_REG_SIZE];
\r
384 mutex_lock(&rk_rtc->mutex);
\r
385 //read the current value of alarm register
\r
386 m41t62_i2c_read_regs(client,M41T62_REG_ALARM_MON,alarmbuf, M41T62_ALARM_REG_SIZE);
\r
387 mutex_unlock(&rk_rtc->mutex);
\r
389 //clear alarm register
\r
390 alarmbuf[M41T62_REG_ALARM_MON_INDEX] &= ~(0x1f | M41T62_ALMON_AFE);
\r
391 alarmbuf[M41T62_REG_ALARM_DAY_INDEX] = 0;
\r
392 alarmbuf[M41T62_REG_ALARM_HOUR_INDEX] &= ~(0x3f | 0x80);
\r
393 alarmbuf[M41T62_REG_ALARM_MIN_INDEX] = 0;
\r
394 alarmbuf[M41T62_REG_ALARM_SEC_INDEX] = 0;
\r
397 rk_rtc->alarm = *alarm;
\r
398 DBG("time write to alarm :%4d-%02d-%02d %02d:%02d:%02d>>enable:%d\n",
\r
399 alarm->time.tm_year+1900,
\r
400 alarm->time.tm_mon,
\r
401 alarm->time.tm_mday,
\r
402 alarm->time.tm_hour,
\r
403 alarm->time.tm_min,
\r
404 alarm->time.tm_sec,
\r
407 m41t62_get_datetime(client,¤t_time);
\r
408 DBG("current time :%4d-%02d-%02d %02d:%02d:%02d>>\n",
\r
409 current_time.tm_year+1900,
\r
410 current_time.tm_mon,
\r
411 current_time.tm_mday,
\r
412 current_time.tm_hour,
\r
413 current_time.tm_min,
\r
414 current_time.tm_sec);
\r
416 /* offset into rtc's regs */
\r
417 alarmbuf[M41T62_REG_ALARM_SEC_INDEX] |= alarm->time.tm_sec >= 0 ?bin2bcd(alarm->time.tm_sec) : 0x80;
\r
418 alarmbuf[M41T62_REG_ALARM_MIN_INDEX] |= alarm->time.tm_min >= 0 ?bin2bcd(alarm->time.tm_min) : 0x80;
\r
419 alarmbuf[M41T62_REG_ALARM_HOUR_INDEX] |= alarm->time.tm_hour >= 0 ?bin2bcd(alarm->time.tm_hour) : 0x80;
\r
420 alarmbuf[M41T62_REG_ALARM_DAY_INDEX] |= alarm->time.tm_mday >= 0 ?bin2bcd(alarm->time.tm_mday) : 0x80;
\r
421 if (alarm->time.tm_mon >= 0)
\r
422 alarmbuf[M41T62_REG_ALARM_MON_INDEX] |= bin2bcd(alarm->time.tm_mon + 1);
\r
424 alarmbuf[M41T62_REG_ALARM_DAY_INDEX] |= 0x40;
\r
427 //DBG("enable mon day");
\r
428 alarmbuf[M41T62_REG_ALARM_MON_INDEX] |= M41T62_ALMON_AFE ;
\r
429 alarmbuf[M41T62_REG_ALARM_DAY_INDEX] |= 0xc0;//mon, day repeat
\r
430 //reg[M41T62_REG_ALARM_HOUR] |= 0x80;//hour repeat
\r
431 //reg[M41T62_REG_ALARM_MIN] |= 0x80;//min repeat
\r
436 //write alarm register
\r
437 mutex_lock(&rk_rtc->mutex);
\r
438 ret = m41t62_i2c_set_regs(client,M41T62_REG_ALARM_MON,alarmbuf, M41T62_DATETIME_REG_SIZE);
\r
441 printk(KERN_INFO "%s:set rtc m41t62 alarm error\n",__func__);
\r
449 mutex_unlock(&rk_rtc->mutex);
\r
454 static int m41t62_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t)
\r
456 //DBG("%s>>>>>>>>>>>>>\n",__func__);
\r
458 struct i2c_client *client = to_i2c_client(dev);
\r
459 struct rock_rtc *rk_rtc = i2c_get_clientdata(client);
\r
460 u8 alarmreg[M41T62_ALARM_REG_SIZE ]; // all alarm regs and flags
\r
464 mutex_lock(&rk_rtc->mutex);
\r
465 m41t62_i2c_read_regs(client,M41T62_REG_ALARM_MON,alarmreg, M41T62_ALARM_REG_SIZE);
\r
466 mutex_unlock(&rk_rtc->mutex);
\r
468 //printk("read alarm mon=0x%x, day=0x%x, hour=0x%x, min=0x%x, sec=0x%x, flags=0x%x\n",
\r
469 // reg[M41T62_REG_ALARM_MON],
\r
470 // reg[M41T62_REG_ALARM_DAY],
\r
471 // reg[M41T62_REG_ALARM_HOUR],
\r
472 // reg[M41T62_REG_ALARM_MIN],
\r
473 // reg[M41T62_REG_ALARM_SEC],
\r
474 // reg[M41T62_REG_FLAGS]);
\r
475 t->time.tm_sec = -1;
\r
476 t->time.tm_min = -1;
\r
477 t->time.tm_hour = -1;
\r
478 t->time.tm_mday = -1;
\r
479 t->time.tm_mon = -1;
\r
480 if (!(alarmreg[M41T62_REG_ALARM_SEC_INDEX] & 0x80))
\r
481 t->time.tm_sec = bcd2bin(alarmreg[M41T62_REG_ALARM_SEC_INDEX] & 0x7f);
\r
482 if (!(alarmreg[M41T62_REG_ALARM_MIN_INDEX] & 0x80))
\r
483 t->time.tm_min = bcd2bin(alarmreg[M41T62_REG_ALARM_MIN_INDEX] & 0x7f);
\r
484 if (!(alarmreg[M41T62_REG_ALARM_HOUR_INDEX] & 0x80))
\r
485 t->time.tm_hour = bcd2bin(alarmreg[M41T62_REG_ALARM_HOUR_INDEX] & 0x3f);
\r
486 if (!(alarmreg[M41T62_REG_ALARM_DAY_INDEX] & 0x80))
\r
487 t->time.tm_mday = bcd2bin(alarmreg[M41T62_REG_ALARM_DAY_INDEX] & 0x3f);
\r
488 if (!(alarmreg[M41T62_REG_ALARM_DAY_INDEX] & 0x40))
\r
489 t->time.tm_mon = bcd2bin(alarmreg[M41T62_REG_ALARM_MON_INDEX] & 0x1f) - 1;
\r
490 t->time.tm_year = -1;
\r
491 t->time.tm_wday = -1;
\r
492 t->time.tm_yday = -1;
\r
493 t->time.tm_isdst = -1;
\r
494 t->enabled = !!(alarmreg[M41T62_REG_ALARM_MON_INDEX] & M41T62_ALMON_AFE);
\r
495 t->pending = !!(alarmreg[M41T62_REG_FLAGS_INDEX] & M41T62_FLAGS_AF);
\r
498 mutex_lock(&rk_rtc->mutex);
\r
499 ret = m41t62_i2c_read_regs(client,M41T62_REG_ALARM_MON,alarmreg, M41T62_ALARM_REG_SIZE );
\r
502 printk(KERN_INFO "%s:read rtc m41t62 alarm error\n",__func__);
\r
508 mutex_unlock(&rk_rtc->mutex);
\r
509 //printk("read alarm2 mon=0x%x, day=0x%x, hour=0x%x, min=0x%x, sec=0x%x, flags=0x%x\n",
\r
510 // reg[M41T62_REG_ALARM_MON],
\r
511 // reg[M41T62_REG_ALARM_DAY],
\r
512 // reg[M41T62_REG_ALARM_HOUR],
\r
513 // reg[M41T62_REG_ALARM_MIN],
\r
514 // reg[M41T62_REG_ALARM_SEC],
\r
515 // reg[M41T62_REG_FLAGS]);
\r
521 static void rockrtc_work_func(struct work_struct *work)
\r
523 struct rock_rtc *rk_rtc = container_of(work, struct rock_rtc, work);
\r
524 struct i2c_client *client = rk_rtc->client;
\r
525 struct rtc_time now;
\r
528 DBG("enter %s\n",__func__);
\r
530 mutex_lock(&rk_rtc->mutex);
\r
531 m41t62_i2c_read_regs(client,M41T62_REG_FLAGS,&flagreg, 1 );
\r
532 flagreg &=~M41T62_FLAGS_AF ;
\r
533 m41t62_i2c_set_regs(client,M41T62_REG_FLAGS,&flagreg, 1 );
\r
534 mutex_unlock(&rk_rtc->mutex);
\r
536 m41t62_get_datetime(client ,&now);
\r
537 mutex_lock(&rk_rtc->mutex);
\r
538 if (rk_rtc->alarm.enabled && rk_rtc->alarm.time.tm_sec > now.tm_sec)
\r
540 long timeout = rk_rtc->alarm.time.tm_sec - now.tm_sec + 1;
\r
541 pr_info("stay awake %lds\n", timeout);
\r
542 wake_lock_timeout(&rk_rtc->wake_lock, timeout * HZ);
\r
544 if (!rk_rtc->exiting)
\r
545 enable_irq(rk_rtc->irq);
\r
546 mutex_unlock(&rk_rtc->mutex);
\r
550 static struct rtc_class_ops m41t62_rtc_ops = {
\r
551 .read_time = m41t62_rtc_read_time,
\r
552 .set_time = m41t62_rtc_set_time,
\r
553 .read_alarm = m41t62_rtc_read_alarm,
\r
554 .set_alarm = m41t62_rtc_set_alarm,
\r
555 .ioctl = m41t62_rtc_ioctl,
\r
558 #if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE)
\r
559 static ssize_t m41t62_sysfs_show_flags(struct device *dev,
\r
560 struct device_attribute *attr, char *buf)
\r
562 struct i2c_client *client = to_i2c_client(dev);
\r
565 val = i2c_smbus_read_byte_data(client, M41T62_REG_FLAGS);
\r
568 return sprintf(buf, "%#x\n", val);
\r
570 static DEVICE_ATTR(flags, S_IRUGO, m41t62_sysfs_show_flags, NULL);
\r
572 static ssize_t m41t62_sysfs_show_sqwfreq(struct device *dev,
\r
573 struct device_attribute *attr, char *buf)
\r
575 struct i2c_client *client = to_i2c_client(dev);
\r
578 val = i2c_smbus_read_byte_data(client, M41T62_REG_SQW);
\r
581 val = (val >> 4) & 0xf;
\r
589 val = 32768 >> val;
\r
591 return sprintf(buf, "%d\n", val);
\r
593 static ssize_t m41t62_sysfs_set_sqwfreq(struct device *dev,
\r
594 struct device_attribute *attr,
\r
595 const char *buf, size_t count)
\r
597 struct i2c_client *client = to_i2c_client(dev);
\r
599 int val = simple_strtoul(buf, NULL, 0);
\r
602 if (!is_power_of_2(val))
\r
612 /* disable SQW, set SQW frequency & re-enable */
\r
613 almon = i2c_smbus_read_byte_data(client, M41T62_REG_ALARM_MON);
\r
616 sqw = i2c_smbus_read_byte_data(client, M41T62_REG_SQW);
\r
619 sqw = (sqw & 0x0f) | (val << 4);
\r
620 if (i2c_smbus_write_byte_data(client, M41T62_REG_ALARM_MON,
\r
621 almon & ~M41T62_ALMON_SQWE) < 0 ||
\r
622 i2c_smbus_write_byte_data(client, M41T62_REG_SQW, sqw) < 0)
\r
624 if (val && i2c_smbus_write_byte_data(client, M41T62_REG_ALARM_MON,
\r
625 almon | M41T62_ALMON_SQWE) < 0)
\r
629 static DEVICE_ATTR(sqwfreq, S_IRUGO | S_IWUSR,
\r
630 m41t62_sysfs_show_sqwfreq, m41t62_sysfs_set_sqwfreq);
\r
632 static struct attribute *attrs[] = {
\r
633 &dev_attr_flags.attr,
\r
634 &dev_attr_sqwfreq.attr,
\r
637 static struct attribute_group attr_group = {
\r
641 static int m41t62_sysfs_register(struct device *dev)
\r
643 DBG("\n@@@@@@@@@@@m41t62_sysfs_register@@@@@@@@@@@@@\n");
\r
644 return sysfs_create_group(&dev->kobj, &attr_group);
\r
647 static int m41t62_sysfs_register(struct device *dev)
\r
649 DBG("\n@@@@@@@@@@@m41t62_sysfs_register@@@@@@@@@@@@@\n");
\r
658 *****************************************************************************
\r
662 *****************************************************************************
\r
664 static int __devinit m41t62_probe(struct i2c_client *client, const struct i2c_device_id *id)
\r
666 printk("%s>>>>>>>>>>>>>client->flags:%d\n",__func__,client->flags);
\r
668 struct rock_rtc *rk_rtc = NULL;
\r
669 struct rtc_device *rtc = NULL;
\r
670 struct rtc_time tm_read, tm = {
\r
680 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C) ){
\r
682 printk("i2c_check_functionality fail\n");
\r
686 rk_rtc = kzalloc(sizeof(struct rock_rtc), GFP_KERNEL);
\r
691 rtc = rtc_device_register(client->name, &client->dev,
\r
692 &m41t62_rtc_ops, THIS_MODULE);
\r
696 printk("\nm41t62_probe err3\n");
\r
700 rk_rtc->client = client;
\r
703 mutex_init(&rk_rtc->mutex);
\r
704 wake_lock_init(&rk_rtc->wake_lock, WAKE_LOCK_SUSPEND, "rtc_m41t62");
\r
705 INIT_WORK(&rk_rtc->work, rockrtc_work_func);
\r
707 i2c_set_clientdata(client, rk_rtc);
\r
709 rc = m41t62_sysfs_register(&client->dev);
\r
712 printk("\nm41t62_probe err4\n");
\r
717 m41t62_init_device(client);//0323
\r
718 m41t62_get_datetime(client, &tm_read);
\r
719 if((tm_read.tm_year < 111 ) |(tm_read.tm_year > 120 ) |(tm_read.tm_mon > 11))
\r
721 m41t62_set_datetime(client, &tm);
\r
722 printk("%s [%d]run set time \n",__FUNCTION__,__LINE__);
\r
725 if(gpio_request(client->irq, "rtc gpio"))
\r
727 dev_err(&client->dev, "gpio request fail\n");
\r
728 gpio_free(client->irq);
\r
732 rk_rtc->irq = gpio_to_irq(client->irq);
\r
733 gpio_pull_updown(client->irq,GPIOPullUp);
\r
734 if (request_irq(rk_rtc->irq, rtc_wakeup_irq, IRQF_TRIGGER_FALLING, client->dev.driver->name, rk_rtc) < 0)
\r
736 printk("unable to request rtc irq\n");
\r
739 enable_irq_wake(rk_rtc->irq);
\r
745 rtc_device_unregister(rtc);
\r
754 static int __devexit m41t62_remove(struct i2c_client *client)
\r
757 struct rock_rtc *rk_rtc = i2c_get_clientdata(client);
\r
759 if (rk_rtc->irq > 0) {
\r
760 mutex_lock(&rk_rtc->mutex);
\r
761 rk_rtc->exiting = 1;
\r
762 mutex_unlock(&rk_rtc->mutex);
\r
764 free_irq(rk_rtc->irq, rk_rtc);
\r
765 cancel_work_sync(&rk_rtc->work);
\r
768 rtc_device_unregister(rk_rtc->rtc);
\r
769 wake_lock_destroy(&rk_rtc->wake_lock);
\r
776 static const struct i2c_device_id m41t62_id[] = {
\r
780 MODULE_DEVICE_TABLE(i2c, m41t62_id);
\r
783 static struct i2c_driver m41t62_driver = {
\r
786 .owner = THIS_MODULE,
\r
788 .probe = m41t62_probe,
\r
789 .remove = __devexit_p(m41t62_remove),
\r
790 .id_table = m41t62_id,
\r
795 static int __init m41t62_rtc_init(void)
\r
799 printk("%s\n",__func__);
\r
800 ret = i2c_add_driver(&m41t62_driver);
\r
801 printk("%s:return = %d\n",__func__,ret);
\r
805 static void __exit m41t62_rtc_exit(void)
\r
807 DBG("%s>>>>>>>>>\n",__func__);
\r
808 i2c_del_driver(&m41t62_driver);
\r
811 MODULE_AUTHOR("rockchip lhh");
\r
812 MODULE_DESCRIPTION("ST Microelectronics M41T62 series RTC I2C Client Driver");
\r
813 MODULE_LICENSE("GPL");
\r
814 MODULE_VERSION(DRV_VERSION);
\r
816 module_init(m41t62_rtc_init);
\r
817 module_exit(m41t62_rtc_exit);
\r