MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / drivers / rtc / rtc-ds1302.c
blob6054cfd1ff862c004873cce436d333da365f97ec
1 /****************************************************************************/
3 /*
4 * drivers/rtc/rtc-ds1302.c -- DS1302 RTC code
6 * Copyright (C) 2002 David McCullough <davidm@snapgear.com>
7 * Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org>
8 * Copyright (C) 2006 Greg Ungerer <gerg@snapgear.com>
10 * Support for the DS1302 on some Snapgear SH based boards.
13 /****************************************************************************/
15 #include <linux/module.h>
16 #include <linux/kernel.h>
17 #include <linux/init.h>
18 #include <linux/rtc.h>
19 #include <linux/bcd.h>
20 #include <linux/platform_device.h>
21 #include <asm/io.h>
22 #include <asm/snapgear.h>
24 /****************************************************************************/
26 * we need to implement a DS1302 driver here that can operate in
27 * conjunction with the builtin rtc driver which is already quite friendly
29 /*****************************************************************************/
31 #define RTC_CMD_READ 0x81 /* Read command */
32 #define RTC_CMD_WRITE 0x80 /* Write command */
34 #define RTC_ADDR_YEAR 0x06 /* Address of year register */
35 #define RTC_ADDR_DAY 0x05 /* Address of day of week register */
36 #define RTC_ADDR_MON 0x04 /* Address of month register */
37 #define RTC_ADDR_DATE 0x03 /* Address of day of month register */
38 #define RTC_ADDR_HOUR 0x02 /* Address of hour register */
39 #define RTC_ADDR_MIN 0x01 /* Address of minute register */
40 #define RTC_ADDR_SEC 0x00 /* Address of second register */
42 #define RTC_RESET 0x1000
43 #define RTC_IODATA 0x0800
44 #define RTC_SCLK 0x0400
46 #define set_dirp(x)
47 #define get_dirp(x) 0
48 #define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00)
49 #define get_dp(x) SECUREEDGE_READ_IOPORT()
51 static void ds1302_sendbits(unsigned int val)
53 int i;
55 for (i = 8; (i); i--, val >>= 1) {
56 set_dp((get_dp() & ~RTC_IODATA) | ((val & 0x1) ? RTC_IODATA : 0));
57 set_dp(get_dp() | RTC_SCLK); // clock high
58 set_dp(get_dp() & ~RTC_SCLK); // clock low
62 static unsigned int ds1302_recvbits(void)
64 unsigned int val;
65 int i;
67 for (i = 0, val = 0; (i < 8); i++) {
68 val |= (((get_dp() & RTC_IODATA) ? 1 : 0) << i);
69 set_dp(get_dp() | RTC_SCLK); // clock high
70 set_dp(get_dp() & ~RTC_SCLK); // clock low
72 return(val);
75 static unsigned int ds1302_readbyte(unsigned int addr)
77 unsigned int val;
78 unsigned long flags;
80 local_irq_save(flags);
81 set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
82 set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
84 set_dp(get_dp() | RTC_RESET);
85 ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ);
86 set_dirp(get_dirp() & ~RTC_IODATA);
87 val = ds1302_recvbits();
88 set_dp(get_dp() & ~RTC_RESET);
89 local_irq_restore(flags);
91 return(val);
94 static void ds1302_writebyte(unsigned int addr, unsigned int val)
96 unsigned long flags;
98 local_irq_save(flags);
99 set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
100 set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
101 set_dp(get_dp() | RTC_RESET);
102 ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE);
103 ds1302_sendbits(val);
104 set_dp(get_dp() & ~RTC_RESET);
105 local_irq_restore(flags);
108 static void ds1302_reset(void)
110 unsigned long flags;
111 /* Hardware dependant reset/init */
112 local_irq_save(flags);
113 set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
114 set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
115 local_irq_restore(flags);
118 /****************************************************************************/
120 static inline int bcd2bin(int val)
122 return BCD2BIN(val);
125 static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm)
127 tm->tm_sec = bcd2bin(ds1302_readbyte(RTC_ADDR_SEC) & 0x7f);
128 tm->tm_min = bcd2bin(ds1302_readbyte(RTC_ADDR_MIN) & 0x7f);
129 tm->tm_hour = bcd2bin(ds1302_readbyte(RTC_ADDR_HOUR) & 0x3f);
130 tm->tm_wday = bcd2bin(ds1302_readbyte(RTC_ADDR_DAY) & 0x07) - 1;
131 tm->tm_mday = bcd2bin(ds1302_readbyte(RTC_ADDR_DATE) & 0x3f);
132 tm->tm_mon = bcd2bin(ds1302_readbyte(RTC_ADDR_MON) & 0x1f) - 1;
133 tm->tm_year = bcd2bin(ds1302_readbyte(RTC_ADDR_YEAR)) + 100;
135 return 0;
138 static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm)
140 /* STOP RTC */
141 ds1302_writebyte(RTC_ADDR_SEC, 0x80);
143 ds1302_writebyte(RTC_ADDR_MIN, BIN2BCD(tm->tm_min));
144 ds1302_writebyte(RTC_ADDR_HOUR, BIN2BCD(tm->tm_hour));
145 ds1302_writebyte(RTC_ADDR_DAY, BIN2BCD(tm->tm_wday + 1));
146 ds1302_writebyte(RTC_ADDR_DATE, BIN2BCD(tm->tm_mday));
147 ds1302_writebyte(RTC_ADDR_MON, BIN2BCD(tm->tm_mon + 1));
148 ds1302_writebyte(RTC_ADDR_YEAR, BIN2BCD(tm->tm_year - 100));
150 /* RESTARTS RTC */
151 ds1302_writebyte(RTC_ADDR_SEC, BIN2BCD(tm->tm_sec));
153 return 0;
156 /****************************************************************************/
158 static struct rtc_class_ops ds1302_rtc_ops = {
159 .read_time = ds1302_rtc_read_time,
160 .set_time = ds1302_rtc_set_time,
163 /****************************************************************************/
165 static int __devinit ds1302_rtc_probe(struct platform_device *pdev)
167 struct rtc_device *rdev;
168 unsigned char *test = "snapgear";
169 int i;
171 ds1302_reset();
173 for (i = 0; test[i]; i++)
174 ds1302_writebyte(32 + i, test[i]);
176 for (i = 0; test[i]; i++) {
177 if (ds1302_readbyte(32 + i) != test[i])
178 return -ENOENT;
181 rdev = rtc_device_register("ds1302", &pdev->dev, &ds1302_rtc_ops, THIS_MODULE);
183 printk("SnapGear RTC: using ds1302 rtc.\n");
185 platform_set_drvdata(pdev, rdev);
186 return 0;
189 /****************************************************************************/
191 static int __devexit ds1302_rtc_remove(struct platform_device *pdev)
193 struct rtc_device *rdev = platform_get_drvdata(pdev);
195 if (rdev)
196 rtc_device_unregister(rdev);
197 return 0;
200 /****************************************************************************/
202 static struct platform_driver ds1302_rtc_platform_driver = {
203 .driver = {
204 .name = "ds1302",
205 .owner = THIS_MODULE,
207 .probe = ds1302_rtc_probe,
208 .remove = __devexit_p(ds1302_rtc_remove),
211 /****************************************************************************/
213 static int __init ds1302_rtc_init(void)
215 return platform_driver_register(&ds1302_rtc_platform_driver);
218 static void __exit ds1302_rtc_exit(void)
220 platform_driver_unregister(&ds1302_rtc_platform_driver);
223 /****************************************************************************/
225 module_init(ds1302_rtc_init);
226 module_exit(ds1302_rtc_exit);
228 /****************************************************************************/
230 MODULE_DESCRIPTION("DS1302 on SnapGear SH hardware platforms");
231 MODULE_AUTHOR("David McCullough <davidm@snapgear.com>, Paul Mundt <lethal@linux-sh.org>, Greg Ungerer <gerg@snapgear.com>");
232 MODULE_LICENSE("GPL");
234 /****************************************************************************/