[PATCH v1 9/9] Revert "irqchip/sifive-plic: Convert PLIC driver into a platform driver"

Emil Renner Berthing emil.renner.berthing at canonical.com
Wed Aug 14 07:56:41 PDT 2024


This reverts commit 8ec99b033147ef3bb8f0a560c24eb1baec3bc0be.

This change makes the Allwinner D1 SoC lock up at boot as described in
the thread below.

Link: https://lore.kernel.org/linux-riscv/CAJM55Z9hGKo4784N3s3DhWw=nMRKZKcmvZ58x7uVBghExhoc9A@mail.gmail.com/
Fixes: 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a platform driver")
Signed-off-by: Emil Renner Berthing <emil.renner.berthing at canonical.com>
---
 drivers/irqchip/irq-sifive-plic.c | 103 ++++++++++++------------------
 1 file changed, 41 insertions(+), 62 deletions(-)

diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
index ac274e1166c3..bf0b40b0fad4 100644
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -64,7 +64,6 @@
 #define PLIC_QUIRK_EDGE_INTERRUPT	0
 
 struct plic_priv {
-	struct device *dev;
 	struct cpumask lmask;
 	struct irq_domain *irqdomain;
 	void __iomem *regs;
@@ -413,50 +412,30 @@ static int plic_starting_cpu(unsigned int cpu)
 	return 0;
 }
 
