* [PATCH 0/4] Add AST2700 INTC0/INTC1 support
@ 2026-02-05 6:07 Ryan Chen
2026-02-05 6:07 ` [PATCH 1/4] dt-bindings: interrupt-controller: aspeed: Add ASPEED AST2700 INTC0/INTC1 Ryan Chen
` (4 more replies)
0 siblings, 5 replies; 20+ messages in thread
From: Ryan Chen @ 2026-02-05 6:07 UTC (permalink / raw)
To: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Joel Stanley, Andrew Jeffery, Paul Walmsley, Palmer Dabbelt,
Albert Ou, Alexandre Ghiti
Cc: linux-kernel, devicetree, linux-arm-kernel, linux-aspeed,
linux-riscv, Ryan Chen
This series replaces the existing AST2700 interrupt controller binding
and driver. The original implementation was focused on a narrow,
PSP-centric view and could not fully describe the complexity of the
AST2700 interrupt fabric:
* It was focused primarily on the perspective of the Primary Service
Processor (PSP).
* It could not handle interrupt route configuration.
* It could not handle interrupt register protection.
By contrast, the new bindings and drivers describe the interrupt
controllers at the block-function level and provide a unified binding
design that can be used from the perspective of any of the four
integrated processors (the Primary, Secondary and Tertiary Service
Processors, and the Boot MCU):
* Can handle interrupt register protection.
* Can handle interrupt route configuration.
* Has a unified binding design that applies to the system perspective
of any integrated processors ({P,S,T}SP, BootMCU).
* Provides enough information for any of the {P,S,T}SP or BootMCU to
route interrupts intended for any of the other processors' interrupt
controllers.
There are no known upstream users of the existing binding. This series
removes it along with the associated driver after introducing the new
binding and driver at the start of this series.
The AST2700 interrupt architecture is built around two controller
designs. INTC0 routes interrupt outputs to upstream interrupt
controllers (e.g. the ARM GIC used by the PSP, as well as interrupt
controllers associated with other cores such as the SSP and TSP).
INTC1 is a banked secondary controller whose interrupt outputs feed
into INTC0 via INTM lines. Connections between the two interrupt
controllers are described in the devicetree using the
aspeed,interrupt-ranges property.
The INTC0 driver creates a hierarchical irqdomain under the selected
upstream interrupt controller. The INTC1 driver implements the INTM-fed
banked controller and exposes a linear interrupt namespace to its
parent.
The design intent of the binding is that, by default, the interrupt for
a given peripheral is routed to the processor consuming that
peripheral. To support this, the devicetree provided to the operating
environment for each processor should set its own processor-local
interrupt controller (e.g. the GIC for the Cortex-A35 PSP) as the
interrupt-parent of INTC0.
Information derived from interrupt-parent at each interrupt controller
is incorporated into the route resolution algorithm implemented in the
INTC0 driver.
Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com>
---
Ryan Chen (4):
dt-bindings: interrupt-controller: aspeed: Add ASPEED AST2700 INTC0/INTC1
irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support
irqchip/aspeed: Remove legacy AST2700 interrupt controller driver
dt-bindings: interrupt-controller: aspeed: Remove legacy AST2700 interrupt binding
.../interrupt-controller/aspeed,ast2700-intc.yaml | 90 ---
.../aspeed,ast2700-interrupt.yaml | 207 ++++++
drivers/irqchip/Kconfig | 11 +
drivers/irqchip/Makefile | 2 +-
drivers/irqchip/irq-aspeed-intc.c | 139 ----
drivers/irqchip/irq-ast2700-intc0-test.c | 474 +++++++++++++
drivers/irqchip/irq-ast2700-intc0.c | 770 +++++++++++++++++++++
drivers/irqchip/irq-ast2700-intc1.c | 345 +++++++++
drivers/irqchip/irq-ast2700.c | 105 +++
drivers/irqchip/irq-ast2700.h | 37 +
10 files changed, 1950 insertions(+), 230 deletions(-)
---
base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
change-id: 20260205-irqchip-7eaef3674de9
Best regards,
--
Ryan Chen <ryan_chen@aspeedtech.com>
^ permalink raw reply [flat|nested] 20+ messages in thread* [PATCH 1/4] dt-bindings: interrupt-controller: aspeed: Add ASPEED AST2700 INTC0/INTC1 2026-02-05 6:07 [PATCH 0/4] Add AST2700 INTC0/INTC1 support Ryan Chen @ 2026-02-05 6:07 ` Ryan Chen 2026-02-05 7:25 ` Rob Herring (Arm) 2026-02-05 8:53 ` Krzysztof Kozlowski 2026-02-05 6:07 ` [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support Ryan Chen ` (3 subsequent siblings) 4 siblings, 2 replies; 20+ messages in thread From: Ryan Chen @ 2026-02-05 6:07 UTC (permalink / raw) To: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti Cc: linux-kernel, devicetree, linux-arm-kernel, linux-aspeed, linux-riscv, Ryan Chen INTC0 is used to assert GIC if interrupt in INTC1 asserted. INTC1 is used to assert INTC0 if interrupt of modules asserted. Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com> --- .../aspeed,ast2700-interrupt.yaml | 207 +++++++++++++++++++++ 1 file changed, 207 insertions(+) diff --git a/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2700-interrupt.yaml b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2700-interrupt.yaml new file mode 100644 index 000000000000..8a27e1e667a1 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2700-interrupt.yaml @@ -0,0 +1,207 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/aspeed,ast2700-interrupt.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ASPEED AST2700 Interrupt Controllers (INTC0/INTC1) + +description: | + The ASPEED AST2700 SoC integrates two interrupt controller designs: + + - INTC0: Primary controller that routes interrupt sources to upstream, + processor-specific interrupt controllers + + - INTC1: Secondary controller whose interrupt outputs feed into + INTC0 + + The SoC contains four processors to which interrupts can be routed: + + - PSP: Primary Service Processor (Cortex-A35) + - SSP: Secondary Service Processor (Cortex-M4) + - TSP: Tertiary Sevice Processor (Cortex-M4) + - BMCU: Boot MCU (a RISC-V microcontroller) + + The following diagram illustrates the overall architecture of the + ASPEED AST2700 interrupt controllers: + + +-----------+ +-----------+ + | INTC0 | | INTC1(0)| + +-----------+ +-----------+ + | Router | +-------+ | Router | + | out int | + SOC0 + | out int | + +-----------+ | 0 0 <---+ INTx + | INTM | +-------+ + |PSP GIC <-|---+ . . | +Modules+ | . . <-----+ SOC1 + + +-----------+ | . . | +-------+ | . . | + INTx + + +-----------+ | . . | | . . | +Modules+ + |SSP NVIC <-|---+ . . <----------------+ . . | +-------+ + +-----------+ | . . | | . . | + +-----------+ | . . <-------- | . . | + |TSP NVIC <-|---+ . . | | ----+ . . | + +-----------+ | . . | | | | O P | + | . . | | | +-----------+ + | . . <---- | -------------------- + | . . | | | +-----------+ | + | M N | | ---------+ INTC1(1) | | + +-----------+ | +-----------+ | + | . | + | +-----------+ | + -------------+ INTC1(N) | | + +-----------+ | + +--------------+ | + + BMCU APLIC <-+--------------------------------------------- + +--------------+ + + INTC0 supports: + - 128 local peripheral interrupt inputs + - Fan-in from up to three INTC1 instances via banked interrupt lines (INTM) + - Local peripheral interrupt outputs + - Merged interrupt outputs + - Software interrupt outputs (SWINT) + - Configurable interrupt routes targeting the PSP, SSP, and TSP + + INTC1 supports: + - 192 local peripheral interrupt inputs + - Banked interrupt outputs (INTM, 5 x 6 banks x 32 interrupts per bank) + - Configurable interrupt routes targeting the PSP, SSP, TSP, and BMCU + + One INTC1 instance is always present, on the SoC's IO die. A further two + instances may be attached to the SoC's one INTC0 instance via LTPI (LVDS + Tunneling Protocol & Interface). + + Interrupt numbering model + ------------------------- + The binding uses a controller-local numbering model. Peripheral device + nodes use the INTCx local interrupt number (hwirq) in their 'interrupts' or + 'interrupts-extended' properties. + + For AST2700, INTC0 exposes the following (inclusive) input ranges: + + - 000..479: Independent interrupts + - 480..489: INTM0-INTM9 + - 490..499: INTM10-INTM19 + - 500..509: INTM20-INTM29 + - 510..519: INTM30-INTM39 + - 520..529: INTM40-INTM49 + + INTC0's (inclusive) output ranges are as follows: + + - 000..127: 1:1 local peripheral interrupt output to PSP + - 144..151: Software interrupts from the SSP output to PSP + - 152..159: Software interrupts from the TSP output to PSP + - 192..201: INTM0-INTM9 banked outputs to PSP + - 208..217: INTM30-INTM39 banked outputs to PSP + - 224..233: INTM40-INTM49 banked outputs to PSP + - 256..383: 1:1 local peripheral interrupt output to SSP + - 384..393: INTM10-INTM19 banked outputs to SSP + - 400..407: Software interrupts from the PSP output to SSP + - 408..415: Software interrupts from the TSP output to SSP + - 426..553: 1:1 local peripheral interrupt output to TSP + - 554..563: INTM20-INTM29 banked outputs to TSP + - 570..577: Software interrupts from the PSP output to TSP + - 578..585: Software interrupts from the SSP output to TSP + + Inputs and outputs for INTC1 instances are context-dependent. However, for the + first instance of INTC1, the (inclusive) output ranges are: + + - 00..05: INTM0-INTM5 + - 10..15: INTM10-INTM15 + - 20..25: INTM20-INTM25 + - 30..35: INTM30-INTM35 + - 40..45: INTM40-INTM45 + - 50..50: BootMCU + +maintainers: + - ryan_chen@aspeedtech.com + - andrew@codeconstruct.com.au + +properties: + compatible: + enum: + - aspeed,ast2700-intc0 + - aspeed,ast2700-intc1 + + reg: + maxItems: 1 + + interrupt-controller: true + + '#interrupt-cells': + const: 1 + description: | + Single cell encoding the INTC local interrupt number (hwirq). + + aspeed,interrupt-ranges: + description: | + Describes how ranges of controller output pins are routed to a parent + interrupt controller. + + Each range entry is encoded as: + + <out count phandle parent-specifier...> + + where: + - out: First controller interrupt output index in the range. + - count: Number of consecutive controller interrupt outputs and parent + interrupt inputs in this range. + - phandle: Phandle to the parent interrupt controller node. + - parent-specifier: Interrupt specifier, as defined by the parent + interrupt controller binding. + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 3 + items: + description: Range descriptors with a parent interrupt specifier. + +required: + - compatible + - reg + - interrupt-controller + - '#interrupt-cells' + - aspeed,interrupt-ranges + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + + intc0: interrupt-controller@12100000 { + compatible = "aspeed,ast2700-intc0-ic"; + reg = <0x12100000 0x3b00>; + interrupt-parent = <&gic>; + interrupt-controller; + #interrupt-cells = <1>; + + aspeed,interrupt-ranges = + <0 128 &gic GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, + <144 8 &gic GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>, + <152 8 &gic GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>, + <192 10 &gic GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>, + <208 10 &gic GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>, + <224 10 &gic GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>, + <256 128 &ssp_nvic 0 0 >, + <384 10 &ssp_nvic 160 0 >, + <400 8 &ssp_nvic 144 0 >, + <408 8 &ssp_nvic 152 0 >, + <426 128 &tsp_nvic 0 0 >, + <554 10 &tsp_nvic 160 0 >, + <570 8 &tsp_nvic 144 0 >, + <578 8 &tsp_nvic 152 0 >; + }; + + - | + intc1: interrupt-controller@14c18000 { + compatible = "aspeed,ast2700-intc1-ic"; + reg = <0x14c18000 0x400>; + interrupt-parent = <&intc0>; + interrupt-controller; + #interrupt-cells = <1>; + + aspeed,interrupt-ranges = + <0 6 &intc0 480>, + <10 6 &intc0 490>, + <20 6 &intc0 500>, + <30 6 &intc0 510>, + <40 6 &intc0 520>, + <50 1 &bootmcu_plic 0>; + }; -- 2.34.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 1/4] dt-bindings: interrupt-controller: aspeed: Add ASPEED AST2700 INTC0/INTC1 2026-02-05 6:07 ` [PATCH 1/4] dt-bindings: interrupt-controller: aspeed: Add ASPEED AST2700 INTC0/INTC1 Ryan Chen @ 2026-02-05 7:25 ` Rob Herring (Arm) 2026-02-05 8:53 ` Krzysztof Kozlowski 1 sibling, 0 replies; 20+ messages in thread From: Rob Herring (Arm) @ 2026-02-05 7:25 UTC (permalink / raw) To: Ryan Chen Cc: Andrew Jeffery, linux-aspeed, linux-riscv, Palmer Dabbelt, linux-kernel, Albert Ou, Krzysztof Kozlowski, devicetree, Paul Walmsley, Thomas Gleixner, linux-arm-kernel, Joel Stanley, Alexandre Ghiti, Conor Dooley On Thu, 05 Feb 2026 14:07:19 +0800, Ryan Chen wrote: > INTC0 is used to assert GIC if interrupt in INTC1 asserted. > INTC1 is used to assert INTC0 if interrupt of modules asserted. > > Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com> > --- > .../aspeed,ast2700-interrupt.yaml | 207 +++++++++++++++++++++ > 1 file changed, 207 insertions(+) > My bot found errors running 'make dt_binding_check' on your patch: yamllint warnings/errors: dtschema/dtc warnings/errors: Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2700-interrupt.example.dtb: /example-0/interrupt-controller@12100000: failed to match any schema with compatible: ['aspeed,ast2700-intc0-ic'] Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2700-interrupt.example.dtb: /example-1/interrupt-controller@14c18000: failed to match any schema with compatible: ['aspeed,ast2700-intc1-ic'] doc reference errors (make refcheckdocs): See https://patchwork.kernel.org/project/devicetree/patch/20260205-irqchip-v1-1-b0310e06c087@aspeedtech.com The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch. If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date: pip3 install dtschema --upgrade Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/4] dt-bindings: interrupt-controller: aspeed: Add ASPEED AST2700 INTC0/INTC1 2026-02-05 6:07 ` [PATCH 1/4] dt-bindings: interrupt-controller: aspeed: Add ASPEED AST2700 INTC0/INTC1 Ryan Chen 2026-02-05 7:25 ` Rob Herring (Arm) @ 2026-02-05 8:53 ` Krzysztof Kozlowski 1 sibling, 0 replies; 20+ messages in thread From: Krzysztof Kozlowski @ 2026-02-05 8:53 UTC (permalink / raw) To: Ryan Chen Cc: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, linux-kernel, devicetree, linux-arm-kernel, linux-aspeed, linux-riscv On Thu, Feb 05, 2026 at 02:07:19PM +0800, Ryan Chen wrote: > INTC0 is used to assert GIC if interrupt in INTC1 asserted. > INTC1 is used to assert INTC0 if interrupt of modules asserted. What happened with 20 revisions of previous discussions? Did you just ignore entire feedback? Best regards, Krzysztof ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support 2026-02-05 6:07 [PATCH 0/4] Add AST2700 INTC0/INTC1 support Ryan Chen 2026-02-05 6:07 ` [PATCH 1/4] dt-bindings: interrupt-controller: aspeed: Add ASPEED AST2700 INTC0/INTC1 Ryan Chen @ 2026-02-05 6:07 ` Ryan Chen 2026-02-05 14:40 ` kernel test robot ` (2 more replies) 2026-02-05 6:07 ` [PATCH 3/4] irqchip/aspeed: Remove legacy AST2700 interrupt controller driver Ryan Chen ` (2 subsequent siblings) 4 siblings, 3 replies; 20+ messages in thread From: Ryan Chen @ 2026-02-05 6:07 UTC (permalink / raw) To: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti Cc: linux-kernel, devicetree, linux-arm-kernel, linux-aspeed, linux-riscv, Ryan Chen The AST2700 interrupt fabric is shared by multiple integrated processors (PSP/SSP/TSP/BootMCU), each with its own interrupt controller and its own devicetree view of the system. As a result, interrupt routing cannot be treated as fixed: the valid route for a peripheral interrupt depends on which processor is consuming it. The INTC0 driver models this by creating a hierarchical irqdomain under the upstream interrupt controller selected by the interrupt-parent property in the devicetree. Information derived from this relationship is incorporated into the route resolution logic for the controller. The INTC1 driver implements the banked INTM-fed controller and forwards interrupts toward INTC0, without embedding assumptions about the final destination processor. Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com> --- drivers/irqchip/Kconfig | 11 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-ast2700-intc0-test.c | 474 +++++++++++++++++++ drivers/irqchip/irq-ast2700-intc0.c | 770 +++++++++++++++++++++++++++++++ drivers/irqchip/irq-ast2700-intc1.c | 345 ++++++++++++++ drivers/irqchip/irq-ast2700.c | 105 +++++ drivers/irqchip/irq-ast2700.h | 37 ++ 7 files changed, 1743 insertions(+) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index f334f49c9791..3cc0f3af0e1e 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -110,6 +110,17 @@ config AL_FIC help Support Amazon's Annapurna Labs Fabric Interrupt Controller. +config ASPEED_AST2700_INTC + bool "ASPEED AST2700 Interrupt Controller support" + depends on OF + depends on ARCH_ASPEED || COMPILE_TEST + select IRQ_DOMAIN_HIERARCHY + +config ASPEED_AST2700_INTC_TEST + bool "Tests for the ASPEED AST2700 Interrupt Controller" + depends on ASPEED_AST2700_INTC && KUNIT=y + default KUNIT_ALL_TESTS + config ATMEL_AIC_IRQ bool select GENERIC_IRQ_CHIP diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 6a229443efe0..51fdf269e436 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -88,6 +88,7 @@ obj-$(CONFIG_MVEBU_PIC) += irq-mvebu-pic.o obj-$(CONFIG_MVEBU_SEI) += irq-mvebu-sei.o obj-$(CONFIG_LS_EXTIRQ) += irq-ls-extirq.o obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o +obj-$(CONFIG_ASPEED_AST2700_INTC) += irq-ast2700.o irq-ast2700-intc0.o irq-ast2700-intc1.o obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o irq-aspeed-scu-ic.o obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-intc.o obj-$(CONFIG_STM32MP_EXTI) += irq-stm32mp-exti.o diff --git a/drivers/irqchip/irq-ast2700-intc0-test.c b/drivers/irqchip/irq-ast2700-intc0-test.c new file mode 100644 index 000000000000..d6bc19676b2e --- /dev/null +++ b/drivers/irqchip/irq-ast2700-intc0-test.c @@ -0,0 +1,474 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026 Code Construct + */ +#include <kunit/test.h> +#include "irq-ast2700.h" + +static void aspeed_intc0_resolve_route_bad_args(struct kunit *test) +{ + static const struct aspeed_intc_interrupt_range c1ranges[] = { 0 }; + static const aspeed_intc_output_t c1outs[] = { 0 }; + struct aspeed_intc_interrupt_range resolved; + const struct irq_domain c0domain = { 0 }; + + int rc; + + rc = aspeed_intc0_resolve_route(NULL, 0, c1outs, 0, c1ranges, NULL); + KUNIT_EXPECT_EQ(test, rc, -EINVAL); + + rc = aspeed_intc0_resolve_route(&c0domain, 0, c1outs, + ARRAY_SIZE(c1ranges), c1ranges, + &resolved); + KUNIT_EXPECT_EQ(test, rc, -ENODEV); + + rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs, + 0, c1ranges, &resolved); + KUNIT_EXPECT_EQ(test, rc, -ENODEV); +} + +static int +arm_gicv3_fwnode_read_string_array(const struct fwnode_handle *fwnode_handle, + const char *propname, const char **val, + size_t nval) +{ + if (!propname) + return -EINVAL; + + if (!val) + return 1; + + if (WARN_ON(nval != 1)) + return -EOVERFLOW; + + *val = "arm,gic-v3"; + return 1; +} + +static const struct fwnode_operations arm_gicv3_fwnode_ops = { + .property_read_string_array = arm_gicv3_fwnode_read_string_array, +}; + +static void aspeed_intc_resolve_route_invalid_c0domain(struct kunit *test) +{ + struct device_node intc0_node = { + .fwnode = { .ops = &arm_gicv3_fwnode_ops }, + }; + const struct irq_domain c0domain = { .fwnode = &intc0_node.fwnode }; + static const struct aspeed_intc_interrupt_range c1ranges[] = { 0 }; + static const aspeed_intc_output_t c1outs[] = { 0 }; + struct aspeed_intc_interrupt_range resolved; + int rc; + + rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs, + ARRAY_SIZE(c1ranges), c1ranges, + &resolved); + KUNIT_EXPECT_NE(test, rc, 0); +} + +static int +aspeed_intc0_fwnode_read_string_array(const struct fwnode_handle *fwnode_handle, + const char *propname, const char **val, + size_t nval) +{ + if (!propname) + return -EINVAL; + + if (!val) + return 1; + + if (WARN_ON(nval != 1)) + return -EOVERFLOW; + + *val = "aspeed,ast2700-intc0-ic"; + return nval; +} + +static const struct fwnode_operations intc0_fwnode_ops = { + .property_read_string_array = aspeed_intc0_fwnode_read_string_array, +}; + +static void +aspeed_intc0_resolve_route_c1i1o1c0i1o1_connected(struct kunit *test) +{ + struct device_node intc0_node = { + .fwnode = { .ops = &intc0_fwnode_ops }, + }; + struct aspeed_intc_interrupt_range c1ranges[] = { + { + .start = 0, + .count = 1, + .upstream = { + .fwnode = &intc0_node.fwnode, + .param_count = 1, + .param = { 128 } + } + } + }; + static const aspeed_intc_output_t c1outs[] = { 0 }; + struct aspeed_intc_interrupt_range resolved; + struct aspeed_intc_interrupt_range intc0_ranges[] = { + { + .start = 128, + .count = 1, + .upstream = { + .fwnode = NULL, + .param_count = 0, + .param = { 0 }, + } + } + }; + struct aspeed_intc0 intc0 = { + .ranges = { .ranges = intc0_ranges, .nranges = ARRAY_SIZE(intc0_ranges), } + }; + const struct irq_domain c0domain = { + .host_data = &intc0, + .fwnode = &intc0_node.fwnode + }; + int rc; + + rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs, + ARRAY_SIZE(c1ranges), c1ranges, + &resolved); + KUNIT_EXPECT_EQ(test, rc, 0); + KUNIT_EXPECT_EQ(test, resolved.start, 0); + KUNIT_EXPECT_EQ(test, resolved.count, 1); + KUNIT_EXPECT_EQ(test, resolved.upstream.param[0], 128); +} + +static void +aspeed_intc0_resolve_route_c1i1o1c0i1o1_disconnected(struct kunit *test) +{ + struct device_node intc0_node = { + .fwnode = { .ops = &intc0_fwnode_ops }, + }; + struct aspeed_intc_interrupt_range c1ranges[] = { + { + .start = 0, + .count = 1, + .upstream = { + .fwnode = &intc0_node.fwnode, + .param_count = 1, + .param = { 128 } + } + } + }; + static const aspeed_intc_output_t c1outs[] = { 0 }; + struct aspeed_intc_interrupt_range resolved; + struct aspeed_intc_interrupt_range intc0_ranges[] = { + { + .start = 129, + .count = 1, + .upstream = { + .fwnode = NULL, + .param_count = 0, + .param = { 0 }, + } + } + }; + struct aspeed_intc0 intc0 = { + .ranges = { + .ranges = intc0_ranges, + .nranges = ARRAY_SIZE(intc0_ranges), + } + }; + const struct irq_domain c0domain = { + .host_data = &intc0, + .fwnode = &intc0_node.fwnode + }; + int rc; + + rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs, + ARRAY_SIZE(c1ranges), c1ranges, + &resolved); + KUNIT_EXPECT_NE(test, rc, 0); +} + +static void aspeed_intc0_resolve_route_c1i1o1mc0i1o1(struct kunit *test) +{ + struct device_node intc0_node = { + .fwnode = { .ops = &intc0_fwnode_ops }, + }; + struct aspeed_intc_interrupt_range c1ranges[] = { + { + .start = 0, + .count = 1, + .upstream = { + .fwnode = &intc0_node.fwnode, + .param_count = 1, + .param = { 480 } + } + } + }; + static const aspeed_intc_output_t c1outs[] = { 0 }; + struct aspeed_intc_interrupt_range resolved; + struct aspeed_intc_interrupt_range intc0_ranges[] = { + { + .start = 192, + .count = 1, + .upstream = { + .fwnode = NULL, + .param_count = 0, + .param = { 0 }, + } + } + }; + struct aspeed_intc0 intc0 = { + .ranges = { + .ranges = intc0_ranges, + .nranges = ARRAY_SIZE(intc0_ranges), + } + }; + const struct irq_domain c0domain = { + .host_data = &intc0, + .fwnode = &intc0_node.fwnode + }; + int rc; + + rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs, + ARRAY_SIZE(c1ranges), c1ranges, + &resolved); + KUNIT_EXPECT_EQ(test, rc, 0); + KUNIT_EXPECT_EQ(test, resolved.start, 0); + KUNIT_EXPECT_EQ(test, resolved.count, 1); + KUNIT_EXPECT_EQ(test, resolved.upstream.param[0], 480); +} + +static void aspeed_intc0_resolve_route_c1i2o2mc0i1o1(struct kunit *test) +{ + struct device_node intc0_node = { + .fwnode = { .ops = &intc0_fwnode_ops }, + }; + struct aspeed_intc_interrupt_range c1ranges[] = { + { + .start = 0, + .count = 1, + .upstream = { + .fwnode = &intc0_node.fwnode, + .param_count = 1, + .param = { 480 } + } + }, + { + .start = 1, + .count = 1, + .upstream = { + .fwnode = &intc0_node.fwnode, + .param_count = 1, + .param = { 510 } + } + } + }; + static const aspeed_intc_output_t c1outs[] = { 1 }; + struct aspeed_intc_interrupt_range resolved; + struct aspeed_intc_interrupt_range intc0_ranges[] = { + { + .start = 208, + .count = 1, + .upstream = { + .fwnode = NULL, + .param_count = 0, + .param = { 0 }, + } + } + }; + struct aspeed_intc0 intc0 = { + .ranges = { + .ranges = intc0_ranges, + .nranges = ARRAY_SIZE(intc0_ranges), + } + }; + const struct irq_domain c0domain = { + .host_data = &intc0, + .fwnode = &intc0_node.fwnode + }; + int rc; + + rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs, + ARRAY_SIZE(c1ranges), c1ranges, + &resolved); + KUNIT_EXPECT_EQ(test, rc, 0); + KUNIT_EXPECT_EQ(test, resolved.start, 1); + KUNIT_EXPECT_EQ(test, resolved.count, 1); + KUNIT_EXPECT_EQ(test, resolved.upstream.param[0], 510); +} + +static void aspeed_intc0_resolve_route_c1i1o1mc0i2o1(struct kunit *test) +{ + struct device_node intc0_node = { + .fwnode = { .ops = &intc0_fwnode_ops }, + }; + struct aspeed_intc_interrupt_range c1ranges[] = { + { + .start = 0, + .count = 1, + .upstream = { + .fwnode = &intc0_node.fwnode, + .param_count = 1, + .param = { 510 } + } + }, + }; + static const aspeed_intc_output_t c1outs[] = { 0 }; + struct aspeed_intc_interrupt_range resolved; + struct aspeed_intc_interrupt_range intc0_ranges[] = { + { + .start = 192, + .count = 1, + .upstream = { + .fwnode = NULL, + .param_count = 0, + .param = {0}, + } + }, + { + .start = 208, + .count = 1, + .upstream = { + .fwnode = NULL, + .param_count = 0, + .param = {0}, + } + } + }; + struct aspeed_intc0 intc0 = { + .ranges = { + .ranges = intc0_ranges, + .nranges = ARRAY_SIZE(intc0_ranges), + } + }; + const struct irq_domain c0domain = { + .host_data = &intc0, + .fwnode = &intc0_node.fwnode + }; + int rc; + + rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs, + ARRAY_SIZE(c1ranges), c1ranges, + &resolved); + KUNIT_EXPECT_EQ(test, rc, 0); + KUNIT_EXPECT_EQ(test, resolved.start, 0); + KUNIT_EXPECT_EQ(test, resolved.count, 1); + KUNIT_EXPECT_EQ(test, resolved.upstream.param[0], 510); +} + +static void aspeed_intc0_resolve_route_c1i1o2mc0i1o1_invalid(struct kunit *test) +{ + struct device_node intc0_node = { + .fwnode = { .ops = &intc0_fwnode_ops }, + }; + struct aspeed_intc_interrupt_range c1ranges[] = { + { + .start = 0, + .count = 1, + .upstream = { + .fwnode = &intc0_node.fwnode, + .param_count = 1, + .param = { 480 } + } + } + }; + static const aspeed_intc_output_t c1outs[] = { + AST2700_INTC_INVALID_ROUTE, 0 + }; + struct aspeed_intc_interrupt_range resolved; + struct aspeed_intc_interrupt_range intc0_ranges[] = { + { + .start = 192, + .count = 1, + .upstream = { + .fwnode = NULL, + .param_count = 0, + .param = { 0 }, + } + } + }; + struct aspeed_intc0 intc0 = { + .ranges = { + .ranges = intc0_ranges, + .nranges = ARRAY_SIZE(intc0_ranges), + } + }; + const struct irq_domain c0domain = { + .host_data = &intc0, + .fwnode = &intc0_node.fwnode + }; + int rc; + + rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs, + ARRAY_SIZE(c1ranges), c1ranges, + &resolved); + KUNIT_EXPECT_EQ(test, rc, 1); + KUNIT_EXPECT_EQ(test, resolved.start, 0); + KUNIT_EXPECT_EQ(test, resolved.count, 1); + KUNIT_EXPECT_EQ(test, resolved.upstream.param[0], 480); +} + +static void +aspeed_intc0_resolve_route_c1i1o1mc0i1o1_bad_range_upstream(struct kunit *test) +{ + struct device_node intc0_node = { + .fwnode = { .ops = &intc0_fwnode_ops }, + }; + struct aspeed_intc_interrupt_range c1ranges[] = { + { + .start = 0, + .count = 1, + .upstream = { + .fwnode = &intc0_node.fwnode, + .param_count = 0, + .param = { 0 } + } + } + }; + static const aspeed_intc_output_t c1outs[] = { 0 }; + struct aspeed_intc_interrupt_range resolved; + struct aspeed_intc_interrupt_range intc0_ranges[] = { + { + .start = 0, + .count = 0, + .upstream = { + .fwnode = NULL, + .param_count = 0, + .param = { 0 }, + } + } + }; + struct aspeed_intc0 intc0 = { + .ranges = { + .ranges = intc0_ranges, + .nranges = ARRAY_SIZE(intc0_ranges), + } + }; + const struct irq_domain c0domain = { + .host_data = &intc0, + .fwnode = &intc0_node.fwnode + }; + int rc; + + rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs, + ARRAY_SIZE(c1ranges), c1ranges, + &resolved); + KUNIT_EXPECT_NE(test, rc, 0); +} + +static struct kunit_case ast2700_intc0_test_cases[] = { + KUNIT_CASE(aspeed_intc0_resolve_route_bad_args), + KUNIT_CASE(aspeed_intc_resolve_route_invalid_c0domain), + KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o1c0i1o1_connected), + KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o1c0i1o1_disconnected), + KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o1mc0i1o1), + KUNIT_CASE(aspeed_intc0_resolve_route_c1i2o2mc0i1o1), + KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o1mc0i2o1), + KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o2mc0i1o1_invalid), + KUNIT_CASE(aspeed_intc0_resolve_route_c1i1o1mc0i1o1_bad_range_upstream), + {}, +}; + +static struct kunit_suite ast2700_intc0_test_suite = { + .name = "ast2700-intc0", + .test_cases = ast2700_intc0_test_cases, +}; +kunit_test_suite(ast2700_intc0_test_suite); + +MODULE_LICENSE("GPL"); diff --git a/drivers/irqchip/irq-ast2700-intc0.c b/drivers/irqchip/irq-ast2700-intc0.c new file mode 100644 index 000000000000..722457dd2e18 --- /dev/null +++ b/drivers/irqchip/irq-ast2700-intc0.c @@ -0,0 +1,770 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Aspeed Interrupt Controller. + * + * Copyright (C) 2023 ASPEED Technology Inc. + */ + +#include <asm-generic/errno.h> +#include <linux/bitops.h> +#include <linux/device.h> +#include <linux/fwnode.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/irqchip.h> +#include <linux/irqchip/chained_irq.h> +#include <linux/irqdomain.h> +#include <linux/kconfig.h> +#include <linux/of.h> +#include <linux/of_irq.h> +#include <linux/property.h> +#include <linux/spinlock.h> + +#include <dt-bindings/interrupt-controller/arm-gic.h> + +#include "irq-ast2700.h" +#define INT_NUM 480 +#define INTM_NUM 50 +#define SWINT_NUM 16 + +#define INTM_BASE (INT_NUM) +#define SWINT_BASE (INT_NUM + INTM_NUM) +#define INT0_NUM (INT_NUM + INTM_NUM + SWINT_NUM) + +#define GIC_P2P_SPI_END 128 + +#define INTC0_SWINT_IER 0x10 +#define INTC0_SWINT_ISR 0x14 +#define INTC0_INTBANKX_IER 0x1000 +#define INTC0_INTBANK_GROUPS 11 +#define INTC0_INTBANKS_PER_GRP 3 +#define INTC0_INTMX_IER 0x1b00 +#define INTC0_INTMX_ISR 0x1b04 +#define INTC0_INTM_BANK_NUM 3 +#define INTM_IRQS_PER_BANK 10 + +struct aspeed_intc0 { + struct device *dev; + void __iomem *base; + raw_spinlock_t intc_lock; + struct irq_domain *local; + struct device_node *parent; + struct aspeed_intc_interrupt_ranges ranges; +}; + +static void aspeed_swint_irq_mask(struct irq_data *data) +{ + struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data); + int bit = data->hwirq - SWINT_BASE; + unsigned int mask; + + guard(raw_spinlock_irqsave)(&intc0->intc_lock); + mask = readl(intc0->base + INTC0_SWINT_IER) & ~BIT(bit); + writel(mask, intc0->base + INTC0_SWINT_IER); + irq_chip_mask_parent(data); +} + +static void aspeed_swint_irq_unmask(struct irq_data *data) +{ + struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data); + int bit = data->hwirq - SWINT_BASE; + unsigned int unmask; + + guard(raw_spinlock_irqsave)(&intc0->intc_lock); + unmask = readl(intc0->base + INTC0_SWINT_IER) | BIT(bit); + writel(unmask, intc0->base + INTC0_SWINT_IER); + irq_chip_unmask_parent(data); +} + +static void aspeed_swint_irq_eoi(struct irq_data *data) +{ + struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data); + int bit = data->hwirq - SWINT_BASE; + + writel(BIT(bit), intc0->base + INTC0_SWINT_ISR); + irq_chip_eoi_parent(data); +} + +static struct irq_chip aspeed_swint_chip = { + .name = "ast2700-swint", + .irq_eoi = aspeed_swint_irq_eoi, + .irq_mask = aspeed_swint_irq_mask, + .irq_unmask = aspeed_swint_irq_unmask, + .irq_set_affinity = irq_chip_set_affinity_parent, + .flags = IRQCHIP_SET_TYPE_MASKED, +}; + +static void aspeed_intc0_irq_mask(struct irq_data *data) +{ + struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data); + int bank = (data->hwirq - INTM_BASE) / INTM_IRQS_PER_BANK; + int bit = (data->hwirq - INTM_BASE) % INTM_IRQS_PER_BANK; + unsigned int mask; + + guard(raw_spinlock_irqsave)(&intc0->intc_lock); + mask = readl(intc0->base + INTC0_INTMX_IER + bank * 0x10) & ~BIT(bit); + writel(mask, intc0->base + INTC0_INTMX_IER + bank * 0x10); + irq_chip_mask_parent(data); +} + +static void aspeed_intc0_irq_unmask(struct irq_data *data) +{ + struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data); + int bank = (data->hwirq - INTM_BASE) / INTM_IRQS_PER_BANK; + int bit = (data->hwirq - INTM_BASE) % INTM_IRQS_PER_BANK; + unsigned int unmask; + + guard(raw_spinlock_irqsave)(&intc0->intc_lock); + unmask = readl(intc0->base + INTC0_INTMX_IER + bank * 0x10) | BIT(bit); + writel(unmask, intc0->base + INTC0_INTMX_IER + bank * 0x10); + irq_chip_unmask_parent(data); +} + +static void aspeed_intc0_irq_eoi(struct irq_data *data) +{ + struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data); + int bank = (data->hwirq - INTM_BASE) / INTM_IRQS_PER_BANK; + int bit = (data->hwirq - INTM_BASE) % INTM_IRQS_PER_BANK; + + writel(BIT(bit), intc0->base + INTC0_INTMX_ISR + bank * 0x10); + irq_chip_eoi_parent(data); +} + +static struct irq_chip aspeed_intm_chip = { + .name = "ast2700-intmerge", + .irq_eoi = aspeed_intc0_irq_eoi, + .irq_mask = aspeed_intc0_irq_mask, + .irq_unmask = aspeed_intc0_irq_unmask, + .irq_set_affinity = irq_chip_set_affinity_parent, + .flags = IRQCHIP_SET_TYPE_MASKED, +}; + +static struct irq_chip linear_intr_irq_chip = { + .name = "ast2700-int", + .irq_eoi = irq_chip_eoi_parent, + .irq_mask = irq_chip_mask_parent, + .irq_unmask = irq_chip_unmask_parent, + .irq_set_affinity = irq_chip_set_affinity_parent, + .flags = IRQCHIP_SET_TYPE_MASKED, +}; + +#define INTC0_IN_NUM 480 +#define INTC0_ROUTE_NUM 5 + +static const aspeed_intc_output_t aspeed_intc0_routes[INTC0_IN_NUM / 32][INTC0_ROUTE_NUM] = { + [0] = { + [0b000] = 0, + [0b001] = 256, + [0b010] = 426, + [0b011] = AST2700_INTC_INVALID_ROUTE, + [0b100] = AST2700_INTC_INVALID_ROUTE, + }, + [1] = { + [0b000] = 32, + [0b001] = 288, + [0b010] = 458, + [0b011] = AST2700_INTC_INVALID_ROUTE, + [0b100] = AST2700_INTC_INVALID_ROUTE, + }, + [2] = { + [0b000] = 64, + [0b001] = 320, + [0b010] = 490, + [0b011] = AST2700_INTC_INVALID_ROUTE, + [0b100] = AST2700_INTC_INVALID_ROUTE, + }, + [3] = { + [0b000] = 96, + [0b001] = 352, + [0b010] = 522, + [0b011] = AST2700_INTC_INVALID_ROUTE, + [0b100] = AST2700_INTC_INVALID_ROUTE, + }, + [4] = { + [0b000] = 128, + [0b001] = 384, + [0b010] = 554, + [0b011] = 160, + [0b100] = 176, + }, + [5] = { + [0b000] = 129, + [0b001] = 385, + [0b010] = 555, + [0b011] = 161, + [0b100] = 177, + }, + [6] = { + [0b000] = 130, + [0b001] = 386, + [0b010] = 556, + [0b011] = 162, + [0b100] = 178, + }, + [7] = { + [0b000] = 131, + [0b001] = 387, + [0b010] = 557, + [0b011] = 163, + [0b100] = 179, + }, + [8] = { + [0b000] = 132, + [0b001] = 388, + [0b010] = 558, + [0b011] = 164, + [0b100] = 180, + + }, + [9] = { + [0b000] = 133, + [0b001] = 544, + [0b010] = 714, + [0b011] = 165, + [0b100] = 181, + }, + [10] = { + [0b000] = 134, + [0b001] = 545, + [0b010] = 715, + [0b011] = 166, + [0b100] = 182, + }, + [11] = { + [0b000] = 135, + [0b001] = 546, + [0b010] = 706, + [0b011] = 167, + [0b100] = 183, + }, + [12] = { + [0b000] = 136, + [0b001] = 547, + [0b010] = 707, + [0b011] = 168, + [0b100] = 184, + + }, + [13] = { + [0b000] = 137, + [0b001] = 548, + [0b010] = 708, + [0b011] = 169, + [0b100] = 185, + + }, + [14] = { + [0b000] = 138, + [0b001] = 549, + [0b010] = 709, + [0b011] = 170, + [0b100] = 186, + }, +}; + +#define INTC0_INTM_NUM 50 + +static const aspeed_intc_output_t + aspeed_intc0_intm_routes[INTC0_INTM_NUM / 10] = { + [0] = 192, /* INTM00 ~ INTM09 */ + [1] = 416, /* INTM10 ~ INTM19 */ + [2] = 586, /* INTM20 ~ INTM29 */ + [3] = 208, /* INTM30 ~ INTM39 */ + [4] = 224, /* INTM40 ~ INTM49 */ + }; + +static bool range_contains_element(u32 start, u32 count, u32 value) +{ + if (WARN_ON_ONCE((U32_MAX - count) < start)) + return false; + + return value >= start && value < start + count; +} + +static int +resolve_input_from_child_ranges(const struct aspeed_intc0 *intc0, + const struct aspeed_intc_interrupt_range *range, + u32 outpin, u32 *input) +{ + u32 offset; + u32 base; + + if (!range_contains_element(range->start, range->count, outpin)) + return -ENOENT; + + if (range->upstream.param_count == 0) + return -EINVAL; + + base = range->upstream.param[0]; + offset = outpin - range->start; + if ((U32_MAX - offset) < base) { + dev_warn(intc0->dev, + "%s: Arithmetic overflow for input derivation: %u + %u\n", + __func__, base, offset); + return -EINVAL; + } + + *input = base + offset; + return 0; +} + +static bool resolve_parent_range_for_output(const struct aspeed_intc0 *intc0, + const struct fwnode_handle *parent, + u32 output, + struct aspeed_intc_interrupt_range *resolved) +{ + for (size_t i = 0; i < intc0->ranges.nranges; i++) { + struct aspeed_intc_interrupt_range range = + intc0->ranges.ranges[i]; + + dev_dbg(intc0->dev, + "%s: Inspecting candidate parent range %zu starting at %u for %u\n", + __func__, i, range.start, range.count); + if (!range_contains_element(range.start, range.count, output)) { + dev_dbg(intc0->dev, "%s: Output %u not in range [%u, %u)\n", + __func__, output, range.start, range.start + range.count); + continue; + } + + if (range.upstream.fwnode != parent) { + dev_dbg(intc0->dev, "%s: Parent mismatch for range %zu\n", __func__, i); + continue; + } + + dev_dbg(intc0->dev, "%s: Parent range %zu matched for output %u\n", + __func__, i, output); + + if (resolved) { + resolved->start = output; + resolved->count = 1; + resolved->upstream = range.upstream; + resolved->upstream.param[1] += output - range.start; + } + + return true; + } + + return false; +} + +static int resolve_parent_route_for_input(const struct aspeed_intc0 *intc0, + const struct fwnode_handle *parent, u32 input, + struct aspeed_intc_interrupt_range *resolved) +{ + aspeed_intc_output_t c0o; + int rc = -ENOENT; + + if (input < INT_NUM) { + bool found; + + dev_dbg(intc0->dev, "%s: Resolving parent route for linear input %u\n", + __func__, input); + static_assert(INTC0_ROUTE_NUM < INT_MAX, "Broken cast"); + for (size_t i = 0; rc == -ENOENT && i < INTC0_ROUTE_NUM; i++) { + c0o = aspeed_intc0_routes[input / 32][i]; + if (c0o == AST2700_INTC_INVALID_ROUTE) + continue; + + if (input < GIC_P2P_SPI_END) + c0o += input % 32; + + found = resolve_parent_range_for_output(intc0, parent, c0o, resolved); + rc = found ? (int)i : -ENOENT; + } + } else if (input < (INT_NUM + INTM_NUM)) { + bool found; + + dev_dbg(intc0->dev, "%s: Resolving parent route for merged input %u\n", + __func__, input); + c0o = aspeed_intc0_intm_routes[(input - INT_NUM) / INTM_IRQS_PER_BANK]; + c0o += ((input - INT_NUM) % INTM_IRQS_PER_BANK); + + found = resolve_parent_range_for_output(intc0, parent, c0o, resolved); + rc = found ? 0 : -ENOENT; + } else if (input < (INT_NUM + INTM_NUM + SWINT_NUM)) { + bool found; + + dev_dbg(intc0->dev, "%s: Resolving parent route for merged input %u\n", + __func__, input); + c0o = input - SWINT_BASE + 144; + found = resolve_parent_range_for_output(intc0, parent, c0o, resolved); + rc = found ? 0 : -ENOENT; + } else { + dev_dbg(intc0->dev, "%s: Invalid input: %u\n", __func__, input); + return -ENOENT; + } + + if (rc < 0) { + dev_dbg(intc0->dev, + "%s: Failed to resolve INTC0 parent route for input %u: %d\n", + __func__, input, rc); + } else { + dev_dbg(intc0->dev, + "%s: Resolved INTC0 input %u route to parent via %d\n", + __func__, input, rc); + } + + return rc; +} + +/** + * aspeed_intc0_resolve_route - Determine the necessary interrupt output at intc1 + * @c0domain: The pointer to intc0's irq_domain + * @nc1outs: The number of valid intc1 outputs available for the input + * @c1outs: The array of available intc1 output indices for the input + * @nc1ranges: The number of interrupt range entries for intc1 + * @c1ranges: The array of configured intc1 interrupt ranges + * @resolved: The fully resolved range entry after applying the resolution + * algorithm + * + * Returns: The intc1 route index associated with the intc1 output identified in + * @resolved on success. Otherwise, a negative errno value. + * + * The AST2700 interrupt architecture allows any peripheral interrupt source + * to be routed to one of up to four processors running in the SoC. A processor + * binding a driver for a peripheral that requests an interrupt is (without + * further design and effort) the destination for the requested interrupt. + * + * Routing a peripheral interrupt to its destination processor requires + * coordination between INTC0 on the CPU die and one or more INTC1 instances. + * At least one INTC1 instance exists in the SoC on the IO-die, however up + * to two more instances may be integrated via LTPI (LVDS Tunneling Protocol + * & Interface). + * + * Between the multiple destinations, various route constraints, and the + * devicetree binding design, some information that's needed at INTC1 instances + * to route inbound interrupts correctly to the destination processor is only + * available at INTC0. + * + * aspeed_intc0_resolve_route() is to be invoked by INTC1 driver instances to + * perform the route resolution. The implementation in INTC0 allows INTC0 to + * encapsulate the information used to perform route selection, and provides it + * with an opportunity to apply policy as part of the selection process. Such + * policy may, for instance, choose to de-prioritise some interrupts destined + * for the PSP (Primary Service Processor) GIC. + */ +int aspeed_intc0_resolve_route(const struct irq_domain *c0domain, size_t nc1outs, + const aspeed_intc_output_t c1outs[static nc1outs], + size_t nc1ranges, + const struct aspeed_intc_interrupt_range c1ranges[static nc1ranges], + struct aspeed_intc_interrupt_range *resolved) +{ + struct aspeed_intc0 *intc0; + struct fwnode_handle *parent_fwnode; + int ret; + + if (!c0domain || !resolved) + return -EINVAL; + + if (nc1outs > INT_MAX) + return -EINVAL; + + if (nc1outs == 0 || nc1ranges == 0) + return -ENODEV; + + if (!fwnode_device_is_compatible(c0domain->fwnode, + "aspeed,ast2700-intc0-ic")) + return -ENODEV; + + intc0 = c0domain->host_data; + if (!intc0) + return -EINVAL; + + parent_fwnode = of_fwnode_handle(intc0->parent); + + for (size_t i = 0; i < nc1outs; i++) { + aspeed_intc_output_t c1o = c1outs[i]; + + if (c1o == AST2700_INTC_INVALID_ROUTE) { + dev_dbg(intc0->dev, "%s: Invalid output at route index %zu\n", + __func__, i); + continue; + } + + dev_dbg(intc0->dev, "%s: Have output %u for route index %zu\n", + __func__, c1o, i); + + for (size_t j = 0; j < nc1ranges; j++) { + struct aspeed_intc_interrupt_range c1r = c1ranges[j]; + u32 input; + + dev_dbg(intc0->dev, + "%s: Inspecting candidate range %zu starting at %u for %u\n", + __func__, j, c1r.start, c1r.count); + + /* + * Range match for intc1 output pin + * + * Assume a failed match is still a match for the purpose of testing, + * saves a bunch of mess in the test fixtures + */ + if (!(c0domain == irq_find_matching_fwspec(&c1r.upstream, + c0domain->bus_token) || + IS_ENABLED(CONFIG_ASPEED_AST2700_INTC_TEST))) { + dev_dbg(intc0->dev, "%s: Parent mismatch for candidate range %zu\n", + __func__, j); + continue; + } + + ret = resolve_input_from_child_ranges(intc0, &c1r, c1o, &input); + if (ret) { + if (ret == -ENOENT) + dev_dbg(intc0->dev, + "%s: Output %u not in candidate range %zu starting at %u for %u\n", + __func__, c1o, j, c1r.start, c1r.count); + continue; + } + dev_dbg(intc0->dev, + "%s: Resolved INTC0 input to %u using candidate range %zu: [%u, %u)\n", + __func__, input, j, c1r.start, c1r.start + c1r.count); + + /* + * INTC1 should never request routes for peripheral interrupt sources + * directly attached to INTC0. + */ + if (input < GIC_P2P_SPI_END) { + dev_dbg(intc0->dev, + "%s: Invalid range specification at index %zu routed INTC1 output to unreachable INTC0 input\n", + __func__, j); + continue; + } + + ret = resolve_parent_route_for_input(intc0, parent_fwnode, input, NULL); + if (ret < 0) + continue; + + /* Route resolution succeeded */ + resolved->start = c1o; + resolved->count = 1; + resolved->upstream = c1r.upstream; + resolved->upstream.param[0] = input; + dev_dbg(intc0->dev, + "%s: Route resolution selected INTC1 output %u via index %zu\n", + __func__, c1o, i); + /* Cast protected by prior test against nc1outs */ + return (int)i; + } + } + + ret = -EHOSTUNREACH; + return ret; +} +EXPORT_SYMBOL_GPL(aspeed_intc0_resolve_route); + +static int aspeed_intc0_irq_domain_map(struct irq_domain *domain, + unsigned int irq, irq_hw_number_t hwirq) +{ + if (hwirq < GIC_P2P_SPI_END) + irq_set_chip_and_handler(irq, &linear_intr_irq_chip, + handle_level_irq); + else if (hwirq < INTM_BASE) + return -EINVAL; + else if (hwirq < SWINT_BASE) + irq_set_chip_and_handler(irq, &aspeed_intm_chip, + handle_level_irq); + else if (hwirq < INT0_NUM) + irq_set_chip_and_handler(irq, &aspeed_swint_chip, + handle_level_irq); + else + return -EINVAL; + + irq_set_chip_data(irq, domain->host_data); + return 0; +} + +static int aspeed_intc0_irq_domain_translate(struct irq_domain *domain, + struct irq_fwspec *fwspec, + unsigned long *hwirq, + unsigned int *type) +{ + if (fwspec->param_count != 1) + return -EINVAL; + + *hwirq = fwspec->param[0]; + *type = IRQ_TYPE_NONE; + return 0; +} + +static int aspeed_intc0_irq_domain_alloc(struct irq_domain *domain, + unsigned int virq, + unsigned int nr_irqs, void *data) +{ + struct aspeed_intc0 *intc0 = domain->host_data; + struct aspeed_intc_interrupt_range resolved; + struct irq_fwspec *fwspec = data; + struct irq_fwspec parent_fwspec; + struct irq_chip *chip; + unsigned long hwirq; + unsigned int type; + int ret; + + ret = aspeed_intc0_irq_domain_translate(domain, fwspec, &hwirq, &type); + if (ret) + return ret; + + if (hwirq >= GIC_P2P_SPI_END && hwirq < INT_NUM) + return -EINVAL; + + if (hwirq < INTM_BASE) + chip = &linear_intr_irq_chip; + else if (hwirq < SWINT_BASE) + chip = &aspeed_intm_chip; + else + chip = &aspeed_swint_chip; + + ret = resolve_parent_route_for_input(intc0, domain->parent->fwnode, + (u32)hwirq, &resolved); + if (ret) + return ret; + + parent_fwspec = resolved.upstream; + ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, + &parent_fwspec); + if (ret) + return ret; + + for (int i = 0; i < nr_irqs; ++i, ++hwirq, ++virq) { + ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, chip, + domain->host_data); + if (ret) + return ret; + } + + return 0; +} + +static int aspeed_intc0_irq_domain_activate(struct irq_domain *domain, + struct irq_data *data, bool reserve) +{ + struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data); + + if (data->hwirq < INT_NUM) { + int bank = data->hwirq / 32; + int bit = data->hwirq % 32; + u32 mask = BIT(bit); + int route; + + route = resolve_parent_route_for_input(intc0, + intc0->local->parent->fwnode, + data->hwirq, NULL); + if (route < 0) + return route; + + guard(raw_spinlock_irqsave)(&intc0->intc_lock); + for (int i = 0; i < 3; i++) { + void __iomem *sel = intc0->base + 0x200 + bank * 4 + 0x100 * i; + u32 reg = readl(sel); + + if (route & BIT(i)) + reg |= mask; + else + reg &= ~mask; + + writel(reg, sel); + if (readl(sel) != reg) + return -EACCES; + } + } else if (data->hwirq < INT0_NUM) { + return 0; + } else { + return -EINVAL; + } + + return 0; +} + +static const struct irq_domain_ops aspeed_intc0_ic_irq_domain_ops = { + .translate = aspeed_intc0_irq_domain_translate, + .alloc = aspeed_intc0_irq_domain_alloc, + .free = irq_domain_free_irqs_common, + .map = aspeed_intc0_irq_domain_map, + .activate = aspeed_intc0_irq_domain_activate, +}; + +static void aspeed_intc0_disable_swint(struct aspeed_intc0 *intc0) +{ + writel(0, intc0->base + INTC0_SWINT_IER); +} + +static void aspeed_intc0_disable_intbank(struct aspeed_intc0 *intc0) +{ + int i, j; + + for (i = 0; i < INTC0_INTBANK_GROUPS; i++) { + for (j = 0; j < INTC0_INTBANKS_PER_GRP; j++) { + u32 base = INTC0_INTBANKX_IER + (0x100 * i) + (0x10 * j); + + writel(0, intc0->base + base); + } + } +} + +static void aspeed_intc0_disable_intm(struct aspeed_intc0 *intc0) +{ + int i; + + for (i = 0; i < INTC0_INTM_BANK_NUM; i++) + writel(0, intc0->base + INTC0_INTMX_IER + (0x10 * i)); +} + +static int aspeed_intc0_ic_probe(struct platform_device *pdev, + struct device_node *parent) +{ + struct device_node *node = pdev->dev.of_node; + struct irq_domain *parent_domain; + struct aspeed_intc0 *intc0; + int ret; + + if (!parent) { + pr_err("missing parent interrupt node\n"); + return -ENODEV; + } + + intc0 = devm_kzalloc(&pdev->dev, sizeof(*intc0), GFP_KERNEL); + if (!intc0) + return -ENOMEM; + + intc0->dev = &pdev->dev; + intc0->parent = parent; + intc0->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(intc0->base)) + return PTR_ERR(intc0->base); + + aspeed_intc0_disable_swint(intc0); + aspeed_intc0_disable_intbank(intc0); + aspeed_intc0_disable_intm(intc0); + + raw_spin_lock_init(&intc0->intc_lock); + + parent_domain = irq_find_host(parent); + if (!parent_domain) { + pr_err("unable to obtain parent domain\n"); + return -ENODEV; + } + + if (!of_device_is_compatible(parent, "arm,gic-v3")) + return -ENODEV; + + intc0->local = irq_domain_create_hierarchy(parent_domain, 0, INT0_NUM, + of_fwnode_handle(node), + &aspeed_intc0_ic_irq_domain_ops, + intc0); + if (!intc0->local) + return -ENOMEM; + + ret = aspeed_intc_populate_ranges(&pdev->dev, &intc0->ranges); + if (ret < 0) { + irq_domain_remove(intc0->local); + return ret; + } + + return 0; +} + +IRQCHIP_PLATFORM_DRIVER_BEGIN(ast2700_intc0) +IRQCHIP_MATCH("aspeed,ast2700-intc0-ic", aspeed_intc0_ic_probe) +IRQCHIP_PLATFORM_DRIVER_END(ast2700_intc0) + +#ifdef CONFIG_ASPEED_AST2700_INTC_TEST +#include "irq-ast2700-intc0-test.c" +#endif diff --git a/drivers/irqchip/irq-ast2700-intc1.c b/drivers/irqchip/irq-ast2700-intc1.c new file mode 100644 index 000000000000..51371cc57c5c --- /dev/null +++ b/drivers/irqchip/irq-ast2700-intc1.c @@ -0,0 +1,345 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Aspeed AST2700 Interrupt Controller. + * + * Copyright (C) 2023 ASPEED Technology Inc. + */ + +#include "linux/dev_printk.h" +#include "linux/device/devres.h" +#include "linux/property.h" +#include <linux/bitops.h> +#include <linux/device.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/irqchip.h> +#include <linux/irqchip/chained_irq.h> +#include <linux/irqdomain.h> +#include <linux/of.h> +#include <linux/of_irq.h> +#include <linux/spinlock.h> + +#include "irq-ast2700.h" + +#define INTC1_IER 0x100 +#define INTC1_ISR 0x104 +#define INTC1_IRQS_PER_BANK 32 +#define INTC1_BANK_NUM 6 +#define INTC1_ROUTE_NUM 7 + +struct aspeed_intc1 { + struct device *dev; + void __iomem *base; + raw_spinlock_t intc_lock; + struct irq_domain *local; + struct irq_domain *upstream; + struct aspeed_intc_interrupt_ranges ranges; +}; + +static void aspeed_intc1_disable_int(struct aspeed_intc1 *intc1) +{ + for (int i = 0; i < INTC1_BANK_NUM; i++) + writel(0x0, intc1->base + INTC1_IER + (0x10 * i)); +} + +static void aspeed_intc1_ic_irq_handler(struct irq_desc *desc) +{ + struct aspeed_intc1 *intc1 = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); + unsigned long bit, status; + + chained_irq_enter(chip, desc); + + for (int bank = 0; bank < INTC1_BANK_NUM; bank++) { + status = readl(intc1->base + INTC1_ISR + (0x10 * bank)); + if (!status) + continue; + + for_each_set_bit(bit, &status, INTC1_IRQS_PER_BANK) { + generic_handle_domain_irq(intc1->local, + (bank * INTC1_IRQS_PER_BANK) + + bit); + writel(BIT(bit), + intc1->base + INTC1_ISR + (0x10 * bank)); + } + } + + chained_irq_exit(chip, desc); +} + +static void aspeed_intc1_irq_mask(struct irq_data *data) +{ + struct aspeed_intc1 *intc1 = irq_data_get_irq_chip_data(data); + int bank = data->hwirq / INTC1_IRQS_PER_BANK; + int bit = data->hwirq % INTC1_IRQS_PER_BANK; + unsigned int mask; + + guard(raw_spinlock_irqsave)(&intc1->intc_lock); + mask = readl(intc1->base + INTC1_IER + (0x10 * bank)) & ~BIT(bit); + writel(mask, intc1->base + INTC1_IER + (0x10 * bank)); +} + +static void aspeed_intc1_irq_unmask(struct irq_data *data) +{ + struct aspeed_intc1 *intc1 = irq_data_get_irq_chip_data(data); + int bank = data->hwirq / INTC1_IRQS_PER_BANK; + int bit = data->hwirq % INTC1_IRQS_PER_BANK; + unsigned int unmask; + + guard(raw_spinlock_irqsave)(&intc1->intc_lock); + unmask = readl(intc1->base + INTC1_IER + (0x10 * bank)) | BIT(bit); + writel(unmask, intc1->base + INTC1_IER + (0x10 * bank)); +} + +static struct irq_chip aspeed_intc_chip = { + .name = "ASPEED INTC1", + .irq_mask = aspeed_intc1_irq_mask, + .irq_unmask = aspeed_intc1_irq_unmask, +}; + +static int aspeed_intc1_irq_domain_translate(struct irq_domain *domain, + struct irq_fwspec *fwspec, + unsigned long *hwirq, + unsigned int *type) +{ + if (fwspec->param_count != 1) + return -EINVAL; + + *hwirq = fwspec->param[0]; + *type = IRQ_TYPE_LEVEL_HIGH; + return 0; +} + +static int aspeed_intc1_ic_map_irq_domain(struct irq_domain *domain, + unsigned int irq, + irq_hw_number_t hwirq) +{ + irq_domain_set_info(domain, irq, hwirq, &aspeed_intc_chip, + domain->host_data, handle_level_irq, NULL, NULL); + return 0; +} + +#define INTC1_IN_NUM 192 + +/* + * In-bound interrupts are progressively merged into one out-bound interrupt in + * groups of 32. Apply this fact to compress the route table in corresponding + * groups of 32. + */ +static const aspeed_intc_output_t aspeed_intc1_routes[INTC1_IN_NUM / 32][INTC1_ROUTE_NUM] = { + [0] = { + [0b000] = 0, + [0b001] = AST2700_INTC_INVALID_ROUTE, /* path not verified */ + [0b010] = 10, + [0b011] = 20, + [0b100] = 30, + [0b101] = 40, + [0b110] = 50, + }, + [1] = { + [0b000] = 1, + [0b001] = AST2700_INTC_INVALID_ROUTE, + [0b010] = 11, + [0b011] = 21, + [0b100] = 31, + [0b101] = 41, + [0b110] = 50, + }, + [2] = { + [0b000] = 2, + [0b001] = AST2700_INTC_INVALID_ROUTE, + [0b010] = 12, + [0b011] = 22, + [0b100] = 32, + [0b101] = 42, + [0b110] = 50, + }, + [3] = { + [0b000] = 3, + [0b001] = AST2700_INTC_INVALID_ROUTE, + [0b010] = 13, + [0b011] = 23, + [0b100] = 33, + [0b101] = 43, + [0b110] = 50, + }, + [4] = { + [0b000] = 4, + [0b001] = AST2700_INTC_INVALID_ROUTE, + [0b010] = 14, + [0b011] = 24, + [0b100] = 34, + [0b101] = 44, + [0b110] = 50, + }, + [5] = { + [0b000] = 5, + [0b001] = AST2700_INTC_INVALID_ROUTE, + [0b010] = 15, + [0b011] = 25, + [0b100] = 35, + [0b101] = 45, + [0b110] = 50, + }, +}; + +#define INTC1_BOOTMCU_ROUTE 0b110 + +static int aspeed_intc1_parent_is_bootmcu(const struct irq_domain *upstream) +{ + if (!upstream || !upstream->fwnode) + return 0; + + return fwnode_device_is_compatible(upstream->fwnode, "riscv,aplic"); +} + +static int aspeed_intc1_irq_domain_activate(struct irq_domain *domain, + struct irq_data *data, bool reserve) +{ + struct aspeed_intc1 *intc1 = irq_data_get_irq_chip_data(data); + int bank = data->hwirq / INTC1_IRQS_PER_BANK; + struct aspeed_intc_interrupt_range resolved; + int bit = data->hwirq % INTC1_IRQS_PER_BANK; + u32 mask = BIT(bit); + int rc; + + if (WARN_ON_ONCE((data->hwirq >> 5) >= ARRAY_SIZE(aspeed_intc1_routes))) + return -EINVAL; + + dev_dbg(intc1->dev, "Activation request for hwirq %lu in domain %s\n", + data->hwirq, domain->name); + + /* + * outpin may be an error if the upstream is the BootMCU APLIC node, or + * anything except a valid intc0 driver instance + */ + rc = aspeed_intc0_resolve_route(intc1->upstream, INTC1_ROUTE_NUM, + aspeed_intc1_routes[data->hwirq >> 5], + intc1->ranges.nranges, + intc1->ranges.ranges, &resolved); + if (rc < 0) { + if (!aspeed_intc1_parent_is_bootmcu(intc1->upstream)) { + dev_warn(intc1->dev, + "Failed to resolve interrupt route for hwirq %lu in domain %s\n", + data->hwirq, domain->name); + return rc; + } + rc = INTC1_BOOTMCU_ROUTE; + } + + guard(raw_spinlock_irqsave)(&intc1->intc_lock); + /* Route selector uses 3 bits across the selector registers. */ + for (int i = 0; i < 3; i++) { + void __iomem *sel = intc1->base + 0x80 + bank * 4 + 0x20 * i; + u32 reg = readl(sel); + + if (rc & BIT(i)) + reg |= mask; + else + reg &= ~mask; + + writel(reg, sel); + if (readl(sel) != reg) + return -EACCES; + } + + dev_dbg(intc1->dev, + "Routed hwirq %lu in domain %s to output %u via route %d\n", + data->hwirq, domain->name, resolved.start, rc); + + return 0; +} + +static const struct irq_domain_ops aspeed_intc1_ic_irq_domain_ops = { + .map = aspeed_intc1_ic_map_irq_domain, + .translate = aspeed_intc1_irq_domain_translate, + .activate = aspeed_intc1_irq_domain_activate, +}; + +static void aspeed_intc1_request_interrupts(struct aspeed_intc1 *intc1) +{ + unsigned int i; + + for (i = 0; i < intc1->ranges.nranges; i++) { + struct aspeed_intc_interrupt_range *r = + &intc1->ranges.ranges[i]; + + if (intc1->upstream != + irq_find_matching_fwspec(&r->upstream, + intc1->upstream->bus_token)) + continue; + + for (u32 k = 0; k < r->count; k++) { + struct of_phandle_args parent_irq; + int irq; + + parent_irq.np = to_of_node(r->upstream.fwnode); + parent_irq.args_count = 1; + parent_irq.args[0] = + intc1->ranges.ranges[i].upstream.param[0] + k; + + irq = irq_create_of_mapping(&parent_irq); + if (!irq) + continue; + + irq_set_chained_handler_and_data(irq, + aspeed_intc1_ic_irq_handler, intc1); + dev_dbg(intc1->dev, "Mapped irq %d\n", parent_irq.args[0]); + } + } +} + +static int aspeed_intc1_ic_probe(struct platform_device *pdev, + struct device_node *parent) +{ + struct device_node *node = pdev->dev.of_node; + struct aspeed_intc1 *intc1; + struct irq_domain *host; + int ret; + + if (!parent) { + dev_err(&pdev->dev, "missing parent interrupt node\n"); + return -ENODEV; + } + + if (!of_device_is_compatible(parent, "aspeed,ast2700-intc0-ic")) + return -ENODEV; + + host = irq_find_host(parent); + if (!host) + return -ENODEV; + + intc1 = devm_kzalloc(&pdev->dev, sizeof(*intc1), GFP_KERNEL); + if (!intc1) + return -ENOMEM; + + intc1->dev = &pdev->dev; + intc1->upstream = host; + intc1->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(intc1->base)) + return PTR_ERR(intc1->base); + + aspeed_intc1_disable_int(intc1); + + raw_spin_lock_init(&intc1->intc_lock); + + intc1->local = irq_domain_create_linear(of_fwnode_handle(node), + INTC1_BANK_NUM * INTC1_IRQS_PER_BANK, + &aspeed_intc1_ic_irq_domain_ops, intc1); + if (!intc1->local) + return -ENOMEM; + + ret = aspeed_intc_populate_ranges(&pdev->dev, &intc1->ranges); + if (ret < 0) { + irq_domain_remove(intc1->local); + return ret; + } + + aspeed_intc1_request_interrupts(intc1); + + return 0; +} + +IRQCHIP_PLATFORM_DRIVER_BEGIN(ast2700_intc1) +IRQCHIP_MATCH("aspeed,ast2700-intc1-ic", aspeed_intc1_ic_probe) +IRQCHIP_PLATFORM_DRIVER_END(ast2700_intc1) diff --git a/drivers/irqchip/irq-ast2700.c b/drivers/irqchip/irq-ast2700.c new file mode 100644 index 000000000000..269d743207ae --- /dev/null +++ b/drivers/irqchip/irq-ast2700.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Aspeed Interrupt Controller. + * + * Copyright (C) 2023 ASPEED Technology Inc. + */ +#include "irq-ast2700.h" + +#include <linux/dev_printk.h> +#include <linux/device/devres.h> + +int aspeed_intc_populate_ranges(struct device *dev, + struct aspeed_intc_interrupt_ranges *ranges) +{ + struct aspeed_intc_interrupt_range *arr; + const __be32 *pvs, *pve; + struct device_node *dn; + int len; + + if (!dev || !ranges) + return -EINVAL; + + dn = dev->of_node; + + pvs = of_get_property(dn, "aspeed,interrupt-ranges", &len); + if (!pvs) + return -EINVAL; + + if (len % sizeof(__be32)) + return -EINVAL; + + /* Over-estimate the range entry count for now */ + ranges->ranges = devm_kmalloc_array(dev, (len / (3 * sizeof(__be32))), + sizeof(*ranges->ranges), + GFP_KERNEL); + if (!ranges->ranges) + return -ENOMEM; + + pve = pvs + (len / sizeof(__be32)); + for (unsigned int i = 0; pve - pvs >= 3; i++) { + struct aspeed_intc_interrupt_range *r; + struct device_node *target; + u32 target_cells; + + target = of_find_node_by_phandle(be32_to_cpu(pvs[2])); + if (!target) + return -EINVAL; + + if (of_property_read_u32(target, "#interrupt-cells", + &target_cells)) { + of_node_put(target); + return -EINVAL; + } + + if (!target_cells || target_cells > IRQ_DOMAIN_IRQ_SPEC_PARAMS) { + of_node_put(target); + return -EINVAL; + } + + if (pve - pvs < 3 + target_cells) { + of_node_put(target); + return -EINVAL; + } + + r = &ranges->ranges[i]; + r->start = be32_to_cpu(pvs[0]); + r->count = be32_to_cpu(pvs[1]); + + { + struct of_phandle_args args = { + .np = target, + .args_count = target_cells, + }; + + for (u32 j = 0; j < target_cells; j++) + args.args[j] = be32_to_cpu(pvs[3 + j]); + + of_phandle_args_to_fwspec(target, args.args, + args.args_count, + &r->upstream); + } + + if (target_cells >= 1) + dev_dbg(dev, + "Mapped %u outputs from %u to %u on parent %s", + r->count, r->start, r->upstream.param[0], target->full_name); + else + dev_dbg(dev, + "Registered interrupt range from %u for count %u\n", + r->start, r->count); + + of_node_put(target); + pvs += 3 + target_cells; + ranges->nranges++; + } + + /* Re-fit the range array now we know the entry count */ + arr = devm_krealloc_array(dev, ranges->ranges, ranges->nranges, + sizeof(*ranges->ranges), GFP_KERNEL); + if (!arr) + return -ENOMEM; + ranges->ranges = arr; + + return 0; +} diff --git a/drivers/irqchip/irq-ast2700.h b/drivers/irqchip/irq-ast2700.h new file mode 100644 index 000000000000..56dbb1c88b11 --- /dev/null +++ b/drivers/irqchip/irq-ast2700.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Aspeed AST2700 Interrupt Controller. + * + * Copyright (C) 2023 ASPEED Technology Inc. + */ +#ifndef DRIVERS_IRQCHIP_AST2700 +#define DRIVERS_IRQCHIP_AST2700 + +#include <linux/device.h> +#include <linux/irqdomain.h> + +#define AST2700_INTC_INVALID_ROUTE (~0U) + +struct aspeed_intc_interrupt_range { + u32 start; + u32 count; + struct irq_fwspec upstream; +}; + +struct aspeed_intc_interrupt_ranges { + struct aspeed_intc_interrupt_range *ranges; + unsigned int nranges; +}; + +int aspeed_intc_populate_ranges(struct device *dev, + struct aspeed_intc_interrupt_ranges *ranges); + +typedef u32 aspeed_intc_output_t; + +int aspeed_intc0_resolve_route( + const struct irq_domain *c0domain, size_t nc1outs, + const aspeed_intc_output_t c1outs[static nc1outs], size_t nc1ranges, + const struct aspeed_intc_interrupt_range c1ranges[static nc1ranges], + struct aspeed_intc_interrupt_range *resolved); + +#endif -- 2.34.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support 2026-02-05 6:07 ` [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support Ryan Chen @ 2026-02-05 14:40 ` kernel test robot 2026-02-05 14:52 ` kernel test robot 2026-02-06 11:34 ` Thomas Gleixner 2 siblings, 0 replies; 20+ messages in thread From: kernel test robot @ 2026-02-05 14:40 UTC (permalink / raw) To: Ryan Chen, Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti Cc: oe-kbuild-all, linux-kernel, devicetree, linux-arm-kernel, linux-aspeed, linux-riscv, Ryan Chen Hi Ryan, kernel test robot noticed the following build warnings: [auto build test WARNING on 8f0b4cce4481fb22653697cced8d0d04027cb1e8] url: https://github.com/intel-lab-lkp/linux/commits/Ryan-Chen/dt-bindings-interrupt-controller-aspeed-Add-ASPEED-AST2700-INTC0-INTC1/20260205-141046 base: 8f0b4cce4481fb22653697cced8d0d04027cb1e8 patch link: https://lore.kernel.org/r/20260205-irqchip-v1-2-b0310e06c087%40aspeedtech.com patch subject: [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support config: parisc-allyesconfig (https://download.01.org/0day-ci/archive/20260205/202602052259.vW8lLakZ-lkp@intel.com/config) compiler: hppa-linux-gcc (GCC) 15.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260205/202602052259.vW8lLakZ-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202602052259.vW8lLakZ-lkp@intel.com/ All warnings (new ones prefixed by >>): In file included from include/linux/err.h:8, from include/linux/cleanup.h:6, from include/linux/irqflags.h:17, from include/asm-generic/cmpxchg-local.h:6, from arch/parisc/include/asm/cmpxchg.h:87, from arch/parisc/include/asm/atomic.h:10, from include/linux/atomic.h:7, from arch/parisc/include/asm/bitops.h:13, from include/linux/bitops.h:67, from drivers/irqchip/irq-ast2700-intc0.c:9: >> arch/parisc/include/uapi/asm/errno.h:7:9: warning: 'ENOMSG' redefined 7 | #define ENOMSG 35 /* No message of desired type */ | ^~~~~~ In file included from drivers/irqchip/irq-ast2700-intc0.c:8: include/uapi/asm-generic/errno.h:23:9: note: this is the location of the previous definition 23 | #define ENOMSG 42 /* No message of desired type */ | ^~~~~~ >> arch/parisc/include/uapi/asm/errno.h:8:9: warning: 'EIDRM' redefined 8 | #define EIDRM 36 /* Identifier removed */ | ^~~~~ include/uapi/asm-generic/errno.h:24:9: note: this is the location of the previous definition 24 | #define EIDRM 43 /* Identifier removed */ | ^~~~~ >> arch/parisc/include/uapi/asm/errno.h:9:9: warning: 'ECHRNG' redefined 9 | #define ECHRNG 37 /* Channel number out of range */ | ^~~~~~ include/uapi/asm-generic/errno.h:25:9: note: this is the location of the previous definition 25 | #define ECHRNG 44 /* Channel number out of range */ | ^~~~~~ >> arch/parisc/include/uapi/asm/errno.h:10:9: warning: 'EL2NSYNC' redefined 10 | #define EL2NSYNC 38 /* Level 2 not synchronized */ | ^~~~~~~~ include/uapi/asm-generic/errno.h:26:9: note: this is the location of the previous definition 26 | #define EL2NSYNC 45 /* Level 2 not synchronized */ | ^~~~~~~~ >> arch/parisc/include/uapi/asm/errno.h:11:9: warning: 'EL3HLT' redefined 11 | #define EL3HLT 39 /* Level 3 halted */ | ^~~~~~ include/uapi/asm-generic/errno.h:27:9: note: this is the location of the previous definition 27 | #define EL3HLT 46 /* Level 3 halted */ | ^~~~~~ >> arch/parisc/include/uapi/asm/errno.h:12:9: warning: 'EL3RST' redefined 12 | #define EL3RST 40 /* Level 3 reset */ | ^~~~~~ include/uapi/asm-generic/errno.h:28:9: note: this is the location of the previous definition 28 | #define EL3RST 47 /* Level 3 reset */ | ^~~~~~ >> arch/parisc/include/uapi/asm/errno.h:13:9: warning: 'ELNRNG' redefined 13 | #define ELNRNG 41 /* Link number out of range */ | ^~~~~~ include/uapi/asm-generic/errno.h:29:9: note: this is the location of the previous definition 29 | #define ELNRNG 48 /* Link number out of range */ | ^~~~~~ >> arch/parisc/include/uapi/asm/errno.h:14:9: warning: 'EUNATCH' redefined 14 | #define EUNATCH 42 /* Protocol driver not attached */ | ^~~~~~~ include/uapi/asm-generic/errno.h:30:9: note: this is the location of the previous definition 30 | #define EUNATCH 49 /* Protocol driver not attached */ | ^~~~~~~ >> arch/parisc/include/uapi/asm/errno.h:15:9: warning: 'ENOCSI' redefined 15 | #define ENOCSI 43 /* No CSI structure available */ | ^~~~~~ include/uapi/asm-generic/errno.h:31:9: note: this is the location of the previous definition 31 | #define ENOCSI 50 /* No CSI structure available */ | ^~~~~~ >> arch/parisc/include/uapi/asm/errno.h:16:9: warning: 'EL2HLT' redefined 16 | #define EL2HLT 44 /* Level 2 halted */ | ^~~~~~ include/uapi/asm-generic/errno.h:32:9: note: this is the location of the previous definition 32 | #define EL2HLT 51 /* Level 2 halted */ | ^~~~~~ >> arch/parisc/include/uapi/asm/errno.h:17:9: warning: 'EDEADLK' redefined 17 | #define EDEADLK 45 /* Resource deadlock would occur */ | ^~~~~~~ include/uapi/asm-generic/errno.h:7:9: note: this is the location of the previous definition 7 | #define EDEADLK 35 /* Resource deadlock would occur */ | ^~~~~~~ >> arch/parisc/include/uapi/asm/errno.h:19:9: warning: 'ENOLCK' redefined 19 | #define ENOLCK 46 /* No record locks available */ | ^~~~~~ include/uapi/asm-generic/errno.h:9:9: note: this is the location of the previous definition 9 | #define ENOLCK 37 /* No record locks available */ | ^~~~~~ >> arch/parisc/include/uapi/asm/errno.h:20:9: warning: 'EILSEQ' redefined 20 | #define EILSEQ 47 /* Illegal byte sequence */ | ^~~~~~ include/uapi/asm-generic/errno.h:67:9: note: this is the location of the previous definition 67 | #define EILSEQ 84 /* Illegal byte sequence */ | ^~~~~~ >> arch/parisc/include/uapi/asm/errno.h:22:9: warning: 'ENONET' redefined 22 | #define ENONET 50 /* Machine is not on the network */ | ^~~~~~ include/uapi/asm-generic/errno.h:47:9: note: this is the location of the previous definition 47 | #define ENONET 64 /* Machine is not on the network */ | ^~~~~~ >> arch/parisc/include/uapi/asm/errno.h:23:9: warning: 'ENODATA' redefined 23 | #define ENODATA 51 /* No data available */ | ^~~~~~~ include/uapi/asm-generic/errno.h:44:9: note: this is the location of the previous definition 44 | #define ENODATA 61 /* No data available */ | ^~~~~~~ >> arch/parisc/include/uapi/asm/errno.h:24:9: warning: 'ETIME' redefined 24 | #define ETIME 52 /* Timer expired */ | ^~~~~ include/uapi/asm-generic/errno.h:45:9: note: this is the location of the previous definition 45 | #define ETIME 62 /* Timer expired */ | ^~~~~ >> arch/parisc/include/uapi/asm/errno.h:25:9: warning: 'ENOSR' redefined 25 | #define ENOSR 53 /* Out of streams resources */ | ^~~~~ include/uapi/asm-generic/errno.h:46:9: note: this is the location of the previous definition 46 | #define ENOSR 63 /* Out of streams resources */ | ^~~~~ >> arch/parisc/include/uapi/asm/errno.h:26:9: warning: 'ENOSTR' redefined 26 | #define ENOSTR 54 /* Device not a stream */ | ^~~~~~ include/uapi/asm-generic/errno.h:43:9: note: this is the location of the previous definition 43 | #define ENOSTR 60 /* Device not a stream */ | ^~~~~~ >> arch/parisc/include/uapi/asm/errno.h:27:9: warning: 'ENOPKG' redefined 27 | #define ENOPKG 55 /* Package not installed */ | ^~~~~~ include/uapi/asm-generic/errno.h:48:9: note: this is the location of the previous definition 48 | #define ENOPKG 65 /* Package not installed */ | ^~~~~~ >> arch/parisc/include/uapi/asm/errno.h:29:9: warning: 'ENOLINK' redefined 29 | #define ENOLINK 57 /* Link has been severed */ | ^~~~~~~ include/uapi/asm-generic/errno.h:50:9: note: this is the location of the previous definition 50 | #define ENOLINK 67 /* Link has been severed */ | ^~~~~~~ arch/parisc/include/uapi/asm/errno.h:30:9: warning: 'EADV' redefined 30 | #define EADV 58 /* Advertise error */ | ^~~~ include/uapi/asm-generic/errno.h:51:9: note: this is the location of the previous definition 51 | #define EADV 68 /* Advertise error */ | ^~~~ arch/parisc/include/uapi/asm/errno.h:31:9: warning: 'ESRMNT' redefined 31 | #define ESRMNT 59 /* Srmount error */ | ^~~~~~ include/uapi/asm-generic/errno.h:52:9: note: this is the location of the previous definition 52 | #define ESRMNT 69 /* Srmount error */ | ^~~~~~ arch/parisc/include/uapi/asm/errno.h:32:9: warning: 'ECOMM' redefined 32 | #define ECOMM 60 /* Communication error on send */ | ^~~~~ include/uapi/asm-generic/errno.h:53:9: note: this is the location of the previous definition 53 | #define ECOMM 70 /* Communication error on send */ | ^~~~~ arch/parisc/include/uapi/asm/errno.h:33:9: warning: 'EPROTO' redefined 33 | #define EPROTO 61 /* Protocol error */ | ^~~~~~ include/uapi/asm-generic/errno.h:54:9: note: this is the location of the previous definition 54 | #define EPROTO 71 /* Protocol error */ | ^~~~~~ arch/parisc/include/uapi/asm/errno.h:35:9: warning: 'EMULTIHOP' redefined 35 | #define EMULTIHOP 64 /* Multihop attempted */ | ^~~~~~~~~ include/uapi/asm-generic/errno.h:55:9: note: this is the location of the previous definition 55 | #define EMULTIHOP 72 /* Multihop attempted */ | ^~~~~~~~~ arch/parisc/include/uapi/asm/errno.h:37:9: warning: 'EDOTDOT' redefined 37 | #define EDOTDOT 66 /* RFS specific error */ | ^~~~~~~ include/uapi/asm-generic/errno.h:56:9: note: this is the location of the previous definition 56 | #define EDOTDOT 73 /* RFS specific error */ | ^~~~~~~ arch/parisc/include/uapi/asm/errno.h:38:9: warning: 'EBADMSG' redefined 38 | #define EBADMSG 67 /* Not a data message */ | ^~~~~~~ include/uapi/asm-generic/errno.h:57:9: note: this is the location of the previous definition 57 | #define EBADMSG 74 /* Not a data message */ | ^~~~~~~ arch/parisc/include/uapi/asm/errno.h:39:9: warning: 'EUSERS' redefined 39 | #define EUSERS 68 /* Too many users */ | ^~~~~~ include/uapi/asm-generic/errno.h:70:9: note: this is the location of the previous definition 70 | #define EUSERS 87 /* Too many users */ | ^~~~~~ arch/parisc/include/uapi/asm/errno.h:40:9: warning: 'EDQUOT' redefined 40 | #define EDQUOT 69 /* Quota exceeded */ | ^~~~~~ include/uapi/asm-generic/errno.h:105:9: note: this is the location of the previous definition 105 | #define EDQUOT 122 /* Quota exceeded */ | ^~~~~~ arch/parisc/include/uapi/asm/errno.h:41:9: warning: 'ESTALE' redefined 41 | #define ESTALE 70 /* Stale file handle */ | ^~~~~~ include/uapi/asm-generic/errno.h:99:9: note: this is the location of the previous definition 99 | #define ESTALE 116 /* Stale file handle */ | ^~~~~~ arch/parisc/include/uapi/asm/errno.h:42:9: warning: 'EREMOTE' redefined 42 | #define EREMOTE 71 /* Object is remote */ | ^~~~~~~ include/uapi/asm-generic/errno.h:49:9: note: this is the location of the previous definition 49 | #define EREMOTE 66 /* Object is remote */ | ^~~~~~~ arch/parisc/include/uapi/asm/errno.h:43:9: warning: 'EOVERFLOW' redefined 43 | #define EOVERFLOW 72 /* Value too large for defined data type */ | ^~~~~~~~~ include/uapi/asm-generic/errno.h:58:9: note: this is the location of the previous definition 58 | #define EOVERFLOW 75 /* Value too large for defined data type */ | ^~~~~~~~~ arch/parisc/include/uapi/asm/errno.h:47:9: warning: 'EBADE' redefined 47 | #define EBADE 160 /* Invalid exchange */ | ^~~~~ include/uapi/asm-generic/errno.h:33:9: note: this is the location of the previous definition 33 | #define EBADE 52 /* Invalid exchange */ | ^~~~~ arch/parisc/include/uapi/asm/errno.h:48:9: warning: 'EBADR' redefined 48 | #define EBADR 161 /* Invalid request descriptor */ | ^~~~~ include/uapi/asm-generic/errno.h:34:9: note: this is the location of the previous definition 34 | #define EBADR 53 /* Invalid request descriptor */ | ^~~~~ arch/parisc/include/uapi/asm/errno.h:49:9: warning: 'EXFULL' redefined 49 | #define EXFULL 162 /* Exchange full */ | ^~~~~~ include/uapi/asm-generic/errno.h:35:9: note: this is the location of the previous definition 35 | #define EXFULL 54 /* Exchange full */ | ^~~~~~ arch/parisc/include/uapi/asm/errno.h:50:9: warning: 'ENOANO' redefined 50 | #define ENOANO 163 /* No anode */ | ^~~~~~ include/uapi/asm-generic/errno.h:36:9: note: this is the location of the previous definition 36 | #define ENOANO 55 /* No anode */ vim +/ENOMSG +7 arch/parisc/include/uapi/asm/errno.h ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 6 ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @7 #define ENOMSG 35 /* No message of desired type */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @8 #define EIDRM 36 /* Identifier removed */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @9 #define ECHRNG 37 /* Channel number out of range */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @10 #define EL2NSYNC 38 /* Level 2 not synchronized */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @11 #define EL3HLT 39 /* Level 3 halted */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @12 #define EL3RST 40 /* Level 3 reset */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @13 #define ELNRNG 41 /* Link number out of range */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @14 #define EUNATCH 42 /* Protocol driver not attached */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @15 #define ENOCSI 43 /* No CSI structure available */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @16 #define EL2HLT 44 /* Level 2 halted */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @17 #define EDEADLK 45 /* Resource deadlock would occur */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 18 #define EDEADLOCK EDEADLK ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @19 #define ENOLCK 46 /* No record locks available */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @20 #define EILSEQ 47 /* Illegal byte sequence */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 21 ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @22 #define ENONET 50 /* Machine is not on the network */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @23 #define ENODATA 51 /* No data available */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @24 #define ETIME 52 /* Timer expired */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @25 #define ENOSR 53 /* Out of streams resources */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @26 #define ENOSTR 54 /* Device not a stream */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @27 #define ENOPKG 55 /* Package not installed */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 28 ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @29 #define ENOLINK 57 /* Link has been severed */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @30 #define EADV 58 /* Advertise error */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @31 #define ESRMNT 59 /* Srmount error */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @32 #define ECOMM 60 /* Communication error on send */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @33 #define EPROTO 61 /* Protocol error */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 34 ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @35 #define EMULTIHOP 64 /* Multihop attempted */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 36 ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @37 #define EDOTDOT 66 /* RFS specific error */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @38 #define EBADMSG 67 /* Not a data message */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @39 #define EUSERS 68 /* Too many users */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @40 #define EDQUOT 69 /* Quota exceeded */ 0ca43435188b9f9 arch/parisc/include/uapi/asm/errno.h Eric Sandeen 2013-11-12 @41 #define ESTALE 70 /* Stale file handle */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @42 #define EREMOTE 71 /* Object is remote */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @43 #define EOVERFLOW 72 /* Value too large for defined data type */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 44 ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 45 /* these errnos are defined by Linux but not HPUX. */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 46 ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @47 #define EBADE 160 /* Invalid exchange */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @48 #define EBADR 161 /* Invalid request descriptor */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @49 #define EXFULL 162 /* Exchange full */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @50 #define ENOANO 163 /* No anode */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @51 #define EBADRQC 164 /* Invalid request code */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @52 #define EBADSLT 165 /* Invalid slot */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @53 #define EBFONT 166 /* Bad font file format */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @54 #define ENOTUNIQ 167 /* Name not unique on network */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @55 #define EBADFD 168 /* File descriptor in bad state */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @56 #define EREMCHG 169 /* Remote address changed */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @57 #define ELIBACC 170 /* Can not access a needed shared library */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @58 #define ELIBBAD 171 /* Accessing a corrupted shared library */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @59 #define ELIBSCN 172 /* .lib section in a.out corrupted */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @60 #define ELIBMAX 173 /* Attempting to link in too many shared libraries */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @61 #define ELIBEXEC 174 /* Cannot exec a shared library directly */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @62 #define ERESTART 175 /* Interrupted system call should be restarted */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @63 #define ESTRPIPE 176 /* Streams pipe error */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @64 #define EUCLEAN 177 /* Structure needs cleaning */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @65 #define ENOTNAM 178 /* Not a XENIX named type file */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @66 #define ENAVAIL 179 /* No XENIX semaphores available */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @67 #define EISNAM 180 /* Is a named type file */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @68 #define EREMOTEIO 181 /* Remote I/O error */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @69 #define ENOMEDIUM 182 /* No medium found */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @70 #define EMEDIUMTYPE 183 /* Wrong medium type */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @71 #define ENOKEY 184 /* Required key not available */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @72 #define EKEYEXPIRED 185 /* Key has expired */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @73 #define EKEYREVOKED 186 /* Key has been revoked */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @74 #define EKEYREJECTED 187 /* Key was rejected by service */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 75 ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 76 /* We now return you to your regularly scheduled HPUX. */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 77 ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @78 #define ENOTSOCK 216 /* Socket operation on non-socket */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @79 #define EDESTADDRREQ 217 /* Destination address required */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @80 #define EMSGSIZE 218 /* Message too long */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @81 #define EPROTOTYPE 219 /* Protocol wrong type for socket */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @82 #define ENOPROTOOPT 220 /* Protocol not available */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @83 #define EPROTONOSUPPORT 221 /* Protocol not supported */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @84 #define ESOCKTNOSUPPORT 222 /* Socket type not supported */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @85 #define EOPNOTSUPP 223 /* Operation not supported on transport endpoint */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @86 #define EPFNOSUPPORT 224 /* Protocol family not supported */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @87 #define EAFNOSUPPORT 225 /* Address family not supported by protocol */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @88 #define EADDRINUSE 226 /* Address already in use */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @89 #define EADDRNOTAVAIL 227 /* Cannot assign requested address */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @90 #define ENETDOWN 228 /* Network is down */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @91 #define ENETUNREACH 229 /* Network is unreachable */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @92 #define ENETRESET 230 /* Network dropped connection because of reset */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @93 #define ECONNABORTED 231 /* Software caused connection abort */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @94 #define ECONNRESET 232 /* Connection reset by peer */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @95 #define ENOBUFS 233 /* No buffer space available */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @96 #define EISCONN 234 /* Transport endpoint is already connected */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @97 #define ENOTCONN 235 /* Transport endpoint is not connected */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @98 #define ESHUTDOWN 236 /* Cannot send after transport endpoint shutdown */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @99 #define ETOOMANYREFS 237 /* Too many references: cannot splice */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @100 #define ETIMEDOUT 238 /* Connection timed out */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @101 #define ECONNREFUSED 239 /* Connection refused */ 3eb53b20d7bd137 arch/parisc/include/uapi/asm/errno.h Helge Deller 2016-08-20 102 #define EREFUSED ECONNREFUSED /* for HP's NFS apparently */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @103 #define EHOSTDOWN 241 /* Host is down */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @104 #define EHOSTUNREACH 242 /* No route to host */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 105 ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @106 #define EALREADY 244 /* Operation already in progress */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @107 #define EINPROGRESS 245 /* Operation now in progress */ f5a408d53edef3a arch/parisc/include/uapi/asm/errno.h Guy Martin 2014-01-16 108 #define EWOULDBLOCK EAGAIN /* Operation would block (Not HPUX compliant) */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @109 #define ENOTEMPTY 247 /* Directory not empty */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @110 #define ENAMETOOLONG 248 /* File name too long */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @111 #define ELOOP 249 /* Too many symbolic links encountered */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 @112 #define ENOSYS 251 /* Function not implemented */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 113 ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 114 #define ECANCELLED 253 /* aio request was canceled before complete (POSIX.4 / HPUX) */ 05aa10de701409b include/asm-parisc/errno.h Grant Grundler 2005-10-21 @115 #define ECANCELED ECANCELLED /* SuSv3 and Solaris wants one 'L' */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 116 4750e2c0c59e0c8 include/asm-parisc/errno.h Joe Korty 2005-05-01 117 /* for robust mutexes */ 4750e2c0c59e0c8 include/asm-parisc/errno.h Joe Korty 2005-05-01 @118 #define EOWNERDEAD 254 /* Owner died */ 4750e2c0c59e0c8 include/asm-parisc/errno.h Joe Korty 2005-05-01 @119 #define ENOTRECOVERABLE 255 /* State not recoverable */ 4750e2c0c59e0c8 include/asm-parisc/errno.h Joe Korty 2005-05-01 120 7d217d7ffc3433d arch/parisc/include/asm/errno.h Alexander Beregalov 2009-06-07 @121 #define ERFKILL 256 /* Operation not possible due to RF-kill */ ^1da177e4c3f415 include/asm-parisc/errno.h Linus Torvalds 2005-04-16 122 69ebb83e13e5142 arch/parisc/include/asm/errno.h Ying Huang 2011-01-30 @123 #define EHWPOISON 257 /* Memory page has hardware error */ 69ebb83e13e5142 arch/parisc/include/asm/errno.h Ying Huang 2011-01-30 124 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support 2026-02-05 6:07 ` [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support Ryan Chen 2026-02-05 14:40 ` kernel test robot @ 2026-02-05 14:52 ` kernel test robot 2026-02-06 11:34 ` Thomas Gleixner 2 siblings, 0 replies; 20+ messages in thread From: kernel test robot @ 2026-02-05 14:52 UTC (permalink / raw) To: Ryan Chen, Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti Cc: oe-kbuild-all, linux-kernel, devicetree, linux-arm-kernel, linux-aspeed, linux-riscv, Ryan Chen Hi Ryan, kernel test robot noticed the following build warnings: [auto build test WARNING on 8f0b4cce4481fb22653697cced8d0d04027cb1e8] url: https://github.com/intel-lab-lkp/linux/commits/Ryan-Chen/dt-bindings-interrupt-controller-aspeed-Add-ASPEED-AST2700-INTC0-INTC1/20260205-141046 base: 8f0b4cce4481fb22653697cced8d0d04027cb1e8 patch link: https://lore.kernel.org/r/20260205-irqchip-v1-2-b0310e06c087%40aspeedtech.com patch subject: [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support config: mips-allyesconfig (https://download.01.org/0day-ci/archive/20260205/202602052233.HNk5pa4R-lkp@intel.com/config) compiler: mips-linux-gcc (GCC) 15.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260205/202602052233.HNk5pa4R-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202602052233.HNk5pa4R-lkp@intel.com/ All warnings (new ones prefixed by >>): In file included from arch/mips/include/asm/errno.h:11, from include/linux/err.h:8, from include/linux/cleanup.h:6, from include/linux/jump_label.h:78, from include/linux/dynamic_debug.h:6, from include/linux/printk.h:621, from include/asm-generic/bug.h:31, from arch/mips/include/asm/bug.h:42, from include/linux/bug.h:5, from include/linux/thread_info.h:13, from include/asm-generic/current.h:6, from ./arch/mips/include/generated/asm/current.h:1, from include/linux/sched.h:12, from include/linux/ratelimit.h:6, from include/linux/dev_printk.h:16, from include/linux/device.h:15, from drivers/irqchip/irq-ast2700-intc0.c:10: >> arch/mips/include/uapi/asm/errno.h:18:9: warning: 'ENOMSG' redefined 18 | #define ENOMSG 35 /* No message of desired type */ | ^~~~~~ In file included from drivers/irqchip/irq-ast2700-intc0.c:8: include/uapi/asm-generic/errno.h:23:9: note: this is the location of the previous definition 23 | #define ENOMSG 42 /* No message of desired type */ | ^~~~~~ >> arch/mips/include/uapi/asm/errno.h:19:9: warning: 'EIDRM' redefined 19 | #define EIDRM 36 /* Identifier removed */ | ^~~~~ include/uapi/asm-generic/errno.h:24:9: note: this is the location of the previous definition 24 | #define EIDRM 43 /* Identifier removed */ | ^~~~~ >> arch/mips/include/uapi/asm/errno.h:20:9: warning: 'ECHRNG' redefined 20 | #define ECHRNG 37 /* Channel number out of range */ | ^~~~~~ include/uapi/asm-generic/errno.h:25:9: note: this is the location of the previous definition 25 | #define ECHRNG 44 /* Channel number out of range */ | ^~~~~~ >> arch/mips/include/uapi/asm/errno.h:21:9: warning: 'EL2NSYNC' redefined 21 | #define EL2NSYNC 38 /* Level 2 not synchronized */ | ^~~~~~~~ include/uapi/asm-generic/errno.h:26:9: note: this is the location of the previous definition 26 | #define EL2NSYNC 45 /* Level 2 not synchronized */ | ^~~~~~~~ >> arch/mips/include/uapi/asm/errno.h:22:9: warning: 'EL3HLT' redefined 22 | #define EL3HLT 39 /* Level 3 halted */ | ^~~~~~ include/uapi/asm-generic/errno.h:27:9: note: this is the location of the previous definition 27 | #define EL3HLT 46 /* Level 3 halted */ | ^~~~~~ >> arch/mips/include/uapi/asm/errno.h:23:9: warning: 'EL3RST' redefined 23 | #define EL3RST 40 /* Level 3 reset */ | ^~~~~~ include/uapi/asm-generic/errno.h:28:9: note: this is the location of the previous definition 28 | #define EL3RST 47 /* Level 3 reset */ | ^~~~~~ >> arch/mips/include/uapi/asm/errno.h:24:9: warning: 'ELNRNG' redefined 24 | #define ELNRNG 41 /* Link number out of range */ | ^~~~~~ include/uapi/asm-generic/errno.h:29:9: note: this is the location of the previous definition 29 | #define ELNRNG 48 /* Link number out of range */ | ^~~~~~ >> arch/mips/include/uapi/asm/errno.h:25:9: warning: 'EUNATCH' redefined 25 | #define EUNATCH 42 /* Protocol driver not attached */ | ^~~~~~~ include/uapi/asm-generic/errno.h:30:9: note: this is the location of the previous definition 30 | #define EUNATCH 49 /* Protocol driver not attached */ | ^~~~~~~ >> arch/mips/include/uapi/asm/errno.h:26:9: warning: 'ENOCSI' redefined 26 | #define ENOCSI 43 /* No CSI structure available */ | ^~~~~~ include/uapi/asm-generic/errno.h:31:9: note: this is the location of the previous definition 31 | #define ENOCSI 50 /* No CSI structure available */ | ^~~~~~ >> arch/mips/include/uapi/asm/errno.h:27:9: warning: 'EL2HLT' redefined 27 | #define EL2HLT 44 /* Level 2 halted */ | ^~~~~~ include/uapi/asm-generic/errno.h:32:9: note: this is the location of the previous definition 32 | #define EL2HLT 51 /* Level 2 halted */ | ^~~~~~ >> arch/mips/include/uapi/asm/errno.h:28:9: warning: 'EDEADLK' redefined 28 | #define EDEADLK 45 /* Resource deadlock would occur */ | ^~~~~~~ include/uapi/asm-generic/errno.h:7:9: note: this is the location of the previous definition 7 | #define EDEADLK 35 /* Resource deadlock would occur */ | ^~~~~~~ >> arch/mips/include/uapi/asm/errno.h:29:9: warning: 'ENOLCK' redefined 29 | #define ENOLCK 46 /* No record locks available */ | ^~~~~~ include/uapi/asm-generic/errno.h:9:9: note: this is the location of the previous definition 9 | #define ENOLCK 37 /* No record locks available */ | ^~~~~~ >> arch/mips/include/uapi/asm/errno.h:30:9: warning: 'EBADE' redefined 30 | #define EBADE 50 /* Invalid exchange */ | ^~~~~ include/uapi/asm-generic/errno.h:33:9: note: this is the location of the previous definition 33 | #define EBADE 52 /* Invalid exchange */ | ^~~~~ >> arch/mips/include/uapi/asm/errno.h:31:9: warning: 'EBADR' redefined 31 | #define EBADR 51 /* Invalid request descriptor */ | ^~~~~ include/uapi/asm-generic/errno.h:34:9: note: this is the location of the previous definition 34 | #define EBADR 53 /* Invalid request descriptor */ | ^~~~~ >> arch/mips/include/uapi/asm/errno.h:32:9: warning: 'EXFULL' redefined 32 | #define EXFULL 52 /* Exchange full */ | ^~~~~~ include/uapi/asm-generic/errno.h:35:9: note: this is the location of the previous definition 35 | #define EXFULL 54 /* Exchange full */ | ^~~~~~ >> arch/mips/include/uapi/asm/errno.h:33:9: warning: 'ENOANO' redefined 33 | #define ENOANO 53 /* No anode */ | ^~~~~~ include/uapi/asm-generic/errno.h:36:9: note: this is the location of the previous definition 36 | #define ENOANO 55 /* No anode */ | ^~~~~~ >> arch/mips/include/uapi/asm/errno.h:34:9: warning: 'EBADRQC' redefined 34 | #define EBADRQC 54 /* Invalid request code */ | ^~~~~~~ include/uapi/asm-generic/errno.h:37:9: note: this is the location of the previous definition 37 | #define EBADRQC 56 /* Invalid request code */ | ^~~~~~~ >> arch/mips/include/uapi/asm/errno.h:35:9: warning: 'EBADSLT' redefined 35 | #define EBADSLT 55 /* Invalid slot */ | ^~~~~~~ include/uapi/asm-generic/errno.h:38:9: note: this is the location of the previous definition 38 | #define EBADSLT 57 /* Invalid slot */ | ^~~~~~~ >> arch/mips/include/uapi/asm/errno.h:36:9: warning: 'EDEADLOCK' redefined 36 | #define EDEADLOCK 56 /* File locking deadlock error */ | ^~~~~~~~~ include/uapi/asm-generic/errno.h:40:9: note: this is the location of the previous definition 40 | #define EDEADLOCK EDEADLK | ^~~~~~~~~ >> arch/mips/include/uapi/asm/errno.h:51:9: warning: 'EMULTIHOP' redefined 51 | #define EMULTIHOP 74 /* Multihop attempted */ | ^~~~~~~~~ include/uapi/asm-generic/errno.h:55:9: note: this is the location of the previous definition 55 | #define EMULTIHOP 72 /* Multihop attempted */ | ^~~~~~~~~ arch/mips/include/uapi/asm/errno.h:52:9: warning: 'EBADMSG' redefined 52 | #define EBADMSG 77 /* Not a data message */ | ^~~~~~~ include/uapi/asm-generic/errno.h:57:9: note: this is the location of the previous definition 57 | #define EBADMSG 74 /* Not a data message */ | ^~~~~~~ arch/mips/include/uapi/asm/errno.h:53:9: warning: 'ENAMETOOLONG' redefined 53 | #define ENAMETOOLONG 78 /* File name too long */ | ^~~~~~~~~~~~ include/uapi/asm-generic/errno.h:8:9: note: this is the location of the previous definition 8 | #define ENAMETOOLONG 36 /* File name too long */ | ^~~~~~~~~~~~ arch/mips/include/uapi/asm/errno.h:54:9: warning: 'EOVERFLOW' redefined 54 | #define EOVERFLOW 79 /* Value too large for defined data type */ | ^~~~~~~~~ include/uapi/asm-generic/errno.h:58:9: note: this is the location of the previous definition 58 | #define EOVERFLOW 75 /* Value too large for defined data type */ | ^~~~~~~~~ arch/mips/include/uapi/asm/errno.h:55:9: warning: 'ENOTUNIQ' redefined 55 | #define ENOTUNIQ 80 /* Name not unique on network */ | ^~~~~~~~ include/uapi/asm-generic/errno.h:59:9: note: this is the location of the previous definition 59 | #define ENOTUNIQ 76 /* Name not unique on network */ | ^~~~~~~~ arch/mips/include/uapi/asm/errno.h:56:9: warning: 'EBADFD' redefined 56 | #define EBADFD 81 /* File descriptor in bad state */ | ^~~~~~ include/uapi/asm-generic/errno.h:60:9: note: this is the location of the previous definition 60 | #define EBADFD 77 /* File descriptor in bad state */ | ^~~~~~ arch/mips/include/uapi/asm/errno.h:57:9: warning: 'EREMCHG' redefined 57 | #define EREMCHG 82 /* Remote address changed */ | ^~~~~~~ include/uapi/asm-generic/errno.h:61:9: note: this is the location of the previous definition 61 | #define EREMCHG 78 /* Remote address changed */ | ^~~~~~~ arch/mips/include/uapi/asm/errno.h:58:9: warning: 'ELIBACC' redefined 58 | #define ELIBACC 83 /* Can not access a needed shared library */ | ^~~~~~~ include/uapi/asm-generic/errno.h:62:9: note: this is the location of the previous definition 62 | #define ELIBACC 79 /* Can not access a needed shared library */ | ^~~~~~~ arch/mips/include/uapi/asm/errno.h:59:9: warning: 'ELIBBAD' redefined 59 | #define ELIBBAD 84 /* Accessing a corrupted shared library */ | ^~~~~~~ include/uapi/asm-generic/errno.h:63:9: note: this is the location of the previous definition 63 | #define ELIBBAD 80 /* Accessing a corrupted shared library */ | ^~~~~~~ arch/mips/include/uapi/asm/errno.h:60:9: warning: 'ELIBSCN' redefined 60 | #define ELIBSCN 85 /* .lib section in a.out corrupted */ | ^~~~~~~ include/uapi/asm-generic/errno.h:64:9: note: this is the location of the previous definition 64 | #define ELIBSCN 81 /* .lib section in a.out corrupted */ | ^~~~~~~ arch/mips/include/uapi/asm/errno.h:61:9: warning: 'ELIBMAX' redefined 61 | #define ELIBMAX 86 /* Attempting to link in too many shared libraries */ | ^~~~~~~ include/uapi/asm-generic/errno.h:65:9: note: this is the location of the previous definition 65 | #define ELIBMAX 82 /* Attempting to link in too many shared libraries */ | ^~~~~~~ arch/mips/include/uapi/asm/errno.h:62:9: warning: 'ELIBEXEC' redefined 62 | #define ELIBEXEC 87 /* Cannot exec a shared library directly */ | ^~~~~~~~ include/uapi/asm-generic/errno.h:66:9: note: this is the location of the previous definition 66 | #define ELIBEXEC 83 /* Cannot exec a shared library directly */ | ^~~~~~~~ arch/mips/include/uapi/asm/errno.h:63:9: warning: 'EILSEQ' redefined 63 | #define EILSEQ 88 /* Illegal byte sequence */ | ^~~~~~ include/uapi/asm-generic/errno.h:67:9: note: this is the location of the previous definition 67 | #define EILSEQ 84 /* Illegal byte sequence */ | ^~~~~~ arch/mips/include/uapi/asm/errno.h:64:9: warning: 'ENOSYS' redefined 64 | #define ENOSYS 89 /* Function not implemented */ | ^~~~~~ include/uapi/asm-generic/errno.h:18:9: note: this is the location of the previous definition 18 | #define ENOSYS 38 /* Invalid system call number */ | ^~~~~~ arch/mips/include/uapi/asm/errno.h:65:9: warning: 'ELOOP' redefined 65 | #define ELOOP 90 /* Too many symbolic links encountered */ | ^~~~~ include/uapi/asm-generic/errno.h:21:9: note: this is the location of the previous definition 21 | #define ELOOP 40 /* Too many symbolic links encountered */ | ^~~~~ arch/mips/include/uapi/asm/errno.h:66:9: warning: 'ERESTART' redefined 66 | #define ERESTART 91 /* Interrupted system call should be restarted */ | ^~~~~~~~ include/uapi/asm-generic/errno.h:68:9: note: this is the location of the previous definition 68 | #define ERESTART 85 /* Interrupted system call should be restarted */ | ^~~~~~~~ arch/mips/include/uapi/asm/errno.h:67:9: warning: 'ESTRPIPE' redefined 67 | #define ESTRPIPE 92 /* Streams pipe error */ | ^~~~~~~~ include/uapi/asm-generic/errno.h:69:9: note: this is the location of the previous definition 69 | #define ESTRPIPE 86 /* Streams pipe error */ vim +/ENOMSG +18 arch/mips/include/uapi/asm/errno.h 61730c538f8281 David Howells 2012-10-09 17 61730c538f8281 David Howells 2012-10-09 @18 #define ENOMSG 35 /* No message of desired type */ 61730c538f8281 David Howells 2012-10-09 @19 #define EIDRM 36 /* Identifier removed */ 61730c538f8281 David Howells 2012-10-09 @20 #define ECHRNG 37 /* Channel number out of range */ 61730c538f8281 David Howells 2012-10-09 @21 #define EL2NSYNC 38 /* Level 2 not synchronized */ 61730c538f8281 David Howells 2012-10-09 @22 #define EL3HLT 39 /* Level 3 halted */ 61730c538f8281 David Howells 2012-10-09 @23 #define EL3RST 40 /* Level 3 reset */ 61730c538f8281 David Howells 2012-10-09 @24 #define ELNRNG 41 /* Link number out of range */ 61730c538f8281 David Howells 2012-10-09 @25 #define EUNATCH 42 /* Protocol driver not attached */ 61730c538f8281 David Howells 2012-10-09 @26 #define ENOCSI 43 /* No CSI structure available */ 61730c538f8281 David Howells 2012-10-09 @27 #define EL2HLT 44 /* Level 2 halted */ 61730c538f8281 David Howells 2012-10-09 @28 #define EDEADLK 45 /* Resource deadlock would occur */ 61730c538f8281 David Howells 2012-10-09 @29 #define ENOLCK 46 /* No record locks available */ 61730c538f8281 David Howells 2012-10-09 @30 #define EBADE 50 /* Invalid exchange */ 61730c538f8281 David Howells 2012-10-09 @31 #define EBADR 51 /* Invalid request descriptor */ 61730c538f8281 David Howells 2012-10-09 @32 #define EXFULL 52 /* Exchange full */ 61730c538f8281 David Howells 2012-10-09 @33 #define ENOANO 53 /* No anode */ 61730c538f8281 David Howells 2012-10-09 @34 #define EBADRQC 54 /* Invalid request code */ 61730c538f8281 David Howells 2012-10-09 @35 #define EBADSLT 55 /* Invalid slot */ 61730c538f8281 David Howells 2012-10-09 @36 #define EDEADLOCK 56 /* File locking deadlock error */ 61730c538f8281 David Howells 2012-10-09 37 #define EBFONT 59 /* Bad font file format */ 61730c538f8281 David Howells 2012-10-09 38 #define ENOSTR 60 /* Device not a stream */ 61730c538f8281 David Howells 2012-10-09 39 #define ENODATA 61 /* No data available */ 61730c538f8281 David Howells 2012-10-09 40 #define ETIME 62 /* Timer expired */ 61730c538f8281 David Howells 2012-10-09 41 #define ENOSR 63 /* Out of streams resources */ 61730c538f8281 David Howells 2012-10-09 42 #define ENONET 64 /* Machine is not on the network */ 61730c538f8281 David Howells 2012-10-09 43 #define ENOPKG 65 /* Package not installed */ 61730c538f8281 David Howells 2012-10-09 44 #define EREMOTE 66 /* Object is remote */ 61730c538f8281 David Howells 2012-10-09 45 #define ENOLINK 67 /* Link has been severed */ 61730c538f8281 David Howells 2012-10-09 46 #define EADV 68 /* Advertise error */ 61730c538f8281 David Howells 2012-10-09 47 #define ESRMNT 69 /* Srmount error */ 61730c538f8281 David Howells 2012-10-09 48 #define ECOMM 70 /* Communication error on send */ 61730c538f8281 David Howells 2012-10-09 49 #define EPROTO 71 /* Protocol error */ 61730c538f8281 David Howells 2012-10-09 50 #define EDOTDOT 73 /* RFS specific error */ 61730c538f8281 David Howells 2012-10-09 @51 #define EMULTIHOP 74 /* Multihop attempted */ 61730c538f8281 David Howells 2012-10-09 @52 #define EBADMSG 77 /* Not a data message */ 61730c538f8281 David Howells 2012-10-09 @53 #define ENAMETOOLONG 78 /* File name too long */ 61730c538f8281 David Howells 2012-10-09 @54 #define EOVERFLOW 79 /* Value too large for defined data type */ 61730c538f8281 David Howells 2012-10-09 @55 #define ENOTUNIQ 80 /* Name not unique on network */ 61730c538f8281 David Howells 2012-10-09 @56 #define EBADFD 81 /* File descriptor in bad state */ 61730c538f8281 David Howells 2012-10-09 @57 #define EREMCHG 82 /* Remote address changed */ 61730c538f8281 David Howells 2012-10-09 @58 #define ELIBACC 83 /* Can not access a needed shared library */ 61730c538f8281 David Howells 2012-10-09 @59 #define ELIBBAD 84 /* Accessing a corrupted shared library */ 61730c538f8281 David Howells 2012-10-09 @60 #define ELIBSCN 85 /* .lib section in a.out corrupted */ 61730c538f8281 David Howells 2012-10-09 @61 #define ELIBMAX 86 /* Attempting to link in too many shared libraries */ 61730c538f8281 David Howells 2012-10-09 @62 #define ELIBEXEC 87 /* Cannot exec a shared library directly */ 61730c538f8281 David Howells 2012-10-09 @63 #define EILSEQ 88 /* Illegal byte sequence */ 61730c538f8281 David Howells 2012-10-09 @64 #define ENOSYS 89 /* Function not implemented */ 61730c538f8281 David Howells 2012-10-09 @65 #define ELOOP 90 /* Too many symbolic links encountered */ 61730c538f8281 David Howells 2012-10-09 @66 #define ERESTART 91 /* Interrupted system call should be restarted */ 61730c538f8281 David Howells 2012-10-09 @67 #define ESTRPIPE 92 /* Streams pipe error */ 61730c538f8281 David Howells 2012-10-09 @68 #define ENOTEMPTY 93 /* Directory not empty */ 61730c538f8281 David Howells 2012-10-09 @69 #define EUSERS 94 /* Too many users */ 61730c538f8281 David Howells 2012-10-09 @70 #define ENOTSOCK 95 /* Socket operation on non-socket */ 61730c538f8281 David Howells 2012-10-09 @71 #define EDESTADDRREQ 96 /* Destination address required */ 61730c538f8281 David Howells 2012-10-09 @72 #define EMSGSIZE 97 /* Message too long */ 61730c538f8281 David Howells 2012-10-09 @73 #define EPROTOTYPE 98 /* Protocol wrong type for socket */ 61730c538f8281 David Howells 2012-10-09 @74 #define ENOPROTOOPT 99 /* Protocol not available */ 61730c538f8281 David Howells 2012-10-09 @75 #define EPROTONOSUPPORT 120 /* Protocol not supported */ 61730c538f8281 David Howells 2012-10-09 @76 #define ESOCKTNOSUPPORT 121 /* Socket type not supported */ 61730c538f8281 David Howells 2012-10-09 @77 #define EOPNOTSUPP 122 /* Operation not supported on transport endpoint */ 61730c538f8281 David Howells 2012-10-09 @78 #define EPFNOSUPPORT 123 /* Protocol family not supported */ 61730c538f8281 David Howells 2012-10-09 @79 #define EAFNOSUPPORT 124 /* Address family not supported by protocol */ 61730c538f8281 David Howells 2012-10-09 @80 #define EADDRINUSE 125 /* Address already in use */ 61730c538f8281 David Howells 2012-10-09 @81 #define EADDRNOTAVAIL 126 /* Cannot assign requested address */ 61730c538f8281 David Howells 2012-10-09 @82 #define ENETDOWN 127 /* Network is down */ 61730c538f8281 David Howells 2012-10-09 @83 #define ENETUNREACH 128 /* Network is unreachable */ 61730c538f8281 David Howells 2012-10-09 @84 #define ENETRESET 129 /* Network dropped connection because of reset */ 61730c538f8281 David Howells 2012-10-09 @85 #define ECONNABORTED 130 /* Software caused connection abort */ 61730c538f8281 David Howells 2012-10-09 @86 #define ECONNRESET 131 /* Connection reset by peer */ 61730c538f8281 David Howells 2012-10-09 @87 #define ENOBUFS 132 /* No buffer space available */ 61730c538f8281 David Howells 2012-10-09 @88 #define EISCONN 133 /* Transport endpoint is already connected */ 61730c538f8281 David Howells 2012-10-09 @89 #define ENOTCONN 134 /* Transport endpoint is not connected */ 61730c538f8281 David Howells 2012-10-09 @90 #define EUCLEAN 135 /* Structure needs cleaning */ 61730c538f8281 David Howells 2012-10-09 @91 #define ENOTNAM 137 /* Not a XENIX named type file */ 61730c538f8281 David Howells 2012-10-09 @92 #define ENAVAIL 138 /* No XENIX semaphores available */ 61730c538f8281 David Howells 2012-10-09 @93 #define EISNAM 139 /* Is a named type file */ 61730c538f8281 David Howells 2012-10-09 @94 #define EREMOTEIO 140 /* Remote I/O error */ 61730c538f8281 David Howells 2012-10-09 95 #define EINIT 141 /* Reserved */ 61730c538f8281 David Howells 2012-10-09 96 #define EREMDEV 142 /* Error 142 */ 61730c538f8281 David Howells 2012-10-09 @97 #define ESHUTDOWN 143 /* Cannot send after transport endpoint shutdown */ 61730c538f8281 David Howells 2012-10-09 @98 #define ETOOMANYREFS 144 /* Too many references: cannot splice */ 61730c538f8281 David Howells 2012-10-09 @99 #define ETIMEDOUT 145 /* Connection timed out */ 61730c538f8281 David Howells 2012-10-09 @100 #define ECONNREFUSED 146 /* Connection refused */ 61730c538f8281 David Howells 2012-10-09 @101 #define EHOSTDOWN 147 /* Host is down */ 61730c538f8281 David Howells 2012-10-09 @102 #define EHOSTUNREACH 148 /* No route to host */ 61730c538f8281 David Howells 2012-10-09 103 #define EWOULDBLOCK EAGAIN /* Operation would block */ 61730c538f8281 David Howells 2012-10-09 @104 #define EALREADY 149 /* Operation already in progress */ 61730c538f8281 David Howells 2012-10-09 @105 #define EINPROGRESS 150 /* Operation now in progress */ 0ca43435188b9f Eric Sandeen 2013-11-12 @106 #define ESTALE 151 /* Stale file handle */ 61730c538f8281 David Howells 2012-10-09 @107 #define ECANCELED 158 /* AIO operation canceled */ 61730c538f8281 David Howells 2012-10-09 108 61730c538f8281 David Howells 2012-10-09 109 /* 61730c538f8281 David Howells 2012-10-09 110 * These error are Linux extensions. 61730c538f8281 David Howells 2012-10-09 111 */ 61730c538f8281 David Howells 2012-10-09 @112 #define ENOMEDIUM 159 /* No medium found */ 61730c538f8281 David Howells 2012-10-09 @113 #define EMEDIUMTYPE 160 /* Wrong medium type */ 61730c538f8281 David Howells 2012-10-09 @114 #define ENOKEY 161 /* Required key not available */ 61730c538f8281 David Howells 2012-10-09 @115 #define EKEYEXPIRED 162 /* Key has expired */ 61730c538f8281 David Howells 2012-10-09 @116 #define EKEYREVOKED 163 /* Key has been revoked */ 61730c538f8281 David Howells 2012-10-09 @117 #define EKEYREJECTED 164 /* Key was rejected by service */ 61730c538f8281 David Howells 2012-10-09 118 61730c538f8281 David Howells 2012-10-09 119 /* for robust mutexes */ 61730c538f8281 David Howells 2012-10-09 @120 #define EOWNERDEAD 165 /* Owner died */ 61730c538f8281 David Howells 2012-10-09 @121 #define ENOTRECOVERABLE 166 /* State not recoverable */ 61730c538f8281 David Howells 2012-10-09 122 61730c538f8281 David Howells 2012-10-09 @123 #define ERFKILL 167 /* Operation not possible due to RF-kill */ 61730c538f8281 David Howells 2012-10-09 124 61730c538f8281 David Howells 2012-10-09 @125 #define EHWPOISON 168 /* Memory page has hardware error */ 61730c538f8281 David Howells 2012-10-09 126 61730c538f8281 David Howells 2012-10-09 @127 #define EDQUOT 1133 /* Quota exceeded */ 61730c538f8281 David Howells 2012-10-09 128 61730c538f8281 David Howells 2012-10-09 129 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support 2026-02-05 6:07 ` [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support Ryan Chen 2026-02-05 14:40 ` kernel test robot 2026-02-05 14:52 ` kernel test robot @ 2026-02-06 11:34 ` Thomas Gleixner 2026-02-07 3:50 ` Ryan Chen 2 siblings, 1 reply; 20+ messages in thread From: Thomas Gleixner @ 2026-02-06 11:34 UTC (permalink / raw) To: Ryan Chen, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti Cc: linux-kernel, devicetree, linux-arm-kernel, linux-aspeed, linux-riscv, Ryan Chen On Thu, Feb 05 2026 at 14:07, Ryan Chen wrote: > @@ -88,6 +88,7 @@ obj-$(CONFIG_MVEBU_PIC) += irq-mvebu-pic.o > obj-$(CONFIG_MVEBU_SEI) += irq-mvebu-sei.o > obj-$(CONFIG_LS_EXTIRQ) += irq-ls-extirq.o > obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o > +obj-$(CONFIG_ASPEED_AST2700_INTC) += irq-ast2700.o irq-ast2700-intc0.o irq-ast2700-intc1.o > obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o irq-aspeed-scu-ic.o > obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-intc.o > obj-$(CONFIG_STM32MP_EXTI) += irq-stm32mp-exti.o > diff --git a/drivers/irqchip/irq-ast2700-intc0-test.c b/drivers/irqchip/irq-ast2700-intc0-test.c How is this kunit test supposed to be built? Also split this kunit thing out into a separate patch. It is not relevant for the functional part. > new file mode 100644 > index 000000000000..d6bc19676b2e > --- /dev/null > +++ b/drivers/irqchip/irq-ast2700-intc0-test.c > @@ -0,0 +1,474 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (C) 2026 Code Construct > + */ > +#include <kunit/test.h> > +#include "irq-ast2700.h" > + > +static void aspeed_intc0_resolve_route_bad_args(struct kunit *test) > +{ > + static const struct aspeed_intc_interrupt_range c1ranges[] = { 0 }; > + static const aspeed_intc_output_t c1outs[] = { 0 }; > + struct aspeed_intc_interrupt_range resolved; > + const struct irq_domain c0domain = { 0 }; > + Pointless newline > + int rc; > + > + rc = aspeed_intc0_resolve_route(NULL, 0, c1outs, 0, c1ranges, NULL); > + KUNIT_EXPECT_EQ(test, rc, -EINVAL); > + > + rc = aspeed_intc0_resolve_route(&c0domain, 0, c1outs, > + ARRAY_SIZE(c1ranges), c1ranges, > + &resolved); > + KUNIT_EXPECT_EQ(test, rc, -ENODEV); > + > + rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs, > + 0, c1ranges, &resolved); > + KUNIT_EXPECT_EQ(test, rc, -ENODEV); > +} > + > +static int > +arm_gicv3_fwnode_read_string_array(const struct fwnode_handle *fwnode_handle, > + const char *propname, const char **val, > + size_t nval) Please use the full 100 character you have available and avoid extra line breaks. It fits nicely into two lines: static int arm_gicv3_fwnode_read_string_array(const struct fwnode_handle *fwnode_handle, const char *propname, const char **val, size_t nval) There is also no real point to have these overly long function and argument names. > +#include <asm-generic/errno.h> That's wrong. Include <linux/errno.h> > +#include <dt-bindings/interrupt-controller/arm-gic.h> > + > +#include "irq-ast2700.h" Missing newline > +#define INT_NUM 480 > +#define INTM_NUM 50 > +#define SWINT_NUM 16 > + > +#define INTM_BASE (INT_NUM) > +#define SWINT_BASE (INT_NUM + INTM_NUM) > +#define INT0_NUM (INT_NUM + INTM_NUM + SWINT_NUM) > + > +#define GIC_P2P_SPI_END 128 > + > +#define INTC0_SWINT_IER 0x10 > +#define INTC0_SWINT_ISR 0x14 > +#define INTC0_INTBANKX_IER 0x1000 > +#define INTC0_INTBANK_GROUPS 11 > +#define INTC0_INTBANKS_PER_GRP 3 > +#define INTC0_INTMX_IER 0x1b00 > +#define INTC0_INTMX_ISR 0x1b04 > +#define INTC0_INTM_BANK_NUM 3 > +#define INTM_IRQS_PER_BANK 10 If you make these defines tabular and they become readable: #define INT_NUM 480 #define INTM_NUM 50 ... #define INTM_BASE (INT_NUM) ... #define GIC_P2P_SPI_END 128 ... #define INTC0_SWINT_IER 0x10 See? > +struct aspeed_intc0 { > + struct device *dev; > + void __iomem *base; > + raw_spinlock_t intc_lock; > + struct irq_domain *local; > + struct device_node *parent; > + struct aspeed_intc_interrupt_ranges ranges; > +}; https://www.kernel.org/doc/html/latest/process/maintainer-tip.html#struct-declarations-and-initializers I pointed you to that documentation before. Do I really have to remind you every couple of week? > + > +static void aspeed_swint_irq_mask(struct irq_data *data) > +{ > + struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data); > + int bit = data->hwirq - SWINT_BASE; > + unsigned int mask; > + > + guard(raw_spinlock_irqsave)(&intc0->intc_lock); s/_irqsave// Interrupts are disabled when this is invoked. > + mask = readl(intc0->base + INTC0_SWINT_IER) & ~BIT(bit); > + writel(mask, intc0->base + INTC0_SWINT_IER); > + irq_chip_mask_parent(data); > +} > + > +static void aspeed_swint_irq_unmask(struct irq_data *data) > +{ > + struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data); > + int bit = data->hwirq - SWINT_BASE; > + unsigned int unmask; > + > + guard(raw_spinlock_irqsave)(&intc0->intc_lock); > + unmask = readl(intc0->base + INTC0_SWINT_IER) | BIT(bit); These unmask/mask variable are simply not helpful. What's wrong with naming them 'ier' because that's what this is about. And while at it the data type for hardware related variables is u32 not unsigned int to make it clear. > +static struct irq_chip aspeed_swint_chip = { > + .name = "ast2700-swint", > + .irq_eoi = aspeed_swint_irq_eoi, > + .irq_mask = aspeed_swint_irq_mask, > + .irq_unmask = aspeed_swint_irq_unmask, > + .irq_set_affinity = irq_chip_set_affinity_parent, > + .flags = IRQCHIP_SET_TYPE_MASKED, See above > + > +#define INTC0_IN_NUM 480 > +#define INTC0_ROUTE_NUM 5 Those should be at the top of the file next to the other constants. > +static const aspeed_intc_output_t aspeed_intc0_routes[INTC0_IN_NUM / 32][INTC0_ROUTE_NUM] = { > + [0] = { > + [0b000] = 0, > + [0b001] = 256, > + [0b010] = 426, > + [0b011] = AST2700_INTC_INVALID_ROUTE, > + [0b100] = AST2700_INTC_INVALID_ROUTE, Seriously? What's the point of this binary notation and the insane amount of space this table occupies? [0] = { 0, 256, 426, AST2700_INTC_INVALID_ROUTE, AST2700_INTC_INVALID_ROUTE }, [1] = { 32, 288, 458, AST2700_INTC_INVALID_ROUTE, AST2700_INTC_INVALID_ROUTE }, [4] = { 128, 384, 554, 160, 176 }, ... > + > +#define INTC0_INTM_NUM 50 > + > +static const aspeed_intc_output_t > + aspeed_intc0_intm_routes[INTC0_INTM_NUM / 10] = { pointless line break > + [0] = 192, /* INTM00 ~ INTM09 */ > + [1] = 416, /* INTM10 ~ INTM19 */ > + [2] = 586, /* INTM20 ~ INTM29 */ > + [3] = 208, /* INTM30 ~ INTM39 */ > + [4] = 224, /* INTM40 ~ INTM49 */ > + }; > + > +static bool range_contains_element(u32 start, u32 count, u32 value) in_range32() provides that already > +{ > + if (WARN_ON_ONCE((U32_MAX - count) < start)) > + return false; > + > + return value >= start && value < start + count; > +} > + > +static int > +resolve_input_from_child_ranges(const struct aspeed_intc0 *intc0, > + const struct aspeed_intc_interrupt_range *range, > + u32 outpin, u32 *input) > +{ > + u32 offset; > + u32 base; One line > + > + if (!range_contains_element(range->start, range->count, outpin)) > + return -ENOENT; > + > + if (range->upstream.param_count == 0) > + return -EINVAL; > + > + base = range->upstream.param[0]; > + offset = outpin - range->start; > + if ((U32_MAX - offset) < base) { if (!in_range32(...) > + dev_warn(intc0->dev, > + "%s: Arithmetic overflow for input derivation: %u + %u\n", Pointless line break. Please fix them all over the place. > + __func__, base, offset); > + return -EINVAL; > + } > + > + *input = base + offset; > + return 0; > +static int resolve_parent_route_for_input(const struct aspeed_intc0 *intc0, > + const struct fwnode_handle *parent, u32 input, > + struct aspeed_intc_interrupt_range *resolved) > +{ > + aspeed_intc_output_t c0o; > + int rc = -ENOENT; > + > + if (input < INT_NUM) { > + bool found; > + > + dev_dbg(intc0->dev, "%s: Resolving parent route for linear input %u\n", > + __func__, input); Do you really still need all those debug prints or are you trusting your code by now? If they still are considered valuable then shorten them in a sensible way so they nicely hide in the code instead of cluttering it to the point of making it unreadable. > +{ > + struct aspeed_intc0 *intc0; > + struct fwnode_handle *parent_fwnode; > + int ret; See Documentation about variable declarations... > + for (size_t i = 0; i < nc1outs; i++) { > + aspeed_intc_output_t c1o = c1outs[i]; > + > + if (c1o == AST2700_INTC_INVALID_ROUTE) { > + dev_dbg(intc0->dev, "%s: Invalid output at route index %zu\n", > + __func__, i); > + continue; > + } > + > + dev_dbg(intc0->dev, "%s: Have output %u for route index %zu\n", > + __func__, c1o, i); > + > + for (size_t j = 0; j < nc1ranges; j++) { > + struct aspeed_intc_interrupt_range c1r = c1ranges[j]; > + u32 input; > + > + dev_dbg(intc0->dev, > + "%s: Inspecting candidate range %zu starting at %u for %u\n", > + __func__, j, c1r.start, c1r.count); > + > + /* > + * Range match for intc1 output pin > + * > + * Assume a failed match is still a match for the purpose of testing, > + * saves a bunch of mess in the test fixtures > + */ > + if (!(c0domain == irq_find_matching_fwspec(&c1r.upstream, > + c0domain->bus_token) || > + IS_ENABLED(CONFIG_ASPEED_AST2700_INTC_TEST))) { > + dev_dbg(intc0->dev, "%s: Parent mismatch for candidate range %zu\n", > + __func__, j); > + continue; > + } > + > + ret = resolve_input_from_child_ranges(intc0, &c1r, c1o, &input); > + if (ret) { > + if (ret == -ENOENT) > + dev_dbg(intc0->dev, > + "%s: Output %u not in candidate range %zu starting at %u for %u\n", > + __func__, c1o, j, c1r.start, c1r.count); > + continue; All of this is unreadable and I told you about the bracket rules before, no? > + } > + dev_dbg(intc0->dev, > + "%s: Resolved INTC0 input to %u using candidate range %zu: [%u, %u)\n", > + __func__, input, j, c1r.start, c1r.start + c1r.count); > + > + /* > + * INTC1 should never request routes for peripheral interrupt sources > + * directly attached to INTC0. > + */ > + if (input < GIC_P2P_SPI_END) { > + dev_dbg(intc0->dev, > + "%s: Invalid range specification at index %zu routed INTC1 output to unreachable INTC0 input\n", > + __func__, j); > + continue; > + } > + > + ret = resolve_parent_route_for_input(intc0, parent_fwnode, input, NULL); > + if (ret < 0) > + continue; > + > + /* Route resolution succeeded */ > + resolved->start = c1o; > + resolved->count = 1; > + resolved->upstream = c1r.upstream; > + resolved->upstream.param[0] = input; > + dev_dbg(intc0->dev, > + "%s: Route resolution selected INTC1 output %u via index %zu\n", > + __func__, c1o, i); > + /* Cast protected by prior test against nc1outs */ > + return (int)i; > + } > + } > + > + ret = -EHOSTUNREACH; > + return ret; Impressive. > +} > +EXPORT_SYMBOL_GPL(aspeed_intc0_resolve_route); What is this export for? All usage sites are built in, no? > +static int aspeed_intc0_irq_domain_map(struct irq_domain *domain, > + unsigned int irq, irq_hw_number_t hwirq) > +{ > + if (hwirq < GIC_P2P_SPI_END) > + irq_set_chip_and_handler(irq, &linear_intr_irq_chip, > + handle_level_irq); Make this one line. Otherwise you need brackets. > + else if (hwirq < INTM_BASE) > + return -EINVAL; > + else if (hwirq < SWINT_BASE) > + irq_set_chip_and_handler(irq, &aspeed_intm_chip, > + handle_level_irq); > + else if (hwirq < INT0_NUM) > + irq_set_chip_and_handler(irq, &aspeed_swint_chip, > + handle_level_irq); > + else > + return -EINVAL; > + > + irq_set_chip_data(irq, domain->host_data); > + return 0; > +} > +static int aspeed_intc0_irq_domain_activate(struct irq_domain *domain, > + struct irq_data *data, bool reserve) > +{ > + struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data); > + > + if (data->hwirq < INT_NUM) { > + int bank = data->hwirq / 32; > + int bit = data->hwirq % 32; > + u32 mask = BIT(bit); > + int route; > + > + route = resolve_parent_route_for_input(intc0, > + intc0->local->parent->fwnode, > + data->hwirq, NULL); > + if (route < 0) > + return route; > + > + guard(raw_spinlock_irqsave)(&intc0->intc_lock); > + for (int i = 0; i < 3; i++) { > + void __iomem *sel = intc0->base + 0x200 + bank * 4 + 0x100 * i; Magic constants 0x200 4 and 0x100. Use proper defines and a macro/inline to calculate the register address and not this incomprehensible garbage. > + u32 reg = readl(sel); > + > + if (route & BIT(i)) > + reg |= mask; > + else > + reg &= ~mask; > + > + writel(reg, sel); > + if (readl(sel) != reg) > + return -EACCES; > + } > + } else if (data->hwirq < INT0_NUM) { > + return 0; > + } else { > + return -EINVAL; > + } If you rearrange those conditions you can avoid the indentation all together if (in_range32(data->hwirq, INTM_BASE, INTM_NUM + SWINT_NUM)) return 0; if (data->hwirq >= INT_NUM) return -EINVAL; No? > + > + return 0; > +} > + > +static void aspeed_intc0_disable_intbank(struct aspeed_intc0 *intc0) > +{ > + int i, j; > + > + for (i = 0; i < INTC0_INTBANK_GROUPS; i++) { > + for (j = 0; j < INTC0_INTBANKS_PER_GRP; j++) { Both i and j should be declared in the for () statement. Your coding style is so inconsistent it's not even funny anymore. > + u32 base = INTC0_INTBANKX_IER + (0x100 * i) + (0x10 * j); > + > + writel(0, intc0->base + base); > + } > + } > +} > +IRQCHIP_PLATFORM_DRIVER_BEGIN(ast2700_intc0) > +IRQCHIP_MATCH("aspeed,ast2700-intc0-ic", aspeed_intc0_ic_probe) > +IRQCHIP_PLATFORM_DRIVER_END(ast2700_intc0) > + > +#ifdef CONFIG_ASPEED_AST2700_INTC_TEST > +#include "irq-ast2700-intc0-test.c" > +#endif Yikes. What's wrong with Makefile? > diff --git a/drivers/irqchip/irq-ast2700-intc1.c b/drivers/irqchip/irq-ast2700-intc1.c > +static void aspeed_intc1_ic_irq_handler(struct irq_desc *desc) > +{ > + struct aspeed_intc1 *intc1 = irq_desc_get_handler_data(desc); > + struct irq_chip *chip = irq_desc_get_chip(desc); > + unsigned long bit, status; > + > + chained_irq_enter(chip, desc); > + > + for (int bank = 0; bank < INTC1_BANK_NUM; bank++) { > + status = readl(intc1->base + INTC1_ISR + (0x10 * bank)); > + if (!status) > + continue; > + > + for_each_set_bit(bit, &status, INTC1_IRQS_PER_BANK) { > + generic_handle_domain_irq(intc1->local, > + (bank * INTC1_IRQS_PER_BANK) + > + bit); > + writel(BIT(bit), > + intc1->base + INTC1_ISR + (0x10 * bank)); My eyes bleed by now. Thanks, tglx ^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support 2026-02-06 11:34 ` Thomas Gleixner @ 2026-02-07 3:50 ` Ryan Chen 2026-02-07 12:40 ` Thomas Gleixner 0 siblings, 1 reply; 20+ messages in thread From: Ryan Chen @ 2026-02-07 3:50 UTC (permalink / raw) To: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-aspeed@lists.ozlabs.org, linux-riscv@lists.infradead.org Hello Thomas, Thanks your feedback. > -----Original Message----- > From: Thomas Gleixner <tglx@linutronix.de> > Sent: Friday, February 6, 2026 7:34 PM > To: Ryan Chen <ryan_chen@aspeedtech.com>; Rob Herring <robh@kernel.org>; > Krzysztof Kozlowski <krzk+dt@kernel.org>; Conor Dooley > <conor+dt@kernel.org>; Joel Stanley <joel@jms.id.au>; Andrew Jeffery > <andrew@codeconstruct.com.au>; Paul Walmsley <pjw@kernel.org>; Palmer > Dabbelt <palmer@dabbelt.com>; Albert Ou <aou@eecs.berkeley.edu>; > Alexandre Ghiti <alex@ghiti.fr> > Cc: linux-kernel@vger.kernel.org; devicetree@vger.kernel.org; > linux-arm-kernel@lists.infradead.org; linux-aspeed@lists.ozlabs.org; > linux-riscv@lists.infradead.org; Ryan Chen <ryan_chen@aspeedtech.com> > Subject: Re: [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 > support > > On Thu, Feb 05 2026 at 14:07, Ryan Chen wrote: > > @@ -88,6 +88,7 @@ obj-$(CONFIG_MVEBU_PIC) += > irq-mvebu-pic.o > > obj-$(CONFIG_MVEBU_SEI) += irq-mvebu-sei.o > > obj-$(CONFIG_LS_EXTIRQ) += irq-ls-extirq.o > > obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o > > +obj-$(CONFIG_ASPEED_AST2700_INTC) += irq-ast2700.o > irq-ast2700-intc0.o irq-ast2700-intc1.o > > obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o > irq-aspeed-scu-ic.o > > obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-intc.o > > obj-$(CONFIG_STM32MP_EXTI) += irq-stm32mp-exti.o > > diff --git a/drivers/irqchip/irq-ast2700-intc0-test.c > > b/drivers/irqchip/irq-ast2700-intc0-test.c > > How is this kunit test supposed to be built? Sorry, do you mean split it with Makefile? obj-$(CONFIG_ASPEED_AST2700_INTC_TEST) += irq-ast2700-intc0-test.o > > Also split this kunit thing out into a separate patch. It is not relevant for the > functional part. Will update to separate patch > > > new file mode 100644 > > index 000000000000..d6bc19676b2e > > --- /dev/null > > +++ b/drivers/irqchip/irq-ast2700-intc0-test.c > > @@ -0,0 +1,474 @@ > > +// SPDX-License-Identifier: GPL-2.0-only > > +/* > > + * Copyright (C) 2026 Code Construct */ #include <kunit/test.h> > > +#include "irq-ast2700.h" > > + > > +static void aspeed_intc0_resolve_route_bad_args(struct kunit *test) { > > + static const struct aspeed_intc_interrupt_range c1ranges[] = { 0 }; > > + static const aspeed_intc_output_t c1outs[] = { 0 }; > > + struct aspeed_intc_interrupt_range resolved; > > + const struct irq_domain c0domain = { 0 }; > > + > > Pointless newline Will update. > > > + int rc; > > + > > + rc = aspeed_intc0_resolve_route(NULL, 0, c1outs, 0, c1ranges, NULL); > > + KUNIT_EXPECT_EQ(test, rc, -EINVAL); > > + > > + rc = aspeed_intc0_resolve_route(&c0domain, 0, c1outs, > > + ARRAY_SIZE(c1ranges), c1ranges, > > + &resolved); > > + KUNIT_EXPECT_EQ(test, rc, -ENODEV); > > + > > + rc = aspeed_intc0_resolve_route(&c0domain, ARRAY_SIZE(c1outs), c1outs, > > + 0, c1ranges, &resolved); > > + KUNIT_EXPECT_EQ(test, rc, -ENODEV); > > +} > > + > > +static int > > +arm_gicv3_fwnode_read_string_array(const struct fwnode_handle > *fwnode_handle, > > + const char *propname, const char **val, > > + size_t nval) > > Please use the full 100 character you have available and avoid extra line breaks. > It fits nicely into two lines: > > static int arm_gicv3_fwnode_read_string_array(const struct fwnode_handle > *fwnode_handle, > const char *propname, const char > **val, size_t nval) > > There is also no real point to have these overly long function and argument > names. Will update static int gicv3_fwnode_read_string_array(const struct fwnode_handle *fwnode, const char *propname, const char **val, size_t nval) > > > +#include <asm-generic/errno.h> > > That's wrong. Include <linux/errno.h> Will update. > > > +#include <dt-bindings/interrupt-controller/arm-gic.h> > > + > > +#include "irq-ast2700.h" > > Missing newline Will update > > > +#define INT_NUM 480 > > +#define INTM_NUM 50 > > +#define SWINT_NUM 16 > > + > > +#define INTM_BASE (INT_NUM) > > +#define SWINT_BASE (INT_NUM + INTM_NUM) #define INT0_NUM > (INT_NUM + > > +INTM_NUM + SWINT_NUM) > > + > > +#define GIC_P2P_SPI_END 128 > > + > > +#define INTC0_SWINT_IER 0x10 > > +#define INTC0_SWINT_ISR 0x14 > > +#define INTC0_INTBANKX_IER 0x1000 > > +#define INTC0_INTBANK_GROUPS 11 > > +#define INTC0_INTBANKS_PER_GRP 3 > > +#define INTC0_INTMX_IER 0x1b00 > > +#define INTC0_INTMX_ISR 0x1b04 > > +#define INTC0_INTM_BANK_NUM 3 > > +#define INTM_IRQS_PER_BANK 10 > > If you make these defines tabular and they become readable: Will update > > #define INT_NUM 480 > #define INTM_NUM 50 > ... > #define INTM_BASE (INT_NUM) > ... > #define GIC_P2P_SPI_END 128 > ... > #define INTC0_SWINT_IER 0x10 > > See? Sorry, do you mean tab? If yes, I will update all with tab #define INT_NUM 480 #define INTM_NUM 50 #define SWINT_NUM 16 #define INTM_BASE (INT_NUM) #define SWINT_BASE (INT_NUM + INTM_NUM) #define INT0_NUM (INT_NUM + INTM_NUM + SWINT_NUM) #define GIC_P2P_SPI_END 128 #define INTC0_SWINT_IER 0x10 #define INTC0_SWINT_ISR 0x14 #define INTC0_INTBANKX_IER 0x1000 #define INTC0_INTBANK_GROUPS 11 #define INTC0_INTBANKS_PER_GRP 3 #define INTC0_INTMX_IER 0x1b00 #define INTC0_INTMX_ISR 0x1b04 #define INTC0_INTM_BANK_NUM 3 #define INTM_IRQS_PER_BANK 10 > > > +struct aspeed_intc0 { > > + struct device *dev; > > + void __iomem *base; > > + raw_spinlock_t intc_lock; > > + struct irq_domain *local; > > + struct device_node *parent; > > + struct aspeed_intc_interrupt_ranges ranges; }; > > https://www.kernel.org/doc/html/latest/process/maintainer-tip.html#struct-de > clarations-and-initializers > > I pointed you to that documentation before. Do I really have to remind you > every couple of week? Sorry, my fault, will update. > > > + > > +static void aspeed_swint_irq_mask(struct irq_data *data) { > > + struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data); > > + int bit = data->hwirq - SWINT_BASE; > > + unsigned int mask; > > + > > + guard(raw_spinlock_irqsave)(&intc0->intc_lock); > > s/_irqsave// Interrupts are disabled when this is invoked. Sorry, do you mean when this function been call. Ther have desc->lock to do the raw_spin_lock_irqsave. Am I right? > > > + mask = readl(intc0->base + INTC0_SWINT_IER) & ~BIT(bit); > > + writel(mask, intc0->base + INTC0_SWINT_IER); > > + irq_chip_mask_parent(data); > > +} > > + > > +static void aspeed_swint_irq_unmask(struct irq_data *data) { > > + struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data); > > + int bit = data->hwirq - SWINT_BASE; > > + unsigned int unmask; > > + > > + guard(raw_spinlock_irqsave)(&intc0->intc_lock); > > + unmask = readl(intc0->base + INTC0_SWINT_IER) | BIT(bit); > > These unmask/mask variable are simply not helpful. What's wrong with > naming them 'ier' because that's what this is about. And while at it the data > type for hardware related variables is u32 not unsigned int to make it clear. > Thanks, Will use u32 ier; > > +static struct irq_chip aspeed_swint_chip = { > > + .name = "ast2700-swint", > > + .irq_eoi = aspeed_swint_irq_eoi, > > + .irq_mask = aspeed_swint_irq_mask, > > + .irq_unmask = aspeed_swint_irq_unmask, > > + .irq_set_affinity = irq_chip_set_affinity_parent, > > + .flags = IRQCHIP_SET_TYPE_MASKED, > > See above All those will review it again. Thanks. > > > + > > +#define INTC0_IN_NUM 480 > > +#define INTC0_ROUTE_NUM 5 > > Those should be at the top of the file next to the other constants. Will update. > > > +static const aspeed_intc_output_t aspeed_intc0_routes[INTC0_IN_NUM / > 32][INTC0_ROUTE_NUM] = { > > + [0] = { > > + [0b000] = 0, > > + [0b001] = 256, > > + [0b010] = 426, > > + [0b011] = AST2700_INTC_INVALID_ROUTE, > > + [0b100] = AST2700_INTC_INVALID_ROUTE, > > Seriously? What's the point of this binary notation and the insane amount of > space this table occupies? > > [0] = { 0, 256, 426, AST2700_INTC_INVALID_ROUTE, > AST2700_INTC_INVALID_ROUTE }, > [1] = { 32, 288, 458, AST2700_INTC_INVALID_ROUTE, > AST2700_INTC_INVALID_ROUTE }, > [4] = { 128, 384, 554, 160, 176 }, > ... > Thanks, will update. > > > + > > +#define INTC0_INTM_NUM 50 > > + > > +static const aspeed_intc_output_t > > + aspeed_intc0_intm_routes[INTC0_INTM_NUM / 10] = { > > pointless line break > > > + [0] = 192, /* INTM00 ~ INTM09 */ > > + [1] = 416, /* INTM10 ~ INTM19 */ > > + [2] = 586, /* INTM20 ~ INTM29 */ > > + [3] = 208, /* INTM30 ~ INTM39 */ > > + [4] = 224, /* INTM40 ~ INTM49 */ > > + }; > > + > > +static bool range_contains_element(u32 start, u32 count, u32 value) > > in_range32() provides that already Will update. > > > +{ > > + if (WARN_ON_ONCE((U32_MAX - count) < start)) > > + return false; > > + > > + return value >= start && value < start + count; } > > + > > +static int > > +resolve_input_from_child_ranges(const struct aspeed_intc0 *intc0, > > + const struct aspeed_intc_interrupt_range *range, > > + u32 outpin, u32 *input) > > +{ > > + u32 offset; > > + u32 base; > > One line Will update > > > + > > + if (!range_contains_element(range->start, range->count, outpin)) > > + return -ENOENT; > > + > > + if (range->upstream.param_count == 0) > > + return -EINVAL; > > + > > + base = range->upstream.param[0]; > > + offset = outpin - range->start; > > + if ((U32_MAX - offset) < base) { > > if (!in_range32(...) Will update if (offset && !in_range32(base, 0, U32_MAX - offset + 1)) { > > > > + dev_warn(intc0->dev, > > + "%s: Arithmetic overflow for input derivation: %u + %u\n", > > Pointless line break. Please fix them all over the place. Will update dev_warn(intc0->dev, "%s: Arithmetic overflow for input derivation: %u + %u\n", __func__, base, offset); > > > + __func__, base, offset); > > + return -EINVAL; > > + } > > + > > + *input = base + offset; > > + return 0; > > +static int resolve_parent_route_for_input(const struct aspeed_intc0 *intc0, > > + const struct fwnode_handle *parent, u32 input, > > + struct aspeed_intc_interrupt_range *resolved) { > > + aspeed_intc_output_t c0o; > > + int rc = -ENOENT; > > + > > + if (input < INT_NUM) { > > + bool found; > > + > > + dev_dbg(intc0->dev, "%s: Resolving parent route for linear input > %u\n", > > + __func__, input); > > Do you really still need all those debug prints or are you trusting your code by > now? > > If they still are considered valuable then shorten them in a sensible way so they > nicely hide in the code instead of cluttering it to the point of making it > unreadable. Will try to remove dev_dbg. > > > +{ > > + struct aspeed_intc0 *intc0; > > + struct fwnode_handle *parent_fwnode; > > + int ret; > > See Documentation about variable declarations... Will update struct fwnode_handle *parent_fwnode; struct aspeed_intc0 *intc0; int ret; > > > + for (size_t i = 0; i < nc1outs; i++) { > > + aspeed_intc_output_t c1o = c1outs[i]; > > + > > + if (c1o == AST2700_INTC_INVALID_ROUTE) { > > + dev_dbg(intc0->dev, "%s: Invalid output at route index %zu\n", > > + __func__, i); > > + continue; > > + } > > + > > + dev_dbg(intc0->dev, "%s: Have output %u for route index %zu\n", > > + __func__, c1o, i); > > + > > + for (size_t j = 0; j < nc1ranges; j++) { > > + struct aspeed_intc_interrupt_range c1r = c1ranges[j]; > > + u32 input; > > + > > + dev_dbg(intc0->dev, > > + "%s: Inspecting candidate range %zu starting at %u for > %u\n", > > + __func__, j, c1r.start, c1r.count); > > + > > + /* > > + * Range match for intc1 output pin > > + * > > + * Assume a failed match is still a match for the purpose of > testing, > > + * saves a bunch of mess in the test fixtures > > + */ > > + if (!(c0domain == irq_find_matching_fwspec(&c1r.upstream, > > + c0domain->bus_token) || > > + IS_ENABLED(CONFIG_ASPEED_AST2700_INTC_TEST))) { > > + dev_dbg(intc0->dev, "%s: Parent mismatch for candidate > range %zu\n", > > + __func__, j); > > + continue; > > + } > > + > > + ret = resolve_input_from_child_ranges(intc0, &c1r, c1o, &input); > > + if (ret) { > > + if (ret == -ENOENT) > > + dev_dbg(intc0->dev, > > + "%s: Output %u not in candidate range %zu > starting at %u for %u\n", > > + __func__, c1o, j, c1r.start, c1r.count); > > + continue; > > All of this is unreadable and I told you about the bracket rules before, no? Will remove dev_dbg with following ret = resolve_input_from_child_ranges(intc0, &c1r, c1o, &input); if (ret) continue; > > > + } > > + dev_dbg(intc0->dev, > > + "%s: Resolved INTC0 input to %u using candidate range %zu: > [%u, %u)\n", > > + __func__, input, j, c1r.start, c1r.start + c1r.count); > > + > > + /* > > + * INTC1 should never request routes for peripheral interrupt > sources > > + * directly attached to INTC0. > > + */ > > + if (input < GIC_P2P_SPI_END) { > > + dev_dbg(intc0->dev, > > + "%s: Invalid range specification at index %zu routed > INTC1 output to unreachable INTC0 input\n", > > + __func__, j); > > + continue; > > + } > > + > > + ret = resolve_parent_route_for_input(intc0, parent_fwnode, > input, NULL); > > + if (ret < 0) > > + continue; > > + > > + /* Route resolution succeeded */ > > + resolved->start = c1o; > > + resolved->count = 1; > > + resolved->upstream = c1r.upstream; > > + resolved->upstream.param[0] = input; > > + dev_dbg(intc0->dev, > > + "%s: Route resolution selected INTC1 output %u via index > %zu\n", > > + __func__, c1o, i); > > + /* Cast protected by prior test against nc1outs */ > > + return (int)i; > > + } > > + } > > + > > + ret = -EHOSTUNREACH; > > + return ret; > > Impressive. Will try to improve this function. > > > +} > > +EXPORT_SYMBOL_GPL(aspeed_intc0_resolve_route); > > What is this export for? All usage sites are built in, no? Will remove this. > > > +static int aspeed_intc0_irq_domain_map(struct irq_domain *domain, > > + unsigned int irq, irq_hw_number_t hwirq) { > > + if (hwirq < GIC_P2P_SPI_END) > > + irq_set_chip_and_handler(irq, &linear_intr_irq_chip, > > + handle_level_irq); > > Make this one line. Otherwise you need brackets. Will update all if (hwirq < GIC_P2P_SPI_END) irq_set_chip_and_handler(irq, &linear_intr_irq_chip, handle_level_irq); else if (hwirq < INTM_BASE) return -EINVAL; else if (hwirq < SWINT_BASE) irq_set_chip_and_handler(irq, &aspeed_intm_chip, handle_level_irq); else if (hwirq < INT0_NUM) irq_set_chip_and_handler(irq, &aspeed_swint_chip, handle_level_irq); else return -EINVAL; > > > + else if (hwirq < INTM_BASE) > > + return -EINVAL; > > + else if (hwirq < SWINT_BASE) > > + irq_set_chip_and_handler(irq, &aspeed_intm_chip, > > + handle_level_irq); > > + else if (hwirq < INT0_NUM) > > + irq_set_chip_and_handler(irq, &aspeed_swint_chip, > > + handle_level_irq); > > + else > > + return -EINVAL; > > + > > + irq_set_chip_data(irq, domain->host_data); > > + return 0; > > +} > > > +static int aspeed_intc0_irq_domain_activate(struct irq_domain *domain, > > + struct irq_data *data, bool reserve) { > > + struct aspeed_intc0 *intc0 = irq_data_get_irq_chip_data(data); > > + > > + if (data->hwirq < INT_NUM) { > > + int bank = data->hwirq / 32; > > + int bit = data->hwirq % 32; > > + u32 mask = BIT(bit); > > + int route; > > + > > + route = resolve_parent_route_for_input(intc0, > > + intc0->local->parent->fwnode, > > + data->hwirq, NULL); > > + if (route < 0) > > + return route; > > + > > + guard(raw_spinlock_irqsave)(&intc0->intc_lock); > > + for (int i = 0; i < 3; i++) { > > + void __iomem *sel = intc0->base + 0x200 + bank * 4 + 0x100 * > i; > > Magic constants 0x200 4 and 0x100. Use proper defines and a macro/inline to > calculate the register address and not this incomprehensible garbage. Will update with #define > > > + u32 reg = readl(sel); > > + > > + if (route & BIT(i)) > > + reg |= mask; > > + else > > + reg &= ~mask; > > + > > + writel(reg, sel); > > + if (readl(sel) != reg) > > + return -EACCES; > > + } > > + } else if (data->hwirq < INT0_NUM) { > > + return 0; > > + } else { > > + return -EINVAL; > > + } > > If you rearrange those conditions you can avoid the indentation all together > > if (in_range32(data->hwirq, INTM_BASE, INTM_NUM + > SWINT_NUM)) > return 0; > if (data->hwirq >= INT_NUM) > return -EINVAL; > > No? Got it will update > > > + > > + return 0; > > +} > > + > > +static void aspeed_intc0_disable_intbank(struct aspeed_intc0 *intc0) > > +{ > > + int i, j; > > + > > + for (i = 0; i < INTC0_INTBANK_GROUPS; i++) { > > + for (j = 0; j < INTC0_INTBANKS_PER_GRP; j++) { > > Both i and j should be declared in the for () statement. Your coding style is so > inconsistent it's not even funny anymore. Will update. > > > + u32 base = INTC0_INTBANKX_IER + (0x100 * i) + (0x10 * j); > > + > > + writel(0, intc0->base + base); > > + } > > + } > > +} > > +IRQCHIP_PLATFORM_DRIVER_BEGIN(ast2700_intc0) > > +IRQCHIP_MATCH("aspeed,ast2700-intc0-ic", aspeed_intc0_ic_probe) > > +IRQCHIP_PLATFORM_DRIVER_END(ast2700_intc0) > > + > > +#ifdef CONFIG_ASPEED_AST2700_INTC_TEST #include > > +"irq-ast2700-intc0-test.c" > > +#endif > > Yikes. What's wrong with Makefile? Will remove it. And add it in Makefile obj-$(CONFIG_ASPEED_AST2700_INTC_TEST) += irq-ast2700-intc0-test.o > > > diff --git a/drivers/irqchip/irq-ast2700-intc1.c > > b/drivers/irqchip/irq-ast2700-intc1.c > > +static void aspeed_intc1_ic_irq_handler(struct irq_desc *desc) { > > + struct aspeed_intc1 *intc1 = irq_desc_get_handler_data(desc); > > + struct irq_chip *chip = irq_desc_get_chip(desc); > > + unsigned long bit, status; > > + > > + chained_irq_enter(chip, desc); > > + > > + for (int bank = 0; bank < INTC1_BANK_NUM; bank++) { > > + status = readl(intc1->base + INTC1_ISR + (0x10 * bank)); > > + if (!status) > > + continue; > > + > > + for_each_set_bit(bit, &status, INTC1_IRQS_PER_BANK) { > > + generic_handle_domain_irq(intc1->local, > > + (bank * INTC1_IRQS_PER_BANK) + > > + bit); > > + writel(BIT(bit), > > + intc1->base + INTC1_ISR + (0x10 * bank)); > > My eyes bleed by now. I will modify the some input in intc1.c Thanks your review. > > Thanks, > > tglx ^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support 2026-02-07 3:50 ` Ryan Chen @ 2026-02-07 12:40 ` Thomas Gleixner 2026-02-08 2:27 ` Ryan Chen 0 siblings, 1 reply; 20+ messages in thread From: Thomas Gleixner @ 2026-02-07 12:40 UTC (permalink / raw) To: Ryan Chen, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-aspeed@lists.ozlabs.org, linux-riscv@lists.infradead.org On Sat, Feb 07 2026 at 03:50, Ryan Chen wrote: >> -----Original Message----- >> From: Thomas Gleixner <tglx@linutronix.de> >> Sent: Friday, February 6, 2026 7:34 PM >> To: Ryan Chen <ryan_chen@aspeedtech.com>; Rob Herring <robh@kernel.org>; >> Krzysztof Kozlowski <krzk+dt@kernel.org>; Conor Dooley >> <conor+dt@kernel.org>; Joel Stanley <joel@jms.id.au>; Andrew Jeffery >> <andrew@codeconstruct.com.au>; Paul Walmsley <pjw@kernel.org>; Palmer >> Dabbelt <palmer@dabbelt.com>; Albert Ou <aou@eecs.berkeley.edu>; >> Alexandre Ghiti <alex@ghiti.fr> >> Cc: linux-kernel@vger.kernel.org; devicetree@vger.kernel.org; >> linux-arm-kernel@lists.infradead.org; linux-aspeed@lists.ozlabs.org; >> linux-riscv@lists.infradead.org; Ryan Chen <ryan_chen@aspeedtech.com> >> Subject: Re: [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 >> support Please fix your email client to not copy all mail headers. If you can't fix it, remove them manually and replace it with the usual: On Fri, Feb 06 2026 at ...., Thomas Gleixner wrote: >> > + guard(raw_spinlock_irqsave)(&intc0->intc_lock); >> >> s/_irqsave// Interrupts are disabled when this is invoked. > Sorry, do you mean when this function been call. > Ther have desc->lock to do the raw_spin_lock_irqsave. The core always holds irq_desc::lock with interrupts disabled when it invokes those irqchip callbacks. So trying to disable interrupts in them again is a pointless exercise. ^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support 2026-02-07 12:40 ` Thomas Gleixner @ 2026-02-08 2:27 ` Ryan Chen 0 siblings, 0 replies; 20+ messages in thread From: Ryan Chen @ 2026-02-08 2:27 UTC (permalink / raw) To: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-aspeed@lists.ozlabs.org, linux-riscv@lists.infradead.org > Subject: RE: [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 > support > > On Sat, Feb 07 2026 at 03:50, Ryan Chen wrote: > >> -----Original Message----- > >> From: Thomas Gleixner <tglx@linutronix.de> > >> Sent: Friday, February 6, 2026 7:34 PM > >> To: Ryan Chen <ryan_chen@aspeedtech.com>; Rob Herring > >> <robh@kernel.org>; Krzysztof Kozlowski <krzk+dt@kernel.org>; Conor > >> Dooley <conor+dt@kernel.org>; Joel Stanley <joel@jms.id.au>; Andrew > >> Jeffery <andrew@codeconstruct.com.au>; Paul Walmsley > >> <pjw@kernel.org>; Palmer Dabbelt <palmer@dabbelt.com>; Albert Ou > >> <aou@eecs.berkeley.edu>; Alexandre Ghiti <alex@ghiti.fr> > >> Cc: linux-kernel@vger.kernel.org; devicetree@vger.kernel.org; > >> linux-arm-kernel@lists.infradead.org; linux-aspeed@lists.ozlabs.org; > >> linux-riscv@lists.infradead.org; Ryan Chen <ryan_chen@aspeedtech.com> > >> Subject: Re: [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 > >> INTC0/INTC1 support > > Please fix your email client to not copy all mail headers. If you can't fix it, > remove them manually and replace it with the usual: Sorry, This is my mistake. > > On Fri, Feb 06 2026 at ...., Thomas Gleixner wrote: > >> > + guard(raw_spinlock_irqsave)(&intc0->intc_lock); > >> > >> s/_irqsave// Interrupts are disabled when this is invoked. > > Sorry, do you mean when this function been call. > > Ther have desc->lock to do the raw_spin_lock_irqsave. > > The core always holds irq_desc::lock with interrupts disabled when it invokes > those irqchip callbacks. So trying to disable interrupts in them again is a > pointless exercise. > Thanks your gyudabce , understood. ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 3/4] irqchip/aspeed: Remove legacy AST2700 interrupt controller driver 2026-02-05 6:07 [PATCH 0/4] Add AST2700 INTC0/INTC1 support Ryan Chen 2026-02-05 6:07 ` [PATCH 1/4] dt-bindings: interrupt-controller: aspeed: Add ASPEED AST2700 INTC0/INTC1 Ryan Chen 2026-02-05 6:07 ` [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support Ryan Chen @ 2026-02-05 6:07 ` Ryan Chen 2026-02-05 6:07 ` [PATCH 4/4] dt-bindings: interrupt-controller: aspeed: Remove legacy AST2700 interrupt binding Ryan Chen 2026-02-05 8:58 ` [PATCH 0/4] Add AST2700 INTC0/INTC1 support Krzysztof Kozlowski 4 siblings, 0 replies; 20+ messages in thread From: Ryan Chen @ 2026-02-05 6:07 UTC (permalink / raw) To: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti Cc: linux-kernel, devicetree, linux-arm-kernel, linux-aspeed, linux-riscv, Ryan Chen The legacy driver was designed around a PSP-centric interrupt model and cannot describe the full routing and protection capabilities of the AST2700 interrupt architecture. This driver is superseded by the new AST2700 INTC0/INTC1 drivers, which provide a unified, block-level description suitable for all integrated processors. There are no known upstream users of the legacy aspeed,ast2700-intc-ic compatible. Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com> --- drivers/irqchip/Makefile | 1 - drivers/irqchip/irq-aspeed-intc.c | 139 -------------------------------------- 2 files changed, 140 deletions(-) diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 51fdf269e436..ed547e90ae89 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -90,7 +90,6 @@ obj-$(CONFIG_LS_EXTIRQ) += irq-ls-extirq.o obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o obj-$(CONFIG_ASPEED_AST2700_INTC) += irq-ast2700.o irq-ast2700-intc0.o irq-ast2700-intc1.o obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o irq-aspeed-scu-ic.o -obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-intc.o obj-$(CONFIG_STM32MP_EXTI) += irq-stm32mp-exti.o obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o obj-$(CONFIG_QCOM_IRQ_COMBINER) += qcom-irq-combiner.o diff --git a/drivers/irqchip/irq-aspeed-intc.c b/drivers/irqchip/irq-aspeed-intc.c deleted file mode 100644 index 8330221799a0..000000000000 --- a/drivers/irqchip/irq-aspeed-intc.c +++ /dev/null @@ -1,139 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Aspeed Interrupt Controller. - * - * Copyright (C) 2023 ASPEED Technology Inc. - */ - -#include <linux/bitops.h> -#include <linux/irq.h> -#include <linux/irqchip.h> -#include <linux/irqchip/chained_irq.h> -#include <linux/irqdomain.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> -#include <linux/io.h> -#include <linux/spinlock.h> - -#define INTC_INT_ENABLE_REG 0x00 -#define INTC_INT_STATUS_REG 0x04 -#define INTC_IRQS_PER_WORD 32 - -struct aspeed_intc_ic { - void __iomem *base; - raw_spinlock_t gic_lock; - raw_spinlock_t intc_lock; - struct irq_domain *irq_domain; -}; - -static void aspeed_intc_ic_irq_handler(struct irq_desc *desc) -{ - struct aspeed_intc_ic *intc_ic = irq_desc_get_handler_data(desc); - struct irq_chip *chip = irq_desc_get_chip(desc); - - chained_irq_enter(chip, desc); - - scoped_guard(raw_spinlock, &intc_ic->gic_lock) { - unsigned long bit, status; - - status = readl(intc_ic->base + INTC_INT_STATUS_REG); - for_each_set_bit(bit, &status, INTC_IRQS_PER_WORD) { - generic_handle_domain_irq(intc_ic->irq_domain, bit); - writel(BIT(bit), intc_ic->base + INTC_INT_STATUS_REG); - } - } - - chained_irq_exit(chip, desc); -} - -static void aspeed_intc_irq_mask(struct irq_data *data) -{ - struct aspeed_intc_ic *intc_ic = irq_data_get_irq_chip_data(data); - unsigned int mask = readl(intc_ic->base + INTC_INT_ENABLE_REG) & ~BIT(data->hwirq); - - guard(raw_spinlock)(&intc_ic->intc_lock); - writel(mask, intc_ic->base + INTC_INT_ENABLE_REG); -} - -static void aspeed_intc_irq_unmask(struct irq_data *data) -{ - struct aspeed_intc_ic *intc_ic = irq_data_get_irq_chip_data(data); - unsigned int unmask = readl(intc_ic->base + INTC_INT_ENABLE_REG) | BIT(data->hwirq); - - guard(raw_spinlock)(&intc_ic->intc_lock); - writel(unmask, intc_ic->base + INTC_INT_ENABLE_REG); -} - -static struct irq_chip aspeed_intc_chip = { - .name = "ASPEED INTC", - .irq_mask = aspeed_intc_irq_mask, - .irq_unmask = aspeed_intc_irq_unmask, -}; - -static int aspeed_intc_ic_map_irq_domain(struct irq_domain *domain, unsigned int irq, - irq_hw_number_t hwirq) -{ - irq_set_chip_and_handler(irq, &aspeed_intc_chip, handle_level_irq); - irq_set_chip_data(irq, domain->host_data); - - return 0; -} - -static const struct irq_domain_ops aspeed_intc_ic_irq_domain_ops = { - .map = aspeed_intc_ic_map_irq_domain, -}; - -static int __init aspeed_intc_ic_of_init(struct device_node *node, - struct device_node *parent) -{ - struct aspeed_intc_ic *intc_ic; - int irq, i, ret = 0; - - intc_ic = kzalloc(sizeof(*intc_ic), GFP_KERNEL); - if (!intc_ic) - return -ENOMEM; - - intc_ic->base = of_iomap(node, 0); - if (!intc_ic->base) { - pr_err("Failed to iomap intc_ic base\n"); - ret = -ENOMEM; - goto err_free_ic; - } - writel(0xffffffff, intc_ic->base + INTC_INT_STATUS_REG); - writel(0x0, intc_ic->base + INTC_INT_ENABLE_REG); - - intc_ic->irq_domain = irq_domain_create_linear(of_fwnode_handle(node), INTC_IRQS_PER_WORD, - &aspeed_intc_ic_irq_domain_ops, intc_ic); - if (!intc_ic->irq_domain) { - ret = -ENOMEM; - goto err_iounmap; - } - - raw_spin_lock_init(&intc_ic->gic_lock); - raw_spin_lock_init(&intc_ic->intc_lock); - - /* Check all the irq numbers valid. If not, unmaps all the base and frees the data. */ - for (i = 0; i < of_irq_count(node); i++) { - irq = irq_of_parse_and_map(node, i); - if (!irq) { - pr_err("Failed to get irq number\n"); - ret = -EINVAL; - goto err_iounmap; - } - } - - for (i = 0; i < of_irq_count(node); i++) { - irq = irq_of_parse_and_map(node, i); - irq_set_chained_handler_and_data(irq, aspeed_intc_ic_irq_handler, intc_ic); - } - - return 0; - -err_iounmap: - iounmap(intc_ic->base); -err_free_ic: - kfree(intc_ic); - return ret; -} - -IRQCHIP_DECLARE(ast2700_intc_ic, "aspeed,ast2700-intc-ic", aspeed_intc_ic_of_init); -- 2.34.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 4/4] dt-bindings: interrupt-controller: aspeed: Remove legacy AST2700 interrupt binding 2026-02-05 6:07 [PATCH 0/4] Add AST2700 INTC0/INTC1 support Ryan Chen ` (2 preceding siblings ...) 2026-02-05 6:07 ` [PATCH 3/4] irqchip/aspeed: Remove legacy AST2700 interrupt controller driver Ryan Chen @ 2026-02-05 6:07 ` Ryan Chen 2026-02-05 8:56 ` Krzysztof Kozlowski 2026-02-05 8:58 ` [PATCH 0/4] Add AST2700 INTC0/INTC1 support Krzysztof Kozlowski 4 siblings, 1 reply; 20+ messages in thread From: Ryan Chen @ 2026-02-05 6:07 UTC (permalink / raw) To: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti Cc: linux-kernel, devicetree, linux-arm-kernel, linux-aspeed, linux-riscv, Ryan Chen Remove the legacy AST2700 interrupt controller Devicetree binding. The legacy binding was limited to a PSP-centric view of the interrupt architecture and cannot describe interrupt routing and protection for the full AST2700 system. It is superseded by the new ASPEED AST2700 INTC0/INTC1 binding, which describes the interrupt controllers at the block-function level. There are no known upstream users of the removed binding. Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com> --- .../interrupt-controller/aspeed,ast2700-intc.yaml | 90 ---------------------- 1 file changed, 90 deletions(-) diff --git a/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2700-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2700-intc.yaml deleted file mode 100644 index 258d21fe6e35..000000000000 --- a/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2700-intc.yaml +++ /dev/null @@ -1,90 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/interrupt-controller/aspeed,ast2700-intc.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Aspeed AST2700 Interrupt Controller - -description: - This interrupt controller hardware is second level interrupt controller that - is hooked to a parent interrupt controller. It's useful to combine multiple - interrupt sources into 1 interrupt to parent interrupt controller. - -maintainers: - - Kevin Chen <kevin_chen@aspeedtech.com> - -properties: - compatible: - enum: - - aspeed,ast2700-intc-ic - - reg: - maxItems: 1 - - interrupt-controller: true - - '#interrupt-cells': - const: 1 - description: - The first cell is the IRQ number, the second cell is the trigger - type as defined in interrupt.txt in this directory. - - interrupts: - minItems: 1 - maxItems: 10 - description: | - Depend to which INTC0 or INTC1 used. - INTC0 and INTC1 are two kinds of interrupt controller with enable and raw - status registers for use. - INTC0 is used to assert GIC if interrupt in INTC1 asserted. - INTC1 is used to assert INTC0 if interrupt of modules asserted. - +-----+ +-------+ +---------+---module0 - | GIC |---| INTC0 |--+--| INTC1_0 |---module2 - | | | | | | |---... - +-----+ +-------+ | +---------+---module31 - | - | +---------+---module0 - +---| INTC1_1 |---module2 - | | |---... - | +---------+---module31 - ... - | +---------+---module0 - +---| INTC1_5 |---module2 - | |---... - +---------+---module31 - -required: - - compatible - - reg - - interrupt-controller - - '#interrupt-cells' - - interrupts - -additionalProperties: false - -examples: - - | - #include <dt-bindings/interrupt-controller/arm-gic.h> - - bus { - #address-cells = <2>; - #size-cells = <2>; - - interrupt-controller@12101b00 { - compatible = "aspeed,ast2700-intc-ic"; - reg = <0 0x12101b00 0 0x10>; - #interrupt-cells = <1>; - interrupt-controller; - interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>; - }; - }; -- 2.34.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 4/4] dt-bindings: interrupt-controller: aspeed: Remove legacy AST2700 interrupt binding 2026-02-05 6:07 ` [PATCH 4/4] dt-bindings: interrupt-controller: aspeed: Remove legacy AST2700 interrupt binding Ryan Chen @ 2026-02-05 8:56 ` Krzysztof Kozlowski 0 siblings, 0 replies; 20+ messages in thread From: Krzysztof Kozlowski @ 2026-02-05 8:56 UTC (permalink / raw) To: Ryan Chen Cc: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, linux-kernel, devicetree, linux-arm-kernel, linux-aspeed, linux-riscv On Thu, Feb 05, 2026 at 02:07:22PM +0800, Ryan Chen wrote: > Remove the legacy AST2700 interrupt controller Devicetree binding. > > The legacy binding was limited to a PSP-centric view of the interrupt > architecture and cannot describe interrupt routing and protection for > the full AST2700 system. > > It is superseded by the new ASPEED AST2700 INTC0/INTC1 binding, which > describes the interrupt controllers at the block-function level. You just added all this ~year ago. I also do not understand how multiple previous revisions of patchset [1] were just ignored. No versioning, no references. This is either unprofessional or just wasting our time. [1] https://lore.kernel.org/all/20251030060155.2342604-1-ryan_chen@aspeedtech.com/ Best regards, Krzysztof ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 0/4] Add AST2700 INTC0/INTC1 support 2026-02-05 6:07 [PATCH 0/4] Add AST2700 INTC0/INTC1 support Ryan Chen ` (3 preceding siblings ...) 2026-02-05 6:07 ` [PATCH 4/4] dt-bindings: interrupt-controller: aspeed: Remove legacy AST2700 interrupt binding Ryan Chen @ 2026-02-05 8:58 ` Krzysztof Kozlowski 2026-02-05 9:49 ` Ryan Chen 4 siblings, 1 reply; 20+ messages in thread From: Krzysztof Kozlowski @ 2026-02-05 8:58 UTC (permalink / raw) To: Ryan Chen Cc: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, linux-kernel, devicetree, linux-arm-kernel, linux-aspeed, linux-riscv On Thu, Feb 05, 2026 at 02:07:18PM +0800, Ryan Chen wrote: > This series replaces the existing AST2700 interrupt controller binding > and driver. The original implementation was focused on a narrow, > PSP-centric view and could not fully describe the complexity of the > AST2700 interrupt fabric: > > * It was focused primarily on the perspective of the Primary Service > Processor (PSP). > * It could not handle interrupt route configuration. > * It could not handle interrupt register protection. > > By contrast, the new bindings and drivers describe the interrupt > controllers at the block-function level and provide a unified binding > design that can be used from the perspective of any of the four > integrated processors (the Primary, Secondary and Tertiary Service > Processors, and the Boot MCU): Where and how did you address last feedback given to you here: https://lore.kernel.org/all/20250814-auspicious-thundering-jaybird-b76f4f@kuoka/ "This binding is not improving. You are not responding to REAL problems described to you. What's more, you send it in a way making our life difficult, look:" So how did you make our life easier now? Best regards, Krzysztof ^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH 0/4] Add AST2700 INTC0/INTC1 support 2026-02-05 8:58 ` [PATCH 0/4] Add AST2700 INTC0/INTC1 support Krzysztof Kozlowski @ 2026-02-05 9:49 ` Ryan Chen 2026-02-05 9:56 ` Krzysztof Kozlowski 0 siblings, 1 reply; 20+ messages in thread From: Ryan Chen @ 2026-02-05 9:49 UTC (permalink / raw) To: Krzysztof Kozlowski Cc: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-aspeed@lists.ozlabs.org, linux-riscv@lists.infradead.org > Subject: Re: [PATCH 0/4] Add AST2700 INTC0/INTC1 support > > On Thu, Feb 05, 2026 at 02:07:18PM +0800, Ryan Chen wrote: > > This series replaces the existing AST2700 interrupt controller binding > > and driver. The original implementation was focused on a narrow, > > PSP-centric view and could not fully describe the complexity of the > > AST2700 interrupt fabric: > > > > * It was focused primarily on the perspective of the Primary Service > > Processor (PSP). > > * It could not handle interrupt route configuration. > > * It could not handle interrupt register protection. > > > > By contrast, the new bindings and drivers describe the interrupt > > controllers at the block-function level and provide a unified binding > > design that can be used from the perspective of any of the four > > integrated processors (the Primary, Secondary and Tertiary Service > > Processors, and the Boot MCU): > > Where and how did you address last feedback given to you here: > > https://lore.kernel.org/all/20250814-auspicious-thundering-jaybird-b76f4f@ku > oka/ > > "This binding is not improving. You are not responding to REAL problems > described to you. What's more, you send it in a way making our life difficult, > look:" > > So how did you make our life easier now? > Hi Krzysztof, Thanks for your feedback. The series you commented on in Aug 2025 (v4 1/2) attempted to model The hardware by introducing parent compatibles (aspeed,ast2700-intc0 / aspeed,ast2700-intc1) with child "interrupt-controller@" nodes using aspeed,ast2700-intc-ic. In hindsight, that approach did not align well with the actual hardware structure and resulted in inconsistencies between the diagrams, the schema, and the register layout (including unit-address issues). It was also difficult to review in isolation. This series addresses that feedback by changing the approach entirely: First, the artificial parent/child split has been removed. The new binding exposes only the two interrupt controller designs that exist in hardware, INTC0 and INTC1. There are no intermediate interrupt-controller child nodes introduced for grouping or driver convenience. Second, the role of aspeed,interrupt-ranges has been clarified and narrowed. The property now describes only the fixed hardware connections between interrupt controllers (i.e. post-routing connectivity), rather than attempting to encode routing policy in the devicetree. Route selection itself is implemented in the INTC0 driver, based on information such as the interrupt-parent of the running firmware environment. Finally, to make the intent explicit and easier to review, this series: the new binding and drivers are added first, and the legacy binding and driver are removed in the same series. In short, the earlier parent/child model—which did not correspond cleanly to hardware resource boundaries—has been dropped entirely, and the binding now directly reflects the hardware blocks present in the AST2700. Best regards, Ryan ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 0/4] Add AST2700 INTC0/INTC1 support 2026-02-05 9:49 ` Ryan Chen @ 2026-02-05 9:56 ` Krzysztof Kozlowski 2026-02-06 7:19 ` Andrew Jeffery 0 siblings, 1 reply; 20+ messages in thread From: Krzysztof Kozlowski @ 2026-02-05 9:56 UTC (permalink / raw) To: Ryan Chen Cc: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-aspeed@lists.ozlabs.org, linux-riscv@lists.infradead.org On 05/02/2026 10:49, Ryan Chen wrote: > >> Subject: Re: [PATCH 0/4] Add AST2700 INTC0/INTC1 support >> >> On Thu, Feb 05, 2026 at 02:07:18PM +0800, Ryan Chen wrote: >>> This series replaces the existing AST2700 interrupt controller binding >>> and driver. The original implementation was focused on a narrow, >>> PSP-centric view and could not fully describe the complexity of the >>> AST2700 interrupt fabric: >>> >>> * It was focused primarily on the perspective of the Primary Service >>> Processor (PSP). >>> * It could not handle interrupt route configuration. >>> * It could not handle interrupt register protection. >>> >>> By contrast, the new bindings and drivers describe the interrupt >>> controllers at the block-function level and provide a unified binding >>> design that can be used from the perspective of any of the four >>> integrated processors (the Primary, Secondary and Tertiary Service >>> Processors, and the Boot MCU): >> >> Where and how did you address last feedback given to you here: >> >> https://lore.kernel.org/all/20250814-auspicious-thundering-jaybird-b76f4f@ku >> oka/ >> >> "This binding is not improving. You are not responding to REAL problems >> described to you. What's more, you send it in a way making our life difficult, >> look:" >> >> So how did you make our life easier now? >> > Hi Krzysztof, > > Thanks for your feedback. > > The series you commented on in Aug 2025 (v4 1/2) attempted to model > The hardware by introducing parent compatibles (aspeed,ast2700-intc0 / > aspeed,ast2700-intc1) with child "interrupt-controller@" nodes using > aspeed,ast2700-intc-ic. In hindsight, that approach did not align well > with the actual hardware structure and resulted in inconsistencies > between the diagrams, the schema, and the register layout (including > unit-address issues). It was also difficult to review in isolation. Read my question again: "So how did you make our life easier now?" And then read the earlier comment - what I expected of you. Please answer these after the "look:" part. Answer these please. I am not going to review any of these because you keep ignoring our process of handling patches and not really responding to review comments. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 0/4] Add AST2700 INTC0/INTC1 support 2026-02-05 9:56 ` Krzysztof Kozlowski @ 2026-02-06 7:19 ` Andrew Jeffery 2026-02-10 7:25 ` Andrew Jeffery 0 siblings, 1 reply; 20+ messages in thread From: Andrew Jeffery @ 2026-02-06 7:19 UTC (permalink / raw) To: Krzysztof Kozlowski, Ryan Chen Cc: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-aspeed@lists.ozlabs.org, linux-riscv@lists.infradead.org, Jeremy Kerr Hi Krzysztof, I've been working with Ryan to address what I considered some shortcomings of the original approach. For reference, I outlined my concerns on v4 of the previous series[1]. [1]: https://lore.kernel.org/all/1a2ca78746e00c2ec4bfc2953a897c48376ed36f.camel@codeconstruct.com.au/ That reply proposed the new DT structure, and this series is a refinement & implementation of those ideas With that context: > On Thu, 2026-02-05 at 10:56 +0100, Krzysztof Kozlowski wrote: > On 05/02/2026 10:49, Ryan Chen wrote: > > > Subject: Re: [PATCH 0/4] Add AST2700 INTC0/INTC1 support > > > > On Thu, Feb 05, 2026 at 02:07:18PM +0800, Ryan Chen wrote: > > > This series replaces the existing AST2700 interrupt controller binding > > > and driver. The original implementation was focused on a narrow, > > > PSP-centric view and could not fully describe the complexity of the > > > AST2700 interrupt fabric: > > > > > > * It was focused primarily on the perspective of the Primary Service > > > > Processor (PSP). > > > * It could not handle interrupt route configuration. > > > * It could not handle interrupt register protection. > > > > > > By contrast, the new bindings and drivers describe the interrupt > > > controllers at the block-function level and provide a unified binding > > > design that can be used from the perspective of any of the four > > > integrated processors (the Primary, Secondary and Tertiary Service > > > Processors, and the Boot MCU): > > > > > > Where and how did you address last feedback given to you here: > > > > > > https://lore.kernel.org/all/20250814-auspicious-thundering-jaybird-b76f4f@ku > > > oka/ At this point the answer is that there wasn't a direct response. I acknowledge that I'm not Ryan, and that it is important that he responds directly to queries on his own patches. However, with the goal of having an upstream binding that better represents the hardware (along with a capable driver), I've pulled the concerns out of your linked feedback for discussion below. > > + +-----+ +---------+ > > + | GIC |---| INTC0 | > > + +-----+ +---------+ > > Same problem as last time. This tells me intc0 has not children... ... > > + +---------+ > > + | | +---------+ > > + | INTC0_11| +---| INTC1 | > > + | | +---------+ > > ...This tells that inc1 has no children (only intc0_11, which you said > is aspeed,ast2700-intc-ic !!!).... > (keep scrolling) ... > > +patternProperties: > > + "^interrupt-controller@": > > ... but this tells me that intc0 and intc1 has children. ... > > + intc0_11: interrupt-controller@1b00 { > > + compatible = "aspeed,ast2700-intc-ic"; > > + reg = <0 0x12101b00 0 0x10>; > > > ... and that's quite wrong unit address. Also no resources in the > parent, so this entire split seems superficial and incorrect. This gets to the heart of it. I share the view that the split was superficial. It tried to recombine existing components to account for some change in hardware design between early revisions of the AST2700 SoC. The original binding from Kevin was too fine-grained. I don't think the design of the diagrams helped the cause for understanding the proposed binding or the hardware architecture, and were misleading in the manner you outlined in the comments above. My reply at [1] above was an (indirect) attempt to address your concerns, though again I acknowledge I'm not Ryan and that review feedback needs direct responses from patch authors. The binding proposed in this series eliminates the subnodes and enables a complete implementation of routing for the hardware, as demonstrated by the proposed drivers. I think it better conforms to the documented DOs and DON'Ts for writing bindings by moving anything implied by the compatible to the driver implementation. I hadn't yet merged the base arch patches for the SoC because I had contentions with the already- accepted binding, and merging the arch patches would make an already difficult job of reversing that acceptance harder again. In essence, this is some pain, but I view it as pain on the path towards better DTS outcomes than we had for prior generations of ASPEED BMC SoCs. > > > > > > "This binding is not improving. You are not responding to REAL problems > > > described to you. What's more, you send it in a way making our life > > > difficult, look:" > > > > > > So how did you make our life easier now? > > > > Hi Krzysztof, > > > > Thanks for your feedback. > > > > The series you commented on in Aug 2025 (v4 1/2) attempted to model > > The hardware by introducing parent compatibles (aspeed,ast2700-intc0 / > > aspeed,ast2700-intc1) with child "interrupt-controller@" nodes using > > aspeed,ast2700-intc-ic. In hindsight, that approach did not align well > > with the actual hardware structure and resulted in inconsistencies > > between the diagrams, the schema, and the register layout (including > > unit-address issues). It was also difficult to review in isolation. > > Read my question again: > > "So how did you make our life easier now?" > > And then read the earlier comment - what I expected of you. Please > answer these after the "look:" part. > > Answer these please. I am not going to review any of these because you > keep ignoring our process of handling patches and not really responding > to review comments. For what it's worth, Ryan has adopted b4 and so hopefully some of the expectations around the mechanics of patch review are less of a concern. In this specific case, because of the divergence in direction, we went with a separate series. The failure to link that earlier series in the cover letter was an unfortunate oversight. I'll take responsibility for that, as part of developing the series with Ryan. Sorry for causing you frustration. Is it acceptable if we take the following actions: 1. Do some b4 magic to transplant this series back onto [1] 2. Send a follow up revision with a link to this discussion in the cover letter Andrew ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 0/4] Add AST2700 INTC0/INTC1 support 2026-02-06 7:19 ` Andrew Jeffery @ 2026-02-10 7:25 ` Andrew Jeffery 2026-02-12 5:58 ` Ryan Chen 0 siblings, 1 reply; 20+ messages in thread From: Andrew Jeffery @ 2026-02-10 7:25 UTC (permalink / raw) To: Krzysztof Kozlowski, Ryan Chen Cc: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-aspeed@lists.ozlabs.org, linux-riscv@lists.infradead.org, Jeremy Kerr Hi Krzysztof, On Fri, 2026-02-06 at 17:49 +1030, Andrew Jeffery wrote: > Is it acceptable if we take the following actions: > > 1. Do some b4 magic to transplant this series back onto [1] > 2. Send a follow up revision with a link to this discussion in the > cover letter Following up my own post, I don't think we should attempt such grafting. [1] references v4. v4 was superseded by v6 at [2], which was merged. Because of that merge, separating this proposal into a new series seems warranted, but has the downside of making it difficult to compare to v4 of that earlier series. I have gone through each of your feedback items from the earlier series to consider recurring issues. Defining a new binding is unfortunate but its addition side-steps an ABI break - perhaps rather than remove the existing binding we can deprecate it, and keep the associated driver (assuming this isn't overkill, given there are no in-tree users). Otherwise it looks to me like the proposal has concerns covered, but let me know if not. Andrew [1]: https://lore.kernel.org/all/1a2ca78746e00c2ec4bfc2953a897c48376ed36f.camel@codeconstruct.com.au/ [2]: https://lore.kernel.org/all/20251030060155.2342604-1-ryan_chen@aspeedtech.com/ ^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH 0/4] Add AST2700 INTC0/INTC1 support 2026-02-10 7:25 ` Andrew Jeffery @ 2026-02-12 5:58 ` Ryan Chen 0 siblings, 0 replies; 20+ messages in thread From: Ryan Chen @ 2026-02-12 5:58 UTC (permalink / raw) To: Andrew Jeffery, Krzysztof Kozlowski Cc: Thomas Gleixner, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-aspeed@lists.ozlabs.org, linux-riscv@lists.infradead.org, Jeremy Kerr > Subject: Re: [PATCH 0/4] Add AST2700 INTC0/INTC1 support > > Hi Krzysztof, > > On Fri, 2026-02-06 at 17:49 +1030, Andrew Jeffery wrote: > > Is it acceptable if we take the following actions: > > > > 1. Do some b4 magic to transplant this series back onto [1] > > 2. Send a follow up revision with a link to this discussion in the > > cover letter > > Following up my own post, I don't think we should attempt such grafting. [1] > references v4. v4 was superseded by v6 at [2], which was merged. > > Because of that merge, separating this proposal into a new series seems > warranted, but has the downside of making it difficult to compare to v4 of that > earlier series. > > I have gone through each of your feedback items from the earlier series to > consider recurring issues. Defining a new binding is unfortunate but its > addition side-steps an ABI break - perhaps rather than remove the existing > binding we can deprecate it, and keep the associated driver (assuming this > isn't overkill, given there are no in-tree users). > Otherwise it looks to me like the proposal has concerns covered, but let me > know if not. > > Andrew > > [1]: > https://lore.kernel.org/all/1a2ca78746e00c2ec4bfc2953a897c48376ed36f.cam > el@codeconstruct.com.au/ > [2]: > https://lore.kernel.org/all/20251030060155.2342604-1-ryan_chen@aspeedtec > h.com/ Hi Krzysztof, First of all, I would like to sincerely apologize for the confusion and extra burden. I recognize that I did not follow the upstream review process carefully enough, which made the series harder to review. I am now working with others to catch problems before sending changes to the lists and align with the community's expectations. Going forward, before sending a new revision, I will ensure that: * All review feedback is addressed explicitly, either through concrete changes or follow-up discussion that resolves the concern. * The series remains structured and traceable using b4. * Relevant tests are run and warnings/errors are addressed prior to posting. * A clearer internal checklist is followed before submission. The current subject line may have made it harder to relate this series to the previous discussion: https://lore.kernel.org/all/20250814-auspicious-thundering-jaybird-b76f4f@kuoka/ To improve clarity and consistency across revisions, I will update the subject for this series to: "AST2700 interrupt controller hierarchy and route support" If you still see process issues, please let me know. I will correct them. Best regards, Ryan ^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2026-02-12 5:58 UTC | newest] Thread overview: 20+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-02-05 6:07 [PATCH 0/4] Add AST2700 INTC0/INTC1 support Ryan Chen 2026-02-05 6:07 ` [PATCH 1/4] dt-bindings: interrupt-controller: aspeed: Add ASPEED AST2700 INTC0/INTC1 Ryan Chen 2026-02-05 7:25 ` Rob Herring (Arm) 2026-02-05 8:53 ` Krzysztof Kozlowski 2026-02-05 6:07 ` [PATCH 2/4] irqchip/ast2700-intcx: Add AST2700 INTC0/INTC1 support Ryan Chen 2026-02-05 14:40 ` kernel test robot 2026-02-05 14:52 ` kernel test robot 2026-02-06 11:34 ` Thomas Gleixner 2026-02-07 3:50 ` Ryan Chen 2026-02-07 12:40 ` Thomas Gleixner 2026-02-08 2:27 ` Ryan Chen 2026-02-05 6:07 ` [PATCH 3/4] irqchip/aspeed: Remove legacy AST2700 interrupt controller driver Ryan Chen 2026-02-05 6:07 ` [PATCH 4/4] dt-bindings: interrupt-controller: aspeed: Remove legacy AST2700 interrupt binding Ryan Chen 2026-02-05 8:56 ` Krzysztof Kozlowski 2026-02-05 8:58 ` [PATCH 0/4] Add AST2700 INTC0/INTC1 support Krzysztof Kozlowski 2026-02-05 9:49 ` Ryan Chen 2026-02-05 9:56 ` Krzysztof Kozlowski 2026-02-06 7:19 ` Andrew Jeffery 2026-02-10 7:25 ` Andrew Jeffery 2026-02-12 5:58 ` Ryan Chen
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox