diff options
author | Christopher Kenna <cjk@cs.unc.edu> | 2012-09-20 13:33:17 -0400 |
---|---|---|
committer | Christopher Kenna <cjk@cs.unc.edu> | 2012-09-20 13:33:17 -0400 |
commit | 5e0a4919ccb230ab449826ef91bdf38a4ed283e5 (patch) | |
tree | 3790db1aa69ed50b08f34c21c1796785df6a0304 /drivers/rtc | |
parent | c00613f1fad38acec00ef2c009ae4e73110084ac (diff) | |
parent | 5dd038629bdedef22d5ecad2d5e75ad81f4dc694 (diff) |
Merge remote-tracking branch 'oneiric-ubuntu/pandaboard' into pandaboard-litmus
Remote branch is from Ubuntu Oneiric (tag Ubuntu-3.0.0-1215.27) with
minor patch to the TWL-RTC code. Trying to pull this into LITMUS^RT
staging (as of 9/20/2012) to get LITMUS^RT running on the PandaBoard.
Conflicts:
Makefile
fs/exec.c
include/linux/fs.h
kernel/fork.c
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/interface.c | 74 | ||||
-rw-r--r-- | drivers/rtc/rtc-m41t80.c | 9 | ||||
-rw-r--r-- | drivers/rtc/rtc-mxc.c | 5 | ||||
-rw-r--r-- | drivers/rtc/rtc-pl031.c | 21 | ||||
-rw-r--r-- | drivers/rtc/rtc-tegra.c | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-twl.c | 14 |
6 files changed, 88 insertions, 37 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index df68618f6db..636a2ec2181 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 unconditionally cancel the timer here, 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); |
@@ -741,6 +762,14 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) | |||
741 | return 0; | 762 | return 0; |
742 | } | 763 | } |
743 | 764 | ||
765 | static void rtc_alarm_disable(struct rtc_device *rtc) | ||
766 | { | ||
767 | if (!rtc->ops || !rtc->ops->alarm_irq_enable) | ||
768 | return; | ||
769 | |||
770 | rtc->ops->alarm_irq_enable(rtc->dev.parent, false); | ||
771 | } | ||
772 | |||
744 | /** | 773 | /** |
745 | * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue | 774 | * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue |
746 | * @rtc rtc device | 775 | * @rtc rtc device |
@@ -762,8 +791,10 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) | |||
762 | struct rtc_wkalrm alarm; | 791 | struct rtc_wkalrm alarm; |
763 | int err; | 792 | int err; |
764 | next = timerqueue_getnext(&rtc->timerqueue); | 793 | next = timerqueue_getnext(&rtc->timerqueue); |
765 | if (!next) | 794 | if (!next) { |
795 | rtc_alarm_disable(rtc); | ||
766 | return; | 796 | return; |
797 | } | ||
767 | alarm.time = rtc_ktime_to_tm(next->expires); | 798 | alarm.time = rtc_ktime_to_tm(next->expires); |
768 | alarm.enabled = 1; | 799 | alarm.enabled = 1; |
769 | err = __rtc_set_alarm(rtc, &alarm); | 800 | err = __rtc_set_alarm(rtc, &alarm); |
@@ -825,7 +856,8 @@ again: | |||
825 | err = __rtc_set_alarm(rtc, &alarm); | 856 | err = __rtc_set_alarm(rtc, &alarm); |
826 | if (err == -ETIME) | 857 | if (err == -ETIME) |
827 | goto again; | 858 | goto again; |
828 | } | 859 | } else |
860 | rtc_alarm_disable(rtc); | ||
829 | 861 | ||
830 | mutex_unlock(&rtc->ops_lock); | 862 | mutex_unlock(&rtc->ops_lock); |
831 | } | 863 | } |
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-mxc.c b/drivers/rtc/rtc-mxc.c index 39e41fbdf08..51603543def 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c | |||
@@ -191,10 +191,11 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id) | |||
191 | struct platform_device *pdev = dev_id; | 191 | struct platform_device *pdev = dev_id; |
192 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 192 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
193 | void __iomem *ioaddr = pdata->ioaddr; | 193 | void __iomem *ioaddr = pdata->ioaddr; |
194 | unsigned long flags; | ||
194 | u32 status; | 195 | u32 status; |
195 | u32 events = 0; | 196 | u32 events = 0; |
196 | 197 | ||
197 | spin_lock_irq(&pdata->rtc->irq_lock); | 198 | spin_lock_irqsave(&pdata->rtc->irq_lock, flags); |
198 | status = readw(ioaddr + RTC_RTCISR) & readw(ioaddr + RTC_RTCIENR); | 199 | status = readw(ioaddr + RTC_RTCISR) & readw(ioaddr + RTC_RTCIENR); |
199 | /* clear interrupt sources */ | 200 | /* clear interrupt sources */ |
200 | writew(status, ioaddr + RTC_RTCISR); | 201 | writew(status, ioaddr + RTC_RTCISR); |
@@ -217,7 +218,7 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id) | |||
217 | rtc_update_alarm(&pdev->dev, &pdata->g_rtc_alarm); | 218 | rtc_update_alarm(&pdev->dev, &pdata->g_rtc_alarm); |
218 | 219 | ||
219 | rtc_update_irq(pdata->rtc, 1, events); | 220 | rtc_update_irq(pdata->rtc, 1, events); |
220 | spin_unlock_irq(&pdata->rtc->irq_lock); | 221 | spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags); |
221 | 222 | ||
222 | return IRQ_HANDLED; | 223 | return IRQ_HANDLED; |
223 | } | 224 | } |
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index ff1b84bd9bb..1e80a48057e 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c | |||
@@ -312,6 +312,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) | |||
312 | int ret; | 312 | int ret; |
313 | struct pl031_local *ldata; | 313 | struct pl031_local *ldata; |
314 | struct rtc_class_ops *ops = id->data; | 314 | struct rtc_class_ops *ops = id->data; |
315 | unsigned long time; | ||
315 | 316 | ||
316 | ret = amba_request_regions(adev, NULL); | 317 | ret = amba_request_regions(adev, NULL); |
317 | if (ret) | 318 | if (ret) |
@@ -339,11 +340,27 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) | |||
339 | dev_dbg(&adev->dev, "revision = 0x%01x\n", ldata->hw_revision); | 340 | dev_dbg(&adev->dev, "revision = 0x%01x\n", ldata->hw_revision); |
340 | 341 | ||
341 | /* Enable the clockwatch on ST Variants */ | 342 | /* Enable the clockwatch on ST Variants */ |
342 | if ((ldata->hw_designer == AMBA_VENDOR_ST) && | 343 | if (ldata->hw_designer == AMBA_VENDOR_ST) |
343 | (ldata->hw_revision > 1)) | ||
344 | writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN, | 344 | writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN, |
345 | ldata->base + RTC_CR); | 345 | ldata->base + RTC_CR); |
346 | 346 | ||
347 | /* | ||
348 | * On ST PL031 variants, the RTC reset value does not provide correct | ||
349 | * weekday for 2000-01-01. Correct the erroneous sunday to saturday. | ||
350 | */ | ||
351 | if (ldata->hw_designer == AMBA_VENDOR_ST) { | ||
352 | if (readl(ldata->base + RTC_YDR) == 0x2000) { | ||
353 | time = readl(ldata->base + RTC_DR); | ||
354 | if ((time & | ||
355 | (RTC_MON_MASK | RTC_MDAY_MASK | RTC_WDAY_MASK)) | ||
356 | == 0x02120000) { | ||
357 | time = time | (0x7 << RTC_WDAY_SHIFT); | ||
358 | writel(0x2000, ldata->base + RTC_YLR); | ||
359 | writel(time, ldata->base + RTC_LR); | ||
360 | } | ||
361 | } | ||
362 | } | ||
363 | |||
347 | ldata->rtc = rtc_device_register("pl031", &adev->dev, ops, | 364 | ldata->rtc = rtc_device_register("pl031", &adev->dev, ops, |
348 | THIS_MODULE); | 365 | THIS_MODULE); |
349 | if (IS_ERR(ldata->rtc)) { | 366 | if (IS_ERR(ldata->rtc)) { |
diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index 2fc31aac3f4..75259fe3860 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c | |||
@@ -343,7 +343,7 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev) | |||
343 | 343 | ||
344 | /* set context info. */ | 344 | /* set context info. */ |
345 | info->pdev = pdev; | 345 | info->pdev = pdev; |
346 | info->tegra_rtc_lock = __SPIN_LOCK_UNLOCKED(info->tegra_rtc_lock); | 346 | spin_lock_init(&info->tegra_rtc_lock); |
347 | 347 | ||
348 | platform_set_drvdata(pdev, info); | 348 | platform_set_drvdata(pdev, info); |
349 | 349 | ||
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index f9a2799c44d..9d51b40f164 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c | |||
@@ -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; |
@@ -462,9 +454,9 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev) | |||
462 | if (ret < 0) | 454 | if (ret < 0) |
463 | goto out1; | 455 | goto out1; |
464 | 456 | ||
465 | ret = request_irq(irq, twl_rtc_interrupt, | 457 | ret = request_threaded_irq(irq, NULL, twl_rtc_interrupt, |
466 | IRQF_TRIGGER_RISING, | 458 | + IRQF_TRIGGER_RISING | IRQF_ONESHOT, |
467 | dev_name(&rtc->dev), rtc); | 459 | dev_name(&rtc->dev), rtc); |
468 | if (ret < 0) { | 460 | if (ret < 0) { |
469 | dev_err(&pdev->dev, "IRQ is not free.\n"); | 461 | dev_err(&pdev->dev, "IRQ is not free.\n"); |
470 | goto out1; | 462 | goto out1; |