diff options
-rw-r--r-- | drivers/i2c/chips/m41t00.c | 313 | ||||
-rw-r--r-- | include/linux/m41t00.h | 50 |
2 files changed, 291 insertions, 72 deletions
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c index eb2be3e4416c..2dd0a34d9472 100644 --- a/drivers/i2c/chips/m41t00.c +++ b/drivers/i2c/chips/m41t00.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * I2C client/driver for the ST M41T00 Real-Time Clock chip. | 2 | * I2C client/driver for the ST M41T00 family of i2c rtc chips. |
3 | * | 3 | * |
4 | * Author: Mark A. Greer <mgreer@mvista.com> | 4 | * Author: Mark A. Greer <mgreer@mvista.com> |
5 | * | 5 | * |
6 | * 2005 (c) MontaVista Software, Inc. This file is licensed under | 6 | * 2005, 2006 (c) MontaVista Software, Inc. This file is licensed under |
7 | * the terms of the GNU General Public License version 2. This program | 7 | * the terms of the GNU General Public License version 2. This program |
8 | * is licensed "as is" without any warranty of any kind, whether express | 8 | * is licensed "as is" without any warranty of any kind, whether express |
9 | * or implied. | 9 | * or implied. |
@@ -19,21 +19,17 @@ | |||
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/rtc.h> | 20 | #include <linux/rtc.h> |
21 | #include <linux/bcd.h> | 21 | #include <linux/bcd.h> |
22 | #include <linux/mutex.h> | ||
23 | #include <linux/workqueue.h> | 22 | #include <linux/workqueue.h> |
24 | 23 | #include <linux/platform_device.h> | |
24 | #include <linux/m41t00.h> | ||
25 | #include <asm/time.h> | 25 | #include <asm/time.h> |
26 | #include <asm/rtc.h> | 26 | #include <asm/rtc.h> |
27 | 27 | ||
28 | #define M41T00_DRV_NAME "m41t00" | ||
29 | |||
30 | static DEFINE_MUTEX(m41t00_mutex); | ||
31 | |||
32 | static struct i2c_driver m41t00_driver; | 28 | static struct i2c_driver m41t00_driver; |
33 | static struct i2c_client *save_client; | 29 | static struct i2c_client *save_client; |
34 | 30 | ||
35 | static unsigned short ignore[] = { I2C_CLIENT_END }; | 31 | static unsigned short ignore[] = { I2C_CLIENT_END }; |
36 | static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END }; | 32 | static unsigned short normal_addr[] = { I2C_CLIENT_END, I2C_CLIENT_END }; |
37 | 33 | ||
38 | static struct i2c_client_address_data addr_data = { | 34 | static struct i2c_client_address_data addr_data = { |
39 | .normal_i2c = normal_addr, | 35 | .normal_i2c = normal_addr, |
@@ -41,34 +37,92 @@ static struct i2c_client_address_data addr_data = { | |||
41 | .ignore = ignore, | 37 | .ignore = ignore, |
42 | }; | 38 | }; |
43 | 39 | ||
40 | struct m41t00_chip_info { | ||
41 | u8 type; | ||
42 | char *name; | ||
43 | u8 read_limit; | ||
44 | u8 sec; /* Offsets for chip regs */ | ||
45 | u8 min; | ||
46 | u8 hour; | ||
47 | u8 day; | ||
48 | u8 mon; | ||
49 | u8 year; | ||
50 | u8 alarm_mon; | ||
51 | u8 alarm_hour; | ||
52 | u8 sqw; | ||
53 | u8 sqw_freq; | ||
54 | }; | ||
55 | |||
56 | static struct m41t00_chip_info m41t00_chip_info_tbl[] = { | ||
57 | { | ||
58 | .type = M41T00_TYPE_M41T00, | ||
59 | .name = "m41t00", | ||
60 | .read_limit = 5, | ||
61 | .sec = 0, | ||
62 | .min = 1, | ||
63 | .hour = 2, | ||
64 | .day = 4, | ||
65 | .mon = 5, | ||
66 | .year = 6, | ||
67 | }, | ||
68 | { | ||
69 | .type = M41T00_TYPE_M41T81, | ||
70 | .name = "m41t81", | ||
71 | .read_limit = 1, | ||
72 | .sec = 1, | ||
73 | .min = 2, | ||
74 | .hour = 3, | ||
75 | .day = 5, | ||
76 | .mon = 6, | ||
77 | .year = 7, | ||
78 | .alarm_mon = 0xa, | ||
79 | .alarm_hour = 0xc, | ||
80 | .sqw = 0x13, | ||
81 | }, | ||
82 | { | ||
83 | .type = M41T00_TYPE_M41T85, | ||
84 | .name = "m41t85", | ||
85 | .read_limit = 1, | ||
86 | .sec = 1, | ||
87 | .min = 2, | ||
88 | .hour = 3, | ||
89 | .day = 5, | ||
90 | .mon = 6, | ||
91 | .year = 7, | ||
92 | .alarm_mon = 0xa, | ||
93 | .alarm_hour = 0xc, | ||
94 | .sqw = 0x13, | ||
95 | }, | ||
96 | }; | ||
97 | static struct m41t00_chip_info *m41t00_chip; | ||
98 | |||
44 | ulong | 99 | ulong |
45 | m41t00_get_rtc_time(void) | 100 | m41t00_get_rtc_time(void) |
46 | { | 101 | { |
47 | s32 sec, min, hour, day, mon, year; | 102 | s32 sec, min, hour, day, mon, year; |
48 | s32 sec1, min1, hour1, day1, mon1, year1; | 103 | s32 sec1, min1, hour1, day1, mon1, year1; |
49 | ulong limit = 10; | 104 | u8 reads = 0; |
105 | u8 buf[8], msgbuf[1] = { 0 }; /* offset into rtc's regs */ | ||
106 | struct i2c_msg msgs[] = { | ||
107 | { | ||
108 | .addr = save_client->addr, | ||
109 | .flags = 0, | ||
110 | .len = 1, | ||
111 | .buf = msgbuf, | ||
112 | }, | ||
113 | { | ||
114 | .addr = save_client->addr, | ||
115 | .flags = I2C_M_RD, | ||
116 | .len = 8, | ||
117 | .buf = buf, | ||
118 | }, | ||
119 | }; | ||
50 | 120 | ||
51 | sec = min = hour = day = mon = year = 0; | 121 | sec = min = hour = day = mon = year = 0; |
52 | sec1 = min1 = hour1 = day1 = mon1 = year1 = 0; | ||
53 | 122 | ||
54 | mutex_lock(&m41t00_mutex); | ||
55 | do { | 123 | do { |
56 | if (((sec = i2c_smbus_read_byte_data(save_client, 0)) >= 0) | 124 | if (i2c_transfer(save_client->adapter, msgs, 2) < 0) |
57 | && ((min = i2c_smbus_read_byte_data(save_client, 1)) | 125 | goto read_err; |
58 | >= 0) | ||
59 | && ((hour = i2c_smbus_read_byte_data(save_client, 2)) | ||
60 | >= 0) | ||
61 | && ((day = i2c_smbus_read_byte_data(save_client, 4)) | ||
62 | >= 0) | ||
63 | && ((mon = i2c_smbus_read_byte_data(save_client, 5)) | ||
64 | >= 0) | ||
65 | && ((year = i2c_smbus_read_byte_data(save_client, 6)) | ||
66 | >= 0) | ||
67 | && ((sec == sec1) && (min == min1) && (hour == hour1) | ||
68 | && (day == day1) && (mon == mon1) | ||
69 | && (year == year1))) | ||
70 | |||
71 | break; | ||
72 | 126 | ||
73 | sec1 = sec; | 127 | sec1 = sec; |
74 | min1 = min; | 128 | min1 = min; |
@@ -76,21 +130,21 @@ m41t00_get_rtc_time(void) | |||
76 | day1 = day; | 130 | day1 = day; |
77 | mon1 = mon; | 131 | mon1 = mon; |
78 | year1 = year; | 132 | year1 = year; |
79 | } while (--limit > 0); | ||
80 | mutex_unlock(&m41t00_mutex); | ||
81 | |||
82 | if (limit == 0) { | ||
83 | dev_warn(&save_client->dev, | ||
84 | "m41t00: can't read rtc chip\n"); | ||
85 | sec = min = hour = day = mon = year = 0; | ||
86 | } | ||
87 | 133 | ||
88 | sec &= 0x7f; | 134 | sec = buf[m41t00_chip->sec] & 0x7f; |
89 | min &= 0x7f; | 135 | min = buf[m41t00_chip->min] & 0x7f; |
90 | hour &= 0x3f; | 136 | hour = buf[m41t00_chip->hour] & 0x3f; |
91 | day &= 0x3f; | 137 | day = buf[m41t00_chip->day] & 0x3f; |
92 | mon &= 0x1f; | 138 | mon = buf[m41t00_chip->mon] & 0x1f; |
93 | year &= 0xff; | 139 | year = buf[m41t00_chip->year]; |
140 | } while ((++reads < m41t00_chip->read_limit) && ((sec != sec1) | ||
141 | || (min != min1) || (hour != hour1) || (day != day1) | ||
142 | || (mon != mon1) || (year != year1))); | ||
143 | |||
144 | if ((m41t00_chip->read_limit > 1) && ((sec != sec1) || (min != min1) | ||
145 | || (hour != hour1) || (day != day1) || (mon != mon1) | ||
146 | || (year != year1))) | ||
147 | goto read_err; | ||
94 | 148 | ||
95 | sec = BCD2BIN(sec); | 149 | sec = BCD2BIN(sec); |
96 | min = BCD2BIN(min); | 150 | min = BCD2BIN(min); |
@@ -104,40 +158,60 @@ m41t00_get_rtc_time(void) | |||
104 | year += 100; | 158 | year += 100; |
105 | 159 | ||
106 | return mktime(year, mon, day, hour, min, sec); | 160 | return mktime(year, mon, day, hour, min, sec); |
161 | |||
162 | read_err: | ||
163 | dev_err(&save_client->dev, "m41t00_get_rtc_time: Read error\n"); | ||
164 | return 0; | ||
107 | } | 165 | } |
166 | EXPORT_SYMBOL_GPL(m41t00_get_rtc_time); | ||
108 | 167 | ||
109 | static void | 168 | static void |
110 | m41t00_set(void *arg) | 169 | m41t00_set(void *arg) |
111 | { | 170 | { |
112 | struct rtc_time tm; | 171 | struct rtc_time tm; |
113 | ulong nowtime = *(ulong *)arg; | 172 | int nowtime = *(int *)arg; |
173 | s32 sec, min, hour, day, mon, year; | ||
174 | u8 wbuf[9], *buf = &wbuf[1], msgbuf[1] = { 0 }; | ||
175 | struct i2c_msg msgs[] = { | ||
176 | { | ||
177 | .addr = save_client->addr, | ||
178 | .flags = 0, | ||
179 | .len = 1, | ||
180 | .buf = msgbuf, | ||
181 | }, | ||
182 | { | ||
183 | .addr = save_client->addr, | ||
184 | .flags = I2C_M_RD, | ||
185 | .len = 8, | ||
186 | .buf = buf, | ||
187 | }, | ||
188 | }; | ||
114 | 189 | ||
115 | to_tm(nowtime, &tm); | 190 | to_tm(nowtime, &tm); |
116 | tm.tm_year = (tm.tm_year - 1900) % 100; | 191 | tm.tm_year = (tm.tm_year - 1900) % 100; |
117 | 192 | ||
118 | tm.tm_sec = BIN2BCD(tm.tm_sec); | 193 | sec = BIN2BCD(tm.tm_sec); |
119 | tm.tm_min = BIN2BCD(tm.tm_min); | 194 | min = BIN2BCD(tm.tm_min); |
120 | tm.tm_hour = BIN2BCD(tm.tm_hour); | 195 | hour = BIN2BCD(tm.tm_hour); |
121 | tm.tm_mon = BIN2BCD(tm.tm_mon); | 196 | day = BIN2BCD(tm.tm_mday); |
122 | tm.tm_mday = BIN2BCD(tm.tm_mday); | 197 | mon = BIN2BCD(tm.tm_mon); |
123 | tm.tm_year = BIN2BCD(tm.tm_year); | 198 | year = BIN2BCD(tm.tm_year); |
124 | 199 | ||
125 | mutex_lock(&m41t00_mutex); | 200 | /* Read reg values into buf[0..7]/wbuf[1..8] */ |
126 | if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0) | 201 | if (i2c_transfer(save_client->adapter, msgs, 2) < 0) { |
127 | || (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f) | 202 | dev_err(&save_client->dev, "m41t00_set: Read error\n"); |
128 | < 0) | 203 | return; |
129 | || (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x3f) | 204 | } |
130 | < 0) | 205 | |
131 | || (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x3f) | 206 | wbuf[0] = 0; /* offset into rtc's regs */ |
132 | < 0) | 207 | buf[m41t00_chip->sec] = (buf[m41t00_chip->sec] & ~0x7f) | (sec & 0x7f); |
133 | || (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x1f) | 208 | buf[m41t00_chip->min] = (buf[m41t00_chip->min] & ~0x7f) | (min & 0x7f); |
134 | < 0) | 209 | buf[m41t00_chip->hour] = (buf[m41t00_chip->hour] & ~0x3f) | (hour& 0x3f); |
135 | || (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0xff) | 210 | buf[m41t00_chip->day] = (buf[m41t00_chip->day] & ~0x3f) | (day & 0x3f); |
136 | < 0)) | 211 | buf[m41t00_chip->mon] = (buf[m41t00_chip->mon] & ~0x1f) | (mon & 0x1f); |
137 | 212 | ||
138 | dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n"); | 213 | if (i2c_master_send(save_client, wbuf, 9) < 0) |
139 | 214 | dev_err(&save_client->dev, "m41t00_set: Write error\n"); | |
140 | mutex_unlock(&m41t00_mutex); | ||
141 | } | 215 | } |
142 | 216 | ||
143 | static ulong new_time; | 217 | static ulong new_time; |
@@ -156,6 +230,48 @@ m41t00_set_rtc_time(ulong nowtime) | |||
156 | 230 | ||
157 | return 0; | 231 | return 0; |
158 | } | 232 | } |
233 | EXPORT_SYMBOL_GPL(m41t00_set_rtc_time); | ||
234 | |||
235 | /* | ||
236 | ***************************************************************************** | ||
237 | * | ||
238 | * platform_data Driver Interface | ||
239 | * | ||
240 | ***************************************************************************** | ||
241 | */ | ||
242 | static int __init | ||
243 | m41t00_platform_probe(struct platform_device *pdev) | ||
244 | { | ||
245 | struct m41t00_platform_data *pdata; | ||
246 | int i; | ||
247 | |||
248 | if (pdev && (pdata = pdev->dev.platform_data)) { | ||
249 | normal_addr[0] = pdata->i2c_addr; | ||
250 | |||
251 | for (i=0; i<ARRAY_SIZE(m41t00_chip_info_tbl); i++) | ||
252 | if (m41t00_chip_info_tbl[i].type == pdata->type) { | ||
253 | m41t00_chip = &m41t00_chip_info_tbl[i]; | ||
254 | m41t00_chip->sqw_freq = pdata->sqw_freq; | ||
255 | return 0; | ||
256 | } | ||
257 | } | ||
258 | return -ENODEV; | ||
259 | } | ||
260 | |||
261 | static int __exit | ||
262 | m41t00_platform_remove(struct platform_device *pdev) | ||
263 | { | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static struct platform_driver m41t00_platform_driver = { | ||
268 | .probe = m41t00_platform_probe, | ||
269 | .remove = m41t00_platform_remove, | ||
270 | .driver = { | ||
271 | .owner = THIS_MODULE, | ||
272 | .name = M41T00_DRV_NAME, | ||
273 | }, | ||
274 | }; | ||
159 | 275 | ||
160 | /* | 276 | /* |
161 | ***************************************************************************** | 277 | ***************************************************************************** |
@@ -170,23 +286,71 @@ m41t00_probe(struct i2c_adapter *adap, int addr, int kind) | |||
170 | struct i2c_client *client; | 286 | struct i2c_client *client; |
171 | int rc; | 287 | int rc; |
172 | 288 | ||
289 | if (!i2c_check_functionality(adap, I2C_FUNC_I2C | ||
290 | | I2C_FUNC_SMBUS_BYTE_DATA)) | ||
291 | return 0; | ||
292 | |||
173 | client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | 293 | client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); |
174 | if (!client) | 294 | if (!client) |
175 | return -ENOMEM; | 295 | return -ENOMEM; |
176 | 296 | ||
177 | strlcpy(client->name, M41T00_DRV_NAME, I2C_NAME_SIZE); | 297 | strlcpy(client->name, m41t00_chip->name, I2C_NAME_SIZE); |
178 | client->addr = addr; | 298 | client->addr = addr; |
179 | client->adapter = adap; | 299 | client->adapter = adap; |
180 | client->driver = &m41t00_driver; | 300 | client->driver = &m41t00_driver; |
181 | 301 | ||
182 | if ((rc = i2c_attach_client(client)) != 0) { | 302 | if ((rc = i2c_attach_client(client))) |
183 | kfree(client); | 303 | goto attach_err; |
184 | return rc; | 304 | |
305 | if (m41t00_chip->type != M41T00_TYPE_M41T00) { | ||
306 | /* If asked, disable SQW, set SQW frequency & re-enable */ | ||
307 | if (m41t00_chip->sqw_freq) | ||
308 | if (((rc = i2c_smbus_read_byte_data(client, | ||
309 | m41t00_chip->alarm_mon)) < 0) | ||
310 | || ((rc = i2c_smbus_write_byte_data(client, | ||
311 | m41t00_chip->alarm_mon, rc & ~0x40)) <0) | ||
312 | || ((rc = i2c_smbus_write_byte_data(client, | ||
313 | m41t00_chip->sqw, | ||
314 | m41t00_chip->sqw_freq)) < 0) | ||
315 | || ((rc = i2c_smbus_write_byte_data(client, | ||
316 | m41t00_chip->alarm_mon, rc | 0x40)) <0)) | ||
317 | goto sqw_err; | ||
318 | |||
319 | /* Make sure HT (Halt Update) bit is cleared */ | ||
320 | if ((rc = i2c_smbus_read_byte_data(client, | ||
321 | m41t00_chip->alarm_hour)) < 0) | ||
322 | goto ht_err; | ||
323 | |||
324 | if (rc & 0x40) | ||
325 | if ((rc = i2c_smbus_write_byte_data(client, | ||
326 | m41t00_chip->alarm_hour, rc & ~0x40))<0) | ||
327 | goto ht_err; | ||
185 | } | 328 | } |
186 | 329 | ||
187 | m41t00_wq = create_singlethread_workqueue("m41t00"); | 330 | /* Make sure ST (stop) bit is cleared */ |
331 | if ((rc = i2c_smbus_read_byte_data(client, m41t00_chip->sec)) < 0) | ||
332 | goto st_err; | ||
333 | |||
334 | if (rc & 0x80) | ||
335 | if ((rc = i2c_smbus_write_byte_data(client, m41t00_chip->sec, | ||
336 | rc & ~0x80)) < 0) | ||
337 | goto st_err; | ||
338 | |||
339 | m41t00_wq = create_singlethread_workqueue(m41t00_chip->name); | ||
188 | save_client = client; | 340 | save_client = client; |
189 | return 0; | 341 | return 0; |
342 | |||
343 | st_err: | ||
344 | dev_err(&client->dev, "m41t00_probe: Can't clear ST bit\n"); | ||
345 | goto attach_err; | ||
346 | ht_err: | ||
347 | dev_err(&client->dev, "m41t00_probe: Can't clear HT bit\n"); | ||
348 | goto attach_err; | ||
349 | sqw_err: | ||
350 | dev_err(&client->dev, "m41t00_probe: Can't set SQW Frequency\n"); | ||
351 | attach_err: | ||
352 | kfree(client); | ||
353 | return rc; | ||
190 | } | 354 | } |
191 | 355 | ||
192 | static int | 356 | static int |
@@ -219,13 +383,18 @@ static struct i2c_driver m41t00_driver = { | |||
219 | static int __init | 383 | static int __init |
220 | m41t00_init(void) | 384 | m41t00_init(void) |
221 | { | 385 | { |
222 | return i2c_add_driver(&m41t00_driver); | 386 | int rc; |
387 | |||
388 | if (!(rc = platform_driver_register(&m41t00_platform_driver))) | ||
389 | rc = i2c_add_driver(&m41t00_driver); | ||
390 | return rc; | ||
223 | } | 391 | } |
224 | 392 | ||
225 | static void __exit | 393 | static void __exit |
226 | m41t00_exit(void) | 394 | m41t00_exit(void) |
227 | { | 395 | { |
228 | i2c_del_driver(&m41t00_driver); | 396 | i2c_del_driver(&m41t00_driver); |
397 | platform_driver_unregister(&m41t00_platform_driver); | ||
229 | } | 398 | } |
230 | 399 | ||
231 | module_init(m41t00_init); | 400 | module_init(m41t00_init); |
diff --git a/include/linux/m41t00.h b/include/linux/m41t00.h new file mode 100644 index 000000000000..b423360ca38e --- /dev/null +++ b/include/linux/m41t00.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * Definitions for the ST M41T00 family of i2c rtc chips. | ||
3 | * | ||
4 | * Author: Mark A. Greer <mgreer@mvista.com> | ||
5 | * | ||
6 | * 2005, 2006 (c) MontaVista Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #ifndef _M41T00_H | ||
13 | #define _M41T00_H | ||
14 | |||
15 | #define M41T00_DRV_NAME "m41t00" | ||
16 | #define M41T00_I2C_ADDR 0x68 | ||
17 | |||
18 | #define M41T00_TYPE_M41T00 0 | ||
19 | #define M41T00_TYPE_M41T81 81 | ||
20 | #define M41T00_TYPE_M41T85 85 | ||
21 | |||
22 | struct m41t00_platform_data { | ||
23 | u8 type; | ||
24 | u8 i2c_addr; | ||
25 | u8 sqw_freq; | ||
26 | }; | ||
27 | |||
28 | /* SQW output disabled, this is default value by power on */ | ||
29 | #define M41T00_SQW_DISABLE (0) | ||
30 | |||
31 | #define M41T00_SQW_32KHZ (1<<4) /* 32.768 KHz */ | ||
32 | #define M41T00_SQW_8KHZ (2<<4) /* 8.192 KHz */ | ||
33 | #define M41T00_SQW_4KHZ (3<<4) /* 4.096 KHz */ | ||
34 | #define M41T00_SQW_2KHZ (4<<4) /* 2.048 KHz */ | ||
35 | #define M41T00_SQW_1KHZ (5<<4) /* 1.024 KHz */ | ||
36 | #define M41T00_SQW_512HZ (6<<4) /* 512 Hz */ | ||
37 | #define M41T00_SQW_256HZ (7<<4) /* 256 Hz */ | ||
38 | #define M41T00_SQW_128HZ (8<<4) /* 128 Hz */ | ||
39 | #define M41T00_SQW_64HZ (9<<4) /* 64 Hz */ | ||
40 | #define M41T00_SQW_32HZ (10<<4) /* 32 Hz */ | ||
41 | #define M41T00_SQW_16HZ (11<<4) /* 16 Hz */ | ||
42 | #define M41T00_SQW_8HZ (12<<4) /* 8 Hz */ | ||
43 | #define M41T00_SQW_4HZ (13<<4) /* 4 Hz */ | ||
44 | #define M41T00_SQW_2HZ (14<<4) /* 2 Hz */ | ||
45 | #define M41T00_SQW_1HZ (15<<4) /* 1 Hz */ | ||
46 | |||
47 | extern ulong m41t00_get_rtc_time(void); | ||
48 | extern int m41t00_set_rtc_time(ulong nowtime); | ||
49 | |||
50 | #endif /* _M41T00_H */ | ||