* [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).