diff options
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/interface.c | 16 | ||||
-rw-r--r-- | drivers/rtc/rtc-at91.c | 3 | ||||
-rw-r--r-- | drivers/rtc/rtc-dev.c | 25 | ||||
-rw-r--r-- | drivers/rtc/rtc-ds1553.c | 3 | ||||
-rw-r--r-- | drivers/rtc/rtc-rs5c372.c | 6 | ||||
-rw-r--r-- | drivers/rtc/rtc-test.c | 2 |
6 files changed, 40 insertions, 15 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 579cd667b16f..6f11f6dfdd9d 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -145,6 +145,13 @@ int rtc_set_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm) } EXPORT_SYMBOL_GPL(rtc_set_alarm); +/** + * rtc_update_irq - report RTC periodic, alarm, and/or update irqs + * @class_dev: the rtc's class device + * @num: how many irqs are being reported (usually one) + * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF + * Context: in_interrupt(), irqs blocked + */ void rtc_update_irq(struct class_device *class_dev, unsigned long num, unsigned long events) { @@ -201,12 +208,12 @@ int rtc_irq_register(struct class_device *class_dev, struct rtc_task *task) if (task == NULL || task->func == NULL) return -EINVAL; - spin_lock(&rtc->irq_task_lock); + spin_lock_irq(&rtc->irq_task_lock); if (rtc->irq_task == NULL) { rtc->irq_task = task; retval = 0; } - spin_unlock(&rtc->irq_task_lock); + spin_unlock_irq(&rtc->irq_task_lock); return retval; } @@ -216,10 +223,10 @@ void rtc_irq_unregister(struct class_device *class_dev, struct rtc_task *task) { struct rtc_device *rtc = to_rtc_device(class_dev); - spin_lock(&rtc->irq_task_lock); + spin_lock_irq(&rtc->irq_task_lock); if (rtc->irq_task == task) rtc->irq_task = NULL; - spin_unlock(&rtc->irq_task_lock); + spin_unlock_irq(&rtc->irq_task_lock); } EXPORT_SYMBOL_GPL(rtc_irq_unregister); @@ -265,3 +272,4 @@ int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int } return err; } +EXPORT_SYMBOL_GPL(rtc_irq_set_freq); diff --git a/drivers/rtc/rtc-at91.c b/drivers/rtc/rtc-at91.c index bd61e99540a3..5c8addcaf1fb 100644 --- a/drivers/rtc/rtc-at91.c +++ b/drivers/rtc/rtc-at91.c @@ -292,7 +292,8 @@ static int __init at91_rtc_probe(struct platform_device *pdev) AT91_RTC_CALEV); ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, - IRQF_SHARED, "at91_rtc", pdev); + IRQF_DISABLED | IRQF_SHARED, + "at91_rtc", pdev); if (ret) { printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n", AT91_ID_SYS); diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index dcf5f86461f7..828b329e08e0 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -62,7 +62,9 @@ static void rtc_uie_task(struct work_struct *work) int err; err = rtc_read_time(&rtc->class_dev, &tm); - spin_lock_irq(&rtc->irq_lock); + + local_irq_disable(); + spin_lock(&rtc->irq_lock); if (rtc->stop_uie_polling || err) { rtc->uie_task_active = 0; } else if (rtc->oldsecs != tm.tm_sec) { @@ -75,11 +77,11 @@ static void rtc_uie_task(struct work_struct *work) } else if (schedule_work(&rtc->uie_task) == 0) { rtc->uie_task_active = 0; } - spin_unlock_irq(&rtc->irq_lock); + spin_unlock(&rtc->irq_lock); if (num) rtc_update_irq(&rtc->class_dev, num, RTC_UF | RTC_IRQF); + local_irq_enable(); } - static void rtc_uie_timer(unsigned long data) { struct rtc_device *rtc = (struct rtc_device *)data; @@ -215,7 +217,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, struct rtc_wkalrm alarm; void __user *uarg = (void __user *) arg; - /* check that the calles has appropriate permissions + /* check that the calling task has appropriate permissions * for certain ioctls. doing this check here is useful * to avoid duplicate code in each driver. */ @@ -239,10 +241,10 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, /* avoid conflicting IRQ users */ if (cmd == RTC_PIE_ON || cmd == RTC_PIE_OFF || cmd == RTC_IRQP_SET) { - spin_lock(&rtc->irq_task_lock); + spin_lock_irq(&rtc->irq_task_lock); if (rtc->irq_task) err = -EBUSY; - spin_unlock(&rtc->irq_task_lock); + spin_unlock_irq(&rtc->irq_task_lock); if (err < 0) return err; @@ -300,6 +302,17 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, err = rtc_set_time(class_dev, &tm); break; + + case RTC_IRQP_READ: + if (ops->irq_set_freq) + err = put_user(rtc->irq_freq, (unsigned long *) arg); + break; + + case RTC_IRQP_SET: + if (ops->irq_set_freq) + err = rtc_irq_set_freq(class_dev, rtc->irq_task, arg); + break; + #if 0 case RTC_EPOCH_SET: #ifndef rtc_epoch diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 78552e6e76aa..001eb1123a65 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -340,7 +340,8 @@ static int __init ds1553_rtc_probe(struct platform_device *pdev) if (pdata->irq >= 0) { writeb(0, ioaddr + RTC_INTERRUPTS); - if (request_irq(pdata->irq, ds1553_rtc_interrupt, IRQF_SHARED, + if (request_irq(pdata->irq, ds1553_rtc_interrupt, + IRQF_DISABLED | IRQF_SHARED, pdev->name, pdev) < 0) { dev_warn(&pdev->dev, "interrupt not available.\n"); pdata->irq = -1; diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 2a86632580f1..a44fe4efa216 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -126,13 +126,13 @@ static int rs5c372_get_trim(struct i2c_client *client, int *osc, int *trim) return -EIO; } - dev_dbg(&client->dev, "%s: raw trim=%x\n", __FUNCTION__, *trim); - if (osc) *osc = (buf & RS5C372_TRIM_XSL) ? 32000 : 32768; - if (trim) + if (trim) { *trim = buf & RS5C372_TRIM_MASK; + dev_dbg(&client->dev, "%s: raw trim=%x\n", __FUNCTION__, *trim); + } return 0; } diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index bc4bd24508a2..6ef9c62d5032 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -99,6 +99,7 @@ static ssize_t test_irq_store(struct device *dev, struct rtc_device *rtc = platform_get_drvdata(plat_dev); retval = count; + local_irq_disable(); if (strncmp(buf, "tick", 4) == 0) rtc_update_irq(&rtc->class_dev, 1, RTC_PF | RTC_IRQF); else if (strncmp(buf, "alarm", 5) == 0) @@ -107,6 +108,7 @@ static ssize_t test_irq_store(struct device *dev, rtc_update_irq(&rtc->class_dev, 1, RTC_UF | RTC_IRQF); else retval = -EINVAL; + local_irq_enable(); return retval; } |