aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-rcar.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpio-rcar.c')
-rw-r--r--drivers/gpio/gpio-rcar.c63
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
175static 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
172static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) 194static 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
449err1: 478err1:
450 gpiochip_remove(&p->gpio_chip); 479 gpiochip_remove(gpio_chip);
451err0: 480err0:
452 pm_runtime_put(dev); 481 pm_runtime_put(dev);
453 pm_runtime_disable(dev); 482 pm_runtime_disable(dev);