diff options
Diffstat (limited to 'drivers/gpio/gpio-tegra.c')
-rw-r--r-- | drivers/gpio/gpio-tegra.c | 43 |
1 files changed, 25 insertions, 18 deletions
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index d982593d7563..5389be8c2b51 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/irqdomain.h> | 28 | #include <linux/irqdomain.h> |
29 | #include <linux/pinctrl/consumer.h> | 29 | #include <linux/pinctrl/consumer.h> |
30 | #include <linux/pm.h> | ||
30 | 31 | ||
31 | #include <asm/mach/irq.h> | 32 | #include <asm/mach/irq.h> |
32 | 33 | ||
@@ -64,7 +65,7 @@ struct tegra_gpio_bank { | |||
64 | int bank; | 65 | int bank; |
65 | int irq; | 66 | int irq; |
66 | spinlock_t lvl_lock[4]; | 67 | spinlock_t lvl_lock[4]; |
67 | #ifdef CONFIG_PM | 68 | #ifdef CONFIG_PM_SLEEP |
68 | u32 cnf[4]; | 69 | u32 cnf[4]; |
69 | u32 out[4]; | 70 | u32 out[4]; |
70 | u32 oe[4]; | 71 | u32 oe[4]; |
@@ -109,20 +110,18 @@ static void tegra_gpio_enable(int gpio) | |||
109 | { | 110 | { |
110 | tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1); | 111 | tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1); |
111 | } | 112 | } |
112 | EXPORT_SYMBOL_GPL(tegra_gpio_enable); | ||
113 | 113 | ||
114 | static void tegra_gpio_disable(int gpio) | 114 | static void tegra_gpio_disable(int gpio) |
115 | { | 115 | { |
116 | tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0); | 116 | tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0); |
117 | } | 117 | } |
118 | EXPORT_SYMBOL_GPL(tegra_gpio_disable); | ||
119 | 118 | ||
120 | int tegra_gpio_request(struct gpio_chip *chip, unsigned offset) | 119 | static int tegra_gpio_request(struct gpio_chip *chip, unsigned offset) |
121 | { | 120 | { |
122 | return pinctrl_request_gpio(offset); | 121 | return pinctrl_request_gpio(offset); |
123 | } | 122 | } |
124 | 123 | ||
125 | void tegra_gpio_free(struct gpio_chip *chip, unsigned offset) | 124 | static void tegra_gpio_free(struct gpio_chip *chip, unsigned offset) |
126 | { | 125 | { |
127 | pinctrl_free_gpio(offset); | 126 | pinctrl_free_gpio(offset); |
128 | tegra_gpio_disable(offset); | 127 | tegra_gpio_disable(offset); |
@@ -135,6 +134,11 @@ static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |||
135 | 134 | ||
136 | static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset) | 135 | static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset) |
137 | { | 136 | { |
137 | /* If gpio is in output mode then read from the out value */ | ||
138 | if ((tegra_gpio_readl(GPIO_OE(offset)) >> GPIO_BIT(offset)) & 1) | ||
139 | return (tegra_gpio_readl(GPIO_OUT(offset)) >> | ||
140 | GPIO_BIT(offset)) & 0x1; | ||
141 | |||
138 | return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1; | 142 | return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1; |
139 | } | 143 | } |
140 | 144 | ||
@@ -285,8 +289,8 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
285 | 289 | ||
286 | } | 290 | } |
287 | 291 | ||
288 | #ifdef CONFIG_PM | 292 | #ifdef CONFIG_PM_SLEEP |
289 | void tegra_gpio_resume(void) | 293 | static int tegra_gpio_resume(struct device *dev) |
290 | { | 294 | { |
291 | unsigned long flags; | 295 | unsigned long flags; |
292 | int b; | 296 | int b; |
@@ -308,9 +312,10 @@ void tegra_gpio_resume(void) | |||
308 | } | 312 | } |
309 | 313 | ||
310 | local_irq_restore(flags); | 314 | local_irq_restore(flags); |
315 | return 0; | ||
311 | } | 316 | } |
312 | 317 | ||
313 | void tegra_gpio_suspend(void) | 318 | static int tegra_gpio_suspend(struct device *dev) |
314 | { | 319 | { |
315 | unsigned long flags; | 320 | unsigned long flags; |
316 | int b; | 321 | int b; |
@@ -330,6 +335,7 @@ void tegra_gpio_suspend(void) | |||
330 | } | 335 | } |
331 | } | 336 | } |
332 | local_irq_restore(flags); | 337 | local_irq_restore(flags); |
338 | return 0; | ||
333 | } | 339 | } |
334 | 340 | ||
335 | static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable) | 341 | static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable) |
@@ -345,11 +351,15 @@ static struct irq_chip tegra_gpio_irq_chip = { | |||
345 | .irq_mask = tegra_gpio_irq_mask, | 351 | .irq_mask = tegra_gpio_irq_mask, |
346 | .irq_unmask = tegra_gpio_irq_unmask, | 352 | .irq_unmask = tegra_gpio_irq_unmask, |
347 | .irq_set_type = tegra_gpio_irq_set_type, | 353 | .irq_set_type = tegra_gpio_irq_set_type, |
348 | #ifdef CONFIG_PM | 354 | #ifdef CONFIG_PM_SLEEP |
349 | .irq_set_wake = tegra_gpio_wake_enable, | 355 | .irq_set_wake = tegra_gpio_wake_enable, |
350 | #endif | 356 | #endif |
351 | }; | 357 | }; |
352 | 358 | ||
359 | static const struct dev_pm_ops tegra_gpio_pm_ops = { | ||
360 | SET_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume) | ||
361 | }; | ||
362 | |||
353 | struct tegra_gpio_soc_config { | 363 | struct tegra_gpio_soc_config { |
354 | u32 bank_stride; | 364 | u32 bank_stride; |
355 | u32 upper_offset; | 365 | u32 upper_offset; |
@@ -380,7 +390,6 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev) | |||
380 | { | 390 | { |
381 | const struct of_device_id *match; | 391 | const struct of_device_id *match; |
382 | struct tegra_gpio_soc_config *config; | 392 | struct tegra_gpio_soc_config *config; |
383 | int irq_base; | ||
384 | struct resource *res; | 393 | struct resource *res; |
385 | struct tegra_gpio_bank *bank; | 394 | struct tegra_gpio_bank *bank; |
386 | int gpio; | 395 | int gpio; |
@@ -417,14 +426,11 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev) | |||
417 | return -ENODEV; | 426 | return -ENODEV; |
418 | } | 427 | } |
419 | 428 | ||
420 | irq_base = irq_alloc_descs(-1, 0, tegra_gpio_chip.ngpio, 0); | 429 | irq_domain = irq_domain_add_linear(pdev->dev.of_node, |
421 | if (irq_base < 0) { | 430 | tegra_gpio_chip.ngpio, |
422 | dev_err(&pdev->dev, "Couldn't allocate IRQ numbers\n"); | ||
423 | return -ENODEV; | ||
424 | } | ||
425 | irq_domain = irq_domain_add_legacy(pdev->dev.of_node, | ||
426 | tegra_gpio_chip.ngpio, irq_base, 0, | ||
427 | &irq_domain_simple_ops, NULL); | 431 | &irq_domain_simple_ops, NULL); |
432 | if (!irq_domain) | ||
433 | return -ENODEV; | ||
428 | 434 | ||
429 | for (i = 0; i < tegra_gpio_bank_count; i++) { | 435 | for (i = 0; i < tegra_gpio_bank_count; i++) { |
430 | res = platform_get_resource(pdev, IORESOURCE_IRQ, i); | 436 | res = platform_get_resource(pdev, IORESOURCE_IRQ, i); |
@@ -464,7 +470,7 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev) | |||
464 | gpiochip_add(&tegra_gpio_chip); | 470 | gpiochip_add(&tegra_gpio_chip); |
465 | 471 | ||
466 | for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) { | 472 | for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) { |
467 | int irq = irq_find_mapping(irq_domain, gpio); | 473 | int irq = irq_create_mapping(irq_domain, gpio); |
468 | /* No validity check; all Tegra GPIOs are valid IRQs */ | 474 | /* No validity check; all Tegra GPIOs are valid IRQs */ |
469 | 475 | ||
470 | bank = &tegra_gpio_banks[GPIO_BANK(gpio)]; | 476 | bank = &tegra_gpio_banks[GPIO_BANK(gpio)]; |
@@ -493,6 +499,7 @@ static struct platform_driver tegra_gpio_driver = { | |||
493 | .driver = { | 499 | .driver = { |
494 | .name = "tegra-gpio", | 500 | .name = "tegra-gpio", |
495 | .owner = THIS_MODULE, | 501 | .owner = THIS_MODULE, |
502 | .pm = &tegra_gpio_pm_ops, | ||
496 | .of_match_table = tegra_gpio_of_match, | 503 | .of_match_table = tegra_gpio_of_match, |
497 | }, | 504 | }, |
498 | .probe = tegra_gpio_probe, | 505 | .probe = tegra_gpio_probe, |