Skip to contentSkip to conversation

clk: add support for Airoha AN7583 clock

PATCH Superseded Christian Marangi 4 participants 12 messages Aug 19 – Oct 7

Subsystems (3)

v6 of 12 Superseded Latest is v12 →

lore
Share & tools
lore
#0 lore raw

v6 cover clk: add support for Airoha AN7583 clock

This small series introduce some cleanup and support for clock and reset of Airoha AN7583.

The implementation is similar to EN7581 but AN7583 introduce new reset and more clock divisor support.

Changes v6:
- Address bot suggestion for DT patch
- Add further information on chip-scu phandle
- Add dedicated PERSTOUT reset and PCIE_HB reset

Changes v5:
- Rebase on top of linux-next
- Drop even more patch to reduce patch delta
- Make chip-scu specific to AN7583

Changes v4:
- Add review tag for DT patch
- Fix clock patch to use en7581-chip-scu compatible
- Drop PCIE SCU SSR write

Changes v3:
- Drop .set_rate patch (will be proposed later)
- Drop chip-scu binding and related patch

Changes v2:
- Add .set_rate support
- Rework DT to EN7581 implementation (clock driver is parent)
- Add additional cleanup patch
- Merge binding with schema patch
- Add chip_scu phandle

Christian Marangi (3):
dt-bindings: clock: airoha: Document support for AN7583 clock
clk: en7523: generalize register clocks function
clk: en7523: add support for Airoha AN7583 clock

 .../bindings/clock/airoha,en7523-scu.yaml     |  20 ++
 drivers/clk/clk-en7523.c                      | 250 +++++++++++++++++-
 include/dt-bindings/clock/en7523-clk.h        |   3 +
 .../dt-bindings/reset/airoha,an7583-reset.h   |  65 +++++
 4 files changed, 336 insertions(+), 2 deletions(-)
 create mode 100644 include/dt-bindings/reset/airoha,an7583-reset.h
Signature · 1 line
2.53.0
#1 lore raw

PATCH v6 1/3 dt-bindings: clock: airoha: Document support for AN7583 clock

Document support for Airoha AN7583 clock. This is based on the EN7523 clock schema with the new requirement of the "airoha,chip-scu".

Add additional binding for additional clock and reset lines.

---
 .../bindings/clock/airoha,en7523-scu.yaml     | 20 ++++++
 include/dt-bindings/clock/en7523-clk.h        |  3 +
 .../dt-bindings/reset/airoha,an7583-reset.h   | 65 +++++++++++++++++++
 3 files changed, 88 insertions(+)
 create mode 100644 include/dt-bindings/reset/airoha,an7583-reset.h
Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +20 -0
index eb24a5687639..edecc635807b 100644
@@ -30,6 +30,7 @@ properties:
   compatible:
     items:
       - enum:
+          - airoha,an7583-scu
           - airoha,en7523-scu
           - airoha,en7581-scu
           - econet,en751221-scu
@@ -50,12 +51,30 @@ properties:
     description: ID of the controller reset line
     const: 1
 
+  airoha,chip-scu:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: phandle to the Chip SCU providing the registers required
+      for configuring the PCIe related clocks and resets.
+
 required:
   - compatible
   - reg
   - '#clock-cells'
 
 allOf:
+  - if:
+      properties:
+        compatible:
+          const: airoha,an7583-scu
+
+    then:
+      required:
+        - airoha,chip-scu
+
+    else:
+      properties:
+        airoha,chip-scu: false
+
   - if:
       properties:
         compatible:
@@ -69,6 +88,7 @@ allOf:
       properties:
         compatible:
           enum:
+            - airoha,an7583-scu
             - airoha,en7581-scu
             - econet,en751221-scu
     then:
include/dt-bindings/clock/en7523-clk.h +3 -0
index edfa64045f52..0fbbcb7b1b25 100644
@@ -14,4 +14,7 @@
 
 #define EN7581_CLK_EMMC		8
 
+#define AN7583_CLK_MDIO0	9
+#define AN7583_CLK_MDIO1	10
+
 #endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */
include/dt-bindings/reset/airoha,an7583-reset.h new file +65 -0

65 lines not on this page · raw message

Signature · 1 line
2.53.0
#2 lore raw

Re: [PATCH v6 1/3] dt-bindings: clock: airoha: Document support for AN7583 clock

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [Medium] The device tree binding defines the SCU as a reset provider but omits #reset-cells from the required properties list. --

--- Patch [1]: [PATCH v6 1/3] dt-bindings: clock: airoha: Document support for AN7583 clock --- commit d5f1a3bf6c2e7155e5e00666d8f07ae07a173ed5
Author: Christian Marangi <[email protected]>

dt-bindings: clock: airoha: Document support for AN7583 clock

This commit documents support for the Airoha AN7583 clock, building upon the EN7523 clock schema. It introduces a new requirement for airoha,chip-scu and adds supplementary bindings for additional clock and reset lines.

Quoted 4 lines
Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +0 -0
index eb24a5687639e..edecc635807be 100644

[ ... ]

Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml properties: · line 62

Quoted 13 lines
Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +5 -0
@@ -50,12 +51,30 @@ properties:
     description: ID of the controller reset line
     const: 1
 
+  airoha,chip-scu:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: phandle to the Chip SCU providing the registers required
+      for configuring the PCIe related clocks and resets.
+
 required:
   - compatible
   - reg
   - '#clock-cells'

[Severity: Medium]
This is a pre-existing issue, but since the binding defines the SCU as a reset provider and this patch adds dedicated reset definitions, should #reset-cells be included in this global required list?

Without it, device tree nodes using the airoha,an7583-scu compatible string (or other variants in this binding) that omit #reset-cells will incorrectly pass schema validation, potentially allowing incomplete device trees to cause runtime failures in dependent drivers.

Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml properties: · line 72

Quoted 10 lines
Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +8 -0
 allOf:
+  - if:
+      properties:
+        compatible:
+          const: airoha,an7583-scu
+
+    then:
+      required:
+        - airoha,chip-scu

[Severity: Medium]
This is a pre-existing issue regarding reset providers in this file, but if #reset-cells is not meant to be globally required for all compatibles, should it be added to this conditional required list specifically for airoha,an7583-scu alongside airoha,chip-scu?

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
#3 lore raw

