diff options
author | David Brownell <david-b@pacbell.net> | 2008-07-24 00:30:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-24 13:47:33 -0400 |
commit | 53e84b672c1a8190af2b376c35c7a39cf1214f59 (patch) | |
tree | 660b29a2ecde189abf799ff3bb5c142434707638 /drivers/rtc/rtc-ds1305.c | |
parent | 8fc2c767b06067b417c565c4e75731e68ed41fd8 (diff) |
rtc: ds1305/ds1306 driver
Support the Dallas/Maxim DS1305 and DS1306 RTC chips. These use SPI, and
support alarms, NVRAM, and a trickle charger for use when their backup
power supply is a supercap or rechargeable cell.
This basic driver doesn't yet support suspend/resume or wakealarms.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc/rtc-ds1305.c')
-rw-r--r-- | drivers/rtc/rtc-ds1305.c | 847 |
1 files changed, 847 insertions, 0 deletions
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c new file mode 100644 index 000000000000..b91d02a3ace9 --- /dev/null +++ b/drivers/rtc/rtc-ds1305.c | |||
@@ -0,0 +1,847 @@ | |||
1 | /* | ||
2 | * rtc-ds1305.c -- driver for DS1305 and DS1306 SPI RTC chips | ||
3 | * | ||
4 | * Copyright (C) 2008 David Brownell | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/bcd.h> | ||
14 | #include <linux/rtc.h> | ||
15 | #include <linux/workqueue.h> | ||
16 | |||
17 | #include <linux/spi/spi.h> | ||
18 | #include <linux/spi/ds1305.h> | ||
19 | |||
20 | |||
21 | /* | ||
22 | * Registers ... mask DS1305_WRITE into register address to write, | ||
23 | * otherwise you're reading it. All non-bitmask values are BCD. | ||
24 | */ | ||
25 | #define DS1305_WRITE 0x80 | ||
26 | |||
27 | |||
28 | /* RTC date/time ... the main special cases are that we: | ||
29 | * - Need fancy "hours" encoding in 12hour mode | ||
30 | * - Don't rely on the "day-of-week" field (or tm_wday) | ||
31 | * - Are a 21st-century clock (2000 <= year < 2100) | ||
32 | */ | ||
33 | #define DS1305_RTC_LEN 7 /* bytes for RTC regs */ | ||
34 | |||
35 | #define DS1305_SEC 0x00 /* register addresses */ | ||
36 | #define DS1305_MIN 0x01 | ||
37 | #define DS1305_HOUR 0x02 | ||
38 | # define DS1305_HR_12 0x40 /* set == 12 hr mode */ | ||
39 | # define DS1305_HR_PM 0x20 /* set == PM (12hr mode) */ | ||
40 | #define DS1305_WDAY 0x03 | ||
41 | #define DS1305_MDAY 0x04 | ||
42 | #define DS1305_MON 0x05 | ||
43 | #define DS1305_YEAR 0x06 | ||
44 | |||
45 | |||
46 | /* The two alarms have only sec/min/hour/wday fields (ALM_LEN). | ||
47 | * DS1305_ALM_DISABLE disables a match field (some combos are bad). | ||
48 | * | ||
49 | * NOTE that since we don't use WDAY, we limit ourselves to alarms | ||
50 | * only one day into the future (vs potentially up to a week). | ||
51 | * | ||
52 | * NOTE ALSO that while we could generate once-a-second IRQs (UIE), we | ||
53 | * don't currently support them. We'd either need to do it only when | ||
54 | * no alarm is pending (not the standard model), or to use the second | ||
55 | * alarm (implying that this is a DS1305 not DS1306, *and* that either | ||
56 | * it's wired up a second IRQ we know, or that INTCN is set) | ||
57 | */ | ||
58 | #define DS1305_ALM_LEN 4 /* bytes for ALM regs */ | ||
59 | #define DS1305_ALM_DISABLE 0x80 | ||
60 | |||
61 | #define DS1305_ALM0(r) (0x07 + (r)) /* register addresses */ | ||
62 | #define DS1305_ALM1(r) (0x0b + (r)) | ||
63 | |||
64 | |||
65 | /* three control registers */ | ||
66 | #define DS1305_CONTROL_LEN 3 /* bytes of control regs */ | ||
67 | |||
68 | #define DS1305_CONTROL 0x0f /* register addresses */ | ||
69 | # define DS1305_nEOSC 0x80 /* low enables oscillator */ | ||
70 | # define DS1305_WP 0x40 /* write protect */ | ||
71 | # define DS1305_INTCN 0x04 /* clear == only int0 used */ | ||
72 | # define DS1306_1HZ 0x04 /* enable 1Hz output */ | ||
73 | # define DS1305_AEI1 0x02 /* enable ALM1 IRQ */ | ||
74 | # define DS1305_AEI0 0x01 /* enable ALM0 IRQ */ | ||
75 | #define DS1305_STATUS 0x10 | ||
76 | /* status has just AEIx bits, mirrored as IRQFx */ | ||
77 | #define DS1305_TRICKLE 0x11 | ||
78 | /* trickle bits are defined in <linux/spi/ds1305.h> */ | ||
79 | |||
80 | /* a bunch of NVRAM */ | ||
81 | #define DS1305_NVRAM_LEN 96 /* bytes of NVRAM */ | ||
82 | |||
83 | #define DS1305_NVRAM 0x20 /* register addresses */ | ||
84 | |||
85 | |||
86 | struct ds1305 { | ||
87 | struct spi_device *spi; | ||
88 | struct rtc_device *rtc; | ||
89 | |||
90 | struct work_struct work; | ||
91 | |||
92 | unsigned long flags; | ||
93 | #define FLAG_EXITING 0 | ||
94 | |||
95 | bool hr12; | ||
96 | u8 ctrl[DS1305_CONTROL_LEN]; | ||
97 | }; | ||
98 | |||
99 | |||
100 | /*----------------------------------------------------------------------*/ | ||
101 | |||
102 | /* | ||
103 | * Utilities ... tolerate 12-hour AM/PM notation in case of non-Linux | ||
104 | * software (like a bootloader) which may require it. | ||
105 | */ | ||
106 | |||
107 | static unsigned bcd2hour(u8 bcd) | ||
108 | { | ||
109 | if (bcd & DS1305_HR_12) { | ||
110 | unsigned hour = 0; | ||
111 | |||
112 | bcd &= ~DS1305_HR_12; | ||
113 | if (bcd & DS1305_HR_PM) { | ||
114 | hour = 12; | ||
115 | bcd &= ~DS1305_HR_PM; | ||
116 | } | ||
117 | hour += BCD2BIN(bcd); | ||
118 | return hour - 1; | ||
119 | } | ||
120 | return BCD2BIN(bcd); | ||
121 | } | ||
122 | |||
123 | static u8 hour2bcd(bool hr12, int hour) | ||
124 | { | ||
125 | if (hr12) { | ||
126 | hour++; | ||
127 | if (hour <= 12) | ||
128 | return DS1305_HR_12 | BIN2BCD(hour); | ||
129 | hour -= 12; | ||
130 | return DS1305_HR_12 | DS1305_HR_PM | BIN2BCD(hour); | ||
131 | } | ||
132 | return BIN2BCD(hour); | ||
133 | } | ||
134 | |||
135 | /*----------------------------------------------------------------------*/ | ||
136 | |||
137 | /* | ||
138 | * Interface to RTC framework | ||
139 | */ | ||
140 | |||
141 | #ifdef CONFIG_RTC_INTF_DEV | ||
142 | |||
143 | /* | ||
144 | * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl) | ||
145 | */ | ||
146 | static int ds1305_ioctl(struct device *dev, unsigned cmd, unsigned long arg) | ||
147 | { | ||
148 | struct ds1305 *ds1305 = dev_get_drvdata(dev); | ||
149 | u8 buf[2]; | ||
150 | int status = -ENOIOCTLCMD; | ||
151 | |||
152 | buf[0] = DS1305_WRITE | DS1305_CONTROL; | ||
153 | buf[1] = ds1305->ctrl[0]; | ||
154 | |||
155 | switch (cmd) { | ||
156 | case RTC_AIE_OFF: | ||
157 | status = 0; | ||
158 | if (!(buf[1] & DS1305_AEI0)) | ||
159 | goto done; | ||
160 | buf[1] &= ~DS1305_AEI0; | ||
161 | break; | ||
162 | |||
163 | case RTC_AIE_ON: | ||
164 | status = 0; | ||
165 | if (ds1305->ctrl[0] & DS1305_AEI0) | ||
166 | goto done; | ||
167 | buf[1] |= DS1305_AEI0; | ||
168 | break; | ||
169 | } | ||
170 | if (status == 0) { | ||
171 | status = spi_write_then_read(ds1305->spi, buf, sizeof buf, | ||
172 | NULL, 0); | ||
173 | if (status >= 0) | ||
174 | ds1305->ctrl[0] = buf[1]; | ||
175 | } | ||
176 | |||
177 | done: | ||
178 | return status; | ||
179 | } | ||
180 | |||
181 | #else | ||
182 | #define ds1305_ioctl NULL | ||
183 | #endif | ||
184 | |||
185 | /* | ||
186 | * Get/set of date and time is pretty normal. | ||
187 | */ | ||
188 | |||
189 | static int ds1305_get_time(struct device *dev, struct rtc_time *time) | ||
190 | { | ||
191 | struct ds1305 *ds1305 = dev_get_drvdata(dev); | ||
192 | u8 addr = DS1305_SEC; | ||
193 | u8 buf[DS1305_RTC_LEN]; | ||
194 | int status; | ||
195 | |||
196 | /* Use write-then-read to get all the date/time registers | ||
197 | * since dma from stack is nonportable | ||
198 | */ | ||
199 | status = spi_write_then_read(ds1305->spi, &addr, sizeof addr, | ||
200 | buf, sizeof buf); | ||
201 | if (status < 0) | ||
202 | return status; | ||
203 | |||
204 | dev_vdbg(dev, "%s: %02x %02x %02x, %02x %02x %02x %02x\n", | ||
205 | "read", buf[0], buf[1], buf[2], buf[3], | ||
206 | buf[4], buf[5], buf[6]); | ||
207 | |||
208 | /* Decode the registers */ | ||
209 | time->tm_sec = BCD2BIN(buf[DS1305_SEC]); | ||
210 | time->tm_min = BCD2BIN(buf[DS1305_MIN]); | ||
211 | time->tm_hour = bcd2hour(buf[DS1305_HOUR]); | ||
212 | time->tm_wday = buf[DS1305_WDAY] - 1; | ||
213 | time->tm_mday = BCD2BIN(buf[DS1305_MDAY]); | ||
214 | time->tm_mon = BCD2BIN(buf[DS1305_MON]) - 1; | ||
215 | time->tm_year = BCD2BIN(buf[DS1305_YEAR]) + 100; | ||
216 | |||
217 | dev_vdbg(dev, "%s secs=%d, mins=%d, " | ||
218 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", | ||
219 | "read", time->tm_sec, time->tm_min, | ||
220 | time->tm_hour, time->tm_mday, | ||
221 | time->tm_mon, time->tm_year, time->tm_wday); | ||
222 | |||
223 | /* Time may not be set */ | ||
224 | return rtc_valid_tm(time); | ||
225 | } | ||
226 | |||
227 | static int ds1305_set_time(struct device *dev, struct rtc_time *time) | ||
228 | { | ||
229 | struct ds1305 *ds1305 = dev_get_drvdata(dev); | ||
230 | u8 buf[1 + DS1305_RTC_LEN]; | ||
231 | u8 *bp = buf; | ||
232 | |||
233 | dev_vdbg(dev, "%s secs=%d, mins=%d, " | ||
234 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", | ||
235 | "write", time->tm_sec, time->tm_min, | ||
236 | time->tm_hour, time->tm_mday, | ||
237 | time->tm_mon, time->tm_year, time->tm_wday); | ||
238 | |||
239 | /* Write registers starting at the first time/date address. */ | ||
240 | *bp++ = DS1305_WRITE | DS1305_SEC; | ||
241 | |||
242 | *bp++ = BIN2BCD(time->tm_sec); | ||
243 | *bp++ = BIN2BCD(time->tm_min); | ||
244 | *bp++ = hour2bcd(ds1305->hr12, time->tm_hour); | ||
245 | *bp++ = (time->tm_wday < 7) ? (time->tm_wday + 1) : 1; | ||
246 | *bp++ = BIN2BCD(time->tm_mday); | ||
247 | *bp++ = BIN2BCD(time->tm_mon + 1); | ||
248 | *bp++ = BIN2BCD(time->tm_year - 100); | ||
249 | |||
250 | dev_dbg(dev, "%s: %02x %02x %02x, %02x %02x %02x %02x\n", | ||
251 | "write", buf[1], buf[2], buf[3], | ||
252 | buf[4], buf[5], buf[6], buf[7]); | ||
253 | |||
254 | /* use write-then-read since dma from stack is nonportable */ | ||
255 | return spi_write_then_read(ds1305->spi, buf, sizeof buf, | ||
256 | NULL, 0); | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * Get/set of alarm is a bit funky: | ||
261 | * | ||
262 | * - First there's the inherent raciness of getting the (partitioned) | ||
263 | * status of an alarm that could trigger while we're reading parts | ||
264 | * of that status. | ||
265 | * | ||
266 | * - Second there's its limited range (we could increase it a bit by | ||
267 | * relying on WDAY), which means it will easily roll over. | ||
268 | * | ||
269 | * - Third there's the choice of two alarms and alarm signals. | ||
270 | * Here we use ALM0 and expect that nINT0 (open drain) is used; | ||
271 | * that's the only real option for DS1306 runtime alarms, and is | ||
272 | * natural on DS1305. | ||
273 | * | ||
274 | * - Fourth, there's also ALM1, and a second interrupt signal: | ||
275 | * + On DS1305 ALM1 uses nINT1 (when INTCN=1) else nINT0; | ||
276 | * + On DS1306 ALM1 only uses INT1 (an active high pulse) | ||
277 | * and it won't work when VCC1 is active. | ||
278 | * | ||
279 | * So to be most general, we should probably set both alarms to the | ||
280 | * same value, letting ALM1 be the wakeup event source on DS1306 | ||
281 | * and handling several wiring options on DS1305. | ||
282 | * | ||
283 | * - Fifth, we support the polled mode (as well as possible; why not?) | ||
284 | * even when no interrupt line is wired to an IRQ. | ||
285 | */ | ||
286 | |||
287 | /* | ||
288 | * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl) | ||
289 | */ | ||
290 | static int ds1305_get_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
291 | { | ||
292 | struct ds1305 *ds1305 = dev_get_drvdata(dev); | ||
293 | struct spi_device *spi = ds1305->spi; | ||
294 | u8 addr; | ||
295 | int status; | ||
296 | u8 buf[DS1305_ALM_LEN]; | ||
297 | |||
298 | /* Refresh control register cache BEFORE reading ALM0 registers, | ||
299 | * since reading alarm registers acks any pending IRQ. That | ||
300 | * makes returning "pending" status a bit of a lie, but that bit | ||
301 | * of EFI status is at best fragile anyway (given IRQ handlers). | ||
302 | */ | ||
303 | addr = DS1305_CONTROL; | ||
304 | status = spi_write_then_read(spi, &addr, sizeof addr, | ||
305 | ds1305->ctrl, sizeof ds1305->ctrl); | ||
306 | if (status < 0) | ||
307 | return status; | ||
308 | |||
309 | alm->enabled = !!(ds1305->ctrl[0] & DS1305_AEI0); | ||
310 | alm->pending = !!(ds1305->ctrl[1] & DS1305_AEI0); | ||
311 | |||
312 | /* get and check ALM0 registers */ | ||
313 | addr = DS1305_ALM0(DS1305_SEC); | ||
314 | status = spi_write_then_read(spi, &addr, sizeof addr, | ||
315 | buf, sizeof buf); | ||
316 | if (status < 0) | ||
317 | return status; | ||
318 | |||
319 | dev_vdbg(dev, "%s: %02x %02x %02x %02x\n", | ||
320 | "alm0 read", buf[DS1305_SEC], buf[DS1305_MIN], | ||
321 | buf[DS1305_HOUR], buf[DS1305_WDAY]); | ||
322 | |||
323 | if ((DS1305_ALM_DISABLE & buf[DS1305_SEC]) | ||
324 | || (DS1305_ALM_DISABLE & buf[DS1305_MIN]) | ||
325 | || (DS1305_ALM_DISABLE & buf[DS1305_HOUR])) | ||
326 | return -EIO; | ||
327 | |||
328 | /* Stuff these values into alm->time and let RTC framework code | ||
329 | * fill in the rest ... and also handle rollover to tomorrow when | ||
330 | * that's needed. | ||
331 | */ | ||
332 | alm->time.tm_sec = BCD2BIN(buf[DS1305_SEC]); | ||
333 | alm->time.tm_min = BCD2BIN(buf[DS1305_MIN]); | ||
334 | alm->time.tm_hour = bcd2hour(buf[DS1305_HOUR]); | ||
335 | alm->time.tm_mday = -1; | ||
336 | alm->time.tm_mon = -1; | ||
337 | alm->time.tm_year = -1; | ||
338 | /* next three fields are unused by Linux */ | ||
339 | alm->time.tm_wday = -1; | ||
340 | alm->time.tm_mday = -1; | ||
341 | alm->time.tm_isdst = -1; | ||
342 | |||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | /* | ||
347 | * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl) | ||
348 | */ | ||
349 | static int ds1305_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
350 | { | ||
351 | struct ds1305 *ds1305 = dev_get_drvdata(dev); | ||
352 | struct spi_device *spi = ds1305->spi; | ||
353 | unsigned long now, later; | ||
354 | struct rtc_time tm; | ||
355 | int status; | ||
356 | u8 buf[1 + DS1305_ALM_LEN]; | ||
357 | |||
358 | /* convert desired alarm to time_t */ | ||
359 | status = rtc_tm_to_time(&alm->time, &later); | ||
360 | if (status < 0) | ||
361 | return status; | ||
362 | |||
363 | /* Read current time as time_t */ | ||
364 | status = ds1305_get_time(dev, &tm); | ||
365 | if (status < 0) | ||
366 | return status; | ||
367 | status = rtc_tm_to_time(&tm, &now); | ||
368 | if (status < 0) | ||
369 | return status; | ||
370 | |||
371 | /* make sure alarm fires within the next 24 hours */ | ||
372 | if (later <= now) | ||
373 | return -EINVAL; | ||
374 | if ((later - now) > 24 * 60 * 60) | ||
375 | return -EDOM; | ||
376 | |||
377 | /* disable alarm if needed */ | ||
378 | if (ds1305->ctrl[0] & DS1305_AEI0) { | ||
379 | ds1305->ctrl[0] &= ~DS1305_AEI0; | ||
380 | |||
381 | buf[0] = DS1305_WRITE | DS1305_CONTROL; | ||
382 | buf[1] = ds1305->ctrl[0]; | ||
383 | status = spi_write_then_read(ds1305->spi, buf, 2, NULL, 0); | ||
384 | if (status < 0) | ||
385 | return status; | ||
386 | } | ||
387 | |||
388 | /* write alarm */ | ||
389 | buf[0] = DS1305_WRITE | DS1305_ALM0(DS1305_SEC); | ||
390 | buf[1 + DS1305_SEC] = BIN2BCD(alm->time.tm_sec); | ||
391 | buf[1 + DS1305_MIN] = BIN2BCD(alm->time.tm_min); | ||
392 | buf[1 + DS1305_HOUR] = hour2bcd(ds1305->hr12, alm->time.tm_hour); | ||
393 | buf[1 + DS1305_WDAY] = DS1305_ALM_DISABLE; | ||
394 | |||
395 | dev_dbg(dev, "%s: %02x %02x %02x %02x\n", | ||
396 | "alm0 write", buf[1 + DS1305_SEC], buf[1 + DS1305_MIN], | ||
397 | buf[1 + DS1305_HOUR], buf[1 + DS1305_WDAY]); | ||
398 | |||
399 | status = spi_write_then_read(spi, buf, sizeof buf, NULL, 0); | ||
400 | if (status < 0) | ||
401 | return status; | ||
402 | |||
403 | /* enable alarm if requested */ | ||
404 | if (alm->enabled) { | ||
405 | ds1305->ctrl[0] |= DS1305_AEI0; | ||
406 | |||
407 | buf[0] = DS1305_WRITE | DS1305_CONTROL; | ||
408 | buf[1] = ds1305->ctrl[0]; | ||
409 | status = spi_write_then_read(ds1305->spi, buf, 2, NULL, 0); | ||
410 | } | ||
411 | |||
412 | return status; | ||
413 | } | ||
414 | |||
415 | #ifdef CONFIG_PROC_FS | ||
416 | |||
417 | static int ds1305_proc(struct device *dev, struct seq_file *seq) | ||
418 | { | ||
419 | struct ds1305 *ds1305 = dev_get_drvdata(dev); | ||
420 | char *diodes = "no"; | ||
421 | char *resistors = ""; | ||
422 | |||
423 | /* ctrl[2] is treated as read-only; no locking needed */ | ||
424 | if ((ds1305->ctrl[2] & 0xf0) == DS1305_TRICKLE_MAGIC) { | ||
425 | switch (ds1305->ctrl[2] & 0x0c) { | ||
426 | case DS1305_TRICKLE_DS2: | ||
427 | diodes = "2 diodes, "; | ||
428 | break; | ||
429 | case DS1305_TRICKLE_DS1: | ||
430 | diodes = "1 diode, "; | ||
431 | break; | ||
432 | default: | ||
433 | goto done; | ||
434 | } | ||
435 | switch (ds1305->ctrl[2] & 0x03) { | ||
436 | case DS1305_TRICKLE_2K: | ||
437 | resistors = "2k Ohm"; | ||
438 | break; | ||
439 | case DS1305_TRICKLE_4K: | ||
440 | resistors = "4k Ohm"; | ||
441 | break; | ||
442 | case DS1305_TRICKLE_8K: | ||
443 | resistors = "8k Ohm"; | ||
444 | break; | ||
445 | default: | ||
446 | diodes = "no"; | ||
447 | break; | ||
448 | } | ||
449 | } | ||
450 | |||
451 | done: | ||
452 | return seq_printf(seq, | ||
453 | "trickle_charge\t: %s%s\n", | ||
454 | diodes, resistors); | ||
455 | } | ||
456 | |||
457 | #else | ||
458 | #define ds1305_proc NULL | ||
459 | #endif | ||
460 | |||
461 | static const struct rtc_class_ops ds1305_ops = { | ||
462 | .ioctl = ds1305_ioctl, | ||
463 | .read_time = ds1305_get_time, | ||
464 | .set_time = ds1305_set_time, | ||
465 | .read_alarm = ds1305_get_alarm, | ||
466 | .set_alarm = ds1305_set_alarm, | ||
467 | .proc = ds1305_proc, | ||
468 | }; | ||
469 | |||
470 | static void ds1305_work(struct work_struct *work) | ||
471 | { | ||
472 | struct ds1305 *ds1305 = container_of(work, struct ds1305, work); | ||
473 | struct mutex *lock = &ds1305->rtc->ops_lock; | ||
474 | struct spi_device *spi = ds1305->spi; | ||
475 | u8 buf[3]; | ||
476 | int status; | ||
477 | |||
478 | /* lock to protect ds1305->ctrl */ | ||
479 | mutex_lock(lock); | ||
480 | |||
481 | /* Disable the IRQ, and clear its status ... for now, we "know" | ||
482 | * that if more than one alarm is active, they're in sync. | ||
483 | * Note that reading ALM data registers also clears IRQ status. | ||
484 | */ | ||
485 | ds1305->ctrl[0] &= ~(DS1305_AEI1 | DS1305_AEI0); | ||
486 | ds1305->ctrl[1] = 0; | ||
487 | |||
488 | buf[0] = DS1305_WRITE | DS1305_CONTROL; | ||
489 | buf[1] = ds1305->ctrl[0]; | ||
490 | buf[2] = 0; | ||
491 | |||
492 | status = spi_write_then_read(spi, buf, sizeof buf, | ||
493 | NULL, 0); | ||
494 | if (status < 0) | ||
495 | dev_dbg(&spi->dev, "clear irq --> %d\n", status); | ||
496 | |||
497 | mutex_unlock(lock); | ||
498 | |||
499 | if (!test_bit(FLAG_EXITING, &ds1305->flags)) | ||
500 | enable_irq(spi->irq); | ||
501 | |||
502 | /* rtc_update_irq() requires an IRQ-disabled context */ | ||
503 | local_irq_disable(); | ||
504 | rtc_update_irq(ds1305->rtc, 1, RTC_AF | RTC_IRQF); | ||
505 | local_irq_enable(); | ||
506 | } | ||
507 | |||
508 | /* | ||
509 | * This "real" IRQ handler hands off to a workqueue mostly to allow | ||
510 | * mutex locking for ds1305->ctrl ... unlike I2C, we could issue async | ||
511 | * I/O requests in IRQ context (to clear the IRQ status). | ||
512 | */ | ||
513 | static irqreturn_t ds1305_irq(int irq, void *p) | ||
514 | { | ||
515 | struct ds1305 *ds1305 = p; | ||
516 | |||
517 | disable_irq(irq); | ||
518 | schedule_work(&ds1305->work); | ||
519 | return IRQ_HANDLED; | ||
520 | } | ||
521 | |||
522 | /*----------------------------------------------------------------------*/ | ||
523 | |||
524 | /* | ||
525 | * Interface for NVRAM | ||
526 | */ | ||
527 | |||
528 | static void msg_init(struct spi_message *m, struct spi_transfer *x, | ||
529 | u8 *addr, size_t count, char *tx, char *rx) | ||
530 | { | ||
531 | spi_message_init(m); | ||
532 | memset(x, 0, 2 * sizeof(*x)); | ||
533 | |||
534 | x->tx_buf = addr; | ||
535 | x->len = 1; | ||
536 | spi_message_add_tail(x, m); | ||
537 | |||
538 | x++; | ||
539 | |||
540 | x->tx_buf = tx; | ||
541 | x->rx_buf = rx; | ||
542 | x->len = count; | ||
543 | spi_message_add_tail(x, m); | ||
544 | } | ||
545 | |||
546 | static ssize_t | ||
547 | ds1305_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | ||
548 | char *buf, loff_t off, size_t count) | ||
549 | { | ||
550 | struct spi_device *spi; | ||
551 | u8 addr; | ||
552 | struct spi_message m; | ||
553 | struct spi_transfer x[2]; | ||
554 | int status; | ||
555 | |||
556 | spi = container_of(kobj, struct spi_device, dev.kobj); | ||
557 | |||
558 | if (unlikely(off >= DS1305_NVRAM_LEN)) | ||
559 | return 0; | ||
560 | if (count >= DS1305_NVRAM_LEN) | ||
561 | count = DS1305_NVRAM_LEN; | ||
562 | if ((off + count) > DS1305_NVRAM_LEN) | ||
563 | count = DS1305_NVRAM_LEN - off; | ||
564 | if (unlikely(!count)) | ||
565 | return count; | ||
566 | |||
567 | addr = DS1305_NVRAM + off; | ||
568 | msg_init(&m, x, &addr, count, NULL, buf); | ||
569 | |||
570 | status = spi_sync(spi, &m); | ||
571 | if (status < 0) | ||
572 | dev_err(&spi->dev, "nvram %s error %d\n", "read", status); | ||
573 | return (status < 0) ? status : count; | ||
574 | } | ||
575 | |||
576 | static ssize_t | ||
577 | ds1305_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | ||
578 | char *buf, loff_t off, size_t count) | ||
579 | { | ||
580 | struct spi_device *spi; | ||
581 | u8 addr; | ||
582 | struct spi_message m; | ||
583 | struct spi_transfer x[2]; | ||
584 | int status; | ||
585 | |||
586 | spi = container_of(kobj, struct spi_device, dev.kobj); | ||
587 | |||
588 | if (unlikely(off >= DS1305_NVRAM_LEN)) | ||
589 | return -EFBIG; | ||
590 | if (count >= DS1305_NVRAM_LEN) | ||
591 | count = DS1305_NVRAM_LEN; | ||
592 | if ((off + count) > DS1305_NVRAM_LEN) | ||
593 | count = DS1305_NVRAM_LEN - off; | ||
594 | if (unlikely(!count)) | ||
595 | return count; | ||
596 | |||
597 | addr = (DS1305_WRITE | DS1305_NVRAM) + off; | ||
598 | msg_init(&m, x, &addr, count, buf, NULL); | ||
599 | |||
600 | status = spi_sync(spi, &m); | ||
601 | if (status < 0) | ||
602 | dev_err(&spi->dev, "nvram %s error %d\n", "write", status); | ||
603 | return (status < 0) ? status : count; | ||
604 | } | ||
605 | |||
606 | static struct bin_attribute nvram = { | ||
607 | .attr.name = "nvram", | ||
608 | .attr.mode = S_IRUGO | S_IWUSR, | ||
609 | .attr.owner = THIS_MODULE, | ||
610 | .read = ds1305_nvram_read, | ||
611 | .write = ds1305_nvram_write, | ||
612 | .size = DS1305_NVRAM_LEN, | ||
613 | }; | ||
614 | |||
615 | /*----------------------------------------------------------------------*/ | ||
616 | |||
617 | /* | ||
618 | * Interface to SPI stack | ||
619 | */ | ||
620 | |||
621 | static int __devinit ds1305_probe(struct spi_device *spi) | ||
622 | { | ||
623 | struct ds1305 *ds1305; | ||
624 | struct rtc_device *rtc; | ||
625 | int status; | ||
626 | u8 addr, value; | ||
627 | struct ds1305_platform_data *pdata = spi->dev.platform_data; | ||
628 | bool write_ctrl = false; | ||
629 | |||
630 | /* Sanity check board setup data. This may be hooked up | ||
631 | * in 3wire mode, but we don't care. Note that unless | ||
632 | * there's an inverter in place, this needs SPI_CS_HIGH! | ||
633 | */ | ||
634 | if ((spi->bits_per_word && spi->bits_per_word != 8) | ||
635 | || (spi->max_speed_hz > 2000000) | ||
636 | || !(spi->mode & SPI_CPHA)) | ||
637 | return -EINVAL; | ||
638 | |||
639 | /* set up driver data */ | ||
640 | ds1305 = kzalloc(sizeof *ds1305, GFP_KERNEL); | ||
641 | if (!ds1305) | ||
642 | return -ENOMEM; | ||
643 | ds1305->spi = spi; | ||
644 | spi_set_drvdata(spi, ds1305); | ||
645 | |||
646 | /* read and cache control registers */ | ||
647 | addr = DS1305_CONTROL; | ||
648 | status = spi_write_then_read(spi, &addr, sizeof addr, | ||
649 | ds1305->ctrl, sizeof ds1305->ctrl); | ||
650 | if (status < 0) { | ||
651 | dev_dbg(&spi->dev, "can't %s, %d\n", | ||
652 | "read", status); | ||
653 | goto fail0; | ||
654 | } | ||
655 | |||
656 | dev_dbg(&spi->dev, "ctrl %s: %02x %02x %02x\n", | ||
657 | "read", ds1305->ctrl[0], | ||
658 | ds1305->ctrl[1], ds1305->ctrl[2]); | ||
659 | |||
660 | /* Sanity check register values ... partially compensating for the | ||
661 | * fact that SPI has no device handshake. A pullup on MISO would | ||
662 | * make these tests fail; but not all systems will have one. If | ||
663 | * some register is neither 0x00 nor 0xff, a chip is likely there. | ||
664 | */ | ||
665 | if ((ds1305->ctrl[0] & 0x38) != 0 || (ds1305->ctrl[1] & 0xfc) != 0) { | ||
666 | dev_dbg(&spi->dev, "RTC chip is not present\n"); | ||
667 | status = -ENODEV; | ||
668 | goto fail0; | ||
669 | } | ||
670 | if (ds1305->ctrl[2] == 0) | ||
671 | dev_dbg(&spi->dev, "chip may not be present\n"); | ||
672 | |||
673 | /* enable writes if needed ... if we were paranoid it would | ||
674 | * make sense to enable them only when absolutely necessary. | ||
675 | */ | ||
676 | if (ds1305->ctrl[0] & DS1305_WP) { | ||
677 | u8 buf[2]; | ||
678 | |||
679 | ds1305->ctrl[0] &= ~DS1305_WP; | ||
680 | |||
681 | buf[0] = DS1305_WRITE | DS1305_CONTROL; | ||
682 | buf[1] = ds1305->ctrl[0]; | ||
683 | status = spi_write_then_read(spi, buf, sizeof buf, NULL, 0); | ||
684 | |||
685 | dev_dbg(&spi->dev, "clear WP --> %d\n", status); | ||
686 | if (status < 0) | ||
687 | goto fail0; | ||
688 | } | ||
689 | |||
690 | /* on DS1305, maybe start oscillator; like most low power | ||
691 | * oscillators, it may take a second to stabilize | ||
692 | */ | ||
693 | if (ds1305->ctrl[0] & DS1305_nEOSC) { | ||
694 | ds1305->ctrl[0] &= ~DS1305_nEOSC; | ||
695 | write_ctrl = true; | ||
696 | dev_warn(&spi->dev, "SET TIME!\n"); | ||
697 | } | ||
698 | |||
699 | /* ack any pending IRQs */ | ||
700 | if (ds1305->ctrl[1]) { | ||
701 | ds1305->ctrl[1] = 0; | ||
702 | write_ctrl = true; | ||
703 | } | ||
704 | |||
705 | /* this may need one-time (re)init */ | ||
706 | if (pdata) { | ||
707 | /* maybe enable trickle charge */ | ||
708 | if (((ds1305->ctrl[2] & 0xf0) != DS1305_TRICKLE_MAGIC)) { | ||
709 | ds1305->ctrl[2] = DS1305_TRICKLE_MAGIC | ||
710 | | pdata->trickle; | ||
711 | write_ctrl = true; | ||
712 | } | ||
713 | |||
714 | /* on DS1306, configure 1 Hz signal */ | ||
715 | if (pdata->is_ds1306) { | ||
716 | if (pdata->en_1hz) { | ||
717 | if (!(ds1305->ctrl[0] & DS1306_1HZ)) { | ||
718 | ds1305->ctrl[0] |= DS1306_1HZ; | ||
719 | write_ctrl = true; | ||
720 | } | ||
721 | } else { | ||
722 | if (ds1305->ctrl[0] & DS1306_1HZ) { | ||
723 | ds1305->ctrl[0] &= ~DS1306_1HZ; | ||
724 | write_ctrl = true; | ||
725 | } | ||
726 | } | ||
727 | } | ||
728 | } | ||
729 | |||
730 | if (write_ctrl) { | ||
731 | u8 buf[4]; | ||
732 | |||
733 | buf[0] = DS1305_WRITE | DS1305_CONTROL; | ||
734 | buf[1] = ds1305->ctrl[0]; | ||
735 | buf[2] = ds1305->ctrl[1]; | ||
736 | buf[3] = ds1305->ctrl[2]; | ||
737 | status = spi_write_then_read(spi, buf, sizeof buf, NULL, 0); | ||
738 | if (status < 0) { | ||
739 | dev_dbg(&spi->dev, "can't %s, %d\n", | ||
740 | "write", status); | ||
741 | goto fail0; | ||
742 | } | ||
743 | |||
744 | dev_dbg(&spi->dev, "ctrl %s: %02x %02x %02x\n", | ||
745 | "write", ds1305->ctrl[0], | ||
746 | ds1305->ctrl[1], ds1305->ctrl[2]); | ||
747 | } | ||
748 | |||
749 | /* see if non-Linux software set up AM/PM mode */ | ||
750 | addr = DS1305_HOUR; | ||
751 | status = spi_write_then_read(spi, &addr, sizeof addr, | ||
752 | &value, sizeof value); | ||
753 | if (status < 0) { | ||
754 | dev_dbg(&spi->dev, "read HOUR --> %d\n", status); | ||
755 | goto fail0; | ||
756 | } | ||
757 | |||
758 | ds1305->hr12 = (DS1305_HR_12 & value) != 0; | ||
759 | if (ds1305->hr12) | ||
760 | dev_dbg(&spi->dev, "AM/PM\n"); | ||
761 | |||
762 | /* register RTC ... from here on, ds1305->ctrl needs locking */ | ||
763 | rtc = rtc_device_register("ds1305", &spi->dev, | ||
764 | &ds1305_ops, THIS_MODULE); | ||
765 | if (IS_ERR(rtc)) { | ||
766 | status = PTR_ERR(rtc); | ||
767 | dev_dbg(&spi->dev, "register rtc --> %d\n", status); | ||
768 | goto fail0; | ||
769 | } | ||
770 | ds1305->rtc = rtc; | ||
771 | |||
772 | /* Maybe set up alarm IRQ; be ready to handle it triggering right | ||
773 | * away. NOTE that we don't share this. The signal is active low, | ||
774 | * and we can't ack it before a SPI message delay. We temporarily | ||
775 | * disable the IRQ until it's acked, which lets us work with more | ||
776 | * IRQ trigger modes (not all IRQ controllers can do falling edge). | ||
777 | */ | ||
778 | if (spi->irq) { | ||
779 | INIT_WORK(&ds1305->work, ds1305_work); | ||
780 | status = request_irq(spi->irq, ds1305_irq, | ||
781 | 0, dev_name(&rtc->dev), ds1305); | ||
782 | if (status < 0) { | ||
783 | dev_dbg(&spi->dev, "request_irq %d --> %d\n", | ||
784 | spi->irq, status); | ||
785 | goto fail1; | ||
786 | } | ||
787 | } | ||
788 | |||
789 | /* export NVRAM */ | ||
790 | status = sysfs_create_bin_file(&spi->dev.kobj, &nvram); | ||
791 | if (status < 0) { | ||
792 | dev_dbg(&spi->dev, "register nvram --> %d\n", status); | ||
793 | goto fail2; | ||
794 | } | ||
795 | |||
796 | return 0; | ||
797 | |||
798 | fail2: | ||
799 | free_irq(spi->irq, ds1305); | ||
800 | fail1: | ||
801 | rtc_device_unregister(rtc); | ||
802 | fail0: | ||
803 | kfree(ds1305); | ||
804 | return status; | ||
805 | } | ||
806 | |||
807 | static int __devexit ds1305_remove(struct spi_device *spi) | ||
808 | { | ||
809 | struct ds1305 *ds1305 = spi_get_drvdata(spi); | ||
810 | |||
811 | sysfs_remove_bin_file(&spi->dev.kobj, &nvram); | ||
812 | |||
813 | /* carefully shut down irq and workqueue, if present */ | ||
814 | if (spi->irq) { | ||
815 | set_bit(FLAG_EXITING, &ds1305->flags); | ||
816 | free_irq(spi->irq, ds1305); | ||
817 | flush_scheduled_work(); | ||
818 | } | ||
819 | |||
820 | rtc_device_unregister(ds1305->rtc); | ||
821 | spi_set_drvdata(spi, NULL); | ||
822 | kfree(ds1305); | ||
823 | return 0; | ||
824 | } | ||
825 | |||
826 | static struct spi_driver ds1305_driver = { | ||
827 | .driver.name = "rtc-ds1305", | ||
828 | .driver.owner = THIS_MODULE, | ||
829 | .probe = ds1305_probe, | ||
830 | .remove = __devexit_p(ds1305_remove), | ||
831 | /* REVISIT add suspend/resume */ | ||
832 | }; | ||
833 | |||
834 | static int __init ds1305_init(void) | ||
835 | { | ||
836 | return spi_register_driver(&ds1305_driver); | ||
837 | } | ||
838 | module_init(ds1305_init); | ||
839 | |||
840 | static void __exit ds1305_exit(void) | ||
841 | { | ||
842 | spi_unregister_driver(&ds1305_driver); | ||
843 | } | ||
844 | module_exit(ds1305_exit); | ||
845 | |||
846 | MODULE_DESCRIPTION("RTC driver for DS1305 and DS1306 chips"); | ||
847 | MODULE_LICENSE("GPL"); | ||