diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2008-08-07 04:55:03 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-08-07 04:55:03 -0400 |
commit | 4fb8af10d0fd09372d52966b76922b9e82bbc950 (patch) | |
tree | d240e4d40357583e3f3eb228dccf20122a5b31ed /drivers/rtc | |
parent | f44f82e8a20b98558486eb14497b2f71c78fa325 (diff) | |
parent | 64a99d2a8c3ed5c4e39f3ae1cc682aa8fd3977fc (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-fixes
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/interface.c | 10 | ||||
-rw-r--r-- | drivers/rtc/rtc-bfin.c | 105 | ||||
-rw-r--r-- | drivers/rtc/rtc-dev.c | 4 |
3 files changed, 63 insertions, 56 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index d397fa5f3a91..7af60b98d8a4 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
@@ -20,7 +20,7 @@ int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) | |||
20 | 20 | ||
21 | err = mutex_lock_interruptible(&rtc->ops_lock); | 21 | err = mutex_lock_interruptible(&rtc->ops_lock); |
22 | if (err) | 22 | if (err) |
23 | return -EBUSY; | 23 | return err; |
24 | 24 | ||
25 | if (!rtc->ops) | 25 | if (!rtc->ops) |
26 | err = -ENODEV; | 26 | err = -ENODEV; |
@@ -46,7 +46,7 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) | |||
46 | 46 | ||
47 | err = mutex_lock_interruptible(&rtc->ops_lock); | 47 | err = mutex_lock_interruptible(&rtc->ops_lock); |
48 | if (err) | 48 | if (err) |
49 | return -EBUSY; | 49 | return err; |
50 | 50 | ||
51 | if (!rtc->ops) | 51 | if (!rtc->ops) |
52 | err = -ENODEV; | 52 | err = -ENODEV; |
@@ -66,7 +66,7 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs) | |||
66 | 66 | ||
67 | err = mutex_lock_interruptible(&rtc->ops_lock); | 67 | err = mutex_lock_interruptible(&rtc->ops_lock); |
68 | if (err) | 68 | if (err) |
69 | return -EBUSY; | 69 | return err; |
70 | 70 | ||
71 | if (!rtc->ops) | 71 | if (!rtc->ops) |
72 | err = -ENODEV; | 72 | err = -ENODEV; |
@@ -106,7 +106,7 @@ static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *al | |||
106 | 106 | ||
107 | err = mutex_lock_interruptible(&rtc->ops_lock); | 107 | err = mutex_lock_interruptible(&rtc->ops_lock); |
108 | if (err) | 108 | if (err) |
109 | return -EBUSY; | 109 | return err; |
110 | 110 | ||
111 | if (rtc->ops == NULL) | 111 | if (rtc->ops == NULL) |
112 | err = -ENODEV; | 112 | err = -ENODEV; |
@@ -293,7 +293,7 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
293 | 293 | ||
294 | err = mutex_lock_interruptible(&rtc->ops_lock); | 294 | err = mutex_lock_interruptible(&rtc->ops_lock); |
295 | if (err) | 295 | if (err) |
296 | return -EBUSY; | 296 | return err; |
297 | 297 | ||
298 | if (!rtc->ops) | 298 | if (!rtc->ops) |
299 | err = -ENODEV; | 299 | err = -ENODEV; |
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 8624f55d0560..a1af4c27939b 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Blackfin On-Chip Real Time Clock Driver | 2 | * Blackfin On-Chip Real Time Clock Driver |
3 | * Supports BF52[257]/BF53[123]/BF53[467]/BF54[24789] | 3 | * Supports BF52[257]/BF53[123]/BF53[467]/BF54[24789] |
4 | * | 4 | * |
5 | * Copyright 2004-2007 Analog Devices Inc. | 5 | * Copyright 2004-2008 Analog Devices Inc. |
6 | * | 6 | * |
7 | * Enter bugs at http://blackfin.uclinux.org/ | 7 | * Enter bugs at http://blackfin.uclinux.org/ |
8 | * | 8 | * |
@@ -32,6 +32,15 @@ | |||
32 | * writes to clear status registers complete immediately. | 32 | * writes to clear status registers complete immediately. |
33 | */ | 33 | */ |
34 | 34 | ||
35 | /* It may seem odd that there is no SWCNT code in here (which would be exposed | ||
36 | * via the periodic interrupt event, or PIE). Since the Blackfin RTC peripheral | ||
37 | * runs in units of seconds (N/HZ) but the Linux framework runs in units of HZ | ||
38 | * (2^N HZ), there is no point in keeping code that only provides 1 HZ PIEs. | ||
39 | * The same exact behavior can be accomplished by using the update interrupt | ||
40 | * event (UIE). Maybe down the line the RTC peripheral will suck less in which | ||
41 | * case we can re-introduce PIE support. | ||
42 | */ | ||
43 | |||
35 | #include <linux/bcd.h> | 44 | #include <linux/bcd.h> |
36 | #include <linux/completion.h> | 45 | #include <linux/completion.h> |
37 | #include <linux/delay.h> | 46 | #include <linux/delay.h> |
@@ -144,14 +153,13 @@ static void bfin_rtc_sync_pending(struct device *dev) | |||
144 | * Initialize the RTC. Enable pre-scaler to scale RTC clock | 153 | * Initialize the RTC. Enable pre-scaler to scale RTC clock |
145 | * to 1Hz and clear interrupt/status registers. | 154 | * to 1Hz and clear interrupt/status registers. |
146 | */ | 155 | */ |
147 | static void bfin_rtc_reset(struct device *dev) | 156 | static void bfin_rtc_reset(struct device *dev, u16 rtc_ictl) |
148 | { | 157 | { |
149 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 158 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
150 | dev_dbg_stamp(dev); | 159 | dev_dbg_stamp(dev); |
151 | bfin_rtc_sync_pending(dev); | 160 | bfin_rtc_sync_pending(dev); |
152 | bfin_write_RTC_PREN(0x1); | 161 | bfin_write_RTC_PREN(0x1); |
153 | bfin_write_RTC_ICTL(RTC_ISTAT_WRITE_COMPLETE); | 162 | bfin_write_RTC_ICTL(rtc_ictl); |
154 | bfin_write_RTC_SWCNT(0); | ||
155 | bfin_write_RTC_ALARM(0); | 163 | bfin_write_RTC_ALARM(0); |
156 | bfin_write_RTC_ISTAT(0xFFFF); | 164 | bfin_write_RTC_ISTAT(0xFFFF); |
157 | rtc->rtc_wrote_regs = 0; | 165 | rtc->rtc_wrote_regs = 0; |
@@ -194,14 +202,6 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) | |||
194 | } | 202 | } |
195 | } | 203 | } |
196 | 204 | ||
197 | if (rtc_ictl & RTC_ISTAT_STOPWATCH) { | ||
198 | if (rtc_istat & RTC_ISTAT_STOPWATCH) { | ||
199 | bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH); | ||
200 | events |= RTC_PF | RTC_IRQF; | ||
201 | bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | if (rtc_ictl & RTC_ISTAT_SEC) { | 205 | if (rtc_ictl & RTC_ISTAT_SEC) { |
206 | if (rtc_istat & RTC_ISTAT_SEC) { | 206 | if (rtc_istat & RTC_ISTAT_SEC) { |
207 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); | 207 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); |
@@ -226,7 +226,7 @@ static int bfin_rtc_open(struct device *dev) | |||
226 | 226 | ||
227 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, to_platform_device(dev)->name, dev); | 227 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, to_platform_device(dev)->name, dev); |
228 | if (!ret) | 228 | if (!ret) |
229 | bfin_rtc_reset(dev); | 229 | bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); |
230 | 230 | ||
231 | return ret; | 231 | return ret; |
232 | } | 232 | } |
@@ -234,16 +234,16 @@ static int bfin_rtc_open(struct device *dev) | |||
234 | static void bfin_rtc_release(struct device *dev) | 234 | static void bfin_rtc_release(struct device *dev) |
235 | { | 235 | { |
236 | dev_dbg_stamp(dev); | 236 | dev_dbg_stamp(dev); |
237 | bfin_rtc_reset(dev); | 237 | bfin_rtc_reset(dev, 0); |
238 | free_irq(IRQ_RTC, dev); | 238 | free_irq(IRQ_RTC, dev); |
239 | } | 239 | } |
240 | 240 | ||
241 | static void bfin_rtc_int_set(struct bfin_rtc *rtc, u16 rtc_int) | 241 | static void bfin_rtc_int_set(u16 rtc_int) |
242 | { | 242 | { |
243 | bfin_write_RTC_ISTAT(rtc_int); | 243 | bfin_write_RTC_ISTAT(rtc_int); |
244 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | rtc_int); | 244 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | rtc_int); |
245 | } | 245 | } |
246 | static void bfin_rtc_int_clear(struct bfin_rtc *rtc, u16 rtc_int) | 246 | static void bfin_rtc_int_clear(u16 rtc_int) |
247 | { | 247 | { |
248 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & rtc_int); | 248 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & rtc_int); |
249 | } | 249 | } |
@@ -252,7 +252,7 @@ static void bfin_rtc_int_set_alarm(struct bfin_rtc *rtc) | |||
252 | /* Blackfin has different bits for whether the alarm is | 252 | /* Blackfin has different bits for whether the alarm is |
253 | * more than 24 hours away. | 253 | * more than 24 hours away. |
254 | */ | 254 | */ |
255 | bfin_rtc_int_set(rtc, (rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY)); | 255 | bfin_rtc_int_set(rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY); |
256 | } | 256 | } |
257 | static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 257 | static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
258 | { | 258 | { |
@@ -264,23 +264,13 @@ static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long ar | |||
264 | bfin_rtc_sync_pending(dev); | 264 | bfin_rtc_sync_pending(dev); |
265 | 265 | ||
266 | switch (cmd) { | 266 | switch (cmd) { |
267 | case RTC_PIE_ON: | ||
268 | dev_dbg_stamp(dev); | ||
269 | bfin_rtc_int_set(rtc, RTC_ISTAT_STOPWATCH); | ||
270 | bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); | ||
271 | break; | ||
272 | case RTC_PIE_OFF: | ||
273 | dev_dbg_stamp(dev); | ||
274 | bfin_rtc_int_clear(rtc, ~RTC_ISTAT_STOPWATCH); | ||
275 | break; | ||
276 | |||
277 | case RTC_UIE_ON: | 267 | case RTC_UIE_ON: |
278 | dev_dbg_stamp(dev); | 268 | dev_dbg_stamp(dev); |
279 | bfin_rtc_int_set(rtc, RTC_ISTAT_SEC); | 269 | bfin_rtc_int_set(RTC_ISTAT_SEC); |
280 | break; | 270 | break; |
281 | case RTC_UIE_OFF: | 271 | case RTC_UIE_OFF: |
282 | dev_dbg_stamp(dev); | 272 | dev_dbg_stamp(dev); |
283 | bfin_rtc_int_clear(rtc, ~RTC_ISTAT_SEC); | 273 | bfin_rtc_int_clear(~RTC_ISTAT_SEC); |
284 | break; | 274 | break; |
285 | 275 | ||
286 | case RTC_AIE_ON: | 276 | case RTC_AIE_ON: |
@@ -289,7 +279,7 @@ static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long ar | |||
289 | break; | 279 | break; |
290 | case RTC_AIE_OFF: | 280 | case RTC_AIE_OFF: |
291 | dev_dbg_stamp(dev); | 281 | dev_dbg_stamp(dev); |
292 | bfin_rtc_int_clear(rtc, ~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); | 282 | bfin_rtc_int_clear(~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); |
293 | break; | 283 | break; |
294 | 284 | ||
295 | default: | 285 | default: |
@@ -371,30 +361,14 @@ static int bfin_rtc_proc(struct device *dev, struct seq_file *seq) | |||
371 | seq_printf(seq, | 361 | seq_printf(seq, |
372 | "alarm_IRQ\t: %s\n" | 362 | "alarm_IRQ\t: %s\n" |
373 | "wkalarm_IRQ\t: %s\n" | 363 | "wkalarm_IRQ\t: %s\n" |
374 | "seconds_IRQ\t: %s\n" | 364 | "seconds_IRQ\t: %s\n", |
375 | "periodic_IRQ\t: %s\n", | ||
376 | yesno(ictl & RTC_ISTAT_ALARM), | 365 | yesno(ictl & RTC_ISTAT_ALARM), |
377 | yesno(ictl & RTC_ISTAT_ALARM_DAY), | 366 | yesno(ictl & RTC_ISTAT_ALARM_DAY), |
378 | yesno(ictl & RTC_ISTAT_SEC), | 367 | yesno(ictl & RTC_ISTAT_SEC)); |
379 | yesno(ictl & RTC_ISTAT_STOPWATCH)); | ||
380 | return 0; | 368 | return 0; |
381 | #undef yesno | 369 | #undef yesno |
382 | } | 370 | } |
383 | 371 | ||
384 | /** | ||
385 | * bfin_irq_set_freq - make sure hardware supports requested freq | ||
386 | * @dev: pointer to RTC device structure | ||
387 | * @freq: requested frequency rate | ||
388 | * | ||
389 | * The Blackfin RTC can only generate periodic events at 1 per | ||
390 | * second (1 Hz), so reject any attempt at changing it. | ||
391 | */ | ||
392 | static int bfin_irq_set_freq(struct device *dev, int freq) | ||
393 | { | ||
394 | dev_dbg_stamp(dev); | ||
395 | return -ENOTTY; | ||
396 | } | ||
397 | |||
398 | static struct rtc_class_ops bfin_rtc_ops = { | 372 | static struct rtc_class_ops bfin_rtc_ops = { |
399 | .open = bfin_rtc_open, | 373 | .open = bfin_rtc_open, |
400 | .release = bfin_rtc_release, | 374 | .release = bfin_rtc_release, |
@@ -404,7 +378,6 @@ static struct rtc_class_ops bfin_rtc_ops = { | |||
404 | .read_alarm = bfin_rtc_read_alarm, | 378 | .read_alarm = bfin_rtc_read_alarm, |
405 | .set_alarm = bfin_rtc_set_alarm, | 379 | .set_alarm = bfin_rtc_set_alarm, |
406 | .proc = bfin_rtc_proc, | 380 | .proc = bfin_rtc_proc, |
407 | .irq_set_freq = bfin_irq_set_freq, | ||
408 | }; | 381 | }; |
409 | 382 | ||
410 | static int __devinit bfin_rtc_probe(struct platform_device *pdev) | 383 | static int __devinit bfin_rtc_probe(struct platform_device *pdev) |
@@ -423,10 +396,14 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) | |||
423 | ret = PTR_ERR(rtc->rtc_dev); | 396 | ret = PTR_ERR(rtc->rtc_dev); |
424 | goto err; | 397 | goto err; |
425 | } | 398 | } |
426 | rtc->rtc_dev->irq_freq = 1; | 399 | |
400 | /* see comment at top of file about stopwatch/PIE */ | ||
401 | bfin_write_RTC_SWCNT(0); | ||
427 | 402 | ||
428 | platform_set_drvdata(pdev, rtc); | 403 | platform_set_drvdata(pdev, rtc); |
429 | 404 | ||
405 | device_init_wakeup(&pdev->dev, 1); | ||
406 | |||
430 | return 0; | 407 | return 0; |
431 | 408 | ||
432 | err: | 409 | err: |
@@ -445,6 +422,32 @@ static int __devexit bfin_rtc_remove(struct platform_device *pdev) | |||
445 | return 0; | 422 | return 0; |
446 | } | 423 | } |
447 | 424 | ||
425 | #ifdef CONFIG_PM | ||
426 | static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) | ||
427 | { | ||
428 | if (device_may_wakeup(&pdev->dev)) { | ||
429 | enable_irq_wake(IRQ_RTC); | ||
430 | bfin_rtc_sync_pending(&pdev->dev); | ||
431 | } else | ||
432 | bfin_rtc_int_clear(-1); | ||
433 | |||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | static int bfin_rtc_resume(struct platform_device *pdev) | ||
438 | { | ||
439 | if (device_may_wakeup(&pdev->dev)) | ||
440 | disable_irq_wake(IRQ_RTC); | ||
441 | else | ||
442 | bfin_write_RTC_ISTAT(-1); | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | #else | ||
447 | # define bfin_rtc_suspend NULL | ||
448 | # define bfin_rtc_resume NULL | ||
449 | #endif | ||
450 | |||
448 | static struct platform_driver bfin_rtc_driver = { | 451 | static struct platform_driver bfin_rtc_driver = { |
449 | .driver = { | 452 | .driver = { |
450 | .name = "rtc-bfin", | 453 | .name = "rtc-bfin", |
@@ -452,6 +455,8 @@ static struct platform_driver bfin_rtc_driver = { | |||
452 | }, | 455 | }, |
453 | .probe = bfin_rtc_probe, | 456 | .probe = bfin_rtc_probe, |
454 | .remove = __devexit_p(bfin_rtc_remove), | 457 | .remove = __devexit_p(bfin_rtc_remove), |
458 | .suspend = bfin_rtc_suspend, | ||
459 | .resume = bfin_rtc_resume, | ||
455 | }; | 460 | }; |
456 | 461 | ||
457 | static int __init bfin_rtc_init(void) | 462 | static int __init bfin_rtc_init(void) |
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 0a870b7e5c32..856cc1af40df 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
@@ -221,7 +221,7 @@ static long rtc_dev_ioctl(struct file *file, | |||
221 | 221 | ||
222 | err = mutex_lock_interruptible(&rtc->ops_lock); | 222 | err = mutex_lock_interruptible(&rtc->ops_lock); |
223 | if (err) | 223 | if (err) |
224 | return -EBUSY; | 224 | return err; |
225 | 225 | ||
226 | /* check that the calling task has appropriate permissions | 226 | /* check that the calling task has appropriate permissions |
227 | * for certain ioctls. doing this check here is useful | 227 | * for certain ioctls. doing this check here is useful |
@@ -432,6 +432,8 @@ static int rtc_dev_release(struct inode *inode, struct file *file) | |||
432 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | 432 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL |
433 | clear_uie(rtc); | 433 | clear_uie(rtc); |
434 | #endif | 434 | #endif |
435 | rtc_irq_set_state(rtc, NULL, 0); | ||
436 | |||
435 | if (rtc->ops->release) | 437 | if (rtc->ops->release) |
436 | rtc->ops->release(rtc->dev.parent); | 438 | rtc->ops->release(rtc->dev.parent); |
437 | 439 | ||