Re: [PATCH v6 1/3] dt-bindings: clock: airoha: Document support for AN7583 clock

In reply to Christian Marangi
Quoted 26 lines · Christian Marangi

Document support for Airoha AN7583 clock. This is based on the EN7523 clock schema with the new requirement of the "airoha,chip-scu".

Add additional binding for additional clock and reset lines.

---
 .../bindings/clock/airoha,en7523-scu.yaml     | 20 ++++++
 include/dt-bindings/clock/en7523-clk.h        |  3 +
 .../dt-bindings/reset/airoha,an7583-reset.h   | 65 +++++++++++++++++++
 3 files changed, 88 insertions(+)
 create mode 100644 include/dt-bindings/reset/airoha,an7583-reset.h
Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +1 -0
index eb24a5687639..edecc635807b 100644
@@ -30,6 +30,7 @@ properties:
   compatible:
     items:
       - enum:
+          - airoha,an7583-scu
           - airoha,en7523-scu
           - airoha,en7581-scu
           - econet,en751221-scu

Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml properties: · line 57

Quoted 7 lines
Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +4 -0
@@ -50,12 +51,30 @@ properties:
     description: ID of the controller reset line
     const: 1
 
+  airoha,chip-scu:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: phandle to the Chip SCU providing the registers required
+      for configuring the PCIe related clocks and resets.

This is the clock provider. Clock provider should not be accessing registers of other device to configure its clocks. Either you misrepresented clock hierarchy or devices.

I did search for DTS to try to understand the big pictuer - nothing, no results, no upstream submission to Linux kernel.

Best regards,
Krzysztof

#4 lore raw

Re: [PATCH v6 1/3] dt-bindings: clock: airoha: Document support for AN7583 clock

Quoted 39 lines · Krzysztof Kozlowski
Quoted 26 lines · Christian Marangi

Document support for Airoha AN7583 clock. This is based on the EN7523 clock schema with the new requirement of the "airoha,chip-scu".

Add additional binding for additional clock and reset lines.

---
 .../bindings/clock/airoha,en7523-scu.yaml     | 20 ++++++
 include/dt-bindings/clock/en7523-clk.h        |  3 +
 .../dt-bindings/reset/airoha,an7583-reset.h   | 65 +++++++++++++++++++
 3 files changed, 88 insertions(+)
 create mode 100644 include/dt-bindings/reset/airoha,an7583-reset.h
Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +1 -0
index eb24a5687639..edecc635807b 100644
@@ -30,6 +30,7 @@ properties:
   compatible:
     items:
       - enum:
+          - airoha,an7583-scu
           - airoha,en7523-scu
           - airoha,en7581-scu
           - econet,en751221-scu

Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml properties: · line 57

Quoted 7 lines
Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +4 -0
@@ -50,12 +51,30 @@ properties:
     description: ID of the controller reset line
     const: 1
 
+  airoha,chip-scu:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: phandle to the Chip SCU providing the registers required
+      for configuring the PCIe related clocks and resets.

This is the clock provider. Clock provider should not be accessing registers of other device to configure its clocks. Either you misrepresented clock hierarchy or devices.

Quoted 3 lines

I did search for DTS to try to understand the big pictuer - nothing, no results, no upstream submission to Linux kernel.

Hi, you can use en7581 as an example as the implementation is exactly the same register wise.

The register for clock and reset for normal system and PCIe are scattered between the "SCU" and "chip SCU" registers (they are 2 different register block, the name is taken from the programming guide)

- Chip SCU provide register access to some clk gate and clk rate
- SCU provide register for reset, PCIe clock, other clock gate and PHY SERDES.

Upcoming and current airoha clock driver all follow this pattern of declaring one of the 2 register and use a sysconf for the other as the 2 register block are tighlty coupled.

There was a similar phandle in another series adding support for pinctrl for econet EN7528.

This phandle is not present for en7581 just because it's hidden by a direct call to the syscon with syscon_regmap_lookup_by_compatible API.

With AN7583 I'm trying to fix this by making it more explicit.

Does this makes the situation more clear?

Signature · 1 line
	Ansuel
#5 lore raw

Re: [PATCH v6 1/3] dt-bindings: clock: airoha: Document support for AN7583 clock

Quoted 62 lines · Christian Marangi
Quoted 39 lines · Krzysztof Kozlowski
Quoted 26 lines · Christian Marangi

Document support for Airoha AN7583 clock. This is based on the EN7523 clock schema with the new requirement of the "airoha,chip-scu".

Add additional binding for additional clock and reset lines.

---
 .../bindings/clock/airoha,en7523-scu.yaml     | 20 ++++++
 include/dt-bindings/clock/en7523-clk.h        |  3 +
 .../dt-bindings/reset/airoha,an7583-reset.h   | 65 +++++++++++++++++++
 3 files changed, 88 insertions(+)
 create mode 100644 include/dt-bindings/reset/airoha,an7583-reset.h
Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +1 -0
index eb24a5687639..edecc635807b 100644
@@ -30,6 +30,7 @@ properties:
   compatible:
     items:
       - enum:
+          - airoha,an7583-scu
           - airoha,en7523-scu
           - airoha,en7581-scu
           - econet,en751221-scu

Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml properties: · line 57

Quoted 7 lines
Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +4 -0
@@ -50,12 +51,30 @@ properties:
     description: ID of the controller reset line
     const: 1
 
+  airoha,chip-scu:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: phandle to the Chip SCU providing the registers required
+      for configuring the PCIe related clocks and resets.

This is the clock provider. Clock provider should not be accessing registers of other device to configure its clocks. Either you misrepresented clock hierarchy or devices.

Quoted 3 lines

I did search for DTS to try to understand the big pictuer - nothing, no results, no upstream submission to Linux kernel.

Hi, you can use en7581 as an example as the implementation is exactly the same register wise.

The register for clock and reset for normal system and PCIe are scattered between the "SCU" and "chip SCU" registers (they are 2 different register block, the name is taken from the programming guide)

- Chip SCU provide register access to some clk gate and clk rate
- SCU provide register for reset, PCIe clock, other clock gate and PHY SERDES.

