Devicetree
 help / color / mirror / Atom feed
* [PATCH] dt-bindings: gpio: meson-axg: Fix whitespace issue
From: Jun Yan @ 2026-05-24 15:49 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Kevin Hilman,
	Jerome Brunet, Martin Blumenstingl
  Cc: Jun Yan, linux-gpio, devicetree, linux-arm-kernel, linux-amlogic,
	linux-kernel

Clean up whitespace misalignment in meson-axg-gpio.h

Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
---
 include/dt-bindings/gpio/meson-axg-gpio.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/dt-bindings/gpio/meson-axg-gpio.h b/include/dt-bindings/gpio/meson-axg-gpio.h
index 25bb1fffa97a..a0d42bcd9bd3 100644
--- a/include/dt-bindings/gpio/meson-axg-gpio.h
+++ b/include/dt-bindings/gpio/meson-axg-gpio.h
@@ -23,7 +23,7 @@
 #define GPIOAO_11	11
 #define GPIOAO_12	12
 #define GPIOAO_13	13
-#define GPIO_TEST_N 14
+#define GPIO_TEST_N	14
 
 /* Second GPIO chip */
 #define GPIOZ_0		0
@@ -52,7 +52,7 @@
 #define BOOT_12		23
 #define BOOT_13		24
 #define BOOT_14		25
-#define GPIOA_0	    26
+#define GPIOA_0		26
 #define GPIOA_1		27
 #define GPIOA_2		28
 #define GPIOA_3		29
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH v8 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema
From: Bryan O'Donoghue @ 2026-05-24 15:37 UTC (permalink / raw)
  To: sashiko-reviews
  Cc: neil.armstrong, robh, devicetree, linux-phy, olteanv, vkoul,
	conor+dt
In-Reply-To: <20260523030420.045501F000E9@smtp.kernel.org>

On 23/05/2026 04:04, sashiko-bot@kernel.org wrote:
>> +  vdda-0p9-supply:
>> +    description: Phandle to a 0.9V regulator supply to a PHY.
> [Severity: Low]
> Does this property name mismatch the actual hardware supply voltage for the
> x1e80100 platform?

Yes and I'm realising I forgot to make some small changes Krzysztof left 
@v3.

----
bod

^ permalink raw reply

* Re: [PATCH v5 4/5] leds: is31fl32xx: Add powerdown pin to exit hardware shutdown mode
From: Jun Yan @ 2026-05-24 15:28 UTC (permalink / raw)
  To: lee
  Cc: conor+dt, daniel, devicetree, jerrysteve1101, krzk+dt,
	linux-kernel, linux-leds, luccafachinetti, pzalewski, robh
In-Reply-To: <20260520141259.GD2767592@google.com>

> On Fri, 08 May 2026, Jun Yan wrote:
> 
> > The IS31FL32XX series features an SDB shutdown pin.
> > Driving it low (active low) places the chip into hardware shutdown
> > mode for power saving, while all register contents are preserved
> > and registers are not reset.
> > 
> > Drive the pin logic low during probe() to exit hardware shutdown
> > mode.
> > 
> > Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
> > ---
> >  drivers/leds/leds-is31fl32xx.c | 7 +++++++
> >  1 file changed, 7 insertions(+)
> > 
> > diff --git "a/drivers/leds/leds-is31fl32xx.c" "b/drivers/leds/leds-is31fl32xx.c"
> > index fe07acbb103a..57d779e07a62 100644
> > --- "a/drivers/leds/leds-is31fl32xx.c"
> > +++ "b/drivers/leds/leds-is31fl32xx.c"
> > @@ -10,6 +10,7 @@
> >   */
> >  
> >  #include <linux/device.h>
> > +#include <linux/gpio.h>
> 
> <linux/gpio/consumer.h>?

Got it.

