phy-for-7.1

- New Support
   - Qualcomm Eliza QMP UFS PHY
   - Canaan K230 USB 2.0 PHY driver
   - Mediatek mt8167 dsi-phy
   - Eswin EIC7700 SATA PHY driver
 
 - Updates
   - Sorted subsytem Makefile/Kconfig and some kernel-doc udpates
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAmnh4msACgkQfBQHDyUj
 g0ctew/+K/rVLCUu/UgbvnV1hPH3q/OCytwcymurSp5+lZ2TGsHcwjzGNKrGxCAp
 nxgzffHwukyuRGq/FHDc1QQa+i5bDzf6dlE3CuZYnZWka8mxbqcBetMQvLb93LXL
 9MEQ8YQgjh96AyX87sP0r5IhBVLl3LiGHj2+L6VXoTzMsJeqT6Kx2rABHgFjXM97
 gjurp1PbHwi2EGQowa9zjsoQnRnN2C4O2xlZsXeNljzS2KPpToQ+sjADwHSau8nw
 b9idowJlJMlN+RFrNKJWgja7ro/E17IGQptJT9Hz89j2dXg0QiWIY/uok25o6XAn
 h0yYWpXP6gaQH1mnpS5Meb8d+ljTL4SNLv/64pYSGPzqXUbuJXVx2Rn7ZBuB3R/H
 +pmVbrdWSUwhXcgXDyVCMLguhCxns4M/SmaYrjVayrogDiz9gqHlGMTfsSmYCnbI
 UDqHyFSa6HRZIFnba0pBkb3eyrKE9qMK0FFgQURQp8GCOJu8waeNyCZ4fTCjXo6v
 MULhauFWDC267LNogt6KGgTC6sFmsitsI8jymMQGfb3g6FdhJUFpQLmNvwYpoHXH
 AofeTHrzdXWRVNiVKO01J2tPskVCczx5R5q5dfDGTM0mIRXMaHCuzT2RNdRmBpNk
 rgBlCvIiiE9VbusN+zybPQfTJAQa2eVMTvBRzjwkdLUYeMUJS0I=
 =qz0Z
 -----END PGP SIGNATURE-----

Merge tag 'phy-for-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy

Pull phy updates from Vinod Koul:
 "New Support:
   - Qualcomm Eliza QMP UFS PHY
   - Canaan K230 USB 2.0 PHY driver
   - Mediatek mt8167 dsi-phy
   - Eswin EIC7700 SATA PHY driver

  Updates:
   - Sorted subsytem Makefile/Kconfig and some kernel-doc udpates"

* tag 'phy-for-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy:
  dt-bindings: phy: qcom,sc8280xp-qmp-ufs-phy: document the Eliza QMP UFS PHY
  phy: qcom: m31-eusb2: clear PLL_EN during init
  phy: eswin: Create eswin directory and add EIC7700 SATA PHY driver
  dt-bindings: phy: eswin: Document the EIC7700 SoC SATA PHY
  phy: apple: apple: Use local variable for ioremap return value
  phy: qcom: qmp-usbc: Simplify check for non-NULL pointer
  phy: marvell: mmp3-hsic: Avoid re-casting __iomem
  phy: apple: atc: Make atcphy_dwc3_reset_ops variable static
  dt-bindings: phy: mediatek,dsi-phy: Add support for mt8167
  phy: usb: Add driver for Canaan K230 USB 2.0 PHY
  dt-bindings: phy: Add Canaan K230 USB PHY
  phy: phy-mtk-tphy: Update names and format of kernel-doc comments
  phy: Sort the subsystem Kconfig
  phy: Sort the subsystem Makefile
  phy: move spacemit pcie driver to its subfolder
This commit is contained in:
Linus Torvalds 2026-04-17 10:22:08 -07:00
commit 3f887edd35
19 changed files with 816 additions and 81 deletions

View File

@ -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>;
};

View File