Upcoming and current airoha clock driver all follow this pattern of declaring one of the 2 register and use a sysconf for the other as the 2 register block are tighlty coupled.

There was a similar phandle in another series adding support for pinctrl for econet EN7528.

Quoted 7 lines

This phandle is not present for en7581 just because it's hidden by a direct call to the syscon with syscon_regmap_lookup_by_compatible API.

With AN7583 I'm trying to fix this by making it more explicit.

Does this makes the situation more clear?

Hi, I would like to send a new revision of this since the clock driver needs to be rebased.

Any hint on this, is the syscon phandle OK after the above explainations?

Signature · 1 line
	Ansuel
#6 lore raw

PATCH v6 2/3 clk: en7523: generalize register clocks function

In reply to Christian Marangi

Airoha AN7583 SoC will use the same logic used by Airoha EN7581 SoC to register clocks. Generalize it to register clocks defined in soc_data.

Add the clocks definition in EN7581 SoC to support this new implementation.

---
 drivers/clk/clk-en7523.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/clk/clk-en7523.c +7 -2
index 5c45aacb6409..924e4f3e36b6 100644
@@ -116,6 +116,7 @@ struct en_rst_data {
 
 struct en_clk_soc_data {
 	u32 num_clocks;
+	const struct en_clk_desc *base_clks;
 	const struct clk_ops pcie_ops;
 	int (*hw_init)(struct platform_device *pdev,
 		       struct clk_hw_onecell_data *clk_data);
@@ -714,12 +715,15 @@ static int en7523_clk_hw_init(struct platform_device *pdev,
 static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
 				   struct regmap *map, void __iomem *base)
 {
+	const struct en_clk_soc_data *soc_data;
 	struct clk_hw *hw;
 	u32 rate;
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(en7581_base_clks); i++) {
-		const struct en_clk_desc *desc = &en7581_base_clks[i];
+	soc_data = device_get_match_data(dev);
+
+	for (i = 0; i < soc_data->num_clocks - 1; i++) {
+		const struct en_clk_desc *desc = &soc_data->base_clks[i];
 		u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg;
 		int err;
 
@@ -1014,6 +1018,7 @@ static const struct en_clk_soc_data en7523_data = {
 };
 
 static const struct en_clk_soc_data en7581_data = {
+	.base_clks = en7581_base_clks,
 	/* We increment num_clocks by 1 to account for additional PCIe clock */
 	.num_clocks = ARRAY_SIZE(en7581_base_clks) + 1,
 	.pcie_ops = {
Signature · 1 line
2.53.0
#7 lore raw

Re: [PATCH v6 2/3] clk: en7523: generalize register clocks function

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [Medium] Fragile loop boundary logic using num_clocks - 1 risks out-of-bounds array access.

Pre-existing issues:
- [High] The PCIe clock gate is registered with an unmanaged API, leading to a Use-After-Free if probe fails.
- [High] Missing spinlock in reset controller update leads to data races and lost writes. --

--- Patch [2]: [PATCH v6 2/3] clk: en7523: generalize register clocks function --- commit c89fd9565e1664803408c338e740e001e5bb4ff0
Author: Christian Marangi <[email protected]>

clk: en7523: generalize register clocks function

This commit generalizes the clock registration logic for the EN7581 SoC so it can be reused by the upcoming AN7583 SoC. It achieves this by moving the base clocks array definition into the soc_data structure.

Quoted 4 lines
drivers/clk/clk-en7523.c +0 -0
index 1ab0e2eca5d32..087ff4568124f 100644

[ ... ]

Quoted 5 lines
drivers/clk/clk-en7523.c +1 -0
@@ -711,12 +712,15 @@ static int en7523_clk_hw_init(struct platform_device *pdev,
 static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
 				   struct regmap *map, void __iomem *base)
 {
+	const struct en_clk_soc_data *soc_data;

drivers/clk/clk-en7523.c static int en7523_clk_hw_init(struct platform_device *pdev, · line 723

Quoted 10 lines
drivers/clk/clk-en7523.c +4 -2
 	struct clk_hw *hw;
 	u32 rate;
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(en7581_base_clks); i++) {
-		const struct en_clk_desc *desc = &en7581_base_clks[i];
+	soc_data = device_get_match_data(dev);
+
+	for (i = 0; i < soc_data->num_clocks - 1; i++) {
+		const struct en_clk_desc *desc = &soc_data->base_clks[i];

[Severity: Medium]
If a future SoC defines a clock provider count (num_clocks) that doesn't exactly equal the number of elements in base_clks plus one, could this loop iterate past the end of the base_clks array?

It seems this loop derives the base_clks array length from soc_data->num_clocks - 1, mathematically conflating the total clock count with the base clock array size.

While reviewing this, I noticed a couple of pre-existing issues in the same file:

drivers/clk/clk-en7523.c:en7523_register_pcie_clk() {
    ...
	cg = devm_kzalloc(dev, sizeof(*cg), GFP_KERNEL);
	if (!cg)
		return NULL;
    ...
	if (clk_hw_register(dev, &cg->hw))
		return NULL;
    ...
}

[Severity: High]
This is a pre-existing issue, but since the clock gate structure is allocated using devres, won't it be automatically freed if probe fails?

Because the clock is registered with the non-managed clk_hw_register() API, if a downstream operation during probe fails, the driver's probe will return an error and trigger devres cleanup. Could this leave a dangling pointer inside the Common Clock Framework and lead to a Use-After-Free?

drivers/clk/clk-en7523.c:en7523_reset_update() {
    ...
	val = readl(addr);
	if (assert)
		val |= BIT(id % RST_NR_PER_BANK);
	else
		val &= ~BIT(id % RST_NR_PER_BANK);
	writel(val, addr);
    ...
}

[Severity: High]
This isn't a bug introduced by this patch, but is it safe to perform this read-modify-write operation on a shared register without a spinlock?

The reset core does not serialize .assert and .deassert operations, so if multiple consumer drivers concurrently assert or deassert resets within the same 32-bit register bank, it seems this unprotected read-modify-write could lead to data races and lost writes.

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
#8 lore raw

Re: [PATCH v6 2/3] clk: en7523: generalize register clocks function

In reply to Christian Marangi

Hi Christian,

Quoted 15 lines · Christian Marangi

Airoha AN7583 SoC will use the same logic used by Airoha EN7581 SoC to register clocks. Generalize it to register clocks defined in soc_data.

Add the clocks definition in EN7581 SoC to support this new implementation.

---
 drivers/clk/clk-en7523.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/clk/clk-en7523.c +0 -0
index 5c45aacb6409..924e4f3e36b6 100644

drivers/clk/clk-en7523.c struct en_rst_data { · line 119

Quoted 4 lines
drivers/clk/clk-en7523.c +1 -0
@@ -116,6 +116,7 @@ struct en_rst_data {
 
 struct en_clk_soc_data {
 	u32 num_clocks;
+	const struct en_clk_desc *base_clks;

What do you think about adding a num_base_clks member as well to avoid the soc_data->num_clocks - 1 below?

Brian

Quoted 32 lines
drivers/clk/clk-en7523.c +6 -2
 	const struct clk_ops pcie_ops;
 	int (*hw_init)(struct platform_device *pdev,
 		       struct clk_hw_onecell_data *clk_data);
@@ -714,12 +715,15 @@ static int en7523_clk_hw_init(struct platform_device *pdev,
 static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
 				   struct regmap *map, void __iomem *base)
 {
+	const struct en_clk_soc_data *soc_data;
 	struct clk_hw *hw;
 	u32 rate;
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(en7581_base_clks); i++) {
-		const struct en_clk_desc *desc = &en7581_base_clks[i];
+	soc_data = device_get_match_data(dev);
+
+	for (i = 0; i < soc_data->num_clocks - 1; i++) {
+		const struct en_clk_desc *desc = &soc_data->base_clks[i];
 		u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg;
 		int err;
 
@@ -1014,6 +1018,7 @@ static const struct en_clk_soc_data en7523_data = {
 };
 
 static const struct en_clk_soc_data en7581_data = {
+	.base_clks = en7581_base_clks,
 	/* We increment num_clocks by 1 to account for additional PCIe clock */
 	.num_clocks = ARRAY_SIZE(en7581_base_clks) + 1,
 	.pcie_ops = {
Signature · 1 line
2.53.0
#9 lore raw

PATCH v6 3/3 clk: en7523: add support for Airoha AN7583 clock

In reply to Christian Marangi

Add support for Airoha AN7583 clock and reset.

Airoha AN7583 SoC have the same register address of EN7581 but implement different bits and additional base clocks. Also reset are different with the introduction of 2 dedicated MDIO line and drop of some reset lines.

---
 drivers/clk/clk-en7523.c | 241 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 241 insertions(+)
drivers/clk/clk-en7523.c +241 -0
index 924e4f3e36b6..f57541ecef84 100644
@@ -10,6 +10,7 @@
 #include <linux/regmap.h>
 #include <linux/reset-controller.h>
 #include <dt-bindings/clock/en7523-clk.h>
+#include <dt-bindings/reset/airoha,an7583-reset.h>
 #include <dt-bindings/reset/airoha,en7523-reset.h>
 #include <dt-bindings/reset/airoha,en7581-reset.h>
 #include <dt-bindings/clock/econet,en751221-scu.h>
@@ -135,6 +136,14 @@ static const u32 crypto_base[] = { 540000000, 480000000 };
 static const u32 emmc7581_base[] = { 200000000, 150000000 };
 /* EN751221 */
 static const u32 gsw751221_base[] = { 500000000, 250000000, 400000000, 200000000 };
+/* AN7583 */
+static const u32 gsw7583_base[] = { 540672000, 270336000, 400000000, 200000000 };
+static const u32 emi7583_base[] = { 540672000, 480000000, 400000000, 300000000 };
+static const u32 bus7583_base[] = { 600000000, 540672000, 480000000, 400000000 };
+static const u32 spi7583_base[] = { 400000000, 12500000 };
+static const u32 npu7583_base[] = { 666000000, 800000000, 720000000, 600000000 };
+static const u32 crypto7583_base[] = { 540672000, 400000000 };
+static const u32 emmc7583_base[] = { 150000000, 200000000 };
 
 static const struct en_clk_desc en7523_base_clks[] = {
 	{
@@ -337,6 +346,138 @@ static const struct en_clk_desc en7581_base_clks[] = {
 	}
 };
 
+static const struct en_clk_desc an7583_base_clks[] = {
+	{
+		.id = EN7523_CLK_GSW,
+		.name = "gsw",
+
+		.base_reg = REG_GSW_CLK_DIV_SEL,
+		.base_bits = 2,
+		.base_shift = 8,
+		.base_values = gsw7583_base,
+		.n_base_values = ARRAY_SIZE(gsw7583_base),
+
+		.div_bits = 3,
+		.div_shift = 0,
+		.div_step = 1,
+		.div_offset = 1,
+	}, {
+		.id = EN7523_CLK_EMI,
+		.name = "emi",
+
+		.base_reg = REG_EMI_CLK_DIV_SEL,
+		.base_bits = 2,
+		.base_shift = 8,
+		.base_values = emi7583_base,
+		.n_base_values = ARRAY_SIZE(emi7583_base),
+
+		.div_bits = 3,
+		.div_shift = 0,
+		.div_step = 1,
+		.div_offset = 1,
+	}, {
+		.id = EN7523_CLK_BUS,
+		.name = "bus",
+
+		.base_reg = REG_BUS_CLK_DIV_SEL,
+		.base_bits = 2,
+		.base_shift = 8,
+		.base_values = bus7583_base,
+		.n_base_values = ARRAY_SIZE(bus7583_base),
+
+		.div_bits = 3,
+		.div_shift = 0,
+		.div_step = 1,
+		.div_offset = 1,
+	}, {
+		.id = EN7523_CLK_SLIC,
+		.name = "slic",
+
+		.base_reg = REG_SPI_CLK_FREQ_SEL,
+		.base_bits = 1,
+		.base_shift = 1,
+		.base_values = slic_base,
+		.n_base_values = ARRAY_SIZE(slic_base),
+
+		.div_reg = REG_SPI_CLK_DIV_SEL,
+		.div_bits = 5,
+		.div_shift = 24,
+		.div_val0 = 20,
+		.div_step = 2,
+	}, {
+		.id = EN7523_CLK_SPI,
+		.name = "spi",
+
+		.base_reg = REG_SPI_CLK_FREQ_SEL,
+		.base_bits = 1,
+		.base_shift = 0,
+		.base_values = spi7583_base,
+		.n_base_values = ARRAY_SIZE(spi7583_base),
+
+		.div_reg = REG_SPI_CLK_DIV_SEL,
+		.div_bits = 5,
+		.div_shift = 8,
+		.div_val0 = 40,
+		.div_step = 2,
+	}, {
+		.id = EN7523_CLK_NPU,
+		.name = "npu",
+
+		.base_reg = REG_NPU_CLK_DIV_SEL,
+		.base_bits = 2,
+		.base_shift = 9,
+		.base_values = npu7583_base,
+		.n_base_values = ARRAY_SIZE(npu7583_base),
+
+		.div_bits = 3,
+		.div_shift = 0,
+		.div_step = 1,
+		.div_offset = 1,
+	}, {
+		.id = EN7523_CLK_CRYPTO,
+		.name = "crypto",
+
+		.base_reg = REG_CRYPTO_CLKSRC2,
+		.base_bits = 1,
+		.base_shift = 0,
+		.base_values = crypto7583_base,
+		.n_base_values = ARRAY_SIZE(crypto7583_base),
+	}, {
+		.id = EN7581_CLK_EMMC,
+		.name = "emmc",
+
+		.base_reg = REG_CRYPTO_CLKSRC2,
+		.base_bits = 1,
+		.base_shift = 13,
+		.base_values = emmc7583_base,
+		.n_base_values = ARRAY_SIZE(emmc7583_base),
+	}, {
+		.id = AN7583_CLK_MDIO0,
+		.name = "mdio0",
+
+		.base_reg = REG_CRYPTO_CLKSRC2,
+
+		.base_value = 25000000,
+
+		.div_bits = 4,
+		.div_shift = 15,
+		.div_step = 1,
+		.div_offset = 1,
+	}, {
+		.id = AN7583_CLK_MDIO1,
+		.name = "mdio1",
+
+		.base_reg = REG_CRYPTO_CLKSRC2,
+
+		.base_value = 25000000,
+
+		.div_bits = 4,
+		.div_shift = 19,
+		.div_step = 1,
+		.div_offset = 1,
+	}
+};
+
 static const u16 en7581_rst_ofs[] = {
 	REG_RST_CTRL2,
 	REG_RST_CTRL1,
@@ -512,6 +653,64 @@ static const u16 en751221_rst_map[] = {
 	[EN751221_USB_PHY_P1_RST]	= 3 * RST_NR_PER_BANK + 7,
 };
 
+static const u16 an7583_rst_map[] = {
+	/* RST_CTRL2 */
+	[AN7583_XPON_PHY_RST]		= 0,
+	[AN7583_GPON_OLT_RST]		= 1,
+	[AN7583_CPU_TIMER2_RST]		= 2,
+	[AN7583_HSUART_RST]		= 3,
+	[AN7583_UART4_RST]		= 4,
+	[AN7583_UART5_RST]		= 5,
+	[AN7583_I2C2_RST]		= 6,
+	[AN7583_XSI_MAC_RST]		= 7,
+	[AN7583_XSI_PHY_RST]		= 8,
+	[AN7583_NPU_RST]		= 9,
+	[AN7583_TRNG_MSTART_RST]	= 12,
+	[AN7583_DUAL_HSI0_RST]		= 13,
+	[AN7583_DUAL_HSI1_RST]		= 14,
+	[AN7583_DUAL_HSI0_MAC_RST]	= 16,
+	[AN7583_DUAL_HSI1_MAC_RST]	= 17,
+	[AN7583_XPON_XFI_RST]		= 18,
+	[AN7583_WDMA_RST]		= 19,
+	[AN7583_WOE0_RST]		= 20,
+	[AN7583_HSDMA_RST]		= 22,
+	[AN7583_TDMA_RST]		= 24,
+	[AN7583_EMMC_RST]		= 25,
+	[AN7583_SOE_RST]		= 26,
+	[AN7583_XFP_MAC_RST]		= 28,
+	[AN7583_MDIO0_RST]		= 30,
+	[AN7583_MDIO1_RST]		= 31,
+	/* RST_CTRL1 */
+	[AN7583_PCM1_ZSI_ISI_RST]	= RST_NR_PER_BANK + 0,
+	[AN7583_FE_PDMA_RST]		= RST_NR_PER_BANK + 1,
+	[AN7583_FE_QDMA_RST]		= RST_NR_PER_BANK + 2,
+	[AN7583_PCM_SPIWP_RST]		= RST_NR_PER_BANK + 4,
+	[AN7583_CRYPTO_RST]		= RST_NR_PER_BANK + 6,
+	[AN7583_TIMER_RST]		= RST_NR_PER_BANK + 8,
+	[AN7583_PCM1_RST]		= RST_NR_PER_BANK + 11,
+	[AN7583_UART_RST]		= RST_NR_PER_BANK + 12,
+	[AN7583_GPIO_RST]		= RST_NR_PER_BANK + 13,
+	[AN7583_GDMA_RST]		= RST_NR_PER_BANK + 14,
+	[AN7583_I2C_MASTER_RST]		= RST_NR_PER_BANK + 16,
+	[AN7583_PCM2_ZSI_ISI_RST]	= RST_NR_PER_BANK + 17,
+	[AN7583_SFC_RST]		= RST_NR_PER_BANK + 18,
+	[AN7583_UART2_RST]		= RST_NR_PER_BANK + 19,
+	[AN7583_GDMP_RST]		= RST_NR_PER_BANK + 20,
+	[AN7583_FE_RST]			= RST_NR_PER_BANK + 21,
+	[AN7583_USB_HOST_P0_RST]	= RST_NR_PER_BANK + 22,
+	[AN7583_GSW_RST]		= RST_NR_PER_BANK + 23,
+	[AN7583_SFC2_PCM_RST]		= RST_NR_PER_BANK + 25,
+	[AN7583_PCIE0_RST]		= RST_NR_PER_BANK + 26,
+	[AN7583_PCIE1_RST]		= RST_NR_PER_BANK + 27,
+	[AN7583_CPU_TIMER_RST]		= RST_NR_PER_BANK + 28,
+	[AN7583_PCIE_HB_RST]		= RST_NR_PER_BANK + 29,
+	[AN7583_XPON_MAC_RST]		= RST_NR_PER_BANK + 31,
+
+	/* RST_PCIC */
+	[AN7583_PCIC_PERSTOUT0_RST]	= 2 * RST_NR_PER_BANK + 29,
+	[AN7583_PCIC_PERSTOUT1_RST]	= 2 * RST_NR_PER_BANK + 26,
+};
+
 static int en7581_reset_register(struct device *dev, void __iomem *base,
 				 const u16 *rst_map, int nr_resets,
 				 const u16 *rst_reg_ofs);
@@ -885,6 +1084,35 @@ static int en7581_clk_hw_init(struct platform_device *pdev,
 				     en7581_rst_ofs);
 }
 
+static int an7583_clk_hw_init(struct platform_device *pdev,
+			      struct clk_hw_onecell_data *clk_data)
+{
+	struct device *dev = &pdev->dev;
+	struct regmap *map;
+	void __iomem *base;
+	u32 val;
+
+	map = syscon_regmap_lookup_by_phandle(dev->of_node, "airoha,chip-scu");
+	if (IS_ERR(map))
+		return PTR_ERR(map);
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	en7581_register_clocks(dev, clk_data, map, base);
+
+	val = readl(base + REG_RST_CTRL1);
+	val |= REG_PCIE_HB_RST;
+	writel(val, base + REG_RST_CTRL1);
+	val &= ~REG_PCIE_HB_RST;
+	writel(val, base + REG_RST_CTRL1);
+
+	return en7581_reset_register(dev, base, an7583_rst_map,
+				     ARRAY_SIZE(an7583_rst_map),
+				     en7581_rst_ofs);
+}
+
 static enum en_hir get_hw_id(void __iomem *np_base)
 {
 	u32 val = FIELD_GET(REG_HIR_MASK, readl(np_base + REG_HIR));
@@ -1029,6 +1257,18 @@ static const struct en_clk_soc_data en7581_data = {
 	.hw_init = en7581_clk_hw_init,
 };
 
+static const struct en_clk_soc_data an7583_data = {
+	.base_clks = an7583_base_clks,
+	/* We increment num_clocks by 1 to account for additional PCIe clock */
+	.num_clocks = ARRAY_SIZE(an7583_base_clks) + 1,
+	.pcie_ops = {
+		.is_enabled = en7581_pci_is_enabled,
+		.enable = en7581_pci_enable,
+		.disable = en7581_pci_disable,
+	},
+	.hw_init = an7583_clk_hw_init,
+};
+
 static const struct en_clk_soc_data en751221_data = {
 	.num_clocks = EN751221_MAX_CLKS,
 	.pcie_ops = {
@@ -1042,6 +1282,7 @@ static const struct en_clk_soc_data en751221_data = {
 static const struct of_device_id of_match_clk_en7523[] = {
 	{ .compatible = "airoha,en7523-scu", .data = &en7523_data },
 	{ .compatible = "airoha,en7581-scu", .data = &en7581_data },
+	{ .compatible = "airoha,an7583-scu", .data = &an7583_data },
 	{ .compatible = "econet,en751221-scu", .data = &en751221_data },
 	{ /* sentinel */ }
 };
Signature · 1 line
2.53.0
#10 lore raw

Re: [PATCH v6 3/3] clk: en7523: add support for Airoha AN7583 clock

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:

New issues:
- [Critical] The macro REG_PCIE_HB_RST is used but never defined, causing a build failure.
- [High] Requesting PCIC resets on AN7583 causes an out-of-bounds read on the en7581_rst_ofs array, leading to undefined hardware behavior or memory corruption.

Pre-existing issues:
- [High] Probe error paths cause a use-after-free by mixing devm_kzalloc with non-devres clk_hw_register() for the PCIe clock.
- [High] Read-modify-write operations on shared registers in the reset and clock controllers lack spinlocks, causing data races and lost writes.
- [High] The clock .disable callback calls usleep_range(), which sleeps while holding an IRQ-disabled spinlock.
--

--- Patch [3]: [PATCH v6 3/3] clk: en7523: add support for Airoha AN7583 clock --- commit e4983d60cb386b35f51bc20a5f0912039bf92780
Author: Christian Marangi <[email protected]>

clk: en7523: add support for Airoha AN7583 clock

Add support for Airoha AN7583 clock and reset.

Airoha AN7583 SoC have the same register address of EN7581 but implement different bits and additional base clocks. Also reset are different with the introduction of 2 dedicated MDIO line and drop of some reset lines.

Quoted 12 lines
drivers/clk/clk-en7523.c +4 -0
index 087ff4568124f..493812c683f53 100644
@@ -505,6 +646,64 @@ static const u16 en751221_rst_map[] = {
 	[EN751221_USB_PHY_P1_RST]	= 3 * RST_NR_PER_BANK + 7,
 };
 
+static const u16 an7583_rst_map[] = {
+	/* RST_CTRL2 */
+	[AN7583_XPON_PHY_RST]		= 0,
+	[AN7583_GPON_OLT_RST]		= 1,

[ ... ]

drivers/clk/clk-en7523.c static const u16 en751221_rst_map[] = { · line 712

Quoted 4 lines
drivers/clk/clk-en7523.c +4 -0
+	/* RST_PCIC */
+	[AN7583_PCIC_PERSTOUT0_RST]	= 2 * RST_NR_PER_BANK + 29,
+	[AN7583_PCIC_PERSTOUT1_RST]	= 2 * RST_NR_PER_BANK + 26,
+};

[Severity: High]
Does this out-of-bounds array access corrupt memory when requesting PCIC resets?

The an7583_rst_map defines these PCIC resets in bank index 2.

When en7581_reset_register() is called later in this patch, it is passed the en7581_rst_ofs array:

	static const u16 en7581_rst_ofs[] = {
		REG_RST_CTRL2,
		REG_RST_CTRL1,
	};

Since en7581_rst_ofs only has 2 elements, when en7523_reset_update() dynamically calculates the bank index via id / RST_NR_PER_BANK, it evaluates to 2. Accessing bank_ofs[2] will read out of bounds.

[ ... ]

Quoted 7 lines
drivers/clk/clk-en7523.c +7 -0
+static int an7583_clk_hw_init(struct platform_device *pdev,
+			      struct clk_hw_onecell_data *clk_data)
+{
+	struct device *dev = &pdev->dev;
+	struct regmap *map;
+	void __iomem *base;
+	u32 val;

drivers/clk/clk-en7523.c static int en7581_clk_hw_init(struct platform_device *pdev, · line 1103

Quoted 10 lines
drivers/clk/clk-en7523.c +10 -0
+
+	map = syscon_regmap_lookup_by_phandle(dev->of_node, "airoha,chip-scu");
+	if (IS_ERR(map))
+		return PTR_ERR(map);
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	en7581_register_clocks(dev, clk_data, map, base);

[Severity: High]
This isn't a bug introduced by this patch, but does the probe error path leave us with a use-after-free for the PCIe clock?

In en7523_register_pcie_clk() which is called by en7581_register_clocks(), the clk_hw structure is allocated via devm_kzalloc(), but registered with the non-devres clk_hw_register():

	cg = devm_kzalloc(dev, sizeof(*cg), GFP_KERNEL);
	...
	if (clk_hw_register(dev, &cg->hw))

If a subsequent initialization step fails in en7523_clk_probe() (like hw_init returning an error), the driver core automatically frees the memory via devres, but the clock framework retains dangling pointers to the freed clk_hw.

drivers/clk/clk-en7523.c static int en7581_clk_hw_init(struct platform_device *pdev, · line 1106

Quoted 3 lines
drivers/clk/clk-en7523.c +3 -0
+
+	val = readl(base + REG_RST_CTRL1);
+	val |= REG_PCIE_HB_RST;

[Severity: Critical]
Will this break the build due to an undefined macro?

The REG_PCIE_HB_RST macro is not defined anywhere. The existing code seems to use REG_RESET_CONTROL_PCIEHB for this bit instead.

[Severity: High]
This is a pre-existing issue, but could this unlocked read-modify-write race with the reset framework?

en7523_pci_prepare() modifies REG_RESET_CONTROL1 (0x834) without any locks:

	val = readl(np_base + REG_RESET_CONTROL1);
	mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
	       REG_RESET_CONTROL_PCIEHB;
	writel(val & ~mask, np_base + REG_RESET_CONTROL1);

Concurrently, en7523_reset_update() performs an unlocked read-modify-write on the same register (REG_RST_CTRL1 is also 0x834):

	val = readl(addr);
	if (assert)
		val |= BIT(id % RST_NR_PER_BANK);
	...
	writel(val, addr);

Since .prepare() runs in process context and resets can be triggered by other probing devices concurrently, this seems likely to cause lost writes.

Quoted 8 lines
drivers/clk/clk-en7523.c +8 -0
+	writel(val, base + REG_RST_CTRL1);
+	val &= ~REG_PCIE_HB_RST;
+	writel(val, base + REG_RST_CTRL1);
+
+	return en7581_reset_register(dev, base, an7583_rst_map,
+				     ARRAY_SIZE(an7583_rst_map),
+				     en7581_rst_ofs);
+}

[ ... ]

drivers/clk/clk-en7523.c static const struct en_clk_soc_data en7581_data = { · line 1268

Quoted 9 lines
drivers/clk/clk-en7523.c +9 -0
+static const struct en_clk_soc_data an7583_data = {
+	.base_clks = an7583_base_clks,
+	/* We increment num_clocks by 1 to account for additional PCIe clock */
+	.num_clocks = ARRAY_SIZE(an7583_base_clks) + 1,
+	.pcie_ops = {
+		.is_enabled = en7581_pci_is_enabled,
+		.enable = en7581_pci_enable,
+		.disable = en7581_pci_disable,
+	},

[Severity: High]
This isn't a bug introduced by this patch, but does mapping en7581_pci_disable to the .disable callback result in sleeping while in an atomic context?

The core clock framework invokes .disable callbacks with the enable_lock spinlock held and hardware interrupts disabled.

However, en7581_pci_disable() explicitly yields and sleeps:

	writel(val & ~mask, np_base + REG_PCI_CONTROL);
	usleep_range(1000, 2000);

Could this cause a scheduling while atomic panic when the PCIe clock is disabled?

Quoted 2 lines
drivers/clk/clk-en7523.c +2 -0
+	.hw_init = an7583_clk_hw_init,
+};
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=3
#11 lore raw

Re: [PATCH v6 3/3] clk: en7523: add support for Airoha AN7583 clock

Quoted 6 lines · On Wed, Aug 19, 2026 at 10:27:42PM +0000, [email protected] wrote:

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:

New issues:
- [Critical] The macro REG_PCIE_HB_RST is used but never defined, causing a build failure.
- [High] Requesting PCIC resets on AN7583 causes an out-of-bounds read on the en7581_rst_ofs array, leading to undefined hardware behavior or memory corruption.

For reference, it seems the bot applied the patch to the wrong branch. The reported problems from the bot are not valid as those changes were introduced by the last 2 patch present in linux-next and clk-next.

Code was compiled and tested with those 2 changes included.

Quoted 160 lines

Pre-existing issues:
- [High] Probe error paths cause a use-after-free by mixing devm_kzalloc with non-devres clk_hw_register() for the PCIe clock.
- [High] Read-modify-write operations on shared registers in the reset and clock controllers lack spinlocks, causing data races and lost writes.
- [High] The clock .disable callback calls usleep_range(), which sleeps while holding an IRQ-disabled spinlock.
--

--- Patch [3]: [PATCH v6 3/3] clk: en7523: add support for Airoha AN7583 clock --- commit e4983d60cb386b35f51bc20a5f0912039bf92780
Author: Christian Marangi <[email protected]>

clk: en7523: add support for Airoha AN7583 clock

Add support for Airoha AN7583 clock and reset.

Airoha AN7583 SoC have the same register address of EN7581 but implement different bits and additional base clocks. Also reset are different with the introduction of 2 dedicated MDIO line and drop of some reset lines.

Quoted 12 lines
drivers/clk/clk-en7523.c +4 -0
index 087ff4568124f..493812c683f53 100644
@@ -505,6 +646,64 @@ static const u16 en751221_rst_map[] = {
 	[EN751221_USB_PHY_P1_RST]	= 3 * RST_NR_PER_BANK + 7,
 };
 
+static const u16 an7583_rst_map[] = {
+	/* RST_CTRL2 */
+	[AN7583_XPON_PHY_RST]		= 0,
+	[AN7583_GPON_OLT_RST]		= 1,

[ ... ]

drivers/clk/clk-en7523.c static const u16 en751221_rst_map[] = { · line 712

Quoted 4 lines
drivers/clk/clk-en7523.c +4 -0
+	/* RST_PCIC */
+	[AN7583_PCIC_PERSTOUT0_RST]	= 2 * RST_NR_PER_BANK + 29,
+	[AN7583_PCIC_PERSTOUT1_RST]	= 2 * RST_NR_PER_BANK + 26,
+};

[Severity: High]
Does this out-of-bounds array access corrupt memory when requesting PCIC resets?

The an7583_rst_map defines these PCIC resets in bank index 2.

When en7581_reset_register() is called later in this patch, it is passed the en7581_rst_ofs array:

	static const u16 en7581_rst_ofs[] = {
		REG_RST_CTRL2,
		REG_RST_CTRL1,
	};

Since en7581_rst_ofs only has 2 elements, when en7523_reset_update() dynamically calculates the bank index via id / RST_NR_PER_BANK, it evaluates to 2. Accessing bank_ofs[2] will read out of bounds.

[ ... ]

Quoted 7 lines
drivers/clk/clk-en7523.c +7 -0
+static int an7583_clk_hw_init(struct platform_device *pdev,
+			      struct clk_hw_onecell_data *clk_data)
+{
+	struct device *dev = &pdev->dev;
+	struct regmap *map;
+	void __iomem *base;
+	u32 val;

drivers/clk/clk-en7523.c static int en7581_clk_hw_init(struct platform_device *pdev, · line 1103

Quoted 10 lines
drivers/clk/clk-en7523.c +10 -0
+
+	map = syscon_regmap_lookup_by_phandle(dev->of_node, "airoha,chip-scu");
+	if (IS_ERR(map))
+		return PTR_ERR(map);
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	en7581_register_clocks(dev, clk_data, map, base);

[Severity: High]
This isn't a bug introduced by this patch, but does the probe error path leave us with a use-after-free for the PCIe clock?

In en7523_register_pcie_clk() which is called by en7581_register_clocks(), the clk_hw structure is allocated via devm_kzalloc(), but registered with the non-devres clk_hw_register():

	cg = devm_kzalloc(dev, sizeof(*cg), GFP_KERNEL);
	...
	if (clk_hw_register(dev, &cg->hw))

If a subsequent initialization step fails in en7523_clk_probe() (like hw_init returning an error), the driver core automatically frees the memory via devres, but the clock framework retains dangling pointers to the freed clk_hw.

drivers/clk/clk-en7523.c static int en7581_clk_hw_init(struct platform_device *pdev, · line 1106

Quoted 3 lines
drivers/clk/clk-en7523.c +3 -0
+
+	val = readl(base + REG_RST_CTRL1);
+	val |= REG_PCIE_HB_RST;

[Severity: Critical]
Will this break the build due to an undefined macro?

The REG_PCIE_HB_RST macro is not defined anywhere. The existing code seems to use REG_RESET_CONTROL_PCIEHB for this bit instead.

[Severity: High]
This is a pre-existing issue, but could this unlocked read-modify-write race with the reset framework?

en7523_pci_prepare() modifies REG_RESET_CONTROL1 (0x834) without any locks:

	val = readl(np_base + REG_RESET_CONTROL1);
	mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
	       REG_RESET_CONTROL_PCIEHB;
	writel(val & ~mask, np_base + REG_RESET_CONTROL1);

Concurrently, en7523_reset_update() performs an unlocked read-modify-write on the same register (REG_RST_CTRL1 is also 0x834):

	val = readl(addr);
	if (assert)
		val |= BIT(id % RST_NR_PER_BANK);
	...
	writel(val, addr);

Since .prepare() runs in process context and resets can be triggered by other probing devices concurrently, this seems likely to cause lost writes.

Quoted 8 lines
drivers/clk/clk-en7523.c +8 -0
+	writel(val, base + REG_RST_CTRL1);
+	val &= ~REG_PCIE_HB_RST;
+	writel(val, base + REG_RST_CTRL1);
+
+	return en7581_reset_register(dev, base, an7583_rst_map,
+				     ARRAY_SIZE(an7583_rst_map),
+				     en7581_rst_ofs);
+}

[ ... ]

drivers/clk/clk-en7523.c static const struct en_clk_soc_data en7581_data = { · line 1268

Quoted 9 lines
drivers/clk/clk-en7523.c +9 -0
+static const struct en_clk_soc_data an7583_data = {
+	.base_clks = an7583_base_clks,
+	/* We increment num_clocks by 1 to account for additional PCIe clock */
+	.num_clocks = ARRAY_SIZE(an7583_base_clks) + 1,
+	.pcie_ops = {
+		.is_enabled = en7581_pci_is_enabled,
+		.enable = en7581_pci_enable,
+		.disable = en7581_pci_disable,
+	},

[Severity: High]
This isn't a bug introduced by this patch, but does mapping en7581_pci_disable to the .disable callback result in sleeping while in an atomic context?

The core clock framework invokes .disable callbacks with the enable_lock spinlock held and hardware interrupts disabled.

However, en7581_pci_disable() explicitly yields and sleeps:

	writel(val & ~mask, np_base + REG_PCI_CONTROL);
	usleep_range(1000, 2000);

Could this cause a scheduling while atomic panic when the PCIe clock is disabled?

Quoted 2 lines
drivers/clk/clk-en7523.c +2 -0
+	.hw_init = an7583_clk_hw_init,
+};
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=3
Signature · 1 line
	Ansuel