1
0
Fork 0

drivers/rtc/rtc-sirfsoc.c: replace local_irq_disable by spin_lock_irq for SMP safety

Signed-off-by: Barry Song <Baohua.Song@csr.com>
Cc: hao liu <hao.liu@csr.com>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
hifive-unleashed-5.1
Barry Song 2014-12-10 15:53:51 -08:00 committed by Linus Torvalds
parent 09e427f87d
commit e9bc7363d6
1 changed files with 19 additions and 8 deletions

View File

@ -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;
@ -217,7 +220,7 @@ static int sirfsoc_rtc_alarm_irq_enable(struct device *dev,
rtcdrv = dev_get_drvdata(dev);
local_irq_disable();
spin_lock_irq(&rtcdrv->lock);
rtc_status_reg = sirfsoc_rtc_iobrg_readl(
rtcdrv->rtc_base + RTC_STATUS);
@ -227,7 +230,8 @@ static int sirfsoc_rtc_alarm_irq_enable(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);
return 0;
@ -248,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
@ -265,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
*/
@ -292,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");