@ -0,0 +1,92 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/eswin,eic7700-sata-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Eswin EIC7700 SoC SATA PHY
maintainers:
- Yulin Lu <luyulin@eswincomputing.com>
- Huan He <hehuan1@eswincomputing.com>
properties:
compatible:
const: eswin,eic7700-sata-phy
reg:
maxItems: 1
clocks:
maxItems: 1
clock-names:
const: phy
resets:
maxItems: 2
reset-names:
items:
- const: port
- const: phy
eswin,tx-amplitude-tuning:
description: This adjusts the transmitter amplitude signal, and its value
is derived from eye diagram tuning. The three values correspond to Gen1,
Gen2, and Gen3 parameters respectively.
$ref: /schemas/types.yaml#/definitions/uint32-array
items:
- description: Gen1 parameter.
minimum: 0
maximum: 0x7f
- description: Gen2 parameter.
minimum: 0
maximum: 0x7f
- description: Gen3 parameter.
minimum: 0
maximum: 0x7f
default: [0, 0, 0]
eswin,tx-preemph-tuning:
description: This adjusts the transmitter de-emphasis signal, and its value
is derived from eye diagram tuning. The three values correspond to Gen1,
Gen2, and Gen3 parameters respectively.
$ref: /schemas/types.yaml#/definitions/uint32-array
items:
- description: Gen1 parameter.
minimum: 0
maximum: 0x3f
- description: Gen2 parameter.
minimum: 0
maximum: 0x3f
- description: Gen3 parameter.
minimum: 0
maximum: 0x3f
default: [0, 0, 0]
"#phy-cells":
const: 0
required:
- compatible
- reg
- clocks
- clock-names
- resets
- reset-names
- "#phy-cells"
additionalProperties: false
examples:
- |
sata-phy@50440300 {
compatible = "eswin,eic7700-sata-phy";
reg = <0x50440300 0x40>;
clocks = <&hspcrg 17>;
clock-names = "phy";
resets = <&hspcrg 0>, <&hspcrg 1>;
reset-names = "port", "phy";
#phy-cells = <0>;
};

View File

@ -16,6 +16,10 @@ description:
properties:
compatible:
oneOf:
- items:
- enum:
- qcom,qcs8300-qmp-ufs-phy
- const: qcom,sa8775p-qmp-ufs-phy
- items:
- enum:
- qcom,qcs615-qmp-ufs-phy
@ -26,8 +30,8 @@ properties:
- const: qcom,sm8550-qmp-ufs-phy
- items:
- enum:
- qcom,qcs8300-qmp-ufs-phy
- const: qcom,sa8775p-qmp-ufs-phy
- qcom,eliza-qmp-ufs-phy
- const: qcom,sm8650-qmp-ufs-phy
- items:
- enum:
- qcom,kaanapali-qmp-ufs-phy

View File

