From 96f6b7b0a8d82d9016ecf241aa78c2c264b77412 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 commit 14cb0deb66fcfca8fdbef75da8c84b5405a8c767 upstream. The GPIO registers need protection from concurrent access for operations that are not atomic. Cc: Juergen Beisert Cc: Daniel Mack Reported-by: rpkamiak@rockwellcollins.com Signed-off-by: Baruch Siach Signed-off-by: Sascha Hauer Signed-off-by: Greg Kroah-Hartman --- arch/arm/plat-mxc/gpio.c | 8 ++++++++ arch/arm/plat-mxc/include/mach/gpio.h | 1 + 2 files changed, 9 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c index cfc4a8b43e6a..c47aa88cc83e 100644 --- a/arch/arm/plat-mxc/gpio.c +++ b/arch/arm/plat-mxc/gpio.c @@ -223,13 +223,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) @@ -238,9 +241,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) @@ -294,6 +300,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 ); diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h index 894d2f87c856..6bd932c3e4e3 100644 --- a/arch/arm/plat-mxc/include/mach/gpio.h +++ b/arch/arm/plat-mxc/include/mach/gpio.h @@ -36,6 +36,7 @@ struct mxc_gpio_port { int virtual_irq_start; struct gpio_chip chip; u32 both_edges; + spinlock_t lock; }; int mxc_gpio_init(struct mxc_gpio_port*, int); -- cgit v1.2.3