aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-mc13783.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-mc13783.c')
-rw-r--r--drivers/rtc/rtc-mc13783.c230
1 files changed, 198 insertions, 32 deletions
diff --git a/drivers/rtc/rtc-mc13783.c b/drivers/rtc/rtc-mc13783.c
index 850f983c039c..675bfb515367 100644
--- a/drivers/rtc/rtc-mc13783.c
+++ b/drivers/rtc/rtc-mc13783.c
@@ -13,6 +13,7 @@
13#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/slab.h>
16#include <linux/rtc.h> 17#include <linux/rtc.h>
17 18
18#define DRIVER_NAME "mc13783-rtc" 19#define DRIVER_NAME "mc13783-rtc"
@@ -28,6 +29,34 @@ struct mc13783_rtc {
28 int valid; 29 int valid;
29}; 30};
30 31
32static int mc13783_rtc_irq_enable_unlocked(struct device *dev,
33 unsigned int enabled, int irq)
34{
35 struct mc13783_rtc *priv = dev_get_drvdata(dev);
36 int (*func)(struct mc13783 *mc13783, int irq);
37
38 if (!priv->valid)
39 return -ENODATA;
40
41 func = enabled ? mc13783_irq_unmask : mc13783_irq_mask;
42 return func(priv->mc13783, irq);
43}
44
45static int mc13783_rtc_irq_enable(struct device *dev,
46 unsigned int enabled, int irq)
47{
48 struct mc13783_rtc *priv = dev_get_drvdata(dev);
49 int ret;
50
51 mc13783_lock(priv->mc13783);
52
53 ret = mc13783_rtc_irq_enable_unlocked(dev, enabled, irq);
54
55 mc13783_unlock(priv->mc13783);
56
57 return ret;
58}
59
31static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm) 60static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm)
32{ 61{
33 struct mc13783_rtc *priv = dev_get_drvdata(dev); 62 struct mc13783_rtc *priv = dev_get_drvdata(dev);
@@ -78,6 +107,7 @@ static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs)
78{ 107{
79 struct mc13783_rtc *priv = dev_get_drvdata(dev); 108 struct mc13783_rtc *priv = dev_get_drvdata(dev);
80 unsigned int seconds, days; 109 unsigned int seconds, days;
110 unsigned int alarmseconds;
81 int ret; 111 int ret;
82 112
83 seconds = secs % 86400; 113 seconds = secs % 86400;
@@ -86,7 +116,22 @@ static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs)
86 mc13783_lock(priv->mc13783); 116 mc13783_lock(priv->mc13783);
87 117
88 /* 118 /*
89 * first write seconds=0 to prevent a day switch between writing days 119 * temporarily invalidate alarm to prevent triggering it when the day is
120 * already updated while the time isn't yet.
121 */
122 ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTODA, &alarmseconds);
123 if (unlikely(ret))
124 goto out;
125
126 if (alarmseconds < 86400) {
127 ret = mc13783_reg_write(priv->mc13783,
128 MC13783_RTCTODA, 0x1ffff);
129 if (unlikely(ret))
130 goto out;
131 }
132
133 /*
134 * write seconds=0 to prevent a day switch between writing days
90 * and seconds below 135 * and seconds below
91 */ 136 */
92 ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, 0); 137 ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, 0);
@@ -101,11 +146,19 @@ static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs)
101 if (unlikely(ret)) 146 if (unlikely(ret))
102 goto out; 147 goto out;
103 148
104 ret = mc13783_ackirq(priv->mc13783, MC13783_IRQ_RTCRST); 149 /* restore alarm */
150 if (alarmseconds < 86400) {
151 ret = mc13783_reg_write(priv->mc13783,
152 MC13783_RTCTODA, alarmseconds);
153 if (unlikely(ret))
154 goto out;
155 }
156
157 ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_RTCRST);
105 if (unlikely(ret)) 158 if (unlikely(ret))
106 goto out; 159 goto out;
107 160
108 ret = mc13783_unmask(priv->mc13783, MC13783_IRQ_RTCRST); 161 ret = mc13783_irq_unmask(priv->mc13783, MC13783_IRQ_RTCRST);
109out: 162out:
110 priv->valid = !ret; 163 priv->valid = !ret;
111 164
@@ -114,41 +167,139 @@ out:
114 return ret; 167 return ret;
115} 168}
116 169
117static irqreturn_t mc13783_rtc_update_handler(int irq, void *dev) 170static int mc13783_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
118{ 171{
119 struct mc13783_rtc *priv = dev; 172 struct mc13783_rtc *priv = dev_get_drvdata(dev);
120 struct mc13783 *mc13783 = priv->mc13783; 173 unsigned seconds, days;
174 unsigned long s1970;
175 int enabled, pending;
176 int ret;
121 177
122 dev_dbg(&priv->rtc->dev, "1HZ\n"); 178 mc13783_lock(priv->mc13783);
123 179
124 rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF); 180 ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTODA, &seconds);
181 if (unlikely(ret))
182 goto out;
183 if (seconds >= 86400) {
184 ret = -ENODATA;
185 goto out;
186 }
187
188 ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days);
189 if (unlikely(ret))
190 goto out;
125 191
126 mc13783_ackirq(mc13783, irq); 192 ret = mc13783_irq_status(priv->mc13783, MC13783_IRQ_TODA,
193 &enabled, &pending);
127 194
128 return IRQ_HANDLED; 195out:
196 mc13783_unlock(priv->mc13783);
197
198 if (ret)
199 return ret;
200
201 alarm->enabled = enabled;
202 alarm->pending = pending;
203
204 s1970 = days * 86400 + seconds;
205
206 rtc_time_to_tm(s1970, &alarm->time);
207 dev_dbg(dev, "%s: %lu\n", __func__, s1970);
208
209 return 0;
129} 210}
130 211
131static int mc13783_rtc_update_irq_enable(struct device *dev, 212static int mc13783_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
132 unsigned int enabled)
133{ 213{
134 struct mc13783_rtc *priv = dev_get_drvdata(dev); 214 struct mc13783_rtc *priv = dev_get_drvdata(dev);
135 int ret = -ENODATA; 215 unsigned long s1970;
216 unsigned seconds, days;
217 int ret;
136 218
137 mc13783_lock(priv->mc13783); 219 mc13783_lock(priv->mc13783);
138 if (!priv->valid) 220
221 /* disable alarm to prevent false triggering */
222 ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, 0x1ffff);
223 if (unlikely(ret))
139 goto out; 224 goto out;
140 225
141 ret = (enabled ? mc13783_unmask : mc13783_mask)(priv->mc13783, 226 ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TODA);
142 MC13783_IRQ_1HZ); 227 if (unlikely(ret))
228 goto out;
229
230 ret = rtc_tm_to_time(&alarm->time, &s1970);
231 if (unlikely(ret))
232 goto out;
233
234 dev_dbg(dev, "%s: o%2.s %lu\n", __func__, alarm->enabled ? "n" : "ff",
235 s1970);
236
237 ret = mc13783_rtc_irq_enable_unlocked(dev, alarm->enabled,
238 MC13783_IRQ_TODA);
239 if (unlikely(ret))
240 goto out;
241
242 seconds = s1970 % 86400;
243 days = s1970 / 86400;
244
245 ret = mc13783_reg_write(priv->mc13783, MC13783_RTCDAYA, days);
246 if (unlikely(ret))
247 goto out;
248
249 ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, seconds);
250
143out: 251out:
144 mc13783_unlock(priv->mc13783); 252 mc13783_unlock(priv->mc13783);
145 253
146 return ret; 254 return ret;
147} 255}
148 256
257static irqreturn_t mc13783_rtc_alarm_handler(int irq, void *dev)
258{
259 struct mc13783_rtc *priv = dev;
260 struct mc13783 *mc13783 = priv->mc13783;
261
262 dev_dbg(&priv->rtc->dev, "Alarm\n");
263
264 rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF);
265
266 mc13783_irq_ack(mc13783, irq);
267
268 return IRQ_HANDLED;
269}
270
271static irqreturn_t mc13783_rtc_update_handler(int irq, void *dev)
272{
273 struct mc13783_rtc *priv = dev;
274 struct mc13783 *mc13783 = priv->mc13783;
275
276 dev_dbg(&priv->rtc->dev, "1HZ\n");
277
278 rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF);
279
280 mc13783_irq_ack(mc13783, irq);
281
282 return IRQ_HANDLED;
283}
284
285static int mc13783_rtc_update_irq_enable(struct device *dev,
286 unsigned int enabled)
287{
288 return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_1HZ);
289}
290
291static int mc13783_rtc_alarm_irq_enable(struct device *dev,
292 unsigned int enabled)
293{
294 return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_TODA);
295}
296
149static const struct rtc_class_ops mc13783_rtc_ops = { 297static const struct rtc_class_ops mc13783_rtc_ops = {
150 .read_time = mc13783_rtc_read_time, 298 .read_time = mc13783_rtc_read_time,
151 .set_mmss = mc13783_rtc_set_mmss, 299 .set_mmss = mc13783_rtc_set_mmss,
300 .read_alarm = mc13783_rtc_read_alarm,
301 .set_alarm = mc13783_rtc_set_alarm,
302 .alarm_irq_enable = mc13783_rtc_alarm_irq_enable,
152 .update_irq_enable = mc13783_rtc_update_irq_enable, 303 .update_irq_enable = mc13783_rtc_update_irq_enable,
153}; 304};
154 305
@@ -160,7 +311,7 @@ static irqreturn_t mc13783_rtc_reset_handler(int irq, void *dev)
160 dev_dbg(&priv->rtc->dev, "RTCRST\n"); 311 dev_dbg(&priv->rtc->dev, "RTCRST\n");
161 priv->valid = 0; 312 priv->valid = 0;
162 313
163 mc13783_mask(mc13783, irq); 314 mc13783_irq_mask(mc13783, irq);
164 315
165 return IRQ_HANDLED; 316 return IRQ_HANDLED;
166} 317}
@@ -169,50 +320,64 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev)
169{ 320{
170 int ret; 321 int ret;
171 struct mc13783_rtc *priv; 322 struct mc13783_rtc *priv;
323 struct mc13783 *mc13783;
324 int rtcrst_pending;
172 325
173 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 326 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
174 if (!priv) 327 if (!priv)
175 return -ENOMEM; 328 return -ENOMEM;
176 329
177 priv->mc13783 = dev_get_drvdata(pdev->dev.parent); 330 mc13783 = dev_get_drvdata(pdev->dev.parent);
178 platform_set_drvdata(pdev, priv); 331 priv->mc13783 = mc13783;
179 332
180 priv->valid = 1; 333 platform_set_drvdata(pdev, priv);
181 334
182 mc13783_lock(priv->mc13783); 335 mc13783_lock(mc13783);
183 336
184 ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_RTCRST, 337 ret = mc13783_irq_request(mc13783, MC13783_IRQ_RTCRST,
185 mc13783_rtc_reset_handler, DRIVER_NAME, priv); 338 mc13783_rtc_reset_handler, DRIVER_NAME, priv);
186 if (ret) 339 if (ret)
187 goto err_reset_irq_request; 340 goto err_reset_irq_request;
188 341
189 ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_1HZ, 342 ret = mc13783_irq_status(mc13783, MC13783_IRQ_RTCRST,
343 NULL, &rtcrst_pending);
344 if (ret)
345 goto err_reset_irq_status;
346
347 priv->valid = !rtcrst_pending;
348
349 ret = mc13783_irq_request_nounmask(mc13783, MC13783_IRQ_1HZ,
190 mc13783_rtc_update_handler, DRIVER_NAME, priv); 350 mc13783_rtc_update_handler, DRIVER_NAME, priv);
191 if (ret) 351 if (ret)
192 goto err_update_irq_request; 352 goto err_update_irq_request;
193 353
194 mc13783_unlock(priv->mc13783); 354 ret = mc13783_irq_request_nounmask(mc13783, MC13783_IRQ_TODA,
355 mc13783_rtc_alarm_handler, DRIVER_NAME, priv);
356 if (ret)
357 goto err_alarm_irq_request;
195 358
196 priv->rtc = rtc_device_register(pdev->name, 359 priv->rtc = rtc_device_register(pdev->name,
197 &pdev->dev, &mc13783_rtc_ops, THIS_MODULE); 360 &pdev->dev, &mc13783_rtc_ops, THIS_MODULE);
198
199 if (IS_ERR(priv->rtc)) { 361 if (IS_ERR(priv->rtc)) {
200 ret = PTR_ERR(priv->rtc); 362 ret = PTR_ERR(priv->rtc);
201 363
202 mc13783_lock(priv->mc13783); 364 mc13783_irq_free(mc13783, MC13783_IRQ_TODA, priv);
365err_alarm_irq_request:
203 366
204 mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); 367 mc13783_irq_free(mc13783, MC13783_IRQ_1HZ, priv);
205err_update_irq_request: 368err_update_irq_request:
206 369
207 mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); 370err_reset_irq_status:
208err_reset_irq_request:
209 371
210 mc13783_unlock(priv->mc13783); 372 mc13783_irq_free(mc13783, MC13783_IRQ_RTCRST, priv);
373err_reset_irq_request:
211 374
212 platform_set_drvdata(pdev, NULL); 375 platform_set_drvdata(pdev, NULL);
213 kfree(priv); 376 kfree(priv);
214 } 377 }
215 378
379 mc13783_unlock(mc13783);
380
216 return ret; 381 return ret;
217} 382}
218 383
@@ -220,10 +385,11 @@ static int __devexit mc13783_rtc_remove(struct platform_device *pdev)
220{ 385{
221 struct mc13783_rtc *priv = platform_get_drvdata(pdev); 386 struct mc13783_rtc *priv = platform_get_drvdata(pdev);
222 387
223 rtc_device_unregister(priv->rtc);
224
225 mc13783_lock(priv->mc13783); 388 mc13783_lock(priv->mc13783);
226 389
390 rtc_device_unregister(priv->rtc);
391
392 mc13783_irq_free(priv->mc13783, MC13783_IRQ_TODA, priv);
227 mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); 393 mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv);
228 mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); 394 mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv);
229 395