diff options
author | Geert Uytterhoeven <geert+renesas@glider.be> | 2015-11-24 10:08:13 -0500 |
---|---|---|
committer | Jason Cooper <jason@lakedaemon.net> | 2015-11-24 11:54:19 -0500 |
commit | 86e57ca735a72b44aab90a649157a678b7069a6d (patch) | |
tree | e38a3ad8ad6d7428167f6275925545fb52560f37 | |
parent | 1affe5946f7293b3747bfe7ef25dc5cfe9869012 (diff) |
irqchip/renesas-intc-irqpin: Improve clock error handling and reporting
If the Renesas External IRQ Pin driver cannot find a functional clock,
it prints a warning, .e.g.
renesas_intc_irqpin fe78001c.interrupt-controller: unable to get clock
and continues, as the clock is optional, depending on the SoC type.
This warning may confuse users.
To fix this, add a flag to indicate that the clock is mandatory or
optional, and add a few more compatible entries:
- If the clock is mandatory (on R-Mobile A1 or SH-Mobile AG5), a
missing clock is now treated as a fatal error,
- If the clock is optional (on R-Car Gen1, or using the generic
"renesas,intc-irqpin" compatible value), the warning is no longer
printed.
This requires making struct intc_irqpin_irlm_config more generic by
renaming it to intc_irqpin_config, and adding a flag to indicate if IRLM
is needed.
The new clock flag is merged with the existing shared_irqs boolean into
a bitfield to save space.
Suggested-by: Magnus Damm <magnus.damm@gmail.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lkml.kernel.org/r/1448377693-19597-1-git-send-email-geert+renesas@glider.be
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
-rw-r--r-- | drivers/irqchip/irq-renesas-intc-irqpin.c | 45 |
1 files changed, 33 insertions, 12 deletions
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c index 7f6cf19aa6ac..713177d97c7a 100644 --- a/drivers/irqchip/irq-renesas-intc-irqpin.c +++ b/drivers/irqchip/irq-renesas-intc-irqpin.c | |||
@@ -79,12 +79,15 @@ struct intc_irqpin_priv { | |||
79 | struct irq_chip irq_chip; | 79 | struct irq_chip irq_chip; |
80 | struct irq_domain *irq_domain; | 80 | struct irq_domain *irq_domain; |
81 | struct clk *clk; | 81 | struct clk *clk; |
82 | bool shared_irqs; | 82 | unsigned shared_irqs:1; |
83 | unsigned needs_clk:1; | ||
83 | u8 shared_irq_mask; | 84 | u8 shared_irq_mask; |
84 | }; | 85 | }; |
85 | 86 | ||
86 | struct intc_irqpin_irlm_config { | 87 | struct intc_irqpin_config { |
87 | unsigned int irlm_bit; | 88 | unsigned int irlm_bit; |
89 | unsigned needs_irlm:1; | ||
90 | unsigned needs_clk:1; | ||
88 | }; | 91 | }; |
89 | 92 | ||
90 | static unsigned long intc_irqpin_read32(void __iomem *iomem) | 93 | static unsigned long intc_irqpin_read32(void __iomem *iomem) |
@@ -359,8 +362,15 @@ static const struct irq_domain_ops intc_irqpin_irq_domain_ops = { | |||
359 | .xlate = irq_domain_xlate_twocell, | 362 | .xlate = irq_domain_xlate_twocell, |
360 | }; | 363 | }; |
361 | 364 | ||
362 | static const struct intc_irqpin_irlm_config intc_irqpin_irlm_r8a777x = { | 365 | static const struct intc_irqpin_config intc_irqpin_irlm_r8a777x = { |
363 | .irlm_bit = 23, /* ICR0.IRLM0 */ | 366 | .irlm_bit = 23, /* ICR0.IRLM0 */ |
367 | .needs_irlm = 1, | ||
368 | .needs_clk = 0, | ||
369 | }; | ||
370 | |||
371 | static const struct intc_irqpin_config intc_irqpin_rmobile = { | ||
372 | .needs_irlm = 0, | ||
373 | .needs_clk = 1, | ||
364 | }; | 374 | }; |
365 | 375 | ||
366 | static const struct of_device_id intc_irqpin_dt_ids[] = { | 376 | static const struct of_device_id intc_irqpin_dt_ids[] = { |
@@ -369,12 +379,17 @@ static const struct of_device_id intc_irqpin_dt_ids[] = { | |||
369 | .data = &intc_irqpin_irlm_r8a777x }, | 379 | .data = &intc_irqpin_irlm_r8a777x }, |
370 | { .compatible = "renesas,intc-irqpin-r8a7779", | 380 | { .compatible = "renesas,intc-irqpin-r8a7779", |
371 | .data = &intc_irqpin_irlm_r8a777x }, | 381 | .data = &intc_irqpin_irlm_r8a777x }, |
382 | { .compatible = "renesas,intc-irqpin-r8a7740", | ||
383 | .data = &intc_irqpin_rmobile }, | ||
384 | { .compatible = "renesas,intc-irqpin-sh73a0", | ||
385 | .data = &intc_irqpin_rmobile }, | ||
372 | {}, | 386 | {}, |
373 | }; | 387 | }; |
374 | MODULE_DEVICE_TABLE(of, intc_irqpin_dt_ids); | 388 | MODULE_DEVICE_TABLE(of, intc_irqpin_dt_ids); |
375 | 389 | ||
376 | static int intc_irqpin_probe(struct platform_device *pdev) | 390 | static int intc_irqpin_probe(struct platform_device *pdev) |
377 | { | 391 | { |
392 | const struct intc_irqpin_config *config = NULL; | ||
378 | struct device *dev = &pdev->dev; | 393 | struct device *dev = &pdev->dev; |
379 | const struct of_device_id *of_id; | 394 | const struct of_device_id *of_id; |
380 | struct intc_irqpin_priv *p; | 395 | struct intc_irqpin_priv *p; |
@@ -407,9 +422,19 @@ static int intc_irqpin_probe(struct platform_device *pdev) | |||
407 | p->pdev = pdev; | 422 | p->pdev = pdev; |
408 | platform_set_drvdata(pdev, p); | 423 | platform_set_drvdata(pdev, p); |
409 | 424 | ||
425 | of_id = of_match_device(intc_irqpin_dt_ids, dev); | ||
426 | if (of_id && of_id->data) { | ||
427 | config = of_id->data; | ||
428 | p->needs_clk = config->needs_clk; | ||
429 | } | ||
430 | |||
410 | p->clk = devm_clk_get(dev, NULL); | 431 | p->clk = devm_clk_get(dev, NULL); |
411 | if (IS_ERR(p->clk)) { | 432 | if (IS_ERR(p->clk)) { |
412 | dev_warn(dev, "unable to get clock\n"); | 433 | if (p->needs_clk) { |
434 | dev_err(dev, "unable to get clock\n"); | ||
435 | ret = PTR_ERR(p->clk); | ||
436 | goto err0; | ||
437 | } | ||
413 | p->clk = NULL; | 438 | p->clk = NULL; |
414 | } | 439 | } |
415 | 440 | ||
@@ -479,14 +504,10 @@ static int intc_irqpin_probe(struct platform_device *pdev) | |||
479 | } | 504 | } |
480 | 505 | ||
481 | /* configure "individual IRQ mode" where needed */ | 506 | /* configure "individual IRQ mode" where needed */ |
482 | of_id = of_match_device(intc_irqpin_dt_ids, dev); | 507 | if (config && config->needs_irlm) { |
483 | if (of_id && of_id->data) { | ||
484 | const struct intc_irqpin_irlm_config *irlm_config = of_id->data; | ||
485 | |||
486 | if (io[INTC_IRQPIN_REG_IRLM]) | 508 | if (io[INTC_IRQPIN_REG_IRLM]) |
487 | intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_IRLM, | 509 | intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_IRLM, |
488 | irlm_config->irlm_bit, | 510 | config->irlm_bit, 1, 1); |
489 | 1, 1); | ||
490 | else | 511 | else |
491 | dev_warn(dev, "unable to select IRLM mode\n"); | 512 | dev_warn(dev, "unable to select IRLM mode\n"); |
492 | } | 513 | } |
@@ -500,10 +521,10 @@ static int intc_irqpin_probe(struct platform_device *pdev) | |||
500 | 521 | ||
501 | /* scan for shared interrupt lines */ | 522 | /* scan for shared interrupt lines */ |
502 | ref_irq = p->irq[0].requested_irq; | 523 | ref_irq = p->irq[0].requested_irq; |
503 | p->shared_irqs = true; | 524 | p->shared_irqs = 1; |
504 | for (k = 1; k < nirqs; k++) { | 525 | for (k = 1; k < nirqs; k++) { |
505 | if (ref_irq != p->irq[k].requested_irq) { | 526 | if (ref_irq != p->irq[k].requested_irq) { |
506 | p->shared_irqs = false; | 527 | p->shared_irqs = 0; |
507 | break; | 528 | break; |
508 | } | 529 | } |
509 | } | 530 | } |