From: Charlie Jenkins <charlie@rivosinc.com>
To: Anup Patel <apatel@ventanamicro.com>
Cc: Emil Renner Berthing <emil.renner.berthing@canonical.com>,
Thomas Gleixner <tglx@linutronix.de>,
Anup Patel <anup@brainfault.org>,
Paul Walmsley <paul.walmsley@sifive.com>,
linux-kernel@vger.kernel.org,
Samuel Holland <samuel.holland@sifive.com>,
Palmer Dabbelt <palmer@dabbelt.com>,
Atish Patra <atishp@atishpatra.org>,
linux-riscv@lists.infradead.org,
Andrew Jones <ajones@ventanamicro.com>
Subject: Re: [PATCH v2] irqchip/sifive-plic: Probe plic driver early for Allwinner D1 platform
Date: Mon, 19 Aug 2024 14:47:18 -0700 [thread overview]
Message-ID: <ZsO9ZmNXa3uvzctr@ghost> (raw)
In-Reply-To: <CAK9=C2UbaPgjH8WuHyCvVUoR+AeXu8TD9+QUFOvCV+L9jTJfOw@mail.gmail.com>
On Mon, Aug 19, 2024 at 08:27:33PM +0530, Anup Patel wrote:
> On Mon, Aug 19, 2024 at 12:27 PM Emil Renner Berthing
> <emil.renner.berthing@canonical.com> wrote:
> >
> > Anup Patel wrote:
> > > The latest Linux RISC-V no longer boots on the Allwinner D1 platform
> > > because the sun4i_timer driver fails to get an interrupt from PLIC.
> > >
> > > The real fix requires enabling the SBI time extension in the platform
> > > firmware (OpenSBI) and convert sun4i_timer into platform driver.
> > > Unfortunately, the real fix involves changing multiple places and
> > > can't be achieved in a short duration.
> > >
> > > As a work-around, retrofit plic probing such that plic is probed
> > > early only for the Allwinner D1 platform and probed as a regular
> > > platform driver for rest of the RISC-V platforms. In the process,
> > > partially revert some of the previous patches because PLIC device
> > > pointer is not available in all probing paths.
> > >
> > > More detailed discussion can found here:
> > > https://lore.kernel.org/lkml/20240814145642.344485-1-emil.renner.berthing@canonical.com/
> > >
> > > Fixes: e306a894bd51 ("irqchip/sifive-plic: Chain to parent IRQ after handlers are ready")
> > > Fixes: 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a platform driver")
> > > Suggested-by: Thomas Gleixner <tglx@linutronix.de>
> > > Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
> > > Tested-by: Samuel Holland <samuel.holland@sifive.com>
> > > Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> > > ---
> > > Changes since v1:
> > > - Set suppress_bind_attrs for PLIC platform driver
> > > ---
> > > drivers/irqchip/irq-sifive-plic.c | 128 +++++++++++++++++++-----------
> > > 1 file changed, 80 insertions(+), 48 deletions(-)
> > >
> > > diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
> > > index 9e22f7e378f5..33395c5a9b5b 100644
> > > --- a/drivers/irqchip/irq-sifive-plic.c
> > > +++ b/drivers/irqchip/irq-sifive-plic.c
> > > @@ -3,6 +3,7 @@
> > > * Copyright (C) 2017 SiFive
> > > * Copyright (C) 2018 Christoph Hellwig
> > > */
> > > +#define pr_fmt(fmt) "riscv-plic: " fmt
> > > #include <linux/cpu.h>
> > > #include <linux/interrupt.h>
> > > #include <linux/io.h>
> > > @@ -63,7 +64,7 @@
> > > #define PLIC_QUIRK_EDGE_INTERRUPT 0
> > >
> > > struct plic_priv {
> > > - struct device *dev;
> > > + struct fwnode_handle *fwnode;
> > > struct cpumask lmask;
> > > struct irq_domain *irqdomain;
> > > void __iomem *regs;
> > > @@ -378,8 +379,8 @@ static void plic_handle_irq(struct irq_desc *desc)
> > > int err = generic_handle_domain_irq(handler->priv->irqdomain,
> > > hwirq);
> > > if (unlikely(err)) {
> > > - dev_warn_ratelimited(handler->priv->dev,
> > > - "can't find mapping for hwirq %lu\n", hwirq);
> > > + pr_warn_ratelimited("%pfwP: can't find mapping for hwirq %lu\n",
> > > + handler->priv->fwnode, hwirq);
> > > }
> > > }
> > >
> > > @@ -408,15 +409,14 @@ static int plic_starting_cpu(unsigned int cpu)
> > > enable_percpu_irq(plic_parent_irq,
> > > irq_get_trigger_type(plic_parent_irq));
> > > else
> > > - dev_warn(handler->priv->dev, "cpu%d: parent irq not available\n", cpu);
> > > + pr_warn("%pfwP: cpu%d: parent irq not available\n",
> > > + handler->priv->fwnode, cpu);
> > > plic_set_threshold(handler, PLIC_ENABLE_THRESHOLD);
> > >
> > > return 0;
> > > }
> > >
> > > -static const struct of_device_id plic_match[] = {
> > > - { .compatible = "sifive,plic-1.0.0" },
> > > - { .compatible = "riscv,plic0" },
> > > +static const struct of_device_id plic_quirks_match[] = {
> > > { .compatible = "andestech,nceplic100",
> > > .data = (const void *)BIT(PLIC_QUIRK_EDGE_INTERRUPT) },
> > > { .compatible = "thead,c900-plic",
> > > @@ -424,38 +424,36 @@ static const struct of_device_id plic_match[] = {
> > > {}
> > > };
> > >
> > > -static int plic_parse_nr_irqs_and_contexts(struct platform_device *pdev,
> > > +static int plic_parse_nr_irqs_and_contexts(struct fwnode_handle *fwnode,
> > > u32 *nr_irqs, u32 *nr_contexts)
> > > {
> > > - struct device *dev = &pdev->dev;
> > > int rc;
> > >
> > > /*
> > > * Currently, only OF fwnode is supported so extend this
> > > * function for ACPI support.
> > > */
> > > - if (!is_of_node(dev->fwnode))
> > > + if (!is_of_node(fwnode))
> > > return -EINVAL;
> > >
> > > - rc = of_property_read_u32(to_of_node(dev->fwnode), "riscv,ndev", nr_irqs);
> > > + rc = of_property_read_u32(to_of_node(fwnode), "riscv,ndev", nr_irqs);
> > > if (rc) {
> > > - dev_err(dev, "riscv,ndev property not available\n");
> > > + pr_err("%pfwP: riscv,ndev property not available\n", fwnode);
> > > return rc;
> > > }
> > >
> > > - *nr_contexts = of_irq_count(to_of_node(dev->fwnode));
> > > + *nr_contexts = of_irq_count(to_of_node(fwnode));
> > > if (WARN_ON(!(*nr_contexts))) {
> > > - dev_err(dev, "no PLIC context available\n");
> > > + pr_err("%pfwP: no PLIC context available\n", fwnode);
> > > return -EINVAL;
> > > }
> > >
> > > return 0;
> > > }
> > >
> > > -static int plic_parse_context_parent(struct platform_device *pdev, u32 context,
> > > +static int plic_parse_context_parent(struct fwnode_handle *fwnode, u32 context,
> > > u32 *parent_hwirq, int *parent_cpu)
> > > {
> > > - struct device *dev = &pdev->dev;
> > > struct of_phandle_args parent;
> > > unsigned long hartid;
> > > int rc;
> > > @@ -464,10 +462,10 @@ static int plic_parse_context_parent(struct platform_device *pdev, u32 context,
> > > * Currently, only OF fwnode is supported so extend this
> > > * function for ACPI support.
> > > */
> > > - if (!is_of_node(dev->fwnode))
> > > + if (!is_of_node(fwnode))
> > > return -EINVAL;
> > >
> > > - rc = of_irq_parse_one(to_of_node(dev->fwnode), context, &parent);
> > > + rc = of_irq_parse_one(to_of_node(fwnode), context, &parent);
> > > if (rc)
> > > return rc;
> > >
> > > @@ -480,48 +478,55 @@ static int plic_parse_context_parent(struct platform_device *pdev, u32 context,
> > > return 0;
> > > }
> > >
> > > -static int plic_probe(struct platform_device *pdev)
> > > +static int plic_probe(struct fwnode_handle *fwnode)
> > > {
> > > int error = 0, nr_contexts, nr_handlers = 0, cpu, i;
> > > - struct device *dev = &pdev->dev;
> > > unsigned long plic_quirks = 0;
> > > struct plic_handler *handler;
> > > u32 nr_irqs, parent_hwirq;
> > > struct plic_priv *priv;
> > > irq_hw_number_t hwirq;
> > > + void __iomem *regs;
> > >
> > > - if (is_of_node(dev->fwnode)) {
> > > + if (is_of_node(fwnode)) {
> > > const struct of_device_id *id;
> > >
> > > - id = of_match_node(plic_match, to_of_node(dev->fwnode));
> > > + id = of_match_node(plic_quirks_match, to_of_node(fwnode));
> > > if (id)
> > > plic_quirks = (unsigned long)id->data;
> > > +
> > > + regs = of_iomap(to_of_node(fwnode), 0);
> > > + if (!regs)
> > > + return -ENOMEM;
> > > + } else {
> > > + return -ENODEV;
> >
> > This driver never worked with ACPI anyways?
> >
> > > }
> > >
> > > - error = plic_parse_nr_irqs_and_contexts(pdev, &nr_irqs, &nr_contexts);
> > > + error = plic_parse_nr_irqs_and_contexts(fwnode, &nr_irqs, &nr_contexts);
> > > if (error)
> > > - return error;
> > > + goto fail_free_regs;
> > >
> > > - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> > > - if (!priv)
> > > - return -ENOMEM;
> > > + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> > > + if (!priv) {
> > > + error = -ENOMEM;
> > > + goto fail_free_regs;
> > > + }
> > >
> > > - priv->dev = dev;
> > > + priv->fwnode = fwnode;
> > > priv->plic_quirks = plic_quirks;
> > > priv->nr_irqs = nr_irqs;
> > > + priv->regs = regs;
> > >
> > > - priv->regs = devm_platform_ioremap_resource(pdev, 0);
> > > - if (WARN_ON(!priv->regs))
> > > - return -EIO;
> > > -
> > > - priv->prio_save = devm_bitmap_zalloc(dev, nr_irqs, GFP_KERNEL);
> > > - if (!priv->prio_save)
> > > - return -ENOMEM;
> > > + priv->prio_save = bitmap_zalloc(nr_irqs, GFP_KERNEL);
> > > + if (!priv->prio_save) {
> > > + error = -ENOMEM;
> > > + goto fail_free_priv;
> > > + }
> > >
> > > for (i = 0; i < nr_contexts; i++) {
> > > - error = plic_parse_context_parent(pdev, i, &parent_hwirq, &cpu);
> > > + error = plic_parse_context_parent(fwnode, i, &parent_hwirq, &cpu);
> > > if (error) {
> > > - dev_warn(dev, "hwirq for context%d not found\n", i);
> > > + pr_warn("%pfwP: hwirq for context%d not found\n", fwnode, i);
> > > continue;
> > > }
> > >
> > > @@ -543,7 +548,7 @@ static int plic_probe(struct platform_device *pdev)
> > > }
> > >
> > > if (cpu < 0) {
> > > - dev_warn(dev, "Invalid cpuid for context %d\n", i);
> > > + pr_warn("%pfwP: Invalid cpuid for context %d\n", fwnode, i);
> > > continue;
> > > }
> > >
> > > @@ -554,7 +559,7 @@ static int plic_probe(struct platform_device *pdev)
> > > */
> > > handler = per_cpu_ptr(&plic_handlers, cpu);
> > > if (handler->present) {
> > > - dev_warn(dev, "handler already present for context %d.\n", i);
> > > + pr_warn("%pfwP: handler already present for context %d.\n", fwnode, i);
> > > plic_set_threshold(handler, PLIC_DISABLE_THRESHOLD);
> > > goto done;
> > > }
> > > @@ -568,8 +573,8 @@ static int plic_probe(struct platform_device *pdev)
> > > i * CONTEXT_ENABLE_SIZE;
> > > handler->priv = priv;
> > >
> > > - handler->enable_save = devm_kcalloc(dev, DIV_ROUND_UP(nr_irqs, 32),
> > > - sizeof(*handler->enable_save), GFP_KERNEL);
> > > + handler->enable_save = kcalloc(DIV_ROUND_UP(nr_irqs, 32),
> > > + sizeof(*handler->enable_save), GFP_KERNEL);
> > > if (!handler->enable_save)
> > > goto fail_cleanup_contexts;
> > > done:
> > > @@ -581,7 +586,7 @@ static int plic_probe(struct platform_device *pdev)
> > > nr_handlers++;
> > > }
> > >
> > > - priv->irqdomain = irq_domain_add_linear(to_of_node(dev->fwnode), nr_irqs + 1,
> > > + priv->irqdomain = irq_domain_add_linear(to_of_node(fwnode), nr_irqs + 1,
> > > &plic_irqdomain_ops, priv);
> > > if (WARN_ON(!priv->irqdomain))
> > > goto fail_cleanup_contexts;
> > > @@ -619,13 +624,13 @@ static int plic_probe(struct platform_device *pdev)
> > > }
> > > }
> > >
> > > - dev_info(dev, "mapped %d interrupts with %d handlers for %d contexts.\n",
> > > - nr_irqs, nr_handlers, nr_contexts);
> > > + pr_info("%pfwP: mapped %d interrupts with %d handlers for %d contexts.\n",
> > > + fwnode, nr_irqs, nr_handlers, nr_contexts);
> > > return 0;
> > >
> > > fail_cleanup_contexts:
> > > for (i = 0; i < nr_contexts; i++) {
> > > - if (plic_parse_context_parent(pdev, i, &parent_hwirq, &cpu))
> > > + if (plic_parse_context_parent(fwnode, i, &parent_hwirq, &cpu))
> > > continue;
> > > if (parent_hwirq != RV_IRQ_EXT || cpu < 0)
> > > continue;
> > > @@ -634,17 +639,44 @@ static int plic_probe(struct platform_device *pdev)
> > > handler->present = false;
> > > handler->hart_base = NULL;
> > > handler->enable_base = NULL;
> > > + kfree(handler->enable_save);
> > > handler->enable_save = NULL;
> > > handler->priv = NULL;
> > > }
> > > - return -ENOMEM;
> > > + bitmap_free(priv->prio_save);
> > > +fail_free_priv:
> > > + kfree(priv);
> > > +fail_free_regs:
> > > + iounmap(regs);
> > > + return error;
> > > +}
> > > +
> > > +static int plic_platform_probe(struct platform_device *pdev)
> > > +{
> > > + return plic_probe(pdev->dev.fwnode);
> > > }
> > >
> > > +static const struct of_device_id plic_platform_match[] = {
> > > + { .compatible = "sifive,plic-1.0.0" },
> > > + { .compatible = "riscv,plic0" },
> > > + { .compatible = "andestech,nceplic100" },
> > > + {}
> > > +};
> > > +
> > > static struct platform_driver plic_driver = {
> > > .driver = {
> > > .name = "riscv-plic",
> > > - .of_match_table = plic_match,
> > > + .of_match_table = plic_platform_match,
> > > + .suppress_bind_attrs = true,
> > > },
> > > - .probe = plic_probe,
> > > + .probe = plic_platform_probe,
> > > };
> > > builtin_platform_driver(plic_driver);
> > > +
> > > +static int __init plic_early_probe(struct device_node *node,
> > > + struct device_node *parent)
> > > +{
> > > + return plic_probe(&node->fwnode);
> > > +}
> > > +
> > > +IRQCHIP_DECLARE(riscv, "thead,c900-plic", plic_early_probe);
> >
> > If this is only needed on the Allwinner D1 maybe this should only match the
> > more specific "allwinner,sun20i-d1-plic"?
> >
> > In any case this works by itself, but not with Samuel's patch[1] applied, so
> > Tested-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
> >
> > [1]: https://lore.kernel.org/r/20240312192519.1602493-1-samuel.holland@sifive.com
>
> Thanks for testing.
>
> Can you confirm that using "allwinner,sun20i-d1-plic" for early
> probe works on the Allwinner D1 board ? If yes, the I will quickly
> send a v3.
I can confirm that this patch works as-is, and with
"allwinner,sun20i-d1-plic" for early probe on the Allwiner D1 board.
Thank you for this fix Anup!
Reviewed-by: Charlie Jenkins <charlie@rivosinc.com>
Tested-by: Charlie Jenkins <charlie@rivosinc.com>
>
> Regards,
> Anup
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
WARNING: multiple messages have this Message-ID (diff)
From: Charlie Jenkins <charlie@rivosinc.com>
To: Anup Patel <apatel@ventanamicro.com>
Cc: Emil Renner Berthing <emil.renner.berthing@canonical.com>,
Thomas Gleixner <tglx@linutronix.de>,
Anup Patel <anup@brainfault.org>,
Paul Walmsley <paul.walmsley@sifive.com>,
linux-kernel@vger.kernel.org,
Samuel Holland <samuel.holland@sifive.com>,
Palmer Dabbelt <palmer@dabbelt.com>,
Atish Patra <atishp@atishpatra.org>,
linux-riscv@lists.infradead.org,
Andrew Jones <ajones@ventanamicro.com>
Subject: Re: [PATCH v2] irqchip/sifive-plic: Probe plic driver early for Allwinner D1 platform
Date: Mon, 19 Aug 2024 14:47:18 -0700 [thread overview]
Message-ID: <ZsO9ZmNXa3uvzctr@ghost> (raw)
In-Reply-To: <CAK9=C2UbaPgjH8WuHyCvVUoR+AeXu8TD9+QUFOvCV+L9jTJfOw@mail.gmail.com>
On Mon, Aug 19, 2024 at 08:27:33PM +0530, Anup Patel wrote:
> On Mon, Aug 19, 2024 at 12:27 PM Emil Renner Berthing
> <emil.renner.berthing@canonical.com> wrote:
> >
> > Anup Patel wrote:
> > > The latest Linux RISC-V no longer boots on the Allwinner D1 platform
> > > because the sun4i_timer driver fails to get an interrupt from PLIC.
> > >
> > > The real fix requires enabling the SBI time extension in the platform
> > > firmware (OpenSBI) and convert sun4i_timer into platform driver.
> > > Unfortunately, the real fix involves changing multiple places and
> > > can't be achieved in a short duration.
> > >
> > > As a work-around, retrofit plic probing such that plic is probed
> > > early only for the Allwinner D1 platform and probed as a regular
> > > platform driver for rest of the RISC-V platforms. In the process,
> > > partially revert some of the previous patches because PLIC device
> > > pointer is not available in all probing paths.
> > >
> > > More detailed discussion can found here:
> > > https://lore.kernel.org/lkml/20240814145642.344485-1-emil.renner.berthing@canonical.com/
> > >
> > > Fixes: e306a894bd51 ("irqchip/sifive-plic: Chain to parent IRQ after handlers are ready")
> > > Fixes: 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a platform driver")
> > > Suggested-by: Thomas Gleixner <tglx@linutronix.de>
> > > Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
> > > Tested-by: Samuel Holland <samuel.holland@sifive.com>
> > > Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> > > ---
> > > Changes since v1:
> > > - Set suppress_bind_attrs for PLIC platform driver
> > > ---
> > > drivers/irqchip/irq-sifive-plic.c | 128 +++++++++++++++++++-----------
> > > 1 file changed, 80 insertions(+), 48 deletions(-)
> > >
> > > diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
> > > index 9e22f7e378f5..33395c5a9b5b 100644
> > > --- a/drivers/irqchip/irq-sifive-plic.c
> > > +++ b/drivers/irqchip/irq-sifive-plic.c
> > > @@ -3,6 +3,7 @@
> > > * Copyright (C) 2017 SiFive
> > > * Copyright (C) 2018 Christoph Hellwig
> > > */
> > > +#define pr_fmt(fmt) "riscv-plic: " fmt
> > > #include <linux/cpu.h>
> > > #include <linux/interrupt.h>
> > > #include <linux/io.h>
> > > @@ -63,7 +64,7 @@
> > > #define PLIC_QUIRK_EDGE_INTERRUPT 0
> > >
> > > struct plic_priv {
> > > - struct device *dev;
> > > + struct fwnode_handle *fwnode;
> > > struct cpumask lmask;
> > > struct irq_domain *irqdomain;
> > > void __iomem *regs;
> > > @@ -378,8 +379,8 @@ static void plic_handle_irq(struct irq_desc *desc)
> > > int err = generic_handle_domain_irq(handler->priv->irqdomain,
> > > hwirq);
> > > if (unlikely(err)) {
> > > - dev_warn_ratelimited(handler->priv->dev,
> > > - "can't find mapping for hwirq %lu\n", hwirq);
> > > + pr_warn_ratelimited("%pfwP: can't find mapping for hwirq %lu\n",
> > > + handler->priv->fwnode, hwirq);
> > > }
> > > }
> > >
> > > @@ -408,15 +409,14 @@ static int plic_starting_cpu(unsigned int cpu)
> > > enable_percpu_irq(plic_parent_irq,
> > > irq_get_trigger_type(plic_parent_irq));
> > > else
> > > - dev_warn(handler->priv->dev, "cpu%d: parent irq not available\n", cpu);
> > > + pr_warn("%pfwP: cpu%d: parent irq not available\n",
> > > + handler->priv->fwnode, cpu);
> > > plic_set_threshold(handler, PLIC_ENABLE_THRESHOLD);
> > >
> > > return 0;
> > > }
> > >
> > > -static const struct of_device_id plic_match[] = {
> > > - { .compatible = "sifive,plic-1.0.0" },
> > > - { .compatible = "riscv,plic0" },
> > > +static const struct of_device_id plic_quirks_match[] = {
> > > { .compatible = "andestech,nceplic100",
> > > .data = (const void *)BIT(PLIC_QUIRK_EDGE_INTERRUPT) },
> > > { .compatible = "thead,c900-plic",
> > > @@ -424,38 +424,36 @@ static const struct of_device_id plic_match[] = {
> > > {}
> > > };
> > >
> > > -static int plic_parse_nr_irqs_and_contexts(struct platform_device *pdev,
> > > +static int plic_parse_nr_irqs_and_contexts(struct fwnode_handle *fwnode,
> > > u32 *nr_irqs, u32 *nr_contexts)
> > > {
> > > - struct device *dev = &pdev->dev;
> > > int rc;
> > >
> > > /*
> > > * Currently, only OF fwnode is supported so extend this
> > > * function for ACPI support.
> > > */
> > > - if (!is_of_node(dev->fwnode))
> > > + if (!is_of_node(fwnode))
> > > return -EINVAL;
> > >
> > > - rc = of_property_read_u32(to_of_node(dev->fwnode), "riscv,ndev", nr_irqs);
> > > + rc = of_property_read_u32(to_of_node(fwnode), "riscv,ndev", nr_irqs);
> > > if (rc) {
> > > - dev_err(dev, "riscv,ndev property not available\n");
> > > + pr_err("%pfwP: riscv,ndev property not available\n", fwnode);
> > > return rc;
> > > }
> > >
> > > - *nr_contexts = of_irq_count(to_of_node(dev->fwnode));
> > > + *nr_contexts = of_irq_count(to_of_node(fwnode));
> > > if (WARN_ON(!(*nr_contexts))) {
> > > - dev_err(dev, "no PLIC context available\n");
> > > + pr_err("%pfwP: no PLIC context available\n", fwnode);
> > > return -EINVAL;
> > > }
> > >
> > > return 0;
> > > }
> > >
> > > -static int plic_parse_context_parent(struct platform_device *pdev, u32 context,
> > > +static int plic_parse_context_parent(struct fwnode_handle *fwnode, u32 context,
> > > u32 *parent_hwirq, int *parent_cpu)
> > > {
> > > - struct device *dev = &pdev->dev;
> > > struct of_phandle_args parent;
> > > unsigned long hartid;
> > > int rc;
> > > @@ -464,10 +462,10 @@ static int plic_parse_context_parent(struct platform_device *pdev, u32 context,
> > > * Currently, only OF fwnode is supported so extend this
> > > * function for ACPI support.
> > > */
> > > - if (!is_of_node(dev->fwnode))
> > > + if (!is_of_node(fwnode))
> > > return -EINVAL;
> > >
> > > - rc = of_irq_parse_one(to_of_node(dev->fwnode), context, &parent);
> > > + rc = of_irq_parse_one(to_of_node(fwnode), context, &parent);
> > > if (rc)
> > > return rc;
> > >
> > > @@ -480,48 +478,55 @@ static int plic_parse_context_parent(struct platform_device *pdev, u32 context,
> > > return 0;
> > > }
> > >
> > > -static int plic_probe(struct platform_device *pdev)
> > > +static int plic_probe(struct fwnode_handle *fwnode)
> > > {
> > > int error = 0, nr_contexts, nr_handlers = 0, cpu, i;
> > > - struct device *dev = &pdev->dev;
> > > unsigned long plic_quirks = 0;
> > > struct plic_handler *handler;
> > > u32 nr_irqs, parent_hwirq;
> > > struct plic_priv *priv;
> > > irq_hw_number_t hwirq;
> > > + void __iomem *regs;
> > >
> > > - if (is_of_node(dev->fwnode)) {
> > > + if (is_of_node(fwnode)) {
> > > const struct of_device_id *id;
> > >
> > > - id = of_match_node(plic_match, to_of_node(dev->fwnode));
> > > + id = of_match_node(plic_quirks_match, to_of_node(fwnode));
> > > if (id)
> > > plic_quirks = (unsigned long)id->data;
> > > +
> > > + regs = of_iomap(to_of_node(fwnode), 0);
> > > + if (!regs)
> > > + return -ENOMEM;
> > > + } else {
> > > + return -ENODEV;
> >
> > This driver never worked with ACPI anyways?
> >
> > > }
> > >
> > > - error = plic_parse_nr_irqs_and_contexts(pdev, &nr_irqs, &nr_contexts);
> > > + error = plic_parse_nr_irqs_and_contexts(fwnode, &nr_irqs, &nr_contexts);
> > > if (error)
> > > - return error;
> > > + goto fail_free_regs;
> > >
> > > - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> > > - if (!priv)
> > > - return -ENOMEM;
> > > + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> > > + if (!priv) {
> > > + error = -ENOMEM;
> > > + goto fail_free_regs;
> > > + }
> > >
> > > - priv->dev = dev;
> > > + priv->fwnode = fwnode;
> > > priv->plic_quirks = plic_quirks;
> > > priv->nr_irqs = nr_irqs;
> > > + priv->regs = regs;
> > >
> > > - priv->regs = devm_platform_ioremap_resource(pdev, 0);
> > > - if (WARN_ON(!priv->regs))
> > > - return -EIO;
> > > -
> > > - priv->prio_save = devm_bitmap_zalloc(dev, nr_irqs, GFP_KERNEL);
> > > - if (!priv->prio_save)
> > > - return -ENOMEM;
> > > + priv->prio_save = bitmap_zalloc(nr_irqs, GFP_KERNEL);
> > > + if (!priv->prio_save) {
> > > + error = -ENOMEM;
> > > + goto fail_free_priv;
> > > + }
> > >
> > > for (i = 0; i < nr_contexts; i++) {
> > > - error = plic_parse_context_parent(pdev, i, &parent_hwirq, &cpu);
> > > + error = plic_parse_context_parent(fwnode, i, &parent_hwirq, &cpu);
> > > if (error) {
> > > - dev_warn(dev, "hwirq for context%d not found\n", i);
> > > + pr_warn("%pfwP: hwirq for context%d not found\n", fwnode, i);
> > > continue;
> > > }
> > >
> > > @@ -543,7 +548,7 @@ static int plic_probe(struct platform_device *pdev)
> > > }
> > >
> > > if (cpu < 0) {
> > > - dev_warn(dev, "Invalid cpuid for context %d\n", i);
> > > + pr_warn("%pfwP: Invalid cpuid for context %d\n", fwnode, i);
> > > continue;
> > > }
> > >
> > > @@ -554,7 +559,7 @@ static int plic_probe(struct platform_device *pdev)
> > > */
> > > handler = per_cpu_ptr(&plic_handlers, cpu);
> > > if (handler->present) {
> > > - dev_warn(dev, "handler already present for context %d.\n", i);
> > > + pr_warn("%pfwP: handler already present for context %d.\n", fwnode, i);
> > > plic_set_threshold(handler, PLIC_DISABLE_THRESHOLD);
> > > goto done;
> > > }
> > > @@ -568,8 +573,8 @@ static int plic_probe(struct platform_device *pdev)
> > > i * CONTEXT_ENABLE_SIZE;
> > > handler->priv = priv;
> > >
> > > - handler->enable_save = devm_kcalloc(dev, DIV_ROUND_UP(nr_irqs, 32),
> > > - sizeof(*handler->enable_save), GFP_KERNEL);
> > > + handler->enable_save = kcalloc(DIV_ROUND_UP(nr_irqs, 32),
> > > + sizeof(*handler->enable_save), GFP_KERNEL);
> > > if (!handler->enable_save)
> > > goto fail_cleanup_contexts;
> > > done:
> > > @@ -581,7 +586,7 @@ static int plic_probe(struct platform_device *pdev)
> > > nr_handlers++;
> > > }
> > >
> > > - priv->irqdomain = irq_domain_add_linear(to_of_node(dev->fwnode), nr_irqs + 1,
> > > + priv->irqdomain = irq_domain_add_linear(to_of_node(fwnode), nr_irqs + 1,
> > > &plic_irqdomain_ops, priv);
> > > if (WARN_ON(!priv->irqdomain))
> > > goto fail_cleanup_contexts;
> > > @@ -619,13 +624,13 @@ static int plic_probe(struct platform_device *pdev)
> > > }
> > > }
> > >
> > > - dev_info(dev, "mapped %d interrupts with %d handlers for %d contexts.\n",
> > > - nr_irqs, nr_handlers, nr_contexts);
> > > + pr_info("%pfwP: mapped %d interrupts with %d handlers for %d contexts.\n",
> > > + fwnode, nr_irqs, nr_handlers, nr_contexts);
> > > return 0;
> > >
> > > fail_cleanup_contexts:
> > > for (i = 0; i < nr_contexts; i++) {
> > > - if (plic_parse_context_parent(pdev, i, &parent_hwirq, &cpu))
> > > + if (plic_parse_context_parent(fwnode, i, &parent_hwirq, &cpu))
> > > continue;
> > > if (parent_hwirq != RV_IRQ_EXT || cpu < 0)
> > > continue;
> > > @@ -634,17 +639,44 @@ static int plic_probe(struct platform_device *pdev)
> > > handler->present = false;
> > > handler->hart_base = NULL;
> > > handler->enable_base = NULL;
> > > + kfree(handler->enable_save);
> > > handler->enable_save = NULL;
> > > handler->priv = NULL;
> > > }
> > > - return -ENOMEM;
> > > + bitmap_free(priv->prio_save);
> > > +fail_free_priv:
> > > + kfree(priv);
> > > +fail_free_regs:
> > > + iounmap(regs);
> > > + return error;
> > > +}
> > > +
> > > +static int plic_platform_probe(struct platform_device *pdev)
> > > +{
> > > + return plic_probe(pdev->dev.fwnode);
> > > }
> > >
> > > +static const struct of_device_id plic_platform_match[] = {
> > > + { .compatible = "sifive,plic-1.0.0" },
> > > + { .compatible = "riscv,plic0" },
> > > + { .compatible = "andestech,nceplic100" },
> > > + {}
> > > +};
> > > +
> > > static struct platform_driver plic_driver = {
> > > .driver = {
> > > .name = "riscv-plic",
> > > - .of_match_table = plic_match,
> > > + .of_match_table = plic_platform_match,
> > > + .suppress_bind_attrs = true,
> > > },
> > > - .probe = plic_probe,
> > > + .probe = plic_platform_probe,
> > > };
> > > builtin_platform_driver(plic_driver);
> > > +
> > > +static int __init plic_early_probe(struct device_node *node,
> > > + struct device_node *parent)
> > > +{
> > > + return plic_probe(&node->fwnode);
> > > +}
> > > +
> > > +IRQCHIP_DECLARE(riscv, "thead,c900-plic", plic_early_probe);
> >
> > If this is only needed on the Allwinner D1 maybe this should only match the
> > more specific "allwinner,sun20i-d1-plic"?
> >
> > In any case this works by itself, but not with Samuel's patch[1] applied, so
> > Tested-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
> >
> > [1]: https://lore.kernel.org/r/20240312192519.1602493-1-samuel.holland@sifive.com
>
> Thanks for testing.
>
> Can you confirm that using "allwinner,sun20i-d1-plic" for early
> probe works on the Allwinner D1 board ? If yes, the I will quickly
> send a v3.
I can confirm that this patch works as-is, and with
"allwinner,sun20i-d1-plic" for early probe on the Allwiner D1 board.
Thank you for this fix Anup!
Reviewed-by: Charlie Jenkins <charlie@rivosinc.com>
Tested-by: Charlie Jenkins <charlie@rivosinc.com>
>
> Regards,
> Anup
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
next prev parent reply other threads:[~2024-08-19 21:47 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-17 8:12 [PATCH v2] irqchip/sifive-plic: Probe plic driver early for Allwinner D1 platform Anup Patel
2024-08-17 8:12 ` Anup Patel
2024-08-19 6:57 ` Emil Renner Berthing
2024-08-19 6:57 ` Emil Renner Berthing
2024-08-19 14:57 ` Anup Patel
2024-08-19 14:57 ` Anup Patel
2024-08-19 21:47 ` Charlie Jenkins [this message]
2024-08-19 21:47 ` Charlie Jenkins
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=ZsO9ZmNXa3uvzctr@ghost \
--to=charlie@rivosinc.com \
--cc=ajones@ventanamicro.com \
--cc=anup@brainfault.org \
--cc=apatel@ventanamicro.com \
--cc=atishp@atishpatra.org \
--cc=emil.renner.berthing@canonical.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=palmer@dabbelt.com \
--cc=paul.walmsley@sifive.com \
--cc=samuel.holland@sifive.com \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.