Commit a46481d7af1e6c59c03f3ddac400d9054f804952
Committed by
Linus Torvalds
1 parent
0c4eae6659
Exists in
master
and in
6 other branches
drivers/rtc/rtc-mc13xxx.c: make mc13xxx_rtc_idtable static
Signed-off-by: Axel Lin <axel.lin@gmail.com> Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Cc: Alessandro Zummo <a.zummo@towertech.it> Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 1 additions and 1 deletions Inline Diff
drivers/rtc/rtc-mc13xxx.c
1 | /* | 1 | /* |
2 | * Real Time Clock driver for Freescale MC13XXX PMIC | 2 | * Real Time Clock driver for Freescale MC13XXX PMIC |
3 | * | 3 | * |
4 | * (C) 2009 Sascha Hauer, Pengutronix | 4 | * (C) 2009 Sascha Hauer, Pengutronix |
5 | * (C) 2009 Uwe Kleine-Koenig, Pengutronix | 5 | * (C) 2009 Uwe Kleine-Koenig, Pengutronix |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/mfd/mc13xxx.h> | 12 | #include <linux/mfd/mc13xxx.h> |
13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/rtc.h> | 17 | #include <linux/rtc.h> |
18 | 18 | ||
19 | #define DRIVER_NAME "mc13xxx-rtc" | 19 | #define DRIVER_NAME "mc13xxx-rtc" |
20 | 20 | ||
21 | #define MC13XXX_RTCTOD 20 | 21 | #define MC13XXX_RTCTOD 20 |
22 | #define MC13XXX_RTCTODA 21 | 22 | #define MC13XXX_RTCTODA 21 |
23 | #define MC13XXX_RTCDAY 22 | 23 | #define MC13XXX_RTCDAY 22 |
24 | #define MC13XXX_RTCDAYA 23 | 24 | #define MC13XXX_RTCDAYA 23 |
25 | 25 | ||
26 | struct mc13xxx_rtc { | 26 | struct mc13xxx_rtc { |
27 | struct rtc_device *rtc; | 27 | struct rtc_device *rtc; |
28 | struct mc13xxx *mc13xxx; | 28 | struct mc13xxx *mc13xxx; |
29 | int valid; | 29 | int valid; |
30 | }; | 30 | }; |
31 | 31 | ||
32 | static int mc13xxx_rtc_irq_enable_unlocked(struct device *dev, | 32 | static int mc13xxx_rtc_irq_enable_unlocked(struct device *dev, |
33 | unsigned int enabled, int irq) | 33 | unsigned int enabled, int irq) |
34 | { | 34 | { |
35 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | 35 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); |
36 | int (*func)(struct mc13xxx *mc13xxx, int irq); | 36 | int (*func)(struct mc13xxx *mc13xxx, int irq); |
37 | 37 | ||
38 | if (!priv->valid) | 38 | if (!priv->valid) |
39 | return -ENODATA; | 39 | return -ENODATA; |
40 | 40 | ||
41 | func = enabled ? mc13xxx_irq_unmask : mc13xxx_irq_mask; | 41 | func = enabled ? mc13xxx_irq_unmask : mc13xxx_irq_mask; |
42 | return func(priv->mc13xxx, irq); | 42 | return func(priv->mc13xxx, irq); |
43 | } | 43 | } |
44 | 44 | ||
45 | static int mc13xxx_rtc_irq_enable(struct device *dev, | 45 | static int mc13xxx_rtc_irq_enable(struct device *dev, |
46 | unsigned int enabled, int irq) | 46 | unsigned int enabled, int irq) |
47 | { | 47 | { |
48 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | 48 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); |
49 | int ret; | 49 | int ret; |
50 | 50 | ||
51 | mc13xxx_lock(priv->mc13xxx); | 51 | mc13xxx_lock(priv->mc13xxx); |
52 | 52 | ||
53 | ret = mc13xxx_rtc_irq_enable_unlocked(dev, enabled, irq); | 53 | ret = mc13xxx_rtc_irq_enable_unlocked(dev, enabled, irq); |
54 | 54 | ||
55 | mc13xxx_unlock(priv->mc13xxx); | 55 | mc13xxx_unlock(priv->mc13xxx); |
56 | 56 | ||
57 | return ret; | 57 | return ret; |
58 | } | 58 | } |
59 | 59 | ||
60 | static int mc13xxx_rtc_read_time(struct device *dev, struct rtc_time *tm) | 60 | static int mc13xxx_rtc_read_time(struct device *dev, struct rtc_time *tm) |
61 | { | 61 | { |
62 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | 62 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); |
63 | unsigned int seconds, days1, days2; | 63 | unsigned int seconds, days1, days2; |
64 | unsigned long s1970; | 64 | unsigned long s1970; |
65 | int ret; | 65 | int ret; |
66 | 66 | ||
67 | mc13xxx_lock(priv->mc13xxx); | 67 | mc13xxx_lock(priv->mc13xxx); |
68 | 68 | ||
69 | if (!priv->valid) { | 69 | if (!priv->valid) { |
70 | ret = -ENODATA; | 70 | ret = -ENODATA; |
71 | goto out; | 71 | goto out; |
72 | } | 72 | } |
73 | 73 | ||
74 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days1); | 74 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days1); |
75 | if (unlikely(ret)) | 75 | if (unlikely(ret)) |
76 | goto out; | 76 | goto out; |
77 | 77 | ||
78 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTOD, &seconds); | 78 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTOD, &seconds); |
79 | if (unlikely(ret)) | 79 | if (unlikely(ret)) |
80 | goto out; | 80 | goto out; |
81 | 81 | ||
82 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days2); | 82 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days2); |
83 | out: | 83 | out: |
84 | mc13xxx_unlock(priv->mc13xxx); | 84 | mc13xxx_unlock(priv->mc13xxx); |
85 | 85 | ||
86 | if (ret) | 86 | if (ret) |
87 | return ret; | 87 | return ret; |
88 | 88 | ||
89 | if (days2 == days1 + 1) { | 89 | if (days2 == days1 + 1) { |
90 | if (seconds >= 86400 / 2) | 90 | if (seconds >= 86400 / 2) |
91 | days2 = days1; | 91 | days2 = days1; |
92 | else | 92 | else |
93 | days1 = days2; | 93 | days1 = days2; |
94 | } | 94 | } |
95 | 95 | ||
96 | if (days1 != days2) | 96 | if (days1 != days2) |
97 | return -EIO; | 97 | return -EIO; |
98 | 98 | ||
99 | s1970 = days1 * 86400 + seconds; | 99 | s1970 = days1 * 86400 + seconds; |
100 | 100 | ||
101 | rtc_time_to_tm(s1970, tm); | 101 | rtc_time_to_tm(s1970, tm); |
102 | 102 | ||
103 | return rtc_valid_tm(tm); | 103 | return rtc_valid_tm(tm); |
104 | } | 104 | } |
105 | 105 | ||
106 | static int mc13xxx_rtc_set_mmss(struct device *dev, unsigned long secs) | 106 | static int mc13xxx_rtc_set_mmss(struct device *dev, unsigned long secs) |
107 | { | 107 | { |
108 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | 108 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); |
109 | unsigned int seconds, days; | 109 | unsigned int seconds, days; |
110 | unsigned int alarmseconds; | 110 | unsigned int alarmseconds; |
111 | int ret; | 111 | int ret; |
112 | 112 | ||
113 | seconds = secs % 86400; | 113 | seconds = secs % 86400; |
114 | days = secs / 86400; | 114 | days = secs / 86400; |
115 | 115 | ||
116 | mc13xxx_lock(priv->mc13xxx); | 116 | mc13xxx_lock(priv->mc13xxx); |
117 | 117 | ||
118 | /* | 118 | /* |
119 | * temporarily invalidate alarm to prevent triggering it when the day is | 119 | * temporarily invalidate alarm to prevent triggering it when the day is |
120 | * already updated while the time isn't yet. | 120 | * already updated while the time isn't yet. |
121 | */ | 121 | */ |
122 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &alarmseconds); | 122 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &alarmseconds); |
123 | if (unlikely(ret)) | 123 | if (unlikely(ret)) |
124 | goto out; | 124 | goto out; |
125 | 125 | ||
126 | if (alarmseconds < 86400) { | 126 | if (alarmseconds < 86400) { |
127 | ret = mc13xxx_reg_write(priv->mc13xxx, | 127 | ret = mc13xxx_reg_write(priv->mc13xxx, |
128 | MC13XXX_RTCTODA, 0x1ffff); | 128 | MC13XXX_RTCTODA, 0x1ffff); |
129 | if (unlikely(ret)) | 129 | if (unlikely(ret)) |
130 | goto out; | 130 | goto out; |
131 | } | 131 | } |
132 | 132 | ||
133 | /* | 133 | /* |
134 | * write seconds=0 to prevent a day switch between writing days | 134 | * write seconds=0 to prevent a day switch between writing days |
135 | * and seconds below | 135 | * and seconds below |
136 | */ | 136 | */ |
137 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, 0); | 137 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, 0); |
138 | if (unlikely(ret)) | 138 | if (unlikely(ret)) |
139 | goto out; | 139 | goto out; |
140 | 140 | ||
141 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAY, days); | 141 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAY, days); |
142 | if (unlikely(ret)) | 142 | if (unlikely(ret)) |
143 | goto out; | 143 | goto out; |
144 | 144 | ||
145 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, seconds); | 145 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, seconds); |
146 | if (unlikely(ret)) | 146 | if (unlikely(ret)) |
147 | goto out; | 147 | goto out; |
148 | 148 | ||
149 | /* restore alarm */ | 149 | /* restore alarm */ |
150 | if (alarmseconds < 86400) { | 150 | if (alarmseconds < 86400) { |
151 | ret = mc13xxx_reg_write(priv->mc13xxx, | 151 | ret = mc13xxx_reg_write(priv->mc13xxx, |
152 | MC13XXX_RTCTODA, alarmseconds); | 152 | MC13XXX_RTCTODA, alarmseconds); |
153 | if (unlikely(ret)) | 153 | if (unlikely(ret)) |
154 | goto out; | 154 | goto out; |
155 | } | 155 | } |
156 | 156 | ||
157 | ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_RTCRST); | 157 | ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_RTCRST); |
158 | if (unlikely(ret)) | 158 | if (unlikely(ret)) |
159 | goto out; | 159 | goto out; |
160 | 160 | ||
161 | ret = mc13xxx_irq_unmask(priv->mc13xxx, MC13XXX_IRQ_RTCRST); | 161 | ret = mc13xxx_irq_unmask(priv->mc13xxx, MC13XXX_IRQ_RTCRST); |
162 | out: | 162 | out: |
163 | priv->valid = !ret; | 163 | priv->valid = !ret; |
164 | 164 | ||
165 | mc13xxx_unlock(priv->mc13xxx); | 165 | mc13xxx_unlock(priv->mc13xxx); |
166 | 166 | ||
167 | return ret; | 167 | return ret; |
168 | } | 168 | } |
169 | 169 | ||
170 | static int mc13xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 170 | static int mc13xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
171 | { | 171 | { |
172 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | 172 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); |
173 | unsigned seconds, days; | 173 | unsigned seconds, days; |
174 | unsigned long s1970; | 174 | unsigned long s1970; |
175 | int enabled, pending; | 175 | int enabled, pending; |
176 | int ret; | 176 | int ret; |
177 | 177 | ||
178 | mc13xxx_lock(priv->mc13xxx); | 178 | mc13xxx_lock(priv->mc13xxx); |
179 | 179 | ||
180 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &seconds); | 180 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &seconds); |
181 | if (unlikely(ret)) | 181 | if (unlikely(ret)) |
182 | goto out; | 182 | goto out; |
183 | if (seconds >= 86400) { | 183 | if (seconds >= 86400) { |
184 | ret = -ENODATA; | 184 | ret = -ENODATA; |
185 | goto out; | 185 | goto out; |
186 | } | 186 | } |
187 | 187 | ||
188 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days); | 188 | ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days); |
189 | if (unlikely(ret)) | 189 | if (unlikely(ret)) |
190 | goto out; | 190 | goto out; |
191 | 191 | ||
192 | ret = mc13xxx_irq_status(priv->mc13xxx, MC13XXX_IRQ_TODA, | 192 | ret = mc13xxx_irq_status(priv->mc13xxx, MC13XXX_IRQ_TODA, |
193 | &enabled, &pending); | 193 | &enabled, &pending); |
194 | 194 | ||
195 | out: | 195 | out: |
196 | mc13xxx_unlock(priv->mc13xxx); | 196 | mc13xxx_unlock(priv->mc13xxx); |
197 | 197 | ||
198 | if (ret) | 198 | if (ret) |
199 | return ret; | 199 | return ret; |
200 | 200 | ||
201 | alarm->enabled = enabled; | 201 | alarm->enabled = enabled; |
202 | alarm->pending = pending; | 202 | alarm->pending = pending; |
203 | 203 | ||
204 | s1970 = days * 86400 + seconds; | 204 | s1970 = days * 86400 + seconds; |
205 | 205 | ||
206 | rtc_time_to_tm(s1970, &alarm->time); | 206 | rtc_time_to_tm(s1970, &alarm->time); |
207 | dev_dbg(dev, "%s: %lu\n", __func__, s1970); | 207 | dev_dbg(dev, "%s: %lu\n", __func__, s1970); |
208 | 208 | ||
209 | return 0; | 209 | return 0; |
210 | } | 210 | } |
211 | 211 | ||
212 | static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 212 | static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
213 | { | 213 | { |
214 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); | 214 | struct mc13xxx_rtc *priv = dev_get_drvdata(dev); |
215 | unsigned long s1970; | 215 | unsigned long s1970; |
216 | unsigned seconds, days; | 216 | unsigned seconds, days; |
217 | int ret; | 217 | int ret; |
218 | 218 | ||
219 | mc13xxx_lock(priv->mc13xxx); | 219 | mc13xxx_lock(priv->mc13xxx); |
220 | 220 | ||
221 | /* disable alarm to prevent false triggering */ | 221 | /* disable alarm to prevent false triggering */ |
222 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, 0x1ffff); | 222 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, 0x1ffff); |
223 | if (unlikely(ret)) | 223 | if (unlikely(ret)) |
224 | goto out; | 224 | goto out; |
225 | 225 | ||
226 | ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_TODA); | 226 | ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_TODA); |
227 | if (unlikely(ret)) | 227 | if (unlikely(ret)) |
228 | goto out; | 228 | goto out; |
229 | 229 | ||
230 | ret = rtc_tm_to_time(&alarm->time, &s1970); | 230 | ret = rtc_tm_to_time(&alarm->time, &s1970); |
231 | if (unlikely(ret)) | 231 | if (unlikely(ret)) |
232 | goto out; | 232 | goto out; |
233 | 233 | ||
234 | dev_dbg(dev, "%s: o%2.s %lu\n", __func__, alarm->enabled ? "n" : "ff", | 234 | dev_dbg(dev, "%s: o%2.s %lu\n", __func__, alarm->enabled ? "n" : "ff", |
235 | s1970); | 235 | s1970); |
236 | 236 | ||
237 | ret = mc13xxx_rtc_irq_enable_unlocked(dev, alarm->enabled, | 237 | ret = mc13xxx_rtc_irq_enable_unlocked(dev, alarm->enabled, |
238 | MC13XXX_IRQ_TODA); | 238 | MC13XXX_IRQ_TODA); |
239 | if (unlikely(ret)) | 239 | if (unlikely(ret)) |
240 | goto out; | 240 | goto out; |
241 | 241 | ||
242 | seconds = s1970 % 86400; | 242 | seconds = s1970 % 86400; |
243 | days = s1970 / 86400; | 243 | days = s1970 / 86400; |
244 | 244 | ||
245 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAYA, days); | 245 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAYA, days); |
246 | if (unlikely(ret)) | 246 | if (unlikely(ret)) |
247 | goto out; | 247 | goto out; |
248 | 248 | ||
249 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, seconds); | 249 | ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, seconds); |
250 | 250 | ||
251 | out: | 251 | out: |
252 | mc13xxx_unlock(priv->mc13xxx); | 252 | mc13xxx_unlock(priv->mc13xxx); |
253 | 253 | ||
254 | return ret; | 254 | return ret; |
255 | } | 255 | } |
256 | 256 | ||
257 | static irqreturn_t mc13xxx_rtc_alarm_handler(int irq, void *dev) | 257 | static irqreturn_t mc13xxx_rtc_alarm_handler(int irq, void *dev) |
258 | { | 258 | { |
259 | struct mc13xxx_rtc *priv = dev; | 259 | struct mc13xxx_rtc *priv = dev; |
260 | struct mc13xxx *mc13xxx = priv->mc13xxx; | 260 | struct mc13xxx *mc13xxx = priv->mc13xxx; |
261 | 261 | ||
262 | dev_dbg(&priv->rtc->dev, "Alarm\n"); | 262 | dev_dbg(&priv->rtc->dev, "Alarm\n"); |
263 | 263 | ||
264 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF); | 264 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF); |
265 | 265 | ||
266 | mc13xxx_irq_ack(mc13xxx, irq); | 266 | mc13xxx_irq_ack(mc13xxx, irq); |
267 | 267 | ||
268 | return IRQ_HANDLED; | 268 | return IRQ_HANDLED; |
269 | } | 269 | } |
270 | 270 | ||
271 | static irqreturn_t mc13xxx_rtc_update_handler(int irq, void *dev) | 271 | static irqreturn_t mc13xxx_rtc_update_handler(int irq, void *dev) |
272 | { | 272 | { |
273 | struct mc13xxx_rtc *priv = dev; | 273 | struct mc13xxx_rtc *priv = dev; |
274 | struct mc13xxx *mc13xxx = priv->mc13xxx; | 274 | struct mc13xxx *mc13xxx = priv->mc13xxx; |
275 | 275 | ||
276 | dev_dbg(&priv->rtc->dev, "1HZ\n"); | 276 | dev_dbg(&priv->rtc->dev, "1HZ\n"); |
277 | 277 | ||
278 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF); | 278 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF); |
279 | 279 | ||
280 | mc13xxx_irq_ack(mc13xxx, irq); | 280 | mc13xxx_irq_ack(mc13xxx, irq); |
281 | 281 | ||
282 | return IRQ_HANDLED; | 282 | return IRQ_HANDLED; |
283 | } | 283 | } |
284 | 284 | ||
285 | static int mc13xxx_rtc_alarm_irq_enable(struct device *dev, | 285 | static int mc13xxx_rtc_alarm_irq_enable(struct device *dev, |
286 | unsigned int enabled) | 286 | unsigned int enabled) |
287 | { | 287 | { |
288 | return mc13xxx_rtc_irq_enable(dev, enabled, MC13XXX_IRQ_TODA); | 288 | return mc13xxx_rtc_irq_enable(dev, enabled, MC13XXX_IRQ_TODA); |
289 | } | 289 | } |
290 | 290 | ||
291 | static const struct rtc_class_ops mc13xxx_rtc_ops = { | 291 | static const struct rtc_class_ops mc13xxx_rtc_ops = { |
292 | .read_time = mc13xxx_rtc_read_time, | 292 | .read_time = mc13xxx_rtc_read_time, |
293 | .set_mmss = mc13xxx_rtc_set_mmss, | 293 | .set_mmss = mc13xxx_rtc_set_mmss, |
294 | .read_alarm = mc13xxx_rtc_read_alarm, | 294 | .read_alarm = mc13xxx_rtc_read_alarm, |
295 | .set_alarm = mc13xxx_rtc_set_alarm, | 295 | .set_alarm = mc13xxx_rtc_set_alarm, |
296 | .alarm_irq_enable = mc13xxx_rtc_alarm_irq_enable, | 296 | .alarm_irq_enable = mc13xxx_rtc_alarm_irq_enable, |
297 | }; | 297 | }; |
298 | 298 | ||
299 | static irqreturn_t mc13xxx_rtc_reset_handler(int irq, void *dev) | 299 | static irqreturn_t mc13xxx_rtc_reset_handler(int irq, void *dev) |
300 | { | 300 | { |
301 | struct mc13xxx_rtc *priv = dev; | 301 | struct mc13xxx_rtc *priv = dev; |
302 | struct mc13xxx *mc13xxx = priv->mc13xxx; | 302 | struct mc13xxx *mc13xxx = priv->mc13xxx; |
303 | 303 | ||
304 | dev_dbg(&priv->rtc->dev, "RTCRST\n"); | 304 | dev_dbg(&priv->rtc->dev, "RTCRST\n"); |
305 | priv->valid = 0; | 305 | priv->valid = 0; |
306 | 306 | ||
307 | mc13xxx_irq_mask(mc13xxx, irq); | 307 | mc13xxx_irq_mask(mc13xxx, irq); |
308 | 308 | ||
309 | return IRQ_HANDLED; | 309 | return IRQ_HANDLED; |
310 | } | 310 | } |
311 | 311 | ||
312 | static int __init mc13xxx_rtc_probe(struct platform_device *pdev) | 312 | static int __init mc13xxx_rtc_probe(struct platform_device *pdev) |
313 | { | 313 | { |
314 | int ret; | 314 | int ret; |
315 | struct mc13xxx_rtc *priv; | 315 | struct mc13xxx_rtc *priv; |
316 | struct mc13xxx *mc13xxx; | 316 | struct mc13xxx *mc13xxx; |
317 | int rtcrst_pending; | 317 | int rtcrst_pending; |
318 | 318 | ||
319 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 319 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
320 | if (!priv) | 320 | if (!priv) |
321 | return -ENOMEM; | 321 | return -ENOMEM; |
322 | 322 | ||
323 | mc13xxx = dev_get_drvdata(pdev->dev.parent); | 323 | mc13xxx = dev_get_drvdata(pdev->dev.parent); |
324 | priv->mc13xxx = mc13xxx; | 324 | priv->mc13xxx = mc13xxx; |
325 | 325 | ||
326 | platform_set_drvdata(pdev, priv); | 326 | platform_set_drvdata(pdev, priv); |
327 | 327 | ||
328 | mc13xxx_lock(mc13xxx); | 328 | mc13xxx_lock(mc13xxx); |
329 | 329 | ||
330 | ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_RTCRST, | 330 | ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_RTCRST, |
331 | mc13xxx_rtc_reset_handler, DRIVER_NAME, priv); | 331 | mc13xxx_rtc_reset_handler, DRIVER_NAME, priv); |
332 | if (ret) | 332 | if (ret) |
333 | goto err_reset_irq_request; | 333 | goto err_reset_irq_request; |
334 | 334 | ||
335 | ret = mc13xxx_irq_status(mc13xxx, MC13XXX_IRQ_RTCRST, | 335 | ret = mc13xxx_irq_status(mc13xxx, MC13XXX_IRQ_RTCRST, |
336 | NULL, &rtcrst_pending); | 336 | NULL, &rtcrst_pending); |
337 | if (ret) | 337 | if (ret) |
338 | goto err_reset_irq_status; | 338 | goto err_reset_irq_status; |
339 | 339 | ||
340 | priv->valid = !rtcrst_pending; | 340 | priv->valid = !rtcrst_pending; |
341 | 341 | ||
342 | ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_1HZ, | 342 | ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_1HZ, |
343 | mc13xxx_rtc_update_handler, DRIVER_NAME, priv); | 343 | mc13xxx_rtc_update_handler, DRIVER_NAME, priv); |
344 | if (ret) | 344 | if (ret) |
345 | goto err_update_irq_request; | 345 | goto err_update_irq_request; |
346 | 346 | ||
347 | ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_TODA, | 347 | ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_TODA, |
348 | mc13xxx_rtc_alarm_handler, DRIVER_NAME, priv); | 348 | mc13xxx_rtc_alarm_handler, DRIVER_NAME, priv); |
349 | if (ret) | 349 | if (ret) |
350 | goto err_alarm_irq_request; | 350 | goto err_alarm_irq_request; |
351 | 351 | ||
352 | mc13xxx_unlock(mc13xxx); | 352 | mc13xxx_unlock(mc13xxx); |
353 | 353 | ||
354 | priv->rtc = rtc_device_register(pdev->name, | 354 | priv->rtc = rtc_device_register(pdev->name, |
355 | &pdev->dev, &mc13xxx_rtc_ops, THIS_MODULE); | 355 | &pdev->dev, &mc13xxx_rtc_ops, THIS_MODULE); |
356 | if (IS_ERR(priv->rtc)) { | 356 | if (IS_ERR(priv->rtc)) { |
357 | ret = PTR_ERR(priv->rtc); | 357 | ret = PTR_ERR(priv->rtc); |
358 | 358 | ||
359 | mc13xxx_lock(mc13xxx); | 359 | mc13xxx_lock(mc13xxx); |
360 | 360 | ||
361 | mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_TODA, priv); | 361 | mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_TODA, priv); |
362 | err_alarm_irq_request: | 362 | err_alarm_irq_request: |
363 | 363 | ||
364 | mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_1HZ, priv); | 364 | mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_1HZ, priv); |
365 | err_update_irq_request: | 365 | err_update_irq_request: |
366 | 366 | ||
367 | err_reset_irq_status: | 367 | err_reset_irq_status: |
368 | 368 | ||
369 | mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv); | 369 | mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv); |
370 | err_reset_irq_request: | 370 | err_reset_irq_request: |
371 | 371 | ||
372 | mc13xxx_unlock(mc13xxx); | 372 | mc13xxx_unlock(mc13xxx); |
373 | 373 | ||
374 | platform_set_drvdata(pdev, NULL); | 374 | platform_set_drvdata(pdev, NULL); |
375 | kfree(priv); | 375 | kfree(priv); |
376 | } | 376 | } |
377 | 377 | ||
378 | return ret; | 378 | return ret; |
379 | } | 379 | } |
380 | 380 | ||
381 | static int __exit mc13xxx_rtc_remove(struct platform_device *pdev) | 381 | static int __exit mc13xxx_rtc_remove(struct platform_device *pdev) |
382 | { | 382 | { |
383 | struct mc13xxx_rtc *priv = platform_get_drvdata(pdev); | 383 | struct mc13xxx_rtc *priv = platform_get_drvdata(pdev); |
384 | 384 | ||
385 | mc13xxx_lock(priv->mc13xxx); | 385 | mc13xxx_lock(priv->mc13xxx); |
386 | 386 | ||
387 | rtc_device_unregister(priv->rtc); | 387 | rtc_device_unregister(priv->rtc); |
388 | 388 | ||
389 | mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TODA, priv); | 389 | mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TODA, priv); |
390 | mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_1HZ, priv); | 390 | mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_1HZ, priv); |
391 | mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_RTCRST, priv); | 391 | mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_RTCRST, priv); |
392 | 392 | ||
393 | mc13xxx_unlock(priv->mc13xxx); | 393 | mc13xxx_unlock(priv->mc13xxx); |
394 | 394 | ||
395 | platform_set_drvdata(pdev, NULL); | 395 | platform_set_drvdata(pdev, NULL); |
396 | 396 | ||
397 | kfree(priv); | 397 | kfree(priv); |
398 | 398 | ||
399 | return 0; | 399 | return 0; |
400 | } | 400 | } |
401 | 401 | ||
402 | const struct platform_device_id mc13xxx_rtc_idtable[] = { | 402 | static const struct platform_device_id mc13xxx_rtc_idtable[] = { |
403 | { | 403 | { |
404 | .name = "mc13783-rtc", | 404 | .name = "mc13783-rtc", |
405 | }, { | 405 | }, { |
406 | .name = "mc13892-rtc", | 406 | .name = "mc13892-rtc", |
407 | }, | 407 | }, |
408 | { } | 408 | { } |
409 | }; | 409 | }; |
410 | 410 | ||
411 | static struct platform_driver mc13xxx_rtc_driver = { | 411 | static struct platform_driver mc13xxx_rtc_driver = { |
412 | .id_table = mc13xxx_rtc_idtable, | 412 | .id_table = mc13xxx_rtc_idtable, |
413 | .remove = __exit_p(mc13xxx_rtc_remove), | 413 | .remove = __exit_p(mc13xxx_rtc_remove), |
414 | .driver = { | 414 | .driver = { |
415 | .name = DRIVER_NAME, | 415 | .name = DRIVER_NAME, |
416 | .owner = THIS_MODULE, | 416 | .owner = THIS_MODULE, |
417 | }, | 417 | }, |
418 | }; | 418 | }; |
419 | 419 | ||
420 | static int __init mc13xxx_rtc_init(void) | 420 | static int __init mc13xxx_rtc_init(void) |
421 | { | 421 | { |
422 | return platform_driver_probe(&mc13xxx_rtc_driver, &mc13xxx_rtc_probe); | 422 | return platform_driver_probe(&mc13xxx_rtc_driver, &mc13xxx_rtc_probe); |
423 | } | 423 | } |
424 | module_init(mc13xxx_rtc_init); | 424 | module_init(mc13xxx_rtc_init); |
425 | 425 | ||
426 | static void __exit mc13xxx_rtc_exit(void) | 426 | static void __exit mc13xxx_rtc_exit(void) |
427 | { | 427 | { |
428 | platform_driver_unregister(&mc13xxx_rtc_driver); | 428 | platform_driver_unregister(&mc13xxx_rtc_driver); |
429 | } | 429 | } |
430 | module_exit(mc13xxx_rtc_exit); | 430 | module_exit(mc13xxx_rtc_exit); |
431 | 431 | ||
432 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); | 432 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); |
433 | MODULE_DESCRIPTION("RTC driver for Freescale MC13XXX PMIC"); | 433 | MODULE_DESCRIPTION("RTC driver for Freescale MC13XXX PMIC"); |
434 | MODULE_LICENSE("GPL v2"); | 434 | MODULE_LICENSE("GPL v2"); |
435 | MODULE_ALIAS("platform:" DRIVER_NAME); | 435 | MODULE_ALIAS("platform:" DRIVER_NAME); |
436 | 436 |