Commit bad2094e authored by Inochi Amaoto's avatar Inochi Amaoto Committed by Thomas Gleixner
Browse files

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: default avatarInochi Amaoto <inochiama@gmail.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Tested-by: Chen Wang <wangchen20@iscas.ac.cn> # SG2042
Reviewed-by: default avatarChen Wang <unicorn_wang@outlook.com>
Link: https://lore.kernel.org/all/20250413224922.69719-4-inochiama@gmail.com
parent bced5549
Loading
Loading
Loading
Loading
+42 −11
Original line number Diff line number Diff line
@@ -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;

	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 },
	{ }
};