@ -46,6 +46,26 @@ config GENERIC_PHY_MIPI_DPHY
Provides a number of helpers a core functions for MIPI D-PHY
drivers to us.
config PHY_AIROHA_PCIE
tristate "Airoha PCIe-PHY Driver"
depends on ARCH_AIROHA || COMPILE_TEST
depends on OF
select GENERIC_PHY
help
Say Y here to add support for Airoha PCIe PHY driver.
This driver create the basic PHY instance and provides initialize
callback for PCIe GEN3 port.
config PHY_CAN_TRANSCEIVER
tristate "CAN transceiver PHY"
select GENERIC_PHY
select MULTIPLEXER
help
This option enables support for CAN transceivers as a PHY. This
driver provides function for putting the transceivers in various
functional modes using gpios and sets the attribute max link
rate, for CAN drivers.
config PHY_GOOGLE_USB
tristate "Google Tensor SoC USB PHY driver"
select GENERIC_PHY
@ -57,6 +77,18 @@ config PHY_GOOGLE_USB
both of which are integrated with the DWC3 USB DRD controller.
This driver currently supports USB high-speed.
config USB_LGM_PHY
tristate "INTEL Lightning Mountain USB PHY Driver"
depends on USB_SUPPORT
depends on X86 || COMPILE_TEST
select USB_PHY
select REGULATOR
select REGULATOR_FIXED_VOLTAGE
help
Enable this to support Intel DWC3 PHY USB phy. This driver provides
interface to interact with USB GEN-II and USB 3.x PHY that is part
of the Intel network SOC.
config PHY_LPC18XX_USB_OTG
tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver"
depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
@ -68,6 +100,17 @@ config PHY_LPC18XX_USB_OTG
This driver is need for USB0 support on LPC18xx/43xx and takes
care of enabling and clock setup.
config PHY_NXP_PTN3222
tristate "NXP PTN3222 1-port eUSB2 to USB2 redriver"
depends on I2C
depends on OF
select GENERIC_PHY
help
Enable this to support NXP PTN3222 1-port eUSB2 to USB2 Redriver.
This redriver performs translation between eUSB2 and USB2 signalling
schemes. It supports all three USB 2.0 data rates: Low Speed, Full
Speed and High Speed.
config PHY_PISTACHIO_USB
tristate "IMG Pistachio USB2.0 PHY driver"
depends on MIPS || COMPILE_TEST
@ -90,69 +133,17 @@ config PHY_XGENE
help
This option enables support for APM X-Gene SoC multi-purpose PHY.
config USB_LGM_PHY
tristate "INTEL Lightning Mountain USB PHY Driver"
depends on USB_SUPPORT
depends on X86 || COMPILE_TEST
select USB_PHY
select REGULATOR
select REGULATOR_FIXED_VOLTAGE
help
Enable this to support Intel DWC3 PHY USB phy. This driver provides
interface to interact with USB GEN-II and USB 3.x PHY that is part
of the Intel network SOC.
config PHY_CAN_TRANSCEIVER
tristate "CAN transceiver PHY"
select GENERIC_PHY
select MULTIPLEXER
help
This option enables support for CAN transceivers as a PHY. This
driver provides function for putting the transceivers in various
functional modes using gpios and sets the attribute max link
rate, for CAN drivers.
config PHY_AIROHA_PCIE
tristate "Airoha PCIe-PHY Driver"
depends on ARCH_AIROHA || COMPILE_TEST
depends on OF
select GENERIC_PHY
help
Say Y here to add support for Airoha PCIe PHY driver.
This driver create the basic PHY instance and provides initialize
callback for PCIe GEN3 port.
config PHY_NXP_PTN3222
tristate "NXP PTN3222 1-port eUSB2 to USB2 redriver"
depends on I2C
depends on OF
select GENERIC_PHY
help
Enable this to support NXP PTN3222 1-port eUSB2 to USB2 Redriver.
This redriver performs translation between eUSB2 and USB2 signalling
schemes. It supports all three USB 2.0 data rates: Low Speed, Full
Speed and High Speed.
config PHY_SPACEMIT_K1_PCIE
tristate "PCIe and combo PHY driver for the SpacemiT K1 SoC"
depends on ARCH_SPACEMIT || COMPILE_TEST
depends on COMMON_CLK
depends on HAS_IOMEM
depends on OF
select GENERIC_PHY
default ARCH_SPACEMIT
help
Enable support for the PCIe and USB 3 combo PHY and two
PCIe-only PHYs used in the SpacemiT K1 SoC.
source "drivers/phy/allwinner/Kconfig"
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/eswin/Kconfig"
source "drivers/phy/freescale/Kconfig"
source "drivers/phy/hisilicon/Kconfig"
source "drivers/phy/ingenic/Kconfig"
source "drivers/phy/intel/Kconfig"
source "drivers/phy/lantiq/Kconfig"
source "drivers/phy/marvell/Kconfig"
source "drivers/phy/mediatek/Kconfig"
@ -174,7 +165,6 @@ source "drivers/phy/starfive/Kconfig"
source "drivers/phy/sunplus/Kconfig"
source "drivers/phy/tegra/Kconfig"
source "drivers/phy/ti/Kconfig"
source "drivers/phy/intel/Kconfig"
source "drivers/phy/xilinx/Kconfig"
endmenu

View File

