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>
This commit is contained in:
		
					parent
					
						
							
								ef93f1443c
							
						
					
				
			
			
				commit
				
					
						14cb0deb66
					
				
			
		
					 2 changed files with 9 additions and 0 deletions
				
			
		|  | @ -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 ); | ||||
| 
 | ||||
|  |  | |||
|  | @ -37,6 +37,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); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Baruch Siach
				Baruch Siach