phy-for-6.18

- New Support
   - Qualcomm SM8750 QMP PCIe PHY dual lane support, PMIV0104 eusb2 repeater
     support, QCS8300 eDP PHY support
   - Renesas RZ/T2H and RZ/N2H support and updates to driver for that
   - TI TCAN1051 phy support
   - Rockchip rk3588 dphy support, RK3528 combphy support
 
 - Updates
   - cadence updates for calibration and polling for ready and enabling of
     lower resolutions, runtime pm support,
   - Rockchip: enable U3 otg port
   - Renesas USXGMII mode support
   - Qualcomm UFS PHY and PLL regulator load support
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAmjjbZMACgkQfBQHDyUj
 g0cTtBAAqF+dgYsDWkwRLIDbfLxgN2siw3h21tllzy8QfId9K5wjG5plz4u2Zk9/
 MkD5gZgdNTkvViFH5iIIV2IgrzeX4E1ed+1SGLcf9wOKUKxgt4j6CxRBvhfWtgQv
 pRLpmzOzt+EM4l2G8I8LVtb0fwy7s9ZjvLUVhLnG5b0PCdK+2ozs0vcAr3RLqFWu
 xfy3AeaIX5wEop4HeAU/4ofAl2Rmni7i7Cx4V4iy8jThQEjWz7Hyff8tXAYqHJrF
 pPInbHU/EFAaiFHJBv/dgDle826jCbuNwy2lD4OxDq8AH4XDAVcBndg4c0lXIGnB
 e39FnNSavTVZhbo+zifvBzRd9wEj/ZIv9Lz8RpvJxKl17PTWzRjS0Bhhf4LwRDyR
 oso8DlLcB4E12d8EwCrqXkRyRZE5IBRdTF6hgmxJa+50S2h9E/A3qWmJur/U1kCm
 meGuodwFZzExjYNqmc0HSAyy5RYnS6P5PGl9D7SxY8QhuFMfpHws9bGaLTpEwwA3
 vUsja74qux0Lq/aFX/EuOOdjPQ8E5HOSqhRFoBbQ1drp02TmvVltbwrujWpdOI1n
 uwlUi0USu59HQuDUgaeOTL4PH6WYQpDYk8rAqV+Vy96BcvgFYEEXyotZ22XqbxS8
 NprtGnU+w0wwIEVv5K7SR6r+RmB/ViEOYEg418GrQCxGIbbOwqs=
 =UiHw
 -----END PGP SIGNATURE-----

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

Pull phy updates from Vinod Koul:
 "The usual bunch of device support and update to drivers.

  New Support
   - Qualcomm SM8750 QMP PCIe PHY dual lane support, PMIV0104 eusb2
     repeater support, QCS8300 eDP PHY support
   - Renesas RZ/T2H and RZ/N2H support and updates to driver for that
   - TI TCAN1051 phy support
   - Rockchip rk3588 dphy support, RK3528 combphy support

  Updates:
   - cadence updates for calibration and polling for ready and enabling
     of lower resolutions, runtime pm support,
   - Rockchip: enable U3 otg port
   - Renesas USXGMII mode support
   - Qualcomm UFS PHY and PLL regulator load support"

* tag 'phy-for-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (64 commits)
  phy: rockchip: phy-rockchip-inno-csidphy: add support for rk3588 variant
  phy: rockchip: phy-rockchip-inno-csidphy: allow for different reset lines
  phy: rockchip: phy-rockchip-inno-csidphy: allow writes to grf register 0
  dt-bindings: phy: rockchip-inno-csi-dphy: add rk3588 variant
  dt-bindings: phy: rockchip-inno-csi-dphy: make power-domains non-required
  phy: cadence: cdns-dphy: Enable lower resolutions in dphy
  phy: renesas: r8a779f0-ether-serdes: add new step added to latest datasheet
  phy: renesas: r8a779f0-ether-serdes: add USXGMII mode
  phy: sophgo: Add USB 2.0 PHY driver for Sophgo CV18XX/SG200X
  dt-bindings: phy: Add Sophgo CV1800 USB phy
  phy: cadence: cdns-dphy: Update calibration wait time for startup state machine
  phy: cadence: cdns-dphy: Fix PLL lock and O_CMN_READY polling
  phy: renesas: rcar-gen3-usb2: Fix ID check logic with VBUS valid
  dt-bindings: phy: ti,tcan104x-can: Document TI TCAN1051
  phy: lynx-28g: check return value when calling lynx_28g_pll_get
  phy: qcom: m31-eusb2: Fix the error log while enabling clock
  phy: rockchip: usbdp: Remove redundant ternary operators
  phy: renesas: rcar-gen3-usb2: Remove redundant ternary operators
  phy: hisilicon: Remove redundant ternary operators
  phy: qcom-qmp-ufs: Add PHY and PLL regulator load
  ...
pull/1354/merge
Linus Torvalds 2025-10-06 10:34:22 -07:00
commit 1d1ba4d390
49 changed files with 1657 additions and 493 deletions

View File

@ -76,7 +76,6 @@ properties:
description:
Adjust TX de-emphasis attenuation in dB at nominal
3.5dB point as per USB specification
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 36

View File

@ -12,6 +12,7 @@ maintainers:
properties:
compatible:
enum:
- rockchip,rk3528-naneng-combphy
- rockchip,rk3562-naneng-combphy
- rockchip,rk3568-naneng-combphy
- rockchip,rk3576-naneng-combphy
@ -45,6 +46,9 @@ properties:
phy-supply:
description: Single PHY regulator
power-domains:
maxItems: 1
rockchip,enable-ssc:
type: boolean
description:
@ -105,7 +109,9 @@ allOf:
properties:
compatible:
contains:
const: rockchip,rk3588-naneng-combphy
enum:
- rockchip,rk3528-naneng-combphy
- rockchip,rk3588-naneng-combphy
then:
properties:
resets:

View File

@ -16,13 +16,18 @@ description:
properties:
compatible:
enum:
- qcom,sa8775p-edp-phy
- qcom,sc7280-edp-phy
- qcom,sc8180x-edp-phy
- qcom,sc8280xp-dp-phy
- qcom,sc8280xp-edp-phy
- qcom,x1e80100-dp-phy
oneOf:
- enum:
- qcom,sa8775p-edp-phy
- qcom,sc7280-edp-phy
- qcom,sc8180x-edp-phy
- qcom,sc8280xp-dp-phy
- qcom,sc8280xp-edp-phy
- qcom,x1e80100-dp-phy
- items:
- enum:
- qcom,qcs8300-edp-phy
- const: qcom,sa8775p-edp-phy
reg:
items:

View File

@ -42,6 +42,7 @@ properties:
- qcom,sm8550-qmp-gen4x2-pcie-phy
- qcom,sm8650-qmp-gen3x2-pcie-phy
- qcom,sm8650-qmp-gen4x2-pcie-phy
- qcom,sm8750-qmp-gen3x2-pcie-phy
- qcom,x1e80100-qmp-gen3x2-pcie-phy
- qcom,x1e80100-qmp-gen4x2-pcie-phy
- qcom,x1e80100-qmp-gen4x4-pcie-phy
@ -164,6 +165,7 @@ allOf:
- qcom,sm8550-qmp-gen4x2-pcie-phy
- qcom,sm8650-qmp-gen3x2-pcie-phy
- qcom,sm8650-qmp-gen4x2-pcie-phy
- qcom,sm8750-qmp-gen3x2-pcie-phy
then:
properties:
clocks:

View File

@ -73,10 +73,8 @@ properties:
description:
See include/dt-bindings/phy/phy-qcom-qmp.h
orientation-switch:
description:
Flag the PHY as possible handler of USB Type-C orientation switching
type: boolean
mode-switch: true
orientation-switch: true
ports:
$ref: /schemas/graph.yaml#/properties/ports
@ -106,6 +104,7 @@ required:
- "#phy-cells"
allOf:
- $ref: /schemas/usb/usb-switch.yaml#
- if:
properties:
compatible:

View File

@ -22,6 +22,7 @@ properties:
- const: qcom,pm8550b-eusb2-repeater
- enum:
- qcom,pm8550b-eusb2-repeater
- qcom,pmiv0104-eusb2-repeater
- qcom,smb2360-eusb2-repeater
reg:
@ -52,6 +53,12 @@ properties:
minimum: 0
maximum: 7
qcom,tune-res-fsdif:
$ref: /schemas/types.yaml#/definitions/uint8
description: FS Differential TX Output Resistance Tuning
minimum: 0
maximum: 7
required:
- compatible
- reg

View File

@ -44,6 +44,12 @@ properties:
- const: renesas,usb2-phy-r9a09g056 # RZ/V2N
- const: renesas,usb2-phy-r9a09g057
- const: renesas,usb2-phy-r9a09g077 # RZ/T2H
- items:
- const: renesas,usb2-phy-r9a09g087 # RZ/N2H
- const: renesas,usb2-phy-r9a09g077
reg:
maxItems: 1
@ -120,6 +126,17 @@ allOf:
required:
- resets
- if:
properties:
compatible:
contains:
const: renesas,usb2-phy-r9a09g077
then:
properties:
clocks:
minItems: 2
resets: false
additionalProperties: false
examples:

View File

@ -21,6 +21,7 @@ properties:
- rockchip,rk3326-csi-dphy
- rockchip,rk3368-csi-dphy
- rockchip,rk3568-csi-dphy
- rockchip,rk3588-csi-dphy
reg:
maxItems: 1
@ -40,11 +41,15 @@ properties:
resets:
items:
- description: exclusive PHY reset line
- description: APB reset line
- description: PHY reset line
minItems: 1
reset-names:
items:
- const: apb
- const: phy
minItems: 1
rockchip,grf:
$ref: /schemas/types.yaml#/definitions/phandle
@ -57,11 +62,48 @@ required:
- clocks
- clock-names
- '#phy-cells'
- power-domains
- resets
- reset-names
- rockchip,grf
allOf:
- if:
properties:
compatible:
contains:
enum:
- rockchip,px30-csi-dphy
- rockchip,rk1808-csi-dphy
- rockchip,rk3326-csi-dphy
- rockchip,rk3368-csi-dphy
then:
required:
- power-domains
- if:
properties:
compatible:
contains:
enum:
- rockchip,px30-csi-dphy
- rockchip,rk1808-csi-dphy
- rockchip,rk3326-csi-dphy
- rockchip,rk3368-csi-dphy
- rockchip,rk3568-csi-dphy
then:
properties:
resets:
maxItems: 1
reset-names:
maxItems: 1
else:
properties:
resets:
minItems: 2
reset-names:
minItems: 2
additionalProperties: false
examples:
@ -78,3 +120,22 @@ examples:
reset-names = "apb";
rockchip,grf = <&grf>;
};
- |
#include <dt-bindings/clock/rockchip,rk3588-cru.h>
#include <dt-bindings/reset/rockchip,rk3588-cru.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
phy@fedc0000 {
compatible = "rockchip,rk3588-csi-dphy";
reg = <0x0 0xfedc0000 0x0 0x8000>;
clocks = <&cru PCLK_CSIPHY0>;
clock-names = "pclk";
#phy-cells = <0>;
resets = <&cru SRST_P_CSIPHY0>, <&cru SRST_CSIPHY0>;
reset-names = "apb", "phy";
rockchip,grf = <&csidphy0_grf>;
};
};

View File

@ -0,0 +1,54 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/sophgo,cv1800b-usb2-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sophgo CV18XX/SG200X USB 2.0 PHY
maintainers:
- Inochi Amaoto <inochiama@gmail.com>
properties:
compatible:
const: sophgo,cv1800b-usb2-phy
reg:
maxItems: 1
"#phy-cells":
const: 0
clocks:
items:
- description: PHY app clock
- description: PHY stb clock
- description: PHY lpm clock
clock-names:
items:
- const: app
- const: stb
- const: lpm
resets:
maxItems: 1
required:
- compatible
- "#phy-cells"
- clocks
- clock-names
additionalProperties: false
examples:
- |
phy@48 {
compatible = "sophgo,cv1800b-usb2-phy";
reg = <0x48 0x4>;
#phy-cells = <0>;
clocks = <&clk 93>, <&clk 94>, <&clk 95>;
clock-names = "app", "stb", "lpm";
resets = <&rst 58>;
};

View File

@ -18,6 +18,7 @@ properties:
- items:
- enum:
- microchip,ata6561
- ti,tcan1051
- const: ti,tcan1042
- enum:
- ti,tcan1042

View File

@ -16,6 +16,7 @@ properties:
- enum:
- rockchip,rk3288-sgrf
- rockchip,rk3528-ioc-grf
- rockchip,rk3528-pipe-phy-grf
- rockchip,rk3528-vo-grf
- rockchip,rk3528-vpu-grf
- rockchip,rk3562-ioc-grf

View File

@ -122,6 +122,7 @@ source "drivers/phy/renesas/Kconfig"
source "drivers/phy/rockchip/Kconfig"
source "drivers/phy/samsung/Kconfig"
source "drivers/phy/socionext/Kconfig"
source "drivers/phy/sophgo/Kconfig"
source "drivers/phy/st/Kconfig"
source "drivers/phy/starfive/Kconfig"
source "drivers/phy/sunplus/Kconfig"

View File

@ -35,6 +35,7 @@ obj-y += allwinner/ \
rockchip/ \
samsung/ \
socionext/ \
sophgo/ \
st/ \
starfive/ \
sunplus/ \

View File

