diff options
Diffstat (limited to 'arch/arm/plat-mxc/gpio.c')
| -rw-r--r-- | arch/arm/plat-mxc/gpio.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c index 71437c61cfd7..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 | ||
| 226 | static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | 229 | 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) | |||
| 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 | ||
| 237 | static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset) | 243 | 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) | |||
| 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 | ||
| @@ -292,6 +300,12 @@ int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt) | |||
| 292 | /* setup one handler for each entry */ | 300 | /* setup one handler for each entry */ |
| 293 | set_irq_chained_handler(port[i].irq, mx3_gpio_irq_handler); | 301 | set_irq_chained_handler(port[i].irq, mx3_gpio_irq_handler); |
| 294 | set_irq_data(port[i].irq, &port[i]); | 302 | set_irq_data(port[i].irq, &port[i]); |
| 303 | if (port[i].irq_high) { | ||
| 304 | /* setup handler for GPIO 16 to 31 */ | ||
| 305 | set_irq_chained_handler(port[i].irq_high, | ||
| 306 | mx3_gpio_irq_handler); | ||
| 307 | set_irq_data(port[i].irq_high, &port[i]); | ||
| 308 | } | ||
| 295 | } | 309 | } |
| 296 | } | 310 | } |
| 297 | 311 | ||
