mirror of
https://github.com/torvalds/linux.git
synced 2024-11-04 11:04:38 +00:00
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>
This commit is contained in:
parent
0fb7dcb1b3
commit
fab262f500
@ -861,6 +861,7 @@ static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip,
|
||||
{
|
||||
struct rockchip_pin_bank *bank;
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
u32 data;
|
||||
|
||||
bank = gc_to_pin_bank(chip);
|
||||
@ -869,6 +870,8 @@ static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
|
||||
/* set bit to 1 for output, 0 for input */
|
||||
if (!input)
|
||||
@ -877,6 +880,8 @@ static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip,
|
||||
data &= ~BIT(pin);
|
||||
writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1394,6 +1399,7 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
|
||||
u32 polarity = 0, data = 0;
|
||||
u32 pend;
|
||||
bool edge_changed = false;
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name);
|
||||
|
||||
@ -1439,10 +1445,14 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
|
||||
|
||||
if (bank->toggle_edge_mode && edge_changed) {
|
||||
/* Interrupt params should only be set with ints disabled */
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
data = readl_relaxed(bank->reg_base + GPIO_INTEN);
|
||||
writel_relaxed(0, bank->reg_base + GPIO_INTEN);
|
||||
writel(polarity, bank->reg_base + GPIO_INT_POLARITY);
|
||||
writel(data, bank->reg_base + GPIO_INTEN);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
@ -1456,6 +1466,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
u32 polarity;
|
||||
u32 level;
|
||||
u32 data;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
/* 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)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
|
||||
data &= ~mask;
|
||||
writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
|
||||
if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
__irq_set_handler_locked(d->irq, handle_edge_irq);
|
||||
else
|
||||
__irq_set_handler_locked(d->irq, handle_level_irq);
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
irq_gc_lock(gc);
|
||||
|
||||
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)
|
||||
break;
|
||||
default:
|
||||
irq_gc_unlock(gc);
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1521,6 +1538,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY);
|
||||
|
||||
irq_gc_unlock(gc);
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user