ds1302.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:12k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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