linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/4] MediaTek CIRQ: new register layout and schema
@ 2022-11-23 11:22 AngeloGioacchino Del Regno
  2022-11-23 11:22 ` [PATCH v2 1/4] dt-bindings: interrupt-controller: mediatek,cirq: Migrate to dt schema AngeloGioacchino Del Regno
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-11-23 11:22 UTC (permalink / raw)
  To: tglx
  Cc: maz, robh+dt, krzysztof.kozlowski+dt, matthias.bgg, youlin.pei,
	linux-kernel, devicetree, linux-arm-kernel, linux-mediatek,
	AngeloGioacchino Del Regno

On newer SoCs (like MT8192/95 and also other non-chromebook chips), the
MediaTek CIRQ controller has a new register layout: this series adds
some more flexibility to the irq-mtk-cirq driver, allowing to select
the register layout based on a SoC-specific compatible.

While at it, I've also performed a schema conversion .. because why not.

This was tested on MT8173 Elm, MT8192 Asurada, MT8195 Tomato (both
MT8192 and MT8195 require devicetree work to actually make use of
the CIRQ, not included in this series - while MT8173 has it already).

Changes in v2:
 - Used the right base patches, as something went wrong in v1 (sorry!)
 - [1/4] Fixed items for mediatek,ext-irq-range
 - [3/4] Renamed `regs` to `offsets`, as it's effectively a register
         offsets (and not registers) array
 - [3/4] Added mtk_cirq_reg() accessor
 - [3/4] Added all supported compatible strings to of_device_id
 - [3/4] Fixed mtk_cirq_reg_index enumeration to not assign 0 to the
         first index (as it's 0 by default), removed meaningless
         CIRQ_MAX index
 - [4/4] Now this patch only adds the `v2` offsets and a compatible
         string "mediatek,mt8192-cirq".

AngeloGioacchino Del Regno (4):
  dt-bindings: interrupt-controller: mediatek,cirq: Migrate to dt schema
  dt-bindings: interrupt-controller: mediatek,cirq: Document MT8192
  irqchip: irq-mtk-cirq: Move register offsets to const array
  irqchip: irq-mtk-cirq: Add support for System CIRQ on MT8192

 .../interrupt-controller/mediatek,cirq.txt    | 33 -------
 .../mediatek,mtk-cirq.yaml                    | 68 ++++++++++++++
 drivers/irqchip/irq-mtk-cirq.c                | 91 +++++++++++++++----
 3 files changed, 142 insertions(+), 50 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/interrupt-controller/mediatek,cirq.txt
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/mediatek,mtk-cirq.yaml

-- 
2.38.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2 1/4] dt-bindings: interrupt-controller: mediatek,cirq: Migrate to dt schema
  2022-11-23 11:22 [PATCH v2 0/4] MediaTek CIRQ: new register layout and schema AngeloGioacchino Del Regno
@ 2022-11-23 11:22 ` AngeloGioacchino Del Regno
  2022-11-23 14:21   ` Krzysztof Kozlowski
  2022-11-23 11:22 ` [PATCH v2 2/4] dt-bindings: interrupt-controller: mediatek,cirq: Document MT8192 AngeloGioacchino Del Regno
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-11-23 11:22 UTC (permalink / raw)
  To: tglx
  Cc: maz, robh+dt, krzysztof.kozlowski+dt, matthias.bgg, youlin.pei,
	linux-kernel, devicetree, linux-arm-kernel, linux-mediatek,
	AngeloGioacchino Del Regno

Migrate mediatek,cirq.txt to dt schema as mediatek,mtk-cirq.yaml.
While at it, I've also fixed some typos that were present in the
original txt binding, as it was suggesting that the compatible
string would have "mediatek,cirq" as compatible but, in reality,
that's supposed to be "mediatek,mtk-cirq" instead.

Little rewording on property descriptions also happened for
them to be more concise.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
 .../interrupt-controller/mediatek,cirq.txt    | 33 ---------
 .../mediatek,mtk-cirq.yaml                    | 67 +++++++++++++++++++
 2 files changed, 67 insertions(+), 33 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/interrupt-controller/mediatek,cirq.txt
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/mediatek,mtk-cirq.yaml

