diff options
author | Doug Anderson <dianders@chromium.org> | 2013-06-12 13:33:17 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2013-06-16 06:01:54 -0400 |
commit | 5ae8cf7980858bcd7559034c716ada440e4cb181 (patch) | |
tree | 5dcf4744cf1e03fca72686fc2c7fd9fcb3e1614c /drivers/pinctrl | |
parent | ce06f40740bc9320e7a22c1964ba408f03c0d013 (diff) |
pinctrl: exynos: Add spinlocks to irq_mask and irq_unmask
The patch:
1984695 pinctrl: samsung: Protect bank registers with a spinlock
...added spinlocks to protect many accesses. However, the irq_mask
and irq_unmask functions still do an unprotected read/modify/write.
Add the spinlock there.
Signed-off-by: Doug Anderson <dianders@chromium.org>
Acked-by: Tomasz Figa <t.figa@samsung.com>
Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r-- | drivers/pinctrl/pinctrl-exynos.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index 2d76f66a2e0b..c29a28ee8d25 100644 --- a/drivers/pinctrl/pinctrl-exynos.c +++ b/drivers/pinctrl/pinctrl-exynos.c | |||
@@ -56,10 +56,15 @@ static void exynos_gpio_irq_unmask(struct irq_data *irqd) | |||
56 | struct samsung_pinctrl_drv_data *d = bank->drvdata; | 56 | struct samsung_pinctrl_drv_data *d = bank->drvdata; |
57 | unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset; | 57 | unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset; |
58 | unsigned long mask; | 58 | unsigned long mask; |
59 | unsigned long flags; | ||
60 | |||
61 | spin_lock_irqsave(&bank->slock, flags); | ||
59 | 62 | ||
60 | mask = readl(d->virt_base + reg_mask); | 63 | mask = readl(d->virt_base + reg_mask); |
61 | mask &= ~(1 << irqd->hwirq); | 64 | mask &= ~(1 << irqd->hwirq); |
62 | writel(mask, d->virt_base + reg_mask); | 65 | writel(mask, d->virt_base + reg_mask); |
66 | |||
67 | spin_unlock_irqrestore(&bank->slock, flags); | ||
63 | } | 68 | } |
64 | 69 | ||
65 | static void exynos_gpio_irq_mask(struct irq_data *irqd) | 70 | static void exynos_gpio_irq_mask(struct irq_data *irqd) |
@@ -68,10 +73,15 @@ static void exynos_gpio_irq_mask(struct irq_data *irqd) | |||
68 | struct samsung_pinctrl_drv_data *d = bank->drvdata; | 73 | struct samsung_pinctrl_drv_data *d = bank->drvdata; |
69 | unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset; | 74 | unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset; |
70 | unsigned long mask; | 75 | unsigned long mask; |
76 | unsigned long flags; | ||
77 | |||
78 | spin_lock_irqsave(&bank->slock, flags); | ||
71 | 79 | ||
72 | mask = readl(d->virt_base + reg_mask); | 80 | mask = readl(d->virt_base + reg_mask); |
73 | mask |= 1 << irqd->hwirq; | 81 | mask |= 1 << irqd->hwirq; |
74 | writel(mask, d->virt_base + reg_mask); | 82 | writel(mask, d->virt_base + reg_mask); |
83 | |||
84 | spin_unlock_irqrestore(&bank->slock, flags); | ||
75 | } | 85 | } |
76 | 86 | ||
77 | static void exynos_gpio_irq_ack(struct irq_data *irqd) | 87 | static void exynos_gpio_irq_ack(struct irq_data *irqd) |
@@ -264,10 +274,15 @@ static void exynos_wkup_irq_unmask(struct irq_data *irqd) | |||
264 | struct samsung_pinctrl_drv_data *d = b->drvdata; | 274 | struct samsung_pinctrl_drv_data *d = b->drvdata; |
265 | unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset; | 275 | unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset; |
266 | unsigned long mask; | 276 | unsigned long mask; |
277 | unsigned long flags; | ||
278 | |||
279 | spin_lock_irqsave(&b->slock, flags); | ||
267 | 280 | ||
268 | mask = readl(d->virt_base + reg_mask); | 281 | mask = readl(d->virt_base + reg_mask); |
269 | mask &= ~(1 << irqd->hwirq); | 282 | mask &= ~(1 << irqd->hwirq); |
270 | writel(mask, d->virt_base + reg_mask); | 283 | writel(mask, d->virt_base + reg_mask); |
284 | |||
285 | spin_unlock_irqrestore(&b->slock, flags); | ||
271 | } | 286 | } |
272 | 287 | ||
273 | static void exynos_wkup_irq_mask(struct irq_data *irqd) | 288 | static void exynos_wkup_irq_mask(struct irq_data *irqd) |
@@ -276,10 +291,15 @@ static void exynos_wkup_irq_mask(struct irq_data *irqd) | |||
276 | struct samsung_pinctrl_drv_data *d = b->drvdata; | 291 | struct samsung_pinctrl_drv_data *d = b->drvdata; |
277 | unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset; | 292 | unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset; |
278 | unsigned long mask; | 293 | unsigned long mask; |
294 | unsigned long flags; | ||
295 | |||
296 | spin_lock_irqsave(&b->slock, flags); | ||
279 | 297 | ||
280 | mask = readl(d->virt_base + reg_mask); | 298 | mask = readl(d->virt_base + reg_mask); |
281 | mask |= 1 << irqd->hwirq; | 299 | mask |= 1 << irqd->hwirq; |
282 | writel(mask, d->virt_base + reg_mask); | 300 | writel(mask, d->virt_base + reg_mask); |
301 | |||
302 | spin_unlock_irqrestore(&b->slock, flags); | ||
283 | } | 303 | } |
284 | 304 | ||
285 | static void exynos_wkup_irq_ack(struct irq_data *irqd) | 305 | static void exynos_wkup_irq_ack(struct irq_data *irqd) |