diff options
Diffstat (limited to 'drivers/rtc')
83 files changed, 11576 insertions, 1607 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 81adbdbd5042..4941cade319f 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -166,6 +166,17 @@ config RTC_DRV_DS1672 | |||
166 | This driver can also be built as a module. If so, the module | 166 | This driver can also be built as a module. If so, the module |
167 | will be called rtc-ds1672. | 167 | will be called rtc-ds1672. |
168 | 168 | ||
169 | config RTC_DRV_DS3232 | ||
170 | tristate "Dallas/Maxim DS3232" | ||
171 | depends on RTC_CLASS && I2C | ||
172 | help | ||
173 | If you say yes here you get support for Dallas Semiconductor | ||
174 | DS3232 real-time clock chips. If an interrupt is associated | ||
175 | with the device, the alarm functionality is supported. | ||
176 | |||
177 | This driver can also be built as a module. If so, the module | ||
178 | will be called rtc-ds3232. | ||
179 | |||
169 | config RTC_DRV_MAX6900 | 180 | config RTC_DRV_MAX6900 |
170 | tristate "Maxim MAX6900" | 181 | tristate "Maxim MAX6900" |
171 | help | 182 | help |
@@ -175,6 +186,26 @@ config RTC_DRV_MAX6900 | |||
175 | This driver can also be built as a module. If so, the module | 186 | This driver can also be built as a module. If so, the module |
176 | will be called rtc-max6900. | 187 | will be called rtc-max6900. |
177 | 188 | ||
189 | config RTC_DRV_MAX8925 | ||
190 | tristate "Maxim MAX8925" | ||
191 | depends on MFD_MAX8925 | ||
192 | help | ||
193 | If you say yes here you will get support for the | ||
194 | RTC of Maxim MAX8925 PMIC. | ||
195 | |||
196 | This driver can also be built as a module. If so, the module | ||
197 | will be called rtc-max8925. | ||
198 | |||
199 | config RTC_DRV_MAX8998 | ||
200 | tristate "Maxim MAX8998" | ||
201 | depends on MFD_MAX8998 | ||
202 | help | ||
203 | If you say yes here you will get support for the | ||
204 | RTC of Maxim MAX8998 PMIC. | ||
205 | |||
206 | This driver can also be built as a module. If so, the module | ||
207 | will be called rtc-max8998. | ||
208 | |||
178 | config RTC_DRV_RS5C372 | 209 | config RTC_DRV_RS5C372 |
179 | tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" | 210 | tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" |
180 | help | 211 | help |
@@ -193,6 +224,15 @@ config RTC_DRV_ISL1208 | |||
193 | This driver can also be built as a module. If so, the module | 224 | This driver can also be built as a module. If so, the module |
194 | will be called rtc-isl1208. | 225 | will be called rtc-isl1208. |
195 | 226 | ||
227 | config RTC_DRV_ISL12022 | ||
228 | tristate "Intersil ISL12022" | ||
229 | help | ||
230 | If you say yes here you get support for the | ||
231 | Intersil ISL12022 RTC chip. | ||
232 | |||
233 | This driver can also be built as a module. If so, the module | ||
234 | will be called rtc-isl12022. | ||
235 | |||
196 | config RTC_DRV_X1205 | 236 | config RTC_DRV_X1205 |
197 | tristate "Xicor/Intersil X1205" | 237 | tristate "Xicor/Intersil X1205" |
198 | help | 238 | help |
@@ -242,6 +282,15 @@ config RTC_DRV_M41T80_WDT | |||
242 | If you say Y here you will get support for the | 282 | If you say Y here you will get support for the |
243 | watchdog timer in the ST M41T60 and M41T80 RTC chips series. | 283 | watchdog timer in the ST M41T60 and M41T80 RTC chips series. |
244 | 284 | ||
285 | config RTC_DRV_BQ32K | ||
286 | tristate "TI BQ32000" | ||
287 | help | ||
288 | If you say Y here you will get support for the TI | ||
289 | BQ32000 I2C RTC chip. | ||
290 | |||
291 | This driver can also be built as a module. If so, the module | ||
292 | will be called rtc-bq32k. | ||
293 | |||
245 | config RTC_DRV_DM355EVM | 294 | config RTC_DRV_DM355EVM |
246 | tristate "TI DaVinci DM355 EVM RTC" | 295 | tristate "TI DaVinci DM355 EVM RTC" |
247 | depends on MFD_DM355EVM_MSP | 296 | depends on MFD_DM355EVM_MSP |
@@ -258,14 +307,14 @@ config RTC_DRV_TWL92330 | |||
258 | the Menelaus driver; it's not separate module. | 307 | the Menelaus driver; it's not separate module. |
259 | 308 | ||
260 | config RTC_DRV_TWL4030 | 309 | config RTC_DRV_TWL4030 |
261 | tristate "TI TWL4030/TWL5030/TPS659x0" | 310 | tristate "TI TWL4030/TWL5030/TWL6030/TPS659x0" |
262 | depends on RTC_CLASS && TWL4030_CORE | 311 | depends on RTC_CLASS && TWL4030_CORE |
263 | help | 312 | help |
264 | If you say yes here you get support for the RTC on the | 313 | If you say yes here you get support for the RTC on the |
265 | TWL4030 family chips, used mostly with OMAP3 platforms. | 314 | TWL4030/TWL5030/TWL6030 family chips, used mostly with OMAP3 platforms. |
266 | 315 | ||
267 | This driver can also be built as a module. If so, the module | 316 | This driver can also be built as a module. If so, the module |
268 | will be called rtc-twl4030. | 317 | will be called rtc-twl. |
269 | 318 | ||
270 | config RTC_DRV_S35390A | 319 | config RTC_DRV_S35390A |
271 | tristate "Seiko Instruments S-35390A" | 320 | tristate "Seiko Instruments S-35390A" |
@@ -378,6 +427,15 @@ config RTC_DRV_DS3234 | |||
378 | This driver can also be built as a module. If so, the module | 427 | This driver can also be built as a module. If so, the module |
379 | will be called rtc-ds3234. | 428 | will be called rtc-ds3234. |
380 | 429 | ||
430 | config RTC_DRV_PCF2123 | ||
431 | tristate "NXP PCF2123" | ||
432 | help | ||
433 | If you say yes here you get support for the NXP PCF2123 | ||
434 | RTC chip. | ||
435 | |||
436 | This driver can also be built as a module. If so, the module | ||
437 | will be called rtc-pcf2123. | ||
438 | |||
381 | endif # SPI_MASTER | 439 | endif # SPI_MASTER |
382 | 440 | ||
383 | comment "Platform RTC drivers" | 441 | comment "Platform RTC drivers" |
@@ -405,6 +463,18 @@ config RTC_DRV_CMOS | |||
405 | This driver can also be built as a module. If so, the module | 463 | This driver can also be built as a module. If so, the module |
406 | will be called rtc-cmos. | 464 | will be called rtc-cmos. |
407 | 465 | ||
466 | config RTC_DRV_VRTC | ||
467 | tristate "Virtual RTC for Moorestown platforms" | ||
468 | depends on X86_MRST | ||
469 | default y if X86_MRST | ||
470 | |||
471 | help | ||
472 | Say "yes" here to get direct support for the real time clock | ||
473 | found on Moorestown platforms. The VRTC is a emulated RTC that | ||
474 | derives its clock source from a real RTC in the PMIC. The MC146818 | ||
475 | style programming interface is mostly conserved, but any | ||
476 | updates are done via IPC calls to the system controller FW. | ||
477 | |||
408 | config RTC_DRV_DS1216 | 478 | config RTC_DRV_DS1216 |
409 | tristate "Dallas DS1216" | 479 | tristate "Dallas DS1216" |
410 | depends on SNI_RM | 480 | depends on SNI_RM |
@@ -500,6 +570,36 @@ config RTC_DRV_M48T59 | |||
500 | This driver can also be built as a module, if so, the module | 570 | This driver can also be built as a module, if so, the module |
501 | will be called "rtc-m48t59". | 571 | will be called "rtc-m48t59". |
502 | 572 | ||
573 | config RTC_DRV_MSM6242 | ||
574 | tristate "Oki MSM6242" | ||
575 | help | ||
576 | If you say yes here you get support for the Oki MSM6242 | ||
577 | timekeeping chip. It is used in some Amiga models (e.g. A2000). | ||
578 | |||
579 | This driver can also be built as a module. If so, the module | ||
580 | will be called rtc-msm6242. | ||
581 | |||
582 | config RTC_DRV_IMXDI | ||
583 | tristate "Freescale IMX DryIce Real Time Clock" | ||
584 | depends on ARCH_MX25 | ||
585 | depends on RTC_CLASS | ||
586 | help | ||
587 | Support for Freescale IMX DryIce RTC | ||
588 | |||
589 | This driver can also be built as a module, if so, the module | ||
590 | will be called "rtc-imxdi". | ||
591 | |||
592 | config RTC_MXC | ||
593 | tristate "Freescale MXC Real Time Clock" | ||
594 | depends on ARCH_MXC | ||
595 | depends on RTC_CLASS | ||
596 | help | ||
597 | If you say yes here you get support for the Freescale MXC | ||
598 | RTC module. | ||
599 | |||
600 | This driver can also be built as a module, if so, the module | ||
601 | will be called "rtc-mxc". | ||
602 | |||
503 | config RTC_DRV_BQ4802 | 603 | config RTC_DRV_BQ4802 |
504 | tristate "TI BQ4802" | 604 | tristate "TI BQ4802" |
505 | help | 605 | help |
@@ -509,6 +609,16 @@ config RTC_DRV_BQ4802 | |||
509 | This driver can also be built as a module. If so, the module | 609 | This driver can also be built as a module. If so, the module |
510 | will be called rtc-bq4802. | 610 | will be called rtc-bq4802. |
511 | 611 | ||
612 | config RTC_DRV_RP5C01 | ||
613 | tristate "Ricoh RP5C01" | ||
614 | help | ||
615 | If you say yes here you get support for the Ricoh RP5C01 | ||
616 | timekeeping chip. It is used in some Amiga models (e.g. A3000 | ||
617 | and A4000). | ||
618 | |||
619 | This driver can also be built as a module. If so, the module | ||
620 | will be called rtc-rp5c01. | ||
621 | |||
512 | config RTC_DRV_V3020 | 622 | config RTC_DRV_V3020 |
513 | tristate "EM Microelectronic V3020" | 623 | tristate "EM Microelectronic V3020" |
514 | help | 624 | help |
@@ -518,6 +628,16 @@ config RTC_DRV_V3020 | |||
518 | This driver can also be built as a module. If so, the module | 628 | This driver can also be built as a module. If so, the module |
519 | will be called rtc-v3020. | 629 | will be called rtc-v3020. |
520 | 630 | ||
631 | config RTC_DRV_WM831X | ||
632 | tristate "Wolfson Microelectronics WM831x RTC" | ||
633 | depends on MFD_WM831X | ||
634 | help | ||
635 | If you say yes here you will get support for the RTC subsystem | ||
636 | of the Wolfson Microelectronics WM831X series PMICs. | ||
637 | |||
638 | This driver can also be built as a module. If so, the module | ||
639 | will be called "rtc-wm831x". | ||
640 | |||
521 | config RTC_DRV_WM8350 | 641 | config RTC_DRV_WM8350 |
522 | tristate "Wolfson Microelectronics WM8350 RTC" | 642 | tristate "Wolfson Microelectronics WM8350 RTC" |
523 | depends on MFD_WM8350 | 643 | depends on MFD_WM8350 |
@@ -535,18 +655,58 @@ config RTC_DRV_PCF50633 | |||
535 | If you say yes here you get support for the RTC subsystem of the | 655 | If you say yes here you get support for the RTC subsystem of the |
536 | NXP PCF50633 used in embedded systems. | 656 | NXP PCF50633 used in embedded systems. |
537 | 657 | ||
658 | config RTC_DRV_AB3100 | ||
659 | tristate "ST-Ericsson AB3100 RTC" | ||
660 | depends on AB3100_CORE | ||
661 | default y if AB3100_CORE | ||
662 | help | ||
663 | Select this to enable the ST-Ericsson AB3100 Mixed Signal IC RTC | ||
664 | support. This chip contains a battery- and capacitor-backed RTC. | ||
665 | |||
666 | config RTC_DRV_AB8500 | ||
667 | tristate "ST-Ericsson AB8500 RTC" | ||
668 | depends on AB8500_CORE | ||
669 | help | ||
670 | Select this to enable the ST-Ericsson AB8500 power management IC RTC | ||
671 | support. This chip contains a battery- and capacitor-backed RTC. | ||
672 | |||
673 | config RTC_DRV_NUC900 | ||
674 | tristate "NUC910/NUC920 RTC driver" | ||
675 | depends on RTC_CLASS && ARCH_W90X900 | ||
676 | help | ||
677 | If you say yes here you get support for the RTC subsystem of the | ||
678 | NUC910/NUC920 used in embedded systems. | ||
679 | |||
538 | comment "on-CPU RTC drivers" | 680 | comment "on-CPU RTC drivers" |
539 | 681 | ||
682 | config RTC_DRV_DAVINCI | ||
683 | tristate "TI DaVinci RTC" | ||
684 | depends on ARCH_DAVINCI_DM365 | ||
685 | help | ||
686 | If you say yes here you get support for the RTC on the | ||
687 | DaVinci platforms (DM365). | ||
688 | |||
689 | This driver can also be built as a module. If so, the module | ||
690 | will be called rtc-davinci. | ||
691 | |||
540 | config RTC_DRV_OMAP | 692 | config RTC_DRV_OMAP |
541 | tristate "TI OMAP1" | 693 | tristate "TI OMAP1" |
542 | depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 | 694 | depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX |
695 | help | ||
696 | Say "yes" here to support the real time clock on TI OMAP1 and | ||
697 | DA8xx/OMAP-L13x chips. This driver can also be built as a | ||
698 | module called rtc-omap. | ||
699 | |||
700 | config HAVE_S3C_RTC | ||
701 | bool | ||
543 | help | 702 | help |
544 | Say "yes" here to support the real time clock on TI OMAP1 chips. | 703 | This will include RTC support for Samsung SoCs. If |
545 | This driver can also be built as a module called rtc-omap. | 704 | you want to include RTC support for any machine, kindly |
705 | select this in the respective mach-XXXX/Kconfig file. | ||
546 | 706 | ||
547 | config RTC_DRV_S3C | 707 | config RTC_DRV_S3C |
548 | tristate "Samsung S3C series SoC RTC" | 708 | tristate "Samsung S3C series SoC RTC" |
549 | depends on ARCH_S3C2410 | 709 | depends on ARCH_S3C2410 || ARCH_S3C64XX || HAVE_S3C_RTC |
550 | help | 710 | help |
551 | RTC (Realtime Clock) driver for the clock inbuilt into the | 711 | RTC (Realtime Clock) driver for the clock inbuilt into the |
552 | Samsung S3C24XX series of SoCs. This can provide periodic | 712 | Samsung S3C24XX series of SoCs. This can provide periodic |
@@ -628,15 +788,15 @@ config RTC_DRV_AT32AP700X | |||
628 | AT32AP700x family processors. | 788 | AT32AP700x family processors. |
629 | 789 | ||
630 | config RTC_DRV_AT91RM9200 | 790 | config RTC_DRV_AT91RM9200 |
631 | tristate "AT91RM9200 or AT91SAM9RL" | 791 | tristate "AT91RM9200 or some AT91SAM9 RTC" |
632 | depends on ARCH_AT91RM9200 || ARCH_AT91SAM9RL | 792 | depends on ARCH_AT91RM9200 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 |
633 | help | 793 | help |
634 | Driver for the internal RTC (Realtime Clock) module found on | 794 | Driver for the internal RTC (Realtime Clock) module found on |
635 | Atmel AT91RM9200's and AT91SAM9RL chips. On SAM9RL chips | 795 | Atmel AT91RM9200's and some AT91SAM9 chips. On AT91SAM9 chips |
636 | this is powered by the backup power supply. | 796 | this is powered by the backup power supply. |
637 | 797 | ||
638 | config RTC_DRV_AT91SAM9 | 798 | config RTC_DRV_AT91SAM9 |
639 | tristate "AT91SAM9x/AT91CAP9" | 799 | tristate "AT91SAM9x/AT91CAP9 RTT as RTC" |
640 | depends on ARCH_AT91 && !(ARCH_AT91RM9200 || ARCH_AT91X40) | 800 | depends on ARCH_AT91 && !(ARCH_AT91RM9200 || ARCH_AT91X40) |
641 | help | 801 | help |
642 | RTC driver for the Atmel AT91SAM9x and AT91CAP9 internal RTT | 802 | RTC driver for the Atmel AT91SAM9x and AT91CAP9 internal RTT |
@@ -644,8 +804,8 @@ config RTC_DRV_AT91SAM9 | |||
644 | supply (such as a small coin cell battery), but do not need to | 804 | supply (such as a small coin cell battery), but do not need to |
645 | be used as RTCs. | 805 | be used as RTCs. |
646 | 806 | ||
647 | (On AT91SAM9rl chips you probably want to use the dedicated RTC | 807 | (On AT91SAM9rl and AT91SAM9G45 chips you probably want to use the |
648 | module and leave the RTT available for other uses.) | 808 | dedicated RTC module and leave the RTT available for other uses.) |
649 | 809 | ||
650 | config RTC_DRV_AT91SAM9_RTT | 810 | config RTC_DRV_AT91SAM9_RTT |
651 | int | 811 | int |
@@ -673,7 +833,7 @@ config RTC_DRV_AT91SAM9_GPBR | |||
673 | 833 | ||
674 | config RTC_DRV_AU1XXX | 834 | config RTC_DRV_AU1XXX |
675 | tristate "Au1xxx Counter0 RTC support" | 835 | tristate "Au1xxx Counter0 RTC support" |
676 | depends on SOC_AU1X00 | 836 | depends on MIPS_ALCHEMY |
677 | help | 837 | help |
678 | This is a driver for the Au1xxx on-chip Counter0 (Time-Of-Year | 838 | This is a driver for the Au1xxx on-chip Counter0 (Time-Of-Year |
679 | counter) to be used as a RTC. | 839 | counter) to be used as a RTC. |
@@ -741,7 +901,7 @@ config RTC_DRV_TX4939 | |||
741 | 901 | ||
742 | config RTC_DRV_MV | 902 | config RTC_DRV_MV |
743 | tristate "Marvell SoC RTC" | 903 | tristate "Marvell SoC RTC" |
744 | depends on ARCH_KIRKWOOD | 904 | depends on ARCH_KIRKWOOD || ARCH_DOVE |
745 | help | 905 | help |
746 | If you say yes here you will get support for the in-chip RTC | 906 | If you say yes here you will get support for the in-chip RTC |
747 | that can be found in some of Marvell's SoC devices, such as | 907 | that can be found in some of Marvell's SoC devices, such as |
@@ -759,4 +919,70 @@ config RTC_DRV_PS3 | |||
759 | This driver can also be built as a module. If so, the module | 919 | This driver can also be built as a module. If so, the module |
760 | will be called rtc-ps3. | 920 | will be called rtc-ps3. |
761 | 921 | ||
922 | config RTC_DRV_COH901331 | ||
923 | tristate "ST-Ericsson COH 901 331 RTC" | ||
924 | depends on ARCH_U300 | ||
925 | help | ||
926 | If you say Y here you will get access to ST-Ericsson | ||
927 | COH 901 331 RTC clock found in some ST-Ericsson Mobile | ||
928 | Platforms. | ||
929 | |||
930 | This driver can also be built as a module. If so, the module | ||
931 | will be called "rtc-coh901331". | ||
932 | |||
933 | |||
934 | config RTC_DRV_STMP | ||
935 | tristate "Freescale STMP3xxx RTC" | ||
936 | depends on ARCH_STMP3XXX | ||
937 | help | ||
938 | If you say yes here you will get support for the onboard | ||
939 | STMP3xxx RTC. | ||
940 | |||
941 | This driver can also be built as a module. If so, the module | ||
942 | will be called rtc-stmp3xxx. | ||
943 | |||
944 | config RTC_DRV_PCAP | ||
945 | tristate "PCAP RTC" | ||
946 | depends on EZX_PCAP | ||
947 | help | ||
948 | If you say Y here you will get support for the RTC found on | ||
949 | the PCAP2 ASIC used on some Motorola phones. | ||
950 | |||
951 | config RTC_DRV_MC13XXX | ||
952 | depends on MFD_MC13XXX | ||
953 | tristate "Freescale MC13xxx RTC" | ||
954 | help | ||
955 | This enables support for the RTCs found on Freescale's PMICs | ||
956 | MC13783 and MC13892. | ||
957 | |||
958 | config RTC_DRV_MPC5121 | ||
959 | tristate "Freescale MPC5121 built-in RTC" | ||
960 | depends on PPC_MPC512x && RTC_CLASS | ||
961 | help | ||
962 | If you say yes here you will get support for the | ||
963 | built-in RTC MPC5121. | ||
964 | |||
965 | This driver can also be built as a module. If so, the module | ||
966 | will be called rtc-mpc5121. | ||
967 | |||
968 | config RTC_DRV_JZ4740 | ||
969 | tristate "Ingenic JZ4740 SoC" | ||
970 | depends on RTC_CLASS | ||
971 | depends on MACH_JZ4740 | ||
972 | help | ||
973 | If you say yes here you get support for the Ingenic JZ4740 SoC RTC | ||
974 | controller. | ||
975 | |||
976 | This driver can also be buillt as a module. If so, the module | ||
977 | will be called rtc-jz4740. | ||
978 | |||
979 | config RTC_DRV_LPC32XX | ||
980 | depends on ARCH_LPC32XX | ||
981 | tristate "NXP LPC32XX RTC" | ||
982 | help | ||
983 | This enables support for the NXP RTC in the LPC32XX | ||
984 | |||
985 | This driver can also be buillt as a module. If so, the module | ||
986 | will be called rtc-lpc32xx. | ||
987 | |||
762 | endif # RTC_CLASS | 988 | endif # RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 3c0f2b2ac927..2afdaf3ff986 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -17,13 +17,20 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o | |||
17 | 17 | ||
18 | # Keep the list ordered. | 18 | # Keep the list ordered. |
19 | 19 | ||
20 | obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o | ||
21 | obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o | ||
20 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o | 22 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o |
21 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o | 23 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o |
22 | obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o | 24 | obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o |
23 | obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o | 25 | obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o |
24 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o | 26 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o |
27 | obj-$(CONFIG_RTC_DRV_BQ32K) += rtc-bq32k.o | ||
28 | obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o | ||
25 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | 29 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o |
30 | obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o | ||
31 | obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o | ||
26 | obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o | 32 | obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o |
33 | obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o | ||
27 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o | 34 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o |
28 | obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o | 35 | obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o |
29 | obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o | 36 | obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o |
@@ -35,30 +42,44 @@ obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o | |||
35 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | 42 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o |
36 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | 43 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o |
37 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o | 44 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o |
45 | obj-$(CONFIG_RTC_DRV_DS3232) += rtc-ds3232.o | ||
38 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o | 46 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o |
39 | obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o | 47 | obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o |
40 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o | 48 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o |
41 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o | 49 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o |
50 | obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o | ||
51 | obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o | ||
42 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o | 52 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o |
53 | obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o | ||
54 | obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o | ||
55 | obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o | ||
43 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o | 56 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o |
44 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o | 57 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o |
45 | obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o | 58 | obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o |
46 | obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o | 59 | obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o |
47 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | 60 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o |
48 | obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o | 61 | obj-$(CONFIG_RTC_MXC) += rtc-mxc.o |
49 | obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o | ||
50 | obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o | ||
51 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o | 62 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o |
63 | obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o | ||
64 | obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o | ||
52 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 65 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
66 | obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o | ||
67 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o | ||
68 | obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o | ||
53 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o | 69 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o |
70 | obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o | ||
54 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o | 71 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o |
72 | obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o | ||
55 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o | 73 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o |
56 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o | 74 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o |
75 | obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o | ||
76 | obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o | ||
57 | obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o | 77 | obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o |
58 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o | 78 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o |
59 | obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o | 79 | obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o |
60 | obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o | 80 | obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o |
61 | obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o | 81 | obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o |
82 | obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o | ||
62 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o | 83 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o |
63 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o | 84 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o |
64 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o | 85 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o |
@@ -68,13 +89,15 @@ obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o | |||
68 | obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o | 89 | obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o |
69 | obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o | 90 | obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o |
70 | obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o | 91 | obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o |
92 | obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o | ||
71 | obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o | 93 | obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o |
94 | obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o | ||
95 | obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o | ||
72 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o | 96 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o |
73 | obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o | 97 | obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o |
74 | obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o | 98 | obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o |
75 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o | 99 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o |
76 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o | 100 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o |
101 | obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o | ||
77 | obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o | 102 | obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o |
78 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o | 103 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o |
79 | obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o | ||
80 | obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o | ||
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index be5a6b73e601..9583cbcc6b79 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <linux/rtc.h> | 15 | #include <linux/rtc.h> |
16 | #include <linux/kdev_t.h> | 16 | #include <linux/kdev_t.h> |
17 | #include <linux/idr.h> | 17 | #include <linux/idr.h> |
18 | #include <linux/slab.h> | ||
19 | #include <linux/workqueue.h> | ||
18 | 20 | ||
19 | #include "rtc-core.h" | 21 | #include "rtc-core.h" |
20 | 22 | ||
@@ -151,14 +153,28 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, | |||
151 | spin_lock_init(&rtc->irq_task_lock); | 153 | spin_lock_init(&rtc->irq_task_lock); |
152 | init_waitqueue_head(&rtc->irq_queue); | 154 | init_waitqueue_head(&rtc->irq_queue); |
153 | 155 | ||
156 | /* Init timerqueue */ | ||
157 | timerqueue_init_head(&rtc->timerqueue); | ||
158 | INIT_WORK(&rtc->irqwork, rtc_timer_do_work); | ||
159 | /* Init aie timer */ | ||
160 | rtc_timer_init(&rtc->aie_timer, rtc_aie_update_irq, (void *)rtc); | ||
161 | /* Init uie timer */ | ||
162 | rtc_timer_init(&rtc->uie_rtctimer, rtc_uie_update_irq, (void *)rtc); | ||
163 | /* Init pie timer */ | ||
164 | hrtimer_init(&rtc->pie_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
165 | rtc->pie_timer.function = rtc_pie_update_irq; | ||
166 | rtc->pie_enabled = 0; | ||
167 | |||
154 | strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); | 168 | strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); |
155 | dev_set_name(&rtc->dev, "rtc%d", id); | 169 | dev_set_name(&rtc->dev, "rtc%d", id); |
156 | 170 | ||
157 | rtc_dev_prepare(rtc); | 171 | rtc_dev_prepare(rtc); |
158 | 172 | ||
159 | err = device_register(&rtc->dev); | 173 | err = device_register(&rtc->dev); |
160 | if (err) | 174 | if (err) { |
175 | put_device(&rtc->dev); | ||
161 | goto exit_kfree; | 176 | goto exit_kfree; |
177 | } | ||
162 | 178 | ||
163 | rtc_dev_add_device(rtc); | 179 | rtc_dev_add_device(rtc); |
164 | rtc_sysfs_add_device(rtc); | 180 | rtc_sysfs_add_device(rtc); |
@@ -226,6 +242,7 @@ static void __exit rtc_exit(void) | |||
226 | { | 242 | { |
227 | rtc_dev_exit(); | 243 | rtc_dev_exit(); |
228 | class_destroy(rtc_class); | 244 | class_destroy(rtc_class); |
245 | idr_destroy(&rtc_idr); | ||
229 | } | 246 | } |
230 | 247 | ||
231 | subsys_initcall(rtc_init); | 248 | subsys_initcall(rtc_init); |
diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c index 33c0e98243ee..bc90b091f195 100644 --- a/drivers/rtc/hctosys.c +++ b/drivers/rtc/hctosys.c | |||
@@ -22,48 +22,57 @@ | |||
22 | * the best guess is to add 0.5s. | 22 | * the best guess is to add 0.5s. |
23 | */ | 23 | */ |
24 | 24 | ||
25 | int rtc_hctosys_ret = -ENODEV; | ||
26 | |||
25 | static int __init rtc_hctosys(void) | 27 | static int __init rtc_hctosys(void) |
26 | { | 28 | { |
27 | int err; | 29 | int err = -ENODEV; |
28 | struct rtc_time tm; | 30 | struct rtc_time tm; |
31 | struct timespec tv = { | ||
32 | .tv_nsec = NSEC_PER_SEC >> 1, | ||
33 | }; | ||
29 | struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); | 34 | struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); |
30 | 35 | ||
31 | if (rtc == NULL) { | 36 | if (rtc == NULL) { |
32 | printk("%s: unable to open rtc device (%s)\n", | 37 | pr_err("%s: unable to open rtc device (%s)\n", |
33 | __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); | 38 | __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); |
34 | return -ENODEV; | 39 | goto err_open; |
35 | } | 40 | } |
36 | 41 | ||
37 | err = rtc_read_time(rtc, &tm); | 42 | err = rtc_read_time(rtc, &tm); |
38 | if (err == 0) { | 43 | if (err) { |
39 | err = rtc_valid_tm(&tm); | 44 | dev_err(rtc->dev.parent, |
40 | if (err == 0) { | 45 | "hctosys: unable to read the hardware clock\n"); |
41 | struct timespec tv; | 46 | goto err_read; |
42 | 47 | ||
43 | tv.tv_nsec = NSEC_PER_SEC >> 1; | 48 | } |
44 | 49 | ||
45 | rtc_tm_to_time(&tm, &tv.tv_sec); | 50 | err = rtc_valid_tm(&tm); |
51 | if (err) { | ||
52 | dev_err(rtc->dev.parent, | ||
53 | "hctosys: invalid date/time\n"); | ||
54 | goto err_invalid; | ||
55 | } | ||
46 | 56 | ||
47 | do_settimeofday(&tv); | 57 | rtc_tm_to_time(&tm, &tv.tv_sec); |
48 | 58 | ||
49 | dev_info(rtc->dev.parent, | 59 | do_settimeofday(&tv); |
50 | "setting system clock to " | ||
51 | "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n", | ||
52 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | ||
53 | tm.tm_hour, tm.tm_min, tm.tm_sec, | ||
54 | (unsigned int) tv.tv_sec); | ||
55 | } | ||
56 | else | ||
57 | dev_err(rtc->dev.parent, | ||
58 | "hctosys: invalid date/time\n"); | ||
59 | } | ||
60 | else | ||
61 | dev_err(rtc->dev.parent, | ||
62 | "hctosys: unable to read the hardware clock\n"); | ||
63 | 60 | ||
61 | dev_info(rtc->dev.parent, | ||
62 | "setting system clock to " | ||
63 | "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n", | ||
64 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | ||
65 | tm.tm_hour, tm.tm_min, tm.tm_sec, | ||
66 | (unsigned int) tv.tv_sec); | ||
67 | |||
68 | err_invalid: | ||
69 | err_read: | ||
64 | rtc_class_close(rtc); | 70 | rtc_class_close(rtc); |
65 | 71 | ||
66 | return 0; | 72 | err_open: |
73 | rtc_hctosys_ret = err; | ||
74 | |||
75 | return err; | ||
67 | } | 76 | } |
68 | 77 | ||
69 | late_initcall(rtc_hctosys); | 78 | late_initcall(rtc_hctosys); |
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 4cdb31a362ca..90384b9f6b2c 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
@@ -12,16 +12,13 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
15 | #include <linux/sched.h> | ||
15 | #include <linux/log2.h> | 16 | #include <linux/log2.h> |
17 | #include <linux/workqueue.h> | ||
16 | 18 | ||
17 | int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) | 19 | static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) |
18 | { | 20 | { |
19 | int err; | 21 | int err; |
20 | |||
21 | err = mutex_lock_interruptible(&rtc->ops_lock); | ||
22 | if (err) | ||
23 | return err; | ||
24 | |||
25 | if (!rtc->ops) | 22 | if (!rtc->ops) |
26 | err = -ENODEV; | 23 | err = -ENODEV; |
27 | else if (!rtc->ops->read_time) | 24 | else if (!rtc->ops->read_time) |
@@ -30,7 +27,18 @@ int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) | |||
30 | memset(tm, 0, sizeof(struct rtc_time)); | 27 | memset(tm, 0, sizeof(struct rtc_time)); |
31 | err = rtc->ops->read_time(rtc->dev.parent, tm); | 28 | err = rtc->ops->read_time(rtc->dev.parent, tm); |
32 | } | 29 | } |
30 | return err; | ||
31 | } | ||
32 | |||
33 | int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) | ||
34 | { | ||
35 | int err; | ||
33 | 36 | ||
37 | err = mutex_lock_interruptible(&rtc->ops_lock); | ||
38 | if (err) | ||
39 | return err; | ||
40 | |||
41 | err = __rtc_read_time(rtc, tm); | ||
34 | mutex_unlock(&rtc->ops_lock); | 42 | mutex_unlock(&rtc->ops_lock); |
35 | return err; | 43 | return err; |
36 | } | 44 | } |
@@ -105,188 +113,54 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs) | |||
105 | } | 113 | } |
106 | EXPORT_SYMBOL_GPL(rtc_set_mmss); | 114 | EXPORT_SYMBOL_GPL(rtc_set_mmss); |
107 | 115 | ||
108 | static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 116 | int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
109 | { | 117 | { |
110 | int err; | 118 | int err; |
111 | 119 | ||
112 | err = mutex_lock_interruptible(&rtc->ops_lock); | 120 | err = mutex_lock_interruptible(&rtc->ops_lock); |
113 | if (err) | 121 | if (err) |
114 | return err; | 122 | return err; |
115 | 123 | alarm->enabled = rtc->aie_timer.enabled; | |
116 | if (rtc->ops == NULL) | 124 | if (alarm->enabled) |
117 | err = -ENODEV; | 125 | alarm->time = rtc_ktime_to_tm(rtc->aie_timer.node.expires); |
118 | else if (!rtc->ops->read_alarm) | ||
119 | err = -EINVAL; | ||
120 | else { | ||
121 | memset(alarm, 0, sizeof(struct rtc_wkalrm)); | ||
122 | err = rtc->ops->read_alarm(rtc->dev.parent, alarm); | ||
123 | } | ||
124 | |||
125 | mutex_unlock(&rtc->ops_lock); | 126 | mutex_unlock(&rtc->ops_lock); |
126 | return err; | 127 | |
128 | return 0; | ||
127 | } | 129 | } |
130 | EXPORT_SYMBOL_GPL(rtc_read_alarm); | ||
128 | 131 | ||
129 | int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 132 | int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
130 | { | 133 | { |
134 | struct rtc_time tm; | ||
135 | long now, scheduled; | ||
131 | int err; | 136 | int err; |
132 | struct rtc_time before, now; | ||
133 | int first_time = 1; | ||
134 | unsigned long t_now, t_alm; | ||
135 | enum { none, day, month, year } missing = none; | ||
136 | unsigned days; | ||
137 | |||
138 | /* The lower level RTC driver may return -1 in some fields, | ||
139 | * creating invalid alarm->time values, for reasons like: | ||
140 | * | ||
141 | * - The hardware may not be capable of filling them in; | ||
142 | * many alarms match only on time-of-day fields, not | ||
143 | * day/month/year calendar data. | ||
144 | * | ||
145 | * - Some hardware uses illegal values as "wildcard" match | ||
146 | * values, which non-Linux firmware (like a BIOS) may try | ||
147 | * to set up as e.g. "alarm 15 minutes after each hour". | ||
148 | * Linux uses only oneshot alarms. | ||
149 | * | ||
150 | * When we see that here, we deal with it by using values from | ||
151 | * a current RTC timestamp for any missing (-1) values. The | ||
152 | * RTC driver prevents "periodic alarm" modes. | ||
153 | * | ||
154 | * But this can be racey, because some fields of the RTC timestamp | ||
155 | * may have wrapped in the interval since we read the RTC alarm, | ||
156 | * which would lead to us inserting inconsistent values in place | ||
157 | * of the -1 fields. | ||
158 | * | ||
159 | * Reading the alarm and timestamp in the reverse sequence | ||
160 | * would have the same race condition, and not solve the issue. | ||
161 | * | ||
162 | * So, we must first read the RTC timestamp, | ||
163 | * then read the RTC alarm value, | ||
164 | * and then read a second RTC timestamp. | ||
165 | * | ||
166 | * If any fields of the second timestamp have changed | ||
167 | * when compared with the first timestamp, then we know | ||
168 | * our timestamp may be inconsistent with that used by | ||
169 | * the low-level rtc_read_alarm_internal() function. | ||
170 | * | ||
171 | * So, when the two timestamps disagree, we just loop and do | ||
172 | * the process again to get a fully consistent set of values. | ||
173 | * | ||
174 | * This could all instead be done in the lower level driver, | ||
175 | * but since more than one lower level RTC implementation needs it, | ||
176 | * then it's probably best best to do it here instead of there.. | ||
177 | */ | ||
178 | 137 | ||
179 | /* Get the "before" timestamp */ | 138 | err = rtc_valid_tm(&alarm->time); |
180 | err = rtc_read_time(rtc, &before); | 139 | if (err) |
181 | if (err < 0) | ||
182 | return err; | 140 | return err; |
183 | do { | 141 | rtc_tm_to_time(&alarm->time, &scheduled); |
184 | if (!first_time) | ||
185 | memcpy(&before, &now, sizeof(struct rtc_time)); | ||
186 | first_time = 0; | ||
187 | |||
188 | /* get the RTC alarm values, which may be incomplete */ | ||
189 | err = rtc_read_alarm_internal(rtc, alarm); | ||
190 | if (err) | ||
191 | return err; | ||
192 | if (!alarm->enabled) | ||
193 | return 0; | ||
194 | |||
195 | /* full-function RTCs won't have such missing fields */ | ||
196 | if (rtc_valid_tm(&alarm->time) == 0) | ||
197 | return 0; | ||
198 | |||
199 | /* get the "after" timestamp, to detect wrapped fields */ | ||
200 | err = rtc_read_time(rtc, &now); | ||
201 | if (err < 0) | ||
202 | return err; | ||
203 | |||
204 | /* note that tm_sec is a "don't care" value here: */ | ||
205 | } while ( before.tm_min != now.tm_min | ||
206 | || before.tm_hour != now.tm_hour | ||
207 | || before.tm_mon != now.tm_mon | ||
208 | || before.tm_year != now.tm_year); | ||
209 | |||
210 | /* Fill in the missing alarm fields using the timestamp; we | ||
211 | * know there's at least one since alarm->time is invalid. | ||
212 | */ | ||
213 | if (alarm->time.tm_sec == -1) | ||
214 | alarm->time.tm_sec = now.tm_sec; | ||
215 | if (alarm->time.tm_min == -1) | ||
216 | alarm->time.tm_min = now.tm_min; | ||
217 | if (alarm->time.tm_hour == -1) | ||
218 | alarm->time.tm_hour = now.tm_hour; | ||
219 | |||
220 | /* For simplicity, only support date rollover for now */ | ||
221 | if (alarm->time.tm_mday == -1) { | ||
222 | alarm->time.tm_mday = now.tm_mday; | ||
223 | missing = day; | ||
224 | } | ||
225 | if (alarm->time.tm_mon == -1) { | ||
226 | alarm->time.tm_mon = now.tm_mon; | ||
227 | if (missing == none) | ||
228 | missing = month; | ||
229 | } | ||
230 | if (alarm->time.tm_year == -1) { | ||
231 | alarm->time.tm_year = now.tm_year; | ||
232 | if (missing == none) | ||
233 | missing = year; | ||
234 | } | ||
235 | |||
236 | /* with luck, no rollover is needed */ | ||
237 | rtc_tm_to_time(&now, &t_now); | ||
238 | rtc_tm_to_time(&alarm->time, &t_alm); | ||
239 | if (t_now < t_alm) | ||
240 | goto done; | ||
241 | |||
242 | switch (missing) { | ||
243 | 142 | ||
244 | /* 24 hour rollover ... if it's now 10am Monday, an alarm that | 143 | /* Make sure we're not setting alarms in the past */ |
245 | * that will trigger at 5am will do so at 5am Tuesday, which | 144 | err = __rtc_read_time(rtc, &tm); |
246 | * could also be in the next month or year. This is a common | 145 | rtc_tm_to_time(&tm, &now); |
247 | * case, especially for PCs. | 146 | if (scheduled <= now) |
248 | */ | 147 | return -ETIME; |
249 | case day: | 148 | /* |
250 | dev_dbg(&rtc->dev, "alarm rollover: %s\n", "day"); | 149 | * XXX - We just checked to make sure the alarm time is not |
251 | t_alm += 24 * 60 * 60; | 150 | * in the past, but there is still a race window where if |
252 | rtc_time_to_tm(t_alm, &alarm->time); | 151 | * the is alarm set for the next second and the second ticks |
253 | break; | 152 | * over right here, before we set the alarm. |
254 | |||
255 | /* Month rollover ... if it's the 31th, an alarm on the 3rd will | ||
256 | * be next month. An alarm matching on the 30th, 29th, or 28th | ||
257 | * may end up in the month after that! Many newer PCs support | ||
258 | * this type of alarm. | ||
259 | */ | 153 | */ |
260 | case month: | ||
261 | dev_dbg(&rtc->dev, "alarm rollover: %s\n", "month"); | ||
262 | do { | ||
263 | if (alarm->time.tm_mon < 11) | ||
264 | alarm->time.tm_mon++; | ||
265 | else { | ||
266 | alarm->time.tm_mon = 0; | ||
267 | alarm->time.tm_year++; | ||
268 | } | ||
269 | days = rtc_month_days(alarm->time.tm_mon, | ||
270 | alarm->time.tm_year); | ||
271 | } while (days < alarm->time.tm_mday); | ||
272 | break; | ||
273 | |||
274 | /* Year rollover ... easy except for leap years! */ | ||
275 | case year: | ||
276 | dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year"); | ||
277 | do { | ||
278 | alarm->time.tm_year++; | ||
279 | } while (rtc_valid_tm(&alarm->time) != 0); | ||
280 | break; | ||
281 | |||
282 | default: | ||
283 | dev_warn(&rtc->dev, "alarm rollover not handled\n"); | ||
284 | } | ||
285 | 154 | ||
286 | done: | 155 | if (!rtc->ops) |
287 | return 0; | 156 | err = -ENODEV; |
157 | else if (!rtc->ops->set_alarm) | ||
158 | err = -EINVAL; | ||
159 | else | ||
160 | err = rtc->ops->set_alarm(rtc->dev.parent, alarm); | ||
161 | |||
162 | return err; | ||
288 | } | 163 | } |
289 | EXPORT_SYMBOL_GPL(rtc_read_alarm); | ||
290 | 164 | ||
291 | int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 165 | int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
292 | { | 166 | { |
@@ -299,16 +173,18 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
299 | err = mutex_lock_interruptible(&rtc->ops_lock); | 173 | err = mutex_lock_interruptible(&rtc->ops_lock); |
300 | if (err) | 174 | if (err) |
301 | return err; | 175 | return err; |
302 | 176 | if (rtc->aie_timer.enabled) { | |
303 | if (!rtc->ops) | 177 | rtc_timer_remove(rtc, &rtc->aie_timer); |
304 | err = -ENODEV; | 178 | rtc->aie_timer.enabled = 0; |
305 | else if (!rtc->ops->set_alarm) | 179 | } |
306 | err = -EINVAL; | 180 | rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); |
307 | else | 181 | rtc->aie_timer.period = ktime_set(0, 0); |
308 | err = rtc->ops->set_alarm(rtc->dev.parent, alarm); | 182 | if (alarm->enabled) { |
309 | 183 | rtc->aie_timer.enabled = 1; | |
184 | rtc_timer_enqueue(rtc, &rtc->aie_timer); | ||
185 | } | ||
310 | mutex_unlock(&rtc->ops_lock); | 186 | mutex_unlock(&rtc->ops_lock); |
311 | return err; | 187 | return 0; |
312 | } | 188 | } |
313 | EXPORT_SYMBOL_GPL(rtc_set_alarm); | 189 | EXPORT_SYMBOL_GPL(rtc_set_alarm); |
314 | 190 | ||
@@ -318,6 +194,16 @@ int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled) | |||
318 | if (err) | 194 | if (err) |
319 | return err; | 195 | return err; |
320 | 196 | ||
197 | if (rtc->aie_timer.enabled != enabled) { | ||
198 | if (enabled) { | ||
199 | rtc->aie_timer.enabled = 1; | ||
200 | rtc_timer_enqueue(rtc, &rtc->aie_timer); | ||
201 | } else { | ||
202 | rtc_timer_remove(rtc, &rtc->aie_timer); | ||
203 | rtc->aie_timer.enabled = 0; | ||
204 | } | ||
205 | } | ||
206 | |||
321 | if (!rtc->ops) | 207 | if (!rtc->ops) |
322 | err = -ENODEV; | 208 | err = -ENODEV; |
323 | else if (!rtc->ops->alarm_irq_enable) | 209 | else if (!rtc->ops->alarm_irq_enable) |
@@ -336,52 +222,53 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) | |||
336 | if (err) | 222 | if (err) |
337 | return err; | 223 | return err; |
338 | 224 | ||
339 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | 225 | /* make sure we're changing state */ |
340 | if (enabled == 0 && rtc->uie_irq_active) { | 226 | if (rtc->uie_rtctimer.enabled == enabled) |
341 | mutex_unlock(&rtc->ops_lock); | 227 | goto out; |
342 | return rtc_dev_update_irq_enable_emul(rtc, enabled); | 228 | |
229 | if (enabled) { | ||
230 | struct rtc_time tm; | ||
231 | ktime_t now, onesec; | ||
232 | |||
233 | __rtc_read_time(rtc, &tm); | ||
234 | onesec = ktime_set(1, 0); | ||
235 | now = rtc_tm_to_ktime(tm); | ||
236 | rtc->uie_rtctimer.node.expires = ktime_add(now, onesec); | ||
237 | rtc->uie_rtctimer.period = ktime_set(1, 0); | ||
238 | rtc->uie_rtctimer.enabled = 1; | ||
239 | rtc_timer_enqueue(rtc, &rtc->uie_rtctimer); | ||
240 | } else { | ||
241 | rtc_timer_remove(rtc, &rtc->uie_rtctimer); | ||
242 | rtc->uie_rtctimer.enabled = 0; | ||
343 | } | 243 | } |
344 | #endif | ||
345 | |||
346 | if (!rtc->ops) | ||
347 | err = -ENODEV; | ||
348 | else if (!rtc->ops->update_irq_enable) | ||
349 | err = -EINVAL; | ||
350 | else | ||
351 | err = rtc->ops->update_irq_enable(rtc->dev.parent, enabled); | ||
352 | 244 | ||
245 | out: | ||
353 | mutex_unlock(&rtc->ops_lock); | 246 | mutex_unlock(&rtc->ops_lock); |
354 | |||
355 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | ||
356 | /* | ||
357 | * Enable emulation if the driver did not provide | ||
358 | * the update_irq_enable function pointer or if returned | ||
359 | * -EINVAL to signal that it has been configured without | ||
360 | * interrupts or that are not available at the moment. | ||
361 | */ | ||
362 | if (err == -EINVAL) | ||
363 | err = rtc_dev_update_irq_enable_emul(rtc, enabled); | ||
364 | #endif | ||
365 | return err; | 247 | return err; |
248 | |||
366 | } | 249 | } |
367 | EXPORT_SYMBOL_GPL(rtc_update_irq_enable); | 250 | EXPORT_SYMBOL_GPL(rtc_update_irq_enable); |
368 | 251 | ||
252 | |||
369 | /** | 253 | /** |
370 | * rtc_update_irq - report RTC periodic, alarm, and/or update irqs | 254 | * rtc_handle_legacy_irq - AIE, UIE and PIE event hook |
371 | * @rtc: the rtc device | 255 | * @rtc: pointer to the rtc device |
372 | * @num: how many irqs are being reported (usually one) | 256 | * |
373 | * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF | 257 | * This function is called when an AIE, UIE or PIE mode interrupt |
374 | * Context: any | 258 | * has occured (or been emulated). |
259 | * | ||
260 | * Triggers the registered irq_task function callback. | ||
375 | */ | 261 | */ |
376 | void rtc_update_irq(struct rtc_device *rtc, | 262 | static void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode) |
377 | unsigned long num, unsigned long events) | ||
378 | { | 263 | { |
379 | unsigned long flags; | 264 | unsigned long flags; |
380 | 265 | ||
266 | /* mark one irq of the appropriate mode */ | ||
381 | spin_lock_irqsave(&rtc->irq_lock, flags); | 267 | spin_lock_irqsave(&rtc->irq_lock, flags); |
382 | rtc->irq_data = (rtc->irq_data + (num << 8)) | events; | 268 | rtc->irq_data = (rtc->irq_data + (num << 8)) | (RTC_IRQF|mode); |
383 | spin_unlock_irqrestore(&rtc->irq_lock, flags); | 269 | spin_unlock_irqrestore(&rtc->irq_lock, flags); |
384 | 270 | ||
271 | /* call the task func */ | ||
385 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | 272 | spin_lock_irqsave(&rtc->irq_task_lock, flags); |
386 | if (rtc->irq_task) | 273 | if (rtc->irq_task) |
387 | rtc->irq_task->func(rtc->irq_task->private_data); | 274 | rtc->irq_task->func(rtc->irq_task->private_data); |
@@ -390,6 +277,69 @@ void rtc_update_irq(struct rtc_device *rtc, | |||
390 | wake_up_interruptible(&rtc->irq_queue); | 277 | wake_up_interruptible(&rtc->irq_queue); |
391 | kill_fasync(&rtc->async_queue, SIGIO, POLL_IN); | 278 | kill_fasync(&rtc->async_queue, SIGIO, POLL_IN); |
392 | } | 279 | } |
280 | |||
281 | |||
282 | /** | ||
283 | * rtc_aie_update_irq - AIE mode rtctimer hook | ||
284 | * @private: pointer to the rtc_device | ||
285 | * | ||
286 | * This functions is called when the aie_timer expires. | ||
287 | */ | ||
288 | void rtc_aie_update_irq(void *private) | ||
289 | { | ||
290 | struct rtc_device *rtc = (struct rtc_device *)private; | ||
291 | rtc_handle_legacy_irq(rtc, 1, RTC_AF); | ||
292 | } | ||
293 | |||
294 | |||
295 | /** | ||
296 | * rtc_uie_update_irq - UIE mode rtctimer hook | ||
297 | * @private: pointer to the rtc_device | ||
298 | * | ||
299 | * This functions is called when the uie_timer expires. | ||
300 | */ | ||
301 | void rtc_uie_update_irq(void *private) | ||
302 | { | ||
303 | struct rtc_device *rtc = (struct rtc_device *)private; | ||
304 | rtc_handle_legacy_irq(rtc, 1, RTC_UF); | ||
305 | } | ||
306 | |||
307 | |||
308 | /** | ||
309 | * rtc_pie_update_irq - PIE mode hrtimer hook | ||
310 | * @timer: pointer to the pie mode hrtimer | ||
311 | * | ||
312 | * This function is used to emulate PIE mode interrupts | ||
313 | * using an hrtimer. This function is called when the periodic | ||
314 | * hrtimer expires. | ||
315 | */ | ||
316 | enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer) | ||
317 | { | ||
318 | struct rtc_device *rtc; | ||
319 | ktime_t period; | ||
320 | int count; | ||
321 | rtc = container_of(timer, struct rtc_device, pie_timer); | ||
322 | |||
323 | period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq); | ||
324 | count = hrtimer_forward_now(timer, period); | ||
325 | |||
326 | rtc_handle_legacy_irq(rtc, count, RTC_PF); | ||
327 | |||
328 | return HRTIMER_RESTART; | ||
329 | } | ||
330 | |||
331 | /** | ||
332 | * rtc_update_irq - Triggered when a RTC interrupt occurs. | ||
333 | * @rtc: the rtc device | ||
334 | * @num: how many irqs are being reported (usually one) | ||
335 | * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF | ||
336 | * Context: any | ||
337 | */ | ||
338 | void rtc_update_irq(struct rtc_device *rtc, | ||
339 | unsigned long num, unsigned long events) | ||
340 | { | ||
341 | schedule_work(&rtc->irqwork); | ||
342 | } | ||
393 | EXPORT_SYMBOL_GPL(rtc_update_irq); | 343 | EXPORT_SYMBOL_GPL(rtc_update_irq); |
394 | 344 | ||
395 | static int __rtc_match(struct device *dev, void *data) | 345 | static int __rtc_match(struct device *dev, void *data) |
@@ -476,18 +426,20 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled | |||
476 | int err = 0; | 426 | int err = 0; |
477 | unsigned long flags; | 427 | unsigned long flags; |
478 | 428 | ||
479 | if (rtc->ops->irq_set_state == NULL) | ||
480 | return -ENXIO; | ||
481 | |||
482 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | 429 | spin_lock_irqsave(&rtc->irq_task_lock, flags); |
483 | if (rtc->irq_task != NULL && task == NULL) | 430 | if (rtc->irq_task != NULL && task == NULL) |
484 | err = -EBUSY; | 431 | err = -EBUSY; |
485 | if (rtc->irq_task != task) | 432 | if (rtc->irq_task != task) |
486 | err = -EACCES; | 433 | err = -EACCES; |
487 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | ||
488 | 434 | ||
489 | if (err == 0) | 435 | if (enabled) { |
490 | err = rtc->ops->irq_set_state(rtc->dev.parent, enabled); | 436 | ktime_t period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq); |
437 | hrtimer_start(&rtc->pie_timer, period, HRTIMER_MODE_REL); | ||
438 | } else { | ||
439 | hrtimer_cancel(&rtc->pie_timer); | ||
440 | } | ||
441 | rtc->pie_enabled = enabled; | ||
442 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | ||
491 | 443 | ||
492 | return err; | 444 | return err; |
493 | } | 445 | } |
@@ -508,21 +460,194 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) | |||
508 | int err = 0; | 460 | int err = 0; |
509 | unsigned long flags; | 461 | unsigned long flags; |
510 | 462 | ||
511 | if (rtc->ops->irq_set_freq == NULL) | ||
512 | return -ENXIO; | ||
513 | |||
514 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | 463 | spin_lock_irqsave(&rtc->irq_task_lock, flags); |
515 | if (rtc->irq_task != NULL && task == NULL) | 464 | if (rtc->irq_task != NULL && task == NULL) |
516 | err = -EBUSY; | 465 | err = -EBUSY; |
517 | if (rtc->irq_task != task) | 466 | if (rtc->irq_task != task) |
518 | err = -EACCES; | 467 | err = -EACCES; |
519 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | ||
520 | |||
521 | if (err == 0) { | 468 | if (err == 0) { |
522 | err = rtc->ops->irq_set_freq(rtc->dev.parent, freq); | 469 | rtc->irq_freq = freq; |
523 | if (err == 0) | 470 | if (rtc->pie_enabled) { |
524 | rtc->irq_freq = freq; | 471 | ktime_t period; |
472 | hrtimer_cancel(&rtc->pie_timer); | ||
473 | period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq); | ||
474 | hrtimer_start(&rtc->pie_timer, period, | ||
475 | HRTIMER_MODE_REL); | ||
476 | } | ||
525 | } | 477 | } |
478 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | ||
526 | return err; | 479 | return err; |
527 | } | 480 | } |
528 | EXPORT_SYMBOL_GPL(rtc_irq_set_freq); | 481 | EXPORT_SYMBOL_GPL(rtc_irq_set_freq); |
482 | |||
483 | /** | ||
484 | * rtc_timer_enqueue - Adds a rtc_timer to the rtc_device timerqueue | ||
485 | * @rtc rtc device | ||
486 | * @timer timer being added. | ||
487 | * | ||
488 | * Enqueues a timer onto the rtc devices timerqueue and sets | ||
489 | * the next alarm event appropriately. | ||
490 | * | ||
491 | * Must hold ops_lock for proper serialization of timerqueue | ||
492 | */ | ||
493 | void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) | ||
494 | { | ||
495 | timerqueue_add(&rtc->timerqueue, &timer->node); | ||
496 | if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) { | ||
497 | struct rtc_wkalrm alarm; | ||
498 | int err; | ||
499 | alarm.time = rtc_ktime_to_tm(timer->node.expires); | ||
500 | alarm.enabled = 1; | ||
501 | err = __rtc_set_alarm(rtc, &alarm); | ||
502 | if (err == -ETIME) | ||
503 | schedule_work(&rtc->irqwork); | ||
504 | } | ||
505 | } | ||
506 | |||
507 | /** | ||
508 | * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue | ||
509 | * @rtc rtc device | ||
510 | * @timer timer being removed. | ||
511 | * | ||
512 | * Removes a timer onto the rtc devices timerqueue and sets | ||
513 | * the next alarm event appropriately. | ||
514 | * | ||
515 | * Must hold ops_lock for proper serialization of timerqueue | ||
516 | */ | ||
517 | void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) | ||
518 | { | ||
519 | struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue); | ||
520 | timerqueue_del(&rtc->timerqueue, &timer->node); | ||
521 | |||
522 | if (next == &timer->node) { | ||
523 | struct rtc_wkalrm alarm; | ||
524 | int err; | ||
525 | next = timerqueue_getnext(&rtc->timerqueue); | ||
526 | if (!next) | ||
527 | return; | ||
528 | alarm.time = rtc_ktime_to_tm(next->expires); | ||
529 | alarm.enabled = 1; | ||
530 | err = __rtc_set_alarm(rtc, &alarm); | ||
531 | if (err == -ETIME) | ||
532 | schedule_work(&rtc->irqwork); | ||
533 | } | ||
534 | } | ||
535 | |||
536 | /** | ||
537 | * rtc_timer_do_work - Expires rtc timers | ||
538 | * @rtc rtc device | ||
539 | * @timer timer being removed. | ||
540 | * | ||
541 | * Expires rtc timers. Reprograms next alarm event if needed. | ||
542 | * Called via worktask. | ||
543 | * | ||
544 | * Serializes access to timerqueue via ops_lock mutex | ||
545 | */ | ||
546 | void rtc_timer_do_work(struct work_struct *work) | ||
547 | { | ||
548 | struct rtc_timer *timer; | ||
549 | struct timerqueue_node *next; | ||
550 | ktime_t now; | ||
551 | struct rtc_time tm; | ||
552 | |||
553 | struct rtc_device *rtc = | ||
554 | container_of(work, struct rtc_device, irqwork); | ||
555 | |||
556 | mutex_lock(&rtc->ops_lock); | ||
557 | again: | ||
558 | __rtc_read_time(rtc, &tm); | ||
559 | now = rtc_tm_to_ktime(tm); | ||
560 | while ((next = timerqueue_getnext(&rtc->timerqueue))) { | ||
561 | if (next->expires.tv64 > now.tv64) | ||
562 | break; | ||
563 | |||
564 | /* expire timer */ | ||
565 | timer = container_of(next, struct rtc_timer, node); | ||
566 | timerqueue_del(&rtc->timerqueue, &timer->node); | ||
567 | timer->enabled = 0; | ||
568 | if (timer->task.func) | ||
569 | timer->task.func(timer->task.private_data); | ||
570 | |||
571 | /* Re-add/fwd periodic timers */ | ||
572 | if (ktime_to_ns(timer->period)) { | ||
573 | timer->node.expires = ktime_add(timer->node.expires, | ||
574 | timer->period); | ||
575 | timer->enabled = 1; | ||
576 | timerqueue_add(&rtc->timerqueue, &timer->node); | ||
577 | } | ||
578 | } | ||
579 | |||
580 | /* Set next alarm */ | ||
581 | if (next) { | ||
582 | struct rtc_wkalrm alarm; | ||
583 | int err; | ||
584 | alarm.time = rtc_ktime_to_tm(next->expires); | ||
585 | alarm.enabled = 1; | ||
586 | err = __rtc_set_alarm(rtc, &alarm); | ||
587 | if (err == -ETIME) | ||
588 | goto again; | ||
589 | } | ||
590 | |||
591 | mutex_unlock(&rtc->ops_lock); | ||
592 | } | ||
593 | |||
594 | |||
595 | /* rtc_timer_init - Initializes an rtc_timer | ||
596 | * @timer: timer to be intiialized | ||
597 | * @f: function pointer to be called when timer fires | ||
598 | * @data: private data passed to function pointer | ||
599 | * | ||
600 | * Kernel interface to initializing an rtc_timer. | ||
601 | */ | ||
602 | void rtc_timer_init(struct rtc_timer *timer, void (*f)(void* p), void* data) | ||
603 | { | ||
604 | timerqueue_init(&timer->node); | ||
605 | timer->enabled = 0; | ||
606 | timer->task.func = f; | ||
607 | timer->task.private_data = data; | ||
608 | } | ||
609 | |||
610 | /* rtc_timer_start - Sets an rtc_timer to fire in the future | ||
611 | * @ rtc: rtc device to be used | ||
612 | * @ timer: timer being set | ||
613 | * @ expires: time at which to expire the timer | ||
614 | * @ period: period that the timer will recur | ||
615 | * | ||
616 | * Kernel interface to set an rtc_timer | ||
617 | */ | ||
618 | int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer* timer, | ||
619 | ktime_t expires, ktime_t period) | ||
620 | { | ||
621 | int ret = 0; | ||
622 | mutex_lock(&rtc->ops_lock); | ||
623 | if (timer->enabled) | ||
624 | rtc_timer_remove(rtc, timer); | ||
625 | |||
626 | timer->node.expires = expires; | ||
627 | timer->period = period; | ||
628 | |||
629 | timer->enabled = 1; | ||
630 | rtc_timer_enqueue(rtc, timer); | ||
631 | |||
632 | mutex_unlock(&rtc->ops_lock); | ||
633 | return ret; | ||
634 | } | ||
635 | |||
636 | /* rtc_timer_cancel - Stops an rtc_timer | ||
637 | * @ rtc: rtc device to be used | ||
638 | * @ timer: timer being set | ||
639 | * | ||
640 | * Kernel interface to cancel an rtc_timer | ||
641 | */ | ||
642 | int rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer* timer) | ||
643 | { | ||
644 | int ret = 0; | ||
645 | mutex_lock(&rtc->ops_lock); | ||
646 | if (timer->enabled) | ||
647 | rtc_timer_remove(rtc, timer); | ||
648 | timer->enabled = 0; | ||
649 | mutex_unlock(&rtc->ops_lock); | ||
650 | return ret; | ||
651 | } | ||
652 | |||
653 | |||
diff --git a/drivers/rtc/rtc-ab3100.c b/drivers/rtc/rtc-ab3100.c new file mode 100644 index 000000000000..261a07e0fb24 --- /dev/null +++ b/drivers/rtc/rtc-ab3100.c | |||
@@ -0,0 +1,276 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2009 ST-Ericsson AB | ||
3 | * License terms: GNU General Public License (GPL) version 2 | ||
4 | * RTC clock driver for the AB3100 Analog Baseband Chip | ||
5 | * Author: Linus Walleij <linus.walleij@stericsson.com> | ||
6 | */ | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/platform_device.h> | ||
11 | #include <linux/rtc.h> | ||
12 | #include <linux/mfd/abx500.h> | ||
13 | |||
14 | /* Clock rate in Hz */ | ||
15 | #define AB3100_RTC_CLOCK_RATE 32768 | ||
16 | |||
17 | /* | ||
18 | * The AB3100 RTC registers. These are the same for | ||
19 | * AB3000 and AB3100. | ||
20 | * Control register: | ||
21 | * Bit 0: RTC Monitor cleared=0, active=1, if you set it | ||
22 | * to 1 it remains active until RTC power is lost. | ||
23 | * Bit 1: 32 kHz Oscillator, 0 = on, 1 = bypass | ||
24 | * Bit 2: Alarm on, 0 = off, 1 = on | ||
25 | * Bit 3: 32 kHz buffer disabling, 0 = enabled, 1 = disabled | ||
26 | */ | ||
27 | #define AB3100_RTC 0x53 | ||
28 | /* default setting, buffer disabled, alarm on */ | ||
29 | #define RTC_SETTING 0x30 | ||
30 | /* Alarm when AL0-AL3 == TI0-TI3 */ | ||
31 | #define AB3100_AL0 0x56 | ||
32 | #define AB3100_AL1 0x57 | ||
33 | #define AB3100_AL2 0x58 | ||
34 | #define AB3100_AL3 0x59 | ||
35 | /* This 48-bit register that counts up at 32768 Hz */ | ||
36 | #define AB3100_TI0 0x5a | ||
37 | #define AB3100_TI1 0x5b | ||
38 | #define AB3100_TI2 0x5c | ||
39 | #define AB3100_TI3 0x5d | ||
40 | #define AB3100_TI4 0x5e | ||
41 | #define AB3100_TI5 0x5f | ||
42 | |||
43 | /* | ||
44 | * RTC clock functions and device struct declaration | ||
45 | */ | ||
46 | static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
47 | { | ||
48 | u8 regs[] = {AB3100_TI0, AB3100_TI1, AB3100_TI2, | ||
49 | AB3100_TI3, AB3100_TI4, AB3100_TI5}; | ||
50 | unsigned char buf[6]; | ||
51 | u64 fat_time = (u64) secs * AB3100_RTC_CLOCK_RATE * 2; | ||
52 | int err = 0; | ||
53 | int i; | ||
54 | |||
55 | buf[0] = (fat_time) & 0xFF; | ||
56 | buf[1] = (fat_time >> 8) & 0xFF; | ||
57 | buf[2] = (fat_time >> 16) & 0xFF; | ||
58 | buf[3] = (fat_time >> 24) & 0xFF; | ||
59 | buf[4] = (fat_time >> 32) & 0xFF; | ||
60 | buf[5] = (fat_time >> 40) & 0xFF; | ||
61 | |||
62 | for (i = 0; i < 6; i++) { | ||
63 | err = abx500_set_register_interruptible(dev, 0, | ||
64 | regs[i], buf[i]); | ||
65 | if (err) | ||
66 | return err; | ||
67 | } | ||
68 | |||
69 | /* Set the flag to mark that the clock is now set */ | ||
70 | return abx500_mask_and_set_register_interruptible(dev, 0, | ||
71 | AB3100_RTC, | ||
72 | 0x01, 0x01); | ||
73 | |||
74 | } | ||
75 | |||
76 | static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
77 | { | ||
78 | unsigned long time; | ||
79 | u8 rtcval; | ||
80 | int err; | ||
81 | |||
82 | err = abx500_get_register_interruptible(dev, 0, | ||
83 | AB3100_RTC, &rtcval); | ||
84 | if (err) | ||
85 | return err; | ||
86 | |||
87 | if (!(rtcval & 0x01)) { | ||
88 | dev_info(dev, "clock not set (lost power)"); | ||
89 | return -EINVAL; | ||
90 | } else { | ||
91 | u64 fat_time; | ||
92 | u8 buf[6]; | ||
93 | |||
94 | /* Read out time registers */ | ||
95 | err = abx500_get_register_page_interruptible(dev, 0, | ||
96 | AB3100_TI0, | ||
97 | buf, 6); | ||
98 | if (err != 0) | ||
99 | return err; | ||
100 | |||
101 | fat_time = ((u64) buf[5] << 40) | ((u64) buf[4] << 32) | | ||
102 | ((u64) buf[3] << 24) | ((u64) buf[2] << 16) | | ||
103 | ((u64) buf[1] << 8) | (u64) buf[0]; | ||
104 | time = (unsigned long) (fat_time / | ||
105 | (u64) (AB3100_RTC_CLOCK_RATE * 2)); | ||
106 | } | ||
107 | |||
108 | rtc_time_to_tm(time, tm); | ||
109 | |||
110 | return rtc_valid_tm(tm); | ||
111 | } | ||
112 | |||
113 | static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
114 | { | ||
115 | unsigned long time; | ||
116 | u64 fat_time; | ||
117 | u8 buf[6]; | ||
118 | u8 rtcval; | ||
119 | int err; | ||
120 | |||
121 | /* Figure out if alarm is enabled or not */ | ||
122 | err = abx500_get_register_interruptible(dev, 0, | ||
123 | AB3100_RTC, &rtcval); | ||
124 | if (err) | ||
125 | return err; | ||
126 | if (rtcval & 0x04) | ||
127 | alarm->enabled = 1; | ||
128 | else | ||
129 | alarm->enabled = 0; | ||
130 | /* No idea how this could be represented */ | ||
131 | alarm->pending = 0; | ||
132 | /* Read out alarm registers, only 4 bytes */ | ||
133 | err = abx500_get_register_page_interruptible(dev, 0, | ||
134 | AB3100_AL0, buf, 4); | ||
135 | if (err) | ||
136 | return err; | ||
137 | fat_time = ((u64) buf[3] << 40) | ((u64) buf[2] << 32) | | ||
138 | ((u64) buf[1] << 24) | ((u64) buf[0] << 16); | ||
139 | time = (unsigned long) (fat_time / (u64) (AB3100_RTC_CLOCK_RATE * 2)); | ||
140 | |||
141 | rtc_time_to_tm(time, &alarm->time); | ||
142 | |||
143 | return rtc_valid_tm(&alarm->time); | ||
144 | } | ||
145 | |||
146 | static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
147 | { | ||
148 | u8 regs[] = {AB3100_AL0, AB3100_AL1, AB3100_AL2, AB3100_AL3}; | ||
149 | unsigned char buf[4]; | ||
150 | unsigned long secs; | ||
151 | u64 fat_time; | ||
152 | int err; | ||
153 | int i; | ||
154 | |||
155 | rtc_tm_to_time(&alarm->time, &secs); | ||
156 | fat_time = (u64) secs * AB3100_RTC_CLOCK_RATE * 2; | ||
157 | buf[0] = (fat_time >> 16) & 0xFF; | ||
158 | buf[1] = (fat_time >> 24) & 0xFF; | ||
159 | buf[2] = (fat_time >> 32) & 0xFF; | ||
160 | buf[3] = (fat_time >> 40) & 0xFF; | ||
161 | |||
162 | /* Set the alarm */ | ||
163 | for (i = 0; i < 4; i++) { | ||
164 | err = abx500_set_register_interruptible(dev, 0, | ||
165 | regs[i], buf[i]); | ||
166 | if (err) | ||
167 | return err; | ||
168 | } | ||
169 | /* Then enable the alarm */ | ||
170 | return abx500_mask_and_set_register_interruptible(dev, 0, | ||
171 | AB3100_RTC, (1 << 2), | ||
172 | alarm->enabled << 2); | ||
173 | } | ||
174 | |||
175 | static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled) | ||
176 | { | ||
177 | /* | ||
178 | * It's not possible to enable/disable the alarm IRQ for this RTC. | ||
179 | * It does not actually trigger any IRQ: instead its only function is | ||
180 | * to power up the system, if it wasn't on. This will manifest as | ||
181 | * a "power up cause" in the AB3100 power driver (battery charging etc) | ||
182 | * and need to be handled there instead. | ||
183 | */ | ||
184 | if (enabled) | ||
185 | return abx500_mask_and_set_register_interruptible(dev, 0, | ||
186 | AB3100_RTC, (1 << 2), | ||
187 | 1 << 2); | ||
188 | else | ||
189 | return abx500_mask_and_set_register_interruptible(dev, 0, | ||
190 | AB3100_RTC, (1 << 2), | ||
191 | 0); | ||
192 | } | ||
193 | |||
194 | static const struct rtc_class_ops ab3100_rtc_ops = { | ||
195 | .read_time = ab3100_rtc_read_time, | ||
196 | .set_mmss = ab3100_rtc_set_mmss, | ||
197 | .read_alarm = ab3100_rtc_read_alarm, | ||
198 | .set_alarm = ab3100_rtc_set_alarm, | ||
199 | .alarm_irq_enable = ab3100_rtc_irq_enable, | ||
200 | }; | ||
201 | |||
202 | static int __init ab3100_rtc_probe(struct platform_device *pdev) | ||
203 | { | ||
204 | int err; | ||
205 | u8 regval; | ||
206 | struct rtc_device *rtc; | ||
207 | |||
208 | /* The first RTC register needs special treatment */ | ||
209 | err = abx500_get_register_interruptible(&pdev->dev, 0, | ||
210 | AB3100_RTC, ®val); | ||
211 | if (err) { | ||
212 | dev_err(&pdev->dev, "unable to read RTC register\n"); | ||
213 | return -ENODEV; | ||
214 | } | ||
215 | |||
216 | if ((regval & 0xFE) != RTC_SETTING) { | ||
217 | dev_warn(&pdev->dev, "not default value in RTC reg 0x%x\n", | ||
218 | regval); | ||
219 | } | ||
220 | |||
221 | if ((regval & 1) == 0) { | ||
222 | /* | ||
223 | * Set bit to detect power loss. | ||
224 | * This bit remains until RTC power is lost. | ||
225 | */ | ||
226 | regval = 1 | RTC_SETTING; | ||
227 | err = abx500_set_register_interruptible(&pdev->dev, 0, | ||
228 | AB3100_RTC, regval); | ||
229 | /* Ignore any error on this write */ | ||
230 | } | ||
231 | |||
232 | rtc = rtc_device_register("ab3100-rtc", &pdev->dev, &ab3100_rtc_ops, | ||
233 | THIS_MODULE); | ||
234 | if (IS_ERR(rtc)) { | ||
235 | err = PTR_ERR(rtc); | ||
236 | return err; | ||
237 | } | ||
238 | platform_set_drvdata(pdev, rtc); | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int __exit ab3100_rtc_remove(struct platform_device *pdev) | ||
244 | { | ||
245 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
246 | |||
247 | rtc_device_unregister(rtc); | ||
248 | platform_set_drvdata(pdev, NULL); | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static struct platform_driver ab3100_rtc_driver = { | ||
253 | .driver = { | ||
254 | .name = "ab3100-rtc", | ||
255 | .owner = THIS_MODULE, | ||
256 | }, | ||
257 | .remove = __exit_p(ab3100_rtc_remove), | ||
258 | }; | ||
259 | |||
260 | static int __init ab3100_rtc_init(void) | ||
261 | { | ||
262 | return platform_driver_probe(&ab3100_rtc_driver, | ||
263 | ab3100_rtc_probe); | ||
264 | } | ||
265 | |||
266 | static void __exit ab3100_rtc_exit(void) | ||
267 | { | ||
268 | platform_driver_unregister(&ab3100_rtc_driver); | ||
269 | } | ||
270 | |||
271 | module_init(ab3100_rtc_init); | ||
272 | module_exit(ab3100_rtc_exit); | ||
273 | |||
274 | MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>"); | ||
275 | MODULE_DESCRIPTION("AB3100 RTC Driver"); | ||
276 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c new file mode 100644 index 000000000000..e346705aae92 --- /dev/null +++ b/drivers/rtc/rtc-ab8500.c | |||
@@ -0,0 +1,366 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | * Author: Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com> | ||
6 | * | ||
7 | * RTC clock driver for the RTC part of the AB8500 Power management chip. | ||
8 | * Based on RTC clock driver for the AB3100 Analog Baseband Chip by | ||
9 | * Linus Walleij <linus.walleij@stericsson.com> | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/rtc.h> | ||
17 | #include <linux/mfd/abx500.h> | ||
18 | #include <linux/mfd/ab8500.h> | ||
19 | #include <linux/delay.h> | ||
20 | |||
21 | #define AB8500_RTC_SOFF_STAT_REG 0x00 | ||
22 | #define AB8500_RTC_CC_CONF_REG 0x01 | ||
23 | #define AB8500_RTC_READ_REQ_REG 0x02 | ||
24 | #define AB8500_RTC_WATCH_TSECMID_REG 0x03 | ||
25 | #define AB8500_RTC_WATCH_TSECHI_REG 0x04 | ||
26 | #define AB8500_RTC_WATCH_TMIN_LOW_REG 0x05 | ||
27 | #define AB8500_RTC_WATCH_TMIN_MID_REG 0x06 | ||
28 | #define AB8500_RTC_WATCH_TMIN_HI_REG 0x07 | ||
29 | #define AB8500_RTC_ALRM_MIN_LOW_REG 0x08 | ||
30 | #define AB8500_RTC_ALRM_MIN_MID_REG 0x09 | ||
31 | #define AB8500_RTC_ALRM_MIN_HI_REG 0x0A | ||
32 | #define AB8500_RTC_STAT_REG 0x0B | ||
33 | #define AB8500_RTC_BKUP_CHG_REG 0x0C | ||
34 | #define AB8500_RTC_FORCE_BKUP_REG 0x0D | ||
35 | #define AB8500_RTC_CALIB_REG 0x0E | ||
36 | #define AB8500_RTC_SWITCH_STAT_REG 0x0F | ||
37 | |||
38 | /* RtcReadRequest bits */ | ||
39 | #define RTC_READ_REQUEST 0x01 | ||
40 | #define RTC_WRITE_REQUEST 0x02 | ||
41 | |||
42 | /* RtcCtrl bits */ | ||
43 | #define RTC_ALARM_ENA 0x04 | ||
44 | #define RTC_STATUS_DATA 0x01 | ||
45 | |||
46 | #define COUNTS_PER_SEC (0xF000 / 60) | ||
47 | #define AB8500_RTC_EPOCH 2000 | ||
48 | |||
49 | static const u8 ab8500_rtc_time_regs[] = { | ||
50 | AB8500_RTC_WATCH_TMIN_HI_REG, AB8500_RTC_WATCH_TMIN_MID_REG, | ||
51 | AB8500_RTC_WATCH_TMIN_LOW_REG, AB8500_RTC_WATCH_TSECHI_REG, | ||
52 | AB8500_RTC_WATCH_TSECMID_REG | ||
53 | }; | ||
54 | |||
55 | static const u8 ab8500_rtc_alarm_regs[] = { | ||
56 | AB8500_RTC_ALRM_MIN_HI_REG, AB8500_RTC_ALRM_MIN_MID_REG, | ||
57 | AB8500_RTC_ALRM_MIN_LOW_REG | ||
58 | }; | ||
59 | |||
60 | /* Calculate the seconds from 1970 to 01-01-2000 00:00:00 */ | ||
61 | static unsigned long get_elapsed_seconds(int year) | ||
62 | { | ||
63 | unsigned long secs; | ||
64 | struct rtc_time tm = { | ||
65 | .tm_year = year - 1900, | ||
66 | .tm_mday = 1, | ||
67 | }; | ||
68 | |||
69 | /* | ||
70 | * This function calculates secs from 1970 and not from | ||
71 | * 1900, even if we supply the offset from year 1900. | ||
72 | */ | ||
73 | rtc_tm_to_time(&tm, &secs); | ||
74 | return secs; | ||
75 | } | ||
76 | |||
77 | static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
78 | { | ||
79 | unsigned long timeout = jiffies + HZ; | ||
80 | int retval, i; | ||
81 | unsigned long mins, secs; | ||
82 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; | ||
83 | u8 value; | ||
84 | |||
85 | /* Request a data read */ | ||
86 | retval = abx500_set_register_interruptible(dev, | ||
87 | AB8500_RTC, AB8500_RTC_READ_REQ_REG, RTC_READ_REQUEST); | ||
88 | if (retval < 0) | ||
89 | return retval; | ||
90 | |||
91 | /* Early AB8500 chips will not clear the rtc read request bit */ | ||
92 | if (abx500_get_chip_id(dev) == 0) { | ||
93 | msleep(1); | ||
94 | } else { | ||
95 | /* Wait for some cycles after enabling the rtc read in ab8500 */ | ||
96 | while (time_before(jiffies, timeout)) { | ||
97 | retval = abx500_get_register_interruptible(dev, | ||
98 | AB8500_RTC, AB8500_RTC_READ_REQ_REG, &value); | ||
99 | if (retval < 0) | ||
100 | return retval; | ||
101 | |||
102 | if (!(value & RTC_READ_REQUEST)) | ||
103 | break; | ||
104 | |||
105 | msleep(1); | ||
106 | } | ||
107 | } | ||
108 | |||
109 | /* Read the Watchtime registers */ | ||
110 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) { | ||
111 | retval = abx500_get_register_interruptible(dev, | ||
112 | AB8500_RTC, ab8500_rtc_time_regs[i], &value); | ||
113 | if (retval < 0) | ||
114 | return retval; | ||
115 | buf[i] = value; | ||
116 | } | ||
117 | |||
118 | mins = (buf[0] << 16) | (buf[1] << 8) | buf[2]; | ||
119 | |||
120 | secs = (buf[3] << 8) | buf[4]; | ||
121 | secs = secs / COUNTS_PER_SEC; | ||
122 | secs = secs + (mins * 60); | ||
123 | |||
124 | /* Add back the initially subtracted number of seconds */ | ||
125 | secs += get_elapsed_seconds(AB8500_RTC_EPOCH); | ||
126 | |||
127 | rtc_time_to_tm(secs, tm); | ||
128 | return rtc_valid_tm(tm); | ||
129 | } | ||
130 | |||
131 | static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
132 | { | ||
133 | int retval, i; | ||
134 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; | ||
135 | unsigned long no_secs, no_mins, secs = 0; | ||
136 | |||
137 | if (tm->tm_year < (AB8500_RTC_EPOCH - 1900)) { | ||
138 | dev_dbg(dev, "year should be equal to or greater than %d\n", | ||
139 | AB8500_RTC_EPOCH); | ||
140 | return -EINVAL; | ||
141 | } | ||
142 | |||
143 | /* Get the number of seconds since 1970 */ | ||
144 | rtc_tm_to_time(tm, &secs); | ||
145 | |||
146 | /* | ||
147 | * Convert it to the number of seconds since 01-01-2000 00:00:00, since | ||
148 | * we only have a small counter in the RTC. | ||
149 | */ | ||
150 | secs -= get_elapsed_seconds(AB8500_RTC_EPOCH); | ||
151 | |||
152 | no_mins = secs / 60; | ||
153 | |||
154 | no_secs = secs % 60; | ||
155 | /* Make the seconds count as per the RTC resolution */ | ||
156 | no_secs = no_secs * COUNTS_PER_SEC; | ||
157 | |||
158 | buf[4] = no_secs & 0xFF; | ||
159 | buf[3] = (no_secs >> 8) & 0xFF; | ||
160 | |||
161 | buf[2] = no_mins & 0xFF; | ||
162 | buf[1] = (no_mins >> 8) & 0xFF; | ||
163 | buf[0] = (no_mins >> 16) & 0xFF; | ||
164 | |||
165 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) { | ||
166 | retval = abx500_set_register_interruptible(dev, AB8500_RTC, | ||
167 | ab8500_rtc_time_regs[i], buf[i]); | ||
168 | if (retval < 0) | ||
169 | return retval; | ||
170 | } | ||
171 | |||
172 | /* Request a data write */ | ||
173 | return abx500_set_register_interruptible(dev, AB8500_RTC, | ||
174 | AB8500_RTC_READ_REQ_REG, RTC_WRITE_REQUEST); | ||
175 | } | ||
176 | |||
177 | static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
178 | { | ||
179 | int retval, i; | ||
180 | u8 rtc_ctrl, value; | ||
181 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; | ||
182 | unsigned long secs, mins; | ||
183 | |||
184 | /* Check if the alarm is enabled or not */ | ||
185 | retval = abx500_get_register_interruptible(dev, AB8500_RTC, | ||
186 | AB8500_RTC_STAT_REG, &rtc_ctrl); | ||
187 | if (retval < 0) | ||
188 | return retval; | ||
189 | |||
190 | if (rtc_ctrl & RTC_ALARM_ENA) | ||
191 | alarm->enabled = 1; | ||
192 | else | ||
193 | alarm->enabled = 0; | ||
194 | |||
195 | alarm->pending = 0; | ||
196 | |||
197 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) { | ||
198 | retval = abx500_get_register_interruptible(dev, AB8500_RTC, | ||
199 | ab8500_rtc_alarm_regs[i], &value); | ||
200 | if (retval < 0) | ||
201 | return retval; | ||
202 | buf[i] = value; | ||
203 | } | ||
204 | |||
205 | mins = (buf[0] << 16) | (buf[1] << 8) | (buf[2]); | ||
206 | secs = mins * 60; | ||
207 | |||
208 | /* Add back the initially subtracted number of seconds */ | ||
209 | secs += get_elapsed_seconds(AB8500_RTC_EPOCH); | ||
210 | |||
211 | rtc_time_to_tm(secs, &alarm->time); | ||
212 | |||
213 | return rtc_valid_tm(&alarm->time); | ||
214 | } | ||
215 | |||
216 | static int ab8500_rtc_irq_enable(struct device *dev, unsigned int enabled) | ||
217 | { | ||
218 | return abx500_mask_and_set_register_interruptible(dev, AB8500_RTC, | ||
219 | AB8500_RTC_STAT_REG, RTC_ALARM_ENA, | ||
220 | enabled ? RTC_ALARM_ENA : 0); | ||
221 | } | ||
222 | |||
223 | static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
224 | { | ||
225 | int retval, i; | ||
226 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; | ||
227 | unsigned long mins, secs = 0; | ||
228 | |||
229 | if (alarm->time.tm_year < (AB8500_RTC_EPOCH - 1900)) { | ||
230 | dev_dbg(dev, "year should be equal to or greater than %d\n", | ||
231 | AB8500_RTC_EPOCH); | ||
232 | return -EINVAL; | ||
233 | } | ||
234 | |||
235 | /* Get the number of seconds since 1970 */ | ||
236 | rtc_tm_to_time(&alarm->time, &secs); | ||
237 | |||
238 | /* | ||
239 | * Convert it to the number of seconds since 01-01-2000 00:00:00, since | ||
240 | * we only have a small counter in the RTC. | ||
241 | */ | ||
242 | secs -= get_elapsed_seconds(AB8500_RTC_EPOCH); | ||
243 | |||
244 | mins = secs / 60; | ||
245 | |||
246 | buf[2] = mins & 0xFF; | ||
247 | buf[1] = (mins >> 8) & 0xFF; | ||
248 | buf[0] = (mins >> 16) & 0xFF; | ||
249 | |||
250 | /* Set the alarm time */ | ||
251 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) { | ||
252 | retval = abx500_set_register_interruptible(dev, AB8500_RTC, | ||
253 | ab8500_rtc_alarm_regs[i], buf[i]); | ||
254 | if (retval < 0) | ||
255 | return retval; | ||
256 | } | ||
257 | |||
258 | return ab8500_rtc_irq_enable(dev, alarm->enabled); | ||
259 | } | ||
260 | |||
261 | static irqreturn_t rtc_alarm_handler(int irq, void *data) | ||
262 | { | ||
263 | struct rtc_device *rtc = data; | ||
264 | unsigned long events = RTC_IRQF | RTC_AF; | ||
265 | |||
266 | dev_dbg(&rtc->dev, "%s\n", __func__); | ||
267 | rtc_update_irq(rtc, 1, events); | ||
268 | |||
269 | return IRQ_HANDLED; | ||
270 | } | ||
271 | |||
272 | static const struct rtc_class_ops ab8500_rtc_ops = { | ||
273 | .read_time = ab8500_rtc_read_time, | ||
274 | .set_time = ab8500_rtc_set_time, | ||
275 | .read_alarm = ab8500_rtc_read_alarm, | ||
276 | .set_alarm = ab8500_rtc_set_alarm, | ||
277 | .alarm_irq_enable = ab8500_rtc_irq_enable, | ||
278 | }; | ||
279 | |||
280 | static int __devinit ab8500_rtc_probe(struct platform_device *pdev) | ||
281 | { | ||
282 | int err; | ||
283 | struct rtc_device *rtc; | ||
284 | u8 rtc_ctrl; | ||
285 | int irq; | ||
286 | |||
287 | irq = platform_get_irq_byname(pdev, "ALARM"); | ||
288 | if (irq < 0) | ||
289 | return irq; | ||
290 | |||
291 | /* For RTC supply test */ | ||
292 | err = abx500_mask_and_set_register_interruptible(&pdev->dev, AB8500_RTC, | ||
293 | AB8500_RTC_STAT_REG, RTC_STATUS_DATA, RTC_STATUS_DATA); | ||
294 | if (err < 0) | ||
295 | return err; | ||
296 | |||
297 | /* Wait for reset by the PorRtc */ | ||
298 | msleep(1); | ||
299 | |||
300 | err = abx500_get_register_interruptible(&pdev->dev, AB8500_RTC, | ||
301 | AB8500_RTC_STAT_REG, &rtc_ctrl); | ||
302 | if (err < 0) | ||
303 | return err; | ||
304 | |||
305 | /* Check if the RTC Supply fails */ | ||
306 | if (!(rtc_ctrl & RTC_STATUS_DATA)) { | ||
307 | dev_err(&pdev->dev, "RTC supply failure\n"); | ||
308 | return -ENODEV; | ||
309 | } | ||
310 | |||
311 | rtc = rtc_device_register("ab8500-rtc", &pdev->dev, &ab8500_rtc_ops, | ||
312 | THIS_MODULE); | ||
313 | if (IS_ERR(rtc)) { | ||
314 | dev_err(&pdev->dev, "Registration failed\n"); | ||
315 | err = PTR_ERR(rtc); | ||
316 | return err; | ||
317 | } | ||
318 | |||
319 | err = request_threaded_irq(irq, NULL, rtc_alarm_handler, 0, | ||
320 | "ab8500-rtc", rtc); | ||
321 | if (err < 0) { | ||
322 | rtc_device_unregister(rtc); | ||
323 | return err; | ||
324 | } | ||
325 | |||
326 | platform_set_drvdata(pdev, rtc); | ||
327 | |||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static int __devexit ab8500_rtc_remove(struct platform_device *pdev) | ||
332 | { | ||
333 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
334 | int irq = platform_get_irq_byname(pdev, "ALARM"); | ||
335 | |||
336 | free_irq(irq, rtc); | ||
337 | rtc_device_unregister(rtc); | ||
338 | platform_set_drvdata(pdev, NULL); | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static struct platform_driver ab8500_rtc_driver = { | ||
344 | .driver = { | ||
345 | .name = "ab8500-rtc", | ||
346 | .owner = THIS_MODULE, | ||
347 | }, | ||
348 | .probe = ab8500_rtc_probe, | ||
349 | .remove = __devexit_p(ab8500_rtc_remove), | ||
350 | }; | ||
351 | |||
352 | static int __init ab8500_rtc_init(void) | ||
353 | { | ||
354 | return platform_driver_register(&ab8500_rtc_driver); | ||
355 | } | ||
356 | |||
357 | static void __exit ab8500_rtc_exit(void) | ||
358 | { | ||
359 | platform_driver_unregister(&ab8500_rtc_driver); | ||
360 | } | ||
361 | |||
362 | module_init(ab8500_rtc_init); | ||
363 | module_exit(ab8500_rtc_exit); | ||
364 | MODULE_AUTHOR("Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>"); | ||
365 | MODULE_DESCRIPTION("AB8500 RTC Driver"); | ||
366 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c index e1ec33e40e38..b2752b6e7a2f 100644 --- a/drivers/rtc/rtc-at32ap700x.c +++ b/drivers/rtc/rtc-at32ap700x.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/rtc.h> | 15 | #include <linux/rtc.h> |
15 | #include <linux/io.h> | 16 | #include <linux/io.h> |
16 | 17 | ||
@@ -256,6 +257,8 @@ static int __init at32_rtc_probe(struct platform_device *pdev) | |||
256 | goto out_iounmap; | 257 | goto out_iounmap; |
257 | } | 258 | } |
258 | 259 | ||
260 | platform_set_drvdata(pdev, rtc); | ||
261 | |||
259 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, | 262 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, |
260 | &at32_rtc_ops, THIS_MODULE); | 263 | &at32_rtc_ops, THIS_MODULE); |
261 | if (IS_ERR(rtc->rtc)) { | 264 | if (IS_ERR(rtc->rtc)) { |
@@ -264,7 +267,6 @@ static int __init at32_rtc_probe(struct platform_device *pdev) | |||
264 | goto out_free_irq; | 267 | goto out_free_irq; |
265 | } | 268 | } |
266 | 269 | ||
267 | platform_set_drvdata(pdev, rtc); | ||
268 | device_init_wakeup(&pdev->dev, 1); | 270 | device_init_wakeup(&pdev->dev, 1); |
269 | 271 | ||
270 | dev_info(&pdev->dev, "Atmel RTC for AT32AP700x at %08lx irq %ld\n", | 272 | dev_info(&pdev->dev, "Atmel RTC for AT32AP700x at %08lx irq %ld\n", |
@@ -273,6 +275,7 @@ static int __init at32_rtc_probe(struct platform_device *pdev) | |||
273 | return 0; | 275 | return 0; |
274 | 276 | ||
275 | out_free_irq: | 277 | out_free_irq: |
278 | platform_set_drvdata(pdev, NULL); | ||
276 | free_irq(irq, rtc); | 279 | free_irq(irq, rtc); |
277 | out_iounmap: | 280 | out_iounmap: |
278 | iounmap(rtc->regs); | 281 | iounmap(rtc->regs); |
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index b5bf93706913..bc8bbca9a2e2 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c | |||
@@ -289,7 +289,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev) | |||
289 | AT91_RTC_CALEV); | 289 | AT91_RTC_CALEV); |
290 | 290 | ||
291 | ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, | 291 | ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, |
292 | IRQF_DISABLED | IRQF_SHARED, | 292 | IRQF_SHARED, |
293 | "at91_rtc", pdev); | 293 | "at91_rtc", pdev); |
294 | if (ret) { | 294 | if (ret) { |
295 | printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n", | 295 | printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n", |
@@ -340,7 +340,7 @@ static int __exit at91_rtc_remove(struct platform_device *pdev) | |||
340 | 340 | ||
341 | static u32 at91_rtc_imr; | 341 | static u32 at91_rtc_imr; |
342 | 342 | ||
343 | static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 343 | static int at91_rtc_suspend(struct device *dev) |
344 | { | 344 | { |
345 | /* this IRQ is shared with DBGU and other hardware which isn't | 345 | /* this IRQ is shared with DBGU and other hardware which isn't |
346 | * necessarily doing PM like we are... | 346 | * necessarily doing PM like we are... |
@@ -348,7 +348,7 @@ static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
348 | at91_rtc_imr = at91_sys_read(AT91_RTC_IMR) | 348 | at91_rtc_imr = at91_sys_read(AT91_RTC_IMR) |
349 | & (AT91_RTC_ALARM|AT91_RTC_SECEV); | 349 | & (AT91_RTC_ALARM|AT91_RTC_SECEV); |
350 | if (at91_rtc_imr) { | 350 | if (at91_rtc_imr) { |
351 | if (device_may_wakeup(&pdev->dev)) | 351 | if (device_may_wakeup(dev)) |
352 | enable_irq_wake(AT91_ID_SYS); | 352 | enable_irq_wake(AT91_ID_SYS); |
353 | else | 353 | else |
354 | at91_sys_write(AT91_RTC_IDR, at91_rtc_imr); | 354 | at91_sys_write(AT91_RTC_IDR, at91_rtc_imr); |
@@ -356,28 +356,34 @@ static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
356 | return 0; | 356 | return 0; |
357 | } | 357 | } |
358 | 358 | ||
359 | static int at91_rtc_resume(struct platform_device *pdev) | 359 | static int at91_rtc_resume(struct device *dev) |
360 | { | 360 | { |
361 | if (at91_rtc_imr) { | 361 | if (at91_rtc_imr) { |
362 | if (device_may_wakeup(&pdev->dev)) | 362 | if (device_may_wakeup(dev)) |
363 | disable_irq_wake(AT91_ID_SYS); | 363 | disable_irq_wake(AT91_ID_SYS); |
364 | else | 364 | else |
365 | at91_sys_write(AT91_RTC_IER, at91_rtc_imr); | 365 | at91_sys_write(AT91_RTC_IER, at91_rtc_imr); |
366 | } | 366 | } |
367 | return 0; | 367 | return 0; |
368 | } | 368 | } |
369 | |||
370 | static const struct dev_pm_ops at91_rtc_pm = { | ||
371 | .suspend = at91_rtc_suspend, | ||
372 | .resume = at91_rtc_resume, | ||
373 | }; | ||
374 | |||
375 | #define at91_rtc_pm_ptr &at91_rtc_pm | ||
376 | |||
369 | #else | 377 | #else |
370 | #define at91_rtc_suspend NULL | 378 | #define at91_rtc_pm_ptr NULL |
371 | #define at91_rtc_resume NULL | ||
372 | #endif | 379 | #endif |
373 | 380 | ||
374 | static struct platform_driver at91_rtc_driver = { | 381 | static struct platform_driver at91_rtc_driver = { |
375 | .remove = __exit_p(at91_rtc_remove), | 382 | .remove = __exit_p(at91_rtc_remove), |
376 | .suspend = at91_rtc_suspend, | ||
377 | .resume = at91_rtc_resume, | ||
378 | .driver = { | 383 | .driver = { |
379 | .name = "at91_rtc", | 384 | .name = "at91_rtc", |
380 | .owner = THIS_MODULE, | 385 | .owner = THIS_MODULE, |
386 | .pm = at91_rtc_pm_ptr, | ||
381 | }, | 387 | }, |
382 | }; | 388 | }; |
383 | 389 | ||
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index 86c61f143515..f677e0710ca1 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/rtc.h> | 18 | #include <linux/rtc.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/ioctl.h> | 20 | #include <linux/ioctl.h> |
21 | #include <linux/slab.h> | ||
21 | 22 | ||
22 | #include <mach/board.h> | 23 | #include <mach/board.h> |
23 | #include <mach/at91_rtt.h> | 24 | #include <mach/at91_rtt.h> |
@@ -161,7 +162,7 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
161 | if (offset == 0) | 162 | if (offset == 0) |
162 | return -EILSEQ; | 163 | return -EILSEQ; |
163 | 164 | ||
164 | memset(alrm, 0, sizeof(alrm)); | 165 | memset(alrm, 0, sizeof(*alrm)); |
165 | if (alarm != ALARM_DISABLED && offset != 0) { | 166 | if (alarm != ALARM_DISABLED && offset != 0) { |
166 | rtc_time_to_tm(offset + alarm, tm); | 167 | rtc_time_to_tm(offset + alarm, tm); |
167 | 168 | ||
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index aafd3e6ebb0d..b4b6087f2234 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
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 BF51x/BF52x/BF53[123]/BF53[467]/BF54x |
4 | * | 4 | * |
5 | * Copyright 2004-2008 Analog Devices Inc. | 5 | * Copyright 2004-2010 Analog Devices Inc. |
6 | * | 6 | * |
7 | * Enter bugs at http://blackfin.uclinux.org/ | 7 | * Enter bugs at http://blackfin.uclinux.org/ |
8 | * | 8 | * |
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/platform_device.h> | 51 | #include <linux/platform_device.h> |
52 | #include <linux/rtc.h> | 52 | #include <linux/rtc.h> |
53 | #include <linux/seq_file.h> | 53 | #include <linux/seq_file.h> |
54 | #include <linux/slab.h> | ||
54 | 55 | ||
55 | #include <asm/blackfin.h> | 56 | #include <asm/blackfin.h> |
56 | 57 | ||
@@ -182,29 +183,33 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) | |||
182 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 183 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
183 | unsigned long events = 0; | 184 | unsigned long events = 0; |
184 | bool write_complete = false; | 185 | bool write_complete = false; |
185 | u16 rtc_istat, rtc_ictl; | 186 | u16 rtc_istat, rtc_istat_clear, rtc_ictl, bits; |
186 | 187 | ||
187 | dev_dbg_stamp(dev); | 188 | dev_dbg_stamp(dev); |
188 | 189 | ||
189 | rtc_istat = bfin_read_RTC_ISTAT(); | 190 | rtc_istat = bfin_read_RTC_ISTAT(); |
190 | rtc_ictl = bfin_read_RTC_ICTL(); | 191 | rtc_ictl = bfin_read_RTC_ICTL(); |
192 | rtc_istat_clear = 0; | ||
191 | 193 | ||
192 | if (rtc_istat & RTC_ISTAT_WRITE_COMPLETE) { | 194 | bits = RTC_ISTAT_WRITE_COMPLETE; |
193 | bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE); | 195 | if (rtc_istat & bits) { |
196 | rtc_istat_clear |= bits; | ||
194 | write_complete = true; | 197 | write_complete = true; |
195 | complete(&bfin_write_complete); | 198 | complete(&bfin_write_complete); |
196 | } | 199 | } |
197 | 200 | ||
198 | if (rtc_ictl & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { | 201 | bits = (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); |
199 | if (rtc_istat & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { | 202 | if (rtc_ictl & bits) { |
200 | bfin_write_RTC_ISTAT(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); | 203 | if (rtc_istat & bits) { |
204 | rtc_istat_clear |= bits; | ||
201 | events |= RTC_AF | RTC_IRQF; | 205 | events |= RTC_AF | RTC_IRQF; |
202 | } | 206 | } |
203 | } | 207 | } |
204 | 208 | ||
205 | if (rtc_ictl & RTC_ISTAT_SEC) { | 209 | bits = RTC_ISTAT_SEC; |
206 | if (rtc_istat & RTC_ISTAT_SEC) { | 210 | if (rtc_ictl & bits) { |
207 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); | 211 | if (rtc_istat & bits) { |
212 | rtc_istat_clear |= bits; | ||
208 | events |= RTC_UF | RTC_IRQF; | 213 | events |= RTC_UF | RTC_IRQF; |
209 | } | 214 | } |
210 | } | 215 | } |
@@ -212,9 +217,10 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) | |||
212 | if (events) | 217 | if (events) |
213 | rtc_update_irq(rtc->rtc_dev, 1, events); | 218 | rtc_update_irq(rtc->rtc_dev, 1, events); |
214 | 219 | ||
215 | if (write_complete || events) | 220 | if (write_complete || events) { |
221 | bfin_write_RTC_ISTAT(rtc_istat_clear); | ||
216 | return IRQ_HANDLED; | 222 | return IRQ_HANDLED; |
217 | else | 223 | } else |
218 | return IRQ_NONE; | 224 | return IRQ_NONE; |
219 | } | 225 | } |
220 | 226 | ||
@@ -363,7 +369,7 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) | |||
363 | struct bfin_rtc *rtc; | 369 | struct bfin_rtc *rtc; |
364 | struct device *dev = &pdev->dev; | 370 | struct device *dev = &pdev->dev; |
365 | int ret = 0; | 371 | int ret = 0; |
366 | unsigned long timeout; | 372 | unsigned long timeout = jiffies + HZ; |
367 | 373 | ||
368 | dev_dbg_stamp(dev); | 374 | dev_dbg_stamp(dev); |
369 | 375 | ||
@@ -374,32 +380,32 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) | |||
374 | platform_set_drvdata(pdev, rtc); | 380 | platform_set_drvdata(pdev, rtc); |
375 | device_init_wakeup(dev, 1); | 381 | device_init_wakeup(dev, 1); |
376 | 382 | ||
383 | /* Register our RTC with the RTC framework */ | ||
384 | rtc->rtc_dev = rtc_device_register(pdev->name, dev, &bfin_rtc_ops, | ||
385 | THIS_MODULE); | ||
386 | if (unlikely(IS_ERR(rtc->rtc_dev))) { | ||
387 | ret = PTR_ERR(rtc->rtc_dev); | ||
388 | goto err; | ||
389 | } | ||
390 | |||
377 | /* Grab the IRQ and init the hardware */ | 391 | /* Grab the IRQ and init the hardware */ |
378 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, pdev->name, dev); | 392 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, 0, pdev->name, dev); |
379 | if (unlikely(ret)) | 393 | if (unlikely(ret)) |
380 | goto err; | 394 | goto err_reg; |
381 | /* sometimes the bootloader touched things, but the write complete was not | 395 | /* sometimes the bootloader touched things, but the write complete was not |
382 | * enabled, so let's just do a quick timeout here since the IRQ will not fire ... | 396 | * enabled, so let's just do a quick timeout here since the IRQ will not fire ... |
383 | */ | 397 | */ |
384 | timeout = jiffies + HZ; | ||
385 | while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING) | 398 | while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING) |
386 | if (time_after(jiffies, timeout)) | 399 | if (time_after(jiffies, timeout)) |
387 | break; | 400 | break; |
388 | bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); | 401 | bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); |
389 | bfin_write_RTC_SWCNT(0); | 402 | bfin_write_RTC_SWCNT(0); |
390 | 403 | ||
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->rtc_dev))) { | ||
394 | ret = PTR_ERR(rtc->rtc_dev); | ||
395 | goto err_irq; | ||
396 | } | ||
397 | |||
398 | return 0; | 404 | return 0; |
399 | 405 | ||
400 | err_irq: | 406 | err_reg: |
401 | free_irq(IRQ_RTC, dev); | 407 | rtc_device_unregister(rtc->rtc_dev); |
402 | err: | 408 | err: |
403 | kfree(rtc); | 409 | kfree(rtc); |
404 | return ret; | 410 | return ret; |
405 | } | 411 | } |
@@ -421,21 +427,38 @@ static int __devexit bfin_rtc_remove(struct platform_device *pdev) | |||
421 | #ifdef CONFIG_PM | 427 | #ifdef CONFIG_PM |
422 | static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 428 | static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
423 | { | 429 | { |
424 | if (device_may_wakeup(&pdev->dev)) { | 430 | struct device *dev = &pdev->dev; |
431 | |||
432 | dev_dbg_stamp(dev); | ||
433 | |||
434 | if (device_may_wakeup(dev)) { | ||
425 | enable_irq_wake(IRQ_RTC); | 435 | enable_irq_wake(IRQ_RTC); |
426 | bfin_rtc_sync_pending(&pdev->dev); | 436 | bfin_rtc_sync_pending(dev); |
427 | } else | 437 | } else |
428 | bfin_rtc_int_clear(-1); | 438 | bfin_rtc_int_clear(0); |
429 | 439 | ||
430 | return 0; | 440 | return 0; |
431 | } | 441 | } |
432 | 442 | ||
433 | static int bfin_rtc_resume(struct platform_device *pdev) | 443 | static int bfin_rtc_resume(struct platform_device *pdev) |
434 | { | 444 | { |
435 | if (device_may_wakeup(&pdev->dev)) | 445 | struct device *dev = &pdev->dev; |
446 | |||
447 | dev_dbg_stamp(dev); | ||
448 | |||
449 | if (device_may_wakeup(dev)) | ||
436 | disable_irq_wake(IRQ_RTC); | 450 | disable_irq_wake(IRQ_RTC); |
437 | else | 451 | |
438 | bfin_write_RTC_ISTAT(-1); | 452 | /* |
453 | * Since only some of the RTC bits are maintained externally in the | ||
454 | * Vbat domain, we need to wait for the RTC MMRs to be synced into | ||
455 | * the core after waking up. This happens every RTC 1HZ. Once that | ||
456 | * has happened, we can go ahead and re-enable the important write | ||
457 | * complete interrupt event. | ||
458 | */ | ||
459 | while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_SEC)) | ||
460 | continue; | ||
461 | bfin_rtc_int_set(RTC_ISTAT_WRITE_COMPLETE); | ||
439 | 462 | ||
440 | return 0; | 463 | return 0; |
441 | } | 464 | } |
diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c new file mode 100644 index 000000000000..408cc8f735be --- /dev/null +++ b/drivers/rtc/rtc-bq32k.c | |||
@@ -0,0 +1,204 @@ | |||
1 | /* | ||
2 | * Driver for TI BQ32000 RTC. | ||
3 | * | ||
4 | * Copyright (C) 2009 Semihalf. | ||
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/i2c.h> | ||
13 | #include <linux/rtc.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/bcd.h> | ||
17 | |||
18 | #define BQ32K_SECONDS 0x00 /* Seconds register address */ | ||
19 | #define BQ32K_SECONDS_MASK 0x7F /* Mask over seconds value */ | ||
20 | #define BQ32K_STOP 0x80 /* Oscillator Stop flat */ | ||
21 | |||
22 | #define BQ32K_MINUTES 0x01 /* Minutes register address */ | ||
23 | #define BQ32K_MINUTES_MASK 0x7F /* Mask over minutes value */ | ||
24 | #define BQ32K_OF 0x80 /* Oscillator Failure flag */ | ||
25 | |||
26 | #define BQ32K_HOURS_MASK 0x3F /* Mask over hours value */ | ||
27 | #define BQ32K_CENT 0x40 /* Century flag */ | ||
28 | #define BQ32K_CENT_EN 0x80 /* Century flag enable bit */ | ||
29 | |||
30 | struct bq32k_regs { | ||
31 | uint8_t seconds; | ||
32 | uint8_t minutes; | ||
33 | uint8_t cent_hours; | ||
34 | uint8_t day; | ||
35 | uint8_t date; | ||
36 | uint8_t month; | ||
37 | uint8_t years; | ||
38 | }; | ||
39 | |||
40 | static struct i2c_driver bq32k_driver; | ||
41 | |||
42 | static int bq32k_read(struct device *dev, void *data, uint8_t off, uint8_t len) | ||
43 | { | ||
44 | struct i2c_client *client = to_i2c_client(dev); | ||
45 | struct i2c_msg msgs[] = { | ||
46 | { | ||
47 | .addr = client->addr, | ||
48 | .flags = 0, | ||
49 | .len = 1, | ||
50 | .buf = &off, | ||
51 | }, { | ||
52 | .addr = client->addr, | ||
53 | .flags = I2C_M_RD, | ||
54 | .len = len, | ||
55 | .buf = data, | ||
56 | } | ||
57 | }; | ||
58 | |||
59 | if (i2c_transfer(client->adapter, msgs, 2) == 2) | ||
60 | return 0; | ||
61 | |||
62 | return -EIO; | ||
63 | } | ||
64 | |||
65 | static int bq32k_write(struct device *dev, void *data, uint8_t off, uint8_t len) | ||
66 | { | ||
67 | struct i2c_client *client = to_i2c_client(dev); | ||
68 | uint8_t buffer[len + 1]; | ||
69 | |||
70 | buffer[0] = off; | ||
71 | memcpy(&buffer[1], data, len); | ||
72 | |||
73 | if (i2c_master_send(client, buffer, len + 1) == len + 1) | ||
74 | return 0; | ||
75 | |||
76 | return -EIO; | ||
77 | } | ||
78 | |||
79 | static int bq32k_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
80 | { | ||
81 | struct bq32k_regs regs; | ||
82 | int error; | ||
83 | |||
84 | error = bq32k_read(dev, ®s, 0, sizeof(regs)); | ||
85 | if (error) | ||
86 | return error; | ||
87 | |||
88 | tm->tm_sec = bcd2bin(regs.seconds & BQ32K_SECONDS_MASK); | ||
89 | tm->tm_min = bcd2bin(regs.minutes & BQ32K_SECONDS_MASK); | ||
90 | tm->tm_hour = bcd2bin(regs.cent_hours & BQ32K_HOURS_MASK); | ||
91 | tm->tm_mday = bcd2bin(regs.date); | ||
92 | tm->tm_wday = bcd2bin(regs.day) - 1; | ||
93 | tm->tm_mon = bcd2bin(regs.month) - 1; | ||
94 | tm->tm_year = bcd2bin(regs.years) + | ||
95 | ((regs.cent_hours & BQ32K_CENT) ? 100 : 0); | ||
96 | |||
97 | return rtc_valid_tm(tm); | ||
98 | } | ||
99 | |||
100 | static int bq32k_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
101 | { | ||
102 | struct bq32k_regs regs; | ||
103 | |||
104 | regs.seconds = bin2bcd(tm->tm_sec); | ||
105 | regs.minutes = bin2bcd(tm->tm_min); | ||
106 | regs.cent_hours = bin2bcd(tm->tm_hour) | BQ32K_CENT_EN; | ||
107 | regs.day = bin2bcd(tm->tm_wday + 1); | ||
108 | regs.date = bin2bcd(tm->tm_mday); | ||
109 | regs.month = bin2bcd(tm->tm_mon + 1); | ||
110 | |||
111 | if (tm->tm_year >= 100) { | ||
112 | regs.cent_hours |= BQ32K_CENT; | ||
113 | regs.years = bin2bcd(tm->tm_year - 100); | ||
114 | } else | ||
115 | regs.years = bin2bcd(tm->tm_year); | ||
116 | |||
117 | return bq32k_write(dev, ®s, 0, sizeof(regs)); | ||
118 | } | ||
119 | |||
120 | static const struct rtc_class_ops bq32k_rtc_ops = { | ||
121 | .read_time = bq32k_rtc_read_time, | ||
122 | .set_time = bq32k_rtc_set_time, | ||
123 | }; | ||
124 | |||
125 | static int bq32k_probe(struct i2c_client *client, | ||
126 | const struct i2c_device_id *id) | ||
127 | { | ||
128 | struct device *dev = &client->dev; | ||
129 | struct rtc_device *rtc; | ||
130 | uint8_t reg; | ||
131 | int error; | ||
132 | |||
133 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | ||
134 | return -ENODEV; | ||
135 | |||
136 | /* Check Oscillator Stop flag */ | ||
137 | error = bq32k_read(dev, ®, BQ32K_SECONDS, 1); | ||
138 | if (!error && (reg & BQ32K_STOP)) { | ||
139 | dev_warn(dev, "Oscillator was halted. Restarting...\n"); | ||
140 | reg &= ~BQ32K_STOP; | ||
141 | error = bq32k_write(dev, ®, BQ32K_SECONDS, 1); | ||
142 | } | ||
143 | if (error) | ||
144 | return error; | ||
145 | |||
146 | /* Check Oscillator Failure flag */ | ||
147 | error = bq32k_read(dev, ®, BQ32K_MINUTES, 1); | ||
148 | if (!error && (reg & BQ32K_OF)) { | ||
149 | dev_warn(dev, "Oscillator Failure. Check RTC battery.\n"); | ||
150 | reg &= ~BQ32K_OF; | ||
151 | error = bq32k_write(dev, ®, BQ32K_MINUTES, 1); | ||
152 | } | ||
153 | if (error) | ||
154 | return error; | ||
155 | |||
156 | rtc = rtc_device_register(bq32k_driver.driver.name, &client->dev, | ||
157 | &bq32k_rtc_ops, THIS_MODULE); | ||
158 | if (IS_ERR(rtc)) | ||
159 | return PTR_ERR(rtc); | ||
160 | |||
161 | i2c_set_clientdata(client, rtc); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static int __devexit bq32k_remove(struct i2c_client *client) | ||
167 | { | ||
168 | struct rtc_device *rtc = i2c_get_clientdata(client); | ||
169 | |||
170 | rtc_device_unregister(rtc); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static const struct i2c_device_id bq32k_id[] = { | ||
175 | { "bq32000", 0 }, | ||
176 | { } | ||
177 | }; | ||
178 | MODULE_DEVICE_TABLE(i2c, bq32k_id); | ||
179 | |||
180 | static struct i2c_driver bq32k_driver = { | ||
181 | .driver = { | ||
182 | .name = "bq32k", | ||
183 | .owner = THIS_MODULE, | ||
184 | }, | ||
185 | .probe = bq32k_probe, | ||
186 | .remove = __devexit_p(bq32k_remove), | ||
187 | .id_table = bq32k_id, | ||
188 | }; | ||
189 | |||
190 | static __init int bq32k_init(void) | ||
191 | { | ||
192 | return i2c_add_driver(&bq32k_driver); | ||
193 | } | ||
194 | module_init(bq32k_init); | ||
195 | |||
196 | static __exit void bq32k_exit(void) | ||
197 | { | ||
198 | i2c_del_driver(&bq32k_driver); | ||
199 | } | ||
200 | module_exit(bq32k_exit); | ||
201 | |||
202 | MODULE_AUTHOR("Semihalf, Piotr Ziecik <kosmo@semihalf.com>"); | ||
203 | MODULE_DESCRIPTION("TI BQ32000 I2C RTC driver"); | ||
204 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c index d00a274df8fc..128270ce355d 100644 --- a/drivers/rtc/rtc-bq4802.c +++ b/drivers/rtc/rtc-bq4802.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/platform_device.h> | 10 | #include <linux/platform_device.h> |
11 | #include <linux/rtc.h> | 11 | #include <linux/rtc.h> |
12 | #include <linux/bcd.h> | 12 | #include <linux/bcd.h> |
13 | #include <linux/slab.h> | ||
13 | 14 | ||
14 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); | 15 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); |
15 | MODULE_DESCRIPTION("TI BQ4802 RTC driver"); | 16 | MODULE_DESCRIPTION("TI BQ4802 RTC driver"); |
@@ -169,6 +170,8 @@ static int __devinit bq4802_probe(struct platform_device *pdev) | |||
169 | goto out_free; | 170 | goto out_free; |
170 | } | 171 | } |
171 | 172 | ||
173 | platform_set_drvdata(pdev, p); | ||
174 | |||
172 | p->rtc = rtc_device_register("bq4802", &pdev->dev, | 175 | p->rtc = rtc_device_register("bq4802", &pdev->dev, |
173 | &bq4802_ops, THIS_MODULE); | 176 | &bq4802_ops, THIS_MODULE); |
174 | if (IS_ERR(p->rtc)) { | 177 | if (IS_ERR(p->rtc)) { |
@@ -176,7 +179,6 @@ static int __devinit bq4802_probe(struct platform_device *pdev) | |||
176 | goto out_iounmap; | 179 | goto out_iounmap; |
177 | } | 180 | } |
178 | 181 | ||
179 | platform_set_drvdata(pdev, p); | ||
180 | err = 0; | 182 | err = 0; |
181 | out: | 183 | out: |
182 | return err; | 184 | return err; |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 23e10b6263d6..7e6ce626b7f1 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -238,31 +238,32 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
238 | rtc_control = CMOS_READ(RTC_CONTROL); | 238 | rtc_control = CMOS_READ(RTC_CONTROL); |
239 | spin_unlock_irq(&rtc_lock); | 239 | spin_unlock_irq(&rtc_lock); |
240 | 240 | ||
241 | /* REVISIT this assumes PC style usage: always BCD */ | 241 | if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
242 | 242 | if (((unsigned)t->time.tm_sec) < 0x60) | |
243 | if (((unsigned)t->time.tm_sec) < 0x60) | 243 | t->time.tm_sec = bcd2bin(t->time.tm_sec); |
244 | t->time.tm_sec = bcd2bin(t->time.tm_sec); | ||
245 | else | ||
246 | t->time.tm_sec = -1; | ||
247 | if (((unsigned)t->time.tm_min) < 0x60) | ||
248 | t->time.tm_min = bcd2bin(t->time.tm_min); | ||
249 | else | ||
250 | t->time.tm_min = -1; | ||
251 | if (((unsigned)t->time.tm_hour) < 0x24) | ||
252 | t->time.tm_hour = bcd2bin(t->time.tm_hour); | ||
253 | else | ||
254 | t->time.tm_hour = -1; | ||
255 | |||
256 | if (cmos->day_alrm) { | ||
257 | if (((unsigned)t->time.tm_mday) <= 0x31) | ||
258 | t->time.tm_mday = bcd2bin(t->time.tm_mday); | ||
259 | else | 244 | else |
260 | t->time.tm_mday = -1; | 245 | t->time.tm_sec = -1; |
261 | if (cmos->mon_alrm) { | 246 | if (((unsigned)t->time.tm_min) < 0x60) |
262 | if (((unsigned)t->time.tm_mon) <= 0x12) | 247 | t->time.tm_min = bcd2bin(t->time.tm_min); |
263 | t->time.tm_mon = bcd2bin(t->time.tm_mon) - 1; | 248 | else |
249 | t->time.tm_min = -1; | ||
250 | if (((unsigned)t->time.tm_hour) < 0x24) | ||
251 | t->time.tm_hour = bcd2bin(t->time.tm_hour); | ||
252 | else | ||
253 | t->time.tm_hour = -1; | ||
254 | |||
255 | if (cmos->day_alrm) { | ||
256 | if (((unsigned)t->time.tm_mday) <= 0x31) | ||
257 | t->time.tm_mday = bcd2bin(t->time.tm_mday); | ||
264 | else | 258 | else |
265 | t->time.tm_mon = -1; | 259 | t->time.tm_mday = -1; |
260 | |||
261 | if (cmos->mon_alrm) { | ||
262 | if (((unsigned)t->time.tm_mon) <= 0x12) | ||
263 | t->time.tm_mon = bcd2bin(t->time.tm_mon)-1; | ||
264 | else | ||
265 | t->time.tm_mon = -1; | ||
266 | } | ||
266 | } | 267 | } |
267 | } | 268 | } |
268 | t->time.tm_year = -1; | 269 | t->time.tm_year = -1; |
@@ -322,29 +323,26 @@ static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask) | |||
322 | static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | 323 | static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) |
323 | { | 324 | { |
324 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 325 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
325 | unsigned char mon, mday, hrs, min, sec; | 326 | unsigned char mon, mday, hrs, min, sec, rtc_control; |
326 | 327 | ||
327 | if (!is_valid_irq(cmos->irq)) | 328 | if (!is_valid_irq(cmos->irq)) |
328 | return -EIO; | 329 | return -EIO; |
329 | 330 | ||
330 | /* REVISIT this assumes PC style usage: always BCD */ | ||
331 | |||
332 | /* Writing 0xff means "don't care" or "match all". */ | ||
333 | |||
334 | mon = t->time.tm_mon + 1; | 331 | mon = t->time.tm_mon + 1; |
335 | mon = (mon <= 12) ? bin2bcd(mon) : 0xff; | ||
336 | |||
337 | mday = t->time.tm_mday; | 332 | mday = t->time.tm_mday; |
338 | mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff; | ||
339 | |||
340 | hrs = t->time.tm_hour; | 333 | hrs = t->time.tm_hour; |
341 | hrs = (hrs < 24) ? bin2bcd(hrs) : 0xff; | ||
342 | |||
343 | min = t->time.tm_min; | 334 | min = t->time.tm_min; |
344 | min = (min < 60) ? bin2bcd(min) : 0xff; | ||
345 | |||
346 | sec = t->time.tm_sec; | 335 | sec = t->time.tm_sec; |
347 | sec = (sec < 60) ? bin2bcd(sec) : 0xff; | 336 | |
337 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
338 | if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
339 | /* Writing 0xff means "don't care" or "match all". */ | ||
340 | mon = (mon <= 12) ? bin2bcd(mon) : 0xff; | ||
341 | mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff; | ||
342 | hrs = (hrs < 24) ? bin2bcd(hrs) : 0xff; | ||
343 | min = (min < 60) ? bin2bcd(min) : 0xff; | ||
344 | sec = (sec < 60) ? bin2bcd(sec) : 0xff; | ||
345 | } | ||
348 | 346 | ||
349 | spin_lock_irq(&rtc_lock); | 347 | spin_lock_irq(&rtc_lock); |
350 | 348 | ||
@@ -420,49 +418,43 @@ static int cmos_irq_set_state(struct device *dev, int enabled) | |||
420 | return 0; | 418 | return 0; |
421 | } | 419 | } |
422 | 420 | ||
423 | #if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE) | 421 | static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) |
424 | |||
425 | static int | ||
426 | cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
427 | { | 422 | { |
428 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 423 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
429 | unsigned long flags; | 424 | unsigned long flags; |
430 | 425 | ||
431 | switch (cmd) { | 426 | if (!is_valid_irq(cmos->irq)) |
432 | case RTC_AIE_OFF: | 427 | return -EINVAL; |
433 | case RTC_AIE_ON: | ||
434 | case RTC_UIE_OFF: | ||
435 | case RTC_UIE_ON: | ||
436 | if (!is_valid_irq(cmos->irq)) | ||
437 | return -EINVAL; | ||
438 | break; | ||
439 | /* PIE ON/OFF is handled by cmos_irq_set_state() */ | ||
440 | default: | ||
441 | return -ENOIOCTLCMD; | ||
442 | } | ||
443 | 428 | ||
444 | spin_lock_irqsave(&rtc_lock, flags); | 429 | spin_lock_irqsave(&rtc_lock, flags); |
445 | switch (cmd) { | 430 | |
446 | case RTC_AIE_OFF: /* alarm off */ | 431 | if (enabled) |
447 | cmos_irq_disable(cmos, RTC_AIE); | ||
448 | break; | ||
449 | case RTC_AIE_ON: /* alarm on */ | ||
450 | cmos_irq_enable(cmos, RTC_AIE); | 432 | cmos_irq_enable(cmos, RTC_AIE); |
451 | break; | 433 | else |
452 | case RTC_UIE_OFF: /* update off */ | 434 | cmos_irq_disable(cmos, RTC_AIE); |
453 | cmos_irq_disable(cmos, RTC_UIE); | 435 | |
454 | break; | ||
455 | case RTC_UIE_ON: /* update on */ | ||
456 | cmos_irq_enable(cmos, RTC_UIE); | ||
457 | break; | ||
458 | } | ||
459 | spin_unlock_irqrestore(&rtc_lock, flags); | 436 | spin_unlock_irqrestore(&rtc_lock, flags); |
460 | return 0; | 437 | return 0; |
461 | } | 438 | } |
462 | 439 | ||
463 | #else | 440 | static int cmos_update_irq_enable(struct device *dev, unsigned int enabled) |
464 | #define cmos_rtc_ioctl NULL | 441 | { |
465 | #endif | 442 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
443 | unsigned long flags; | ||
444 | |||
445 | if (!is_valid_irq(cmos->irq)) | ||
446 | return -EINVAL; | ||
447 | |||
448 | spin_lock_irqsave(&rtc_lock, flags); | ||
449 | |||
450 | if (enabled) | ||
451 | cmos_irq_enable(cmos, RTC_UIE); | ||
452 | else | ||
453 | cmos_irq_disable(cmos, RTC_UIE); | ||
454 | |||
455 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
456 | return 0; | ||
457 | } | ||
466 | 458 | ||
467 | #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) | 459 | #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) |
468 | 460 | ||
@@ -484,7 +476,7 @@ static int cmos_procfs(struct device *dev, struct seq_file *seq) | |||
484 | "update_IRQ\t: %s\n" | 476 | "update_IRQ\t: %s\n" |
485 | "HPET_emulated\t: %s\n" | 477 | "HPET_emulated\t: %s\n" |
486 | // "square_wave\t: %s\n" | 478 | // "square_wave\t: %s\n" |
487 | // "BCD\t\t: %s\n" | 479 | "BCD\t\t: %s\n" |
488 | "DST_enable\t: %s\n" | 480 | "DST_enable\t: %s\n" |
489 | "periodic_freq\t: %d\n" | 481 | "periodic_freq\t: %d\n" |
490 | "batt_status\t: %s\n", | 482 | "batt_status\t: %s\n", |
@@ -492,7 +484,7 @@ static int cmos_procfs(struct device *dev, struct seq_file *seq) | |||
492 | (rtc_control & RTC_UIE) ? "yes" : "no", | 484 | (rtc_control & RTC_UIE) ? "yes" : "no", |
493 | is_hpet_enabled() ? "yes" : "no", | 485 | is_hpet_enabled() ? "yes" : "no", |
494 | // (rtc_control & RTC_SQWE) ? "yes" : "no", | 486 | // (rtc_control & RTC_SQWE) ? "yes" : "no", |
495 | // (rtc_control & RTC_DM_BINARY) ? "no" : "yes", | 487 | (rtc_control & RTC_DM_BINARY) ? "no" : "yes", |
496 | (rtc_control & RTC_DST_EN) ? "yes" : "no", | 488 | (rtc_control & RTC_DST_EN) ? "yes" : "no", |
497 | cmos->rtc->irq_freq, | 489 | cmos->rtc->irq_freq, |
498 | (valid & RTC_VRT) ? "okay" : "dead"); | 490 | (valid & RTC_VRT) ? "okay" : "dead"); |
@@ -503,14 +495,15 @@ static int cmos_procfs(struct device *dev, struct seq_file *seq) | |||
503 | #endif | 495 | #endif |
504 | 496 | ||
505 | static const struct rtc_class_ops cmos_rtc_ops = { | 497 | static const struct rtc_class_ops cmos_rtc_ops = { |
506 | .ioctl = cmos_rtc_ioctl, | 498 | .read_time = cmos_read_time, |
507 | .read_time = cmos_read_time, | 499 | .set_time = cmos_set_time, |
508 | .set_time = cmos_set_time, | 500 | .read_alarm = cmos_read_alarm, |
509 | .read_alarm = cmos_read_alarm, | 501 | .set_alarm = cmos_set_alarm, |
510 | .set_alarm = cmos_set_alarm, | 502 | .proc = cmos_procfs, |
511 | .proc = cmos_procfs, | 503 | .irq_set_freq = cmos_irq_set_freq, |
512 | .irq_set_freq = cmos_irq_set_freq, | 504 | .irq_set_state = cmos_irq_set_state, |
513 | .irq_set_state = cmos_irq_set_state, | 505 | .alarm_irq_enable = cmos_alarm_irq_enable, |
506 | .update_irq_enable = cmos_update_irq_enable, | ||
514 | }; | 507 | }; |
515 | 508 | ||
516 | /*----------------------------------------------------------------*/ | 509 | /*----------------------------------------------------------------*/ |
@@ -524,7 +517,8 @@ static const struct rtc_class_ops cmos_rtc_ops = { | |||
524 | #define NVRAM_OFFSET (RTC_REG_D + 1) | 517 | #define NVRAM_OFFSET (RTC_REG_D + 1) |
525 | 518 | ||
526 | static ssize_t | 519 | static ssize_t |
527 | cmos_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | 520 | cmos_nvram_read(struct file *filp, struct kobject *kobj, |
521 | struct bin_attribute *attr, | ||
528 | char *buf, loff_t off, size_t count) | 522 | char *buf, loff_t off, size_t count) |
529 | { | 523 | { |
530 | int retval; | 524 | int retval; |
@@ -552,7 +546,8 @@ cmos_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | |||
552 | } | 546 | } |
553 | 547 | ||
554 | static ssize_t | 548 | static ssize_t |
555 | cmos_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | 549 | cmos_nvram_write(struct file *filp, struct kobject *kobj, |
550 | struct bin_attribute *attr, | ||
556 | char *buf, loff_t off, size_t count) | 551 | char *buf, loff_t off, size_t count) |
557 | { | 552 | { |
558 | struct cmos_rtc *cmos; | 553 | struct cmos_rtc *cmos; |
@@ -691,7 +686,9 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
691 | */ | 686 | */ |
692 | #if defined(CONFIG_ATARI) | 687 | #if defined(CONFIG_ATARI) |
693 | address_space = 64; | 688 | address_space = 64; |
694 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__sparc__) | 689 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) \ |
690 | || defined(__sparc__) || defined(__mips__) \ | ||
691 | || defined(__powerpc__) | ||
695 | address_space = 128; | 692 | address_space = 128; |
696 | #else | 693 | #else |
697 | #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. |
@@ -723,6 +720,9 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
723 | } | 720 | } |
724 | } | 721 | } |
725 | 722 | ||
723 | cmos_rtc.dev = dev; | ||
724 | dev_set_drvdata(dev, &cmos_rtc); | ||
725 | |||
726 | cmos_rtc.rtc = rtc_device_register(driver_name, dev, | 726 | cmos_rtc.rtc = rtc_device_register(driver_name, dev, |
727 | &cmos_rtc_ops, THIS_MODULE); | 727 | &cmos_rtc_ops, THIS_MODULE); |
728 | if (IS_ERR(cmos_rtc.rtc)) { | 728 | if (IS_ERR(cmos_rtc.rtc)) { |
@@ -730,8 +730,6 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
730 | goto cleanup0; | 730 | goto cleanup0; |
731 | } | 731 | } |
732 | 732 | ||
733 | cmos_rtc.dev = dev; | ||
734 | dev_set_drvdata(dev, &cmos_rtc); | ||
735 | rename_region(ports, dev_name(&cmos_rtc.rtc->dev)); | 733 | rename_region(ports, dev_name(&cmos_rtc.rtc->dev)); |
736 | 734 | ||
737 | spin_lock_irq(&rtc_lock); | 735 | spin_lock_irq(&rtc_lock); |
@@ -753,12 +751,11 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
753 | 751 | ||
754 | spin_unlock_irq(&rtc_lock); | 752 | spin_unlock_irq(&rtc_lock); |
755 | 753 | ||
756 | /* FIXME teach the alarm code how to handle binary mode; | 754 | /* FIXME: |
757 | * <asm-generic/rtc.h> doesn't know 12-hour mode either. | 755 | * <asm-generic/rtc.h> doesn't know 12-hour mode either. |
758 | */ | 756 | */ |
759 | if (is_valid_irq(rtc_irq) && | 757 | if (is_valid_irq(rtc_irq) && !(rtc_control & RTC_24H)) { |
760 | (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY)))) { | 758 | dev_warn(dev, "only 24-hr supported\n"); |
761 | dev_dbg(dev, "only 24-hr BCD mode supported\n"); | ||
762 | retval = -ENXIO; | 759 | retval = -ENXIO; |
763 | goto cleanup1; | 760 | goto cleanup1; |
764 | } | 761 | } |
@@ -871,8 +868,9 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg) | |||
871 | mask = RTC_IRQMASK; | 868 | mask = RTC_IRQMASK; |
872 | tmp &= ~mask; | 869 | tmp &= ~mask; |
873 | CMOS_WRITE(tmp, RTC_CONTROL); | 870 | CMOS_WRITE(tmp, RTC_CONTROL); |
874 | hpet_mask_rtc_irq_bit(mask); | ||
875 | 871 | ||
872 | /* shut down hpet emulation - we don't need it for alarm */ | ||
873 | hpet_mask_rtc_irq_bit(RTC_PIE|RTC_AIE|RTC_UIE); | ||
876 | cmos_checkintr(cmos, tmp); | 874 | cmos_checkintr(cmos, tmp); |
877 | } | 875 | } |
878 | spin_unlock_irq(&rtc_lock); | 876 | spin_unlock_irq(&rtc_lock); |
@@ -973,7 +971,6 @@ static inline int cmos_poweroff(struct device *dev) | |||
973 | 971 | ||
974 | #include <linux/acpi.h> | 972 | #include <linux/acpi.h> |
975 | 973 | ||
976 | #ifdef CONFIG_PM | ||
977 | static u32 rtc_handler(void *context) | 974 | static u32 rtc_handler(void *context) |
978 | { | 975 | { |
979 | acpi_clear_event(ACPI_EVENT_RTC); | 976 | acpi_clear_event(ACPI_EVENT_RTC); |
@@ -1002,11 +999,6 @@ static void rtc_wake_off(struct device *dev) | |||
1002 | { | 999 | { |
1003 | acpi_disable_event(ACPI_EVENT_RTC, 0); | 1000 | acpi_disable_event(ACPI_EVENT_RTC, 0); |
1004 | } | 1001 | } |
1005 | #else | ||
1006 | #define rtc_wake_setup() do{}while(0) | ||
1007 | #define rtc_wake_on NULL | ||
1008 | #define rtc_wake_off NULL | ||
1009 | #endif | ||
1010 | 1002 | ||
1011 | /* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find | 1003 | /* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find |
1012 | * its device node and pass extra config data. This helps its driver use | 1004 | * its device node and pass extra config data. This helps its driver use |
@@ -1099,9 +1091,9 @@ static int cmos_pnp_resume(struct pnp_dev *pnp) | |||
1099 | #define cmos_pnp_resume NULL | 1091 | #define cmos_pnp_resume NULL |
1100 | #endif | 1092 | #endif |
1101 | 1093 | ||
1102 | static void cmos_pnp_shutdown(struct device *pdev) | 1094 | static void cmos_pnp_shutdown(struct pnp_dev *pnp) |
1103 | { | 1095 | { |
1104 | if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(pdev)) | 1096 | if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pnp->dev)) |
1105 | return; | 1097 | return; |
1106 | 1098 | ||
1107 | cmos_do_shutdown(); | 1099 | cmos_do_shutdown(); |
@@ -1120,15 +1112,12 @@ static struct pnp_driver cmos_pnp_driver = { | |||
1120 | .id_table = rtc_ids, | 1112 | .id_table = rtc_ids, |
1121 | .probe = cmos_pnp_probe, | 1113 | .probe = cmos_pnp_probe, |
1122 | .remove = __exit_p(cmos_pnp_remove), | 1114 | .remove = __exit_p(cmos_pnp_remove), |
1115 | .shutdown = cmos_pnp_shutdown, | ||
1123 | 1116 | ||
1124 | /* flag ensures resume() gets called, and stops syslog spam */ | 1117 | /* flag ensures resume() gets called, and stops syslog spam */ |
1125 | .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, | 1118 | .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, |
1126 | .suspend = cmos_pnp_suspend, | 1119 | .suspend = cmos_pnp_suspend, |
1127 | .resume = cmos_pnp_resume, | 1120 | .resume = cmos_pnp_resume, |
1128 | .driver = { | ||
1129 | .name = (char *)driver_name, | ||
1130 | .shutdown = cmos_pnp_shutdown, | ||
1131 | } | ||
1132 | }; | 1121 | }; |
1133 | 1122 | ||
1134 | #endif /* CONFIG_PNP */ | 1123 | #endif /* CONFIG_PNP */ |
@@ -1174,23 +1163,34 @@ static struct platform_driver cmos_platform_driver = { | |||
1174 | } | 1163 | } |
1175 | }; | 1164 | }; |
1176 | 1165 | ||
1166 | #ifdef CONFIG_PNP | ||
1167 | static bool pnp_driver_registered; | ||
1168 | #endif | ||
1169 | static bool platform_driver_registered; | ||
1170 | |||
1177 | static int __init cmos_init(void) | 1171 | static int __init cmos_init(void) |
1178 | { | 1172 | { |
1179 | int retval = 0; | 1173 | int retval = 0; |
1180 | 1174 | ||
1181 | #ifdef CONFIG_PNP | 1175 | #ifdef CONFIG_PNP |
1182 | pnp_register_driver(&cmos_pnp_driver); | 1176 | retval = pnp_register_driver(&cmos_pnp_driver); |
1177 | if (retval == 0) | ||
1178 | pnp_driver_registered = true; | ||
1183 | #endif | 1179 | #endif |
1184 | 1180 | ||
1185 | if (!cmos_rtc.dev) | 1181 | if (!cmos_rtc.dev) { |
1186 | retval = platform_driver_probe(&cmos_platform_driver, | 1182 | retval = platform_driver_probe(&cmos_platform_driver, |
1187 | cmos_platform_probe); | 1183 | cmos_platform_probe); |
1184 | if (retval == 0) | ||
1185 | platform_driver_registered = true; | ||
1186 | } | ||
1188 | 1187 | ||
1189 | if (retval == 0) | 1188 | if (retval == 0) |
1190 | return 0; | 1189 | return 0; |
1191 | 1190 | ||
1192 | #ifdef CONFIG_PNP | 1191 | #ifdef CONFIG_PNP |
1193 | pnp_unregister_driver(&cmos_pnp_driver); | 1192 | if (pnp_driver_registered) |
1193 | pnp_unregister_driver(&cmos_pnp_driver); | ||
1194 | #endif | 1194 | #endif |
1195 | return retval; | 1195 | return retval; |
1196 | } | 1196 | } |
@@ -1199,9 +1199,11 @@ module_init(cmos_init); | |||
1199 | static void __exit cmos_exit(void) | 1199 | static void __exit cmos_exit(void) |
1200 | { | 1200 | { |
1201 | #ifdef CONFIG_PNP | 1201 | #ifdef CONFIG_PNP |
1202 | pnp_unregister_driver(&cmos_pnp_driver); | 1202 | if (pnp_driver_registered) |
1203 | pnp_unregister_driver(&cmos_pnp_driver); | ||
1203 | #endif | 1204 | #endif |
1204 | platform_driver_unregister(&cmos_platform_driver); | 1205 | if (platform_driver_registered) |
1206 | platform_driver_unregister(&cmos_platform_driver); | ||
1205 | } | 1207 | } |
1206 | module_exit(cmos_exit); | 1208 | module_exit(cmos_exit); |
1207 | 1209 | ||
diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c new file mode 100644 index 000000000000..316f484999b5 --- /dev/null +++ b/drivers/rtc/rtc-coh901331.c | |||
@@ -0,0 +1,324 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2009 ST-Ericsson AB | ||
3 | * License terms: GNU General Public License (GPL) version 2 | ||
4 | * Real Time Clock interface for ST-Ericsson AB COH 901 331 RTC. | ||
5 | * Author: Linus Walleij <linus.walleij@stericsson.com> | ||
6 | * Based on rtc-pl031.c by Deepak Saxena <dsaxena@plexity.net> | ||
7 | * Copyright 2006 (c) MontaVista Software, Inc. | ||
8 | */ | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/rtc.h> | ||
12 | #include <linux/clk.h> | ||
13 | #include <linux/interrupt.h> | ||
14 | #include <linux/pm.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/slab.h> | ||
18 | |||
19 | /* | ||
20 | * Registers in the COH 901 331 | ||
21 | */ | ||
22 | /* Alarm value 32bit (R/W) */ | ||
23 | #define COH901331_ALARM 0x00U | ||
24 | /* Used to set current time 32bit (R/W) */ | ||
25 | #define COH901331_SET_TIME 0x04U | ||
26 | /* Indication if current time is valid 32bit (R/-) */ | ||
27 | #define COH901331_VALID 0x08U | ||
28 | /* Read the current time 32bit (R/-) */ | ||
29 | #define COH901331_CUR_TIME 0x0cU | ||
30 | /* Event register for the "alarm" interrupt */ | ||
31 | #define COH901331_IRQ_EVENT 0x10U | ||
32 | /* Mask register for the "alarm" interrupt */ | ||
33 | #define COH901331_IRQ_MASK 0x14U | ||
34 | /* Force register for the "alarm" interrupt */ | ||
35 | #define COH901331_IRQ_FORCE 0x18U | ||
36 | |||
37 | /* | ||
38 | * Reference to RTC block clock | ||
39 | * Notice that the frequent clk_enable()/clk_disable() on this | ||
40 | * clock is mainly to be able to turn on/off other clocks in the | ||
41 | * hierarchy as needed, the RTC clock is always on anyway. | ||
42 | */ | ||
43 | struct coh901331_port { | ||
44 | struct rtc_device *rtc; | ||
45 | struct clk *clk; | ||
46 | u32 phybase; | ||
47 | u32 physize; | ||
48 | void __iomem *virtbase; | ||
49 | int irq; | ||
50 | #ifdef CONFIG_PM | ||
51 | u32 irqmaskstore; | ||
52 | #endif | ||
53 | }; | ||
54 | |||
55 | static irqreturn_t coh901331_interrupt(int irq, void *data) | ||
56 | { | ||
57 | struct coh901331_port *rtap = data; | ||
58 | |||
59 | clk_enable(rtap->clk); | ||
60 | /* Ack IRQ */ | ||
61 | writel(1, rtap->virtbase + COH901331_IRQ_EVENT); | ||
62 | /* | ||
63 | * Disable the interrupt. This is necessary because | ||
64 | * the RTC lives on a lower-clocked line and will | ||
65 | * not release the IRQ line until after a few (slower) | ||
66 | * clock cycles. The interrupt will be re-enabled when | ||
67 | * a new alarm is set anyway. | ||
68 | */ | ||
69 | writel(0, rtap->virtbase + COH901331_IRQ_MASK); | ||
70 | clk_disable(rtap->clk); | ||
71 | |||
72 | /* Set alarm flag */ | ||
73 | rtc_update_irq(rtap->rtc, 1, RTC_AF); | ||
74 | |||
75 | return IRQ_HANDLED; | ||
76 | } | ||
77 | |||
78 | static int coh901331_read_time(struct device *dev, struct rtc_time *tm) | ||
79 | { | ||
80 | struct coh901331_port *rtap = dev_get_drvdata(dev); | ||
81 | |||
82 | clk_enable(rtap->clk); | ||
83 | /* Check if the time is valid */ | ||
84 | if (readl(rtap->virtbase + COH901331_VALID)) { | ||
85 | rtc_time_to_tm(readl(rtap->virtbase + COH901331_CUR_TIME), tm); | ||
86 | clk_disable(rtap->clk); | ||
87 | return rtc_valid_tm(tm); | ||
88 | } | ||
89 | clk_disable(rtap->clk); | ||
90 | return -EINVAL; | ||
91 | } | ||
92 | |||
93 | static int coh901331_set_mmss(struct device *dev, unsigned long secs) | ||
94 | { | ||
95 | struct coh901331_port *rtap = dev_get_drvdata(dev); | ||
96 | |||
97 | clk_enable(rtap->clk); | ||
98 | writel(secs, rtap->virtbase + COH901331_SET_TIME); | ||
99 | clk_disable(rtap->clk); | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static int coh901331_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
105 | { | ||
106 | struct coh901331_port *rtap = dev_get_drvdata(dev); | ||
107 | |||
108 | clk_enable(rtap->clk); | ||
109 | rtc_time_to_tm(readl(rtap->virtbase + COH901331_ALARM), &alarm->time); | ||
110 | alarm->pending = readl(rtap->virtbase + COH901331_IRQ_EVENT) & 1U; | ||
111 | alarm->enabled = readl(rtap->virtbase + COH901331_IRQ_MASK) & 1U; | ||
112 | clk_disable(rtap->clk); | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static int coh901331_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
118 | { | ||
119 | struct coh901331_port *rtap = dev_get_drvdata(dev); | ||
120 | unsigned long time; | ||
121 | |||
122 | rtc_tm_to_time(&alarm->time, &time); | ||
123 | clk_enable(rtap->clk); | ||
124 | writel(time, rtap->virtbase + COH901331_ALARM); | ||
125 | writel(alarm->enabled, rtap->virtbase + COH901331_IRQ_MASK); | ||
126 | clk_disable(rtap->clk); | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static int coh901331_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
132 | { | ||
133 | struct coh901331_port *rtap = dev_get_drvdata(dev); | ||
134 | |||
135 | clk_enable(rtap->clk); | ||
136 | if (enabled) | ||
137 | writel(1, rtap->virtbase + COH901331_IRQ_MASK); | ||
138 | else | ||
139 | writel(0, rtap->virtbase + COH901331_IRQ_MASK); | ||
140 | clk_disable(rtap->clk); | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static struct rtc_class_ops coh901331_ops = { | ||
146 | .read_time = coh901331_read_time, | ||
147 | .set_mmss = coh901331_set_mmss, | ||
148 | .read_alarm = coh901331_read_alarm, | ||
149 | .set_alarm = coh901331_set_alarm, | ||
150 | .alarm_irq_enable = coh901331_alarm_irq_enable, | ||
151 | }; | ||
152 | |||
153 | static int __exit coh901331_remove(struct platform_device *pdev) | ||
154 | { | ||
155 | struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev); | ||
156 | |||
157 | if (rtap) { | ||
158 | free_irq(rtap->irq, rtap); | ||
159 | rtc_device_unregister(rtap->rtc); | ||
160 | clk_put(rtap->clk); | ||
161 | iounmap(rtap->virtbase); | ||
162 | release_mem_region(rtap->phybase, rtap->physize); | ||
163 | platform_set_drvdata(pdev, NULL); | ||
164 | kfree(rtap); | ||
165 | } | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | |||
171 | static int __init coh901331_probe(struct platform_device *pdev) | ||
172 | { | ||
173 | int ret; | ||
174 | struct coh901331_port *rtap; | ||
175 | struct resource *res; | ||
176 | |||
177 | rtap = kzalloc(sizeof(struct coh901331_port), GFP_KERNEL); | ||
178 | if (!rtap) | ||
179 | return -ENOMEM; | ||
180 | |||
181 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
182 | if (!res) { | ||
183 | ret = -ENOENT; | ||
184 | goto out_no_resource; | ||
185 | } | ||
186 | rtap->phybase = res->start; | ||
187 | rtap->physize = resource_size(res); | ||
188 | |||
189 | if (request_mem_region(rtap->phybase, rtap->physize, | ||
190 | "rtc-coh901331") == NULL) { | ||
191 | ret = -EBUSY; | ||
192 | goto out_no_memregion; | ||
193 | } | ||
194 | |||
195 | rtap->virtbase = ioremap(rtap->phybase, rtap->physize); | ||
196 | if (!rtap->virtbase) { | ||
197 | ret = -ENOMEM; | ||
198 | goto out_no_remap; | ||
199 | } | ||
200 | |||
201 | rtap->irq = platform_get_irq(pdev, 0); | ||
202 | if (request_irq(rtap->irq, coh901331_interrupt, IRQF_DISABLED, | ||
203 | "RTC COH 901 331 Alarm", rtap)) { | ||
204 | ret = -EIO; | ||
205 | goto out_no_irq; | ||
206 | } | ||
207 | |||
208 | rtap->clk = clk_get(&pdev->dev, NULL); | ||
209 | if (IS_ERR(rtap->clk)) { | ||
210 | ret = PTR_ERR(rtap->clk); | ||
211 | dev_err(&pdev->dev, "could not get clock\n"); | ||
212 | goto out_no_clk; | ||
213 | } | ||
214 | |||
215 | /* We enable/disable the clock only to assure it works */ | ||
216 | ret = clk_enable(rtap->clk); | ||
217 | if (ret) { | ||
218 | dev_err(&pdev->dev, "could not enable clock\n"); | ||
219 | goto out_no_clk_enable; | ||
220 | } | ||
221 | clk_disable(rtap->clk); | ||
222 | |||
223 | rtap->rtc = rtc_device_register("coh901331", &pdev->dev, &coh901331_ops, | ||
224 | THIS_MODULE); | ||
225 | if (IS_ERR(rtap->rtc)) { | ||
226 | ret = PTR_ERR(rtap->rtc); | ||
227 | goto out_no_rtc; | ||
228 | } | ||
229 | |||
230 | platform_set_drvdata(pdev, rtap); | ||
231 | |||
232 | return 0; | ||
233 | |||
234 | out_no_rtc: | ||
235 | out_no_clk_enable: | ||
236 | clk_put(rtap->clk); | ||
237 | out_no_clk: | ||
238 | free_irq(rtap->irq, rtap); | ||
239 | out_no_irq: | ||
240 | iounmap(rtap->virtbase); | ||
241 | out_no_remap: | ||
242 | platform_set_drvdata(pdev, NULL); | ||
243 | out_no_memregion: | ||
244 | release_mem_region(rtap->phybase, SZ_4K); | ||
245 | out_no_resource: | ||
246 | kfree(rtap); | ||
247 | return ret; | ||
248 | } | ||
249 | |||
250 | #ifdef CONFIG_PM | ||
251 | static int coh901331_suspend(struct platform_device *pdev, pm_message_t state) | ||
252 | { | ||
253 | struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev); | ||
254 | |||
255 | /* | ||
256 | * If this RTC alarm will be used for waking the system up, | ||
257 | * don't disable it of course. Else we just disable the alarm | ||
258 | * and await suspension. | ||
259 | */ | ||
260 | if (device_may_wakeup(&pdev->dev)) { | ||
261 | enable_irq_wake(rtap->irq); | ||
262 | } else { | ||
263 | clk_enable(rtap->clk); | ||
264 | rtap->irqmaskstore = readl(rtap->virtbase + COH901331_IRQ_MASK); | ||
265 | writel(0, rtap->virtbase + COH901331_IRQ_MASK); | ||
266 | clk_disable(rtap->clk); | ||
267 | } | ||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static int coh901331_resume(struct platform_device *pdev) | ||
272 | { | ||
273 | struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev); | ||
274 | |||
275 | if (device_may_wakeup(&pdev->dev)) { | ||
276 | disable_irq_wake(rtap->irq); | ||
277 | } else { | ||
278 | clk_enable(rtap->clk); | ||
279 | writel(rtap->irqmaskstore, rtap->virtbase + COH901331_IRQ_MASK); | ||
280 | clk_disable(rtap->clk); | ||
281 | } | ||
282 | return 0; | ||
283 | } | ||
284 | #else | ||
285 | #define coh901331_suspend NULL | ||
286 | #define coh901331_resume NULL | ||
287 | #endif | ||
288 | |||
289 | static void coh901331_shutdown(struct platform_device *pdev) | ||
290 | { | ||
291 | struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev); | ||
292 | |||
293 | clk_enable(rtap->clk); | ||
294 | writel(0, rtap->virtbase + COH901331_IRQ_MASK); | ||
295 | clk_disable(rtap->clk); | ||
296 | } | ||
297 | |||
298 | static struct platform_driver coh901331_driver = { | ||
299 | .driver = { | ||
300 | .name = "rtc-coh901331", | ||
301 | .owner = THIS_MODULE, | ||
302 | }, | ||
303 | .remove = __exit_p(coh901331_remove), | ||
304 | .suspend = coh901331_suspend, | ||
305 | .resume = coh901331_resume, | ||
306 | .shutdown = coh901331_shutdown, | ||
307 | }; | ||
308 | |||
309 | static int __init coh901331_init(void) | ||
310 | { | ||
311 | return platform_driver_probe(&coh901331_driver, coh901331_probe); | ||
312 | } | ||
313 | |||
314 | static void __exit coh901331_exit(void) | ||
315 | { | ||
316 | platform_driver_unregister(&coh901331_driver); | ||
317 | } | ||
318 | |||
319 | module_init(coh901331_init); | ||
320 | module_exit(coh901331_exit); | ||
321 | |||
322 | MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>"); | ||
323 | MODULE_DESCRIPTION("ST-Ericsson AB COH 901 331 RTC Driver"); | ||
324 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c new file mode 100644 index 000000000000..34647fc1ee98 --- /dev/null +++ b/drivers/rtc/rtc-davinci.c | |||
@@ -0,0 +1,674 @@ | |||
1 | /* | ||
2 | * DaVinci Power Management and Real Time Clock Driver for TI platforms | ||
3 | * | ||
4 | * Copyright (C) 2009 Texas Instruments, Inc | ||
5 | * | ||
6 | * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com> | ||
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 as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/ioport.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/spinlock.h> | ||
28 | #include <linux/rtc.h> | ||
29 | #include <linux/bcd.h> | ||
30 | #include <linux/platform_device.h> | ||
31 | #include <linux/io.h> | ||
32 | #include <linux/slab.h> | ||
33 | |||
34 | /* | ||
35 | * The DaVinci RTC is a simple RTC with the following | ||
36 | * Sec: 0 - 59 : BCD count | ||
37 | * Min: 0 - 59 : BCD count | ||
38 | * Hour: 0 - 23 : BCD count | ||
39 | * Day: 0 - 0x7FFF(32767) : Binary count ( Over 89 years ) | ||
40 | */ | ||
41 | |||
42 | /* PRTC interface registers */ | ||
43 | #define DAVINCI_PRTCIF_PID 0x00 | ||
44 | #define PRTCIF_CTLR 0x04 | ||
45 | #define PRTCIF_LDATA 0x08 | ||
46 | #define PRTCIF_UDATA 0x0C | ||
47 | #define PRTCIF_INTEN 0x10 | ||
48 | #define PRTCIF_INTFLG 0x14 | ||
49 | |||
50 | /* PRTCIF_CTLR bit fields */ | ||
51 | #define PRTCIF_CTLR_BUSY BIT(31) | ||
52 | #define PRTCIF_CTLR_SIZE BIT(25) | ||
53 | #define PRTCIF_CTLR_DIR BIT(24) | ||
54 | #define PRTCIF_CTLR_BENU_MSB BIT(23) | ||
55 | #define PRTCIF_CTLR_BENU_3RD_BYTE BIT(22) | ||
56 | #define PRTCIF_CTLR_BENU_2ND_BYTE BIT(21) | ||
57 | #define PRTCIF_CTLR_BENU_LSB BIT(20) | ||
58 | #define PRTCIF_CTLR_BENU_MASK (0x00F00000) | ||
59 | #define PRTCIF_CTLR_BENL_MSB BIT(19) | ||
60 | #define PRTCIF_CTLR_BENL_3RD_BYTE BIT(18) | ||
61 | #define PRTCIF_CTLR_BENL_2ND_BYTE BIT(17) | ||
62 | #define PRTCIF_CTLR_BENL_LSB BIT(16) | ||
63 | #define PRTCIF_CTLR_BENL_MASK (0x000F0000) | ||
64 | |||
65 | /* PRTCIF_INTEN bit fields */ | ||
66 | #define PRTCIF_INTEN_RTCSS BIT(1) | ||
67 | #define PRTCIF_INTEN_RTCIF BIT(0) | ||
68 | #define PRTCIF_INTEN_MASK (PRTCIF_INTEN_RTCSS \ | ||
69 | | PRTCIF_INTEN_RTCIF) | ||
70 | |||
71 | /* PRTCIF_INTFLG bit fields */ | ||
72 | #define PRTCIF_INTFLG_RTCSS BIT(1) | ||
73 | #define PRTCIF_INTFLG_RTCIF BIT(0) | ||
74 | #define PRTCIF_INTFLG_MASK (PRTCIF_INTFLG_RTCSS \ | ||
75 | | PRTCIF_INTFLG_RTCIF) | ||
76 | |||
77 | /* PRTC subsystem registers */ | ||
78 | #define PRTCSS_RTC_INTC_EXTENA1 (0x0C) | ||
79 | #define PRTCSS_RTC_CTRL (0x10) | ||
80 | #define PRTCSS_RTC_WDT (0x11) | ||
81 | #define PRTCSS_RTC_TMR0 (0x12) | ||
82 | #define PRTCSS_RTC_TMR1 (0x13) | ||
83 | #define PRTCSS_RTC_CCTRL (0x14) | ||
84 | #define PRTCSS_RTC_SEC (0x15) | ||
85 | #define PRTCSS_RTC_MIN (0x16) | ||
86 | #define PRTCSS_RTC_HOUR (0x17) | ||
87 | #define PRTCSS_RTC_DAY0 (0x18) | ||
88 | #define PRTCSS_RTC_DAY1 (0x19) | ||
89 | #define PRTCSS_RTC_AMIN (0x1A) | ||
90 | #define PRTCSS_RTC_AHOUR (0x1B) | ||
91 | #define PRTCSS_RTC_ADAY0 (0x1C) | ||
92 | #define PRTCSS_RTC_ADAY1 (0x1D) | ||
93 | #define PRTCSS_RTC_CLKC_CNT (0x20) | ||
94 | |||
95 | /* PRTCSS_RTC_INTC_EXTENA1 */ | ||
96 | #define PRTCSS_RTC_INTC_EXTENA1_MASK (0x07) | ||
97 | |||
98 | /* PRTCSS_RTC_CTRL bit fields */ | ||
99 | #define PRTCSS_RTC_CTRL_WDTBUS BIT(7) | ||
100 | #define PRTCSS_RTC_CTRL_WEN BIT(6) | ||
101 | #define PRTCSS_RTC_CTRL_WDRT BIT(5) | ||
102 | #define PRTCSS_RTC_CTRL_WDTFLG BIT(4) | ||
103 | #define PRTCSS_RTC_CTRL_TE BIT(3) | ||
104 | #define PRTCSS_RTC_CTRL_TIEN BIT(2) | ||
105 | #define PRTCSS_RTC_CTRL_TMRFLG BIT(1) | ||
106 | #define PRTCSS_RTC_CTRL_TMMD BIT(0) | ||
107 | |||
108 | /* PRTCSS_RTC_CCTRL bit fields */ | ||
109 | #define PRTCSS_RTC_CCTRL_CALBUSY BIT(7) | ||
110 | #define PRTCSS_RTC_CCTRL_DAEN BIT(5) | ||
111 | #define PRTCSS_RTC_CCTRL_HAEN BIT(4) | ||
112 | #define PRTCSS_RTC_CCTRL_MAEN BIT(3) | ||
113 | #define PRTCSS_RTC_CCTRL_ALMFLG BIT(2) | ||
114 | #define PRTCSS_RTC_CCTRL_AIEN BIT(1) | ||
115 | #define PRTCSS_RTC_CCTRL_CAEN BIT(0) | ||
116 | |||
117 | static DEFINE_SPINLOCK(davinci_rtc_lock); | ||
118 | |||
119 | struct davinci_rtc { | ||
120 | struct rtc_device *rtc; | ||
121 | void __iomem *base; | ||
122 | resource_size_t pbase; | ||
123 | size_t base_size; | ||
124 | int irq; | ||
125 | }; | ||
126 | |||
127 | static inline void rtcif_write(struct davinci_rtc *davinci_rtc, | ||
128 | u32 val, u32 addr) | ||
129 | { | ||
130 | writel(val, davinci_rtc->base + addr); | ||
131 | } | ||
132 | |||
133 | static inline u32 rtcif_read(struct davinci_rtc *davinci_rtc, u32 addr) | ||
134 | { | ||
135 | return readl(davinci_rtc->base + addr); | ||
136 | } | ||
137 | |||
138 | static inline void rtcif_wait(struct davinci_rtc *davinci_rtc) | ||
139 | { | ||
140 | while (rtcif_read(davinci_rtc, PRTCIF_CTLR) & PRTCIF_CTLR_BUSY) | ||
141 | cpu_relax(); | ||
142 | } | ||
143 | |||
144 | static inline void rtcss_write(struct davinci_rtc *davinci_rtc, | ||
145 | unsigned long val, u8 addr) | ||
146 | { | ||
147 | rtcif_wait(davinci_rtc); | ||
148 | |||
149 | rtcif_write(davinci_rtc, PRTCIF_CTLR_BENL_LSB | addr, PRTCIF_CTLR); | ||
150 | rtcif_write(davinci_rtc, val, PRTCIF_LDATA); | ||
151 | |||
152 | rtcif_wait(davinci_rtc); | ||
153 | } | ||
154 | |||
155 | static inline u8 rtcss_read(struct davinci_rtc *davinci_rtc, u8 addr) | ||
156 | { | ||
157 | rtcif_wait(davinci_rtc); | ||
158 | |||
159 | rtcif_write(davinci_rtc, PRTCIF_CTLR_DIR | PRTCIF_CTLR_BENL_LSB | addr, | ||
160 | PRTCIF_CTLR); | ||
161 | |||
162 | rtcif_wait(davinci_rtc); | ||
163 | |||
164 | return rtcif_read(davinci_rtc, PRTCIF_LDATA); | ||
165 | } | ||
166 | |||
167 | static inline void davinci_rtcss_calendar_wait(struct davinci_rtc *davinci_rtc) | ||
168 | { | ||
169 | while (rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL) & | ||
170 | PRTCSS_RTC_CCTRL_CALBUSY) | ||
171 | cpu_relax(); | ||
172 | } | ||
173 | |||
174 | static irqreturn_t davinci_rtc_interrupt(int irq, void *class_dev) | ||
175 | { | ||
176 | struct davinci_rtc *davinci_rtc = class_dev; | ||
177 | unsigned long events = 0; | ||
178 | u32 irq_flg; | ||
179 | u8 alm_irq, tmr_irq; | ||
180 | u8 rtc_ctrl, rtc_cctrl; | ||
181 | int ret = IRQ_NONE; | ||
182 | |||
183 | irq_flg = rtcif_read(davinci_rtc, PRTCIF_INTFLG) & | ||
184 | PRTCIF_INTFLG_RTCSS; | ||
185 | |||
186 | alm_irq = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL) & | ||
187 | PRTCSS_RTC_CCTRL_ALMFLG; | ||
188 | |||
189 | tmr_irq = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL) & | ||
190 | PRTCSS_RTC_CTRL_TMRFLG; | ||
191 | |||
192 | if (irq_flg) { | ||
193 | if (alm_irq) { | ||
194 | events |= RTC_IRQF | RTC_AF; | ||
195 | rtc_cctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL); | ||
196 | rtc_cctrl |= PRTCSS_RTC_CCTRL_ALMFLG; | ||
197 | rtcss_write(davinci_rtc, rtc_cctrl, PRTCSS_RTC_CCTRL); | ||
198 | } else if (tmr_irq) { | ||
199 | events |= RTC_IRQF | RTC_PF; | ||
200 | rtc_ctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL); | ||
201 | rtc_ctrl |= PRTCSS_RTC_CTRL_TMRFLG; | ||
202 | rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL); | ||
203 | } | ||
204 | |||
205 | rtcif_write(davinci_rtc, PRTCIF_INTFLG_RTCSS, | ||
206 | PRTCIF_INTFLG); | ||
207 | rtc_update_irq(davinci_rtc->rtc, 1, events); | ||
208 | |||
209 | ret = IRQ_HANDLED; | ||
210 | } | ||
211 | |||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | static int | ||
216 | davinci_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
217 | { | ||
218 | struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); | ||
219 | u8 rtc_ctrl; | ||
220 | unsigned long flags; | ||
221 | int ret = 0; | ||
222 | |||
223 | spin_lock_irqsave(&davinci_rtc_lock, flags); | ||
224 | |||
225 | rtc_ctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL); | ||
226 | |||
227 | switch (cmd) { | ||
228 | case RTC_WIE_ON: | ||
229 | rtc_ctrl |= PRTCSS_RTC_CTRL_WEN | PRTCSS_RTC_CTRL_WDTFLG; | ||
230 | break; | ||
231 | case RTC_WIE_OFF: | ||
232 | rtc_ctrl &= ~PRTCSS_RTC_CTRL_WEN; | ||
233 | break; | ||
234 | case RTC_UIE_OFF: | ||
235 | case RTC_UIE_ON: | ||
236 | ret = -ENOTTY; | ||
237 | break; | ||
238 | default: | ||
239 | ret = -ENOIOCTLCMD; | ||
240 | } | ||
241 | |||
242 | rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL); | ||
243 | |||
244 | spin_unlock_irqrestore(&davinci_rtc_lock, flags); | ||
245 | |||
246 | return ret; | ||
247 | } | ||
248 | |||
249 | static int convertfromdays(u16 days, struct rtc_time *tm) | ||
250 | { | ||
251 | int tmp_days, year, mon; | ||
252 | |||
253 | for (year = 2000;; year++) { | ||
254 | tmp_days = rtc_year_days(1, 12, year); | ||
255 | if (days >= tmp_days) | ||
256 | days -= tmp_days; | ||
257 | else { | ||
258 | for (mon = 0;; mon++) { | ||
259 | tmp_days = rtc_month_days(mon, year); | ||
260 | if (days >= tmp_days) { | ||
261 | days -= tmp_days; | ||
262 | } else { | ||
263 | tm->tm_year = year - 1900; | ||
264 | tm->tm_mon = mon; | ||
265 | tm->tm_mday = days + 1; | ||
266 | break; | ||
267 | } | ||
268 | } | ||
269 | break; | ||
270 | } | ||
271 | } | ||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | static int convert2days(u16 *days, struct rtc_time *tm) | ||
276 | { | ||
277 | int i; | ||
278 | *days = 0; | ||
279 | |||
280 | /* epoch == 1900 */ | ||
281 | if (tm->tm_year < 100 || tm->tm_year > 199) | ||
282 | return -EINVAL; | ||
283 | |||
284 | for (i = 2000; i < 1900 + tm->tm_year; i++) | ||
285 | *days += rtc_year_days(1, 12, i); | ||
286 | |||
287 | *days += rtc_year_days(tm->tm_mday, tm->tm_mon, 1900 + tm->tm_year); | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int davinci_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
293 | { | ||
294 | struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); | ||
295 | u16 days = 0; | ||
296 | u8 day0, day1; | ||
297 | unsigned long flags; | ||
298 | |||
299 | spin_lock_irqsave(&davinci_rtc_lock, flags); | ||
300 | |||
301 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
302 | tm->tm_sec = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_SEC)); | ||
303 | |||
304 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
305 | tm->tm_min = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_MIN)); | ||
306 | |||
307 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
308 | tm->tm_hour = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_HOUR)); | ||
309 | |||
310 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
311 | day0 = rtcss_read(davinci_rtc, PRTCSS_RTC_DAY0); | ||
312 | |||
313 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
314 | day1 = rtcss_read(davinci_rtc, PRTCSS_RTC_DAY1); | ||
315 | |||
316 | spin_unlock_irqrestore(&davinci_rtc_lock, flags); | ||
317 | |||
318 | days |= day1; | ||
319 | days <<= 8; | ||
320 | days |= day0; | ||
321 | |||
322 | if (convertfromdays(days, tm) < 0) | ||
323 | return -EINVAL; | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static int davinci_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
329 | { | ||
330 | struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); | ||
331 | u16 days; | ||
332 | u8 rtc_cctrl; | ||
333 | unsigned long flags; | ||
334 | |||
335 | if (convert2days(&days, tm) < 0) | ||
336 | return -EINVAL; | ||
337 | |||
338 | spin_lock_irqsave(&davinci_rtc_lock, flags); | ||
339 | |||
340 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
341 | rtcss_write(davinci_rtc, bin2bcd(tm->tm_sec), PRTCSS_RTC_SEC); | ||
342 | |||
343 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
344 | rtcss_write(davinci_rtc, bin2bcd(tm->tm_min), PRTCSS_RTC_MIN); | ||
345 | |||
346 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
347 | rtcss_write(davinci_rtc, bin2bcd(tm->tm_hour), PRTCSS_RTC_HOUR); | ||
348 | |||
349 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
350 | rtcss_write(davinci_rtc, days & 0xFF, PRTCSS_RTC_DAY0); | ||
351 | |||
352 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
353 | rtcss_write(davinci_rtc, (days & 0xFF00) >> 8, PRTCSS_RTC_DAY1); | ||
354 | |||
355 | rtc_cctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL); | ||
356 | rtc_cctrl |= PRTCSS_RTC_CCTRL_CAEN; | ||
357 | rtcss_write(davinci_rtc, rtc_cctrl, PRTCSS_RTC_CCTRL); | ||
358 | |||
359 | spin_unlock_irqrestore(&davinci_rtc_lock, flags); | ||
360 | |||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | static int davinci_rtc_alarm_irq_enable(struct device *dev, | ||
365 | unsigned int enabled) | ||
366 | { | ||
367 | struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); | ||
368 | unsigned long flags; | ||
369 | u8 rtc_cctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL); | ||
370 | |||
371 | spin_lock_irqsave(&davinci_rtc_lock, flags); | ||
372 | |||
373 | if (enabled) | ||
374 | rtc_cctrl |= PRTCSS_RTC_CCTRL_DAEN | | ||
375 | PRTCSS_RTC_CCTRL_HAEN | | ||
376 | PRTCSS_RTC_CCTRL_MAEN | | ||
377 | PRTCSS_RTC_CCTRL_ALMFLG | | ||
378 | PRTCSS_RTC_CCTRL_AIEN; | ||
379 | else | ||
380 | rtc_cctrl &= ~PRTCSS_RTC_CCTRL_AIEN; | ||
381 | |||
382 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
383 | rtcss_write(davinci_rtc, rtc_cctrl, PRTCSS_RTC_CCTRL); | ||
384 | |||
385 | spin_unlock_irqrestore(&davinci_rtc_lock, flags); | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | static int davinci_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
391 | { | ||
392 | struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); | ||
393 | u16 days = 0; | ||
394 | u8 day0, day1; | ||
395 | unsigned long flags; | ||
396 | |||
397 | spin_lock_irqsave(&davinci_rtc_lock, flags); | ||
398 | |||
399 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
400 | alm->time.tm_min = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_AMIN)); | ||
401 | |||
402 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
403 | alm->time.tm_hour = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_AHOUR)); | ||
404 | |||
405 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
406 | day0 = rtcss_read(davinci_rtc, PRTCSS_RTC_ADAY0); | ||
407 | |||
408 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
409 | day1 = rtcss_read(davinci_rtc, PRTCSS_RTC_ADAY1); | ||
410 | |||
411 | spin_unlock_irqrestore(&davinci_rtc_lock, flags); | ||
412 | days |= day1; | ||
413 | days <<= 8; | ||
414 | days |= day0; | ||
415 | |||
416 | if (convertfromdays(days, &alm->time) < 0) | ||
417 | return -EINVAL; | ||
418 | |||
419 | alm->pending = !!(rtcss_read(davinci_rtc, | ||
420 | PRTCSS_RTC_CCTRL) & | ||
421 | PRTCSS_RTC_CCTRL_AIEN); | ||
422 | alm->enabled = alm->pending && device_may_wakeup(dev); | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static int davinci_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
428 | { | ||
429 | struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); | ||
430 | unsigned long flags; | ||
431 | u16 days; | ||
432 | |||
433 | if (alm->time.tm_mday <= 0 && alm->time.tm_mon < 0 | ||
434 | && alm->time.tm_year < 0) { | ||
435 | struct rtc_time tm; | ||
436 | unsigned long now, then; | ||
437 | |||
438 | davinci_rtc_read_time(dev, &tm); | ||
439 | rtc_tm_to_time(&tm, &now); | ||
440 | |||
441 | alm->time.tm_mday = tm.tm_mday; | ||
442 | alm->time.tm_mon = tm.tm_mon; | ||
443 | alm->time.tm_year = tm.tm_year; | ||
444 | rtc_tm_to_time(&alm->time, &then); | ||
445 | |||
446 | if (then < now) { | ||
447 | rtc_time_to_tm(now + 24 * 60 * 60, &tm); | ||
448 | alm->time.tm_mday = tm.tm_mday; | ||
449 | alm->time.tm_mon = tm.tm_mon; | ||
450 | alm->time.tm_year = tm.tm_year; | ||
451 | } | ||
452 | } | ||
453 | |||
454 | if (convert2days(&days, &alm->time) < 0) | ||
455 | return -EINVAL; | ||
456 | |||
457 | spin_lock_irqsave(&davinci_rtc_lock, flags); | ||
458 | |||
459 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
460 | rtcss_write(davinci_rtc, bin2bcd(alm->time.tm_min), PRTCSS_RTC_AMIN); | ||
461 | |||
462 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
463 | rtcss_write(davinci_rtc, bin2bcd(alm->time.tm_hour), PRTCSS_RTC_AHOUR); | ||
464 | |||
465 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
466 | rtcss_write(davinci_rtc, days & 0xFF, PRTCSS_RTC_ADAY0); | ||
467 | |||
468 | davinci_rtcss_calendar_wait(davinci_rtc); | ||
469 | rtcss_write(davinci_rtc, (days & 0xFF00) >> 8, PRTCSS_RTC_ADAY1); | ||
470 | |||
471 | spin_unlock_irqrestore(&davinci_rtc_lock, flags); | ||
472 | |||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | static int davinci_rtc_irq_set_state(struct device *dev, int enabled) | ||
477 | { | ||
478 | struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); | ||
479 | unsigned long flags; | ||
480 | u8 rtc_ctrl; | ||
481 | |||
482 | spin_lock_irqsave(&davinci_rtc_lock, flags); | ||
483 | |||
484 | rtc_ctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL); | ||
485 | |||
486 | if (enabled) { | ||
487 | while (rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL) | ||
488 | & PRTCSS_RTC_CTRL_WDTBUS) | ||
489 | cpu_relax(); | ||
490 | |||
491 | rtc_ctrl |= PRTCSS_RTC_CTRL_TE; | ||
492 | rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL); | ||
493 | |||
494 | rtcss_write(davinci_rtc, 0x0, PRTCSS_RTC_CLKC_CNT); | ||
495 | |||
496 | rtc_ctrl |= PRTCSS_RTC_CTRL_TIEN | | ||
497 | PRTCSS_RTC_CTRL_TMMD | | ||
498 | PRTCSS_RTC_CTRL_TMRFLG; | ||
499 | } else | ||
500 | rtc_ctrl &= ~PRTCSS_RTC_CTRL_TIEN; | ||
501 | |||
502 | rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL); | ||
503 | |||
504 | spin_unlock_irqrestore(&davinci_rtc_lock, flags); | ||
505 | |||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | static int davinci_rtc_irq_set_freq(struct device *dev, int freq) | ||
510 | { | ||
511 | struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); | ||
512 | unsigned long flags; | ||
513 | u16 tmr_counter = (0x8000 >> (ffs(freq) - 1)); | ||
514 | |||
515 | spin_lock_irqsave(&davinci_rtc_lock, flags); | ||
516 | |||
517 | rtcss_write(davinci_rtc, tmr_counter & 0xFF, PRTCSS_RTC_TMR0); | ||
518 | rtcss_write(davinci_rtc, (tmr_counter & 0xFF00) >> 8, PRTCSS_RTC_TMR1); | ||
519 | |||
520 | spin_unlock_irqrestore(&davinci_rtc_lock, flags); | ||
521 | |||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static struct rtc_class_ops davinci_rtc_ops = { | ||
526 | .ioctl = davinci_rtc_ioctl, | ||
527 | .read_time = davinci_rtc_read_time, | ||
528 | .set_time = davinci_rtc_set_time, | ||
529 | .alarm_irq_enable = davinci_rtc_alarm_irq_enable, | ||
530 | .read_alarm = davinci_rtc_read_alarm, | ||
531 | .set_alarm = davinci_rtc_set_alarm, | ||
532 | .irq_set_state = davinci_rtc_irq_set_state, | ||
533 | .irq_set_freq = davinci_rtc_irq_set_freq, | ||
534 | }; | ||
535 | |||
536 | static int __init davinci_rtc_probe(struct platform_device *pdev) | ||
537 | { | ||
538 | struct device *dev = &pdev->dev; | ||
539 | struct davinci_rtc *davinci_rtc; | ||
540 | struct resource *res, *mem; | ||
541 | int ret = 0; | ||
542 | |||
543 | davinci_rtc = kzalloc(sizeof(struct davinci_rtc), GFP_KERNEL); | ||
544 | if (!davinci_rtc) { | ||
545 | dev_dbg(dev, "could not allocate memory for private data\n"); | ||
546 | return -ENOMEM; | ||
547 | } | ||
548 | |||
549 | davinci_rtc->irq = platform_get_irq(pdev, 0); | ||
550 | if (davinci_rtc->irq < 0) { | ||
551 | dev_err(dev, "no RTC irq\n"); | ||
552 | ret = davinci_rtc->irq; | ||
553 | goto fail1; | ||
554 | } | ||
555 | |||
556 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
557 | if (!res) { | ||
558 | dev_err(dev, "no mem resource\n"); | ||
559 | ret = -EINVAL; | ||
560 | goto fail1; | ||
561 | } | ||
562 | |||
563 | davinci_rtc->pbase = res->start; | ||
564 | davinci_rtc->base_size = resource_size(res); | ||
565 | |||
566 | mem = request_mem_region(davinci_rtc->pbase, davinci_rtc->base_size, | ||
567 | pdev->name); | ||
568 | if (!mem) { | ||
569 | dev_err(dev, "RTC registers at %08x are not free\n", | ||
570 | davinci_rtc->pbase); | ||
571 | ret = -EBUSY; | ||
572 | goto fail1; | ||
573 | } | ||
574 | |||
575 | davinci_rtc->base = ioremap(davinci_rtc->pbase, davinci_rtc->base_size); | ||
576 | if (!davinci_rtc->base) { | ||
577 | dev_err(dev, "unable to ioremap MEM resource\n"); | ||
578 | ret = -ENOMEM; | ||
579 | goto fail2; | ||
580 | } | ||
581 | |||
582 | davinci_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
583 | &davinci_rtc_ops, THIS_MODULE); | ||
584 | if (IS_ERR(davinci_rtc->rtc)) { | ||
585 | dev_err(dev, "unable to register RTC device, err %ld\n", | ||
586 | PTR_ERR(davinci_rtc->rtc)); | ||
587 | goto fail3; | ||
588 | } | ||
589 | |||
590 | rtcif_write(davinci_rtc, PRTCIF_INTFLG_RTCSS, PRTCIF_INTFLG); | ||
591 | rtcif_write(davinci_rtc, 0, PRTCIF_INTEN); | ||
592 | rtcss_write(davinci_rtc, 0, PRTCSS_RTC_INTC_EXTENA1); | ||
593 | |||
594 | rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CTRL); | ||
595 | rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CCTRL); | ||
596 | |||
597 | ret = request_irq(davinci_rtc->irq, davinci_rtc_interrupt, | ||
598 | IRQF_DISABLED, "davinci_rtc", davinci_rtc); | ||
599 | if (ret < 0) { | ||
600 | dev_err(dev, "unable to register davinci RTC interrupt\n"); | ||
601 | goto fail4; | ||
602 | } | ||
603 | |||
604 | /* Enable interrupts */ | ||
605 | rtcif_write(davinci_rtc, PRTCIF_INTEN_RTCSS, PRTCIF_INTEN); | ||
606 | rtcss_write(davinci_rtc, PRTCSS_RTC_INTC_EXTENA1_MASK, | ||
607 | PRTCSS_RTC_INTC_EXTENA1); | ||
608 | |||
609 | rtcss_write(davinci_rtc, PRTCSS_RTC_CCTRL_CAEN, PRTCSS_RTC_CCTRL); | ||
610 | |||
611 | platform_set_drvdata(pdev, davinci_rtc); | ||
612 | |||
613 | device_init_wakeup(&pdev->dev, 0); | ||
614 | |||
615 | return 0; | ||
616 | |||
617 | fail4: | ||
618 | rtc_device_unregister(davinci_rtc->rtc); | ||
619 | fail3: | ||
620 | iounmap(davinci_rtc->base); | ||
621 | fail2: | ||
622 | release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size); | ||
623 | fail1: | ||
624 | kfree(davinci_rtc); | ||
625 | |||
626 | return ret; | ||
627 | } | ||
628 | |||
629 | static int __devexit davinci_rtc_remove(struct platform_device *pdev) | ||
630 | { | ||
631 | struct davinci_rtc *davinci_rtc = platform_get_drvdata(pdev); | ||
632 | |||
633 | device_init_wakeup(&pdev->dev, 0); | ||
634 | |||
635 | rtcif_write(davinci_rtc, 0, PRTCIF_INTEN); | ||
636 | |||
637 | free_irq(davinci_rtc->irq, davinci_rtc); | ||
638 | |||
639 | rtc_device_unregister(davinci_rtc->rtc); | ||
640 | |||
641 | iounmap(davinci_rtc->base); | ||
642 | release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size); | ||
643 | |||
644 | platform_set_drvdata(pdev, NULL); | ||
645 | |||
646 | kfree(davinci_rtc); | ||
647 | |||
648 | return 0; | ||
649 | } | ||
650 | |||
651 | static struct platform_driver davinci_rtc_driver = { | ||
652 | .probe = davinci_rtc_probe, | ||
653 | .remove = __devexit_p(davinci_rtc_remove), | ||
654 | .driver = { | ||
655 | .name = "rtc_davinci", | ||
656 | .owner = THIS_MODULE, | ||
657 | }, | ||
658 | }; | ||
659 | |||
660 | static int __init rtc_init(void) | ||
661 | { | ||
662 | return platform_driver_probe(&davinci_rtc_driver, davinci_rtc_probe); | ||
663 | } | ||
664 | module_init(rtc_init); | ||
665 | |||
666 | static void __exit rtc_exit(void) | ||
667 | { | ||
668 | platform_driver_unregister(&davinci_rtc_driver); | ||
669 | } | ||
670 | module_exit(rtc_exit); | ||
671 | |||
672 | MODULE_AUTHOR("Miguel Aguilar <miguel.aguilar@ridgerun.com>"); | ||
673 | MODULE_DESCRIPTION("Texas Instruments DaVinci PRTC Driver"); | ||
674 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 8a11de9552cd..212b16edafc0 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
@@ -13,6 +13,7 @@ | |||
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/sched.h> | ||
16 | #include "rtc-core.h" | 17 | #include "rtc-core.h" |
17 | 18 | ||
18 | static dev_t rtc_devt; | 19 | static dev_t rtc_devt; |
@@ -45,105 +46,6 @@ static int rtc_dev_open(struct inode *inode, struct file *file) | |||
45 | return err; | 46 | return err; |
46 | } | 47 | } |
47 | 48 | ||
48 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | ||
49 | /* | ||
50 | * Routine to poll RTC seconds field for change as often as possible, | ||
51 | * after first RTC_UIE use timer to reduce polling | ||
52 | */ | ||
53 | static void rtc_uie_task(struct work_struct *work) | ||
54 | { | ||
55 | struct rtc_device *rtc = | ||
56 | container_of(work, struct rtc_device, uie_task); | ||
57 | struct rtc_time tm; | ||
58 | int num = 0; | ||
59 | int err; | ||
60 | |||
61 | err = rtc_read_time(rtc, &tm); | ||
62 | |||
63 | spin_lock_irq(&rtc->irq_lock); | ||
64 | if (rtc->stop_uie_polling || err) { | ||
65 | rtc->uie_task_active = 0; | ||
66 | } else if (rtc->oldsecs != tm.tm_sec) { | ||
67 | num = (tm.tm_sec + 60 - rtc->oldsecs) % 60; | ||
68 | rtc->oldsecs = tm.tm_sec; | ||
69 | rtc->uie_timer.expires = jiffies + HZ - (HZ/10); | ||
70 | rtc->uie_timer_active = 1; | ||
71 | rtc->uie_task_active = 0; | ||
72 | add_timer(&rtc->uie_timer); | ||
73 | } else if (schedule_work(&rtc->uie_task) == 0) { | ||
74 | rtc->uie_task_active = 0; | ||
75 | } | ||
76 | spin_unlock_irq(&rtc->irq_lock); | ||
77 | if (num) | ||
78 | rtc_update_irq(rtc, num, RTC_UF | RTC_IRQF); | ||
79 | } | ||
80 | static void rtc_uie_timer(unsigned long data) | ||
81 | { | ||
82 | struct rtc_device *rtc = (struct rtc_device *)data; | ||
83 | unsigned long flags; | ||
84 | |||
85 | spin_lock_irqsave(&rtc->irq_lock, flags); | ||
86 | rtc->uie_timer_active = 0; | ||
87 | rtc->uie_task_active = 1; | ||
88 | if ((schedule_work(&rtc->uie_task) == 0)) | ||
89 | rtc->uie_task_active = 0; | ||
90 | spin_unlock_irqrestore(&rtc->irq_lock, flags); | ||
91 | } | ||
92 | |||
93 | static int clear_uie(struct rtc_device *rtc) | ||
94 | { | ||
95 | spin_lock_irq(&rtc->irq_lock); | ||
96 | if (rtc->uie_irq_active) { | ||
97 | rtc->stop_uie_polling = 1; | ||
98 | if (rtc->uie_timer_active) { | ||
99 | spin_unlock_irq(&rtc->irq_lock); | ||
100 | del_timer_sync(&rtc->uie_timer); | ||
101 | spin_lock_irq(&rtc->irq_lock); | ||
102 | rtc->uie_timer_active = 0; | ||
103 | } | ||
104 | if (rtc->uie_task_active) { | ||
105 | spin_unlock_irq(&rtc->irq_lock); | ||
106 | flush_scheduled_work(); | ||
107 | spin_lock_irq(&rtc->irq_lock); | ||
108 | } | ||
109 | rtc->uie_irq_active = 0; | ||
110 | } | ||
111 | spin_unlock_irq(&rtc->irq_lock); | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static int set_uie(struct rtc_device *rtc) | ||
116 | { | ||
117 | struct rtc_time tm; | ||
118 | int err; | ||
119 | |||
120 | err = rtc_read_time(rtc, &tm); | ||
121 | if (err) | ||
122 | return err; | ||
123 | spin_lock_irq(&rtc->irq_lock); | ||
124 | if (!rtc->uie_irq_active) { | ||
125 | rtc->uie_irq_active = 1; | ||
126 | rtc->stop_uie_polling = 0; | ||
127 | rtc->oldsecs = tm.tm_sec; | ||
128 | rtc->uie_task_active = 1; | ||
129 | if (schedule_work(&rtc->uie_task) == 0) | ||
130 | rtc->uie_task_active = 0; | ||
131 | } | ||
132 | rtc->irq_data = 0; | ||
133 | spin_unlock_irq(&rtc->irq_lock); | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc, unsigned int enabled) | ||
138 | { | ||
139 | if (enabled) | ||
140 | return set_uie(rtc); | ||
141 | else | ||
142 | return clear_uie(rtc); | ||
143 | } | ||
144 | EXPORT_SYMBOL(rtc_dev_update_irq_enable_emul); | ||
145 | |||
146 | #endif /* CONFIG_RTC_INTF_DEV_UIE_EMUL */ | ||
147 | 49 | ||
148 | static ssize_t | 50 | static ssize_t |
149 | rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | 51 | rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) |
@@ -492,11 +394,6 @@ void rtc_dev_prepare(struct rtc_device *rtc) | |||
492 | 394 | ||
493 | rtc->dev.devt = MKDEV(MAJOR(rtc_devt), rtc->id); | 395 | rtc->dev.devt = MKDEV(MAJOR(rtc_devt), rtc->id); |
494 | 396 | ||
495 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | ||
496 | INIT_WORK(&rtc->uie_task, rtc_uie_task); | ||
497 | setup_timer(&rtc->uie_timer, rtc_uie_timer, (unsigned long)rtc); | ||
498 | #endif | ||
499 | |||
500 | cdev_init(&rtc->char_dev, &rtc_dev_fops); | 397 | cdev_init(&rtc->char_dev, &rtc_dev_fops); |
501 | rtc->char_dev.owner = rtc->owner; | 398 | rtc->char_dev.owner = rtc->owner; |
502 | } | 399 | } |
diff --git a/drivers/rtc/rtc-ds1216.c b/drivers/rtc/rtc-ds1216.c index 4aedc705518c..45cd8c9f5a39 100644 --- a/drivers/rtc/rtc-ds1216.c +++ b/drivers/rtc/rtc-ds1216.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/rtc.h> | 9 | #include <linux/rtc.h> |
10 | #include <linux/platform_device.h> | 10 | #include <linux/platform_device.h> |
11 | #include <linux/bcd.h> | 11 | #include <linux/bcd.h> |
12 | #include <linux/slab.h> | ||
12 | 13 | ||
13 | #define DRV_VERSION "0.2" | 14 | #define DRV_VERSION "0.2" |
14 | 15 | ||
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c index 4fcb16bbff4a..bf430f9091ed 100644 --- a/drivers/rtc/rtc-ds1286.c +++ b/drivers/rtc/rtc-ds1286.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/bcd.h> | 18 | #include <linux/bcd.h> |
19 | #include <linux/ds1286.h> | 19 | #include <linux/ds1286.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/slab.h> | ||
21 | 22 | ||
22 | #define DRV_VERSION "1.0" | 23 | #define DRV_VERSION "1.0" |
23 | 24 | ||
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c index 184556620778..f0d638922644 100644 --- a/drivers/rtc/rtc-ds1302.c +++ b/drivers/rtc/rtc-ds1302.c | |||
@@ -1,26 +1,24 @@ | |||
1 | /* | 1 | /* |
2 | * Dallas DS1302 RTC Support | 2 | * Dallas DS1302 RTC Support |
3 | * | 3 | * |
4 | * Copyright (C) 2002 David McCullough | 4 | * Copyright (C) 2002 David McCullough |
5 | * Copyright (C) 2003 - 2007 Paul Mundt | 5 | * Copyright (C) 2003 - 2007 Paul Mundt |
6 | * | 6 | * |
7 | * This file is subject to the terms and conditions of the GNU General Public | 7 | * This file is subject to the terms and conditions of the GNU General Public |
8 | * License version 2. See the file "COPYING" in the main directory of | 8 | * License version 2. See the file "COPYING" in the main directory of |
9 | * this archive for more details. | 9 | * this archive for more details. |
10 | */ | 10 | */ |
11 | |||
11 | #include <linux/init.h> | 12 | #include <linux/init.h> |
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
13 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
14 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
15 | #include <linux/time.h> | ||
16 | #include <linux/rtc.h> | 16 | #include <linux/rtc.h> |
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/io.h> | 17 | #include <linux/io.h> |
19 | #include <linux/bcd.h> | 18 | #include <linux/bcd.h> |
20 | #include <asm/rtc.h> | ||
21 | 19 | ||
22 | #define DRV_NAME "rtc-ds1302" | 20 | #define DRV_NAME "rtc-ds1302" |
23 | #define DRV_VERSION "0.1.0" | 21 | #define DRV_VERSION "0.1.1" |
24 | 22 | ||
25 | #define RTC_CMD_READ 0x81 /* Read command */ | 23 | #define RTC_CMD_READ 0x81 /* Read command */ |
26 | #define RTC_CMD_WRITE 0x80 /* Write command */ | 24 | #define RTC_CMD_WRITE 0x80 /* Write command */ |
@@ -35,32 +33,68 @@ | |||
35 | #define RTC_ADDR_MIN 0x01 /* Address of minute register */ | 33 | #define RTC_ADDR_MIN 0x01 /* Address of minute register */ |
36 | #define RTC_ADDR_SEC 0x00 /* Address of second register */ | 34 | #define RTC_ADDR_SEC 0x00 /* Address of second register */ |
37 | 35 | ||
36 | #ifdef CONFIG_SH_SECUREEDGE5410 | ||
37 | #include <asm/rtc.h> | ||
38 | #include <mach/secureedge5410.h> | ||
39 | |||
38 | #define RTC_RESET 0x1000 | 40 | #define RTC_RESET 0x1000 |
39 | #define RTC_IODATA 0x0800 | 41 | #define RTC_IODATA 0x0800 |
40 | #define RTC_SCLK 0x0400 | 42 | #define RTC_SCLK 0x0400 |
41 | 43 | ||
42 | #ifdef CONFIG_SH_SECUREEDGE5410 | ||
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 | #define ds1302_set_tx() | ||
47 | #define ds1302_set_rx() | ||
48 | |||
49 | static inline int ds1302_hw_init(void) | ||
50 | { | ||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | static inline void ds1302_reset(void) | ||
55 | { | ||
56 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | ||
57 | } | ||
58 | |||
59 | static inline void ds1302_clock(void) | ||
60 | { | ||
61 | set_dp(get_dp() | RTC_SCLK); /* clock high */ | ||
62 | set_dp(get_dp() & ~RTC_SCLK); /* clock low */ | ||
63 | } | ||
64 | |||
65 | static inline void ds1302_start(void) | ||
66 | { | ||
67 | set_dp(get_dp() | RTC_RESET); | ||
68 | } | ||
69 | |||
70 | static inline void ds1302_stop(void) | ||
71 | { | ||
72 | set_dp(get_dp() & ~RTC_RESET); | ||
73 | } | ||
74 | |||
75 | static inline void ds1302_txbit(int bit) | ||
76 | { | ||
77 | set_dp((get_dp() & ~RTC_IODATA) | (bit ? RTC_IODATA : 0)); | ||
78 | } | ||
79 | |||
80 | static inline int ds1302_rxbit(void) | ||
81 | { | ||
82 | return !!(get_dp() & RTC_IODATA); | ||
83 | } | ||
84 | |||
46 | #else | 85 | #else |
47 | #error "Add support for your platform" | 86 | #error "Add support for your platform" |
48 | #endif | 87 | #endif |
49 | 88 | ||
50 | struct ds1302_rtc { | ||
51 | struct rtc_device *rtc_dev; | ||
52 | spinlock_t lock; | ||
53 | }; | ||
54 | |||
55 | static void ds1302_sendbits(unsigned int val) | 89 | static void ds1302_sendbits(unsigned int val) |
56 | { | 90 | { |
57 | int i; | 91 | int i; |
58 | 92 | ||
93 | ds1302_set_tx(); | ||
94 | |||
59 | for (i = 8; (i); i--, val >>= 1) { | 95 | for (i = 8; (i); i--, val >>= 1) { |
60 | set_dp((get_dp() & ~RTC_IODATA) | ((val & 0x1) ? | 96 | ds1302_txbit(val & 0x1); |
61 | RTC_IODATA : 0)); | 97 | ds1302_clock(); |
62 | set_dp(get_dp() | RTC_SCLK); /* clock high */ | ||
63 | set_dp(get_dp() & ~RTC_SCLK); /* clock low */ | ||
64 | } | 98 | } |
65 | } | 99 | } |
66 | 100 | ||
@@ -69,10 +103,11 @@ static unsigned int ds1302_recvbits(void) | |||
69 | unsigned int val; | 103 | unsigned int val; |
70 | int i; | 104 | int i; |
71 | 105 | ||
106 | ds1302_set_rx(); | ||
107 | |||
72 | for (i = 0, val = 0; (i < 8); i++) { | 108 | for (i = 0, val = 0; (i < 8); i++) { |
73 | val |= (((get_dp() & RTC_IODATA) ? 1 : 0) << i); | 109 | val |= (ds1302_rxbit() << i); |
74 | set_dp(get_dp() | RTC_SCLK); /* clock high */ | 110 | ds1302_clock(); |
75 | set_dp(get_dp() & ~RTC_SCLK); /* clock low */ | ||
76 | } | 111 | } |
77 | 112 | ||
78 | return val; | 113 | return val; |
@@ -82,31 +117,28 @@ static unsigned int ds1302_readbyte(unsigned int addr) | |||
82 | { | 117 | { |
83 | unsigned int val; | 118 | unsigned int val; |
84 | 119 | ||
85 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | 120 | ds1302_reset(); |
86 | 121 | ||
87 | set_dp(get_dp() | RTC_RESET); | 122 | ds1302_start(); |
88 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ); | 123 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ); |
89 | val = ds1302_recvbits(); | 124 | val = ds1302_recvbits(); |
90 | set_dp(get_dp() & ~RTC_RESET); | 125 | ds1302_stop(); |
91 | 126 | ||
92 | return val; | 127 | return val; |
93 | } | 128 | } |
94 | 129 | ||
95 | static void ds1302_writebyte(unsigned int addr, unsigned int val) | 130 | static void ds1302_writebyte(unsigned int addr, unsigned int val) |
96 | { | 131 | { |
97 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | 132 | ds1302_reset(); |
98 | set_dp(get_dp() | RTC_RESET); | 133 | |
134 | ds1302_start(); | ||
99 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE); | 135 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE); |
100 | ds1302_sendbits(val); | 136 | ds1302_sendbits(val); |
101 | set_dp(get_dp() & ~RTC_RESET); | 137 | ds1302_stop(); |
102 | } | 138 | } |
103 | 139 | ||
104 | static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm) | 140 | static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm) |
105 | { | 141 | { |
106 | struct ds1302_rtc *rtc = dev_get_drvdata(dev); | ||
107 | |||
108 | spin_lock_irq(&rtc->lock); | ||
109 | |||
110 | tm->tm_sec = bcd2bin(ds1302_readbyte(RTC_ADDR_SEC)); | 142 | tm->tm_sec = bcd2bin(ds1302_readbyte(RTC_ADDR_SEC)); |
111 | tm->tm_min = bcd2bin(ds1302_readbyte(RTC_ADDR_MIN)); | 143 | tm->tm_min = bcd2bin(ds1302_readbyte(RTC_ADDR_MIN)); |
112 | tm->tm_hour = bcd2bin(ds1302_readbyte(RTC_ADDR_HOUR)); | 144 | tm->tm_hour = bcd2bin(ds1302_readbyte(RTC_ADDR_HOUR)); |
@@ -118,26 +150,17 @@ static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
118 | if (tm->tm_year < 70) | 150 | if (tm->tm_year < 70) |
119 | tm->tm_year += 100; | 151 | tm->tm_year += 100; |
120 | 152 | ||
121 | spin_unlock_irq(&rtc->lock); | ||
122 | |||
123 | dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " | 153 | dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " |
124 | "mday=%d, mon=%d, year=%d, wday=%d\n", | 154 | "mday=%d, mon=%d, year=%d, wday=%d\n", |
125 | __func__, | 155 | __func__, |
126 | tm->tm_sec, tm->tm_min, tm->tm_hour, | 156 | tm->tm_sec, tm->tm_min, tm->tm_hour, |
127 | tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday); | 157 | tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday); |
128 | 158 | ||
129 | if (rtc_valid_tm(tm) < 0) | 159 | return rtc_valid_tm(tm); |
130 | dev_err(dev, "invalid date\n"); | ||
131 | |||
132 | return 0; | ||
133 | } | 160 | } |
134 | 161 | ||
135 | static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm) | 162 | static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm) |
136 | { | 163 | { |
137 | struct ds1302_rtc *rtc = dev_get_drvdata(dev); | ||
138 | |||
139 | spin_lock_irq(&rtc->lock); | ||
140 | |||
141 | /* Stop RTC */ | 164 | /* Stop RTC */ |
142 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80); | 165 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80); |
143 | 166 | ||
@@ -152,8 +175,6 @@ static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
152 | /* Start RTC */ | 175 | /* Start RTC */ |
153 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80); | 176 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80); |
154 | 177 | ||
155 | spin_unlock_irq(&rtc->lock); | ||
156 | |||
157 | return 0; | 178 | return 0; |
158 | } | 179 | } |
159 | 180 | ||
@@ -164,15 +185,12 @@ static int ds1302_rtc_ioctl(struct device *dev, unsigned int cmd, | |||
164 | #ifdef RTC_SET_CHARGE | 185 | #ifdef RTC_SET_CHARGE |
165 | case RTC_SET_CHARGE: | 186 | case RTC_SET_CHARGE: |
166 | { | 187 | { |
167 | struct ds1302_rtc *rtc = dev_get_drvdata(dev); | ||
168 | int tcs_val; | 188 | int tcs_val; |
169 | 189 | ||
170 | if (copy_from_user(&tcs_val, (int __user *)arg, sizeof(int))) | 190 | if (copy_from_user(&tcs_val, (int __user *)arg, sizeof(int))) |
171 | return -EFAULT; | 191 | return -EFAULT; |
172 | 192 | ||
173 | spin_lock_irq(&rtc->lock); | ||
174 | ds1302_writebyte(RTC_ADDR_TCR, (0xa0 | tcs_val * 0xf)); | 193 | ds1302_writebyte(RTC_ADDR_TCR, (0xa0 | tcs_val * 0xf)); |
175 | spin_unlock_irq(&rtc->lock); | ||
176 | return 0; | 194 | return 0; |
177 | } | 195 | } |
178 | #endif | 196 | #endif |
@@ -187,50 +205,42 @@ static struct rtc_class_ops ds1302_rtc_ops = { | |||
187 | .ioctl = ds1302_rtc_ioctl, | 205 | .ioctl = ds1302_rtc_ioctl, |
188 | }; | 206 | }; |
189 | 207 | ||
190 | static int __devinit ds1302_rtc_probe(struct platform_device *pdev) | 208 | static int __init ds1302_rtc_probe(struct platform_device *pdev) |
191 | { | 209 | { |
192 | struct ds1302_rtc *rtc; | 210 | struct rtc_device *rtc; |
193 | int ret; | 211 | |
212 | if (ds1302_hw_init()) { | ||
213 | dev_err(&pdev->dev, "Failed to init communication channel"); | ||
214 | return -EINVAL; | ||
215 | } | ||
194 | 216 | ||
195 | /* Reset */ | 217 | /* Reset */ |
196 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | 218 | ds1302_reset(); |
197 | 219 | ||
198 | /* Write a magic value to the DS1302 RAM, and see if it sticks. */ | 220 | /* Write a magic value to the DS1302 RAM, and see if it sticks. */ |
199 | ds1302_writebyte(RTC_ADDR_RAM0, 0x42); | 221 | ds1302_writebyte(RTC_ADDR_RAM0, 0x42); |
200 | if (ds1302_readbyte(RTC_ADDR_RAM0) != 0x42) | 222 | if (ds1302_readbyte(RTC_ADDR_RAM0) != 0x42) { |
223 | dev_err(&pdev->dev, "Failed to probe"); | ||
201 | return -ENODEV; | 224 | return -ENODEV; |
225 | } | ||
202 | 226 | ||
203 | rtc = kzalloc(sizeof(struct ds1302_rtc), GFP_KERNEL); | 227 | rtc = rtc_device_register("ds1302", &pdev->dev, |
204 | if (unlikely(!rtc)) | ||
205 | return -ENOMEM; | ||
206 | |||
207 | spin_lock_init(&rtc->lock); | ||
208 | rtc->rtc_dev = rtc_device_register("ds1302", &pdev->dev, | ||
209 | &ds1302_rtc_ops, THIS_MODULE); | 228 | &ds1302_rtc_ops, THIS_MODULE); |
210 | if (IS_ERR(rtc->rtc_dev)) { | 229 | if (IS_ERR(rtc)) |
211 | ret = PTR_ERR(rtc->rtc_dev); | 230 | return PTR_ERR(rtc); |
212 | goto out; | ||
213 | } | ||
214 | 231 | ||
215 | platform_set_drvdata(pdev, rtc); | 232 | platform_set_drvdata(pdev, rtc); |
216 | 233 | ||
217 | return 0; | 234 | return 0; |
218 | out: | ||
219 | kfree(rtc); | ||
220 | return ret; | ||
221 | } | 235 | } |
222 | 236 | ||
223 | static int __devexit ds1302_rtc_remove(struct platform_device *pdev) | 237 | static int __devexit ds1302_rtc_remove(struct platform_device *pdev) |
224 | { | 238 | { |
225 | struct ds1302_rtc *rtc = platform_get_drvdata(pdev); | 239 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
226 | |||
227 | if (likely(rtc->rtc_dev)) | ||
228 | rtc_device_unregister(rtc->rtc_dev); | ||
229 | 240 | ||
241 | rtc_device_unregister(rtc); | ||
230 | platform_set_drvdata(pdev, NULL); | 242 | platform_set_drvdata(pdev, NULL); |
231 | 243 | ||
232 | kfree(rtc); | ||
233 | |||
234 | return 0; | 244 | return 0; |
235 | } | 245 | } |
236 | 246 | ||
@@ -239,13 +249,12 @@ static struct platform_driver ds1302_platform_driver = { | |||
239 | .name = DRV_NAME, | 249 | .name = DRV_NAME, |
240 | .owner = THIS_MODULE, | 250 | .owner = THIS_MODULE, |
241 | }, | 251 | }, |
242 | .probe = ds1302_rtc_probe, | ||
243 | .remove = __devexit_p(ds1302_rtc_remove), | 252 | .remove = __devexit_p(ds1302_rtc_remove), |
244 | }; | 253 | }; |
245 | 254 | ||
246 | static int __init ds1302_rtc_init(void) | 255 | static int __init ds1302_rtc_init(void) |
247 | { | 256 | { |
248 | return platform_driver_register(&ds1302_platform_driver); | 257 | return platform_driver_probe(&ds1302_platform_driver, ds1302_rtc_probe); |
249 | } | 258 | } |
250 | 259 | ||
251 | static void __exit ds1302_rtc_exit(void) | 260 | static void __exit ds1302_rtc_exit(void) |
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 8f410e59d9f5..077af1d7b9e4 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/bcd.h> | 13 | #include <linux/bcd.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/rtc.h> | 15 | #include <linux/rtc.h> |
15 | #include <linux/workqueue.h> | 16 | #include <linux/workqueue.h> |
16 | 17 | ||
@@ -541,7 +542,8 @@ static void msg_init(struct spi_message *m, struct spi_transfer *x, | |||
541 | } | 542 | } |
542 | 543 | ||
543 | static ssize_t | 544 | static ssize_t |
544 | ds1305_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | 545 | ds1305_nvram_read(struct file *filp, struct kobject *kobj, |
546 | struct bin_attribute *attr, | ||
545 | char *buf, loff_t off, size_t count) | 547 | char *buf, loff_t off, size_t count) |
546 | { | 548 | { |
547 | struct spi_device *spi; | 549 | struct spi_device *spi; |
@@ -571,7 +573,8 @@ ds1305_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | |||
571 | } | 573 | } |
572 | 574 | ||
573 | static ssize_t | 575 | static ssize_t |
574 | ds1305_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | 576 | ds1305_nvram_write(struct file *filp, struct kobject *kobj, |
577 | struct bin_attribute *attr, | ||
575 | char *buf, loff_t off, size_t count) | 578 | char *buf, loff_t off, size_t count) |
576 | { | 579 | { |
577 | struct spi_device *spi; | 580 | struct spi_device *spi; |
@@ -617,7 +620,6 @@ static struct bin_attribute nvram = { | |||
617 | static int __devinit ds1305_probe(struct spi_device *spi) | 620 | static int __devinit ds1305_probe(struct spi_device *spi) |
618 | { | 621 | { |
619 | struct ds1305 *ds1305; | 622 | struct ds1305 *ds1305; |
620 | struct rtc_device *rtc; | ||
621 | int status; | 623 | int status; |
622 | u8 addr, value; | 624 | u8 addr, value; |
623 | struct ds1305_platform_data *pdata = spi->dev.platform_data; | 625 | struct ds1305_platform_data *pdata = spi->dev.platform_data; |
@@ -756,14 +758,13 @@ static int __devinit ds1305_probe(struct spi_device *spi) | |||
756 | dev_dbg(&spi->dev, "AM/PM\n"); | 758 | dev_dbg(&spi->dev, "AM/PM\n"); |
757 | 759 | ||
758 | /* register RTC ... from here on, ds1305->ctrl needs locking */ | 760 | /* register RTC ... from here on, ds1305->ctrl needs locking */ |
759 | rtc = rtc_device_register("ds1305", &spi->dev, | 761 | ds1305->rtc = rtc_device_register("ds1305", &spi->dev, |
760 | &ds1305_ops, THIS_MODULE); | 762 | &ds1305_ops, THIS_MODULE); |
761 | if (IS_ERR(rtc)) { | 763 | if (IS_ERR(ds1305->rtc)) { |
762 | status = PTR_ERR(rtc); | 764 | status = PTR_ERR(ds1305->rtc); |
763 | dev_dbg(&spi->dev, "register rtc --> %d\n", status); | 765 | dev_dbg(&spi->dev, "register rtc --> %d\n", status); |
764 | goto fail0; | 766 | goto fail0; |
765 | } | 767 | } |
766 | ds1305->rtc = rtc; | ||
767 | 768 | ||
768 | /* Maybe set up alarm IRQ; be ready to handle it triggering right | 769 | /* Maybe set up alarm IRQ; be ready to handle it triggering right |
769 | * away. NOTE that we don't share this. The signal is active low, | 770 | * away. NOTE that we don't share this. The signal is active low, |
@@ -774,12 +775,14 @@ static int __devinit ds1305_probe(struct spi_device *spi) | |||
774 | if (spi->irq) { | 775 | if (spi->irq) { |
775 | INIT_WORK(&ds1305->work, ds1305_work); | 776 | INIT_WORK(&ds1305->work, ds1305_work); |
776 | status = request_irq(spi->irq, ds1305_irq, | 777 | status = request_irq(spi->irq, ds1305_irq, |
777 | 0, dev_name(&rtc->dev), ds1305); | 778 | 0, dev_name(&ds1305->rtc->dev), ds1305); |
778 | if (status < 0) { | 779 | if (status < 0) { |
779 | dev_dbg(&spi->dev, "request_irq %d --> %d\n", | 780 | dev_dbg(&spi->dev, "request_irq %d --> %d\n", |
780 | spi->irq, status); | 781 | spi->irq, status); |
781 | goto fail1; | 782 | goto fail1; |
782 | } | 783 | } |
784 | |||
785 | device_set_wakeup_capable(&spi->dev, 1); | ||
783 | } | 786 | } |
784 | 787 | ||
785 | /* export NVRAM */ | 788 | /* export NVRAM */ |
@@ -794,7 +797,7 @@ static int __devinit ds1305_probe(struct spi_device *spi) | |||
794 | fail2: | 797 | fail2: |
795 | free_irq(spi->irq, ds1305); | 798 | free_irq(spi->irq, ds1305); |
796 | fail1: | 799 | fail1: |
797 | rtc_device_unregister(rtc); | 800 | rtc_device_unregister(ds1305->rtc); |
798 | fail0: | 801 | fail0: |
799 | kfree(ds1305); | 802 | kfree(ds1305); |
800 | return status; | 803 | return status; |
@@ -802,7 +805,7 @@ fail0: | |||
802 | 805 | ||
803 | static int __devexit ds1305_remove(struct spi_device *spi) | 806 | static int __devexit ds1305_remove(struct spi_device *spi) |
804 | { | 807 | { |
805 | struct ds1305 *ds1305 = spi_get_drvdata(spi); | 808 | struct ds1305 *ds1305 = spi_get_drvdata(spi); |
806 | 809 | ||
807 | sysfs_remove_bin_file(&spi->dev.kobj, &nvram); | 810 | sysfs_remove_bin_file(&spi->dev.kobj, &nvram); |
808 | 811 | ||
@@ -810,7 +813,7 @@ static int __devexit ds1305_remove(struct spi_device *spi) | |||
810 | if (spi->irq) { | 813 | if (spi->irq) { |
811 | set_bit(FLAG_EXITING, &ds1305->flags); | 814 | set_bit(FLAG_EXITING, &ds1305->flags); |
812 | free_irq(spi->irq, ds1305); | 815 | free_irq(spi->irq, ds1305); |
813 | flush_scheduled_work(); | 816 | cancel_work_sync(&ds1305->work); |
814 | } | 817 | } |
815 | 818 | ||
816 | rtc_device_unregister(ds1305->rtc); | 819 | rtc_device_unregister(ds1305->rtc); |
@@ -841,3 +844,4 @@ module_exit(ds1305_exit); | |||
841 | 844 | ||
842 | MODULE_DESCRIPTION("RTC driver for DS1305 and DS1306 chips"); | 845 | MODULE_DESCRIPTION("RTC driver for DS1305 and DS1306 chips"); |
843 | MODULE_LICENSE("GPL"); | 846 | MODULE_LICENSE("GPL"); |
847 | MODULE_ALIAS("spi:rtc-ds1305"); | ||
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 47a93c022d91..0d559b6416dd 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
@@ -106,9 +106,9 @@ struct ds1307 { | |||
106 | struct i2c_client *client; | 106 | struct i2c_client *client; |
107 | struct rtc_device *rtc; | 107 | struct rtc_device *rtc; |
108 | struct work_struct work; | 108 | struct work_struct work; |
109 | s32 (*read_block_data)(struct i2c_client *client, u8 command, | 109 | s32 (*read_block_data)(const struct i2c_client *client, u8 command, |
110 | u8 length, u8 *values); | 110 | u8 length, u8 *values); |
111 | s32 (*write_block_data)(struct i2c_client *client, u8 command, | 111 | s32 (*write_block_data)(const struct i2c_client *client, u8 command, |
112 | u8 length, const u8 *values); | 112 | u8 length, const u8 *values); |
113 | }; | 113 | }; |
114 | 114 | ||
@@ -158,8 +158,8 @@ MODULE_DEVICE_TABLE(i2c, ds1307_id); | |||
158 | 158 | ||
159 | #define BLOCK_DATA_MAX_TRIES 10 | 159 | #define BLOCK_DATA_MAX_TRIES 10 |
160 | 160 | ||
161 | static s32 ds1307_read_block_data_once(struct i2c_client *client, u8 command, | 161 | static s32 ds1307_read_block_data_once(const struct i2c_client *client, |
162 | u8 length, u8 *values) | 162 | u8 command, u8 length, u8 *values) |
163 | { | 163 | { |
164 | s32 i, data; | 164 | s32 i, data; |
165 | 165 | ||
@@ -172,7 +172,7 @@ static s32 ds1307_read_block_data_once(struct i2c_client *client, u8 command, | |||
172 | return i; | 172 | return i; |
173 | } | 173 | } |
174 | 174 | ||
175 | static s32 ds1307_read_block_data(struct i2c_client *client, u8 command, | 175 | static s32 ds1307_read_block_data(const struct i2c_client *client, u8 command, |
176 | u8 length, u8 *values) | 176 | u8 length, u8 *values) |
177 | { | 177 | { |
178 | u8 oldvalues[I2C_SMBUS_BLOCK_MAX]; | 178 | u8 oldvalues[I2C_SMBUS_BLOCK_MAX]; |
@@ -198,7 +198,7 @@ static s32 ds1307_read_block_data(struct i2c_client *client, u8 command, | |||
198 | return length; | 198 | return length; |
199 | } | 199 | } |
200 | 200 | ||
201 | static s32 ds1307_write_block_data(struct i2c_client *client, u8 command, | 201 | static s32 ds1307_write_block_data(const struct i2c_client *client, u8 command, |
202 | u8 length, const u8 *values) | 202 | u8 length, const u8 *values) |
203 | { | 203 | { |
204 | u8 currvalues[I2C_SMBUS_BLOCK_MAX]; | 204 | u8 currvalues[I2C_SMBUS_BLOCK_MAX]; |
@@ -556,7 +556,8 @@ static const struct rtc_class_ops ds13xx_rtc_ops = { | |||
556 | #define NVRAM_SIZE 56 | 556 | #define NVRAM_SIZE 56 |
557 | 557 | ||
558 | static ssize_t | 558 | static ssize_t |
559 | ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | 559 | ds1307_nvram_read(struct file *filp, struct kobject *kobj, |
560 | struct bin_attribute *attr, | ||
560 | char *buf, loff_t off, size_t count) | 561 | char *buf, loff_t off, size_t count) |
561 | { | 562 | { |
562 | struct i2c_client *client; | 563 | struct i2c_client *client; |
@@ -580,7 +581,8 @@ ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | |||
580 | } | 581 | } |
581 | 582 | ||
582 | static ssize_t | 583 | static ssize_t |
583 | ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | 584 | ds1307_nvram_write(struct file *filp, struct kobject *kobj, |
585 | struct bin_attribute *attr, | ||
584 | char *buf, loff_t off, size_t count) | 586 | char *buf, loff_t off, size_t count) |
585 | { | 587 | { |
586 | struct i2c_client *client; | 588 | struct i2c_client *client; |
@@ -775,7 +777,7 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
775 | 777 | ||
776 | read_rtc: | 778 | read_rtc: |
777 | /* read RTC registers */ | 779 | /* read RTC registers */ |
778 | tmp = ds1307->read_block_data(ds1307->client, 0, 8, buf); | 780 | tmp = ds1307->read_block_data(ds1307->client, ds1307->offset, 8, buf); |
779 | if (tmp != 8) { | 781 | if (tmp != 8) { |
780 | pr_debug("read error %d\n", tmp); | 782 | pr_debug("read error %d\n", tmp); |
781 | err = -EIO; | 783 | err = -EIO; |
@@ -860,7 +862,7 @@ read_rtc: | |||
860 | if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM) | 862 | if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM) |
861 | tmp += 12; | 863 | tmp += 12; |
862 | i2c_smbus_write_byte_data(client, | 864 | i2c_smbus_write_byte_data(client, |
863 | DS1307_REG_HOUR, | 865 | ds1307->offset + DS1307_REG_HOUR, |
864 | bin2bcd(tmp)); | 866 | bin2bcd(tmp)); |
865 | } | 867 | } |
866 | 868 | ||
@@ -874,13 +876,15 @@ read_rtc: | |||
874 | } | 876 | } |
875 | 877 | ||
876 | if (want_irq) { | 878 | if (want_irq) { |
877 | err = request_irq(client->irq, ds1307_irq, 0, | 879 | err = request_irq(client->irq, ds1307_irq, IRQF_SHARED, |
878 | ds1307->rtc->name, client); | 880 | ds1307->rtc->name, client); |
879 | if (err) { | 881 | if (err) { |
880 | dev_err(&client->dev, | 882 | dev_err(&client->dev, |
881 | "unable to request IRQ!\n"); | 883 | "unable to request IRQ!\n"); |
882 | goto exit_irq; | 884 | goto exit_irq; |
883 | } | 885 | } |
886 | |||
887 | device_set_wakeup_capable(&client->dev, 1); | ||
884 | set_bit(HAS_ALARM, &ds1307->flags); | 888 | set_bit(HAS_ALARM, &ds1307->flags); |
885 | dev_dbg(&client->dev, "got IRQ %d\n", client->irq); | 889 | dev_dbg(&client->dev, "got IRQ %d\n", client->irq); |
886 | } | 890 | } |
@@ -896,8 +900,7 @@ read_rtc: | |||
896 | return 0; | 900 | return 0; |
897 | 901 | ||
898 | exit_irq: | 902 | exit_irq: |
899 | if (ds1307->rtc) | 903 | rtc_device_unregister(ds1307->rtc); |
900 | rtc_device_unregister(ds1307->rtc); | ||
901 | exit_free: | 904 | exit_free: |
902 | kfree(ds1307); | 905 | kfree(ds1307); |
903 | return err; | 906 | return err; |
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 32b27739ec2a..47fb6357c346 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/rtc.h> | 24 | #include <linux/rtc.h> |
25 | #include <linux/bcd.h> | 25 | #include <linux/bcd.h> |
26 | #include <linux/workqueue.h> | 26 | #include <linux/workqueue.h> |
27 | #include <linux/slab.h> | ||
27 | 28 | ||
28 | #define DS1374_REG_TOD0 0x00 /* Time of Day */ | 29 | #define DS1374_REG_TOD0 0x00 /* Time of Day */ |
29 | #define DS1374_REG_TOD1 0x01 | 30 | #define DS1374_REG_TOD1 0x01 |
@@ -283,7 +284,7 @@ static void ds1374_work(struct work_struct *work) | |||
283 | 284 | ||
284 | stat = i2c_smbus_read_byte_data(client, DS1374_REG_SR); | 285 | stat = i2c_smbus_read_byte_data(client, DS1374_REG_SR); |
285 | if (stat < 0) | 286 | if (stat < 0) |
286 | return; | 287 | goto unlock; |
287 | 288 | ||
288 | if (stat & DS1374_REG_SR_AF) { | 289 | if (stat & DS1374_REG_SR_AF) { |
289 | stat &= ~DS1374_REG_SR_AF; | 290 | stat &= ~DS1374_REG_SR_AF; |
@@ -302,7 +303,7 @@ static void ds1374_work(struct work_struct *work) | |||
302 | out: | 303 | out: |
303 | if (!ds1374->exiting) | 304 | if (!ds1374->exiting) |
304 | enable_irq(client->irq); | 305 | enable_irq(client->irq); |
305 | 306 | unlock: | |
306 | mutex_unlock(&ds1374->mutex); | 307 | mutex_unlock(&ds1374->mutex); |
307 | } | 308 | } |
308 | 309 | ||
@@ -383,6 +384,8 @@ static int ds1374_probe(struct i2c_client *client, | |||
383 | dev_err(&client->dev, "unable to request IRQ\n"); | 384 | dev_err(&client->dev, "unable to request IRQ\n"); |
384 | goto out_free; | 385 | goto out_free; |
385 | } | 386 | } |
387 | |||
388 | device_set_wakeup_capable(&client->dev, 1); | ||
386 | } | 389 | } |
387 | 390 | ||
388 | ds1374->rtc = rtc_device_register(client->name, &client->dev, | 391 | ds1374->rtc = rtc_device_register(client->name, &client->dev, |
@@ -400,7 +403,6 @@ out_irq: | |||
400 | free_irq(client->irq, client); | 403 | free_irq(client->irq, client); |
401 | 404 | ||
402 | out_free: | 405 | out_free: |
403 | i2c_set_clientdata(client, NULL); | ||
404 | kfree(ds1374); | 406 | kfree(ds1374); |
405 | return ret; | 407 | return ret; |
406 | } | 408 | } |
@@ -415,11 +417,10 @@ static int __devexit ds1374_remove(struct i2c_client *client) | |||
415 | mutex_unlock(&ds1374->mutex); | 417 | mutex_unlock(&ds1374->mutex); |
416 | 418 | ||
417 | free_irq(client->irq, client); | 419 | free_irq(client->irq, client); |
418 | flush_scheduled_work(); | 420 | cancel_work_sync(&ds1374->work); |
419 | } | 421 | } |
420 | 422 | ||
421 | rtc_device_unregister(ds1374->rtc); | 423 | rtc_device_unregister(ds1374->rtc); |
422 | i2c_set_clientdata(client, NULL); | ||
423 | kfree(ds1374); | 424 | kfree(ds1374); |
424 | return 0; | 425 | return 0; |
425 | } | 426 | } |
diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c index e01b955db077..26a86d235051 100644 --- a/drivers/rtc/rtc-ds1390.c +++ b/drivers/rtc/rtc-ds1390.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/rtc.h> | 19 | #include <linux/rtc.h> |
20 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
21 | #include <linux/bcd.h> | 21 | #include <linux/bcd.h> |
22 | #include <linux/slab.h> | ||
22 | 23 | ||
23 | #define DS1390_REG_100THS 0x00 | 24 | #define DS1390_REG_100THS 0x00 |
24 | #define DS1390_REG_SECONDS 0x01 | 25 | #define DS1390_REG_SECONDS 0x01 |
@@ -189,3 +190,4 @@ module_exit(ds1390_exit); | |||
189 | MODULE_DESCRIPTION("Dallas/Maxim DS1390/93/94 SPI RTC driver"); | 190 | MODULE_DESCRIPTION("Dallas/Maxim DS1390/93/94 SPI RTC driver"); |
190 | MODULE_AUTHOR("Mark Jackson <mpfj@mimc.co.uk>"); | 191 | MODULE_AUTHOR("Mark Jackson <mpfj@mimc.co.uk>"); |
191 | MODULE_LICENSE("GPL"); | 192 | MODULE_LICENSE("GPL"); |
193 | MODULE_ALIAS("spi:rtc-ds1390"); | ||
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 0b6b7730c716..37268e97de49 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * An rtc driver for the Dallas DS1511 | 2 | * An rtc driver for the Dallas DS1511 |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 4 | * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> |
5 | * Copyright (C) 2007 Andrew Sharp <andy.sharp@onstor.com> | 5 | * Copyright (C) 2007 Andrew Sharp <andy.sharp@lsi.com> |
6 | * | 6 | * |
7 | * 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 |
8 | * 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 |
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/bcd.h> | 17 | #include <linux/bcd.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/gfp.h> | ||
20 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
21 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
22 | #include <linux/rtc.h> | 23 | #include <linux/rtc.h> |
@@ -87,7 +88,6 @@ enum ds1511reg { | |||
87 | struct rtc_plat_data { | 88 | struct rtc_plat_data { |
88 | struct rtc_device *rtc; | 89 | struct rtc_device *rtc; |
89 | void __iomem *ioaddr; /* virtual base address */ | 90 | void __iomem *ioaddr; /* virtual base address */ |
90 | unsigned long baseaddr; /* physical base address */ | ||
91 | int size; /* amount of memory mapped */ | 91 | int size; /* amount of memory mapped */ |
92 | int irq; | 92 | int irq; |
93 | unsigned int irqen; | 93 | unsigned int irqen; |
@@ -95,6 +95,7 @@ struct rtc_plat_data { | |||
95 | int alrm_min; | 95 | int alrm_min; |
96 | int alrm_hour; | 96 | int alrm_hour; |
97 | int alrm_mday; | 97 | int alrm_mday; |
98 | spinlock_t lock; | ||
98 | }; | 99 | }; |
99 | 100 | ||
100 | static DEFINE_SPINLOCK(ds1511_lock); | 101 | static DEFINE_SPINLOCK(ds1511_lock); |
@@ -302,7 +303,7 @@ ds1511_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
302 | { | 303 | { |
303 | unsigned long flags; | 304 | unsigned long flags; |
304 | 305 | ||
305 | spin_lock_irqsave(&pdata->rtc->irq_lock, flags); | 306 | spin_lock_irqsave(&pdata->lock, flags); |
306 | rtc_write(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? | 307 | rtc_write(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? |
307 | 0x80 : bin2bcd(pdata->alrm_mday) & 0x3f, | 308 | 0x80 : bin2bcd(pdata->alrm_mday) & 0x3f, |
308 | RTC_ALARM_DATE); | 309 | RTC_ALARM_DATE); |
@@ -317,7 +318,7 @@ ds1511_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
317 | RTC_ALARM_SEC); | 318 | RTC_ALARM_SEC); |
318 | rtc_write(rtc_read(RTC_CMD) | (pdata->irqen ? RTC_TIE : 0), RTC_CMD); | 319 | rtc_write(rtc_read(RTC_CMD) | (pdata->irqen ? RTC_TIE : 0), RTC_CMD); |
319 | rtc_read(RTC_CMD1); /* clear interrupts */ | 320 | rtc_read(RTC_CMD1); /* clear interrupts */ |
320 | spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags); | 321 | spin_unlock_irqrestore(&pdata->lock, flags); |
321 | } | 322 | } |
322 | 323 | ||
323 | static int | 324 | static int |
@@ -362,66 +363,69 @@ ds1511_interrupt(int irq, void *dev_id) | |||
362 | { | 363 | { |
363 | struct platform_device *pdev = dev_id; | 364 | struct platform_device *pdev = dev_id; |
364 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 365 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
365 | unsigned long events = RTC_IRQF; | 366 | unsigned long events = 0; |
366 | 367 | ||
368 | spin_lock(&pdata->lock); | ||
367 | /* | 369 | /* |
368 | * read and clear interrupt | 370 | * read and clear interrupt |
369 | */ | 371 | */ |
370 | if (!(rtc_read(RTC_CMD1) & DS1511_IRQF)) { | 372 | if (rtc_read(RTC_CMD1) & DS1511_IRQF) { |
371 | return IRQ_NONE; | 373 | events = RTC_IRQF; |
372 | } | 374 | if (rtc_read(RTC_ALARM_SEC) & 0x80) |
373 | if (rtc_read(RTC_ALARM_SEC) & 0x80) { | 375 | events |= RTC_UF; |
374 | events |= RTC_UF; | 376 | else |
375 | } else { | 377 | events |= RTC_AF; |
376 | events |= RTC_AF; | 378 | if (likely(pdata->rtc)) |
377 | } | 379 | rtc_update_irq(pdata->rtc, 1, events); |
378 | rtc_update_irq(pdata->rtc, 1, events); | 380 | } |
379 | return IRQ_HANDLED; | 381 | spin_unlock(&pdata->lock); |
382 | return events ? IRQ_HANDLED : IRQ_NONE; | ||
380 | } | 383 | } |
381 | 384 | ||
382 | static int | 385 | static int ds1511_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
383 | ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
384 | { | 386 | { |
385 | struct platform_device *pdev = to_platform_device(dev); | 387 | struct platform_device *pdev = to_platform_device(dev); |
386 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 388 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
387 | 389 | ||
388 | if (pdata->irq <= 0) { | 390 | if (pdata->irq <= 0) |
389 | return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ | 391 | return -EINVAL; |
390 | } | 392 | if (enabled) |
391 | switch (cmd) { | ||
392 | case RTC_AIE_OFF: | ||
393 | pdata->irqen &= ~RTC_AF; | ||
394 | ds1511_rtc_update_alarm(pdata); | ||
395 | break; | ||
396 | case RTC_AIE_ON: | ||
397 | pdata->irqen |= RTC_AF; | 393 | pdata->irqen |= RTC_AF; |
398 | ds1511_rtc_update_alarm(pdata); | 394 | else |
399 | break; | 395 | pdata->irqen &= ~RTC_AF; |
400 | case RTC_UIE_OFF: | 396 | ds1511_rtc_update_alarm(pdata); |
401 | pdata->irqen &= ~RTC_UF; | 397 | return 0; |
402 | ds1511_rtc_update_alarm(pdata); | 398 | } |
403 | break; | 399 | |
404 | case RTC_UIE_ON: | 400 | static int ds1511_rtc_update_irq_enable(struct device *dev, |
401 | unsigned int enabled) | ||
402 | { | ||
403 | struct platform_device *pdev = to_platform_device(dev); | ||
404 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
405 | |||
406 | if (pdata->irq <= 0) | ||
407 | return -EINVAL; | ||
408 | if (enabled) | ||
405 | pdata->irqen |= RTC_UF; | 409 | pdata->irqen |= RTC_UF; |
406 | ds1511_rtc_update_alarm(pdata); | 410 | else |
407 | break; | 411 | pdata->irqen &= ~RTC_UF; |
408 | default: | 412 | ds1511_rtc_update_alarm(pdata); |
409 | return -ENOIOCTLCMD; | ||
410 | } | ||
411 | return 0; | 413 | return 0; |
412 | } | 414 | } |
413 | 415 | ||
414 | static const struct rtc_class_ops ds1511_rtc_ops = { | 416 | static const struct rtc_class_ops ds1511_rtc_ops = { |
415 | .read_time = ds1511_rtc_read_time, | 417 | .read_time = ds1511_rtc_read_time, |
416 | .set_time = ds1511_rtc_set_time, | 418 | .set_time = ds1511_rtc_set_time, |
417 | .read_alarm = ds1511_rtc_read_alarm, | 419 | .read_alarm = ds1511_rtc_read_alarm, |
418 | .set_alarm = ds1511_rtc_set_alarm, | 420 | .set_alarm = ds1511_rtc_set_alarm, |
419 | .ioctl = ds1511_rtc_ioctl, | 421 | .alarm_irq_enable = ds1511_rtc_alarm_irq_enable, |
422 | .update_irq_enable = ds1511_rtc_update_irq_enable, | ||
420 | }; | 423 | }; |
421 | 424 | ||
422 | static ssize_t | 425 | static ssize_t |
423 | ds1511_nvram_read(struct kobject *kobj, struct bin_attribute *ba, | 426 | ds1511_nvram_read(struct file *filp, struct kobject *kobj, |
424 | char *buf, loff_t pos, size_t size) | 427 | struct bin_attribute *ba, |
428 | char *buf, loff_t pos, size_t size) | ||
425 | { | 429 | { |
426 | ssize_t count; | 430 | ssize_t count; |
427 | 431 | ||
@@ -449,8 +453,9 @@ ds1511_nvram_read(struct kobject *kobj, struct bin_attribute *ba, | |||
449 | } | 453 | } |
450 | 454 | ||
451 | static ssize_t | 455 | static ssize_t |
452 | ds1511_nvram_write(struct kobject *kobj, struct bin_attribute *bin_attr, | 456 | ds1511_nvram_write(struct file *filp, struct kobject *kobj, |
453 | char *buf, loff_t pos, size_t size) | 457 | struct bin_attribute *bin_attr, |
458 | char *buf, loff_t pos, size_t size) | ||
454 | { | 459 | { |
455 | ssize_t count; | 460 | ssize_t count; |
456 | 461 | ||
@@ -492,29 +497,23 @@ ds1511_rtc_probe(struct platform_device *pdev) | |||
492 | { | 497 | { |
493 | struct rtc_device *rtc; | 498 | struct rtc_device *rtc; |
494 | struct resource *res; | 499 | struct resource *res; |
495 | struct rtc_plat_data *pdata = NULL; | 500 | struct rtc_plat_data *pdata; |
496 | int ret = 0; | 501 | int ret = 0; |
497 | 502 | ||
498 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 503 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
499 | if (!res) { | 504 | if (!res) { |
500 | return -ENODEV; | 505 | return -ENODEV; |
501 | } | 506 | } |
502 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 507 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
503 | if (!pdata) { | 508 | if (!pdata) |
504 | return -ENOMEM; | 509 | return -ENOMEM; |
505 | } | ||
506 | pdata->size = res->end - res->start + 1; | 510 | pdata->size = res->end - res->start + 1; |
507 | if (!request_mem_region(res->start, pdata->size, pdev->name)) { | 511 | if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size, |
508 | ret = -EBUSY; | 512 | pdev->name)) |
509 | goto out; | 513 | return -EBUSY; |
510 | } | 514 | ds1511_base = devm_ioremap(&pdev->dev, res->start, pdata->size); |
511 | pdata->baseaddr = res->start; | 515 | if (!ds1511_base) |
512 | pdata->size = pdata->size; | 516 | return -ENOMEM; |
513 | ds1511_base = ioremap(pdata->baseaddr, pdata->size); | ||
514 | if (!ds1511_base) { | ||
515 | ret = -ENOMEM; | ||
516 | goto out; | ||
517 | } | ||
518 | pdata->ioaddr = ds1511_base; | 517 | pdata->ioaddr = ds1511_base; |
519 | pdata->irq = platform_get_irq(pdev, 0); | 518 | pdata->irq = platform_get_irq(pdev, 0); |
520 | 519 | ||
@@ -540,13 +539,15 @@ ds1511_rtc_probe(struct platform_device *pdev) | |||
540 | dev_warn(&pdev->dev, "voltage-low detected.\n"); | 539 | dev_warn(&pdev->dev, "voltage-low detected.\n"); |
541 | } | 540 | } |
542 | 541 | ||
542 | spin_lock_init(&pdata->lock); | ||
543 | platform_set_drvdata(pdev, pdata); | ||
543 | /* | 544 | /* |
544 | * if the platform has an interrupt in mind for this device, | 545 | * if the platform has an interrupt in mind for this device, |
545 | * then by all means, set it | 546 | * then by all means, set it |
546 | */ | 547 | */ |
547 | if (pdata->irq > 0) { | 548 | if (pdata->irq > 0) { |
548 | rtc_read(RTC_CMD1); | 549 | rtc_read(RTC_CMD1); |
549 | if (request_irq(pdata->irq, ds1511_interrupt, | 550 | if (devm_request_irq(&pdev->dev, pdata->irq, ds1511_interrupt, |
550 | IRQF_DISABLED | IRQF_SHARED, pdev->name, pdev) < 0) { | 551 | IRQF_DISABLED | IRQF_SHARED, pdev->name, pdev) < 0) { |
551 | 552 | ||
552 | dev_warn(&pdev->dev, "interrupt not available.\n"); | 553 | dev_warn(&pdev->dev, "interrupt not available.\n"); |
@@ -556,33 +557,13 @@ ds1511_rtc_probe(struct platform_device *pdev) | |||
556 | 557 | ||
557 | rtc = rtc_device_register(pdev->name, &pdev->dev, &ds1511_rtc_ops, | 558 | rtc = rtc_device_register(pdev->name, &pdev->dev, &ds1511_rtc_ops, |
558 | THIS_MODULE); | 559 | THIS_MODULE); |
559 | if (IS_ERR(rtc)) { | 560 | if (IS_ERR(rtc)) |
560 | ret = PTR_ERR(rtc); | 561 | return PTR_ERR(rtc); |
561 | goto out; | ||
562 | } | ||
563 | pdata->rtc = rtc; | 562 | pdata->rtc = rtc; |
564 | platform_set_drvdata(pdev, pdata); | 563 | |
565 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); | 564 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); |
566 | if (ret) { | 565 | if (ret) |
567 | goto out; | ||
568 | } | ||
569 | return 0; | ||
570 | out: | ||
571 | if (pdata->rtc) { | ||
572 | rtc_device_unregister(pdata->rtc); | 566 | rtc_device_unregister(pdata->rtc); |
573 | } | ||
574 | if (pdata->irq > 0) { | ||
575 | free_irq(pdata->irq, pdev); | ||
576 | } | ||
577 | if (ds1511_base) { | ||
578 | iounmap(ds1511_base); | ||
579 | ds1511_base = NULL; | ||
580 | } | ||
581 | if (pdata->baseaddr) { | ||
582 | release_mem_region(pdata->baseaddr, pdata->size); | ||
583 | } | ||
584 | |||
585 | kfree(pdata); | ||
586 | return ret; | 567 | return ret; |
587 | } | 568 | } |
588 | 569 | ||
@@ -593,19 +574,13 @@ ds1511_rtc_remove(struct platform_device *pdev) | |||
593 | 574 | ||
594 | sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); | 575 | sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); |
595 | rtc_device_unregister(pdata->rtc); | 576 | rtc_device_unregister(pdata->rtc); |
596 | pdata->rtc = NULL; | ||
597 | if (pdata->irq > 0) { | 577 | if (pdata->irq > 0) { |
598 | /* | 578 | /* |
599 | * disable the alarm interrupt | 579 | * disable the alarm interrupt |
600 | */ | 580 | */ |
601 | rtc_write(rtc_read(RTC_CMD) & ~RTC_TIE, RTC_CMD); | 581 | rtc_write(rtc_read(RTC_CMD) & ~RTC_TIE, RTC_CMD); |
602 | rtc_read(RTC_CMD1); | 582 | rtc_read(RTC_CMD1); |
603 | free_irq(pdata->irq, pdev); | ||
604 | } | 583 | } |
605 | iounmap(pdata->ioaddr); | ||
606 | ds1511_base = NULL; | ||
607 | release_mem_region(pdata->baseaddr, pdata->size); | ||
608 | kfree(pdata); | ||
609 | return 0; | 584 | return 0; |
610 | } | 585 | } |
611 | 586 | ||
@@ -636,7 +611,7 @@ ds1511_rtc_exit(void) | |||
636 | module_init(ds1511_rtc_init); | 611 | module_init(ds1511_rtc_init); |
637 | module_exit(ds1511_rtc_exit); | 612 | module_exit(ds1511_rtc_exit); |
638 | 613 | ||
639 | MODULE_AUTHOR("Andrew Sharp <andy.sharp@onstor.com>"); | 614 | MODULE_AUTHOR("Andrew Sharp <andy.sharp@lsi.com>"); |
640 | MODULE_DESCRIPTION("Dallas DS1511 RTC driver"); | 615 | MODULE_DESCRIPTION("Dallas DS1511 RTC driver"); |
641 | MODULE_LICENSE("GPL"); | 616 | MODULE_LICENSE("GPL"); |
642 | MODULE_VERSION(DRV_VERSION); | 617 | MODULE_VERSION(DRV_VERSION); |
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 717288527c6b..ff432e2ca275 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/bcd.h> | 11 | #include <linux/bcd.h> |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/gfp.h> | ||
14 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
15 | #include <linux/jiffies.h> | 16 | #include <linux/jiffies.h> |
16 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
@@ -18,7 +19,7 @@ | |||
18 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
19 | #include <linux/io.h> | 20 | #include <linux/io.h> |
20 | 21 | ||
21 | #define DRV_VERSION "0.2" | 22 | #define DRV_VERSION "0.3" |
22 | 23 | ||
23 | #define RTC_REG_SIZE 0x2000 | 24 | #define RTC_REG_SIZE 0x2000 |
24 | #define RTC_OFFSET 0x1ff0 | 25 | #define RTC_OFFSET 0x1ff0 |
@@ -61,7 +62,6 @@ | |||
61 | struct rtc_plat_data { | 62 | struct rtc_plat_data { |
62 | struct rtc_device *rtc; | 63 | struct rtc_device *rtc; |
63 | void __iomem *ioaddr; | 64 | void __iomem *ioaddr; |
64 | resource_size_t baseaddr; | ||
65 | unsigned long last_jiffies; | 65 | unsigned long last_jiffies; |
66 | int irq; | 66 | int irq; |
67 | unsigned int irqen; | 67 | unsigned int irqen; |
@@ -69,6 +69,7 @@ struct rtc_plat_data { | |||
69 | int alrm_min; | 69 | int alrm_min; |
70 | int alrm_hour; | 70 | int alrm_hour; |
71 | int alrm_mday; | 71 | int alrm_mday; |
72 | spinlock_t lock; | ||
72 | }; | 73 | }; |
73 | 74 | ||
74 | static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm) | 75 | static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm) |
@@ -139,7 +140,7 @@ static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
139 | void __iomem *ioaddr = pdata->ioaddr; | 140 | void __iomem *ioaddr = pdata->ioaddr; |
140 | unsigned long flags; | 141 | unsigned long flags; |
141 | 142 | ||
142 | spin_lock_irqsave(&pdata->rtc->irq_lock, flags); | 143 | spin_lock_irqsave(&pdata->lock, flags); |
143 | writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? | 144 | writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? |
144 | 0x80 : bin2bcd(pdata->alrm_mday), | 145 | 0x80 : bin2bcd(pdata->alrm_mday), |
145 | ioaddr + RTC_DATE_ALARM); | 146 | ioaddr + RTC_DATE_ALARM); |
@@ -154,7 +155,7 @@ static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
154 | ioaddr + RTC_SECONDS_ALARM); | 155 | ioaddr + RTC_SECONDS_ALARM); |
155 | writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS); | 156 | writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS); |
156 | readb(ioaddr + RTC_FLAGS); /* clear interrupts */ | 157 | readb(ioaddr + RTC_FLAGS); /* clear interrupts */ |
157 | spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags); | 158 | spin_unlock_irqrestore(&pdata->lock, flags); |
158 | } | 159 | } |
159 | 160 | ||
160 | static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 161 | static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
@@ -194,64 +195,69 @@ static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id) | |||
194 | struct platform_device *pdev = dev_id; | 195 | struct platform_device *pdev = dev_id; |
195 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 196 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
196 | void __iomem *ioaddr = pdata->ioaddr; | 197 | void __iomem *ioaddr = pdata->ioaddr; |
197 | unsigned long events = RTC_IRQF; | 198 | unsigned long events = 0; |
198 | 199 | ||
200 | spin_lock(&pdata->lock); | ||
199 | /* read and clear interrupt */ | 201 | /* read and clear interrupt */ |
200 | if (!(readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF)) | 202 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF) { |
201 | return IRQ_NONE; | 203 | events = RTC_IRQF; |
202 | if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80) | 204 | if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80) |
203 | events |= RTC_UF; | 205 | events |= RTC_UF; |
204 | else | 206 | else |
205 | events |= RTC_AF; | 207 | events |= RTC_AF; |
206 | rtc_update_irq(pdata->rtc, 1, events); | 208 | if (likely(pdata->rtc)) |
207 | return IRQ_HANDLED; | 209 | rtc_update_irq(pdata->rtc, 1, events); |
210 | } | ||
211 | spin_unlock(&pdata->lock); | ||
212 | return events ? IRQ_HANDLED : IRQ_NONE; | ||
208 | } | 213 | } |
209 | 214 | ||
210 | static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd, | 215 | static int ds1553_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
211 | unsigned long arg) | ||
212 | { | 216 | { |
213 | struct platform_device *pdev = to_platform_device(dev); | 217 | struct platform_device *pdev = to_platform_device(dev); |
214 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 218 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
215 | 219 | ||
216 | if (pdata->irq <= 0) | 220 | if (pdata->irq <= 0) |
217 | return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ | 221 | return -EINVAL; |
218 | switch (cmd) { | 222 | if (enabled) |
219 | case RTC_AIE_OFF: | ||
220 | pdata->irqen &= ~RTC_AF; | ||
221 | ds1553_rtc_update_alarm(pdata); | ||
222 | break; | ||
223 | case RTC_AIE_ON: | ||
224 | pdata->irqen |= RTC_AF; | 223 | pdata->irqen |= RTC_AF; |
225 | ds1553_rtc_update_alarm(pdata); | 224 | else |
226 | break; | 225 | pdata->irqen &= ~RTC_AF; |
227 | case RTC_UIE_OFF: | 226 | ds1553_rtc_update_alarm(pdata); |
228 | pdata->irqen &= ~RTC_UF; | 227 | return 0; |
229 | ds1553_rtc_update_alarm(pdata); | 228 | } |
230 | break; | 229 | |
231 | case RTC_UIE_ON: | 230 | static int ds1553_rtc_update_irq_enable(struct device *dev, |
231 | unsigned int enabled) | ||
232 | { | ||
233 | struct platform_device *pdev = to_platform_device(dev); | ||
234 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
235 | |||
236 | if (pdata->irq <= 0) | ||
237 | return -EINVAL; | ||
238 | if (enabled) | ||
232 | pdata->irqen |= RTC_UF; | 239 | pdata->irqen |= RTC_UF; |
233 | ds1553_rtc_update_alarm(pdata); | 240 | else |
234 | break; | 241 | pdata->irqen &= ~RTC_UF; |
235 | default: | 242 | ds1553_rtc_update_alarm(pdata); |
236 | return -ENOIOCTLCMD; | ||
237 | } | ||
238 | return 0; | 243 | return 0; |
239 | } | 244 | } |
240 | 245 | ||
241 | static const struct rtc_class_ops ds1553_rtc_ops = { | 246 | static const struct rtc_class_ops ds1553_rtc_ops = { |
242 | .read_time = ds1553_rtc_read_time, | 247 | .read_time = ds1553_rtc_read_time, |
243 | .set_time = ds1553_rtc_set_time, | 248 | .set_time = ds1553_rtc_set_time, |
244 | .read_alarm = ds1553_rtc_read_alarm, | 249 | .read_alarm = ds1553_rtc_read_alarm, |
245 | .set_alarm = ds1553_rtc_set_alarm, | 250 | .set_alarm = ds1553_rtc_set_alarm, |
246 | .ioctl = ds1553_rtc_ioctl, | 251 | .alarm_irq_enable = ds1553_rtc_alarm_irq_enable, |
252 | .update_irq_enable = ds1553_rtc_update_irq_enable, | ||
247 | }; | 253 | }; |
248 | 254 | ||
249 | static ssize_t ds1553_nvram_read(struct kobject *kobj, | 255 | static ssize_t ds1553_nvram_read(struct file *filp, struct kobject *kobj, |
250 | struct bin_attribute *bin_attr, | 256 | struct bin_attribute *bin_attr, |
251 | char *buf, loff_t pos, size_t size) | 257 | char *buf, loff_t pos, size_t size) |
252 | { | 258 | { |
253 | struct platform_device *pdev = | 259 | struct device *dev = container_of(kobj, struct device, kobj); |
254 | to_platform_device(container_of(kobj, struct device, kobj)); | 260 | struct platform_device *pdev = to_platform_device(dev); |
255 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 261 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
256 | void __iomem *ioaddr = pdata->ioaddr; | 262 | void __iomem *ioaddr = pdata->ioaddr; |
257 | ssize_t count; | 263 | ssize_t count; |
@@ -261,12 +267,12 @@ static ssize_t ds1553_nvram_read(struct kobject *kobj, | |||
261 | return count; | 267 | return count; |
262 | } | 268 | } |
263 | 269 | ||
264 | static ssize_t ds1553_nvram_write(struct kobject *kobj, | 270 | static ssize_t ds1553_nvram_write(struct file *filp, struct kobject *kobj, |
265 | struct bin_attribute *bin_attr, | 271 | struct bin_attribute *bin_attr, |
266 | char *buf, loff_t pos, size_t size) | 272 | char *buf, loff_t pos, size_t size) |
267 | { | 273 | { |
268 | struct platform_device *pdev = | 274 | struct device *dev = container_of(kobj, struct device, kobj); |
269 | to_platform_device(container_of(kobj, struct device, kobj)); | 275 | struct platform_device *pdev = to_platform_device(dev); |
270 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 276 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
271 | void __iomem *ioaddr = pdata->ioaddr; | 277 | void __iomem *ioaddr = pdata->ioaddr; |
272 | ssize_t count; | 278 | ssize_t count; |
@@ -291,26 +297,23 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev) | |||
291 | struct rtc_device *rtc; | 297 | struct rtc_device *rtc; |
292 | struct resource *res; | 298 | struct resource *res; |
293 | unsigned int cen, sec; | 299 | unsigned int cen, sec; |
294 | struct rtc_plat_data *pdata = NULL; | 300 | struct rtc_plat_data *pdata; |
295 | void __iomem *ioaddr = NULL; | 301 | void __iomem *ioaddr; |
296 | int ret = 0; | 302 | int ret = 0; |
297 | 303 | ||
298 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 304 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
299 | if (!res) | 305 | if (!res) |
300 | return -ENODEV; | 306 | return -ENODEV; |
301 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 307 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
302 | if (!pdata) | 308 | if (!pdata) |
303 | return -ENOMEM; | 309 | return -ENOMEM; |
304 | if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) { | 310 | if (!devm_request_mem_region(&pdev->dev, res->start, RTC_REG_SIZE, |
305 | ret = -EBUSY; | 311 | pdev->name)) |
306 | goto out; | 312 | return -EBUSY; |
307 | } | 313 | |
308 | pdata->baseaddr = res->start; | 314 | ioaddr = devm_ioremap(&pdev->dev, res->start, RTC_REG_SIZE); |
309 | ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE); | 315 | if (!ioaddr) |
310 | if (!ioaddr) { | 316 | return -ENOMEM; |
311 | ret = -ENOMEM; | ||
312 | goto out; | ||
313 | } | ||
314 | pdata->ioaddr = ioaddr; | 317 | pdata->ioaddr = ioaddr; |
315 | pdata->irq = platform_get_irq(pdev, 0); | 318 | pdata->irq = platform_get_irq(pdev, 0); |
316 | 319 | ||
@@ -326,9 +329,13 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev) | |||
326 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_BLF) | 329 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_BLF) |
327 | dev_warn(&pdev->dev, "voltage-low detected.\n"); | 330 | dev_warn(&pdev->dev, "voltage-low detected.\n"); |
328 | 331 | ||
332 | spin_lock_init(&pdata->lock); | ||
333 | pdata->last_jiffies = jiffies; | ||
334 | platform_set_drvdata(pdev, pdata); | ||
329 | if (pdata->irq > 0) { | 335 | if (pdata->irq > 0) { |
330 | writeb(0, ioaddr + RTC_INTERRUPTS); | 336 | writeb(0, ioaddr + RTC_INTERRUPTS); |
331 | if (request_irq(pdata->irq, ds1553_rtc_interrupt, | 337 | if (devm_request_irq(&pdev->dev, pdata->irq, |
338 | ds1553_rtc_interrupt, | ||
332 | IRQF_DISABLED, pdev->name, pdev) < 0) { | 339 | IRQF_DISABLED, pdev->name, pdev) < 0) { |
333 | dev_warn(&pdev->dev, "interrupt not available.\n"); | 340 | dev_warn(&pdev->dev, "interrupt not available.\n"); |
334 | pdata->irq = 0; | 341 | pdata->irq = 0; |
@@ -337,27 +344,13 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev) | |||
337 | 344 | ||
338 | rtc = rtc_device_register(pdev->name, &pdev->dev, | 345 | rtc = rtc_device_register(pdev->name, &pdev->dev, |
339 | &ds1553_rtc_ops, THIS_MODULE); | 346 | &ds1553_rtc_ops, THIS_MODULE); |
340 | if (IS_ERR(rtc)) { | 347 | if (IS_ERR(rtc)) |
341 | ret = PTR_ERR(rtc); | 348 | return PTR_ERR(rtc); |
342 | goto out; | ||
343 | } | ||
344 | pdata->rtc = rtc; | 349 | pdata->rtc = rtc; |
345 | pdata->last_jiffies = jiffies; | 350 | |
346 | platform_set_drvdata(pdev, pdata); | ||
347 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); | 351 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); |
348 | if (ret) | 352 | if (ret) |
349 | goto out; | 353 | rtc_device_unregister(rtc); |
350 | return 0; | ||
351 | out: | ||
352 | if (pdata->rtc) | ||
353 | rtc_device_unregister(pdata->rtc); | ||
354 | if (pdata->irq > 0) | ||
355 | free_irq(pdata->irq, pdev); | ||
356 | if (ioaddr) | ||
357 | iounmap(ioaddr); | ||
358 | if (pdata->baseaddr) | ||
359 | release_mem_region(pdata->baseaddr, RTC_REG_SIZE); | ||
360 | kfree(pdata); | ||
361 | return ret; | 354 | return ret; |
362 | } | 355 | } |
363 | 356 | ||
@@ -367,13 +360,8 @@ static int __devexit ds1553_rtc_remove(struct platform_device *pdev) | |||
367 | 360 | ||
368 | sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); | 361 | sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); |
369 | rtc_device_unregister(pdata->rtc); | 362 | rtc_device_unregister(pdata->rtc); |
370 | if (pdata->irq > 0) { | 363 | if (pdata->irq > 0) |
371 | writeb(0, pdata->ioaddr + RTC_INTERRUPTS); | 364 | writeb(0, pdata->ioaddr + RTC_INTERRUPTS); |
372 | free_irq(pdata->irq, pdev); | ||
373 | } | ||
374 | iounmap(pdata->ioaddr); | ||
375 | release_mem_region(pdata->baseaddr, RTC_REG_SIZE); | ||
376 | kfree(pdata); | ||
377 | return 0; | 365 | return 0; |
378 | } | 366 | } |
379 | 367 | ||
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 09249459e9a4..042630c90dd3 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
@@ -15,13 +15,14 @@ | |||
15 | #include <linux/bcd.h> | 15 | #include <linux/bcd.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/gfp.h> | ||
18 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
19 | #include <linux/jiffies.h> | 20 | #include <linux/jiffies.h> |
20 | #include <linux/rtc.h> | 21 | #include <linux/rtc.h> |
21 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
22 | #include <linux/io.h> | 23 | #include <linux/io.h> |
23 | 24 | ||
24 | #define DRV_VERSION "0.3" | 25 | #define DRV_VERSION "0.4" |
25 | 26 | ||
26 | #define RTC_SIZE 8 | 27 | #define RTC_SIZE 8 |
27 | 28 | ||
@@ -55,7 +56,6 @@ struct rtc_plat_data { | |||
55 | void __iomem *ioaddr_rtc; | 56 | void __iomem *ioaddr_rtc; |
56 | size_t size_nvram; | 57 | size_t size_nvram; |
57 | size_t size; | 58 | size_t size; |
58 | resource_size_t baseaddr; | ||
59 | unsigned long last_jiffies; | 59 | unsigned long last_jiffies; |
60 | struct bin_attribute nvram_attr; | 60 | struct bin_attribute nvram_attr; |
61 | }; | 61 | }; |
@@ -128,12 +128,12 @@ static const struct rtc_class_ops ds1742_rtc_ops = { | |||
128 | .set_time = ds1742_rtc_set_time, | 128 | .set_time = ds1742_rtc_set_time, |
129 | }; | 129 | }; |
130 | 130 | ||
131 | static ssize_t ds1742_nvram_read(struct kobject *kobj, | 131 | static ssize_t ds1742_nvram_read(struct file *filp, struct kobject *kobj, |
132 | struct bin_attribute *bin_attr, | 132 | struct bin_attribute *bin_attr, |
133 | char *buf, loff_t pos, size_t size) | 133 | char *buf, loff_t pos, size_t size) |
134 | { | 134 | { |
135 | struct platform_device *pdev = | 135 | struct device *dev = container_of(kobj, struct device, kobj); |
136 | to_platform_device(container_of(kobj, struct device, kobj)); | 136 | struct platform_device *pdev = to_platform_device(dev); |
137 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 137 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
138 | void __iomem *ioaddr = pdata->ioaddr_nvram; | 138 | void __iomem *ioaddr = pdata->ioaddr_nvram; |
139 | ssize_t count; | 139 | ssize_t count; |
@@ -143,12 +143,12 @@ static ssize_t ds1742_nvram_read(struct kobject *kobj, | |||
143 | return count; | 143 | return count; |
144 | } | 144 | } |
145 | 145 | ||
146 | static ssize_t ds1742_nvram_write(struct kobject *kobj, | 146 | static ssize_t ds1742_nvram_write(struct file *filp, struct kobject *kobj, |
147 | struct bin_attribute *bin_attr, | 147 | struct bin_attribute *bin_attr, |
148 | char *buf, loff_t pos, size_t size) | 148 | char *buf, loff_t pos, size_t size) |
149 | { | 149 | { |
150 | struct platform_device *pdev = | 150 | struct device *dev = container_of(kobj, struct device, kobj); |
151 | to_platform_device(container_of(kobj, struct device, kobj)); | 151 | struct platform_device *pdev = to_platform_device(dev); |
152 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 152 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
153 | void __iomem *ioaddr = pdata->ioaddr_nvram; | 153 | void __iomem *ioaddr = pdata->ioaddr_nvram; |
154 | ssize_t count; | 154 | ssize_t count; |
@@ -163,31 +163,29 @@ static int __devinit ds1742_rtc_probe(struct platform_device *pdev) | |||
163 | struct rtc_device *rtc; | 163 | struct rtc_device *rtc; |
164 | struct resource *res; | 164 | struct resource *res; |
165 | unsigned int cen, sec; | 165 | unsigned int cen, sec; |
166 | struct rtc_plat_data *pdata = NULL; | 166 | struct rtc_plat_data *pdata; |
167 | void __iomem *ioaddr = NULL; | 167 | void __iomem *ioaddr; |
168 | int ret = 0; | 168 | int ret = 0; |
169 | 169 | ||
170 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 170 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
171 | if (!res) | 171 | if (!res) |
172 | return -ENODEV; | 172 | return -ENODEV; |
173 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 173 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
174 | if (!pdata) | 174 | if (!pdata) |
175 | return -ENOMEM; | 175 | return -ENOMEM; |
176 | pdata->size = res->end - res->start + 1; | 176 | pdata->size = res->end - res->start + 1; |
177 | if (!request_mem_region(res->start, pdata->size, pdev->name)) { | 177 | if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size, |
178 | ret = -EBUSY; | 178 | pdev->name)) |
179 | goto out; | 179 | return -EBUSY; |
180 | } | 180 | ioaddr = devm_ioremap(&pdev->dev, res->start, pdata->size); |
181 | pdata->baseaddr = res->start; | 181 | if (!ioaddr) |
182 | ioaddr = ioremap(pdata->baseaddr, pdata->size); | 182 | return -ENOMEM; |
183 | if (!ioaddr) { | 183 | |
184 | ret = -ENOMEM; | ||
185 | goto out; | ||
186 | } | ||
187 | pdata->ioaddr_nvram = ioaddr; | 184 | pdata->ioaddr_nvram = ioaddr; |
188 | pdata->size_nvram = pdata->size - RTC_SIZE; | 185 | pdata->size_nvram = pdata->size - RTC_SIZE; |
189 | pdata->ioaddr_rtc = ioaddr + pdata->size_nvram; | 186 | pdata->ioaddr_rtc = ioaddr + pdata->size_nvram; |
190 | 187 | ||
188 | sysfs_bin_attr_init(&pdata->nvram_attr); | ||
191 | pdata->nvram_attr.attr.name = "nvram"; | 189 | pdata->nvram_attr.attr.name = "nvram"; |
192 | pdata->nvram_attr.attr.mode = S_IRUGO | S_IWUSR; | 190 | pdata->nvram_attr.attr.mode = S_IRUGO | S_IWUSR; |
193 | pdata->nvram_attr.read = ds1742_nvram_read; | 191 | pdata->nvram_attr.read = ds1742_nvram_read; |
@@ -207,31 +205,19 @@ static int __devinit ds1742_rtc_probe(struct platform_device *pdev) | |||
207 | if (!(readb(ioaddr + RTC_DAY) & RTC_BATT_FLAG)) | 205 | if (!(readb(ioaddr + RTC_DAY) & RTC_BATT_FLAG)) |
208 | dev_warn(&pdev->dev, "voltage-low detected.\n"); | 206 | dev_warn(&pdev->dev, "voltage-low detected.\n"); |
209 | 207 | ||
208 | pdata->last_jiffies = jiffies; | ||
209 | platform_set_drvdata(pdev, pdata); | ||
210 | rtc = rtc_device_register(pdev->name, &pdev->dev, | 210 | rtc = rtc_device_register(pdev->name, &pdev->dev, |
211 | &ds1742_rtc_ops, THIS_MODULE); | 211 | &ds1742_rtc_ops, THIS_MODULE); |
212 | if (IS_ERR(rtc)) { | 212 | if (IS_ERR(rtc)) |
213 | ret = PTR_ERR(rtc); | 213 | return PTR_ERR(rtc); |
214 | goto out; | ||
215 | } | ||
216 | pdata->rtc = rtc; | 214 | pdata->rtc = rtc; |
217 | pdata->last_jiffies = jiffies; | ||
218 | platform_set_drvdata(pdev, pdata); | ||
219 | 215 | ||
220 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); | 216 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); |
221 | if (ret) { | 217 | if (ret) { |
222 | dev_err(&pdev->dev, "creating nvram file in sysfs failed\n"); | 218 | dev_err(&pdev->dev, "creating nvram file in sysfs failed\n"); |
223 | goto out; | 219 | rtc_device_unregister(rtc); |
224 | } | 220 | } |
225 | |||
226 | return 0; | ||
227 | out: | ||
228 | if (pdata->rtc) | ||
229 | rtc_device_unregister(pdata->rtc); | ||
230 | if (pdata->ioaddr_nvram) | ||
231 | iounmap(pdata->ioaddr_nvram); | ||
232 | if (pdata->baseaddr) | ||
233 | release_mem_region(pdata->baseaddr, pdata->size); | ||
234 | kfree(pdata); | ||
235 | return ret; | 221 | return ret; |
236 | } | 222 | } |
237 | 223 | ||
@@ -241,9 +227,6 @@ static int __devexit ds1742_rtc_remove(struct platform_device *pdev) | |||
241 | 227 | ||
242 | sysfs_remove_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); | 228 | sysfs_remove_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); |
243 | rtc_device_unregister(pdata->rtc); | 229 | rtc_device_unregister(pdata->rtc); |
244 | iounmap(pdata->ioaddr_nvram); | ||
245 | release_mem_region(pdata->baseaddr, pdata->size); | ||
246 | kfree(pdata); | ||
247 | return 0; | 230 | return 0; |
248 | } | 231 | } |
249 | 232 | ||
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c new file mode 100644 index 000000000000..23a9ee19764c --- /dev/null +++ b/drivers/rtc/rtc-ds3232.c | |||
@@ -0,0 +1,505 @@ | |||
1 | /* | ||
2 | * RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Freescale Semiconductor. | ||
5 | * Author: Jack Lan <jack.lan@freescale.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | /* | ||
13 | * It would be more efficient to use i2c msgs/i2c_transfer directly but, as | ||
14 | * recommened in .../Documentation/i2c/writing-clients section | ||
15 | * "Sending and receiving", using SMBus level communication is preferred. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/i2c.h> | ||
22 | #include <linux/rtc.h> | ||
23 | #include <linux/bcd.h> | ||
24 | #include <linux/workqueue.h> | ||
25 | #include <linux/slab.h> | ||
26 | |||
27 | #define DS3232_REG_SECONDS 0x00 | ||
28 | #define DS3232_REG_MINUTES 0x01 | ||
29 | #define DS3232_REG_HOURS 0x02 | ||
30 | #define DS3232_REG_AMPM 0x02 | ||
31 | #define DS3232_REG_DAY 0x03 | ||
32 | #define DS3232_REG_DATE 0x04 | ||
33 | #define DS3232_REG_MONTH 0x05 | ||
34 | #define DS3232_REG_CENTURY 0x05 | ||
35 | #define DS3232_REG_YEAR 0x06 | ||
36 | #define DS3232_REG_ALARM1 0x07 /* Alarm 1 BASE */ | ||
37 | #define DS3232_REG_ALARM2 0x0B /* Alarm 2 BASE */ | ||
38 | #define DS3232_REG_CR 0x0E /* Control register */ | ||
39 | # define DS3232_REG_CR_nEOSC 0x80 | ||
40 | # define DS3232_REG_CR_INTCN 0x04 | ||
41 | # define DS3232_REG_CR_A2IE 0x02 | ||
42 | # define DS3232_REG_CR_A1IE 0x01 | ||
43 | |||
44 | #define DS3232_REG_SR 0x0F /* control/status register */ | ||
45 | # define DS3232_REG_SR_OSF 0x80 | ||
46 | # define DS3232_REG_SR_BSY 0x04 | ||
47 | # define DS3232_REG_SR_A2F 0x02 | ||
48 | # define DS3232_REG_SR_A1F 0x01 | ||
49 | |||
50 | struct ds3232 { | ||
51 | struct i2c_client *client; | ||
52 | struct rtc_device *rtc; | ||
53 | struct work_struct work; | ||
54 | |||
55 | /* The mutex protects alarm operations, and prevents a race | ||
56 | * between the enable_irq() in the workqueue and the free_irq() | ||
57 | * in the remove function. | ||
58 | */ | ||
59 | struct mutex mutex; | ||
60 | int exiting; | ||
61 | }; | ||
62 | |||
63 | static struct i2c_driver ds3232_driver; | ||
64 | |||
65 | static int ds3232_check_rtc_status(struct i2c_client *client) | ||
66 | { | ||
67 | int ret = 0; | ||
68 | int control, stat; | ||
69 | |||
70 | stat = i2c_smbus_read_byte_data(client, DS3232_REG_SR); | ||
71 | if (stat < 0) | ||
72 | return stat; | ||
73 | |||
74 | if (stat & DS3232_REG_SR_OSF) | ||
75 | dev_warn(&client->dev, | ||
76 | "oscillator discontinuity flagged, " | ||
77 | "time unreliable\n"); | ||
78 | |||
79 | stat &= ~(DS3232_REG_SR_OSF | DS3232_REG_SR_A1F | DS3232_REG_SR_A2F); | ||
80 | |||
81 | ret = i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat); | ||
82 | if (ret < 0) | ||
83 | return ret; | ||
84 | |||
85 | /* If the alarm is pending, clear it before requesting | ||
86 | * the interrupt, so an interrupt event isn't reported | ||
87 | * before everything is initialized. | ||
88 | */ | ||
89 | |||
90 | control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); | ||
91 | if (control < 0) | ||
92 | return control; | ||
93 | |||
94 | control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE); | ||
95 | control |= DS3232_REG_CR_INTCN; | ||
96 | |||
97 | return i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); | ||
98 | } | ||
99 | |||
100 | static int ds3232_read_time(struct device *dev, struct rtc_time *time) | ||
101 | { | ||
102 | struct i2c_client *client = to_i2c_client(dev); | ||
103 | int ret; | ||
104 | u8 buf[7]; | ||
105 | unsigned int year, month, day, hour, minute, second; | ||
106 | unsigned int week, twelve_hr, am_pm; | ||
107 | unsigned int century, add_century = 0; | ||
108 | |||
109 | ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_SECONDS, 7, buf); | ||
110 | |||
111 | if (ret < 0) | ||
112 | return ret; | ||
113 | if (ret < 7) | ||
114 | return -EIO; | ||
115 | |||
116 | second = buf[0]; | ||
117 | minute = buf[1]; | ||
118 | hour = buf[2]; | ||
119 | week = buf[3]; | ||
120 | day = buf[4]; | ||
121 | month = buf[5]; | ||
122 | year = buf[6]; | ||
123 | |||
124 | /* Extract additional information for AM/PM and century */ | ||
125 | |||
126 | twelve_hr = hour & 0x40; | ||
127 | am_pm = hour & 0x20; | ||
128 | century = month & 0x80; | ||
129 | |||
130 | /* Write to rtc_time structure */ | ||
131 | |||
132 | time->tm_sec = bcd2bin(second); | ||
133 | time->tm_min = bcd2bin(minute); | ||
134 | if (twelve_hr) { | ||
135 | /* Convert to 24 hr */ | ||
136 | if (am_pm) | ||
137 | time->tm_hour = bcd2bin(hour & 0x1F) + 12; | ||
138 | else | ||
139 | time->tm_hour = bcd2bin(hour & 0x1F); | ||
140 | } else { | ||
141 | time->tm_hour = bcd2bin(hour); | ||
142 | } | ||
143 | |||
144 | time->tm_wday = bcd2bin(week); | ||
145 | time->tm_mday = bcd2bin(day); | ||
146 | time->tm_mon = bcd2bin(month & 0x7F); | ||
147 | if (century) | ||
148 | add_century = 100; | ||
149 | |||
150 | time->tm_year = bcd2bin(year) + add_century; | ||
151 | |||
152 | return rtc_valid_tm(time); | ||
153 | } | ||
154 | |||
155 | static int ds3232_set_time(struct device *dev, struct rtc_time *time) | ||
156 | { | ||
157 | struct i2c_client *client = to_i2c_client(dev); | ||
158 | u8 buf[7]; | ||
159 | |||
160 | /* Extract time from rtc_time and load into ds3232*/ | ||
161 | |||
162 | buf[0] = bin2bcd(time->tm_sec); | ||
163 | buf[1] = bin2bcd(time->tm_min); | ||
164 | buf[2] = bin2bcd(time->tm_hour); | ||
165 | buf[3] = bin2bcd(time->tm_wday); /* Day of the week */ | ||
166 | buf[4] = bin2bcd(time->tm_mday); /* Date */ | ||
167 | buf[5] = bin2bcd(time->tm_mon); | ||
168 | if (time->tm_year >= 100) { | ||
169 | buf[5] |= 0x80; | ||
170 | buf[6] = bin2bcd(time->tm_year - 100); | ||
171 | } else { | ||
172 | buf[6] = bin2bcd(time->tm_year); | ||
173 | } | ||
174 | |||
175 | return i2c_smbus_write_i2c_block_data(client, | ||
176 | DS3232_REG_SECONDS, 7, buf); | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * DS3232 has two alarm, we only use alarm1 | ||
181 | * According to linux specification, only support one-shot alarm | ||
182 | * no periodic alarm mode | ||
183 | */ | ||
184 | static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
185 | { | ||
186 | struct i2c_client *client = to_i2c_client(dev); | ||
187 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
188 | int control, stat; | ||
189 | int ret; | ||
190 | u8 buf[4]; | ||
191 | |||
192 | mutex_lock(&ds3232->mutex); | ||
193 | |||
194 | ret = i2c_smbus_read_byte_data(client, DS3232_REG_SR); | ||
195 | if (ret < 0) | ||
196 | goto out; | ||
197 | stat = ret; | ||
198 | ret = i2c_smbus_read_byte_data(client, DS3232_REG_CR); | ||
199 | if (ret < 0) | ||
200 | goto out; | ||
201 | control = ret; | ||
202 | ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf); | ||
203 | if (ret < 0) | ||
204 | goto out; | ||
205 | |||
206 | alarm->time.tm_sec = bcd2bin(buf[0] & 0x7F); | ||
207 | alarm->time.tm_min = bcd2bin(buf[1] & 0x7F); | ||
208 | alarm->time.tm_hour = bcd2bin(buf[2] & 0x7F); | ||
209 | alarm->time.tm_mday = bcd2bin(buf[3] & 0x7F); | ||
210 | |||
211 | alarm->time.tm_mon = -1; | ||
212 | alarm->time.tm_year = -1; | ||
213 | alarm->time.tm_wday = -1; | ||
214 | alarm->time.tm_yday = -1; | ||
215 | alarm->time.tm_isdst = -1; | ||
216 | |||
217 | alarm->enabled = !!(control & DS3232_REG_CR_A1IE); | ||
218 | alarm->pending = !!(stat & DS3232_REG_SR_A1F); | ||
219 | |||
220 | ret = 0; | ||
221 | out: | ||
222 | mutex_unlock(&ds3232->mutex); | ||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * linux rtc-module does not support wday alarm | ||
228 | * and only 24h time mode supported indeed | ||
229 | */ | ||
230 | static int ds3232_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
231 | { | ||
232 | struct i2c_client *client = to_i2c_client(dev); | ||
233 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
234 | int control, stat; | ||
235 | int ret; | ||
236 | u8 buf[4]; | ||
237 | |||
238 | if (client->irq <= 0) | ||
239 | return -EINVAL; | ||
240 | |||
241 | mutex_lock(&ds3232->mutex); | ||
242 | |||
243 | buf[0] = bin2bcd(alarm->time.tm_sec); | ||
244 | buf[1] = bin2bcd(alarm->time.tm_min); | ||
245 | buf[2] = bin2bcd(alarm->time.tm_hour); | ||
246 | buf[3] = bin2bcd(alarm->time.tm_mday); | ||
247 | |||
248 | /* clear alarm interrupt enable bit */ | ||
249 | ret = i2c_smbus_read_byte_data(client, DS3232_REG_CR); | ||
250 | if (ret < 0) | ||
251 | goto out; | ||
252 | control = ret; | ||
253 | control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE); | ||
254 | ret = i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); | ||
255 | if (ret < 0) | ||
256 | goto out; | ||
257 | |||
258 | /* clear any pending alarm flag */ | ||
259 | ret = i2c_smbus_read_byte_data(client, DS3232_REG_SR); | ||
260 | if (ret < 0) | ||
261 | goto out; | ||
262 | stat = ret; | ||
263 | stat &= ~(DS3232_REG_SR_A1F | DS3232_REG_SR_A2F); | ||
264 | ret = i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat); | ||
265 | if (ret < 0) | ||
266 | goto out; | ||
267 | |||
268 | ret = i2c_smbus_write_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf); | ||
269 | |||
270 | if (alarm->enabled) { | ||
271 | control |= DS3232_REG_CR_A1IE; | ||
272 | ret = i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); | ||
273 | } | ||
274 | out: | ||
275 | mutex_unlock(&ds3232->mutex); | ||
276 | return ret; | ||
277 | } | ||
278 | |||
279 | static void ds3232_update_alarm(struct i2c_client *client) | ||
280 | { | ||
281 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
282 | int control; | ||
283 | int ret; | ||
284 | u8 buf[4]; | ||
285 | |||
286 | mutex_lock(&ds3232->mutex); | ||
287 | |||
288 | ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf); | ||
289 | if (ret < 0) | ||
290 | goto unlock; | ||
291 | |||
292 | buf[0] = bcd2bin(buf[0]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ? | ||
293 | 0x80 : buf[0]; | ||
294 | buf[1] = bcd2bin(buf[1]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ? | ||
295 | 0x80 : buf[1]; | ||
296 | buf[2] = bcd2bin(buf[2]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ? | ||
297 | 0x80 : buf[2]; | ||
298 | buf[3] = bcd2bin(buf[3]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ? | ||
299 | 0x80 : buf[3]; | ||
300 | |||
301 | ret = i2c_smbus_write_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf); | ||
302 | if (ret < 0) | ||
303 | goto unlock; | ||
304 | |||
305 | control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); | ||
306 | if (control < 0) | ||
307 | goto unlock; | ||
308 | |||
309 | if (ds3232->rtc->irq_data & (RTC_AF | RTC_UF)) | ||
310 | /* enable alarm1 interrupt */ | ||
311 | control |= DS3232_REG_CR_A1IE; | ||
312 | else | ||
313 | /* disable alarm1 interrupt */ | ||
314 | control &= ~(DS3232_REG_CR_A1IE); | ||
315 | i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); | ||
316 | |||
317 | unlock: | ||
318 | mutex_unlock(&ds3232->mutex); | ||
319 | } | ||
320 | |||
321 | static int ds3232_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
322 | { | ||
323 | struct i2c_client *client = to_i2c_client(dev); | ||
324 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
325 | |||
326 | if (client->irq <= 0) | ||
327 | return -EINVAL; | ||
328 | |||
329 | if (enabled) | ||
330 | ds3232->rtc->irq_data |= RTC_AF; | ||
331 | else | ||
332 | ds3232->rtc->irq_data &= ~RTC_AF; | ||
333 | |||
334 | ds3232_update_alarm(client); | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static int ds3232_update_irq_enable(struct device *dev, unsigned int enabled) | ||
339 | { | ||
340 | struct i2c_client *client = to_i2c_client(dev); | ||
341 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
342 | |||
343 | if (client->irq <= 0) | ||
344 | return -EINVAL; | ||
345 | |||
346 | if (enabled) | ||
347 | ds3232->rtc->irq_data |= RTC_UF; | ||
348 | else | ||
349 | ds3232->rtc->irq_data &= ~RTC_UF; | ||
350 | |||
351 | ds3232_update_alarm(client); | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static irqreturn_t ds3232_irq(int irq, void *dev_id) | ||
356 | { | ||
357 | struct i2c_client *client = dev_id; | ||
358 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
359 | |||
360 | disable_irq_nosync(irq); | ||
361 | schedule_work(&ds3232->work); | ||
362 | return IRQ_HANDLED; | ||
363 | } | ||
364 | |||
365 | static void ds3232_work(struct work_struct *work) | ||
366 | { | ||
367 | struct ds3232 *ds3232 = container_of(work, struct ds3232, work); | ||
368 | struct i2c_client *client = ds3232->client; | ||
369 | int stat, control; | ||
370 | |||
371 | mutex_lock(&ds3232->mutex); | ||
372 | |||
373 | stat = i2c_smbus_read_byte_data(client, DS3232_REG_SR); | ||
374 | if (stat < 0) | ||
375 | goto unlock; | ||
376 | |||
377 | if (stat & DS3232_REG_SR_A1F) { | ||
378 | control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); | ||
379 | if (control < 0) | ||
380 | goto out; | ||
381 | /* disable alarm1 interrupt */ | ||
382 | control &= ~(DS3232_REG_CR_A1IE); | ||
383 | i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); | ||
384 | |||
385 | /* clear the alarm pend flag */ | ||
386 | stat &= ~DS3232_REG_SR_A1F; | ||
387 | i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat); | ||
388 | |||
389 | rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF); | ||
390 | } | ||
391 | |||
392 | out: | ||
393 | if (!ds3232->exiting) | ||
394 | enable_irq(client->irq); | ||
395 | unlock: | ||
396 | mutex_unlock(&ds3232->mutex); | ||
397 | } | ||
398 | |||
399 | static const struct rtc_class_ops ds3232_rtc_ops = { | ||
400 | .read_time = ds3232_read_time, | ||
401 | .set_time = ds3232_set_time, | ||
402 | .read_alarm = ds3232_read_alarm, | ||
403 | .set_alarm = ds3232_set_alarm, | ||
404 | .alarm_irq_enable = ds3232_alarm_irq_enable, | ||
405 | .update_irq_enable = ds3232_update_irq_enable, | ||
406 | }; | ||
407 | |||
408 | static int __devinit ds3232_probe(struct i2c_client *client, | ||
409 | const struct i2c_device_id *id) | ||
410 | { | ||
411 | struct ds3232 *ds3232; | ||
412 | int ret; | ||
413 | |||
414 | ds3232 = kzalloc(sizeof(struct ds3232), GFP_KERNEL); | ||
415 | if (!ds3232) | ||
416 | return -ENOMEM; | ||
417 | |||
418 | ds3232->client = client; | ||
419 | i2c_set_clientdata(client, ds3232); | ||
420 | |||
421 | INIT_WORK(&ds3232->work, ds3232_work); | ||
422 | mutex_init(&ds3232->mutex); | ||
423 | |||
424 | ret = ds3232_check_rtc_status(client); | ||
425 | if (ret) | ||
426 | goto out_free; | ||
427 | |||
428 | ds3232->rtc = rtc_device_register(client->name, &client->dev, | ||
429 | &ds3232_rtc_ops, THIS_MODULE); | ||
430 | if (IS_ERR(ds3232->rtc)) { | ||
431 | ret = PTR_ERR(ds3232->rtc); | ||
432 | dev_err(&client->dev, "unable to register the class device\n"); | ||
433 | goto out_irq; | ||
434 | } | ||
435 | |||
436 | if (client->irq >= 0) { | ||
437 | ret = request_irq(client->irq, ds3232_irq, 0, | ||
438 | "ds3232", client); | ||
439 | if (ret) { | ||
440 | dev_err(&client->dev, "unable to request IRQ\n"); | ||
441 | goto out_free; | ||
442 | } | ||
443 | } | ||
444 | |||
445 | return 0; | ||
446 | |||
447 | out_irq: | ||
448 | if (client->irq >= 0) | ||
449 | free_irq(client->irq, client); | ||
450 | |||
451 | out_free: | ||
452 | kfree(ds3232); | ||
453 | return ret; | ||
454 | } | ||
455 | |||
456 | static int __devexit ds3232_remove(struct i2c_client *client) | ||
457 | { | ||
458 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
459 | |||
460 | if (client->irq >= 0) { | ||
461 | mutex_lock(&ds3232->mutex); | ||
462 | ds3232->exiting = 1; | ||
463 | mutex_unlock(&ds3232->mutex); | ||
464 | |||
465 | free_irq(client->irq, client); | ||
466 | cancel_work_sync(&ds3232->work); | ||
467 | } | ||
468 | |||
469 | rtc_device_unregister(ds3232->rtc); | ||
470 | kfree(ds3232); | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static const struct i2c_device_id ds3232_id[] = { | ||
475 | { "ds3232", 0 }, | ||
476 | { } | ||
477 | }; | ||
478 | MODULE_DEVICE_TABLE(i2c, ds3232_id); | ||
479 | |||
480 | static struct i2c_driver ds3232_driver = { | ||
481 | .driver = { | ||
482 | .name = "rtc-ds3232", | ||
483 | .owner = THIS_MODULE, | ||
484 | }, | ||
485 | .probe = ds3232_probe, | ||
486 | .remove = __devexit_p(ds3232_remove), | ||
487 | .id_table = ds3232_id, | ||
488 | }; | ||
489 | |||
490 | static int __init ds3232_init(void) | ||
491 | { | ||
492 | return i2c_add_driver(&ds3232_driver); | ||
493 | } | ||
494 | |||
495 | static void __exit ds3232_exit(void) | ||
496 | { | ||
497 | i2c_del_driver(&ds3232_driver); | ||
498 | } | ||
499 | |||
500 | module_init(ds3232_init); | ||
501 | module_exit(ds3232_exit); | ||
502 | |||
503 | MODULE_AUTHOR("Srikanth Srinivasan <srikanth.srinivasan@freescale.com>"); | ||
504 | MODULE_DESCRIPTION("Maxim/Dallas DS3232 RTC Driver"); | ||
505 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-ds3234.c b/drivers/rtc/rtc-ds3234.c index c51589ede5b7..a774ca35b5f7 100644 --- a/drivers/rtc/rtc-ds3234.c +++ b/drivers/rtc/rtc-ds3234.c | |||
@@ -188,3 +188,4 @@ module_exit(ds3234_exit); | |||
188 | MODULE_DESCRIPTION("DS3234 SPI RTC driver"); | 188 | MODULE_DESCRIPTION("DS3234 SPI RTC driver"); |
189 | MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>"); | 189 | MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>"); |
190 | MODULE_LICENSE("GPL"); | 190 | MODULE_LICENSE("GPL"); |
191 | MODULE_ALIAS("spi:ds3234"); | ||
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c index 551332e4ed02..11ae64dcbf3c 100644 --- a/drivers/rtc/rtc-ep93xx.c +++ b/drivers/rtc/rtc-ep93xx.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/rtc.h> | 13 | #include <linux/rtc.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/gfp.h> | ||
16 | 17 | ||
17 | #define EP93XX_RTC_DATA 0x000 | 18 | #define EP93XX_RTC_DATA 0x000 |
18 | #define EP93XX_RTC_MATCH 0x004 | 19 | #define EP93XX_RTC_MATCH 0x004 |
@@ -115,6 +116,15 @@ static ssize_t ep93xx_rtc_show_comp_delete(struct device *dev, | |||
115 | } | 116 | } |
116 | static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_rtc_show_comp_delete, NULL); | 117 | static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_rtc_show_comp_delete, NULL); |
117 | 118 | ||
119 | static struct attribute *ep93xx_rtc_attrs[] = { | ||
120 | &dev_attr_comp_preload.attr, | ||
121 | &dev_attr_comp_delete.attr, | ||
122 | NULL | ||
123 | }; | ||
124 | |||
125 | static const struct attribute_group ep93xx_rtc_sysfs_files = { | ||
126 | .attrs = ep93xx_rtc_attrs, | ||
127 | }; | ||
118 | 128 | ||
119 | static int __init ep93xx_rtc_probe(struct platform_device *pdev) | 129 | static int __init ep93xx_rtc_probe(struct platform_device *pdev) |
120 | { | 130 | { |
@@ -123,23 +133,22 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev) | |||
123 | struct rtc_device *rtc; | 133 | struct rtc_device *rtc; |
124 | int err; | 134 | int err; |
125 | 135 | ||
126 | ep93xx_rtc = kzalloc(sizeof(struct ep93xx_rtc), GFP_KERNEL); | 136 | ep93xx_rtc = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_rtc), GFP_KERNEL); |
127 | if (ep93xx_rtc == NULL) | 137 | if (!ep93xx_rtc) |
128 | return -ENOMEM; | 138 | return -ENOMEM; |
129 | 139 | ||
130 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 140 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
131 | if (res == NULL) | 141 | if (!res) |
132 | return -ENXIO; | 142 | return -ENXIO; |
133 | 143 | ||
134 | res = request_mem_region(res->start, resource_size(res), pdev->name); | 144 | if (!devm_request_mem_region(&pdev->dev, res->start, |
135 | if (res == NULL) | 145 | resource_size(res), pdev->name)) |
136 | return -EBUSY; | 146 | return -EBUSY; |
137 | 147 | ||
138 | ep93xx_rtc->mmio_base = ioremap(res->start, resource_size(res)); | 148 | ep93xx_rtc->mmio_base = devm_ioremap(&pdev->dev, res->start, |
139 | if (ep93xx_rtc->mmio_base == NULL) { | 149 | resource_size(res)); |
140 | err = -ENXIO; | 150 | if (!ep93xx_rtc->mmio_base) |
141 | goto fail; | 151 | return -ENXIO; |
142 | } | ||
143 | 152 | ||
144 | pdev->dev.platform_data = ep93xx_rtc; | 153 | pdev->dev.platform_data = ep93xx_rtc; |
145 | 154 | ||
@@ -147,51 +156,34 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev) | |||
147 | &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE); | 156 | &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE); |
148 | if (IS_ERR(rtc)) { | 157 | if (IS_ERR(rtc)) { |
149 | err = PTR_ERR(rtc); | 158 | err = PTR_ERR(rtc); |
150 | goto fail; | 159 | goto exit; |
151 | } | 160 | } |
152 | 161 | ||
153 | platform_set_drvdata(pdev, rtc); | 162 | platform_set_drvdata(pdev, rtc); |
154 | 163 | ||
155 | err = device_create_file(&pdev->dev, &dev_attr_comp_preload); | 164 | err = sysfs_create_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files); |
156 | if (err) | 165 | if (err) |
157 | goto fail; | 166 | goto fail; |
158 | err = device_create_file(&pdev->dev, &dev_attr_comp_delete); | ||
159 | if (err) { | ||
160 | device_remove_file(&pdev->dev, &dev_attr_comp_preload); | ||
161 | goto fail; | ||
162 | } | ||
163 | 167 | ||
164 | return 0; | 168 | return 0; |
165 | 169 | ||
166 | fail: | 170 | fail: |
167 | if (ep93xx_rtc->mmio_base) { | 171 | platform_set_drvdata(pdev, NULL); |
168 | iounmap(ep93xx_rtc->mmio_base); | 172 | rtc_device_unregister(rtc); |
169 | pdev->dev.platform_data = NULL; | 173 | exit: |
170 | } | 174 | pdev->dev.platform_data = NULL; |
171 | release_mem_region(res->start, resource_size(res)); | ||
172 | return err; | 175 | return err; |
173 | } | 176 | } |
174 | 177 | ||
175 | static int __exit ep93xx_rtc_remove(struct platform_device *pdev) | 178 | static int __exit ep93xx_rtc_remove(struct platform_device *pdev) |
176 | { | 179 | { |
177 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 180 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
178 | struct ep93xx_rtc *ep93xx_rtc = pdev->dev.platform_data; | ||
179 | struct resource *res; | ||
180 | |||
181 | /* cleanup sysfs */ | ||
182 | device_remove_file(&pdev->dev, &dev_attr_comp_delete); | ||
183 | device_remove_file(&pdev->dev, &dev_attr_comp_preload); | ||
184 | 181 | ||
182 | sysfs_remove_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files); | ||
183 | platform_set_drvdata(pdev, NULL); | ||
185 | rtc_device_unregister(rtc); | 184 | rtc_device_unregister(rtc); |
186 | |||
187 | iounmap(ep93xx_rtc->mmio_base); | ||
188 | pdev->dev.platform_data = NULL; | 185 | pdev->dev.platform_data = NULL; |
189 | 186 | ||
190 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
191 | release_mem_region(res->start, resource_size(res)); | ||
192 | |||
193 | platform_set_drvdata(pdev, NULL); | ||
194 | |||
195 | return 0; | 187 | return 0; |
196 | } | 188 | } |
197 | 189 | ||
diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index 3a7be11cc6b9..4cf2e70c5078 100644 --- a/drivers/rtc/rtc-fm3130.c +++ b/drivers/rtc/rtc-fm3130.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/i2c.h> | 13 | #include <linux/i2c.h> |
14 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
15 | #include <linux/bcd.h> | 15 | #include <linux/bcd.h> |
16 | #include <linux/slab.h> | ||
16 | 17 | ||
17 | #define FM3130_RTC_CONTROL (0x0) | 18 | #define FM3130_RTC_CONTROL (0x0) |
18 | #define FM3130_CAL_CONTROL (0x1) | 19 | #define FM3130_CAL_CONTROL (0x1) |
@@ -51,8 +52,8 @@ struct fm3130 { | |||
51 | struct i2c_msg msg[4]; | 52 | struct i2c_msg msg[4]; |
52 | struct i2c_client *client; | 53 | struct i2c_client *client; |
53 | struct rtc_device *rtc; | 54 | struct rtc_device *rtc; |
55 | int alarm_valid; | ||
54 | int data_valid; | 56 | int data_valid; |
55 | int alarm; | ||
56 | }; | 57 | }; |
57 | static const struct i2c_device_id fm3130_id[] = { | 58 | static const struct i2c_device_id fm3130_id[] = { |
58 | { "fm3130", 0 }, | 59 | { "fm3130", 0 }, |
@@ -86,11 +87,7 @@ static void fm3130_rtc_mode(struct device *dev, int mode) | |||
86 | dev_dbg(dev, "invalid mode %d\n", mode); | 87 | dev_dbg(dev, "invalid mode %d\n", mode); |
87 | break; | 88 | break; |
88 | } | 89 | } |
89 | /* Checking for alarm */ | 90 | |
90 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) { | ||
91 | fm3130->alarm = 1; | ||
92 | fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF; | ||
93 | } | ||
94 | i2c_smbus_write_byte_data(fm3130->client, | 91 | i2c_smbus_write_byte_data(fm3130->client, |
95 | FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL]); | 92 | FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL]); |
96 | } | 93 | } |
@@ -103,7 +100,7 @@ static int fm3130_get_time(struct device *dev, struct rtc_time *t) | |||
103 | if (!fm3130->data_valid) { | 100 | if (!fm3130->data_valid) { |
104 | /* We have invalid data in RTC, probably due | 101 | /* We have invalid data in RTC, probably due |
105 | to battery faults or other problems. Return EIO | 102 | to battery faults or other problems. Return EIO |
106 | for now, it will allow us to set data later insted | 103 | for now, it will allow us to set data later instead |
107 | of error during probing which disables device */ | 104 | of error during probing which disables device */ |
108 | return -EIO; | 105 | return -EIO; |
109 | } | 106 | } |
@@ -207,6 +204,17 @@ static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
207 | struct fm3130 *fm3130 = dev_get_drvdata(dev); | 204 | struct fm3130 *fm3130 = dev_get_drvdata(dev); |
208 | int tmp; | 205 | int tmp; |
209 | struct rtc_time *tm = &alrm->time; | 206 | struct rtc_time *tm = &alrm->time; |
207 | |||
208 | if (!fm3130->alarm_valid) { | ||
209 | /* | ||
210 | * We have invalid alarm in RTC, probably due to battery faults | ||
211 | * or other problems. Return EIO for now, it will allow us to | ||
212 | * set alarm value later instead of error during probing which | ||
213 | * disables device | ||
214 | */ | ||
215 | return -EIO; | ||
216 | } | ||
217 | |||
210 | /* read the RTC alarm registers all at once */ | 218 | /* read the RTC alarm registers all at once */ |
211 | tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent), | 219 | tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent), |
212 | &fm3130->msg[2], 2); | 220 | &fm3130->msg[2], 2); |
@@ -221,20 +229,31 @@ static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
221 | fm3130->regs[FM3130_ALARM_DATE], | 229 | fm3130->regs[FM3130_ALARM_DATE], |
222 | fm3130->regs[FM3130_ALARM_MONTHS]); | 230 | fm3130->regs[FM3130_ALARM_MONTHS]); |
223 | 231 | ||
224 | |||
225 | tm->tm_sec = bcd2bin(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F); | 232 | tm->tm_sec = bcd2bin(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F); |
226 | tm->tm_min = bcd2bin(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F); | 233 | tm->tm_min = bcd2bin(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F); |
227 | tm->tm_hour = bcd2bin(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F); | 234 | tm->tm_hour = bcd2bin(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F); |
228 | tm->tm_mday = bcd2bin(fm3130->regs[FM3130_ALARM_DATE] & 0x3F); | 235 | tm->tm_mday = bcd2bin(fm3130->regs[FM3130_ALARM_DATE] & 0x3F); |
229 | tm->tm_mon = bcd2bin(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F); | 236 | tm->tm_mon = bcd2bin(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F); |
237 | |||
230 | if (tm->tm_mon > 0) | 238 | if (tm->tm_mon > 0) |
231 | tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */ | 239 | tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */ |
240 | |||
232 | dev_dbg(dev, "%s secs=%d, mins=%d, " | 241 | dev_dbg(dev, "%s secs=%d, mins=%d, " |
233 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", | 242 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", |
234 | "read alarm", tm->tm_sec, tm->tm_min, | 243 | "read alarm", tm->tm_sec, tm->tm_min, |
235 | tm->tm_hour, tm->tm_mday, | 244 | tm->tm_hour, tm->tm_mday, |
236 | tm->tm_mon, tm->tm_year, tm->tm_wday); | 245 | tm->tm_mon, tm->tm_year, tm->tm_wday); |
237 | 246 | ||
247 | /* check if alarm enabled */ | ||
248 | fm3130->regs[FM3130_RTC_CONTROL] = | ||
249 | i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL); | ||
250 | |||
251 | if ((fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AEN) && | ||
252 | (~fm3130->regs[FM3130_RTC_CONTROL] & | ||
253 | FM3130_RTC_CONTROL_BIT_CAL)) { | ||
254 | alrm->enabled = 1; | ||
255 | } | ||
256 | |||
238 | return 0; | 257 | return 0; |
239 | } | 258 | } |
240 | 259 | ||
@@ -250,25 +269,20 @@ static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
250 | tm->tm_hour, tm->tm_mday, | 269 | tm->tm_hour, tm->tm_mday, |
251 | tm->tm_mon, tm->tm_year, tm->tm_wday); | 270 | tm->tm_mon, tm->tm_year, tm->tm_wday); |
252 | 271 | ||
253 | if (tm->tm_sec != -1) | 272 | fm3130->regs[FM3130_ALARM_SECONDS] = |
254 | fm3130->regs[FM3130_ALARM_SECONDS] = | 273 | (tm->tm_sec != -1) ? bin2bcd(tm->tm_sec) : 0x80; |
255 | bin2bcd(tm->tm_sec) | 0x80; | ||
256 | 274 | ||
257 | if (tm->tm_min != -1) | 275 | fm3130->regs[FM3130_ALARM_MINUTES] = |
258 | fm3130->regs[FM3130_ALARM_MINUTES] = | 276 | (tm->tm_min != -1) ? bin2bcd(tm->tm_min) : 0x80; |
259 | bin2bcd(tm->tm_min) | 0x80; | ||
260 | 277 | ||
261 | if (tm->tm_hour != -1) | 278 | fm3130->regs[FM3130_ALARM_HOURS] = |
262 | fm3130->regs[FM3130_ALARM_HOURS] = | 279 | (tm->tm_hour != -1) ? bin2bcd(tm->tm_hour) : 0x80; |
263 | bin2bcd(tm->tm_hour) | 0x80; | ||
264 | 280 | ||
265 | if (tm->tm_mday != -1) | 281 | fm3130->regs[FM3130_ALARM_DATE] = |
266 | fm3130->regs[FM3130_ALARM_DATE] = | 282 | (tm->tm_mday != -1) ? bin2bcd(tm->tm_mday) : 0x80; |
267 | bin2bcd(tm->tm_mday) | 0x80; | ||
268 | 283 | ||
269 | if (tm->tm_mon != -1) | 284 | fm3130->regs[FM3130_ALARM_MONTHS] = |
270 | fm3130->regs[FM3130_ALARM_MONTHS] = | 285 | (tm->tm_mon != -1) ? bin2bcd(tm->tm_mon + 1) : 0x80; |
271 | bin2bcd(tm->tm_mon + 1) | 0x80; | ||
272 | 286 | ||
273 | dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n", | 287 | dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n", |
274 | fm3130->regs[FM3130_ALARM_SECONDS], | 288 | fm3130->regs[FM3130_ALARM_SECONDS], |
@@ -284,11 +298,8 @@ static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
284 | } | 298 | } |
285 | fm3130->regs[FM3130_RTC_CONTROL] = | 299 | fm3130->regs[FM3130_RTC_CONTROL] = |
286 | i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL); | 300 | i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL); |
287 | /* Checking for alarm */ | 301 | |
288 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) { | 302 | /* enable or disable alarm */ |
289 | fm3130->alarm = 1; | ||
290 | fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF; | ||
291 | } | ||
292 | if (alrm->enabled) { | 303 | if (alrm->enabled) { |
293 | i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL, | 304 | i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL, |
294 | (fm3130->regs[FM3130_RTC_CONTROL] & | 305 | (fm3130->regs[FM3130_RTC_CONTROL] & |
@@ -297,16 +308,55 @@ static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
297 | } else { | 308 | } else { |
298 | i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL, | 309 | i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL, |
299 | fm3130->regs[FM3130_RTC_CONTROL] & | 310 | fm3130->regs[FM3130_RTC_CONTROL] & |
300 | ~(FM3130_RTC_CONTROL_BIT_AEN)); | 311 | ~(FM3130_RTC_CONTROL_BIT_CAL) & |
312 | ~(FM3130_RTC_CONTROL_BIT_AEN)); | ||
301 | } | 313 | } |
314 | |||
315 | /* We assume here that data is valid once written */ | ||
316 | if (!fm3130->alarm_valid) | ||
317 | fm3130->alarm_valid = 1; | ||
318 | |||
302 | return 0; | 319 | return 0; |
303 | } | 320 | } |
304 | 321 | ||
322 | static int fm3130_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
323 | { | ||
324 | struct fm3130 *fm3130 = dev_get_drvdata(dev); | ||
325 | int ret = 0; | ||
326 | |||
327 | fm3130->regs[FM3130_RTC_CONTROL] = | ||
328 | i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL); | ||
329 | |||
330 | dev_dbg(dev, "alarm_irq_enable: enable=%d, FM3130_RTC_CONTROL=%02x\n", | ||
331 | enabled, fm3130->regs[FM3130_RTC_CONTROL]); | ||
332 | |||
333 | switch (enabled) { | ||
334 | case 0: /* alarm off */ | ||
335 | ret = i2c_smbus_write_byte_data(fm3130->client, | ||
336 | FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL] & | ||
337 | ~(FM3130_RTC_CONTROL_BIT_CAL) & | ||
338 | ~(FM3130_RTC_CONTROL_BIT_AEN)); | ||
339 | break; | ||
340 | case 1: /* alarm on */ | ||
341 | ret = i2c_smbus_write_byte_data(fm3130->client, | ||
342 | FM3130_RTC_CONTROL, (fm3130->regs[FM3130_RTC_CONTROL] & | ||
343 | ~(FM3130_RTC_CONTROL_BIT_CAL)) | | ||
344 | FM3130_RTC_CONTROL_BIT_AEN); | ||
345 | break; | ||
346 | default: | ||
347 | ret = -EINVAL; | ||
348 | break; | ||
349 | } | ||
350 | |||
351 | return ret; | ||
352 | } | ||
353 | |||
305 | static const struct rtc_class_ops fm3130_rtc_ops = { | 354 | static const struct rtc_class_ops fm3130_rtc_ops = { |
306 | .read_time = fm3130_get_time, | 355 | .read_time = fm3130_get_time, |
307 | .set_time = fm3130_set_time, | 356 | .set_time = fm3130_set_time, |
308 | .read_alarm = fm3130_read_alarm, | 357 | .read_alarm = fm3130_read_alarm, |
309 | .set_alarm = fm3130_set_alarm, | 358 | .set_alarm = fm3130_set_alarm, |
359 | .alarm_irq_enable = fm3130_alarm_irq_enable, | ||
310 | }; | 360 | }; |
311 | 361 | ||
312 | static struct i2c_driver fm3130_driver; | 362 | static struct i2c_driver fm3130_driver; |
@@ -355,6 +405,7 @@ static int __devinit fm3130_probe(struct i2c_client *client, | |||
355 | fm3130->msg[3].len = FM3130_ALARM_REGS; | 405 | fm3130->msg[3].len = FM3130_ALARM_REGS; |
356 | fm3130->msg[3].buf = &fm3130->regs[FM3130_ALARM_SECONDS]; | 406 | fm3130->msg[3].buf = &fm3130->regs[FM3130_ALARM_SECONDS]; |
357 | 407 | ||
408 | fm3130->alarm_valid = 0; | ||
358 | fm3130->data_valid = 0; | 409 | fm3130->data_valid = 0; |
359 | 410 | ||
360 | tmp = i2c_transfer(adapter, fm3130->msg, 4); | 411 | tmp = i2c_transfer(adapter, fm3130->msg, 4); |
@@ -369,27 +420,23 @@ static int __devinit fm3130_probe(struct i2c_client *client, | |||
369 | fm3130->regs[FM3130_CAL_CONTROL] = | 420 | fm3130->regs[FM3130_CAL_CONTROL] = |
370 | i2c_smbus_read_byte_data(client, FM3130_CAL_CONTROL); | 421 | i2c_smbus_read_byte_data(client, FM3130_CAL_CONTROL); |
371 | 422 | ||
372 | /* Checking for alarm */ | ||
373 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) { | ||
374 | fm3130->alarm = 1; | ||
375 | fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF; | ||
376 | } | ||
377 | |||
378 | /* Disabling calibration mode */ | 423 | /* Disabling calibration mode */ |
379 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) | 424 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) { |
380 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, | 425 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, |
381 | fm3130->regs[FM3130_RTC_CONTROL] & | 426 | fm3130->regs[FM3130_RTC_CONTROL] & |
382 | ~(FM3130_RTC_CONTROL_BIT_CAL)); | 427 | ~(FM3130_RTC_CONTROL_BIT_CAL)); |
383 | dev_warn(&client->dev, "Disabling calibration mode!\n"); | 428 | dev_warn(&client->dev, "Disabling calibration mode!\n"); |
429 | } | ||
384 | 430 | ||
385 | /* Disabling read and write modes */ | 431 | /* Disabling read and write modes */ |
386 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE || | 432 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE || |
387 | fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) | 433 | fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) { |
388 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, | 434 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, |
389 | fm3130->regs[FM3130_RTC_CONTROL] & | 435 | fm3130->regs[FM3130_RTC_CONTROL] & |
390 | ~(FM3130_RTC_CONTROL_BIT_READ | | 436 | ~(FM3130_RTC_CONTROL_BIT_READ | |
391 | FM3130_RTC_CONTROL_BIT_WRITE)); | 437 | FM3130_RTC_CONTROL_BIT_WRITE)); |
392 | dev_warn(&client->dev, "Disabling READ or WRITE mode!\n"); | 438 | dev_warn(&client->dev, "Disabling READ or WRITE mode!\n"); |
439 | } | ||
393 | 440 | ||
394 | /* oscillator off? turn it on, so clock can tick. */ | 441 | /* oscillator off? turn it on, so clock can tick. */ |
395 | if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN) | 442 | if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN) |
@@ -397,44 +444,79 @@ static int __devinit fm3130_probe(struct i2c_client *client, | |||
397 | fm3130->regs[FM3130_CAL_CONTROL] & | 444 | fm3130->regs[FM3130_CAL_CONTROL] & |
398 | ~(FM3130_CAL_CONTROL_BIT_nOSCEN)); | 445 | ~(FM3130_CAL_CONTROL_BIT_nOSCEN)); |
399 | 446 | ||
400 | /* oscillator fault? clear flag, and warn */ | 447 | /* low battery? clear flag, and warn */ |
401 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_LB) | 448 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_LB) { |
449 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, | ||
450 | fm3130->regs[FM3130_RTC_CONTROL] & | ||
451 | ~(FM3130_RTC_CONTROL_BIT_LB)); | ||
402 | dev_warn(&client->dev, "Low battery!\n"); | 452 | dev_warn(&client->dev, "Low battery!\n"); |
453 | } | ||
403 | 454 | ||
404 | /* oscillator fault? clear flag, and warn */ | 455 | /* check if Power On Reset bit is set */ |
405 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_POR) { | 456 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_POR) { |
406 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, | 457 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, |
407 | fm3130->regs[FM3130_RTC_CONTROL] & | 458 | fm3130->regs[FM3130_RTC_CONTROL] & |
408 | ~FM3130_RTC_CONTROL_BIT_POR); | 459 | ~FM3130_RTC_CONTROL_BIT_POR); |
409 | dev_warn(&client->dev, "SET TIME!\n"); | 460 | dev_dbg(&client->dev, "POR bit is set\n"); |
410 | } | 461 | } |
411 | /* ACS is controlled by alarm */ | 462 | /* ACS is controlled by alarm */ |
412 | i2c_smbus_write_byte_data(client, FM3130_ALARM_WP_CONTROL, 0x80); | 463 | i2c_smbus_write_byte_data(client, FM3130_ALARM_WP_CONTROL, 0x80); |
413 | 464 | ||
414 | /* TODO */ | 465 | /* alarm registers sanity check */ |
415 | /* TODO need to sanity check alarm */ | 466 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f); |
416 | tmp = fm3130->regs[FM3130_RTC_SECONDS]; | 467 | if (tmp > 59) |
417 | tmp = bcd2bin(tmp & 0x7f); | 468 | goto bad_alarm; |
418 | if (tmp > 60) | 469 | |
419 | goto exit_bad; | ||
420 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); | 470 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); |
421 | if (tmp > 60) | 471 | if (tmp > 59) |
422 | goto exit_bad; | 472 | goto bad_alarm; |
473 | |||
474 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f); | ||
475 | if (tmp > 23) | ||
476 | goto bad_alarm; | ||
423 | 477 | ||
424 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f); | 478 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f); |
425 | if (tmp == 0 || tmp > 31) | 479 | if (tmp == 0 || tmp > 31) |
426 | goto exit_bad; | 480 | goto bad_alarm; |
427 | 481 | ||
428 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f); | 482 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f); |
429 | if (tmp == 0 || tmp > 12) | 483 | if (tmp == 0 || tmp > 12) |
430 | goto exit_bad; | 484 | goto bad_alarm; |
431 | 485 | ||
432 | tmp = fm3130->regs[FM3130_RTC_HOURS]; | 486 | fm3130->alarm_valid = 1; |
487 | |||
488 | bad_alarm: | ||
489 | |||
490 | /* clock registers sanity chek */ | ||
491 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f); | ||
492 | if (tmp > 59) | ||
493 | goto bad_clock; | ||
494 | |||
495 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); | ||
496 | if (tmp > 59) | ||
497 | goto bad_clock; | ||
498 | |||
499 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f); | ||
500 | if (tmp > 23) | ||
501 | goto bad_clock; | ||
502 | |||
503 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_DAY] & 0x7); | ||
504 | if (tmp == 0 || tmp > 7) | ||
505 | goto bad_clock; | ||
506 | |||
507 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f); | ||
508 | if (tmp == 0 || tmp > 31) | ||
509 | goto bad_clock; | ||
510 | |||
511 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f); | ||
512 | if (tmp == 0 || tmp > 12) | ||
513 | goto bad_clock; | ||
433 | 514 | ||
434 | fm3130->data_valid = 1; | 515 | fm3130->data_valid = 1; |
435 | 516 | ||
436 | exit_bad: | 517 | bad_clock: |
437 | if (!fm3130->data_valid) | 518 | |
519 | if (!fm3130->data_valid || !fm3130->alarm_valid) | ||
438 | dev_dbg(&client->dev, | 520 | dev_dbg(&client->dev, |
439 | "%s: %02x %02x %02x %02x %02x %02x %02x %02x" | 521 | "%s: %02x %02x %02x %02x %02x %02x %02x %02x" |
440 | "%02x %02x %02x %02x %02x %02x %02x\n", | 522 | "%02x %02x %02x %02x %02x %02x %02x\n", |
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c new file mode 100644 index 000000000000..2dd3c0163272 --- /dev/null +++ b/drivers/rtc/rtc-imxdi.c | |||
@@ -0,0 +1,519 @@ | |||
1 | /* | ||
2 | * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | * Copyright 2010 Orex Computed Radiography | ||
4 | */ | ||
5 | |||
6 | /* | ||
7 | * The code contained herein is licensed under the GNU General Public | ||
8 | * License. You may obtain a copy of the GNU General Public License | ||
9 | * Version 2 or later at the following locations: | ||
10 | * | ||
11 | * http://www.opensource.org/licenses/gpl-license.html | ||
12 | * http://www.gnu.org/copyleft/gpl.html | ||
13 | */ | ||
14 | |||
15 | /* based on rtc-mc13892.c */ | ||
16 | |||
17 | /* | ||
18 | * This driver uses the 47-bit 32 kHz counter in the Freescale DryIce block | ||
19 | * to implement a Linux RTC. Times and alarms are truncated to seconds. | ||
20 | * Since the RTC framework performs API locking via rtc->ops_lock the | ||
21 | * only simultaneous accesses we need to deal with is updating DryIce | ||
22 | * registers while servicing an alarm. | ||
23 | * | ||
24 | * Note that reading the DSR (DryIce Status Register) automatically clears | ||
25 | * the WCF (Write Complete Flag). All DryIce writes are synchronized to the | ||
26 | * LP (Low Power) domain and set the WCF upon completion. Writes to the | ||
27 | * DIER (DryIce Interrupt Enable Register) are the only exception. These | ||
28 | * occur at normal bus speeds and do not set WCF. Periodic interrupts are | ||
29 | * not supported by the hardware. | ||
30 | */ | ||
31 | |||
32 | #include <linux/io.h> | ||
33 | #include <linux/clk.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/platform_device.h> | ||
37 | #include <linux/rtc.h> | ||
38 | #include <linux/workqueue.h> | ||
39 | |||
40 | /* DryIce Register Definitions */ | ||
41 | |||
42 | #define DTCMR 0x00 /* Time Counter MSB Reg */ | ||
43 | #define DTCLR 0x04 /* Time Counter LSB Reg */ | ||
44 | |||
45 | #define DCAMR 0x08 /* Clock Alarm MSB Reg */ | ||
46 | #define DCALR 0x0c /* Clock Alarm LSB Reg */ | ||
47 | #define DCAMR_UNSET 0xFFFFFFFF /* doomsday - 1 sec */ | ||
48 | |||
49 | #define DCR 0x10 /* Control Reg */ | ||
50 | #define DCR_TCE (1 << 3) /* Time Counter Enable */ | ||
51 | |||
52 | #define DSR 0x14 /* Status Reg */ | ||
53 | #define DSR_WBF (1 << 10) /* Write Busy Flag */ | ||
54 | #define DSR_WNF (1 << 9) /* Write Next Flag */ | ||
55 | #define DSR_WCF (1 << 8) /* Write Complete Flag */ | ||
56 | #define DSR_WEF (1 << 7) /* Write Error Flag */ | ||
57 | #define DSR_CAF (1 << 4) /* Clock Alarm Flag */ | ||
58 | #define DSR_NVF (1 << 1) /* Non-Valid Flag */ | ||
59 | #define DSR_SVF (1 << 0) /* Security Violation Flag */ | ||
60 | |||
61 | #define DIER 0x18 /* Interrupt Enable Reg */ | ||
62 | #define DIER_WNIE (1 << 9) /* Write Next Interrupt Enable */ | ||
63 | #define DIER_WCIE (1 << 8) /* Write Complete Interrupt Enable */ | ||
64 | #define DIER_WEIE (1 << 7) /* Write Error Interrupt Enable */ | ||
65 | #define DIER_CAIE (1 << 4) /* Clock Alarm Interrupt Enable */ | ||
66 | |||
67 | /** | ||
68 | * struct imxdi_dev - private imxdi rtc data | ||
69 | * @pdev: pionter to platform dev | ||
70 | * @rtc: pointer to rtc struct | ||
71 | * @ioaddr: IO registers pointer | ||
72 | * @irq: dryice normal interrupt | ||
73 | * @clk: input reference clock | ||
74 | * @dsr: copy of the DSR register | ||
75 | * @irq_lock: interrupt enable register (DIER) lock | ||
76 | * @write_wait: registers write complete queue | ||
77 | * @write_mutex: serialize registers write | ||
78 | * @work: schedule alarm work | ||
79 | */ | ||
80 | struct imxdi_dev { | ||
81 | struct platform_device *pdev; | ||
82 | struct rtc_device *rtc; | ||
83 | void __iomem *ioaddr; | ||
84 | int irq; | ||
85 | struct clk *clk; | ||
86 | u32 dsr; | ||
87 | spinlock_t irq_lock; | ||
88 | wait_queue_head_t write_wait; | ||
89 | struct mutex write_mutex; | ||
90 | struct work_struct work; | ||
91 | }; | ||
92 | |||
93 | /* | ||
94 | * enable a dryice interrupt | ||
95 | */ | ||
96 | static void di_int_enable(struct imxdi_dev *imxdi, u32 intr) | ||
97 | { | ||
98 | unsigned long flags; | ||
99 | |||
100 | spin_lock_irqsave(&imxdi->irq_lock, flags); | ||
101 | __raw_writel(__raw_readl(imxdi->ioaddr + DIER) | intr, | ||
102 | imxdi->ioaddr + DIER); | ||
103 | spin_unlock_irqrestore(&imxdi->irq_lock, flags); | ||
104 | } | ||
105 | |||
106 | /* | ||
107 | * disable a dryice interrupt | ||
108 | */ | ||
109 | static void di_int_disable(struct imxdi_dev *imxdi, u32 intr) | ||
110 | { | ||
111 | unsigned long flags; | ||
112 | |||
113 | spin_lock_irqsave(&imxdi->irq_lock, flags); | ||
114 | __raw_writel(__raw_readl(imxdi->ioaddr + DIER) & ~intr, | ||
115 | imxdi->ioaddr + DIER); | ||
116 | spin_unlock_irqrestore(&imxdi->irq_lock, flags); | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * This function attempts to clear the dryice write-error flag. | ||
121 | * | ||
122 | * A dryice write error is similar to a bus fault and should not occur in | ||
123 | * normal operation. Clearing the flag requires another write, so the root | ||
124 | * cause of the problem may need to be fixed before the flag can be cleared. | ||
125 | */ | ||
126 | static void clear_write_error(struct imxdi_dev *imxdi) | ||
127 | { | ||
128 | int cnt; | ||
129 | |||
130 | dev_warn(&imxdi->pdev->dev, "WARNING: Register write error!\n"); | ||
131 | |||
132 | /* clear the write error flag */ | ||
133 | __raw_writel(DSR_WEF, imxdi->ioaddr + DSR); | ||
134 | |||
135 | /* wait for it to take effect */ | ||
136 | for (cnt = 0; cnt < 1000; cnt++) { | ||
137 | if ((__raw_readl(imxdi->ioaddr + DSR) & DSR_WEF) == 0) | ||
138 | return; | ||
139 | udelay(10); | ||
140 | } | ||
141 | dev_err(&imxdi->pdev->dev, | ||
142 | "ERROR: Cannot clear write-error flag!\n"); | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * Write a dryice register and wait until it completes. | ||
147 | * | ||
148 | * This function uses interrupts to determine when the | ||
149 | * write has completed. | ||
150 | */ | ||
151 | static int di_write_wait(struct imxdi_dev *imxdi, u32 val, int reg) | ||
152 | { | ||
153 | int ret; | ||
154 | int rc = 0; | ||
155 | |||
156 | /* serialize register writes */ | ||
157 | mutex_lock(&imxdi->write_mutex); | ||
158 | |||
159 | /* enable the write-complete interrupt */ | ||
160 | di_int_enable(imxdi, DIER_WCIE); | ||
161 | |||
162 | imxdi->dsr = 0; | ||
163 | |||
164 | /* do the register write */ | ||
165 | __raw_writel(val, imxdi->ioaddr + reg); | ||
166 | |||
167 | /* wait for the write to finish */ | ||
168 | ret = wait_event_interruptible_timeout(imxdi->write_wait, | ||
169 | imxdi->dsr & (DSR_WCF | DSR_WEF), msecs_to_jiffies(1)); | ||
170 | if (ret < 0) { | ||
171 | rc = ret; | ||
172 | goto out; | ||
173 | } else if (ret == 0) { | ||
174 | dev_warn(&imxdi->pdev->dev, | ||
175 | "Write-wait timeout " | ||
176 | "val = 0x%08x reg = 0x%08x\n", val, reg); | ||
177 | } | ||
178 | |||
179 | /* check for write error */ | ||
180 | if (imxdi->dsr & DSR_WEF) { | ||
181 | clear_write_error(imxdi); | ||
182 | rc = -EIO; | ||
183 | } | ||
184 | |||
185 | out: | ||
186 | mutex_unlock(&imxdi->write_mutex); | ||
187 | |||
188 | return rc; | ||
189 | } | ||
190 | |||
191 | /* | ||
192 | * read the seconds portion of the current time from the dryice time counter | ||
193 | */ | ||
194 | static int dryice_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
195 | { | ||
196 | struct imxdi_dev *imxdi = dev_get_drvdata(dev); | ||
197 | unsigned long now; | ||
198 | |||
199 | now = __raw_readl(imxdi->ioaddr + DTCMR); | ||
200 | rtc_time_to_tm(now, tm); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * set the seconds portion of dryice time counter and clear the | ||
207 | * fractional part. | ||
208 | */ | ||
209 | static int dryice_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
210 | { | ||
211 | struct imxdi_dev *imxdi = dev_get_drvdata(dev); | ||
212 | int rc; | ||
213 | |||
214 | /* zero the fractional part first */ | ||
215 | rc = di_write_wait(imxdi, 0, DTCLR); | ||
216 | if (rc == 0) | ||
217 | rc = di_write_wait(imxdi, secs, DTCMR); | ||
218 | |||
219 | return rc; | ||
220 | } | ||
221 | |||
222 | static int dryice_rtc_alarm_irq_enable(struct device *dev, | ||
223 | unsigned int enabled) | ||
224 | { | ||
225 | struct imxdi_dev *imxdi = dev_get_drvdata(dev); | ||
226 | |||
227 | if (enabled) | ||
228 | di_int_enable(imxdi, DIER_CAIE); | ||
229 | else | ||
230 | di_int_disable(imxdi, DIER_CAIE); | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | /* | ||
236 | * read the seconds portion of the alarm register. | ||
237 | * the fractional part of the alarm register is always zero. | ||
238 | */ | ||
239 | static int dryice_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
240 | { | ||
241 | struct imxdi_dev *imxdi = dev_get_drvdata(dev); | ||
242 | u32 dcamr; | ||
243 | |||
244 | dcamr = __raw_readl(imxdi->ioaddr + DCAMR); | ||
245 | rtc_time_to_tm(dcamr, &alarm->time); | ||
246 | |||
247 | /* alarm is enabled if the interrupt is enabled */ | ||
248 | alarm->enabled = (__raw_readl(imxdi->ioaddr + DIER) & DIER_CAIE) != 0; | ||
249 | |||
250 | /* don't allow the DSR read to mess up DSR_WCF */ | ||
251 | mutex_lock(&imxdi->write_mutex); | ||
252 | |||
253 | /* alarm is pending if the alarm flag is set */ | ||
254 | alarm->pending = (__raw_readl(imxdi->ioaddr + DSR) & DSR_CAF) != 0; | ||
255 | |||
256 | mutex_unlock(&imxdi->write_mutex); | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | /* | ||
262 | * set the seconds portion of dryice alarm register | ||
263 | */ | ||
264 | static int dryice_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
265 | { | ||
266 | struct imxdi_dev *imxdi = dev_get_drvdata(dev); | ||
267 | unsigned long now; | ||
268 | unsigned long alarm_time; | ||
269 | int rc; | ||
270 | |||
271 | rc = rtc_tm_to_time(&alarm->time, &alarm_time); | ||
272 | if (rc) | ||
273 | return rc; | ||
274 | |||
275 | /* don't allow setting alarm in the past */ | ||
276 | now = __raw_readl(imxdi->ioaddr + DTCMR); | ||
277 | if (alarm_time < now) | ||
278 | return -EINVAL; | ||
279 | |||
280 | /* write the new alarm time */ | ||
281 | rc = di_write_wait(imxdi, (u32)alarm_time, DCAMR); | ||
282 | if (rc) | ||
283 | return rc; | ||
284 | |||
285 | if (alarm->enabled) | ||
286 | di_int_enable(imxdi, DIER_CAIE); /* enable alarm intr */ | ||
287 | else | ||
288 | di_int_disable(imxdi, DIER_CAIE); /* disable alarm intr */ | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static struct rtc_class_ops dryice_rtc_ops = { | ||
294 | .read_time = dryice_rtc_read_time, | ||
295 | .set_mmss = dryice_rtc_set_mmss, | ||
296 | .alarm_irq_enable = dryice_rtc_alarm_irq_enable, | ||
297 | .read_alarm = dryice_rtc_read_alarm, | ||
298 | .set_alarm = dryice_rtc_set_alarm, | ||
299 | }; | ||
300 | |||
301 | /* | ||
302 | * dryice "normal" interrupt handler | ||
303 | */ | ||
304 | static irqreturn_t dryice_norm_irq(int irq, void *dev_id) | ||
305 | { | ||
306 | struct imxdi_dev *imxdi = dev_id; | ||
307 | u32 dsr, dier; | ||
308 | irqreturn_t rc = IRQ_NONE; | ||
309 | |||
310 | dier = __raw_readl(imxdi->ioaddr + DIER); | ||
311 | |||
312 | /* handle write complete and write error cases */ | ||
313 | if ((dier & DIER_WCIE)) { | ||
314 | /*If the write wait queue is empty then there is no pending | ||
315 | operations. It means the interrupt is for DryIce -Security. | ||
316 | IRQ must be returned as none.*/ | ||
317 | if (list_empty_careful(&imxdi->write_wait.task_list)) | ||
318 | return rc; | ||
319 | |||
320 | /* DSR_WCF clears itself on DSR read */ | ||
321 | dsr = __raw_readl(imxdi->ioaddr + DSR); | ||
322 | if ((dsr & (DSR_WCF | DSR_WEF))) { | ||
323 | /* mask the interrupt */ | ||
324 | di_int_disable(imxdi, DIER_WCIE); | ||
325 | |||
326 | /* save the dsr value for the wait queue */ | ||
327 | imxdi->dsr |= dsr; | ||
328 | |||
329 | wake_up_interruptible(&imxdi->write_wait); | ||
330 | rc = IRQ_HANDLED; | ||
331 | } | ||
332 | } | ||
333 | |||
334 | /* handle the alarm case */ | ||
335 | if ((dier & DIER_CAIE)) { | ||
336 | /* DSR_WCF clears itself on DSR read */ | ||
337 | dsr = __raw_readl(imxdi->ioaddr + DSR); | ||
338 | if (dsr & DSR_CAF) { | ||
339 | /* mask the interrupt */ | ||
340 | di_int_disable(imxdi, DIER_CAIE); | ||
341 | |||
342 | /* finish alarm in user context */ | ||
343 | schedule_work(&imxdi->work); | ||
344 | rc = IRQ_HANDLED; | ||
345 | } | ||
346 | } | ||
347 | return rc; | ||
348 | } | ||
349 | |||
350 | /* | ||
351 | * post the alarm event from user context so it can sleep | ||
352 | * on the write completion. | ||
353 | */ | ||
354 | static void dryice_work(struct work_struct *work) | ||
355 | { | ||
356 | struct imxdi_dev *imxdi = container_of(work, | ||
357 | struct imxdi_dev, work); | ||
358 | |||
359 | /* dismiss the interrupt (ignore error) */ | ||
360 | di_write_wait(imxdi, DSR_CAF, DSR); | ||
361 | |||
362 | /* pass the alarm event to the rtc framework. */ | ||
363 | rtc_update_irq(imxdi->rtc, 1, RTC_AF | RTC_IRQF); | ||
364 | } | ||
365 | |||
366 | /* | ||
367 | * probe for dryice rtc device | ||
368 | */ | ||
369 | static int dryice_rtc_probe(struct platform_device *pdev) | ||
370 | { | ||
371 | struct resource *res; | ||
372 | struct imxdi_dev *imxdi; | ||
373 | int rc; | ||
374 | |||
375 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
376 | if (!res) | ||
377 | return -ENODEV; | ||
378 | |||
379 | imxdi = devm_kzalloc(&pdev->dev, sizeof(*imxdi), GFP_KERNEL); | ||
380 | if (!imxdi) | ||
381 | return -ENOMEM; | ||
382 | |||
383 | imxdi->pdev = pdev; | ||
384 | |||
385 | if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), | ||
386 | pdev->name)) | ||
387 | return -EBUSY; | ||
388 | |||
389 | imxdi->ioaddr = devm_ioremap(&pdev->dev, res->start, | ||
390 | resource_size(res)); | ||
391 | if (imxdi->ioaddr == NULL) | ||
392 | return -ENOMEM; | ||
393 | |||
394 | imxdi->irq = platform_get_irq(pdev, 0); | ||
395 | if (imxdi->irq < 0) | ||
396 | return imxdi->irq; | ||
397 | |||
398 | init_waitqueue_head(&imxdi->write_wait); | ||
399 | |||
400 | INIT_WORK(&imxdi->work, dryice_work); | ||
401 | |||
402 | mutex_init(&imxdi->write_mutex); | ||
403 | |||
404 | imxdi->clk = clk_get(&pdev->dev, NULL); | ||
405 | if (IS_ERR(imxdi->clk)) | ||
406 | return PTR_ERR(imxdi->clk); | ||
407 | clk_enable(imxdi->clk); | ||
408 | |||
409 | /* | ||
410 | * Initialize dryice hardware | ||
411 | */ | ||
412 | |||
413 | /* mask all interrupts */ | ||
414 | __raw_writel(0, imxdi->ioaddr + DIER); | ||
415 | |||
416 | rc = devm_request_irq(&pdev->dev, imxdi->irq, dryice_norm_irq, | ||
417 | IRQF_SHARED, pdev->name, imxdi); | ||
418 | if (rc) { | ||
419 | dev_warn(&pdev->dev, "interrupt not available.\n"); | ||
420 | goto err; | ||
421 | } | ||
422 | |||
423 | /* put dryice into valid state */ | ||
424 | if (__raw_readl(imxdi->ioaddr + DSR) & DSR_NVF) { | ||
425 | rc = di_write_wait(imxdi, DSR_NVF | DSR_SVF, DSR); | ||
426 | if (rc) | ||
427 | goto err; | ||
428 | } | ||
429 | |||
430 | /* initialize alarm */ | ||
431 | rc = di_write_wait(imxdi, DCAMR_UNSET, DCAMR); | ||
432 | if (rc) | ||
433 | goto err; | ||
434 | rc = di_write_wait(imxdi, 0, DCALR); | ||
435 | if (rc) | ||
436 | goto err; | ||
437 | |||
438 | /* clear alarm flag */ | ||
439 | if (__raw_readl(imxdi->ioaddr + DSR) & DSR_CAF) { | ||
440 | rc = di_write_wait(imxdi, DSR_CAF, DSR); | ||
441 | if (rc) | ||
442 | goto err; | ||
443 | } | ||
444 | |||
445 | /* the timer won't count if it has never been written to */ | ||
446 | if (__raw_readl(imxdi->ioaddr + DTCMR) == 0) { | ||
447 | rc = di_write_wait(imxdi, 0, DTCMR); | ||
448 | if (rc) | ||
449 | goto err; | ||
450 | } | ||
451 | |||
452 | /* start keeping time */ | ||
453 | if (!(__raw_readl(imxdi->ioaddr + DCR) & DCR_TCE)) { | ||
454 | rc = di_write_wait(imxdi, | ||
455 | __raw_readl(imxdi->ioaddr + DCR) | DCR_TCE, | ||
456 | DCR); | ||
457 | if (rc) | ||
458 | goto err; | ||
459 | } | ||
460 | |||
461 | platform_set_drvdata(pdev, imxdi); | ||
462 | imxdi->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
463 | &dryice_rtc_ops, THIS_MODULE); | ||
464 | if (IS_ERR(imxdi->rtc)) { | ||
465 | rc = PTR_ERR(imxdi->rtc); | ||
466 | goto err; | ||
467 | } | ||
468 | |||
469 | return 0; | ||
470 | |||
471 | err: | ||
472 | clk_disable(imxdi->clk); | ||
473 | clk_put(imxdi->clk); | ||
474 | |||
475 | return rc; | ||
476 | } | ||
477 | |||
478 | static int __devexit dryice_rtc_remove(struct platform_device *pdev) | ||
479 | { | ||
480 | struct imxdi_dev *imxdi = platform_get_drvdata(pdev); | ||
481 | |||
482 | flush_work(&imxdi->work); | ||
483 | |||
484 | /* mask all interrupts */ | ||
485 | __raw_writel(0, imxdi->ioaddr + DIER); | ||
486 | |||
487 | rtc_device_unregister(imxdi->rtc); | ||
488 | |||
489 | clk_disable(imxdi->clk); | ||
490 | clk_put(imxdi->clk); | ||
491 | |||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | static struct platform_driver dryice_rtc_driver = { | ||
496 | .driver = { | ||
497 | .name = "imxdi_rtc", | ||
498 | .owner = THIS_MODULE, | ||
499 | }, | ||
500 | .remove = __devexit_p(dryice_rtc_remove), | ||
501 | }; | ||
502 | |||
503 | static int __init dryice_rtc_init(void) | ||
504 | { | ||
505 | return platform_driver_probe(&dryice_rtc_driver, dryice_rtc_probe); | ||
506 | } | ||
507 | |||
508 | static void __exit dryice_rtc_exit(void) | ||
509 | { | ||
510 | platform_driver_unregister(&dryice_rtc_driver); | ||
511 | } | ||
512 | |||
513 | module_init(dryice_rtc_init); | ||
514 | module_exit(dryice_rtc_exit); | ||
515 | |||
516 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
517 | MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); | ||
518 | MODULE_DESCRIPTION("IMX DryIce Realtime Clock Driver (RTC)"); | ||
519 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c new file mode 100644 index 000000000000..ddbc797ea6cd --- /dev/null +++ b/drivers/rtc/rtc-isl12022.c | |||
@@ -0,0 +1,327 @@ | |||
1 | /* | ||
2 | * An I2C driver for the Intersil ISL 12022 | ||
3 | * | ||
4 | * Author: Roman Fietze <roman.fietze@telemotive.de> | ||
5 | * | ||
6 | * Based on the Philips PCF8563 RTC | ||
7 | * by Alessandro Zummo <a.zummo@towertech.it>. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License version | ||
11 | * 2 as published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/bcd.h> | ||
16 | #include <linux/rtc.h> | ||
17 | #include <linux/slab.h> | ||
18 | |||
19 | #define DRV_VERSION "0.1" | ||
20 | |||
21 | /* ISL register offsets */ | ||
22 | #define ISL12022_REG_SC 0x00 | ||
23 | #define ISL12022_REG_MN 0x01 | ||
24 | #define ISL12022_REG_HR 0x02 | ||
25 | #define ISL12022_REG_DT 0x03 | ||
26 | #define ISL12022_REG_MO 0x04 | ||
27 | #define ISL12022_REG_YR 0x05 | ||
28 | #define ISL12022_REG_DW 0x06 | ||
29 | |||
30 | #define ISL12022_REG_SR 0x07 | ||
31 | #define ISL12022_REG_INT 0x08 | ||
32 | |||
33 | /* ISL register bits */ | ||
34 | #define ISL12022_HR_MIL (1 << 7) /* military or 24 hour time */ | ||
35 | |||
36 | #define ISL12022_SR_LBAT85 (1 << 2) | ||
37 | #define ISL12022_SR_LBAT75 (1 << 1) | ||
38 | |||
39 | #define ISL12022_INT_WRTC (1 << 6) | ||
40 | |||
41 | |||
42 | static struct i2c_driver isl12022_driver; | ||
43 | |||
44 | struct isl12022 { | ||
45 | struct rtc_device *rtc; | ||
46 | |||
47 | bool write_enabled; /* true if write enable is set */ | ||
48 | }; | ||
49 | |||
50 | |||
51 | static int isl12022_read_regs(struct i2c_client *client, uint8_t reg, | ||
52 | uint8_t *data, size_t n) | ||
53 | { | ||
54 | struct i2c_msg msgs[] = { | ||
55 | { | ||
56 | .addr = client->addr, | ||
57 | .flags = 0, | ||
58 | .len = 1, | ||
59 | .buf = data | ||
60 | }, /* setup read ptr */ | ||
61 | { | ||
62 | .addr = client->addr, | ||
63 | .flags = I2C_M_RD, | ||
64 | .len = n, | ||
65 | .buf = data | ||
66 | } | ||
67 | }; | ||
68 | |||
69 | int ret; | ||
70 | |||
71 | data[0] = reg; | ||
72 | ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
73 | if (ret != ARRAY_SIZE(msgs)) { | ||
74 | dev_err(&client->dev, "%s: read error, ret=%d\n", | ||
75 | __func__, ret); | ||
76 | return -EIO; | ||
77 | } | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | |||
83 | static int isl12022_write_reg(struct i2c_client *client, | ||
84 | uint8_t reg, uint8_t val) | ||
85 | { | ||
86 | uint8_t data[2] = { reg, val }; | ||
87 | int err; | ||
88 | |||
89 | err = i2c_master_send(client, data, sizeof(data)); | ||
90 | if (err != sizeof(data)) { | ||
91 | dev_err(&client->dev, | ||
92 | "%s: err=%d addr=%02x, data=%02x\n", | ||
93 | __func__, err, data[0], data[1]); | ||
94 | return -EIO; | ||
95 | } | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | |||
101 | /* | ||
102 | * In the routines that deal directly with the isl12022 hardware, we use | ||
103 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. | ||
104 | */ | ||
105 | static int isl12022_get_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
106 | { | ||
107 | uint8_t buf[ISL12022_REG_INT + 1]; | ||
108 | int ret; | ||
109 | |||
110 | ret = isl12022_read_regs(client, ISL12022_REG_SC, buf, sizeof(buf)); | ||
111 | if (ret) | ||
112 | return ret; | ||
113 | |||
114 | if (buf[ISL12022_REG_SR] & (ISL12022_SR_LBAT85 | ISL12022_SR_LBAT75)) { | ||
115 | dev_warn(&client->dev, | ||
116 | "voltage dropped below %u%%, " | ||
117 | "date and time is not reliable.\n", | ||
118 | buf[ISL12022_REG_SR] & ISL12022_SR_LBAT85 ? 85 : 75); | ||
119 | } | ||
120 | |||
121 | dev_dbg(&client->dev, | ||
122 | "%s: raw data is sec=%02x, min=%02x, hr=%02x, " | ||
123 | "mday=%02x, mon=%02x, year=%02x, wday=%02x, " | ||
124 | "sr=%02x, int=%02x", | ||
125 | __func__, | ||
126 | buf[ISL12022_REG_SC], | ||
127 | buf[ISL12022_REG_MN], | ||
128 | buf[ISL12022_REG_HR], | ||
129 | buf[ISL12022_REG_DT], | ||
130 | buf[ISL12022_REG_MO], | ||
131 | buf[ISL12022_REG_YR], | ||
132 | buf[ISL12022_REG_DW], | ||
133 | buf[ISL12022_REG_SR], | ||
134 | buf[ISL12022_REG_INT]); | ||
135 | |||
136 | tm->tm_sec = bcd2bin(buf[ISL12022_REG_SC] & 0x7F); | ||
137 | tm->tm_min = bcd2bin(buf[ISL12022_REG_MN] & 0x7F); | ||
138 | tm->tm_hour = bcd2bin(buf[ISL12022_REG_HR] & 0x3F); | ||
139 | tm->tm_mday = bcd2bin(buf[ISL12022_REG_DT] & 0x3F); | ||
140 | tm->tm_wday = buf[ISL12022_REG_DW] & 0x07; | ||
141 | tm->tm_mon = bcd2bin(buf[ISL12022_REG_MO] & 0x1F) - 1; | ||
142 | tm->tm_year = bcd2bin(buf[ISL12022_REG_YR]) + 100; | ||
143 | |||
144 | dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " | ||
145 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
146 | __func__, | ||
147 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
148 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
149 | |||
150 | /* The clock can give out invalid datetime, but we cannot return | ||
151 | * -EINVAL otherwise hwclock will refuse to set the time on bootup. */ | ||
152 | if (rtc_valid_tm(tm) < 0) | ||
153 | dev_err(&client->dev, "retrieved date and time is invalid.\n"); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static int isl12022_set_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
159 | { | ||
160 | struct isl12022 *isl12022 = i2c_get_clientdata(client); | ||
161 | size_t i; | ||
162 | int ret; | ||
163 | uint8_t buf[ISL12022_REG_DW + 1]; | ||
164 | |||
165 | dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " | ||
166 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
167 | __func__, | ||
168 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
169 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
170 | |||
171 | if (!isl12022->write_enabled) { | ||
172 | |||
173 | ret = isl12022_read_regs(client, ISL12022_REG_INT, buf, 1); | ||
174 | if (ret) | ||
175 | return ret; | ||
176 | |||
177 | /* Check if WRTC (write rtc enable) is set factory default is | ||
178 | * 0 (not set) */ | ||
179 | if (!(buf[0] & ISL12022_INT_WRTC)) { | ||
180 | dev_info(&client->dev, | ||
181 | "init write enable and 24 hour format\n"); | ||
182 | |||
183 | /* Set the write enable bit. */ | ||
184 | ret = isl12022_write_reg(client, | ||
185 | ISL12022_REG_INT, | ||
186 | buf[0] | ISL12022_INT_WRTC); | ||
187 | if (ret) | ||
188 | return ret; | ||
189 | |||
190 | /* Write to any RTC register to start RTC, we use the | ||
191 | * HR register, setting the MIL bit to use the 24 hour | ||
192 | * format. */ | ||
193 | ret = isl12022_read_regs(client, ISL12022_REG_HR, | ||
194 | buf, 1); | ||
195 | if (ret) | ||
196 | return ret; | ||
197 | |||
198 | ret = isl12022_write_reg(client, | ||
199 | ISL12022_REG_HR, | ||
200 | buf[0] | ISL12022_HR_MIL); | ||
201 | if (ret) | ||
202 | return ret; | ||
203 | } | ||
204 | |||
205 | isl12022->write_enabled = 1; | ||
206 | } | ||
207 | |||
208 | /* hours, minutes and seconds */ | ||
209 | buf[ISL12022_REG_SC] = bin2bcd(tm->tm_sec); | ||
210 | buf[ISL12022_REG_MN] = bin2bcd(tm->tm_min); | ||
211 | buf[ISL12022_REG_HR] = bin2bcd(tm->tm_hour) | ISL12022_HR_MIL; | ||
212 | |||
213 | buf[ISL12022_REG_DT] = bin2bcd(tm->tm_mday); | ||
214 | |||
215 | /* month, 1 - 12 */ | ||
216 | buf[ISL12022_REG_MO] = bin2bcd(tm->tm_mon + 1); | ||
217 | |||
218 | /* year and century */ | ||
219 | buf[ISL12022_REG_YR] = bin2bcd(tm->tm_year % 100); | ||
220 | |||
221 | buf[ISL12022_REG_DW] = tm->tm_wday & 0x07; | ||
222 | |||
223 | /* write register's data */ | ||
224 | for (i = 0; i < ARRAY_SIZE(buf); i++) { | ||
225 | ret = isl12022_write_reg(client, ISL12022_REG_SC + i, | ||
226 | buf[ISL12022_REG_SC + i]); | ||
227 | if (ret) | ||
228 | return -EIO; | ||
229 | }; | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
235 | { | ||
236 | return isl12022_get_datetime(to_i2c_client(dev), tm); | ||
237 | } | ||
238 | |||
239 | static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
240 | { | ||
241 | return isl12022_set_datetime(to_i2c_client(dev), tm); | ||
242 | } | ||
243 | |||
244 | static const struct rtc_class_ops isl12022_rtc_ops = { | ||
245 | .read_time = isl12022_rtc_read_time, | ||
246 | .set_time = isl12022_rtc_set_time, | ||
247 | }; | ||
248 | |||
249 | static int isl12022_probe(struct i2c_client *client, | ||
250 | const struct i2c_device_id *id) | ||
251 | { | ||
252 | struct isl12022 *isl12022; | ||
253 | |||
254 | int ret = 0; | ||
255 | |||
256 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | ||
257 | return -ENODEV; | ||
258 | |||
259 | isl12022 = kzalloc(sizeof(struct isl12022), GFP_KERNEL); | ||
260 | if (!isl12022) | ||
261 | return -ENOMEM; | ||
262 | |||
263 | dev_dbg(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | ||
264 | |||
265 | i2c_set_clientdata(client, isl12022); | ||
266 | |||
267 | isl12022->rtc = rtc_device_register(isl12022_driver.driver.name, | ||
268 | &client->dev, | ||
269 | &isl12022_rtc_ops, | ||
270 | THIS_MODULE); | ||
271 | |||
272 | if (IS_ERR(isl12022->rtc)) { | ||
273 | ret = PTR_ERR(isl12022->rtc); | ||
274 | goto exit_kfree; | ||
275 | } | ||
276 | |||
277 | return 0; | ||
278 | |||
279 | exit_kfree: | ||
280 | kfree(isl12022); | ||
281 | |||
282 | return ret; | ||
283 | } | ||
284 | |||
285 | static int isl12022_remove(struct i2c_client *client) | ||
286 | { | ||
287 | struct isl12022 *isl12022 = i2c_get_clientdata(client); | ||
288 | |||
289 | rtc_device_unregister(isl12022->rtc); | ||
290 | kfree(isl12022); | ||
291 | |||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | static const struct i2c_device_id isl12022_id[] = { | ||
296 | { "isl12022", 0 }, | ||
297 | { "rtc8564", 0 }, | ||
298 | { } | ||
299 | }; | ||
300 | MODULE_DEVICE_TABLE(i2c, isl12022_id); | ||
301 | |||
302 | static struct i2c_driver isl12022_driver = { | ||
303 | .driver = { | ||
304 | .name = "rtc-isl12022", | ||
305 | }, | ||
306 | .probe = isl12022_probe, | ||
307 | .remove = isl12022_remove, | ||
308 | .id_table = isl12022_id, | ||
309 | }; | ||
310 | |||
311 | static int __init isl12022_init(void) | ||
312 | { | ||
313 | return i2c_add_driver(&isl12022_driver); | ||
314 | } | ||
315 | |||
316 | static void __exit isl12022_exit(void) | ||
317 | { | ||
318 | i2c_del_driver(&isl12022_driver); | ||
319 | } | ||
320 | |||
321 | module_init(isl12022_init); | ||
322 | module_exit(isl12022_exit); | ||
323 | |||
324 | MODULE_AUTHOR("roman.fietze@telemotive.de"); | ||
325 | MODULE_DESCRIPTION("ISL 12022 RTC driver"); | ||
326 | MODULE_LICENSE("GPL"); | ||
327 | MODULE_VERSION(DRV_VERSION); | ||
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index 054e05294af8..468200c38ecb 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c | |||
@@ -462,39 +462,16 @@ isl1208_sysfs_store_usr(struct device *dev, | |||
462 | static DEVICE_ATTR(usr, S_IRUGO | S_IWUSR, isl1208_sysfs_show_usr, | 462 | static DEVICE_ATTR(usr, S_IRUGO | S_IWUSR, isl1208_sysfs_show_usr, |
463 | isl1208_sysfs_store_usr); | 463 | isl1208_sysfs_store_usr); |
464 | 464 | ||
465 | static int | 465 | static struct attribute *isl1208_rtc_attrs[] = { |
466 | isl1208_sysfs_register(struct device *dev) | 466 | &dev_attr_atrim.attr, |
467 | { | 467 | &dev_attr_dtrim.attr, |
468 | int err; | 468 | &dev_attr_usr.attr, |
469 | 469 | NULL | |
470 | err = device_create_file(dev, &dev_attr_atrim); | 470 | }; |
471 | if (err) | ||
472 | return err; | ||
473 | |||
474 | err = device_create_file(dev, &dev_attr_dtrim); | ||
475 | if (err) { | ||
476 | device_remove_file(dev, &dev_attr_atrim); | ||
477 | return err; | ||
478 | } | ||
479 | |||
480 | err = device_create_file(dev, &dev_attr_usr); | ||
481 | if (err) { | ||
482 | device_remove_file(dev, &dev_attr_atrim); | ||
483 | device_remove_file(dev, &dev_attr_dtrim); | ||
484 | } | ||
485 | |||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | static int | ||
490 | isl1208_sysfs_unregister(struct device *dev) | ||
491 | { | ||
492 | device_remove_file(dev, &dev_attr_dtrim); | ||
493 | device_remove_file(dev, &dev_attr_atrim); | ||
494 | device_remove_file(dev, &dev_attr_usr); | ||
495 | 471 | ||
496 | return 0; | 472 | static const struct attribute_group isl1208_rtc_sysfs_files = { |
497 | } | 473 | .attrs = isl1208_rtc_attrs, |
474 | }; | ||
498 | 475 | ||
499 | static int | 476 | static int |
500 | isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) | 477 | isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) |
@@ -529,7 +506,7 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
529 | dev_warn(&client->dev, "rtc power failure detected, " | 506 | dev_warn(&client->dev, "rtc power failure detected, " |
530 | "please set clock.\n"); | 507 | "please set clock.\n"); |
531 | 508 | ||
532 | rc = isl1208_sysfs_register(&client->dev); | 509 | rc = sysfs_create_group(&client->dev.kobj, &isl1208_rtc_sysfs_files); |
533 | if (rc) | 510 | if (rc) |
534 | goto exit_unregister; | 511 | goto exit_unregister; |
535 | 512 | ||
@@ -546,7 +523,7 @@ isl1208_remove(struct i2c_client *client) | |||
546 | { | 523 | { |
547 | struct rtc_device *rtc = i2c_get_clientdata(client); | 524 | struct rtc_device *rtc = i2c_get_clientdata(client); |
548 | 525 | ||
549 | isl1208_sysfs_unregister(&client->dev); | 526 | sysfs_remove_group(&client->dev.kobj, &isl1208_rtc_sysfs_files); |
550 | rtc_device_unregister(rtc); | 527 | rtc_device_unregister(rtc); |
551 | 528 | ||
552 | return 0; | 529 | return 0; |
diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c new file mode 100644 index 000000000000..2e16f72c9056 --- /dev/null +++ b/drivers/rtc/rtc-jz4740.c | |||
@@ -0,0 +1,380 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> | ||
3 | * Copyright (C) 2010, Paul Cercueil <paul@crapouillou.net> | ||
4 | * JZ4740 SoC RTC driver | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | * You should have received a copy of the GNU General Public License along | ||
12 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
13 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/rtc.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | |||
24 | #define JZ_REG_RTC_CTRL 0x00 | ||
25 | #define JZ_REG_RTC_SEC 0x04 | ||
26 | #define JZ_REG_RTC_SEC_ALARM 0x08 | ||
27 | #define JZ_REG_RTC_REGULATOR 0x0C | ||
28 | #define JZ_REG_RTC_HIBERNATE 0x20 | ||
29 | #define JZ_REG_RTC_SCRATCHPAD 0x34 | ||
30 | |||
31 | #define JZ_RTC_CTRL_WRDY BIT(7) | ||
32 | #define JZ_RTC_CTRL_1HZ BIT(6) | ||
33 | #define JZ_RTC_CTRL_1HZ_IRQ BIT(5) | ||
34 | #define JZ_RTC_CTRL_AF BIT(4) | ||
35 | #define JZ_RTC_CTRL_AF_IRQ BIT(3) | ||
36 | #define JZ_RTC_CTRL_AE BIT(2) | ||
37 | #define JZ_RTC_CTRL_ENABLE BIT(0) | ||
38 | |||
39 | struct jz4740_rtc { | ||
40 | struct resource *mem; | ||
41 | void __iomem *base; | ||
42 | |||
43 | struct rtc_device *rtc; | ||
44 | |||
45 | unsigned int irq; | ||
46 | |||
47 | spinlock_t lock; | ||
48 | }; | ||
49 | |||
50 | static inline uint32_t jz4740_rtc_reg_read(struct jz4740_rtc *rtc, size_t reg) | ||
51 | { | ||
52 | return readl(rtc->base + reg); | ||
53 | } | ||
54 | |||
55 | static int jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc) | ||
56 | { | ||
57 | uint32_t ctrl; | ||
58 | int timeout = 1000; | ||
59 | |||
60 | do { | ||
61 | ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); | ||
62 | } while (!(ctrl & JZ_RTC_CTRL_WRDY) && --timeout); | ||
63 | |||
64 | return timeout ? 0 : -EIO; | ||
65 | } | ||
66 | |||
67 | static inline int jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg, | ||
68 | uint32_t val) | ||
69 | { | ||
70 | int ret; | ||
71 | ret = jz4740_rtc_wait_write_ready(rtc); | ||
72 | if (ret == 0) | ||
73 | writel(val, rtc->base + reg); | ||
74 | |||
75 | return ret; | ||
76 | } | ||
77 | |||
78 | static int jz4740_rtc_ctrl_set_bits(struct jz4740_rtc *rtc, uint32_t mask, | ||
79 | bool set) | ||
80 | { | ||
81 | int ret; | ||
82 | unsigned long flags; | ||
83 | uint32_t ctrl; | ||
84 | |||
85 | spin_lock_irqsave(&rtc->lock, flags); | ||
86 | |||
87 | ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); | ||
88 | |||
89 | /* Don't clear interrupt flags by accident */ | ||
90 | ctrl |= JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF; | ||
91 | |||
92 | if (set) | ||
93 | ctrl |= mask; | ||
94 | else | ||
95 | ctrl &= ~mask; | ||
96 | |||
97 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_CTRL, ctrl); | ||
98 | |||
99 | spin_unlock_irqrestore(&rtc->lock, flags); | ||
100 | |||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | static int jz4740_rtc_read_time(struct device *dev, struct rtc_time *time) | ||
105 | { | ||
106 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
107 | uint32_t secs, secs2; | ||
108 | int timeout = 5; | ||
109 | |||
110 | /* If the seconds register is read while it is updated, it can contain a | ||
111 | * bogus value. This can be avoided by making sure that two consecutive | ||
112 | * reads have the same value. | ||
113 | */ | ||
114 | secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); | ||
115 | secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); | ||
116 | |||
117 | while (secs != secs2 && --timeout) { | ||
118 | secs = secs2; | ||
119 | secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC); | ||
120 | } | ||
121 | |||
122 | if (timeout == 0) | ||
123 | return -EIO; | ||
124 | |||
125 | rtc_time_to_tm(secs, time); | ||
126 | |||
127 | return rtc_valid_tm(time); | ||
128 | } | ||
129 | |||
130 | static int jz4740_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
131 | { | ||
132 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
133 | |||
134 | return jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, secs); | ||
135 | } | ||
136 | |||
137 | static int jz4740_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
138 | { | ||
139 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
140 | uint32_t secs; | ||
141 | uint32_t ctrl; | ||
142 | |||
143 | secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM); | ||
144 | |||
145 | ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); | ||
146 | |||
147 | alrm->enabled = !!(ctrl & JZ_RTC_CTRL_AE); | ||
148 | alrm->pending = !!(ctrl & JZ_RTC_CTRL_AF); | ||
149 | |||
150 | rtc_time_to_tm(secs, &alrm->time); | ||
151 | |||
152 | return rtc_valid_tm(&alrm->time); | ||
153 | } | ||
154 | |||
155 | static int jz4740_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
156 | { | ||
157 | int ret; | ||
158 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
159 | unsigned long secs; | ||
160 | |||
161 | rtc_tm_to_time(&alrm->time, &secs); | ||
162 | |||
163 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, secs); | ||
164 | if (!ret) | ||
165 | ret = jz4740_rtc_ctrl_set_bits(rtc, | ||
166 | JZ_RTC_CTRL_AE | JZ_RTC_CTRL_AF_IRQ, alrm->enabled); | ||
167 | |||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | static int jz4740_rtc_update_irq_enable(struct device *dev, unsigned int enable) | ||
172 | { | ||
173 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
174 | return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ_IRQ, enable); | ||
175 | } | ||
176 | |||
177 | static int jz4740_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) | ||
178 | { | ||
179 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
180 | return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AF_IRQ, enable); | ||
181 | } | ||
182 | |||
183 | static struct rtc_class_ops jz4740_rtc_ops = { | ||
184 | .read_time = jz4740_rtc_read_time, | ||
185 | .set_mmss = jz4740_rtc_set_mmss, | ||
186 | .read_alarm = jz4740_rtc_read_alarm, | ||
187 | .set_alarm = jz4740_rtc_set_alarm, | ||
188 | .update_irq_enable = jz4740_rtc_update_irq_enable, | ||
189 | .alarm_irq_enable = jz4740_rtc_alarm_irq_enable, | ||
190 | }; | ||
191 | |||
192 | static irqreturn_t jz4740_rtc_irq(int irq, void *data) | ||
193 | { | ||
194 | struct jz4740_rtc *rtc = data; | ||
195 | uint32_t ctrl; | ||
196 | unsigned long events = 0; | ||
197 | |||
198 | ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); | ||
199 | |||
200 | if (ctrl & JZ_RTC_CTRL_1HZ) | ||
201 | events |= (RTC_UF | RTC_IRQF); | ||
202 | |||
203 | if (ctrl & JZ_RTC_CTRL_AF) | ||
204 | events |= (RTC_AF | RTC_IRQF); | ||
205 | |||
206 | rtc_update_irq(rtc->rtc, 1, events); | ||
207 | |||
208 | jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF, false); | ||
209 | |||
210 | return IRQ_HANDLED; | ||
211 | } | ||
212 | |||
213 | void jz4740_rtc_poweroff(struct device *dev) | ||
214 | { | ||
215 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
216 | jz4740_rtc_reg_write(rtc, JZ_REG_RTC_HIBERNATE, 1); | ||
217 | } | ||
218 | EXPORT_SYMBOL_GPL(jz4740_rtc_poweroff); | ||
219 | |||
220 | static int __devinit jz4740_rtc_probe(struct platform_device *pdev) | ||
221 | { | ||
222 | int ret; | ||
223 | struct jz4740_rtc *rtc; | ||
224 | uint32_t scratchpad; | ||
225 | |||
226 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | ||
227 | if (!rtc) | ||
228 | return -ENOMEM; | ||
229 | |||
230 | rtc->irq = platform_get_irq(pdev, 0); | ||
231 | if (rtc->irq < 0) { | ||
232 | ret = -ENOENT; | ||
233 | dev_err(&pdev->dev, "Failed to get platform irq\n"); | ||
234 | goto err_free; | ||
235 | } | ||
236 | |||
237 | rtc->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
238 | if (!rtc->mem) { | ||
239 | ret = -ENOENT; | ||
240 | dev_err(&pdev->dev, "Failed to get platform mmio memory\n"); | ||
241 | goto err_free; | ||
242 | } | ||
243 | |||
244 | rtc->mem = request_mem_region(rtc->mem->start, resource_size(rtc->mem), | ||
245 | pdev->name); | ||
246 | if (!rtc->mem) { | ||
247 | ret = -EBUSY; | ||
248 | dev_err(&pdev->dev, "Failed to request mmio memory region\n"); | ||
249 | goto err_free; | ||
250 | } | ||
251 | |||
252 | rtc->base = ioremap_nocache(rtc->mem->start, resource_size(rtc->mem)); | ||
253 | if (!rtc->base) { | ||
254 | ret = -EBUSY; | ||
255 | dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); | ||
256 | goto err_release_mem_region; | ||
257 | } | ||
258 | |||
259 | spin_lock_init(&rtc->lock); | ||
260 | |||
261 | platform_set_drvdata(pdev, rtc); | ||
262 | |||
263 | device_init_wakeup(&pdev->dev, 1); | ||
264 | |||
265 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, &jz4740_rtc_ops, | ||
266 | THIS_MODULE); | ||
267 | if (IS_ERR(rtc->rtc)) { | ||
268 | ret = PTR_ERR(rtc->rtc); | ||
269 | dev_err(&pdev->dev, "Failed to register rtc device: %d\n", ret); | ||
270 | goto err_iounmap; | ||
271 | } | ||
272 | |||
273 | ret = request_irq(rtc->irq, jz4740_rtc_irq, 0, | ||
274 | pdev->name, rtc); | ||
275 | if (ret) { | ||
276 | dev_err(&pdev->dev, "Failed to request rtc irq: %d\n", ret); | ||
277 | goto err_unregister_rtc; | ||
278 | } | ||
279 | |||
280 | scratchpad = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SCRATCHPAD); | ||
281 | if (scratchpad != 0x12345678) { | ||
282 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678); | ||
283 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0); | ||
284 | if (ret) { | ||
285 | dev_err(&pdev->dev, "Could not write write to RTC registers\n"); | ||
286 | goto err_free_irq; | ||
287 | } | ||
288 | } | ||
289 | |||
290 | return 0; | ||
291 | |||
292 | err_free_irq: | ||
293 | free_irq(rtc->irq, rtc); | ||
294 | err_unregister_rtc: | ||
295 | rtc_device_unregister(rtc->rtc); | ||
296 | err_iounmap: | ||
297 | platform_set_drvdata(pdev, NULL); | ||
298 | iounmap(rtc->base); | ||
299 | err_release_mem_region: | ||
300 | release_mem_region(rtc->mem->start, resource_size(rtc->mem)); | ||
301 | err_free: | ||
302 | kfree(rtc); | ||
303 | |||
304 | return ret; | ||
305 | } | ||
306 | |||
307 | static int __devexit jz4740_rtc_remove(struct platform_device *pdev) | ||
308 | { | ||
309 | struct jz4740_rtc *rtc = platform_get_drvdata(pdev); | ||
310 | |||
311 | free_irq(rtc->irq, rtc); | ||
312 | |||
313 | rtc_device_unregister(rtc->rtc); | ||
314 | |||
315 | iounmap(rtc->base); | ||
316 | release_mem_region(rtc->mem->start, resource_size(rtc->mem)); | ||
317 | |||
318 | kfree(rtc); | ||
319 | |||
320 | platform_set_drvdata(pdev, NULL); | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | |||
326 | #ifdef CONFIG_PM | ||
327 | static int jz4740_rtc_suspend(struct device *dev) | ||
328 | { | ||
329 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
330 | |||
331 | if (device_may_wakeup(dev)) | ||
332 | enable_irq_wake(rtc->irq); | ||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static int jz4740_rtc_resume(struct device *dev) | ||
337 | { | ||
338 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
339 | |||
340 | if (device_may_wakeup(dev)) | ||
341 | disable_irq_wake(rtc->irq); | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static const struct dev_pm_ops jz4740_pm_ops = { | ||
346 | .suspend = jz4740_rtc_suspend, | ||
347 | .resume = jz4740_rtc_resume, | ||
348 | }; | ||
349 | #define JZ4740_RTC_PM_OPS (&jz4740_pm_ops) | ||
350 | |||
351 | #else | ||
352 | #define JZ4740_RTC_PM_OPS NULL | ||
353 | #endif /* CONFIG_PM */ | ||
354 | |||
355 | struct platform_driver jz4740_rtc_driver = { | ||
356 | .probe = jz4740_rtc_probe, | ||
357 | .remove = __devexit_p(jz4740_rtc_remove), | ||
358 | .driver = { | ||
359 | .name = "jz4740-rtc", | ||
360 | .owner = THIS_MODULE, | ||
361 | .pm = JZ4740_RTC_PM_OPS, | ||
362 | }, | ||
363 | }; | ||
364 | |||
365 | static int __init jz4740_rtc_init(void) | ||
366 | { | ||
367 | return platform_driver_register(&jz4740_rtc_driver); | ||
368 | } | ||
369 | module_init(jz4740_rtc_init); | ||
370 | |||
371 | static void __exit jz4740_rtc_exit(void) | ||
372 | { | ||
373 | platform_driver_unregister(&jz4740_rtc_driver); | ||
374 | } | ||
375 | module_exit(jz4740_rtc_exit); | ||
376 | |||
377 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
378 | MODULE_LICENSE("GPL"); | ||
379 | MODULE_DESCRIPTION("RTC driver for the JZ4740 SoC\n"); | ||
380 | MODULE_ALIAS("platform:jz4740-rtc"); | ||
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c index 773851f338b8..075f1708deae 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c | |||
@@ -117,4 +117,32 @@ int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) | |||
117 | } | 117 | } |
118 | EXPORT_SYMBOL(rtc_tm_to_time); | 118 | EXPORT_SYMBOL(rtc_tm_to_time); |
119 | 119 | ||
120 | /* | ||
121 | * Convert rtc_time to ktime | ||
122 | */ | ||
123 | ktime_t rtc_tm_to_ktime(struct rtc_time tm) | ||
124 | { | ||
125 | time_t time; | ||
126 | rtc_tm_to_time(&tm, &time); | ||
127 | return ktime_set(time, 0); | ||
128 | } | ||
129 | EXPORT_SYMBOL_GPL(rtc_tm_to_ktime); | ||
130 | |||
131 | /* | ||
132 | * Convert ktime to rtc_time | ||
133 | */ | ||
134 | struct rtc_time rtc_ktime_to_tm(ktime_t kt) | ||
135 | { | ||
136 | struct timespec ts; | ||
137 | struct rtc_time ret; | ||
138 | |||
139 | ts = ktime_to_timespec(kt); | ||
140 | /* Round up any ns */ | ||
141 | if (ts.tv_nsec) | ||
142 | ts.tv_sec++; | ||
143 | rtc_time_to_tm(ts.tv_sec, &ret); | ||
144 | return ret; | ||
145 | } | ||
146 | EXPORT_SYMBOL_GPL(rtc_ktime_to_tm); | ||
147 | |||
120 | MODULE_LICENSE("GPL"); | 148 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/rtc/rtc-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c new file mode 100644 index 000000000000..ec8701ce99f9 --- /dev/null +++ b/drivers/rtc/rtc-lpc32xx.c | |||
@@ -0,0 +1,414 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 NXP Semiconductors | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * You should have received a copy of the GNU General Public License along | ||
10 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
11 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | #include <linux/rtc.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/io.h> | ||
22 | |||
23 | /* | ||
24 | * Clock and Power control register offsets | ||
25 | */ | ||
26 | #define LPC32XX_RTC_UCOUNT 0x00 | ||
27 | #define LPC32XX_RTC_DCOUNT 0x04 | ||
28 | #define LPC32XX_RTC_MATCH0 0x08 | ||
29 | #define LPC32XX_RTC_MATCH1 0x0C | ||
30 | #define LPC32XX_RTC_CTRL 0x10 | ||
31 | #define LPC32XX_RTC_INTSTAT 0x14 | ||
32 | #define LPC32XX_RTC_KEY 0x18 | ||
33 | #define LPC32XX_RTC_SRAM 0x80 | ||
34 | |||
35 | #define LPC32XX_RTC_CTRL_MATCH0 (1 << 0) | ||
36 | #define LPC32XX_RTC_CTRL_MATCH1 (1 << 1) | ||
37 | #define LPC32XX_RTC_CTRL_ONSW_MATCH0 (1 << 2) | ||
38 | #define LPC32XX_RTC_CTRL_ONSW_MATCH1 (1 << 3) | ||
39 | #define LPC32XX_RTC_CTRL_SW_RESET (1 << 4) | ||
40 | #define LPC32XX_RTC_CTRL_CNTR_DIS (1 << 6) | ||
41 | #define LPC32XX_RTC_CTRL_ONSW_FORCE_HI (1 << 7) | ||
42 | |||
43 | #define LPC32XX_RTC_INTSTAT_MATCH0 (1 << 0) | ||
44 | #define LPC32XX_RTC_INTSTAT_MATCH1 (1 << 1) | ||
45 | #define LPC32XX_RTC_INTSTAT_ONSW (1 << 2) | ||
46 | |||
47 | #define LPC32XX_RTC_KEY_ONSW_LOADVAL 0xB5C13F27 | ||
48 | |||
49 | #define RTC_NAME "rtc-lpc32xx" | ||
50 | |||
51 | #define rtc_readl(dev, reg) \ | ||
52 | __raw_readl((dev)->rtc_base + (reg)) | ||
53 | #define rtc_writel(dev, reg, val) \ | ||
54 | __raw_writel((val), (dev)->rtc_base + (reg)) | ||
55 | |||
56 | struct lpc32xx_rtc { | ||
57 | void __iomem *rtc_base; | ||
58 | int irq; | ||
59 | unsigned char alarm_enabled; | ||
60 | struct rtc_device *rtc; | ||
61 | spinlock_t lock; | ||
62 | }; | ||
63 | |||
64 | static int lpc32xx_rtc_read_time(struct device *dev, struct rtc_time *time) | ||
65 | { | ||
66 | unsigned long elapsed_sec; | ||
67 | struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); | ||
68 | |||
69 | elapsed_sec = rtc_readl(rtc, LPC32XX_RTC_UCOUNT); | ||
70 | rtc_time_to_tm(elapsed_sec, time); | ||
71 | |||
72 | return rtc_valid_tm(time); | ||
73 | } | ||
74 | |||
75 | static int lpc32xx_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
76 | { | ||
77 | struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); | ||
78 | u32 tmp; | ||
79 | |||
80 | spin_lock_irq(&rtc->lock); | ||
81 | |||
82 | /* RTC must be disabled during count update */ | ||
83 | tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); | ||
84 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp | LPC32XX_RTC_CTRL_CNTR_DIS); | ||
85 | rtc_writel(rtc, LPC32XX_RTC_UCOUNT, secs); | ||
86 | rtc_writel(rtc, LPC32XX_RTC_DCOUNT, 0xFFFFFFFF - secs); | ||
87 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp &= ~LPC32XX_RTC_CTRL_CNTR_DIS); | ||
88 | |||
89 | spin_unlock_irq(&rtc->lock); | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static int lpc32xx_rtc_read_alarm(struct device *dev, | ||
95 | struct rtc_wkalrm *wkalrm) | ||
96 | { | ||
97 | struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); | ||
98 | |||
99 | rtc_time_to_tm(rtc_readl(rtc, LPC32XX_RTC_MATCH0), &wkalrm->time); | ||
100 | wkalrm->enabled = rtc->alarm_enabled; | ||
101 | wkalrm->pending = !!(rtc_readl(rtc, LPC32XX_RTC_INTSTAT) & | ||
102 | LPC32XX_RTC_INTSTAT_MATCH0); | ||
103 | |||
104 | return rtc_valid_tm(&wkalrm->time); | ||
105 | } | ||
106 | |||
107 | static int lpc32xx_rtc_set_alarm(struct device *dev, | ||
108 | struct rtc_wkalrm *wkalrm) | ||
109 | { | ||
110 | struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); | ||
111 | unsigned long alarmsecs; | ||
112 | u32 tmp; | ||
113 | int ret; | ||
114 | |||
115 | ret = rtc_tm_to_time(&wkalrm->time, &alarmsecs); | ||
116 | if (ret < 0) { | ||
117 | dev_warn(dev, "Failed to convert time: %d\n", ret); | ||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | spin_lock_irq(&rtc->lock); | ||
122 | |||
123 | /* Disable alarm during update */ | ||
124 | tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); | ||
125 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp & ~LPC32XX_RTC_CTRL_MATCH0); | ||
126 | |||
127 | rtc_writel(rtc, LPC32XX_RTC_MATCH0, alarmsecs); | ||
128 | |||
129 | rtc->alarm_enabled = wkalrm->enabled; | ||
130 | if (wkalrm->enabled) { | ||
131 | rtc_writel(rtc, LPC32XX_RTC_INTSTAT, | ||
132 | LPC32XX_RTC_INTSTAT_MATCH0); | ||
133 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp | | ||
134 | LPC32XX_RTC_CTRL_MATCH0); | ||
135 | } | ||
136 | |||
137 | spin_unlock_irq(&rtc->lock); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static int lpc32xx_rtc_alarm_irq_enable(struct device *dev, | ||
143 | unsigned int enabled) | ||
144 | { | ||
145 | struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); | ||
146 | u32 tmp; | ||
147 | |||
148 | spin_lock_irq(&rtc->lock); | ||
149 | tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); | ||
150 | |||
151 | if (enabled) { | ||
152 | rtc->alarm_enabled = 1; | ||
153 | tmp |= LPC32XX_RTC_CTRL_MATCH0; | ||
154 | } else { | ||
155 | rtc->alarm_enabled = 0; | ||
156 | tmp &= ~LPC32XX_RTC_CTRL_MATCH0; | ||
157 | } | ||
158 | |||
159 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp); | ||
160 | spin_unlock_irq(&rtc->lock); | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static irqreturn_t lpc32xx_rtc_alarm_interrupt(int irq, void *dev) | ||
166 | { | ||
167 | struct lpc32xx_rtc *rtc = dev; | ||
168 | |||
169 | spin_lock(&rtc->lock); | ||
170 | |||
171 | /* Disable alarm interrupt */ | ||
172 | rtc_writel(rtc, LPC32XX_RTC_CTRL, | ||
173 | rtc_readl(rtc, LPC32XX_RTC_CTRL) & | ||
174 | ~LPC32XX_RTC_CTRL_MATCH0); | ||
175 | rtc->alarm_enabled = 0; | ||
176 | |||
177 | /* | ||
178 | * Write a large value to the match value so the RTC won't | ||
179 | * keep firing the match status | ||
180 | */ | ||
181 | rtc_writel(rtc, LPC32XX_RTC_MATCH0, 0xFFFFFFFF); | ||
182 | rtc_writel(rtc, LPC32XX_RTC_INTSTAT, LPC32XX_RTC_INTSTAT_MATCH0); | ||
183 | |||
184 | spin_unlock(&rtc->lock); | ||
185 | |||
186 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); | ||
187 | |||
188 | return IRQ_HANDLED; | ||
189 | } | ||
190 | |||
191 | static const struct rtc_class_ops lpc32xx_rtc_ops = { | ||
192 | .read_time = lpc32xx_rtc_read_time, | ||
193 | .set_mmss = lpc32xx_rtc_set_mmss, | ||
194 | .read_alarm = lpc32xx_rtc_read_alarm, | ||
195 | .set_alarm = lpc32xx_rtc_set_alarm, | ||
196 | .alarm_irq_enable = lpc32xx_rtc_alarm_irq_enable, | ||
197 | }; | ||
198 | |||
199 | static int __devinit lpc32xx_rtc_probe(struct platform_device *pdev) | ||
200 | { | ||
201 | struct resource *res; | ||
202 | struct lpc32xx_rtc *rtc; | ||
203 | resource_size_t size; | ||
204 | int rtcirq; | ||
205 | u32 tmp; | ||
206 | |||
207 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
208 | if (!res) { | ||
209 | dev_err(&pdev->dev, "Can't get memory resource\n"); | ||
210 | return -ENOENT; | ||
211 | } | ||
212 | |||
213 | rtcirq = platform_get_irq(pdev, 0); | ||
214 | if (rtcirq < 0 || rtcirq >= NR_IRQS) { | ||
215 | dev_warn(&pdev->dev, "Can't get interrupt resource\n"); | ||
216 | rtcirq = -1; | ||
217 | } | ||
218 | |||
219 | rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); | ||
220 | if (unlikely(!rtc)) { | ||
221 | dev_err(&pdev->dev, "Can't allocate memory\n"); | ||
222 | return -ENOMEM; | ||
223 | } | ||
224 | rtc->irq = rtcirq; | ||
225 | |||
226 | size = resource_size(res); | ||
227 | |||
228 | if (!devm_request_mem_region(&pdev->dev, res->start, size, | ||
229 | pdev->name)) { | ||
230 | dev_err(&pdev->dev, "RTC registers are not free\n"); | ||
231 | return -EBUSY; | ||
232 | } | ||
233 | |||
234 | rtc->rtc_base = devm_ioremap(&pdev->dev, res->start, size); | ||
235 | if (!rtc->rtc_base) { | ||
236 | dev_err(&pdev->dev, "Can't map memory\n"); | ||
237 | return -ENOMEM; | ||
238 | } | ||
239 | |||
240 | spin_lock_init(&rtc->lock); | ||
241 | |||
242 | /* | ||
243 | * The RTC is on a seperate power domain and can keep it's state | ||
244 | * across a chip power cycle. If the RTC has never been previously | ||
245 | * setup, then set it up now for the first time. | ||
246 | */ | ||
247 | tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); | ||
248 | if (rtc_readl(rtc, LPC32XX_RTC_KEY) != LPC32XX_RTC_KEY_ONSW_LOADVAL) { | ||
249 | tmp &= ~(LPC32XX_RTC_CTRL_SW_RESET | | ||
250 | LPC32XX_RTC_CTRL_CNTR_DIS | | ||
251 | LPC32XX_RTC_CTRL_MATCH0 | | ||
252 | LPC32XX_RTC_CTRL_MATCH1 | | ||
253 | LPC32XX_RTC_CTRL_ONSW_MATCH0 | | ||
254 | LPC32XX_RTC_CTRL_ONSW_MATCH1 | | ||
255 | LPC32XX_RTC_CTRL_ONSW_FORCE_HI); | ||
256 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp); | ||
257 | |||
258 | /* Clear latched interrupt states */ | ||
259 | rtc_writel(rtc, LPC32XX_RTC_MATCH0, 0xFFFFFFFF); | ||
260 | rtc_writel(rtc, LPC32XX_RTC_INTSTAT, | ||
261 | LPC32XX_RTC_INTSTAT_MATCH0 | | ||
262 | LPC32XX_RTC_INTSTAT_MATCH1 | | ||
263 | LPC32XX_RTC_INTSTAT_ONSW); | ||
264 | |||
265 | /* Write key value to RTC so it won't reload on reset */ | ||
266 | rtc_writel(rtc, LPC32XX_RTC_KEY, | ||
267 | LPC32XX_RTC_KEY_ONSW_LOADVAL); | ||
268 | } else { | ||
269 | rtc_writel(rtc, LPC32XX_RTC_CTRL, | ||
270 | tmp & ~LPC32XX_RTC_CTRL_MATCH0); | ||
271 | } | ||
272 | |||
273 | platform_set_drvdata(pdev, rtc); | ||
274 | |||
275 | rtc->rtc = rtc_device_register(RTC_NAME, &pdev->dev, &lpc32xx_rtc_ops, | ||
276 | THIS_MODULE); | ||
277 | if (IS_ERR(rtc->rtc)) { | ||
278 | dev_err(&pdev->dev, "Can't get RTC\n"); | ||
279 | platform_set_drvdata(pdev, NULL); | ||
280 | return PTR_ERR(rtc->rtc); | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * IRQ is enabled after device registration in case alarm IRQ | ||
285 | * is pending upon suspend exit. | ||
286 | */ | ||
287 | if (rtc->irq >= 0) { | ||
288 | if (devm_request_irq(&pdev->dev, rtc->irq, | ||
289 | lpc32xx_rtc_alarm_interrupt, | ||
290 | IRQF_DISABLED, pdev->name, rtc) < 0) { | ||
291 | dev_warn(&pdev->dev, "Can't request interrupt.\n"); | ||
292 | rtc->irq = -1; | ||
293 | } else { | ||
294 | device_init_wakeup(&pdev->dev, 1); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static int __devexit lpc32xx_rtc_remove(struct platform_device *pdev) | ||
302 | { | ||
303 | struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); | ||
304 | |||
305 | if (rtc->irq >= 0) | ||
306 | device_init_wakeup(&pdev->dev, 0); | ||
307 | |||
308 | platform_set_drvdata(pdev, NULL); | ||
309 | rtc_device_unregister(rtc->rtc); | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | #ifdef CONFIG_PM | ||
315 | static int lpc32xx_rtc_suspend(struct device *dev) | ||
316 | { | ||
317 | struct platform_device *pdev = to_platform_device(dev); | ||
318 | struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); | ||
319 | |||
320 | if (rtc->irq >= 0) { | ||
321 | if (device_may_wakeup(&pdev->dev)) | ||
322 | enable_irq_wake(rtc->irq); | ||
323 | else | ||
324 | disable_irq_wake(rtc->irq); | ||
325 | } | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static int lpc32xx_rtc_resume(struct device *dev) | ||
331 | { | ||
332 | struct platform_device *pdev = to_platform_device(dev); | ||
333 | struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); | ||
334 | |||
335 | if (rtc->irq >= 0 && device_may_wakeup(&pdev->dev)) | ||
336 | disable_irq_wake(rtc->irq); | ||
337 | |||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | /* Unconditionally disable the alarm */ | ||
342 | static int lpc32xx_rtc_freeze(struct device *dev) | ||
343 | { | ||
344 | struct platform_device *pdev = to_platform_device(dev); | ||
345 | struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); | ||
346 | |||
347 | spin_lock_irq(&rtc->lock); | ||
348 | |||
349 | rtc_writel(rtc, LPC32XX_RTC_CTRL, | ||
350 | rtc_readl(rtc, LPC32XX_RTC_CTRL) & | ||
351 | ~LPC32XX_RTC_CTRL_MATCH0); | ||
352 | |||
353 | spin_unlock_irq(&rtc->lock); | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static int lpc32xx_rtc_thaw(struct device *dev) | ||
359 | { | ||
360 | struct platform_device *pdev = to_platform_device(dev); | ||
361 | struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); | ||
362 | |||
363 | if (rtc->alarm_enabled) { | ||
364 | spin_lock_irq(&rtc->lock); | ||
365 | |||
366 | rtc_writel(rtc, LPC32XX_RTC_CTRL, | ||
367 | rtc_readl(rtc, LPC32XX_RTC_CTRL) | | ||
368 | LPC32XX_RTC_CTRL_MATCH0); | ||
369 | |||
370 | spin_unlock_irq(&rtc->lock); | ||
371 | } | ||
372 | |||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static const struct dev_pm_ops lpc32xx_rtc_pm_ops = { | ||
377 | .suspend = lpc32xx_rtc_suspend, | ||
378 | .resume = lpc32xx_rtc_resume, | ||
379 | .freeze = lpc32xx_rtc_freeze, | ||
380 | .thaw = lpc32xx_rtc_thaw, | ||
381 | .restore = lpc32xx_rtc_resume | ||
382 | }; | ||
383 | |||
384 | #define LPC32XX_RTC_PM_OPS (&lpc32xx_rtc_pm_ops) | ||
385 | #else | ||
386 | #define LPC32XX_RTC_PM_OPS NULL | ||
387 | #endif | ||
388 | |||
389 | static struct platform_driver lpc32xx_rtc_driver = { | ||
390 | .probe = lpc32xx_rtc_probe, | ||
391 | .remove = __devexit_p(lpc32xx_rtc_remove), | ||
392 | .driver = { | ||
393 | .name = RTC_NAME, | ||
394 | .owner = THIS_MODULE, | ||
395 | .pm = LPC32XX_RTC_PM_OPS | ||
396 | }, | ||
397 | }; | ||
398 | |||
399 | static int __init lpc32xx_rtc_init(void) | ||
400 | { | ||
401 | return platform_driver_register(&lpc32xx_rtc_driver); | ||
402 | } | ||
403 | module_init(lpc32xx_rtc_init); | ||
404 | |||
405 | static void __exit lpc32xx_rtc_exit(void) | ||
406 | { | ||
407 | platform_driver_unregister(&lpc32xx_rtc_driver); | ||
408 | } | ||
409 | module_exit(lpc32xx_rtc_exit); | ||
410 | |||
411 | MODULE_AUTHOR("Kevin Wells <wellsk40@gmail.com"); | ||
412 | MODULE_DESCRIPTION("RTC driver for the LPC32xx SoC"); | ||
413 | MODULE_LICENSE("GPL"); | ||
414 | MODULE_ALIAS("platform:rtc-lpc32xx"); | ||
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 60fe266f0f49..5a8daa358066 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/rtc.h> | 21 | #include <linux/rtc.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/smp_lock.h> | 23 | #include <linux/mutex.h> |
24 | #include <linux/string.h> | 24 | #include <linux/string.h> |
25 | #ifdef CONFIG_RTC_DRV_M41T80_WDT | 25 | #ifdef CONFIG_RTC_DRV_M41T80_WDT |
26 | #include <linux/fs.h> | 26 | #include <linux/fs.h> |
@@ -68,6 +68,7 @@ | |||
68 | 68 | ||
69 | #define DRV_VERSION "0.05" | 69 | #define DRV_VERSION "0.05" |
70 | 70 | ||
71 | static DEFINE_MUTEX(m41t80_rtc_mutex); | ||
71 | static const struct i2c_device_id m41t80_id[] = { | 72 | static const struct i2c_device_id m41t80_id[] = { |
72 | { "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT }, | 73 | { "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT }, |
73 | { "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD }, | 74 | { "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD }, |
@@ -121,7 +122,7 @@ static int m41t80_get_datetime(struct i2c_client *client, | |||
121 | 122 | ||
122 | /* assume 20YY not 19YY, and ignore the Century Bit */ | 123 | /* assume 20YY not 19YY, and ignore the Century Bit */ |
123 | tm->tm_year = bcd2bin(buf[M41T80_REG_YEAR]) + 100; | 124 | tm->tm_year = bcd2bin(buf[M41T80_REG_YEAR]) + 100; |
124 | return 0; | 125 | return rtc_valid_tm(tm); |
125 | } | 126 | } |
126 | 127 | ||
127 | /* Sets the given date and time to the real time clock. */ | 128 | /* Sets the given date and time to the real time clock. */ |
@@ -595,10 +596,6 @@ static void wdt_disable(void) | |||
595 | static ssize_t wdt_write(struct file *file, const char __user *buf, | 596 | static ssize_t wdt_write(struct file *file, const char __user *buf, |
596 | size_t count, loff_t *ppos) | 597 | size_t count, loff_t *ppos) |
597 | { | 598 | { |
598 | /* Can't seek (pwrite) on this device | ||
599 | if (ppos != &file->f_pos) | ||
600 | return -ESPIPE; | ||
601 | */ | ||
602 | if (count) { | 599 | if (count) { |
603 | wdt_ping(); | 600 | wdt_ping(); |
604 | return 1; | 601 | return 1; |
@@ -623,7 +620,7 @@ static ssize_t wdt_read(struct file *file, char __user *buf, | |||
623 | * according to their available features. We only actually usefully support | 620 | * according to their available features. We only actually usefully support |
624 | * querying capabilities and current status. | 621 | * querying capabilities and current status. |
625 | */ | 622 | */ |
626 | static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 623 | static int wdt_ioctl(struct file *file, unsigned int cmd, |
627 | unsigned long arg) | 624 | unsigned long arg) |
628 | { | 625 | { |
629 | int new_margin, rv; | 626 | int new_margin, rv; |
@@ -676,6 +673,18 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
676 | return -ENOTTY; | 673 | return -ENOTTY; |
677 | } | 674 | } |
678 | 675 | ||
676 | static long wdt_unlocked_ioctl(struct file *file, unsigned int cmd, | ||
677 | unsigned long arg) | ||
678 | { | ||
679 | int ret; | ||
680 | |||
681 | mutex_lock(&m41t80_rtc_mutex); | ||
682 | ret = wdt_ioctl(file, cmd, arg); | ||
683 | mutex_unlock(&m41t80_rtc_mutex); | ||
684 | |||
685 | return ret; | ||
686 | } | ||
687 | |||
679 | /** | 688 | /** |
680 | * wdt_open: | 689 | * wdt_open: |
681 | * @inode: inode of device | 690 | * @inode: inode of device |
@@ -685,17 +694,17 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
685 | static int wdt_open(struct inode *inode, struct file *file) | 694 | static int wdt_open(struct inode *inode, struct file *file) |
686 | { | 695 | { |
687 | if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) { | 696 | if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) { |
688 | lock_kernel(); | 697 | mutex_lock(&m41t80_rtc_mutex); |
689 | if (test_and_set_bit(0, &wdt_is_open)) { | 698 | if (test_and_set_bit(0, &wdt_is_open)) { |
690 | unlock_kernel(); | 699 | mutex_unlock(&m41t80_rtc_mutex); |
691 | return -EBUSY; | 700 | return -EBUSY; |
692 | } | 701 | } |
693 | /* | 702 | /* |
694 | * Activate | 703 | * Activate |
695 | */ | 704 | */ |
696 | wdt_is_open = 1; | 705 | wdt_is_open = 1; |
697 | unlock_kernel(); | 706 | mutex_unlock(&m41t80_rtc_mutex); |
698 | return 0; | 707 | return nonseekable_open(inode, file); |
699 | } | 708 | } |
700 | return -ENODEV; | 709 | return -ENODEV; |
701 | } | 710 | } |
@@ -736,10 +745,11 @@ static int wdt_notify_sys(struct notifier_block *this, unsigned long code, | |||
736 | static const struct file_operations wdt_fops = { | 745 | static const struct file_operations wdt_fops = { |
737 | .owner = THIS_MODULE, | 746 | .owner = THIS_MODULE, |
738 | .read = wdt_read, | 747 | .read = wdt_read, |
739 | .ioctl = wdt_ioctl, | 748 | .unlocked_ioctl = wdt_unlocked_ioctl, |
740 | .write = wdt_write, | 749 | .write = wdt_write, |
741 | .open = wdt_open, | 750 | .open = wdt_open, |
742 | .release = wdt_release, | 751 | .release = wdt_release, |
752 | .llseek = no_llseek, | ||
743 | }; | 753 | }; |
744 | 754 | ||
745 | static struct miscdevice wdt_dev = { | 755 | static struct miscdevice wdt_dev = { |
diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c index c3a18c58daf6..c8c97a4169d4 100644 --- a/drivers/rtc/rtc-m41t94.c +++ b/drivers/rtc/rtc-m41t94.c | |||
@@ -171,3 +171,4 @@ module_exit(m41t94_exit); | |||
171 | MODULE_AUTHOR("Kim B. Heino <Kim.Heino@bluegiga.com>"); | 171 | MODULE_AUTHOR("Kim B. Heino <Kim.Heino@bluegiga.com>"); |
172 | MODULE_DESCRIPTION("Driver for ST M41T94 SPI RTC"); | 172 | MODULE_DESCRIPTION("Driver for ST M41T94 SPI RTC"); |
173 | MODULE_LICENSE("GPL"); | 173 | MODULE_LICENSE("GPL"); |
174 | MODULE_ALIAS("spi:rtc-m41t94"); | ||
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c index 0b2197559940..7410875e5838 100644 --- a/drivers/rtc/rtc-m48t35.c +++ b/drivers/rtc/rtc-m48t35.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/rtc.h> | 18 | #include <linux/rtc.h> |
19 | #include <linux/slab.h> | ||
19 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
20 | #include <linux/bcd.h> | 21 | #include <linux/bcd.h> |
21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
@@ -142,7 +143,6 @@ static const struct rtc_class_ops m48t35_ops = { | |||
142 | 143 | ||
143 | static int __devinit m48t35_probe(struct platform_device *pdev) | 144 | static int __devinit m48t35_probe(struct platform_device *pdev) |
144 | { | 145 | { |
145 | struct rtc_device *rtc; | ||
146 | struct resource *res; | 146 | struct resource *res; |
147 | struct m48t35_priv *priv; | 147 | struct m48t35_priv *priv; |
148 | int ret = 0; | 148 | int ret = 0; |
@@ -171,20 +171,21 @@ static int __devinit m48t35_probe(struct platform_device *pdev) | |||
171 | ret = -ENOMEM; | 171 | ret = -ENOMEM; |
172 | goto out; | 172 | goto out; |
173 | } | 173 | } |
174 | |||
174 | spin_lock_init(&priv->lock); | 175 | spin_lock_init(&priv->lock); |
175 | rtc = rtc_device_register("m48t35", &pdev->dev, | 176 | |
177 | platform_set_drvdata(pdev, priv); | ||
178 | |||
179 | priv->rtc = rtc_device_register("m48t35", &pdev->dev, | ||
176 | &m48t35_ops, THIS_MODULE); | 180 | &m48t35_ops, THIS_MODULE); |
177 | if (IS_ERR(rtc)) { | 181 | if (IS_ERR(priv->rtc)) { |
178 | ret = PTR_ERR(rtc); | 182 | ret = PTR_ERR(priv->rtc); |
179 | goto out; | 183 | goto out; |
180 | } | 184 | } |
181 | priv->rtc = rtc; | 185 | |
182 | platform_set_drvdata(pdev, priv); | ||
183 | return 0; | 186 | return 0; |
184 | 187 | ||
185 | out: | 188 | out: |
186 | if (priv->rtc) | ||
187 | rtc_device_unregister(priv->rtc); | ||
188 | if (priv->reg) | 189 | if (priv->reg) |
189 | iounmap(priv->reg); | 190 | iounmap(priv->reg); |
190 | if (priv->baseaddr) | 191 | if (priv->baseaddr) |
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 33921a6b1707..a99a0b554eb8 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/rtc.h> | 19 | #include <linux/rtc.h> |
20 | #include <linux/rtc/m48t59.h> | 20 | #include <linux/rtc/m48t59.h> |
21 | #include <linux/bcd.h> | 21 | #include <linux/bcd.h> |
22 | #include <linux/slab.h> | ||
22 | 23 | ||
23 | #ifndef NO_IRQ | 24 | #ifndef NO_IRQ |
24 | #define NO_IRQ (-1) | 25 | #define NO_IRQ (-1) |
@@ -104,7 +105,7 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
104 | dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n", | 105 | dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n", |
105 | tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, | 106 | tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, |
106 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 107 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
107 | return 0; | 108 | return rtc_valid_tm(tm); |
108 | } | 109 | } |
109 | 110 | ||
110 | static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) | 111 | static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) |
@@ -195,7 +196,7 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
195 | dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d/%02d/%02d\n", | 196 | dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d/%02d/%02d\n", |
196 | tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, | 197 | tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, |
197 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 198 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
198 | return 0; | 199 | return rtc_valid_tm(tm); |
199 | } | 200 | } |
200 | 201 | ||
201 | /* | 202 | /* |
@@ -342,7 +343,7 @@ static const struct rtc_class_ops m48t02_rtc_ops = { | |||
342 | .set_time = m48t59_rtc_set_time, | 343 | .set_time = m48t59_rtc_set_time, |
343 | }; | 344 | }; |
344 | 345 | ||
345 | static ssize_t m48t59_nvram_read(struct kobject *kobj, | 346 | static ssize_t m48t59_nvram_read(struct file *filp, struct kobject *kobj, |
346 | struct bin_attribute *bin_attr, | 347 | struct bin_attribute *bin_attr, |
347 | char *buf, loff_t pos, size_t size) | 348 | char *buf, loff_t pos, size_t size) |
348 | { | 349 | { |
@@ -362,7 +363,7 @@ static ssize_t m48t59_nvram_read(struct kobject *kobj, | |||
362 | return cnt; | 363 | return cnt; |
363 | } | 364 | } |
364 | 365 | ||
365 | static ssize_t m48t59_nvram_write(struct kobject *kobj, | 366 | static ssize_t m48t59_nvram_write(struct file *filp, struct kobject *kobj, |
366 | struct bin_attribute *bin_attr, | 367 | struct bin_attribute *bin_attr, |
367 | char *buf, loff_t pos, size_t size) | 368 | char *buf, loff_t pos, size_t size) |
368 | { | 369 | { |
@@ -481,6 +482,9 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
481 | goto out; | 482 | goto out; |
482 | } | 483 | } |
483 | 484 | ||
485 | spin_lock_init(&m48t59->lock); | ||
486 | platform_set_drvdata(pdev, m48t59); | ||
487 | |||
484 | m48t59->rtc = rtc_device_register(name, &pdev->dev, ops, THIS_MODULE); | 488 | m48t59->rtc = rtc_device_register(name, &pdev->dev, ops, THIS_MODULE); |
485 | if (IS_ERR(m48t59->rtc)) { | 489 | if (IS_ERR(m48t59->rtc)) { |
486 | ret = PTR_ERR(m48t59->rtc); | 490 | ret = PTR_ERR(m48t59->rtc); |
@@ -490,21 +494,18 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
490 | m48t59_nvram_attr.size = pdata->offset; | 494 | m48t59_nvram_attr.size = pdata->offset; |
491 | 495 | ||
492 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); | 496 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); |
493 | if (ret) | 497 | if (ret) { |
498 | rtc_device_unregister(m48t59->rtc); | ||
494 | goto out; | 499 | goto out; |
500 | } | ||
495 | 501 | ||
496 | spin_lock_init(&m48t59->lock); | ||
497 | platform_set_drvdata(pdev, m48t59); | ||
498 | return 0; | 502 | return 0; |
499 | 503 | ||
500 | out: | 504 | out: |
501 | if (!IS_ERR(m48t59->rtc)) | ||
502 | rtc_device_unregister(m48t59->rtc); | ||
503 | if (m48t59->irq != NO_IRQ) | 505 | if (m48t59->irq != NO_IRQ) |
504 | free_irq(m48t59->irq, &pdev->dev); | 506 | free_irq(m48t59->irq, &pdev->dev); |
505 | if (m48t59->ioaddr) | 507 | if (m48t59->ioaddr) |
506 | iounmap(m48t59->ioaddr); | 508 | iounmap(m48t59->ioaddr); |
507 | if (m48t59) | ||
508 | kfree(m48t59); | 509 | kfree(m48t59); |
509 | return ret; | 510 | return ret; |
510 | } | 511 | } |
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index 7c045cffa9ff..f981287d582b 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c | |||
@@ -77,7 +77,7 @@ static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
77 | if (ops->readbyte(M48T86_REG_HOUR) & 0x80) | 77 | if (ops->readbyte(M48T86_REG_HOUR) & 0x80) |
78 | tm->tm_hour += 12; | 78 | tm->tm_hour += 12; |
79 | 79 | ||
80 | return 0; | 80 | return rtc_valid_tm(tm); |
81 | } | 81 | } |
82 | 82 | ||
83 | static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm) | 83 | static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm) |
diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c index a4f6665ab3c5..486142c2637a 100644 --- a/drivers/rtc/rtc-max6900.c +++ b/drivers/rtc/rtc-max6900.c | |||
@@ -159,7 +159,7 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) | |||
159 | bcd2bin(regs[MAX6900_REG_CENTURY]) * 100 - 1900; | 159 | bcd2bin(regs[MAX6900_REG_CENTURY]) * 100 - 1900; |
160 | tm->tm_wday = bcd2bin(regs[MAX6900_REG_DW]); | 160 | tm->tm_wday = bcd2bin(regs[MAX6900_REG_DW]); |
161 | 161 | ||
162 | return 0; | 162 | return rtc_valid_tm(tm); |
163 | } | 163 | } |
164 | 164 | ||
165 | static int max6900_i2c_clear_write_protect(struct i2c_client *client) | 165 | static int max6900_i2c_clear_write_protect(struct i2c_client *client) |
diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c index 36a8ea9ed8ba..657403ebd54a 100644 --- a/drivers/rtc/rtc-max6902.c +++ b/drivers/rtc/rtc-max6902.c | |||
@@ -175,3 +175,4 @@ module_exit(max6902_exit); | |||
175 | MODULE_DESCRIPTION ("max6902 spi RTC driver"); | 175 | MODULE_DESCRIPTION ("max6902 spi RTC driver"); |
176 | MODULE_AUTHOR ("Raphael Assenat"); | 176 | MODULE_AUTHOR ("Raphael Assenat"); |
177 | MODULE_LICENSE ("GPL"); | 177 | MODULE_LICENSE ("GPL"); |
178 | MODULE_ALIAS("spi:rtc-max6902"); | ||
diff --git a/drivers/rtc/rtc-max8925.c b/drivers/rtc/rtc-max8925.c new file mode 100644 index 000000000000..174036dda786 --- /dev/null +++ b/drivers/rtc/rtc-max8925.c | |||
@@ -0,0 +1,315 @@ | |||
1 | /* | ||
2 | * RTC driver for Maxim MAX8925 | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Marvell International Ltd. | ||
5 | * Haojian Zhuang <haojian.zhuang@marvell.com> | ||
6 | * | ||
7 | * 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 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/rtc.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/mfd/max8925.h> | ||
18 | |||
19 | enum { | ||
20 | RTC_SEC = 0, | ||
21 | RTC_MIN, | ||
22 | RTC_HOUR, | ||
23 | RTC_WEEKDAY, | ||
24 | RTC_DATE, | ||
25 | RTC_MONTH, | ||
26 | RTC_YEAR1, | ||
27 | RTC_YEAR2, | ||
28 | }; | ||
29 | |||
30 | #define MAX8925_RTC_SEC 0x00 | ||
31 | #define MAX8925_RTC_MIN 0x01 | ||
32 | #define MAX8925_RTC_HOUR 0x02 | ||
33 | #define MAX8925_RTC_WEEKDAY 0x03 | ||
34 | #define MAX8925_RTC_DATE 0x04 | ||
35 | #define MAX8925_RTC_MONTH 0x05 | ||
36 | #define MAX8925_RTC_YEAR1 0x06 | ||
37 | #define MAX8925_RTC_YEAR2 0x07 | ||
38 | #define MAX8925_ALARM0_SEC 0x08 | ||
39 | #define MAX8925_ALARM0_MIN 0x09 | ||
40 | #define MAX8925_ALARM0_HOUR 0x0a | ||
41 | #define MAX8925_ALARM0_WEEKDAY 0x0b | ||
42 | #define MAX8925_ALARM0_DATE 0x0c | ||
43 | #define MAX8925_ALARM0_MON 0x0d | ||
44 | #define MAX8925_ALARM0_YEAR1 0x0e | ||
45 | #define MAX8925_ALARM0_YEAR2 0x0f | ||
46 | #define MAX8925_ALARM1_SEC 0x10 | ||
47 | #define MAX8925_ALARM1_MIN 0x11 | ||
48 | #define MAX8925_ALARM1_HOUR 0x12 | ||
49 | #define MAX8925_ALARM1_WEEKDAY 0x13 | ||
50 | #define MAX8925_ALARM1_DATE 0x14 | ||
51 | #define MAX8925_ALARM1_MON 0x15 | ||
52 | #define MAX8925_ALARM1_YEAR1 0x16 | ||
53 | #define MAX8925_ALARM1_YEAR2 0x17 | ||
54 | #define MAX8925_RTC_CNTL 0x1b | ||
55 | #define MAX8925_RTC_STATUS 0x20 | ||
56 | |||
57 | #define TIME_NUM 8 | ||
58 | #define ALARM_1SEC (1 << 7) | ||
59 | #define HOUR_12 (1 << 7) | ||
60 | #define HOUR_AM_PM (1 << 5) | ||
61 | #define ALARM0_IRQ (1 << 3) | ||
62 | #define ALARM1_IRQ (1 << 2) | ||
63 | #define ALARM0_STATUS (1 << 2) | ||
64 | #define ALARM1_STATUS (1 << 1) | ||
65 | |||
66 | |||
67 | struct max8925_rtc_info { | ||
68 | struct rtc_device *rtc_dev; | ||
69 | struct max8925_chip *chip; | ||
70 | struct i2c_client *rtc; | ||
71 | struct device *dev; | ||
72 | }; | ||
73 | |||
74 | static irqreturn_t rtc_update_handler(int irq, void *data) | ||
75 | { | ||
76 | struct max8925_rtc_info *info = (struct max8925_rtc_info *)data; | ||
77 | |||
78 | /* disable ALARM0 except for 1SEC alarm */ | ||
79 | max8925_set_bits(info->rtc, MAX8925_ALARM0_CNTL, 0x7f, 0); | ||
80 | rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); | ||
81 | return IRQ_HANDLED; | ||
82 | } | ||
83 | |||
84 | static int tm_calc(struct rtc_time *tm, unsigned char *buf, int len) | ||
85 | { | ||
86 | if (len < TIME_NUM) | ||
87 | return -EINVAL; | ||
88 | tm->tm_year = (buf[RTC_YEAR2] >> 4) * 1000 | ||
89 | + (buf[RTC_YEAR2] & 0xf) * 100 | ||
90 | + (buf[RTC_YEAR1] >> 4) * 10 | ||
91 | + (buf[RTC_YEAR1] & 0xf); | ||
92 | tm->tm_year -= 1900; | ||
93 | tm->tm_mon = ((buf[RTC_MONTH] >> 4) & 0x01) * 10 | ||
94 | + (buf[RTC_MONTH] & 0x0f); | ||
95 | tm->tm_mday = ((buf[RTC_DATE] >> 4) & 0x03) * 10 | ||
96 | + (buf[RTC_DATE] & 0x0f); | ||
97 | tm->tm_wday = buf[RTC_WEEKDAY] & 0x07; | ||
98 | if (buf[RTC_HOUR] & HOUR_12) { | ||
99 | tm->tm_hour = ((buf[RTC_HOUR] >> 4) & 0x1) * 10 | ||
100 | + (buf[RTC_HOUR] & 0x0f); | ||
101 | if (buf[RTC_HOUR] & HOUR_AM_PM) | ||
102 | tm->tm_hour += 12; | ||
103 | } else | ||
104 | tm->tm_hour = ((buf[RTC_HOUR] >> 4) & 0x03) * 10 | ||
105 | + (buf[RTC_HOUR] & 0x0f); | ||
106 | tm->tm_min = ((buf[RTC_MIN] >> 4) & 0x7) * 10 | ||
107 | + (buf[RTC_MIN] & 0x0f); | ||
108 | tm->tm_sec = ((buf[RTC_SEC] >> 4) & 0x7) * 10 | ||
109 | + (buf[RTC_SEC] & 0x0f); | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static int data_calc(unsigned char *buf, struct rtc_time *tm, int len) | ||
114 | { | ||
115 | unsigned char high, low; | ||
116 | |||
117 | if (len < TIME_NUM) | ||
118 | return -EINVAL; | ||
119 | |||
120 | high = (tm->tm_year + 1900) / 1000; | ||
121 | low = (tm->tm_year + 1900) / 100; | ||
122 | low = low - high * 10; | ||
123 | buf[RTC_YEAR2] = (high << 4) + low; | ||
124 | high = (tm->tm_year + 1900) / 10; | ||
125 | low = tm->tm_year + 1900; | ||
126 | low = low - high * 10; | ||
127 | high = high - (high / 10) * 10; | ||
128 | buf[RTC_YEAR1] = (high << 4) + low; | ||
129 | high = tm->tm_mon / 10; | ||
130 | low = tm->tm_mon; | ||
131 | low = low - high * 10; | ||
132 | buf[RTC_MONTH] = (high << 4) + low; | ||
133 | high = tm->tm_mday / 10; | ||
134 | low = tm->tm_mday; | ||
135 | low = low - high * 10; | ||
136 | buf[RTC_DATE] = (high << 4) + low; | ||
137 | buf[RTC_WEEKDAY] = tm->tm_wday; | ||
138 | high = tm->tm_hour / 10; | ||
139 | low = tm->tm_hour; | ||
140 | low = low - high * 10; | ||
141 | buf[RTC_HOUR] = (high << 4) + low; | ||
142 | high = tm->tm_min / 10; | ||
143 | low = tm->tm_min; | ||
144 | low = low - high * 10; | ||
145 | buf[RTC_MIN] = (high << 4) + low; | ||
146 | high = tm->tm_sec / 10; | ||
147 | low = tm->tm_sec; | ||
148 | low = low - high * 10; | ||
149 | buf[RTC_SEC] = (high << 4) + low; | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int max8925_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
154 | { | ||
155 | struct max8925_rtc_info *info = dev_get_drvdata(dev); | ||
156 | unsigned char buf[TIME_NUM]; | ||
157 | int ret; | ||
158 | |||
159 | ret = max8925_bulk_read(info->rtc, MAX8925_RTC_SEC, TIME_NUM, buf); | ||
160 | if (ret < 0) | ||
161 | goto out; | ||
162 | ret = tm_calc(tm, buf, TIME_NUM); | ||
163 | out: | ||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | static int max8925_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
168 | { | ||
169 | struct max8925_rtc_info *info = dev_get_drvdata(dev); | ||
170 | unsigned char buf[TIME_NUM]; | ||
171 | int ret; | ||
172 | |||
173 | ret = data_calc(buf, tm, TIME_NUM); | ||
174 | if (ret < 0) | ||
175 | goto out; | ||
176 | ret = max8925_bulk_write(info->rtc, MAX8925_RTC_SEC, TIME_NUM, buf); | ||
177 | out: | ||
178 | return ret; | ||
179 | } | ||
180 | |||
181 | static int max8925_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
182 | { | ||
183 | struct max8925_rtc_info *info = dev_get_drvdata(dev); | ||
184 | unsigned char buf[TIME_NUM]; | ||
185 | int ret; | ||
186 | |||
187 | ret = max8925_bulk_read(info->rtc, MAX8925_ALARM0_SEC, TIME_NUM, buf); | ||
188 | if (ret < 0) | ||
189 | goto out; | ||
190 | ret = tm_calc(&alrm->time, buf, TIME_NUM); | ||
191 | if (ret < 0) | ||
192 | goto out; | ||
193 | ret = max8925_reg_read(info->rtc, MAX8925_RTC_IRQ_MASK); | ||
194 | if (ret < 0) | ||
195 | goto out; | ||
196 | if ((ret & ALARM0_IRQ) == 0) | ||
197 | alrm->enabled = 1; | ||
198 | else | ||
199 | alrm->enabled = 0; | ||
200 | ret = max8925_reg_read(info->rtc, MAX8925_RTC_STATUS); | ||
201 | if (ret < 0) | ||
202 | goto out; | ||
203 | if (ret & ALARM0_STATUS) | ||
204 | alrm->pending = 1; | ||
205 | else | ||
206 | alrm->pending = 0; | ||
207 | out: | ||
208 | return ret; | ||
209 | } | ||
210 | |||
211 | static int max8925_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
212 | { | ||
213 | struct max8925_rtc_info *info = dev_get_drvdata(dev); | ||
214 | unsigned char buf[TIME_NUM]; | ||
215 | int ret; | ||
216 | |||
217 | ret = data_calc(buf, &alrm->time, TIME_NUM); | ||
218 | if (ret < 0) | ||
219 | goto out; | ||
220 | ret = max8925_bulk_write(info->rtc, MAX8925_ALARM0_SEC, TIME_NUM, buf); | ||
221 | if (ret < 0) | ||
222 | goto out; | ||
223 | /* only enable alarm on year/month/day/hour/min/sec */ | ||
224 | ret = max8925_reg_write(info->rtc, MAX8925_ALARM0_CNTL, 0x77); | ||
225 | if (ret < 0) | ||
226 | goto out; | ||
227 | out: | ||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | static const struct rtc_class_ops max8925_rtc_ops = { | ||
232 | .read_time = max8925_rtc_read_time, | ||
233 | .set_time = max8925_rtc_set_time, | ||
234 | .read_alarm = max8925_rtc_read_alarm, | ||
235 | .set_alarm = max8925_rtc_set_alarm, | ||
236 | }; | ||
237 | |||
238 | static int __devinit max8925_rtc_probe(struct platform_device *pdev) | ||
239 | { | ||
240 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
241 | struct max8925_rtc_info *info; | ||
242 | int irq, ret; | ||
243 | |||
244 | info = kzalloc(sizeof(struct max8925_rtc_info), GFP_KERNEL); | ||
245 | if (!info) | ||
246 | return -ENOMEM; | ||
247 | info->chip = chip; | ||
248 | info->rtc = chip->rtc; | ||
249 | info->dev = &pdev->dev; | ||
250 | irq = chip->irq_base + MAX8925_IRQ_RTC_ALARM0; | ||
251 | |||
252 | ret = request_threaded_irq(irq, NULL, rtc_update_handler, | ||
253 | IRQF_ONESHOT, "rtc-alarm0", info); | ||
254 | if (ret < 0) { | ||
255 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", | ||
256 | irq, ret); | ||
257 | goto out_irq; | ||
258 | } | ||
259 | |||
260 | info->rtc_dev = rtc_device_register("max8925-rtc", &pdev->dev, | ||
261 | &max8925_rtc_ops, THIS_MODULE); | ||
262 | ret = PTR_ERR(info->rtc_dev); | ||
263 | if (IS_ERR(info->rtc_dev)) { | ||
264 | dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); | ||
265 | goto out_rtc; | ||
266 | } | ||
267 | |||
268 | dev_set_drvdata(&pdev->dev, info); | ||
269 | platform_set_drvdata(pdev, info); | ||
270 | |||
271 | return 0; | ||
272 | out_rtc: | ||
273 | free_irq(chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info); | ||
274 | out_irq: | ||
275 | kfree(info); | ||
276 | return ret; | ||
277 | } | ||
278 | |||
279 | static int __devexit max8925_rtc_remove(struct platform_device *pdev) | ||
280 | { | ||
281 | struct max8925_rtc_info *info = platform_get_drvdata(pdev); | ||
282 | |||
283 | if (info) { | ||
284 | free_irq(info->chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info); | ||
285 | rtc_device_unregister(info->rtc_dev); | ||
286 | kfree(info); | ||
287 | } | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static struct platform_driver max8925_rtc_driver = { | ||
292 | .driver = { | ||
293 | .name = "max8925-rtc", | ||
294 | .owner = THIS_MODULE, | ||
295 | }, | ||
296 | .probe = max8925_rtc_probe, | ||
297 | .remove = __devexit_p(max8925_rtc_remove), | ||
298 | }; | ||
299 | |||
300 | static int __init max8925_rtc_init(void) | ||
301 | { | ||
302 | return platform_driver_register(&max8925_rtc_driver); | ||
303 | } | ||
304 | module_init(max8925_rtc_init); | ||
305 | |||
306 | static void __exit max8925_rtc_exit(void) | ||
307 | { | ||
308 | platform_driver_unregister(&max8925_rtc_driver); | ||
309 | } | ||
310 | module_exit(max8925_rtc_exit); | ||
311 | |||
312 | MODULE_DESCRIPTION("Maxim MAX8925 RTC driver"); | ||
313 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | ||
314 | MODULE_LICENSE("GPL"); | ||
315 | |||
diff --git a/drivers/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c new file mode 100644 index 000000000000..f22dee35f330 --- /dev/null +++ b/drivers/rtc/rtc-max8998.c | |||
@@ -0,0 +1,300 @@ | |||
1 | /* | ||
2 | * RTC driver for Maxim MAX8998 | ||
3 | * | ||
4 | * Copyright (C) 2010 Samsung Electronics Co.Ltd | ||
5 | * Author: Minkyu Kang <mk7.kang@samsung.com> | ||
6 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/bcd.h> | ||
19 | #include <linux/rtc.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/mfd/max8998.h> | ||
22 | #include <linux/mfd/max8998-private.h> | ||
23 | |||
24 | #define MAX8998_RTC_SEC 0x00 | ||
25 | #define MAX8998_RTC_MIN 0x01 | ||
26 | #define MAX8998_RTC_HOUR 0x02 | ||
27 | #define MAX8998_RTC_WEEKDAY 0x03 | ||
28 | #define MAX8998_RTC_DATE 0x04 | ||
29 | #define MAX8998_RTC_MONTH 0x05 | ||
30 | #define MAX8998_RTC_YEAR1 0x06 | ||
31 | #define MAX8998_RTC_YEAR2 0x07 | ||
32 | #define MAX8998_ALARM0_SEC 0x08 | ||
33 | #define MAX8998_ALARM0_MIN 0x09 | ||
34 | #define MAX8998_ALARM0_HOUR 0x0a | ||
35 | #define MAX8998_ALARM0_WEEKDAY 0x0b | ||
36 | #define MAX8998_ALARM0_DATE 0x0c | ||
37 | #define MAX8998_ALARM0_MONTH 0x0d | ||
38 | #define MAX8998_ALARM0_YEAR1 0x0e | ||
39 | #define MAX8998_ALARM0_YEAR2 0x0f | ||
40 | #define MAX8998_ALARM1_SEC 0x10 | ||
41 | #define MAX8998_ALARM1_MIN 0x11 | ||
42 | #define MAX8998_ALARM1_HOUR 0x12 | ||
43 | #define MAX8998_ALARM1_WEEKDAY 0x13 | ||
44 | #define MAX8998_ALARM1_DATE 0x14 | ||
45 | #define MAX8998_ALARM1_MONTH 0x15 | ||
46 | #define MAX8998_ALARM1_YEAR1 0x16 | ||
47 | #define MAX8998_ALARM1_YEAR2 0x17 | ||
48 | #define MAX8998_ALARM0_CONF 0x18 | ||
49 | #define MAX8998_ALARM1_CONF 0x19 | ||
50 | #define MAX8998_RTC_STATUS 0x1a | ||
51 | #define MAX8998_WTSR_SMPL_CNTL 0x1b | ||
52 | #define MAX8998_TEST 0x1f | ||
53 | |||
54 | #define HOUR_12 (1 << 7) | ||
55 | #define HOUR_PM (1 << 5) | ||
56 | #define ALARM0_STATUS (1 << 1) | ||
57 | #define ALARM1_STATUS (1 << 2) | ||
58 | |||
59 | enum { | ||
60 | RTC_SEC = 0, | ||
61 | RTC_MIN, | ||
62 | RTC_HOUR, | ||
63 | RTC_WEEKDAY, | ||
64 | RTC_DATE, | ||
65 | RTC_MONTH, | ||
66 | RTC_YEAR1, | ||
67 | RTC_YEAR2, | ||
68 | }; | ||
69 | |||
70 | struct max8998_rtc_info { | ||
71 | struct device *dev; | ||
72 | struct max8998_dev *max8998; | ||
73 | struct i2c_client *rtc; | ||
74 | struct rtc_device *rtc_dev; | ||
75 | int irq; | ||
76 | }; | ||
77 | |||
78 | static void max8998_data_to_tm(u8 *data, struct rtc_time *tm) | ||
79 | { | ||
80 | tm->tm_sec = bcd2bin(data[RTC_SEC]); | ||
81 | tm->tm_min = bcd2bin(data[RTC_MIN]); | ||
82 | if (data[RTC_HOUR] & HOUR_12) { | ||
83 | tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x1f); | ||
84 | if (data[RTC_HOUR] & HOUR_PM) | ||
85 | tm->tm_hour += 12; | ||
86 | } else | ||
87 | tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x3f); | ||
88 | |||
89 | tm->tm_wday = data[RTC_WEEKDAY] & 0x07; | ||
90 | tm->tm_mday = bcd2bin(data[RTC_DATE]); | ||
91 | tm->tm_mon = bcd2bin(data[RTC_MONTH]); | ||
92 | tm->tm_year = bcd2bin(data[RTC_YEAR1]) + bcd2bin(data[RTC_YEAR2]) * 100; | ||
93 | tm->tm_year -= 1900; | ||
94 | } | ||
95 | |||
96 | static void max8998_tm_to_data(struct rtc_time *tm, u8 *data) | ||
97 | { | ||
98 | data[RTC_SEC] = bin2bcd(tm->tm_sec); | ||
99 | data[RTC_MIN] = bin2bcd(tm->tm_min); | ||
100 | data[RTC_HOUR] = bin2bcd(tm->tm_hour); | ||
101 | data[RTC_WEEKDAY] = tm->tm_wday; | ||
102 | data[RTC_DATE] = bin2bcd(tm->tm_mday); | ||
103 | data[RTC_MONTH] = bin2bcd(tm->tm_mon); | ||
104 | data[RTC_YEAR1] = bin2bcd(tm->tm_year % 100); | ||
105 | data[RTC_YEAR2] = bin2bcd((tm->tm_year + 1900) / 100); | ||
106 | } | ||
107 | |||
108 | static int max8998_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
109 | { | ||
110 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
111 | u8 data[8]; | ||
112 | int ret; | ||
113 | |||
114 | ret = max8998_bulk_read(info->rtc, MAX8998_RTC_SEC, 8, data); | ||
115 | if (ret < 0) | ||
116 | return ret; | ||
117 | |||
118 | max8998_data_to_tm(data, tm); | ||
119 | |||
120 | return rtc_valid_tm(tm); | ||
121 | } | ||
122 | |||
123 | static int max8998_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
124 | { | ||
125 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
126 | u8 data[8]; | ||
127 | |||
128 | max8998_tm_to_data(tm, data); | ||
129 | |||
130 | return max8998_bulk_write(info->rtc, MAX8998_RTC_SEC, 8, data); | ||
131 | } | ||
132 | |||
133 | static int max8998_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
134 | { | ||
135 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
136 | u8 data[8]; | ||
137 | u8 val; | ||
138 | int ret; | ||
139 | |||
140 | ret = max8998_bulk_read(info->rtc, MAX8998_ALARM0_SEC, 8, data); | ||
141 | if (ret < 0) | ||
142 | return ret; | ||
143 | |||
144 | max8998_data_to_tm(data, &alrm->time); | ||
145 | |||
146 | ret = max8998_read_reg(info->rtc, MAX8998_ALARM0_CONF, &val); | ||
147 | if (ret < 0) | ||
148 | return ret; | ||
149 | |||
150 | alrm->enabled = !!val; | ||
151 | |||
152 | ret = max8998_read_reg(info->rtc, MAX8998_RTC_STATUS, &val); | ||
153 | if (ret < 0) | ||
154 | return ret; | ||
155 | |||
156 | if (val & ALARM0_STATUS) | ||
157 | alrm->pending = 1; | ||
158 | else | ||
159 | alrm->pending = 0; | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static int max8998_rtc_stop_alarm(struct max8998_rtc_info *info) | ||
165 | { | ||
166 | return max8998_write_reg(info->rtc, MAX8998_ALARM0_CONF, 0); | ||
167 | } | ||
168 | |||
169 | static int max8998_rtc_start_alarm(struct max8998_rtc_info *info) | ||
170 | { | ||
171 | return max8998_write_reg(info->rtc, MAX8998_ALARM0_CONF, 0x77); | ||
172 | } | ||
173 | |||
174 | static int max8998_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
175 | { | ||
176 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
177 | u8 data[8]; | ||
178 | int ret; | ||
179 | |||
180 | max8998_tm_to_data(&alrm->time, data); | ||
181 | |||
182 | ret = max8998_rtc_stop_alarm(info); | ||
183 | if (ret < 0) | ||
184 | return ret; | ||
185 | |||
186 | ret = max8998_bulk_write(info->rtc, MAX8998_ALARM0_SEC, 8, data); | ||
187 | if (ret < 0) | ||
188 | return ret; | ||
189 | |||
190 | if (alrm->enabled) | ||
191 | return max8998_rtc_start_alarm(info); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static int max8998_rtc_alarm_irq_enable(struct device *dev, | ||
197 | unsigned int enabled) | ||
198 | { | ||
199 | struct max8998_rtc_info *info = dev_get_drvdata(dev); | ||
200 | |||
201 | if (enabled) | ||
202 | return max8998_rtc_start_alarm(info); | ||
203 | else | ||
204 | return max8998_rtc_stop_alarm(info); | ||
205 | } | ||
206 | |||
207 | static irqreturn_t max8998_rtc_alarm_irq(int irq, void *data) | ||
208 | { | ||
209 | struct max8998_rtc_info *info = data; | ||
210 | |||
211 | rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); | ||
212 | |||
213 | return IRQ_HANDLED; | ||
214 | } | ||
215 | |||
216 | static const struct rtc_class_ops max8998_rtc_ops = { | ||
217 | .read_time = max8998_rtc_read_time, | ||
218 | .set_time = max8998_rtc_set_time, | ||
219 | .read_alarm = max8998_rtc_read_alarm, | ||
220 | .set_alarm = max8998_rtc_set_alarm, | ||
221 | .alarm_irq_enable = max8998_rtc_alarm_irq_enable, | ||
222 | }; | ||
223 | |||
224 | static int __devinit max8998_rtc_probe(struct platform_device *pdev) | ||
225 | { | ||
226 | struct max8998_dev *max8998 = dev_get_drvdata(pdev->dev.parent); | ||
227 | struct max8998_rtc_info *info; | ||
228 | int ret; | ||
229 | |||
230 | info = kzalloc(sizeof(struct max8998_rtc_info), GFP_KERNEL); | ||
231 | if (!info) | ||
232 | return -ENOMEM; | ||
233 | |||
234 | info->dev = &pdev->dev; | ||
235 | info->max8998 = max8998; | ||
236 | info->rtc = max8998->rtc; | ||
237 | info->irq = max8998->irq_base + MAX8998_IRQ_ALARM0; | ||
238 | |||
239 | info->rtc_dev = rtc_device_register("max8998-rtc", &pdev->dev, | ||
240 | &max8998_rtc_ops, THIS_MODULE); | ||
241 | |||
242 | if (IS_ERR(info->rtc_dev)) { | ||
243 | ret = PTR_ERR(info->rtc_dev); | ||
244 | dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); | ||
245 | goto out_rtc; | ||
246 | } | ||
247 | |||
248 | platform_set_drvdata(pdev, info); | ||
249 | |||
250 | ret = request_threaded_irq(info->irq, NULL, max8998_rtc_alarm_irq, 0, | ||
251 | "rtc-alarm0", info); | ||
252 | if (ret < 0) | ||
253 | dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", | ||
254 | info->irq, ret); | ||
255 | |||
256 | return 0; | ||
257 | |||
258 | out_rtc: | ||
259 | kfree(info); | ||
260 | return ret; | ||
261 | } | ||
262 | |||
263 | static int __devexit max8998_rtc_remove(struct platform_device *pdev) | ||
264 | { | ||
265 | struct max8998_rtc_info *info = platform_get_drvdata(pdev); | ||
266 | |||
267 | if (info) { | ||
268 | free_irq(info->irq, info); | ||
269 | rtc_device_unregister(info->rtc_dev); | ||
270 | kfree(info); | ||
271 | } | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static struct platform_driver max8998_rtc_driver = { | ||
277 | .driver = { | ||
278 | .name = "max8998-rtc", | ||
279 | .owner = THIS_MODULE, | ||
280 | }, | ||
281 | .probe = max8998_rtc_probe, | ||
282 | .remove = __devexit_p(max8998_rtc_remove), | ||
283 | }; | ||
284 | |||
285 | static int __init max8998_rtc_init(void) | ||
286 | { | ||
287 | return platform_driver_register(&max8998_rtc_driver); | ||
288 | } | ||
289 | module_init(max8998_rtc_init); | ||
290 | |||
291 | static void __exit max8998_rtc_exit(void) | ||
292 | { | ||
293 | platform_driver_unregister(&max8998_rtc_driver); | ||
294 | } | ||
295 | module_exit(max8998_rtc_exit); | ||
296 | |||
297 | MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>"); | ||
298 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | ||
299 | MODULE_DESCRIPTION("Maxim MAX8998 RTC driver"); | ||
300 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c new file mode 100644 index 000000000000..5314b153bfba --- /dev/null +++ b/drivers/rtc/rtc-mc13xxx.c | |||
@@ -0,0 +1,437 @@ | |||
1 | /* | ||
2 | * Real Time Clock driver for Freescale MC13XXX PMIC | ||
3 | * | ||
4 | * (C) 2009 Sascha Hauer, Pengutronix | ||
5 | * (C) 2009 Uwe Kleine-Koenig, Pengutronix | ||
6 | * | ||
7 | * 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 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/mfd/mc13xxx.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/rtc.h> | ||
18 | |||
19 | #define DRIVER_NAME "mc13xxx-rtc" | ||
20 | |||
21 | #define MC13XXX_RTCTOD 20 | ||
22 | #define MC13XXX_RTCTODA 21 | ||
23 | #define MC13XXX_RTCDAY 22 | ||
24 | #define MC13XXX_RTCDAYA 23 | ||
25 | |||
26 | struct mc13xxx_rtc { | ||
27 | struct rtc_device *rtc; | ||
28 | struct mc13xxx *mc13xxx; | ||
29 | int valid; | ||
30 | }; | ||
31 | |||
32 | static int mc13xxx_rtc_irq_enable_unlocked(struct device *dev, | ||
33 | unsigned int enabled, int irq) | ||
34 | { | ||
35 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
36 | int (*func)(struct mc13xxx *mc13xxx, int irq); | ||
37 | |||
38 | if (!priv->valid) | ||
39 | return -ENODATA; | ||
40 | |||
41 | func = enabled ? mc13xxx_irq_unmask : mc13xxx_irq_mask; | ||
42 | return func(priv->mc13xxx, irq); | ||
43 | } | ||
44 | |||
45 | static int mc13xxx_rtc_irq_enable(struct device *dev, | ||
46 | unsigned int enabled, int irq) | ||
47 | { | ||
48 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
49 | int ret; | ||
50 | |||
51 | mc13xxx_lock(priv->mc13xxx); | ||
52 | |||
53 | ret = mc13xxx_rtc_irq_enable_unlocked(dev, enabled, irq); | ||
54 | |||
55 | mc13xxx_unlock(priv->mc13xxx); | ||
56 | |||
57 | return ret; | ||
58 | } | ||
59 | |||
60 | static int mc13xxx_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
61 | { | ||
62 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
63 | unsigned int seconds, days1, days2; | ||
64 | unsigned long s1970; | ||
65 | int ret; | ||
66 | |||
67 | mc13xxx_lock(priv->mc13xxx); | ||
68 | |||
69 | if (!priv->valid) { | ||
70 | ret = -ENODATA; | ||
71 | goto out; | ||
72 | } | ||
73 | |||
74 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days1); | ||
75 | if (unlikely(ret)) | ||
76 | goto out; | ||
77 | |||
78 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTOD, &seconds); | ||
79 | if (unlikely(ret)) | ||
80 | goto out; | ||
81 | |||
82 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days2); | ||
83 | out: | ||
84 | mc13xxx_unlock(priv->mc13xxx); | ||
85 | |||
86 | if (ret) | ||
87 | return ret; | ||
88 | |||
89 | if (days2 == days1 + 1) { | ||
90 | if (seconds >= 86400 / 2) | ||
91 | days2 = days1; | ||
92 | else | ||
93 | days1 = days2; | ||
94 | } | ||
95 | |||
96 | if (days1 != days2) | ||
97 | return -EIO; | ||
98 | |||
99 | s1970 = days1 * 86400 + seconds; | ||
100 | |||
101 | rtc_time_to_tm(s1970, tm); | ||
102 | |||
103 | return rtc_valid_tm(tm); | ||
104 | } | ||
105 | |||
106 | static int mc13xxx_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
107 | { | ||
108 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
109 | unsigned int seconds, days; | ||
110 | unsigned int alarmseconds; | ||
111 | int ret; | ||
112 | |||
113 | seconds = secs % 86400; | ||
114 | days = secs / 86400; | ||
115 | |||
116 | mc13xxx_lock(priv->mc13xxx); | ||
117 | |||
118 | /* | ||
119 | * temporarily invalidate alarm to prevent triggering it when the day is | ||
120 | * already updated while the time isn't yet. | ||
121 | */ | ||
122 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &alarmseconds); | ||
123 | if (unlikely(ret)) | ||
124 | goto out; | ||
125 | |||
126 | if (alarmseconds < 86400) { | ||
127 | ret = mc13xxx_reg_write(priv->mc13xxx, | ||
128 | MC13XXX_RTCTODA, 0x1ffff); | ||
129 | if (unlikely(ret)) | ||
130 | goto out; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * write seconds=0 to prevent a day switch between writing days | ||
135 | * and seconds below | ||
136 | */ | ||
137 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, 0); | ||
138 | if (unlikely(ret)) | ||
139 | goto out; | ||
140 | |||
141 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAY, days); | ||
142 | if (unlikely(ret)) | ||
143 | goto out; | ||
144 | |||
145 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, seconds); | ||
146 | if (unlikely(ret)) | ||
147 | goto out; | ||
148 | |||
149 | /* restore alarm */ | ||
150 | if (alarmseconds < 86400) { | ||
151 | ret = mc13xxx_reg_write(priv->mc13xxx, | ||
152 | MC13XXX_RTCTODA, alarmseconds); | ||
153 | if (unlikely(ret)) | ||
154 | goto out; | ||
155 | } | ||
156 | |||
157 | ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_RTCRST); | ||
158 | if (unlikely(ret)) | ||
159 | goto out; | ||
160 | |||
161 | ret = mc13xxx_irq_unmask(priv->mc13xxx, MC13XXX_IRQ_RTCRST); | ||
162 | out: | ||
163 | priv->valid = !ret; | ||
164 | |||
165 | mc13xxx_unlock(priv->mc13xxx); | ||
166 | |||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | static int mc13xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
171 | { | ||
172 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
173 | unsigned seconds, days; | ||
174 | unsigned long s1970; | ||
175 | int enabled, pending; | ||
176 | int ret; | ||
177 | |||
178 | mc13xxx_lock(priv->mc13xxx); | ||
179 | |||
180 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &seconds); | ||
181 | if (unlikely(ret)) | ||
182 | goto out; | ||
183 | if (seconds >= 86400) { | ||
184 | ret = -ENODATA; | ||
185 | goto out; | ||
186 | } | ||
187 | |||
188 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days); | ||
189 | if (unlikely(ret)) | ||
190 | goto out; | ||
191 | |||
192 | ret = mc13xxx_irq_status(priv->mc13xxx, MC13XXX_IRQ_TODA, | ||
193 | &enabled, &pending); | ||
194 | |||
195 | out: | ||
196 | mc13xxx_unlock(priv->mc13xxx); | ||
197 | |||
198 | if (ret) | ||
199 | return ret; | ||
200 | |||
201 | alarm->enabled = enabled; | ||
202 | alarm->pending = pending; | ||
203 | |||
204 | s1970 = days * 86400 + seconds; | ||
205 | |||
206 | rtc_time_to_tm(s1970, &alarm->time); | ||
207 | dev_dbg(dev, "%s: %lu\n", __func__, s1970); | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
213 | { | ||
214 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | ||
215 | unsigned long s1970; | ||
216 | unsigned seconds, days; | ||
217 | int ret; | ||
218 | |||
219 | mc13xxx_lock(priv->mc13xxx); | ||
220 | |||
221 | /* disable alarm to prevent false triggering */ | ||
222 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, 0x1ffff); | ||
223 | if (unlikely(ret)) | ||
224 | goto out; | ||
225 | |||
226 | ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_TODA); | ||
227 | if (unlikely(ret)) | ||
228 | goto out; | ||
229 | |||
230 | ret = rtc_tm_to_time(&alarm->time, &s1970); | ||
231 | if (unlikely(ret)) | ||
232 | goto out; | ||
233 | |||
234 | dev_dbg(dev, "%s: o%2.s %lu\n", __func__, alarm->enabled ? "n" : "ff", | ||
235 | s1970); | ||
236 | |||
237 | ret = mc13xxx_rtc_irq_enable_unlocked(dev, alarm->enabled, | ||
238 | MC13XXX_IRQ_TODA); | ||
239 | if (unlikely(ret)) | ||
240 | goto out; | ||
241 | |||
242 | seconds = s1970 % 86400; | ||
243 | days = s1970 / 86400; | ||
244 | |||
245 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAYA, days); | ||
246 | if (unlikely(ret)) | ||
247 | goto out; | ||
248 | |||
249 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, seconds); | ||
250 | |||
251 | out: | ||
252 | mc13xxx_unlock(priv->mc13xxx); | ||
253 | |||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | static irqreturn_t mc13xxx_rtc_alarm_handler(int irq, void *dev) | ||
258 | { | ||
259 | struct mc13xxx_rtc *priv = dev; | ||
260 | struct mc13xxx *mc13xxx = priv->mc13xxx; | ||
261 | |||
262 | dev_dbg(&priv->rtc->dev, "Alarm\n"); | ||
263 | |||
264 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF); | ||
265 | |||
266 | mc13xxx_irq_ack(mc13xxx, irq); | ||
267 | |||
268 | return IRQ_HANDLED; | ||
269 | } | ||
270 | |||
271 | static irqreturn_t mc13xxx_rtc_update_handler(int irq, void *dev) | ||
272 | { | ||
273 | struct mc13xxx_rtc *priv = dev; | ||
274 | struct mc13xxx *mc13xxx = priv->mc13xxx; | ||
275 | |||
276 | dev_dbg(&priv->rtc->dev, "1HZ\n"); | ||
277 | |||
278 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF); | ||
279 | |||
280 | mc13xxx_irq_ack(mc13xxx, irq); | ||
281 | |||
282 | return IRQ_HANDLED; | ||
283 | } | ||
284 | |||
285 | static int mc13xxx_rtc_update_irq_enable(struct device *dev, | ||
286 | unsigned int enabled) | ||
287 | { | ||
288 | return mc13xxx_rtc_irq_enable(dev, enabled, MC13XXX_IRQ_1HZ); | ||
289 | } | ||
290 | |||
291 | static int mc13xxx_rtc_alarm_irq_enable(struct device *dev, | ||
292 | unsigned int enabled) | ||
293 | { | ||
294 | return mc13xxx_rtc_irq_enable(dev, enabled, MC13XXX_IRQ_TODA); | ||
295 | } | ||
296 | |||
297 | static const struct rtc_class_ops mc13xxx_rtc_ops = { | ||
298 | .read_time = mc13xxx_rtc_read_time, | ||
299 | .set_mmss = mc13xxx_rtc_set_mmss, | ||
300 | .read_alarm = mc13xxx_rtc_read_alarm, | ||
301 | .set_alarm = mc13xxx_rtc_set_alarm, | ||
302 | .alarm_irq_enable = mc13xxx_rtc_alarm_irq_enable, | ||
303 | .update_irq_enable = mc13xxx_rtc_update_irq_enable, | ||
304 | }; | ||
305 | |||
306 | static irqreturn_t mc13xxx_rtc_reset_handler(int irq, void *dev) | ||
307 | { | ||
308 | struct mc13xxx_rtc *priv = dev; | ||
309 | struct mc13xxx *mc13xxx = priv->mc13xxx; | ||
310 | |||
311 | dev_dbg(&priv->rtc->dev, "RTCRST\n"); | ||
312 | priv->valid = 0; | ||
313 | |||
314 | mc13xxx_irq_mask(mc13xxx, irq); | ||
315 | |||
316 | return IRQ_HANDLED; | ||
317 | } | ||
318 | |||
319 | static int __devinit mc13xxx_rtc_probe(struct platform_device *pdev) | ||
320 | { | ||
321 | int ret; | ||
322 | struct mc13xxx_rtc *priv; | ||
323 | struct mc13xxx *mc13xxx; | ||
324 | int rtcrst_pending; | ||
325 | |||
326 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
327 | if (!priv) | ||
328 | return -ENOMEM; | ||
329 | |||
330 | mc13xxx = dev_get_drvdata(pdev->dev.parent); | ||
331 | priv->mc13xxx = mc13xxx; | ||
332 | |||
333 | platform_set_drvdata(pdev, priv); | ||
334 | |||
335 | mc13xxx_lock(mc13xxx); | ||
336 | |||
337 | ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_RTCRST, | ||
338 | mc13xxx_rtc_reset_handler, DRIVER_NAME, priv); | ||
339 | if (ret) | ||
340 | goto err_reset_irq_request; | ||
341 | |||
342 | ret = mc13xxx_irq_status(mc13xxx, MC13XXX_IRQ_RTCRST, | ||
343 | NULL, &rtcrst_pending); | ||
344 | if (ret) | ||
345 | goto err_reset_irq_status; | ||
346 | |||
347 | priv->valid = !rtcrst_pending; | ||
348 | |||
349 | ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_1HZ, | ||
350 | mc13xxx_rtc_update_handler, DRIVER_NAME, priv); | ||
351 | if (ret) | ||
352 | goto err_update_irq_request; | ||
353 | |||
354 | ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_TODA, | ||
355 | mc13xxx_rtc_alarm_handler, DRIVER_NAME, priv); | ||
356 | if (ret) | ||
357 | goto err_alarm_irq_request; | ||
358 | |||
359 | priv->rtc = rtc_device_register(pdev->name, | ||
360 | &pdev->dev, &mc13xxx_rtc_ops, THIS_MODULE); | ||
361 | if (IS_ERR(priv->rtc)) { | ||
362 | ret = PTR_ERR(priv->rtc); | ||
363 | |||
364 | mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_TODA, priv); | ||
365 | err_alarm_irq_request: | ||
366 | |||
367 | mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_1HZ, priv); | ||
368 | err_update_irq_request: | ||
369 | |||
370 | err_reset_irq_status: | ||
371 | |||
372 | mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv); | ||
373 | err_reset_irq_request: | ||
374 | |||
375 | platform_set_drvdata(pdev, NULL); | ||
376 | kfree(priv); | ||
377 | } | ||
378 | |||
379 | mc13xxx_unlock(mc13xxx); | ||
380 | |||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | static int __devexit mc13xxx_rtc_remove(struct platform_device *pdev) | ||
385 | { | ||
386 | struct mc13xxx_rtc *priv = platform_get_drvdata(pdev); | ||
387 | |||
388 | mc13xxx_lock(priv->mc13xxx); | ||
389 | |||
390 | rtc_device_unregister(priv->rtc); | ||
391 | |||
392 | mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TODA, priv); | ||
393 | mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_1HZ, priv); | ||
394 | mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_RTCRST, priv); | ||
395 | |||
396 | mc13xxx_unlock(priv->mc13xxx); | ||
397 | |||
398 | platform_set_drvdata(pdev, NULL); | ||
399 | |||
400 | kfree(priv); | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | const struct platform_device_id mc13xxx_rtc_idtable[] = { | ||
406 | { | ||
407 | .name = "mc13783-rtc", | ||
408 | }, { | ||
409 | .name = "mc13892-rtc", | ||
410 | }, | ||
411 | }; | ||
412 | |||
413 | static struct platform_driver mc13xxx_rtc_driver = { | ||
414 | .id_table = mc13xxx_rtc_idtable, | ||
415 | .remove = __devexit_p(mc13xxx_rtc_remove), | ||
416 | .driver = { | ||
417 | .name = DRIVER_NAME, | ||
418 | .owner = THIS_MODULE, | ||
419 | }, | ||
420 | }; | ||
421 | |||
422 | static int __init mc13xxx_rtc_init(void) | ||
423 | { | ||
424 | return platform_driver_probe(&mc13xxx_rtc_driver, &mc13xxx_rtc_probe); | ||
425 | } | ||
426 | module_init(mc13xxx_rtc_init); | ||
427 | |||
428 | static void __exit mc13xxx_rtc_exit(void) | ||
429 | { | ||
430 | platform_driver_unregister(&mc13xxx_rtc_driver); | ||
431 | } | ||
432 | module_exit(mc13xxx_rtc_exit); | ||
433 | |||
434 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); | ||
435 | MODULE_DESCRIPTION("RTC driver for Freescale MC13XXX PMIC"); | ||
436 | MODULE_LICENSE("GPL v2"); | ||
437 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c new file mode 100644 index 000000000000..dfcdf0901d21 --- /dev/null +++ b/drivers/rtc/rtc-mpc5121.c | |||
@@ -0,0 +1,390 @@ | |||
1 | /* | ||
2 | * Real-time clock driver for MPC5121 | ||
3 | * | ||
4 | * Copyright 2007, Domen Puncer <domen.puncer@telargo.com> | ||
5 | * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved. | ||
6 | * | ||
7 | * 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 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/rtc.h> | ||
15 | #include <linux/of_device.h> | ||
16 | #include <linux/of_platform.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/slab.h> | ||
19 | |||
20 | struct mpc5121_rtc_regs { | ||
21 | u8 set_time; /* RTC + 0x00 */ | ||
22 | u8 hour_set; /* RTC + 0x01 */ | ||
23 | u8 minute_set; /* RTC + 0x02 */ | ||
24 | u8 second_set; /* RTC + 0x03 */ | ||
25 | |||
26 | u8 set_date; /* RTC + 0x04 */ | ||
27 | u8 month_set; /* RTC + 0x05 */ | ||
28 | u8 weekday_set; /* RTC + 0x06 */ | ||
29 | u8 date_set; /* RTC + 0x07 */ | ||
30 | |||
31 | u8 write_sw; /* RTC + 0x08 */ | ||
32 | u8 sw_set; /* RTC + 0x09 */ | ||
33 | u16 year_set; /* RTC + 0x0a */ | ||
34 | |||
35 | u8 alm_enable; /* RTC + 0x0c */ | ||
36 | u8 alm_hour_set; /* RTC + 0x0d */ | ||
37 | u8 alm_min_set; /* RTC + 0x0e */ | ||
38 | u8 int_enable; /* RTC + 0x0f */ | ||
39 | |||
40 | u8 reserved1; | ||
41 | u8 hour; /* RTC + 0x11 */ | ||
42 | u8 minute; /* RTC + 0x12 */ | ||
43 | u8 second; /* RTC + 0x13 */ | ||
44 | |||
45 | u8 month; /* RTC + 0x14 */ | ||
46 | u8 wday_mday; /* RTC + 0x15 */ | ||
47 | u16 year; /* RTC + 0x16 */ | ||
48 | |||
49 | u8 int_alm; /* RTC + 0x18 */ | ||
50 | u8 int_sw; /* RTC + 0x19 */ | ||
51 | u8 alm_status; /* RTC + 0x1a */ | ||
52 | u8 sw_minute; /* RTC + 0x1b */ | ||
53 | |||
54 | u8 bus_error_1; /* RTC + 0x1c */ | ||
55 | u8 int_day; /* RTC + 0x1d */ | ||
56 | u8 int_min; /* RTC + 0x1e */ | ||
57 | u8 int_sec; /* RTC + 0x1f */ | ||
58 | |||
59 | /* | ||
60 | * target_time: | ||
61 | * intended to be used for hibernation but hibernation | ||
62 | * does not work on silicon rev 1.5 so use it for non-volatile | ||
63 | * storage of offset between the actual_time register and linux | ||
64 | * time | ||
65 | */ | ||
66 | u32 target_time; /* RTC + 0x20 */ | ||
67 | /* | ||
68 | * actual_time: | ||
69 | * readonly time since VBAT_RTC was last connected | ||
70 | */ | ||
71 | u32 actual_time; /* RTC + 0x24 */ | ||
72 | u32 keep_alive; /* RTC + 0x28 */ | ||
73 | }; | ||
74 | |||
75 | struct mpc5121_rtc_data { | ||
76 | unsigned irq; | ||
77 | unsigned irq_periodic; | ||
78 | struct mpc5121_rtc_regs __iomem *regs; | ||
79 | struct rtc_device *rtc; | ||
80 | struct rtc_wkalrm wkalarm; | ||
81 | }; | ||
82 | |||
83 | /* | ||
84 | * Update second/minute/hour registers. | ||
85 | * | ||
86 | * This is just so alarm will work. | ||
87 | */ | ||
88 | static void mpc5121_rtc_update_smh(struct mpc5121_rtc_regs __iomem *regs, | ||
89 | struct rtc_time *tm) | ||
90 | { | ||
91 | out_8(®s->second_set, tm->tm_sec); | ||
92 | out_8(®s->minute_set, tm->tm_min); | ||
93 | out_8(®s->hour_set, tm->tm_hour); | ||
94 | |||
95 | /* set time sequence */ | ||
96 | out_8(®s->set_time, 0x1); | ||
97 | out_8(®s->set_time, 0x3); | ||
98 | out_8(®s->set_time, 0x1); | ||
99 | out_8(®s->set_time, 0x0); | ||
100 | } | ||
101 | |||
102 | static int mpc5121_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
103 | { | ||
104 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
105 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
106 | unsigned long now; | ||
107 | |||
108 | /* | ||
109 | * linux time is actual_time plus the offset saved in target_time | ||
110 | */ | ||
111 | now = in_be32(®s->actual_time) + in_be32(®s->target_time); | ||
112 | |||
113 | rtc_time_to_tm(now, tm); | ||
114 | |||
115 | /* | ||
116 | * update second minute hour registers | ||
117 | * so alarms will work | ||
118 | */ | ||
119 | mpc5121_rtc_update_smh(regs, tm); | ||
120 | |||
121 | return rtc_valid_tm(tm); | ||
122 | } | ||
123 | |||
124 | static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
125 | { | ||
126 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
127 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
128 | int ret; | ||
129 | unsigned long now; | ||
130 | |||
131 | /* | ||
132 | * The actual_time register is read only so we write the offset | ||
133 | * between it and linux time to the target_time register. | ||
134 | */ | ||
135 | ret = rtc_tm_to_time(tm, &now); | ||
136 | if (ret == 0) | ||
137 | out_be32(®s->target_time, now - in_be32(®s->actual_time)); | ||
138 | |||
139 | /* | ||
140 | * update second minute hour registers | ||
141 | * so alarms will work | ||
142 | */ | ||
143 | mpc5121_rtc_update_smh(regs, tm); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
149 | { | ||
150 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
151 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
152 | |||
153 | *alarm = rtc->wkalarm; | ||
154 | |||
155 | alarm->pending = in_8(®s->alm_status); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static int mpc5121_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
161 | { | ||
162 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
163 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
164 | |||
165 | /* | ||
166 | * the alarm has no seconds so deal with it | ||
167 | */ | ||
168 | if (alarm->time.tm_sec) { | ||
169 | alarm->time.tm_sec = 0; | ||
170 | alarm->time.tm_min++; | ||
171 | if (alarm->time.tm_min >= 60) { | ||
172 | alarm->time.tm_min = 0; | ||
173 | alarm->time.tm_hour++; | ||
174 | if (alarm->time.tm_hour >= 24) | ||
175 | alarm->time.tm_hour = 0; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | alarm->time.tm_mday = -1; | ||
180 | alarm->time.tm_mon = -1; | ||
181 | alarm->time.tm_year = -1; | ||
182 | |||
183 | out_8(®s->alm_min_set, alarm->time.tm_min); | ||
184 | out_8(®s->alm_hour_set, alarm->time.tm_hour); | ||
185 | |||
186 | out_8(®s->alm_enable, alarm->enabled); | ||
187 | |||
188 | rtc->wkalarm = *alarm; | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static irqreturn_t mpc5121_rtc_handler(int irq, void *dev) | ||
193 | { | ||
194 | struct mpc5121_rtc_data *rtc = dev_get_drvdata((struct device *)dev); | ||
195 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
196 | |||
197 | if (in_8(®s->int_alm)) { | ||
198 | /* acknowledge and clear status */ | ||
199 | out_8(®s->int_alm, 1); | ||
200 | out_8(®s->alm_status, 1); | ||
201 | |||
202 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); | ||
203 | return IRQ_HANDLED; | ||
204 | } | ||
205 | |||
206 | return IRQ_NONE; | ||
207 | } | ||
208 | |||
209 | static irqreturn_t mpc5121_rtc_handler_upd(int irq, void *dev) | ||
210 | { | ||
211 | struct mpc5121_rtc_data *rtc = dev_get_drvdata((struct device *)dev); | ||
212 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
213 | |||
214 | if (in_8(®s->int_sec) && (in_8(®s->int_enable) & 0x1)) { | ||
215 | /* acknowledge */ | ||
216 | out_8(®s->int_sec, 1); | ||
217 | |||
218 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_UF); | ||
219 | return IRQ_HANDLED; | ||
220 | } | ||
221 | |||
222 | return IRQ_NONE; | ||
223 | } | ||
224 | |||
225 | static int mpc5121_rtc_alarm_irq_enable(struct device *dev, | ||
226 | unsigned int enabled) | ||
227 | { | ||
228 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
229 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
230 | int val; | ||
231 | |||
232 | if (enabled) | ||
233 | val = 1; | ||
234 | else | ||
235 | val = 0; | ||
236 | |||
237 | out_8(®s->alm_enable, val); | ||
238 | rtc->wkalarm.enabled = val; | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int mpc5121_rtc_update_irq_enable(struct device *dev, | ||
244 | unsigned int enabled) | ||
245 | { | ||
246 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
247 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
248 | int val; | ||
249 | |||
250 | val = in_8(®s->int_enable); | ||
251 | |||
252 | if (enabled) | ||
253 | val = (val & ~0x8) | 0x1; | ||
254 | else | ||
255 | val &= ~0x1; | ||
256 | |||
257 | out_8(®s->int_enable, val); | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static const struct rtc_class_ops mpc5121_rtc_ops = { | ||
263 | .read_time = mpc5121_rtc_read_time, | ||
264 | .set_time = mpc5121_rtc_set_time, | ||
265 | .read_alarm = mpc5121_rtc_read_alarm, | ||
266 | .set_alarm = mpc5121_rtc_set_alarm, | ||
267 | .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable, | ||
268 | .update_irq_enable = mpc5121_rtc_update_irq_enable, | ||
269 | }; | ||
270 | |||
271 | static int __devinit mpc5121_rtc_probe(struct platform_device *op, | ||
272 | const struct of_device_id *match) | ||
273 | { | ||
274 | struct mpc5121_rtc_data *rtc; | ||
275 | int err = 0; | ||
276 | u32 ka; | ||
277 | |||
278 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | ||
279 | if (!rtc) | ||
280 | return -ENOMEM; | ||
281 | |||
282 | rtc->regs = of_iomap(op->dev.of_node, 0); | ||
283 | if (!rtc->regs) { | ||
284 | dev_err(&op->dev, "%s: couldn't map io space\n", __func__); | ||
285 | err = -ENOSYS; | ||
286 | goto out_free; | ||
287 | } | ||
288 | |||
289 | device_init_wakeup(&op->dev, 1); | ||
290 | |||
291 | dev_set_drvdata(&op->dev, rtc); | ||
292 | |||
293 | rtc->irq = irq_of_parse_and_map(op->dev.of_node, 1); | ||
294 | err = request_irq(rtc->irq, mpc5121_rtc_handler, IRQF_DISABLED, | ||
295 | "mpc5121-rtc", &op->dev); | ||
296 | if (err) { | ||
297 | dev_err(&op->dev, "%s: could not request irq: %i\n", | ||
298 | __func__, rtc->irq); | ||
299 | goto out_dispose; | ||
300 | } | ||
301 | |||
302 | rtc->irq_periodic = irq_of_parse_and_map(op->dev.of_node, 0); | ||
303 | err = request_irq(rtc->irq_periodic, mpc5121_rtc_handler_upd, | ||
304 | IRQF_DISABLED, "mpc5121-rtc_upd", &op->dev); | ||
305 | if (err) { | ||
306 | dev_err(&op->dev, "%s: could not request irq: %i\n", | ||
307 | __func__, rtc->irq_periodic); | ||
308 | goto out_dispose2; | ||
309 | } | ||
310 | |||
311 | ka = in_be32(&rtc->regs->keep_alive); | ||
312 | if (ka & 0x02) { | ||
313 | dev_warn(&op->dev, | ||
314 | "mpc5121-rtc: Battery or oscillator failure!\n"); | ||
315 | out_be32(&rtc->regs->keep_alive, ka); | ||
316 | } | ||
317 | |||
318 | rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev, | ||
319 | &mpc5121_rtc_ops, THIS_MODULE); | ||
320 | if (IS_ERR(rtc->rtc)) { | ||
321 | err = PTR_ERR(rtc->rtc); | ||
322 | goto out_free_irq; | ||
323 | } | ||
324 | |||
325 | return 0; | ||
326 | |||
327 | out_free_irq: | ||
328 | free_irq(rtc->irq_periodic, &op->dev); | ||
329 | out_dispose2: | ||
330 | irq_dispose_mapping(rtc->irq_periodic); | ||
331 | free_irq(rtc->irq, &op->dev); | ||
332 | out_dispose: | ||
333 | irq_dispose_mapping(rtc->irq); | ||
334 | iounmap(rtc->regs); | ||
335 | out_free: | ||
336 | kfree(rtc); | ||
337 | |||
338 | return err; | ||
339 | } | ||
340 | |||
341 | static int __devexit mpc5121_rtc_remove(struct platform_device *op) | ||
342 | { | ||
343 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(&op->dev); | ||
344 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
345 | |||
346 | /* disable interrupt, so there are no nasty surprises */ | ||
347 | out_8(®s->alm_enable, 0); | ||
348 | out_8(®s->int_enable, in_8(®s->int_enable) & ~0x1); | ||
349 | |||
350 | rtc_device_unregister(rtc->rtc); | ||
351 | iounmap(rtc->regs); | ||
352 | free_irq(rtc->irq, &op->dev); | ||
353 | free_irq(rtc->irq_periodic, &op->dev); | ||
354 | irq_dispose_mapping(rtc->irq); | ||
355 | irq_dispose_mapping(rtc->irq_periodic); | ||
356 | dev_set_drvdata(&op->dev, NULL); | ||
357 | kfree(rtc); | ||
358 | |||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static struct of_device_id mpc5121_rtc_match[] __devinitdata = { | ||
363 | { .compatible = "fsl,mpc5121-rtc", }, | ||
364 | {}, | ||
365 | }; | ||
366 | |||
367 | static struct of_platform_driver mpc5121_rtc_driver = { | ||
368 | .driver = { | ||
369 | .name = "mpc5121-rtc", | ||
370 | .owner = THIS_MODULE, | ||
371 | .of_match_table = mpc5121_rtc_match, | ||
372 | }, | ||
373 | .probe = mpc5121_rtc_probe, | ||
374 | .remove = __devexit_p(mpc5121_rtc_remove), | ||
375 | }; | ||
376 | |||
377 | static int __init mpc5121_rtc_init(void) | ||
378 | { | ||
379 | return of_register_platform_driver(&mpc5121_rtc_driver); | ||
380 | } | ||
381 | module_init(mpc5121_rtc_init); | ||
382 | |||
383 | static void __exit mpc5121_rtc_exit(void) | ||
384 | { | ||
385 | of_unregister_platform_driver(&mpc5121_rtc_driver); | ||
386 | } | ||
387 | module_exit(mpc5121_rtc_exit); | ||
388 | |||
389 | MODULE_LICENSE("GPL"); | ||
390 | MODULE_AUTHOR("John Rigby <jcrigby@gmail.com>"); | ||
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c new file mode 100644 index 000000000000..bcd0cf63eb16 --- /dev/null +++ b/drivers/rtc/rtc-mrst.c | |||
@@ -0,0 +1,582 @@ | |||
1 | /* | ||
2 | * rtc-mrst.c: Driver for Moorestown virtual RTC | ||
3 | * | ||
4 | * (C) Copyright 2009 Intel Corporation | ||
5 | * Author: Jacob Pan (jacob.jun.pan@intel.com) | ||
6 | * Feng Tang (feng.tang@intel.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; version 2 | ||
11 | * of the License. | ||
12 | * | ||
13 | * Note: | ||
14 | * VRTC is emulated by system controller firmware, the real HW | ||
15 | * RTC is located in the PMIC device. SCU FW shadows PMIC RTC | ||
16 | * in a memory mapped IO space that is visible to the host IA | ||
17 | * processor. | ||
18 | * | ||
19 | * This driver is based upon drivers/rtc/rtc-cmos.c | ||
20 | */ | ||
21 | |||
22 | /* | ||
23 | * Note: | ||
24 | * * vRTC only supports binary mode and 24H mode | ||
25 | * * vRTC only support PIE and AIE, no UIE, and its PIE only happens | ||
26 | * at 23:59:59pm everyday, no support for adjustable frequency | ||
27 | * * Alarm function is also limited to hr/min/sec. | ||
28 | */ | ||
29 | |||
30 | #include <linux/mod_devicetable.h> | ||
31 | #include <linux/platform_device.h> | ||
32 | #include <linux/interrupt.h> | ||
33 | #include <linux/spinlock.h> | ||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/init.h> | ||
37 | #include <linux/sfi.h> | ||
38 | |||
39 | #include <asm-generic/rtc.h> | ||
40 | #include <asm/intel_scu_ipc.h> | ||
41 | #include <asm/mrst.h> | ||
42 | #include <asm/mrst-vrtc.h> | ||
43 | |||
44 | struct mrst_rtc { | ||
45 | struct rtc_device *rtc; | ||
46 | struct device *dev; | ||
47 | int irq; | ||
48 | struct resource *iomem; | ||
49 | |||
50 | u8 enabled_wake; | ||
51 | u8 suspend_ctrl; | ||
52 | }; | ||
53 | |||
54 | static const char driver_name[] = "rtc_mrst"; | ||
55 | |||
56 | #define RTC_IRQMASK (RTC_PF | RTC_AF) | ||
57 | |||
58 | static inline int is_intr(u8 rtc_intr) | ||
59 | { | ||
60 | if (!(rtc_intr & RTC_IRQF)) | ||
61 | return 0; | ||
62 | return rtc_intr & RTC_IRQMASK; | ||
63 | } | ||
64 | |||
65 | /* | ||
66 | * rtc_time's year contains the increment over 1900, but vRTC's YEAR | ||
67 | * register can't be programmed to value larger than 0x64, so vRTC | ||
68 | * driver chose to use 1960 (1970 is UNIX time start point) as the base, | ||
69 | * and does the translation at read/write time. | ||
70 | * | ||
71 | * Why not just use 1970 as the offset? it's because using 1960 will | ||
72 | * make it consistent in leap year setting for both vrtc and low-level | ||
73 | * physical rtc devices. | ||
74 | */ | ||
75 | static int mrst_read_time(struct device *dev, struct rtc_time *time) | ||
76 | { | ||
77 | unsigned long flags; | ||
78 | |||
79 | if (rtc_is_updating()) | ||
80 | mdelay(20); | ||
81 | |||
82 | spin_lock_irqsave(&rtc_lock, flags); | ||
83 | time->tm_sec = vrtc_cmos_read(RTC_SECONDS); | ||
84 | time->tm_min = vrtc_cmos_read(RTC_MINUTES); | ||
85 | time->tm_hour = vrtc_cmos_read(RTC_HOURS); | ||
86 | time->tm_mday = vrtc_cmos_read(RTC_DAY_OF_MONTH); | ||
87 | time->tm_mon = vrtc_cmos_read(RTC_MONTH); | ||
88 | time->tm_year = vrtc_cmos_read(RTC_YEAR); | ||
89 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
90 | |||
91 | /* Adjust for the 1960/1900 */ | ||
92 | time->tm_year += 60; | ||
93 | time->tm_mon--; | ||
94 | return RTC_24H; | ||
95 | } | ||
96 | |||
97 | static int mrst_set_time(struct device *dev, struct rtc_time *time) | ||
98 | { | ||
99 | int ret; | ||
100 | unsigned long flags; | ||
101 | unsigned char mon, day, hrs, min, sec; | ||
102 | unsigned int yrs; | ||
103 | |||
104 | yrs = time->tm_year; | ||
105 | mon = time->tm_mon + 1; /* tm_mon starts at zero */ | ||
106 | day = time->tm_mday; | ||
107 | hrs = time->tm_hour; | ||
108 | min = time->tm_min; | ||
109 | sec = time->tm_sec; | ||
110 | |||
111 | if (yrs < 70 || yrs > 138) | ||
112 | return -EINVAL; | ||
113 | yrs -= 60; | ||
114 | |||
115 | spin_lock_irqsave(&rtc_lock, flags); | ||
116 | |||
117 | vrtc_cmos_write(yrs, RTC_YEAR); | ||
118 | vrtc_cmos_write(mon, RTC_MONTH); | ||
119 | vrtc_cmos_write(day, RTC_DAY_OF_MONTH); | ||
120 | vrtc_cmos_write(hrs, RTC_HOURS); | ||
121 | vrtc_cmos_write(min, RTC_MINUTES); | ||
122 | vrtc_cmos_write(sec, RTC_SECONDS); | ||
123 | |||
124 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
125 | |||
126 | ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETTIME); | ||
127 | return ret; | ||
128 | } | ||
129 | |||
130 | static int mrst_read_alarm(struct device *dev, struct rtc_wkalrm *t) | ||
131 | { | ||
132 | struct mrst_rtc *mrst = dev_get_drvdata(dev); | ||
133 | unsigned char rtc_control; | ||
134 | |||
135 | if (mrst->irq <= 0) | ||
136 | return -EIO; | ||
137 | |||
138 | /* Basic alarms only support hour, minute, and seconds fields. | ||
139 | * Some also support day and month, for alarms up to a year in | ||
140 | * the future. | ||
141 | */ | ||
142 | t->time.tm_mday = -1; | ||
143 | t->time.tm_mon = -1; | ||
144 | t->time.tm_year = -1; | ||
145 | |||
146 | /* vRTC only supports binary mode */ | ||
147 | spin_lock_irq(&rtc_lock); | ||
148 | t->time.tm_sec = vrtc_cmos_read(RTC_SECONDS_ALARM); | ||
149 | t->time.tm_min = vrtc_cmos_read(RTC_MINUTES_ALARM); | ||
150 | t->time.tm_hour = vrtc_cmos_read(RTC_HOURS_ALARM); | ||
151 | |||
152 | rtc_control = vrtc_cmos_read(RTC_CONTROL); | ||
153 | spin_unlock_irq(&rtc_lock); | ||
154 | |||
155 | t->enabled = !!(rtc_control & RTC_AIE); | ||
156 | t->pending = 0; | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static void mrst_checkintr(struct mrst_rtc *mrst, unsigned char rtc_control) | ||
162 | { | ||
163 | unsigned char rtc_intr; | ||
164 | |||
165 | /* | ||
166 | * NOTE after changing RTC_xIE bits we always read INTR_FLAGS; | ||
167 | * allegedly some older rtcs need that to handle irqs properly | ||
168 | */ | ||
169 | rtc_intr = vrtc_cmos_read(RTC_INTR_FLAGS); | ||
170 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | ||
171 | if (is_intr(rtc_intr)) | ||
172 | rtc_update_irq(mrst->rtc, 1, rtc_intr); | ||
173 | } | ||
174 | |||
175 | static void mrst_irq_enable(struct mrst_rtc *mrst, unsigned char mask) | ||
176 | { | ||
177 | unsigned char rtc_control; | ||
178 | |||
179 | /* | ||
180 | * Flush any pending IRQ status, notably for update irqs, | ||
181 | * before we enable new IRQs | ||
182 | */ | ||
183 | rtc_control = vrtc_cmos_read(RTC_CONTROL); | ||
184 | mrst_checkintr(mrst, rtc_control); | ||
185 | |||
186 | rtc_control |= mask; | ||
187 | vrtc_cmos_write(rtc_control, RTC_CONTROL); | ||
188 | |||
189 | mrst_checkintr(mrst, rtc_control); | ||
190 | } | ||
191 | |||
192 | static void mrst_irq_disable(struct mrst_rtc *mrst, unsigned char mask) | ||
193 | { | ||
194 | unsigned char rtc_control; | ||
195 | |||
196 | rtc_control = vrtc_cmos_read(RTC_CONTROL); | ||
197 | rtc_control &= ~mask; | ||
198 | vrtc_cmos_write(rtc_control, RTC_CONTROL); | ||
199 | mrst_checkintr(mrst, rtc_control); | ||
200 | } | ||
201 | |||
202 | static int mrst_set_alarm(struct device *dev, struct rtc_wkalrm *t) | ||
203 | { | ||
204 | struct mrst_rtc *mrst = dev_get_drvdata(dev); | ||
205 | unsigned char hrs, min, sec; | ||
206 | int ret = 0; | ||
207 | |||
208 | if (!mrst->irq) | ||
209 | return -EIO; | ||
210 | |||
211 | hrs = t->time.tm_hour; | ||
212 | min = t->time.tm_min; | ||
213 | sec = t->time.tm_sec; | ||
214 | |||
215 | spin_lock_irq(&rtc_lock); | ||
216 | /* Next rtc irq must not be from previous alarm setting */ | ||
217 | mrst_irq_disable(mrst, RTC_AIE); | ||
218 | |||
219 | /* Update alarm */ | ||
220 | vrtc_cmos_write(hrs, RTC_HOURS_ALARM); | ||
221 | vrtc_cmos_write(min, RTC_MINUTES_ALARM); | ||
222 | vrtc_cmos_write(sec, RTC_SECONDS_ALARM); | ||
223 | |||
224 | spin_unlock_irq(&rtc_lock); | ||
225 | |||
226 | ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETALARM); | ||
227 | if (ret) | ||
228 | return ret; | ||
229 | |||
230 | spin_lock_irq(&rtc_lock); | ||
231 | if (t->enabled) | ||
232 | mrst_irq_enable(mrst, RTC_AIE); | ||
233 | |||
234 | spin_unlock_irq(&rtc_lock); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static int mrst_irq_set_state(struct device *dev, int enabled) | ||
240 | { | ||
241 | struct mrst_rtc *mrst = dev_get_drvdata(dev); | ||
242 | unsigned long flags; | ||
243 | |||
244 | if (!mrst->irq) | ||
245 | return -ENXIO; | ||
246 | |||
247 | spin_lock_irqsave(&rtc_lock, flags); | ||
248 | |||
249 | if (enabled) | ||
250 | mrst_irq_enable(mrst, RTC_PIE); | ||
251 | else | ||
252 | mrst_irq_disable(mrst, RTC_PIE); | ||
253 | |||
254 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | #if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE) | ||
259 | |||
260 | /* Currently, the vRTC doesn't support UIE ON/OFF */ | ||
261 | static int | ||
262 | mrst_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
263 | { | ||
264 | struct mrst_rtc *mrst = dev_get_drvdata(dev); | ||
265 | unsigned long flags; | ||
266 | |||
267 | switch (cmd) { | ||
268 | case RTC_AIE_OFF: | ||
269 | case RTC_AIE_ON: | ||
270 | if (!mrst->irq) | ||
271 | return -EINVAL; | ||
272 | break; | ||
273 | default: | ||
274 | /* PIE ON/OFF is handled by mrst_irq_set_state() */ | ||
275 | return -ENOIOCTLCMD; | ||
276 | } | ||
277 | |||
278 | spin_lock_irqsave(&rtc_lock, flags); | ||
279 | switch (cmd) { | ||
280 | case RTC_AIE_OFF: /* alarm off */ | ||
281 | mrst_irq_disable(mrst, RTC_AIE); | ||
282 | break; | ||
283 | case RTC_AIE_ON: /* alarm on */ | ||
284 | mrst_irq_enable(mrst, RTC_AIE); | ||
285 | break; | ||
286 | } | ||
287 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | #else | ||
292 | #define mrst_rtc_ioctl NULL | ||
293 | #endif | ||
294 | |||
295 | #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) | ||
296 | |||
297 | static int mrst_procfs(struct device *dev, struct seq_file *seq) | ||
298 | { | ||
299 | unsigned char rtc_control, valid; | ||
300 | |||
301 | spin_lock_irq(&rtc_lock); | ||
302 | rtc_control = vrtc_cmos_read(RTC_CONTROL); | ||
303 | valid = vrtc_cmos_read(RTC_VALID); | ||
304 | spin_unlock_irq(&rtc_lock); | ||
305 | |||
306 | return seq_printf(seq, | ||
307 | "periodic_IRQ\t: %s\n" | ||
308 | "alarm\t\t: %s\n" | ||
309 | "BCD\t\t: no\n" | ||
310 | "periodic_freq\t: daily (not adjustable)\n", | ||
311 | (rtc_control & RTC_PIE) ? "on" : "off", | ||
312 | (rtc_control & RTC_AIE) ? "on" : "off"); | ||
313 | } | ||
314 | |||
315 | #else | ||
316 | #define mrst_procfs NULL | ||
317 | #endif | ||
318 | |||
319 | static const struct rtc_class_ops mrst_rtc_ops = { | ||
320 | .ioctl = mrst_rtc_ioctl, | ||
321 | .read_time = mrst_read_time, | ||
322 | .set_time = mrst_set_time, | ||
323 | .read_alarm = mrst_read_alarm, | ||
324 | .set_alarm = mrst_set_alarm, | ||
325 | .proc = mrst_procfs, | ||
326 | .irq_set_state = mrst_irq_set_state, | ||
327 | }; | ||
328 | |||
329 | static struct mrst_rtc mrst_rtc; | ||
330 | |||
331 | /* | ||
332 | * When vRTC IRQ is captured by SCU FW, FW will clear the AIE bit in | ||
333 | * Reg B, so no need for this driver to clear it | ||
334 | */ | ||
335 | static irqreturn_t mrst_rtc_irq(int irq, void *p) | ||
336 | { | ||
337 | u8 irqstat; | ||
338 | |||
339 | spin_lock(&rtc_lock); | ||
340 | /* This read will clear all IRQ flags inside Reg C */ | ||
341 | irqstat = vrtc_cmos_read(RTC_INTR_FLAGS); | ||
342 | spin_unlock(&rtc_lock); | ||
343 | |||
344 | irqstat &= RTC_IRQMASK | RTC_IRQF; | ||
345 | if (is_intr(irqstat)) { | ||
346 | rtc_update_irq(p, 1, irqstat); | ||
347 | return IRQ_HANDLED; | ||
348 | } | ||
349 | return IRQ_NONE; | ||
350 | } | ||
351 | |||
352 | static int __init | ||
353 | vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) | ||
354 | { | ||
355 | int retval = 0; | ||
356 | unsigned char rtc_control; | ||
357 | |||
358 | /* There can be only one ... */ | ||
359 | if (mrst_rtc.dev) | ||
360 | return -EBUSY; | ||
361 | |||
362 | if (!iomem) | ||
363 | return -ENODEV; | ||
364 | |||
365 | iomem = request_mem_region(iomem->start, | ||
366 | iomem->end + 1 - iomem->start, | ||
367 | driver_name); | ||
368 | if (!iomem) { | ||
369 | dev_dbg(dev, "i/o mem already in use.\n"); | ||
370 | return -EBUSY; | ||
371 | } | ||
372 | |||
373 | mrst_rtc.irq = rtc_irq; | ||
374 | mrst_rtc.iomem = iomem; | ||
375 | |||
376 | mrst_rtc.rtc = rtc_device_register(driver_name, dev, | ||
377 | &mrst_rtc_ops, THIS_MODULE); | ||
378 | if (IS_ERR(mrst_rtc.rtc)) { | ||
379 | retval = PTR_ERR(mrst_rtc.rtc); | ||
380 | goto cleanup0; | ||
381 | } | ||
382 | |||
383 | mrst_rtc.dev = dev; | ||
384 | dev_set_drvdata(dev, &mrst_rtc); | ||
385 | rename_region(iomem, dev_name(&mrst_rtc.rtc->dev)); | ||
386 | |||
387 | spin_lock_irq(&rtc_lock); | ||
388 | mrst_irq_disable(&mrst_rtc, RTC_PIE | RTC_AIE); | ||
389 | rtc_control = vrtc_cmos_read(RTC_CONTROL); | ||
390 | spin_unlock_irq(&rtc_lock); | ||
391 | |||
392 | if (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY))) | ||
393 | dev_dbg(dev, "TODO: support more than 24-hr BCD mode\n"); | ||
394 | |||
395 | if (rtc_irq) { | ||
396 | retval = request_irq(rtc_irq, mrst_rtc_irq, | ||
397 | IRQF_DISABLED, dev_name(&mrst_rtc.rtc->dev), | ||
398 | mrst_rtc.rtc); | ||
399 | if (retval < 0) { | ||
400 | dev_dbg(dev, "IRQ %d is already in use, err %d\n", | ||
401 | rtc_irq, retval); | ||
402 | goto cleanup1; | ||
403 | } | ||
404 | } | ||
405 | dev_dbg(dev, "initialised\n"); | ||
406 | return 0; | ||
407 | |||
408 | cleanup1: | ||
409 | mrst_rtc.dev = NULL; | ||
410 | rtc_device_unregister(mrst_rtc.rtc); | ||
411 | cleanup0: | ||
412 | release_region(iomem->start, iomem->end + 1 - iomem->start); | ||
413 | dev_err(dev, "rtc-mrst: unable to initialise\n"); | ||
414 | return retval; | ||
415 | } | ||
416 | |||
417 | static void rtc_mrst_do_shutdown(void) | ||
418 | { | ||
419 | spin_lock_irq(&rtc_lock); | ||
420 | mrst_irq_disable(&mrst_rtc, RTC_IRQMASK); | ||
421 | spin_unlock_irq(&rtc_lock); | ||
422 | } | ||
423 | |||
424 | static void __exit rtc_mrst_do_remove(struct device *dev) | ||
425 | { | ||
426 | struct mrst_rtc *mrst = dev_get_drvdata(dev); | ||
427 | struct resource *iomem; | ||
428 | |||
429 | rtc_mrst_do_shutdown(); | ||
430 | |||
431 | if (mrst->irq) | ||
432 | free_irq(mrst->irq, mrst->rtc); | ||
433 | |||
434 | rtc_device_unregister(mrst->rtc); | ||
435 | mrst->rtc = NULL; | ||
436 | |||
437 | iomem = mrst->iomem; | ||
438 | release_region(iomem->start, iomem->end + 1 - iomem->start); | ||
439 | mrst->iomem = NULL; | ||
440 | |||
441 | mrst->dev = NULL; | ||
442 | dev_set_drvdata(dev, NULL); | ||
443 | } | ||
444 | |||
445 | #ifdef CONFIG_PM | ||
446 | static int mrst_suspend(struct device *dev, pm_message_t mesg) | ||
447 | { | ||
448 | struct mrst_rtc *mrst = dev_get_drvdata(dev); | ||
449 | unsigned char tmp; | ||
450 | |||
451 | /* Only the alarm might be a wakeup event source */ | ||
452 | spin_lock_irq(&rtc_lock); | ||
453 | mrst->suspend_ctrl = tmp = vrtc_cmos_read(RTC_CONTROL); | ||
454 | if (tmp & (RTC_PIE | RTC_AIE)) { | ||
455 | unsigned char mask; | ||
456 | |||
457 | if (device_may_wakeup(dev)) | ||
458 | mask = RTC_IRQMASK & ~RTC_AIE; | ||
459 | else | ||
460 | mask = RTC_IRQMASK; | ||
461 | tmp &= ~mask; | ||
462 | vrtc_cmos_write(tmp, RTC_CONTROL); | ||
463 | |||
464 | mrst_checkintr(mrst, tmp); | ||
465 | } | ||
466 | spin_unlock_irq(&rtc_lock); | ||
467 | |||
468 | if (tmp & RTC_AIE) { | ||
469 | mrst->enabled_wake = 1; | ||
470 | enable_irq_wake(mrst->irq); | ||
471 | } | ||
472 | |||
473 | dev_dbg(&mrst_rtc.rtc->dev, "suspend%s, ctrl %02x\n", | ||
474 | (tmp & RTC_AIE) ? ", alarm may wake" : "", | ||
475 | tmp); | ||
476 | |||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | /* | ||
481 | * We want RTC alarms to wake us from the deep power saving state | ||
482 | */ | ||
483 | static inline int mrst_poweroff(struct device *dev) | ||
484 | { | ||
485 | return mrst_suspend(dev, PMSG_HIBERNATE); | ||
486 | } | ||
487 | |||
488 | static int mrst_resume(struct device *dev) | ||
489 | { | ||
490 | struct mrst_rtc *mrst = dev_get_drvdata(dev); | ||
491 | unsigned char tmp = mrst->suspend_ctrl; | ||
492 | |||
493 | /* Re-enable any irqs previously active */ | ||
494 | if (tmp & RTC_IRQMASK) { | ||
495 | unsigned char mask; | ||
496 | |||
497 | if (mrst->enabled_wake) { | ||
498 | disable_irq_wake(mrst->irq); | ||
499 | mrst->enabled_wake = 0; | ||
500 | } | ||
501 | |||
502 | spin_lock_irq(&rtc_lock); | ||
503 | do { | ||
504 | vrtc_cmos_write(tmp, RTC_CONTROL); | ||
505 | |||
506 | mask = vrtc_cmos_read(RTC_INTR_FLAGS); | ||
507 | mask &= (tmp & RTC_IRQMASK) | RTC_IRQF; | ||
508 | if (!is_intr(mask)) | ||
509 | break; | ||
510 | |||
511 | rtc_update_irq(mrst->rtc, 1, mask); | ||
512 | tmp &= ~RTC_AIE; | ||
513 | } while (mask & RTC_AIE); | ||
514 | spin_unlock_irq(&rtc_lock); | ||
515 | } | ||
516 | |||
517 | dev_dbg(&mrst_rtc.rtc->dev, "resume, ctrl %02x\n", tmp); | ||
518 | |||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | #else | ||
523 | #define mrst_suspend NULL | ||
524 | #define mrst_resume NULL | ||
525 | |||
526 | static inline int mrst_poweroff(struct device *dev) | ||
527 | { | ||
528 | return -ENOSYS; | ||
529 | } | ||
530 | |||
531 | #endif | ||
532 | |||
533 | static int __init vrtc_mrst_platform_probe(struct platform_device *pdev) | ||
534 | { | ||
535 | return vrtc_mrst_do_probe(&pdev->dev, | ||
536 | platform_get_resource(pdev, IORESOURCE_MEM, 0), | ||
537 | platform_get_irq(pdev, 0)); | ||
538 | } | ||
539 | |||
540 | static int __exit vrtc_mrst_platform_remove(struct platform_device *pdev) | ||
541 | { | ||
542 | rtc_mrst_do_remove(&pdev->dev); | ||
543 | return 0; | ||
544 | } | ||
545 | |||
546 | static void vrtc_mrst_platform_shutdown(struct platform_device *pdev) | ||
547 | { | ||
548 | if (system_state == SYSTEM_POWER_OFF && !mrst_poweroff(&pdev->dev)) | ||
549 | return; | ||
550 | |||
551 | rtc_mrst_do_shutdown(); | ||
552 | } | ||
553 | |||
554 | MODULE_ALIAS("platform:vrtc_mrst"); | ||
555 | |||
556 | static struct platform_driver vrtc_mrst_platform_driver = { | ||
557 | .probe = vrtc_mrst_platform_probe, | ||
558 | .remove = __exit_p(vrtc_mrst_platform_remove), | ||
559 | .shutdown = vrtc_mrst_platform_shutdown, | ||
560 | .driver = { | ||
561 | .name = (char *) driver_name, | ||
562 | .suspend = mrst_suspend, | ||
563 | .resume = mrst_resume, | ||
564 | } | ||
565 | }; | ||
566 | |||
567 | static int __init vrtc_mrst_init(void) | ||
568 | { | ||
569 | return platform_driver_register(&vrtc_mrst_platform_driver); | ||
570 | } | ||
571 | |||
572 | static void __exit vrtc_mrst_exit(void) | ||
573 | { | ||
574 | platform_driver_unregister(&vrtc_mrst_platform_driver); | ||
575 | } | ||
576 | |||
577 | module_init(vrtc_mrst_init); | ||
578 | module_exit(vrtc_mrst_exit); | ||
579 | |||
580 | MODULE_AUTHOR("Jacob Pan; Feng Tang"); | ||
581 | MODULE_DESCRIPTION("Driver for Moorestown virtual RTC"); | ||
582 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-msm6242.c b/drivers/rtc/rtc-msm6242.c new file mode 100644 index 000000000000..b2fff0ca49f8 --- /dev/null +++ b/drivers/rtc/rtc-msm6242.c | |||
@@ -0,0 +1,270 @@ | |||
1 | /* | ||
2 | * Oki MSM6242 RTC Driver | ||
3 | * | ||
4 | * Copyright 2009 Geert Uytterhoeven | ||
5 | * | ||
6 | * Based on the A2000 TOD code in arch/m68k/amiga/config.c | ||
7 | * Copyright (C) 1993 Hamish Macdonald | ||
8 | */ | ||
9 | |||
10 | #include <linux/delay.h> | ||
11 | #include <linux/io.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/rtc.h> | ||
16 | #include <linux/slab.h> | ||
17 | |||
18 | |||
19 | enum { | ||
20 | MSM6242_SECOND1 = 0x0, /* 1-second digit register */ | ||
21 | MSM6242_SECOND10 = 0x1, /* 10-second digit register */ | ||
22 | MSM6242_MINUTE1 = 0x2, /* 1-minute digit register */ | ||
23 | MSM6242_MINUTE10 = 0x3, /* 10-minute digit register */ | ||
24 | MSM6242_HOUR1 = 0x4, /* 1-hour digit register */ | ||
25 | MSM6242_HOUR10 = 0x5, /* PM/AM, 10-hour digit register */ | ||
26 | MSM6242_DAY1 = 0x6, /* 1-day digit register */ | ||
27 | MSM6242_DAY10 = 0x7, /* 10-day digit register */ | ||
28 | MSM6242_MONTH1 = 0x8, /* 1-month digit register */ | ||
29 | MSM6242_MONTH10 = 0x9, /* 10-month digit register */ | ||
30 | MSM6242_YEAR1 = 0xa, /* 1-year digit register */ | ||
31 | MSM6242_YEAR10 = 0xb, /* 10-year digit register */ | ||
32 | MSM6242_WEEK = 0xc, /* Week register */ | ||
33 | MSM6242_CD = 0xd, /* Control Register D */ | ||
34 | MSM6242_CE = 0xe, /* Control Register E */ | ||
35 | MSM6242_CF = 0xf, /* Control Register F */ | ||
36 | }; | ||
37 | |||
38 | #define MSM6242_HOUR10_AM (0 << 2) | ||
39 | #define MSM6242_HOUR10_PM (1 << 2) | ||
40 | #define MSM6242_HOUR10_HR_MASK (3 << 0) | ||
41 | |||
42 | #define MSM6242_WEEK_SUNDAY 0 | ||
43 | #define MSM6242_WEEK_MONDAY 1 | ||
44 | #define MSM6242_WEEK_TUESDAY 2 | ||
45 | #define MSM6242_WEEK_WEDNESDAY 3 | ||
46 | #define MSM6242_WEEK_THURSDAY 4 | ||
47 | #define MSM6242_WEEK_FRIDAY 5 | ||
48 | #define MSM6242_WEEK_SATURDAY 6 | ||
49 | |||
50 | #define MSM6242_CD_30_S_ADJ (1 << 3) /* 30-second adjustment */ | ||
51 | #define MSM6242_CD_IRQ_FLAG (1 << 2) | ||
52 | #define MSM6242_CD_BUSY (1 << 1) | ||
53 | #define MSM6242_CD_HOLD (1 << 0) | ||
54 | |||
55 | #define MSM6242_CE_T_MASK (3 << 2) | ||
56 | #define MSM6242_CE_T_64HZ (0 << 2) /* period 1/64 second */ | ||
57 | #define MSM6242_CE_T_1HZ (1 << 2) /* period 1 second */ | ||
58 | #define MSM6242_CE_T_1MINUTE (2 << 2) /* period 1 minute */ | ||
59 | #define MSM6242_CE_T_1HOUR (3 << 2) /* period 1 hour */ | ||
60 | |||
61 | #define MSM6242_CE_ITRPT_STND (1 << 1) | ||
62 | #define MSM6242_CE_MASK (1 << 0) /* STD.P output control */ | ||
63 | |||
64 | #define MSM6242_CF_TEST (1 << 3) | ||
65 | #define MSM6242_CF_12H (0 << 2) | ||
66 | #define MSM6242_CF_24H (1 << 2) | ||
67 | #define MSM6242_CF_STOP (1 << 1) | ||
68 | #define MSM6242_CF_REST (1 << 0) /* reset */ | ||
69 | |||
70 | |||
71 | struct msm6242_priv { | ||
72 | u32 __iomem *regs; | ||
73 | struct rtc_device *rtc; | ||
74 | }; | ||
75 | |||
76 | static inline unsigned int msm6242_read(struct msm6242_priv *priv, | ||
77 | unsigned int reg) | ||
78 | { | ||
79 | return __raw_readl(&priv->regs[reg]) & 0xf; | ||
80 | } | ||
81 | |||
82 | static inline void msm6242_write(struct msm6242_priv *priv, unsigned int val, | ||
83 | unsigned int reg) | ||
84 | { | ||
85 | return __raw_writel(val, &priv->regs[reg]); | ||
86 | } | ||
87 | |||
88 | static inline void msm6242_set(struct msm6242_priv *priv, unsigned int val, | ||
89 | unsigned int reg) | ||
90 | { | ||
91 | msm6242_write(priv, msm6242_read(priv, reg) | val, reg); | ||
92 | } | ||
93 | |||
94 | static inline void msm6242_clear(struct msm6242_priv *priv, unsigned int val, | ||
95 | unsigned int reg) | ||
96 | { | ||
97 | msm6242_write(priv, msm6242_read(priv, reg) & ~val, reg); | ||
98 | } | ||
99 | |||
100 | static void msm6242_lock(struct msm6242_priv *priv) | ||
101 | { | ||
102 | int cnt = 5; | ||
103 | |||
104 | msm6242_set(priv, MSM6242_CD_HOLD, MSM6242_CD); | ||
105 | |||
106 | while ((msm6242_read(priv, MSM6242_CD) & MSM6242_CD_BUSY) && cnt) { | ||
107 | msm6242_clear(priv, MSM6242_CD_HOLD, MSM6242_CD); | ||
108 | udelay(70); | ||
109 | msm6242_set(priv, MSM6242_CD_HOLD, MSM6242_CD); | ||
110 | cnt--; | ||
111 | } | ||
112 | |||
113 | if (!cnt) | ||
114 | pr_warning("msm6242: timed out waiting for RTC (0x%x)\n", | ||
115 | msm6242_read(priv, MSM6242_CD)); | ||
116 | } | ||
117 | |||
118 | static void msm6242_unlock(struct msm6242_priv *priv) | ||
119 | { | ||
120 | msm6242_clear(priv, MSM6242_CD_HOLD, MSM6242_CD); | ||
121 | } | ||
122 | |||
123 | static int msm6242_read_time(struct device *dev, struct rtc_time *tm) | ||
124 | { | ||
125 | struct msm6242_priv *priv = dev_get_drvdata(dev); | ||
126 | |||
127 | msm6242_lock(priv); | ||
128 | |||
129 | tm->tm_sec = msm6242_read(priv, MSM6242_SECOND10) * 10 + | ||
130 | msm6242_read(priv, MSM6242_SECOND1); | ||
131 | tm->tm_min = msm6242_read(priv, MSM6242_MINUTE10) * 10 + | ||
132 | msm6242_read(priv, MSM6242_MINUTE1); | ||
133 | tm->tm_hour = (msm6242_read(priv, MSM6242_HOUR10 & 3)) * 10 + | ||
134 | msm6242_read(priv, MSM6242_HOUR1); | ||
135 | tm->tm_mday = msm6242_read(priv, MSM6242_DAY10) * 10 + | ||
136 | msm6242_read(priv, MSM6242_DAY1); | ||
137 | tm->tm_wday = msm6242_read(priv, MSM6242_WEEK); | ||
138 | tm->tm_mon = msm6242_read(priv, MSM6242_MONTH10) * 10 + | ||
139 | msm6242_read(priv, MSM6242_MONTH1) - 1; | ||
140 | tm->tm_year = msm6242_read(priv, MSM6242_YEAR10) * 10 + | ||
141 | msm6242_read(priv, MSM6242_YEAR1); | ||
142 | if (tm->tm_year <= 69) | ||
143 | tm->tm_year += 100; | ||
144 | |||
145 | if (!(msm6242_read(priv, MSM6242_CF) & MSM6242_CF_24H)) { | ||
146 | unsigned int pm = msm6242_read(priv, MSM6242_HOUR10) & | ||
147 | MSM6242_HOUR10_PM; | ||
148 | if (!pm && tm->tm_hour == 12) | ||
149 | tm->tm_hour = 0; | ||
150 | else if (pm && tm->tm_hour != 12) | ||
151 | tm->tm_hour += 12; | ||
152 | } | ||
153 | |||
154 | msm6242_unlock(priv); | ||
155 | |||
156 | return rtc_valid_tm(tm); | ||
157 | } | ||
158 | |||
159 | static int msm6242_set_time(struct device *dev, struct rtc_time *tm) | ||
160 | { | ||
161 | struct msm6242_priv *priv = dev_get_drvdata(dev); | ||
162 | |||
163 | msm6242_lock(priv); | ||
164 | |||
165 | msm6242_write(priv, tm->tm_sec / 10, MSM6242_SECOND10); | ||
166 | msm6242_write(priv, tm->tm_sec % 10, MSM6242_SECOND1); | ||
167 | msm6242_write(priv, tm->tm_min / 10, MSM6242_MINUTE10); | ||
168 | msm6242_write(priv, tm->tm_min % 10, MSM6242_MINUTE1); | ||
169 | if (msm6242_read(priv, MSM6242_CF) & MSM6242_CF_24H) | ||
170 | msm6242_write(priv, tm->tm_hour / 10, MSM6242_HOUR10); | ||
171 | else if (tm->tm_hour >= 12) | ||
172 | msm6242_write(priv, MSM6242_HOUR10_PM + (tm->tm_hour - 12) / 10, | ||
173 | MSM6242_HOUR10); | ||
174 | else | ||
175 | msm6242_write(priv, tm->tm_hour / 10, MSM6242_HOUR10); | ||
176 | msm6242_write(priv, tm->tm_hour % 10, MSM6242_HOUR1); | ||
177 | msm6242_write(priv, tm->tm_mday / 10, MSM6242_DAY10); | ||
178 | msm6242_write(priv, tm->tm_mday % 10, MSM6242_DAY1); | ||
179 | if (tm->tm_wday != -1) | ||
180 | msm6242_write(priv, tm->tm_wday, MSM6242_WEEK); | ||
181 | msm6242_write(priv, (tm->tm_mon + 1) / 10, MSM6242_MONTH10); | ||
182 | msm6242_write(priv, (tm->tm_mon + 1) % 10, MSM6242_MONTH1); | ||
183 | if (tm->tm_year >= 100) | ||
184 | tm->tm_year -= 100; | ||
185 | msm6242_write(priv, tm->tm_year / 10, MSM6242_YEAR10); | ||
186 | msm6242_write(priv, tm->tm_year % 10, MSM6242_YEAR1); | ||
187 | |||
188 | msm6242_unlock(priv); | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static const struct rtc_class_ops msm6242_rtc_ops = { | ||
193 | .read_time = msm6242_read_time, | ||
194 | .set_time = msm6242_set_time, | ||
195 | }; | ||
196 | |||
197 | static int __init msm6242_rtc_probe(struct platform_device *dev) | ||
198 | { | ||
199 | struct resource *res; | ||
200 | struct msm6242_priv *priv; | ||
201 | struct rtc_device *rtc; | ||
202 | int error; | ||
203 | |||
204 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
205 | if (!res) | ||
206 | return -ENODEV; | ||
207 | |||
208 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
209 | if (!priv) | ||
210 | return -ENOMEM; | ||
211 | |||
212 | priv->regs = ioremap(res->start, resource_size(res)); | ||
213 | if (!priv->regs) { | ||
214 | error = -ENOMEM; | ||
215 | goto out_free_priv; | ||
216 | } | ||
217 | |||
218 | rtc = rtc_device_register("rtc-msm6242", &dev->dev, &msm6242_rtc_ops, | ||
219 | THIS_MODULE); | ||
220 | if (IS_ERR(rtc)) { | ||
221 | error = PTR_ERR(rtc); | ||
222 | goto out_unmap; | ||
223 | } | ||
224 | |||
225 | priv->rtc = rtc; | ||
226 | platform_set_drvdata(dev, priv); | ||
227 | return 0; | ||
228 | |||
229 | out_unmap: | ||
230 | iounmap(priv->regs); | ||
231 | out_free_priv: | ||
232 | kfree(priv); | ||
233 | return error; | ||
234 | } | ||
235 | |||
236 | static int __exit msm6242_rtc_remove(struct platform_device *dev) | ||
237 | { | ||
238 | struct msm6242_priv *priv = platform_get_drvdata(dev); | ||
239 | |||
240 | rtc_device_unregister(priv->rtc); | ||
241 | iounmap(priv->regs); | ||
242 | kfree(priv); | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static struct platform_driver msm6242_rtc_driver = { | ||
247 | .driver = { | ||
248 | .name = "rtc-msm6242", | ||
249 | .owner = THIS_MODULE, | ||
250 | }, | ||
251 | .remove = __exit_p(msm6242_rtc_remove), | ||
252 | }; | ||
253 | |||
254 | static int __init msm6242_rtc_init(void) | ||
255 | { | ||
256 | return platform_driver_probe(&msm6242_rtc_driver, msm6242_rtc_probe); | ||
257 | } | ||
258 | |||
259 | static void __exit msm6242_rtc_fini(void) | ||
260 | { | ||
261 | platform_driver_unregister(&msm6242_rtc_driver); | ||
262 | } | ||
263 | |||
264 | module_init(msm6242_rtc_init); | ||
265 | module_exit(msm6242_rtc_fini); | ||
266 | |||
267 | MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>"); | ||
268 | MODULE_LICENSE("GPL"); | ||
269 | MODULE_DESCRIPTION("Oki MSM6242 RTC driver"); | ||
270 | MODULE_ALIAS("platform:rtc-msm6242"); | ||
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index e0263d2005ee..bcca47298554 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/io.h> | 13 | #include <linux/io.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <linux/gfp.h> | ||
16 | 17 | ||
17 | 18 | ||
18 | #define RTC_TIME_REG_OFFS 0 | 19 | #define RTC_TIME_REG_OFFS 0 |
@@ -27,10 +28,17 @@ | |||
27 | #define RTC_MONTH_OFFS 8 | 28 | #define RTC_MONTH_OFFS 8 |
28 | #define RTC_YEAR_OFFS 16 | 29 | #define RTC_YEAR_OFFS 16 |
29 | 30 | ||
31 | #define RTC_ALARM_TIME_REG_OFFS 8 | ||
32 | #define RTC_ALARM_DATE_REG_OFFS 0xc | ||
33 | #define RTC_ALARM_VALID (1 << 7) | ||
34 | |||
35 | #define RTC_ALARM_INTERRUPT_MASK_REG_OFFS 0x10 | ||
36 | #define RTC_ALARM_INTERRUPT_CASUE_REG_OFFS 0x14 | ||
30 | 37 | ||
31 | struct rtc_plat_data { | 38 | struct rtc_plat_data { |
32 | struct rtc_device *rtc; | 39 | struct rtc_device *rtc; |
33 | void __iomem *ioaddr; | 40 | void __iomem *ioaddr; |
41 | int irq; | ||
34 | }; | 42 | }; |
35 | 43 | ||
36 | static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm) | 44 | static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm) |
@@ -84,12 +92,134 @@ static int mv_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
84 | return rtc_valid_tm(tm); | 92 | return rtc_valid_tm(tm); |
85 | } | 93 | } |
86 | 94 | ||
95 | static int mv_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
96 | { | ||
97 | struct rtc_plat_data *pdata = dev_get_drvdata(dev); | ||
98 | void __iomem *ioaddr = pdata->ioaddr; | ||
99 | u32 rtc_time, rtc_date; | ||
100 | unsigned int year, month, day, hour, minute, second, wday; | ||
101 | |||
102 | rtc_time = readl(ioaddr + RTC_ALARM_TIME_REG_OFFS); | ||
103 | rtc_date = readl(ioaddr + RTC_ALARM_DATE_REG_OFFS); | ||
104 | |||
105 | second = rtc_time & 0x7f; | ||
106 | minute = (rtc_time >> RTC_MINUTES_OFFS) & 0x7f; | ||
107 | hour = (rtc_time >> RTC_HOURS_OFFS) & 0x3f; /* assume 24 hours mode */ | ||
108 | wday = (rtc_time >> RTC_WDAY_OFFS) & 0x7; | ||
109 | |||
110 | day = rtc_date & 0x3f; | ||
111 | month = (rtc_date >> RTC_MONTH_OFFS) & 0x3f; | ||
112 | year = (rtc_date >> RTC_YEAR_OFFS) & 0xff; | ||
113 | |||
114 | alm->time.tm_sec = bcd2bin(second); | ||
115 | alm->time.tm_min = bcd2bin(minute); | ||
116 | alm->time.tm_hour = bcd2bin(hour); | ||
117 | alm->time.tm_mday = bcd2bin(day); | ||
118 | alm->time.tm_wday = bcd2bin(wday); | ||
119 | alm->time.tm_mon = bcd2bin(month) - 1; | ||
120 | /* hw counts from year 2000, but tm_year is relative to 1900 */ | ||
121 | alm->time.tm_year = bcd2bin(year) + 100; | ||
122 | |||
123 | if (rtc_valid_tm(&alm->time) < 0) { | ||
124 | dev_err(dev, "retrieved alarm date/time is not valid.\n"); | ||
125 | rtc_time_to_tm(0, &alm->time); | ||
126 | } | ||
127 | |||
128 | alm->enabled = !!readl(ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int mv_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
133 | { | ||
134 | struct rtc_plat_data *pdata = dev_get_drvdata(dev); | ||
135 | void __iomem *ioaddr = pdata->ioaddr; | ||
136 | u32 rtc_reg = 0; | ||
137 | |||
138 | if (alm->time.tm_sec >= 0) | ||
139 | rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_sec)) | ||
140 | << RTC_SECONDS_OFFS; | ||
141 | if (alm->time.tm_min >= 0) | ||
142 | rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_min)) | ||
143 | << RTC_MINUTES_OFFS; | ||
144 | if (alm->time.tm_hour >= 0) | ||
145 | rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_hour)) | ||
146 | << RTC_HOURS_OFFS; | ||
147 | |||
148 | writel(rtc_reg, ioaddr + RTC_ALARM_TIME_REG_OFFS); | ||
149 | |||
150 | if (alm->time.tm_mday >= 0) | ||
151 | rtc_reg = (RTC_ALARM_VALID | bin2bcd(alm->time.tm_mday)) | ||
152 | << RTC_MDAY_OFFS; | ||
153 | else | ||
154 | rtc_reg = 0; | ||
155 | |||
156 | if (alm->time.tm_mon >= 0) | ||
157 | rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_mon + 1)) | ||
158 | << RTC_MONTH_OFFS; | ||
159 | |||
160 | if (alm->time.tm_year >= 0) | ||
161 | rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_year % 100)) | ||
162 | << RTC_YEAR_OFFS; | ||
163 | |||
164 | writel(rtc_reg, ioaddr + RTC_ALARM_DATE_REG_OFFS); | ||
165 | writel(0, ioaddr + RTC_ALARM_INTERRUPT_CASUE_REG_OFFS); | ||
166 | writel(alm->enabled ? 1 : 0, | ||
167 | ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static int mv_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
173 | unsigned long arg) | ||
174 | { | ||
175 | struct platform_device *pdev = to_platform_device(dev); | ||
176 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
177 | void __iomem *ioaddr = pdata->ioaddr; | ||
178 | |||
179 | if (pdata->irq < 0) | ||
180 | return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ | ||
181 | switch (cmd) { | ||
182 | case RTC_AIE_OFF: | ||
183 | writel(0, ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | ||
184 | break; | ||
185 | case RTC_AIE_ON: | ||
186 | writel(1, ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | ||
187 | break; | ||
188 | default: | ||
189 | return -ENOIOCTLCMD; | ||
190 | } | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static irqreturn_t mv_rtc_interrupt(int irq, void *data) | ||
195 | { | ||
196 | struct rtc_plat_data *pdata = data; | ||
197 | void __iomem *ioaddr = pdata->ioaddr; | ||
198 | |||
199 | /* alarm irq? */ | ||
200 | if (!readl(ioaddr + RTC_ALARM_INTERRUPT_CASUE_REG_OFFS)) | ||
201 | return IRQ_NONE; | ||
202 | |||
203 | /* clear interrupt */ | ||
204 | writel(0, ioaddr + RTC_ALARM_INTERRUPT_CASUE_REG_OFFS); | ||
205 | rtc_update_irq(pdata->rtc, 1, RTC_IRQF | RTC_AF); | ||
206 | return IRQ_HANDLED; | ||
207 | } | ||
208 | |||
87 | static const struct rtc_class_ops mv_rtc_ops = { | 209 | static const struct rtc_class_ops mv_rtc_ops = { |
88 | .read_time = mv_rtc_read_time, | 210 | .read_time = mv_rtc_read_time, |
89 | .set_time = mv_rtc_set_time, | 211 | .set_time = mv_rtc_set_time, |
90 | }; | 212 | }; |
91 | 213 | ||
92 | static int __init mv_rtc_probe(struct platform_device *pdev) | 214 | static const struct rtc_class_ops mv_rtc_alarm_ops = { |
215 | .read_time = mv_rtc_read_time, | ||
216 | .set_time = mv_rtc_set_time, | ||
217 | .read_alarm = mv_rtc_read_alarm, | ||
218 | .set_alarm = mv_rtc_set_alarm, | ||
219 | .ioctl = mv_rtc_ioctl, | ||
220 | }; | ||
221 | |||
222 | static int __devinit mv_rtc_probe(struct platform_device *pdev) | ||
93 | { | 223 | { |
94 | struct resource *res; | 224 | struct resource *res; |
95 | struct rtc_plat_data *pdata; | 225 | struct rtc_plat_data *pdata; |
@@ -130,12 +260,31 @@ static int __init mv_rtc_probe(struct platform_device *pdev) | |||
130 | } | 260 | } |
131 | } | 261 | } |
132 | 262 | ||
263 | pdata->irq = platform_get_irq(pdev, 0); | ||
264 | |||
133 | platform_set_drvdata(pdev, pdata); | 265 | platform_set_drvdata(pdev, pdata); |
134 | pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, | 266 | |
135 | &mv_rtc_ops, THIS_MODULE); | 267 | if (pdata->irq >= 0) { |
268 | device_init_wakeup(&pdev->dev, 1); | ||
269 | pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
270 | &mv_rtc_alarm_ops, | ||
271 | THIS_MODULE); | ||
272 | } else | ||
273 | pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
274 | &mv_rtc_ops, THIS_MODULE); | ||
136 | if (IS_ERR(pdata->rtc)) | 275 | if (IS_ERR(pdata->rtc)) |
137 | return PTR_ERR(pdata->rtc); | 276 | return PTR_ERR(pdata->rtc); |
138 | 277 | ||
278 | if (pdata->irq >= 0) { | ||
279 | writel(0, pdata->ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | ||
280 | if (devm_request_irq(&pdev->dev, pdata->irq, mv_rtc_interrupt, | ||
281 | IRQF_DISABLED | IRQF_SHARED, | ||
282 | pdev->name, pdata) < 0) { | ||
283 | dev_warn(&pdev->dev, "interrupt not available.\n"); | ||
284 | pdata->irq = -1; | ||
285 | } | ||
286 | } | ||
287 | |||
139 | return 0; | 288 | return 0; |
140 | } | 289 | } |
141 | 290 | ||
@@ -143,6 +292,9 @@ static int __exit mv_rtc_remove(struct platform_device *pdev) | |||
143 | { | 292 | { |
144 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 293 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
145 | 294 | ||
295 | if (pdata->irq >= 0) | ||
296 | device_init_wakeup(&pdev->dev, 0); | ||
297 | |||
146 | rtc_device_unregister(pdata->rtc); | 298 | rtc_device_unregister(pdata->rtc); |
147 | return 0; | 299 | return 0; |
148 | } | 300 | } |
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c new file mode 100644 index 000000000000..0b06c1e03fd5 --- /dev/null +++ b/drivers/rtc/rtc-mxc.c | |||
@@ -0,0 +1,496 @@ | |||
1 | /* | ||
2 | * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/io.h> | ||
13 | #include <linux/rtc.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/clk.h> | ||
19 | |||
20 | #include <mach/hardware.h> | ||
21 | |||
22 | #define RTC_INPUT_CLK_32768HZ (0x00 << 5) | ||
23 | #define RTC_INPUT_CLK_32000HZ (0x01 << 5) | ||
24 | #define RTC_INPUT_CLK_38400HZ (0x02 << 5) | ||
25 | |||
26 | #define RTC_SW_BIT (1 << 0) | ||
27 | #define RTC_ALM_BIT (1 << 2) | ||
28 | #define RTC_1HZ_BIT (1 << 4) | ||
29 | #define RTC_2HZ_BIT (1 << 7) | ||
30 | #define RTC_SAM0_BIT (1 << 8) | ||
31 | #define RTC_SAM1_BIT (1 << 9) | ||
32 | #define RTC_SAM2_BIT (1 << 10) | ||
33 | #define RTC_SAM3_BIT (1 << 11) | ||
34 | #define RTC_SAM4_BIT (1 << 12) | ||
35 | #define RTC_SAM5_BIT (1 << 13) | ||
36 | #define RTC_SAM6_BIT (1 << 14) | ||
37 | #define RTC_SAM7_BIT (1 << 15) | ||
38 | #define PIT_ALL_ON (RTC_2HZ_BIT | RTC_SAM0_BIT | RTC_SAM1_BIT | \ | ||
39 | RTC_SAM2_BIT | RTC_SAM3_BIT | RTC_SAM4_BIT | \ | ||
40 | RTC_SAM5_BIT | RTC_SAM6_BIT | RTC_SAM7_BIT) | ||
41 | |||
42 | #define RTC_ENABLE_BIT (1 << 7) | ||
43 | |||
44 | #define MAX_PIE_NUM 9 | ||
45 | #define MAX_PIE_FREQ 512 | ||
46 | static const u32 PIE_BIT_DEF[MAX_PIE_NUM][2] = { | ||
47 | { 2, RTC_2HZ_BIT }, | ||
48 | { 4, RTC_SAM0_BIT }, | ||
49 | { 8, RTC_SAM1_BIT }, | ||
50 | { 16, RTC_SAM2_BIT }, | ||
51 | { 32, RTC_SAM3_BIT }, | ||
52 | { 64, RTC_SAM4_BIT }, | ||
53 | { 128, RTC_SAM5_BIT }, | ||
54 | { 256, RTC_SAM6_BIT }, | ||
55 | { MAX_PIE_FREQ, RTC_SAM7_BIT }, | ||
56 | }; | ||
57 | |||
58 | /* Those are the bits from a classic RTC we want to mimic */ | ||
59 | #define RTC_IRQF 0x80 /* any of the following 3 is active */ | ||
60 | #define RTC_PF 0x40 /* Periodic interrupt */ | ||
61 | #define RTC_AF 0x20 /* Alarm interrupt */ | ||
62 | #define RTC_UF 0x10 /* Update interrupt for 1Hz RTC */ | ||
63 | |||
64 | #define MXC_RTC_TIME 0 | ||
65 | #define MXC_RTC_ALARM 1 | ||
66 | |||
67 | #define RTC_HOURMIN 0x00 /* 32bit rtc hour/min counter reg */ | ||
68 | #define RTC_SECOND 0x04 /* 32bit rtc seconds counter reg */ | ||
69 | #define RTC_ALRM_HM 0x08 /* 32bit rtc alarm hour/min reg */ | ||
70 | #define RTC_ALRM_SEC 0x0C /* 32bit rtc alarm seconds reg */ | ||
71 | #define RTC_RTCCTL 0x10 /* 32bit rtc control reg */ | ||
72 | #define RTC_RTCISR 0x14 /* 32bit rtc interrupt status reg */ | ||
73 | #define RTC_RTCIENR 0x18 /* 32bit rtc interrupt enable reg */ | ||
74 | #define RTC_STPWCH 0x1C /* 32bit rtc stopwatch min reg */ | ||
75 | #define RTC_DAYR 0x20 /* 32bit rtc days counter reg */ | ||
76 | #define RTC_DAYALARM 0x24 /* 32bit rtc day alarm reg */ | ||
77 | #define RTC_TEST1 0x28 /* 32bit rtc test reg 1 */ | ||
78 | #define RTC_TEST2 0x2C /* 32bit rtc test reg 2 */ | ||
79 | #define RTC_TEST3 0x30 /* 32bit rtc test reg 3 */ | ||
80 | |||
81 | struct rtc_plat_data { | ||
82 | struct rtc_device *rtc; | ||
83 | void __iomem *ioaddr; | ||
84 | int irq; | ||
85 | struct clk *clk; | ||
86 | struct rtc_time g_rtc_alarm; | ||
87 | }; | ||
88 | |||
89 | /* | ||
90 | * This function is used to obtain the RTC time or the alarm value in | ||
91 | * second. | ||
92 | */ | ||
93 | static u32 get_alarm_or_time(struct device *dev, int time_alarm) | ||
94 | { | ||
95 | struct platform_device *pdev = to_platform_device(dev); | ||
96 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
97 | void __iomem *ioaddr = pdata->ioaddr; | ||
98 | u32 day = 0, hr = 0, min = 0, sec = 0, hr_min = 0; | ||
99 | |||
100 | switch (time_alarm) { | ||
101 | case MXC_RTC_TIME: | ||
102 | day = readw(ioaddr + RTC_DAYR); | ||
103 | hr_min = readw(ioaddr + RTC_HOURMIN); | ||
104 | sec = readw(ioaddr + RTC_SECOND); | ||
105 | break; | ||
106 | case MXC_RTC_ALARM: | ||
107 | day = readw(ioaddr + RTC_DAYALARM); | ||
108 | hr_min = readw(ioaddr + RTC_ALRM_HM) & 0xffff; | ||
109 | sec = readw(ioaddr + RTC_ALRM_SEC); | ||
110 | break; | ||
111 | } | ||
112 | |||
113 | hr = hr_min >> 8; | ||
114 | min = hr_min & 0xff; | ||
115 | |||
116 | return (((day * 24 + hr) * 60) + min) * 60 + sec; | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * This function sets the RTC alarm value or the time value. | ||
121 | */ | ||
122 | static void set_alarm_or_time(struct device *dev, int time_alarm, u32 time) | ||
123 | { | ||
124 | u32 day, hr, min, sec, temp; | ||
125 | struct platform_device *pdev = to_platform_device(dev); | ||
126 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
127 | void __iomem *ioaddr = pdata->ioaddr; | ||
128 | |||
129 | day = time / 86400; | ||
130 | time -= day * 86400; | ||
131 | |||
132 | /* time is within a day now */ | ||
133 | hr = time / 3600; | ||
134 | time -= hr * 3600; | ||
135 | |||
136 | /* time is within an hour now */ | ||
137 | min = time / 60; | ||
138 | sec = time - min * 60; | ||
139 | |||
140 | temp = (hr << 8) + min; | ||
141 | |||
142 | switch (time_alarm) { | ||
143 | case MXC_RTC_TIME: | ||
144 | writew(day, ioaddr + RTC_DAYR); | ||
145 | writew(sec, ioaddr + RTC_SECOND); | ||
146 | writew(temp, ioaddr + RTC_HOURMIN); | ||
147 | break; | ||
148 | case MXC_RTC_ALARM: | ||
149 | writew(day, ioaddr + RTC_DAYALARM); | ||
150 | writew(sec, ioaddr + RTC_ALRM_SEC); | ||
151 | writew(temp, ioaddr + RTC_ALRM_HM); | ||
152 | break; | ||
153 | } | ||
154 | } | ||
155 | |||
156 | /* | ||
157 | * This function updates the RTC alarm registers and then clears all the | ||
158 | * interrupt status bits. | ||
159 | */ | ||
160 | static int rtc_update_alarm(struct device *dev, struct rtc_time *alrm) | ||
161 | { | ||
162 | struct rtc_time alarm_tm, now_tm; | ||
163 | unsigned long now, time; | ||
164 | int ret; | ||
165 | struct platform_device *pdev = to_platform_device(dev); | ||
166 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
167 | void __iomem *ioaddr = pdata->ioaddr; | ||
168 | |||
169 | now = get_alarm_or_time(dev, MXC_RTC_TIME); | ||
170 | rtc_time_to_tm(now, &now_tm); | ||
171 | alarm_tm.tm_year = now_tm.tm_year; | ||
172 | alarm_tm.tm_mon = now_tm.tm_mon; | ||
173 | alarm_tm.tm_mday = now_tm.tm_mday; | ||
174 | alarm_tm.tm_hour = alrm->tm_hour; | ||
175 | alarm_tm.tm_min = alrm->tm_min; | ||
176 | alarm_tm.tm_sec = alrm->tm_sec; | ||
177 | rtc_tm_to_time(&now_tm, &now); | ||
178 | rtc_tm_to_time(&alarm_tm, &time); | ||
179 | |||
180 | if (time < now) { | ||
181 | time += 60 * 60 * 24; | ||
182 | rtc_time_to_tm(time, &alarm_tm); | ||
183 | } | ||
184 | |||
185 | ret = rtc_tm_to_time(&alarm_tm, &time); | ||
186 | |||
187 | /* clear all the interrupt status bits */ | ||
188 | writew(readw(ioaddr + RTC_RTCISR), ioaddr + RTC_RTCISR); | ||
189 | set_alarm_or_time(dev, MXC_RTC_ALARM, time); | ||
190 | |||
191 | return ret; | ||
192 | } | ||
193 | |||
194 | /* This function is the RTC interrupt service routine. */ | ||
195 | static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id) | ||
196 | { | ||
197 | struct platform_device *pdev = dev_id; | ||
198 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
199 | void __iomem *ioaddr = pdata->ioaddr; | ||
200 | u32 status; | ||
201 | u32 events = 0; | ||
202 | |||
203 | spin_lock_irq(&pdata->rtc->irq_lock); | ||
204 | status = readw(ioaddr + RTC_RTCISR) & readw(ioaddr + RTC_RTCIENR); | ||
205 | /* clear interrupt sources */ | ||
206 | writew(status, ioaddr + RTC_RTCISR); | ||
207 | |||
208 | /* clear alarm interrupt if it has occurred */ | ||
209 | if (status & RTC_ALM_BIT) | ||
210 | status &= ~RTC_ALM_BIT; | ||
211 | |||
212 | /* update irq data & counter */ | ||
213 | if (status & RTC_ALM_BIT) | ||
214 | events |= (RTC_AF | RTC_IRQF); | ||
215 | |||
216 | if (status & RTC_1HZ_BIT) | ||
217 | events |= (RTC_UF | RTC_IRQF); | ||
218 | |||
219 | if (status & PIT_ALL_ON) | ||
220 | events |= (RTC_PF | RTC_IRQF); | ||
221 | |||
222 | if ((status & RTC_ALM_BIT) && rtc_valid_tm(&pdata->g_rtc_alarm)) | ||
223 | rtc_update_alarm(&pdev->dev, &pdata->g_rtc_alarm); | ||
224 | |||
225 | rtc_update_irq(pdata->rtc, 1, events); | ||
226 | spin_unlock_irq(&pdata->rtc->irq_lock); | ||
227 | |||
228 | return IRQ_HANDLED; | ||
229 | } | ||
230 | |||
231 | /* | ||
232 | * Clear all interrupts and release the IRQ | ||
233 | */ | ||
234 | static void mxc_rtc_release(struct device *dev) | ||
235 | { | ||
236 | struct platform_device *pdev = to_platform_device(dev); | ||
237 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
238 | void __iomem *ioaddr = pdata->ioaddr; | ||
239 | |||
240 | spin_lock_irq(&pdata->rtc->irq_lock); | ||
241 | |||
242 | /* Disable all rtc interrupts */ | ||
243 | writew(0, ioaddr + RTC_RTCIENR); | ||
244 | |||
245 | /* Clear all interrupt status */ | ||
246 | writew(0xffffffff, ioaddr + RTC_RTCISR); | ||
247 | |||
248 | spin_unlock_irq(&pdata->rtc->irq_lock); | ||
249 | } | ||
250 | |||
251 | static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit, | ||
252 | unsigned int enabled) | ||
253 | { | ||
254 | struct platform_device *pdev = to_platform_device(dev); | ||
255 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
256 | void __iomem *ioaddr = pdata->ioaddr; | ||
257 | u32 reg; | ||
258 | |||
259 | spin_lock_irq(&pdata->rtc->irq_lock); | ||
260 | reg = readw(ioaddr + RTC_RTCIENR); | ||
261 | |||
262 | if (enabled) | ||
263 | reg |= bit; | ||
264 | else | ||
265 | reg &= ~bit; | ||
266 | |||
267 | writew(reg, ioaddr + RTC_RTCIENR); | ||
268 | spin_unlock_irq(&pdata->rtc->irq_lock); | ||
269 | } | ||
270 | |||
271 | static int mxc_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
272 | { | ||
273 | mxc_rtc_irq_enable(dev, RTC_ALM_BIT, enabled); | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static int mxc_rtc_update_irq_enable(struct device *dev, unsigned int enabled) | ||
278 | { | ||
279 | mxc_rtc_irq_enable(dev, RTC_1HZ_BIT, enabled); | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * This function reads the current RTC time into tm in Gregorian date. | ||
285 | */ | ||
286 | static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
287 | { | ||
288 | u32 val; | ||
289 | |||
290 | /* Avoid roll-over from reading the different registers */ | ||
291 | do { | ||
292 | val = get_alarm_or_time(dev, MXC_RTC_TIME); | ||
293 | } while (val != get_alarm_or_time(dev, MXC_RTC_TIME)); | ||
294 | |||
295 | rtc_time_to_tm(val, tm); | ||
296 | |||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | /* | ||
301 | * This function sets the internal RTC time based on tm in Gregorian date. | ||
302 | */ | ||
303 | static int mxc_rtc_set_mmss(struct device *dev, unsigned long time) | ||
304 | { | ||
305 | /* Avoid roll-over from reading the different registers */ | ||
306 | do { | ||
307 | set_alarm_or_time(dev, MXC_RTC_TIME, time); | ||
308 | } while (time != get_alarm_or_time(dev, MXC_RTC_TIME)); | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | /* | ||
314 | * This function reads the current alarm value into the passed in 'alrm' | ||
315 | * argument. It updates the alrm's pending field value based on the whether | ||
316 | * an alarm interrupt occurs or not. | ||
317 | */ | ||
318 | static int mxc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
319 | { | ||
320 | struct platform_device *pdev = to_platform_device(dev); | ||
321 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
322 | void __iomem *ioaddr = pdata->ioaddr; | ||
323 | |||
324 | rtc_time_to_tm(get_alarm_or_time(dev, MXC_RTC_ALARM), &alrm->time); | ||
325 | alrm->pending = ((readw(ioaddr + RTC_RTCISR) & RTC_ALM_BIT)) ? 1 : 0; | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | /* | ||
331 | * This function sets the RTC alarm based on passed in alrm. | ||
332 | */ | ||
333 | static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
334 | { | ||
335 | struct platform_device *pdev = to_platform_device(dev); | ||
336 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
337 | int ret; | ||
338 | |||
339 | if (rtc_valid_tm(&alrm->time)) { | ||
340 | if (alrm->time.tm_sec > 59 || | ||
341 | alrm->time.tm_hour > 23 || | ||
342 | alrm->time.tm_min > 59) | ||
343 | return -EINVAL; | ||
344 | |||
345 | ret = rtc_update_alarm(dev, &alrm->time); | ||
346 | } else { | ||
347 | ret = rtc_valid_tm(&alrm->time); | ||
348 | if (ret) | ||
349 | return ret; | ||
350 | |||
351 | ret = rtc_update_alarm(dev, &alrm->time); | ||
352 | } | ||
353 | |||
354 | if (ret) | ||
355 | return ret; | ||
356 | |||
357 | memcpy(&pdata->g_rtc_alarm, &alrm->time, sizeof(struct rtc_time)); | ||
358 | mxc_rtc_irq_enable(dev, RTC_ALM_BIT, alrm->enabled); | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | /* RTC layer */ | ||
364 | static struct rtc_class_ops mxc_rtc_ops = { | ||
365 | .release = mxc_rtc_release, | ||
366 | .read_time = mxc_rtc_read_time, | ||
367 | .set_mmss = mxc_rtc_set_mmss, | ||
368 | .read_alarm = mxc_rtc_read_alarm, | ||
369 | .set_alarm = mxc_rtc_set_alarm, | ||
370 | .alarm_irq_enable = mxc_rtc_alarm_irq_enable, | ||
371 | .update_irq_enable = mxc_rtc_update_irq_enable, | ||
372 | }; | ||
373 | |||
374 | static int __init mxc_rtc_probe(struct platform_device *pdev) | ||
375 | { | ||
376 | struct resource *res; | ||
377 | struct rtc_device *rtc; | ||
378 | struct rtc_plat_data *pdata = NULL; | ||
379 | u32 reg; | ||
380 | unsigned long rate; | ||
381 | int ret; | ||
382 | |||
383 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
384 | if (!res) | ||
385 | return -ENODEV; | ||
386 | |||
387 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
388 | if (!pdata) | ||
389 | return -ENOMEM; | ||
390 | |||
391 | if (!devm_request_mem_region(&pdev->dev, res->start, | ||
392 | resource_size(res), pdev->name)) | ||
393 | return -EBUSY; | ||
394 | |||
395 | pdata->ioaddr = devm_ioremap(&pdev->dev, res->start, | ||
396 | resource_size(res)); | ||
397 | |||
398 | pdata->clk = clk_get(&pdev->dev, "rtc"); | ||
399 | if (IS_ERR(pdata->clk)) { | ||
400 | dev_err(&pdev->dev, "unable to get clock!\n"); | ||
401 | ret = PTR_ERR(pdata->clk); | ||
402 | goto exit_free_pdata; | ||
403 | } | ||
404 | |||
405 | clk_enable(pdata->clk); | ||
406 | rate = clk_get_rate(pdata->clk); | ||
407 | |||
408 | if (rate == 32768) | ||
409 | reg = RTC_INPUT_CLK_32768HZ; | ||
410 | else if (rate == 32000) | ||
411 | reg = RTC_INPUT_CLK_32000HZ; | ||
412 | else if (rate == 38400) | ||
413 | reg = RTC_INPUT_CLK_38400HZ; | ||
414 | else { | ||
415 | dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", rate); | ||
416 | ret = -EINVAL; | ||
417 | goto exit_put_clk; | ||
418 | } | ||
419 | |||
420 | reg |= RTC_ENABLE_BIT; | ||
421 | writew(reg, (pdata->ioaddr + RTC_RTCCTL)); | ||
422 | if (((readw(pdata->ioaddr + RTC_RTCCTL)) & RTC_ENABLE_BIT) == 0) { | ||
423 | dev_err(&pdev->dev, "hardware module can't be enabled!\n"); | ||
424 | ret = -EIO; | ||
425 | goto exit_put_clk; | ||
426 | } | ||
427 | |||
428 | rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops, | ||
429 | THIS_MODULE); | ||
430 | if (IS_ERR(rtc)) { | ||
431 | ret = PTR_ERR(rtc); | ||
432 | goto exit_put_clk; | ||
433 | } | ||
434 | |||
435 | pdata->rtc = rtc; | ||
436 | platform_set_drvdata(pdev, pdata); | ||
437 | |||
438 | /* Configure and enable the RTC */ | ||
439 | pdata->irq = platform_get_irq(pdev, 0); | ||
440 | |||
441 | if (pdata->irq >= 0 && | ||
442 | devm_request_irq(&pdev->dev, pdata->irq, mxc_rtc_interrupt, | ||
443 | IRQF_SHARED, pdev->name, pdev) < 0) { | ||
444 | dev_warn(&pdev->dev, "interrupt not available.\n"); | ||
445 | pdata->irq = -1; | ||
446 | } | ||
447 | |||
448 | return 0; | ||
449 | |||
450 | exit_put_clk: | ||
451 | clk_disable(pdata->clk); | ||
452 | clk_put(pdata->clk); | ||
453 | |||
454 | exit_free_pdata: | ||
455 | |||
456 | return ret; | ||
457 | } | ||
458 | |||
459 | static int __exit mxc_rtc_remove(struct platform_device *pdev) | ||
460 | { | ||
461 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
462 | |||
463 | rtc_device_unregister(pdata->rtc); | ||
464 | |||
465 | clk_disable(pdata->clk); | ||
466 | clk_put(pdata->clk); | ||
467 | platform_set_drvdata(pdev, NULL); | ||
468 | |||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | static struct platform_driver mxc_rtc_driver = { | ||
473 | .driver = { | ||
474 | .name = "mxc_rtc", | ||
475 | .owner = THIS_MODULE, | ||
476 | }, | ||
477 | .remove = __exit_p(mxc_rtc_remove), | ||
478 | }; | ||
479 | |||
480 | static int __init mxc_rtc_init(void) | ||
481 | { | ||
482 | return platform_driver_probe(&mxc_rtc_driver, mxc_rtc_probe); | ||
483 | } | ||
484 | |||
485 | static void __exit mxc_rtc_exit(void) | ||
486 | { | ||
487 | platform_driver_unregister(&mxc_rtc_driver); | ||
488 | } | ||
489 | |||
490 | module_init(mxc_rtc_init); | ||
491 | module_exit(mxc_rtc_exit); | ||
492 | |||
493 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | ||
494 | MODULE_DESCRIPTION("RTC driver for Freescale MXC"); | ||
495 | MODULE_LICENSE("GPL"); | ||
496 | |||
diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c new file mode 100644 index 000000000000..ddb0857e15a4 --- /dev/null +++ b/drivers/rtc/rtc-nuc900.c | |||
@@ -0,0 +1,345 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Nuvoton technology corporation. | ||
3 | * | ||
4 | * Wan ZongShun <mcuos.com@gmail.com> | ||
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 as published by | ||
8 | * the Free Software Foundation;version 2 of the License. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/rtc.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/bcd.h> | ||
20 | |||
21 | /* RTC Control Registers */ | ||
22 | #define REG_RTC_INIR 0x00 | ||
23 | #define REG_RTC_AER 0x04 | ||
24 | #define REG_RTC_FCR 0x08 | ||
25 | #define REG_RTC_TLR 0x0C | ||
26 | #define REG_RTC_CLR 0x10 | ||
27 | #define REG_RTC_TSSR 0x14 | ||
28 | #define REG_RTC_DWR 0x18 | ||
29 | #define REG_RTC_TAR 0x1C | ||
30 | #define REG_RTC_CAR 0x20 | ||
31 | #define REG_RTC_LIR 0x24 | ||
32 | #define REG_RTC_RIER 0x28 | ||
33 | #define REG_RTC_RIIR 0x2C | ||
34 | #define REG_RTC_TTR 0x30 | ||
35 | |||
36 | #define RTCSET 0x01 | ||
37 | #define AERRWENB 0x10000 | ||
38 | #define INIRRESET 0xa5eb1357 | ||
39 | #define AERPOWERON 0xA965 | ||
40 | #define AERPOWEROFF 0x0000 | ||
41 | #define LEAPYEAR 0x0001 | ||
42 | #define TICKENB 0x80 | ||
43 | #define TICKINTENB 0x0002 | ||
44 | #define ALARMINTENB 0x0001 | ||
45 | #define MODE24 0x0001 | ||
46 | |||
47 | struct nuc900_rtc { | ||
48 | int irq_num; | ||
49 | void __iomem *rtc_reg; | ||
50 | struct rtc_device *rtcdev; | ||
51 | }; | ||
52 | |||
53 | struct nuc900_bcd_time { | ||
54 | int bcd_sec; | ||
55 | int bcd_min; | ||
56 | int bcd_hour; | ||
57 | int bcd_mday; | ||
58 | int bcd_mon; | ||
59 | int bcd_year; | ||
60 | }; | ||
61 | |||
62 | static irqreturn_t nuc900_rtc_interrupt(int irq, void *_rtc) | ||
63 | { | ||
64 | struct nuc900_rtc *rtc = _rtc; | ||
65 | unsigned long events = 0, rtc_irq; | ||
66 | |||
67 | rtc_irq = __raw_readl(rtc->rtc_reg + REG_RTC_RIIR); | ||
68 | |||
69 | if (rtc_irq & ALARMINTENB) { | ||
70 | rtc_irq &= ~ALARMINTENB; | ||
71 | __raw_writel(rtc_irq, rtc->rtc_reg + REG_RTC_RIIR); | ||
72 | events |= RTC_AF | RTC_IRQF; | ||
73 | } | ||
74 | |||
75 | if (rtc_irq & TICKINTENB) { | ||
76 | rtc_irq &= ~TICKINTENB; | ||
77 | __raw_writel(rtc_irq, rtc->rtc_reg + REG_RTC_RIIR); | ||
78 | events |= RTC_UF | RTC_IRQF; | ||
79 | } | ||
80 | |||
81 | rtc_update_irq(rtc->rtcdev, 1, events); | ||
82 | |||
83 | return IRQ_HANDLED; | ||
84 | } | ||
85 | |||
86 | static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc) | ||
87 | { | ||
88 | unsigned int timeout = 0x1000; | ||
89 | __raw_writel(INIRRESET, nuc900_rtc->rtc_reg + REG_RTC_INIR); | ||
90 | |||
91 | mdelay(10); | ||
92 | |||
93 | __raw_writel(AERPOWERON, nuc900_rtc->rtc_reg + REG_RTC_AER); | ||
94 | |||
95 | while (!(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB) | ||
96 | && timeout--) | ||
97 | mdelay(1); | ||
98 | |||
99 | if (!timeout) | ||
100 | return ERR_PTR(-EPERM); | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static int nuc900_rtc_bcd2bin(unsigned int timereg, | ||
106 | unsigned int calreg, struct rtc_time *tm) | ||
107 | { | ||
108 | tm->tm_mday = bcd2bin(calreg >> 0); | ||
109 | tm->tm_mon = bcd2bin(calreg >> 8); | ||
110 | tm->tm_year = bcd2bin(calreg >> 16) + 100; | ||
111 | |||
112 | tm->tm_sec = bcd2bin(timereg >> 0); | ||
113 | tm->tm_min = bcd2bin(timereg >> 8); | ||
114 | tm->tm_hour = bcd2bin(timereg >> 16); | ||
115 | |||
116 | return rtc_valid_tm(tm); | ||
117 | } | ||
118 | |||
119 | static void nuc900_rtc_bin2bcd(struct device *dev, struct rtc_time *settm, | ||
120 | struct nuc900_bcd_time *gettm) | ||
121 | { | ||
122 | gettm->bcd_mday = bin2bcd(settm->tm_mday) << 0; | ||
123 | gettm->bcd_mon = bin2bcd(settm->tm_mon) << 8; | ||
124 | |||
125 | if (settm->tm_year < 100) { | ||
126 | dev_warn(dev, "The year will be between 1970-1999, right?\n"); | ||
127 | gettm->bcd_year = bin2bcd(settm->tm_year) << 16; | ||
128 | } else { | ||
129 | gettm->bcd_year = bin2bcd(settm->tm_year - 100) << 16; | ||
130 | } | ||
131 | |||
132 | gettm->bcd_sec = bin2bcd(settm->tm_sec) << 0; | ||
133 | gettm->bcd_min = bin2bcd(settm->tm_min) << 8; | ||
134 | gettm->bcd_hour = bin2bcd(settm->tm_hour) << 16; | ||
135 | } | ||
136 | |||
137 | static int nuc900_update_irq_enable(struct device *dev, unsigned int enabled) | ||
138 | { | ||
139 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
140 | |||
141 | if (enabled) | ||
142 | __raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)| | ||
143 | (TICKINTENB), rtc->rtc_reg + REG_RTC_RIER); | ||
144 | else | ||
145 | __raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)& | ||
146 | (~TICKINTENB), rtc->rtc_reg + REG_RTC_RIER); | ||
147 | |||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static int nuc900_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
152 | { | ||
153 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
154 | |||
155 | if (enabled) | ||
156 | __raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)| | ||
157 | (ALARMINTENB), rtc->rtc_reg + REG_RTC_RIER); | ||
158 | else | ||
159 | __raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)& | ||
160 | (~ALARMINTENB), rtc->rtc_reg + REG_RTC_RIER); | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int nuc900_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
166 | { | ||
167 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
168 | unsigned int timeval, clrval; | ||
169 | |||
170 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TLR); | ||
171 | clrval = __raw_readl(rtc->rtc_reg + REG_RTC_CLR); | ||
172 | |||
173 | return nuc900_rtc_bcd2bin(timeval, clrval, tm); | ||
174 | } | ||
175 | |||
176 | static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
177 | { | ||
178 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
179 | struct nuc900_bcd_time gettm; | ||
180 | unsigned long val; | ||
181 | int *err; | ||
182 | |||
183 | nuc900_rtc_bin2bcd(dev, tm, &gettm); | ||
184 | |||
185 | err = check_rtc_access_enable(rtc); | ||
186 | if (IS_ERR(err)) | ||
187 | return PTR_ERR(err); | ||
188 | |||
189 | val = gettm.bcd_mday | gettm.bcd_mon | gettm.bcd_year; | ||
190 | __raw_writel(val, rtc->rtc_reg + REG_RTC_CLR); | ||
191 | |||
192 | val = gettm.bcd_sec | gettm.bcd_min | gettm.bcd_hour; | ||
193 | __raw_writel(val, rtc->rtc_reg + REG_RTC_TLR); | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static int nuc900_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
199 | { | ||
200 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
201 | unsigned int timeval, carval; | ||
202 | |||
203 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TAR); | ||
204 | carval = __raw_readl(rtc->rtc_reg + REG_RTC_CAR); | ||
205 | |||
206 | return nuc900_rtc_bcd2bin(timeval, carval, &alrm->time); | ||
207 | } | ||
208 | |||
209 | static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
210 | { | ||
211 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
212 | struct nuc900_bcd_time tm; | ||
213 | unsigned long val; | ||
214 | int *err; | ||
215 | |||
216 | nuc900_rtc_bin2bcd(dev, &alrm->time, &tm); | ||
217 | |||
218 | err = check_rtc_access_enable(rtc); | ||
219 | if (IS_ERR(err)) | ||
220 | return PTR_ERR(err); | ||
221 | |||
222 | val = tm.bcd_mday | tm.bcd_mon | tm.bcd_year; | ||
223 | __raw_writel(val, rtc->rtc_reg + REG_RTC_CAR); | ||
224 | |||
225 | val = tm.bcd_sec | tm.bcd_min | tm.bcd_hour; | ||
226 | __raw_writel(val, rtc->rtc_reg + REG_RTC_TAR); | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static struct rtc_class_ops nuc900_rtc_ops = { | ||
232 | .read_time = nuc900_rtc_read_time, | ||
233 | .set_time = nuc900_rtc_set_time, | ||
234 | .read_alarm = nuc900_rtc_read_alarm, | ||
235 | .set_alarm = nuc900_rtc_set_alarm, | ||
236 | .alarm_irq_enable = nuc900_alarm_irq_enable, | ||
237 | .update_irq_enable = nuc900_update_irq_enable, | ||
238 | }; | ||
239 | |||
240 | static int __devinit nuc900_rtc_probe(struct platform_device *pdev) | ||
241 | { | ||
242 | struct resource *res; | ||
243 | struct nuc900_rtc *nuc900_rtc; | ||
244 | int err = 0; | ||
245 | |||
246 | nuc900_rtc = kzalloc(sizeof(struct nuc900_rtc), GFP_KERNEL); | ||
247 | if (!nuc900_rtc) { | ||
248 | dev_err(&pdev->dev, "kzalloc nuc900_rtc failed\n"); | ||
249 | return -ENOMEM; | ||
250 | } | ||
251 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
252 | if (!res) { | ||
253 | dev_err(&pdev->dev, "platform_get_resource failed\n"); | ||
254 | err = -ENXIO; | ||
255 | goto fail1; | ||
256 | } | ||
257 | |||
258 | if (!request_mem_region(res->start, resource_size(res), | ||
259 | pdev->name)) { | ||
260 | dev_err(&pdev->dev, "request_mem_region failed\n"); | ||
261 | err = -EBUSY; | ||
262 | goto fail1; | ||
263 | } | ||
264 | |||
265 | nuc900_rtc->rtc_reg = ioremap(res->start, resource_size(res)); | ||
266 | if (!nuc900_rtc->rtc_reg) { | ||
267 | dev_err(&pdev->dev, "ioremap rtc_reg failed\n"); | ||
268 | err = -ENOMEM; | ||
269 | goto fail2; | ||
270 | } | ||
271 | |||
272 | platform_set_drvdata(pdev, nuc900_rtc); | ||
273 | |||
274 | nuc900_rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev, | ||
275 | &nuc900_rtc_ops, THIS_MODULE); | ||
276 | if (IS_ERR(nuc900_rtc->rtcdev)) { | ||
277 | dev_err(&pdev->dev, "rtc device register failed\n"); | ||
278 | err = PTR_ERR(nuc900_rtc->rtcdev); | ||
279 | goto fail3; | ||
280 | } | ||
281 | |||
282 | __raw_writel(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_TSSR) | MODE24, | ||
283 | nuc900_rtc->rtc_reg + REG_RTC_TSSR); | ||
284 | |||
285 | nuc900_rtc->irq_num = platform_get_irq(pdev, 0); | ||
286 | if (request_irq(nuc900_rtc->irq_num, nuc900_rtc_interrupt, | ||
287 | IRQF_DISABLED, "nuc900rtc", nuc900_rtc)) { | ||
288 | dev_err(&pdev->dev, "NUC900 RTC request irq failed\n"); | ||
289 | err = -EBUSY; | ||
290 | goto fail4; | ||
291 | } | ||
292 | |||
293 | return 0; | ||
294 | |||
295 | fail4: rtc_device_unregister(nuc900_rtc->rtcdev); | ||
296 | fail3: iounmap(nuc900_rtc->rtc_reg); | ||
297 | fail2: release_mem_region(res->start, resource_size(res)); | ||
298 | fail1: kfree(nuc900_rtc); | ||
299 | return err; | ||
300 | } | ||
301 | |||
302 | static int __devexit nuc900_rtc_remove(struct platform_device *pdev) | ||
303 | { | ||
304 | struct nuc900_rtc *nuc900_rtc = platform_get_drvdata(pdev); | ||
305 | struct resource *res; | ||
306 | |||
307 | free_irq(nuc900_rtc->irq_num, nuc900_rtc); | ||
308 | rtc_device_unregister(nuc900_rtc->rtcdev); | ||
309 | iounmap(nuc900_rtc->rtc_reg); | ||
310 | |||
311 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
312 | release_mem_region(res->start, resource_size(res)); | ||
313 | |||
314 | kfree(nuc900_rtc); | ||
315 | |||
316 | platform_set_drvdata(pdev, NULL); | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static struct platform_driver nuc900_rtc_driver = { | ||
322 | .remove = __devexit_p(nuc900_rtc_remove), | ||
323 | .driver = { | ||
324 | .name = "nuc900-rtc", | ||
325 | .owner = THIS_MODULE, | ||
326 | }, | ||
327 | }; | ||
328 | |||
329 | static int __init nuc900_rtc_init(void) | ||
330 | { | ||
331 | return platform_driver_probe(&nuc900_rtc_driver, nuc900_rtc_probe); | ||
332 | } | ||
333 | |||
334 | static void __exit nuc900_rtc_exit(void) | ||
335 | { | ||
336 | platform_driver_unregister(&nuc900_rtc_driver); | ||
337 | } | ||
338 | |||
339 | module_init(nuc900_rtc_init); | ||
340 | module_exit(nuc900_rtc_exit); | ||
341 | |||
342 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); | ||
343 | MODULE_DESCRIPTION("nuc910/nuc920 RTC driver"); | ||
344 | MODULE_LICENSE("GPL"); | ||
345 | MODULE_ALIAS("platform:nuc900-rtc"); | ||
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index bd1ce8e2bc18..73377b0d65da 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c | |||
@@ -34,7 +34,8 @@ | |||
34 | * Board-specific wiring options include using split power mode with | 34 | * Board-specific wiring options include using split power mode with |
35 | * RTC_OFF_NOFF used as the reset signal (so the RTC won't be reset), | 35 | * RTC_OFF_NOFF used as the reset signal (so the RTC won't be reset), |
36 | * and wiring RTC_WAKE_INT (so the RTC alarm can wake the system from | 36 | * and wiring RTC_WAKE_INT (so the RTC alarm can wake the system from |
37 | * low power modes). See the BOARD-SPECIFIC CUSTOMIZATION comment. | 37 | * low power modes) for OMAP1 boards (OMAP-L138 has this built into |
38 | * the SoC). See the BOARD-SPECIFIC CUSTOMIZATION comment. | ||
38 | */ | 39 | */ |
39 | 40 | ||
40 | #define OMAP_RTC_BASE 0xfffb4800 | 41 | #define OMAP_RTC_BASE 0xfffb4800 |
@@ -87,9 +88,10 @@ | |||
87 | #define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3) | 88 | #define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3) |
88 | #define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2) | 89 | #define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2) |
89 | 90 | ||
91 | static void __iomem *rtc_base; | ||
90 | 92 | ||
91 | #define rtc_read(addr) omap_readb(OMAP_RTC_BASE + (addr)) | 93 | #define rtc_read(addr) __raw_readb(rtc_base + (addr)) |
92 | #define rtc_write(val, addr) omap_writeb(val, OMAP_RTC_BASE + (addr)) | 94 | #define rtc_write(val, addr) __raw_writeb(val, rtc_base + (addr)) |
93 | 95 | ||
94 | 96 | ||
95 | /* we rely on the rtc framework to handle locking (rtc->ops_lock), | 97 | /* we rely on the rtc framework to handle locking (rtc->ops_lock), |
@@ -330,32 +332,31 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
330 | return -ENOENT; | 332 | return -ENOENT; |
331 | } | 333 | } |
332 | 334 | ||
333 | /* NOTE: using static mapping for RTC registers */ | ||
334 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 335 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
335 | if (res && res->start != OMAP_RTC_BASE) { | 336 | if (!res) { |
336 | pr_debug("%s: RTC registers at %08x, expected %08x\n", | 337 | pr_debug("%s: RTC resource data missing\n", pdev->name); |
337 | pdev->name, (unsigned) res->start, OMAP_RTC_BASE); | ||
338 | return -ENOENT; | 338 | return -ENOENT; |
339 | } | 339 | } |
340 | 340 | ||
341 | if (res) | 341 | mem = request_mem_region(res->start, resource_size(res), pdev->name); |
342 | mem = request_mem_region(res->start, | ||
343 | res->end - res->start + 1, | ||
344 | pdev->name); | ||
345 | else | ||
346 | mem = NULL; | ||
347 | if (!mem) { | 342 | if (!mem) { |
348 | pr_debug("%s: RTC registers at %08x are not free\n", | 343 | pr_debug("%s: RTC registers at %08x are not free\n", |
349 | pdev->name, OMAP_RTC_BASE); | 344 | pdev->name, res->start); |
350 | return -EBUSY; | 345 | return -EBUSY; |
351 | } | 346 | } |
352 | 347 | ||
348 | rtc_base = ioremap(res->start, resource_size(res)); | ||
349 | if (!rtc_base) { | ||
350 | pr_debug("%s: RTC registers can't be mapped\n", pdev->name); | ||
351 | goto fail; | ||
352 | } | ||
353 | |||
353 | rtc = rtc_device_register(pdev->name, &pdev->dev, | 354 | rtc = rtc_device_register(pdev->name, &pdev->dev, |
354 | &omap_rtc_ops, THIS_MODULE); | 355 | &omap_rtc_ops, THIS_MODULE); |
355 | if (IS_ERR(rtc)) { | 356 | if (IS_ERR(rtc)) { |
356 | pr_debug("%s: can't register RTC device, err %ld\n", | 357 | pr_debug("%s: can't register RTC device, err %ld\n", |
357 | pdev->name, PTR_ERR(rtc)); | 358 | pdev->name, PTR_ERR(rtc)); |
358 | goto fail; | 359 | goto fail0; |
359 | } | 360 | } |
360 | platform_set_drvdata(pdev, rtc); | 361 | platform_set_drvdata(pdev, rtc); |
361 | dev_set_drvdata(&rtc->dev, mem); | 362 | dev_set_drvdata(&rtc->dev, mem); |
@@ -380,13 +381,14 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
380 | dev_name(&rtc->dev), rtc)) { | 381 | dev_name(&rtc->dev), rtc)) { |
381 | pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n", | 382 | pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n", |
382 | pdev->name, omap_rtc_timer); | 383 | pdev->name, omap_rtc_timer); |
383 | goto fail0; | 384 | goto fail1; |
384 | } | 385 | } |
385 | if (request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED, | 386 | if ((omap_rtc_timer != omap_rtc_alarm) && |
386 | dev_name(&rtc->dev), rtc)) { | 387 | (request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED, |
388 | dev_name(&rtc->dev), rtc))) { | ||
387 | pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n", | 389 | pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n", |
388 | pdev->name, omap_rtc_alarm); | 390 | pdev->name, omap_rtc_alarm); |
389 | goto fail1; | 391 | goto fail2; |
390 | } | 392 | } |
391 | 393 | ||
392 | /* On boards with split power, RTC_ON_NOFF won't reset the RTC */ | 394 | /* On boards with split power, RTC_ON_NOFF won't reset the RTC */ |
@@ -400,16 +402,17 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
400 | 402 | ||
401 | /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: | 403 | /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: |
402 | * | 404 | * |
403 | * - Boards wired so that RTC_WAKE_INT does something, and muxed | 405 | * - Device wake-up capability setting should come through chip |
404 | * right (W13_1610_RTC_WAKE_INT is the default after chip reset), | 406 | * init logic. OMAP1 boards should initialize the "wakeup capable" |
405 | * should initialize the device wakeup flag appropriately. | 407 | * flag in the platform device if the board is wired right for |
408 | * being woken up by RTC alarm. For OMAP-L138, this capability | ||
409 | * is built into the SoC by the "Deep Sleep" capability. | ||
406 | * | 410 | * |
407 | * - Boards wired so RTC_ON_nOFF is used as the reset signal, | 411 | * - Boards wired so RTC_ON_nOFF is used as the reset signal, |
408 | * rather than nPWRON_RESET, should forcibly enable split | 412 | * rather than nPWRON_RESET, should forcibly enable split |
409 | * power mode. (Some chip errata report that RTC_CTRL_SPLIT | 413 | * power mode. (Some chip errata report that RTC_CTRL_SPLIT |
410 | * is write-only, and always reads as zero...) | 414 | * is write-only, and always reads as zero...) |
411 | */ | 415 | */ |
412 | device_init_wakeup(&pdev->dev, 0); | ||
413 | 416 | ||
414 | if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT) | 417 | if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT) |
415 | pr_info("%s: split power mode\n", pdev->name); | 418 | pr_info("%s: split power mode\n", pdev->name); |
@@ -419,10 +422,12 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
419 | 422 | ||
420 | return 0; | 423 | return 0; |
421 | 424 | ||
422 | fail1: | 425 | fail2: |
423 | free_irq(omap_rtc_timer, NULL); | 426 | free_irq(omap_rtc_timer, NULL); |
424 | fail0: | 427 | fail1: |
425 | rtc_device_unregister(rtc); | 428 | rtc_device_unregister(rtc); |
429 | fail0: | ||
430 | iounmap(rtc_base); | ||
426 | fail: | 431 | fail: |
427 | release_resource(mem); | 432 | release_resource(mem); |
428 | return -EIO; | 433 | return -EIO; |
@@ -430,7 +435,7 @@ fail: | |||
430 | 435 | ||
431 | static int __exit omap_rtc_remove(struct platform_device *pdev) | 436 | static int __exit omap_rtc_remove(struct platform_device *pdev) |
432 | { | 437 | { |
433 | struct rtc_device *rtc = platform_get_drvdata(pdev);; | 438 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
434 | 439 | ||
435 | device_init_wakeup(&pdev->dev, 0); | 440 | device_init_wakeup(&pdev->dev, 0); |
436 | 441 | ||
@@ -438,7 +443,9 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) | |||
438 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); | 443 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); |
439 | 444 | ||
440 | free_irq(omap_rtc_timer, rtc); | 445 | free_irq(omap_rtc_timer, rtc); |
441 | free_irq(omap_rtc_alarm, rtc); | 446 | |
447 | if (omap_rtc_timer != omap_rtc_alarm) | ||
448 | free_irq(omap_rtc_alarm, rtc); | ||
442 | 449 | ||
443 | release_resource(dev_get_drvdata(&rtc->dev)); | 450 | release_resource(dev_get_drvdata(&rtc->dev)); |
444 | rtc_device_unregister(rtc); | 451 | rtc_device_unregister(rtc); |
diff --git a/drivers/rtc/rtc-pcap.c b/drivers/rtc/rtc-pcap.c new file mode 100644 index 000000000000..25c0b3fd44f1 --- /dev/null +++ b/drivers/rtc/rtc-pcap.c | |||
@@ -0,0 +1,225 @@ | |||
1 | /* | ||
2 | * pcap rtc code for Motorola EZX phones | ||
3 | * | ||
4 | * Copyright (c) 2008 guiming zhuo <gmzhuo@gmail.com> | ||
5 | * Copyright (c) 2009 Daniel Ribeiro <drwyrm@gmail.com> | ||
6 | * | ||
7 | * Based on Motorola's rtc.c Copyright (c) 2003-2005 Motorola | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/mfd/ezx-pcap.h> | ||
19 | #include <linux/rtc.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | |||
23 | struct pcap_rtc { | ||
24 | struct pcap_chip *pcap; | ||
25 | struct rtc_device *rtc; | ||
26 | }; | ||
27 | |||
28 | static irqreturn_t pcap_rtc_irq(int irq, void *_pcap_rtc) | ||
29 | { | ||
30 | struct pcap_rtc *pcap_rtc = _pcap_rtc; | ||
31 | unsigned long rtc_events; | ||
32 | |||
33 | if (irq == pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_1HZ)) | ||
34 | rtc_events = RTC_IRQF | RTC_UF; | ||
35 | else if (irq == pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_TODA)) | ||
36 | rtc_events = RTC_IRQF | RTC_AF; | ||
37 | else | ||
38 | rtc_events = 0; | ||
39 | |||
40 | rtc_update_irq(pcap_rtc->rtc, 1, rtc_events); | ||
41 | return IRQ_HANDLED; | ||
42 | } | ||
43 | |||
44 | static int pcap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
45 | { | ||
46 | struct platform_device *pdev = to_platform_device(dev); | ||
47 | struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); | ||
48 | struct rtc_time *tm = &alrm->time; | ||
49 | unsigned long secs; | ||
50 | u32 tod; /* time of day, seconds since midnight */ | ||
51 | u32 days; /* days since 1/1/1970 */ | ||
52 | |||
53 | ezx_pcap_read(pcap_rtc->pcap, PCAP_REG_RTC_TODA, &tod); | ||
54 | secs = tod & PCAP_RTC_TOD_MASK; | ||
55 | |||
56 | ezx_pcap_read(pcap_rtc->pcap, PCAP_REG_RTC_DAYA, &days); | ||
57 | secs += (days & PCAP_RTC_DAY_MASK) * SEC_PER_DAY; | ||
58 | |||
59 | rtc_time_to_tm(secs, tm); | ||
60 | |||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static int pcap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
65 | { | ||
66 | struct platform_device *pdev = to_platform_device(dev); | ||
67 | struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); | ||
68 | struct rtc_time *tm = &alrm->time; | ||
69 | unsigned long secs; | ||
70 | u32 tod, days; | ||
71 | |||
72 | rtc_tm_to_time(tm, &secs); | ||
73 | |||
74 | tod = secs % SEC_PER_DAY; | ||
75 | ezx_pcap_write(pcap_rtc->pcap, PCAP_REG_RTC_TODA, tod); | ||
76 | |||
77 | days = secs / SEC_PER_DAY; | ||
78 | ezx_pcap_write(pcap_rtc->pcap, PCAP_REG_RTC_DAYA, days); | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static int pcap_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
84 | { | ||
85 | struct platform_device *pdev = to_platform_device(dev); | ||
86 | struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); | ||
87 | unsigned long secs; | ||
88 | u32 tod, days; | ||
89 | |||
90 | ezx_pcap_read(pcap_rtc->pcap, PCAP_REG_RTC_TOD, &tod); | ||
91 | secs = tod & PCAP_RTC_TOD_MASK; | ||
92 | |||
93 | ezx_pcap_read(pcap_rtc->pcap, PCAP_REG_RTC_DAY, &days); | ||
94 | secs += (days & PCAP_RTC_DAY_MASK) * SEC_PER_DAY; | ||
95 | |||
96 | rtc_time_to_tm(secs, tm); | ||
97 | |||
98 | return rtc_valid_tm(tm); | ||
99 | } | ||
100 | |||
101 | static int pcap_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
102 | { | ||
103 | struct platform_device *pdev = to_platform_device(dev); | ||
104 | struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); | ||
105 | u32 tod, days; | ||
106 | |||
107 | tod = secs % SEC_PER_DAY; | ||
108 | ezx_pcap_write(pcap_rtc->pcap, PCAP_REG_RTC_TOD, tod); | ||
109 | |||
110 | days = secs / SEC_PER_DAY; | ||
111 | ezx_pcap_write(pcap_rtc->pcap, PCAP_REG_RTC_DAY, days); | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static int pcap_rtc_irq_enable(struct device *dev, int pirq, unsigned int en) | ||
117 | { | ||
118 | struct platform_device *pdev = to_platform_device(dev); | ||
119 | struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); | ||
120 | |||
121 | if (en) | ||
122 | enable_irq(pcap_to_irq(pcap_rtc->pcap, pirq)); | ||
123 | else | ||
124 | disable_irq(pcap_to_irq(pcap_rtc->pcap, pirq)); | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int pcap_rtc_alarm_irq_enable(struct device *dev, unsigned int en) | ||
130 | { | ||
131 | return pcap_rtc_irq_enable(dev, PCAP_IRQ_TODA, en); | ||
132 | } | ||
133 | |||
134 | static int pcap_rtc_update_irq_enable(struct device *dev, unsigned int en) | ||
135 | { | ||
136 | return pcap_rtc_irq_enable(dev, PCAP_IRQ_1HZ, en); | ||
137 | } | ||
138 | |||
139 | static const struct rtc_class_ops pcap_rtc_ops = { | ||
140 | .read_time = pcap_rtc_read_time, | ||
141 | .read_alarm = pcap_rtc_read_alarm, | ||
142 | .set_alarm = pcap_rtc_set_alarm, | ||
143 | .set_mmss = pcap_rtc_set_mmss, | ||
144 | .alarm_irq_enable = pcap_rtc_alarm_irq_enable, | ||
145 | .update_irq_enable = pcap_rtc_update_irq_enable, | ||
146 | }; | ||
147 | |||
148 | static int __devinit pcap_rtc_probe(struct platform_device *pdev) | ||
149 | { | ||
150 | struct pcap_rtc *pcap_rtc; | ||
151 | int timer_irq, alarm_irq; | ||
152 | int err = -ENOMEM; | ||
153 | |||
154 | pcap_rtc = kmalloc(sizeof(struct pcap_rtc), GFP_KERNEL); | ||
155 | if (!pcap_rtc) | ||
156 | return err; | ||
157 | |||
158 | pcap_rtc->pcap = dev_get_drvdata(pdev->dev.parent); | ||
159 | |||
160 | pcap_rtc->rtc = rtc_device_register("pcap", &pdev->dev, | ||
161 | &pcap_rtc_ops, THIS_MODULE); | ||
162 | if (IS_ERR(pcap_rtc->rtc)) { | ||
163 | err = PTR_ERR(pcap_rtc->rtc); | ||
164 | goto fail_rtc; | ||
165 | } | ||
166 | |||
167 | platform_set_drvdata(pdev, pcap_rtc); | ||
168 | |||
169 | timer_irq = pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_1HZ); | ||
170 | alarm_irq = pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_TODA); | ||
171 | |||
172 | err = request_irq(timer_irq, pcap_rtc_irq, 0, "RTC Timer", pcap_rtc); | ||
173 | if (err) | ||
174 | goto fail_timer; | ||
175 | |||
176 | err = request_irq(alarm_irq, pcap_rtc_irq, 0, "RTC Alarm", pcap_rtc); | ||
177 | if (err) | ||
178 | goto fail_alarm; | ||
179 | |||
180 | return 0; | ||
181 | fail_alarm: | ||
182 | free_irq(timer_irq, pcap_rtc); | ||
183 | fail_timer: | ||
184 | rtc_device_unregister(pcap_rtc->rtc); | ||
185 | fail_rtc: | ||
186 | kfree(pcap_rtc); | ||
187 | return err; | ||
188 | } | ||
189 | |||
190 | static int __devexit pcap_rtc_remove(struct platform_device *pdev) | ||
191 | { | ||
192 | struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); | ||
193 | |||
194 | free_irq(pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_1HZ), pcap_rtc); | ||
195 | free_irq(pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_TODA), pcap_rtc); | ||
196 | rtc_device_unregister(pcap_rtc->rtc); | ||
197 | kfree(pcap_rtc); | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static struct platform_driver pcap_rtc_driver = { | ||
203 | .remove = __devexit_p(pcap_rtc_remove), | ||
204 | .driver = { | ||
205 | .name = "pcap-rtc", | ||
206 | .owner = THIS_MODULE, | ||
207 | }, | ||
208 | }; | ||
209 | |||
210 | static int __init rtc_pcap_init(void) | ||
211 | { | ||
212 | return platform_driver_probe(&pcap_rtc_driver, pcap_rtc_probe); | ||
213 | } | ||
214 | |||
215 | static void __exit rtc_pcap_exit(void) | ||
216 | { | ||
217 | platform_driver_unregister(&pcap_rtc_driver); | ||
218 | } | ||
219 | |||
220 | module_init(rtc_pcap_init); | ||
221 | module_exit(rtc_pcap_exit); | ||
222 | |||
223 | MODULE_DESCRIPTION("Motorola pcap rtc driver"); | ||
224 | MODULE_AUTHOR("guiming zhuo <gmzhuo@gmail.com>"); | ||
225 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c new file mode 100644 index 000000000000..71bab0ef5443 --- /dev/null +++ b/drivers/rtc/rtc-pcf2123.c | |||
@@ -0,0 +1,365 @@ | |||
1 | /* | ||
2 | * An SPI driver for the Philips PCF2123 RTC | ||
3 | * Copyright 2009 Cyber Switching, Inc. | ||
4 | * | ||
5 | * Author: Chris Verges <chrisv@cyberswitching.com> | ||
6 | * Maintainers: http://www.cyberswitching.com | ||
7 | * | ||
8 | * based on the RS5C348 driver in this same directory. | ||
9 | * | ||
10 | * Thanks to Christian Pellegrin <chripell@fsfe.org> for | ||
11 | * the sysfs contributions to this driver. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | * | ||
17 | * Please note that the CS is active high, so platform data | ||
18 | * should look something like: | ||
19 | * | ||
20 | * static struct spi_board_info ek_spi_devices[] = { | ||
21 | * ... | ||
22 | * { | ||
23 | * .modalias = "rtc-pcf2123", | ||
24 | * .chip_select = 1, | ||
25 | * .controller_data = (void *)AT91_PIN_PA10, | ||
26 | * .max_speed_hz = 1000 * 1000, | ||
27 | * .mode = SPI_CS_HIGH, | ||
28 | * .bus_num = 0, | ||
29 | * }, | ||
30 | * ... | ||
31 | *}; | ||
32 | * | ||
33 | */ | ||
34 | |||
35 | #include <linux/bcd.h> | ||
36 | #include <linux/delay.h> | ||
37 | #include <linux/device.h> | ||
38 | #include <linux/errno.h> | ||
39 | #include <linux/init.h> | ||
40 | #include <linux/kernel.h> | ||
41 | #include <linux/string.h> | ||
42 | #include <linux/slab.h> | ||
43 | #include <linux/rtc.h> | ||
44 | #include <linux/spi/spi.h> | ||
45 | |||
46 | #define DRV_VERSION "0.6" | ||
47 | |||
48 | #define PCF2123_REG_CTRL1 (0x00) /* Control Register 1 */ | ||
49 | #define PCF2123_REG_CTRL2 (0x01) /* Control Register 2 */ | ||
50 | #define PCF2123_REG_SC (0x02) /* datetime */ | ||
51 | #define PCF2123_REG_MN (0x03) | ||
52 | #define PCF2123_REG_HR (0x04) | ||
53 | #define PCF2123_REG_DM (0x05) | ||
54 | #define PCF2123_REG_DW (0x06) | ||
55 | #define PCF2123_REG_MO (0x07) | ||
56 | #define PCF2123_REG_YR (0x08) | ||
57 | |||
58 | #define PCF2123_SUBADDR (1 << 4) | ||
59 | #define PCF2123_WRITE ((0 << 7) | PCF2123_SUBADDR) | ||
60 | #define PCF2123_READ ((1 << 7) | PCF2123_SUBADDR) | ||
61 | |||
62 | static struct spi_driver pcf2123_driver; | ||
63 | |||
64 | struct pcf2123_sysfs_reg { | ||
65 | struct device_attribute attr; | ||
66 | char name[2]; | ||
67 | }; | ||
68 | |||
69 | struct pcf2123_plat_data { | ||
70 | struct rtc_device *rtc; | ||
71 | struct pcf2123_sysfs_reg regs[16]; | ||
72 | }; | ||
73 | |||
74 | /* | ||
75 | * Causes a 30 nanosecond delay to ensure that the PCF2123 chip select | ||
76 | * is released properly after an SPI write. This function should be | ||
77 | * called after EVERY read/write call over SPI. | ||
78 | */ | ||
79 | static inline void pcf2123_delay_trec(void) | ||
80 | { | ||
81 | ndelay(30); | ||
82 | } | ||
83 | |||
84 | static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr, | ||
85 | char *buffer) | ||
86 | { | ||
87 | struct spi_device *spi = to_spi_device(dev); | ||
88 | struct pcf2123_sysfs_reg *r; | ||
89 | u8 txbuf[1], rxbuf[1]; | ||
90 | unsigned long reg; | ||
91 | int ret; | ||
92 | |||
93 | r = container_of(attr, struct pcf2123_sysfs_reg, attr); | ||
94 | |||
95 | if (strict_strtoul(r->name, 16, ®)) | ||
96 | return -EINVAL; | ||
97 | |||
98 | txbuf[0] = PCF2123_READ | reg; | ||
99 | ret = spi_write_then_read(spi, txbuf, 1, rxbuf, 1); | ||
100 | if (ret < 0) | ||
101 | return -EIO; | ||
102 | pcf2123_delay_trec(); | ||
103 | return sprintf(buffer, "0x%x\n", rxbuf[0]); | ||
104 | } | ||
105 | |||
106 | static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr, | ||
107 | const char *buffer, size_t count) { | ||
108 | struct spi_device *spi = to_spi_device(dev); | ||
109 | struct pcf2123_sysfs_reg *r; | ||
110 | u8 txbuf[2]; | ||
111 | unsigned long reg; | ||
112 | unsigned long val; | ||
113 | |||
114 | int ret; | ||
115 | |||
116 | r = container_of(attr, struct pcf2123_sysfs_reg, attr); | ||
117 | |||
118 | if (strict_strtoul(r->name, 16, ®) | ||
119 | || strict_strtoul(buffer, 10, &val)) | ||
120 | return -EINVAL; | ||
121 | |||
122 | txbuf[0] = PCF2123_WRITE | reg; | ||
123 | txbuf[1] = val; | ||
124 | ret = spi_write(spi, txbuf, sizeof(txbuf)); | ||
125 | if (ret < 0) | ||
126 | return -EIO; | ||
127 | pcf2123_delay_trec(); | ||
128 | return count; | ||
129 | } | ||
130 | |||
131 | static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
132 | { | ||
133 | struct spi_device *spi = to_spi_device(dev); | ||
134 | u8 txbuf[1], rxbuf[7]; | ||
135 | int ret; | ||
136 | |||
137 | txbuf[0] = PCF2123_READ | PCF2123_REG_SC; | ||
138 | ret = spi_write_then_read(spi, txbuf, sizeof(txbuf), | ||
139 | rxbuf, sizeof(rxbuf)); | ||
140 | if (ret < 0) | ||
141 | return ret; | ||
142 | pcf2123_delay_trec(); | ||
143 | |||
144 | tm->tm_sec = bcd2bin(rxbuf[0] & 0x7F); | ||
145 | tm->tm_min = bcd2bin(rxbuf[1] & 0x7F); | ||
146 | tm->tm_hour = bcd2bin(rxbuf[2] & 0x3F); /* rtc hr 0-23 */ | ||
147 | tm->tm_mday = bcd2bin(rxbuf[3] & 0x3F); | ||
148 | tm->tm_wday = rxbuf[4] & 0x07; | ||
149 | tm->tm_mon = bcd2bin(rxbuf[5] & 0x1F) - 1; /* rtc mn 1-12 */ | ||
150 | tm->tm_year = bcd2bin(rxbuf[6]); | ||
151 | if (tm->tm_year < 70) | ||
152 | tm->tm_year += 100; /* assume we are in 1970...2069 */ | ||
153 | |||
154 | dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " | ||
155 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
156 | __func__, | ||
157 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
158 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
159 | |||
160 | /* the clock can give out invalid datetime, but we cannot return | ||
161 | * -EINVAL otherwise hwclock will refuse to set the time on bootup. | ||
162 | */ | ||
163 | if (rtc_valid_tm(tm) < 0) | ||
164 | dev_err(dev, "retrieved date/time is not valid.\n"); | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
170 | { | ||
171 | struct spi_device *spi = to_spi_device(dev); | ||
172 | u8 txbuf[8]; | ||
173 | int ret; | ||
174 | |||
175 | dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " | ||
176 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
177 | __func__, | ||
178 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
179 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
180 | |||
181 | /* Stop the counter first */ | ||
182 | txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1; | ||
183 | txbuf[1] = 0x20; | ||
184 | ret = spi_write(spi, txbuf, 2); | ||
185 | if (ret < 0) | ||
186 | return ret; | ||
187 | pcf2123_delay_trec(); | ||
188 | |||
189 | /* Set the new time */ | ||
190 | txbuf[0] = PCF2123_WRITE | PCF2123_REG_SC; | ||
191 | txbuf[1] = bin2bcd(tm->tm_sec & 0x7F); | ||
192 | txbuf[2] = bin2bcd(tm->tm_min & 0x7F); | ||
193 | txbuf[3] = bin2bcd(tm->tm_hour & 0x3F); | ||
194 | txbuf[4] = bin2bcd(tm->tm_mday & 0x3F); | ||
195 | txbuf[5] = tm->tm_wday & 0x07; | ||
196 | txbuf[6] = bin2bcd((tm->tm_mon + 1) & 0x1F); /* rtc mn 1-12 */ | ||
197 | txbuf[7] = bin2bcd(tm->tm_year < 100 ? tm->tm_year : tm->tm_year - 100); | ||
198 | |||
199 | ret = spi_write(spi, txbuf, sizeof(txbuf)); | ||
200 | if (ret < 0) | ||
201 | return ret; | ||
202 | pcf2123_delay_trec(); | ||
203 | |||
204 | /* Start the counter */ | ||
205 | txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1; | ||
206 | txbuf[1] = 0x00; | ||
207 | ret = spi_write(spi, txbuf, 2); | ||
208 | if (ret < 0) | ||
209 | return ret; | ||
210 | pcf2123_delay_trec(); | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static const struct rtc_class_ops pcf2123_rtc_ops = { | ||
216 | .read_time = pcf2123_rtc_read_time, | ||
217 | .set_time = pcf2123_rtc_set_time, | ||
218 | }; | ||
219 | |||
220 | static int __devinit pcf2123_probe(struct spi_device *spi) | ||
221 | { | ||
222 | struct rtc_device *rtc; | ||
223 | struct pcf2123_plat_data *pdata; | ||
224 | u8 txbuf[2], rxbuf[2]; | ||
225 | int ret, i; | ||
226 | |||
227 | pdata = kzalloc(sizeof(struct pcf2123_plat_data), GFP_KERNEL); | ||
228 | if (!pdata) | ||
229 | return -ENOMEM; | ||
230 | spi->dev.platform_data = pdata; | ||
231 | |||
232 | /* Send a software reset command */ | ||
233 | txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1; | ||
234 | txbuf[1] = 0x58; | ||
235 | dev_dbg(&spi->dev, "resetting RTC (0x%02X 0x%02X)\n", | ||
236 | txbuf[0], txbuf[1]); | ||
237 | ret = spi_write(spi, txbuf, 2 * sizeof(u8)); | ||
238 | if (ret < 0) | ||
239 | goto kfree_exit; | ||
240 | pcf2123_delay_trec(); | ||
241 | |||
242 | /* Stop the counter */ | ||
243 | txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1; | ||
244 | txbuf[1] = 0x20; | ||
245 | dev_dbg(&spi->dev, "stopping RTC (0x%02X 0x%02X)\n", | ||
246 | txbuf[0], txbuf[1]); | ||
247 | ret = spi_write(spi, txbuf, 2 * sizeof(u8)); | ||
248 | if (ret < 0) | ||
249 | goto kfree_exit; | ||
250 | pcf2123_delay_trec(); | ||
251 | |||
252 | /* See if the counter was actually stopped */ | ||
253 | txbuf[0] = PCF2123_READ | PCF2123_REG_CTRL1; | ||
254 | dev_dbg(&spi->dev, "checking for presence of RTC (0x%02X)\n", | ||
255 | txbuf[0]); | ||
256 | ret = spi_write_then_read(spi, txbuf, 1 * sizeof(u8), | ||
257 | rxbuf, 2 * sizeof(u8)); | ||
258 | dev_dbg(&spi->dev, "received data from RTC (0x%02X 0x%02X)\n", | ||
259 | rxbuf[0], rxbuf[1]); | ||
260 | if (ret < 0) | ||
261 | goto kfree_exit; | ||
262 | pcf2123_delay_trec(); | ||
263 | |||
264 | if (!(rxbuf[0] & 0x20)) { | ||
265 | dev_err(&spi->dev, "chip not found\n"); | ||
266 | goto kfree_exit; | ||
267 | } | ||
268 | |||
269 | dev_info(&spi->dev, "chip found, driver version " DRV_VERSION "\n"); | ||
270 | dev_info(&spi->dev, "spiclk %u KHz.\n", | ||
271 | (spi->max_speed_hz + 500) / 1000); | ||
272 | |||
273 | /* Start the counter */ | ||
274 | txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1; | ||
275 | txbuf[1] = 0x00; | ||
276 | ret = spi_write(spi, txbuf, sizeof(txbuf)); | ||
277 | if (ret < 0) | ||
278 | goto kfree_exit; | ||
279 | pcf2123_delay_trec(); | ||
280 | |||
281 | /* Finalize the initialization */ | ||
282 | rtc = rtc_device_register(pcf2123_driver.driver.name, &spi->dev, | ||
283 | &pcf2123_rtc_ops, THIS_MODULE); | ||
284 | |||
285 | if (IS_ERR(rtc)) { | ||
286 | dev_err(&spi->dev, "failed to register.\n"); | ||
287 | ret = PTR_ERR(rtc); | ||
288 | goto kfree_exit; | ||
289 | } | ||
290 | |||
291 | pdata->rtc = rtc; | ||
292 | |||
293 | for (i = 0; i < 16; i++) { | ||
294 | sprintf(pdata->regs[i].name, "%1x", i); | ||
295 | pdata->regs[i].attr.attr.mode = S_IRUGO | S_IWUSR; | ||
296 | pdata->regs[i].attr.attr.name = pdata->regs[i].name; | ||
297 | pdata->regs[i].attr.show = pcf2123_show; | ||
298 | pdata->regs[i].attr.store = pcf2123_store; | ||
299 | ret = device_create_file(&spi->dev, &pdata->regs[i].attr); | ||
300 | if (ret) { | ||
301 | dev_err(&spi->dev, "Unable to create sysfs %s\n", | ||
302 | pdata->regs[i].name); | ||
303 | goto sysfs_exit; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | return 0; | ||
308 | |||
309 | sysfs_exit: | ||
310 | for (i--; i >= 0; i--) | ||
311 | device_remove_file(&spi->dev, &pdata->regs[i].attr); | ||
312 | |||
313 | kfree_exit: | ||
314 | kfree(pdata); | ||
315 | spi->dev.platform_data = NULL; | ||
316 | return ret; | ||
317 | } | ||
318 | |||
319 | static int __devexit pcf2123_remove(struct spi_device *spi) | ||
320 | { | ||
321 | struct pcf2123_plat_data *pdata = spi->dev.platform_data; | ||
322 | int i; | ||
323 | |||
324 | if (pdata) { | ||
325 | struct rtc_device *rtc = pdata->rtc; | ||
326 | |||
327 | if (rtc) | ||
328 | rtc_device_unregister(rtc); | ||
329 | for (i = 0; i < 16; i++) | ||
330 | if (pdata->regs[i].name[0]) | ||
331 | device_remove_file(&spi->dev, | ||
332 | &pdata->regs[i].attr); | ||
333 | kfree(pdata); | ||
334 | } | ||
335 | |||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | static struct spi_driver pcf2123_driver = { | ||
340 | .driver = { | ||
341 | .name = "rtc-pcf2123", | ||
342 | .bus = &spi_bus_type, | ||
343 | .owner = THIS_MODULE, | ||
344 | }, | ||
345 | .probe = pcf2123_probe, | ||
346 | .remove = __devexit_p(pcf2123_remove), | ||
347 | }; | ||
348 | |||
349 | static int __init pcf2123_init(void) | ||
350 | { | ||
351 | return spi_register_driver(&pcf2123_driver); | ||
352 | } | ||
353 | |||
354 | static void __exit pcf2123_exit(void) | ||
355 | { | ||
356 | spi_unregister_driver(&pcf2123_driver); | ||
357 | } | ||
358 | |||
359 | MODULE_AUTHOR("Chris Verges <chrisv@cyberswitching.com>"); | ||
360 | MODULE_DESCRIPTION("NXP PCF2123 RTC driver"); | ||
361 | MODULE_LICENSE("GPL"); | ||
362 | MODULE_VERSION(DRV_VERSION); | ||
363 | |||
364 | module_init(pcf2123_init); | ||
365 | module_exit(pcf2123_exit); | ||
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c index f4dd87e29075..16edf94ab42f 100644 --- a/drivers/rtc/rtc-pcf50633.c +++ b/drivers/rtc/rtc-pcf50633.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
21 | #include <linux/slab.h> | ||
21 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
22 | #include <linux/rtc.h> | 23 | #include <linux/rtc.h> |
23 | #include <linux/bcd.h> | 24 | #include <linux/bcd.h> |
@@ -58,6 +59,7 @@ struct pcf50633_time { | |||
58 | struct pcf50633_rtc { | 59 | struct pcf50633_rtc { |
59 | int alarm_enabled; | 60 | int alarm_enabled; |
60 | int second_enabled; | 61 | int second_enabled; |
62 | int alarm_pending; | ||
61 | 63 | ||
62 | struct pcf50633 *pcf; | 64 | struct pcf50633 *pcf; |
63 | struct rtc_device *rtc_dev; | 65 | struct rtc_device *rtc_dev; |
@@ -70,7 +72,7 @@ static void pcf2rtc_time(struct rtc_time *rtc, struct pcf50633_time *pcf) | |||
70 | rtc->tm_hour = bcd2bin(pcf->time[PCF50633_TI_HOUR]); | 72 | rtc->tm_hour = bcd2bin(pcf->time[PCF50633_TI_HOUR]); |
71 | rtc->tm_wday = bcd2bin(pcf->time[PCF50633_TI_WKDAY]); | 73 | rtc->tm_wday = bcd2bin(pcf->time[PCF50633_TI_WKDAY]); |
72 | rtc->tm_mday = bcd2bin(pcf->time[PCF50633_TI_DAY]); | 74 | rtc->tm_mday = bcd2bin(pcf->time[PCF50633_TI_DAY]); |
73 | rtc->tm_mon = bcd2bin(pcf->time[PCF50633_TI_MONTH]); | 75 | rtc->tm_mon = bcd2bin(pcf->time[PCF50633_TI_MONTH]) - 1; |
74 | rtc->tm_year = bcd2bin(pcf->time[PCF50633_TI_YEAR]) + 100; | 76 | rtc->tm_year = bcd2bin(pcf->time[PCF50633_TI_YEAR]) + 100; |
75 | } | 77 | } |
76 | 78 | ||
@@ -81,7 +83,7 @@ static void rtc2pcf_time(struct pcf50633_time *pcf, struct rtc_time *rtc) | |||
81 | pcf->time[PCF50633_TI_HOUR] = bin2bcd(rtc->tm_hour); | 83 | pcf->time[PCF50633_TI_HOUR] = bin2bcd(rtc->tm_hour); |
82 | pcf->time[PCF50633_TI_WKDAY] = bin2bcd(rtc->tm_wday); | 84 | pcf->time[PCF50633_TI_WKDAY] = bin2bcd(rtc->tm_wday); |
83 | pcf->time[PCF50633_TI_DAY] = bin2bcd(rtc->tm_mday); | 85 | pcf->time[PCF50633_TI_DAY] = bin2bcd(rtc->tm_mday); |
84 | pcf->time[PCF50633_TI_MONTH] = bin2bcd(rtc->tm_mon); | 86 | pcf->time[PCF50633_TI_MONTH] = bin2bcd(rtc->tm_mon + 1); |
85 | pcf->time[PCF50633_TI_YEAR] = bin2bcd(rtc->tm_year % 100); | 87 | pcf->time[PCF50633_TI_YEAR] = bin2bcd(rtc->tm_year % 100); |
86 | } | 88 | } |
87 | 89 | ||
@@ -209,6 +211,7 @@ static int pcf50633_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
209 | rtc = dev_get_drvdata(dev); | 211 | rtc = dev_get_drvdata(dev); |
210 | 212 | ||
211 | alrm->enabled = rtc->alarm_enabled; | 213 | alrm->enabled = rtc->alarm_enabled; |
214 | alrm->pending = rtc->alarm_pending; | ||
212 | 215 | ||
213 | ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSCA, | 216 | ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSCA, |
214 | PCF50633_TI_EXTENT, &pcf_tm.time[0]); | 217 | PCF50633_TI_EXTENT, &pcf_tm.time[0]); |
@@ -244,9 +247,12 @@ static int pcf50633_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
244 | /* Returns 0 on success */ | 247 | /* Returns 0 on success */ |
245 | ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSCA, | 248 | ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSCA, |
246 | PCF50633_TI_EXTENT, &pcf_tm.time[0]); | 249 | PCF50633_TI_EXTENT, &pcf_tm.time[0]); |
250 | if (!alrm->enabled) | ||
251 | rtc->alarm_pending = 0; | ||
247 | 252 | ||
248 | if (!alarm_masked) | 253 | if (!alarm_masked || alrm->enabled) |
249 | pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); | 254 | pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); |
255 | rtc->alarm_enabled = alrm->enabled; | ||
250 | 256 | ||
251 | return ret; | 257 | return ret; |
252 | } | 258 | } |
@@ -267,6 +273,7 @@ static void pcf50633_rtc_irq(int irq, void *data) | |||
267 | switch (irq) { | 273 | switch (irq) { |
268 | case PCF50633_IRQ_ALARM: | 274 | case PCF50633_IRQ_ALARM: |
269 | rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); | 275 | rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); |
276 | rtc->alarm_pending = 1; | ||
270 | break; | 277 | break; |
271 | case PCF50633_IRQ_SECOND: | 278 | case PCF50633_IRQ_SECOND: |
272 | rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF); | 279 | rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF); |
@@ -276,23 +283,21 @@ static void pcf50633_rtc_irq(int irq, void *data) | |||
276 | 283 | ||
277 | static int __devinit pcf50633_rtc_probe(struct platform_device *pdev) | 284 | static int __devinit pcf50633_rtc_probe(struct platform_device *pdev) |
278 | { | 285 | { |
279 | struct pcf50633_subdev_pdata *pdata; | ||
280 | struct pcf50633_rtc *rtc; | 286 | struct pcf50633_rtc *rtc; |
281 | 287 | ||
282 | |||
283 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | 288 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); |
284 | if (!rtc) | 289 | if (!rtc) |
285 | return -ENOMEM; | 290 | return -ENOMEM; |
286 | 291 | ||
287 | pdata = pdev->dev.platform_data; | 292 | rtc->pcf = dev_to_pcf50633(pdev->dev.parent); |
288 | rtc->pcf = pdata->pcf; | ||
289 | platform_set_drvdata(pdev, rtc); | 293 | platform_set_drvdata(pdev, rtc); |
290 | rtc->rtc_dev = rtc_device_register("pcf50633-rtc", &pdev->dev, | 294 | rtc->rtc_dev = rtc_device_register("pcf50633-rtc", &pdev->dev, |
291 | &pcf50633_rtc_ops, THIS_MODULE); | 295 | &pcf50633_rtc_ops, THIS_MODULE); |
292 | 296 | ||
293 | if (IS_ERR(rtc->rtc_dev)) { | 297 | if (IS_ERR(rtc->rtc_dev)) { |
298 | int ret = PTR_ERR(rtc->rtc_dev); | ||
294 | kfree(rtc); | 299 | kfree(rtc); |
295 | return PTR_ERR(rtc->rtc_dev); | 300 | return ret; |
296 | } | 301 | } |
297 | 302 | ||
298 | pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_ALARM, | 303 | pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_ALARM, |
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index b725913ccbe8..b42c0c679266 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/bcd.h> | 18 | #include <linux/bcd.h> |
19 | #include <linux/rtc.h> | 19 | #include <linux/rtc.h> |
20 | #include <linux/slab.h> | ||
20 | 21 | ||
21 | #define DRV_VERSION "0.4.3" | 22 | #define DRV_VERSION "0.4.3" |
22 | 23 | ||
@@ -171,14 +172,6 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
171 | return 0; | 172 | return 0; |
172 | } | 173 | } |
173 | 174 | ||
174 | struct pcf8563_limit | ||
175 | { | ||
176 | unsigned char reg; | ||
177 | unsigned char mask; | ||
178 | unsigned char min; | ||
179 | unsigned char max; | ||
180 | }; | ||
181 | |||
182 | static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) | 175 | static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) |
183 | { | 176 | { |
184 | return pcf8563_get_datetime(to_i2c_client(dev), tm); | 177 | return pcf8563_get_datetime(to_i2c_client(dev), tm); |
@@ -212,6 +205,8 @@ static int pcf8563_probe(struct i2c_client *client, | |||
212 | 205 | ||
213 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | 206 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
214 | 207 | ||
208 | i2c_set_clientdata(client, pcf8563); | ||
209 | |||
215 | pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name, | 210 | pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name, |
216 | &client->dev, &pcf8563_rtc_ops, THIS_MODULE); | 211 | &client->dev, &pcf8563_rtc_ops, THIS_MODULE); |
217 | 212 | ||
@@ -220,8 +215,6 @@ static int pcf8563_probe(struct i2c_client *client, | |||
220 | goto exit_kfree; | 215 | goto exit_kfree; |
221 | } | 216 | } |
222 | 217 | ||
223 | i2c_set_clientdata(client, pcf8563); | ||
224 | |||
225 | return 0; | 218 | return 0; |
226 | 219 | ||
227 | exit_kfree: | 220 | exit_kfree: |
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index 7d33cda3f8f6..2d201afead3b 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c | |||
@@ -277,6 +277,8 @@ static int pcf8583_probe(struct i2c_client *client, | |||
277 | if (!pcf8583) | 277 | if (!pcf8583) |
278 | return -ENOMEM; | 278 | return -ENOMEM; |
279 | 279 | ||
280 | i2c_set_clientdata(client, pcf8583); | ||
281 | |||
280 | pcf8583->rtc = rtc_device_register(pcf8583_driver.driver.name, | 282 | pcf8583->rtc = rtc_device_register(pcf8583_driver.driver.name, |
281 | &client->dev, &pcf8583_rtc_ops, THIS_MODULE); | 283 | &client->dev, &pcf8583_rtc_ops, THIS_MODULE); |
282 | 284 | ||
@@ -285,7 +287,6 @@ static int pcf8583_probe(struct i2c_client *client, | |||
285 | goto exit_kfree; | 287 | goto exit_kfree; |
286 | } | 288 | } |
287 | 289 | ||
288 | i2c_set_clientdata(client, pcf8583); | ||
289 | return 0; | 290 | return 0; |
290 | 291 | ||
291 | exit_kfree: | 292 | exit_kfree: |
diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c index 457231bb1029..bbdb2f02798a 100644 --- a/drivers/rtc/rtc-pl030.c +++ b/drivers/rtc/rtc-pl030.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/amba/bus.h> | 14 | #include <linux/amba/bus.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/slab.h> | ||
16 | 17 | ||
17 | #define RTC_DR (0) | 18 | #define RTC_DR (0) |
18 | #define RTC_MR (4) | 19 | #define RTC_MR (4) |
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index f41873f98f66..b7a6690e5b35 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c | |||
@@ -7,6 +7,9 @@ | |||
7 | * | 7 | * |
8 | * Copyright 2006 (c) MontaVista Software, Inc. | 8 | * Copyright 2006 (c) MontaVista Software, Inc. |
9 | * | 9 | * |
10 | * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> | ||
11 | * Copyright 2010 (c) ST-Ericsson AB | ||
12 | * | ||
10 | * This program is free software; you can redistribute it and/or | 13 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 14 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 15 | * as published by the Free Software Foundation; either version |
@@ -18,6 +21,9 @@ | |||
18 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
19 | #include <linux/amba/bus.h> | 22 | #include <linux/amba/bus.h> |
20 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/bcd.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/slab.h> | ||
21 | 27 | ||
22 | /* | 28 | /* |
23 | * Register definitions | 29 | * Register definitions |
@@ -30,42 +36,214 @@ | |||
30 | #define RTC_RIS 0x14 /* Raw interrupt status register */ | 36 | #define RTC_RIS 0x14 /* Raw interrupt status register */ |
31 | #define RTC_MIS 0x18 /* Masked interrupt status register */ | 37 | #define RTC_MIS 0x18 /* Masked interrupt status register */ |
32 | #define RTC_ICR 0x1c /* Interrupt clear register */ | 38 | #define RTC_ICR 0x1c /* Interrupt clear register */ |
39 | /* ST variants have additional timer functionality */ | ||
40 | #define RTC_TDR 0x20 /* Timer data read register */ | ||
41 | #define RTC_TLR 0x24 /* Timer data load register */ | ||
42 | #define RTC_TCR 0x28 /* Timer control register */ | ||
43 | #define RTC_YDR 0x30 /* Year data read register */ | ||
44 | #define RTC_YMR 0x34 /* Year match register */ | ||
45 | #define RTC_YLR 0x38 /* Year data load register */ | ||
46 | |||
47 | #define RTC_CR_CWEN (1 << 26) /* Clockwatch enable bit */ | ||
48 | |||
49 | #define RTC_TCR_EN (1 << 1) /* Periodic timer enable bit */ | ||
50 | |||
51 | /* Common bit definitions for Interrupt status and control registers */ | ||
52 | #define RTC_BIT_AI (1 << 0) /* Alarm interrupt bit */ | ||
53 | #define RTC_BIT_PI (1 << 1) /* Periodic interrupt bit. ST variants only. */ | ||
54 | |||
55 | /* Common bit definations for ST v2 for reading/writing time */ | ||
56 | #define RTC_SEC_SHIFT 0 | ||
57 | #define RTC_SEC_MASK (0x3F << RTC_SEC_SHIFT) /* Second [0-59] */ | ||
58 | #define RTC_MIN_SHIFT 6 | ||
59 | #define RTC_MIN_MASK (0x3F << RTC_MIN_SHIFT) /* Minute [0-59] */ | ||
60 | #define RTC_HOUR_SHIFT 12 | ||
61 | #define RTC_HOUR_MASK (0x1F << RTC_HOUR_SHIFT) /* Hour [0-23] */ | ||
62 | #define RTC_WDAY_SHIFT 17 | ||
63 | #define RTC_WDAY_MASK (0x7 << RTC_WDAY_SHIFT) /* Day of Week [1-7] 1=Sunday */ | ||
64 | #define RTC_MDAY_SHIFT 20 | ||
65 | #define RTC_MDAY_MASK (0x1F << RTC_MDAY_SHIFT) /* Day of Month [1-31] */ | ||
66 | #define RTC_MON_SHIFT 25 | ||
67 | #define RTC_MON_MASK (0xF << RTC_MON_SHIFT) /* Month [1-12] 1=January */ | ||
68 | |||
69 | #define RTC_TIMER_FREQ 32768 | ||
33 | 70 | ||
34 | struct pl031_local { | 71 | struct pl031_local { |
35 | struct rtc_device *rtc; | 72 | struct rtc_device *rtc; |
36 | void __iomem *base; | 73 | void __iomem *base; |
74 | u8 hw_designer; | ||
75 | u8 hw_revision:4; | ||
37 | }; | 76 | }; |
38 | 77 | ||
39 | static irqreturn_t pl031_interrupt(int irq, void *dev_id) | 78 | static int pl031_alarm_irq_enable(struct device *dev, |
79 | unsigned int enabled) | ||
40 | { | 80 | { |
41 | struct rtc_device *rtc = dev_id; | 81 | struct pl031_local *ldata = dev_get_drvdata(dev); |
82 | unsigned long imsc; | ||
83 | |||
84 | /* Clear any pending alarm interrupts. */ | ||
85 | writel(RTC_BIT_AI, ldata->base + RTC_ICR); | ||
86 | |||
87 | imsc = readl(ldata->base + RTC_IMSC); | ||
42 | 88 | ||
43 | rtc_update_irq(rtc, 1, RTC_AF); | 89 | if (enabled == 1) |
90 | writel(imsc | RTC_BIT_AI, ldata->base + RTC_IMSC); | ||
91 | else | ||
92 | writel(imsc & ~RTC_BIT_AI, ldata->base + RTC_IMSC); | ||
44 | 93 | ||
45 | return IRQ_HANDLED; | 94 | return 0; |
46 | } | 95 | } |
47 | 96 | ||
48 | static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 97 | /* |
98 | * Convert Gregorian date to ST v2 RTC format. | ||
99 | */ | ||
100 | static int pl031_stv2_tm_to_time(struct device *dev, | ||
101 | struct rtc_time *tm, unsigned long *st_time, | ||
102 | unsigned long *bcd_year) | ||
49 | { | 103 | { |
104 | int year = tm->tm_year + 1900; | ||
105 | int wday = tm->tm_wday; | ||
106 | |||
107 | /* wday masking is not working in hardware so wday must be valid */ | ||
108 | if (wday < -1 || wday > 6) { | ||
109 | dev_err(dev, "invalid wday value %d\n", tm->tm_wday); | ||
110 | return -EINVAL; | ||
111 | } else if (wday == -1) { | ||
112 | /* wday is not provided, calculate it here */ | ||
113 | unsigned long time; | ||
114 | struct rtc_time calc_tm; | ||
115 | |||
116 | rtc_tm_to_time(tm, &time); | ||
117 | rtc_time_to_tm(time, &calc_tm); | ||
118 | wday = calc_tm.tm_wday; | ||
119 | } | ||
120 | |||
121 | *bcd_year = (bin2bcd(year % 100) | bin2bcd(year / 100) << 8); | ||
122 | |||
123 | *st_time = ((tm->tm_mon + 1) << RTC_MON_SHIFT) | ||
124 | | (tm->tm_mday << RTC_MDAY_SHIFT) | ||
125 | | ((wday + 1) << RTC_WDAY_SHIFT) | ||
126 | | (tm->tm_hour << RTC_HOUR_SHIFT) | ||
127 | | (tm->tm_min << RTC_MIN_SHIFT) | ||
128 | | (tm->tm_sec << RTC_SEC_SHIFT); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * Convert ST v2 RTC format to Gregorian date. | ||
135 | */ | ||
136 | static int pl031_stv2_time_to_tm(unsigned long st_time, unsigned long bcd_year, | ||
137 | struct rtc_time *tm) | ||
138 | { | ||
139 | tm->tm_year = bcd2bin(bcd_year) + (bcd2bin(bcd_year >> 8) * 100); | ||
140 | tm->tm_mon = ((st_time & RTC_MON_MASK) >> RTC_MON_SHIFT) - 1; | ||
141 | tm->tm_mday = ((st_time & RTC_MDAY_MASK) >> RTC_MDAY_SHIFT); | ||
142 | tm->tm_wday = ((st_time & RTC_WDAY_MASK) >> RTC_WDAY_SHIFT) - 1; | ||
143 | tm->tm_hour = ((st_time & RTC_HOUR_MASK) >> RTC_HOUR_SHIFT); | ||
144 | tm->tm_min = ((st_time & RTC_MIN_MASK) >> RTC_MIN_SHIFT); | ||
145 | tm->tm_sec = ((st_time & RTC_SEC_MASK) >> RTC_SEC_SHIFT); | ||
146 | |||
147 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); | ||
148 | tm->tm_year -= 1900; | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int pl031_stv2_read_time(struct device *dev, struct rtc_time *tm) | ||
154 | { | ||
155 | struct pl031_local *ldata = dev_get_drvdata(dev); | ||
156 | |||
157 | pl031_stv2_time_to_tm(readl(ldata->base + RTC_DR), | ||
158 | readl(ldata->base + RTC_YDR), tm); | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static int pl031_stv2_set_time(struct device *dev, struct rtc_time *tm) | ||
164 | { | ||
165 | unsigned long time; | ||
166 | unsigned long bcd_year; | ||
50 | struct pl031_local *ldata = dev_get_drvdata(dev); | 167 | struct pl031_local *ldata = dev_get_drvdata(dev); |
168 | int ret; | ||
51 | 169 | ||
52 | switch (cmd) { | 170 | ret = pl031_stv2_tm_to_time(dev, tm, &time, &bcd_year); |
53 | case RTC_AIE_OFF: | 171 | if (ret == 0) { |
54 | __raw_writel(1, ldata->base + RTC_MIS); | 172 | writel(bcd_year, ldata->base + RTC_YLR); |
55 | return 0; | 173 | writel(time, ldata->base + RTC_LR); |
56 | case RTC_AIE_ON: | ||
57 | __raw_writel(0, ldata->base + RTC_MIS); | ||
58 | return 0; | ||
59 | } | 174 | } |
60 | 175 | ||
61 | return -ENOIOCTLCMD; | 176 | return ret; |
177 | } | ||
178 | |||
179 | static int pl031_stv2_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
180 | { | ||
181 | struct pl031_local *ldata = dev_get_drvdata(dev); | ||
182 | int ret; | ||
183 | |||
184 | ret = pl031_stv2_time_to_tm(readl(ldata->base + RTC_MR), | ||
185 | readl(ldata->base + RTC_YMR), &alarm->time); | ||
186 | |||
187 | alarm->pending = readl(ldata->base + RTC_RIS) & RTC_BIT_AI; | ||
188 | alarm->enabled = readl(ldata->base + RTC_IMSC) & RTC_BIT_AI; | ||
189 | |||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | static int pl031_stv2_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
194 | { | ||
195 | struct pl031_local *ldata = dev_get_drvdata(dev); | ||
196 | unsigned long time; | ||
197 | unsigned long bcd_year; | ||
198 | int ret; | ||
199 | |||
200 | /* At the moment, we can only deal with non-wildcarded alarm times. */ | ||
201 | ret = rtc_valid_tm(&alarm->time); | ||
202 | if (ret == 0) { | ||
203 | ret = pl031_stv2_tm_to_time(dev, &alarm->time, | ||
204 | &time, &bcd_year); | ||
205 | if (ret == 0) { | ||
206 | writel(bcd_year, ldata->base + RTC_YMR); | ||
207 | writel(time, ldata->base + RTC_MR); | ||
208 | |||
209 | pl031_alarm_irq_enable(dev, alarm->enabled); | ||
210 | } | ||
211 | } | ||
212 | |||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | static irqreturn_t pl031_interrupt(int irq, void *dev_id) | ||
217 | { | ||
218 | struct pl031_local *ldata = dev_id; | ||
219 | unsigned long rtcmis; | ||
220 | unsigned long events = 0; | ||
221 | |||
222 | rtcmis = readl(ldata->base + RTC_MIS); | ||
223 | if (rtcmis) { | ||
224 | writel(rtcmis, ldata->base + RTC_ICR); | ||
225 | |||
226 | if (rtcmis & RTC_BIT_AI) | ||
227 | events |= (RTC_AF | RTC_IRQF); | ||
228 | |||
229 | /* Timer interrupt is only available in ST variants */ | ||
230 | if ((rtcmis & RTC_BIT_PI) && | ||
231 | (ldata->hw_designer == AMBA_VENDOR_ST)) | ||
232 | events |= (RTC_PF | RTC_IRQF); | ||
233 | |||
234 | rtc_update_irq(ldata->rtc, 1, events); | ||
235 | |||
236 | return IRQ_HANDLED; | ||
237 | } | ||
238 | |||
239 | return IRQ_NONE; | ||
62 | } | 240 | } |
63 | 241 | ||
64 | static int pl031_read_time(struct device *dev, struct rtc_time *tm) | 242 | static int pl031_read_time(struct device *dev, struct rtc_time *tm) |
65 | { | 243 | { |
66 | struct pl031_local *ldata = dev_get_drvdata(dev); | 244 | struct pl031_local *ldata = dev_get_drvdata(dev); |
67 | 245 | ||
68 | rtc_time_to_tm(__raw_readl(ldata->base + RTC_DR), tm); | 246 | rtc_time_to_tm(readl(ldata->base + RTC_DR), tm); |
69 | 247 | ||
70 | return 0; | 248 | return 0; |
71 | } | 249 | } |
@@ -74,20 +252,24 @@ static int pl031_set_time(struct device *dev, struct rtc_time *tm) | |||
74 | { | 252 | { |
75 | unsigned long time; | 253 | unsigned long time; |
76 | struct pl031_local *ldata = dev_get_drvdata(dev); | 254 | struct pl031_local *ldata = dev_get_drvdata(dev); |
255 | int ret; | ||
77 | 256 | ||
78 | rtc_tm_to_time(tm, &time); | 257 | ret = rtc_tm_to_time(tm, &time); |
79 | __raw_writel(time, ldata->base + RTC_LR); | ||
80 | 258 | ||
81 | return 0; | 259 | if (ret == 0) |
260 | writel(time, ldata->base + RTC_LR); | ||
261 | |||
262 | return ret; | ||
82 | } | 263 | } |
83 | 264 | ||
84 | static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 265 | static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
85 | { | 266 | { |
86 | struct pl031_local *ldata = dev_get_drvdata(dev); | 267 | struct pl031_local *ldata = dev_get_drvdata(dev); |
87 | 268 | ||
88 | rtc_time_to_tm(__raw_readl(ldata->base + RTC_MR), &alarm->time); | 269 | rtc_time_to_tm(readl(ldata->base + RTC_MR), &alarm->time); |
89 | alarm->pending = __raw_readl(ldata->base + RTC_RIS); | 270 | |
90 | alarm->enabled = __raw_readl(ldata->base + RTC_IMSC); | 271 | alarm->pending = readl(ldata->base + RTC_RIS) & RTC_BIT_AI; |
272 | alarm->enabled = readl(ldata->base + RTC_IMSC) & RTC_BIT_AI; | ||
91 | 273 | ||
92 | return 0; | 274 | return 0; |
93 | } | 275 | } |
@@ -96,22 +278,71 @@ static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
96 | { | 278 | { |
97 | struct pl031_local *ldata = dev_get_drvdata(dev); | 279 | struct pl031_local *ldata = dev_get_drvdata(dev); |
98 | unsigned long time; | 280 | unsigned long time; |
281 | int ret; | ||
282 | |||
283 | /* At the moment, we can only deal with non-wildcarded alarm times. */ | ||
284 | ret = rtc_valid_tm(&alarm->time); | ||
285 | if (ret == 0) { | ||
286 | ret = rtc_tm_to_time(&alarm->time, &time); | ||
287 | if (ret == 0) { | ||
288 | writel(time, ldata->base + RTC_MR); | ||
289 | pl031_alarm_irq_enable(dev, alarm->enabled); | ||
290 | } | ||
291 | } | ||
292 | |||
293 | return ret; | ||
294 | } | ||
295 | |||
296 | /* Periodic interrupt is only available in ST variants. */ | ||
297 | static int pl031_irq_set_state(struct device *dev, int enabled) | ||
298 | { | ||
299 | struct pl031_local *ldata = dev_get_drvdata(dev); | ||
300 | |||
301 | if (enabled == 1) { | ||
302 | /* Clear any pending timer interrupt. */ | ||
303 | writel(RTC_BIT_PI, ldata->base + RTC_ICR); | ||
304 | |||
305 | writel(readl(ldata->base + RTC_IMSC) | RTC_BIT_PI, | ||
306 | ldata->base + RTC_IMSC); | ||
307 | |||
308 | /* Now start the timer */ | ||
309 | writel(readl(ldata->base + RTC_TCR) | RTC_TCR_EN, | ||
310 | ldata->base + RTC_TCR); | ||
99 | 311 | ||
100 | rtc_tm_to_time(&alarm->time, &time); | 312 | } else { |
313 | writel(readl(ldata->base + RTC_IMSC) & (~RTC_BIT_PI), | ||
314 | ldata->base + RTC_IMSC); | ||
101 | 315 | ||
102 | __raw_writel(time, ldata->base + RTC_MR); | 316 | /* Also stop the timer */ |
103 | __raw_writel(!alarm->enabled, ldata->base + RTC_MIS); | 317 | writel(readl(ldata->base + RTC_TCR) & (~RTC_TCR_EN), |
318 | ldata->base + RTC_TCR); | ||
319 | } | ||
320 | /* Wait at least 1 RTC32 clock cycle to ensure next access | ||
321 | * to RTC_TCR will succeed. | ||
322 | */ | ||
323 | udelay(40); | ||
104 | 324 | ||
105 | return 0; | 325 | return 0; |
106 | } | 326 | } |
107 | 327 | ||
108 | static const struct rtc_class_ops pl031_ops = { | 328 | static int pl031_irq_set_freq(struct device *dev, int freq) |
109 | .ioctl = pl031_ioctl, | 329 | { |
110 | .read_time = pl031_read_time, | 330 | struct pl031_local *ldata = dev_get_drvdata(dev); |
111 | .set_time = pl031_set_time, | 331 | |
112 | .read_alarm = pl031_read_alarm, | 332 | /* Cant set timer if it is already enabled */ |
113 | .set_alarm = pl031_set_alarm, | 333 | if (readl(ldata->base + RTC_TCR) & RTC_TCR_EN) { |
114 | }; | 334 | dev_err(dev, "can't change frequency while timer enabled\n"); |
335 | return -EINVAL; | ||
336 | } | ||
337 | |||
338 | /* If self start bit in RTC_TCR is set timer will start here, | ||
339 | * but we never set that bit. Instead we start the timer when | ||
340 | * set_state is called with enabled == 1. | ||
341 | */ | ||
342 | writel(RTC_TIMER_FREQ / freq, ldata->base + RTC_TLR); | ||
343 | |||
344 | return 0; | ||
345 | } | ||
115 | 346 | ||
116 | static int pl031_remove(struct amba_device *adev) | 347 | static int pl031_remove(struct amba_device *adev) |
117 | { | 348 | { |
@@ -131,18 +362,20 @@ static int pl031_probe(struct amba_device *adev, struct amba_id *id) | |||
131 | { | 362 | { |
132 | int ret; | 363 | int ret; |
133 | struct pl031_local *ldata; | 364 | struct pl031_local *ldata; |
365 | struct rtc_class_ops *ops = id->data; | ||
134 | 366 | ||
135 | ret = amba_request_regions(adev, NULL); | 367 | ret = amba_request_regions(adev, NULL); |
136 | if (ret) | 368 | if (ret) |
137 | goto err_req; | 369 | goto err_req; |
138 | 370 | ||
139 | ldata = kmalloc(sizeof(struct pl031_local), GFP_KERNEL); | 371 | ldata = kzalloc(sizeof(struct pl031_local), GFP_KERNEL); |
140 | if (!ldata) { | 372 | if (!ldata) { |
141 | ret = -ENOMEM; | 373 | ret = -ENOMEM; |
142 | goto out; | 374 | goto out; |
143 | } | 375 | } |
144 | 376 | ||
145 | ldata->base = ioremap(adev->res.start, resource_size(&adev->res)); | 377 | ldata->base = ioremap(adev->res.start, resource_size(&adev->res)); |
378 | |||
146 | if (!ldata->base) { | 379 | if (!ldata->base) { |
147 | ret = -ENOMEM; | 380 | ret = -ENOMEM; |
148 | goto out_no_remap; | 381 | goto out_no_remap; |
@@ -150,24 +383,36 @@ static int pl031_probe(struct amba_device *adev, struct amba_id *id) | |||
150 | 383 | ||
151 | amba_set_drvdata(adev, ldata); | 384 | amba_set_drvdata(adev, ldata); |
152 | 385 | ||
153 | if (request_irq(adev->irq[0], pl031_interrupt, IRQF_DISABLED, | 386 | ldata->hw_designer = amba_manf(adev); |
154 | "rtc-pl031", ldata->rtc)) { | 387 | ldata->hw_revision = amba_rev(adev); |
155 | ret = -EIO; | 388 | |
156 | goto out_no_irq; | 389 | dev_dbg(&adev->dev, "designer ID = 0x%02x\n", ldata->hw_designer); |
157 | } | 390 | dev_dbg(&adev->dev, "revision = 0x%01x\n", ldata->hw_revision); |
391 | |||
392 | /* Enable the clockwatch on ST Variants */ | ||
393 | if ((ldata->hw_designer == AMBA_VENDOR_ST) && | ||
394 | (ldata->hw_revision > 1)) | ||
395 | writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN, | ||
396 | ldata->base + RTC_CR); | ||
158 | 397 | ||
159 | ldata->rtc = rtc_device_register("pl031", &adev->dev, &pl031_ops, | 398 | ldata->rtc = rtc_device_register("pl031", &adev->dev, ops, |
160 | THIS_MODULE); | 399 | THIS_MODULE); |
161 | if (IS_ERR(ldata->rtc)) { | 400 | if (IS_ERR(ldata->rtc)) { |
162 | ret = PTR_ERR(ldata->rtc); | 401 | ret = PTR_ERR(ldata->rtc); |
163 | goto out_no_rtc; | 402 | goto out_no_rtc; |
164 | } | 403 | } |
165 | 404 | ||
405 | if (request_irq(adev->irq[0], pl031_interrupt, | ||
406 | IRQF_DISABLED, "rtc-pl031", ldata)) { | ||
407 | ret = -EIO; | ||
408 | goto out_no_irq; | ||
409 | } | ||
410 | |||
166 | return 0; | 411 | return 0; |
167 | 412 | ||
168 | out_no_rtc: | ||
169 | free_irq(adev->irq[0], ldata->rtc); | ||
170 | out_no_irq: | 413 | out_no_irq: |
414 | rtc_device_unregister(ldata->rtc); | ||
415 | out_no_rtc: | ||
171 | iounmap(ldata->base); | 416 | iounmap(ldata->base); |
172 | amba_set_drvdata(adev, NULL); | 417 | amba_set_drvdata(adev, NULL); |
173 | out_no_remap: | 418 | out_no_remap: |
@@ -175,13 +420,58 @@ out_no_remap: | |||
175 | out: | 420 | out: |
176 | amba_release_regions(adev); | 421 | amba_release_regions(adev); |
177 | err_req: | 422 | err_req: |
423 | |||
178 | return ret; | 424 | return ret; |
179 | } | 425 | } |
180 | 426 | ||
181 | static struct amba_id pl031_ids[] __initdata = { | 427 | /* Operations for the original ARM version */ |
428 | static struct rtc_class_ops arm_pl031_ops = { | ||
429 | .read_time = pl031_read_time, | ||
430 | .set_time = pl031_set_time, | ||
431 | .read_alarm = pl031_read_alarm, | ||
432 | .set_alarm = pl031_set_alarm, | ||
433 | .alarm_irq_enable = pl031_alarm_irq_enable, | ||
434 | }; | ||
435 | |||
436 | /* The First ST derivative */ | ||
437 | static struct rtc_class_ops stv1_pl031_ops = { | ||
438 | .read_time = pl031_read_time, | ||
439 | .set_time = pl031_set_time, | ||
440 | .read_alarm = pl031_read_alarm, | ||
441 | .set_alarm = pl031_set_alarm, | ||
442 | .alarm_irq_enable = pl031_alarm_irq_enable, | ||
443 | .irq_set_state = pl031_irq_set_state, | ||
444 | .irq_set_freq = pl031_irq_set_freq, | ||
445 | }; | ||
446 | |||
447 | /* And the second ST derivative */ | ||
448 | static struct rtc_class_ops stv2_pl031_ops = { | ||
449 | .read_time = pl031_stv2_read_time, | ||
450 | .set_time = pl031_stv2_set_time, | ||
451 | .read_alarm = pl031_stv2_read_alarm, | ||
452 | .set_alarm = pl031_stv2_set_alarm, | ||
453 | .alarm_irq_enable = pl031_alarm_irq_enable, | ||
454 | .irq_set_state = pl031_irq_set_state, | ||
455 | .irq_set_freq = pl031_irq_set_freq, | ||
456 | }; | ||
457 | |||
458 | static struct amba_id pl031_ids[] = { | ||
459 | { | ||
460 | .id = 0x00041031, | ||
461 | .mask = 0x000fffff, | ||
462 | .data = &arm_pl031_ops, | ||
463 | }, | ||
464 | /* ST Micro variants */ | ||
465 | { | ||
466 | .id = 0x00180031, | ||
467 | .mask = 0x00ffffff, | ||
468 | .data = &stv1_pl031_ops, | ||
469 | }, | ||
182 | { | 470 | { |
183 | .id = 0x00041031, | 471 | .id = 0x00280031, |
184 | .mask = 0x000fffff, }, | 472 | .mask = 0x00ffffff, |
473 | .data = &stv2_pl031_ops, | ||
474 | }, | ||
185 | {0, 0}, | 475 | {0, 0}, |
186 | }; | 476 | }; |
187 | 477 | ||
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index bb8cc05605ac..29e867a1aaa8 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
28 | #include <linux/io.h> | 28 | #include <linux/io.h> |
29 | #include <linux/slab.h> | ||
29 | 30 | ||
30 | #include <mach/hardware.h> | 31 | #include <mach/hardware.h> |
31 | 32 | ||
@@ -86,7 +87,6 @@ struct pxa_rtc { | |||
86 | int irq_Alrm; | 87 | int irq_Alrm; |
87 | struct rtc_device *rtc; | 88 | struct rtc_device *rtc; |
88 | spinlock_t lock; /* Protects this structure */ | 89 | spinlock_t lock; /* Protects this structure */ |
89 | struct rtc_time rtc_alarm; | ||
90 | }; | 90 | }; |
91 | 91 | ||
92 | static u32 ryxr_calc(struct rtc_time *tm) | 92 | static u32 ryxr_calc(struct rtc_time *tm) |
@@ -235,32 +235,34 @@ static int pxa_periodic_irq_set_state(struct device *dev, int enabled) | |||
235 | return 0; | 235 | return 0; |
236 | } | 236 | } |
237 | 237 | ||
238 | static int pxa_rtc_ioctl(struct device *dev, unsigned int cmd, | 238 | static int pxa_alarm_irq_enable(struct device *dev, unsigned int enabled) |
239 | unsigned long arg) | ||
240 | { | 239 | { |
241 | struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev); | 240 | struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev); |
242 | int ret = 0; | ||
243 | 241 | ||
244 | spin_lock_irq(&pxa_rtc->lock); | 242 | spin_lock_irq(&pxa_rtc->lock); |
245 | switch (cmd) { | 243 | |
246 | case RTC_AIE_OFF: | 244 | if (enabled) |
247 | rtsr_clear_bits(pxa_rtc, RTSR_RDALE1); | ||
248 | break; | ||
249 | case RTC_AIE_ON: | ||
250 | rtsr_set_bits(pxa_rtc, RTSR_RDALE1); | 245 | rtsr_set_bits(pxa_rtc, RTSR_RDALE1); |
251 | break; | 246 | else |
252 | case RTC_UIE_OFF: | 247 | rtsr_clear_bits(pxa_rtc, RTSR_RDALE1); |
253 | rtsr_clear_bits(pxa_rtc, RTSR_HZE); | 248 | |
254 | break; | 249 | spin_unlock_irq(&pxa_rtc->lock); |
255 | case RTC_UIE_ON: | 250 | return 0; |
251 | } | ||
252 | |||
253 | static int pxa_update_irq_enable(struct device *dev, unsigned int enabled) | ||
254 | { | ||
255 | struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev); | ||
256 | |||
257 | spin_lock_irq(&pxa_rtc->lock); | ||
258 | |||
259 | if (enabled) | ||
256 | rtsr_set_bits(pxa_rtc, RTSR_HZE); | 260 | rtsr_set_bits(pxa_rtc, RTSR_HZE); |
257 | break; | 261 | else |
258 | default: | 262 | rtsr_clear_bits(pxa_rtc, RTSR_HZE); |
259 | ret = -ENOIOCTLCMD; | ||
260 | } | ||
261 | 263 | ||
262 | spin_unlock_irq(&pxa_rtc->lock); | 264 | spin_unlock_irq(&pxa_rtc->lock); |
263 | return ret; | 265 | return 0; |
264 | } | 266 | } |
265 | 267 | ||
266 | static int pxa_rtc_read_time(struct device *dev, struct rtc_time *tm) | 268 | static int pxa_rtc_read_time(struct device *dev, struct rtc_time *tm) |
@@ -339,11 +341,12 @@ static int pxa_rtc_proc(struct device *dev, struct seq_file *seq) | |||
339 | static const struct rtc_class_ops pxa_rtc_ops = { | 341 | static const struct rtc_class_ops pxa_rtc_ops = { |
340 | .open = pxa_rtc_open, | 342 | .open = pxa_rtc_open, |
341 | .release = pxa_rtc_release, | 343 | .release = pxa_rtc_release, |
342 | .ioctl = pxa_rtc_ioctl, | ||
343 | .read_time = pxa_rtc_read_time, | 344 | .read_time = pxa_rtc_read_time, |
344 | .set_time = pxa_rtc_set_time, | 345 | .set_time = pxa_rtc_set_time, |
345 | .read_alarm = pxa_rtc_read_alarm, | 346 | .read_alarm = pxa_rtc_read_alarm, |
346 | .set_alarm = pxa_rtc_set_alarm, | 347 | .set_alarm = pxa_rtc_set_alarm, |
348 | .alarm_irq_enable = pxa_alarm_irq_enable, | ||
349 | .update_irq_enable = pxa_update_irq_enable, | ||
347 | .proc = pxa_rtc_proc, | 350 | .proc = pxa_rtc_proc, |
348 | .irq_set_state = pxa_periodic_irq_set_state, | 351 | .irq_set_state = pxa_periodic_irq_set_state, |
349 | .irq_set_freq = pxa_periodic_irq_set_freq, | 352 | .irq_set_freq = pxa_periodic_irq_set_freq, |
@@ -438,34 +441,37 @@ static int __exit pxa_rtc_remove(struct platform_device *pdev) | |||
438 | } | 441 | } |
439 | 442 | ||
440 | #ifdef CONFIG_PM | 443 | #ifdef CONFIG_PM |
441 | static int pxa_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 444 | static int pxa_rtc_suspend(struct device *dev) |
442 | { | 445 | { |
443 | struct pxa_rtc *pxa_rtc = platform_get_drvdata(pdev); | 446 | struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev); |
444 | 447 | ||
445 | if (device_may_wakeup(&pdev->dev)) | 448 | if (device_may_wakeup(dev)) |
446 | enable_irq_wake(pxa_rtc->irq_Alrm); | 449 | enable_irq_wake(pxa_rtc->irq_Alrm); |
447 | return 0; | 450 | return 0; |
448 | } | 451 | } |
449 | 452 | ||
450 | static int pxa_rtc_resume(struct platform_device *pdev) | 453 | static int pxa_rtc_resume(struct device *dev) |
451 | { | 454 | { |
452 | struct pxa_rtc *pxa_rtc = platform_get_drvdata(pdev); | 455 | struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev); |
453 | 456 | ||
454 | if (device_may_wakeup(&pdev->dev)) | 457 | if (device_may_wakeup(dev)) |
455 | disable_irq_wake(pxa_rtc->irq_Alrm); | 458 | disable_irq_wake(pxa_rtc->irq_Alrm); |
456 | return 0; | 459 | return 0; |
457 | } | 460 | } |
458 | #else | 461 | |
459 | #define pxa_rtc_suspend NULL | 462 | static const struct dev_pm_ops pxa_rtc_pm_ops = { |
460 | #define pxa_rtc_resume NULL | 463 | .suspend = pxa_rtc_suspend, |
464 | .resume = pxa_rtc_resume, | ||
465 | }; | ||
461 | #endif | 466 | #endif |
462 | 467 | ||
463 | static struct platform_driver pxa_rtc_driver = { | 468 | static struct platform_driver pxa_rtc_driver = { |
464 | .remove = __exit_p(pxa_rtc_remove), | 469 | .remove = __exit_p(pxa_rtc_remove), |
465 | .suspend = pxa_rtc_suspend, | ||
466 | .resume = pxa_rtc_resume, | ||
467 | .driver = { | 470 | .driver = { |
468 | .name = "pxa-rtc", | 471 | .name = "pxa-rtc", |
472 | #ifdef CONFIG_PM | ||
473 | .pm = &pxa_rtc_pm_ops, | ||
474 | #endif | ||
469 | }, | 475 | }, |
470 | }; | 476 | }; |
471 | 477 | ||
diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c index 42028f233bef..9beba49c3c5b 100644 --- a/drivers/rtc/rtc-r9701.c +++ b/drivers/rtc/rtc-r9701.c | |||
@@ -174,3 +174,4 @@ module_exit(r9701_exit); | |||
174 | MODULE_DESCRIPTION("r9701 spi RTC driver"); | 174 | MODULE_DESCRIPTION("r9701 spi RTC driver"); |
175 | MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); | 175 | MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); |
176 | MODULE_LICENSE("GPL"); | 176 | MODULE_LICENSE("GPL"); |
177 | MODULE_ALIAS("spi:rtc-r9701"); | ||
diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c new file mode 100644 index 000000000000..36eb66184461 --- /dev/null +++ b/drivers/rtc/rtc-rp5c01.c | |||
@@ -0,0 +1,312 @@ | |||
1 | /* | ||
2 | * Ricoh RP5C01 RTC Driver | ||
3 | * | ||
4 | * Copyright 2009 Geert Uytterhoeven | ||
5 | * | ||
6 | * Based on the A3000 TOD code in arch/m68k/amiga/config.c | ||
7 | * Copyright (C) 1993 Hamish Macdonald | ||
8 | */ | ||
9 | |||
10 | #include <linux/io.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/rtc.h> | ||
15 | #include <linux/slab.h> | ||
16 | |||
17 | |||
18 | enum { | ||
19 | RP5C01_1_SECOND = 0x0, /* MODE 00 */ | ||
20 | RP5C01_10_SECOND = 0x1, /* MODE 00 */ | ||
21 | RP5C01_1_MINUTE = 0x2, /* MODE 00 and MODE 01 */ | ||
22 | RP5C01_10_MINUTE = 0x3, /* MODE 00 and MODE 01 */ | ||
23 | RP5C01_1_HOUR = 0x4, /* MODE 00 and MODE 01 */ | ||
24 | RP5C01_10_HOUR = 0x5, /* MODE 00 and MODE 01 */ | ||
25 | RP5C01_DAY_OF_WEEK = 0x6, /* MODE 00 and MODE 01 */ | ||
26 | RP5C01_1_DAY = 0x7, /* MODE 00 and MODE 01 */ | ||
27 | RP5C01_10_DAY = 0x8, /* MODE 00 and MODE 01 */ | ||
28 | RP5C01_1_MONTH = 0x9, /* MODE 00 */ | ||
29 | RP5C01_10_MONTH = 0xa, /* MODE 00 */ | ||
30 | RP5C01_1_YEAR = 0xb, /* MODE 00 */ | ||
31 | RP5C01_10_YEAR = 0xc, /* MODE 00 */ | ||
32 | |||
33 | RP5C01_12_24_SELECT = 0xa, /* MODE 01 */ | ||
34 | RP5C01_LEAP_YEAR = 0xb, /* MODE 01 */ | ||
35 | |||
36 | RP5C01_MODE = 0xd, /* all modes */ | ||
37 | RP5C01_TEST = 0xe, /* all modes */ | ||
38 | RP5C01_RESET = 0xf, /* all modes */ | ||
39 | }; | ||
40 | |||
41 | #define RP5C01_12_24_SELECT_12 (0 << 0) | ||
42 | #define RP5C01_12_24_SELECT_24 (1 << 0) | ||
43 | |||
44 | #define RP5C01_10_HOUR_AM (0 << 1) | ||
45 | #define RP5C01_10_HOUR_PM (1 << 1) | ||
46 | |||
47 | #define RP5C01_MODE_TIMER_EN (1 << 3) /* timer enable */ | ||
48 | #define RP5C01_MODE_ALARM_EN (1 << 2) /* alarm enable */ | ||
49 | |||
50 | #define RP5C01_MODE_MODE_MASK (3 << 0) | ||
51 | #define RP5C01_MODE_MODE00 (0 << 0) /* time */ | ||
52 | #define RP5C01_MODE_MODE01 (1 << 0) /* alarm, 12h/24h, leap year */ | ||
53 | #define RP5C01_MODE_RAM_BLOCK10 (2 << 0) /* RAM 4 bits x 13 */ | ||
54 | #define RP5C01_MODE_RAM_BLOCK11 (3 << 0) /* RAM 4 bits x 13 */ | ||
55 | |||
56 | #define RP5C01_RESET_1HZ_PULSE (1 << 3) | ||
57 | #define RP5C01_RESET_16HZ_PULSE (1 << 2) | ||
58 | #define RP5C01_RESET_SECOND (1 << 1) /* reset divider stages for */ | ||
59 | /* seconds or smaller units */ | ||
60 | #define RP5C01_RESET_ALARM (1 << 0) /* reset all alarm registers */ | ||
61 | |||
62 | |||
63 | struct rp5c01_priv { | ||
64 | u32 __iomem *regs; | ||
65 | struct rtc_device *rtc; | ||
66 | spinlock_t lock; /* against concurrent RTC/NVRAM access */ | ||
67 | struct bin_attribute nvram_attr; | ||
68 | }; | ||
69 | |||
70 | static inline unsigned int rp5c01_read(struct rp5c01_priv *priv, | ||
71 | unsigned int reg) | ||
72 | { | ||
73 | return __raw_readl(&priv->regs[reg]) & 0xf; | ||
74 | } | ||
75 | |||
76 | static inline void rp5c01_write(struct rp5c01_priv *priv, unsigned int val, | ||
77 | unsigned int reg) | ||
78 | { | ||
79 | return __raw_writel(val, &priv->regs[reg]); | ||
80 | } | ||
81 | |||
82 | static void rp5c01_lock(struct rp5c01_priv *priv) | ||
83 | { | ||
84 | rp5c01_write(priv, RP5C01_MODE_MODE00, RP5C01_MODE); | ||
85 | } | ||
86 | |||
87 | static void rp5c01_unlock(struct rp5c01_priv *priv) | ||
88 | { | ||
89 | rp5c01_write(priv, RP5C01_MODE_TIMER_EN | RP5C01_MODE_MODE01, | ||
90 | RP5C01_MODE); | ||
91 | } | ||
92 | |||
93 | static int rp5c01_read_time(struct device *dev, struct rtc_time *tm) | ||
94 | { | ||
95 | struct rp5c01_priv *priv = dev_get_drvdata(dev); | ||
96 | |||
97 | spin_lock_irq(&priv->lock); | ||
98 | rp5c01_lock(priv); | ||
99 | |||
100 | tm->tm_sec = rp5c01_read(priv, RP5C01_10_SECOND) * 10 + | ||
101 | rp5c01_read(priv, RP5C01_1_SECOND); | ||
102 | tm->tm_min = rp5c01_read(priv, RP5C01_10_MINUTE) * 10 + | ||
103 | rp5c01_read(priv, RP5C01_1_MINUTE); | ||
104 | tm->tm_hour = rp5c01_read(priv, RP5C01_10_HOUR) * 10 + | ||
105 | rp5c01_read(priv, RP5C01_1_HOUR); | ||
106 | tm->tm_mday = rp5c01_read(priv, RP5C01_10_DAY) * 10 + | ||
107 | rp5c01_read(priv, RP5C01_1_DAY); | ||
108 | tm->tm_wday = rp5c01_read(priv, RP5C01_DAY_OF_WEEK); | ||
109 | tm->tm_mon = rp5c01_read(priv, RP5C01_10_MONTH) * 10 + | ||
110 | rp5c01_read(priv, RP5C01_1_MONTH) - 1; | ||
111 | tm->tm_year = rp5c01_read(priv, RP5C01_10_YEAR) * 10 + | ||
112 | rp5c01_read(priv, RP5C01_1_YEAR); | ||
113 | if (tm->tm_year <= 69) | ||
114 | tm->tm_year += 100; | ||
115 | |||
116 | rp5c01_unlock(priv); | ||
117 | spin_unlock_irq(&priv->lock); | ||
118 | |||
119 | return rtc_valid_tm(tm); | ||
120 | } | ||
121 | |||
122 | static int rp5c01_set_time(struct device *dev, struct rtc_time *tm) | ||
123 | { | ||
124 | struct rp5c01_priv *priv = dev_get_drvdata(dev); | ||
125 | |||
126 | spin_lock_irq(&priv->lock); | ||
127 | rp5c01_lock(priv); | ||
128 | |||
129 | rp5c01_write(priv, tm->tm_sec / 10, RP5C01_10_SECOND); | ||
130 | rp5c01_write(priv, tm->tm_sec % 10, RP5C01_1_SECOND); | ||
131 | rp5c01_write(priv, tm->tm_min / 10, RP5C01_10_MINUTE); | ||
132 | rp5c01_write(priv, tm->tm_min % 10, RP5C01_1_MINUTE); | ||
133 | rp5c01_write(priv, tm->tm_hour / 10, RP5C01_10_HOUR); | ||
134 | rp5c01_write(priv, tm->tm_hour % 10, RP5C01_1_HOUR); | ||
135 | rp5c01_write(priv, tm->tm_mday / 10, RP5C01_10_DAY); | ||
136 | rp5c01_write(priv, tm->tm_mday % 10, RP5C01_1_DAY); | ||
137 | if (tm->tm_wday != -1) | ||
138 | rp5c01_write(priv, tm->tm_wday, RP5C01_DAY_OF_WEEK); | ||
139 | rp5c01_write(priv, (tm->tm_mon + 1) / 10, RP5C01_10_MONTH); | ||
140 | rp5c01_write(priv, (tm->tm_mon + 1) % 10, RP5C01_1_MONTH); | ||
141 | if (tm->tm_year >= 100) | ||
142 | tm->tm_year -= 100; | ||
143 | rp5c01_write(priv, tm->tm_year / 10, RP5C01_10_YEAR); | ||
144 | rp5c01_write(priv, tm->tm_year % 10, RP5C01_1_YEAR); | ||
145 | |||
146 | rp5c01_unlock(priv); | ||
147 | spin_unlock_irq(&priv->lock); | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static const struct rtc_class_ops rp5c01_rtc_ops = { | ||
152 | .read_time = rp5c01_read_time, | ||
153 | .set_time = rp5c01_set_time, | ||
154 | }; | ||
155 | |||
156 | |||
157 | /* | ||
158 | * The NVRAM is organized as 2 blocks of 13 nibbles of 4 bits. | ||
159 | * We provide access to them like AmigaOS does: the high nibble of each 8-bit | ||
160 | * byte is stored in BLOCK10, the low nibble in BLOCK11. | ||
161 | */ | ||
162 | |||
163 | static ssize_t rp5c01_nvram_read(struct file *filp, struct kobject *kobj, | ||
164 | struct bin_attribute *bin_attr, | ||
165 | char *buf, loff_t pos, size_t size) | ||
166 | { | ||
167 | struct device *dev = container_of(kobj, struct device, kobj); | ||
168 | struct rp5c01_priv *priv = dev_get_drvdata(dev); | ||
169 | ssize_t count; | ||
170 | |||
171 | spin_lock_irq(&priv->lock); | ||
172 | |||
173 | for (count = 0; size > 0 && pos < RP5C01_MODE; count++, size--) { | ||
174 | u8 data; | ||
175 | |||
176 | rp5c01_write(priv, | ||
177 | RP5C01_MODE_TIMER_EN | RP5C01_MODE_RAM_BLOCK10, | ||
178 | RP5C01_MODE); | ||
179 | data = rp5c01_read(priv, pos) << 4; | ||
180 | rp5c01_write(priv, | ||
181 | RP5C01_MODE_TIMER_EN | RP5C01_MODE_RAM_BLOCK11, | ||
182 | RP5C01_MODE); | ||
183 | data |= rp5c01_read(priv, pos++); | ||
184 | rp5c01_write(priv, RP5C01_MODE_TIMER_EN | RP5C01_MODE_MODE01, | ||
185 | RP5C01_MODE); | ||
186 | *buf++ = data; | ||
187 | } | ||
188 | |||
189 | spin_unlock_irq(&priv->lock); | ||
190 | return count; | ||
191 | } | ||
192 | |||
193 | static ssize_t rp5c01_nvram_write(struct file *filp, struct kobject *kobj, | ||
194 | struct bin_attribute *bin_attr, | ||
195 | char *buf, loff_t pos, size_t size) | ||
196 | { | ||
197 | struct device *dev = container_of(kobj, struct device, kobj); | ||
198 | struct rp5c01_priv *priv = dev_get_drvdata(dev); | ||
199 | ssize_t count; | ||
200 | |||
201 | spin_lock_irq(&priv->lock); | ||
202 | |||
203 | for (count = 0; size > 0 && pos < RP5C01_MODE; count++, size--) { | ||
204 | u8 data = *buf++; | ||
205 | |||
206 | rp5c01_write(priv, | ||
207 | RP5C01_MODE_TIMER_EN | RP5C01_MODE_RAM_BLOCK10, | ||
208 | RP5C01_MODE); | ||
209 | rp5c01_write(priv, data >> 4, pos); | ||
210 | rp5c01_write(priv, | ||
211 | RP5C01_MODE_TIMER_EN | RP5C01_MODE_RAM_BLOCK11, | ||
212 | RP5C01_MODE); | ||
213 | rp5c01_write(priv, data & 0xf, pos++); | ||
214 | rp5c01_write(priv, RP5C01_MODE_TIMER_EN | RP5C01_MODE_MODE01, | ||
215 | RP5C01_MODE); | ||
216 | } | ||
217 | |||
218 | spin_unlock_irq(&priv->lock); | ||
219 | return count; | ||
220 | } | ||
221 | |||
222 | static int __init rp5c01_rtc_probe(struct platform_device *dev) | ||
223 | { | ||
224 | struct resource *res; | ||
225 | struct rp5c01_priv *priv; | ||
226 | struct rtc_device *rtc; | ||
227 | int error; | ||
228 | |||
229 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
230 | if (!res) | ||
231 | return -ENODEV; | ||
232 | |||
233 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
234 | if (!priv) | ||
235 | return -ENOMEM; | ||
236 | |||
237 | priv->regs = ioremap(res->start, resource_size(res)); | ||
238 | if (!priv->regs) { | ||
239 | error = -ENOMEM; | ||
240 | goto out_free_priv; | ||
241 | } | ||
242 | |||
243 | sysfs_bin_attr_init(&priv->nvram_attr); | ||
244 | priv->nvram_attr.attr.name = "nvram"; | ||
245 | priv->nvram_attr.attr.mode = S_IRUGO | S_IWUSR; | ||
246 | priv->nvram_attr.read = rp5c01_nvram_read; | ||
247 | priv->nvram_attr.write = rp5c01_nvram_write; | ||
248 | priv->nvram_attr.size = RP5C01_MODE; | ||
249 | |||
250 | spin_lock_init(&priv->lock); | ||
251 | |||
252 | rtc = rtc_device_register("rtc-rp5c01", &dev->dev, &rp5c01_rtc_ops, | ||
253 | THIS_MODULE); | ||
254 | if (IS_ERR(rtc)) { | ||
255 | error = PTR_ERR(rtc); | ||
256 | goto out_unmap; | ||
257 | } | ||
258 | |||
259 | priv->rtc = rtc; | ||
260 | platform_set_drvdata(dev, priv); | ||
261 | |||
262 | error = sysfs_create_bin_file(&dev->dev.kobj, &priv->nvram_attr); | ||
263 | if (error) | ||
264 | goto out_unregister; | ||
265 | |||
266 | return 0; | ||
267 | |||
268 | out_unregister: | ||
269 | rtc_device_unregister(rtc); | ||
270 | out_unmap: | ||
271 | iounmap(priv->regs); | ||
272 | out_free_priv: | ||
273 | kfree(priv); | ||
274 | return error; | ||
275 | } | ||
276 | |||
277 | static int __exit rp5c01_rtc_remove(struct platform_device *dev) | ||
278 | { | ||
279 | struct rp5c01_priv *priv = platform_get_drvdata(dev); | ||
280 | |||
281 | sysfs_remove_bin_file(&dev->dev.kobj, &priv->nvram_attr); | ||
282 | rtc_device_unregister(priv->rtc); | ||
283 | iounmap(priv->regs); | ||
284 | kfree(priv); | ||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static struct platform_driver rp5c01_rtc_driver = { | ||
289 | .driver = { | ||
290 | .name = "rtc-rp5c01", | ||
291 | .owner = THIS_MODULE, | ||
292 | }, | ||
293 | .remove = __exit_p(rp5c01_rtc_remove), | ||
294 | }; | ||
295 | |||
296 | static int __init rp5c01_rtc_init(void) | ||
297 | { | ||
298 | return platform_driver_probe(&rp5c01_rtc_driver, rp5c01_rtc_probe); | ||
299 | } | ||
300 | |||
301 | static void __exit rp5c01_rtc_fini(void) | ||
302 | { | ||
303 | platform_driver_unregister(&rp5c01_rtc_driver); | ||
304 | } | ||
305 | |||
306 | module_init(rp5c01_rtc_init); | ||
307 | module_exit(rp5c01_rtc_fini); | ||
308 | |||
309 | MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>"); | ||
310 | MODULE_LICENSE("GPL"); | ||
311 | MODULE_DESCRIPTION("Ricoh RP5C01 RTC driver"); | ||
312 | MODULE_ALIAS("platform:rtc-rp5c01"); | ||
diff --git a/drivers/rtc/rtc-rs5c313.c b/drivers/rtc/rtc-rs5c313.c index e6ea3f5ee1eb..e3ff179b99ca 100644 --- a/drivers/rtc/rtc-rs5c313.c +++ b/drivers/rtc/rtc-rs5c313.c | |||
@@ -80,21 +80,21 @@ | |||
80 | /* SCSPTR1 data */ | 80 | /* SCSPTR1 data */ |
81 | unsigned char scsptr1_data; | 81 | unsigned char scsptr1_data; |
82 | 82 | ||
83 | #define RS5C313_CEENABLE ctrl_outb(RS5C313_CE_RTCCE, RS5C313_CE); | 83 | #define RS5C313_CEENABLE __raw_writeb(RS5C313_CE_RTCCE, RS5C313_CE); |
84 | #define RS5C313_CEDISABLE ctrl_outb(0x00, RS5C313_CE) | 84 | #define RS5C313_CEDISABLE __raw_writeb(0x00, RS5C313_CE) |
85 | #define RS5C313_MISCOP ctrl_outb(0x02, 0xB0000008) | 85 | #define RS5C313_MISCOP __raw_writeb(0x02, 0xB0000008) |
86 | 86 | ||
87 | static void rs5c313_init_port(void) | 87 | static void rs5c313_init_port(void) |
88 | { | 88 | { |
89 | /* Set SCK as I/O port and Initialize SCSPTR1 data & I/O port. */ | 89 | /* Set SCK as I/O port and Initialize SCSPTR1 data & I/O port. */ |
90 | ctrl_outb(ctrl_inb(SCSMR1) & ~SCSMR1_CA, SCSMR1); | 90 | __raw_writeb(__raw_readb(SCSMR1) & ~SCSMR1_CA, SCSMR1); |
91 | ctrl_outb(ctrl_inb(SCSCR1) & ~SCSCR1_CKE, SCSCR1); | 91 | __raw_writeb(__raw_readb(SCSCR1) & ~SCSCR1_CKE, SCSCR1); |
92 | 92 | ||
93 | /* And Initialize SCL for RS5C313 clock */ | 93 | /* And Initialize SCL for RS5C313 clock */ |
94 | scsptr1_data = ctrl_inb(SCSPTR1) | SCL; /* SCL:H */ | 94 | scsptr1_data = __raw_readb(SCSPTR1) | SCL; /* SCL:H */ |
95 | ctrl_outb(scsptr1_data, SCSPTR1); | 95 | __raw_writeb(scsptr1_data, SCSPTR1); |
96 | scsptr1_data = ctrl_inb(SCSPTR1) | SCL_OEN; /* SCL output enable */ | 96 | scsptr1_data = __raw_readb(SCSPTR1) | SCL_OEN; /* SCL output enable */ |
97 | ctrl_outb(scsptr1_data, SCSPTR1); | 97 | __raw_writeb(scsptr1_data, SCSPTR1); |
98 | RS5C313_CEDISABLE; /* CE:L */ | 98 | RS5C313_CEDISABLE; /* CE:L */ |
99 | } | 99 | } |
100 | 100 | ||
@@ -106,21 +106,21 @@ static void rs5c313_write_data(unsigned char data) | |||
106 | /* SDA:Write Data */ | 106 | /* SDA:Write Data */ |
107 | scsptr1_data = (scsptr1_data & ~SDA) | | 107 | scsptr1_data = (scsptr1_data & ~SDA) | |
108 | ((((0x80 >> i) & data) >> (7 - i)) << 2); | 108 | ((((0x80 >> i) & data) >> (7 - i)) << 2); |
109 | ctrl_outb(scsptr1_data, SCSPTR1); | 109 | __raw_writeb(scsptr1_data, SCSPTR1); |
110 | if (i == 0) { | 110 | if (i == 0) { |
111 | scsptr1_data |= SDA_OEN; /* SDA:output enable */ | 111 | scsptr1_data |= SDA_OEN; /* SDA:output enable */ |
112 | ctrl_outb(scsptr1_data, SCSPTR1); | 112 | __raw_writeb(scsptr1_data, SCSPTR1); |
113 | } | 113 | } |
114 | ndelay(700); | 114 | ndelay(700); |
115 | scsptr1_data &= ~SCL; /* SCL:L */ | 115 | scsptr1_data &= ~SCL; /* SCL:L */ |
116 | ctrl_outb(scsptr1_data, SCSPTR1); | 116 | __raw_writeb(scsptr1_data, SCSPTR1); |
117 | ndelay(700); | 117 | ndelay(700); |
118 | scsptr1_data |= SCL; /* SCL:H */ | 118 | scsptr1_data |= SCL; /* SCL:H */ |
119 | ctrl_outb(scsptr1_data, SCSPTR1); | 119 | __raw_writeb(scsptr1_data, SCSPTR1); |
120 | } | 120 | } |
121 | 121 | ||
122 | scsptr1_data &= ~SDA_OEN; /* SDA:output disable */ | 122 | scsptr1_data &= ~SDA_OEN; /* SDA:output disable */ |
123 | ctrl_outb(scsptr1_data, SCSPTR1); | 123 | __raw_writeb(scsptr1_data, SCSPTR1); |
124 | } | 124 | } |
125 | 125 | ||
126 | static unsigned char rs5c313_read_data(void) | 126 | static unsigned char rs5c313_read_data(void) |
@@ -131,12 +131,12 @@ static unsigned char rs5c313_read_data(void) | |||
131 | for (i = 0; i < 8; i++) { | 131 | for (i = 0; i < 8; i++) { |
132 | ndelay(700); | 132 | ndelay(700); |
133 | /* SDA:Read Data */ | 133 | /* SDA:Read Data */ |
134 | data |= ((ctrl_inb(SCSPTR1) & SDA) >> 2) << (7 - i); | 134 | data |= ((__raw_readb(SCSPTR1) & SDA) >> 2) << (7 - i); |
135 | scsptr1_data &= ~SCL; /* SCL:L */ | 135 | scsptr1_data &= ~SCL; /* SCL:L */ |
136 | ctrl_outb(scsptr1_data, SCSPTR1); | 136 | __raw_writeb(scsptr1_data, SCSPTR1); |
137 | ndelay(700); | 137 | ndelay(700); |
138 | scsptr1_data |= SCL; /* SCL:H */ | 138 | scsptr1_data |= SCL; /* SCL:H */ |
139 | ctrl_outb(scsptr1_data, SCSPTR1); | 139 | __raw_writeb(scsptr1_data, SCSPTR1); |
140 | } | 140 | } |
141 | return data & 0x0F; | 141 | return data & 0x0F; |
142 | } | 142 | } |
diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index dd1e2bc7a472..368d0e63cf83 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/string.h> | 21 | #include <linux/string.h> |
22 | #include <linux/slab.h> | ||
22 | #include <linux/rtc.h> | 23 | #include <linux/rtc.h> |
23 | #include <linux/workqueue.h> | 24 | #include <linux/workqueue.h> |
24 | #include <linux/spi/spi.h> | 25 | #include <linux/spi/spi.h> |
@@ -251,3 +252,4 @@ MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); | |||
251 | MODULE_DESCRIPTION("Ricoh RS5C348 RTC driver"); | 252 | MODULE_DESCRIPTION("Ricoh RS5C348 RTC driver"); |
252 | MODULE_LICENSE("GPL"); | 253 | MODULE_LICENSE("GPL"); |
253 | MODULE_VERSION(DRV_VERSION); | 254 | MODULE_VERSION(DRV_VERSION); |
255 | MODULE_ALIAS("spi:rtc-rs5c348"); | ||
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 2f2c68d476da..dd14e202c2c8 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/i2c.h> | 13 | #include <linux/i2c.h> |
14 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
15 | #include <linux/bcd.h> | 15 | #include <linux/bcd.h> |
16 | #include <linux/slab.h> | ||
16 | 17 | ||
17 | #define DRV_VERSION "0.6" | 18 | #define DRV_VERSION "0.6" |
18 | 19 | ||
@@ -206,7 +207,7 @@ static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
206 | static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) | 207 | static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) |
207 | { | 208 | { |
208 | struct rs5c372 *rs5c = i2c_get_clientdata(client); | 209 | struct rs5c372 *rs5c = i2c_get_clientdata(client); |
209 | unsigned char buf[8]; | 210 | unsigned char buf[7]; |
210 | int addr; | 211 | int addr; |
211 | 212 | ||
212 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d " | 213 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d " |
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index b1a29bcfdf13..af32a62e12a8 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/slab.h> | ||
23 | #include <linux/init.h> | 24 | #include <linux/init.h> |
24 | #include <linux/bcd.h> | 25 | #include <linux/bcd.h> |
25 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
@@ -460,7 +461,7 @@ static struct rtc_class_ops rx8025_rtc_ops = { | |||
460 | * Clock precision adjustment support | 461 | * Clock precision adjustment support |
461 | * | 462 | * |
462 | * According to the RX8025 SA/NB application manual the frequency and | 463 | * According to the RX8025 SA/NB application manual the frequency and |
463 | * temperature charateristics can be approximated using the following | 464 | * temperature characteristics can be approximated using the following |
464 | * equation: | 465 | * equation: |
465 | * | 466 | * |
466 | * df = a * (ut - t)**2 | 467 | * df = a * (ut - t)**2 |
@@ -631,7 +632,6 @@ errout_reg: | |||
631 | rtc_device_unregister(rx8025->rtc); | 632 | rtc_device_unregister(rx8025->rtc); |
632 | 633 | ||
633 | errout_free: | 634 | errout_free: |
634 | i2c_set_clientdata(client, NULL); | ||
635 | kfree(rx8025); | 635 | kfree(rx8025); |
636 | 636 | ||
637 | errout: | 637 | errout: |
@@ -650,12 +650,11 @@ static int __devexit rx8025_remove(struct i2c_client *client) | |||
650 | mutex_unlock(lock); | 650 | mutex_unlock(lock); |
651 | 651 | ||
652 | free_irq(client->irq, client); | 652 | free_irq(client->irq, client); |
653 | flush_scheduled_work(); | 653 | cancel_work_sync(&rx8025->work); |
654 | } | 654 | } |
655 | 655 | ||
656 | rx8025_sysfs_unregister(&client->dev); | 656 | rx8025_sysfs_unregister(&client->dev); |
657 | rtc_device_unregister(rx8025->rtc); | 657 | rtc_device_unregister(rx8025->rtc); |
658 | i2c_set_clientdata(client, NULL); | ||
659 | kfree(rx8025); | 658 | kfree(rx8025); |
660 | return 0; | 659 | return 0; |
661 | } | 660 | } |
diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index c9522f3bc21c..600b890a3c15 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * An I2C driver for the Epson RX8581 RTC | 2 | * An I2C driver for the Epson RX8581 RTC |
3 | * | 3 | * |
4 | * Author: Martyn Welch <martyn.welch@gefanuc.com> | 4 | * Author: Martyn Welch <martyn.welch@ge.com> |
5 | * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc. | 5 | * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. |
6 | * | 6 | * |
7 | * 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 |
8 | * 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 |
@@ -168,7 +168,7 @@ static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
168 | return -EIO; | 168 | return -EIO; |
169 | } | 169 | } |
170 | 170 | ||
171 | err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, | 171 | err = i2c_smbus_write_byte_data(client, RX8581_REG_CTRL, |
172 | (data | RX8581_CTRL_STOP)); | 172 | (data | RX8581_CTRL_STOP)); |
173 | if (err < 0) { | 173 | if (err < 0) { |
174 | dev_err(&client->dev, "Unable to write control register\n"); | 174 | dev_err(&client->dev, "Unable to write control register\n"); |
@@ -182,6 +182,20 @@ static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
182 | return -EIO; | 182 | return -EIO; |
183 | } | 183 | } |
184 | 184 | ||
185 | /* get VLF and clear it */ | ||
186 | data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG); | ||
187 | if (data < 0) { | ||
188 | dev_err(&client->dev, "Unable to read flag register\n"); | ||
189 | return -EIO; | ||
190 | } | ||
191 | |||
192 | err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, | ||
193 | (data & ~(RX8581_FLAG_VLF))); | ||
194 | if (err != 0) { | ||
195 | dev_err(&client->dev, "Unable to write flag register\n"); | ||
196 | return -EIO; | ||
197 | } | ||
198 | |||
185 | /* Restart the clock */ | 199 | /* Restart the clock */ |
186 | data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL); | 200 | data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL); |
187 | if (data < 0) { | 201 | if (data < 0) { |
@@ -189,8 +203,8 @@ static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
189 | return -EIO; | 203 | return -EIO; |
190 | } | 204 | } |
191 | 205 | ||
192 | err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, | 206 | err = i2c_smbus_write_byte_data(client, RX8581_REG_CTRL, |
193 | (data | ~(RX8581_CTRL_STOP))); | 207 | (data & ~(RX8581_CTRL_STOP))); |
194 | if (err != 0) { | 208 | if (err != 0) { |
195 | dev_err(&client->dev, "Unable to write control register\n"); | 209 | dev_err(&client->dev, "Unable to write control register\n"); |
196 | return -EIO; | 210 | return -EIO; |
@@ -272,7 +286,7 @@ static void __exit rx8581_exit(void) | |||
272 | i2c_del_driver(&rx8581_driver); | 286 | i2c_del_driver(&rx8581_driver); |
273 | } | 287 | } |
274 | 288 | ||
275 | MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com>"); | 289 | MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com>"); |
276 | MODULE_DESCRIPTION("Epson RX-8581 RTC driver"); | 290 | MODULE_DESCRIPTION("Epson RX-8581 RTC driver"); |
277 | MODULE_LICENSE("GPL"); | 291 | MODULE_LICENSE("GPL"); |
278 | MODULE_VERSION(DRV_VERSION); | 292 | MODULE_VERSION(DRV_VERSION); |
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index def4d396d0b0..f789e002c9b0 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c | |||
@@ -275,7 +275,6 @@ exit_dummy: | |||
275 | if (s35390a->client[i]) | 275 | if (s35390a->client[i]) |
276 | i2c_unregister_device(s35390a->client[i]); | 276 | i2c_unregister_device(s35390a->client[i]); |
277 | kfree(s35390a); | 277 | kfree(s35390a); |
278 | i2c_set_clientdata(client, NULL); | ||
279 | 278 | ||
280 | exit: | 279 | exit: |
281 | return err; | 280 | return err; |
@@ -292,7 +291,6 @@ static int s35390a_remove(struct i2c_client *client) | |||
292 | 291 | ||
293 | rtc_device_unregister(s35390a->rtc); | 292 | rtc_device_unregister(s35390a->rtc); |
294 | kfree(s35390a); | 293 | kfree(s35390a); |
295 | i2c_set_clientdata(client, NULL); | ||
296 | 294 | ||
297 | return 0; | 295 | return 0; |
298 | } | 296 | } |
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index e0d7b9991505..cf953ecbfca9 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -1,5 +1,8 @@ | |||
1 | /* drivers/rtc/rtc-s3c.c | 1 | /* drivers/rtc/rtc-s3c.c |
2 | * | 2 | * |
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
3 | * Copyright (c) 2004,2006 Simtec Electronics | 6 | * Copyright (c) 2004,2006 Simtec Electronics |
4 | * Ben Dooks, <ben@simtec.co.uk> | 7 | * Ben Dooks, <ben@simtec.co.uk> |
5 | * http://armlinux.simtec.co.uk/ | 8 | * http://armlinux.simtec.co.uk/ |
@@ -21,6 +24,7 @@ | |||
21 | #include <linux/bcd.h> | 24 | #include <linux/bcd.h> |
22 | #include <linux/clk.h> | 25 | #include <linux/clk.h> |
23 | #include <linux/log2.h> | 26 | #include <linux/log2.h> |
27 | #include <linux/slab.h> | ||
24 | 28 | ||
25 | #include <mach/hardware.h> | 29 | #include <mach/hardware.h> |
26 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
@@ -28,14 +32,21 @@ | |||
28 | #include <asm/irq.h> | 32 | #include <asm/irq.h> |
29 | #include <plat/regs-rtc.h> | 33 | #include <plat/regs-rtc.h> |
30 | 34 | ||
35 | enum s3c_cpu_type { | ||
36 | TYPE_S3C2410, | ||
37 | TYPE_S3C64XX, | ||
38 | }; | ||
39 | |||
31 | /* I have yet to find an S3C implementation with more than one | 40 | /* I have yet to find an S3C implementation with more than one |
32 | * of these rtc blocks in */ | 41 | * of these rtc blocks in */ |
33 | 42 | ||
34 | static struct resource *s3c_rtc_mem; | 43 | static struct resource *s3c_rtc_mem; |
35 | 44 | ||
45 | static struct clk *rtc_clk; | ||
36 | static void __iomem *s3c_rtc_base; | 46 | static void __iomem *s3c_rtc_base; |
37 | static int s3c_rtc_alarmno = NO_IRQ; | 47 | static int s3c_rtc_alarmno = NO_IRQ; |
38 | static int s3c_rtc_tickno = NO_IRQ; | 48 | static int s3c_rtc_tickno = NO_IRQ; |
49 | static enum s3c_cpu_type s3c_rtc_cpu_type; | ||
39 | 50 | ||
40 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); | 51 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); |
41 | 52 | ||
@@ -46,6 +57,10 @@ static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) | |||
46 | struct rtc_device *rdev = id; | 57 | struct rtc_device *rdev = id; |
47 | 58 | ||
48 | rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); | 59 | rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); |
60 | |||
61 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | ||
62 | writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP); | ||
63 | |||
49 | return IRQ_HANDLED; | 64 | return IRQ_HANDLED; |
50 | } | 65 | } |
51 | 66 | ||
@@ -54,6 +69,10 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id) | |||
54 | struct rtc_device *rdev = id; | 69 | struct rtc_device *rdev = id; |
55 | 70 | ||
56 | rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); | 71 | rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); |
72 | |||
73 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | ||
74 | writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP); | ||
75 | |||
57 | return IRQ_HANDLED; | 76 | return IRQ_HANDLED; |
58 | } | 77 | } |
59 | 78 | ||
@@ -79,12 +98,25 @@ static int s3c_rtc_setpie(struct device *dev, int enabled) | |||
79 | pr_debug("%s: pie=%d\n", __func__, enabled); | 98 | pr_debug("%s: pie=%d\n", __func__, enabled); |
80 | 99 | ||
81 | spin_lock_irq(&s3c_rtc_pie_lock); | 100 | spin_lock_irq(&s3c_rtc_pie_lock); |
82 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE; | ||
83 | 101 | ||
84 | if (enabled) | 102 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
85 | tmp |= S3C2410_TICNT_ENABLE; | 103 | tmp = readw(s3c_rtc_base + S3C2410_RTCCON); |
104 | tmp &= ~S3C64XX_RTCCON_TICEN; | ||
105 | |||
106 | if (enabled) | ||
107 | tmp |= S3C64XX_RTCCON_TICEN; | ||
108 | |||
109 | writew(tmp, s3c_rtc_base + S3C2410_RTCCON); | ||
110 | } else { | ||
111 | tmp = readb(s3c_rtc_base + S3C2410_TICNT); | ||
112 | tmp &= ~S3C2410_TICNT_ENABLE; | ||
113 | |||
114 | if (enabled) | ||
115 | tmp |= S3C2410_TICNT_ENABLE; | ||
116 | |||
117 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | ||
118 | } | ||
86 | 119 | ||
87 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | ||
88 | spin_unlock_irq(&s3c_rtc_pie_lock); | 120 | spin_unlock_irq(&s3c_rtc_pie_lock); |
89 | 121 | ||
90 | return 0; | 122 | return 0; |
@@ -92,17 +124,23 @@ static int s3c_rtc_setpie(struct device *dev, int enabled) | |||
92 | 124 | ||
93 | static int s3c_rtc_setfreq(struct device *dev, int freq) | 125 | static int s3c_rtc_setfreq(struct device *dev, int freq) |
94 | { | 126 | { |
95 | unsigned int tmp; | 127 | struct platform_device *pdev = to_platform_device(dev); |
128 | struct rtc_device *rtc_dev = platform_get_drvdata(pdev); | ||
129 | unsigned int tmp = 0; | ||
96 | 130 | ||
97 | if (!is_power_of_2(freq)) | 131 | if (!is_power_of_2(freq)) |
98 | return -EINVAL; | 132 | return -EINVAL; |
99 | 133 | ||
100 | spin_lock_irq(&s3c_rtc_pie_lock); | 134 | spin_lock_irq(&s3c_rtc_pie_lock); |
101 | 135 | ||
102 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE; | 136 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { |
103 | tmp |= (128 / freq)-1; | 137 | tmp = readb(s3c_rtc_base + S3C2410_TICNT); |
138 | tmp &= S3C2410_TICNT_ENABLE; | ||
139 | } | ||
140 | |||
141 | tmp |= (rtc_dev->max_user_freq / freq)-1; | ||
104 | 142 | ||
105 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | 143 | writel(tmp, s3c_rtc_base + S3C2410_TICNT); |
106 | spin_unlock_irq(&s3c_rtc_pie_lock); | 144 | spin_unlock_irq(&s3c_rtc_pie_lock); |
107 | 145 | ||
108 | return 0; | 146 | return 0; |
@@ -133,8 +171,8 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
133 | goto retry_get_time; | 171 | goto retry_get_time; |
134 | } | 172 | } |
135 | 173 | ||
136 | pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n", | 174 | pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n", |
137 | rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, | 175 | 1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, |
138 | rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); | 176 | rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); |
139 | 177 | ||
140 | rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); | 178 | rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); |
@@ -147,7 +185,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
147 | rtc_tm->tm_year += 100; | 185 | rtc_tm->tm_year += 100; |
148 | rtc_tm->tm_mon -= 1; | 186 | rtc_tm->tm_mon -= 1; |
149 | 187 | ||
150 | return 0; | 188 | return rtc_valid_tm(rtc_tm); |
151 | } | 189 | } |
152 | 190 | ||
153 | static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) | 191 | static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) |
@@ -155,8 +193,8 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
155 | void __iomem *base = s3c_rtc_base; | 193 | void __iomem *base = s3c_rtc_base; |
156 | int year = tm->tm_year - 100; | 194 | int year = tm->tm_year - 100; |
157 | 195 | ||
158 | pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n", | 196 | pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n", |
159 | tm->tm_year, tm->tm_mon, tm->tm_mday, | 197 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, |
160 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 198 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
161 | 199 | ||
162 | /* we get around y2k by simply not supporting it */ | 200 | /* we get around y2k by simply not supporting it */ |
@@ -193,9 +231,9 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
193 | 231 | ||
194 | alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; | 232 | alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; |
195 | 233 | ||
196 | pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n", | 234 | pr_debug("read alarm %d, %04d.%02d.%02d %02d:%02d:%02d\n", |
197 | alm_en, | 235 | alm_en, |
198 | alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, | 236 | 1900 + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, |
199 | alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); | 237 | alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); |
200 | 238 | ||
201 | 239 | ||
@@ -204,34 +242,34 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
204 | if (alm_en & S3C2410_RTCALM_SECEN) | 242 | if (alm_en & S3C2410_RTCALM_SECEN) |
205 | alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); | 243 | alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); |
206 | else | 244 | else |
207 | alm_tm->tm_sec = 0xff; | 245 | alm_tm->tm_sec = -1; |
208 | 246 | ||
209 | if (alm_en & S3C2410_RTCALM_MINEN) | 247 | if (alm_en & S3C2410_RTCALM_MINEN) |
210 | alm_tm->tm_min = bcd2bin(alm_tm->tm_min); | 248 | alm_tm->tm_min = bcd2bin(alm_tm->tm_min); |
211 | else | 249 | else |
212 | alm_tm->tm_min = 0xff; | 250 | alm_tm->tm_min = -1; |
213 | 251 | ||
214 | if (alm_en & S3C2410_RTCALM_HOUREN) | 252 | if (alm_en & S3C2410_RTCALM_HOUREN) |
215 | alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); | 253 | alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); |
216 | else | 254 | else |
217 | alm_tm->tm_hour = 0xff; | 255 | alm_tm->tm_hour = -1; |
218 | 256 | ||
219 | if (alm_en & S3C2410_RTCALM_DAYEN) | 257 | if (alm_en & S3C2410_RTCALM_DAYEN) |
220 | alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); | 258 | alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); |
221 | else | 259 | else |
222 | alm_tm->tm_mday = 0xff; | 260 | alm_tm->tm_mday = -1; |
223 | 261 | ||
224 | if (alm_en & S3C2410_RTCALM_MONEN) { | 262 | if (alm_en & S3C2410_RTCALM_MONEN) { |
225 | alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon); | 263 | alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon); |
226 | alm_tm->tm_mon -= 1; | 264 | alm_tm->tm_mon -= 1; |
227 | } else { | 265 | } else { |
228 | alm_tm->tm_mon = 0xff; | 266 | alm_tm->tm_mon = -1; |
229 | } | 267 | } |
230 | 268 | ||
231 | if (alm_en & S3C2410_RTCALM_YEAREN) | 269 | if (alm_en & S3C2410_RTCALM_YEAREN) |
232 | alm_tm->tm_year = bcd2bin(alm_tm->tm_year); | 270 | alm_tm->tm_year = bcd2bin(alm_tm->tm_year); |
233 | else | 271 | else |
234 | alm_tm->tm_year = 0xffff; | 272 | alm_tm->tm_year = -1; |
235 | 273 | ||
236 | return 0; | 274 | return 0; |
237 | } | 275 | } |
@@ -242,10 +280,10 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
242 | void __iomem *base = s3c_rtc_base; | 280 | void __iomem *base = s3c_rtc_base; |
243 | unsigned int alrm_en; | 281 | unsigned int alrm_en; |
244 | 282 | ||
245 | pr_debug("s3c_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n", | 283 | pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", |
246 | alrm->enabled, | 284 | alrm->enabled, |
247 | tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff, | 285 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, |
248 | tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec); | 286 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
249 | 287 | ||
250 | 288 | ||
251 | alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; | 289 | alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; |
@@ -272,20 +310,22 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
272 | 310 | ||
273 | s3c_rtc_setaie(alrm->enabled); | 311 | s3c_rtc_setaie(alrm->enabled); |
274 | 312 | ||
275 | if (alrm->enabled) | ||
276 | enable_irq_wake(s3c_rtc_alarmno); | ||
277 | else | ||
278 | disable_irq_wake(s3c_rtc_alarmno); | ||
279 | |||
280 | return 0; | 313 | return 0; |
281 | } | 314 | } |
282 | 315 | ||
283 | static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) | 316 | static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) |
284 | { | 317 | { |
285 | unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT); | 318 | unsigned int ticnt; |
286 | 319 | ||
287 | seq_printf(seq, "periodic_IRQ\t: %s\n", | 320 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
288 | (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" ); | 321 | ticnt = readw(s3c_rtc_base + S3C2410_RTCCON); |
322 | ticnt &= S3C64XX_RTCCON_TICEN; | ||
323 | } else { | ||
324 | ticnt = readb(s3c_rtc_base + S3C2410_TICNT); | ||
325 | ticnt &= S3C2410_TICNT_ENABLE; | ||
326 | } | ||
327 | |||
328 | seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); | ||
289 | return 0; | 329 | return 0; |
290 | } | 330 | } |
291 | 331 | ||
@@ -339,7 +379,8 @@ static const struct rtc_class_ops s3c_rtcops = { | |||
339 | .set_alarm = s3c_rtc_setalarm, | 379 | .set_alarm = s3c_rtc_setalarm, |
340 | .irq_set_freq = s3c_rtc_setfreq, | 380 | .irq_set_freq = s3c_rtc_setfreq, |
341 | .irq_set_state = s3c_rtc_setpie, | 381 | .irq_set_state = s3c_rtc_setpie, |
342 | .proc = s3c_rtc_proc, | 382 | .proc = s3c_rtc_proc, |
383 | .alarm_irq_enable = s3c_rtc_setaie, | ||
343 | }; | 384 | }; |
344 | 385 | ||
345 | static void s3c_rtc_enable(struct platform_device *pdev, int en) | 386 | static void s3c_rtc_enable(struct platform_device *pdev, int en) |
@@ -351,33 +392,42 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
351 | return; | 392 | return; |
352 | 393 | ||
353 | if (!en) { | 394 | if (!en) { |
354 | tmp = readb(base + S3C2410_RTCCON); | 395 | tmp = readw(base + S3C2410_RTCCON); |
355 | writeb(tmp & ~S3C2410_RTCCON_RTCEN, base + S3C2410_RTCCON); | 396 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
356 | 397 | tmp &= ~S3C64XX_RTCCON_TICEN; | |
357 | tmp = readb(base + S3C2410_TICNT); | 398 | tmp &= ~S3C2410_RTCCON_RTCEN; |
358 | writeb(tmp & ~S3C2410_TICNT_ENABLE, base + S3C2410_TICNT); | 399 | writew(tmp, base + S3C2410_RTCCON); |
400 | |||
401 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { | ||
402 | tmp = readb(base + S3C2410_TICNT); | ||
403 | tmp &= ~S3C2410_TICNT_ENABLE; | ||
404 | writeb(tmp, base + S3C2410_TICNT); | ||
405 | } | ||
359 | } else { | 406 | } else { |
360 | /* re-enable the device, and check it is ok */ | 407 | /* re-enable the device, and check it is ok */ |
361 | 408 | ||
362 | if ((readb(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){ | 409 | if ((readw(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0) { |
363 | dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); | 410 | dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); |
364 | 411 | ||
365 | tmp = readb(base + S3C2410_RTCCON); | 412 | tmp = readw(base + S3C2410_RTCCON); |
366 | writeb(tmp|S3C2410_RTCCON_RTCEN, base+S3C2410_RTCCON); | 413 | writew(tmp | S3C2410_RTCCON_RTCEN, |
414 | base + S3C2410_RTCCON); | ||
367 | } | 415 | } |
368 | 416 | ||
369 | if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){ | 417 | if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)) { |
370 | dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n"); | 418 | dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n"); |
371 | 419 | ||
372 | tmp = readb(base + S3C2410_RTCCON); | 420 | tmp = readw(base + S3C2410_RTCCON); |
373 | writeb(tmp& ~S3C2410_RTCCON_CNTSEL, base+S3C2410_RTCCON); | 421 | writew(tmp & ~S3C2410_RTCCON_CNTSEL, |
422 | base + S3C2410_RTCCON); | ||
374 | } | 423 | } |
375 | 424 | ||
376 | if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){ | 425 | if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)) { |
377 | dev_info(&pdev->dev, "removing RTCCON_CLKRST\n"); | 426 | dev_info(&pdev->dev, "removing RTCCON_CLKRST\n"); |
378 | 427 | ||
379 | tmp = readb(base + S3C2410_RTCCON); | 428 | tmp = readw(base + S3C2410_RTCCON); |
380 | writeb(tmp & ~S3C2410_RTCCON_CLKRST, base+S3C2410_RTCCON); | 429 | writew(tmp & ~S3C2410_RTCCON_CLKRST, |
430 | base + S3C2410_RTCCON); | ||
381 | } | 431 | } |
382 | } | 432 | } |
383 | } | 433 | } |
@@ -392,6 +442,10 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev) | |||
392 | s3c_rtc_setpie(&dev->dev, 0); | 442 | s3c_rtc_setpie(&dev->dev, 0); |
393 | s3c_rtc_setaie(0); | 443 | s3c_rtc_setaie(0); |
394 | 444 | ||
445 | clk_disable(rtc_clk); | ||
446 | clk_put(rtc_clk); | ||
447 | rtc_clk = NULL; | ||
448 | |||
395 | iounmap(s3c_rtc_base); | 449 | iounmap(s3c_rtc_base); |
396 | release_resource(s3c_rtc_mem); | 450 | release_resource(s3c_rtc_mem); |
397 | kfree(s3c_rtc_mem); | 451 | kfree(s3c_rtc_mem); |
@@ -402,6 +456,7 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev) | |||
402 | static int __devinit s3c_rtc_probe(struct platform_device *pdev) | 456 | static int __devinit s3c_rtc_probe(struct platform_device *pdev) |
403 | { | 457 | { |
404 | struct rtc_device *rtc; | 458 | struct rtc_device *rtc; |
459 | struct rtc_time rtc_tm; | ||
405 | struct resource *res; | 460 | struct resource *res; |
406 | int ret; | 461 | int ret; |
407 | 462 | ||
@@ -449,14 +504,22 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
449 | goto err_nomap; | 504 | goto err_nomap; |
450 | } | 505 | } |
451 | 506 | ||
507 | rtc_clk = clk_get(&pdev->dev, "rtc"); | ||
508 | if (IS_ERR(rtc_clk)) { | ||
509 | dev_err(&pdev->dev, "failed to find rtc clock source\n"); | ||
510 | ret = PTR_ERR(rtc_clk); | ||
511 | rtc_clk = NULL; | ||
512 | goto err_clk; | ||
513 | } | ||
514 | |||
515 | clk_enable(rtc_clk); | ||
516 | |||
452 | /* check to see if everything is setup correctly */ | 517 | /* check to see if everything is setup correctly */ |
453 | 518 | ||
454 | s3c_rtc_enable(pdev, 1); | 519 | s3c_rtc_enable(pdev, 1); |
455 | 520 | ||
456 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", | 521 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", |
457 | readb(s3c_rtc_base + S3C2410_RTCCON)); | 522 | readw(s3c_rtc_base + S3C2410_RTCCON)); |
458 | |||
459 | s3c_rtc_setfreq(&pdev->dev, 1); | ||
460 | 523 | ||
461 | device_init_wakeup(&pdev->dev, 1); | 524 | device_init_wakeup(&pdev->dev, 1); |
462 | 525 | ||
@@ -471,13 +534,42 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
471 | goto err_nortc; | 534 | goto err_nortc; |
472 | } | 535 | } |
473 | 536 | ||
474 | rtc->max_user_freq = 128; | 537 | s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data; |
538 | |||
539 | /* Check RTC Time */ | ||
540 | |||
541 | s3c_rtc_gettime(NULL, &rtc_tm); | ||
542 | |||
543 | if (rtc_valid_tm(&rtc_tm)) { | ||
544 | rtc_tm.tm_year = 100; | ||
545 | rtc_tm.tm_mon = 0; | ||
546 | rtc_tm.tm_mday = 1; | ||
547 | rtc_tm.tm_hour = 0; | ||
548 | rtc_tm.tm_min = 0; | ||
549 | rtc_tm.tm_sec = 0; | ||
550 | |||
551 | s3c_rtc_settime(NULL, &rtc_tm); | ||
552 | |||
553 | dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n"); | ||
554 | } | ||
555 | |||
556 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | ||
557 | rtc->max_user_freq = 32768; | ||
558 | else | ||
559 | rtc->max_user_freq = 128; | ||
475 | 560 | ||
476 | platform_set_drvdata(pdev, rtc); | 561 | platform_set_drvdata(pdev, rtc); |
562 | |||
563 | s3c_rtc_setfreq(&pdev->dev, 1); | ||
564 | |||
477 | return 0; | 565 | return 0; |
478 | 566 | ||
479 | err_nortc: | 567 | err_nortc: |
480 | s3c_rtc_enable(pdev, 0); | 568 | s3c_rtc_enable(pdev, 0); |
569 | clk_disable(rtc_clk); | ||
570 | clk_put(rtc_clk); | ||
571 | |||
572 | err_clk: | ||
481 | iounmap(s3c_rtc_base); | 573 | iounmap(s3c_rtc_base); |
482 | 574 | ||
483 | err_nomap: | 575 | err_nomap: |
@@ -491,20 +583,38 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
491 | 583 | ||
492 | /* RTC Power management control */ | 584 | /* RTC Power management control */ |
493 | 585 | ||
494 | static int ticnt_save; | 586 | static int ticnt_save, ticnt_en_save; |
495 | 587 | ||
496 | static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 588 | static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
497 | { | 589 | { |
498 | /* save TICNT for anyone using periodic interrupts */ | 590 | /* save TICNT for anyone using periodic interrupts */ |
499 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); | 591 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); |
592 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | ||
593 | ticnt_en_save = readw(s3c_rtc_base + S3C2410_RTCCON); | ||
594 | ticnt_en_save &= S3C64XX_RTCCON_TICEN; | ||
595 | } | ||
500 | s3c_rtc_enable(pdev, 0); | 596 | s3c_rtc_enable(pdev, 0); |
597 | |||
598 | if (device_may_wakeup(&pdev->dev)) | ||
599 | enable_irq_wake(s3c_rtc_alarmno); | ||
600 | |||
501 | return 0; | 601 | return 0; |
502 | } | 602 | } |
503 | 603 | ||
504 | static int s3c_rtc_resume(struct platform_device *pdev) | 604 | static int s3c_rtc_resume(struct platform_device *pdev) |
505 | { | 605 | { |
606 | unsigned int tmp; | ||
607 | |||
506 | s3c_rtc_enable(pdev, 1); | 608 | s3c_rtc_enable(pdev, 1); |
507 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); | 609 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); |
610 | if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { | ||
611 | tmp = readw(s3c_rtc_base + S3C2410_RTCCON); | ||
612 | writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); | ||
613 | } | ||
614 | |||
615 | if (device_may_wakeup(&pdev->dev)) | ||
616 | disable_irq_wake(s3c_rtc_alarmno); | ||
617 | |||
508 | return 0; | 618 | return 0; |
509 | } | 619 | } |
510 | #else | 620 | #else |
@@ -512,13 +622,27 @@ static int s3c_rtc_resume(struct platform_device *pdev) | |||
512 | #define s3c_rtc_resume NULL | 622 | #define s3c_rtc_resume NULL |
513 | #endif | 623 | #endif |
514 | 624 | ||
515 | static struct platform_driver s3c2410_rtc_driver = { | 625 | static struct platform_device_id s3c_rtc_driver_ids[] = { |
626 | { | ||
627 | .name = "s3c2410-rtc", | ||
628 | .driver_data = TYPE_S3C2410, | ||
629 | }, { | ||
630 | .name = "s3c64xx-rtc", | ||
631 | .driver_data = TYPE_S3C64XX, | ||
632 | }, | ||
633 | { } | ||
634 | }; | ||
635 | |||
636 | MODULE_DEVICE_TABLE(platform, s3c_rtc_driver_ids); | ||
637 | |||
638 | static struct platform_driver s3c_rtc_driver = { | ||
516 | .probe = s3c_rtc_probe, | 639 | .probe = s3c_rtc_probe, |
517 | .remove = __devexit_p(s3c_rtc_remove), | 640 | .remove = __devexit_p(s3c_rtc_remove), |
518 | .suspend = s3c_rtc_suspend, | 641 | .suspend = s3c_rtc_suspend, |
519 | .resume = s3c_rtc_resume, | 642 | .resume = s3c_rtc_resume, |
643 | .id_table = s3c_rtc_driver_ids, | ||
520 | .driver = { | 644 | .driver = { |
521 | .name = "s3c2410-rtc", | 645 | .name = "s3c-rtc", |
522 | .owner = THIS_MODULE, | 646 | .owner = THIS_MODULE, |
523 | }, | 647 | }, |
524 | }; | 648 | }; |
@@ -528,12 +652,12 @@ static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics | |||
528 | static int __init s3c_rtc_init(void) | 652 | static int __init s3c_rtc_init(void) |
529 | { | 653 | { |
530 | printk(banner); | 654 | printk(banner); |
531 | return platform_driver_register(&s3c2410_rtc_driver); | 655 | return platform_driver_register(&s3c_rtc_driver); |
532 | } | 656 | } |
533 | 657 | ||
534 | static void __exit s3c_rtc_exit(void) | 658 | static void __exit s3c_rtc_exit(void) |
535 | { | 659 | { |
536 | platform_driver_unregister(&s3c2410_rtc_driver); | 660 | platform_driver_unregister(&s3c_rtc_driver); |
537 | } | 661 | } |
538 | 662 | ||
539 | module_init(s3c_rtc_init); | 663 | module_init(s3c_rtc_init); |
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 4f247e4dd3f9..88ea52b8647a 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * | 9 | * |
10 | * Modifications from: | 10 | * Modifications from: |
11 | * CIH <cih@coventive.com> | 11 | * CIH <cih@coventive.com> |
12 | * Nicolas Pitre <nico@cam.org> | 12 | * Nicolas Pitre <nico@fluxnic.net> |
13 | * Andrew Christian <andrew.christian@hp.com> | 13 | * Andrew Christian <andrew.christian@hp.com> |
14 | * | 14 | * |
15 | * Converted to the RTC subsystem and Driver Model | 15 | * Converted to the RTC subsystem and Driver Model |
@@ -39,10 +39,10 @@ | |||
39 | #include <mach/regs-ost.h> | 39 | #include <mach/regs-ost.h> |
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | #define RTC_DEF_DIVIDER 32768 - 1 | 42 | #define RTC_DEF_DIVIDER (32768 - 1) |
43 | #define RTC_DEF_TRIM 0 | 43 | #define RTC_DEF_TRIM 0 |
44 | 44 | ||
45 | static unsigned long rtc_freq = 1024; | 45 | static const unsigned long RTC_FREQ = 1024; |
46 | static unsigned long timer_freq; | 46 | static unsigned long timer_freq; |
47 | static struct rtc_time rtc_alarm; | 47 | static struct rtc_time rtc_alarm; |
48 | static DEFINE_SPINLOCK(sa1100_rtc_lock); | 48 | static DEFINE_SPINLOCK(sa1100_rtc_lock); |
@@ -61,7 +61,8 @@ static inline int rtc_periodic_alarm(struct rtc_time *tm) | |||
61 | * Calculate the next alarm time given the requested alarm time mask | 61 | * Calculate the next alarm time given the requested alarm time mask |
62 | * and the current time. | 62 | * and the current time. |
63 | */ | 63 | */ |
64 | static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc_time *alrm) | 64 | static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, |
65 | struct rtc_time *alrm) | ||
65 | { | 66 | { |
66 | unsigned long next_time; | 67 | unsigned long next_time; |
67 | unsigned long now_time; | 68 | unsigned long now_time; |
@@ -116,7 +117,23 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) | |||
116 | rtsr = RTSR; | 117 | rtsr = RTSR; |
117 | /* clear interrupt sources */ | 118 | /* clear interrupt sources */ |
118 | RTSR = 0; | 119 | RTSR = 0; |
119 | RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2); | 120 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. |
121 | * See also the comments in sa1100_rtc_probe(). */ | ||
122 | if (rtsr & (RTSR_ALE | RTSR_HZE)) { | ||
123 | /* This is the original code, before there was the if test | ||
124 | * above. This code does not clear interrupts that were not | ||
125 | * enabled. */ | ||
126 | RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2); | ||
127 | } else { | ||
128 | /* For some reason, it is possible to enter this routine | ||
129 | * without interruptions enabled, it has been tested with | ||
130 | * several units (Bug in SA11xx chip?). | ||
131 | * | ||
132 | * This situation leads to an infinite "loop" of interrupt | ||
133 | * routine calling and as a result the processor seems to | ||
134 | * lock on its first call to open(). */ | ||
135 | RTSR = RTSR_AL | RTSR_HZ; | ||
136 | } | ||
120 | 137 | ||
121 | /* clear alarm interrupt if it has occurred */ | 138 | /* clear alarm interrupt if it has occurred */ |
122 | if (rtsr & RTSR_AL) | 139 | if (rtsr & RTSR_AL) |
@@ -139,8 +156,58 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) | |||
139 | return IRQ_HANDLED; | 156 | return IRQ_HANDLED; |
140 | } | 157 | } |
141 | 158 | ||
159 | static int sa1100_irq_set_freq(struct device *dev, int freq) | ||
160 | { | ||
161 | if (freq < 1 || freq > timer_freq) { | ||
162 | return -EINVAL; | ||
163 | } else { | ||
164 | struct rtc_device *rtc = (struct rtc_device *)dev; | ||
165 | |||
166 | rtc->irq_freq = freq; | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | } | ||
171 | |||
142 | static int rtc_timer1_count; | 172 | static int rtc_timer1_count; |
143 | 173 | ||
174 | static int sa1100_irq_set_state(struct device *dev, int enabled) | ||
175 | { | ||
176 | spin_lock_irq(&sa1100_rtc_lock); | ||
177 | if (enabled) { | ||
178 | struct rtc_device *rtc = (struct rtc_device *)dev; | ||
179 | |||
180 | OSMR1 = timer_freq / rtc->irq_freq + OSCR; | ||
181 | OIER |= OIER_E1; | ||
182 | rtc_timer1_count = 1; | ||
183 | } else { | ||
184 | OIER &= ~OIER_E1; | ||
185 | } | ||
186 | spin_unlock_irq(&sa1100_rtc_lock); | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static inline int sa1100_timer1_retrigger(struct rtc_device *rtc) | ||
192 | { | ||
193 | unsigned long diff; | ||
194 | unsigned long period = timer_freq / rtc->irq_freq; | ||
195 | |||
196 | spin_lock_irq(&sa1100_rtc_lock); | ||
197 | |||
198 | do { | ||
199 | OSMR1 += period; | ||
200 | diff = OSMR1 - OSCR; | ||
201 | /* If OSCR > OSMR1, diff is a very large number (unsigned | ||
202 | * math). This means we have a lost interrupt. */ | ||
203 | } while (diff > period); | ||
204 | OIER |= OIER_E1; | ||
205 | |||
206 | spin_unlock_irq(&sa1100_rtc_lock); | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
144 | static irqreturn_t timer1_interrupt(int irq, void *dev_id) | 211 | static irqreturn_t timer1_interrupt(int irq, void *dev_id) |
145 | { | 212 | { |
146 | struct platform_device *pdev = to_platform_device(dev_id); | 213 | struct platform_device *pdev = to_platform_device(dev_id); |
@@ -158,7 +225,11 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id) | |||
158 | rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF); | 225 | rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF); |
159 | 226 | ||
160 | if (rtc_timer1_count == 1) | 227 | if (rtc_timer1_count == 1) |
161 | rtc_timer1_count = (rtc_freq * ((1 << 30) / (timer_freq >> 2))); | 228 | rtc_timer1_count = |
229 | (rtc->irq_freq * ((1 << 30) / (timer_freq >> 2))); | ||
230 | |||
231 | /* retrigger. */ | ||
232 | sa1100_timer1_retrigger(rtc); | ||
162 | 233 | ||
163 | return IRQ_HANDLED; | 234 | return IRQ_HANDLED; |
164 | } | 235 | } |
@@ -166,8 +237,10 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id) | |||
166 | static int sa1100_rtc_read_callback(struct device *dev, int data) | 237 | static int sa1100_rtc_read_callback(struct device *dev, int data) |
167 | { | 238 | { |
168 | if (data & RTC_PF) { | 239 | if (data & RTC_PF) { |
240 | struct rtc_device *rtc = (struct rtc_device *)dev; | ||
241 | |||
169 | /* interpolate missed periods and set match for the next */ | 242 | /* interpolate missed periods and set match for the next */ |
170 | unsigned long period = timer_freq / rtc_freq; | 243 | unsigned long period = timer_freq / rtc->irq_freq; |
171 | unsigned long oscr = OSCR; | 244 | unsigned long oscr = OSCR; |
172 | unsigned long osmr1 = OSMR1; | 245 | unsigned long osmr1 = OSMR1; |
173 | unsigned long missed = (oscr - osmr1)/period; | 246 | unsigned long missed = (oscr - osmr1)/period; |
@@ -178,7 +251,7 @@ static int sa1100_rtc_read_callback(struct device *dev, int data) | |||
178 | * Here we compare (match - OSCR) 8 instead of 0 -- | 251 | * Here we compare (match - OSCR) 8 instead of 0 -- |
179 | * see comment in pxa_timer_interrupt() for explanation. | 252 | * see comment in pxa_timer_interrupt() for explanation. |
180 | */ | 253 | */ |
181 | while( (signed long)((osmr1 = OSMR1) - OSCR) <= 8 ) { | 254 | while ((signed long)((osmr1 = OSMR1) - OSCR) <= 8) { |
182 | data += 0x100; | 255 | data += 0x100; |
183 | OSSR = OSSR_M1; /* clear match on timer 1 */ | 256 | OSSR = OSSR_M1; /* clear match on timer 1 */ |
184 | OSMR1 = osmr1 + period; | 257 | OSMR1 = osmr1 + period; |
@@ -190,25 +263,29 @@ static int sa1100_rtc_read_callback(struct device *dev, int data) | |||
190 | static int sa1100_rtc_open(struct device *dev) | 263 | static int sa1100_rtc_open(struct device *dev) |
191 | { | 264 | { |
192 | int ret; | 265 | int ret; |
266 | struct rtc_device *rtc = (struct rtc_device *)dev; | ||
193 | 267 | ||
194 | ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED, | 268 | ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED, |
195 | "rtc 1Hz", dev); | 269 | "rtc 1Hz", dev); |
196 | if (ret) { | 270 | if (ret) { |
197 | dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz); | 271 | dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz); |
198 | goto fail_ui; | 272 | goto fail_ui; |
199 | } | 273 | } |
200 | ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED, | 274 | ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED, |
201 | "rtc Alrm", dev); | 275 | "rtc Alrm", dev); |
202 | if (ret) { | 276 | if (ret) { |
203 | dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm); | 277 | dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm); |
204 | goto fail_ai; | 278 | goto fail_ai; |
205 | } | 279 | } |
206 | ret = request_irq(IRQ_OST1, timer1_interrupt, IRQF_DISABLED, | 280 | ret = request_irq(IRQ_OST1, timer1_interrupt, IRQF_DISABLED, |
207 | "rtc timer", dev); | 281 | "rtc timer", dev); |
208 | if (ret) { | 282 | if (ret) { |
209 | dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1); | 283 | dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1); |
210 | goto fail_pi; | 284 | goto fail_pi; |
211 | } | 285 | } |
286 | rtc->max_user_freq = RTC_FREQ; | ||
287 | sa1100_irq_set_freq(dev, RTC_FREQ); | ||
288 | |||
212 | return 0; | 289 | return 0; |
213 | 290 | ||
214 | fail_pi: | 291 | fail_pi: |
@@ -236,7 +313,7 @@ static void sa1100_rtc_release(struct device *dev) | |||
236 | static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd, | 313 | static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd, |
237 | unsigned long arg) | 314 | unsigned long arg) |
238 | { | 315 | { |
239 | switch(cmd) { | 316 | switch (cmd) { |
240 | case RTC_AIE_OFF: | 317 | case RTC_AIE_OFF: |
241 | spin_lock_irq(&sa1100_rtc_lock); | 318 | spin_lock_irq(&sa1100_rtc_lock); |
242 | RTSR &= ~RTSR_ALE; | 319 | RTSR &= ~RTSR_ALE; |
@@ -257,25 +334,6 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd, | |||
257 | RTSR |= RTSR_HZE; | 334 | RTSR |= RTSR_HZE; |
258 | spin_unlock_irq(&sa1100_rtc_lock); | 335 | spin_unlock_irq(&sa1100_rtc_lock); |
259 | return 0; | 336 | return 0; |
260 | case RTC_PIE_OFF: | ||
261 | spin_lock_irq(&sa1100_rtc_lock); | ||
262 | OIER &= ~OIER_E1; | ||
263 | spin_unlock_irq(&sa1100_rtc_lock); | ||
264 | return 0; | ||
265 | case RTC_PIE_ON: | ||
266 | spin_lock_irq(&sa1100_rtc_lock); | ||
267 | OSMR1 = timer_freq / rtc_freq + OSCR; | ||
268 | OIER |= OIER_E1; | ||
269 | rtc_timer1_count = 1; | ||
270 | spin_unlock_irq(&sa1100_rtc_lock); | ||
271 | return 0; | ||
272 | case RTC_IRQP_READ: | ||
273 | return put_user(rtc_freq, (unsigned long *)arg); | ||
274 | case RTC_IRQP_SET: | ||
275 | if (arg < 1 || arg > timer_freq) | ||
276 | return -EINVAL; | ||
277 | rtc_freq = arg; | ||
278 | return 0; | ||
279 | } | 337 | } |
280 | return -ENOIOCTLCMD; | 338 | return -ENOIOCTLCMD; |
281 | } | 339 | } |
@@ -327,12 +385,15 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
327 | 385 | ||
328 | static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) | 386 | static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) |
329 | { | 387 | { |
388 | struct rtc_device *rtc = (struct rtc_device *)dev; | ||
389 | |||
330 | seq_printf(seq, "trim/divider\t: 0x%08x\n", (u32) RTTR); | 390 | seq_printf(seq, "trim/divider\t: 0x%08x\n", (u32) RTTR); |
331 | seq_printf(seq, "update_IRQ\t: %s\n", | 391 | seq_printf(seq, "update_IRQ\t: %s\n", |
332 | (RTSR & RTSR_HZE) ? "yes" : "no"); | 392 | (RTSR & RTSR_HZE) ? "yes" : "no"); |
333 | seq_printf(seq, "periodic_IRQ\t: %s\n", | 393 | seq_printf(seq, "periodic_IRQ\t: %s\n", |
334 | (OIER & OIER_E1) ? "yes" : "no"); | 394 | (OIER & OIER_E1) ? "yes" : "no"); |
335 | seq_printf(seq, "periodic_freq\t: %ld\n", rtc_freq); | 395 | seq_printf(seq, "periodic_freq\t: %d\n", rtc->irq_freq); |
396 | seq_printf(seq, "RTSR\t\t: 0x%08x\n", (u32)RTSR); | ||
336 | 397 | ||
337 | return 0; | 398 | return 0; |
338 | } | 399 | } |
@@ -347,6 +408,8 @@ static const struct rtc_class_ops sa1100_rtc_ops = { | |||
347 | .read_alarm = sa1100_rtc_read_alarm, | 408 | .read_alarm = sa1100_rtc_read_alarm, |
348 | .set_alarm = sa1100_rtc_set_alarm, | 409 | .set_alarm = sa1100_rtc_set_alarm, |
349 | .proc = sa1100_rtc_proc, | 410 | .proc = sa1100_rtc_proc, |
411 | .irq_set_freq = sa1100_irq_set_freq, | ||
412 | .irq_set_state = sa1100_irq_set_state, | ||
350 | }; | 413 | }; |
351 | 414 | ||
352 | static int sa1100_rtc_probe(struct platform_device *pdev) | 415 | static int sa1100_rtc_probe(struct platform_device *pdev) |
@@ -364,7 +427,8 @@ static int sa1100_rtc_probe(struct platform_device *pdev) | |||
364 | */ | 427 | */ |
365 | if (RTTR == 0) { | 428 | if (RTTR == 0) { |
366 | RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); | 429 | RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); |
367 | dev_warn(&pdev->dev, "warning: initializing default clock divider/trim value\n"); | 430 | dev_warn(&pdev->dev, "warning: " |
431 | "initializing default clock divider/trim value\n"); | ||
368 | /* The current RTC value probably doesn't make sense either */ | 432 | /* The current RTC value probably doesn't make sense either */ |
369 | RCNR = 0; | 433 | RCNR = 0; |
370 | } | 434 | } |
@@ -372,13 +436,42 @@ static int sa1100_rtc_probe(struct platform_device *pdev) | |||
372 | device_init_wakeup(&pdev->dev, 1); | 436 | device_init_wakeup(&pdev->dev, 1); |
373 | 437 | ||
374 | rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops, | 438 | rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops, |
375 | THIS_MODULE); | 439 | THIS_MODULE); |
376 | 440 | ||
377 | if (IS_ERR(rtc)) | 441 | if (IS_ERR(rtc)) |
378 | return PTR_ERR(rtc); | 442 | return PTR_ERR(rtc); |
379 | 443 | ||
380 | platform_set_drvdata(pdev, rtc); | 444 | platform_set_drvdata(pdev, rtc); |
381 | 445 | ||
446 | /* Set the irq_freq */ | ||
447 | /*TODO: Find out who is messing with this value after we initialize | ||
448 | * it here.*/ | ||
449 | rtc->irq_freq = RTC_FREQ; | ||
450 | |||
451 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. | ||
452 | * See also the comments in sa1100_rtc_interrupt(). | ||
453 | * | ||
454 | * Sometimes bit 1 of the RTSR (RTSR_HZ) will wake up 1, which means an | ||
455 | * interrupt pending, even though interrupts were never enabled. | ||
456 | * In this case, this bit it must be reset before enabling | ||
457 | * interruptions to avoid a nonexistent interrupt to occur. | ||
458 | * | ||
459 | * In principle, the same problem would apply to bit 0, although it has | ||
460 | * never been observed to happen. | ||
461 | * | ||
462 | * This issue is addressed both here and in sa1100_rtc_interrupt(). | ||
463 | * If the issue is not addressed here, in the times when the processor | ||
464 | * wakes up with the bit set there will be one spurious interrupt. | ||
465 | * | ||
466 | * The issue is also dealt with in sa1100_rtc_interrupt() to be on the | ||
467 | * safe side, once the condition that lead to this strange | ||
468 | * initialization is unknown and could in principle happen during | ||
469 | * normal processing. | ||
470 | * | ||
471 | * Notice that clearing bit 1 and 0 is accomplished by writting ONES to | ||
472 | * the corresponding bits in RTSR. */ | ||
473 | RTSR = RTSR_AL | RTSR_HZ; | ||
474 | |||
382 | return 0; | 475 | return 0; |
383 | } | 476 | } |
384 | 477 | ||
@@ -386,38 +479,41 @@ static int sa1100_rtc_remove(struct platform_device *pdev) | |||
386 | { | 479 | { |
387 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 480 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
388 | 481 | ||
389 | if (rtc) | 482 | if (rtc) |
390 | rtc_device_unregister(rtc); | 483 | rtc_device_unregister(rtc); |
391 | 484 | ||
392 | return 0; | 485 | return 0; |
393 | } | 486 | } |
394 | 487 | ||
395 | #ifdef CONFIG_PM | 488 | #ifdef CONFIG_PM |
396 | static int sa1100_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 489 | static int sa1100_rtc_suspend(struct device *dev) |
397 | { | 490 | { |
398 | if (device_may_wakeup(&pdev->dev)) | 491 | if (device_may_wakeup(dev)) |
399 | enable_irq_wake(IRQ_RTCAlrm); | 492 | enable_irq_wake(IRQ_RTCAlrm); |
400 | return 0; | 493 | return 0; |
401 | } | 494 | } |
402 | 495 | ||
403 | static int sa1100_rtc_resume(struct platform_device *pdev) | 496 | static int sa1100_rtc_resume(struct device *dev) |
404 | { | 497 | { |
405 | if (device_may_wakeup(&pdev->dev)) | 498 | if (device_may_wakeup(dev)) |
406 | disable_irq_wake(IRQ_RTCAlrm); | 499 | disable_irq_wake(IRQ_RTCAlrm); |
407 | return 0; | 500 | return 0; |
408 | } | 501 | } |
409 | #else | 502 | |
410 | #define sa1100_rtc_suspend NULL | 503 | static const struct dev_pm_ops sa1100_rtc_pm_ops = { |
411 | #define sa1100_rtc_resume NULL | 504 | .suspend = sa1100_rtc_suspend, |
505 | .resume = sa1100_rtc_resume, | ||
506 | }; | ||
412 | #endif | 507 | #endif |
413 | 508 | ||
414 | static struct platform_driver sa1100_rtc_driver = { | 509 | static struct platform_driver sa1100_rtc_driver = { |
415 | .probe = sa1100_rtc_probe, | 510 | .probe = sa1100_rtc_probe, |
416 | .remove = sa1100_rtc_remove, | 511 | .remove = sa1100_rtc_remove, |
417 | .suspend = sa1100_rtc_suspend, | ||
418 | .resume = sa1100_rtc_resume, | ||
419 | .driver = { | 512 | .driver = { |
420 | .name = "sa1100-rtc", | 513 | .name = "sa1100-rtc", |
514 | #ifdef CONFIG_PM | ||
515 | .pm = &sa1100_rtc_pm_ops, | ||
516 | #endif | ||
421 | }, | 517 | }, |
422 | }; | 518 | }; |
423 | 519 | ||
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index d7310adb7152..06e41ed93230 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c | |||
@@ -26,10 +26,11 @@ | |||
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/log2.h> | 27 | #include <linux/log2.h> |
28 | #include <linux/clk.h> | 28 | #include <linux/clk.h> |
29 | #include <linux/slab.h> | ||
29 | #include <asm/rtc.h> | 30 | #include <asm/rtc.h> |
30 | 31 | ||
31 | #define DRV_NAME "sh-rtc" | 32 | #define DRV_NAME "sh-rtc" |
32 | #define DRV_VERSION "0.2.2" | 33 | #define DRV_VERSION "0.2.3" |
33 | 34 | ||
34 | #define RTC_REG(r) ((r) * rtc_reg_size) | 35 | #define RTC_REG(r) ((r) * rtc_reg_size) |
35 | 36 | ||
@@ -215,7 +216,7 @@ static irqreturn_t sh_rtc_shared(int irq, void *dev_id) | |||
215 | return IRQ_RETVAL(ret); | 216 | return IRQ_RETVAL(ret); |
216 | } | 217 | } |
217 | 218 | ||
218 | static inline void sh_rtc_setpie(struct device *dev, unsigned int enable) | 219 | static int sh_rtc_irq_set_state(struct device *dev, int enable) |
219 | { | 220 | { |
220 | struct sh_rtc *rtc = dev_get_drvdata(dev); | 221 | struct sh_rtc *rtc = dev_get_drvdata(dev); |
221 | unsigned int tmp; | 222 | unsigned int tmp; |
@@ -225,17 +226,22 @@ static inline void sh_rtc_setpie(struct device *dev, unsigned int enable) | |||
225 | tmp = readb(rtc->regbase + RCR2); | 226 | tmp = readb(rtc->regbase + RCR2); |
226 | 227 | ||
227 | if (enable) { | 228 | if (enable) { |
229 | rtc->periodic_freq |= PF_KOU; | ||
228 | tmp &= ~RCR2_PEF; /* Clear PES bit */ | 230 | tmp &= ~RCR2_PEF; /* Clear PES bit */ |
229 | tmp |= (rtc->periodic_freq & ~PF_HP); /* Set PES2-0 */ | 231 | tmp |= (rtc->periodic_freq & ~PF_HP); /* Set PES2-0 */ |
230 | } else | 232 | } else { |
233 | rtc->periodic_freq &= ~PF_KOU; | ||
231 | tmp &= ~(RCR2_PESMASK | RCR2_PEF); | 234 | tmp &= ~(RCR2_PESMASK | RCR2_PEF); |
235 | } | ||
232 | 236 | ||
233 | writeb(tmp, rtc->regbase + RCR2); | 237 | writeb(tmp, rtc->regbase + RCR2); |
234 | 238 | ||
235 | spin_unlock_irq(&rtc->lock); | 239 | spin_unlock_irq(&rtc->lock); |
240 | |||
241 | return 0; | ||
236 | } | 242 | } |
237 | 243 | ||
238 | static inline int sh_rtc_setfreq(struct device *dev, unsigned int freq) | 244 | static int sh_rtc_irq_set_freq(struct device *dev, int freq) |
239 | { | 245 | { |
240 | struct sh_rtc *rtc = dev_get_drvdata(dev); | 246 | struct sh_rtc *rtc = dev_get_drvdata(dev); |
241 | int tmp, ret = 0; | 247 | int tmp, ret = 0; |
@@ -278,10 +284,8 @@ static inline int sh_rtc_setfreq(struct device *dev, unsigned int freq) | |||
278 | ret = -ENOTSUPP; | 284 | ret = -ENOTSUPP; |
279 | } | 285 | } |
280 | 286 | ||
281 | if (ret == 0) { | 287 | if (ret == 0) |
282 | rtc->periodic_freq |= tmp; | 288 | rtc->periodic_freq |= tmp; |
283 | rtc->rtc_dev->irq_freq = freq; | ||
284 | } | ||
285 | 289 | ||
286 | spin_unlock_irq(&rtc->lock); | 290 | spin_unlock_irq(&rtc->lock); |
287 | return ret; | 291 | return ret; |
@@ -346,10 +350,6 @@ static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
346 | unsigned int ret = 0; | 350 | unsigned int ret = 0; |
347 | 351 | ||
348 | switch (cmd) { | 352 | switch (cmd) { |
349 | case RTC_PIE_OFF: | ||
350 | case RTC_PIE_ON: | ||
351 | sh_rtc_setpie(dev, cmd == RTC_PIE_ON); | ||
352 | break; | ||
353 | case RTC_AIE_OFF: | 353 | case RTC_AIE_OFF: |
354 | case RTC_AIE_ON: | 354 | case RTC_AIE_ON: |
355 | sh_rtc_setaie(dev, cmd == RTC_AIE_ON); | 355 | sh_rtc_setaie(dev, cmd == RTC_AIE_ON); |
@@ -362,13 +362,6 @@ static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
362 | rtc->periodic_freq |= PF_OXS; | 362 | rtc->periodic_freq |= PF_OXS; |
363 | sh_rtc_setcie(dev, 1); | 363 | sh_rtc_setcie(dev, 1); |
364 | break; | 364 | break; |
365 | case RTC_IRQP_READ: | ||
366 | ret = put_user(rtc->rtc_dev->irq_freq, | ||
367 | (unsigned long __user *)arg); | ||
368 | break; | ||
369 | case RTC_IRQP_SET: | ||
370 | ret = sh_rtc_setfreq(dev, arg); | ||
371 | break; | ||
372 | default: | 365 | default: |
373 | ret = -ENOIOCTLCMD; | 366 | ret = -ENOIOCTLCMD; |
374 | } | 367 | } |
@@ -602,28 +595,6 @@ static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | |||
602 | return 0; | 595 | return 0; |
603 | } | 596 | } |
604 | 597 | ||
605 | static int sh_rtc_irq_set_state(struct device *dev, int enabled) | ||
606 | { | ||
607 | struct platform_device *pdev = to_platform_device(dev); | ||
608 | struct sh_rtc *rtc = platform_get_drvdata(pdev); | ||
609 | |||
610 | if (enabled) { | ||
611 | rtc->periodic_freq |= PF_KOU; | ||
612 | return sh_rtc_ioctl(dev, RTC_PIE_ON, 0); | ||
613 | } else { | ||
614 | rtc->periodic_freq &= ~PF_KOU; | ||
615 | return sh_rtc_ioctl(dev, RTC_PIE_OFF, 0); | ||
616 | } | ||
617 | } | ||
618 | |||
619 | static int sh_rtc_irq_set_freq(struct device *dev, int freq) | ||
620 | { | ||
621 | if (!is_power_of_2(freq)) | ||
622 | return -EINVAL; | ||
623 | |||
624 | return sh_rtc_ioctl(dev, RTC_IRQP_SET, freq); | ||
625 | } | ||
626 | |||
627 | static struct rtc_class_ops sh_rtc_ops = { | 598 | static struct rtc_class_ops sh_rtc_ops = { |
628 | .ioctl = sh_rtc_ioctl, | 599 | .ioctl = sh_rtc_ioctl, |
629 | .read_time = sh_rtc_read_time, | 600 | .read_time = sh_rtc_read_time, |
@@ -635,7 +606,7 @@ static struct rtc_class_ops sh_rtc_ops = { | |||
635 | .proc = sh_rtc_proc, | 606 | .proc = sh_rtc_proc, |
636 | }; | 607 | }; |
637 | 608 | ||
638 | static int __devinit sh_rtc_probe(struct platform_device *pdev) | 609 | static int __init sh_rtc_probe(struct platform_device *pdev) |
639 | { | 610 | { |
640 | struct sh_rtc *rtc; | 611 | struct sh_rtc *rtc; |
641 | struct resource *res; | 612 | struct resource *res; |
@@ -702,13 +673,6 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) | |||
702 | 673 | ||
703 | clk_enable(rtc->clk); | 674 | clk_enable(rtc->clk); |
704 | 675 | ||
705 | rtc->rtc_dev = rtc_device_register("sh", &pdev->dev, | ||
706 | &sh_rtc_ops, THIS_MODULE); | ||
707 | if (IS_ERR(rtc->rtc_dev)) { | ||
708 | ret = PTR_ERR(rtc->rtc_dev); | ||
709 | goto err_unmap; | ||
710 | } | ||
711 | |||
712 | rtc->capabilities = RTC_DEF_CAPABILITIES; | 676 | rtc->capabilities = RTC_DEF_CAPABILITIES; |
713 | if (pdev->dev.platform_data) { | 677 | if (pdev->dev.platform_data) { |
714 | struct sh_rtc_platform_info *pinfo = pdev->dev.platform_data; | 678 | struct sh_rtc_platform_info *pinfo = pdev->dev.platform_data; |
@@ -720,10 +684,6 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) | |||
720 | rtc->capabilities |= pinfo->capabilities; | 684 | rtc->capabilities |= pinfo->capabilities; |
721 | } | 685 | } |
722 | 686 | ||
723 | rtc->rtc_dev->max_user_freq = 256; | ||
724 | |||
725 | platform_set_drvdata(pdev, rtc); | ||
726 | |||
727 | if (rtc->carry_irq <= 0) { | 687 | if (rtc->carry_irq <= 0) { |
728 | /* register shared periodic/carry/alarm irq */ | 688 | /* register shared periodic/carry/alarm irq */ |
729 | ret = request_irq(rtc->periodic_irq, sh_rtc_shared, | 689 | ret = request_irq(rtc->periodic_irq, sh_rtc_shared, |
@@ -767,13 +727,26 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) | |||
767 | } | 727 | } |
768 | } | 728 | } |
769 | 729 | ||
730 | platform_set_drvdata(pdev, rtc); | ||
731 | |||
770 | /* everything disabled by default */ | 732 | /* everything disabled by default */ |
771 | rtc->periodic_freq = 0; | 733 | sh_rtc_irq_set_freq(&pdev->dev, 0); |
772 | rtc->rtc_dev->irq_freq = 0; | 734 | sh_rtc_irq_set_state(&pdev->dev, 0); |
773 | sh_rtc_setpie(&pdev->dev, 0); | ||
774 | sh_rtc_setaie(&pdev->dev, 0); | 735 | sh_rtc_setaie(&pdev->dev, 0); |
775 | sh_rtc_setcie(&pdev->dev, 0); | 736 | sh_rtc_setcie(&pdev->dev, 0); |
776 | 737 | ||
738 | rtc->rtc_dev = rtc_device_register("sh", &pdev->dev, | ||
739 | &sh_rtc_ops, THIS_MODULE); | ||
740 | if (IS_ERR(rtc->rtc_dev)) { | ||
741 | ret = PTR_ERR(rtc->rtc_dev); | ||
742 | free_irq(rtc->periodic_irq, rtc); | ||
743 | free_irq(rtc->carry_irq, rtc); | ||
744 | free_irq(rtc->alarm_irq, rtc); | ||
745 | goto err_unmap; | ||
746 | } | ||
747 | |||
748 | rtc->rtc_dev->max_user_freq = 256; | ||
749 | |||
777 | /* reset rtc to epoch 0 if time is invalid */ | 750 | /* reset rtc to epoch 0 if time is invalid */ |
778 | if (rtc_read_time(rtc->rtc_dev, &r) < 0) { | 751 | if (rtc_read_time(rtc->rtc_dev, &r) < 0) { |
779 | rtc_time_to_tm(0, &r); | 752 | rtc_time_to_tm(0, &r); |
@@ -788,21 +761,20 @@ err_unmap: | |||
788 | clk_put(rtc->clk); | 761 | clk_put(rtc->clk); |
789 | iounmap(rtc->regbase); | 762 | iounmap(rtc->regbase); |
790 | err_badmap: | 763 | err_badmap: |
791 | release_resource(rtc->res); | 764 | release_mem_region(rtc->res->start, rtc->regsize); |
792 | err_badres: | 765 | err_badres: |
793 | kfree(rtc); | 766 | kfree(rtc); |
794 | 767 | ||
795 | return ret; | 768 | return ret; |
796 | } | 769 | } |
797 | 770 | ||
798 | static int __devexit sh_rtc_remove(struct platform_device *pdev) | 771 | static int __exit sh_rtc_remove(struct platform_device *pdev) |
799 | { | 772 | { |
800 | struct sh_rtc *rtc = platform_get_drvdata(pdev); | 773 | struct sh_rtc *rtc = platform_get_drvdata(pdev); |
801 | 774 | ||
802 | if (likely(rtc->rtc_dev)) | 775 | rtc_device_unregister(rtc->rtc_dev); |
803 | rtc_device_unregister(rtc->rtc_dev); | 776 | sh_rtc_irq_set_state(&pdev->dev, 0); |
804 | 777 | ||
805 | sh_rtc_setpie(&pdev->dev, 0); | ||
806 | sh_rtc_setaie(&pdev->dev, 0); | 778 | sh_rtc_setaie(&pdev->dev, 0); |
807 | sh_rtc_setcie(&pdev->dev, 0); | 779 | sh_rtc_setcie(&pdev->dev, 0); |
808 | 780 | ||
@@ -813,9 +785,8 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev) | |||
813 | free_irq(rtc->alarm_irq, rtc); | 785 | free_irq(rtc->alarm_irq, rtc); |
814 | } | 786 | } |
815 | 787 | ||
816 | release_resource(rtc->res); | ||
817 | |||
818 | iounmap(rtc->regbase); | 788 | iounmap(rtc->regbase); |
789 | release_mem_region(rtc->res->start, rtc->regsize); | ||
819 | 790 | ||
820 | clk_disable(rtc->clk); | 791 | clk_disable(rtc->clk); |
821 | clk_put(rtc->clk); | 792 | clk_put(rtc->clk); |
@@ -856,7 +827,7 @@ static int sh_rtc_resume(struct device *dev) | |||
856 | return 0; | 827 | return 0; |
857 | } | 828 | } |
858 | 829 | ||
859 | static struct dev_pm_ops sh_rtc_dev_pm_ops = { | 830 | static const struct dev_pm_ops sh_rtc_dev_pm_ops = { |
860 | .suspend = sh_rtc_suspend, | 831 | .suspend = sh_rtc_suspend, |
861 | .resume = sh_rtc_resume, | 832 | .resume = sh_rtc_resume, |
862 | }; | 833 | }; |
@@ -867,13 +838,12 @@ static struct platform_driver sh_rtc_platform_driver = { | |||
867 | .owner = THIS_MODULE, | 838 | .owner = THIS_MODULE, |
868 | .pm = &sh_rtc_dev_pm_ops, | 839 | .pm = &sh_rtc_dev_pm_ops, |
869 | }, | 840 | }, |
870 | .probe = sh_rtc_probe, | 841 | .remove = __exit_p(sh_rtc_remove), |
871 | .remove = __devexit_p(sh_rtc_remove), | ||
872 | }; | 842 | }; |
873 | 843 | ||
874 | static int __init sh_rtc_init(void) | 844 | static int __init sh_rtc_init(void) |
875 | { | 845 | { |
876 | return platform_driver_register(&sh_rtc_platform_driver); | 846 | return platform_driver_probe(&sh_rtc_platform_driver, sh_rtc_probe); |
877 | } | 847 | } |
878 | 848 | ||
879 | static void __exit sh_rtc_exit(void) | 849 | static void __exit sh_rtc_exit(void) |
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index 7d1547b0070e..3b943673cd3e 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * A RTC driver for the Simtek STK17TA8 | 2 | * A RTC driver for the Simtek STK17TA8 |
3 | * | 3 | * |
4 | * By Thomas Hommel <thomas.hommel@gefanuc.com> | 4 | * By Thomas Hommel <thomas.hommel@ge.com> |
5 | * | 5 | * |
6 | * Based on the DS1553 driver from | 6 | * Based on the DS1553 driver from |
7 | * Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 7 | * Atsushi Nemoto <anemo@mba.ocn.ne.jp> |
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/bcd.h> | 14 | #include <linux/bcd.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/gfp.h> | ||
17 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
18 | #include <linux/jiffies.h> | 19 | #include <linux/jiffies.h> |
19 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
@@ -62,7 +63,6 @@ | |||
62 | struct rtc_plat_data { | 63 | struct rtc_plat_data { |
63 | struct rtc_device *rtc; | 64 | struct rtc_device *rtc; |
64 | void __iomem *ioaddr; | 65 | void __iomem *ioaddr; |
65 | unsigned long baseaddr; | ||
66 | unsigned long last_jiffies; | 66 | unsigned long last_jiffies; |
67 | int irq; | 67 | int irq; |
68 | unsigned int irqen; | 68 | unsigned int irqen; |
@@ -70,6 +70,7 @@ struct rtc_plat_data { | |||
70 | int alrm_min; | 70 | int alrm_min; |
71 | int alrm_hour; | 71 | int alrm_hour; |
72 | int alrm_mday; | 72 | int alrm_mday; |
73 | spinlock_t lock; | ||
73 | }; | 74 | }; |
74 | 75 | ||
75 | static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm) | 76 | static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm) |
@@ -142,7 +143,7 @@ static void stk17ta8_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
142 | unsigned long irqflags; | 143 | unsigned long irqflags; |
143 | u8 flags; | 144 | u8 flags; |
144 | 145 | ||
145 | spin_lock_irqsave(&pdata->rtc->irq_lock, irqflags); | 146 | spin_lock_irqsave(&pdata->lock, irqflags); |
146 | 147 | ||
147 | flags = readb(ioaddr + RTC_FLAGS); | 148 | flags = readb(ioaddr + RTC_FLAGS); |
148 | writeb(flags | RTC_WRITE, ioaddr + RTC_FLAGS); | 149 | writeb(flags | RTC_WRITE, ioaddr + RTC_FLAGS); |
@@ -162,7 +163,7 @@ static void stk17ta8_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
162 | writeb(pdata->irqen ? RTC_INTS_AIE : 0, ioaddr + RTC_INTERRUPTS); | 163 | writeb(pdata->irqen ? RTC_INTS_AIE : 0, ioaddr + RTC_INTERRUPTS); |
163 | readb(ioaddr + RTC_FLAGS); /* clear interrupts */ | 164 | readb(ioaddr + RTC_FLAGS); /* clear interrupts */ |
164 | writeb(flags & ~RTC_WRITE, ioaddr + RTC_FLAGS); | 165 | writeb(flags & ~RTC_WRITE, ioaddr + RTC_FLAGS); |
165 | spin_unlock_irqrestore(&pdata->rtc->irq_lock, irqflags); | 166 | spin_unlock_irqrestore(&pdata->lock, irqflags); |
166 | } | 167 | } |
167 | 168 | ||
168 | static int stk17ta8_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 169 | static int stk17ta8_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
@@ -202,56 +203,53 @@ static irqreturn_t stk17ta8_rtc_interrupt(int irq, void *dev_id) | |||
202 | struct platform_device *pdev = dev_id; | 203 | struct platform_device *pdev = dev_id; |
203 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 204 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
204 | void __iomem *ioaddr = pdata->ioaddr; | 205 | void __iomem *ioaddr = pdata->ioaddr; |
205 | unsigned long events = RTC_IRQF; | 206 | unsigned long events = 0; |
206 | 207 | ||
208 | spin_lock(&pdata->lock); | ||
207 | /* read and clear interrupt */ | 209 | /* read and clear interrupt */ |
208 | if (!(readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF)) | 210 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF) { |
209 | return IRQ_NONE; | 211 | events = RTC_IRQF; |
210 | if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80) | 212 | if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80) |
211 | events |= RTC_UF; | 213 | events |= RTC_UF; |
212 | else | 214 | else |
213 | events |= RTC_AF; | 215 | events |= RTC_AF; |
214 | rtc_update_irq(pdata->rtc, 1, events); | 216 | if (likely(pdata->rtc)) |
215 | return IRQ_HANDLED; | 217 | rtc_update_irq(pdata->rtc, 1, events); |
218 | } | ||
219 | spin_unlock(&pdata->lock); | ||
220 | return events ? IRQ_HANDLED : IRQ_NONE; | ||
216 | } | 221 | } |
217 | 222 | ||
218 | static int stk17ta8_rtc_ioctl(struct device *dev, unsigned int cmd, | 223 | static int stk17ta8_rtc_alarm_irq_enable(struct device *dev, |
219 | unsigned long arg) | 224 | unsigned int enabled) |
220 | { | 225 | { |
221 | struct platform_device *pdev = to_platform_device(dev); | 226 | struct platform_device *pdev = to_platform_device(dev); |
222 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 227 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
223 | 228 | ||
224 | if (pdata->irq <= 0) | 229 | if (pdata->irq <= 0) |
225 | return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ | 230 | return -EINVAL; |
226 | switch (cmd) { | 231 | if (enabled) |
227 | case RTC_AIE_OFF: | ||
228 | pdata->irqen &= ~RTC_AF; | ||
229 | stk17ta8_rtc_update_alarm(pdata); | ||
230 | break; | ||
231 | case RTC_AIE_ON: | ||
232 | pdata->irqen |= RTC_AF; | 232 | pdata->irqen |= RTC_AF; |
233 | stk17ta8_rtc_update_alarm(pdata); | 233 | else |
234 | break; | 234 | pdata->irqen &= ~RTC_AF; |
235 | default: | 235 | stk17ta8_rtc_update_alarm(pdata); |
236 | return -ENOIOCTLCMD; | ||
237 | } | ||
238 | return 0; | 236 | return 0; |
239 | } | 237 | } |
240 | 238 | ||
241 | static const struct rtc_class_ops stk17ta8_rtc_ops = { | 239 | static const struct rtc_class_ops stk17ta8_rtc_ops = { |
242 | .read_time = stk17ta8_rtc_read_time, | 240 | .read_time = stk17ta8_rtc_read_time, |
243 | .set_time = stk17ta8_rtc_set_time, | 241 | .set_time = stk17ta8_rtc_set_time, |
244 | .read_alarm = stk17ta8_rtc_read_alarm, | 242 | .read_alarm = stk17ta8_rtc_read_alarm, |
245 | .set_alarm = stk17ta8_rtc_set_alarm, | 243 | .set_alarm = stk17ta8_rtc_set_alarm, |
246 | .ioctl = stk17ta8_rtc_ioctl, | 244 | .alarm_irq_enable = stk17ta8_rtc_alarm_irq_enable, |
247 | }; | 245 | }; |
248 | 246 | ||
249 | static ssize_t stk17ta8_nvram_read(struct kobject *kobj, | 247 | static ssize_t stk17ta8_nvram_read(struct file *filp, struct kobject *kobj, |
250 | struct bin_attribute *attr, char *buf, | 248 | struct bin_attribute *attr, char *buf, |
251 | loff_t pos, size_t size) | 249 | loff_t pos, size_t size) |
252 | { | 250 | { |
253 | struct platform_device *pdev = | 251 | struct device *dev = container_of(kobj, struct device, kobj); |
254 | to_platform_device(container_of(kobj, struct device, kobj)); | 252 | struct platform_device *pdev = to_platform_device(dev); |
255 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 253 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
256 | void __iomem *ioaddr = pdata->ioaddr; | 254 | void __iomem *ioaddr = pdata->ioaddr; |
257 | ssize_t count; | 255 | ssize_t count; |
@@ -261,12 +259,12 @@ static ssize_t stk17ta8_nvram_read(struct kobject *kobj, | |||
261 | return count; | 259 | return count; |
262 | } | 260 | } |
263 | 261 | ||
264 | static ssize_t stk17ta8_nvram_write(struct kobject *kobj, | 262 | static ssize_t stk17ta8_nvram_write(struct file *filp, struct kobject *kobj, |
265 | struct bin_attribute *attr, char *buf, | 263 | struct bin_attribute *attr, char *buf, |
266 | loff_t pos, size_t size) | 264 | loff_t pos, size_t size) |
267 | { | 265 | { |
268 | struct platform_device *pdev = | 266 | struct device *dev = container_of(kobj, struct device, kobj); |
269 | to_platform_device(container_of(kobj, struct device, kobj)); | 267 | struct platform_device *pdev = to_platform_device(dev); |
270 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 268 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
271 | void __iomem *ioaddr = pdata->ioaddr; | 269 | void __iomem *ioaddr = pdata->ioaddr; |
272 | ssize_t count; | 270 | ssize_t count; |
@@ -286,33 +284,28 @@ static struct bin_attribute stk17ta8_nvram_attr = { | |||
286 | .write = stk17ta8_nvram_write, | 284 | .write = stk17ta8_nvram_write, |
287 | }; | 285 | }; |
288 | 286 | ||
289 | static int __init stk17ta8_rtc_probe(struct platform_device *pdev) | 287 | static int __devinit stk17ta8_rtc_probe(struct platform_device *pdev) |
290 | { | 288 | { |
291 | struct rtc_device *rtc; | ||
292 | struct resource *res; | 289 | struct resource *res; |
293 | unsigned int cal; | 290 | unsigned int cal; |
294 | unsigned int flags; | 291 | unsigned int flags; |
295 | struct rtc_plat_data *pdata; | 292 | struct rtc_plat_data *pdata; |
296 | void __iomem *ioaddr = NULL; | 293 | void __iomem *ioaddr; |
297 | int ret = 0; | 294 | int ret = 0; |
298 | 295 | ||
299 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 296 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
300 | if (!res) | 297 | if (!res) |
301 | return -ENODEV; | 298 | return -ENODEV; |
302 | 299 | ||
303 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 300 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
304 | if (!pdata) | 301 | if (!pdata) |
305 | return -ENOMEM; | 302 | return -ENOMEM; |
306 | if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) { | 303 | if (!devm_request_mem_region(&pdev->dev, res->start, RTC_REG_SIZE, |
307 | ret = -EBUSY; | 304 | pdev->name)) |
308 | goto out; | 305 | return -EBUSY; |
309 | } | 306 | ioaddr = devm_ioremap(&pdev->dev, res->start, RTC_REG_SIZE); |
310 | pdata->baseaddr = res->start; | 307 | if (!ioaddr) |
311 | ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE); | 308 | return -ENOMEM; |
312 | if (!ioaddr) { | ||
313 | ret = -ENOMEM; | ||
314 | goto out; | ||
315 | } | ||
316 | pdata->ioaddr = ioaddr; | 309 | pdata->ioaddr = ioaddr; |
317 | pdata->irq = platform_get_irq(pdev, 0); | 310 | pdata->irq = platform_get_irq(pdev, 0); |
318 | 311 | ||
@@ -328,9 +321,13 @@ static int __init stk17ta8_rtc_probe(struct platform_device *pdev) | |||
328 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_PF) | 321 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_PF) |
329 | dev_warn(&pdev->dev, "voltage-low detected.\n"); | 322 | dev_warn(&pdev->dev, "voltage-low detected.\n"); |
330 | 323 | ||
324 | spin_lock_init(&pdata->lock); | ||
325 | pdata->last_jiffies = jiffies; | ||
326 | platform_set_drvdata(pdev, pdata); | ||
331 | if (pdata->irq > 0) { | 327 | if (pdata->irq > 0) { |
332 | writeb(0, ioaddr + RTC_INTERRUPTS); | 328 | writeb(0, ioaddr + RTC_INTERRUPTS); |
333 | if (request_irq(pdata->irq, stk17ta8_rtc_interrupt, | 329 | if (devm_request_irq(&pdev->dev, pdata->irq, |
330 | stk17ta8_rtc_interrupt, | ||
334 | IRQF_DISABLED | IRQF_SHARED, | 331 | IRQF_DISABLED | IRQF_SHARED, |
335 | pdev->name, pdev) < 0) { | 332 | pdev->name, pdev) < 0) { |
336 | dev_warn(&pdev->dev, "interrupt not available.\n"); | 333 | dev_warn(&pdev->dev, "interrupt not available.\n"); |
@@ -338,29 +335,14 @@ static int __init stk17ta8_rtc_probe(struct platform_device *pdev) | |||
338 | } | 335 | } |
339 | } | 336 | } |
340 | 337 | ||
341 | rtc = rtc_device_register(pdev->name, &pdev->dev, | 338 | pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, |
342 | &stk17ta8_rtc_ops, THIS_MODULE); | 339 | &stk17ta8_rtc_ops, THIS_MODULE); |
343 | if (IS_ERR(rtc)) { | 340 | if (IS_ERR(pdata->rtc)) |
344 | ret = PTR_ERR(rtc); | 341 | return PTR_ERR(pdata->rtc); |
345 | goto out; | 342 | |
346 | } | ||
347 | pdata->rtc = rtc; | ||
348 | pdata->last_jiffies = jiffies; | ||
349 | platform_set_drvdata(pdev, pdata); | ||
350 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); | 343 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); |
351 | if (ret) | 344 | if (ret) |
352 | goto out; | ||
353 | return 0; | ||
354 | out: | ||
355 | if (pdata->rtc) | ||
356 | rtc_device_unregister(pdata->rtc); | 345 | rtc_device_unregister(pdata->rtc); |
357 | if (pdata->irq > 0) | ||
358 | free_irq(pdata->irq, pdev); | ||
359 | if (ioaddr) | ||
360 | iounmap(ioaddr); | ||
361 | if (pdata->baseaddr) | ||
362 | release_mem_region(pdata->baseaddr, RTC_REG_SIZE); | ||
363 | kfree(pdata); | ||
364 | return ret; | 346 | return ret; |
365 | } | 347 | } |
366 | 348 | ||
@@ -370,13 +352,8 @@ static int __devexit stk17ta8_rtc_remove(struct platform_device *pdev) | |||
370 | 352 | ||
371 | sysfs_remove_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); | 353 | sysfs_remove_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); |
372 | rtc_device_unregister(pdata->rtc); | 354 | rtc_device_unregister(pdata->rtc); |
373 | if (pdata->irq > 0) { | 355 | if (pdata->irq > 0) |
374 | writeb(0, pdata->ioaddr + RTC_INTERRUPTS); | 356 | writeb(0, pdata->ioaddr + RTC_INTERRUPTS); |
375 | free_irq(pdata->irq, pdev); | ||
376 | } | ||
377 | iounmap(pdata->ioaddr); | ||
378 | release_mem_region(pdata->baseaddr, RTC_REG_SIZE); | ||
379 | kfree(pdata); | ||
380 | return 0; | 357 | return 0; |
381 | } | 358 | } |
382 | 359 | ||
@@ -405,7 +382,7 @@ static __exit void stk17ta8_exit(void) | |||
405 | module_init(stk17ta8_init); | 382 | module_init(stk17ta8_init); |
406 | module_exit(stk17ta8_exit); | 383 | module_exit(stk17ta8_exit); |
407 | 384 | ||
408 | MODULE_AUTHOR("Thomas Hommel <thomas.hommel@gefanuc.com>"); | 385 | MODULE_AUTHOR("Thomas Hommel <thomas.hommel@ge.com>"); |
409 | MODULE_DESCRIPTION("Simtek STK17TA8 RTC driver"); | 386 | MODULE_DESCRIPTION("Simtek STK17TA8 RTC driver"); |
410 | MODULE_LICENSE("GPL"); | 387 | MODULE_LICENSE("GPL"); |
411 | MODULE_VERSION(DRV_VERSION); | 388 | MODULE_VERSION(DRV_VERSION); |
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c new file mode 100644 index 000000000000..7e7d0c806f2d --- /dev/null +++ b/drivers/rtc/rtc-stmp3xxx.c | |||
@@ -0,0 +1,305 @@ | |||
1 | /* | ||
2 | * Freescale STMP37XX/STMP378X Real Time Clock driver | ||
3 | * | ||
4 | * Copyright (c) 2007 Sigmatel, Inc. | ||
5 | * Peter Hartley, <peter.hartley@sigmatel.com> | ||
6 | * | ||
7 | * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. | ||
8 | * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * The code contained herein is licensed under the GNU General Public | ||
13 | * License. You may obtain a copy of the GNU General Public License | ||
14 | * Version 2 or later at the following locations: | ||
15 | * | ||
16 | * http://www.opensource.org/licenses/gpl-license.html | ||
17 | * http://www.gnu.org/copyleft/gpl.html | ||
18 | */ | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/rtc.h> | ||
25 | #include <linux/slab.h> | ||
26 | |||
27 | #include <mach/platform.h> | ||
28 | #include <mach/stmp3xxx.h> | ||
29 | #include <mach/regs-rtc.h> | ||
30 | |||
31 | struct stmp3xxx_rtc_data { | ||
32 | struct rtc_device *rtc; | ||
33 | unsigned irq_count; | ||
34 | void __iomem *io; | ||
35 | int irq_alarm, irq_1msec; | ||
36 | }; | ||
37 | |||
38 | static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data) | ||
39 | { | ||
40 | /* | ||
41 | * The datasheet doesn't say which way round the | ||
42 | * NEW_REGS/STALE_REGS bitfields go. In fact it's 0x1=P0, | ||
43 | * 0x2=P1, .., 0x20=P5, 0x40=ALARM, 0x80=SECONDS | ||
44 | */ | ||
45 | while (__raw_readl(rtc_data->io + HW_RTC_STAT) & | ||
46 | BF(0x80, RTC_STAT_STALE_REGS)) | ||
47 | cpu_relax(); | ||
48 | } | ||
49 | |||
50 | /* Time read/write */ | ||
51 | static int stmp3xxx_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | ||
52 | { | ||
53 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | ||
54 | |||
55 | stmp3xxx_wait_time(rtc_data); | ||
56 | rtc_time_to_tm(__raw_readl(rtc_data->io + HW_RTC_SECONDS), rtc_tm); | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t) | ||
61 | { | ||
62 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | ||
63 | |||
64 | __raw_writel(t, rtc_data->io + HW_RTC_SECONDS); | ||
65 | stmp3xxx_wait_time(rtc_data); | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | /* interrupt(s) handler */ | ||
70 | static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id) | ||
71 | { | ||
72 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev_id); | ||
73 | u32 status; | ||
74 | u32 events = 0; | ||
75 | |||
76 | status = __raw_readl(rtc_data->io + HW_RTC_CTRL) & | ||
77 | (BM_RTC_CTRL_ALARM_IRQ | BM_RTC_CTRL_ONEMSEC_IRQ); | ||
78 | |||
79 | if (status & BM_RTC_CTRL_ALARM_IRQ) { | ||
80 | stmp3xxx_clearl(BM_RTC_CTRL_ALARM_IRQ, | ||
81 | rtc_data->io + HW_RTC_CTRL); | ||
82 | events |= RTC_AF | RTC_IRQF; | ||
83 | } | ||
84 | |||
85 | if (status & BM_RTC_CTRL_ONEMSEC_IRQ) { | ||
86 | stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ, | ||
87 | rtc_data->io + HW_RTC_CTRL); | ||
88 | if (++rtc_data->irq_count % 1000 == 0) { | ||
89 | events |= RTC_UF | RTC_IRQF; | ||
90 | rtc_data->irq_count = 0; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | if (events) | ||
95 | rtc_update_irq(rtc_data->rtc, 1, events); | ||
96 | |||
97 | return IRQ_HANDLED; | ||
98 | } | ||
99 | |||
100 | static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
101 | { | ||
102 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | ||
103 | void __iomem *p = rtc_data->io + HW_RTC_PERSISTENT0, | ||
104 | *ctl = rtc_data->io + HW_RTC_CTRL; | ||
105 | |||
106 | if (enabled) { | ||
107 | stmp3xxx_setl(BM_RTC_PERSISTENT0_ALARM_EN | | ||
108 | BM_RTC_PERSISTENT0_ALARM_WAKE_EN, p); | ||
109 | stmp3xxx_setl(BM_RTC_CTRL_ALARM_IRQ_EN, ctl); | ||
110 | } else { | ||
111 | stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN | | ||
112 | BM_RTC_PERSISTENT0_ALARM_WAKE_EN, p); | ||
113 | stmp3xxx_clearl(BM_RTC_CTRL_ALARM_IRQ_EN, ctl); | ||
114 | } | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int stmp3xxx_update_irq_enable(struct device *dev, unsigned int enabled) | ||
119 | { | ||
120 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | ||
121 | |||
122 | if (enabled) | ||
123 | stmp3xxx_setl(BM_RTC_CTRL_ONEMSEC_IRQ_EN, | ||
124 | rtc_data->io + HW_RTC_CTRL); | ||
125 | else | ||
126 | stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN, | ||
127 | rtc_data->io + HW_RTC_CTRL); | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static int stmp3xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
132 | { | ||
133 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | ||
134 | |||
135 | rtc_time_to_tm(__raw_readl(rtc_data->io + HW_RTC_ALARM), &alm->time); | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
140 | { | ||
141 | unsigned long t; | ||
142 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | ||
143 | |||
144 | rtc_tm_to_time(&alm->time, &t); | ||
145 | __raw_writel(t, rtc_data->io + HW_RTC_ALARM); | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static struct rtc_class_ops stmp3xxx_rtc_ops = { | ||
150 | .alarm_irq_enable = | ||
151 | stmp3xxx_alarm_irq_enable, | ||
152 | .update_irq_enable = | ||
153 | stmp3xxx_update_irq_enable, | ||
154 | .read_time = stmp3xxx_rtc_gettime, | ||
155 | .set_mmss = stmp3xxx_rtc_set_mmss, | ||
156 | .read_alarm = stmp3xxx_rtc_read_alarm, | ||
157 | .set_alarm = stmp3xxx_rtc_set_alarm, | ||
158 | }; | ||
159 | |||
160 | static int stmp3xxx_rtc_remove(struct platform_device *pdev) | ||
161 | { | ||
162 | struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(pdev); | ||
163 | |||
164 | if (!rtc_data) | ||
165 | return 0; | ||
166 | |||
167 | stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN | BM_RTC_CTRL_ALARM_IRQ_EN, | ||
168 | rtc_data->io + HW_RTC_CTRL); | ||
169 | free_irq(rtc_data->irq_alarm, &pdev->dev); | ||
170 | free_irq(rtc_data->irq_1msec, &pdev->dev); | ||
171 | rtc_device_unregister(rtc_data->rtc); | ||
172 | iounmap(rtc_data->io); | ||
173 | kfree(rtc_data); | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static int stmp3xxx_rtc_probe(struct platform_device *pdev) | ||
179 | { | ||
180 | struct stmp3xxx_rtc_data *rtc_data; | ||
181 | struct resource *r; | ||
182 | int err; | ||
183 | |||
184 | rtc_data = kzalloc(sizeof *rtc_data, GFP_KERNEL); | ||
185 | if (!rtc_data) | ||
186 | return -ENOMEM; | ||
187 | |||
188 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
189 | if (!r) { | ||
190 | dev_err(&pdev->dev, "failed to get resource\n"); | ||
191 | err = -ENXIO; | ||
192 | goto out_free; | ||
193 | } | ||
194 | |||
195 | rtc_data->io = ioremap(r->start, resource_size(r)); | ||
196 | if (!rtc_data->io) { | ||
197 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
198 | err = -EIO; | ||
199 | goto out_free; | ||
200 | } | ||
201 | |||
202 | rtc_data->irq_alarm = platform_get_irq(pdev, 0); | ||
203 | rtc_data->irq_1msec = platform_get_irq(pdev, 1); | ||
204 | |||
205 | if (!(__raw_readl(HW_RTC_STAT + rtc_data->io) & | ||
206 | BM_RTC_STAT_RTC_PRESENT)) { | ||
207 | dev_err(&pdev->dev, "no device onboard\n"); | ||
208 | err = -ENODEV; | ||
209 | goto out_remap; | ||
210 | } | ||
211 | |||
212 | stmp3xxx_reset_block(rtc_data->io, true); | ||
213 | stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN | | ||
214 | BM_RTC_PERSISTENT0_ALARM_WAKE_EN | | ||
215 | BM_RTC_PERSISTENT0_ALARM_WAKE, | ||
216 | rtc_data->io + HW_RTC_PERSISTENT0); | ||
217 | rtc_data->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
218 | &stmp3xxx_rtc_ops, THIS_MODULE); | ||
219 | if (IS_ERR(rtc_data->rtc)) { | ||
220 | err = PTR_ERR(rtc_data->rtc); | ||
221 | goto out_remap; | ||
222 | } | ||
223 | |||
224 | rtc_data->irq_count = 0; | ||
225 | err = request_irq(rtc_data->irq_alarm, stmp3xxx_rtc_interrupt, | ||
226 | IRQF_DISABLED, "RTC alarm", &pdev->dev); | ||
227 | if (err) { | ||
228 | dev_err(&pdev->dev, "Cannot claim IRQ%d\n", | ||
229 | rtc_data->irq_alarm); | ||
230 | goto out_irq_alarm; | ||
231 | } | ||
232 | err = request_irq(rtc_data->irq_1msec, stmp3xxx_rtc_interrupt, | ||
233 | IRQF_DISABLED, "RTC tick", &pdev->dev); | ||
234 | if (err) { | ||
235 | dev_err(&pdev->dev, "Cannot claim IRQ%d\n", | ||
236 | rtc_data->irq_1msec); | ||
237 | goto out_irq1; | ||
238 | } | ||
239 | |||
240 | platform_set_drvdata(pdev, rtc_data); | ||
241 | |||
242 | return 0; | ||
243 | |||
244 | out_irq1: | ||
245 | free_irq(rtc_data->irq_alarm, &pdev->dev); | ||
246 | out_irq_alarm: | ||
247 | stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN | BM_RTC_CTRL_ALARM_IRQ_EN, | ||
248 | rtc_data->io + HW_RTC_CTRL); | ||
249 | rtc_device_unregister(rtc_data->rtc); | ||
250 | out_remap: | ||
251 | iounmap(rtc_data->io); | ||
252 | out_free: | ||
253 | kfree(rtc_data); | ||
254 | return err; | ||
255 | } | ||
256 | |||
257 | #ifdef CONFIG_PM | ||
258 | static int stmp3xxx_rtc_suspend(struct platform_device *dev, pm_message_t state) | ||
259 | { | ||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static int stmp3xxx_rtc_resume(struct platform_device *dev) | ||
264 | { | ||
265 | struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(dev); | ||
266 | |||
267 | stmp3xxx_reset_block(rtc_data->io, true); | ||
268 | stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN | | ||
269 | BM_RTC_PERSISTENT0_ALARM_WAKE_EN | | ||
270 | BM_RTC_PERSISTENT0_ALARM_WAKE, | ||
271 | rtc_data->io + HW_RTC_PERSISTENT0); | ||
272 | return 0; | ||
273 | } | ||
274 | #else | ||
275 | #define stmp3xxx_rtc_suspend NULL | ||
276 | #define stmp3xxx_rtc_resume NULL | ||
277 | #endif | ||
278 | |||
279 | static struct platform_driver stmp3xxx_rtcdrv = { | ||
280 | .probe = stmp3xxx_rtc_probe, | ||
281 | .remove = stmp3xxx_rtc_remove, | ||
282 | .suspend = stmp3xxx_rtc_suspend, | ||
283 | .resume = stmp3xxx_rtc_resume, | ||
284 | .driver = { | ||
285 | .name = "stmp3xxx-rtc", | ||
286 | .owner = THIS_MODULE, | ||
287 | }, | ||
288 | }; | ||
289 | |||
290 | static int __init stmp3xxx_rtc_init(void) | ||
291 | { | ||
292 | return platform_driver_register(&stmp3xxx_rtcdrv); | ||
293 | } | ||
294 | |||
295 | static void __exit stmp3xxx_rtc_exit(void) | ||
296 | { | ||
297 | platform_driver_unregister(&stmp3xxx_rtcdrv); | ||
298 | } | ||
299 | |||
300 | module_init(stmp3xxx_rtc_init); | ||
301 | module_exit(stmp3xxx_rtc_exit); | ||
302 | |||
303 | MODULE_DESCRIPTION("STMP3xxx RTC Driver"); | ||
304 | MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com>"); | ||
305 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index 2531ce4c9db0..380083ca572f 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c | |||
@@ -102,6 +102,20 @@ rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr, | |||
102 | return n; | 102 | return n; |
103 | } | 103 | } |
104 | 104 | ||
105 | static ssize_t | ||
106 | rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr, | ||
107 | char *buf) | ||
108 | { | ||
109 | #ifdef CONFIG_RTC_HCTOSYS_DEVICE | ||
110 | if (rtc_hctosys_ret == 0 && | ||
111 | strcmp(dev_name(&to_rtc_device(dev)->dev), | ||
112 | CONFIG_RTC_HCTOSYS_DEVICE) == 0) | ||
113 | return sprintf(buf, "1\n"); | ||
114 | else | ||
115 | #endif | ||
116 | return sprintf(buf, "0\n"); | ||
117 | } | ||
118 | |||
105 | static struct device_attribute rtc_attrs[] = { | 119 | static struct device_attribute rtc_attrs[] = { |
106 | __ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL), | 120 | __ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL), |
107 | __ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL), | 121 | __ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL), |
@@ -109,6 +123,7 @@ static struct device_attribute rtc_attrs[] = { | |||
109 | __ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL), | 123 | __ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL), |
110 | __ATTR(max_user_freq, S_IRUGO | S_IWUSR, rtc_sysfs_show_max_user_freq, | 124 | __ATTR(max_user_freq, S_IRUGO | S_IWUSR, rtc_sysfs_show_max_user_freq, |
111 | rtc_sysfs_set_max_user_freq), | 125 | rtc_sysfs_set_max_user_freq), |
126 | __ATTR(hctosys, S_IRUGO, rtc_sysfs_show_hctosys, NULL), | ||
112 | { }, | 127 | { }, |
113 | }; | 128 | }; |
114 | 129 | ||
diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl.c index 9c8c70c497dc..ed1b86828124 100644 --- a/drivers/rtc/rtc-twl4030.c +++ b/drivers/rtc/rtc-twl.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * rtc-twl4030.c -- TWL4030 Real Time Clock interface | 2 | * rtc-twl.c -- TWL Real Time Clock interface |
3 | * | 3 | * |
4 | * Copyright (C) 2007 MontaVista Software, Inc | 4 | * Copyright (C) 2007 MontaVista Software, Inc |
5 | * Author: Alexandre Rusev <source@mvista.com> | 5 | * Author: Alexandre Rusev <source@mvista.com> |
@@ -28,33 +28,81 @@ | |||
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | 30 | ||
31 | #include <linux/i2c/twl4030.h> | 31 | #include <linux/i2c/twl.h> |
32 | 32 | ||
33 | 33 | ||
34 | /* | 34 | /* |
35 | * RTC block register offsets (use TWL_MODULE_RTC) | 35 | * RTC block register offsets (use TWL_MODULE_RTC) |
36 | */ | 36 | */ |
37 | #define REG_SECONDS_REG 0x00 | 37 | enum { |
38 | #define REG_MINUTES_REG 0x01 | 38 | REG_SECONDS_REG = 0, |
39 | #define REG_HOURS_REG 0x02 | 39 | REG_MINUTES_REG, |
40 | #define REG_DAYS_REG 0x03 | 40 | REG_HOURS_REG, |
41 | #define REG_MONTHS_REG 0x04 | 41 | REG_DAYS_REG, |
42 | #define REG_YEARS_REG 0x05 | 42 | REG_MONTHS_REG, |
43 | #define REG_WEEKS_REG 0x06 | 43 | REG_YEARS_REG, |
44 | 44 | REG_WEEKS_REG, | |
45 | #define REG_ALARM_SECONDS_REG 0x07 | 45 | |
46 | #define REG_ALARM_MINUTES_REG 0x08 | 46 | REG_ALARM_SECONDS_REG, |
47 | #define REG_ALARM_HOURS_REG 0x09 | 47 | REG_ALARM_MINUTES_REG, |
48 | #define REG_ALARM_DAYS_REG 0x0A | 48 | REG_ALARM_HOURS_REG, |
49 | #define REG_ALARM_MONTHS_REG 0x0B | 49 | REG_ALARM_DAYS_REG, |
50 | #define REG_ALARM_YEARS_REG 0x0C | 50 | REG_ALARM_MONTHS_REG, |
51 | 51 | REG_ALARM_YEARS_REG, | |
52 | #define REG_RTC_CTRL_REG 0x0D | 52 | |
53 | #define REG_RTC_STATUS_REG 0x0E | 53 | REG_RTC_CTRL_REG, |
54 | #define REG_RTC_INTERRUPTS_REG 0x0F | 54 | REG_RTC_STATUS_REG, |
55 | 55 | REG_RTC_INTERRUPTS_REG, | |
56 | #define REG_RTC_COMP_LSB_REG 0x10 | 56 | |
57 | #define REG_RTC_COMP_MSB_REG 0x11 | 57 | REG_RTC_COMP_LSB_REG, |
58 | REG_RTC_COMP_MSB_REG, | ||
59 | }; | ||
60 | static const u8 twl4030_rtc_reg_map[] = { | ||
61 | [REG_SECONDS_REG] = 0x00, | ||
62 | [REG_MINUTES_REG] = 0x01, | ||
63 | [REG_HOURS_REG] = 0x02, | ||
64 | [REG_DAYS_REG] = 0x03, | ||
65 | [REG_MONTHS_REG] = 0x04, | ||
66 | [REG_YEARS_REG] = 0x05, | ||
67 | [REG_WEEKS_REG] = 0x06, | ||
68 | |||
69 | [REG_ALARM_SECONDS_REG] = 0x07, | ||
70 | [REG_ALARM_MINUTES_REG] = 0x08, | ||
71 | [REG_ALARM_HOURS_REG] = 0x09, | ||
72 | [REG_ALARM_DAYS_REG] = 0x0A, | ||
73 | [REG_ALARM_MONTHS_REG] = 0x0B, | ||
74 | [REG_ALARM_YEARS_REG] = 0x0C, | ||
75 | |||
76 | [REG_RTC_CTRL_REG] = 0x0D, | ||
77 | [REG_RTC_STATUS_REG] = 0x0E, | ||
78 | [REG_RTC_INTERRUPTS_REG] = 0x0F, | ||
79 | |||
80 | [REG_RTC_COMP_LSB_REG] = 0x10, | ||
81 | [REG_RTC_COMP_MSB_REG] = 0x11, | ||
82 | }; | ||
83 | static const u8 twl6030_rtc_reg_map[] = { | ||
84 | [REG_SECONDS_REG] = 0x00, | ||
85 | [REG_MINUTES_REG] = 0x01, | ||
86 | [REG_HOURS_REG] = 0x02, | ||
87 | [REG_DAYS_REG] = 0x03, | ||
88 | [REG_MONTHS_REG] = 0x04, | ||
89 | [REG_YEARS_REG] = 0x05, | ||
90 | [REG_WEEKS_REG] = 0x06, | ||
91 | |||
92 | [REG_ALARM_SECONDS_REG] = 0x08, | ||
93 | [REG_ALARM_MINUTES_REG] = 0x09, | ||
94 | [REG_ALARM_HOURS_REG] = 0x0A, | ||
95 | [REG_ALARM_DAYS_REG] = 0x0B, | ||
96 | [REG_ALARM_MONTHS_REG] = 0x0C, | ||
97 | [REG_ALARM_YEARS_REG] = 0x0D, | ||
98 | |||
99 | [REG_RTC_CTRL_REG] = 0x10, | ||
100 | [REG_RTC_STATUS_REG] = 0x11, | ||
101 | [REG_RTC_INTERRUPTS_REG] = 0x12, | ||
102 | |||
103 | [REG_RTC_COMP_LSB_REG] = 0x13, | ||
104 | [REG_RTC_COMP_MSB_REG] = 0x14, | ||
105 | }; | ||
58 | 106 | ||
59 | /* RTC_CTRL_REG bitfields */ | 107 | /* RTC_CTRL_REG bitfields */ |
60 | #define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01 | 108 | #define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01 |
@@ -84,31 +132,32 @@ | |||
84 | #define ALL_TIME_REGS 6 | 132 | #define ALL_TIME_REGS 6 |
85 | 133 | ||
86 | /*----------------------------------------------------------------------*/ | 134 | /*----------------------------------------------------------------------*/ |
135 | static u8 *rtc_reg_map; | ||
87 | 136 | ||
88 | /* | 137 | /* |
89 | * Supports 1 byte read from TWL4030 RTC register. | 138 | * Supports 1 byte read from TWL RTC register. |
90 | */ | 139 | */ |
91 | static int twl4030_rtc_read_u8(u8 *data, u8 reg) | 140 | static int twl_rtc_read_u8(u8 *data, u8 reg) |
92 | { | 141 | { |
93 | int ret; | 142 | int ret; |
94 | 143 | ||
95 | ret = twl4030_i2c_read_u8(TWL4030_MODULE_RTC, data, reg); | 144 | ret = twl_i2c_read_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg])); |
96 | if (ret < 0) | 145 | if (ret < 0) |
97 | pr_err("twl4030_rtc: Could not read TWL4030" | 146 | pr_err("twl_rtc: Could not read TWL" |
98 | "register %X - error %d\n", reg, ret); | 147 | "register %X - error %d\n", reg, ret); |
99 | return ret; | 148 | return ret; |
100 | } | 149 | } |
101 | 150 | ||
102 | /* | 151 | /* |
103 | * Supports 1 byte write to TWL4030 RTC registers. | 152 | * Supports 1 byte write to TWL RTC registers. |
104 | */ | 153 | */ |
105 | static int twl4030_rtc_write_u8(u8 data, u8 reg) | 154 | static int twl_rtc_write_u8(u8 data, u8 reg) |
106 | { | 155 | { |
107 | int ret; | 156 | int ret; |
108 | 157 | ||
109 | ret = twl4030_i2c_write_u8(TWL4030_MODULE_RTC, data, reg); | 158 | ret = twl_i2c_write_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg])); |
110 | if (ret < 0) | 159 | if (ret < 0) |
111 | pr_err("twl4030_rtc: Could not write TWL4030" | 160 | pr_err("twl_rtc: Could not write TWL" |
112 | "register %X - error %d\n", reg, ret); | 161 | "register %X - error %d\n", reg, ret); |
113 | return ret; | 162 | return ret; |
114 | } | 163 | } |
@@ -129,7 +178,7 @@ static int set_rtc_irq_bit(unsigned char bit) | |||
129 | 178 | ||
130 | val = rtc_irq_bits | bit; | 179 | val = rtc_irq_bits | bit; |
131 | val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M; | 180 | val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M; |
132 | ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); | 181 | ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); |
133 | if (ret == 0) | 182 | if (ret == 0) |
134 | rtc_irq_bits = val; | 183 | rtc_irq_bits = val; |
135 | 184 | ||
@@ -145,14 +194,14 @@ static int mask_rtc_irq_bit(unsigned char bit) | |||
145 | int ret; | 194 | int ret; |
146 | 195 | ||
147 | val = rtc_irq_bits & ~bit; | 196 | val = rtc_irq_bits & ~bit; |
148 | ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); | 197 | ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); |
149 | if (ret == 0) | 198 | if (ret == 0) |
150 | rtc_irq_bits = val; | 199 | rtc_irq_bits = val; |
151 | 200 | ||
152 | return ret; | 201 | return ret; |
153 | } | 202 | } |
154 | 203 | ||
155 | static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) | 204 | static int twl_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) |
156 | { | 205 | { |
157 | int ret; | 206 | int ret; |
158 | 207 | ||
@@ -164,7 +213,7 @@ static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) | |||
164 | return ret; | 213 | return ret; |
165 | } | 214 | } |
166 | 215 | ||
167 | static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) | 216 | static int twl_rtc_update_irq_enable(struct device *dev, unsigned enabled) |
168 | { | 217 | { |
169 | int ret; | 218 | int ret; |
170 | 219 | ||
@@ -177,7 +226,7 @@ static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) | |||
177 | } | 226 | } |
178 | 227 | ||
179 | /* | 228 | /* |
180 | * Gets current TWL4030 RTC time and date parameters. | 229 | * Gets current TWL RTC time and date parameters. |
181 | * | 230 | * |
182 | * The RTC's time/alarm representation is not what gmtime(3) requires | 231 | * The RTC's time/alarm representation is not what gmtime(3) requires |
183 | * Linux to use: | 232 | * Linux to use: |
@@ -185,24 +234,24 @@ static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) | |||
185 | * - Months are 1..12 vs Linux 0-11 | 234 | * - Months are 1..12 vs Linux 0-11 |
186 | * - Years are 0..99 vs Linux 1900..N (we assume 21st century) | 235 | * - Years are 0..99 vs Linux 1900..N (we assume 21st century) |
187 | */ | 236 | */ |
188 | static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm) | 237 | static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm) |
189 | { | 238 | { |
190 | unsigned char rtc_data[ALL_TIME_REGS + 1]; | 239 | unsigned char rtc_data[ALL_TIME_REGS + 1]; |
191 | int ret; | 240 | int ret; |
192 | u8 save_control; | 241 | u8 save_control; |
193 | 242 | ||
194 | ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); | 243 | ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); |
195 | if (ret < 0) | 244 | if (ret < 0) |
196 | return ret; | 245 | return ret; |
197 | 246 | ||
198 | save_control |= BIT_RTC_CTRL_REG_GET_TIME_M; | 247 | save_control |= BIT_RTC_CTRL_REG_GET_TIME_M; |
199 | 248 | ||
200 | ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); | 249 | ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); |
201 | if (ret < 0) | 250 | if (ret < 0) |
202 | return ret; | 251 | return ret; |
203 | 252 | ||
204 | ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, | 253 | ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, |
205 | REG_SECONDS_REG, ALL_TIME_REGS); | 254 | (rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS); |
206 | 255 | ||
207 | if (ret < 0) { | 256 | if (ret < 0) { |
208 | dev_err(dev, "rtc_read_time error %d\n", ret); | 257 | dev_err(dev, "rtc_read_time error %d\n", ret); |
@@ -219,7 +268,7 @@ static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
219 | return ret; | 268 | return ret; |
220 | } | 269 | } |
221 | 270 | ||
222 | static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) | 271 | static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm) |
223 | { | 272 | { |
224 | unsigned char save_control; | 273 | unsigned char save_control; |
225 | unsigned char rtc_data[ALL_TIME_REGS + 1]; | 274 | unsigned char rtc_data[ALL_TIME_REGS + 1]; |
@@ -233,18 +282,18 @@ static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
233 | rtc_data[6] = bin2bcd(tm->tm_year - 100); | 282 | rtc_data[6] = bin2bcd(tm->tm_year - 100); |
234 | 283 | ||
235 | /* Stop RTC while updating the TC registers */ | 284 | /* Stop RTC while updating the TC registers */ |
236 | ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); | 285 | ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); |
237 | if (ret < 0) | 286 | if (ret < 0) |
238 | goto out; | 287 | goto out; |
239 | 288 | ||
240 | save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; | 289 | save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; |
241 | twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); | 290 | twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); |
242 | if (ret < 0) | 291 | if (ret < 0) |
243 | goto out; | 292 | goto out; |
244 | 293 | ||
245 | /* update all the time registers in one shot */ | 294 | /* update all the time registers in one shot */ |
246 | ret = twl4030_i2c_write(TWL4030_MODULE_RTC, rtc_data, | 295 | ret = twl_i2c_write(TWL_MODULE_RTC, rtc_data, |
247 | REG_SECONDS_REG, ALL_TIME_REGS); | 296 | (rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS); |
248 | if (ret < 0) { | 297 | if (ret < 0) { |
249 | dev_err(dev, "rtc_set_time error %d\n", ret); | 298 | dev_err(dev, "rtc_set_time error %d\n", ret); |
250 | goto out; | 299 | goto out; |
@@ -252,22 +301,22 @@ static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
252 | 301 | ||
253 | /* Start back RTC */ | 302 | /* Start back RTC */ |
254 | save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M; | 303 | save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M; |
255 | ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); | 304 | ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); |
256 | 305 | ||
257 | out: | 306 | out: |
258 | return ret; | 307 | return ret; |
259 | } | 308 | } |
260 | 309 | ||
261 | /* | 310 | /* |
262 | * Gets current TWL4030 RTC alarm time. | 311 | * Gets current TWL RTC alarm time. |
263 | */ | 312 | */ |
264 | static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | 313 | static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) |
265 | { | 314 | { |
266 | unsigned char rtc_data[ALL_TIME_REGS + 1]; | 315 | unsigned char rtc_data[ALL_TIME_REGS + 1]; |
267 | int ret; | 316 | int ret; |
268 | 317 | ||
269 | ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, | 318 | ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, |
270 | REG_ALARM_SECONDS_REG, ALL_TIME_REGS); | 319 | (rtc_reg_map[REG_ALARM_SECONDS_REG]), ALL_TIME_REGS); |
271 | if (ret < 0) { | 320 | if (ret < 0) { |
272 | dev_err(dev, "rtc_read_alarm error %d\n", ret); | 321 | dev_err(dev, "rtc_read_alarm error %d\n", ret); |
273 | return ret; | 322 | return ret; |
@@ -288,12 +337,12 @@ static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
288 | return ret; | 337 | return ret; |
289 | } | 338 | } |
290 | 339 | ||
291 | static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | 340 | static int twl_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) |
292 | { | 341 | { |
293 | unsigned char alarm_data[ALL_TIME_REGS + 1]; | 342 | unsigned char alarm_data[ALL_TIME_REGS + 1]; |
294 | int ret; | 343 | int ret; |
295 | 344 | ||
296 | ret = twl4030_rtc_alarm_irq_enable(dev, 0); | 345 | ret = twl_rtc_alarm_irq_enable(dev, 0); |
297 | if (ret) | 346 | if (ret) |
298 | goto out; | 347 | goto out; |
299 | 348 | ||
@@ -305,20 +354,20 @@ static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
305 | alarm_data[6] = bin2bcd(alm->time.tm_year - 100); | 354 | alarm_data[6] = bin2bcd(alm->time.tm_year - 100); |
306 | 355 | ||
307 | /* update all the alarm registers in one shot */ | 356 | /* update all the alarm registers in one shot */ |
308 | ret = twl4030_i2c_write(TWL4030_MODULE_RTC, alarm_data, | 357 | ret = twl_i2c_write(TWL_MODULE_RTC, alarm_data, |
309 | REG_ALARM_SECONDS_REG, ALL_TIME_REGS); | 358 | (rtc_reg_map[REG_ALARM_SECONDS_REG]), ALL_TIME_REGS); |
310 | if (ret) { | 359 | if (ret) { |
311 | dev_err(dev, "rtc_set_alarm error %d\n", ret); | 360 | dev_err(dev, "rtc_set_alarm error %d\n", ret); |
312 | goto out; | 361 | goto out; |
313 | } | 362 | } |
314 | 363 | ||
315 | if (alm->enabled) | 364 | if (alm->enabled) |
316 | ret = twl4030_rtc_alarm_irq_enable(dev, 1); | 365 | ret = twl_rtc_alarm_irq_enable(dev, 1); |
317 | out: | 366 | out: |
318 | return ret; | 367 | return ret; |
319 | } | 368 | } |
320 | 369 | ||
321 | static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) | 370 | static irqreturn_t twl_rtc_interrupt(int irq, void *rtc) |
322 | { | 371 | { |
323 | unsigned long events = 0; | 372 | unsigned long events = 0; |
324 | int ret = IRQ_NONE; | 373 | int ret = IRQ_NONE; |
@@ -333,7 +382,7 @@ static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) | |||
333 | local_irq_enable(); | 382 | local_irq_enable(); |
334 | #endif | 383 | #endif |
335 | 384 | ||
336 | res = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); | 385 | res = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); |
337 | if (res) | 386 | if (res) |
338 | goto out; | 387 | goto out; |
339 | /* | 388 | /* |
@@ -347,26 +396,28 @@ static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) | |||
347 | else | 396 | else |
348 | events |= RTC_IRQF | RTC_UF; | 397 | events |= RTC_IRQF | RTC_UF; |
349 | 398 | ||
350 | res = twl4030_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M, | 399 | res = twl_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M, |
351 | REG_RTC_STATUS_REG); | 400 | REG_RTC_STATUS_REG); |
352 | if (res) | 401 | if (res) |
353 | goto out; | 402 | goto out; |
354 | 403 | ||
355 | /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 | 404 | if (twl_class_is_4030()) { |
356 | * needs 2 reads to clear the interrupt. One read is done in | 405 | /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 |
357 | * do_twl4030_pwrirq(). Doing the second read, to clear | 406 | * needs 2 reads to clear the interrupt. One read is done in |
358 | * the bit. | 407 | * do_twl_pwrirq(). Doing the second read, to clear |
359 | * | 408 | * the bit. |
360 | * FIXME the reason PWR_ISR1 needs an extra read is that | 409 | * |
361 | * RTC_IF retriggered until we cleared REG_ALARM_M above. | 410 | * FIXME the reason PWR_ISR1 needs an extra read is that |
362 | * But re-reading like this is a bad hack; by doing so we | 411 | * RTC_IF retriggered until we cleared REG_ALARM_M above. |
363 | * risk wrongly clearing status for some other IRQ (losing | 412 | * But re-reading like this is a bad hack; by doing so we |
364 | * the interrupt). Be smarter about handling RTC_UF ... | 413 | * risk wrongly clearing status for some other IRQ (losing |
365 | */ | 414 | * the interrupt). Be smarter about handling RTC_UF ... |
366 | res = twl4030_i2c_read_u8(TWL4030_MODULE_INT, | 415 | */ |
416 | res = twl_i2c_read_u8(TWL4030_MODULE_INT, | ||
367 | &rd_reg, TWL4030_INT_PWR_ISR1); | 417 | &rd_reg, TWL4030_INT_PWR_ISR1); |
368 | if (res) | 418 | if (res) |
369 | goto out; | 419 | goto out; |
420 | } | ||
370 | 421 | ||
371 | /* Notify RTC core on event */ | 422 | /* Notify RTC core on event */ |
372 | rtc_update_irq(rtc, 1, events); | 423 | rtc_update_irq(rtc, 1, events); |
@@ -376,18 +427,18 @@ out: | |||
376 | return ret; | 427 | return ret; |
377 | } | 428 | } |
378 | 429 | ||
379 | static struct rtc_class_ops twl4030_rtc_ops = { | 430 | static struct rtc_class_ops twl_rtc_ops = { |
380 | .read_time = twl4030_rtc_read_time, | 431 | .read_time = twl_rtc_read_time, |
381 | .set_time = twl4030_rtc_set_time, | 432 | .set_time = twl_rtc_set_time, |
382 | .read_alarm = twl4030_rtc_read_alarm, | 433 | .read_alarm = twl_rtc_read_alarm, |
383 | .set_alarm = twl4030_rtc_set_alarm, | 434 | .set_alarm = twl_rtc_set_alarm, |
384 | .alarm_irq_enable = twl4030_rtc_alarm_irq_enable, | 435 | .alarm_irq_enable = twl_rtc_alarm_irq_enable, |
385 | .update_irq_enable = twl4030_rtc_update_irq_enable, | 436 | .update_irq_enable = twl_rtc_update_irq_enable, |
386 | }; | 437 | }; |
387 | 438 | ||
388 | /*----------------------------------------------------------------------*/ | 439 | /*----------------------------------------------------------------------*/ |
389 | 440 | ||
390 | static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | 441 | static int __devinit twl_rtc_probe(struct platform_device *pdev) |
391 | { | 442 | { |
392 | struct rtc_device *rtc; | 443 | struct rtc_device *rtc; |
393 | int ret = 0; | 444 | int ret = 0; |
@@ -398,7 +449,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | |||
398 | return -EINVAL; | 449 | return -EINVAL; |
399 | 450 | ||
400 | rtc = rtc_device_register(pdev->name, | 451 | rtc = rtc_device_register(pdev->name, |
401 | &pdev->dev, &twl4030_rtc_ops, THIS_MODULE); | 452 | &pdev->dev, &twl_rtc_ops, THIS_MODULE); |
402 | if (IS_ERR(rtc)) { | 453 | if (IS_ERR(rtc)) { |
403 | ret = PTR_ERR(rtc); | 454 | ret = PTR_ERR(rtc); |
404 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", | 455 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", |
@@ -409,7 +460,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | |||
409 | 460 | ||
410 | platform_set_drvdata(pdev, rtc); | 461 | platform_set_drvdata(pdev, rtc); |
411 | 462 | ||
412 | ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); | 463 | ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); |
413 | if (ret < 0) | 464 | if (ret < 0) |
414 | goto out1; | 465 | goto out1; |
415 | 466 | ||
@@ -420,11 +471,11 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | |||
420 | dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); | 471 | dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); |
421 | 472 | ||
422 | /* Clear RTC Power up reset and pending alarm interrupts */ | 473 | /* Clear RTC Power up reset and pending alarm interrupts */ |
423 | ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); | 474 | ret = twl_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); |
424 | if (ret < 0) | 475 | if (ret < 0) |
425 | goto out1; | 476 | goto out1; |
426 | 477 | ||
427 | ret = request_irq(irq, twl4030_rtc_interrupt, | 478 | ret = request_irq(irq, twl_rtc_interrupt, |
428 | IRQF_TRIGGER_RISING, | 479 | IRQF_TRIGGER_RISING, |
429 | dev_name(&rtc->dev), rtc); | 480 | dev_name(&rtc->dev), rtc); |
430 | if (ret < 0) { | 481 | if (ret < 0) { |
@@ -432,21 +483,28 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) | |||
432 | goto out1; | 483 | goto out1; |
433 | } | 484 | } |
434 | 485 | ||
486 | if (twl_class_is_6030()) { | ||
487 | twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, | ||
488 | REG_INT_MSK_LINE_A); | ||
489 | twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, | ||
490 | REG_INT_MSK_STS_A); | ||
491 | } | ||
492 | |||
435 | /* Check RTC module status, Enable if it is off */ | 493 | /* Check RTC module status, Enable if it is off */ |
436 | ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); | 494 | ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); |
437 | if (ret < 0) | 495 | if (ret < 0) |
438 | goto out2; | 496 | goto out2; |
439 | 497 | ||
440 | if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { | 498 | if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { |
441 | dev_info(&pdev->dev, "Enabling TWL4030-RTC.\n"); | 499 | dev_info(&pdev->dev, "Enabling TWL-RTC.\n"); |
442 | rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; | 500 | rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; |
443 | ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); | 501 | ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); |
444 | if (ret < 0) | 502 | if (ret < 0) |
445 | goto out2; | 503 | goto out2; |
446 | } | 504 | } |
447 | 505 | ||
448 | /* init cached IRQ enable bits */ | 506 | /* init cached IRQ enable bits */ |
449 | ret = twl4030_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); | 507 | ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); |
450 | if (ret < 0) | 508 | if (ret < 0) |
451 | goto out2; | 509 | goto out2; |
452 | 510 | ||
@@ -461,10 +519,10 @@ out0: | |||
461 | } | 519 | } |
462 | 520 | ||
463 | /* | 521 | /* |
464 | * Disable all TWL4030 RTC module interrupts. | 522 | * Disable all TWL RTC module interrupts. |
465 | * Sets status flag to free. | 523 | * Sets status flag to free. |
466 | */ | 524 | */ |
467 | static int __devexit twl4030_rtc_remove(struct platform_device *pdev) | 525 | static int __devexit twl_rtc_remove(struct platform_device *pdev) |
468 | { | 526 | { |
469 | /* leave rtc running, but disable irqs */ | 527 | /* leave rtc running, but disable irqs */ |
470 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 528 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
@@ -472,6 +530,13 @@ static int __devexit twl4030_rtc_remove(struct platform_device *pdev) | |||
472 | 530 | ||
473 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); | 531 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); |
474 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); | 532 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); |
533 | if (twl_class_is_6030()) { | ||
534 | twl6030_interrupt_mask(TWL6030_RTC_INT_MASK, | ||
535 | REG_INT_MSK_LINE_A); | ||
536 | twl6030_interrupt_mask(TWL6030_RTC_INT_MASK, | ||
537 | REG_INT_MSK_STS_A); | ||
538 | } | ||
539 | |||
475 | 540 | ||
476 | free_irq(irq, rtc); | 541 | free_irq(irq, rtc); |
477 | 542 | ||
@@ -480,7 +545,7 @@ static int __devexit twl4030_rtc_remove(struct platform_device *pdev) | |||
480 | return 0; | 545 | return 0; |
481 | } | 546 | } |
482 | 547 | ||
483 | static void twl4030_rtc_shutdown(struct platform_device *pdev) | 548 | static void twl_rtc_shutdown(struct platform_device *pdev) |
484 | { | 549 | { |
485 | /* mask timer interrupts, but leave alarm interrupts on to enable | 550 | /* mask timer interrupts, but leave alarm interrupts on to enable |
486 | power-on when alarm is triggered */ | 551 | power-on when alarm is triggered */ |
@@ -491,7 +556,7 @@ static void twl4030_rtc_shutdown(struct platform_device *pdev) | |||
491 | 556 | ||
492 | static unsigned char irqstat; | 557 | static unsigned char irqstat; |
493 | 558 | ||
494 | static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 559 | static int twl_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
495 | { | 560 | { |
496 | irqstat = rtc_irq_bits; | 561 | irqstat = rtc_irq_bits; |
497 | 562 | ||
@@ -499,42 +564,47 @@ static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
499 | return 0; | 564 | return 0; |
500 | } | 565 | } |
501 | 566 | ||
502 | static int twl4030_rtc_resume(struct platform_device *pdev) | 567 | static int twl_rtc_resume(struct platform_device *pdev) |
503 | { | 568 | { |
504 | set_rtc_irq_bit(irqstat); | 569 | set_rtc_irq_bit(irqstat); |
505 | return 0; | 570 | return 0; |
506 | } | 571 | } |
507 | 572 | ||
508 | #else | 573 | #else |
509 | #define twl4030_rtc_suspend NULL | 574 | #define twl_rtc_suspend NULL |
510 | #define twl4030_rtc_resume NULL | 575 | #define twl_rtc_resume NULL |
511 | #endif | 576 | #endif |
512 | 577 | ||
513 | MODULE_ALIAS("platform:twl4030_rtc"); | 578 | MODULE_ALIAS("platform:twl_rtc"); |
514 | 579 | ||
515 | static struct platform_driver twl4030rtc_driver = { | 580 | static struct platform_driver twl4030rtc_driver = { |
516 | .probe = twl4030_rtc_probe, | 581 | .probe = twl_rtc_probe, |
517 | .remove = __devexit_p(twl4030_rtc_remove), | 582 | .remove = __devexit_p(twl_rtc_remove), |
518 | .shutdown = twl4030_rtc_shutdown, | 583 | .shutdown = twl_rtc_shutdown, |
519 | .suspend = twl4030_rtc_suspend, | 584 | .suspend = twl_rtc_suspend, |
520 | .resume = twl4030_rtc_resume, | 585 | .resume = twl_rtc_resume, |
521 | .driver = { | 586 | .driver = { |
522 | .owner = THIS_MODULE, | 587 | .owner = THIS_MODULE, |
523 | .name = "twl4030_rtc", | 588 | .name = "twl_rtc", |
524 | }, | 589 | }, |
525 | }; | 590 | }; |
526 | 591 | ||
527 | static int __init twl4030_rtc_init(void) | 592 | static int __init twl_rtc_init(void) |
528 | { | 593 | { |
594 | if (twl_class_is_4030()) | ||
595 | rtc_reg_map = (u8 *) twl4030_rtc_reg_map; | ||
596 | else | ||
597 | rtc_reg_map = (u8 *) twl6030_rtc_reg_map; | ||
598 | |||
529 | return platform_driver_register(&twl4030rtc_driver); | 599 | return platform_driver_register(&twl4030rtc_driver); |
530 | } | 600 | } |
531 | module_init(twl4030_rtc_init); | 601 | module_init(twl_rtc_init); |
532 | 602 | ||
533 | static void __exit twl4030_rtc_exit(void) | 603 | static void __exit twl_rtc_exit(void) |
534 | { | 604 | { |
535 | platform_driver_unregister(&twl4030rtc_driver); | 605 | platform_driver_unregister(&twl4030rtc_driver); |
536 | } | 606 | } |
537 | module_exit(twl4030_rtc_exit); | 607 | module_exit(twl_rtc_exit); |
538 | 608 | ||
539 | MODULE_AUTHOR("Texas Instruments, MontaVista Software"); | 609 | MODULE_AUTHOR("Texas Instruments, MontaVista Software"); |
540 | MODULE_LICENSE("GPL"); | 610 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index 4a6ed1104fbb..ec6313d15359 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c | |||
@@ -12,11 +12,13 @@ | |||
12 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | #include <linux/gfp.h> | ||
15 | #include <asm/txx9/tx4939.h> | 16 | #include <asm/txx9/tx4939.h> |
16 | 17 | ||
17 | struct tx4939rtc_plat_data { | 18 | struct tx4939rtc_plat_data { |
18 | struct rtc_device *rtc; | 19 | struct rtc_device *rtc; |
19 | struct tx4939_rtc_reg __iomem *rtcreg; | 20 | struct tx4939_rtc_reg __iomem *rtcreg; |
21 | spinlock_t lock; | ||
20 | }; | 22 | }; |
21 | 23 | ||
22 | static struct tx4939rtc_plat_data *get_tx4939rtc_plat_data(struct device *dev) | 24 | static struct tx4939rtc_plat_data *get_tx4939rtc_plat_data(struct device *dev) |
@@ -52,14 +54,14 @@ static int tx4939_rtc_set_mmss(struct device *dev, unsigned long secs) | |||
52 | buf[3] = secs >> 8; | 54 | buf[3] = secs >> 8; |
53 | buf[4] = secs >> 16; | 55 | buf[4] = secs >> 16; |
54 | buf[5] = secs >> 24; | 56 | buf[5] = secs >> 24; |
55 | spin_lock_irq(&pdata->rtc->irq_lock); | 57 | spin_lock_irq(&pdata->lock); |
56 | __raw_writel(0, &rtcreg->adr); | 58 | __raw_writel(0, &rtcreg->adr); |
57 | for (i = 0; i < 6; i++) | 59 | for (i = 0; i < 6; i++) |
58 | __raw_writel(buf[i], &rtcreg->dat); | 60 | __raw_writel(buf[i], &rtcreg->dat); |
59 | ret = tx4939_rtc_cmd(rtcreg, | 61 | ret = tx4939_rtc_cmd(rtcreg, |
60 | TX4939_RTCCTL_COMMAND_SETTIME | | 62 | TX4939_RTCCTL_COMMAND_SETTIME | |
61 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); | 63 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); |
62 | spin_unlock_irq(&pdata->rtc->irq_lock); | 64 | spin_unlock_irq(&pdata->lock); |
63 | return ret; | 65 | return ret; |
64 | } | 66 | } |
65 | 67 | ||
@@ -71,18 +73,18 @@ static int tx4939_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
71 | unsigned long sec; | 73 | unsigned long sec; |
72 | unsigned char buf[6]; | 74 | unsigned char buf[6]; |
73 | 75 | ||
74 | spin_lock_irq(&pdata->rtc->irq_lock); | 76 | spin_lock_irq(&pdata->lock); |
75 | ret = tx4939_rtc_cmd(rtcreg, | 77 | ret = tx4939_rtc_cmd(rtcreg, |
76 | TX4939_RTCCTL_COMMAND_GETTIME | | 78 | TX4939_RTCCTL_COMMAND_GETTIME | |
77 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); | 79 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); |
78 | if (ret) { | 80 | if (ret) { |
79 | spin_unlock_irq(&pdata->rtc->irq_lock); | 81 | spin_unlock_irq(&pdata->lock); |
80 | return ret; | 82 | return ret; |
81 | } | 83 | } |
82 | __raw_writel(2, &rtcreg->adr); | 84 | __raw_writel(2, &rtcreg->adr); |
83 | for (i = 2; i < 6; i++) | 85 | for (i = 2; i < 6; i++) |
84 | buf[i] = __raw_readl(&rtcreg->dat); | 86 | buf[i] = __raw_readl(&rtcreg->dat); |
85 | spin_unlock_irq(&pdata->rtc->irq_lock); | 87 | spin_unlock_irq(&pdata->lock); |
86 | sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; | 88 | sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; |
87 | rtc_time_to_tm(sec, tm); | 89 | rtc_time_to_tm(sec, tm); |
88 | return rtc_valid_tm(tm); | 90 | return rtc_valid_tm(tm); |
@@ -110,13 +112,13 @@ static int tx4939_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
110 | buf[3] = sec >> 8; | 112 | buf[3] = sec >> 8; |
111 | buf[4] = sec >> 16; | 113 | buf[4] = sec >> 16; |
112 | buf[5] = sec >> 24; | 114 | buf[5] = sec >> 24; |
113 | spin_lock_irq(&pdata->rtc->irq_lock); | 115 | spin_lock_irq(&pdata->lock); |
114 | __raw_writel(0, &rtcreg->adr); | 116 | __raw_writel(0, &rtcreg->adr); |
115 | for (i = 0; i < 6; i++) | 117 | for (i = 0; i < 6; i++) |
116 | __raw_writel(buf[i], &rtcreg->dat); | 118 | __raw_writel(buf[i], &rtcreg->dat); |
117 | ret = tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_SETALARM | | 119 | ret = tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_SETALARM | |
118 | (alrm->enabled ? TX4939_RTCCTL_ALME : 0)); | 120 | (alrm->enabled ? TX4939_RTCCTL_ALME : 0)); |
119 | spin_unlock_irq(&pdata->rtc->irq_lock); | 121 | spin_unlock_irq(&pdata->lock); |
120 | return ret; | 122 | return ret; |
121 | } | 123 | } |
122 | 124 | ||
@@ -129,12 +131,12 @@ static int tx4939_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
129 | unsigned char buf[6]; | 131 | unsigned char buf[6]; |
130 | u32 ctl; | 132 | u32 ctl; |
131 | 133 | ||
132 | spin_lock_irq(&pdata->rtc->irq_lock); | 134 | spin_lock_irq(&pdata->lock); |
133 | ret = tx4939_rtc_cmd(rtcreg, | 135 | ret = tx4939_rtc_cmd(rtcreg, |
134 | TX4939_RTCCTL_COMMAND_GETALARM | | 136 | TX4939_RTCCTL_COMMAND_GETALARM | |
135 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); | 137 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); |
136 | if (ret) { | 138 | if (ret) { |
137 | spin_unlock_irq(&pdata->rtc->irq_lock); | 139 | spin_unlock_irq(&pdata->lock); |
138 | return ret; | 140 | return ret; |
139 | } | 141 | } |
140 | __raw_writel(2, &rtcreg->adr); | 142 | __raw_writel(2, &rtcreg->adr); |
@@ -143,7 +145,7 @@ static int tx4939_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
143 | ctl = __raw_readl(&rtcreg->ctl); | 145 | ctl = __raw_readl(&rtcreg->ctl); |
144 | alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0; | 146 | alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0; |
145 | alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0; | 147 | alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0; |
146 | spin_unlock_irq(&pdata->rtc->irq_lock); | 148 | spin_unlock_irq(&pdata->lock); |
147 | sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; | 149 | sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; |
148 | rtc_time_to_tm(sec, &alrm->time); | 150 | rtc_time_to_tm(sec, &alrm->time); |
149 | return rtc_valid_tm(&alrm->time); | 151 | return rtc_valid_tm(&alrm->time); |
@@ -153,11 +155,11 @@ static int tx4939_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
153 | { | 155 | { |
154 | struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev); | 156 | struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev); |
155 | 157 | ||
156 | spin_lock_irq(&pdata->rtc->irq_lock); | 158 | spin_lock_irq(&pdata->lock); |
157 | tx4939_rtc_cmd(pdata->rtcreg, | 159 | tx4939_rtc_cmd(pdata->rtcreg, |
158 | TX4939_RTCCTL_COMMAND_NOP | | 160 | TX4939_RTCCTL_COMMAND_NOP | |
159 | (enabled ? TX4939_RTCCTL_ALME : 0)); | 161 | (enabled ? TX4939_RTCCTL_ALME : 0)); |
160 | spin_unlock_irq(&pdata->rtc->irq_lock); | 162 | spin_unlock_irq(&pdata->lock); |
161 | return 0; | 163 | return 0; |
162 | } | 164 | } |
163 | 165 | ||
@@ -167,13 +169,14 @@ static irqreturn_t tx4939_rtc_interrupt(int irq, void *dev_id) | |||
167 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; | 169 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; |
168 | unsigned long events = RTC_IRQF; | 170 | unsigned long events = RTC_IRQF; |
169 | 171 | ||
170 | spin_lock(&pdata->rtc->irq_lock); | 172 | spin_lock(&pdata->lock); |
171 | if (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALMD) { | 173 | if (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALMD) { |
172 | events |= RTC_AF; | 174 | events |= RTC_AF; |
173 | tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_NOP); | 175 | tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_NOP); |
174 | } | 176 | } |
175 | spin_unlock(&pdata->rtc->irq_lock); | 177 | spin_unlock(&pdata->lock); |
176 | rtc_update_irq(pdata->rtc, 1, events); | 178 | if (likely(pdata->rtc)) |
179 | rtc_update_irq(pdata->rtc, 1, events); | ||
177 | return IRQ_HANDLED; | 180 | return IRQ_HANDLED; |
178 | } | 181 | } |
179 | 182 | ||
@@ -185,7 +188,7 @@ static const struct rtc_class_ops tx4939_rtc_ops = { | |||
185 | .alarm_irq_enable = tx4939_rtc_alarm_irq_enable, | 188 | .alarm_irq_enable = tx4939_rtc_alarm_irq_enable, |
186 | }; | 189 | }; |
187 | 190 | ||
188 | static ssize_t tx4939_rtc_nvram_read(struct kobject *kobj, | 191 | static ssize_t tx4939_rtc_nvram_read(struct file *filp, struct kobject *kobj, |
189 | struct bin_attribute *bin_attr, | 192 | struct bin_attribute *bin_attr, |
190 | char *buf, loff_t pos, size_t size) | 193 | char *buf, loff_t pos, size_t size) |
191 | { | 194 | { |
@@ -194,17 +197,17 @@ static ssize_t tx4939_rtc_nvram_read(struct kobject *kobj, | |||
194 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; | 197 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; |
195 | ssize_t count; | 198 | ssize_t count; |
196 | 199 | ||
197 | spin_lock_irq(&pdata->rtc->irq_lock); | 200 | spin_lock_irq(&pdata->lock); |
198 | for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; | 201 | for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; |
199 | count++, size--) { | 202 | count++, size--) { |
200 | __raw_writel(pos++, &rtcreg->adr); | 203 | __raw_writel(pos++, &rtcreg->adr); |
201 | *buf++ = __raw_readl(&rtcreg->dat); | 204 | *buf++ = __raw_readl(&rtcreg->dat); |
202 | } | 205 | } |
203 | spin_unlock_irq(&pdata->rtc->irq_lock); | 206 | spin_unlock_irq(&pdata->lock); |
204 | return count; | 207 | return count; |
205 | } | 208 | } |
206 | 209 | ||
207 | static ssize_t tx4939_rtc_nvram_write(struct kobject *kobj, | 210 | static ssize_t tx4939_rtc_nvram_write(struct file *filp, struct kobject *kobj, |
208 | struct bin_attribute *bin_attr, | 211 | struct bin_attribute *bin_attr, |
209 | char *buf, loff_t pos, size_t size) | 212 | char *buf, loff_t pos, size_t size) |
210 | { | 213 | { |
@@ -213,13 +216,13 @@ static ssize_t tx4939_rtc_nvram_write(struct kobject *kobj, | |||
213 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; | 216 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; |
214 | ssize_t count; | 217 | ssize_t count; |
215 | 218 | ||
216 | spin_lock_irq(&pdata->rtc->irq_lock); | 219 | spin_lock_irq(&pdata->lock); |
217 | for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; | 220 | for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; |
218 | count++, size--) { | 221 | count++, size--) { |
219 | __raw_writel(pos++, &rtcreg->adr); | 222 | __raw_writel(pos++, &rtcreg->adr); |
220 | __raw_writel(*buf++, &rtcreg->dat); | 223 | __raw_writel(*buf++, &rtcreg->dat); |
221 | } | 224 | } |
222 | spin_unlock_irq(&pdata->rtc->irq_lock); | 225 | spin_unlock_irq(&pdata->lock); |
223 | return count; | 226 | return count; |
224 | } | 227 | } |
225 | 228 | ||
@@ -259,6 +262,7 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev) | |||
259 | if (!pdata->rtcreg) | 262 | if (!pdata->rtcreg) |
260 | return -EBUSY; | 263 | return -EBUSY; |
261 | 264 | ||
265 | spin_lock_init(&pdata->lock); | ||
262 | tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); | 266 | tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); |
263 | if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt, | 267 | if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt, |
264 | IRQF_DISABLED, pdev->name, &pdev->dev) < 0) | 268 | IRQF_DISABLED, pdev->name, &pdev->dev) < 0) |
@@ -277,14 +281,12 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev) | |||
277 | static int __exit tx4939_rtc_remove(struct platform_device *pdev) | 281 | static int __exit tx4939_rtc_remove(struct platform_device *pdev) |
278 | { | 282 | { |
279 | struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev); | 283 | struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev); |
280 | struct rtc_device *rtc = pdata->rtc; | ||
281 | 284 | ||
282 | spin_lock_irq(&rtc->irq_lock); | ||
283 | tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); | ||
284 | spin_unlock_irq(&rtc->irq_lock); | ||
285 | sysfs_remove_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr); | 285 | sysfs_remove_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr); |
286 | rtc_device_unregister(rtc); | 286 | rtc_device_unregister(pdata->rtc); |
287 | platform_set_drvdata(pdev, NULL); | 287 | spin_lock_irq(&pdata->lock); |
288 | tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); | ||
289 | spin_unlock_irq(&pdata->lock); | ||
288 | return 0; | 290 | return 0; |
289 | } | 291 | } |
290 | 292 | ||
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c index ad164056feb6..f71c3ce18036 100644 --- a/drivers/rtc/rtc-v3020.c +++ b/drivers/rtc/rtc-v3020.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/rtc-v3020.h> | 28 | #include <linux/rtc-v3020.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/gpio.h> | 30 | #include <linux/gpio.h> |
31 | #include <linux/slab.h> | ||
31 | 32 | ||
32 | #include <linux/io.h> | 33 | #include <linux/io.h> |
33 | 34 | ||
@@ -96,7 +97,7 @@ static void v3020_mmio_write_bit(struct v3020 *chip, unsigned char bit) | |||
96 | 97 | ||
97 | static unsigned char v3020_mmio_read_bit(struct v3020 *chip) | 98 | static unsigned char v3020_mmio_read_bit(struct v3020 *chip) |
98 | { | 99 | { |
99 | return readl(chip->ioaddress) & (1 << chip->leftshift); | 100 | return !!(readl(chip->ioaddress) & (1 << chip->leftshift)); |
100 | } | 101 | } |
101 | 102 | ||
102 | static struct v3020_chip_ops v3020_mmio_ops = { | 103 | static struct v3020_chip_ops v3020_mmio_ops = { |
@@ -304,7 +305,6 @@ static int rtc_probe(struct platform_device *pdev) | |||
304 | { | 305 | { |
305 | struct v3020_platform_data *pdata = pdev->dev.platform_data; | 306 | struct v3020_platform_data *pdata = pdev->dev.platform_data; |
306 | struct v3020 *chip; | 307 | struct v3020 *chip; |
307 | struct rtc_device *rtc; | ||
308 | int retval = -EBUSY; | 308 | int retval = -EBUSY; |
309 | int i; | 309 | int i; |
310 | int temp; | 310 | int temp; |
@@ -335,7 +335,7 @@ static int rtc_probe(struct platform_device *pdev) | |||
335 | goto err_io; | 335 | goto err_io; |
336 | } | 336 | } |
337 | 337 | ||
338 | /* Make sure frequency measurment mode, test modes, and lock | 338 | /* Make sure frequency measurement mode, test modes, and lock |
339 | * are all disabled */ | 339 | * are all disabled */ |
340 | v3020_set_reg(chip, V3020_STATUS_0, 0x0); | 340 | v3020_set_reg(chip, V3020_STATUS_0, 0x0); |
341 | 341 | ||
@@ -353,13 +353,12 @@ static int rtc_probe(struct platform_device *pdev) | |||
353 | 353 | ||
354 | platform_set_drvdata(pdev, chip); | 354 | platform_set_drvdata(pdev, chip); |
355 | 355 | ||
356 | rtc = rtc_device_register("v3020", | 356 | chip->rtc = rtc_device_register("v3020", |
357 | &pdev->dev, &v3020_rtc_ops, THIS_MODULE); | 357 | &pdev->dev, &v3020_rtc_ops, THIS_MODULE); |
358 | if (IS_ERR(rtc)) { | 358 | if (IS_ERR(chip->rtc)) { |
359 | retval = PTR_ERR(rtc); | 359 | retval = PTR_ERR(chip->rtc); |
360 | goto err_io; | 360 | goto err_io; |
361 | } | 361 | } |
362 | chip->rtc = rtc; | ||
363 | 362 | ||
364 | return 0; | 363 | return 0; |
365 | 364 | ||
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index f11297aff854..c3244244e8cf 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-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2003-2008 Yoichi Yuasa <yuasa@linux-mips.org> |
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 |
@@ -33,7 +33,7 @@ | |||
33 | #include <asm/io.h> | 33 | #include <asm/io.h> |
34 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
35 | 35 | ||
36 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 36 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
37 | MODULE_DESCRIPTION("NEC VR4100 series RTC driver"); | 37 | MODULE_DESCRIPTION("NEC VR4100 series RTC driver"); |
38 | MODULE_LICENSE("GPL v2"); | 38 | MODULE_LICENSE("GPL v2"); |
39 | 39 | ||
@@ -209,19 +209,18 @@ static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | |||
209 | 209 | ||
210 | static int vr41xx_rtc_irq_set_freq(struct device *dev, int freq) | 210 | static int vr41xx_rtc_irq_set_freq(struct device *dev, int freq) |
211 | { | 211 | { |
212 | unsigned long count; | 212 | u64 count; |
213 | 213 | ||
214 | if (!is_power_of_2(freq)) | 214 | if (!is_power_of_2(freq)) |
215 | return -EINVAL; | 215 | return -EINVAL; |
216 | count = RTC_FREQUENCY; | 216 | count = RTC_FREQUENCY; |
217 | do_div(count, freq); | 217 | do_div(count, freq); |
218 | 218 | ||
219 | periodic_count = count; | ||
220 | |||
221 | spin_lock_irq(&rtc_lock); | 219 | spin_lock_irq(&rtc_lock); |
222 | 220 | ||
223 | rtc1_write(RTCL1LREG, count); | 221 | periodic_count = count; |
224 | rtc1_write(RTCL1HREG, count >> 16); | 222 | rtc1_write(RTCL1LREG, periodic_count); |
223 | rtc1_write(RTCL1HREG, periodic_count >> 16); | ||
225 | 224 | ||
226 | spin_unlock_irq(&rtc_lock); | 225 | spin_unlock_irq(&rtc_lock); |
227 | 226 | ||
@@ -328,7 +327,7 @@ static int __devinit rtc_probe(struct platform_device *pdev) | |||
328 | if (!res) | 327 | if (!res) |
329 | return -EBUSY; | 328 | return -EBUSY; |
330 | 329 | ||
331 | rtc1_base = ioremap(res->start, res->end - res->start + 1); | 330 | rtc1_base = ioremap(res->start, resource_size(res)); |
332 | if (!rtc1_base) | 331 | if (!rtc1_base) |
333 | return -EBUSY; | 332 | return -EBUSY; |
334 | 333 | ||
@@ -338,7 +337,7 @@ static int __devinit rtc_probe(struct platform_device *pdev) | |||
338 | goto err_rtc1_iounmap; | 337 | goto err_rtc1_iounmap; |
339 | } | 338 | } |
340 | 339 | ||
341 | rtc2_base = ioremap(res->start, res->end - res->start + 1); | 340 | rtc2_base = ioremap(res->start, resource_size(res)); |
342 | if (!rtc2_base) { | 341 | if (!rtc2_base) { |
343 | retval = -EBUSY; | 342 | retval = -EBUSY; |
344 | goto err_rtc1_iounmap; | 343 | goto err_rtc1_iounmap; |
diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c new file mode 100644 index 000000000000..82931dc65c0b --- /dev/null +++ b/drivers/rtc/rtc-wm831x.c | |||
@@ -0,0 +1,524 @@ | |||
1 | /* | ||
2 | * Real Time Clock driver for Wolfson Microelectronics WM831x | ||
3 | * | ||
4 | * Copyright (C) 2009 Wolfson Microelectronics PLC. | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/time.h> | ||
18 | #include <linux/rtc.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/bcd.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/ioctl.h> | ||
23 | #include <linux/completion.h> | ||
24 | #include <linux/mfd/wm831x/core.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | |||
28 | |||
29 | /* | ||
30 | * R16416 (0x4020) - RTC Write Counter | ||
31 | */ | ||
32 | #define WM831X_RTC_WR_CNT_MASK 0xFFFF /* RTC_WR_CNT - [15:0] */ | ||
33 | #define WM831X_RTC_WR_CNT_SHIFT 0 /* RTC_WR_CNT - [15:0] */ | ||
34 | #define WM831X_RTC_WR_CNT_WIDTH 16 /* RTC_WR_CNT - [15:0] */ | ||
35 | |||
36 | /* | ||
37 | * R16417 (0x4021) - RTC Time 1 | ||
38 | */ | ||
39 | #define WM831X_RTC_TIME_MASK 0xFFFF /* RTC_TIME - [15:0] */ | ||
40 | #define WM831X_RTC_TIME_SHIFT 0 /* RTC_TIME - [15:0] */ | ||
41 | #define WM831X_RTC_TIME_WIDTH 16 /* RTC_TIME - [15:0] */ | ||
42 | |||
43 | /* | ||
44 | * R16418 (0x4022) - RTC Time 2 | ||
45 | */ | ||
46 | #define WM831X_RTC_TIME_MASK 0xFFFF /* RTC_TIME - [15:0] */ | ||
47 | #define WM831X_RTC_TIME_SHIFT 0 /* RTC_TIME - [15:0] */ | ||
48 | #define WM831X_RTC_TIME_WIDTH 16 /* RTC_TIME - [15:0] */ | ||
49 | |||
50 | /* | ||
51 | * R16419 (0x4023) - RTC Alarm 1 | ||
52 | */ | ||
53 | #define WM831X_RTC_ALM_MASK 0xFFFF /* RTC_ALM - [15:0] */ | ||
54 | #define WM831X_RTC_ALM_SHIFT 0 /* RTC_ALM - [15:0] */ | ||
55 | #define WM831X_RTC_ALM_WIDTH 16 /* RTC_ALM - [15:0] */ | ||
56 | |||
57 | /* | ||
58 | * R16420 (0x4024) - RTC Alarm 2 | ||
59 | */ | ||
60 | #define WM831X_RTC_ALM_MASK 0xFFFF /* RTC_ALM - [15:0] */ | ||
61 | #define WM831X_RTC_ALM_SHIFT 0 /* RTC_ALM - [15:0] */ | ||
62 | #define WM831X_RTC_ALM_WIDTH 16 /* RTC_ALM - [15:0] */ | ||
63 | |||
64 | /* | ||
65 | * R16421 (0x4025) - RTC Control | ||
66 | */ | ||
67 | #define WM831X_RTC_VALID 0x8000 /* RTC_VALID */ | ||
68 | #define WM831X_RTC_VALID_MASK 0x8000 /* RTC_VALID */ | ||
69 | #define WM831X_RTC_VALID_SHIFT 15 /* RTC_VALID */ | ||
70 | #define WM831X_RTC_VALID_WIDTH 1 /* RTC_VALID */ | ||
71 | #define WM831X_RTC_SYNC_BUSY 0x4000 /* RTC_SYNC_BUSY */ | ||
72 | #define WM831X_RTC_SYNC_BUSY_MASK 0x4000 /* RTC_SYNC_BUSY */ | ||
73 | #define WM831X_RTC_SYNC_BUSY_SHIFT 14 /* RTC_SYNC_BUSY */ | ||
74 | #define WM831X_RTC_SYNC_BUSY_WIDTH 1 /* RTC_SYNC_BUSY */ | ||
75 | #define WM831X_RTC_ALM_ENA 0x0400 /* RTC_ALM_ENA */ | ||
76 | #define WM831X_RTC_ALM_ENA_MASK 0x0400 /* RTC_ALM_ENA */ | ||
77 | #define WM831X_RTC_ALM_ENA_SHIFT 10 /* RTC_ALM_ENA */ | ||
78 | #define WM831X_RTC_ALM_ENA_WIDTH 1 /* RTC_ALM_ENA */ | ||
79 | #define WM831X_RTC_PINT_FREQ_MASK 0x0070 /* RTC_PINT_FREQ - [6:4] */ | ||
80 | #define WM831X_RTC_PINT_FREQ_SHIFT 4 /* RTC_PINT_FREQ - [6:4] */ | ||
81 | #define WM831X_RTC_PINT_FREQ_WIDTH 3 /* RTC_PINT_FREQ - [6:4] */ | ||
82 | |||
83 | /* | ||
84 | * R16422 (0x4026) - RTC Trim | ||
85 | */ | ||
86 | #define WM831X_RTC_TRIM_MASK 0x03FF /* RTC_TRIM - [9:0] */ | ||
87 | #define WM831X_RTC_TRIM_SHIFT 0 /* RTC_TRIM - [9:0] */ | ||
88 | #define WM831X_RTC_TRIM_WIDTH 10 /* RTC_TRIM - [9:0] */ | ||
89 | |||
90 | #define WM831X_SET_TIME_RETRIES 5 | ||
91 | #define WM831X_GET_TIME_RETRIES 5 | ||
92 | |||
93 | struct wm831x_rtc { | ||
94 | struct wm831x *wm831x; | ||
95 | struct rtc_device *rtc; | ||
96 | unsigned int alarm_enabled:1; | ||
97 | }; | ||
98 | |||
99 | /* | ||
100 | * Read current time and date in RTC | ||
101 | */ | ||
102 | static int wm831x_rtc_readtime(struct device *dev, struct rtc_time *tm) | ||
103 | { | ||
104 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(dev); | ||
105 | struct wm831x *wm831x = wm831x_rtc->wm831x; | ||
106 | u16 time1[2], time2[2]; | ||
107 | int ret; | ||
108 | int count = 0; | ||
109 | |||
110 | /* Has the RTC been programmed? */ | ||
111 | ret = wm831x_reg_read(wm831x, WM831X_RTC_CONTROL); | ||
112 | if (ret < 0) { | ||
113 | dev_err(dev, "Failed to read RTC control: %d\n", ret); | ||
114 | return ret; | ||
115 | } | ||
116 | if (!(ret & WM831X_RTC_VALID)) { | ||
117 | dev_dbg(dev, "RTC not yet configured\n"); | ||
118 | return -EINVAL; | ||
119 | } | ||
120 | |||
121 | /* Read twice to make sure we don't read a corrupt, partially | ||
122 | * incremented, value. | ||
123 | */ | ||
124 | do { | ||
125 | ret = wm831x_bulk_read(wm831x, WM831X_RTC_TIME_1, | ||
126 | 2, time1); | ||
127 | if (ret != 0) | ||
128 | continue; | ||
129 | |||
130 | ret = wm831x_bulk_read(wm831x, WM831X_RTC_TIME_1, | ||
131 | 2, time2); | ||
132 | if (ret != 0) | ||
133 | continue; | ||
134 | |||
135 | if (memcmp(time1, time2, sizeof(time1)) == 0) { | ||
136 | u32 time = (time1[0] << 16) | time1[1]; | ||
137 | |||
138 | rtc_time_to_tm(time, tm); | ||
139 | return rtc_valid_tm(tm); | ||
140 | } | ||
141 | |||
142 | } while (++count < WM831X_GET_TIME_RETRIES); | ||
143 | |||
144 | dev_err(dev, "Timed out reading current time\n"); | ||
145 | |||
146 | return -EIO; | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * Set current time and date in RTC | ||
151 | */ | ||
152 | static int wm831x_rtc_set_mmss(struct device *dev, unsigned long time) | ||
153 | { | ||
154 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(dev); | ||
155 | struct wm831x *wm831x = wm831x_rtc->wm831x; | ||
156 | struct rtc_time new_tm; | ||
157 | unsigned long new_time; | ||
158 | int ret; | ||
159 | int count = 0; | ||
160 | |||
161 | ret = wm831x_reg_write(wm831x, WM831X_RTC_TIME_1, | ||
162 | (time >> 16) & 0xffff); | ||
163 | if (ret < 0) { | ||
164 | dev_err(dev, "Failed to write TIME_1: %d\n", ret); | ||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | ret = wm831x_reg_write(wm831x, WM831X_RTC_TIME_2, time & 0xffff); | ||
169 | if (ret < 0) { | ||
170 | dev_err(dev, "Failed to write TIME_2: %d\n", ret); | ||
171 | return ret; | ||
172 | } | ||
173 | |||
174 | /* Wait for the update to complete - should happen first time | ||
175 | * round but be conservative. | ||
176 | */ | ||
177 | do { | ||
178 | msleep(1); | ||
179 | |||
180 | ret = wm831x_reg_read(wm831x, WM831X_RTC_CONTROL); | ||
181 | if (ret < 0) | ||
182 | ret = WM831X_RTC_SYNC_BUSY; | ||
183 | } while (!(ret & WM831X_RTC_SYNC_BUSY) && | ||
184 | ++count < WM831X_SET_TIME_RETRIES); | ||
185 | |||
186 | if (ret & WM831X_RTC_SYNC_BUSY) { | ||
187 | dev_err(dev, "Timed out writing RTC update\n"); | ||
188 | return -EIO; | ||
189 | } | ||
190 | |||
191 | /* Check that the update was accepted; security features may | ||
192 | * have caused the update to be ignored. | ||
193 | */ | ||
194 | ret = wm831x_rtc_readtime(dev, &new_tm); | ||
195 | if (ret < 0) | ||
196 | return ret; | ||
197 | |||
198 | ret = rtc_tm_to_time(&new_tm, &new_time); | ||
199 | if (ret < 0) { | ||
200 | dev_err(dev, "Failed to convert time: %d\n", ret); | ||
201 | return ret; | ||
202 | } | ||
203 | |||
204 | /* Allow a second of change in case of tick */ | ||
205 | if (new_time - time > 1) { | ||
206 | dev_err(dev, "RTC update not permitted by hardware\n"); | ||
207 | return -EPERM; | ||
208 | } | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | /* | ||
214 | * Read alarm time and date in RTC | ||
215 | */ | ||
216 | static int wm831x_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
217 | { | ||
218 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(dev); | ||
219 | int ret; | ||
220 | u16 data[2]; | ||
221 | u32 time; | ||
222 | |||
223 | ret = wm831x_bulk_read(wm831x_rtc->wm831x, WM831X_RTC_ALARM_1, | ||
224 | 2, data); | ||
225 | if (ret != 0) { | ||
226 | dev_err(dev, "Failed to read alarm time: %d\n", ret); | ||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | time = (data[0] << 16) | data[1]; | ||
231 | |||
232 | rtc_time_to_tm(time, &alrm->time); | ||
233 | |||
234 | ret = wm831x_reg_read(wm831x_rtc->wm831x, WM831X_RTC_CONTROL); | ||
235 | if (ret < 0) { | ||
236 | dev_err(dev, "Failed to read RTC control: %d\n", ret); | ||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | if (ret & WM831X_RTC_ALM_ENA) | ||
241 | alrm->enabled = 1; | ||
242 | else | ||
243 | alrm->enabled = 0; | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static int wm831x_rtc_stop_alarm(struct wm831x_rtc *wm831x_rtc) | ||
249 | { | ||
250 | wm831x_rtc->alarm_enabled = 0; | ||
251 | |||
252 | return wm831x_set_bits(wm831x_rtc->wm831x, WM831X_RTC_CONTROL, | ||
253 | WM831X_RTC_ALM_ENA, 0); | ||
254 | } | ||
255 | |||
256 | static int wm831x_rtc_start_alarm(struct wm831x_rtc *wm831x_rtc) | ||
257 | { | ||
258 | wm831x_rtc->alarm_enabled = 1; | ||
259 | |||
260 | return wm831x_set_bits(wm831x_rtc->wm831x, WM831X_RTC_CONTROL, | ||
261 | WM831X_RTC_ALM_ENA, WM831X_RTC_ALM_ENA); | ||
262 | } | ||
263 | |||
264 | static int wm831x_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
265 | { | ||
266 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(dev); | ||
267 | struct wm831x *wm831x = wm831x_rtc->wm831x; | ||
268 | int ret; | ||
269 | unsigned long time; | ||
270 | |||
271 | ret = rtc_tm_to_time(&alrm->time, &time); | ||
272 | if (ret < 0) { | ||
273 | dev_err(dev, "Failed to convert time: %d\n", ret); | ||
274 | return ret; | ||
275 | } | ||
276 | |||
277 | ret = wm831x_rtc_stop_alarm(wm831x_rtc); | ||
278 | if (ret < 0) { | ||
279 | dev_err(dev, "Failed to stop alarm: %d\n", ret); | ||
280 | return ret; | ||
281 | } | ||
282 | |||
283 | ret = wm831x_reg_write(wm831x, WM831X_RTC_ALARM_1, | ||
284 | (time >> 16) & 0xffff); | ||
285 | if (ret < 0) { | ||
286 | dev_err(dev, "Failed to write ALARM_1: %d\n", ret); | ||
287 | return ret; | ||
288 | } | ||
289 | |||
290 | ret = wm831x_reg_write(wm831x, WM831X_RTC_ALARM_2, time & 0xffff); | ||
291 | if (ret < 0) { | ||
292 | dev_err(dev, "Failed to write ALARM_2: %d\n", ret); | ||
293 | return ret; | ||
294 | } | ||
295 | |||
296 | if (alrm->enabled) { | ||
297 | ret = wm831x_rtc_start_alarm(wm831x_rtc); | ||
298 | if (ret < 0) { | ||
299 | dev_err(dev, "Failed to start alarm: %d\n", ret); | ||
300 | return ret; | ||
301 | } | ||
302 | } | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static int wm831x_rtc_alarm_irq_enable(struct device *dev, | ||
308 | unsigned int enabled) | ||
309 | { | ||
310 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(dev); | ||
311 | |||
312 | if (enabled) | ||
313 | return wm831x_rtc_start_alarm(wm831x_rtc); | ||
314 | else | ||
315 | return wm831x_rtc_stop_alarm(wm831x_rtc); | ||
316 | } | ||
317 | |||
318 | static int wm831x_rtc_update_irq_enable(struct device *dev, | ||
319 | unsigned int enabled) | ||
320 | { | ||
321 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(dev); | ||
322 | int val; | ||
323 | |||
324 | if (enabled) | ||
325 | val = 1 << WM831X_RTC_PINT_FREQ_SHIFT; | ||
326 | else | ||
327 | val = 0; | ||
328 | |||
329 | return wm831x_set_bits(wm831x_rtc->wm831x, WM831X_RTC_CONTROL, | ||
330 | WM831X_RTC_PINT_FREQ_MASK, val); | ||
331 | } | ||
332 | |||
333 | static irqreturn_t wm831x_alm_irq(int irq, void *data) | ||
334 | { | ||
335 | struct wm831x_rtc *wm831x_rtc = data; | ||
336 | |||
337 | rtc_update_irq(wm831x_rtc->rtc, 1, RTC_IRQF | RTC_AF); | ||
338 | |||
339 | return IRQ_HANDLED; | ||
340 | } | ||
341 | |||
342 | static irqreturn_t wm831x_per_irq(int irq, void *data) | ||
343 | { | ||
344 | struct wm831x_rtc *wm831x_rtc = data; | ||
345 | |||
346 | rtc_update_irq(wm831x_rtc->rtc, 1, RTC_IRQF | RTC_UF); | ||
347 | |||
348 | return IRQ_HANDLED; | ||
349 | } | ||
350 | |||
351 | static const struct rtc_class_ops wm831x_rtc_ops = { | ||
352 | .read_time = wm831x_rtc_readtime, | ||
353 | .set_mmss = wm831x_rtc_set_mmss, | ||
354 | .read_alarm = wm831x_rtc_readalarm, | ||
355 | .set_alarm = wm831x_rtc_setalarm, | ||
356 | .alarm_irq_enable = wm831x_rtc_alarm_irq_enable, | ||
357 | .update_irq_enable = wm831x_rtc_update_irq_enable, | ||
358 | }; | ||
359 | |||
360 | #ifdef CONFIG_PM | ||
361 | /* Turn off the alarm if it should not be a wake source. */ | ||
362 | static int wm831x_rtc_suspend(struct device *dev) | ||
363 | { | ||
364 | struct platform_device *pdev = to_platform_device(dev); | ||
365 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(&pdev->dev); | ||
366 | int ret, enable; | ||
367 | |||
368 | if (wm831x_rtc->alarm_enabled && device_may_wakeup(&pdev->dev)) | ||
369 | enable = WM831X_RTC_ALM_ENA; | ||
370 | else | ||
371 | enable = 0; | ||
372 | |||
373 | ret = wm831x_set_bits(wm831x_rtc->wm831x, WM831X_RTC_CONTROL, | ||
374 | WM831X_RTC_ALM_ENA, enable); | ||
375 | if (ret != 0) | ||
376 | dev_err(&pdev->dev, "Failed to update RTC alarm: %d\n", ret); | ||
377 | |||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | /* Enable the alarm if it should be enabled (in case it was disabled to | ||
382 | * prevent use as a wake source). | ||
383 | */ | ||
384 | static int wm831x_rtc_resume(struct device *dev) | ||
385 | { | ||
386 | struct platform_device *pdev = to_platform_device(dev); | ||
387 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(&pdev->dev); | ||
388 | int ret; | ||
389 | |||
390 | if (wm831x_rtc->alarm_enabled) { | ||
391 | ret = wm831x_rtc_start_alarm(wm831x_rtc); | ||
392 | if (ret != 0) | ||
393 | dev_err(&pdev->dev, | ||
394 | "Failed to restart RTC alarm: %d\n", ret); | ||
395 | } | ||
396 | |||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | /* Unconditionally disable the alarm */ | ||
401 | static int wm831x_rtc_freeze(struct device *dev) | ||
402 | { | ||
403 | struct platform_device *pdev = to_platform_device(dev); | ||
404 | struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(&pdev->dev); | ||
405 | int ret; | ||
406 | |||
407 | ret = wm831x_set_bits(wm831x_rtc->wm831x, WM831X_RTC_CONTROL, | ||
408 | WM831X_RTC_ALM_ENA, 0); | ||
409 | if (ret != 0) | ||
410 | dev_err(&pdev->dev, "Failed to stop RTC alarm: %d\n", ret); | ||
411 | |||
412 | return 0; | ||
413 | } | ||
414 | #else | ||
415 | #define wm831x_rtc_suspend NULL | ||
416 | #define wm831x_rtc_resume NULL | ||
417 | #define wm831x_rtc_freeze NULL | ||
418 | #endif | ||
419 | |||
420 | static int wm831x_rtc_probe(struct platform_device *pdev) | ||
421 | { | ||
422 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); | ||
423 | struct wm831x_rtc *wm831x_rtc; | ||
424 | int per_irq = platform_get_irq_byname(pdev, "PER"); | ||
425 | int alm_irq = platform_get_irq_byname(pdev, "ALM"); | ||
426 | int ret = 0; | ||
427 | |||
428 | wm831x_rtc = kzalloc(sizeof(*wm831x_rtc), GFP_KERNEL); | ||
429 | if (wm831x_rtc == NULL) | ||
430 | return -ENOMEM; | ||
431 | |||
432 | platform_set_drvdata(pdev, wm831x_rtc); | ||
433 | wm831x_rtc->wm831x = wm831x; | ||
434 | |||
435 | ret = wm831x_reg_read(wm831x, WM831X_RTC_CONTROL); | ||
436 | if (ret < 0) { | ||
437 | dev_err(&pdev->dev, "Failed to read RTC control: %d\n", ret); | ||
438 | goto err; | ||
439 | } | ||
440 | if (ret & WM831X_RTC_ALM_ENA) | ||
441 | wm831x_rtc->alarm_enabled = 1; | ||
442 | |||
443 | device_init_wakeup(&pdev->dev, 1); | ||
444 | |||
445 | wm831x_rtc->rtc = rtc_device_register("wm831x", &pdev->dev, | ||
446 | &wm831x_rtc_ops, THIS_MODULE); | ||
447 | if (IS_ERR(wm831x_rtc->rtc)) { | ||
448 | ret = PTR_ERR(wm831x_rtc->rtc); | ||
449 | goto err; | ||
450 | } | ||
451 | |||
452 | ret = request_threaded_irq(per_irq, NULL, wm831x_per_irq, | ||
453 | IRQF_TRIGGER_RISING, "RTC period", | ||
454 | wm831x_rtc); | ||
455 | if (ret != 0) { | ||
456 | dev_err(&pdev->dev, "Failed to request periodic IRQ %d: %d\n", | ||
457 | per_irq, ret); | ||
458 | } | ||
459 | |||
460 | ret = request_threaded_irq(alm_irq, NULL, wm831x_alm_irq, | ||
461 | IRQF_TRIGGER_RISING, "RTC alarm", | ||
462 | wm831x_rtc); | ||
463 | if (ret != 0) { | ||
464 | dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", | ||
465 | alm_irq, ret); | ||
466 | } | ||
467 | |||
468 | return 0; | ||
469 | |||
470 | err: | ||
471 | kfree(wm831x_rtc); | ||
472 | return ret; | ||
473 | } | ||
474 | |||
475 | static int __devexit wm831x_rtc_remove(struct platform_device *pdev) | ||
476 | { | ||
477 | struct wm831x_rtc *wm831x_rtc = platform_get_drvdata(pdev); | ||
478 | int per_irq = platform_get_irq_byname(pdev, "PER"); | ||
479 | int alm_irq = platform_get_irq_byname(pdev, "ALM"); | ||
480 | |||
481 | free_irq(alm_irq, wm831x_rtc); | ||
482 | free_irq(per_irq, wm831x_rtc); | ||
483 | rtc_device_unregister(wm831x_rtc->rtc); | ||
484 | kfree(wm831x_rtc); | ||
485 | |||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | static const struct dev_pm_ops wm831x_rtc_pm_ops = { | ||
490 | .suspend = wm831x_rtc_suspend, | ||
491 | .resume = wm831x_rtc_resume, | ||
492 | |||
493 | .freeze = wm831x_rtc_freeze, | ||
494 | .thaw = wm831x_rtc_resume, | ||
495 | .restore = wm831x_rtc_resume, | ||
496 | |||
497 | .poweroff = wm831x_rtc_suspend, | ||
498 | }; | ||
499 | |||
500 | static struct platform_driver wm831x_rtc_driver = { | ||
501 | .probe = wm831x_rtc_probe, | ||
502 | .remove = __devexit_p(wm831x_rtc_remove), | ||
503 | .driver = { | ||
504 | .name = "wm831x-rtc", | ||
505 | .pm = &wm831x_rtc_pm_ops, | ||
506 | }, | ||
507 | }; | ||
508 | |||
509 | static int __init wm831x_rtc_init(void) | ||
510 | { | ||
511 | return platform_driver_register(&wm831x_rtc_driver); | ||
512 | } | ||
513 | module_init(wm831x_rtc_init); | ||
514 | |||
515 | static void __exit wm831x_rtc_exit(void) | ||
516 | { | ||
517 | platform_driver_unregister(&wm831x_rtc_driver); | ||
518 | } | ||
519 | module_exit(wm831x_rtc_exit); | ||
520 | |||
521 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
522 | MODULE_DESCRIPTION("RTC driver for the WM831x series PMICs"); | ||
523 | MODULE_LICENSE("GPL"); | ||
524 | MODULE_ALIAS("platform:wm831x-rtc"); | ||
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c index c91edc572eb6..3d0dc76b38af 100644 --- a/drivers/rtc/rtc-wm8350.c +++ b/drivers/rtc/rtc-wm8350.c | |||
@@ -307,17 +307,24 @@ static int wm8350_rtc_update_irq_enable(struct device *dev, | |||
307 | { | 307 | { |
308 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | 308 | struct wm8350 *wm8350 = dev_get_drvdata(dev); |
309 | 309 | ||
310 | /* Suppress duplicate changes since genirq nests enable and | ||
311 | * disable calls. */ | ||
312 | if (enabled == wm8350->rtc.update_enabled) | ||
313 | return 0; | ||
314 | |||
310 | if (enabled) | 315 | if (enabled) |
311 | wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC); | 316 | wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC); |
312 | else | 317 | else |
313 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | 318 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); |
314 | 319 | ||
320 | wm8350->rtc.update_enabled = enabled; | ||
321 | |||
315 | return 0; | 322 | return 0; |
316 | } | 323 | } |
317 | 324 | ||
318 | static void wm8350_rtc_alarm_handler(struct wm8350 *wm8350, int irq, | 325 | static irqreturn_t wm8350_rtc_alarm_handler(int irq, void *data) |
319 | void *data) | ||
320 | { | 326 | { |
327 | struct wm8350 *wm8350 = data; | ||
321 | struct rtc_device *rtc = wm8350->rtc.rtc; | 328 | struct rtc_device *rtc = wm8350->rtc.rtc; |
322 | int ret; | 329 | int ret; |
323 | 330 | ||
@@ -330,14 +337,18 @@ static void wm8350_rtc_alarm_handler(struct wm8350 *wm8350, int irq, | |||
330 | dev_err(&(wm8350->rtc.pdev->dev), | 337 | dev_err(&(wm8350->rtc.pdev->dev), |
331 | "Failed to disable alarm: %d\n", ret); | 338 | "Failed to disable alarm: %d\n", ret); |
332 | } | 339 | } |
340 | |||
341 | return IRQ_HANDLED; | ||
333 | } | 342 | } |
334 | 343 | ||
335 | static void wm8350_rtc_update_handler(struct wm8350 *wm8350, int irq, | 344 | static irqreturn_t wm8350_rtc_update_handler(int irq, void *data) |
336 | void *data) | ||
337 | { | 345 | { |
346 | struct wm8350 *wm8350 = data; | ||
338 | struct rtc_device *rtc = wm8350->rtc.rtc; | 347 | struct rtc_device *rtc = wm8350->rtc.rtc; |
339 | 348 | ||
340 | rtc_update_irq(rtc, 1, RTC_IRQF | RTC_UF); | 349 | rtc_update_irq(rtc, 1, RTC_IRQF | RTC_UF); |
350 | |||
351 | return IRQ_HANDLED; | ||
341 | } | 352 | } |
342 | 353 | ||
343 | static const struct rtc_class_ops wm8350_rtc_ops = { | 354 | static const struct rtc_class_ops wm8350_rtc_ops = { |
@@ -350,8 +361,9 @@ static const struct rtc_class_ops wm8350_rtc_ops = { | |||
350 | }; | 361 | }; |
351 | 362 | ||
352 | #ifdef CONFIG_PM | 363 | #ifdef CONFIG_PM |
353 | static int wm8350_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 364 | static int wm8350_rtc_suspend(struct device *dev) |
354 | { | 365 | { |
366 | struct platform_device *pdev = to_platform_device(dev); | ||
355 | struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); | 367 | struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); |
356 | int ret = 0; | 368 | int ret = 0; |
357 | u16 reg; | 369 | u16 reg; |
@@ -369,8 +381,9 @@ static int wm8350_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
369 | return ret; | 381 | return ret; |
370 | } | 382 | } |
371 | 383 | ||
372 | static int wm8350_rtc_resume(struct platform_device *pdev) | 384 | static int wm8350_rtc_resume(struct device *dev) |
373 | { | 385 | { |
386 | struct platform_device *pdev = to_platform_device(dev); | ||
374 | struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); | 387 | struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); |
375 | int ret; | 388 | int ret; |
376 | 389 | ||
@@ -455,15 +468,14 @@ static int wm8350_rtc_probe(struct platform_device *pdev) | |||
455 | return ret; | 468 | return ret; |
456 | } | 469 | } |
457 | 470 | ||
458 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
459 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_PER); | ||
460 | |||
461 | wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC, | 471 | wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC, |
462 | wm8350_rtc_update_handler, NULL); | 472 | wm8350_rtc_update_handler, 0, |
473 | "RTC Seconds", wm8350); | ||
474 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
463 | 475 | ||
464 | wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM, | 476 | wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM, |
465 | wm8350_rtc_alarm_handler, NULL); | 477 | wm8350_rtc_alarm_handler, 0, |
466 | wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_ALM); | 478 | "RTC Alarm", wm8350); |
467 | 479 | ||
468 | return 0; | 480 | return 0; |
469 | } | 481 | } |
@@ -473,23 +485,25 @@ static int __devexit wm8350_rtc_remove(struct platform_device *pdev) | |||
473 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | 485 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); |
474 | struct wm8350_rtc *wm_rtc = &wm8350->rtc; | 486 | struct wm8350_rtc *wm_rtc = &wm8350->rtc; |
475 | 487 | ||
476 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | 488 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC, wm8350); |
477 | 489 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM, wm8350); | |
478 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
479 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM); | ||
480 | 490 | ||
481 | rtc_device_unregister(wm_rtc->rtc); | 491 | rtc_device_unregister(wm_rtc->rtc); |
482 | 492 | ||
483 | return 0; | 493 | return 0; |
484 | } | 494 | } |
485 | 495 | ||
496 | static struct dev_pm_ops wm8350_rtc_pm_ops = { | ||
497 | .suspend = wm8350_rtc_suspend, | ||
498 | .resume = wm8350_rtc_resume, | ||
499 | }; | ||
500 | |||
486 | static struct platform_driver wm8350_rtc_driver = { | 501 | static struct platform_driver wm8350_rtc_driver = { |
487 | .probe = wm8350_rtc_probe, | 502 | .probe = wm8350_rtc_probe, |
488 | .remove = __devexit_p(wm8350_rtc_remove), | 503 | .remove = __devexit_p(wm8350_rtc_remove), |
489 | .suspend = wm8350_rtc_suspend, | ||
490 | .resume = wm8350_rtc_resume, | ||
491 | .driver = { | 504 | .driver = { |
492 | .name = "wm8350-rtc", | 505 | .name = "wm8350-rtc", |
506 | .pm = &wm8350_rtc_pm_ops, | ||
493 | }, | 507 | }, |
494 | }; | 508 | }; |
495 | 509 | ||
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index 310c10795e9a..9aae49139a0a 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c | |||
@@ -155,11 +155,11 @@ static int x1205_get_status(struct i2c_client *client, unsigned char *sr) | |||
155 | } | 155 | } |
156 | 156 | ||
157 | static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | 157 | static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, |
158 | int datetoo, u8 reg_base, unsigned char alm_enable) | 158 | u8 reg_base, unsigned char alm_enable) |
159 | { | 159 | { |
160 | int i, xfer, nbytes; | 160 | int i, xfer; |
161 | unsigned char buf[8]; | ||
162 | unsigned char rdata[10] = { 0, reg_base }; | 161 | unsigned char rdata[10] = { 0, reg_base }; |
162 | unsigned char *buf = rdata + 2; | ||
163 | 163 | ||
164 | static const unsigned char wel[3] = { 0, X1205_REG_SR, | 164 | static const unsigned char wel[3] = { 0, X1205_REG_SR, |
165 | X1205_SR_WEL }; | 165 | X1205_SR_WEL }; |
@@ -170,9 +170,9 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
170 | static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 }; | 170 | static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 }; |
171 | 171 | ||
172 | dev_dbg(&client->dev, | 172 | dev_dbg(&client->dev, |
173 | "%s: secs=%d, mins=%d, hours=%d\n", | 173 | "%s: sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d\n", |
174 | __func__, | 174 | __func__, tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, |
175 | tm->tm_sec, tm->tm_min, tm->tm_hour); | 175 | tm->tm_mon, tm->tm_year, tm->tm_wday); |
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); |
@@ -180,23 +180,15 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
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 | buf[CCR_MDAY] = bin2bcd(tm->tm_mday); |
184 | if (datetoo) { | ||
185 | dev_dbg(&client->dev, | ||
186 | "%s: mday=%d, mon=%d, year=%d, wday=%d\n", | ||
187 | __func__, | ||
188 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
189 | 184 | ||
190 | buf[CCR_MDAY] = bin2bcd(tm->tm_mday); | 185 | /* month, 1 - 12 */ |
186 | buf[CCR_MONTH] = bin2bcd(tm->tm_mon + 1); | ||
191 | 187 | ||
192 | /* month, 1 - 12 */ | 188 | /* year, since the rtc epoch*/ |
193 | buf[CCR_MONTH] = bin2bcd(tm->tm_mon + 1); | 189 | buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100); |
194 | 190 | buf[CCR_WDAY] = tm->tm_wday & 0x07; | |
195 | /* year, since the rtc epoch*/ | 191 | buf[CCR_Y2K] = bin2bcd((tm->tm_year + 1900) / 100); |
196 | buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100); | ||
197 | buf[CCR_WDAY] = tm->tm_wday & 0x07; | ||
198 | buf[CCR_Y2K] = bin2bcd(tm->tm_year / 100); | ||
199 | } | ||
200 | 192 | ||
201 | /* If writing alarm registers, set compare bits on registers 0-4 */ | 193 | /* If writing alarm registers, set compare bits on registers 0-4 */ |
202 | if (reg_base < X1205_CCR_BASE) | 194 | if (reg_base < X1205_CCR_BASE) |
@@ -214,17 +206,8 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
214 | return -EIO; | 206 | return -EIO; |
215 | } | 207 | } |
216 | 208 | ||
217 | 209 | xfer = i2c_master_send(client, rdata, sizeof(rdata)); | |
218 | /* write register's data */ | 210 | if (xfer != sizeof(rdata)) { |
219 | if (datetoo) | ||
220 | nbytes = 8; | ||
221 | else | ||
222 | nbytes = 3; | ||
223 | for (i = 0; i < nbytes; i++) | ||
224 | rdata[2+i] = buf[i]; | ||
225 | |||
226 | xfer = i2c_master_send(client, rdata, nbytes+2); | ||
227 | if (xfer != nbytes+2) { | ||
228 | dev_err(&client->dev, | 211 | dev_err(&client->dev, |
229 | "%s: result=%d addr=%02x, data=%02x\n", | 212 | "%s: result=%d addr=%02x, data=%02x\n", |
230 | __func__, | 213 | __func__, |
@@ -280,9 +263,9 @@ static int x1205_fix_osc(struct i2c_client *client) | |||
280 | int err; | 263 | int err; |
281 | struct rtc_time tm; | 264 | struct rtc_time tm; |
282 | 265 | ||
283 | tm.tm_hour = tm.tm_min = tm.tm_sec = 0; | 266 | memset(&tm, 0, sizeof(tm)); |
284 | 267 | ||
285 | err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE, 0); | 268 | err = x1205_set_datetime(client, &tm, X1205_CCR_BASE, 0); |
286 | if (err < 0) | 269 | if (err < 0) |
287 | dev_err(&client->dev, "unable to restart the oscillator\n"); | 270 | dev_err(&client->dev, "unable to restart the oscillator\n"); |
288 | 271 | ||
@@ -481,7 +464,7 @@ static int x1205_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
481 | static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 464 | static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
482 | { | 465 | { |
483 | return x1205_set_datetime(to_i2c_client(dev), | 466 | return x1205_set_datetime(to_i2c_client(dev), |
484 | &alrm->time, 1, X1205_ALM0_BASE, alrm->enabled); | 467 | &alrm->time, X1205_ALM0_BASE, alrm->enabled); |
485 | } | 468 | } |
486 | 469 | ||
487 | static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm) | 470 | static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm) |
@@ -493,7 +476,7 @@ static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
493 | static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm) | 476 | static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm) |
494 | { | 477 | { |
495 | return x1205_set_datetime(to_i2c_client(dev), | 478 | return x1205_set_datetime(to_i2c_client(dev), |
496 | tm, 1, X1205_CCR_BASE, 0); | 479 | tm, X1205_CCR_BASE, 0); |
497 | } | 480 | } |
498 | 481 | ||
499 | static int x1205_rtc_proc(struct device *dev, struct seq_file *seq) | 482 | static int x1205_rtc_proc(struct device *dev, struct seq_file *seq) |