linux-riscv.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/4] Add USB2.0 PHY and USB3.0 PHY support for SpacemiT K1
@ 2025-05-27 12:01 Ze Huang
  2025-05-27 12:01 ` [PATCH v5 1/4] dt-bindings: phy: spacemit: add K1 USB2 PHY Ze Huang
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Ze Huang @ 2025-05-27 12:01 UTC (permalink / raw)
  To: Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Philipp Zabel
  Cc: linux-phy, devicetree, linux-riscv, spacemit, linux-kernel,
	Ze Huang, Junzhong Pan, Neil Armstrong

This patch series introduces support for the USB2.0 PHY and PCIe/USB3.0
Combo PHY on the SpacemiT K1 SoC. The implementation has been tested on the
Milk-V Jupiter and BananaPi-f3.

K1 includes three USB ports as follows[1]:
- A USB2.0 OTG Port
- A USB2.0 Host Only Port
- A USB3.0 Port with a USB2.0 DRD interface

USB3.0 PHY for USB3.0 Port is shared with PCIe port A, meaning that only one of
these interfaces (PCIe or USB3.0) can be active at a given time.

Link: https://developer.spacemit.com/documentation?token=AjHDwrW78igAAEkiHracBI9HnTb#part5 [1]

Signed-off-by: Ze Huang <huangze@whut.edu.cn>
---
Changes in v5:
- phy driver for usb2:
  - convert readl/writel to regmap
  - fix typo: sentinal -> sentinel
- Link to v4: https://lore.kernel.org/r/20250526-b4-k1-usb3-phy-v2-v4-0-eca668fc16a2@whut.edu.cn

Changes in v4:
- combphy driver:
  - add in-code comments to indicate that PCIe mode is not yet supported.
  - replace custom spacemit_reg_update() with standard regmap API.
  - drop spacemit_combphy_wait_ready helper function as only used once.
  - Fix PHY init timeout handling: ensure proper error reporting when PLL
    lock fails during USB3 PHY initialization
- Link to v3: https://lore.kernel.org/r/20250517-b4-k1-usb3-phy-v2-v3-0-e0655613a163@whut.edu.cn

Changes in v3:
- improve commit message, provide more info about phy hardware
- drop superfluous local variable in `spacemit_combphy_wait_ready`
- replace devm_reset_control_get with devm_reset_control_get_exclusive
- Link to v2: https://lore.kernel.org/r/20250418-b4-k1-usb3-phy-v2-v2-0-b69e02da84eb@whut.edu.cn

Changes in v2:
- combphy dt-bindings:
  - fix reg-names
  - describe reg
  - describe #phy-cells argument
- drop stale ".owner" in driver struct
- add support for usb lfps_thres in combphy
- fix Kconfig depends on
- Link to v1: https://lore.kernel.org/all/20250407-b4-k1-usb3-v3-2-v1-0-bf0bcc41c9ba@whut.edu.cn

---
Ze Huang (4):
      dt-bindings: phy: spacemit: add K1 USB2 PHY
      dt-bindings: phy: spacemit: add K1 PCIe/USB3 combo PHY
      phy: spacemit: support K1 USB2.0 PHY controller
      phy: spacemit: add USB3 support for K1 PCIe/USB3 combo PHY

 .../bindings/phy/spacemit,k1-combphy.yaml          |  72 ++++++
 .../devicetree/bindings/phy/spacemit,usb2-phy.yaml |  40 ++++
 drivers/phy/Kconfig                                |   1 +
 drivers/phy/Makefile                               |   1 +
 drivers/phy/spacemit/Kconfig                       |  21 ++
 drivers/phy/spacemit/Makefile                      |   3 +
 drivers/phy/spacemit/phy-k1-combphy.c              | 266 +++++++++++++++++++++
 drivers/phy/spacemit/phy-k1-usb2.c                 | 144 +++++++++++
 8 files changed, 548 insertions(+)
---
base-commit: 64e9fdfc89a76fed38d8ddeed72d42ec71957ed9
change-id: 20250417-b4-k1-usb3-phy-v2-fb1e41849049

Best regards,
-- 
Ze Huang <huangze@whut.edu.cn>


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* [PATCH v5 1/4] dt-bindings: phy: spacemit: add K1 USB2 PHY
  2025-05-27 12:01 [PATCH v5 0/4] Add USB2.0 PHY and USB3.0 PHY support for SpacemiT K1 Ze Huang
@ 2025-05-27 12:01 ` Ze Huang
  2025-05-27 12:01 ` [PATCH v5 2/4] dt-bindings: phy: spacemit: add K1 PCIe/USB3 combo PHY Ze Huang
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Ze Huang @ 2025-05-27 12:01 UTC (permalink / raw)
  To: Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Philipp Zabel
  Cc: linux-phy, devicetree, linux-riscv, spacemit, linux-kernel,
	Ze Huang

Add support for USB2 PHY found on SpacemiT K1 SoC.

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Ze Huang <huangze@whut.edu.cn>
---
 .../devicetree/bindings/phy/spacemit,usb2-phy.yaml | 40 ++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/Documentation/devicetree/bindings/phy/spacemit,usb2-phy.yaml b/Documentation/devicetree/bindings/phy/spacemit,usb2-phy.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..8a91b730cb8733ddf29f1b94fc31e6ba920dbc1b
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/spacemit,usb2-phy.yaml
@@ -0,0 +1,40 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/spacemit,usb2-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: SpacemiT K1 SoC USB 2.0 PHY
+
+maintainers:
+  - Ze Huang <huangze9015@gmail.com>
+
+properties:
+  compatible:
+    const: spacemit,k1-usb2-phy
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  "#phy-cells":
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - "#phy-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    usb-phy@c09c0000 {
+        compatible = "spacemit,k1-usb2-phy";
+        reg = <0xc09c0000 0x200>;
+        clocks = <&syscon_apmu 15>;
+        #phy-cells = <0>;
+    };

-- 
2.49.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* [PATCH v5 2/4] dt-bindings: phy: spacemit: add K1 PCIe/USB3 combo PHY
  2025-05-27 12:01 [PATCH v5 0/4] Add USB2.0 PHY and USB3.0 PHY support for SpacemiT K1 Ze Huang
  2025-05-27 12:01 ` [PATCH v5 1/4] dt-bindings: phy: spacemit: add K1 USB2 PHY Ze Huang
@ 2025-05-27 12:01 ` Ze Huang
  2025-06-10 19:57   ` Alex Elder
  2025-05-27 12:01 ` [PATCH v5 3/4] phy: spacemit: support K1 USB2.0 PHY controller Ze Huang
  2025-05-27 12:01 ` [PATCH v5 4/4] phy: spacemit: add USB3 support for K1 PCIe/USB3 combo PHY Ze Huang
  3 siblings, 1 reply; 10+ messages in thread
From: Ze Huang @ 2025-05-27 12:01 UTC (permalink / raw)
  To: Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Philipp Zabel
  Cc: linux-phy, devicetree, linux-riscv, spacemit, linux-kernel,
	Ze Huang, Junzhong Pan

Introduce support for SpacemiT K1 PCIe/USB3 combo PHY controller.

PCIe portA and USB3 controller share this phy, only one of them can work
at any given application scenario.

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Co-developed-by: Junzhong Pan <junzhong.pan@spacemit.com>
Signed-off-by: Junzhong Pan <junzhong.pan@spacemit.com>
Signed-off-by: Ze Huang <huangze@whut.edu.cn>
---
 .../bindings/phy/spacemit,k1-combphy.yaml          | 72 ++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/Documentation/devicetree/bindings/phy/spacemit,k1-combphy.yaml b/Documentation/devicetree/bindings/phy/spacemit,k1-combphy.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..93f7a3bb06bba380def77f87f6db0184af26e9e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/spacemit,k1-combphy.yaml
@@ -0,0 +1,72 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/spacemit,k1-combphy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: SpacemiT K1 PCIe/USB3 Combo PHY
+
+maintainers:
+  - Ze Huang <huangze9015@gmail.com>
+
+description:
+  Combo PHY on SpacemiT K1 SoC. PCIe port A and USB3 controller share this
+  phy, only one of PCIe port A and USB3 port can work at any given application
+  scenario.
+
+properties:
+  compatible:
+    const: spacemit,k1-combphy
+
+  reg:
+    items:
+      - description: PHY control registers
+      - description: PCIe/USB3 mode selection register
+
+  reg-names:
+    items:
+      - const: ctrl
+      - const: sel
+
+  resets:
+    maxItems: 1
+
+  "#phy-cells":
+    const: 1
+    description:
+      Indicates the PHY mode to select. The value determines whether the PHY
+      operates in PCIe or USB3 mode.
+
+  spacemit,lfps-threshold:
+    description:
+      Controls the LFPS signal detection threshold, affects polling.LFPS
+      handshake. Lower the threshold when core voltage rises.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0
+    maximum: 0xff
+
+  spacemit,rx-always-on:
+    description:
+      Affects RX.detect, enhance compatibility of some DFPs in device mode but
+      increase power consumption.
+    type: boolean
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - resets
+  - "#phy-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    phy@c0b10000 {
+        compatible = "spacemit,k1-combphy";
+        reg = <0xc0b10000 0x800>,
+              <0xd4282910 0x400>;
+        reg-names = "ctrl", "sel";
+        resets = <&syscon_apmu 19>;
+        #phy-cells = <1>;
+    };

-- 
2.49.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* [PATCH v5 3/4] phy: spacemit: support K1 USB2.0 PHY controller
  2025-05-27 12:01 [PATCH v5 0/4] Add USB2.0 PHY and USB3.0 PHY support for SpacemiT K1 Ze Huang
  2025-05-27 12:01 ` [PATCH v5 1/4] dt-bindings: phy: spacemit: add K1 USB2 PHY Ze Huang
  2025-05-27 12:01 ` [PATCH v5 2/4] dt-bindings: phy: spacemit: add K1 PCIe/USB3 combo PHY Ze Huang
