diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-10 18:34:42 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-10 18:34:42 -0800 |
commit | b6da0076bab5a12afb19312ffee41c95490af2a0 (patch) | |
tree | 52a5675b9c2ff95d88b981d5b9a3822f6073c112 /drivers/rtc/rtc-sirfsoc.c | |
parent | cbfe0de303a55ed96d8831c2d5f56f8131cd6612 (diff) | |
parent | a53b831549141aa060a8b54b76e3a42870d74cc0 (diff) |
Merge branch 'akpm' (patchbomb from Andrew)
Merge first patchbomb from Andrew Morton:
- a few minor cifs fixes
- dma-debug upadtes
- ocfs2
- slab
- about half of MM
- procfs
- kernel/exit.c
- panic.c tweaks
- printk upates
- lib/ updates
- checkpatch updates
- fs/binfmt updates
- the drivers/rtc tree
- nilfs
- kmod fixes
- more kernel/exit.c
- various other misc tweaks and fixes
* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (190 commits)
exit: pidns: fix/update the comments in zap_pid_ns_processes()
exit: pidns: alloc_pid() leaks pid_namespace if child_reaper is exiting
exit: exit_notify: re-use "dead" list to autoreap current
exit: reparent: call forget_original_parent() under tasklist_lock
exit: reparent: avoid find_new_reaper() if no children
exit: reparent: introduce find_alive_thread()
exit: reparent: introduce find_child_reaper()
exit: reparent: document the ->has_child_subreaper checks
exit: reparent: s/while_each_thread/for_each_thread/ in find_new_reaper()
exit: reparent: fix the cross-namespace PR_SET_CHILD_SUBREAPER reparenting
exit: reparent: fix the dead-parent PR_SET_CHILD_SUBREAPER reparenting
exit: proc: don't try to flush /proc/tgid/task/tgid
exit: release_task: fix the comment about group leader accounting
exit: wait: drop tasklist_lock before psig->c* accounting
exit: wait: don't use zombie->real_parent
exit: wait: cleanup the ptrace_reparented() checks
usermodehelper: kill the kmod_thread_locker logic
usermodehelper: don't use CLONE_VFORK for ____call_usermodehelper()
fs/hfs/catalog.c: fix comparison bug in hfs_cat_keycmp
nilfs2: fix the nilfs_iget() vs. nilfs_new_inode() races
...
Diffstat (limited to 'drivers/rtc/rtc-sirfsoc.c')
-rw-r--r-- | drivers/rtc/rtc-sirfsoc.c | 66 |
1 files changed, 51 insertions, 15 deletions
diff --git a/drivers/rtc/rtc-sirfsoc.c b/drivers/rtc/rtc-sirfsoc.c index 76e38007ba90..d2ac6688e5c7 100644 --- a/drivers/rtc/rtc-sirfsoc.c +++ b/drivers/rtc/rtc-sirfsoc.c @@ -47,6 +47,7 @@ struct sirfsoc_rtc_drv { unsigned irq_wake; /* Overflow for every 8 years extra time */ u32 overflow_rtc; + spinlock_t lock; #ifdef CONFIG_PM u32 saved_counter; u32 saved_overflow_rtc; @@ -61,7 +62,7 @@ static int sirfsoc_rtc_read_alarm(struct device *dev, rtcdrv = dev_get_drvdata(dev); - local_irq_disable(); + spin_lock_irq(&rtcdrv->lock); rtc_count = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN); @@ -84,7 +85,8 @@ static int sirfsoc_rtc_read_alarm(struct device *dev, if (sirfsoc_rtc_iobrg_readl( rtcdrv->rtc_base + RTC_STATUS) & SIRFSOC_RTC_AL0E) alrm->enabled = 1; - local_irq_enable(); + + spin_unlock_irq(&rtcdrv->lock); return 0; } @@ -99,7 +101,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev, if (alrm->enabled) { rtc_tm_to_time(&(alrm->time), &rtc_alarm); - local_irq_disable(); + spin_lock_irq(&rtcdrv->lock); rtc_status_reg = sirfsoc_rtc_iobrg_readl( rtcdrv->rtc_base + RTC_STATUS); @@ -123,14 +125,15 @@ static int sirfsoc_rtc_set_alarm(struct device *dev, rtc_status_reg |= SIRFSOC_RTC_AL0E; sirfsoc_rtc_iobrg_writel( rtc_status_reg, rtcdrv->rtc_base + RTC_STATUS); - local_irq_enable(); + + spin_unlock_irq(&rtcdrv->lock); } else { /* * if this function was called with enabled=0 * then it could mean that the application is * trying to cancel an ongoing alarm */ - local_irq_disable(); + spin_lock_irq(&rtcdrv->lock); rtc_status_reg = sirfsoc_rtc_iobrg_readl( rtcdrv->rtc_base + RTC_STATUS); @@ -146,7 +149,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev, rtcdrv->rtc_base + RTC_STATUS); } - local_irq_enable(); + spin_unlock_irq(&rtcdrv->lock); } return 0; @@ -209,12 +212,38 @@ static int sirfsoc_rtc_ioctl(struct device *dev, unsigned int cmd, } } +static int sirfsoc_rtc_alarm_irq_enable(struct device *dev, + unsigned int enabled) +{ + unsigned long rtc_status_reg = 0x0; + struct sirfsoc_rtc_drv *rtcdrv; + + rtcdrv = dev_get_drvdata(dev); + + spin_lock_irq(&rtcdrv->lock); + + rtc_status_reg = sirfsoc_rtc_iobrg_readl( + rtcdrv->rtc_base + RTC_STATUS); + if (enabled) + rtc_status_reg |= SIRFSOC_RTC_AL0E; + else + rtc_status_reg &= ~SIRFSOC_RTC_AL0E; + + sirfsoc_rtc_iobrg_writel(rtc_status_reg, rtcdrv->rtc_base + RTC_STATUS); + + spin_unlock_irq(&rtcdrv->lock); + + return 0; + +} + static const struct rtc_class_ops sirfsoc_rtc_ops = { .read_time = sirfsoc_rtc_read_time, .set_time = sirfsoc_rtc_set_time, .read_alarm = sirfsoc_rtc_read_alarm, .set_alarm = sirfsoc_rtc_set_alarm, - .ioctl = sirfsoc_rtc_ioctl + .ioctl = sirfsoc_rtc_ioctl, + .alarm_irq_enable = sirfsoc_rtc_alarm_irq_enable }; static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata) @@ -223,6 +252,8 @@ static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata) unsigned long rtc_status_reg = 0x0; unsigned long events = 0x0; + spin_lock(&rtcdrv->lock); + rtc_status_reg = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_STATUS); /* this bit will be set ONLY if an alarm was active * and it expired NOW @@ -240,6 +271,9 @@ static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata) rtc_status_reg &= ~(SIRFSOC_RTC_AL0E); } sirfsoc_rtc_iobrg_writel(rtc_status_reg, rtcdrv->rtc_base + RTC_STATUS); + + spin_unlock(&rtcdrv->lock); + /* this should wake up any apps polling/waiting on the read * after setting the alarm */ @@ -267,6 +301,8 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev) if (rtcdrv == NULL) return -ENOMEM; + spin_lock_init(&rtcdrv->lock); + err = of_property_read_u32(np, "reg", &rtcdrv->rtc_base); if (err) { dev_err(&pdev->dev, "unable to find base address of rtc node in dtb\n"); @@ -286,14 +322,6 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev) rtc_div = ((32768 / RTC_HZ) / 2) - 1; sirfsoc_rtc_iobrg_writel(rtc_div, rtcdrv->rtc_base + RTC_DIV); - rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, - &sirfsoc_rtc_ops, THIS_MODULE); - if (IS_ERR(rtcdrv->rtc)) { - err = PTR_ERR(rtcdrv->rtc); - dev_err(&pdev->dev, "can't register RTC device\n"); - return err; - } - /* 0x3 -> RTC_CLK */ sirfsoc_rtc_iobrg_writel(SIRFSOC_RTC_CLK, rtcdrv->rtc_base + RTC_CLOCK_SWITCH); @@ -308,6 +336,14 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev) rtcdrv->overflow_rtc = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_SW_VALUE); + rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, + &sirfsoc_rtc_ops, THIS_MODULE); + if (IS_ERR(rtcdrv->rtc)) { + err = PTR_ERR(rtcdrv->rtc); + dev_err(&pdev->dev, "can't register RTC device\n"); + return err; + } + rtcdrv->irq = platform_get_irq(pdev, 0); err = devm_request_irq( &pdev->dev, |