diff options
Diffstat (limited to 'drivers/rtc')
59 files changed, 2762 insertions, 374 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 8167e9e6827a..10ba12c8c5e0 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -175,6 +175,16 @@ config RTC_DRV_MAX6900 | |||
| 175 | This driver can also be built as a module. If so, the module | 175 | This driver can also be built as a module. If so, the module |
| 176 | will be called rtc-max6900. | 176 | will be called rtc-max6900. |
| 177 | 177 | ||
| 178 | config RTC_DRV_MAX8925 | ||
| 179 | tristate "Maxim MAX8925" | ||
| 180 | depends on MFD_MAX8925 | ||
| 181 | help | ||
| 182 | If you say yes here you will get support for the | ||
| 183 | RTC of Maxim MAX8925 PMIC. | ||
| 184 | |||
| 185 | This driver can also be built as a module. If so, the module | ||
| 186 | will be called rtc-max8925. | ||
| 187 | |||
| 178 | config RTC_DRV_RS5C372 | 188 | config RTC_DRV_RS5C372 |
| 179 | tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" | 189 | tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" |
| 180 | help | 190 | help |
| @@ -601,6 +611,13 @@ config RTC_DRV_AB3100 | |||
| 601 | Select this to enable the ST-Ericsson AB3100 Mixed Signal IC RTC | 611 | Select this to enable the ST-Ericsson AB3100 Mixed Signal IC RTC |
| 602 | support. This chip contains a battery- and capacitor-backed RTC. | 612 | support. This chip contains a battery- and capacitor-backed RTC. |
| 603 | 613 | ||
| 614 | config RTC_DRV_AB8500 | ||
| 615 | tristate "ST-Ericsson AB8500 RTC" | ||
| 616 | depends on AB8500_CORE | ||
| 617 | help | ||
| 618 | Select this to enable the ST-Ericsson AB8500 power management IC RTC | ||
| 619 | support. This chip contains a battery- and capacitor-backed RTC. | ||
| 620 | |||
| 604 | config RTC_DRV_NUC900 | 621 | config RTC_DRV_NUC900 |
| 605 | tristate "NUC910/NUC920 RTC driver" | 622 | tristate "NUC910/NUC920 RTC driver" |
| 606 | depends on RTC_CLASS && ARCH_W90X900 | 623 | depends on RTC_CLASS && ARCH_W90X900 |
| @@ -610,6 +627,16 @@ config RTC_DRV_NUC900 | |||
| 610 | 627 | ||
| 611 | comment "on-CPU RTC drivers" | 628 | comment "on-CPU RTC drivers" |
| 612 | 629 | ||
| 630 | config RTC_DRV_DAVINCI | ||
| 631 | tristate "TI DaVinci RTC" | ||
| 632 | depends on ARCH_DAVINCI_DM365 | ||
| 633 | help | ||
| 634 | If you say yes here you get support for the RTC on the | ||
| 635 | DaVinci platforms (DM365). | ||
| 636 | |||
| 637 | This driver can also be built as a module. If so, the module | ||
| 638 | will be called rtc-davinci. | ||
| 639 | |||
| 613 | config RTC_DRV_OMAP | 640 | config RTC_DRV_OMAP |
| 614 | tristate "TI OMAP1" | 641 | tristate "TI OMAP1" |
| 615 | depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX | 642 | depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX |
| @@ -620,7 +647,7 @@ config RTC_DRV_OMAP | |||
| 620 | 647 | ||
| 621 | config RTC_DRV_S3C | 648 | config RTC_DRV_S3C |
| 622 | tristate "Samsung S3C series SoC RTC" | 649 | tristate "Samsung S3C series SoC RTC" |
| 623 | depends on ARCH_S3C2410 | 650 | depends on ARCH_S3C2410 || ARCH_S3C64XX |
| 624 | help | 651 | help |
| 625 | RTC (Realtime Clock) driver for the clock inbuilt into the | 652 | RTC (Realtime Clock) driver for the clock inbuilt into the |
| 626 | Samsung S3C24XX series of SoCs. This can provide periodic | 653 | Samsung S3C24XX series of SoCs. This can provide periodic |
| @@ -868,4 +895,14 @@ config RTC_DRV_MC13783 | |||
| 868 | help | 895 | help |
| 869 | This enables support for the Freescale MC13783 PMIC RTC | 896 | This enables support for the Freescale MC13783 PMIC RTC |
| 870 | 897 | ||
| 898 | config RTC_DRV_MPC5121 | ||
| 899 | tristate "Freescale MPC5121 built-in RTC" | ||
| 900 | depends on PPC_MPC512x && RTC_CLASS | ||
| 901 | help | ||
| 902 | If you say yes here you will get support for the | ||
| 903 | built-in RTC MPC5121. | ||
| 904 | |||
| 905 | This driver can also be built as a module. If so, the module | ||
| 906 | will be called rtc-mpc5121. | ||
| 907 | |||
| 871 | endif # RTC_CLASS | 908 | endif # RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index e5160fddc446..5adbba7cf89c 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
| @@ -18,6 +18,7 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o | |||
| 18 | # Keep the list ordered. | 18 | # Keep the list ordered. |
| 19 | 19 | ||
| 20 | obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o | 20 | obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o |
| 21 | obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o | ||
| 21 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o | 22 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o |
| 22 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o | 23 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o |
| 23 | obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o | 24 | obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o |
| @@ -27,6 +28,7 @@ obj-$(CONFIG_RTC_DRV_BQ32K) += rtc-bq32k.o | |||
| 27 | obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o | 28 | obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o |
| 28 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | 29 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o |
| 29 | obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o | 30 | obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o |
| 31 | obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o | ||
| 30 | obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o | 32 | obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o |
| 31 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o | 33 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o |
| 32 | obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o | 34 | obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o |
| @@ -52,9 +54,11 @@ obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o | |||
| 52 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | 54 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o |
| 53 | obj-$(CONFIG_RTC_MXC) += rtc-mxc.o | 55 | obj-$(CONFIG_RTC_MXC) += rtc-mxc.o |
| 54 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o | 56 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o |
| 57 | obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o | ||
| 55 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 58 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
| 56 | obj-$(CONFIG_RTC_DRV_MC13783) += rtc-mc13783.o | 59 | obj-$(CONFIG_RTC_DRV_MC13783) += rtc-mc13783.o |
| 57 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o | 60 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o |
| 61 | obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o | ||
| 58 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o | 62 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o |
| 59 | obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o | 63 | obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o |
| 60 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o | 64 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o |
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index be5a6b73e601..565562ba6ac9 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
| @@ -15,6 +15,7 @@ | |||
| 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> | ||
| 18 | 19 | ||
| 19 | #include "rtc-core.h" | 20 | #include "rtc-core.h" |
| 20 | 21 | ||
| @@ -226,6 +227,7 @@ static void __exit rtc_exit(void) | |||
| 226 | { | 227 | { |
| 227 | rtc_dev_exit(); | 228 | rtc_dev_exit(); |
| 228 | class_destroy(rtc_class); | 229 | class_destroy(rtc_class); |
| 230 | idr_destroy(&rtc_idr); | ||
| 229 | } | 231 | } |
| 230 | 232 | ||
| 231 | subsys_initcall(rtc_init); | 233 | 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/rtc-ab3100.c b/drivers/rtc/rtc-ab3100.c index 4704aac2b5af..d26780ea254b 100644 --- a/drivers/rtc/rtc-ab3100.c +++ b/drivers/rtc/rtc-ab3100.c | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
| 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/mfd/ab3100.h> | 12 | #include <linux/mfd/abx500.h> |
| 13 | 13 | ||
| 14 | /* Clock rate in Hz */ | 14 | /* Clock rate in Hz */ |
| 15 | #define AB3100_RTC_CLOCK_RATE 32768 | 15 | #define AB3100_RTC_CLOCK_RATE 32768 |
| @@ -45,7 +45,6 @@ | |||
| 45 | */ | 45 | */ |
| 46 | static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs) | 46 | static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs) |
| 47 | { | 47 | { |
| 48 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
| 49 | u8 regs[] = {AB3100_TI0, AB3100_TI1, AB3100_TI2, | 48 | u8 regs[] = {AB3100_TI0, AB3100_TI1, AB3100_TI2, |
| 50 | AB3100_TI3, AB3100_TI4, AB3100_TI5}; | 49 | AB3100_TI3, AB3100_TI4, AB3100_TI5}; |
| 51 | unsigned char buf[6]; | 50 | unsigned char buf[6]; |
| @@ -61,27 +60,26 @@ static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs) | |||
| 61 | buf[5] = (fat_time >> 40) & 0xFF; | 60 | buf[5] = (fat_time >> 40) & 0xFF; |
| 62 | 61 | ||
| 63 | for (i = 0; i < 6; i++) { | 62 | for (i = 0; i < 6; i++) { |
| 64 | err = ab3100_set_register_interruptible(ab3100_data, | 63 | err = abx500_set_register_interruptible(dev, 0, |
| 65 | regs[i], buf[i]); | 64 | regs[i], buf[i]); |
| 66 | if (err) | 65 | if (err) |
| 67 | return err; | 66 | return err; |
| 68 | } | 67 | } |
| 69 | 68 | ||
| 70 | /* Set the flag to mark that the clock is now set */ | 69 | /* Set the flag to mark that the clock is now set */ |
| 71 | return ab3100_mask_and_set_register_interruptible(ab3100_data, | 70 | return abx500_mask_and_set_register_interruptible(dev, 0, |
| 72 | AB3100_RTC, | 71 | AB3100_RTC, |
| 73 | 0xFE, 0x01); | 72 | 0x01, 0x01); |
| 74 | 73 | ||
| 75 | } | 74 | } |
| 76 | 75 | ||
| 77 | static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm) | 76 | static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm) |
| 78 | { | 77 | { |
| 79 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
| 80 | unsigned long time; | 78 | unsigned long time; |
| 81 | u8 rtcval; | 79 | u8 rtcval; |
| 82 | int err; | 80 | int err; |
| 83 | 81 | ||
| 84 | err = ab3100_get_register_interruptible(ab3100_data, | 82 | err = abx500_get_register_interruptible(dev, 0, |
| 85 | AB3100_RTC, &rtcval); | 83 | AB3100_RTC, &rtcval); |
| 86 | if (err) | 84 | if (err) |
| 87 | return err; | 85 | return err; |
| @@ -94,7 +92,7 @@ static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
| 94 | u8 buf[6]; | 92 | u8 buf[6]; |
| 95 | 93 | ||
| 96 | /* Read out time registers */ | 94 | /* Read out time registers */ |
| 97 | err = ab3100_get_register_page_interruptible(ab3100_data, | 95 | err = abx500_get_register_page_interruptible(dev, 0, |
| 98 | AB3100_TI0, | 96 | AB3100_TI0, |
| 99 | buf, 6); | 97 | buf, 6); |
| 100 | if (err != 0) | 98 | if (err != 0) |
| @@ -114,7 +112,6 @@ static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
| 114 | 112 | ||
| 115 | static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 113 | static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
| 116 | { | 114 | { |
| 117 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
| 118 | unsigned long time; | 115 | unsigned long time; |
| 119 | u64 fat_time; | 116 | u64 fat_time; |
| 120 | u8 buf[6]; | 117 | u8 buf[6]; |
| @@ -122,7 +119,7 @@ static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
| 122 | int err; | 119 | int err; |
| 123 | 120 | ||
| 124 | /* Figure out if alarm is enabled or not */ | 121 | /* Figure out if alarm is enabled or not */ |
| 125 | err = ab3100_get_register_interruptible(ab3100_data, | 122 | err = abx500_get_register_interruptible(dev, 0, |
| 126 | AB3100_RTC, &rtcval); | 123 | AB3100_RTC, &rtcval); |
| 127 | if (err) | 124 | if (err) |
| 128 | return err; | 125 | return err; |
| @@ -133,7 +130,7 @@ static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
| 133 | /* No idea how this could be represented */ | 130 | /* No idea how this could be represented */ |
| 134 | alarm->pending = 0; | 131 | alarm->pending = 0; |
| 135 | /* Read out alarm registers, only 4 bytes */ | 132 | /* Read out alarm registers, only 4 bytes */ |
| 136 | err = ab3100_get_register_page_interruptible(ab3100_data, | 133 | err = abx500_get_register_page_interruptible(dev, 0, |
| 137 | AB3100_AL0, buf, 4); | 134 | AB3100_AL0, buf, 4); |
| 138 | if (err) | 135 | if (err) |
| 139 | return err; | 136 | return err; |
| @@ -148,7 +145,6 @@ static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
| 148 | 145 | ||
| 149 | static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 146 | static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
| 150 | { | 147 | { |
| 151 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
| 152 | u8 regs[] = {AB3100_AL0, AB3100_AL1, AB3100_AL2, AB3100_AL3}; | 148 | u8 regs[] = {AB3100_AL0, AB3100_AL1, AB3100_AL2, AB3100_AL3}; |
| 153 | unsigned char buf[4]; | 149 | unsigned char buf[4]; |
| 154 | unsigned long secs; | 150 | unsigned long secs; |
| @@ -165,21 +161,19 @@ static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
| 165 | 161 | ||
| 166 | /* Set the alarm */ | 162 | /* Set the alarm */ |
| 167 | for (i = 0; i < 4; i++) { | 163 | for (i = 0; i < 4; i++) { |
| 168 | err = ab3100_set_register_interruptible(ab3100_data, | 164 | err = abx500_set_register_interruptible(dev, 0, |
| 169 | regs[i], buf[i]); | 165 | regs[i], buf[i]); |
| 170 | if (err) | 166 | if (err) |
| 171 | return err; | 167 | return err; |
| 172 | } | 168 | } |
| 173 | /* Then enable the alarm */ | 169 | /* Then enable the alarm */ |
| 174 | return ab3100_mask_and_set_register_interruptible(ab3100_data, | 170 | return abx500_mask_and_set_register_interruptible(dev, 0, |
| 175 | AB3100_RTC, ~(1 << 2), | 171 | AB3100_RTC, (1 << 2), |
| 176 | alarm->enabled << 2); | 172 | alarm->enabled << 2); |
| 177 | } | 173 | } |
| 178 | 174 | ||
| 179 | static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled) | 175 | static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled) |
| 180 | { | 176 | { |
| 181 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
| 182 | |||
| 183 | /* | 177 | /* |
| 184 | * It's not possible to enable/disable the alarm IRQ for this RTC. | 178 | * It's not possible to enable/disable the alarm IRQ for this RTC. |
| 185 | * It does not actually trigger any IRQ: instead its only function is | 179 | * It does not actually trigger any IRQ: instead its only function is |
| @@ -188,12 +182,12 @@ static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled) | |||
| 188 | * and need to be handled there instead. | 182 | * and need to be handled there instead. |
| 189 | */ | 183 | */ |
| 190 | if (enabled) | 184 | if (enabled) |
| 191 | return ab3100_mask_and_set_register_interruptible(ab3100_data, | 185 | return abx500_mask_and_set_register_interruptible(dev, 0, |
| 192 | AB3100_RTC, ~(1 << 2), | 186 | AB3100_RTC, (1 << 2), |
| 193 | 1 << 2); | 187 | 1 << 2); |
| 194 | else | 188 | else |
| 195 | return ab3100_mask_and_set_register_interruptible(ab3100_data, | 189 | return abx500_mask_and_set_register_interruptible(dev, 0, |
| 196 | AB3100_RTC, ~(1 << 2), | 190 | AB3100_RTC, (1 << 2), |
| 197 | 0); | 191 | 0); |
| 198 | } | 192 | } |
| 199 | 193 | ||
| @@ -210,10 +204,9 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev) | |||
| 210 | int err; | 204 | int err; |
| 211 | u8 regval; | 205 | u8 regval; |
| 212 | struct rtc_device *rtc; | 206 | struct rtc_device *rtc; |
| 213 | struct ab3100 *ab3100_data = platform_get_drvdata(pdev); | ||
| 214 | 207 | ||
| 215 | /* The first RTC register needs special treatment */ | 208 | /* The first RTC register needs special treatment */ |
| 216 | err = ab3100_get_register_interruptible(ab3100_data, | 209 | err = abx500_get_register_interruptible(&pdev->dev, 0, |
| 217 | AB3100_RTC, ®val); | 210 | AB3100_RTC, ®val); |
| 218 | if (err) { | 211 | if (err) { |
| 219 | dev_err(&pdev->dev, "unable to read RTC register\n"); | 212 | dev_err(&pdev->dev, "unable to read RTC register\n"); |
| @@ -231,7 +224,7 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev) | |||
| 231 | * This bit remains until RTC power is lost. | 224 | * This bit remains until RTC power is lost. |
| 232 | */ | 225 | */ |
| 233 | regval = 1 | RTC_SETTING; | 226 | regval = 1 | RTC_SETTING; |
| 234 | err = ab3100_set_register_interruptible(ab3100_data, | 227 | err = abx500_set_register_interruptible(&pdev->dev, 0, |
| 235 | AB3100_RTC, regval); | 228 | AB3100_RTC, regval); |
| 236 | /* Ignore any error on this write */ | 229 | /* Ignore any error on this write */ |
| 237 | } | 230 | } |
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c new file mode 100644 index 000000000000..2fda03125e55 --- /dev/null +++ b/drivers/rtc/rtc-ab8500.c | |||
| @@ -0,0 +1,363 @@ | |||
| 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/ab8500.h> | ||
| 18 | #include <linux/delay.h> | ||
| 19 | |||
| 20 | #define AB8500_RTC_SOFF_STAT_REG 0x0F00 | ||
| 21 | #define AB8500_RTC_CC_CONF_REG 0x0F01 | ||
| 22 | #define AB8500_RTC_READ_REQ_REG 0x0F02 | ||
| 23 | #define AB8500_RTC_WATCH_TSECMID_REG 0x0F03 | ||
| 24 | #define AB8500_RTC_WATCH_TSECHI_REG 0x0F04 | ||
| 25 | #define AB8500_RTC_WATCH_TMIN_LOW_REG 0x0F05 | ||
| 26 | #define AB8500_RTC_WATCH_TMIN_MID_REG 0x0F06 | ||
| 27 | #define AB8500_RTC_WATCH_TMIN_HI_REG 0x0F07 | ||
| 28 | #define AB8500_RTC_ALRM_MIN_LOW_REG 0x0F08 | ||
| 29 | #define AB8500_RTC_ALRM_MIN_MID_REG 0x0F09 | ||
| 30 | #define AB8500_RTC_ALRM_MIN_HI_REG 0x0F0A | ||
| 31 | #define AB8500_RTC_STAT_REG 0x0F0B | ||
| 32 | #define AB8500_RTC_BKUP_CHG_REG 0x0F0C | ||
| 33 | #define AB8500_RTC_FORCE_BKUP_REG 0x0F0D | ||
| 34 | #define AB8500_RTC_CALIB_REG 0x0F0E | ||
| 35 | #define AB8500_RTC_SWITCH_STAT_REG 0x0F0F | ||
| 36 | #define AB8500_REV_REG 0x1080 | ||
| 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 unsigned long 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 unsigned long 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 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
| 80 | unsigned long timeout = jiffies + HZ; | ||
| 81 | int retval, i; | ||
| 82 | unsigned long mins, secs; | ||
| 83 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; | ||
| 84 | |||
| 85 | /* Request a data read */ | ||
| 86 | retval = ab8500_write(ab8500, AB8500_RTC_READ_REQ_REG, | ||
| 87 | 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 (ab8500->revision == 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 = ab8500_read(ab8500, AB8500_RTC_READ_REQ_REG); | ||
| 98 | if (retval < 0) | ||
| 99 | return retval; | ||
| 100 | |||
| 101 | if (!(retval & RTC_READ_REQUEST)) | ||
| 102 | break; | ||
| 103 | |||
| 104 | msleep(1); | ||
| 105 | } | ||
| 106 | } | ||
| 107 | |||
| 108 | /* Read the Watchtime registers */ | ||
| 109 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) { | ||
| 110 | retval = ab8500_read(ab8500, ab8500_rtc_time_regs[i]); | ||
| 111 | if (retval < 0) | ||
| 112 | return retval; | ||
| 113 | buf[i] = retval; | ||
| 114 | } | ||
| 115 | |||
| 116 | mins = (buf[0] << 16) | (buf[1] << 8) | buf[2]; | ||
| 117 | |||
| 118 | secs = (buf[3] << 8) | buf[4]; | ||
| 119 | secs = secs / COUNTS_PER_SEC; | ||
| 120 | secs = secs + (mins * 60); | ||
| 121 | |||
| 122 | /* Add back the initially subtracted number of seconds */ | ||
| 123 | secs += get_elapsed_seconds(AB8500_RTC_EPOCH); | ||
| 124 | |||
| 125 | rtc_time_to_tm(secs, tm); | ||
| 126 | return rtc_valid_tm(tm); | ||
| 127 | } | ||
| 128 | |||
| 129 | static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 130 | { | ||
| 131 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
| 132 | int retval, i; | ||
| 133 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; | ||
| 134 | unsigned long no_secs, no_mins, secs = 0; | ||
| 135 | |||
| 136 | if (tm->tm_year < (AB8500_RTC_EPOCH - 1900)) { | ||
| 137 | dev_dbg(dev, "year should be equal to or greater than %d\n", | ||
| 138 | AB8500_RTC_EPOCH); | ||
| 139 | return -EINVAL; | ||
| 140 | } | ||
| 141 | |||
| 142 | /* Get the number of seconds since 1970 */ | ||
| 143 | rtc_tm_to_time(tm, &secs); | ||
| 144 | |||
| 145 | /* | ||
| 146 | * Convert it to the number of seconds since 01-01-2000 00:00:00, since | ||
| 147 | * we only have a small counter in the RTC. | ||
| 148 | */ | ||
| 149 | secs -= get_elapsed_seconds(AB8500_RTC_EPOCH); | ||
| 150 | |||
| 151 | no_mins = secs / 60; | ||
| 152 | |||
| 153 | no_secs = secs % 60; | ||
| 154 | /* Make the seconds count as per the RTC resolution */ | ||
| 155 | no_secs = no_secs * COUNTS_PER_SEC; | ||
| 156 | |||
| 157 | buf[4] = no_secs & 0xFF; | ||
| 158 | buf[3] = (no_secs >> 8) & 0xFF; | ||
| 159 | |||
| 160 | buf[2] = no_mins & 0xFF; | ||
| 161 | buf[1] = (no_mins >> 8) & 0xFF; | ||
| 162 | buf[0] = (no_mins >> 16) & 0xFF; | ||
| 163 | |||
| 164 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) { | ||
| 165 | retval = ab8500_write(ab8500, ab8500_rtc_time_regs[i], buf[i]); | ||
| 166 | if (retval < 0) | ||
| 167 | return retval; | ||
| 168 | } | ||
| 169 | |||
| 170 | /* Request a data write */ | ||
| 171 | return ab8500_write(ab8500, AB8500_RTC_READ_REQ_REG, RTC_WRITE_REQUEST); | ||
| 172 | } | ||
| 173 | |||
| 174 | static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
| 175 | { | ||
| 176 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
| 177 | int retval, i; | ||
| 178 | int rtc_ctrl; | ||
| 179 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; | ||
| 180 | unsigned long secs, mins; | ||
| 181 | |||
| 182 | /* Check if the alarm is enabled or not */ | ||
| 183 | rtc_ctrl = ab8500_read(ab8500, AB8500_RTC_STAT_REG); | ||
| 184 | if (rtc_ctrl < 0) | ||
| 185 | return rtc_ctrl; | ||
| 186 | |||
| 187 | if (rtc_ctrl & RTC_ALARM_ENA) | ||
| 188 | alarm->enabled = 1; | ||
| 189 | else | ||
| 190 | alarm->enabled = 0; | ||
| 191 | |||
| 192 | alarm->pending = 0; | ||
| 193 | |||
| 194 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) { | ||
| 195 | retval = ab8500_read(ab8500, ab8500_rtc_alarm_regs[i]); | ||
| 196 | if (retval < 0) | ||
| 197 | return retval; | ||
| 198 | buf[i] = retval; | ||
| 199 | } | ||
| 200 | |||
| 201 | mins = (buf[0] << 16) | (buf[1] << 8) | (buf[2]); | ||
| 202 | secs = mins * 60; | ||
| 203 | |||
| 204 | /* Add back the initially subtracted number of seconds */ | ||
| 205 | secs += get_elapsed_seconds(AB8500_RTC_EPOCH); | ||
| 206 | |||
| 207 | rtc_time_to_tm(secs, &alarm->time); | ||
| 208 | |||
| 209 | return rtc_valid_tm(&alarm->time); | ||
| 210 | } | ||
| 211 | |||
| 212 | static int ab8500_rtc_irq_enable(struct device *dev, unsigned int enabled) | ||
| 213 | { | ||
| 214 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
| 215 | |||
| 216 | return ab8500_set_bits(ab8500, AB8500_RTC_STAT_REG, RTC_ALARM_ENA, | ||
| 217 | enabled ? RTC_ALARM_ENA : 0); | ||
| 218 | } | ||
| 219 | |||
| 220 | static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
| 221 | { | ||
| 222 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
| 223 | int retval, i; | ||
| 224 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; | ||
| 225 | unsigned long mins, secs = 0; | ||
| 226 | |||
| 227 | if (alarm->time.tm_year < (AB8500_RTC_EPOCH - 1900)) { | ||
| 228 | dev_dbg(dev, "year should be equal to or greater than %d\n", | ||
| 229 | AB8500_RTC_EPOCH); | ||
| 230 | return -EINVAL; | ||
| 231 | } | ||
| 232 | |||
| 233 | /* Get the number of seconds since 1970 */ | ||
| 234 | rtc_tm_to_time(&alarm->time, &secs); | ||
| 235 | |||
| 236 | /* | ||
| 237 | * Convert it to the number of seconds since 01-01-2000 00:00:00, since | ||
| 238 | * we only have a small counter in the RTC. | ||
| 239 | */ | ||
| 240 | secs -= get_elapsed_seconds(AB8500_RTC_EPOCH); | ||
| 241 | |||
| 242 | mins = secs / 60; | ||
| 243 | |||
| 244 | buf[2] = mins & 0xFF; | ||
| 245 | buf[1] = (mins >> 8) & 0xFF; | ||
| 246 | buf[0] = (mins >> 16) & 0xFF; | ||
| 247 | |||
| 248 | /* Set the alarm time */ | ||
| 249 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) { | ||
| 250 | retval = ab8500_write(ab8500, ab8500_rtc_alarm_regs[i], buf[i]); | ||
| 251 | if (retval < 0) | ||
| 252 | return retval; | ||
| 253 | } | ||
| 254 | |||
| 255 | return ab8500_rtc_irq_enable(dev, alarm->enabled); | ||
| 256 | } | ||
| 257 | |||
| 258 | static irqreturn_t rtc_alarm_handler(int irq, void *data) | ||
| 259 | { | ||
| 260 | struct rtc_device *rtc = data; | ||
| 261 | unsigned long events = RTC_IRQF | RTC_AF; | ||
| 262 | |||
| 263 | dev_dbg(&rtc->dev, "%s\n", __func__); | ||
| 264 | rtc_update_irq(rtc, 1, events); | ||
| 265 | |||
| 266 | return IRQ_HANDLED; | ||
| 267 | } | ||
| 268 | |||
| 269 | static const struct rtc_class_ops ab8500_rtc_ops = { | ||
| 270 | .read_time = ab8500_rtc_read_time, | ||
| 271 | .set_time = ab8500_rtc_set_time, | ||
| 272 | .read_alarm = ab8500_rtc_read_alarm, | ||
| 273 | .set_alarm = ab8500_rtc_set_alarm, | ||
| 274 | .alarm_irq_enable = ab8500_rtc_irq_enable, | ||
| 275 | }; | ||
| 276 | |||
| 277 | static int __devinit ab8500_rtc_probe(struct platform_device *pdev) | ||
| 278 | { | ||
| 279 | struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); | ||
| 280 | int err; | ||
| 281 | struct rtc_device *rtc; | ||
| 282 | int rtc_ctrl; | ||
| 283 | int irq; | ||
| 284 | |||
| 285 | irq = platform_get_irq_byname(pdev, "ALARM"); | ||
| 286 | if (irq < 0) | ||
| 287 | return irq; | ||
| 288 | |||
| 289 | /* For RTC supply test */ | ||
| 290 | err = ab8500_set_bits(ab8500, AB8500_RTC_STAT_REG, RTC_STATUS_DATA, | ||
| 291 | RTC_STATUS_DATA); | ||
| 292 | if (err < 0) | ||
| 293 | return err; | ||
| 294 | |||
| 295 | /* Wait for reset by the PorRtc */ | ||
| 296 | msleep(1); | ||
| 297 | |||
| 298 | rtc_ctrl = ab8500_read(ab8500, AB8500_RTC_STAT_REG); | ||
| 299 | if (rtc_ctrl < 0) | ||
| 300 | return rtc_ctrl; | ||
| 301 | |||
| 302 | /* Check if the RTC Supply fails */ | ||
| 303 | if (!(rtc_ctrl & RTC_STATUS_DATA)) { | ||
| 304 | dev_err(&pdev->dev, "RTC supply failure\n"); | ||
| 305 | return -ENODEV; | ||
| 306 | } | ||
| 307 | |||
| 308 | rtc = rtc_device_register("ab8500-rtc", &pdev->dev, &ab8500_rtc_ops, | ||
| 309 | THIS_MODULE); | ||
| 310 | if (IS_ERR(rtc)) { | ||
| 311 | dev_err(&pdev->dev, "Registration failed\n"); | ||
| 312 | err = PTR_ERR(rtc); | ||
| 313 | return err; | ||
| 314 | } | ||
| 315 | |||
| 316 | err = request_threaded_irq(irq, NULL, rtc_alarm_handler, 0, | ||
| 317 | "ab8500-rtc", rtc); | ||
| 318 | if (err < 0) { | ||
| 319 | rtc_device_unregister(rtc); | ||
| 320 | return err; | ||
| 321 | } | ||
| 322 | |||
| 323 | platform_set_drvdata(pdev, rtc); | ||
| 324 | |||
| 325 | return 0; | ||
| 326 | } | ||
| 327 | |||
| 328 | static int __devexit ab8500_rtc_remove(struct platform_device *pdev) | ||
| 329 | { | ||
| 330 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
| 331 | int irq = platform_get_irq_byname(pdev, "ALARM"); | ||
| 332 | |||
| 333 | free_irq(irq, rtc); | ||
| 334 | rtc_device_unregister(rtc); | ||
| 335 | platform_set_drvdata(pdev, NULL); | ||
| 336 | |||
| 337 | return 0; | ||
| 338 | } | ||
| 339 | |||
| 340 | static struct platform_driver ab8500_rtc_driver = { | ||
| 341 | .driver = { | ||
| 342 | .name = "ab8500-rtc", | ||
| 343 | .owner = THIS_MODULE, | ||
| 344 | }, | ||
| 345 | .probe = ab8500_rtc_probe, | ||
| 346 | .remove = __devexit_p(ab8500_rtc_remove), | ||
| 347 | }; | ||
| 348 | |||
| 349 | static int __init ab8500_rtc_init(void) | ||
| 350 | { | ||
| 351 | return platform_driver_register(&ab8500_rtc_driver); | ||
| 352 | } | ||
| 353 | |||
| 354 | static void __exit ab8500_rtc_exit(void) | ||
| 355 | { | ||
| 356 | platform_driver_unregister(&ab8500_rtc_driver); | ||
| 357 | } | ||
| 358 | |||
| 359 | module_init(ab8500_rtc_init); | ||
| 360 | module_exit(ab8500_rtc_exit); | ||
| 361 | MODULE_AUTHOR("Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>"); | ||
| 362 | MODULE_DESCRIPTION("AB8500 RTC Driver"); | ||
| 363 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c index 8825695777df..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 | ||
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 b11485b9f21c..72b2bcc2c224 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
| @@ -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 | ||
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c index 280fe48ada0b..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"); |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index e9aa814ddd23..11b8ea29d2b7 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 | ||
| @@ -478,7 +476,7 @@ static int cmos_procfs(struct device *dev, struct seq_file *seq) | |||
| 478 | "update_IRQ\t: %s\n" | 476 | "update_IRQ\t: %s\n" |
| 479 | "HPET_emulated\t: %s\n" | 477 | "HPET_emulated\t: %s\n" |
| 480 | // "square_wave\t: %s\n" | 478 | // "square_wave\t: %s\n" |
| 481 | // "BCD\t\t: %s\n" | 479 | "BCD\t\t: %s\n" |
| 482 | "DST_enable\t: %s\n" | 480 | "DST_enable\t: %s\n" |
| 483 | "periodic_freq\t: %d\n" | 481 | "periodic_freq\t: %d\n" |
| 484 | "batt_status\t: %s\n", | 482 | "batt_status\t: %s\n", |
| @@ -486,7 +484,7 @@ static int cmos_procfs(struct device *dev, struct seq_file *seq) | |||
| 486 | (rtc_control & RTC_UIE) ? "yes" : "no", | 484 | (rtc_control & RTC_UIE) ? "yes" : "no", |
| 487 | is_hpet_enabled() ? "yes" : "no", | 485 | is_hpet_enabled() ? "yes" : "no", |
| 488 | // (rtc_control & RTC_SQWE) ? "yes" : "no", | 486 | // (rtc_control & RTC_SQWE) ? "yes" : "no", |
| 489 | // (rtc_control & RTC_DM_BINARY) ? "no" : "yes", | 487 | (rtc_control & RTC_DM_BINARY) ? "no" : "yes", |
| 490 | (rtc_control & RTC_DST_EN) ? "yes" : "no", | 488 | (rtc_control & RTC_DST_EN) ? "yes" : "no", |
| 491 | cmos->rtc->irq_freq, | 489 | cmos->rtc->irq_freq, |
| 492 | (valid & RTC_VRT) ? "okay" : "dead"); | 490 | (valid & RTC_VRT) ? "okay" : "dead"); |
| @@ -519,7 +517,8 @@ static const struct rtc_class_ops cmos_rtc_ops = { | |||
| 519 | #define NVRAM_OFFSET (RTC_REG_D + 1) | 517 | #define NVRAM_OFFSET (RTC_REG_D + 1) |
| 520 | 518 | ||
| 521 | static ssize_t | 519 | static ssize_t |
| 522 | 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, | ||
| 523 | char *buf, loff_t off, size_t count) | 522 | char *buf, loff_t off, size_t count) |
| 524 | { | 523 | { |
| 525 | int retval; | 524 | int retval; |
| @@ -547,7 +546,8 @@ cmos_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | |||
| 547 | } | 546 | } |
| 548 | 547 | ||
| 549 | static ssize_t | 548 | static ssize_t |
| 550 | 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, | ||
| 551 | char *buf, loff_t off, size_t count) | 551 | char *buf, loff_t off, size_t count) |
| 552 | { | 552 | { |
| 553 | struct cmos_rtc *cmos; | 553 | struct cmos_rtc *cmos; |
| @@ -719,6 +719,9 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 719 | } | 719 | } |
| 720 | } | 720 | } |
| 721 | 721 | ||
| 722 | cmos_rtc.dev = dev; | ||
| 723 | dev_set_drvdata(dev, &cmos_rtc); | ||
| 724 | |||
| 722 | cmos_rtc.rtc = rtc_device_register(driver_name, dev, | 725 | cmos_rtc.rtc = rtc_device_register(driver_name, dev, |
| 723 | &cmos_rtc_ops, THIS_MODULE); | 726 | &cmos_rtc_ops, THIS_MODULE); |
| 724 | if (IS_ERR(cmos_rtc.rtc)) { | 727 | if (IS_ERR(cmos_rtc.rtc)) { |
| @@ -726,8 +729,6 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 726 | goto cleanup0; | 729 | goto cleanup0; |
| 727 | } | 730 | } |
| 728 | 731 | ||
| 729 | cmos_rtc.dev = dev; | ||
| 730 | dev_set_drvdata(dev, &cmos_rtc); | ||
| 731 | rename_region(ports, dev_name(&cmos_rtc.rtc->dev)); | 732 | rename_region(ports, dev_name(&cmos_rtc.rtc->dev)); |
| 732 | 733 | ||
| 733 | spin_lock_irq(&rtc_lock); | 734 | spin_lock_irq(&rtc_lock); |
| @@ -749,12 +750,11 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 749 | 750 | ||
| 750 | spin_unlock_irq(&rtc_lock); | 751 | spin_unlock_irq(&rtc_lock); |
| 751 | 752 | ||
| 752 | /* FIXME teach the alarm code how to handle binary mode; | 753 | /* FIXME: |
| 753 | * <asm-generic/rtc.h> doesn't know 12-hour mode either. | 754 | * <asm-generic/rtc.h> doesn't know 12-hour mode either. |
| 754 | */ | 755 | */ |
| 755 | if (is_valid_irq(rtc_irq) && | 756 | if (is_valid_irq(rtc_irq) && !(rtc_control & RTC_24H)) { |
| 756 | (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY)))) { | 757 | dev_warn(dev, "only 24-hr supported\n"); |
| 757 | dev_dbg(dev, "only 24-hr BCD mode supported\n"); | ||
| 758 | retval = -ENXIO; | 758 | retval = -ENXIO; |
| 759 | goto cleanup1; | 759 | goto cleanup1; |
| 760 | } | 760 | } |
diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c index 03ea530981d1..316f484999b5 100644 --- a/drivers/rtc/rtc-coh901331.c +++ b/drivers/rtc/rtc-coh901331.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/pm.h> | 14 | #include <linux/pm.h> |
| 15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
| 16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
| 17 | #include <linux/slab.h> | ||
| 17 | 18 | ||
| 18 | /* | 19 | /* |
| 19 | * Registers in the COH 901 331 | 20 | * Registers in the COH 901 331 |
| @@ -271,12 +272,13 @@ static int coh901331_resume(struct platform_device *pdev) | |||
| 271 | { | 272 | { |
| 272 | struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev); | 273 | struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev); |
| 273 | 274 | ||
| 274 | if (device_may_wakeup(&pdev->dev)) | 275 | if (device_may_wakeup(&pdev->dev)) { |
| 275 | disable_irq_wake(rtap->irq); | 276 | disable_irq_wake(rtap->irq); |
| 276 | else | 277 | } else { |
| 277 | clk_enable(rtap->clk); | 278 | clk_enable(rtap->clk); |
| 278 | writel(rtap->irqmaskstore, rtap->virtbase + COH901331_IRQ_MASK); | 279 | writel(rtap->irqmaskstore, rtap->virtbase + COH901331_IRQ_MASK); |
| 279 | clk_disable(rtap->clk); | 280 | clk_disable(rtap->clk); |
| 281 | } | ||
| 280 | return 0; | 282 | return 0; |
| 281 | } | 283 | } |
| 282 | #else | 284 | #else |
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-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 532acf9b05d8..359d1e04626c 100644 --- a/drivers/rtc/rtc-ds1302.c +++ b/drivers/rtc/rtc-ds1302.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | #include <linux/rtc.h> | 16 | #include <linux/rtc.h> |
| 17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
| 18 | #include <linux/bcd.h> | 18 | #include <linux/bcd.h> |
| 19 | #include <asm/rtc.h> | ||
| 20 | 19 | ||
| 21 | #define DRV_NAME "rtc-ds1302" | 20 | #define DRV_NAME "rtc-ds1302" |
| 22 | #define DRV_VERSION "0.1.1" | 21 | #define DRV_VERSION "0.1.1" |
| @@ -34,14 +33,55 @@ | |||
| 34 | #define RTC_ADDR_MIN 0x01 /* Address of minute register */ | 33 | #define RTC_ADDR_MIN 0x01 /* Address of minute register */ |
| 35 | #define RTC_ADDR_SEC 0x00 /* Address of second register */ | 34 | #define RTC_ADDR_SEC 0x00 /* Address of second register */ |
| 36 | 35 | ||
| 36 | #ifdef CONFIG_SH_SECUREEDGE5410 | ||
| 37 | #include <asm/rtc.h> | ||
| 38 | #include <mach/snapgear.h> | ||
| 39 | |||
| 37 | #define RTC_RESET 0x1000 | 40 | #define RTC_RESET 0x1000 |
| 38 | #define RTC_IODATA 0x0800 | 41 | #define RTC_IODATA 0x0800 |
| 39 | #define RTC_SCLK 0x0400 | 42 | #define RTC_SCLK 0x0400 |
| 40 | 43 | ||
| 41 | #ifdef CONFIG_SH_SECUREEDGE5410 | ||
| 42 | #include <mach/snapgear.h> | ||
| 43 | #define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00) | 44 | #define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00) |
| 44 | #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 | |||
| 45 | #else | 85 | #else |
| 46 | #error "Add support for your platform" | 86 | #error "Add support for your platform" |
| 47 | #endif | 87 | #endif |
| @@ -50,11 +90,11 @@ static void ds1302_sendbits(unsigned int val) | |||
| 50 | { | 90 | { |
| 51 | int i; | 91 | int i; |
| 52 | 92 | ||
| 93 | ds1302_set_tx(); | ||
| 94 | |||
| 53 | for (i = 8; (i); i--, val >>= 1) { | 95 | for (i = 8; (i); i--, val >>= 1) { |
| 54 | set_dp((get_dp() & ~RTC_IODATA) | ((val & 0x1) ? | 96 | ds1302_txbit(val & 0x1); |
| 55 | RTC_IODATA : 0)); | 97 | ds1302_clock(); |
| 56 | set_dp(get_dp() | RTC_SCLK); /* clock high */ | ||
| 57 | set_dp(get_dp() & ~RTC_SCLK); /* clock low */ | ||
| 58 | } | 98 | } |
| 59 | } | 99 | } |
| 60 | 100 | ||
| @@ -63,10 +103,11 @@ static unsigned int ds1302_recvbits(void) | |||
| 63 | unsigned int val; | 103 | unsigned int val; |
| 64 | int i; | 104 | int i; |
| 65 | 105 | ||
| 106 | ds1302_set_rx(); | ||
| 107 | |||
| 66 | for (i = 0, val = 0; (i < 8); i++) { | 108 | for (i = 0, val = 0; (i < 8); i++) { |
| 67 | val |= (((get_dp() & RTC_IODATA) ? 1 : 0) << i); | 109 | val |= (ds1302_rxbit() << i); |
| 68 | set_dp(get_dp() | RTC_SCLK); /* clock high */ | 110 | ds1302_clock(); |
| 69 | set_dp(get_dp() & ~RTC_SCLK); /* clock low */ | ||
| 70 | } | 111 | } |
| 71 | 112 | ||
| 72 | return val; | 113 | return val; |
| @@ -76,23 +117,24 @@ static unsigned int ds1302_readbyte(unsigned int addr) | |||
| 76 | { | 117 | { |
| 77 | unsigned int val; | 118 | unsigned int val; |
| 78 | 119 | ||
| 79 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | 120 | ds1302_reset(); |
| 80 | 121 | ||
| 81 | set_dp(get_dp() | RTC_RESET); | 122 | ds1302_start(); |
| 82 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ); | 123 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ); |
| 83 | val = ds1302_recvbits(); | 124 | val = ds1302_recvbits(); |
| 84 | set_dp(get_dp() & ~RTC_RESET); | 125 | ds1302_stop(); |
| 85 | 126 | ||
| 86 | return val; | 127 | return val; |
| 87 | } | 128 | } |
| 88 | 129 | ||
| 89 | static void ds1302_writebyte(unsigned int addr, unsigned int val) | 130 | static void ds1302_writebyte(unsigned int addr, unsigned int val) |
| 90 | { | 131 | { |
| 91 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | 132 | ds1302_reset(); |
| 92 | set_dp(get_dp() | RTC_RESET); | 133 | |
| 134 | ds1302_start(); | ||
| 93 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE); | 135 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE); |
| 94 | ds1302_sendbits(val); | 136 | ds1302_sendbits(val); |
| 95 | set_dp(get_dp() & ~RTC_RESET); | 137 | ds1302_stop(); |
| 96 | } | 138 | } |
| 97 | 139 | ||
| 98 | 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) |
| @@ -167,13 +209,20 @@ static int __init ds1302_rtc_probe(struct platform_device *pdev) | |||
| 167 | { | 209 | { |
| 168 | struct rtc_device *rtc; | 210 | struct rtc_device *rtc; |
| 169 | 211 | ||
| 212 | if (ds1302_hw_init()) { | ||
| 213 | dev_err(&pdev->dev, "Failed to init communication channel"); | ||
| 214 | return -EINVAL; | ||
| 215 | } | ||
| 216 | |||
| 170 | /* Reset */ | 217 | /* Reset */ |
| 171 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | 218 | ds1302_reset(); |
| 172 | 219 | ||
| 173 | /* 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. */ |
| 174 | ds1302_writebyte(RTC_ADDR_RAM0, 0x42); | 221 | ds1302_writebyte(RTC_ADDR_RAM0, 0x42); |
| 175 | if (ds1302_readbyte(RTC_ADDR_RAM0) != 0x42) | 222 | if (ds1302_readbyte(RTC_ADDR_RAM0) != 0x42) { |
| 223 | dev_err(&pdev->dev, "Failed to probe"); | ||
| 176 | return -ENODEV; | 224 | return -ENODEV; |
| 225 | } | ||
| 177 | 226 | ||
| 178 | rtc = rtc_device_register("ds1302", &pdev->dev, | 227 | rtc = rtc_device_register("ds1302", &pdev->dev, |
| 179 | &ds1302_rtc_ops, THIS_MODULE); | 228 | &ds1302_rtc_ops, THIS_MODULE); |
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 9630e7d3314e..48da85e97ca4 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; |
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index c4ec5c158aa1..d827ce570a8c 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
| @@ -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 | ||
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 5317bbcbc7a0..1f0007fd4431 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 |
| @@ -402,7 +403,6 @@ out_irq: | |||
| 402 | free_irq(client->irq, client); | 403 | free_irq(client->irq, client); |
| 403 | 404 | ||
| 404 | out_free: | 405 | out_free: |
| 405 | i2c_set_clientdata(client, NULL); | ||
| 406 | kfree(ds1374); | 406 | kfree(ds1374); |
| 407 | return ret; | 407 | return ret; |
| 408 | } | 408 | } |
| @@ -421,7 +421,6 @@ static int __devexit ds1374_remove(struct i2c_client *client) | |||
| 421 | } | 421 | } |
| 422 | 422 | ||
| 423 | rtc_device_unregister(ds1374->rtc); | 423 | rtc_device_unregister(ds1374->rtc); |
| 424 | i2c_set_clientdata(client, NULL); | ||
| 425 | kfree(ds1374); | 424 | kfree(ds1374); |
| 426 | return 0; | 425 | return 0; |
| 427 | } | 426 | } |
diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c index cdb705057091..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 |
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 4166b84cb514..37268e97de49 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c | |||
| @@ -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> |
| @@ -422,8 +423,9 @@ static const struct rtc_class_ops ds1511_rtc_ops = { | |||
| 422 | }; | 423 | }; |
| 423 | 424 | ||
| 424 | static ssize_t | 425 | static ssize_t |
| 425 | ds1511_nvram_read(struct kobject *kobj, struct bin_attribute *ba, | 426 | ds1511_nvram_read(struct file *filp, struct kobject *kobj, |
| 426 | char *buf, loff_t pos, size_t size) | 427 | struct bin_attribute *ba, |
| 428 | char *buf, loff_t pos, size_t size) | ||
| 427 | { | 429 | { |
| 428 | ssize_t count; | 430 | ssize_t count; |
| 429 | 431 | ||
| @@ -451,8 +453,9 @@ ds1511_nvram_read(struct kobject *kobj, struct bin_attribute *ba, | |||
| 451 | } | 453 | } |
| 452 | 454 | ||
| 453 | static ssize_t | 455 | static ssize_t |
| 454 | ds1511_nvram_write(struct kobject *kobj, struct bin_attribute *bin_attr, | 456 | ds1511_nvram_write(struct file *filp, struct kobject *kobj, |
| 455 | char *buf, loff_t pos, size_t size) | 457 | struct bin_attribute *bin_attr, |
| 458 | char *buf, loff_t pos, size_t size) | ||
| 456 | { | 459 | { |
| 457 | ssize_t count; | 460 | ssize_t count; |
| 458 | 461 | ||
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index ed1ef7c9cc06..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> |
| @@ -251,7 +252,7 @@ static const struct rtc_class_ops ds1553_rtc_ops = { | |||
| 251 | .update_irq_enable = ds1553_rtc_update_irq_enable, | 252 | .update_irq_enable = ds1553_rtc_update_irq_enable, |
| 252 | }; | 253 | }; |
| 253 | 254 | ||
| 254 | static ssize_t ds1553_nvram_read(struct kobject *kobj, | 255 | static ssize_t ds1553_nvram_read(struct file *filp, struct kobject *kobj, |
| 255 | struct bin_attribute *bin_attr, | 256 | struct bin_attribute *bin_attr, |
| 256 | char *buf, loff_t pos, size_t size) | 257 | char *buf, loff_t pos, size_t size) |
| 257 | { | 258 | { |
| @@ -266,7 +267,7 @@ static ssize_t ds1553_nvram_read(struct kobject *kobj, | |||
| 266 | return count; | 267 | return count; |
| 267 | } | 268 | } |
| 268 | 269 | ||
| 269 | static ssize_t ds1553_nvram_write(struct kobject *kobj, | 270 | static ssize_t ds1553_nvram_write(struct file *filp, struct kobject *kobj, |
| 270 | struct bin_attribute *bin_attr, | 271 | struct bin_attribute *bin_attr, |
| 271 | char *buf, loff_t pos, size_t size) | 272 | char *buf, loff_t pos, size_t size) |
| 272 | { | 273 | { |
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index a1273360a44e..042630c90dd3 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
| @@ -15,6 +15,7 @@ | |||
| 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> |
| @@ -127,7 +128,7 @@ static const struct rtc_class_ops ds1742_rtc_ops = { | |||
| 127 | .set_time = ds1742_rtc_set_time, | 128 | .set_time = ds1742_rtc_set_time, |
| 128 | }; | 129 | }; |
| 129 | 130 | ||
| 130 | static ssize_t ds1742_nvram_read(struct kobject *kobj, | 131 | static ssize_t ds1742_nvram_read(struct file *filp, struct kobject *kobj, |
| 131 | struct bin_attribute *bin_attr, | 132 | struct bin_attribute *bin_attr, |
| 132 | char *buf, loff_t pos, size_t size) | 133 | char *buf, loff_t pos, size_t size) |
| 133 | { | 134 | { |
| @@ -142,7 +143,7 @@ static ssize_t ds1742_nvram_read(struct kobject *kobj, | |||
| 142 | return count; | 143 | return count; |
| 143 | } | 144 | } |
| 144 | 145 | ||
| 145 | static ssize_t ds1742_nvram_write(struct kobject *kobj, | 146 | static ssize_t ds1742_nvram_write(struct file *filp, struct kobject *kobj, |
| 146 | struct bin_attribute *bin_attr, | 147 | struct bin_attribute *bin_attr, |
| 147 | char *buf, loff_t pos, size_t size) | 148 | char *buf, loff_t pos, size_t size) |
| 148 | { | 149 | { |
| @@ -184,6 +185,7 @@ static int __devinit ds1742_rtc_probe(struct platform_device *pdev) | |||
| 184 | pdata->size_nvram = pdata->size - RTC_SIZE; | 185 | pdata->size_nvram = pdata->size - RTC_SIZE; |
| 185 | pdata->ioaddr_rtc = ioaddr + pdata->size_nvram; | 186 | pdata->ioaddr_rtc = ioaddr + pdata->size_nvram; |
| 186 | 187 | ||
| 188 | sysfs_bin_attr_init(&pdata->nvram_attr); | ||
| 187 | pdata->nvram_attr.attr.name = "nvram"; | 189 | pdata->nvram_attr.attr.name = "nvram"; |
| 188 | pdata->nvram_attr.attr.mode = S_IRUGO | S_IWUSR; | 190 | pdata->nvram_attr.attr.mode = S_IRUGO | S_IWUSR; |
| 189 | pdata->nvram_attr.read = ds1742_nvram_read; | 191 | pdata->nvram_attr.read = ds1742_nvram_read; |
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c index 9da02d108b73..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,27 +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 | err = -ENXIO; | 142 | return -ENXIO; |
| 133 | goto fail_free; | ||
| 134 | } | ||
| 135 | 143 | ||
| 136 | res = request_mem_region(res->start, resource_size(res), pdev->name); | 144 | if (!devm_request_mem_region(&pdev->dev, res->start, |
| 137 | if (res == NULL) { | 145 | resource_size(res), pdev->name)) |
| 138 | err = -EBUSY; | 146 | return -EBUSY; |
| 139 | goto fail_free; | ||
| 140 | } | ||
| 141 | 147 | ||
| 142 | ep93xx_rtc->mmio_base = ioremap(res->start, resource_size(res)); | 148 | ep93xx_rtc->mmio_base = devm_ioremap(&pdev->dev, res->start, |
| 143 | if (ep93xx_rtc->mmio_base == NULL) { | 149 | resource_size(res)); |
| 144 | err = -ENXIO; | 150 | if (!ep93xx_rtc->mmio_base) |
| 145 | goto fail; | 151 | return -ENXIO; |
| 146 | } | ||
| 147 | 152 | ||
| 148 | pdev->dev.platform_data = ep93xx_rtc; | 153 | pdev->dev.platform_data = ep93xx_rtc; |
| 149 | 154 | ||
| @@ -151,53 +156,34 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev) | |||
| 151 | &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE); | 156 | &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE); |
| 152 | if (IS_ERR(rtc)) { | 157 | if (IS_ERR(rtc)) { |
| 153 | err = PTR_ERR(rtc); | 158 | err = PTR_ERR(rtc); |
| 154 | goto fail; | 159 | goto exit; |
| 155 | } | 160 | } |
| 156 | 161 | ||
| 157 | platform_set_drvdata(pdev, rtc); | 162 | platform_set_drvdata(pdev, rtc); |
| 158 | 163 | ||
| 159 | err = device_create_file(&pdev->dev, &dev_attr_comp_preload); | 164 | err = sysfs_create_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files); |
| 160 | if (err) | 165 | if (err) |
| 161 | goto fail; | 166 | goto fail; |
| 162 | err = device_create_file(&pdev->dev, &dev_attr_comp_delete); | ||
| 163 | if (err) { | ||
| 164 | device_remove_file(&pdev->dev, &dev_attr_comp_preload); | ||
| 165 | goto fail; | ||
| 166 | } | ||
| 167 | 167 | ||
| 168 | return 0; | 168 | return 0; |
| 169 | 169 | ||
| 170 | fail: | 170 | fail: |
| 171 | if (ep93xx_rtc->mmio_base) { | 171 | platform_set_drvdata(pdev, NULL); |
| 172 | iounmap(ep93xx_rtc->mmio_base); | 172 | rtc_device_unregister(rtc); |
| 173 | pdev->dev.platform_data = NULL; | 173 | exit: |
| 174 | } | 174 | pdev->dev.platform_data = NULL; |
| 175 | release_mem_region(res->start, resource_size(res)); | ||
| 176 | fail_free: | ||
| 177 | kfree(ep93xx_rtc); | ||
| 178 | return err; | 175 | return err; |
| 179 | } | 176 | } |
| 180 | 177 | ||
| 181 | static int __exit ep93xx_rtc_remove(struct platform_device *pdev) | 178 | static int __exit ep93xx_rtc_remove(struct platform_device *pdev) |
| 182 | { | 179 | { |
| 183 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 180 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
| 184 | struct ep93xx_rtc *ep93xx_rtc = pdev->dev.platform_data; | ||
| 185 | struct resource *res; | ||
| 186 | |||
| 187 | /* cleanup sysfs */ | ||
| 188 | device_remove_file(&pdev->dev, &dev_attr_comp_delete); | ||
| 189 | device_remove_file(&pdev->dev, &dev_attr_comp_preload); | ||
| 190 | 181 | ||
| 182 | sysfs_remove_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files); | ||
| 183 | platform_set_drvdata(pdev, NULL); | ||
| 191 | rtc_device_unregister(rtc); | 184 | rtc_device_unregister(rtc); |
| 192 | |||
| 193 | iounmap(ep93xx_rtc->mmio_base); | ||
| 194 | pdev->dev.platform_data = NULL; | 185 | pdev->dev.platform_data = NULL; |
| 195 | 186 | ||
| 196 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 197 | release_mem_region(res->start, resource_size(res)); | ||
| 198 | |||
| 199 | platform_set_drvdata(pdev, NULL); | ||
| 200 | |||
| 201 | return 0; | 187 | return 0; |
| 202 | } | 188 | } |
| 203 | 189 | ||
diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index 3a7be11cc6b9..ff6fce61ea41 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) |
| @@ -376,20 +377,22 @@ static int __devinit fm3130_probe(struct i2c_client *client, | |||
| 376 | } | 377 | } |
| 377 | 378 | ||
| 378 | /* Disabling calibration mode */ | 379 | /* Disabling calibration mode */ |
| 379 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) | 380 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) { |
| 380 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, | 381 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, |
| 381 | fm3130->regs[FM3130_RTC_CONTROL] & | 382 | fm3130->regs[FM3130_RTC_CONTROL] & |
| 382 | ~(FM3130_RTC_CONTROL_BIT_CAL)); | 383 | ~(FM3130_RTC_CONTROL_BIT_CAL)); |
| 383 | dev_warn(&client->dev, "Disabling calibration mode!\n"); | 384 | dev_warn(&client->dev, "Disabling calibration mode!\n"); |
| 385 | } | ||
| 384 | 386 | ||
| 385 | /* Disabling read and write modes */ | 387 | /* Disabling read and write modes */ |
| 386 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE || | 388 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE || |
| 387 | fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) | 389 | fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) { |
| 388 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, | 390 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, |
| 389 | fm3130->regs[FM3130_RTC_CONTROL] & | 391 | fm3130->regs[FM3130_RTC_CONTROL] & |
| 390 | ~(FM3130_RTC_CONTROL_BIT_READ | | 392 | ~(FM3130_RTC_CONTROL_BIT_READ | |
| 391 | FM3130_RTC_CONTROL_BIT_WRITE)); | 393 | FM3130_RTC_CONTROL_BIT_WRITE)); |
| 392 | dev_warn(&client->dev, "Disabling READ or WRITE mode!\n"); | 394 | dev_warn(&client->dev, "Disabling READ or WRITE mode!\n"); |
| 395 | } | ||
| 393 | 396 | ||
| 394 | /* oscillator off? turn it on, so clock can tick. */ | 397 | /* oscillator off? turn it on, so clock can tick. */ |
| 395 | if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN) | 398 | if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN) |
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-m41t80.c b/drivers/rtc/rtc-m41t80.c index 60fe266f0f49..6dc4e6241418 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c | |||
| @@ -595,10 +595,6 @@ static void wdt_disable(void) | |||
| 595 | static ssize_t wdt_write(struct file *file, const char __user *buf, | 595 | static ssize_t wdt_write(struct file *file, const char __user *buf, |
| 596 | size_t count, loff_t *ppos) | 596 | size_t count, loff_t *ppos) |
| 597 | { | 597 | { |
| 598 | /* Can't seek (pwrite) on this device | ||
| 599 | if (ppos != &file->f_pos) | ||
| 600 | return -ESPIPE; | ||
| 601 | */ | ||
| 602 | if (count) { | 598 | if (count) { |
| 603 | wdt_ping(); | 599 | wdt_ping(); |
| 604 | return 1; | 600 | return 1; |
| @@ -623,7 +619,7 @@ static ssize_t wdt_read(struct file *file, char __user *buf, | |||
| 623 | * according to their available features. We only actually usefully support | 619 | * according to their available features. We only actually usefully support |
| 624 | * querying capabilities and current status. | 620 | * querying capabilities and current status. |
| 625 | */ | 621 | */ |
| 626 | static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 622 | static int wdt_ioctl(struct file *file, unsigned int cmd, |
| 627 | unsigned long arg) | 623 | unsigned long arg) |
| 628 | { | 624 | { |
| 629 | int new_margin, rv; | 625 | int new_margin, rv; |
| @@ -676,6 +672,18 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 676 | return -ENOTTY; | 672 | return -ENOTTY; |
| 677 | } | 673 | } |
| 678 | 674 | ||
| 675 | static long wdt_unlocked_ioctl(struct file *file, unsigned int cmd, | ||
| 676 | unsigned long arg) | ||
| 677 | { | ||
| 678 | int ret; | ||
| 679 | |||
| 680 | lock_kernel(); | ||
| 681 | ret = wdt_ioctl(file, cmd, arg); | ||
| 682 | unlock_kernel(); | ||
| 683 | |||
| 684 | return ret; | ||
| 685 | } | ||
| 686 | |||
| 679 | /** | 687 | /** |
| 680 | * wdt_open: | 688 | * wdt_open: |
| 681 | * @inode: inode of device | 689 | * @inode: inode of device |
| @@ -695,7 +703,7 @@ static int wdt_open(struct inode *inode, struct file *file) | |||
| 695 | */ | 703 | */ |
| 696 | wdt_is_open = 1; | 704 | wdt_is_open = 1; |
| 697 | unlock_kernel(); | 705 | unlock_kernel(); |
| 698 | return 0; | 706 | return nonseekable_open(inode, file); |
| 699 | } | 707 | } |
| 700 | return -ENODEV; | 708 | return -ENODEV; |
| 701 | } | 709 | } |
| @@ -736,7 +744,7 @@ static int wdt_notify_sys(struct notifier_block *this, unsigned long code, | |||
| 736 | static const struct file_operations wdt_fops = { | 744 | static const struct file_operations wdt_fops = { |
| 737 | .owner = THIS_MODULE, | 745 | .owner = THIS_MODULE, |
| 738 | .read = wdt_read, | 746 | .read = wdt_read, |
| 739 | .ioctl = wdt_ioctl, | 747 | .unlocked_ioctl = wdt_unlocked_ioctl, |
| 740 | .write = wdt_write, | 748 | .write = wdt_write, |
| 741 | .open = wdt_open, | 749 | .open = wdt_open, |
| 742 | .release = wdt_release, | 750 | .release = wdt_release, |
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c index 8cb5b8959e5b..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> |
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index ede43b846859..be8359fdb65a 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) |
| @@ -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 | { |
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-mc13783.c b/drivers/rtc/rtc-mc13783.c index 850f983c039c..675bfb515367 100644 --- a/drivers/rtc/rtc-mc13783.c +++ b/drivers/rtc/rtc-mc13783.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
| 14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | #include <linux/slab.h> | ||
| 16 | #include <linux/rtc.h> | 17 | #include <linux/rtc.h> |
| 17 | 18 | ||
| 18 | #define DRIVER_NAME "mc13783-rtc" | 19 | #define DRIVER_NAME "mc13783-rtc" |
| @@ -28,6 +29,34 @@ struct mc13783_rtc { | |||
| 28 | int valid; | 29 | int valid; |
| 29 | }; | 30 | }; |
| 30 | 31 | ||
| 32 | static int mc13783_rtc_irq_enable_unlocked(struct device *dev, | ||
| 33 | unsigned int enabled, int irq) | ||
| 34 | { | ||
| 35 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
| 36 | int (*func)(struct mc13783 *mc13783, int irq); | ||
| 37 | |||
| 38 | if (!priv->valid) | ||
| 39 | return -ENODATA; | ||
| 40 | |||
| 41 | func = enabled ? mc13783_irq_unmask : mc13783_irq_mask; | ||
| 42 | return func(priv->mc13783, irq); | ||
| 43 | } | ||
| 44 | |||
| 45 | static int mc13783_rtc_irq_enable(struct device *dev, | ||
| 46 | unsigned int enabled, int irq) | ||
| 47 | { | ||
| 48 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
| 49 | int ret; | ||
| 50 | |||
| 51 | mc13783_lock(priv->mc13783); | ||
| 52 | |||
| 53 | ret = mc13783_rtc_irq_enable_unlocked(dev, enabled, irq); | ||
| 54 | |||
| 55 | mc13783_unlock(priv->mc13783); | ||
| 56 | |||
| 57 | return ret; | ||
| 58 | } | ||
| 59 | |||
| 31 | static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm) | 60 | static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm) |
| 32 | { | 61 | { |
| 33 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | 62 | struct mc13783_rtc *priv = dev_get_drvdata(dev); |
| @@ -78,6 +107,7 @@ static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs) | |||
| 78 | { | 107 | { |
| 79 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | 108 | struct mc13783_rtc *priv = dev_get_drvdata(dev); |
| 80 | unsigned int seconds, days; | 109 | unsigned int seconds, days; |
| 110 | unsigned int alarmseconds; | ||
| 81 | int ret; | 111 | int ret; |
| 82 | 112 | ||
| 83 | seconds = secs % 86400; | 113 | seconds = secs % 86400; |
| @@ -86,7 +116,22 @@ static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs) | |||
| 86 | mc13783_lock(priv->mc13783); | 116 | mc13783_lock(priv->mc13783); |
| 87 | 117 | ||
| 88 | /* | 118 | /* |
| 89 | * first write seconds=0 to prevent a day switch between writing days | 119 | * temporarily invalidate alarm to prevent triggering it when the day is |
| 120 | * already updated while the time isn't yet. | ||
| 121 | */ | ||
| 122 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTODA, &alarmseconds); | ||
| 123 | if (unlikely(ret)) | ||
| 124 | goto out; | ||
| 125 | |||
| 126 | if (alarmseconds < 86400) { | ||
| 127 | ret = mc13783_reg_write(priv->mc13783, | ||
| 128 | MC13783_RTCTODA, 0x1ffff); | ||
| 129 | if (unlikely(ret)) | ||
| 130 | goto out; | ||
| 131 | } | ||
| 132 | |||
| 133 | /* | ||
| 134 | * write seconds=0 to prevent a day switch between writing days | ||
| 90 | * and seconds below | 135 | * and seconds below |
| 91 | */ | 136 | */ |
| 92 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, 0); | 137 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, 0); |
| @@ -101,11 +146,19 @@ static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs) | |||
| 101 | if (unlikely(ret)) | 146 | if (unlikely(ret)) |
| 102 | goto out; | 147 | goto out; |
| 103 | 148 | ||
| 104 | ret = mc13783_ackirq(priv->mc13783, MC13783_IRQ_RTCRST); | 149 | /* restore alarm */ |
| 150 | if (alarmseconds < 86400) { | ||
| 151 | ret = mc13783_reg_write(priv->mc13783, | ||
| 152 | MC13783_RTCTODA, alarmseconds); | ||
| 153 | if (unlikely(ret)) | ||
| 154 | goto out; | ||
| 155 | } | ||
| 156 | |||
| 157 | ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_RTCRST); | ||
| 105 | if (unlikely(ret)) | 158 | if (unlikely(ret)) |
| 106 | goto out; | 159 | goto out; |
| 107 | 160 | ||
| 108 | ret = mc13783_unmask(priv->mc13783, MC13783_IRQ_RTCRST); | 161 | ret = mc13783_irq_unmask(priv->mc13783, MC13783_IRQ_RTCRST); |
| 109 | out: | 162 | out: |
| 110 | priv->valid = !ret; | 163 | priv->valid = !ret; |
| 111 | 164 | ||
| @@ -114,41 +167,139 @@ out: | |||
| 114 | return ret; | 167 | return ret; |
| 115 | } | 168 | } |
| 116 | 169 | ||
| 117 | static irqreturn_t mc13783_rtc_update_handler(int irq, void *dev) | 170 | static int mc13783_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
| 118 | { | 171 | { |
| 119 | struct mc13783_rtc *priv = dev; | 172 | struct mc13783_rtc *priv = dev_get_drvdata(dev); |
| 120 | struct mc13783 *mc13783 = priv->mc13783; | 173 | unsigned seconds, days; |
| 174 | unsigned long s1970; | ||
| 175 | int enabled, pending; | ||
| 176 | int ret; | ||
| 121 | 177 | ||
| 122 | dev_dbg(&priv->rtc->dev, "1HZ\n"); | 178 | mc13783_lock(priv->mc13783); |
| 123 | 179 | ||
| 124 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF); | 180 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTODA, &seconds); |
| 181 | if (unlikely(ret)) | ||
| 182 | goto out; | ||
| 183 | if (seconds >= 86400) { | ||
| 184 | ret = -ENODATA; | ||
| 185 | goto out; | ||
| 186 | } | ||
| 187 | |||
| 188 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days); | ||
| 189 | if (unlikely(ret)) | ||
| 190 | goto out; | ||
| 125 | 191 | ||
| 126 | mc13783_ackirq(mc13783, irq); | 192 | ret = mc13783_irq_status(priv->mc13783, MC13783_IRQ_TODA, |
| 193 | &enabled, &pending); | ||
| 127 | 194 | ||
| 128 | return IRQ_HANDLED; | 195 | out: |
| 196 | mc13783_unlock(priv->mc13783); | ||
| 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; | ||
| 129 | } | 210 | } |
| 130 | 211 | ||
| 131 | static int mc13783_rtc_update_irq_enable(struct device *dev, | 212 | static int mc13783_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
| 132 | unsigned int enabled) | ||
| 133 | { | 213 | { |
| 134 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | 214 | struct mc13783_rtc *priv = dev_get_drvdata(dev); |
| 135 | int ret = -ENODATA; | 215 | unsigned long s1970; |
| 216 | unsigned seconds, days; | ||
| 217 | int ret; | ||
| 136 | 218 | ||
| 137 | mc13783_lock(priv->mc13783); | 219 | mc13783_lock(priv->mc13783); |
| 138 | if (!priv->valid) | 220 | |
| 221 | /* disable alarm to prevent false triggering */ | ||
| 222 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, 0x1ffff); | ||
| 223 | if (unlikely(ret)) | ||
| 139 | goto out; | 224 | goto out; |
| 140 | 225 | ||
| 141 | ret = (enabled ? mc13783_unmask : mc13783_mask)(priv->mc13783, | 226 | ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TODA); |
| 142 | MC13783_IRQ_1HZ); | 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 = mc13783_rtc_irq_enable_unlocked(dev, alarm->enabled, | ||
| 238 | MC13783_IRQ_TODA); | ||
| 239 | if (unlikely(ret)) | ||
| 240 | goto out; | ||
| 241 | |||
| 242 | seconds = s1970 % 86400; | ||
| 243 | days = s1970 / 86400; | ||
| 244 | |||
| 245 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCDAYA, days); | ||
| 246 | if (unlikely(ret)) | ||
| 247 | goto out; | ||
| 248 | |||
| 249 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, seconds); | ||
| 250 | |||
| 143 | out: | 251 | out: |
| 144 | mc13783_unlock(priv->mc13783); | 252 | mc13783_unlock(priv->mc13783); |
| 145 | 253 | ||
| 146 | return ret; | 254 | return ret; |
| 147 | } | 255 | } |
| 148 | 256 | ||
| 257 | static irqreturn_t mc13783_rtc_alarm_handler(int irq, void *dev) | ||
| 258 | { | ||
| 259 | struct mc13783_rtc *priv = dev; | ||
| 260 | struct mc13783 *mc13783 = priv->mc13783; | ||
| 261 | |||
| 262 | dev_dbg(&priv->rtc->dev, "Alarm\n"); | ||
| 263 | |||
| 264 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF); | ||
| 265 | |||
| 266 | mc13783_irq_ack(mc13783, irq); | ||
| 267 | |||
| 268 | return IRQ_HANDLED; | ||
| 269 | } | ||
| 270 | |||
| 271 | static irqreturn_t mc13783_rtc_update_handler(int irq, void *dev) | ||
| 272 | { | ||
| 273 | struct mc13783_rtc *priv = dev; | ||
| 274 | struct mc13783 *mc13783 = priv->mc13783; | ||
| 275 | |||
| 276 | dev_dbg(&priv->rtc->dev, "1HZ\n"); | ||
| 277 | |||
| 278 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF); | ||
| 279 | |||
| 280 | mc13783_irq_ack(mc13783, irq); | ||
| 281 | |||
| 282 | return IRQ_HANDLED; | ||
| 283 | } | ||
| 284 | |||
| 285 | static int mc13783_rtc_update_irq_enable(struct device *dev, | ||
| 286 | unsigned int enabled) | ||
| 287 | { | ||
| 288 | return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_1HZ); | ||
| 289 | } | ||
| 290 | |||
| 291 | static int mc13783_rtc_alarm_irq_enable(struct device *dev, | ||
| 292 | unsigned int enabled) | ||
| 293 | { | ||
| 294 | return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_TODA); | ||
| 295 | } | ||
| 296 | |||
| 149 | static const struct rtc_class_ops mc13783_rtc_ops = { | 297 | static const struct rtc_class_ops mc13783_rtc_ops = { |
| 150 | .read_time = mc13783_rtc_read_time, | 298 | .read_time = mc13783_rtc_read_time, |
| 151 | .set_mmss = mc13783_rtc_set_mmss, | 299 | .set_mmss = mc13783_rtc_set_mmss, |
| 300 | .read_alarm = mc13783_rtc_read_alarm, | ||
| 301 | .set_alarm = mc13783_rtc_set_alarm, | ||
| 302 | .alarm_irq_enable = mc13783_rtc_alarm_irq_enable, | ||
| 152 | .update_irq_enable = mc13783_rtc_update_irq_enable, | 303 | .update_irq_enable = mc13783_rtc_update_irq_enable, |
| 153 | }; | 304 | }; |
| 154 | 305 | ||
| @@ -160,7 +311,7 @@ static irqreturn_t mc13783_rtc_reset_handler(int irq, void *dev) | |||
| 160 | dev_dbg(&priv->rtc->dev, "RTCRST\n"); | 311 | dev_dbg(&priv->rtc->dev, "RTCRST\n"); |
| 161 | priv->valid = 0; | 312 | priv->valid = 0; |
| 162 | 313 | ||
| 163 | mc13783_mask(mc13783, irq); | 314 | mc13783_irq_mask(mc13783, irq); |
| 164 | 315 | ||
| 165 | return IRQ_HANDLED; | 316 | return IRQ_HANDLED; |
| 166 | } | 317 | } |
| @@ -169,50 +320,64 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev) | |||
| 169 | { | 320 | { |
| 170 | int ret; | 321 | int ret; |
| 171 | struct mc13783_rtc *priv; | 322 | struct mc13783_rtc *priv; |
| 323 | struct mc13783 *mc13783; | ||
| 324 | int rtcrst_pending; | ||
| 172 | 325 | ||
| 173 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 326 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
| 174 | if (!priv) | 327 | if (!priv) |
| 175 | return -ENOMEM; | 328 | return -ENOMEM; |
| 176 | 329 | ||
| 177 | priv->mc13783 = dev_get_drvdata(pdev->dev.parent); | 330 | mc13783 = dev_get_drvdata(pdev->dev.parent); |
| 178 | platform_set_drvdata(pdev, priv); | 331 | priv->mc13783 = mc13783; |
| 179 | 332 | ||
| 180 | priv->valid = 1; | 333 | platform_set_drvdata(pdev, priv); |
| 181 | 334 | ||
| 182 | mc13783_lock(priv->mc13783); | 335 | mc13783_lock(mc13783); |
| 183 | 336 | ||
| 184 | ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_RTCRST, | 337 | ret = mc13783_irq_request(mc13783, MC13783_IRQ_RTCRST, |
| 185 | mc13783_rtc_reset_handler, DRIVER_NAME, priv); | 338 | mc13783_rtc_reset_handler, DRIVER_NAME, priv); |
| 186 | if (ret) | 339 | if (ret) |
| 187 | goto err_reset_irq_request; | 340 | goto err_reset_irq_request; |
| 188 | 341 | ||
| 189 | ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_1HZ, | 342 | ret = mc13783_irq_status(mc13783, MC13783_IRQ_RTCRST, |
| 343 | NULL, &rtcrst_pending); | ||
| 344 | if (ret) | ||
| 345 | goto err_reset_irq_status; | ||
| 346 | |||
| 347 | priv->valid = !rtcrst_pending; | ||
| 348 | |||
| 349 | ret = mc13783_irq_request_nounmask(mc13783, MC13783_IRQ_1HZ, | ||
| 190 | mc13783_rtc_update_handler, DRIVER_NAME, priv); | 350 | mc13783_rtc_update_handler, DRIVER_NAME, priv); |
| 191 | if (ret) | 351 | if (ret) |
| 192 | goto err_update_irq_request; | 352 | goto err_update_irq_request; |
| 193 | 353 | ||
| 194 | mc13783_unlock(priv->mc13783); | 354 | ret = mc13783_irq_request_nounmask(mc13783, MC13783_IRQ_TODA, |
| 355 | mc13783_rtc_alarm_handler, DRIVER_NAME, priv); | ||
| 356 | if (ret) | ||
| 357 | goto err_alarm_irq_request; | ||
| 195 | 358 | ||
| 196 | priv->rtc = rtc_device_register(pdev->name, | 359 | priv->rtc = rtc_device_register(pdev->name, |
| 197 | &pdev->dev, &mc13783_rtc_ops, THIS_MODULE); | 360 | &pdev->dev, &mc13783_rtc_ops, THIS_MODULE); |
| 198 | |||
| 199 | if (IS_ERR(priv->rtc)) { | 361 | if (IS_ERR(priv->rtc)) { |
| 200 | ret = PTR_ERR(priv->rtc); | 362 | ret = PTR_ERR(priv->rtc); |
| 201 | 363 | ||
| 202 | mc13783_lock(priv->mc13783); | 364 | mc13783_irq_free(mc13783, MC13783_IRQ_TODA, priv); |
| 365 | err_alarm_irq_request: | ||
| 203 | 366 | ||
| 204 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); | 367 | mc13783_irq_free(mc13783, MC13783_IRQ_1HZ, priv); |
| 205 | err_update_irq_request: | 368 | err_update_irq_request: |
| 206 | 369 | ||
| 207 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); | 370 | err_reset_irq_status: |
| 208 | err_reset_irq_request: | ||
| 209 | 371 | ||
| 210 | mc13783_unlock(priv->mc13783); | 372 | mc13783_irq_free(mc13783, MC13783_IRQ_RTCRST, priv); |
| 373 | err_reset_irq_request: | ||
| 211 | 374 | ||
| 212 | platform_set_drvdata(pdev, NULL); | 375 | platform_set_drvdata(pdev, NULL); |
| 213 | kfree(priv); | 376 | kfree(priv); |
| 214 | } | 377 | } |
| 215 | 378 | ||
| 379 | mc13783_unlock(mc13783); | ||
| 380 | |||
| 216 | return ret; | 381 | return ret; |
| 217 | } | 382 | } |
| 218 | 383 | ||
| @@ -220,10 +385,11 @@ static int __devexit mc13783_rtc_remove(struct platform_device *pdev) | |||
| 220 | { | 385 | { |
| 221 | struct mc13783_rtc *priv = platform_get_drvdata(pdev); | 386 | struct mc13783_rtc *priv = platform_get_drvdata(pdev); |
| 222 | 387 | ||
| 223 | rtc_device_unregister(priv->rtc); | ||
| 224 | |||
| 225 | mc13783_lock(priv->mc13783); | 388 | mc13783_lock(priv->mc13783); |
| 226 | 389 | ||
| 390 | rtc_device_unregister(priv->rtc); | ||
| 391 | |||
| 392 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_TODA, priv); | ||
| 227 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); | 393 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); |
| 228 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); | 394 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); |
| 229 | 395 | ||
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c new file mode 100644 index 000000000000..db5d8c416d26 --- /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 of_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 of_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-msm6242.c b/drivers/rtc/rtc-msm6242.c index 5f5968a48925..b2fff0ca49f8 100644 --- a/drivers/rtc/rtc-msm6242.c +++ b/drivers/rtc/rtc-msm6242.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
| 15 | #include <linux/rtc.h> | 15 | #include <linux/rtc.h> |
| 16 | #include <linux/slab.h> | ||
| 16 | 17 | ||
| 17 | 18 | ||
| 18 | enum { | 19 | enum { |
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index dc052ce6e63a..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 |
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index 6bd5072d4eb7..25ec921db07c 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/io.h> | 12 | #include <linux/io.h> |
| 13 | #include <linux/rtc.h> | 13 | #include <linux/rtc.h> |
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/slab.h> | ||
| 15 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
| 16 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
| 17 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
| @@ -378,29 +379,37 @@ static struct rtc_class_ops mxc_rtc_ops = { | |||
| 378 | 379 | ||
| 379 | static int __init mxc_rtc_probe(struct platform_device *pdev) | 380 | static int __init mxc_rtc_probe(struct platform_device *pdev) |
| 380 | { | 381 | { |
| 381 | struct clk *clk; | ||
| 382 | struct resource *res; | 382 | struct resource *res; |
| 383 | struct rtc_device *rtc; | 383 | struct rtc_device *rtc; |
| 384 | struct rtc_plat_data *pdata = NULL; | 384 | struct rtc_plat_data *pdata = NULL; |
| 385 | u32 reg; | 385 | u32 reg; |
| 386 | int ret, rate; | 386 | unsigned long rate; |
| 387 | int ret; | ||
| 387 | 388 | ||
| 388 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 389 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 389 | if (!res) | 390 | if (!res) |
| 390 | return -ENODEV; | 391 | return -ENODEV; |
| 391 | 392 | ||
| 392 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 393 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
| 393 | if (!pdata) | 394 | if (!pdata) |
| 394 | return -ENOMEM; | 395 | return -ENOMEM; |
| 395 | 396 | ||
| 396 | pdata->ioaddr = ioremap(res->start, resource_size(res)); | 397 | if (!devm_request_mem_region(&pdev->dev, res->start, |
| 398 | resource_size(res), pdev->name)) | ||
| 399 | return -EBUSY; | ||
| 397 | 400 | ||
| 398 | clk = clk_get(&pdev->dev, "ckil"); | 401 | pdata->ioaddr = devm_ioremap(&pdev->dev, res->start, |
| 399 | if (IS_ERR(clk)) | 402 | resource_size(res)); |
| 400 | return PTR_ERR(clk); | ||
| 401 | 403 | ||
| 402 | rate = clk_get_rate(clk); | 404 | pdata->clk = clk_get(&pdev->dev, "rtc"); |
| 403 | clk_put(clk); | 405 | if (IS_ERR(pdata->clk)) { |
| 406 | dev_err(&pdev->dev, "unable to get clock!\n"); | ||
| 407 | ret = PTR_ERR(pdata->clk); | ||
| 408 | goto exit_free_pdata; | ||
| 409 | } | ||
| 410 | |||
| 411 | clk_enable(pdata->clk); | ||
| 412 | rate = clk_get_rate(pdata->clk); | ||
| 404 | 413 | ||
| 405 | if (rate == 32768) | 414 | if (rate == 32768) |
| 406 | reg = RTC_INPUT_CLK_32768HZ; | 415 | reg = RTC_INPUT_CLK_32768HZ; |
| @@ -409,10 +418,9 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
| 409 | else if (rate == 38400) | 418 | else if (rate == 38400) |
| 410 | reg = RTC_INPUT_CLK_38400HZ; | 419 | reg = RTC_INPUT_CLK_38400HZ; |
| 411 | else { | 420 | else { |
| 412 | dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", | 421 | dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", rate); |
| 413 | clk_get_rate(clk)); | ||
| 414 | ret = -EINVAL; | 422 | ret = -EINVAL; |
| 415 | goto exit_free_pdata; | 423 | goto exit_put_clk; |
| 416 | } | 424 | } |
| 417 | 425 | ||
| 418 | reg |= RTC_ENABLE_BIT; | 426 | reg |= RTC_ENABLE_BIT; |
| @@ -420,18 +428,9 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
| 420 | if (((readw(pdata->ioaddr + RTC_RTCCTL)) & RTC_ENABLE_BIT) == 0) { | 428 | if (((readw(pdata->ioaddr + RTC_RTCCTL)) & RTC_ENABLE_BIT) == 0) { |
| 421 | dev_err(&pdev->dev, "hardware module can't be enabled!\n"); | 429 | dev_err(&pdev->dev, "hardware module can't be enabled!\n"); |
| 422 | ret = -EIO; | 430 | ret = -EIO; |
| 423 | goto exit_free_pdata; | 431 | goto exit_put_clk; |
| 424 | } | ||
| 425 | |||
| 426 | pdata->clk = clk_get(&pdev->dev, "rtc"); | ||
| 427 | if (IS_ERR(pdata->clk)) { | ||
| 428 | dev_err(&pdev->dev, "unable to get clock!\n"); | ||
| 429 | ret = PTR_ERR(pdata->clk); | ||
| 430 | goto exit_free_pdata; | ||
| 431 | } | 432 | } |
| 432 | 433 | ||
| 433 | clk_enable(pdata->clk); | ||
| 434 | |||
| 435 | rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops, | 434 | rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops, |
| 436 | THIS_MODULE); | 435 | THIS_MODULE); |
| 437 | if (IS_ERR(rtc)) { | 436 | if (IS_ERR(rtc)) { |
| @@ -446,8 +445,8 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
| 446 | pdata->irq = platform_get_irq(pdev, 0); | 445 | pdata->irq = platform_get_irq(pdev, 0); |
| 447 | 446 | ||
| 448 | if (pdata->irq >= 0 && | 447 | if (pdata->irq >= 0 && |
| 449 | request_irq(pdata->irq, mxc_rtc_interrupt, IRQF_SHARED, | 448 | devm_request_irq(&pdev->dev, pdata->irq, mxc_rtc_interrupt, |
| 450 | pdev->name, pdev) < 0) { | 449 | IRQF_SHARED, pdev->name, pdev) < 0) { |
| 451 | dev_warn(&pdev->dev, "interrupt not available.\n"); | 450 | dev_warn(&pdev->dev, "interrupt not available.\n"); |
| 452 | pdata->irq = -1; | 451 | pdata->irq = -1; |
| 453 | } | 452 | } |
| @@ -455,10 +454,10 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
| 455 | return 0; | 454 | return 0; |
| 456 | 455 | ||
| 457 | exit_put_clk: | 456 | exit_put_clk: |
| 457 | clk_disable(pdata->clk); | ||
| 458 | clk_put(pdata->clk); | 458 | clk_put(pdata->clk); |
| 459 | 459 | ||
| 460 | exit_free_pdata: | 460 | exit_free_pdata: |
| 461 | kfree(pdata); | ||
| 462 | 461 | ||
| 463 | return ret; | 462 | return ret; |
| 464 | } | 463 | } |
| @@ -469,12 +468,8 @@ static int __exit mxc_rtc_remove(struct platform_device *pdev) | |||
| 469 | 468 | ||
| 470 | rtc_device_unregister(pdata->rtc); | 469 | rtc_device_unregister(pdata->rtc); |
| 471 | 470 | ||
| 472 | if (pdata->irq >= 0) | ||
| 473 | free_irq(pdata->irq, pdev); | ||
| 474 | |||
| 475 | clk_disable(pdata->clk); | 471 | clk_disable(pdata->clk); |
| 476 | clk_put(pdata->clk); | 472 | clk_put(pdata->clk); |
| 477 | kfree(pdata); | ||
| 478 | platform_set_drvdata(pdev, NULL); | 473 | platform_set_drvdata(pdev, NULL); |
| 479 | 474 | ||
| 480 | return 0; | 475 | return 0; |
diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c index bf59c9c586b2..a351bd5d8176 100644 --- a/drivers/rtc/rtc-nuc900.c +++ b/drivers/rtc/rtc-nuc900.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
| 15 | #include <linux/slab.h> | ||
| 15 | #include <linux/rtc.h> | 16 | #include <linux/rtc.h> |
| 16 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
| 17 | #include <linux/io.h> | 18 | #include <linux/io.h> |
diff --git a/drivers/rtc/rtc-pcap.c b/drivers/rtc/rtc-pcap.c index a99c28992d21..25c0b3fd44f1 100644 --- a/drivers/rtc/rtc-pcap.c +++ b/drivers/rtc/rtc-pcap.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 18 | #include <linux/mfd/ezx-pcap.h> | 18 | #include <linux/mfd/ezx-pcap.h> |
| 19 | #include <linux/rtc.h> | 19 | #include <linux/rtc.h> |
| 20 | #include <linux/slab.h> | ||
| 20 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
| 21 | 22 | ||
| 22 | struct pcap_rtc { | 23 | struct pcap_rtc { |
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index e75df9d50e27..71bab0ef5443 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include <linux/init.h> | 39 | #include <linux/init.h> |
| 40 | #include <linux/kernel.h> | 40 | #include <linux/kernel.h> |
| 41 | #include <linux/string.h> | 41 | #include <linux/string.h> |
| 42 | #include <linux/slab.h> | ||
| 42 | #include <linux/rtc.h> | 43 | #include <linux/rtc.h> |
| 43 | #include <linux/spi/spi.h> | 44 | #include <linux/spi/spi.h> |
| 44 | 45 | ||
| @@ -315,7 +316,7 @@ kfree_exit: | |||
| 315 | return ret; | 316 | return ret; |
| 316 | } | 317 | } |
| 317 | 318 | ||
| 318 | static int pcf2123_remove(struct spi_device *spi) | 319 | static int __devexit pcf2123_remove(struct spi_device *spi) |
| 319 | { | 320 | { |
| 320 | struct pcf2123_plat_data *pdata = spi->dev.platform_data; | 321 | struct pcf2123_plat_data *pdata = spi->dev.platform_data; |
| 321 | int i; | 322 | int i; |
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c index 854c3cb365a1..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> |
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 65f346b2fbae..1af42b4a6f59 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 | ||
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 0264b117893b..3587d9922f28 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,10 @@ | |||
| 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/version.h> | ||
| 27 | #include <linux/slab.h> | ||
| 21 | 28 | ||
| 22 | /* | 29 | /* |
| 23 | * Register definitions | 30 | * Register definitions |
| @@ -30,35 +37,207 @@ | |||
| 30 | #define RTC_RIS 0x14 /* Raw interrupt status register */ | 37 | #define RTC_RIS 0x14 /* Raw interrupt status register */ |
| 31 | #define RTC_MIS 0x18 /* Masked interrupt status register */ | 38 | #define RTC_MIS 0x18 /* Masked interrupt status register */ |
| 32 | #define RTC_ICR 0x1c /* Interrupt clear register */ | 39 | #define RTC_ICR 0x1c /* Interrupt clear register */ |
| 40 | /* ST variants have additional timer functionality */ | ||
| 41 | #define RTC_TDR 0x20 /* Timer data read register */ | ||
| 42 | #define RTC_TLR 0x24 /* Timer data load register */ | ||
| 43 | #define RTC_TCR 0x28 /* Timer control register */ | ||
| 44 | #define RTC_YDR 0x30 /* Year data read register */ | ||
| 45 | #define RTC_YMR 0x34 /* Year match register */ | ||
| 46 | #define RTC_YLR 0x38 /* Year data load register */ | ||
| 47 | |||
| 48 | #define RTC_CR_CWEN (1 << 26) /* Clockwatch enable bit */ | ||
| 49 | |||
| 50 | #define RTC_TCR_EN (1 << 1) /* Periodic timer enable bit */ | ||
| 51 | |||
| 52 | /* Common bit definitions for Interrupt status and control registers */ | ||
| 53 | #define RTC_BIT_AI (1 << 0) /* Alarm interrupt bit */ | ||
| 54 | #define RTC_BIT_PI (1 << 1) /* Periodic interrupt bit. ST variants only. */ | ||
| 55 | |||
| 56 | /* Common bit definations for ST v2 for reading/writing time */ | ||
| 57 | #define RTC_SEC_SHIFT 0 | ||
| 58 | #define RTC_SEC_MASK (0x3F << RTC_SEC_SHIFT) /* Second [0-59] */ | ||
| 59 | #define RTC_MIN_SHIFT 6 | ||
| 60 | #define RTC_MIN_MASK (0x3F << RTC_MIN_SHIFT) /* Minute [0-59] */ | ||
| 61 | #define RTC_HOUR_SHIFT 12 | ||
| 62 | #define RTC_HOUR_MASK (0x1F << RTC_HOUR_SHIFT) /* Hour [0-23] */ | ||
| 63 | #define RTC_WDAY_SHIFT 17 | ||
| 64 | #define RTC_WDAY_MASK (0x7 << RTC_WDAY_SHIFT) /* Day of Week [1-7] 1=Sunday */ | ||
| 65 | #define RTC_MDAY_SHIFT 20 | ||
| 66 | #define RTC_MDAY_MASK (0x1F << RTC_MDAY_SHIFT) /* Day of Month [1-31] */ | ||
| 67 | #define RTC_MON_SHIFT 25 | ||
| 68 | #define RTC_MON_MASK (0xF << RTC_MON_SHIFT) /* Month [1-12] 1=January */ | ||
| 69 | |||
| 70 | #define RTC_TIMER_FREQ 32768 | ||
| 33 | 71 | ||
| 34 | struct pl031_local { | 72 | struct pl031_local { |
| 35 | struct rtc_device *rtc; | 73 | struct rtc_device *rtc; |
| 36 | void __iomem *base; | 74 | void __iomem *base; |
| 75 | u8 hw_designer; | ||
| 76 | u8 hw_revision:4; | ||
| 37 | }; | 77 | }; |
| 38 | 78 | ||
| 39 | static irqreturn_t pl031_interrupt(int irq, void *dev_id) | 79 | static int pl031_alarm_irq_enable(struct device *dev, |
| 80 | unsigned int enabled) | ||
| 81 | { | ||
| 82 | struct pl031_local *ldata = dev_get_drvdata(dev); | ||
| 83 | unsigned long imsc; | ||
| 84 | |||
| 85 | /* Clear any pending alarm interrupts. */ | ||
| 86 | writel(RTC_BIT_AI, ldata->base + RTC_ICR); | ||
| 87 | |||
| 88 | imsc = readl(ldata->base + RTC_IMSC); | ||
| 89 | |||
| 90 | if (enabled == 1) | ||
| 91 | writel(imsc | RTC_BIT_AI, ldata->base + RTC_IMSC); | ||
| 92 | else | ||
| 93 | writel(imsc & ~RTC_BIT_AI, ldata->base + RTC_IMSC); | ||
| 94 | |||
| 95 | return 0; | ||
| 96 | } | ||
| 97 | |||
| 98 | /* | ||
| 99 | * Convert Gregorian date to ST v2 RTC format. | ||
| 100 | */ | ||
| 101 | static int pl031_stv2_tm_to_time(struct device *dev, | ||
| 102 | struct rtc_time *tm, unsigned long *st_time, | ||
| 103 | unsigned long *bcd_year) | ||
| 104 | { | ||
| 105 | int year = tm->tm_year + 1900; | ||
| 106 | int wday = tm->tm_wday; | ||
| 107 | |||
| 108 | /* wday masking is not working in hardware so wday must be valid */ | ||
| 109 | if (wday < -1 || wday > 6) { | ||
| 110 | dev_err(dev, "invalid wday value %d\n", tm->tm_wday); | ||
| 111 | return -EINVAL; | ||
| 112 | } else if (wday == -1) { | ||
| 113 | /* wday is not provided, calculate it here */ | ||
| 114 | unsigned long time; | ||
| 115 | struct rtc_time calc_tm; | ||
| 116 | |||
| 117 | rtc_tm_to_time(tm, &time); | ||
| 118 | rtc_time_to_tm(time, &calc_tm); | ||
| 119 | wday = calc_tm.tm_wday; | ||
| 120 | } | ||
| 121 | |||
| 122 | *bcd_year = (bin2bcd(year % 100) | bin2bcd(year / 100) << 8); | ||
| 123 | |||
| 124 | *st_time = ((tm->tm_mon + 1) << RTC_MON_SHIFT) | ||
| 125 | | (tm->tm_mday << RTC_MDAY_SHIFT) | ||
| 126 | | ((wday + 1) << RTC_WDAY_SHIFT) | ||
| 127 | | (tm->tm_hour << RTC_HOUR_SHIFT) | ||
| 128 | | (tm->tm_min << RTC_MIN_SHIFT) | ||
| 129 | | (tm->tm_sec << RTC_SEC_SHIFT); | ||
| 130 | |||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | /* | ||
| 135 | * Convert ST v2 RTC format to Gregorian date. | ||
| 136 | */ | ||
| 137 | static int pl031_stv2_time_to_tm(unsigned long st_time, unsigned long bcd_year, | ||
| 138 | struct rtc_time *tm) | ||
| 139 | { | ||
| 140 | tm->tm_year = bcd2bin(bcd_year) + (bcd2bin(bcd_year >> 8) * 100); | ||
| 141 | tm->tm_mon = ((st_time & RTC_MON_MASK) >> RTC_MON_SHIFT) - 1; | ||
| 142 | tm->tm_mday = ((st_time & RTC_MDAY_MASK) >> RTC_MDAY_SHIFT); | ||
| 143 | tm->tm_wday = ((st_time & RTC_WDAY_MASK) >> RTC_WDAY_SHIFT) - 1; | ||
| 144 | tm->tm_hour = ((st_time & RTC_HOUR_MASK) >> RTC_HOUR_SHIFT); | ||
| 145 | tm->tm_min = ((st_time & RTC_MIN_MASK) >> RTC_MIN_SHIFT); | ||
| 146 | tm->tm_sec = ((st_time & RTC_SEC_MASK) >> RTC_SEC_SHIFT); | ||
| 147 | |||
| 148 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); | ||
| 149 | tm->tm_year -= 1900; | ||
| 150 | |||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | static int pl031_stv2_read_time(struct device *dev, struct rtc_time *tm) | ||
| 155 | { | ||
| 156 | struct pl031_local *ldata = dev_get_drvdata(dev); | ||
| 157 | |||
| 158 | pl031_stv2_time_to_tm(readl(ldata->base + RTC_DR), | ||
| 159 | readl(ldata->base + RTC_YDR), tm); | ||
| 160 | |||
| 161 | return 0; | ||
| 162 | } | ||
| 163 | |||
| 164 | static int pl031_stv2_set_time(struct device *dev, struct rtc_time *tm) | ||
| 165 | { | ||
| 166 | unsigned long time; | ||
| 167 | unsigned long bcd_year; | ||
| 168 | struct pl031_local *ldata = dev_get_drvdata(dev); | ||
| 169 | int ret; | ||
| 170 | |||
| 171 | ret = pl031_stv2_tm_to_time(dev, tm, &time, &bcd_year); | ||
| 172 | if (ret == 0) { | ||
| 173 | writel(bcd_year, ldata->base + RTC_YLR); | ||
| 174 | writel(time, ldata->base + RTC_LR); | ||
| 175 | } | ||
| 176 | |||
| 177 | return ret; | ||
| 178 | } | ||
| 179 | |||
| 180 | static int pl031_stv2_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
| 40 | { | 181 | { |
| 41 | struct rtc_device *rtc = dev_id; | 182 | struct pl031_local *ldata = dev_get_drvdata(dev); |
| 183 | int ret; | ||
| 42 | 184 | ||
| 43 | rtc_update_irq(rtc, 1, RTC_AF); | 185 | ret = pl031_stv2_time_to_tm(readl(ldata->base + RTC_MR), |
| 186 | readl(ldata->base + RTC_YMR), &alarm->time); | ||
| 44 | 187 | ||
| 45 | return IRQ_HANDLED; | 188 | alarm->pending = readl(ldata->base + RTC_RIS) & RTC_BIT_AI; |
| 189 | alarm->enabled = readl(ldata->base + RTC_IMSC) & RTC_BIT_AI; | ||
| 190 | |||
| 191 | return ret; | ||
| 46 | } | 192 | } |
| 47 | 193 | ||
| 48 | static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 194 | static int pl031_stv2_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
| 49 | { | 195 | { |
| 50 | struct pl031_local *ldata = dev_get_drvdata(dev); | 196 | struct pl031_local *ldata = dev_get_drvdata(dev); |
| 197 | unsigned long time; | ||
| 198 | unsigned long bcd_year; | ||
| 199 | int ret; | ||
| 200 | |||
| 201 | /* At the moment, we can only deal with non-wildcarded alarm times. */ | ||
| 202 | ret = rtc_valid_tm(&alarm->time); | ||
| 203 | if (ret == 0) { | ||
| 204 | ret = pl031_stv2_tm_to_time(dev, &alarm->time, | ||
| 205 | &time, &bcd_year); | ||
| 206 | if (ret == 0) { | ||
| 207 | writel(bcd_year, ldata->base + RTC_YMR); | ||
| 208 | writel(time, ldata->base + RTC_MR); | ||
| 209 | |||
| 210 | pl031_alarm_irq_enable(dev, alarm->enabled); | ||
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 214 | return ret; | ||
| 215 | } | ||
| 216 | |||
| 217 | static irqreturn_t pl031_interrupt(int irq, void *dev_id) | ||
| 218 | { | ||
| 219 | struct pl031_local *ldata = dev_id; | ||
| 220 | unsigned long rtcmis; | ||
| 221 | unsigned long events = 0; | ||
| 222 | |||
| 223 | rtcmis = readl(ldata->base + RTC_MIS); | ||
| 224 | if (rtcmis) { | ||
| 225 | writel(rtcmis, ldata->base + RTC_ICR); | ||
| 226 | |||
| 227 | if (rtcmis & RTC_BIT_AI) | ||
| 228 | events |= (RTC_AF | RTC_IRQF); | ||
| 229 | |||
| 230 | /* Timer interrupt is only available in ST variants */ | ||
| 231 | if ((rtcmis & RTC_BIT_PI) && | ||
| 232 | (ldata->hw_designer == AMBA_VENDOR_ST)) | ||
| 233 | events |= (RTC_PF | RTC_IRQF); | ||
| 234 | |||
| 235 | rtc_update_irq(ldata->rtc, 1, events); | ||
| 51 | 236 | ||
| 52 | switch (cmd) { | 237 | return IRQ_HANDLED; |
| 53 | case RTC_AIE_OFF: | ||
| 54 | writel(1, ldata->base + RTC_MIS); | ||
| 55 | return 0; | ||
| 56 | case RTC_AIE_ON: | ||
| 57 | writel(0, ldata->base + RTC_MIS); | ||
| 58 | return 0; | ||
| 59 | } | 238 | } |
| 60 | 239 | ||
| 61 | return -ENOIOCTLCMD; | 240 | return IRQ_NONE; |
| 62 | } | 241 | } |
| 63 | 242 | ||
| 64 | static int pl031_read_time(struct device *dev, struct rtc_time *tm) | 243 | static int pl031_read_time(struct device *dev, struct rtc_time *tm) |
| @@ -74,11 +253,14 @@ static int pl031_set_time(struct device *dev, struct rtc_time *tm) | |||
| 74 | { | 253 | { |
| 75 | unsigned long time; | 254 | unsigned long time; |
| 76 | struct pl031_local *ldata = dev_get_drvdata(dev); | 255 | struct pl031_local *ldata = dev_get_drvdata(dev); |
| 256 | int ret; | ||
| 77 | 257 | ||
| 78 | rtc_tm_to_time(tm, &time); | 258 | ret = rtc_tm_to_time(tm, &time); |
| 79 | writel(time, ldata->base + RTC_LR); | ||
| 80 | 259 | ||
| 81 | return 0; | 260 | if (ret == 0) |
| 261 | writel(time, ldata->base + RTC_LR); | ||
| 262 | |||
| 263 | return ret; | ||
| 82 | } | 264 | } |
| 83 | 265 | ||
| 84 | static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 266 | static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
| @@ -86,8 +268,9 @@ static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
| 86 | struct pl031_local *ldata = dev_get_drvdata(dev); | 268 | struct pl031_local *ldata = dev_get_drvdata(dev); |
| 87 | 269 | ||
| 88 | rtc_time_to_tm(readl(ldata->base + RTC_MR), &alarm->time); | 270 | rtc_time_to_tm(readl(ldata->base + RTC_MR), &alarm->time); |
| 89 | alarm->pending = readl(ldata->base + RTC_RIS); | 271 | |
| 90 | alarm->enabled = readl(ldata->base + RTC_IMSC); | 272 | alarm->pending = readl(ldata->base + RTC_RIS) & RTC_BIT_AI; |
| 273 | alarm->enabled = readl(ldata->base + RTC_IMSC) & RTC_BIT_AI; | ||
| 91 | 274 | ||
| 92 | return 0; | 275 | return 0; |
| 93 | } | 276 | } |
| @@ -96,22 +279,71 @@ static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
| 96 | { | 279 | { |
| 97 | struct pl031_local *ldata = dev_get_drvdata(dev); | 280 | struct pl031_local *ldata = dev_get_drvdata(dev); |
| 98 | unsigned long time; | 281 | unsigned long time; |
| 282 | int ret; | ||
| 283 | |||
| 284 | /* At the moment, we can only deal with non-wildcarded alarm times. */ | ||
| 285 | ret = rtc_valid_tm(&alarm->time); | ||
| 286 | if (ret == 0) { | ||
| 287 | ret = rtc_tm_to_time(&alarm->time, &time); | ||
| 288 | if (ret == 0) { | ||
| 289 | writel(time, ldata->base + RTC_MR); | ||
| 290 | pl031_alarm_irq_enable(dev, alarm->enabled); | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | return ret; | ||
| 295 | } | ||
| 296 | |||
| 297 | /* Periodic interrupt is only available in ST variants. */ | ||
| 298 | static int pl031_irq_set_state(struct device *dev, int enabled) | ||
| 299 | { | ||
| 300 | struct pl031_local *ldata = dev_get_drvdata(dev); | ||
| 301 | |||
| 302 | if (enabled == 1) { | ||
| 303 | /* Clear any pending timer interrupt. */ | ||
| 304 | writel(RTC_BIT_PI, ldata->base + RTC_ICR); | ||
| 305 | |||
| 306 | writel(readl(ldata->base + RTC_IMSC) | RTC_BIT_PI, | ||
| 307 | ldata->base + RTC_IMSC); | ||
| 99 | 308 | ||
| 100 | rtc_tm_to_time(&alarm->time, &time); | 309 | /* Now start the timer */ |
| 310 | writel(readl(ldata->base + RTC_TCR) | RTC_TCR_EN, | ||
| 311 | ldata->base + RTC_TCR); | ||
| 101 | 312 | ||
| 102 | writel(time, ldata->base + RTC_MR); | 313 | } else { |
| 103 | writel(!alarm->enabled, ldata->base + RTC_MIS); | 314 | writel(readl(ldata->base + RTC_IMSC) & (~RTC_BIT_PI), |
| 315 | ldata->base + RTC_IMSC); | ||
| 316 | |||
| 317 | /* Also stop the timer */ | ||
| 318 | writel(readl(ldata->base + RTC_TCR) & (~RTC_TCR_EN), | ||
| 319 | ldata->base + RTC_TCR); | ||
| 320 | } | ||
| 321 | /* Wait at least 1 RTC32 clock cycle to ensure next access | ||
| 322 | * to RTC_TCR will succeed. | ||
| 323 | */ | ||
| 324 | udelay(40); | ||
| 104 | 325 | ||
| 105 | return 0; | 326 | return 0; |
| 106 | } | 327 | } |
| 107 | 328 | ||
| 108 | static const struct rtc_class_ops pl031_ops = { | 329 | static int pl031_irq_set_freq(struct device *dev, int freq) |
| 109 | .ioctl = pl031_ioctl, | 330 | { |
| 110 | .read_time = pl031_read_time, | 331 | struct pl031_local *ldata = dev_get_drvdata(dev); |
| 111 | .set_time = pl031_set_time, | 332 | |
| 112 | .read_alarm = pl031_read_alarm, | 333 | /* Cant set timer if it is already enabled */ |
| 113 | .set_alarm = pl031_set_alarm, | 334 | if (readl(ldata->base + RTC_TCR) & RTC_TCR_EN) { |
| 114 | }; | 335 | dev_err(dev, "can't change frequency while timer enabled\n"); |
| 336 | return -EINVAL; | ||
| 337 | } | ||
| 338 | |||
| 339 | /* If self start bit in RTC_TCR is set timer will start here, | ||
| 340 | * but we never set that bit. Instead we start the timer when | ||
| 341 | * set_state is called with enabled == 1. | ||
| 342 | */ | ||
| 343 | writel(RTC_TIMER_FREQ / freq, ldata->base + RTC_TLR); | ||
| 344 | |||
| 345 | return 0; | ||
| 346 | } | ||
| 115 | 347 | ||
| 116 | static int pl031_remove(struct amba_device *adev) | 348 | static int pl031_remove(struct amba_device *adev) |
| 117 | { | 349 | { |
| @@ -131,18 +363,20 @@ static int pl031_probe(struct amba_device *adev, struct amba_id *id) | |||
| 131 | { | 363 | { |
| 132 | int ret; | 364 | int ret; |
| 133 | struct pl031_local *ldata; | 365 | struct pl031_local *ldata; |
| 366 | struct rtc_class_ops *ops = id->data; | ||
| 134 | 367 | ||
| 135 | ret = amba_request_regions(adev, NULL); | 368 | ret = amba_request_regions(adev, NULL); |
| 136 | if (ret) | 369 | if (ret) |
| 137 | goto err_req; | 370 | goto err_req; |
| 138 | 371 | ||
| 139 | ldata = kmalloc(sizeof(struct pl031_local), GFP_KERNEL); | 372 | ldata = kzalloc(sizeof(struct pl031_local), GFP_KERNEL); |
| 140 | if (!ldata) { | 373 | if (!ldata) { |
| 141 | ret = -ENOMEM; | 374 | ret = -ENOMEM; |
| 142 | goto out; | 375 | goto out; |
| 143 | } | 376 | } |
| 144 | 377 | ||
| 145 | ldata->base = ioremap(adev->res.start, resource_size(&adev->res)); | 378 | ldata->base = ioremap(adev->res.start, resource_size(&adev->res)); |
| 379 | |||
| 146 | if (!ldata->base) { | 380 | if (!ldata->base) { |
| 147 | ret = -ENOMEM; | 381 | ret = -ENOMEM; |
| 148 | goto out_no_remap; | 382 | goto out_no_remap; |
| @@ -150,24 +384,36 @@ static int pl031_probe(struct amba_device *adev, struct amba_id *id) | |||
| 150 | 384 | ||
| 151 | amba_set_drvdata(adev, ldata); | 385 | amba_set_drvdata(adev, ldata); |
| 152 | 386 | ||
| 153 | if (request_irq(adev->irq[0], pl031_interrupt, IRQF_DISABLED, | 387 | ldata->hw_designer = amba_manf(adev); |
| 154 | "rtc-pl031", ldata->rtc)) { | 388 | ldata->hw_revision = amba_rev(adev); |
| 155 | ret = -EIO; | 389 | |
| 156 | goto out_no_irq; | 390 | dev_dbg(&adev->dev, "designer ID = 0x%02x\n", ldata->hw_designer); |
| 157 | } | 391 | dev_dbg(&adev->dev, "revision = 0x%01x\n", ldata->hw_revision); |
| 158 | 392 | ||
| 159 | ldata->rtc = rtc_device_register("pl031", &adev->dev, &pl031_ops, | 393 | /* Enable the clockwatch on ST Variants */ |
| 160 | THIS_MODULE); | 394 | if ((ldata->hw_designer == AMBA_VENDOR_ST) && |
| 395 | (ldata->hw_revision > 1)) | ||
| 396 | writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN, | ||
| 397 | ldata->base + RTC_CR); | ||
| 398 | |||
| 399 | ldata->rtc = rtc_device_register("pl031", &adev->dev, ops, | ||
| 400 | THIS_MODULE); | ||
| 161 | if (IS_ERR(ldata->rtc)) { | 401 | if (IS_ERR(ldata->rtc)) { |
| 162 | ret = PTR_ERR(ldata->rtc); | 402 | ret = PTR_ERR(ldata->rtc); |
| 163 | goto out_no_rtc; | 403 | goto out_no_rtc; |
| 164 | } | 404 | } |
| 165 | 405 | ||
| 406 | if (request_irq(adev->irq[0], pl031_interrupt, | ||
| 407 | IRQF_DISABLED | IRQF_SHARED, "rtc-pl031", ldata)) { | ||
| 408 | ret = -EIO; | ||
| 409 | goto out_no_irq; | ||
| 410 | } | ||
| 411 | |||
| 166 | return 0; | 412 | return 0; |
| 167 | 413 | ||
| 168 | out_no_rtc: | ||
| 169 | free_irq(adev->irq[0], ldata->rtc); | ||
| 170 | out_no_irq: | 414 | out_no_irq: |
| 415 | rtc_device_unregister(ldata->rtc); | ||
| 416 | out_no_rtc: | ||
| 171 | iounmap(ldata->base); | 417 | iounmap(ldata->base); |
| 172 | amba_set_drvdata(adev, NULL); | 418 | amba_set_drvdata(adev, NULL); |
| 173 | out_no_remap: | 419 | out_no_remap: |
| @@ -175,13 +421,57 @@ out_no_remap: | |||
| 175 | out: | 421 | out: |
| 176 | amba_release_regions(adev); | 422 | amba_release_regions(adev); |
| 177 | err_req: | 423 | err_req: |
| 424 | |||
| 178 | return ret; | 425 | return ret; |
| 179 | } | 426 | } |
| 180 | 427 | ||
| 428 | /* Operations for the original ARM version */ | ||
| 429 | static struct rtc_class_ops arm_pl031_ops = { | ||
| 430 | .read_time = pl031_read_time, | ||
| 431 | .set_time = pl031_set_time, | ||
| 432 | .read_alarm = pl031_read_alarm, | ||
| 433 | .set_alarm = pl031_set_alarm, | ||
| 434 | .alarm_irq_enable = pl031_alarm_irq_enable, | ||
| 435 | }; | ||
| 436 | |||
| 437 | /* The First ST derivative */ | ||
| 438 | static struct rtc_class_ops stv1_pl031_ops = { | ||
| 439 | .read_time = pl031_read_time, | ||
| 440 | .set_time = pl031_set_time, | ||
| 441 | .read_alarm = pl031_read_alarm, | ||
| 442 | .set_alarm = pl031_set_alarm, | ||
| 443 | .alarm_irq_enable = pl031_alarm_irq_enable, | ||
| 444 | .irq_set_state = pl031_irq_set_state, | ||
| 445 | .irq_set_freq = pl031_irq_set_freq, | ||
| 446 | }; | ||
| 447 | |||
| 448 | /* And the second ST derivative */ | ||
| 449 | static struct rtc_class_ops stv2_pl031_ops = { | ||
| 450 | .read_time = pl031_stv2_read_time, | ||
| 451 | .set_time = pl031_stv2_set_time, | ||
| 452 | .read_alarm = pl031_stv2_read_alarm, | ||
| 453 | .set_alarm = pl031_stv2_set_alarm, | ||
| 454 | .alarm_irq_enable = pl031_alarm_irq_enable, | ||
| 455 | .irq_set_state = pl031_irq_set_state, | ||
| 456 | .irq_set_freq = pl031_irq_set_freq, | ||
| 457 | }; | ||
| 458 | |||
| 181 | static struct amba_id pl031_ids[] __initdata = { | 459 | static struct amba_id pl031_ids[] __initdata = { |
| 182 | { | 460 | { |
| 183 | .id = 0x00041031, | 461 | .id = 0x00041031, |
| 184 | .mask = 0x000fffff, | 462 | .mask = 0x000fffff, |
| 463 | .data = &arm_pl031_ops, | ||
| 464 | }, | ||
| 465 | /* ST Micro variants */ | ||
| 466 | { | ||
| 467 | .id = 0x00180031, | ||
| 468 | .mask = 0x00ffffff, | ||
| 469 | .data = &stv1_pl031_ops, | ||
| 470 | }, | ||
| 471 | { | ||
| 472 | .id = 0x00280031, | ||
| 473 | .mask = 0x00ffffff, | ||
| 474 | .data = &stv2_pl031_ops, | ||
| 185 | }, | 475 | }, |
| 186 | {0, 0}, | 476 | {0, 0}, |
| 187 | }; | 477 | }; |
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index e6351b743da6..e9c6fa035989 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 | ||
diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c index e1313feb060f..a95f733bb15a 100644 --- a/drivers/rtc/rtc-rp5c01.c +++ b/drivers/rtc/rtc-rp5c01.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
| 14 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
| 15 | #include <linux/slab.h> | ||
| 15 | 16 | ||
| 16 | 17 | ||
| 17 | enum { | 18 | enum { |
diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index 2099037cb3ea..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> |
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 2f2c68d476da..90cf0a6ff23e 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 | ||
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index b1a29bcfdf13..789f62f9b47d 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> |
| @@ -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: |
| @@ -655,7 +655,6 @@ static int __devexit rx8025_remove(struct i2c_client *client) | |||
| 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..70b68d35f969 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/bcd.h> | 21 | #include <linux/bcd.h> |
| 22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
| 23 | #include <linux/log2.h> | 23 | #include <linux/log2.h> |
| 24 | #include <linux/slab.h> | ||
| 24 | 25 | ||
| 25 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
| 26 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
| @@ -28,6 +29,11 @@ | |||
| 28 | #include <asm/irq.h> | 29 | #include <asm/irq.h> |
| 29 | #include <plat/regs-rtc.h> | 30 | #include <plat/regs-rtc.h> |
| 30 | 31 | ||
| 32 | enum s3c_cpu_type { | ||
| 33 | TYPE_S3C2410, | ||
| 34 | TYPE_S3C64XX, | ||
| 35 | }; | ||
| 36 | |||
| 31 | /* I have yet to find an S3C implementation with more than one | 37 | /* I have yet to find an S3C implementation with more than one |
| 32 | * of these rtc blocks in */ | 38 | * of these rtc blocks in */ |
| 33 | 39 | ||
| @@ -36,6 +42,7 @@ static struct resource *s3c_rtc_mem; | |||
| 36 | static void __iomem *s3c_rtc_base; | 42 | static void __iomem *s3c_rtc_base; |
| 37 | static int s3c_rtc_alarmno = NO_IRQ; | 43 | static int s3c_rtc_alarmno = NO_IRQ; |
| 38 | static int s3c_rtc_tickno = NO_IRQ; | 44 | static int s3c_rtc_tickno = NO_IRQ; |
| 45 | static enum s3c_cpu_type s3c_rtc_cpu_type; | ||
| 39 | 46 | ||
| 40 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); | 47 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); |
| 41 | 48 | ||
| @@ -79,12 +86,25 @@ static int s3c_rtc_setpie(struct device *dev, int enabled) | |||
| 79 | pr_debug("%s: pie=%d\n", __func__, enabled); | 86 | pr_debug("%s: pie=%d\n", __func__, enabled); |
| 80 | 87 | ||
| 81 | spin_lock_irq(&s3c_rtc_pie_lock); | 88 | spin_lock_irq(&s3c_rtc_pie_lock); |
| 82 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE; | ||
| 83 | 89 | ||
| 84 | if (enabled) | 90 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
| 85 | tmp |= S3C2410_TICNT_ENABLE; | 91 | tmp = readb(s3c_rtc_base + S3C2410_RTCCON); |
| 92 | tmp &= ~S3C64XX_RTCCON_TICEN; | ||
| 93 | |||
| 94 | if (enabled) | ||
| 95 | tmp |= S3C64XX_RTCCON_TICEN; | ||
| 96 | |||
| 97 | writeb(tmp, s3c_rtc_base + S3C2410_RTCCON); | ||
| 98 | } else { | ||
| 99 | tmp = readb(s3c_rtc_base + S3C2410_TICNT); | ||
| 100 | tmp &= ~S3C2410_TICNT_ENABLE; | ||
| 101 | |||
| 102 | if (enabled) | ||
| 103 | tmp |= S3C2410_TICNT_ENABLE; | ||
| 104 | |||
| 105 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | ||
| 106 | } | ||
| 86 | 107 | ||
| 87 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | ||
| 88 | spin_unlock_irq(&s3c_rtc_pie_lock); | 108 | spin_unlock_irq(&s3c_rtc_pie_lock); |
| 89 | 109 | ||
| 90 | return 0; | 110 | return 0; |
| @@ -92,15 +112,21 @@ static int s3c_rtc_setpie(struct device *dev, int enabled) | |||
| 92 | 112 | ||
| 93 | static int s3c_rtc_setfreq(struct device *dev, int freq) | 113 | static int s3c_rtc_setfreq(struct device *dev, int freq) |
| 94 | { | 114 | { |
| 95 | unsigned int tmp; | 115 | struct platform_device *pdev = to_platform_device(dev); |
| 116 | struct rtc_device *rtc_dev = platform_get_drvdata(pdev); | ||
| 117 | unsigned int tmp = 0; | ||
| 96 | 118 | ||
| 97 | if (!is_power_of_2(freq)) | 119 | if (!is_power_of_2(freq)) |
| 98 | return -EINVAL; | 120 | return -EINVAL; |
| 99 | 121 | ||
| 100 | spin_lock_irq(&s3c_rtc_pie_lock); | 122 | spin_lock_irq(&s3c_rtc_pie_lock); |
| 101 | 123 | ||
| 102 | tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE; | 124 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { |
| 103 | tmp |= (128 / freq)-1; | 125 | tmp = readb(s3c_rtc_base + S3C2410_TICNT); |
| 126 | tmp &= S3C2410_TICNT_ENABLE; | ||
| 127 | } | ||
| 128 | |||
| 129 | tmp |= (rtc_dev->max_user_freq / freq)-1; | ||
| 104 | 130 | ||
| 105 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | 131 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); |
| 106 | spin_unlock_irq(&s3c_rtc_pie_lock); | 132 | spin_unlock_irq(&s3c_rtc_pie_lock); |
| @@ -282,10 +308,17 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 282 | 308 | ||
| 283 | static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) | 309 | static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) |
| 284 | { | 310 | { |
| 285 | unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT); | 311 | unsigned int ticnt; |
| 312 | |||
| 313 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | ||
| 314 | ticnt = readb(s3c_rtc_base + S3C2410_RTCCON); | ||
| 315 | ticnt &= S3C64XX_RTCCON_TICEN; | ||
| 316 | } else { | ||
| 317 | ticnt = readb(s3c_rtc_base + S3C2410_TICNT); | ||
| 318 | ticnt &= S3C2410_TICNT_ENABLE; | ||
| 319 | } | ||
| 286 | 320 | ||
| 287 | seq_printf(seq, "periodic_IRQ\t: %s\n", | 321 | seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); |
| 288 | (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" ); | ||
| 289 | return 0; | 322 | return 0; |
| 290 | } | 323 | } |
| 291 | 324 | ||
| @@ -352,10 +385,16 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
| 352 | 385 | ||
| 353 | if (!en) { | 386 | if (!en) { |
| 354 | tmp = readb(base + S3C2410_RTCCON); | 387 | tmp = readb(base + S3C2410_RTCCON); |
| 355 | writeb(tmp & ~S3C2410_RTCCON_RTCEN, base + S3C2410_RTCCON); | 388 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
| 356 | 389 | tmp &= ~S3C64XX_RTCCON_TICEN; | |
| 357 | tmp = readb(base + S3C2410_TICNT); | 390 | tmp &= ~S3C2410_RTCCON_RTCEN; |
| 358 | writeb(tmp & ~S3C2410_TICNT_ENABLE, base + S3C2410_TICNT); | 391 | writeb(tmp, base + S3C2410_RTCCON); |
| 392 | |||
| 393 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { | ||
| 394 | tmp = readb(base + S3C2410_TICNT); | ||
| 395 | tmp &= ~S3C2410_TICNT_ENABLE; | ||
| 396 | writeb(tmp, base + S3C2410_TICNT); | ||
| 397 | } | ||
| 359 | } else { | 398 | } else { |
| 360 | /* re-enable the device, and check it is ok */ | 399 | /* re-enable the device, and check it is ok */ |
| 361 | 400 | ||
| @@ -456,8 +495,6 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
| 456 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", | 495 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", |
| 457 | readb(s3c_rtc_base + S3C2410_RTCCON)); | 496 | readb(s3c_rtc_base + S3C2410_RTCCON)); |
| 458 | 497 | ||
| 459 | s3c_rtc_setfreq(&pdev->dev, 1); | ||
| 460 | |||
| 461 | device_init_wakeup(&pdev->dev, 1); | 498 | device_init_wakeup(&pdev->dev, 1); |
| 462 | 499 | ||
| 463 | /* register RTC and exit */ | 500 | /* register RTC and exit */ |
| @@ -471,9 +508,17 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
| 471 | goto err_nortc; | 508 | goto err_nortc; |
| 472 | } | 509 | } |
| 473 | 510 | ||
| 474 | rtc->max_user_freq = 128; | 511 | s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data; |
| 512 | |||
| 513 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | ||
| 514 | rtc->max_user_freq = 32768; | ||
| 515 | else | ||
| 516 | rtc->max_user_freq = 128; | ||
| 475 | 517 | ||
| 476 | platform_set_drvdata(pdev, rtc); | 518 | platform_set_drvdata(pdev, rtc); |
| 519 | |||
| 520 | s3c_rtc_setfreq(&pdev->dev, 1); | ||
| 521 | |||
| 477 | return 0; | 522 | return 0; |
| 478 | 523 | ||
| 479 | err_nortc: | 524 | err_nortc: |
| @@ -491,20 +536,30 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
| 491 | 536 | ||
| 492 | /* RTC Power management control */ | 537 | /* RTC Power management control */ |
| 493 | 538 | ||
| 494 | static int ticnt_save; | 539 | static int ticnt_save, ticnt_en_save; |
| 495 | 540 | ||
| 496 | static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 541 | static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
| 497 | { | 542 | { |
| 498 | /* save TICNT for anyone using periodic interrupts */ | 543 | /* save TICNT for anyone using periodic interrupts */ |
| 499 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); | 544 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); |
| 545 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | ||
| 546 | ticnt_en_save = readb(s3c_rtc_base + S3C2410_RTCCON); | ||
| 547 | ticnt_en_save &= S3C64XX_RTCCON_TICEN; | ||
| 548 | } | ||
| 500 | s3c_rtc_enable(pdev, 0); | 549 | s3c_rtc_enable(pdev, 0); |
| 501 | return 0; | 550 | return 0; |
| 502 | } | 551 | } |
| 503 | 552 | ||
| 504 | static int s3c_rtc_resume(struct platform_device *pdev) | 553 | static int s3c_rtc_resume(struct platform_device *pdev) |
| 505 | { | 554 | { |
| 555 | unsigned int tmp; | ||
| 556 | |||
| 506 | s3c_rtc_enable(pdev, 1); | 557 | s3c_rtc_enable(pdev, 1); |
| 507 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); | 558 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); |
| 559 | if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { | ||
| 560 | tmp = readb(s3c_rtc_base + S3C2410_RTCCON); | ||
| 561 | writeb(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); | ||
| 562 | } | ||
| 508 | return 0; | 563 | return 0; |
| 509 | } | 564 | } |
| 510 | #else | 565 | #else |
| @@ -512,13 +567,27 @@ static int s3c_rtc_resume(struct platform_device *pdev) | |||
| 512 | #define s3c_rtc_resume NULL | 567 | #define s3c_rtc_resume NULL |
| 513 | #endif | 568 | #endif |
| 514 | 569 | ||
| 515 | static struct platform_driver s3c2410_rtc_driver = { | 570 | static struct platform_device_id s3c_rtc_driver_ids[] = { |
| 571 | { | ||
| 572 | .name = "s3c2410-rtc", | ||
| 573 | .driver_data = TYPE_S3C2410, | ||
| 574 | }, { | ||
| 575 | .name = "s3c64xx-rtc", | ||
| 576 | .driver_data = TYPE_S3C64XX, | ||
| 577 | }, | ||
| 578 | { } | ||
| 579 | }; | ||
| 580 | |||
| 581 | MODULE_DEVICE_TABLE(platform, s3c_rtc_driver_ids); | ||
| 582 | |||
| 583 | static struct platform_driver s3c_rtc_driver = { | ||
| 516 | .probe = s3c_rtc_probe, | 584 | .probe = s3c_rtc_probe, |
| 517 | .remove = __devexit_p(s3c_rtc_remove), | 585 | .remove = __devexit_p(s3c_rtc_remove), |
| 518 | .suspend = s3c_rtc_suspend, | 586 | .suspend = s3c_rtc_suspend, |
| 519 | .resume = s3c_rtc_resume, | 587 | .resume = s3c_rtc_resume, |
| 588 | .id_table = s3c_rtc_driver_ids, | ||
| 520 | .driver = { | 589 | .driver = { |
| 521 | .name = "s3c2410-rtc", | 590 | .name = "s3c-rtc", |
| 522 | .owner = THIS_MODULE, | 591 | .owner = THIS_MODULE, |
| 523 | }, | 592 | }, |
| 524 | }; | 593 | }; |
| @@ -528,12 +597,12 @@ static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics | |||
| 528 | static int __init s3c_rtc_init(void) | 597 | static int __init s3c_rtc_init(void) |
| 529 | { | 598 | { |
| 530 | printk(banner); | 599 | printk(banner); |
| 531 | return platform_driver_register(&s3c2410_rtc_driver); | 600 | return platform_driver_register(&s3c_rtc_driver); |
| 532 | } | 601 | } |
| 533 | 602 | ||
| 534 | static void __exit s3c_rtc_exit(void) | 603 | static void __exit s3c_rtc_exit(void) |
| 535 | { | 604 | { |
| 536 | platform_driver_unregister(&s3c2410_rtc_driver); | 605 | platform_driver_unregister(&s3c_rtc_driver); |
| 537 | } | 606 | } |
| 538 | 607 | ||
| 539 | module_init(s3c_rtc_init); | 608 | module_init(s3c_rtc_init); |
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index e95cc6f8d61e..5efbd5990ff8 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c | |||
| @@ -26,6 +26,7 @@ | |||
| 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" |
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index 67700831b5c9..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> |
| @@ -243,7 +244,7 @@ static const struct rtc_class_ops stk17ta8_rtc_ops = { | |||
| 243 | .alarm_irq_enable = stk17ta8_rtc_alarm_irq_enable, | 244 | .alarm_irq_enable = stk17ta8_rtc_alarm_irq_enable, |
| 244 | }; | 245 | }; |
| 245 | 246 | ||
| 246 | static ssize_t stk17ta8_nvram_read(struct kobject *kobj, | 247 | static ssize_t stk17ta8_nvram_read(struct file *filp, struct kobject *kobj, |
| 247 | struct bin_attribute *attr, char *buf, | 248 | struct bin_attribute *attr, char *buf, |
| 248 | loff_t pos, size_t size) | 249 | loff_t pos, size_t size) |
| 249 | { | 250 | { |
| @@ -258,7 +259,7 @@ static ssize_t stk17ta8_nvram_read(struct kobject *kobj, | |||
| 258 | return count; | 259 | return count; |
| 259 | } | 260 | } |
| 260 | 261 | ||
| 261 | static ssize_t stk17ta8_nvram_write(struct kobject *kobj, | 262 | static ssize_t stk17ta8_nvram_write(struct file *filp, struct kobject *kobj, |
| 262 | struct bin_attribute *attr, char *buf, | 263 | struct bin_attribute *attr, char *buf, |
| 263 | loff_t pos, size_t size) | 264 | loff_t pos, size_t size) |
| 264 | { | 265 | { |
| @@ -381,7 +382,7 @@ static __exit void stk17ta8_exit(void) | |||
| 381 | module_init(stk17ta8_init); | 382 | module_init(stk17ta8_init); |
| 382 | module_exit(stk17ta8_exit); | 383 | module_exit(stk17ta8_exit); |
| 383 | 384 | ||
| 384 | MODULE_AUTHOR("Thomas Hommel <thomas.hommel@gefanuc.com>"); | 385 | MODULE_AUTHOR("Thomas Hommel <thomas.hommel@ge.com>"); |
| 385 | MODULE_DESCRIPTION("Simtek STK17TA8 RTC driver"); | 386 | MODULE_DESCRIPTION("Simtek STK17TA8 RTC driver"); |
| 386 | MODULE_LICENSE("GPL"); | 387 | MODULE_LICENSE("GPL"); |
| 387 | MODULE_VERSION(DRV_VERSION); | 388 | MODULE_VERSION(DRV_VERSION); |
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index d7ce1a5c857d..7e7d0c806f2d 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
| 23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
| 24 | #include <linux/rtc.h> | 24 | #include <linux/rtc.h> |
| 25 | #include <linux/slab.h> | ||
| 25 | 26 | ||
| 26 | #include <mach/platform.h> | 27 | #include <mach/platform.h> |
| 27 | #include <mach/stmp3xxx.h> | 28 | #include <mach/stmp3xxx.h> |
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index 7dd23a6fc825..380083ca572f 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c | |||
| @@ -107,8 +107,9 @@ rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr, | |||
| 107 | char *buf) | 107 | char *buf) |
| 108 | { | 108 | { |
| 109 | #ifdef CONFIG_RTC_HCTOSYS_DEVICE | 109 | #ifdef CONFIG_RTC_HCTOSYS_DEVICE |
| 110 | if (strcmp(dev_name(&to_rtc_device(dev)->dev), | 110 | if (rtc_hctosys_ret == 0 && |
| 111 | CONFIG_RTC_HCTOSYS_DEVICE) == 0) | 111 | strcmp(dev_name(&to_rtc_device(dev)->dev), |
| 112 | CONFIG_RTC_HCTOSYS_DEVICE) == 0) | ||
| 112 | return sprintf(buf, "1\n"); | 113 | return sprintf(buf, "1\n"); |
| 113 | else | 114 | else |
| 114 | #endif | 115 | #endif |
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index c6a83a2a722c..ed1b86828124 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c | |||
| @@ -57,7 +57,7 @@ enum { | |||
| 57 | REG_RTC_COMP_LSB_REG, | 57 | REG_RTC_COMP_LSB_REG, |
| 58 | REG_RTC_COMP_MSB_REG, | 58 | REG_RTC_COMP_MSB_REG, |
| 59 | }; | 59 | }; |
| 60 | const static u8 twl4030_rtc_reg_map[] = { | 60 | static const u8 twl4030_rtc_reg_map[] = { |
| 61 | [REG_SECONDS_REG] = 0x00, | 61 | [REG_SECONDS_REG] = 0x00, |
| 62 | [REG_MINUTES_REG] = 0x01, | 62 | [REG_MINUTES_REG] = 0x01, |
| 63 | [REG_HOURS_REG] = 0x02, | 63 | [REG_HOURS_REG] = 0x02, |
| @@ -80,7 +80,7 @@ const static u8 twl4030_rtc_reg_map[] = { | |||
| 80 | [REG_RTC_COMP_LSB_REG] = 0x10, | 80 | [REG_RTC_COMP_LSB_REG] = 0x10, |
| 81 | [REG_RTC_COMP_MSB_REG] = 0x11, | 81 | [REG_RTC_COMP_MSB_REG] = 0x11, |
| 82 | }; | 82 | }; |
| 83 | const static u8 twl6030_rtc_reg_map[] = { | 83 | static const u8 twl6030_rtc_reg_map[] = { |
| 84 | [REG_SECONDS_REG] = 0x00, | 84 | [REG_SECONDS_REG] = 0x00, |
| 85 | [REG_MINUTES_REG] = 0x01, | 85 | [REG_MINUTES_REG] = 0x01, |
| 86 | [REG_HOURS_REG] = 0x02, | 86 | [REG_HOURS_REG] = 0x02, |
diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index 9ee81d8aa7c0..ec6313d15359 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c | |||
| @@ -12,6 +12,7 @@ | |||
| 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 { |
| @@ -187,7 +188,7 @@ static const struct rtc_class_ops tx4939_rtc_ops = { | |||
| 187 | .alarm_irq_enable = tx4939_rtc_alarm_irq_enable, | 188 | .alarm_irq_enable = tx4939_rtc_alarm_irq_enable, |
| 188 | }; | 189 | }; |
| 189 | 190 | ||
| 190 | static ssize_t tx4939_rtc_nvram_read(struct kobject *kobj, | 191 | static ssize_t tx4939_rtc_nvram_read(struct file *filp, struct kobject *kobj, |
| 191 | struct bin_attribute *bin_attr, | 192 | struct bin_attribute *bin_attr, |
| 192 | char *buf, loff_t pos, size_t size) | 193 | char *buf, loff_t pos, size_t size) |
| 193 | { | 194 | { |
| @@ -206,7 +207,7 @@ static ssize_t tx4939_rtc_nvram_read(struct kobject *kobj, | |||
| 206 | return count; | 207 | return count; |
| 207 | } | 208 | } |
| 208 | 209 | ||
| 209 | static ssize_t tx4939_rtc_nvram_write(struct kobject *kobj, | 210 | static ssize_t tx4939_rtc_nvram_write(struct file *filp, struct kobject *kobj, |
| 210 | struct bin_attribute *bin_attr, | 211 | struct bin_attribute *bin_attr, |
| 211 | char *buf, loff_t pos, size_t size) | 212 | char *buf, loff_t pos, size_t size) |
| 212 | { | 213 | { |
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c index bed4cab07043..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 | ||
diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index 000c7e481e59..82931dc65c0b 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 17 | #include <linux/time.h> | 17 | #include <linux/time.h> |
| 18 | #include <linux/rtc.h> | 18 | #include <linux/rtc.h> |
| 19 | #include <linux/slab.h> | ||
| 19 | #include <linux/bcd.h> | 20 | #include <linux/bcd.h> |
| 20 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
| 21 | #include <linux/ioctl.h> | 22 | #include <linux/ioctl.h> |
| @@ -448,17 +449,17 @@ static int wm831x_rtc_probe(struct platform_device *pdev) | |||
| 448 | goto err; | 449 | goto err; |
| 449 | } | 450 | } |
| 450 | 451 | ||
| 451 | ret = wm831x_request_irq(wm831x, per_irq, wm831x_per_irq, | 452 | ret = request_threaded_irq(per_irq, NULL, wm831x_per_irq, |
| 452 | IRQF_TRIGGER_RISING, "wm831x_rtc_per", | 453 | IRQF_TRIGGER_RISING, "RTC period", |
| 453 | wm831x_rtc); | 454 | wm831x_rtc); |
| 454 | if (ret != 0) { | 455 | if (ret != 0) { |
| 455 | dev_err(&pdev->dev, "Failed to request periodic IRQ %d: %d\n", | 456 | dev_err(&pdev->dev, "Failed to request periodic IRQ %d: %d\n", |
| 456 | per_irq, ret); | 457 | per_irq, ret); |
| 457 | } | 458 | } |
| 458 | 459 | ||
| 459 | ret = wm831x_request_irq(wm831x, alm_irq, wm831x_alm_irq, | 460 | ret = request_threaded_irq(alm_irq, NULL, wm831x_alm_irq, |
| 460 | IRQF_TRIGGER_RISING, "wm831x_rtc_alm", | 461 | IRQF_TRIGGER_RISING, "RTC alarm", |
| 461 | wm831x_rtc); | 462 | wm831x_rtc); |
| 462 | if (ret != 0) { | 463 | if (ret != 0) { |
| 463 | dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", | 464 | dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", |
| 464 | alm_irq, ret); | 465 | alm_irq, ret); |
| @@ -477,8 +478,8 @@ static int __devexit wm831x_rtc_remove(struct platform_device *pdev) | |||
| 477 | int per_irq = platform_get_irq_byname(pdev, "PER"); | 478 | int per_irq = platform_get_irq_byname(pdev, "PER"); |
| 478 | int alm_irq = platform_get_irq_byname(pdev, "ALM"); | 479 | int alm_irq = platform_get_irq_byname(pdev, "ALM"); |
| 479 | 480 | ||
| 480 | wm831x_free_irq(wm831x_rtc->wm831x, alm_irq, wm831x_rtc); | 481 | free_irq(alm_irq, wm831x_rtc); |
| 481 | wm831x_free_irq(wm831x_rtc->wm831x, per_irq, wm831x_rtc); | 482 | free_irq(per_irq, wm831x_rtc); |
| 482 | rtc_device_unregister(wm831x_rtc->rtc); | 483 | rtc_device_unregister(wm831x_rtc->rtc); |
| 483 | kfree(wm831x_rtc); | 484 | kfree(wm831x_rtc); |
| 484 | 485 | ||
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c index f1e440521c54..3d0dc76b38af 100644 --- a/drivers/rtc/rtc-wm8350.c +++ b/drivers/rtc/rtc-wm8350.c | |||
| @@ -307,11 +307,18 @@ 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 | ||
| @@ -478,8 +485,8 @@ static int __devexit wm8350_rtc_remove(struct platform_device *pdev) | |||
| 478 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | 485 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); |
| 479 | struct wm8350_rtc *wm_rtc = &wm8350->rtc; | 486 | struct wm8350_rtc *wm_rtc = &wm8350->rtc; |
| 480 | 487 | ||
| 481 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC); | 488 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC, wm8350); |
| 482 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM); | 489 | wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM, wm8350); |
| 483 | 490 | ||
| 484 | rtc_device_unregister(wm_rtc->rtc); | 491 | rtc_device_unregister(wm_rtc->rtc); |
| 485 | 492 | ||