diff --git a/Documentation/devicetree/bindings/interrupt-controller/mediatek,cirq.txt b/Documentation/devicetree/bindings/interrupt-controller/mediatek,cirq.txt
deleted file mode 100644
index 5865f4f2c69d..000000000000
--- a/Documentation/devicetree/bindings/interrupt-controller/mediatek,cirq.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-* Mediatek 27xx cirq
-
-In Mediatek SOCs, the CIRQ is a low power interrupt controller designed to
-work outside MCUSYS which comprises with Cortex-Ax cores,CCI and GIC.
-The external interrupts (outside MCUSYS) will feed through CIRQ and connect
-to GIC in MCUSYS. When CIRQ is enabled, it will record the edge-sensitive
-interrupts and generate a pulse signal to parent interrupt controller when
-flush command is executed. With CIRQ, MCUSYS can be completely turned off
-to improve the system power consumption without losing interrupts.
-
-Required properties:
-- compatible: should be one of
-  - "mediatek,mt2701-cirq" for mt2701 CIRQ
-  - "mediatek,mt8135-cirq" for mt8135 CIRQ
-  - "mediatek,mt8173-cirq" for mt8173 CIRQ
-  and "mediatek,cirq" as a fallback.
-- interrupt-controller : Identifies the node as an interrupt controller.
-- #interrupt-cells : Use the same format as specified by GIC in arm,gic.txt.
-- reg: Physical base address of the cirq registers and length of memory
-  mapped region.
-- mediatek,ext-irq-range: Identifies external irq number range in different
-  SOCs.
-
-Example:
-	cirq: interrupt-controller@10204000 {
-		compatible = "mediatek,mt2701-cirq",
-			     "mediatek,mtk-cirq";
-		interrupt-controller;
-		#interrupt-cells = <3>;
-		interrupt-parent = <&sysirq>;
-		reg = <0 0x10204000 0 0x400>;
-		mediatek,ext-irq-start = <32 200>;
-	};
diff --git a/Documentation/devicetree/bindings/interrupt-controller/mediatek,mtk-cirq.yaml b/Documentation/devicetree/bindings/interrupt-controller/mediatek,mtk-cirq.yaml
new file mode 100644
index 000000000000..4f1132c077ff
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/mediatek,mtk-cirq.yaml
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interrupt-controller/mediatek,mtk-cirq.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek System Interrupt Controller
+
+maintainers:
+  - Youlin Pei <youlin.pei@mediatek.com>
+
+description:
+  In MediaTek SoCs, the CIRQ is a low power interrupt controller designed to
+  work outside of MCUSYS which comprises with Cortex-Ax cores, CCI and GIC.
+  The external interrupts (outside MCUSYS) will feed through CIRQ and connect
+  to GIC in MCUSYS. When CIRQ is enabled, it will record the edge-sensitive
+  interrupts and generate a pulse signal to parent interrupt controller when
+  flush command is executed. With CIRQ, MCUSYS can be completely turned off
+  to improve the system power consumption without losing interrupts.
+
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - mediatek,mt2701-cirq
+          - mediatek,mt8135-cirq
+          - mediatek,mt8173-cirq
+      - const: mediatek,mtk-cirq
+
+  reg:
+    maxItems: 1
+
+  '#interrupt-cells':
+    const: 3
+
+  interrupt-controller: true
+
+  mediatek,ext-irq-range:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    items:
+      - description: First CIRQ interrupt
+      - description: Last CIRQ interrupt
+    description:
+      Identifies the range of external interrupts in different SoCs
+
+required:
+  - compatible
+  - reg
+  - '#interrupt-cells'
+  - interrupt-controller
+  - mediatek,ext-irq-range
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    cirq: interrupt-controller@10204000 {
+        compatible = "mediatek,mt2701-cirq", "mediatek,mtk-cirq";
+        reg = <0x10204000 0x400>;
+        #interrupt-cells = <3>;
+        interrupt-controller;
+        interrupt-parent = <&sysirq>;
+        mediatek,ext-irq-range = <32 200>;
+    };
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 2/4] dt-bindings: interrupt-controller: mediatek,cirq: Document MT8192
  2022-11-23 11:22 [PATCH v2 0/4] MediaTek CIRQ: new register layout and schema AngeloGioacchino Del Regno
  2022-11-23 11:22 ` [PATCH v2 1/4] dt-bindings: interrupt-controller: mediatek,cirq: Migrate to dt schema AngeloGioacchino Del Regno
@ 2022-11-23 11:22 ` AngeloGioacchino Del Regno
  2022-11-23 11:22 ` [PATCH v2 3/4] irqchip: irq-mtk-cirq: Move register offsets to const array AngeloGioacchino Del Regno
  2022-11-23 11:22 ` [PATCH v2 4/4] irqchip: irq-mtk-cirq: Add support for System CIRQ on MT8192 AngeloGioacchino Del Regno
  3 siblings, 0 replies; 10+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-11-23 11:22 UTC (permalink / raw)
  To: tglx
  Cc: maz, robh+dt, krzysztof.kozlowski+dt, matthias.bgg, youlin.pei,
	linux-kernel, devicetree, linux-arm-kernel, linux-mediatek,
	AngeloGioacchino Del Regno, Krzysztof Kozlowski

Add compatible to support the SYS_CIRQ controller found on MT8192.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
 .../bindings/interrupt-controller/mediatek,mtk-cirq.yaml         | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/mediatek,mtk-cirq.yaml b/Documentation/devicetree/bindings/interrupt-controller/mediatek,mtk-cirq.yaml
index 4f1132c077ff..fdcb4d8db818 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/mediatek,mtk-cirq.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/mediatek,mtk-cirq.yaml
@@ -26,6 +26,7 @@ properties:
           - mediatek,mt2701-cirq
           - mediatek,mt8135-cirq
           - mediatek,mt8173-cirq
+          - mediatek,mt8192-cirq
       - const: mediatek,mtk-cirq
 
   reg:
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 3/4] irqchip: irq-mtk-cirq: Move register offsets to const array
  2022-11-23 11:22 [PATCH v2 0/4] MediaTek CIRQ: new register layout and schema AngeloGioacchino Del Regno
  2022-11-23 11:22 ` [PATCH v2 1/4] dt-bindings: interrupt-controller: mediatek,cirq: Migrate to dt schema AngeloGioacchino Del Regno
  2022-11-23 11:22 ` [PATCH v2 2/4] dt-bindings: interrupt-controller: mediatek,cirq: Document MT8192 AngeloGioacchino Del Regno
