diff options
Diffstat (limited to 'drivers/rtc')
33 files changed, 4673 insertions, 244 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index ce2aabf5c55..45f4c804084 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -106,6 +106,24 @@ config RTC_INTF_DEV_UIE_EMUL | |||
106 | clock several times per second, please enable this option | 106 | clock several times per second, please enable this option |
107 | only if you know that you really need it. | 107 | only if you know that you really need it. |
108 | 108 | ||
109 | config RTC_INTF_ALARM | ||
110 | bool "Android alarm driver" | ||
111 | depends on RTC_CLASS | ||
112 | default y | ||
113 | help | ||
114 | Provides non-wakeup and rtc backed wakeup alarms based on rtc or | ||
115 | elapsed realtime, and a non-wakeup alarm on the monotonic clock. | ||
116 | Also provides an interface to set the wall time which must be used | ||
117 | for elapsed realtime to work. | ||
118 | |||
119 | config RTC_INTF_ALARM_DEV | ||
120 | bool "Android alarm device" | ||
121 | depends on RTC_INTF_ALARM | ||
122 | default y | ||
123 | help | ||
124 | Exports the alarm interface to user-space. | ||
125 | |||
126 | |||
109 | config RTC_DRV_TEST | 127 | config RTC_DRV_TEST |
110 | tristate "Test driver/device" | 128 | tristate "Test driver/device" |
111 | help | 129 | help |
@@ -213,6 +231,26 @@ config RTC_DRV_MAX8998 | |||
213 | This driver can also be built as a module. If so, the module | 231 | This driver can also be built as a module. If so, the module |
214 | will be called rtc-max8998. | 232 | will be called rtc-max8998. |
215 | 233 | ||
234 | config RTC_DRV_MAX8907C | ||
235 | tristate "Maxim MAX8907C" | ||
236 | depends on MFD_MAX8907C | ||
237 | help | ||
238 | If you say yes here you will get support for the | ||
239 | RTC of Maxim MAX8907C PMIC. | ||
240 | |||
241 | This driver can also be built as a module. If so, the module | ||
242 | will be called rtc-max8907c. | ||
243 | |||
244 | config RTC_DRV_MAX77663 | ||
245 | tristate "Maxim MAX77663" | ||
246 | depends on MFD_MAX77663 | ||
247 | help | ||
248 | If you say yes here you will get support for the | ||
249 | RTC of Maxim MAX77663 PMIC. | ||
250 | |||
251 | This driver can also be built as a module. If so, the module | ||
252 | will be called rtc-max77663. | ||
253 | |||
216 | config RTC_DRV_RS5C372 | 254 | config RTC_DRV_RS5C372 |
217 | tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" | 255 | tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" |
218 | help | 256 | help |
@@ -304,6 +342,12 @@ config RTC_DRV_DM355EVM | |||
304 | help | 342 | help |
305 | Supports the RTC firmware in the MSP430 on the DM355 EVM. | 343 | Supports the RTC firmware in the MSP430 on the DM355 EVM. |
306 | 344 | ||
345 | config RTC_DRV_TPS6586X | ||
346 | tristate "TI TPS6586X RTC" | ||
347 | depends on MFD_TPS6586X | ||
348 | help | ||
349 | This driver supports TPS6586X RTC | ||
350 | |||
307 | config RTC_DRV_TWL92330 | 351 | config RTC_DRV_TWL92330 |
308 | boolean "TI TWL92330/Menelaus" | 352 | boolean "TI TWL92330/Menelaus" |
309 | depends on MENELAUS | 353 | depends on MENELAUS |
@@ -981,11 +1025,11 @@ config RTC_DRV_COH901331 | |||
981 | 1025 | ||
982 | 1026 | ||
983 | config RTC_DRV_STMP | 1027 | config RTC_DRV_STMP |
984 | tristate "Freescale STMP3xxx RTC" | 1028 | tristate "Freescale STMP3xxx/i.MX23/i.MX28 RTC" |
985 | depends on ARCH_STMP3XXX | 1029 | depends on ARCH_MXS |
986 | help | 1030 | help |
987 | If you say yes here you will get support for the onboard | 1031 | If you say yes here you will get support for the onboard |
988 | STMP3xxx RTC. | 1032 | STMP3xxx/i.MX23/i.MX28 RTC. |
989 | 1033 | ||
990 | This driver can also be built as a module. If so, the module | 1034 | This driver can also be built as a module. If so, the module |
991 | will be called rtc-stmp3xxx. | 1035 | will be called rtc-stmp3xxx. |
@@ -1006,10 +1050,10 @@ config RTC_DRV_MC13XXX | |||
1006 | 1050 | ||
1007 | config RTC_DRV_MPC5121 | 1051 | config RTC_DRV_MPC5121 |
1008 | tristate "Freescale MPC5121 built-in RTC" | 1052 | tristate "Freescale MPC5121 built-in RTC" |
1009 | depends on PPC_MPC512x && RTC_CLASS | 1053 | depends on PPC_MPC512x || PPC_MPC52xx |
1010 | help | 1054 | help |
1011 | If you say yes here you will get support for the | 1055 | If you say yes here you will get support for the |
1012 | built-in RTC MPC5121. | 1056 | built-in RTC on MPC5121 or on MPC5200. |
1013 | 1057 | ||
1014 | This driver can also be built as a module. If so, the module | 1058 | This driver can also be built as a module. If so, the module |
1015 | will be called rtc-mpc5121. | 1059 | will be called rtc-mpc5121. |
@@ -1034,12 +1078,21 @@ config RTC_DRV_LPC32XX | |||
1034 | This driver can also be buillt as a module. If so, the module | 1078 | This driver can also be buillt as a module. If so, the module |
1035 | will be called rtc-lpc32xx. | 1079 | will be called rtc-lpc32xx. |
1036 | 1080 | ||
1081 | config RTC_DRV_PM8XXX | ||
1082 | tristate "Qualcomm PMIC8XXX RTC" | ||
1083 | depends on MFD_PM8XXX | ||
1084 | help | ||
1085 | If you say yes here you get support for the | ||
1086 | Qualcomm PMIC8XXX RTC. | ||
1087 | |||
1088 | To compile this driver as a module, choose M here: the | ||
1089 | module will be called rtc-pm8xxx. | ||
1090 | |||
1037 | config RTC_DRV_TEGRA | 1091 | config RTC_DRV_TEGRA |
1038 | tristate "NVIDIA Tegra Internal RTC driver" | 1092 | tristate "NVIDIA Tegra Internal RTC driver" |
1039 | depends on RTC_CLASS && ARCH_TEGRA | 1093 | depends on RTC_CLASS && ARCH_TEGRA |
1040 | help | 1094 | help |
1041 | If you say yes here you get support for the | 1095 | If you say yes here you get support for the Tegra internal RTC module. |
1042 | Tegra 200 series internal RTC module. | ||
1043 | 1096 | ||
1044 | This drive can also be built as a module. If so, the module | 1097 | This drive can also be built as a module. If so, the module |
1045 | will be called rtc-tegra. | 1098 | will be called rtc-tegra. |
@@ -1051,6 +1104,26 @@ config RTC_DRV_TILE | |||
1051 | Enable support for the Linux driver side of the Tilera | 1104 | Enable support for the Linux driver side of the Tilera |
1052 | hypervisor's real-time clock interface. | 1105 | hypervisor's real-time clock interface. |
1053 | 1106 | ||
1107 | config RTC_DRV_TPS6591x | ||
1108 | tristate "TPS6591x RTC driver" | ||
1109 | depends on MFD_TPS6591X | ||
1110 | default n | ||
1111 | help | ||
1112 | If you say yes here you get support for the TPS6591x RTC module. | ||
1113 | |||
1114 | This driver can also be built as a module. If so, the module | ||
1115 | will be called rtc-tps6591x. | ||
1116 | |||
1117 | config RTC_DRV_TPS80031 | ||
1118 | tristate "TPS80031 RTC driver" | ||
1119 | depends on MFD_TPS80031 | ||
1120 | default n | ||
1121 | help | ||
1122 | If you say yes here you get support for the TPS80031 RTC module. | ||
1123 | |||
1124 | This driver can also be built as a module. If so, the module | ||
1125 | will be called rtc-tps6591x. | ||
1126 | |||
1054 | config RTC_DRV_PUV3 | 1127 | config RTC_DRV_PUV3 |
1055 | tristate "PKUnity v3 RTC support" | 1128 | tristate "PKUnity v3 RTC support" |
1056 | depends on ARCH_PUV3 | 1129 | depends on ARCH_PUV3 |
@@ -1060,4 +1133,14 @@ config RTC_DRV_PUV3 | |||
1060 | This drive can also be built as a module. If so, the module | 1133 | This drive can also be built as a module. If so, the module |
1061 | will be called rtc-puv3. | 1134 | will be called rtc-puv3. |
1062 | 1135 | ||
1136 | config RTC_DRV_RC5T583 | ||
1137 | tristate "RICOH RC5T583 PMU RTC driver" | ||
1138 | depends on MFD_RICOH583 | ||
1139 | default n | ||
1140 | help | ||
1141 | If you say yes here you get support for the RICOH RC5T583 RTC module. | ||
1142 | |||
1143 | This driver can also be built as a module. If so, the module | ||
1144 | will be called rtc-rc5t583. | ||
1145 | |||
1063 | endif # RTC_CLASS | 1146 | endif # RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 0ffefe877bf..be5b16284db 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -9,6 +9,8 @@ obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o | |||
9 | obj-$(CONFIG_RTC_CLASS) += rtc-core.o | 9 | obj-$(CONFIG_RTC_CLASS) += rtc-core.o |
10 | rtc-core-y := class.o interface.o | 10 | rtc-core-y := class.o interface.o |
11 | 11 | ||
12 | obj-$(CONFIG_RTC_INTF_ALARM) += alarm.o | ||
13 | obj-$(CONFIG_RTC_INTF_ALARM_DEV) += alarm-dev.o | ||
12 | rtc-core-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o | 14 | rtc-core-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o |
13 | rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o | 15 | rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o |
14 | rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o | 16 | rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o |
@@ -63,8 +65,10 @@ obj-$(CONFIG_RTC_MXC) += rtc-mxc.o | |||
63 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o | 65 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o |
64 | obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o | 66 | obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o |
65 | obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o | 67 | obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o |
68 | obj-$(CONFIG_RTC_DRV_MAX8907C) += rtc-max8907c.o | ||
66 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 69 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
67 | obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o | 70 | obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o |
71 | obj-$(CONFIG_RTC_DRV_MAX77663) += rtc-max77663.o | ||
68 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o | 72 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o |
69 | obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o | 73 | obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o |
70 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o | 74 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o |
@@ -77,6 +81,7 @@ obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o | |||
77 | obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o | 81 | obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o |
78 | obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o | 82 | obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o |
79 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o | 83 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o |
84 | obj-$(CONFIG_RTC_DRV_PM8XXX) += rtc-pm8xxx.o | ||
80 | obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o | 85 | obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o |
81 | obj-$(CONFIG_RTC_DRV_PUV3) += rtc-puv3.o | 86 | obj-$(CONFIG_RTC_DRV_PUV3) += rtc-puv3.o |
82 | obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o | 87 | obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o |
@@ -100,6 +105,10 @@ obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o | |||
100 | obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o | 105 | obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o |
101 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o | 106 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o |
102 | obj-$(CONFIG_RTC_DRV_TILE) += rtc-tile.o | 107 | obj-$(CONFIG_RTC_DRV_TILE) += rtc-tile.o |
108 | obj-$(CONFIG_RTC_DRV_TPS6586X) += rtc-tps6586x.o | ||
109 | obj-$(CONFIG_RTC_DRV_TPS6591x) += rtc-tps6591x.o | ||
110 | obj-$(CONFIG_RTC_DRV_TPS80031) += rtc-tps80031.o | ||
111 | obj-$(CONFIG_RTC_DRV_RC5T583) += rtc-ricoh583.o | ||
103 | obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o | 112 | obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o |
104 | obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o | 113 | obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o |
105 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o | 114 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o |
diff --git a/drivers/rtc/alarm-dev.c b/drivers/rtc/alarm-dev.c new file mode 100644 index 00000000000..686e6f7ed48 --- /dev/null +++ b/drivers/rtc/alarm-dev.c | |||
@@ -0,0 +1,286 @@ | |||
1 | /* drivers/rtc/alarm-dev.c | ||
2 | * | ||
3 | * Copyright (C) 2007-2009 Google, Inc. | ||
4 | * | ||
5 | * This software is licensed under the terms of the GNU General Public | ||
6 | * License version 2, as published by the Free Software Foundation, and | ||
7 | * may be copied, distributed, and modified under those terms. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <asm/mach/time.h> | ||
17 | #include <linux/android_alarm.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/miscdevice.h> | ||
20 | #include <linux/fs.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/sysdev.h> | ||
25 | #include <linux/uaccess.h> | ||
26 | #include <linux/wakelock.h> | ||
27 | |||
28 | #define ANDROID_ALARM_PRINT_INFO (1U << 0) | ||
29 | #define ANDROID_ALARM_PRINT_IO (1U << 1) | ||
30 | #define ANDROID_ALARM_PRINT_INT (1U << 2) | ||
31 | |||
32 | static int debug_mask = ANDROID_ALARM_PRINT_INFO; | ||
33 | module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); | ||
34 | |||
35 | #define pr_alarm(debug_level_mask, args...) \ | ||
36 | do { \ | ||
37 | if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) { \ | ||
38 | pr_info(args); \ | ||
39 | } \ | ||
40 | } while (0) | ||
41 | |||
42 | #define ANDROID_ALARM_WAKEUP_MASK ( \ | ||
43 | ANDROID_ALARM_RTC_WAKEUP_MASK | \ | ||
44 | ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK) | ||
45 | |||
46 | /* support old usespace code */ | ||
47 | #define ANDROID_ALARM_SET_OLD _IOW('a', 2, time_t) /* set alarm */ | ||
48 | #define ANDROID_ALARM_SET_AND_WAIT_OLD _IOW('a', 3, time_t) | ||
49 | |||
50 | static int alarm_opened; | ||
51 | static DEFINE_SPINLOCK(alarm_slock); | ||
52 | static struct wake_lock alarm_wake_lock; | ||
53 | static DECLARE_WAIT_QUEUE_HEAD(alarm_wait_queue); | ||
54 | static uint32_t alarm_pending; | ||
55 | static uint32_t alarm_enabled; | ||
56 | static uint32_t wait_pending; | ||
57 | |||
58 | static struct alarm alarms[ANDROID_ALARM_TYPE_COUNT]; | ||
59 | |||
60 | static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
61 | { | ||
62 | int rv = 0; | ||
63 | unsigned long flags; | ||
64 | struct timespec new_alarm_time; | ||
65 | struct timespec new_rtc_time; | ||
66 | struct timespec tmp_time; | ||
67 | enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd); | ||
68 | uint32_t alarm_type_mask = 1U << alarm_type; | ||
69 | |||
70 | if (alarm_type >= ANDROID_ALARM_TYPE_COUNT) | ||
71 | return -EINVAL; | ||
72 | |||
73 | if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) { | ||
74 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) | ||
75 | return -EPERM; | ||
76 | if (file->private_data == NULL && | ||
77 | cmd != ANDROID_ALARM_SET_RTC) { | ||
78 | spin_lock_irqsave(&alarm_slock, flags); | ||
79 | if (alarm_opened) { | ||
80 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
81 | return -EBUSY; | ||
82 | } | ||
83 | alarm_opened = 1; | ||
84 | file->private_data = (void *)1; | ||
85 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | switch (ANDROID_ALARM_BASE_CMD(cmd)) { | ||
90 | case ANDROID_ALARM_CLEAR(0): | ||
91 | spin_lock_irqsave(&alarm_slock, flags); | ||
92 | pr_alarm(IO, "alarm %d clear\n", alarm_type); | ||
93 | alarm_try_to_cancel(&alarms[alarm_type]); | ||
94 | if (alarm_pending) { | ||
95 | alarm_pending &= ~alarm_type_mask; | ||
96 | if (!alarm_pending && !wait_pending) | ||
97 | wake_unlock(&alarm_wake_lock); | ||
98 | } | ||
99 | alarm_enabled &= ~alarm_type_mask; | ||
100 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
101 | break; | ||
102 | |||
103 | case ANDROID_ALARM_SET_OLD: | ||
104 | case ANDROID_ALARM_SET_AND_WAIT_OLD: | ||
105 | if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) { | ||
106 | rv = -EFAULT; | ||
107 | goto err1; | ||
108 | } | ||
109 | new_alarm_time.tv_nsec = 0; | ||
110 | goto from_old_alarm_set; | ||
111 | |||
112 | case ANDROID_ALARM_SET_AND_WAIT(0): | ||
113 | case ANDROID_ALARM_SET(0): | ||
114 | if (copy_from_user(&new_alarm_time, (void __user *)arg, | ||
115 | sizeof(new_alarm_time))) { | ||
116 | rv = -EFAULT; | ||
117 | goto err1; | ||
118 | } | ||
119 | from_old_alarm_set: | ||
120 | spin_lock_irqsave(&alarm_slock, flags); | ||
121 | pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type, | ||
122 | new_alarm_time.tv_sec, new_alarm_time.tv_nsec); | ||
123 | alarm_enabled |= alarm_type_mask; | ||
124 | alarm_start_range(&alarms[alarm_type], | ||
125 | timespec_to_ktime(new_alarm_time), | ||
126 | timespec_to_ktime(new_alarm_time)); | ||
127 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
128 | if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0) | ||
129 | && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD) | ||
130 | break; | ||
131 | /* fall though */ | ||
132 | case ANDROID_ALARM_WAIT: | ||
133 | spin_lock_irqsave(&alarm_slock, flags); | ||
134 | pr_alarm(IO, "alarm wait\n"); | ||
135 | if (!alarm_pending && wait_pending) { | ||
136 | wake_unlock(&alarm_wake_lock); | ||
137 | wait_pending = 0; | ||
138 | } | ||
139 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
140 | rv = wait_event_interruptible(alarm_wait_queue, alarm_pending); | ||
141 | if (rv) | ||
142 | goto err1; | ||
143 | spin_lock_irqsave(&alarm_slock, flags); | ||
144 | rv = alarm_pending; | ||
145 | wait_pending = 1; | ||
146 | alarm_pending = 0; | ||
147 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
148 | break; | ||
149 | case ANDROID_ALARM_SET_RTC: | ||
150 | if (copy_from_user(&new_rtc_time, (void __user *)arg, | ||
151 | sizeof(new_rtc_time))) { | ||
152 | rv = -EFAULT; | ||
153 | goto err1; | ||
154 | } | ||
155 | rv = alarm_set_rtc(new_rtc_time); | ||
156 | spin_lock_irqsave(&alarm_slock, flags); | ||
157 | alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK; | ||
158 | wake_up(&alarm_wait_queue); | ||
159 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
160 | if (rv < 0) | ||
161 | goto err1; | ||
162 | break; | ||
163 | case ANDROID_ALARM_GET_TIME(0): | ||
164 | switch (alarm_type) { | ||
165 | case ANDROID_ALARM_RTC_WAKEUP: | ||
166 | case ANDROID_ALARM_RTC: | ||
167 | getnstimeofday(&tmp_time); | ||
168 | break; | ||
169 | case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP: | ||
170 | case ANDROID_ALARM_ELAPSED_REALTIME: | ||
171 | tmp_time = | ||
172 | ktime_to_timespec(alarm_get_elapsed_realtime()); | ||
173 | break; | ||
174 | case ANDROID_ALARM_TYPE_COUNT: | ||
175 | case ANDROID_ALARM_SYSTEMTIME: | ||
176 | ktime_get_ts(&tmp_time); | ||
177 | break; | ||
178 | } | ||
179 | if (copy_to_user((void __user *)arg, &tmp_time, | ||
180 | sizeof(tmp_time))) { | ||
181 | rv = -EFAULT; | ||
182 | goto err1; | ||
183 | } | ||
184 | break; | ||
185 | |||
186 | default: | ||
187 | rv = -EINVAL; | ||
188 | goto err1; | ||
189 | } | ||
190 | err1: | ||
191 | return rv; | ||
192 | } | ||
193 | |||
194 | static int alarm_open(struct inode *inode, struct file *file) | ||
195 | { | ||
196 | file->private_data = NULL; | ||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static int alarm_release(struct inode *inode, struct file *file) | ||
201 | { | ||
202 | int i; | ||
203 | unsigned long flags; | ||
204 | |||
205 | spin_lock_irqsave(&alarm_slock, flags); | ||
206 | if (file->private_data != 0) { | ||
207 | for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { | ||
208 | uint32_t alarm_type_mask = 1U << i; | ||
209 | if (alarm_enabled & alarm_type_mask) { | ||
210 | pr_alarm(INFO, "alarm_release: clear alarm, " | ||
211 | "pending %d\n", | ||
212 | !!(alarm_pending & alarm_type_mask)); | ||
213 | alarm_enabled &= ~alarm_type_mask; | ||
214 | } | ||
215 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
216 | alarm_cancel(&alarms[i]); | ||
217 | spin_lock_irqsave(&alarm_slock, flags); | ||
218 | } | ||
219 | if (alarm_pending | wait_pending) { | ||
220 | if (alarm_pending) | ||
221 | pr_alarm(INFO, "alarm_release: clear " | ||
222 | "pending alarms %x\n", alarm_pending); | ||
223 | wake_unlock(&alarm_wake_lock); | ||
224 | wait_pending = 0; | ||
225 | alarm_pending = 0; | ||
226 | } | ||
227 | alarm_opened = 0; | ||
228 | } | ||
229 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static void alarm_triggered(struct alarm *alarm) | ||
234 | { | ||
235 | unsigned long flags; | ||
236 | uint32_t alarm_type_mask = 1U << alarm->type; | ||
237 | |||
238 | pr_alarm(INT, "alarm_triggered type %d\n", alarm->type); | ||
239 | spin_lock_irqsave(&alarm_slock, flags); | ||
240 | if (alarm_enabled & alarm_type_mask) { | ||
241 | wake_lock_timeout(&alarm_wake_lock, 5 * HZ); | ||
242 | alarm_enabled &= ~alarm_type_mask; | ||
243 | alarm_pending |= alarm_type_mask; | ||
244 | wake_up(&alarm_wait_queue); | ||
245 | } | ||
246 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
247 | } | ||
248 | |||
249 | static const struct file_operations alarm_fops = { | ||
250 | .owner = THIS_MODULE, | ||
251 | .unlocked_ioctl = alarm_ioctl, | ||
252 | .open = alarm_open, | ||
253 | .release = alarm_release, | ||
254 | }; | ||
255 | |||
256 | static struct miscdevice alarm_device = { | ||
257 | .minor = MISC_DYNAMIC_MINOR, | ||
258 | .name = "alarm", | ||
259 | .fops = &alarm_fops, | ||
260 | }; | ||
261 | |||
262 | static int __init alarm_dev_init(void) | ||
263 | { | ||
264 | int err; | ||
265 | int i; | ||
266 | |||
267 | err = misc_register(&alarm_device); | ||
268 | if (err) | ||
269 | return err; | ||
270 | |||
271 | for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) | ||
272 | alarm_init(&alarms[i], i, alarm_triggered); | ||
273 | wake_lock_init(&alarm_wake_lock, WAKE_LOCK_SUSPEND, "alarm"); | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static void __exit alarm_dev_exit(void) | ||
279 | { | ||
280 | misc_deregister(&alarm_device); | ||
281 | wake_lock_destroy(&alarm_wake_lock); | ||
282 | } | ||
283 | |||
284 | module_init(alarm_dev_init); | ||
285 | module_exit(alarm_dev_exit); | ||
286 | |||
diff --git a/drivers/rtc/alarm.c b/drivers/rtc/alarm.c new file mode 100644 index 00000000000..28b0df836a3 --- /dev/null +++ b/drivers/rtc/alarm.c | |||
@@ -0,0 +1,590 @@ | |||
1 | /* drivers/rtc/alarm.c | ||
2 | * | ||
3 | * Copyright (C) 2007-2009 Google, Inc. | ||
4 | * | ||
5 | * This software is licensed under the terms of the GNU General Public | ||
6 | * License version 2, as published by the Free Software Foundation, and | ||
7 | * may be copied, distributed, and modified under those terms. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <asm/mach/time.h> | ||
17 | #include <linux/android_alarm.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/miscdevice.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/rtc.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/sysdev.h> | ||
25 | #include <linux/wakelock.h> | ||
26 | |||
27 | #define ANDROID_ALARM_PRINT_ERROR (1U << 0) | ||
28 | #define ANDROID_ALARM_PRINT_INIT_STATUS (1U << 1) | ||
29 | #define ANDROID_ALARM_PRINT_TSET (1U << 2) | ||
30 | #define ANDROID_ALARM_PRINT_CALL (1U << 3) | ||
31 | #define ANDROID_ALARM_PRINT_SUSPEND (1U << 4) | ||
32 | #define ANDROID_ALARM_PRINT_INT (1U << 5) | ||
33 | #define ANDROID_ALARM_PRINT_FLOW (1U << 6) | ||
34 | |||
35 | static int debug_mask = ANDROID_ALARM_PRINT_ERROR | \ | ||
36 | ANDROID_ALARM_PRINT_INIT_STATUS; | ||
37 | module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); | ||
38 | |||
39 | #define pr_alarm(debug_level_mask, args...) \ | ||
40 | do { \ | ||
41 | if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) { \ | ||
42 | pr_info(args); \ | ||
43 | } \ | ||
44 | } while (0) | ||
45 | |||
46 | #define ANDROID_ALARM_WAKEUP_MASK ( \ | ||
47 | ANDROID_ALARM_RTC_WAKEUP_MASK | \ | ||
48 | ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK) | ||
49 | |||
50 | /* support old usespace code */ | ||
51 | #define ANDROID_ALARM_SET_OLD _IOW('a', 2, time_t) /* set alarm */ | ||
52 | #define ANDROID_ALARM_SET_AND_WAIT_OLD _IOW('a', 3, time_t) | ||
53 | |||
54 | struct alarm_queue { | ||
55 | struct rb_root alarms; | ||
56 | struct rb_node *first; | ||
57 | struct hrtimer timer; | ||
58 | ktime_t delta; | ||
59 | bool stopped; | ||
60 | ktime_t stopped_time; | ||
61 | }; | ||
62 | |||
63 | static struct rtc_device *alarm_rtc_dev; | ||
64 | static DEFINE_SPINLOCK(alarm_slock); | ||
65 | static DEFINE_MUTEX(alarm_setrtc_mutex); | ||
66 | static struct wake_lock alarm_rtc_wake_lock; | ||
67 | static struct platform_device *alarm_platform_dev; | ||
68 | struct alarm_queue alarms[ANDROID_ALARM_TYPE_COUNT]; | ||
69 | static bool suspended; | ||
70 | |||
71 | static void update_timer_locked(struct alarm_queue *base, bool head_removed) | ||
72 | { | ||
73 | struct alarm *alarm; | ||
74 | bool is_wakeup = base == &alarms[ANDROID_ALARM_RTC_WAKEUP] || | ||
75 | base == &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP]; | ||
76 | |||
77 | if (base->stopped) { | ||
78 | pr_alarm(FLOW, "changed alarm while setting the wall time\n"); | ||
79 | return; | ||
80 | } | ||
81 | |||
82 | if (is_wakeup && !suspended && head_removed) | ||
83 | wake_unlock(&alarm_rtc_wake_lock); | ||
84 | |||
85 | if (!base->first) | ||
86 | return; | ||
87 | |||
88 | alarm = container_of(base->first, struct alarm, node); | ||
89 | |||
90 | pr_alarm(FLOW, "selected alarm, type %d, func %pF at %lld\n", | ||
91 | alarm->type, alarm->function, ktime_to_ns(alarm->expires)); | ||
92 | |||
93 | if (is_wakeup && suspended) { | ||
94 | pr_alarm(FLOW, "changed alarm while suspened\n"); | ||
95 | wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ); | ||
96 | return; | ||
97 | } | ||
98 | |||
99 | hrtimer_try_to_cancel(&base->timer); | ||
100 | base->timer.node.expires = ktime_add(base->delta, alarm->expires); | ||
101 | base->timer._softexpires = ktime_add(base->delta, alarm->softexpires); | ||
102 | hrtimer_start_expires(&base->timer, HRTIMER_MODE_ABS); | ||
103 | } | ||
104 | |||
105 | static void alarm_enqueue_locked(struct alarm *alarm) | ||
106 | { | ||
107 | struct alarm_queue *base = &alarms[alarm->type]; | ||
108 | struct rb_node **link = &base->alarms.rb_node; | ||
109 | struct rb_node *parent = NULL; | ||
110 | struct alarm *entry; | ||
111 | int leftmost = 1; | ||
112 | bool was_first = false; | ||
113 | |||
114 | pr_alarm(FLOW, "added alarm, type %d, func %pF at %lld\n", | ||
115 | alarm->type, alarm->function, ktime_to_ns(alarm->expires)); | ||
116 | |||
117 | if (base->first == &alarm->node) { | ||
118 | base->first = rb_next(&alarm->node); | ||
119 | was_first = true; | ||
120 | } | ||
121 | if (!RB_EMPTY_NODE(&alarm->node)) { | ||
122 | rb_erase(&alarm->node, &base->alarms); | ||
123 | RB_CLEAR_NODE(&alarm->node); | ||
124 | } | ||
125 | |||
126 | while (*link) { | ||
127 | parent = *link; | ||
128 | entry = rb_entry(parent, struct alarm, node); | ||
129 | /* | ||
130 | * We dont care about collisions. Nodes with | ||
131 | * the same expiry time stay together. | ||
132 | */ | ||
133 | if (alarm->expires.tv64 < entry->expires.tv64) { | ||
134 | link = &(*link)->rb_left; | ||
135 | } else { | ||
136 | link = &(*link)->rb_right; | ||
137 | leftmost = 0; | ||
138 | } | ||
139 | } | ||
140 | if (leftmost) | ||
141 | base->first = &alarm->node; | ||
142 | if (leftmost || was_first) | ||
143 | update_timer_locked(base, was_first); | ||
144 | |||
145 | rb_link_node(&alarm->node, parent, link); | ||
146 | rb_insert_color(&alarm->node, &base->alarms); | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * alarm_init - initialize an alarm | ||
151 | * @alarm: the alarm to be initialized | ||
152 | * @type: the alarm type to be used | ||
153 | * @function: alarm callback function | ||
154 | */ | ||
155 | void alarm_init(struct alarm *alarm, | ||
156 | enum android_alarm_type type, void (*function)(struct alarm *)) | ||
157 | { | ||
158 | RB_CLEAR_NODE(&alarm->node); | ||
159 | alarm->type = type; | ||
160 | alarm->function = function; | ||
161 | |||
162 | pr_alarm(FLOW, "created alarm, type %d, func %pF\n", type, function); | ||
163 | } | ||
164 | |||
165 | |||
166 | /** | ||
167 | * alarm_start_range - (re)start an alarm | ||
168 | * @alarm: the alarm to be added | ||
169 | * @start: earliest expiry time | ||
170 | * @end: expiry time | ||
171 | */ | ||
172 | void alarm_start_range(struct alarm *alarm, ktime_t start, ktime_t end) | ||
173 | { | ||
174 | unsigned long flags; | ||
175 | |||
176 | spin_lock_irqsave(&alarm_slock, flags); | ||
177 | alarm->softexpires = start; | ||
178 | alarm->expires = end; | ||
179 | alarm_enqueue_locked(alarm); | ||
180 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
181 | } | ||
182 | |||
183 | /** | ||
184 | * alarm_try_to_cancel - try to deactivate an alarm | ||
185 | * @alarm: alarm to stop | ||
186 | * | ||
187 | * Returns: | ||
188 | * 0 when the alarm was not active | ||
189 | * 1 when the alarm was active | ||
190 | * -1 when the alarm may currently be excuting the callback function and | ||
191 | * cannot be stopped (it may also be inactive) | ||
192 | */ | ||
193 | int alarm_try_to_cancel(struct alarm *alarm) | ||
194 | { | ||
195 | struct alarm_queue *base = &alarms[alarm->type]; | ||
196 | unsigned long flags; | ||
197 | bool first = false; | ||
198 | int ret = 0; | ||
199 | |||
200 | spin_lock_irqsave(&alarm_slock, flags); | ||
201 | if (!RB_EMPTY_NODE(&alarm->node)) { | ||
202 | pr_alarm(FLOW, "canceled alarm, type %d, func %pF at %lld\n", | ||
203 | alarm->type, alarm->function, | ||
204 | ktime_to_ns(alarm->expires)); | ||
205 | ret = 1; | ||
206 | if (base->first == &alarm->node) { | ||
207 | base->first = rb_next(&alarm->node); | ||
208 | first = true; | ||
209 | } | ||
210 | rb_erase(&alarm->node, &base->alarms); | ||
211 | RB_CLEAR_NODE(&alarm->node); | ||
212 | if (first) | ||
213 | update_timer_locked(base, true); | ||
214 | } else | ||
215 | pr_alarm(FLOW, "tried to cancel alarm, type %d, func %pF\n", | ||
216 | alarm->type, alarm->function); | ||
217 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
218 | if (!ret && hrtimer_callback_running(&base->timer)) | ||
219 | ret = -1; | ||
220 | return ret; | ||
221 | } | ||
222 | |||
223 | /** | ||
224 | * alarm_cancel - cancel an alarm and wait for the handler to finish. | ||
225 | * @alarm: the alarm to be cancelled | ||
226 | * | ||
227 | * Returns: | ||
228 | * 0 when the alarm was not active | ||
229 | * 1 when the alarm was active | ||
230 | */ | ||
231 | int alarm_cancel(struct alarm *alarm) | ||
232 | { | ||
233 | for (;;) { | ||
234 | int ret = alarm_try_to_cancel(alarm); | ||
235 | if (ret >= 0) | ||
236 | return ret; | ||
237 | cpu_relax(); | ||
238 | } | ||
239 | } | ||
240 | |||
241 | /** | ||
242 | * alarm_set_rtc - set the kernel and rtc walltime | ||
243 | * @new_time: timespec value containing the new time | ||
244 | */ | ||
245 | int alarm_set_rtc(struct timespec new_time) | ||
246 | { | ||
247 | int i; | ||
248 | int ret; | ||
249 | unsigned long flags; | ||
250 | struct rtc_time rtc_new_rtc_time; | ||
251 | struct timespec tmp_time; | ||
252 | |||
253 | rtc_time_to_tm(new_time.tv_sec, &rtc_new_rtc_time); | ||
254 | |||
255 | pr_alarm(TSET, "set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d\n", | ||
256 | new_time.tv_sec, new_time.tv_nsec, | ||
257 | rtc_new_rtc_time.tm_hour, rtc_new_rtc_time.tm_min, | ||
258 | rtc_new_rtc_time.tm_sec, rtc_new_rtc_time.tm_mon + 1, | ||
259 | rtc_new_rtc_time.tm_mday, | ||
260 | rtc_new_rtc_time.tm_year + 1900); | ||
261 | |||
262 | mutex_lock(&alarm_setrtc_mutex); | ||
263 | spin_lock_irqsave(&alarm_slock, flags); | ||
264 | wake_lock(&alarm_rtc_wake_lock); | ||
265 | getnstimeofday(&tmp_time); | ||
266 | for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) { | ||
267 | hrtimer_try_to_cancel(&alarms[i].timer); | ||
268 | alarms[i].stopped = true; | ||
269 | alarms[i].stopped_time = timespec_to_ktime(tmp_time); | ||
270 | } | ||
271 | alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta = | ||
272 | alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta = | ||
273 | ktime_sub(alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta, | ||
274 | timespec_to_ktime(timespec_sub(tmp_time, new_time))); | ||
275 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
276 | ret = do_settimeofday(&new_time); | ||
277 | spin_lock_irqsave(&alarm_slock, flags); | ||
278 | for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) { | ||
279 | alarms[i].stopped = false; | ||
280 | update_timer_locked(&alarms[i], false); | ||
281 | } | ||
282 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
283 | if (ret < 0) { | ||
284 | pr_alarm(ERROR, "alarm_set_rtc: Failed to set time\n"); | ||
285 | goto err; | ||
286 | } | ||
287 | if (!alarm_rtc_dev) { | ||
288 | pr_alarm(ERROR, | ||
289 | "alarm_set_rtc: no RTC, time will be lost on reboot\n"); | ||
290 | goto err; | ||
291 | } | ||
292 | ret = rtc_set_time(alarm_rtc_dev, &rtc_new_rtc_time); | ||
293 | if (ret < 0) | ||
294 | pr_alarm(ERROR, "alarm_set_rtc: " | ||
295 | "Failed to set RTC, time will be lost on reboot\n"); | ||
296 | err: | ||
297 | wake_unlock(&alarm_rtc_wake_lock); | ||
298 | mutex_unlock(&alarm_setrtc_mutex); | ||
299 | return ret; | ||
300 | } | ||
301 | |||
302 | /** | ||
303 | * alarm_get_elapsed_realtime - get the elapsed real time in ktime_t format | ||
304 | * | ||
305 | * returns the time in ktime_t format | ||
306 | */ | ||
307 | ktime_t alarm_get_elapsed_realtime(void) | ||
308 | { | ||
309 | ktime_t now; | ||
310 | unsigned long flags; | ||
311 | struct alarm_queue *base = &alarms[ANDROID_ALARM_ELAPSED_REALTIME]; | ||
312 | |||
313 | spin_lock_irqsave(&alarm_slock, flags); | ||
314 | now = base->stopped ? base->stopped_time : ktime_get_real(); | ||
315 | now = ktime_sub(now, base->delta); | ||
316 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
317 | return now; | ||
318 | } | ||
319 | |||
320 | static enum hrtimer_restart alarm_timer_triggered(struct hrtimer *timer) | ||
321 | { | ||
322 | struct alarm_queue *base; | ||
323 | struct alarm *alarm; | ||
324 | unsigned long flags; | ||
325 | ktime_t now; | ||
326 | |||
327 | spin_lock_irqsave(&alarm_slock, flags); | ||
328 | |||
329 | base = container_of(timer, struct alarm_queue, timer); | ||
330 | now = base->stopped ? base->stopped_time : hrtimer_cb_get_time(timer); | ||
331 | now = ktime_sub(now, base->delta); | ||
332 | |||
333 | pr_alarm(INT, "alarm_timer_triggered type %d at %lld\n", | ||
334 | base - alarms, ktime_to_ns(now)); | ||
335 | |||
336 | while (base->first) { | ||
337 | alarm = container_of(base->first, struct alarm, node); | ||
338 | if (alarm->softexpires.tv64 > now.tv64) { | ||
339 | pr_alarm(FLOW, "don't call alarm, %pF, %lld (s %lld)\n", | ||
340 | alarm->function, ktime_to_ns(alarm->expires), | ||
341 | ktime_to_ns(alarm->softexpires)); | ||
342 | break; | ||
343 | } | ||
344 | base->first = rb_next(&alarm->node); | ||
345 | rb_erase(&alarm->node, &base->alarms); | ||
346 | RB_CLEAR_NODE(&alarm->node); | ||
347 | pr_alarm(CALL, "call alarm, type %d, func %pF, %lld (s %lld)\n", | ||
348 | alarm->type, alarm->function, | ||
349 | ktime_to_ns(alarm->expires), | ||
350 | ktime_to_ns(alarm->softexpires)); | ||
351 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
352 | alarm->function(alarm); | ||
353 | spin_lock_irqsave(&alarm_slock, flags); | ||
354 | } | ||
355 | if (!base->first) | ||
356 | pr_alarm(FLOW, "no more alarms of type %d\n", base - alarms); | ||
357 | update_timer_locked(base, true); | ||
358 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
359 | return HRTIMER_NORESTART; | ||
360 | } | ||
361 | |||
362 | static void alarm_triggered_func(void *p) | ||
363 | { | ||
364 | struct rtc_device *rtc = alarm_rtc_dev; | ||
365 | if (!(rtc->irq_data & RTC_AF)) | ||
366 | return; | ||
367 | pr_alarm(INT, "rtc alarm triggered\n"); | ||
368 | wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ); | ||
369 | } | ||
370 | |||
371 | static int alarm_suspend(struct platform_device *pdev, pm_message_t state) | ||
372 | { | ||
373 | int err = 0; | ||
374 | unsigned long flags; | ||
375 | struct rtc_wkalrm rtc_alarm; | ||
376 | struct rtc_time rtc_current_rtc_time; | ||
377 | unsigned long rtc_current_time; | ||
378 | unsigned long rtc_alarm_time; | ||
379 | struct timespec rtc_delta; | ||
380 | struct timespec wall_time; | ||
381 | struct alarm_queue *wakeup_queue = NULL; | ||
382 | struct alarm_queue *tmp_queue = NULL; | ||
383 | |||
384 | pr_alarm(SUSPEND, "alarm_suspend(%p, %d)\n", pdev, state.event); | ||
385 | |||
386 | spin_lock_irqsave(&alarm_slock, flags); | ||
387 | suspended = true; | ||
388 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
389 | |||
390 | hrtimer_cancel(&alarms[ANDROID_ALARM_RTC_WAKEUP].timer); | ||
391 | hrtimer_cancel(&alarms[ | ||
392 | ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].timer); | ||
393 | |||
394 | tmp_queue = &alarms[ANDROID_ALARM_RTC_WAKEUP]; | ||
395 | if (tmp_queue->first) | ||
396 | wakeup_queue = tmp_queue; | ||
397 | tmp_queue = &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP]; | ||
398 | if (tmp_queue->first && (!wakeup_queue || | ||
399 | hrtimer_get_expires(&tmp_queue->timer).tv64 < | ||
400 | hrtimer_get_expires(&wakeup_queue->timer).tv64)) | ||
401 | wakeup_queue = tmp_queue; | ||
402 | if (wakeup_queue) { | ||
403 | rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time); | ||
404 | getnstimeofday(&wall_time); | ||
405 | rtc_tm_to_time(&rtc_current_rtc_time, &rtc_current_time); | ||
406 | set_normalized_timespec(&rtc_delta, | ||
407 | wall_time.tv_sec - rtc_current_time, | ||
408 | wall_time.tv_nsec); | ||
409 | |||
410 | rtc_alarm_time = timespec_sub(ktime_to_timespec( | ||
411 | hrtimer_get_expires(&wakeup_queue->timer)), | ||
412 | rtc_delta).tv_sec; | ||
413 | |||
414 | rtc_time_to_tm(rtc_alarm_time, &rtc_alarm.time); | ||
415 | rtc_alarm.enabled = 1; | ||
416 | rtc_set_alarm(alarm_rtc_dev, &rtc_alarm); | ||
417 | rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time); | ||
418 | rtc_tm_to_time(&rtc_current_rtc_time, &rtc_current_time); | ||
419 | pr_alarm(SUSPEND, | ||
420 | "rtc alarm set at %ld, now %ld, rtc delta %ld.%09ld\n", | ||
421 | rtc_alarm_time, rtc_current_time, | ||
422 | rtc_delta.tv_sec, rtc_delta.tv_nsec); | ||
423 | if (rtc_current_time + 1 >= rtc_alarm_time) { | ||
424 | pr_alarm(SUSPEND, "alarm about to go off\n"); | ||
425 | memset(&rtc_alarm, 0, sizeof(rtc_alarm)); | ||
426 | rtc_alarm.enabled = 0; | ||
427 | rtc_set_alarm(alarm_rtc_dev, &rtc_alarm); | ||
428 | |||
429 | spin_lock_irqsave(&alarm_slock, flags); | ||
430 | suspended = false; | ||
431 | wake_lock_timeout(&alarm_rtc_wake_lock, 2 * HZ); | ||
432 | update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP], | ||
433 | false); | ||
434 | update_timer_locked(&alarms[ | ||
435 | ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP], false); | ||
436 | err = -EBUSY; | ||
437 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
438 | } | ||
439 | } | ||
440 | return err; | ||
441 | } | ||
442 | |||
443 | static int alarm_resume(struct platform_device *pdev) | ||
444 | { | ||
445 | struct rtc_wkalrm alarm; | ||
446 | unsigned long flags; | ||
447 | |||
448 | pr_alarm(SUSPEND, "alarm_resume(%p)\n", pdev); | ||
449 | |||
450 | memset(&alarm, 0, sizeof(alarm)); | ||
451 | alarm.enabled = 0; | ||
452 | rtc_set_alarm(alarm_rtc_dev, &alarm); | ||
453 | |||
454 | spin_lock_irqsave(&alarm_slock, flags); | ||
455 | suspended = false; | ||
456 | update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP], false); | ||
457 | update_timer_locked(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP], | ||
458 | false); | ||
459 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
460 | |||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | static struct rtc_task alarm_rtc_task = { | ||
465 | .func = alarm_triggered_func | ||
466 | }; | ||
467 | |||
468 | static int rtc_alarm_add_device(struct device *dev, | ||
469 | struct class_interface *class_intf) | ||
470 | { | ||
471 | int err; | ||
472 | struct rtc_device *rtc = to_rtc_device(dev); | ||
473 | |||
474 | mutex_lock(&alarm_setrtc_mutex); | ||
475 | |||
476 | if (alarm_rtc_dev) { | ||
477 | err = -EBUSY; | ||
478 | goto err1; | ||
479 | } | ||
480 | |||
481 | alarm_platform_dev = | ||
482 | platform_device_register_simple("alarm", -1, NULL, 0); | ||
483 | if (IS_ERR(alarm_platform_dev)) { | ||
484 | err = PTR_ERR(alarm_platform_dev); | ||
485 | goto err2; | ||
486 | } | ||
487 | err = rtc_irq_register(rtc, &alarm_rtc_task); | ||
488 | if (err) | ||
489 | goto err3; | ||
490 | alarm_rtc_dev = rtc; | ||
491 | pr_alarm(INIT_STATUS, "using rtc device, %s, for alarms", rtc->name); | ||
492 | mutex_unlock(&alarm_setrtc_mutex); | ||
493 | |||
494 | return 0; | ||
495 | |||
496 | err3: | ||
497 | platform_device_unregister(alarm_platform_dev); | ||
498 | err2: | ||
499 | err1: | ||
500 | mutex_unlock(&alarm_setrtc_mutex); | ||
501 | return err; | ||
502 | } | ||
503 | |||
504 | static void rtc_alarm_remove_device(struct device *dev, | ||
505 | struct class_interface *class_intf) | ||
506 | { | ||
507 | if (dev == &alarm_rtc_dev->dev) { | ||
508 | pr_alarm(INIT_STATUS, "lost rtc device for alarms"); | ||
509 | rtc_irq_unregister(alarm_rtc_dev, &alarm_rtc_task); | ||
510 | platform_device_unregister(alarm_platform_dev); | ||
511 | alarm_rtc_dev = NULL; | ||
512 | } | ||
513 | } | ||
514 | |||
515 | static struct class_interface rtc_alarm_interface = { | ||
516 | .add_dev = &rtc_alarm_add_device, | ||
517 | .remove_dev = &rtc_alarm_remove_device, | ||
518 | }; | ||
519 | |||
520 | static struct platform_driver alarm_driver = { | ||
521 | .suspend = alarm_suspend, | ||
522 | .resume = alarm_resume, | ||
523 | .driver = { | ||
524 | .name = "alarm" | ||
525 | } | ||
526 | }; | ||
527 | |||
528 | static int __init alarm_late_init(void) | ||
529 | { | ||
530 | unsigned long flags; | ||
531 | struct timespec tmp_time, system_time; | ||
532 | |||
533 | /* this needs to run after the rtc is read at boot */ | ||
534 | spin_lock_irqsave(&alarm_slock, flags); | ||
535 | /* We read the current rtc and system time so we can later calulate | ||
536 | * elasped realtime to be (boot_systemtime + rtc - boot_rtc) == | ||
537 | * (rtc - (boot_rtc - boot_systemtime)) | ||
538 | */ | ||
539 | getnstimeofday(&tmp_time); | ||
540 | ktime_get_ts(&system_time); | ||
541 | alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta = | ||
542 | alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta = | ||
543 | timespec_to_ktime(timespec_sub(tmp_time, system_time)); | ||
544 | |||
545 | spin_unlock_irqrestore(&alarm_slock, flags); | ||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | static int __init alarm_driver_init(void) | ||
550 | { | ||
551 | int err; | ||
552 | int i; | ||
553 | |||
554 | for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) { | ||
555 | hrtimer_init(&alarms[i].timer, | ||
556 | CLOCK_REALTIME, HRTIMER_MODE_ABS); | ||
557 | alarms[i].timer.function = alarm_timer_triggered; | ||
558 | } | ||
559 | hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].timer, | ||
560 | CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | ||
561 | alarms[ANDROID_ALARM_SYSTEMTIME].timer.function = alarm_timer_triggered; | ||
562 | err = platform_driver_register(&alarm_driver); | ||
563 | if (err < 0) | ||
564 | goto err1; | ||
565 | wake_lock_init(&alarm_rtc_wake_lock, WAKE_LOCK_SUSPEND, "alarm_rtc"); | ||
566 | rtc_alarm_interface.class = rtc_class; | ||
567 | err = class_interface_register(&rtc_alarm_interface); | ||
568 | if (err < 0) | ||
569 | goto err2; | ||
570 | |||
571 | return 0; | ||
572 | |||
573 | err2: | ||
574 | wake_lock_destroy(&alarm_rtc_wake_lock); | ||
575 | platform_driver_unregister(&alarm_driver); | ||
576 | err1: | ||
577 | return err; | ||
578 | } | ||
579 | |||
580 | static void __exit alarm_exit(void) | ||
581 | { | ||
582 | class_interface_unregister(&rtc_alarm_interface); | ||
583 | wake_lock_destroy(&alarm_rtc_wake_lock); | ||
584 | platform_driver_unregister(&alarm_driver); | ||
585 | } | ||
586 | |||
587 | late_initcall(alarm_late_init); | ||
588 | module_init(alarm_driver_init); | ||
589 | module_exit(alarm_exit); | ||
590 | |||
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 4194e59e14c..b82a1554cdc 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
@@ -41,20 +41,41 @@ static void rtc_device_release(struct device *dev) | |||
41 | * system's wall clock; restore it on resume(). | 41 | * system's wall clock; restore it on resume(). |
42 | */ | 42 | */ |
43 | 43 | ||
44 | static time_t oldtime; | 44 | static struct timespec old_rtc, old_system, old_delta; |
45 | static struct timespec oldts; | 45 | |
46 | 46 | ||
47 | static int rtc_suspend(struct device *dev, pm_message_t mesg) | 47 | static int rtc_suspend(struct device *dev, pm_message_t mesg) |
48 | { | 48 | { |
49 | struct rtc_device *rtc = to_rtc_device(dev); | 49 | struct rtc_device *rtc = to_rtc_device(dev); |
50 | struct rtc_time tm; | 50 | struct rtc_time tm; |
51 | 51 | struct timespec delta, delta_delta; | |
52 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) | 52 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) |
53 | return 0; | 53 | return 0; |
54 | 54 | ||
55 | /* snapshot the current RTC and system time at suspend*/ | ||
55 | rtc_read_time(rtc, &tm); | 56 | rtc_read_time(rtc, &tm); |
56 | ktime_get_ts(&oldts); | 57 | getnstimeofday(&old_system); |
57 | rtc_tm_to_time(&tm, &oldtime); | 58 | rtc_tm_to_time(&tm, &old_rtc.tv_sec); |
59 | |||
60 | |||
61 | /* | ||
62 | * To avoid drift caused by repeated suspend/resumes, | ||
63 | * which each can add ~1 second drift error, | ||
64 | * try to compensate so the difference in system time | ||
65 | * and rtc time stays close to constant. | ||
66 | */ | ||
67 | delta = timespec_sub(old_system, old_rtc); | ||
68 | delta_delta = timespec_sub(delta, old_delta); | ||
69 | if (delta_delta.tv_sec < -2 || delta_delta.tv_sec >= 2) { | ||
70 | /* | ||
71 | * if delta_delta is too large, assume time correction | ||
72 | * has occured and set old_delta to the current delta. | ||
73 | */ | ||
74 | old_delta = delta; | ||
75 | } else { | ||
76 | /* Otherwise try to adjust old_system to compensate */ | ||
77 | old_system = timespec_sub(old_system, delta_delta); | ||
78 | } | ||
58 | 79 | ||
59 | return 0; | 80 | return 0; |
60 | } | 81 | } |
@@ -63,32 +84,42 @@ static int rtc_resume(struct device *dev) | |||
63 | { | 84 | { |
64 | struct rtc_device *rtc = to_rtc_device(dev); | 85 | struct rtc_device *rtc = to_rtc_device(dev); |
65 | struct rtc_time tm; | 86 | struct rtc_time tm; |
66 | time_t newtime; | 87 | struct timespec new_system, new_rtc; |
67 | struct timespec time; | 88 | struct timespec sleep_time; |
68 | struct timespec newts; | ||
69 | 89 | ||
70 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) | 90 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) |
71 | return 0; | 91 | return 0; |
72 | 92 | ||
73 | ktime_get_ts(&newts); | 93 | /* snapshot the current rtc and system time at resume */ |
94 | getnstimeofday(&new_system); | ||
74 | rtc_read_time(rtc, &tm); | 95 | rtc_read_time(rtc, &tm); |
75 | if (rtc_valid_tm(&tm) != 0) { | 96 | if (rtc_valid_tm(&tm) != 0) { |
76 | pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev)); | 97 | pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev)); |
77 | return 0; | 98 | return 0; |
78 | } | 99 | } |
79 | rtc_tm_to_time(&tm, &newtime); | 100 | rtc_tm_to_time(&tm, &new_rtc.tv_sec); |
80 | if (newtime <= oldtime) { | 101 | new_rtc.tv_nsec = 0; |
81 | if (newtime < oldtime) | 102 | |
82 | pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); | 103 | if (new_rtc.tv_sec < old_rtc.tv_sec) { |
104 | pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); | ||
83 | return 0; | 105 | return 0; |
84 | } | 106 | } |
85 | /* calculate the RTC time delta */ | ||
86 | set_normalized_timespec(&time, newtime - oldtime, 0); | ||
87 | |||
88 | /* subtract kernel time between rtc_suspend to rtc_resume */ | ||
89 | time = timespec_sub(time, timespec_sub(newts, oldts)); | ||
90 | 107 | ||
91 | timekeeping_inject_sleeptime(&time); | 108 | /* calculate the RTC time delta (sleep time)*/ |
109 | sleep_time = timespec_sub(new_rtc, old_rtc); | ||
110 | |||
111 | /* | ||
112 | * Since these RTC suspend/resume handlers are not called | ||
113 | * at the very end of suspend or the start of resume, | ||
114 | * some run-time may pass on either sides of the sleep time | ||
115 | * so subtract kernel run-time between rtc_suspend to rtc_resume | ||
116 | * to keep things accurate. | ||
117 | */ | ||
118 | sleep_time = timespec_sub(sleep_time, | ||
119 | timespec_sub(new_system, old_system)); | ||
120 | |||
121 | if (sleep_time.tv_sec >= 0) | ||
122 | timekeeping_inject_sleeptime(&sleep_time); | ||
92 | return 0; | 123 | return 0; |
93 | } | 124 | } |
94 | 125 | ||
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index df68618f6db..a86f3013747 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
@@ -227,11 +227,11 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
227 | alarm->time.tm_hour = now.tm_hour; | 227 | alarm->time.tm_hour = now.tm_hour; |
228 | 228 | ||
229 | /* For simplicity, only support date rollover for now */ | 229 | /* For simplicity, only support date rollover for now */ |
230 | if (alarm->time.tm_mday == -1) { | 230 | if (alarm->time.tm_mday < 1 || alarm->time.tm_mday > 31) { |
231 | alarm->time.tm_mday = now.tm_mday; | 231 | alarm->time.tm_mday = now.tm_mday; |
232 | missing = day; | 232 | missing = day; |
233 | } | 233 | } |
234 | if (alarm->time.tm_mon == -1) { | 234 | if ((unsigned)alarm->time.tm_mon >= 12) { |
235 | alarm->time.tm_mon = now.tm_mon; | 235 | alarm->time.tm_mon = now.tm_mon; |
236 | if (missing == none) | 236 | if (missing == none) |
237 | missing = month; | 237 | missing = month; |
@@ -636,6 +636,29 @@ void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task) | |||
636 | } | 636 | } |
637 | EXPORT_SYMBOL_GPL(rtc_irq_unregister); | 637 | EXPORT_SYMBOL_GPL(rtc_irq_unregister); |
638 | 638 | ||
639 | static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled) | ||
640 | { | ||
641 | /* | ||
642 | * We always cancel the timer here first, because otherwise | ||
643 | * we could run into BUG_ON(timer->state != HRTIMER_STATE_CALLBACK); | ||
644 | * when we manage to start the timer before the callback | ||
645 | * returns HRTIMER_RESTART. | ||
646 | * | ||
647 | * We cannot use hrtimer_cancel() here as a running callback | ||
648 | * could be blocked on rtc->irq_task_lock and hrtimer_cancel() | ||
649 | * would spin forever. | ||
650 | */ | ||
651 | if (hrtimer_try_to_cancel(&rtc->pie_timer) < 0) | ||
652 | return -1; | ||
653 | |||
654 | if (enabled) { | ||
655 | ktime_t period = ktime_set(0, NSEC_PER_SEC / rtc->irq_freq); | ||
656 | |||
657 | hrtimer_start(&rtc->pie_timer, period, HRTIMER_MODE_REL); | ||
658 | } | ||
659 | return 0; | ||
660 | } | ||
661 | |||
639 | /** | 662 | /** |
640 | * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs | 663 | * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs |
641 | * @rtc: the rtc device | 664 | * @rtc: the rtc device |
@@ -651,21 +674,21 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled | |||
651 | int err = 0; | 674 | int err = 0; |
652 | unsigned long flags; | 675 | unsigned long flags; |
653 | 676 | ||
677 | retry: | ||
654 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | 678 | spin_lock_irqsave(&rtc->irq_task_lock, flags); |
655 | if (rtc->irq_task != NULL && task == NULL) | 679 | if (rtc->irq_task != NULL && task == NULL) |
656 | err = -EBUSY; | 680 | err = -EBUSY; |
657 | if (rtc->irq_task != task) | 681 | if (rtc->irq_task != task) |
658 | err = -EACCES; | 682 | err = -EACCES; |
659 | 683 | if (!err) { | |
660 | if (enabled) { | 684 | if (rtc_update_hrtimer(rtc, enabled) < 0) { |
661 | ktime_t period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq); | 685 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); |
662 | hrtimer_start(&rtc->pie_timer, period, HRTIMER_MODE_REL); | 686 | cpu_relax(); |
663 | } else { | 687 | goto retry; |
664 | hrtimer_cancel(&rtc->pie_timer); | 688 | } |
689 | rtc->pie_enabled = enabled; | ||
665 | } | 690 | } |
666 | rtc->pie_enabled = enabled; | ||
667 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | 691 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); |
668 | |||
669 | return err; | 692 | return err; |
670 | } | 693 | } |
671 | EXPORT_SYMBOL_GPL(rtc_irq_set_state); | 694 | EXPORT_SYMBOL_GPL(rtc_irq_set_state); |
@@ -685,22 +708,20 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) | |||
685 | int err = 0; | 708 | int err = 0; |
686 | unsigned long flags; | 709 | unsigned long flags; |
687 | 710 | ||
688 | if (freq <= 0) | 711 | if (freq <= 0 || freq > RTC_MAX_FREQ) |
689 | return -EINVAL; | 712 | return -EINVAL; |
690 | 713 | retry: | |
691 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | 714 | spin_lock_irqsave(&rtc->irq_task_lock, flags); |
692 | if (rtc->irq_task != NULL && task == NULL) | 715 | if (rtc->irq_task != NULL && task == NULL) |
693 | err = -EBUSY; | 716 | err = -EBUSY; |
694 | if (rtc->irq_task != task) | 717 | if (rtc->irq_task != task) |
695 | err = -EACCES; | 718 | err = -EACCES; |
696 | if (err == 0) { | 719 | if (!err) { |
697 | rtc->irq_freq = freq; | 720 | rtc->irq_freq = freq; |
698 | if (rtc->pie_enabled) { | 721 | if (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0) { |
699 | ktime_t period; | 722 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); |
700 | hrtimer_cancel(&rtc->pie_timer); | 723 | cpu_relax(); |
701 | period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq); | 724 | goto retry; |
702 | hrtimer_start(&rtc->pie_timer, period, | ||
703 | HRTIMER_MODE_REL); | ||
704 | } | 725 | } |
705 | } | 726 | } |
706 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | 727 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); |
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c index e725d51e773..8dd08305aae 100644 --- a/drivers/rtc/rtc-at32ap700x.c +++ b/drivers/rtc/rtc-at32ap700x.c | |||
@@ -223,7 +223,7 @@ static int __init at32_rtc_probe(struct platform_device *pdev) | |||
223 | } | 223 | } |
224 | 224 | ||
225 | rtc->irq = irq; | 225 | rtc->irq = irq; |
226 | rtc->regs = ioremap(regs->start, regs->end - regs->start + 1); | 226 | rtc->regs = ioremap(regs->start, resource_size(regs)); |
227 | if (!rtc->regs) { | 227 | if (!rtc->regs) { |
228 | ret = -ENOMEM; | 228 | ret = -ENOMEM; |
229 | dev_dbg(&pdev->dev, "could not map I/O memory\n"); | 229 | dev_dbg(&pdev->dev, "could not map I/O memory\n"); |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 911e75cdc12..05beb6c1ca7 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -606,7 +606,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
606 | * (needing ioremap etc), not i/o space resources like this ... | 606 | * (needing ioremap etc), not i/o space resources like this ... |
607 | */ | 607 | */ |
608 | ports = request_region(ports->start, | 608 | ports = request_region(ports->start, |
609 | ports->end + 1 - ports->start, | 609 | resource_size(ports), |
610 | driver_name); | 610 | driver_name); |
611 | if (!ports) { | 611 | if (!ports) { |
612 | dev_dbg(dev, "i/o registers already in use\n"); | 612 | dev_dbg(dev, "i/o registers already in use\n"); |
@@ -750,7 +750,7 @@ cleanup1: | |||
750 | cmos_rtc.dev = NULL; | 750 | cmos_rtc.dev = NULL; |
751 | rtc_device_unregister(cmos_rtc.rtc); | 751 | rtc_device_unregister(cmos_rtc.rtc); |
752 | cleanup0: | 752 | cleanup0: |
753 | release_region(ports->start, ports->end + 1 - ports->start); | 753 | release_region(ports->start, resource_size(ports)); |
754 | return retval; | 754 | return retval; |
755 | } | 755 | } |
756 | 756 | ||
@@ -779,7 +779,7 @@ static void __exit cmos_do_remove(struct device *dev) | |||
779 | cmos->rtc = NULL; | 779 | cmos->rtc = NULL; |
780 | 780 | ||
781 | ports = cmos->iomem; | 781 | ports = cmos->iomem; |
782 | release_region(ports->start, ports->end + 1 - ports->start); | 782 | release_region(ports->start, resource_size(ports)); |
783 | cmos->iomem = NULL; | 783 | cmos->iomem = NULL; |
784 | 784 | ||
785 | cmos->dev = NULL; | 785 | cmos->dev = NULL; |
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c index 47e681df31e..68e6caf2549 100644 --- a/drivers/rtc/rtc-ds1286.c +++ b/drivers/rtc/rtc-ds1286.c | |||
@@ -343,7 +343,7 @@ static int __devinit ds1286_probe(struct platform_device *pdev) | |||
343 | if (!priv) | 343 | if (!priv) |
344 | return -ENOMEM; | 344 | return -ENOMEM; |
345 | 345 | ||
346 | priv->size = res->end - res->start + 1; | 346 | priv->size = resource_size(res); |
347 | if (!request_mem_region(res->start, priv->size, pdev->name)) { | 347 | if (!request_mem_region(res->start, priv->size, pdev->name)) { |
348 | ret = -EBUSY; | 348 | ret = -EBUSY; |
349 | goto out; | 349 | goto out; |
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index fbabc773dde..568ad30617e 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c | |||
@@ -490,7 +490,7 @@ ds1511_rtc_probe(struct platform_device *pdev) | |||
490 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | 490 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
491 | if (!pdata) | 491 | if (!pdata) |
492 | return -ENOMEM; | 492 | return -ENOMEM; |
493 | pdata->size = res->end - res->start + 1; | 493 | pdata->size = resource_size(res); |
494 | if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size, | 494 | if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size, |
495 | pdev->name)) | 495 | pdev->name)) |
496 | return -EBUSY; | 496 | return -EBUSY; |
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 042630c90dd..d84a448dd75 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
@@ -173,7 +173,7 @@ static int __devinit ds1742_rtc_probe(struct platform_device *pdev) | |||
173 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | 173 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
174 | if (!pdata) | 174 | if (!pdata) |
175 | return -ENOMEM; | 175 | return -ENOMEM; |
176 | pdata->size = res->end - res->start + 1; | 176 | pdata->size = resource_size(res); |
177 | if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size, | 177 | if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size, |
178 | pdev->name)) | 178 | pdev->name)) |
179 | return -EBUSY; | 179 | return -EBUSY; |
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c index 335551d333b..14a42a1edc6 100644 --- a/drivers/rtc/rtc-ep93xx.c +++ b/drivers/rtc/rtc-ep93xx.c | |||
@@ -36,6 +36,7 @@ | |||
36 | */ | 36 | */ |
37 | struct ep93xx_rtc { | 37 | struct ep93xx_rtc { |
38 | void __iomem *mmio_base; | 38 | void __iomem *mmio_base; |
39 | struct rtc_device *rtc; | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload, | 42 | static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload, |
@@ -130,7 +131,6 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev) | |||
130 | { | 131 | { |
131 | struct ep93xx_rtc *ep93xx_rtc; | 132 | struct ep93xx_rtc *ep93xx_rtc; |
132 | struct resource *res; | 133 | struct resource *res; |
133 | struct rtc_device *rtc; | ||
134 | int err; | 134 | int err; |
135 | 135 | ||
136 | ep93xx_rtc = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_rtc), GFP_KERNEL); | 136 | ep93xx_rtc = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_rtc), GFP_KERNEL); |
@@ -151,12 +151,12 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev) | |||
151 | return -ENXIO; | 151 | return -ENXIO; |
152 | 152 | ||
153 | pdev->dev.platform_data = ep93xx_rtc; | 153 | pdev->dev.platform_data = ep93xx_rtc; |
154 | platform_set_drvdata(pdev, rtc); | 154 | platform_set_drvdata(pdev, ep93xx_rtc); |
155 | 155 | ||
156 | rtc = rtc_device_register(pdev->name, | 156 | ep93xx_rtc->rtc = rtc_device_register(pdev->name, |
157 | &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE); | 157 | &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE); |
158 | if (IS_ERR(rtc)) { | 158 | if (IS_ERR(ep93xx_rtc->rtc)) { |
159 | err = PTR_ERR(rtc); | 159 | err = PTR_ERR(ep93xx_rtc->rtc); |
160 | goto exit; | 160 | goto exit; |
161 | } | 161 | } |
162 | 162 | ||
@@ -167,7 +167,7 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev) | |||
167 | return 0; | 167 | return 0; |
168 | 168 | ||
169 | fail: | 169 | fail: |
170 | rtc_device_unregister(rtc); | 170 | rtc_device_unregister(ep93xx_rtc->rtc); |
171 | exit: | 171 | exit: |
172 | platform_set_drvdata(pdev, NULL); | 172 | platform_set_drvdata(pdev, NULL); |
173 | pdev->dev.platform_data = NULL; | 173 | pdev->dev.platform_data = NULL; |
@@ -176,11 +176,11 @@ exit: | |||
176 | 176 | ||
177 | static int __exit ep93xx_rtc_remove(struct platform_device *pdev) | 177 | static int __exit ep93xx_rtc_remove(struct platform_device *pdev) |
178 | { | 178 | { |
179 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 179 | struct ep93xx_rtc *ep93xx_rtc = platform_get_drvdata(pdev); |
180 | 180 | ||
181 | sysfs_remove_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files); | 181 | sysfs_remove_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files); |
182 | platform_set_drvdata(pdev, NULL); | 182 | platform_set_drvdata(pdev, NULL); |
183 | rtc_device_unregister(rtc); | 183 | rtc_device_unregister(ep93xx_rtc->rtc); |
184 | pdev->dev.platform_data = NULL; | 184 | pdev->dev.platform_data = NULL; |
185 | 185 | ||
186 | return 0; | 186 | return 0; |
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 2dd3c016327..d93a9608b1f 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/rtc.h> | 37 | #include <linux/rtc.h> |
38 | #include <linux/sched.h> | ||
38 | #include <linux/workqueue.h> | 39 | #include <linux/workqueue.h> |
39 | 40 | ||
40 | /* DryIce Register Definitions */ | 41 | /* DryIce Register Definitions */ |
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c index 075f1708dea..c4cf0573111 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c | |||
@@ -85,6 +85,8 @@ void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) | |||
85 | time -= tm->tm_hour * 3600; | 85 | time -= tm->tm_hour * 3600; |
86 | tm->tm_min = time / 60; | 86 | tm->tm_min = time / 60; |
87 | tm->tm_sec = time - tm->tm_min * 60; | 87 | tm->tm_sec = time - tm->tm_min * 60; |
88 | |||
89 | tm->tm_isdst = 0; | ||
88 | } | 90 | } |
89 | EXPORT_SYMBOL(rtc_time_to_tm); | 91 | EXPORT_SYMBOL(rtc_time_to_tm); |
90 | 92 | ||
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index eda128fc1d3..64aedd8cc09 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c | |||
@@ -357,10 +357,19 @@ static int m41t80_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
357 | static struct rtc_class_ops m41t80_rtc_ops = { | 357 | static struct rtc_class_ops m41t80_rtc_ops = { |
358 | .read_time = m41t80_rtc_read_time, | 358 | .read_time = m41t80_rtc_read_time, |
359 | .set_time = m41t80_rtc_set_time, | 359 | .set_time = m41t80_rtc_set_time, |
360 | /* | ||
361 | * XXX - m41t80 alarm functionality is reported broken. | ||
362 | * until it is fixed, don't register alarm functions. | ||
363 | * | ||
360 | .read_alarm = m41t80_rtc_read_alarm, | 364 | .read_alarm = m41t80_rtc_read_alarm, |
361 | .set_alarm = m41t80_rtc_set_alarm, | 365 | .set_alarm = m41t80_rtc_set_alarm, |
366 | */ | ||
362 | .proc = m41t80_rtc_proc, | 367 | .proc = m41t80_rtc_proc, |
368 | /* | ||
369 | * See above comment on broken alarm | ||
370 | * | ||
363 | .alarm_irq_enable = m41t80_rtc_alarm_irq_enable, | 371 | .alarm_irq_enable = m41t80_rtc_alarm_irq_enable, |
372 | */ | ||
364 | }; | 373 | }; |
365 | 374 | ||
366 | #if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE) | 375 | #if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE) |
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c index 7410875e583..8e2a24e33ed 100644 --- a/drivers/rtc/rtc-m48t35.c +++ b/drivers/rtc/rtc-m48t35.c | |||
@@ -154,7 +154,7 @@ static int __devinit m48t35_probe(struct platform_device *pdev) | |||
154 | if (!priv) | 154 | if (!priv) |
155 | return -ENOMEM; | 155 | return -ENOMEM; |
156 | 156 | ||
157 | priv->size = res->end - res->start + 1; | 157 | priv->size = resource_size(res); |
158 | /* | 158 | /* |
159 | * kludge: remove the #ifndef after ioc3 resource | 159 | * kludge: remove the #ifndef after ioc3 resource |
160 | * conflicts are resolved | 160 | * conflicts are resolved |
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 3978f4caf72..28365388fb6 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c | |||
@@ -433,7 +433,7 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
433 | 433 | ||
434 | if (!m48t59->ioaddr) { | 434 | if (!m48t59->ioaddr) { |
435 | /* ioaddr not mapped externally */ | 435 | /* ioaddr not mapped externally */ |
436 | m48t59->ioaddr = ioremap(res->start, res->end - res->start + 1); | 436 | m48t59->ioaddr = ioremap(res->start, resource_size(res)); |
437 | if (!m48t59->ioaddr) | 437 | if (!m48t59->ioaddr) |
438 | goto out; | 438 | goto out; |
439 | } | 439 | } |
diff --git a/drivers/rtc/rtc-max77663.c b/drivers/rtc/rtc-max77663.c new file mode 100644 index 00000000000..874a2df86dc --- /dev/null +++ b/drivers/rtc/rtc-max77663.c | |||
@@ -0,0 +1,617 @@ | |||
1 | /* | ||
2 | * drivers/rtc/rtc-max77663.c | ||
3 | * Max77663 RTC driver | ||
4 | * | ||
5 | * Copyright 2011 Maxim Integrated Products, Inc. | ||
6 | * Copyright (C) 2011 NVIDIA Corporation | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License as | ||
10 | * published by the Free Software Foundation; either version 2 of the | ||
11 | * License, or (at your option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/rtc.h> | ||
20 | #include <linux/mfd/max77663-core.h> | ||
21 | |||
22 | /* RTC Registers */ | ||
23 | #define MAX77663_RTC_IRQ 0x00 | ||
24 | #define MAX77663_RTC_IRQ_MASK 0x01 | ||
25 | #define MAX77663_RTC_CTRL_MODE 0x02 | ||
26 | #define MAX77663_RTC_CTRL 0x03 | ||
27 | #define MAX77663_RTC_UPDATE0 0x04 | ||
28 | #define MAX77663_RTC_UPDATE1 0x05 | ||
29 | #define MAX77663_RTC_SEC 0x07 | ||
30 | #define MAX77663_RTC_MIN 0x08 | ||
31 | #define MAX77663_RTC_HOUR 0x09 | ||
32 | #define MAX77663_RTC_WEEKDAY 0x0A | ||
33 | #define MAX77663_RTC_MONTH 0x0B | ||
34 | #define MAX77663_RTC_YEAR 0x0C | ||
35 | #define MAX77663_RTC_MONTHDAY 0x0D | ||
36 | #define MAX77663_RTC_ALARM_SEC1 0x0E | ||
37 | #define MAX77663_RTC_ALARM_MIN1 0x0F | ||
38 | #define MAX77663_RTC_ALARM_HOUR1 0x10 | ||
39 | #define MAX77663_RTC_ALARM_WEEKDAY1 0x11 | ||
40 | #define MAX77663_RTC_ALARM_MONTH1 0x12 | ||
41 | #define MAX77663_RTC_ALARM_YEAR1 0x13 | ||
42 | #define MAX77663_RTC_ALARM_MONTHDAY1 0x14 | ||
43 | |||
44 | #define RTC_IRQ_60SEC_MASK (1 << 0) | ||
45 | #define RTC_IRQ_ALARM1_MASK (1 << 1) | ||
46 | #define RTC_IRQ_ALARM2_MASK (1 << 2) | ||
47 | #define RTC_IRQ_SMPL_MASK (1 << 3) | ||
48 | #define RTC_IRQ_1SEC_MASK (1 << 4) | ||
49 | #define RTC_IRQ_MASK 0x1F | ||
50 | |||
51 | #define BCD_MODE_MASK (1 << 0) | ||
52 | #define HR_MODE_MASK (1 << 1) | ||
53 | |||
54 | #define WB_UPDATE_MASK (1 << 0) | ||
55 | #define FLAG_AUTO_CLEAR_MASK (1 << 1) | ||
56 | #define FREEZE_SEC_MASK (1 << 2) | ||
57 | #define RTC_WAKE_MASK (1 << 3) | ||
58 | #define RB_UPDATE_MASK (1 << 4) | ||
59 | |||
60 | #define WB_UPDATE_FLAG_MASK (1 << 0) | ||
61 | #define RB_UPDATE_FLAG_MASK (1 << 1) | ||
62 | |||
63 | #define SEC_MASK 0x7F | ||
64 | #define MIN_MASK 0x7F | ||
65 | #define HOUR_MASK 0x3F | ||
66 | #define WEEKDAY_MASK 0x7F | ||
67 | #define MONTH_MASK 0x1F | ||
68 | #define YEAR_MASK 0xFF | ||
69 | #define MONTHDAY_MASK 0x3F | ||
70 | |||
71 | #define ALARM_EN_MASK 0x80 | ||
72 | #define ALARM_EN_SHIFT 7 | ||
73 | |||
74 | #define RTC_YEAR_BASE 100 | ||
75 | #define RTC_YEAR_MAX 99 | ||
76 | |||
77 | /* ON/OFF Registers */ | ||
78 | #define MAX77663_REG_ONOFF_CFG2 0x42 | ||
79 | |||
80 | #define ONOFF_WK_ALARM1_MASK (1 << 2) | ||
81 | |||
82 | enum { | ||
83 | RTC_SEC, | ||
84 | RTC_MIN, | ||
85 | RTC_HOUR, | ||
86 | RTC_WEEKDAY, | ||
87 | RTC_MONTH, | ||
88 | RTC_YEAR, | ||
89 | RTC_MONTHDAY, | ||
90 | RTC_NR | ||
91 | }; | ||
92 | |||
93 | struct max77663_rtc { | ||
94 | struct rtc_device *rtc; | ||
95 | struct device *dev; | ||
96 | |||
97 | struct mutex io_lock; | ||
98 | int irq; | ||
99 | u8 irq_mask; | ||
100 | }; | ||
101 | |||
102 | static inline struct device *_to_parent(struct max77663_rtc *rtc) | ||
103 | { | ||
104 | return rtc->dev->parent; | ||
105 | } | ||
106 | |||
107 | static inline int max77663_rtc_update_buffer(struct max77663_rtc *rtc, | ||
108 | int write) | ||
109 | { | ||
110 | struct device *parent = _to_parent(rtc); | ||
111 | u8 val = FLAG_AUTO_CLEAR_MASK | RTC_WAKE_MASK; | ||
112 | int ret; | ||
113 | |||
114 | if (write) | ||
115 | val |= WB_UPDATE_MASK; | ||
116 | else | ||
117 | val |= RB_UPDATE_MASK; | ||
118 | |||
119 | dev_dbg(rtc->dev, "rtc_update_buffer: write=%d, addr=0x%x, val=0x%x\n", | ||
120 | write, MAX77663_RTC_UPDATE0, val); | ||
121 | ret = max77663_write(parent, MAX77663_RTC_UPDATE0, &val, 1, 1); | ||
122 | if (ret < 0) { | ||
123 | dev_err(rtc->dev, "rtc_update_buffer: " | ||
124 | "Failed to get rtc update0\n"); | ||
125 | return ret; | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * Must wait 14ms for buffer update. | ||
130 | * If the sleeping time is 10us - 20ms, usleep_range() is recommended. | ||
131 | * Please refer Documentation/timers/timers-howto.txt. | ||
132 | */ | ||
133 | usleep_range(14000, 14000); | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static inline int max77663_rtc_write(struct max77663_rtc *rtc, u8 addr, | ||
139 | void *values, u32 len, int update_buffer) | ||
140 | { | ||
141 | struct device *parent = _to_parent(rtc); | ||
142 | int ret; | ||
143 | |||
144 | mutex_lock(&rtc->io_lock); | ||
145 | |||
146 | dev_dbg(rtc->dev, "rtc_write: addr=0x%x, values=0x%x, len=%u, " | ||
147 | "update_buffer=%d\n", | ||
148 | addr, *((u8 *)values), len, update_buffer); | ||
149 | ret = max77663_write(parent, addr, values, len, 1); | ||
150 | if (ret < 0) | ||
151 | goto out; | ||
152 | |||
153 | if (update_buffer) | ||
154 | ret = max77663_rtc_update_buffer(rtc, 1); | ||
155 | |||
156 | out: | ||
157 | mutex_unlock(&rtc->io_lock); | ||
158 | return ret; | ||
159 | } | ||
160 | |||
161 | static inline int max77663_rtc_read(struct max77663_rtc *rtc, u8 addr, | ||
162 | void *values, u32 len, int update_buffer) | ||
163 | { | ||
164 | struct device *parent = _to_parent(rtc); | ||
165 | int ret; | ||
166 | |||
167 | mutex_lock(&rtc->io_lock); | ||
168 | |||
169 | if (update_buffer) { | ||
170 | ret = max77663_rtc_update_buffer(rtc, 0); | ||
171 | if (ret < 0) | ||
172 | goto out; | ||
173 | } | ||
174 | |||
175 | ret = max77663_read(parent, addr, values, len, 1); | ||
176 | dev_dbg(rtc->dev, "rtc_read: addr=0x%x, values=0x%x, len=%u, " | ||
177 | "update_buffer=%d\n", | ||
178 | addr, *((u8 *)values), len, update_buffer); | ||
179 | |||
180 | out: | ||
181 | mutex_unlock(&rtc->io_lock); | ||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | static inline int max77663_rtc_reg_to_tm(struct max77663_rtc *rtc, u8 *buf, | ||
186 | struct rtc_time *tm) | ||
187 | { | ||
188 | int wday = buf[RTC_WEEKDAY] & WEEKDAY_MASK; | ||
189 | |||
190 | if (unlikely(!wday)) { | ||
191 | dev_err(rtc->dev, | ||
192 | "rtc_reg_to_tm: Invalid day of week, %d\n", wday); | ||
193 | return -EINVAL; | ||
194 | } | ||
195 | |||
196 | tm->tm_sec = (int)(buf[RTC_SEC] & SEC_MASK); | ||
197 | tm->tm_min = (int)(buf[RTC_MIN] & MIN_MASK); | ||
198 | tm->tm_hour = (int)(buf[RTC_HOUR] & HOUR_MASK); | ||
199 | tm->tm_mday = (int)(buf[RTC_MONTHDAY] & MONTHDAY_MASK); | ||
200 | tm->tm_mon = (int)(buf[RTC_MONTH] & MONTH_MASK) - 1; | ||
201 | tm->tm_year = (int)(buf[RTC_YEAR] & YEAR_MASK) + RTC_YEAR_BASE; | ||
202 | tm->tm_wday = ffs(wday) - 1; | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | static inline int max77663_rtc_tm_to_reg(struct max77663_rtc *rtc, u8 *buf, | ||
208 | struct rtc_time *tm, int alarm) | ||
209 | { | ||
210 | u8 alarm_mask = alarm ? ALARM_EN_MASK : 0; | ||
211 | |||
212 | if (unlikely((tm->tm_year < RTC_YEAR_BASE) || | ||
213 | (tm->tm_year > RTC_YEAR_BASE + RTC_YEAR_MAX))) { | ||
214 | dev_err(rtc->dev, | ||
215 | "rtc_tm_to_reg: Invalid year, %d\n", tm->tm_year); | ||
216 | return -EINVAL; | ||
217 | } | ||
218 | |||
219 | buf[RTC_SEC] = tm->tm_sec | alarm_mask; | ||
220 | buf[RTC_MIN] = tm->tm_min | alarm_mask; | ||
221 | buf[RTC_HOUR] = tm->tm_hour | alarm_mask; | ||
222 | buf[RTC_MONTHDAY] = tm->tm_mday | alarm_mask; | ||
223 | buf[RTC_MONTH] = (tm->tm_mon + 1) | alarm_mask; | ||
224 | buf[RTC_YEAR] = (tm->tm_year - RTC_YEAR_BASE) | alarm_mask; | ||
225 | |||
226 | /* The wday is configured only when disabled alarm. */ | ||
227 | if (!alarm) | ||
228 | buf[RTC_WEEKDAY] = (1 << tm->tm_wday); | ||
229 | else | ||
230 | buf[RTC_WEEKDAY] = 0; | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static inline int max77663_rtc_irq_mask(struct max77663_rtc *rtc, u8 irq) | ||
236 | { | ||
237 | struct device *parent = _to_parent(rtc); | ||
238 | u8 irq_mask = rtc->irq_mask | irq; | ||
239 | int ret = 0; | ||
240 | |||
241 | ret = max77663_write(parent, MAX77663_RTC_IRQ_MASK, &irq_mask, 1, 1); | ||
242 | if (ret < 0) { | ||
243 | dev_err(rtc->dev, "rtc_irq_mask: Failed to set rtc irq mask\n"); | ||
244 | goto out; | ||
245 | } | ||
246 | rtc->irq_mask = irq_mask; | ||
247 | |||
248 | out: | ||
249 | return ret; | ||
250 | } | ||
251 | |||
252 | static inline int max77663_rtc_irq_unmask(struct max77663_rtc *rtc, u8 irq) | ||
253 | { | ||
254 | struct device *parent = _to_parent(rtc); | ||
255 | u8 irq_mask = rtc->irq_mask & ~irq; | ||
256 | int ret = 0; | ||
257 | |||
258 | ret = max77663_write(parent, MAX77663_RTC_IRQ_MASK, &irq_mask, 1, 1); | ||
259 | if (ret < 0) { | ||
260 | dev_err(rtc->dev, | ||
261 | "rtc_irq_unmask: Failed to set rtc irq mask\n"); | ||
262 | goto out; | ||
263 | } | ||
264 | rtc->irq_mask = irq_mask; | ||
265 | |||
266 | out: | ||
267 | return ret; | ||
268 | } | ||
269 | |||
270 | static inline int max77663_rtc_do_irq(struct max77663_rtc *rtc) | ||
271 | { | ||
272 | struct device *parent = _to_parent(rtc); | ||
273 | u8 irq_status; | ||
274 | int ret; | ||
275 | |||
276 | ret = max77663_rtc_update_buffer(rtc, 0); | ||
277 | if (ret < 0) { | ||
278 | dev_err(rtc->dev, "rtc_irq: Failed to get rtc update buffer\n"); | ||
279 | return ret; | ||
280 | } | ||
281 | |||
282 | ret = max77663_read(parent, MAX77663_RTC_IRQ, &irq_status, 1, 1); | ||
283 | if (ret < 0) { | ||
284 | dev_err(rtc->dev, "rtc_irq: Failed to get rtc irq status\n"); | ||
285 | return ret; | ||
286 | } | ||
287 | |||
288 | dev_dbg(rtc->dev, "rtc_do_irq: irq_mask=0x%02x, irq_status=0x%02x\n", | ||
289 | rtc->irq_mask, irq_status); | ||
290 | |||
291 | if (!(rtc->irq_mask & RTC_IRQ_ALARM1_MASK) && | ||
292 | (irq_status & RTC_IRQ_ALARM1_MASK)) | ||
293 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); | ||
294 | |||
295 | if (!(rtc->irq_mask & RTC_IRQ_1SEC_MASK) && | ||
296 | (irq_status & RTC_IRQ_1SEC_MASK)) | ||
297 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_UF); | ||
298 | |||
299 | return ret; | ||
300 | } | ||
301 | |||
302 | static irqreturn_t max77663_rtc_irq(int irq, void *data) | ||
303 | { | ||
304 | struct max77663_rtc *rtc = (struct max77663_rtc *)data; | ||
305 | |||
306 | max77663_rtc_do_irq(rtc); | ||
307 | |||
308 | return IRQ_HANDLED; | ||
309 | } | ||
310 | |||
311 | static int max77663_rtc_alarm_irq_enable(struct device *dev, | ||
312 | unsigned int enabled) | ||
313 | { | ||
314 | struct max77663_rtc *rtc = dev_get_drvdata(dev); | ||
315 | int ret = 0; | ||
316 | |||
317 | if (rtc->irq < 0) | ||
318 | return -ENXIO; | ||
319 | |||
320 | mutex_lock(&rtc->io_lock); | ||
321 | |||
322 | /* Handle pending interrupt */ | ||
323 | ret = max77663_rtc_do_irq(rtc); | ||
324 | if (ret < 0) | ||
325 | goto out; | ||
326 | |||
327 | /* Config alarm interrupt */ | ||
328 | if (enabled) { | ||
329 | ret = max77663_rtc_irq_unmask(rtc, RTC_IRQ_ALARM1_MASK); | ||
330 | if (ret < 0) | ||
331 | goto out; | ||
332 | } else { | ||
333 | ret = max77663_rtc_irq_mask(rtc, RTC_IRQ_ALARM1_MASK); | ||
334 | if (ret < 0) | ||
335 | goto out; | ||
336 | } | ||
337 | out: | ||
338 | mutex_unlock(&rtc->io_lock); | ||
339 | return ret; | ||
340 | } | ||
341 | |||
342 | static int max77663_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
343 | { | ||
344 | struct max77663_rtc *rtc = dev_get_drvdata(dev); | ||
345 | u8 buf[RTC_NR]; | ||
346 | int ret; | ||
347 | |||
348 | ret = max77663_rtc_read(rtc, MAX77663_RTC_SEC, buf, sizeof(buf), 1); | ||
349 | if (ret < 0) { | ||
350 | dev_err(rtc->dev, "rtc_read_time: Failed to read rtc time\n"); | ||
351 | return ret; | ||
352 | } | ||
353 | |||
354 | dev_dbg(rtc->dev, "rtc_read_time: " | ||
355 | "buf: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
356 | buf[RTC_SEC], buf[RTC_MIN], buf[RTC_HOUR], buf[RTC_WEEKDAY], | ||
357 | buf[RTC_MONTH], buf[RTC_YEAR], buf[RTC_MONTHDAY]); | ||
358 | |||
359 | ret = max77663_rtc_reg_to_tm(rtc, buf, tm); | ||
360 | if (ret < 0) { | ||
361 | dev_err(rtc->dev, "rtc_read_time: " | ||
362 | "Failed to convert register format into time format\n"); | ||
363 | return ret; | ||
364 | } | ||
365 | |||
366 | dev_dbg(rtc->dev, "rtc_read_time: " | ||
367 | "tm: %d-%02d-%02d %02d:%02d:%02d, wday=%d\n", | ||
368 | tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, | ||
369 | tm->tm_sec, tm->tm_wday); | ||
370 | |||
371 | return ret; | ||
372 | } | ||
373 | |||
374 | static int max77663_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
375 | { | ||
376 | struct max77663_rtc *rtc = dev_get_drvdata(dev); | ||
377 | u8 buf[RTC_NR]; | ||
378 | int ret; | ||
379 | |||
380 | dev_dbg(rtc->dev, "rtc_set_time: " | ||
381 | "tm: %d-%02d-%02d %02d:%02d:%02d, wday=%d\n", | ||
382 | tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, | ||
383 | tm->tm_sec, tm->tm_wday); | ||
384 | |||
385 | ret = max77663_rtc_tm_to_reg(rtc, buf, tm, 0); | ||
386 | if (ret < 0) { | ||
387 | dev_err(rtc->dev, "rtc_set_time: " | ||
388 | "Failed to convert time format into register format\n"); | ||
389 | return ret; | ||
390 | } | ||
391 | |||
392 | dev_dbg(rtc->dev, "rtc_set_time: " | ||
393 | "buf: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
394 | buf[RTC_SEC], buf[RTC_MIN], buf[RTC_HOUR], buf[RTC_WEEKDAY], | ||
395 | buf[RTC_MONTH], buf[RTC_YEAR], buf[RTC_MONTHDAY]); | ||
396 | |||
397 | return max77663_rtc_write(rtc, MAX77663_RTC_SEC, buf, sizeof(buf), 1); | ||
398 | } | ||
399 | |||
400 | static int max77663_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
401 | { | ||
402 | struct max77663_rtc *rtc = dev_get_drvdata(dev); | ||
403 | u8 buf[RTC_NR]; | ||
404 | int ret; | ||
405 | |||
406 | ret = max77663_rtc_read(rtc, MAX77663_RTC_ALARM_SEC1, buf, sizeof(buf), | ||
407 | 1); | ||
408 | if (ret < 0) { | ||
409 | dev_err(rtc->dev, | ||
410 | "rtc_read_alarm: Failed to read rtc alarm time\n"); | ||
411 | return ret; | ||
412 | } | ||
413 | |||
414 | dev_dbg(rtc->dev, "rtc_read_alarm: " | ||
415 | "buf: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
416 | buf[RTC_SEC], buf[RTC_MIN], buf[RTC_HOUR], buf[RTC_WEEKDAY], | ||
417 | buf[RTC_MONTH], buf[RTC_YEAR], buf[RTC_MONTHDAY]); | ||
418 | |||
419 | ret = max77663_rtc_reg_to_tm(rtc, buf, &alrm->time); | ||
420 | if (ret < 0) { | ||
421 | dev_err(rtc->dev, "rtc_read_alarm: " | ||
422 | "Failed to convert register format into time format\n"); | ||
423 | return ret; | ||
424 | } | ||
425 | |||
426 | dev_dbg(rtc->dev, "rtc_read_alarm: " | ||
427 | "tm: %d-%02d-%02d %02d:%02d:%02d, wday=%d\n", | ||
428 | alrm->time.tm_year, alrm->time.tm_mon, alrm->time.tm_mday, | ||
429 | alrm->time.tm_hour, alrm->time.tm_min, alrm->time.tm_sec, | ||
430 | alrm->time.tm_wday); | ||
431 | |||
432 | if (rtc->irq_mask & RTC_IRQ_ALARM1_MASK) | ||
433 | alrm->enabled = 1; | ||
434 | else | ||
435 | alrm->enabled = 0; | ||
436 | |||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | static int max77663_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
441 | { | ||
442 | struct max77663_rtc *rtc = dev_get_drvdata(dev); | ||
443 | u8 buf[RTC_NR]; | ||
444 | int ret; | ||
445 | |||
446 | dev_dbg(rtc->dev, "rtc_set_alarm: " | ||
447 | "tm: %d-%02d-%02d %02d:%02d:%02d, wday=%d [%s]\n", | ||
448 | alrm->time.tm_year, alrm->time.tm_mon, alrm->time.tm_mday, | ||
449 | alrm->time.tm_hour, alrm->time.tm_min, alrm->time.tm_sec, | ||
450 | alrm->time.tm_wday, alrm->enabled?"enable":"disable"); | ||
451 | |||
452 | ret = max77663_rtc_tm_to_reg(rtc, buf, &alrm->time, 1); | ||
453 | if (ret < 0) { | ||
454 | dev_err(rtc->dev, "rtc_set_alarm: " | ||
455 | "Failed to convert time format into register format\n"); | ||
456 | return ret; | ||
457 | } | ||
458 | |||
459 | dev_dbg(rtc->dev, "rtc_set_alarm: " | ||
460 | "buf: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
461 | buf[RTC_SEC], buf[RTC_MIN], buf[RTC_HOUR], buf[RTC_WEEKDAY], | ||
462 | buf[RTC_MONTH], buf[RTC_YEAR], buf[RTC_MONTHDAY]); | ||
463 | |||
464 | ret = max77663_rtc_write(rtc, MAX77663_RTC_ALARM_SEC1, buf, sizeof(buf), | ||
465 | 1); | ||
466 | if (ret < 0) { | ||
467 | dev_err(rtc->dev, | ||
468 | "rtc_set_alarm: Failed to write rtc alarm time\n"); | ||
469 | return ret; | ||
470 | } | ||
471 | |||
472 | ret = max77663_rtc_alarm_irq_enable(dev, alrm->enabled); | ||
473 | if (ret < 0) { | ||
474 | dev_err(rtc->dev, | ||
475 | "rtc_set_alarm: Failed to enable rtc alarm\n"); | ||
476 | return ret; | ||
477 | } | ||
478 | |||
479 | return ret; | ||
480 | } | ||
481 | |||
482 | static const struct rtc_class_ops max77663_rtc_ops = { | ||
483 | .read_time = max77663_rtc_read_time, | ||
484 | .set_time = max77663_rtc_set_time, | ||
485 | .read_alarm = max77663_rtc_read_alarm, | ||
486 | .set_alarm = max77663_rtc_set_alarm, | ||
487 | .alarm_irq_enable = max77663_rtc_alarm_irq_enable, | ||
488 | }; | ||
489 | |||
490 | static int max77663_rtc_preinit(struct max77663_rtc *rtc) | ||
491 | { | ||
492 | struct device *parent = _to_parent(rtc); | ||
493 | u8 val; | ||
494 | int ret; | ||
495 | |||
496 | /* Mask all interrupts */ | ||
497 | rtc->irq_mask = 0xFF; | ||
498 | ret = max77663_rtc_write(rtc, MAX77663_RTC_IRQ_MASK, &rtc->irq_mask, 1, | ||
499 | 0); | ||
500 | if (ret < 0) { | ||
501 | dev_err(rtc->dev, "preinit: Failed to set rtc irq mask\n"); | ||
502 | return ret; | ||
503 | } | ||
504 | |||
505 | /* Configure Binary mode and 24hour mode */ | ||
506 | val = HR_MODE_MASK; | ||
507 | ret = max77663_rtc_write(rtc, MAX77663_RTC_CTRL, &val, 1, 0); | ||
508 | if (ret < 0) { | ||
509 | dev_err(rtc->dev, "preinit: Failed to set rtc control\n"); | ||
510 | return ret; | ||
511 | } | ||
512 | |||
513 | /* It should be disabled alarm wakeup to wakeup from sleep | ||
514 | * by EN1 input signal */ | ||
515 | ret = max77663_set_bits(parent, MAX77663_REG_ONOFF_CFG2, | ||
516 | ONOFF_WK_ALARM1_MASK, 0, 0); | ||
517 | if (ret < 0) { | ||
518 | dev_err(rtc->dev, "preinit: Failed to set onoff cfg2\n"); | ||
519 | return ret; | ||
520 | } | ||
521 | |||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static int max77663_rtc_probe(struct platform_device *pdev) | ||
526 | { | ||
527 | struct max77663_platform_data *parent_pdata = | ||
528 | pdev->dev.parent->platform_data; | ||
529 | static struct max77663_rtc *rtc; | ||
530 | int ret = 0; | ||
531 | |||
532 | rtc = kzalloc(sizeof(struct max77663_rtc), GFP_KERNEL); | ||
533 | if (!rtc) { | ||
534 | dev_err(&pdev->dev, "probe: kzalloc() failed\n"); | ||
535 | return -ENOMEM; | ||
536 | } | ||
537 | |||
538 | dev_set_drvdata(&pdev->dev, rtc); | ||
539 | rtc->dev = &pdev->dev; | ||
540 | mutex_init(&rtc->io_lock); | ||
541 | |||
542 | ret = max77663_rtc_preinit(rtc); | ||
543 | if (ret) { | ||
544 | dev_err(&pdev->dev, "probe: Failed to rtc preinit\n"); | ||
545 | goto out_kfree; | ||
546 | } | ||
547 | |||
548 | rtc->rtc = rtc_device_register("max77663-rtc", &pdev->dev, | ||
549 | &max77663_rtc_ops, THIS_MODULE); | ||
550 | if (IS_ERR_OR_NULL(rtc->rtc)) { | ||
551 | dev_err(&pdev->dev, "probe: Failed to register rtc\n"); | ||
552 | ret = PTR_ERR(rtc->rtc); | ||
553 | goto out_kfree; | ||
554 | } | ||
555 | |||
556 | if (parent_pdata->irq_base < 0) | ||
557 | goto out; | ||
558 | |||
559 | rtc->irq = parent_pdata->irq_base + MAX77663_IRQ_RTC; | ||
560 | ret = request_threaded_irq(rtc->irq, NULL, max77663_rtc_irq, | ||
561 | IRQF_ONESHOT, "max77663-rtc", rtc); | ||
562 | if (ret < 0) { | ||
563 | dev_err(rtc->dev, "probe: Failed to request irq %d\n", | ||
564 | rtc->irq); | ||
565 | rtc->irq = -1; | ||
566 | } else { | ||
567 | device_init_wakeup(rtc->dev, 1); | ||
568 | enable_irq_wake(rtc->irq); | ||
569 | } | ||
570 | |||
571 | return 0; | ||
572 | |||
573 | out_kfree: | ||
574 | mutex_destroy(&rtc->io_lock); | ||
575 | kfree(rtc->rtc); | ||
576 | out: | ||
577 | return ret; | ||
578 | } | ||
579 | |||
580 | static int __devexit max77663_rtc_remove(struct platform_device *pdev) | ||
581 | { | ||
582 | struct max77663_rtc *rtc = dev_get_drvdata(&pdev->dev); | ||
583 | |||
584 | if (rtc->irq != -1) | ||
585 | free_irq(rtc->irq, rtc); | ||
586 | |||
587 | rtc_device_unregister(rtc->rtc); | ||
588 | mutex_destroy(&rtc->io_lock); | ||
589 | kfree(rtc); | ||
590 | |||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | static struct platform_driver max77663_rtc_driver = { | ||
595 | .probe = max77663_rtc_probe, | ||
596 | .remove = __devexit_p(max77663_rtc_remove), | ||
597 | .driver = { | ||
598 | .name = "max77663-rtc", | ||
599 | .owner = THIS_MODULE, | ||
600 | }, | ||
601 | }; | ||
602 | |||
603 | static int __init max77663_rtc_init(void) | ||
604 | { | ||
605 | return platform_driver_register(&max77663_rtc_driver); | ||
606 | } | ||
607 | module_init(max77663_rtc_init); | ||
608 | |||
609 | static void __exit max77663_rtc_exit(void) | ||
610 | { | ||
611 | platform_driver_unregister(&max77663_rtc_driver); | ||
612 | } | ||
613 | module_exit(max77663_rtc_exit); | ||
614 | |||
615 | MODULE_DESCRIPTION("max77663 RTC driver"); | ||
616 | MODULE_LICENSE("GPL v2"); | ||
617 | MODULE_VERSION("1.0"); | ||
diff --git a/drivers/rtc/rtc-max8907c.c b/drivers/rtc/rtc-max8907c.c new file mode 100644 index 00000000000..f7287021da3 --- /dev/null +++ b/drivers/rtc/rtc-max8907c.c | |||
@@ -0,0 +1,323 @@ | |||
1 | /* | ||
2 | * RTC driver for Maxim MAX8907c | ||
3 | * | ||
4 | * Copyright (c) 2011, NVIDIA Corporation. | ||
5 | * Based on drivers/rtc/rtc-max8925.c, Copyright (C) 2009-2010 Marvell International Ltd. | ||
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/max8907c.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 TIME_NUM 8 | ||
31 | #define ALARM_1SEC (1 << 7) | ||
32 | #define HOUR_12 (1 << 7) | ||
33 | #define HOUR_AM_PM (1 << 5) | ||
34 | #define ALARM0_IRQ (1 << 3) | ||
35 | #define ALARM1_IRQ (1 << 2) | ||
36 | #define ALARM0_STATUS (1 << 2) | ||
37 | #define ALARM1_STATUS (1 << 1) | ||
38 | |||
39 | struct max8907c_rtc_info { | ||
40 | struct rtc_device *rtc_dev; | ||
41 | struct i2c_client *i2c; | ||
42 | struct max8907c *chip; | ||
43 | }; | ||
44 | |||
45 | static irqreturn_t rtc_update_handler(int irq, void *data) | ||
46 | { | ||
47 | struct max8907c_rtc_info *info = (struct max8907c_rtc_info *)data; | ||
48 | |||
49 | /* disable ALARM0 except for 1SEC alarm */ | ||
50 | max8907c_set_bits(info->i2c, MAX8907C_REG_ALARM0_CNTL, 0x7f, 0); | ||
51 | rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); | ||
52 | return IRQ_HANDLED; | ||
53 | } | ||
54 | |||
55 | static int tm_calc(struct rtc_time *tm, u8 *buf, int len) | ||
56 | { | ||
57 | if (len < TIME_NUM) | ||
58 | return -EINVAL; | ||
59 | tm->tm_year = (buf[RTC_YEAR2] >> 4) * 1000 | ||
60 | + (buf[RTC_YEAR2] & 0xf) * 100 | ||
61 | + (buf[RTC_YEAR1] >> 4) * 10 | ||
62 | + (buf[RTC_YEAR1] & 0xf); | ||
63 | tm->tm_year -= 1900; | ||
64 | /* RTC month index issue in max8907c | ||
65 | : January index is 1 but kernel assumes it as 0 */ | ||
66 | tm->tm_mon = ((buf[RTC_MONTH] >> 4) & 0x01) * 10 | ||
67 | + (buf[RTC_MONTH] & 0x0f) - 1; | ||
68 | tm->tm_mday = ((buf[RTC_DATE] >> 4) & 0x03) * 10 | ||
69 | + (buf[RTC_DATE] & 0x0f); | ||
70 | tm->tm_wday = buf[RTC_WEEKDAY] & 0x07; | ||
71 | if (buf[RTC_HOUR] & HOUR_12) { | ||
72 | tm->tm_hour = ((buf[RTC_HOUR] >> 4) & 0x1) * 10 | ||
73 | + (buf[RTC_HOUR] & 0x0f); | ||
74 | if (buf[RTC_HOUR] & HOUR_AM_PM) | ||
75 | tm->tm_hour += 12; | ||
76 | } else { | ||
77 | tm->tm_hour = ((buf[RTC_HOUR] >> 4) & 0x03) * 10 | ||
78 | + (buf[RTC_HOUR] & 0x0f); | ||
79 | } | ||
80 | tm->tm_min = ((buf[RTC_MIN] >> 4) & 0x7) * 10 | ||
81 | + (buf[RTC_MIN] & 0x0f); | ||
82 | tm->tm_sec = ((buf[RTC_SEC] >> 4) & 0x7) * 10 | ||
83 | + (buf[RTC_SEC] & 0x0f); | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int data_calc(u8 *buf, struct rtc_time *tm, int len) | ||
88 | { | ||
89 | u8 high, low; | ||
90 | |||
91 | if (len < TIME_NUM) | ||
92 | return -EINVAL; | ||
93 | |||
94 | high = (tm->tm_year + 1900) / 1000; | ||
95 | low = (tm->tm_year + 1900) / 100; | ||
96 | low = low - high * 10; | ||
97 | buf[RTC_YEAR2] = (high << 4) + low; | ||
98 | high = (tm->tm_year + 1900) / 10; | ||
99 | low = tm->tm_year + 1900; | ||
100 | low = low - high * 10; | ||
101 | high = high - (high / 10) * 10; | ||
102 | buf[RTC_YEAR1] = (high << 4) + low; | ||
103 | |||
104 | /* RTC month index issue in max8907c | ||
105 | : January index is 1 but kernel assumes it as 0 */ | ||
106 | high = (tm->tm_mon + 1) / 10; | ||
107 | low = (tm->tm_mon + 1) % 10; | ||
108 | buf[RTC_MONTH] = (high << 4) + low; | ||
109 | |||
110 | high = tm->tm_mday / 10; | ||
111 | low = tm->tm_mday; | ||
112 | low = low - high * 10; | ||
113 | buf[RTC_DATE] = (high << 4) + low; | ||
114 | buf[RTC_WEEKDAY] = tm->tm_wday; | ||
115 | high = tm->tm_hour / 10; | ||
116 | low = tm->tm_hour; | ||
117 | low = low - high * 10; | ||
118 | buf[RTC_HOUR] = (high << 4) + low; | ||
119 | high = tm->tm_min / 10; | ||
120 | low = tm->tm_min; | ||
121 | low = low - high * 10; | ||
122 | buf[RTC_MIN] = (high << 4) + low; | ||
123 | high = tm->tm_sec / 10; | ||
124 | low = tm->tm_sec; | ||
125 | low = low - high * 10; | ||
126 | buf[RTC_SEC] = (high << 4) + low; | ||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static int max8907c_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
131 | { | ||
132 | struct max8907c_rtc_info *info = dev_get_drvdata(dev); | ||
133 | u8 buf[TIME_NUM]; | ||
134 | int ret; | ||
135 | |||
136 | ret = max8907c_reg_bulk_read(info->i2c, MAX8907C_REG_RTC_SEC, TIME_NUM, buf); | ||
137 | |||
138 | if (ret < 0) | ||
139 | return ret; | ||
140 | ret = tm_calc(tm, buf, TIME_NUM); | ||
141 | |||
142 | return ret; | ||
143 | } | ||
144 | |||
145 | static int max8907c_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
146 | { | ||
147 | struct max8907c_rtc_info *info = dev_get_drvdata(dev); | ||
148 | u8 buf[TIME_NUM]; | ||
149 | int ret; | ||
150 | |||
151 | ret = data_calc(buf, tm, TIME_NUM); | ||
152 | |||
153 | if (ret < 0) | ||
154 | return ret; | ||
155 | ret = max8907c_reg_bulk_write(info->i2c, MAX8907C_REG_RTC_SEC, TIME_NUM, buf); | ||
156 | |||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | static int max8907c_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
161 | { | ||
162 | struct max8907c_rtc_info *info = dev_get_drvdata(dev); | ||
163 | unsigned char buf[TIME_NUM]; | ||
164 | int ret; | ||
165 | |||
166 | ret = max8907c_reg_bulk_read(info->i2c, MAX8907C_REG_ALARM0_SEC, TIME_NUM, buf); | ||
167 | if (ret < 0) | ||
168 | return ret; | ||
169 | ret = tm_calc(&alrm->time, buf, TIME_NUM); | ||
170 | if (ret < 0) | ||
171 | return ret; | ||
172 | ret = max8907c_reg_read(info->i2c, MAX8907C_REG_RTC_IRQ_MASK); | ||
173 | if (ret < 0) | ||
174 | return ret; | ||
175 | if ((ret & ALARM0_IRQ) == 0) | ||
176 | alrm->enabled = 1; | ||
177 | else | ||
178 | alrm->enabled = 0; | ||
179 | ret = max8907c_reg_read(info->i2c, MAX8907C_REG_RTC_STATUS); | ||
180 | if (ret < 0) | ||
181 | return ret; | ||
182 | if (ret & ALARM0_STATUS) | ||
183 | alrm->pending = 1; | ||
184 | else | ||
185 | alrm->pending = 0; | ||
186 | |||
187 | return ret; | ||
188 | } | ||
189 | |||
190 | static int max8907c_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
191 | { | ||
192 | struct max8907c_rtc_info *info = dev_get_drvdata(dev); | ||
193 | unsigned char buf[TIME_NUM]; | ||
194 | int ret; | ||
195 | |||
196 | ret = data_calc(buf, &alrm->time, TIME_NUM); | ||
197 | if (ret < 0) | ||
198 | return ret; | ||
199 | ret = max8907c_reg_bulk_write(info->i2c, MAX8907C_REG_ALARM0_SEC, TIME_NUM, buf); | ||
200 | if (ret < 0) | ||
201 | return ret; | ||
202 | /* only enable alarm on year/month/day/hour/min/sec */ | ||
203 | ret = max8907c_reg_write(info->i2c, MAX8907C_REG_ALARM0_CNTL, 0x77); | ||
204 | |||
205 | return ret; | ||
206 | } | ||
207 | |||
208 | static const struct rtc_class_ops max8907c_rtc_ops = { | ||
209 | .read_time = max8907c_rtc_read_time, | ||
210 | .set_time = max8907c_rtc_set_time, | ||
211 | .read_alarm = max8907c_rtc_read_alarm, | ||
212 | .set_alarm = max8907c_rtc_set_alarm, | ||
213 | }; | ||
214 | |||
215 | static int __devinit max8907c_rtc_probe(struct platform_device *pdev) | ||
216 | { | ||
217 | struct max8907c *chip = dev_get_drvdata(pdev->dev.parent); | ||
218 | struct max8907c_rtc_info *info; | ||
219 | int irq, ret; | ||
220 | |||
221 | info = kzalloc(sizeof(struct max8907c_rtc_info), GFP_KERNEL); | ||
222 | if (!info) | ||
223 | return -ENOMEM; | ||
224 | info->i2c = chip->i2c_rtc; | ||
225 | info->chip = chip; | ||
226 | |||
227 | irq = chip->irq_base + MAX8907C_IRQ_RTC_ALARM0; | ||
228 | |||
229 | ret = request_threaded_irq(irq, NULL, rtc_update_handler, | ||
230 | IRQF_ONESHOT, "rtc-alarm0", info); | ||
231 | if (ret < 0) { | ||
232 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", | ||
233 | irq, ret); | ||
234 | goto out_irq; | ||
235 | } | ||
236 | |||
237 | dev_set_drvdata(&pdev->dev, info); | ||
238 | info->rtc_dev = rtc_device_register("max8907c-rtc", &pdev->dev, | ||
239 | &max8907c_rtc_ops, THIS_MODULE); | ||
240 | ret = PTR_ERR(info->rtc_dev); | ||
241 | if (IS_ERR(info->rtc_dev)) { | ||
242 | dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); | ||
243 | goto out_rtc; | ||
244 | } | ||
245 | |||
246 | max8907c_set_bits(chip->i2c_power, MAX8907C_REG_SYSENSEL, 0x2, 0x2); | ||
247 | |||
248 | platform_set_drvdata(pdev, info); | ||
249 | |||
250 | device_init_wakeup(&pdev->dev, 1); | ||
251 | |||
252 | return 0; | ||
253 | out_rtc: | ||
254 | free_irq(chip->irq_base + MAX8907C_IRQ_RTC_ALARM0, info); | ||
255 | |||
256 | out_irq: | ||
257 | kfree(info); | ||
258 | return ret; | ||
259 | } | ||
260 | |||
261 | static int __devexit max8907c_rtc_remove(struct platform_device *pdev) | ||
262 | { | ||
263 | struct max8907c_rtc_info *info = platform_get_drvdata(pdev); | ||
264 | |||
265 | if (info) { | ||
266 | free_irq(info->chip->irq_base + MAX8907C_IRQ_RTC_ALARM0, info); | ||
267 | |||
268 | rtc_device_unregister(info->rtc_dev); | ||
269 | kfree(info); | ||
270 | } | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | #ifdef CONFIG_PM | ||
275 | static int max8907c_rtc_suspend(struct platform_device *pdev, pm_message_t state) | ||
276 | { | ||
277 | struct device *dev=&pdev->dev; | ||
278 | struct max8907c_rtc_info *info = platform_get_drvdata(pdev); | ||
279 | |||
280 | if (device_may_wakeup(dev)) | ||
281 | enable_irq_wake(info->chip->irq_base + MAX8907C_IRQ_RTC_ALARM0); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static int max8907c_rtc_resume(struct platform_device *pdev) | ||
286 | { | ||
287 | struct device *dev=&pdev->dev; | ||
288 | struct max8907c_rtc_info *info = platform_get_drvdata(pdev); | ||
289 | |||
290 | if (device_may_wakeup(dev)) | ||
291 | disable_irq_wake(info->chip->irq_base + MAX8907C_IRQ_RTC_ALARM0); | ||
292 | return 0; | ||
293 | } | ||
294 | #endif | ||
295 | |||
296 | static struct platform_driver max8907c_rtc_driver = { | ||
297 | .driver = { | ||
298 | .name = "max8907c-rtc", | ||
299 | .owner = THIS_MODULE, | ||
300 | }, | ||
301 | .probe = max8907c_rtc_probe, | ||
302 | .remove = __devexit_p(max8907c_rtc_remove), | ||
303 | #ifdef CONFIG_PM | ||
304 | .suspend = max8907c_rtc_suspend, | ||
305 | .resume = max8907c_rtc_resume, | ||
306 | #endif | ||
307 | }; | ||
308 | |||
309 | static int __init max8907c_rtc_init(void) | ||
310 | { | ||
311 | return platform_driver_register(&max8907c_rtc_driver); | ||
312 | } | ||
313 | module_init(max8907c_rtc_init); | ||
314 | |||
315 | static void __exit max8907c_rtc_exit(void) | ||
316 | { | ||
317 | platform_driver_unregister(&max8907c_rtc_driver); | ||
318 | } | ||
319 | module_exit(max8907c_rtc_exit); | ||
320 | |||
321 | MODULE_DESCRIPTION("Maxim MAX8907C RTC driver"); | ||
322 | MODULE_LICENSE("GPL"); | ||
323 | |||
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index 09ccd8d3ba2..da60915818b 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright 2007, Domen Puncer <domen.puncer@telargo.com> | 4 | * Copyright 2007, Domen Puncer <domen.puncer@telargo.com> |
5 | * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved. | 5 | * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved. |
6 | * Copyright 2011, Dmitry Eremin-Solenikov | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -145,6 +146,55 @@ static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
145 | return 0; | 146 | return 0; |
146 | } | 147 | } |
147 | 148 | ||
149 | static int mpc5200_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
150 | { | ||
151 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
152 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
153 | int tmp; | ||
154 | |||
155 | tm->tm_sec = in_8(®s->second); | ||
156 | tm->tm_min = in_8(®s->minute); | ||
157 | |||
158 | /* 12 hour format? */ | ||
159 | if (in_8(®s->hour) & 0x20) | ||
160 | tm->tm_hour = (in_8(®s->hour) >> 1) + | ||
161 | (in_8(®s->hour) & 1 ? 12 : 0); | ||
162 | else | ||
163 | tm->tm_hour = in_8(®s->hour); | ||
164 | |||
165 | tmp = in_8(®s->wday_mday); | ||
166 | tm->tm_mday = tmp & 0x1f; | ||
167 | tm->tm_mon = in_8(®s->month) - 1; | ||
168 | tm->tm_year = in_be16(®s->year) - 1900; | ||
169 | tm->tm_wday = (tmp >> 5) % 7; | ||
170 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); | ||
171 | tm->tm_isdst = 0; | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int mpc5200_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
177 | { | ||
178 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
179 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
180 | |||
181 | mpc5121_rtc_update_smh(regs, tm); | ||
182 | |||
183 | /* date */ | ||
184 | out_8(®s->month_set, tm->tm_mon + 1); | ||
185 | out_8(®s->weekday_set, tm->tm_wday ? tm->tm_wday : 7); | ||
186 | out_8(®s->date_set, tm->tm_mday); | ||
187 | out_be16(®s->year_set, tm->tm_year + 1900); | ||
188 | |||
189 | /* set date sequence */ | ||
190 | out_8(®s->set_date, 0x1); | ||
191 | out_8(®s->set_date, 0x3); | ||
192 | out_8(®s->set_date, 0x1); | ||
193 | out_8(®s->set_date, 0x0); | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
148 | static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 198 | static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
149 | { | 199 | { |
150 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | 200 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); |
@@ -248,11 +298,18 @@ static const struct rtc_class_ops mpc5121_rtc_ops = { | |||
248 | .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable, | 298 | .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable, |
249 | }; | 299 | }; |
250 | 300 | ||
301 | static const struct rtc_class_ops mpc5200_rtc_ops = { | ||
302 | .read_time = mpc5200_rtc_read_time, | ||
303 | .set_time = mpc5200_rtc_set_time, | ||
304 | .read_alarm = mpc5121_rtc_read_alarm, | ||
305 | .set_alarm = mpc5121_rtc_set_alarm, | ||
306 | .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable, | ||
307 | }; | ||
308 | |||
251 | static int __devinit mpc5121_rtc_probe(struct platform_device *op) | 309 | static int __devinit mpc5121_rtc_probe(struct platform_device *op) |
252 | { | 310 | { |
253 | struct mpc5121_rtc_data *rtc; | 311 | struct mpc5121_rtc_data *rtc; |
254 | int err = 0; | 312 | int err = 0; |
255 | u32 ka; | ||
256 | 313 | ||
257 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | 314 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); |
258 | if (!rtc) | 315 | if (!rtc) |
@@ -287,15 +344,22 @@ static int __devinit mpc5121_rtc_probe(struct platform_device *op) | |||
287 | goto out_dispose2; | 344 | goto out_dispose2; |
288 | } | 345 | } |
289 | 346 | ||
290 | ka = in_be32(&rtc->regs->keep_alive); | 347 | if (of_device_is_compatible(op->dev.of_node, "fsl,mpc5121-rtc")) { |
291 | if (ka & 0x02) { | 348 | u32 ka; |
292 | dev_warn(&op->dev, | 349 | ka = in_be32(&rtc->regs->keep_alive); |
293 | "mpc5121-rtc: Battery or oscillator failure!\n"); | 350 | if (ka & 0x02) { |
294 | out_be32(&rtc->regs->keep_alive, ka); | 351 | dev_warn(&op->dev, |
352 | "mpc5121-rtc: Battery or oscillator failure!\n"); | ||
353 | out_be32(&rtc->regs->keep_alive, ka); | ||
354 | } | ||
355 | |||
356 | rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev, | ||
357 | &mpc5121_rtc_ops, THIS_MODULE); | ||
358 | } else { | ||
359 | rtc->rtc = rtc_device_register("mpc5200-rtc", &op->dev, | ||
360 | &mpc5200_rtc_ops, THIS_MODULE); | ||
295 | } | 361 | } |
296 | 362 | ||
297 | rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev, | ||
298 | &mpc5121_rtc_ops, THIS_MODULE); | ||
299 | if (IS_ERR(rtc->rtc)) { | 363 | if (IS_ERR(rtc->rtc)) { |
300 | err = PTR_ERR(rtc->rtc); | 364 | err = PTR_ERR(rtc->rtc); |
301 | goto out_free_irq; | 365 | goto out_free_irq; |
@@ -340,6 +404,7 @@ static int __devexit mpc5121_rtc_remove(struct platform_device *op) | |||
340 | 404 | ||
341 | static struct of_device_id mpc5121_rtc_match[] __devinitdata = { | 405 | static struct of_device_id mpc5121_rtc_match[] __devinitdata = { |
342 | { .compatible = "fsl,mpc5121-rtc", }, | 406 | { .compatible = "fsl,mpc5121-rtc", }, |
407 | { .compatible = "fsl,mpc5200-rtc", }, | ||
343 | {}, | 408 | {}, |
344 | }; | 409 | }; |
345 | 410 | ||
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index 0cec5650d56..d33544802a2 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c | |||
@@ -332,9 +332,8 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) | |||
332 | if (!iomem) | 332 | if (!iomem) |
333 | return -ENODEV; | 333 | return -ENODEV; |
334 | 334 | ||
335 | iomem = request_mem_region(iomem->start, | 335 | iomem = request_mem_region(iomem->start, resource_size(iomem), |
336 | iomem->end + 1 - iomem->start, | 336 | driver_name); |
337 | driver_name); | ||
338 | if (!iomem) { | 337 | if (!iomem) { |
339 | dev_dbg(dev, "i/o mem already in use.\n"); | 338 | dev_dbg(dev, "i/o mem already in use.\n"); |
340 | return -EBUSY; | 339 | return -EBUSY; |
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index bcae8dd4149..7789002bdd5 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c | |||
@@ -368,7 +368,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
368 | pr_info("%s: already running\n", pdev->name); | 368 | pr_info("%s: already running\n", pdev->name); |
369 | 369 | ||
370 | /* force to 24 hour mode */ | 370 | /* force to 24 hour mode */ |
371 | new_ctrl = reg & ~(OMAP_RTC_CTRL_SPLIT|OMAP_RTC_CTRL_AUTO_COMP); | 371 | new_ctrl = reg & (OMAP_RTC_CTRL_SPLIT|OMAP_RTC_CTRL_AUTO_COMP); |
372 | new_ctrl |= OMAP_RTC_CTRL_STOP; | 372 | new_ctrl |= OMAP_RTC_CTRL_STOP; |
373 | 373 | ||
374 | /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: | 374 | /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: |
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c new file mode 100644 index 00000000000..d420e9d877e --- /dev/null +++ b/drivers/rtc/rtc-pm8xxx.c | |||
@@ -0,0 +1,550 @@ | |||
1 | /* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/rtc.h> | ||
16 | #include <linux/pm.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | |||
20 | #include <linux/mfd/pm8xxx/core.h> | ||
21 | #include <linux/mfd/pm8xxx/rtc.h> | ||
22 | |||
23 | |||
24 | /* RTC Register offsets from RTC CTRL REG */ | ||
25 | #define PM8XXX_ALARM_CTRL_OFFSET 0x01 | ||
26 | #define PM8XXX_RTC_WRITE_OFFSET 0x02 | ||
27 | #define PM8XXX_RTC_READ_OFFSET 0x06 | ||
28 | #define PM8XXX_ALARM_RW_OFFSET 0x0A | ||
29 | |||
30 | /* RTC_CTRL register bit fields */ | ||
31 | #define PM8xxx_RTC_ENABLE BIT(7) | ||
32 | #define PM8xxx_RTC_ALARM_ENABLE BIT(1) | ||
33 | #define PM8xxx_RTC_ALARM_CLEAR BIT(0) | ||
34 | |||
35 | #define NUM_8_BIT_RTC_REGS 0x4 | ||
36 | |||
37 | /** | ||
38 | * struct pm8xxx_rtc - rtc driver internal structure | ||
39 | * @rtc: rtc device for this driver. | ||
40 | * @rtc_alarm_irq: rtc alarm irq number. | ||
41 | * @rtc_base: address of rtc control register. | ||
42 | * @rtc_read_base: base address of read registers. | ||
43 | * @rtc_write_base: base address of write registers. | ||
44 | * @alarm_rw_base: base address of alarm registers. | ||
45 | * @ctrl_reg: rtc control register. | ||
46 | * @rtc_dev: device structure. | ||
47 | * @ctrl_reg_lock: spinlock protecting access to ctrl_reg. | ||
48 | */ | ||
49 | struct pm8xxx_rtc { | ||
50 | struct rtc_device *rtc; | ||
51 | int rtc_alarm_irq; | ||
52 | int rtc_base; | ||
53 | int rtc_read_base; | ||
54 | int rtc_write_base; | ||
55 | int alarm_rw_base; | ||
56 | u8 ctrl_reg; | ||
57 | struct device *rtc_dev; | ||
58 | spinlock_t ctrl_reg_lock; | ||
59 | }; | ||
60 | |||
61 | /* | ||
62 | * The RTC registers need to be read/written one byte at a time. This is a | ||
63 | * hardware limitation. | ||
64 | */ | ||
65 | static int pm8xxx_read_wrapper(struct pm8xxx_rtc *rtc_dd, u8 *rtc_val, | ||
66 | int base, int count) | ||
67 | { | ||
68 | int i, rc; | ||
69 | struct device *parent = rtc_dd->rtc_dev->parent; | ||
70 | |||
71 | for (i = 0; i < count; i++) { | ||
72 | rc = pm8xxx_readb(parent, base + i, &rtc_val[i]); | ||
73 | if (rc < 0) { | ||
74 | dev_err(rtc_dd->rtc_dev, "PMIC read failed\n"); | ||
75 | return rc; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int pm8xxx_write_wrapper(struct pm8xxx_rtc *rtc_dd, u8 *rtc_val, | ||
83 | int base, int count) | ||
84 | { | ||
85 | int i, rc; | ||
86 | struct device *parent = rtc_dd->rtc_dev->parent; | ||
87 | |||
88 | for (i = 0; i < count; i++) { | ||
89 | rc = pm8xxx_writeb(parent, base + i, rtc_val[i]); | ||
90 | if (rc < 0) { | ||
91 | dev_err(rtc_dd->rtc_dev, "PMIC write failed\n"); | ||
92 | return rc; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * Steps to write the RTC registers. | ||
101 | * 1. Disable alarm if enabled. | ||
102 | * 2. Write 0x00 to LSB. | ||
103 | * 3. Write Byte[1], Byte[2], Byte[3] then Byte[0]. | ||
104 | * 4. Enable alarm if disabled in step 1. | ||
105 | */ | ||
106 | static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
107 | { | ||
108 | int rc, i; | ||
109 | unsigned long secs, irq_flags; | ||
110 | u8 value[NUM_8_BIT_RTC_REGS], reg = 0, alarm_enabled = 0, ctrl_reg; | ||
111 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
112 | |||
113 | rtc_tm_to_time(tm, &secs); | ||
114 | |||
115 | for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) { | ||
116 | value[i] = secs & 0xFF; | ||
117 | secs >>= 8; | ||
118 | } | ||
119 | |||
120 | dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs); | ||
121 | |||
122 | spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
123 | ctrl_reg = rtc_dd->ctrl_reg; | ||
124 | |||
125 | if (ctrl_reg & PM8xxx_RTC_ALARM_ENABLE) { | ||
126 | alarm_enabled = 1; | ||
127 | ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE; | ||
128 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, | ||
129 | 1); | ||
130 | if (rc < 0) { | ||
131 | dev_err(dev, "Write to RTC control register " | ||
132 | "failed\n"); | ||
133 | goto rtc_rw_fail; | ||
134 | } | ||
135 | rtc_dd->ctrl_reg = ctrl_reg; | ||
136 | } else | ||
137 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
138 | |||
139 | /* Write 0 to Byte[0] */ | ||
140 | reg = 0; | ||
141 | rc = pm8xxx_write_wrapper(rtc_dd, ®, rtc_dd->rtc_write_base, 1); | ||
142 | if (rc < 0) { | ||
143 | dev_err(dev, "Write to RTC write data register failed\n"); | ||
144 | goto rtc_rw_fail; | ||
145 | } | ||
146 | |||
147 | /* Write Byte[1], Byte[2], Byte[3] */ | ||
148 | rc = pm8xxx_write_wrapper(rtc_dd, value + 1, | ||
149 | rtc_dd->rtc_write_base + 1, 3); | ||
150 | if (rc < 0) { | ||
151 | dev_err(dev, "Write to RTC write data register failed\n"); | ||
152 | goto rtc_rw_fail; | ||
153 | } | ||
154 | |||
155 | /* Write Byte[0] */ | ||
156 | rc = pm8xxx_write_wrapper(rtc_dd, value, rtc_dd->rtc_write_base, 1); | ||
157 | if (rc < 0) { | ||
158 | dev_err(dev, "Write to RTC write data register failed\n"); | ||
159 | goto rtc_rw_fail; | ||
160 | } | ||
161 | |||
162 | if (alarm_enabled) { | ||
163 | ctrl_reg |= PM8xxx_RTC_ALARM_ENABLE; | ||
164 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, | ||
165 | 1); | ||
166 | if (rc < 0) { | ||
167 | dev_err(dev, "Write to RTC control register " | ||
168 | "failed\n"); | ||
169 | goto rtc_rw_fail; | ||
170 | } | ||
171 | rtc_dd->ctrl_reg = ctrl_reg; | ||
172 | } | ||
173 | |||
174 | rtc_rw_fail: | ||
175 | if (alarm_enabled) | ||
176 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
177 | |||
178 | return rc; | ||
179 | } | ||
180 | |||
181 | static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
182 | { | ||
183 | int rc; | ||
184 | u8 value[NUM_8_BIT_RTC_REGS], reg; | ||
185 | unsigned long secs; | ||
186 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
187 | |||
188 | rc = pm8xxx_read_wrapper(rtc_dd, value, rtc_dd->rtc_read_base, | ||
189 | NUM_8_BIT_RTC_REGS); | ||
190 | if (rc < 0) { | ||
191 | dev_err(dev, "RTC read data register failed\n"); | ||
192 | return rc; | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * Read the LSB again and check if there has been a carry over. | ||
197 | * If there is, redo the read operation. | ||
198 | */ | ||
199 | rc = pm8xxx_read_wrapper(rtc_dd, ®, rtc_dd->rtc_read_base, 1); | ||
200 | if (rc < 0) { | ||
201 | dev_err(dev, "RTC read data register failed\n"); | ||
202 | return rc; | ||
203 | } | ||
204 | |||
205 | if (unlikely(reg < value[0])) { | ||
206 | rc = pm8xxx_read_wrapper(rtc_dd, value, | ||
207 | rtc_dd->rtc_read_base, NUM_8_BIT_RTC_REGS); | ||
208 | if (rc < 0) { | ||
209 | dev_err(dev, "RTC read data register failed\n"); | ||
210 | return rc; | ||
211 | } | ||
212 | } | ||
213 | |||
214 | secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24); | ||
215 | |||
216 | rtc_time_to_tm(secs, tm); | ||
217 | |||
218 | rc = rtc_valid_tm(tm); | ||
219 | if (rc < 0) { | ||
220 | dev_err(dev, "Invalid time read from RTC\n"); | ||
221 | return rc; | ||
222 | } | ||
223 | |||
224 | dev_dbg(dev, "secs = %lu, h:m:s == %d:%d:%d, d/m/y = %d/%d/%d\n", | ||
225 | secs, tm->tm_hour, tm->tm_min, tm->tm_sec, | ||
226 | tm->tm_mday, tm->tm_mon, tm->tm_year); | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
232 | { | ||
233 | int rc, i; | ||
234 | u8 value[NUM_8_BIT_RTC_REGS], ctrl_reg; | ||
235 | unsigned long secs, irq_flags; | ||
236 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
237 | |||
238 | rtc_tm_to_time(&alarm->time, &secs); | ||
239 | |||
240 | for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) { | ||
241 | value[i] = secs & 0xFF; | ||
242 | secs >>= 8; | ||
243 | } | ||
244 | |||
245 | spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
246 | |||
247 | rc = pm8xxx_write_wrapper(rtc_dd, value, rtc_dd->alarm_rw_base, | ||
248 | NUM_8_BIT_RTC_REGS); | ||
249 | if (rc < 0) { | ||
250 | dev_err(dev, "Write to RTC ALARM register failed\n"); | ||
251 | goto rtc_rw_fail; | ||
252 | } | ||
253 | |||
254 | ctrl_reg = rtc_dd->ctrl_reg; | ||
255 | ctrl_reg = alarm->enabled ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) : | ||
256 | (ctrl_reg & ~PM8xxx_RTC_ALARM_ENABLE); | ||
257 | |||
258 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1); | ||
259 | if (rc < 0) { | ||
260 | dev_err(dev, "Write to RTC control register failed\n"); | ||
261 | goto rtc_rw_fail; | ||
262 | } | ||
263 | |||
264 | rtc_dd->ctrl_reg = ctrl_reg; | ||
265 | |||
266 | dev_dbg(dev, "Alarm Set for h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n", | ||
267 | alarm->time.tm_hour, alarm->time.tm_min, | ||
268 | alarm->time.tm_sec, alarm->time.tm_mday, | ||
269 | alarm->time.tm_mon, alarm->time.tm_year); | ||
270 | rtc_rw_fail: | ||
271 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
272 | return rc; | ||
273 | } | ||
274 | |||
275 | static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
276 | { | ||
277 | int rc; | ||
278 | u8 value[NUM_8_BIT_RTC_REGS]; | ||
279 | unsigned long secs; | ||
280 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
281 | |||
282 | rc = pm8xxx_read_wrapper(rtc_dd, value, rtc_dd->alarm_rw_base, | ||
283 | NUM_8_BIT_RTC_REGS); | ||
284 | if (rc < 0) { | ||
285 | dev_err(dev, "RTC alarm time read failed\n"); | ||
286 | return rc; | ||
287 | } | ||
288 | |||
289 | secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24); | ||
290 | |||
291 | rtc_time_to_tm(secs, &alarm->time); | ||
292 | |||
293 | rc = rtc_valid_tm(&alarm->time); | ||
294 | if (rc < 0) { | ||
295 | dev_err(dev, "Invalid alarm time read from RTC\n"); | ||
296 | return rc; | ||
297 | } | ||
298 | |||
299 | dev_dbg(dev, "Alarm set for - h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n", | ||
300 | alarm->time.tm_hour, alarm->time.tm_min, | ||
301 | alarm->time.tm_sec, alarm->time.tm_mday, | ||
302 | alarm->time.tm_mon, alarm->time.tm_year); | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static int pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) | ||
308 | { | ||
309 | int rc; | ||
310 | unsigned long irq_flags; | ||
311 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
312 | u8 ctrl_reg; | ||
313 | |||
314 | spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
315 | ctrl_reg = rtc_dd->ctrl_reg; | ||
316 | ctrl_reg = (enable) ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) : | ||
317 | (ctrl_reg & ~PM8xxx_RTC_ALARM_ENABLE); | ||
318 | |||
319 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1); | ||
320 | if (rc < 0) { | ||
321 | dev_err(dev, "Write to RTC control register failed\n"); | ||
322 | goto rtc_rw_fail; | ||
323 | } | ||
324 | |||
325 | rtc_dd->ctrl_reg = ctrl_reg; | ||
326 | |||
327 | rtc_rw_fail: | ||
328 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
329 | return rc; | ||
330 | } | ||
331 | |||
332 | static struct rtc_class_ops pm8xxx_rtc_ops = { | ||
333 | .read_time = pm8xxx_rtc_read_time, | ||
334 | .set_alarm = pm8xxx_rtc_set_alarm, | ||
335 | .read_alarm = pm8xxx_rtc_read_alarm, | ||
336 | .alarm_irq_enable = pm8xxx_rtc_alarm_irq_enable, | ||
337 | }; | ||
338 | |||
339 | static irqreturn_t pm8xxx_alarm_trigger(int irq, void *dev_id) | ||
340 | { | ||
341 | struct pm8xxx_rtc *rtc_dd = dev_id; | ||
342 | u8 ctrl_reg; | ||
343 | int rc; | ||
344 | unsigned long irq_flags; | ||
345 | |||
346 | rtc_update_irq(rtc_dd->rtc, 1, RTC_IRQF | RTC_AF); | ||
347 | |||
348 | spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
349 | |||
350 | /* Clear the alarm enable bit */ | ||
351 | ctrl_reg = rtc_dd->ctrl_reg; | ||
352 | ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE; | ||
353 | |||
354 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1); | ||
355 | if (rc < 0) { | ||
356 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
357 | dev_err(rtc_dd->rtc_dev, "Write to RTC control register " | ||
358 | "failed\n"); | ||
359 | goto rtc_alarm_handled; | ||
360 | } | ||
361 | |||
362 | rtc_dd->ctrl_reg = ctrl_reg; | ||
363 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
364 | |||
365 | /* Clear RTC alarm register */ | ||
366 | rc = pm8xxx_read_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base + | ||
367 | PM8XXX_ALARM_CTRL_OFFSET, 1); | ||
368 | if (rc < 0) { | ||
369 | dev_err(rtc_dd->rtc_dev, "RTC Alarm control register read " | ||
370 | "failed\n"); | ||
371 | goto rtc_alarm_handled; | ||
372 | } | ||
373 | |||
374 | ctrl_reg &= ~PM8xxx_RTC_ALARM_CLEAR; | ||
375 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base + | ||
376 | PM8XXX_ALARM_CTRL_OFFSET, 1); | ||
377 | if (rc < 0) | ||
378 | dev_err(rtc_dd->rtc_dev, "Write to RTC Alarm control register" | ||
379 | " failed\n"); | ||
380 | |||
381 | rtc_alarm_handled: | ||
382 | return IRQ_HANDLED; | ||
383 | } | ||
384 | |||
385 | static int __devinit pm8xxx_rtc_probe(struct platform_device *pdev) | ||
386 | { | ||
387 | int rc; | ||
388 | u8 ctrl_reg; | ||
389 | bool rtc_write_enable = false; | ||
390 | struct pm8xxx_rtc *rtc_dd; | ||
391 | struct resource *rtc_resource; | ||
392 | const struct pm8xxx_rtc_platform_data *pdata = | ||
393 | dev_get_platdata(&pdev->dev); | ||
394 | |||
395 | if (pdata != NULL) | ||
396 | rtc_write_enable = pdata->rtc_write_enable; | ||
397 | |||
398 | rtc_dd = kzalloc(sizeof(*rtc_dd), GFP_KERNEL); | ||
399 | if (rtc_dd == NULL) { | ||
400 | dev_err(&pdev->dev, "Unable to allocate memory!\n"); | ||
401 | return -ENOMEM; | ||
402 | } | ||
403 | |||
404 | /* Initialise spinlock to protect RTC control register */ | ||
405 | spin_lock_init(&rtc_dd->ctrl_reg_lock); | ||
406 | |||
407 | rtc_dd->rtc_alarm_irq = platform_get_irq(pdev, 0); | ||
408 | if (rtc_dd->rtc_alarm_irq < 0) { | ||
409 | dev_err(&pdev->dev, "Alarm IRQ resource absent!\n"); | ||
410 | rc = -ENXIO; | ||
411 | goto fail_rtc_enable; | ||
412 | } | ||
413 | |||
414 | rtc_resource = platform_get_resource_byname(pdev, IORESOURCE_IO, | ||
415 | "pmic_rtc_base"); | ||
416 | if (!(rtc_resource && rtc_resource->start)) { | ||
417 | dev_err(&pdev->dev, "RTC IO resource absent!\n"); | ||
418 | rc = -ENXIO; | ||
419 | goto fail_rtc_enable; | ||
420 | } | ||
421 | |||
422 | rtc_dd->rtc_base = rtc_resource->start; | ||
423 | |||
424 | /* Setup RTC register addresses */ | ||
425 | rtc_dd->rtc_write_base = rtc_dd->rtc_base + PM8XXX_RTC_WRITE_OFFSET; | ||
426 | rtc_dd->rtc_read_base = rtc_dd->rtc_base + PM8XXX_RTC_READ_OFFSET; | ||
427 | rtc_dd->alarm_rw_base = rtc_dd->rtc_base + PM8XXX_ALARM_RW_OFFSET; | ||
428 | |||
429 | rtc_dd->rtc_dev = &pdev->dev; | ||
430 | |||
431 | /* Check if the RTC is on, else turn it on */ | ||
432 | rc = pm8xxx_read_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1); | ||
433 | if (rc < 0) { | ||
434 | dev_err(&pdev->dev, "RTC control register read failed!\n"); | ||
435 | goto fail_rtc_enable; | ||
436 | } | ||
437 | |||
438 | if (!(ctrl_reg & PM8xxx_RTC_ENABLE)) { | ||
439 | ctrl_reg |= PM8xxx_RTC_ENABLE; | ||
440 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, | ||
441 | 1); | ||
442 | if (rc < 0) { | ||
443 | dev_err(&pdev->dev, "Write to RTC control register " | ||
444 | "failed\n"); | ||
445 | goto fail_rtc_enable; | ||
446 | } | ||
447 | } | ||
448 | |||
449 | rtc_dd->ctrl_reg = ctrl_reg; | ||
450 | if (rtc_write_enable == true) | ||
451 | pm8xxx_rtc_ops.set_time = pm8xxx_rtc_set_time; | ||
452 | |||
453 | platform_set_drvdata(pdev, rtc_dd); | ||
454 | |||
455 | /* Register the RTC device */ | ||
456 | rtc_dd->rtc = rtc_device_register("pm8xxx_rtc", &pdev->dev, | ||
457 | &pm8xxx_rtc_ops, THIS_MODULE); | ||
458 | if (IS_ERR(rtc_dd->rtc)) { | ||
459 | dev_err(&pdev->dev, "%s: RTC registration failed (%ld)\n", | ||
460 | __func__, PTR_ERR(rtc_dd->rtc)); | ||
461 | rc = PTR_ERR(rtc_dd->rtc); | ||
462 | goto fail_rtc_enable; | ||
463 | } | ||
464 | |||
465 | /* Request the alarm IRQ */ | ||
466 | rc = request_any_context_irq(rtc_dd->rtc_alarm_irq, | ||
467 | pm8xxx_alarm_trigger, IRQF_TRIGGER_RISING, | ||
468 | "pm8xxx_rtc_alarm", rtc_dd); | ||
469 | if (rc < 0) { | ||
470 | dev_err(&pdev->dev, "Request IRQ failed (%d)\n", rc); | ||
471 | goto fail_req_irq; | ||
472 | } | ||
473 | |||
474 | device_init_wakeup(&pdev->dev, 1); | ||
475 | |||
476 | dev_dbg(&pdev->dev, "Probe success !!\n"); | ||
477 | |||
478 | return 0; | ||
479 | |||
480 | fail_req_irq: | ||
481 | rtc_device_unregister(rtc_dd->rtc); | ||
482 | fail_rtc_enable: | ||
483 | platform_set_drvdata(pdev, NULL); | ||
484 | kfree(rtc_dd); | ||
485 | return rc; | ||
486 | } | ||
487 | |||
488 | static int __devexit pm8xxx_rtc_remove(struct platform_device *pdev) | ||
489 | { | ||
490 | struct pm8xxx_rtc *rtc_dd = platform_get_drvdata(pdev); | ||
491 | |||
492 | device_init_wakeup(&pdev->dev, 0); | ||
493 | free_irq(rtc_dd->rtc_alarm_irq, rtc_dd); | ||
494 | rtc_device_unregister(rtc_dd->rtc); | ||
495 | platform_set_drvdata(pdev, NULL); | ||
496 | kfree(rtc_dd); | ||
497 | |||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | #ifdef CONFIG_PM_SLEEP | ||
502 | static int pm8xxx_rtc_resume(struct device *dev) | ||
503 | { | ||
504 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
505 | |||
506 | if (device_may_wakeup(dev)) | ||
507 | disable_irq_wake(rtc_dd->rtc_alarm_irq); | ||
508 | |||
509 | return 0; | ||
510 | } | ||
511 | |||
512 | static int pm8xxx_rtc_suspend(struct device *dev) | ||
513 | { | ||
514 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
515 | |||
516 | if (device_may_wakeup(dev)) | ||
517 | enable_irq_wake(rtc_dd->rtc_alarm_irq); | ||
518 | |||
519 | return 0; | ||
520 | } | ||
521 | #endif | ||
522 | |||
523 | SIMPLE_DEV_PM_OPS(pm8xxx_rtc_pm_ops, pm8xxx_rtc_suspend, pm8xxx_rtc_resume); | ||
524 | |||
525 | static struct platform_driver pm8xxx_rtc_driver = { | ||
526 | .probe = pm8xxx_rtc_probe, | ||
527 | .remove = __devexit_p(pm8xxx_rtc_remove), | ||
528 | .driver = { | ||
529 | .name = PM8XXX_RTC_DEV_NAME, | ||
530 | .owner = THIS_MODULE, | ||
531 | .pm = &pm8xxx_rtc_pm_ops, | ||
532 | }, | ||
533 | }; | ||
534 | |||
535 | static int __init pm8xxx_rtc_init(void) | ||
536 | { | ||
537 | return platform_driver_register(&pm8xxx_rtc_driver); | ||
538 | } | ||
539 | module_init(pm8xxx_rtc_init); | ||
540 | |||
541 | static void __exit pm8xxx_rtc_exit(void) | ||
542 | { | ||
543 | platform_driver_unregister(&pm8xxx_rtc_driver); | ||
544 | } | ||
545 | module_exit(pm8xxx_rtc_exit); | ||
546 | |||
547 | MODULE_ALIAS("platform:rtc-pm8xxx"); | ||
548 | MODULE_DESCRIPTION("PMIC8xxx RTC driver"); | ||
549 | MODULE_LICENSE("GPL v2"); | ||
550 | MODULE_AUTHOR("Anirudh Ghayal <aghayal@codeaurora.org>"); | ||
diff --git a/drivers/rtc/rtc-puv3.c b/drivers/rtc/rtc-puv3.c index 46f14b82f3a..b3eba3cddd4 100644 --- a/drivers/rtc/rtc-puv3.c +++ b/drivers/rtc/rtc-puv3.c | |||
@@ -267,9 +267,8 @@ static int puv3_rtc_probe(struct platform_device *pdev) | |||
267 | return -ENOENT; | 267 | return -ENOENT; |
268 | } | 268 | } |
269 | 269 | ||
270 | puv3_rtc_mem = request_mem_region(res->start, | 270 | puv3_rtc_mem = request_mem_region(res->start, resource_size(res), |
271 | res->end-res->start+1, | 271 | pdev->name); |
272 | pdev->name); | ||
273 | 272 | ||
274 | if (puv3_rtc_mem == NULL) { | 273 | if (puv3_rtc_mem == NULL) { |
275 | dev_err(&pdev->dev, "failed to reserve memory region\n"); | 274 | dev_err(&pdev->dev, "failed to reserve memory region\n"); |
diff --git a/drivers/rtc/rtc-ricoh583.c b/drivers/rtc/rtc-ricoh583.c new file mode 100644 index 00000000000..8bc17d9a101 --- /dev/null +++ b/drivers/rtc/rtc-ricoh583.c | |||
@@ -0,0 +1,403 @@ | |||
1 | /* | ||
2 | * drivers/rtc/rtc_ricoh583.c | ||
3 | * | ||
4 | * rtc driver for ricoh rc5t583 pmu | ||
5 | * | ||
6 | * copyright (c) 2011, nvidia corporation. | ||
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, but without | ||
14 | * any warranty; without even the implied warranty of merchantability or | ||
15 | * fitness for a particular purpose. see the gnu general public license for | ||
16 | * more details. | ||
17 | * | ||
18 | * you should have received a copy of the gnu general public license along | ||
19 | * with this program; if not, write to the free software foundation, inc., | ||
20 | * 51 franklin street, fifth floor, boston, ma 02110-1301, usa. | ||
21 | */ | ||
22 | |||
23 | /* #define debug 1 */ | ||
24 | /* #define verbose_debug 1 */ | ||
25 | |||
26 | #include <linux/device.h> | ||
27 | #include <linux/err.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/mfd/ricoh583.h> | ||
31 | #include <linux/platform_device.h> | ||
32 | #include <linux/rtc.h> | ||
33 | #include <linux/slab.h> | ||
34 | |||
35 | #define rtc_ctrl1 0xED | ||
36 | #define rtc_ctrl2 0xEE | ||
37 | #define rtc_seconds_reg 0xE0 | ||
38 | #define rtc_alarm_y 0xF0 | ||
39 | #define rtc_adjust 0xE7 | ||
40 | |||
41 | /* | ||
42 | linux rtc driver refers 1900 as base year in many calculations. | ||
43 | (e.g. refer drivers/rtc/rtc-lib.c) | ||
44 | */ | ||
45 | #define os_ref_year 1900 | ||
46 | |||
47 | /* | ||
48 | pmu rtc have only 2 nibbles to store year information, so using an | ||
49 | offset of 100 to set the base year as 2000 for our driver. | ||
50 | */ | ||
51 | #define rtc_year_offset 100 | ||
52 | |||
53 | struct ricoh583_rtc { | ||
54 | unsigned long epoch_start; | ||
55 | int irq; | ||
56 | struct rtc_device *rtc; | ||
57 | bool irq_en; | ||
58 | }; | ||
59 | |||
60 | static int ricoh583_read_regs(struct device *dev, int reg, int len, | ||
61 | uint8_t *val) | ||
62 | { | ||
63 | int ret; | ||
64 | |||
65 | ret = ricoh583_bulk_reads(dev->parent, reg, len, val); | ||
66 | if (ret < 0) { | ||
67 | dev_err(dev->parent, "\n %s failed reading from 0x%02x\n", | ||
68 | __func__, reg); | ||
69 | WARN_ON(1); | ||
70 | } | ||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | static int ricoh583_write_regs(struct device *dev, int reg, int len, | ||
75 | uint8_t *val) | ||
76 | { | ||
77 | int ret; | ||
78 | ret = ricoh583_bulk_writes(dev->parent, reg, len, val); | ||
79 | if (ret < 0) { | ||
80 | dev_err(dev->parent, "\n %s failed writing\n", __func__); | ||
81 | WARN_ON(1); | ||
82 | } | ||
83 | |||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | static int ricoh583_rtc_valid_tm(struct device *dev, struct rtc_time *tm) | ||
88 | { | ||
89 | if (tm->tm_year >= (rtc_year_offset + 99) | ||
90 | || tm->tm_mon > 12 | ||
91 | || tm->tm_mday < 1 | ||
92 | || tm->tm_mday > rtc_month_days(tm->tm_mon, | ||
93 | tm->tm_year + os_ref_year) | ||
94 | || tm->tm_hour >= 24 | ||
95 | || tm->tm_min >= 60 | ||
96 | || tm->tm_sec >= 60) { | ||
97 | dev_err(dev->parent, "\n returning error due to time" | ||
98 | "%d/%d/%d %d:%d:%d", tm->tm_mon, tm->tm_mday, | ||
99 | tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
100 | return -EINVAL; | ||
101 | } | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static u8 dec2bcd(u8 dec) | ||
106 | { | ||
107 | return ((dec/10)<<4)+(dec%10); | ||
108 | } | ||
109 | |||
110 | static u8 bcd2dec(u8 bcd) | ||
111 | { | ||
112 | return (bcd >> 4)*10+(bcd & 0xf); | ||
113 | } | ||
114 | |||
115 | static void convert_bcd_to_decimal(u8 *buf, u8 len) | ||
116 | { | ||
117 | int i = 0; | ||
118 | for (i = 0; i < len; i++) | ||
119 | buf[i] = bcd2dec(buf[i]); | ||
120 | } | ||
121 | |||
122 | static void convert_decimal_to_bcd(u8 *buf, u8 len) | ||
123 | { | ||
124 | int i = 0; | ||
125 | for (i = 0; i < len; i++) | ||
126 | buf[i] = dec2bcd(buf[i]); | ||
127 | } | ||
128 | |||
129 | static void print_time(struct device *dev, struct rtc_time *tm) | ||
130 | { | ||
131 | dev_info(dev, "rtc-time : %d/%d/%d %d:%d\n", | ||
132 | (tm->tm_mon + 1), tm->tm_mday, (tm->tm_year + os_ref_year), | ||
133 | tm->tm_hour, tm->tm_min); | ||
134 | } | ||
135 | |||
136 | static int ricoh583_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
137 | { | ||
138 | u8 buff[7]; | ||
139 | int err; | ||
140 | err = ricoh583_read_regs(dev, rtc_seconds_reg, sizeof(buff), buff); | ||
141 | if (err < 0) { | ||
142 | dev_err(dev, "\n %s :: failed to read time\n", __FILE__); | ||
143 | return err; | ||
144 | } | ||
145 | convert_bcd_to_decimal(buff, sizeof(buff)); | ||
146 | tm->tm_sec = buff[0]; | ||
147 | tm->tm_min = buff[1]; | ||
148 | tm->tm_hour = buff[2]; | ||
149 | tm->tm_wday = buff[3]; | ||
150 | tm->tm_mday = buff[4]; | ||
151 | tm->tm_mon = buff[5] - 1; | ||
152 | tm->tm_year = buff[6] + rtc_year_offset; | ||
153 | print_time(dev, tm); | ||
154 | return ricoh583_rtc_valid_tm(dev, tm); | ||
155 | } | ||
156 | |||
157 | static int ricoh583_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
158 | { | ||
159 | u8 buff[7]; | ||
160 | int err; | ||
161 | |||
162 | print_time(dev, tm); | ||
163 | buff[0] = tm->tm_sec; | ||
164 | buff[1] = tm->tm_min; | ||
165 | buff[2] = tm->tm_hour; | ||
166 | buff[3] = tm->tm_wday; | ||
167 | buff[4] = tm->tm_mday; | ||
168 | buff[5] = tm->tm_mon + 1; | ||
169 | buff[6] = tm->tm_year - rtc_year_offset; | ||
170 | |||
171 | convert_decimal_to_bcd(buff, sizeof(buff)); | ||
172 | err = ricoh583_write_regs(dev, rtc_seconds_reg, sizeof(buff), buff); | ||
173 | if (err < 0) { | ||
174 | dev_err(dev->parent, "\n failed to program new time\n"); | ||
175 | return err; | ||
176 | } | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | static int ricoh583_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm); | ||
181 | |||
182 | static int ricoh583_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
183 | { | ||
184 | struct ricoh583_rtc *rtc = dev_get_drvdata(dev); | ||
185 | unsigned long seconds; | ||
186 | u8 buff[5]; | ||
187 | int err; | ||
188 | struct rtc_time tm; | ||
189 | |||
190 | if (rtc->irq == -1) | ||
191 | return -EIO; | ||
192 | |||
193 | rtc_tm_to_time(&alrm->time, &seconds); | ||
194 | ricoh583_rtc_read_time(dev, &tm); | ||
195 | rtc_tm_to_time(&tm, &rtc->epoch_start); | ||
196 | /* | ||
197 | work around: As YAL does not provide the seconds register, | ||
198 | program minute register to next minute, in cases when alarm | ||
199 | is requested within a minute from the current time. | ||
200 | */ | ||
201 | if (seconds - rtc->epoch_start < 60) | ||
202 | alrm->time.tm_min += 1; | ||
203 | dev_info(dev->parent, "\n setting alarm to requested time::\n"); | ||
204 | print_time(dev->parent, &alrm->time); | ||
205 | |||
206 | if (WARN_ON(alrm->enabled && (seconds < rtc->epoch_start))) { | ||
207 | dev_err(dev->parent, "\n can't set alarm to requested time\n"); | ||
208 | return -EINVAL; | ||
209 | } | ||
210 | |||
211 | if (alrm->enabled && !rtc->irq_en) | ||
212 | rtc->irq_en = true; | ||
213 | else if (!alrm->enabled && rtc->irq_en) | ||
214 | rtc->irq_en = false; | ||
215 | |||
216 | buff[0] = alrm->time.tm_min; | ||
217 | buff[1] = alrm->time.tm_hour; | ||
218 | buff[2] = alrm->time.tm_mday; | ||
219 | buff[3] = alrm->time.tm_mon + 1; | ||
220 | buff[4] = alrm->time.tm_year - rtc_year_offset; | ||
221 | convert_decimal_to_bcd(buff, sizeof(buff)); | ||
222 | err = ricoh583_write_regs(dev, rtc_alarm_y, sizeof(buff), buff); | ||
223 | if (err) { | ||
224 | dev_err(dev->parent, "\n unable to set alarm\n"); | ||
225 | return -EBUSY; | ||
226 | } | ||
227 | buff[0] = 0x20; /* to enable alarm_y */ | ||
228 | buff[1] = 0x20; /* to enable 24-hour format */ | ||
229 | err = ricoh583_write_regs(dev, rtc_ctrl1, 2, buff); | ||
230 | if (err) { | ||
231 | dev_err(dev, "failed programming rtc ctrl regs\n"); | ||
232 | return -EBUSY; | ||
233 | } | ||
234 | return err; | ||
235 | } | ||
236 | |||
237 | static int ricoh583_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
238 | { | ||
239 | u8 buff[5]; | ||
240 | int err; | ||
241 | |||
242 | err = ricoh583_read_regs(dev, rtc_alarm_y, sizeof(buff), buff); | ||
243 | if (err) | ||
244 | return err; | ||
245 | convert_bcd_to_decimal(buff, sizeof(buff)); | ||
246 | |||
247 | alrm->time.tm_min = buff[0]; | ||
248 | alrm->time.tm_hour = buff[1]; | ||
249 | alrm->time.tm_mday = buff[2]; | ||
250 | alrm->time.tm_mon = buff[3] - 1; | ||
251 | alrm->time.tm_year = buff[4] + rtc_year_offset; | ||
252 | |||
253 | dev_info(dev->parent, "\n getting alarm time::\n"); | ||
254 | print_time(dev, &alrm->time); | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static const struct rtc_class_ops ricoh583_rtc_ops = { | ||
260 | .read_time = ricoh583_rtc_read_time, | ||
261 | .set_time = ricoh583_rtc_set_time, | ||
262 | .set_alarm = ricoh583_rtc_set_alarm, | ||
263 | .read_alarm = ricoh583_rtc_read_alarm, | ||
264 | }; | ||
265 | |||
266 | static irqreturn_t ricoh583_rtc_irq(int irq, void *data) | ||
267 | { | ||
268 | struct device *dev = data; | ||
269 | struct ricoh583_rtc *rtc = dev_get_drvdata(dev); | ||
270 | u8 reg; | ||
271 | int err; | ||
272 | |||
273 | /* clear alarm-Y status bits.*/ | ||
274 | err = ricoh583_read_regs(dev, rtc_ctrl2, 1, ®); | ||
275 | if (err) { | ||
276 | dev_err(dev->parent, "unable to read rtc_ctrl2 reg\n"); | ||
277 | return -EBUSY; | ||
278 | } | ||
279 | reg &= ~0x8; | ||
280 | err = ricoh583_write_regs(dev, rtc_ctrl2, 1, ®); | ||
281 | if (err) { | ||
282 | dev_err(dev->parent, "unable to program rtc_status reg\n"); | ||
283 | return -EBUSY; | ||
284 | } | ||
285 | |||
286 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); | ||
287 | return IRQ_HANDLED; | ||
288 | } | ||
289 | |||
290 | static int __devinit ricoh583_rtc_probe(struct platform_device *pdev) | ||
291 | { | ||
292 | struct ricoh583_rtc_platform_data *pdata = pdev->dev.platform_data; | ||
293 | struct ricoh583_rtc *rtc; | ||
294 | struct rtc_time tm; | ||
295 | int err; | ||
296 | u8 reg[2]; | ||
297 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | ||
298 | |||
299 | if (!rtc) | ||
300 | return -ENOMEM; | ||
301 | |||
302 | rtc->irq = -1; | ||
303 | |||
304 | if (!pdata) { | ||
305 | dev_err(&pdev->dev, "no platform_data specified\n"); | ||
306 | return -EINVAL; | ||
307 | } | ||
308 | |||
309 | if (pdata->irq < 0) | ||
310 | dev_err(&pdev->dev, "\n no irq specified, wakeup is disabled\n"); | ||
311 | |||
312 | dev_set_drvdata(&pdev->dev, rtc); | ||
313 | device_init_wakeup(&pdev->dev, 1); | ||
314 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
315 | &ricoh583_rtc_ops, THIS_MODULE); | ||
316 | |||
317 | if (IS_ERR(rtc->rtc)) { | ||
318 | err = PTR_ERR(rtc->rtc); | ||
319 | goto fail; | ||
320 | } | ||
321 | reg[0] = 0; /* clearing RTC Adjust register */ | ||
322 | err = ricoh583_write_regs(&pdev->dev, rtc_adjust, 1, reg); | ||
323 | if (err) { | ||
324 | dev_err(&pdev->dev, "unable to program rtc_adjust reg\n"); | ||
325 | return -EBUSY; | ||
326 | } | ||
327 | |||
328 | reg[0] = 0x20; /* to enable alarm_y */ | ||
329 | reg[1] = 0x20; /* to enable 24-hour format */ | ||
330 | err = ricoh583_write_regs(&pdev->dev, rtc_ctrl1, 2, reg); | ||
331 | if (err) { | ||
332 | dev_err(&pdev->dev, "failed rtc setup\n"); | ||
333 | return -EBUSY; | ||
334 | } | ||
335 | |||
336 | ricoh583_rtc_read_time(&pdev->dev, &tm); | ||
337 | if (ricoh583_rtc_valid_tm(&pdev->dev, &tm)) { | ||
338 | if (pdata->time.tm_year < 2000 || pdata->time.tm_year > 2100) { | ||
339 | memset(&pdata->time, 0, sizeof(pdata->time)); | ||
340 | pdata->time.tm_year = rtc_year_offset; | ||
341 | pdata->time.tm_mday = 1; | ||
342 | } else | ||
343 | pdata->time.tm_year -= os_ref_year; | ||
344 | ricoh583_rtc_set_time(&pdev->dev, &pdata->time); | ||
345 | } | ||
346 | if (pdata && (pdata->irq >= 0)) { | ||
347 | rtc->irq = pdata->irq; | ||
348 | err = request_threaded_irq(pdata->irq, NULL, ricoh583_rtc_irq, | ||
349 | IRQF_ONESHOT, "rtc_ricoh583", | ||
350 | &pdev->dev); | ||
351 | if (err) { | ||
352 | dev_err(&pdev->dev, "request IRQ:%d fail\n", rtc->irq); | ||
353 | rtc->irq = -1; | ||
354 | } else { | ||
355 | device_init_wakeup(&pdev->dev, 1); | ||
356 | enable_irq_wake(rtc->irq); | ||
357 | } | ||
358 | } | ||
359 | return 0; | ||
360 | |||
361 | fail: | ||
362 | if (!IS_ERR_OR_NULL(rtc->rtc)) | ||
363 | rtc_device_unregister(rtc->rtc); | ||
364 | kfree(rtc); | ||
365 | return err; | ||
366 | } | ||
367 | |||
368 | static int __devexit ricoh583_rtc_remove(struct platform_device *pdev) | ||
369 | { | ||
370 | struct ricoh583_rtc *rtc = dev_get_drvdata(&pdev->dev); | ||
371 | |||
372 | if (rtc->irq != -1) | ||
373 | free_irq(rtc->irq, rtc); | ||
374 | rtc_device_unregister(rtc->rtc); | ||
375 | kfree(rtc); | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | static struct platform_driver ricoh583_rtc_driver = { | ||
380 | .driver = { | ||
381 | .name = "rtc_ricoh583", | ||
382 | .owner = THIS_MODULE, | ||
383 | }, | ||
384 | .probe = ricoh583_rtc_probe, | ||
385 | .remove = __devexit_p(ricoh583_rtc_remove), | ||
386 | }; | ||
387 | |||
388 | static int __init ricoh583_rtc_init(void) | ||
389 | { | ||
390 | return platform_driver_register(&ricoh583_rtc_driver); | ||
391 | } | ||
392 | module_init(ricoh583_rtc_init); | ||
393 | |||
394 | static void __exit ricoh583_rtc_exit(void) | ||
395 | { | ||
396 | platform_driver_unregister(&ricoh583_rtc_driver); | ||
397 | } | ||
398 | module_exit(ricoh583_rtc_exit); | ||
399 | |||
400 | MODULE_DESCRIPTION("RICOH PMU ricoh583 RTC driver"); | ||
401 | MODULE_AUTHOR("NVIDIA Corporation"); | ||
402 | MODULE_LICENSE("GPL"); | ||
403 | MODULE_ALIAS("platform:rtc_ricoh583"); | ||
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 16512ecae31..5b979d9cc33 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -51,17 +51,43 @@ static enum s3c_cpu_type s3c_rtc_cpu_type; | |||
51 | 51 | ||
52 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); | 52 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); |
53 | 53 | ||
54 | static void s3c_rtc_alarm_clk_enable(bool enable) | ||
55 | { | ||
56 | static DEFINE_SPINLOCK(s3c_rtc_alarm_clk_lock); | ||
57 | static bool alarm_clk_enabled; | ||
58 | unsigned long irq_flags; | ||
59 | |||
60 | spin_lock_irqsave(&s3c_rtc_alarm_clk_lock, irq_flags); | ||
61 | if (enable) { | ||
62 | if (!alarm_clk_enabled) { | ||
63 | clk_enable(rtc_clk); | ||
64 | alarm_clk_enabled = true; | ||
65 | } | ||
66 | } else { | ||
67 | if (alarm_clk_enabled) { | ||
68 | clk_disable(rtc_clk); | ||
69 | alarm_clk_enabled = false; | ||
70 | } | ||
71 | } | ||
72 | spin_unlock_irqrestore(&s3c_rtc_alarm_clk_lock, irq_flags); | ||
73 | } | ||
74 | |||
54 | /* IRQ Handlers */ | 75 | /* IRQ Handlers */ |
55 | 76 | ||
56 | static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) | 77 | static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) |
57 | { | 78 | { |
58 | struct rtc_device *rdev = id; | 79 | struct rtc_device *rdev = id; |
59 | 80 | ||
81 | clk_enable(rtc_clk); | ||
60 | rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); | 82 | rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); |
61 | 83 | ||
62 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | 84 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
63 | writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP); | 85 | writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP); |
64 | 86 | ||
87 | clk_disable(rtc_clk); | ||
88 | |||
89 | s3c_rtc_alarm_clk_enable(false); | ||
90 | |||
65 | return IRQ_HANDLED; | 91 | return IRQ_HANDLED; |
66 | } | 92 | } |
67 | 93 | ||
@@ -69,11 +95,13 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id) | |||
69 | { | 95 | { |
70 | struct rtc_device *rdev = id; | 96 | struct rtc_device *rdev = id; |
71 | 97 | ||
98 | clk_enable(rtc_clk); | ||
72 | rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); | 99 | rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); |
73 | 100 | ||
74 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | 101 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
75 | writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP); | 102 | writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP); |
76 | 103 | ||
104 | clk_disable(rtc_clk); | ||
77 | return IRQ_HANDLED; | 105 | return IRQ_HANDLED; |
78 | } | 106 | } |
79 | 107 | ||
@@ -84,12 +112,16 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled) | |||
84 | 112 | ||
85 | pr_debug("%s: aie=%d\n", __func__, enabled); | 113 | pr_debug("%s: aie=%d\n", __func__, enabled); |
86 | 114 | ||
115 | clk_enable(rtc_clk); | ||
87 | tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; | 116 | tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; |
88 | 117 | ||
89 | if (enabled) | 118 | if (enabled) |
90 | tmp |= S3C2410_RTCALM_ALMEN; | 119 | tmp |= S3C2410_RTCALM_ALMEN; |
91 | 120 | ||
92 | writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); | 121 | writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); |
122 | clk_disable(rtc_clk); | ||
123 | |||
124 | s3c_rtc_alarm_clk_enable(enabled); | ||
93 | 125 | ||
94 | return 0; | 126 | return 0; |
95 | } | 127 | } |
@@ -103,6 +135,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq) | |||
103 | if (!is_power_of_2(freq)) | 135 | if (!is_power_of_2(freq)) |
104 | return -EINVAL; | 136 | return -EINVAL; |
105 | 137 | ||
138 | clk_enable(rtc_clk); | ||
106 | spin_lock_irq(&s3c_rtc_pie_lock); | 139 | spin_lock_irq(&s3c_rtc_pie_lock); |
107 | 140 | ||
108 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { | 141 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { |
@@ -114,6 +147,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq) | |||
114 | 147 | ||
115 | writel(tmp, s3c_rtc_base + S3C2410_TICNT); | 148 | writel(tmp, s3c_rtc_base + S3C2410_TICNT); |
116 | spin_unlock_irq(&s3c_rtc_pie_lock); | 149 | spin_unlock_irq(&s3c_rtc_pie_lock); |
150 | clk_disable(rtc_clk); | ||
117 | 151 | ||
118 | return 0; | 152 | return 0; |
119 | } | 153 | } |
@@ -125,6 +159,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
125 | unsigned int have_retried = 0; | 159 | unsigned int have_retried = 0; |
126 | void __iomem *base = s3c_rtc_base; | 160 | void __iomem *base = s3c_rtc_base; |
127 | 161 | ||
162 | clk_enable(rtc_clk); | ||
128 | retry_get_time: | 163 | retry_get_time: |
129 | rtc_tm->tm_min = readb(base + S3C2410_RTCMIN); | 164 | rtc_tm->tm_min = readb(base + S3C2410_RTCMIN); |
130 | rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR); | 165 | rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR); |
@@ -143,10 +178,6 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
143 | goto retry_get_time; | 178 | goto retry_get_time; |
144 | } | 179 | } |
145 | 180 | ||
146 | pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n", | ||
147 | 1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, | ||
148 | rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); | ||
149 | |||
150 | rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); | 181 | rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); |
151 | rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min); | 182 | rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min); |
152 | rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour); | 183 | rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour); |
@@ -155,8 +186,14 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
155 | rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year); | 186 | rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year); |
156 | 187 | ||
157 | rtc_tm->tm_year += 100; | 188 | rtc_tm->tm_year += 100; |
189 | |||
190 | pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n", | ||
191 | 1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, | ||
192 | rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); | ||
193 | |||
158 | rtc_tm->tm_mon -= 1; | 194 | rtc_tm->tm_mon -= 1; |
159 | 195 | ||
196 | clk_disable(rtc_clk); | ||
160 | return rtc_valid_tm(rtc_tm); | 197 | return rtc_valid_tm(rtc_tm); |
161 | } | 198 | } |
162 | 199 | ||
@@ -176,12 +213,14 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
176 | return -EINVAL; | 213 | return -EINVAL; |
177 | } | 214 | } |
178 | 215 | ||
216 | clk_enable(rtc_clk); | ||
179 | writeb(bin2bcd(tm->tm_sec), base + S3C2410_RTCSEC); | 217 | writeb(bin2bcd(tm->tm_sec), base + S3C2410_RTCSEC); |
180 | writeb(bin2bcd(tm->tm_min), base + S3C2410_RTCMIN); | 218 | writeb(bin2bcd(tm->tm_min), base + S3C2410_RTCMIN); |
181 | writeb(bin2bcd(tm->tm_hour), base + S3C2410_RTCHOUR); | 219 | writeb(bin2bcd(tm->tm_hour), base + S3C2410_RTCHOUR); |
182 | writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE); | 220 | writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE); |
183 | writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON); | 221 | writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON); |
184 | writeb(bin2bcd(year), base + S3C2410_RTCYEAR); | 222 | writeb(bin2bcd(year), base + S3C2410_RTCYEAR); |
223 | clk_disable(rtc_clk); | ||
185 | 224 | ||
186 | return 0; | 225 | return 0; |
187 | } | 226 | } |
@@ -192,6 +231,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
192 | void __iomem *base = s3c_rtc_base; | 231 | void __iomem *base = s3c_rtc_base; |
193 | unsigned int alm_en; | 232 | unsigned int alm_en; |
194 | 233 | ||
234 | clk_enable(rtc_clk); | ||
195 | alm_tm->tm_sec = readb(base + S3C2410_ALMSEC); | 235 | alm_tm->tm_sec = readb(base + S3C2410_ALMSEC); |
196 | alm_tm->tm_min = readb(base + S3C2410_ALMMIN); | 236 | alm_tm->tm_min = readb(base + S3C2410_ALMMIN); |
197 | alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR); | 237 | alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR); |
@@ -243,6 +283,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
243 | else | 283 | else |
244 | alm_tm->tm_year = -1; | 284 | alm_tm->tm_year = -1; |
245 | 285 | ||
286 | clk_disable(rtc_clk); | ||
246 | return 0; | 287 | return 0; |
247 | } | 288 | } |
248 | 289 | ||
@@ -252,12 +293,12 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
252 | void __iomem *base = s3c_rtc_base; | 293 | void __iomem *base = s3c_rtc_base; |
253 | unsigned int alrm_en; | 294 | unsigned int alrm_en; |
254 | 295 | ||
296 | clk_enable(rtc_clk); | ||
255 | pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", | 297 | pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", |
256 | alrm->enabled, | 298 | alrm->enabled, |
257 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | 299 | 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, |
258 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 300 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
259 | 301 | ||
260 | |||
261 | alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; | 302 | alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; |
262 | writeb(0x00, base + S3C2410_RTCALM); | 303 | writeb(0x00, base + S3C2410_RTCALM); |
263 | 304 | ||
@@ -282,6 +323,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
282 | 323 | ||
283 | s3c_rtc_setaie(dev, alrm->enabled); | 324 | s3c_rtc_setaie(dev, alrm->enabled); |
284 | 325 | ||
326 | clk_disable(rtc_clk); | ||
285 | return 0; | 327 | return 0; |
286 | } | 328 | } |
287 | 329 | ||
@@ -289,6 +331,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) | |||
289 | { | 331 | { |
290 | unsigned int ticnt; | 332 | unsigned int ticnt; |
291 | 333 | ||
334 | clk_enable(rtc_clk); | ||
292 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | 335 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
293 | ticnt = readw(s3c_rtc_base + S3C2410_RTCCON); | 336 | ticnt = readw(s3c_rtc_base + S3C2410_RTCCON); |
294 | ticnt &= S3C64XX_RTCCON_TICEN; | 337 | ticnt &= S3C64XX_RTCCON_TICEN; |
@@ -298,52 +341,11 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) | |||
298 | } | 341 | } |
299 | 342 | ||
300 | seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); | 343 | seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); |
344 | clk_disable(rtc_clk); | ||
301 | return 0; | 345 | return 0; |
302 | } | 346 | } |
303 | 347 | ||
304 | static int s3c_rtc_open(struct device *dev) | ||
305 | { | ||
306 | struct platform_device *pdev = to_platform_device(dev); | ||
307 | struct rtc_device *rtc_dev = platform_get_drvdata(pdev); | ||
308 | int ret; | ||
309 | |||
310 | ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq, | ||
311 | IRQF_DISABLED, "s3c2410-rtc alarm", rtc_dev); | ||
312 | |||
313 | if (ret) { | ||
314 | dev_err(dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret); | ||
315 | return ret; | ||
316 | } | ||
317 | |||
318 | ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq, | ||
319 | IRQF_DISABLED, "s3c2410-rtc tick", rtc_dev); | ||
320 | |||
321 | if (ret) { | ||
322 | dev_err(dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret); | ||
323 | goto tick_err; | ||
324 | } | ||
325 | |||
326 | return ret; | ||
327 | |||
328 | tick_err: | ||
329 | free_irq(s3c_rtc_alarmno, rtc_dev); | ||
330 | return ret; | ||
331 | } | ||
332 | |||
333 | static void s3c_rtc_release(struct device *dev) | ||
334 | { | ||
335 | struct platform_device *pdev = to_platform_device(dev); | ||
336 | struct rtc_device *rtc_dev = platform_get_drvdata(pdev); | ||
337 | |||
338 | /* do not clear AIE here, it may be needed for wake */ | ||
339 | |||
340 | free_irq(s3c_rtc_alarmno, rtc_dev); | ||
341 | free_irq(s3c_rtc_tickno, rtc_dev); | ||
342 | } | ||
343 | |||
344 | static const struct rtc_class_ops s3c_rtcops = { | 348 | static const struct rtc_class_ops s3c_rtcops = { |
345 | .open = s3c_rtc_open, | ||
346 | .release = s3c_rtc_release, | ||
347 | .read_time = s3c_rtc_gettime, | 349 | .read_time = s3c_rtc_gettime, |
348 | .set_time = s3c_rtc_settime, | 350 | .set_time = s3c_rtc_settime, |
349 | .read_alarm = s3c_rtc_getalarm, | 351 | .read_alarm = s3c_rtc_getalarm, |
@@ -360,6 +362,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
360 | if (s3c_rtc_base == NULL) | 362 | if (s3c_rtc_base == NULL) |
361 | return; | 363 | return; |
362 | 364 | ||
365 | clk_enable(rtc_clk); | ||
363 | if (!en) { | 366 | if (!en) { |
364 | tmp = readw(base + S3C2410_RTCCON); | 367 | tmp = readw(base + S3C2410_RTCCON); |
365 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | 368 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
@@ -399,18 +402,21 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
399 | base + S3C2410_RTCCON); | 402 | base + S3C2410_RTCCON); |
400 | } | 403 | } |
401 | } | 404 | } |
405 | clk_disable(rtc_clk); | ||
402 | } | 406 | } |
403 | 407 | ||
404 | static int __devexit s3c_rtc_remove(struct platform_device *dev) | 408 | static int __devexit s3c_rtc_remove(struct platform_device *dev) |
405 | { | 409 | { |
406 | struct rtc_device *rtc = platform_get_drvdata(dev); | 410 | struct rtc_device *rtc = platform_get_drvdata(dev); |
407 | 411 | ||
412 | free_irq(s3c_rtc_alarmno, rtc); | ||
413 | free_irq(s3c_rtc_tickno, rtc); | ||
414 | |||
408 | platform_set_drvdata(dev, NULL); | 415 | platform_set_drvdata(dev, NULL); |
409 | rtc_device_unregister(rtc); | 416 | rtc_device_unregister(rtc); |
410 | 417 | ||
411 | s3c_rtc_setaie(&dev->dev, 0); | 418 | s3c_rtc_setaie(&dev->dev, 0); |
412 | 419 | ||
413 | clk_disable(rtc_clk); | ||
414 | clk_put(rtc_clk); | 420 | clk_put(rtc_clk); |
415 | rtc_clk = NULL; | 421 | rtc_clk = NULL; |
416 | 422 | ||
@@ -455,8 +461,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
455 | return -ENOENT; | 461 | return -ENOENT; |
456 | } | 462 | } |
457 | 463 | ||
458 | s3c_rtc_mem = request_mem_region(res->start, | 464 | s3c_rtc_mem = request_mem_region(res->start, resource_size(res), |
459 | res->end-res->start+1, | ||
460 | pdev->name); | 465 | pdev->name); |
461 | 466 | ||
462 | if (s3c_rtc_mem == NULL) { | 467 | if (s3c_rtc_mem == NULL) { |
@@ -465,7 +470,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
465 | goto err_nores; | 470 | goto err_nores; |
466 | } | 471 | } |
467 | 472 | ||
468 | s3c_rtc_base = ioremap(res->start, res->end - res->start + 1); | 473 | s3c_rtc_base = ioremap(res->start, resource_size(res)); |
469 | if (s3c_rtc_base == NULL) { | 474 | if (s3c_rtc_base == NULL) { |
470 | dev_err(&pdev->dev, "failed ioremap()\n"); | 475 | dev_err(&pdev->dev, "failed ioremap()\n"); |
471 | ret = -EINVAL; | 476 | ret = -EINVAL; |
@@ -530,8 +535,32 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
530 | 535 | ||
531 | s3c_rtc_setfreq(&pdev->dev, 1); | 536 | s3c_rtc_setfreq(&pdev->dev, 1); |
532 | 537 | ||
538 | ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq, | ||
539 | IRQF_DISABLED, "s3c2410-rtc alarm", rtc); | ||
540 | if (ret) { | ||
541 | dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret); | ||
542 | goto err_alarm_irq; | ||
543 | } | ||
544 | |||
545 | ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq, | ||
546 | IRQF_DISABLED, "s3c2410-rtc tick", rtc); | ||
547 | if (ret) { | ||
548 | dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret); | ||
549 | free_irq(s3c_rtc_alarmno, rtc); | ||
550 | goto err_tick_irq; | ||
551 | } | ||
552 | |||
553 | clk_disable(rtc_clk); | ||
554 | |||
533 | return 0; | 555 | return 0; |
534 | 556 | ||
557 | err_tick_irq: | ||
558 | free_irq(s3c_rtc_alarmno, rtc); | ||
559 | |||
560 | err_alarm_irq: | ||
561 | platform_set_drvdata(pdev, NULL); | ||
562 | rtc_device_unregister(rtc); | ||
563 | |||
535 | err_nortc: | 564 | err_nortc: |
536 | s3c_rtc_enable(pdev, 0); | 565 | s3c_rtc_enable(pdev, 0); |
537 | clk_disable(rtc_clk); | 566 | clk_disable(rtc_clk); |
@@ -555,6 +584,7 @@ static int ticnt_save, ticnt_en_save; | |||
555 | 584 | ||
556 | static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 585 | static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
557 | { | 586 | { |
587 | clk_enable(rtc_clk); | ||
558 | /* save TICNT for anyone using periodic interrupts */ | 588 | /* save TICNT for anyone using periodic interrupts */ |
559 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); | 589 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); |
560 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | 590 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
@@ -569,6 +599,7 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
569 | else | 599 | else |
570 | dev_err(&pdev->dev, "enable_irq_wake failed\n"); | 600 | dev_err(&pdev->dev, "enable_irq_wake failed\n"); |
571 | } | 601 | } |
602 | clk_disable(rtc_clk); | ||
572 | 603 | ||
573 | return 0; | 604 | return 0; |
574 | } | 605 | } |
@@ -577,6 +608,7 @@ static int s3c_rtc_resume(struct platform_device *pdev) | |||
577 | { | 608 | { |
578 | unsigned int tmp; | 609 | unsigned int tmp; |
579 | 610 | ||
611 | clk_enable(rtc_clk); | ||
580 | s3c_rtc_enable(pdev, 1); | 612 | s3c_rtc_enable(pdev, 1); |
581 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); | 613 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); |
582 | if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { | 614 | if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { |
@@ -588,6 +620,7 @@ static int s3c_rtc_resume(struct platform_device *pdev) | |||
588 | disable_irq_wake(s3c_rtc_alarmno); | 620 | disable_irq_wake(s3c_rtc_alarmno); |
589 | wake_en = false; | 621 | wake_en = false; |
590 | } | 622 | } |
623 | clk_disable(rtc_clk); | ||
591 | 624 | ||
592 | return 0; | 625 | return 0; |
593 | } | 626 | } |
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index 572e9534b59..7315068daa5 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c | |||
@@ -6,6 +6,7 @@ | |||
6 | * | 6 | * |
7 | * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. | 7 | * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. |
8 | * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. | 8 | * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. |
9 | * Copyright 2011 Wolfram Sang, Pengutronix e.K. | ||
9 | */ | 10 | */ |
10 | 11 | ||
11 | /* | 12 | /* |
@@ -18,21 +19,41 @@ | |||
18 | */ | 19 | */ |
19 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/io.h> | ||
21 | #include <linux/init.h> | 23 | #include <linux/init.h> |
22 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
23 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
24 | #include <linux/rtc.h> | 26 | #include <linux/rtc.h> |
25 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
26 | 28 | ||
27 | #include <mach/platform.h> | 29 | #include <mach/common.h> |
28 | #include <mach/stmp3xxx.h> | 30 | |
29 | #include <mach/regs-rtc.h> | 31 | #define STMP3XXX_RTC_CTRL 0x0 |
32 | #define STMP3XXX_RTC_CTRL_SET 0x4 | ||
33 | #define STMP3XXX_RTC_CTRL_CLR 0x8 | ||
34 | #define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN 0x00000001 | ||
35 | #define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN 0x00000002 | ||
36 | #define STMP3XXX_RTC_CTRL_ALARM_IRQ 0x00000004 | ||
37 | |||
38 | #define STMP3XXX_RTC_STAT 0x10 | ||
39 | #define STMP3XXX_RTC_STAT_STALE_SHIFT 16 | ||
40 | #define STMP3XXX_RTC_STAT_RTC_PRESENT 0x80000000 | ||
41 | |||
42 | #define STMP3XXX_RTC_SECONDS 0x30 | ||
43 | |||
44 | #define STMP3XXX_RTC_ALARM 0x40 | ||
45 | |||
46 | #define STMP3XXX_RTC_PERSISTENT0 0x60 | ||
47 | #define STMP3XXX_RTC_PERSISTENT0_SET 0x64 | ||
48 | #define STMP3XXX_RTC_PERSISTENT0_CLR 0x68 | ||
49 | #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN 0x00000002 | ||
50 | #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN 0x00000004 | ||
51 | #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE 0x00000080 | ||
30 | 52 | ||
31 | struct stmp3xxx_rtc_data { | 53 | struct stmp3xxx_rtc_data { |
32 | struct rtc_device *rtc; | 54 | struct rtc_device *rtc; |
33 | unsigned irq_count; | ||
34 | void __iomem *io; | 55 | void __iomem *io; |
35 | int irq_alarm, irq_1msec; | 56 | int irq_alarm; |
36 | }; | 57 | }; |
37 | 58 | ||
38 | static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data) | 59 | static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data) |
@@ -42,8 +63,8 @@ static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data) | |||
42 | * NEW_REGS/STALE_REGS bitfields go. In fact it's 0x1=P0, | 63 | * NEW_REGS/STALE_REGS bitfields go. In fact it's 0x1=P0, |
43 | * 0x2=P1, .., 0x20=P5, 0x40=ALARM, 0x80=SECONDS | 64 | * 0x2=P1, .., 0x20=P5, 0x40=ALARM, 0x80=SECONDS |
44 | */ | 65 | */ |
45 | while (__raw_readl(rtc_data->io + HW_RTC_STAT) & | 66 | while (readl(rtc_data->io + STMP3XXX_RTC_STAT) & |
46 | BF(0x80, RTC_STAT_STALE_REGS)) | 67 | (0x80 << STMP3XXX_RTC_STAT_STALE_SHIFT)) |
47 | cpu_relax(); | 68 | cpu_relax(); |
48 | } | 69 | } |
49 | 70 | ||
@@ -53,7 +74,7 @@ static int stmp3xxx_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
53 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | 74 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); |
54 | 75 | ||
55 | stmp3xxx_wait_time(rtc_data); | 76 | stmp3xxx_wait_time(rtc_data); |
56 | rtc_time_to_tm(__raw_readl(rtc_data->io + HW_RTC_SECONDS), rtc_tm); | 77 | rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_SECONDS), rtc_tm); |
57 | return 0; | 78 | return 0; |
58 | } | 79 | } |
59 | 80 | ||
@@ -61,7 +82,7 @@ static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t) | |||
61 | { | 82 | { |
62 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | 83 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); |
63 | 84 | ||
64 | __raw_writel(t, rtc_data->io + HW_RTC_SECONDS); | 85 | writel(t, rtc_data->io + STMP3XXX_RTC_SECONDS); |
65 | stmp3xxx_wait_time(rtc_data); | 86 | stmp3xxx_wait_time(rtc_data); |
66 | return 0; | 87 | return 0; |
67 | } | 88 | } |
@@ -70,47 +91,34 @@ static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t) | |||
70 | static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id) | 91 | static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id) |
71 | { | 92 | { |
72 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev_id); | 93 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev_id); |
73 | u32 status; | 94 | u32 status = readl(rtc_data->io + STMP3XXX_RTC_CTRL); |
74 | u32 events = 0; | ||
75 | |||
76 | status = __raw_readl(rtc_data->io + HW_RTC_CTRL) & | ||
77 | (BM_RTC_CTRL_ALARM_IRQ | BM_RTC_CTRL_ONEMSEC_IRQ); | ||
78 | 95 | ||
79 | if (status & BM_RTC_CTRL_ALARM_IRQ) { | 96 | if (status & STMP3XXX_RTC_CTRL_ALARM_IRQ) { |
80 | stmp3xxx_clearl(BM_RTC_CTRL_ALARM_IRQ, | 97 | writel(STMP3XXX_RTC_CTRL_ALARM_IRQ, |
81 | rtc_data->io + HW_RTC_CTRL); | 98 | rtc_data->io + STMP3XXX_RTC_CTRL_CLR); |
82 | events |= RTC_AF | RTC_IRQF; | 99 | rtc_update_irq(rtc_data->rtc, 1, RTC_AF | RTC_IRQF); |
100 | return IRQ_HANDLED; | ||
83 | } | 101 | } |
84 | 102 | ||
85 | if (status & BM_RTC_CTRL_ONEMSEC_IRQ) { | 103 | return IRQ_NONE; |
86 | stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ, | ||
87 | rtc_data->io + HW_RTC_CTRL); | ||
88 | if (++rtc_data->irq_count % 1000 == 0) { | ||
89 | events |= RTC_UF | RTC_IRQF; | ||
90 | rtc_data->irq_count = 0; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | if (events) | ||
95 | rtc_update_irq(rtc_data->rtc, 1, events); | ||
96 | |||
97 | return IRQ_HANDLED; | ||
98 | } | 104 | } |
99 | 105 | ||
100 | static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled) | 106 | static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled) |
101 | { | 107 | { |
102 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | 108 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); |
103 | void __iomem *p = rtc_data->io + HW_RTC_PERSISTENT0, | ||
104 | *ctl = rtc_data->io + HW_RTC_CTRL; | ||
105 | 109 | ||
106 | if (enabled) { | 110 | if (enabled) { |
107 | stmp3xxx_setl(BM_RTC_PERSISTENT0_ALARM_EN | | 111 | writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | |
108 | BM_RTC_PERSISTENT0_ALARM_WAKE_EN, p); | 112 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN, |
109 | stmp3xxx_setl(BM_RTC_CTRL_ALARM_IRQ_EN, ctl); | 113 | rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET); |
114 | writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, | ||
115 | rtc_data->io + STMP3XXX_RTC_CTRL_SET); | ||
110 | } else { | 116 | } else { |
111 | stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN | | 117 | writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | |
112 | BM_RTC_PERSISTENT0_ALARM_WAKE_EN, p); | 118 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN, |
113 | stmp3xxx_clearl(BM_RTC_CTRL_ALARM_IRQ_EN, ctl); | 119 | rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); |
120 | writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, | ||
121 | rtc_data->io + STMP3XXX_RTC_CTRL_CLR); | ||
114 | } | 122 | } |
115 | return 0; | 123 | return 0; |
116 | } | 124 | } |
@@ -119,7 +127,7 @@ static int stmp3xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
119 | { | 127 | { |
120 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | 128 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); |
121 | 129 | ||
122 | rtc_time_to_tm(__raw_readl(rtc_data->io + HW_RTC_ALARM), &alm->time); | 130 | rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_ALARM), &alm->time); |
123 | return 0; | 131 | return 0; |
124 | } | 132 | } |
125 | 133 | ||
@@ -129,7 +137,10 @@ static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
129 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | 137 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); |
130 | 138 | ||
131 | rtc_tm_to_time(&alm->time, &t); | 139 | rtc_tm_to_time(&alm->time, &t); |
132 | __raw_writel(t, rtc_data->io + HW_RTC_ALARM); | 140 | writel(t, rtc_data->io + STMP3XXX_RTC_ALARM); |
141 | |||
142 | stmp3xxx_alarm_irq_enable(dev, alm->enabled); | ||
143 | |||
133 | return 0; | 144 | return 0; |
134 | } | 145 | } |
135 | 146 | ||
@@ -149,11 +160,11 @@ static int stmp3xxx_rtc_remove(struct platform_device *pdev) | |||
149 | if (!rtc_data) | 160 | if (!rtc_data) |
150 | return 0; | 161 | return 0; |
151 | 162 | ||
152 | stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN | BM_RTC_CTRL_ALARM_IRQ_EN, | 163 | writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, |
153 | rtc_data->io + HW_RTC_CTRL); | 164 | rtc_data->io + STMP3XXX_RTC_CTRL_CLR); |
154 | free_irq(rtc_data->irq_alarm, &pdev->dev); | 165 | free_irq(rtc_data->irq_alarm, &pdev->dev); |
155 | free_irq(rtc_data->irq_1msec, &pdev->dev); | ||
156 | rtc_device_unregister(rtc_data->rtc); | 166 | rtc_device_unregister(rtc_data->rtc); |
167 | platform_set_drvdata(pdev, NULL); | ||
157 | iounmap(rtc_data->io); | 168 | iounmap(rtc_data->io); |
158 | kfree(rtc_data); | 169 | kfree(rtc_data); |
159 | 170 | ||
@@ -185,20 +196,26 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) | |||
185 | } | 196 | } |
186 | 197 | ||
187 | rtc_data->irq_alarm = platform_get_irq(pdev, 0); | 198 | rtc_data->irq_alarm = platform_get_irq(pdev, 0); |
188 | rtc_data->irq_1msec = platform_get_irq(pdev, 1); | ||
189 | 199 | ||
190 | if (!(__raw_readl(HW_RTC_STAT + rtc_data->io) & | 200 | if (!(readl(STMP3XXX_RTC_STAT + rtc_data->io) & |
191 | BM_RTC_STAT_RTC_PRESENT)) { | 201 | STMP3XXX_RTC_STAT_RTC_PRESENT)) { |
192 | dev_err(&pdev->dev, "no device onboard\n"); | 202 | dev_err(&pdev->dev, "no device onboard\n"); |
193 | err = -ENODEV; | 203 | err = -ENODEV; |
194 | goto out_remap; | 204 | goto out_remap; |
195 | } | 205 | } |
196 | 206 | ||
197 | stmp3xxx_reset_block(rtc_data->io, true); | 207 | platform_set_drvdata(pdev, rtc_data); |
198 | stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN | | 208 | |
199 | BM_RTC_PERSISTENT0_ALARM_WAKE_EN | | 209 | mxs_reset_block(rtc_data->io); |
200 | BM_RTC_PERSISTENT0_ALARM_WAKE, | 210 | writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | |
201 | rtc_data->io + HW_RTC_PERSISTENT0); | 211 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN | |
212 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, | ||
213 | rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); | ||
214 | |||
215 | writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN | | ||
216 | STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, | ||
217 | rtc_data->io + STMP3XXX_RTC_CTRL_CLR); | ||
218 | |||
202 | rtc_data->rtc = rtc_device_register(pdev->name, &pdev->dev, | 219 | rtc_data->rtc = rtc_device_register(pdev->name, &pdev->dev, |
203 | &stmp3xxx_rtc_ops, THIS_MODULE); | 220 | &stmp3xxx_rtc_ops, THIS_MODULE); |
204 | if (IS_ERR(rtc_data->rtc)) { | 221 | if (IS_ERR(rtc_data->rtc)) { |
@@ -206,33 +223,20 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) | |||
206 | goto out_remap; | 223 | goto out_remap; |
207 | } | 224 | } |
208 | 225 | ||
209 | rtc_data->irq_count = 0; | 226 | err = request_irq(rtc_data->irq_alarm, stmp3xxx_rtc_interrupt, 0, |
210 | err = request_irq(rtc_data->irq_alarm, stmp3xxx_rtc_interrupt, | 227 | "RTC alarm", &pdev->dev); |
211 | IRQF_DISABLED, "RTC alarm", &pdev->dev); | ||
212 | if (err) { | 228 | if (err) { |
213 | dev_err(&pdev->dev, "Cannot claim IRQ%d\n", | 229 | dev_err(&pdev->dev, "Cannot claim IRQ%d\n", |
214 | rtc_data->irq_alarm); | 230 | rtc_data->irq_alarm); |
215 | goto out_irq_alarm; | 231 | goto out_irq_alarm; |
216 | } | 232 | } |
217 | err = request_irq(rtc_data->irq_1msec, stmp3xxx_rtc_interrupt, | ||
218 | IRQF_DISABLED, "RTC tick", &pdev->dev); | ||
219 | if (err) { | ||
220 | dev_err(&pdev->dev, "Cannot claim IRQ%d\n", | ||
221 | rtc_data->irq_1msec); | ||
222 | goto out_irq1; | ||
223 | } | ||
224 | |||
225 | platform_set_drvdata(pdev, rtc_data); | ||
226 | 233 | ||
227 | return 0; | 234 | return 0; |
228 | 235 | ||
229 | out_irq1: | ||
230 | free_irq(rtc_data->irq_alarm, &pdev->dev); | ||
231 | out_irq_alarm: | 236 | out_irq_alarm: |
232 | stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN | BM_RTC_CTRL_ALARM_IRQ_EN, | ||
233 | rtc_data->io + HW_RTC_CTRL); | ||
234 | rtc_device_unregister(rtc_data->rtc); | 237 | rtc_device_unregister(rtc_data->rtc); |
235 | out_remap: | 238 | out_remap: |
239 | platform_set_drvdata(pdev, NULL); | ||
236 | iounmap(rtc_data->io); | 240 | iounmap(rtc_data->io); |
237 | out_free: | 241 | out_free: |
238 | kfree(rtc_data); | 242 | kfree(rtc_data); |
@@ -249,11 +253,11 @@ static int stmp3xxx_rtc_resume(struct platform_device *dev) | |||
249 | { | 253 | { |
250 | struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(dev); | 254 | struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(dev); |
251 | 255 | ||
252 | stmp3xxx_reset_block(rtc_data->io, true); | 256 | mxs_reset_block(rtc_data->io); |
253 | stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN | | 257 | writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | |
254 | BM_RTC_PERSISTENT0_ALARM_WAKE_EN | | 258 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN | |
255 | BM_RTC_PERSISTENT0_ALARM_WAKE, | 259 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, |
256 | rtc_data->io + HW_RTC_PERSISTENT0); | 260 | rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); |
257 | return 0; | 261 | return 0; |
258 | } | 262 | } |
259 | #else | 263 | #else |
@@ -286,5 +290,6 @@ module_init(stmp3xxx_rtc_init); | |||
286 | module_exit(stmp3xxx_rtc_exit); | 290 | module_exit(stmp3xxx_rtc_exit); |
287 | 291 | ||
288 | MODULE_DESCRIPTION("STMP3xxx RTC Driver"); | 292 | MODULE_DESCRIPTION("STMP3xxx RTC Driver"); |
289 | MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com>"); | 293 | MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and " |
294 | "Wolfram Sang <w.sang@pengutronix.de>"); | ||
290 | MODULE_LICENSE("GPL"); | 295 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index 2fc31aac3f4..773adffac27 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * An RTC driver for the NVIDIA Tegra 200 series internal RTC. | 2 | * An RTC driver for the NVIDIA Tegra 200 series internal RTC. |
3 | * | 3 | * |
4 | * Copyright (c) 2010, NVIDIA Corporation. | 4 | * Copyright (c) 2010-2011, NVIDIA Corporation. |
5 | * Copyright (c) 2010 Jon Mayo <jmayo@nvidia.com> | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
@@ -343,7 +344,7 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev) | |||
343 | 344 | ||
344 | /* set context info. */ | 345 | /* set context info. */ |
345 | info->pdev = pdev; | 346 | info->pdev = pdev; |
346 | info->tegra_rtc_lock = __SPIN_LOCK_UNLOCKED(info->tegra_rtc_lock); | 347 | spin_lock_init(&info->tegra_rtc_lock); |
347 | 348 | ||
348 | platform_set_drvdata(pdev, info); | 349 | platform_set_drvdata(pdev, info); |
349 | 350 | ||
@@ -376,6 +377,36 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev) | |||
376 | 377 | ||
377 | dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n"); | 378 | dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n"); |
378 | 379 | ||
380 | #ifndef CONFIG_TEGRA_SILICON_PLATFORM | ||
381 | { | ||
382 | struct rtc_time tm; | ||
383 | |||
384 | /* Get the current time from the RTC. */ | ||
385 | ret = tegra_rtc_read_time(&pdev->dev, &tm); | ||
386 | if (ret) { | ||
387 | /* Report but ignore this error. */ | ||
388 | dev_err(&pdev->dev, | ||
389 | "Failed to get FPGA internal RTC time (err=%d)\n", | ||
390 | ret); | ||
391 | } else if (tm.tm_year < 2010) { | ||
392 | /* The RTC's default reset time is soooo last century. */ | ||
393 | tm.tm_year = 2010-1900; | ||
394 | tm.tm_mon = 0; | ||
395 | tm.tm_mday = 1; | ||
396 | tm.tm_hour = 0; | ||
397 | tm.tm_min = 0; | ||
398 | tm.tm_sec = 0; | ||
399 | ret = tegra_rtc_set_time(&pdev->dev, &tm); | ||
400 | if (ret) { | ||
401 | /* Report but ignore this error. */ | ||
402 | dev_err(&pdev->dev, | ||
403 | "Failed to set FPGA internal RTC time (err=%d)\n", | ||
404 | ret); | ||
405 | } | ||
406 | } | ||
407 | } | ||
408 | #endif | ||
409 | |||
379 | return 0; | 410 | return 0; |
380 | 411 | ||
381 | err_dev_unreg: | 412 | err_dev_unreg: |
diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c new file mode 100644 index 00000000000..c41edabf0b2 --- /dev/null +++ b/drivers/rtc/rtc-tps6586x.c | |||
@@ -0,0 +1,387 @@ | |||
1 | /* | ||
2 | * drivers/rtc/rtc-tps6586x.c | ||
3 | * | ||
4 | * RTC driver for TI TPS6586x | ||
5 | * | ||
6 | * Copyright (c) 2010, NVIDIA Corporation. | ||
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, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/device.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/mfd/tps6586x.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/rtc.h> | ||
30 | #include <linux/slab.h> | ||
31 | |||
32 | #define RTC_CTRL 0xc0 | ||
33 | #define POR_RESET_N BIT(7) | ||
34 | #define OSC_SRC_SEL BIT(6) | ||
35 | #define RTC_ENABLE BIT(5) /* enables alarm */ | ||
36 | #define RTC_BUF_ENABLE BIT(4) /* 32 KHz buffer enable */ | ||
37 | #define PRE_BYPASS BIT(3) /* 0=1KHz or 1=32KHz updates */ | ||
38 | #define CL_SEL_MASK (BIT(2)|BIT(1)) | ||
39 | #define CL_SEL_POS 1 | ||
40 | #define RTC_ALARM1_HI 0xc1 | ||
41 | #define RTC_COUNT4 0xc6 | ||
42 | #define RTC_COUNT4_DUMMYREAD 0xc5 /* start a PMU RTC access by reading the register prior to the RTC_COUNT4 */ | ||
43 | #define ALM1_VALID_RANGE_IN_SEC 0x3FFF /*only 14-bits width in second*/ | ||
44 | |||
45 | struct tps6586x_rtc { | ||
46 | unsigned long epoch_start; | ||
47 | int irq; | ||
48 | struct rtc_device *rtc; | ||
49 | bool irq_en; | ||
50 | }; | ||
51 | |||
52 | static inline struct device *to_tps6586x_dev(struct device *dev) | ||
53 | { | ||
54 | return dev->parent; | ||
55 | } | ||
56 | |||
57 | static int tps6586x_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
58 | { | ||
59 | struct tps6586x_rtc *rtc = dev_get_drvdata(dev); | ||
60 | struct device *tps_dev = to_tps6586x_dev(dev); | ||
61 | unsigned long long ticks = 0; | ||
62 | unsigned long seconds; | ||
63 | u8 buff[6]; | ||
64 | int err; | ||
65 | int i; | ||
66 | |||
67 | err = tps6586x_reads(tps_dev, RTC_COUNT4_DUMMYREAD, sizeof(buff), buff); | ||
68 | if (err < 0) { | ||
69 | dev_err(dev, "failed to read counter\n"); | ||
70 | return err; | ||
71 | } | ||
72 | |||
73 | for (i = 1; i < sizeof(buff); i++) { | ||
74 | ticks <<= 8; | ||
75 | ticks |= buff[i]; | ||
76 | } | ||
77 | |||
78 | seconds = ticks >> 10; | ||
79 | |||
80 | seconds += rtc->epoch_start; | ||
81 | rtc_time_to_tm(seconds, tm); | ||
82 | return rtc_valid_tm(tm); | ||
83 | } | ||
84 | |||
85 | static int tps6586x_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
86 | { | ||
87 | struct tps6586x_rtc *rtc = dev_get_drvdata(dev); | ||
88 | struct device *tps_dev = to_tps6586x_dev(dev); | ||
89 | unsigned long long ticks; | ||
90 | unsigned long seconds; | ||
91 | u8 buff[5]; | ||
92 | int err; | ||
93 | |||
94 | rtc_tm_to_time(tm, &seconds); | ||
95 | |||
96 | if (WARN_ON(seconds < rtc->epoch_start)) { | ||
97 | dev_err(dev, "requested time unsupported\n"); | ||
98 | return -EINVAL; | ||
99 | } | ||
100 | |||
101 | seconds -= rtc->epoch_start; | ||
102 | |||
103 | ticks = (unsigned long long)seconds << 10; | ||
104 | buff[0] = (ticks >> 32) & 0xff; | ||
105 | buff[1] = (ticks >> 24) & 0xff; | ||
106 | buff[2] = (ticks >> 16) & 0xff; | ||
107 | buff[3] = (ticks >> 8) & 0xff; | ||
108 | buff[4] = ticks & 0xff; | ||
109 | |||
110 | err = tps6586x_clr_bits(tps_dev, RTC_CTRL, RTC_ENABLE); | ||
111 | if (err < 0) { | ||
112 | dev_err(dev, "failed to clear RTC_ENABLE\n"); | ||
113 | return err; | ||
114 | } | ||
115 | |||
116 | err = tps6586x_writes(tps_dev, RTC_COUNT4, sizeof(buff), buff); | ||
117 | if (err < 0) { | ||
118 | dev_err(dev, "failed to program new time\n"); | ||
119 | return err; | ||
120 | } | ||
121 | |||
122 | err = tps6586x_set_bits(tps_dev, RTC_CTRL, RTC_ENABLE); | ||
123 | if (err < 0) { | ||
124 | dev_err(dev, "failed to set RTC_ENABLE\n"); | ||
125 | return err; | ||
126 | } | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
132 | { | ||
133 | struct tps6586x_rtc *rtc = dev_get_drvdata(dev); | ||
134 | struct device *tps_dev = to_tps6586x_dev(dev); | ||
135 | unsigned long seconds; | ||
136 | unsigned long ticks; | ||
137 | unsigned long rtc_current_time; | ||
138 | unsigned long long rticks = 0; | ||
139 | u8 buff[3]; | ||
140 | u8 rbuff[6]; | ||
141 | int err; | ||
142 | int i; | ||
143 | |||
144 | if (rtc->irq == -1) | ||
145 | return -EIO; | ||
146 | |||
147 | rtc_tm_to_time(&alrm->time, &seconds); | ||
148 | |||
149 | if (WARN_ON(alrm->enabled && (seconds < rtc->epoch_start))) { | ||
150 | dev_err(dev, "can't set alarm to requested time\n"); | ||
151 | return -EINVAL; | ||
152 | } | ||
153 | |||
154 | if (alrm->enabled && !rtc->irq_en) { | ||
155 | enable_irq(rtc->irq); | ||
156 | rtc->irq_en = true; | ||
157 | } else if (!alrm->enabled && rtc->irq_en) { | ||
158 | disable_irq(rtc->irq); | ||
159 | rtc->irq_en = false; | ||
160 | } | ||
161 | |||
162 | seconds -= rtc->epoch_start; | ||
163 | |||
164 | err = tps6586x_reads(tps_dev, RTC_COUNT4_DUMMYREAD, sizeof(rbuff), rbuff); | ||
165 | if (err < 0) { | ||
166 | dev_err(dev, "failed to read counter\n"); | ||
167 | return err; | ||
168 | } | ||
169 | |||
170 | for (i = 1; i < sizeof(rbuff); i++) { | ||
171 | rticks <<= 8; | ||
172 | rticks |= rbuff[i]; | ||
173 | } | ||
174 | |||
175 | rtc_current_time = rticks >> 10; | ||
176 | if ((seconds - rtc_current_time) > ALM1_VALID_RANGE_IN_SEC) | ||
177 | seconds = rtc_current_time - 1; | ||
178 | |||
179 | ticks = (unsigned long long)seconds << 10; | ||
180 | |||
181 | buff[0] = (ticks >> 16) & 0xff; | ||
182 | buff[1] = (ticks >> 8) & 0xff; | ||
183 | buff[2] = ticks & 0xff; | ||
184 | |||
185 | err = tps6586x_writes(tps_dev, RTC_ALARM1_HI, sizeof(buff), buff); | ||
186 | if (err) | ||
187 | dev_err(tps_dev, "unable to program alarm\n"); | ||
188 | |||
189 | return err; | ||
190 | } | ||
191 | |||
192 | static int tps6586x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
193 | { | ||
194 | struct tps6586x_rtc *rtc = dev_get_drvdata(dev); | ||
195 | struct device *tps_dev = to_tps6586x_dev(dev); | ||
196 | unsigned long ticks; | ||
197 | unsigned long seconds; | ||
198 | u8 buff[3]; | ||
199 | int err; | ||
200 | |||
201 | err = tps6586x_reads(tps_dev, RTC_ALARM1_HI, sizeof(buff), buff); | ||
202 | if (err) | ||
203 | return err; | ||
204 | |||
205 | ticks = (buff[0] << 16) | (buff[1] << 8) | buff[2]; | ||
206 | seconds = ticks >> 10; | ||
207 | seconds += rtc->epoch_start; | ||
208 | |||
209 | rtc_time_to_tm(seconds, &alrm->time); | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static int tps6586x_rtc_alarm_irq_enable(struct device *dev, | ||
215 | unsigned int enabled) | ||
216 | { | ||
217 | struct tps6586x_rtc *rtc = dev_get_drvdata(dev); | ||
218 | struct device *tps_dev = to_tps6586x_dev(dev); | ||
219 | u8 buff; | ||
220 | int err; | ||
221 | |||
222 | if (rtc->irq == -1) | ||
223 | return -EIO; | ||
224 | |||
225 | err = tps6586x_read(tps_dev, RTC_CTRL, &buff); | ||
226 | if (err < 0) { | ||
227 | dev_err(dev, "failed to read RTC_CTRL\n"); | ||
228 | return err; | ||
229 | } | ||
230 | |||
231 | if ((enabled && (buff & RTC_ENABLE)) || | ||
232 | (!enabled && !(buff & RTC_ENABLE))) | ||
233 | return 0; | ||
234 | |||
235 | if (enabled) { | ||
236 | err = tps6586x_set_bits(tps_dev, RTC_CTRL, RTC_ENABLE); | ||
237 | if (err < 0) { | ||
238 | dev_err(dev, "failed to set RTC_ENABLE\n"); | ||
239 | return err; | ||
240 | } | ||
241 | |||
242 | if (!rtc->irq_en) { | ||
243 | enable_irq(rtc->irq); | ||
244 | rtc->irq_en = true; | ||
245 | } | ||
246 | } else { | ||
247 | err = tps6586x_clr_bits(tps_dev, RTC_CTRL, RTC_ENABLE); | ||
248 | if (err < 0) { | ||
249 | dev_err(dev, "failed to clear RTC_ENABLE\n"); | ||
250 | return err; | ||
251 | } | ||
252 | |||
253 | if (rtc->irq_en) { | ||
254 | disable_irq(rtc->irq); | ||
255 | rtc->irq_en = false; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static const struct rtc_class_ops tps6586x_rtc_ops = { | ||
263 | .read_time = tps6586x_rtc_read_time, | ||
264 | .set_time = tps6586x_rtc_set_time, | ||
265 | .set_alarm = tps6586x_rtc_set_alarm, | ||
266 | .read_alarm = tps6586x_rtc_read_alarm, | ||
267 | .alarm_irq_enable = tps6586x_rtc_alarm_irq_enable, | ||
268 | }; | ||
269 | |||
270 | static irqreturn_t tps6586x_rtc_irq(int irq, void *data) | ||
271 | { | ||
272 | struct device *dev = data; | ||
273 | struct tps6586x_rtc *rtc = dev_get_drvdata(dev); | ||
274 | |||
275 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); | ||
276 | return IRQ_HANDLED; | ||
277 | } | ||
278 | |||
279 | static int __devinit tps6586x_rtc_probe(struct platform_device *pdev) | ||
280 | { | ||
281 | struct tps6586x_rtc_platform_data *pdata = pdev->dev.platform_data; | ||
282 | struct device *tps_dev = to_tps6586x_dev(&pdev->dev); | ||
283 | struct tps6586x_rtc *rtc; | ||
284 | int err; | ||
285 | struct tps6586x_epoch_start *epoch; | ||
286 | |||
287 | if (!pdata) { | ||
288 | dev_err(&pdev->dev, "no platform_data specified\n"); | ||
289 | return -EINVAL; | ||
290 | } | ||
291 | |||
292 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | ||
293 | |||
294 | if (!rtc) | ||
295 | return -ENOMEM; | ||
296 | |||
297 | rtc->irq = -1; | ||
298 | |||
299 | if (pdata->irq < 0) | ||
300 | dev_warn(&pdev->dev, "no IRQ specified, wakeup is disabled\n"); | ||
301 | |||
302 | epoch = &pdata->start; | ||
303 | rtc->epoch_start = mktime(epoch->year, epoch->month, epoch->day, | ||
304 | epoch->hour, epoch->min, epoch->sec); | ||
305 | |||
306 | dev_set_drvdata(&pdev->dev, rtc); | ||
307 | |||
308 | device_init_wakeup(&pdev->dev, 1); | ||
309 | |||
310 | rtc->rtc = rtc_device_register("tps6586x-rtc", &pdev->dev, | ||
311 | &tps6586x_rtc_ops, THIS_MODULE); | ||
312 | |||
313 | if (IS_ERR(rtc->rtc)) { | ||
314 | err = PTR_ERR(rtc->rtc); | ||
315 | goto fail; | ||
316 | } | ||
317 | |||
318 | /* 1 kHz tick mode, enable tick counting */ | ||
319 | err = tps6586x_update(tps_dev, RTC_CTRL, | ||
320 | RTC_ENABLE | OSC_SRC_SEL | ((pdata->cl_sel << CL_SEL_POS) & | ||
321 | CL_SEL_MASK), | ||
322 | RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK); | ||
323 | if (err < 0) { | ||
324 | dev_err(&pdev->dev, "unable to start counter\n"); | ||
325 | goto fail; | ||
326 | } | ||
327 | |||
328 | if (pdata && (pdata->irq >= 0)) { | ||
329 | rtc->irq = pdata->irq; | ||
330 | err = request_threaded_irq(pdata->irq, NULL, tps6586x_rtc_irq, | ||
331 | IRQF_ONESHOT, "tps6586x-rtc", | ||
332 | &pdev->dev); | ||
333 | if (err) { | ||
334 | dev_warn(&pdev->dev, "unable to request IRQ(%d)\n", rtc->irq); | ||
335 | rtc->irq = -1; | ||
336 | } else { | ||
337 | enable_irq_wake(rtc->irq); | ||
338 | disable_irq(rtc->irq); | ||
339 | } | ||
340 | } | ||
341 | |||
342 | return 0; | ||
343 | |||
344 | fail: | ||
345 | if (!IS_ERR_OR_NULL(rtc->rtc)) | ||
346 | rtc_device_unregister(rtc->rtc); | ||
347 | device_init_wakeup(&pdev->dev, 0); | ||
348 | kfree(rtc); | ||
349 | return err; | ||
350 | } | ||
351 | |||
352 | static int __devexit tps6586x_rtc_remove(struct platform_device *pdev) | ||
353 | { | ||
354 | struct tps6586x_rtc *rtc = dev_get_drvdata(&pdev->dev); | ||
355 | |||
356 | if (rtc->irq != -1) | ||
357 | free_irq(rtc->irq, rtc); | ||
358 | rtc_device_unregister(rtc->rtc); | ||
359 | kfree(rtc); | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static struct platform_driver tps6586x_rtc_driver = { | ||
364 | .driver = { | ||
365 | .name = "tps6586x-rtc", | ||
366 | .owner = THIS_MODULE, | ||
367 | }, | ||
368 | .probe = tps6586x_rtc_probe, | ||
369 | .remove = __devexit_p(tps6586x_rtc_remove), | ||
370 | }; | ||
371 | |||
372 | static int __init tps6586x_rtc_init(void) | ||
373 | { | ||
374 | return platform_driver_register(&tps6586x_rtc_driver); | ||
375 | } | ||
376 | module_init(tps6586x_rtc_init); | ||
377 | |||
378 | static void __exit tps6586x_rtc_exit(void) | ||
379 | { | ||
380 | platform_driver_unregister(&tps6586x_rtc_driver); | ||
381 | } | ||
382 | module_exit(tps6586x_rtc_exit); | ||
383 | |||
384 | MODULE_DESCRIPTION("TI TPS6586x RTC driver"); | ||
385 | MODULE_AUTHOR("NVIDIA Corporation"); | ||
386 | MODULE_LICENSE("GPL"); | ||
387 | MODULE_ALIAS("platform:rtc-tps6586x"); | ||
diff --git a/drivers/rtc/rtc-tps6591x.c b/drivers/rtc/rtc-tps6591x.c new file mode 100644 index 00000000000..cab3e8874df --- /dev/null +++ b/drivers/rtc/rtc-tps6591x.c | |||
@@ -0,0 +1,546 @@ | |||
1 | /* | ||
2 | * drivers/rtc/rtc_tps6591x.c | ||
3 | * | ||
4 | * RTC driver for TI TPS6591x | ||
5 | * | ||
6 | * Copyright (c) 2011, NVIDIA Corporation. | ||
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, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
21 | */ | ||
22 | |||
23 | /* #define DEBUG 1 */ | ||
24 | /* #define VERBOSE_DEBUG 1 */ | ||
25 | |||
26 | #include <linux/device.h> | ||
27 | #include <linux/err.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/mfd/tps6591x.h> | ||
31 | #include <linux/platform_device.h> | ||
32 | #include <linux/rtc.h> | ||
33 | #include <linux/slab.h> | ||
34 | |||
35 | #define RTC_CTRL 0x10 | ||
36 | #define RTC_STATUS 0x11 | ||
37 | #define RTC_SECONDS_REG 0x0 | ||
38 | #define RTC_ALARM 0x8 | ||
39 | #define RTC_INT 0x12 | ||
40 | #define RTC_RESET_STATUS 0x16 | ||
41 | #define RTC_BBCH_REG 0x39 | ||
42 | |||
43 | #define RTC_BBCH_SEL 0x02 | ||
44 | #define RTC_BBCH_EN 0x01 | ||
45 | #define ENABLE_ALARM_INT 0x8 | ||
46 | #define RTC_RESET_VALUE 0x80 | ||
47 | #define ALARM_INT_STATUS 0x40 | ||
48 | |||
49 | /* | ||
50 | Linux RTC driver refers 1900 as base year in many calculations. | ||
51 | (e.g. refer drivers/rtc/rtc-lib.c) | ||
52 | */ | ||
53 | #define OS_REF_YEAR 1900 | ||
54 | |||
55 | /* | ||
56 | PMU RTC have only 2 nibbles to store year information, so using an offset | ||
57 | of 100 to set the base year as 2000 for our driver. | ||
58 | */ | ||
59 | #define RTC_YEAR_OFFSET 100 | ||
60 | |||
61 | struct tps6591x_rtc { | ||
62 | unsigned long epoch_start; | ||
63 | int irq; | ||
64 | struct rtc_device *rtc; | ||
65 | bool irq_en; | ||
66 | }; | ||
67 | |||
68 | static int tps6591x_read_regs(struct device *dev, int reg, int len, | ||
69 | uint8_t *val) | ||
70 | { | ||
71 | int ret; | ||
72 | |||
73 | /* dummy read of STATUS_REG as per data sheet */ | ||
74 | ret = tps6591x_reads(dev->parent, RTC_STATUS, 1, val); | ||
75 | if (ret < 0) { | ||
76 | dev_err(dev->parent, "\n %s failed reading from RTC_STATUS\n", | ||
77 | __func__); | ||
78 | WARN_ON(1); | ||
79 | return ret; | ||
80 | } | ||
81 | |||
82 | ret = tps6591x_reads(dev->parent, reg, len, val); | ||
83 | if (ret < 0) { | ||
84 | dev_err(dev->parent, "\n %s failed reading from 0x%02x\n", | ||
85 | __func__, reg); | ||
86 | WARN_ON(1); | ||
87 | return ret; | ||
88 | } | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static int tps6591x_write_regs(struct device *dev, int reg, int len, | ||
93 | uint8_t *val) | ||
94 | { | ||
95 | int ret; | ||
96 | ret = tps6591x_writes(dev->parent, reg, len, val); | ||
97 | if (ret < 0) { | ||
98 | dev_err(dev->parent, "\n %s failed writing\n", __func__); | ||
99 | WARN_ON(1); | ||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int tps6591x_rtc_valid_tm(struct rtc_time *tm) | ||
107 | { | ||
108 | if (tm->tm_year >= (RTC_YEAR_OFFSET + 99) | ||
109 | || tm->tm_mon >= 12 | ||
110 | || tm->tm_mday < 1 | ||
111 | || tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year + OS_REF_YEAR) | ||
112 | || tm->tm_hour >= 24 | ||
113 | || tm->tm_min >= 60 | ||
114 | || tm->tm_sec >= 60) | ||
115 | return -EINVAL; | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | static u8 dec2bcd(u8 dec) | ||
120 | { | ||
121 | return ((dec/10)<<4)+(dec%10); | ||
122 | } | ||
123 | |||
124 | static u8 bcd2dec(u8 bcd) | ||
125 | { | ||
126 | return (bcd >> 4)*10+(bcd & 0xF); | ||
127 | } | ||
128 | |||
129 | static void convert_bcd_to_decimal(u8 *buf, u8 len) | ||
130 | { | ||
131 | int i = 0; | ||
132 | for (i = 0; i < len; i++) | ||
133 | buf[i] = bcd2dec(buf[i]); | ||
134 | } | ||
135 | |||
136 | static void convert_decimal_to_bcd(u8 *buf, u8 len) | ||
137 | { | ||
138 | int i = 0; | ||
139 | for (i = 0; i < len; i++) | ||
140 | buf[i] = dec2bcd(buf[i]); | ||
141 | } | ||
142 | |||
143 | static void print_time(struct device *dev, struct rtc_time *tm) | ||
144 | { | ||
145 | dev_info(dev, "RTC Time : %d/%d/%d %d:%d:%d\n", | ||
146 | (tm->tm_mon + 1), tm->tm_mday, (tm->tm_year + OS_REF_YEAR), | ||
147 | tm->tm_hour, tm->tm_min , tm->tm_sec); | ||
148 | } | ||
149 | |||
150 | static int tps6591x_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
151 | { | ||
152 | u8 buff[7]; | ||
153 | int err; | ||
154 | err = tps6591x_read_regs(dev, RTC_SECONDS_REG, sizeof(buff), buff); | ||
155 | if (err < 0) { | ||
156 | dev_err(dev, "\n %s :: failed to read time\n", __FILE__); | ||
157 | return err; | ||
158 | } | ||
159 | convert_bcd_to_decimal(buff, sizeof(buff)); | ||
160 | tm->tm_sec = buff[0]; | ||
161 | tm->tm_min = buff[1]; | ||
162 | tm->tm_hour = buff[2]; | ||
163 | tm->tm_mday = buff[3]; | ||
164 | tm->tm_mon = buff[4] - 1; | ||
165 | tm->tm_year = buff[5]; | ||
166 | tm->tm_wday = buff[6]; | ||
167 | print_time(dev, tm); | ||
168 | return tps6591x_rtc_valid_tm(tm); | ||
169 | } | ||
170 | |||
171 | static int tps6591x_rtc_stop(struct device *dev) | ||
172 | { | ||
173 | u8 reg = 0; | ||
174 | u8 retries = 0; | ||
175 | int err; | ||
176 | do { | ||
177 | err = tps6591x_read_regs(dev, RTC_CTRL, 1, ®); | ||
178 | if (err < 0) { | ||
179 | dev_err(dev->parent, "\n failed to read RTC_CTRL reg\n"); | ||
180 | return err; | ||
181 | } | ||
182 | |||
183 | /* clear STOP bit alone */ | ||
184 | reg &= ~0x1; | ||
185 | |||
186 | err = tps6591x_write_regs(dev, RTC_CTRL, 1, ®); | ||
187 | if (err < 0) { | ||
188 | dev_err(dev->parent, "\n failed to program RTC_CTRL reg\n"); | ||
189 | return err; | ||
190 | } | ||
191 | |||
192 | err = tps6591x_read_regs(dev, RTC_STATUS, 1, ®); | ||
193 | if (err < 0) { | ||
194 | dev_err(dev->parent, "\n failed to read RTC_CTRL reg\n"); | ||
195 | return err; | ||
196 | } | ||
197 | /* FixMe: Is allowing up to 5 retries sufficient?? */ | ||
198 | if (retries++ == 5) { | ||
199 | dev_err(dev->parent, "\n failed to stop RTC\n"); | ||
200 | return -EBUSY; | ||
201 | } | ||
202 | } while (reg & 2); | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static int tps6591x_rtc_start(struct device *dev) | ||
207 | { | ||
208 | u8 reg = 0; | ||
209 | u8 retries = 0; | ||
210 | int err; | ||
211 | |||
212 | do { | ||
213 | err = tps6591x_read_regs(dev, RTC_CTRL, 1, ®); | ||
214 | if (err < 0) { | ||
215 | dev_err(dev->parent, "\n failed to read RTC_CTRL reg\n"); | ||
216 | return err; | ||
217 | } | ||
218 | |||
219 | /* set STOP bit alone */ | ||
220 | reg |= 0x1; | ||
221 | |||
222 | err = tps6591x_write_regs(dev, RTC_CTRL, 1, ®); | ||
223 | if (err < 0) { | ||
224 | dev_err(dev->parent, "\n failed to program RTC_CTRL reg\n"); | ||
225 | return err; | ||
226 | } | ||
227 | |||
228 | err = tps6591x_read_regs(dev, RTC_STATUS, 1, ®); | ||
229 | if (err < 0) { | ||
230 | dev_err(dev->parent, "\n failed to read RTC_CTRL reg\n"); | ||
231 | return err; | ||
232 | } | ||
233 | /* FixMe: Is allowing up to 5 retries sufficient?? */ | ||
234 | if (retries++ == 5) { | ||
235 | dev_err(dev->parent, "\n failed to stop RTC\n"); | ||
236 | return -EBUSY; | ||
237 | } | ||
238 | } while (!(reg & 2)); | ||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | |||
243 | static int tps6591x_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
244 | { | ||
245 | u8 buff[7]; | ||
246 | int err; | ||
247 | |||
248 | buff[0] = tm->tm_sec; | ||
249 | buff[1] = tm->tm_min; | ||
250 | buff[2] = tm->tm_hour; | ||
251 | buff[3] = tm->tm_mday; | ||
252 | buff[4] = tm->tm_mon + 1; | ||
253 | buff[5] = tm->tm_year; | ||
254 | buff[6] = tm->tm_wday; | ||
255 | |||
256 | print_time(dev, tm); | ||
257 | convert_decimal_to_bcd(buff, sizeof(buff)); | ||
258 | err = tps6591x_rtc_stop(dev); | ||
259 | if (err < 0) { | ||
260 | dev_err(dev->parent, "\n failed to clear RTC_ENABLE\n"); | ||
261 | return err; | ||
262 | } | ||
263 | |||
264 | err = tps6591x_write_regs(dev, RTC_SECONDS_REG, sizeof(buff), buff); | ||
265 | if (err < 0) { | ||
266 | dev_err(dev->parent, "\n failed to program new time\n"); | ||
267 | return err; | ||
268 | } | ||
269 | |||
270 | err = tps6591x_rtc_start(dev); | ||
271 | if (err < 0) { | ||
272 | dev_err(dev->parent, "\n failed to set RTC_ENABLE\n"); | ||
273 | return err; | ||
274 | } | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static int tps6591x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
280 | { | ||
281 | struct tps6591x_rtc *rtc = dev_get_drvdata(dev); | ||
282 | unsigned long seconds; | ||
283 | u8 buff[6]; | ||
284 | int err; | ||
285 | struct rtc_time tm; | ||
286 | |||
287 | if (rtc->irq == -1) | ||
288 | return -EIO; | ||
289 | |||
290 | dev_info(dev->parent, "\n setting alarm to requested time::\n"); | ||
291 | print_time(dev->parent, &alrm->time); | ||
292 | rtc_tm_to_time(&alrm->time, &seconds); | ||
293 | tps6591x_rtc_read_time(dev, &tm); | ||
294 | rtc_tm_to_time(&tm, &rtc->epoch_start); | ||
295 | |||
296 | if (WARN_ON(alrm->enabled && (seconds < rtc->epoch_start))) { | ||
297 | dev_err(dev->parent, "\n can't set alarm to requested time\n"); | ||
298 | return -EINVAL; | ||
299 | } | ||
300 | |||
301 | if (alrm->enabled && !rtc->irq_en) { | ||
302 | rtc->irq_en = true; | ||
303 | } else if (!alrm->enabled && rtc->irq_en) { | ||
304 | rtc->irq_en = false; | ||
305 | } | ||
306 | |||
307 | buff[0] = alrm->time.tm_sec; | ||
308 | buff[1] = alrm->time.tm_min; | ||
309 | buff[2] = alrm->time.tm_hour; | ||
310 | buff[3] = alrm->time.tm_mday; | ||
311 | buff[4] = alrm->time.tm_mon + 1; | ||
312 | buff[5] = alrm->time.tm_year; | ||
313 | convert_decimal_to_bcd(buff, sizeof(buff)); | ||
314 | err = tps6591x_write_regs(dev, RTC_ALARM, sizeof(buff), buff); | ||
315 | if (err) | ||
316 | dev_err(dev->parent, "\n unable to program alarm\n"); | ||
317 | |||
318 | return err; | ||
319 | } | ||
320 | |||
321 | static int tps6591x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
322 | { | ||
323 | u8 buff[6]; | ||
324 | int err; | ||
325 | |||
326 | err = tps6591x_read_regs(dev, RTC_ALARM, sizeof(buff), buff); | ||
327 | if (err) | ||
328 | return err; | ||
329 | convert_bcd_to_decimal(buff, sizeof(buff)); | ||
330 | |||
331 | alrm->time.tm_sec = buff[0]; | ||
332 | alrm->time.tm_min = buff[1]; | ||
333 | alrm->time.tm_hour = buff[2]; | ||
334 | alrm->time.tm_mday = buff[3]; | ||
335 | alrm->time.tm_mon = buff[4] - 1; | ||
336 | alrm->time.tm_year = buff[5]; | ||
337 | |||
338 | dev_info(dev->parent, "\n getting alarm time::\n"); | ||
339 | print_time(dev, &alrm->time); | ||
340 | |||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static int tps6591x_rtc_alarm_irq_enable(struct device *dev, | ||
345 | unsigned int enable) | ||
346 | { | ||
347 | struct tps6591x_rtc *rtc = dev_get_drvdata(dev); | ||
348 | u8 reg; | ||
349 | int err; | ||
350 | |||
351 | if (rtc->irq == -1) | ||
352 | return -EIO; | ||
353 | |||
354 | if (enable) { | ||
355 | if (rtc->irq_en == true) | ||
356 | return 0; | ||
357 | err = tps6591x_read_regs(dev, RTC_INT, 1, ®); | ||
358 | if (err) | ||
359 | return err; | ||
360 | reg |= 0x8; | ||
361 | err = tps6591x_write_regs(dev, RTC_INT, 1, ®); | ||
362 | if (err) | ||
363 | return err; | ||
364 | rtc->irq_en = true; | ||
365 | } else { | ||
366 | if (rtc->irq_en == false) | ||
367 | return 0; | ||
368 | err = tps6591x_read_regs(dev, RTC_INT, 1, ®); | ||
369 | if (err) | ||
370 | return err; | ||
371 | reg &= ~0x8; | ||
372 | err = tps6591x_write_regs(dev, RTC_INT, 1, ®); | ||
373 | if (err) | ||
374 | return err; | ||
375 | rtc->irq_en = false; | ||
376 | } | ||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static const struct rtc_class_ops tps6591x_rtc_ops = { | ||
381 | .read_time = tps6591x_rtc_read_time, | ||
382 | .set_time = tps6591x_rtc_set_time, | ||
383 | .set_alarm = tps6591x_rtc_set_alarm, | ||
384 | .read_alarm = tps6591x_rtc_read_alarm, | ||
385 | .alarm_irq_enable = tps6591x_rtc_alarm_irq_enable, | ||
386 | }; | ||
387 | |||
388 | static irqreturn_t tps6591x_rtc_irq(int irq, void *data) | ||
389 | { | ||
390 | struct device *dev = data; | ||
391 | struct tps6591x_rtc *rtc = dev_get_drvdata(dev); | ||
392 | u8 reg; | ||
393 | int err; | ||
394 | |||
395 | /* clear Alarm status bits.*/ | ||
396 | err = tps6591x_read_regs(dev, RTC_STATUS, 1, ®); | ||
397 | if (err) { | ||
398 | dev_err(dev->parent, "unable to read RTC_STATUS reg\n"); | ||
399 | return -EBUSY; | ||
400 | } | ||
401 | |||
402 | reg = ALARM_INT_STATUS; | ||
403 | err = tps6591x_write_regs(dev, RTC_STATUS, 1, ®); | ||
404 | if (err) { | ||
405 | dev_err(dev->parent, "unable to program RTC_STATUS reg\n"); | ||
406 | return -EBUSY; | ||
407 | } | ||
408 | |||
409 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); | ||
410 | return IRQ_HANDLED; | ||
411 | } | ||
412 | |||
413 | static int __devinit tps6591x_rtc_probe(struct platform_device *pdev) | ||
414 | { | ||
415 | struct tps6591x_rtc_platform_data *pdata = pdev->dev.platform_data; | ||
416 | struct tps6591x_rtc *rtc; | ||
417 | struct rtc_time tm; | ||
418 | int err; | ||
419 | u8 reg; | ||
420 | |||
421 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | ||
422 | |||
423 | if (!rtc) | ||
424 | return -ENOMEM; | ||
425 | |||
426 | rtc->irq = -1; | ||
427 | |||
428 | if (!pdata) { | ||
429 | dev_err(&pdev->dev, "no platform_data specified\n"); | ||
430 | return -EINVAL; | ||
431 | } | ||
432 | |||
433 | if (pdata->irq < 0) | ||
434 | dev_err(&pdev->dev, "\n no IRQ specified, wakeup is disabled\n"); | ||
435 | |||
436 | dev_set_drvdata(&pdev->dev, rtc); | ||
437 | device_init_wakeup(&pdev->dev, 1); | ||
438 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
439 | &tps6591x_rtc_ops, THIS_MODULE); | ||
440 | |||
441 | if (IS_ERR(rtc->rtc)) { | ||
442 | err = PTR_ERR(rtc->rtc); | ||
443 | goto fail; | ||
444 | } | ||
445 | |||
446 | if ((int)pdev && (int)&pdev->dev) | ||
447 | err = tps6591x_read_regs(&pdev->dev, RTC_STATUS, 1, ®); | ||
448 | else { | ||
449 | dev_err(&pdev->dev, "\n %s Input params incorrect\n", __func__); | ||
450 | return -EBUSY; | ||
451 | } | ||
452 | if (err) { | ||
453 | dev_err(&pdev->dev, "\n %s unable to read status\n", __func__); | ||
454 | return -EBUSY; | ||
455 | } | ||
456 | |||
457 | reg = RTC_BBCH_SEL | RTC_BBCH_EN; | ||
458 | tps6591x_write_regs(&pdev->dev, RTC_BBCH_REG, 1, ®); | ||
459 | if (err) { | ||
460 | dev_err(&pdev->dev, "unable to program Charger reg\n"); | ||
461 | return -EBUSY; | ||
462 | } | ||
463 | |||
464 | tps6591x_rtc_read_time(&pdev->dev, &tm); | ||
465 | if ((tm.tm_year < RTC_YEAR_OFFSET || tm.tm_year > (RTC_YEAR_OFFSET + 99))){ | ||
466 | if (pdata->time.tm_year < 2000 || pdata->time.tm_year > 2100) { | ||
467 | memset(&pdata->time, 0, sizeof(pdata->time)); | ||
468 | pdata->time.tm_year = RTC_YEAR_OFFSET; | ||
469 | pdata->time.tm_mday = 1; | ||
470 | } else | ||
471 | pdata->time.tm_year -= OS_REF_YEAR; | ||
472 | tps6591x_rtc_set_time(&pdev->dev, &pdata->time); | ||
473 | } | ||
474 | |||
475 | reg = ALARM_INT_STATUS; | ||
476 | err = tps6591x_write_regs(&pdev->dev, RTC_STATUS, 1, ®); | ||
477 | if (err) { | ||
478 | dev_err(&pdev->dev, "unable to program RTC_STATUS reg\n"); | ||
479 | return -EBUSY; | ||
480 | } | ||
481 | |||
482 | reg = ENABLE_ALARM_INT; | ||
483 | tps6591x_write_regs(&pdev->dev, RTC_INT, 1, ®); | ||
484 | if (err) { | ||
485 | dev_err(&pdev->dev, "unable to program Interrupt Mask reg\n"); | ||
486 | return -EBUSY; | ||
487 | } | ||
488 | |||
489 | if (pdata && (pdata->irq >= 0)) { | ||
490 | rtc->irq = pdata->irq; | ||
491 | err = request_threaded_irq(pdata->irq, NULL, tps6591x_rtc_irq, | ||
492 | IRQF_ONESHOT, "rtc_tps6591x", | ||
493 | &pdev->dev); | ||
494 | if (err) { | ||
495 | dev_err(&pdev->dev, "request IRQ:%d fail\n", rtc->irq); | ||
496 | rtc->irq = -1; | ||
497 | } else { | ||
498 | device_init_wakeup(&pdev->dev, 1); | ||
499 | enable_irq_wake(rtc->irq); | ||
500 | } | ||
501 | } | ||
502 | return 0; | ||
503 | |||
504 | fail: | ||
505 | if (!IS_ERR_OR_NULL(rtc->rtc)) | ||
506 | rtc_device_unregister(rtc->rtc); | ||
507 | kfree(rtc); | ||
508 | return err; | ||
509 | } | ||
510 | |||
511 | static int __devexit tps6591x_rtc_remove(struct platform_device *pdev) | ||
512 | { | ||
513 | struct tps6591x_rtc *rtc = dev_get_drvdata(&pdev->dev); | ||
514 | |||
515 | if (rtc->irq != -1) | ||
516 | free_irq(rtc->irq, rtc); | ||
517 | rtc_device_unregister(rtc->rtc); | ||
518 | kfree(rtc); | ||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | static struct platform_driver tps6591x_rtc_driver = { | ||
523 | .driver = { | ||
524 | .name = "rtc_tps6591x", | ||
525 | .owner = THIS_MODULE, | ||
526 | }, | ||
527 | .probe = tps6591x_rtc_probe, | ||
528 | .remove = __devexit_p(tps6591x_rtc_remove), | ||
529 | }; | ||
530 | |||
531 | static int __init tps6591x_rtc_init(void) | ||
532 | { | ||
533 | return platform_driver_register(&tps6591x_rtc_driver); | ||
534 | } | ||
535 | module_init(tps6591x_rtc_init); | ||
536 | |||
537 | static void __exit tps6591x_rtc_exit(void) | ||
538 | { | ||
539 | platform_driver_unregister(&tps6591x_rtc_driver); | ||
540 | } | ||
541 | module_exit(tps6591x_rtc_exit); | ||
542 | |||
543 | MODULE_DESCRIPTION("TI TPS6591x RTC driver"); | ||
544 | MODULE_AUTHOR("NVIDIA Corporation"); | ||
545 | MODULE_LICENSE("GPL"); | ||
546 | MODULE_ALIAS("platform:rtc_tps6591x"); | ||
diff --git a/drivers/rtc/rtc-tps80031.c b/drivers/rtc/rtc-tps80031.c new file mode 100644 index 00000000000..70d6734a570 --- /dev/null +++ b/drivers/rtc/rtc-tps80031.c | |||
@@ -0,0 +1,449 @@ | |||
1 | /* | ||
2 | * drivers/rtc/rtc_tps80031.c | ||
3 | * | ||
4 | * RTC driver for TI TPS80031 | ||
5 | * | ||
6 | * Copyright (c) 2011, NVIDIA Corporation. | ||
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, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
21 | */ | ||
22 | |||
23 | /* #define DEBUG 1 */ | ||
24 | /* #define VERBOSE_DEBUG 1 */ | ||
25 | |||
26 | #include <linux/device.h> | ||
27 | #include <linux/err.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/mfd/tps80031.h> | ||
31 | #include <linux/platform_device.h> | ||
32 | #include <linux/rtc.h> | ||
33 | #include <linux/slab.h> | ||
34 | |||
35 | #define RTC_CTRL 0x10 | ||
36 | #define RTC_STATUS 0x11 | ||
37 | #define RTC_SECONDS_REG 0x0 | ||
38 | #define RTC_ALARM 0x8 | ||
39 | #define RTC_INT 0x12 | ||
40 | #define RTC_RESET_STATUS 0x16 | ||
41 | |||
42 | #define ENABLE_ALARM_INT 0x8 | ||
43 | #define ALARM_INT_STATUS 0x40 | ||
44 | #define STOP_RTC 1 | ||
45 | |||
46 | /* Power on reset Values of RTC registers */ | ||
47 | #define RTC_POR_YEAR 0 | ||
48 | #define RTC_POR_MONTH 1 | ||
49 | #define RTC_POR_DAY 1 | ||
50 | |||
51 | /* | ||
52 | Linux RTC driver refers 19th centaury as base year in many | ||
53 | calculations. (e.g. refer drivers/rtc/rtc-lib.c) | ||
54 | */ | ||
55 | #define OS_REF_YEAR 1900 | ||
56 | |||
57 | /* | ||
58 | PMU RTC have only 2 nibbles to store year information, so using an | ||
59 | offset of 100 to set the base year as 2000 for our driver. | ||
60 | */ | ||
61 | #define RTC_YEAR_OFFSET 100 | ||
62 | |||
63 | struct tps80031_rtc { | ||
64 | unsigned long epoch_start; | ||
65 | int irq; | ||
66 | struct rtc_device *rtc; | ||
67 | u8 alarm_irq_enabled; | ||
68 | }; | ||
69 | |||
70 | static int tps80031_read_regs(struct device *dev, int reg, int len, | ||
71 | uint8_t *val) | ||
72 | { | ||
73 | int ret; | ||
74 | |||
75 | /* dummy read of STATUS_REG as per data sheet */ | ||
76 | ret = tps80031_reads(dev->parent, 1, RTC_STATUS, 1, val); | ||
77 | if (ret < 0) { | ||
78 | dev_err(dev->parent, "failed reading RTC_STATUS\n"); | ||
79 | WARN_ON(1); | ||
80 | return ret; | ||
81 | } | ||
82 | |||
83 | ret = tps80031_reads(dev->parent, 1, reg, len, val); | ||
84 | if (ret < 0) { | ||
85 | dev_err(dev->parent, "failed reading from reg %d\n", reg); | ||
86 | WARN_ON(1); | ||
87 | return ret; | ||
88 | } | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static int tps80031_write_regs(struct device *dev, int reg, int len, | ||
93 | uint8_t *val) | ||
94 | { | ||
95 | int ret; | ||
96 | ret = tps80031_writes(dev->parent, 1, reg, len, val); | ||
97 | if (ret < 0) { | ||
98 | dev_err(dev->parent, "failed writing reg: %d\n", reg); | ||
99 | WARN_ON(1); | ||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static u8 dec2bcd(u8 dec) | ||
107 | { | ||
108 | return ((dec/10)<<4)+(dec%10); | ||
109 | } | ||
110 | |||
111 | static u8 bcd2dec(u8 bcd) | ||
112 | { | ||
113 | return (bcd >> 4)*10+(bcd & 0xF); | ||
114 | } | ||
115 | |||
116 | static void convert_bcd_to_decimal(u8 *buf, u8 len) | ||
117 | { | ||
118 | int i = 0; | ||
119 | for (i = 0; i < len; i++) | ||
120 | buf[i] = bcd2dec(buf[i]); | ||
121 | } | ||
122 | |||
123 | static void convert_decimal_to_bcd(u8 *buf, u8 len) | ||
124 | { | ||
125 | int i = 0; | ||
126 | for (i = 0; i < len; i++) | ||
127 | buf[i] = dec2bcd(buf[i]); | ||
128 | } | ||
129 | |||
130 | static int tps80031_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
131 | { | ||
132 | u8 buff[7]; | ||
133 | int err; | ||
134 | err = tps80031_read_regs(dev, RTC_SECONDS_REG, sizeof(buff), buff); | ||
135 | if (err < 0) { | ||
136 | dev_err(dev->parent, "failed reading time\n"); | ||
137 | return err; | ||
138 | } | ||
139 | convert_bcd_to_decimal(buff, sizeof(buff)); | ||
140 | tm->tm_sec = buff[0]; | ||
141 | tm->tm_min = buff[1]; | ||
142 | tm->tm_hour = buff[2]; | ||
143 | tm->tm_mday = buff[3]; | ||
144 | tm->tm_mon = buff[4] - 1; | ||
145 | tm->tm_year = buff[5] + RTC_YEAR_OFFSET; | ||
146 | tm->tm_wday = buff[6]; | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static int tps80031_rtc_stop(struct device *dev) | ||
151 | { | ||
152 | int err; | ||
153 | err = tps80031_clr_bits(dev->parent, 1, RTC_CTRL, STOP_RTC); | ||
154 | if (err < 0) | ||
155 | dev_err(dev->parent, "failed to stop RTC. err: %d\n", err); | ||
156 | return err; | ||
157 | } | ||
158 | |||
159 | static int tps80031_rtc_start(struct device *dev) | ||
160 | { | ||
161 | int err; | ||
162 | err = tps80031_set_bits(dev->parent, 1, RTC_CTRL, STOP_RTC); | ||
163 | if (err < 0) | ||
164 | dev_err(dev->parent, "failed to start RTC. err: %d\n", err); | ||
165 | return err; | ||
166 | } | ||
167 | |||
168 | |||
169 | static int tps80031_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
170 | { | ||
171 | u8 buff[7]; | ||
172 | int err; | ||
173 | |||
174 | buff[0] = tm->tm_sec; | ||
175 | buff[1] = tm->tm_min; | ||
176 | buff[2] = tm->tm_hour; | ||
177 | buff[3] = tm->tm_mday; | ||
178 | buff[4] = tm->tm_mon + 1; | ||
179 | buff[5] = tm->tm_year % RTC_YEAR_OFFSET; | ||
180 | buff[6] = tm->tm_wday; | ||
181 | |||
182 | convert_decimal_to_bcd(buff, sizeof(buff)); | ||
183 | err = tps80031_rtc_stop(dev); | ||
184 | if (err < 0) | ||
185 | return err; | ||
186 | |||
187 | err = tps80031_write_regs(dev, RTC_SECONDS_REG, sizeof(buff), buff); | ||
188 | if (err < 0) { | ||
189 | dev_err(dev->parent, "failed to program new time\n"); | ||
190 | return err; | ||
191 | } | ||
192 | |||
193 | err = tps80031_rtc_start(dev); | ||
194 | return err; | ||
195 | } | ||
196 | |||
197 | static int tps80031_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
198 | { | ||
199 | struct tps80031_rtc *rtc = dev_get_drvdata(dev); | ||
200 | unsigned long seconds; | ||
201 | u8 buff[6]; | ||
202 | int err; | ||
203 | struct rtc_time tm; | ||
204 | |||
205 | if (rtc->irq == -1) | ||
206 | return -EIO; | ||
207 | |||
208 | rtc_tm_to_time(&alrm->time, &seconds); | ||
209 | tps80031_rtc_read_time(dev, &tm); | ||
210 | rtc_tm_to_time(&tm, &rtc->epoch_start); | ||
211 | |||
212 | if (WARN_ON(alrm->enabled && (seconds < rtc->epoch_start))) { | ||
213 | dev_err(dev->parent, "can't set alarm to requested time\n"); | ||
214 | return -EINVAL; | ||
215 | } | ||
216 | |||
217 | buff[0] = alrm->time.tm_sec; | ||
218 | buff[1] = alrm->time.tm_min; | ||
219 | buff[2] = alrm->time.tm_hour; | ||
220 | buff[3] = alrm->time.tm_mday; | ||
221 | buff[4] = alrm->time.tm_mon + 1; | ||
222 | buff[5] = alrm->time.tm_year % RTC_YEAR_OFFSET; | ||
223 | convert_decimal_to_bcd(buff, sizeof(buff)); | ||
224 | err = tps80031_write_regs(dev, RTC_ALARM, sizeof(buff), buff); | ||
225 | if (err) | ||
226 | dev_err(dev->parent, "unable to program alarm\n"); | ||
227 | |||
228 | return err; | ||
229 | } | ||
230 | |||
231 | static int tps80031_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
232 | { | ||
233 | u8 buff[6]; | ||
234 | int err; | ||
235 | |||
236 | err = tps80031_read_regs(dev, RTC_ALARM, sizeof(buff), buff); | ||
237 | if (err) | ||
238 | return err; | ||
239 | convert_bcd_to_decimal(buff, sizeof(buff)); | ||
240 | |||
241 | alrm->time.tm_sec = buff[0]; | ||
242 | alrm->time.tm_min = buff[1]; | ||
243 | alrm->time.tm_hour = buff[2]; | ||
244 | alrm->time.tm_mday = buff[3]; | ||
245 | alrm->time.tm_mon = buff[4] - 1; | ||
246 | alrm->time.tm_year = buff[5] + RTC_YEAR_OFFSET; | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | static int tps80031_rtc_alarm_irq_enable(struct device *dev, | ||
252 | unsigned int enable) | ||
253 | { | ||
254 | struct tps80031_rtc *rtc = dev_get_drvdata(dev); | ||
255 | int err; | ||
256 | struct device *p = dev->parent; | ||
257 | |||
258 | if (rtc->irq == -1) | ||
259 | return -EIO; | ||
260 | |||
261 | if (enable) { | ||
262 | if (rtc->alarm_irq_enabled) | ||
263 | return 0; | ||
264 | |||
265 | err = tps80031_set_bits(p, 1, RTC_INT, ENABLE_ALARM_INT); | ||
266 | if (err < 0) { | ||
267 | dev_err(p, "failed to set ALRM int. err: %d\n", err); | ||
268 | return err; | ||
269 | } else | ||
270 | rtc->alarm_irq_enabled = 1; | ||
271 | } else { | ||
272 | if(!rtc->alarm_irq_enabled) | ||
273 | return 0; | ||
274 | err = tps80031_clr_bits(p, 1, RTC_INT, ENABLE_ALARM_INT); | ||
275 | if (err < 0) { | ||
276 | dev_err(p, "failed to clear ALRM int. err: %d\n", err); | ||
277 | return err; | ||
278 | } else | ||
279 | rtc->alarm_irq_enabled = 0; | ||
280 | } | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static const struct rtc_class_ops tps80031_rtc_ops = { | ||
285 | .read_time = tps80031_rtc_read_time, | ||
286 | .set_time = tps80031_rtc_set_time, | ||
287 | .set_alarm = tps80031_rtc_set_alarm, | ||
288 | .read_alarm = tps80031_rtc_read_alarm, | ||
289 | .alarm_irq_enable = tps80031_rtc_alarm_irq_enable, | ||
290 | }; | ||
291 | |||
292 | static irqreturn_t tps80031_rtc_irq(int irq, void *data) | ||
293 | { | ||
294 | struct device *dev = data; | ||
295 | struct tps80031_rtc *rtc = dev_get_drvdata(dev); | ||
296 | u8 reg; | ||
297 | int err; | ||
298 | |||
299 | /* clear Alarm status bits.*/ | ||
300 | err = tps80031_read_regs(dev, RTC_STATUS, 1, ®); | ||
301 | if (err) { | ||
302 | dev_err(dev->parent, "unable to read RTC_STATUS reg\n"); | ||
303 | return -EBUSY; | ||
304 | } | ||
305 | |||
306 | err = tps80031_force_update(dev->parent, 1, RTC_STATUS, | ||
307 | ALARM_INT_STATUS, ALARM_INT_STATUS); | ||
308 | if (err) { | ||
309 | dev_err(dev->parent, "unable to set Alarm INT\n"); | ||
310 | return -EBUSY; | ||
311 | } | ||
312 | |||
313 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); | ||
314 | return IRQ_HANDLED; | ||
315 | } | ||
316 | |||
317 | static int __devinit tps80031_rtc_probe(struct platform_device *pdev) | ||
318 | { | ||
319 | struct tps80031_rtc_platform_data *pdata = pdev->dev.platform_data; | ||
320 | struct tps80031_rtc *rtc; | ||
321 | struct rtc_time tm; | ||
322 | int err; | ||
323 | u8 reg; | ||
324 | |||
325 | if (!pdata) { | ||
326 | dev_err(&pdev->dev, "no platform_data specified\n"); | ||
327 | return -EINVAL; | ||
328 | } | ||
329 | |||
330 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | ||
331 | if (!rtc) | ||
332 | return -ENOMEM; | ||
333 | |||
334 | rtc->irq = -1; | ||
335 | if (pdata->irq < 0) | ||
336 | dev_err(&pdev->dev, "no IRQ specified, wakeup is disabled\n"); | ||
337 | |||
338 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
339 | &tps80031_rtc_ops, THIS_MODULE); | ||
340 | |||
341 | if (IS_ERR(rtc->rtc)) { | ||
342 | err = PTR_ERR(rtc->rtc); | ||
343 | goto fail; | ||
344 | } | ||
345 | |||
346 | if ((int)pdev && (int)&pdev->dev) | ||
347 | err = tps80031_read_regs(&pdev->dev, RTC_STATUS, 1, ®); | ||
348 | else { | ||
349 | dev_err(&pdev->dev, "%s Input params incorrect\n", __func__); | ||
350 | err = -EBUSY; | ||
351 | goto fail; | ||
352 | } | ||
353 | |||
354 | if (err) { | ||
355 | dev_err(&pdev->dev, "%s unable to read status\n", __func__); | ||
356 | err = -EBUSY; | ||
357 | goto fail; | ||
358 | } | ||
359 | |||
360 | /* If RTC have POR values, set time using platform data*/ | ||
361 | tps80031_rtc_read_time(&pdev->dev, &tm); | ||
362 | if ((tm.tm_year == RTC_YEAR_OFFSET + RTC_POR_YEAR) && | ||
363 | (tm.tm_mon == (RTC_POR_MONTH - 1)) && | ||
364 | (tm.tm_mday == RTC_POR_DAY)) { | ||
365 | if (pdata->time.tm_year < 2000 || | ||
366 | pdata->time.tm_year > 2100) { | ||
367 | dev_err(&pdev->dev, "Invalid platform data\n"); | ||
368 | memset(&pdata->time, 0, sizeof(pdata->time)); | ||
369 | pdata->time.tm_year = 2011; | ||
370 | pdata->time.tm_mday = 1; | ||
371 | } | ||
372 | tps80031_rtc_set_time(&pdev->dev, &pdata->time); | ||
373 | } | ||
374 | |||
375 | reg = ALARM_INT_STATUS; | ||
376 | err = tps80031_write_regs(&pdev->dev, RTC_STATUS, 1, ®); | ||
377 | if (err) { | ||
378 | dev_err(&pdev->dev, "unable to program RTC_STATUS reg\n"); | ||
379 | return -EBUSY; | ||
380 | } | ||
381 | |||
382 | err = tps80031_set_bits(pdev->dev.parent, 1, RTC_INT, ENABLE_ALARM_INT); | ||
383 | if (err) { | ||
384 | dev_err(&pdev->dev, "unable to program Interrupt Mask reg\n"); | ||
385 | err = -EBUSY; | ||
386 | rtc->alarm_irq_enabled = 0; | ||
387 | goto fail; | ||
388 | } else | ||
389 | rtc->alarm_irq_enabled = 1; | ||
390 | |||
391 | dev_set_drvdata(&pdev->dev, rtc); | ||
392 | if (pdata && (pdata->irq >= 0)) { | ||
393 | rtc->irq = pdata->irq; | ||
394 | err = request_threaded_irq(pdata->irq, NULL, tps80031_rtc_irq, | ||
395 | IRQF_ONESHOT, "rtc_tps80031", | ||
396 | &pdev->dev); | ||
397 | if (err) { | ||
398 | dev_err(&pdev->dev, "request IRQ:%d fail\n", rtc->irq); | ||
399 | rtc->irq = -1; | ||
400 | } else { | ||
401 | device_init_wakeup(&pdev->dev, 1); | ||
402 | enable_irq_wake(rtc->irq); | ||
403 | } | ||
404 | } | ||
405 | return 0; | ||
406 | |||
407 | fail: | ||
408 | if (!IS_ERR_OR_NULL(rtc->rtc)) | ||
409 | rtc_device_unregister(rtc->rtc); | ||
410 | kfree(rtc); | ||
411 | return err; | ||
412 | } | ||
413 | |||
414 | static int __devexit tps80031_rtc_remove(struct platform_device *pdev) | ||
415 | { | ||
416 | struct tps80031_rtc *rtc = dev_get_drvdata(&pdev->dev); | ||
417 | |||
418 | if (rtc->irq != -1) | ||
419 | free_irq(rtc->irq, rtc); | ||
420 | rtc_device_unregister(rtc->rtc); | ||
421 | kfree(rtc); | ||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | static struct platform_driver tps80031_rtc_driver = { | ||
426 | .driver = { | ||
427 | .name = "rtc_tps80031", | ||
428 | .owner = THIS_MODULE, | ||
429 | }, | ||
430 | .probe = tps80031_rtc_probe, | ||
431 | .remove = __devexit_p(tps80031_rtc_remove), | ||
432 | }; | ||
433 | |||
434 | static int __init tps80031_rtc_init(void) | ||
435 | { | ||
436 | return platform_driver_register(&tps80031_rtc_driver); | ||
437 | } | ||
438 | module_init(tps80031_rtc_init); | ||
439 | |||
440 | static void __exit tps80031_rtc_exit(void) | ||
441 | { | ||
442 | platform_driver_unregister(&tps80031_rtc_driver); | ||
443 | } | ||
444 | module_exit(tps80031_rtc_exit); | ||
445 | |||
446 | MODULE_DESCRIPTION("TI TPS80031 RTC driver"); | ||
447 | MODULE_AUTHOR("NVIDIA Corporation"); | ||
448 | MODULE_LICENSE("GPL"); | ||
449 | MODULE_ALIAS("platform:rtc_tps80031"); | ||
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index f9a2799c44d..20687d55e7a 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c | |||
@@ -275,7 +275,7 @@ static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
275 | goto out; | 275 | goto out; |
276 | 276 | ||
277 | save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; | 277 | save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; |
278 | twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); | 278 | ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); |
279 | if (ret < 0) | 279 | if (ret < 0) |
280 | goto out; | 280 | goto out; |
281 | 281 | ||
@@ -362,14 +362,6 @@ static irqreturn_t twl_rtc_interrupt(int irq, void *rtc) | |||
362 | int res; | 362 | int res; |
363 | u8 rd_reg; | 363 | u8 rd_reg; |
364 | 364 | ||
365 | #ifdef CONFIG_LOCKDEP | ||
366 | /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which | ||
367 | * we don't want and can't tolerate. Although it might be | ||
368 | * friendlier not to borrow this thread context... | ||
369 | */ | ||
370 | local_irq_enable(); | ||
371 | #endif | ||
372 | |||
373 | res = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); | 365 | res = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); |
374 | if (res) | 366 | if (res) |
375 | goto out; | 367 | goto out; |
@@ -428,24 +420,12 @@ static struct rtc_class_ops twl_rtc_ops = { | |||
428 | static int __devinit twl_rtc_probe(struct platform_device *pdev) | 420 | static int __devinit twl_rtc_probe(struct platform_device *pdev) |
429 | { | 421 | { |
430 | struct rtc_device *rtc; | 422 | struct rtc_device *rtc; |
431 | int ret = 0; | 423 | int ret = -EINVAL; |
432 | int irq = platform_get_irq(pdev, 0); | 424 | int irq = platform_get_irq(pdev, 0); |
433 | u8 rd_reg; | 425 | u8 rd_reg; |
434 | 426 | ||
435 | if (irq <= 0) | 427 | if (irq <= 0) |
436 | return -EINVAL; | 428 | goto out1; |
437 | |||
438 | rtc = rtc_device_register(pdev->name, | ||
439 | &pdev->dev, &twl_rtc_ops, THIS_MODULE); | ||
440 | if (IS_ERR(rtc)) { | ||
441 | ret = PTR_ERR(rtc); | ||
442 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", | ||
443 | PTR_ERR(rtc)); | ||
444 | goto out0; | ||
445 | |||
446 | } | ||
447 | |||
448 | platform_set_drvdata(pdev, rtc); | ||
449 | 429 | ||
450 | ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); | 430 | ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); |
451 | if (ret < 0) | 431 | if (ret < 0) |
@@ -462,14 +442,6 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev) | |||
462 | if (ret < 0) | 442 | if (ret < 0) |
463 | goto out1; | 443 | goto out1; |
464 | 444 | ||
465 | ret = request_irq(irq, twl_rtc_interrupt, | ||
466 | IRQF_TRIGGER_RISING, | ||
467 | dev_name(&rtc->dev), rtc); | ||
468 | if (ret < 0) { | ||
469 | dev_err(&pdev->dev, "IRQ is not free.\n"); | ||
470 | goto out1; | ||
471 | } | ||
472 | |||
473 | if (twl_class_is_6030()) { | 445 | if (twl_class_is_6030()) { |
474 | twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, | 446 | twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, |
475 | REG_INT_MSK_LINE_A); | 447 | REG_INT_MSK_LINE_A); |
@@ -480,28 +452,44 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev) | |||
480 | /* Check RTC module status, Enable if it is off */ | 452 | /* Check RTC module status, Enable if it is off */ |
481 | ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); | 453 | ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); |
482 | if (ret < 0) | 454 | if (ret < 0) |
483 | goto out2; | 455 | goto out1; |
484 | 456 | ||
485 | if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { | 457 | if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { |
486 | dev_info(&pdev->dev, "Enabling TWL-RTC.\n"); | 458 | dev_info(&pdev->dev, "Enabling TWL-RTC.\n"); |
487 | rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; | 459 | rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; |
488 | ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); | 460 | ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); |
489 | if (ret < 0) | 461 | if (ret < 0) |
490 | goto out2; | 462 | goto out1; |
491 | } | 463 | } |
492 | 464 | ||
493 | /* init cached IRQ enable bits */ | 465 | /* init cached IRQ enable bits */ |
494 | ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); | 466 | ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); |
495 | if (ret < 0) | 467 | if (ret < 0) |
468 | goto out1; | ||
469 | |||
470 | rtc = rtc_device_register(pdev->name, | ||
471 | &pdev->dev, &twl_rtc_ops, THIS_MODULE); | ||
472 | if (IS_ERR(rtc)) { | ||
473 | ret = PTR_ERR(rtc); | ||
474 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", | ||
475 | PTR_ERR(rtc)); | ||
476 | goto out1; | ||
477 | } | ||
478 | |||
479 | ret = request_threaded_irq(irq, NULL, twl_rtc_interrupt, | ||
480 | IRQF_TRIGGER_RISING, | ||
481 | dev_name(&rtc->dev), rtc); | ||
482 | if (ret < 0) { | ||
483 | dev_err(&pdev->dev, "IRQ is not free.\n"); | ||
496 | goto out2; | 484 | goto out2; |
485 | } | ||
497 | 486 | ||
498 | return ret; | 487 | platform_set_drvdata(pdev, rtc); |
488 | return 0; | ||
499 | 489 | ||
500 | out2: | 490 | out2: |
501 | free_irq(irq, rtc); | ||
502 | out1: | ||
503 | rtc_device_unregister(rtc); | 491 | rtc_device_unregister(rtc); |
504 | out0: | 492 | out1: |
505 | return ret; | 493 | return ret; |
506 | } | 494 | } |
507 | 495 | ||
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index efd6066b5cd..f93f412423c 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c | |||
@@ -74,6 +74,8 @@ | |||
74 | #define VT8500_RTC_CR_SM_SEC (1 << 3) /* 0: 1Hz/60, 1: 1Hz */ | 74 | #define VT8500_RTC_CR_SM_SEC (1 << 3) /* 0: 1Hz/60, 1: 1Hz */ |
75 | #define VT8500_RTC_CR_CALIB (1 << 4) /* Enable calibration */ | 75 | #define VT8500_RTC_CR_CALIB (1 << 4) /* Enable calibration */ |
76 | 76 | ||
77 | #define VT8500_RTC_IS_ALARM (1 << 0) /* Alarm interrupt status */ | ||
78 | |||
77 | struct vt8500_rtc { | 79 | struct vt8500_rtc { |
78 | void __iomem *regbase; | 80 | void __iomem *regbase; |
79 | struct resource *res; | 81 | struct resource *res; |
@@ -96,7 +98,7 @@ static irqreturn_t vt8500_rtc_irq(int irq, void *dev_id) | |||
96 | 98 | ||
97 | spin_unlock(&vt8500_rtc->lock); | 99 | spin_unlock(&vt8500_rtc->lock); |
98 | 100 | ||
99 | if (isr & 1) | 101 | if (isr & VT8500_RTC_IS_ALARM) |
100 | events |= RTC_AF | RTC_IRQF; | 102 | events |= RTC_AF | RTC_IRQF; |
101 | 103 | ||
102 | rtc_update_irq(vt8500_rtc->rtc, 1, events); | 104 | rtc_update_irq(vt8500_rtc->rtc, 1, events); |
@@ -161,8 +163,8 @@ static int vt8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
161 | alrm->time.tm_sec = bcd2bin((alarm & TIME_SEC_MASK)); | 163 | alrm->time.tm_sec = bcd2bin((alarm & TIME_SEC_MASK)); |
162 | 164 | ||
163 | alrm->enabled = (alarm & ALARM_ENABLE_MASK) ? 1 : 0; | 165 | alrm->enabled = (alarm & ALARM_ENABLE_MASK) ? 1 : 0; |
166 | alrm->pending = (isr & VT8500_RTC_IS_ALARM) ? 1 : 0; | ||
164 | 167 | ||
165 | alrm->pending = (isr & 1) ? 1 : 0; | ||
166 | return rtc_valid_tm(&alrm->time); | 168 | return rtc_valid_tm(&alrm->time); |
167 | } | 169 | } |
168 | 170 | ||