aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorChristopher Kenna <cjk@cs.unc.edu>2012-09-20 13:33:17 -0400
committerChristopher Kenna <cjk@cs.unc.edu>2012-09-20 13:33:17 -0400
commit5e0a4919ccb230ab449826ef91bdf38a4ed283e5 (patch)
tree3790db1aa69ed50b08f34c21c1796785df6a0304 /drivers/rtc
parentc00613f1fad38acec00ef2c009ae4e73110084ac (diff)
parent5dd038629bdedef22d5ecad2d5e75ad81f4dc694 (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.c74
-rw-r--r--drivers/rtc/rtc-m41t80.c9
-rw-r--r--drivers/rtc/rtc-mxc.c5
-rw-r--r--drivers/rtc/rtc-pl031.c21
-rw-r--r--drivers/rtc/rtc-tegra.c2
-rw-r--r--drivers/rtc/rtc-twl.c14
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}
637EXPORT_SYMBOL_GPL(rtc_irq_unregister); 637EXPORT_SYMBOL_GPL(rtc_irq_unregister);
638 638
639static 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
677retry:
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}
671EXPORT_SYMBOL_GPL(rtc_irq_set_state); 694EXPORT_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 713retry:
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
765static 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)
357static struct rtc_class_ops m41t80_rtc_ops = { 357static 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;