* [PATCH v3 1/4] dt-bindings: phy: Add Canaan K230 USB PHY
2026-01-19 9:38 [PATCH v3 0/4] Add USB support for Canaan K230 Jiayu Du
@ 2026-01-19 9:38 ` Jiayu Du
2026-01-19 9:38 ` [PATCH v3 2/4] dt-bindings: usb: dwc2: Add support for Canaan K230 SoC Jiayu Du
` (3 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Jiayu Du @ 2026-01-19 9:38 UTC (permalink / raw)
To: vkoul, gregkh, conor
Cc: neil.armstrong, robh, krzk+dt, pjw, palmer, aou, alex,
jiayu.riscv, linux-phy, linux-usb, devicetree, linux-riscv,
linux-kernel
K230 SoC USB PHY requires configuring registers for control and
configuration. Add USB phy bindings for K230 SoC.
Signed-off-by: Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn>
---
.../bindings/phy/canaan,k230-usb-phy.yaml | 35 +++++++++++++++++++
1 file changed, 35 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/canaan,k230-usb-phy.yaml
diff --git a/Documentation/devicetree/bindings/phy/canaan,k230-usb-phy.yaml b/Documentation/devicetree/bindings/phy/canaan,k230-usb-phy.yaml
new file mode 100644
index 000000000000..b959b381c44c
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/canaan,k230-usb-phy.yaml
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/canaan,k230-usb-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Canaan K230 USB2.0 PHY
+
+maintainers:
+ - Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn>
+
+properties:
+ compatible:
+ const: canaan,k230-usb-phy
+
+ reg:
+ maxItems: 1
+
+ "#phy-cells":
+ const: 1
+
+required:
+ - compatible
+ - reg
+ - "#phy-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ usbphy: usb-phy@91585000 {
+ compatible = "canaan,k230-usb-phy";
+ reg = <0x91585000 0x400>;
+ #phy-cells = <1>;
+ };
--
2.52.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v3 3/4] phy: usb: Add driver for Canaan K230 USB 2.0 PHY
2026-01-19 9:38 [PATCH v3 0/4] Add USB support for Canaan K230 Jiayu Du
2026-01-19 9:38 ` [PATCH v3 1/4] dt-bindings: phy: Add Canaan K230 USB PHY Jiayu Du
2026-01-19 9:38 ` [PATCH v3 2/4] dt-bindings: usb: dwc2: Add support for Canaan K230 SoC Jiayu Du
@ 2026-01-19 9:38 ` Jiayu Du
2026-01-19 9:38 ` [PATCH v3 4/4] riscv: dts: canaan: Add syscon and USB nodes for K230 Jiayu Du
2026-01-19 16:07 ` [PATCH v3 0/4] Add USB support for Canaan K230 Jiayu Du
4 siblings, 0 replies; 10+ messages in thread
From: Jiayu Du @ 2026-01-19 9:38 UTC (permalink / raw)
To: vkoul, gregkh, conor
Cc: neil.armstrong, robh, krzk+dt, pjw, palmer, aou, alex,
jiayu.riscv, linux-phy, linux-usb, devicetree, linux-riscv,
linux-kernel
Add driver for the USB 2.0 PHY in Canaan K230 SoC, which supports PHY
initialization and power management.
Add Kconfig/Makefile under drivers/phy/canaan/.
Signed-off-by: Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn>
---
drivers/phy/Kconfig | 1 +
drivers/phy/Makefile | 1 +
drivers/phy/canaan/Kconfig | 14 ++
drivers/phy/canaan/Makefile | 2 +
drivers/phy/canaan/phy-k230-usb.c | 283 ++++++++++++++++++++++++++++++
5 files changed, 301 insertions(+)
create mode 100644 drivers/phy/canaan/Kconfig
create mode 100644 drivers/phy/canaan/Makefile
create mode 100644 drivers/phy/canaan/phy-k230-usb.c
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 142e7b0ef2ef..e37bcceef65a 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -150,6 +150,7 @@ source "drivers/phy/amlogic/Kconfig"
source "drivers/phy/apple/Kconfig"
source "drivers/phy/broadcom/Kconfig"
source "drivers/phy/cadence/Kconfig"
+source "drivers/phy/canaan/Kconfig"
source "drivers/phy/freescale/Kconfig"
source "drivers/phy/hisilicon/Kconfig"
source "drivers/phy/ingenic/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index dcbb060c8207..8cef0a447986 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -22,6 +22,7 @@ obj-y += allwinner/ \
apple/ \
broadcom/ \
cadence/ \
+ canaan/ \
freescale/ \
hisilicon/ \
ingenic/ \
diff --git a/drivers/phy/canaan/Kconfig b/drivers/phy/canaan/Kconfig
new file mode 100644
index 000000000000..1ff8831846d5
--- /dev/null
+++ b/drivers/phy/canaan/Kconfig
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Phy drivers for Canaan platforms
+#
+config PHY_CANAAN_USB
+ tristate "Canaan USB2 PHY Driver"
+ depends on (ARCH_CANAAN || COMPILE_TEST) && OF
+ select GENERIC_PHY
+ help
+ Enable this driver to support the USB 2.0 PHY controller
+ on Canaan K230 RISC-V SoCs. This PHY controller
+ provides physical layer functionality for USB 2.0 devices.
+ If you have a Canaan K230 board and need USB 2.0 support,
+ say Y or M here.
diff --git a/drivers/phy/canaan/Makefile b/drivers/phy/canaan/Makefile
new file mode 100644
index 000000000000..d73857ba284e
--- /dev/null
+++ b/drivers/phy/canaan/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_PHY_CANAAN_USB) += phy-k230-usb.o
diff --git a/drivers/phy/canaan/phy-k230-usb.c b/drivers/phy/canaan/phy-k230-usb.c
new file mode 100644
index 000000000000..350950563f60
--- /dev/null
+++ b/drivers/phy/canaan/phy-k230-usb.c
@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Canaan usb PHY driver
+ *
+ * Copyright (C) 2025 Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+#define MAX_PHYS 2
+
+/* Register offsets within the HiSysConfig system controller */
+#define K230_USB0_TEST_REG_BASE 0x70
+#define K230_USB0_CTL_REG_BASE 0xb0
+#define K230_USB1_TEST_REG_BASE 0x90
+#define K230_USB1_CTL_REG_BASE 0xb8
+
+/* Relative offsets within each PHY's control/test block */
+#define CTL0_OFFSET 0x00
+#define CTL1_OFFSET 0x04
+#define TEST_CTL3_OFFSET 0x0c
+
+/* Bit definitions for TEST_CTL3 */
+#define USB_IDPULLUP0 BIT(4)
+#define USB_DMPULLDOWN0 BIT(8)
+#define USB_DPPULLDOWN0 BIT(9)
+
+/* USB control register 0 in HiSysConfig system controller */
+/* PLL Integral Path Tune */
+#define USB_CTL0_PLLITUNE_MASK GENMASK(23, 22)
+
+/* PLL Proportional Path Tune */
+#define USB_CTL0_PLLPTUNE_MASK GENMASK(21, 18)
+
+/* PLL Bandwidth Adjustment */
+#define USB_CTL0_PLLBTUNE_MASK GENMASK(17, 17)
+
+/* VReg18 Bypass Control */
+#define USB_CTL0_VREGBYPASS_MASK GENMASK(16, 16)
+
+/* Retention Mode Enable */
+#define USB_CTL0_RETENABLEN_MASK GENMASK(15, 15)
+
+/* Reserved Request Input */
+#define USB_CTL0_RESREQIN_MASK GENMASK(14, 14)
+
+/* External VBUS Valid Select */
+#define USB_CTL0_VBUSVLDEXTSEL0_MASK GENMASK(13, 13)
+
+/* OTG Block Disable Control */
+#define USB_CTL0_OTGDISABLE0_MASK GENMASK(12, 12)
+
+/* Drive VBUS Enable */
+#define USB_CTL0_DRVVBUS0_MASK GENMASK(11, 11)
+
+/* Autoresume Mode Enable */
+#define USB_CTL0_AUTORSMENB0_MASK GENMASK(10, 10)
+
+/* HS Transceiver Asynchronous Control */
+#define USB_CTL0_HSXCVREXTCTL0_MASK GENMASK(9, 9)
+
+/* USB 1.1 Transmit Data */
+#define USB_CTL0_FSDATAEXT0_MASK GENMASK(8, 8)
+
+/* USB 1.1 SE0 Generation */
+#define USB_CTL0_FSSE0EXT0_MASK GENMASK(7, 7)
+
+/* USB 1.1 Data Enable */
+#define USB_CTL0_TXENABLEN0_MASK GENMASK(6, 6)
+
+/* Disconnect Threshold */
+#define USB_CTL0_COMPDISTUNE0_MASK GENMASK(5, 3)
+
+/* Squelch Threshold */
+#define USB_CTL0_SQRXTUNE0_MASK GENMASK(2, 0)
+
+/* USB control register 1 in HiSysConfig system controller */
+/* Data Detect Voltage */
+#define USB_CTL1_VDATREFTUNE0_MASK GENMASK(23, 22)
+
+/* VBUS Valid Threshold */
+#define USB_CTL1_OTGTUNE0_MASK GENMASK(21, 19)
+
+/* Transmitter High-Speed Crossover */
+#define USB_CTL1_TXHSXVTUNE0_MASK GENMASK(18, 17)
+
+/* FS/LS Source Impedance */
+#define USB_CTL1_TXFSLSTUNE0_MASK GENMASK(16, 13)
+
+/* HS DC Voltage Level */
+#define USB_CTL1_TXVREFTUNE0_MASK GENMASK(12, 9)
+
+/* HS Transmitter Rise/Fall Time */
+#define USB_CTL1_TXRISETUNE0_MASK GENMASK(8, 7)
+
+/* USB Source Impedance */
+#define USB_CTL1_TXRESTUNE0_MASK GENMASK(6, 5)
+
+/* HS Transmitter Pre-Emphasis Current Control */
+#define USB_CTL1_TXPREEMPAMPTUNE0_MASK GENMASK(4, 3)
+
+/* HS Transmitter Pre-Emphasis Duration Control */
+#define USB_CTL1_TXPREEMPPULSETUNE0_MASK GENMASK(2, 2)
+
+/* charging detection */
+#define USB_CTL1_CHRGSRCPUENB0_MASK GENMASK(1, 0)
+
+#define K230_PHY_CTL0_VAL \
+( \
+ FIELD_PREP(USB_CTL0_PLLITUNE_MASK, 0x0) | \
+ FIELD_PREP(USB_CTL0_PLLPTUNE_MASK, 0xc) | \
+ FIELD_PREP(USB_CTL0_PLLBTUNE_MASK, 0x1) | \
+ FIELD_PREP(USB_CTL0_VREGBYPASS_MASK, 0x1) | \
+ FIELD_PREP(USB_CTL0_RETENABLEN_MASK, 0x1) | \
+ FIELD_PREP(USB_CTL0_RESREQIN_MASK, 0x0) | \
+ FIELD_PREP(USB_CTL0_VBUSVLDEXTSEL0_MASK, 0x0) | \
+ FIELD_PREP(USB_CTL0_OTGDISABLE0_MASK, 0x0) | \
+ FIELD_PREP(USB_CTL0_DRVVBUS0_MASK, 0x1) | \
+ FIELD_PREP(USB_CTL0_AUTORSMENB0_MASK, 0x0) | \
+ FIELD_PREP(USB_CTL0_HSXCVREXTCTL0_MASK, 0x0) | \
+ FIELD_PREP(USB_CTL0_FSDATAEXT0_MASK, 0x0) | \
+ FIELD_PREP(USB_CTL0_FSSE0EXT0_MASK, 0x0) | \
+ FIELD_PREP(USB_CTL0_TXENABLEN0_MASK, 0x0) | \
+ FIELD_PREP(USB_CTL0_COMPDISTUNE0_MASK, 0x3) | \
+ FIELD_PREP(USB_CTL0_SQRXTUNE0_MASK, 0x3) \
+)
+
+#define K230_PHY_CTL1_VAL \
+( \
+ FIELD_PREP(USB_CTL1_VDATREFTUNE0_MASK, 0x1) | \
+ FIELD_PREP(USB_CTL1_OTGTUNE0_MASK, 0x3) | \
+ FIELD_PREP(USB_CTL1_TXHSXVTUNE0_MASK, 0x3) | \
+ FIELD_PREP(USB_CTL1_TXFSLSTUNE0_MASK, 0x3) | \
+ FIELD_PREP(USB_CTL1_TXVREFTUNE0_MASK, 0x3) | \
+ FIELD_PREP(USB_CTL1_TXRISETUNE0_MASK, 0x1) | \
+ FIELD_PREP(USB_CTL1_TXRESTUNE0_MASK, 0x1) | \
+ FIELD_PREP(USB_CTL1_TXPREEMPAMPTUNE0_MASK, 0x0) | \
+ FIELD_PREP(USB_CTL1_TXPREEMPPULSETUNE0_MASK, 0x0) | \
+ FIELD_PREP(USB_CTL1_CHRGSRCPUENB0_MASK, 0x0) \
+)
+
+struct k230_usb_phy_instance {
+ struct k230_usb_phy_global *global;
+ struct phy *phy;
+ u32 test_offset;
+ u32 ctl_offset;
+ int index;
+};
+
+struct k230_usb_phy_global {
+ struct k230_usb_phy_instance phys[MAX_PHYS];
+ void __iomem *base;
+};
+
+static int k230_usb_phy_power_on(struct phy *phy)
+{
+ struct k230_usb_phy_instance *inst = phy_get_drvdata(phy);
+ struct k230_usb_phy_global *global = inst->global;
+ void __iomem *base = global->base;
+ u32 val;
+ /* Apply recommended settings */
+ writel(K230_PHY_CTL0_VAL, base + inst->ctl_offset + CTL0_OFFSET);
+ writel(K230_PHY_CTL1_VAL, base + inst->ctl_offset + CTL1_OFFSET);
+
+ /* Configure test register (pull-ups/pull-downs) */
+ val = readl(base + inst->test_offset + TEST_CTL3_OFFSET);
+ val |= USB_IDPULLUP0;
+
+ if (inst->index == 1)
+ val |= (USB_DMPULLDOWN0 | USB_DPPULLDOWN0);
+ else
+ val &= ~(USB_DMPULLDOWN0 | USB_DPPULLDOWN0);
+
+ writel(val, base + inst->test_offset + TEST_CTL3_OFFSET);
+
+ return 0;
+}
+
+static int k230_usb_phy_power_off(struct phy *phy)
+{
+ struct k230_usb_phy_instance *inst = phy_get_drvdata(phy);
+ struct k230_usb_phy_global *global = inst->global;
+ void __iomem *base = global->base;
+ u32 val;
+
+ val = readl(base + inst->test_offset + TEST_CTL3_OFFSET);
+ val &= ~(USB_DMPULLDOWN0 | USB_DPPULLDOWN0);
+ writel(val, base + inst->test_offset + TEST_CTL3_OFFSET);
+
+ return 0;
+}
+
+static const struct phy_ops k230_usb_phy_ops = {
+ .power_on = k230_usb_phy_power_on,
+ .power_off = k230_usb_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static struct phy *k230_usb_phy_xlate(struct device *dev,
+ const struct of_phandle_args *args)
+{
+ struct k230_usb_phy_global *global = dev_get_drvdata(dev);
+ unsigned int idx = args->args[0];
+
+ if (idx >= MAX_PHYS)
+ return ERR_PTR(-EINVAL);
+
+ return global->phys[idx].phy;
+}
+
+static int k230_usb_phy_probe(struct platform_device *pdev)
+{
+ struct k230_usb_phy_global *global;
+ struct device *dev = &pdev->dev;
+ struct phy_provider *provider;
+ int i;
+
+ global = devm_kzalloc(dev, sizeof(*global), GFP_KERNEL);
+ if (!global)
+ return -ENOMEM;
+ dev_set_drvdata(dev, global);
+
+ global->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(global->base))
+ return dev_err_probe(dev, PTR_ERR(global->base),
+ "failed to map registers\n");
+
+ static const struct {
+ u32 test_offset;
+ u32 ctl_offset;
+ } phy_reg_info[MAX_PHYS] = {
+ [0] = { K230_USB0_TEST_REG_BASE, K230_USB0_CTL_REG_BASE },
+ [1] = { K230_USB1_TEST_REG_BASE, K230_USB1_CTL_REG_BASE },
+ };
+
+ for (i = 0; i < MAX_PHYS; i++) {
+ struct k230_usb_phy_instance *inst = &global->phys[i];
+ struct phy *phy;
+
+ inst->global = global;
+ inst->index = i;
+ inst->test_offset = phy_reg_info[i].test_offset;
+ inst->ctl_offset = phy_reg_info[i].ctl_offset;
+
+ phy = devm_phy_create(dev, NULL, &k230_usb_phy_ops);
+ if (IS_ERR(phy)) {
+ dev_err(dev, "failed to create phy%d\n", i);
+ return PTR_ERR(phy);
+ }
+
+ phy_set_drvdata(phy, inst);
+ inst->phy = phy;
+ }
+
+ provider = devm_of_phy_provider_register(dev, k230_usb_phy_xlate);
+ if (IS_ERR(provider))
+ return PTR_ERR(provider);
+
+ return 0;
+}
+
+static const struct of_device_id k230_usb_phy_of_match[] = {
+ { .compatible = "canaan,k230-usb-phy" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, k230_usb_phy_of_match);
+
+static struct platform_driver k230_usb_phy_driver = {
+ .probe = k230_usb_phy_probe,
+ .driver = {
+ .name = "k230-usb-phy",
+ .of_match_table = k230_usb_phy_of_match,
+ },
+};
+module_platform_driver(k230_usb_phy_driver);
+
+MODULE_DESCRIPTION("Canaan Kendryte K230 USB 2.0 PHY driver");
+MODULE_AUTHOR("Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn>");
+MODULE_LICENSE("GPL");
--
2.52.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v3 4/4] riscv: dts: canaan: Add syscon and USB nodes for K230
2026-01-19 9:38 [PATCH v3 0/4] Add USB support for Canaan K230 Jiayu Du
` (2 preceding siblings ...)
2026-01-19 9:38 ` [PATCH v3 3/4] phy: usb: Add driver for Canaan K230 USB 2.0 PHY Jiayu Du
@ 2026-01-19 9:38 ` Jiayu Du
2026-01-19 16:07 ` [PATCH v3 0/4] Add USB support for Canaan K230 Jiayu Du
4 siblings, 0 replies; 10+ messages in thread
From: Jiayu Du @ 2026-01-19 9:38 UTC (permalink / raw)
To: vkoul, gregkh, conor
Cc: neil.armstrong, robh, krzk+dt, pjw, palmer, aou, alex,
jiayu.riscv, linux-phy, linux-usb, devicetree, linux-riscv,
linux-kernel
Add top syscon and USB PHY subdevice nodes, USB0/USB1 dwc2 controller
to K230 DTSI, and enable UART0 and USB0/USB1 in DshanPI DT.
Signed-off-by: Jiayu Du <jiayu.riscv@isrc.iscas.ac.cn>
---
.../boot/dts/canaan/k230-canmv-dshanpi.dts | 17 +++++++++
arch/riscv/boot/dts/canaan/k230.dtsi | 35 +++++++++++++++++++
2 files changed, 52 insertions(+)
diff --git a/arch/riscv/boot/dts/canaan/k230-canmv-dshanpi.dts b/arch/riscv/boot/dts/canaan/k230-canmv-dshanpi.dts
index 4f95b534ee87..55197cfc25b4 100644
--- a/arch/riscv/boot/dts/canaan/k230-canmv-dshanpi.dts
+++ b/arch/riscv/boot/dts/canaan/k230-canmv-dshanpi.dts
@@ -80,3 +80,20 @@ &uart0 {
pinctrl-0 = <&uart0_pins>;
status = "okay";
};
+
+&usb0 {
+ vusb_d-supply = <&vdd_3v3>;
+ vusb_a-supply = <&vdd_1v8>;
+ status = "okay";
+};
+
+&usb1 {
+ dr_mode = "host";
+ vusb_d-supply = <&vdd_3v3>;
+ vusb_a-supply = <&vdd_1v8>;
+ status = "okay";
+};
+
+&usbphy {
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/canaan/k230.dtsi b/arch/riscv/boot/dts/canaan/k230.dtsi
index 8ca5c7dee427..b369b7d8dc83 100644
--- a/arch/riscv/boot/dts/canaan/k230.dtsi
+++ b/arch/riscv/boot/dts/canaan/k230.dtsi
@@ -148,5 +148,40 @@ uart4: serial@91404000 {
reg-shift = <2>;
status = "disabled";
};
+
+ usb0: usb@91500000 {
+ compatible = "canaan,k230-usb", "snps,dwc2";
+ reg = <0x0 0x91500000 0x0 0x40000>;
+ interrupts = <173 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&sysclk K230_HS_USB0_AHB_GATE>;
+ clock-names = "otg";
+ g-rx-fifo-size = <512>;
+ g-np-tx-fifo-size = <64>;
+ g-tx-fifo-size = <512 1024 64 64 64 64>;
+ phys = <&usbphy 0>;
+ phy-names = "usb2-phy";
+ status = "disabled";
+ };
+
+ usb1: usb@91540000 {
+ compatible = "canaan,k230-usb", "snps,dwc2";
+ reg = <0x0 0x91540000 0x0 0x40000>;
+ interrupts = <174 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&sysclk K230_HS_USB1_AHB_GATE>;
+ clock-names = "otg";
+ g-rx-fifo-size = <512>;
+ g-np-tx-fifo-size = <64>;
+ g-tx-fifo-size = <512 1024 64 64 64 64>;
+ phys = <&usbphy 1>;
+ phy-names = "usb2-phy";
+ status = "disabled";
+ };
+
+ usbphy: usb-phy@91585000 {
+ compatible = "canaan,k230-usb-phy";
+ reg = <0x0 0x91585000 0x0 0x400>;
+ #phy-cells = <1>;
+ status = "disabled";
+ };
};
};
--
2.52.0
^ permalink raw reply related [flat|nested] 10+ messages in thread