diff options
author | Baruch Siach <baruch@tkos.co.il> | 2010-07-06 14:03:22 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 10:20:37 -0700 |
commit | 96f6b7b0a8d82d9016ecf241aa78c2c264b77412 (patch) | |
tree | 1524ddd96be2f686ee7fb83b84bb8ed74f92edc3 /arch | |
parent | 250fac9f6418d573e8031ad0ad0028585034e80d (diff) |
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 <j.beisert@pengutronix.de>
Cc: Daniel Mack <daniel@caiaq.de>
Reported-by: rpkamiak@rockwellcollins.com
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/plat-mxc/gpio.c | 8 | ||||
-rw-r--r-- | arch/arm/plat-mxc/include/mach/gpio.h | 1 |
2 files changed, 9 insertions, 0 deletions
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c index cfc4a8b43e6..c47aa88cc83 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 894d2f87c85..6bd932c3e4e 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); |