@ -7,21 +7,23 @@ obj-$(CONFIG_PHY_COMMON_PROPS) += phy-common-props.o
obj-$(CONFIG_PHY_COMMON_PROPS_TEST) += phy-common-props-test.o
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o
obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o
obj-$(CONFIG_PHY_CAN_TRANSCEIVER) += phy-can-transceiver.o
obj-$(CONFIG_PHY_GOOGLE_USB) += phy-google-usb.o
obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o
obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
obj-$(CONFIG_PHY_NXP_PTN3222) += phy-nxp-ptn3222.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
obj-$(CONFIG_PHY_SNPS_EUSB2) += phy-snps-eusb2.o
obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o
obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o
obj-$(CONFIG_PHY_NXP_PTN3222) += phy-nxp-ptn3222.o
obj-$(CONFIG_PHY_SPACEMIT_K1_PCIE) += phy-spacemit-k1-pcie.o
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
obj-$(CONFIG_GENERIC_PHY) += allwinner/ \
amlogic/ \
apple/ \
broadcom/ \
cadence/ \
canaan/ \
eswin/ \
freescale/ \
hisilicon/ \
ingenic/ \

View File

@ -2023,7 +2023,7 @@ static int atcphy_dwc3_reset_deassert(struct reset_controller_dev *rcdev, unsign
return 0;
}
const struct reset_control_ops atcphy_dwc3_reset_ops = {
static const struct reset_control_ops atcphy_dwc3_reset_ops = {
.assert = atcphy_dwc3_reset_assert,
.deassert = atcphy_dwc3_reset_deassert,
};
@ -2202,14 +2202,16 @@ static int atcphy_map_resources(struct platform_device *pdev, struct apple_atcph
{ "pipehandler", &atcphy->regs.pipehandler, NULL },
};
struct resource *res;
void __iomem *addr;
for (int i = 0; i < ARRAY_SIZE(resources); i++) {
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, resources[i].name);
*resources[i].addr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(resources[i].addr))
return dev_err_probe(atcphy->dev, PTR_ERR(resources[i].addr),
addr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(addr))
return dev_err_probe(atcphy->dev, PTR_ERR(addr),
"Unable to map %s regs", resources[i].name);
*resources[i].addr = addr;
if (resources[i].res)
*resources[i].res = res;
}

View File

@ -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.

View File

@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_CANAAN_USB) += phy-k230-usb.o

View File

@ -0,0 +1,284 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Canaan usb PHY driver
*
* Copyright (C) 2026 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");

14
drivers/phy/eswin/Kconfig Normal file
View File

@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Phy drivers for ESWIN platforms
#
config PHY_EIC7700_SATA
tristate "eic7700 Sata SerDes/PHY driver"
depends on ARCH_ESWIN || COMPILE_TEST
depends on HAS_IOMEM
select GENERIC_PHY
help
Enable this to support SerDes/Phy found on ESWIN's
EIC7700 SoC. This Phy supports SATA 1.5 Gb/s,
SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds.
It supports one SATA host port to accept one SATA device.

View File

@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_EIC7700_SATA) += phy-eic7700-sata.o

View File