@ 2025-05-27 12:01 ` Ze Huang
  2025-06-03  7:37   ` neil.armstrong
  2025-06-05 12:58   ` Yixun Lan
  2025-05-27 12:01 ` [PATCH v5 4/4] phy: spacemit: add USB3 support for K1 PCIe/USB3 combo PHY Ze Huang
  3 siblings, 2 replies; 10+ messages in thread
From: Ze Huang @ 2025-05-27 12:01 UTC (permalink / raw)
  To: Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Philipp Zabel
  Cc: linux-phy, devicetree, linux-riscv, spacemit, linux-kernel,
	Ze Huang

The SpacemiT K1 SoC includes three USB ports:

- One USB2.0 OTG port
- One USB2.0 host-only port
- One USB3.0 port with an integrated USB2.0 DRD interface

Each of these ports is connected to a USB2.0 PHY responsible for USB2
transmission.

This commit adds support for the SpacemiT K1 USB2.0 PHY, which is
compliant with the USB 2.0 specification and supports both 8-bit 60MHz
and 16-bit 30MHz parallel interfaces.

Signed-off-by: Ze Huang <huangze@whut.edu.cn>
---
 drivers/phy/Kconfig                |   1 +
 drivers/phy/Makefile               |   1 +
 drivers/phy/spacemit/Kconfig       |  13 ++++
 drivers/phy/spacemit/Makefile      |   2 +
 drivers/phy/spacemit/phy-k1-usb2.c | 144 +++++++++++++++++++++++++++++++++++++
 5 files changed, 161 insertions(+)

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 8d58efe998ec5fd50054eed2c90d6ecce6bd5dd8..fca589aa7926eb5bce14e99785cf32cf0395202e 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -114,6 +114,7 @@ source "drivers/phy/renesas/Kconfig"
 source "drivers/phy/rockchip/Kconfig"
 source "drivers/phy/samsung/Kconfig"
 source "drivers/phy/socionext/Kconfig"
