diff options
Diffstat (limited to 'drivers/rtc')
52 files changed, 5033 insertions, 1493 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index fc85bf2e4a97..8abbb2020af9 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -171,10 +171,10 @@ config RTC_DRV_MAX6900 | |||
171 | will be called rtc-max6900. | 171 | will be called rtc-max6900. |
172 | 172 | ||
173 | config RTC_DRV_RS5C372 | 173 | config RTC_DRV_RS5C372 |
174 | tristate "Ricoh RS5C372A/B, RV5C386, RV5C387A" | 174 | tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" |
175 | help | 175 | help |
176 | If you say yes here you get support for the | 176 | If you say yes here you get support for the |
177 | Ricoh RS5C372A, RS5C372B, RV5C386, and RV5C387A RTC chips. | 177 | Ricoh R2025S/D, RS5C372A, RS5C372B, RV5C386, and RV5C387A RTC chips. |
178 | 178 | ||
179 | This driver can also be built as a module. If so, the module | 179 | This driver can also be built as a module. If so, the module |
180 | will be called rtc-rs5c372. | 180 | will be called rtc-rs5c372. |
@@ -220,22 +220,22 @@ config RTC_DRV_PCF8583 | |||
220 | will be called rtc-pcf8583. | 220 | will be called rtc-pcf8583. |
221 | 221 | ||
222 | config RTC_DRV_M41T80 | 222 | config RTC_DRV_M41T80 |
223 | tristate "ST M41T80/81/82/83/84/85/87" | 223 | tristate "ST M41T65/M41T80/81/82/83/84/85/87" |
224 | help | 224 | help |
225 | If you say Y here you will get support for the | 225 | If you say Y here you will get support for the ST M41T60 |
226 | ST M41T80 RTC chips series. Currently following chips are | 226 | and M41T80 RTC chips series. Currently, the following chips are |
227 | supported: M41T80, M41T81, M41T82, M41T83, M41ST84, M41ST85 | 227 | supported: M41T65, M41T80, M41T81, M41T82, M41T83, M41ST84, |
228 | and M41ST87. | 228 | M41ST85, and M41ST87. |
229 | 229 | ||
230 | This driver can also be built as a module. If so, the module | 230 | This driver can also be built as a module. If so, the module |
231 | will be called rtc-m41t80. | 231 | will be called rtc-m41t80. |
232 | 232 | ||
233 | config RTC_DRV_M41T80_WDT | 233 | config RTC_DRV_M41T80_WDT |
234 | bool "ST M41T80 series RTC watchdog timer" | 234 | bool "ST M41T65/M41T80 series RTC watchdog timer" |
235 | depends on RTC_DRV_M41T80 | 235 | depends on RTC_DRV_M41T80 |
236 | help | 236 | help |
237 | If you say Y here you will get support for the | 237 | If you say Y here you will get support for the |
238 | watchdog timer in ST M41T80 RTC chips series. | 238 | watchdog timer in the ST M41T60 and M41T80 RTC chips series. |
239 | 239 | ||
240 | config RTC_DRV_TWL92330 | 240 | config RTC_DRV_TWL92330 |
241 | boolean "TI TWL92330/Menelaus" | 241 | boolean "TI TWL92330/Menelaus" |
@@ -246,6 +246,16 @@ config RTC_DRV_TWL92330 | |||
246 | platforms. The support is integrated with the rest of | 246 | platforms. The support is integrated with the rest of |
247 | the Menelaus driver; it's not separate module. | 247 | the Menelaus driver; it's not separate module. |
248 | 248 | ||
249 | config RTC_DRV_TWL4030 | ||
250 | tristate "TI TWL4030/TWL5030/TPS659x0" | ||
251 | depends on RTC_CLASS && TWL4030_CORE | ||
252 | help | ||
253 | If you say yes here you get support for the RTC on the | ||
254 | TWL4030 family chips, used mostly with OMAP3 platforms. | ||
255 | |||
256 | This driver can also be built as a module. If so, the module | ||
257 | will be called rtc-twl4030. | ||
258 | |||
249 | config RTC_DRV_S35390A | 259 | config RTC_DRV_S35390A |
250 | tristate "Seiko Instruments S-35390A" | 260 | tristate "Seiko Instruments S-35390A" |
251 | select BITREVERSE | 261 | select BITREVERSE |
@@ -273,6 +283,25 @@ comment "SPI RTC drivers" | |||
273 | 283 | ||
274 | if SPI_MASTER | 284 | if SPI_MASTER |
275 | 285 | ||
286 | config RTC_DRV_M41T94 | ||
287 | tristate "ST M41T94" | ||
288 | help | ||
289 | If you say yes here you will get support for the | ||
290 | ST M41T94 SPI RTC chip. | ||
291 | |||
292 | This driver can also be built as a module. If so, the module | ||
293 | will be called rtc-m41t94. | ||
294 | |||
295 | config RTC_DRV_DS1305 | ||
296 | tristate "Dallas/Maxim DS1305/DS1306" | ||
297 | help | ||
298 | Select this driver to get support for the Dallas/Maxim DS1305 | ||
299 | and DS1306 real time clock chips. These support a trickle | ||
300 | charger, alarms, and NVRAM in addition to the clock. | ||
301 | |||
302 | This driver can also be built as a module. If so, the module | ||
303 | will be called rtc-ds1305. | ||
304 | |||
276 | config RTC_DRV_MAX6902 | 305 | config RTC_DRV_MAX6902 |
277 | tristate "Maxim MAX6902" | 306 | tristate "Maxim MAX6902" |
278 | help | 307 | help |
@@ -300,6 +329,15 @@ config RTC_DRV_RS5C348 | |||
300 | This driver can also be built as a module. If so, the module | 329 | This driver can also be built as a module. If so, the module |
301 | will be called rtc-rs5c348. | 330 | will be called rtc-rs5c348. |
302 | 331 | ||
332 | config RTC_DRV_DS3234 | ||
333 | tristate "Maxim/Dallas DS3234" | ||
334 | help | ||
335 | If you say yes here you get support for the | ||
336 | Maxim/Dallas DS3234 SPI RTC chip. | ||
337 | |||
338 | This driver can also be built as a module. If so, the module | ||
339 | will be called rtc-ds3234. | ||
340 | |||
303 | endif # SPI_MASTER | 341 | endif # SPI_MASTER |
304 | 342 | ||
305 | comment "Platform RTC drivers" | 343 | comment "Platform RTC drivers" |
@@ -310,7 +348,7 @@ comment "Platform RTC drivers" | |||
310 | 348 | ||
311 | config RTC_DRV_CMOS | 349 | config RTC_DRV_CMOS |
312 | tristate "PC-style 'CMOS'" | 350 | tristate "PC-style 'CMOS'" |
313 | depends on X86 || ALPHA || ARM || M32R || ATARI || PPC || MIPS | 351 | depends on X86 || ALPHA || ARM || M32R || ATARI || PPC || MIPS || SPARC64 |
314 | default y if X86 | 352 | default y if X86 |
315 | help | 353 | help |
316 | Say "yes" here to get direct support for the real time clock | 354 | Say "yes" here to get direct support for the real time clock |
@@ -333,6 +371,11 @@ config RTC_DRV_DS1216 | |||
333 | help | 371 | help |
334 | If you say yes here you get support for the Dallas DS1216 RTC chips. | 372 | If you say yes here you get support for the Dallas DS1216 RTC chips. |
335 | 373 | ||
374 | config RTC_DRV_DS1286 | ||
375 | tristate "Dallas DS1286" | ||
376 | help | ||
377 | If you say yes here you get support for the Dallas DS1286 RTC chips. | ||
378 | |||
336 | config RTC_DRV_DS1302 | 379 | config RTC_DRV_DS1302 |
337 | tristate "Dallas DS1302" | 380 | tristate "Dallas DS1302" |
338 | depends on SH_SECUREEDGE5410 | 381 | depends on SH_SECUREEDGE5410 |
@@ -386,15 +429,36 @@ config RTC_DRV_M48T86 | |||
386 | This driver can also be built as a module. If so, the module | 429 | This driver can also be built as a module. If so, the module |
387 | will be called rtc-m48t86. | 430 | will be called rtc-m48t86. |
388 | 431 | ||
432 | config RTC_DRV_M48T35 | ||
433 | tristate "ST M48T35" | ||
434 | help | ||
435 | If you say Y here you will get support for the | ||
436 | ST M48T35 RTC chip. | ||
437 | |||
438 | This driver can also be built as a module, if so, the module | ||
439 | will be called "rtc-m48t35". | ||
440 | |||
389 | config RTC_DRV_M48T59 | 441 | config RTC_DRV_M48T59 |
390 | tristate "ST M48T59" | 442 | tristate "ST M48T59/M48T08/M48T02" |
391 | help | 443 | help |
392 | If you say Y here you will get support for the | 444 | If you say Y here you will get support for the |
393 | ST M48T59 RTC chip. | 445 | ST M48T59 RTC chip and compatible ST M48T08 and M48T02. |
446 | |||
447 | These chips are usually found in Sun SPARC and UltraSPARC | ||
448 | workstations. | ||
394 | 449 | ||
395 | This driver can also be built as a module, if so, the module | 450 | This driver can also be built as a module, if so, the module |
396 | will be called "rtc-m48t59". | 451 | will be called "rtc-m48t59". |
397 | 452 | ||
453 | config RTC_DRV_BQ4802 | ||
454 | tristate "TI BQ4802" | ||
455 | help | ||
456 | If you say Y here you will get support for the TI | ||
457 | BQ4802 RTC chip. | ||
458 | |||
459 | This driver can also be built as a module. If so, the module | ||
460 | will be called rtc-bq4802. | ||
461 | |||
398 | config RTC_DRV_V3020 | 462 | config RTC_DRV_V3020 |
399 | tristate "EM Microelectronic V3020" | 463 | tristate "EM Microelectronic V3020" |
400 | help | 464 | help |
@@ -542,7 +606,7 @@ config RTC_DRV_AT91SAM9_GPBR | |||
542 | 606 | ||
543 | config RTC_DRV_BFIN | 607 | config RTC_DRV_BFIN |
544 | tristate "Blackfin On-Chip RTC" | 608 | tristate "Blackfin On-Chip RTC" |
545 | depends on BLACKFIN | 609 | depends on BLACKFIN && !BF561 |
546 | help | 610 | help |
547 | If you say yes here you will get support for the | 611 | If you say yes here you will get support for the |
548 | Blackfin On-Chip Real Time Clock. | 612 | Blackfin On-Chip Real Time Clock. |
@@ -556,12 +620,34 @@ config RTC_DRV_RS5C313 | |||
556 | help | 620 | help |
557 | If you say yes here you get support for the Ricoh RS5C313 RTC chips. | 621 | If you say yes here you get support for the Ricoh RS5C313 RTC chips. |
558 | 622 | ||
623 | config RTC_DRV_PARISC | ||
624 | tristate "PA-RISC firmware RTC support" | ||
625 | depends on PARISC | ||
626 | help | ||
627 | Say Y or M here to enable RTC support on PA-RISC systems using | ||
628 | firmware calls. If you do not know what you are doing, you should | ||
629 | just say Y. | ||
630 | |||
559 | config RTC_DRV_PPC | 631 | config RTC_DRV_PPC |
560 | tristate "PowerPC machine dependent RTC support" | 632 | tristate "PowerPC machine dependent RTC support" |
561 | depends on PPC_MERGE | 633 | depends on PPC |
562 | help | 634 | help |
563 | The PowerPC kernel has machine-specific functions for accessing | 635 | The PowerPC kernel has machine-specific functions for accessing |
564 | the RTC. This exposes that functionality through the generic RTC | 636 | the RTC. This exposes that functionality through the generic RTC |
565 | class. | 637 | class. |
566 | 638 | ||
639 | config RTC_DRV_SUN4V | ||
640 | bool "SUN4V Hypervisor RTC" | ||
641 | depends on SPARC64 | ||
642 | help | ||
643 | If you say Y here you will get support for the Hypervisor | ||
644 | based RTC on SUN4V systems. | ||
645 | |||
646 | config RTC_DRV_STARFIRE | ||
647 | bool "Starfire RTC" | ||
648 | depends on SPARC64 | ||
649 | help | ||
650 | If you say Y here you will get support for the RTC found on | ||
651 | Starfire systems. | ||
652 | |||
567 | endif # RTC_CLASS | 653 | endif # RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index b5d9d67df887..e9e8474cc8fe 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -23,19 +23,27 @@ obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o | |||
23 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o | 23 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o |
24 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | 24 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o |
25 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o | 25 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o |
26 | obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o | ||
26 | obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o | 27 | obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o |
28 | obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o | ||
27 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o | 29 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o |
28 | obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o | 30 | obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o |
29 | obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o | 31 | obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o |
30 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | 32 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o |
31 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | 33 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o |
32 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o | 34 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o |
35 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o | ||
33 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o | 36 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o |
34 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o | 37 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o |
35 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o | 38 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o |
36 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o | 39 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o |
40 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o | ||
41 | obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o | ||
37 | obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o | 42 | obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o |
38 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | 43 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o |
44 | obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o | ||
45 | obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o | ||
46 | obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o | ||
39 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o | 47 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o |
40 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 48 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
41 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o | 49 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o |
@@ -43,6 +51,7 @@ obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o | |||
43 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o | 51 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o |
44 | obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o | 52 | obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o |
45 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o | 53 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o |
54 | obj-$(CONFIG_RTC_DRV_PARISC) += rtc-parisc.o | ||
46 | obj-$(CONFIG_RTC_DRV_PPC) += rtc-ppc.o | 55 | obj-$(CONFIG_RTC_DRV_PPC) += rtc-ppc.o |
47 | obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o | 56 | obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o |
48 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o | 57 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o |
@@ -54,6 +63,7 @@ obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o | |||
54 | obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o | 63 | obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o |
55 | obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o | 64 | obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o |
56 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o | 65 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o |
66 | obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o | ||
57 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o | 67 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o |
58 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o | 68 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o |
59 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o | 69 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o |
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 58b7336640ff..7af60b98d8a4 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
@@ -20,7 +20,7 @@ int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) | |||
20 | 20 | ||
21 | err = mutex_lock_interruptible(&rtc->ops_lock); | 21 | err = mutex_lock_interruptible(&rtc->ops_lock); |
22 | if (err) | 22 | if (err) |
23 | return -EBUSY; | 23 | return err; |
24 | 24 | ||
25 | if (!rtc->ops) | 25 | if (!rtc->ops) |
26 | err = -ENODEV; | 26 | err = -ENODEV; |
@@ -46,7 +46,7 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) | |||
46 | 46 | ||
47 | err = mutex_lock_interruptible(&rtc->ops_lock); | 47 | err = mutex_lock_interruptible(&rtc->ops_lock); |
48 | if (err) | 48 | if (err) |
49 | return -EBUSY; | 49 | return err; |
50 | 50 | ||
51 | if (!rtc->ops) | 51 | if (!rtc->ops) |
52 | err = -ENODEV; | 52 | err = -ENODEV; |
@@ -66,7 +66,7 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs) | |||
66 | 66 | ||
67 | err = mutex_lock_interruptible(&rtc->ops_lock); | 67 | err = mutex_lock_interruptible(&rtc->ops_lock); |
68 | if (err) | 68 | if (err) |
69 | return -EBUSY; | 69 | return err; |
70 | 70 | ||
71 | if (!rtc->ops) | 71 | if (!rtc->ops) |
72 | err = -ENODEV; | 72 | err = -ENODEV; |
@@ -106,7 +106,7 @@ static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *al | |||
106 | 106 | ||
107 | err = mutex_lock_interruptible(&rtc->ops_lock); | 107 | err = mutex_lock_interruptible(&rtc->ops_lock); |
108 | if (err) | 108 | if (err) |
109 | return -EBUSY; | 109 | return err; |
110 | 110 | ||
111 | if (rtc->ops == NULL) | 111 | if (rtc->ops == NULL) |
112 | err = -ENODEV; | 112 | err = -ENODEV; |
@@ -293,7 +293,7 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
293 | 293 | ||
294 | err = mutex_lock_interruptible(&rtc->ops_lock); | 294 | err = mutex_lock_interruptible(&rtc->ops_lock); |
295 | if (err) | 295 | if (err) |
296 | return -EBUSY; | 296 | return err; |
297 | 297 | ||
298 | if (!rtc->ops) | 298 | if (!rtc->ops) |
299 | err = -ENODEV; | 299 | err = -ENODEV; |
@@ -345,7 +345,7 @@ struct rtc_device *rtc_class_open(char *name) | |||
345 | struct device *dev; | 345 | struct device *dev; |
346 | struct rtc_device *rtc = NULL; | 346 | struct rtc_device *rtc = NULL; |
347 | 347 | ||
348 | dev = class_find_device(rtc_class, name, __rtc_match); | 348 | dev = class_find_device(rtc_class, NULL, name, __rtc_match); |
349 | if (dev) | 349 | if (dev) |
350 | rtc = to_rtc_device(dev); | 350 | rtc = to_rtc_device(dev); |
351 | 351 | ||
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index 9c3db934cc24..b5bf93706913 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c | |||
@@ -29,10 +29,10 @@ | |||
29 | #include <linux/completion.h> | 29 | #include <linux/completion.h> |
30 | 30 | ||
31 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
32 | #include <asm/arch/at91_rtc.h> | 32 | |
33 | #include <mach/at91_rtc.h> | ||
33 | 34 | ||
34 | 35 | ||
35 | #define AT91_RTC_FREQ 1 | ||
36 | #define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */ | 36 | #define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */ |
37 | 37 | ||
38 | static DECLARE_COMPLETION(at91_rtc_updated); | 38 | static DECLARE_COMPLETION(at91_rtc_updated); |
@@ -53,21 +53,21 @@ static void at91_rtc_decodetime(unsigned int timereg, unsigned int calreg, | |||
53 | } while ((time != at91_sys_read(timereg)) || | 53 | } while ((time != at91_sys_read(timereg)) || |
54 | (date != at91_sys_read(calreg))); | 54 | (date != at91_sys_read(calreg))); |
55 | 55 | ||
56 | tm->tm_sec = BCD2BIN((time & AT91_RTC_SEC) >> 0); | 56 | tm->tm_sec = bcd2bin((time & AT91_RTC_SEC) >> 0); |
57 | tm->tm_min = BCD2BIN((time & AT91_RTC_MIN) >> 8); | 57 | tm->tm_min = bcd2bin((time & AT91_RTC_MIN) >> 8); |
58 | tm->tm_hour = BCD2BIN((time & AT91_RTC_HOUR) >> 16); | 58 | tm->tm_hour = bcd2bin((time & AT91_RTC_HOUR) >> 16); |
59 | 59 | ||
60 | /* | 60 | /* |
61 | * The Calendar Alarm register does not have a field for | 61 | * The Calendar Alarm register does not have a field for |
62 | * the year - so these will return an invalid value. When an | 62 | * the year - so these will return an invalid value. When an |
63 | * alarm is set, at91_alarm_year wille store the current year. | 63 | * alarm is set, at91_alarm_year wille store the current year. |
64 | */ | 64 | */ |
65 | tm->tm_year = BCD2BIN(date & AT91_RTC_CENT) * 100; /* century */ | 65 | tm->tm_year = bcd2bin(date & AT91_RTC_CENT) * 100; /* century */ |
66 | tm->tm_year += BCD2BIN((date & AT91_RTC_YEAR) >> 8); /* year */ | 66 | tm->tm_year += bcd2bin((date & AT91_RTC_YEAR) >> 8); /* year */ |
67 | 67 | ||
68 | tm->tm_wday = BCD2BIN((date & AT91_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */ | 68 | tm->tm_wday = bcd2bin((date & AT91_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */ |
69 | tm->tm_mon = BCD2BIN((date & AT91_RTC_MONTH) >> 16) - 1; | 69 | tm->tm_mon = bcd2bin((date & AT91_RTC_MONTH) >> 16) - 1; |
70 | tm->tm_mday = BCD2BIN((date & AT91_RTC_DATE) >> 24); | 70 | tm->tm_mday = bcd2bin((date & AT91_RTC_DATE) >> 24); |
71 | } | 71 | } |
72 | 72 | ||
73 | /* | 73 | /* |
@@ -106,16 +106,16 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
106 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD); | 106 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD); |
107 | 107 | ||
108 | at91_sys_write(AT91_RTC_TIMR, | 108 | at91_sys_write(AT91_RTC_TIMR, |
109 | BIN2BCD(tm->tm_sec) << 0 | 109 | bin2bcd(tm->tm_sec) << 0 |
110 | | BIN2BCD(tm->tm_min) << 8 | 110 | | bin2bcd(tm->tm_min) << 8 |
111 | | BIN2BCD(tm->tm_hour) << 16); | 111 | | bin2bcd(tm->tm_hour) << 16); |
112 | 112 | ||
113 | at91_sys_write(AT91_RTC_CALR, | 113 | at91_sys_write(AT91_RTC_CALR, |
114 | BIN2BCD((tm->tm_year + 1900) / 100) /* century */ | 114 | bin2bcd((tm->tm_year + 1900) / 100) /* century */ |
115 | | BIN2BCD(tm->tm_year % 100) << 8 /* year */ | 115 | | bin2bcd(tm->tm_year % 100) << 8 /* year */ |
116 | | BIN2BCD(tm->tm_mon + 1) << 16 /* tm_mon starts at zero */ | 116 | | bin2bcd(tm->tm_mon + 1) << 16 /* tm_mon starts at zero */ |
117 | | BIN2BCD(tm->tm_wday + 1) << 21 /* day of the week [0-6], Sunday=0 */ | 117 | | bin2bcd(tm->tm_wday + 1) << 21 /* day of the week [0-6], Sunday=0 */ |
118 | | BIN2BCD(tm->tm_mday) << 24); | 118 | | bin2bcd(tm->tm_mday) << 24); |
119 | 119 | ||
120 | /* Restart Time/Calendar */ | 120 | /* Restart Time/Calendar */ |
121 | cr = at91_sys_read(AT91_RTC_CR); | 121 | cr = at91_sys_read(AT91_RTC_CR); |
@@ -162,17 +162,19 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
162 | 162 | ||
163 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM); | 163 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM); |
164 | at91_sys_write(AT91_RTC_TIMALR, | 164 | at91_sys_write(AT91_RTC_TIMALR, |
165 | BIN2BCD(tm.tm_sec) << 0 | 165 | bin2bcd(tm.tm_sec) << 0 |
166 | | BIN2BCD(tm.tm_min) << 8 | 166 | | bin2bcd(tm.tm_min) << 8 |
167 | | BIN2BCD(tm.tm_hour) << 16 | 167 | | bin2bcd(tm.tm_hour) << 16 |
168 | | AT91_RTC_HOUREN | AT91_RTC_MINEN | AT91_RTC_SECEN); | 168 | | AT91_RTC_HOUREN | AT91_RTC_MINEN | AT91_RTC_SECEN); |
169 | at91_sys_write(AT91_RTC_CALALR, | 169 | at91_sys_write(AT91_RTC_CALALR, |
170 | BIN2BCD(tm.tm_mon + 1) << 16 /* tm_mon starts at zero */ | 170 | bin2bcd(tm.tm_mon + 1) << 16 /* tm_mon starts at zero */ |
171 | | BIN2BCD(tm.tm_mday) << 24 | 171 | | bin2bcd(tm.tm_mday) << 24 |
172 | | AT91_RTC_DATEEN | AT91_RTC_MTHEN); | 172 | | AT91_RTC_DATEEN | AT91_RTC_MTHEN); |
173 | 173 | ||
174 | if (alrm->enabled) | 174 | if (alrm->enabled) { |
175 | at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM); | ||
175 | at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM); | 176 | at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM); |
177 | } | ||
176 | 178 | ||
177 | pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, | 179 | pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, |
178 | at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, | 180 | at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, |
@@ -191,28 +193,22 @@ static int at91_rtc_ioctl(struct device *dev, unsigned int cmd, | |||
191 | 193 | ||
192 | pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __func__, cmd, arg); | 194 | pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __func__, cmd, arg); |
193 | 195 | ||
196 | /* important: scrub old status before enabling IRQs */ | ||
194 | switch (cmd) { | 197 | switch (cmd) { |
195 | case RTC_AIE_OFF: /* alarm off */ | 198 | case RTC_AIE_OFF: /* alarm off */ |
196 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM); | 199 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM); |
197 | break; | 200 | break; |
198 | case RTC_AIE_ON: /* alarm on */ | 201 | case RTC_AIE_ON: /* alarm on */ |
202 | at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM); | ||
199 | at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM); | 203 | at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM); |
200 | break; | 204 | break; |
201 | case RTC_UIE_OFF: /* update off */ | 205 | case RTC_UIE_OFF: /* update off */ |
202 | case RTC_PIE_OFF: /* periodic off */ | ||
203 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV); | 206 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV); |
204 | break; | 207 | break; |
205 | case RTC_UIE_ON: /* update on */ | 208 | case RTC_UIE_ON: /* update on */ |
206 | case RTC_PIE_ON: /* periodic on */ | 209 | at91_sys_write(AT91_RTC_SCCR, AT91_RTC_SECEV); |
207 | at91_sys_write(AT91_RTC_IER, AT91_RTC_SECEV); | 210 | at91_sys_write(AT91_RTC_IER, AT91_RTC_SECEV); |
208 | break; | 211 | break; |
209 | case RTC_IRQP_READ: /* read periodic alarm frequency */ | ||
210 | ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg); | ||
211 | break; | ||
212 | case RTC_IRQP_SET: /* set periodic alarm frequency */ | ||
213 | if (arg != AT91_RTC_FREQ) | ||
214 | ret = -EINVAL; | ||
215 | break; | ||
216 | default: | 212 | default: |
217 | ret = -ENOIOCTLCMD; | 213 | ret = -ENOIOCTLCMD; |
218 | break; | 214 | break; |
@@ -232,8 +228,6 @@ static int at91_rtc_proc(struct device *dev, struct seq_file *seq) | |||
232 | (imr & AT91_RTC_ACKUPD) ? "yes" : "no"); | 228 | (imr & AT91_RTC_ACKUPD) ? "yes" : "no"); |
233 | seq_printf(seq, "periodic_IRQ\t: %s\n", | 229 | seq_printf(seq, "periodic_IRQ\t: %s\n", |
234 | (imr & AT91_RTC_SECEV) ? "yes" : "no"); | 230 | (imr & AT91_RTC_SECEV) ? "yes" : "no"); |
235 | seq_printf(seq, "periodic_freq\t: %ld\n", | ||
236 | (unsigned long) AT91_RTC_FREQ); | ||
237 | 231 | ||
238 | return 0; | 232 | return 0; |
239 | } | 233 | } |
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index f0246ef413a4..2133f37906f2 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c | |||
@@ -19,8 +19,8 @@ | |||
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/ioctl.h> | 20 | #include <linux/ioctl.h> |
21 | 21 | ||
22 | #include <asm/arch/board.h> | 22 | #include <mach/board.h> |
23 | #include <asm/arch/at91_rtt.h> | 23 | #include <mach/at91_rtt.h> |
24 | 24 | ||
25 | 25 | ||
26 | /* | 26 | /* |
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 8624f55d0560..34439ce3967e 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Blackfin On-Chip Real Time Clock Driver | 2 | * Blackfin On-Chip Real Time Clock Driver |
3 | * Supports BF52[257]/BF53[123]/BF53[467]/BF54[24789] | 3 | * Supports BF52[257]/BF53[123]/BF53[467]/BF54[24789] |
4 | * | 4 | * |
5 | * Copyright 2004-2007 Analog Devices Inc. | 5 | * Copyright 2004-2008 Analog Devices Inc. |
6 | * | 6 | * |
7 | * Enter bugs at http://blackfin.uclinux.org/ | 7 | * Enter bugs at http://blackfin.uclinux.org/ |
8 | * | 8 | * |
@@ -32,6 +32,15 @@ | |||
32 | * writes to clear status registers complete immediately. | 32 | * writes to clear status registers complete immediately. |
33 | */ | 33 | */ |
34 | 34 | ||
35 | /* It may seem odd that there is no SWCNT code in here (which would be exposed | ||
36 | * via the periodic interrupt event, or PIE). Since the Blackfin RTC peripheral | ||
37 | * runs in units of seconds (N/HZ) but the Linux framework runs in units of HZ | ||
38 | * (2^N HZ), there is no point in keeping code that only provides 1 HZ PIEs. | ||
39 | * The same exact behavior can be accomplished by using the update interrupt | ||
40 | * event (UIE). Maybe down the line the RTC peripheral will suck less in which | ||
41 | * case we can re-introduce PIE support. | ||
42 | */ | ||
43 | |||
35 | #include <linux/bcd.h> | 44 | #include <linux/bcd.h> |
36 | #include <linux/completion.h> | 45 | #include <linux/completion.h> |
37 | #include <linux/delay.h> | 46 | #include <linux/delay.h> |
@@ -144,14 +153,13 @@ static void bfin_rtc_sync_pending(struct device *dev) | |||
144 | * Initialize the RTC. Enable pre-scaler to scale RTC clock | 153 | * Initialize the RTC. Enable pre-scaler to scale RTC clock |
145 | * to 1Hz and clear interrupt/status registers. | 154 | * to 1Hz and clear interrupt/status registers. |
146 | */ | 155 | */ |
147 | static void bfin_rtc_reset(struct device *dev) | 156 | static void bfin_rtc_reset(struct device *dev, u16 rtc_ictl) |
148 | { | 157 | { |
149 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 158 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
150 | dev_dbg_stamp(dev); | 159 | dev_dbg_stamp(dev); |
151 | bfin_rtc_sync_pending(dev); | 160 | bfin_rtc_sync_pending(dev); |
152 | bfin_write_RTC_PREN(0x1); | 161 | bfin_write_RTC_PREN(0x1); |
153 | bfin_write_RTC_ICTL(RTC_ISTAT_WRITE_COMPLETE); | 162 | bfin_write_RTC_ICTL(rtc_ictl); |
154 | bfin_write_RTC_SWCNT(0); | ||
155 | bfin_write_RTC_ALARM(0); | 163 | bfin_write_RTC_ALARM(0); |
156 | bfin_write_RTC_ISTAT(0xFFFF); | 164 | bfin_write_RTC_ISTAT(0xFFFF); |
157 | rtc->rtc_wrote_regs = 0; | 165 | rtc->rtc_wrote_regs = 0; |
@@ -194,14 +202,6 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) | |||
194 | } | 202 | } |
195 | } | 203 | } |
196 | 204 | ||
197 | if (rtc_ictl & RTC_ISTAT_STOPWATCH) { | ||
198 | if (rtc_istat & RTC_ISTAT_STOPWATCH) { | ||
199 | bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH); | ||
200 | events |= RTC_PF | RTC_IRQF; | ||
201 | bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | if (rtc_ictl & RTC_ISTAT_SEC) { | 205 | if (rtc_ictl & RTC_ISTAT_SEC) { |
206 | if (rtc_istat & RTC_ISTAT_SEC) { | 206 | if (rtc_istat & RTC_ISTAT_SEC) { |
207 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); | 207 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); |
@@ -218,32 +218,12 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) | |||
218 | return IRQ_NONE; | 218 | return IRQ_NONE; |
219 | } | 219 | } |
220 | 220 | ||
221 | static int bfin_rtc_open(struct device *dev) | 221 | static void bfin_rtc_int_set(u16 rtc_int) |
222 | { | ||
223 | int ret; | ||
224 | |||
225 | dev_dbg_stamp(dev); | ||
226 | |||
227 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, to_platform_device(dev)->name, dev); | ||
228 | if (!ret) | ||
229 | bfin_rtc_reset(dev); | ||
230 | |||
231 | return ret; | ||
232 | } | ||
233 | |||
234 | static void bfin_rtc_release(struct device *dev) | ||
235 | { | ||
236 | dev_dbg_stamp(dev); | ||
237 | bfin_rtc_reset(dev); | ||
238 | free_irq(IRQ_RTC, dev); | ||
239 | } | ||
240 | |||
241 | static void bfin_rtc_int_set(struct bfin_rtc *rtc, u16 rtc_int) | ||
242 | { | 222 | { |
243 | bfin_write_RTC_ISTAT(rtc_int); | 223 | bfin_write_RTC_ISTAT(rtc_int); |
244 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | rtc_int); | 224 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | rtc_int); |
245 | } | 225 | } |
246 | static void bfin_rtc_int_clear(struct bfin_rtc *rtc, u16 rtc_int) | 226 | static void bfin_rtc_int_clear(u16 rtc_int) |
247 | { | 227 | { |
248 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & rtc_int); | 228 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & rtc_int); |
249 | } | 229 | } |
@@ -252,7 +232,7 @@ static void bfin_rtc_int_set_alarm(struct bfin_rtc *rtc) | |||
252 | /* Blackfin has different bits for whether the alarm is | 232 | /* Blackfin has different bits for whether the alarm is |
253 | * more than 24 hours away. | 233 | * more than 24 hours away. |
254 | */ | 234 | */ |
255 | bfin_rtc_int_set(rtc, (rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY)); | 235 | bfin_rtc_int_set(rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY); |
256 | } | 236 | } |
257 | static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 237 | static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
258 | { | 238 | { |
@@ -264,23 +244,13 @@ static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long ar | |||
264 | bfin_rtc_sync_pending(dev); | 244 | bfin_rtc_sync_pending(dev); |
265 | 245 | ||
266 | switch (cmd) { | 246 | switch (cmd) { |
267 | case RTC_PIE_ON: | ||
268 | dev_dbg_stamp(dev); | ||
269 | bfin_rtc_int_set(rtc, RTC_ISTAT_STOPWATCH); | ||
270 | bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); | ||
271 | break; | ||
272 | case RTC_PIE_OFF: | ||
273 | dev_dbg_stamp(dev); | ||
274 | bfin_rtc_int_clear(rtc, ~RTC_ISTAT_STOPWATCH); | ||
275 | break; | ||
276 | |||
277 | case RTC_UIE_ON: | 247 | case RTC_UIE_ON: |
278 | dev_dbg_stamp(dev); | 248 | dev_dbg_stamp(dev); |
279 | bfin_rtc_int_set(rtc, RTC_ISTAT_SEC); | 249 | bfin_rtc_int_set(RTC_ISTAT_SEC); |
280 | break; | 250 | break; |
281 | case RTC_UIE_OFF: | 251 | case RTC_UIE_OFF: |
282 | dev_dbg_stamp(dev); | 252 | dev_dbg_stamp(dev); |
283 | bfin_rtc_int_clear(rtc, ~RTC_ISTAT_SEC); | 253 | bfin_rtc_int_clear(~RTC_ISTAT_SEC); |
284 | break; | 254 | break; |
285 | 255 | ||
286 | case RTC_AIE_ON: | 256 | case RTC_AIE_ON: |
@@ -289,7 +259,7 @@ static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long ar | |||
289 | break; | 259 | break; |
290 | case RTC_AIE_OFF: | 260 | case RTC_AIE_OFF: |
291 | dev_dbg_stamp(dev); | 261 | dev_dbg_stamp(dev); |
292 | bfin_rtc_int_clear(rtc, ~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); | 262 | bfin_rtc_int_clear(~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); |
293 | break; | 263 | break; |
294 | 264 | ||
295 | default: | 265 | default: |
@@ -371,64 +341,64 @@ static int bfin_rtc_proc(struct device *dev, struct seq_file *seq) | |||
371 | seq_printf(seq, | 341 | seq_printf(seq, |
372 | "alarm_IRQ\t: %s\n" | 342 | "alarm_IRQ\t: %s\n" |
373 | "wkalarm_IRQ\t: %s\n" | 343 | "wkalarm_IRQ\t: %s\n" |
374 | "seconds_IRQ\t: %s\n" | 344 | "seconds_IRQ\t: %s\n", |
375 | "periodic_IRQ\t: %s\n", | ||
376 | yesno(ictl & RTC_ISTAT_ALARM), | 345 | yesno(ictl & RTC_ISTAT_ALARM), |
377 | yesno(ictl & RTC_ISTAT_ALARM_DAY), | 346 | yesno(ictl & RTC_ISTAT_ALARM_DAY), |
378 | yesno(ictl & RTC_ISTAT_SEC), | 347 | yesno(ictl & RTC_ISTAT_SEC)); |
379 | yesno(ictl & RTC_ISTAT_STOPWATCH)); | ||
380 | return 0; | 348 | return 0; |
381 | #undef yesno | 349 | #undef yesno |
382 | } | 350 | } |
383 | 351 | ||
384 | /** | ||
385 | * bfin_irq_set_freq - make sure hardware supports requested freq | ||
386 | * @dev: pointer to RTC device structure | ||
387 | * @freq: requested frequency rate | ||
388 | * | ||
389 | * The Blackfin RTC can only generate periodic events at 1 per | ||
390 | * second (1 Hz), so reject any attempt at changing it. | ||
391 | */ | ||
392 | static int bfin_irq_set_freq(struct device *dev, int freq) | ||
393 | { | ||
394 | dev_dbg_stamp(dev); | ||
395 | return -ENOTTY; | ||
396 | } | ||
397 | |||
398 | static struct rtc_class_ops bfin_rtc_ops = { | 352 | static struct rtc_class_ops bfin_rtc_ops = { |
399 | .open = bfin_rtc_open, | ||
400 | .release = bfin_rtc_release, | ||
401 | .ioctl = bfin_rtc_ioctl, | 353 | .ioctl = bfin_rtc_ioctl, |
402 | .read_time = bfin_rtc_read_time, | 354 | .read_time = bfin_rtc_read_time, |
403 | .set_time = bfin_rtc_set_time, | 355 | .set_time = bfin_rtc_set_time, |
404 | .read_alarm = bfin_rtc_read_alarm, | 356 | .read_alarm = bfin_rtc_read_alarm, |
405 | .set_alarm = bfin_rtc_set_alarm, | 357 | .set_alarm = bfin_rtc_set_alarm, |
406 | .proc = bfin_rtc_proc, | 358 | .proc = bfin_rtc_proc, |
407 | .irq_set_freq = bfin_irq_set_freq, | ||
408 | }; | 359 | }; |
409 | 360 | ||
410 | static int __devinit bfin_rtc_probe(struct platform_device *pdev) | 361 | static int __devinit bfin_rtc_probe(struct platform_device *pdev) |
411 | { | 362 | { |
412 | struct bfin_rtc *rtc; | 363 | struct bfin_rtc *rtc; |
364 | struct device *dev = &pdev->dev; | ||
413 | int ret = 0; | 365 | int ret = 0; |
366 | unsigned long timeout; | ||
414 | 367 | ||
415 | dev_dbg_stamp(&pdev->dev); | 368 | dev_dbg_stamp(dev); |
416 | 369 | ||
370 | /* Allocate memory for our RTC struct */ | ||
417 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | 371 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); |
418 | if (unlikely(!rtc)) | 372 | if (unlikely(!rtc)) |
419 | return -ENOMEM; | 373 | return -ENOMEM; |
374 | platform_set_drvdata(pdev, rtc); | ||
375 | device_init_wakeup(dev, 1); | ||
420 | 376 | ||
421 | rtc->rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &bfin_rtc_ops, THIS_MODULE); | 377 | /* Grab the IRQ and init the hardware */ |
422 | if (IS_ERR(rtc)) { | 378 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, pdev->name, dev); |
423 | ret = PTR_ERR(rtc->rtc_dev); | 379 | if (unlikely(ret)) |
424 | goto err; | 380 | goto err; |
425 | } | 381 | /* sometimes the bootloader touched things, but the write complete was not |
426 | rtc->rtc_dev->irq_freq = 1; | 382 | * enabled, so let's just do a quick timeout here since the IRQ will not fire ... |
383 | */ | ||
384 | timeout = jiffies + HZ; | ||
385 | while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING) | ||
386 | if (time_after(jiffies, timeout)) | ||
387 | break; | ||
388 | bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); | ||
389 | bfin_write_RTC_SWCNT(0); | ||
427 | 390 | ||
428 | platform_set_drvdata(pdev, rtc); | 391 | /* Register our RTC with the RTC framework */ |
392 | rtc->rtc_dev = rtc_device_register(pdev->name, dev, &bfin_rtc_ops, THIS_MODULE); | ||
393 | if (unlikely(IS_ERR(rtc))) { | ||
394 | ret = PTR_ERR(rtc->rtc_dev); | ||
395 | goto err_irq; | ||
396 | } | ||
429 | 397 | ||
430 | return 0; | 398 | return 0; |
431 | 399 | ||
400 | err_irq: | ||
401 | free_irq(IRQ_RTC, dev); | ||
432 | err: | 402 | err: |
433 | kfree(rtc); | 403 | kfree(rtc); |
434 | return ret; | 404 | return ret; |
@@ -437,7 +407,10 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) | |||
437 | static int __devexit bfin_rtc_remove(struct platform_device *pdev) | 407 | static int __devexit bfin_rtc_remove(struct platform_device *pdev) |
438 | { | 408 | { |
439 | struct bfin_rtc *rtc = platform_get_drvdata(pdev); | 409 | struct bfin_rtc *rtc = platform_get_drvdata(pdev); |
410 | struct device *dev = &pdev->dev; | ||
440 | 411 | ||
412 | bfin_rtc_reset(dev, 0); | ||
413 | free_irq(IRQ_RTC, dev); | ||
441 | rtc_device_unregister(rtc->rtc_dev); | 414 | rtc_device_unregister(rtc->rtc_dev); |
442 | platform_set_drvdata(pdev, NULL); | 415 | platform_set_drvdata(pdev, NULL); |
443 | kfree(rtc); | 416 | kfree(rtc); |
@@ -445,6 +418,32 @@ static int __devexit bfin_rtc_remove(struct platform_device *pdev) | |||
445 | return 0; | 418 | return 0; |
446 | } | 419 | } |
447 | 420 | ||
421 | #ifdef CONFIG_PM | ||
422 | static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) | ||
423 | { | ||
424 | if (device_may_wakeup(&pdev->dev)) { | ||
425 | enable_irq_wake(IRQ_RTC); | ||
426 | bfin_rtc_sync_pending(&pdev->dev); | ||
427 | } else | ||
428 | bfin_rtc_int_clear(-1); | ||
429 | |||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | static int bfin_rtc_resume(struct platform_device *pdev) | ||
434 | { | ||
435 | if (device_may_wakeup(&pdev->dev)) | ||
436 | disable_irq_wake(IRQ_RTC); | ||
437 | else | ||
438 | bfin_write_RTC_ISTAT(-1); | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | #else | ||
443 | # define bfin_rtc_suspend NULL | ||
444 | # define bfin_rtc_resume NULL | ||
445 | #endif | ||
446 | |||
448 | static struct platform_driver bfin_rtc_driver = { | 447 | static struct platform_driver bfin_rtc_driver = { |
449 | .driver = { | 448 | .driver = { |
450 | .name = "rtc-bfin", | 449 | .name = "rtc-bfin", |
@@ -452,6 +451,8 @@ static struct platform_driver bfin_rtc_driver = { | |||
452 | }, | 451 | }, |
453 | .probe = bfin_rtc_probe, | 452 | .probe = bfin_rtc_probe, |
454 | .remove = __devexit_p(bfin_rtc_remove), | 453 | .remove = __devexit_p(bfin_rtc_remove), |
454 | .suspend = bfin_rtc_suspend, | ||
455 | .resume = bfin_rtc_resume, | ||
455 | }; | 456 | }; |
456 | 457 | ||
457 | static int __init bfin_rtc_init(void) | 458 | static int __init bfin_rtc_init(void) |
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c new file mode 100644 index 000000000000..d00a274df8fc --- /dev/null +++ b/drivers/rtc/rtc-bq4802.c | |||
@@ -0,0 +1,230 @@ | |||
1 | /* rtc-bq4802.c: TI BQ4802 RTC driver. | ||
2 | * | ||
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/init.h> | ||
9 | #include <linux/io.h> | ||
10 | #include <linux/platform_device.h> | ||
11 | #include <linux/rtc.h> | ||
12 | #include <linux/bcd.h> | ||
13 | |||
14 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); | ||
15 | MODULE_DESCRIPTION("TI BQ4802 RTC driver"); | ||
16 | MODULE_LICENSE("GPL"); | ||
17 | |||
18 | struct bq4802 { | ||
19 | void __iomem *regs; | ||
20 | unsigned long ioport; | ||
21 | struct rtc_device *rtc; | ||
22 | spinlock_t lock; | ||
23 | struct resource *r; | ||
24 | u8 (*read)(struct bq4802 *, int); | ||
25 | void (*write)(struct bq4802 *, int, u8); | ||
26 | }; | ||
27 | |||
28 | static u8 bq4802_read_io(struct bq4802 *p, int off) | ||
29 | { | ||
30 | return inb(p->ioport + off); | ||
31 | } | ||
32 | |||
33 | static void bq4802_write_io(struct bq4802 *p, int off, u8 val) | ||
34 | { | ||
35 | outb(val, p->ioport + off); | ||
36 | } | ||
37 | |||
38 | static u8 bq4802_read_mem(struct bq4802 *p, int off) | ||
39 | { | ||
40 | return readb(p->regs + off); | ||
41 | } | ||
42 | |||
43 | static void bq4802_write_mem(struct bq4802 *p, int off, u8 val) | ||
44 | { | ||
45 | writeb(val, p->regs + off); | ||
46 | } | ||
47 | |||
48 | static int bq4802_read_time(struct device *dev, struct rtc_time *tm) | ||
49 | { | ||
50 | struct platform_device *pdev = to_platform_device(dev); | ||
51 | struct bq4802 *p = platform_get_drvdata(pdev); | ||
52 | unsigned long flags; | ||
53 | unsigned int century; | ||
54 | u8 val; | ||
55 | |||
56 | spin_lock_irqsave(&p->lock, flags); | ||
57 | |||
58 | val = p->read(p, 0x0e); | ||
59 | p->write(p, 0xe, val | 0x08); | ||
60 | |||
61 | tm->tm_sec = p->read(p, 0x00); | ||
62 | tm->tm_min = p->read(p, 0x02); | ||
63 | tm->tm_hour = p->read(p, 0x04); | ||
64 | tm->tm_mday = p->read(p, 0x06); | ||
65 | tm->tm_mon = p->read(p, 0x09); | ||
66 | tm->tm_year = p->read(p, 0x0a); | ||
67 | tm->tm_wday = p->read(p, 0x08); | ||
68 | century = p->read(p, 0x0f); | ||
69 | |||
70 | p->write(p, 0x0e, val); | ||
71 | |||
72 | spin_unlock_irqrestore(&p->lock, flags); | ||
73 | |||
74 | tm->tm_sec = bcd2bin(tm->tm_sec); | ||
75 | tm->tm_min = bcd2bin(tm->tm_min); | ||
76 | tm->tm_hour = bcd2bin(tm->tm_hour); | ||
77 | tm->tm_mday = bcd2bin(tm->tm_mday); | ||
78 | tm->tm_mon = bcd2bin(tm->tm_mon); | ||
79 | tm->tm_year = bcd2bin(tm->tm_year); | ||
80 | tm->tm_wday = bcd2bin(tm->tm_wday); | ||
81 | century = bcd2bin(century); | ||
82 | |||
83 | tm->tm_year += (century * 100); | ||
84 | tm->tm_year -= 1900; | ||
85 | |||
86 | tm->tm_mon--; | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int bq4802_set_time(struct device *dev, struct rtc_time *tm) | ||
92 | { | ||
93 | struct platform_device *pdev = to_platform_device(dev); | ||
94 | struct bq4802 *p = platform_get_drvdata(pdev); | ||
95 | u8 sec, min, hrs, day, mon, yrs, century, val; | ||
96 | unsigned long flags; | ||
97 | unsigned int year; | ||
98 | |||
99 | year = tm->tm_year + 1900; | ||
100 | century = year / 100; | ||
101 | yrs = year % 100; | ||
102 | |||
103 | mon = tm->tm_mon + 1; /* tm_mon starts at zero */ | ||
104 | day = tm->tm_mday; | ||
105 | hrs = tm->tm_hour; | ||
106 | min = tm->tm_min; | ||
107 | sec = tm->tm_sec; | ||
108 | |||
109 | sec = bin2bcd(sec); | ||
110 | min = bin2bcd(min); | ||
111 | hrs = bin2bcd(hrs); | ||
112 | day = bin2bcd(day); | ||
113 | mon = bin2bcd(mon); | ||
114 | yrs = bin2bcd(yrs); | ||
115 | century = bin2bcd(century); | ||
116 | |||
117 | spin_lock_irqsave(&p->lock, flags); | ||
118 | |||
119 | val = p->read(p, 0x0e); | ||
120 | p->write(p, 0x0e, val | 0x08); | ||
121 | |||
122 | p->write(p, 0x00, sec); | ||
123 | p->write(p, 0x02, min); | ||
124 | p->write(p, 0x04, hrs); | ||
125 | p->write(p, 0x06, day); | ||
126 | p->write(p, 0x09, mon); | ||
127 | p->write(p, 0x0a, yrs); | ||
128 | p->write(p, 0x0f, century); | ||
129 | |||
130 | p->write(p, 0x0e, val); | ||
131 | |||
132 | spin_unlock_irqrestore(&p->lock, flags); | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static const struct rtc_class_ops bq4802_ops = { | ||
138 | .read_time = bq4802_read_time, | ||
139 | .set_time = bq4802_set_time, | ||
140 | }; | ||
141 | |||
142 | static int __devinit bq4802_probe(struct platform_device *pdev) | ||
143 | { | ||
144 | struct bq4802 *p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
145 | int err = -ENOMEM; | ||
146 | |||
147 | if (!p) | ||
148 | goto out; | ||
149 | |||
150 | spin_lock_init(&p->lock); | ||
151 | |||
152 | p->r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
153 | if (!p->r) { | ||
154 | p->r = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
155 | err = -EINVAL; | ||
156 | if (!p->r) | ||
157 | goto out_free; | ||
158 | } | ||
159 | if (p->r->flags & IORESOURCE_IO) { | ||
160 | p->ioport = p->r->start; | ||
161 | p->read = bq4802_read_io; | ||
162 | p->write = bq4802_write_io; | ||
163 | } else if (p->r->flags & IORESOURCE_MEM) { | ||
164 | p->regs = ioremap(p->r->start, resource_size(p->r)); | ||
165 | p->read = bq4802_read_mem; | ||
166 | p->write = bq4802_write_mem; | ||
167 | } else { | ||
168 | err = -EINVAL; | ||
169 | goto out_free; | ||
170 | } | ||
171 | |||
172 | p->rtc = rtc_device_register("bq4802", &pdev->dev, | ||
173 | &bq4802_ops, THIS_MODULE); | ||
174 | if (IS_ERR(p->rtc)) { | ||
175 | err = PTR_ERR(p->rtc); | ||
176 | goto out_iounmap; | ||
177 | } | ||
178 | |||
179 | platform_set_drvdata(pdev, p); | ||
180 | err = 0; | ||
181 | out: | ||
182 | return err; | ||
183 | |||
184 | out_iounmap: | ||
185 | if (p->r->flags & IORESOURCE_MEM) | ||
186 | iounmap(p->regs); | ||
187 | out_free: | ||
188 | kfree(p); | ||
189 | goto out; | ||
190 | } | ||
191 | |||
192 | static int __devexit bq4802_remove(struct platform_device *pdev) | ||
193 | { | ||
194 | struct bq4802 *p = platform_get_drvdata(pdev); | ||
195 | |||
196 | rtc_device_unregister(p->rtc); | ||
197 | if (p->r->flags & IORESOURCE_MEM) | ||
198 | iounmap(p->regs); | ||
199 | |||
200 | platform_set_drvdata(pdev, NULL); | ||
201 | |||
202 | kfree(p); | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | /* work with hotplug and coldplug */ | ||
208 | MODULE_ALIAS("platform:rtc-bq4802"); | ||
209 | |||
210 | static struct platform_driver bq4802_driver = { | ||
211 | .driver = { | ||
212 | .name = "rtc-bq4802", | ||
213 | .owner = THIS_MODULE, | ||
214 | }, | ||
215 | .probe = bq4802_probe, | ||
216 | .remove = __devexit_p(bq4802_remove), | ||
217 | }; | ||
218 | |||
219 | static int __init bq4802_init(void) | ||
220 | { | ||
221 | return platform_driver_register(&bq4802_driver); | ||
222 | } | ||
223 | |||
224 | static void __exit bq4802_exit(void) | ||
225 | { | ||
226 | platform_driver_unregister(&bq4802_driver); | ||
227 | } | ||
228 | |||
229 | module_init(bq4802_init); | ||
230 | module_exit(bq4802_exit); | ||
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index d7bb9bac71df..5549231179a2 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -36,25 +36,9 @@ | |||
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/mod_devicetable.h> | 37 | #include <linux/mod_devicetable.h> |
38 | 38 | ||
39 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
40 | #include <asm/hpet.h> | ||
41 | #endif | ||
42 | |||
43 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ | 39 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ |
44 | #include <asm-generic/rtc.h> | 40 | #include <asm-generic/rtc.h> |
45 | 41 | ||
46 | #ifndef CONFIG_HPET_EMULATE_RTC | ||
47 | #define is_hpet_enabled() 0 | ||
48 | #define hpet_set_alarm_time(hrs, min, sec) do { } while (0) | ||
49 | #define hpet_set_periodic_freq(arg) 0 | ||
50 | #define hpet_mask_rtc_irq_bit(arg) do { } while (0) | ||
51 | #define hpet_set_rtc_irq_bit(arg) do { } while (0) | ||
52 | #define hpet_rtc_timer_init() do { } while (0) | ||
53 | #define hpet_register_irq_handler(h) 0 | ||
54 | #define hpet_unregister_irq_handler(h) do { } while (0) | ||
55 | extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id); | ||
56 | #endif | ||
57 | |||
58 | struct cmos_rtc { | 42 | struct cmos_rtc { |
59 | struct rtc_device *rtc; | 43 | struct rtc_device *rtc; |
60 | struct device *dev; | 44 | struct device *dev; |
@@ -93,6 +77,109 @@ static inline int is_intr(u8 rtc_intr) | |||
93 | 77 | ||
94 | /*----------------------------------------------------------------*/ | 78 | /*----------------------------------------------------------------*/ |
95 | 79 | ||
80 | /* Much modern x86 hardware has HPETs (10+ MHz timers) which, because | ||
81 | * many BIOS programmers don't set up "sane mode" IRQ routing, are mostly | ||
82 | * used in a broken "legacy replacement" mode. The breakage includes | ||
83 | * HPET #1 hijacking the IRQ for this RTC, and being unavailable for | ||
84 | * other (better) use. | ||
85 | * | ||
86 | * When that broken mode is in use, platform glue provides a partial | ||
87 | * emulation of hardware RTC IRQ facilities using HPET #1. We don't | ||
88 | * want to use HPET for anything except those IRQs though... | ||
89 | */ | ||
90 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
91 | #include <asm/hpet.h> | ||
92 | #else | ||
93 | |||
94 | static inline int is_hpet_enabled(void) | ||
95 | { | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static inline int hpet_mask_rtc_irq_bit(unsigned long mask) | ||
100 | { | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static inline int hpet_set_rtc_irq_bit(unsigned long mask) | ||
105 | { | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static inline int | ||
110 | hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec) | ||
111 | { | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static inline int hpet_set_periodic_freq(unsigned long freq) | ||
116 | { | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static inline int hpet_rtc_dropped_irq(void) | ||
121 | { | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static inline int hpet_rtc_timer_init(void) | ||
126 | { | ||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | extern irq_handler_t hpet_rtc_interrupt; | ||
131 | |||
132 | static inline int hpet_register_irq_handler(irq_handler_t handler) | ||
133 | { | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static inline int hpet_unregister_irq_handler(irq_handler_t handler) | ||
138 | { | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | #endif | ||
143 | |||
144 | /*----------------------------------------------------------------*/ | ||
145 | |||
146 | #ifdef RTC_PORT | ||
147 | |||
148 | /* Most newer x86 systems have two register banks, the first used | ||
149 | * for RTC and NVRAM and the second only for NVRAM. Caller must | ||
150 | * own rtc_lock ... and we won't worry about access during NMI. | ||
151 | */ | ||
152 | #define can_bank2 true | ||
153 | |||
154 | static inline unsigned char cmos_read_bank2(unsigned char addr) | ||
155 | { | ||
156 | outb(addr, RTC_PORT(2)); | ||
157 | return inb(RTC_PORT(3)); | ||
158 | } | ||
159 | |||
160 | static inline void cmos_write_bank2(unsigned char val, unsigned char addr) | ||
161 | { | ||
162 | outb(addr, RTC_PORT(2)); | ||
163 | outb(val, RTC_PORT(2)); | ||
164 | } | ||
165 | |||
166 | #else | ||
167 | |||
168 | #define can_bank2 false | ||
169 | |||
170 | static inline unsigned char cmos_read_bank2(unsigned char addr) | ||
171 | { | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static inline void cmos_write_bank2(unsigned char val, unsigned char addr) | ||
176 | { | ||
177 | } | ||
178 | |||
179 | #endif | ||
180 | |||
181 | /*----------------------------------------------------------------*/ | ||
182 | |||
96 | static int cmos_read_time(struct device *dev, struct rtc_time *t) | 183 | static int cmos_read_time(struct device *dev, struct rtc_time *t) |
97 | { | 184 | { |
98 | /* REVISIT: if the clock has a "century" register, use | 185 | /* REVISIT: if the clock has a "century" register, use |
@@ -153,26 +240,26 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
153 | /* REVISIT this assumes PC style usage: always BCD */ | 240 | /* REVISIT this assumes PC style usage: always BCD */ |
154 | 241 | ||
155 | if (((unsigned)t->time.tm_sec) < 0x60) | 242 | if (((unsigned)t->time.tm_sec) < 0x60) |
156 | t->time.tm_sec = BCD2BIN(t->time.tm_sec); | 243 | t->time.tm_sec = bcd2bin(t->time.tm_sec); |
157 | else | 244 | else |
158 | t->time.tm_sec = -1; | 245 | t->time.tm_sec = -1; |
159 | if (((unsigned)t->time.tm_min) < 0x60) | 246 | if (((unsigned)t->time.tm_min) < 0x60) |
160 | t->time.tm_min = BCD2BIN(t->time.tm_min); | 247 | t->time.tm_min = bcd2bin(t->time.tm_min); |
161 | else | 248 | else |
162 | t->time.tm_min = -1; | 249 | t->time.tm_min = -1; |
163 | if (((unsigned)t->time.tm_hour) < 0x24) | 250 | if (((unsigned)t->time.tm_hour) < 0x24) |
164 | t->time.tm_hour = BCD2BIN(t->time.tm_hour); | 251 | t->time.tm_hour = bcd2bin(t->time.tm_hour); |
165 | else | 252 | else |
166 | t->time.tm_hour = -1; | 253 | t->time.tm_hour = -1; |
167 | 254 | ||
168 | if (cmos->day_alrm) { | 255 | if (cmos->day_alrm) { |
169 | if (((unsigned)t->time.tm_mday) <= 0x31) | 256 | if (((unsigned)t->time.tm_mday) <= 0x31) |
170 | t->time.tm_mday = BCD2BIN(t->time.tm_mday); | 257 | t->time.tm_mday = bcd2bin(t->time.tm_mday); |
171 | else | 258 | else |
172 | t->time.tm_mday = -1; | 259 | t->time.tm_mday = -1; |
173 | if (cmos->mon_alrm) { | 260 | if (cmos->mon_alrm) { |
174 | if (((unsigned)t->time.tm_mon) <= 0x12) | 261 | if (((unsigned)t->time.tm_mon) <= 0x12) |
175 | t->time.tm_mon = BCD2BIN(t->time.tm_mon) - 1; | 262 | t->time.tm_mon = bcd2bin(t->time.tm_mon) - 1; |
176 | else | 263 | else |
177 | t->time.tm_mon = -1; | 264 | t->time.tm_mon = -1; |
178 | } | 265 | } |
@@ -185,11 +272,56 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
185 | return 0; | 272 | return 0; |
186 | } | 273 | } |
187 | 274 | ||
275 | static void cmos_checkintr(struct cmos_rtc *cmos, unsigned char rtc_control) | ||
276 | { | ||
277 | unsigned char rtc_intr; | ||
278 | |||
279 | /* NOTE after changing RTC_xIE bits we always read INTR_FLAGS; | ||
280 | * allegedly some older rtcs need that to handle irqs properly | ||
281 | */ | ||
282 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | ||
283 | |||
284 | if (is_hpet_enabled()) | ||
285 | return; | ||
286 | |||
287 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | ||
288 | if (is_intr(rtc_intr)) | ||
289 | rtc_update_irq(cmos->rtc, 1, rtc_intr); | ||
290 | } | ||
291 | |||
292 | static void cmos_irq_enable(struct cmos_rtc *cmos, unsigned char mask) | ||
293 | { | ||
294 | unsigned char rtc_control; | ||
295 | |||
296 | /* flush any pending IRQ status, notably for update irqs, | ||
297 | * before we enable new IRQs | ||
298 | */ | ||
299 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
300 | cmos_checkintr(cmos, rtc_control); | ||
301 | |||
302 | rtc_control |= mask; | ||
303 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
304 | hpet_set_rtc_irq_bit(mask); | ||
305 | |||
306 | cmos_checkintr(cmos, rtc_control); | ||
307 | } | ||
308 | |||
309 | static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask) | ||
310 | { | ||
311 | unsigned char rtc_control; | ||
312 | |||
313 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
314 | rtc_control &= ~mask; | ||
315 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
316 | hpet_mask_rtc_irq_bit(mask); | ||
317 | |||
318 | cmos_checkintr(cmos, rtc_control); | ||
319 | } | ||
320 | |||
188 | static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | 321 | static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) |
189 | { | 322 | { |
190 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 323 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
191 | unsigned char mon, mday, hrs, min, sec; | 324 | unsigned char mon, mday, hrs, min, sec; |
192 | unsigned char rtc_control, rtc_intr; | ||
193 | 325 | ||
194 | if (!is_valid_irq(cmos->irq)) | 326 | if (!is_valid_irq(cmos->irq)) |
195 | return -EIO; | 327 | return -EIO; |
@@ -199,31 +331,24 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
199 | /* Writing 0xff means "don't care" or "match all". */ | 331 | /* Writing 0xff means "don't care" or "match all". */ |
200 | 332 | ||
201 | mon = t->time.tm_mon + 1; | 333 | mon = t->time.tm_mon + 1; |
202 | mon = (mon <= 12) ? BIN2BCD(mon) : 0xff; | 334 | mon = (mon <= 12) ? bin2bcd(mon) : 0xff; |
203 | 335 | ||
204 | mday = t->time.tm_mday; | 336 | mday = t->time.tm_mday; |
205 | mday = (mday >= 1 && mday <= 31) ? BIN2BCD(mday) : 0xff; | 337 | mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff; |
206 | 338 | ||
207 | hrs = t->time.tm_hour; | 339 | hrs = t->time.tm_hour; |
208 | hrs = (hrs < 24) ? BIN2BCD(hrs) : 0xff; | 340 | hrs = (hrs < 24) ? bin2bcd(hrs) : 0xff; |
209 | 341 | ||
210 | min = t->time.tm_min; | 342 | min = t->time.tm_min; |
211 | min = (min < 60) ? BIN2BCD(min) : 0xff; | 343 | min = (min < 60) ? bin2bcd(min) : 0xff; |
212 | 344 | ||
213 | sec = t->time.tm_sec; | 345 | sec = t->time.tm_sec; |
214 | sec = (sec < 60) ? BIN2BCD(sec) : 0xff; | 346 | sec = (sec < 60) ? bin2bcd(sec) : 0xff; |
215 | 347 | ||
216 | hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec); | ||
217 | spin_lock_irq(&rtc_lock); | 348 | spin_lock_irq(&rtc_lock); |
218 | 349 | ||
219 | /* next rtc irq must not be from previous alarm setting */ | 350 | /* next rtc irq must not be from previous alarm setting */ |
220 | rtc_control = CMOS_READ(RTC_CONTROL); | 351 | cmos_irq_disable(cmos, RTC_AIE); |
221 | rtc_control &= ~RTC_AIE; | ||
222 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
223 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | ||
224 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | ||
225 | if (is_intr(rtc_intr)) | ||
226 | rtc_update_irq(cmos->rtc, 1, rtc_intr); | ||
227 | 352 | ||
228 | /* update alarm */ | 353 | /* update alarm */ |
229 | CMOS_WRITE(hrs, RTC_HOURS_ALARM); | 354 | CMOS_WRITE(hrs, RTC_HOURS_ALARM); |
@@ -237,14 +362,13 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
237 | CMOS_WRITE(mon, cmos->mon_alrm); | 362 | CMOS_WRITE(mon, cmos->mon_alrm); |
238 | } | 363 | } |
239 | 364 | ||
240 | if (t->enabled) { | 365 | /* FIXME the HPET alarm glue currently ignores day_alrm |
241 | rtc_control |= RTC_AIE; | 366 | * and mon_alrm ... |
242 | CMOS_WRITE(rtc_control, RTC_CONTROL); | 367 | */ |
243 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | 368 | hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec); |
244 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | 369 | |
245 | if (is_intr(rtc_intr)) | 370 | if (t->enabled) |
246 | rtc_update_irq(cmos->rtc, 1, rtc_intr); | 371 | cmos_irq_enable(cmos, RTC_AIE); |
247 | } | ||
248 | 372 | ||
249 | spin_unlock_irq(&rtc_lock); | 373 | spin_unlock_irq(&rtc_lock); |
250 | 374 | ||
@@ -267,8 +391,8 @@ static int cmos_irq_set_freq(struct device *dev, int freq) | |||
267 | f = 16 - f; | 391 | f = 16 - f; |
268 | 392 | ||
269 | spin_lock_irqsave(&rtc_lock, flags); | 393 | spin_lock_irqsave(&rtc_lock, flags); |
270 | if (!hpet_set_periodic_freq(freq)) | 394 | hpet_set_periodic_freq(freq); |
271 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); | 395 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); |
272 | spin_unlock_irqrestore(&rtc_lock, flags); | 396 | spin_unlock_irqrestore(&rtc_lock, flags); |
273 | 397 | ||
274 | return 0; | 398 | return 0; |
@@ -277,26 +401,17 @@ static int cmos_irq_set_freq(struct device *dev, int freq) | |||
277 | static int cmos_irq_set_state(struct device *dev, int enabled) | 401 | static int cmos_irq_set_state(struct device *dev, int enabled) |
278 | { | 402 | { |
279 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 403 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
280 | unsigned char rtc_control, rtc_intr; | ||
281 | unsigned long flags; | 404 | unsigned long flags; |
282 | 405 | ||
283 | if (!is_valid_irq(cmos->irq)) | 406 | if (!is_valid_irq(cmos->irq)) |
284 | return -ENXIO; | 407 | return -ENXIO; |
285 | 408 | ||
286 | spin_lock_irqsave(&rtc_lock, flags); | 409 | spin_lock_irqsave(&rtc_lock, flags); |
287 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
288 | 410 | ||
289 | if (enabled) | 411 | if (enabled) |
290 | rtc_control |= RTC_PIE; | 412 | cmos_irq_enable(cmos, RTC_PIE); |
291 | else | 413 | else |
292 | rtc_control &= ~RTC_PIE; | 414 | cmos_irq_disable(cmos, RTC_PIE); |
293 | |||
294 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
295 | |||
296 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | ||
297 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | ||
298 | if (is_intr(rtc_intr)) | ||
299 | rtc_update_irq(cmos->rtc, 1, rtc_intr); | ||
300 | 415 | ||
301 | spin_unlock_irqrestore(&rtc_lock, flags); | 416 | spin_unlock_irqrestore(&rtc_lock, flags); |
302 | return 0; | 417 | return 0; |
@@ -308,7 +423,6 @@ static int | |||
308 | cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 423 | cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
309 | { | 424 | { |
310 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 425 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
311 | unsigned char rtc_control, rtc_intr; | ||
312 | unsigned long flags; | 426 | unsigned long flags; |
313 | 427 | ||
314 | switch (cmd) { | 428 | switch (cmd) { |
@@ -316,51 +430,29 @@ cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
316 | case RTC_AIE_ON: | 430 | case RTC_AIE_ON: |
317 | case RTC_UIE_OFF: | 431 | case RTC_UIE_OFF: |
318 | case RTC_UIE_ON: | 432 | case RTC_UIE_ON: |
319 | case RTC_PIE_OFF: | ||
320 | case RTC_PIE_ON: | ||
321 | if (!is_valid_irq(cmos->irq)) | 433 | if (!is_valid_irq(cmos->irq)) |
322 | return -EINVAL; | 434 | return -EINVAL; |
323 | break; | 435 | break; |
436 | /* PIE ON/OFF is handled by cmos_irq_set_state() */ | ||
324 | default: | 437 | default: |
325 | return -ENOIOCTLCMD; | 438 | return -ENOIOCTLCMD; |
326 | } | 439 | } |
327 | 440 | ||
328 | spin_lock_irqsave(&rtc_lock, flags); | 441 | spin_lock_irqsave(&rtc_lock, flags); |
329 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
330 | switch (cmd) { | 442 | switch (cmd) { |
331 | case RTC_AIE_OFF: /* alarm off */ | 443 | case RTC_AIE_OFF: /* alarm off */ |
332 | rtc_control &= ~RTC_AIE; | 444 | cmos_irq_disable(cmos, RTC_AIE); |
333 | hpet_mask_rtc_irq_bit(RTC_AIE); | ||
334 | break; | 445 | break; |
335 | case RTC_AIE_ON: /* alarm on */ | 446 | case RTC_AIE_ON: /* alarm on */ |
336 | rtc_control |= RTC_AIE; | 447 | cmos_irq_enable(cmos, RTC_AIE); |
337 | hpet_set_rtc_irq_bit(RTC_AIE); | ||
338 | break; | 448 | break; |
339 | case RTC_UIE_OFF: /* update off */ | 449 | case RTC_UIE_OFF: /* update off */ |
340 | rtc_control &= ~RTC_UIE; | 450 | cmos_irq_disable(cmos, RTC_UIE); |
341 | hpet_mask_rtc_irq_bit(RTC_UIE); | ||
342 | break; | 451 | break; |
343 | case RTC_UIE_ON: /* update on */ | 452 | case RTC_UIE_ON: /* update on */ |
344 | rtc_control |= RTC_UIE; | 453 | cmos_irq_enable(cmos, RTC_UIE); |
345 | hpet_set_rtc_irq_bit(RTC_UIE); | ||
346 | break; | ||
347 | case RTC_PIE_OFF: /* periodic off */ | ||
348 | rtc_control &= ~RTC_PIE; | ||
349 | hpet_mask_rtc_irq_bit(RTC_PIE); | ||
350 | break; | ||
351 | case RTC_PIE_ON: /* periodic on */ | ||
352 | rtc_control |= RTC_PIE; | ||
353 | hpet_set_rtc_irq_bit(RTC_PIE); | ||
354 | break; | 454 | break; |
355 | } | 455 | } |
356 | if (!is_hpet_enabled()) | ||
357 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
358 | |||
359 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | ||
360 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | ||
361 | if (is_intr(rtc_intr)) | ||
362 | rtc_update_irq(cmos->rtc, 1, rtc_intr); | ||
363 | |||
364 | spin_unlock_irqrestore(&rtc_lock, flags); | 456 | spin_unlock_irqrestore(&rtc_lock, flags); |
365 | return 0; | 457 | return 0; |
366 | } | 458 | } |
@@ -436,12 +528,21 @@ cmos_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | |||
436 | 528 | ||
437 | if (unlikely(off >= attr->size)) | 529 | if (unlikely(off >= attr->size)) |
438 | return 0; | 530 | return 0; |
531 | if (unlikely(off < 0)) | ||
532 | return -EINVAL; | ||
439 | if ((off + count) > attr->size) | 533 | if ((off + count) > attr->size) |
440 | count = attr->size - off; | 534 | count = attr->size - off; |
441 | 535 | ||
536 | off += NVRAM_OFFSET; | ||
442 | spin_lock_irq(&rtc_lock); | 537 | spin_lock_irq(&rtc_lock); |
443 | for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++) | 538 | for (retval = 0; count; count--, off++, retval++) { |
444 | *buf++ = CMOS_READ(off); | 539 | if (off < 128) |
540 | *buf++ = CMOS_READ(off); | ||
541 | else if (can_bank2) | ||
542 | *buf++ = cmos_read_bank2(off); | ||
543 | else | ||
544 | break; | ||
545 | } | ||
445 | spin_unlock_irq(&rtc_lock); | 546 | spin_unlock_irq(&rtc_lock); |
446 | 547 | ||
447 | return retval; | 548 | return retval; |
@@ -457,6 +558,8 @@ cmos_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | |||
457 | cmos = dev_get_drvdata(container_of(kobj, struct device, kobj)); | 558 | cmos = dev_get_drvdata(container_of(kobj, struct device, kobj)); |
458 | if (unlikely(off >= attr->size)) | 559 | if (unlikely(off >= attr->size)) |
459 | return -EFBIG; | 560 | return -EFBIG; |
561 | if (unlikely(off < 0)) | ||
562 | return -EINVAL; | ||
460 | if ((off + count) > attr->size) | 563 | if ((off + count) > attr->size) |
461 | count = attr->size - off; | 564 | count = attr->size - off; |
462 | 565 | ||
@@ -465,15 +568,20 @@ cmos_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | |||
465 | * here. If userspace is smart enough to know what fields of | 568 | * here. If userspace is smart enough to know what fields of |
466 | * NVRAM to update, updating checksums is also part of its job. | 569 | * NVRAM to update, updating checksums is also part of its job. |
467 | */ | 570 | */ |
571 | off += NVRAM_OFFSET; | ||
468 | spin_lock_irq(&rtc_lock); | 572 | spin_lock_irq(&rtc_lock); |
469 | for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++) { | 573 | for (retval = 0; count; count--, off++, retval++) { |
470 | /* don't trash RTC registers */ | 574 | /* don't trash RTC registers */ |
471 | if (off == cmos->day_alrm | 575 | if (off == cmos->day_alrm |
472 | || off == cmos->mon_alrm | 576 | || off == cmos->mon_alrm |
473 | || off == cmos->century) | 577 | || off == cmos->century) |
474 | buf++; | 578 | buf++; |
475 | else | 579 | else if (off < 128) |
476 | CMOS_WRITE(*buf++, off); | 580 | CMOS_WRITE(*buf++, off); |
581 | else if (can_bank2) | ||
582 | cmos_write_bank2(*buf++, off); | ||
583 | else | ||
584 | break; | ||
477 | } | 585 | } |
478 | spin_unlock_irq(&rtc_lock); | 586 | spin_unlock_irq(&rtc_lock); |
479 | 587 | ||
@@ -484,7 +592,6 @@ static struct bin_attribute nvram = { | |||
484 | .attr = { | 592 | .attr = { |
485 | .name = "nvram", | 593 | .name = "nvram", |
486 | .mode = S_IRUGO | S_IWUSR, | 594 | .mode = S_IRUGO | S_IWUSR, |
487 | .owner = THIS_MODULE, | ||
488 | }, | 595 | }, |
489 | 596 | ||
490 | .read = cmos_nvram_read, | 597 | .read = cmos_nvram_read, |
@@ -502,27 +609,29 @@ static irqreturn_t cmos_interrupt(int irq, void *p) | |||
502 | u8 rtc_control; | 609 | u8 rtc_control; |
503 | 610 | ||
504 | spin_lock(&rtc_lock); | 611 | spin_lock(&rtc_lock); |
505 | /* | 612 | |
506 | * In this case it is HPET RTC interrupt handler | 613 | /* When the HPET interrupt handler calls us, the interrupt |
507 | * calling us, with the interrupt information | 614 | * status is passed as arg1 instead of the irq number. But |
508 | * passed as arg1, instead of irq. | 615 | * always clear irq status, even when HPET is in the way. |
616 | * | ||
617 | * Note that HPET and RTC are almost certainly out of phase, | ||
618 | * giving different IRQ status ... | ||
509 | */ | 619 | */ |
620 | irqstat = CMOS_READ(RTC_INTR_FLAGS); | ||
621 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
510 | if (is_hpet_enabled()) | 622 | if (is_hpet_enabled()) |
511 | irqstat = (unsigned long)irq & 0xF0; | 623 | irqstat = (unsigned long)irq & 0xF0; |
512 | else { | 624 | irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; |
513 | irqstat = CMOS_READ(RTC_INTR_FLAGS); | ||
514 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
515 | irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | ||
516 | } | ||
517 | 625 | ||
518 | /* All Linux RTC alarms should be treated as if they were oneshot. | 626 | /* All Linux RTC alarms should be treated as if they were oneshot. |
519 | * Similar code may be needed in system wakeup paths, in case the | 627 | * Similar code may be needed in system wakeup paths, in case the |
520 | * alarm woke the system. | 628 | * alarm woke the system. |
521 | */ | 629 | */ |
522 | if (irqstat & RTC_AIE) { | 630 | if (irqstat & RTC_AIE) { |
523 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
524 | rtc_control &= ~RTC_AIE; | 631 | rtc_control &= ~RTC_AIE; |
525 | CMOS_WRITE(rtc_control, RTC_CONTROL); | 632 | CMOS_WRITE(rtc_control, RTC_CONTROL); |
633 | hpet_mask_rtc_irq_bit(RTC_AIE); | ||
634 | |||
526 | CMOS_READ(RTC_INTR_FLAGS); | 635 | CMOS_READ(RTC_INTR_FLAGS); |
527 | } | 636 | } |
528 | spin_unlock(&rtc_lock); | 637 | spin_unlock(&rtc_lock); |
@@ -574,17 +683,19 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
574 | 683 | ||
575 | /* Heuristic to deduce NVRAM size ... do what the legacy NVRAM | 684 | /* Heuristic to deduce NVRAM size ... do what the legacy NVRAM |
576 | * driver did, but don't reject unknown configs. Old hardware | 685 | * driver did, but don't reject unknown configs. Old hardware |
577 | * won't address 128 bytes, and for now we ignore the way newer | 686 | * won't address 128 bytes. Newer chips have multiple banks, |
578 | * chips can address 256 bytes (using two more i/o ports). | 687 | * though they may not be listed in one I/O resource. |
579 | */ | 688 | */ |
580 | #if defined(CONFIG_ATARI) | 689 | #if defined(CONFIG_ATARI) |
581 | address_space = 64; | 690 | address_space = 64; |
582 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) | 691 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__sparc__) |
583 | address_space = 128; | 692 | address_space = 128; |
584 | #else | 693 | #else |
585 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. | 694 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. |
586 | address_space = 128; | 695 | address_space = 128; |
587 | #endif | 696 | #endif |
697 | if (can_bank2 && ports->end > (ports->start + 1)) | ||
698 | address_space = 256; | ||
588 | 699 | ||
589 | /* For ACPI systems extension info comes from the FADT. On others, | 700 | /* For ACPI systems extension info comes from the FADT. On others, |
590 | * board specific setup provides it as appropriate. Systems where | 701 | * board specific setup provides it as appropriate. Systems where |
@@ -629,25 +740,21 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
629 | * do something about other clock frequencies. | 740 | * do something about other clock frequencies. |
630 | */ | 741 | */ |
631 | cmos_rtc.rtc->irq_freq = 1024; | 742 | cmos_rtc.rtc->irq_freq = 1024; |
632 | if (!hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq)) | 743 | hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq); |
633 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); | 744 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); |
745 | |||
746 | /* disable irqs */ | ||
747 | cmos_irq_disable(&cmos_rtc, RTC_PIE | RTC_AIE | RTC_UIE); | ||
634 | 748 | ||
635 | /* disable irqs. | ||
636 | * | ||
637 | * NOTE after changing RTC_xIE bits we always read INTR_FLAGS; | ||
638 | * allegedly some older rtcs need that to handle irqs properly | ||
639 | */ | ||
640 | rtc_control = CMOS_READ(RTC_CONTROL); | 749 | rtc_control = CMOS_READ(RTC_CONTROL); |
641 | rtc_control &= ~(RTC_PIE | RTC_AIE | RTC_UIE); | ||
642 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
643 | CMOS_READ(RTC_INTR_FLAGS); | ||
644 | 750 | ||
645 | spin_unlock_irq(&rtc_lock); | 751 | spin_unlock_irq(&rtc_lock); |
646 | 752 | ||
647 | /* FIXME teach the alarm code how to handle binary mode; | 753 | /* FIXME teach the alarm code how to handle binary mode; |
648 | * <asm-generic/rtc.h> doesn't know 12-hour mode either. | 754 | * <asm-generic/rtc.h> doesn't know 12-hour mode either. |
649 | */ | 755 | */ |
650 | if (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY))) { | 756 | if (is_valid_irq(rtc_irq) && |
757 | (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY)))) { | ||
651 | dev_dbg(dev, "only 24-hr BCD mode supported\n"); | 758 | dev_dbg(dev, "only 24-hr BCD mode supported\n"); |
652 | retval = -ENXIO; | 759 | retval = -ENXIO; |
653 | goto cleanup1; | 760 | goto cleanup1; |
@@ -687,7 +794,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
687 | goto cleanup2; | 794 | goto cleanup2; |
688 | } | 795 | } |
689 | 796 | ||
690 | pr_info("%s: alarms up to one %s%s\n", | 797 | pr_info("%s: alarms up to one %s%s, %zd bytes nvram, %s irqs\n", |
691 | cmos_rtc.rtc->dev.bus_id, | 798 | cmos_rtc.rtc->dev.bus_id, |
692 | is_valid_irq(rtc_irq) | 799 | is_valid_irq(rtc_irq) |
693 | ? (cmos_rtc.mon_alrm | 800 | ? (cmos_rtc.mon_alrm |
@@ -695,8 +802,9 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
695 | : (cmos_rtc.day_alrm | 802 | : (cmos_rtc.day_alrm |
696 | ? "month" : "day")) | 803 | ? "month" : "day")) |
697 | : "no", | 804 | : "no", |
698 | cmos_rtc.century ? ", y3k" : "" | 805 | cmos_rtc.century ? ", y3k" : "", |
699 | ); | 806 | nvram.size, |
807 | is_hpet_enabled() ? ", hpet irqs" : ""); | ||
700 | 808 | ||
701 | return 0; | 809 | return 0; |
702 | 810 | ||
@@ -713,13 +821,8 @@ cleanup0: | |||
713 | 821 | ||
714 | static void cmos_do_shutdown(void) | 822 | static void cmos_do_shutdown(void) |
715 | { | 823 | { |
716 | unsigned char rtc_control; | ||
717 | |||
718 | spin_lock_irq(&rtc_lock); | 824 | spin_lock_irq(&rtc_lock); |
719 | rtc_control = CMOS_READ(RTC_CONTROL); | 825 | cmos_irq_disable(&cmos_rtc, RTC_IRQMASK); |
720 | rtc_control &= ~(RTC_PIE|RTC_AIE|RTC_UIE); | ||
721 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
722 | CMOS_READ(RTC_INTR_FLAGS); | ||
723 | spin_unlock_irq(&rtc_lock); | 826 | spin_unlock_irq(&rtc_lock); |
724 | } | 827 | } |
725 | 828 | ||
@@ -753,24 +856,23 @@ static void __exit cmos_do_remove(struct device *dev) | |||
753 | static int cmos_suspend(struct device *dev, pm_message_t mesg) | 856 | static int cmos_suspend(struct device *dev, pm_message_t mesg) |
754 | { | 857 | { |
755 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 858 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
756 | int do_wake = device_may_wakeup(dev); | ||
757 | unsigned char tmp; | 859 | unsigned char tmp; |
758 | 860 | ||
759 | /* only the alarm might be a wakeup event source */ | 861 | /* only the alarm might be a wakeup event source */ |
760 | spin_lock_irq(&rtc_lock); | 862 | spin_lock_irq(&rtc_lock); |
761 | cmos->suspend_ctrl = tmp = CMOS_READ(RTC_CONTROL); | 863 | cmos->suspend_ctrl = tmp = CMOS_READ(RTC_CONTROL); |
762 | if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) { | 864 | if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) { |
763 | unsigned char irqstat; | 865 | unsigned char mask; |
764 | 866 | ||
765 | if (do_wake) | 867 | if (device_may_wakeup(dev)) |
766 | tmp &= ~(RTC_PIE|RTC_UIE); | 868 | mask = RTC_IRQMASK & ~RTC_AIE; |
767 | else | 869 | else |
768 | tmp &= ~(RTC_PIE|RTC_AIE|RTC_UIE); | 870 | mask = RTC_IRQMASK; |
871 | tmp &= ~mask; | ||
769 | CMOS_WRITE(tmp, RTC_CONTROL); | 872 | CMOS_WRITE(tmp, RTC_CONTROL); |
770 | irqstat = CMOS_READ(RTC_INTR_FLAGS); | 873 | hpet_mask_rtc_irq_bit(mask); |
771 | irqstat &= (tmp & RTC_IRQMASK) | RTC_IRQF; | 874 | |
772 | if (is_intr(irqstat)) | 875 | cmos_checkintr(cmos, tmp); |
773 | rtc_update_irq(cmos->rtc, 1, irqstat); | ||
774 | } | 876 | } |
775 | spin_unlock_irq(&rtc_lock); | 877 | spin_unlock_irq(&rtc_lock); |
776 | 878 | ||
@@ -790,13 +892,25 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg) | |||
790 | return 0; | 892 | return 0; |
791 | } | 893 | } |
792 | 894 | ||
895 | /* We want RTC alarms to wake us from e.g. ACPI G2/S5 "soft off", even | ||
896 | * after a detour through G3 "mechanical off", although the ACPI spec | ||
897 | * says wakeup should only work from G1/S4 "hibernate". To most users, | ||
898 | * distinctions between S4 and S5 are pointless. So when the hardware | ||
899 | * allows, don't draw that distinction. | ||
900 | */ | ||
901 | static inline int cmos_poweroff(struct device *dev) | ||
902 | { | ||
903 | return cmos_suspend(dev, PMSG_HIBERNATE); | ||
904 | } | ||
905 | |||
793 | static int cmos_resume(struct device *dev) | 906 | static int cmos_resume(struct device *dev) |
794 | { | 907 | { |
795 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 908 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
796 | unsigned char tmp = cmos->suspend_ctrl; | 909 | unsigned char tmp = cmos->suspend_ctrl; |
797 | 910 | ||
798 | /* re-enable any irqs previously active */ | 911 | /* re-enable any irqs previously active */ |
799 | if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) { | 912 | if (tmp & RTC_IRQMASK) { |
913 | unsigned char mask; | ||
800 | 914 | ||
801 | if (cmos->enabled_wake) { | 915 | if (cmos->enabled_wake) { |
802 | if (cmos->wake_off) | 916 | if (cmos->wake_off) |
@@ -807,18 +921,28 @@ static int cmos_resume(struct device *dev) | |||
807 | } | 921 | } |
808 | 922 | ||
809 | spin_lock_irq(&rtc_lock); | 923 | spin_lock_irq(&rtc_lock); |
810 | CMOS_WRITE(tmp, RTC_CONTROL); | 924 | do { |
811 | tmp = CMOS_READ(RTC_INTR_FLAGS); | 925 | CMOS_WRITE(tmp, RTC_CONTROL); |
812 | tmp &= (cmos->suspend_ctrl & RTC_IRQMASK) | RTC_IRQF; | 926 | hpet_set_rtc_irq_bit(tmp & RTC_IRQMASK); |
813 | if (is_intr(tmp)) | 927 | |
814 | rtc_update_irq(cmos->rtc, 1, tmp); | 928 | mask = CMOS_READ(RTC_INTR_FLAGS); |
929 | mask &= (tmp & RTC_IRQMASK) | RTC_IRQF; | ||
930 | if (!is_hpet_enabled() || !is_intr(mask)) | ||
931 | break; | ||
932 | |||
933 | /* force one-shot behavior if HPET blocked | ||
934 | * the wake alarm's irq | ||
935 | */ | ||
936 | rtc_update_irq(cmos->rtc, 1, mask); | ||
937 | tmp &= ~RTC_AIE; | ||
938 | hpet_mask_rtc_irq_bit(RTC_AIE); | ||
939 | } while (mask & RTC_AIE); | ||
815 | spin_unlock_irq(&rtc_lock); | 940 | spin_unlock_irq(&rtc_lock); |
816 | } | 941 | } |
817 | 942 | ||
818 | pr_debug("%s: resume, ctrl %02x\n", | 943 | pr_debug("%s: resume, ctrl %02x\n", |
819 | cmos_rtc.rtc->dev.bus_id, | 944 | cmos_rtc.rtc->dev.bus_id, |
820 | cmos->suspend_ctrl); | 945 | tmp); |
821 | |||
822 | 946 | ||
823 | return 0; | 947 | return 0; |
824 | } | 948 | } |
@@ -826,6 +950,12 @@ static int cmos_resume(struct device *dev) | |||
826 | #else | 950 | #else |
827 | #define cmos_suspend NULL | 951 | #define cmos_suspend NULL |
828 | #define cmos_resume NULL | 952 | #define cmos_resume NULL |
953 | |||
954 | static inline int cmos_poweroff(struct device *dev) | ||
955 | { | ||
956 | return -ENOSYS; | ||
957 | } | ||
958 | |||
829 | #endif | 959 | #endif |
830 | 960 | ||
831 | /*----------------------------------------------------------------*/ | 961 | /*----------------------------------------------------------------*/ |
@@ -838,6 +968,92 @@ static int cmos_resume(struct device *dev) | |||
838 | * predate even PNPBIOS should set up platform_bus devices. | 968 | * predate even PNPBIOS should set up platform_bus devices. |
839 | */ | 969 | */ |
840 | 970 | ||
971 | #ifdef CONFIG_ACPI | ||
972 | |||
973 | #include <linux/acpi.h> | ||
974 | |||
975 | #ifdef CONFIG_PM | ||
976 | static u32 rtc_handler(void *context) | ||
977 | { | ||
978 | acpi_clear_event(ACPI_EVENT_RTC); | ||
979 | acpi_disable_event(ACPI_EVENT_RTC, 0); | ||
980 | return ACPI_INTERRUPT_HANDLED; | ||
981 | } | ||
982 | |||
983 | static inline void rtc_wake_setup(void) | ||
984 | { | ||
985 | acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); | ||
986 | /* | ||
987 | * After the RTC handler is installed, the Fixed_RTC event should | ||
988 | * be disabled. Only when the RTC alarm is set will it be enabled. | ||
989 | */ | ||
990 | acpi_clear_event(ACPI_EVENT_RTC); | ||
991 | acpi_disable_event(ACPI_EVENT_RTC, 0); | ||
992 | } | ||
993 | |||
994 | static void rtc_wake_on(struct device *dev) | ||
995 | { | ||
996 | acpi_clear_event(ACPI_EVENT_RTC); | ||
997 | acpi_enable_event(ACPI_EVENT_RTC, 0); | ||
998 | } | ||
999 | |||
1000 | static void rtc_wake_off(struct device *dev) | ||
1001 | { | ||
1002 | acpi_disable_event(ACPI_EVENT_RTC, 0); | ||
1003 | } | ||
1004 | #else | ||
1005 | #define rtc_wake_setup() do{}while(0) | ||
1006 | #define rtc_wake_on NULL | ||
1007 | #define rtc_wake_off NULL | ||
1008 | #endif | ||
1009 | |||
1010 | /* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find | ||
1011 | * its device node and pass extra config data. This helps its driver use | ||
1012 | * capabilities that the now-obsolete mc146818 didn't have, and informs it | ||
1013 | * that this board's RTC is wakeup-capable (per ACPI spec). | ||
1014 | */ | ||
1015 | static struct cmos_rtc_board_info acpi_rtc_info; | ||
1016 | |||
1017 | static void __devinit | ||
1018 | cmos_wake_setup(struct device *dev) | ||
1019 | { | ||
1020 | if (acpi_disabled) | ||
1021 | return; | ||
1022 | |||
1023 | rtc_wake_setup(); | ||
1024 | acpi_rtc_info.wake_on = rtc_wake_on; | ||
1025 | acpi_rtc_info.wake_off = rtc_wake_off; | ||
1026 | |||
1027 | /* workaround bug in some ACPI tables */ | ||
1028 | if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) { | ||
1029 | dev_dbg(dev, "bogus FADT month_alarm (%d)\n", | ||
1030 | acpi_gbl_FADT.month_alarm); | ||
1031 | acpi_gbl_FADT.month_alarm = 0; | ||
1032 | } | ||
1033 | |||
1034 | acpi_rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm; | ||
1035 | acpi_rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm; | ||
1036 | acpi_rtc_info.rtc_century = acpi_gbl_FADT.century; | ||
1037 | |||
1038 | /* NOTE: S4_RTC_WAKE is NOT currently useful to Linux */ | ||
1039 | if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE) | ||
1040 | dev_info(dev, "RTC can wake from S4\n"); | ||
1041 | |||
1042 | dev->platform_data = &acpi_rtc_info; | ||
1043 | |||
1044 | /* RTC always wakes from S1/S2/S3, and often S4/STD */ | ||
1045 | device_init_wakeup(dev, 1); | ||
1046 | } | ||
1047 | |||
1048 | #else | ||
1049 | |||
1050 | static void __devinit | ||
1051 | cmos_wake_setup(struct device *dev) | ||
1052 | { | ||
1053 | } | ||
1054 | |||
1055 | #endif | ||
1056 | |||
841 | #ifdef CONFIG_PNP | 1057 | #ifdef CONFIG_PNP |
842 | 1058 | ||
843 | #include <linux/pnp.h> | 1059 | #include <linux/pnp.h> |
@@ -845,10 +1061,8 @@ static int cmos_resume(struct device *dev) | |||
845 | static int __devinit | 1061 | static int __devinit |
846 | cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) | 1062 | cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) |
847 | { | 1063 | { |
848 | /* REVISIT paranoia argues for a shutdown notifier, since PNP | 1064 | cmos_wake_setup(&pnp->dev); |
849 | * drivers can't provide shutdown() methods to disable IRQs. | 1065 | |
850 | * Or better yet, fix PNP to allow those methods... | ||
851 | */ | ||
852 | if (pnp_port_start(pnp,0) == 0x70 && !pnp_irq_valid(pnp,0)) | 1066 | if (pnp_port_start(pnp,0) == 0x70 && !pnp_irq_valid(pnp,0)) |
853 | /* Some machines contain a PNP entry for the RTC, but | 1067 | /* Some machines contain a PNP entry for the RTC, but |
854 | * don't define the IRQ. It should always be safe to | 1068 | * don't define the IRQ. It should always be safe to |
@@ -884,6 +1098,13 @@ static int cmos_pnp_resume(struct pnp_dev *pnp) | |||
884 | #define cmos_pnp_resume NULL | 1098 | #define cmos_pnp_resume NULL |
885 | #endif | 1099 | #endif |
886 | 1100 | ||
1101 | static void cmos_pnp_shutdown(struct device *pdev) | ||
1102 | { | ||
1103 | if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(pdev)) | ||
1104 | return; | ||
1105 | |||
1106 | cmos_do_shutdown(); | ||
1107 | } | ||
887 | 1108 | ||
888 | static const struct pnp_device_id rtc_ids[] = { | 1109 | static const struct pnp_device_id rtc_ids[] = { |
889 | { .id = "PNP0b00", }, | 1110 | { .id = "PNP0b00", }, |
@@ -903,6 +1124,10 @@ static struct pnp_driver cmos_pnp_driver = { | |||
903 | .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, | 1124 | .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, |
904 | .suspend = cmos_pnp_suspend, | 1125 | .suspend = cmos_pnp_suspend, |
905 | .resume = cmos_pnp_resume, | 1126 | .resume = cmos_pnp_resume, |
1127 | .driver = { | ||
1128 | .name = (char *)driver_name, | ||
1129 | .shutdown = cmos_pnp_shutdown, | ||
1130 | } | ||
906 | }; | 1131 | }; |
907 | 1132 | ||
908 | #endif /* CONFIG_PNP */ | 1133 | #endif /* CONFIG_PNP */ |
@@ -915,6 +1140,7 @@ static struct pnp_driver cmos_pnp_driver = { | |||
915 | 1140 | ||
916 | static int __init cmos_platform_probe(struct platform_device *pdev) | 1141 | static int __init cmos_platform_probe(struct platform_device *pdev) |
917 | { | 1142 | { |
1143 | cmos_wake_setup(&pdev->dev); | ||
918 | return cmos_do_probe(&pdev->dev, | 1144 | return cmos_do_probe(&pdev->dev, |
919 | platform_get_resource(pdev, IORESOURCE_IO, 0), | 1145 | platform_get_resource(pdev, IORESOURCE_IO, 0), |
920 | platform_get_irq(pdev, 0)); | 1146 | platform_get_irq(pdev, 0)); |
@@ -928,6 +1154,9 @@ static int __exit cmos_platform_remove(struct platform_device *pdev) | |||
928 | 1154 | ||
929 | static void cmos_platform_shutdown(struct platform_device *pdev) | 1155 | static void cmos_platform_shutdown(struct platform_device *pdev) |
930 | { | 1156 | { |
1157 | if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pdev->dev)) | ||
1158 | return; | ||
1159 | |||
931 | cmos_do_shutdown(); | 1160 | cmos_do_shutdown(); |
932 | } | 1161 | } |
933 | 1162 | ||
@@ -946,29 +1175,32 @@ static struct platform_driver cmos_platform_driver = { | |||
946 | 1175 | ||
947 | static int __init cmos_init(void) | 1176 | static int __init cmos_init(void) |
948 | { | 1177 | { |
1178 | int retval = 0; | ||
1179 | |||
949 | #ifdef CONFIG_PNP | 1180 | #ifdef CONFIG_PNP |
950 | if (pnp_platform_devices) | 1181 | pnp_register_driver(&cmos_pnp_driver); |
951 | return pnp_register_driver(&cmos_pnp_driver); | 1182 | #endif |
952 | else | 1183 | |
953 | return platform_driver_probe(&cmos_platform_driver, | 1184 | if (!cmos_rtc.dev) |
954 | cmos_platform_probe); | 1185 | retval = platform_driver_probe(&cmos_platform_driver, |
955 | #else | 1186 | cmos_platform_probe); |
956 | return platform_driver_probe(&cmos_platform_driver, | 1187 | |
957 | cmos_platform_probe); | 1188 | if (retval == 0) |
958 | #endif /* CONFIG_PNP */ | 1189 | return 0; |
1190 | |||
1191 | #ifdef CONFIG_PNP | ||
1192 | pnp_unregister_driver(&cmos_pnp_driver); | ||
1193 | #endif | ||
1194 | return retval; | ||
959 | } | 1195 | } |
960 | module_init(cmos_init); | 1196 | module_init(cmos_init); |
961 | 1197 | ||
962 | static void __exit cmos_exit(void) | 1198 | static void __exit cmos_exit(void) |
963 | { | 1199 | { |
964 | #ifdef CONFIG_PNP | 1200 | #ifdef CONFIG_PNP |
965 | if (pnp_platform_devices) | 1201 | pnp_unregister_driver(&cmos_pnp_driver); |
966 | pnp_unregister_driver(&cmos_pnp_driver); | 1202 | #endif |
967 | else | ||
968 | platform_driver_unregister(&cmos_platform_driver); | ||
969 | #else | ||
970 | platform_driver_unregister(&cmos_platform_driver); | 1203 | platform_driver_unregister(&cmos_platform_driver); |
971 | #endif /* CONFIG_PNP */ | ||
972 | } | 1204 | } |
973 | module_exit(cmos_exit); | 1205 | module_exit(cmos_exit); |
974 | 1206 | ||
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 0114a78b7cbb..079e9ed907e0 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/rtc.h> | 15 | #include <linux/rtc.h> |
16 | #include <linux/smp_lock.h> | ||
17 | #include "rtc-core.h" | 16 | #include "rtc-core.h" |
18 | 17 | ||
19 | static dev_t rtc_devt; | 18 | static dev_t rtc_devt; |
@@ -27,11 +26,8 @@ static int rtc_dev_open(struct inode *inode, struct file *file) | |||
27 | struct rtc_device, char_dev); | 26 | struct rtc_device, char_dev); |
28 | const struct rtc_class_ops *ops = rtc->ops; | 27 | const struct rtc_class_ops *ops = rtc->ops; |
29 | 28 | ||
30 | lock_kernel(); | 29 | if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags)) |
31 | if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags)) { | 30 | return -EBUSY; |
32 | err = -EBUSY; | ||
33 | goto out; | ||
34 | } | ||
35 | 31 | ||
36 | file->private_data = rtc; | 32 | file->private_data = rtc; |
37 | 33 | ||
@@ -41,13 +37,11 @@ static int rtc_dev_open(struct inode *inode, struct file *file) | |||
41 | rtc->irq_data = 0; | 37 | rtc->irq_data = 0; |
42 | spin_unlock_irq(&rtc->irq_lock); | 38 | spin_unlock_irq(&rtc->irq_lock); |
43 | 39 | ||
44 | goto out; | 40 | return 0; |
45 | } | 41 | } |
46 | 42 | ||
47 | /* something has gone wrong */ | 43 | /* something has gone wrong */ |
48 | clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); | 44 | clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); |
49 | out: | ||
50 | unlock_kernel(); | ||
51 | return err; | 45 | return err; |
52 | } | 46 | } |
53 | 47 | ||
@@ -209,7 +203,7 @@ static unsigned int rtc_dev_poll(struct file *file, poll_table *wait) | |||
209 | return (data != 0) ? (POLLIN | POLLRDNORM) : 0; | 203 | return (data != 0) ? (POLLIN | POLLRDNORM) : 0; |
210 | } | 204 | } |
211 | 205 | ||
212 | static int rtc_dev_ioctl(struct inode *inode, struct file *file, | 206 | static long rtc_dev_ioctl(struct file *file, |
213 | unsigned int cmd, unsigned long arg) | 207 | unsigned int cmd, unsigned long arg) |
214 | { | 208 | { |
215 | int err = 0; | 209 | int err = 0; |
@@ -219,6 +213,10 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
219 | struct rtc_wkalrm alarm; | 213 | struct rtc_wkalrm alarm; |
220 | void __user *uarg = (void __user *) arg; | 214 | void __user *uarg = (void __user *) arg; |
221 | 215 | ||
216 | err = mutex_lock_interruptible(&rtc->ops_lock); | ||
217 | if (err) | ||
218 | return err; | ||
219 | |||
222 | /* check that the calling task has appropriate permissions | 220 | /* check that the calling task has appropriate permissions |
223 | * for certain ioctls. doing this check here is useful | 221 | * for certain ioctls. doing this check here is useful |
224 | * to avoid duplicate code in each driver. | 222 | * to avoid duplicate code in each driver. |
@@ -227,26 +225,31 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
227 | case RTC_EPOCH_SET: | 225 | case RTC_EPOCH_SET: |
228 | case RTC_SET_TIME: | 226 | case RTC_SET_TIME: |
229 | if (!capable(CAP_SYS_TIME)) | 227 | if (!capable(CAP_SYS_TIME)) |
230 | return -EACCES; | 228 | err = -EACCES; |
231 | break; | 229 | break; |
232 | 230 | ||
233 | case RTC_IRQP_SET: | 231 | case RTC_IRQP_SET: |
234 | if (arg > rtc->max_user_freq && !capable(CAP_SYS_RESOURCE)) | 232 | if (arg > rtc->max_user_freq && !capable(CAP_SYS_RESOURCE)) |
235 | return -EACCES; | 233 | err = -EACCES; |
236 | break; | 234 | break; |
237 | 235 | ||
238 | case RTC_PIE_ON: | 236 | case RTC_PIE_ON: |
239 | if (rtc->irq_freq > rtc->max_user_freq && | 237 | if (rtc->irq_freq > rtc->max_user_freq && |
240 | !capable(CAP_SYS_RESOURCE)) | 238 | !capable(CAP_SYS_RESOURCE)) |
241 | return -EACCES; | 239 | err = -EACCES; |
242 | break; | 240 | break; |
243 | } | 241 | } |
244 | 242 | ||
243 | if (err) | ||
244 | goto done; | ||
245 | |||
245 | /* try the driver's ioctl interface */ | 246 | /* try the driver's ioctl interface */ |
246 | if (ops->ioctl) { | 247 | if (ops->ioctl) { |
247 | err = ops->ioctl(rtc->dev.parent, cmd, arg); | 248 | err = ops->ioctl(rtc->dev.parent, cmd, arg); |
248 | if (err != -ENOIOCTLCMD) | 249 | if (err != -ENOIOCTLCMD) { |
250 | mutex_unlock(&rtc->ops_lock); | ||
249 | return err; | 251 | return err; |
252 | } | ||
250 | } | 253 | } |
251 | 254 | ||
252 | /* if the driver does not provide the ioctl interface | 255 | /* if the driver does not provide the ioctl interface |
@@ -265,15 +268,19 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
265 | 268 | ||
266 | switch (cmd) { | 269 | switch (cmd) { |
267 | case RTC_ALM_READ: | 270 | case RTC_ALM_READ: |
271 | mutex_unlock(&rtc->ops_lock); | ||
272 | |||
268 | err = rtc_read_alarm(rtc, &alarm); | 273 | err = rtc_read_alarm(rtc, &alarm); |
269 | if (err < 0) | 274 | if (err < 0) |
270 | return err; | 275 | return err; |
271 | 276 | ||
272 | if (copy_to_user(uarg, &alarm.time, sizeof(tm))) | 277 | if (copy_to_user(uarg, &alarm.time, sizeof(tm))) |
273 | return -EFAULT; | 278 | err = -EFAULT; |
274 | break; | 279 | return err; |
275 | 280 | ||
276 | case RTC_ALM_SET: | 281 | case RTC_ALM_SET: |
282 | mutex_unlock(&rtc->ops_lock); | ||
283 | |||
277 | if (copy_from_user(&alarm.time, uarg, sizeof(tm))) | 284 | if (copy_from_user(&alarm.time, uarg, sizeof(tm))) |
278 | return -EFAULT; | 285 | return -EFAULT; |
279 | 286 | ||
@@ -321,24 +328,26 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
321 | } | 328 | } |
322 | } | 329 | } |
323 | 330 | ||
324 | err = rtc_set_alarm(rtc, &alarm); | 331 | return rtc_set_alarm(rtc, &alarm); |
325 | break; | ||
326 | 332 | ||
327 | case RTC_RD_TIME: | 333 | case RTC_RD_TIME: |
334 | mutex_unlock(&rtc->ops_lock); | ||
335 | |||
328 | err = rtc_read_time(rtc, &tm); | 336 | err = rtc_read_time(rtc, &tm); |
329 | if (err < 0) | 337 | if (err < 0) |
330 | return err; | 338 | return err; |
331 | 339 | ||
332 | if (copy_to_user(uarg, &tm, sizeof(tm))) | 340 | if (copy_to_user(uarg, &tm, sizeof(tm))) |
333 | return -EFAULT; | 341 | err = -EFAULT; |
334 | break; | 342 | return err; |
335 | 343 | ||
336 | case RTC_SET_TIME: | 344 | case RTC_SET_TIME: |
345 | mutex_unlock(&rtc->ops_lock); | ||
346 | |||
337 | if (copy_from_user(&tm, uarg, sizeof(tm))) | 347 | if (copy_from_user(&tm, uarg, sizeof(tm))) |
338 | return -EFAULT; | 348 | return -EFAULT; |
339 | 349 | ||
340 | err = rtc_set_time(rtc, &tm); | 350 | return rtc_set_time(rtc, &tm); |
341 | break; | ||
342 | 351 | ||
343 | case RTC_PIE_ON: | 352 | case RTC_PIE_ON: |
344 | err = rtc_irq_set_state(rtc, NULL, 1); | 353 | err = rtc_irq_set_state(rtc, NULL, 1); |
@@ -376,63 +385,80 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
376 | break; | 385 | break; |
377 | #endif | 386 | #endif |
378 | case RTC_WKALM_SET: | 387 | case RTC_WKALM_SET: |
388 | mutex_unlock(&rtc->ops_lock); | ||
379 | if (copy_from_user(&alarm, uarg, sizeof(alarm))) | 389 | if (copy_from_user(&alarm, uarg, sizeof(alarm))) |
380 | return -EFAULT; | 390 | return -EFAULT; |
381 | 391 | ||
382 | err = rtc_set_alarm(rtc, &alarm); | 392 | return rtc_set_alarm(rtc, &alarm); |
383 | break; | ||
384 | 393 | ||
385 | case RTC_WKALM_RD: | 394 | case RTC_WKALM_RD: |
395 | mutex_unlock(&rtc->ops_lock); | ||
386 | err = rtc_read_alarm(rtc, &alarm); | 396 | err = rtc_read_alarm(rtc, &alarm); |
387 | if (err < 0) | 397 | if (err < 0) |
388 | return err; | 398 | return err; |
389 | 399 | ||
390 | if (copy_to_user(uarg, &alarm, sizeof(alarm))) | 400 | if (copy_to_user(uarg, &alarm, sizeof(alarm))) |
391 | return -EFAULT; | 401 | err = -EFAULT; |
392 | break; | 402 | return err; |
393 | 403 | ||
394 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | 404 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL |
395 | case RTC_UIE_OFF: | 405 | case RTC_UIE_OFF: |
406 | mutex_unlock(&rtc->ops_lock); | ||
396 | clear_uie(rtc); | 407 | clear_uie(rtc); |
397 | return 0; | 408 | return 0; |
398 | 409 | ||
399 | case RTC_UIE_ON: | 410 | case RTC_UIE_ON: |
400 | return set_uie(rtc); | 411 | mutex_unlock(&rtc->ops_lock); |
412 | err = set_uie(rtc); | ||
413 | return err; | ||
401 | #endif | 414 | #endif |
402 | default: | 415 | default: |
403 | err = -ENOTTY; | 416 | err = -ENOTTY; |
404 | break; | 417 | break; |
405 | } | 418 | } |
406 | 419 | ||
420 | done: | ||
421 | mutex_unlock(&rtc->ops_lock); | ||
407 | return err; | 422 | return err; |
408 | } | 423 | } |
409 | 424 | ||
425 | static int rtc_dev_fasync(int fd, struct file *file, int on) | ||
426 | { | ||
427 | struct rtc_device *rtc = file->private_data; | ||
428 | return fasync_helper(fd, file, on, &rtc->async_queue); | ||
429 | } | ||
430 | |||
410 | static int rtc_dev_release(struct inode *inode, struct file *file) | 431 | static int rtc_dev_release(struct inode *inode, struct file *file) |
411 | { | 432 | { |
412 | struct rtc_device *rtc = file->private_data; | 433 | struct rtc_device *rtc = file->private_data; |
413 | 434 | ||
414 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | 435 | /* We shut down the repeating IRQs that userspace enabled, |
415 | clear_uie(rtc); | 436 | * since nothing is listening to them. |
416 | #endif | 437 | * - Update (UIE) ... currently only managed through ioctls |
438 | * - Periodic (PIE) ... also used through rtc_*() interface calls | ||
439 | * | ||
440 | * Leave the alarm alone; it may be set to trigger a system wakeup | ||
441 | * later, or be used by kernel code, and is a one-shot event anyway. | ||
442 | */ | ||
443 | rtc_dev_ioctl(file, RTC_UIE_OFF, 0); | ||
444 | rtc_irq_set_state(rtc, NULL, 0); | ||
445 | |||
417 | if (rtc->ops->release) | 446 | if (rtc->ops->release) |
418 | rtc->ops->release(rtc->dev.parent); | 447 | rtc->ops->release(rtc->dev.parent); |
419 | 448 | ||
449 | if (file->f_flags & FASYNC) | ||
450 | rtc_dev_fasync(-1, file, 0); | ||
451 | |||
420 | clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); | 452 | clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); |
421 | return 0; | 453 | return 0; |
422 | } | 454 | } |
423 | 455 | ||
424 | static int rtc_dev_fasync(int fd, struct file *file, int on) | ||
425 | { | ||
426 | struct rtc_device *rtc = file->private_data; | ||
427 | return fasync_helper(fd, file, on, &rtc->async_queue); | ||
428 | } | ||
429 | |||
430 | static const struct file_operations rtc_dev_fops = { | 456 | static const struct file_operations rtc_dev_fops = { |
431 | .owner = THIS_MODULE, | 457 | .owner = THIS_MODULE, |
432 | .llseek = no_llseek, | 458 | .llseek = no_llseek, |
433 | .read = rtc_dev_read, | 459 | .read = rtc_dev_read, |
434 | .poll = rtc_dev_poll, | 460 | .poll = rtc_dev_poll, |
435 | .ioctl = rtc_dev_ioctl, | 461 | .unlocked_ioctl = rtc_dev_ioctl, |
436 | .open = rtc_dev_open, | 462 | .open = rtc_dev_open, |
437 | .release = rtc_dev_release, | 463 | .release = rtc_dev_release, |
438 | .fasync = rtc_dev_fasync, | 464 | .fasync = rtc_dev_fasync, |
diff --git a/drivers/rtc/rtc-ds1216.c b/drivers/rtc/rtc-ds1216.c index 0b17770b032b..9a234a4ec06d 100644 --- a/drivers/rtc/rtc-ds1216.c +++ b/drivers/rtc/rtc-ds1216.c | |||
@@ -86,19 +86,19 @@ static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
86 | ds1216_switch_ds_to_clock(priv->ioaddr); | 86 | ds1216_switch_ds_to_clock(priv->ioaddr); |
87 | ds1216_read(priv->ioaddr, (u8 *)®s); | 87 | ds1216_read(priv->ioaddr, (u8 *)®s); |
88 | 88 | ||
89 | tm->tm_sec = BCD2BIN(regs.sec); | 89 | tm->tm_sec = bcd2bin(regs.sec); |
90 | tm->tm_min = BCD2BIN(regs.min); | 90 | tm->tm_min = bcd2bin(regs.min); |
91 | if (regs.hour & DS1216_HOUR_1224) { | 91 | if (regs.hour & DS1216_HOUR_1224) { |
92 | /* AM/PM mode */ | 92 | /* AM/PM mode */ |
93 | tm->tm_hour = BCD2BIN(regs.hour & 0x1f); | 93 | tm->tm_hour = bcd2bin(regs.hour & 0x1f); |
94 | if (regs.hour & DS1216_HOUR_AMPM) | 94 | if (regs.hour & DS1216_HOUR_AMPM) |
95 | tm->tm_hour += 12; | 95 | tm->tm_hour += 12; |
96 | } else | 96 | } else |
97 | tm->tm_hour = BCD2BIN(regs.hour & 0x3f); | 97 | tm->tm_hour = bcd2bin(regs.hour & 0x3f); |
98 | tm->tm_wday = (regs.wday & 7) - 1; | 98 | tm->tm_wday = (regs.wday & 7) - 1; |
99 | tm->tm_mday = BCD2BIN(regs.mday & 0x3f); | 99 | tm->tm_mday = bcd2bin(regs.mday & 0x3f); |
100 | tm->tm_mon = BCD2BIN(regs.month & 0x1f); | 100 | tm->tm_mon = bcd2bin(regs.month & 0x1f); |
101 | tm->tm_year = BCD2BIN(regs.year); | 101 | tm->tm_year = bcd2bin(regs.year); |
102 | if (tm->tm_year < 70) | 102 | if (tm->tm_year < 70) |
103 | tm->tm_year += 100; | 103 | tm->tm_year += 100; |
104 | return 0; | 104 | return 0; |
@@ -114,19 +114,19 @@ static int ds1216_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
114 | ds1216_read(priv->ioaddr, (u8 *)®s); | 114 | ds1216_read(priv->ioaddr, (u8 *)®s); |
115 | 115 | ||
116 | regs.tsec = 0; /* clear 0.1 and 0.01 seconds */ | 116 | regs.tsec = 0; /* clear 0.1 and 0.01 seconds */ |
117 | regs.sec = BIN2BCD(tm->tm_sec); | 117 | regs.sec = bin2bcd(tm->tm_sec); |
118 | regs.min = BIN2BCD(tm->tm_min); | 118 | regs.min = bin2bcd(tm->tm_min); |
119 | regs.hour &= DS1216_HOUR_1224; | 119 | regs.hour &= DS1216_HOUR_1224; |
120 | if (regs.hour && tm->tm_hour > 12) { | 120 | if (regs.hour && tm->tm_hour > 12) { |
121 | regs.hour |= DS1216_HOUR_AMPM; | 121 | regs.hour |= DS1216_HOUR_AMPM; |
122 | tm->tm_hour -= 12; | 122 | tm->tm_hour -= 12; |
123 | } | 123 | } |
124 | regs.hour |= BIN2BCD(tm->tm_hour); | 124 | regs.hour |= bin2bcd(tm->tm_hour); |
125 | regs.wday &= ~7; | 125 | regs.wday &= ~7; |
126 | regs.wday |= tm->tm_wday; | 126 | regs.wday |= tm->tm_wday; |
127 | regs.mday = BIN2BCD(tm->tm_mday); | 127 | regs.mday = bin2bcd(tm->tm_mday); |
128 | regs.month = BIN2BCD(tm->tm_mon); | 128 | regs.month = bin2bcd(tm->tm_mon); |
129 | regs.year = BIN2BCD(tm->tm_year % 100); | 129 | regs.year = bin2bcd(tm->tm_year % 100); |
130 | 130 | ||
131 | ds1216_switch_ds_to_clock(priv->ioaddr); | 131 | ds1216_switch_ds_to_clock(priv->ioaddr); |
132 | ds1216_write(priv->ioaddr, (u8 *)®s); | 132 | ds1216_write(priv->ioaddr, (u8 *)®s); |
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c new file mode 100644 index 000000000000..4fcb16bbff4a --- /dev/null +++ b/drivers/rtc/rtc-ds1286.c | |||
@@ -0,0 +1,410 @@ | |||
1 | /* | ||
2 | * DS1286 Real Time Clock interface for Linux | ||
3 | * | ||
4 | * Copyright (C) 1998, 1999, 2000 Ralf Baechle | ||
5 | * Copyright (C) 2008 Thomas Bogendoerfer | ||
6 | * | ||
7 | * Based on code written by Paul Gortmaker. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/rtc.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/bcd.h> | ||
19 | #include <linux/ds1286.h> | ||
20 | #include <linux/io.h> | ||
21 | |||
22 | #define DRV_VERSION "1.0" | ||
23 | |||
24 | struct ds1286_priv { | ||
25 | struct rtc_device *rtc; | ||
26 | u32 __iomem *rtcregs; | ||
27 | size_t size; | ||
28 | unsigned long baseaddr; | ||
29 | spinlock_t lock; | ||
30 | }; | ||
31 | |||
32 | static inline u8 ds1286_rtc_read(struct ds1286_priv *priv, int reg) | ||
33 | { | ||
34 | return __raw_readl(&priv->rtcregs[reg]) & 0xff; | ||
35 | } | ||
36 | |||
37 | static inline void ds1286_rtc_write(struct ds1286_priv *priv, u8 data, int reg) | ||
38 | { | ||
39 | __raw_writel(data, &priv->rtcregs[reg]); | ||
40 | } | ||
41 | |||
42 | #ifdef CONFIG_RTC_INTF_DEV | ||
43 | |||
44 | static int ds1286_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
45 | { | ||
46 | struct ds1286_priv *priv = dev_get_drvdata(dev); | ||
47 | unsigned long flags; | ||
48 | unsigned char val; | ||
49 | |||
50 | switch (cmd) { | ||
51 | case RTC_AIE_OFF: | ||
52 | /* Mask alarm int. enab. bit */ | ||
53 | spin_lock_irqsave(&priv->lock, flags); | ||
54 | val = ds1286_rtc_read(priv, RTC_CMD); | ||
55 | val |= RTC_TDM; | ||
56 | ds1286_rtc_write(priv, val, RTC_CMD); | ||
57 | spin_unlock_irqrestore(&priv->lock, flags); | ||
58 | break; | ||
59 | case RTC_AIE_ON: | ||
60 | /* Allow alarm interrupts. */ | ||
61 | spin_lock_irqsave(&priv->lock, flags); | ||
62 | val = ds1286_rtc_read(priv, RTC_CMD); | ||
63 | val &= ~RTC_TDM; | ||
64 | ds1286_rtc_write(priv, val, RTC_CMD); | ||
65 | spin_unlock_irqrestore(&priv->lock, flags); | ||
66 | break; | ||
67 | case RTC_WIE_OFF: | ||
68 | /* Mask watchdog int. enab. bit */ | ||
69 | spin_lock_irqsave(&priv->lock, flags); | ||
70 | val = ds1286_rtc_read(priv, RTC_CMD); | ||
71 | val |= RTC_WAM; | ||
72 | ds1286_rtc_write(priv, val, RTC_CMD); | ||
73 | spin_unlock_irqrestore(&priv->lock, flags); | ||
74 | break; | ||
75 | case RTC_WIE_ON: | ||
76 | /* Allow watchdog interrupts. */ | ||
77 | spin_lock_irqsave(&priv->lock, flags); | ||
78 | val = ds1286_rtc_read(priv, RTC_CMD); | ||
79 | val &= ~RTC_WAM; | ||
80 | ds1286_rtc_write(priv, val, RTC_CMD); | ||
81 | spin_unlock_irqrestore(&priv->lock, flags); | ||
82 | break; | ||
83 | default: | ||
84 | return -ENOIOCTLCMD; | ||
85 | } | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | #else | ||
90 | #define ds1286_ioctl NULL | ||
91 | #endif | ||
92 | |||
93 | #ifdef CONFIG_PROC_FS | ||
94 | |||
95 | static int ds1286_proc(struct device *dev, struct seq_file *seq) | ||
96 | { | ||
97 | struct ds1286_priv *priv = dev_get_drvdata(dev); | ||
98 | unsigned char month, cmd, amode; | ||
99 | const char *s; | ||
100 | |||
101 | month = ds1286_rtc_read(priv, RTC_MONTH); | ||
102 | seq_printf(seq, | ||
103 | "oscillator\t: %s\n" | ||
104 | "square_wave\t: %s\n", | ||
105 | (month & RTC_EOSC) ? "disabled" : "enabled", | ||
106 | (month & RTC_ESQW) ? "disabled" : "enabled"); | ||
107 | |||
108 | amode = ((ds1286_rtc_read(priv, RTC_MINUTES_ALARM) & 0x80) >> 5) | | ||
109 | ((ds1286_rtc_read(priv, RTC_HOURS_ALARM) & 0x80) >> 6) | | ||
110 | ((ds1286_rtc_read(priv, RTC_DAY_ALARM) & 0x80) >> 7); | ||
111 | switch (amode) { | ||
112 | case 7: | ||
113 | s = "each minute"; | ||
114 | break; | ||
115 | case 3: | ||
116 | s = "minutes match"; | ||
117 | break; | ||
118 | case 1: | ||
119 | s = "hours and minutes match"; | ||
120 | break; | ||
121 | case 0: | ||
122 | s = "days, hours and minutes match"; | ||
123 | break; | ||
124 | default: | ||
125 | s = "invalid"; | ||
126 | break; | ||
127 | } | ||
128 | seq_printf(seq, "alarm_mode\t: %s\n", s); | ||
129 | |||
130 | cmd = ds1286_rtc_read(priv, RTC_CMD); | ||
131 | seq_printf(seq, | ||
132 | "alarm_enable\t: %s\n" | ||
133 | "wdog_alarm\t: %s\n" | ||
134 | "alarm_mask\t: %s\n" | ||
135 | "wdog_alarm_mask\t: %s\n" | ||
136 | "interrupt_mode\t: %s\n" | ||
137 | "INTB_mode\t: %s_active\n" | ||
138 | "interrupt_pins\t: %s\n", | ||
139 | (cmd & RTC_TDF) ? "yes" : "no", | ||
140 | (cmd & RTC_WAF) ? "yes" : "no", | ||
141 | (cmd & RTC_TDM) ? "disabled" : "enabled", | ||
142 | (cmd & RTC_WAM) ? "disabled" : "enabled", | ||
143 | (cmd & RTC_PU_LVL) ? "pulse" : "level", | ||
144 | (cmd & RTC_IBH_LO) ? "low" : "high", | ||
145 | (cmd & RTC_IPSW) ? "unswapped" : "swapped"); | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | #else | ||
150 | #define ds1286_proc NULL | ||
151 | #endif | ||
152 | |||
153 | static int ds1286_read_time(struct device *dev, struct rtc_time *tm) | ||
154 | { | ||
155 | struct ds1286_priv *priv = dev_get_drvdata(dev); | ||
156 | unsigned char save_control; | ||
157 | unsigned long flags; | ||
158 | unsigned long uip_watchdog = jiffies; | ||
159 | |||
160 | /* | ||
161 | * read RTC once any update in progress is done. The update | ||
162 | * can take just over 2ms. We wait 10 to 20ms. There is no need to | ||
163 | * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP. | ||
164 | * If you need to know *exactly* when a second has started, enable | ||
165 | * periodic update complete interrupts, (via ioctl) and then | ||
166 | * immediately read /dev/rtc which will block until you get the IRQ. | ||
167 | * Once the read clears, read the RTC time (again via ioctl). Easy. | ||
168 | */ | ||
169 | |||
170 | if (ds1286_rtc_read(priv, RTC_CMD) & RTC_TE) | ||
171 | while (time_before(jiffies, uip_watchdog + 2*HZ/100)) | ||
172 | barrier(); | ||
173 | |||
174 | /* | ||
175 | * Only the values that we read from the RTC are set. We leave | ||
176 | * tm_wday, tm_yday and tm_isdst untouched. Even though the | ||
177 | * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated | ||
178 | * by the RTC when initially set to a non-zero value. | ||
179 | */ | ||
180 | spin_lock_irqsave(&priv->lock, flags); | ||
181 | save_control = ds1286_rtc_read(priv, RTC_CMD); | ||
182 | ds1286_rtc_write(priv, (save_control|RTC_TE), RTC_CMD); | ||
183 | |||
184 | tm->tm_sec = ds1286_rtc_read(priv, RTC_SECONDS); | ||
185 | tm->tm_min = ds1286_rtc_read(priv, RTC_MINUTES); | ||
186 | tm->tm_hour = ds1286_rtc_read(priv, RTC_HOURS) & 0x3f; | ||
187 | tm->tm_mday = ds1286_rtc_read(priv, RTC_DATE); | ||
188 | tm->tm_mon = ds1286_rtc_read(priv, RTC_MONTH) & 0x1f; | ||
189 | tm->tm_year = ds1286_rtc_read(priv, RTC_YEAR); | ||
190 | |||
191 | ds1286_rtc_write(priv, save_control, RTC_CMD); | ||
192 | spin_unlock_irqrestore(&priv->lock, flags); | ||
193 | |||
194 | tm->tm_sec = bcd2bin(tm->tm_sec); | ||
195 | tm->tm_min = bcd2bin(tm->tm_min); | ||
196 | tm->tm_hour = bcd2bin(tm->tm_hour); | ||
197 | tm->tm_mday = bcd2bin(tm->tm_mday); | ||
198 | tm->tm_mon = bcd2bin(tm->tm_mon); | ||
199 | tm->tm_year = bcd2bin(tm->tm_year); | ||
200 | |||
201 | /* | ||
202 | * Account for differences between how the RTC uses the values | ||
203 | * and how they are defined in a struct rtc_time; | ||
204 | */ | ||
205 | if (tm->tm_year < 45) | ||
206 | tm->tm_year += 30; | ||
207 | tm->tm_year += 40; | ||
208 | if (tm->tm_year < 70) | ||
209 | tm->tm_year += 100; | ||
210 | |||
211 | tm->tm_mon--; | ||
212 | |||
213 | return rtc_valid_tm(tm); | ||
214 | } | ||
215 | |||
216 | static int ds1286_set_time(struct device *dev, struct rtc_time *tm) | ||
217 | { | ||
218 | struct ds1286_priv *priv = dev_get_drvdata(dev); | ||
219 | unsigned char mon, day, hrs, min, sec; | ||
220 | unsigned char save_control; | ||
221 | unsigned int yrs; | ||
222 | unsigned long flags; | ||
223 | |||
224 | yrs = tm->tm_year + 1900; | ||
225 | mon = tm->tm_mon + 1; /* tm_mon starts at zero */ | ||
226 | day = tm->tm_mday; | ||
227 | hrs = tm->tm_hour; | ||
228 | min = tm->tm_min; | ||
229 | sec = tm->tm_sec; | ||
230 | |||
231 | if (yrs < 1970) | ||
232 | return -EINVAL; | ||
233 | |||
234 | yrs -= 1940; | ||
235 | if (yrs > 255) /* They are unsigned */ | ||
236 | return -EINVAL; | ||
237 | |||
238 | if (yrs >= 100) | ||
239 | yrs -= 100; | ||
240 | |||
241 | sec = bin2bcd(sec); | ||
242 | min = bin2bcd(min); | ||
243 | hrs = bin2bcd(hrs); | ||
244 | day = bin2bcd(day); | ||
245 | mon = bin2bcd(mon); | ||
246 | yrs = bin2bcd(yrs); | ||
247 | |||
248 | spin_lock_irqsave(&priv->lock, flags); | ||
249 | save_control = ds1286_rtc_read(priv, RTC_CMD); | ||
250 | ds1286_rtc_write(priv, (save_control|RTC_TE), RTC_CMD); | ||
251 | |||
252 | ds1286_rtc_write(priv, yrs, RTC_YEAR); | ||
253 | ds1286_rtc_write(priv, mon, RTC_MONTH); | ||
254 | ds1286_rtc_write(priv, day, RTC_DATE); | ||
255 | ds1286_rtc_write(priv, hrs, RTC_HOURS); | ||
256 | ds1286_rtc_write(priv, min, RTC_MINUTES); | ||
257 | ds1286_rtc_write(priv, sec, RTC_SECONDS); | ||
258 | ds1286_rtc_write(priv, 0, RTC_HUNDREDTH_SECOND); | ||
259 | |||
260 | ds1286_rtc_write(priv, save_control, RTC_CMD); | ||
261 | spin_unlock_irqrestore(&priv->lock, flags); | ||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static int ds1286_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
266 | { | ||
267 | struct ds1286_priv *priv = dev_get_drvdata(dev); | ||
268 | unsigned char cmd; | ||
269 | unsigned long flags; | ||
270 | |||
271 | /* | ||
272 | * Only the values that we read from the RTC are set. That | ||
273 | * means only tm_wday, tm_hour, tm_min. | ||
274 | */ | ||
275 | spin_lock_irqsave(&priv->lock, flags); | ||
276 | alm->time.tm_min = ds1286_rtc_read(priv, RTC_MINUTES_ALARM) & 0x7f; | ||
277 | alm->time.tm_hour = ds1286_rtc_read(priv, RTC_HOURS_ALARM) & 0x1f; | ||
278 | alm->time.tm_wday = ds1286_rtc_read(priv, RTC_DAY_ALARM) & 0x07; | ||
279 | cmd = ds1286_rtc_read(priv, RTC_CMD); | ||
280 | spin_unlock_irqrestore(&priv->lock, flags); | ||
281 | |||
282 | alm->time.tm_min = bcd2bin(alm->time.tm_min); | ||
283 | alm->time.tm_hour = bcd2bin(alm->time.tm_hour); | ||
284 | alm->time.tm_sec = 0; | ||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static int ds1286_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
289 | { | ||
290 | struct ds1286_priv *priv = dev_get_drvdata(dev); | ||
291 | unsigned char hrs, min, sec; | ||
292 | |||
293 | hrs = alm->time.tm_hour; | ||
294 | min = alm->time.tm_min; | ||
295 | sec = alm->time.tm_sec; | ||
296 | |||
297 | if (hrs >= 24) | ||
298 | hrs = 0xff; | ||
299 | |||
300 | if (min >= 60) | ||
301 | min = 0xff; | ||
302 | |||
303 | if (sec != 0) | ||
304 | return -EINVAL; | ||
305 | |||
306 | min = bin2bcd(min); | ||
307 | hrs = bin2bcd(hrs); | ||
308 | |||
309 | spin_lock(&priv->lock); | ||
310 | ds1286_rtc_write(priv, hrs, RTC_HOURS_ALARM); | ||
311 | ds1286_rtc_write(priv, min, RTC_MINUTES_ALARM); | ||
312 | spin_unlock(&priv->lock); | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static const struct rtc_class_ops ds1286_ops = { | ||
318 | .ioctl = ds1286_ioctl, | ||
319 | .proc = ds1286_proc, | ||
320 | .read_time = ds1286_read_time, | ||
321 | .set_time = ds1286_set_time, | ||
322 | .read_alarm = ds1286_read_alarm, | ||
323 | .set_alarm = ds1286_set_alarm, | ||
324 | }; | ||
325 | |||
326 | static int __devinit ds1286_probe(struct platform_device *pdev) | ||
327 | { | ||
328 | struct rtc_device *rtc; | ||
329 | struct resource *res; | ||
330 | struct ds1286_priv *priv; | ||
331 | int ret = 0; | ||
332 | |||
333 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
334 | if (!res) | ||
335 | return -ENODEV; | ||
336 | priv = kzalloc(sizeof(struct ds1286_priv), GFP_KERNEL); | ||
337 | if (!priv) | ||
338 | return -ENOMEM; | ||
339 | |||
340 | priv->size = res->end - res->start + 1; | ||
341 | if (!request_mem_region(res->start, priv->size, pdev->name)) { | ||
342 | ret = -EBUSY; | ||
343 | goto out; | ||
344 | } | ||
345 | priv->baseaddr = res->start; | ||
346 | priv->rtcregs = ioremap(priv->baseaddr, priv->size); | ||
347 | if (!priv->rtcregs) { | ||
348 | ret = -ENOMEM; | ||
349 | goto out; | ||
350 | } | ||
351 | spin_lock_init(&priv->lock); | ||
352 | rtc = rtc_device_register("ds1286", &pdev->dev, | ||
353 | &ds1286_ops, THIS_MODULE); | ||
354 | if (IS_ERR(rtc)) { | ||
355 | ret = PTR_ERR(rtc); | ||
356 | goto out; | ||
357 | } | ||
358 | priv->rtc = rtc; | ||
359 | platform_set_drvdata(pdev, priv); | ||
360 | return 0; | ||
361 | |||
362 | out: | ||
363 | if (priv->rtc) | ||
364 | rtc_device_unregister(priv->rtc); | ||
365 | if (priv->rtcregs) | ||
366 | iounmap(priv->rtcregs); | ||
367 | if (priv->baseaddr) | ||
368 | release_mem_region(priv->baseaddr, priv->size); | ||
369 | kfree(priv); | ||
370 | return ret; | ||
371 | } | ||
372 | |||
373 | static int __devexit ds1286_remove(struct platform_device *pdev) | ||
374 | { | ||
375 | struct ds1286_priv *priv = platform_get_drvdata(pdev); | ||
376 | |||
377 | rtc_device_unregister(priv->rtc); | ||
378 | iounmap(priv->rtcregs); | ||
379 | release_mem_region(priv->baseaddr, priv->size); | ||
380 | kfree(priv); | ||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | static struct platform_driver ds1286_platform_driver = { | ||
385 | .driver = { | ||
386 | .name = "rtc-ds1286", | ||
387 | .owner = THIS_MODULE, | ||
388 | }, | ||
389 | .probe = ds1286_probe, | ||
390 | .remove = __devexit_p(ds1286_remove), | ||
391 | }; | ||
392 | |||
393 | static int __init ds1286_init(void) | ||
394 | { | ||
395 | return platform_driver_register(&ds1286_platform_driver); | ||
396 | } | ||
397 | |||
398 | static void __exit ds1286_exit(void) | ||
399 | { | ||
400 | platform_driver_unregister(&ds1286_platform_driver); | ||
401 | } | ||
402 | |||
403 | MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>"); | ||
404 | MODULE_DESCRIPTION("DS1286 RTC driver"); | ||
405 | MODULE_LICENSE("GPL"); | ||
406 | MODULE_VERSION(DRV_VERSION); | ||
407 | MODULE_ALIAS("platform:rtc-ds1286"); | ||
408 | |||
409 | module_init(ds1286_init); | ||
410 | module_exit(ds1286_exit); | ||
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c index b9397818f73a..184556620778 100644 --- a/drivers/rtc/rtc-ds1302.c +++ b/drivers/rtc/rtc-ds1302.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #define RTC_SCLK 0x0400 | 40 | #define RTC_SCLK 0x0400 |
41 | 41 | ||
42 | #ifdef CONFIG_SH_SECUREEDGE5410 | 42 | #ifdef CONFIG_SH_SECUREEDGE5410 |
43 | #include <asm/snapgear.h> | 43 | #include <mach/snapgear.h> |
44 | #define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00) | 44 | #define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00) |
45 | #define get_dp() SECUREEDGE_READ_IOPORT() | 45 | #define get_dp() SECUREEDGE_READ_IOPORT() |
46 | #else | 46 | #else |
@@ -107,13 +107,13 @@ static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
107 | 107 | ||
108 | spin_lock_irq(&rtc->lock); | 108 | spin_lock_irq(&rtc->lock); |
109 | 109 | ||
110 | tm->tm_sec = BCD2BIN(ds1302_readbyte(RTC_ADDR_SEC)); | 110 | tm->tm_sec = bcd2bin(ds1302_readbyte(RTC_ADDR_SEC)); |
111 | tm->tm_min = BCD2BIN(ds1302_readbyte(RTC_ADDR_MIN)); | 111 | tm->tm_min = bcd2bin(ds1302_readbyte(RTC_ADDR_MIN)); |
112 | tm->tm_hour = BCD2BIN(ds1302_readbyte(RTC_ADDR_HOUR)); | 112 | tm->tm_hour = bcd2bin(ds1302_readbyte(RTC_ADDR_HOUR)); |
113 | tm->tm_wday = BCD2BIN(ds1302_readbyte(RTC_ADDR_DAY)); | 113 | tm->tm_wday = bcd2bin(ds1302_readbyte(RTC_ADDR_DAY)); |
114 | tm->tm_mday = BCD2BIN(ds1302_readbyte(RTC_ADDR_DATE)); | 114 | tm->tm_mday = bcd2bin(ds1302_readbyte(RTC_ADDR_DATE)); |
115 | tm->tm_mon = BCD2BIN(ds1302_readbyte(RTC_ADDR_MON)) - 1; | 115 | tm->tm_mon = bcd2bin(ds1302_readbyte(RTC_ADDR_MON)) - 1; |
116 | tm->tm_year = BCD2BIN(ds1302_readbyte(RTC_ADDR_YEAR)); | 116 | tm->tm_year = bcd2bin(ds1302_readbyte(RTC_ADDR_YEAR)); |
117 | 117 | ||
118 | if (tm->tm_year < 70) | 118 | if (tm->tm_year < 70) |
119 | tm->tm_year += 100; | 119 | tm->tm_year += 100; |
@@ -141,13 +141,13 @@ static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
141 | /* Stop RTC */ | 141 | /* Stop RTC */ |
142 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80); | 142 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80); |
143 | 143 | ||
144 | ds1302_writebyte(RTC_ADDR_SEC, BIN2BCD(tm->tm_sec)); | 144 | ds1302_writebyte(RTC_ADDR_SEC, bin2bcd(tm->tm_sec)); |
145 | ds1302_writebyte(RTC_ADDR_MIN, BIN2BCD(tm->tm_min)); | 145 | ds1302_writebyte(RTC_ADDR_MIN, bin2bcd(tm->tm_min)); |
146 | ds1302_writebyte(RTC_ADDR_HOUR, BIN2BCD(tm->tm_hour)); | 146 | ds1302_writebyte(RTC_ADDR_HOUR, bin2bcd(tm->tm_hour)); |
147 | ds1302_writebyte(RTC_ADDR_DAY, BIN2BCD(tm->tm_wday)); | 147 | ds1302_writebyte(RTC_ADDR_DAY, bin2bcd(tm->tm_wday)); |
148 | ds1302_writebyte(RTC_ADDR_DATE, BIN2BCD(tm->tm_mday)); | 148 | ds1302_writebyte(RTC_ADDR_DATE, bin2bcd(tm->tm_mday)); |
149 | ds1302_writebyte(RTC_ADDR_MON, BIN2BCD(tm->tm_mon + 1)); | 149 | ds1302_writebyte(RTC_ADDR_MON, bin2bcd(tm->tm_mon + 1)); |
150 | ds1302_writebyte(RTC_ADDR_YEAR, BIN2BCD(tm->tm_year % 100)); | 150 | ds1302_writebyte(RTC_ADDR_YEAR, bin2bcd(tm->tm_year % 100)); |
151 | 151 | ||
152 | /* Start RTC */ | 152 | /* Start RTC */ |
153 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80); | 153 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80); |
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c new file mode 100644 index 000000000000..fc372df6534b --- /dev/null +++ b/drivers/rtc/rtc-ds1305.c | |||
@@ -0,0 +1,846 @@ | |||
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 | .read = ds1305_nvram_read, | ||
610 | .write = ds1305_nvram_write, | ||
611 | .size = DS1305_NVRAM_LEN, | ||
612 | }; | ||
613 | |||
614 | /*----------------------------------------------------------------------*/ | ||
615 | |||
616 | /* | ||
617 | * Interface to SPI stack | ||
618 | */ | ||
619 | |||
620 | static int __devinit ds1305_probe(struct spi_device *spi) | ||
621 | { | ||
622 | struct ds1305 *ds1305; | ||
623 | struct rtc_device *rtc; | ||
624 | int status; | ||
625 | u8 addr, value; | ||
626 | struct ds1305_platform_data *pdata = spi->dev.platform_data; | ||
627 | bool write_ctrl = false; | ||
628 | |||
629 | /* Sanity check board setup data. This may be hooked up | ||
630 | * in 3wire mode, but we don't care. Note that unless | ||
631 | * there's an inverter in place, this needs SPI_CS_HIGH! | ||
632 | */ | ||
633 | if ((spi->bits_per_word && spi->bits_per_word != 8) | ||
634 | || (spi->max_speed_hz > 2000000) | ||
635 | || !(spi->mode & SPI_CPHA)) | ||
636 | return -EINVAL; | ||
637 | |||
638 | /* set up driver data */ | ||
639 | ds1305 = kzalloc(sizeof *ds1305, GFP_KERNEL); | ||
640 | if (!ds1305) | ||
641 | return -ENOMEM; | ||
642 | ds1305->spi = spi; | ||
643 | spi_set_drvdata(spi, ds1305); | ||
644 | |||
645 | /* read and cache control registers */ | ||
646 | addr = DS1305_CONTROL; | ||
647 | status = spi_write_then_read(spi, &addr, sizeof addr, | ||
648 | ds1305->ctrl, sizeof ds1305->ctrl); | ||
649 | if (status < 0) { | ||
650 | dev_dbg(&spi->dev, "can't %s, %d\n", | ||
651 | "read", status); | ||
652 | goto fail0; | ||
653 | } | ||
654 | |||
655 | dev_dbg(&spi->dev, "ctrl %s: %02x %02x %02x\n", | ||
656 | "read", ds1305->ctrl[0], | ||
657 | ds1305->ctrl[1], ds1305->ctrl[2]); | ||
658 | |||
659 | /* Sanity check register values ... partially compensating for the | ||
660 | * fact that SPI has no device handshake. A pullup on MISO would | ||
661 | * make these tests fail; but not all systems will have one. If | ||
662 | * some register is neither 0x00 nor 0xff, a chip is likely there. | ||
663 | */ | ||
664 | if ((ds1305->ctrl[0] & 0x38) != 0 || (ds1305->ctrl[1] & 0xfc) != 0) { | ||
665 | dev_dbg(&spi->dev, "RTC chip is not present\n"); | ||
666 | status = -ENODEV; | ||
667 | goto fail0; | ||
668 | } | ||
669 | if (ds1305->ctrl[2] == 0) | ||
670 | dev_dbg(&spi->dev, "chip may not be present\n"); | ||
671 | |||
672 | /* enable writes if needed ... if we were paranoid it would | ||
673 | * make sense to enable them only when absolutely necessary. | ||
674 | */ | ||
675 | if (ds1305->ctrl[0] & DS1305_WP) { | ||
676 | u8 buf[2]; | ||
677 | |||
678 | ds1305->ctrl[0] &= ~DS1305_WP; | ||
679 | |||
680 | buf[0] = DS1305_WRITE | DS1305_CONTROL; | ||
681 | buf[1] = ds1305->ctrl[0]; | ||
682 | status = spi_write_then_read(spi, buf, sizeof buf, NULL, 0); | ||
683 | |||
684 | dev_dbg(&spi->dev, "clear WP --> %d\n", status); | ||
685 | if (status < 0) | ||
686 | goto fail0; | ||
687 | } | ||
688 | |||
689 | /* on DS1305, maybe start oscillator; like most low power | ||
690 | * oscillators, it may take a second to stabilize | ||
691 | */ | ||
692 | if (ds1305->ctrl[0] & DS1305_nEOSC) { | ||
693 | ds1305->ctrl[0] &= ~DS1305_nEOSC; | ||
694 | write_ctrl = true; | ||
695 | dev_warn(&spi->dev, "SET TIME!\n"); | ||
696 | } | ||
697 | |||
698 | /* ack any pending IRQs */ | ||
699 | if (ds1305->ctrl[1]) { | ||
700 | ds1305->ctrl[1] = 0; | ||
701 | write_ctrl = true; | ||
702 | } | ||
703 | |||
704 | /* this may need one-time (re)init */ | ||
705 | if (pdata) { | ||
706 | /* maybe enable trickle charge */ | ||
707 | if (((ds1305->ctrl[2] & 0xf0) != DS1305_TRICKLE_MAGIC)) { | ||
708 | ds1305->ctrl[2] = DS1305_TRICKLE_MAGIC | ||
709 | | pdata->trickle; | ||
710 | write_ctrl = true; | ||
711 | } | ||
712 | |||
713 | /* on DS1306, configure 1 Hz signal */ | ||
714 | if (pdata->is_ds1306) { | ||
715 | if (pdata->en_1hz) { | ||
716 | if (!(ds1305->ctrl[0] & DS1306_1HZ)) { | ||
717 | ds1305->ctrl[0] |= DS1306_1HZ; | ||
718 | write_ctrl = true; | ||
719 | } | ||
720 | } else { | ||
721 | if (ds1305->ctrl[0] & DS1306_1HZ) { | ||
722 | ds1305->ctrl[0] &= ~DS1306_1HZ; | ||
723 | write_ctrl = true; | ||
724 | } | ||
725 | } | ||
726 | } | ||
727 | } | ||
728 | |||
729 | if (write_ctrl) { | ||
730 | u8 buf[4]; | ||
731 | |||
732 | buf[0] = DS1305_WRITE | DS1305_CONTROL; | ||
733 | buf[1] = ds1305->ctrl[0]; | ||
734 | buf[2] = ds1305->ctrl[1]; | ||
735 | buf[3] = ds1305->ctrl[2]; | ||
736 | status = spi_write_then_read(spi, buf, sizeof buf, NULL, 0); | ||
737 | if (status < 0) { | ||
738 | dev_dbg(&spi->dev, "can't %s, %d\n", | ||
739 | "write", status); | ||
740 | goto fail0; | ||
741 | } | ||
742 | |||
743 | dev_dbg(&spi->dev, "ctrl %s: %02x %02x %02x\n", | ||
744 | "write", ds1305->ctrl[0], | ||
745 | ds1305->ctrl[1], ds1305->ctrl[2]); | ||
746 | } | ||
747 | |||
748 | /* see if non-Linux software set up AM/PM mode */ | ||
749 | addr = DS1305_HOUR; | ||
750 | status = spi_write_then_read(spi, &addr, sizeof addr, | ||
751 | &value, sizeof value); | ||
752 | if (status < 0) { | ||
753 | dev_dbg(&spi->dev, "read HOUR --> %d\n", status); | ||
754 | goto fail0; | ||
755 | } | ||
756 | |||
757 | ds1305->hr12 = (DS1305_HR_12 & value) != 0; | ||
758 | if (ds1305->hr12) | ||
759 | dev_dbg(&spi->dev, "AM/PM\n"); | ||
760 | |||
761 | /* register RTC ... from here on, ds1305->ctrl needs locking */ | ||
762 | rtc = rtc_device_register("ds1305", &spi->dev, | ||
763 | &ds1305_ops, THIS_MODULE); | ||
764 | if (IS_ERR(rtc)) { | ||
765 | status = PTR_ERR(rtc); | ||
766 | dev_dbg(&spi->dev, "register rtc --> %d\n", status); | ||
767 | goto fail0; | ||
768 | } | ||
769 | ds1305->rtc = rtc; | ||
770 | |||
771 | /* Maybe set up alarm IRQ; be ready to handle it triggering right | ||
772 | * away. NOTE that we don't share this. The signal is active low, | ||
773 | * and we can't ack it before a SPI message delay. We temporarily | ||
774 | * disable the IRQ until it's acked, which lets us work with more | ||
775 | * IRQ trigger modes (not all IRQ controllers can do falling edge). | ||
776 | */ | ||
777 | if (spi->irq) { | ||
778 | INIT_WORK(&ds1305->work, ds1305_work); | ||
779 | status = request_irq(spi->irq, ds1305_irq, | ||
780 | 0, dev_name(&rtc->dev), ds1305); | ||
781 | if (status < 0) { | ||
782 | dev_dbg(&spi->dev, "request_irq %d --> %d\n", | ||
783 | spi->irq, status); | ||
784 | goto fail1; | ||
785 | } | ||
786 | } | ||
787 | |||
788 | /* export NVRAM */ | ||
789 | status = sysfs_create_bin_file(&spi->dev.kobj, &nvram); | ||
790 | if (status < 0) { | ||
791 | dev_dbg(&spi->dev, "register nvram --> %d\n", status); | ||
792 | goto fail2; | ||
793 | } | ||
794 | |||
795 | return 0; | ||
796 | |||
797 | fail2: | ||
798 | free_irq(spi->irq, ds1305); | ||
799 | fail1: | ||
800 | rtc_device_unregister(rtc); | ||
801 | fail0: | ||
802 | kfree(ds1305); | ||
803 | return status; | ||
804 | } | ||
805 | |||
806 | static int __devexit ds1305_remove(struct spi_device *spi) | ||
807 | { | ||
808 | struct ds1305 *ds1305 = spi_get_drvdata(spi); | ||
809 | |||
810 | sysfs_remove_bin_file(&spi->dev.kobj, &nvram); | ||
811 | |||
812 | /* carefully shut down irq and workqueue, if present */ | ||
813 | if (spi->irq) { | ||
814 | set_bit(FLAG_EXITING, &ds1305->flags); | ||
815 | free_irq(spi->irq, ds1305); | ||
816 | flush_scheduled_work(); | ||
817 | } | ||
818 | |||
819 | rtc_device_unregister(ds1305->rtc); | ||
820 | spi_set_drvdata(spi, NULL); | ||
821 | kfree(ds1305); | ||
822 | return 0; | ||
823 | } | ||
824 | |||
825 | static struct spi_driver ds1305_driver = { | ||
826 | .driver.name = "rtc-ds1305", | ||
827 | .driver.owner = THIS_MODULE, | ||
828 | .probe = ds1305_probe, | ||
829 | .remove = __devexit_p(ds1305_remove), | ||
830 | /* REVISIT add suspend/resume */ | ||
831 | }; | ||
832 | |||
833 | static int __init ds1305_init(void) | ||
834 | { | ||
835 | return spi_register_driver(&ds1305_driver); | ||
836 | } | ||
837 | module_init(ds1305_init); | ||
838 | |||
839 | static void __exit ds1305_exit(void) | ||
840 | { | ||
841 | spi_unregister_driver(&ds1305_driver); | ||
842 | } | ||
843 | module_exit(ds1305_exit); | ||
844 | |||
845 | MODULE_DESCRIPTION("RTC driver for DS1305 and DS1306 chips"); | ||
846 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index bbf97e65202a..162330b9d1dc 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
@@ -23,10 +23,6 @@ | |||
23 | * to have set the chip up as a clock (turning on the oscillator and | 23 | * to have set the chip up as a clock (turning on the oscillator and |
24 | * setting the date and time), Linux can ignore the non-clock features. | 24 | * setting the date and time), Linux can ignore the non-clock features. |
25 | * That's a natural job for a factory or repair bench. | 25 | * That's a natural job for a factory or repair bench. |
26 | * | ||
27 | * This is currently a simple no-alarms driver. If your board has the | ||
28 | * alarm irq wired up on a ds1337 or ds1339, and you want to use that, | ||
29 | * then look at the rtc-rs5c372 driver for code to steal... | ||
30 | */ | 26 | */ |
31 | enum ds_type { | 27 | enum ds_type { |
32 | ds_1307, | 28 | ds_1307, |
@@ -67,6 +63,7 @@ enum ds_type { | |||
67 | # define DS1307_BIT_RS0 0x01 | 63 | # define DS1307_BIT_RS0 0x01 |
68 | #define DS1337_REG_CONTROL 0x0e | 64 | #define DS1337_REG_CONTROL 0x0e |
69 | # define DS1337_BIT_nEOSC 0x80 | 65 | # define DS1337_BIT_nEOSC 0x80 |
66 | # define DS1339_BIT_BBSQI 0x20 | ||
70 | # define DS1337_BIT_RS2 0x10 | 67 | # define DS1337_BIT_RS2 0x10 |
71 | # define DS1337_BIT_RS1 0x08 | 68 | # define DS1337_BIT_RS1 0x08 |
72 | # define DS1337_BIT_INTCN 0x04 | 69 | # define DS1337_BIT_INTCN 0x04 |
@@ -83,19 +80,22 @@ enum ds_type { | |||
83 | # define DS1337_BIT_OSF 0x80 | 80 | # define DS1337_BIT_OSF 0x80 |
84 | # define DS1337_BIT_A2I 0x02 | 81 | # define DS1337_BIT_A2I 0x02 |
85 | # define DS1337_BIT_A1I 0x01 | 82 | # define DS1337_BIT_A1I 0x01 |
83 | #define DS1339_REG_ALARM1_SECS 0x07 | ||
86 | #define DS1339_REG_TRICKLE 0x10 | 84 | #define DS1339_REG_TRICKLE 0x10 |
87 | 85 | ||
88 | 86 | ||
89 | 87 | ||
90 | struct ds1307 { | 88 | struct ds1307 { |
91 | u8 reg_addr; | 89 | u8 reg_addr; |
92 | bool has_nvram; | 90 | u8 regs[11]; |
93 | u8 regs[8]; | ||
94 | enum ds_type type; | 91 | enum ds_type type; |
92 | unsigned long flags; | ||
93 | #define HAS_NVRAM 0 /* bit 0 == sysfs file active */ | ||
94 | #define HAS_ALARM 1 /* bit 1 == irq claimed */ | ||
95 | struct i2c_msg msg[2]; | 95 | struct i2c_msg msg[2]; |
96 | struct i2c_client *client; | 96 | struct i2c_client *client; |
97 | struct i2c_client dev; | ||
98 | struct rtc_device *rtc; | 97 | struct rtc_device *rtc; |
98 | struct work_struct work; | ||
99 | }; | 99 | }; |
100 | 100 | ||
101 | struct chip_desc { | 101 | struct chip_desc { |
@@ -132,12 +132,79 @@ static const struct i2c_device_id ds1307_id[] = { | |||
132 | }; | 132 | }; |
133 | MODULE_DEVICE_TABLE(i2c, ds1307_id); | 133 | MODULE_DEVICE_TABLE(i2c, ds1307_id); |
134 | 134 | ||
135 | /*----------------------------------------------------------------------*/ | ||
136 | |||
137 | /* | ||
138 | * The IRQ logic includes a "real" handler running in IRQ context just | ||
139 | * long enough to schedule this workqueue entry. We need a task context | ||
140 | * to talk to the RTC, since I2C I/O calls require that; and disable the | ||
141 | * IRQ until we clear its status on the chip, so that this handler can | ||
142 | * work with any type of triggering (not just falling edge). | ||
143 | * | ||
144 | * The ds1337 and ds1339 both have two alarms, but we only use the first | ||
145 | * one (with a "seconds" field). For ds1337 we expect nINTA is our alarm | ||
146 | * signal; ds1339 chips have only one alarm signal. | ||
147 | */ | ||
148 | static void ds1307_work(struct work_struct *work) | ||
149 | { | ||
150 | struct ds1307 *ds1307; | ||
151 | struct i2c_client *client; | ||
152 | struct mutex *lock; | ||
153 | int stat, control; | ||
154 | |||
155 | ds1307 = container_of(work, struct ds1307, work); | ||
156 | client = ds1307->client; | ||
157 | lock = &ds1307->rtc->ops_lock; | ||
158 | |||
159 | mutex_lock(lock); | ||
160 | stat = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS); | ||
161 | if (stat < 0) | ||
162 | goto out; | ||
163 | |||
164 | if (stat & DS1337_BIT_A1I) { | ||
165 | stat &= ~DS1337_BIT_A1I; | ||
166 | i2c_smbus_write_byte_data(client, DS1337_REG_STATUS, stat); | ||
167 | |||
168 | control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); | ||
169 | if (control < 0) | ||
170 | goto out; | ||
171 | |||
172 | control &= ~DS1337_BIT_A1IE; | ||
173 | i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, control); | ||
174 | |||
175 | /* rtc_update_irq() assumes that it is called | ||
176 | * from IRQ-disabled context. | ||
177 | */ | ||
178 | local_irq_disable(); | ||
179 | rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF); | ||
180 | local_irq_enable(); | ||
181 | } | ||
182 | |||
183 | out: | ||
184 | if (test_bit(HAS_ALARM, &ds1307->flags)) | ||
185 | enable_irq(client->irq); | ||
186 | mutex_unlock(lock); | ||
187 | } | ||
188 | |||
189 | static irqreturn_t ds1307_irq(int irq, void *dev_id) | ||
190 | { | ||
191 | struct i2c_client *client = dev_id; | ||
192 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | ||
193 | |||
194 | disable_irq_nosync(irq); | ||
195 | schedule_work(&ds1307->work); | ||
196 | return IRQ_HANDLED; | ||
197 | } | ||
198 | |||
199 | /*----------------------------------------------------------------------*/ | ||
200 | |||
135 | static int ds1307_get_time(struct device *dev, struct rtc_time *t) | 201 | static int ds1307_get_time(struct device *dev, struct rtc_time *t) |
136 | { | 202 | { |
137 | struct ds1307 *ds1307 = dev_get_drvdata(dev); | 203 | struct ds1307 *ds1307 = dev_get_drvdata(dev); |
138 | int tmp; | 204 | int tmp; |
139 | 205 | ||
140 | /* read the RTC date and time registers all at once */ | 206 | /* read the RTC date and time registers all at once */ |
207 | ds1307->reg_addr = 0; | ||
141 | ds1307->msg[1].flags = I2C_M_RD; | 208 | ds1307->msg[1].flags = I2C_M_RD; |
142 | ds1307->msg[1].len = 7; | 209 | ds1307->msg[1].len = 7; |
143 | 210 | ||
@@ -155,17 +222,17 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t) | |||
155 | ds1307->regs[4], ds1307->regs[5], | 222 | ds1307->regs[4], ds1307->regs[5], |
156 | ds1307->regs[6]); | 223 | ds1307->regs[6]); |
157 | 224 | ||
158 | t->tm_sec = BCD2BIN(ds1307->regs[DS1307_REG_SECS] & 0x7f); | 225 | t->tm_sec = bcd2bin(ds1307->regs[DS1307_REG_SECS] & 0x7f); |
159 | t->tm_min = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f); | 226 | t->tm_min = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f); |
160 | tmp = ds1307->regs[DS1307_REG_HOUR] & 0x3f; | 227 | tmp = ds1307->regs[DS1307_REG_HOUR] & 0x3f; |
161 | t->tm_hour = BCD2BIN(tmp); | 228 | t->tm_hour = bcd2bin(tmp); |
162 | t->tm_wday = BCD2BIN(ds1307->regs[DS1307_REG_WDAY] & 0x07) - 1; | 229 | t->tm_wday = bcd2bin(ds1307->regs[DS1307_REG_WDAY] & 0x07) - 1; |
163 | t->tm_mday = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f); | 230 | t->tm_mday = bcd2bin(ds1307->regs[DS1307_REG_MDAY] & 0x3f); |
164 | tmp = ds1307->regs[DS1307_REG_MONTH] & 0x1f; | 231 | tmp = ds1307->regs[DS1307_REG_MONTH] & 0x1f; |
165 | t->tm_mon = BCD2BIN(tmp) - 1; | 232 | t->tm_mon = bcd2bin(tmp) - 1; |
166 | 233 | ||
167 | /* assume 20YY not 19YY, and ignore DS1337_BIT_CENTURY */ | 234 | /* assume 20YY not 19YY, and ignore DS1337_BIT_CENTURY */ |
168 | t->tm_year = BCD2BIN(ds1307->regs[DS1307_REG_YEAR]) + 100; | 235 | t->tm_year = bcd2bin(ds1307->regs[DS1307_REG_YEAR]) + 100; |
169 | 236 | ||
170 | dev_dbg(dev, "%s secs=%d, mins=%d, " | 237 | dev_dbg(dev, "%s secs=%d, mins=%d, " |
171 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", | 238 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", |
@@ -191,16 +258,16 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) | |||
191 | t->tm_mon, t->tm_year, t->tm_wday); | 258 | t->tm_mon, t->tm_year, t->tm_wday); |
192 | 259 | ||
193 | *buf++ = 0; /* first register addr */ | 260 | *buf++ = 0; /* first register addr */ |
194 | buf[DS1307_REG_SECS] = BIN2BCD(t->tm_sec); | 261 | buf[DS1307_REG_SECS] = bin2bcd(t->tm_sec); |
195 | buf[DS1307_REG_MIN] = BIN2BCD(t->tm_min); | 262 | buf[DS1307_REG_MIN] = bin2bcd(t->tm_min); |
196 | buf[DS1307_REG_HOUR] = BIN2BCD(t->tm_hour); | 263 | buf[DS1307_REG_HOUR] = bin2bcd(t->tm_hour); |
197 | buf[DS1307_REG_WDAY] = BIN2BCD(t->tm_wday + 1); | 264 | buf[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1); |
198 | buf[DS1307_REG_MDAY] = BIN2BCD(t->tm_mday); | 265 | buf[DS1307_REG_MDAY] = bin2bcd(t->tm_mday); |
199 | buf[DS1307_REG_MONTH] = BIN2BCD(t->tm_mon + 1); | 266 | buf[DS1307_REG_MONTH] = bin2bcd(t->tm_mon + 1); |
200 | 267 | ||
201 | /* assume 20YY not 19YY */ | 268 | /* assume 20YY not 19YY */ |
202 | tmp = t->tm_year - 100; | 269 | tmp = t->tm_year - 100; |
203 | buf[DS1307_REG_YEAR] = BIN2BCD(tmp); | 270 | buf[DS1307_REG_YEAR] = bin2bcd(tmp); |
204 | 271 | ||
205 | switch (ds1307->type) { | 272 | switch (ds1307->type) { |
206 | case ds_1337: | 273 | case ds_1337: |
@@ -231,9 +298,186 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) | |||
231 | return 0; | 298 | return 0; |
232 | } | 299 | } |
233 | 300 | ||
301 | static int ds1307_read_alarm(struct device *dev, struct rtc_wkalrm *t) | ||
302 | { | ||
303 | struct i2c_client *client = to_i2c_client(dev); | ||
304 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | ||
305 | int ret; | ||
306 | |||
307 | if (!test_bit(HAS_ALARM, &ds1307->flags)) | ||
308 | return -EINVAL; | ||
309 | |||
310 | /* read all ALARM1, ALARM2, and status registers at once */ | ||
311 | ds1307->reg_addr = DS1339_REG_ALARM1_SECS; | ||
312 | ds1307->msg[1].flags = I2C_M_RD; | ||
313 | ds1307->msg[1].len = 9; | ||
314 | |||
315 | ret = i2c_transfer(to_i2c_adapter(client->dev.parent), | ||
316 | ds1307->msg, 2); | ||
317 | if (ret != 2) { | ||
318 | dev_err(dev, "%s error %d\n", "alarm read", ret); | ||
319 | return -EIO; | ||
320 | } | ||
321 | |||
322 | dev_dbg(dev, "%s: %02x %02x %02x %02x, %02x %02x %02x, %02x %02x\n", | ||
323 | "alarm read", | ||
324 | ds1307->regs[0], ds1307->regs[1], | ||
325 | ds1307->regs[2], ds1307->regs[3], | ||
326 | ds1307->regs[4], ds1307->regs[5], | ||
327 | ds1307->regs[6], ds1307->regs[7], | ||
328 | ds1307->regs[8]); | ||
329 | |||
330 | /* report alarm time (ALARM1); assume 24 hour and day-of-month modes, | ||
331 | * and that all four fields are checked matches | ||
332 | */ | ||
333 | t->time.tm_sec = bcd2bin(ds1307->regs[0] & 0x7f); | ||
334 | t->time.tm_min = bcd2bin(ds1307->regs[1] & 0x7f); | ||
335 | t->time.tm_hour = bcd2bin(ds1307->regs[2] & 0x3f); | ||
336 | t->time.tm_mday = bcd2bin(ds1307->regs[3] & 0x3f); | ||
337 | t->time.tm_mon = -1; | ||
338 | t->time.tm_year = -1; | ||
339 | t->time.tm_wday = -1; | ||
340 | t->time.tm_yday = -1; | ||
341 | t->time.tm_isdst = -1; | ||
342 | |||
343 | /* ... and status */ | ||
344 | t->enabled = !!(ds1307->regs[7] & DS1337_BIT_A1IE); | ||
345 | t->pending = !!(ds1307->regs[8] & DS1337_BIT_A1I); | ||
346 | |||
347 | dev_dbg(dev, "%s secs=%d, mins=%d, " | ||
348 | "hours=%d, mday=%d, enabled=%d, pending=%d\n", | ||
349 | "alarm read", t->time.tm_sec, t->time.tm_min, | ||
350 | t->time.tm_hour, t->time.tm_mday, | ||
351 | t->enabled, t->pending); | ||
352 | |||
353 | return 0; | ||
354 | } | ||
355 | |||
356 | static int ds1307_set_alarm(struct device *dev, struct rtc_wkalrm *t) | ||
357 | { | ||
358 | struct i2c_client *client = to_i2c_client(dev); | ||
359 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | ||
360 | unsigned char *buf = ds1307->regs; | ||
361 | u8 control, status; | ||
362 | int ret; | ||
363 | |||
364 | if (!test_bit(HAS_ALARM, &ds1307->flags)) | ||
365 | return -EINVAL; | ||
366 | |||
367 | dev_dbg(dev, "%s secs=%d, mins=%d, " | ||
368 | "hours=%d, mday=%d, enabled=%d, pending=%d\n", | ||
369 | "alarm set", t->time.tm_sec, t->time.tm_min, | ||
370 | t->time.tm_hour, t->time.tm_mday, | ||
371 | t->enabled, t->pending); | ||
372 | |||
373 | /* read current status of both alarms and the chip */ | ||
374 | ds1307->reg_addr = DS1339_REG_ALARM1_SECS; | ||
375 | ds1307->msg[1].flags = I2C_M_RD; | ||
376 | ds1307->msg[1].len = 9; | ||
377 | |||
378 | ret = i2c_transfer(to_i2c_adapter(client->dev.parent), | ||
379 | ds1307->msg, 2); | ||
380 | if (ret != 2) { | ||
381 | dev_err(dev, "%s error %d\n", "alarm write", ret); | ||
382 | return -EIO; | ||
383 | } | ||
384 | control = ds1307->regs[7]; | ||
385 | status = ds1307->regs[8]; | ||
386 | |||
387 | dev_dbg(dev, "%s: %02x %02x %02x %02x, %02x %02x %02x, %02x %02x\n", | ||
388 | "alarm set (old status)", | ||
389 | ds1307->regs[0], ds1307->regs[1], | ||
390 | ds1307->regs[2], ds1307->regs[3], | ||
391 | ds1307->regs[4], ds1307->regs[5], | ||
392 | ds1307->regs[6], control, status); | ||
393 | |||
394 | /* set ALARM1, using 24 hour and day-of-month modes */ | ||
395 | *buf++ = DS1339_REG_ALARM1_SECS; /* first register addr */ | ||
396 | buf[0] = bin2bcd(t->time.tm_sec); | ||
397 | buf[1] = bin2bcd(t->time.tm_min); | ||
398 | buf[2] = bin2bcd(t->time.tm_hour); | ||
399 | buf[3] = bin2bcd(t->time.tm_mday); | ||
400 | |||
401 | /* set ALARM2 to non-garbage */ | ||
402 | buf[4] = 0; | ||
403 | buf[5] = 0; | ||
404 | buf[6] = 0; | ||
405 | |||
406 | /* optionally enable ALARM1 */ | ||
407 | buf[7] = control & ~(DS1337_BIT_A1IE | DS1337_BIT_A2IE); | ||
408 | if (t->enabled) { | ||
409 | dev_dbg(dev, "alarm IRQ armed\n"); | ||
410 | buf[7] |= DS1337_BIT_A1IE; /* only ALARM1 is used */ | ||
411 | } | ||
412 | buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I); | ||
413 | |||
414 | ds1307->msg[1].flags = 0; | ||
415 | ds1307->msg[1].len = 10; | ||
416 | |||
417 | ret = i2c_transfer(to_i2c_adapter(client->dev.parent), | ||
418 | &ds1307->msg[1], 1); | ||
419 | if (ret != 1) { | ||
420 | dev_err(dev, "can't set alarm time\n"); | ||
421 | return -EIO; | ||
422 | } | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static int ds1307_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
428 | { | ||
429 | struct i2c_client *client = to_i2c_client(dev); | ||
430 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | ||
431 | int ret; | ||
432 | |||
433 | switch (cmd) { | ||
434 | case RTC_AIE_OFF: | ||
435 | if (!test_bit(HAS_ALARM, &ds1307->flags)) | ||
436 | return -ENOTTY; | ||
437 | |||
438 | ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); | ||
439 | if (ret < 0) | ||
440 | return ret; | ||
441 | |||
442 | ret &= ~DS1337_BIT_A1IE; | ||
443 | |||
444 | ret = i2c_smbus_write_byte_data(client, | ||
445 | DS1337_REG_CONTROL, ret); | ||
446 | if (ret < 0) | ||
447 | return ret; | ||
448 | |||
449 | break; | ||
450 | |||
451 | case RTC_AIE_ON: | ||
452 | if (!test_bit(HAS_ALARM, &ds1307->flags)) | ||
453 | return -ENOTTY; | ||
454 | |||
455 | ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); | ||
456 | if (ret < 0) | ||
457 | return ret; | ||
458 | |||
459 | ret |= DS1337_BIT_A1IE; | ||
460 | |||
461 | ret = i2c_smbus_write_byte_data(client, | ||
462 | DS1337_REG_CONTROL, ret); | ||
463 | if (ret < 0) | ||
464 | return ret; | ||
465 | |||
466 | break; | ||
467 | |||
468 | default: | ||
469 | return -ENOIOCTLCMD; | ||
470 | } | ||
471 | |||
472 | return 0; | ||
473 | } | ||
474 | |||
234 | static const struct rtc_class_ops ds13xx_rtc_ops = { | 475 | static const struct rtc_class_ops ds13xx_rtc_ops = { |
235 | .read_time = ds1307_get_time, | 476 | .read_time = ds1307_get_time, |
236 | .set_time = ds1307_set_time, | 477 | .set_time = ds1307_set_time, |
478 | .read_alarm = ds1307_read_alarm, | ||
479 | .set_alarm = ds1307_set_alarm, | ||
480 | .ioctl = ds1307_ioctl, | ||
237 | }; | 481 | }; |
238 | 482 | ||
239 | /*----------------------------------------------------------------------*/ | 483 | /*----------------------------------------------------------------------*/ |
@@ -307,7 +551,6 @@ static struct bin_attribute nvram = { | |||
307 | .attr = { | 551 | .attr = { |
308 | .name = "nvram", | 552 | .name = "nvram", |
309 | .mode = S_IRUGO | S_IWUSR, | 553 | .mode = S_IRUGO | S_IWUSR, |
310 | .owner = THIS_MODULE, | ||
311 | }, | 554 | }, |
312 | 555 | ||
313 | .read = ds1307_nvram_read, | 556 | .read = ds1307_nvram_read, |
@@ -327,6 +570,7 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
327 | int tmp; | 570 | int tmp; |
328 | const struct chip_desc *chip = &chips[id->driver_data]; | 571 | const struct chip_desc *chip = &chips[id->driver_data]; |
329 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 572 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
573 | int want_irq = false; | ||
330 | 574 | ||
331 | if (!i2c_check_functionality(adapter, | 575 | if (!i2c_check_functionality(adapter, |
332 | I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) | 576 | I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) |
@@ -353,6 +597,12 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
353 | switch (ds1307->type) { | 597 | switch (ds1307->type) { |
354 | case ds_1337: | 598 | case ds_1337: |
355 | case ds_1339: | 599 | case ds_1339: |
600 | /* has IRQ? */ | ||
601 | if (ds1307->client->irq > 0 && chip->alarm) { | ||
602 | INIT_WORK(&ds1307->work, ds1307_work); | ||
603 | want_irq = true; | ||
604 | } | ||
605 | |||
356 | ds1307->reg_addr = DS1337_REG_CONTROL; | 606 | ds1307->reg_addr = DS1337_REG_CONTROL; |
357 | ds1307->msg[1].len = 2; | 607 | ds1307->msg[1].len = 2; |
358 | 608 | ||
@@ -369,8 +619,20 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
369 | 619 | ||
370 | /* oscillator off? turn it on, so clock can tick. */ | 620 | /* oscillator off? turn it on, so clock can tick. */ |
371 | if (ds1307->regs[0] & DS1337_BIT_nEOSC) | 621 | if (ds1307->regs[0] & DS1337_BIT_nEOSC) |
372 | i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, | 622 | ds1307->regs[0] &= ~DS1337_BIT_nEOSC; |
373 | ds1307->regs[0] & ~DS1337_BIT_nEOSC); | 623 | |
624 | /* Using IRQ? Disable the square wave and both alarms. | ||
625 | * For ds1339, be sure alarms can trigger when we're | ||
626 | * running on Vbackup (BBSQI); we assume ds1337 will | ||
627 | * ignore that bit | ||
628 | */ | ||
629 | if (want_irq) { | ||
630 | ds1307->regs[0] |= DS1337_BIT_INTCN | DS1339_BIT_BBSQI; | ||
631 | ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE); | ||
632 | } | ||
633 | |||
634 | i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, | ||
635 | ds1307->regs[0]); | ||
374 | 636 | ||
375 | /* oscillator fault? clear flag, and warn */ | 637 | /* oscillator fault? clear flag, and warn */ |
376 | if (ds1307->regs[1] & DS1337_BIT_OSF) { | 638 | if (ds1307->regs[1] & DS1337_BIT_OSF) { |
@@ -446,18 +708,18 @@ read_rtc: | |||
446 | } | 708 | } |
447 | 709 | ||
448 | tmp = ds1307->regs[DS1307_REG_SECS]; | 710 | tmp = ds1307->regs[DS1307_REG_SECS]; |
449 | tmp = BCD2BIN(tmp & 0x7f); | 711 | tmp = bcd2bin(tmp & 0x7f); |
450 | if (tmp > 60) | 712 | if (tmp > 60) |
451 | goto exit_bad; | 713 | goto exit_bad; |
452 | tmp = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f); | 714 | tmp = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f); |
453 | if (tmp > 60) | 715 | if (tmp > 60) |
454 | goto exit_bad; | 716 | goto exit_bad; |
455 | 717 | ||
456 | tmp = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f); | 718 | tmp = bcd2bin(ds1307->regs[DS1307_REG_MDAY] & 0x3f); |
457 | if (tmp == 0 || tmp > 31) | 719 | if (tmp == 0 || tmp > 31) |
458 | goto exit_bad; | 720 | goto exit_bad; |
459 | 721 | ||
460 | tmp = BCD2BIN(ds1307->regs[DS1307_REG_MONTH] & 0x1f); | 722 | tmp = bcd2bin(ds1307->regs[DS1307_REG_MONTH] & 0x1f); |
461 | if (tmp == 0 || tmp > 12) | 723 | if (tmp == 0 || tmp > 12) |
462 | goto exit_bad; | 724 | goto exit_bad; |
463 | 725 | ||
@@ -476,14 +738,14 @@ read_rtc: | |||
476 | /* Be sure we're in 24 hour mode. Multi-master systems | 738 | /* Be sure we're in 24 hour mode. Multi-master systems |
477 | * take note... | 739 | * take note... |
478 | */ | 740 | */ |
479 | tmp = BCD2BIN(tmp & 0x1f); | 741 | tmp = bcd2bin(tmp & 0x1f); |
480 | if (tmp == 12) | 742 | if (tmp == 12) |
481 | tmp = 0; | 743 | tmp = 0; |
482 | if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM) | 744 | if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM) |
483 | tmp += 12; | 745 | tmp += 12; |
484 | i2c_smbus_write_byte_data(client, | 746 | i2c_smbus_write_byte_data(client, |
485 | DS1307_REG_HOUR, | 747 | DS1307_REG_HOUR, |
486 | BIN2BCD(tmp)); | 748 | bin2bcd(tmp)); |
487 | } | 749 | } |
488 | 750 | ||
489 | ds1307->rtc = rtc_device_register(client->name, &client->dev, | 751 | ds1307->rtc = rtc_device_register(client->name, &client->dev, |
@@ -495,10 +757,22 @@ read_rtc: | |||
495 | goto exit_free; | 757 | goto exit_free; |
496 | } | 758 | } |
497 | 759 | ||
760 | if (want_irq) { | ||
761 | err = request_irq(client->irq, ds1307_irq, 0, | ||
762 | ds1307->rtc->name, client); | ||
763 | if (err) { | ||
764 | dev_err(&client->dev, | ||
765 | "unable to request IRQ!\n"); | ||
766 | goto exit_irq; | ||
767 | } | ||
768 | set_bit(HAS_ALARM, &ds1307->flags); | ||
769 | dev_dbg(&client->dev, "got IRQ %d\n", client->irq); | ||
770 | } | ||
771 | |||
498 | if (chip->nvram56) { | 772 | if (chip->nvram56) { |
499 | err = sysfs_create_bin_file(&client->dev.kobj, &nvram); | 773 | err = sysfs_create_bin_file(&client->dev.kobj, &nvram); |
500 | if (err == 0) { | 774 | if (err == 0) { |
501 | ds1307->has_nvram = true; | 775 | set_bit(HAS_NVRAM, &ds1307->flags); |
502 | dev_info(&client->dev, "56 bytes nvram\n"); | 776 | dev_info(&client->dev, "56 bytes nvram\n"); |
503 | } | 777 | } |
504 | } | 778 | } |
@@ -512,7 +786,9 @@ exit_bad: | |||
512 | ds1307->regs[2], ds1307->regs[3], | 786 | ds1307->regs[2], ds1307->regs[3], |
513 | ds1307->regs[4], ds1307->regs[5], | 787 | ds1307->regs[4], ds1307->regs[5], |
514 | ds1307->regs[6]); | 788 | ds1307->regs[6]); |
515 | 789 | exit_irq: | |
790 | if (ds1307->rtc) | ||
791 | rtc_device_unregister(ds1307->rtc); | ||
516 | exit_free: | 792 | exit_free: |
517 | kfree(ds1307); | 793 | kfree(ds1307); |
518 | return err; | 794 | return err; |
@@ -520,9 +796,14 @@ exit_free: | |||
520 | 796 | ||
521 | static int __devexit ds1307_remove(struct i2c_client *client) | 797 | static int __devexit ds1307_remove(struct i2c_client *client) |
522 | { | 798 | { |
523 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | 799 | struct ds1307 *ds1307 = i2c_get_clientdata(client); |
800 | |||
801 | if (test_and_clear_bit(HAS_ALARM, &ds1307->flags)) { | ||
802 | free_irq(client->irq, client); | ||
803 | cancel_work_sync(&ds1307->work); | ||
804 | } | ||
524 | 805 | ||
525 | if (ds1307->has_nvram) | 806 | if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags)) |
526 | sysfs_remove_bin_file(&client->dev.kobj, &nvram); | 807 | sysfs_remove_bin_file(&client->dev.kobj, &nvram); |
527 | 808 | ||
528 | rtc_device_unregister(ds1307->rtc); | 809 | rtc_device_unregister(ds1307->rtc); |
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 640acd20fdde..a5b0fc09f0c6 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c | |||
@@ -173,7 +173,7 @@ static int ds1374_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
173 | int cr, sr; | 173 | int cr, sr; |
174 | int ret = 0; | 174 | int ret = 0; |
175 | 175 | ||
176 | if (client->irq < 0) | 176 | if (client->irq <= 0) |
177 | return -EINVAL; | 177 | return -EINVAL; |
178 | 178 | ||
179 | mutex_lock(&ds1374->mutex); | 179 | mutex_lock(&ds1374->mutex); |
@@ -212,7 +212,7 @@ static int ds1374_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
212 | int cr; | 212 | int cr; |
213 | int ret = 0; | 213 | int ret = 0; |
214 | 214 | ||
215 | if (client->irq < 0) | 215 | if (client->irq <= 0) |
216 | return -EINVAL; | 216 | return -EINVAL; |
217 | 217 | ||
218 | ret = ds1374_read_time(dev, &now); | 218 | ret = ds1374_read_time(dev, &now); |
@@ -381,7 +381,7 @@ static int ds1374_probe(struct i2c_client *client, | |||
381 | if (ret) | 381 | if (ret) |
382 | goto out_free; | 382 | goto out_free; |
383 | 383 | ||
384 | if (client->irq >= 0) { | 384 | if (client->irq > 0) { |
385 | ret = request_irq(client->irq, ds1374_irq, 0, | 385 | ret = request_irq(client->irq, ds1374_irq, 0, |
386 | "ds1374", client); | 386 | "ds1374", client); |
387 | if (ret) { | 387 | if (ret) { |
@@ -401,7 +401,7 @@ static int ds1374_probe(struct i2c_client *client, | |||
401 | return 0; | 401 | return 0; |
402 | 402 | ||
403 | out_irq: | 403 | out_irq: |
404 | if (client->irq >= 0) | 404 | if (client->irq > 0) |
405 | free_irq(client->irq, client); | 405 | free_irq(client->irq, client); |
406 | 406 | ||
407 | out_free: | 407 | out_free: |
@@ -414,7 +414,7 @@ static int __devexit ds1374_remove(struct i2c_client *client) | |||
414 | { | 414 | { |
415 | struct ds1374 *ds1374 = i2c_get_clientdata(client); | 415 | struct ds1374 *ds1374 = i2c_get_clientdata(client); |
416 | 416 | ||
417 | if (client->irq >= 0) { | 417 | if (client->irq > 0) { |
418 | mutex_lock(&ds1374->mutex); | 418 | mutex_lock(&ds1374->mutex); |
419 | ds1374->exiting = 1; | 419 | ds1374->exiting = 1; |
420 | mutex_unlock(&ds1374->mutex); | 420 | mutex_unlock(&ds1374->mutex); |
@@ -429,12 +429,33 @@ static int __devexit ds1374_remove(struct i2c_client *client) | |||
429 | return 0; | 429 | return 0; |
430 | } | 430 | } |
431 | 431 | ||
432 | #ifdef CONFIG_PM | ||
433 | static int ds1374_suspend(struct i2c_client *client, pm_message_t state) | ||
434 | { | ||
435 | if (client->irq >= 0 && device_may_wakeup(&client->dev)) | ||
436 | enable_irq_wake(client->irq); | ||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | static int ds1374_resume(struct i2c_client *client) | ||
441 | { | ||
442 | if (client->irq >= 0 && device_may_wakeup(&client->dev)) | ||
443 | disable_irq_wake(client->irq); | ||
444 | return 0; | ||
445 | } | ||
446 | #else | ||
447 | #define ds1374_suspend NULL | ||
448 | #define ds1374_resume NULL | ||
449 | #endif | ||
450 | |||
432 | static struct i2c_driver ds1374_driver = { | 451 | static struct i2c_driver ds1374_driver = { |
433 | .driver = { | 452 | .driver = { |
434 | .name = "rtc-ds1374", | 453 | .name = "rtc-ds1374", |
435 | .owner = THIS_MODULE, | 454 | .owner = THIS_MODULE, |
436 | }, | 455 | }, |
437 | .probe = ds1374_probe, | 456 | .probe = ds1374_probe, |
457 | .suspend = ds1374_suspend, | ||
458 | .resume = ds1374_resume, | ||
438 | .remove = __devexit_p(ds1374_remove), | 459 | .remove = __devexit_p(ds1374_remove), |
439 | .id_table = ds1374_id, | 460 | .id_table = ds1374_id, |
440 | }; | 461 | }; |
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 0f0d27d1c4ca..25caada78398 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c | |||
@@ -153,8 +153,8 @@ ds1511_wdog_set(unsigned long deciseconds) | |||
153 | /* | 153 | /* |
154 | * set the wdog values in the wdog registers | 154 | * set the wdog values in the wdog registers |
155 | */ | 155 | */ |
156 | rtc_write(BIN2BCD(deciseconds % 100), DS1511_WD_MSEC); | 156 | rtc_write(bin2bcd(deciseconds % 100), DS1511_WD_MSEC); |
157 | rtc_write(BIN2BCD(deciseconds / 100), DS1511_WD_SEC); | 157 | rtc_write(bin2bcd(deciseconds / 100), DS1511_WD_SEC); |
158 | /* | 158 | /* |
159 | * set wdog enable and wdog 'steering' bit to issue a reset | 159 | * set wdog enable and wdog 'steering' bit to issue a reset |
160 | */ | 160 | */ |
@@ -220,13 +220,13 @@ static int ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm) | |||
220 | /* | 220 | /* |
221 | * each register is a different number of valid bits | 221 | * each register is a different number of valid bits |
222 | */ | 222 | */ |
223 | sec = BIN2BCD(sec) & 0x7f; | 223 | sec = bin2bcd(sec) & 0x7f; |
224 | min = BIN2BCD(min) & 0x7f; | 224 | min = bin2bcd(min) & 0x7f; |
225 | hrs = BIN2BCD(hrs) & 0x3f; | 225 | hrs = bin2bcd(hrs) & 0x3f; |
226 | day = BIN2BCD(day) & 0x3f; | 226 | day = bin2bcd(day) & 0x3f; |
227 | mon = BIN2BCD(mon) & 0x1f; | 227 | mon = bin2bcd(mon) & 0x1f; |
228 | yrs = BIN2BCD(yrs) & 0xff; | 228 | yrs = bin2bcd(yrs) & 0xff; |
229 | cen = BIN2BCD(cen) & 0xff; | 229 | cen = bin2bcd(cen) & 0xff; |
230 | 230 | ||
231 | spin_lock_irqsave(&ds1511_lock, flags); | 231 | spin_lock_irqsave(&ds1511_lock, flags); |
232 | rtc_disable_update(); | 232 | rtc_disable_update(); |
@@ -264,14 +264,14 @@ static int ds1511_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) | |||
264 | rtc_enable_update(); | 264 | rtc_enable_update(); |
265 | spin_unlock_irqrestore(&ds1511_lock, flags); | 265 | spin_unlock_irqrestore(&ds1511_lock, flags); |
266 | 266 | ||
267 | rtc_tm->tm_sec = BCD2BIN(rtc_tm->tm_sec); | 267 | rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); |
268 | rtc_tm->tm_min = BCD2BIN(rtc_tm->tm_min); | 268 | rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min); |
269 | rtc_tm->tm_hour = BCD2BIN(rtc_tm->tm_hour); | 269 | rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour); |
270 | rtc_tm->tm_mday = BCD2BIN(rtc_tm->tm_mday); | 270 | rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday); |
271 | rtc_tm->tm_wday = BCD2BIN(rtc_tm->tm_wday); | 271 | rtc_tm->tm_wday = bcd2bin(rtc_tm->tm_wday); |
272 | rtc_tm->tm_mon = BCD2BIN(rtc_tm->tm_mon); | 272 | rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon); |
273 | rtc_tm->tm_year = BCD2BIN(rtc_tm->tm_year); | 273 | rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year); |
274 | century = BCD2BIN(century) * 100; | 274 | century = bcd2bin(century) * 100; |
275 | 275 | ||
276 | /* | 276 | /* |
277 | * Account for differences between how the RTC uses the values | 277 | * Account for differences between how the RTC uses the values |
@@ -304,16 +304,16 @@ ds1511_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
304 | 304 | ||
305 | spin_lock_irqsave(&pdata->rtc->irq_lock, flags); | 305 | spin_lock_irqsave(&pdata->rtc->irq_lock, flags); |
306 | rtc_write(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? | 306 | rtc_write(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? |
307 | 0x80 : BIN2BCD(pdata->alrm_mday) & 0x3f, | 307 | 0x80 : bin2bcd(pdata->alrm_mday) & 0x3f, |
308 | RTC_ALARM_DATE); | 308 | RTC_ALARM_DATE); |
309 | rtc_write(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ? | 309 | rtc_write(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ? |
310 | 0x80 : BIN2BCD(pdata->alrm_hour) & 0x3f, | 310 | 0x80 : bin2bcd(pdata->alrm_hour) & 0x3f, |
311 | RTC_ALARM_HOUR); | 311 | RTC_ALARM_HOUR); |
312 | rtc_write(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ? | 312 | rtc_write(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ? |
313 | 0x80 : BIN2BCD(pdata->alrm_min) & 0x7f, | 313 | 0x80 : bin2bcd(pdata->alrm_min) & 0x7f, |
314 | RTC_ALARM_MIN); | 314 | RTC_ALARM_MIN); |
315 | rtc_write(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ? | 315 | rtc_write(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ? |
316 | 0x80 : BIN2BCD(pdata->alrm_sec) & 0x7f, | 316 | 0x80 : bin2bcd(pdata->alrm_sec) & 0x7f, |
317 | RTC_ALARM_SEC); | 317 | RTC_ALARM_SEC); |
318 | rtc_write(rtc_read(RTC_CMD) | (pdata->irqen ? RTC_TIE : 0), RTC_CMD); | 318 | rtc_write(rtc_read(RTC_CMD) | (pdata->irqen ? RTC_TIE : 0), RTC_CMD); |
319 | rtc_read(RTC_CMD1); /* clear interrupts */ | 319 | rtc_read(RTC_CMD1); /* clear interrupts */ |
@@ -379,18 +379,6 @@ ds1511_interrupt(int irq, void *dev_id) | |||
379 | return IRQ_HANDLED; | 379 | return IRQ_HANDLED; |
380 | } | 380 | } |
381 | 381 | ||
382 | static void | ||
383 | ds1511_rtc_release(struct device *dev) | ||
384 | { | ||
385 | struct platform_device *pdev = to_platform_device(dev); | ||
386 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
387 | |||
388 | if (pdata->irq >= 0) { | ||
389 | pdata->irqen = 0; | ||
390 | ds1511_rtc_update_alarm(pdata); | ||
391 | } | ||
392 | } | ||
393 | |||
394 | static int | 382 | static int |
395 | ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 383 | ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
396 | { | 384 | { |
@@ -428,7 +416,6 @@ static const struct rtc_class_ops ds1511_rtc_ops = { | |||
428 | .set_time = ds1511_rtc_set_time, | 416 | .set_time = ds1511_rtc_set_time, |
429 | .read_alarm = ds1511_rtc_read_alarm, | 417 | .read_alarm = ds1511_rtc_read_alarm, |
430 | .set_alarm = ds1511_rtc_set_alarm, | 418 | .set_alarm = ds1511_rtc_set_alarm, |
431 | .release = ds1511_rtc_release, | ||
432 | .ioctl = ds1511_rtc_ioctl, | 419 | .ioctl = ds1511_rtc_ioctl, |
433 | }; | 420 | }; |
434 | 421 | ||
@@ -494,7 +481,6 @@ static struct bin_attribute ds1511_nvram_attr = { | |||
494 | .attr = { | 481 | .attr = { |
495 | .name = "nvram", | 482 | .name = "nvram", |
496 | .mode = S_IRUGO | S_IWUGO, | 483 | .mode = S_IRUGO | S_IWUGO, |
497 | .owner = THIS_MODULE, | ||
498 | }, | 484 | }, |
499 | .size = DS1511_RAM_MAX, | 485 | .size = DS1511_RAM_MAX, |
500 | .read = ds1511_nvram_read, | 486 | .read = ds1511_nvram_read, |
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index a19f11415540..b9475cd20210 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c | |||
@@ -78,17 +78,17 @@ static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
78 | void __iomem *ioaddr = pdata->ioaddr; | 78 | void __iomem *ioaddr = pdata->ioaddr; |
79 | u8 century; | 79 | u8 century; |
80 | 80 | ||
81 | century = BIN2BCD((tm->tm_year + 1900) / 100); | 81 | century = bin2bcd((tm->tm_year + 1900) / 100); |
82 | 82 | ||
83 | writeb(RTC_WRITE, pdata->ioaddr + RTC_CONTROL); | 83 | writeb(RTC_WRITE, pdata->ioaddr + RTC_CONTROL); |
84 | 84 | ||
85 | writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR); | 85 | writeb(bin2bcd(tm->tm_year % 100), ioaddr + RTC_YEAR); |
86 | writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH); | 86 | writeb(bin2bcd(tm->tm_mon + 1), ioaddr + RTC_MONTH); |
87 | writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY); | 87 | writeb(bin2bcd(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY); |
88 | writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE); | 88 | writeb(bin2bcd(tm->tm_mday), ioaddr + RTC_DATE); |
89 | writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS); | 89 | writeb(bin2bcd(tm->tm_hour), ioaddr + RTC_HOURS); |
90 | writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES); | 90 | writeb(bin2bcd(tm->tm_min), ioaddr + RTC_MINUTES); |
91 | writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS); | 91 | writeb(bin2bcd(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS); |
92 | 92 | ||
93 | /* RTC_CENTURY and RTC_CONTROL share same register */ | 93 | /* RTC_CENTURY and RTC_CONTROL share same register */ |
94 | writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY); | 94 | writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY); |
@@ -118,14 +118,14 @@ static int ds1553_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
118 | year = readb(ioaddr + RTC_YEAR); | 118 | year = readb(ioaddr + RTC_YEAR); |
119 | century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK; | 119 | century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK; |
120 | writeb(0, ioaddr + RTC_CONTROL); | 120 | writeb(0, ioaddr + RTC_CONTROL); |
121 | tm->tm_sec = BCD2BIN(second); | 121 | tm->tm_sec = bcd2bin(second); |
122 | tm->tm_min = BCD2BIN(minute); | 122 | tm->tm_min = bcd2bin(minute); |
123 | tm->tm_hour = BCD2BIN(hour); | 123 | tm->tm_hour = bcd2bin(hour); |
124 | tm->tm_mday = BCD2BIN(day); | 124 | tm->tm_mday = bcd2bin(day); |
125 | tm->tm_wday = BCD2BIN(week); | 125 | tm->tm_wday = bcd2bin(week); |
126 | tm->tm_mon = BCD2BIN(month) - 1; | 126 | tm->tm_mon = bcd2bin(month) - 1; |
127 | /* year is 1900 + tm->tm_year */ | 127 | /* year is 1900 + tm->tm_year */ |
128 | tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900; | 128 | tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900; |
129 | 129 | ||
130 | if (rtc_valid_tm(tm) < 0) { | 130 | if (rtc_valid_tm(tm) < 0) { |
131 | dev_err(dev, "retrieved date/time is not valid.\n"); | 131 | dev_err(dev, "retrieved date/time is not valid.\n"); |
@@ -141,16 +141,16 @@ static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
141 | 141 | ||
142 | spin_lock_irqsave(&pdata->rtc->irq_lock, flags); | 142 | spin_lock_irqsave(&pdata->rtc->irq_lock, flags); |
143 | writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? | 143 | writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? |
144 | 0x80 : BIN2BCD(pdata->alrm_mday), | 144 | 0x80 : bin2bcd(pdata->alrm_mday), |
145 | ioaddr + RTC_DATE_ALARM); | 145 | ioaddr + RTC_DATE_ALARM); |
146 | writeb(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ? | 146 | writeb(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ? |
147 | 0x80 : BIN2BCD(pdata->alrm_hour), | 147 | 0x80 : bin2bcd(pdata->alrm_hour), |
148 | ioaddr + RTC_HOURS_ALARM); | 148 | ioaddr + RTC_HOURS_ALARM); |
149 | writeb(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ? | 149 | writeb(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ? |
150 | 0x80 : BIN2BCD(pdata->alrm_min), | 150 | 0x80 : bin2bcd(pdata->alrm_min), |
151 | ioaddr + RTC_MINUTES_ALARM); | 151 | ioaddr + RTC_MINUTES_ALARM); |
152 | writeb(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ? | 152 | writeb(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ? |
153 | 0x80 : BIN2BCD(pdata->alrm_sec), | 153 | 0x80 : bin2bcd(pdata->alrm_sec), |
154 | ioaddr + RTC_SECONDS_ALARM); | 154 | ioaddr + RTC_SECONDS_ALARM); |
155 | writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS); | 155 | writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS); |
156 | readb(ioaddr + RTC_FLAGS); /* clear interrupts */ | 156 | readb(ioaddr + RTC_FLAGS); /* clear interrupts */ |
@@ -207,17 +207,6 @@ static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id) | |||
207 | return IRQ_HANDLED; | 207 | return IRQ_HANDLED; |
208 | } | 208 | } |
209 | 209 | ||
210 | static void ds1553_rtc_release(struct device *dev) | ||
211 | { | ||
212 | struct platform_device *pdev = to_platform_device(dev); | ||
213 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
214 | |||
215 | if (pdata->irq >= 0) { | ||
216 | pdata->irqen = 0; | ||
217 | ds1553_rtc_update_alarm(pdata); | ||
218 | } | ||
219 | } | ||
220 | |||
221 | static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd, | 210 | static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd, |
222 | unsigned long arg) | 211 | unsigned long arg) |
223 | { | 212 | { |
@@ -254,7 +243,6 @@ static const struct rtc_class_ops ds1553_rtc_ops = { | |||
254 | .set_time = ds1553_rtc_set_time, | 243 | .set_time = ds1553_rtc_set_time, |
255 | .read_alarm = ds1553_rtc_read_alarm, | 244 | .read_alarm = ds1553_rtc_read_alarm, |
256 | .set_alarm = ds1553_rtc_set_alarm, | 245 | .set_alarm = ds1553_rtc_set_alarm, |
257 | .release = ds1553_rtc_release, | ||
258 | .ioctl = ds1553_rtc_ioctl, | 246 | .ioctl = ds1553_rtc_ioctl, |
259 | }; | 247 | }; |
260 | 248 | ||
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index 6fa4556f5f5c..341d7a5b45a2 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c | |||
@@ -9,17 +9,10 @@ | |||
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/i2c.h> | 12 | #include <linux/i2c.h> |
14 | #include <linux/rtc.h> | 13 | #include <linux/rtc.h> |
15 | 14 | ||
16 | #define DRV_VERSION "0.3" | 15 | #define DRV_VERSION "0.4" |
17 | |||
18 | /* Addresses to scan: none. This chip cannot be detected. */ | ||
19 | static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; | ||
20 | |||
21 | /* Insmod parameters */ | ||
22 | I2C_CLIENT_INSMOD; | ||
23 | 16 | ||
24 | /* Registers */ | 17 | /* Registers */ |
25 | 18 | ||
@@ -29,8 +22,7 @@ I2C_CLIENT_INSMOD; | |||
29 | 22 | ||
30 | #define DS1672_REG_CONTROL_EOSC 0x80 | 23 | #define DS1672_REG_CONTROL_EOSC 0x80 |
31 | 24 | ||
32 | /* Prototypes */ | 25 | static struct i2c_driver ds1672_driver; |
33 | static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind); | ||
34 | 26 | ||
35 | /* | 27 | /* |
36 | * In the routines that deal directly with the ds1672 hardware, we use | 28 | * In the routines that deal directly with the ds1672 hardware, we use |
@@ -44,8 +36,8 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
44 | unsigned char buf[4]; | 36 | unsigned char buf[4]; |
45 | 37 | ||
46 | struct i2c_msg msgs[] = { | 38 | struct i2c_msg msgs[] = { |
47 | { client->addr, 0, 1, &addr }, /* setup read ptr */ | 39 | {client->addr, 0, 1, &addr}, /* setup read ptr */ |
48 | { client->addr, I2C_M_RD, 4, buf }, /* read date */ | 40 | {client->addr, I2C_M_RD, 4, buf}, /* read date */ |
49 | }; | 41 | }; |
50 | 42 | ||
51 | /* read date registers */ | 43 | /* read date registers */ |
@@ -80,7 +72,7 @@ static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs) | |||
80 | buf[2] = (secs & 0x0000FF00) >> 8; | 72 | buf[2] = (secs & 0x0000FF00) >> 8; |
81 | buf[3] = (secs & 0x00FF0000) >> 16; | 73 | buf[3] = (secs & 0x00FF0000) >> 16; |
82 | buf[4] = (secs & 0xFF000000) >> 24; | 74 | buf[4] = (secs & 0xFF000000) >> 24; |
83 | buf[5] = 0; /* set control reg to enable counting */ | 75 | buf[5] = 0; /* set control reg to enable counting */ |
84 | 76 | ||
85 | xfer = i2c_master_send(client, buf, 6); | 77 | xfer = i2c_master_send(client, buf, 6); |
86 | if (xfer != 6) { | 78 | if (xfer != 6) { |
@@ -127,8 +119,8 @@ static int ds1672_get_control(struct i2c_client *client, u8 *status) | |||
127 | unsigned char addr = DS1672_REG_CONTROL; | 119 | unsigned char addr = DS1672_REG_CONTROL; |
128 | 120 | ||
129 | struct i2c_msg msgs[] = { | 121 | struct i2c_msg msgs[] = { |
130 | { client->addr, 0, 1, &addr }, /* setup read ptr */ | 122 | {client->addr, 0, 1, &addr}, /* setup read ptr */ |
131 | { client->addr, I2C_M_RD, 1, status }, /* read control */ | 123 | {client->addr, I2C_M_RD, 1, status}, /* read control */ |
132 | }; | 124 | }; |
133 | 125 | ||
134 | /* read control register */ | 126 | /* read control register */ |
@@ -141,7 +133,8 @@ static int ds1672_get_control(struct i2c_client *client, u8 *status) | |||
141 | } | 133 | } |
142 | 134 | ||
143 | /* following are the sysfs callback functions */ | 135 | /* following are the sysfs callback functions */ |
144 | static ssize_t show_control(struct device *dev, struct device_attribute *attr, char *buf) | 136 | static ssize_t show_control(struct device *dev, struct device_attribute *attr, |
137 | char *buf) | ||
145 | { | 138 | { |
146 | struct i2c_client *client = to_i2c_client(dev); | 139 | struct i2c_client *client = to_i2c_client(dev); |
147 | u8 control; | 140 | u8 control; |
@@ -152,85 +145,46 @@ static ssize_t show_control(struct device *dev, struct device_attribute *attr, c | |||
152 | return err; | 145 | return err; |
153 | 146 | ||
154 | return sprintf(buf, "%s\n", (control & DS1672_REG_CONTROL_EOSC) | 147 | return sprintf(buf, "%s\n", (control & DS1672_REG_CONTROL_EOSC) |
155 | ? "disabled" : "enabled"); | 148 | ? "disabled" : "enabled"); |
156 | } | 149 | } |
150 | |||
157 | static DEVICE_ATTR(control, S_IRUGO, show_control, NULL); | 151 | static DEVICE_ATTR(control, S_IRUGO, show_control, NULL); |
158 | 152 | ||
159 | static const struct rtc_class_ops ds1672_rtc_ops = { | 153 | static const struct rtc_class_ops ds1672_rtc_ops = { |
160 | .read_time = ds1672_rtc_read_time, | 154 | .read_time = ds1672_rtc_read_time, |
161 | .set_time = ds1672_rtc_set_time, | 155 | .set_time = ds1672_rtc_set_time, |
162 | .set_mmss = ds1672_rtc_set_mmss, | 156 | .set_mmss = ds1672_rtc_set_mmss, |
163 | }; | 157 | }; |
164 | 158 | ||
165 | static int ds1672_attach(struct i2c_adapter *adapter) | 159 | static int ds1672_remove(struct i2c_client *client) |
166 | { | 160 | { |
167 | return i2c_probe(adapter, &addr_data, ds1672_probe); | ||
168 | } | ||
169 | |||
170 | static int ds1672_detach(struct i2c_client *client) | ||
171 | { | ||
172 | int err; | ||
173 | struct rtc_device *rtc = i2c_get_clientdata(client); | 161 | struct rtc_device *rtc = i2c_get_clientdata(client); |
174 | 162 | ||
175 | if (rtc) | 163 | if (rtc) |
176 | rtc_device_unregister(rtc); | 164 | rtc_device_unregister(rtc); |
177 | 165 | ||
178 | if ((err = i2c_detach_client(client))) | ||
179 | return err; | ||
180 | |||
181 | kfree(client); | ||
182 | |||
183 | return 0; | 166 | return 0; |
184 | } | 167 | } |
185 | 168 | ||
186 | static struct i2c_driver ds1672_driver = { | 169 | static int ds1672_probe(struct i2c_client *client, |
187 | .driver = { | 170 | const struct i2c_device_id *id) |
188 | .name = "ds1672", | ||
189 | }, | ||
190 | .id = I2C_DRIVERID_DS1672, | ||
191 | .attach_adapter = &ds1672_attach, | ||
192 | .detach_client = &ds1672_detach, | ||
193 | }; | ||
194 | |||
195 | static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) | ||
196 | { | 171 | { |
197 | int err = 0; | 172 | int err = 0; |
198 | u8 control; | 173 | u8 control; |
199 | struct i2c_client *client; | ||
200 | struct rtc_device *rtc; | 174 | struct rtc_device *rtc; |
201 | 175 | ||
202 | dev_dbg(&adapter->dev, "%s\n", __func__); | 176 | dev_dbg(&client->dev, "%s\n", __func__); |
203 | 177 | ||
204 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | 178 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) |
205 | err = -ENODEV; | 179 | return -ENODEV; |
206 | goto exit; | ||
207 | } | ||
208 | |||
209 | if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { | ||
210 | err = -ENOMEM; | ||
211 | goto exit; | ||
212 | } | ||
213 | |||
214 | /* I2C client */ | ||
215 | client->addr = address; | ||
216 | client->driver = &ds1672_driver; | ||
217 | client->adapter = adapter; | ||
218 | |||
219 | strlcpy(client->name, ds1672_driver.driver.name, I2C_NAME_SIZE); | ||
220 | |||
221 | /* Inform the i2c layer */ | ||
222 | if ((err = i2c_attach_client(client))) | ||
223 | goto exit_kfree; | ||
224 | 180 | ||
225 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | 181 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
226 | 182 | ||
227 | rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev, | 183 | rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev, |
228 | &ds1672_rtc_ops, THIS_MODULE); | 184 | &ds1672_rtc_ops, THIS_MODULE); |
229 | 185 | ||
230 | if (IS_ERR(rtc)) { | 186 | if (IS_ERR(rtc)) |
231 | err = PTR_ERR(rtc); | 187 | return PTR_ERR(rtc); |
232 | goto exit_detach; | ||
233 | } | ||
234 | 188 | ||
235 | i2c_set_clientdata(client, rtc); | 189 | i2c_set_clientdata(client, rtc); |
236 | 190 | ||
@@ -241,7 +195,7 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) | |||
241 | 195 | ||
242 | if (control & DS1672_REG_CONTROL_EOSC) | 196 | if (control & DS1672_REG_CONTROL_EOSC) |
243 | dev_warn(&client->dev, "Oscillator not enabled. " | 197 | dev_warn(&client->dev, "Oscillator not enabled. " |
244 | "Set time to enable.\n"); | 198 | "Set time to enable.\n"); |
245 | 199 | ||
246 | /* Register sysfs hooks */ | 200 | /* Register sysfs hooks */ |
247 | err = device_create_file(&client->dev, &dev_attr_control); | 201 | err = device_create_file(&client->dev, &dev_attr_control); |
@@ -250,19 +204,19 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) | |||
250 | 204 | ||
251 | return 0; | 205 | return 0; |
252 | 206 | ||
253 | exit_devreg: | 207 | exit_devreg: |
254 | rtc_device_unregister(rtc); | 208 | rtc_device_unregister(rtc); |
255 | |||
256 | exit_detach: | ||
257 | i2c_detach_client(client); | ||
258 | |||
259 | exit_kfree: | ||
260 | kfree(client); | ||
261 | |||
262 | exit: | ||
263 | return err; | 209 | return err; |
264 | } | 210 | } |
265 | 211 | ||
212 | static struct i2c_driver ds1672_driver = { | ||
213 | .driver = { | ||
214 | .name = "rtc-ds1672", | ||
215 | }, | ||
216 | .probe = &ds1672_probe, | ||
217 | .remove = &ds1672_remove, | ||
218 | }; | ||
219 | |||
266 | static int __init ds1672_init(void) | 220 | static int __init ds1672_init(void) |
267 | { | 221 | { |
268 | return i2c_add_driver(&ds1672_driver); | 222 | return i2c_add_driver(&ds1672_driver); |
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 24d35ede2dbf..8bc8501bffc8 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
@@ -66,17 +66,17 @@ static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
66 | void __iomem *ioaddr = pdata->ioaddr_rtc; | 66 | void __iomem *ioaddr = pdata->ioaddr_rtc; |
67 | u8 century; | 67 | u8 century; |
68 | 68 | ||
69 | century = BIN2BCD((tm->tm_year + 1900) / 100); | 69 | century = bin2bcd((tm->tm_year + 1900) / 100); |
70 | 70 | ||
71 | writeb(RTC_WRITE, ioaddr + RTC_CONTROL); | 71 | writeb(RTC_WRITE, ioaddr + RTC_CONTROL); |
72 | 72 | ||
73 | writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR); | 73 | writeb(bin2bcd(tm->tm_year % 100), ioaddr + RTC_YEAR); |
74 | writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH); | 74 | writeb(bin2bcd(tm->tm_mon + 1), ioaddr + RTC_MONTH); |
75 | writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY); | 75 | writeb(bin2bcd(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY); |
76 | writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE); | 76 | writeb(bin2bcd(tm->tm_mday), ioaddr + RTC_DATE); |
77 | writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS); | 77 | writeb(bin2bcd(tm->tm_hour), ioaddr + RTC_HOURS); |
78 | writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES); | 78 | writeb(bin2bcd(tm->tm_min), ioaddr + RTC_MINUTES); |
79 | writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS); | 79 | writeb(bin2bcd(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS); |
80 | 80 | ||
81 | /* RTC_CENTURY and RTC_CONTROL share same register */ | 81 | /* RTC_CENTURY and RTC_CONTROL share same register */ |
82 | writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY); | 82 | writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY); |
@@ -106,14 +106,14 @@ static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
106 | year = readb(ioaddr + RTC_YEAR); | 106 | year = readb(ioaddr + RTC_YEAR); |
107 | century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK; | 107 | century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK; |
108 | writeb(0, ioaddr + RTC_CONTROL); | 108 | writeb(0, ioaddr + RTC_CONTROL); |
109 | tm->tm_sec = BCD2BIN(second); | 109 | tm->tm_sec = bcd2bin(second); |
110 | tm->tm_min = BCD2BIN(minute); | 110 | tm->tm_min = bcd2bin(minute); |
111 | tm->tm_hour = BCD2BIN(hour); | 111 | tm->tm_hour = bcd2bin(hour); |
112 | tm->tm_mday = BCD2BIN(day); | 112 | tm->tm_mday = bcd2bin(day); |
113 | tm->tm_wday = BCD2BIN(week); | 113 | tm->tm_wday = bcd2bin(week); |
114 | tm->tm_mon = BCD2BIN(month) - 1; | 114 | tm->tm_mon = bcd2bin(month) - 1; |
115 | /* year is 1900 + tm->tm_year */ | 115 | /* year is 1900 + tm->tm_year */ |
116 | tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900; | 116 | tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900; |
117 | 117 | ||
118 | if (rtc_valid_tm(tm) < 0) { | 118 | if (rtc_valid_tm(tm) < 0) { |
119 | dev_err(dev, "retrieved date/time is not valid.\n"); | 119 | dev_err(dev, "retrieved date/time is not valid.\n"); |
diff --git a/drivers/rtc/rtc-ds3234.c b/drivers/rtc/rtc-ds3234.c new file mode 100644 index 000000000000..37d131d03f33 --- /dev/null +++ b/drivers/rtc/rtc-ds3234.c | |||
@@ -0,0 +1,290 @@ | |||
1 | /* drivers/rtc/rtc-ds3234.c | ||
2 | * | ||
3 | * Driver for Dallas Semiconductor (DS3234) SPI RTC with Integrated Crystal | ||
4 | * and SRAM. | ||
5 | * | ||
6 | * Copyright (C) 2008 MIMOMax Wireless Ltd. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * Changelog: | ||
13 | * | ||
14 | * 07-May-2008: Dennis Aberilla <denzzzhome@yahoo.com> | ||
15 | * - Created based on the max6902 code. Only implements the | ||
16 | * date/time keeping functions; no SRAM yet. | ||
17 | */ | ||
18 | |||
19 | #include <linux/device.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/rtc.h> | ||
22 | #include <linux/spi/spi.h> | ||
23 | #include <linux/bcd.h> | ||
24 | |||
25 | #define DS3234_REG_SECONDS 0x00 | ||
26 | #define DS3234_REG_MINUTES 0x01 | ||
27 | #define DS3234_REG_HOURS 0x02 | ||
28 | #define DS3234_REG_DAY 0x03 | ||
29 | #define DS3234_REG_DATE 0x04 | ||
30 | #define DS3234_REG_MONTH 0x05 | ||
31 | #define DS3234_REG_YEAR 0x06 | ||
32 | #define DS3234_REG_CENTURY (1 << 7) /* Bit 7 of the Month register */ | ||
33 | |||
34 | #define DS3234_REG_CONTROL 0x0E | ||
35 | #define DS3234_REG_CONT_STAT 0x0F | ||
36 | |||
37 | #undef DS3234_DEBUG | ||
38 | |||
39 | struct ds3234 { | ||
40 | struct rtc_device *rtc; | ||
41 | u8 buf[8]; /* Burst read: addr + 7 regs */ | ||
42 | u8 tx_buf[2]; | ||
43 | u8 rx_buf[2]; | ||
44 | }; | ||
45 | |||
46 | static void ds3234_set_reg(struct device *dev, unsigned char address, | ||
47 | unsigned char data) | ||
48 | { | ||
49 | struct spi_device *spi = to_spi_device(dev); | ||
50 | unsigned char buf[2]; | ||
51 | |||
52 | /* MSB must be '1' to indicate write */ | ||
53 | buf[0] = address | 0x80; | ||
54 | buf[1] = data; | ||
55 | |||
56 | spi_write(spi, buf, 2); | ||
57 | } | ||
58 | |||
59 | static int ds3234_get_reg(struct device *dev, unsigned char address, | ||
60 | unsigned char *data) | ||
61 | { | ||
62 | struct spi_device *spi = to_spi_device(dev); | ||
63 | struct ds3234 *chip = dev_get_drvdata(dev); | ||
64 | struct spi_message message; | ||
65 | struct spi_transfer xfer; | ||
66 | int status; | ||
67 | |||
68 | if (!data) | ||
69 | return -EINVAL; | ||
70 | |||
71 | /* Build our spi message */ | ||
72 | spi_message_init(&message); | ||
73 | memset(&xfer, 0, sizeof(xfer)); | ||
74 | |||
75 | /* Address + dummy tx byte */ | ||
76 | xfer.len = 2; | ||
77 | xfer.tx_buf = chip->tx_buf; | ||
78 | xfer.rx_buf = chip->rx_buf; | ||
79 | |||
80 | chip->tx_buf[0] = address; | ||
81 | chip->tx_buf[1] = 0xff; | ||
82 | |||
83 | spi_message_add_tail(&xfer, &message); | ||
84 | |||
85 | /* do the i/o */ | ||
86 | status = spi_sync(spi, &message); | ||
87 | if (status == 0) | ||
88 | status = message.status; | ||
89 | else | ||
90 | return status; | ||
91 | |||
92 | *data = chip->rx_buf[1]; | ||
93 | |||
94 | return status; | ||
95 | } | ||
96 | |||
97 | static int ds3234_get_datetime(struct device *dev, struct rtc_time *dt) | ||
98 | { | ||
99 | struct spi_device *spi = to_spi_device(dev); | ||
100 | struct ds3234 *chip = dev_get_drvdata(dev); | ||
101 | struct spi_message message; | ||
102 | struct spi_transfer xfer; | ||
103 | int status; | ||
104 | |||
105 | /* build the message */ | ||
106 | spi_message_init(&message); | ||
107 | memset(&xfer, 0, sizeof(xfer)); | ||
108 | xfer.len = 1 + 7; /* Addr + 7 registers */ | ||
109 | xfer.tx_buf = chip->buf; | ||
110 | xfer.rx_buf = chip->buf; | ||
111 | chip->buf[0] = 0x00; /* Start address */ | ||
112 | spi_message_add_tail(&xfer, &message); | ||
113 | |||
114 | /* do the i/o */ | ||
115 | status = spi_sync(spi, &message); | ||
116 | if (status == 0) | ||
117 | status = message.status; | ||
118 | else | ||
119 | return status; | ||
120 | |||
121 | /* Seconds, Minutes, Hours, Day, Date, Month, Year */ | ||
122 | dt->tm_sec = bcd2bin(chip->buf[1]); | ||
123 | dt->tm_min = bcd2bin(chip->buf[2]); | ||
124 | dt->tm_hour = bcd2bin(chip->buf[3] & 0x3f); | ||
125 | dt->tm_wday = bcd2bin(chip->buf[4]) - 1; /* 0 = Sun */ | ||
126 | dt->tm_mday = bcd2bin(chip->buf[5]); | ||
127 | dt->tm_mon = bcd2bin(chip->buf[6] & 0x1f) - 1; /* 0 = Jan */ | ||
128 | dt->tm_year = bcd2bin(chip->buf[7] & 0xff) + 100; /* Assume 20YY */ | ||
129 | |||
130 | #ifdef DS3234_DEBUG | ||
131 | dev_dbg(dev, "\n%s : Read RTC values\n", __func__); | ||
132 | dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour); | ||
133 | dev_dbg(dev, "tm_min : %i\n", dt->tm_min); | ||
134 | dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec); | ||
135 | dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday); | ||
136 | dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday); | ||
137 | dev_dbg(dev, "tm_mon : %i\n", dt->tm_mon); | ||
138 | dev_dbg(dev, "tm_year: %i\n", dt->tm_year); | ||
139 | #endif | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int ds3234_set_datetime(struct device *dev, struct rtc_time *dt) | ||
145 | { | ||
146 | #ifdef DS3234_DEBUG | ||
147 | dev_dbg(dev, "\n%s : Setting RTC values\n", __func__); | ||
148 | dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec); | ||
149 | dev_dbg(dev, "tm_min : %i\n", dt->tm_min); | ||
150 | dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour); | ||
151 | dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday); | ||
152 | dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday); | ||
153 | dev_dbg(dev, "tm_mon : %i\n", dt->tm_mon); | ||
154 | dev_dbg(dev, "tm_year: %i\n", dt->tm_year); | ||
155 | #endif | ||
156 | |||
157 | ds3234_set_reg(dev, DS3234_REG_SECONDS, bin2bcd(dt->tm_sec)); | ||
158 | ds3234_set_reg(dev, DS3234_REG_MINUTES, bin2bcd(dt->tm_min)); | ||
159 | ds3234_set_reg(dev, DS3234_REG_HOURS, bin2bcd(dt->tm_hour) & 0x3f); | ||
160 | |||
161 | /* 0 = Sun */ | ||
162 | ds3234_set_reg(dev, DS3234_REG_DAY, bin2bcd(dt->tm_wday + 1)); | ||
163 | ds3234_set_reg(dev, DS3234_REG_DATE, bin2bcd(dt->tm_mday)); | ||
164 | |||
165 | /* 0 = Jan */ | ||
166 | ds3234_set_reg(dev, DS3234_REG_MONTH, bin2bcd(dt->tm_mon + 1)); | ||
167 | |||
168 | /* Assume 20YY although we just want to make sure not to go negative. */ | ||
169 | if (dt->tm_year > 100) | ||
170 | dt->tm_year -= 100; | ||
171 | |||
172 | ds3234_set_reg(dev, DS3234_REG_YEAR, bin2bcd(dt->tm_year)); | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | static int ds3234_read_time(struct device *dev, struct rtc_time *tm) | ||
178 | { | ||
179 | return ds3234_get_datetime(dev, tm); | ||
180 | } | ||
181 | |||
182 | static int ds3234_set_time(struct device *dev, struct rtc_time *tm) | ||
183 | { | ||
184 | return ds3234_set_datetime(dev, tm); | ||
185 | } | ||
186 | |||
187 | static const struct rtc_class_ops ds3234_rtc_ops = { | ||
188 | .read_time = ds3234_read_time, | ||
189 | .set_time = ds3234_set_time, | ||
190 | }; | ||
191 | |||
192 | static int ds3234_probe(struct spi_device *spi) | ||
193 | { | ||
194 | struct rtc_device *rtc; | ||
195 | unsigned char tmp; | ||
196 | struct ds3234 *chip; | ||
197 | int res; | ||
198 | |||
199 | rtc = rtc_device_register("ds3234", | ||
200 | &spi->dev, &ds3234_rtc_ops, THIS_MODULE); | ||
201 | if (IS_ERR(rtc)) | ||
202 | return PTR_ERR(rtc); | ||
203 | |||
204 | spi->mode = SPI_MODE_3; | ||
205 | spi->bits_per_word = 8; | ||
206 | spi_setup(spi); | ||
207 | |||
208 | chip = kzalloc(sizeof(struct ds3234), GFP_KERNEL); | ||
209 | if (!chip) { | ||
210 | rtc_device_unregister(rtc); | ||
211 | return -ENOMEM; | ||
212 | } | ||
213 | chip->rtc = rtc; | ||
214 | dev_set_drvdata(&spi->dev, chip); | ||
215 | |||
216 | res = ds3234_get_reg(&spi->dev, DS3234_REG_SECONDS, &tmp); | ||
217 | if (res) { | ||
218 | rtc_device_unregister(rtc); | ||
219 | return res; | ||
220 | } | ||
221 | |||
222 | /* Control settings | ||
223 | * | ||
224 | * CONTROL_REG | ||
225 | * BIT 7 6 5 4 3 2 1 0 | ||
226 | * EOSC BBSQW CONV RS2 RS1 INTCN A2IE A1IE | ||
227 | * | ||
228 | * 0 0 0 1 1 1 0 0 | ||
229 | * | ||
230 | * CONTROL_STAT_REG | ||
231 | * BIT 7 6 5 4 3 2 1 0 | ||
232 | * OSF BB32kHz CRATE1 CRATE0 EN32kHz BSY A2F A1F | ||
233 | * | ||
234 | * 1 0 0 0 1 0 0 0 | ||
235 | */ | ||
236 | ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp); | ||
237 | ds3234_set_reg(&spi->dev, DS3234_REG_CONTROL, tmp & 0x1c); | ||
238 | |||
239 | ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp); | ||
240 | ds3234_set_reg(&spi->dev, DS3234_REG_CONT_STAT, tmp & 0x88); | ||
241 | |||
242 | /* Print our settings */ | ||
243 | ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp); | ||
244 | dev_info(&spi->dev, "Control Reg: 0x%02x\n", tmp); | ||
245 | |||
246 | ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp); | ||
247 | dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp); | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static int __exit ds3234_remove(struct spi_device *spi) | ||
253 | { | ||
254 | struct ds3234 *chip = platform_get_drvdata(spi); | ||
255 | struct rtc_device *rtc = chip->rtc; | ||
256 | |||
257 | if (rtc) | ||
258 | rtc_device_unregister(rtc); | ||
259 | |||
260 | kfree(chip); | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static struct spi_driver ds3234_driver = { | ||
266 | .driver = { | ||
267 | .name = "ds3234", | ||
268 | .bus = &spi_bus_type, | ||
269 | .owner = THIS_MODULE, | ||
270 | }, | ||
271 | .probe = ds3234_probe, | ||
272 | .remove = __devexit_p(ds3234_remove), | ||
273 | }; | ||
274 | |||
275 | static __init int ds3234_init(void) | ||
276 | { | ||
277 | printk(KERN_INFO "DS3234 SPI RTC Driver\n"); | ||
278 | return spi_register_driver(&ds3234_driver); | ||
279 | } | ||
280 | module_init(ds3234_init); | ||
281 | |||
282 | static __exit void ds3234_exit(void) | ||
283 | { | ||
284 | spi_unregister_driver(&ds3234_driver); | ||
285 | } | ||
286 | module_exit(ds3234_exit); | ||
287 | |||
288 | MODULE_DESCRIPTION("DS3234 SPI RTC driver"); | ||
289 | MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>"); | ||
290 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c index 1e99325270df..36e4ac0bd69c 100644 --- a/drivers/rtc/rtc-ep93xx.c +++ b/drivers/rtc/rtc-ep93xx.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/rtc.h> | 13 | #include <linux/rtc.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <asm/hardware.h> | 15 | #include <mach/hardware.h> |
16 | 16 | ||
17 | #define EP93XX_RTC_REG(x) (EP93XX_RTC_BASE + (x)) | 17 | #define EP93XX_RTC_REG(x) (EP93XX_RTC_BASE + (x)) |
18 | #define EP93XX_RTC_DATA EP93XX_RTC_REG(0x0000) | 18 | #define EP93XX_RTC_DATA EP93XX_RTC_REG(0x0000) |
diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index abfdfcbaa059..3a7be11cc6b9 100644 --- a/drivers/rtc/rtc-fm3130.c +++ b/drivers/rtc/rtc-fm3130.c | |||
@@ -131,17 +131,17 @@ static int fm3130_get_time(struct device *dev, struct rtc_time *t) | |||
131 | fm3130->regs[0xc], fm3130->regs[0xd], | 131 | fm3130->regs[0xc], fm3130->regs[0xd], |
132 | fm3130->regs[0xe]); | 132 | fm3130->regs[0xe]); |
133 | 133 | ||
134 | t->tm_sec = BCD2BIN(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f); | 134 | t->tm_sec = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f); |
135 | t->tm_min = BCD2BIN(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); | 135 | t->tm_min = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); |
136 | tmp = fm3130->regs[FM3130_RTC_HOURS] & 0x3f; | 136 | tmp = fm3130->regs[FM3130_RTC_HOURS] & 0x3f; |
137 | t->tm_hour = BCD2BIN(tmp); | 137 | t->tm_hour = bcd2bin(tmp); |
138 | t->tm_wday = BCD2BIN(fm3130->regs[FM3130_RTC_DAY] & 0x07) - 1; | 138 | t->tm_wday = bcd2bin(fm3130->regs[FM3130_RTC_DAY] & 0x07) - 1; |
139 | t->tm_mday = BCD2BIN(fm3130->regs[FM3130_RTC_DATE] & 0x3f); | 139 | t->tm_mday = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f); |
140 | tmp = fm3130->regs[FM3130_RTC_MONTHS] & 0x1f; | 140 | tmp = fm3130->regs[FM3130_RTC_MONTHS] & 0x1f; |
141 | t->tm_mon = BCD2BIN(tmp) - 1; | 141 | t->tm_mon = bcd2bin(tmp) - 1; |
142 | 142 | ||
143 | /* assume 20YY not 19YY, and ignore CF bit */ | 143 | /* assume 20YY not 19YY, and ignore CF bit */ |
144 | t->tm_year = BCD2BIN(fm3130->regs[FM3130_RTC_YEARS]) + 100; | 144 | t->tm_year = bcd2bin(fm3130->regs[FM3130_RTC_YEARS]) + 100; |
145 | 145 | ||
146 | dev_dbg(dev, "%s secs=%d, mins=%d, " | 146 | dev_dbg(dev, "%s secs=%d, mins=%d, " |
147 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", | 147 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", |
@@ -167,16 +167,16 @@ static int fm3130_set_time(struct device *dev, struct rtc_time *t) | |||
167 | t->tm_mon, t->tm_year, t->tm_wday); | 167 | t->tm_mon, t->tm_year, t->tm_wday); |
168 | 168 | ||
169 | /* first register addr */ | 169 | /* first register addr */ |
170 | buf[FM3130_RTC_SECONDS] = BIN2BCD(t->tm_sec); | 170 | buf[FM3130_RTC_SECONDS] = bin2bcd(t->tm_sec); |
171 | buf[FM3130_RTC_MINUTES] = BIN2BCD(t->tm_min); | 171 | buf[FM3130_RTC_MINUTES] = bin2bcd(t->tm_min); |
172 | buf[FM3130_RTC_HOURS] = BIN2BCD(t->tm_hour); | 172 | buf[FM3130_RTC_HOURS] = bin2bcd(t->tm_hour); |
173 | buf[FM3130_RTC_DAY] = BIN2BCD(t->tm_wday + 1); | 173 | buf[FM3130_RTC_DAY] = bin2bcd(t->tm_wday + 1); |
174 | buf[FM3130_RTC_DATE] = BIN2BCD(t->tm_mday); | 174 | buf[FM3130_RTC_DATE] = bin2bcd(t->tm_mday); |
175 | buf[FM3130_RTC_MONTHS] = BIN2BCD(t->tm_mon + 1); | 175 | buf[FM3130_RTC_MONTHS] = bin2bcd(t->tm_mon + 1); |
176 | 176 | ||
177 | /* assume 20YY not 19YY */ | 177 | /* assume 20YY not 19YY */ |
178 | tmp = t->tm_year - 100; | 178 | tmp = t->tm_year - 100; |
179 | buf[FM3130_RTC_YEARS] = BIN2BCD(tmp); | 179 | buf[FM3130_RTC_YEARS] = bin2bcd(tmp); |
180 | 180 | ||
181 | dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x" | 181 | dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x" |
182 | "%02x %02x %02x %02x %02x %02x %02x %02x\n", | 182 | "%02x %02x %02x %02x %02x %02x %02x %02x\n", |
@@ -222,11 +222,11 @@ static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
222 | fm3130->regs[FM3130_ALARM_MONTHS]); | 222 | fm3130->regs[FM3130_ALARM_MONTHS]); |
223 | 223 | ||
224 | 224 | ||
225 | tm->tm_sec = BCD2BIN(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F); | 225 | tm->tm_sec = bcd2bin(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F); |
226 | tm->tm_min = BCD2BIN(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F); | 226 | tm->tm_min = bcd2bin(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F); |
227 | tm->tm_hour = BCD2BIN(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F); | 227 | tm->tm_hour = bcd2bin(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F); |
228 | tm->tm_mday = BCD2BIN(fm3130->regs[FM3130_ALARM_DATE] & 0x3F); | 228 | tm->tm_mday = bcd2bin(fm3130->regs[FM3130_ALARM_DATE] & 0x3F); |
229 | tm->tm_mon = BCD2BIN(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F); | 229 | tm->tm_mon = bcd2bin(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F); |
230 | if (tm->tm_mon > 0) | 230 | if (tm->tm_mon > 0) |
231 | tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */ | 231 | tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */ |
232 | dev_dbg(dev, "%s secs=%d, mins=%d, " | 232 | dev_dbg(dev, "%s secs=%d, mins=%d, " |
@@ -252,23 +252,23 @@ static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
252 | 252 | ||
253 | if (tm->tm_sec != -1) | 253 | if (tm->tm_sec != -1) |
254 | fm3130->regs[FM3130_ALARM_SECONDS] = | 254 | fm3130->regs[FM3130_ALARM_SECONDS] = |
255 | BIN2BCD(tm->tm_sec) | 0x80; | 255 | bin2bcd(tm->tm_sec) | 0x80; |
256 | 256 | ||
257 | if (tm->tm_min != -1) | 257 | if (tm->tm_min != -1) |
258 | fm3130->regs[FM3130_ALARM_MINUTES] = | 258 | fm3130->regs[FM3130_ALARM_MINUTES] = |
259 | BIN2BCD(tm->tm_min) | 0x80; | 259 | bin2bcd(tm->tm_min) | 0x80; |
260 | 260 | ||
261 | if (tm->tm_hour != -1) | 261 | if (tm->tm_hour != -1) |
262 | fm3130->regs[FM3130_ALARM_HOURS] = | 262 | fm3130->regs[FM3130_ALARM_HOURS] = |
263 | BIN2BCD(tm->tm_hour) | 0x80; | 263 | bin2bcd(tm->tm_hour) | 0x80; |
264 | 264 | ||
265 | if (tm->tm_mday != -1) | 265 | if (tm->tm_mday != -1) |
266 | fm3130->regs[FM3130_ALARM_DATE] = | 266 | fm3130->regs[FM3130_ALARM_DATE] = |
267 | BIN2BCD(tm->tm_mday) | 0x80; | 267 | bin2bcd(tm->tm_mday) | 0x80; |
268 | 268 | ||
269 | if (tm->tm_mon != -1) | 269 | if (tm->tm_mon != -1) |
270 | fm3130->regs[FM3130_ALARM_MONTHS] = | 270 | fm3130->regs[FM3130_ALARM_MONTHS] = |
271 | BIN2BCD(tm->tm_mon + 1) | 0x80; | 271 | bin2bcd(tm->tm_mon + 1) | 0x80; |
272 | 272 | ||
273 | dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n", | 273 | dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n", |
274 | fm3130->regs[FM3130_ALARM_SECONDS], | 274 | fm3130->regs[FM3130_ALARM_SECONDS], |
@@ -414,18 +414,18 @@ static int __devinit fm3130_probe(struct i2c_client *client, | |||
414 | /* TODO */ | 414 | /* TODO */ |
415 | /* TODO need to sanity check alarm */ | 415 | /* TODO need to sanity check alarm */ |
416 | tmp = fm3130->regs[FM3130_RTC_SECONDS]; | 416 | tmp = fm3130->regs[FM3130_RTC_SECONDS]; |
417 | tmp = BCD2BIN(tmp & 0x7f); | 417 | tmp = bcd2bin(tmp & 0x7f); |
418 | if (tmp > 60) | 418 | if (tmp > 60) |
419 | goto exit_bad; | 419 | goto exit_bad; |
420 | tmp = BCD2BIN(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); | 420 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); |
421 | if (tmp > 60) | 421 | if (tmp > 60) |
422 | goto exit_bad; | 422 | goto exit_bad; |
423 | 423 | ||
424 | tmp = BCD2BIN(fm3130->regs[FM3130_RTC_DATE] & 0x3f); | 424 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f); |
425 | if (tmp == 0 || tmp > 31) | 425 | if (tmp == 0 || tmp > 31) |
426 | goto exit_bad; | 426 | goto exit_bad; |
427 | 427 | ||
428 | tmp = BCD2BIN(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f); | 428 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f); |
429 | if (tmp == 0 || tmp > 12) | 429 | if (tmp == 0 || tmp > 12) |
430 | goto exit_bad; | 430 | goto exit_bad; |
431 | 431 | ||
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index fbb90b1e4098..2cd77ab8fc66 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c | |||
@@ -259,26 +259,26 @@ isl1208_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) | |||
259 | return sr; | 259 | return sr; |
260 | } | 260 | } |
261 | 261 | ||
262 | tm->tm_sec = BCD2BIN(regs[ISL1208_REG_SC]); | 262 | tm->tm_sec = bcd2bin(regs[ISL1208_REG_SC]); |
263 | tm->tm_min = BCD2BIN(regs[ISL1208_REG_MN]); | 263 | tm->tm_min = bcd2bin(regs[ISL1208_REG_MN]); |
264 | 264 | ||
265 | /* HR field has a more complex interpretation */ | 265 | /* HR field has a more complex interpretation */ |
266 | { | 266 | { |
267 | const u8 _hr = regs[ISL1208_REG_HR]; | 267 | const u8 _hr = regs[ISL1208_REG_HR]; |
268 | if (_hr & ISL1208_REG_HR_MIL) /* 24h format */ | 268 | if (_hr & ISL1208_REG_HR_MIL) /* 24h format */ |
269 | tm->tm_hour = BCD2BIN(_hr & 0x3f); | 269 | tm->tm_hour = bcd2bin(_hr & 0x3f); |
270 | else { | 270 | else { |
271 | /* 12h format */ | 271 | /* 12h format */ |
272 | tm->tm_hour = BCD2BIN(_hr & 0x1f); | 272 | tm->tm_hour = bcd2bin(_hr & 0x1f); |
273 | if (_hr & ISL1208_REG_HR_PM) /* PM flag set */ | 273 | if (_hr & ISL1208_REG_HR_PM) /* PM flag set */ |
274 | tm->tm_hour += 12; | 274 | tm->tm_hour += 12; |
275 | } | 275 | } |
276 | } | 276 | } |
277 | 277 | ||
278 | tm->tm_mday = BCD2BIN(regs[ISL1208_REG_DT]); | 278 | tm->tm_mday = bcd2bin(regs[ISL1208_REG_DT]); |
279 | tm->tm_mon = BCD2BIN(regs[ISL1208_REG_MO]) - 1; /* rtc starts at 1 */ | 279 | tm->tm_mon = bcd2bin(regs[ISL1208_REG_MO]) - 1; /* rtc starts at 1 */ |
280 | tm->tm_year = BCD2BIN(regs[ISL1208_REG_YR]) + 100; | 280 | tm->tm_year = bcd2bin(regs[ISL1208_REG_YR]) + 100; |
281 | tm->tm_wday = BCD2BIN(regs[ISL1208_REG_DW]); | 281 | tm->tm_wday = bcd2bin(regs[ISL1208_REG_DW]); |
282 | 282 | ||
283 | return 0; | 283 | return 0; |
284 | } | 284 | } |
@@ -305,13 +305,13 @@ isl1208_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm) | |||
305 | } | 305 | } |
306 | 306 | ||
307 | /* MSB of each alarm register is an enable bit */ | 307 | /* MSB of each alarm register is an enable bit */ |
308 | tm->tm_sec = BCD2BIN(regs[ISL1208_REG_SCA - ISL1208_REG_SCA] & 0x7f); | 308 | tm->tm_sec = bcd2bin(regs[ISL1208_REG_SCA - ISL1208_REG_SCA] & 0x7f); |
309 | tm->tm_min = BCD2BIN(regs[ISL1208_REG_MNA - ISL1208_REG_SCA] & 0x7f); | 309 | tm->tm_min = bcd2bin(regs[ISL1208_REG_MNA - ISL1208_REG_SCA] & 0x7f); |
310 | tm->tm_hour = BCD2BIN(regs[ISL1208_REG_HRA - ISL1208_REG_SCA] & 0x3f); | 310 | tm->tm_hour = bcd2bin(regs[ISL1208_REG_HRA - ISL1208_REG_SCA] & 0x3f); |
311 | tm->tm_mday = BCD2BIN(regs[ISL1208_REG_DTA - ISL1208_REG_SCA] & 0x3f); | 311 | tm->tm_mday = bcd2bin(regs[ISL1208_REG_DTA - ISL1208_REG_SCA] & 0x3f); |
312 | tm->tm_mon = | 312 | tm->tm_mon = |
313 | BCD2BIN(regs[ISL1208_REG_MOA - ISL1208_REG_SCA] & 0x1f) - 1; | 313 | bcd2bin(regs[ISL1208_REG_MOA - ISL1208_REG_SCA] & 0x1f) - 1; |
314 | tm->tm_wday = BCD2BIN(regs[ISL1208_REG_DWA - ISL1208_REG_SCA] & 0x03); | 314 | tm->tm_wday = bcd2bin(regs[ISL1208_REG_DWA - ISL1208_REG_SCA] & 0x03); |
315 | 315 | ||
316 | return 0; | 316 | return 0; |
317 | } | 317 | } |
@@ -328,15 +328,15 @@ isl1208_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm) | |||
328 | int sr; | 328 | int sr; |
329 | u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, }; | 329 | u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, }; |
330 | 330 | ||
331 | regs[ISL1208_REG_SC] = BIN2BCD(tm->tm_sec); | 331 | regs[ISL1208_REG_SC] = bin2bcd(tm->tm_sec); |
332 | regs[ISL1208_REG_MN] = BIN2BCD(tm->tm_min); | 332 | regs[ISL1208_REG_MN] = bin2bcd(tm->tm_min); |
333 | regs[ISL1208_REG_HR] = BIN2BCD(tm->tm_hour) | ISL1208_REG_HR_MIL; | 333 | regs[ISL1208_REG_HR] = bin2bcd(tm->tm_hour) | ISL1208_REG_HR_MIL; |
334 | 334 | ||
335 | regs[ISL1208_REG_DT] = BIN2BCD(tm->tm_mday); | 335 | regs[ISL1208_REG_DT] = bin2bcd(tm->tm_mday); |
336 | regs[ISL1208_REG_MO] = BIN2BCD(tm->tm_mon + 1); | 336 | regs[ISL1208_REG_MO] = bin2bcd(tm->tm_mon + 1); |
337 | regs[ISL1208_REG_YR] = BIN2BCD(tm->tm_year - 100); | 337 | regs[ISL1208_REG_YR] = bin2bcd(tm->tm_year - 100); |
338 | 338 | ||
339 | regs[ISL1208_REG_DW] = BIN2BCD(tm->tm_wday & 7); | 339 | regs[ISL1208_REG_DW] = bin2bcd(tm->tm_wday & 7); |
340 | 340 | ||
341 | sr = isl1208_i2c_get_sr(client); | 341 | sr = isl1208_i2c_get_sr(client); |
342 | if (sr < 0) { | 342 | if (sr < 0) { |
@@ -482,7 +482,7 @@ isl1208_sysfs_register(struct device *dev) | |||
482 | static int | 482 | static int |
483 | isl1208_sysfs_unregister(struct device *dev) | 483 | isl1208_sysfs_unregister(struct device *dev) |
484 | { | 484 | { |
485 | device_remove_file(dev, &dev_attr_atrim); | 485 | device_remove_file(dev, &dev_attr_dtrim); |
486 | device_remove_file(dev, &dev_attr_atrim); | 486 | device_remove_file(dev, &dev_attr_atrim); |
487 | device_remove_file(dev, &dev_attr_usr); | 487 | device_remove_file(dev, &dev_attr_usr); |
488 | 488 | ||
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c index 9f996ec881ce..dd70bf73ce9d 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c | |||
@@ -51,10 +51,11 @@ EXPORT_SYMBOL(rtc_year_days); | |||
51 | */ | 51 | */ |
52 | void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) | 52 | void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) |
53 | { | 53 | { |
54 | unsigned int days, month, year; | 54 | unsigned int month, year; |
55 | int days; | ||
55 | 56 | ||
56 | days = time / 86400; | 57 | days = time / 86400; |
57 | time -= days * 86400; | 58 | time -= (unsigned int) days * 86400; |
58 | 59 | ||
59 | /* day of the week, 1970-01-01 was a Thursday */ | 60 | /* day of the week, 1970-01-01 was a Thursday */ |
60 | tm->tm_wday = (days + 4) % 7; | 61 | tm->tm_wday = (days + 4) % 7; |
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 0a19c06019be..893f7dece239 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c | |||
@@ -13,21 +13,21 @@ | |||
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/module.h> | 16 | #include <linux/bcd.h> |
17 | #include <linux/i2c.h> | ||
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
18 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/module.h> | ||
21 | #include <linux/rtc.h> | ||
19 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
20 | #include <linux/smp_lock.h> | 23 | #include <linux/smp_lock.h> |
21 | #include <linux/string.h> | 24 | #include <linux/string.h> |
22 | #include <linux/i2c.h> | ||
23 | #include <linux/rtc.h> | ||
24 | #include <linux/bcd.h> | ||
25 | #ifdef CONFIG_RTC_DRV_M41T80_WDT | 25 | #ifdef CONFIG_RTC_DRV_M41T80_WDT |
26 | #include <linux/miscdevice.h> | ||
27 | #include <linux/watchdog.h> | ||
28 | #include <linux/reboot.h> | ||
29 | #include <linux/fs.h> | 26 | #include <linux/fs.h> |
30 | #include <linux/ioctl.h> | 27 | #include <linux/ioctl.h> |
28 | #include <linux/miscdevice.h> | ||
29 | #include <linux/reboot.h> | ||
30 | #include <linux/watchdog.h> | ||
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | #define M41T80_REG_SSEC 0 | 33 | #define M41T80_REG_SSEC 0 |
@@ -56,21 +56,27 @@ | |||
56 | #define M41T80_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */ | 56 | #define M41T80_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */ |
57 | #define M41T80_FLAGS_AF (1 << 6) /* AF: Alarm Flag Bit */ | 57 | #define M41T80_FLAGS_AF (1 << 6) /* AF: Alarm Flag Bit */ |
58 | #define M41T80_FLAGS_BATT_LOW (1 << 4) /* BL: Battery Low Bit */ | 58 | #define M41T80_FLAGS_BATT_LOW (1 << 4) /* BL: Battery Low Bit */ |
59 | #define M41T80_WATCHDOG_RB2 (1 << 7) /* RB: Watchdog resolution */ | ||
60 | #define M41T80_WATCHDOG_RB1 (1 << 1) /* RB: Watchdog resolution */ | ||
61 | #define M41T80_WATCHDOG_RB0 (1 << 0) /* RB: Watchdog resolution */ | ||
59 | 62 | ||
60 | #define M41T80_FEATURE_HT (1 << 0) | 63 | #define M41T80_FEATURE_HT (1 << 0) /* Halt feature */ |
61 | #define M41T80_FEATURE_BL (1 << 1) | 64 | #define M41T80_FEATURE_BL (1 << 1) /* Battery low indicator */ |
65 | #define M41T80_FEATURE_SQ (1 << 2) /* Squarewave feature */ | ||
66 | #define M41T80_FEATURE_WD (1 << 3) /* Extra watchdog resolution */ | ||
62 | 67 | ||
63 | #define DRV_VERSION "0.05" | 68 | #define DRV_VERSION "0.05" |
64 | 69 | ||
65 | static const struct i2c_device_id m41t80_id[] = { | 70 | static const struct i2c_device_id m41t80_id[] = { |
66 | { "m41t80", 0 }, | 71 | { "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD }, |
67 | { "m41t81", M41T80_FEATURE_HT }, | 72 | { "m41t80", M41T80_FEATURE_SQ }, |
68 | { "m41t81s", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 73 | { "m41t81", M41T80_FEATURE_HT | M41T80_FEATURE_SQ}, |
69 | { "m41t82", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 74 | { "m41t81s", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
70 | { "m41t83", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 75 | { "m41t82", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
71 | { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 76 | { "m41t83", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
72 | { "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 77 | { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
73 | { "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 78 | { "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
79 | { "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, | ||
74 | { } | 80 | { } |
75 | }; | 81 | }; |
76 | MODULE_DEVICE_TABLE(i2c, m41t80_id); | 82 | MODULE_DEVICE_TABLE(i2c, m41t80_id); |
@@ -104,15 +110,15 @@ static int m41t80_get_datetime(struct i2c_client *client, | |||
104 | return -EIO; | 110 | return -EIO; |
105 | } | 111 | } |
106 | 112 | ||
107 | tm->tm_sec = BCD2BIN(buf[M41T80_REG_SEC] & 0x7f); | 113 | tm->tm_sec = bcd2bin(buf[M41T80_REG_SEC] & 0x7f); |
108 | tm->tm_min = BCD2BIN(buf[M41T80_REG_MIN] & 0x7f); | 114 | tm->tm_min = bcd2bin(buf[M41T80_REG_MIN] & 0x7f); |
109 | tm->tm_hour = BCD2BIN(buf[M41T80_REG_HOUR] & 0x3f); | 115 | tm->tm_hour = bcd2bin(buf[M41T80_REG_HOUR] & 0x3f); |
110 | tm->tm_mday = BCD2BIN(buf[M41T80_REG_DAY] & 0x3f); | 116 | tm->tm_mday = bcd2bin(buf[M41T80_REG_DAY] & 0x3f); |
111 | tm->tm_wday = buf[M41T80_REG_WDAY] & 0x07; | 117 | tm->tm_wday = buf[M41T80_REG_WDAY] & 0x07; |
112 | tm->tm_mon = BCD2BIN(buf[M41T80_REG_MON] & 0x1f) - 1; | 118 | tm->tm_mon = bcd2bin(buf[M41T80_REG_MON] & 0x1f) - 1; |
113 | 119 | ||
114 | /* assume 20YY not 19YY, and ignore the Century Bit */ | 120 | /* assume 20YY not 19YY, and ignore the Century Bit */ |
115 | tm->tm_year = BCD2BIN(buf[M41T80_REG_YEAR]) + 100; | 121 | tm->tm_year = bcd2bin(buf[M41T80_REG_YEAR]) + 100; |
116 | return 0; | 122 | return 0; |
117 | } | 123 | } |
118 | 124 | ||
@@ -155,19 +161,19 @@ static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
155 | /* Merge time-data and register flags into buf[0..7] */ | 161 | /* Merge time-data and register flags into buf[0..7] */ |
156 | buf[M41T80_REG_SSEC] = 0; | 162 | buf[M41T80_REG_SSEC] = 0; |
157 | buf[M41T80_REG_SEC] = | 163 | buf[M41T80_REG_SEC] = |
158 | BIN2BCD(tm->tm_sec) | (buf[M41T80_REG_SEC] & ~0x7f); | 164 | bin2bcd(tm->tm_sec) | (buf[M41T80_REG_SEC] & ~0x7f); |
159 | buf[M41T80_REG_MIN] = | 165 | buf[M41T80_REG_MIN] = |
160 | BIN2BCD(tm->tm_min) | (buf[M41T80_REG_MIN] & ~0x7f); | 166 | bin2bcd(tm->tm_min) | (buf[M41T80_REG_MIN] & ~0x7f); |
161 | buf[M41T80_REG_HOUR] = | 167 | buf[M41T80_REG_HOUR] = |
162 | BIN2BCD(tm->tm_hour) | (buf[M41T80_REG_HOUR] & ~0x3f) ; | 168 | bin2bcd(tm->tm_hour) | (buf[M41T80_REG_HOUR] & ~0x3f) ; |
163 | buf[M41T80_REG_WDAY] = | 169 | buf[M41T80_REG_WDAY] = |
164 | (tm->tm_wday & 0x07) | (buf[M41T80_REG_WDAY] & ~0x07); | 170 | (tm->tm_wday & 0x07) | (buf[M41T80_REG_WDAY] & ~0x07); |
165 | buf[M41T80_REG_DAY] = | 171 | buf[M41T80_REG_DAY] = |
166 | BIN2BCD(tm->tm_mday) | (buf[M41T80_REG_DAY] & ~0x3f); | 172 | bin2bcd(tm->tm_mday) | (buf[M41T80_REG_DAY] & ~0x3f); |
167 | buf[M41T80_REG_MON] = | 173 | buf[M41T80_REG_MON] = |
168 | BIN2BCD(tm->tm_mon + 1) | (buf[M41T80_REG_MON] & ~0x1f); | 174 | bin2bcd(tm->tm_mon + 1) | (buf[M41T80_REG_MON] & ~0x1f); |
169 | /* assume 20YY not 19YY */ | 175 | /* assume 20YY not 19YY */ |
170 | buf[M41T80_REG_YEAR] = BIN2BCD(tm->tm_year % 100); | 176 | buf[M41T80_REG_YEAR] = bin2bcd(tm->tm_year % 100); |
171 | 177 | ||
172 | if (i2c_transfer(client->adapter, msgs, 1) != 1) { | 178 | if (i2c_transfer(client->adapter, msgs, 1) != 1) { |
173 | dev_err(&client->dev, "write error\n"); | 179 | dev_err(&client->dev, "write error\n"); |
@@ -282,15 +288,15 @@ static int m41t80_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
282 | 288 | ||
283 | wbuf[0] = M41T80_REG_ALARM_MON; /* offset into rtc's regs */ | 289 | wbuf[0] = M41T80_REG_ALARM_MON; /* offset into rtc's regs */ |
284 | reg[M41T80_REG_ALARM_SEC] |= t->time.tm_sec >= 0 ? | 290 | reg[M41T80_REG_ALARM_SEC] |= t->time.tm_sec >= 0 ? |
285 | BIN2BCD(t->time.tm_sec) : 0x80; | 291 | bin2bcd(t->time.tm_sec) : 0x80; |
286 | reg[M41T80_REG_ALARM_MIN] |= t->time.tm_min >= 0 ? | 292 | reg[M41T80_REG_ALARM_MIN] |= t->time.tm_min >= 0 ? |
287 | BIN2BCD(t->time.tm_min) : 0x80; | 293 | bin2bcd(t->time.tm_min) : 0x80; |
288 | reg[M41T80_REG_ALARM_HOUR] |= t->time.tm_hour >= 0 ? | 294 | reg[M41T80_REG_ALARM_HOUR] |= t->time.tm_hour >= 0 ? |
289 | BIN2BCD(t->time.tm_hour) : 0x80; | 295 | bin2bcd(t->time.tm_hour) : 0x80; |
290 | reg[M41T80_REG_ALARM_DAY] |= t->time.tm_mday >= 0 ? | 296 | reg[M41T80_REG_ALARM_DAY] |= t->time.tm_mday >= 0 ? |
291 | BIN2BCD(t->time.tm_mday) : 0x80; | 297 | bin2bcd(t->time.tm_mday) : 0x80; |
292 | if (t->time.tm_mon >= 0) | 298 | if (t->time.tm_mon >= 0) |
293 | reg[M41T80_REG_ALARM_MON] |= BIN2BCD(t->time.tm_mon + 1); | 299 | reg[M41T80_REG_ALARM_MON] |= bin2bcd(t->time.tm_mon + 1); |
294 | else | 300 | else |
295 | reg[M41T80_REG_ALARM_DAY] |= 0x40; | 301 | reg[M41T80_REG_ALARM_DAY] |= 0x40; |
296 | 302 | ||
@@ -341,15 +347,15 @@ static int m41t80_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
341 | t->time.tm_mday = -1; | 347 | t->time.tm_mday = -1; |
342 | t->time.tm_mon = -1; | 348 | t->time.tm_mon = -1; |
343 | if (!(reg[M41T80_REG_ALARM_SEC] & 0x80)) | 349 | if (!(reg[M41T80_REG_ALARM_SEC] & 0x80)) |
344 | t->time.tm_sec = BCD2BIN(reg[M41T80_REG_ALARM_SEC] & 0x7f); | 350 | t->time.tm_sec = bcd2bin(reg[M41T80_REG_ALARM_SEC] & 0x7f); |
345 | if (!(reg[M41T80_REG_ALARM_MIN] & 0x80)) | 351 | if (!(reg[M41T80_REG_ALARM_MIN] & 0x80)) |
346 | t->time.tm_min = BCD2BIN(reg[M41T80_REG_ALARM_MIN] & 0x7f); | 352 | t->time.tm_min = bcd2bin(reg[M41T80_REG_ALARM_MIN] & 0x7f); |
347 | if (!(reg[M41T80_REG_ALARM_HOUR] & 0x80)) | 353 | if (!(reg[M41T80_REG_ALARM_HOUR] & 0x80)) |
348 | t->time.tm_hour = BCD2BIN(reg[M41T80_REG_ALARM_HOUR] & 0x3f); | 354 | t->time.tm_hour = bcd2bin(reg[M41T80_REG_ALARM_HOUR] & 0x3f); |
349 | if (!(reg[M41T80_REG_ALARM_DAY] & 0x80)) | 355 | if (!(reg[M41T80_REG_ALARM_DAY] & 0x80)) |
350 | t->time.tm_mday = BCD2BIN(reg[M41T80_REG_ALARM_DAY] & 0x3f); | 356 | t->time.tm_mday = bcd2bin(reg[M41T80_REG_ALARM_DAY] & 0x3f); |
351 | if (!(reg[M41T80_REG_ALARM_DAY] & 0x40)) | 357 | if (!(reg[M41T80_REG_ALARM_DAY] & 0x40)) |
352 | t->time.tm_mon = BCD2BIN(reg[M41T80_REG_ALARM_MON] & 0x1f) - 1; | 358 | t->time.tm_mon = bcd2bin(reg[M41T80_REG_ALARM_MON] & 0x1f) - 1; |
353 | t->time.tm_year = -1; | 359 | t->time.tm_year = -1; |
354 | t->time.tm_wday = -1; | 360 | t->time.tm_wday = -1; |
355 | t->time.tm_yday = -1; | 361 | t->time.tm_yday = -1; |
@@ -386,8 +392,12 @@ static ssize_t m41t80_sysfs_show_sqwfreq(struct device *dev, | |||
386 | struct device_attribute *attr, char *buf) | 392 | struct device_attribute *attr, char *buf) |
387 | { | 393 | { |
388 | struct i2c_client *client = to_i2c_client(dev); | 394 | struct i2c_client *client = to_i2c_client(dev); |
395 | struct m41t80_data *clientdata = i2c_get_clientdata(client); | ||
389 | int val; | 396 | int val; |
390 | 397 | ||
398 | if (!(clientdata->features & M41T80_FEATURE_SQ)) | ||
399 | return -EINVAL; | ||
400 | |||
391 | val = i2c_smbus_read_byte_data(client, M41T80_REG_SQW); | 401 | val = i2c_smbus_read_byte_data(client, M41T80_REG_SQW); |
392 | if (val < 0) | 402 | if (val < 0) |
393 | return -EIO; | 403 | return -EIO; |
@@ -408,9 +418,13 @@ static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev, | |||
408 | const char *buf, size_t count) | 418 | const char *buf, size_t count) |
409 | { | 419 | { |
410 | struct i2c_client *client = to_i2c_client(dev); | 420 | struct i2c_client *client = to_i2c_client(dev); |
421 | struct m41t80_data *clientdata = i2c_get_clientdata(client); | ||
411 | int almon, sqw; | 422 | int almon, sqw; |
412 | int val = simple_strtoul(buf, NULL, 0); | 423 | int val = simple_strtoul(buf, NULL, 0); |
413 | 424 | ||
425 | if (!(clientdata->features & M41T80_FEATURE_SQ)) | ||
426 | return -EINVAL; | ||
427 | |||
414 | if (val) { | 428 | if (val) { |
415 | if (!is_power_of_2(val)) | 429 | if (!is_power_of_2(val)) |
416 | return -EINVAL; | 430 | return -EINVAL; |
@@ -499,6 +513,8 @@ static void wdt_ping(void) | |||
499 | .buf = i2c_data, | 513 | .buf = i2c_data, |
500 | }, | 514 | }, |
501 | }; | 515 | }; |
516 | struct m41t80_data *clientdata = i2c_get_clientdata(save_client); | ||
517 | |||
502 | i2c_data[0] = 0x09; /* watchdog register */ | 518 | i2c_data[0] = 0x09; /* watchdog register */ |
503 | 519 | ||
504 | if (wdt_margin > 31) | 520 | if (wdt_margin > 31) |
@@ -509,6 +525,13 @@ static void wdt_ping(void) | |||
509 | */ | 525 | */ |
510 | i2c_data[1] = wdt_margin<<2 | 0x82; | 526 | i2c_data[1] = wdt_margin<<2 | 0x82; |
511 | 527 | ||
528 | /* | ||
529 | * M41T65 has three bits for watchdog resolution. Don't set bit 7, as | ||
530 | * that would be an invalid resolution. | ||
531 | */ | ||
532 | if (clientdata->features & M41T80_FEATURE_WD) | ||
533 | i2c_data[1] &= ~M41T80_WATCHDOG_RB2; | ||
534 | |||
512 | i2c_transfer(save_client->adapter, msgs1, 1); | 535 | i2c_transfer(save_client->adapter, msgs1, 1); |
513 | } | 536 | } |
514 | 537 | ||
@@ -631,14 +654,12 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
631 | return -EFAULT; | 654 | return -EFAULT; |
632 | 655 | ||
633 | if (rv & WDIOS_DISABLECARD) { | 656 | if (rv & WDIOS_DISABLECARD) { |
634 | printk(KERN_INFO | 657 | pr_info("rtc-m41t80: disable watchdog\n"); |
635 | "rtc-m41t80: disable watchdog\n"); | ||
636 | wdt_disable(); | 658 | wdt_disable(); |
637 | } | 659 | } |
638 | 660 | ||
639 | if (rv & WDIOS_ENABLECARD) { | 661 | if (rv & WDIOS_ENABLECARD) { |
640 | printk(KERN_INFO | 662 | pr_info("rtc-m41t80: enable watchdog\n"); |
641 | "rtc-m41t80: enable watchdog\n"); | ||
642 | wdt_ping(); | 663 | wdt_ping(); |
643 | } | 664 | } |
644 | 665 | ||
diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c new file mode 100644 index 000000000000..c3a18c58daf6 --- /dev/null +++ b/drivers/rtc/rtc-m41t94.c | |||
@@ -0,0 +1,173 @@ | |||
1 | /* | ||
2 | * Driver for ST M41T94 SPI RTC | ||
3 | * | ||
4 | * Copyright (C) 2008 Kim B. Heino | ||
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/module.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/rtc.h> | ||
15 | #include <linux/spi/spi.h> | ||
16 | #include <linux/bcd.h> | ||
17 | |||
18 | #define M41T94_REG_SECONDS 0x01 | ||
19 | #define M41T94_REG_MINUTES 0x02 | ||
20 | #define M41T94_REG_HOURS 0x03 | ||
21 | #define M41T94_REG_WDAY 0x04 | ||
22 | #define M41T94_REG_DAY 0x05 | ||
23 | #define M41T94_REG_MONTH 0x06 | ||
24 | #define M41T94_REG_YEAR 0x07 | ||
25 | #define M41T94_REG_HT 0x0c | ||
26 | |||
27 | #define M41T94_BIT_HALT 0x40 | ||
28 | #define M41T94_BIT_STOP 0x80 | ||
29 | #define M41T94_BIT_CB 0x40 | ||
30 | #define M41T94_BIT_CEB 0x80 | ||
31 | |||
32 | static int m41t94_set_time(struct device *dev, struct rtc_time *tm) | ||
33 | { | ||
34 | struct spi_device *spi = to_spi_device(dev); | ||
35 | u8 buf[8]; /* write cmd + 7 registers */ | ||
36 | |||
37 | dev_dbg(dev, "%s secs=%d, mins=%d, " | ||
38 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", | ||
39 | "write", tm->tm_sec, tm->tm_min, | ||
40 | tm->tm_hour, tm->tm_mday, | ||
41 | tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
42 | |||
43 | buf[0] = 0x80 | M41T94_REG_SECONDS; /* write time + date */ | ||
44 | buf[M41T94_REG_SECONDS] = bin2bcd(tm->tm_sec); | ||
45 | buf[M41T94_REG_MINUTES] = bin2bcd(tm->tm_min); | ||
46 | buf[M41T94_REG_HOURS] = bin2bcd(tm->tm_hour); | ||
47 | buf[M41T94_REG_WDAY] = bin2bcd(tm->tm_wday + 1); | ||
48 | buf[M41T94_REG_DAY] = bin2bcd(tm->tm_mday); | ||
49 | buf[M41T94_REG_MONTH] = bin2bcd(tm->tm_mon + 1); | ||
50 | |||
51 | buf[M41T94_REG_HOURS] |= M41T94_BIT_CEB; | ||
52 | if (tm->tm_year >= 100) | ||
53 | buf[M41T94_REG_HOURS] |= M41T94_BIT_CB; | ||
54 | buf[M41T94_REG_YEAR] = bin2bcd(tm->tm_year % 100); | ||
55 | |||
56 | return spi_write(spi, buf, 8); | ||
57 | } | ||
58 | |||
59 | static int m41t94_read_time(struct device *dev, struct rtc_time *tm) | ||
60 | { | ||
61 | struct spi_device *spi = to_spi_device(dev); | ||
62 | u8 buf[2]; | ||
63 | int ret, hour; | ||
64 | |||
65 | /* clear halt update bit */ | ||
66 | ret = spi_w8r8(spi, M41T94_REG_HT); | ||
67 | if (ret < 0) | ||
68 | return ret; | ||
69 | if (ret & M41T94_BIT_HALT) { | ||
70 | buf[0] = 0x80 | M41T94_REG_HT; | ||
71 | buf[1] = ret & ~M41T94_BIT_HALT; | ||
72 | spi_write(spi, buf, 2); | ||
73 | } | ||
74 | |||
75 | /* clear stop bit */ | ||
76 | ret = spi_w8r8(spi, M41T94_REG_SECONDS); | ||
77 | if (ret < 0) | ||
78 | return ret; | ||
79 | if (ret & M41T94_BIT_STOP) { | ||
80 | buf[0] = 0x80 | M41T94_REG_SECONDS; | ||
81 | buf[1] = ret & ~M41T94_BIT_STOP; | ||
82 | spi_write(spi, buf, 2); | ||
83 | } | ||
84 | |||
85 | tm->tm_sec = bcd2bin(spi_w8r8(spi, M41T94_REG_SECONDS)); | ||
86 | tm->tm_min = bcd2bin(spi_w8r8(spi, M41T94_REG_MINUTES)); | ||
87 | hour = spi_w8r8(spi, M41T94_REG_HOURS); | ||
88 | tm->tm_hour = bcd2bin(hour & 0x3f); | ||
89 | tm->tm_wday = bcd2bin(spi_w8r8(spi, M41T94_REG_WDAY)) - 1; | ||
90 | tm->tm_mday = bcd2bin(spi_w8r8(spi, M41T94_REG_DAY)); | ||
91 | tm->tm_mon = bcd2bin(spi_w8r8(spi, M41T94_REG_MONTH)) - 1; | ||
92 | tm->tm_year = bcd2bin(spi_w8r8(spi, M41T94_REG_YEAR)); | ||
93 | if ((hour & M41T94_BIT_CB) || !(hour & M41T94_BIT_CEB)) | ||
94 | tm->tm_year += 100; | ||
95 | |||
96 | dev_dbg(dev, "%s secs=%d, mins=%d, " | ||
97 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", | ||
98 | "read", tm->tm_sec, tm->tm_min, | ||
99 | tm->tm_hour, tm->tm_mday, | ||
100 | tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
101 | |||
102 | /* initial clock setting can be undefined */ | ||
103 | return rtc_valid_tm(tm); | ||
104 | } | ||
105 | |||
106 | static const struct rtc_class_ops m41t94_rtc_ops = { | ||
107 | .read_time = m41t94_read_time, | ||
108 | .set_time = m41t94_set_time, | ||
109 | }; | ||
110 | |||
111 | static struct spi_driver m41t94_driver; | ||
112 | |||
113 | static int __devinit m41t94_probe(struct spi_device *spi) | ||
114 | { | ||
115 | struct rtc_device *rtc; | ||
116 | int res; | ||
117 | |||
118 | spi->bits_per_word = 8; | ||
119 | spi_setup(spi); | ||
120 | |||
121 | res = spi_w8r8(spi, M41T94_REG_SECONDS); | ||
122 | if (res < 0) { | ||
123 | dev_err(&spi->dev, "not found.\n"); | ||
124 | return res; | ||
125 | } | ||
126 | |||
127 | rtc = rtc_device_register(m41t94_driver.driver.name, | ||
128 | &spi->dev, &m41t94_rtc_ops, THIS_MODULE); | ||
129 | if (IS_ERR(rtc)) | ||
130 | return PTR_ERR(rtc); | ||
131 | |||
132 | dev_set_drvdata(&spi->dev, rtc); | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static int __devexit m41t94_remove(struct spi_device *spi) | ||
138 | { | ||
139 | struct rtc_device *rtc = platform_get_drvdata(spi); | ||
140 | |||
141 | if (rtc) | ||
142 | rtc_device_unregister(rtc); | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static struct spi_driver m41t94_driver = { | ||
148 | .driver = { | ||
149 | .name = "rtc-m41t94", | ||
150 | .bus = &spi_bus_type, | ||
151 | .owner = THIS_MODULE, | ||
152 | }, | ||
153 | .probe = m41t94_probe, | ||
154 | .remove = __devexit_p(m41t94_remove), | ||
155 | }; | ||
156 | |||
157 | static __init int m41t94_init(void) | ||
158 | { | ||
159 | return spi_register_driver(&m41t94_driver); | ||
160 | } | ||
161 | |||
162 | module_init(m41t94_init); | ||
163 | |||
164 | static __exit void m41t94_exit(void) | ||
165 | { | ||
166 | spi_unregister_driver(&m41t94_driver); | ||
167 | } | ||
168 | |||
169 | module_exit(m41t94_exit); | ||
170 | |||
171 | MODULE_AUTHOR("Kim B. Heino <Kim.Heino@bluegiga.com>"); | ||
172 | MODULE_DESCRIPTION("Driver for ST M41T94 SPI RTC"); | ||
173 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c new file mode 100644 index 000000000000..0b2197559940 --- /dev/null +++ b/drivers/rtc/rtc-m48t35.c | |||
@@ -0,0 +1,235 @@ | |||
1 | /* | ||
2 | * Driver for the SGS-Thomson M48T35 Timekeeper RAM chip | ||
3 | * | ||
4 | * Copyright (C) 2000 Silicon Graphics, Inc. | ||
5 | * Written by Ulf Carlsson (ulfc@engr.sgi.com) | ||
6 | * | ||
7 | * Copyright (C) 2008 Thomas Bogendoerfer | ||
8 | * | ||
9 | * Based on code written by Paul Gortmaker. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/rtc.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/bcd.h> | ||
21 | #include <linux/io.h> | ||
22 | |||
23 | #define DRV_VERSION "1.0" | ||
24 | |||
25 | struct m48t35_rtc { | ||
26 | u8 pad[0x7ff8]; /* starts at 0x7ff8 */ | ||
27 | u8 control; | ||
28 | u8 sec; | ||
29 | u8 min; | ||
30 | u8 hour; | ||
31 | u8 day; | ||
32 | u8 date; | ||
33 | u8 month; | ||
34 | u8 year; | ||
35 | }; | ||
36 | |||
37 | #define M48T35_RTC_SET 0x80 | ||
38 | #define M48T35_RTC_READ 0x40 | ||
39 | |||
40 | struct m48t35_priv { | ||
41 | struct rtc_device *rtc; | ||
42 | struct m48t35_rtc __iomem *reg; | ||
43 | size_t size; | ||
44 | unsigned long baseaddr; | ||
45 | spinlock_t lock; | ||
46 | }; | ||
47 | |||
48 | static int m48t35_read_time(struct device *dev, struct rtc_time *tm) | ||
49 | { | ||
50 | struct m48t35_priv *priv = dev_get_drvdata(dev); | ||
51 | u8 control; | ||
52 | |||
53 | /* | ||
54 | * Only the values that we read from the RTC are set. We leave | ||
55 | * tm_wday, tm_yday and tm_isdst untouched. Even though the | ||
56 | * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated | ||
57 | * by the RTC when initially set to a non-zero value. | ||
58 | */ | ||
59 | spin_lock_irq(&priv->lock); | ||
60 | control = readb(&priv->reg->control); | ||
61 | writeb(control | M48T35_RTC_READ, &priv->reg->control); | ||
62 | tm->tm_sec = readb(&priv->reg->sec); | ||
63 | tm->tm_min = readb(&priv->reg->min); | ||
64 | tm->tm_hour = readb(&priv->reg->hour); | ||
65 | tm->tm_mday = readb(&priv->reg->date); | ||
66 | tm->tm_mon = readb(&priv->reg->month); | ||
67 | tm->tm_year = readb(&priv->reg->year); | ||
68 | writeb(control, &priv->reg->control); | ||
69 | spin_unlock_irq(&priv->lock); | ||
70 | |||
71 | tm->tm_sec = bcd2bin(tm->tm_sec); | ||
72 | tm->tm_min = bcd2bin(tm->tm_min); | ||
73 | tm->tm_hour = bcd2bin(tm->tm_hour); | ||
74 | tm->tm_mday = bcd2bin(tm->tm_mday); | ||
75 | tm->tm_mon = bcd2bin(tm->tm_mon); | ||
76 | tm->tm_year = bcd2bin(tm->tm_year); | ||
77 | |||
78 | /* | ||
79 | * Account for differences between how the RTC uses the values | ||
80 | * and how they are defined in a struct rtc_time; | ||
81 | */ | ||
82 | tm->tm_year += 70; | ||
83 | if (tm->tm_year <= 69) | ||
84 | tm->tm_year += 100; | ||
85 | |||
86 | tm->tm_mon--; | ||
87 | return rtc_valid_tm(tm); | ||
88 | } | ||
89 | |||
90 | static int m48t35_set_time(struct device *dev, struct rtc_time *tm) | ||
91 | { | ||
92 | struct m48t35_priv *priv = dev_get_drvdata(dev); | ||
93 | unsigned char mon, day, hrs, min, sec; | ||
94 | unsigned int yrs; | ||
95 | u8 control; | ||
96 | |||
97 | yrs = tm->tm_year + 1900; | ||
98 | mon = tm->tm_mon + 1; /* tm_mon starts at zero */ | ||
99 | day = tm->tm_mday; | ||
100 | hrs = tm->tm_hour; | ||
101 | min = tm->tm_min; | ||
102 | sec = tm->tm_sec; | ||
103 | |||
104 | if (yrs < 1970) | ||
105 | return -EINVAL; | ||
106 | |||
107 | yrs -= 1970; | ||
108 | if (yrs > 255) /* They are unsigned */ | ||
109 | return -EINVAL; | ||
110 | |||
111 | if (yrs > 169) | ||
112 | return -EINVAL; | ||
113 | |||
114 | if (yrs >= 100) | ||
115 | yrs -= 100; | ||
116 | |||
117 | sec = bin2bcd(sec); | ||
118 | min = bin2bcd(min); | ||
119 | hrs = bin2bcd(hrs); | ||
120 | day = bin2bcd(day); | ||
121 | mon = bin2bcd(mon); | ||
122 | yrs = bin2bcd(yrs); | ||
123 | |||
124 | spin_lock_irq(&priv->lock); | ||
125 | control = readb(&priv->reg->control); | ||
126 | writeb(control | M48T35_RTC_SET, &priv->reg->control); | ||
127 | writeb(yrs, &priv->reg->year); | ||
128 | writeb(mon, &priv->reg->month); | ||
129 | writeb(day, &priv->reg->date); | ||
130 | writeb(hrs, &priv->reg->hour); | ||
131 | writeb(min, &priv->reg->min); | ||
132 | writeb(sec, &priv->reg->sec); | ||
133 | writeb(control, &priv->reg->control); | ||
134 | spin_unlock_irq(&priv->lock); | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static const struct rtc_class_ops m48t35_ops = { | ||
139 | .read_time = m48t35_read_time, | ||
140 | .set_time = m48t35_set_time, | ||
141 | }; | ||
142 | |||
143 | static int __devinit m48t35_probe(struct platform_device *pdev) | ||
144 | { | ||
145 | struct rtc_device *rtc; | ||
146 | struct resource *res; | ||
147 | struct m48t35_priv *priv; | ||
148 | int ret = 0; | ||
149 | |||
150 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
151 | if (!res) | ||
152 | return -ENODEV; | ||
153 | priv = kzalloc(sizeof(struct m48t35_priv), GFP_KERNEL); | ||
154 | if (!priv) | ||
155 | return -ENOMEM; | ||
156 | |||
157 | priv->size = res->end - res->start + 1; | ||
158 | /* | ||
159 | * kludge: remove the #ifndef after ioc3 resource | ||
160 | * conflicts are resolved | ||
161 | */ | ||
162 | #ifndef CONFIG_SGI_IP27 | ||
163 | if (!request_mem_region(res->start, priv->size, pdev->name)) { | ||
164 | ret = -EBUSY; | ||
165 | goto out; | ||
166 | } | ||
167 | #endif | ||
168 | priv->baseaddr = res->start; | ||
169 | priv->reg = ioremap(priv->baseaddr, priv->size); | ||
170 | if (!priv->reg) { | ||
171 | ret = -ENOMEM; | ||
172 | goto out; | ||
173 | } | ||
174 | spin_lock_init(&priv->lock); | ||
175 | rtc = rtc_device_register("m48t35", &pdev->dev, | ||
176 | &m48t35_ops, THIS_MODULE); | ||
177 | if (IS_ERR(rtc)) { | ||
178 | ret = PTR_ERR(rtc); | ||
179 | goto out; | ||
180 | } | ||
181 | priv->rtc = rtc; | ||
182 | platform_set_drvdata(pdev, priv); | ||
183 | return 0; | ||
184 | |||
185 | out: | ||
186 | if (priv->rtc) | ||
187 | rtc_device_unregister(priv->rtc); | ||
188 | if (priv->reg) | ||
189 | iounmap(priv->reg); | ||
190 | if (priv->baseaddr) | ||
191 | release_mem_region(priv->baseaddr, priv->size); | ||
192 | kfree(priv); | ||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | static int __devexit m48t35_remove(struct platform_device *pdev) | ||
197 | { | ||
198 | struct m48t35_priv *priv = platform_get_drvdata(pdev); | ||
199 | |||
200 | rtc_device_unregister(priv->rtc); | ||
201 | iounmap(priv->reg); | ||
202 | #ifndef CONFIG_SGI_IP27 | ||
203 | release_mem_region(priv->baseaddr, priv->size); | ||
204 | #endif | ||
205 | kfree(priv); | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static struct platform_driver m48t35_platform_driver = { | ||
210 | .driver = { | ||
211 | .name = "rtc-m48t35", | ||
212 | .owner = THIS_MODULE, | ||
213 | }, | ||
214 | .probe = m48t35_probe, | ||
215 | .remove = __devexit_p(m48t35_remove), | ||
216 | }; | ||
217 | |||
218 | static int __init m48t35_init(void) | ||
219 | { | ||
220 | return platform_driver_register(&m48t35_platform_driver); | ||
221 | } | ||
222 | |||
223 | static void __exit m48t35_exit(void) | ||
224 | { | ||
225 | platform_driver_unregister(&m48t35_platform_driver); | ||
226 | } | ||
227 | |||
228 | MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>"); | ||
229 | MODULE_DESCRIPTION("M48T35 RTC driver"); | ||
230 | MODULE_LICENSE("GPL"); | ||
231 | MODULE_VERSION(DRV_VERSION); | ||
232 | MODULE_ALIAS("platform:rtc-m48t35"); | ||
233 | |||
234 | module_init(m48t35_init); | ||
235 | module_exit(m48t35_exit); | ||
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 013e6c103b9c..04b63dab6932 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c | |||
@@ -24,8 +24,9 @@ | |||
24 | #define NO_IRQ (-1) | 24 | #define NO_IRQ (-1) |
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | #define M48T59_READ(reg) pdata->read_byte(dev, reg) | 27 | #define M48T59_READ(reg) (pdata->read_byte(dev, pdata->offset + reg)) |
28 | #define M48T59_WRITE(val, reg) pdata->write_byte(dev, reg, val) | 28 | #define M48T59_WRITE(val, reg) \ |
29 | (pdata->write_byte(dev, pdata->offset + reg, val)) | ||
29 | 30 | ||
30 | #define M48T59_SET_BITS(mask, reg) \ | 31 | #define M48T59_SET_BITS(mask, reg) \ |
31 | M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg)) | 32 | M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg)) |
@@ -34,7 +35,6 @@ | |||
34 | 35 | ||
35 | struct m48t59_private { | 36 | struct m48t59_private { |
36 | void __iomem *ioaddr; | 37 | void __iomem *ioaddr; |
37 | unsigned int size; /* iomem size */ | ||
38 | int irq; | 38 | int irq; |
39 | struct rtc_device *rtc; | 39 | struct rtc_device *rtc; |
40 | spinlock_t lock; /* serialize the NVRAM and RTC access */ | 40 | spinlock_t lock; /* serialize the NVRAM and RTC access */ |
@@ -76,21 +76,22 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
76 | /* Issue the READ command */ | 76 | /* Issue the READ command */ |
77 | M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL); | 77 | M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL); |
78 | 78 | ||
79 | tm->tm_year = BCD2BIN(M48T59_READ(M48T59_YEAR)); | 79 | tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR)); |
80 | /* tm_mon is 0-11 */ | 80 | /* tm_mon is 0-11 */ |
81 | tm->tm_mon = BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1; | 81 | tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1; |
82 | tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_MDAY)); | 82 | tm->tm_mday = bcd2bin(M48T59_READ(M48T59_MDAY)); |
83 | 83 | ||
84 | val = M48T59_READ(M48T59_WDAY); | 84 | val = M48T59_READ(M48T59_WDAY); |
85 | if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) { | 85 | if ((pdata->type == M48T59RTC_TYPE_M48T59) && |
86 | (val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) { | ||
86 | dev_dbg(dev, "Century bit is enabled\n"); | 87 | dev_dbg(dev, "Century bit is enabled\n"); |
87 | tm->tm_year += 100; /* one century */ | 88 | tm->tm_year += 100; /* one century */ |
88 | } | 89 | } |
89 | 90 | ||
90 | tm->tm_wday = BCD2BIN(val & 0x07); | 91 | tm->tm_wday = bcd2bin(val & 0x07); |
91 | tm->tm_hour = BCD2BIN(M48T59_READ(M48T59_HOUR) & 0x3F); | 92 | tm->tm_hour = bcd2bin(M48T59_READ(M48T59_HOUR) & 0x3F); |
92 | tm->tm_min = BCD2BIN(M48T59_READ(M48T59_MIN) & 0x7F); | 93 | tm->tm_min = bcd2bin(M48T59_READ(M48T59_MIN) & 0x7F); |
93 | tm->tm_sec = BCD2BIN(M48T59_READ(M48T59_SEC) & 0x7F); | 94 | tm->tm_sec = bcd2bin(M48T59_READ(M48T59_SEC) & 0x7F); |
94 | 95 | ||
95 | /* Clear the READ bit */ | 96 | /* Clear the READ bit */ |
96 | M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL); | 97 | M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL); |
@@ -118,17 +119,17 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
118 | /* Issue the WRITE command */ | 119 | /* Issue the WRITE command */ |
119 | M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL); | 120 | M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL); |
120 | 121 | ||
121 | M48T59_WRITE((BIN2BCD(tm->tm_sec) & 0x7F), M48T59_SEC); | 122 | M48T59_WRITE((bin2bcd(tm->tm_sec) & 0x7F), M48T59_SEC); |
122 | M48T59_WRITE((BIN2BCD(tm->tm_min) & 0x7F), M48T59_MIN); | 123 | M48T59_WRITE((bin2bcd(tm->tm_min) & 0x7F), M48T59_MIN); |
123 | M48T59_WRITE((BIN2BCD(tm->tm_hour) & 0x3F), M48T59_HOUR); | 124 | M48T59_WRITE((bin2bcd(tm->tm_hour) & 0x3F), M48T59_HOUR); |
124 | M48T59_WRITE((BIN2BCD(tm->tm_mday) & 0x3F), M48T59_MDAY); | 125 | M48T59_WRITE((bin2bcd(tm->tm_mday) & 0x3F), M48T59_MDAY); |
125 | /* tm_mon is 0-11 */ | 126 | /* tm_mon is 0-11 */ |
126 | M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH); | 127 | M48T59_WRITE((bin2bcd(tm->tm_mon + 1) & 0x1F), M48T59_MONTH); |
127 | M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR); | 128 | M48T59_WRITE(bin2bcd(tm->tm_year % 100), M48T59_YEAR); |
128 | 129 | ||
129 | if (tm->tm_year/100) | 130 | if (pdata->type == M48T59RTC_TYPE_M48T59 && (tm->tm_year / 100)) |
130 | val = (M48T59_WDAY_CEB | M48T59_WDAY_CB); | 131 | val = (M48T59_WDAY_CEB | M48T59_WDAY_CB); |
131 | val |= (BIN2BCD(tm->tm_wday) & 0x07); | 132 | val |= (bin2bcd(tm->tm_wday) & 0x07); |
132 | M48T59_WRITE(val, M48T59_WDAY); | 133 | M48T59_WRITE(val, M48T59_WDAY); |
133 | 134 | ||
134 | /* Clear the WRITE bit */ | 135 | /* Clear the WRITE bit */ |
@@ -157,18 +158,18 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
157 | /* Issue the READ command */ | 158 | /* Issue the READ command */ |
158 | M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL); | 159 | M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL); |
159 | 160 | ||
160 | tm->tm_year = BCD2BIN(M48T59_READ(M48T59_YEAR)); | 161 | tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR)); |
161 | /* tm_mon is 0-11 */ | 162 | /* tm_mon is 0-11 */ |
162 | tm->tm_mon = BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1; | 163 | tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1; |
163 | 164 | ||
164 | val = M48T59_READ(M48T59_WDAY); | 165 | val = M48T59_READ(M48T59_WDAY); |
165 | if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) | 166 | if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) |
166 | tm->tm_year += 100; /* one century */ | 167 | tm->tm_year += 100; /* one century */ |
167 | 168 | ||
168 | tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_ALARM_DATE)); | 169 | tm->tm_mday = bcd2bin(M48T59_READ(M48T59_ALARM_DATE)); |
169 | tm->tm_hour = BCD2BIN(M48T59_READ(M48T59_ALARM_HOUR)); | 170 | tm->tm_hour = bcd2bin(M48T59_READ(M48T59_ALARM_HOUR)); |
170 | tm->tm_min = BCD2BIN(M48T59_READ(M48T59_ALARM_MIN)); | 171 | tm->tm_min = bcd2bin(M48T59_READ(M48T59_ALARM_MIN)); |
171 | tm->tm_sec = BCD2BIN(M48T59_READ(M48T59_ALARM_SEC)); | 172 | tm->tm_sec = bcd2bin(M48T59_READ(M48T59_ALARM_SEC)); |
172 | 173 | ||
173 | /* Clear the READ bit */ | 174 | /* Clear the READ bit */ |
174 | M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL); | 175 | M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL); |
@@ -200,18 +201,18 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
200 | * 0xff means "always match" | 201 | * 0xff means "always match" |
201 | */ | 202 | */ |
202 | mday = tm->tm_mday; | 203 | mday = tm->tm_mday; |
203 | mday = (mday >= 1 && mday <= 31) ? BIN2BCD(mday) : 0xff; | 204 | mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff; |
204 | if (mday == 0xff) | 205 | if (mday == 0xff) |
205 | mday = M48T59_READ(M48T59_MDAY); | 206 | mday = M48T59_READ(M48T59_MDAY); |
206 | 207 | ||
207 | hour = tm->tm_hour; | 208 | hour = tm->tm_hour; |
208 | hour = (hour < 24) ? BIN2BCD(hour) : 0x00; | 209 | hour = (hour < 24) ? bin2bcd(hour) : 0x00; |
209 | 210 | ||
210 | min = tm->tm_min; | 211 | min = tm->tm_min; |
211 | min = (min < 60) ? BIN2BCD(min) : 0x00; | 212 | min = (min < 60) ? bin2bcd(min) : 0x00; |
212 | 213 | ||
213 | sec = tm->tm_sec; | 214 | sec = tm->tm_sec; |
214 | sec = (sec < 60) ? BIN2BCD(sec) : 0x00; | 215 | sec = (sec < 60) ? bin2bcd(sec) : 0x00; |
215 | 216 | ||
216 | spin_lock_irqsave(&m48t59->lock, flags); | 217 | spin_lock_irqsave(&m48t59->lock, flags); |
217 | /* Issue the WRITE command */ | 218 | /* Issue the WRITE command */ |
@@ -310,6 +311,11 @@ static const struct rtc_class_ops m48t59_rtc_ops = { | |||
310 | .proc = m48t59_rtc_proc, | 311 | .proc = m48t59_rtc_proc, |
311 | }; | 312 | }; |
312 | 313 | ||
314 | static const struct rtc_class_ops m48t02_rtc_ops = { | ||
315 | .read_time = m48t59_rtc_read_time, | ||
316 | .set_time = m48t59_rtc_set_time, | ||
317 | }; | ||
318 | |||
313 | static ssize_t m48t59_nvram_read(struct kobject *kobj, | 319 | static ssize_t m48t59_nvram_read(struct kobject *kobj, |
314 | struct bin_attribute *bin_attr, | 320 | struct bin_attribute *bin_attr, |
315 | char *buf, loff_t pos, size_t size) | 321 | char *buf, loff_t pos, size_t size) |
@@ -321,7 +327,7 @@ static ssize_t m48t59_nvram_read(struct kobject *kobj, | |||
321 | ssize_t cnt = 0; | 327 | ssize_t cnt = 0; |
322 | unsigned long flags; | 328 | unsigned long flags; |
323 | 329 | ||
324 | for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { | 330 | for (; size > 0 && pos < pdata->offset; cnt++, size--) { |
325 | spin_lock_irqsave(&m48t59->lock, flags); | 331 | spin_lock_irqsave(&m48t59->lock, flags); |
326 | *buf++ = M48T59_READ(cnt); | 332 | *buf++ = M48T59_READ(cnt); |
327 | spin_unlock_irqrestore(&m48t59->lock, flags); | 333 | spin_unlock_irqrestore(&m48t59->lock, flags); |
@@ -341,7 +347,7 @@ static ssize_t m48t59_nvram_write(struct kobject *kobj, | |||
341 | ssize_t cnt = 0; | 347 | ssize_t cnt = 0; |
342 | unsigned long flags; | 348 | unsigned long flags; |
343 | 349 | ||
344 | for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { | 350 | for (; size > 0 && pos < pdata->offset; cnt++, size--) { |
345 | spin_lock_irqsave(&m48t59->lock, flags); | 351 | spin_lock_irqsave(&m48t59->lock, flags); |
346 | M48T59_WRITE(*buf++, cnt); | 352 | M48T59_WRITE(*buf++, cnt); |
347 | spin_unlock_irqrestore(&m48t59->lock, flags); | 353 | spin_unlock_irqrestore(&m48t59->lock, flags); |
@@ -354,11 +360,9 @@ static struct bin_attribute m48t59_nvram_attr = { | |||
354 | .attr = { | 360 | .attr = { |
355 | .name = "nvram", | 361 | .name = "nvram", |
356 | .mode = S_IRUGO | S_IWUSR, | 362 | .mode = S_IRUGO | S_IWUSR, |
357 | .owner = THIS_MODULE, | ||
358 | }, | 363 | }, |
359 | .read = m48t59_nvram_read, | 364 | .read = m48t59_nvram_read, |
360 | .write = m48t59_nvram_write, | 365 | .write = m48t59_nvram_write, |
361 | .size = M48T59_NVRAM_SIZE, | ||
362 | }; | 366 | }; |
363 | 367 | ||
364 | static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | 368 | static int __devinit m48t59_rtc_probe(struct platform_device *pdev) |
@@ -367,6 +371,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
367 | struct m48t59_private *m48t59 = NULL; | 371 | struct m48t59_private *m48t59 = NULL; |
368 | struct resource *res; | 372 | struct resource *res; |
369 | int ret = -ENOMEM; | 373 | int ret = -ENOMEM; |
374 | char *name; | ||
375 | const struct rtc_class_ops *ops; | ||
370 | 376 | ||
371 | /* This chip could be memory-mapped or I/O-mapped */ | 377 | /* This chip could be memory-mapped or I/O-mapped */ |
372 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 378 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -391,6 +397,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
391 | /* Ensure we only kmalloc platform data once */ | 397 | /* Ensure we only kmalloc platform data once */ |
392 | pdev->dev.platform_data = pdata; | 398 | pdev->dev.platform_data = pdata; |
393 | } | 399 | } |
400 | if (!pdata->type) | ||
401 | pdata->type = M48T59RTC_TYPE_M48T59; | ||
394 | 402 | ||
395 | /* Try to use the generic memory read/write ops */ | 403 | /* Try to use the generic memory read/write ops */ |
396 | if (!pdata->write_byte) | 404 | if (!pdata->write_byte) |
@@ -403,10 +411,14 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
403 | if (!m48t59) | 411 | if (!m48t59) |
404 | return -ENOMEM; | 412 | return -ENOMEM; |
405 | 413 | ||
406 | m48t59->size = res->end - res->start + 1; | 414 | m48t59->ioaddr = pdata->ioaddr; |
407 | m48t59->ioaddr = ioremap(res->start, m48t59->size); | 415 | |
408 | if (!m48t59->ioaddr) | 416 | if (!m48t59->ioaddr) { |
409 | goto out; | 417 | /* ioaddr not mapped externally */ |
418 | m48t59->ioaddr = ioremap(res->start, res->end - res->start + 1); | ||
419 | if (!m48t59->ioaddr) | ||
420 | goto out; | ||
421 | } | ||
410 | 422 | ||
411 | /* Try to get irq number. We also can work in | 423 | /* Try to get irq number. We also can work in |
412 | * the mode without IRQ. | 424 | * the mode without IRQ. |
@@ -421,14 +433,36 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
421 | if (ret) | 433 | if (ret) |
422 | goto out; | 434 | goto out; |
423 | } | 435 | } |
436 | switch (pdata->type) { | ||
437 | case M48T59RTC_TYPE_M48T59: | ||
438 | name = "m48t59"; | ||
439 | ops = &m48t59_rtc_ops; | ||
440 | pdata->offset = 0x1ff0; | ||
441 | break; | ||
442 | case M48T59RTC_TYPE_M48T02: | ||
443 | name = "m48t02"; | ||
444 | ops = &m48t02_rtc_ops; | ||
445 | pdata->offset = 0x7f0; | ||
446 | break; | ||
447 | case M48T59RTC_TYPE_M48T08: | ||
448 | name = "m48t08"; | ||
449 | ops = &m48t02_rtc_ops; | ||
450 | pdata->offset = 0x1ff0; | ||
451 | break; | ||
452 | default: | ||
453 | dev_err(&pdev->dev, "Unknown RTC type\n"); | ||
454 | ret = -ENODEV; | ||
455 | goto out; | ||
456 | } | ||
424 | 457 | ||
425 | m48t59->rtc = rtc_device_register("m48t59", &pdev->dev, | 458 | m48t59->rtc = rtc_device_register(name, &pdev->dev, ops, THIS_MODULE); |
426 | &m48t59_rtc_ops, THIS_MODULE); | ||
427 | if (IS_ERR(m48t59->rtc)) { | 459 | if (IS_ERR(m48t59->rtc)) { |
428 | ret = PTR_ERR(m48t59->rtc); | 460 | ret = PTR_ERR(m48t59->rtc); |
429 | goto out; | 461 | goto out; |
430 | } | 462 | } |
431 | 463 | ||
464 | m48t59_nvram_attr.size = pdata->offset; | ||
465 | |||
432 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); | 466 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); |
433 | if (ret) | 467 | if (ret) |
434 | goto out; | 468 | goto out; |
@@ -452,11 +486,12 @@ out: | |||
452 | static int __devexit m48t59_rtc_remove(struct platform_device *pdev) | 486 | static int __devexit m48t59_rtc_remove(struct platform_device *pdev) |
453 | { | 487 | { |
454 | struct m48t59_private *m48t59 = platform_get_drvdata(pdev); | 488 | struct m48t59_private *m48t59 = platform_get_drvdata(pdev); |
489 | struct m48t59_plat_data *pdata = pdev->dev.platform_data; | ||
455 | 490 | ||
456 | sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); | 491 | sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); |
457 | if (!IS_ERR(m48t59->rtc)) | 492 | if (!IS_ERR(m48t59->rtc)) |
458 | rtc_device_unregister(m48t59->rtc); | 493 | rtc_device_unregister(m48t59->rtc); |
459 | if (m48t59->ioaddr) | 494 | if (m48t59->ioaddr && !pdata->ioaddr) |
460 | iounmap(m48t59->ioaddr); | 495 | iounmap(m48t59->ioaddr); |
461 | if (m48t59->irq != NO_IRQ) | 496 | if (m48t59->irq != NO_IRQ) |
462 | free_irq(m48t59->irq, &pdev->dev); | 497 | free_irq(m48t59->irq, &pdev->dev); |
@@ -491,5 +526,5 @@ module_init(m48t59_rtc_init); | |||
491 | module_exit(m48t59_rtc_exit); | 526 | module_exit(m48t59_rtc_exit); |
492 | 527 | ||
493 | MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); | 528 | MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); |
494 | MODULE_DESCRIPTION("M48T59 RTC driver"); | 529 | MODULE_DESCRIPTION("M48T59/M48T02/M48T08 RTC driver"); |
495 | MODULE_LICENSE("GPL"); | 530 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index 3f7f99a5d96a..7c045cffa9ff 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c | |||
@@ -62,14 +62,14 @@ static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
62 | tm->tm_wday = ops->readbyte(M48T86_REG_DOW); | 62 | tm->tm_wday = ops->readbyte(M48T86_REG_DOW); |
63 | } else { | 63 | } else { |
64 | /* bcd mode */ | 64 | /* bcd mode */ |
65 | tm->tm_sec = BCD2BIN(ops->readbyte(M48T86_REG_SEC)); | 65 | tm->tm_sec = bcd2bin(ops->readbyte(M48T86_REG_SEC)); |
66 | tm->tm_min = BCD2BIN(ops->readbyte(M48T86_REG_MIN)); | 66 | tm->tm_min = bcd2bin(ops->readbyte(M48T86_REG_MIN)); |
67 | tm->tm_hour = BCD2BIN(ops->readbyte(M48T86_REG_HOUR) & 0x3F); | 67 | tm->tm_hour = bcd2bin(ops->readbyte(M48T86_REG_HOUR) & 0x3F); |
68 | tm->tm_mday = BCD2BIN(ops->readbyte(M48T86_REG_DOM)); | 68 | tm->tm_mday = bcd2bin(ops->readbyte(M48T86_REG_DOM)); |
69 | /* tm_mon is 0-11 */ | 69 | /* tm_mon is 0-11 */ |
70 | tm->tm_mon = BCD2BIN(ops->readbyte(M48T86_REG_MONTH)) - 1; | 70 | tm->tm_mon = bcd2bin(ops->readbyte(M48T86_REG_MONTH)) - 1; |
71 | tm->tm_year = BCD2BIN(ops->readbyte(M48T86_REG_YEAR)) + 100; | 71 | tm->tm_year = bcd2bin(ops->readbyte(M48T86_REG_YEAR)) + 100; |
72 | tm->tm_wday = BCD2BIN(ops->readbyte(M48T86_REG_DOW)); | 72 | tm->tm_wday = bcd2bin(ops->readbyte(M48T86_REG_DOW)); |
73 | } | 73 | } |
74 | 74 | ||
75 | /* correct the hour if the clock is in 12h mode */ | 75 | /* correct the hour if the clock is in 12h mode */ |
@@ -103,13 +103,13 @@ static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
103 | ops->writebyte(tm->tm_wday, M48T86_REG_DOW); | 103 | ops->writebyte(tm->tm_wday, M48T86_REG_DOW); |
104 | } else { | 104 | } else { |
105 | /* bcd mode */ | 105 | /* bcd mode */ |
106 | ops->writebyte(BIN2BCD(tm->tm_sec), M48T86_REG_SEC); | 106 | ops->writebyte(bin2bcd(tm->tm_sec), M48T86_REG_SEC); |
107 | ops->writebyte(BIN2BCD(tm->tm_min), M48T86_REG_MIN); | 107 | ops->writebyte(bin2bcd(tm->tm_min), M48T86_REG_MIN); |
108 | ops->writebyte(BIN2BCD(tm->tm_hour), M48T86_REG_HOUR); | 108 | ops->writebyte(bin2bcd(tm->tm_hour), M48T86_REG_HOUR); |
109 | ops->writebyte(BIN2BCD(tm->tm_mday), M48T86_REG_DOM); | 109 | ops->writebyte(bin2bcd(tm->tm_mday), M48T86_REG_DOM); |
110 | ops->writebyte(BIN2BCD(tm->tm_mon + 1), M48T86_REG_MONTH); | 110 | ops->writebyte(bin2bcd(tm->tm_mon + 1), M48T86_REG_MONTH); |
111 | ops->writebyte(BIN2BCD(tm->tm_year % 100), M48T86_REG_YEAR); | 111 | ops->writebyte(bin2bcd(tm->tm_year % 100), M48T86_REG_YEAR); |
112 | ops->writebyte(BIN2BCD(tm->tm_wday), M48T86_REG_DOW); | 112 | ops->writebyte(bin2bcd(tm->tm_wday), M48T86_REG_DOW); |
113 | } | 113 | } |
114 | 114 | ||
115 | /* update ended */ | 115 | /* update ended */ |
diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c index ded3c0abad83..80782798763f 100644 --- a/drivers/rtc/rtc-max6900.c +++ b/drivers/rtc/rtc-max6900.c | |||
@@ -17,19 +17,18 @@ | |||
17 | #include <linux/rtc.h> | 17 | #include <linux/rtc.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | 19 | ||
20 | #define DRV_NAME "max6900" | 20 | #define DRV_VERSION "0.2" |
21 | #define DRV_VERSION "0.1" | ||
22 | 21 | ||
23 | /* | 22 | /* |
24 | * register indices | 23 | * register indices |
25 | */ | 24 | */ |
26 | #define MAX6900_REG_SC 0 /* seconds 00-59 */ | 25 | #define MAX6900_REG_SC 0 /* seconds 00-59 */ |
27 | #define MAX6900_REG_MN 1 /* minutes 00-59 */ | 26 | #define MAX6900_REG_MN 1 /* minutes 00-59 */ |
28 | #define MAX6900_REG_HR 2 /* hours 00-23 */ | 27 | #define MAX6900_REG_HR 2 /* hours 00-23 */ |
29 | #define MAX6900_REG_DT 3 /* day of month 00-31 */ | 28 | #define MAX6900_REG_DT 3 /* day of month 00-31 */ |
30 | #define MAX6900_REG_MO 4 /* month 01-12 */ | 29 | #define MAX6900_REG_MO 4 /* month 01-12 */ |
31 | #define MAX6900_REG_DW 5 /* day of week 1-7 */ | 30 | #define MAX6900_REG_DW 5 /* day of week 1-7 */ |
32 | #define MAX6900_REG_YR 6 /* year 00-99 */ | 31 | #define MAX6900_REG_YR 6 /* year 00-99 */ |
33 | #define MAX6900_REG_CT 7 /* control */ | 32 | #define MAX6900_REG_CT 7 /* control */ |
34 | /* register 8 is undocumented */ | 33 | /* register 8 is undocumented */ |
35 | #define MAX6900_REG_CENTURY 9 /* century */ | 34 | #define MAX6900_REG_CENTURY 9 /* century */ |
@@ -39,7 +38,6 @@ | |||
39 | 38 | ||
40 | #define MAX6900_REG_CT_WP (1 << 7) /* Write Protect */ | 39 | #define MAX6900_REG_CT_WP (1 << 7) /* Write Protect */ |
41 | 40 | ||
42 | |||
43 | /* | 41 | /* |
44 | * register read/write commands | 42 | * register read/write commands |
45 | */ | 43 | */ |
@@ -52,16 +50,7 @@ | |||
52 | 50 | ||
53 | #define MAX6900_IDLE_TIME_AFTER_WRITE 3 /* specification says 2.5 mS */ | 51 | #define MAX6900_IDLE_TIME_AFTER_WRITE 3 /* specification says 2.5 mS */ |
54 | 52 | ||
55 | #define MAX6900_I2C_ADDR 0xa0 | 53 | static struct i2c_driver max6900_driver; |
56 | |||
57 | static const unsigned short normal_i2c[] = { | ||
58 | MAX6900_I2C_ADDR >> 1, | ||
59 | I2C_CLIENT_END | ||
60 | }; | ||
61 | |||
62 | I2C_CLIENT_INSMOD; /* defines addr_data */ | ||
63 | |||
64 | static int max6900_probe(struct i2c_adapter *adapter, int addr, int kind); | ||
65 | 54 | ||
66 | static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf) | 55 | static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf) |
67 | { | 56 | { |
@@ -69,36 +58,35 @@ static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf) | |||
69 | u8 reg_century_read[1] = { MAX6900_REG_CENTURY_READ }; | 58 | u8 reg_century_read[1] = { MAX6900_REG_CENTURY_READ }; |
70 | struct i2c_msg msgs[4] = { | 59 | struct i2c_msg msgs[4] = { |
71 | { | 60 | { |
72 | .addr = client->addr, | 61 | .addr = client->addr, |
73 | .flags = 0, /* write */ | 62 | .flags = 0, /* write */ |
74 | .len = sizeof(reg_burst_read), | 63 | .len = sizeof(reg_burst_read), |
75 | .buf = reg_burst_read | 64 | .buf = reg_burst_read} |
76 | }, | 65 | , |
77 | { | 66 | { |
78 | .addr = client->addr, | 67 | .addr = client->addr, |
79 | .flags = I2C_M_RD, | 68 | .flags = I2C_M_RD, |
80 | .len = MAX6900_BURST_LEN, | 69 | .len = MAX6900_BURST_LEN, |
81 | .buf = buf | 70 | .buf = buf} |
82 | }, | 71 | , |
83 | { | 72 | { |
84 | .addr = client->addr, | 73 | .addr = client->addr, |
85 | .flags = 0, /* write */ | 74 | .flags = 0, /* write */ |
86 | .len = sizeof(reg_century_read), | 75 | .len = sizeof(reg_century_read), |
87 | .buf = reg_century_read | 76 | .buf = reg_century_read} |
88 | }, | 77 | , |
89 | { | 78 | { |
90 | .addr = client->addr, | 79 | .addr = client->addr, |
91 | .flags = I2C_M_RD, | 80 | .flags = I2C_M_RD, |
92 | .len = sizeof(buf[MAX6900_REG_CENTURY]), | 81 | .len = sizeof(buf[MAX6900_REG_CENTURY]), |
93 | .buf = &buf[MAX6900_REG_CENTURY] | 82 | .buf = &buf[MAX6900_REG_CENTURY] |
94 | } | 83 | } |
95 | }; | 84 | }; |
96 | int rc; | 85 | int rc; |
97 | 86 | ||
98 | rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | 87 | rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); |
99 | if (rc != ARRAY_SIZE(msgs)) { | 88 | if (rc != ARRAY_SIZE(msgs)) { |
100 | dev_err(&client->dev, "%s: register read failed\n", | 89 | dev_err(&client->dev, "%s: register read failed\n", __func__); |
101 | __func__); | ||
102 | return -EIO; | 90 | return -EIO; |
103 | } | 91 | } |
104 | return 0; | 92 | return 0; |
@@ -109,20 +97,18 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf) | |||
109 | u8 i2c_century_buf[1 + 1] = { MAX6900_REG_CENTURY_WRITE }; | 97 | u8 i2c_century_buf[1 + 1] = { MAX6900_REG_CENTURY_WRITE }; |
110 | struct i2c_msg century_msgs[1] = { | 98 | struct i2c_msg century_msgs[1] = { |
111 | { | 99 | { |
112 | .addr = client->addr, | 100 | .addr = client->addr, |
113 | .flags = 0, /* write */ | 101 | .flags = 0, /* write */ |
114 | .len = sizeof(i2c_century_buf), | 102 | .len = sizeof(i2c_century_buf), |
115 | .buf = i2c_century_buf | 103 | .buf = i2c_century_buf} |
116 | } | ||
117 | }; | 104 | }; |
118 | u8 i2c_burst_buf[MAX6900_BURST_LEN + 1] = { MAX6900_REG_BURST_WRITE }; | 105 | u8 i2c_burst_buf[MAX6900_BURST_LEN + 1] = { MAX6900_REG_BURST_WRITE }; |
119 | struct i2c_msg burst_msgs[1] = { | 106 | struct i2c_msg burst_msgs[1] = { |
120 | { | 107 | { |
121 | .addr = client->addr, | 108 | .addr = client->addr, |
122 | .flags = 0, /* write */ | 109 | .flags = 0, /* write */ |
123 | .len = sizeof(i2c_burst_buf), | 110 | .len = sizeof(i2c_burst_buf), |
124 | .buf = i2c_burst_buf | 111 | .buf = i2c_burst_buf} |
125 | } | ||
126 | }; | 112 | }; |
127 | int rc; | 113 | int rc; |
128 | 114 | ||
@@ -133,10 +119,12 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf) | |||
133 | * bit as part of the burst write. | 119 | * bit as part of the burst write. |
134 | */ | 120 | */ |
135 | i2c_century_buf[1] = buf[MAX6900_REG_CENTURY]; | 121 | i2c_century_buf[1] = buf[MAX6900_REG_CENTURY]; |
122 | |||
136 | rc = i2c_transfer(client->adapter, century_msgs, | 123 | rc = i2c_transfer(client->adapter, century_msgs, |
137 | ARRAY_SIZE(century_msgs)); | 124 | ARRAY_SIZE(century_msgs)); |
138 | if (rc != ARRAY_SIZE(century_msgs)) | 125 | if (rc != ARRAY_SIZE(century_msgs)) |
139 | goto write_failed; | 126 | goto write_failed; |
127 | |||
140 | msleep(MAX6900_IDLE_TIME_AFTER_WRITE); | 128 | msleep(MAX6900_IDLE_TIME_AFTER_WRITE); |
141 | 129 | ||
142 | memcpy(&i2c_burst_buf[1], buf, MAX6900_BURST_LEN); | 130 | memcpy(&i2c_burst_buf[1], buf, MAX6900_BURST_LEN); |
@@ -148,45 +136,11 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf) | |||
148 | 136 | ||
149 | return 0; | 137 | return 0; |
150 | 138 | ||
151 | write_failed: | 139 | write_failed: |
152 | dev_err(&client->dev, "%s: register write failed\n", | 140 | dev_err(&client->dev, "%s: register write failed\n", __func__); |
153 | __func__); | ||
154 | return -EIO; | 141 | return -EIO; |
155 | } | 142 | } |
156 | 143 | ||
157 | static int max6900_i2c_validate_client(struct i2c_client *client) | ||
158 | { | ||
159 | u8 regs[MAX6900_REG_LEN]; | ||
160 | u8 zero_mask[] = { | ||
161 | 0x80, /* seconds */ | ||
162 | 0x80, /* minutes */ | ||
163 | 0x40, /* hours */ | ||
164 | 0xc0, /* day of month */ | ||
165 | 0xe0, /* month */ | ||
166 | 0xf8, /* day of week */ | ||
167 | 0x00, /* year */ | ||
168 | 0x7f, /* control */ | ||
169 | }; | ||
170 | int i; | ||
171 | int rc; | ||
172 | int reserved; | ||
173 | |||
174 | reserved = i2c_smbus_read_byte_data(client, MAX6900_REG_RESERVED_READ); | ||
175 | if (reserved != 0x07) | ||
176 | return -ENODEV; | ||
177 | |||
178 | rc = max6900_i2c_read_regs(client, regs); | ||
179 | if (rc < 0) | ||
180 | return rc; | ||
181 | |||
182 | for (i = 0; i < ARRAY_SIZE(zero_mask); ++i) { | ||
183 | if (regs[i] & zero_mask[i]) | ||
184 | return -ENODEV; | ||
185 | } | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) | 144 | static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) |
191 | { | 145 | { |
192 | int rc; | 146 | int rc; |
@@ -196,14 +150,14 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) | |||
196 | if (rc < 0) | 150 | if (rc < 0) |
197 | return rc; | 151 | return rc; |
198 | 152 | ||
199 | tm->tm_sec = BCD2BIN(regs[MAX6900_REG_SC]); | 153 | tm->tm_sec = bcd2bin(regs[MAX6900_REG_SC]); |
200 | tm->tm_min = BCD2BIN(regs[MAX6900_REG_MN]); | 154 | tm->tm_min = bcd2bin(regs[MAX6900_REG_MN]); |
201 | tm->tm_hour = BCD2BIN(regs[MAX6900_REG_HR] & 0x3f); | 155 | tm->tm_hour = bcd2bin(regs[MAX6900_REG_HR] & 0x3f); |
202 | tm->tm_mday = BCD2BIN(regs[MAX6900_REG_DT]); | 156 | tm->tm_mday = bcd2bin(regs[MAX6900_REG_DT]); |
203 | tm->tm_mon = BCD2BIN(regs[MAX6900_REG_MO]) - 1; | 157 | tm->tm_mon = bcd2bin(regs[MAX6900_REG_MO]) - 1; |
204 | tm->tm_year = BCD2BIN(regs[MAX6900_REG_YR]) + | 158 | tm->tm_year = bcd2bin(regs[MAX6900_REG_YR]) + |
205 | BCD2BIN(regs[MAX6900_REG_CENTURY]) * 100 - 1900; | 159 | bcd2bin(regs[MAX6900_REG_CENTURY]) * 100 - 1900; |
206 | tm->tm_wday = BCD2BIN(regs[MAX6900_REG_DW]); | 160 | tm->tm_wday = bcd2bin(regs[MAX6900_REG_DW]); |
207 | 161 | ||
208 | return 0; | 162 | return 0; |
209 | } | 163 | } |
@@ -211,7 +165,7 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) | |||
211 | static int max6900_i2c_clear_write_protect(struct i2c_client *client) | 165 | static int max6900_i2c_clear_write_protect(struct i2c_client *client) |
212 | { | 166 | { |
213 | int rc; | 167 | int rc; |
214 | rc = i2c_smbus_write_byte_data (client, MAX6900_REG_CONTROL_WRITE, 0); | 168 | rc = i2c_smbus_write_byte_data(client, MAX6900_REG_CONTROL_WRITE, 0); |
215 | if (rc < 0) { | 169 | if (rc < 0) { |
216 | dev_err(&client->dev, "%s: control register write failed\n", | 170 | dev_err(&client->dev, "%s: control register write failed\n", |
217 | __func__); | 171 | __func__); |
@@ -220,8 +174,8 @@ static int max6900_i2c_clear_write_protect(struct i2c_client *client) | |||
220 | return 0; | 174 | return 0; |
221 | } | 175 | } |
222 | 176 | ||
223 | static int max6900_i2c_set_time(struct i2c_client *client, | 177 | static int |
224 | struct rtc_time const *tm) | 178 | max6900_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm) |
225 | { | 179 | { |
226 | u8 regs[MAX6900_REG_LEN]; | 180 | u8 regs[MAX6900_REG_LEN]; |
227 | int rc; | 181 | int rc; |
@@ -230,14 +184,14 @@ static int max6900_i2c_set_time(struct i2c_client *client, | |||
230 | if (rc < 0) | 184 | if (rc < 0) |
231 | return rc; | 185 | return rc; |
232 | 186 | ||
233 | regs[MAX6900_REG_SC] = BIN2BCD(tm->tm_sec); | 187 | regs[MAX6900_REG_SC] = bin2bcd(tm->tm_sec); |
234 | regs[MAX6900_REG_MN] = BIN2BCD(tm->tm_min); | 188 | regs[MAX6900_REG_MN] = bin2bcd(tm->tm_min); |
235 | regs[MAX6900_REG_HR] = BIN2BCD(tm->tm_hour); | 189 | regs[MAX6900_REG_HR] = bin2bcd(tm->tm_hour); |
236 | regs[MAX6900_REG_DT] = BIN2BCD(tm->tm_mday); | 190 | regs[MAX6900_REG_DT] = bin2bcd(tm->tm_mday); |
237 | regs[MAX6900_REG_MO] = BIN2BCD(tm->tm_mon + 1); | 191 | regs[MAX6900_REG_MO] = bin2bcd(tm->tm_mon + 1); |
238 | regs[MAX6900_REG_DW] = BIN2BCD(tm->tm_wday); | 192 | regs[MAX6900_REG_DW] = bin2bcd(tm->tm_wday); |
239 | regs[MAX6900_REG_YR] = BIN2BCD(tm->tm_year % 100); | 193 | regs[MAX6900_REG_YR] = bin2bcd(tm->tm_year % 100); |
240 | regs[MAX6900_REG_CENTURY] = BIN2BCD((tm->tm_year + 1900) / 100); | 194 | regs[MAX6900_REG_CENTURY] = bin2bcd((tm->tm_year + 1900) / 100); |
241 | /* set write protect */ | 195 | /* set write protect */ |
242 | regs[MAX6900_REG_CT] = MAX6900_REG_CT_WP; | 196 | regs[MAX6900_REG_CT] = MAX6900_REG_CT_WP; |
243 | 197 | ||
@@ -258,89 +212,49 @@ static int max6900_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
258 | return max6900_i2c_set_time(to_i2c_client(dev), tm); | 212 | return max6900_i2c_set_time(to_i2c_client(dev), tm); |
259 | } | 213 | } |
260 | 214 | ||
261 | static int max6900_attach_adapter(struct i2c_adapter *adapter) | 215 | static int max6900_remove(struct i2c_client *client) |
262 | { | ||
263 | return i2c_probe(adapter, &addr_data, max6900_probe); | ||
264 | } | ||
265 | |||
266 | static int max6900_detach_client(struct i2c_client *client) | ||
267 | { | 216 | { |
268 | struct rtc_device *const rtc = i2c_get_clientdata(client); | 217 | struct rtc_device *rtc = i2c_get_clientdata(client); |
269 | 218 | ||
270 | if (rtc) | 219 | if (rtc) |
271 | rtc_device_unregister(rtc); | 220 | rtc_device_unregister(rtc); |
272 | 221 | ||
273 | return i2c_detach_client(client); | 222 | return 0; |
274 | } | 223 | } |
275 | 224 | ||
276 | static struct i2c_driver max6900_driver = { | ||
277 | .driver = { | ||
278 | .name = DRV_NAME, | ||
279 | }, | ||
280 | .id = I2C_DRIVERID_MAX6900, | ||
281 | .attach_adapter = max6900_attach_adapter, | ||
282 | .detach_client = max6900_detach_client, | ||
283 | }; | ||
284 | |||
285 | static const struct rtc_class_ops max6900_rtc_ops = { | 225 | static const struct rtc_class_ops max6900_rtc_ops = { |
286 | .read_time = max6900_rtc_read_time, | 226 | .read_time = max6900_rtc_read_time, |
287 | .set_time = max6900_rtc_set_time, | 227 | .set_time = max6900_rtc_set_time, |
288 | }; | 228 | }; |
289 | 229 | ||
290 | static int max6900_probe(struct i2c_adapter *adapter, int addr, int kind) | 230 | static int |
231 | max6900_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
291 | { | 232 | { |
292 | int rc = 0; | 233 | struct rtc_device *rtc; |
293 | struct i2c_client *client = NULL; | ||
294 | struct rtc_device *rtc = NULL; | ||
295 | |||
296 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | ||
297 | rc = -ENODEV; | ||
298 | goto failout; | ||
299 | } | ||
300 | |||
301 | client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
302 | if (client == NULL) { | ||
303 | rc = -ENOMEM; | ||
304 | goto failout; | ||
305 | } | ||
306 | |||
307 | client->addr = addr; | ||
308 | client->adapter = adapter; | ||
309 | client->driver = &max6900_driver; | ||
310 | strlcpy(client->name, DRV_NAME, I2C_NAME_SIZE); | ||
311 | |||
312 | if (kind < 0) { | ||
313 | rc = max6900_i2c_validate_client(client); | ||
314 | if (rc < 0) | ||
315 | goto failout; | ||
316 | } | ||
317 | 234 | ||
318 | rc = i2c_attach_client(client); | 235 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) |
319 | if (rc < 0) | 236 | return -ENODEV; |
320 | goto failout; | ||
321 | 237 | ||
322 | dev_info(&client->dev, | 238 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
323 | "chip found, driver version " DRV_VERSION "\n"); | ||
324 | 239 | ||
325 | rtc = rtc_device_register(max6900_driver.driver.name, | 240 | rtc = rtc_device_register(max6900_driver.driver.name, |
326 | &client->dev, | 241 | &client->dev, &max6900_rtc_ops, THIS_MODULE); |
327 | &max6900_rtc_ops, THIS_MODULE); | 242 | if (IS_ERR(rtc)) |
328 | if (IS_ERR(rtc)) { | 243 | return PTR_ERR(rtc); |
329 | rc = PTR_ERR(rtc); | ||
330 | goto failout_detach; | ||
331 | } | ||
332 | 244 | ||
333 | i2c_set_clientdata(client, rtc); | 245 | i2c_set_clientdata(client, rtc); |
334 | 246 | ||
335 | return 0; | 247 | return 0; |
336 | |||
337 | failout_detach: | ||
338 | i2c_detach_client(client); | ||
339 | failout: | ||
340 | kfree(client); | ||
341 | return rc; | ||
342 | } | 248 | } |
343 | 249 | ||
250 | static struct i2c_driver max6900_driver = { | ||
251 | .driver = { | ||
252 | .name = "rtc-max6900", | ||
253 | }, | ||
254 | .probe = max6900_probe, | ||
255 | .remove = max6900_remove, | ||
256 | }; | ||
257 | |||
344 | static int __init max6900_init(void) | 258 | static int __init max6900_init(void) |
345 | { | 259 | { |
346 | return i2c_add_driver(&max6900_driver); | 260 | return i2c_add_driver(&max6900_driver); |
@@ -352,6 +266,7 @@ static void __exit max6900_exit(void) | |||
352 | } | 266 | } |
353 | 267 | ||
354 | MODULE_DESCRIPTION("Maxim MAX6900 RTC driver"); | 268 | MODULE_DESCRIPTION("Maxim MAX6900 RTC driver"); |
269 | MODULE_AUTHOR("Dale Farnsworth <dale@farnsworth.org>"); | ||
355 | MODULE_LICENSE("GPL"); | 270 | MODULE_LICENSE("GPL"); |
356 | MODULE_VERSION(DRV_VERSION); | 271 | MODULE_VERSION(DRV_VERSION); |
357 | 272 | ||
diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c index 12f0310ae89c..2f6507df7b49 100644 --- a/drivers/rtc/rtc-max6902.c +++ b/drivers/rtc/rtc-max6902.c | |||
@@ -20,8 +20,6 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/version.h> | ||
24 | |||
25 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
26 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
27 | #include <linux/init.h> | 25 | #include <linux/init.h> |
@@ -126,15 +124,15 @@ static int max6902_get_datetime(struct device *dev, struct rtc_time *dt) | |||
126 | 124 | ||
127 | /* The chip sends data in this order: | 125 | /* The chip sends data in this order: |
128 | * Seconds, Minutes, Hours, Date, Month, Day, Year */ | 126 | * Seconds, Minutes, Hours, Date, Month, Day, Year */ |
129 | dt->tm_sec = BCD2BIN(chip->buf[1]); | 127 | dt->tm_sec = bcd2bin(chip->buf[1]); |
130 | dt->tm_min = BCD2BIN(chip->buf[2]); | 128 | dt->tm_min = bcd2bin(chip->buf[2]); |
131 | dt->tm_hour = BCD2BIN(chip->buf[3]); | 129 | dt->tm_hour = bcd2bin(chip->buf[3]); |
132 | dt->tm_mday = BCD2BIN(chip->buf[4]); | 130 | dt->tm_mday = bcd2bin(chip->buf[4]); |
133 | dt->tm_mon = BCD2BIN(chip->buf[5]) - 1; | 131 | dt->tm_mon = bcd2bin(chip->buf[5]) - 1; |
134 | dt->tm_wday = BCD2BIN(chip->buf[6]); | 132 | dt->tm_wday = bcd2bin(chip->buf[6]); |
135 | dt->tm_year = BCD2BIN(chip->buf[7]); | 133 | dt->tm_year = bcd2bin(chip->buf[7]); |
136 | 134 | ||
137 | century = BCD2BIN(tmp) * 100; | 135 | century = bcd2bin(tmp) * 100; |
138 | 136 | ||
139 | dt->tm_year += century; | 137 | dt->tm_year += century; |
140 | dt->tm_year -= 1900; | 138 | dt->tm_year -= 1900; |
@@ -170,15 +168,15 @@ static int max6902_set_datetime(struct device *dev, struct rtc_time *dt) | |||
170 | /* Remove write protection */ | 168 | /* Remove write protection */ |
171 | max6902_set_reg(dev, 0xF, 0); | 169 | max6902_set_reg(dev, 0xF, 0); |
172 | 170 | ||
173 | max6902_set_reg(dev, 0x01, BIN2BCD(dt->tm_sec)); | 171 | max6902_set_reg(dev, 0x01, bin2bcd(dt->tm_sec)); |
174 | max6902_set_reg(dev, 0x03, BIN2BCD(dt->tm_min)); | 172 | max6902_set_reg(dev, 0x03, bin2bcd(dt->tm_min)); |
175 | max6902_set_reg(dev, 0x05, BIN2BCD(dt->tm_hour)); | 173 | max6902_set_reg(dev, 0x05, bin2bcd(dt->tm_hour)); |
176 | 174 | ||
177 | max6902_set_reg(dev, 0x07, BIN2BCD(dt->tm_mday)); | 175 | max6902_set_reg(dev, 0x07, bin2bcd(dt->tm_mday)); |
178 | max6902_set_reg(dev, 0x09, BIN2BCD(dt->tm_mon+1)); | 176 | max6902_set_reg(dev, 0x09, bin2bcd(dt->tm_mon+1)); |
179 | max6902_set_reg(dev, 0x0B, BIN2BCD(dt->tm_wday)); | 177 | max6902_set_reg(dev, 0x0B, bin2bcd(dt->tm_wday)); |
180 | max6902_set_reg(dev, 0x0D, BIN2BCD(dt->tm_year%100)); | 178 | max6902_set_reg(dev, 0x0D, bin2bcd(dt->tm_year%100)); |
181 | max6902_set_reg(dev, 0x13, BIN2BCD(dt->tm_year/100)); | 179 | max6902_set_reg(dev, 0x13, bin2bcd(dt->tm_year/100)); |
182 | 180 | ||
183 | /* Compulab used a delay here. However, the datasheet | 181 | /* Compulab used a delay here. However, the datasheet |
184 | * does not mention a delay being required anywhere... */ | 182 | * does not mention a delay being required anywhere... */ |
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index eb23d8423f42..2cbeb0794f14 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c | |||
@@ -92,18 +92,6 @@ | |||
92 | #define rtc_write(val, addr) omap_writeb(val, OMAP_RTC_BASE + (addr)) | 92 | #define rtc_write(val, addr) omap_writeb(val, OMAP_RTC_BASE + (addr)) |
93 | 93 | ||
94 | 94 | ||
95 | /* platform_bus isn't hotpluggable, so for static linkage it'd be safe | ||
96 | * to get rid of probe() and remove() code ... too bad the driver struct | ||
97 | * remembers probe(), that's about 25% of the runtime footprint!! | ||
98 | */ | ||
99 | #ifndef MODULE | ||
100 | #undef __devexit | ||
101 | #undef __devexit_p | ||
102 | #define __devexit __exit | ||
103 | #define __devexit_p __exit_p | ||
104 | #endif | ||
105 | |||
106 | |||
107 | /* we rely on the rtc framework to handle locking (rtc->ops_lock), | 95 | /* we rely on the rtc framework to handle locking (rtc->ops_lock), |
108 | * so the only other requirement is that register accesses which | 96 | * so the only other requirement is that register accesses which |
109 | * require BUSY to be clear are made with IRQs locally disabled | 97 | * require BUSY to be clear are made with IRQs locally disabled |
@@ -198,30 +186,30 @@ static int tm2bcd(struct rtc_time *tm) | |||
198 | if (rtc_valid_tm(tm) != 0) | 186 | if (rtc_valid_tm(tm) != 0) |
199 | return -EINVAL; | 187 | return -EINVAL; |
200 | 188 | ||
201 | tm->tm_sec = BIN2BCD(tm->tm_sec); | 189 | tm->tm_sec = bin2bcd(tm->tm_sec); |
202 | tm->tm_min = BIN2BCD(tm->tm_min); | 190 | tm->tm_min = bin2bcd(tm->tm_min); |
203 | tm->tm_hour = BIN2BCD(tm->tm_hour); | 191 | tm->tm_hour = bin2bcd(tm->tm_hour); |
204 | tm->tm_mday = BIN2BCD(tm->tm_mday); | 192 | tm->tm_mday = bin2bcd(tm->tm_mday); |
205 | 193 | ||
206 | tm->tm_mon = BIN2BCD(tm->tm_mon + 1); | 194 | tm->tm_mon = bin2bcd(tm->tm_mon + 1); |
207 | 195 | ||
208 | /* epoch == 1900 */ | 196 | /* epoch == 1900 */ |
209 | if (tm->tm_year < 100 || tm->tm_year > 199) | 197 | if (tm->tm_year < 100 || tm->tm_year > 199) |
210 | return -EINVAL; | 198 | return -EINVAL; |
211 | tm->tm_year = BIN2BCD(tm->tm_year - 100); | 199 | tm->tm_year = bin2bcd(tm->tm_year - 100); |
212 | 200 | ||
213 | return 0; | 201 | return 0; |
214 | } | 202 | } |
215 | 203 | ||
216 | static void bcd2tm(struct rtc_time *tm) | 204 | static void bcd2tm(struct rtc_time *tm) |
217 | { | 205 | { |
218 | tm->tm_sec = BCD2BIN(tm->tm_sec); | 206 | tm->tm_sec = bcd2bin(tm->tm_sec); |
219 | tm->tm_min = BCD2BIN(tm->tm_min); | 207 | tm->tm_min = bcd2bin(tm->tm_min); |
220 | tm->tm_hour = BCD2BIN(tm->tm_hour); | 208 | tm->tm_hour = bcd2bin(tm->tm_hour); |
221 | tm->tm_mday = BCD2BIN(tm->tm_mday); | 209 | tm->tm_mday = bcd2bin(tm->tm_mday); |
222 | tm->tm_mon = BCD2BIN(tm->tm_mon) - 1; | 210 | tm->tm_mon = bcd2bin(tm->tm_mon) - 1; |
223 | /* epoch == 1900 */ | 211 | /* epoch == 1900 */ |
224 | tm->tm_year = BCD2BIN(tm->tm_year) + 100; | 212 | tm->tm_year = bcd2bin(tm->tm_year) + 100; |
225 | } | 213 | } |
226 | 214 | ||
227 | 215 | ||
@@ -324,7 +312,7 @@ static struct rtc_class_ops omap_rtc_ops = { | |||
324 | static int omap_rtc_alarm; | 312 | static int omap_rtc_alarm; |
325 | static int omap_rtc_timer; | 313 | static int omap_rtc_timer; |
326 | 314 | ||
327 | static int __devinit omap_rtc_probe(struct platform_device *pdev) | 315 | static int __init omap_rtc_probe(struct platform_device *pdev) |
328 | { | 316 | { |
329 | struct resource *res, *mem; | 317 | struct resource *res, *mem; |
330 | struct rtc_device *rtc; | 318 | struct rtc_device *rtc; |
@@ -440,7 +428,7 @@ fail: | |||
440 | return -EIO; | 428 | return -EIO; |
441 | } | 429 | } |
442 | 430 | ||
443 | static int __devexit omap_rtc_remove(struct platform_device *pdev) | 431 | static int __exit omap_rtc_remove(struct platform_device *pdev) |
444 | { | 432 | { |
445 | struct rtc_device *rtc = platform_get_drvdata(pdev);; | 433 | struct rtc_device *rtc = platform_get_drvdata(pdev);; |
446 | 434 | ||
@@ -498,8 +486,7 @@ static void omap_rtc_shutdown(struct platform_device *pdev) | |||
498 | 486 | ||
499 | MODULE_ALIAS("platform:omap_rtc"); | 487 | MODULE_ALIAS("platform:omap_rtc"); |
500 | static struct platform_driver omap_rtc_driver = { | 488 | static struct platform_driver omap_rtc_driver = { |
501 | .probe = omap_rtc_probe, | 489 | .remove = __exit_p(omap_rtc_remove), |
502 | .remove = __devexit_p(omap_rtc_remove), | ||
503 | .suspend = omap_rtc_suspend, | 490 | .suspend = omap_rtc_suspend, |
504 | .resume = omap_rtc_resume, | 491 | .resume = omap_rtc_resume, |
505 | .shutdown = omap_rtc_shutdown, | 492 | .shutdown = omap_rtc_shutdown, |
@@ -511,7 +498,7 @@ static struct platform_driver omap_rtc_driver = { | |||
511 | 498 | ||
512 | static int __init rtc_init(void) | 499 | static int __init rtc_init(void) |
513 | { | 500 | { |
514 | return platform_driver_register(&omap_rtc_driver); | 501 | return platform_driver_probe(&omap_rtc_driver, omap_rtc_probe); |
515 | } | 502 | } |
516 | module_init(rtc_init); | 503 | module_init(rtc_init); |
517 | 504 | ||
diff --git a/drivers/rtc/rtc-parisc.c b/drivers/rtc/rtc-parisc.c new file mode 100644 index 000000000000..346d633655e7 --- /dev/null +++ b/drivers/rtc/rtc-parisc.c | |||
@@ -0,0 +1,111 @@ | |||
1 | /* rtc-parisc: RTC for HP PA-RISC firmware | ||
2 | * | ||
3 | * Copyright (C) 2008 Kyle McMartin <kyle@mcmartin.ca> | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/time.h> | ||
9 | #include <linux/platform_device.h> | ||
10 | |||
11 | #include <asm/rtc.h> | ||
12 | |||
13 | /* as simple as can be, and no simpler. */ | ||
14 | struct parisc_rtc { | ||
15 | struct rtc_device *rtc; | ||
16 | spinlock_t lock; | ||
17 | }; | ||
18 | |||
19 | static int parisc_get_time(struct device *dev, struct rtc_time *tm) | ||
20 | { | ||
21 | struct parisc_rtc *p = dev_get_drvdata(dev); | ||
22 | unsigned long flags, ret; | ||
23 | |||
24 | spin_lock_irqsave(&p->lock, flags); | ||
25 | ret = get_rtc_time(tm); | ||
26 | spin_unlock_irqrestore(&p->lock, flags); | ||
27 | |||
28 | if (ret & RTC_BATT_BAD) | ||
29 | return -EOPNOTSUPP; | ||
30 | |||
31 | return 0; | ||
32 | } | ||
33 | |||
34 | static int parisc_set_time(struct device *dev, struct rtc_time *tm) | ||
35 | { | ||
36 | struct parisc_rtc *p = dev_get_drvdata(dev); | ||
37 | unsigned long flags, ret; | ||
38 | |||
39 | spin_lock_irqsave(&p->lock, flags); | ||
40 | ret = set_rtc_time(tm); | ||
41 | spin_unlock_irqrestore(&p->lock, flags); | ||
42 | |||
43 | if (ret < 0) | ||
44 | return -EOPNOTSUPP; | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static const struct rtc_class_ops parisc_rtc_ops = { | ||
50 | .read_time = parisc_get_time, | ||
51 | .set_time = parisc_set_time, | ||
52 | }; | ||
53 | |||
54 | static int __devinit parisc_rtc_probe(struct platform_device *dev) | ||
55 | { | ||
56 | struct parisc_rtc *p; | ||
57 | |||
58 | p = kzalloc(sizeof (*p), GFP_KERNEL); | ||
59 | if (!p) | ||
60 | return -ENOMEM; | ||
61 | |||
62 | spin_lock_init(&p->lock); | ||
63 | |||
64 | p->rtc = rtc_device_register("rtc-parisc", &dev->dev, &parisc_rtc_ops, | ||
65 | THIS_MODULE); | ||
66 | if (IS_ERR(p->rtc)) { | ||
67 | int err = PTR_ERR(p->rtc); | ||
68 | kfree(p); | ||
69 | return err; | ||
70 | } | ||
71 | |||
72 | platform_set_drvdata(dev, p); | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int __devexit parisc_rtc_remove(struct platform_device *dev) | ||
78 | { | ||
79 | struct parisc_rtc *p = platform_get_drvdata(dev); | ||
80 | |||
81 | rtc_device_unregister(p->rtc); | ||
82 | kfree(p); | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static struct platform_driver parisc_rtc_driver = { | ||
88 | .driver = { | ||
89 | .name = "rtc-parisc", | ||
90 | .owner = THIS_MODULE, | ||
91 | }, | ||
92 | .probe = parisc_rtc_probe, | ||
93 | .remove = __devexit_p(parisc_rtc_remove), | ||
94 | }; | ||
95 | |||
96 | static int __init parisc_rtc_init(void) | ||
97 | { | ||
98 | return platform_driver_register(&parisc_rtc_driver); | ||
99 | } | ||
100 | |||
101 | static void __exit parisc_rtc_fini(void) | ||
102 | { | ||
103 | platform_driver_unregister(&parisc_rtc_driver); | ||
104 | } | ||
105 | |||
106 | module_init(parisc_rtc_init); | ||
107 | module_exit(parisc_rtc_fini); | ||
108 | |||
109 | MODULE_AUTHOR("Kyle McMartin <kyle@mcmartin.ca>"); | ||
110 | MODULE_LICENSE("GPL"); | ||
111 | MODULE_DESCRIPTION("HP PA-RISC RTC driver"); | ||
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 748a502a6355..b725913ccbe8 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c | |||
@@ -97,13 +97,13 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
97 | buf[8]); | 97 | buf[8]); |
98 | 98 | ||
99 | 99 | ||
100 | tm->tm_sec = BCD2BIN(buf[PCF8563_REG_SC] & 0x7F); | 100 | tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F); |
101 | tm->tm_min = BCD2BIN(buf[PCF8563_REG_MN] & 0x7F); | 101 | tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F); |
102 | tm->tm_hour = BCD2BIN(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */ | 102 | tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */ |
103 | tm->tm_mday = BCD2BIN(buf[PCF8563_REG_DM] & 0x3F); | 103 | tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F); |
104 | tm->tm_wday = buf[PCF8563_REG_DW] & 0x07; | 104 | tm->tm_wday = buf[PCF8563_REG_DW] & 0x07; |
105 | tm->tm_mon = BCD2BIN(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ | 105 | tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ |
106 | tm->tm_year = BCD2BIN(buf[PCF8563_REG_YR]); | 106 | tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]); |
107 | if (tm->tm_year < 70) | 107 | if (tm->tm_year < 70) |
108 | tm->tm_year += 100; /* assume we are in 1970...2069 */ | 108 | tm->tm_year += 100; /* assume we are in 1970...2069 */ |
109 | /* detect the polarity heuristically. see note above. */ | 109 | /* detect the polarity heuristically. see note above. */ |
@@ -138,17 +138,17 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
138 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | 138 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); |
139 | 139 | ||
140 | /* hours, minutes and seconds */ | 140 | /* hours, minutes and seconds */ |
141 | buf[PCF8563_REG_SC] = BIN2BCD(tm->tm_sec); | 141 | buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec); |
142 | buf[PCF8563_REG_MN] = BIN2BCD(tm->tm_min); | 142 | buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min); |
143 | buf[PCF8563_REG_HR] = BIN2BCD(tm->tm_hour); | 143 | buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour); |
144 | 144 | ||
145 | buf[PCF8563_REG_DM] = BIN2BCD(tm->tm_mday); | 145 | buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday); |
146 | 146 | ||
147 | /* month, 1 - 12 */ | 147 | /* month, 1 - 12 */ |
148 | buf[PCF8563_REG_MO] = BIN2BCD(tm->tm_mon + 1); | 148 | buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1); |
149 | 149 | ||
150 | /* year and century */ | 150 | /* year and century */ |
151 | buf[PCF8563_REG_YR] = BIN2BCD(tm->tm_year % 100); | 151 | buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100); |
152 | if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100)) | 152 | if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100)) |
153 | buf[PCF8563_REG_MO] |= PCF8563_MO_C; | 153 | buf[PCF8563_REG_MO] |= PCF8563_MO_C; |
154 | 154 | ||
@@ -179,58 +179,6 @@ struct pcf8563_limit | |||
179 | unsigned char max; | 179 | unsigned char max; |
180 | }; | 180 | }; |
181 | 181 | ||
182 | static int pcf8563_validate_client(struct i2c_client *client) | ||
183 | { | ||
184 | int i; | ||
185 | |||
186 | static const struct pcf8563_limit pattern[] = { | ||
187 | /* register, mask, min, max */ | ||
188 | { PCF8563_REG_SC, 0x7F, 0, 59 }, | ||
189 | { PCF8563_REG_MN, 0x7F, 0, 59 }, | ||
190 | { PCF8563_REG_HR, 0x3F, 0, 23 }, | ||
191 | { PCF8563_REG_DM, 0x3F, 0, 31 }, | ||
192 | { PCF8563_REG_MO, 0x1F, 0, 12 }, | ||
193 | }; | ||
194 | |||
195 | /* check limits (only registers with bcd values) */ | ||
196 | for (i = 0; i < ARRAY_SIZE(pattern); i++) { | ||
197 | int xfer; | ||
198 | unsigned char value; | ||
199 | unsigned char buf = pattern[i].reg; | ||
200 | |||
201 | struct i2c_msg msgs[] = { | ||
202 | { client->addr, 0, 1, &buf }, | ||
203 | { client->addr, I2C_M_RD, 1, &buf }, | ||
204 | }; | ||
205 | |||
206 | xfer = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
207 | |||
208 | if (xfer != ARRAY_SIZE(msgs)) { | ||
209 | dev_err(&client->dev, | ||
210 | "%s: could not read register 0x%02X\n", | ||
211 | __func__, pattern[i].reg); | ||
212 | |||
213 | return -EIO; | ||
214 | } | ||
215 | |||
216 | value = BCD2BIN(buf & pattern[i].mask); | ||
217 | |||
218 | if (value > pattern[i].max || | ||
219 | value < pattern[i].min) { | ||
220 | dev_dbg(&client->dev, | ||
221 | "%s: pattern=%d, reg=%x, mask=0x%02x, min=%d, " | ||
222 | "max=%d, value=%d, raw=0x%02X\n", | ||
223 | __func__, i, pattern[i].reg, pattern[i].mask, | ||
224 | pattern[i].min, pattern[i].max, | ||
225 | value, buf); | ||
226 | |||
227 | return -ENODEV; | ||
228 | } | ||
229 | } | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) | 182 | static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) |
235 | { | 183 | { |
236 | return pcf8563_get_datetime(to_i2c_client(dev), tm); | 184 | return pcf8563_get_datetime(to_i2c_client(dev), tm); |
@@ -262,12 +210,6 @@ static int pcf8563_probe(struct i2c_client *client, | |||
262 | if (!pcf8563) | 210 | if (!pcf8563) |
263 | return -ENOMEM; | 211 | return -ENOMEM; |
264 | 212 | ||
265 | /* Verify the chip is really an PCF8563 */ | ||
266 | if (pcf8563_validate_client(client) < 0) { | ||
267 | err = -ENODEV; | ||
268 | goto exit_kfree; | ||
269 | } | ||
270 | |||
271 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | 213 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
272 | 214 | ||
273 | pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name, | 215 | pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name, |
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index 3d09d8f0b1f0..7d33cda3f8f6 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * drivers/rtc/rtc-pcf8583.c | 2 | * drivers/rtc/rtc-pcf8583.c |
3 | * | 3 | * |
4 | * Copyright (C) 2000 Russell King | 4 | * Copyright (C) 2000 Russell King |
5 | * Copyright (C) 2008 Wolfram Sang & Juergen Beisert, Pengutronix | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * 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 | * it under the terms of the GNU General Public License version 2 as |
@@ -14,7 +15,6 @@ | |||
14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
15 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
16 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
17 | #include <linux/string.h> | ||
18 | #include <linux/rtc.h> | 18 | #include <linux/rtc.h> |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
@@ -27,7 +27,6 @@ struct rtc_mem { | |||
27 | }; | 27 | }; |
28 | 28 | ||
29 | struct pcf8583 { | 29 | struct pcf8583 { |
30 | struct i2c_client client; | ||
31 | struct rtc_device *rtc; | 30 | struct rtc_device *rtc; |
32 | unsigned char ctrl; | 31 | unsigned char ctrl; |
33 | }; | 32 | }; |
@@ -40,10 +39,6 @@ struct pcf8583 { | |||
40 | #define CTRL_ALARM 0x02 | 39 | #define CTRL_ALARM 0x02 |
41 | #define CTRL_TIMER 0x01 | 40 | #define CTRL_TIMER 0x01 |
42 | 41 | ||
43 | static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; | ||
44 | |||
45 | /* Module parameters */ | ||
46 | I2C_CLIENT_INSMOD; | ||
47 | 42 | ||
48 | static struct i2c_driver pcf8583_driver; | 43 | static struct i2c_driver pcf8583_driver; |
49 | 44 | ||
@@ -81,11 +76,11 @@ static int pcf8583_get_datetime(struct i2c_client *client, struct rtc_time *dt) | |||
81 | buf[4] &= 0x3f; | 76 | buf[4] &= 0x3f; |
82 | buf[5] &= 0x1f; | 77 | buf[5] &= 0x1f; |
83 | 78 | ||
84 | dt->tm_sec = BCD2BIN(buf[1]); | 79 | dt->tm_sec = bcd2bin(buf[1]); |
85 | dt->tm_min = BCD2BIN(buf[2]); | 80 | dt->tm_min = bcd2bin(buf[2]); |
86 | dt->tm_hour = BCD2BIN(buf[3]); | 81 | dt->tm_hour = bcd2bin(buf[3]); |
87 | dt->tm_mday = BCD2BIN(buf[4]); | 82 | dt->tm_mday = bcd2bin(buf[4]); |
88 | dt->tm_mon = BCD2BIN(buf[5]) - 1; | 83 | dt->tm_mon = bcd2bin(buf[5]) - 1; |
89 | } | 84 | } |
90 | 85 | ||
91 | return ret == 2 ? 0 : -EIO; | 86 | return ret == 2 ? 0 : -EIO; |
@@ -99,14 +94,14 @@ static int pcf8583_set_datetime(struct i2c_client *client, struct rtc_time *dt, | |||
99 | buf[0] = 0; | 94 | buf[0] = 0; |
100 | buf[1] = get_ctrl(client) | 0x80; | 95 | buf[1] = get_ctrl(client) | 0x80; |
101 | buf[2] = 0; | 96 | buf[2] = 0; |
102 | buf[3] = BIN2BCD(dt->tm_sec); | 97 | buf[3] = bin2bcd(dt->tm_sec); |
103 | buf[4] = BIN2BCD(dt->tm_min); | 98 | buf[4] = bin2bcd(dt->tm_min); |
104 | buf[5] = BIN2BCD(dt->tm_hour); | 99 | buf[5] = bin2bcd(dt->tm_hour); |
105 | 100 | ||
106 | if (datetoo) { | 101 | if (datetoo) { |
107 | len = 8; | 102 | len = 8; |
108 | buf[6] = BIN2BCD(dt->tm_mday) | (dt->tm_year << 6); | 103 | buf[6] = bin2bcd(dt->tm_mday) | (dt->tm_year << 6); |
109 | buf[7] = BIN2BCD(dt->tm_mon + 1) | (dt->tm_wday << 5); | 104 | buf[7] = bin2bcd(dt->tm_mon + 1) | (dt->tm_wday << 5); |
110 | } | 105 | } |
111 | 106 | ||
112 | ret = i2c_master_send(client, (char *)buf, len); | 107 | ret = i2c_master_send(client, (char *)buf, len); |
@@ -269,106 +264,60 @@ static const struct rtc_class_ops pcf8583_rtc_ops = { | |||
269 | .set_time = pcf8583_rtc_set_time, | 264 | .set_time = pcf8583_rtc_set_time, |
270 | }; | 265 | }; |
271 | 266 | ||
272 | static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind); | 267 | static int pcf8583_probe(struct i2c_client *client, |
273 | 268 | const struct i2c_device_id *id) | |
274 | static int pcf8583_attach(struct i2c_adapter *adap) | ||
275 | { | ||
276 | return i2c_probe(adap, &addr_data, pcf8583_probe); | ||
277 | } | ||
278 | |||
279 | static int pcf8583_detach(struct i2c_client *client) | ||
280 | { | ||
281 | int err; | ||
282 | struct pcf8583 *pcf = i2c_get_clientdata(client); | ||
283 | struct rtc_device *rtc = pcf->rtc; | ||
284 | |||
285 | if (rtc) | ||
286 | rtc_device_unregister(rtc); | ||
287 | |||
288 | if ((err = i2c_detach_client(client))) | ||
289 | return err; | ||
290 | |||
291 | kfree(pcf); | ||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | static struct i2c_driver pcf8583_driver = { | ||
296 | .driver = { | ||
297 | .name = "pcf8583", | ||
298 | }, | ||
299 | .id = I2C_DRIVERID_PCF8583, | ||
300 | .attach_adapter = pcf8583_attach, | ||
301 | .detach_client = pcf8583_detach, | ||
302 | }; | ||
303 | |||
304 | static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind) | ||
305 | { | 269 | { |
306 | struct pcf8583 *pcf; | 270 | struct pcf8583 *pcf8583; |
307 | struct i2c_client *client; | ||
308 | struct rtc_device *rtc; | ||
309 | unsigned char buf[1], ad[1] = { 0 }; | ||
310 | int err; | 271 | int err; |
311 | struct i2c_msg msgs[2] = { | ||
312 | { | ||
313 | .addr = addr, | ||
314 | .flags = 0, | ||
315 | .len = 1, | ||
316 | .buf = ad, | ||
317 | }, { | ||
318 | .addr = addr, | ||
319 | .flags = I2C_M_RD, | ||
320 | .len = 1, | ||
321 | .buf = buf, | ||
322 | } | ||
323 | }; | ||
324 | 272 | ||
325 | if (!i2c_check_functionality(adap, I2C_FUNC_I2C)) | 273 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) |
326 | return 0; | 274 | return -ENODEV; |
327 | 275 | ||
328 | pcf = kzalloc(sizeof(*pcf), GFP_KERNEL); | 276 | pcf8583 = kzalloc(sizeof(struct pcf8583), GFP_KERNEL); |
329 | if (!pcf) | 277 | if (!pcf8583) |
330 | return -ENOMEM; | 278 | return -ENOMEM; |
331 | 279 | ||
332 | client = &pcf->client; | 280 | pcf8583->rtc = rtc_device_register(pcf8583_driver.driver.name, |
281 | &client->dev, &pcf8583_rtc_ops, THIS_MODULE); | ||
333 | 282 | ||
334 | client->addr = addr; | 283 | if (IS_ERR(pcf8583->rtc)) { |
335 | client->adapter = adap; | 284 | err = PTR_ERR(pcf8583->rtc); |
336 | client->driver = &pcf8583_driver; | ||
337 | |||
338 | strlcpy(client->name, pcf8583_driver.driver.name, I2C_NAME_SIZE); | ||
339 | |||
340 | if (i2c_transfer(client->adapter, msgs, 2) != 2) { | ||
341 | err = -EIO; | ||
342 | goto exit_kfree; | 285 | goto exit_kfree; |
343 | } | 286 | } |
344 | 287 | ||
345 | err = i2c_attach_client(client); | 288 | i2c_set_clientdata(client, pcf8583); |
346 | 289 | return 0; | |
347 | if (err) | ||
348 | goto exit_kfree; | ||
349 | |||
350 | rtc = rtc_device_register(pcf8583_driver.driver.name, &client->dev, | ||
351 | &pcf8583_rtc_ops, THIS_MODULE); | ||
352 | 290 | ||
353 | if (IS_ERR(rtc)) { | 291 | exit_kfree: |
354 | err = PTR_ERR(rtc); | 292 | kfree(pcf8583); |
355 | goto exit_detach; | 293 | return err; |
356 | } | 294 | } |
357 | 295 | ||
358 | pcf->rtc = rtc; | 296 | static int __devexit pcf8583_remove(struct i2c_client *client) |
359 | i2c_set_clientdata(client, pcf); | 297 | { |
360 | set_ctrl(client, buf[0]); | 298 | struct pcf8583 *pcf8583 = i2c_get_clientdata(client); |
361 | 299 | ||
300 | if (pcf8583->rtc) | ||
301 | rtc_device_unregister(pcf8583->rtc); | ||
302 | kfree(pcf8583); | ||
362 | return 0; | 303 | return 0; |
304 | } | ||
363 | 305 | ||
364 | exit_detach: | 306 | static const struct i2c_device_id pcf8583_id[] = { |
365 | i2c_detach_client(client); | 307 | { "pcf8583", 0 }, |
366 | 308 | { } | |
367 | exit_kfree: | 309 | }; |
368 | kfree(pcf); | 310 | MODULE_DEVICE_TABLE(i2c, pcf8583_id); |
369 | 311 | ||
370 | return err; | 312 | static struct i2c_driver pcf8583_driver = { |
371 | } | 313 | .driver = { |
314 | .name = "pcf8583", | ||
315 | .owner = THIS_MODULE, | ||
316 | }, | ||
317 | .probe = pcf8583_probe, | ||
318 | .remove = __devexit_p(pcf8583_remove), | ||
319 | .id_table = pcf8583_id, | ||
320 | }; | ||
372 | 321 | ||
373 | static __init int pcf8583_init(void) | 322 | static __init int pcf8583_init(void) |
374 | { | 323 | { |
diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c index 8448eeb9d675..826153552157 100644 --- a/drivers/rtc/rtc-pl030.c +++ b/drivers/rtc/rtc-pl030.c | |||
@@ -34,15 +34,6 @@ static irqreturn_t pl030_interrupt(int irq, void *dev_id) | |||
34 | return IRQ_HANDLED; | 34 | return IRQ_HANDLED; |
35 | } | 35 | } |
36 | 36 | ||
37 | static int pl030_open(struct device *dev) | ||
38 | { | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static void pl030_release(struct device *dev) | ||
43 | { | ||
44 | } | ||
45 | |||
46 | static int pl030_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 37 | static int pl030_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
47 | { | 38 | { |
48 | return -ENOIOCTLCMD; | 39 | return -ENOIOCTLCMD; |
@@ -104,8 +95,6 @@ static int pl030_set_time(struct device *dev, struct rtc_time *tm) | |||
104 | } | 95 | } |
105 | 96 | ||
106 | static const struct rtc_class_ops pl030_ops = { | 97 | static const struct rtc_class_ops pl030_ops = { |
107 | .open = pl030_open, | ||
108 | .release = pl030_release, | ||
109 | .ioctl = pl030_ioctl, | 98 | .ioctl = pl030_ioctl, |
110 | .read_time = pl030_read_time, | 99 | .read_time = pl030_read_time, |
111 | .set_time = pl030_set_time, | 100 | .set_time = pl030_set_time, |
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 08b4610ec5a6..333eec689d2f 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c | |||
@@ -45,18 +45,6 @@ static irqreturn_t pl031_interrupt(int irq, void *dev_id) | |||
45 | return IRQ_HANDLED; | 45 | return IRQ_HANDLED; |
46 | } | 46 | } |
47 | 47 | ||
48 | static int pl031_open(struct device *dev) | ||
49 | { | ||
50 | /* | ||
51 | * We request IRQ in pl031_probe, so nothing to do here... | ||
52 | */ | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static void pl031_release(struct device *dev) | ||
57 | { | ||
58 | } | ||
59 | |||
60 | static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 48 | static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
61 | { | 49 | { |
62 | struct pl031_local *ldata = dev_get_drvdata(dev); | 50 | struct pl031_local *ldata = dev_get_drvdata(dev); |
@@ -118,8 +106,6 @@ static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
118 | } | 106 | } |
119 | 107 | ||
120 | static const struct rtc_class_ops pl031_ops = { | 108 | static const struct rtc_class_ops pl031_ops = { |
121 | .open = pl031_open, | ||
122 | .release = pl031_release, | ||
123 | .ioctl = pl031_ioctl, | 109 | .ioctl = pl031_ioctl, |
124 | .read_time = pl031_read_time, | 110 | .read_time = pl031_read_time, |
125 | .set_time = pl031_set_time, | 111 | .set_time = pl031_set_time, |
diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c index b35f9bfa2af4..42028f233bef 100644 --- a/drivers/rtc/rtc-r9701.c +++ b/drivers/rtc/rtc-r9701.c | |||
@@ -14,7 +14,6 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/version.h> | ||
18 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
19 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
20 | #include <linux/device.h> | 19 | #include <linux/device.h> |
@@ -81,13 +80,13 @@ static int r9701_get_datetime(struct device *dev, struct rtc_time *dt) | |||
81 | 80 | ||
82 | memset(dt, 0, sizeof(*dt)); | 81 | memset(dt, 0, sizeof(*dt)); |
83 | 82 | ||
84 | dt->tm_sec = BCD2BIN(buf[0]); /* RSECCNT */ | 83 | dt->tm_sec = bcd2bin(buf[0]); /* RSECCNT */ |
85 | dt->tm_min = BCD2BIN(buf[1]); /* RMINCNT */ | 84 | dt->tm_min = bcd2bin(buf[1]); /* RMINCNT */ |
86 | dt->tm_hour = BCD2BIN(buf[2]); /* RHRCNT */ | 85 | dt->tm_hour = bcd2bin(buf[2]); /* RHRCNT */ |
87 | 86 | ||
88 | dt->tm_mday = BCD2BIN(buf[3]); /* RDAYCNT */ | 87 | dt->tm_mday = bcd2bin(buf[3]); /* RDAYCNT */ |
89 | dt->tm_mon = BCD2BIN(buf[4]) - 1; /* RMONCNT */ | 88 | dt->tm_mon = bcd2bin(buf[4]) - 1; /* RMONCNT */ |
90 | dt->tm_year = BCD2BIN(buf[5]) + 100; /* RYRCNT */ | 89 | dt->tm_year = bcd2bin(buf[5]) + 100; /* RYRCNT */ |
91 | 90 | ||
92 | /* the rtc device may contain illegal values on power up | 91 | /* the rtc device may contain illegal values on power up |
93 | * according to the data sheet. make sure they are valid. | 92 | * according to the data sheet. make sure they are valid. |
@@ -104,12 +103,12 @@ static int r9701_set_datetime(struct device *dev, struct rtc_time *dt) | |||
104 | if (year >= 2100 || year < 2000) | 103 | if (year >= 2100 || year < 2000) |
105 | return -EINVAL; | 104 | return -EINVAL; |
106 | 105 | ||
107 | ret = write_reg(dev, RHRCNT, BIN2BCD(dt->tm_hour)); | 106 | ret = write_reg(dev, RHRCNT, bin2bcd(dt->tm_hour)); |
108 | ret = ret ? ret : write_reg(dev, RMINCNT, BIN2BCD(dt->tm_min)); | 107 | ret = ret ? ret : write_reg(dev, RMINCNT, bin2bcd(dt->tm_min)); |
109 | ret = ret ? ret : write_reg(dev, RSECCNT, BIN2BCD(dt->tm_sec)); | 108 | ret = ret ? ret : write_reg(dev, RSECCNT, bin2bcd(dt->tm_sec)); |
110 | ret = ret ? ret : write_reg(dev, RDAYCNT, BIN2BCD(dt->tm_mday)); | 109 | ret = ret ? ret : write_reg(dev, RDAYCNT, bin2bcd(dt->tm_mday)); |
111 | ret = ret ? ret : write_reg(dev, RMONCNT, BIN2BCD(dt->tm_mon + 1)); | 110 | ret = ret ? ret : write_reg(dev, RMONCNT, bin2bcd(dt->tm_mon + 1)); |
112 | ret = ret ? ret : write_reg(dev, RYRCNT, BIN2BCD(dt->tm_year - 100)); | 111 | ret = ret ? ret : write_reg(dev, RYRCNT, bin2bcd(dt->tm_year - 100)); |
113 | ret = ret ? ret : write_reg(dev, RWKCNT, 1 << dt->tm_wday); | 112 | ret = ret ? ret : write_reg(dev, RWKCNT, 1 << dt->tm_wday); |
114 | 113 | ||
115 | return ret; | 114 | return ret; |
diff --git a/drivers/rtc/rtc-rs5c313.c b/drivers/rtc/rtc-rs5c313.c index 1c14d4497c4d..e6ea3f5ee1eb 100644 --- a/drivers/rtc/rtc-rs5c313.c +++ b/drivers/rtc/rtc-rs5c313.c | |||
@@ -235,33 +235,33 @@ static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
235 | 235 | ||
236 | data = rs5c313_read_reg(RS5C313_ADDR_SEC); | 236 | data = rs5c313_read_reg(RS5C313_ADDR_SEC); |
237 | data |= (rs5c313_read_reg(RS5C313_ADDR_SEC10) << 4); | 237 | data |= (rs5c313_read_reg(RS5C313_ADDR_SEC10) << 4); |
238 | tm->tm_sec = BCD2BIN(data); | 238 | tm->tm_sec = bcd2bin(data); |
239 | 239 | ||
240 | data = rs5c313_read_reg(RS5C313_ADDR_MIN); | 240 | data = rs5c313_read_reg(RS5C313_ADDR_MIN); |
241 | data |= (rs5c313_read_reg(RS5C313_ADDR_MIN10) << 4); | 241 | data |= (rs5c313_read_reg(RS5C313_ADDR_MIN10) << 4); |
242 | tm->tm_min = BCD2BIN(data); | 242 | tm->tm_min = bcd2bin(data); |
243 | 243 | ||
244 | data = rs5c313_read_reg(RS5C313_ADDR_HOUR); | 244 | data = rs5c313_read_reg(RS5C313_ADDR_HOUR); |
245 | data |= (rs5c313_read_reg(RS5C313_ADDR_HOUR10) << 4); | 245 | data |= (rs5c313_read_reg(RS5C313_ADDR_HOUR10) << 4); |
246 | tm->tm_hour = BCD2BIN(data); | 246 | tm->tm_hour = bcd2bin(data); |
247 | 247 | ||
248 | data = rs5c313_read_reg(RS5C313_ADDR_DAY); | 248 | data = rs5c313_read_reg(RS5C313_ADDR_DAY); |
249 | data |= (rs5c313_read_reg(RS5C313_ADDR_DAY10) << 4); | 249 | data |= (rs5c313_read_reg(RS5C313_ADDR_DAY10) << 4); |
250 | tm->tm_mday = BCD2BIN(data); | 250 | tm->tm_mday = bcd2bin(data); |
251 | 251 | ||
252 | data = rs5c313_read_reg(RS5C313_ADDR_MON); | 252 | data = rs5c313_read_reg(RS5C313_ADDR_MON); |
253 | data |= (rs5c313_read_reg(RS5C313_ADDR_MON10) << 4); | 253 | data |= (rs5c313_read_reg(RS5C313_ADDR_MON10) << 4); |
254 | tm->tm_mon = BCD2BIN(data) - 1; | 254 | tm->tm_mon = bcd2bin(data) - 1; |
255 | 255 | ||
256 | data = rs5c313_read_reg(RS5C313_ADDR_YEAR); | 256 | data = rs5c313_read_reg(RS5C313_ADDR_YEAR); |
257 | data |= (rs5c313_read_reg(RS5C313_ADDR_YEAR10) << 4); | 257 | data |= (rs5c313_read_reg(RS5C313_ADDR_YEAR10) << 4); |
258 | tm->tm_year = BCD2BIN(data); | 258 | tm->tm_year = bcd2bin(data); |
259 | 259 | ||
260 | if (tm->tm_year < 70) | 260 | if (tm->tm_year < 70) |
261 | tm->tm_year += 100; | 261 | tm->tm_year += 100; |
262 | 262 | ||
263 | data = rs5c313_read_reg(RS5C313_ADDR_WEEK); | 263 | data = rs5c313_read_reg(RS5C313_ADDR_WEEK); |
264 | tm->tm_wday = BCD2BIN(data); | 264 | tm->tm_wday = bcd2bin(data); |
265 | 265 | ||
266 | RS5C313_CEDISABLE; | 266 | RS5C313_CEDISABLE; |
267 | ndelay(700); /* CE:L */ | 267 | ndelay(700); /* CE:L */ |
@@ -294,31 +294,31 @@ static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
294 | } | 294 | } |
295 | } | 295 | } |
296 | 296 | ||
297 | data = BIN2BCD(tm->tm_sec); | 297 | data = bin2bcd(tm->tm_sec); |
298 | rs5c313_write_reg(RS5C313_ADDR_SEC, data); | 298 | rs5c313_write_reg(RS5C313_ADDR_SEC, data); |
299 | rs5c313_write_reg(RS5C313_ADDR_SEC10, (data >> 4)); | 299 | rs5c313_write_reg(RS5C313_ADDR_SEC10, (data >> 4)); |
300 | 300 | ||
301 | data = BIN2BCD(tm->tm_min); | 301 | data = bin2bcd(tm->tm_min); |
302 | rs5c313_write_reg(RS5C313_ADDR_MIN, data ); | 302 | rs5c313_write_reg(RS5C313_ADDR_MIN, data ); |
303 | rs5c313_write_reg(RS5C313_ADDR_MIN10, (data >> 4)); | 303 | rs5c313_write_reg(RS5C313_ADDR_MIN10, (data >> 4)); |
304 | 304 | ||
305 | data = BIN2BCD(tm->tm_hour); | 305 | data = bin2bcd(tm->tm_hour); |
306 | rs5c313_write_reg(RS5C313_ADDR_HOUR, data); | 306 | rs5c313_write_reg(RS5C313_ADDR_HOUR, data); |
307 | rs5c313_write_reg(RS5C313_ADDR_HOUR10, (data >> 4)); | 307 | rs5c313_write_reg(RS5C313_ADDR_HOUR10, (data >> 4)); |
308 | 308 | ||
309 | data = BIN2BCD(tm->tm_mday); | 309 | data = bin2bcd(tm->tm_mday); |
310 | rs5c313_write_reg(RS5C313_ADDR_DAY, data); | 310 | rs5c313_write_reg(RS5C313_ADDR_DAY, data); |
311 | rs5c313_write_reg(RS5C313_ADDR_DAY10, (data>> 4)); | 311 | rs5c313_write_reg(RS5C313_ADDR_DAY10, (data>> 4)); |
312 | 312 | ||
313 | data = BIN2BCD(tm->tm_mon + 1); | 313 | data = bin2bcd(tm->tm_mon + 1); |
314 | rs5c313_write_reg(RS5C313_ADDR_MON, data); | 314 | rs5c313_write_reg(RS5C313_ADDR_MON, data); |
315 | rs5c313_write_reg(RS5C313_ADDR_MON10, (data >> 4)); | 315 | rs5c313_write_reg(RS5C313_ADDR_MON10, (data >> 4)); |
316 | 316 | ||
317 | data = BIN2BCD(tm->tm_year % 100); | 317 | data = bin2bcd(tm->tm_year % 100); |
318 | rs5c313_write_reg(RS5C313_ADDR_YEAR, data); | 318 | rs5c313_write_reg(RS5C313_ADDR_YEAR, data); |
319 | rs5c313_write_reg(RS5C313_ADDR_YEAR10, (data >> 4)); | 319 | rs5c313_write_reg(RS5C313_ADDR_YEAR10, (data >> 4)); |
320 | 320 | ||
321 | data = BIN2BCD(tm->tm_wday); | 321 | data = bin2bcd(tm->tm_wday); |
322 | rs5c313_write_reg(RS5C313_ADDR_WEEK, data); | 322 | rs5c313_write_reg(RS5C313_ADDR_WEEK, data); |
323 | 323 | ||
324 | RS5C313_CEDISABLE; /* CE:H */ | 324 | RS5C313_CEDISABLE; /* CE:H */ |
diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index 839462659afa..dd1e2bc7a472 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c | |||
@@ -74,20 +74,20 @@ rs5c348_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
74 | txbuf[3] = 0; /* dummy */ | 74 | txbuf[3] = 0; /* dummy */ |
75 | txbuf[4] = RS5C348_CMD_MW(RS5C348_REG_SECS); /* cmd, sec, ... */ | 75 | txbuf[4] = RS5C348_CMD_MW(RS5C348_REG_SECS); /* cmd, sec, ... */ |
76 | txp = &txbuf[5]; | 76 | txp = &txbuf[5]; |
77 | txp[RS5C348_REG_SECS] = BIN2BCD(tm->tm_sec); | 77 | txp[RS5C348_REG_SECS] = bin2bcd(tm->tm_sec); |
78 | txp[RS5C348_REG_MINS] = BIN2BCD(tm->tm_min); | 78 | txp[RS5C348_REG_MINS] = bin2bcd(tm->tm_min); |
79 | if (pdata->rtc_24h) { | 79 | if (pdata->rtc_24h) { |
80 | txp[RS5C348_REG_HOURS] = BIN2BCD(tm->tm_hour); | 80 | txp[RS5C348_REG_HOURS] = bin2bcd(tm->tm_hour); |
81 | } else { | 81 | } else { |
82 | /* hour 0 is AM12, noon is PM12 */ | 82 | /* hour 0 is AM12, noon is PM12 */ |
83 | txp[RS5C348_REG_HOURS] = BIN2BCD((tm->tm_hour + 11) % 12 + 1) | | 83 | txp[RS5C348_REG_HOURS] = bin2bcd((tm->tm_hour + 11) % 12 + 1) | |
84 | (tm->tm_hour >= 12 ? RS5C348_BIT_PM : 0); | 84 | (tm->tm_hour >= 12 ? RS5C348_BIT_PM : 0); |
85 | } | 85 | } |
86 | txp[RS5C348_REG_WDAY] = BIN2BCD(tm->tm_wday); | 86 | txp[RS5C348_REG_WDAY] = bin2bcd(tm->tm_wday); |
87 | txp[RS5C348_REG_DAY] = BIN2BCD(tm->tm_mday); | 87 | txp[RS5C348_REG_DAY] = bin2bcd(tm->tm_mday); |
88 | txp[RS5C348_REG_MONTH] = BIN2BCD(tm->tm_mon + 1) | | 88 | txp[RS5C348_REG_MONTH] = bin2bcd(tm->tm_mon + 1) | |
89 | (tm->tm_year >= 100 ? RS5C348_BIT_Y2K : 0); | 89 | (tm->tm_year >= 100 ? RS5C348_BIT_Y2K : 0); |
90 | txp[RS5C348_REG_YEAR] = BIN2BCD(tm->tm_year % 100); | 90 | txp[RS5C348_REG_YEAR] = bin2bcd(tm->tm_year % 100); |
91 | /* write in one transfer to avoid data inconsistency */ | 91 | /* write in one transfer to avoid data inconsistency */ |
92 | ret = spi_write_then_read(spi, txbuf, sizeof(txbuf), NULL, 0); | 92 | ret = spi_write_then_read(spi, txbuf, sizeof(txbuf), NULL, 0); |
93 | udelay(62); /* Tcsr 62us */ | 93 | udelay(62); /* Tcsr 62us */ |
@@ -116,20 +116,20 @@ rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
116 | if (ret < 0) | 116 | if (ret < 0) |
117 | return ret; | 117 | return ret; |
118 | 118 | ||
119 | tm->tm_sec = BCD2BIN(rxbuf[RS5C348_REG_SECS] & RS5C348_SECS_MASK); | 119 | tm->tm_sec = bcd2bin(rxbuf[RS5C348_REG_SECS] & RS5C348_SECS_MASK); |
120 | tm->tm_min = BCD2BIN(rxbuf[RS5C348_REG_MINS] & RS5C348_MINS_MASK); | 120 | tm->tm_min = bcd2bin(rxbuf[RS5C348_REG_MINS] & RS5C348_MINS_MASK); |
121 | tm->tm_hour = BCD2BIN(rxbuf[RS5C348_REG_HOURS] & RS5C348_HOURS_MASK); | 121 | tm->tm_hour = bcd2bin(rxbuf[RS5C348_REG_HOURS] & RS5C348_HOURS_MASK); |
122 | if (!pdata->rtc_24h) { | 122 | if (!pdata->rtc_24h) { |
123 | tm->tm_hour %= 12; | 123 | tm->tm_hour %= 12; |
124 | if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM) | 124 | if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM) |
125 | tm->tm_hour += 12; | 125 | tm->tm_hour += 12; |
126 | } | 126 | } |
127 | tm->tm_wday = BCD2BIN(rxbuf[RS5C348_REG_WDAY] & RS5C348_WDAY_MASK); | 127 | tm->tm_wday = bcd2bin(rxbuf[RS5C348_REG_WDAY] & RS5C348_WDAY_MASK); |
128 | tm->tm_mday = BCD2BIN(rxbuf[RS5C348_REG_DAY] & RS5C348_DAY_MASK); | 128 | tm->tm_mday = bcd2bin(rxbuf[RS5C348_REG_DAY] & RS5C348_DAY_MASK); |
129 | tm->tm_mon = | 129 | tm->tm_mon = |
130 | BCD2BIN(rxbuf[RS5C348_REG_MONTH] & RS5C348_MONTH_MASK) - 1; | 130 | bcd2bin(rxbuf[RS5C348_REG_MONTH] & RS5C348_MONTH_MASK) - 1; |
131 | /* year is 1900 + tm->tm_year */ | 131 | /* year is 1900 + tm->tm_year */ |
132 | tm->tm_year = BCD2BIN(rxbuf[RS5C348_REG_YEAR]) + | 132 | tm->tm_year = bcd2bin(rxbuf[RS5C348_REG_YEAR]) + |
133 | ((rxbuf[RS5C348_REG_MONTH] & RS5C348_BIT_Y2K) ? 100 : 0); | 133 | ((rxbuf[RS5C348_REG_MONTH] & RS5C348_BIT_Y2K) ? 100 : 0); |
134 | 134 | ||
135 | if (rtc_valid_tm(tm) < 0) { | 135 | if (rtc_valid_tm(tm) < 0) { |
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 56caf6b2c3e5..2f2c68d476da 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c | |||
@@ -1,8 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * An I2C driver for Ricoh RS5C372 and RV5C38[67] RTCs | 2 | * An I2C driver for Ricoh RS5C372, R2025S/D and RV5C38[67] RTCs |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Pavel Mironchik <pmironchik@optifacio.net> | 4 | * Copyright (C) 2005 Pavel Mironchik <pmironchik@optifacio.net> |
5 | * Copyright (C) 2006 Tower Technologies | 5 | * Copyright (C) 2006 Tower Technologies |
6 | * Copyright (C) 2008 Paul Mundt | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -13,7 +14,7 @@ | |||
13 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
14 | #include <linux/bcd.h> | 15 | #include <linux/bcd.h> |
15 | 16 | ||
16 | #define DRV_VERSION "0.5" | 17 | #define DRV_VERSION "0.6" |
17 | 18 | ||
18 | 19 | ||
19 | /* | 20 | /* |
@@ -51,7 +52,8 @@ | |||
51 | # define RS5C_CTRL1_CT4 (4 << 0) /* 1 Hz level irq */ | 52 | # define RS5C_CTRL1_CT4 (4 << 0) /* 1 Hz level irq */ |
52 | #define RS5C_REG_CTRL2 15 | 53 | #define RS5C_REG_CTRL2 15 |
53 | # define RS5C372_CTRL2_24 (1 << 5) | 54 | # define RS5C372_CTRL2_24 (1 << 5) |
54 | # define RS5C_CTRL2_XSTP (1 << 4) | 55 | # define R2025_CTRL2_XST (1 << 5) |
56 | # define RS5C_CTRL2_XSTP (1 << 4) /* only if !R2025S/D */ | ||
55 | # define RS5C_CTRL2_CTFG (1 << 2) | 57 | # define RS5C_CTRL2_CTFG (1 << 2) |
56 | # define RS5C_CTRL2_AAFG (1 << 1) /* or WAFG */ | 58 | # define RS5C_CTRL2_AAFG (1 << 1) /* or WAFG */ |
57 | # define RS5C_CTRL2_BAFG (1 << 0) /* or DAFG */ | 59 | # define RS5C_CTRL2_BAFG (1 << 0) /* or DAFG */ |
@@ -63,6 +65,7 @@ | |||
63 | 65 | ||
64 | enum rtc_type { | 66 | enum rtc_type { |
65 | rtc_undef = 0, | 67 | rtc_undef = 0, |
68 | rtc_r2025sd, | ||
66 | rtc_rs5c372a, | 69 | rtc_rs5c372a, |
67 | rtc_rs5c372b, | 70 | rtc_rs5c372b, |
68 | rtc_rv5c386, | 71 | rtc_rv5c386, |
@@ -70,6 +73,7 @@ enum rtc_type { | |||
70 | }; | 73 | }; |
71 | 74 | ||
72 | static const struct i2c_device_id rs5c372_id[] = { | 75 | static const struct i2c_device_id rs5c372_id[] = { |
76 | { "r2025sd", rtc_r2025sd }, | ||
73 | { "rs5c372a", rtc_rs5c372a }, | 77 | { "rs5c372a", rtc_rs5c372a }, |
74 | { "rs5c372b", rtc_rs5c372b }, | 78 | { "rs5c372b", rtc_rs5c372b }, |
75 | { "rv5c386", rtc_rv5c386 }, | 79 | { "rv5c386", rtc_rv5c386 }, |
@@ -89,6 +93,7 @@ struct rs5c372 { | |||
89 | enum rtc_type type; | 93 | enum rtc_type type; |
90 | unsigned time24:1; | 94 | unsigned time24:1; |
91 | unsigned has_irq:1; | 95 | unsigned has_irq:1; |
96 | unsigned smbus:1; | ||
92 | char buf[17]; | 97 | char buf[17]; |
93 | char *regs; | 98 | char *regs; |
94 | }; | 99 | }; |
@@ -106,10 +111,25 @@ static int rs5c_get_regs(struct rs5c372 *rs5c) | |||
106 | * | 111 | * |
107 | * The first method doesn't work with the iop3xx adapter driver, on at | 112 | * The first method doesn't work with the iop3xx adapter driver, on at |
108 | * least 80219 chips; this works around that bug. | 113 | * least 80219 chips; this works around that bug. |
114 | * | ||
115 | * The third method on the other hand doesn't work for the SMBus-only | ||
116 | * configurations, so we use the the first method there, stripping off | ||
117 | * the extra register in the process. | ||
109 | */ | 118 | */ |
110 | if ((i2c_transfer(client->adapter, msgs, 1)) != 1) { | 119 | if (rs5c->smbus) { |
111 | dev_warn(&client->dev, "can't read registers\n"); | 120 | int addr = RS5C_ADDR(RS5C372_REG_SECS); |
112 | return -EIO; | 121 | int size = sizeof(rs5c->buf) - 1; |
122 | |||
123 | if (i2c_smbus_read_i2c_block_data(client, addr, size, | ||
124 | rs5c->buf + 1) != size) { | ||
125 | dev_warn(&client->dev, "can't read registers\n"); | ||
126 | return -EIO; | ||
127 | } | ||
128 | } else { | ||
129 | if ((i2c_transfer(client->adapter, msgs, 1)) != 1) { | ||
130 | dev_warn(&client->dev, "can't read registers\n"); | ||
131 | return -EIO; | ||
132 | } | ||
113 | } | 133 | } |
114 | 134 | ||
115 | dev_dbg(&client->dev, | 135 | dev_dbg(&client->dev, |
@@ -128,9 +148,9 @@ static unsigned rs5c_reg2hr(struct rs5c372 *rs5c, unsigned reg) | |||
128 | unsigned hour; | 148 | unsigned hour; |
129 | 149 | ||
130 | if (rs5c->time24) | 150 | if (rs5c->time24) |
131 | return BCD2BIN(reg & 0x3f); | 151 | return bcd2bin(reg & 0x3f); |
132 | 152 | ||
133 | hour = BCD2BIN(reg & 0x1f); | 153 | hour = bcd2bin(reg & 0x1f); |
134 | if (hour == 12) | 154 | if (hour == 12) |
135 | hour = 0; | 155 | hour = 0; |
136 | if (reg & 0x20) | 156 | if (reg & 0x20) |
@@ -141,15 +161,15 @@ static unsigned rs5c_reg2hr(struct rs5c372 *rs5c, unsigned reg) | |||
141 | static unsigned rs5c_hr2reg(struct rs5c372 *rs5c, unsigned hour) | 161 | static unsigned rs5c_hr2reg(struct rs5c372 *rs5c, unsigned hour) |
142 | { | 162 | { |
143 | if (rs5c->time24) | 163 | if (rs5c->time24) |
144 | return BIN2BCD(hour); | 164 | return bin2bcd(hour); |
145 | 165 | ||
146 | if (hour > 12) | 166 | if (hour > 12) |
147 | return 0x20 | BIN2BCD(hour - 12); | 167 | return 0x20 | bin2bcd(hour - 12); |
148 | if (hour == 12) | 168 | if (hour == 12) |
149 | return 0x20 | BIN2BCD(12); | 169 | return 0x20 | bin2bcd(12); |
150 | if (hour == 0) | 170 | if (hour == 0) |
151 | return BIN2BCD(12); | 171 | return bin2bcd(12); |
152 | return BIN2BCD(hour); | 172 | return bin2bcd(hour); |
153 | } | 173 | } |
154 | 174 | ||
155 | static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm) | 175 | static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm) |
@@ -160,18 +180,18 @@ static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
160 | if (status < 0) | 180 | if (status < 0) |
161 | return status; | 181 | return status; |
162 | 182 | ||
163 | tm->tm_sec = BCD2BIN(rs5c->regs[RS5C372_REG_SECS] & 0x7f); | 183 | tm->tm_sec = bcd2bin(rs5c->regs[RS5C372_REG_SECS] & 0x7f); |
164 | tm->tm_min = BCD2BIN(rs5c->regs[RS5C372_REG_MINS] & 0x7f); | 184 | tm->tm_min = bcd2bin(rs5c->regs[RS5C372_REG_MINS] & 0x7f); |
165 | tm->tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C372_REG_HOURS]); | 185 | tm->tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C372_REG_HOURS]); |
166 | 186 | ||
167 | tm->tm_wday = BCD2BIN(rs5c->regs[RS5C372_REG_WDAY] & 0x07); | 187 | tm->tm_wday = bcd2bin(rs5c->regs[RS5C372_REG_WDAY] & 0x07); |
168 | tm->tm_mday = BCD2BIN(rs5c->regs[RS5C372_REG_DAY] & 0x3f); | 188 | tm->tm_mday = bcd2bin(rs5c->regs[RS5C372_REG_DAY] & 0x3f); |
169 | 189 | ||
170 | /* tm->tm_mon is zero-based */ | 190 | /* tm->tm_mon is zero-based */ |
171 | tm->tm_mon = BCD2BIN(rs5c->regs[RS5C372_REG_MONTH] & 0x1f) - 1; | 191 | tm->tm_mon = bcd2bin(rs5c->regs[RS5C372_REG_MONTH] & 0x1f) - 1; |
172 | 192 | ||
173 | /* year is 1900 + tm->tm_year */ | 193 | /* year is 1900 + tm->tm_year */ |
174 | tm->tm_year = BCD2BIN(rs5c->regs[RS5C372_REG_YEAR]) + 100; | 194 | tm->tm_year = bcd2bin(rs5c->regs[RS5C372_REG_YEAR]) + 100; |
175 | 195 | ||
176 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " | 196 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " |
177 | "mday=%d, mon=%d, year=%d, wday=%d\n", | 197 | "mday=%d, mon=%d, year=%d, wday=%d\n", |
@@ -187,6 +207,7 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
187 | { | 207 | { |
188 | struct rs5c372 *rs5c = i2c_get_clientdata(client); | 208 | struct rs5c372 *rs5c = i2c_get_clientdata(client); |
189 | unsigned char buf[8]; | 209 | unsigned char buf[8]; |
210 | int addr; | ||
190 | 211 | ||
191 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d " | 212 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d " |
192 | "mday=%d, mon=%d, year=%d, wday=%d\n", | 213 | "mday=%d, mon=%d, year=%d, wday=%d\n", |
@@ -194,16 +215,16 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
194 | tm->tm_sec, tm->tm_min, tm->tm_hour, | 215 | tm->tm_sec, tm->tm_min, tm->tm_hour, |
195 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | 216 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); |
196 | 217 | ||
197 | buf[0] = RS5C_ADDR(RS5C372_REG_SECS); | 218 | addr = RS5C_ADDR(RS5C372_REG_SECS); |
198 | buf[1] = BIN2BCD(tm->tm_sec); | 219 | buf[0] = bin2bcd(tm->tm_sec); |
199 | buf[2] = BIN2BCD(tm->tm_min); | 220 | buf[1] = bin2bcd(tm->tm_min); |
200 | buf[3] = rs5c_hr2reg(rs5c, tm->tm_hour); | 221 | buf[2] = rs5c_hr2reg(rs5c, tm->tm_hour); |
201 | buf[4] = BIN2BCD(tm->tm_wday); | 222 | buf[3] = bin2bcd(tm->tm_wday); |
202 | buf[5] = BIN2BCD(tm->tm_mday); | 223 | buf[4] = bin2bcd(tm->tm_mday); |
203 | buf[6] = BIN2BCD(tm->tm_mon + 1); | 224 | buf[5] = bin2bcd(tm->tm_mon + 1); |
204 | buf[7] = BIN2BCD(tm->tm_year - 100); | 225 | buf[6] = bin2bcd(tm->tm_year - 100); |
205 | 226 | ||
206 | if ((i2c_master_send(client, buf, 8)) != 8) { | 227 | if (i2c_smbus_write_i2c_block_data(client, addr, sizeof(buf), buf) < 0) { |
207 | dev_err(&client->dev, "%s: write error\n", __func__); | 228 | dev_err(&client->dev, "%s: write error\n", __func__); |
208 | return -EIO; | 229 | return -EIO; |
209 | } | 230 | } |
@@ -266,16 +287,16 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
266 | { | 287 | { |
267 | struct i2c_client *client = to_i2c_client(dev); | 288 | struct i2c_client *client = to_i2c_client(dev); |
268 | struct rs5c372 *rs5c = i2c_get_clientdata(client); | 289 | struct rs5c372 *rs5c = i2c_get_clientdata(client); |
269 | unsigned char buf[2]; | 290 | unsigned char buf; |
270 | int status; | 291 | int status, addr; |
271 | 292 | ||
272 | buf[1] = rs5c->regs[RS5C_REG_CTRL1]; | 293 | buf = rs5c->regs[RS5C_REG_CTRL1]; |
273 | switch (cmd) { | 294 | switch (cmd) { |
274 | case RTC_UIE_OFF: | 295 | case RTC_UIE_OFF: |
275 | case RTC_UIE_ON: | 296 | case RTC_UIE_ON: |
276 | /* some 327a modes use a different IRQ pin for 1Hz irqs */ | 297 | /* some 327a modes use a different IRQ pin for 1Hz irqs */ |
277 | if (rs5c->type == rtc_rs5c372a | 298 | if (rs5c->type == rtc_rs5c372a |
278 | && (buf[1] & RS5C372A_CTRL1_SL1)) | 299 | && (buf & RS5C372A_CTRL1_SL1)) |
279 | return -ENOIOCTLCMD; | 300 | return -ENOIOCTLCMD; |
280 | case RTC_AIE_OFF: | 301 | case RTC_AIE_OFF: |
281 | case RTC_AIE_ON: | 302 | case RTC_AIE_ON: |
@@ -293,28 +314,30 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
293 | if (status < 0) | 314 | if (status < 0) |
294 | return status; | 315 | return status; |
295 | 316 | ||
296 | buf[0] = RS5C_ADDR(RS5C_REG_CTRL1); | 317 | addr = RS5C_ADDR(RS5C_REG_CTRL1); |
297 | switch (cmd) { | 318 | switch (cmd) { |
298 | case RTC_AIE_OFF: /* alarm off */ | 319 | case RTC_AIE_OFF: /* alarm off */ |
299 | buf[1] &= ~RS5C_CTRL1_AALE; | 320 | buf &= ~RS5C_CTRL1_AALE; |
300 | break; | 321 | break; |
301 | case RTC_AIE_ON: /* alarm on */ | 322 | case RTC_AIE_ON: /* alarm on */ |
302 | buf[1] |= RS5C_CTRL1_AALE; | 323 | buf |= RS5C_CTRL1_AALE; |
303 | break; | 324 | break; |
304 | case RTC_UIE_OFF: /* update off */ | 325 | case RTC_UIE_OFF: /* update off */ |
305 | buf[1] &= ~RS5C_CTRL1_CT_MASK; | 326 | buf &= ~RS5C_CTRL1_CT_MASK; |
306 | break; | 327 | break; |
307 | case RTC_UIE_ON: /* update on */ | 328 | case RTC_UIE_ON: /* update on */ |
308 | buf[1] &= ~RS5C_CTRL1_CT_MASK; | 329 | buf &= ~RS5C_CTRL1_CT_MASK; |
309 | buf[1] |= RS5C_CTRL1_CT4; | 330 | buf |= RS5C_CTRL1_CT4; |
310 | break; | 331 | break; |
311 | } | 332 | } |
312 | if ((i2c_master_send(client, buf, 2)) != 2) { | 333 | |
334 | if (i2c_smbus_write_byte_data(client, addr, buf) < 0) { | ||
313 | printk(KERN_WARNING "%s: can't update alarm\n", | 335 | printk(KERN_WARNING "%s: can't update alarm\n", |
314 | rs5c->rtc->name); | 336 | rs5c->rtc->name); |
315 | status = -EIO; | 337 | status = -EIO; |
316 | } else | 338 | } else |
317 | rs5c->regs[RS5C_REG_CTRL1] = buf[1]; | 339 | rs5c->regs[RS5C_REG_CTRL1] = buf; |
340 | |||
318 | return status; | 341 | return status; |
319 | } | 342 | } |
320 | 343 | ||
@@ -344,7 +367,7 @@ static int rs5c_read_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
344 | 367 | ||
345 | /* report alarm time */ | 368 | /* report alarm time */ |
346 | t->time.tm_sec = 0; | 369 | t->time.tm_sec = 0; |
347 | t->time.tm_min = BCD2BIN(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f); | 370 | t->time.tm_min = bcd2bin(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f); |
348 | t->time.tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C_REG_ALARM_A_HOURS]); | 371 | t->time.tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C_REG_ALARM_A_HOURS]); |
349 | t->time.tm_mday = -1; | 372 | t->time.tm_mday = -1; |
350 | t->time.tm_mon = -1; | 373 | t->time.tm_mon = -1; |
@@ -364,8 +387,8 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
364 | { | 387 | { |
365 | struct i2c_client *client = to_i2c_client(dev); | 388 | struct i2c_client *client = to_i2c_client(dev); |
366 | struct rs5c372 *rs5c = i2c_get_clientdata(client); | 389 | struct rs5c372 *rs5c = i2c_get_clientdata(client); |
367 | int status; | 390 | int status, addr, i; |
368 | unsigned char buf[4]; | 391 | unsigned char buf[3]; |
369 | 392 | ||
370 | /* only handle up to 24 hours in the future, like RTC_ALM_SET */ | 393 | /* only handle up to 24 hours in the future, like RTC_ALM_SET */ |
371 | if (t->time.tm_mday != -1 | 394 | if (t->time.tm_mday != -1 |
@@ -380,33 +403,36 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
380 | if (status < 0) | 403 | if (status < 0) |
381 | return status; | 404 | return status; |
382 | if (rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE) { | 405 | if (rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE) { |
383 | buf[0] = RS5C_ADDR(RS5C_REG_CTRL1); | 406 | addr = RS5C_ADDR(RS5C_REG_CTRL1); |
384 | buf[1] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE; | 407 | buf[0] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE; |
385 | if (i2c_master_send(client, buf, 2) != 2) { | 408 | if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) { |
386 | pr_debug("%s: can't disable alarm\n", rs5c->rtc->name); | 409 | pr_debug("%s: can't disable alarm\n", rs5c->rtc->name); |
387 | return -EIO; | 410 | return -EIO; |
388 | } | 411 | } |
389 | rs5c->regs[RS5C_REG_CTRL1] = buf[1]; | 412 | rs5c->regs[RS5C_REG_CTRL1] = buf[0]; |
390 | } | 413 | } |
391 | 414 | ||
392 | /* set alarm */ | 415 | /* set alarm */ |
393 | buf[0] = RS5C_ADDR(RS5C_REG_ALARM_A_MIN); | 416 | buf[0] = bin2bcd(t->time.tm_min); |
394 | buf[1] = BIN2BCD(t->time.tm_min); | 417 | buf[1] = rs5c_hr2reg(rs5c, t->time.tm_hour); |
395 | buf[2] = rs5c_hr2reg(rs5c, t->time.tm_hour); | 418 | buf[2] = 0x7f; /* any/all days */ |
396 | buf[3] = 0x7f; /* any/all days */ | 419 | |
397 | if ((i2c_master_send(client, buf, 4)) != 4) { | 420 | for (i = 0; i < sizeof(buf); i++) { |
398 | pr_debug("%s: can't set alarm time\n", rs5c->rtc->name); | 421 | addr = RS5C_ADDR(RS5C_REG_ALARM_A_MIN + i); |
399 | return -EIO; | 422 | if (i2c_smbus_write_byte_data(client, addr, buf[i]) < 0) { |
423 | pr_debug("%s: can't set alarm time\n", rs5c->rtc->name); | ||
424 | return -EIO; | ||
425 | } | ||
400 | } | 426 | } |
401 | 427 | ||
402 | /* ... and maybe enable its irq */ | 428 | /* ... and maybe enable its irq */ |
403 | if (t->enabled) { | 429 | if (t->enabled) { |
404 | buf[0] = RS5C_ADDR(RS5C_REG_CTRL1); | 430 | addr = RS5C_ADDR(RS5C_REG_CTRL1); |
405 | buf[1] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE; | 431 | buf[0] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE; |
406 | if ((i2c_master_send(client, buf, 2)) != 2) | 432 | if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) |
407 | printk(KERN_WARNING "%s: can't enable alarm\n", | 433 | printk(KERN_WARNING "%s: can't enable alarm\n", |
408 | rs5c->rtc->name); | 434 | rs5c->rtc->name); |
409 | rs5c->regs[RS5C_REG_CTRL1] = buf[1]; | 435 | rs5c->regs[RS5C_REG_CTRL1] = buf[0]; |
410 | } | 436 | } |
411 | 437 | ||
412 | return 0; | 438 | return 0; |
@@ -503,18 +529,81 @@ static void rs5c_sysfs_unregister(struct device *dev) | |||
503 | 529 | ||
504 | static struct i2c_driver rs5c372_driver; | 530 | static struct i2c_driver rs5c372_driver; |
505 | 531 | ||
532 | static int rs5c_oscillator_setup(struct rs5c372 *rs5c372) | ||
533 | { | ||
534 | unsigned char buf[2]; | ||
535 | int addr, i, ret = 0; | ||
536 | |||
537 | if (rs5c372->type == rtc_r2025sd) { | ||
538 | if (!(rs5c372->regs[RS5C_REG_CTRL2] & R2025_CTRL2_XST)) | ||
539 | return ret; | ||
540 | rs5c372->regs[RS5C_REG_CTRL2] &= ~R2025_CTRL2_XST; | ||
541 | } else { | ||
542 | if (!(rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP)) | ||
543 | return ret; | ||
544 | rs5c372->regs[RS5C_REG_CTRL2] &= ~RS5C_CTRL2_XSTP; | ||
545 | } | ||
546 | |||
547 | addr = RS5C_ADDR(RS5C_REG_CTRL1); | ||
548 | buf[0] = rs5c372->regs[RS5C_REG_CTRL1]; | ||
549 | buf[1] = rs5c372->regs[RS5C_REG_CTRL2]; | ||
550 | |||
551 | /* use 24hr mode */ | ||
552 | switch (rs5c372->type) { | ||
553 | case rtc_rs5c372a: | ||
554 | case rtc_rs5c372b: | ||
555 | buf[1] |= RS5C372_CTRL2_24; | ||
556 | rs5c372->time24 = 1; | ||
557 | break; | ||
558 | case rtc_r2025sd: | ||
559 | case rtc_rv5c386: | ||
560 | case rtc_rv5c387a: | ||
561 | buf[0] |= RV5C387_CTRL1_24; | ||
562 | rs5c372->time24 = 1; | ||
563 | break; | ||
564 | default: | ||
565 | /* impossible */ | ||
566 | break; | ||
567 | } | ||
568 | |||
569 | for (i = 0; i < sizeof(buf); i++) { | ||
570 | addr = RS5C_ADDR(RS5C_REG_CTRL1 + i); | ||
571 | ret = i2c_smbus_write_byte_data(rs5c372->client, addr, buf[i]); | ||
572 | if (unlikely(ret < 0)) | ||
573 | return ret; | ||
574 | } | ||
575 | |||
576 | rs5c372->regs[RS5C_REG_CTRL1] = buf[0]; | ||
577 | rs5c372->regs[RS5C_REG_CTRL2] = buf[1]; | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
506 | static int rs5c372_probe(struct i2c_client *client, | 582 | static int rs5c372_probe(struct i2c_client *client, |
507 | const struct i2c_device_id *id) | 583 | const struct i2c_device_id *id) |
508 | { | 584 | { |
509 | int err = 0; | 585 | int err = 0; |
586 | int smbus_mode = 0; | ||
510 | struct rs5c372 *rs5c372; | 587 | struct rs5c372 *rs5c372; |
511 | struct rtc_time tm; | 588 | struct rtc_time tm; |
512 | 589 | ||
513 | dev_dbg(&client->dev, "%s\n", __func__); | 590 | dev_dbg(&client->dev, "%s\n", __func__); |
514 | 591 | ||
515 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | 592 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | |
516 | err = -ENODEV; | 593 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK)) { |
517 | goto exit; | 594 | /* |
595 | * If we don't have any master mode adapter, try breaking | ||
596 | * it down in to the barest of capabilities. | ||
597 | */ | ||
598 | if (i2c_check_functionality(client->adapter, | ||
599 | I2C_FUNC_SMBUS_BYTE_DATA | | ||
600 | I2C_FUNC_SMBUS_I2C_BLOCK)) | ||
601 | smbus_mode = 1; | ||
602 | else { | ||
603 | /* Still no good, give up */ | ||
604 | err = -ENODEV; | ||
605 | goto exit; | ||
606 | } | ||
518 | } | 607 | } |
519 | 608 | ||
520 | if (!(rs5c372 = kzalloc(sizeof(struct rs5c372), GFP_KERNEL))) { | 609 | if (!(rs5c372 = kzalloc(sizeof(struct rs5c372), GFP_KERNEL))) { |
@@ -528,6 +617,7 @@ static int rs5c372_probe(struct i2c_client *client, | |||
528 | 617 | ||
529 | /* we read registers 0x0f then 0x00-0x0f; skip the first one */ | 618 | /* we read registers 0x0f then 0x00-0x0f; skip the first one */ |
530 | rs5c372->regs = &rs5c372->buf[1]; | 619 | rs5c372->regs = &rs5c372->buf[1]; |
620 | rs5c372->smbus = smbus_mode; | ||
531 | 621 | ||
532 | err = rs5c_get_regs(rs5c372); | 622 | err = rs5c_get_regs(rs5c372); |
533 | if (err < 0) | 623 | if (err < 0) |
@@ -543,6 +633,7 @@ static int rs5c372_probe(struct i2c_client *client, | |||
543 | if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C372_CTRL2_24) | 633 | if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C372_CTRL2_24) |
544 | rs5c372->time24 = 1; | 634 | rs5c372->time24 = 1; |
545 | break; | 635 | break; |
636 | case rtc_r2025sd: | ||
546 | case rtc_rv5c386: | 637 | case rtc_rv5c386: |
547 | case rtc_rv5c387a: | 638 | case rtc_rv5c387a: |
548 | if (rs5c372->regs[RS5C_REG_CTRL1] & RV5C387_CTRL1_24) | 639 | if (rs5c372->regs[RS5C_REG_CTRL1] & RV5C387_CTRL1_24) |
@@ -558,39 +649,14 @@ static int rs5c372_probe(struct i2c_client *client, | |||
558 | 649 | ||
559 | /* if the oscillator lost power and no other software (like | 650 | /* if the oscillator lost power and no other software (like |
560 | * the bootloader) set it up, do it here. | 651 | * the bootloader) set it up, do it here. |
652 | * | ||
653 | * The R2025S/D does this a little differently than the other | ||
654 | * parts, so we special case that.. | ||
561 | */ | 655 | */ |
562 | if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP) { | 656 | err = rs5c_oscillator_setup(rs5c372); |
563 | unsigned char buf[3]; | 657 | if (unlikely(err < 0)) { |
564 | 658 | dev_err(&client->dev, "setup error\n"); | |
565 | rs5c372->regs[RS5C_REG_CTRL2] &= ~RS5C_CTRL2_XSTP; | 659 | goto exit_kfree; |
566 | |||
567 | buf[0] = RS5C_ADDR(RS5C_REG_CTRL1); | ||
568 | buf[1] = rs5c372->regs[RS5C_REG_CTRL1]; | ||
569 | buf[2] = rs5c372->regs[RS5C_REG_CTRL2]; | ||
570 | |||
571 | /* use 24hr mode */ | ||
572 | switch (rs5c372->type) { | ||
573 | case rtc_rs5c372a: | ||
574 | case rtc_rs5c372b: | ||
575 | buf[2] |= RS5C372_CTRL2_24; | ||
576 | rs5c372->time24 = 1; | ||
577 | break; | ||
578 | case rtc_rv5c386: | ||
579 | case rtc_rv5c387a: | ||
580 | buf[1] |= RV5C387_CTRL1_24; | ||
581 | rs5c372->time24 = 1; | ||
582 | break; | ||
583 | default: | ||
584 | /* impossible */ | ||
585 | break; | ||
586 | } | ||
587 | |||
588 | if ((i2c_master_send(client, buf, 3)) != 3) { | ||
589 | dev_err(&client->dev, "setup error\n"); | ||
590 | goto exit_kfree; | ||
591 | } | ||
592 | rs5c372->regs[RS5C_REG_CTRL1] = buf[1]; | ||
593 | rs5c372->regs[RS5C_REG_CTRL2] = buf[2]; | ||
594 | } | 660 | } |
595 | 661 | ||
596 | if (rs5c372_get_datetime(client, &tm) < 0) | 662 | if (rs5c372_get_datetime(client, &tm) < 0) |
@@ -598,6 +664,7 @@ static int rs5c372_probe(struct i2c_client *client, | |||
598 | 664 | ||
599 | dev_info(&client->dev, "%s found, %s, driver version " DRV_VERSION "\n", | 665 | dev_info(&client->dev, "%s found, %s, driver version " DRV_VERSION "\n", |
600 | ({ char *s; switch (rs5c372->type) { | 666 | ({ char *s; switch (rs5c372->type) { |
667 | case rtc_r2025sd: s = "r2025sd"; break; | ||
601 | case rtc_rs5c372a: s = "rs5c372a"; break; | 668 | case rtc_rs5c372a: s = "rs5c372a"; break; |
602 | case rtc_rs5c372b: s = "rs5c372b"; break; | 669 | case rtc_rs5c372b: s = "rs5c372b"; break; |
603 | case rtc_rv5c386: s = "rv5c386"; break; | 670 | case rtc_rv5c386: s = "rv5c386"; break; |
@@ -667,7 +734,8 @@ module_exit(rs5c372_exit); | |||
667 | 734 | ||
668 | MODULE_AUTHOR( | 735 | MODULE_AUTHOR( |
669 | "Pavel Mironchik <pmironchik@optifacio.net>, " | 736 | "Pavel Mironchik <pmironchik@optifacio.net>, " |
670 | "Alessandro Zummo <a.zummo@towertech.it>"); | 737 | "Alessandro Zummo <a.zummo@towertech.it>, " |
738 | "Paul Mundt <lethal@linux-sh.org>"); | ||
671 | MODULE_DESCRIPTION("Ricoh RS5C372 RTC driver"); | 739 | MODULE_DESCRIPTION("Ricoh RS5C372 RTC driver"); |
672 | MODULE_LICENSE("GPL"); | 740 | MODULE_LICENSE("GPL"); |
673 | MODULE_VERSION(DRV_VERSION); | 741 | MODULE_VERSION(DRV_VERSION); |
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index a6fa1f2f2ca6..def4d396d0b0 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c | |||
@@ -104,12 +104,12 @@ static int s35390a_disable_test_mode(struct s35390a *s35390a) | |||
104 | static char s35390a_hr2reg(struct s35390a *s35390a, int hour) | 104 | static char s35390a_hr2reg(struct s35390a *s35390a, int hour) |
105 | { | 105 | { |
106 | if (s35390a->twentyfourhour) | 106 | if (s35390a->twentyfourhour) |
107 | return BIN2BCD(hour); | 107 | return bin2bcd(hour); |
108 | 108 | ||
109 | if (hour < 12) | 109 | if (hour < 12) |
110 | return BIN2BCD(hour); | 110 | return bin2bcd(hour); |
111 | 111 | ||
112 | return 0x40 | BIN2BCD(hour - 12); | 112 | return 0x40 | bin2bcd(hour - 12); |
113 | } | 113 | } |
114 | 114 | ||
115 | static int s35390a_reg2hr(struct s35390a *s35390a, char reg) | 115 | static int s35390a_reg2hr(struct s35390a *s35390a, char reg) |
@@ -117,9 +117,9 @@ static int s35390a_reg2hr(struct s35390a *s35390a, char reg) | |||
117 | unsigned hour; | 117 | unsigned hour; |
118 | 118 | ||
119 | if (s35390a->twentyfourhour) | 119 | if (s35390a->twentyfourhour) |
120 | return BCD2BIN(reg & 0x3f); | 120 | return bcd2bin(reg & 0x3f); |
121 | 121 | ||
122 | hour = BCD2BIN(reg & 0x3f); | 122 | hour = bcd2bin(reg & 0x3f); |
123 | if (reg & 0x40) | 123 | if (reg & 0x40) |
124 | hour += 12; | 124 | hour += 12; |
125 | 125 | ||
@@ -137,13 +137,13 @@ static int s35390a_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
137 | tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, | 137 | tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, |
138 | tm->tm_wday); | 138 | tm->tm_wday); |
139 | 139 | ||
140 | buf[S35390A_BYTE_YEAR] = BIN2BCD(tm->tm_year - 100); | 140 | buf[S35390A_BYTE_YEAR] = bin2bcd(tm->tm_year - 100); |
141 | buf[S35390A_BYTE_MONTH] = BIN2BCD(tm->tm_mon + 1); | 141 | buf[S35390A_BYTE_MONTH] = bin2bcd(tm->tm_mon + 1); |
142 | buf[S35390A_BYTE_DAY] = BIN2BCD(tm->tm_mday); | 142 | buf[S35390A_BYTE_DAY] = bin2bcd(tm->tm_mday); |
143 | buf[S35390A_BYTE_WDAY] = BIN2BCD(tm->tm_wday); | 143 | buf[S35390A_BYTE_WDAY] = bin2bcd(tm->tm_wday); |
144 | buf[S35390A_BYTE_HOURS] = s35390a_hr2reg(s35390a, tm->tm_hour); | 144 | buf[S35390A_BYTE_HOURS] = s35390a_hr2reg(s35390a, tm->tm_hour); |
145 | buf[S35390A_BYTE_MINS] = BIN2BCD(tm->tm_min); | 145 | buf[S35390A_BYTE_MINS] = bin2bcd(tm->tm_min); |
146 | buf[S35390A_BYTE_SECS] = BIN2BCD(tm->tm_sec); | 146 | buf[S35390A_BYTE_SECS] = bin2bcd(tm->tm_sec); |
147 | 147 | ||
148 | /* This chip expects the bits of each byte to be in reverse order */ | 148 | /* This chip expects the bits of each byte to be in reverse order */ |
149 | for (i = 0; i < 7; ++i) | 149 | for (i = 0; i < 7; ++i) |
@@ -168,13 +168,13 @@ static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
168 | for (i = 0; i < 7; ++i) | 168 | for (i = 0; i < 7; ++i) |
169 | buf[i] = bitrev8(buf[i]); | 169 | buf[i] = bitrev8(buf[i]); |
170 | 170 | ||
171 | tm->tm_sec = BCD2BIN(buf[S35390A_BYTE_SECS]); | 171 | tm->tm_sec = bcd2bin(buf[S35390A_BYTE_SECS]); |
172 | tm->tm_min = BCD2BIN(buf[S35390A_BYTE_MINS]); | 172 | tm->tm_min = bcd2bin(buf[S35390A_BYTE_MINS]); |
173 | tm->tm_hour = s35390a_reg2hr(s35390a, buf[S35390A_BYTE_HOURS]); | 173 | tm->tm_hour = s35390a_reg2hr(s35390a, buf[S35390A_BYTE_HOURS]); |
174 | tm->tm_wday = BCD2BIN(buf[S35390A_BYTE_WDAY]); | 174 | tm->tm_wday = bcd2bin(buf[S35390A_BYTE_WDAY]); |
175 | tm->tm_mday = BCD2BIN(buf[S35390A_BYTE_DAY]); | 175 | tm->tm_mday = bcd2bin(buf[S35390A_BYTE_DAY]); |
176 | tm->tm_mon = BCD2BIN(buf[S35390A_BYTE_MONTH]) - 1; | 176 | tm->tm_mon = bcd2bin(buf[S35390A_BYTE_MONTH]) - 1; |
177 | tm->tm_year = BCD2BIN(buf[S35390A_BYTE_YEAR]) + 100; | 177 | tm->tm_year = bcd2bin(buf[S35390A_BYTE_YEAR]) + 100; |
178 | 178 | ||
179 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, mday=%d, " | 179 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, mday=%d, " |
180 | "mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec, | 180 | "mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec, |
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index fed86e507fdf..910bc704939c 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/log2.h> | 23 | #include <linux/log2.h> |
24 | 24 | ||
25 | #include <asm/hardware.h> | 25 | #include <mach/hardware.h> |
26 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
27 | #include <asm/io.h> | 27 | #include <asm/io.h> |
28 | #include <asm/irq.h> | 28 | #include <asm/irq.h> |
@@ -36,10 +36,8 @@ static struct resource *s3c_rtc_mem; | |||
36 | static void __iomem *s3c_rtc_base; | 36 | static void __iomem *s3c_rtc_base; |
37 | static int s3c_rtc_alarmno = NO_IRQ; | 37 | static int s3c_rtc_alarmno = NO_IRQ; |
38 | static int s3c_rtc_tickno = NO_IRQ; | 38 | static int s3c_rtc_tickno = NO_IRQ; |
39 | static int s3c_rtc_freq = 1; | ||
40 | 39 | ||
41 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); | 40 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); |
42 | static unsigned int tick_count; | ||
43 | 41 | ||
44 | /* IRQ Handlers */ | 42 | /* IRQ Handlers */ |
45 | 43 | ||
@@ -55,7 +53,7 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id) | |||
55 | { | 53 | { |
56 | struct rtc_device *rdev = id; | 54 | struct rtc_device *rdev = id; |
57 | 55 | ||
58 | rtc_update_irq(rdev, tick_count++, RTC_PF | RTC_IRQF); | 56 | rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); |
59 | return IRQ_HANDLED; | 57 | return IRQ_HANDLED; |
60 | } | 58 | } |
61 | 59 | ||
@@ -74,35 +72,37 @@ static void s3c_rtc_setaie(int to) | |||
74 | writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); | 72 | writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); |
75 | } | 73 | } |
76 | 74 | ||
77 | static void s3c_rtc_setpie(int to) | 75 | static int s3c_rtc_setpie(struct device *dev, int enabled) |
78 | { | 76 | { |
79 | unsigned int tmp; | 77 | unsigned int tmp; |
80 | 78 | ||
81 | pr_debug("%s: pie=%d\n", __func__, to); | 79 | pr_debug("%s: pie=%d\n", __func__, enabled); |
82 | 80 | ||
83 | spin_lock_irq(&s3c_rtc_pie_lock); | 81 | spin_lock_irq(&s3c_rtc_pie_lock); |
84 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE; | 82 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE; |
85 | 83 | ||
86 | if (to) | 84 | if (enabled) |
87 | tmp |= S3C2410_TICNT_ENABLE; | 85 | tmp |= S3C2410_TICNT_ENABLE; |
88 | 86 | ||
89 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | 87 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); |
90 | spin_unlock_irq(&s3c_rtc_pie_lock); | 88 | spin_unlock_irq(&s3c_rtc_pie_lock); |
89 | |||
90 | return 0; | ||
91 | } | 91 | } |
92 | 92 | ||
93 | static void s3c_rtc_setfreq(int freq) | 93 | static int s3c_rtc_setfreq(struct device *dev, int freq) |
94 | { | 94 | { |
95 | unsigned int tmp; | 95 | unsigned int tmp; |
96 | 96 | ||
97 | spin_lock_irq(&s3c_rtc_pie_lock); | 97 | spin_lock_irq(&s3c_rtc_pie_lock); |
98 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE; | ||
99 | |||
100 | s3c_rtc_freq = freq; | ||
101 | 98 | ||
99 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE; | ||
102 | tmp |= (128 / freq)-1; | 100 | tmp |= (128 / freq)-1; |
103 | 101 | ||
104 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | 102 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); |
105 | spin_unlock_irq(&s3c_rtc_pie_lock); | 103 | spin_unlock_irq(&s3c_rtc_pie_lock); |
104 | |||
105 | return 0; | ||
106 | } | 106 | } |
107 | 107 | ||
108 | /* Time read/write */ | 108 | /* Time read/write */ |
@@ -134,12 +134,12 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
134 | rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, | 134 | rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, |
135 | rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); | 135 | rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); |
136 | 136 | ||
137 | BCD_TO_BIN(rtc_tm->tm_sec); | 137 | rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); |
138 | BCD_TO_BIN(rtc_tm->tm_min); | 138 | rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min); |
139 | BCD_TO_BIN(rtc_tm->tm_hour); | 139 | rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour); |
140 | BCD_TO_BIN(rtc_tm->tm_mday); | 140 | rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday); |
141 | BCD_TO_BIN(rtc_tm->tm_mon); | 141 | rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon); |
142 | BCD_TO_BIN(rtc_tm->tm_year); | 142 | rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year); |
143 | 143 | ||
144 | rtc_tm->tm_year += 100; | 144 | rtc_tm->tm_year += 100; |
145 | rtc_tm->tm_mon -= 1; | 145 | rtc_tm->tm_mon -= 1; |
@@ -163,12 +163,12 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
163 | return -EINVAL; | 163 | return -EINVAL; |
164 | } | 164 | } |
165 | 165 | ||
166 | writeb(BIN2BCD(tm->tm_sec), base + S3C2410_RTCSEC); | 166 | writeb(bin2bcd(tm->tm_sec), base + S3C2410_RTCSEC); |
167 | writeb(BIN2BCD(tm->tm_min), base + S3C2410_RTCMIN); | 167 | writeb(bin2bcd(tm->tm_min), base + S3C2410_RTCMIN); |
168 | writeb(BIN2BCD(tm->tm_hour), base + S3C2410_RTCHOUR); | 168 | writeb(bin2bcd(tm->tm_hour), base + S3C2410_RTCHOUR); |
169 | writeb(BIN2BCD(tm->tm_mday), base + S3C2410_RTCDATE); | 169 | writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE); |
170 | writeb(BIN2BCD(tm->tm_mon + 1), base + S3C2410_RTCMON); | 170 | writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON); |
171 | writeb(BIN2BCD(year), base + S3C2410_RTCYEAR); | 171 | writeb(bin2bcd(year), base + S3C2410_RTCYEAR); |
172 | 172 | ||
173 | return 0; | 173 | return 0; |
174 | } | 174 | } |
@@ -199,34 +199,34 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
199 | /* decode the alarm enable field */ | 199 | /* decode the alarm enable field */ |
200 | 200 | ||
201 | if (alm_en & S3C2410_RTCALM_SECEN) | 201 | if (alm_en & S3C2410_RTCALM_SECEN) |
202 | BCD_TO_BIN(alm_tm->tm_sec); | 202 | alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); |
203 | else | 203 | else |
204 | alm_tm->tm_sec = 0xff; | 204 | alm_tm->tm_sec = 0xff; |
205 | 205 | ||
206 | if (alm_en & S3C2410_RTCALM_MINEN) | 206 | if (alm_en & S3C2410_RTCALM_MINEN) |
207 | BCD_TO_BIN(alm_tm->tm_min); | 207 | alm_tm->tm_min = bcd2bin(alm_tm->tm_min); |
208 | else | 208 | else |
209 | alm_tm->tm_min = 0xff; | 209 | alm_tm->tm_min = 0xff; |
210 | 210 | ||
211 | if (alm_en & S3C2410_RTCALM_HOUREN) | 211 | if (alm_en & S3C2410_RTCALM_HOUREN) |
212 | BCD_TO_BIN(alm_tm->tm_hour); | 212 | alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); |
213 | else | 213 | else |
214 | alm_tm->tm_hour = 0xff; | 214 | alm_tm->tm_hour = 0xff; |
215 | 215 | ||
216 | if (alm_en & S3C2410_RTCALM_DAYEN) | 216 | if (alm_en & S3C2410_RTCALM_DAYEN) |
217 | BCD_TO_BIN(alm_tm->tm_mday); | 217 | alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); |
218 | else | 218 | else |
219 | alm_tm->tm_mday = 0xff; | 219 | alm_tm->tm_mday = 0xff; |
220 | 220 | ||
221 | if (alm_en & S3C2410_RTCALM_MONEN) { | 221 | if (alm_en & S3C2410_RTCALM_MONEN) { |
222 | BCD_TO_BIN(alm_tm->tm_mon); | 222 | alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon); |
223 | alm_tm->tm_mon -= 1; | 223 | alm_tm->tm_mon -= 1; |
224 | } else { | 224 | } else { |
225 | alm_tm->tm_mon = 0xff; | 225 | alm_tm->tm_mon = 0xff; |
226 | } | 226 | } |
227 | 227 | ||
228 | if (alm_en & S3C2410_RTCALM_YEAREN) | 228 | if (alm_en & S3C2410_RTCALM_YEAREN) |
229 | BCD_TO_BIN(alm_tm->tm_year); | 229 | alm_tm->tm_year = bcd2bin(alm_tm->tm_year); |
230 | else | 230 | else |
231 | alm_tm->tm_year = 0xffff; | 231 | alm_tm->tm_year = 0xffff; |
232 | 232 | ||
@@ -250,29 +250,24 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
250 | 250 | ||
251 | if (tm->tm_sec < 60 && tm->tm_sec >= 0) { | 251 | if (tm->tm_sec < 60 && tm->tm_sec >= 0) { |
252 | alrm_en |= S3C2410_RTCALM_SECEN; | 252 | alrm_en |= S3C2410_RTCALM_SECEN; |
253 | writeb(BIN2BCD(tm->tm_sec), base + S3C2410_ALMSEC); | 253 | writeb(bin2bcd(tm->tm_sec), base + S3C2410_ALMSEC); |
254 | } | 254 | } |
255 | 255 | ||
256 | if (tm->tm_min < 60 && tm->tm_min >= 0) { | 256 | if (tm->tm_min < 60 && tm->tm_min >= 0) { |
257 | alrm_en |= S3C2410_RTCALM_MINEN; | 257 | alrm_en |= S3C2410_RTCALM_MINEN; |
258 | writeb(BIN2BCD(tm->tm_min), base + S3C2410_ALMMIN); | 258 | writeb(bin2bcd(tm->tm_min), base + S3C2410_ALMMIN); |
259 | } | 259 | } |
260 | 260 | ||
261 | if (tm->tm_hour < 24 && tm->tm_hour >= 0) { | 261 | if (tm->tm_hour < 24 && tm->tm_hour >= 0) { |
262 | alrm_en |= S3C2410_RTCALM_HOUREN; | 262 | alrm_en |= S3C2410_RTCALM_HOUREN; |
263 | writeb(BIN2BCD(tm->tm_hour), base + S3C2410_ALMHOUR); | 263 | writeb(bin2bcd(tm->tm_hour), base + S3C2410_ALMHOUR); |
264 | } | 264 | } |
265 | 265 | ||
266 | pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en); | 266 | pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en); |
267 | 267 | ||
268 | writeb(alrm_en, base + S3C2410_RTCALM); | 268 | writeb(alrm_en, base + S3C2410_RTCALM); |
269 | 269 | ||
270 | if (0) { | 270 | s3c_rtc_setaie(alrm->enabled); |
271 | alrm_en = readb(base + S3C2410_RTCALM); | ||
272 | alrm_en &= ~S3C2410_RTCALM_ALMEN; | ||
273 | writeb(alrm_en, base + S3C2410_RTCALM); | ||
274 | disable_irq_wake(s3c_rtc_alarmno); | ||
275 | } | ||
276 | 271 | ||
277 | if (alrm->enabled) | 272 | if (alrm->enabled) |
278 | enable_irq_wake(s3c_rtc_alarmno); | 273 | enable_irq_wake(s3c_rtc_alarmno); |
@@ -282,59 +277,12 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
282 | return 0; | 277 | return 0; |
283 | } | 278 | } |
284 | 279 | ||
285 | static int s3c_rtc_ioctl(struct device *dev, | ||
286 | unsigned int cmd, unsigned long arg) | ||
287 | { | ||
288 | unsigned int ret = -ENOIOCTLCMD; | ||
289 | |||
290 | switch (cmd) { | ||
291 | case RTC_AIE_OFF: | ||
292 | case RTC_AIE_ON: | ||
293 | s3c_rtc_setaie((cmd == RTC_AIE_ON) ? 1 : 0); | ||
294 | ret = 0; | ||
295 | break; | ||
296 | |||
297 | case RTC_PIE_OFF: | ||
298 | case RTC_PIE_ON: | ||
299 | tick_count = 0; | ||
300 | s3c_rtc_setpie((cmd == RTC_PIE_ON) ? 1 : 0); | ||
301 | ret = 0; | ||
302 | break; | ||
303 | |||
304 | case RTC_IRQP_READ: | ||
305 | ret = put_user(s3c_rtc_freq, (unsigned long __user *)arg); | ||
306 | break; | ||
307 | |||
308 | case RTC_IRQP_SET: | ||
309 | if (!is_power_of_2(arg)) { | ||
310 | ret = -EINVAL; | ||
311 | goto exit; | ||
312 | } | ||
313 | |||
314 | pr_debug("s3c2410_rtc: setting frequency %ld\n", arg); | ||
315 | |||
316 | s3c_rtc_setfreq(arg); | ||
317 | ret = 0; | ||
318 | break; | ||
319 | |||
320 | case RTC_UIE_ON: | ||
321 | case RTC_UIE_OFF: | ||
322 | ret = -EINVAL; | ||
323 | } | ||
324 | |||
325 | exit: | ||
326 | return ret; | ||
327 | } | ||
328 | |||
329 | static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) | 280 | static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) |
330 | { | 281 | { |
331 | unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT); | 282 | unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT); |
332 | 283 | ||
333 | seq_printf(seq, "periodic_IRQ\t: %s\n", | 284 | seq_printf(seq, "periodic_IRQ\t: %s\n", |
334 | (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" ); | 285 | (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" ); |
335 | |||
336 | seq_printf(seq, "periodic_freq\t: %d\n", s3c_rtc_freq); | ||
337 | |||
338 | return 0; | 286 | return 0; |
339 | } | 287 | } |
340 | 288 | ||
@@ -374,7 +322,7 @@ static void s3c_rtc_release(struct device *dev) | |||
374 | 322 | ||
375 | /* do not clear AIE here, it may be needed for wake */ | 323 | /* do not clear AIE here, it may be needed for wake */ |
376 | 324 | ||
377 | s3c_rtc_setpie(0); | 325 | s3c_rtc_setpie(dev, 0); |
378 | free_irq(s3c_rtc_alarmno, rtc_dev); | 326 | free_irq(s3c_rtc_alarmno, rtc_dev); |
379 | free_irq(s3c_rtc_tickno, rtc_dev); | 327 | free_irq(s3c_rtc_tickno, rtc_dev); |
380 | } | 328 | } |
@@ -382,11 +330,12 @@ static void s3c_rtc_release(struct device *dev) | |||
382 | static const struct rtc_class_ops s3c_rtcops = { | 330 | static const struct rtc_class_ops s3c_rtcops = { |
383 | .open = s3c_rtc_open, | 331 | .open = s3c_rtc_open, |
384 | .release = s3c_rtc_release, | 332 | .release = s3c_rtc_release, |
385 | .ioctl = s3c_rtc_ioctl, | ||
386 | .read_time = s3c_rtc_gettime, | 333 | .read_time = s3c_rtc_gettime, |
387 | .set_time = s3c_rtc_settime, | 334 | .set_time = s3c_rtc_settime, |
388 | .read_alarm = s3c_rtc_getalarm, | 335 | .read_alarm = s3c_rtc_getalarm, |
389 | .set_alarm = s3c_rtc_setalarm, | 336 | .set_alarm = s3c_rtc_setalarm, |
337 | .irq_set_freq = s3c_rtc_setfreq, | ||
338 | .irq_set_state = s3c_rtc_setpie, | ||
390 | .proc = s3c_rtc_proc, | 339 | .proc = s3c_rtc_proc, |
391 | }; | 340 | }; |
392 | 341 | ||
@@ -430,14 +379,14 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
430 | } | 379 | } |
431 | } | 380 | } |
432 | 381 | ||
433 | static int s3c_rtc_remove(struct platform_device *dev) | 382 | static int __devexit s3c_rtc_remove(struct platform_device *dev) |
434 | { | 383 | { |
435 | struct rtc_device *rtc = platform_get_drvdata(dev); | 384 | struct rtc_device *rtc = platform_get_drvdata(dev); |
436 | 385 | ||
437 | platform_set_drvdata(dev, NULL); | 386 | platform_set_drvdata(dev, NULL); |
438 | rtc_device_unregister(rtc); | 387 | rtc_device_unregister(rtc); |
439 | 388 | ||
440 | s3c_rtc_setpie(0); | 389 | s3c_rtc_setpie(&dev->dev, 0); |
441 | s3c_rtc_setaie(0); | 390 | s3c_rtc_setaie(0); |
442 | 391 | ||
443 | iounmap(s3c_rtc_base); | 392 | iounmap(s3c_rtc_base); |
@@ -447,7 +396,7 @@ static int s3c_rtc_remove(struct platform_device *dev) | |||
447 | return 0; | 396 | return 0; |
448 | } | 397 | } |
449 | 398 | ||
450 | static int s3c_rtc_probe(struct platform_device *pdev) | 399 | static int __devinit s3c_rtc_probe(struct platform_device *pdev) |
451 | { | 400 | { |
452 | struct rtc_device *rtc; | 401 | struct rtc_device *rtc; |
453 | struct resource *res; | 402 | struct resource *res; |
@@ -504,7 +453,7 @@ static int s3c_rtc_probe(struct platform_device *pdev) | |||
504 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", | 453 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", |
505 | readb(s3c_rtc_base + S3C2410_RTCCON)); | 454 | readb(s3c_rtc_base + S3C2410_RTCCON)); |
506 | 455 | ||
507 | s3c_rtc_setfreq(s3c_rtc_freq); | 456 | s3c_rtc_setfreq(&pdev->dev, 1); |
508 | 457 | ||
509 | /* register RTC and exit */ | 458 | /* register RTC and exit */ |
510 | 459 | ||
@@ -560,7 +509,7 @@ static int s3c_rtc_resume(struct platform_device *pdev) | |||
560 | 509 | ||
561 | static struct platform_driver s3c2410_rtcdrv = { | 510 | static struct platform_driver s3c2410_rtcdrv = { |
562 | .probe = s3c_rtc_probe, | 511 | .probe = s3c_rtc_probe, |
563 | .remove = s3c_rtc_remove, | 512 | .remove = __devexit_p(s3c_rtc_remove), |
564 | .suspend = s3c_rtc_suspend, | 513 | .suspend = s3c_rtc_suspend, |
565 | .resume = s3c_rtc_resume, | 514 | .resume = s3c_rtc_resume, |
566 | .driver = { | 515 | .driver = { |
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index f47294c60148..66a9bb85bbe8 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
@@ -31,11 +31,11 @@ | |||
31 | #include <linux/pm.h> | 31 | #include <linux/pm.h> |
32 | #include <linux/bitops.h> | 32 | #include <linux/bitops.h> |
33 | 33 | ||
34 | #include <asm/hardware.h> | 34 | #include <mach/hardware.h> |
35 | #include <asm/irq.h> | 35 | #include <asm/irq.h> |
36 | 36 | ||
37 | #ifdef CONFIG_ARCH_PXA | 37 | #ifdef CONFIG_ARCH_PXA |
38 | #include <asm/arch/pxa-regs.h> | 38 | #include <mach/pxa-regs.h> |
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | #define TIMER_FREQ CLOCK_TICK_RATE | 41 | #define TIMER_FREQ CLOCK_TICK_RATE |
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 1f88e9e914ec..aaf9d6a337cc 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c | |||
@@ -257,12 +257,6 @@ static inline void sh_rtc_setaie(struct device *dev, unsigned int enable) | |||
257 | spin_unlock_irq(&rtc->lock); | 257 | spin_unlock_irq(&rtc->lock); |
258 | } | 258 | } |
259 | 259 | ||
260 | static void sh_rtc_release(struct device *dev) | ||
261 | { | ||
262 | sh_rtc_setpie(dev, 0); | ||
263 | sh_rtc_setaie(dev, 0); | ||
264 | } | ||
265 | |||
266 | static int sh_rtc_proc(struct device *dev, struct seq_file *seq) | 260 | static int sh_rtc_proc(struct device *dev, struct seq_file *seq) |
267 | { | 261 | { |
268 | struct sh_rtc *rtc = dev_get_drvdata(dev); | 262 | struct sh_rtc *rtc = dev_get_drvdata(dev); |
@@ -330,23 +324,23 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
330 | 324 | ||
331 | sec128 = readb(rtc->regbase + R64CNT); | 325 | sec128 = readb(rtc->regbase + R64CNT); |
332 | 326 | ||
333 | tm->tm_sec = BCD2BIN(readb(rtc->regbase + RSECCNT)); | 327 | tm->tm_sec = bcd2bin(readb(rtc->regbase + RSECCNT)); |
334 | tm->tm_min = BCD2BIN(readb(rtc->regbase + RMINCNT)); | 328 | tm->tm_min = bcd2bin(readb(rtc->regbase + RMINCNT)); |
335 | tm->tm_hour = BCD2BIN(readb(rtc->regbase + RHRCNT)); | 329 | tm->tm_hour = bcd2bin(readb(rtc->regbase + RHRCNT)); |
336 | tm->tm_wday = BCD2BIN(readb(rtc->regbase + RWKCNT)); | 330 | tm->tm_wday = bcd2bin(readb(rtc->regbase + RWKCNT)); |
337 | tm->tm_mday = BCD2BIN(readb(rtc->regbase + RDAYCNT)); | 331 | tm->tm_mday = bcd2bin(readb(rtc->regbase + RDAYCNT)); |
338 | tm->tm_mon = BCD2BIN(readb(rtc->regbase + RMONCNT)) - 1; | 332 | tm->tm_mon = bcd2bin(readb(rtc->regbase + RMONCNT)) - 1; |
339 | 333 | ||
340 | if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) { | 334 | if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) { |
341 | yr = readw(rtc->regbase + RYRCNT); | 335 | yr = readw(rtc->regbase + RYRCNT); |
342 | yr100 = BCD2BIN(yr >> 8); | 336 | yr100 = bcd2bin(yr >> 8); |
343 | yr &= 0xff; | 337 | yr &= 0xff; |
344 | } else { | 338 | } else { |
345 | yr = readb(rtc->regbase + RYRCNT); | 339 | yr = readb(rtc->regbase + RYRCNT); |
346 | yr100 = BCD2BIN((yr == 0x99) ? 0x19 : 0x20); | 340 | yr100 = bcd2bin((yr == 0x99) ? 0x19 : 0x20); |
347 | } | 341 | } |
348 | 342 | ||
349 | tm->tm_year = (yr100 * 100 + BCD2BIN(yr)) - 1900; | 343 | tm->tm_year = (yr100 * 100 + bcd2bin(yr)) - 1900; |
350 | 344 | ||
351 | sec2 = readb(rtc->regbase + R64CNT); | 345 | sec2 = readb(rtc->regbase + R64CNT); |
352 | cf_bit = readb(rtc->regbase + RCR1) & RCR1_CF; | 346 | cf_bit = readb(rtc->regbase + RCR1) & RCR1_CF; |
@@ -388,20 +382,20 @@ static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
388 | tmp &= ~RCR2_START; | 382 | tmp &= ~RCR2_START; |
389 | writeb(tmp, rtc->regbase + RCR2); | 383 | writeb(tmp, rtc->regbase + RCR2); |
390 | 384 | ||
391 | writeb(BIN2BCD(tm->tm_sec), rtc->regbase + RSECCNT); | 385 | writeb(bin2bcd(tm->tm_sec), rtc->regbase + RSECCNT); |
392 | writeb(BIN2BCD(tm->tm_min), rtc->regbase + RMINCNT); | 386 | writeb(bin2bcd(tm->tm_min), rtc->regbase + RMINCNT); |
393 | writeb(BIN2BCD(tm->tm_hour), rtc->regbase + RHRCNT); | 387 | writeb(bin2bcd(tm->tm_hour), rtc->regbase + RHRCNT); |
394 | writeb(BIN2BCD(tm->tm_wday), rtc->regbase + RWKCNT); | 388 | writeb(bin2bcd(tm->tm_wday), rtc->regbase + RWKCNT); |
395 | writeb(BIN2BCD(tm->tm_mday), rtc->regbase + RDAYCNT); | 389 | writeb(bin2bcd(tm->tm_mday), rtc->regbase + RDAYCNT); |
396 | writeb(BIN2BCD(tm->tm_mon + 1), rtc->regbase + RMONCNT); | 390 | writeb(bin2bcd(tm->tm_mon + 1), rtc->regbase + RMONCNT); |
397 | 391 | ||
398 | if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) { | 392 | if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) { |
399 | year = (BIN2BCD((tm->tm_year + 1900) / 100) << 8) | | 393 | year = (bin2bcd((tm->tm_year + 1900) / 100) << 8) | |
400 | BIN2BCD(tm->tm_year % 100); | 394 | bin2bcd(tm->tm_year % 100); |
401 | writew(year, rtc->regbase + RYRCNT); | 395 | writew(year, rtc->regbase + RYRCNT); |
402 | } else { | 396 | } else { |
403 | year = tm->tm_year % 100; | 397 | year = tm->tm_year % 100; |
404 | writeb(BIN2BCD(year), rtc->regbase + RYRCNT); | 398 | writeb(bin2bcd(year), rtc->regbase + RYRCNT); |
405 | } | 399 | } |
406 | 400 | ||
407 | /* Start RTC */ | 401 | /* Start RTC */ |
@@ -423,7 +417,7 @@ static inline int sh_rtc_read_alarm_value(struct sh_rtc *rtc, int reg_off) | |||
423 | byte = readb(rtc->regbase + reg_off); | 417 | byte = readb(rtc->regbase + reg_off); |
424 | if (byte & AR_ENB) { | 418 | if (byte & AR_ENB) { |
425 | byte &= ~AR_ENB; /* strip the enable bit */ | 419 | byte &= ~AR_ENB; /* strip the enable bit */ |
426 | value = BCD2BIN(byte); | 420 | value = bcd2bin(byte); |
427 | } | 421 | } |
428 | 422 | ||
429 | return value; | 423 | return value; |
@@ -461,7 +455,7 @@ static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc, | |||
461 | if (value < 0) | 455 | if (value < 0) |
462 | writeb(0, rtc->regbase + reg_off); | 456 | writeb(0, rtc->regbase + reg_off); |
463 | else | 457 | else |
464 | writeb(BIN2BCD(value) | AR_ENB, rtc->regbase + reg_off); | 458 | writeb(bin2bcd(value) | AR_ENB, rtc->regbase + reg_off); |
465 | } | 459 | } |
466 | 460 | ||
467 | static int sh_rtc_check_alarm(struct rtc_time *tm) | 461 | static int sh_rtc_check_alarm(struct rtc_time *tm) |
@@ -559,7 +553,6 @@ static int sh_rtc_irq_set_freq(struct device *dev, int freq) | |||
559 | } | 553 | } |
560 | 554 | ||
561 | static struct rtc_class_ops sh_rtc_ops = { | 555 | static struct rtc_class_ops sh_rtc_ops = { |
562 | .release = sh_rtc_release, | ||
563 | .ioctl = sh_rtc_ioctl, | 556 | .ioctl = sh_rtc_ioctl, |
564 | .read_time = sh_rtc_read_time, | 557 | .read_time = sh_rtc_read_time, |
565 | .set_time = sh_rtc_set_time, | 558 | .set_time = sh_rtc_set_time, |
@@ -575,7 +568,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) | |||
575 | struct sh_rtc *rtc; | 568 | struct sh_rtc *rtc; |
576 | struct resource *res; | 569 | struct resource *res; |
577 | unsigned int tmp; | 570 | unsigned int tmp; |
578 | int ret = -ENOENT; | 571 | int ret; |
579 | 572 | ||
580 | rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL); | 573 | rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL); |
581 | if (unlikely(!rtc)) | 574 | if (unlikely(!rtc)) |
@@ -584,26 +577,33 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) | |||
584 | spin_lock_init(&rtc->lock); | 577 | spin_lock_init(&rtc->lock); |
585 | 578 | ||
586 | /* get periodic/carry/alarm irqs */ | 579 | /* get periodic/carry/alarm irqs */ |
587 | rtc->periodic_irq = platform_get_irq(pdev, 0); | 580 | ret = platform_get_irq(pdev, 0); |
588 | if (unlikely(rtc->periodic_irq < 0)) { | 581 | if (unlikely(ret < 0)) { |
582 | ret = -ENOENT; | ||
589 | dev_err(&pdev->dev, "No IRQ for period\n"); | 583 | dev_err(&pdev->dev, "No IRQ for period\n"); |
590 | goto err_badres; | 584 | goto err_badres; |
591 | } | 585 | } |
586 | rtc->periodic_irq = ret; | ||
592 | 587 | ||
593 | rtc->carry_irq = platform_get_irq(pdev, 1); | 588 | ret = platform_get_irq(pdev, 1); |
594 | if (unlikely(rtc->carry_irq < 0)) { | 589 | if (unlikely(ret < 0)) { |
590 | ret = -ENOENT; | ||
595 | dev_err(&pdev->dev, "No IRQ for carry\n"); | 591 | dev_err(&pdev->dev, "No IRQ for carry\n"); |
596 | goto err_badres; | 592 | goto err_badres; |
597 | } | 593 | } |
594 | rtc->carry_irq = ret; | ||
598 | 595 | ||
599 | rtc->alarm_irq = platform_get_irq(pdev, 2); | 596 | ret = platform_get_irq(pdev, 2); |
600 | if (unlikely(rtc->alarm_irq < 0)) { | 597 | if (unlikely(ret < 0)) { |
598 | ret = -ENOENT; | ||
601 | dev_err(&pdev->dev, "No IRQ for alarm\n"); | 599 | dev_err(&pdev->dev, "No IRQ for alarm\n"); |
602 | goto err_badres; | 600 | goto err_badres; |
603 | } | 601 | } |
602 | rtc->alarm_irq = ret; | ||
604 | 603 | ||
605 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 604 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
606 | if (unlikely(res == NULL)) { | 605 | if (unlikely(res == NULL)) { |
606 | ret = -ENOENT; | ||
607 | dev_err(&pdev->dev, "No IO resource\n"); | 607 | dev_err(&pdev->dev, "No IO resource\n"); |
608 | goto err_badres; | 608 | goto err_badres; |
609 | } | 609 | } |
diff --git a/drivers/rtc/rtc-starfire.c b/drivers/rtc/rtc-starfire.c new file mode 100644 index 000000000000..7ccb0dd700af --- /dev/null +++ b/drivers/rtc/rtc-starfire.c | |||
@@ -0,0 +1,120 @@ | |||
1 | /* rtc-starfire.c: Starfire platform RTC driver. | ||
2 | * | ||
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/init.h> | ||
9 | #include <linux/time.h> | ||
10 | #include <linux/rtc.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | |||
13 | #include <asm/oplib.h> | ||
14 | |||
15 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); | ||
16 | MODULE_DESCRIPTION("Starfire RTC driver"); | ||
17 | MODULE_LICENSE("GPL"); | ||
18 | |||
19 | struct starfire_rtc { | ||
20 | struct rtc_device *rtc; | ||
21 | spinlock_t lock; | ||
22 | }; | ||
23 | |||
24 | static u32 starfire_get_time(void) | ||
25 | { | ||
26 | static char obp_gettod[32]; | ||
27 | static u32 unix_tod; | ||
28 | |||
29 | sprintf(obp_gettod, "h# %08x unix-gettod", | ||
30 | (unsigned int) (long) &unix_tod); | ||
31 | prom_feval(obp_gettod); | ||
32 | |||
33 | return unix_tod; | ||
34 | } | ||
35 | |||
36 | static int starfire_read_time(struct device *dev, struct rtc_time *tm) | ||
37 | { | ||
38 | struct starfire_rtc *p = dev_get_drvdata(dev); | ||
39 | unsigned long flags, secs; | ||
40 | |||
41 | spin_lock_irqsave(&p->lock, flags); | ||
42 | secs = starfire_get_time(); | ||
43 | spin_unlock_irqrestore(&p->lock, flags); | ||
44 | |||
45 | rtc_time_to_tm(secs, tm); | ||
46 | |||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | static int starfire_set_time(struct device *dev, struct rtc_time *tm) | ||
51 | { | ||
52 | unsigned long secs; | ||
53 | int err; | ||
54 | |||
55 | err = rtc_tm_to_time(tm, &secs); | ||
56 | if (err) | ||
57 | return err; | ||
58 | |||
59 | /* Do nothing, time is set using the service processor | ||
60 | * console on this platform. | ||
61 | */ | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static const struct rtc_class_ops starfire_rtc_ops = { | ||
66 | .read_time = starfire_read_time, | ||
67 | .set_time = starfire_set_time, | ||
68 | }; | ||
69 | |||
70 | static int __devinit starfire_rtc_probe(struct platform_device *pdev) | ||
71 | { | ||
72 | struct starfire_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
73 | |||
74 | if (!p) | ||
75 | return -ENOMEM; | ||
76 | |||
77 | spin_lock_init(&p->lock); | ||
78 | |||
79 | p->rtc = rtc_device_register("starfire", &pdev->dev, | ||
80 | &starfire_rtc_ops, THIS_MODULE); | ||
81 | if (IS_ERR(p->rtc)) { | ||
82 | int err = PTR_ERR(p->rtc); | ||
83 | kfree(p); | ||
84 | return err; | ||
85 | } | ||
86 | platform_set_drvdata(pdev, p); | ||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static int __devexit starfire_rtc_remove(struct platform_device *pdev) | ||
91 | { | ||
92 | struct starfire_rtc *p = platform_get_drvdata(pdev); | ||
93 | |||
94 | rtc_device_unregister(p->rtc); | ||
95 | kfree(p); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static struct platform_driver starfire_rtc_driver = { | ||
101 | .driver = { | ||
102 | .name = "rtc-starfire", | ||
103 | .owner = THIS_MODULE, | ||
104 | }, | ||
105 | .probe = starfire_rtc_probe, | ||
106 | .remove = __devexit_p(starfire_rtc_remove), | ||
107 | }; | ||
108 | |||
109 | static int __init starfire_rtc_init(void) | ||
110 | { | ||
111 | return platform_driver_register(&starfire_rtc_driver); | ||
112 | } | ||
113 | |||
114 | static void __exit starfire_rtc_exit(void) | ||
115 | { | ||
116 | platform_driver_unregister(&starfire_rtc_driver); | ||
117 | } | ||
118 | |||
119 | module_init(starfire_rtc_init); | ||
120 | module_exit(starfire_rtc_exit); | ||
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index 31d3c8c28588..f4cd46e15af9 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c | |||
@@ -82,14 +82,14 @@ static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
82 | flags = readb(pdata->ioaddr + RTC_FLAGS); | 82 | flags = readb(pdata->ioaddr + RTC_FLAGS); |
83 | writeb(flags | RTC_WRITE, pdata->ioaddr + RTC_FLAGS); | 83 | writeb(flags | RTC_WRITE, pdata->ioaddr + RTC_FLAGS); |
84 | 84 | ||
85 | writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR); | 85 | writeb(bin2bcd(tm->tm_year % 100), ioaddr + RTC_YEAR); |
86 | writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH); | 86 | writeb(bin2bcd(tm->tm_mon + 1), ioaddr + RTC_MONTH); |
87 | writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY); | 87 | writeb(bin2bcd(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY); |
88 | writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE); | 88 | writeb(bin2bcd(tm->tm_mday), ioaddr + RTC_DATE); |
89 | writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS); | 89 | writeb(bin2bcd(tm->tm_hour), ioaddr + RTC_HOURS); |
90 | writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES); | 90 | writeb(bin2bcd(tm->tm_min), ioaddr + RTC_MINUTES); |
91 | writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS); | 91 | writeb(bin2bcd(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS); |
92 | writeb(BIN2BCD((tm->tm_year + 1900) / 100), ioaddr + RTC_CENTURY); | 92 | writeb(bin2bcd((tm->tm_year + 1900) / 100), ioaddr + RTC_CENTURY); |
93 | 93 | ||
94 | writeb(flags & ~RTC_WRITE, pdata->ioaddr + RTC_FLAGS); | 94 | writeb(flags & ~RTC_WRITE, pdata->ioaddr + RTC_FLAGS); |
95 | return 0; | 95 | return 0; |
@@ -120,14 +120,14 @@ static int stk17ta8_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
120 | year = readb(ioaddr + RTC_YEAR); | 120 | year = readb(ioaddr + RTC_YEAR); |
121 | century = readb(ioaddr + RTC_CENTURY); | 121 | century = readb(ioaddr + RTC_CENTURY); |
122 | writeb(flags & ~RTC_READ, ioaddr + RTC_FLAGS); | 122 | writeb(flags & ~RTC_READ, ioaddr + RTC_FLAGS); |
123 | tm->tm_sec = BCD2BIN(second); | 123 | tm->tm_sec = bcd2bin(second); |
124 | tm->tm_min = BCD2BIN(minute); | 124 | tm->tm_min = bcd2bin(minute); |
125 | tm->tm_hour = BCD2BIN(hour); | 125 | tm->tm_hour = bcd2bin(hour); |
126 | tm->tm_mday = BCD2BIN(day); | 126 | tm->tm_mday = bcd2bin(day); |
127 | tm->tm_wday = BCD2BIN(week); | 127 | tm->tm_wday = bcd2bin(week); |
128 | tm->tm_mon = BCD2BIN(month) - 1; | 128 | tm->tm_mon = bcd2bin(month) - 1; |
129 | /* year is 1900 + tm->tm_year */ | 129 | /* year is 1900 + tm->tm_year */ |
130 | tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900; | 130 | tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900; |
131 | 131 | ||
132 | if (rtc_valid_tm(tm) < 0) { | 132 | if (rtc_valid_tm(tm) < 0) { |
133 | dev_err(dev, "retrieved date/time is not valid.\n"); | 133 | dev_err(dev, "retrieved date/time is not valid.\n"); |
@@ -148,16 +148,16 @@ static void stk17ta8_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
148 | writeb(flags | RTC_WRITE, ioaddr + RTC_FLAGS); | 148 | writeb(flags | RTC_WRITE, ioaddr + RTC_FLAGS); |
149 | 149 | ||
150 | writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? | 150 | writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? |
151 | 0x80 : BIN2BCD(pdata->alrm_mday), | 151 | 0x80 : bin2bcd(pdata->alrm_mday), |
152 | ioaddr + RTC_DATE_ALARM); | 152 | ioaddr + RTC_DATE_ALARM); |
153 | writeb(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ? | 153 | writeb(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ? |
154 | 0x80 : BIN2BCD(pdata->alrm_hour), | 154 | 0x80 : bin2bcd(pdata->alrm_hour), |
155 | ioaddr + RTC_HOURS_ALARM); | 155 | ioaddr + RTC_HOURS_ALARM); |
156 | writeb(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ? | 156 | writeb(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ? |
157 | 0x80 : BIN2BCD(pdata->alrm_min), | 157 | 0x80 : bin2bcd(pdata->alrm_min), |
158 | ioaddr + RTC_MINUTES_ALARM); | 158 | ioaddr + RTC_MINUTES_ALARM); |
159 | writeb(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ? | 159 | writeb(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ? |
160 | 0x80 : BIN2BCD(pdata->alrm_sec), | 160 | 0x80 : bin2bcd(pdata->alrm_sec), |
161 | ioaddr + RTC_SECONDS_ALARM); | 161 | ioaddr + RTC_SECONDS_ALARM); |
162 | writeb(pdata->irqen ? RTC_INTS_AIE : 0, ioaddr + RTC_INTERRUPTS); | 162 | writeb(pdata->irqen ? RTC_INTS_AIE : 0, ioaddr + RTC_INTERRUPTS); |
163 | readb(ioaddr + RTC_FLAGS); /* clear interrupts */ | 163 | readb(ioaddr + RTC_FLAGS); /* clear interrupts */ |
@@ -215,17 +215,6 @@ static irqreturn_t stk17ta8_rtc_interrupt(int irq, void *dev_id) | |||
215 | return IRQ_HANDLED; | 215 | return IRQ_HANDLED; |
216 | } | 216 | } |
217 | 217 | ||
218 | static void stk17ta8_rtc_release(struct device *dev) | ||
219 | { | ||
220 | struct platform_device *pdev = to_platform_device(dev); | ||
221 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
222 | |||
223 | if (pdata->irq >= 0) { | ||
224 | pdata->irqen = 0; | ||
225 | stk17ta8_rtc_update_alarm(pdata); | ||
226 | } | ||
227 | } | ||
228 | |||
229 | static int stk17ta8_rtc_ioctl(struct device *dev, unsigned int cmd, | 218 | static int stk17ta8_rtc_ioctl(struct device *dev, unsigned int cmd, |
230 | unsigned long arg) | 219 | unsigned long arg) |
231 | { | 220 | { |
@@ -254,7 +243,6 @@ static const struct rtc_class_ops stk17ta8_rtc_ops = { | |||
254 | .set_time = stk17ta8_rtc_set_time, | 243 | .set_time = stk17ta8_rtc_set_time, |
255 | .read_alarm = stk17ta8_rtc_read_alarm, | 244 | .read_alarm = stk17ta8_rtc_read_alarm, |
256 | .set_alarm = stk17ta8_rtc_set_alarm, | 245 | .set_alarm = stk17ta8_rtc_set_alarm, |
257 | .release = stk17ta8_rtc_release, | ||
258 | .ioctl = stk17ta8_rtc_ioctl, | 246 | .ioctl = stk17ta8_rtc_ioctl, |
259 | }; | 247 | }; |
260 | 248 | ||
@@ -292,7 +280,6 @@ static struct bin_attribute stk17ta8_nvram_attr = { | |||
292 | .attr = { | 280 | .attr = { |
293 | .name = "nvram", | 281 | .name = "nvram", |
294 | .mode = S_IRUGO | S_IWUSR, | 282 | .mode = S_IRUGO | S_IWUSR, |
295 | .owner = THIS_MODULE, | ||
296 | }, | 283 | }, |
297 | .size = RTC_OFFSET, | 284 | .size = RTC_OFFSET, |
298 | .read = stk17ta8_nvram_read, | 285 | .read = stk17ta8_nvram_read, |
diff --git a/drivers/rtc/rtc-sun4v.c b/drivers/rtc/rtc-sun4v.c new file mode 100644 index 000000000000..2012ccbb4a53 --- /dev/null +++ b/drivers/rtc/rtc-sun4v.c | |||
@@ -0,0 +1,153 @@ | |||
1 | /* rtc-sun4c.c: Hypervisor based RTC for SUN4V systems. | ||
2 | * | ||
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/delay.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/time.h> | ||
11 | #include <linux/rtc.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | |||
14 | #include <asm/hypervisor.h> | ||
15 | |||
16 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); | ||
17 | MODULE_DESCRIPTION("SUN4V RTC driver"); | ||
18 | MODULE_LICENSE("GPL"); | ||
19 | |||
20 | struct sun4v_rtc { | ||
21 | struct rtc_device *rtc; | ||
22 | spinlock_t lock; | ||
23 | }; | ||
24 | |||
25 | static unsigned long hypervisor_get_time(void) | ||
26 | { | ||
27 | unsigned long ret, time; | ||
28 | int retries = 10000; | ||
29 | |||
30 | retry: | ||
31 | ret = sun4v_tod_get(&time); | ||
32 | if (ret == HV_EOK) | ||
33 | return time; | ||
34 | if (ret == HV_EWOULDBLOCK) { | ||
35 | if (--retries > 0) { | ||
36 | udelay(100); | ||
37 | goto retry; | ||
38 | } | ||
39 | printk(KERN_WARNING "SUN4V: tod_get() timed out.\n"); | ||
40 | return 0; | ||
41 | } | ||
42 | printk(KERN_WARNING "SUN4V: tod_get() not supported.\n"); | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | static int sun4v_read_time(struct device *dev, struct rtc_time *tm) | ||
47 | { | ||
48 | struct sun4v_rtc *p = dev_get_drvdata(dev); | ||
49 | unsigned long flags, secs; | ||
50 | |||
51 | spin_lock_irqsave(&p->lock, flags); | ||
52 | secs = hypervisor_get_time(); | ||
53 | spin_unlock_irqrestore(&p->lock, flags); | ||
54 | |||
55 | rtc_time_to_tm(secs, tm); | ||
56 | |||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static int hypervisor_set_time(unsigned long secs) | ||
61 | { | ||
62 | unsigned long ret; | ||
63 | int retries = 10000; | ||
64 | |||
65 | retry: | ||
66 | ret = sun4v_tod_set(secs); | ||
67 | if (ret == HV_EOK) | ||
68 | return 0; | ||
69 | if (ret == HV_EWOULDBLOCK) { | ||
70 | if (--retries > 0) { | ||
71 | udelay(100); | ||
72 | goto retry; | ||
73 | } | ||
74 | printk(KERN_WARNING "SUN4V: tod_set() timed out.\n"); | ||
75 | return -EAGAIN; | ||
76 | } | ||
77 | printk(KERN_WARNING "SUN4V: tod_set() not supported.\n"); | ||
78 | return -EOPNOTSUPP; | ||
79 | } | ||
80 | |||
81 | static int sun4v_set_time(struct device *dev, struct rtc_time *tm) | ||
82 | { | ||
83 | struct sun4v_rtc *p = dev_get_drvdata(dev); | ||
84 | unsigned long flags, secs; | ||
85 | int err; | ||
86 | |||
87 | err = rtc_tm_to_time(tm, &secs); | ||
88 | if (err) | ||
89 | return err; | ||
90 | |||
91 | spin_lock_irqsave(&p->lock, flags); | ||
92 | err = hypervisor_set_time(secs); | ||
93 | spin_unlock_irqrestore(&p->lock, flags); | ||
94 | |||
95 | return err; | ||
96 | } | ||
97 | |||
98 | static const struct rtc_class_ops sun4v_rtc_ops = { | ||
99 | .read_time = sun4v_read_time, | ||
100 | .set_time = sun4v_set_time, | ||
101 | }; | ||
102 | |||
103 | static int __devinit sun4v_rtc_probe(struct platform_device *pdev) | ||
104 | { | ||
105 | struct sun4v_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
106 | |||
107 | if (!p) | ||
108 | return -ENOMEM; | ||
109 | |||
110 | spin_lock_init(&p->lock); | ||
111 | |||
112 | p->rtc = rtc_device_register("sun4v", &pdev->dev, | ||
113 | &sun4v_rtc_ops, THIS_MODULE); | ||
114 | if (IS_ERR(p->rtc)) { | ||
115 | int err = PTR_ERR(p->rtc); | ||
116 | kfree(p); | ||
117 | return err; | ||
118 | } | ||
119 | platform_set_drvdata(pdev, p); | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static int __devexit sun4v_rtc_remove(struct platform_device *pdev) | ||
124 | { | ||
125 | struct sun4v_rtc *p = platform_get_drvdata(pdev); | ||
126 | |||
127 | rtc_device_unregister(p->rtc); | ||
128 | kfree(p); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static struct platform_driver sun4v_rtc_driver = { | ||
134 | .driver = { | ||
135 | .name = "rtc-sun4v", | ||
136 | .owner = THIS_MODULE, | ||
137 | }, | ||
138 | .probe = sun4v_rtc_probe, | ||
139 | .remove = __devexit_p(sun4v_rtc_remove), | ||
140 | }; | ||
141 | |||
142 | static int __init sun4v_rtc_init(void) | ||
143 | { | ||
144 | return platform_driver_register(&sun4v_rtc_driver); | ||
145 | } | ||
146 | |||
147 | static void __exit sun4v_rtc_exit(void) | ||
148 | { | ||
149 | platform_driver_unregister(&sun4v_rtc_driver); | ||
150 | } | ||
151 | |||
152 | module_init(sun4v_rtc_init); | ||
153 | module_exit(sun4v_rtc_exit); | ||
diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl4030.c new file mode 100644 index 000000000000..abe87a4d2665 --- /dev/null +++ b/drivers/rtc/rtc-twl4030.c | |||
@@ -0,0 +1,564 @@ | |||
1 | /* | ||
2 | * rtc-twl4030.c -- TWL4030 Real Time Clock interface | ||
3 | * | ||
4 | * Copyright (C) 2007 MontaVista Software, Inc | ||
5 | * Author: Alexandre Rusev <source@mvista.com> | ||
6 | * | ||
7 | * Based on original TI driver twl4030-rtc.c | ||
8 | * Copyright (C) 2006 Texas Instruments, Inc. | ||
9 | * | ||
10 | * Based on rtc-omap.c | ||
11 | * Copyright (C) 2003 MontaVista Software, Inc. | ||
12 | * Author: George G. Davis <gdavis@mvista.com> or <source@mvista.com> | ||
13 | * Copyright (C) 2006 David Brownell | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License | ||
17 | * as published by the Free Software Foundation; either version | ||
18 | * 2 of the License, or (at your option) any later version. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/types.h> | ||
25 | #include <linux/rtc.h> | ||
26 | #include <linux/bcd.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | |||
30 | #include <linux/i2c/twl4030.h> | ||
31 | |||
32 | |||
33 | /* | ||
34 | * RTC block register offsets (use TWL_MODULE_RTC) | ||
35 | */ | ||
36 | #define REG_SECONDS_REG 0x00 | ||
37 | #define REG_MINUTES_REG 0x01 | ||
38 | #define REG_HOURS_REG 0x02 | ||
39 | #define REG_DAYS_REG 0x03 | ||
40 | #define REG_MONTHS_REG 0x04 | ||
41 | #define REG_YEARS_REG 0x05 | ||
42 | #define REG_WEEKS_REG 0x06 | ||
43 | |||
44 | #define REG_ALARM_SECONDS_REG 0x07 | ||
45 | #define REG_ALARM_MINUTES_REG 0x08 | ||
46 | #define REG_ALARM_HOURS_REG 0x09 | ||
47 | #define REG_ALARM_DAYS_REG 0x0A | ||
48 | #define REG_ALARM_MONTHS_REG 0x0B | ||
49 | #define REG_ALARM_YEARS_REG 0x0C | ||
50 | |||
51 | #define REG_RTC_CTRL_REG 0x0D | ||
52 | #define REG_RTC_STATUS_REG 0x0E | ||
53 | #define REG_RTC_INTERRUPTS_REG 0x0F | ||
54 | |||
55 | #define REG_RTC_COMP_LSB_REG 0x10 | ||
56 | #define REG_RTC_COMP_MSB_REG 0x11 | ||
57 | |||
58 | /* RTC_CTRL_REG bitfields */ | ||
59 | #define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01 | ||
60 | #define BIT_RTC_CTRL_REG_ROUND_30S_M 0x02 | ||
61 | #define BIT_RTC_CTRL_REG_AUTO_COMP_M 0x04 | ||
62 | #define BIT_RTC_CTRL_REG_MODE_12_24_M 0x08 | ||
63 | #define BIT_RTC_CTRL_REG_TEST_MODE_M 0x10 | ||
64 | #define BIT_RTC_CTRL_REG_SET_32_COUNTER_M 0x20 | ||
65 | #define BIT_RTC_CTRL_REG_GET_TIME_M 0x40 | ||
66 | |||
67 | /* RTC_STATUS_REG bitfields */ | ||
68 | #define BIT_RTC_STATUS_REG_RUN_M 0x02 | ||
69 | #define BIT_RTC_STATUS_REG_1S_EVENT_M 0x04 | ||
70 | #define BIT_RTC_STATUS_REG_1M_EVENT_M 0x08 | ||
71 | #define BIT_RTC_STATUS_REG_1H_EVENT_M 0x10 | ||
72 | #define BIT_RTC_STATUS_REG_1D_EVENT_M 0x20 | ||
73 | #define BIT_RTC_STATUS_REG_ALARM_M 0x40 | ||
74 | #define BIT_RTC_STATUS_REG_POWER_UP_M 0x80 | ||
75 | |||
76 | /* RTC_INTERRUPTS_REG bitfields */ | ||
77 | #define BIT_RTC_INTERRUPTS_REG_EVERY_M 0x03 | ||
78 | #define BIT_RTC_INTERRUPTS_REG_IT_TIMER_M 0x04 | ||
79 | #define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M 0x08 | ||
80 | |||
81 | |||
82 | /* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */ | ||
83 | #define ALL_TIME_REGS 6 | ||
84 | |||
85 | /*----------------------------------------------------------------------*/ | ||
86 | |||
87 | /* | ||
88 | * Supports 1 byte read from TWL4030 RTC register. | ||
89 | */ | ||
90 | static int twl4030_rtc_read_u8(u8 *data, u8 reg) | ||
91 | { | ||
92 | int ret; | ||
93 | |||
94 | ret = twl4030_i2c_read_u8(TWL4030_MODULE_RTC, data, reg); | ||
95 | if (ret < 0) | ||
96 | pr_err("twl4030_rtc: Could not read TWL4030" | ||
97 | "register %X - error %d\n", reg, ret); | ||
98 | return ret; | ||
99 | } | ||
100 | |||
101 | /* | ||
102 | * Supports 1 byte write to TWL4030 RTC registers. | ||
103 | */ | ||
104 | static int twl4030_rtc_write_u8(u8 data, u8 reg) | ||
105 | { | ||
106 | int ret; | ||
107 | |||
108 | ret = twl4030_i2c_write_u8(TWL4030_MODULE_RTC, data, reg); | ||
109 | if (ret < 0) | ||
110 | pr_err("twl4030_rtc: Could not write TWL4030" | ||
111 | "register %X - error %d\n", reg, ret); | ||
112 | return ret; | ||
113 | } | ||
114 | |||
115 | /* | ||
116 | * Cache the value for timer/alarm interrupts register; this is | ||
117 | * only changed by callers holding rtc ops lock (or resume). | ||
118 | */ | ||
119 | static unsigned char rtc_irq_bits; | ||
120 | |||
121 | /* | ||
122 | * Enable timer and/or alarm interrupts. | ||
123 | */ | ||
124 | static int set_rtc_irq_bit(unsigned char bit) | ||
125 | { | ||
126 | unsigned char val; | ||
127 | int ret; | ||
128 | |||
129 | val = rtc_irq_bits | bit; | ||
130 | ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); | ||
131 | if (ret == 0) | ||
132 | rtc_irq_bits = val; | ||
133 | |||
134 | return ret; | ||
135 | } | ||
136 | |||
137 | /* | ||
138 | * Disable timer and/or alarm interrupts. | ||
139 | */ | ||
140 | static int mask_rtc_irq_bit(unsigned char bit) | ||
141 | { | ||
142 | unsigned char val; | ||
143 | int ret; | ||
144 | |||
145 | val = rtc_irq_bits & ~bit; | ||
146 | ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); | ||
147 | if (ret == 0) | ||
148 | rtc_irq_bits = val; | ||
149 | |||
150 | return ret; | ||
151 | } | ||
152 | |||
153 | static inline int twl4030_rtc_alarm_irq_set_state(int enabled) | ||
154 | { | ||
155 | int ret; | ||
156 | |||
157 | if (enabled) | ||
158 | ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); | ||
159 | else | ||
160 | ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); | ||
161 | |||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | static inline int twl4030_rtc_irq_set_state(int enabled) | ||
166 | { | ||
167 | int ret; | ||
168 | |||
169 | if (enabled) | ||
170 | ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); | ||
171 | else | ||
172 | ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); | ||
173 | |||
174 | return ret; | ||
175 | } | ||
176 | |||
177 | /* | ||
178 | * Gets current TWL4030 RTC time and date parameters. | ||
179 | * | ||
180 | * The RTC's time/alarm representation is not what gmtime(3) requires | ||
181 | * Linux to use: | ||
182 | * | ||
183 | * - Months are 1..12 vs Linux 0-11 | ||
184 | * - Years are 0..99 vs Linux 1900..N (we assume 21st century) | ||
185 | */ | ||
186 | static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
187 | { | ||
188 | unsigned char rtc_data[ALL_TIME_REGS + 1]; | ||
189 | int ret; | ||
190 | u8 save_control; | ||
191 | |||
192 | ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); | ||
193 | if (ret < 0) | ||
194 | return ret; | ||
195 | |||
196 | save_control |= BIT_RTC_CTRL_REG_GET_TIME_M; | ||
197 | |||
198 | ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); | ||
199 | if (ret < 0) | ||
200 | return ret; | ||
201 | |||
202 | ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, | ||
203 | REG_SECONDS_REG, ALL_TIME_REGS); | ||
204 | |||
205 | if (ret < 0) { | ||
206 | dev_err(dev, "rtc_read_time error %d\n", ret); | ||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | tm->tm_sec = bcd2bin(rtc_data[0]); | ||
211 | tm->tm_min = bcd2bin(rtc_data[1]); | ||
212 | tm->tm_hour = bcd2bin(rtc_data[2]); | ||
213 | tm->tm_mday = bcd2bin(rtc_data[3]); | ||
214 | tm->tm_mon = bcd2bin(rtc_data[4]) - 1; | ||
215 | tm->tm_year = bcd2bin(rtc_data[5]) + 100; | ||
216 | |||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
221 | { | ||
222 | unsigned char save_control; | ||
223 | unsigned char rtc_data[ALL_TIME_REGS + 1]; | ||
224 | int ret; | ||
225 | |||
226 | rtc_data[1] = bin2bcd(tm->tm_sec); | ||
227 | rtc_data[2] = bin2bcd(tm->tm_min); | ||
228 | rtc_data[3] = bin2bcd(tm->tm_hour); | ||
229 | rtc_data[4] = bin2bcd(tm->tm_mday); | ||
230 | rtc_data[5] = bin2bcd(tm->tm_mon + 1); | ||
231 | rtc_data[6] = bin2bcd(tm->tm_year - 100); | ||
232 | |||
233 | /* Stop RTC while updating the TC registers */ | ||
234 | ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); | ||
235 | if (ret < 0) | ||
236 | goto out; | ||
237 | |||
238 | save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; | ||
239 | twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); | ||
240 | if (ret < 0) | ||
241 | goto out; | ||
242 | |||
243 | /* update all the time registers in one shot */ | ||
244 | ret = twl4030_i2c_write(TWL4030_MODULE_RTC, rtc_data, | ||
245 | REG_SECONDS_REG, ALL_TIME_REGS); | ||
246 | if (ret < 0) { | ||
247 | dev_err(dev, "rtc_set_time error %d\n", ret); | ||
248 | goto out; | ||
249 | } | ||
250 | |||
251 | /* Start back RTC */ | ||
252 | save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M; | ||
253 | ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); | ||
254 | |||
255 | out: | ||
256 | return ret; | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * Gets current TWL4030 RTC alarm time. | ||
261 | */ | ||
262 | static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
263 | { | ||
264 | unsigned char rtc_data[ALL_TIME_REGS + 1]; | ||
265 | int ret; | ||
266 | |||
267 | ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, | ||
268 | REG_ALARM_SECONDS_REG, ALL_TIME_REGS); | ||
269 | if (ret < 0) { | ||
270 | dev_err(dev, "rtc_read_alarm error %d\n", ret); | ||
271 | return ret; | ||
272 | } | ||
273 | |||
274 | /* some of these fields may be wildcard/"match all" */ | ||
275 | alm->time.tm_sec = bcd2bin(rtc_data[0]); | ||
276 | alm->time.tm_min = bcd2bin(rtc_data[1]); | ||
277 | alm->time.tm_hour = bcd2bin(rtc_data[2]); | ||
278 | alm->time.tm_mday = bcd2bin(rtc_data[3]); | ||
279 | alm->time.tm_mon = bcd2bin(rtc_data[4]) - 1; | ||
280 | alm->time.tm_year = bcd2bin(rtc_data[5]) + 100; | ||
281 | |||
282 | /* report cached alarm enable state */ | ||
283 | if (rtc_irq_bits & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M) | ||
284 | alm->enabled = 1; | ||
285 | |||
286 | return ret; | ||
287 | } | ||
288 | |||
289 | static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
290 | { | ||
291 | unsigned char alarm_data[ALL_TIME_REGS + 1]; | ||
292 | int ret; | ||
293 | |||
294 | ret = twl4030_rtc_alarm_irq_set_state(0); | ||
295 | if (ret) | ||
296 | goto out; | ||
297 | |||
298 | alarm_data[1] = bin2bcd(alm->time.tm_sec); | ||
299 | alarm_data[2] = bin2bcd(alm->time.tm_min); | ||
300 | alarm_data[3] = bin2bcd(alm->time.tm_hour); | ||
301 | alarm_data[4] = bin2bcd(alm->time.tm_mday); | ||
302 | alarm_data[5] = bin2bcd(alm->time.tm_mon + 1); | ||
303 | alarm_data[6] = bin2bcd(alm->time.tm_year - 100); | ||
304 | |||
305 | /* update all the alarm registers in one shot */ | ||
306 | ret = twl4030_i2c_write(TWL4030_MODULE_RTC, alarm_data, | ||
307 | REG_ALARM_SECONDS_REG, ALL_TIME_REGS); | ||
308 | if (ret) { | ||
309 | dev_err(dev, "rtc_set_alarm error %d\n", ret); | ||
310 | goto out; | ||
311 | } | ||
312 | |||
313 | if (alm->enabled) | ||
314 | ret = twl4030_rtc_alarm_irq_set_state(1); | ||
315 | out: | ||
316 | return ret; | ||
317 | } | ||
318 | |||
319 | #ifdef CONFIG_RTC_INTF_DEV | ||
320 | |||
321 | static int twl4030_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
322 | unsigned long arg) | ||
323 | { | ||
324 | switch (cmd) { | ||
325 | case RTC_AIE_OFF: | ||
326 | return twl4030_rtc_alarm_irq_set_state(0); | ||
327 | case RTC_AIE_ON: | ||
328 | return twl4030_rtc_alarm_irq_set_state(1); | ||
329 | case RTC_UIE_OFF: | ||
330 | return twl4030_rtc_irq_set_state(0); | ||
331 | case RTC_UIE_ON: | ||
332 | return twl4030_rtc_irq_set_state(1); | ||
333 | |||
334 | default: | ||
335 | return -ENOIOCTLCMD; | ||
336 | } | ||
337 | } | ||
338 | |||
339 | #else | ||
340 | #define omap_rtc_ioctl NULL | ||
341 | #endif | ||
342 | |||
343 | static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) | ||
344 | { | ||
345 | unsigned long events = 0; | ||
346 | int ret = IRQ_NONE; | ||
347 | int res; | ||
348 | u8 rd_reg; | ||
349 | |||
350 | #ifdef CONFIG_LOCKDEP | ||
351 | /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which | ||
352 | * we don't want and can't tolerate. Although it might be | ||
353 | * friendlier not to borrow this thread context... | ||
354 | */ | ||
355 | local_irq_enable(); | ||
356 | #endif | ||
357 | |||
358 | res = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); | ||
359 | if (res) | ||
360 | goto out; | ||
361 | /* | ||
362 | * Figure out source of interrupt: ALARM or TIMER in RTC_STATUS_REG. | ||
363 | * only one (ALARM or RTC) interrupt source may be enabled | ||
364 | * at time, we also could check our results | ||
365 | * by reading RTS_INTERRUPTS_REGISTER[IT_TIMER,IT_ALARM] | ||
366 | */ | ||
367 | if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) | ||
368 | events |= RTC_IRQF | RTC_AF; | ||
369 | else | ||
370 | events |= RTC_IRQF | RTC_UF; | ||
371 | |||
372 | res = twl4030_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M, | ||
373 | REG_RTC_STATUS_REG); | ||
374 | if (res) | ||
375 | goto out; | ||
376 | |||
377 | /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 | ||
378 | * needs 2 reads to clear the interrupt. One read is done in | ||
379 | * do_twl4030_pwrirq(). Doing the second read, to clear | ||
380 | * the bit. | ||
381 | * | ||
382 | * FIXME the reason PWR_ISR1 needs an extra read is that | ||
383 | * RTC_IF retriggered until we cleared REG_ALARM_M above. | ||
384 | * But re-reading like this is a bad hack; by doing so we | ||
385 | * risk wrongly clearing status for some other IRQ (losing | ||
386 | * the interrupt). Be smarter about handling RTC_UF ... | ||
387 | */ | ||
388 | res = twl4030_i2c_read_u8(TWL4030_MODULE_INT, | ||
389 | &rd_reg, TWL4030_INT_PWR_ISR1); | ||
390 | if (res) | ||
391 | goto out; | ||
392 | |||
393 | /* Notify RTC core on event */ | ||
394 | rtc_update_irq(rtc, 1, events); | ||
395 | |||
396 | ret = IRQ_HANDLED; | ||
397 | out: | ||
398 | return ret; | ||
399 | } | ||
400 | |||
401 | static struct rtc_class_ops twl4030_rtc_ops = { | ||
402 | .ioctl = twl4030_rtc_ioctl, | ||
403 | .read_time = twl4030_rtc_read_time, | ||
404 | .set_time = twl4030_rtc_set_time, | ||
405 | .read_alarm = twl4030_rtc_read_alarm, | ||
406 | .set_alarm = twl4030_rtc_set_alarm, | ||
407 | }; | ||
408 | |||
409 | /*----------------------------------------------------------------------*/ | ||
410 | |||
411 | static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | ||
412 | { | ||
413 | struct rtc_device *rtc; | ||
414 | int ret = 0; | ||
415 | int irq = platform_get_irq(pdev, 0); | ||
416 | u8 rd_reg; | ||
417 | |||
418 | if (irq < 0) | ||
419 | return irq; | ||
420 | |||
421 | rtc = rtc_device_register(pdev->name, | ||
422 | &pdev->dev, &twl4030_rtc_ops, THIS_MODULE); | ||
423 | if (IS_ERR(rtc)) { | ||
424 | ret = -EINVAL; | ||
425 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", | ||
426 | PTR_ERR(rtc)); | ||
427 | goto out0; | ||
428 | |||
429 | } | ||
430 | |||
431 | platform_set_drvdata(pdev, rtc); | ||
432 | |||
433 | ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); | ||
434 | |||
435 | if (ret < 0) | ||
436 | goto out1; | ||
437 | |||
438 | if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M) | ||
439 | dev_warn(&pdev->dev, "Power up reset detected.\n"); | ||
440 | |||
441 | if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) | ||
442 | dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); | ||
443 | |||
444 | /* Clear RTC Power up reset and pending alarm interrupts */ | ||
445 | ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); | ||
446 | if (ret < 0) | ||
447 | goto out1; | ||
448 | |||
449 | ret = request_irq(irq, twl4030_rtc_interrupt, | ||
450 | IRQF_TRIGGER_RISING, | ||
451 | rtc->dev.bus_id, rtc); | ||
452 | if (ret < 0) { | ||
453 | dev_err(&pdev->dev, "IRQ is not free.\n"); | ||
454 | goto out1; | ||
455 | } | ||
456 | |||
457 | /* Check RTC module status, Enable if it is off */ | ||
458 | ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); | ||
459 | if (ret < 0) | ||
460 | goto out2; | ||
461 | |||
462 | if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { | ||
463 | dev_info(&pdev->dev, "Enabling TWL4030-RTC.\n"); | ||
464 | rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; | ||
465 | ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); | ||
466 | if (ret < 0) | ||
467 | goto out2; | ||
468 | } | ||
469 | |||
470 | /* init cached IRQ enable bits */ | ||
471 | ret = twl4030_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); | ||
472 | if (ret < 0) | ||
473 | goto out2; | ||
474 | |||
475 | return ret; | ||
476 | |||
477 | |||
478 | out2: | ||
479 | free_irq(irq, rtc); | ||
480 | out1: | ||
481 | rtc_device_unregister(rtc); | ||
482 | out0: | ||
483 | return ret; | ||
484 | } | ||
485 | |||
486 | /* | ||
487 | * Disable all TWL4030 RTC module interrupts. | ||
488 | * Sets status flag to free. | ||
489 | */ | ||
490 | static int __devexit twl4030_rtc_remove(struct platform_device *pdev) | ||
491 | { | ||
492 | /* leave rtc running, but disable irqs */ | ||
493 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
494 | int irq = platform_get_irq(pdev, 0); | ||
495 | |||
496 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); | ||
497 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); | ||
498 | |||
499 | free_irq(irq, rtc); | ||
500 | |||
501 | rtc_device_unregister(rtc); | ||
502 | platform_set_drvdata(pdev, NULL); | ||
503 | return 0; | ||
504 | } | ||
505 | |||
506 | static void twl4030_rtc_shutdown(struct platform_device *pdev) | ||
507 | { | ||
508 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M | | ||
509 | BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); | ||
510 | } | ||
511 | |||
512 | #ifdef CONFIG_PM | ||
513 | |||
514 | static unsigned char irqstat; | ||
515 | |||
516 | static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state) | ||
517 | { | ||
518 | irqstat = rtc_irq_bits; | ||
519 | |||
520 | /* REVISIT alarm may need to wake us from sleep */ | ||
521 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M | | ||
522 | BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); | ||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | static int twl4030_rtc_resume(struct platform_device *pdev) | ||
527 | { | ||
528 | set_rtc_irq_bit(irqstat); | ||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | #else | ||
533 | #define twl4030_rtc_suspend NULL | ||
534 | #define twl4030_rtc_resume NULL | ||
535 | #endif | ||
536 | |||
537 | MODULE_ALIAS("platform:twl4030_rtc"); | ||
538 | |||
539 | static struct platform_driver twl4030rtc_driver = { | ||
540 | .probe = twl4030_rtc_probe, | ||
541 | .remove = __devexit_p(twl4030_rtc_remove), | ||
542 | .shutdown = twl4030_rtc_shutdown, | ||
543 | .suspend = twl4030_rtc_suspend, | ||
544 | .resume = twl4030_rtc_resume, | ||
545 | .driver = { | ||
546 | .owner = THIS_MODULE, | ||
547 | .name = "twl4030_rtc", | ||
548 | }, | ||
549 | }; | ||
550 | |||
551 | static int __init twl4030_rtc_init(void) | ||
552 | { | ||
553 | return platform_driver_register(&twl4030rtc_driver); | ||
554 | } | ||
555 | module_init(twl4030_rtc_init); | ||
556 | |||
557 | static void __exit twl4030_rtc_exit(void) | ||
558 | { | ||
559 | platform_driver_unregister(&twl4030rtc_driver); | ||
560 | } | ||
561 | module_exit(twl4030_rtc_exit); | ||
562 | |||
563 | MODULE_AUTHOR("Texas Instruments, MontaVista Software"); | ||
564 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c index 10025d840268..14d4f036a768 100644 --- a/drivers/rtc/rtc-v3020.c +++ b/drivers/rtc/rtc-v3020.c | |||
@@ -92,19 +92,19 @@ static int v3020_read_time(struct device *dev, struct rtc_time *dt) | |||
92 | 92 | ||
93 | /* ...and then read constant values. */ | 93 | /* ...and then read constant values. */ |
94 | tmp = v3020_get_reg(chip, V3020_SECONDS); | 94 | tmp = v3020_get_reg(chip, V3020_SECONDS); |
95 | dt->tm_sec = BCD2BIN(tmp); | 95 | dt->tm_sec = bcd2bin(tmp); |
96 | tmp = v3020_get_reg(chip, V3020_MINUTES); | 96 | tmp = v3020_get_reg(chip, V3020_MINUTES); |
97 | dt->tm_min = BCD2BIN(tmp); | 97 | dt->tm_min = bcd2bin(tmp); |
98 | tmp = v3020_get_reg(chip, V3020_HOURS); | 98 | tmp = v3020_get_reg(chip, V3020_HOURS); |
99 | dt->tm_hour = BCD2BIN(tmp); | 99 | dt->tm_hour = bcd2bin(tmp); |
100 | tmp = v3020_get_reg(chip, V3020_MONTH_DAY); | 100 | tmp = v3020_get_reg(chip, V3020_MONTH_DAY); |
101 | dt->tm_mday = BCD2BIN(tmp); | 101 | dt->tm_mday = bcd2bin(tmp); |
102 | tmp = v3020_get_reg(chip, V3020_MONTH); | 102 | tmp = v3020_get_reg(chip, V3020_MONTH); |
103 | dt->tm_mon = BCD2BIN(tmp) - 1; | 103 | dt->tm_mon = bcd2bin(tmp) - 1; |
104 | tmp = v3020_get_reg(chip, V3020_WEEK_DAY); | 104 | tmp = v3020_get_reg(chip, V3020_WEEK_DAY); |
105 | dt->tm_wday = BCD2BIN(tmp); | 105 | dt->tm_wday = bcd2bin(tmp); |
106 | tmp = v3020_get_reg(chip, V3020_YEAR); | 106 | tmp = v3020_get_reg(chip, V3020_YEAR); |
107 | dt->tm_year = BCD2BIN(tmp)+100; | 107 | dt->tm_year = bcd2bin(tmp)+100; |
108 | 108 | ||
109 | #ifdef DEBUG | 109 | #ifdef DEBUG |
110 | printk("\n%s : Read RTC values\n",__func__); | 110 | printk("\n%s : Read RTC values\n",__func__); |
@@ -136,13 +136,13 @@ static int v3020_set_time(struct device *dev, struct rtc_time *dt) | |||
136 | #endif | 136 | #endif |
137 | 137 | ||
138 | /* Write all the values to ram... */ | 138 | /* Write all the values to ram... */ |
139 | v3020_set_reg(chip, V3020_SECONDS, BIN2BCD(dt->tm_sec)); | 139 | v3020_set_reg(chip, V3020_SECONDS, bin2bcd(dt->tm_sec)); |
140 | v3020_set_reg(chip, V3020_MINUTES, BIN2BCD(dt->tm_min)); | 140 | v3020_set_reg(chip, V3020_MINUTES, bin2bcd(dt->tm_min)); |
141 | v3020_set_reg(chip, V3020_HOURS, BIN2BCD(dt->tm_hour)); | 141 | v3020_set_reg(chip, V3020_HOURS, bin2bcd(dt->tm_hour)); |
142 | v3020_set_reg(chip, V3020_MONTH_DAY, BIN2BCD(dt->tm_mday)); | 142 | v3020_set_reg(chip, V3020_MONTH_DAY, bin2bcd(dt->tm_mday)); |
143 | v3020_set_reg(chip, V3020_MONTH, BIN2BCD(dt->tm_mon + 1)); | 143 | v3020_set_reg(chip, V3020_MONTH, bin2bcd(dt->tm_mon + 1)); |
144 | v3020_set_reg(chip, V3020_WEEK_DAY, BIN2BCD(dt->tm_wday)); | 144 | v3020_set_reg(chip, V3020_WEEK_DAY, bin2bcd(dt->tm_wday)); |
145 | v3020_set_reg(chip, V3020_YEAR, BIN2BCD(dt->tm_year % 100)); | 145 | v3020_set_reg(chip, V3020_YEAR, bin2bcd(dt->tm_year % 100)); |
146 | 146 | ||
147 | /* ...and set the clock. */ | 147 | /* ...and set the clock. */ |
148 | v3020_set_reg(chip, V3020_CMD_RAM2CLOCK, 0); | 148 | v3020_set_reg(chip, V3020_CMD_RAM2CLOCK, 0); |
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index be9c70d0b193..834dcc6d785f 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for NEC VR4100 series Real Time Clock unit. | 2 | * Driver for NEC VR4100 series Real Time Clock unit. |
3 | * | 3 | * |
4 | * Copyright (C) 2003-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2003-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -34,7 +34,7 @@ | |||
34 | 34 | ||
35 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 35 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); |
36 | MODULE_DESCRIPTION("NEC VR4100 series RTC driver"); | 36 | MODULE_DESCRIPTION("NEC VR4100 series RTC driver"); |
37 | MODULE_LICENSE("GPL"); | 37 | MODULE_LICENSE("GPL v2"); |
38 | 38 | ||
39 | /* RTC 1 registers */ | 39 | /* RTC 1 registers */ |
40 | #define ETIMELREG 0x00 | 40 | #define ETIMELREG 0x00 |
@@ -82,7 +82,6 @@ static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */ | |||
82 | 82 | ||
83 | static DEFINE_SPINLOCK(rtc_lock); | 83 | static DEFINE_SPINLOCK(rtc_lock); |
84 | static char rtc_name[] = "RTC"; | 84 | static char rtc_name[] = "RTC"; |
85 | static unsigned long periodic_frequency; | ||
86 | static unsigned long periodic_count; | 85 | static unsigned long periodic_count; |
87 | static unsigned int alarm_enabled; | 86 | static unsigned int alarm_enabled; |
88 | static int aie_irq = -1; | 87 | static int aie_irq = -1; |
@@ -207,10 +206,37 @@ static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | |||
207 | return 0; | 206 | return 0; |
208 | } | 207 | } |
209 | 208 | ||
210 | static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 209 | static int vr41xx_rtc_irq_set_freq(struct device *dev, int freq) |
211 | { | 210 | { |
212 | unsigned long count; | 211 | unsigned long count; |
213 | 212 | ||
213 | count = RTC_FREQUENCY; | ||
214 | do_div(count, freq); | ||
215 | |||
216 | periodic_count = count; | ||
217 | |||
218 | spin_lock_irq(&rtc_lock); | ||
219 | |||
220 | rtc1_write(RTCL1LREG, count); | ||
221 | rtc1_write(RTCL1HREG, count >> 16); | ||
222 | |||
223 | spin_unlock_irq(&rtc_lock); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static int vr41xx_rtc_irq_set_state(struct device *dev, int enabled) | ||
229 | { | ||
230 | if (enabled) | ||
231 | enable_irq(pie_irq); | ||
232 | else | ||
233 | disable_irq(pie_irq); | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
239 | { | ||
214 | switch (cmd) { | 240 | switch (cmd) { |
215 | case RTC_AIE_ON: | 241 | case RTC_AIE_ON: |
216 | spin_lock_irq(&rtc_lock); | 242 | spin_lock_irq(&rtc_lock); |
@@ -232,33 +258,6 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long | |||
232 | 258 | ||
233 | spin_unlock_irq(&rtc_lock); | 259 | spin_unlock_irq(&rtc_lock); |
234 | break; | 260 | break; |
235 | case RTC_PIE_ON: | ||
236 | enable_irq(pie_irq); | ||
237 | break; | ||
238 | case RTC_PIE_OFF: | ||
239 | disable_irq(pie_irq); | ||
240 | break; | ||
241 | case RTC_IRQP_READ: | ||
242 | return put_user(periodic_frequency, (unsigned long __user *)arg); | ||
243 | break; | ||
244 | case RTC_IRQP_SET: | ||
245 | if (arg > MAX_PERIODIC_RATE) | ||
246 | return -EINVAL; | ||
247 | |||
248 | periodic_frequency = arg; | ||
249 | |||
250 | count = RTC_FREQUENCY; | ||
251 | do_div(count, arg); | ||
252 | |||
253 | periodic_count = count; | ||
254 | |||
255 | spin_lock_irq(&rtc_lock); | ||
256 | |||
257 | rtc1_write(RTCL1LREG, count); | ||
258 | rtc1_write(RTCL1HREG, count >> 16); | ||
259 | |||
260 | spin_unlock_irq(&rtc_lock); | ||
261 | break; | ||
262 | case RTC_EPOCH_READ: | 261 | case RTC_EPOCH_READ: |
263 | return put_user(epoch, (unsigned long __user *)arg); | 262 | return put_user(epoch, (unsigned long __user *)arg); |
264 | case RTC_EPOCH_SET: | 263 | case RTC_EPOCH_SET: |
@@ -309,6 +308,8 @@ static const struct rtc_class_ops vr41xx_rtc_ops = { | |||
309 | .set_time = vr41xx_rtc_set_time, | 308 | .set_time = vr41xx_rtc_set_time, |
310 | .read_alarm = vr41xx_rtc_read_alarm, | 309 | .read_alarm = vr41xx_rtc_read_alarm, |
311 | .set_alarm = vr41xx_rtc_set_alarm, | 310 | .set_alarm = vr41xx_rtc_set_alarm, |
311 | .irq_set_freq = vr41xx_rtc_irq_set_freq, | ||
312 | .irq_set_state = vr41xx_rtc_irq_set_state, | ||
312 | }; | 313 | }; |
313 | 314 | ||
314 | static int __devinit rtc_probe(struct platform_device *pdev) | 315 | static int __devinit rtc_probe(struct platform_device *pdev) |
@@ -346,6 +347,8 @@ static int __devinit rtc_probe(struct platform_device *pdev) | |||
346 | goto err_iounmap_all; | 347 | goto err_iounmap_all; |
347 | } | 348 | } |
348 | 349 | ||
350 | rtc->max_user_freq = MAX_PERIODIC_RATE; | ||
351 | |||
349 | spin_lock_irq(&rtc_lock); | 352 | spin_lock_irq(&rtc_lock); |
350 | 353 | ||
351 | rtc1_write(ECMPLREG, 0); | 354 | rtc1_write(ECMPLREG, 0); |
@@ -357,7 +360,7 @@ static int __devinit rtc_probe(struct platform_device *pdev) | |||
357 | spin_unlock_irq(&rtc_lock); | 360 | spin_unlock_irq(&rtc_lock); |
358 | 361 | ||
359 | aie_irq = platform_get_irq(pdev, 0); | 362 | aie_irq = platform_get_irq(pdev, 0); |
360 | if (aie_irq < 0 || aie_irq >= NR_IRQS) { | 363 | if (aie_irq < 0 || aie_irq >= nr_irqs) { |
361 | retval = -EBUSY; | 364 | retval = -EBUSY; |
362 | goto err_device_unregister; | 365 | goto err_device_unregister; |
363 | } | 366 | } |
@@ -368,7 +371,7 @@ static int __devinit rtc_probe(struct platform_device *pdev) | |||
368 | goto err_device_unregister; | 371 | goto err_device_unregister; |
369 | 372 | ||
370 | pie_irq = platform_get_irq(pdev, 1); | 373 | pie_irq = platform_get_irq(pdev, 1); |
371 | if (pie_irq < 0 || pie_irq >= NR_IRQS) | 374 | if (pie_irq < 0 || pie_irq >= nr_irqs) |
372 | goto err_free_irq; | 375 | goto err_free_irq; |
373 | 376 | ||
374 | retval = request_irq(pie_irq, rtclong1_interrupt, IRQF_DISABLED, | 377 | retval = request_irq(pie_irq, rtclong1_interrupt, IRQF_DISABLED, |
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index 7dcfba1bbfe1..310c10795e9a 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c | |||
@@ -118,13 +118,13 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
118 | for (i = 0; i <= 4; i++) | 118 | for (i = 0; i <= 4; i++) |
119 | buf[i] &= 0x7F; | 119 | buf[i] &= 0x7F; |
120 | 120 | ||
121 | tm->tm_sec = BCD2BIN(buf[CCR_SEC]); | 121 | tm->tm_sec = bcd2bin(buf[CCR_SEC]); |
122 | tm->tm_min = BCD2BIN(buf[CCR_MIN]); | 122 | tm->tm_min = bcd2bin(buf[CCR_MIN]); |
123 | tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */ | 123 | tm->tm_hour = bcd2bin(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */ |
124 | tm->tm_mday = BCD2BIN(buf[CCR_MDAY]); | 124 | tm->tm_mday = bcd2bin(buf[CCR_MDAY]); |
125 | tm->tm_mon = BCD2BIN(buf[CCR_MONTH]) - 1; /* mon is 0-11 */ | 125 | tm->tm_mon = bcd2bin(buf[CCR_MONTH]) - 1; /* mon is 0-11 */ |
126 | tm->tm_year = BCD2BIN(buf[CCR_YEAR]) | 126 | tm->tm_year = bcd2bin(buf[CCR_YEAR]) |
127 | + (BCD2BIN(buf[CCR_Y2K]) * 100) - 1900; | 127 | + (bcd2bin(buf[CCR_Y2K]) * 100) - 1900; |
128 | tm->tm_wday = buf[CCR_WDAY]; | 128 | tm->tm_wday = buf[CCR_WDAY]; |
129 | 129 | ||
130 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " | 130 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " |
@@ -174,11 +174,11 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
174 | __func__, | 174 | __func__, |
175 | tm->tm_sec, tm->tm_min, tm->tm_hour); | 175 | tm->tm_sec, tm->tm_min, tm->tm_hour); |
176 | 176 | ||
177 | buf[CCR_SEC] = BIN2BCD(tm->tm_sec); | 177 | buf[CCR_SEC] = bin2bcd(tm->tm_sec); |
178 | buf[CCR_MIN] = BIN2BCD(tm->tm_min); | 178 | buf[CCR_MIN] = bin2bcd(tm->tm_min); |
179 | 179 | ||
180 | /* set hour and 24hr bit */ | 180 | /* set hour and 24hr bit */ |
181 | buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL; | 181 | buf[CCR_HOUR] = bin2bcd(tm->tm_hour) | X1205_HR_MIL; |
182 | 182 | ||
183 | /* should we also set the date? */ | 183 | /* should we also set the date? */ |
184 | if (datetoo) { | 184 | if (datetoo) { |
@@ -187,15 +187,15 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
187 | __func__, | 187 | __func__, |
188 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | 188 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); |
189 | 189 | ||
190 | buf[CCR_MDAY] = BIN2BCD(tm->tm_mday); | 190 | buf[CCR_MDAY] = bin2bcd(tm->tm_mday); |
191 | 191 | ||
192 | /* month, 1 - 12 */ | 192 | /* month, 1 - 12 */ |
193 | buf[CCR_MONTH] = BIN2BCD(tm->tm_mon + 1); | 193 | buf[CCR_MONTH] = bin2bcd(tm->tm_mon + 1); |
194 | 194 | ||
195 | /* year, since the rtc epoch*/ | 195 | /* year, since the rtc epoch*/ |
196 | buf[CCR_YEAR] = BIN2BCD(tm->tm_year % 100); | 196 | buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100); |
197 | buf[CCR_WDAY] = tm->tm_wday & 0x07; | 197 | buf[CCR_WDAY] = tm->tm_wday & 0x07; |
198 | buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100); | 198 | buf[CCR_Y2K] = bin2bcd(tm->tm_year / 100); |
199 | } | 199 | } |
200 | 200 | ||
201 | /* If writing alarm registers, set compare bits on registers 0-4 */ | 201 | /* If writing alarm registers, set compare bits on registers 0-4 */ |
@@ -437,7 +437,7 @@ static int x1205_validate_client(struct i2c_client *client) | |||
437 | return -EIO; | 437 | return -EIO; |
438 | } | 438 | } |
439 | 439 | ||
440 | value = BCD2BIN(reg & probe_limits_pattern[i].mask); | 440 | value = bcd2bin(reg & probe_limits_pattern[i].mask); |
441 | 441 | ||
442 | if (value > probe_limits_pattern[i].max || | 442 | if (value > probe_limits_pattern[i].max || |
443 | value < probe_limits_pattern[i].min) { | 443 | value < probe_limits_pattern[i].min) { |