* [PATCH v2 0/4] Add USB2.0 PHY and USB3.0 PHY support for SpacemiT K1
@ 2025-04-18 13:19 Ze Huang
2025-04-18 13:19 ` [PATCH v2 1/4] dt-bindings: phy: spacemit: add K1 USB2 PHY Ze Huang
` (3 more replies)
0 siblings, 4 replies; 11+ messages in thread
From: Ze Huang @ 2025-04-18 13:19 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
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 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 | 251 +++++++++++++++++++++
drivers/phy/spacemit/phy-k1-usb2.c | 131 +++++++++++
8 files changed, 520 insertions(+)
---
base-commit: 64e9fdfc89a76fed38d8ddeed72d42ec71957ed9
change-id: 20250417-b4-k1-usb3-phy-v2-fb1e41849049
prerequisite-message-id: <20250416135406.16284-1-heylenay@4d2.org>
prerequisite-patch-id: 19b7f061557b184b9565e10ccfc0aab5754dfa73
prerequisite-patch-id: a56183c8b71a141ca6f5d401b67a5456f40d4a9c
prerequisite-patch-id: a4a3c44d4c3e44f5209bff2b2bd0b49cd5a9eebe
prerequisite-patch-id: 471fe02daa5297e85e9cee8dfef873375a348e9f
prerequisite-patch-id: 717bc3d50f0924f7697312cb78280b15a029ce2c
prerequisite-patch-id: 585a2a9ce37a5e2a036f7351ff8ff4ed859bbe3e
prerequisite-message-id: <20250414191715.2264758-1-elder@riscstar.com>
prerequisite-patch-id: a7769b6451bfd80d5e5366013753c5fc870b2255
prerequisite-patch-id: 8a8d0eefd0b4423d87f3c093b451a0fa60622ec4
prerequisite-patch-id: 30f92f93e5b3577bde61424303f21c709a715ec5
prerequisite-patch-id: d774b8281b5c6a822445365ee94925e1ab6c7a93
prerequisite-patch-id: 54a4f5d065eb9f212fd99efec6e7e06abbb9bad8
prerequisite-patch-id: db30b8a180a5f04f499d851384d4a7f95ccb00b3
prerequisite-patch-id: 5f53f8bf16fb067628092daebc4831293261aa01
Best regards,
--
Ze Huang <huangze@whut.edu.cn>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2 1/4] dt-bindings: phy: spacemit: add K1 USB2 PHY
2025-04-18 13:19 [PATCH v2 0/4] Add USB2.0 PHY and USB3.0 PHY support for SpacemiT K1 Ze Huang
@ 2025-04-18 13:19 ` Ze Huang
2025-04-18 13:19 ` [PATCH v2 2/4] dt-bindings: phy: spacemit: add K1 PCIe/USB3 combo PHY Ze Huang
` (2 subsequent siblings)
3 siblings, 0 replies; 11+ messages in thread
From: Ze Huang @ 2025-04-18 13:19 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..ea999cff9c250b144dd049e5ac3c084b22bd56ea
--- /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 <huangze@whut.edu.cn>
+
+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-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 2/4] dt-bindings: phy: spacemit: add K1 PCIe/USB3 combo PHY
2025-04-18 13:19 [PATCH v2 0/4] Add USB2.0 PHY and USB3.0 PHY support for SpacemiT K1 Ze Huang
2025-04-18 13:19 ` [PATCH v2 1/4] dt-bindings: phy: spacemit: add K1 USB2 PHY Ze Huang
@ 2025-04-18 13:19 ` Ze Huang
2025-04-23 15:23 ` Rob Herring (Arm)
2025-04-18 13:19 ` [PATCH v2 3/4] phy: spacemit: support K1 USB2.0 PHY controller Ze Huang
2025-04-18 13:19 ` [PATCH v2 4/4] phy: spacemit: add USB3 support for K1 PCIe/USB3 combo PHY Ze Huang
3 siblings, 1 reply; 11+ messages in thread
From: Ze Huang @ 2025-04-18 13:19 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.
Co-developed-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..3c2e7dfb34a27b5d9e0a14193d0cc1c64c16c8f5
--- /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 <huangze@whut.edu.cn>
+
+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-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 3/4] phy: spacemit: support K1 USB2.0 PHY controller
2025-04-18 13:19 [PATCH v2 0/4] Add USB2.0 PHY and USB3.0 PHY support for SpacemiT K1 Ze Huang
2025-04-18 13:19 ` [PATCH v2 1/4] dt-bindings: phy: spacemit: add K1 USB2 PHY Ze Huang
2025-04-18 13:19 ` [PATCH v2 2/4] dt-bindings: phy: spacemit: add K1 PCIe/USB3 combo PHY Ze Huang
@ 2025-04-18 13:19 ` Ze Huang
2025-05-14 8:51 ` Vinod Koul
2025-04-18 13:19 ` [PATCH v2 4/4] phy: spacemit: add USB3 support for K1 PCIe/USB3 combo PHY Ze Huang
3 siblings, 1 reply; 11+ messages in thread
From: Ze Huang @ 2025-04-18 13:19 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 SpacemiT K1 USB2.0 PHY.
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 | 131 +++++++++++++++++++++++++++++++++++++
5 files changed, 148 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..4a5684f3185f61f9d865b0fb52644bb280756d00
--- /dev/null
+++ b/drivers/phy/spacemit/phy-k1-usb2.c
@@ -0,0 +1,131 @@
+// 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 <huangze@whut.edu.cn>
+ */
+
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <linux/platform_device.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;
+ void __iomem *base;
+};
+
+static int spacemit_usb2phy_init(struct phy *phy)
+{
+ struct spacemit_usb2phy *sphy = phy_get_drvdata(phy);
+ void __iomem *base = sphy->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);
+ writel(USB2_PHY_REG26_VAL, base + USB2_PHY_REG26); /* 24M ref clk */
+
+ ret = read_poll_timeout(readl, val, (val & USB2_PHY_REG01_PLL_IS_READY),
+ 500, USB2D_CTRL_RESET_TIME_MS * 1000, true,
+ base + USB2_PHY_REG01);
+ if (ret) {
+ dev_err(&phy->dev, "wait PHY_REG01[PLLREADY] timeout\n");
+ return ret;
+ }
+
+ /* release usb2 phy internal reset and enable clock gating */
+ writel(USB2_PHY_REG01_VAL, base + USB2_PHY_REG01);
+ writel(USB2_PHY_REG0D_VAL, base + USB2_PHY_REG0D);
+
+ /* auto clear host disc */
+ val = readl(base + USB2_PHY_REG04);
+ val |= USB2_PHY_REG04_AUTO_CLEAR_DIS;
+ writel(val, base + USB2_PHY_REG04);
+
+ 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;
+
+ 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");
+
+ sphy->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(sphy->base))
+ return PTR_ERR(sphy->base);
+
+ 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", },
+ { /* sentinal */ }
+};
+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-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 4/4] phy: spacemit: add USB3 support for K1 PCIe/USB3 combo PHY
2025-04-18 13:19 [PATCH v2 0/4] Add USB2.0 PHY and USB3.0 PHY support for SpacemiT K1 Ze Huang
` (2 preceding siblings ...)
2025-04-18 13:19 ` [PATCH v2 3/4] phy: spacemit: support K1 USB2.0 PHY controller Ze Huang
@ 2025-04-18 13:19 ` Ze Huang
2025-05-14 8:53 ` Vinod Koul
2025-05-14 13:06 ` Philipp Zabel
3 siblings, 2 replies; 11+ messages in thread
From: Ze Huang @ 2025-04-18 13:19 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 USB 3.0 mode on the K1 PCIe/USB3 combo PHY. Currently,
only USB mode is supported; PCIe support is not included in this change.
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 | 251 ++++++++++++++++++++++++++++++++++
3 files changed, 260 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..a291b7a78fae2f4072b74c1d2cc65847ed821bec
--- /dev/null
+++ b/drivers/phy/spacemit/phy-k1-combphy.c
@@ -0,0 +1,251 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SpacemiT K1 PCIE/USB3 PHY driver
+ *
+ * Copyright (C) 2025 SpacemiT (Hangzhou) Technology Co. Ltd
+ * Copyright (C) 2025 Ze Huang <huangze@whut.edu.cn>
+ */
+
+#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/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 BIT(3)
+#define COMBPHY_WAIT_TIMEOUT 1000
+
+struct spacemit_combphy_priv {
+ struct device *dev;
+ struct phy *phy;
+ struct reset_control *phy_rst;
+ void __iomem *phy_ctrl;
+ void __iomem *phy_sel;
+ bool rx_always_on;
+ u8 lfps_threshold;
+ u8 type;
+};
+
+static void spacemit_reg_update(void __iomem *reg, u32 offset, u32 mask, u32 val)
+{
+ u32 tmp;
+
+ tmp = readl(reg + offset);
+ tmp = (tmp & ~(mask)) | val;
+ writel(tmp, reg + offset);
+}
+
+static int spacemit_combphy_wait_ready(struct spacemit_combphy_priv *priv,
+ u32 offset, u32 mask, u32 val)
+{
+ u32 reg_val;
+ int ret = 0;
+
+ ret = read_poll_timeout(readl, reg_val, (reg_val & mask) == val,
+ 1000, COMBPHY_WAIT_TIMEOUT * 1000, false,
+ priv->phy_ctrl + offset);
+
+ return ret;
+}
+
+static int spacemit_combphy_set_mode(struct spacemit_combphy_priv *priv)
+{
+ int ret = 0;
+
+ switch (priv->type) {
+ case PHY_TYPE_USB3:
+ spacemit_reg_update(priv->phy_sel, 0, 0, COMBPHY_MODE_SEL);
+ 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)
+{
+ void __iomem *base = priv->phy_ctrl;
+ int ret;
+
+ writel(COMBPHY_USB_REG1_VAL, base + COMBPHY_USB_REG1);
+ writel(COMBPHY_USB_REG2_VAL, base + COMBPHY_USB_REG2);
+ writel(COMBPHY_USB_REG3_VAL, base + COMBPHY_USB_REG3);
+ writel(COMBPHY_USB_REG4_VAL, base + COMBPHY_USB_REG4);
+
+ ret = spacemit_combphy_wait_ready(priv, COMBPHY_USB_PLL_REG,
+ COMBPHY_USB_PLL_MASK,
+ COMBPHY_USB_PLL_VAL);
+
+ dev_dbg(priv->dev, "USB3 PHY init lfps threshold %d\n", priv->lfps_threshold);
+ spacemit_reg_update(base, COMBPHY_USB_LFPS_REG,
+ COMBPHY_USB_LFPS_MASK,
+ (priv->lfps_threshold << 8));
+
+ if (priv->rx_always_on)
+ spacemit_reg_update(base, COMBPHY_USB_REG4,
+ COMBPHY_USB_TERM_SHORT_MASK,
+ COMBPHY_USB_TERM_SHORT_VAL);
+
+ if (ret)
+ dev_err(priv->dev, "USB3 PHY init timeout!\n");
+
+ 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;
+ struct phy_provider *phy_provider;
+ struct device *dev = &pdev->dev;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->phy_ctrl = devm_platform_ioremap_resource_byname(pdev, "ctrl");
+ if (IS_ERR(priv->phy_ctrl))
+ return PTR_ERR(priv->phy_ctrl);
+
+ priv->phy_sel = devm_platform_ioremap_resource_byname(pdev, "sel");
+ if (IS_ERR(priv->phy_sel))
+ return PTR_ERR(priv->phy_sel);
+
+ 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(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-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v2 2/4] dt-bindings: phy: spacemit: add K1 PCIe/USB3 combo PHY
2025-04-18 13:19 ` [PATCH v2 2/4] dt-bindings: phy: spacemit: add K1 PCIe/USB3 combo PHY Ze Huang
@ 2025-04-23 15:23 ` Rob Herring (Arm)
0 siblings, 0 replies; 11+ messages in thread
From: Rob Herring (Arm) @ 2025-04-23 15:23 UTC (permalink / raw)
To: Ze Huang
Cc: linux-phy, linux-riscv, Junzhong Pan, Vinod Koul, Philipp Zabel,
linux-kernel, Yixun Lan, devicetree, Krzysztof Kozlowski,
Conor Dooley, Kishon Vijay Abraham I, spacemit
On Fri, 18 Apr 2025 21:19:51 +0800, 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.
>
> Co-developed-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(+)
>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 3/4] phy: spacemit: support K1 USB2.0 PHY controller
2025-04-18 13:19 ` [PATCH v2 3/4] phy: spacemit: support K1 USB2.0 PHY controller Ze Huang
@ 2025-05-14 8:51 ` Vinod Koul
2025-05-14 11:54 ` Ze Huang
0 siblings, 1 reply; 11+ messages in thread
From: Vinod Koul @ 2025-05-14 8:51 UTC (permalink / raw)
To: Ze Huang
Cc: Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yixun Lan, Philipp Zabel, linux-phy, devicetree,
linux-riscv, spacemit, linux-kernel
Hi,
On 18-04-25, 21:19, Ze Huang wrote:
> Add support for SpacemiT K1 USB2.0 PHY.
Can you please add more details of this device, which SoC is this, and
what are the capablities of this phy
>
> 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 | 131 +++++++++++++++++++++++++++++++++++++
> 5 files changed, 148 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..4a5684f3185f61f9d865b0fb52644bb280756d00
> --- /dev/null
> +++ b/drivers/phy/spacemit/phy-k1-usb2.c
> @@ -0,0 +1,131 @@
> +// 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 <huangze@whut.edu.cn>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/iopoll.h>
> +#include <linux/platform_device.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
What are these values referred to, why are you defining fixed values for
driver to use and not set the register bits?
> +
> +#define USB2D_CTRL_RESET_TIME_MS 50
> +
> +struct spacemit_usb2phy {
> + struct phy *phy;
> + struct clk *clk;
> + void __iomem *base;
> +};
> +
> +static int spacemit_usb2phy_init(struct phy *phy)
> +{
> + struct spacemit_usb2phy *sphy = phy_get_drvdata(phy);
> + void __iomem *base = sphy->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);
> + writel(USB2_PHY_REG26_VAL, base + USB2_PHY_REG26); /* 24M ref clk */
> +
> + ret = read_poll_timeout(readl, val, (val & USB2_PHY_REG01_PLL_IS_READY),
> + 500, USB2D_CTRL_RESET_TIME_MS * 1000, true,
> + base + USB2_PHY_REG01);
> + if (ret) {
> + dev_err(&phy->dev, "wait PHY_REG01[PLLREADY] timeout\n");
> + return ret;
> + }
> +
> + /* release usb2 phy internal reset and enable clock gating */
> + writel(USB2_PHY_REG01_VAL, base + USB2_PHY_REG01);
> + writel(USB2_PHY_REG0D_VAL, base + USB2_PHY_REG0D);
> +
> + /* auto clear host disc */
> + val = readl(base + USB2_PHY_REG04);
> + val |= USB2_PHY_REG04_AUTO_CLEAR_DIS;
> + writel(val, base + USB2_PHY_REG04);
> +
> + 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;
> +
> + 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");
> +
> + sphy->base = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(sphy->base))
> + return PTR_ERR(sphy->base);
> +
> + 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", },
> + { /* sentinal */ }
> +};
> +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-phy mailing list
> linux-phy@lists.infradead.org
> https://lists.infradead.org/mailman/listinfo/linux-phy
--
~Vinod
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 4/4] phy: spacemit: add USB3 support for K1 PCIe/USB3 combo PHY
2025-04-18 13:19 ` [PATCH v2 4/4] phy: spacemit: add USB3 support for K1 PCIe/USB3 combo PHY Ze Huang
@ 2025-05-14 8:53 ` Vinod Koul
2025-05-14 12:00 ` Ze Huang
2025-05-14 13:06 ` Philipp Zabel
1 sibling, 1 reply; 11+ messages in thread
From: Vinod Koul @ 2025-05-14 8:53 UTC (permalink / raw)
To: Ze Huang
Cc: Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yixun Lan, Philipp Zabel, linux-phy, devicetree,
linux-riscv, spacemit, linux-kernel
On 18-04-25, 21:19, Ze Huang wrote:
> Add support for USB 3.0 mode on the K1 PCIe/USB3 combo PHY. Currently,
> only USB mode is supported; PCIe support is not included in this change.
>
> 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 | 251 ++++++++++++++++++++++++++++++++++
> 3 files changed, 260 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..a291b7a78fae2f4072b74c1d2cc65847ed821bec
> --- /dev/null
> +++ b/drivers/phy/spacemit/phy-k1-combphy.c
> @@ -0,0 +1,251 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * SpacemiT K1 PCIE/USB3 PHY driver
> + *
> + * Copyright (C) 2025 SpacemiT (Hangzhou) Technology Co. Ltd
> + * Copyright (C) 2025 Ze Huang <huangze@whut.edu.cn>
> + */
> +
> +#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/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
Same comment as other patch
> +
> +#define COMBPHY_MODE_SEL BIT(3)
> +#define COMBPHY_WAIT_TIMEOUT 1000
> +
> +struct spacemit_combphy_priv {
> + struct device *dev;
> + struct phy *phy;
> + struct reset_control *phy_rst;
> + void __iomem *phy_ctrl;
> + void __iomem *phy_sel;
> + bool rx_always_on;
> + u8 lfps_threshold;
> + u8 type;
> +};
> +
> +static void spacemit_reg_update(void __iomem *reg, u32 offset, u32 mask, u32 val)
> +{
> + u32 tmp;
> +
> + tmp = readl(reg + offset);
> + tmp = (tmp & ~(mask)) | val;
> + writel(tmp, reg + offset);
> +}
> +
> +static int spacemit_combphy_wait_ready(struct spacemit_combphy_priv *priv,
> + u32 offset, u32 mask, u32 val)
> +{
> + u32 reg_val;
> + int ret = 0;
Superfluous init, drop it pls
> +
> + ret = read_poll_timeout(readl, reg_val, (reg_val & mask) == val,
> + 1000, COMBPHY_WAIT_TIMEOUT * 1000, false,
> + priv->phy_ctrl + offset);
> +
> + return ret;
why use local variable?
> +}
> +
> +static int spacemit_combphy_set_mode(struct spacemit_combphy_priv *priv)
> +{
> + int ret = 0;
> +
> + switch (priv->type) {
> + case PHY_TYPE_USB3:
> + spacemit_reg_update(priv->phy_sel, 0, 0, COMBPHY_MODE_SEL);
> + 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)
> +{
> + void __iomem *base = priv->phy_ctrl;
> + int ret;
> +
> + writel(COMBPHY_USB_REG1_VAL, base + COMBPHY_USB_REG1);
> + writel(COMBPHY_USB_REG2_VAL, base + COMBPHY_USB_REG2);
> + writel(COMBPHY_USB_REG3_VAL, base + COMBPHY_USB_REG3);
> + writel(COMBPHY_USB_REG4_VAL, base + COMBPHY_USB_REG4);
> +
> + ret = spacemit_combphy_wait_ready(priv, COMBPHY_USB_PLL_REG,
> + COMBPHY_USB_PLL_MASK,
> + COMBPHY_USB_PLL_VAL);
> +
> + dev_dbg(priv->dev, "USB3 PHY init lfps threshold %d\n", priv->lfps_threshold);
> + spacemit_reg_update(base, COMBPHY_USB_LFPS_REG,
> + COMBPHY_USB_LFPS_MASK,
> + (priv->lfps_threshold << 8));
> +
> + if (priv->rx_always_on)
> + spacemit_reg_update(base, COMBPHY_USB_REG4,
> + COMBPHY_USB_TERM_SHORT_MASK,
> + COMBPHY_USB_TERM_SHORT_VAL);
> +
> + if (ret)
> + dev_err(priv->dev, "USB3 PHY init timeout!\n");
> +
> + 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;
> + struct phy_provider *phy_provider;
> + struct device *dev = &pdev->dev;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->phy_ctrl = devm_platform_ioremap_resource_byname(pdev, "ctrl");
> + if (IS_ERR(priv->phy_ctrl))
> + return PTR_ERR(priv->phy_ctrl);
> +
> + priv->phy_sel = devm_platform_ioremap_resource_byname(pdev, "sel");
> + if (IS_ERR(priv->phy_sel))
> + return PTR_ERR(priv->phy_sel);
> +
> + 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(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");
Could this be single driver with different init register sequences?
>
> --
> 2.49.0
--
~Vinod
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 3/4] phy: spacemit: support K1 USB2.0 PHY controller
2025-05-14 8:51 ` Vinod Koul
@ 2025-05-14 11:54 ` Ze Huang
0 siblings, 0 replies; 11+ messages in thread
From: Ze Huang @ 2025-05-14 11:54 UTC (permalink / raw)
To: Vinod Koul
Cc: Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yixun Lan, Philipp Zabel, linux-phy, devicetree,
linux-riscv, spacemit, linux-kernel
On 5/14/25 4:51 PM, Vinod Koul wrote:
> Hi,
>
> On 18-04-25, 21:19, Ze Huang wrote:
>> Add support for SpacemiT K1 USB2.0 PHY.
> Can you please add more details of this device, which SoC is this, and
> what are the capablities of this phy
Hi, Vinod, thank you for the comments!
How about these:
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 | 131 +++++++++++++++++++++++++++++++++++++
>> 5 files changed, 148 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..4a5684f3185f61f9d865b0fb52644bb280756d00
>> --- /dev/null
>> +++ b/drivers/phy/spacemit/phy-k1-usb2.c
>> @@ -0,0 +1,131 @@
>> +// 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 <huangze@whut.edu.cn>
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/iopoll.h>
>> +#include <linux/platform_device.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
> What are these values referred to, why are you defining fixed values for
> driver to use and not set the register bits?
At the moment, documentation[1] for the USB2.0/USB3.0 PHY is
incomplete and does not include detailed register definitions.
The fixed values here are derived from the vendor driver and
reflect the required initialization for the PHY to operate correctly on K1.
Link:
https://developer.spacemit.com/documentation?token=AjHDwrW78igAAEkiHracBI9HnTb
[1]
>> +
>> +#define USB2D_CTRL_RESET_TIME_MS 50
>> +
>> +struct spacemit_usb2phy {
>> + struct phy *phy;
>> + struct clk *clk;
>> + void __iomem *base;
>> +};
>> +
>> +static int spacemit_usb2phy_init(struct phy *phy)
>> +{
>> + struct spacemit_usb2phy *sphy = phy_get_drvdata(phy);
>> + void __iomem *base = sphy->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);
>> + writel(USB2_PHY_REG26_VAL, base + USB2_PHY_REG26); /* 24M ref clk */
>> +
>> + ret = read_poll_timeout(readl, val, (val & USB2_PHY_REG01_PLL_IS_READY),
>> + 500, USB2D_CTRL_RESET_TIME_MS * 1000, true,
>> + base + USB2_PHY_REG01);
>> + if (ret) {
>> + dev_err(&phy->dev, "wait PHY_REG01[PLLREADY] timeout\n");
>> + return ret;
>> + }
>> +
>> + /* release usb2 phy internal reset and enable clock gating */
>> + writel(USB2_PHY_REG01_VAL, base + USB2_PHY_REG01);
>> + writel(USB2_PHY_REG0D_VAL, base + USB2_PHY_REG0D);
>> +
>> + /* auto clear host disc */
>> + val = readl(base + USB2_PHY_REG04);
>> + val |= USB2_PHY_REG04_AUTO_CLEAR_DIS;
>> + writel(val, base + USB2_PHY_REG04);
>> +
>> + 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;
>> +
>> + 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");
>> +
>> + sphy->base = devm_platform_ioremap_resource(pdev, 0);
>> + if (IS_ERR(sphy->base))
>> + return PTR_ERR(sphy->base);
>> +
>> + 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", },
>> + { /* sentinal */ }
>> +};
>> +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-phy mailing list
>> linux-phy@lists.infradead.org
>> https://lists.infradead.org/mailman/listinfo/linux-phy
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 4/4] phy: spacemit: add USB3 support for K1 PCIe/USB3 combo PHY
2025-05-14 8:53 ` Vinod Koul
@ 2025-05-14 12:00 ` Ze Huang
0 siblings, 0 replies; 11+ messages in thread
From: Ze Huang @ 2025-05-14 12:00 UTC (permalink / raw)
To: Vinod Koul
Cc: Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yixun Lan, Philipp Zabel, linux-phy, devicetree,
linux-riscv, spacemit, linux-kernel
On 5/14/25 4:53 PM, Vinod Koul wrote:
> On 18-04-25, 21:19, Ze Huang wrote:
>> Add support for USB 3.0 mode on the K1 PCIe/USB3 combo PHY. Currently,
>> only USB mode is supported; PCIe support is not included in this change.
>>
>> Signed-off-by: Ze Huang <huangze@whut.edu.cn>
>> ---
...
>> +#define COMBPHY_USB_LFPS_REG 0x58
>> +#define COMBPHY_USB_LFPS_MASK 0x700
>> +#define COMBPHY_USB_LFPS_THRES_DEFAULT 0x03
> Same comment as other patch
>> +
>> +#define COMBPHY_MODE_SEL BIT(3)
>> +#define COMBPHY_WAIT_TIMEOUT 1000
>> +
>> +struct spacemit_combphy_priv {
>> + struct device *dev;
>> + struct phy *phy;
>> + struct reset_control *phy_rst;
>> + void __iomem *phy_ctrl;
>> + void __iomem *phy_sel;
>> + bool rx_always_on;
>> + u8 lfps_threshold;
>> + u8 type;
>> +};
>> +
>> +static void spacemit_reg_update(void __iomem *reg, u32 offset, u32 mask, u32 val)
>> +{
>> + u32 tmp;
>> +
>> + tmp = readl(reg + offset);
>> + tmp = (tmp & ~(mask)) | val;
>> + writel(tmp, reg + offset);
>> +}
>> +
>> +static int spacemit_combphy_wait_ready(struct spacemit_combphy_priv *priv,
>> + u32 offset, u32 mask, u32 val)
>> +{
>> + u32 reg_val;
>> + int ret = 0;
> Superfluous init, drop it pls
OK
>
>> +
>> + ret = read_poll_timeout(readl, reg_val, (reg_val & mask) == val,
>> + 1000, COMBPHY_WAIT_TIMEOUT * 1000, false,
>> + priv->phy_ctrl + offset);
>> +
>> + return ret;
> why use local variable?
Will drop it.
>
>> +}
>> +
>> +static int spacemit_combphy_set_mode(struct spacemit_combphy_priv *priv)
>> +{
>> + int ret = 0;
>> +
>> + switch (priv->type) {
>> + case PHY_TYPE_USB3:
>> + spacemit_reg_update(priv->phy_sel, 0, 0, COMBPHY_MODE_SEL);
>> + break;
>> + default:
>> + dev_err(priv->dev, "PHY type %x not supported\n", priv->type);
>> + ret = -EINVAL;
>> + break;
>> + }
>> +
>> + return ret;
>> +}
...
>> +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");
> Could this be single driver with different init register sequences?
Yes, on K1 SoC, the USB3 and PCIe Port A share the same COMBO PHY hardware.
PHY can be initialized for PCIe as well via a different init sequence.
In the future, we can extend the driver to support both modes based on
the DT property.
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 4/4] phy: spacemit: add USB3 support for K1 PCIe/USB3 combo PHY
2025-04-18 13:19 ` [PATCH v2 4/4] phy: spacemit: add USB3 support for K1 PCIe/USB3 combo PHY Ze Huang
2025-05-14 8:53 ` Vinod Koul
@ 2025-05-14 13:06 ` Philipp Zabel
1 sibling, 0 replies; 11+ messages in thread
From: Philipp Zabel @ 2025-05-14 13:06 UTC (permalink / raw)
To: Ze Huang, Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Yixun Lan
Cc: linux-phy, devicetree, linux-riscv, spacemit, linux-kernel
On Fr, 2025-04-18 at 21:19 +0800, Ze Huang wrote:
> Add support for USB 3.0 mode on the K1 PCIe/USB3 combo PHY. Currently,
> only USB mode is supported; PCIe support is not included in this change.
>
> 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 | 251 ++++++++++++++++++++++++++++++++++
> 3 files changed, 260 insertions(+)
>
[...]
> diff --git a/drivers/phy/spacemit/phy-k1-combphy.c b/drivers/phy/spacemit/phy-k1-combphy.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..a291b7a78fae2f4072b74c1d2cc65847ed821bec
> --- /dev/null
> +++ b/drivers/phy/spacemit/phy-k1-combphy.c
> @@ -0,0 +1,251 @@
[...]
> +static int spacemit_combphy_probe(struct platform_device *pdev)
> +{
> + struct spacemit_combphy_priv *priv;
> + struct phy_provider *phy_provider;
> + struct device *dev = &pdev->dev;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->phy_ctrl = devm_platform_ioremap_resource_byname(pdev, "ctrl");
> + if (IS_ERR(priv->phy_ctrl))
> + return PTR_ERR(priv->phy_ctrl);
> +
> + priv->phy_sel = devm_platform_ioremap_resource_byname(pdev, "sel");
> + if (IS_ERR(priv->phy_sel))
> + return PTR_ERR(priv->phy_sel);
> +
> + 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(dev, NULL);
Please use devm_reset_control_get_exclusive() directly.
regards
Philipp
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2025-05-14 14:04 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-18 13:19 [PATCH v2 0/4] Add USB2.0 PHY and USB3.0 PHY support for SpacemiT K1 Ze Huang
2025-04-18 13:19 ` [PATCH v2 1/4] dt-bindings: phy: spacemit: add K1 USB2 PHY Ze Huang
2025-04-18 13:19 ` [PATCH v2 2/4] dt-bindings: phy: spacemit: add K1 PCIe/USB3 combo PHY Ze Huang
2025-04-23 15:23 ` Rob Herring (Arm)
2025-04-18 13:19 ` [PATCH v2 3/4] phy: spacemit: support K1 USB2.0 PHY controller Ze Huang
2025-05-14 8:51 ` Vinod Koul
2025-05-14 11:54 ` Ze Huang
2025-04-18 13:19 ` [PATCH v2 4/4] phy: spacemit: add USB3 support for K1 PCIe/USB3 combo PHY Ze Huang
2025-05-14 8:53 ` Vinod Koul
2025-05-14 12:00 ` Ze Huang
2025-05-14 13:06 ` Philipp Zabel
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).