+source "drivers/phy/spacemit/Kconfig"
 source "drivers/phy/st/Kconfig"
 source "drivers/phy/starfive/Kconfig"
 source "drivers/phy/sunplus/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index e281442acc752820fe0bd638dfe38986a37c2a78..05993ff8a15daf7e2583b5f9b9b37ac584a30609 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -34,6 +34,7 @@ obj-y					+= allwinner/	\
 					   rockchip/	\
 					   samsung/	\
 					   socionext/	\
+					   spacemit/	\
 					   st/		\
 					   starfive/	\
 					   sunplus/	\
diff --git a/drivers/phy/spacemit/Kconfig b/drivers/phy/spacemit/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..0136aee2e8a2f5f484da136b26f80130794b992c
--- /dev/null
+++ b/drivers/phy/spacemit/Kconfig
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Phy drivers for SpacemiT platforms
+#
+config PHY_SPACEMIT_K1_USB2
+	tristate "SpacemiT K1 USB 2.0 PHY support"
+	depends on (ARCH_SPACEMIT || COMPILE_TEST) && OF
+	depends on COMMON_CLK
+	depends on USB_COMMON
+	select GENERIC_PHY
+	help
+	  Enable this to support K1 USB 2.0 PHY driver. This driver takes care of
+	  enabling and clock setup and will be used by K1 udc/ehci/otg/xhci driver.
diff --git a/drivers/phy/spacemit/Makefile b/drivers/phy/spacemit/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..fec0b425a948541b39b814caef0b05e1e002d92f
--- /dev/null
+++ b/drivers/phy/spacemit/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_PHY_SPACEMIT_K1_USB2)		+= phy-k1-usb2.o
diff --git a/drivers/phy/spacemit/phy-k1-usb2.c b/drivers/phy/spacemit/phy-k1-usb2.c
new file mode 100644
index 0000000000000000000000000000000000000000..ee64af07478ea02b421473e6f73fd37a3a135e7d
--- /dev/null
+++ b/drivers/phy/spacemit/phy-k1-usb2.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SpacemiT K1 USB 2.0 PHY driver
+ *
+ * Copyright (C) 2025 SpacemiT (Hangzhou) Technology Co. Ltd
+ * Copyright (C) 2025 Ze Huang <huangze9015@gmail.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/usb/of.h>
+
+#define USB2_PHY_REG01			0x04
+#define  USB2_PHY_REG01_VAL		0x60ef
+#define  USB2_PHY_REG01_PLL_IS_READY	BIT(0)
+#define USB2_PHY_REG04			0x10
+#define  USB2_PHY_REG04_AUTO_CLEAR_DIS	BIT(2)
+#define USB2_PHY_REG0D			0x34
+#define  USB2_PHY_REG0D_VAL		0x1c
+#define USB2_PHY_REG26			0x98
+#define  USB2_PHY_REG26_VAL		0xbec4
+
+#define USB2D_CTRL_RESET_TIME_MS	50
+
+struct spacemit_usb2phy {
+	struct phy	*phy;
+	struct clk	*clk;
+	struct regmap	*regmap_base;
+};
+
+static const struct regmap_config phy_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = 0x200,
+};
+
+static int spacemit_usb2phy_init(struct phy *phy)
+{
+	struct spacemit_usb2phy *sphy = phy_get_drvdata(phy);
+	struct regmap *map = sphy->regmap_base;
+	u32 val;
+	int ret;
+
+	ret = clk_prepare_enable(sphy->clk);
+	if (ret) {
+		dev_err(&phy->dev, "failed to enable clock\n");
+		return ret;
+	}
+
+	/*
+	 * make sure the usb controller is not under reset process before
+	 * any configuration
+	 */
+	usleep_range(150, 200);
+	regmap_write(map, USB2_PHY_REG26, USB2_PHY_REG26_VAL); /* 24M ref clk */
+
+	ret = regmap_read_poll_timeout(map, USB2_PHY_REG01, val,
+				       (val & USB2_PHY_REG01_PLL_IS_READY),
+				       500, USB2D_CTRL_RESET_TIME_MS * 1000);
+	if (ret) {
+		dev_err(&phy->dev, "wait PHY_REG01[PLLREADY] timeout\n");
+		return ret;
+	}
+
+	/* release usb2 phy internal reset and enable clock gating */
+	regmap_write(map, USB2_PHY_REG01, USB2_PHY_REG01_VAL);
+	regmap_write(map, USB2_PHY_REG0D, USB2_PHY_REG0D_VAL);
+
+	/* auto clear host disc */
+	regmap_update_bits(map, USB2_PHY_REG04, USB2_PHY_REG04_AUTO_CLEAR_DIS,
+			   USB2_PHY_REG04_AUTO_CLEAR_DIS);
+
+	return 0;
+}
+
+static int spacemit_usb2phy_exit(struct phy *phy)
+{
+	struct spacemit_usb2phy *sphy = phy_get_drvdata(phy);
+
+	clk_disable_unprepare(sphy->clk);
+
+	return 0;
+}
+
+static const struct phy_ops spacemit_usb2phy_ops = {
+	.init = spacemit_usb2phy_init,
+	.exit = spacemit_usb2phy_exit,
+	.owner = THIS_MODULE,
+};
+
+static int spacemit_usb2phy_probe(struct platform_device *pdev)
+{
+	struct phy_provider *phy_provider;
+	struct device *dev = &pdev->dev;
+	struct spacemit_usb2phy *sphy;
+	void __iomem *base;
+
+	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
+	if (!sphy)
+		return -ENOMEM;
+
+	sphy->clk = devm_clk_get_prepared(&pdev->dev, NULL);
+	if (IS_ERR(sphy->clk))
+		return dev_err_probe(dev, PTR_ERR(sphy->clk), "Failed to get clock\n");
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	sphy->regmap_base = devm_regmap_init_mmio(dev, base, &phy_regmap_config);
+	if (IS_ERR(sphy->regmap_base))
+		return dev_err_probe(dev, PTR_ERR(sphy->regmap_base),
+				     "Failed to init regmap\n");
+
+	sphy->phy = devm_phy_create(dev, NULL, &spacemit_usb2phy_ops);
+	if (IS_ERR(sphy->phy))
+		return dev_err_probe(dev, PTR_ERR(sphy->phy), "Failed to create phy\n");
+
+	phy_set_drvdata(sphy->phy, sphy);
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id spacemit_usb2phy_dt_match[] = {
+	{ .compatible = "spacemit,k1-usb2-phy", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, spacemit_usb2phy_dt_match);
+
+static struct platform_driver spacemit_usb2_phy_driver = {
+	.probe	= spacemit_usb2phy_probe,
+	.driver = {
+		.name   = "spacemit-usb2-phy",
+		.of_match_table = spacemit_usb2phy_dt_match,
+	},
+};
+module_platform_driver(spacemit_usb2_phy_driver);
+
+MODULE_DESCRIPTION("Spacemit USB 2.0 PHY driver");
+MODULE_LICENSE("GPL");

-- 
2.49.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* [PATCH v5 4/4] phy: spacemit: add USB3 support for K1 PCIe/USB3 combo PHY
  2025-05-27 12:01 [PATCH v5 0/4] Add USB2.0 PHY and USB3.0 PHY support for SpacemiT K1 Ze Huang
                   ` (2 preceding siblings ...)
  2025-05-27 12:01 ` [PATCH v5 3/4] phy: spacemit: support K1 USB2.0 PHY controller Ze Huang
@ 2025-05-27 12:01 ` Ze Huang
  3 siblings, 0 replies; 10+ messages in thread
From: Ze Huang @ 2025-05-27 12:01 UTC (permalink / raw)
  To: Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Philipp Zabel
  Cc: linux-phy, devicetree, linux-riscv, spacemit, linux-kernel,
	Ze Huang, Neil Armstrong

Add support for USB 3.0 mode on the K1 PCIe/USB3 combo PHY which
implements PIPE3(125MHz) interface for USB3.0. Currently, only USB mode
is supported; PCIe support is not included in this change.

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Ze Huang <huangze@whut.edu.cn>
---
 drivers/phy/spacemit/Kconfig          |   8 +
 drivers/phy/spacemit/Makefile         |   1 +
 drivers/phy/spacemit/phy-k1-combphy.c | 266 ++++++++++++++++++++++++++++++++++
 3 files changed, 275 insertions(+)

diff --git a/drivers/phy/spacemit/Kconfig b/drivers/phy/spacemit/Kconfig
index 0136aee2e8a2f5f484da136b26f80130794b992c..ccc6bf9ea49f4988a27f79a4dcd024b18cbd78b0 100644
--- a/drivers/phy/spacemit/Kconfig
+++ b/drivers/phy/spacemit/Kconfig
@@ -11,3 +11,11 @@ config PHY_SPACEMIT_K1_USB2
 	help
 	  Enable this to support K1 USB 2.0 PHY driver. This driver takes care of
 	  enabling and clock setup and will be used by K1 udc/ehci/otg/xhci driver.
+
+config PHY_SPACEMIT_K1_COMBPHY
+	tristate "SpacemiT K1 PCIe/USB3 combo PHY support"
+	depends on (ARCH_SPACEMIT || COMPILE_TEST) && OF
+	depends on COMMON_CLK
+	select GENERIC_PHY
+	help
+	  USB3/PCIe Combo PHY Support for SpacemiT K1 SoC
diff --git a/drivers/phy/spacemit/Makefile b/drivers/phy/spacemit/Makefile
index fec0b425a948541b39b814caef0b05e1e002d92f..1fd0c65f2c5cd10ea2f70e43e62c70588d1ffae9 100644
--- a/drivers/phy/spacemit/Makefile
+++ b/drivers/phy/spacemit/Makefile
@@ -1,2 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_PHY_SPACEMIT_K1_COMBPHY)	+= phy-k1-combphy.o
 obj-$(CONFIG_PHY_SPACEMIT_K1_USB2)		+= phy-k1-usb2.o
diff --git a/drivers/phy/spacemit/phy-k1-combphy.c b/drivers/phy/spacemit/phy-k1-combphy.c
new file mode 100644
index 0000000000000000000000000000000000000000..227b1c743f4d981b3d4555c871ef397c1c8df0b5
--- /dev/null
+++ b/drivers/phy/spacemit/phy-k1-combphy.c
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SpacemiT K1 PCIE/USB3 PHY driver
+ *
+ * This driver supports the combo PHY found on Spacemit K1 SoC, which integrates
+ * a dual-mode USB3/PCIe PHY shared between the USB3.0 DRD controller and PCIe
+ * PortA. But only one mode can work at any given application scenario.
+ *
+ * PCIe mode is not supported yet and any attempt to use the PHY in PCIe mode
+ * will result in an error.
+ *
+ * Copyright (C) 2025 SpacemiT (Hangzhou) Technology Co. Ltd
+ * Copyright (C) 2025 Ze Huang <huangze9015@gmail.com>
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/usb/of.h>
+
+#define COMBPHY_USB_REG1		0x68
+#define  COMBPHY_USB_REG1_VAL		0x00
+#define COMBPHY_USB_REG2		0x48
+#define  COMBPHY_USB_REG2_VAL		0x603a2276
+#define COMBPHY_USB_REG3		0x08
+#define  COMBPHY_USB_REG3_VAL		0x97c
+#define COMBPHY_USB_REG4		0x18
+#define  COMBPHY_USB_REG4_VAL		0x00
+#define  COMBPHY_USB_TERM_SHORT_MASK	0x3000
+#define  COMBPHY_USB_TERM_SHORT_VAL	0x3000
+#define COMBPHY_USB_PLL_REG		0x08
+#define  COMBPHY_USB_PLL_MASK		0x01
+#define  COMBPHY_USB_PLL_VAL		0x01
+#define COMBPHY_USB_LFPS_REG		0x58
+#define  COMBPHY_USB_LFPS_MASK		0x700
+#define  COMBPHY_USB_LFPS_THRES_DEFAULT	0x03
+
+#define COMBPHY_MODE_SEL_MASK	BIT(3)
+#define COMBPHY_MODE_USB	BIT(3)
+#define COMBPHY_WAIT_TIMEOUT	1000
+
+struct spacemit_combphy_priv {
+	struct device *dev;
+	struct phy *phy;
+	struct reset_control *phy_rst;
+	struct regmap *regmap_ctrl;
+	struct regmap *regmap_sel;
+	bool rx_always_on;
+	u8 lfps_threshold;
+	u8 type;
+};
+
+static const struct regmap_config phy_ctrl_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = 0x800,
+};
+
+static const struct regmap_config phy_sel_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = 0x400,
+};
+
+static int spacemit_combphy_set_mode(struct spacemit_combphy_priv *priv)
+{
+	struct regmap *map = priv->regmap_sel;
+	int ret = 0;
+
+	switch (priv->type) {
+	case PHY_TYPE_USB3:
+		regmap_update_bits(map, 0, COMBPHY_MODE_SEL_MASK, COMBPHY_MODE_USB);
+		break;
+	default:
+		dev_err(priv->dev, "PHY type %x not supported\n", priv->type);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int spacemit_combphy_init_usb(struct spacemit_combphy_priv *priv)
+{
+	struct regmap *map = priv->regmap_ctrl;
+	u32 reg_val;
+	int ret;
+
+	regmap_write(map, COMBPHY_USB_REG1, COMBPHY_USB_REG1_VAL);
+	regmap_write(map, COMBPHY_USB_REG2, COMBPHY_USB_REG2_VAL);
+	regmap_write(map, COMBPHY_USB_REG3, COMBPHY_USB_REG3_VAL);
+	regmap_write(map, COMBPHY_USB_REG4, COMBPHY_USB_REG4_VAL);
+
+	ret = regmap_read_poll_timeout(map, COMBPHY_USB_PLL_REG, reg_val,
+				       (reg_val & COMBPHY_USB_PLL_MASK) == COMBPHY_USB_PLL_VAL,
+				       1000, COMBPHY_WAIT_TIMEOUT * 1000);
+	if (ret) {
+		dev_err(priv->dev, "USB3 PHY init timeout!\n");
+		return ret;
+	}
+
+	dev_dbg(priv->dev, "USB3 PHY init lfps threshold %d\n", priv->lfps_threshold);
+	regmap_update_bits(map, COMBPHY_USB_LFPS_REG,
+			   COMBPHY_USB_LFPS_MASK,
+			   priv->lfps_threshold << 8);
+
+	if (priv->rx_always_on)
+		regmap_update_bits(map, COMBPHY_USB_REG4,
+				   COMBPHY_USB_TERM_SHORT_MASK,
+				   COMBPHY_USB_TERM_SHORT_VAL);
+
+	return ret;
+}
+
+static int spacemit_combphy_init(struct phy *phy)
+{
+	struct spacemit_combphy_priv *priv = phy_get_drvdata(phy);
+	int ret;
+
+	ret = spacemit_combphy_set_mode(priv);
+	if (ret) {
+		dev_err(priv->dev, "failed to set mode for PHY type %x\n",
+			priv->type);
+		goto out;
+	}
+
+	ret = reset_control_deassert(priv->phy_rst);
+	if (ret) {
+		dev_err(priv->dev, "failed to deassert rst\n");
+		goto err_rst;
+	}
+
+	switch (priv->type) {
+	case PHY_TYPE_USB3:
+		ret = spacemit_combphy_init_usb(priv);
+		break;
+	default:
+		dev_err(priv->dev, "PHY type %x not supported\n", priv->type);
+		ret = -EINVAL;
+		break;
+	}
+
+	if (ret)
+		goto err_rst;
+
+	return 0;
+
+err_rst:
+	reset_control_assert(priv->phy_rst);
+out:
+	return ret;
+}
+
+static int spacemit_combphy_exit(struct phy *phy)
+{
+	struct spacemit_combphy_priv *priv = phy_get_drvdata(phy);
+
+	reset_control_assert(priv->phy_rst);
+
+	return 0;
+}
+
+static struct phy *spacemit_combphy_xlate(struct device *dev,
+					  const struct of_phandle_args *args)
+{
+	struct spacemit_combphy_priv *priv = dev_get_drvdata(dev);
+
+	if (args->args_count != 1) {
+		dev_err(dev, "invalid number of arguments\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (priv->type != PHY_NONE && priv->type != args->args[0])
+		dev_warn(dev, "PHY type %d is selected to override %d\n",
+			 args->args[0], priv->type);
+
+	priv->type = args->args[0];
+
+	if (args->args_count > 1)
+		dev_dbg(dev, "combo phy idx: %d selected",  args->args[1]);
+
+	return priv->phy;
+}
+
+static const struct phy_ops spacemit_combphy_ops = {
+	.init = spacemit_combphy_init,
+	.exit = spacemit_combphy_exit,
+	.owner = THIS_MODULE,
+};
+
+static int spacemit_combphy_probe(struct platform_device *pdev)
+{
+	struct spacemit_combphy_priv *priv;
+	void __iomem *ctrl_base, *sel_base;
+	struct phy_provider *phy_provider;
+	struct device *dev = &pdev->dev;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	ctrl_base = devm_platform_ioremap_resource_byname(pdev, "ctrl");
+	if (IS_ERR(ctrl_base))
+		return PTR_ERR(ctrl_base);
+
+	priv->regmap_ctrl = devm_regmap_init_mmio(dev, ctrl_base, &phy_ctrl_regmap_config);
+	if (IS_ERR(priv->regmap_ctrl))
+		return dev_err_probe(dev, PTR_ERR(priv->regmap_ctrl),
+				     "Failed to init regmap for ctrl\n");
+
+	sel_base = devm_platform_ioremap_resource_byname(pdev, "sel");
+	if (IS_ERR(sel_base))
+		return PTR_ERR(sel_base);
+
+	priv->regmap_sel = devm_regmap_init_mmio(dev, sel_base, &phy_sel_regmap_config);
+	if (IS_ERR(priv->regmap_sel))
+		return dev_err_probe(dev, PTR_ERR(priv->regmap_sel),
+				     "Failed to init regmap for sel\n");
+
+	priv->lfps_threshold = COMBPHY_USB_LFPS_THRES_DEFAULT;
+	device_property_read_u8(&pdev->dev, "spacemit,lfps-threshold", &priv->lfps_threshold);
+
+	priv->rx_always_on = device_property_read_bool(&pdev->dev, "spacemit,rx-always-on");
+	priv->type = PHY_NONE;
+	priv->dev = dev;
+
+	priv->phy_rst = devm_reset_control_get_exclusive(dev, NULL);
+	if (IS_ERR(priv->phy_rst))
+		return dev_err_probe(dev, PTR_ERR(priv->phy_rst),
+				     "failed to get phy reset\n");
+
+	priv->phy = devm_phy_create(dev, NULL, &spacemit_combphy_ops);
+	if (IS_ERR(priv->phy))
+		return dev_err_probe(dev, PTR_ERR(priv->phy),
+				     "failed to create combphy\n");
+
+	dev_set_drvdata(dev, priv);
+	phy_set_drvdata(priv->phy, priv);
+	phy_provider = devm_of_phy_provider_register(dev, spacemit_combphy_xlate);
+
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id spacemit_combphy_of_match[] = {
+	{ .compatible = "spacemit,k1-combphy", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, spacemit_combphy_of_match);
+
+static struct platform_driver spacemit_combphy_driver = {
+	.probe	= spacemit_combphy_probe,
+	.driver = {
+		.name = "spacemit-k1-combphy",
+		.of_match_table = spacemit_combphy_of_match,
+	},
+};
+module_platform_driver(spacemit_combphy_driver);
+
+MODULE_DESCRIPTION("Spacemit PCIE/USB3.0 COMBO PHY driver");
+MODULE_LICENSE("GPL");

-- 
2.49.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v5 3/4] phy: spacemit: support K1 USB2.0 PHY controller
  2025-05-27 12:01 ` [PATCH v5 3/4] phy: spacemit: support K1 USB2.0 PHY controller Ze Huang
@ 2025-06-03  7:37   ` neil.armstrong
  2025-06-03 12:30     ` Ze Huang
  2025-06-05 12:58   ` Yixun Lan
  1 sibling, 1 reply; 10+ messages in thread
From: neil.armstrong @ 2025-06-03  7:37 UTC (permalink / raw)
  To: Ze Huang, Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Philipp Zabel
  Cc: linux-phy, devicetree, linux-riscv, spacemit, linux-kernel

On 27/05/2025 14:01, Ze Huang wrote:
> The SpacemiT K1 SoC includes three USB ports:
> 
> - One USB2.0 OTG port
> - One USB2.0 host-only port
> - One USB3.0 port with an integrated USB2.0 DRD interface
> 
> Each of these ports is connected to a USB2.0 PHY responsible for USB2
> transmission.
> 
> This commit adds support for the SpacemiT K1 USB2.0 PHY, which is
> compliant with the USB 2.0 specification and supports both 8-bit 60MHz
> and 16-bit 30MHz parallel interfaces.
> 
> Signed-off-by: Ze Huang <huangze@whut.edu.cn>
> ---
>   drivers/phy/Kconfig                |   1 +
>   drivers/phy/Makefile               |   1 +
>   drivers/phy/spacemit/Kconfig       |  13 ++++
>   drivers/phy/spacemit/Makefile      |   2 +
>   drivers/phy/spacemit/phy-k1-usb2.c | 144 +++++++++++++++++++++++++++++++++++++
>   5 files changed, 161 insertions(+)
> 
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index 8d58efe998ec5fd50054eed2c90d6ecce6bd5dd8..fca589aa7926eb5bce14e99785cf32cf0395202e 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -114,6 +114,7 @@ source "drivers/phy/renesas/Kconfig"
>   source "drivers/phy/rockchip/Kconfig"
>   source "drivers/phy/samsung/Kconfig"
>   source "drivers/phy/socionext/Kconfig"
> +source "drivers/phy/spacemit/Kconfig"
>   source "drivers/phy/st/Kconfig"
>   source "drivers/phy/starfive/Kconfig"
>   source "drivers/phy/sunplus/Kconfig"
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index e281442acc752820fe0bd638dfe38986a37c2a78..05993ff8a15daf7e2583b5f9b9b37ac584a30609 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -34,6 +34,7 @@ obj-y					+= allwinner/	\
>   					   rockchip/	\
>   					   samsung/	\
>   					   socionext/	\
> +					   spacemit/	\
>   					   st/		\
>   					   starfive/	\
>   					   sunplus/	\
> diff --git a/drivers/phy/spacemit/Kconfig b/drivers/phy/spacemit/Kconfig
> new file mode 100644
> index 0000000000000000000000000000000000000000..0136aee2e8a2f5f484da136b26f80130794b992c
> --- /dev/null
> +++ b/drivers/phy/spacemit/Kconfig
> @@ -0,0 +1,13 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +#
> +# Phy drivers for SpacemiT platforms
> +#
> +config PHY_SPACEMIT_K1_USB2
> +	tristate "SpacemiT K1 USB 2.0 PHY support"
> +	depends on (ARCH_SPACEMIT || COMPILE_TEST) && OF
> +	depends on COMMON_CLK
> +	depends on USB_COMMON
> +	select GENERIC_PHY
> +	help
> +	  Enable this to support K1 USB 2.0 PHY driver. This driver takes care of
> +	  enabling and clock setup and will be used by K1 udc/ehci/otg/xhci driver.
> diff --git a/drivers/phy/spacemit/Makefile b/drivers/phy/spacemit/Makefile
> new file mode 100644
> index 0000000000000000000000000000000000000000..fec0b425a948541b39b814caef0b05e1e002d92f
> --- /dev/null
> +++ b/drivers/phy/spacemit/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +obj-$(CONFIG_PHY_SPACEMIT_K1_USB2)		+= phy-k1-usb2.o
> diff --git a/drivers/phy/spacemit/phy-k1-usb2.c b/drivers/phy/spacemit/phy-k1-usb2.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..ee64af07478ea02b421473e6f73fd37a3a135e7d
> --- /dev/null
> +++ b/drivers/phy/spacemit/phy-k1-usb2.c
> @@ -0,0 +1,144 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * SpacemiT K1 USB 2.0 PHY driver
> + *
> + * Copyright (C) 2025 SpacemiT (Hangzhou) Technology Co. Ltd
> + * Copyright (C) 2025 Ze Huang <huangze9015@gmail.com>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/iopoll.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/usb/of.h>
> +
> +#define USB2_PHY_REG01			0x04
> +#define  USB2_PHY_REG01_VAL		0x60ef
> +#define  USB2_PHY_REG01_PLL_IS_READY	BIT(0)
> +#define USB2_PHY_REG04			0x10
> +#define  USB2_PHY_REG04_AUTO_CLEAR_DIS	BIT(2)
> +#define USB2_PHY_REG0D			0x34
> +#define  USB2_PHY_REG0D_VAL		0x1c
> +#define USB2_PHY_REG26			0x98
> +#define  USB2_PHY_REG26_VAL		0xbec4
> +
> +#define USB2D_CTRL_RESET_TIME_MS	50
> +
> +struct spacemit_usb2phy {
> +	struct phy	*phy;
> +	struct clk	*clk;
> +	struct regmap	*regmap_base;
> +};
> +
> +static const struct regmap_config phy_regmap_config = {
> +	.reg_bits = 32,
> +	.val_bits = 32,
> +	.reg_stride = 4,
> +	.max_register = 0x200,
> +};
> +
> +static int spacemit_usb2phy_init(struct phy *phy)
> +{
> +	struct spacemit_usb2phy *sphy = phy_get_drvdata(phy);
> +	struct regmap *map = sphy->regmap_base;
> +	u32 val;
> +	int ret;
> +
> +	ret = clk_prepare_enable(sphy->clk);

clock is already prepared, should be clk_enable

> +	if (ret) {
> +		dev_err(&phy->dev, "failed to enable clock\n");
> +		return ret;
> +	}
> +
> +	/*
> +	 * make sure the usb controller is not under reset process before
> +	 * any configuration
> +	 */
> +	usleep_range(150, 200);
> +	regmap_write(map, USB2_PHY_REG26, USB2_PHY_REG26_VAL); /* 24M ref clk */
> +
> +	ret = regmap_read_poll_timeout(map, USB2_PHY_REG01, val,
> +				       (val & USB2_PHY_REG01_PLL_IS_READY),
> +				       500, USB2D_CTRL_RESET_TIME_MS * 1000);
> +	if (ret) {
> +		dev_err(&phy->dev, "wait PHY_REG01[PLLREADY] timeout\n");
> +		return ret;

clk_disable on error ?


> +	}
> +
> +	/* release usb2 phy internal reset and enable clock gating */
> +	regmap_write(map, USB2_PHY_REG01, USB2_PHY_REG01_VAL);
> +	regmap_write(map, USB2_PHY_REG0D, USB2_PHY_REG0D_VAL);
> +
> +	/* auto clear host disc */
> +	regmap_update_bits(map, USB2_PHY_REG04, USB2_PHY_REG04_AUTO_CLEAR_DIS,
> +			   USB2_PHY_REG04_AUTO_CLEAR_DIS);
> +
> +	return 0;
> +}
> +
> +static int spacemit_usb2phy_exit(struct phy *phy)
> +{
> +	struct spacemit_usb2phy *sphy = phy_get_drvdata(phy);
> +
> +	clk_disable_unprepare(sphy->clk);

clk_disable

> +
> +	return 0;
> +}
> +
> +static const struct phy_ops spacemit_usb2phy_ops = {
> +	.init = spacemit_usb2phy_init,
> +	.exit = spacemit_usb2phy_exit,
> +	.owner = THIS_MODULE,
> +};
> +
> +static int spacemit_usb2phy_probe(struct platform_device *pdev)
> +{
> +	struct phy_provider *phy_provider;
> +	struct device *dev = &pdev->dev;
> +	struct spacemit_usb2phy *sphy;
> +	void __iomem *base;
> +
> +	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
> +	if (!sphy)
> +		return -ENOMEM;
> +
> +	sphy->clk = devm_clk_get_prepared(&pdev->dev, NULL);
> +	if (IS_ERR(sphy->clk))
> +		return dev_err_probe(dev, PTR_ERR(sphy->clk), "Failed to get clock\n");
> +
> +	base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	sphy->regmap_base = devm_regmap_init_mmio(dev, base, &phy_regmap_config);
> +	if (IS_ERR(sphy->regmap_base))
> +		return dev_err_probe(dev, PTR_ERR(sphy->regmap_base),
> +				     "Failed to init regmap\n");
> +
> +	sphy->phy = devm_phy_create(dev, NULL, &spacemit_usb2phy_ops);
> +	if (IS_ERR(sphy->phy))
> +		return dev_err_probe(dev, PTR_ERR(sphy->phy), "Failed to create phy\n");
> +
> +	phy_set_drvdata(sphy->phy, sphy);
> +	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> +
> +	return PTR_ERR_OR_ZERO(phy_provider);
> +}
> +
> +static const struct of_device_id spacemit_usb2phy_dt_match[] = {
> +	{ .compatible = "spacemit,k1-usb2-phy", },
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, spacemit_usb2phy_dt_match);
> +
> +static struct platform_driver spacemit_usb2_phy_driver = {
> +	.probe	= spacemit_usb2phy_probe,
> +	.driver = {
> +		.name   = "spacemit-usb2-phy",
> +		.of_match_table = spacemit_usb2phy_dt_match,
> +	},
> +};
> +module_platform_driver(spacemit_usb2_phy_driver);
> +
> +MODULE_DESCRIPTION("Spacemit USB 2.0 PHY driver");
> +MODULE_LICENSE("GPL");
> 

Thanks,
Neil

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v5 3/4] phy: spacemit: support K1 USB2.0 PHY controller
  2025-06-03  7:37   ` neil.armstrong
@ 2025-06-03 12:30     ` Ze Huang
  0 siblings, 0 replies; 10+ messages in thread
From: Ze Huang @ 2025-06-03 12:30 UTC (permalink / raw)
  To: Neil Armstrong, Ze Huang, Vinod Koul, Kishon Vijay Abraham I,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yixun Lan,
	Philipp Zabel
  Cc: linux-phy, devicetree, linux-riscv, spacemit, linux-kernel

On Tue, Jun 03, 2025 at 09:37:58AM +0200, neil.armstrong@linaro.org wrote:
> On 27/05/2025 14:01, Ze Huang wrote:
> > The SpacemiT K1 SoC includes three USB ports:
> > 
> > - One USB2.0 OTG port
> > - One USB2.0 host-only port
> > - One USB3.0 port with an integrated USB2.0 DRD interface
> > 
> > Each of these ports is connected to a USB2.0 PHY responsible for USB2
> > transmission.
> > 
> > This commit adds support for the SpacemiT K1 USB2.0 PHY, which is
> > compliant with the USB 2.0 specification and supports both 8-bit 60MHz
> > and 16-bit 30MHz parallel interfaces.
> > 
> > Signed-off-by: Ze Huang <huangze@whut.edu.cn>
> > ---
> >   drivers/phy/Kconfig                |   1 +
> >   drivers/phy/Makefile               |   1 +
> >   drivers/phy/spacemit/Kconfig       |  13 ++++
> >   drivers/phy/spacemit/Makefile      |   2 +
> >   drivers/phy/spacemit/phy-k1-usb2.c | 144 +++++++++++++++++++++++++++++++++++++
> >   5 files changed, 161 insertions(+)
> > 
> > diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> > index 8d58efe998ec5fd50054eed2c90d6ecce6bd5dd8..fca589aa7926eb5bce14e99785cf32cf0395202e 100644
> > --- a/drivers/phy/Kconfig
> > +++ b/drivers/phy/Kconfig
> > @@ -114,6 +114,7 @@ source "drivers/phy/renesas/Kconfig"
> >   source "drivers/phy/rockchip/Kconfig"
> >   source "drivers/phy/samsung/Kconfig"
> >   source "drivers/phy/socionext/Kconfig"
> > +source "drivers/phy/spacemit/Kconfig"
> >   source "drivers/phy/st/Kconfig"
> >   source "drivers/phy/starfive/Kconfig"
> >   source "drivers/phy/sunplus/Kconfig"
> > diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> > index e281442acc752820fe0bd638dfe38986a37c2a78..05993ff8a15daf7e2583b5f9b9b37ac584a30609 100644
> > --- a/drivers/phy/Makefile
> > +++ b/drivers/phy/Makefile
> > @@ -34,6 +34,7 @@ obj-y					+= allwinner/	\
> >   					   rockchip/	\
> >   					   samsung/	\
> >   					   socionext/	\
> > +					   spacemit/	\
> >   					   st/		\
> >   					   starfive/	\
> >   					   sunplus/	\
> > diff --git a/drivers/phy/spacemit/Kconfig b/drivers/phy/spacemit/Kconfig
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..0136aee2e8a2f5f484da136b26f80130794b992c
> > --- /dev/null
> > +++ b/drivers/phy/spacemit/Kconfig
> > @@ -0,0 +1,13 @@
> > +# SPDX-License-Identifier: GPL-2.0-only
> > +#
> > +# Phy drivers for SpacemiT platforms
> > +#
> > +config PHY_SPACEMIT_K1_USB2
> > +	tristate "SpacemiT K1 USB 2.0 PHY support"
> > +	depends on (ARCH_SPACEMIT || COMPILE_TEST) && OF
> > +	depends on COMMON_CLK
> > +	depends on USB_COMMON
> > +	select GENERIC_PHY
> > +	help
> > +	  Enable this to support K1 USB 2.0 PHY driver. This driver takes care of
> > +	  enabling and clock setup and will be used by K1 udc/ehci/otg/xhci driver.
> > diff --git a/drivers/phy/spacemit/Makefile b/drivers/phy/spacemit/Makefile
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..fec0b425a948541b39b814caef0b05e1e002d92f
> > --- /dev/null
> > +++ b/drivers/phy/spacemit/Makefile
> > @@ -0,0 +1,2 @@
> > +# SPDX-License-Identifier: GPL-2.0-only
> > +obj-$(CONFIG_PHY_SPACEMIT_K1_USB2)		+= phy-k1-usb2.o
> > diff --git a/drivers/phy/spacemit/phy-k1-usb2.c b/drivers/phy/spacemit/phy-k1-usb2.c
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..ee64af07478ea02b421473e6f73fd37a3a135e7d
> > --- /dev/null
> > +++ b/drivers/phy/spacemit/phy-k1-usb2.c
> > @@ -0,0 +1,144 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * SpacemiT K1 USB 2.0 PHY driver
> > + *
> > + * Copyright (C) 2025 SpacemiT (Hangzhou) Technology Co. Ltd
> > + * Copyright (C) 2025 Ze Huang <huangze9015@gmail.com>
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/iopoll.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +#include <linux/usb/of.h>
> > +
> > +#define USB2_PHY_REG01			0x04
> > +#define  USB2_PHY_REG01_VAL		0x60ef
> > +#define  USB2_PHY_REG01_PLL_IS_READY	BIT(0)
> > +#define USB2_PHY_REG04			0x10
> > +#define  USB2_PHY_REG04_AUTO_CLEAR_DIS	BIT(2)
> > +#define USB2_PHY_REG0D			0x34
> > +#define  USB2_PHY_REG0D_VAL		0x1c
> > +#define USB2_PHY_REG26			0x98
> > +#define  USB2_PHY_REG26_VAL		0xbec4
> > +
> > +#define USB2D_CTRL_RESET_TIME_MS	50
> > +
> > +struct spacemit_usb2phy {
> > +	struct phy	*phy;
> > +	struct clk	*clk;
> > +	struct regmap	*regmap_base;
> > +};
> > +
> > +static const struct regmap_config phy_regmap_config = {
> > +	.reg_bits = 32,
> > +	.val_bits = 32,
> > +	.reg_stride = 4,
> > +	.max_register = 0x200,
> > +};
> > +
> > +static int spacemit_usb2phy_init(struct phy *phy)
> > +{
> > +	struct spacemit_usb2phy *sphy = phy_get_drvdata(phy);
> > +	struct regmap *map = sphy->regmap_base;
> > +	u32 val;
> > +	int ret;
> > +
> > +	ret = clk_prepare_enable(sphy->clk);
> 
> clock is already prepared, should be clk_enable
> 

Yes, the clock is already prepared during probe and managed by devm. I'll
change it to clk_enable here.

> > +	if (ret) {
> > +		dev_err(&phy->dev, "failed to enable clock\n");
> > +		return ret;
> > +	}
> > +
> > +	/*
> > +	 * make sure the usb controller is not under reset process before
> > +	 * any configuration
> > +	 */
> > +	usleep_range(150, 200);
> > +	regmap_write(map, USB2_PHY_REG26, USB2_PHY_REG26_VAL); /* 24M ref clk */
> > +
> > +	ret = regmap_read_poll_timeout(map, USB2_PHY_REG01, val,
> > +				       (val & USB2_PHY_REG01_PLL_IS_READY),
> > +				       500, USB2D_CTRL_RESET_TIME_MS * 1000);
> > +	if (ret) {
> > +		dev_err(&phy->dev, "wait PHY_REG01[PLLREADY] timeout\n");
> > +		return ret;
> 
> clk_disable on error ?
> 
> 

Will do

    if (ret) {
        dev_err(&phy->dev, "wait PHY_REG01[PLLREADY] timeout\n");
        clk_disable(sphy->clk);
        return ret;
    }

> > +	}
> > +
> > +	/* release usb2 phy internal reset and enable clock gating */
> > +	regmap_write(map, USB2_PHY_REG01, USB2_PHY_REG01_VAL);
> > +	regmap_write(map, USB2_PHY_REG0D, USB2_PHY_REG0D_VAL);
> > +
> > +	/* auto clear host disc */
> > +	regmap_update_bits(map, USB2_PHY_REG04, USB2_PHY_REG04_AUTO_CLEAR_DIS,
> > +			   USB2_PHY_REG04_AUTO_CLEAR_DIS);
> > +
> > +	return 0;
> > +}
> > +
> > +static int spacemit_usb2phy_exit(struct phy *phy)
> > +{
> > +	struct spacemit_usb2phy *sphy = phy_get_drvdata(phy);
> > +
> > +	clk_disable_unprepare(sphy->clk);
> 
> clk_disable
> 

Thanks, will fix

> > +
> > +	return 0;
> > +}
> > +
> > +static const struct phy_ops spacemit_usb2phy_ops = {
> > +	.init = spacemit_usb2phy_init,
> > +	.exit = spacemit_usb2phy_exit,
> > +	.owner = THIS_MODULE,
> > +};
> > +
> > +static int spacemit_usb2phy_probe(struct platform_device *pdev)
> > +{
> > +	struct phy_provider *phy_provider;
> > +	struct device *dev = &pdev->dev;
> > +	struct spacemit_usb2phy *sphy;
> > +	void __iomem *base;
> > +
> > +	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
> > +	if (!sphy)
> > +		return -ENOMEM;
> > +
> > +	sphy->clk = devm_clk_get_prepared(&pdev->dev, NULL);
> > +	if (IS_ERR(sphy->clk))
> > +		return dev_err_probe(dev, PTR_ERR(sphy->clk), "Failed to get clock\n");
> > +
> > +	base = devm_platform_ioremap_resource(pdev, 0);
> > +	if (IS_ERR(base))
> > +		return PTR_ERR(base);
> > +
> > +	sphy->regmap_base = devm_regmap_init_mmio(dev, base, &phy_regmap_config);
> > +	if (IS_ERR(sphy->regmap_base))
> > +		return dev_err_probe(dev, PTR_ERR(sphy->regmap_base),
> > +				     "Failed to init regmap\n");
> > +
> > +	sphy->phy = devm_phy_create(dev, NULL, &spacemit_usb2phy_ops);
> > +	if (IS_ERR(sphy->phy))
> > +		return dev_err_probe(dev, PTR_ERR(sphy->phy), "Failed to create phy\n");
> > +
> > +	phy_set_drvdata(sphy->phy, sphy);
> > +	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> > +
> > +	return PTR_ERR_OR_ZERO(phy_provider);
> > +}
> > +
> > +static const struct of_device_id spacemit_usb2phy_dt_match[] = {
> > +	{ .compatible = "spacemit,k1-usb2-phy", },
> > +	{ /* sentinel */ }
> > +};
> > +MODULE_DEVICE_TABLE(of, spacemit_usb2phy_dt_match);
> > +
> > +static struct platform_driver spacemit_usb2_phy_driver = {
> > +	.probe	= spacemit_usb2phy_probe,
> > +	.driver = {
> > +		.name   = "spacemit-usb2-phy",
> > +		.of_match_table = spacemit_usb2phy_dt_match,
> > +	},
> > +};
> > +module_platform_driver(spacemit_usb2_phy_driver);
> > +
> > +MODULE_DESCRIPTION("Spacemit USB 2.0 PHY driver");
> > +MODULE_LICENSE("GPL");
> > 
> 
> Thanks,
> Neil
> 
> 
> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v5 3/4] phy: spacemit: support K1 USB2.0 PHY controller
  2025-05-27 12:01 ` [PATCH v5 3/4] phy: spacemit: support K1 USB2.0 PHY controller Ze Huang
  2025-06-03  7:37   ` neil.armstrong
@ 2025-06-05 12:58   ` Yixun Lan
  2025-06-05 13:15     ` Ze Huang
  1 sibling, 1 reply; 10+ messages in thread
From: Yixun Lan @ 2025-06-05 12:58 UTC (permalink / raw)
  To: Ze Huang
  Cc: Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Philipp Zabel, linux-phy,
	devicetree, linux-riscv, spacemit, linux-kernel

Hi Ze,

few minor comments..
On 20:01 Tue 27 May     , Ze Huang wrote:
> The SpacemiT K1 SoC includes three USB ports:
> 
> - One USB2.0 OTG port
> - One USB2.0 host-only port
> - One USB3.0 port with an integrated USB2.0 DRD interface
> 
> Each of these ports is connected to a USB2.0 PHY responsible for USB2
> transmission.
> 
> This commit adds support for the SpacemiT K1 USB2.0 PHY, which is
> compliant with the USB 2.0 specification and supports both 8-bit 60MHz
> and 16-bit 30MHz parallel interfaces.
> 
> Signed-off-by: Ze Huang <huangze@whut.edu.cn>
> ---
>  drivers/phy/Kconfig                |   1 +
>  drivers/phy/Makefile               |   1 +
>  drivers/phy/spacemit/Kconfig       |  13 ++++
>  drivers/phy/spacemit/Makefile      |   2 +
>  drivers/phy/spacemit/phy-k1-usb2.c | 144 +++++++++++++++++++++++++++++++++++++
>  5 files changed, 161 insertions(+)
> 
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index 8d58efe998ec5fd50054eed2c90d6ecce6bd5dd8..fca589aa7926eb5bce14e99785cf32cf0395202e 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -114,6 +114,7 @@ source "drivers/phy/renesas/Kconfig"
>  source "drivers/phy/rockchip/Kconfig"
>  source "drivers/phy/samsung/Kconfig"
>  source "drivers/phy/socionext/Kconfig"
> +source "drivers/phy/spacemit/Kconfig"
>  source "drivers/phy/st/Kconfig"
>  source "drivers/phy/starfive/Kconfig"
>  source "drivers/phy/sunplus/Kconfig"
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index e281442acc752820fe0bd638dfe38986a37c2a78..05993ff8a15daf7e2583b5f9b9b37ac584a30609 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -34,6 +34,7 @@ obj-y					+= allwinner/	\
>  					   rockchip/	\
>  					   samsung/	\
>  					   socionext/	\
> +					   spacemit/	\
>  					   st/		\
>  					   starfive/	\
>  					   sunplus/	\
> diff --git a/drivers/phy/spacemit/Kconfig b/drivers/phy/spacemit/Kconfig
> new file mode 100644
> index 0000000000000000000000000000000000000000..0136aee2e8a2f5f484da136b26f80130794b992c
> --- /dev/null
> +++ b/drivers/phy/spacemit/Kconfig
> @@ -0,0 +1,13 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +#
> +# Phy drivers for SpacemiT platforms
> +#
> +config PHY_SPACEMIT_K1_USB2
> +	tristate "SpacemiT K1 USB 2.0 PHY support"
> +	depends on (ARCH_SPACEMIT || COMPILE_TEST) && OF
> +	depends on COMMON_CLK
> +	depends on USB_COMMON
> +	select GENERIC_PHY
> +	help
> +	  Enable this to support K1 USB 2.0 PHY driver. This driver takes care of
> +	  enabling and clock setup and will be used by K1 udc/ehci/otg/xhci driver.
> diff --git a/drivers/phy/spacemit/Makefile b/drivers/phy/spacemit/Makefile
> new file mode 100644
> index 0000000000000000000000000000000000000000..fec0b425a948541b39b814caef0b05e1e002d92f
> --- /dev/null
> +++ b/drivers/phy/spacemit/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +obj-$(CONFIG_PHY_SPACEMIT_K1_USB2)		+= phy-k1-usb2.o
> diff --git a/drivers/phy/spacemit/phy-k1-usb2.c b/drivers/phy/spacemit/phy-k1-usb2.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..ee64af07478ea02b421473e6f73fd37a3a135e7d
> --- /dev/null
> +++ b/drivers/phy/spacemit/phy-k1-usb2.c
> @@ -0,0 +1,144 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * SpacemiT K1 USB 2.0 PHY driver
> + *
> + * Copyright (C) 2025 SpacemiT (Hangzhou) Technology Co. Ltd
> + * Copyright (C) 2025 Ze Huang <huangze9015@gmail.com>
keep email address consistent with your SoF?

> + */
> +
> +#include <linux/clk.h>
> +#include <linux/iopoll.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/usb/of.h>
> +
> +#define USB2_PHY_REG01			0x04
> +#define  USB2_PHY_REG01_VAL		0x60ef
> +#define  USB2_PHY_REG01_PLL_IS_READY	BIT(0)
> +#define USB2_PHY_REG04			0x10
> +#define  USB2_PHY_REG04_AUTO_CLEAR_DIS	BIT(2)
> +#define USB2_PHY_REG0D			0x34
> +#define  USB2_PHY_REG0D_VAL		0x1c
> +#define USB2_PHY_REG26			0x98
> +#define  USB2_PHY_REG26_VAL		0xbec4
> +
> +#define USB2D_CTRL_RESET_TIME_MS	50
> +
> +struct spacemit_usb2phy {
> +	struct phy	*phy;
use space instead of tab? same as you do in 4/4 patch
(It would be easy to break the alignment if adding more members in
the future, or bring unnecessary changes if re-arrange alignment)
> +	struct clk	*clk;
> +	struct regmap	*regmap_base;
> +};
> +
> +static const struct regmap_config phy_regmap_config = {
> +	.reg_bits = 32,
> +	.val_bits = 32,
> +	.reg_stride = 4,
> +	.max_register = 0x200,
> +};
> +
> +static int spacemit_usb2phy_init(struct phy *phy)
> +{
> +	struct spacemit_usb2phy *sphy = phy_get_drvdata(phy);
> +	struct regmap *map = sphy->regmap_base;
> +	u32 val;
> +	int ret;
> +
> +	ret = clk_prepare_enable(sphy->clk);
> +	if (ret) {
> +		dev_err(&phy->dev, "failed to enable clock\n");
> +		return ret;
> +	}
> +
> +	/*
> +	 * make sure the usb controller is not under reset process before
> +	 * any configuration
> +	 */
> +	usleep_range(150, 200);
> +	regmap_write(map, USB2_PHY_REG26, USB2_PHY_REG26_VAL); /* 24M ref clk */
> +
> +	ret = regmap_read_poll_timeout(map, USB2_PHY_REG01, val,
> +				       (val & USB2_PHY_REG01_PLL_IS_READY),
> +				       500, USB2D_CTRL_RESET_TIME_MS * 1000);
> +	if (ret) {
> +		dev_err(&phy->dev, "wait PHY_REG01[PLLREADY] timeout\n");
> +		return ret;
> +	}
> +
> +	/* release usb2 phy internal reset and enable clock gating */
> +	regmap_write(map, USB2_PHY_REG01, USB2_PHY_REG01_VAL);
> +	regmap_write(map, USB2_PHY_REG0D, USB2_PHY_REG0D_VAL);
> +
> +	/* auto clear host disc */
> +	regmap_update_bits(map, USB2_PHY_REG04, USB2_PHY_REG04_AUTO_CLEAR_DIS,
> +			   USB2_PHY_REG04_AUTO_CLEAR_DIS);
> +
> +	return 0;
> +}
> +
> +static int spacemit_usb2phy_exit(struct phy *phy)
> +{
> +	struct spacemit_usb2phy *sphy = phy_get_drvdata(phy);
> +
> +	clk_disable_unprepare(sphy->clk);
> +
> +	return 0;
> +}
> +
> +static const struct phy_ops spacemit_usb2phy_ops = {
> +	.init = spacemit_usb2phy_init,
> +	.exit = spacemit_usb2phy_exit,
> +	.owner = THIS_MODULE,
> +};
> +
> +static int spacemit_usb2phy_probe(struct platform_device *pdev)
> +{
> +	struct phy_provider *phy_provider;
> +	struct device *dev = &pdev->dev;
> +	struct spacemit_usb2phy *sphy;
> +	void __iomem *base;
> +
> +	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
> +	if (!sphy)
> +		return -ENOMEM;
> +
> +	sphy->clk = devm_clk_get_prepared(&pdev->dev, NULL);
> +	if (IS_ERR(sphy->clk))
> +		return dev_err_probe(dev, PTR_ERR(sphy->clk), "Failed to get clock\n");
> +
> +	base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	sphy->regmap_base = devm_regmap_init_mmio(dev, base, &phy_regmap_config);
> +	if (IS_ERR(sphy->regmap_base))
> +		return dev_err_probe(dev, PTR_ERR(sphy->regmap_base),
..
> +				     "Failed to init regmap\n");
no need to break line
> +
> +	sphy->phy = devm_phy_create(dev, NULL, &spacemit_usb2phy_ops);
> +	if (IS_ERR(sphy->phy))
> +		return dev_err_probe(dev, PTR_ERR(sphy->phy), "Failed to create phy\n");
> +
> +	phy_set_drvdata(sphy->phy, sphy);
> +	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> +
> +	return PTR_ERR_OR_ZERO(phy_provider);
> +}
> +
> +static const struct of_device_id spacemit_usb2phy_dt_match[] = {
> +	{ .compatible = "spacemit,k1-usb2-phy", },
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, spacemit_usb2phy_dt_match);
> +
> +static struct platform_driver spacemit_usb2_phy_driver = {
> +	.probe	= spacemit_usb2phy_probe,
> +	.driver = {
> +		.name   = "spacemit-usb2-phy",
> +		.of_match_table = spacemit_usb2phy_dt_match,
> +	},
> +};
> +module_platform_driver(spacemit_usb2_phy_driver);
> +
> +MODULE_DESCRIPTION("Spacemit USB 2.0 PHY driver");
> +MODULE_LICENSE("GPL");
> 
> -- 
> 2.49.0
> 

-- 
Yixun Lan (dlan)

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v5 3/4] phy: spacemit: support K1 USB2.0 PHY controller
  2025-06-05 12:58   ` Yixun Lan
@ 2025-06-05 13:15     ` Ze Huang
  0 siblings, 0 replies; 10+ messages in thread
From: Ze Huang @ 2025-06-05 13:15 UTC (permalink / raw)
  To: Yixun Lan, Ze Huang
  Cc: Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Philipp Zabel, linux-phy,
	devicetree, linux-riscv, spacemit, linux-kernel

On Thu, Jun 05, 2025 at 12:58:37PM +0000, Yixun Lan wrote:
> Hi Ze,
> 
> few minor comments..
> On 20:01 Tue 27 May     , Ze Huang wrote:
> > The SpacemiT K1 SoC includes three USB ports:
> > 
> > - One USB2.0 OTG port
> > - One USB2.0 host-only port
> > - One USB3.0 port with an integrated USB2.0 DRD interface
> > 
> > Each of these ports is connected to a USB2.0 PHY responsible for USB2
> > transmission.
> > 
> > This commit adds support for the SpacemiT K1 USB2.0 PHY, which is
> > compliant with the USB 2.0 specification and supports both 8-bit 60MHz
> > and 16-bit 30MHz parallel interfaces.
> > 
> > Signed-off-by: Ze Huang <huangze@whut.edu.cn>
> > ---
> >  drivers/phy/Kconfig                |   1 +
> >  drivers/phy/Makefile               |   1 +
> >  drivers/phy/spacemit/Kconfig       |  13 ++++
> >  drivers/phy/spacemit/Makefile      |   2 +
> >  drivers/phy/spacemit/phy-k1-usb2.c | 144 +++++++++++++++++++++++++++++++++++++
> >  5 files changed, 161 insertions(+)
> > 
> > diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> > index 8d58efe998ec5fd50054eed2c90d6ecce6bd5dd8..fca589aa7926eb5bce14e99785cf32cf0395202e 100644
> > --- a/drivers/phy/Kconfig
> > +++ b/drivers/phy/Kconfig
> > @@ -114,6 +114,7 @@ source "drivers/phy/renesas/Kconfig"
> >  source "drivers/phy/rockchip/Kconfig"
> >  source "drivers/phy/samsung/Kconfig"
> >  source "drivers/phy/socionext/Kconfig"
> > +source "drivers/phy/spacemit/Kconfig"
> >  source "drivers/phy/st/Kconfig"
> >  source "drivers/phy/starfive/Kconfig"
> >  source "drivers/phy/sunplus/Kconfig"
> > diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> > index e281442acc752820fe0bd638dfe38986a37c2a78..05993ff8a15daf7e2583b5f9b9b37ac584a30609 100644
> > --- a/drivers/phy/Makefile
> > +++ b/drivers/phy/Makefile
> > @@ -34,6 +34,7 @@ obj-y					+= allwinner/	\
> >  					   rockchip/	\
> >  					   samsung/	\
> >  					   socionext/	\
> > +					   spacemit/	\
> >  					   st/		\
> >  					   starfive/	\
> >  					   sunplus/	\
> > diff --git a/drivers/phy/spacemit/Kconfig b/drivers/phy/spacemit/Kconfig
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..0136aee2e8a2f5f484da136b26f80130794b992c
> > --- /dev/null
> > +++ b/drivers/phy/spacemit/Kconfig
> > @@ -0,0 +1,13 @@
> > +# SPDX-License-Identifier: GPL-2.0-only
> > +#
> > +# Phy drivers for SpacemiT platforms
> > +#
> > +config PHY_SPACEMIT_K1_USB2
> > +	tristate "SpacemiT K1 USB 2.0 PHY support"
> > +	depends on (ARCH_SPACEMIT || COMPILE_TEST) && OF
> > +	depends on COMMON_CLK
> > +	depends on USB_COMMON
> > +	select GENERIC_PHY
> > +	help
> > +	  Enable this to support K1 USB 2.0 PHY driver. This driver takes care of
> > +	  enabling and clock setup and will be used by K1 udc/ehci/otg/xhci driver.
> > diff --git a/drivers/phy/spacemit/Makefile b/drivers/phy/spacemit/Makefile
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..fec0b425a948541b39b814caef0b05e1e002d92f
> > --- /dev/null
> > +++ b/drivers/phy/spacemit/Makefile
> > @@ -0,0 +1,2 @@
> > +# SPDX-License-Identifier: GPL-2.0-only
> > +obj-$(CONFIG_PHY_SPACEMIT_K1_USB2)		+= phy-k1-usb2.o
> > diff --git a/drivers/phy/spacemit/phy-k1-usb2.c b/drivers/phy/spacemit/phy-k1-usb2.c
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..ee64af07478ea02b421473e6f73fd37a3a135e7d
> > --- /dev/null
> > +++ b/drivers/phy/spacemit/phy-k1-usb2.c
> > @@ -0,0 +1,144 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * SpacemiT K1 USB 2.0 PHY driver
> > + *
> > + * Copyright (C) 2025 SpacemiT (Hangzhou) Technology Co. Ltd
> > + * Copyright (C) 2025 Ze Huang <huangze9015@gmail.com>
> keep email address consistent with your SoF?
> 

I used my personal email since my .edu address might be revoked after
graduation.

> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/iopoll.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +#include <linux/usb/of.h>
> > +
> > +#define USB2_PHY_REG01			0x04
> > +#define  USB2_PHY_REG01_VAL		0x60ef
> > +#define  USB2_PHY_REG01_PLL_IS_READY	BIT(0)
> > +#define USB2_PHY_REG04			0x10
> > +#define  USB2_PHY_REG04_AUTO_CLEAR_DIS	BIT(2)
> > +#define USB2_PHY_REG0D			0x34
> > +#define  USB2_PHY_REG0D_VAL		0x1c
> > +#define USB2_PHY_REG26			0x98
> > +#define  USB2_PHY_REG26_VAL		0xbec4
> > +
> > +#define USB2D_CTRL_RESET_TIME_MS	50
> > +
> > +struct spacemit_usb2phy {
> > +	struct phy	*phy;
> use space instead of tab? same as you do in 4/4 patch
> (It would be easy to break the alignment if adding more members in
> the future, or bring unnecessary changes if re-arrange alignment)

Thanks, will follow

> > +	struct clk	*clk;
> > +	struct regmap	*regmap_base;
> > +};
> > +
> > +static const struct regmap_config phy_regmap_config = {
> > +	.reg_bits = 32,
> > +	.val_bits = 32,
> > +	.reg_stride = 4,
> > +	.max_register = 0x200,
> > +};
> > +
> > +static int spacemit_usb2phy_init(struct phy *phy)
> > +{
> > +	struct spacemit_usb2phy *sphy = phy_get_drvdata(phy);
> > +	struct regmap *map = sphy->regmap_base;
> > +	u32 val;
> > +	int ret;
> > +
> > +	ret = clk_prepare_enable(sphy->clk);
> > +	if (ret) {
> > +		dev_err(&phy->dev, "failed to enable clock\n");
> > +		return ret;
> > +	}
> > +
> > +	/*
> > +	 * make sure the usb controller is not under reset process before
> > +	 * any configuration
> > +	 */
> > +	usleep_range(150, 200);
> > +	regmap_write(map, USB2_PHY_REG26, USB2_PHY_REG26_VAL); /* 24M ref clk */
> > +
> > +	ret = regmap_read_poll_timeout(map, USB2_PHY_REG01, val,
> > +				       (val & USB2_PHY_REG01_PLL_IS_READY),
> > +				       500, USB2D_CTRL_RESET_TIME_MS * 1000);
> > +	if (ret) {
> > +		dev_err(&phy->dev, "wait PHY_REG01[PLLREADY] timeout\n");
> > +		return ret;
> > +	}
> > +
> > +	/* release usb2 phy internal reset and enable clock gating */
> > +	regmap_write(map, USB2_PHY_REG01, USB2_PHY_REG01_VAL);
> > +	regmap_write(map, USB2_PHY_REG0D, USB2_PHY_REG0D_VAL);
> > +
> > +	/* auto clear host disc */
> > +	regmap_update_bits(map, USB2_PHY_REG04, USB2_PHY_REG04_AUTO_CLEAR_DIS,
> > +			   USB2_PHY_REG04_AUTO_CLEAR_DIS);
> > +
> > +	return 0;
> > +}
> > +
> > +static int spacemit_usb2phy_exit(struct phy *phy)
> > +{
> > +	struct spacemit_usb2phy *sphy = phy_get_drvdata(phy);
> > +
> > +	clk_disable_unprepare(sphy->clk);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct phy_ops spacemit_usb2phy_ops = {
> > +	.init = spacemit_usb2phy_init,
> > +	.exit = spacemit_usb2phy_exit,
> > +	.owner = THIS_MODULE,
> > +};
> > +
> > +static int spacemit_usb2phy_probe(struct platform_device *pdev)
> > +{
> > +	struct phy_provider *phy_provider;
> > +	struct device *dev = &pdev->dev;
> > +	struct spacemit_usb2phy *sphy;
> > +	void __iomem *base;
> > +
> > +	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
> > +	if (!sphy)
> > +		return -ENOMEM;
> > +
> > +	sphy->clk = devm_clk_get_prepared(&pdev->dev, NULL);
> > +	if (IS_ERR(sphy->clk))
> > +		return dev_err_probe(dev, PTR_ERR(sphy->clk), "Failed to get clock\n");
> > +
> > +	base = devm_platform_ioremap_resource(pdev, 0);
> > +	if (IS_ERR(base))
> > +		return PTR_ERR(base);
> > +
> > +	sphy->regmap_base = devm_regmap_init_mmio(dev, base, &phy_regmap_config);
> > +	if (IS_ERR(sphy->regmap_base))
> > +		return dev_err_probe(dev, PTR_ERR(sphy->regmap_base),
> ..
> > +				     "Failed to init regmap\n");
> no need to break line

OK

> > +
> > +	sphy->phy = devm_phy_create(dev, NULL, &spacemit_usb2phy_ops);
> > +	if (IS_ERR(sphy->phy))
> > +		return dev_err_probe(dev, PTR_ERR(sphy->phy), "Failed to create phy\n");
> > +
> > +	phy_set_drvdata(sphy->phy, sphy);
> > +	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> > +
> > +	return PTR_ERR_OR_ZERO(phy_provider);
> > +}
> > +
> > +static const struct of_device_id spacemit_usb2phy_dt_match[] = {
> > +	{ .compatible = "spacemit,k1-usb2-phy", },
> > +	{ /* sentinel */ }
> > +};
> > +MODULE_DEVICE_TABLE(of, spacemit_usb2phy_dt_match);
> > +
> > +static struct platform_driver spacemit_usb2_phy_driver = {
> > +	.probe	= spacemit_usb2phy_probe,
> > +	.driver = {
> > +		.name   = "spacemit-usb2-phy",
> > +		.of_match_table = spacemit_usb2phy_dt_match,
> > +	},
> > +};
> > +module_platform_driver(spacemit_usb2_phy_driver);
> > +
> > +MODULE_DESCRIPTION("Spacemit USB 2.0 PHY driver");
> > +MODULE_LICENSE("GPL");
> > 
> > -- 
> > 2.49.0
> > 
> 
> -- 
> Yixun Lan (dlan)
> 
> 
> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v5 2/4] dt-bindings: phy: spacemit: add K1 PCIe/USB3 combo PHY
  2025-05-27 12:01 ` [PATCH v5 2/4] dt-bindings: phy: spacemit: add K1 PCIe/USB3 combo PHY Ze Huang
@ 2025-06-10 19:57   ` Alex Elder
  0 siblings, 0 replies; 10+ messages in thread
From: Alex Elder @ 2025-06-10 19:57 UTC (permalink / raw)
  To: Ze Huang, Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Philipp Zabel
  Cc: linux-phy, devicetree, linux-riscv, spacemit, linux-kernel,
	Junzhong Pan

On 5/27/25 7:01 AM, Ze Huang wrote:
> Introduce support for SpacemiT K1 PCIe/USB3 combo PHY controller.
> 
> PCIe portA and USB3 controller share this phy, only one of them can work
> at any given application scenario.
> 
> Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
> Co-developed-by: Junzhong Pan <junzhong.pan@spacemit.com>
> Signed-off-by: Junzhong Pan <junzhong.pan@spacemit.com>
> Signed-off-by: Ze Huang <huangze@whut.edu.cn>

This PHY has an interaction with PCIe port A.

In practice this PHY is only used for USB 3.0 (not PCIe).

However I am told that only the PHY used for port A is capable
of performing a resistor termination/tuning process (not ports
B and C).  As a result, the PCIe driver needs this process to
complete on the PHY for port A; it can then read the port A TX
and RX calibration values (4 bits each).  It uses these values
to configure the PHYs for ports B and C.

For this reason, this PHY code (and binding) should not be
merged until we are sure that the solution will also satisfy
these PCIe requirements.

					-Alex


> ---
>   .../bindings/phy/spacemit,k1-combphy.yaml          | 72 ++++++++++++++++++++++
>   1 file changed, 72 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/phy/spacemit,k1-combphy.yaml b/Documentation/devicetree/bindings/phy/spacemit,k1-combphy.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..93f7a3bb06bba380def77f87f6db0184af26e9e6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/spacemit,k1-combphy.yaml
> @@ -0,0 +1,72 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/phy/spacemit,k1-combphy.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: SpacemiT K1 PCIe/USB3 Combo PHY
> +
> +maintainers:
> +  - Ze Huang <huangze9015@gmail.com>
> +
> +description:
> +  Combo PHY on SpacemiT K1 SoC. PCIe port A and USB3 controller share this
> +  phy, only one of PCIe port A and USB3 port can work at any given application
> +  scenario.
> +
> +properties:
> +  compatible:
> +    const: spacemit,k1-combphy
> +
> +  reg:
> +    items:
> +      - description: PHY control registers
> +      - description: PCIe/USB3 mode selection register
> +
> +  reg-names:
> +    items:
> +      - const: ctrl
> +      - const: sel
> +
> +  resets:
> +    maxItems: 1
> +
> +  "#phy-cells":
> +    const: 1
> +    description:
> +      Indicates the PHY mode to select. The value determines whether the PHY
> +      operates in PCIe or USB3 mode.
> +
> +  spacemit,lfps-threshold:
> +    description:
> +      Controls the LFPS signal detection threshold, affects polling.LFPS
> +      handshake. Lower the threshold when core voltage rises.
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 0
> +    maximum: 0xff
> +
> +  spacemit,rx-always-on:
> +    description:
> +      Affects RX.detect, enhance compatibility of some DFPs in device mode but
> +      increase power consumption.
> +    type: boolean
> +
> +required:
> +  - compatible
> +  - reg
> +  - reg-names
> +  - resets
> +  - "#phy-cells"
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    phy@c0b10000 {
> +        compatible = "spacemit,k1-combphy";
> +        reg = <0xc0b10000 0x800>,
> +              <0xd4282910 0x400>;
> +        reg-names = "ctrl", "sel";
> +        resets = <&syscon_apmu 19>;
> +        #phy-cells = <1>;
> +    };
> 


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

end of thread, other threads:[~2025-06-10 22:49 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-27 12:01 [PATCH v5 0/4] Add USB2.0 PHY and USB3.0 PHY support for SpacemiT K1 Ze Huang
2025-05-27 12:01 ` [PATCH v5 1/4] dt-bindings: phy: spacemit: add K1 USB2 PHY Ze Huang
2025-05-27 12:01 ` [PATCH v5 2/4] dt-bindings: phy: spacemit: add K1 PCIe/USB3 combo PHY Ze Huang
2025-06-10 19:57   ` Alex Elder
2025-05-27 12:01 ` [PATCH v5 3/4] phy: spacemit: support K1 USB2.0 PHY controller Ze Huang
2025-06-03  7:37   ` neil.armstrong
2025-06-03 12:30     ` Ze Huang
2025-06-05 12:58   ` Yixun Lan
2025-06-05 13:15     ` Ze Huang
2025-05-27 12:01 ` [PATCH v5 4/4] phy: spacemit: add USB3 support for K1 PCIe/USB3 combo PHY Ze Huang

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