diff options
author | Shawn Guo <shawn.guo@linaro.org> | 2011-06-06 01:22:41 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2011-06-06 12:01:19 -0400 |
commit | 2ce420da39078a6135d1c004a0e4436fdc1458b4 (patch) | |
tree | 1f46faaf625ee24a996ad026f88b62ae02ddcda6 | |
parent | b78d8e59a6f611e229fab8ec3014c58eba975000 (diff) |
gpio/mxc: convert gpio-mxc to use basic_mmio_gpio library
The gpio-mxc controller complies with basic_mmio_gpio library. The
patch convert the driver to use the library.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Acked-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-rw-r--r-- | drivers/gpio/Kconfig | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-mxc.c | 83 |
2 files changed, 15 insertions, 69 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 1ee725aa021d..57d7bc547f4b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -100,6 +100,7 @@ config GPIO_MXS | |||
100 | config GPIO_MXC | 100 | config GPIO_MXC |
101 | def_bool y | 101 | def_bool y |
102 | depends on ARCH_MXC | 102 | depends on ARCH_MXC |
103 | select GPIO_BASIC_MMIO_CORE | ||
103 | 104 | ||
104 | config GPIO_PLAT_SAMSUNG | 105 | config GPIO_PLAT_SAMSUNG |
105 | bool "Samsung SoCs GPIO library support" | 106 | bool "Samsung SoCs GPIO library support" |
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 844079a83f25..b351952893bb 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/gpio.h> | 26 | #include <linux/gpio.h> |
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/basic_mmio_gpio.h> | ||
29 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
30 | #include <asm-generic/bug.h> | 31 | #include <asm-generic/bug.h> |
31 | 32 | ||
@@ -35,9 +36,8 @@ struct mxc_gpio_port { | |||
35 | int irq; | 36 | int irq; |
36 | int irq_high; | 37 | int irq_high; |
37 | int virtual_irq_start; | 38 | int virtual_irq_start; |
38 | struct gpio_chip chip; | 39 | struct bgpio_chip bgc; |
39 | u32 both_edges; | 40 | u32 both_edges; |
40 | spinlock_t lock; | ||
41 | }; | 41 | }; |
42 | 42 | ||
43 | /* | 43 | /* |
@@ -101,8 +101,6 @@ static void gpio_unmask_irq(struct irq_data *d) | |||
101 | _set_gpio_irqenable(port, gpio & 0x1f, 1); | 101 | _set_gpio_irqenable(port, gpio & 0x1f, 1); |
102 | } | 102 | } |
103 | 103 | ||
104 | static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset); | ||
105 | |||
106 | static int gpio_set_irq_type(struct irq_data *d, u32 type) | 104 | static int gpio_set_irq_type(struct irq_data *d, u32 type) |
107 | { | 105 | { |
108 | u32 gpio = irq_to_gpio(d->irq); | 106 | u32 gpio = irq_to_gpio(d->irq); |
@@ -120,7 +118,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) | |||
120 | edge = GPIO_INT_FALL_EDGE; | 118 | edge = GPIO_INT_FALL_EDGE; |
121 | break; | 119 | break; |
122 | case IRQ_TYPE_EDGE_BOTH: | 120 | case IRQ_TYPE_EDGE_BOTH: |
123 | val = mxc_gpio_get(&port->chip, gpio & 31); | 121 | val = gpio_get_value(gpio & 31); |
124 | if (val) { | 122 | if (val) { |
125 | edge = GPIO_INT_LOW_LEV; | 123 | edge = GPIO_INT_LOW_LEV; |
126 | pr_debug("mxc: set GPIO %d to low trigger\n", gpio); | 124 | pr_debug("mxc: set GPIO %d to low trigger\n", gpio); |
@@ -259,60 +257,6 @@ static struct irq_chip gpio_irq_chip = { | |||
259 | .irq_set_wake = gpio_set_wake_irq, | 257 | .irq_set_wake = gpio_set_wake_irq, |
260 | }; | 258 | }; |
261 | 259 | ||
262 | static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset, | ||
263 | int dir) | ||
264 | { | ||
265 | struct mxc_gpio_port *port = | ||
266 | container_of(chip, struct mxc_gpio_port, chip); | ||
267 | u32 l; | ||
268 | unsigned long flags; | ||
269 | |||
270 | spin_lock_irqsave(&port->lock, flags); | ||
271 | l = readl(port->base + GPIO_GDIR); | ||
272 | if (dir) | ||
273 | l |= 1 << offset; | ||
274 | else | ||
275 | l &= ~(1 << offset); | ||
276 | writel(l, port->base + GPIO_GDIR); | ||
277 | spin_unlock_irqrestore(&port->lock, flags); | ||
278 | } | ||
279 | |||
280 | static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
281 | { | ||
282 | struct mxc_gpio_port *port = | ||
283 | container_of(chip, struct mxc_gpio_port, chip); | ||
284 | void __iomem *reg = port->base + GPIO_DR; | ||
285 | u32 l; | ||
286 | unsigned long flags; | ||
287 | |||
288 | spin_lock_irqsave(&port->lock, flags); | ||
289 | l = (readl(reg) & (~(1 << offset))) | (!!value << offset); | ||
290 | writel(l, reg); | ||
291 | spin_unlock_irqrestore(&port->lock, flags); | ||
292 | } | ||
293 | |||
294 | static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
295 | { | ||
296 | struct mxc_gpio_port *port = | ||
297 | container_of(chip, struct mxc_gpio_port, chip); | ||
298 | |||
299 | return (readl(port->base + GPIO_PSR) >> offset) & 1; | ||
300 | } | ||
301 | |||
302 | static int mxc_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | ||
303 | { | ||
304 | _set_gpio_direction(chip, offset, 0); | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static int mxc_gpio_direction_output(struct gpio_chip *chip, | ||
309 | unsigned offset, int value) | ||
310 | { | ||
311 | mxc_gpio_set(chip, offset, value); | ||
312 | _set_gpio_direction(chip, offset, 1); | ||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | /* | 260 | /* |
317 | * This lock class tells lockdep that GPIO irqs are in a different | 261 | * This lock class tells lockdep that GPIO irqs are in a different |
318 | * category than their parents, so it won't report false recursion. | 262 | * category than their parents, so it won't report false recursion. |
@@ -385,24 +329,25 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev) | |||
385 | } | 329 | } |
386 | } | 330 | } |
387 | 331 | ||
388 | /* register gpio chip */ | 332 | err = bgpio_init(&port->bgc, &pdev->dev, 4, |
389 | port->chip.direction_input = mxc_gpio_direction_input; | 333 | port->base + GPIO_PSR, |
390 | port->chip.direction_output = mxc_gpio_direction_output; | 334 | port->base + GPIO_DR, NULL, |
391 | port->chip.get = mxc_gpio_get; | 335 | port->base + GPIO_GDIR, NULL, false); |
392 | port->chip.set = mxc_gpio_set; | 336 | if (err) |
393 | port->chip.base = pdev->id * 32; | 337 | goto out_iounmap; |
394 | port->chip.ngpio = 32; | ||
395 | 338 | ||
396 | spin_lock_init(&port->lock); | 339 | port->bgc.gc.base = pdev->id * 32; |
397 | 340 | ||
398 | err = gpiochip_add(&port->chip); | 341 | err = gpiochip_add(&port->bgc.gc); |
399 | if (err) | 342 | if (err) |
400 | goto out_iounmap; | 343 | goto out_bgpio_remove; |
401 | 344 | ||
402 | list_add_tail(&port->node, &mxc_gpio_ports); | 345 | list_add_tail(&port->node, &mxc_gpio_ports); |
403 | 346 | ||
404 | return 0; | 347 | return 0; |
405 | 348 | ||
349 | out_bgpio_remove: | ||
350 | bgpio_remove(&port->bgc); | ||
406 | out_iounmap: | 351 | out_iounmap: |
407 | iounmap(port->base); | 352 | iounmap(port->base); |
408 | out_release_mem: | 353 | out_release_mem: |