diff options
author | Doug Anderson <dianders@chromium.org> | 2014-10-21 13:47:35 -0400 |
---|---|---|
committer | Heiko Stuebner <heiko@sntech.de> | 2014-10-29 16:06:49 -0400 |
commit | fab262f5000407ce86a010ab5bc683c01c02d1a6 (patch) | |
tree | 9ad659d5a9adc5f1e94cff33bdbf397a28c3ef8d /drivers/pinctrl/pinctrl-rockchip.c | |
parent | 0fb7dcb1b3328e2ec4958b681f2e31dfd8f004fb (diff) |
pinctrl: rockchip: Protect read-modify-write with the spinlock
There were a few instances where the rockchip pinctrl driver would do
read-modify-write with no spinlock. Add a spinlock for these cases.
Signed-off-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Diffstat (limited to 'drivers/pinctrl/pinctrl-rockchip.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-rockchip.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 6c14f6c9c455..59a54617bf75 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c | |||
@@ -861,6 +861,7 @@ static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip, | |||
861 | { | 861 | { |
862 | struct rockchip_pin_bank *bank; | 862 | struct rockchip_pin_bank *bank; |
863 | int ret; | 863 | int ret; |
864 | unsigned long flags; | ||
864 | u32 data; | 865 | u32 data; |
865 | 866 | ||
866 | bank = gc_to_pin_bank(chip); | 867 | bank = gc_to_pin_bank(chip); |
@@ -869,6 +870,8 @@ static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip, | |||
869 | if (ret < 0) | 870 | if (ret < 0) |
870 | return ret; | 871 | return ret; |
871 | 872 | ||
873 | spin_lock_irqsave(&bank->slock, flags); | ||
874 | |||
872 | data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); | 875 | data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); |
873 | /* set bit to 1 for output, 0 for input */ | 876 | /* set bit to 1 for output, 0 for input */ |
874 | if (!input) | 877 | if (!input) |
@@ -877,6 +880,8 @@ static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip, | |||
877 | data &= ~BIT(pin); | 880 | data &= ~BIT(pin); |
878 | writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR); | 881 | writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR); |
879 | 882 | ||
883 | spin_unlock_irqrestore(&bank->slock, flags); | ||
884 | |||
880 | return 0; | 885 | return 0; |
881 | } | 886 | } |
882 | 887 | ||
@@ -1394,6 +1399,7 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc) | |||
1394 | u32 polarity = 0, data = 0; | 1399 | u32 polarity = 0, data = 0; |
1395 | u32 pend; | 1400 | u32 pend; |
1396 | bool edge_changed = false; | 1401 | bool edge_changed = false; |
1402 | unsigned long flags; | ||
1397 | 1403 | ||
1398 | dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name); | 1404 | dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name); |
1399 | 1405 | ||
@@ -1439,10 +1445,14 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc) | |||
1439 | 1445 | ||
1440 | if (bank->toggle_edge_mode && edge_changed) { | 1446 | if (bank->toggle_edge_mode && edge_changed) { |
1441 | /* Interrupt params should only be set with ints disabled */ | 1447 | /* Interrupt params should only be set with ints disabled */ |
1448 | spin_lock_irqsave(&bank->slock, flags); | ||
1449 | |||
1442 | data = readl_relaxed(bank->reg_base + GPIO_INTEN); | 1450 | data = readl_relaxed(bank->reg_base + GPIO_INTEN); |
1443 | writel_relaxed(0, bank->reg_base + GPIO_INTEN); | 1451 | writel_relaxed(0, bank->reg_base + GPIO_INTEN); |
1444 | writel(polarity, bank->reg_base + GPIO_INT_POLARITY); | 1452 | writel(polarity, bank->reg_base + GPIO_INT_POLARITY); |
1445 | writel(data, bank->reg_base + GPIO_INTEN); | 1453 | writel(data, bank->reg_base + GPIO_INTEN); |
1454 | |||
1455 | spin_unlock_irqrestore(&bank->slock, flags); | ||
1446 | } | 1456 | } |
1447 | 1457 | ||
1448 | chained_irq_exit(chip, desc); | 1458 | chained_irq_exit(chip, desc); |
@@ -1456,6 +1466,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) | |||
1456 | u32 polarity; | 1466 | u32 polarity; |
1457 | u32 level; | 1467 | u32 level; |
1458 | u32 data; | 1468 | u32 data; |
1469 | unsigned long flags; | ||
1459 | int ret; | 1470 | int ret; |
1460 | 1471 | ||
1461 | /* make sure the pin is configured as gpio input */ | 1472 | /* make sure the pin is configured as gpio input */ |
@@ -1463,15 +1474,20 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) | |||
1463 | if (ret < 0) | 1474 | if (ret < 0) |
1464 | return ret; | 1475 | return ret; |
1465 | 1476 | ||
1477 | spin_lock_irqsave(&bank->slock, flags); | ||
1478 | |||
1466 | data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); | 1479 | data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); |
1467 | data &= ~mask; | 1480 | data &= ~mask; |
1468 | writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR); | 1481 | writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR); |
1469 | 1482 | ||
1483 | spin_unlock_irqrestore(&bank->slock, flags); | ||
1484 | |||
1470 | if (type & IRQ_TYPE_EDGE_BOTH) | 1485 | if (type & IRQ_TYPE_EDGE_BOTH) |
1471 | __irq_set_handler_locked(d->irq, handle_edge_irq); | 1486 | __irq_set_handler_locked(d->irq, handle_edge_irq); |
1472 | else | 1487 | else |
1473 | __irq_set_handler_locked(d->irq, handle_level_irq); | 1488 | __irq_set_handler_locked(d->irq, handle_level_irq); |
1474 | 1489 | ||
1490 | spin_lock_irqsave(&bank->slock, flags); | ||
1475 | irq_gc_lock(gc); | 1491 | irq_gc_lock(gc); |
1476 | 1492 | ||
1477 | level = readl_relaxed(gc->reg_base + GPIO_INTTYPE_LEVEL); | 1493 | level = readl_relaxed(gc->reg_base + GPIO_INTTYPE_LEVEL); |
@@ -1514,6 +1530,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) | |||
1514 | break; | 1530 | break; |
1515 | default: | 1531 | default: |
1516 | irq_gc_unlock(gc); | 1532 | irq_gc_unlock(gc); |
1533 | spin_unlock_irqrestore(&bank->slock, flags); | ||
1517 | return -EINVAL; | 1534 | return -EINVAL; |
1518 | } | 1535 | } |
1519 | 1536 | ||
@@ -1521,6 +1538,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) | |||
1521 | writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY); | 1538 | writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY); |
1522 | 1539 | ||
1523 | irq_gc_unlock(gc); | 1540 | irq_gc_unlock(gc); |
1541 | spin_unlock_irqrestore(&bank->slock, flags); | ||
1524 | 1542 | ||
1525 | return 0; | 1543 | return 0; |
1526 | } | 1544 | } |