@ -0,0 +1,273 @@
// SPDX-License-Identifier: GPL-2.0
/*
* ESWIN SATA PHY driver
*
* Copyright 2026, Beijing ESWIN Computing Technology Co., Ltd..
* All rights reserved.
*
* Authors: Yulin Lu <luyulin@eswincomputing.com>
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#define SATA_AXI_LP_CTRL 0x08
#define SATA_MPLL_CTRL 0x20
#define SATA_P0_PHY_STAT 0x24
#define SATA_PHY_CTRL0 0x28
#define SATA_PHY_CTRL1 0x2c
#define SATA_REF_CTRL 0x34
#define SATA_REF_CTRL1 0x38
#define SATA_LOS_IDEN 0x3c
#define SATA_CLK_RST_SOURCE_PHY BIT(0)
#define SATA_P0_PHY_TX_AMPLITUDE_GEN1_MASK GENMASK(6, 0)
#define SATA_P0_PHY_TX_AMPLITUDE_GEN1_DEFAULT 0x42
#define SATA_P0_PHY_TX_AMPLITUDE_GEN2_MASK GENMASK(14, 8)
#define SATA_P0_PHY_TX_AMPLITUDE_GEN2_DEFAULT 0x46
#define SATA_P0_PHY_TX_AMPLITUDE_GEN3_MASK GENMASK(22, 16)
#define SATA_P0_PHY_TX_AMPLITUDE_GEN3_DEFAULT 0x73
#define SATA_P0_PHY_TX_PREEMPH_GEN1_MASK GENMASK(5, 0)
#define SATA_P0_PHY_TX_PREEMPH_GEN1_DEFAULT 0x5
#define SATA_P0_PHY_TX_PREEMPH_GEN2_MASK GENMASK(13, 8)
#define SATA_P0_PHY_TX_PREEMPH_GEN2_DEFAULT 0x5
#define SATA_P0_PHY_TX_PREEMPH_GEN3_MASK GENMASK(21, 16)
#define SATA_P0_PHY_TX_PREEMPH_GEN3_DEFAULT 0x23
#define SATA_LOS_LEVEL_MASK GENMASK(4, 0)
#define SATA_LOS_BIAS_MASK GENMASK(18, 16)
#define SATA_M_CSYSREQ BIT(0)
#define SATA_S_CSYSREQ BIT(16)
#define SATA_REF_REPEATCLK_EN BIT(0)
#define SATA_REF_USE_PAD BIT(20)
#define SATA_MPLL_MULTIPLIER_MASK GENMASK(22, 16)
#define SATA_P0_PHY_READY BIT(0)
#define PLL_LOCK_SLEEP_US 10
#define PLL_LOCK_TIMEOUT_US 1000
struct eic7700_sata_phy {
u32 tx_amplitude_tuning_val[3];
u32 tx_preemph_tuning_val[3];
struct reset_control *rst;
struct regmap *regmap;
struct clk *clk;
struct phy *phy;
};
static const struct regmap_config eic7700_sata_phy_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.max_register = SATA_LOS_IDEN,
};
static int wait_for_phy_ready(struct regmap *regmap, u32 reg, u32 checkbit,
u32 status)
{
u32 val;
int ret;
ret = regmap_read_poll_timeout(regmap, reg, val,
(val & checkbit) == status,
PLL_LOCK_SLEEP_US, PLL_LOCK_TIMEOUT_US);
return ret;
}
static int eic7700_sata_phy_init(struct phy *phy)
{
struct eic7700_sata_phy *sata_phy = phy_get_drvdata(phy);
u32 val;
int ret;
ret = clk_prepare_enable(sata_phy->clk);
if (ret)
return ret;
regmap_write(sata_phy->regmap, SATA_REF_CTRL1, SATA_CLK_RST_SOURCE_PHY);
val = FIELD_PREP(SATA_P0_PHY_TX_AMPLITUDE_GEN1_MASK,
sata_phy->tx_amplitude_tuning_val[0]) |
FIELD_PREP(SATA_P0_PHY_TX_AMPLITUDE_GEN2_MASK,
sata_phy->tx_amplitude_tuning_val[1]) |
FIELD_PREP(SATA_P0_PHY_TX_AMPLITUDE_GEN3_MASK,
sata_phy->tx_amplitude_tuning_val[2]);
regmap_write(sata_phy->regmap, SATA_PHY_CTRL0, val);
val = FIELD_PREP(SATA_P0_PHY_TX_PREEMPH_GEN1_MASK,
sata_phy->tx_preemph_tuning_val[0]) |
FIELD_PREP(SATA_P0_PHY_TX_PREEMPH_GEN2_MASK,
sata_phy->tx_preemph_tuning_val[1]) |
FIELD_PREP(SATA_P0_PHY_TX_PREEMPH_GEN3_MASK,
sata_phy->tx_preemph_tuning_val[2]);
regmap_write(sata_phy->regmap, SATA_PHY_CTRL1, val);
val = FIELD_PREP(SATA_LOS_LEVEL_MASK, 0x9) |
FIELD_PREP(SATA_LOS_BIAS_MASK, 0x2);
regmap_write(sata_phy->regmap, SATA_LOS_IDEN, val);
val = SATA_M_CSYSREQ | SATA_S_CSYSREQ;
regmap_write(sata_phy->regmap, SATA_AXI_LP_CTRL, val);
val = SATA_REF_REPEATCLK_EN | SATA_REF_USE_PAD;
regmap_write(sata_phy->regmap, SATA_REF_CTRL, val);
val = FIELD_PREP(SATA_MPLL_MULTIPLIER_MASK, 0x3c);
regmap_write(sata_phy->regmap, SATA_MPLL_CTRL, val);
usleep_range(15, 20);
ret = reset_control_deassert(sata_phy->rst);
if (ret)
goto disable_clk;
ret = wait_for_phy_ready(sata_phy->regmap, SATA_P0_PHY_STAT,
SATA_P0_PHY_READY, 1);
if (ret < 0) {
dev_err(&sata_phy->phy->dev, "PHY READY check failed\n");
goto disable_clk;
}
return 0;
disable_clk:
clk_disable_unprepare(sata_phy->clk);
return ret;
}
static int eic7700_sata_phy_exit(struct phy *phy)
{
struct eic7700_sata_phy *sata_phy = phy_get_drvdata(phy);
int ret;
ret = reset_control_assert(sata_phy->rst);
if (ret)
return ret;
clk_disable_unprepare(sata_phy->clk);
return 0;
}
static const struct phy_ops eic7700_sata_phy_ops = {
.init = eic7700_sata_phy_init,
.exit = eic7700_sata_phy_exit,
.owner = THIS_MODULE,
};
static void eic7700_get_tuning_param(struct device_node *np,
struct eic7700_sata_phy *sata_phy)
{
if (of_property_read_u32_array
(np, "eswin,tx-amplitude-tuning",
sata_phy->tx_amplitude_tuning_val,
ARRAY_SIZE(sata_phy->tx_amplitude_tuning_val))) {
sata_phy->tx_amplitude_tuning_val[0] =
SATA_P0_PHY_TX_AMPLITUDE_GEN1_DEFAULT;
sata_phy->tx_amplitude_tuning_val[1] =
SATA_P0_PHY_TX_AMPLITUDE_GEN2_DEFAULT;
sata_phy->tx_amplitude_tuning_val[2] =
SATA_P0_PHY_TX_AMPLITUDE_GEN3_DEFAULT;
}
if (of_property_read_u32_array
(np, "eswin,tx-preemph-tuning",
sata_phy->tx_preemph_tuning_val,
ARRAY_SIZE(sata_phy->tx_preemph_tuning_val))) {
sata_phy->tx_preemph_tuning_val[0] =
SATA_P0_PHY_TX_PREEMPH_GEN1_DEFAULT;
sata_phy->tx_preemph_tuning_val[1] =
SATA_P0_PHY_TX_PREEMPH_GEN2_DEFAULT;
sata_phy->tx_preemph_tuning_val[2] =
SATA_P0_PHY_TX_PREEMPH_GEN3_DEFAULT;
}
}
static int eic7700_sata_phy_probe(struct platform_device *pdev)
{
struct eic7700_sata_phy *sata_phy;
struct phy_provider *phy_provider;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct resource *res;
void __iomem *regs;
sata_phy = devm_kzalloc(dev, sizeof(*sata_phy), GFP_KERNEL);
if (!sata_phy)
return -ENOMEM;
/*
* Map the I/O resource with platform_get_resource and devm_ioremap
* instead of the devm_platform_ioremap_resource API, because the
* address region of the SATA-PHY falls into the region of the HSP
* clock & reset that has already been obtained by the HSP
* clock-and-reset driver.
*/
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENOENT;
regs = devm_ioremap(dev, res->start, resource_size(res));
if (IS_ERR(regs))
return PTR_ERR(regs);
sata_phy->regmap = devm_regmap_init_mmio
(dev, regs, &eic7700_sata_phy_regmap_config);
if (IS_ERR(sata_phy->regmap))
return dev_err_probe(dev, PTR_ERR(sata_phy->regmap),
"failed to init regmap\n");
dev_set_drvdata(dev, sata_phy);
eic7700_get_tuning_param(np, sata_phy);
sata_phy->clk = devm_clk_get(dev, "phy");
if (IS_ERR(sata_phy->clk))
return PTR_ERR(sata_phy->clk);
sata_phy->rst = devm_reset_control_array_get_exclusive(dev);
if (IS_ERR(sata_phy->rst))
return dev_err_probe(dev, PTR_ERR(sata_phy->rst),
"failed to get reset control\n");
sata_phy->phy = devm_phy_create(dev, NULL, &eic7700_sata_phy_ops);
if (IS_ERR(sata_phy->phy))
return dev_err_probe(dev, PTR_ERR(sata_phy->phy),
"failed to create PHY\n");
phy_set_drvdata(sata_phy->phy, sata_phy);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(phy_provider))
return dev_err_probe(dev, PTR_ERR(phy_provider),
"failed to register PHY provider\n");
return 0;
}
static const struct of_device_id eic7700_sata_phy_of_match[] = {
{ .compatible = "eswin,eic7700-sata-phy" },
{ },
};
MODULE_DEVICE_TABLE(of, eic7700_sata_phy_of_match);
static struct platform_driver eic7700_sata_phy_driver = {
.probe = eic7700_sata_phy_probe,
.driver = {
.of_match_table = eic7700_sata_phy_of_match,
.name = "eic7700-sata-phy",
}
};
module_platform_driver(eic7700_sata_phy_driver);
MODULE_DESCRIPTION("SATA PHY driver for the ESWIN EIC7700 SoC");
MODULE_AUTHOR("Yulin Lu <luyulin@eswincomputing.com>");
MODULE_LICENSE("GPL");

