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
commit
1d1ba4d390
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
|
|
@ -18,6 +18,7 @@ properties:
|
|||
- items:
|
||||
- enum:
|
||||
- microchip,ata6561
|
||||
- ti,tcan1051
|
||||
- const: ti,tcan1042
|
||||
- enum:
|
||||
- ti,tcan1042
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ obj-y += allwinner/ \
|
|||
rockchip/ \
|
||||
samsung/ \
|
||||
socionext/ \
|
||||
sophgo/ \
|
||||
st/ \
|
||||
starfive/ \
|
||||
sunplus/ \
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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[] = {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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>");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_PHY_SOPHGO_CV1800_USB2) += phy-cv1800-usb2.o
|
||||
|
|
@ -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, ®val);
|
||||
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");
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
Loading…
Reference in New Issue