aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorBaruch Siach <baruch@tkos.co.il>2010-07-06 07:03:22 -0400
committerSascha Hauer <s.hauer@pengutronix.de>2010-07-28 03:22:51 -0400
commit14cb0deb66fcfca8fdbef75da8c84b5405a8c767 (patch)
tree56f48e64c92f694c75a126a4bac0dee64d8f6b60 /arch
parentef93f1443c014e0d6dd7a5b1e592a02aa266f001 (diff)
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 <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>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/plat-mxc/gpio.c8
-rw-r--r--arch/arm/plat-mxc/include/mach/gpio.h1
2 files changed, 9 insertions, 0 deletions
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
index 11dc06190b5d..57ec4a896a5d 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,
214 struct mxc_gpio_port *port = 214 struct mxc_gpio_port *port =
215 container_of(chip, struct mxc_gpio_port, chip); 215 container_of(chip, struct mxc_gpio_port, chip);
216 u32 l; 216 u32 l;
217 unsigned long flags;
217 218
219 spin_lock_irqsave(&port->lock, flags);
218 l = __raw_readl(port->base + GPIO_GDIR); 220 l = __raw_readl(port->base + GPIO_GDIR);
219 if (dir) 221 if (dir)
220 l |= 1 << offset; 222 l |= 1 << offset;
221 else 223 else
222 l &= ~(1 << offset); 224 l &= ~(1 << offset);
223 __raw_writel(l, port->base + GPIO_GDIR); 225 __raw_writel(l, port->base + GPIO_GDIR);
226 spin_unlock_irqrestore(&port->lock, flags);
224} 227}
225 228
226static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 229static 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)
229 container_of(chip, struct mxc_gpio_port, chip); 232 container_of(chip, struct mxc_gpio_port, chip);
230 void __iomem *reg = port->base + GPIO_DR; 233 void __iomem *reg = port->base + GPIO_DR;
231 u32 l; 234 u32 l;
235 unsigned long flags;
232 236
237 spin_lock_irqsave(&port->lock, flags);
233 l = (__raw_readl(reg) & (~(1 << offset))) | (value << offset); 238 l = (__raw_readl(reg) & (~(1 << offset))) | (value << offset);
234 __raw_writel(l, reg); 239 __raw_writel(l, reg);
240 spin_unlock_irqrestore(&port->lock, flags);
235} 241}
236 242
237static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset) 243static 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)
285 port[i].chip.base = i * 32; 291 port[i].chip.base = i * 32;
286 port[i].chip.ngpio = 32; 292 port[i].chip.ngpio = 32;
287 293
294 spin_lock_init(&port[i].lock);
295
288 /* its a serious configuration bug when it fails */ 296 /* its a serious configuration bug when it fails */
289 BUG_ON( gpiochip_add(&port[i].chip) < 0 ); 297 BUG_ON( gpiochip_add(&port[i].chip) < 0 );
290 298
diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h
index 9541ecbfd22c..661fbc605759 100644
--- a/arch/arm/plat-mxc/include/mach/gpio.h
+++ b/arch/arm/plat-mxc/include/mach/gpio.h
@@ -37,6 +37,7 @@ struct mxc_gpio_port {
37 int virtual_irq_start; 37 int virtual_irq_start;
38 struct gpio_chip chip; 38 struct gpio_chip chip;
39 u32 both_edges; 39 u32 both_edges;
40 spinlock_t lock;
40}; 41};
41 42
42int mxc_gpio_init(struct mxc_gpio_port*, int); 43int mxc_gpio_init(struct mxc_gpio_port*, int);