Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/4] Add CIX Sky1 USBSSP controller support
@ 2026-09-06  3:24 Hongliang Yang
  2026-09-06  3:24 ` [PATCH v4 1/4] dt-bindings: usb: Add CIX Sky1 USBSSP RCSU system controller Hongliang Yang
                   ` (3 more replies)
  0 siblings, 4 replies; 12+ messages in thread
From: Hongliang Yang @ 2026-09-06  3:24 UTC (permalink / raw)
  To: peter.chen, gregkh, robh, krzk+dt, conor+dt, krzk,
	linux-arm-kernel, linux-usb, devicetree, linux-kernel
  Cc: p.zabel, vkoul, neil.armstrong, pawell, rogerq

This series adds support for the USB4 and USB5 controllers (based on
Cadence USBSSP DRD) found on the CIX Sky1 SoC: the RCSU system
controller binding, the devicetree binding, the glue driver, and the
device tree nodes for the two controllers.

The per-controller RCSU glue registers (AXI cache attribute
configuration and controller clock status) live inside a shared RCSU
register region, not inside the controller's own address space.  The
region is therefore described as a separate syscon node and each glue
node references its registers through the cix,usb-rcsu phandle with
the register offsets.  The OTG mode straps live in the S5 system
control block and are referenced through the cix,usb-syscon phandle.