View File

@ -14,15 +14,19 @@
#define HSIC_ENABLE BIT(7)
#define PLL_BYPASS BIT(4)
struct mmp3_hsic_data {
void __iomem *base;
};
static int mmp3_hsic_phy_init(struct phy *phy)
{
void __iomem *base = (void __iomem *)phy_get_drvdata(phy);
struct mmp3_hsic_data *mmp3 = phy_get_drvdata(phy);
u32 hsic_ctrl;
hsic_ctrl = readl_relaxed(base + HSIC_CTRL);
hsic_ctrl = readl_relaxed(mmp3->base + HSIC_CTRL);
hsic_ctrl |= HSIC_ENABLE;
hsic_ctrl |= PLL_BYPASS;
writel_relaxed(hsic_ctrl, base + HSIC_CTRL);
writel_relaxed(hsic_ctrl, mmp3->base + HSIC_CTRL);
return 0;
}
@ -41,13 +45,17 @@ MODULE_DEVICE_TABLE(of, mmp3_hsic_phy_of_match);
static int mmp3_hsic_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mmp3_hsic_data *mmp3;
struct phy_provider *provider;
void __iomem *base;
struct phy *phy;
base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(base))
return PTR_ERR(base);
mmp3 = devm_kzalloc(dev, sizeof(*mmp3), GFP_KERNEL);
if (!mmp3)
return -ENOMEM;
mmp3->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(mmp3->base))
return PTR_ERR(mmp3->base);
phy = devm_phy_create(dev, NULL, &mmp3_hsic_phy_ops);
if (IS_ERR(phy)) {
@ -55,7 +63,7 @@ static int mmp3_hsic_phy_probe(struct platform_device *pdev)
return PTR_ERR(phy);
}
phy_set_drvdata(phy, (void *)base);
phy_set_drvdata(phy, mmp3);
provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(provider)) {
dev_err(dev, "failed to register PHY provider\n");

View File

@ -276,14 +276,14 @@ enum mtk_phy_version {
};
/**
* mtk_phy_pdata - SoC specific platform data
* struct mtk_phy_pdata - SoC specific platform data
* @avoid_rx_sen_degradation: Avoid TX Sensitivity level degradation (MT6795/8173 only)
* @sw_pll_48m_to_26m: Workaround for V3 IP (MT8195) - switch the 48MHz PLL from
* fractional mode to integer to output 26MHz for U2PHY
* @sw_efuse_supported: Switches off eFuse auto-load from PHY and applies values
* read from different nvmem (usually different eFuse array)
* that is pointed at in the device tree node for this PHY
* @slew_ref_clk_mhz: Default reference clock (in MHz) for slew rate calibration
* @slew_ref_clock_mhz: Default reference clock (in MHz) for slew rate calibration
* @slew_rate_coefficient: Coefficient for slew rate calibration
* @version: PHY IP Version
*/

View File

@ -83,7 +83,7 @@ static const struct m31_phy_tbl_entry m31_eusb2_setup_tbl[] = {
M31_EUSB_PHY_INIT_CFG(USB_PHY_CFG0, UTMI_PHY_CMN_CTRL_OVERRIDE_EN, 1),
M31_EUSB_PHY_INIT_CFG(USB_PHY_UTMI_CTRL5, POR, 1),
M31_EUSB_PHY_INIT_CFG(USB_PHY_HS_PHY_CTRL_COMMON0, PHY_ENABLE, 1),
M31_EUSB_PHY_INIT_CFG(USB_PHY_CFG1, PLL_EN, 1),
M31_EUSB_PHY_INIT_CFG(USB_PHY_CFG1, PLL_EN, 0),
M31_EUSB_PHY_INIT_CFG(USB_PHY_FSEL_SEL, FSEL_SEL, 1),
};

View File

@ -1679,7 +1679,7 @@ static int qmp_usbc_register_clocks(struct qmp_usbc *qmp, struct device_node *np
if (ret)
return ret;
if (qmp->dp_serdes != 0) {
if (qmp->dp_serdes) {
ret = phy_dp_clks_register(qmp, np);
if (ret)
return ret;
@ -1833,7 +1833,7 @@ static int qmp_usbc_parse_dt(struct qmp_usbc *qmp)
if (IS_ERR(base))
return PTR_ERR(base);
if (offs->dp_serdes != 0) {
if (offs->dp_serdes) {
qmp->dp_serdes = base + offs->dp_serdes;
qmp->dp_tx = base + offs->dp_txa;
qmp->dp_tx2 = base + offs->dp_txb;
@ -1982,7 +1982,7 @@ static int qmp_usbc_probe(struct platform_device *pdev)
phy_set_drvdata(qmp->usb_phy, qmp);
if (qmp->dp_serdes != 0) {
if (qmp->dp_serdes) {
qmp->dp_phy = devm_phy_create(dev, np, &qmp_usbc_dp_phy_ops);
if (IS_ERR(qmp->dp_phy)) {
ret = PTR_ERR(qmp->dp_phy);

View File

@ -2,6 +2,18 @@
#
# Phy drivers for SpacemiT platforms
#
config PHY_SPACEMIT_K1_PCIE
tristate "PCIe and combo PHY driver for the SpacemiT K1 SoC"
depends on ARCH_SPACEMIT || COMPILE_TEST
depends on COMMON_CLK
depends on HAS_IOMEM
depends on OF
select GENERIC_PHY
default ARCH_SPACEMIT
help
Enable support for the PCIe and USB 3 combo PHY and two
PCIe-only PHYs used in the SpacemiT K1 SoC.
config PHY_SPACEMIT_K1_USB2
tristate "SpacemiT K1 USB 2.0 PHY support"
depends on (ARCH_SPACEMIT || COMPILE_TEST) && OF

View File

@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_PHY_SPACEMIT_K1_PCIE) += phy-k1-pcie.o
obj-$(CONFIG_PHY_SPACEMIT_K1_USB2) += phy-k1-usb2.o