From: Alexey Brodkin <Alexey.Brodkin@synopsys.com>
To: linux-kernel@vger.kernel.org
Cc: Alexey Brodkin <Alexey.Brodkin@synopsys.com>,
Vineet Gupta <Vineet.Gupta1@synopsys.com>,
Thomas Gleixner <tglx@linutronix.de>,
Jason Cooper <jason@lakedaemon.net>,
Jisheng Zhang <jszhang@marvell.com>
Subject: [PATCH] irq-dw-apb-ictl: convert to platform device
Date: Tue, 3 Mar 2015 17:56:59 +0300 [thread overview]
Message-ID: <1425394619-1461-1-git-send-email-abrodkin@synopsys.com> (raw)
This allows utilization of probe deferral if master interrupt controller
was not yet probed.
In my case there's an DW APB GPIO configured as interrupt controller
which is a master for DW APB INTC.
Interrupt controller sub-node of DW APB GPIO gets parsed only on DW APB
GPIO real probe - before that slave interrupt controllers cannot resolve
its master connection which lead to failures on probes of devices that
use DW APB INTC as its interrupt controller.
Now when this driver is converted to a normal platform device it may use
probe deferral and so all dependences between devices and their
interrupt controllers are resolved automatically on boot.
Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
Cc: Vineet Gupta <vgupta@synopsys.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Jisheng Zhang <jszhang@marvell.com>
---
drivers/irqchip/irq-dw-apb-ictl.c | 112 +++++++++++++++++++++++---------------
1 file changed, 67 insertions(+), 45 deletions(-)
diff --git a/drivers/irqchip/irq-dw-apb-ictl.c b/drivers/irqchip/irq-dw-apb-ictl.c
index 53bb732..0b05c58 100644
--- a/drivers/irqchip/irq-dw-apb-ictl.c
+++ b/drivers/irqchip/irq-dw-apb-ictl.c
@@ -11,13 +11,15 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/io.h>
-#include <linux/irq.h>
#include <linux/irqchip/chained_irq.h>
-#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/module.h>
-#include "irqchip.h"
+struct dw_apb_intl_priv {
+ struct device *dev;
+ struct irq_domain *irq_domain;
+};
#define APB_INT_ENABLE_L 0x00
#define APB_INT_ENABLE_H 0x04
@@ -65,41 +67,38 @@ static void dw_apb_ictl_resume(struct irq_data *d)
#define dw_apb_ictl_resume NULL
#endif /* CONFIG_PM */
-static int __init dw_apb_ictl_init(struct device_node *np,
- struct device_node *parent)
+static int dw_apb_ictl_probe(struct platform_device *pdev)
{
unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
- struct resource r;
- struct irq_domain *domain;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
struct irq_chip_generic *gc;
+ struct dw_apb_intl_priv *p;
+ struct resource *res;
void __iomem *iobase;
int ret, nrirqs, irq;
u32 reg;
- /* Map the parent interrupt for the chained handler */
- irq = irq_of_parse_and_map(np, 0);
- if (irq <= 0) {
- pr_err("%s: unable to parse irq\n", np->full_name);
- return -EINVAL;
- }
+ if (!np)
+ return -ENODEV;
- ret = of_address_to_resource(np, 0, &r);
- if (ret) {
- pr_err("%s: unable to get resource\n", np->full_name);
- return ret;
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ if (irq != -EPROBE_DEFER)
+ dev_err(dev, "no irq resource %d\n", irq);
+ return irq;
}
- if (!request_mem_region(r.start, resource_size(&r), np->full_name)) {
- pr_err("%s: unable to request mem region\n", np->full_name);
+ p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
+ if (!p)
return -ENOMEM;
- }
- iobase = ioremap(r.start, resource_size(&r));
- if (!iobase) {
- pr_err("%s: unable to map resource\n", np->full_name);
- ret = -ENOMEM;
- goto err_release;
- }
+ p->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ iobase = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(iobase))
+ return PTR_ERR(iobase);
/*
* DW IP can be configured to allow 2-64 irqs. We can determine
@@ -120,25 +119,27 @@ static int __init dw_apb_ictl_init(struct device_node *np,
else
nrirqs = fls(readl_relaxed(iobase + APB_INT_ENABLE_L));
- domain = irq_domain_add_linear(np, nrirqs,
- &irq_generic_chip_ops, NULL);
- if (!domain) {
+ p->irq_domain = irq_domain_add_linear(np, nrirqs,
+ &irq_generic_chip_ops, NULL);
+ if (!p->irq_domain) {
pr_err("%s: unable to add irq domain\n", np->full_name);
- ret = -ENOMEM;
- goto err_unmap;
+ return -ENOMEM;
}
- ret = irq_alloc_domain_generic_chips(domain, 32, (nrirqs > 32) ? 2 : 1,
- np->name, handle_level_irq, clr, 0,
+ ret = irq_alloc_domain_generic_chips(p->irq_domain, 32,
+ (nrirqs > 32) ? 2 : 1, np->name,
+ handle_level_irq, clr, 0,
IRQ_GC_MASK_CACHE_PER_TYPE |
IRQ_GC_INIT_MASK_CACHE);
if (ret) {
- pr_err("%s: unable to alloc irq domain gc\n", np->full_name);
- goto err_unmap;
+ dev_info(p->dev, "irq_alloc_domain_generic_chips failed\n");
+ irq_domain_remove(p->irq_domain);
+ p->irq_domain = NULL;
+ return -ENOMEM;
}
- gc = irq_get_domain_generic_chip(domain, 0);
- gc->private = domain;
+ gc = irq_get_domain_generic_chip(p->irq_domain, 0);
+ gc->private = p->irq_domain;
gc->reg_base = iobase;
gc->chip_types[0].regs.mask = APB_INT_MASK_L;
@@ -159,12 +160,33 @@ static int __init dw_apb_ictl_init(struct device_node *np,
irq_set_chained_handler(irq, dw_apb_ictl_handler);
return 0;
+}
-err_unmap:
- iounmap(iobase);
-err_release:
- release_mem_region(r.start, resource_size(&r));
- return ret;
+static int dw_apb_ictl_remove(struct platform_device *pdev)
+{
+ struct dw_apb_intl_priv *p = platform_get_drvdata(pdev);
+
+ irq_domain_remove(p->irq_domain);
+ return 0;
}
-IRQCHIP_DECLARE(dw_apb_ictl,
- "snps,dw-apb-ictl", dw_apb_ictl_init);
+
+static const struct of_device_id dw_apb_ictl_dt_ids[] = {
+ { .compatible = "snps,dw-apb-ictl", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, dw_apb_ictl_dt_ids);
+
+static struct platform_driver dw_apb_ictl_device_driver = {
+ .probe = dw_apb_ictl_probe,
+ .remove = dw_apb_ictl_remove,
+ .driver = {
+ .name = "synopsys_dw_apb_irq",
+ .of_match_table = of_match_ptr(dw_apb_ictl_dt_ids),
+ }
+};
+
+module_platform_driver(dw_apb_ictl_device_driver);
+
+MODULE_AUTHOR("Sebastian Hesselbarth");
+MODULE_DESCRIPTION("Synopsys DW APB ICTL irqchip driver");
+MODULE_LICENSE("GPL v2");
--
2.1.0
next reply other threads:[~2015-03-03 14:57 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-03-03 14:56 Alexey Brodkin [this message]
2015-03-04 3:11 ` Jisheng Zhang
2015-03-04 9:00 ` Sebastian Hesselbarth
2015-03-04 10:46 ` Vineet Gupta
2015-03-04 12:00 ` Sebastian Hesselbarth
2015-03-04 12:44 ` Vineet Gupta
2015-03-09 16:03 ` Linus Walleij
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1425394619-1461-1-git-send-email-abrodkin@synopsys.com \
--to=alexey.brodkin@synopsys.com \
--cc=Vineet.Gupta1@synopsys.com \
--cc=jason@lakedaemon.net \
--cc=jszhang@marvell.com \
--cc=linux-kernel@vger.kernel.org \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®