This series depends on the Sky1 USB3 PHY series ("Add CIX Sky1 USB3
PHY support"), which provides the usb3_phy4 node referenced by the
device tree patch, and should be applied on top of it.

Changes in v4:
- Split the combined USB series into two: this controller series and
  the Sky1 USB3 PHY series it depends on.
- Restructure the RCSU glue register description as suggested during
  review [1]: instead of describing two individual 4-byte registers
  in the glue node's reg, describe the address range and hierarchy -
  the shared RCSU region becomes a syscon node (new cix,sky1-usbss-rcsu
  binding) and the glue node references its per-controller registers
  through the cix,usb-rcsu phandle with offsets.  The glue driver
  accesses them through a regmap instead of ioremap.

Changes in v3:

Device tree:
- Fix the interrupt specifiers of the usb4/usb5 child nodes: the Sky1
  GICv3 interrupt controller uses 4 cells, so add the missing fourth
  (empty) cell to every entry.  Without it the controller IRQs cannot
  be resolved (platform_get_irq_byname() returns -ENXIO).

USBSSP glue driver:
- Add error cleanup to the probe paths: unmap the xhci/dev registers,
  assert the resets and disable the clocks.
- Replace the static of_dev_auxdata array with a probe-local one and
  allocate the platform data with devm_kzalloc(), so repeated probes
  cannot corrupt shared state or leak the allocation.
- Quiesce the hardware on remove: assert (not deassert) the resets
  before disabling the clocks, and balance the runtime PM usage count
  with pm_runtime_disable()/pm_runtime_set_suspended()/
  pm_runtime_put_noidle().
- Check cdns->host_dev for NULL before dereferencing it in the
  platform suspend callback.
- Drop the reference of the OF node returned by of_get_next_child().
- Stop clearing the clock pointers in the enable error paths, which
  left NULL pointers in the driver state on later resume attempts.
- Take device references in the shutdown child-iteration callbacks and
  drop them after use to avoid a use-after-free.
- Use BIT(31) instead of a signed 1 << 31 shift.
- Assign the system sleep callbacks with SYSTEM_SLEEP_PM_OPS() and
  pm_sleep_ptr() instead of a plain dev_pm_ops behind #ifdef.

[1] https://lore.kernel.org/linux-phy/503e87d9-3311-413a-98c0-e02a02c4a354@kernel.org/

Hongliang Yang (4):
  dt-bindings: usb: Add CIX Sky1 USBSSP RCSU system controller
  dt-bindings: usb: Add CIX Sky1 USBSSP controller
  usb: cdns3: Add CIX Sky1 glue driver
  arm64: dts: cix: Add USB4/USB5 nodes for Sky1

 .../bindings/usb/cix,sky1-usbss-rcsu.yaml     |  46 ++
 .../bindings/usb/cix,sky1-usbssp.yaml         | 144 ++++
 MAINTAINERS                                   |   4 +
 arch/arm64/boot/dts/cix/sky1-orion-o6.dts     |  42 +
 arch/arm64/boot/dts/cix/sky1.dtsi             |  88 +++
 drivers/usb/cdns3/Kconfig                     |  13 +
 drivers/usb/cdns3/Makefile                    |   1 +
 drivers/usb/cdns3/cdnsp-sky1.c                | 726 ++++++++++++++++++
 drivers/usb/cdns3/cdnsp-sky1.h                | 129 ++++
 9 files changed, 1193 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/cix,sky1-usbss-rcsu.yaml
 create mode 100644 Documentation/devicetree/bindings/usb/cix,sky1-usbssp.yaml
 create mode 100644 drivers/usb/cdns3/cdnsp-sky1.c
 create mode 100644 drivers/usb/cdns3/cdnsp-sky1.h

-- 
2.54.0



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

* [PATCH v4 1/4] dt-bindings: usb: Add CIX Sky1 USBSSP RCSU system controller
  2026-09-06  3:24 [PATCH v4 0/4] Add CIX Sky1 USBSSP controller support Hongliang Yang
@ 2026-09-06  3:24 ` Hongliang Yang
  2026-09-06  6:45   ` Krzysztof Kozlowski
  2026-09-06  3:24 ` [PATCH v4 2/4] dt-bindings: usb: Add CIX Sky1 USBSSP controller Hongliang Yang
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 12+ messages in thread
From: Hongliang Yang @ 2026-09-06  3:24 UTC (permalink / raw)
  To: peter.chen, gregkh, robh, krzk+dt, conor+dt, krzk,
	linux-arm-kernel, linux-usb, devicetree, linux-kernel
  Cc: p.zabel, vkoul, neil.armstrong, pawell, rogerq

Add device tree binding for the per-controller RCSU register regions
of the CIX Sky1 USBSSP controllers. The regions are exposed as syscon
nodes; USBSSP glue nodes reference their per-controller registers
through the cix,usb-rcsu phandle with register offsets.

The per-controller RCSU control and status registers live in a shared
RCSU region described by the cix,sky1-usbss-rcsu binding and are
referenced through the cix,usb-rcsu phandle.
Signed-off-by: Hongliang Yang <hongliang.yang@cixtech.com>
---
 .../bindings/usb/cix,sky1-usbss-rcsu.yaml     | 46 +++++++++++++++++++
 MAINTAINERS                                   |  1 +
 2 files changed, 47 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/cix,sky1-usbss-rcsu.yaml

diff --git a/Documentation/devicetree/bindings/usb/cix,sky1-usbss-rcsu.yaml b/Documentation/devicetree/bindings/usb/cix,sky1-usbss-rcsu.yaml
new file mode 100644
index 000000000000..d0c54fd2cd5f
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/cix,sky1-usbss-rcsu.yaml
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/cix,sky1-usbss-rcsu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: CIX Sky1 USBSSP RCSU system controller
+
+maintainers:
+  - Hongliang Yang <hongliang.yang@cixtech.com>
+
+description:
+  The CIX Sky1 USBSSP controllers integrate their per-instance glue
+  registers (AXI bus attribute configuration and controller status)
+  inside a shared RCSU register region in the SoC system control
+  aperture. This binding describes that region as a syscon, so USBSSP
+  glue nodes can reference their register offsets through the
+  cix,usb-rcsu phandle (see cix,sky1-usbssp.yaml).
+
+properties:
+  compatible:
+    items:
+      - const: cix,sky1-usbss-rcsu
+      - const: syscon
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        syscon@91c0300 {
+            compatible = "cix,sky1-usbss-rcsu", "syscon";
+            reg = <0x00 0x091c0300 0x00 0x200>;
+        };
+    };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 15011f5752a9..1408b89607ff 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2775,6 +2775,7 @@ S:	Maintained
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/cix.git
 F:	Documentation/devicetree/bindings/arm/cix.yaml
 F:	Documentation/devicetree/bindings/mailbox/cix,sky1-mbox.yaml
+F:	Documentation/devicetree/bindings/usb/cix,sky1-usbss-rcsu.yaml
 F:	arch/arm64/boot/dts/cix/
 F:	drivers/mailbox/cix-mailbox.c
 K:	\bcix\b
-- 
2.54.0



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

* [PATCH v4 2/4] dt-bindings: usb: Add CIX Sky1 USBSSP controller
  2026-09-06  3:24 [PATCH v4 0/4] Add CIX Sky1 USBSSP controller support Hongliang Yang
  2026-09-06  3:24 ` [PATCH v4 1/4] dt-bindings: usb: Add CIX Sky1 USBSSP RCSU system controller Hongliang Yang
@ 2026-09-06  3:24 ` Hongliang Yang
  2026-09-06  6:55   ` Krzysztof Kozlowski
  2026-09-09  7:51   ` Krzysztof Kozlowski
  2026-09-06  3:24 ` [PATCH v4 3/4] usb: cdns3: Add CIX Sky1 glue driver Hongliang Yang
  2026-09-06  3:24 ` [PATCH v4 4/4] arm64: dts: cix: Add USB4/USB5 nodes for Sky1 Hongliang Yang
  3 siblings, 2 replies; 12+ messages in thread
From: Hongliang Yang @ 2026-09-06  3:24 UTC (permalink / raw)
  To: peter.chen, gregkh, robh, krzk+dt, conor+dt, krzk,
	linux-arm-kernel, linux-usb, devicetree, linux-kernel
  Cc: p.zabel, vkoul, neil.armstrong, pawell, rogerq

Add device tree binding for the CIX Sky1 Cadence USBSSP controller
glue layer. The integration adds glue registers and mode strap
controls in the Sky1 S5 system controller. The CIX glue node wraps
a Cadence USBSSP core as a child node.

The per-controller RCSU control and status registers live in a shared
RCSU region described by the cix,sky1-usbss-rcsu binding and are
referenced through the cix,usb-rcsu phandle.

The per-controller RCSU registers are accessed through a syscon regmap
referenced by the cix,usb-rcsu phandle.
Signed-off-by: Hongliang Yang <hongliang.yang@cixtech.com>
---
 .../bindings/usb/cix,sky1-usbssp.yaml         | 144 ++++++++++++++++++
 MAINTAINERS                                   |   3 +
 2 files changed, 147 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/cix,sky1-usbssp.yaml

diff --git a/Documentation/devicetree/bindings/usb/cix,sky1-usbssp.yaml b/Documentation/devicetree/bindings/usb/cix,sky1-usbssp.yaml
new file mode 100644
index 000000000000..8e66dea50fa7
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/cix,sky1-usbssp.yaml
@@ -0,0 +1,144 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/cix,sky1-usbssp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: CIX Sky1 Cadence USBSSP Controller
+
+maintainers:
+  - Hongliang Yang <hongliang.yang@cixtech.com>
+
+description:
+  The CIX Sky1 USBSSP controller is based on the Cadence USBSSP DRD
+  controller. The integration adds glue registers and mode strap controls
+  in the Sky1 S5 system controller. The CIX glue node wraps a Cadence
+  USBSSP core as a child node. The per-controller RCSU control/status
+  registers live in a shared RCSU region and are accessed through the
+  cix,usb-rcsu phandle.
+
+properties:
+  compatible:
+    const: cix,sky1-usbssp
+
+  cix,usb-rcsu:
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    description: |
+      A phandle to the USBSSP RCSU system controller region (see
+      cix,sky1-usbss-rcsu.yaml) followed by two cells: the offset of
+      the AXI property configuration register and the offset of the
+      controller status register, both relative to the RCSU region.
+    items:
+      items:
+        - description: phandle to the USBSSP RCSU syscon node
+        - description: offset of the AXI property configuration register
+        - description: offset of the controller status register
+
+  clocks:
+    items:
+      - description: Start-of-frame clock
+      - description: AXI bus clock
+      - description: Low-power mode clock
+      - description: APB register interface clock
+
+  clock-names:
+    items:
+      - const: sof
+      - const: axi
+      - const: lpm
+      - const: apb
+
+  resets:
+    items:
+      - description: APB register reset
+      - description: Controller reset
+
+  reset-names:
+    items:
+      - const: apb
+      - const: core
+
+  cix,usb-syscon:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      Phandle to the Sky1 S5 system controller used to program USB mode
+      strap controls.
+
+  "#address-cells":
+    const: 2
+
+  "#size-cells":
+    const: 2
+
+  ranges: true
+
+patternProperties:
+  "^usb@[0-9a-f]+$":
+    $ref: cdns,usb3.yaml#
+
+required:
+  - compatible
+  - cix,usb-rcsu
+  - clocks
+  - clock-names
+  - resets
+  - reset-names
+  - cix,usb-syscon
+  - "#address-cells"
+  - "#size-cells"
+  - ranges
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/cix,sky1.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/reset/cix,sky1-s5-system-control.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        rcsu: syscon@91c0300 {
+            compatible = "cix,sky1-usbss-rcsu", "syscon";
+            reg = <0x00 0x091c0300 0x00 0x200>;
+        };
+
+        usb-4 {
+            compatible = "cix,sky1-usbssp";
+            ranges;
+            #address-cells = <2>;
+
+            clocks = <&scmi_clk CLK_TREE_USB3A_H0_CLK_SOF>,
+                     <&scmi_clk CLK_TREE_USB3A_0_AXI_GATE>,
+                     <&scmi_clk CLK_TREE_USB3A_H0_CLK_LPM>,
+                     <&scmi_clk CLK_TREE_USB3A_0_APB_GATE>;
+            clock-names = "sof", "axi", "lpm", "apb";
+            resets = <&src SKY1_USBC_SS2_PRST_N>,
+                     <&src SKY1_USBC_SS2_RST_N>;
+            reset-names = "apb", "core";
+            #size-cells = <2>;
+            cix,usb-syscon = <&src>;
+            cix,usb-rcsu = <&rcsu 0x14 0x100>;
+
+            usb@91d0000 {
+                compatible = "cdns,usb3";
+                reg = <0x00 0x91d0000 0x00 0x4000>,
+                      <0x00 0x91d8000 0x00 0x8000>,
+                      <0x00 0x91d4000 0x00 0x4000>;
+                reg-names = "otg", "xhci", "dev";
+                dr_mode = "otg";
+
+                interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
+                             <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>,
+                             <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+                             <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
+                interrupt-names = "host", "peripheral", "otg", "wakeup";
+                maximum-speed = "super-speed-plus";
+
+                phys = <&usb3_phy4_0>, <&usb2_phy6>;
+                phy-names = "cdns3,usb3-phy", "cdns3,usb2-phy";
+            };
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 1408b89607ff..8899a010fece 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2775,9 +2775,12 @@ S:	Maintained
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/cix.git
 F:	Documentation/devicetree/bindings/arm/cix.yaml
 F:	Documentation/devicetree/bindings/mailbox/cix,sky1-mbox.yaml
+F:	Documentation/devicetree/bindings/phy/cix,sky1-usb3-phy.yaml
 F:	Documentation/devicetree/bindings/usb/cix,sky1-usbss-rcsu.yaml
+F:	Documentation/devicetree/bindings/usb/cix,sky1-usbssp.yaml
 F:	arch/arm64/boot/dts/cix/
 F:	drivers/mailbox/cix-mailbox.c
+F:	drivers/phy/cix/
 K:	\bcix\b
 
 ARM/CLKDEV SUPPORT
-- 
2.54.0



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

* [PATCH v4 3/4] usb: cdns3: Add CIX Sky1 glue driver
  2026-09-06  3:24 [PATCH v4 0/4] Add CIX Sky1 USBSSP controller support Hongliang Yang
  2026-09-06  3:24 ` [PATCH v4 1/4] dt-bindings: usb: Add CIX Sky1 USBSSP RCSU system controller Hongliang Yang
  2026-09-06  3:24 ` [PATCH v4 2/4] dt-bindings: usb: Add CIX Sky1 USBSSP controller Hongliang Yang
@ 2026-09-06  3:24 ` Hongliang Yang
  2026-09-06  3:24 ` [PATCH v4 4/4] arm64: dts: cix: Add USB4/USB5 nodes for Sky1 Hongliang Yang
  3 siblings, 0 replies; 12+ messages in thread
From: Hongliang Yang @ 2026-09-06  3:24 UTC (permalink / raw)
  To: peter.chen, gregkh, robh, krzk+dt, conor+dt, krzk,
	linux-arm-kernel, linux-usb, devicetree, linux-kernel
  Cc: p.zabel, vkoul, neil.armstrong, pawell, rogerq

Add a glue layer driver for the Cadence USBSSP controller integrated
in the CIX Sky1 SoC. The driver manages the controller clocks,
resets, and the mode strap controls located in the Sky1 S5 system
controller.

The per-controller RCSU control and status registers live in a shared
RCSU region described by the cix,sky1-usbss-rcsu binding and are
referenced through the cix,usb-rcsu phandle.

The per-controller RCSU registers are accessed through a syscon regmap
referenced by the cix,usb-rcsu phandle.

The shared RCSU slice of the two controllers is described by a syscon
node; each controller references its registers through the cix,usb-rcsu
phandle with offsets.
Signed-off-by: Hongliang Yang <hongliang.yang@cixtech.com>
---
 drivers/usb/cdns3/Kconfig      |  13 +
 drivers/usb/cdns3/Makefile     |   1 +
 drivers/usb/cdns3/cdnsp-sky1.c | 726 +++++++++++++++++++++++++++++++++
 drivers/usb/cdns3/cdnsp-sky1.h | 129 ++++++
 4 files changed, 869 insertions(+)
 create mode 100644 drivers/usb/cdns3/cdnsp-sky1.c
 create mode 100644 drivers/usb/cdns3/cdnsp-sky1.h

diff --git a/drivers/usb/cdns3/Kconfig b/drivers/usb/cdns3/Kconfig
index 39ad23d1ada8..03d8e170a98a 100644
--- a/drivers/usb/cdns3/Kconfig
+++ b/drivers/usb/cdns3/Kconfig
@@ -77,6 +77,19 @@ config USB_CDNSP_PCI
 	  If you choose to build this driver as module it will
 	  be dynamically linked and module will be called cdnsp-pci.ko
 
+config USB_CDNSP_SKY1
+	tristate "Cadence USB3 support on CIX Sky1 SoC platforms"
+	depends on USB_CDNS3
+	depends on ARCH_CIX || COMPILE_TEST
+	default USB_CDNS3
+	help
+	  Glue driver for the Cadence USB dual-role controllers on CIX Sky1
+	  (device tree compatible cix,sky1-usb3). It enables clocks and resets
+	  from the SoC, then uses the shared cdns3 platform core (cdns.ko).
+
+	  If built as a module, the module is named cdnsp-sky1.ko and must be
+	  loaded after the cdns core module when both are loadable modules.
+
 config USB_CDNS3_TI
 	tristate "Cadence USB3 support on TI platforms"
 	depends on ARCH_K3 || COMPILE_TEST
diff --git a/drivers/usb/cdns3/Makefile b/drivers/usb/cdns3/Makefile
index b2e4ba6a49a3..ab813aaf9940 100644
--- a/drivers/usb/cdns3/Makefile
+++ b/drivers/usb/cdns3/Makefile
@@ -28,3 +28,4 @@ obj-$(CONFIG_USB_CDNSP_PCI)			+= cdnsp-pci.o
 obj-$(CONFIG_USB_CDNS3_TI)			+= cdns3-ti.o
 obj-$(CONFIG_USB_CDNS3_IMX)			+= cdns3-imx.o
 obj-$(CONFIG_USB_CDNS3_STARFIVE)		+= cdns3-starfive.o
+obj-$(CONFIG_USB_CDNSP_SKY1)			+= cdnsp-sky1.o
diff --git a/drivers/usb/cdns3/cdnsp-sky1.c b/drivers/usb/cdns3/cdnsp-sky1.c
new file mode 100644
index 000000000000..1618b2783a80
--- /dev/null
+++ b/drivers/usb/cdns3/cdnsp-sky1.c
@@ -0,0 +1,726 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * cdnsp-sky1.c - CIX Sky1 glue for Cadence USBSSP DRD controller
+ *
+ * Copyright (C) 2026 CIX Technology Group Co., Ltd.
+ */
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "cdnsp-sky1.h"
+#include "core.h"
+
+static const char *cix_usb_clk_names[CIX_USB_CLK_NUM] = {
+	"sof",
+	"axi",
+	"lpm",
+	"apb",
+};
+
+struct cdnsp_sky1_strap_signal {
+	unsigned int offset, bit;
+};
+
+static const struct cdnsp_sky1_strap_signal strap_signals[SKY1_USB_S5_NUM] = {
+	/* usb config in s5 domain */
+	[U3_TYPEC_DRD_ID]	= { USB_MODE_STRAP_S5_DOMAIN, U3_TYPEC_DRD_MODE_STRAP_BIT },
+	[U3_TYPEC_HOST0_ID]	= { USB_MODE_STRAP_S5_DOMAIN, U3_TYPEC_HOST0_MODE_STRAP_BIT },
+	[U3_TYPEC_HOST1_ID]	= { USB_MODE_STRAP_S5_DOMAIN, U3_TYPEC_HOST1_MODE_STRAP_BIT },
+	[U3_TYPEC_HOST2_ID]	= { USB_MODE_STRAP_S5_DOMAIN, U3_TYPEC_HOST2_MODE_STRAP_BIT },
+	[U3_TYPEA_CTRL0_ID]	= { USB_MODE_STRAP_S5_DOMAIN, U3_TYPEA_CTRL0_MODE_STRAP_BIT },
+	[U3_TYPEA_CTRL1_ID]	= { USB_MODE_STRAP_S5_DOMAIN, U3_TYPEA_CTRL1_MODE_STRAP_BIT},
+	[U2_HOST0_ID]		= { USB_MODE_STRAP_S5_DOMAIN, U2_HOST0_MODE_STRAP_BIT },
+	[U2_HOST1_ID]		= { USB_MODE_STRAP_S5_DOMAIN, U2_HOST1_MODE_STRAP_BIT },
+	[U2_HOST2_ID]		= { USB_MODE_STRAP_S5_DOMAIN, U2_HOST2_MODE_STRAP_BIT },
+	[U2_HOST3_ID]		= { USB_MODE_STRAP_S5_DOMAIN, U2_HOST3_MODE_STRAP_BIT },
+};
+
+static int cdnsp_sky1_set_mode_by_id(struct device *dev, int mode)
+{
+	struct cdnsp_sky1 *data = dev_get_drvdata(dev);
+
+	return regmap_update_bits(data->usb_syscon,
+				  strap_signals[data->id].offset,
+				  GENMASK(strap_signals[data->id].bit + 1,
+					  strap_signals[data->id].bit),
+				  mode << strap_signals[data->id].bit);
+}
+
+/**
+ * cdnsp_sky1_clk_enable_all() - enable all clocks for usb controller
+ * @dev:	Pointer to the device of platform_device
+ *
+ */
+
+static int cdnsp_sky1_clk_enable_all(struct device *dev)
+{
+	int i, ret = 0;
+	struct cdnsp_sky1 *data = dev_get_drvdata(dev);
+	struct clk **cix_usb_clks = data->cix_usb_clks;
+
+	for (i = 0; i < CIX_USB_CLK_NUM; i++) {
+		cix_usb_clks[i] = devm_clk_get(dev, cix_usb_clk_names[i]);
+		if (IS_ERR(cix_usb_clks[i])) {
+			ret = dev_err_probe(dev, PTR_ERR(cix_usb_clks[i]),
+					    "could not get %s clock\n",
+					    cix_usb_clk_names[i]);
+			goto err_usb_clks;
+		}
+		ret = clk_prepare_enable(cix_usb_clks[i]);
+		if (ret) {
+			dev_err(dev, "%s enable failed:%d\n", cix_usb_clk_names[i], ret);
+			goto err_usb_clks;
+		}
+	}
+	dev_dbg(dev, "enable sky1 USB clock done\n");
+	return ret;
+
+err_usb_clks:
+	while (--i >= 0)
+		clk_disable_unprepare(cix_usb_clks[i]);
+	return ret;
+};
+
+/**
+ * cdnsp_sky1_clk_disable_all() - disable all clocks for usb controller
+ * @dev:	Pointer to the device of platform_device
+ *
+ */
+
+static void cdnsp_sky1_clk_disable_all(struct device *dev)
+{
+	int i;
+	struct cdnsp_sky1 *data = dev_get_drvdata(dev);
+	struct clk **cix_usb_clks = data->cix_usb_clks;
+
+	for (i = 0; i < CIX_USB_CLK_NUM; i++)
+		clk_disable_unprepare(cix_usb_clks[i]);
+};
+
+/**
+ * cdnsp_sky1_clk_enable_resume() - enable the clocks that are turned
+ * off while suspend
+ * @dev:	Pointer to the device of platform_device
+ *
+ */
+
+static int cdnsp_sky1_clk_enable_resume(struct device *dev)
+{
+	int i, ret;
+	struct cdnsp_sky1 *data = dev_get_drvdata(dev);
+	struct clk **cix_usb_clks = data->cix_usb_clks;
+
+	for (i = 0; i < CIX_USB_CLK_OFF_NUM; i++) {
+		ret = clk_prepare_enable(cix_usb_clks[i]);
+		if (ret) {
+			dev_err(dev, "failed to enable clock %s: %d\n",
+				cix_usb_clk_names[i], ret);
+			goto err_usb_clks;
+		}
+	}
+	return 0;
+
+err_usb_clks:
+	while (--i >= 0)
+		clk_disable_unprepare(cix_usb_clks[i]);
+	return ret;
+};
+
+/**
+ * cdnsp_sky1_clk_disable_suspend() - disable the clocks which are not
+ * needed when suspend
+ * @dev:	Pointer to the device of platform_device
+ *
+ */
+
+static void cdnsp_sky1_clk_disable_suspend(struct device *dev)
+{
+	int i;
+	struct cdnsp_sky1 *data = dev_get_drvdata(dev);
+	struct clk **cix_usb_clks = data->cix_usb_clks;
+
+	for (i = 0; i < CIX_USB_CLK_OFF_NUM; i++)
+		clk_disable_unprepare(cix_usb_clks[i]);
+};
+
+static int sky1_rcsu_handshake(struct cdnsp_sky1 *data, u32 mask, u32 done,
+			       u64 timeout_us)
+{
+	u32	result;
+	int	ret;
+
+	ret = regmap_read_poll_timeout(data->rcsu, data->rcsu_ctst_off, result,
+				       (result & mask) == done ||
+				       result == U32_MAX,
+				       10, timeout_us);
+	if (result == U32_MAX)		/* card removed */
+		return -ENODEV;
+	return ret;
+}
+
+static int cdns_sky1_platform_suspend(struct device *dev,
+				      bool suspend, bool wakeup)
+{
+	struct cdns *cdns = dev_get_drvdata(dev);
+	struct platform_device *xhci_dev = cdns->host_dev;
+	struct usb_hcd  *hcd;
+	struct device *parent = cdns->dev->parent;
+	struct cdnsp_sky1 *data = dev_get_drvdata(parent);
+	u32 value;
+	int poll;
+	int ret = 0;
+	int count = 3;
+
+	data->wakeup = wakeup;
+
+	if (cdns->role != USB_ROLE_HOST)
+		return 0;
+
+	if (!xhci_dev) {
+		dev_dbg(dev, "host controller has not been registered\n");
+		return 0;
+	}
+
+	hcd = dev_get_drvdata(&xhci_dev->dev);
+	if (!hcd) {
+		dev_dbg(dev, "host controller have not registered\n");
+		return 0;
+	}
+
+	if (suspend) {
+		while (count--) {
+			value = readl(hcd->regs + XECP_PM_PMCSR);
+			value &= ~PS_MASK;
+			value |= PS_D3 | PS_PME_En;
+			writel(value, hcd->regs + XECP_PM_PMCSR);
+			/* After controller enters D3, disable AXI and SOF
+			 * until AXI valid flag changes to 0.
+			 */
+			if (sky1_rcsu_handshake(data, AXI_CLOCK_VALID, 0,
+						100ULL * 1000)) {
+				u32 ctst;
+
+				regmap_read(data->rcsu, data->rcsu_ctst_off, &ctst);
+				dev_dbg(dev, "enter D3 failed, register value:%x\n",
+					ctst);
+			} else {
+				break;
+			}
+		}
+		if (count < 0) {
+			u32 ctst;
+
+			regmap_read(data->rcsu, data->rcsu_ctst_off, &ctst);
+			dev_err(dev, "enter D3 failed after retries, register value:%x\n",
+				ctst);
+		}
+	} else {
+		while (count--) {
+			value = readl(hcd->regs + XECP_PM_PMCSR);
+			value &= ~PS_MASK;
+			value |= PS_D0;
+			value &= ~PS_PME_En;
+			writel(value, hcd->regs + XECP_PM_PMCSR);
+			/* Wait power state back to D0 */
+			poll = readl_poll_timeout(hcd->regs + XECP_PM_PMCSR,
+						  value,
+						  (value & PS_MASK) == 0 ||
+						  value == U32_MAX,
+						  10, 100ULL * 1000);
+			if (poll) {
+				dev_dbg(dev, "exit D3 timeout, power state=0x%lx\n",
+					value & PS_MASK);
+			} else {
+				break;
+			}
+		}
+		if (count < 0) {
+			dev_err(dev, "exit D3 timeout after retries, power state=0x%lx\n",
+				value & PS_MASK);
+		}
+	}
+
+	return ret;
+}
+
+static void cdnsp_sky1_configure_controller(struct cdnsp_sky1 *data)
+{
+	int clk;
+	int v0, v1, v2;
+	u32 val = 0;
+
+	if (data->u3_disable) {
+		dev_dbg(data->dev, "disable u3 port\n");
+		writel(D_XEC_CFG_3XPORT_MODE_VALUE, data->device_base
+			+ D_XEC_CFG_3XPORT_MODE);
+	}
+	writel(AXI_HALT, data->device_base + D_XEC_AXI_CAP);
+	writel(AXI_HALT, data->xhci_base + D_XEC_AXI_CAP);
+	writel(data->axi_bmax_value, data->device_base + D_XEC_AXI_CTRL0);
+	writel(data->axi_bmax_value, data->xhci_base + D_XEC_AXI_CTRL0);
+	writel((~(u32)(AXI_HALT)), data->device_base + D_XEC_AXI_CAP);
+	writel((~(u32)(AXI_HALT)), data->xhci_base + D_XEC_AXI_CAP);
+	clk = data->sof_clk_freq;
+	v0 =  25 * clk / 100000000;
+	v1 = clk / 10000;
+	v2 = clk / 10;
+	writel(((v0 > 1) ? v0 - 1 : 1), data->device_base
+		+ D_XEC_PRE_REG_250NS);
+	writel((unsigned int)((v1 / 100 > 1) > 0 ? (v1 / 100) - 1 : 1),
+	       data->device_base + D_XEC_PRE_REG_1US);
+	writel((unsigned int)((v1 / 10 > 1) > 0 ? (v1 / 10) - 1 : 1),
+	       data->device_base + D_XEC_PRE_REG_10US);
+	writel(((v1) > 1 ? v1 - 1 : 1), data->device_base
+		+ D_XEC_PRE_REG_100US);
+	writel((unsigned int)((125 * clk / 1000000) > 1 ? (125 * clk / 1000000) : 1),
+	       data->device_base + D_XEC_PRE_REG_125US);
+	writel(((v2 / 100 > 1) ? (v2 / 100) - 1 : 1), data->device_base
+		+ D_XEC_PRE_REG_1MS);
+	writel(((v2 / 10 > 1) ? (v2 / 10) - 1 : 1), data->device_base
+		+ D_XEC_PRE_REG_10MS);
+	writel((v2 > 1 ? v2 - 1 : 1), data->device_base
+		+ D_XEC_PRE_REG_100MS);
+	dev_dbg(data->dev, "readl:%x, %x ,%x, %x, %x, %x, %x, %x\n",
+		readl(data->device_base + D_XEC_PRE_REG_250NS),
+		readl(data->device_base + D_XEC_PRE_REG_1US),
+		readl(data->device_base + D_XEC_PRE_REG_10US),
+		readl(data->device_base + D_XEC_PRE_REG_100US),
+		readl(data->device_base + D_XEC_PRE_REG_125US),
+		readl(data->device_base + D_XEC_PRE_REG_1MS),
+		readl(data->device_base + D_XEC_PRE_REG_10MS),
+		readl(data->device_base + D_XEC_PRE_REG_100MS));
+	clk = data->lpm_clk_freq;
+	v0 =  25 * clk / 100000000;
+	v1 = clk / 10000;
+	v2 = clk / 10;
+	writel(((v0 > 1) ? v0 - 1 : 1), data->device_base
+		+ D_XEC_LPM_PRE_REG_250NS);
+	writel((unsigned int)((v1 / 100 > 1) > 0 ? (v1 / 100) - 1 : 1), data->device_base
+		+ D_XEC_LPM_PRE_REG_1US);
+	writel((unsigned int)((v1 / 10 > 1) > 0 ? (v1 / 10) - 1 : 1), data->device_base
+		+ D_XEC_LPM_PRE_REG_10US);
+	writel(((v1) > 1 ? v1 - 1 : 1), data->device_base
+		+ D_XEC_LPM_PRE_REG_100US);
+	writel((unsigned int)((125 * clk / 1000000) > 1 ? (125 * clk / 1000000) : 1),
+	       data->device_base + D_XEC_LPM_PRE_REG_125US);
+	writel(((v2 / 100 > 1) ? (v2 / 100) - 1 : 1), data->device_base
+		+ D_XEC_LPM_PRE_REG_1MS);
+	writel(((v2 / 10 > 1) ? (v2 / 10) - 1 : 1), data->device_base
+		+ D_XEC_LPM_PRE_REG_10MS);
+	writel((v2 > 1 ? v2 - 1 : 1), data->device_base
+		+ D_XEC_LPM_PRE_REG_100MS);
+	v0 = readl(data->xhci_base + XEC_USBSSP_CHICKEN_BITS_3);
+	v0 &= ~(CFG_APB_TIMEOUT_PSLVERR_EN | CFG_APB_PSLVERR_EN);
+	writel(v0, data->xhci_base + XEC_USBSSP_CHICKEN_BITS_3);
+	if (data->u3_disable) {
+		dev_dbg(data->dev, "disable u3 port\n");
+		writel(XEC_CFG_3XPORT_MODE_VALUE, data->xhci_base
+			+ XEC_CFG_3XPORT_MODE);
+	} else if (data->ssp_disable) {
+		dev_dbg(data->dev, "disable ssp\n");
+		v0 = readl(data->xhci_base + XEC_CFG_3XPORT_MODE);
+		writel(v0  & CFG_3XPORT_MODE_DIS_SSP, data->xhci_base
+			+ XEC_CFG_3XPORT_MODE);
+	}
+	clk = data->sof_clk_freq;
+	v0 =  25 * clk / 100000000;
+	v1 = clk / 10000;
+	v2 = clk / 10;
+	writel(((v0 > 1) ? v0 - 1 : 0), data->xhci_base
+		+ XEC_PRE_REG_250NS);
+	writel((unsigned int)((v1 / 100 > 1) > 0 ? (v1 / 100) - 1 : 0), data->xhci_base
+		+ XEC_PRE_REG_1US);
+	writel((unsigned int)((v1 / 10 > 1) > 0 ? (v1 / 10) - 1 : 0), data->xhci_base
+		+ XEC_PRE_REG_10US);
+	writel(((v1) > 1 ? v1 - 1 : 0), data->xhci_base
+		+ XEC_PRE_REG_100US);
+	writel((unsigned int)((125 * clk / 1000000) > 1 ? (125 * clk / 1000000) : 0),
+	       data->xhci_base + XEC_PRE_REG_125US);
+	writel(((v2 / 100 > 1) ? (v2 / 100) - 1 : 0), data->xhci_base
+		+ XEC_PRE_REG_1MS);
+	writel(((v2 / 10 > 1) ? (v2 / 10) - 1 : 0), data->xhci_base
+		+ XEC_PRE_REG_10MS);
+	writel((v2 > 1 ? v2 - 1 : 0), data->xhci_base
+		+ XEC_PRE_REG_100MS);
+	clk = data->lpm_clk_freq;
+	v0 =  25 * clk / 100000000;
+	v1 = clk / 10000;
+	v2 = clk / 10;
+	writel(((v0 > 1) ? v0 - 1 : 0), data->xhci_base
+		+ XEC_LPM_PRE_REG_250NS);
+	writel((unsigned int)((v1 / 100 > 1) > 0 ? (v1 / 100) - 1 : 0), data->xhci_base
+		+ XEC_LPM_PRE_REG_1US);
+	writel((unsigned int)((v1 / 10 > 1) > 0 ? (v1 / 10) - 1 : 0), data->xhci_base
+		+ XEC_LPM_PRE_REG_10US);
+	writel(((v1) > 1 ? v1 - 1 : 0), data->xhci_base
+		+ XEC_LPM_PRE_REG_100US);
+	writel((unsigned int)((125 * clk / 1000000) > 1 ? (125 * clk / 1000000) : 0),
+	       data->xhci_base + XEC_LPM_PRE_REG_125US);
+	writel(((v2 / 100 > 1) ? (v2 / 100) - 1 : 0), data->xhci_base
+		+ XEC_LPM_PRE_REG_1MS);
+	writel(((v2 / 10 > 1) ? (v2 / 10) - 1 : 0), data->xhci_base
+		+ XEC_LPM_PRE_REG_10MS);
+	writel((v2 > 1 ? v2 - 1 : 0), data->xhci_base
+		+ XEC_LPM_PRE_REG_100MS);
+	val = readl(data->xhci_base + XEC_USBSSP_CLK_GATING_CTRL);
+	val |= HOST20_ACLK_GATING_DISABLE | HOST20_UTMI_GATING_DISABLE;
+	writel(val, data->xhci_base + XEC_USBSSP_CLK_GATING_CTRL);
+}
+
+static int cdnsp_sky1_drd_init(struct cdnsp_sky1 *data)
+{
+	int ret = 0;
+
+	reset_control_assert(data->reset);
+	reset_control_assert(data->preset);
+	cdnsp_sky1_clk_disable_all(data->dev);
+	ret = cdnsp_sky1_clk_enable_all(data->dev);
+	if (ret)
+		return ret;
+	regmap_write(data->rcsu, data->rcsu_axi_off, CIX_USB_AXI_WR_CACHE_VALUE);
+	cdnsp_sky1_set_mode_by_id(data->dev, MODE_STRAP_OTG);
+	reset_control_deassert(data->preset);
+	cdnsp_sky1_configure_controller(data);
+	reset_control_deassert(data->reset);
+	return ret;
+}
+
+static void __iomem *sky1_of_get_addr_by_name(struct device_node *parent, const char *name)
+{
+	void __iomem *addr = NULL;
+	struct device_node *node;
+	int index;
+
+	for_each_child_of_node(parent, node) {
+		index = of_property_match_string(node, "reg-names", name);
+		if (index >= 0) {
+			addr = of_iomap(node, index);
+			of_node_put(node);
+			break;
+		}
+	}
+
+	return addr;
+}
+
+static void __iomem *sky1_get_addr_by_name(struct device *dev, const char *name)
+{
+	return sky1_of_get_addr_by_name(dev->of_node, name);
+}
+
+static void sky1_put_addr(void __iomem *regs)
+{
+	if (regs)
+		iounmap(regs);
+}
+
+static int cdnsp_sky1_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
+	struct of_dev_auxdata cdns_sky1_auxdata[] = {
+		{ .compatible = "cdns,usb3", },
+		{},
+	};
+	struct cdnsp_sky1 *data;
+	struct cdns3_platform_data *cdns_sky1_pdata;
+	struct of_phandle_args rcsu_args;
+	int ret = 0;
+
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+	ret = of_parse_phandle_with_fixed_args(node, "cix,usb-rcsu", 2, 0,
+					       &rcsu_args);
+	if (ret) {
+		dev_err(dev, "failed to parse cix,usb-rcsu: %d\n", ret);
+		return ret;
+	}
+	data->rcsu = syscon_regmap_lookup_by_phandle(node, "cix,usb-rcsu");
+	if (IS_ERR(data->rcsu)) {
+		ret = PTR_ERR(data->rcsu);
+		dev_err(dev, "Unable to get cix,usb-rcsu regmap");
+		return ret;
+	}
+	data->rcsu_axi_off = rcsu_args.args[0];
+	data->rcsu_ctst_off = rcsu_args.args[1];
+	data->reset = devm_reset_control_get_exclusive(&pdev->dev, "core");
+	if (IS_ERR(data->reset)) {
+		ret = PTR_ERR(data->reset);
+		dev_err(dev, "get reset error:%d\n", ret);
+		return ret;
+	}
+	data->preset = devm_reset_control_get_exclusive(&pdev->dev, "apb");
+	if (IS_ERR(data->preset)) {
+		ret = PTR_ERR(data->preset);
+		dev_err(dev, "get reset error:%d\n", ret);
+		return ret;
+	}
+	platform_set_drvdata(pdev, data);
+	data->dev = dev;
+	ret = of_alias_get_id(dev->of_node, "usb");
+	if (ret == -ENODEV) {
+		if (device_property_read_u32(dev, "id", &ret))
+			ret = -ENODEV;
+	}
+	if (ret < 0 || ret >=  SKY1_USB_S5_NUM) {
+		dev_err(dev, "get alias failed.\n");
+		return ret;
+	}
+	data->id = ret;
+	data->usb_syscon = syscon_regmap_lookup_by_phandle(dev->of_node,
+							   "cix,usb-syscon");
+	if (IS_ERR(data->usb_syscon)) {
+		dev_err(dev, "Unable to get cix,usb-syscon regmap");
+		return PTR_ERR(data->usb_syscon);
+	}
+	data->u3_disable = device_property_read_bool(dev, "u3-port-disable");
+	data->ssp_disable = device_property_read_bool(dev, "ssp-disable");
+	data->sof_clk_freq = CIX_USB_CLK_8M;
+	data->lpm_clk_freq = CIX_USB_CLK_32K;
+	data->axi_bmax_value = AXI_BMAX_VALUE_DEFAULT;
+	data->xhci_base = sky1_get_addr_by_name(dev, "xhci");
+	if (!data->xhci_base) {
+		ret = -ENODEV;
+		goto err_put_xhci;
+	}
+	data->device_base = sky1_get_addr_by_name(dev, "dev");
+	if (!data->device_base) {
+		ret = -ENODEV;
+		goto err_put_addrs;
+	}
+	ret = cdnsp_sky1_drd_init(data);
+	if (ret == -ETIMEDOUT)
+		ret = -EPROBE_DEFER;
+	if (ret) {
+		/*
+		 * drd_init() leaves the clocks disabled and the resets
+		 * asserted on failure; only the address mappings are
+		 * left to release.
+		 */
+		goto err_put_addrs;
+	}
+	data->oc_gpio = devm_gpiod_get_optional(data->dev, "oc", GPIOD_IN);
+	if (IS_ERR(data->oc_gpio)) {
+		dev_err(data->dev, "can not get oc_gpio\n");
+		ret = PTR_ERR(data->oc_gpio);
+		goto err_quiesce;
+	}
+	if (data->oc_gpio) {
+		ret = gpiod_direction_input(data->oc_gpio);
+		if (ret < 0)
+			dev_err(data->dev, "set oc_gpio input failed:%d\n", ret);
+	}
+	/*
+	 * The platform data is devm-allocated, so it stays alive as long as
+	 * this device; the child devices are depopulated before it is freed.
+	 */
+	cdns_sky1_pdata = devm_kzalloc(dev, sizeof(*cdns_sky1_pdata), GFP_KERNEL);
+	if (!cdns_sky1_pdata) {
+		ret = -ENOMEM;
+		goto err_quiesce;
+	}
+	cdns_sky1_pdata->platform_suspend = cdns_sky1_platform_suspend;
+	cdns_sky1_pdata->quirks = CDNS3_DEFAULT_PM_RUNTIME_ALLOW;
+	cdns_sky1_auxdata[0].platform_data = cdns_sky1_pdata;
+	ret = of_platform_populate(node, NULL, cdns_sky1_auxdata, dev);
+	if (ret) {
+		dev_err(dev, "failed to create children: %d\n", ret);
+		goto err_quiesce;
+	}
+	device_set_wakeup_capable(dev, true);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+	return 0;
+
+err_quiesce:
+	reset_control_assert(data->reset);
+	reset_control_assert(data->preset);
+	cdnsp_sky1_clk_disable_all(dev);
+err_put_addrs:
+	sky1_put_addr(data->device_base);
+err_put_xhci:
+	sky1_put_addr(data->xhci_base);
+	return ret;
+}
+
+static void cdnsp_sky1_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct cdnsp_sky1 *data = dev_get_drvdata(dev);
+
+	pm_runtime_get_sync(dev);
+	of_platform_depopulate(dev);
+	sky1_put_addr(data->xhci_base);
+	sky1_put_addr(data->device_base);
+	reset_control_assert(data->reset);
+	reset_control_assert(data->preset);
+	cdnsp_sky1_clk_disable_all(dev);
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+	pm_runtime_put_noidle(dev);
+}
+
+/*
+ * Because the wake-up interrupt and host interrupt are the same interrupt,
+ * closing the axi and sof clock will result in the inability to generate
+ * port status change interrupt.
+ */
+static int cdnsp_sky1_system_suspend(struct device *dev)
+{
+	struct cdnsp_sky1 *data = dev_get_drvdata(dev);
+
+	if (!data->wakeup) {
+		reset_control_assert(data->reset);
+		reset_control_assert(data->preset);
+	}
+	cdnsp_sky1_clk_disable_suspend(dev);
+	return 0;
+}
+
+static int cdnsp_sky1_system_resume(struct device *dev)
+{
+	int ret = 0;
+	struct cdnsp_sky1 *data = dev_get_drvdata(dev);
+
+	ret = cdnsp_sky1_clk_enable_resume(dev);
+	if (ret)
+		return ret;
+	if (!data->wakeup) {
+		regmap_write(data->rcsu, data->rcsu_axi_off,
+			     CIX_USB_AXI_WR_CACHE_VALUE);
+		cdnsp_sky1_set_mode_by_id(data->dev, MODE_STRAP_OTG);
+		reset_control_deassert(data->preset);
+		cdnsp_sky1_configure_controller(data);
+		reset_control_deassert(data->reset);
+	}
+	return 0;
+}
+
+static const struct dev_pm_ops cdnsp_sky1_pm_ops = {
+	SYSTEM_SLEEP_PM_OPS(cdnsp_sky1_system_suspend, cdnsp_sky1_system_resume)
+};
+
+static const struct of_device_id cdns_sky1_of_match[] = {
+	{ .compatible = "cix,sky1-usbssp", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, cdns_sky1_of_match);
+
+static int cdnsp_sky1_find_cdns_dev(struct device *dev, void *data)
+{
+	struct device **cdns_dev = data;
+
+	if (dev->of_node && of_device_is_compatible(dev->of_node, "cdns,usb3")) {
+		/* keep a reference: the pointer is used after the iteration */
+		*cdns_dev = get_device(dev);
+		return 1;
+	}
+	return 0;
+}
+
+static int cdnsp_sky1_find_gadget_match(struct device *dev, void *data)
+{
+	struct device **gadget_dev = data;
+	const char *name = dev_name(dev);
+	static const char gadget_prefix[] = "gadget.";
+
+	/*
+	 * The gadget device is registered on the gadget bus with name
+	 * "gadget.%d" (see usb_add_gadget_udc -> dev_set_name).
+	 * It sits on the gadget bus and has the function driver bound to it.
+	 * Verify the device is on the gadget bus by checking the bus name.
+	 * This prevents matching devices that happen to have "gadget." prefix
+	 * in their name but are not real gadget devices, and also avoids
+	 * NULL pointer dereference when device bus is being removed.
+	 */
+	if (name && dev->bus && !strcmp(dev->bus->name, "gadget") &&
+	    !strncmp(name, gadget_prefix, sizeof(gadget_prefix) - 1)) {
+		/* keep a reference: the pointer is used after the iteration */
+		*gadget_dev = get_device(dev);
+		return 1;
+	}
+	return 0;
+}
+
+static void cdnsp_sky1_shutdown(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct cdnsp_sky1 *data = dev_get_drvdata(dev);
+	struct device *cdns_dev = NULL;
+	struct device *gadget_dev = NULL;
+	struct cdns *cdns = NULL;
+
+	if (!device_may_wakeup(dev)) {
+		/*
+		 * Find the cdns3 child device, then find its gadget device
+		 * and release the function driver before disabling clocks.
+		 * This ensures all register accesses in gadget_unbind_driver
+		 * complete before clocks are turned off.
+		 */
+		device_for_each_child(dev, &cdns_dev, cdnsp_sky1_find_cdns_dev);
+		if (cdns_dev)
+			cdns = dev_get_drvdata(cdns_dev);
+		if (cdns)
+			device_for_each_child(cdns_dev, &gadget_dev,
+					      cdnsp_sky1_find_gadget_match);
+		if (gadget_dev)
+			device_release_driver(gadget_dev);
+		if (cdns && cdns->host_dev) {
+			struct usb_hcd *hcd = platform_get_drvdata(cdns->host_dev);
+
+			if (hcd && hcd->irq > 0) {
+				/*
+				 * Clear HCD_FLAG_HW_ACCESSIBLE before disable_irq.
+				 * This prevents usb_hcd_irq from calling xhci_irq
+				 * (which reads USBSTS) after clocks are disabled.
+				 */
+				clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+				disable_irq(hcd->irq);
+				synchronize_irq(hcd->irq);
+			}
+		}
+		reset_control_assert(data->reset);
+		reset_control_assert(data->preset);
+		cdnsp_sky1_clk_disable_all(dev);
+		put_device(gadget_dev);
+		put_device(cdns_dev);
+	}
+}
+
+static struct platform_driver cdnsp_sky1_driver = {
+	.probe		= cdnsp_sky1_probe,
+	.remove		= cdnsp_sky1_remove,
+	.shutdown	= cdnsp_sky1_shutdown,
+	.driver		= {
+		.name	= "cdnsp-sky1",
+		.of_match_table	= cdns_sky1_of_match,
+		.pm	= pm_sleep_ptr(&cdnsp_sky1_pm_ops),
+	},
+};
+
+module_platform_driver(cdnsp_sky1_driver);
+
+MODULE_ALIAS("platform:cdnsp-sky1");
+MODULE_DESCRIPTION("CIX Sky1 Cadence USBSSP DRD glue driver");
+MODULE_AUTHOR("Hongliang Yang <hongliang.yang@cixtech.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/cdns3/cdnsp-sky1.h b/drivers/usb/cdns3/cdnsp-sky1.h
new file mode 100644
index 000000000000..2405d01dd5a4
--- /dev/null
+++ b/drivers/usb/cdns3/cdnsp-sky1.h
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _CDNSP_SKY1_H
+#define _CDNSP_SKY1_H
+#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
+#include <linux/reset.h>
+#include <linux/types.h>
+
+#define USB_MODE_STRAP_S5_DOMAIN        0x424
+
+#define MODE_STRAP_OTG                  0
+
+#define U3_TYPEC_DRD_ID                 0
+#define U3_TYPEC_HOST0_ID               1
+#define U3_TYPEC_HOST1_ID               2
+#define U3_TYPEC_HOST2_ID               3
+#define U3_TYPEA_CTRL0_ID               4
+#define U3_TYPEA_CTRL1_ID               5
+#define U2_HOST0_ID                     6
+#define U2_HOST1_ID                     7
+#define U2_HOST2_ID                     8
+#define U2_HOST3_ID                     9
+#define SKY1_USB_S5_NUM                 10
+
+#define U3_TYPEC_DRD_MODE_STRAP_BIT     12
+#define U3_TYPEC_HOST0_MODE_STRAP_BIT   14
+#define U3_TYPEC_HOST1_MODE_STRAP_BIT   16
+#define U3_TYPEC_HOST2_MODE_STRAP_BIT   18
+#define U3_TYPEA_CTRL0_MODE_STRAP_BIT   8
+#define U3_TYPEA_CTRL1_MODE_STRAP_BIT   10
+#define U2_HOST0_MODE_STRAP_BIT         0
+#define U2_HOST1_MODE_STRAP_BIT         2
+#define U2_HOST2_MODE_STRAP_BIT         4
+#define U2_HOST3_MODE_STRAP_BIT         6
+
+#define AXI_HALT                        BIT(31)
+#define AXI_BMAX_VALUE_DEFAULT          0x7
+
+#define D_XEC_CFG_3XPORT_MODE           0x2040
+#define D_XEC_AXI_CAP                   0x2174
+#define D_XEC_AXI_CTRL0                 0x217C
+#define D_XEC_PRE_REG_250NS             0x21E8
+#define D_XEC_PRE_REG_1US               0x21EC
+#define D_XEC_PRE_REG_10US              0x21F0
+#define D_XEC_PRE_REG_100US             0x21F4
+#define D_XEC_PRE_REG_125US             0x21F8
+#define D_XEC_PRE_REG_1MS               0x21FC
+#define D_XEC_PRE_REG_10MS              0x2200
+#define D_XEC_PRE_REG_100MS             0x2204
+#define D_XEC_LPM_PRE_REG_250NS         0x2208
+#define D_XEC_LPM_PRE_REG_1US           0x220C
+#define D_XEC_LPM_PRE_REG_10US          0x2210
+#define D_XEC_LPM_PRE_REG_100US         0x2214
+#define D_XEC_LPM_PRE_REG_125US         0x2218
+#define D_XEC_LPM_PRE_REG_1MS           0x221C
+#define D_XEC_LPM_PRE_REG_10MS          0x2220
+#define D_XEC_LPM_PRE_REG_100MS         0x2224
+
+#define XEC_CFG_3XPORT_MODE             0x2040
+#define XEC_PRE_REG_250NS               0x21E8
+#define XEC_PRE_REG_1US                 0x21EC
+#define XEC_PRE_REG_10US                0x21F0
+#define XEC_PRE_REG_100US               0x21F4
+#define XEC_PRE_REG_125US               0x21F8
+#define XEC_PRE_REG_1MS                 0x21FC
+#define XEC_PRE_REG_10MS                0x2200
+#define XEC_PRE_REG_100MS               0x2204
+#define XEC_LPM_PRE_REG_250NS           0x2208
+#define XEC_LPM_PRE_REG_1US             0x220C
+#define XEC_LPM_PRE_REG_10US            0x2210
+#define XEC_LPM_PRE_REG_100US           0x2214
+#define XEC_LPM_PRE_REG_125US           0x2218
+#define XEC_LPM_PRE_REG_1MS             0x221C
+#define XEC_LPM_PRE_REG_10MS            0x2220
+#define XEC_LPM_PRE_REG_100MS           0x2224
+#define XEC_USBSSP_CHICKEN_BITS_3       0x2230
+#define XEC_USBSSP_CLK_GATING_CTRL      0x2234
+#define XECP_PM_PMCSR                   0x2240
+
+/* XEC_USBSSP_CLK_GATING_CTRL */
+#define HOST20_ACLK_GATING_DISABLE      BIT(4)
+#define HOST20_UTMI_GATING_DISABLE      BIT(5)
+
+/* XECP_PM_PMCSR */
+#define PS_MASK                         GENMASK(1, 0)
+#define PS_D0                           0
+#define PS_D3                           3
+#define PS_PME_En                       BIT(8)
+
+#define D_XEC_CFG_3XPORT_MODE_VALUE     0xa0031e07
+#define XEC_CFG_3XPORT_MODE_VALUE       0xa0031e07
+#define CFG_3XPORT_MODE_DIS_SSP         (~BIT(31))
+
+#define CFG_APB_TIMEOUT_PSLVERR_EN      BIT(22)
+#define CFG_APB_PSLVERR_EN              BIT(23)
+
+#define CIX_USB_CLK_NUM                 (4)
+#define CIX_USB_CLK_OFF_NUM             (2)
+#define CIX_USB_AXI_WR_CACHE_VALUE      0x33
+#define CIX_USB_CLK_32K                 32000
+#define CIX_USB_CLK_8M                  8000000
+
+#define AXI_CLOCK_VALID                 BIT(1)
+
+struct cdnsp_sky1 {
+	struct device *dev;
+	struct regmap *rcsu;
+	u32 rcsu_axi_off;
+	u32 rcsu_ctst_off;
+	void __iomem *dr_base;
+	void __iomem *xhci_base;
+	void __iomem *device_base;
+	struct platform_device *cdnsp_pdev;
+	struct reset_control *reset;
+	struct reset_control *preset;
+	struct clk *cix_usb_clks[CIX_USB_CLK_NUM];
+	int id;
+	struct regmap	*usb_syscon;
+	int lpm_clk_freq;
+	int sof_clk_freq;
+	bool u3_disable;
+	bool ssp_disable;
+	int axi_bmax_value;
+	struct gpio_desc *oc_gpio;
+	bool wakeup;
+};
+
+#endif /* _CDNSP_SKY1_H */
-- 
2.54.0



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

* [PATCH v4 4/4] arm64: dts: cix: Add USB4/USB5 nodes for Sky1
  2026-09-06  3:24 [PATCH v4 0/4] Add CIX Sky1 USBSSP controller support Hongliang Yang
                   ` (2 preceding siblings ...)
  2026-09-06  3:24 ` [PATCH v4 3/4] usb: cdns3: Add CIX Sky1 glue driver Hongliang Yang
@ 2026-09-06  3:24 ` Hongliang Yang
  2026-09-06  6:41   ` Krzysztof Kozlowski
  2026-09-09  7:52   ` Krzysztof Kozlowski
  3 siblings, 2 replies; 12+ messages in thread
From: Hongliang Yang @ 2026-09-06  3:24 UTC (permalink / raw)
  To: peter.chen, gregkh, robh, krzk+dt, conor+dt, krzk,
	linux-arm-kernel, linux-usb, devicetree, linux-kernel
  Cc: p.zabel, vkoul, neil.armstrong, pawell, rogerq

Add USB4 and USB5 controller nodes for the CIX Sky1 SoC. Enable USB4
and USB5 in host mode on the Radxa Orion O6 board.

The per-controller RCSU registers are accessed through a syscon regmap
referenced by the cix,usb-rcsu phandle.

The shared RCSU slice of the two controllers is described by a syscon
node; each controller references its registers through the cix,usb-rcsu
phandle with offsets.
Signed-off-by: Hongliang Yang <hongliang.yang@cixtech.com>
---
 arch/arm64/boot/dts/cix/sky1-orion-o6.dts | 42 +++++++++++
 arch/arm64/boot/dts/cix/sky1.dtsi         | 88 +++++++++++++++++++++++
 2 files changed, 130 insertions(+)

diff --git a/arch/arm64/boot/dts/cix/sky1-orion-o6.dts b/arch/arm64/boot/dts/cix/sky1-orion-o6.dts
index b152942aaa60..4f47e8cd70fc 100644
--- a/arch/arm64/boot/dts/cix/sky1-orion-o6.dts
+++ b/arch/arm64/boot/dts/cix/sky1-orion-o6.dts
@@ -80,6 +80,22 @@ pins {
 
 		};
 	};
+
+	pinctrl_usb4: usb4-power-on-cfg {
+		pins {
+			bias-pull-down;
+			drive-strength = <8>;
+			pinmux = <CIX_PAD_GPIO041_FUNC_USB_DRIVE_VBUS4>;
+		};
+	};
+
+	pinctrl_usb5: usb5-power-on-cfg {
+		pins {
+			bias-pull-down;
+			drive-strength = <8>;
+			pinmux = <CIX_PAD_GPIO042_FUNC_USB_DRIVE_VBUS5>;
+		};
+	};
 };
 
 &pcie_x8_rc {
@@ -118,6 +134,32 @@ &uart2 {
 	status = "okay";
 };
 
+&usb4 {
+	pinctrl-0 = <&pinctrl_usb4>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
+
+&usbss_4 {
+	dr_mode = "host";
+
+	status = "okay";
+};
+
+&usb5 {
+	pinctrl-0 = <&pinctrl_usb5>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
+
+&usbss_5 {
+	dr_mode = "host";
+
+	status = "okay";
+};
+
 &usb3_phy4 {
 	status = "okay";
 
diff --git a/arch/arm64/boot/dts/cix/sky1.dtsi b/arch/arm64/boot/dts/cix/sky1.dtsi
index 478c726fae96..2fe9e8244447 100644
--- a/arch/arm64/boot/dts/cix/sky1.dtsi
+++ b/arch/arm64/boot/dts/cix/sky1.dtsi
@@ -15,6 +15,11 @@ / {
 	#address-cells = <2>;
 	#size-cells = <2>;
 
+	aliases {
+		usb4 = &usb4;
+		usb5 = &usb5;
+	};
+
 	cpus {
 		#address-cells = <2>;
 		#size-cells = <0>;
@@ -576,6 +581,89 @@ mbox_ap2sfh: mailbox@80a0000 {
 			cix,mbox-dir = "tx";
 		};
 
+		usbss_rcsu45: syscon@91c0300 {
+			compatible = "cix,sky1-usbss-rcsu", "syscon";
+			reg = <0x00 0x091c0300 0x00 0x200>;
+		};
+
+		usb4: usb-4 {
+			compatible = "cix,sky1-usbssp";
+			ranges;
+			#address-cells = <2>;
+			clocks = <&scmi_clk CLK_TREE_USB3A_H0_CLK_SOF>,
+			         <&scmi_clk CLK_TREE_USB3A_0_AXI_GATE>,
+			         <&scmi_clk CLK_TREE_USB3A_H0_CLK_LPM>,
+			         <&scmi_clk CLK_TREE_USB3A_0_APB_GATE>;
+			clock-names = "sof", "axi", "lpm", "apb";
+			resets = <&s5_syscon SKY1_USBC_SS2_PRST_N>,
+			         <&s5_syscon SKY1_USBC_SS2_RST_N>;
+			reset-names = "apb", "core";
+			#size-cells = <2>;
+			cix,usb-rcsu = <&usbss_rcsu45 0x14 0x100>;
+			cix,usb-syscon = <&s5_syscon>;
+
+			status = "disabled";
+
+			usbss_4: usb@91d0000 {
+				compatible = "cdns,usb3";
+				reg = <0x00 0x91d0000 0x00 0x4000>,
+				      <0x00 0x91d8000 0x00 0x8000>,
+				      <0x00 0x91d4000 0x00 0x4000>;
+				reg-names = "otg", "xhci", "dev";
+				dr_mode = "otg";
+				interrupts = <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH 0>,
+				             <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH 0>,
+				             <GIC_SPI 253 IRQ_TYPE_LEVEL_HIGH 0>,
+				             <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH 0>;
+				interrupt-names = "host", "peripheral",
+				                  "otg", "wakeup";
+				maximum-speed = "super-speed-plus";
+				phys = <&usb3_phy4_0>;
+				phy-names = "cdns3,usb3-phy";
+
+				status = "disabled";
+			};
+		};
+
+		usb5: usb-5 {
+			compatible = "cix,sky1-usbssp";
+			ranges;
+			#address-cells = <2>;
+			clocks = <&scmi_clk CLK_TREE_USB3A_H1_CLK_SOF>,
+			         <&scmi_clk CLK_TREE_USB3A_1_AXI_GATE>,
+			         <&scmi_clk CLK_TREE_USB3A_H1_CLK_LPM>,
+			         <&scmi_clk CLK_TREE_USB3A_1_APB_GATE>;
+			clock-names = "sof", "axi", "lpm", "apb";
+			resets = <&s5_syscon SKY1_USBC_SS3_PRST_N>,
+			         <&s5_syscon SKY1_USBC_SS3_RST_N>;
+			reset-names = "apb", "core";
+			#size-cells = <2>;
+			cix,usb-rcsu = <&usbss_rcsu45 0x24 0x110>;
+			cix,usb-syscon = <&s5_syscon>;
+
+			status = "disabled";
+
+			usbss_5: usb@91e0000 {
+				compatible = "cdns,usb3";
+				reg = <0x00 0x91e0000 0x00 0x4000>,
+				      <0x00 0x91e8000 0x00 0x8000>,
+				      <0x00 0x91e4000 0x00 0x4000>;
+				reg-names = "otg", "xhci", "dev";
+				dr_mode = "otg";
+				interrupts = <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH 0>,
+				             <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH 0>,
+				             <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH 0>,
+				             <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH 0>;
+				interrupt-names = "host", "peripheral",
+				                  "otg", "wakeup";
+				maximum-speed = "super-speed-plus";
+				phys = <&usb3_phy4_1>;
+				phy-names = "cdns3,usb3-phy";
+
+				status = "disabled";
+			};
+		};
+
 		usb3_phy4: usb-phy@9210000 {
 			compatible = "cix,sky1-usb3-phy";
 			reg = <0x00 0x09210000 0x00 0x40000>;
-- 
2.54.0



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

* Re: [PATCH v4 4/4] arm64: dts: cix: Add USB4/USB5 nodes for Sky1
  2026-09-06  3:24 ` [PATCH v4 4/4] arm64: dts: cix: Add USB4/USB5 nodes for Sky1 Hongliang Yang
@ 2026-09-06  6:41   ` Krzysztof Kozlowski
  2026-09-09  7:52   ` Krzysztof Kozlowski
  1 sibling, 0 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2026-09-06  6:41 UTC (permalink / raw)
  To: Hongliang Yang, peter.chen, gregkh, robh, krzk+dt, conor+dt,
	linux-arm-kernel, linux-usb, devicetree, linux-kernel
  Cc: p.zabel, vkoul, neil.armstrong, pawell, rogerq

On 06/09/2026 05:24, Hongliang Yang wrote:
> Add USB4 and USB5 controller nodes for the CIX Sky1 SoC. Enable USB4
> and USB5 in host mode on the Radxa Orion O6 board.
> 
> The per-controller RCSU registers are accessed through a syscon regmap
> referenced by the cix,usb-rcsu phandle.
> 
> The shared RCSU slice of the two controllers is described by a syscon
> node; each controller references its registers through the cix,usb-rcsu
> phandle with offsets.
> Signed-off-by: Hongliang Yang <hongliang.yang@cixtech.com>


Odd style. Please read `git commit` help page to understand how to add
the tag properly.

> ---
>  arch/arm64/boot/dts/cix/sky1-orion-o6.dts | 42 +++++++++++
>  arch/arm64/boot/dts/cix/sky1.dtsi         | 88 +++++++++++++++++++++++
>  2 files changed, 130 insertions(+)

For the last time, read my v2 feedback

Which subsystems do you target here?

Which subsystems do you target in the previous patch?

Why are you combining them, even though I asked not?

Best regards,
Krzysztof


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

* Re: [PATCH v4 1/4] dt-bindings: usb: Add CIX Sky1 USBSSP RCSU system controller
  2026-09-06  3:24 ` [PATCH v4 1/4] dt-bindings: usb: Add CIX Sky1 USBSSP RCSU system controller Hongliang Yang
@ 2026-09-06  6:45   ` Krzysztof Kozlowski
  2026-09-07  8:15     ` Hongliang Yang
  0 siblings, 1 reply; 12+ messages in thread
From: Krzysztof Kozlowski @ 2026-09-06  6:45 UTC (permalink / raw)
  To: Hongliang Yang, peter.chen, gregkh, robh, krzk+dt, conor+dt,
	linux-arm-kernel, linux-usb, devicetree, linux-kernel
  Cc: p.zabel, vkoul, neil.armstrong, pawell, rogerq

On 06/09/2026 05:24, Hongliang Yang wrote:
> Add device tree binding for the per-controller RCSU register regions
> of the CIX Sky1 USBSSP controllers. The regions are exposed as syscon
> nodes; USBSSP glue nodes reference their per-controller registers
> through the cix,usb-rcsu phandle with register offsets.
> 
> The per-controller RCSU control and status registers live in a shared
> RCSU region described by the cix,sky1-usbss-rcsu binding and are
> referenced through the cix,usb-rcsu phandle.
> Signed-off-by: Hongliang Yang <hongliang.yang@cixtech.com>
> ---
>  .../bindings/usb/cix,sky1-usbss-rcsu.yaml     | 46 +++++++++++++++++++
>  MAINTAINERS                                   |  1 +
>  2 files changed, 47 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/usb/cix,sky1-usbss-rcsu.yaml
> 
> diff --git a/Documentation/devicetree/bindings/usb/cix,sky1-usbss-rcsu.yaml b/Documentation/devicetree/bindings/usb/cix,sky1-usbss-rcsu.yaml
> new file mode 100644
> index 000000000000..d0c54fd2cd5f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/usb/cix,sky1-usbss-rcsu.yaml
> @@ -0,0 +1,46 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/usb/cix,sky1-usbss-rcsu.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: CIX Sky1 USBSSP RCSU system controller
> +
> +maintainers:
> +  - Hongliang Yang <hongliang.yang@cixtech.com>
> +
> +description:
> +  The CIX Sky1 USBSSP controllers integrate their per-instance glue
> +  registers (AXI bus attribute configuration and controller status)
> +  inside a shared RCSU register region in the SoC system control
> +  aperture. This binding describes that region as a syscon, so USBSSP

In the description you describe hardware, not binding.

> +  glue nodes can reference their register offsets through the
> +  cix,usb-rcsu phandle (see cix,sky1-usbssp.yaml).

Syscon is not a USB device. This is not supposed to be in USB.


Best regards,
Krzysztof


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

* Re: [PATCH v4 2/4] dt-bindings: usb: Add CIX Sky1 USBSSP controller
  2026-09-06  3:24 ` [PATCH v4 2/4] dt-bindings: usb: Add CIX Sky1 USBSSP controller Hongliang Yang
@ 2026-09-06  6:55   ` Krzysztof Kozlowski
  2026-09-10  2:52     ` Hongliang Yang
  2026-09-09  7:51   ` Krzysztof Kozlowski
  1 sibling, 1 reply; 12+ messages in thread
From: Krzysztof Kozlowski @ 2026-09-06  6:55 UTC (permalink / raw)
  To: Hongliang Yang, peter.chen, gregkh, robh, krzk+dt, conor+dt,
	linux-arm-kernel, linux-usb, devicetree, linux-kernel
  Cc: p.zabel, vkoul, neil.armstrong, pawell, rogerq

On 06/09/2026 05:24, Hongliang Yang wrote:
> Add device tree binding for the CIX Sky1 Cadence USBSSP controller
> glue layer. The integration adds glue registers and mode strap
> controls in the Sky1 S5 system controller. The CIX glue node wraps
> a Cadence USBSSP core as a child node.
> 
> The per-controller RCSU control and status registers live in a shared
> RCSU region described by the cix,sky1-usbss-rcsu binding and are
> referenced through the cix,usb-rcsu phandle.
> 
> The per-controller RCSU registers are accessed through a syscon regmap
> referenced by the cix,usb-rcsu phandle.
> Signed-off-by: Hongliang Yang <hongliang.yang@cixtech.com>
> ---
>  .../bindings/usb/cix,sky1-usbssp.yaml         | 144 ++++++++++++++++++
>  MAINTAINERS                                   |   3 +
>  2 files changed, 147 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/usb/cix,sky1-usbssp.yaml
> 
> diff --git a/Documentation/devicetree/bindings/usb/cix,sky1-usbssp.yaml b/Documentation/devicetree/bindings/usb/cix,sky1-usbssp.yaml
> new file mode 100644
> index 000000000000..8e66dea50fa7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/usb/cix,sky1-usbssp.yaml
> @@ -0,0 +1,144 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/usb/cix,sky1-usbssp.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: CIX Sky1 Cadence USBSSP Controller
> +
> +maintainers:
> +  - Hongliang Yang <hongliang.yang@cixtech.com>
> +
> +description:
> +  The CIX Sky1 USBSSP controller is based on the Cadence USBSSP DRD
> +  controller. The integration adds glue registers and mode strap controls
> +  in the Sky1 S5 system controller. The CIX glue node wraps a Cadence
> +  USBSSP core as a child node. The per-controller RCSU control/status
> +  registers live in a shared RCSU region and are accessed through the
> +  cix,usb-rcsu phandle.
> +
> +properties:
> +  compatible:
> +    const: cix,sky1-usbssp
> +

No MMIO here?

> +  cix,usb-rcsu:

Then this is your device.

Last time you claimed you have TWO registers. ONLY. Now you claim you
have entire address space, but somewhere else.

If you do not have here MMIO, then this glue layer is not a separate
device node and you should have one node only, just like we did for DWC.
One node for glue layer and CDNS USB.

If you have here MMIO for some glue over IP block, then it is unlikely
to be a syscon.



> +    $ref: /schemas/types.yaml#/definitions/phandle-array
> +    description: |
> +      A phandle to the USBSSP RCSU system controller region (see
> +      cix,sky1-usbss-rcsu.yaml) followed by two cells: the offset of
> +      the AXI property configuration register and the offset of the
> +      controller status register, both relative to the RCSU region.
> +    items:
> +      items:
> +        - description: phandle to the USBSSP RCSU syscon node
> +        - description: offset of the AXI property configuration register
> +        - description: offset of the controller status register
> +
> +  clocks:
> +    items:
> +      - description: Start-of-frame clock
> +      - description: AXI bus clock
> +      - description: Low-power mode clock
> +      - description: APB register interface clock
> +
> +  clock-names:
> +    items:
> +      - const: sof
> +      - const: axi
> +      - const: lpm
> +      - const: apb
> +
> +  resets:
> +    items:
> +      - description: APB register reset
> +      - description: Controller reset
> +
> +  reset-names:
> +    items:
> +      - const: apb
> +      - const: core
> +
> +  cix,usb-syscon:
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description:
> +      Phandle to the Sky1 S5 system controller used to program USB mode
> +      strap controls.

One more syscon?

> +
> +  "#address-cells":
> +    const: 2
> +
> +  "#size-cells":
> +    const: 2
> +
> +  ranges: true
> +
> +patternProperties:
> +  "^usb@[0-9a-f]+$":
> +    $ref: cdns,usb3.yaml#
> +
> +required:
> +  - compatible
> +  - cix,usb-rcsu
> +  - clocks
> +  - clock-names
> +  - resets
> +  - reset-names
> +  - cix,usb-syscon
> +  - "#address-cells"
> +  - "#size-cells"
> +  - ranges
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/cix,sky1.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +    #include <dt-bindings/reset/cix,sky1-s5-system-control.h>
> +
> +    soc {
> +        #address-cells = <2>;
> +        #size-cells = <2>;
> +
> +        rcsu: syscon@91c0300 {
> +            compatible = "cix,sky1-usbss-rcsu", "syscon";
> +            reg = <0x00 0x091c0300 0x00 0x200>;
> +        };

Drop node irrelevant.


> +
> +        usb-4 {

This is just "usb". Not usb-foo.

> +            compatible = "cix,sky1-usbssp";
> +            ranges;
> +            #address-cells = <2>;
> +
> +            clocks = <&scmi_clk CLK_TREE_USB3A_H0_CLK_SOF>,
> +                     <&scmi_clk CLK_TREE_USB3A_0_AXI_GATE>,
> +                     <&scmi_clk CLK_TREE_USB3A_H0_CLK_LPM>,
> +                     <&scmi_clk CLK_TREE_USB3A_0_APB_GATE>;
> +            clock-names = "sof", "axi", "lpm", "apb";
> +            resets = <&src SKY1_USBC_SS2_PRST_N>,
> +                     <&src SKY1_USBC_SS2_RST_N>;
> +            reset-names = "apb", "core";
> +            #size-cells = <2>;

size-cells follows address-cells.


Best regards,
Krzysztof


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

* Re: [PATCH v4 1/4] dt-bindings: usb: Add CIX Sky1 USBSSP RCSU system controller
  2026-09-06  6:45   ` Krzysztof Kozlowski
@ 2026-09-07  8:15     ` Hongliang Yang
  0 siblings, 0 replies; 12+ messages in thread
From: Hongliang Yang @ 2026-09-07  8:15 UTC (permalink / raw)
  To: krzk
  Cc: peter.chen, pawell, rogerq, gregkh, robh, conor+dt, linux-usb,
	devicetree, linux-kernel, linux-arm-kernel, cix-kernel-upstream

On 06/09/2026 06:45, Krzysztof Kozlowski wrote:
> In the description you describe hardware, not binding.
>
>> +  glue nodes can reference their register offsets through the
>> +  cix,usb-rcsu phandle (see cix,sky1-usbssp.yaml).
>
> Syscon is not a USB device. This is not supposed to be in USB.

Understood. We will drop the syscon node and this binding entirely.

To explain the hardware first, so that we agree on the target shape:

USB4 (controller 0) and USB5 (controller 1) do not have their own glue
register bank inside the controller address space. Their glue registers
live in a shared RCSU register region in the SoC system control
aperture (0x091c0000 ~ 0x091c0440). Within that region each controller
owns its own registers and the two sets do not overlap:

  - USB4: AXI bus attribute configuration register at 0x091c0314 and
    controller status registers (clock enable/valid/req flags) at
    0x091c0400 ~ 0x091c040c
  - USB5: AXI bus attribute configuration register at 0x091c0324 and
    controller status registers at 0x091c0410 ~ 0x091c041c

Only the USB controllers use these registers. The remaining USB
controllers (USB0 ~ USB3) each have their own private RCSU slice
elsewhere in the same aperture, one slice per controller.

Following your feedback on the wrapper node ("If you do not have here
MMIO, then this glue layer is not a separate device node and you should
have one node only, just like we did for DWC"), our plan for v5 is to
drop the separate glue node and merge everything into a single node,
in the same shape as socionext,uniphier-dwc3:

    usb@91d0000 {
        compatible = "cix,sky1-usbssp", "cdns,usb3";
        reg = <0x00 0x91d0000 0x00 0x4000>,   /* otg */
              <0x00 0x91d8000 0x00 0x8000>,   /* xhci */
              <0x00 0x91d4000 0x00 0x4000>,   /* dev */
              <0x00 0x091c0314 0x00 0x10>,    /* axi attribute cfg */
              <0x00 0x091c0400 0x00 0x10>;    /* controller status */
        reg-names = "otg", "xhci", "dev", "axi", "status";
        /* clocks, resets, interrupts, phys, dr_mode, cix,usb-syscon */
    };

The cix,sky1-usbssp binding would then $ref cdns,usb3.yaml and add the
two extra reg entries plus the Sky1 glue properties (clocks, resets and
the cix,usb-syscon phandle to the S5 system controller for mode
straps, which also provides the resets). No syscon node, no wrapper
node, no child node.

On the driver side the Sky1 glue driver would follow the same approach
as the DWC3 glue drivers (e.g. dwc3-generic-plat / dwc3-imx8mp): the
glue driver binds the single node and initializes the Cadence core
in-process instead of populating a child device, with the core probe
split into an exported helper as done for DWC3.

Does this match what you had in mind, or would you prefer a different
split of the reg entries / naming?

Best regards,
Hongliang Yang


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

* Re: [PATCH v4 2/4] dt-bindings: usb: Add CIX Sky1 USBSSP controller
  2026-09-06  3:24 ` [PATCH v4 2/4] dt-bindings: usb: Add CIX Sky1 USBSSP controller Hongliang Yang
  2026-09-06  6:55   ` Krzysztof Kozlowski
@ 2026-09-09  7:51   ` Krzysztof Kozlowski
  1 sibling, 0 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2026-09-09  7:51 UTC (permalink / raw)
  To: Hongliang Yang
  Cc: peter.chen, gregkh, robh, krzk+dt, conor+dt, linux-arm-kernel,
	linux-usb, devicetree, linux-kernel, p.zabel, vkoul,
	neil.armstrong, pawell, rogerq

On Sun, Sep 06, 2026 at 11:24:38AM +0800, Hongliang Yang wrote:
> Add device tree binding for the CIX Sky1 Cadence USBSSP controller
> glue layer. The integration adds glue registers and mode strap
> controls in the Sky1 S5 system controller. The CIX glue node wraps
> a Cadence USBSSP core as a child node.
> 
> The per-controller RCSU control and status registers live in a shared
> RCSU region described by the cix,sky1-usbss-rcsu binding and are
> referenced through the cix,usb-rcsu phandle.
> 
> The per-controller RCSU registers are accessed through a syscon regmap
> referenced by the cix,usb-rcsu phandle.
> Signed-off-by: Hongliang Yang <hongliang.yang@cixtech.com>

One more note:

Please use git to write commit msgs and then actually commit.

Missing blank line before tag. This is triviality, but why you can't
just use tools which solve such trivialities and no one ever has to care
about noticing them?

Best regards,
Krzysztof



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

* Re: [PATCH v4 4/4] arm64: dts: cix: Add USB4/USB5 nodes for Sky1
  2026-09-06  3:24 ` [PATCH v4 4/4] arm64: dts: cix: Add USB4/USB5 nodes for Sky1 Hongliang Yang
  2026-09-06  6:41   ` Krzysztof Kozlowski
@ 2026-09-09  7:52   ` Krzysztof Kozlowski
  1 sibling, 0 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2026-09-09  7:52 UTC (permalink / raw)
  To: Hongliang Yang
  Cc: peter.chen, gregkh, robh, krzk+dt, conor+dt, linux-arm-kernel,
	linux-usb, devicetree, linux-kernel, p.zabel, vkoul,
	neil.armstrong, pawell, rogerq

On Sun, Sep 06, 2026 at 11:24:40AM +0800, Hongliang Yang wrote:
> Add USB4 and USB5 controller nodes for the CIX Sky1 SoC. Enable USB4
> and USB5 in host mode on the Radxa Orion O6 board.
> 
> The per-controller RCSU registers are accessed through a syscon regmap
> referenced by the cix,usb-rcsu phandle.
> 
> The shared RCSU slice of the two controllers is described by a syscon
> node; each controller references its registers through the cix,usb-rcsu
> phandle with offsets.
> Signed-off-by: Hongliang Yang <hongliang.yang@cixtech.com>

So all your patches here have manually-created wrong style...

Best regards,
Krzysztof



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

* Re: [PATCH v4 2/4] dt-bindings: usb: Add CIX Sky1 USBSSP controller
  2026-09-06  6:55   ` Krzysztof Kozlowski
@ 2026-09-10  2:52     ` Hongliang Yang
  0 siblings, 0 replies; 12+ messages in thread
From: Hongliang Yang @ 2026-09-10  2:52 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Hongliang Yang, peter.chen, gregkh, robh, krzk+dt, conor+dt,
	linux-arm-kernel, linux-usb, devicetree, linux-kernel, p.zabel,
	vkoul, neil.armstrong, pawell, rogerq, cix-kernel-upstream

Hi Krzysztof,

Thanks for the review.

On 06/09/2026 08:55, Krzysztof Kozlowski wrote:
> No MMIO here?
>
> Then this is your device.
>
> Last time you claimed you have TWO registers. ONLY. Now you claim you
> have entire address space, but somewhere else.
>
> If you do not have here MMIO, then this glue layer is not a separate
> device node and you should have one node only, just like we did for
> DWC. One node for glue layer and CDNS USB.
>
> If you have here MMIO for some glue over IP block, then it is unlikely
> to be a syscon.

The glue layer does have its own MMIO: each controller has a small set
of RCSU registers (an AXI attribute configuration register and a
controller status register), so I dropped the syscon node, the
cix,usb-rcsu phandle and the separate cix,sky1-usbss-rcsu binding
entirely. The glue registers are now mapped through the reg property of
the glue node itself.

One complication is that the two controllers (usb4 and usb5) share a
single RCSU register region and their registers are interleaved inside
it, so neither controller owns a contiguous slice:

    0x091c0300 + 0x14 : usb4 AXI attribute configuration
    0x091c0300 + 0x24 : usb5 AXI attribute configuration
    0x091c0300 + 0x100: usb4 controller status
    0x091c0300 + 0x110: usb5 controller status

To express this in DT I made the shared RCSU region a simple-bus
container node with an address-translating ranges, and moved both glue
nodes under it. The glue nodes then describe their registers as offsets
inside the RCSU window:

    usb-rcsu@91c0300 {
        compatible = "simple-bus";
        #address-cells = <2>;
        #size-cells = <2>;
        ranges = <0x00 0x091c0300 0x00 0x091c0300 0x00 0x150>;

        usb@14 {
            compatible = "cix,sky1-usbssp";
            reg = <0x00 0x14 0x00 0x10>,
                  <0x00 0x100 0x00 0x10>;
            reg-names = "axi", "status";
            ...
        };

        usb@24 {
            ...
        };
    };

The Cadence core stays a child of each glue node with an empty ranges,
so its addresses are unchanged. The driver maps the two glue registers
by name via devm_platform_ioremap_resource_byname(), so no driver
changes are needed.

Would you be fine with such representation of the shared RCSU region?
The alternative would be to keep the glue nodes directly under the soc
node with absolute addresses in reg:

    usb@91c0314 {
        compatible = "cix,sky1-usbssp";
        reg = <0x00 0x091c0314 0x00 0x10>,
              <0x00 0x091c0400 0x00 0x10>;
        ...
    };

Both work with the current driver; I slightly prefer the ranges variant
because it documents the shared region and constrains the glue
registers to the RCSU window, but I am happy to go either way,
whatever you consider more appropriate.

> One more syscon?
>
> ...
>     cix,usb-syscon:
>
> One more syscon?

The cix,usb-syscon phandle points to the Sky1 S5 system controller,
which holds the USB mode strap controls shared with other USB
instances of the SoC (it is a genuine system controller, not a
register block created for this driver). I will clarify that in the
binding description.

Best regards,
Hongliang Yang


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

end of thread, other threads:[~2026-09-10  2:53 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-06  3:24 [PATCH v4 0/4] Add CIX Sky1 USBSSP controller support Hongliang Yang
2026-09-06  3:24 ` [PATCH v4 1/4] dt-bindings: usb: Add CIX Sky1 USBSSP RCSU system controller Hongliang Yang
2026-09-06  6:45   ` Krzysztof Kozlowski
2026-09-07  8:15     ` Hongliang Yang
2026-09-06  3:24 ` [PATCH v4 2/4] dt-bindings: usb: Add CIX Sky1 USBSSP controller Hongliang Yang
2026-09-06  6:55   ` Krzysztof Kozlowski
2026-09-10  2:52     ` Hongliang Yang
2026-09-09  7:51   ` Krzysztof Kozlowski
2026-09-06  3:24 ` [PATCH v4 3/4] usb: cdns3: Add CIX Sky1 glue driver Hongliang Yang
2026-09-06  3:24 ` [PATCH v4 4/4] arm64: dts: cix: Add USB4/USB5 nodes for Sky1 Hongliang Yang
2026-09-06  6:41   ` Krzysztof Kozlowski
2026-09-09  7:52   ` Krzysztof Kozlowski

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