> 
> >  #include <linux/i2c.h>
> >  #include <linux/kernel.h>
> >  #include <linux/leds.h>
> > @@ -60,6 +61,7 @@ struct is31fl32xx_led_data {
> >  struct is31fl32xx_priv {
> >  	const struct is31fl32xx_chipdef *cdef;
> >  	struct i2c_client *client;
> > +	struct gpio_desc *powerdown_gpio;
> >  	unsigned int num_leds;
> >  	struct is31fl32xx_led_data leds[];
> >  };
> > @@ -421,6 +423,11 @@ static int is31fl32xx_parse_dt(struct device *dev,
> >  	const struct is31fl32xx_chipdef *cdef = priv->cdef;
> >  	int ret = 0;
> >  
> > +	priv->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_LOW);
> > +	if (IS_ERR(priv->powerdown_gpio))
> > +		return dev_err_probe(dev, PTR_ERR(priv->powerdown_gpio),
> > +				"Failed to get powerdown gpio\n");
> > +
> 
> "Failed to get 'powerdown' GPIO".
> 
> Shows that powerdown is the name of the pin and correctly capitalises
> GPIO.

Okay, I'll fix this.

> 
> >  	if ((cdef->output_frequency_setting_reg != IS31FL32XX_REG_NONE) &&
> >  	    of_property_read_bool(dev_of_node(dev), "issi,22khz-pwm")) {
> >  
> > -- 
> > 2.53.0
> > 
> > 
> 
> -- 
> Lee Jones


^ permalink raw reply

* Re: [PATCH v4] dt-bindings: clock: via,vt8500: Convert to DT Schema
From: sashiko-bot @ 2026-05-24 15:23 UTC (permalink / raw)
  To: Udaya Kiran Challa; +Cc: robh, conor+dt, devicetree
In-Reply-To: <20260524151110.21277-1-challauday369@gmail.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] The `patternProperties` regex enforces strictly lowercase node names, inadvertently rejecting standard `fixed-clock` nodes unless they violate DT naming conventions by including uppercase letters to bypass validation.
- [Medium] The patch defines a new schema for `via,vt8500-pmc` but fails to delete the existing legacy text binding for the same compatible string.
- [Low] The `divisor-mask` property lacks a `dependentRequired` constraint to enforce that it can only be used when `divisor-reg` is also present.
--

commit f63cd62ab71a54ca61f786bce852286bf98a7852
Author: Udaya Kiran Challa <challauday369@gmail.com>

dt-bindings: clock: via,vt8500: Convert to DT Schema
    
Convert the VIA/Wondermedia VT8500 and Wondermedia WM8xxx series SoCs clock
controller binding from the legacy text format to DT schema.

> diff --git a/Documentation/devicetree/bindings/clock/via,vt8500-clock.yaml b/Documentation/devicetree/bindings/clock/via,vt8500-clock.yaml
> new file mode 100644
> index 0000000000000..51a68df6c2f30
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/via,vt8500-clock.yaml

[Severity: Medium]
Should this patch also delete the existing text binding for this compatible
located at Documentation/devicetree/bindings/arm/vt8500/via,vt8500-pmc.txt?
Leaving the old text binding intact causes duplicate and fragmented
documentation for the exact same compatible string.

[ ... ]
> +    patternProperties:
> +      "^[a-z0-9-]+(@[0-9a-f]+)?$":
> +        type: object
> +
> +        properties:
> +          compatible:
> +            enum:
> +              - via,vt8500-pll-clock
> +              - wm,wm8650-pll-clock
> +              - wm,wm8750-pll-clock
> +              - wm,wm8850-pll-clock
> +              - via,vt8500-device-clock

[Severity: High]
Does this regex unintentionally restrict compliant lowercase node names?

Any standard child node with a compliant lowercase name (like "ref24") will
match this pattern and be strictly restricted to the compatibles above, failing
if it contains properties like clock-frequency.

It appears the fixed-clock examples in this patch only pass validation because
their node names include uppercase letters (e.g., "ref24M"), which evades the
regex entirely and falls through to additionalProperties.

[ ... ]
> +          divisor-reg:
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            description:
> +              Offset of the clock divisor register within the PMC
> +              register space.
> +
> +          divisor-mask:
> +            $ref: /schemas/types.yaml#/definitions/uint32
> +            default: 0x1f
> +            description:
> +              Bitmask describing the divisor field inside divisor-reg.
> +
> +        dependentRequired:
> +          enable-reg:
> +            - enable-bit
> +
> +          enable-bit:
> +            - enable-reg

[Severity: Low]
Should this section also include a constraint to enforce that divisor-mask
can only be used when divisor-reg is present? The legacy text binding indicates
the mask is semantically tied to the divisor register.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260524151110.21277-1-challauday369@gmail.com?part=1

^ permalink raw reply

* Re: [PATCH v7 1/9] arm64: dts: lx2160a-rev2: extend 32-bit, and add 64-bit pci regions
From: sashiko-bot @ 2026-05-24 15:13 UTC (permalink / raw)
  To: Josua Mayer; +Cc: conor+dt, robh, Frank.Li, devicetree, imx
In-Reply-To: <20260524-lx2160-pci-v7-1-09370c23b952@solid-run.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Expanding the 32-bit PCI outbound window to 3GB causes it to overlap with the inbound system memory address space, breaking DMA.
- [High] The introduction of the 64-bit PCI memory range causes existing U-Boot bootloaders to fail device tree patching, breaking MSI and IOMMU.
--

commit a80e2e3f97808fdad781240469c5e07e019191e9
Author: Josua Mayer <josua@solid-run.com>

arm64: dts: lx2160a-rev2: extend 32-bit, and add 64-bit pci regions

This commit extends the 32-bit PCIe memory regions to 3GB and adds 64-bit
PCIe memory regions for LX2160A rev2. This allows allocation of large BARs
requested by graphics processors or AI accelerators.

> [4] pci bootloaderp atching related errors with IORESOURCE_MEM_64 flag:
> [    0.967809] layerscape-pcie 3800000.pcie: host bridge /soc/pcie@3800000 ranges:
> [    0.967830] layerscape-pcie 3800000.pcie:      MEM 0xa400000000..0xa7ffffffff -> 0xa400000000
> [    0.967842] layerscape-pcie 3800000.pcie:      MEM 0xa040000000..0xa0ffffffff -> 0x0040000000
> [    0.967849] layerscape-pcie 3800000.pcie:       IO 0xa000010000..0xa00001ffff -> 0x0000000000
> [    1.169315] pci 0000:01:00.0: [8086:1572] type 00 class 0x020000 PCIe Endpoint
> [    1.169733] pci 0000:01:00.0: BAR 0 [mem 0x00000000-0x00ffffff 64bit pref]
> [    1.169771] pci 0000:01:00.0: BAR 3 [mem 0x00000000-0x00007fff 64bit pref]
> [    1.169796] pci 0000:01:00.0: ROM [mem 0x00000000-0x0007ffff pref]
> [    1.173389] OF: /soc/pcie@3800000: no msi-map translation for id 0x100 on (null)
> [    1.173515] OF: /soc/pcie@3800000: no iommu-map translation for id 0x100 on (null)

[Severity: High]
Does adding the 64-bit PCI memory range cause existing U-Boot bootloaders to
fail device tree patching?

When U-Boot encounters the 64-bit range, it appears fdt_fixup_pcie() aborts
and fails to append the msi-map and iommu-map properties.

Without iommu-map, the kernel will not attach the SMMU to the PCIe devices.
Without msi-map, the kernel cannot translate PCIe Requester IDs to ITS
Device IDs, which breaks MSI/MSI-X allocations.

Could this prevent devices like NVMe drives from initializing and break
compatibility with existing deployed bootloaders?

> diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi
> index f54005e37924b..db1ebee53f6f0 100644
> --- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi
> +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi
> @@ -14,8 +14,9 @@ &pcie1 {
>  	      0x80 0x00000000 0x0 0x00002000>; /* configuration space */
>  	reg-names = "regs", "config";
>  
> -	ranges = <0x81000000 0x0 0x00000000 0x80 0x00010000 0x0 0x00010000
> -		  0x82000000 0x0 0x40000000 0x80 0x40000000 0x0 0x40000000>;
> +	ranges = <0x81000000 0x00 0x00000000 0x80 0x00010000 0x00 0x00010000>, /* 16-Bit IO Window */
> +		 <0x82000000 0x00 0x40000000 0x80 0x40000000 0x00 0xc0000000>, /* 32-Bit - non-prefetchable */
> +		 <0xC3000000 0x84 0x00000000 0x84 0x00000000 0x04 0x00000000>; /* 64-Bit - prefetchable - 16GB */

[Severity: High]
Does expanding the 32-bit PCI outbound window to 3GB (0xc0000000) cause it to
overlap with inbound system memory?

System memory starts at physical address 0x80000000. Since there isn't a
dma-ranges property mapping inbound DMA to a different bus address, system
memory uses a 1:1 mapping, meaning inbound DMA targets 0x80000000 and above.

If a PCIe device requests a large 32-bit BAR, the kernel might allocate it
within this 0x40000000-0xffffffff range. This causes the Root Port's
downstream bridge Memory Limit register to be programmed to a value >=
0x80000000.

A Root Port won't forward upstream memory transactions if the address falls
within its programmed downstream window, as it assumes it is peer-to-peer
traffic.

Could this intercept endpoint DMA targeting system memory in the overlapped
range and cause system hangs?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260524-lx2160-pci-v7-0-09370c23b952@solid-run.com?part=1

^ permalink raw reply

* [PATCH v4] dt-bindings: clock: via,vt8500: Convert to DT Schema
From: Udaya Kiran Challa @ 2026-05-24 15:10 UTC (permalink / raw)
  To: mturquette, sboyd, robh, krzk+dt, conor+dt
  Cc: skhan, me, linux-rtc, devicetree, linux-kernel,
	Udaya Kiran Challa

Convert the VIA/Wondermedia VT8500 and Wondermedia WM8xxx series SoCs clock
controller binding from the legacy text format to DT schema.

Signed-off-by: Udaya Kiran Challa <challauday369@gmail.com>
---
Changelog:
Changes since v3
- Add schema select matching for via,vt8500-pmc
- Allow hyphen in node names under patternProperties
- Add dependentRequired validation for enable-reg/enable-bit
- Fix example validation against PMC schema

Link to v3:https://lore.kernel.org/all/20260524111813.39810-1-challauday369@gmail.com/

Changes since v2:
- Drop redundant description for clocks
- Disable reg property for device clocks
- Fix schema hierarchy to match actual DTS structure

Link to v2:https://lore.kernel.org/all/20260521170810.19702-1-challauday369@gmail.com/

Changes since v1:
- Add default value for divisor-mask
- Add required properties compatible and model
- Fix example node name
- Update example size cells and reg value

Link to v1:https://lore.kernel.org/all/20260520025131.17772-1-challauday369@gmail.com/
---
 .../bindings/clock/via,vt8500-clock.yaml      | 209 ++++++++++++++++++
 .../devicetree/bindings/clock/vt8500.txt      |  74 -------
 2 files changed, 209 insertions(+), 74 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/via,vt8500-clock.yaml
 delete mode 100644 Documentation/devicetree/bindings/clock/vt8500.txt

diff --git a/Documentation/devicetree/bindings/clock/via,vt8500-clock.yaml b/Documentation/devicetree/bindings/clock/via,vt8500-clock.yaml
new file mode 100644
index 000000000000..51a68df6c2f3
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/via,vt8500-clock.yaml
@@ -0,0 +1,209 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/via,vt8500-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: VIA/Wondermedia VT8500 Clock Controller
+
+maintainers:
+  - Michael Turquette <mturquette@baylibre.com>
+  - Stephen Boyd <sboyd@kernel.org>
+
+description:
+  Clock controller bindings for VIA/Wondermedia VT8500 and Wondermedia WM8xxx
+  series SoCs.
+
+select:
+  properties:
+    compatible:
+      const: via,vt8500-pmc
+
+  required:
+    - compatible
+
+properties:
+  compatible:
+    const: via,vt8500-pmc
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    type: object
+    additionalProperties: true
+
+    properties:
+      "#address-cells":
+        const: 1
+
+      "#size-cells":
+        const: 0
+
+    required:
+      - "#address-cells"
+      - "#size-cells"
+
+    patternProperties:
+      "^[a-z0-9-]+(@[0-9a-f]+)?$":
+        type: object
+
+        properties:
+          compatible:
+            enum:
+              - via,vt8500-pll-clock
+              - wm,wm8650-pll-clock
+              - wm,wm8750-pll-clock
+              - wm,wm8850-pll-clock
+              - via,vt8500-device-clock
+
+          reg:
+            maxItems: 1
+            description:
+              Offset of the PLL register within the PMC register space.
+
+          clocks:
+            maxItems: 1
+
+          "#clock-cells":
+            const: 0
+
+          enable-reg:
+            $ref: /schemas/types.yaml#/definitions/uint32
+            description:
+              Offset of the clock enable register within the PMC
+              register space.
+
+          enable-bit:
+            $ref: /schemas/types.yaml#/definitions/uint32
+            maximum: 31
+            description:
+              Bit index controlling clock enable.
+
+          divisor-reg:
+            $ref: /schemas/types.yaml#/definitions/uint32
+            description:
+              Offset of the clock divisor register within the PMC
+              register space.
+
+          divisor-mask:
+            $ref: /schemas/types.yaml#/definitions/uint32
+            default: 0x1f
+            description:
+              Bitmask describing the divisor field inside divisor-reg.
+
+        dependentRequired:
+          enable-reg:
+            - enable-bit
+
+          enable-bit:
+            - enable-reg
+
+        required:
+          - compatible
+          - "#clock-cells"
+
+        allOf:
+          - if:
+              properties:
+                compatible:
+                  enum:
+                    - via,vt8500-pll-clock
+                    - wm,wm8650-pll-clock
+                    - wm,wm8750-pll-clock
+                    - wm,wm8850-pll-clock
+            then:
+              required:
+                - reg
+                - clocks
+
+          - if:
+              properties:
+                compatible:
+                  const: via,vt8500-device-clock
+            then:
+              properties:
+                reg: false
+
+              required:
+                - clocks
+
+              anyOf:
+                - required:
+                    - enable-reg
+                    - enable-bit
+
+                - required:
+                    - divisor-reg
+
+        additionalProperties: false
+
+required:
+  - compatible
+  - reg
+  - clocks
+
+additionalProperties: false
+
+examples:
+  - |
+    pmc@d8130000 {
+        compatible = "via,vt8500-pmc";
+        reg = <0xd8130000 0x1000>;
+
+        clocks {
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            ref24: ref24M {
+                compatible = "fixed-clock";
+                #clock-cells = <0>;
+                clock-frequency = <24000000>;
+            };
+
+            ref25: ref25M {
+                compatible = "fixed-clock";
+                #clock-cells = <0>;
+                clock-frequency = <25000000>;
+            };
+
+            plla: clock@200 {
+                compatible = "wm,wm8650-pll-clock";
+                #clock-cells = <0>;
+                clocks = <&ref25>;
+                reg = <0x200>;
+            };
+
+            pllb: clock@204 {
+                compatible = "wm,wm8650-pll-clock";
+                #clock-cells = <0>;
+                clocks = <&ref25>;
+                reg = <0x204>;
+            };
+
+            clkarm: arm {
+                compatible = "via,vt8500-device-clock";
+                #clock-cells = <0>;
+                clocks = <&plla>;
+                divisor-reg = <0x300>;
+            };
+
+            clkuart0: uart0 {
+                compatible = "via,vt8500-device-clock";
+                #clock-cells = <0>;
+                clocks = <&ref24>;
+                enable-reg = <0x250>;
+                enable-bit = <1>;
+            };
+
+            clksdhc: sdhc {
+                compatible = "via,vt8500-device-clock";
+                #clock-cells = <0>;
+                clocks = <&pllb>;
+                divisor-reg = <0x328>;
+                divisor-mask = <0x3f>;
+                enable-reg = <0x254>;
+                enable-bit = <18>;
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/clock/vt8500.txt b/Documentation/devicetree/bindings/clock/vt8500.txt
deleted file mode 100644
index 91d71cc0314a..000000000000
--- a/Documentation/devicetree/bindings/clock/vt8500.txt
+++ /dev/null
@@ -1,74 +0,0 @@
-Device Tree Clock bindings for arch-vt8500
-
-This binding uses the common clock binding[1].
-
-[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
-
-Required properties:
-- compatible : shall be one of the following:
-	"via,vt8500-pll-clock" - for a VT8500/WM8505 PLL clock
-	"wm,wm8650-pll-clock" - for a WM8650 PLL clock
-	"wm,wm8750-pll-clock" - for a WM8750 PLL clock
-	"wm,wm8850-pll-clock" - for a WM8850 PLL clock
-	"via,vt8500-device-clock" - for a VT/WM device clock
-
-Required properties for PLL clocks:
-- reg : shall be the control register offset from PMC base for the pll clock.
-- clocks : shall be the input parent clock phandle for the clock. This should
-	be the reference clock.
-- #clock-cells : from common clock binding; shall be set to 0.
-
-Required properties for device clocks:
-- clocks : shall be the input parent clock phandle for the clock. This should
-	be a pll output.
-- #clock-cells : from common clock binding; shall be set to 0.
-
-
-Device Clocks
-
-Device clocks are required to have one or both of the following sets of
-properties:
-
-
-Gated device clocks:
-
-Required properties:
-- enable-reg : shall be the register offset from PMC base for the enable
-	register.
-- enable-bit : shall be the bit within enable-reg to enable/disable the clock.
-
-
-Divisor device clocks:
-
-Required property:
-- divisor-reg : shall be the register offset from PMC base for the divisor
-	register.
-Optional property:
-- divisor-mask : shall be the mask for the divisor register. Defaults to 0x1f
-	if not specified.
-
-
-For example:
-
-ref25: ref25M {
-	#clock-cells = <0>;
-	compatible = "fixed-clock";
-	clock-frequency = <25000000>;
-};
-
-plla: plla {
-	#clock-cells = <0>;
-	compatible = "wm,wm8650-pll-clock";
-	clocks = <&ref25>;
-	reg = <0x200>;
-};
-
-sdhc: sdhc {
-	#clock-cells = <0>;
-	compatible = "via,vt8500-device-clock";
-	clocks = <&pllb>;
-	divisor-reg = <0x328>;
-	divisor-mask = <0x3f>;
-	enable-reg = <0x254>;
-	enable-bit = <18>;
-};
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH v7 1/9] arm64: dts: lx2160a-rev2: extend 32-bit, and add 64-bit pci regions
From: Josua Mayer @ 2026-05-24 15:03 UTC (permalink / raw)
  To: Shawn Guo, Li Yang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Rob Herring, Krzysztof Kozlowski, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
  Cc: Yazan Shhady, Jon Nettleton, linux-arm-kernel@lists.infradead.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	imx@lists.linux.dev
In-Reply-To: <20260524-lx2160-pci-v7-1-09370c23b952@solid-run.com>

Am 24.05.26 um 16:54 schrieb Josua Mayer:
> LX2160 SoC pci-e controller supports 64-bit memory regions up to 16GB,
> 32-bit regions up to 3GB and 16-bit regions up to 64k.
>
> For each pci-e controller:
> - extend the existing 32-bit regions to 3GB size
> - add 64-bit region
> See [1] and [2] for boot messages showing ranges before and after.
>
> On LX2160A Silicon revision 1, the pcie driver fails to program atu for
> ranges larger than 4GB [3]. Therefore changes are limited to revision 2.
>
> Similar memory allocation with similar flags was tested with UEFI and ACPI
> on pcie3 and pcie5, on a variety of nxp vendor fork versions.
>
> This patch was tested on Linux v7.1-rc1 and u-boot, with two pcie cards:
> - pcie5: Radeon Pro WX2100
> - pcie3: ADATA NVME
>
> This fixes allocation of large, and 64-bit BARs as requested by many pci
> cards - especially graphics processors or AI accelerators, e.g.:
>
> [    2.941187] pci 0000:01:00.0: BAR 0: no space for [mem size 0x200000000 64bit pref]
> [    2.948834] pci 0000:01:00.0: BAR 0: failed to assign [mem size 0x200000000 64bit pref]
>
> [1] example of new allocations (pcie5):
> [    1.182745] layerscape-pcie 3800000.pcie: host bridge /soc/pcie@3800000 ranges:
> [    1.182760] layerscape-pcie 3800000.pcie:      MEM 0xa400000000..0xa7ffffffff -> 0xa400000000
> [    1.182771] layerscape-pcie 3800000.pcie:      MEM 0xa040000000..0xa0ffffffff -> 0x0040000000
> [    1.182778] layerscape-pcie 3800000.pcie:       IO 0xa000010000..0xa00001ffff -> 0x0000000000
> [    1.183642] layerscape-pcie 3800000.pcie: iATU: unroll F, 256 ob, 24 ib, align 4K, limit 4G
> [    1.385429] layerscape-pcie 3800000.pcie: PCIe Gen.3 x8 link up
> [    1.385481] layerscape-pcie 3800000.pcie: PCI host bridge to bus 0001:00
> [    1.385484] pci_bus 0001:00: root bus resource [bus 00-ff]
> [    1.385488] pci_bus 0001:00: root bus resource [mem 0xa400000000-0xa7ffffffff pref]
> [    1.385491] pci_bus 0001:00: root bus resource [mem 0xa040000000-0xa0ffffffff] (bus address [0x40000000-0xffffffff])
> [    1.385494] pci_bus 0001:00: root bus resource [io  0x10000-0x1ffff] (bus address [0x0000-0xffff])
> [    1.385516] pci 0001:00:00.0: [1957:8d80] type 01 class 0x060400 PCIe Root Port
> [    1.385538] pci 0001:00:00.0: PCI bridge to [bus 01-ff]
> [    1.385544] pci 0001:00:00.0:   bridge window [io  0x11000-0x11fff]
> [    1.385548] pci 0001:00:00.0:   bridge window [mem 0xa040000000-0xa0502fffff]
> [    1.385605] pci 0001:00:00.0: supports D1 D2
> [    1.385607] pci 0001:00:00.0: PME# supported from D0 D1 D2 D3hot
> [    1.386778] pci 0001:01:00.0: [1002:6995] type 00 class 0x030000 PCIe Legacy Endpoint
> [    1.387336] pci 0001:01:00.0: BAR 0 [mem 0xa040000000-0xa04fffffff 64bit pref]
> [    1.387368] pci 0001:01:00.0: BAR 2 [mem 0xa050000000-0xa0501fffff 64bit pref]
> [    1.387385] pci 0001:01:00.0: BAR 4 [io  0x11000-0x110ff]
> [    1.387402] pci 0001:01:00.0: BAR 5 [mem 0xa050200000-0xa05023ffff]
> [    1.387418] pci 0001:01:00.0: ROM [mem 0xa050240000-0xa05025ffff pref]
> [    1.387493] pci 0001:01:00.0: enabling Extended Tags
> [    1.388960] pci 0001:01:00.0: supports D1 D2
>
> [2] example of previous allocations (pcie5):
> [    1.716744] layerscape-pcie 3800000.pcie: host bridge /soc/pcie@3800000 ranges:
> [    1.724060] layerscape-pcie 3800000.pcie:      MEM 0xa040000000..0xa07fffffff -> 0x0040000000
> [    1.733277] layerscape-pcie 3800000.pcie: iATU: unroll F, 256 ob, 24 ib, align 4K, limit 4G
> [    1.836220] layerscape-pcie 3800000.pcie: PCIe Gen.3 x8 link up
> [    1.842186] layerscape-pcie 3800000.pcie: PCI host bridge to bus 0001:00
> [    1.848883] pci_bus 0001:00: root bus resource [bus 00-ff]
> [    1.854363] pci_bus 0001:00: root bus resource [mem 0xa040000000-0xa07fffffff] (bus address [0x40000000-0x7fffffff])
> [    1.864892] pci 0001:00:00.0: [1957:8d80] type 01 class 0x060400 PCIe Root Port
> [    1.872216] pci 0001:00:00.0: PCI bridge to [bus 01-ff]
> [    1.877438] pci 0001:00:00.0:   bridge window [io  0x1000-0x1fff]
> [    1.883526] pci 0001:00:00.0:   bridge window [mem 0xa040000000-0xa0502fffff]
>
> [3] error programming atu beyond 4GB:
> [    1.716762] layerscape-pcie 3800000.pcie: host bridge /soc/pcie@3800000 ranges:
> [    1.724080] layerscape-pcie 3800000.pcie:      MEM 0xa400000000..0xa7ffffffff -> 0xa400000000
> [    1.732615] layerscape-pcie 3800000.pcie:      MEM 0xa040000000..0xa0ffffffff -> 0x0040000000
> [    1.741142] layerscape-pcie 3800000.pcie:       IO 0xa010000000..0xa01000ffff -> 0x0000000000
> [    1.750379] layerscape-pcie 3800000.pcie: iATU: unroll F, 256 ob, 24 ib, align 4K, limit 4G
> [    1.759089] layerscape-pcie 3800000.pcie: Failed to set MEM range [mem 0xa400000000-0xa7ffffffff flags 0x2200]
> [    1.769089] layerscape-pcie 3800000.pcie: probe with driver layerscape-pcie failed with error -22
>
> [4] pci bootloaderp atching related errors with IORESOURCE_MEM_64 flag:
> [    0.967809] layerscape-pcie 3800000.pcie: host bridge /soc/pcie@3800000 ranges:
> [    0.967830] layerscape-pcie 3800000.pcie:      MEM 0xa400000000..0xa7ffffffff -> 0xa400000000
> [    0.967842] layerscape-pcie 3800000.pcie:      MEM 0xa040000000..0xa0ffffffff -> 0x0040000000
> [    0.967849] layerscape-pcie 3800000.pcie:       IO 0xa000010000..0xa00001ffff -> 0x0000000000
> [    1.169315] pci 0000:01:00.0: [8086:1572] type 00 class 0x020000 PCIe Endpoint
> [    1.169733] pci 0000:01:00.0: BAR 0 [mem 0x00000000-0x00ffffff 64bit pref]
> [    1.169771] pci 0000:01:00.0: BAR 3 [mem 0x00000000-0x00007fff 64bit pref]
> [    1.169796] pci 0000:01:00.0: ROM [mem 0x00000000-0x0007ffff pref]
> [    1.173389] OF: /soc/pcie@3800000: no msi-map translation for id 0x100 on (null)
> [    1.173515] OF: /soc/pcie@3800000: no iommu-map translation for id 0x100 on (null)
I meant to drop this bootloader error log, because after fixing the ranges flags
this is no longer an issue with this v7 patch.

^ permalink raw reply

* [PATCH v2] ASoC: dt-bindings: sound: asahi-kasei,ak4118: Convert DT schema
From: Manish Baing @ 2026-05-24 15:02 UTC (permalink / raw)
  To: lgirdwood, broonie, robh, krzk+dt, conor+dt, peron.clem
  Cc: linux-sound, devicetree, linux-kernel, manishbaing2789

Convert the Asahi Kasei AK4118 S/PDIF transceiver bindings from
text format to YAML schema.

Signed-off-by: Manish Baing <manishbaing2789@gmail.com>
---
Changes in v2:
- Restored legacy 'irq-gpios' property to prevent C driver probe failure.
- Added 'reset-gpios' and 'irq-gpios' to the required properties list.

 .../devicetree/bindings/sound/ak4118.txt      | 22 -------
 .../bindings/sound/asahi-kasei,ak4118.yaml    | 58 +++++++++++++++++++
 2 files changed, 58 insertions(+), 22 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/sound/ak4118.txt
 create mode 100644 Documentation/devicetree/bindings/sound/asahi-kasei,ak4118.yaml

diff --git a/Documentation/devicetree/bindings/sound/ak4118.txt b/Documentation/devicetree/bindings/sound/ak4118.txt
deleted file mode 100644
index 6e11a2f7404c..000000000000
--- a/Documentation/devicetree/bindings/sound/ak4118.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-AK4118 S/PDIF transceiver
-
-This device supports I2C mode.
-
-Required properties:
-
-- compatible : "asahi-kasei,ak4118"
-- reg : The I2C address of the device for I2C
-- reset-gpios: A GPIO specifier for the reset pin
-- irq-gpios: A GPIO specifier for the IRQ pin
-
-Example:
-
-&i2c {
-	ak4118: ak4118@13 {
-		#sound-dai-cells = <0>;
-		compatible = "asahi-kasei,ak4118";
-		reg = <0x13>;
-		reset-gpios = <&gpio 0 GPIO_ACTIVE_LOW>
-		irq-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
-	};
-};
diff --git a/Documentation/devicetree/bindings/sound/asahi-kasei,ak4118.yaml b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4118.yaml
new file mode 100644
index 000000000000..c8aa61643ca0
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4118.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/asahi-kasei,ak4118.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Asahi Kasei AK4118 Digital Audio Transceiver
+
+maintainers:
+  - Clément Péron <peron.clem@gmail.com>
+
+allOf:
+  - $ref: dai-common.yaml#
+
+properties:
+  compatible:
+    const: asahi-kasei,ak4118
+
+  reg:
+    maxItems: 1
+    description: I2C address of the device
+
+  "#sound-dai-cells":
+    const: 0
+
+  irq-gpios:
+    maxItems: 1
+    description: GPIO used for IRQ pin
+
+  reset-gpios:
+    maxItems: 1
+    description: GPIO used for the Reset pin
+
+required:
+  - compatible
+  - reg
+  - "#sound-dai-cells"
+  - irq-gpios
+  - reset-gpios
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        audio-codec@13 {
+            compatible = "asahi-kasei,ak4118";
+            reg = <0x13>;
+            #sound-dai-cells = <0>;
+            reset-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
+            irq-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;
+        };
+    };
-- 
2.43.0


^ permalink raw reply related

* [PATCH v7 9/9] arm64: dts: Add support for LX2160 Twins board in single configuration
From: Josua Mayer @ 2026-05-24 14:54 UTC (permalink / raw)
  To: Shawn Guo, Li Yang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Rob Herring, Krzysztof Kozlowski, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
  Cc: Yazan Shhady, Jon Nettleton, linux-arm-kernel, devicetree,
	linux-kernel, imx, Josua Mayer
In-Reply-To: <20260524-lx2160-pci-v7-0-09370c23b952@solid-run.com>

Add support for the SolidRun LX2160A Twins board in its single cpu
configuration.

The twins board is designed to host a pair of LX2160A CEX-7 modules,
sharing a single PCI-E connector in multi-host mode.

It may be assembled in two configurations (different assembly options
facilitating signal re-routing), with a single or with dual CEX-7
module. Their marketing names are:

- SolidWAN Single LX2160
- SolidWAN Dual LX2160

This patch adds the single configuration, featuring:
- 8x SFP (1Gbps)
- 8x SFP+ (1/10Gbps)
- PCI-E OCP card connector
- USB-3.0 front-panel header with single port
- microSD
- dual hot-swappable power supplies

Signed-off-by: Josua Mayer <josua@solid-run.com>
---
 arch/arm64/boot/dts/freescale/Makefile             |   2 +
 .../arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi |   8 +-
 .../boot/dts/freescale/fsl-lx2160a-half-twins.dts  | 830 +++++++++++++++++++++
 arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi     |  24 +-
 4 files changed, 848 insertions(+), 16 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index 711e36cc2c990..59eee431562ef 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -51,6 +51,8 @@ DTC_FLAGS_fsl-lx2160a-bluebox3-rev-a := -Wno-interrupt_map
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-bluebox3-rev-a.dtb
 DTC_FLAGS_fsl-lx2160a-clearfog-cx := -Wno-interrupt_map
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-clearfog-cx.dtb
+DTC_FLAGS_fsl-lx2160a-half-twins := -Wno-interrupt_map
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-half-twins.dtb
 DTC_FLAGS_fsl-lx2160a-honeycomb := -Wno-interrupt_map
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-honeycomb.dtb
 DTC_FLAGS_fsl-lx2160a-qds := -Wno-interrupt_map
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi
index 2c86734c39ab2..16caa281ece02 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi
@@ -65,7 +65,7 @@ i2c-mux@77 {
 		#size-cells = <0>;
 		reg = <0x77>;
 
-		i2c@0 {
+		ddr_i2c: i2c@0 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0>;
@@ -91,7 +91,7 @@ eeprom@57 {
 			};
 		};
 
-		i2c@1 {
+		fan_i2c: i2c@1 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <1>;
@@ -102,7 +102,7 @@ fan-temperature-ctrlr@18 {
 			};
 		};
 
-		i2c@2 {
+		power_i2c: i2c@2 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <2>;
@@ -113,7 +113,7 @@ regulator@5c {
 			};
 		};
 
-		i2c@3 {
+		i2c_smb: i2c@3 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <3>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-half-twins.dts b/arch/arm64/boot/dts/freescale/fsl-lx2160a-half-twins.dts
new file mode 100644
index 0000000000000..d16e273072754
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-half-twins.dts
@@ -0,0 +1,830 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+//
+// Device Tree file for single LX2160A CEX-7 on Twins board.
+//
+// Copyright 2022 SolidRun Ltd.
+
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+
+#include "fsl-lx2160a-rev2.dtsi"
+#include "fsl-lx2160a-cex7.dtsi"
+
+/ {
+	compatible = "solidrun,twins-single", "solidrun,lx2160a-cex7", "fsl,lx2160a";
+	model = "SolidRun LX2160A SolidWAN Single";
+
+	aliases {
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+		gpio2 = &gpio2;
+		gpio3 = &gpio3;
+		gpio4 = &expander0;
+		gpio5 = &expander1;
+		gpio6 = &expander2;
+		gpio7 = &expander3;
+		i2c0 = &i2c0;
+		i2c1 = &i2c2;
+		i2c2 = &i2c4;
+		i2c3 = &fan_i2c;
+		i2c4 = &power_i2c;
+		i2c5 = &i2c_smb;
+		i2c6 = &sfp0_i2c;
+		i2c7 = &sfp1_i2c;
+		i2c8 = &sfp2_i2c;
+		i2c9 = &sfp3_i2c;
+		i2c10 = &twins_sfp_c1_at_i2c;
+		i2c11 = &twins_sfp_c1_ab_i2c;
+		i2c12 = &twins_sfp_c1_bt_i2c;
+		i2c13 = &twins_sfp_c1_bb_i2c;
+		i2c14 = &twins_sfp_c2_at_i2c;
+		i2c15 = &twins_sfp_c2_ab_i2c;
+		i2c16 = &twins_sfp_c2_bt_i2c;
+		i2c17 = &twins_sfp_c2_bb_i2c;
+		i2c18 = &twins_sfp_c3_at_i2c;
+		i2c19 = &twins_sfp_c3_ab_i2c;
+		i2c20 = &twins_sfp_c3_bt_i2c;
+		i2c21 = &twins_sfp_c3_bb_i2c;
+		i2c22 = &htwins_sfp_c3_at_i2c;
+		i2c23 = &htwins_sfp_c3_ab_i2c;
+		i2c24 = &htwins_sfp_c3_bt_i2c;
+		i2c25 = &htwins_sfp_c3_bb_i2c;
+		i2c26 = &ddr_i2c;
+		mmc0 = &esdhc0;
+		mmc1 = &esdhc1;
+		serial0 = &uart0;
+		serial1 = &uart1;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led_ht_c3_bt: led-sfp-1 {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <1>;
+			gpios = <&expander3 14 GPIO_ACTIVE_LOW>;
+			trigger-sources = <&dpmac5>;
+			linux,default-trigger = "netdev";
+		};
+
+		led_ht_c3_bb: led-sfp-2 {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <2>;
+			gpios = <&expander3 13 GPIO_ACTIVE_LOW>;
+			trigger-sources = <&dpmac15>;
+			linux,default-trigger = "netdev";
+		};
+
+		led_ht_c3_at: led-sfp-3 {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <3>;
+			gpios = <&expander3 11 GPIO_ACTIVE_LOW>;
+			trigger-sources = <&dpmac6>;
+			linux,default-trigger = "netdev";
+		};
+
+		led_ht_c3_ab: led-sfp-4 {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <4>;
+			gpios = <&expander3 12 GPIO_ACTIVE_LOW>;
+			trigger-sources = <&dpmac11>;
+			linux,default-trigger = "netdev";
+		};
+
+		led_c1_bt: led-sfp-9 {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <9>;
+			gpios = <&expander1 4 GPIO_ACTIVE_LOW>;
+			trigger-sources = <&dpmac4>;
+			linux,default-trigger = "netdev";
+		};
+
+		led_c1_bb: led-sfp-10 {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <10>;
+			gpios = <&expander1 3 GPIO_ACTIVE_LOW>;
+			trigger-sources = <&dpmac17>;
+			linux,default-trigger = "netdev";
+		};
+
+		led_c1_at: led-sfp-11 {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <11>;
+			gpios = <&expander1 1 GPIO_ACTIVE_LOW>;
+			trigger-sources = <&dpmac3>;
+			linux,default-trigger = "netdev";
+		};
+
+		led_c1_ab: led-sfp-12 {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <12>;
+			gpios = <&expander1 2 GPIO_ACTIVE_LOW>;
+			trigger-sources = <&dpmac12>;
+			linux,default-trigger = "netdev";
+		};
+
+		led_c2_bt: led-sfp-13 {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <13>;
+			gpios = <&expander1 10 GPIO_ACTIVE_LOW>;
+			trigger-sources = <&dpmac8>;
+			linux,default-trigger = "netdev";
+		};
+
+		led_c2_bb: led-sfp-14 {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <14>;
+			gpios = <&expander1 9 GPIO_ACTIVE_LOW>;
+			trigger-sources = <&dpmac16>;
+			linux,default-trigger = "netdev";
+		};
+
+		led_c2_at: led-sfp-15 {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <15>;
+			gpios = <&expander1 5 GPIO_ACTIVE_LOW>;
+			trigger-sources = <&dpmac7>;
+			linux,default-trigger = "netdev";
+		};
+
+		led_c2_ab: led-sfp-16 {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <16>;
+			gpios = <&expander1 6 GPIO_ACTIVE_LOW>;
+			trigger-sources = <&dpmac18>;
+			linux,default-trigger = "netdev";
+		};
+
+		led_c3_bt: led-sfp-17 {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <17>;
+			gpios = <&expander1 14 GPIO_ACTIVE_LOW>;
+			trigger-sources = <&dpmac10>;
+			linux,default-trigger = "netdev";
+		};
+
+		led_c3_bb: led-sfp-18 {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <18>;
+			gpios = <&expander1 13 GPIO_ACTIVE_LOW>;
+			trigger-sources = <&dpmac14>;
+			linux,default-trigger = "netdev";
+		};
+
+		led_c3_at: led-sfp-19 {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <19>;
+			gpios = <&expander1 11 GPIO_ACTIVE_LOW>;
+			trigger-sources = <&dpmac9>;
+			linux,default-trigger = "netdev";
+		};
+
+		led_c3_ab: led-sfp-20 {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <20>;
+			gpios = <&expander1 12 GPIO_ACTIVE_LOW>;
+			trigger-sources = <&dpmac13>;
+			linux,default-trigger = "netdev";
+		};
+
+		led-status {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_STATUS;
+			function-enumerator = <0>;
+			gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "heartbeat";
+		};
+
+		led-status-twin {
+			color = <LED_COLOR_ID_GREEN>;
+			default-state = "off";
+			function = LED_FUNCTION_STATUS;
+			function-enumerator = <1>;
+			gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
+		};
+
+		led-fault {
+			color = <LED_COLOR_ID_YELLOW>;
+			default-state = "off";
+			function = LED_FUNCTION_FAULT;
+			function-enumerator = <0>;
+			gpios = <&gpio2 11 GPIO_ACTIVE_LOW>;
+			panic-indicator;
+		};
+
+		led-fault-twin {
+			color = <LED_COLOR_ID_YELLOW>;
+			default-state = "off";
+			function = LED_FUNCTION_FAULT;
+			function-enumerator = <1>;
+			gpios = <&gpio2 9 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	mux-controller {
+		compatible = "gpio-mux";
+		#mux-control-cells = <0>;
+		/*
+		 * This gpio controlled mux can route the tacho signals of 6 PWM FAN connectors
+		 * to the tacho inputs of both CEX-7 modules (twins).
+		 *
+		 * The first twin controls this mux and monitors four fan connectors, two intended
+		 * for itself, and two for the OCP card.
+		 *
+		 * The second twin monitors only two fan connectors intended for itself.
+		 *
+		 * The table below maps selector GPIO states to monitored fan connector per twin:
+		 *
+		 * | SEL1 | SEL0 | Twin 1 | Twin 2 |
+		 * | ---: | ---: | :------| ------ |
+		 * |    0 |    0 | J10    |  J5024 |
+		 * |    0 |    1 | J5016  |  J5024 |
+		 * |    1 |    0 | J5026  |  J5025 |
+		 * |    1 |    1 | J5013  |  J5025 |
+		 */
+		mux-gpios = <&expander0 8 GPIO_ACTIVE_HIGH>, /* SEL0 */
+			    <&expander0 15 GPIO_ACTIVE_HIGH>; /* SEL1 */
+	};
+
+	ht_c3_bt_sfp: sfp-1 {
+		compatible = "sff,sfp";
+		i2c-bus = <&htwins_sfp_c3_bt_i2c>;
+		maximum-power-milliwatt = <2000>;
+		mod-def0-gpios = <&expander2 13 GPIO_ACTIVE_LOW>;
+	};
+
+	ht_c3_bb_sfp: sfp-2 {
+		compatible = "sff,sfp";
+		i2c-bus = <&htwins_sfp_c3_bb_i2c>;
+		maximum-power-milliwatt = <2000>;
+		mod-def0-gpios = <&expander2 14 GPIO_ACTIVE_LOW>;
+	};
+
+	ht_c3_at_sfp: sfp-3 {
+		compatible = "sff,sfp";
+		i2c-bus = <&htwins_sfp_c3_at_i2c>;
+		maximum-power-milliwatt = <2000>;
+		mod-def0-gpios = <&expander2 11 GPIO_ACTIVE_LOW>;
+	};
+
+	ht_c3_ab_sfp: sfp-4 {
+		compatible = "sff,sfp";
+		i2c-bus = <&htwins_sfp_c3_ab_i2c>;
+		maximum-power-milliwatt = <2000>;
+		mod-def0-gpios = <&expander2 12 GPIO_ACTIVE_LOW>;
+	};
+
+	c1_bt_sfp: sfp-9 {
+		compatible = "sff,sfp";
+		i2c-bus = <&twins_sfp_c1_bt_i2c>;
+		maximum-power-milliwatt = <2000>;
+		mod-def0-gpios = <&expander0 3 GPIO_ACTIVE_LOW>;
+	};
+
+	c1_bb_sfp: sfp-10 {
+		compatible = "sff,sfp";
+		i2c-bus = <&twins_sfp_c1_bb_i2c>;
+		maximum-power-milliwatt = <2000>;
+		mod-def0-gpios = <&expander0 4 GPIO_ACTIVE_LOW>;
+	};
+
+	c1_at_sfp: sfp-11 {
+		compatible = "sff,sfp";
+		i2c-bus = <&twins_sfp_c1_at_i2c>;
+		maximum-power-milliwatt = <2000>;
+		mod-def0-gpios = <&expander0 1 GPIO_ACTIVE_LOW>;
+	};
+
+	c1_ab_sfp: sfp-12 {
+		compatible = "sff,sfp";
+		i2c-bus = <&twins_sfp_c1_ab_i2c>;
+		maximum-power-milliwatt = <2000>;
+		mod-def0-gpios = <&expander0 2 GPIO_ACTIVE_LOW>;
+	};
+
+	c2_bt_sfp: sfp-13 {
+		compatible = "sff,sfp";
+		i2c-bus = <&twins_sfp_c2_bt_i2c>;
+		maximum-power-milliwatt = <2000>;
+		mod-def0-gpios = <&expander0 9 GPIO_ACTIVE_LOW>;
+	};
+
+	c2_bb_sfp: sfp-14 {
+		compatible = "sff,sfp";
+		i2c-bus = <&twins_sfp_c2_bb_i2c>;
+		maximum-power-milliwatt = <2000>;
+		mod-def0-gpios = <&expander0 10 GPIO_ACTIVE_LOW>;
+	};
+
+	c2_at_sfp: sfp-15 {
+		compatible = "sff,sfp";
+		i2c-bus = <&twins_sfp_c2_at_i2c>;
+		maximum-power-milliwatt = <2000>;
+		mod-def0-gpios = <&expander0 5 GPIO_ACTIVE_LOW>;
+	};
+
+	c2_ab_sfp: sfp-16 {
+		compatible = "sff,sfp";
+		i2c-bus = <&twins_sfp_c2_ab_i2c>;
+		maximum-power-milliwatt = <2000>;
+		mod-def0-gpios = <&expander0 6 GPIO_ACTIVE_LOW>;
+	};
+
+	c3_bt_sfp: sfp-17 {
+		compatible = "sff,sfp";
+		i2c-bus = <&twins_sfp_c3_bt_i2c>;
+		maximum-power-milliwatt = <2000>;
+		mod-def0-gpios = <&expander0 13 GPIO_ACTIVE_LOW>;
+	};
+
+	c3_bb_sfp: sfp-18 {
+		compatible = "sff,sfp";
+		i2c-bus = <&twins_sfp_c3_bb_i2c>;
+		maximum-power-milliwatt = <2000>;
+		mod-def0-gpios = <&expander0 14 GPIO_ACTIVE_LOW>;
+	};
+
+	c3_at_sfp: sfp-19 {
+		compatible = "sff,sfp";
+		i2c-bus = <&twins_sfp_c3_at_i2c>;
+		maximum-power-milliwatt = <2000>;
+		mod-def0-gpios = <&expander0 11 GPIO_ACTIVE_LOW>;
+	};
+
+	c3_ab_sfp: sfp-20 {
+		compatible = "sff,sfp";
+		i2c-bus = <&twins_sfp_c3_ab_i2c>;
+		maximum-power-milliwatt = <2000>;
+		mod-def0-gpios = <&expander0 12 GPIO_ACTIVE_LOW>;
+	};
+};
+
+/*
+ * This board supports industrial grade temperatures,
+ * the LX2160A SoC maximum junction temperature is 105°C.
+ *
+ * Raise thermal thresholds to allow operation near maximum temperature.
+ */
+&ccn_dpaa_alert {
+	temperature = <100000>;
+};
+
+&ccn_dpaa_crit {
+	temperature = <105000>;
+};
+
+&cluster2_3_alert {
+	temperature = <100000>;
+};
+
+&cluster2_3_crit {
+	temperature = <105000>;
+};
+
+&cluster4_alert {
+	temperature = <100000>;
+};
+
+&cluster4_crit {
+	temperature = <105000>;
+};
+
+&cluster5_alert {
+	temperature = <100000>;
+};
+
+&cluster5_crit {
+	temperature = <105000>;
+};
+
+&cluster6_7_alert {
+	temperature = <100000>;
+};
+
+&cluster6_7_crit {
+	temperature = <105000>;
+};
+
+&dce_qbman_alert {
+	temperature = <100000>;
+};
+
+&dce_qbman_crit {
+	temperature = <105000>;
+};
+
+/* sfp port 11 */
+&dpmac3 {
+	managed = "in-band-status";
+	phys = <&serdes_1 7>;
+	sfp = <&c1_at_sfp>;
+};
+
+/* sfp port 9 */
+&dpmac4 {
+	managed = "in-band-status";
+	phys = <&serdes_1 6>;
+	sfp = <&c1_bt_sfp>;
+};
+
+/* sfp port 1 */
+&dpmac5 {
+	managed = "in-band-status";
+	phys = <&serdes_1 5>;
+	sfp = <&ht_c3_bt_sfp>;
+};
+
+/* sfp port 3 */
+&dpmac6 {
+	managed = "in-band-status";
+	phys = <&serdes_1 4>;
+	sfp = <&ht_c3_at_sfp>;
+};
+
+/* sfp port 15 */
+&dpmac7 {
+	managed = "in-band-status";
+	phys = <&serdes_1 3>;
+	sfp = <&c2_at_sfp>;
+};
+
+/* sfp port 13 */
+&dpmac8 {
+	managed = "in-band-status";
+	phys = <&serdes_1 2>;
+	sfp = <&c2_bt_sfp>;
+};
+
+/* sfp port 19 */
+&dpmac9 {
+	managed = "in-band-status";
+	phys = <&serdes_1 1>;
+	sfp = <&c3_at_sfp>;
+};
+
+/* sfp port 17 */
+&dpmac10 {
+	managed = "in-band-status";
+	phys = <&serdes_1 0>;
+	sfp = <&c3_bt_sfp>;
+};
+
+/* sfp port 4 */
+&dpmac11 {
+	managed = "in-band-status";
+	phys = <&serdes_2 0>;
+	sfp = <&ht_c3_ab_sfp>;
+};
+
+/* sfp port 12 */
+&dpmac12 {
+	managed = "in-band-status";
+	phys = <&serdes_2 1>;
+	sfp = <&c1_ab_sfp>;
+};
+
+/* sfp port 20 */
+&dpmac13 {
+	managed = "in-band-status";
+	phys = <&serdes_2 6>;
+	sfp = <&c3_ab_sfp>;
+};
+
+/* sfp port 18 */
+&dpmac14 {
+	managed = "in-band-status";
+	phys = <&serdes_2 7>;
+	sfp = <&c3_bb_sfp>;
+};
+
+/* sfp port 2 */
+&dpmac15 {
+	managed = "in-band-status";
+	phys = <&serdes_2 4>;
+	sfp = <&ht_c3_bb_sfp>;
+};
+
+/* sfp port 14 */
+&dpmac16 {
+	managed = "in-band-status";
+	phys = <&serdes_2 5>;
+	sfp = <&c2_bb_sfp>;
+};
+
+/* sfp port 10 */
+&dpmac17 {
+	/* override connection to on-COM phy */
+	/delete-property/ phy-handle;
+	/delete-property/ phy-connection-type;
+	managed = "in-band-status";
+	phys = <&serdes_2 2>;
+	sfp = <&c1_bb_sfp>;
+};
+
+/* sfp port 16 */
+&dpmac18 {
+	managed = "in-band-status";
+	phys = <&serdes_2 3>;
+	sfp = <&c2_ab_sfp>;
+};
+
+&esdhc0 {
+	pinctrl-0 = <&esdhc0_cd_wp_pins>, <&esdhc0_cmd_data30_clk_vsel_pins>;
+	pinctrl-names = "default";
+	/*
+	 * Disable 1.8V modes so that microsd state is same between
+	 * power-on-reset, u-boot and linux.
+	 * This avoids sporadic read errors after hard reset with some cards.
+	 */
+	no-1-8-v;
+	status = "okay";
+};
+
+&i2c2 {
+	expander0: gpio@20 {
+		compatible = "nxp,pca9555";
+		reg = <0x20>;
+		#gpio-cells = <2>;
+		gpio-controller;
+	};
+
+	expander1: gpio@21 {
+		compatible = "nxp,pca9555";
+		reg = <0x21>;
+		#gpio-cells = <2>;
+		gpio-controller;
+	};
+
+	expander2: gpio@24 {
+		compatible = "nxp,pca9555";
+		reg = <0x24>;
+		#gpio-cells = <2>;
+		gpio-controller;
+	};
+
+	expander3: gpio@25 {
+		compatible = "nxp,pca9555";
+		reg = <0x25>;
+		#gpio-cells = <2>;
+		gpio-controller;
+	};
+
+	/* Half twins configuration; take over c3 from the other twin side */
+	i2c-mux@73 {
+		compatible = "nxp,pca9547";
+		reg = <0x73>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		i2c-mux-idle-disconnect;
+
+		htwins_sfp_c3_at_i2c: i2c@3 {
+			reg = <3>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		htwins_sfp_c3_ab_i2c: i2c@4 {
+			reg = <4>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		htwins_sfp_c3_bt_i2c: i2c@5 {
+			reg = <5>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		htwins_sfp_c3_bb_i2c: i2c@6 {
+			reg = <6>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	i2c-mux@76 {
+		compatible = "nxp,pca9547";
+		reg = <0x76>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		i2c-mux-idle-disconnect;
+
+		twins_sfp_c1_at_i2c: i2c@1 {
+			reg = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		twins_sfp_c1_ab_i2c: i2c@2 {
+			reg = <2>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		twins_sfp_c1_bt_i2c: i2c@3 {
+			reg = <3>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		twins_sfp_c1_bb_i2c: i2c@4 {
+			reg = <4>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		twins_sfp_c2_at_i2c: i2c@5 {
+			reg = <5>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		twins_sfp_c2_ab_i2c: i2c@6 {
+			reg = <6>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	i2c-mux@77 {
+		compatible = "nxp,pca9547";
+		reg = <0x77>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		i2c-mux-idle-disconnect;
+
+		twins_sfp_c2_bt_i2c: i2c@1 {
+			reg = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		twins_sfp_c2_bb_i2c: i2c@2 {
+			reg = <2>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		twins_sfp_c3_at_i2c: i2c@3 {
+			reg = <3>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		twins_sfp_c3_ab_i2c: i2c@4 {
+			reg = <4>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		twins_sfp_c3_bt_i2c: i2c@5 {
+			reg = <5>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		twins_sfp_c3_bb_i2c: i2c@6 {
+			reg = <6>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+};
+
+&pcie5 {
+	status = "okay";
+};
+
+&pcs_mdio3 {
+	status = "okay";
+};
+
+&pcs_mdio4 {
+	status = "okay";
+};
+
+&pcs_mdio5 {
+	status = "okay";
+};
+
+&pcs_mdio6 {
+	status = "okay";
+};
+
+&pcs_mdio7 {
+	status = "okay";
+};
+
+&pcs_mdio8 {
+	status = "okay";
+};
+
+&pcs_mdio9 {
+	status = "okay";
+};
+
+&pcs_mdio10 {
+	status = "okay";
+};
+
+&pcs_mdio11 {
+	status = "okay";
+};
+
+&pcs_mdio12 {
+	status = "okay";
+};
+
+&pcs_mdio13 {
+	status = "okay";
+};
+
+&pcs_mdio14 {
+	status = "okay";
+};
+
+&pcs_mdio15 {
+	status = "okay";
+};
+
+&pcs_mdio16 {
+	status = "okay";
+};
+
+&pcs_mdio17 {
+	status = "okay";
+};
+
+&pcs_mdio18 {
+	status = "okay";
+};
+
+&rgmii_phy1 {
+	/*
+	 * COM has a phy at address 1 connected to SoC Ethernet Controller 1.
+	 * It competes for WRIOP MAC17, and no connector has been wired.
+	 */
+	status = "disabled";
+};
+
+&serdes_2 {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+};
+
+&wriop_alert {
+	temperature = <100000>;
+};
+
+&wriop_crit {
+	temperature = <105000>;
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
index 479982948ee53..1d73abffa6b72 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
@@ -499,13 +499,13 @@ ddr-ctrl5-thermal {
 			thermal-sensors = <&tmu 1>;
 
 			trips {
-				ddr-cluster5-alert {
+				cluster5_alert: ddr-cluster5-alert {
 					temperature = <85000>;
 					hysteresis = <2000>;
 					type = "passive";
 				};
 
-				ddr-cluster5-crit {
+				cluster5_crit: ddr-cluster5-crit {
 					temperature = <95000>;
 					hysteresis = <2000>;
 					type = "critical";
@@ -519,13 +519,13 @@ wriop-thermal {
 			thermal-sensors = <&tmu 2>;
 
 			trips {
-				wriop-alert {
+				wriop_alert: wriop-alert {
 					temperature = <85000>;
 					hysteresis = <2000>;
 					type = "passive";
 				};
 
-				wriop-crit {
+				wriop_crit: wriop-crit {
 					temperature = <95000>;
 					hysteresis = <2000>;
 					type = "critical";
@@ -539,13 +539,13 @@ dce-thermal {
 			thermal-sensors = <&tmu 3>;
 
 			trips {
-				dce-qbman-alert {
+				dce_qbman_alert: dce-qbman-alert {
 					temperature = <85000>;
 					hysteresis = <2000>;
 					type = "passive";
 				};
 
-				dce-qbman-crit {
+				dce_qbman_crit: dce-qbman-crit {
 					temperature = <95000>;
 					hysteresis = <2000>;
 					type = "critical";
@@ -559,13 +559,13 @@ ccn-thermal {
 			thermal-sensors = <&tmu 4>;
 
 			trips {
-				ccn-dpaa-alert {
+				ccn_dpaa_alert: ccn-dpaa-alert {
 					temperature = <85000>;
 					hysteresis = <2000>;
 					type = "passive";
 				};
 
-				ccn-dpaa-crit {
+				ccn_dpaa_crit: ccn-dpaa-crit {
 					temperature = <95000>;
 					hysteresis = <2000>;
 					type = "critical";
@@ -579,13 +579,13 @@ cluster4-thermal {
 			thermal-sensors = <&tmu 5>;
 
 			trips {
-				clust4-hsio3-alert {
+				cluster4_alert: clust4-hsio3-alert {
 					temperature = <85000>;
 					hysteresis = <2000>;
 					type = "passive";
 				};
 
-				clust4-hsio3-crit {
+				cluster4_crit: clust4-hsio3-crit {
 					temperature = <95000>;
 					hysteresis = <2000>;
 					type = "critical";
@@ -599,13 +599,13 @@ cluster2-3-thermal {
 			thermal-sensors = <&tmu 6>;
 
 			trips {
-				cluster2-3-alert {
+				cluster2_3_alert: cluster2-3-alert {
 					temperature = <85000>;
 					hysteresis = <2000>;
 					type = "passive";
 				};
 
-				cluster2-3-crit {
+				cluster2_3_crit: cluster2-3-crit {
 					temperature = <95000>;
 					hysteresis = <2000>;
 					type = "critical";

-- 
2.51.0


^ permalink raw reply related

* [PATCH v7 8/9] arm64: dts: lx2160a-cex7: add usb hub
From: Josua Mayer @ 2026-05-24 14:54 UTC (permalink / raw)
  To: Shawn Guo, Li Yang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Rob Herring, Krzysztof Kozlowski, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
  Cc: Yazan Shhady, Jon Nettleton, linux-arm-kernel, devicetree,
	linux-kernel, imx, Josua Mayer
In-Reply-To: <20260524-lx2160-pci-v7-0-09370c23b952@solid-run.com>

LX2160A CEX-7 module provides a total of 4 USB ports to the carrier
board, one from first usb controller, and 3 from a hub behind the second
controller.

Both controllers currently have their status set okay in the module's
dtsi file. However devices should be disabled by default when
incomplete.

The first USB controller is only completed by a carrier board featuring
a device or USB connector.

The second controller hosts a USB hub and should therefore be active.

Add description for the USB hub, and enable the first controller only in
the carrier board description.

Signed-off-by: Josua Mayer <josua@solid-run.com>
---
 .../arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi | 29 +++++++++++++++++++---
 .../dts/freescale/fsl-lx2160a-clearfog-itx.dtsi    |  4 +++
 2 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi
index 7df93bb37d13c..2c86734c39ab2 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi
@@ -13,6 +13,13 @@ aliases {
 		rtc0 = &com_rtc;
 	};
 
+	v_1_2: regulator-1-2 {
+		compatible = "regulator-fixed";
+		regulator-name = "1v2";
+		regulator-max-microvolt = <1200000>;
+		regulator-min-microvolt = <1200000>;
+	};
+
 	sb_3v3: regulator-sb3v3 {
 		compatible = "regulator-fixed";
 		regulator-name = "RT7290";
@@ -181,10 +188,24 @@ &pinmux_i2crv {
 	pinctrl-0 = <&gpio0_14_12_pins>;
 };
 
-&usb0 {
-	status = "okay";
-};
-
 &usb1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
 	status = "okay";
+
+	usb_hub_2_0: hub@1 {
+		compatible = "usb4b4,6502", "usb4b4,6506";
+		reg = <1>;
+		peer-hub = <&usb_hub_3_0>;
+		vdd2-supply = <&sb_3v3>;
+		vdd-supply = <&v_1_2>;
+	};
+
+	usb_hub_3_0: hub@2 {
+		compatible = "usb4b4,6500", "usb4b4,6504";
+		reg = <2>;
+		peer-hub = <&usb_hub_2_0>;
+		vdd2-supply = <&sb_3v3>;
+		vdd-supply = <&v_1_2>;
+	};
 };
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi
index 170e5b0034f19..4bc151d721ddf 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi
@@ -142,3 +142,7 @@ &uart0 {
 &uart1 {
 	status = "okay";
 };
+
+&usb0 {
+	status = "okay";
+};

-- 
2.51.0


^ permalink raw reply related

* [PATCH v7 7/9] arm64: dts: lx2160a-clearfog-itx: move shared includes to dts
From: Josua Mayer @ 2026-05-24 14:54 UTC (permalink / raw)
  To: Shawn Guo, Li Yang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Rob Herring, Krzysztof Kozlowski, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
  Cc: Yazan Shhady, Jon Nettleton, linux-arm-kernel, devicetree,
	linux-kernel, imx, Josua Mayer
In-Reply-To: <20260524-lx2160-pci-v7-0-09370c23b952@solid-run.com>

Originally includes were defined hierarchically:
- CEX-7 Module includes SoC
- Clearfog-CX & Honeycomb common parts include CEX-7 Module
- Boards include common parts

This makes it difficult to modify the includes on a per-board level,
e.g. when adding a new board based on CEX-7 module but revision 2 SoC
(which now has its own soc dtsi).

Move includes of both SoC and CEX-7 module out of common parts and into
each board dts.

Signed-off-by: Josua Mayer <josua@solid-run.com>
---
 arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi         | 2 --
 arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-cx.dts   | 2 ++
 arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi | 1 -
 arch/arm64/boot/dts/freescale/fsl-lx2160a-honeycomb.dts     | 2 ++
 4 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi
index 56b74837ddd48..7df93bb37d13c 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi
@@ -4,8 +4,6 @@
 //
 // Copyright 2019 SolidRun Ltd.
 
-#include "fsl-lx2160a.dtsi"
-
 / {
 	model = "SolidRun LX2160A COM Express Type 7 module";
 	compatible = "solidrun,lx2160a-cex7", "fsl,lx2160a";
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-cx.dts b/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-cx.dts
index 86a9b771428dc..802d7611c6479 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-cx.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-cx.dts
@@ -6,6 +6,8 @@
 
 /dts-v1/;
 
+#include "fsl-lx2160a.dtsi"
+#include "fsl-lx2160a-cex7.dtsi"
 #include "fsl-lx2160a-clearfog-itx.dtsi"
 
 / {
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi
index 6388bd60ffdf5..170e5b0034f19 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi
@@ -5,7 +5,6 @@
 //
 // Copyright 2019 SolidRun Ltd.
 
-#include "fsl-lx2160a-cex7.dtsi"
 #include <dt-bindings/input/linux-event-codes.h>
 
 / {
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-honeycomb.dts b/arch/arm64/boot/dts/freescale/fsl-lx2160a-honeycomb.dts
index fe19f3009ea58..2b1e13053422b 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-honeycomb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-honeycomb.dts
@@ -6,6 +6,8 @@
 
 /dts-v1/;
 
+#include "fsl-lx2160a.dtsi"
+#include "fsl-lx2160a-cex7.dtsi"
 #include "fsl-lx2160a-clearfog-itx.dtsi"
 
 / {

-- 
2.51.0


^ permalink raw reply related

* [PATCH v7 6/9] arm64: dts: lx2160a-clearfog-itx: remove redundant dts version tag
From: Josua Mayer @ 2026-05-24 14:54 UTC (permalink / raw)
  To: Shawn Guo, Li Yang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Rob Herring, Krzysztof Kozlowski, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
  Cc: Yazan Shhady, Jon Nettleton, linux-arm-kernel, devicetree,
	linux-kernel, imx, Josua Mayer
In-Reply-To: <20260524-lx2160-pci-v7-0-09370c23b952@solid-run.com>

The dts version tag should only appear in the top level dts file.

Since the cex-7 module and clearfog-itx are shared code intended for
inclusion, drop their dts version tags.

Signed-off-by: Josua Mayer <josua@solid-run.com>
---
 arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi         | 2 --
 arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi | 2 --
 2 files changed, 4 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi
index 90956ffb8ea9a..56b74837ddd48 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi
@@ -4,8 +4,6 @@
 //
 // Copyright 2019 SolidRun Ltd.
 
-/dts-v1/;
-
 #include "fsl-lx2160a.dtsi"
 
 / {
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi
index 580ee9b3026e3..6388bd60ffdf5 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi
@@ -5,8 +5,6 @@
 //
 // Copyright 2019 SolidRun Ltd.
 
-/dts-v1/;
-
 #include "fsl-lx2160a-cex7.dtsi"
 #include <dt-bindings/input/linux-event-codes.h>
 

-- 
2.51.0


^ permalink raw reply related

* [PATCH v7 3/9] arm64: dts: lx2162a-clearfog: cleanup superfluous status properties
From: Josua Mayer @ 2026-05-24 14:54 UTC (permalink / raw)
  To: Shawn Guo, Li Yang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Rob Herring, Krzysztof Kozlowski, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
  Cc: Yazan Shhady, Jon Nettleton, linux-arm-kernel, devicetree,
	linux-kernel, imx, Josua Mayer
In-Reply-To: <20260524-lx2160-pci-v7-0-09370c23b952@solid-run.com>

The SoC dtsi has always enabled serdes block 1, enabled dpmac and
disabled pcie nodes.

Drop the superfluous status properties on these nodes.

Further drop crypto alias as SoM dtsi already set it.

Signed-off-by: Josua Mayer <josua@solid-run.com>
---
 .../boot/dts/freescale/fsl-lx2162a-clearfog.dts     | 21 ---------------------
 1 file changed, 21 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts b/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts
index f95e9c19bfc75..6fd85a5cac94e 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts
@@ -14,7 +14,6 @@ / {
 	compatible = "solidrun,lx2162a-clearfog", "solidrun,lx2162a-som", "fsl,lx2160a";
 
 	aliases {
-		crypto = &crypto;
 		i2c0 = &i2c0;
 		i2c1 = &i2c2;
 		i2c2 = &i2c4;
@@ -124,42 +123,36 @@ &dpmac11 {
 	phys = <&serdes_2 0>;
 	phy-handle = <&ethernet_phy3>;
 	phy-connection-type = "sgmii";
-	status = "okay";
 };
 
 &dpmac12 {
 	phys = <&serdes_2 1>;
 	phy-handle = <&ethernet_phy1>;
 	phy-connection-type = "sgmii";
-	status = "okay";
 };
 
 &dpmac13 {
 	phys = <&serdes_2 6>;
 	phy-handle = <&ethernet_phy6>;
 	phy-connection-type = "sgmii";
-	status = "okay";
 };
 
 &dpmac14 {
 	phys = <&serdes_2 7>;
 	phy-handle = <&ethernet_phy8>;
 	phy-connection-type = "sgmii";
-	status = "okay";
 };
 
 &dpmac15 {
 	phys = <&serdes_2 4>;
 	phy-handle = <&ethernet_phy4>;
 	phy-connection-type = "sgmii";
-	status = "okay";
 };
 
 &dpmac16 {
 	phys = <&serdes_2 5>;
 	phy-handle = <&ethernet_phy2>;
 	phy-connection-type = "sgmii";
-	status = "okay";
 };
 
 &dpmac17 {
@@ -170,14 +163,12 @@ &dpmac17 {
 	phys = <&serdes_2 2>;
 	phy-handle = <&ethernet_phy5>;
 	phy-connection-type = "sgmii";
-	status = "okay";
 };
 
 &dpmac18 {
 	phys = <&serdes_2 3>;
 	phy-handle = <&ethernet_phy7>;
 	phy-connection-type = "sgmii";
-	status = "okay";
 };
 
 &emdio1 {
@@ -314,14 +305,6 @@ pcieclk_i2c: i2c@2 {
 	};
 };
 
-&pcie3 {
-	status = "disabled";
-};
-
-&pcie4 {
-	status = "disabled";
-};
-
 &pcs_mdio3 {
 	status = "okay";
 };
@@ -370,10 +353,6 @@ &pcs_mdio18 {
 	status = "okay";
 };
 
-&serdes_1 {
-	status = "okay";
-};
-
 &serdes_2 {
 	status = "okay";
 };

-- 
2.51.0


^ permalink raw reply related

* [PATCH v7 5/9] dt-bindings: arm: fsl: Add solidrun lx2160a twins board
From: Josua Mayer @ 2026-05-24 14:54 UTC (permalink / raw)
  To: Shawn Guo, Li Yang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Rob Herring, Krzysztof Kozlowski, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
  Cc: Yazan Shhady, Jon Nettleton, linux-arm-kernel, devicetree,
	linux-kernel, imx, Josua Mayer
In-Reply-To: <20260524-lx2160-pci-v7-0-09370c23b952@solid-run.com>

The SolidRun LX2160A Twins board supports two configurations, one with
with a single CEX-7 module, and one with two (dual).

The single configuration is a specific assembly that maximises
connectivity for single cpu by routing some second cpu resources to the
first via zero-Ohm resistors.

The dual configuration was not yet tested and is intentionally omitted.

Initial review strongly suggests that the dual configuration will have
different bindings, because from either cpu point of view the board
appears different (e.g. different number of sfp, fewer i2c gpio).

Add binding for the single variant only.

Signed-off-by: Josua Mayer <josua@solid-run.com>
---
 Documentation/devicetree/bindings/arm/fsl.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml
index 0023cd1268075..1f11c1208c248 100644
--- a/Documentation/devicetree/bindings/arm/fsl.yaml
+++ b/Documentation/devicetree/bindings/arm/fsl.yaml
@@ -1868,6 +1868,7 @@ properties:
           - enum:
               - solidrun,clearfog-cx
               - solidrun,honeycomb
+              - solidrun,twins-single
           - const: solidrun,lx2160a-cex7
           - const: fsl,lx2160a
 

-- 
2.51.0


^ permalink raw reply related

* [PATCH v7 2/9] arm64: dts: lx2162a-clearfog: use rev2 SoC dtsi
From: Josua Mayer @ 2026-05-24 14:54 UTC (permalink / raw)
  To: Shawn Guo, Li Yang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Rob Herring, Krzysztof Kozlowski, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
  Cc: Yazan Shhady, Jon Nettleton, linux-arm-kernel, devicetree,
	linux-kernel, imx, Josua Mayer
In-Reply-To: <20260524-lx2160-pci-v7-0-09370c23b952@solid-run.com>

LX2160A and LX2162A are different pakages of the same silicon.
While LX2160A had two revisions, LX2162A was released later based on
LX2160A revision 2.

Commit a8fe6c8dfc40 ("arm64: dts: fsl-lx2160a: add rev2 support") has
added a new soc dtsi for revision 2.

Update LX2162A Clearfog description to use revision 2 dtsi.

Fixes: 5093b190f9ce ("arm64: dts: freescale: Add support for LX2162 SoM & Clearfog Board") # no-stable
Signed-off-by: Josua Mayer <josua@solid-run.com>
---
 arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts b/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts
index 9d50d3e2761da..f95e9c19bfc75 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts
@@ -6,7 +6,7 @@
 
 /dts-v1/;
 
-#include "fsl-lx2160a.dtsi"
+#include "fsl-lx2160a-rev2.dtsi"
 #include "fsl-lx2162a-sr-som.dtsi"
 
 / {

-- 
2.51.0


^ permalink raw reply related

* [PATCH v7 4/9] arm64: dts: lx2162a-clearfog: specify sfp ports led colour and function
From: Josua Mayer @ 2026-05-24 14:54 UTC (permalink / raw)
  To: Shawn Guo, Li Yang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Rob Herring, Krzysztof Kozlowski, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
  Cc: Yazan Shhady, Jon Nettleton, linux-arm-kernel, devicetree,
	linux-kernel, imx, Josua Mayer
In-Reply-To: <20260524-lx2160-pci-v7-0-09370c23b952@solid-run.com>

The LX2162A Clearfog board has a green LED on each of four SFP ports.

Describe in device-tree that their colour is green and function "lan".

Signed-off-by: Josua Mayer <josua@solid-run.com>
---
 arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts b/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts
index 6fd85a5cac94e..99ee2b1c0f13b 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts
@@ -6,6 +6,8 @@
 
 /dts-v1/;
 
+#include <dt-bindings/leds/common.h>
+
 #include "fsl-lx2160a-rev2.dtsi"
 #include "fsl-lx2162a-sr-som.dtsi"
 
@@ -38,6 +40,9 @@ leds {
 		compatible = "gpio-leds";
 
 		led_sfp_at: led-sfp-at {
+			color = <LED_COLOR_ID_GREEN>;
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <1>;
 			gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>; /* PROC_IRQ5 */
 			default-state = "off";
 			linux,default-trigger = "netdev";
@@ -45,6 +50,9 @@ led_sfp_at: led-sfp-at {
 		};
 
 		led_sfp_ab: led-sfp-ab {
+			color = <LED_COLOR_ID_GREEN>;
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <2>;
 			gpios = <&gpio2 11 GPIO_ACTIVE_HIGH>; /* PROC_IRQ11 */
 			default-state = "off";
 			linux,default-trigger = "netdev";
@@ -52,6 +60,9 @@ led_sfp_ab: led-sfp-ab {
 		};
 
 		led_sfp_bt: led-sfp-bt {
+			color = <LED_COLOR_ID_GREEN>;
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <3>;
 			gpios = <&gpio2 13 GPIO_ACTIVE_HIGH>; /* EVT1_B */
 			default-state = "off";
 			linux,default-trigger = "netdev";
@@ -59,6 +70,9 @@ led_sfp_bt: led-sfp-bt {
 		};
 
 		led_sfp_bb: led-sfp-bb {
+			color = <LED_COLOR_ID_GREEN>;
+			function = LED_FUNCTION_LAN;
+			function-enumerator = <4>;
 			gpios = <&gpio2 14 GPIO_ACTIVE_HIGH>; /* EVT2_B */
 			default-state = "off";
 			linux,default-trigger = "netdev";

-- 
2.51.0


^ permalink raw reply related

* [PATCH v7 1/9] arm64: dts: lx2160a-rev2: extend 32-bit, and add 64-bit pci regions
From: Josua Mayer @ 2026-05-24 14:54 UTC (permalink / raw)
  To: Shawn Guo, Li Yang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Rob Herring, Krzysztof Kozlowski, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
  Cc: Yazan Shhady, Jon Nettleton, linux-arm-kernel, devicetree,
	linux-kernel, imx, Josua Mayer
In-Reply-To: <20260524-lx2160-pci-v7-0-09370c23b952@solid-run.com>

LX2160 SoC pci-e controller supports 64-bit memory regions up to 16GB,
32-bit regions up to 3GB and 16-bit regions up to 64k.

For each pci-e controller:
- extend the existing 32-bit regions to 3GB size
- add 64-bit region
See [1] and [2] for boot messages showing ranges before and after.

On LX2160A Silicon revision 1, the pcie driver fails to program atu for
ranges larger than 4GB [3]. Therefore changes are limited to revision 2.

Similar memory allocation with similar flags was tested with UEFI and ACPI
on pcie3 and pcie5, on a variety of nxp vendor fork versions.

This patch was tested on Linux v7.1-rc1 and u-boot, with two pcie cards:
- pcie5: Radeon Pro WX2100
- pcie3: ADATA NVME

This fixes allocation of large, and 64-bit BARs as requested by many pci
cards - especially graphics processors or AI accelerators, e.g.:

[    2.941187] pci 0000:01:00.0: BAR 0: no space for [mem size 0x200000000 64bit pref]
[    2.948834] pci 0000:01:00.0: BAR 0: failed to assign [mem size 0x200000000 64bit pref]

[1] example of new allocations (pcie5):
[    1.182745] layerscape-pcie 3800000.pcie: host bridge /soc/pcie@3800000 ranges:
[    1.182760] layerscape-pcie 3800000.pcie:      MEM 0xa400000000..0xa7ffffffff -> 0xa400000000
[    1.182771] layerscape-pcie 3800000.pcie:      MEM 0xa040000000..0xa0ffffffff -> 0x0040000000
[    1.182778] layerscape-pcie 3800000.pcie:       IO 0xa000010000..0xa00001ffff -> 0x0000000000
[    1.183642] layerscape-pcie 3800000.pcie: iATU: unroll F, 256 ob, 24 ib, align 4K, limit 4G
[    1.385429] layerscape-pcie 3800000.pcie: PCIe Gen.3 x8 link up
[    1.385481] layerscape-pcie 3800000.pcie: PCI host bridge to bus 0001:00
[    1.385484] pci_bus 0001:00: root bus resource [bus 00-ff]
[    1.385488] pci_bus 0001:00: root bus resource [mem 0xa400000000-0xa7ffffffff pref]
[    1.385491] pci_bus 0001:00: root bus resource [mem 0xa040000000-0xa0ffffffff] (bus address [0x40000000-0xffffffff])
[    1.385494] pci_bus 0001:00: root bus resource [io  0x10000-0x1ffff] (bus address [0x0000-0xffff])
[    1.385516] pci 0001:00:00.0: [1957:8d80] type 01 class 0x060400 PCIe Root Port
[    1.385538] pci 0001:00:00.0: PCI bridge to [bus 01-ff]
[    1.385544] pci 0001:00:00.0:   bridge window [io  0x11000-0x11fff]
[    1.385548] pci 0001:00:00.0:   bridge window [mem 0xa040000000-0xa0502fffff]
[    1.385605] pci 0001:00:00.0: supports D1 D2
[    1.385607] pci 0001:00:00.0: PME# supported from D0 D1 D2 D3hot
[    1.386778] pci 0001:01:00.0: [1002:6995] type 00 class 0x030000 PCIe Legacy Endpoint
[    1.387336] pci 0001:01:00.0: BAR 0 [mem 0xa040000000-0xa04fffffff 64bit pref]
[    1.387368] pci 0001:01:00.0: BAR 2 [mem 0xa050000000-0xa0501fffff 64bit pref]
[    1.387385] pci 0001:01:00.0: BAR 4 [io  0x11000-0x110ff]
[    1.387402] pci 0001:01:00.0: BAR 5 [mem 0xa050200000-0xa05023ffff]
[    1.387418] pci 0001:01:00.0: ROM [mem 0xa050240000-0xa05025ffff pref]
[    1.387493] pci 0001:01:00.0: enabling Extended Tags
[    1.388960] pci 0001:01:00.0: supports D1 D2

[2] example of previous allocations (pcie5):
[    1.716744] layerscape-pcie 3800000.pcie: host bridge /soc/pcie@3800000 ranges:
[    1.724060] layerscape-pcie 3800000.pcie:      MEM 0xa040000000..0xa07fffffff -> 0x0040000000
[    1.733277] layerscape-pcie 3800000.pcie: iATU: unroll F, 256 ob, 24 ib, align 4K, limit 4G
[    1.836220] layerscape-pcie 3800000.pcie: PCIe Gen.3 x8 link up
[    1.842186] layerscape-pcie 3800000.pcie: PCI host bridge to bus 0001:00
[    1.848883] pci_bus 0001:00: root bus resource [bus 00-ff]
[    1.854363] pci_bus 0001:00: root bus resource [mem 0xa040000000-0xa07fffffff] (bus address [0x40000000-0x7fffffff])
[    1.864892] pci 0001:00:00.0: [1957:8d80] type 01 class 0x060400 PCIe Root Port
[    1.872216] pci 0001:00:00.0: PCI bridge to [bus 01-ff]
[    1.877438] pci 0001:00:00.0:   bridge window [io  0x1000-0x1fff]
[    1.883526] pci 0001:00:00.0:   bridge window [mem 0xa040000000-0xa0502fffff]

[3] error programming atu beyond 4GB:
[    1.716762] layerscape-pcie 3800000.pcie: host bridge /soc/pcie@3800000 ranges:
[    1.724080] layerscape-pcie 3800000.pcie:      MEM 0xa400000000..0xa7ffffffff -> 0xa400000000
[    1.732615] layerscape-pcie 3800000.pcie:      MEM 0xa040000000..0xa0ffffffff -> 0x0040000000
[    1.741142] layerscape-pcie 3800000.pcie:       IO 0xa010000000..0xa01000ffff -> 0x0000000000
[    1.750379] layerscape-pcie 3800000.pcie: iATU: unroll F, 256 ob, 24 ib, align 4K, limit 4G
[    1.759089] layerscape-pcie 3800000.pcie: Failed to set MEM range [mem 0xa400000000-0xa7ffffffff flags 0x2200]
[    1.769089] layerscape-pcie 3800000.pcie: probe with driver layerscape-pcie failed with error -22

[4] pci bootloaderp atching related errors with IORESOURCE_MEM_64 flag:
[    0.967809] layerscape-pcie 3800000.pcie: host bridge /soc/pcie@3800000 ranges:
[    0.967830] layerscape-pcie 3800000.pcie:      MEM 0xa400000000..0xa7ffffffff -> 0xa400000000
[    0.967842] layerscape-pcie 3800000.pcie:      MEM 0xa040000000..0xa0ffffffff -> 0x0040000000
[    0.967849] layerscape-pcie 3800000.pcie:       IO 0xa000010000..0xa00001ffff -> 0x0000000000
[    1.169315] pci 0000:01:00.0: [8086:1572] type 00 class 0x020000 PCIe Endpoint
[    1.169733] pci 0000:01:00.0: BAR 0 [mem 0x00000000-0x00ffffff 64bit pref]
[    1.169771] pci 0000:01:00.0: BAR 3 [mem 0x00000000-0x00007fff 64bit pref]
[    1.169796] pci 0000:01:00.0: ROM [mem 0x00000000-0x0007ffff pref]
[    1.173389] OF: /soc/pcie@3800000: no msi-map translation for id 0x100 on (null)
[    1.173515] OF: /soc/pcie@3800000: no iommu-map translation for id 0x100 on (null)

Signed-off-by: Josua Mayer <josua@solid-run.com>
---
 .../arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi | 30 +++++++++++++---------
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi
index f54005e37924b..db1ebee53f6f0 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi
@@ -14,8 +14,9 @@ &pcie1 {
 	      0x80 0x00000000 0x0 0x00002000>; /* configuration space */
 	reg-names = "regs", "config";
 
-	ranges = <0x81000000 0x0 0x00000000 0x80 0x00010000 0x0 0x00010000
-		  0x82000000 0x0 0x40000000 0x80 0x40000000 0x0 0x40000000>;
+	ranges = <0x81000000 0x00 0x00000000 0x80 0x00010000 0x00 0x00010000>, /* 16-Bit IO Window */
+		 <0x82000000 0x00 0x40000000 0x80 0x40000000 0x00 0xc0000000>, /* 32-Bit - non-prefetchable */
+		 <0xC3000000 0x84 0x00000000 0x84 0x00000000 0x04 0x00000000>; /* 64-Bit - prefetchable - 16GB */
 
 	interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
 	interrupt-names = "intr";
@@ -30,8 +31,9 @@ &pcie2 {
 	       0x88 0x00000000 0x0 0x00002000>; /* configuration space */
 	reg-names = "regs", "config";
 
-	ranges = <0x81000000 0x0 0x00000000 0x88 0x00010000 0x0 0x00010000
-		  0x82000000 0x0 0x40000000 0x88 0x40000000 0x0 0x40000000>;
+	ranges = <0x81000000 0x00 0x00000000 0x88 0x00010000 0x00 0x00010000>, /* 16-Bit IO Window */
+		 <0x82000000 0x00 0x40000000 0x88 0x40000000 0x00 0xc0000000>, /* 32-Bit - non-prefetchable */
+		 <0xC3000000 0x8c 0x00000000 0x8c 0x00000000 0x04 0x00000000>; /* 64-Bit - prefetchable - 16GB */
 
 	interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
 	interrupt-names = "intr";
@@ -46,8 +48,9 @@ &pcie3 {
 	       0x90 0x00000000 0x0 0x00002000>; /* configuration space */
 	reg-names = "regs", "config";
 
-	ranges = <0x81000000 0x0 0x00000000 0x90 0x00010000 0x0 0x00010000
-		  0x82000000 0x0 0x40000000 0x90 0x40000000 0x0 0x40000000>;
+	ranges = <0x81000000 0x00 0x00000000 0x90 0x00010000 0x00 0x00010000>, /* 16-Bit IO Window */
+		 <0x82000000 0x00 0x40000000 0x90 0x40000000 0x00 0xc0000000>, /* 32-Bit - non-prefetchable */
+		 <0xC3000000 0x94 0x00000000 0x94 0x00000000 0x04 0x00000000>; /* 64-Bit - prefetchable - 16GB */
 
 	interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
 	interrupt-names = "intr";
@@ -63,8 +66,9 @@ &pcie4 {
 	       0x98 0x00000000 0x0 0x00002000>; /* configuration space */
 	reg-names = "regs", "config";
 
-	ranges = <0x81000000 0x0 0x00000000 0x98 0x00010000 0x0 0x00010000
-		  0x82000000 0x0 0x40000000 0x98 0x40000000 0x0 0x40000000>;
+	ranges = <0x81000000 0x00 0x00000000 0x98 0x00010000 0x00 0x00010000>, /* 16-Bit IO Window */
+		 <0x82000000 0x00 0x40000000 0x98 0x40000000 0x00 0xc0000000>, /* 32-Bit - non-prefetchable */
+		 <0xC3000000 0x9c 0x00000000 0x9c 0x00000000 0x04 0x00000000>; /* 64-Bit - prefetchable - 16GB */
 
 	interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
 	interrupt-names = "intr";
@@ -79,8 +83,9 @@ &pcie5 {
 	       0xa0 0x00000000 0x0 0x00002000>; /* configuration space */
 	reg-names = "regs", "config";
 
-	ranges = <0x81000000 0x0 0x00000000 0xa0 0x00010000 0x0 0x00010000
-		  0x82000000 0x0 0x40000000 0xa0 0x40000000 0x0 0x40000000>;
+	ranges = <0x81000000 0x00 0x00000000 0xa0 0x00010000 0x00 0x00010000>, /* 16-Bit IO Window */
+		 <0x82000000 0x00 0x40000000 0xa0 0x40000000 0x00 0xc0000000>, /* 32-Bit - non-prefetchable */
+		 <0xC3000000 0xa4 0x00000000 0xa4 0x00000000 0x04 0x00000000>; /* 64-Bit - prefetchable - 16GB */
 
 	interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
 	interrupt-names = "intr";
@@ -95,8 +100,9 @@ &pcie6 {
 	       0xa8 0x00000000 0x0 0x00002000>; /* configuration space */
 	reg-names = "regs", "config";
 
-	ranges = <0x81000000 0x0 0x00000000 0xa8 0x00010000 0x0 0x00010000
-		  0x82000000 0x0 0x40000000 0xa8 0x40000000 0x0 0x40000000>;
+	ranges = <0x81000000 0x00 0x00000000 0xa8 0x00010000 0x00 0x00010000>, /* 16-Bit IO Window */
+		 <0x82000000 0x00 0x40000000 0xa8 0x40000000 0x00 0xc0000000>, /* 32-Bit - non-prefetchable */
+		 <0xC3000000 0xac 0x00000000 0xac 0x00000000 0x04 0x00000000>; /* 64-Bit - prefetchable - 16GB */
 
 	interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
 	interrupt-names = "intr";

-- 
2.51.0


^ permalink raw reply related

* [PATCH v7 0/9] arm64: dts: lx2160a: cleanups, add new board, large pci bars
From: Josua Mayer @ 2026-05-24 14:54 UTC (permalink / raw)
  To: Shawn Guo, Li Yang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Rob Herring, Krzysztof Kozlowski, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
  Cc: Yazan Shhady, Jon Nettleton, linux-arm-kernel, devicetree,
	linux-kernel, imx, Josua Mayer

This patch-set is made of 3 parts:

1. Extend lx2160 pci node ranges to support 16-bit, and large 64-bit
   bars. LX2160A SoC has always supported this, and SolidRun carried it
   in vendor fork for several years now.

2. Cleanup some status properties in LX2162A Clearfog dts.

3. Add description for solidrun twins baord with single LX2160A CEX-7
   module.

There are no inter-dependencies between the parts and they may apply
individually if necessary.

Signed-off-by: Josua Mayer <josua@solid-run.com>
---
Changes in v7:
- Dropped pcie silicon 1 changes because they add too much noise.
- Changed pcie range flags per sashiko feedback.
  This also fixed bootloader patching issues seen previously.
- Added CEX-7 module onboard USB Hub.
- Keep first usb controller disabled in cex-7 module.
- Added reasoning for adding nly single configuration binding to commit
  description.
  (Reported-by: Krzysztof Kozlowski <krzk@kernel.org>)
- Squashed DT label commits with their user (twins board dts).
  (Reported-by: Krzysztof Kozlowski <krzk@kernel.org>)
- Link to v6: https://lore.kernel.org/r/20260512-lx2160-pci-v6-0-d0ff72d3c983@solid-run.com

Changes in v6:
- Add explanation why IORESOURCE_MEM_64 flag is not set.
- Fixed pci bar size 1GB/4GB typo in pcie4 node.
- Enable twins board pcie controller node.
- Fixed function-enumerator value for led-sfp-3.
- Reverted accidental change of clearfog-cx soc revision.
- Link to v5: https://lore.kernel.org/r/20260510-lx2160-pci-v5-0-540b83852227@solid-run.com

Changes in v5:
- add new board
- add cleanups to existing solidrun boards
- pci: extend to lx2160a-rev2 dtsi
- pci: remove non-standard flags to pass dtbs_check
- Link to v4: https://lore.kernel.org/r/20260302-lx2160-pci-v4-1-30a30dc47ec6@solid-run.com

Changes in v4
- dropped accidentally added empty line at top of file:
- actually drop RFC prefix
- rebased on v7.0-rc1 and re-tested on v7.0-rc2
- Link to v3: https://lore.kernel.org/r/20250907-lx2160-pci-v3-1-bb66cc41b8f9@solid-run.com

Changes in v3:
- dropped rfc label
- adjusted flags
- split 16GB area into 4x4GB sections.
- enhance commit description with details explanation
- Link to v2: https://lore.kernel.org/r/20240429-lx2160-pci-v2-1-1b94576d6263@solid-run.com

Changes in v2:
- adjusted flags to fix several errors during probe and bar allocation
- explicitly tested with 2 pci cards on Debian (Linux 6.1)
- still rfc because a limitation in designware pci driver
- Link to v1: https://lore.kernel.org/r/20240321-lx2160-pci-v1-1-3673708f7eb6@solid-run.com

---
Josua Mayer (9):
      arm64: dts: lx2160a-rev2: extend 32-bit, and add 64-bit pci regions
      arm64: dts: lx2162a-clearfog: use rev2 SoC dtsi
      arm64: dts: lx2162a-clearfog: cleanup superfluous status properties
      arm64: dts: lx2162a-clearfog: specify sfp ports led colour and function
      dt-bindings: arm: fsl: Add solidrun lx2160a twins board
      arm64: dts: lx2160a-clearfog-itx: remove redundant dts version tag
      arm64: dts: lx2160a-clearfog-itx: move shared includes to dts
      arm64: dts: lx2160a-cex7: add usb hub
      arm64: dts: Add support for LX2160 Twins board in single configuration

 Documentation/devicetree/bindings/arm/fsl.yaml     |   1 +
 arch/arm64/boot/dts/freescale/Makefile             |   2 +
 .../arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi |  41 +-
 .../boot/dts/freescale/fsl-lx2160a-clearfog-cx.dts |   2 +
 .../dts/freescale/fsl-lx2160a-clearfog-itx.dtsi    |   7 +-
 .../boot/dts/freescale/fsl-lx2160a-half-twins.dts  | 830 +++++++++++++++++++++
 .../boot/dts/freescale/fsl-lx2160a-honeycomb.dts   |   2 +
 .../arm64/boot/dts/freescale/fsl-lx2160a-rev2.dtsi |  30 +-
 arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi     |  24 +-
 .../boot/dts/freescale/fsl-lx2162a-clearfog.dts    |  37 +-
 10 files changed, 915 insertions(+), 61 deletions(-)
---
base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
change-id: 20240118-lx2160-pci-4bdb196e58f3

Best regards,
-- 
Josua Mayer <josua@solid-run.com>


^ permalink raw reply

* RE: [PATCH 1/2] arm64: dts: renesas: r9a08g046: Add RSPI{0..2} nodes
From: Biju Das @ 2026-05-24 14:28 UTC (permalink / raw)
  To: biju.das.au, Geert Uytterhoeven, magnus.damm, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-renesas-soc@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, Prabhakar Mahadev Lad, biju.das.au
In-Reply-To: <20260519111958.233194-2-biju.das.jz@bp.renesas.com>

Hi All,

> -----Original Message-----
> From: Biju <biju.das.au@gmail.com>
> Sent: 19 May 2026 12:20
> Subject: [PATCH 1/2] arm64: dts: renesas: r9a08g046: Add RSPI{0..2} nodes
> 
> From: Biju Das <biju.das.jz@bp.renesas.com>
> 
> Add device tree nodes for the three RSPI channels on the RZ/G3L
> (R9A08G046) SoC.
> 
> Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
> ---
>  arch/arm64/boot/dts/renesas/r9a08g046.dtsi | 72 ++++++++++++++++++++++
>  1 file changed, 72 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/renesas/r9a08g046.dtsi b/arch/arm64/boot/dts/renesas/r9a08g046.dtsi
> index a53d579eaad2..1fc409ebdd44 100644
> --- a/arch/arm64/boot/dts/renesas/r9a08g046.dtsi
> +++ b/arch/arm64/boot/dts/renesas/r9a08g046.dtsi
> @@ -442,6 +442,78 @@ rsci3: serial@100f3000 {
>  			status = "disabled";
>  		};
> 
> +		rspi0: spi@100b0000 {
> +			compatible = "renesas,r9a08g046-rspi";
> +			reg = <0 0x100b0000 0 0x400>;

The size is 4K, so it should be 0x1000, same for othe nodes.

Cheers,
Biju

> +			interrupts = <GIC_SPI 440 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 441 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 442 IRQ_TYPE_EDGE_RISING>,
> +				     <GIC_SPI 443 IRQ_TYPE_EDGE_RISING>,
> +				     <GIC_SPI 444 IRQ_TYPE_EDGE_RISING>;
> +			interrupt-names = "idle", "error", "end", "rx", "tx";
> +			clocks = <&cpg CPG_MOD R9A08G046_RSPI0_PCLK>,
> +				 <&cpg CPG_MOD R9A08G046_RSPI0_TCLK>;
> +			clock-names = "pclk", "tclk";
> +			resets = <&cpg R9A08G046_RSPI0_PRESETN>,
> +				 <&cpg R9A08G046_RSPI0_TRESETN>;
> +			reset-names = "presetn", "tresetn";
> +			dmas = <&dmac 0x26f2>, <&dmac 0x26f1>;
> +			dma-names = "rx", "tx";
> +			power-domains = <&cpg>;
> +			num-cs = <1>;
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +			status = "disabled";
> +		};
> +
> +		rspi1: spi@100e9000 {
> +			compatible = "renesas,r9a08g046-rspi";
> +			reg = <0 0x100e9000 0 0x400>;
> +			interrupts = <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 446 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 447 IRQ_TYPE_EDGE_RISING>,
> +				     <GIC_SPI 448 IRQ_TYPE_EDGE_RISING>,
> +				     <GIC_SPI 449 IRQ_TYPE_EDGE_RISING>;
> +			interrupt-names = "idle", "error", "end", "rx", "tx";
> +			clocks = <&cpg CPG_MOD R9A08G046_RSPI1_PCLK>,
> +				 <&cpg CPG_MOD R9A08G046_RSPI1_TCLK>;
> +			clock-names = "pclk", "tclk";
> +			resets = <&cpg R9A08G046_RSPI1_PRESETN>,
> +				 <&cpg R9A08G046_RSPI1_TRESETN>;
> +			reset-names = "presetn", "tresetn";
> +			dmas = <&dmac 0x26f6>, <&dmac 0x26f5>;
> +			dma-names = "rx", "tx";
> +			power-domains = <&cpg>;
> +			num-cs = <1>;
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +			status = "disabled";
> +		};
> +
> +		rspi2: spi@100ea000 {
> +			compatible = "renesas,r9a08g046-rspi";
> +			reg = <0 0x100ea000 0 0x400>;
> +			interrupts = <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 451 IRQ_TYPE_LEVEL_HIGH>,
> +				     <GIC_SPI 452 IRQ_TYPE_EDGE_RISING>,
> +				     <GIC_SPI 453 IRQ_TYPE_EDGE_RISING>,
> +				     <GIC_SPI 454 IRQ_TYPE_EDGE_RISING>;
> +			interrupt-names = "idle", "error", "end", "rx", "tx";
> +			clocks = <&cpg CPG_MOD R9A08G046_RSPI2_PCLK>,
> +				 <&cpg CPG_MOD R9A08G046_RSPI2_TCLK>;
> +			clock-names = "pclk", "tclk";
> +			resets = <&cpg R9A08G046_RSPI2_PRESETN>,
> +				 <&cpg R9A08G046_RSPI2_TRESETN>;
> +			reset-names = "presetn", "tresetn";
> +			dmas = <&dmac 0x26fa>, <&dmac 0x26f9>;
> +			dma-names = "rx", "tx";
> +			power-domains = <&cpg>;
> +			num-cs = <1>;
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +			status = "disabled";
> +		};
> +
>  		canfd: can@100c0000 {
>  			reg = <0 0x100c0000 0 0x20000>;
>  			/* placeholder */
> --
> 2.43.0


^ permalink raw reply

* Re: [PATCH v2 3/3] clk: add support for siflower sf21-topcrm
From: sashiko-bot @ 2026-05-24 14:02 UTC (permalink / raw)
  To: Chuanhong Guo; +Cc: devicetree, conor+dt, robh
In-Reply-To: <20260524-sf21-topcrm-v2-3-4527aae05c3d@gmail.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Holding a raw spinlock and disabling interrupts while busy-waiting for up to 1ms.
- [High] Global clock structures are mutated with pointers to dynamically allocated memory, causing dangling pointers on probe failure or driver unbind.
--

commit 479eb0c843e2bfaa965d0cb0f125d0ed4dd0cf0b
Author: Chuanhong Guo <gch981213@gmail.com>

clk: add support for siflower sf21-topcrm

This commit adds a driver for the Toplevel clock and reset controller
found on Siflower SF21A6826/SF21H8898 SoCs. It includes control for 3
PLLs, several clock mux/gate/divider blocks, and a reset register.

> diff --git a/drivers/clk/siflower/clk-sf21-topcrm.c b/drivers/clk/siflower/clk-sf21-topcrm.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/clk/siflower/clk-sf21-topcrm.c
[ ... ]
> +static int sf21_cmnpll_vco_set_rate(struct clk_hw *hw, unsigned long rate,
> +				    unsigned long parent_rate)
> +{
> +	struct sf_clk_common *priv = hw_to_sf_clk_common(hw);
> +	unsigned long fbdiv, refdiv;
> +	u32 val;
> +
> +	rational_best_approximation(rate, parent_rate, FIELD_MAX(PLL_CMN_FBDIV),
> +				    FIELD_MAX(PLL_CMN_REFDIV), &fbdiv, &refdiv);
> +	if (!refdiv || !fbdiv)
> +		return -EINVAL;
> +
> +	guard(raw_spinlock_irqsave)(priv->lock);
> +
> +	sf_rmw(priv, PLL_CMN_CFG1, PLL_CMN_REFDIV | PLL_CMN_FBDIV | PLL_CMN_PD,
> +	       FIELD_PREP(PLL_CMN_REFDIV, refdiv) |
> +		       FIELD_PREP(PLL_CMN_FBDIV, fbdiv));
> +	sf_writel(priv, CFG_LOAD, BIT(CFG_LOAD_CMN_PLL_BIT));
> +	sf_writel(priv, CFG_LOAD, 0);
> +
> +	return readl_poll_timeout_atomic(priv->base + PLL_CMN_LOCK, val, val & 1,
> +					0, PLL_LOCK_TIMEOUT_US);
> +}

[Severity: High]
Does this code hold the raw spinlock with interrupts disabled for up to 1ms
while polling for the PLL to lock?

Because guard() releases the lock at the end of the variable's scope, the
lock remains held during the readl_poll_timeout_atomic() call. Tightly
spinning for 1ms with interrupts disabled could cause system latency spikes
or RCU stalls.

Would it be better to use scoped_guard() for the sf_rmw() and sf_writel()
calls so the lock is dropped before the polling loop?

[ ... ]
> +static int sf21_pciepll_vco_enable(struct clk_hw *hw)
> +{
> +	struct sf_clk_common *priv = hw_to_sf_clk_common(hw);
> +	u32 val;
> +
> +	guard(raw_spinlock_irqsave)(priv->lock);
> +	sf_rmw(priv, PLL_PCIE_CFG1, 0, PLL_PCIE_PLLEN);
> +	sf_writel(priv, CFG_LOAD, BIT(CFG_LOAD_PCIE_PLL_BIT));
> +	sf_writel(priv, CFG_LOAD, 0);
> +	return readl_poll_timeout_atomic(priv->base + PLL_PCIE_LOCK, val,
> +					 val & 1, 0, PLL_LOCK_TIMEOUT_US);
> +}

[Severity: High]
This appears to have the same issue mentioned above where a raw spinlock
is held with interrupts disabled during a 1ms polling loop.

[ ... ]
> +static struct sf_clk_common cmnpll_vco = {
> +	.hw.init = CLK_HW_INIT_PARENTS_DATA("cmnpll_vco", sf21_ref_parent,
> +					    &sf21_cmnpll_vco_ops, 0),
> +};
[ ... ]
> +static struct clk_hw_onecell_data sf21_hw_clks = {
> +	.num = SF21_NUM_CLKS,
> +	.hws = {
> +		[SF21_CLK_CMNPLL_VCO] = &cmnpll_vco.hw,
[ ... ]
> +static int sf21_topcrm_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct sf21_clk_ctrl *ctrl;
> +	int i, ret;
> +
> +	ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
> +	if (!ctrl)
> +		return -ENOMEM;
> +
> +	ctrl->base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(ctrl->base))
> +		return dev_err_probe(dev, PTR_ERR(ctrl->base),
> +				     "failed to map resources\n");
> +
> +	raw_spin_lock_init(&ctrl->clk_lock);
> +	spin_lock_init(&ctrl->rst_lock);
> +
> +	for (i = 0; i < sf21_hw_clks.num; i++) {
> +		struct clk_hw *hw = sf21_hw_clks.hws[i];
> +		struct sf_clk_common *common;
> +
> +		if (!hw)
> +			continue;
> +		common = hw_to_sf_clk_common(hw);
> +		common->base = ctrl->base;
> +		common->lock = &ctrl->clk_lock;
> +		ret = devm_clk_hw_register(dev, hw);
> +		if (ret)
> +			return dev_err_probe(dev, ret,
> +					     "failed to register clock %d\n",
> +					     i);
> +	}

[Severity: High]
Does this setup mutate the global static clock structures (like cmnpll_vco)
with pointers to the dynamically allocated ctrl memory?

If probe() fails later or the driver unbinds, devm_kzalloc will free ctrl,
potentially leaving dangling pointers in the global clock structures. This
could result in a use-after-free or corrupt the clock framework's internal
tree if the driver is probed again later.

Should the clock structures be dynamically allocated per-device or embedded
in a driver-private struct instead of using global state?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260524-sf21-topcrm-v2-0-4527aae05c3d@gmail.com?part=3

^ permalink raw reply

* [PATCH v2 3/3] clk: add support for siflower sf21-topcrm
From: Chuanhong Guo @ 2026-05-24 13:13 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Philipp Zabel, Yao Zi
  Cc: linux-riscv, linux-kernel, linux-clk, devicetree, Chuanhong Guo
In-Reply-To: <20260524-sf21-topcrm-v2-0-4527aae05c3d@gmail.com>

This commit adds a driver for the Toplevel clock and reset controller
found on Siflower SF21A6826/SF21H8898 SoCs.
This block contains control for 3 PLLs, several clock mux/gate/divider
blocks, and a reset register for on-chip peripherals.

There are also two registers for enabling PCIe clock output in this
block. They aren't covered by this patch because I can't test those
without a PCIe driver. These will be added with the PCIe driver
patchset later after I get that working.

Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
---
 drivers/clk/Kconfig                    |    1 +
 drivers/clk/Makefile                   |    1 +
 drivers/clk/siflower/Kconfig           |   23 +
 drivers/clk/siflower/Makefile          |    1 +
 drivers/clk/siflower/clk-sf21-topcrm.c | 1017 ++++++++++++++++++++++++++++++++
 5 files changed, 1043 insertions(+)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 1717ce75a907..0fb6a69bb329 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -529,6 +529,7 @@ source "drivers/clk/renesas/Kconfig"
 source "drivers/clk/rockchip/Kconfig"
 source "drivers/clk/samsung/Kconfig"
 source "drivers/clk/sifive/Kconfig"
+source "drivers/clk/siflower/Kconfig"
 source "drivers/clk/socfpga/Kconfig"
 source "drivers/clk/sophgo/Kconfig"
 source "drivers/clk/spacemit/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index cc108a75a900..8ac25e6694a7 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -145,6 +145,7 @@ obj-y					+= renesas/
 obj-$(CONFIG_COMMON_CLK_ROCKCHIP)	+= rockchip/
 obj-$(CONFIG_COMMON_CLK_SAMSUNG)	+= samsung/
 obj-$(CONFIG_CLK_SIFIVE)		+= sifive/
+obj-$(CONFIG_CLK_SIFLOWER)		+= siflower/
 obj-y					+= socfpga/
 obj-y					+= sophgo/
 obj-y					+= spacemit/
diff --git a/drivers/clk/siflower/Kconfig b/drivers/clk/siflower/Kconfig
new file mode 100644
index 000000000000..25e94828360b
--- /dev/null
+++ b/drivers/clk/siflower/Kconfig
@@ -0,0 +1,23 @@
+# SPDX-License-Identifier: GPL-2.0
+
+menuconfig CLK_SIFLOWER
+	bool "Clock driver for Siflower SoCs"
+	depends on ARCH_SIFLOWER || COMPILE_TEST
+	default ARCH_SIFLOWER
+	help
+	  Clock drivers for Siflower Linux-capable SoCs.
+
+if CLK_SIFLOWER
+
+config CLK_SF21_TOPCRM
+	tristate "Clock driver for Siflower SF21 toplevel clock & reset module"
+	depends on ARCH_SIFLOWER || COMPILE_TEST
+	default ARCH_SIFLOWER
+	select RESET_CONTROLLER
+	select RATIONAL
+	help
+	  Supports the toplevel clock and reset module in Siflower SF21 SoCs.
+	  If this kernel is meant to run on Siflower SF21A6826 or SF21H8898,
+	  enable this driver.
+
+endif
diff --git a/drivers/clk/siflower/Makefile b/drivers/clk/siflower/Makefile
new file mode 100644
index 000000000000..952a470a4308
--- /dev/null
+++ b/drivers/clk/siflower/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_CLK_SF21_TOPCRM) += clk-sf21-topcrm.o
diff --git a/drivers/clk/siflower/clk-sf21-topcrm.c b/drivers/clk/siflower/clk-sf21-topcrm.c
new file mode 100644
index 000000000000..ad96a2ff97ac
--- /dev/null
+++ b/drivers/clk/siflower/clk-sf21-topcrm.c
@@ -0,0 +1,1017 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dt-bindings/clock/siflower,sf21-topcrm.h>
+#include <dt-bindings/reset/siflower,sf21-topcrm.h>
+#include <linux/bitfield.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/rational.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+struct sf_clk_common {
+	void __iomem	*base;
+	/* Serializes register RMW sequences by clock ops. */
+	raw_spinlock_t	*lock;
+	struct clk_hw	hw;
+};
+
+static const struct clk_parent_data sf21_ref_parent[] = {
+	{ .index = 0 },
+};
+
+static inline struct sf_clk_common *hw_to_sf_clk_common(struct clk_hw *hw)
+{
+	return container_of(hw, struct sf_clk_common, hw);
+}
+
+static inline u32 sf_readl(struct sf_clk_common *priv, u32 reg)
+{
+	return readl(priv->base + reg);
+}
+
+static inline void sf_writel(struct sf_clk_common *priv, u32 reg, u32 val)
+{
+	return writel(val, priv->base + reg);
+}
+
+static inline void sf_rmw(struct sf_clk_common *priv, u32 reg, u32 clr, u32 set)
+{
+	u32 val;
+
+	val = sf_readl(priv, reg);
+	val &= ~clr;
+	val |= set;
+	sf_writel(priv, reg, val);
+}
+
+struct sf_dual_divider {
+	struct sf_clk_common common;
+	u8 div_reg;
+	u8 div1_offs;
+	u8 div2_offs;
+	u8 en_reg;
+	u8 en_bit;
+	u16 load_reg;
+	u8 load_bit;
+	u8 flags;
+};
+
+#define SF_DUAL_DIVIDER_DIV_MASK	GENMASK(2, 0)
+#define SF_DUAL_DIVIDER_START_FROM_1	BIT(0)
+
+static unsigned long sf21_dualdiv_round_rate(unsigned long rate,
+					     unsigned long parent_rate,
+					     unsigned int max_div,
+					     unsigned int *diva,
+					     unsigned int *divb)
+{
+	unsigned int div = DIV_ROUND_CLOSEST(parent_rate, rate);
+	unsigned int best_diff, da, db, cur_div, cur_diff;
+
+	if (div <= 1) {
+		*diva = 1;
+		*divb = 1;
+		return parent_rate;
+	}
+
+	best_diff = div - 1;
+	*diva = 1;
+	*divb = 1;
+
+	for (da = 1; da <= max_div; da++) {
+		db = DIV_ROUND_CLOSEST(div, da);
+		if (db > da)
+			db = da;
+
+		cur_div = da * db;
+		if (div > cur_div)
+			cur_diff = div - cur_div;
+		else
+			cur_diff = cur_div - div;
+
+		if (cur_diff < best_diff) {
+			best_diff = cur_diff;
+			*diva = da;
+			*divb = db;
+		}
+		if (cur_diff == 0)
+			break;
+	}
+
+	return parent_rate / *diva / *divb;
+}
+
+static unsigned int sf21_dual_divider_max(struct sf_dual_divider *priv)
+{
+	return FIELD_MAX(SF_DUAL_DIVIDER_DIV_MASK) +
+	       !!(priv->flags & SF_DUAL_DIVIDER_START_FROM_1);
+}
+
+static int sf21_dual_divider_determine_rate(struct clk_hw *hw,
+					    struct clk_rate_request *req)
+{
+	struct sf_dual_divider *priv =
+		container_of(hw, struct sf_dual_divider, common.hw);
+	unsigned int diva, divb;
+
+	if (!req->rate)
+		return -EINVAL;
+
+	req->rate = sf21_dualdiv_round_rate(req->rate, req->best_parent_rate,
+					    sf21_dual_divider_max(priv),
+					    &diva, &divb);
+
+	return 0;
+}
+
+static int sf21_dual_divider_set_rate(struct clk_hw *hw, unsigned long rate,
+				      unsigned long parent_rate)
+{
+	struct sf_dual_divider *priv =
+		container_of(hw, struct sf_dual_divider, common.hw);
+	struct sf_clk_common *cmn = hw_to_sf_clk_common(hw);
+	unsigned int div1, div2;
+
+	if (!rate)
+		return -EINVAL;
+
+	sf21_dualdiv_round_rate(rate, parent_rate, sf21_dual_divider_max(priv),
+				&div1, &div2);
+
+	if (priv->flags & SF_DUAL_DIVIDER_START_FROM_1) {
+		div1--;
+		div2--;
+	}
+
+	guard(raw_spinlock_irqsave)(cmn->lock);
+	sf_rmw(cmn, priv->div_reg,
+	       (SF_DUAL_DIVIDER_DIV_MASK << priv->div1_offs) |
+		       (SF_DUAL_DIVIDER_DIV_MASK << priv->div2_offs),
+	       (div1 << priv->div1_offs) | (div2 << priv->div2_offs));
+	sf_writel(cmn, priv->load_reg, BIT(priv->load_bit));
+	sf_writel(cmn, priv->load_reg, 0);
+	return 0;
+}
+
+static unsigned long sf21_dual_divider_recalc_rate(struct clk_hw *hw,
+						   unsigned long parent_rate)
+{
+	struct sf_dual_divider *priv =
+		container_of(hw, struct sf_dual_divider, common.hw);
+	struct sf_clk_common *cmn = hw_to_sf_clk_common(hw);
+	u32 cfg = sf_readl(cmn, priv->div_reg);
+	unsigned long div1 = (cfg >> priv->div1_offs) &
+			     SF_DUAL_DIVIDER_DIV_MASK;
+	unsigned long div2 = (cfg >> priv->div2_offs) &
+			     SF_DUAL_DIVIDER_DIV_MASK;
+
+	if (priv->flags & SF_DUAL_DIVIDER_START_FROM_1) {
+		div1++;
+		div2++;
+	} else if (!div1 || !div2) {
+		return 0;
+	}
+
+	return parent_rate / div1 / div2;
+}
+
+static int sf21_dual_divider_enable(struct clk_hw *hw)
+{
+	struct sf_dual_divider *priv =
+		container_of(hw, struct sf_dual_divider, common.hw);
+	struct sf_clk_common *cmn = hw_to_sf_clk_common(hw);
+
+	guard(raw_spinlock_irqsave)(priv->common.lock);
+	sf_rmw(cmn, priv->en_reg, 0, BIT(priv->en_bit));
+	sf_writel(cmn, priv->load_reg, BIT(priv->load_bit));
+	sf_writel(cmn, priv->load_reg, 0);
+	return 0;
+}
+
+static void sf21_dual_divider_disable(struct clk_hw *hw)
+{
+	struct sf_dual_divider *priv =
+		container_of(hw, struct sf_dual_divider, common.hw);
+	struct sf_clk_common *cmn = hw_to_sf_clk_common(hw);
+
+	guard(raw_spinlock_irqsave)(priv->common.lock);
+	sf_rmw(cmn, priv->en_reg, BIT(priv->en_bit), 0);
+	sf_writel(cmn, priv->load_reg, BIT(priv->load_bit));
+	sf_writel(cmn, priv->load_reg, 0);
+}
+
+static int sf21_dual_divider_is_enabled(struct clk_hw *hw)
+{
+	struct sf_dual_divider *priv =
+		container_of(hw, struct sf_dual_divider, common.hw);
+	struct sf_clk_common *cmn = hw_to_sf_clk_common(hw);
+
+	return sf_readl(cmn, priv->en_reg) & BIT(priv->en_bit) ? 1 : 0;
+}
+
+#define PLL_CMN_CFG1		0x0
+#define  PLL_CMN_BYPASS		BIT(27)
+#define  PLL_CMN_PD		BIT(26)
+#define  PLL_CMN_FBDIV		GENMASK(25, 14)
+#define  PLL_CMN_POSTDIV_PD	13
+#define  PLL_CMN_VCO_PD		BIT(12)
+#define  PLL_CMN_POSTDIV1_OFFS	9
+#define  PLL_CMN_POSTDIV2_OFFS	6
+#define  PLL_CMN_REFDIV		GENMASK(5, 0)
+
+#define PLL_CMN_LOCK		0xc8
+#define PLL_DDR_LOCK		0xcc
+#define PLL_PCIE_LOCK		0xd4
+
+#define CFG_LOAD		0x100
+#define  CFG_LOAD_PCIE_PLL_BIT	4
+#define  CFG_LOAD_DDR_PLL_BIT	2
+#define  CFG_LOAD_CMN_PLL_BIT	1
+#define  CFG_LOAD_DIV_BIT	0
+
+#define PLL_LOCK_TIMEOUT_US	1000
+
+static unsigned long sf21_cmnpll_vco_recalc_rate(struct clk_hw *hw,
+						 unsigned long parent_rate)
+{
+	struct sf_clk_common *priv = hw_to_sf_clk_common(hw);
+	u32 cfg = sf_readl(priv, PLL_CMN_CFG1);
+	unsigned long refdiv = FIELD_GET(PLL_CMN_REFDIV, cfg);
+	unsigned long fbdiv = FIELD_GET(PLL_CMN_FBDIV, cfg);
+
+	if (!refdiv || !fbdiv)
+		return 0;
+
+	return div_u64((u64)parent_rate * fbdiv, refdiv);
+}
+
+static int sf21_cmnpll_vco_determine_rate(struct clk_hw *hw,
+					  struct clk_rate_request *req)
+{
+	unsigned long fbdiv, refdiv;
+
+	rational_best_approximation(req->rate, req->best_parent_rate,
+				    FIELD_MAX(PLL_CMN_FBDIV),
+				    FIELD_MAX(PLL_CMN_REFDIV), &fbdiv, &refdiv);
+	if (!refdiv || !fbdiv)
+		return -EINVAL;
+
+	req->rate = div_u64((u64)req->best_parent_rate * fbdiv, refdiv);
+
+	return 0;
+}
+
+static int sf21_cmnpll_vco_set_rate(struct clk_hw *hw, unsigned long rate,
+				    unsigned long parent_rate)
+{
+	struct sf_clk_common *priv = hw_to_sf_clk_common(hw);
+	unsigned long fbdiv, refdiv;
+	u32 val;
+
+	rational_best_approximation(rate, parent_rate, FIELD_MAX(PLL_CMN_FBDIV),
+				    FIELD_MAX(PLL_CMN_REFDIV), &fbdiv, &refdiv);
+	if (!refdiv || !fbdiv)
+		return -EINVAL;
+
+	guard(raw_spinlock_irqsave)(priv->lock);
+
+	sf_rmw(priv, PLL_CMN_CFG1, PLL_CMN_REFDIV | PLL_CMN_FBDIV | PLL_CMN_PD,
+	       FIELD_PREP(PLL_CMN_REFDIV, refdiv) |
+		       FIELD_PREP(PLL_CMN_FBDIV, fbdiv));
+	sf_writel(priv, CFG_LOAD, BIT(CFG_LOAD_CMN_PLL_BIT));
+	sf_writel(priv, CFG_LOAD, 0);
+
+	return readl_poll_timeout_atomic(priv->base + PLL_CMN_LOCK, val, val & 1,
+					0, PLL_LOCK_TIMEOUT_US);
+}
+
+static const struct clk_ops sf21_cmnpll_vco_ops = {
+	.recalc_rate = sf21_cmnpll_vco_recalc_rate,
+	.determine_rate = sf21_cmnpll_vco_determine_rate,
+	.set_rate = sf21_cmnpll_vco_set_rate,
+};
+
+static struct sf_clk_common cmnpll_vco = {
+	.hw.init = CLK_HW_INIT_PARENTS_DATA("cmnpll_vco", sf21_ref_parent,
+					    &sf21_cmnpll_vco_ops, 0),
+};
+
+static const struct clk_ops sf21_cmnpll_postdiv_ops = {
+	.recalc_rate = sf21_dual_divider_recalc_rate,
+	.determine_rate = sf21_dual_divider_determine_rate,
+	.set_rate = sf21_dual_divider_set_rate,
+};
+
+static struct sf_dual_divider cmnpll_postdiv = {
+	.common.hw.init = CLK_HW_INIT_HW("cmnpll_postdiv", &cmnpll_vco.hw,
+				  &sf21_cmnpll_postdiv_ops, 0),
+	.div_reg = PLL_CMN_CFG1,
+	.div1_offs = PLL_CMN_POSTDIV1_OFFS,
+	.div2_offs = PLL_CMN_POSTDIV2_OFFS,
+	.load_reg = CFG_LOAD,
+	.load_bit = CFG_LOAD_CMN_PLL_BIT,
+};
+
+#define PLL_DDR_CFG1		0x18
+#define  PLL_DDR_BYPASS		BIT(23)
+#define  PLL_DDR_PLLEN		BIT(22)
+#define  PLL_DDR_4PHASEEN	BIT(21)
+#define  PLL_DDR_POSTDIVEN	BIT(20)
+#define  PLL_DDR_DSMEN		BIT(19)
+#define  PLL_DDR_DACEN		BIT(18)
+#define  PLL_DDR_DSKEWCALBYP	BIT(17)
+#define  PLL_DDR_DSKEWCALCNT	GENMASK(16, 14)
+#define  PLL_DDR_DSKEWCALEN	BIT(13)
+#define  PLL_DDR_DSKEWCALIN	GENMASK(12, 1)
+#define  PLL_DDR_DSKEWFASTCAL	BIT(0)
+
+#define PLL_DDR_CFG2		0x1c
+#define  PLL_DDR_POSTDIV1	GENMASK(29, 27)
+#define  PLL_DDR_POSTDIV2	GENMASK(26, 24)
+#define  PLL_DDR_FRAC		GENMASK(23, 0)
+
+#define PLL_DDR_CFG3		0x20
+#define  PLL_DDR_FBDIV		GENMASK(17, 6)
+#define  PLL_DDR_REFDIV		GENMASK(5, 0)
+
+static unsigned long
+sf21_ddrpll_postdiv_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct sf_clk_common *priv = hw_to_sf_clk_common(hw);
+	u32 cfg2 = sf_readl(priv, PLL_DDR_CFG2);
+	u32 postdiv1 = FIELD_GET(PLL_DDR_POSTDIV1, cfg2);
+	u32 postdiv2 = FIELD_GET(PLL_DDR_POSTDIV2, cfg2);
+	u32 cfg3 = sf_readl(priv, PLL_DDR_CFG3);
+	u32 fbdiv = FIELD_GET(PLL_DDR_FBDIV, cfg3);
+	u32 refdiv = FIELD_GET(PLL_DDR_REFDIV, cfg3);
+
+	if (!refdiv || !fbdiv || !postdiv1 || !postdiv2)
+		return 0;
+
+	return div_u64((u64)parent_rate * fbdiv, refdiv * postdiv1 * postdiv2);
+}
+
+static const struct clk_ops sf21_ddrpll_postdiv_ops = {
+	.recalc_rate = sf21_ddrpll_postdiv_recalc_rate,
+};
+
+static struct sf_clk_common ddrpll_postdiv = {
+	.hw.init = CLK_HW_INIT_PARENTS_DATA("ddrpll_postdiv",
+					    sf21_ref_parent,
+					    &sf21_ddrpll_postdiv_ops, 0),
+};
+
+#define PLL_PCIE_CFG1		0x4c
+#define  PLL_PCIE_PLLEN		BIT(31)
+#define  PLL_PCIE_POSTDIV0PRE	BIT(30)
+#define  PLL_PCIE_REFDIV	GENMASK(29, 24)
+#define  PLL_PCIE_FRAC		GENMASK(23, 0)
+
+#define PLL_PCIE_CFG2		0x50
+#define  PLL_PCIE_FOUTEN_BIT(i)	(28 + (i))
+#define  PLL_PCIE_BYPASS(i)	BIT(24 + (i))
+#define  PLL_PCIE_PDIV1_OFFS(i)	(21 - 6 * (i))
+#define  PLL_PCIE_PDIV2_OFFS(i)	(18 - 6 * (i))
+#define  PLL_PCIE_PDIV_MASK	GENMASK(2, 0)
+
+#define PLL_PCIE_CFG3		0x54
+#define  PLL_PCIE_DSKEWFASTCAL	BIT(31)
+#define  PLL_PCIE_DACEN		BIT(30)
+#define  PLL_PCIE_DSMEN		BIT(29)
+#define  PLL_PCIE_DSKEWCALEN	BIT(28)
+#define  PLL_PCIE_DSKEWCALBYP	BIT(27)
+#define  PLL_PCIE_DSKEWCALCNT	GENMASK(26, 24)
+#define  PLL_PCIE_DSKEWCALIN	GENMASK(23, 12)
+#define  PLL_PCIE_FBDIV		GENMASK(11, 0)
+
+static unsigned long
+sf21_pciepll_vco_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct sf_clk_common *priv = hw_to_sf_clk_common(hw);
+	u32 cfg1 = sf_readl(priv, PLL_PCIE_CFG1);
+	unsigned long refdiv = FIELD_GET(PLL_PCIE_REFDIV, cfg1);
+	u32 cfg3 = sf_readl(priv, PLL_PCIE_CFG3);
+	unsigned long fbdiv = FIELD_GET(PLL_PCIE_FBDIV, cfg3);
+
+	if (!refdiv || !fbdiv)
+		return 0;
+
+	return div_u64((u64)parent_rate * fbdiv, refdiv * 4);
+}
+
+static int sf21_pciepll_vco_enable(struct clk_hw *hw)
+{
+	struct sf_clk_common *priv = hw_to_sf_clk_common(hw);
+	u32 val;
+
+	guard(raw_spinlock_irqsave)(priv->lock);
+	sf_rmw(priv, PLL_PCIE_CFG1, 0, PLL_PCIE_PLLEN);
+	sf_writel(priv, CFG_LOAD, BIT(CFG_LOAD_PCIE_PLL_BIT));
+	sf_writel(priv, CFG_LOAD, 0);
+	return readl_poll_timeout_atomic(priv->base + PLL_PCIE_LOCK, val,
+					 val & 1, 0, PLL_LOCK_TIMEOUT_US);
+}
+
+static void sf21_pciepll_vco_disable(struct clk_hw *hw)
+{
+	struct sf_clk_common *priv = hw_to_sf_clk_common(hw);
+
+	guard(raw_spinlock_irqsave)(priv->lock);
+	sf_rmw(priv, PLL_PCIE_CFG1, PLL_PCIE_PLLEN, 0);
+	sf_writel(priv, CFG_LOAD, BIT(CFG_LOAD_PCIE_PLL_BIT));
+	sf_writel(priv, CFG_LOAD, 0);
+}
+
+static int sf21_pciepll_vco_is_enabled(struct clk_hw *hw)
+{
+	struct sf_clk_common *priv = hw_to_sf_clk_common(hw);
+
+	return !!(sf_readl(priv, PLL_PCIE_CFG1) & PLL_PCIE_PLLEN);
+}
+
+static const struct clk_ops sf21_pciepll_vco_ops = {
+	.enable = sf21_pciepll_vco_enable,
+	.disable = sf21_pciepll_vco_disable,
+	.is_enabled = sf21_pciepll_vco_is_enabled,
+	.recalc_rate = sf21_pciepll_vco_recalc_rate,
+};
+
+static struct sf_clk_common pciepll_vco = {
+	.hw.init = CLK_HW_INIT_PARENTS_DATA("pciepll_vco", sf21_ref_parent,
+					    &sf21_pciepll_vco_ops,
+					    CLK_SET_RATE_GATE),
+};
+
+static const struct clk_ops sf21_pciepll_fout_ops = {
+	.enable = sf21_dual_divider_enable,
+	.disable = sf21_dual_divider_disable,
+	.is_enabled = sf21_dual_divider_is_enabled,
+	.recalc_rate = sf21_dual_divider_recalc_rate,
+	.determine_rate = sf21_dual_divider_determine_rate,
+	.set_rate = sf21_dual_divider_set_rate,
+};
+
+#define SF21_PCIEPLL_FOUT(_name, _idx, _flags)				\
+	struct sf_dual_divider _name = {				\
+		.common.hw.init = CLK_HW_INIT_HW(#_name,		\
+						 &pciepll_vco.hw,	\
+						 &sf21_pciepll_fout_ops,\
+						 _flags),		\
+	.div_reg = PLL_PCIE_CFG2,					\
+	.div1_offs = PLL_PCIE_PDIV1_OFFS(_idx),				\
+	.div2_offs = PLL_PCIE_PDIV2_OFFS(_idx),				\
+	.en_reg = PLL_PCIE_CFG2,					\
+	.en_bit = PLL_PCIE_FOUTEN_BIT(_idx),				\
+	.load_reg = CFG_LOAD,						\
+	.load_bit = CFG_LOAD_PCIE_PLL_BIT,				\
+	.flags = SF_DUAL_DIVIDER_START_FROM_1,				\
+	}
+
+static SF21_PCIEPLL_FOUT(pciepll_fout0, 0, 0);
+static SF21_PCIEPLL_FOUT(pciepll_fout1, 1, 0);
+static SF21_PCIEPLL_FOUT(pciepll_fout2, 2, 0);
+static SF21_PCIEPLL_FOUT(pciepll_fout3, 3, 0);
+
+struct sf21_clk_muxdiv {
+	struct sf_clk_common common;
+	u16 en;
+	u8 mux_reg;
+	u8 mux_offs;
+	u8 div_reg;
+	u8 div_offs;
+};
+
+#define CRM_CLK_SEL(_x)		((_x) * 4 + 0x80)
+#define  CLK_SEL1_PLL_TEST	GENMASK(6, 4)
+#define CRM_CLK_EN		0x8c
+#define CRM_CLK_DIV(_x)		((_x) * 4 + 0x94)
+#define  CRM_CLK_DIV_MASK	GENMASK(7, 0)
+
+static unsigned long sf21_muxdiv_recalc_rate(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+	struct sf21_clk_muxdiv *priv =
+		container_of(cmn_priv, struct sf21_clk_muxdiv, common);
+	ulong div_reg = CRM_CLK_DIV(priv->div_reg);
+	u16 div_offs = priv->div_offs;
+	u16 div_val = (sf_readl(cmn_priv, div_reg) >> div_offs) &
+		      CRM_CLK_DIV_MASK;
+	div_val += 1;
+	return parent_rate / div_val;
+}
+
+static int sf21_muxdiv_determine_rate(struct clk_hw *hw,
+				      struct clk_rate_request *req)
+{
+	unsigned int div;
+
+	if (!req->rate)
+		return -EINVAL;
+
+	div = DIV_ROUND_CLOSEST(req->best_parent_rate, req->rate);
+	if (!div)
+		div = 1;
+	else if (div > CRM_CLK_DIV_MASK + 1)
+		div = CRM_CLK_DIV_MASK + 1;
+
+	req->rate = req->best_parent_rate / div;
+	return 0;
+}
+
+static int sf21_muxdiv_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+	struct sf21_clk_muxdiv *priv =
+		container_of(cmn_priv, struct sf21_clk_muxdiv, common);
+	ulong div_reg = CRM_CLK_DIV(priv->div_reg);
+	u16 div_offs = priv->div_offs;
+	unsigned int div;
+
+	if (!rate)
+		return -EINVAL;
+
+	div = DIV_ROUND_CLOSEST(parent_rate, rate);
+	if (div < 1)
+		div = 1;
+	else if (div > CRM_CLK_DIV_MASK + 1)
+		div = CRM_CLK_DIV_MASK + 1;
+	div -= 1;
+
+	guard(raw_spinlock_irqsave)(cmn_priv->lock);
+	sf_rmw(cmn_priv, div_reg, CRM_CLK_DIV_MASK << div_offs,
+	       div << div_offs);
+	sf_writel(cmn_priv, CFG_LOAD, BIT(CFG_LOAD_DIV_BIT));
+	sf_writel(cmn_priv, CFG_LOAD, 0);
+	return 0;
+}
+
+static int sf21_muxdiv_enable(struct clk_hw *hw)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+	struct sf21_clk_muxdiv *priv =
+		container_of(cmn_priv, struct sf21_clk_muxdiv, common);
+
+	guard(raw_spinlock_irqsave)(cmn_priv->lock);
+	sf_rmw(cmn_priv, CRM_CLK_EN, 0, BIT(priv->en));
+	/*
+	 * Clock divider value load only happens when the clock is running.
+	 * Pulse the CFG_LOAD_DIV so that set_rate() which happened
+	 * before enable() is applied.
+	 */
+	sf_writel(cmn_priv, CFG_LOAD, BIT(CFG_LOAD_DIV_BIT));
+	sf_writel(cmn_priv, CFG_LOAD, 0);
+	return 0;
+}
+
+static void sf21_muxdiv_disable(struct clk_hw *hw)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+	struct sf21_clk_muxdiv *priv =
+		container_of(cmn_priv, struct sf21_clk_muxdiv, common);
+
+	guard(raw_spinlock_irqsave)(cmn_priv->lock);
+	sf_rmw(cmn_priv, CRM_CLK_EN, BIT(priv->en), 0);
+}
+
+static int sf21_muxdiv_is_enabled(struct clk_hw *hw)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+	struct sf21_clk_muxdiv *priv =
+		container_of(cmn_priv, struct sf21_clk_muxdiv, common);
+	u32 reg_val = sf_readl(cmn_priv, CRM_CLK_EN);
+
+	return reg_val & (BIT(priv->en)) ? 1 : 0;
+}
+
+static u8 sf21_muxdiv_get_parent(struct clk_hw *hw)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+	struct sf21_clk_muxdiv *priv =
+		container_of(cmn_priv, struct sf21_clk_muxdiv, common);
+	ulong mux_reg = CRM_CLK_SEL(priv->mux_reg);
+	u16 mux_offs = priv->mux_offs;
+	u32 reg_val = sf_readl(cmn_priv, mux_reg);
+
+	return reg_val & BIT(mux_offs) ? 1 : 0;
+}
+
+static int sf21_muxdiv_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+	struct sf21_clk_muxdiv *priv =
+		container_of(cmn_priv, struct sf21_clk_muxdiv, common);
+	ulong mux_reg = CRM_CLK_SEL(priv->mux_reg);
+	u16 mux_offs = priv->mux_offs;
+
+	guard(raw_spinlock_irqsave)(cmn_priv->lock);
+	if (index)
+		sf_rmw(cmn_priv, mux_reg, 0, BIT(mux_offs));
+	else
+		sf_rmw(cmn_priv, mux_reg, BIT(mux_offs), 0);
+
+	return 0;
+}
+
+static const struct clk_ops sf21_clk_muxdiv_ops = {
+	.enable = sf21_muxdiv_enable,
+	.disable = sf21_muxdiv_disable,
+	.is_enabled = sf21_muxdiv_is_enabled,
+	.recalc_rate = sf21_muxdiv_recalc_rate,
+	.determine_rate = sf21_muxdiv_determine_rate,
+	.set_rate = sf21_muxdiv_set_rate,
+	.get_parent = sf21_muxdiv_get_parent,
+	.set_parent = sf21_muxdiv_set_parent,
+};
+
+#define SF21_MUXDIV(_name, _parents, _mux_reg, _mux_offs, _div_reg,	\
+		    _div_offs, _en, _flags)				\
+	struct sf21_clk_muxdiv _name = {				\
+		.common.hw.init = CLK_HW_INIT_PARENTS_HW(		\
+		#_name, _parents, &sf21_clk_muxdiv_ops, _flags),	\
+		.en = _en,						\
+		.mux_reg = _mux_reg,					\
+		.mux_offs = _mux_offs,					\
+		.div_reg = _div_reg,					\
+		.div_offs = _div_offs,					\
+	}
+
+static const struct clk_hw *clk_periph_parents[] = {
+	&cmnpll_postdiv.common.hw,
+	&ddrpll_postdiv.hw,
+};
+
+static const struct clk_hw *clk_ddr_parents[] = {
+	&ddrpll_postdiv.hw,
+	&cmnpll_postdiv.common.hw,
+};
+
+static const struct clk_hw *clk_gmac_usb_parents[] = {
+	&cmnpll_vco.hw,
+	&ddrpll_postdiv.hw,
+};
+
+static SF21_MUXDIV(muxdiv_cpu, clk_periph_parents, 0, 1, 0, 0, 0,
+		   CLK_IS_CRITICAL);
+static SF21_MUXDIV(muxdiv_pic, clk_periph_parents, 0, 3, 3, 16, 1,
+		   CLK_IS_CRITICAL);
+static SF21_MUXDIV(muxdiv_axi, clk_periph_parents, 0, 5, 0, 8, 2,
+		   CLK_IS_CRITICAL);
+static SF21_MUXDIV(muxdiv_ahb, clk_periph_parents, 0, 7, 0, 16, 3,
+		   CLK_IS_CRITICAL);
+static SF21_MUXDIV(muxdiv_apb, clk_periph_parents, 0, 9, 0, 24, 4,
+		   CLK_IS_CRITICAL);
+static SF21_MUXDIV(muxdiv_uart, clk_periph_parents, 0, 11, 1, 0, 5, 0);
+static SF21_MUXDIV(muxdiv_iram, clk_periph_parents, 0, 13, 1, 8, 6, 0);
+static SF21_MUXDIV(muxdiv_npu, clk_periph_parents, 0, 17, 1, 24, 8, 0);
+static SF21_MUXDIV(muxdiv_ddrphy, clk_ddr_parents, 0, 19, 2, 0, 9,
+		   CLK_IS_CRITICAL);
+static SF21_MUXDIV(muxdiv_ddr_bypass, clk_ddr_parents, 0, 21, 3, 0, 10,
+		   CLK_IS_CRITICAL);
+static SF21_MUXDIV(muxdiv_ethtsu, clk_periph_parents, 0, 25, 2, 16, 12,
+		   0);
+static SF21_MUXDIV(muxdiv_gmac_byp_ref, clk_gmac_usb_parents, 0, 27, 2,
+		   24, 13, 0);
+static SF21_MUXDIV(muxdiv_usb, clk_gmac_usb_parents, 1, 1, 1, 16, 24, 0);
+static SF21_MUXDIV(muxdiv_usbphy, clk_gmac_usb_parents, 1, 3, 2, 8, 25,
+		   0);
+static SF21_MUXDIV(muxdiv_serdes_csr, clk_periph_parents, 1, 15, 5, 0,
+		   20, 0);
+static SF21_MUXDIV(muxdiv_crypt_csr, clk_periph_parents, 1, 17, 5, 8,
+		   21, 0);
+static SF21_MUXDIV(muxdiv_crypt_app, clk_periph_parents, 1, 19, 5, 16,
+		   22, 0);
+static SF21_MUXDIV(muxdiv_irom, clk_periph_parents, 1, 21, 5, 24, 23,
+		   CLK_IS_CRITICAL);
+
+static int sf21_mux_determine_rate(struct clk_hw *hw,
+				   struct clk_rate_request *req)
+{
+	req->rate = req->best_parent_rate;
+	return 0;
+}
+
+static const struct clk_ops sf21_clk_mux_ops = {
+	.get_parent = sf21_muxdiv_get_parent,
+	.set_parent = sf21_muxdiv_set_parent,
+	.determine_rate = sf21_mux_determine_rate,
+};
+
+#define SF21_MUX(_name, _parents, _mux_reg, _mux_offs, _flags)	\
+	struct sf21_clk_muxdiv _name = {				\
+		.common.hw.init = CLK_HW_INIT_PARENTS_DATA(		\
+			#_name, _parents, &sf21_clk_mux_ops, _flags),	\
+		.en = 0,						\
+		.mux_reg = _mux_reg,					\
+		.mux_offs = _mux_offs,					\
+		.div_reg = 0,						\
+		.div_offs = 0,						\
+	}
+
+static const struct clk_parent_data clk_boot_parents[] = {
+	{ .hw = &muxdiv_irom.common.hw },
+	{ .index = 0 },
+};
+
+static SF21_MUX(mux_boot, clk_boot_parents, 0, 30, CLK_IS_CRITICAL);
+
+static const struct clk_ops sf21_clk_div_ops = {
+	.recalc_rate = sf21_muxdiv_recalc_rate,
+	.determine_rate = sf21_muxdiv_determine_rate,
+	.set_rate = sf21_muxdiv_set_rate,
+};
+
+#define SF21_DIV(_name, _parents, _div_reg, _div_offs, _flags)		\
+	struct sf21_clk_muxdiv _name = {				\
+		.common.hw.init = CLK_HW_INIT_PARENTS_DATA(		\
+			#_name, _parents, &sf21_clk_div_ops, _flags),	\
+		.en = 0,						\
+		.mux_reg = 0,						\
+		.mux_offs = 0,						\
+		.div_reg = _div_reg,					\
+		.div_offs = _div_offs,					\
+	}
+
+static SF21_DIV(div_pvt, sf21_ref_parent, 3, 8, 0);
+
+static const struct clk_hw *clk_pll_test_parents[] = {
+	&cmnpll_postdiv.common.hw,
+	&ddrpll_postdiv.hw,
+	&pciepll_fout3.common.hw,
+};
+
+static u8 sf21_pll_test_get_parent(struct clk_hw *hw)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+	u32 reg_val = sf_readl(cmn_priv, CRM_CLK_SEL(1));
+	u8 parent = FIELD_GET(CLK_SEL1_PLL_TEST, reg_val);
+
+	if (parent >= ARRAY_SIZE(clk_pll_test_parents))
+		return 0;
+
+	return parent;
+}
+
+static int sf21_pll_test_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+
+	if (index >= ARRAY_SIZE(clk_pll_test_parents))
+		return -EINVAL;
+
+	guard(raw_spinlock_irqsave)(cmn_priv->lock);
+	sf_rmw(cmn_priv, CRM_CLK_SEL(1), CLK_SEL1_PLL_TEST,
+	       FIELD_PREP(CLK_SEL1_PLL_TEST, index));
+	return 0;
+}
+
+static const struct clk_ops sf21_clk_pll_test_ops = {
+	.recalc_rate = sf21_muxdiv_recalc_rate,
+	.determine_rate = sf21_muxdiv_determine_rate,
+	.set_rate = sf21_muxdiv_set_rate,
+	.get_parent = sf21_pll_test_get_parent,
+	.set_parent = sf21_pll_test_set_parent,
+};
+
+static struct sf21_clk_muxdiv muxdiv_pll_test = {
+	.common.hw.init = CLK_HW_INIT_PARENTS_HW("muxdiv_pll_test",
+						 clk_pll_test_parents,
+						 &sf21_clk_pll_test_ops, 0),
+	.en = 0,
+	.mux_reg = 0,
+	.mux_offs = 0,
+	.div_reg = 3,
+	.div_offs = 24,
+};
+
+static const struct clk_ops sf21_clk_gate_ops = {
+	.enable = sf21_muxdiv_enable,
+	.disable = sf21_muxdiv_disable,
+	.is_enabled = sf21_muxdiv_is_enabled,
+};
+
+#define SF21_GATE(_name, _parents, _en, _flags)				\
+	struct sf21_clk_muxdiv _name = {				\
+		.common.hw.init = CLK_HW_INIT_PARENTS_HW(		\
+			#_name, _parents, &sf21_clk_gate_ops, _flags),	\
+		.en = _en,						\
+		.mux_reg = 0,						\
+		.mux_offs = 0,						\
+		.div_reg = 0,						\
+		.div_offs = 0,						\
+	}
+
+static const struct clk_hw *clk_pcie_parents[] = {
+	&pciepll_fout1.common.hw,
+};
+
+static SF21_GATE(pcie_refclk_n, clk_pcie_parents, 15, 0);
+static SF21_GATE(pcie_refclk_p, clk_pcie_parents, 16, 0);
+
+#define SF21_NUM_CLKS			31
+
+static struct clk_hw_onecell_data sf21_hw_clks = {
+	.num = SF21_NUM_CLKS,
+	.hws = {
+		[SF21_CLK_CMNPLL_VCO] = &cmnpll_vco.hw,
+		[SF21_CLK_CMNPLL_POSTDIV] = &cmnpll_postdiv.common.hw,
+		[SF21_CLK_DDRPLL_POSTDIV] = &ddrpll_postdiv.hw,
+		[SF21_CLK_PCIEPLL_VCO] = &pciepll_vco.hw,
+		[SF21_CLK_PCIEPLL_FOUT0] = &pciepll_fout0.common.hw,
+		[SF21_CLK_PCIEPLL_FOUT1] = &pciepll_fout1.common.hw,
+		[SF21_CLK_PCIEPLL_FOUT2] = &pciepll_fout2.common.hw,
+		[SF21_CLK_PCIEPLL_FOUT3] = &pciepll_fout3.common.hw,
+		[SF21_CLK_CPU] = &muxdiv_cpu.common.hw,
+		[SF21_CLK_PIC] = &muxdiv_pic.common.hw,
+		[SF21_CLK_AXI] = &muxdiv_axi.common.hw,
+		[SF21_CLK_AHB] = &muxdiv_ahb.common.hw,
+		[SF21_CLK_APB] = &muxdiv_apb.common.hw,
+		[SF21_CLK_UART] = &muxdiv_uart.common.hw,
+		[SF21_CLK_IRAM] = &muxdiv_iram.common.hw,
+		[SF21_CLK_NPU] = &muxdiv_npu.common.hw,
+		[SF21_CLK_DDRPHY_REF] = &muxdiv_ddrphy.common.hw,
+		[SF21_CLK_DDR_BYPASS] = &muxdiv_ddr_bypass.common.hw,
+		[SF21_CLK_ETHTSU] = &muxdiv_ethtsu.common.hw,
+		[SF21_CLK_GMAC_BYP_REF] = &muxdiv_gmac_byp_ref.common.hw,
+		[SF21_CLK_USB] = &muxdiv_usb.common.hw,
+		[SF21_CLK_USBPHY] = &muxdiv_usbphy.common.hw,
+		[SF21_CLK_SERDES_CSR] = &muxdiv_serdes_csr.common.hw,
+		[SF21_CLK_CRYPT_CSR] = &muxdiv_crypt_csr.common.hw,
+		[SF21_CLK_CRYPT_APP] = &muxdiv_crypt_app.common.hw,
+		[SF21_CLK_IROM] = &muxdiv_irom.common.hw,
+		[SF21_CLK_BOOT] = &mux_boot.common.hw,
+		[SF21_CLK_PVT] = &div_pvt.common.hw,
+		[SF21_CLK_PLL_TEST] = &muxdiv_pll_test.common.hw,
+		[SF21_CLK_PCIE_REFN] = &pcie_refclk_n.common.hw,
+		[SF21_CLK_PCIE_REFP] = &pcie_refclk_p.common.hw,
+	}
+};
+
+struct sf21_clk_ctrl {
+	void __iomem *base;
+	/* Serializes register RMW sequences by clock ops. */
+	raw_spinlock_t clk_lock;
+	/* Serializes register RMW sequences by reset ops. */
+	spinlock_t rst_lock;
+	struct reset_controller_dev rcdev;
+	const u32 *reset_bits;
+	unsigned int nr_resets;
+};
+
+#define SF21_SOFT_RESET		0xc0
+
+static const u32 sf21_topcrm_reset_bits[] = {
+	[SF21_RESET_GIC]			= BIT(1),
+	[SF21_RESET_AXI]			= BIT(2),
+	[SF21_RESET_AHB]			= BIT(3),
+	[SF21_RESET_APB]			= BIT(4),
+	[SF21_RESET_IRAM]			= BIT(5),
+	[SF21_RESET_NPU]			= BIT(7),
+	[SF21_RESET_DDR_CTL]			= BIT(8),
+	[SF21_RESET_DDR_PHY]			= BIT(9),
+	[SF21_RESET_DDR_PWR_OK_IN]		= BIT(10),
+	[SF21_RESET_DDR_CTL_APB]		= BIT(11),
+	[SF21_RESET_DDR_PHY_APB]		= BIT(12),
+	[SF21_RESET_USB]			= BIT(19),
+	[SF21_RESET_PVT]			= BIT(23),
+	[SF21_RESET_SERDES_CSR]			= BIT(24),
+	[SF21_RESET_CRYPT_CSR]			= BIT(28),
+	[SF21_RESET_CRYPT_APP]			= BIT(29),
+	[SF21_RESET_NPU2DDR_ASYNCBRIDGE]	= BIT(30),
+	[SF21_RESET_IROM]			= BIT(31),
+};
+
+static inline struct sf21_clk_ctrl *
+rcdev_to_sf21_topcrm(struct reset_controller_dev *rcdev)
+{
+	return container_of(rcdev, struct sf21_clk_ctrl, rcdev);
+}
+
+static int sf21_topcrm_reset_update(struct reset_controller_dev *rcdev,
+				    unsigned long id, bool assert)
+{
+	struct sf21_clk_ctrl *ctrl = rcdev_to_sf21_topcrm(rcdev);
+	u32 bit = ctrl->reset_bits[id];
+	u32 reg;
+
+	guard(spinlock_irqsave)(&ctrl->rst_lock);
+	reg = readl(ctrl->base + SF21_SOFT_RESET);
+	if (assert)
+		reg &= ~bit;
+	else
+		reg |= bit;
+	writel(reg, ctrl->base + SF21_SOFT_RESET);
+
+	return 0;
+}
+
+static int sf21_topcrm_reset_assert(struct reset_controller_dev *rcdev,
+				    unsigned long id)
+{
+	return sf21_topcrm_reset_update(rcdev, id, true);
+}
+
+static int sf21_topcrm_reset_deassert(struct reset_controller_dev *rcdev,
+				      unsigned long id)
+{
+	return sf21_topcrm_reset_update(rcdev, id, false);
+}
+
+static int sf21_topcrm_reset_status(struct reset_controller_dev *rcdev,
+				    unsigned long id)
+{
+	struct sf21_clk_ctrl *ctrl = rcdev_to_sf21_topcrm(rcdev);
+	u32 bit = ctrl->reset_bits[id];
+
+	return !(readl(ctrl->base + SF21_SOFT_RESET) & bit);
+}
+
+static const struct reset_control_ops sf21_topcrm_reset_ops = {
+	.assert = sf21_topcrm_reset_assert,
+	.deassert = sf21_topcrm_reset_deassert,
+	.status = sf21_topcrm_reset_status,
+};
+
+static int sf21_topcrm_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct sf21_clk_ctrl *ctrl;
+	int i, ret;
+
+	ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
+	if (!ctrl)
+		return -ENOMEM;
+
+	ctrl->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(ctrl->base))
+		return dev_err_probe(dev, PTR_ERR(ctrl->base),
+				     "failed to map resources\n");
+
+	raw_spin_lock_init(&ctrl->clk_lock);
+	spin_lock_init(&ctrl->rst_lock);
+
+	for (i = 0; i < sf21_hw_clks.num; i++) {
+		struct clk_hw *hw = sf21_hw_clks.hws[i];
+		struct sf_clk_common *common;
+
+		if (!hw)
+			continue;
+		common = hw_to_sf_clk_common(hw);
+		common->base = ctrl->base;
+		common->lock = &ctrl->clk_lock;
+		ret = devm_clk_hw_register(dev, hw);
+		if (ret)
+			return dev_err_probe(dev, ret,
+					     "failed to register clock %d\n",
+					     i);
+	}
+
+	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+					  &sf21_hw_clks);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to add hw provider\n");
+
+	ctrl->reset_bits = sf21_topcrm_reset_bits;
+	ctrl->nr_resets = ARRAY_SIZE(sf21_topcrm_reset_bits);
+	ctrl->rcdev.owner = THIS_MODULE;
+	ctrl->rcdev.nr_resets = ctrl->nr_resets;
+	ctrl->rcdev.ops = &sf21_topcrm_reset_ops;
+	ctrl->rcdev.of_node = dev->of_node;
+	ctrl->rcdev.of_reset_n_cells = 1;
+
+	ret = devm_reset_controller_register(dev, &ctrl->rcdev);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "failed to register reset controller\n");
+
+	return 0;
+}
+
+static const struct of_device_id sf21_topcrm_dt_ids[] = {
+	{ .compatible = "siflower,sf21-topcrm" },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, sf21_topcrm_dt_ids);
+
+static struct platform_driver sf21_topcrm_driver = {
+	.probe	= sf21_topcrm_probe,
+	.driver	= {
+		.name			= "sf21-topcrm",
+		.suppress_bind_attrs	= true,
+		.of_match_table		= sf21_topcrm_dt_ids,
+	},
+};
+module_platform_driver(sf21_topcrm_driver);
+
+MODULE_AUTHOR("Chuanhong Guo <gch981213@gmail.com>");
+MODULE_DESCRIPTION("driver for Siflower SF21 top clock and reset module");
+MODULE_LICENSE("GPL");

-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 2/3] dt-bindings: clock: add header/doc for Siflower sf21-topcrm
From: Chuanhong Guo @ 2026-05-24 13:13 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Philipp Zabel, Yao Zi
  Cc: linux-riscv, linux-kernel, linux-clk, devicetree, Chuanhong Guo
In-Reply-To: <20260524-sf21-topcrm-v2-0-4527aae05c3d@gmail.com>

Add the device tree binding header and binding doc for
Siflower SF21A6826/SF21H8898 toplevel clock and reset module.

CLK_ETH_REF_P is a clock name that exists in the vendor datasheet.
This clock connects directly to CLK_PCIEPLL_FOUT2 and there's no
clock gate/mux in between. An alias is created for this clock
to make available clock names align with the datasheet.

Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
---
 .../bindings/clock/siflower,sf21-topcrm.yaml       | 60 ++++++++++++++++++++++
 include/dt-bindings/clock/siflower,sf21-topcrm.h   | 42 +++++++++++++++
 include/dt-bindings/reset/siflower,sf21-topcrm.h   | 25 +++++++++
 3 files changed, 127 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/siflower,sf21-topcrm.yaml b/Documentation/devicetree/bindings/clock/siflower,sf21-topcrm.yaml
new file mode 100644
index 000000000000..3782d9c32370
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/siflower,sf21-topcrm.yaml
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/siflower,sf21-topcrm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Siflower SF21 toplevel clock and reset module
+
+maintainers:
+  - Chuanhong Guo <gch981213@gmail.com>
+
+description: |
+  The toplevel clock and reset module on Siflower SF21 SoCs manages
+  the main PLLs, high-level clock muxes/dividers/gates, and some
+  reset lines.
+  Available clocks are defined in:
+  include/dt-bindings/clock/siflower,sf21-topcrm.h
+  Available resets are defined in:
+  include/dt-bindings/reset/siflower,sf21-topcrm.h
+
+properties:
+  compatible:
+    const: siflower,sf21-topcrm
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  "#clock-cells":
+    const: 1
+
+  "#reset-cells":
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - "#clock-cells"
+  - "#reset-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/siflower,sf21-topcrm.h>
+    soc {
+        #address-cells = <1>;
+        #size-cells = <1>;
+
+        clock-controller@ce00400 {
+            compatible = "siflower,sf21-topcrm";
+            reg = <0x0ce00400 0x400>;
+            clocks = <&refclk>;
+            #clock-cells = <1>;
+            #reset-cells = <1>;
+        };
+    };
diff --git a/include/dt-bindings/clock/siflower,sf21-topcrm.h b/include/dt-bindings/clock/siflower,sf21-topcrm.h
new file mode 100644
index 000000000000..1b2e3cde931a
--- /dev/null
+++ b/include/dt-bindings/clock/siflower,sf21-topcrm.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+
+#ifndef _DT_BINDINGS_CLK_SIFLOWER_SF21_TOPCRM_H
+#define _DT_BINDINGS_CLK_SIFLOWER_SF21_TOPCRM_H
+
+#define SF21_CLK_CMNPLL_VCO		0
+#define SF21_CLK_CMNPLL_POSTDIV		1
+
+#define SF21_CLK_DDRPLL_POSTDIV		2
+
+#define SF21_CLK_PCIEPLL_VCO		3
+#define SF21_CLK_PCIEPLL_FOUT0		4
+#define SF21_CLK_PCIEPLL_FOUT1		5
+#define SF21_CLK_PCIEPLL_FOUT2		6
+#define SF21_CLK_ETH_REF_P		SF21_CLK_PCIEPLL_FOUT2
+#define SF21_CLK_PCIEPLL_FOUT3		7
+
+#define SF21_CLK_CPU			8
+#define SF21_CLK_PIC			9
+#define SF21_CLK_AXI			10
+#define SF21_CLK_AHB			11
+#define SF21_CLK_APB			12
+#define SF21_CLK_UART			13
+#define SF21_CLK_IRAM			14
+#define SF21_CLK_NPU			15
+#define SF21_CLK_DDRPHY_REF		16
+#define SF21_CLK_DDR_BYPASS		17
+#define SF21_CLK_ETHTSU			18
+#define SF21_CLK_GMAC_BYP_REF		19
+#define SF21_CLK_USB			20
+#define SF21_CLK_USBPHY			21
+#define SF21_CLK_SERDES_CSR		22
+#define SF21_CLK_CRYPT_CSR		23
+#define SF21_CLK_CRYPT_APP		24
+#define SF21_CLK_IROM			25
+#define SF21_CLK_BOOT			26
+#define SF21_CLK_PVT			27
+#define SF21_CLK_PLL_TEST		28
+#define SF21_CLK_PCIE_REFN		29
+#define SF21_CLK_PCIE_REFP		30
+
+#endif
diff --git a/include/dt-bindings/reset/siflower,sf21-topcrm.h b/include/dt-bindings/reset/siflower,sf21-topcrm.h
new file mode 100644
index 000000000000..fa700accff54
--- /dev/null
+++ b/include/dt-bindings/reset/siflower,sf21-topcrm.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+
+#ifndef _DT_BINDINGS_RESET_SIFLOWER_SF21_TOPCRM_H
+#define _DT_BINDINGS_RESET_SIFLOWER_SF21_TOPCRM_H
+
+#define SF21_RESET_GIC			0
+#define SF21_RESET_AXI			1
+#define SF21_RESET_AHB			2
+#define SF21_RESET_APB			3
+#define SF21_RESET_IRAM			4
+#define SF21_RESET_NPU			5
+#define SF21_RESET_DDR_CTL		6
+#define SF21_RESET_DDR_PHY		7
+#define SF21_RESET_DDR_PWR_OK_IN	8
+#define SF21_RESET_DDR_CTL_APB		9
+#define SF21_RESET_DDR_PHY_APB		10
+#define SF21_RESET_USB			11
+#define SF21_RESET_PVT			12
+#define SF21_RESET_SERDES_CSR		13
+#define SF21_RESET_CRYPT_CSR		14
+#define SF21_RESET_CRYPT_APP		15
+#define SF21_RESET_NPU2DDR_ASYNCBRIDGE	16
+#define SF21_RESET_IROM			17
+
+#endif

-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 1/3] riscv: add Siflower RISC-V SoC family Kconfig support
From: Chuanhong Guo @ 2026-05-24 13:13 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Philipp Zabel, Yao Zi
  Cc: linux-riscv, linux-kernel, linux-clk, devicetree, Chuanhong Guo
In-Reply-To: <20260524-sf21-topcrm-v2-0-4527aae05c3d@gmail.com>

Siflower RISC-V SoCs, including SF21A6826 and SF21H8898, are RISC-V
chips with T-Head C908 cores for home routers and gateways. Add a
Kconfig entry named ARCH_SIFLOWER for them.
Notably these chips uses ARM PL011 for UART. ARM_AMBA is selected
for its driver.

Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
---
 arch/riscv/Kconfig.socs | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index c174ac0ec46b..7c412b2bdbe1 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -37,6 +37,13 @@ config ARCH_SIFIVE
 	help
 	  This enables support for SiFive SoC platform hardware.
 
+config ARCH_SIFLOWER
+	bool "Siflower RISC-V SoCs"
+	select ARM_AMBA
+	select ERRATA_THEAD
+	help
+	  This enables support for Siflower RISC-V SoC platform hardware.
+
 config ARCH_SOPHGO
 	bool "Sophgo SoCs"
 	help

-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 0/3] clk: add Siflower SF21 topcrm support
From: Chuanhong Guo @ 2026-05-24 13:13 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Philipp Zabel, Yao Zi
  Cc: linux-riscv, linux-kernel, linux-clk, devicetree, Chuanhong Guo

Siflower SF21A6826 and SF21H8898 are RISC-V chips with quad-core
T-Head C908 for home routers and gateways.
This series adds the initial RISC-V Kconfig entry for Siflower SoCs and
support for the toplevel clock and reset module on Siflower SF21 socs.

Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
---
Changes in v2:
- drop "if TTY" condition in ARCH_SIFLOWER
- drop "xin25m" in dt bindings for the possibility of a different
  xtal frequency.
- use index instead of fw_name for xtal clock in the driver.
- drop unnecessary fixed-clock node in dt binding example.
- name the top node "soc" instead of "/" to fix binding check
  failure on missing "model" and "compatible".
- drop SF21_RESET_MAX, rename SF21_CLK_MAX to SF21_NUM_CLKS and
  define it in driver instead of binding header.
- split dt binding header into separated clock and reset headers.
- sort headers in the driver
- add a shared sf21_dual_dividers for the two dividers in series
  in CMNPLL and PCIEPLL.
- multiply before divide for PLL VCO calculations.
- change cpu and pic clock flags from ignore_unused to is_critical.
- use guard macro for spinlocks.
- split clock and reset locks and use raw_spinlock for clock lock.
- select RATIONAL in Kconfig for clk driver.
- use FIELD_MAX instead of BIT(x) - 1 for field max value.

- Link to v1: https://lore.kernel.org/r/20260517-sf21-topcrm-v1-0-438f2e0513ff@gmail.com

---
Chuanhong Guo (3):
      riscv: add Siflower RISC-V SoC family Kconfig support
      dt-bindings: clock: add header/doc for Siflower sf21-topcrm
      clk: add support for siflower sf21-topcrm

 .../bindings/clock/siflower,sf21-topcrm.yaml       |   60 ++
 arch/riscv/Kconfig.socs                            |    7 +
 drivers/clk/Kconfig                                |    1 +
 drivers/clk/Makefile                               |    1 +
 drivers/clk/siflower/Kconfig                       |   23 +
 drivers/clk/siflower/Makefile                      |    1 +
 drivers/clk/siflower/clk-sf21-topcrm.c             | 1017 ++++++++++++++++++++
 include/dt-bindings/clock/siflower,sf21-topcrm.h   |   42 +
 include/dt-bindings/reset/siflower,sf21-topcrm.h   |   25 +
 9 files changed, 1177 insertions(+)
---
base-commit: c1ecb239fa3456529a32255359fc78b69eb9d847
change-id: 20260515-sf21-topcrm-1856c05b6138

Best regards,
-- 
Chuanhong Guo <gch981213@gmail.com>


^ permalink raw reply

* Re: [PATCH v3 5/5] arm64: dts: qcom: Add Shikra EVK boards
From: Komal Bajaj @ 2026-05-24 13:07 UTC (permalink / raw)
  To: sashiko-reviews
  Cc: vkoul, devicetree, linux-phy, conor+dt, neil.armstrong, olteanv,
	robh
In-Reply-To: <20260522193943.660811F000E9@smtp.kernel.org>

On 5/23/2026 1:09 AM, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [High] The device tree file shikra-cqs-evk.dts incorrectly includes the CQM SoM device tree (shikra-cqm-som.dtsi) instead of the expected CQS SoM device tree (shikra-cqs-som.dtsi).
> --
>
> commit cb9ff9c76f4ee019113138237f57794fa621d71f
> Author: Komal Bajaj <komal.bajaj@oss.qualcomm.com>
>
> arm64: dts: qcom: Add Shikra EVK boards
>
> This commit adds device trees for the Shikra EVK platform, combining
> Shikra SoM variants with a common carrier board. It introduces three EVK
> boards: CQM (retail with modem), CQS (retail without modem), and IQS
> (industrial without modem).
>
> [ ... ]
>
>> diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts
>> new file mode 100644
>> index 0000000000000..b3f19a64d7aed
>> --- /dev/null
>> +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts
>> @@ -0,0 +1,40 @@
>> +// SPDX-License-Identifier: BSD-3-Clause
>> +/*
>> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
>> + */
>> +
>> +/dts-v1/;
>> +
>> +#include "shikra-cqm-som.dtsi"
> [Severity: High]
> The commit message states that shikra-cqs-evk.dts pairs with the CQ2390S
> SoM (retail, without modem). Does this file include the incorrect SoM dtsi?
>
> Including shikra-cqm-som.dtsi here seems like it would pull in the hardware
> description of the modem-enabled CQM SoM instead of the expected CQS variant.
>
> Could this cause boot issues or lead to loading drivers for hardware that
> isn't actually present on the CQS board?

Already discussed, refer: 
https://lore.kernel.org/all/4787d5f9-601a-4d27-91d3-33216ee6f64d@oss.qualcomm.com/

Thanks
Komal

>
>> +#include "shikra-evk.dtsi"
>> +
>> +/ {
>> +	model = "Qualcomm Technologies, Inc. Shikra CQS EVK";
>> +	compatible = "qcom,shikra-cqs-evk", "qcom,shikra-cqs-som", "qcom,shikra";
> [ ... ]
>


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox