diff options
Diffstat (limited to 'drivers/gpio/gpio-rcar.c')
-rw-r--r-- | drivers/gpio/gpio-rcar.c | 38 |
1 files changed, 16 insertions, 22 deletions
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index e76de57dd617..ebaea8b1594b 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c | |||
@@ -14,7 +14,6 @@ | |||
14 | * GNU General Public License for more details. | 14 | * GNU General Public License for more details. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/clk.h> | ||
18 | #include <linux/err.h> | 17 | #include <linux/err.h> |
19 | #include <linux/gpio.h> | 18 | #include <linux/gpio.h> |
20 | #include <linux/init.h> | 19 | #include <linux/init.h> |
@@ -37,10 +36,9 @@ struct gpio_rcar_priv { | |||
37 | struct platform_device *pdev; | 36 | struct platform_device *pdev; |
38 | struct gpio_chip gpio_chip; | 37 | struct gpio_chip gpio_chip; |
39 | struct irq_chip irq_chip; | 38 | struct irq_chip irq_chip; |
40 | struct clk *clk; | ||
41 | unsigned int irq_parent; | 39 | unsigned int irq_parent; |
40 | atomic_t wakeup_path; | ||
42 | bool has_both_edge_trigger; | 41 | bool has_both_edge_trigger; |
43 | bool needs_clk; | ||
44 | }; | 42 | }; |
45 | 43 | ||
46 | #define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */ | 44 | #define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */ |
@@ -186,13 +184,10 @@ static int gpio_rcar_irq_set_wake(struct irq_data *d, unsigned int on) | |||
186 | } | 184 | } |
187 | } | 185 | } |
188 | 186 | ||
189 | if (!p->clk) | ||
190 | return 0; | ||
191 | |||
192 | if (on) | 187 | if (on) |
193 | clk_enable(p->clk); | 188 | atomic_inc(&p->wakeup_path); |
194 | else | 189 | else |
195 | clk_disable(p->clk); | 190 | atomic_dec(&p->wakeup_path); |
196 | 191 | ||
197 | return 0; | 192 | return 0; |
198 | } | 193 | } |
@@ -330,17 +325,14 @@ static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset, | |||
330 | 325 | ||
331 | struct gpio_rcar_info { | 326 | struct gpio_rcar_info { |
332 | bool has_both_edge_trigger; | 327 | bool has_both_edge_trigger; |
333 | bool needs_clk; | ||
334 | }; | 328 | }; |
335 | 329 | ||
336 | static const struct gpio_rcar_info gpio_rcar_info_gen1 = { | 330 | static const struct gpio_rcar_info gpio_rcar_info_gen1 = { |
337 | .has_both_edge_trigger = false, | 331 | .has_both_edge_trigger = false, |
338 | .needs_clk = false, | ||
339 | }; | 332 | }; |
340 | 333 | ||
341 | static const struct gpio_rcar_info gpio_rcar_info_gen2 = { | 334 | static const struct gpio_rcar_info gpio_rcar_info_gen2 = { |
342 | .has_both_edge_trigger = true, | 335 | .has_both_edge_trigger = true, |
343 | .needs_clk = true, | ||
344 | }; | 336 | }; |
345 | 337 | ||
346 | static const struct of_device_id gpio_rcar_of_table[] = { | 338 | static const struct of_device_id gpio_rcar_of_table[] = { |
@@ -403,7 +395,6 @@ static int gpio_rcar_parse_dt(struct gpio_rcar_priv *p, unsigned int *npins) | |||
403 | ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args); | 395 | ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args); |
404 | *npins = ret == 0 ? args.args[2] : RCAR_MAX_GPIO_PER_BANK; | 396 | *npins = ret == 0 ? args.args[2] : RCAR_MAX_GPIO_PER_BANK; |
405 | p->has_both_edge_trigger = info->has_both_edge_trigger; | 397 | p->has_both_edge_trigger = info->has_both_edge_trigger; |
406 | p->needs_clk = info->needs_clk; | ||
407 | 398 | ||
408 | if (*npins == 0 || *npins > RCAR_MAX_GPIO_PER_BANK) { | 399 | if (*npins == 0 || *npins > RCAR_MAX_GPIO_PER_BANK) { |
409 | dev_warn(&p->pdev->dev, | 400 | dev_warn(&p->pdev->dev, |
@@ -440,16 +431,6 @@ static int gpio_rcar_probe(struct platform_device *pdev) | |||
440 | 431 | ||
441 | platform_set_drvdata(pdev, p); | 432 | platform_set_drvdata(pdev, p); |
442 | 433 | ||
443 | p->clk = devm_clk_get(dev, NULL); | ||
444 | if (IS_ERR(p->clk)) { | ||
445 | if (p->needs_clk) { | ||
446 | dev_err(dev, "unable to get clock\n"); | ||
447 | ret = PTR_ERR(p->clk); | ||
448 | goto err0; | ||
449 | } | ||
450 | p->clk = NULL; | ||
451 | } | ||
452 | |||
453 | pm_runtime_enable(dev); | 434 | pm_runtime_enable(dev); |
454 | 435 | ||
455 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 436 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
@@ -531,11 +512,24 @@ static int gpio_rcar_remove(struct platform_device *pdev) | |||
531 | return 0; | 512 | return 0; |
532 | } | 513 | } |
533 | 514 | ||
515 | static int __maybe_unused gpio_rcar_suspend(struct device *dev) | ||
516 | { | ||
517 | struct gpio_rcar_priv *p = dev_get_drvdata(dev); | ||
518 | |||
519 | if (atomic_read(&p->wakeup_path)) | ||
520 | device_set_wakeup_path(dev); | ||
521 | |||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static SIMPLE_DEV_PM_OPS(gpio_rcar_pm_ops, gpio_rcar_suspend, NULL); | ||
526 | |||
534 | static struct platform_driver gpio_rcar_device_driver = { | 527 | static struct platform_driver gpio_rcar_device_driver = { |
535 | .probe = gpio_rcar_probe, | 528 | .probe = gpio_rcar_probe, |
536 | .remove = gpio_rcar_remove, | 529 | .remove = gpio_rcar_remove, |
537 | .driver = { | 530 | .driver = { |
538 | .name = "gpio_rcar", | 531 | .name = "gpio_rcar", |
532 | .pm = &gpio_rcar_pm_ops, | ||
539 | .of_match_table = of_match_ptr(gpio_rcar_of_table), | 533 | .of_match_table = of_match_ptr(gpio_rcar_of_table), |
540 | } | 534 | } |
541 | }; | 535 | }; |