@ 2022-11-23 11:22 ` AngeloGioacchino Del Regno
  2022-11-23 13:50   ` Marc Zyngier
  2022-11-23 11:22 ` [PATCH v2 4/4] irqchip: irq-mtk-cirq: Add support for System CIRQ on MT8192 AngeloGioacchino Del Regno
  3 siblings, 1 reply; 10+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-11-23 11:22 UTC (permalink / raw)
  To: tglx
  Cc: maz, robh+dt, krzysztof.kozlowski+dt, matthias.bgg, youlin.pei,
	linux-kernel, devicetree, linux-arm-kernel, linux-mediatek,
	AngeloGioacchino Del Regno

In preparation to add support for new SoCs having a different
register layout, add an enumeration that documents register
offsets and move the definitions for the same to a u32 array;

Selecting the right register offsets array is done by adding an
of_device_id array containing all of the currently supported
compatible strings pointing to the "v1" offsets array (as data):
since no devicetree declares the `mediatek,mtk-cirq` compatible
without a SoC-specific one, it wasn't necessary to provide any
legacy fallback.

Every usage of the aforemementioned definitions was changed to
get a register address through a newly introduced `mtk_cirq_reg()`
accessor.

This change brings no functional changes.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
 drivers/irqchip/irq-mtk-cirq.c | 78 ++++++++++++++++++++++++++--------
 1 file changed, 61 insertions(+), 17 deletions(-)

diff --git a/drivers/irqchip/irq-mtk-cirq.c b/drivers/irqchip/irq-mtk-cirq.c
index 9bca0918078e..4d873d2ba0fd 100644
--- a/drivers/irqchip/irq-mtk-cirq.c
+++ b/drivers/irqchip/irq-mtk-cirq.c
@@ -15,14 +15,29 @@
 #include <linux/slab.h>
 #include <linux/syscore_ops.h>
 
-#define CIRQ_ACK	0x40
-#define CIRQ_MASK_SET	0xc0
-#define CIRQ_MASK_CLR	0x100
-#define CIRQ_SENS_SET	0x180
-#define CIRQ_SENS_CLR	0x1c0
-#define CIRQ_POL_SET	0x240
-#define CIRQ_POL_CLR	0x280
-#define CIRQ_CONTROL	0x300
+enum mtk_cirq_reg_index {
+	CIRQ_STA,
+	CIRQ_ACK,
+	CIRQ_MASK_SET,
+	CIRQ_MASK_CLR,
+	CIRQ_SENS_SET,
+	CIRQ_SENS_CLR,
+	CIRQ_POL_SET,
+	CIRQ_POL_CLR,
+	CIRQ_CONTROL
+};
+
+static const u32 mtk_cirq_regs_v1[] = {
+	[CIRQ_STA]	= 0x0,
+	[CIRQ_ACK]	= 0x40,
+	[CIRQ_MASK_SET]	= 0xc0,
+	[CIRQ_MASK_CLR]	= 0x100,
+	[CIRQ_SENS_SET]	= 0x180,
+	[CIRQ_SENS_CLR]	= 0x1c0,
+	[CIRQ_POL_SET]	= 0x240,
+	[CIRQ_POL_CLR]	= 0x280,
+	[CIRQ_CONTROL]	= 0x300,
+};
 
 #define CIRQ_EN	0x1
 #define CIRQ_EDGE	0x2
@@ -32,18 +47,28 @@ struct mtk_cirq_chip_data {
 	void __iomem *base;
 	unsigned int ext_irq_start;
 	unsigned int ext_irq_end;
+	const u32 *offsets;
 	struct irq_domain *domain;
 };
 
 static struct mtk_cirq_chip_data *cirq_data;
 
-static void mtk_cirq_write_mask(struct irq_data *data, unsigned int offset)
+static inline void __iomem *mtk_cirq_reg(struct mtk_cirq_chip_data *chip_data,
+					 enum mtk_cirq_reg_index idx,
+					 unsigned int cirq_num)
+{
+	void __iomem *reg = chip_data->base + chip_data->offsets[idx];
+
+	return reg + (cirq_num / 32) * 4;
+}
+
+static void mtk_cirq_write_mask(struct irq_data *data, enum mtk_cirq_reg_index idx)
 {
 	struct mtk_cirq_chip_data *chip_data = data->chip_data;
 	unsigned int cirq_num = data->hwirq;
 	u32 mask = 1 << (cirq_num % 32);
 
-	writel_relaxed(mask, chip_data->base + offset + (cirq_num / 32) * 4);
+	writel_relaxed(mask, mtk_cirq_reg(chip_data, idx, cirq_num));
 }
 
 static void mtk_cirq_mask(struct irq_data *data)
@@ -160,6 +185,7 @@ static const struct irq_domain_ops cirq_domain_ops = {
 #ifdef CONFIG_PM_SLEEP
 static int mtk_cirq_suspend(void)
 {
+	void __iomem *reg;
 	u32 value, mask;
 	unsigned int irq, hwirq_num;
 	bool pending, masked;
@@ -200,31 +226,34 @@ static int mtk_cirq_suspend(void)
 				continue;
 		}
 
+		reg = mtk_cirq_reg(cirq_data, CIRQ_ACK, i);
 		mask = 1 << (i % 32);
-		writel_relaxed(mask, cirq_data->base + CIRQ_ACK + (i / 32) * 4);
+		writel_relaxed(mask, reg);
 	}
 
 	/* set edge_only mode, record edge-triggerd interrupts */
 	/* enable cirq */
-	value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
+	reg = mtk_cirq_reg(cirq_data, CIRQ_CONTROL, 0);
+	value = readl_relaxed(reg);
 	value |= (CIRQ_EDGE | CIRQ_EN);
-	writel_relaxed(value, cirq_data->base + CIRQ_CONTROL);
+	writel_relaxed(value, reg);
 
 	return 0;
 }
 
 static void mtk_cirq_resume(void)
 {
+	void __iomem *reg = mtk_cirq_reg(cirq_data, CIRQ_CONTROL, 0);
 	u32 value;
 
 	/* flush recorded interrupts, will send signals to parent controller */
-	value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
-	writel_relaxed(value | CIRQ_FLUSH, cirq_data->base + CIRQ_CONTROL);
+	value = readl_relaxed(reg);
+	writel_relaxed(value | CIRQ_FLUSH, reg);
 
 	/* disable cirq */
-	value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
+	value = readl_relaxed(reg);
 	value &= ~(CIRQ_EDGE | CIRQ_EN);
-	writel_relaxed(value, cirq_data->base + CIRQ_CONTROL);
+	writel_relaxed(value, reg);
 }
 
 static struct syscore_ops mtk_cirq_syscore_ops = {
@@ -240,10 +269,18 @@ static void mtk_cirq_syscore_init(void)
 static inline void mtk_cirq_syscore_init(void) {}
 #endif
 
+static const struct of_device_id mtk_cirq_of_match[] = {
+	{ .compatible = "mediatek,mt2701-cirq", .data = &mtk_cirq_regs_v1 },
+	{ .compatible = "mediatek,mt8135-cirq", .data = &mtk_cirq_regs_v1 },
+	{ .compatible = "mediatek,mt8173-cirq", .data = &mtk_cirq_regs_v1 },
+	{ /* sentinel */ }
+};
+
 static int __init mtk_cirq_of_init(struct device_node *node,
 				   struct device_node *parent)
 {
 	struct irq_domain *domain, *domain_parent;
+	const struct of_device_id *match;
 	unsigned int irq_num;
 	int ret;
 
@@ -274,6 +311,13 @@ static int __init mtk_cirq_of_init(struct device_node *node,
 	if (ret)
 		goto out_unmap;
 
+	match = of_match_node(mtk_cirq_of_match, node);
+	if (!match) {
+		ret = -ENODEV;
+		goto out_unmap;
+	}
+	cirq_data->offsets = match->data;
+
 	irq_num = cirq_data->ext_irq_end - cirq_data->ext_irq_start + 1;
 	domain = irq_domain_add_hierarchy(domain_parent, 0,
 					  irq_num, node,
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 4/4] irqchip: irq-mtk-cirq: Add support for System CIRQ on MT8192
  2022-11-23 11:22 [PATCH v2 0/4] MediaTek CIRQ: new register layout and schema AngeloGioacchino Del Regno
                   ` (2 preceding siblings ...)
  2022-11-23 11:22 ` [PATCH v2 3/4] irqchip: irq-mtk-cirq: Move register offsets to const array AngeloGioacchino Del Regno
@ 2022-11-23 11:22 ` AngeloGioacchino Del Regno
  3 siblings, 0 replies; 10+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-11-23 11:22 UTC (permalink / raw)
  To: tglx
  Cc: maz, robh+dt, krzysztof.kozlowski+dt, matthias.bgg, youlin.pei,
	linux-kernel, devicetree, linux-arm-kernel, linux-mediatek,
	AngeloGioacchino Del Regno

