@@ -121,6 +121,7 @@ struct dmtimer {
int id;
int irq;
struct clk *fclk;
+ spinlock_t lock; /* For shared register access */
void __iomem *io_base;
int irq_stat; /* TISR/IRQSTATUS interrupt status */
@@ -633,6 +634,7 @@ static struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *n
static int omap_dm_timer_free(struct omap_dm_timer *cookie)
{
struct dmtimer *timer;
+ unsigned long flags;
struct device *dev;
int rc;
@@ -649,7 +651,9 @@ static int omap_dm_timer_free(struct omap_dm_timer *cookie)
return rc;
/* Clear timer configuration */
+ spin_lock_irqsave(&timer->lock, flags);
dmtimer_write(timer, OMAP_TIMER_CTRL_REG, 0);
+ spin_unlock_irqrestore(&timer->lock, flags);
pm_runtime_put_sync(dev);
@@ -728,6 +732,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
static int omap_dm_timer_start(struct omap_dm_timer *cookie)
{
struct dmtimer *timer;
+ unsigned long flags;
struct device *dev;
int rc;
u32 l;
@@ -742,11 +747,13 @@ static int omap_dm_timer_start(struct omap_dm_timer *cookie)
if (rc)
return rc;
+ spin_lock_irqsave(&timer->lock, flags);
l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG);
if (!(l & OMAP_TIMER_CTRL_ST)) {
l |= OMAP_TIMER_CTRL_ST;
dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l);
}
+ spin_unlock_irqrestore(&timer->lock, flags);
return 0;
}
@@ -754,6 +761,7 @@ static int omap_dm_timer_start(struct omap_dm_timer *cookie)
static int omap_dm_timer_stop(struct omap_dm_timer *cookie)
{
struct dmtimer *timer;
+ unsigned long flags;
struct device *dev;
unsigned long rate = 0;
@@ -766,7 +774,9 @@ static int omap_dm_timer_stop(struct omap_dm_timer *cookie)
if (!timer->omap1)
rate = clk_get_rate(timer->fclk);
+ spin_lock_irqsave(&timer->lock, flags);
__omap_dm_timer_stop(timer, rate);
+ spin_unlock_irqrestore(&timer->lock, flags);
pm_runtime_put_sync(dev);
@@ -800,6 +810,7 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *cookie, int enable,
unsigned int match)
{
struct dmtimer *timer;
+ unsigned long flags;
struct device *dev;
int rc;
u32 l;
@@ -813,6 +824,7 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *cookie, int enable,
if (rc)
return rc;
+ spin_lock_irqsave(&timer->lock, flags);
l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG);
if (enable)
l |= OMAP_TIMER_CTRL_CE;
@@ -820,6 +832,7 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *cookie, int enable,
l &= ~OMAP_TIMER_CTRL_CE;
dmtimer_write(timer, OMAP_TIMER_MATCH_REG, match);
dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l);
+ spin_unlock_irqrestore(&timer->lock, flags);
pm_runtime_put_sync(dev);
@@ -830,6 +843,7 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *cookie, int def_on,
int toggle, int trigger, int autoreload)
{
struct dmtimer *timer;
+ unsigned long flags;
struct device *dev;
int rc;
u32 l;
@@ -843,6 +857,7 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *cookie, int def_on,
if (rc)
return rc;
+ spin_lock_irqsave(&timer->lock, flags);
l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG);
l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
OMAP_TIMER_CTRL_PT | (0x03 << 10) | OMAP_TIMER_CTRL_AR);
@@ -854,6 +869,7 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *cookie, int def_on,
if (autoreload)
l |= OMAP_TIMER_CTRL_AR;
dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l);
+ spin_unlock_irqrestore(&timer->lock, flags);
pm_runtime_put_sync(dev);
@@ -887,6 +903,7 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *cookie,
int prescaler)
{
struct dmtimer *timer;
+ unsigned long flags;
struct device *dev;
int rc;
u32 l;
@@ -900,6 +917,7 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *cookie,
if (rc)
return rc;
+ spin_lock_irqsave(&timer->lock, flags);
l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG);
l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
if (prescaler >= 0) {
@@ -907,6 +925,7 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *cookie,
l |= prescaler << 2;
}
dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l);
+ spin_unlock_irqrestore(&timer->lock, flags);
pm_runtime_put_sync(dev);
@@ -1093,6 +1112,8 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
if (!timer)
return -ENOMEM;
+ spin_lock_init(&timer->lock);
+
timer->irq = platform_get_irq(pdev, 0);
if (timer->irq < 0)
return timer->irq;