aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pinctrl/pinctrl-exynos.c11
-rw-r--r--drivers/pinctrl/pinctrl-samsung.c24
-rw-r--r--drivers/pinctrl/pinctrl-samsung.h2
3 files changed, 37 insertions, 0 deletions
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c
index 538b9ddaadf7..cf7700ed57b8 100644
--- a/drivers/pinctrl/pinctrl-exynos.c
+++ b/drivers/pinctrl/pinctrl-exynos.c
@@ -26,6 +26,7 @@
26#include <linux/of_irq.h> 26#include <linux/of_irq.h>
27#include <linux/io.h> 27#include <linux/io.h>
28#include <linux/slab.h> 28#include <linux/slab.h>
29#include <linux/spinlock.h>
29#include <linux/err.h> 30#include <linux/err.h>
30 31
31#include <asm/mach/irq.h> 32#include <asm/mach/irq.h>
@@ -81,6 +82,7 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
81 unsigned int shift = EXYNOS_EINT_CON_LEN * pin; 82 unsigned int shift = EXYNOS_EINT_CON_LEN * pin;
82 unsigned int con, trig_type; 83 unsigned int con, trig_type;
83 unsigned long reg_con = ctrl->geint_con + bank->eint_offset; 84 unsigned long reg_con = ctrl->geint_con + bank->eint_offset;
85 unsigned long flags;
84 unsigned int mask; 86 unsigned int mask;
85 87
86 switch (type) { 88 switch (type) {
@@ -118,11 +120,15 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
118 shift = pin * bank->func_width; 120 shift = pin * bank->func_width;
119 mask = (1 << bank->func_width) - 1; 121 mask = (1 << bank->func_width) - 1;
120 122
123 spin_lock_irqsave(&bank->slock, flags);
124
121 con = readl(d->virt_base + reg_con); 125 con = readl(d->virt_base + reg_con);
122 con &= ~(mask << shift); 126 con &= ~(mask << shift);
123 con |= EXYNOS_EINT_FUNC << shift; 127 con |= EXYNOS_EINT_FUNC << shift;
124 writel(con, d->virt_base + reg_con); 128 writel(con, d->virt_base + reg_con);
125 129
130 spin_unlock_irqrestore(&bank->slock, flags);
131
126 return 0; 132 return 0;
127} 133}
128 134
@@ -258,6 +264,7 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
258 unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset; 264 unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset;
259 unsigned long shift = EXYNOS_EINT_CON_LEN * pin; 265 unsigned long shift = EXYNOS_EINT_CON_LEN * pin;
260 unsigned long con, trig_type; 266 unsigned long con, trig_type;
267 unsigned long flags;
261 unsigned int mask; 268 unsigned int mask;
262 269
263 switch (type) { 270 switch (type) {
@@ -295,11 +302,15 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
295 shift = pin * bank->func_width; 302 shift = pin * bank->func_width;
296 mask = (1 << bank->func_width) - 1; 303 mask = (1 << bank->func_width) - 1;
297 304
305 spin_lock_irqsave(&bank->slock, flags);
306
298 con = readl(d->virt_base + reg_con); 307 con = readl(d->virt_base + reg_con);
299 con &= ~(mask << shift); 308 con &= ~(mask << shift);
300 con |= EXYNOS_EINT_FUNC << shift; 309 con |= EXYNOS_EINT_FUNC << shift;
301 writel(con, d->virt_base + reg_con); 310 writel(con, d->virt_base + reg_con);
302 311
312 spin_unlock_irqrestore(&bank->slock, flags);
313
303 return 0; 314 return 0;
304} 315}
305 316
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index 3475b92b24a4..b1d4ac8d36f8 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -27,6 +27,7 @@
27#include <linux/err.h> 27#include <linux/err.h>
28#include <linux/gpio.h> 28#include <linux/gpio.h>
29#include <linux/irqdomain.h> 29#include <linux/irqdomain.h>
30#include <linux/spinlock.h>
30 31
31#include "core.h" 32#include "core.h"
32#include "pinctrl-samsung.h" 33#include "pinctrl-samsung.h"
@@ -289,6 +290,7 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
289 struct samsung_pin_bank *bank; 290 struct samsung_pin_bank *bank;
290 void __iomem *reg; 291 void __iomem *reg;
291 u32 mask, shift, data, pin_offset, cnt; 292 u32 mask, shift, data, pin_offset, cnt;
293 unsigned long flags;
292 294
293 drvdata = pinctrl_dev_get_drvdata(pctldev); 295 drvdata = pinctrl_dev_get_drvdata(pctldev);
294 pins = drvdata->pin_groups[group].pins; 296 pins = drvdata->pin_groups[group].pins;
@@ -303,11 +305,15 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
303 mask = (1 << bank->func_width) - 1; 305 mask = (1 << bank->func_width) - 1;
304 shift = pin_offset * bank->func_width; 306 shift = pin_offset * bank->func_width;
305 307
308 spin_lock_irqsave(&bank->slock, flags);
309
306 data = readl(reg); 310 data = readl(reg);
307 data &= ~(mask << shift); 311 data &= ~(mask << shift);
308 if (enable) 312 if (enable)
309 data |= drvdata->pin_groups[group].func << shift; 313 data |= drvdata->pin_groups[group].func << shift;
310 writel(data, reg); 314 writel(data, reg);
315
316 spin_unlock_irqrestore(&bank->slock, flags);
311 } 317 }
312} 318}
313 319
@@ -338,6 +344,7 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
338 struct samsung_pinctrl_drv_data *drvdata; 344 struct samsung_pinctrl_drv_data *drvdata;
339 void __iomem *reg; 345 void __iomem *reg;
340 u32 data, pin_offset, mask, shift; 346 u32 data, pin_offset, mask, shift;
347 unsigned long flags;
341 348
342 bank = gc_to_pin_bank(range->gc); 349 bank = gc_to_pin_bank(range->gc);
343 drvdata = pinctrl_dev_get_drvdata(pctldev); 350 drvdata = pinctrl_dev_get_drvdata(pctldev);
@@ -348,11 +355,16 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
348 mask = (1 << bank->func_width) - 1; 355 mask = (1 << bank->func_width) - 1;
349 shift = pin_offset * bank->func_width; 356 shift = pin_offset * bank->func_width;
350 357
358 spin_lock_irqsave(&bank->slock, flags);
359
351 data = readl(reg); 360 data = readl(reg);
352 data &= ~(mask << shift); 361 data &= ~(mask << shift);
353 if (!input) 362 if (!input)
354 data |= FUNC_OUTPUT << shift; 363 data |= FUNC_OUTPUT << shift;
355 writel(data, reg); 364 writel(data, reg);
365
366 spin_unlock_irqrestore(&bank->slock, flags);
367
356 return 0; 368 return 0;
357} 369}
358 370
@@ -376,6 +388,7 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
376 enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config); 388 enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config);
377 u32 data, width, pin_offset, mask, shift; 389 u32 data, width, pin_offset, mask, shift;
378 u32 cfg_value, cfg_reg; 390 u32 cfg_value, cfg_reg;
391 unsigned long flags;
379 392
380 drvdata = pinctrl_dev_get_drvdata(pctldev); 393 drvdata = pinctrl_dev_get_drvdata(pctldev);
381 pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, &reg_base, 394 pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, &reg_base,
@@ -406,6 +419,8 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
406 if (!width) 419 if (!width)
407 return -EINVAL; 420 return -EINVAL;
408 421
422 spin_lock_irqsave(&bank->slock, flags);
423
409 mask = (1 << width) - 1; 424 mask = (1 << width) - 1;
410 shift = pin_offset * width; 425 shift = pin_offset * width;
411 data = readl(reg_base + cfg_reg); 426 data = readl(reg_base + cfg_reg);
@@ -420,6 +435,9 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
420 data &= mask; 435 data &= mask;
421 *config = PINCFG_PACK(cfg_type, data); 436 *config = PINCFG_PACK(cfg_type, data);
422 } 437 }
438
439 spin_unlock_irqrestore(&bank->slock, flags);
440
423 return 0; 441 return 0;
424} 442}
425 443
@@ -479,16 +497,21 @@ static const struct pinconf_ops samsung_pinconf_ops = {
479static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value) 497static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
480{ 498{
481 struct samsung_pin_bank *bank = gc_to_pin_bank(gc); 499 struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
500 unsigned long flags;
482 void __iomem *reg; 501 void __iomem *reg;
483 u32 data; 502 u32 data;
484 503
485 reg = bank->drvdata->virt_base + bank->pctl_offset; 504 reg = bank->drvdata->virt_base + bank->pctl_offset;
486 505
506 spin_lock_irqsave(&bank->slock, flags);
507
487 data = readl(reg + DAT_REG); 508 data = readl(reg + DAT_REG);
488 data &= ~(1 << offset); 509 data &= ~(1 << offset);
489 if (value) 510 if (value)
490 data |= 1 << offset; 511 data |= 1 << offset;
491 writel(data, reg + DAT_REG); 512 writel(data, reg + DAT_REG);
513
514 spin_unlock_irqrestore(&bank->slock, flags);
492} 515}
493 516
494/* gpiolib gpio_get callback function */ 517/* gpiolib gpio_get callback function */
@@ -859,6 +882,7 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(
859 882
860 bank = ctrl->pin_banks; 883 bank = ctrl->pin_banks;
861 for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { 884 for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
885 spin_lock_init(&bank->slock);
862 bank->drvdata = d; 886 bank->drvdata = d;
863 bank->pin_base = ctrl->nr_pins; 887 bank->pin_base = ctrl->nr_pins;
864 ctrl->nr_pins += bank->nr_pins; 888 ctrl->nr_pins += bank->nr_pins;
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h
index e2d4e67f7e88..b9dbe7949fab 100644
--- a/drivers/pinctrl/pinctrl-samsung.h
+++ b/drivers/pinctrl/pinctrl-samsung.h
@@ -119,6 +119,7 @@ struct samsung_pinctrl_drv_data;
119 * @irq_domain: IRQ domain of the bank. 119 * @irq_domain: IRQ domain of the bank.
120 * @gpio_chip: GPIO chip of the bank. 120 * @gpio_chip: GPIO chip of the bank.
121 * @grange: linux gpio pin range supported by this bank. 121 * @grange: linux gpio pin range supported by this bank.
122 * @slock: spinlock protecting bank registers
122 */ 123 */
123struct samsung_pin_bank { 124struct samsung_pin_bank {
124 u32 pctl_offset; 125 u32 pctl_offset;
@@ -137,6 +138,7 @@ struct samsung_pin_bank {
137 struct irq_domain *irq_domain; 138 struct irq_domain *irq_domain;
138 struct gpio_chip gpio_chip; 139 struct gpio_chip gpio_chip;
139 struct pinctrl_gpio_range grange; 140 struct pinctrl_gpio_range grange;
141 spinlock_t slock;
140}; 142};
141 143
142/** 144/**