irqchip/sg2042-msi: Introduce configurable chipinfo for SG2042

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
This commit is contained in:
Inochi Amaoto 2025-04-14 06:49:14 +08:00 committed by Thomas Gleixner
parent bced55494c
commit bad2094e3b

View File

@ -19,18 +19,33 @@
#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; // see TRM, 10.1.32, GP_INTR0_SET
phys_addr_t doorbell_addr;
u32 irq_first; // The vector number that MSIs starts
u32 num_irqs; // The number of vectors for MSIs
u32 irq_first;
u32 num_irqs;
DECLARE_BITMAP(msi_map, SG2042_MAX_MSI_VECTOR);
struct mutex msi_map_lock; // lock for msi_map
unsigned long *msi_map;
struct mutex msi_map_lock;
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 },
{ }
};