From 14cb0deb66fcfca8fdbef75da8c84b5405a8c767 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Tue, 6 Jul 2010 14:03:22 +0300 Subject: arm/imx/gpio: add spinlock protection The GPIO registers need protection from concurrent access for operations that are not atomic. Cc: stable@kernel.org Cc: Juergen Beisert Cc: Daniel Mack Reported-by: rpkamiak@rockwellcollins.com Signed-off-by: Baruch Siach Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/gpio.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch/arm/plat-mxc/gpio.c') diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c index 11dc06190b5..57ec4a896a5 100644 --- a/arch/arm/plat-mxc/gpio.c +++ b/arch/arm/plat-mxc/gpio.c @@ -214,13 +214,16 @@ static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset, struct mxc_gpio_port *port = container_of(chip, struct mxc_gpio_port, chip); u32 l; + unsigned long flags; + spin_lock_irqsave(&port->lock, flags); l = __raw_readl(port->base + GPIO_GDIR); if (dir) l |= 1 << offset; else l &= ~(1 << offset); __raw_writel(l, port->base + GPIO_GDIR); + spin_unlock_irqrestore(&port->lock, flags); } static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value) @@ -229,9 +232,12 @@ static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value) container_of(chip, struct mxc_gpio_port, chip); void __iomem *reg = port->base + GPIO_DR; u32 l; + unsigned long flags; + spin_lock_irqsave(&port->lock, flags); l = (__raw_readl(reg) & (~(1 << offset))) | (value << offset); __raw_writel(l, reg); + spin_unlock_irqrestore(&port->lock, flags); } static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset) @@ -285,6 +291,8 @@ int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt) port[i].chip.base = i * 32; port[i].chip.ngpio = 32; + spin_lock_init(&port[i].lock); + /* its a serious configuration bug when it fails */ BUG_ON( gpiochip_add(&port[i].chip) < 0 ); -- cgit v1.2.3-18-g5258