On some SoCs the System CIRQ register layout is slightly different,
as there are more registers per function and in some cases other
differences later in the layout: this is seen on at least MT8192,
but it's also valid for some other "contemporary" SoCs both for
Chromebooks and for smartphones.

Add the new "v2" register layout and use it if the compatible
"mediatek,mt8192-cirq" is found.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
 drivers/irqchip/irq-mtk-cirq.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/irqchip/irq-mtk-cirq.c b/drivers/irqchip/irq-mtk-cirq.c
index 4d873d2ba0fd..57452d389b47 100644
--- a/drivers/irqchip/irq-mtk-cirq.c
+++ b/drivers/irqchip/irq-mtk-cirq.c
@@ -39,6 +39,18 @@ static const u32 mtk_cirq_regs_v1[] = {
 	[CIRQ_CONTROL]	= 0x300,
 };
 
+static const u32 mtk_cirq_regs_v2[] = {
+	[CIRQ_STA]	= 0x0,
+	[CIRQ_ACK]	= 0x80,
+	[CIRQ_MASK_SET]	= 0x180,
+	[CIRQ_MASK_CLR]	= 0x200,
+	[CIRQ_SENS_SET]	= 0x300,
+	[CIRQ_SENS_CLR]	= 0x380,
+	[CIRQ_POL_SET]	= 0x480,
+	[CIRQ_POL_CLR]	= 0x500,
+	[CIRQ_CONTROL]	= 0x600,
+};
+
 #define CIRQ_EN	0x1
 #define CIRQ_EDGE	0x2
 #define CIRQ_FLUSH	0x4
