diff options
Diffstat (limited to 'drivers/irqchip/irq-renesas-intc-irqpin.c')
-rw-r--r-- | drivers/irqchip/irq-renesas-intc-irqpin.c | 85 |
1 files changed, 56 insertions, 29 deletions
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c index 3ee78f02e5d7..542e850f4946 100644 --- a/drivers/irqchip/irq-renesas-intc-irqpin.c +++ b/drivers/irqchip/irq-renesas-intc-irqpin.c | |||
@@ -17,6 +17,7 @@ | |||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/clk.h> | ||
20 | #include <linux/init.h> | 21 | #include <linux/init.h> |
21 | #include <linux/of.h> | 22 | #include <linux/of.h> |
22 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
@@ -30,6 +31,7 @@ | |||
30 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
31 | #include <linux/module.h> | 32 | #include <linux/module.h> |
32 | #include <linux/platform_data/irq-renesas-intc-irqpin.h> | 33 | #include <linux/platform_data/irq-renesas-intc-irqpin.h> |
34 | #include <linux/pm_runtime.h> | ||
33 | 35 | ||
34 | #define INTC_IRQPIN_MAX 8 /* maximum 8 interrupts per driver instance */ | 36 | #define INTC_IRQPIN_MAX 8 /* maximum 8 interrupts per driver instance */ |
35 | 37 | ||
@@ -75,6 +77,7 @@ struct intc_irqpin_priv { | |||
75 | struct platform_device *pdev; | 77 | struct platform_device *pdev; |
76 | struct irq_chip irq_chip; | 78 | struct irq_chip irq_chip; |
77 | struct irq_domain *irq_domain; | 79 | struct irq_domain *irq_domain; |
80 | struct clk *clk; | ||
78 | bool shared_irqs; | 81 | bool shared_irqs; |
79 | u8 shared_irq_mask; | 82 | u8 shared_irq_mask; |
80 | }; | 83 | }; |
@@ -270,6 +273,21 @@ static int intc_irqpin_irq_set_type(struct irq_data *d, unsigned int type) | |||
270 | value ^ INTC_IRQ_SENSE_VALID); | 273 | value ^ INTC_IRQ_SENSE_VALID); |
271 | } | 274 | } |
272 | 275 | ||
276 | static int intc_irqpin_irq_set_wake(struct irq_data *d, unsigned int on) | ||
277 | { | ||
278 | struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d); | ||
279 | |||
280 | if (!p->clk) | ||
281 | return 0; | ||
282 | |||
283 | if (on) | ||
284 | clk_enable(p->clk); | ||
285 | else | ||
286 | clk_disable(p->clk); | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
273 | static irqreturn_t intc_irqpin_irq_handler(int irq, void *dev_id) | 291 | static irqreturn_t intc_irqpin_irq_handler(int irq, void *dev_id) |
274 | { | 292 | { |
275 | struct intc_irqpin_irq *i = dev_id; | 293 | struct intc_irqpin_irq *i = dev_id; |
@@ -329,7 +347,8 @@ static struct irq_domain_ops intc_irqpin_irq_domain_ops = { | |||
329 | 347 | ||
330 | static int intc_irqpin_probe(struct platform_device *pdev) | 348 | static int intc_irqpin_probe(struct platform_device *pdev) |
331 | { | 349 | { |
332 | struct renesas_intc_irqpin_config *pdata = pdev->dev.platform_data; | 350 | struct device *dev = &pdev->dev; |
351 | struct renesas_intc_irqpin_config *pdata = dev->platform_data; | ||
333 | struct intc_irqpin_priv *p; | 352 | struct intc_irqpin_priv *p; |
334 | struct intc_irqpin_iomem *i; | 353 | struct intc_irqpin_iomem *i; |
335 | struct resource *io[INTC_IRQPIN_REG_NR]; | 354 | struct resource *io[INTC_IRQPIN_REG_NR]; |
@@ -337,25 +356,24 @@ static int intc_irqpin_probe(struct platform_device *pdev) | |||
337 | struct irq_chip *irq_chip; | 356 | struct irq_chip *irq_chip; |
338 | void (*enable_fn)(struct irq_data *d); | 357 | void (*enable_fn)(struct irq_data *d); |
339 | void (*disable_fn)(struct irq_data *d); | 358 | void (*disable_fn)(struct irq_data *d); |
340 | const char *name = dev_name(&pdev->dev); | 359 | const char *name = dev_name(dev); |
341 | int ref_irq; | 360 | int ref_irq; |
342 | int ret; | 361 | int ret; |
343 | int k; | 362 | int k; |
344 | 363 | ||
345 | p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); | 364 | p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL); |
346 | if (!p) { | 365 | if (!p) { |
347 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | 366 | dev_err(dev, "failed to allocate driver data\n"); |
348 | ret = -ENOMEM; | 367 | return -ENOMEM; |
349 | goto err0; | ||
350 | } | 368 | } |
351 | 369 | ||
352 | /* deal with driver instance configuration */ | 370 | /* deal with driver instance configuration */ |
353 | if (pdata) { | 371 | if (pdata) { |
354 | memcpy(&p->config, pdata, sizeof(*pdata)); | 372 | memcpy(&p->config, pdata, sizeof(*pdata)); |
355 | } else { | 373 | } else { |
356 | of_property_read_u32(pdev->dev.of_node, "sense-bitfield-width", | 374 | of_property_read_u32(dev->of_node, "sense-bitfield-width", |
357 | &p->config.sense_bitfield_width); | 375 | &p->config.sense_bitfield_width); |
358 | p->config.control_parent = of_property_read_bool(pdev->dev.of_node, | 376 | p->config.control_parent = of_property_read_bool(dev->of_node, |
359 | "control-parent"); | 377 | "control-parent"); |
360 | } | 378 | } |
361 | if (!p->config.sense_bitfield_width) | 379 | if (!p->config.sense_bitfield_width) |
@@ -364,11 +382,20 @@ static int intc_irqpin_probe(struct platform_device *pdev) | |||
364 | p->pdev = pdev; | 382 | p->pdev = pdev; |
365 | platform_set_drvdata(pdev, p); | 383 | platform_set_drvdata(pdev, p); |
366 | 384 | ||
385 | p->clk = devm_clk_get(dev, NULL); | ||
386 | if (IS_ERR(p->clk)) { | ||
387 | dev_warn(dev, "unable to get clock\n"); | ||
388 | p->clk = NULL; | ||
389 | } | ||
390 | |||
391 | pm_runtime_enable(dev); | ||
392 | pm_runtime_get_sync(dev); | ||
393 | |||
367 | /* get hold of manadatory IOMEM */ | 394 | /* get hold of manadatory IOMEM */ |
368 | for (k = 0; k < INTC_IRQPIN_REG_NR; k++) { | 395 | for (k = 0; k < INTC_IRQPIN_REG_NR; k++) { |
369 | io[k] = platform_get_resource(pdev, IORESOURCE_MEM, k); | 396 | io[k] = platform_get_resource(pdev, IORESOURCE_MEM, k); |
370 | if (!io[k]) { | 397 | if (!io[k]) { |
371 | dev_err(&pdev->dev, "not enough IOMEM resources\n"); | 398 | dev_err(dev, "not enough IOMEM resources\n"); |
372 | ret = -EINVAL; | 399 | ret = -EINVAL; |
373 | goto err0; | 400 | goto err0; |
374 | } | 401 | } |
@@ -386,7 +413,7 @@ static int intc_irqpin_probe(struct platform_device *pdev) | |||
386 | 413 | ||
387 | p->number_of_irqs = k; | 414 | p->number_of_irqs = k; |
388 | if (p->number_of_irqs < 1) { | 415 | if (p->number_of_irqs < 1) { |
389 | dev_err(&pdev->dev, "not enough IRQ resources\n"); | 416 | dev_err(dev, "not enough IRQ resources\n"); |
390 | ret = -EINVAL; | 417 | ret = -EINVAL; |
391 | goto err0; | 418 | goto err0; |
392 | } | 419 | } |
@@ -407,15 +434,15 @@ static int intc_irqpin_probe(struct platform_device *pdev) | |||
407 | i->write = intc_irqpin_write32; | 434 | i->write = intc_irqpin_write32; |
408 | break; | 435 | break; |
409 | default: | 436 | default: |
410 | dev_err(&pdev->dev, "IOMEM size mismatch\n"); | 437 | dev_err(dev, "IOMEM size mismatch\n"); |
411 | ret = -EINVAL; | 438 | ret = -EINVAL; |
412 | goto err0; | 439 | goto err0; |
413 | } | 440 | } |
414 | 441 | ||
415 | i->iomem = devm_ioremap_nocache(&pdev->dev, io[k]->start, | 442 | i->iomem = devm_ioremap_nocache(dev, io[k]->start, |
416 | resource_size(io[k])); | 443 | resource_size(io[k])); |
417 | if (!i->iomem) { | 444 | if (!i->iomem) { |
418 | dev_err(&pdev->dev, "failed to remap IOMEM\n"); | 445 | dev_err(dev, "failed to remap IOMEM\n"); |
419 | ret = -ENXIO; | 446 | ret = -ENXIO; |
420 | goto err0; | 447 | goto err0; |
421 | } | 448 | } |
@@ -454,39 +481,36 @@ static int intc_irqpin_probe(struct platform_device *pdev) | |||
454 | irq_chip->name = name; | 481 | irq_chip->name = name; |
455 | irq_chip->irq_mask = disable_fn; | 482 | irq_chip->irq_mask = disable_fn; |
456 | irq_chip->irq_unmask = enable_fn; | 483 | irq_chip->irq_unmask = enable_fn; |
457 | irq_chip->irq_enable = enable_fn; | ||
458 | irq_chip->irq_disable = disable_fn; | ||
459 | irq_chip->irq_set_type = intc_irqpin_irq_set_type; | 484 | irq_chip->irq_set_type = intc_irqpin_irq_set_type; |
460 | irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; | 485 | irq_chip->irq_set_wake = intc_irqpin_irq_set_wake; |
486 | irq_chip->flags = IRQCHIP_MASK_ON_SUSPEND; | ||
461 | 487 | ||
462 | p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, | 488 | p->irq_domain = irq_domain_add_simple(dev->of_node, |
463 | p->number_of_irqs, | 489 | p->number_of_irqs, |
464 | p->config.irq_base, | 490 | p->config.irq_base, |
465 | &intc_irqpin_irq_domain_ops, p); | 491 | &intc_irqpin_irq_domain_ops, p); |
466 | if (!p->irq_domain) { | 492 | if (!p->irq_domain) { |
467 | ret = -ENXIO; | 493 | ret = -ENXIO; |
468 | dev_err(&pdev->dev, "cannot initialize irq domain\n"); | 494 | dev_err(dev, "cannot initialize irq domain\n"); |
469 | goto err0; | 495 | goto err0; |
470 | } | 496 | } |
471 | 497 | ||
472 | if (p->shared_irqs) { | 498 | if (p->shared_irqs) { |
473 | /* request one shared interrupt */ | 499 | /* request one shared interrupt */ |
474 | if (devm_request_irq(&pdev->dev, p->irq[0].requested_irq, | 500 | if (devm_request_irq(dev, p->irq[0].requested_irq, |
475 | intc_irqpin_shared_irq_handler, | 501 | intc_irqpin_shared_irq_handler, |
476 | IRQF_SHARED, name, p)) { | 502 | IRQF_SHARED, name, p)) { |
477 | dev_err(&pdev->dev, "failed to request low IRQ\n"); | 503 | dev_err(dev, "failed to request low IRQ\n"); |
478 | ret = -ENOENT; | 504 | ret = -ENOENT; |
479 | goto err1; | 505 | goto err1; |
480 | } | 506 | } |
481 | } else { | 507 | } else { |
482 | /* request interrupts one by one */ | 508 | /* request interrupts one by one */ |
483 | for (k = 0; k < p->number_of_irqs; k++) { | 509 | for (k = 0; k < p->number_of_irqs; k++) { |
484 | if (devm_request_irq(&pdev->dev, | 510 | if (devm_request_irq(dev, p->irq[k].requested_irq, |
485 | p->irq[k].requested_irq, | 511 | intc_irqpin_irq_handler, 0, name, |
486 | intc_irqpin_irq_handler, | 512 | &p->irq[k])) { |
487 | 0, name, &p->irq[k])) { | 513 | dev_err(dev, "failed to request low IRQ\n"); |
488 | dev_err(&pdev->dev, | ||
489 | "failed to request low IRQ\n"); | ||
490 | ret = -ENOENT; | 514 | ret = -ENOENT; |
491 | goto err1; | 515 | goto err1; |
492 | } | 516 | } |
@@ -497,12 +521,12 @@ static int intc_irqpin_probe(struct platform_device *pdev) | |||
497 | for (k = 0; k < p->number_of_irqs; k++) | 521 | for (k = 0; k < p->number_of_irqs; k++) |
498 | intc_irqpin_mask_unmask_prio(p, k, 0); | 522 | intc_irqpin_mask_unmask_prio(p, k, 0); |
499 | 523 | ||
500 | dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs); | 524 | dev_info(dev, "driving %d irqs\n", p->number_of_irqs); |
501 | 525 | ||
502 | /* warn in case of mismatch if irq base is specified */ | 526 | /* warn in case of mismatch if irq base is specified */ |
503 | if (p->config.irq_base) { | 527 | if (p->config.irq_base) { |
504 | if (p->config.irq_base != p->irq[0].domain_irq) | 528 | if (p->config.irq_base != p->irq[0].domain_irq) |
505 | dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n", | 529 | dev_warn(dev, "irq base mismatch (%d/%d)\n", |
506 | p->config.irq_base, p->irq[0].domain_irq); | 530 | p->config.irq_base, p->irq[0].domain_irq); |
507 | } | 531 | } |
508 | 532 | ||
@@ -511,6 +535,8 @@ static int intc_irqpin_probe(struct platform_device *pdev) | |||
511 | err1: | 535 | err1: |
512 | irq_domain_remove(p->irq_domain); | 536 | irq_domain_remove(p->irq_domain); |
513 | err0: | 537 | err0: |
538 | pm_runtime_put(dev); | ||
539 | pm_runtime_disable(dev); | ||
514 | return ret; | 540 | return ret; |
515 | } | 541 | } |
516 | 542 | ||
@@ -519,7 +545,8 @@ static int intc_irqpin_remove(struct platform_device *pdev) | |||
519 | struct intc_irqpin_priv *p = platform_get_drvdata(pdev); | 545 | struct intc_irqpin_priv *p = platform_get_drvdata(pdev); |
520 | 546 | ||
521 | irq_domain_remove(p->irq_domain); | 547 | irq_domain_remove(p->irq_domain); |
522 | 548 | pm_runtime_put(&pdev->dev); | |
549 | pm_runtime_disable(&pdev->dev); | ||
523 | return 0; | 550 | return 0; |
524 | } | 551 | } |
525 | 552 | ||