diff options
Diffstat (limited to 'drivers/gpio/gpio-rcar.c')
-rw-r--r-- | drivers/gpio/gpio-rcar.c | 63 |
1 files changed, 46 insertions, 17 deletions
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index c49522efa7b3..fd3977465948 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c | |||
@@ -14,6 +14,7 @@ | |||
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> | ||
17 | #include <linux/err.h> | 18 | #include <linux/err.h> |
18 | #include <linux/gpio.h> | 19 | #include <linux/gpio.h> |
19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
@@ -37,20 +38,22 @@ struct gpio_rcar_priv { | |||
37 | struct platform_device *pdev; | 38 | struct platform_device *pdev; |
38 | struct gpio_chip gpio_chip; | 39 | struct gpio_chip gpio_chip; |
39 | struct irq_chip irq_chip; | 40 | struct irq_chip irq_chip; |
41 | unsigned int irq_parent; | ||
42 | struct clk *clk; | ||
40 | }; | 43 | }; |
41 | 44 | ||
42 | #define IOINTSEL 0x00 | 45 | #define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */ |
43 | #define INOUTSEL 0x04 | 46 | #define INOUTSEL 0x04 /* General Input/Output Switching Register */ |
44 | #define OUTDT 0x08 | 47 | #define OUTDT 0x08 /* General Output Register */ |
45 | #define INDT 0x0c | 48 | #define INDT 0x0c /* General Input Register */ |
46 | #define INTDT 0x10 | 49 | #define INTDT 0x10 /* Interrupt Display Register */ |
47 | #define INTCLR 0x14 | 50 | #define INTCLR 0x14 /* Interrupt Clear Register */ |
48 | #define INTMSK 0x18 | 51 | #define INTMSK 0x18 /* Interrupt Mask Register */ |
49 | #define MSKCLR 0x1c | 52 | #define MSKCLR 0x1c /* Interrupt Mask Clear Register */ |
50 | #define POSNEG 0x20 | 53 | #define POSNEG 0x20 /* Positive/Negative Logic Select Register */ |
51 | #define EDGLEVEL 0x24 | 54 | #define EDGLEVEL 0x24 /* Edge/level Select Register */ |
52 | #define FILONOFF 0x28 | 55 | #define FILONOFF 0x28 /* Chattering Prevention On/Off Register */ |
53 | #define BOTHEDGE 0x4c | 56 | #define BOTHEDGE 0x4c /* One Edge/Both Edge Select Register */ |
54 | 57 | ||
55 | #define RCAR_MAX_GPIO_PER_BANK 32 | 58 | #define RCAR_MAX_GPIO_PER_BANK 32 |
56 | 59 | ||
@@ -169,6 +172,25 @@ static int gpio_rcar_irq_set_type(struct irq_data *d, unsigned int type) | |||
169 | return 0; | 172 | return 0; |
170 | } | 173 | } |
171 | 174 | ||
175 | static int gpio_rcar_irq_set_wake(struct irq_data *d, unsigned int on) | ||
176 | { | ||
177 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | ||
178 | struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv, | ||
179 | gpio_chip); | ||
180 | |||
181 | irq_set_irq_wake(p->irq_parent, on); | ||
182 | |||
183 | if (!p->clk) | ||
184 | return 0; | ||
185 | |||
186 | if (on) | ||
187 | clk_enable(p->clk); | ||
188 | else | ||
189 | clk_disable(p->clk); | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
172 | static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) | 194 | static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) |
173 | { | 195 | { |
174 | struct gpio_rcar_priv *p = dev_id; | 196 | struct gpio_rcar_priv *p = dev_id; |
@@ -367,6 +389,12 @@ static int gpio_rcar_probe(struct platform_device *pdev) | |||
367 | 389 | ||
368 | platform_set_drvdata(pdev, p); | 390 | platform_set_drvdata(pdev, p); |
369 | 391 | ||
392 | p->clk = devm_clk_get(dev, NULL); | ||
393 | if (IS_ERR(p->clk)) { | ||
394 | dev_warn(dev, "unable to get clock\n"); | ||
395 | p->clk = NULL; | ||
396 | } | ||
397 | |||
370 | pm_runtime_enable(dev); | 398 | pm_runtime_enable(dev); |
371 | pm_runtime_get_sync(dev); | 399 | pm_runtime_get_sync(dev); |
372 | 400 | ||
@@ -404,8 +432,8 @@ static int gpio_rcar_probe(struct platform_device *pdev) | |||
404 | irq_chip->irq_mask = gpio_rcar_irq_disable; | 432 | irq_chip->irq_mask = gpio_rcar_irq_disable; |
405 | irq_chip->irq_unmask = gpio_rcar_irq_enable; | 433 | irq_chip->irq_unmask = gpio_rcar_irq_enable; |
406 | irq_chip->irq_set_type = gpio_rcar_irq_set_type; | 434 | irq_chip->irq_set_type = gpio_rcar_irq_set_type; |
407 | irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED | 435 | irq_chip->irq_set_wake = gpio_rcar_irq_set_wake; |
408 | | IRQCHIP_MASK_ON_SUSPEND; | 436 | irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND; |
409 | 437 | ||
410 | ret = gpiochip_add(gpio_chip); | 438 | ret = gpiochip_add(gpio_chip); |
411 | if (ret) { | 439 | if (ret) { |
@@ -413,13 +441,14 @@ static int gpio_rcar_probe(struct platform_device *pdev) | |||
413 | goto err0; | 441 | goto err0; |
414 | } | 442 | } |
415 | 443 | ||
416 | ret = gpiochip_irqchip_add(&p->gpio_chip, irq_chip, p->config.irq_base, | 444 | ret = gpiochip_irqchip_add(gpio_chip, irq_chip, p->config.irq_base, |
417 | handle_level_irq, IRQ_TYPE_NONE); | 445 | handle_level_irq, IRQ_TYPE_NONE); |
418 | if (ret) { | 446 | if (ret) { |
419 | dev_err(dev, "cannot add irqchip\n"); | 447 | dev_err(dev, "cannot add irqchip\n"); |
420 | goto err1; | 448 | goto err1; |
421 | } | 449 | } |
422 | 450 | ||
451 | p->irq_parent = irq->start; | ||
423 | if (devm_request_irq(dev, irq->start, gpio_rcar_irq_handler, | 452 | if (devm_request_irq(dev, irq->start, gpio_rcar_irq_handler, |
424 | IRQF_SHARED, name, p)) { | 453 | IRQF_SHARED, name, p)) { |
425 | dev_err(dev, "failed to request IRQ\n"); | 454 | dev_err(dev, "failed to request IRQ\n"); |
@@ -431,7 +460,7 @@ static int gpio_rcar_probe(struct platform_device *pdev) | |||
431 | 460 | ||
432 | /* warn in case of mismatch if irq base is specified */ | 461 | /* warn in case of mismatch if irq base is specified */ |
433 | if (p->config.irq_base) { | 462 | if (p->config.irq_base) { |
434 | ret = irq_find_mapping(p->gpio_chip.irqdomain, 0); | 463 | ret = irq_find_mapping(gpio_chip->irqdomain, 0); |
435 | if (p->config.irq_base != ret) | 464 | if (p->config.irq_base != ret) |
436 | dev_warn(dev, "irq base mismatch (%u/%u)\n", | 465 | dev_warn(dev, "irq base mismatch (%u/%u)\n", |
437 | p->config.irq_base, ret); | 466 | p->config.irq_base, ret); |
@@ -447,7 +476,7 @@ static int gpio_rcar_probe(struct platform_device *pdev) | |||
447 | return 0; | 476 | return 0; |
448 | 477 | ||
449 | err1: | 478 | err1: |
450 | gpiochip_remove(&p->gpio_chip); | 479 | gpiochip_remove(gpio_chip); |
451 | err0: | 480 | err0: |
452 | pm_runtime_put(dev); | 481 | pm_runtime_put(dev); |
453 | pm_runtime_disable(dev); | 482 | pm_runtime_disable(dev); |