@@ -273,6 +285,7 @@ static const struct of_device_id mtk_cirq_of_match[] = {
 	{ .compatible = "mediatek,mt2701-cirq", .data = &mtk_cirq_regs_v1 },
 	{ .compatible = "mediatek,mt8135-cirq", .data = &mtk_cirq_regs_v1 },
 	{ .compatible = "mediatek,mt8173-cirq", .data = &mtk_cirq_regs_v1 },
+	{ .compatible = "mediatek,mt8192-cirq", .data = &mtk_cirq_regs_v2 },
 	{ /* sentinel */ }
 };
 
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 3/4] irqchip: irq-mtk-cirq: Move register offsets to const array
  2022-11-23 11:22 ` [PATCH v2 3/4] irqchip: irq-mtk-cirq: Move register offsets to const array AngeloGioacchino Del Regno
@ 2022-11-23 13:50   ` Marc Zyngier
  2022-11-23 14:57     ` AngeloGioacchino Del Regno
  0 siblings, 1 reply; 10+ messages in thread
From: Marc Zyngier @ 2022-11-23 13:50 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: tglx, robh+dt, krzysztof.kozlowski+dt, matthias.bgg, youlin.pei,
	linux-kernel, devicetree, linux-arm-kernel, linux-mediatek

On Wed, 23 Nov 2022 11:22:48 +0000,
AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> wrote:
> 
> In preparation to add support for new SoCs having a different
> register layout, add an enumeration that documents register
> offsets and move the definitions for the same to a u32 array;
> 
> Selecting the right register offsets array is done by adding an
> of_device_id array containing all of the currently supported
> compatible strings pointing to the "v1" offsets array (as data):
> since no devicetree declares the `mediatek,mtk-cirq` compatible
> without a SoC-specific one, it wasn't necessary to provide any
> legacy fallback.
> 
> Every usage of the aforemementioned definitions was changed to
> get a register address through a newly introduced `mtk_cirq_reg()`
> accessor.
> 
> This change brings no functional changes.
> 
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> ---
>  drivers/irqchip/irq-mtk-cirq.c | 78 ++++++++++++++++++++++++++--------
>  1 file changed, 61 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-mtk-cirq.c b/drivers/irqchip/irq-mtk-cirq.c
> index 9bca0918078e..4d873d2ba0fd 100644
> --- a/drivers/irqchip/irq-mtk-cirq.c
> +++ b/drivers/irqchip/irq-mtk-cirq.c
> @@ -15,14 +15,29 @@
>  #include <linux/slab.h>
>  #include <linux/syscore_ops.h>
>  
> -#define CIRQ_ACK	0x40
> -#define CIRQ_MASK_SET	0xc0
> -#define CIRQ_MASK_CLR	0x100
> -#define CIRQ_SENS_SET	0x180
> -#define CIRQ_SENS_CLR	0x1c0
> -#define CIRQ_POL_SET	0x240
> -#define CIRQ_POL_CLR	0x280
> -#define CIRQ_CONTROL	0x300
> +enum mtk_cirq_reg_index {
> +	CIRQ_STA,
> +	CIRQ_ACK,
> +	CIRQ_MASK_SET,
> +	CIRQ_MASK_CLR,
> +	CIRQ_SENS_SET,
> +	CIRQ_SENS_CLR,
> +	CIRQ_POL_SET,
> +	CIRQ_POL_CLR,
> +	CIRQ_CONTROL
> +};
> +
> +static const u32 mtk_cirq_regs_v1[] = {

Again: this contains offsets, not registers. Consistency matters.

> +	[CIRQ_STA]	= 0x0,
> +	[CIRQ_ACK]	= 0x40,
> +	[CIRQ_MASK_SET]	= 0xc0,
> +	[CIRQ_MASK_CLR]	= 0x100,
> +	[CIRQ_SENS_SET]	= 0x180,
> +	[CIRQ_SENS_CLR]	= 0x1c0,
> +	[CIRQ_POL_SET]	= 0x240,
> +	[CIRQ_POL_CLR]	= 0x280,
> +	[CIRQ_CONTROL]	= 0x300,
> +};
>  
>  #define CIRQ_EN	0x1
>  #define CIRQ_EDGE	0x2
> @@ -32,18 +47,28 @@ struct mtk_cirq_chip_data {
>  	void __iomem *base;
>  	unsigned int ext_irq_start;
>  	unsigned int ext_irq_end;
> +	const u32 *offsets;
>  	struct irq_domain *domain;
>  };
>  
>  static struct mtk_cirq_chip_data *cirq_data;
>  
> -static void mtk_cirq_write_mask(struct irq_data *data, unsigned int offset)
> +static inline void __iomem *mtk_cirq_reg(struct mtk_cirq_chip_data *chip_data,

Drop the inline. That's for the compiler to figure it out.

> +					 enum mtk_cirq_reg_index idx,
> +					 unsigned int cirq_num)

What does cirq_num mean for registers that are not relative to an
interrupt? Create a separate helper for those.

> +{
> +	void __iomem *reg = chip_data->base + chip_data->offsets[idx];
> +
> +	return reg + (cirq_num / 32) * 4;
> +}
> +
> +static void mtk_cirq_write_mask(struct irq_data *data, enum mtk_cirq_reg_index idx)
>  {
>  	struct mtk_cirq_chip_data *chip_data = data->chip_data;
>  	unsigned int cirq_num = data->hwirq;
>  	u32 mask = 1 << (cirq_num % 32);
>  
> -	writel_relaxed(mask, chip_data->base + offset + (cirq_num / 32) * 4);
> +	writel_relaxed(mask, mtk_cirq_reg(chip_data, idx, cirq_num));
>  }
>  
>  static void mtk_cirq_mask(struct irq_data *data)
> @@ -160,6 +185,7 @@ static const struct irq_domain_ops cirq_domain_ops = {
>  #ifdef CONFIG_PM_SLEEP
>  static int mtk_cirq_suspend(void)
>  {
> +	void __iomem *reg;
>  	u32 value, mask;
>  	unsigned int irq, hwirq_num;
>  	bool pending, masked;
> @@ -200,31 +226,34 @@ static int mtk_cirq_suspend(void)
>  				continue;
>  		}
>  
> +		reg = mtk_cirq_reg(cirq_data, CIRQ_ACK, i);
>  		mask = 1 << (i % 32);
> -		writel_relaxed(mask, cirq_data->base + CIRQ_ACK + (i / 32) * 4);
> +		writel_relaxed(mask, reg);
>  	}
>  
>  	/* set edge_only mode, record edge-triggerd interrupts */
>  	/* enable cirq */
> -	value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
> +	reg = mtk_cirq_reg(cirq_data, CIRQ_CONTROL, 0);
> +	value = readl_relaxed(reg);
>  	value |= (CIRQ_EDGE | CIRQ_EN);
> -	writel_relaxed(value, cirq_data->base + CIRQ_CONTROL);
> +	writel_relaxed(value, reg);
>  
>  	return 0;
>  }
>  
>  static void mtk_cirq_resume(void)
>  {
> +	void __iomem *reg = mtk_cirq_reg(cirq_data, CIRQ_CONTROL, 0);
>  	u32 value;
>  
>  	/* flush recorded interrupts, will send signals to parent controller */
> -	value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
> -	writel_relaxed(value | CIRQ_FLUSH, cirq_data->base + CIRQ_CONTROL);
> +	value = readl_relaxed(reg);
> +	writel_relaxed(value | CIRQ_FLUSH, reg);
>  
>  	/* disable cirq */
> -	value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
> +	value = readl_relaxed(reg);
>  	value &= ~(CIRQ_EDGE | CIRQ_EN);
> -	writel_relaxed(value, cirq_data->base + CIRQ_CONTROL);
> +	writel_relaxed(value, reg);
>  }
>  
>  static struct syscore_ops mtk_cirq_syscore_ops = {
> @@ -240,10 +269,18 @@ static void mtk_cirq_syscore_init(void)
>  static inline void mtk_cirq_syscore_init(void) {}
>  #endif
>  
> +static const struct of_device_id mtk_cirq_of_match[] = {

Can't this be made __initconst?

> +	{ .compatible = "mediatek,mt2701-cirq", .data = &mtk_cirq_regs_v1 },
> +	{ .compatible = "mediatek,mt8135-cirq", .data = &mtk_cirq_regs_v1 },
> +	{ .compatible = "mediatek,mt8173-cirq", .data = &mtk_cirq_regs_v1 },
> +	{ /* sentinel */ }
> +};
> +
>  static int __init mtk_cirq_of_init(struct device_node *node,
>  				   struct device_node *parent)
>  {
>  	struct irq_domain *domain, *domain_parent;
> +	const struct of_device_id *match;
>  	unsigned int irq_num;
>  	int ret;
>  
> @@ -274,6 +311,13 @@ static int __init mtk_cirq_of_init(struct device_node *node,
>  	if (ret)
>  		goto out_unmap;
>  
> +	match = of_match_node(mtk_cirq_of_match, node);
> +	if (!match) {
> +		ret = -ENODEV;
> +		goto out_unmap;
> +	}

Can't you perform this before mapping the MMIO region and allocating
memory? If you must fail, fail early.

> +	cirq_data->offsets = match->data;
> +
>  	irq_num = cirq_data->ext_irq_end - cirq_data->ext_irq_start + 1;
>  	domain = irq_domain_add_hierarchy(domain_parent, 0,
>  					  irq_num, node,

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/4] dt-bindings: interrupt-controller: mediatek,cirq: Migrate to dt schema
  2022-11-23 11:22 ` [PATCH v2 1/4] dt-bindings: interrupt-controller: mediatek,cirq: Migrate to dt schema AngeloGioacchino Del Regno
@ 2022-11-23 14:21   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 10+ messages in thread
From: Krzysztof Kozlowski @ 2022-11-23 14:21 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, tglx
  Cc: maz, robh+dt, krzysztof.kozlowski+dt, matthias.bgg, youlin.pei,
	linux-kernel, devicetree, linux-arm-kernel, linux-mediatek

On 23/11/2022 12:22, AngeloGioacchino Del Regno wrote:
> Migrate mediatek,cirq.txt to dt schema as mediatek,mtk-cirq.yaml.
> While at it, I've also fixed some typos that were present in the
> original txt binding, as it was suggesting that the compatible
> string would have "mediatek,cirq" as compatible but, in reality,
> that's supposed to be "mediatek,mtk-cirq" instead.
> 
> Little rewording on property descriptions also happened for
> them to be more concise.
> 
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> ---
>  .../interrupt-controller/mediatek,cirq.txt    | 33 ---------


Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 3/4] irqchip: irq-mtk-cirq: Move register offsets to const array
  2022-11-23 13:50   ` Marc Zyngier
@ 2022-11-23 14:57     ` AngeloGioacchino Del Regno
  2022-11-23 16:28       ` Marc Zyngier
  0 siblings, 1 reply; 10+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-11-23 14:57 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: tglx, robh+dt, krzysztof.kozlowski+dt, matthias.bgg, youlin.pei,
	linux-kernel, devicetree, linux-arm-kernel, linux-mediatek

Il 23/11/22 14:50, Marc Zyngier ha scritto:
> On Wed, 23 Nov 2022 11:22:48 +0000,
> AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> wrote:
>>
>> In preparation to add support for new SoCs having a different
>> register layout, add an enumeration that documents register
>> offsets and move the definitions for the same to a u32 array;
>>
>> Selecting the right register offsets array is done by adding an
>> of_device_id array containing all of the currently supported
>> compatible strings pointing to the "v1" offsets array (as data):
>> since no devicetree declares the `mediatek,mtk-cirq` compatible
>> without a SoC-specific one, it wasn't necessary to provide any
>> legacy fallback.
>>
>> Every usage of the aforemementioned definitions was changed to
>> get a register address through a newly introduced `mtk_cirq_reg()`
>> accessor.
>>
>> This change brings no functional changes.
>>
>> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>> ---
>>   drivers/irqchip/irq-mtk-cirq.c | 78 ++++++++++++++++++++++++++--------
>>   1 file changed, 61 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/irqchip/irq-mtk-cirq.c b/drivers/irqchip/irq-mtk-cirq.c
>> index 9bca0918078e..4d873d2ba0fd 100644
>> --- a/drivers/irqchip/irq-mtk-cirq.c
>> +++ b/drivers/irqchip/irq-mtk-cirq.c
>> @@ -15,14 +15,29 @@
>>   #include <linux/slab.h>
>>   #include <linux/syscore_ops.h>
>>   
>> -#define CIRQ_ACK	0x40
>> -#define CIRQ_MASK_SET	0xc0
>> -#define CIRQ_MASK_CLR	0x100
>> -#define CIRQ_SENS_SET	0x180
>> -#define CIRQ_SENS_CLR	0x1c0
>> -#define CIRQ_POL_SET	0x240
>> -#define CIRQ_POL_CLR	0x280
>> -#define CIRQ_CONTROL	0x300
>> +enum mtk_cirq_reg_index {
>> +	CIRQ_STA,
>> +	CIRQ_ACK,
>> +	CIRQ_MASK_SET,
>> +	CIRQ_MASK_CLR,
>> +	CIRQ_SENS_SET,
>> +	CIRQ_SENS_CLR,
>> +	CIRQ_POL_SET,
>> +	CIRQ_POL_CLR,
>> +	CIRQ_CONTROL
>> +};
>> +
>> +static const u32 mtk_cirq_regs_v1[] = {
> 
> Again: this contains offsets, not registers. Consistency matters.
> 

Ack.

>> +	[CIRQ_STA]	= 0x0,
>> +	[CIRQ_ACK]	= 0x40,
>> +	[CIRQ_MASK_SET]	= 0xc0,
>> +	[CIRQ_MASK_CLR]	= 0x100,
>> +	[CIRQ_SENS_SET]	= 0x180,
>> +	[CIRQ_SENS_CLR]	= 0x1c0,
>> +	[CIRQ_POL_SET]	= 0x240,
>> +	[CIRQ_POL_CLR]	= 0x280,
>> +	[CIRQ_CONTROL]	= 0x300,
>> +};
>>   
>>   #define CIRQ_EN	0x1
>>   #define CIRQ_EDGE	0x2
>> @@ -32,18 +47,28 @@ struct mtk_cirq_chip_data {
>>   	void __iomem *base;
>>   	unsigned int ext_irq_start;
>>   	unsigned int ext_irq_end;
>> +	const u32 *offsets;
>>   	struct irq_domain *domain;
>>   };
>>   
>>   static struct mtk_cirq_chip_data *cirq_data;
>>   
>> -static void mtk_cirq_write_mask(struct irq_data *data, unsigned int offset)
>> +static inline void __iomem *mtk_cirq_reg(struct mtk_cirq_chip_data *chip_data,
> 
> Drop the inline. That's for the compiler to figure it out.
> 

Will do.

>> +					 enum mtk_cirq_reg_index idx,
>> +					 unsigned int cirq_num)
> 
> What does cirq_num mean for registers that are not relative to an
> interrupt? Create a separate helper for those.
> 
Means literally nothing, so yes I agree, but...

... mtk_cirq_irq_reg(), mtk_cirq_reg() feels too similar and may lead to
confusion while reading the code.

Any advice about a possibly clear-er name?

>> +{
>> +	void __iomem *reg = chip_data->base + chip_data->offsets[idx];
>> +
>> +	return reg + (cirq_num / 32) * 4;
>> +}
>> +
>> +static void mtk_cirq_write_mask(struct irq_data *data, enum mtk_cirq_reg_index idx)
>>   {
>>   	struct mtk_cirq_chip_data *chip_data = data->chip_data;
>>   	unsigned int cirq_num = data->hwirq;
>>   	u32 mask = 1 << (cirq_num % 32);
>>   
>> -	writel_relaxed(mask, chip_data->base + offset + (cirq_num / 32) * 4);
>> +	writel_relaxed(mask, mtk_cirq_reg(chip_data, idx, cirq_num));
>>   }
>>   
>>   static void mtk_cirq_mask(struct irq_data *data)
>> @@ -160,6 +185,7 @@ static const struct irq_domain_ops cirq_domain_ops = {
>>   #ifdef CONFIG_PM_SLEEP
>>   static int mtk_cirq_suspend(void)
>>   {
>> +	void __iomem *reg;
>>   	u32 value, mask;
>>   	unsigned int irq, hwirq_num;
>>   	bool pending, masked;
>> @@ -200,31 +226,34 @@ static int mtk_cirq_suspend(void)
>>   				continue;
>>   		}
>>   
>> +		reg = mtk_cirq_reg(cirq_data, CIRQ_ACK, i);
>>   		mask = 1 << (i % 32);
>> -		writel_relaxed(mask, cirq_data->base + CIRQ_ACK + (i / 32) * 4);
>> +		writel_relaxed(mask, reg);
>>   	}
>>   
>>   	/* set edge_only mode, record edge-triggerd interrupts */
>>   	/* enable cirq */
>> -	value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
>> +	reg = mtk_cirq_reg(cirq_data, CIRQ_CONTROL, 0);
>> +	value = readl_relaxed(reg);
>>   	value |= (CIRQ_EDGE | CIRQ_EN);
>> -	writel_relaxed(value, cirq_data->base + CIRQ_CONTROL);
>> +	writel_relaxed(value, reg);
>>   
>>   	return 0;
>>   }
>>   
>>   static void mtk_cirq_resume(void)
>>   {
>> +	void __iomem *reg = mtk_cirq_reg(cirq_data, CIRQ_CONTROL, 0);
>>   	u32 value;
>>   
>>   	/* flush recorded interrupts, will send signals to parent controller */
>> -	value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
>> -	writel_relaxed(value | CIRQ_FLUSH, cirq_data->base + CIRQ_CONTROL);
>> +	value = readl_relaxed(reg);
>> +	writel_relaxed(value | CIRQ_FLUSH, reg);
>>   
>>   	/* disable cirq */
>> -	value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
>> +	value = readl_relaxed(reg);
>>   	value &= ~(CIRQ_EDGE | CIRQ_EN);
>> -	writel_relaxed(value, cirq_data->base + CIRQ_CONTROL);
>> +	writel_relaxed(value, reg);
>>   }
>>   
>>   static struct syscore_ops mtk_cirq_syscore_ops = {
>> @@ -240,10 +269,18 @@ static void mtk_cirq_syscore_init(void)
>>   static inline void mtk_cirq_syscore_init(void) {}
>>   #endif
>>   
>> +static const struct of_device_id mtk_cirq_of_match[] = {
> 
> Can't this be made __initconst?
> 

Ack.

>> +	{ .compatible = "mediatek,mt2701-cirq", .data = &mtk_cirq_regs_v1 },
>> +	{ .compatible = "mediatek,mt8135-cirq", .data = &mtk_cirq_regs_v1 },
>> +	{ .compatible = "mediatek,mt8173-cirq", .data = &mtk_cirq_regs_v1 },
>> +	{ /* sentinel */ }
>> +};
>> +
>>   static int __init mtk_cirq_of_init(struct device_node *node,
>>   				   struct device_node *parent)
>>   {
>>   	struct irq_domain *domain, *domain_parent;
>> +	const struct of_device_id *match;
>>   	unsigned int irq_num;
>>   	int ret;
>>   
>> @@ -274,6 +311,13 @@ static int __init mtk_cirq_of_init(struct device_node *node,
>>   	if (ret)
>>   		goto out_unmap;
>>   
>> +	match = of_match_node(mtk_cirq_of_match, node);
>> +	if (!match) {
>> +		ret = -ENODEV;
>> +		goto out_unmap;
>> +	}
> 
> Can't you perform this before mapping the MMIO region and allocating
> memory? If you must fail, fail early.
> 

I was thinking the same, but ultimately chose to aggregate handling that entirely
in one place...

I'll move that as suggested.

Many thanks,
Angelo


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 3/4] irqchip: irq-mtk-cirq: Move register offsets to const array
  2022-11-23 14:57     ` AngeloGioacchino Del Regno
@ 2022-11-23 16:28       ` Marc Zyngier
  2022-11-24  9:59         ` AngeloGioacchino Del Regno
  0 siblings, 1 reply; 10+ messages in thread
From: Marc Zyngier @ 2022-11-23 16:28 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: tglx, robh+dt, krzysztof.kozlowski+dt, matthias.bgg, youlin.pei,
	linux-kernel, devicetree, linux-arm-kernel, linux-mediatek

On Wed, 23 Nov 2022 14:57:02 +0000,
AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> wrote:
> 
> >> +					 enum mtk_cirq_reg_index idx,
> >> +					 unsigned int cirq_num)
> > 
> > What does cirq_num mean for registers that are not relative to an
> > interrupt? Create a separate helper for those.
> > 
> Means literally nothing, so yes I agree, but...
> 
> ... mtk_cirq_irq_reg(), mtk_cirq_reg() feels too similar and may lead to
> confusion while reading the code.
> 
> Any advice about a possibly clear-er name?

I think the names are OK. Passing an interrupt number as a parameter
is a good discriminant anyway.

Please wait for a few days before posting the next version though.

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 3/4] irqchip: irq-mtk-cirq: Move register offsets to const array
  2022-11-23 16:28       ` Marc Zyngier
@ 2022-11-24  9:59         ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 10+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-11-24  9:59 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: tglx, robh+dt, krzysztof.kozlowski+dt, matthias.bgg, youlin.pei,
	linux-kernel, devicetree, linux-arm-kernel, linux-mediatek

Il 23/11/22 17:28, Marc Zyngier ha scritto:
> On Wed, 23 Nov 2022 14:57:02 +0000,
> AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> wrote:
>>
>>>> +					 enum mtk_cirq_reg_index idx,
>>>> +					 unsigned int cirq_num)
>>>
>>> What does cirq_num mean for registers that are not relative to an
>>> interrupt? Create a separate helper for those.
>>>
>> Means literally nothing, so yes I agree, but...
>>
>> ... mtk_cirq_irq_reg(), mtk_cirq_reg() feels too similar and may lead to
>> confusion while reading the code.
>>
>> Any advice about a possibly clear-er name?
> 
> I think the names are OK. Passing an interrupt number as a parameter
> is a good discriminant anyway.
> 
> Please wait for a few days before posting the next version though.
> 
> 	M.
> 

Let's go with these names then, thank you!

Regards,
Angelo

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2022-11-24 10:00 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-23 11:22 [PATCH v2 0/4] MediaTek CIRQ: new register layout and schema AngeloGioacchino Del Regno
2022-11-23 11:22 ` [PATCH v2 1/4] dt-bindings: interrupt-controller: mediatek,cirq: Migrate to dt schema AngeloGioacchino Del Regno
2022-11-23 14:21   ` Krzysztof Kozlowski
2022-11-23 11:22 ` [PATCH v2 2/4] dt-bindings: interrupt-controller: mediatek,cirq: Document MT8192 AngeloGioacchino Del Regno
2022-11-23 11:22 ` [PATCH v2 3/4] irqchip: irq-mtk-cirq: Move register offsets to const array AngeloGioacchino Del Regno
2022-11-23 13:50   ` Marc Zyngier
2022-11-23 14:57     ` AngeloGioacchino Del Regno
2022-11-23 16:28       ` Marc Zyngier
2022-11-24  9:59         ` AngeloGioacchino Del Regno
2022-11-23 11:22 ` [PATCH v2 4/4] irqchip: irq-mtk-cirq: Add support for System CIRQ on MT8192 AngeloGioacchino Del Regno

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).