* [PATCH v2 1/4] dt-bindings: interrupt-controller: Add Aspeed SCU interrupt controller
2019-09-27 20:58 [PATCH v2 0/4] irqchip: Add Aspeed SCU Interrupt Controller Eddie James
@ 2019-09-27 20:58 ` Eddie James
2019-10-11 14:33 ` Rob Herring
2019-09-27 20:58 ` [PATCH v2 2/4] irqchip: " Eddie James
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Eddie James @ 2019-09-27 20:58 UTC (permalink / raw)
To: linux-kernel
Cc: devicetree, linux-aspeed, andrew, joel, mark.rutland, robh+dt,
maz, jason, tglx, Eddie James
Document the Aspeed SCU interrupt controller and add an include file
for the interrupts it provides.
Signed-off-by: Eddie James <eajames@linux.ibm.com>
---
.../interrupt-controller/aspeed,ast2xxx-scu-ic.txt | 26 ++++++++++++++++++++++
MAINTAINERS | 7 ++++++
.../interrupt-controller/aspeed-scu-ic.h | 23 +++++++++++++++++++
3 files changed, 56 insertions(+)
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2xxx-scu-ic.txt
create mode 100644 include/dt-bindings/interrupt-controller/aspeed-scu-ic.h
diff --git a/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2xxx-scu-ic.txt b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2xxx-scu-ic.txt
new file mode 100644
index 0000000..baa3780
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2xxx-scu-ic.txt
@@ -0,0 +1,26 @@
+Aspeed AST25XX and AST26XX SCU Interrupt Controller
+
+Required Properties:
+ - #interrupt-cells : must be 1
+ - compatible : must be "aspeed,ast2500-scu-ic",
+ "aspeed,ast2600-scu-ic0" or
+ "aspeed,ast2600-scu-ic1"
+ - reg : address and size of the SCU register
+ associated with the controller
+ - interrupts : interrupt from the parent controller
+ - interrupt-controller : indicates that the controlle receives and
+ fires new interrupts for child busses
+
+Example:
+
+ syscon@1e6e2000 {
+ ranges = <0 0x1e6e2000 0x1a8>;
+
+ scu_ic: interrupt-controller@18 {
+ #interrupt-cells = <1>;
+ compatible = "aspeed,ast2500-scu-ic";
+ reg = <0x18 0x04>;
+ interrupts = <21>;
+ interrupt-controller;
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 7ce3c95..c7e028c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2651,6 +2651,13 @@ S: Maintained
F: drivers/pinctrl/aspeed/
F: Documentation/devicetree/bindings/pinctrl/aspeed,*
+ASPEED SCU INTERRUPT CONTROLLER DRIVER
+M: Eddie James <eajames@linux.ibm.com>
+L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
+S: Maintained
+F: Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2xxx-scu-ic.txt
+F: include/dt-bindings/interrupt-controller/aspeed-scu-ic.h
+
ASPEED VIDEO ENGINE DRIVER
M: Eddie James <eajames@linux.ibm.com>
L: linux-media@vger.kernel.org
diff --git a/include/dt-bindings/interrupt-controller/aspeed-scu-ic.h b/include/dt-bindings/interrupt-controller/aspeed-scu-ic.h
new file mode 100644
index 0000000..f315d5a
--- /dev/null
+++ b/include/dt-bindings/interrupt-controller/aspeed-scu-ic.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_ASPEED_SCU_IC_H_
+#define _DT_BINDINGS_INTERRUPT_CONTROLLER_ASPEED_SCU_IC_H_
+
+#define ASPEED_SCU_IC_VGA_CURSOR_CHANGE 0
+#define ASPEED_SCU_IC_VGA_SCRATCH_REG_CHANGE 1
+
+#define ASPEED_AST2500_SCU_IC_PCIE_RESET_LO_TO_HI 2
+#define ASPEED_AST2500_SCU_IC_PCIE_RESET_HI_TO_LO 3
+#define ASPEED_AST2500_SCU_IC_LPC_RESET_LO_TO_HI 4
+#define ASPEED_AST2500_SCU_IC_LPC_RESET_HI_TO_LO 5
+#define ASPEED_AST2500_SCU_IC_ISSUE_MSI 6
+
+#define ASPEED_AST2600_SCU_IC0_PCIE_PERST_LO_TO_HI 2
+#define ASPEED_AST2600_SCU_IC0_PCIE_PERST_HI_TO_LO 3
+#define ASPEED_AST2600_SCU_IC0_PCIE_RCRST_LO_TO_HI 4
+#define ASPEED_AST2600_SCU_IC0_PCIE_RCRST_HI_TO_LO 5
+
+#define ASPEED_AST2600_SCU_IC1_LPC_RESET_LO_TO_HI 0
+#define ASPEED_AST2600_SCU_IC1_LPC_RESET_HI_TO_LO 1
+
+#endif /* _DT_BINDINGS_INTERRUPT_CONTROLLER_ASPEED_SCU_IC_H_ */
--
1.8.3.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 2/4] irqchip: Add Aspeed SCU interrupt controller
2019-09-27 20:58 [PATCH v2 0/4] irqchip: Add Aspeed SCU Interrupt Controller Eddie James
2019-09-27 20:58 ` [PATCH v2 1/4] dt-bindings: interrupt-controller: Add Aspeed SCU interrupt controller Eddie James
@ 2019-09-27 20:58 ` Eddie James
2019-12-03 1:49 ` Andrew Jeffery
2019-09-27 20:58 ` [PATCH v2 3/4] ARM: dts: aspeed: ast2500: Add " Eddie James
2019-09-27 20:58 ` [PATCH v2 4/4] ARM: dts: aspeed: ast2600: Add SCU interrupt controllers Eddie James
3 siblings, 1 reply; 8+ messages in thread
From: Eddie James @ 2019-09-27 20:58 UTC (permalink / raw)
To: linux-kernel
Cc: devicetree, linux-aspeed, andrew, joel, mark.rutland, robh+dt,
maz, jason, tglx, Eddie James
The Aspeed SOCs provide some interrupts through the System Control
Unit registers. Add an interrupt controller that provides these
interrupts to the system.
Signed-off-by: Eddie James <eajames@linux.ibm.com>
---
Changes since v1:
- add a spinlock to protect read-modify-write operation for irq masking
- use readl/writel relaxed versions
- add a comment explaining the irq status/enable register
- provide affinity callback that returns -EINVAL
MAINTAINERS | 1 +
drivers/irqchip/Makefile | 2 +-
drivers/irqchip/irq-aspeed-scu-ic.c | 233 ++++++++++++++++++++++++++++++++++++
3 files changed, 235 insertions(+), 1 deletion(-)
create mode 100644 drivers/irqchip/irq-aspeed-scu-ic.c
diff --git a/MAINTAINERS b/MAINTAINERS
index c7e028c..b6db122 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2656,6 +2656,7 @@ M: Eddie James <eajames@linux.ibm.com>
L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2xxx-scu-ic.txt
+F: drivers/irqchip/irq-aspeed-scu-ic.c
F: include/dt-bindings/interrupt-controller/aspeed-scu-ic.h
ASPEED VIDEO ENGINE DRIVER
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index cc7c439..fce6b1d 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -86,7 +86,7 @@ obj-$(CONFIG_MVEBU_PIC) += irq-mvebu-pic.o
obj-$(CONFIG_MVEBU_SEI) += irq-mvebu-sei.o
obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o
obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o
-obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o
+obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o irq-aspeed-scu-ic.o
obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o
obj-$(CONFIG_QCOM_IRQ_COMBINER) += qcom-irq-combiner.o
obj-$(CONFIG_IRQ_UNIPHIER_AIDET) += irq-uniphier-aidet.o
diff --git a/drivers/irqchip/irq-aspeed-scu-ic.c b/drivers/irqchip/irq-aspeed-scu-ic.c
new file mode 100644
index 0000000..64c3ac4
--- /dev/null
+++ b/drivers/irqchip/irq-aspeed-scu-ic.c
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Aspeed AST24XX, AST25XX, and AST26XX SCU Interrupt Controller
+ * Copyright 2019 IBM Corporation
+ *
+ * Eddie James <eajames@linux.ibm.com>
+ */
+
+#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 ASPEED_SCU_IC_SHIFT 0
+#define ASPEED_SCU_IC_ENABLE GENMASK(6, ASPEED_SCU_IC_SHIFT)
+#define ASPEED_SCU_IC_NUM_IRQS 7
+#define ASPEED_SCU_IC_STATUS_SHIFT 16
+
+#define ASPEED_AST2600_SCU_IC0_SHIFT 0
+#define ASPEED_AST2600_SCU_IC0_ENABLE \
+ GENMASK(5, ASPEED_AST2600_SCU_IC0_SHIFT)
+#define ASPEED_AST2600_SCU_IC0_NUM_IRQS 6
+
+#define ASPEED_AST2600_SCU_IC1_SHIFT 4
+#define ASPEED_AST2600_SCU_IC1_ENABLE \
+ GENMASK(5, ASPEED_AST2600_SCU_IC1_SHIFT)
+#define ASPEED_AST2600_SCU_IC1_NUM_IRQS 2
+
+struct aspeed_scu_ic {
+ unsigned long irq_enable;
+ unsigned long irq_shift;
+ unsigned int num_irqs;
+ void __iomem *reg;
+ struct irq_domain *irq_domain;
+ spinlock_t lock;
+};
+
+static void aspeed_scu_ic_irq_handler(struct irq_desc *desc)
+{
+ unsigned int irq;
+ unsigned long bit;
+ unsigned long enabled;
+ unsigned long max;
+ unsigned long status;
+ struct aspeed_scu_ic *scu_ic = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+
+ chained_irq_enter(chip, desc);
+
+ /*
+ * The SCU IC has just one register to control its operation and read
+ * status. The interrupt enable bits occupy the lower 16 bits of the
+ * register, while the interrupt status bits occupy the upper 16 bits.
+ * The status bit for a given interrupt is always 16 bits shifted from
+ * the enable bit for the same interrupt.
+ * Therefore, perform the IRQ operations in the enable bit space by
+ * shifting the status down to get the mapping and then back up to
+ * clear the bit.
+ */
+ status = readl_relaxed(scu_ic->reg);
+ enabled = status & scu_ic->irq_enable;
+ status = (status >> ASPEED_SCU_IC_STATUS_SHIFT) & enabled;
+
+ bit = scu_ic->irq_shift;
+ max = scu_ic->num_irqs + bit;
+
+ for_each_set_bit_from(bit, &status, max) {
+ irq = irq_find_mapping(scu_ic->irq_domain,
+ bit - scu_ic->irq_shift);
+ generic_handle_irq(irq);
+
+ writel_relaxed(enabled | BIT(bit + ASPEED_SCU_IC_STATUS_SHIFT),
+ scu_ic->reg);
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void aspeed_scu_ic_irq_mask(struct irq_data *data)
+{
+ struct aspeed_scu_ic *scu_ic = irq_data_get_irq_chip_data(data);
+ unsigned long bit = BIT(data->hwirq + scu_ic->irq_shift);
+ unsigned long flags;
+ unsigned long reg;
+
+ spin_lock_irqsave(&scu_ic->lock, flags);
+
+ reg = readl_relaxed(scu_ic->reg);
+ writel_relaxed((reg & ~bit) & scu_ic->irq_enable, scu_ic->reg);
+
+ spin_unlock_irqrestore(&scu_ic->lock, flags);
+}
+
+static void aspeed_scu_ic_irq_unmask(struct irq_data *data)
+{
+ struct aspeed_scu_ic *scu_ic = irq_data_get_irq_chip_data(data);
+ unsigned long bit = BIT(data->hwirq + scu_ic->irq_shift);
+ unsigned long flags;
+ unsigned long reg;
+
+ spin_lock_irqsave(&scu_ic->lock, flags);
+
+ reg = readl_relaxed(scu_ic->reg);
+ writel_relaxed((reg | bit) & scu_ic->irq_enable, scu_ic->reg);
+
+ spin_unlock_irqrestore(&scu_ic->lock, flags);
+}
+
+static int aspeed_scu_ic_irq_set_affinity(struct irq_data *data,
+ const struct cpumask *dest,
+ bool force)
+{
+ return -EINVAL;
+}
+
+struct irq_chip aspeed_scu_ic_chip = {
+ .name = "aspeed-scu-ic",
+ .irq_mask = aspeed_scu_ic_irq_mask,
+ .irq_unmask = aspeed_scu_ic_irq_unmask,
+ .irq_set_affinity = aspeed_scu_ic_irq_set_affinity,
+};
+
+static int aspeed_scu_ic_map(struct irq_domain *domain, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ irq_set_chip_and_handler(irq, &aspeed_scu_ic_chip, handle_simple_irq);
+ irq_set_chip_data(irq, domain->host_data);
+
+ return 0;
+}
+
+static const struct irq_domain_ops aspeed_scu_ic_domain_ops = {
+ .map = aspeed_scu_ic_map,
+};
+
+static int aspeed_scu_ic_of_init_common(struct aspeed_scu_ic *scu_ic,
+ struct device_node *node)
+{
+ int irq;
+ int rc = 0;
+
+ scu_ic->reg = of_iomap(node, 0);
+ if (!scu_ic->reg) {
+ rc = -ENOMEM;
+ goto err_free;
+ }
+
+ irq = irq_of_parse_and_map(node, 0);
+ if (irq < 0) {
+ rc = irq;
+ goto err_iounmap;
+ }
+
+ spin_lock_init(&scu_ic->lock);
+
+ scu_ic->irq_domain = irq_domain_add_linear(node, scu_ic->num_irqs,
+ &aspeed_scu_ic_domain_ops,
+ scu_ic);
+ if (!scu_ic->irq_domain) {
+ rc = -ENOMEM;
+ goto err_iounmap;
+ }
+
+ irq_set_chained_handler_and_data(irq, aspeed_scu_ic_irq_handler,
+ scu_ic);
+
+ return 0;
+
+err_iounmap:
+ iounmap(scu_ic->reg);
+
+err_free:
+ kfree(scu_ic);
+
+ return rc;
+}
+
+static int __init aspeed_scu_ic_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct aspeed_scu_ic *scu_ic = kzalloc(sizeof(*scu_ic), GFP_KERNEL);
+
+ if (!scu_ic)
+ return -ENOMEM;
+
+ scu_ic->irq_enable = ASPEED_SCU_IC_ENABLE;
+ scu_ic->irq_shift = ASPEED_SCU_IC_SHIFT;
+ scu_ic->num_irqs = ASPEED_SCU_IC_NUM_IRQS;
+
+ return aspeed_scu_ic_of_init_common(scu_ic, node);
+}
+
+static int __init aspeed_ast2600_scu_ic0_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct aspeed_scu_ic *scu_ic = kzalloc(sizeof(*scu_ic), GFP_KERNEL);
+
+ if (!scu_ic)
+ return -ENOMEM;
+
+ scu_ic->irq_enable = ASPEED_AST2600_SCU_IC0_ENABLE;
+ scu_ic->irq_shift = ASPEED_AST2600_SCU_IC0_SHIFT;
+ scu_ic->num_irqs = ASPEED_AST2600_SCU_IC0_NUM_IRQS;
+
+ return aspeed_scu_ic_of_init_common(scu_ic, node);
+}
+
+static int __init aspeed_ast2600_scu_ic1_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct aspeed_scu_ic *scu_ic = kzalloc(sizeof(*scu_ic), GFP_KERNEL);
+
+ if (!scu_ic)
+ return -ENOMEM;
+
+ scu_ic->irq_enable = ASPEED_AST2600_SCU_IC1_ENABLE;
+ scu_ic->irq_shift = ASPEED_AST2600_SCU_IC1_SHIFT;
+ scu_ic->num_irqs = ASPEED_AST2600_SCU_IC1_NUM_IRQS;
+
+ return aspeed_scu_ic_of_init_common(scu_ic, node);
+}
+
+IRQCHIP_DECLARE(ast2400_scu_ic, "aspeed,ast2400-scu-ic", aspeed_scu_ic_of_init);
+IRQCHIP_DECLARE(ast2500_scu_ic, "aspeed,ast2500-scu-ic", aspeed_scu_ic_of_init);
+IRQCHIP_DECLARE(ast2600_scu_ic0, "aspeed,ast2600-scu-ic0",
+ aspeed_ast2600_scu_ic0_of_init);
+IRQCHIP_DECLARE(ast2600_scu_ic1, "aspeed,ast2600-scu-ic1",
+ aspeed_ast2600_scu_ic1_of_init);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 3/4] ARM: dts: aspeed: ast2500: Add SCU interrupt controller
2019-09-27 20:58 [PATCH v2 0/4] irqchip: Add Aspeed SCU Interrupt Controller Eddie James
2019-09-27 20:58 ` [PATCH v2 1/4] dt-bindings: interrupt-controller: Add Aspeed SCU interrupt controller Eddie James
2019-09-27 20:58 ` [PATCH v2 2/4] irqchip: " Eddie James
@ 2019-09-27 20:58 ` Eddie James
2019-09-27 20:58 ` [PATCH v2 4/4] ARM: dts: aspeed: ast2600: Add SCU interrupt controllers Eddie James
3 siblings, 0 replies; 8+ messages in thread
From: Eddie James @ 2019-09-27 20:58 UTC (permalink / raw)
To: linux-kernel
Cc: devicetree, linux-aspeed, andrew, joel, mark.rutland, robh+dt,
maz, jason, tglx, Eddie James
Add a node for the interrupt controller provided by the SCU.
Signed-off-by: Eddie James <eajames@linux.ibm.com>
---
arch/arm/boot/dts/aspeed-g5.dtsi | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
index e8feb8b..450c2d2 100644
--- a/arch/arm/boot/dts/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed-g5.dtsi
@@ -209,8 +209,9 @@
syscon: syscon@1e6e2000 {
compatible = "aspeed,ast2500-scu", "syscon", "simple-mfd";
reg = <0x1e6e2000 0x1a8>;
+ ranges = <0 0x1e6e2000 0x1a8>;
#address-cells = <1>;
- #size-cells = <0>;
+ #size-cells = <1>;
#clock-cells = <1>;
#reset-cells = <1>;
@@ -224,6 +225,14 @@
compatible = "aspeed,ast2500-p2a-ctrl";
status = "disabled";
};
+
+ scu_ic: interrupt-controller@18 {
+ #interrupt-cells = <1>;
+ compatible = "aspeed,ast2500-scu-ic";
+ reg = <0x18 0x04>;
+ interrupts = <21>;
+ interrupt-controller;
+ };
};
rng: hwrng@1e6e2078 {
--
1.8.3.1
^ permalink raw reply related [flat|nested] 8+ messages in thread