-static const struct of_device_id plic_match[] = {
-	{ .compatible = "sifive,plic-1.0.0" },
-	{ .compatible = "riscv,plic0" },
-	{ .compatible = "andestech,nceplic100",
-	  .data = (const void *)BIT(PLIC_QUIRK_EDGE_INTERRUPT) },
-	{ .compatible = "thead,c900-plic",
-	  .data = (const void *)BIT(PLIC_QUIRK_EDGE_INTERRUPT) },
-	{}
-};
-
-static int plic_probe(struct platform_device *pdev)
+static int __init __plic_init(struct device_node *node,
+			      struct device_node *parent,
+			      unsigned long plic_quirks)
 {
 	int error = 0, nr_contexts, nr_handlers = 0, i;
-	struct device *dev = &pdev->dev;
-	unsigned long plic_quirks = 0;
-	struct plic_handler *handler;
-	struct plic_priv *priv;
-	bool cpuhp_setup;
-	unsigned int cpu;
 	u32 nr_irqs;
-
-	if (is_of_node(dev->fwnode)) {
-		const struct of_device_id *id;
-
-		id = of_match_node(plic_match, to_of_node(dev->fwnode));
-		if (id)
-			plic_quirks = (unsigned long)id->data;
-	}
+	struct plic_priv *priv;
+	struct plic_handler *handler;
+	unsigned int cpu;
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
-	priv->dev = dev;
 	priv->plic_quirks = plic_quirks;
 
-	priv->regs = of_iomap(to_of_node(dev->fwnode), 0);
+	priv->regs = of_iomap(node, 0);
 	if (WARN_ON(!priv->regs)) {
 		error = -EIO;
 		goto out_free_priv;
 	}
 
 	error = -EINVAL;
-	of_property_read_u32(to_of_node(dev->fwnode), "riscv,ndev", &nr_irqs);
+	of_property_read_u32(node, "riscv,ndev", &nr_irqs);
 	if (WARN_ON(!nr_irqs))
 		goto out_iounmap;
 
@@ -466,13 +445,13 @@ static int plic_probe(struct platform_device *pdev)
 	if (!priv->prio_save)
 		goto out_free_priority_reg;
 
-	nr_contexts = of_irq_count(to_of_node(dev->fwnode));
+	nr_contexts = of_irq_count(node);
 	if (WARN_ON(!nr_contexts))
 		goto out_free_priority_reg;
 
 	error = -ENOMEM;
-	priv->irqdomain = irq_domain_add_linear(to_of_node(dev->fwnode), nr_irqs + 1,
-						&plic_irqdomain_ops, priv);
+	priv->irqdomain = irq_domain_add_linear(node, nr_irqs + 1,
+			&plic_irqdomain_ops, priv);
 	if (WARN_ON(!priv->irqdomain))
 		goto out_free_priority_reg;
 
@@ -482,7 +461,7 @@ static int plic_probe(struct platform_device *pdev)
 		int cpu;
 		unsigned long hartid;
 
-		if (of_irq_parse_one(to_of_node(dev->fwnode), i, &parent)) {
+		if (of_irq_parse_one(node, i, &parent)) {
 			pr_err("failed to parse parent for context %d.\n", i);
 			continue;
 		}
@@ -518,7 +497,7 @@ static int plic_probe(struct platform_device *pdev)
 
 		/* Find parent domain and register chained handler */
 		if (!plic_parent_irq && irq_find_host(parent.np)) {
-			plic_parent_irq = irq_of_parse_and_map(to_of_node(dev->fwnode), i);
+			plic_parent_irq = irq_of_parse_and_map(node, i);
 			if (plic_parent_irq)
 				irq_set_chained_handler(plic_parent_irq,
 							plic_handle_irq);
@@ -560,29 +539,20 @@ static int plic_probe(struct platform_device *pdev)
 
 	/*
 	 * We can have multiple PLIC instances so setup cpuhp state
-	 * and register syscore operations only once after context
-	 * handlers of all online CPUs are initialized.
+	 * and register syscore operations only when context handler
+	 * for current/boot CPU is present.
 	 */
-	if (!plic_cpuhp_setup_done) {
-		cpuhp_setup = true;
-		for_each_online_cpu(cpu) {
-			handler = per_cpu_ptr(&plic_handlers, cpu);
-			if (!handler->present) {
-				cpuhp_setup = false;
-				break;
-			}
-		}
-		if (cpuhp_setup) {
-			cpuhp_setup_state(CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING,
-					  "irqchip/sifive/plic:starting",
-					  plic_starting_cpu, plic_dying_cpu);
-			register_syscore_ops(&plic_irq_syscore_ops);
-			plic_cpuhp_setup_done = true;
-		}
+	handler = this_cpu_ptr(&plic_handlers);
+	if (handler->present && !plic_cpuhp_setup_done) {
+		cpuhp_setup_state(CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING,
+				  "irqchip/sifive/plic:starting",
+				  plic_starting_cpu, plic_dying_cpu);
+		register_syscore_ops(&plic_irq_syscore_ops);
+		plic_cpuhp_setup_done = true;
 	}
 
-	pr_info("%pOFP: mapped %d interrupts with %d handlers for %d contexts.\n",
-		to_of_node(dev->fwnode), nr_irqs, nr_handlers, nr_contexts);
+	pr_info("%pOFP: mapped %d interrupts with %d handlers for"
+		" %d contexts.\n", node, nr_irqs, nr_handlers, nr_contexts);
 	return 0;
 
 out_free_enable_reg:
@@ -599,11 +569,20 @@ static int plic_probe(struct platform_device *pdev)
 	return error;
 }
 
-static struct platform_driver plic_driver = {
-	.driver = {
-		.name		= "riscv-plic",
-		.of_match_table	= plic_match,
-	},
-	.probe = plic_probe,
-};
-builtin_platform_driver(plic_driver);
+static int __init plic_init(struct device_node *node,
+			    struct device_node *parent)
+{
+	return __plic_init(node, parent, 0);
+}
+
+IRQCHIP_DECLARE(sifive_plic, "sifive,plic-1.0.0", plic_init);
+IRQCHIP_DECLARE(riscv_plic0, "riscv,plic0", plic_init); /* for legacy systems */
+
+static int __init plic_edge_init(struct device_node *node,
+				 struct device_node *parent)
+{
+	return __plic_init(node, parent, BIT(PLIC_QUIRK_EDGE_INTERRUPT));
+}
+
+IRQCHIP_DECLARE(andestech_nceplic100, "andestech,nceplic100", plic_edge_init);
+IRQCHIP_DECLARE(thead_c900_plic, "thead,c900-plic", plic_edge_init);
-- 
2.43.0




More information about the linux-riscv mailing list