@ -97,7 +97,6 @@
#define POLL_TIME msecs_to_jiffies(250)
struct sun4i_usb_phy_cfg {
int num_phys;
int hsic_index;
u32 disc_thresh;
u32 hci_phy_ctl_clear;
@ -115,6 +114,7 @@ struct sun4i_usb_phy_data {
const struct sun4i_usb_phy_cfg *cfg;
enum usb_dr_mode dr_mode;
spinlock_t reg_lock; /* guard access to phyctl reg */
int num_phys;
struct sun4i_usb_phy {
struct phy *phy;
void __iomem *pmu;
@ -686,7 +686,7 @@ static struct phy *sun4i_usb_phy_xlate(struct device *dev,
{
struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
if (args->args[0] >= data->cfg->num_phys)
if (args->args[0] >= data->num_phys)
return ERR_PTR(-ENODEV);
if (data->cfg->missing_phys & BIT(args->args[0]))
@ -779,13 +779,22 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
return ret;
}
for (i = 0; i < data->cfg->num_phys; i++) {
for (i = 0; i < MAX_PHYS; i++) {
struct sun4i_usb_phy *phy = data->phys + i;
char name[32];
if (data->cfg->missing_phys & BIT(i))
continue;
snprintf(name, sizeof(name), "usb%d_reset", i);
phy->reset = devm_reset_control_get(dev, name);
if (IS_ERR(phy->reset)) {
if (PTR_ERR(phy->reset) == -ENOENT)
break;
dev_err(dev, "failed to get reset %s\n", name);
return PTR_ERR(phy->reset);
}
snprintf(name, sizeof(name), "usb%d_vbus", i);
phy->vbus = devm_regulator_get_optional(dev, name);
if (IS_ERR(phy->vbus)) {
@ -828,13 +837,6 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
}
}
snprintf(name, sizeof(name), "usb%d_reset", i);
phy->reset = devm_reset_control_get(dev, name);
if (IS_ERR(phy->reset)) {
dev_err(dev, "failed to get reset %s\n", name);
return PTR_ERR(phy->reset);
}
if (i || data->cfg->phy0_dual_route) { /* No pmu for musb */
snprintf(name, sizeof(name), "pmu%d", i);
phy->pmu = devm_platform_ioremap_resource_byname(pdev, name);
@ -851,6 +853,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
phy->index = i;
phy_set_drvdata(phy->phy, &data->phys[i]);
}
data->num_phys = i;
data->id_det_irq = gpiod_to_irq(data->id_det_gpio);
if (data->id_det_irq > 0) {
@ -901,28 +904,24 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
}
static const struct sun4i_usb_phy_cfg suniv_f1c100s_cfg = {
.num_phys = 1,
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = true,
};
static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = {
.num_phys = 3,
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = false,
};
static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = {
.num_phys = 2,
.disc_thresh = 2,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = false,
};
static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = {
.num_phys = 3,
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = true,
@ -930,14 +929,12 @@ static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = {
};
static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = {
.num_phys = 3,
.disc_thresh = 2,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = false,
};
static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = {
.num_phys = 2,
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = true,
@ -945,7 +942,6 @@ static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = {
};
static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = {
.num_phys = 2,
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
@ -953,7 +949,6 @@ static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = {
};
static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = {
.num_phys = 3,
.hsic_index = 2,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
@ -961,7 +956,6 @@ static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = {
};
static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
.num_phys = 4,
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
@ -970,7 +964,6 @@ static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
};
static const struct sun4i_usb_phy_cfg sun8i_r40_cfg = {
.num_phys = 3,
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
@ -979,7 +972,6 @@ static const struct sun4i_usb_phy_cfg sun8i_r40_cfg = {
};
static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = {
.num_phys = 1,
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
@ -988,7 +980,6 @@ static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = {
};
static const struct sun4i_usb_phy_cfg sun20i_d1_cfg = {
.num_phys = 2,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
.hci_phy_ctl_clear = PHY_CTL_SIDDQ,
@ -997,7 +988,6 @@ static const struct sun4i_usb_phy_cfg sun20i_d1_cfg = {
};
static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
.num_phys = 2,
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
@ -1006,7 +996,6 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
};
static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = {
.num_phys = 4,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
.phy0_dual_route = true,
@ -1015,7 +1004,6 @@ static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = {
};
static const struct sun4i_usb_phy_cfg sun50i_h616_cfg = {
.num_phys = 4,
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,

View File

@ -850,4 +850,3 @@ MODULE_DESCRIPTION("Broadcom SATA PHY driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marc Carino");
MODULE_AUTHOR("Brian Norris");
MODULE_ALIAS("platform:phy-brcm-sata");

View File

@ -691,7 +691,6 @@ static struct platform_driver brcm_usb_driver = {
module_platform_driver(brcm_usb_driver);
MODULE_ALIAS("platform:brcmstb-usb-phy");
MODULE_AUTHOR("Al Cooper <acooper@broadcom.com>");
MODULE_DESCRIPTION("BRCM USB PHY driver");
MODULE_LICENSE("GPL v2");

View File

@ -12,6 +12,7 @@
#include <linux/phy/phy.h>
#include <linux/phy/phy-mipi-dphy.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/sys_soc.h>
#define DPHY_PMA_CMN(reg) (reg)
@ -265,7 +266,7 @@ static int cdns_dphy_rx_probe(struct platform_device *pdev)
return PTR_ERR(provider);
}
return 0;
return devm_pm_runtime_enable(dev);
}
static const struct of_device_id cdns_dphy_rx_of_match[] = {

View File

@ -30,6 +30,7 @@
#define DPHY_CMN_SSM DPHY_PMA_CMN(0x20)
#define DPHY_CMN_SSM_EN BIT(0)
#define DPHY_CMN_SSM_CAL_WAIT_TIME GENMASK(8, 1)
#define DPHY_CMN_TX_MODE_EN BIT(9)
#define DPHY_CMN_PWM DPHY_PMA_CMN(0x40)
@ -55,14 +56,6 @@
#define DPHY_PSM_CFG_FROM_REG BIT(0)
#define DPHY_PSM_CLK_DIV(x) ((x) << 1)
#define DSI_HBP_FRAME_OVERHEAD 12
#define DSI_HSA_FRAME_OVERHEAD 14
#define DSI_HFP_FRAME_OVERHEAD 6
#define DSI_HSS_VSS_VSE_FRAME_OVERHEAD 4
#define DSI_BLANKING_FRAME_OVERHEAD 6
#define DSI_NULL_FRAME_OVERHEAD 6
#define DSI_EOT_PKT_SIZE 4
#define DPHY_TX_J721E_WIZ_PLL_CTRL 0xF04
#define DPHY_TX_J721E_WIZ_STATUS 0xF08
#define DPHY_TX_J721E_WIZ_RST_CTRL 0xF0C
@ -79,6 +72,7 @@ struct cdns_dphy_cfg {
u8 pll_ipdiv;
u8 pll_opdiv;
u16 pll_fbdiv;
u32 hs_clk_rate;
unsigned int nlanes;
};
@ -99,6 +93,8 @@ struct cdns_dphy_ops {
void (*set_pll_cfg)(struct cdns_dphy *dphy,
const struct cdns_dphy_cfg *cfg);
unsigned long (*get_wakeup_time_ns)(struct cdns_dphy *dphy);
int (*wait_for_pll_lock)(struct cdns_dphy *dphy);
int (*wait_for_cmn_ready)(struct cdns_dphy *dphy);
};
struct cdns_dphy {
@ -108,6 +104,8 @@ struct cdns_dphy {
struct clk *pll_ref_clk;
const struct cdns_dphy_ops *ops;
struct phy *phy;
bool is_configured;
bool is_powered;
};
/* Order of bands is important since the index is the band number. */
@ -116,10 +114,9 @@ static const unsigned int tx_bands[] = {
870, 950, 1000, 1200, 1400, 1600, 1800, 2000, 2200, 2500
};
static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy,
struct cdns_dphy_cfg *cfg,
struct phy_configure_opts_mipi_dphy *opts,
unsigned int *dsi_hfp_ext)
static int cdns_dphy_get_pll_cfg(struct cdns_dphy *dphy,
struct cdns_dphy_cfg *cfg,
struct phy_configure_opts_mipi_dphy *opts)
{
unsigned long pll_ref_hz = clk_get_rate(dphy->pll_ref_clk);
u64 dlane_bps;
@ -139,7 +136,7 @@ static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy,
dlane_bps = opts->hs_clk_rate;
if (dlane_bps > 2500000000UL || dlane_bps < 160000000UL)
if (dlane_bps > 2500000000UL || dlane_bps < 80000000UL)
return -EINVAL;
else if (dlane_bps >= 1250000000)
cfg->pll_opdiv = 1;
@ -149,11 +146,16 @@ static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy,
cfg->pll_opdiv = 4;
else if (dlane_bps >= 160000000)
cfg->pll_opdiv = 8;
else if (dlane_bps >= 80000000)
cfg->pll_opdiv = 16;
cfg->pll_fbdiv = DIV_ROUND_UP_ULL(dlane_bps * 2 * cfg->pll_opdiv *
cfg->pll_ipdiv,
pll_ref_hz);
cfg->hs_clk_rate = div_u64((u64)pll_ref_hz * cfg->pll_fbdiv,
2 * cfg->pll_opdiv * cfg->pll_ipdiv);
return 0;
}
@ -191,6 +193,16 @@ static unsigned long cdns_dphy_get_wakeup_time_ns(struct cdns_dphy *dphy)
return dphy->ops->get_wakeup_time_ns(dphy);
}
static int cdns_dphy_wait_for_pll_lock(struct cdns_dphy *dphy)
{
return dphy->ops->wait_for_pll_lock ? dphy->ops->wait_for_pll_lock(dphy) : 0;
}
static int cdns_dphy_wait_for_cmn_ready(struct cdns_dphy *dphy)
{
return dphy->ops->wait_for_cmn_ready ? dphy->ops->wait_for_cmn_ready(dphy) : 0;
}
static unsigned long cdns_dphy_ref_get_wakeup_time_ns(struct cdns_dphy *dphy)
{
/* Default wakeup time is 800 ns (in a simulated environment). */
@ -232,7 +244,6 @@ static unsigned long cdns_dphy_j721e_get_wakeup_time_ns(struct cdns_dphy *dphy)
static void cdns_dphy_j721e_set_pll_cfg(struct cdns_dphy *dphy,
const struct cdns_dphy_cfg *cfg)
{
u32 status;
/*
* set the PWM and PLL Byteclk divider settings to recommended values
@ -249,13 +260,6 @@ static void cdns_dphy_j721e_set_pll_cfg(struct cdns_dphy *dphy,
writel(DPHY_TX_J721E_WIZ_LANE_RSTB,
dphy->regs + DPHY_TX_J721E_WIZ_RST_CTRL);
readl_poll_timeout(dphy->regs + DPHY_TX_J721E_WIZ_PLL_CTRL, status,
(status & DPHY_TX_WIZ_PLL_LOCK), 0, POLL_TIMEOUT_US);
readl_poll_timeout(dphy->regs + DPHY_TX_J721E_WIZ_STATUS, status,
(status & DPHY_TX_WIZ_O_CMN_READY), 0,
POLL_TIMEOUT_US);
}
static void cdns_dphy_j721e_set_psm_div(struct cdns_dphy *dphy, u8 div)
@ -263,6 +267,23 @@ static void cdns_dphy_j721e_set_psm_div(struct cdns_dphy *dphy, u8 div)
writel(div, dphy->regs + DPHY_TX_J721E_WIZ_PSM_FREQ);
}
static int cdns_dphy_j721e_wait_for_pll_lock(struct cdns_dphy *dphy)
{
u32 status;
return readl_poll_timeout(dphy->regs + DPHY_TX_J721E_WIZ_PLL_CTRL, status,
status & DPHY_TX_WIZ_PLL_LOCK, 0, POLL_TIMEOUT_US);
}
static int cdns_dphy_j721e_wait_for_cmn_ready(struct cdns_dphy *dphy)
{
u32 status;
return readl_poll_timeout(dphy->regs + DPHY_TX_J721E_WIZ_STATUS, status,
status & DPHY_TX_WIZ_O_CMN_READY, 0,
POLL_TIMEOUT_US);
}
/*
* This is the reference implementation of DPHY hooks. Specific integration of
* this IP may have to re-implement some of them depending on how they decided
@ -278,6 +299,8 @@ static const struct cdns_dphy_ops j721e_dphy_ops = {
.get_wakeup_time_ns = cdns_dphy_j721e_get_wakeup_time_ns,
.set_pll_cfg = cdns_dphy_j721e_set_pll_cfg,
.set_psm_div = cdns_dphy_j721e_set_psm_div,
.wait_for_pll_lock = cdns_dphy_j721e_wait_for_pll_lock,
.wait_for_cmn_ready = cdns_dphy_j721e_wait_for_cmn_ready,
};
static int cdns_dphy_config_from_opts(struct phy *phy,
@ -285,18 +308,17 @@ static int cdns_dphy_config_from_opts(struct phy *phy,
struct cdns_dphy_cfg *cfg)
{
struct cdns_dphy *dphy = phy_get_drvdata(phy);
unsigned int dsi_hfp_ext = 0;
int ret;
ret = phy_mipi_dphy_config_validate(opts);
if (ret)
return ret;
ret = cdns_dsi_get_dphy_pll_cfg(dphy, cfg,
opts, &dsi_hfp_ext);
ret = cdns_dphy_get_pll_cfg(dphy, cfg, opts);
if (ret)
return ret;
opts->hs_clk_rate = cfg->hs_clk_rate;
opts->wakeup = cdns_dphy_get_wakeup_time_ns(dphy) / 1000;
return 0;
@ -334,21 +356,36 @@ static int cdns_dphy_validate(struct phy *phy, enum phy_mode mode, int submode,
static int cdns_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
{
struct cdns_dphy *dphy = phy_get_drvdata(phy);
struct cdns_dphy_cfg cfg = { 0 };
int ret, band_ctrl;
unsigned int reg;
int ret;
ret = cdns_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg);
if (ret)
return ret;
ret = cdns_dphy_config_from_opts(phy, &opts->mipi_dphy, &dphy->cfg);
if (!ret)
dphy->is_configured = true;
return ret;
}
static int cdns_dphy_power_on(struct phy *phy)
{
struct cdns_dphy *dphy = phy_get_drvdata(phy);
int ret;
u32 reg;
if (!dphy->is_configured || dphy->is_powered)
return -EINVAL;
clk_prepare_enable(dphy->psm_clk);
clk_prepare_enable(dphy->pll_ref_clk);
/*
* Configure the internal PSM clk divider so that the DPHY has a
* 1MHz clk (or something close).
*/
ret = cdns_dphy_setup_psm(dphy);
if (ret)
return ret;
if (ret) {
dev_err(&dphy->phy->dev, "Failed to setup PSM with error %d\n", ret);
goto err_power_on;
}
/*
* Configure attach clk lanes to data lanes: the DPHY has 2 clk lanes
@ -363,40 +400,61 @@ static int cdns_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
* Configure the DPHY PLL that will be used to generate the TX byte
* clk.
*/
cdns_dphy_set_pll_cfg(dphy, &cfg);
cdns_dphy_set_pll_cfg(dphy, &dphy->cfg);
band_ctrl = cdns_dphy_tx_get_band_ctrl(opts->mipi_dphy.hs_clk_rate);
if (band_ctrl < 0)
return band_ctrl;
ret = cdns_dphy_tx_get_band_ctrl(dphy->cfg.hs_clk_rate);
if (ret < 0) {
dev_err(&dphy->phy->dev, "Failed to get band control value with error %d\n", ret);
goto err_power_on;
}
reg = FIELD_PREP(DPHY_BAND_CFG_LEFT_BAND, band_ctrl) |
FIELD_PREP(DPHY_BAND_CFG_RIGHT_BAND, band_ctrl);
reg = FIELD_PREP(DPHY_BAND_CFG_LEFT_BAND, ret) |
FIELD_PREP(DPHY_BAND_CFG_RIGHT_BAND, ret);
writel(reg, dphy->regs + DPHY_BAND_CFG);
return 0;
}
static int cdns_dphy_power_on(struct phy *phy)
{
struct cdns_dphy *dphy = phy_get_drvdata(phy);
clk_prepare_enable(dphy->psm_clk);
clk_prepare_enable(dphy->pll_ref_clk);
/* Start TX state machine. */
writel(DPHY_CMN_SSM_EN | DPHY_CMN_TX_MODE_EN,
reg = readl(dphy->regs + DPHY_CMN_SSM);
writel((reg & DPHY_CMN_SSM_CAL_WAIT_TIME) | DPHY_CMN_SSM_EN | DPHY_CMN_TX_MODE_EN,
dphy->regs + DPHY_CMN_SSM);
ret = cdns_dphy_wait_for_pll_lock(dphy);
if (ret) {
dev_err(&dphy->phy->dev, "Failed to lock PLL with error %d\n", ret);
goto err_power_on;
}
ret = cdns_dphy_wait_for_cmn_ready(dphy);
if (ret) {
dev_err(&dphy->phy->dev, "O_CMN_READY signal failed to assert with error %d\n",
ret);
goto err_power_on;
}
dphy->is_powered = true;
return 0;
err_power_on:
clk_disable_unprepare(dphy->pll_ref_clk);
clk_disable_unprepare(dphy->psm_clk);
return ret;
}
static int cdns_dphy_power_off(struct phy *phy)
{
struct cdns_dphy *dphy = phy_get_drvdata(phy);
u32 reg;
clk_disable_unprepare(dphy->pll_ref_clk);
clk_disable_unprepare(dphy->psm_clk);
/* Stop TX state machine. */
reg = readl(dphy->regs + DPHY_CMN_SSM);
writel(reg & ~DPHY_CMN_SSM_EN, dphy->regs + DPHY_CMN_SSM);
dphy->is_powered = false;
return 0;
}

View File

@ -2919,7 +2919,6 @@ static struct platform_driver cdns_sierra_driver = {
};
module_platform_driver(cdns_sierra_driver);
MODULE_ALIAS("platform:cdns_sierra");
MODULE_AUTHOR("Cadence Design Systems");
MODULE_DESCRIPTION("CDNS sierra phy driver");
MODULE_LICENSE("GPL v2");

View File

@ -188,6 +188,10 @@ static struct lynx_28g_pll *lynx_28g_pll_get(struct lynx_28g_priv *priv,
return pll;
}
/* no pll supports requested mode, either caller forgot to check
* lynx_28g_supports_lane_mode, or this is a bug.
*/
dev_WARN_ONCE(priv->dev, 1, "no pll for interface %s\n", phy_modes(intf));
return NULL;
}
@ -276,8 +280,12 @@ static void lynx_28g_lane_set_sgmii(struct lynx_28g_lane *lane)
lynx_28g_lane_rmw(lane, LNaGCR0, PROTO_SEL_SGMII, PROTO_SEL_MSK);
lynx_28g_lane_rmw(lane, LNaGCR0, IF_WIDTH_10_BIT, IF_WIDTH_MSK);
/* Switch to the PLL that works with this interface type */
/* Find the PLL that works with this interface type */
pll = lynx_28g_pll_get(priv, PHY_INTERFACE_MODE_SGMII);
if (unlikely(pll == NULL))
return;
/* Switch to the PLL that works with this interface type */
lynx_28g_lane_set_pll(lane, pll);
/* Choose the portion of clock net to be used on this lane */
@ -312,8 +320,12 @@ static void lynx_28g_lane_set_10gbaser(struct lynx_28g_lane *lane)
lynx_28g_lane_rmw(lane, LNaGCR0, PROTO_SEL_XFI, PROTO_SEL_MSK);
lynx_28g_lane_rmw(lane, LNaGCR0, IF_WIDTH_20_BIT, IF_WIDTH_MSK);
/* Switch to the PLL that works with this interface type */
/* Find the PLL that works with this interface type */
pll = lynx_28g_pll_get(priv, PHY_INTERFACE_MODE_10GBASER);
if (unlikely(pll == NULL))
return;
/* Switch to the PLL that works with this interface type */
lynx_28g_lane_set_pll(lane, pll);
/* Choose the portion of clock net to be used on this lane */

View File

@ -161,5 +161,4 @@ static struct platform_driver hi6220_phy_driver = {
module_platform_driver(hi6220_phy_driver);
MODULE_DESCRIPTION("HISILICON HI6220 USB PHY driver");
MODULE_ALIAS("platform:hi6220-usb-phy");
MODULE_LICENSE("GPL");

View File

@ -73,7 +73,7 @@ static void nano_register_write(struct histb_combphy_priv *priv,
static int is_mode_fixed(struct histb_combphy_mode *mode)
{
return (mode->fixed != PHY_NONE) ? true : false;
return mode->fixed != PHY_NONE;
}
static int histb_combphy_set_mode(struct histb_combphy_priv *priv)

View File

@ -339,17 +339,13 @@ static int ingenic_usb_phy_probe(struct platform_device *pdev)
priv->clk = devm_clk_get(dev, NULL);
if (IS_ERR(priv->clk)) {
err = PTR_ERR(priv->clk);
if (err != -EPROBE_DEFER)
dev_err(dev, "Failed to get clock\n");
return err;
return dev_err_probe(dev, err, "Failed to get clock\n");
}
priv->vcc_supply = devm_regulator_get(dev, "vcc");
if (IS_ERR(priv->vcc_supply)) {
err = PTR_ERR(priv->vcc_supply);
if (err != -EPROBE_DEFER)
dev_err(dev, "Failed to get regulator\n");
return err;
return dev_err_probe(dev, err, "Failed to get regulator\n");
}
priv->phy = devm_phy_create(dev, NULL, &ingenic_usb_phy_ops);

View File

@ -82,6 +82,14 @@ static const struct eusb2_repeater_cfg pm8550b_eusb2_cfg = {
.num_vregs = ARRAY_SIZE(pm8550b_vreg_l),
};
static const struct eusb2_repeater_cfg pmiv0104_eusb2_cfg = {
/* No PMIC-specific init sequence, only board level tuning via DT */
.init_tbl = (struct eusb2_repeater_init_tbl_reg[]) {},
.init_tbl_num = 0,
.vreg_list = pm8550b_vreg_l,
.num_vregs = ARRAY_SIZE(pm8550b_vreg_l),
};
static const struct eusb2_repeater_cfg smb2360_eusb2_cfg = {
.init_tbl = smb2360_init_tbl,
.init_tbl_num = ARRAY_SIZE(smb2360_init_tbl),
@ -136,6 +144,9 @@ static int eusb2_repeater_init(struct phy *phy)
if (!of_property_read_u8(np, "qcom,tune-usb2-amplitude", &val))
regmap_write(regmap, base + EUSB2_TUNE_IUSB2, val);
if (!of_property_read_u8(np, "qcom,tune-res-fsdif", &val))
regmap_write(regmap, base + EUSB2_TUNE_RES_FSDIF, val);
/* Wait for status OK */
ret = regmap_read_poll_timeout(regmap, base + EUSB2_RPTR_STATUS, poll_val,
poll_val & RPTR_OK, 10, 5);
@ -259,6 +270,10 @@ static const struct of_device_id eusb2_repeater_of_match_table[] = {
.compatible = "qcom,pm8550b-eusb2-repeater",
.data = &pm8550b_eusb2_cfg,
},
{
.compatible = "qcom,pmiv0104-eusb2-repeater",
.data = &pmiv0104_eusb2_cfg,
},
{
.compatible = "qcom,smb2360-eusb2-repeater",
.data = &smb2360_eusb2_cfg,

View File

@ -559,7 +559,6 @@ static struct platform_driver qcom_ipq806x_usb_phy_driver = {
module_platform_driver(qcom_ipq806x_usb_phy_driver);
MODULE_ALIAS("platform:phy-qcom-ipq806x-usb");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Andy Gross <agross@codeaurora.org>");
MODULE_AUTHOR("Ivan T. Ivanov <iivanov@mm-sol.com>");

View File

@ -196,7 +196,7 @@ static int m31eusb2_phy_init(struct phy *uphy)
ret = clk_prepare_enable(phy->clk);
if (ret) {
dev_err(&uphy->dev, "failed to enable cfg ahb clock, %d\n", ret);
dev_err(&uphy->dev, "failed to enable ref clock, %d\n", ret);
goto disable_repeater;
}

View File

@ -19,6 +19,7 @@
#include <linux/reset.h>
#include <linux/slab.h>
#include <linux/usb/typec.h>
#include <linux/usb/typec_dp.h>
#include <linux/usb/typec_mux.h>
#include <drm/bridge/aux-bridge.h>
@ -62,6 +63,12 @@
#define PHY_INIT_COMPLETE_TIMEOUT 10000
enum qmpphy_mode {
QMPPHY_MODE_USB3DP = 0,
QMPPHY_MODE_DP_ONLY,
QMPPHY_MODE_USB3_ONLY,
};
/* set of registers with offsets different per-PHY */
enum qphy_reg_layout {
/* PCS registers */
@ -1844,15 +1851,17 @@ struct qmp_combo {
struct mutex phy_mutex;
int init_count;
enum qmpphy_mode qmpphy_mode;
struct phy *usb_phy;
enum phy_mode mode;
enum phy_mode phy_mode;
unsigned int usb_init_count;
struct phy *dp_phy;
unsigned int dp_aux_cfg;
struct phy_configure_opts_dp dp_opts;
unsigned int dp_init_count;
bool dp_powered_on;
struct clk_fixed_rate pipe_clk_fixed;
struct clk_hw dp_link_hw;
@ -1860,6 +1869,8 @@ struct qmp_combo {
struct typec_switch_dev *sw;
enum typec_orientation orientation;
struct typec_mux_dev *mux;
};
static void qmp_v3_dp_aux_init(struct qmp_combo *qmp);
@ -3036,12 +3047,33 @@ static int qmp_combo_com_init(struct qmp_combo *qmp, bool force)
if (qmp->orientation == TYPEC_ORIENTATION_REVERSE)
val |= SW_PORTSELECT_VAL;
writel(val, com + QPHY_V3_DP_COM_TYPEC_CTRL);
writel(USB3_MODE | DP_MODE, com + QPHY_V3_DP_COM_PHY_MODE_CTRL);
/* bring both QMP USB and QMP DP PHYs PCS block out of reset */
qphy_clrbits(com, QPHY_V3_DP_COM_RESET_OVRD_CTRL,
SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
switch (qmp->qmpphy_mode) {
case QMPPHY_MODE_USB3DP:
writel(USB3_MODE | DP_MODE, com + QPHY_V3_DP_COM_PHY_MODE_CTRL);
/* bring both QMP USB and QMP DP PHYs PCS block out of reset */
qphy_clrbits(com, QPHY_V3_DP_COM_RESET_OVRD_CTRL,
SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
break;
case QMPPHY_MODE_DP_ONLY:
writel(DP_MODE, com + QPHY_V3_DP_COM_PHY_MODE_CTRL);
/* bring QMP DP PHY PCS block out of reset */
qphy_clrbits(com, QPHY_V3_DP_COM_RESET_OVRD_CTRL,
SW_DPPHY_RESET_MUX | SW_DPPHY_RESET);
break;
case QMPPHY_MODE_USB3_ONLY:
writel(USB3_MODE, com + QPHY_V3_DP_COM_PHY_MODE_CTRL);
/* bring QMP USB PHY PCS block out of reset */
qphy_clrbits(com, QPHY_V3_DP_COM_RESET_OVRD_CTRL,
SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
break;
}
qphy_clrbits(com, QPHY_V3_DP_COM_SWI_CTRL, 0x03);
qphy_clrbits(com, QPHY_V3_DP_COM_SW_RESET, SW_RESET);
@ -3133,6 +3165,8 @@ static int qmp_combo_dp_power_on(struct phy *phy)
/* Configure link rate, swing, etc. */
cfg->configure_dp_phy(qmp);
qmp->dp_powered_on = true;
mutex_unlock(&qmp->phy_mutex);
return 0;
@ -3147,6 +3181,8 @@ static int qmp_combo_dp_power_off(struct phy *phy)
/* Assert DP PHY power down */
writel(DP_PHY_PD_CTL_PSR_PWRDN, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL);
qmp->dp_powered_on = false;
mutex_unlock(&qmp->phy_mutex);
return 0;
@ -3282,7 +3318,7 @@ static int qmp_combo_usb_set_mode(struct phy *phy, enum phy_mode mode, int submo
{
struct qmp_combo *qmp = phy_get_drvdata(phy);
qmp->mode = mode;
qmp->phy_mode = mode;
return 0;
}
@ -3311,8 +3347,8 @@ static void qmp_combo_enable_autonomous_mode(struct qmp_combo *qmp)
void __iomem *pcs_misc = qmp->pcs_misc;
u32 intr_mask;
if (qmp->mode == PHY_MODE_USB_HOST_SS ||
qmp->mode == PHY_MODE_USB_DEVICE_SS)
if (qmp->phy_mode == PHY_MODE_USB_HOST_SS ||
qmp->phy_mode == PHY_MODE_USB_DEVICE_SS)
intr_mask = ARCVR_DTCT_EN | ALFPS_DTCT_EN;
else
intr_mask = ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL;
@ -3355,7 +3391,7 @@ static int __maybe_unused qmp_combo_runtime_suspend(struct device *dev)
{
struct qmp_combo *qmp = dev_get_drvdata(dev);
dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qmp->mode);
dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qmp->phy_mode);
if (!qmp->init_count) {
dev_vdbg(dev, "PHY not initialized, bailing out\n");
@ -3375,7 +3411,7 @@ static int __maybe_unused qmp_combo_runtime_resume(struct device *dev)
struct qmp_combo *qmp = dev_get_drvdata(dev);
int ret = 0;
dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qmp->mode);
dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qmp->phy_mode);
if (!qmp->init_count) {
dev_vdbg(dev, "PHY not initialized, bailing out\n");
@ -3769,17 +3805,109 @@ static int qmp_combo_typec_switch_set(struct typec_switch_dev *sw,
return 0;
}
static void qmp_combo_typec_unregister(void *data)
static int qmp_combo_typec_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state)
{
struct qmp_combo *qmp = typec_mux_get_drvdata(mux);
const struct qmp_phy_cfg *cfg = qmp->cfg;
enum qmpphy_mode new_mode;
unsigned int svid;
guard(mutex)(&qmp->phy_mutex);
if (state->alt)
svid = state->alt->svid;
else
svid = 0;
if (svid == USB_TYPEC_DP_SID) {
switch (state->mode) {
/* DP Only */
case TYPEC_DP_STATE_C:
case TYPEC_DP_STATE_E:
new_mode = QMPPHY_MODE_DP_ONLY;
break;
/* DP + USB */
case TYPEC_DP_STATE_D:
case TYPEC_DP_STATE_F:
/* Safe fallback...*/
default:
new_mode = QMPPHY_MODE_USB3DP;
break;
}
} else {
/* No DP SVID => don't care, assume it's just USB3 */
new_mode = QMPPHY_MODE_USB3_ONLY;
}
if (new_mode == qmp->qmpphy_mode) {
dev_dbg(qmp->dev, "typec_mux_set: same qmpphy mode, bail out\n");
return 0;
}
if (qmp->qmpphy_mode != QMPPHY_MODE_USB3_ONLY && qmp->dp_powered_on) {
dev_dbg(qmp->dev, "typec_mux_set: DP PHY is still in use, delaying switch\n");
return 0;
}
dev_dbg(qmp->dev, "typec_mux_set: switching from qmpphy mode %d to %d\n",
qmp->qmpphy_mode, new_mode);
qmp->qmpphy_mode = new_mode;
if (qmp->init_count) {
if (qmp->usb_init_count)
qmp_combo_usb_power_off(qmp->usb_phy);
if (qmp->dp_init_count)
writel(DP_PHY_PD_CTL_PSR_PWRDN, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL);
qmp_combo_com_exit(qmp, true);
/* Now everything's powered down, power up the right PHYs */
qmp_combo_com_init(qmp, true);
if (new_mode == QMPPHY_MODE_DP_ONLY) {
if (qmp->usb_init_count)
qmp->usb_init_count--;
}
if (new_mode == QMPPHY_MODE_USB3DP || new_mode == QMPPHY_MODE_USB3_ONLY) {
qmp_combo_usb_power_on(qmp->usb_phy);
if (!qmp->usb_init_count)
qmp->usb_init_count++;
}
if (new_mode == QMPPHY_MODE_DP_ONLY || new_mode == QMPPHY_MODE_USB3DP) {
if (qmp->dp_init_count)
cfg->dp_aux_init(qmp);
}
}
return 0;
}
static void qmp_combo_typec_switch_unregister(void *data)
{
struct qmp_combo *qmp = data;
typec_switch_unregister(qmp->sw);
}
static int qmp_combo_typec_switch_register(struct qmp_combo *qmp)
static void qmp_combo_typec_mux_unregister(void *data)
{
struct qmp_combo *qmp = data;
typec_mux_unregister(qmp->mux);
}
static int qmp_combo_typec_register(struct qmp_combo *qmp)
{
struct typec_switch_desc sw_desc = {};
struct typec_mux_desc mux_desc = { };
struct device *dev = qmp->dev;
int ret;
sw_desc.drvdata = qmp;
sw_desc.fwnode = dev->fwnode;
@ -3790,10 +3918,23 @@ static int qmp_combo_typec_switch_register(struct qmp_combo *qmp)
return PTR_ERR(qmp->sw);
}
return devm_add_action_or_reset(dev, qmp_combo_typec_unregister, qmp);
ret = devm_add_action_or_reset(dev, qmp_combo_typec_switch_unregister, qmp);
if (ret)
return ret;
mux_desc.drvdata = qmp;
mux_desc.fwnode = dev->fwnode;
mux_desc.set = qmp_combo_typec_mux_set;
qmp->mux = typec_mux_register(dev, &mux_desc);
if (IS_ERR(qmp->mux)) {
dev_err(dev, "Unable to register typec mux: %pe\n", qmp->mux);
return PTR_ERR(qmp->mux);
}
return devm_add_action_or_reset(dev, qmp_combo_typec_mux_unregister, qmp);
}
#else
static int qmp_combo_typec_switch_register(struct qmp_combo *qmp)
static int qmp_combo_typec_register(struct qmp_combo *qmp)
{
return 0;
}
@ -4026,7 +4167,7 @@ static int qmp_combo_probe(struct platform_device *pdev)
if (ret)
goto err_node_put;
ret = qmp_combo_typec_switch_register(qmp);
ret = qmp_combo_typec_register(qmp);
if (ret)
goto err_node_put;
@ -4048,6 +4189,12 @@ static int qmp_combo_probe(struct platform_device *pdev)
if (ret)
goto err_node_put;
/*
* The hw default is USB3_ONLY, but USB3+DP mode lets us more easily
* check both sub-blocks' init tables for blunders at probe time.
*/
qmp->qmpphy_mode = QMPPHY_MODE_USB3DP;
qmp->usb_phy = devm_phy_create(dev, usb_np, &qmp_combo_usb_phy_ops);
if (IS_ERR(qmp->usb_phy)) {
ret = PTR_ERR(qmp->usb_phy);

View File

@ -93,6 +93,13 @@ static const unsigned int pciephy_v6_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V6_PCS_POWER_DOWN_CONTROL,
};
static const unsigned int pciephy_v7_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_SW_RESET] = QPHY_V7_PCS_SW_RESET,
[QPHY_START_CTRL] = QPHY_V7_PCS_START_CONTROL,
[QPHY_PCS_STATUS] = QPHY_V7_PCS_PCS_STATUS1,
[QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V7_PCS_POWER_DOWN_CONTROL,
};
static const struct qmp_phy_init_tbl msm8998_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30),
@ -2590,6 +2597,108 @@ static const struct qmp_phy_init_tbl sm8650_qmp_gen4x2_pcie_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B6, 0xff),
};
static const struct qmp_phy_init_tbl sm8750_qmp_gen3x2_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V7_COM_SSC_EN_CENTER, 0x1),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_SSC_PER1, 0x62),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_SSC_PER2, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_SSC_STEP_SIZE1_MODE0, 0xf8),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_SSC_STEP_SIZE2_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_SSC_STEP_SIZE1_MODE1, 0x93),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_SSC_STEP_SIZE2_MODE1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_CLK_ENABLE1, 0x90),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_SYS_CLK_CTRL, 0x82),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_PLL_IVCO, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_CP_CTRL_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_CP_CTRL_MODE1, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_PLL_RCTRL_MODE1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_PLL_CCTRL_MODE0, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_PLL_CCTRL_MODE1, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_SYSCLK_EN_SEL, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_BG_TIMER, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_LOCK_CMP_EN, 0x42),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_LOCK_CMP1_MODE0, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_LOCK_CMP2_MODE0, 0x0d),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_LOCK_CMP1_MODE1, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_LOCK_CMP2_MODE1, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_DEC_START_MODE0, 0x41),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_DEC_START_MODE1, 0x34),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_DIV_FRAC_START1_MODE0, 0xab),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_DIV_FRAC_START2_MODE0, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_DIV_FRAC_START3_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_DIV_FRAC_START1_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_DIV_FRAC_START2_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_DIV_FRAC_START3_MODE1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_VCO_TUNE_MAP, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_CLK_SELECT, 0x34),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_HSCLK_SEL_1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_CORECLK_DIV_MODE1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_CMN_CONFIG_1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_ADDITIONAL_MISC_3, 0x0F),
QMP_PHY_INIT_CFG(QSERDES_V7_COM_CORE_CLK_EN, 0xA0),
};
static const struct qmp_phy_init_tbl sm8750_qmp_gen3x2_pcie_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V7_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_GM_CAL, 0x11),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_RX_MODE_00_HIGH, 0xBF),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_RX_MODE_00_HIGH2, 0xBF),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_RX_MODE_00_HIGH3, 0xB7),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_RX_MODE_00_HIGH4, 0xEA),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_RX_MODE_00_LOW, 0x3F),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_RX_MODE_01_HIGH, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_RX_MODE_01_HIGH2, 0x49),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_RX_MODE_01_HIGH3, 0x1B),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_RX_MODE_01_HIGH4, 0x9C),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_RX_MODE_01_LOW, 0xD1),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_RX_MODE_10_HIGH, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_RX_MODE_10_HIGH2, 0x49),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_RX_MODE_10_HIGH3, 0x1B),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_RX_MODE_10_HIGH4, 0x9C),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_RX_MODE_10_LOW, 0xD1),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_TX_ADAPT_PRE_THRESH1, 0x3E),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_TX_ADAPT_PRE_THRESH2, 0x1E),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_TX_ADAPT_POST_THRESH, 0xD2),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_UCDR_FO_GAIN, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_UCDR_SO_GAIN, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_UCDR_SB2_THRESH1, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_UCDR_SB2_THRESH2, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_VGA_CAL_CNTRL2, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_SIGDET_ENABLES, 0x1C),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_SIGDET_CNTRL, 0x60),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_RX_IDAC_TSETTLE_LOW, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V7_RX_SIGDET_CAL_TRIM, 0x08),
};
static const struct qmp_phy_init_tbl sm8750_qmp_gen3x2_pcie_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V7_TX_LANE_MODE_1, 0x35),
QMP_PHY_INIT_CFG(QSERDES_V7_TX_LANE_MODE_3, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V7_TX_LANE_MODE_4, 0x31),
QMP_PHY_INIT_CFG(QSERDES_V7_TX_LANE_MODE_5, 0x7F),
QMP_PHY_INIT_CFG(QSERDES_V7_TX_PI_QEC_CTRL, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V7_TX_RES_CODE_LANE_OFFSET_RX, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V7_TX_RES_CODE_LANE_OFFSET_TX, 0x14),
};
static const struct qmp_phy_init_tbl sm8750_qmp_gen3x2_pcie_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V7_PCS_REFGEN_REQ_CONFIG1, 0x05),
QMP_PHY_INIT_CFG(QPHY_V7_PCS_RX_SIGDET_LVL, 0x77),
QMP_PHY_INIT_CFG(QPHY_V7_PCS_RATE_SLEW_CNTRL1, 0x0B),
QMP_PHY_INIT_CFG(QPHY_V7_PCS_EQ_CONFIG2, 0x0F),
QMP_PHY_INIT_CFG(QPHY_V7_PCS_PCS_TX_RX_CONFIG, 0x8C),
QMP_PHY_INIT_CFG(QPHY_V7_PCS_G12S1_TXDEEMPH_M6DB, 0x17),
QMP_PHY_INIT_CFG(QPHY_V7_PCS_G3S2_PRE_GAIN, 0x2E),
};
static const struct qmp_phy_init_tbl sm8750_qmp_gen3x2_pcie_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_EQ_CONFIG1, 0x1E),
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_RXEQEVAL_TIME, 0x27),
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG2, 0x1D),
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG4, 0x07),
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xC1),
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00),
};
static const struct qmp_phy_init_tbl sa8775p_qmp_gen4x2_pcie_serdes_alt_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f),
@ -3215,6 +3324,16 @@ static const struct qmp_pcie_offsets qmp_pcie_offsets_v5_30 = {
.rx2 = 0x3a00,
};
static const struct qmp_pcie_offsets qmp_pcie_offsets_v7 = {
.serdes = 0x0,
.pcs = 0x400,
.pcs_misc = 0x800,
.tx = 0x1000,
.rx = 0x1200,
.tx2 = 0x1800,
.rx2 = 0x1a00,
};
static const struct qmp_pcie_offsets qmp_pcie_offsets_v6_20 = {
.serdes = 0x1000,
.pcs = 0x1200,
@ -4004,6 +4123,33 @@ static const struct qmp_phy_cfg sm8550_qmp_gen3x2_pciephy_cfg = {
.phy_status = PHYSTATUS,
};
static const struct qmp_phy_cfg sm8750_qmp_gen3x2_pciephy_cfg = {
.lanes = 2,
.offsets = &qmp_pcie_offsets_v7,
.tbls = {
.serdes = sm8750_qmp_gen3x2_pcie_serdes_tbl,
.serdes_num = ARRAY_SIZE(sm8750_qmp_gen3x2_pcie_serdes_tbl),
.tx = sm8750_qmp_gen3x2_pcie_tx_tbl,
.tx_num = ARRAY_SIZE(sm8750_qmp_gen3x2_pcie_tx_tbl),
.rx = sm8750_qmp_gen3x2_pcie_rx_tbl,
.rx_num = ARRAY_SIZE(sm8750_qmp_gen3x2_pcie_rx_tbl),
.pcs = sm8750_qmp_gen3x2_pcie_pcs_tbl,
.pcs_num = ARRAY_SIZE(sm8750_qmp_gen3x2_pcie_pcs_tbl),
.pcs_misc = sm8750_qmp_gen3x2_pcie_pcs_misc_tbl,
.pcs_misc_num = ARRAY_SIZE(sm8750_qmp_gen3x2_pcie_pcs_misc_tbl),
},
.reset_list = sdm845_pciephy_reset_l,
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = pciephy_v7_regs_layout,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS,
};
static const struct qmp_phy_cfg sm8550_qmp_gen4x2_pciephy_cfg = {
.lanes = 2,
@ -5112,6 +5258,9 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
}, {
.compatible = "qcom,sm8650-qmp-gen4x2-pcie-phy",
.data = &sm8650_qmp_gen4x2_pciephy_cfg,
}, {
.compatible = "qcom,sm8750-qmp-gen3x2-pcie-phy",
.data = &sm8750_qmp_gen3x2_pciephy_cfg,
}, {
.compatible = "qcom,x1e80100-qmp-gen3x2-pcie-phy",
.data = &sm8550_qmp_gen3x2_pciephy_cfg,

View File

@ -17,6 +17,8 @@
#define QPHY_V7_PCS_LOCK_DETECT_CONFIG3 0x0cc
#define QPHY_V7_PCS_LOCK_DETECT_CONFIG6 0x0d8
#define QPHY_V7_PCS_REFGEN_REQ_CONFIG1 0x0dc
#define QPHY_V7_PCS_G12S1_TXDEEMPH_M6DB 0x168
#define QPHY_V7_PCS_G3S2_PRE_GAIN 0x170
#define QPHY_V7_PCS_RX_SIGDET_LVL 0x188
#define QPHY_V7_PCS_RCVR_DTCT_DLY_P1U2_L 0x190
#define QPHY_V7_PCS_RCVR_DTCT_DLY_P1U2_H 0x194

View File

@ -40,6 +40,8 @@
#define QSERDES_V7_RX_UCDR_SB2_GAIN1 0x54
#define QSERDES_V7_RX_UCDR_SB2_GAIN2 0x58
#define QSERDES_V7_RX_AUX_DATA_TCOARSE_TFINE 0x60
#define QSERDES_V7_RX_TX_ADAPT_PRE_THRESH1 0xc4
#define QSERDES_V7_RX_TX_ADAPT_PRE_THRESH2 0xc8
#define QSERDES_V7_RX_TX_ADAPT_POST_THRESH 0xcc
#define QSERDES_V7_RX_VGA_CAL_CNTRL1 0xd4
#define QSERDES_V7_RX_VGA_CAL_CNTRL2 0xd8
@ -50,7 +52,7 @@
#define QSERDES_V7_RX_RX_IDAC_TSETTLE_LOW 0xf8
#define QSERDES_V7_RX_RX_IDAC_TSETTLE_HIGH 0xfc
#define QSERDES_V7_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x110
#define QSERDES_V7_RX_SIDGET_ENABLES 0x118
#define QSERDES_V7_RX_SIGDET_ENABLES 0x118
#define QSERDES_V7_RX_SIGDET_CNTRL 0x11c
#define QSERDES_V7_RX_SIGDET_DEGLITCH_CNTRL 0x124
#define QSERDES_V7_RX_RX_MODE_00_LOW 0x15c

View File

@ -1107,7 +1107,7 @@ struct qmp_phy_cfg {
const struct qmp_phy_cfg_tbls tbls_hs_overlay[NUM_OVERLAY];
/* regulators to be requested */
const char * const *vreg_list;
const struct regulator_bulk_data *vreg_list;
int num_vregs;
/* array of registers with different offsets */
@ -1164,9 +1164,80 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
readl(base + offset);
}
/* list of regulators */
static const char * const qmp_phy_vreg_l[] = {
"vdda-phy", "vdda-pll",
/* Regulator bulk data with load values for specific configurations */
static const struct regulator_bulk_data msm8996_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 51400 },
{ .supply = "vdda-pll", .init_load_uA = 14600 },
};
static const struct regulator_bulk_data sa8775p_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 137000 },
{ .supply = "vdda-pll", .init_load_uA = 18300 },
};
static const struct regulator_bulk_data sc7280_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 97500 },
{ .supply = "vdda-pll", .init_load_uA = 18400 },
};
static const struct regulator_bulk_data sc8280xp_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 85700 },
{ .supply = "vdda-pll", .init_load_uA = 18300 },
};
static const struct regulator_bulk_data sdm845_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 51400 },
{ .supply = "vdda-pll", .init_load_uA = 14600 },
};
static const struct regulator_bulk_data sm6115_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 51400 },
{ .supply = "vdda-pll", .init_load_uA = 14200 },
};
static const struct regulator_bulk_data sm7150_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 62900 },
{ .supply = "vdda-pll", .init_load_uA = 18300 },
};
static const struct regulator_bulk_data sm8150_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 90200 },
{ .supply = "vdda-pll", .init_load_uA = 19000 },
};
static const struct regulator_bulk_data sm8250_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 89900 },
{ .supply = "vdda-pll", .init_load_uA = 18800 },
};
static const struct regulator_bulk_data sm8350_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 91600 },
{ .supply = "vdda-pll", .init_load_uA = 19000 },
};
static const struct regulator_bulk_data sm8450_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 173000 },
{ .supply = "vdda-pll", .init_load_uA = 24900 },
};
static const struct regulator_bulk_data sm8475_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 213030 },
{ .supply = "vdda-pll", .init_load_uA = 18340 },
};
static const struct regulator_bulk_data sm8550_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 188000 },
{ .supply = "vdda-pll", .init_load_uA = 18300 },
};
static const struct regulator_bulk_data sm8650_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 205000 },
{ .supply = "vdda-pll", .init_load_uA = 17500 },
};
static const struct regulator_bulk_data sm8750_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 213000 },
{ .supply = "vdda-pll", .init_load_uA = 18300 },
};
static const struct qmp_ufs_offsets qmp_ufs_offsets = {
@ -1202,8 +1273,8 @@ static const struct qmp_phy_cfg msm8996_ufsphy_cfg = {
.rx_num = ARRAY_SIZE(msm8996_ufsphy_rx),
},
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.vreg_list = msm8996_ufsphy_vreg_l,
.num_vregs = ARRAY_SIZE(msm8996_ufsphy_vreg_l),
.regs = ufsphy_v2_regs_layout,
@ -1239,8 +1310,8 @@ static const struct qmp_phy_cfg sa8775p_ufsphy_cfg = {
.pcs_num = ARRAY_SIZE(sm8350_ufsphy_g4_pcs),
.max_gear = UFS_HS_G4,
},
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.vreg_list = sa8775p_ufsphy_vreg_l,
.num_vregs = ARRAY_SIZE(sa8775p_ufsphy_vreg_l),
.regs = ufsphy_v5_regs_layout,
};
@ -1273,8 +1344,8 @@ static const struct qmp_phy_cfg sc7280_ufsphy_cfg = {
.pcs_num = ARRAY_SIZE(sm8150_ufsphy_hs_g4_pcs),
.max_gear = UFS_HS_G4,
},
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.vreg_list = sc7280_ufsphy_vreg_l,
.num_vregs = ARRAY_SIZE(sc7280_ufsphy_vreg_l),
.regs = ufsphy_v4_regs_layout,
};
@ -1307,8 +1378,8 @@ static const struct qmp_phy_cfg sc8280xp_ufsphy_cfg = {
.pcs_num = ARRAY_SIZE(sm8350_ufsphy_g4_pcs),
.max_gear = UFS_HS_G4,
},
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.vreg_list = sc8280xp_ufsphy_vreg_l,
.num_vregs = ARRAY_SIZE(sc8280xp_ufsphy_vreg_l),
.regs = ufsphy_v5_regs_layout,
};
@ -1332,8 +1403,8 @@ static const struct qmp_phy_cfg sdm845_ufsphy_cfg = {
.serdes = sdm845_ufsphy_hs_b_serdes,
.serdes_num = ARRAY_SIZE(sdm845_ufsphy_hs_b_serdes),
},
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.vreg_list = sdm845_ufsphy_vreg_l,
.num_vregs = ARRAY_SIZE(sdm845_ufsphy_vreg_l),
.regs = ufsphy_v3_regs_layout,
.no_pcs_sw_reset = true,
@ -1359,8 +1430,8 @@ static const struct qmp_phy_cfg sm6115_ufsphy_cfg = {
.serdes = sm6115_ufsphy_hs_b_serdes,
.serdes_num = ARRAY_SIZE(sm6115_ufsphy_hs_b_serdes),
},
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.vreg_list = sm6115_ufsphy_vreg_l,
.num_vregs = ARRAY_SIZE(sm6115_ufsphy_vreg_l),
.regs = ufsphy_v2_regs_layout,
.no_pcs_sw_reset = true,
@ -1386,8 +1457,8 @@ static const struct qmp_phy_cfg sm7150_ufsphy_cfg = {
.serdes = sdm845_ufsphy_hs_b_serdes,
.serdes_num = ARRAY_SIZE(sdm845_ufsphy_hs_b_serdes),
},
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.vreg_list = sm7150_ufsphy_vreg_l,
.num_vregs = ARRAY_SIZE(sm7150_ufsphy_vreg_l),
.regs = ufsphy_v3_regs_layout,
.no_pcs_sw_reset = true,
@ -1422,8 +1493,8 @@ static const struct qmp_phy_cfg sm8150_ufsphy_cfg = {
.pcs_num = ARRAY_SIZE(sm8150_ufsphy_hs_g4_pcs),
.max_gear = UFS_HS_G4,
},
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.vreg_list = sm8150_ufsphy_vreg_l,
.num_vregs = ARRAY_SIZE(sm8150_ufsphy_vreg_l),
.regs = ufsphy_v4_regs_layout,
};
@ -1456,8 +1527,8 @@ static const struct qmp_phy_cfg sm8250_ufsphy_cfg = {
.pcs_num = ARRAY_SIZE(sm8150_ufsphy_hs_g4_pcs),
.max_gear = UFS_HS_G4,
},
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.vreg_list = sm8250_ufsphy_vreg_l,
.num_vregs = ARRAY_SIZE(sm8250_ufsphy_vreg_l),
.regs = ufsphy_v4_regs_layout,
};
@ -1490,8 +1561,8 @@ static const struct qmp_phy_cfg sm8350_ufsphy_cfg = {
.pcs_num = ARRAY_SIZE(sm8350_ufsphy_g4_pcs),
.max_gear = UFS_HS_G4,
},
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.vreg_list = sm8350_ufsphy_vreg_l,
.num_vregs = ARRAY_SIZE(sm8350_ufsphy_vreg_l),
.regs = ufsphy_v5_regs_layout,
};
@ -1524,8 +1595,8 @@ static const struct qmp_phy_cfg sm8450_ufsphy_cfg = {
.pcs_num = ARRAY_SIZE(sm8350_ufsphy_g4_pcs),
.max_gear = UFS_HS_G4,
},
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.vreg_list = sm8450_ufsphy_vreg_l,
.num_vregs = ARRAY_SIZE(sm8450_ufsphy_vreg_l),
.regs = ufsphy_v5_regs_layout,
};
@ -1560,8 +1631,8 @@ static const struct qmp_phy_cfg sm8475_ufsphy_cfg = {
.pcs_num = ARRAY_SIZE(sm8475_ufsphy_g4_pcs),
.max_gear = UFS_HS_G4,
},
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.vreg_list = sm8475_ufsphy_vreg_l,
.num_vregs = ARRAY_SIZE(sm8475_ufsphy_vreg_l),
.regs = ufsphy_v6_regs_layout,
};
@ -1605,8 +1676,8 @@ static const struct qmp_phy_cfg sm8550_ufsphy_cfg = {
.pcs_num = ARRAY_SIZE(sm8550_ufsphy_g5_pcs),
.max_gear = UFS_HS_G5,
},
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.vreg_list = sm8550_ufsphy_vreg_l,
.num_vregs = ARRAY_SIZE(sm8550_ufsphy_vreg_l),
.regs = ufsphy_v6_regs_layout,
};
@ -1637,8 +1708,8 @@ static const struct qmp_phy_cfg sm8650_ufsphy_cfg = {
.max_gear = UFS_HS_G5,
},
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.vreg_list = sm8650_ufsphy_vreg_l,
.num_vregs = ARRAY_SIZE(sm8650_ufsphy_vreg_l),
.regs = ufsphy_v6_regs_layout,
};
@ -1675,8 +1746,8 @@ static const struct qmp_phy_cfg sm8750_ufsphy_cfg = {
.max_gear = UFS_HS_G5,
},
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.vreg_list = sm8750_ufsphy_vreg_l,
.num_vregs = ARRAY_SIZE(sm8750_ufsphy_vreg_l),
.regs = ufsphy_v6_regs_layout,
};
@ -1890,22 +1961,6 @@ static const struct phy_ops qcom_qmp_ufs_phy_ops = {
.owner = THIS_MODULE,
};
static int qmp_ufs_vreg_init(struct qmp_ufs *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
struct device *dev = qmp->dev;
int num = cfg->num_vregs;
int i;
qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL);
if (!qmp->vregs)
return -ENOMEM;
for (i = 0; i < num; i++)
qmp->vregs[i].supply = cfg->vreg_list[i];
return devm_regulator_bulk_get(dev, num, qmp->vregs);
}
static int qmp_ufs_clk_init(struct qmp_ufs *qmp)
{
@ -2068,7 +2123,9 @@ static int qmp_ufs_probe(struct platform_device *pdev)
if (ret)
return ret;
ret = qmp_ufs_vreg_init(qmp);
ret = devm_regulator_bulk_get_const(dev, qmp->cfg->num_vregs,
qmp->cfg->vreg_list,
&qmp->vregs);
if (ret)
return ret;

View File

@ -9,6 +9,8 @@
* Copyright (C) 2014 Cogent Embedded, Inc.
*/
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/cleanup.h>
#include <linux/extcon-provider.h>
#include <linux/interrupt.h>
@ -69,14 +71,20 @@
#define USB2_COMMCTRL_OTG_PERI BIT(31) /* 1 = Peripheral mode */
/* OBINTSTA and OBINTEN */
#define USB2_OBINTSTA_CLEAR GENMASK(31, 0)
#define USB2_OBINT_SESSVLDCHG BIT(12)
#define USB2_OBINT_IDDIGCHG BIT(11)
#define USB2_OBINT_BITS (USB2_OBINT_SESSVLDCHG | \
USB2_OBINT_IDDIGCHG)
#define USB2_OBINT_VBSTAINT BIT(3)
#define USB2_OBINT_IDCHG_EN BIT(0) /* RZ/G2L specific */
/* VBCTRL */
#define USB2_VBCTRL_VBSTA_MASK GENMASK(31, 28)
#define USB2_VBCTRL_VBSTA_DEFAULT 2
#define USB2_VBCTRL_VBLVL_MASK GENMASK(23, 20)
#define USB2_VBCTRL_VBLVL(m) FIELD_PREP_CONST(USB2_VBCTRL_VBLVL_MASK, (m))
#define USB2_VBCTRL_OCCLREN BIT(16)
#define USB2_VBCTRL_DRVVBUSSEL BIT(8)
#define USB2_VBCTRL_SIDDQREL BIT(2)
#define USB2_VBCTRL_VBOUT BIT(0)
/* LINECTRL1 */
@ -89,11 +97,11 @@
/* ADPCTRL */
#define USB2_ADPCTRL_OTGSESSVLD BIT(20)
#define USB2_ADPCTRL_IDDIG BIT(19)
#define USB2_ADPCTRL_VBUSVALID BIT(18)
#define USB2_ADPCTRL_IDPULLUP BIT(5) /* 1 = ID sampling is enabled */
#define USB2_ADPCTRL_DRVVBUS BIT(4)
/* RZ/G2L specific */
#define USB2_OBINT_IDCHG_EN BIT(0)
#define USB2_LINECTRL1_USB2_IDMON BIT(0)
#define NUM_OF_PHYS 4
@ -122,6 +130,7 @@ struct rcar_gen3_phy {
struct rcar_gen3_chan {
void __iomem *base;
struct device *dev; /* platform_device's device */
const struct rcar_gen3_phy_drv_data *phy_data;
struct extcon_dev *extcon;
struct rcar_gen3_phy rphys[NUM_OF_PHYS];
struct regulator *vbus;
@ -129,12 +138,9 @@ struct rcar_gen3_chan {
struct work_struct work;
spinlock_t lock; /* protects access to hardware and driver data structure. */
enum usb_dr_mode dr_mode;
u32 obint_enable_bits;
bool extcon_host;
bool is_otg_channel;
bool uses_otg_pins;
bool soc_no_adp_ctrl;
bool utmi_ctrl;
};
struct rcar_gen3_phy_drv_data {
@ -142,6 +148,8 @@ struct rcar_gen3_phy_drv_data {
bool no_adp_ctrl;
bool init_bus;
bool utmi_ctrl;
bool vblvl_ctrl;
u32 obint_enable_bits;
};
/*
@ -203,8 +211,7 @@ static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
u32 vbus_ctrl_val = USB2_ADPCTRL_DRVVBUS;
u32 val;
dev_vdbg(ch->dev, "%s: %08x, %d\n", __func__, val, vbus);
if (ch->soc_no_adp_ctrl) {
if (ch->phy_data->no_adp_ctrl || ch->phy_data->vblvl_ctrl) {
if (ch->vbus)
regulator_hardware_enable(ch->vbus, vbus);
@ -217,6 +224,7 @@ static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
val |= vbus_ctrl_val;
else
val &= ~vbus_ctrl_val;
dev_vdbg(ch->dev, "%s: %08x, %d\n", __func__, val, vbus);
writel(val, usb2_base + vbus_ctrl_reg);
}
@ -226,9 +234,9 @@ static void rcar_gen3_control_otg_irq(struct rcar_gen3_chan *ch, int enable)
u32 val = readl(usb2_base + USB2_OBINTEN);
if (ch->uses_otg_pins && enable)
val |= ch->obint_enable_bits;
val |= ch->phy_data->obint_enable_bits;
else
val &= ~ch->obint_enable_bits;
val &= ~ch->phy_data->obint_enable_bits;
writel(val, usb2_base + USB2_OBINTEN);
}
@ -287,10 +295,20 @@ static void rcar_gen3_init_from_a_peri_to_a_host(struct rcar_gen3_chan *ch)
static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch)
{
if (!ch->uses_otg_pins)
return (ch->dr_mode == USB_DR_MODE_HOST) ? false : true;
if (ch->phy_data->vblvl_ctrl) {
bool vbus_valid;
bool device;
if (ch->soc_no_adp_ctrl)
device = !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG);
vbus_valid = !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_VBUSVALID);
return vbus_valid ? device : !device;
}
if (!ch->uses_otg_pins)
return ch->dr_mode != USB_DR_MODE_HOST;
if (ch->phy_data->no_adp_ctrl)
return !!(readl(ch->base + USB2_LINECTRL1) & USB2_LINECTRL1_USB2_IDMON);
return !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG);
@ -421,21 +439,47 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
USB2_LINECTRL1_DMRPD_EN | USB2_LINECTRL1_DM_RPD;
writel(val, usb2_base + USB2_LINECTRL1);
if (!ch->soc_no_adp_ctrl) {
val = readl(usb2_base + USB2_VBCTRL);
val &= ~USB2_VBCTRL_OCCLREN;
writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL);
val = readl(usb2_base + USB2_ADPCTRL);
writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL);
if (!ch->phy_data->no_adp_ctrl) {
if (ch->phy_data->vblvl_ctrl) {
val = readl(usb2_base + USB2_VBCTRL);
val = (val & ~USB2_VBCTRL_VBLVL_MASK) | USB2_VBCTRL_VBLVL(2);
writel(val, usb2_base + USB2_VBCTRL);
val = readl(usb2_base + USB2_ADPCTRL);
writel(val | USB2_ADPCTRL_IDPULLUP | USB2_ADPCTRL_DRVVBUS,
usb2_base + USB2_ADPCTRL);
} else {
val = readl(usb2_base + USB2_VBCTRL);
val &= ~USB2_VBCTRL_OCCLREN;
writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL);
val = readl(usb2_base + USB2_ADPCTRL);
writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL);
}
}
mdelay(20);
writel(0xffffffff, usb2_base + USB2_OBINTSTA);
writel(ch->obint_enable_bits, usb2_base + USB2_OBINTEN);
writel(ch->phy_data->obint_enable_bits, usb2_base + USB2_OBINTEN);
rcar_gen3_device_recognition(ch);
}
static void rcar_gen3_configure_vblvl_ctrl(struct rcar_gen3_chan *ch)
{
void __iomem *usb2_base = ch->base;
u32 val;
if (!ch->phy_data->vblvl_ctrl)
return;
val = readl(usb2_base + USB2_VBCTRL);
if ((val & USB2_VBCTRL_VBSTA_MASK) ==
FIELD_PREP_CONST(USB2_VBCTRL_VBSTA_MASK, USB2_VBCTRL_VBSTA_DEFAULT))
val &= ~USB2_VBCTRL_VBLVL_MASK;
else
val |= USB2_VBCTRL_VBLVL(USB2_VBCTRL_VBSTA_DEFAULT);
writel(val, usb2_base + USB2_VBCTRL);
}
static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
{
struct rcar_gen3_chan *ch = _ch;
@ -451,10 +495,14 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
scoped_guard(spinlock, &ch->lock) {
status = readl(usb2_base + USB2_OBINTSTA);
if (status & ch->obint_enable_bits) {
if (status & ch->phy_data->obint_enable_bits) {
dev_vdbg(dev, "%s: %08x\n", __func__, status);
writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA);
if (ch->phy_data->vblvl_ctrl)
writel(USB2_OBINTSTA_CLEAR, usb2_base + USB2_OBINTSTA);
else
writel(ch->phy_data->obint_enable_bits, usb2_base + USB2_OBINTSTA);
rcar_gen3_device_recognition(ch);
rcar_gen3_configure_vblvl_ctrl(ch);
ret = IRQ_HANDLED;
}
}
@ -487,7 +535,14 @@ static int rcar_gen3_phy_usb2_init(struct phy *p)
if (rphy->int_enable_bits)
rcar_gen3_init_otg(channel);
if (channel->utmi_ctrl) {
if (channel->phy_data->vblvl_ctrl) {
/* SIDDQ mode release */
writel(readl(usb2_base + USB2_VBCTRL) | USB2_VBCTRL_SIDDQREL,
usb2_base + USB2_VBCTRL);
udelay(250);
}
if (channel->phy_data->utmi_ctrl) {
val = readl(usb2_base + USB2_REGEN_CG_CTRL) | USB2_REGEN_CG_CTRL_UPHY_WEN;
writel(val, usb2_base + USB2_REGEN_CG_CTRL);
@ -592,28 +647,41 @@ static const struct phy_ops rz_g1c_phy_usb2_ops = {
static const struct rcar_gen3_phy_drv_data rcar_gen3_phy_usb2_data = {
.phy_usb2_ops = &rcar_gen3_phy_usb2_ops,
.no_adp_ctrl = false,
.obint_enable_bits = USB2_OBINT_SESSVLDCHG |
USB2_OBINT_IDDIGCHG,
};
static const struct rcar_gen3_phy_drv_data rz_g1c_phy_usb2_data = {
.phy_usb2_ops = &rz_g1c_phy_usb2_ops,
.no_adp_ctrl = false,
.obint_enable_bits = USB2_OBINT_SESSVLDCHG |
USB2_OBINT_IDDIGCHG,
};
static const struct rcar_gen3_phy_drv_data rz_g2l_phy_usb2_data = {
.phy_usb2_ops = &rcar_gen3_phy_usb2_ops,
.no_adp_ctrl = true,
.obint_enable_bits = USB2_OBINT_IDCHG_EN,
};
static const struct rcar_gen3_phy_drv_data rz_g3s_phy_usb2_data = {
.phy_usb2_ops = &rcar_gen3_phy_usb2_ops,
.no_adp_ctrl = true,
.init_bus = true,
.obint_enable_bits = USB2_OBINT_IDCHG_EN,
};
static const struct rcar_gen3_phy_drv_data rz_t2h_phy_usb2_data = {
.phy_usb2_ops = &rcar_gen3_phy_usb2_ops,
.vblvl_ctrl = true,
.obint_enable_bits = USB2_OBINT_IDCHG_EN | USB2_OBINT_VBSTAINT,
};
static const struct rcar_gen3_phy_drv_data rz_v2h_phy_usb2_data = {
.phy_usb2_ops = &rcar_gen3_phy_usb2_ops,
.no_adp_ctrl = true,
.utmi_ctrl = true,
.obint_enable_bits = USB2_OBINT_IDCHG_EN,
};
static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = {
@ -641,6 +709,10 @@ static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = {
.compatible = "renesas,usb2-phy-r9a09g057",
.data = &rz_v2h_phy_usb2_data,
},
{
.compatible = "renesas,usb2-phy-r9a09g077",
.data = &rz_t2h_phy_usb2_data,
},
{
.compatible = "renesas,rzg2l-usb2-phy",
.data = &rz_g2l_phy_usb2_data,
@ -730,7 +802,6 @@ rpm_put:
static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
{
const struct rcar_gen3_phy_drv_data *phy_data;
struct device *dev = &pdev->dev;
struct rcar_gen3_chan *channel;
struct phy_provider *provider;
@ -749,7 +820,6 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
if (IS_ERR(channel->base))
return PTR_ERR(channel->base);
channel->obint_enable_bits = USB2_OBINT_BITS;
channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node);
if (channel->dr_mode != USB_DR_MODE_UNKNOWN) {
channel->is_otg_channel = true;
@ -773,8 +843,8 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
*/
pm_runtime_enable(dev);
phy_data = of_device_get_match_data(dev);
if (!phy_data) {
channel->phy_data = of_device_get_match_data(dev);
if (!channel->phy_data) {
ret = -EINVAL;
goto error;
}
@ -782,22 +852,16 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, channel);
channel->dev = dev;
if (phy_data->init_bus) {
if (channel->phy_data->init_bus) {
ret = rcar_gen3_phy_usb2_init_bus(channel);
if (ret)
goto error;
}
channel->soc_no_adp_ctrl = phy_data->no_adp_ctrl;
if (phy_data->no_adp_ctrl)
channel->obint_enable_bits = USB2_OBINT_IDCHG_EN;
channel->utmi_ctrl = phy_data->utmi_ctrl;
spin_lock_init(&channel->lock);
for (i = 0; i < NUM_OF_PHYS; i++) {
channel->rphys[i].phy = devm_phy_create(dev, NULL,
phy_data->phy_usb2_ops);
channel->phy_data->phy_usb2_ops);
if (IS_ERR(channel->rphys[i].phy)) {
dev_err(dev, "Failed to create USB2 PHY\n");
ret = PTR_ERR(channel->rphys[i].phy);
@ -808,7 +872,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
phy_set_drvdata(channel->rphys[i].phy, &channel->rphys[i]);
}
if (channel->soc_no_adp_ctrl && channel->is_otg_channel)
if (channel->phy_data->no_adp_ctrl && channel->is_otg_channel)
channel->vbus = devm_regulator_get_exclusive(dev, "vbus");
else
channel->vbus = devm_regulator_get_optional(dev, "vbus");

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/* Renesas Ethernet SERDES device driver
*
* Copyright (C) 2022 Renesas Electronics Corporation
* Copyright (C) 2022-2025 Renesas Electronics Corporation
*/
#include <linux/delay.h>
@ -49,6 +49,13 @@ static void r8a779f0_eth_serdes_write32(void __iomem *addr, u32 offs, u32 bank,
iowrite32(data, addr + offs);
}
static u32 r8a779f0_eth_serdes_read32(void __iomem *addr, u32 offs, u32 bank)
{
iowrite32(bank, addr + R8A779F0_ETH_SERDES_BANK_SELECT);
return ioread32(addr + offs);
}
static int
r8a779f0_eth_serdes_reg_wait(struct r8a779f0_eth_serdes_channel *channel,
u32 offs, u32 bank, u32 mask, u32 expected)
@ -92,17 +99,18 @@ r8a779f0_eth_serdes_common_setting(struct r8a779f0_eth_serdes_channel *channel)
{
struct r8a779f0_eth_serdes_drv_data *dd = channel->dd;
switch (channel->phy_interface) {
case PHY_INTERFACE_MODE_SGMII:
r8a779f0_eth_serdes_write32(dd->addr, 0x0244, 0x180, 0x0097);
r8a779f0_eth_serdes_write32(dd->addr, 0x01d0, 0x180, 0x0060);
r8a779f0_eth_serdes_write32(dd->addr, 0x01d8, 0x180, 0x2200);
r8a779f0_eth_serdes_write32(dd->addr, 0x01d4, 0x180, 0x0000);
r8a779f0_eth_serdes_write32(dd->addr, 0x01e0, 0x180, 0x003d);
return 0;
default:
return -EOPNOTSUPP;
}
/* Set combination mode */
r8a779f0_eth_serdes_write32(dd->addr, 0x0244, 0x180, 0x00d7);
r8a779f0_eth_serdes_write32(dd->addr, 0x01cc, 0x180, 0xc200);
r8a779f0_eth_serdes_write32(dd->addr, 0x01c4, 0x180, 0x0042);
r8a779f0_eth_serdes_write32(dd->addr, 0x01c8, 0x180, 0x0000);
r8a779f0_eth_serdes_write32(dd->addr, 0x01dc, 0x180, 0x002f);
r8a779f0_eth_serdes_write32(dd->addr, 0x01d0, 0x180, 0x0060);
r8a779f0_eth_serdes_write32(dd->addr, 0x01d8, 0x180, 0x2200);
r8a779f0_eth_serdes_write32(dd->addr, 0x01d4, 0x180, 0x0000);
r8a779f0_eth_serdes_write32(dd->addr, 0x01e0, 0x180, 0x003d);
return 0;
}
static int
@ -155,6 +163,42 @@ r8a779f0_eth_serdes_chan_setting(struct r8a779f0_eth_serdes_channel *channel)
r8a779f0_eth_serdes_write32(channel->addr, 0x0028, 0x1f80, 0x07a1);
r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x1f80, 0x0208);
break;
case PHY_INTERFACE_MODE_USXGMII:
r8a779f0_eth_serdes_write32(channel->addr, 0x001c, 0x300, 0x0000);
r8a779f0_eth_serdes_write32(channel->addr, 0x0014, 0x380, 0x0050);
r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x380, 0x2200);
r8a779f0_eth_serdes_write32(channel->addr, 0x001c, 0x380, 0x0400);
r8a779f0_eth_serdes_write32(channel->addr, 0x01c0, 0x180, 0x0001);
r8a779f0_eth_serdes_write32(channel->addr, 0x0248, 0x180, 0x056a);
r8a779f0_eth_serdes_write32(channel->addr, 0x0258, 0x180, 0x0015);
r8a779f0_eth_serdes_write32(channel->addr, 0x0144, 0x180, 0x1100);
r8a779f0_eth_serdes_write32(channel->addr, 0x01a0, 0x180, 0x0001);
r8a779f0_eth_serdes_write32(channel->addr, 0x00d0, 0x180, 0x0001);
r8a779f0_eth_serdes_write32(channel->addr, 0x0150, 0x180, 0x0001);
r8a779f0_eth_serdes_write32(channel->addr, 0x00c8, 0x180, 0x0300);
r8a779f0_eth_serdes_write32(channel->addr, 0x0148, 0x180, 0x0300);
r8a779f0_eth_serdes_write32(channel->addr, 0x0174, 0x180, 0x0000);
r8a779f0_eth_serdes_write32(channel->addr, 0x0160, 0x180, 0x0004);
r8a779f0_eth_serdes_write32(channel->addr, 0x01ac, 0x180, 0x0000);
r8a779f0_eth_serdes_write32(channel->addr, 0x00c4, 0x180, 0x0310);
r8a779f0_eth_serdes_write32(channel->addr, 0x00c8, 0x180, 0x0301);
ret = r8a779f0_eth_serdes_reg_wait(channel, 0x00c8, 0x180, BIT(0), 0);
if (ret)
return ret;
r8a779f0_eth_serdes_write32(channel->addr, 0x0148, 0x180, 0x0301);
ret = r8a779f0_eth_serdes_reg_wait(channel, 0x0148, 0x180, BIT(0), 0);
if (ret)
return ret;
r8a779f0_eth_serdes_write32(channel->addr, 0x00c4, 0x180, 0x1310);
r8a779f0_eth_serdes_write32(channel->addr, 0x00d8, 0x180, 0x1800);
r8a779f0_eth_serdes_write32(channel->addr, 0x00dc, 0x180, 0x0000);
r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x380, 0x2300);
ret = r8a779f0_eth_serdes_reg_wait(channel, 0x0000, 0x380, BIT(8), 0);
if (ret)
return ret;
break;
default:
return -EOPNOTSUPP;
}
@ -179,6 +223,14 @@ r8a779f0_eth_serdes_chan_speed(struct r8a779f0_eth_serdes_channel *channel)
return ret;
r8a779f0_eth_serdes_write32(channel->addr, 0x0008, 0x1f80, 0x0000);
break;
case PHY_INTERFACE_MODE_USXGMII:
r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x1f00, 0x0120);
usleep_range(10, 20);
r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x380, 0x2600);
ret = r8a779f0_eth_serdes_reg_wait(channel, 0x0000, 0x380, BIT(10), 0);
if (ret)
return ret;
break;
default:
return -EOPNOTSUPP;
}
@ -274,6 +326,7 @@ static int r8a779f0_eth_serdes_hw_init_late(struct r8a779f0_eth_serdes_channel
*channel)
{
int ret;
u32 val;
ret = r8a779f0_eth_serdes_chan_setting(channel);
if (ret)
@ -287,6 +340,26 @@ static int r8a779f0_eth_serdes_hw_init_late(struct r8a779f0_eth_serdes_channel
r8a779f0_eth_serdes_write32(channel->addr, 0x03d0, 0x380, 0x0000);
val = r8a779f0_eth_serdes_read32(channel->addr, 0x00c0, 0x180);
r8a779f0_eth_serdes_write32(channel->addr, 0x00c0, 0x180, val | BIT(8));
ret = r8a779f0_eth_serdes_reg_wait(channel, 0x0100, 0x180, BIT(0), 1);
if (ret)
return ret;
r8a779f0_eth_serdes_write32(channel->addr, 0x00c0, 0x180, val & ~BIT(8));
ret = r8a779f0_eth_serdes_reg_wait(channel, 0x0100, 0x180, BIT(0), 0);
if (ret)
return ret;
val = r8a779f0_eth_serdes_read32(channel->addr, 0x0144, 0x180);
r8a779f0_eth_serdes_write32(channel->addr, 0x0144, 0x180, val | BIT(4));
ret = r8a779f0_eth_serdes_reg_wait(channel, 0x0180, 0x180, BIT(0), 1);
if (ret)
return ret;
r8a779f0_eth_serdes_write32(channel->addr, 0x0144, 0x180, val & ~BIT(4));
ret = r8a779f0_eth_serdes_reg_wait(channel, 0x0180, 0x180, BIT(0), 0);
if (ret)
return ret;
return r8a779f0_eth_serdes_monitor_linkup(channel);
}

View File

@ -30,6 +30,8 @@
#define RK3568_GRF_VI_CON0 0x0340
#define RK3568_GRF_VI_CON1 0x0344
#define RK3588_CSIDPHY_GRF_CON0 0x0000
/* PHY */
#define CSIDPHY_CTRL_LANE_ENABLE 0x00
#define CSIDPHY_CTRL_LANE_ENABLE_CK BIT(6)
@ -67,6 +69,8 @@
#define RK1808_CSIDPHY_CLK_CALIB_EN 0x168
#define RK3568_CSIDPHY_CLK_CALIB_EN 0x168
#define RESETS_MAX 2
/*
* The higher 16-bit of this register is used for write protection
* only if BIT(x + 16) set to 1 the BIT(x) can be written.
@ -87,10 +91,11 @@ struct dphy_reg {
u32 offset;
u32 mask;
u32 shift;
u8 valid;
};
#define PHY_REG(_offset, _width, _shift) \
{ .offset = _offset, .mask = BIT(_width) - 1, .shift = _shift, }
{ .offset = _offset, .mask = BIT(_width) - 1, .shift = _shift, .valid = 1, }
static const struct dphy_reg rk1808_grf_dphy_regs[] = {
[GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK1808_GRF_PD_VI_CON_OFFSET, 4, 0),
@ -114,6 +119,12 @@ static const struct dphy_reg rk3568_grf_dphy_regs[] = {
[GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RK3568_GRF_VI_CON0, 1, 8),
};
static const struct dphy_reg rk3588_grf_dphy_regs[] = {
[GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK3588_CSIDPHY_GRF_CON0, 4, 0),
[GRF_DPHY_CSIPHY_DATALANE_EN] = PHY_REG(RK3588_CSIDPHY_GRF_CON0, 4, 4),
[GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RK3588_CSIDPHY_GRF_CON0, 1, 8),
};
struct hsfreq_range {
u32 range_h;
u8 cfg_bit;
@ -126,6 +137,8 @@ struct dphy_drv_data {
const struct hsfreq_range *hsfreq_ranges;
int num_hsfreq_ranges;
const struct dphy_reg *grf_regs;
const char *const *resets;
unsigned int resets_num;
};
struct rockchip_inno_csidphy {
@ -133,7 +146,8 @@ struct rockchip_inno_csidphy {
void __iomem *phy_base;
struct clk *pclk;
struct regmap *grf;
struct reset_control *rst;
struct reset_control_bulk_data resets[RESETS_MAX];
unsigned int resets_num;
const struct dphy_drv_data *drv_data;
struct phy_configure_opts_mipi_dphy config;
u8 hsfreq;
@ -145,7 +159,7 @@ static inline void write_grf_reg(struct rockchip_inno_csidphy *priv,
const struct dphy_drv_data *drv_data = priv->drv_data;
const struct dphy_reg *reg = &drv_data->grf_regs[index];
if (reg->offset)
if (reg->valid)
regmap_write(priv->grf, reg->offset,
HIWORD_UPDATE(value, reg->mask, reg->shift));
}
@ -173,6 +187,15 @@ static const struct hsfreq_range rk3368_mipidphy_hsfreq_ranges[] = {
{1249, 0x0c}, {1349, 0x0d}, {1500, 0x0e}
};
static const char *const rk3368_reset_names[] = {
"apb"
};
static const char *const rk3588_reset_names[] = {
"apb",
"phy"
};
static void rockchip_inno_csidphy_ths_settle(struct rockchip_inno_csidphy *priv,
int hsfreq, int offset)
{
@ -343,6 +366,8 @@ static const struct dphy_drv_data rk1808_mipidphy_drv_data = {
.hsfreq_ranges = rk1808_mipidphy_hsfreq_ranges,
.num_hsfreq_ranges = ARRAY_SIZE(rk1808_mipidphy_hsfreq_ranges),
.grf_regs = rk1808_grf_dphy_regs,
.resets = rk3368_reset_names,
.resets_num = ARRAY_SIZE(rk3368_reset_names),
};
static const struct dphy_drv_data rk3326_mipidphy_drv_data = {
@ -352,6 +377,8 @@ static const struct dphy_drv_data rk3326_mipidphy_drv_data = {
.hsfreq_ranges = rk3326_mipidphy_hsfreq_ranges,
.num_hsfreq_ranges = ARRAY_SIZE(rk3326_mipidphy_hsfreq_ranges),
.grf_regs = rk3326_grf_dphy_regs,
.resets = rk3368_reset_names,
.resets_num = ARRAY_SIZE(rk3368_reset_names),
};
static const struct dphy_drv_data rk3368_mipidphy_drv_data = {
@ -361,6 +388,8 @@ static const struct dphy_drv_data rk3368_mipidphy_drv_data = {
.hsfreq_ranges = rk3368_mipidphy_hsfreq_ranges,
.num_hsfreq_ranges = ARRAY_SIZE(rk3368_mipidphy_hsfreq_ranges),
.grf_regs = rk3368_grf_dphy_regs,
.resets = rk3368_reset_names,
.resets_num = ARRAY_SIZE(rk3368_reset_names),
};
static const struct dphy_drv_data rk3568_mipidphy_drv_data = {
@ -370,6 +399,19 @@ static const struct dphy_drv_data rk3568_mipidphy_drv_data = {
.hsfreq_ranges = rk1808_mipidphy_hsfreq_ranges,
.num_hsfreq_ranges = ARRAY_SIZE(rk1808_mipidphy_hsfreq_ranges),
.grf_regs = rk3568_grf_dphy_regs,
.resets = rk3368_reset_names,
.resets_num = ARRAY_SIZE(rk3368_reset_names),
};
static const struct dphy_drv_data rk3588_mipidphy_drv_data = {
.pwrctl_offset = -1,
.ths_settle_offset = RK3568_CSIDPHY_CLK_WR_THS_SETTLE,
.calib_offset = RK3568_CSIDPHY_CLK_CALIB_EN,
.hsfreq_ranges = rk1808_mipidphy_hsfreq_ranges,
.num_hsfreq_ranges = ARRAY_SIZE(rk1808_mipidphy_hsfreq_ranges),
.grf_regs = rk3588_grf_dphy_regs,
.resets = rk3588_reset_names,
.resets_num = ARRAY_SIZE(rk3588_reset_names),
};
static const struct of_device_id rockchip_inno_csidphy_match_id[] = {
@ -393,6 +435,10 @@ static const struct of_device_id rockchip_inno_csidphy_match_id[] = {
.compatible = "rockchip,rk3568-csi-dphy",
.data = &rk3568_mipidphy_drv_data,
},
{
.compatible = "rockchip,rk3588-csi-dphy",
.data = &rk3588_mipidphy_drv_data,
},
{}
};
MODULE_DEVICE_TABLE(of, rockchip_inno_csidphy_match_id);
@ -403,6 +449,7 @@ static int rockchip_inno_csidphy_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct phy_provider *phy_provider;
struct phy *phy;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@ -434,10 +481,18 @@ static int rockchip_inno_csidphy_probe(struct platform_device *pdev)
return PTR_ERR(priv->pclk);
}
priv->rst = devm_reset_control_get(dev, "apb");
if (IS_ERR(priv->rst)) {
if (priv->drv_data->resets_num > RESETS_MAX) {
dev_err(dev, "invalid number of resets\n");
return -EINVAL;
}
priv->resets_num = priv->drv_data->resets_num;
for (unsigned int i = 0; i < priv->resets_num; i++)
priv->resets[i].id = priv->drv_data->resets[i];
ret = devm_reset_control_bulk_get_exclusive(dev, priv->resets_num,
priv->resets);
if (ret) {
dev_err(dev, "failed to get system reset control\n");
return PTR_ERR(priv->rst);
return ret;
}
phy = devm_phy_create(dev, NULL, &rockchip_inno_csidphy_ops);

File diff suppressed because it is too large Load Diff

View File

@ -795,7 +795,6 @@ static const struct regmap_config rk_hdptx_phy_regmap_config = {
.val_bits = 32,
.writeable_reg = rk_hdptx_phy_is_rw_reg,
.readable_reg = rk_hdptx_phy_is_rw_reg,
.fast_io = true,
.max_register = 0x18b4,
};

View File

@ -666,7 +666,7 @@ static int rk_udphy_orien_sw_set(struct typec_switch_dev *sw,
goto unlock_ret;
}
udphy->flip = (orien == TYPEC_ORIENTATION_REVERSE) ? true : false;
udphy->flip = orien == TYPEC_ORIENTATION_REVERSE;
rk_udphy_set_typec_default_mapping(udphy);
rk_udphy_usb_bvalid_enable(udphy, true);
@ -1430,7 +1430,6 @@ static const struct regmap_config rk_udphy_pma_regmap_cfg = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.fast_io = true,
.max_register = 0x20dc,
};

View File

@ -2417,4 +2417,3 @@ module_platform_driver(exynos5_usb3drd_phy);
MODULE_DESCRIPTION("Samsung Exynos5 SoCs USB 3.0 DRD controller PHY driver");
MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:exynos5_usb3drd_phy");

View File

@ -258,4 +258,3 @@ module_platform_driver(samsung_usb2_phy_driver);
MODULE_DESCRIPTION("Samsung S5P/Exynos SoC USB PHY driver");
MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:samsung-usb2-phy");

View File

@ -0,0 +1,19 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Phy drivers for Sophgo platforms
#
if ARCH_SOPHGO || COMPILE_TEST
config PHY_SOPHGO_CV1800_USB2
tristate "Sophgo CV18XX/SG200X USB 2.0 PHY support"
depends on MFD_SYSCON
depends on USB_SUPPORT
select GENERIC_PHY
help
Enable this to support the USB 2.0 PHY used with
the DWC2 USB controller in Sophgo CV18XX/SG200X
series SoC.
If unsure, say N.
endif # ARCH_SOPHGO || COMPILE_TEST

View File

@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_SOPHGO_CV1800_USB2) += phy-cv1800-usb2.o

View File

@ -0,0 +1,170 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2025 Inochi Amaoto <inochiama@outlook.com>
*/
#include <linux/clk.h>
#include <linux/bitfield.h>
#include <linux/debugfs.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/phy/phy.h>
#include <linux/regmap.h>
#include <linux/spinlock.h>
#define REG_USB_PHY_CTRL 0x048
#define PHY_VBUS_POWER_EN BIT(0)
#define PHY_VBUS_POWER BIT(1)
#define PHY_ID_OVERWRITE_EN BIT(6)
#define PHY_ID_OVERWRITE_MODE BIT(7)
#define PHY_ID_OVERWRITE_MODE_HOST FIELD_PREP(BIT(7), 0)
#define PHY_ID_OVERWRITE_MODE_DEVICE FIELD_PREP(BIT(7), 1)
#define PHY_APP_CLK_RATE 125000000
#define PHY_LPM_CLK_RATE 12000000
#define PHY_STB_CLK_RATE 333334
struct cv1800_usb_phy {
struct phy *phy;
struct regmap *syscon;
spinlock_t lock;
struct clk *usb_app_clk;
struct clk *usb_lpm_clk;
struct clk *usb_stb_clk;
bool support_otg;
};
static int cv1800_usb_phy_set_mode(struct phy *_phy,
enum phy_mode mode, int submode)
{
struct cv1800_usb_phy *phy = phy_get_drvdata(_phy);
unsigned int regval = 0;
int ret;
dev_info(&phy->phy->dev, "set mode %d", (int)mode);
switch (mode) {
case PHY_MODE_USB_DEVICE:
regval = PHY_ID_OVERWRITE_EN | PHY_ID_OVERWRITE_MODE_DEVICE;
regmap_clear_bits(phy->syscon, REG_USB_PHY_CTRL, PHY_VBUS_POWER);
break;
case PHY_MODE_USB_HOST:
regval = PHY_ID_OVERWRITE_EN | PHY_ID_OVERWRITE_MODE_HOST;
regmap_set_bits(phy->syscon, REG_USB_PHY_CTRL, PHY_VBUS_POWER);
break;
case PHY_MODE_USB_OTG:
if (!phy->support_otg)
return 0;
ret = regmap_read(phy->syscon, REG_USB_PHY_CTRL, &regval);
if (ret)
return ret;
regval = FIELD_GET(PHY_ID_OVERWRITE_MODE, regval);
break;
default:
return -EINVAL;
}
return regmap_update_bits(phy->syscon, REG_USB_PHY_CTRL,
PHY_ID_OVERWRITE_EN | PHY_ID_OVERWRITE_MODE,
regval);
}
static int cv1800_usb_phy_set_clock(struct cv1800_usb_phy *phy)
{
int ret;
ret = clk_set_rate(phy->usb_app_clk, PHY_APP_CLK_RATE);
if (ret)
return ret;
ret = clk_set_rate(phy->usb_lpm_clk, PHY_LPM_CLK_RATE);
if (ret)
return ret;
return clk_set_rate(phy->usb_stb_clk, PHY_STB_CLK_RATE);
}
static const struct phy_ops cv1800_usb_phy_ops = {
.set_mode = cv1800_usb_phy_set_mode,
.owner = THIS_MODULE,
};
static int cv1800_usb_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device *parent = dev->parent;
struct cv1800_usb_phy *phy;
struct phy_provider *phy_provider;
int ret;
if (!parent)
return -ENODEV;
phy = devm_kmalloc(dev, sizeof(*phy), GFP_KERNEL);
if (!phy)
return -ENOMEM;
phy->syscon = syscon_node_to_regmap(parent->of_node);
if (IS_ERR_OR_NULL(phy->syscon))
return -ENODEV;
phy->support_otg = false;
spin_lock_init(&phy->lock);
phy->usb_app_clk = devm_clk_get_enabled(dev, "app");
if (IS_ERR(phy->usb_app_clk))
return dev_err_probe(dev, PTR_ERR(phy->usb_app_clk),
"Failed to get app clock\n");
phy->usb_lpm_clk = devm_clk_get_enabled(dev, "lpm");
if (IS_ERR(phy->usb_lpm_clk))
return dev_err_probe(dev, PTR_ERR(phy->usb_lpm_clk),
"Failed to get lpm clock\n");
phy->usb_stb_clk = devm_clk_get_enabled(dev, "stb");
if (IS_ERR(phy->usb_stb_clk))
return dev_err_probe(dev, PTR_ERR(phy->usb_stb_clk),
"Failed to get stb clock\n");
phy->phy = devm_phy_create(dev, NULL, &cv1800_usb_phy_ops);
if (IS_ERR(phy->phy))
return dev_err_probe(dev, PTR_ERR(phy->phy),
"Failed to create phy\n");
ret = cv1800_usb_phy_set_clock(phy);
if (ret)
return ret;
phy_set_drvdata(phy->phy, phy);
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 cv1800_usb_phy_ids[] = {
{ .compatible = "sophgo,cv1800b-usb2-phy" },
{ },
};
MODULE_DEVICE_TABLE(of, cv1800_usb_phy_ids);
static struct platform_driver cv1800_usb_phy_driver = {
.probe = cv1800_usb_phy_probe,
.driver = {
.name = "cv1800-usb2-phy",
.of_match_table = cv1800_usb_phy_ids,
},
};
module_platform_driver(cv1800_usb_phy_driver);
MODULE_AUTHOR("Inochi Amaoto <inochiama@outlook.com>");
MODULE_DESCRIPTION("CV1800/SG2000 SoC USB 2.0 PHY driver");
MODULE_LICENSE("GPL");

View File

@ -62,7 +62,7 @@ config OMAP_CONTROL_PHY
config OMAP_USB2
tristate "OMAP USB2 PHY Driver"
depends on ARCH_OMAP2PLUS || ARCH_K3
depends on ARCH_OMAP2PLUS || ARCH_K3 || COMPILE_TEST
depends on USB_SUPPORT
select GENERIC_PHY
select USB_PHY

View File

@ -99,7 +99,6 @@ static const struct regmap_config serdes_am654_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.fast_io = true,
.max_register = 0x1ffc,
};

View File

@ -269,7 +269,6 @@ static struct platform_driver dm816x_usb_phy_driver = {
module_platform_driver(dm816x_usb_phy_driver);
MODULE_ALIAS("platform:dm816x_usb");
MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
MODULE_DESCRIPTION("dm816x usb phy driver");
MODULE_LICENSE("GPL v2");

View File

@ -1319,7 +1319,6 @@ static const struct regmap_config wiz_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.fast_io = true,
};
static struct wiz_data j721e_16g_data = {

View File

@ -334,7 +334,6 @@ static void __exit omap_control_phy_exit(void)
}
module_exit(omap_control_phy_exit);
MODULE_ALIAS("platform:omap_control_phy");
MODULE_AUTHOR("Texas Instruments Inc.");
MODULE_DESCRIPTION("OMAP Control Module PHY Driver");
MODULE_LICENSE("GPL v2");

View File

@ -533,7 +533,6 @@ static struct platform_driver omap_usb2_driver = {
module_platform_driver(omap_usb2_driver);
MODULE_ALIAS("platform:omap_usb2");
MODULE_AUTHOR("Texas Instruments Inc.");
MODULE_DESCRIPTION("OMAP USB2 phy driver");
MODULE_LICENSE("GPL v2");

View File

@ -942,7 +942,6 @@ static struct platform_driver ti_pipe3_driver = {
module_platform_driver(ti_pipe3_driver);
MODULE_ALIAS("platform:ti_pipe3");
MODULE_AUTHOR("Texas Instruments Inc.");
MODULE_DESCRIPTION("TI PIPE3 phy driver");
MODULE_LICENSE("GPL v2");