irqchip/sg2042-msi: Add the Sophgo SG2044 MSI interrupt controller
Inochi Amaoto
maintainerv4 cover irqchip/sg2042-msi: Add the Sophgo SG2044 MSI interrupt controller
Like Sophgo SG2042, SG2044 also uses an external interrupt controller to handle MSI/MSI-X. It supports more interrupt and has a different msi message address mapping.
Changed from v3:
- https://lore.kernel.org/all/[email protected]/
1. reapply Chen'tag for the whole series
2. patch 3: move msi_map from patch 4 into this one
Changed from v2:
- https://lore.kernel.org/all/[email protected]/
1. patch 2: separate from patch 2 of v2 for better reviewing
2. patch 3: separate from patch 2 of v2 for better reviewing
3. patch 4: apply Chen'tag
Changed from v1:
- https://lore.kernel.org/all/[email protected]/
1. patch 1: apply Conor's tag
2. patch 1: improve the bindings comments.
3. patch 2: rebased on tips:irq/drivers patch
4. patch 2: remove unused macro "SG2042_MAX_MSI_VECTOR"
5. patch 2: rename generic structure name to match sg204x.
6. patch 2: rename info field name to avoid misunderstanding.
Inochi Amaoto (4):
dt-bindings: interrupt-controller: Add Sophgo SG2044 MSI controller irqchip/sg2042-msi: rename generic function and structure irqchip/sg2042-msi: introduce configurable chipinfo for sg2042 irqchip/sg2042-msi: Add the Sophgo SG2044 MSI interrupt controller
.../sophgo,sg2042-msi.yaml | 4 +- drivers/irqchip/irq-sg2042-msi.c | 149 ++++++++++++++---- 2 files changed, 119 insertions(+), 34 deletions(-)
--
2.49.0
Inochi Amaoto
maintainerPATCH v4 1/4 dt-bindings: interrupt-controller: Add Sophgo SG2044 MSI controller
Like SG2042, SG2044 also uses an external msi controller to provide MSI interrupt for PCIe controllers. The difference between these two msi controlling are summary as follows:
1. SG2044 acks the interrupt by writing 0, as on SG2042 by setting related bit.
2. SG2044 uses interrupt number mod 32 as msi message data, but SG2042 uses setting related bit.
Add support for the SG2044 msi controller.
--- .../bindings/interrupt-controller/sophgo,sg2042-msi.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/interrupt-controller/sophgo,sg2042-msi.yaml +3 -1
@@ -18,7 +18,9 @@ allOf: properties: compatible: - const: sophgo,sg2042-msi + enum: + - sophgo,sg2042-msi + - sophgo,sg2044-msi reg: items:
Signature · 1 line
2.49.0
[tip: irq/drivers] dt-bindings: interrupt-controller: Add Sophgo SG2044 MSI controller
The following commit has been merged into the irq/drivers branch of tip:
The following commit has been merged into the irq/drivers branch of tip:
Commit-ID: 9fe5a0790af6af619940a2819aabe8f6fb30700c Gitweb: https://git.kernel.org/tip/9fe5a0790af6af619940a2819aabe8f6fb30700c Author: Inochi Amaoto <[email protected]> AuthorDate: Mon, 14 Apr 2025 06:49:12 +08:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Mon, 14 Apr 2025 19:35:36 +02:00
dt-bindings: interrupt-controller: Add Sophgo SG2044 MSI controller
Like SG2042, SG2044 also uses an external MSI controller to provide MSI interrupt for PCIe controllers. The difference between these two MSI controllers are:
1. SG2044 acks the interrupt by writing 0, SG2042 by setting the bit related to the interrupt.
2. SG2044 uses interrupt number modulo 32 as MSI message data, but SG2042 uses the bit related to the interrupt.
Add support for the SG2044 MSI controller.
--- Documentation/devicetree/bindings/interrupt-controller/sophgo,sg2042-msi.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/interrupt-controller/sophgo,sg2042-msi.yaml +3 -1
@@ -18,7 +18,9 @@ allOf: properties: compatible: - const: sophgo,sg2042-msi + enum: + - sophgo,sg2042-msi + - sophgo,sg2044-msi reg: items:
Inochi Amaoto
maintainerPATCH v4 2/4 irqchip/sg2042-msi: rename generic function and structure
In reply to Inochi AmaotoAs the driver logic can be used in both SG2042 and SG2044, it will be better to have a generic name.
--- drivers/irqchip/irq-sg2042-msi.c | 46 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-)
drivers/irqchip/irq-sg2042-msi.c +23 -23
@@ -21,7 +21,7 @@#define SG2042_MAX_MSI_VECTOR 32 -struct sg2042_msi_chipdata { +struct sg204x_msi_chipdata {void __iomem *reg_clr;// clear reg, see TRM, 10.1.33, GP_INTR0_CLR phys_addr_t doorbell_addr;// see TRM, 10.1.32, GP_INTR0_SET
@@ -33,7 +33,7 @@ struct sg2042_msi_chipdata {struct mutex msi_map_lock;// lock for msi_map }; -static int sg2042_msi_allocate_hwirq (struct sg2042_msi_chipdata *data,int num_req) +static int sg204x_msi_allocate_hwirq (struct sg204x_msi_chipdata *data,int num_req) {int first;
@@ -43,7 +43,7 @@ static int sg2042_msi_allocate_hwirq(struct sg2042_msi_chipdata *data, int num_rreturn first >=0 ? first : -ENOSPC ; } -static void sg2042_msi_free_hwirq (struct sg2042_msi_chipdata *data,int hwirq,int num_req) +static void sg204x_msi_free_hwirq (struct sg204x_msi_chipdata *data,int hwirq,int num_req) {guard (mutex)(&data->msi_map_lock);bitmap_release_region (data->msi_map, hwirq,get_count_order (num_req));
@@ -51,7 +51,7 @@ static void sg2042_msi_free_hwirq(struct sg2042_msi_chipdata *data, int hwirq, istatic void sg2042_msi_irq_ack (struct irq_data *d) { -struct sg2042_msi_chipdata *data =irq_data_get_irq_chip_data (d); +struct sg204x_msi_chipdata *data =irq_data_get_irq_chip_data (d);int bit_off = d->hwirq;writel (1 << bit_off, data->reg_clr);
@@ -61,7 +61,7 @@ static void sg2042_msi_irq_ack(struct irq_data *d)static void sg2042_msi_irq_compose_msi_msg (struct irq_data *d,struct msi_msg *msg) { -struct sg2042_msi_chipdata *data =irq_data_get_irq_chip_data (d); +struct sg204x_msi_chipdata *data =irq_data_get_irq_chip_data (d); msg->address_hi =upper_32_bits (data->doorbell_addr); msg->address_lo =lower_32_bits (data->doorbell_addr);
@@ -79,9 +79,9 @@ static const struct irq_chip sg2042_msi_middle_irq_chip = { .irq_compose_msi_msg = sg2042_msi_irq_compose_msi_msg, }; -static int sg2042_msi_parent_domain_alloc (struct irq_domain *domain,unsigned int virq,int hwirq) +static int sg204x_msi_parent_domain_alloc (struct irq_domain *domain,unsigned int virq,int hwirq) { -struct sg2042_msi_chipdata *data = domain->host_data; +struct sg204x_msi_chipdata *data = domain->host_data;struct irq_fwspec fwspec;struct irq_data *d;int ret;
@@ -99,18 +99,18 @@ static int sg2042_msi_parent_domain_alloc(struct irq_domain *domain, unsigned inreturn d->chip->irq_set_type (d,IRQ_TYPE_EDGE_RISING ); } -static int sg2042_msi_middle_domain_alloc (struct irq_domain *domain,unsigned int virq, +static int sg204x_msi_middle_domain_alloc (struct irq_domain *domain,unsigned int virq,unsigned int nr_irqs,void *args) { -struct sg2042_msi_chipdata *data = domain->host_data; +struct sg204x_msi_chipdata *data = domain->host_data;int hwirq, err, i; - hwirq =sg2042_msi_allocate_hwirq (data, nr_irqs); + hwirq =sg204x_msi_allocate_hwirq (data, nr_irqs);if (hwirq <0 )return hwirq;for (i =0 ; i < nr_irqs; i++) { - err =sg2042_msi_parent_domain_alloc (domain, virq + i, hwirq + i); + err =sg204x_msi_parent_domain_alloc (domain, virq + i, hwirq + i);if (err) goto err_hwirq;
@@ -121,25 +121,25 @@ static int sg2042_msi_middle_domain_alloc(struct irq_domain *domain, unsigned inreturn 0 ; err_hwirq: -sg2042_msi_free_hwirq (data, hwirq, nr_irqs); +sg204x_msi_free_hwirq (data, hwirq, nr_irqs);irq_domain_free_irqs_parent (domain, virq, i);return err; } -static void sg2042_msi_middle_domain_free (struct irq_domain *domain,unsigned int virq, +static void sg204x_msi_middle_domain_free (struct irq_domain *domain,unsigned int virq,unsigned int nr_irqs) {struct irq_data *d =irq_domain_get_irq_data (domain, virq); -struct sg2042_msi_chipdata *data =irq_data_get_irq_chip_data (d); +struct sg204x_msi_chipdata *data =irq_data_get_irq_chip_data (d);irq_domain_free_irqs_parent (domain, virq, nr_irqs); -sg2042_msi_free_hwirq (data, d->hwirq, nr_irqs); +sg204x_msi_free_hwirq (data, d->hwirq, nr_irqs); } -static const struct irq_domain_ops sg2042_msi_middle_domain_ops = { - .alloc = sg2042_msi_middle_domain_alloc, - .free = sg2042_msi_middle_domain_free, +static const struct irq_domain_ops sg204x_msi_middle_domain_ops = { + .alloc = sg204x_msi_middle_domain_alloc, + .free = sg204x_msi_middle_domain_free, .select = msi_lib_irq_domain_select, };
@@ -158,14 +158,14 @@ static const struct msi_parent_ops sg2042_msi_parent_ops = { .init_dev_msi_info = msi_lib_init_dev_msi_info, }; -static int sg2042_msi_init_domains (struct sg2042_msi_chipdata *data, +static int sg204x_msi_init_domains (struct sg204x_msi_chipdata *data,struct irq_domain *plic_domain,struct device *dev) {struct fwnode_handle *fwnode =dev_fwnode (dev);struct irq_domain *middle_domain; middle_domain =irq_domain_create_hierarchy (plic_domain,0 , data->num_irqs, fwnode, - &sg2042_msi_middle_domain_ops, data); + &sg204x_msi_middle_domain_ops, data);if (!middle_domain) {pr_err ("Failed to create the MSI middle domain\n" );return -ENOMEM ;
@@ -182,13 +182,13 @@ static int sg2042_msi_init_domains(struct sg2042_msi_chipdata *data,static int sg2042_msi_probe (struct platform_device *pdev) {struct fwnode_reference_args args = { }; -struct sg2042_msi_chipdata *data; +struct sg204x_msi_chipdata *data;struct device *dev = &pdev->dev;struct irq_domain *plic_domain;struct resource *res;int ret; - data =devm_kzalloc (dev,sizeof (struct sg2042_msi_chipdata ),GFP_KERNEL ); + data =devm_kzalloc (dev,sizeof (struct sg204x_msi_chipdata ),GFP_KERNEL );if (!data)return -ENOMEM ;
@@ -232,7 +232,7 @@ static int sg2042_msi_probe(struct platform_device *pdev)mutex_init (&data->msi_map_lock); -return sg2042_msi_init_domains (data, plic_domain, dev); +return sg204x_msi_init_domains (data, plic_domain, dev); }static const struct of_device_id sg2042_msi_of_match[] = {
Signature · 1 line
2.49.0
[tip: irq/drivers] irqchip/sg2042-msi: Rename functions and data structures to be SG2042 agnostic
The following commit has been merged into the irq/drivers branch of tip:
The following commit has been merged into the irq/drivers branch of tip:
Commit-ID: bced55494c23dca674c3c18b4a07ffe7c15000e2 Gitweb: https://git.kernel.org/tip/bced55494c23dca674c3c18b4a07ffe7c15000e2 Author: Inochi Amaoto <[email protected]> AuthorDate: Mon, 14 Apr 2025 06:49:13 +08:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Mon, 14 Apr 2025 19:35:36 +02:00
irqchip/sg2042-msi: Rename functions and data structures to be SG2042 agnostic
As the driver logic can be used in both SG2042 and SG2044 SoCs, rename functions and data structures, which are not SG2042 specific, to SG204x*.
--- drivers/irqchip/irq-sg2042-msi.c | 46 +++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-)
drivers/irqchip/irq-sg2042-msi.c +23 -23
@@ -21,7 +21,7 @@#define SG2042_MAX_MSI_VECTOR 32 -struct sg2042_msi_chipdata { +struct sg204x_msi_chipdata {void __iomem *reg_clr;// clear reg, see TRM, 10.1.33, GP_INTR0_CLR phys_addr_t doorbell_addr;// see TRM, 10.1.32, GP_INTR0_SET
@@ -33,7 +33,7 @@ struct sg2042_msi_chipdata {struct mutex msi_map_lock;// lock for msi_map }; -static int sg2042_msi_allocate_hwirq (struct sg2042_msi_chipdata *data,int num_req) +static int sg204x_msi_allocate_hwirq (struct sg204x_msi_chipdata *data,int num_req) {int first;
@@ -43,7 +43,7 @@ static int sg2042_msi_allocate_hwirq(struct sg2042_msi_chipdata *data, int num_rreturn first >=0 ? first : -ENOSPC ; } -static void sg2042_msi_free_hwirq (struct sg2042_msi_chipdata *data,int hwirq,int num_req) +static void sg204x_msi_free_hwirq (struct sg204x_msi_chipdata *data,int hwirq,int num_req) {guard (mutex)(&data->msi_map_lock);bitmap_release_region (data->msi_map, hwirq,get_count_order (num_req));
@@ -51,7 +51,7 @@ static void sg2042_msi_free_hwirq(struct sg2042_msi_chipdata *data, int hwirq, istatic void sg2042_msi_irq_ack (struct irq_data *d) { -struct sg2042_msi_chipdata *data =irq_data_get_irq_chip_data (d); +struct sg204x_msi_chipdata *data =irq_data_get_irq_chip_data (d);int bit_off = d->hwirq;writel (1 << bit_off, data->reg_clr);
@@ -61,7 +61,7 @@ static void sg2042_msi_irq_ack(struct irq_data *d)static void sg2042_msi_irq_compose_msi_msg (struct irq_data *d,struct msi_msg *msg) { -struct sg2042_msi_chipdata *data =irq_data_get_irq_chip_data (d); +struct sg204x_msi_chipdata *data =irq_data_get_irq_chip_data (d); msg->address_hi =upper_32_bits (data->doorbell_addr); msg->address_lo =lower_32_bits (data->doorbell_addr);
@@ -79,9 +79,9 @@ static const struct irq_chip sg2042_msi_middle_irq_chip = { .irq_compose_msi_msg = sg2042_msi_irq_compose_msi_msg, }; -static int sg2042_msi_parent_domain_alloc (struct irq_domain *domain,unsigned int virq,int hwirq) +static int sg204x_msi_parent_domain_alloc (struct irq_domain *domain,unsigned int virq,int hwirq) { -struct sg2042_msi_chipdata *data = domain->host_data; +struct sg204x_msi_chipdata *data = domain->host_data;struct irq_fwspec fwspec;struct irq_data *d;int ret;
@@ -99,18 +99,18 @@ static int sg2042_msi_parent_domain_alloc(struct irq_domain *domain, unsigned inreturn d->chip->irq_set_type (d,IRQ_TYPE_EDGE_RISING ); } -static int sg2042_msi_middle_domain_alloc (struct irq_domain *domain,unsigned int virq, +static int sg204x_msi_middle_domain_alloc (struct irq_domain *domain,unsigned int virq,unsigned int nr_irqs,void *args) { -struct sg2042_msi_chipdata *data = domain->host_data; +struct sg204x_msi_chipdata *data = domain->host_data;int hwirq, err, i; - hwirq =sg2042_msi_allocate_hwirq (data, nr_irqs); + hwirq =sg204x_msi_allocate_hwirq (data, nr_irqs);if (hwirq <0 )return hwirq;for (i =0 ; i < nr_irqs; i++) { - err =sg2042_msi_parent_domain_alloc (domain, virq + i, hwirq + i); + err =sg204x_msi_parent_domain_alloc (domain, virq + i, hwirq + i);if (err) goto err_hwirq;
@@ -121,25 +121,25 @@ static int sg2042_msi_middle_domain_alloc(struct irq_domain *domain, unsigned inreturn 0 ; err_hwirq: -sg2042_msi_free_hwirq (data, hwirq, nr_irqs); +sg204x_msi_free_hwirq (data, hwirq, nr_irqs);irq_domain_free_irqs_parent (domain, virq, i);return err; } -static void sg2042_msi_middle_domain_free (struct irq_domain *domain,unsigned int virq, +static void sg204x_msi_middle_domain_free (struct irq_domain *domain,unsigned int virq,unsigned int nr_irqs) {struct irq_data *d =irq_domain_get_irq_data (domain, virq); -struct sg2042_msi_chipdata *data =irq_data_get_irq_chip_data (d); +struct sg204x_msi_chipdata *data =irq_data_get_irq_chip_data (d);irq_domain_free_irqs_parent (domain, virq, nr_irqs); -sg2042_msi_free_hwirq (data, d->hwirq, nr_irqs); +sg204x_msi_free_hwirq (data, d->hwirq, nr_irqs); } -static const struct irq_domain_ops sg2042_msi_middle_domain_ops = { - .alloc = sg2042_msi_middle_domain_alloc, - .free = sg2042_msi_middle_domain_free, +static const struct irq_domain_ops sg204x_msi_middle_domain_ops = { + .alloc = sg204x_msi_middle_domain_alloc, + .free = sg204x_msi_middle_domain_free, .select = msi_lib_irq_domain_select, };
@@ -157,14 +157,14 @@ static const struct msi_parent_ops sg2042_msi_parent_ops = { .init_dev_msi_info = msi_lib_init_dev_msi_info, }; -static int sg2042_msi_init_domains (struct sg2042_msi_chipdata *data, +static int sg204x_msi_init_domains (struct sg204x_msi_chipdata *data,struct irq_domain *plic_domain,struct device *dev) {struct fwnode_handle *fwnode =dev_fwnode (dev);struct irq_domain *middle_domain; middle_domain =irq_domain_create_hierarchy (plic_domain,0 , data->num_irqs, fwnode, - &sg2042_msi_middle_domain_ops, data); + &sg204x_msi_middle_domain_ops, data);if (!middle_domain) {pr_err ("Failed to create the MSI middle domain\n" );return -ENOMEM ;
@@ -181,13 +181,13 @@ static int sg2042_msi_init_domains(struct sg2042_msi_chipdata *data,static int sg2042_msi_probe (struct platform_device *pdev) {struct fwnode_reference_args args = { }; -struct sg2042_msi_chipdata *data; +struct sg204x_msi_chipdata *data;struct device *dev = &pdev->dev;struct irq_domain *plic_domain;struct resource *res;int ret; - data =devm_kzalloc (dev,sizeof (struct sg2042_msi_chipdata ),GFP_KERNEL ); + data =devm_kzalloc (dev,sizeof (struct sg204x_msi_chipdata ),GFP_KERNEL );if (!data)return -ENOMEM ;
@@ -231,7 +231,7 @@ static int sg2042_msi_probe(struct platform_device *pdev)mutex_init (&data->msi_map_lock); -return sg2042_msi_init_domains (data, plic_domain, dev); +return sg204x_msi_init_domains (data, plic_domain, dev); }static const struct of_device_id sg2042_msi_of_match[] = {
Inochi Amaoto
maintainerPATCH v4 3/4 irqchip/sg2042-msi: introduce configurable chipinfo for sg2042
In reply to Inochi AmaotoAs the controller on SG2044 uses different msi_parent_ops and irq_chip, it is necessary to add a structure to hold the configuration across controllers.
Add the chipinfo structure and implement necessary logic for it.
--- drivers/irqchip/irq-sg2042-msi.c | 52 ++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 10 deletions(-)
drivers/irqchip/irq-sg2042-msi.c +42 -10
@@ -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 ;
@@ -174,7 +189,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 ; }
@@ -192,6 +207,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" );
@@ -232,11 +253,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 }, { } };
Signature · 1 line
2.49.0
Re: [PATCH v4 3/4] irqchip/sg2042-msi: introduce configurable chipinfo for sg2042
hi, Inochi,
Quoted 21 lines · Inochi Amaoto
As the controller on SG2044 uses different
msi_parent_opsandirq_chip, it is necessary to add a structure to hold the configuration across controllers.Add the chipinfo structure and implement necessary logic for it.
Signed-off-by Inochi Amaoto <[email protected]>Reviewed-by Chen Wang <[email protected]>Tested-by Chen Wang <[email protected]> # SG2042--- drivers/irqchip/irq-sg2042-msi.c | 52 ++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 10 deletions(-)drivers/irqchip/irq-sg2042-msi.c +0
-0@@ -19,18 +19,33 @@#include "irq-msi-lib.h"
drivers/irqchip/irq-sg2042-msi.c line 30
Quoted 10 lines
drivers/irqchip/irq-sg2042-msi.c +8
-1-#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
I remember asking some questions about this last time, but you didn't respond.
Chen
Quoted 82 lines
drivers/irqchip/irq-sg2042-msi.c +34
-9+* @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 ;@@ -174,7 +189,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 ; }@@ -192,6 +207,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" );@@ -232,11 +253,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 }, { } };
Inochi Amaoto
maintainerRe: [PATCH v4 3/4] irqchip/sg2042-msi: introduce configurable chipinfo for sg2042
Quoted 26 lines · Chen Wang
hi, Inochi,
Quoted 23 lines · Inochi Amaoto
As the controller on SG2044 uses different
msi_parent_opsandirq_chip, it is necessary to add a structure to hold the configuration across controllers.Add the chipinfo structure and implement necessary logic for it.
Signed-off-by Inochi Amaoto <[email protected]>Reviewed-by Chen Wang <[email protected]>Tested-by Chen Wang <[email protected]> # SG2042--- drivers/irqchip/irq-sg2042-msi.c | 52 ++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 10 deletions(-)drivers/irqchip/irq-sg2042-msi.c +3
-1@@ -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;
Quoted 9 lines
drivers/irqchip/irq-sg2042-msi.c line 30
Quoted 5 lines
drivers/irqchip/irq-sg2042-msi.c +5
-0+}; +/** +* 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 I remember asking some questions about this last time, but you didn't respond.
Oh, I forgot to respond this. Since the SG2044 document is not opened public for now. I think it is possible to leave this for someone to reference it. Also, I find nothing about this address in my copy of the document, and was told it follows a similar design of SG2042. So I think it is OK to reserve it at least for now.
Regards,
Inochi
[tip: irq/drivers] irqchip/sg2042-msi: Introduce configurable chipinfo for SG2042
In reply to Inochi AmaotoThe following commit has been merged into the irq/drivers branch of tip:
The following commit has been merged into the irq/drivers branch of tip:
Commit-ID: bad2094e3b1c37c683f183a2a885ea0232ba31e9 Gitweb: https://git.kernel.org/tip/bad2094e3b1c37c683f183a2a885ea0232ba31e9 Author: Inochi Amaoto <[email protected]> AuthorDate: Mon, 14 Apr 2025 06:49:14 +08:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Mon, 14 Apr 2025 19:35:36 +02:00
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.
--- drivers/irqchip/irq-sg2042-msi.c | 53 ++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 11 deletions(-)
drivers/irqchip/irq-sg2042-msi.c +42 -11
@@ -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 }, { } };
Inochi Amaoto
maintainerPATCH v4 4/4 irqchip/sg2042-msi: Add the Sophgo SG2044 MSI interrupt controller
In reply to Inochi AmaotoAdd support for Sophgo SG2044 MSI interrupt controller.
--- drivers/irqchip/irq-sg2042-msi.c | 51 ++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)
drivers/irqchip/irq-sg2042-msi.c +51 -0
@@ -94,6 +94,35 @@ static const struct irq_chip sg2042_msi_middle_irq_chip = { .irq_compose_msi_msg = sg2042_msi_irq_compose_msi_msg, }; +static void sg2044_msi_irq_ack (struct irq_data *d) +{ +struct sg204x_msi_chipdata *data =irq_data_get_irq_chip_data (d); + +writel (0 , (unsigned int *)data->reg_clr + d->hwirq); +irq_chip_ack_parent (d); +} + +static void sg2044_msi_irq_compose_msi_msg (struct irq_data *d,struct msi_msg *msg) +{ +struct sg204x_msi_chipdata *data =irq_data_get_irq_chip_data (d); +phys_addr_t doorbell = data->doorbell_addr +4 * (d->hwirq /32 ); + + msg->address_lo =lower_32_bits (doorbell); + msg->address_hi =upper_32_bits (doorbell); + msg->data = d->hwirq %32 ; +} + +static struct irq_chip sg2044_msi_middle_irq_chip = { + .name ="SG2044 MSI" , + .irq_ack = sg2044_msi_irq_ack, + .irq_mask = irq_chip_mask_parent, + .irq_unmask = irq_chip_unmask_parent, +#ifdef CONFIG_SMP + .irq_set_affinity = irq_chip_set_affinity_parent, +#endif + .irq_compose_msi_msg = sg2044_msi_irq_compose_msi_msg, +}; +static int sg204x_msi_parent_domain_alloc (struct irq_domain *domain,unsigned int virq,int hwirq) {struct sg204x_msi_chipdata *data = domain->host_data;
@@ -173,6 +202,22 @@ static const struct msi_parent_ops sg2042_msi_parent_ops = { .init_dev_msi_info = msi_lib_init_dev_msi_info, }; +#define SG2044_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ + MSI_FLAG_USE_DEF_CHIP_OPS) + +#define SG2044_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ + MSI_FLAG_PCI_MSIX) + +static const struct msi_parent_ops sg2044_msi_parent_ops = { + .required_flags =SG2044_MSI_FLAGS_REQUIRED , + .supported_flags =SG2044_MSI_FLAGS_SUPPORTED , + .chip_flags =MSI_CHIP_FLAG_SET_EOI |MSI_CHIP_FLAG_SET_ACK , + .bus_select_mask =MATCH_PCI_MSI , + .bus_select_token =DOMAIN_BUS_NEXUS , + .prefix ="SG2044-" , + .init_dev_msi_info = msi_lib_init_dev_msi_info, +}; +static int sg204x_msi_init_domains (struct sg204x_msi_chipdata *data,struct irq_domain *plic_domain,struct device *dev) {
@@ -267,8 +312,14 @@ static const struct sg204x_msi_chip_info sg2042_chip_info = { .parent_ops = &sg2042_msi_parent_ops, }; +static const struct sg204x_msi_chip_info sg2044_chip_info = { + .irqchip = &sg2044_msi_middle_irq_chip, + .parent_ops = &sg2044_msi_parent_ops, +}; +static const struct of_device_id sg2042_msi_of_match[] = { { .compatible ="sophgo,sg2042-msi" , .data = &sg2042_chip_info }, + { .compatible ="sophgo,sg2044-msi" , .data = &sg2044_chip_info }, { } };
Signature · 1 line
2.49.0
The following commit has been merged into the irq/drivers branch of tip:
The following commit has been merged into the irq/drivers branch of tip:
Commit-ID: e96b93a97c90181627cef6e70a0dbc8dbdae4adc Gitweb: https://git.kernel.org/tip/e96b93a97c90181627cef6e70a0dbc8dbdae4adc Author: Inochi Amaoto <[email protected]> AuthorDate: Mon, 14 Apr 2025 06:49:15 +08:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Mon, 14 Apr 2025 19:35:36 +02:00
irqchip/sg2042-msi: Add the Sophgo SG2044 MSI interrupt controller
Add support for Sophgo SG2044 MSI interrupt controller.
--- drivers/irqchip/irq-sg2042-msi.c | 53 +++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-)
drivers/irqchip/irq-sg2042-msi.c +51 -2
@@ -94,6 +94,35 @@ static const struct irq_chip sg2042_msi_middle_irq_chip = { .irq_compose_msi_msg = sg2042_msi_irq_compose_msi_msg, }; +static void sg2044_msi_irq_ack (struct irq_data *d) +{ +struct sg204x_msi_chipdata *data =irq_data_get_irq_chip_data (d); + +writel (0 , (u32 *)data->reg_clr + d->hwirq); +irq_chip_ack_parent (d); +} + +static void sg2044_msi_irq_compose_msi_msg (struct irq_data *d,struct msi_msg *msg) +{ +struct sg204x_msi_chipdata *data =irq_data_get_irq_chip_data (d); +phys_addr_t doorbell = data->doorbell_addr +4 * (d->hwirq /32 ); + + msg->address_lo =lower_32_bits (doorbell); + msg->address_hi =upper_32_bits (doorbell); + msg->data = d->hwirq %32 ; +} + +static struct irq_chip sg2044_msi_middle_irq_chip = { + .name ="SG2044 MSI" , + .irq_ack = sg2044_msi_irq_ack, + .irq_mask = irq_chip_mask_parent, + .irq_unmask = irq_chip_unmask_parent, +#ifdef CONFIG_SMP + .irq_set_affinity = irq_chip_set_affinity_parent, +#endif + .irq_compose_msi_msg = sg2044_msi_irq_compose_msi_msg, +}; +static int sg204x_msi_parent_domain_alloc (struct irq_domain *domain,unsigned int virq,int hwirq) {struct sg204x_msi_chipdata *data = domain->host_data;
@@ -132,13 +161,11 @@ static int sg204x_msi_middle_domain_alloc(struct irq_domain *domain, unsigned inirq_domain_set_hwirq_and_chip (domain, virq + i, hwirq + i, data->chip_info->irqchip, data); } -return 0 ; err_hwirq:sg204x_msi_free_hwirq (data, hwirq, nr_irqs);irq_domain_free_irqs_parent (domain, virq, i); -return err; }
@@ -172,6 +199,22 @@ static const struct msi_parent_ops sg2042_msi_parent_ops = { .init_dev_msi_info = msi_lib_init_dev_msi_info, }; +#define SG2044_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ + MSI_FLAG_USE_DEF_CHIP_OPS) + +#define SG2044_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ + MSI_FLAG_PCI_MSIX) + +static const struct msi_parent_ops sg2044_msi_parent_ops = { + .required_flags =SG2044_MSI_FLAGS_REQUIRED , + .supported_flags =SG2044_MSI_FLAGS_SUPPORTED , + .chip_flags =MSI_CHIP_FLAG_SET_EOI |MSI_CHIP_FLAG_SET_ACK , + .bus_select_mask =MATCH_PCI_MSI , + .bus_select_token =DOMAIN_BUS_NEXUS , + .prefix ="SG2044-" , + .init_dev_msi_info = msi_lib_init_dev_msi_info, +}; +static int sg204x_msi_init_domains (struct sg204x_msi_chipdata *data,struct irq_domain *plic_domain,struct device *dev) {
@@ -265,8 +308,14 @@ static const struct sg204x_msi_chip_info sg2042_chip_info = { .parent_ops = &sg2042_msi_parent_ops, }; +static const struct sg204x_msi_chip_info sg2044_chip_info = { + .irqchip = &sg2044_msi_middle_irq_chip, + .parent_ops = &sg2044_msi_parent_ops, +}; +static const struct of_device_id sg2042_msi_of_match[] = { { .compatible ="sophgo,sg2042-msi" , .data = &sg2042_chip_info }, + { .compatible ="sophgo,sg2044-msi" , .data = &sg2044_chip_info }, { } };