]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
irqchip/sg2042-msi: Introduce configurable chipinfo for SG2042
authorInochi Amaoto <inochiama@gmail.com>
Sun, 13 Apr 2025 22:49:14 +0000 (06:49 +0800)
committerThomas Gleixner <tglx@linutronix.de>
Mon, 14 Apr 2025 17:35:36 +0000 (19:35 +0200)
As the controller on SG2044 uses different msi_parent_ops and a difffernt
irq_chip, it is necessary to provide that information to the probe function.

Add a new chipinfo structure to hold that information, implement the
necessary logic and make SG2042 use it.

Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Chen Wang <wangchen20@iscas.ac.cn> # SG2042
Reviewed-by: Chen Wang <unicorn_wang@outlook.com>
Link: https://lore.kernel.org/all/20250413224922.69719-4-inochiama@gmail.com
drivers/irqchip/irq-sg2042-msi.c

index 5f7fae456bd47b233b0381755a927ae5acff20b7..325a83c1757327cc310a459ca85eec2a1f029e76 100644 (file)
 
 #include "irq-msi-lib.h"
 
-#define SG2042_MAX_MSI_VECTOR  32
+struct sg204x_msi_chip_info {
+       const struct irq_chip           *irqchip;
+       const struct msi_parent_ops     *parent_ops;
+};
 
+/**
+ * struct sg204x_msi_chipdata - chip data for the SG204x MSI IRQ controller
+ * @reg_clr:           clear reg, see TRM, 10.1.33, GP_INTR0_CLR
+ * @doorbell_addr:     see TRM, 10.1.32, GP_INTR0_SET
+ * @irq_first:         First vectors number that MSIs starts
+ * @num_irqs:          Number of vectors for MSIs
+ * @msi_map:           mapping for allocated MSI vectors.
+ * @msi_map_lock:      Lock for msi_map
+ * @chip_info:         chip specific infomations
+ */
 struct sg204x_msi_chipdata {
-       void __iomem    *reg_clr;       // clear reg, see TRM, 10.1.33, GP_INTR0_CLR
+       void __iomem                            *reg_clr;
+
+       phys_addr_t                             doorbell_addr;
 
-       phys_addr_t     doorbell_addr;  // see TRM, 10.1.32, GP_INTR0_SET
+       u32                                     irq_first;
+       u32                                     num_irqs;
 
-       u32             irq_first;      // The vector number that MSIs starts
-       u32             num_irqs;       // The number of vectors for MSIs
+       unsigned long                           *msi_map;
+       struct mutex                            msi_map_lock;
 
-       DECLARE_BITMAP(msi_map, SG2042_MAX_MSI_VECTOR);
-       struct mutex    msi_map_lock;   // lock for msi_map
+       const struct sg204x_msi_chip_info       *chip_info;
 };
 
 static int sg204x_msi_allocate_hwirq(struct sg204x_msi_chipdata *data, int num_req)
@@ -115,7 +130,7 @@ static int sg204x_msi_middle_domain_alloc(struct irq_domain *domain, unsigned in
                        goto err_hwirq;
 
                irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
-                                             &sg2042_msi_middle_irq_chip, data);
+                                             data->chip_info->irqchip, data);
        }
 
        return 0;
@@ -173,8 +188,7 @@ static int sg204x_msi_init_domains(struct sg204x_msi_chipdata *data,
        irq_domain_update_bus_token(middle_domain, DOMAIN_BUS_NEXUS);
 
        middle_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT;
-       middle_domain->msi_parent_ops = &sg2042_msi_parent_ops;
-
+       middle_domain->msi_parent_ops = data->chip_info->parent_ops;
        return 0;
 }
 
@@ -191,6 +205,12 @@ static int sg2042_msi_probe(struct platform_device *pdev)
        if (!data)
                return -ENOMEM;
 
+       data->chip_info = device_get_match_data(&pdev->dev);
+       if (!data->chip_info) {
+               dev_err(&pdev->dev, "Failed to get irqchip\n");
+               return -EINVAL;
+       }
+
        data->reg_clr = devm_platform_ioremap_resource_byname(pdev, "clr");
        if (IS_ERR(data->reg_clr)) {
                dev_err(dev, "Failed to map clear register\n");
@@ -231,11 +251,22 @@ static int sg2042_msi_probe(struct platform_device *pdev)
 
        mutex_init(&data->msi_map_lock);
 
+       data->msi_map = devm_bitmap_zalloc(&pdev->dev, data->num_irqs, GFP_KERNEL);
+       if (!data->msi_map) {
+               dev_err(&pdev->dev, "Unable to allocate msi mapping\n");
+               return -ENOMEM;
+       }
+
        return sg204x_msi_init_domains(data, plic_domain, dev);
 }
 
+static const struct sg204x_msi_chip_info sg2042_chip_info = {
+       .irqchip        = &sg2042_msi_middle_irq_chip,
+       .parent_ops     = &sg2042_msi_parent_ops,
+};
+
 static const struct of_device_id sg2042_msi_of_match[] = {
-       { .compatible   = "sophgo,sg2042-msi" },
+       { .compatible   = "sophgo,sg2042-msi", .data    = &sg2042_chip_info },
        { }
 };