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

Pull phy updates from Vinod Koul:
 "As usual bunch of new device and driver support and updates to
  existing drivers and addition of Manivannan to help with reviews.

  New Support:
   - Mediatek MT8196 DSI PHY support
   - Renesas RZ/G3L usb2 support
   - Qualcomm SM8475 QMP USB PHY and PCIe phy, IPQ9650 QMP PCIe PHY,
     QUSB2 Phy for Shikra SoC, Hawi support for QMP PCIe phy and UFS
     PHY. Glymur QMP PCIe Multi-PHY driver and multiple link-mode
     support, ipq5210 PCIe phy support
   - Spacemit USB3/PCIe comb PHY driver

  Updates:
   - Samsung hdptx driver improvements for modernizing the register
     access and code cleanup
   - Qualcomm drop duplicate v8 DP headers, improved runtime handling
     for qmp drivers
   - Rockchip clock lane phase tuning and 2500 Mbps support and TMDS
     rate handling
   - Freescale imx8mq improvements for runtime pm, pd handling"

* tag 'phy-for-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (76 commits)
  MAINTAINERS: Add Manivannan Sadhasivam as the Reviewer for Generic PHY Framework
  phy: rockchip-samsung-dcphy: fix out-of-range max_register
  phy: qcom: qmp-pcie: Add QMP PCIe Multi-PHY driver
  dt-bindings: phy: qcom: Add Glymur QMP PCIe multiple link-mode PHY
  phy: rockchip: samsung-hdptx: Consistently use bitfield macros
  phy: rockchip: samsung-hdptx: Simplify GRF access with FIELD_PREP_WM16()
  phy: rockchip: samsung-hdptx: Drop restrict_rate_change handling
  phy: rockchip: samsung-hdptx: Consolidate consumer_put on error path
  phy: rockchip: samsung-hdptx: Drop TMDS rate setup workaround
  phy: rockchip: samsung-hdptx: Handle uncommitted PHY config changes
  phy: rockchip: samsung-hdptx: Fix rate recalculation for 3.2GHz FRL
  phy: rockchip: samsung-hdptx: Guard against clk rate integer underflow
  phy: rockchip: samsung-hdptx: Prevent divide-by-zero when computing clk rate
  phy: rockchip: samsung-hdptx: Fix rate recalculation for high bpc
  phy: qcom: qmp-combo: Drop qmp_v4_calibrate_dp_phy
  phy: qcom: qmp-combo: Correct pre-emphasis table for QMP v4 DP PHYs
  phy: renesas: rcar-gen3-usb2: Ignore missing VBUS regulator
  phy: qcom: qmp-pcie: Add support for SM8475 Gen3x1 PCIe0 port
  phy: qcom: qmp-pcie: Add pcs_lane1 offset to V5 offsets
  dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Add SM8475 QMP PHY
  ...
This commit is contained in:
Linus Torvalds
2026-08-24 12:19:23 -07:00
66 changed files with 4608 additions and 359 deletions

View File

@@ -39,6 +39,7 @@ properties:
- const: mediatek,mt2701-mipi-tx
- const: mediatek,mt8173-mipi-tx
- const: mediatek,mt8183-mipi-tx
- const: mediatek,mt8196-mipi-tx
reg:
maxItems: 1

View File

@@ -0,0 +1,177 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/qcom,glymur-qmp-gen5x8-pcie-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm QMP PCIe multiple link-mode PHY controller (PCIe, Glymur)
maintainers:
- Qiang Yu <qiang.yu@oss.qualcomm.com>
- Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
description: |
The Glymur SoC uses a single PCIe Gen5 PHY hardware block for the
PCIe3a/PCIe3b controllers. This block supports two link modes, selected
at runtime via a TCSR syscon register:
1. x8 - a single 8-lane PHY instance is exposed (PCIe3a only)
2. x4+x4 - two independent 4-lane PHY instances are exposed (PCIe3a and
PCIe3b)
The node always describes both PHY instances ("port a" and "port b"),
regardless of which link mode is active on the board.
properties:
compatible:
enum:
- qcom,glymur-qmp-gen5x8-pcie-phy
reg:
maxItems: 2
reg-names:
items:
- const: port_a
- const: port_b
clocks:
maxItems: 10
clock-names:
items:
- const: aux
- const: cfg_ahb
- const: ref
- const: rchng
- const: pipe
- const: phy_b_aux
- const: cfg_ahb_b
- const: rchng_b
- const: pipe_b
- const: pipediv2_b
power-domains:
maxItems: 2
power-domain-names:
items:
- const: port_a
- const: port_b
resets:
maxItems: 4
reset-names:
items:
- const: port_a
- const: port_a_nocsr
- const: port_b
- const: port_b_nocsr
vdda-phy-supply: true
vdda-pll-supply: true
vdda-refgen0p9-supply: true
vdda-refgen1p2-supply: true
qcom,link-mode:
description:
Reference to a register in the TCSR syscon that reports the link
mode the PCIe PHY is currently configured for, either a single x8
link or two independent x4 links. The link mode is programmed by
firmware before Linux boots; this property is only used to read
the active link mode, specified as a phandle to the syscon and
the register offset.
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
- items:
- description: phandle of TCSR syscon
- description: offset of link mode register
"#clock-cells":
const: 1
clock-output-names:
items:
- description: Name of the PHY A pipe clock output.
- description: Name of the PHY B pipe clock output.
"#phy-cells":
const: 1
description:
The cell is the index of the sub-PHY within the active link
mode, e.g. on Glymur, 0 for "port a" and 1 for "port b" in
x4x4 mode, and only index 0 (the single wide PHY) is valid in
x8 mode.
required:
- compatible
- reg
- reg-names
- clocks
- clock-names
- power-domains
- power-domain-names
- resets
- reset-names
- vdda-phy-supply
- vdda-pll-supply
- vdda-refgen0p9-supply
- vdda-refgen1p2-supply
- qcom,link-mode
- "#clock-cells"
- clock-output-names
- "#phy-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,glymur-gcc.h>
#include <dt-bindings/clock/qcom,glymur-tcsr.h>
phy@f00000 {
compatible = "qcom,glymur-qmp-gen5x8-pcie-phy";
reg = <0x00f00000 0x10000>, <0x00f10000 0x10000>;
reg-names = "port_a", "port_b";
clocks = <&gcc GCC_PCIE_PHY_3A_AUX_CLK>,
<&gcc GCC_PCIE_3A_CFG_AHB_CLK>,
<&tcsr TCSR_PCIE_3_CLKREF_EN>,
<&gcc GCC_PCIE_3A_PHY_RCHNG_CLK>,
<&gcc GCC_PCIE_3A_PIPE_CLK>,
<&gcc GCC_PCIE_PHY_3B_AUX_CLK>,
<&gcc GCC_PCIE_3B_CFG_AHB_CLK>,
<&gcc GCC_PCIE_3B_PHY_RCHNG_CLK>,
<&gcc GCC_PCIE_3B_PIPE_CLK>,
<&gcc GCC_PCIE_3B_PIPE_DIV2_CLK>;
clock-names = "aux", "cfg_ahb", "ref", "rchng", "pipe",
"phy_b_aux", "cfg_ahb_b", "rchng_b", "pipe_b",
"pipediv2_b";
resets = <&gcc GCC_PCIE_3A_PHY_BCR>,
<&gcc GCC_PCIE_3A_NOCSR_COM_PHY_BCR>,
<&gcc GCC_PCIE_3B_PHY_BCR>,
<&gcc GCC_PCIE_3B_NOCSR_COM_PHY_BCR>;
reset-names = "port_a", "port_a_nocsr", "port_b", "port_b_nocsr";
power-domains = <&gcc GCC_PCIE_3A_PHY_GDSC>,
<&gcc GCC_PCIE_3B_PHY_GDSC>;
power-domain-names = "port_a", "port_b";
vdda-phy-supply = <&vreg_l3c>;
vdda-pll-supply = <&vreg_l2c>;
vdda-refgen0p9-supply = <&vreg_l3c>;
vdda-refgen1p2-supply = <&vreg_l2c>;
qcom,link-mode = <&tcsr 0x5000>;
#clock-cells = <1>;
clock-output-names = "pcie3a_pipe_clk", "pcie3b_pipe_clk";
#phy-cells = <1>;
};

View File

@@ -17,17 +17,21 @@ properties:
compatible:
oneOf:
- enum:
- qcom,ipq5210-qmp-gen3x1-pcie-phy
- qcom,ipq6018-qmp-pcie-phy
- qcom,ipq8074-qmp-gen3-pcie-phy
- qcom,ipq8074-qmp-pcie-phy
- qcom,ipq9574-qmp-gen3x1-pcie-phy
- qcom,ipq9574-qmp-gen3x2-pcie-phy
- qcom,ipq9650-qmp-gen3x1-pcie-phy
- qcom,ipq9650-qmp-gen3x2-pcie-phy
- items:
- enum:
- qcom,ipq5424-qmp-gen3x1-pcie-phy
- const: qcom,ipq9574-qmp-gen3x1-pcie-phy
- items:
- enum:
- qcom,ipq5210-qmp-gen3x2-pcie-phy
- qcom,ipq5424-qmp-gen3x2-pcie-phy
- const: qcom,ipq9574-qmp-gen3x2-pcie-phy
@@ -61,6 +65,8 @@ properties:
"#phy-cells":
const: 0
refgen-supply: true
required:
- compatible
- reg
@@ -72,6 +78,21 @@ required:
- clock-output-names
- "#phy-cells"
allOf:
- if:
properties:
compatible:
contains:
enum:
- qcom,ipq9650-qmp-gen3x1-pcie-phy
- qcom,ipq9650-qmp-gen3x2-pcie-phy
then:
required:
- refgen-supply
else:
properties:
refgen-supply: false
additionalProperties: false
examples:

View File

@@ -19,6 +19,7 @@ properties:
- items:
- enum:
- qcom,glymur-m31-eusb2-phy
- qcom,hawi-m31-eusb2-phy
- qcom,kaanapali-m31-eusb2-phy
- const: qcom,sm8750-m31-eusb2-phy
- const: qcom,sm8750-m31-eusb2-phy

View File

@@ -18,6 +18,7 @@ properties:
compatible:
enum:
- qcom,qcs615-qmp-usb3-dp-phy
- qcom,shikra-qmp-usb3-dp-phy
reg:
maxItems: 1
@@ -33,12 +34,15 @@ properties:
- const: pipe
resets:
maxItems: 2
minItems: 2
maxItems: 3
reset-names:
minItems: 2
items:
- const: phy_phy
- const: dp_phy
- const: phy
vdda-phy-supply: true
@@ -63,6 +67,22 @@ properties:
- description: offset of the PHY mode register
description: Clamp and PHY mode register present in the TCSR
orientation-switch:
description:
Flag the PHY as possible handler of USB Type-C orientation switching
type: boolean
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
description: Output endpoint of the PHY
port@1:
$ref: /schemas/graph.yaml#/properties/port
description: Incoming endpoint from the USB controller
required:
- compatible
- reg
@@ -78,6 +98,33 @@ required:
additionalProperties: false
allOf:
- if:
properties:
compatible:
contains:
enum:
- qcom,shikra-qmp-usb3-dp-phy
then:
properties:
resets:
minItems: 3
reset-names:
minItems: 3
- if:
properties:
compatible:
contains:
enum:
- qcom,qcs615-qmp-usb3-dp-phy
then:
properties:
resets:
maxItems: 2
reset-names:
maxItems: 2
examples:
- |
#include <dt-bindings/clock/qcom,qcs615-gcc.h>

View File

@@ -28,6 +28,7 @@ properties:
- qcom,qcm2290-qusb2-phy
- qcom,qcs615-qusb2-phy
- qcom,sdm660-qusb2-phy
- qcom,shikra-qusb2-phy
- qcom,sm4250-qusb2-phy
- qcom,sm6115-qusb2-phy
- items:

View File

@@ -35,6 +35,17 @@ properties:
phy-supply:
description:
Phandle to a regulator that provides power to the PHY.
deprecated: true
vdda-0p9-supply:
description:
Phandle to a 0.9V regulator supply to the PHY, which draws a peak
current of 46 mA.
vdda-1p2-supply:
description:
Phandle to a 1.2V regulator supply to the PHY, which draws a peak
current of 15 mA.
"#phy-cells":
const: 0

View File

@@ -20,6 +20,8 @@ properties:
- qcom,eliza-qmp-gen3x2-pcie-phy
- qcom,glymur-qmp-gen4x2-pcie-phy
- qcom,glymur-qmp-gen5x4-pcie-phy
- qcom,hawi-qmp-gen3x2-pcie-phy
- qcom,hawi-qmp-gen4x1-pcie-phy
- qcom,kaanapali-qmp-gen3x2-pcie-phy
- qcom,qcs615-qmp-gen3x1-pcie-phy
- qcom,qcs8300-qmp-gen4x2-pcie-phy
@@ -43,6 +45,7 @@ properties:
- qcom,sm8350-qmp-gen3x2-pcie-phy
- qcom,sm8450-qmp-gen3x1-pcie-phy
- qcom,sm8450-qmp-gen4x2-pcie-phy
- qcom,sm8475-qmp-gen3x1-pcie-phy
- qcom,sm8550-qmp-gen3x2-pcie-phy
- qcom,sm8550-qmp-gen4x2-pcie-phy
- qcom,sm8650-qmp-gen3x2-pcie-phy
@@ -175,6 +178,7 @@ allOf:
- qcom,sm8350-qmp-gen3x2-pcie-phy
- qcom,sm8450-qmp-gen3x1-pcie-phy
- qcom,sm8450-qmp-gen3x2-pcie-phy
- qcom,sm8475-qmp-gen3x1-pcie-phy
- qcom,sm8550-qmp-gen3x2-pcie-phy
- qcom,sm8550-qmp-gen4x2-pcie-phy
- qcom,sm8650-qmp-gen3x2-pcie-phy
@@ -196,6 +200,8 @@ allOf:
- qcom,eliza-qmp-gen3x2-pcie-phy
- qcom,glymur-qmp-gen4x2-pcie-phy
- qcom,glymur-qmp-gen5x4-pcie-phy
- qcom,hawi-qmp-gen3x2-pcie-phy
- qcom,hawi-qmp-gen4x1-pcie-phy
- qcom,qcs8300-qmp-gen4x2-pcie-phy
- qcom,sa8775p-qmp-gen4x2-pcie-phy
- qcom,sa8775p-qmp-gen4x4-pcie-phy
@@ -223,6 +229,8 @@ allOf:
- qcom,eliza-qmp-gen3x2-pcie-phy
- qcom,glymur-qmp-gen4x2-pcie-phy
- qcom,glymur-qmp-gen5x4-pcie-phy
- qcom,hawi-qmp-gen3x2-pcie-phy
- qcom,hawi-qmp-gen4x1-pcie-phy
- qcom,kaanapali-qmp-gen3x2-pcie-phy
- qcom,sm8550-qmp-gen4x2-pcie-phy
- qcom,sm8650-qmp-gen4x2-pcie-phy

View File

@@ -38,6 +38,7 @@ properties:
- qcom,kaanapali-qmp-ufs-phy
- const: qcom,sm8750-qmp-ufs-phy
- enum:
- qcom,hawi-qmp-ufs-phy
- qcom,milos-qmp-ufs-phy
- qcom,msm8996-qmp-ufs-phy
- qcom,msm8998-qmp-ufs-phy
@@ -108,6 +109,7 @@ allOf:
compatible:
contains:
enum:
- qcom,hawi-qmp-ufs-phy
- qcom,milos-qmp-ufs-phy
- qcom,msm8998-qmp-ufs-phy
- qcom,sa8775p-qmp-ufs-phy

View File

@@ -26,6 +26,7 @@ properties:
- const: qcom,sm8750-qmp-usb3-dp-phy
- enum:
- qcom,glymur-qmp-usb3-dp-phy
- qcom,hawi-qmp-usb3-dp-phy
- qcom,sar2130p-qmp-usb3-dp-phy
- qcom,sc7180-qmp-usb3-dp-phy
- qcom,sc7280-qmp-usb3-dp-phy
@@ -37,6 +38,7 @@ properties:
- qcom,sm8250-qmp-usb3-dp-phy
- qcom,sm8350-qmp-usb3-dp-phy
- qcom,sm8450-qmp-usb3-dp-phy
- qcom,sm8475-qmp-usb3-dp-phy
- qcom,sm8550-qmp-usb3-dp-phy
- qcom,sm8650-qmp-usb3-dp-phy
- qcom,sm8750-qmp-usb3-dp-phy
@@ -209,6 +211,7 @@ allOf:
contains:
enum:
- qcom,glymur-qmp-usb3-dp-phy
- qcom,hawi-qmp-usb3-dp-phy
- qcom,sar2130p-qmp-usb3-dp-phy
- qcom,sc8280xp-qmp-usb43dp-phy
- qcom,sm6350-qmp-usb3-dp-phy

View File

@@ -16,6 +16,7 @@ properties:
- enum:
- renesas,usb2-phy-r8a77470 # RZ/G1C
- renesas,usb2-phy-r9a08g045 # RZ/G3S
- renesas,usb2-phy-r9a08g046 # RZ/G3L
- renesas,usb2-phy-r9a09g057 # RZ/V2H(P)
- items:
@@ -132,6 +133,7 @@ allOf:
enum:
- renesas,usb2-phy-r9a09g057
- renesas,usb2-phy-r9a08g045
- renesas,usb2-phy-r9a08g046
- renesas,rzg2l-usb2-phy
then:
properties:

View File

@@ -56,6 +56,16 @@ properties:
description:
Some additional phy settings are access through GRF regs.
rockchip,clk-lane-phase:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 7
default: 3
description:
Clock lane sampling phase selection (hardware tap index 07). Each step
corresponds to an approximately 40 ps delay as described in the hardware
specification.
required:
- compatible
- reg

View File

@@ -0,0 +1,68 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/spacemit,k3-combo-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Spacemit K3 PCIE/USB3 Comb PHY
maintainers:
- Inochi Amaoto <inochiama@gmail.com>
properties:
compatible:
const: spacemit,k3-combo-phy
reg:
maxItems: 1
"#phy-cells":
const: 2
description:
The first one is phy id, the second one is phy type. This
only supports types are PCIe and USB .
spacemit,apb-spare:
$ref: /schemas/types.yaml#/definitions/phandle
description:
Phandle to APB SPARE system controller interface, used for
PHY calibration.
spacemit,apmu:
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
- items:
- description: phandle of APMU syscon
- description: configuration of the PHY lanes
description: |
Phandle to control PHY mux configuration. The configuration
is described as follows:
bit 4: 0 - PCIe A x8 mode, 1 - PCIe lane share mode
bit 3: 0 - PCIe A x4 mode, 1 - PCIe A x2 and PCIe B x2 mode
bit 2: 0 - PCIe C lane 0 is PCIe mode , 1 - USB mode
bit 1: 0 - PCIe C lane 1 is PCIe mode , 1 - USB mode
bit 0: 0 - PCIe D lane is PCIe mode , 1 - USB mode
The bit[3:0] is only valid when bit 4 is 1.
This mux control does not affect the PHY for PCIe E, it is always
in PCIe mode.
required:
- compatible
- reg
- "#phy-cells"
- spacemit,apb-spare
- spacemit,apmu
additionalProperties: false
examples:
- |
phy@81d00000 {
compatible = "spacemit,k3-combo-phy";
reg = <0x81d00000 0x600000>;
#phy-cells = <2>;
spacemit,apb-spare = <&apb_spare>;
spacemit,apmu = <&apmu 0x00>;
};

View File

@@ -10979,6 +10979,7 @@ F: include/uapi/asm-generic/
GENERIC PHY FRAMEWORK
M: Vinod Koul <vkoul@kernel.org>
R: Neil Armstrong <neil.armstrong@linaro.org>
R: Manivannan Sadhasivam <mani@kernel.org>
L: linux-phy@lists.infradead.org
S: Supported
Q: https://patchwork.kernel.org/project/linux-phy/list/
@@ -29873,6 +29874,7 @@ F: drivers/edac/zynqmp_edac.c
XILINX ZYNQMP PSGTR PHY DRIVER
M: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
M: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
L: linux-kernel@vger.kernel.org
S: Supported
T: git https://github.com/Xilinx/linux-xlnx.git

View File

@@ -7,6 +7,7 @@ config PHY_FSL_IMX8MQ_USB
depends on OF && HAS_IOMEM
depends on TYPEC || TYPEC=n
select GENERIC_PHY
select REGMAP_MMIO
default ARCH_MXC && ARM64
config PHY_MIXEL_LVDS_PHY

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0+
/* Copyright (c) 2017 NXP. */
/* Copyright 2017-2026 NXP. */
#include <linux/bitfield.h>
#include <linux/clk.h>
@@ -9,7 +9,10 @@
#include <linux/of.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/regmap.h>
#include <linux/usb/typec_mux.h>
#define PHY_CTRL0 0x0
@@ -55,6 +58,8 @@
#define PHY_CTRL6_ALT_CLK_EN BIT(1)
#define PHY_CTRL6_ALT_CLK_SEL BIT(0)
#define PHY_CRCTL 0x30
#define PHY_TUNE_DEFAULT 0xffffffff
#define TCA_CLK_RST 0x00
@@ -118,6 +123,7 @@ struct imx8mq_usb_phy {
void __iomem *base;
struct regulator *vbus;
struct tca_blk *tca;
struct regmap *cr_regmap;
u32 pcs_tx_swing_full;
u32 pcs_tx_deemph_3p5db;
u32 tx_vref_tune;
@@ -127,6 +133,10 @@ struct imx8mq_usb_phy {
u32 comp_dis_tune;
};
struct imx8mq_usb_phy_drvdata {
const struct phy_ops *ops;
bool need_genpd_rpm_on;
};
static void tca_blk_orientation_set(struct tca_blk *tca,
enum typec_orientation orientation);
@@ -136,17 +146,15 @@ static int tca_blk_typec_switch_set(struct typec_switch_dev *sw,
{
struct imx8mq_usb_phy *imx_phy = typec_switch_get_drvdata(sw);
struct tca_blk *tca = imx_phy->tca;
int ret;
if (tca->orientation == orientation)
return 0;
ret = clk_prepare_enable(imx_phy->clk);
if (ret)
return ret;
PM_RUNTIME_ACQUIRE_IF_ENABLED(&imx_phy->phy->dev, pm);
if (PM_RUNTIME_ACQUIRE_ERR(&pm))
return -ENXIO;
tca_blk_orientation_set(tca, orientation);
clk_disable_unprepare(imx_phy->clk);
return 0;
}
@@ -173,9 +181,9 @@ static struct typec_switch_dev *tca_blk_get_typec_switch(struct platform_device
return sw;
}
static void tca_blk_put_typec_switch(struct typec_switch_dev *sw)
static void tca_blk_put_typec_switch(void *data)
{
typec_switch_unregister(sw);
typec_switch_unregister(data);
}
static void tca_blk_orientation_set(struct tca_blk *tca,
@@ -248,6 +256,7 @@ static struct tca_blk *imx95_usb_phy_get_tca(struct platform_device *pdev,
struct device *dev = &pdev->dev;
struct resource *res;
struct tca_blk *tca;
int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!res)
@@ -266,19 +275,13 @@ static struct tca_blk *imx95_usb_phy_get_tca(struct platform_device *pdev,
tca->orientation = TYPEC_ORIENTATION_NORMAL;
tca->sw = tca_blk_get_typec_switch(pdev, imx_phy);
ret = devm_add_action_or_reset(&pdev->dev, tca_blk_put_typec_switch, tca->sw);
if (ret)
return ERR_PTR(ret);
return tca;
}
static void imx95_usb_phy_put_tca(struct imx8mq_usb_phy *imx_phy)
{
struct tca_blk *tca = imx_phy->tca;
if (!tca)
return;
tca_blk_put_typec_switch(tca->sw);
}
static u32 phy_tx_vref_tune_from_property(u32 percent)
{
percent = clamp(percent, 94U, 124U);
@@ -625,16 +628,6 @@ static int imx8mq_phy_power_on(struct phy *phy)
if (ret)
return ret;
ret = clk_prepare_enable(imx_phy->clk);
if (ret)
return ret;
ret = clk_prepare_enable(imx_phy->alt_clk);
if (ret) {
clk_disable_unprepare(imx_phy->clk);
return ret;
}
/* Disable rx term override */
value = readl(imx_phy->base + PHY_CTRL6);
value &= ~PHY_CTRL6_RXTERM_OVERRIDE_SEL;
@@ -653,8 +646,6 @@ static int imx8mq_phy_power_off(struct phy *phy)
value |= PHY_CTRL6_RXTERM_OVERRIDE_SEL;
writel(value, imx_phy->base + PHY_CTRL6);
clk_disable_unprepare(imx_phy->alt_clk);
clk_disable_unprepare(imx_phy->clk);
regulator_disable(imx_phy->vbus);
return 0;
@@ -674,23 +665,45 @@ static const struct phy_ops imx8mp_usb_phy_ops = {
.owner = THIS_MODULE,
};
static const struct imx8mq_usb_phy_drvdata imx8mq_usb_phy_data = {
.ops = &imx8mq_usb_phy_ops,
};
static const struct imx8mq_usb_phy_drvdata imx8mp_usb_phy_data = {
.ops = &imx8mp_usb_phy_ops,
.need_genpd_rpm_on = true,
};
static const struct imx8mq_usb_phy_drvdata imx95_usb_phy_data = {
.ops = &imx8mp_usb_phy_ops,
};
static const struct of_device_id imx8mq_usb_phy_of_match[] = {
{.compatible = "fsl,imx8mq-usb-phy",
.data = &imx8mq_usb_phy_ops,},
.data = &imx8mq_usb_phy_data,},
{.compatible = "fsl,imx8mp-usb-phy",
.data = &imx8mp_usb_phy_ops,},
.data = &imx8mp_usb_phy_data,},
{.compatible = "fsl,imx95-usb-phy",
.data = &imx8mp_usb_phy_ops,},
.data = &imx95_usb_phy_data,},
{ }
};
MODULE_DEVICE_TABLE(of, imx8mq_usb_phy_of_match);
static const struct regmap_config imx_cr_regmap_config = {
.name = "cr",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.max_register = 0x7,
};
static int imx8mq_usb_phy_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
struct device *dev = &pdev->dev;
struct imx8mq_usb_phy *imx_phy;
const struct phy_ops *phy_ops;
const struct imx8mq_usb_phy_drvdata *phy_data;
int ret;
imx_phy = devm_kzalloc(dev, sizeof(*imx_phy), GFP_KERNEL);
if (!imx_phy)
@@ -698,13 +711,13 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, imx_phy);
imx_phy->clk = devm_clk_get(dev, "phy");
imx_phy->clk = devm_clk_get_enabled(dev, "phy");
if (IS_ERR(imx_phy->clk)) {
dev_err(dev, "failed to get imx8mq usb phy clock\n");
return PTR_ERR(imx_phy->clk);
}
imx_phy->alt_clk = devm_clk_get_optional(dev, "alt");
imx_phy->alt_clk = devm_clk_get_optional_enabled(dev, "alt");
if (IS_ERR(imx_phy->alt_clk))
return dev_err_probe(dev, PTR_ERR(imx_phy->alt_clk),
"Failed to get alt clk\n");
@@ -713,45 +726,120 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
if (IS_ERR(imx_phy->base))
return PTR_ERR(imx_phy->base);
phy_ops = of_device_get_match_data(dev);
if (!phy_ops)
return -EINVAL;
imx_phy->phy = devm_phy_create(dev, NULL, phy_ops);
if (IS_ERR(imx_phy->phy))
return PTR_ERR(imx_phy->phy);
imx_phy->cr_regmap = devm_regmap_init_mmio(dev, imx_phy->base + PHY_CRCTL,
&imx_cr_regmap_config);
if (IS_ERR(imx_phy->cr_regmap)) {
dev_warn(dev, "Fail to init debug register regmap\n");
imx_phy->cr_regmap = NULL;
}
imx_phy->vbus = devm_regulator_get(dev, "vbus");
if (IS_ERR(imx_phy->vbus))
return dev_err_probe(dev, PTR_ERR(imx_phy->vbus), "failed to get vbus\n");
phy_data = of_device_get_match_data(dev);
if (!phy_data)
return -EINVAL;
if (phy_data->need_genpd_rpm_on) {
ret = dev_pm_genpd_rpm_always_on(dev, true);
if (ret && ret != -EOPNOTSUPP)
dev_warn(dev, "failed to set genpd rpm always on\n");
}
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
imx_phy->phy = devm_phy_create(dev, NULL, phy_data->ops);
if (IS_ERR(imx_phy->phy)) {
ret = dev_err_probe(dev, PTR_ERR(imx_phy->phy),
"failed to create PHY\n");
goto disable_rpm;
}
phy_set_drvdata(imx_phy->phy, imx_phy);
imx_phy->tca = imx95_usb_phy_get_tca(pdev, imx_phy);
if (IS_ERR(imx_phy->tca))
return dev_err_probe(dev, PTR_ERR(imx_phy->tca),
"failed to get tca\n");
if (IS_ERR(imx_phy->tca)) {
ret = dev_err_probe(dev, PTR_ERR(imx_phy->tca),
"failed to get tca\n");
goto disable_rpm;
}
imx8m_get_phy_tuning_data(imx_phy);
device_set_wakeup_capable(dev, true);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(phy_provider)) {
ret = dev_err_probe(dev, PTR_ERR(phy_provider),
"failed to register phy provider\n");
goto disable_rpm;
}
return PTR_ERR_OR_ZERO(phy_provider);
return 0;
disable_rpm:
pm_runtime_disable(dev);
return ret;
}
static void imx8mq_usb_phy_remove(struct platform_device *pdev)
{
struct imx8mq_usb_phy *imx_phy = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
int ret;
imx95_usb_phy_put_tca(imx_phy);
ret = pm_runtime_get_sync(dev);
if (ret < 0)
dev_warn(dev, "failed to resume on remove: %d\n", ret);
pm_runtime_disable(dev);
pm_runtime_put_noidle(dev);
}
static int imx8mq_usb_phy_runtime_suspend(struct device *dev)
{
struct imx8mq_usb_phy *imx_phy = dev_get_drvdata(dev);
if (imx_phy->cr_regmap)
regcache_cache_only(imx_phy->cr_regmap, true);
clk_disable_unprepare(imx_phy->alt_clk);
clk_disable_unprepare(imx_phy->clk);
return 0;
}
static int imx8mq_usb_phy_runtime_resume(struct device *dev)
{
struct imx8mq_usb_phy *imx_phy = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(imx_phy->clk);
if (ret)
return ret;
ret = clk_prepare_enable(imx_phy->alt_clk);
if (ret) {
clk_disable_unprepare(imx_phy->clk);
return ret;
}
if (imx_phy->cr_regmap)
regcache_cache_only(imx_phy->cr_regmap, false);
return 0;
}
static DEFINE_RUNTIME_DEV_PM_OPS(imx8mq_usb_phy_pm_ops, imx8mq_usb_phy_runtime_suspend,
imx8mq_usb_phy_runtime_resume, NULL);
static struct platform_driver imx8mq_usb_phy_driver = {
.probe = imx8mq_usb_phy_probe,
.remove = imx8mq_usb_phy_remove,
.driver = {
.name = "imx8mq-usb-phy",
.of_match_table = imx8mq_usb_phy_of_match,
.pm = pm_ptr(&imx8mq_usb_phy_pm_ops),
.suppress_bind_attrs = true,
}
};

View File

@@ -387,7 +387,7 @@ static void lynx_10g_backup_pccr_val(struct lynx_lane *lane)
*/
static bool lynx_10g_pccr_val_enabled(u32 pccr)
{
return FIELD_PREP(PCCR8_SGMIIa_CFG, pccr) != 0;
return FIELD_GET(PCCR8_SGMIIa_CFG, pccr) != 0;
}
static bool lynx_10g_lane_is_3_125g(struct lynx_lane *lane)

View File

@@ -679,12 +679,15 @@ static int fsl_samsung_hdmi_phy_probe(struct platform_device *pdev)
return 0;
register_clk_failed:
pm_runtime_disable(phy->dev);
pm_runtime_put_noidle(phy->dev);
return ret;
}
static void fsl_samsung_hdmi_phy_remove(struct platform_device *pdev)
{
of_clk_del_provider(pdev->dev.of_node);
pm_runtime_disable(&pdev->dev);
}
static int __maybe_unused fsl_samsung_hdmi_phy_suspend(struct device *dev)

View File

@@ -21,4 +21,5 @@ obj-$(CONFIG_PHY_MTK_MIPI_CSI_0_5) += phy-mtk-mipi-csi-0-5.o
phy-mtk-mipi-dsi-drv-y := phy-mtk-mipi-dsi.o
phy-mtk-mipi-dsi-drv-y += phy-mtk-mipi-dsi-mt8173.o
phy-mtk-mipi-dsi-drv-y += phy-mtk-mipi-dsi-mt8183.o
phy-mtk-mipi-dsi-drv-y += phy-mtk-mipi-dsi-mt8196.o
obj-$(CONFIG_PHY_MTK_MIPI_DSI) += phy-mtk-mipi-dsi-drv.o

View File

@@ -0,0 +1,201 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: jitao.shi <jitao.shi@mediatek.com>
*
* Copyright (c) 2026 Collabora Ltd.
* AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
*/
#include "phy-mtk-io.h"
#include "phy-mtk-mipi-dsi.h"
#define MIPITX_LANE_CON 0x0004
#define RG_DSI_CPHY_T1DRV_EN BIT(0)
#define RG_DSI_ANA_CK_SEL BIT(1)
#define RG_DSI_PHY_CK_SEL BIT(2)
#define RG_DSI_CPHY_EN BIT(3)
#define RG_DSI_PHYCK_INV_EN BIT(4)
#define RG_DSI_PWR04_EN BIT(5)
#define RG_DSI_BG_LPF_EN BIT(6)
#define RG_DSI_BG_CORE_EN BIT(7)
#define RG_DSI_PAD_TIEL_SEL BIT(8)
#define MIPITX_VOLTAGE_SEL 0x0008
#define RG_DSI_HSTX_LDO_REF_SEL GENMASK(9, 6)
#define RG_DSI_PRD_REF_SEL GENMASK(5, 0)
#define RG_DSI_PRD_REF_MINI 0
#define RG_DSI_PRD_REF_DEF 4
#define RG_DSI_PRD_REF_MAX 7
#define MIPITX_PRESERVED 0x000c
#define MIPITX_PRESERVED_DEF 0xffff0040
#define MIPITX_PRESERVED_MINI 0xffff00f0
#define MIPITX_PLL_PWR 0x0028
#define AD_DSI_PLL_SDM_PWR_ON BIT(0)
#define AD_DSI_PLL_SDM_ISO_EN BIT(1)
#define MIPITX_PLL_CON0 0x002c
#define MIPITX_PLL_CON1 0x0030
#define RG_DSI_PLL_EN BIT(0)
#define RG_DSI_PLL_POSDIV GENMASK(10, 8)
#define MIPITX_PLL_CON2 0x0034
#define MIPITX_PLL_CON3 0x0038
#define MIPITX_PLL_CON4 0x003c
#define RG_DSI_PLL_IBIAS GENMASK(11, 10)
#define MIPITX_D2_SW_CTL_EN 0x015c
#define MIPITX_D0_SW_CTL_EN 0x025c
#define MIPITX_CK_CKMODE_EN 0x0320
#define DSI_CK_CKMODE_EN BIT(0)
#define MIPITX_CK_SW_CTL_EN 0x035c
#define MIPITX_D1_SW_CTL_EN 0x045c
#define MIPITX_D3_SW_CTL_EN 0x055c
#define DSI_SW_CTL_EN BIT(0)
#define DSI_PHY_XTAL_CLK_HZ 26000000
#define DSI_PHY_PLL_MIN_RATE_HZ 125000000
#define DSI_PHY_PLL_MAX_RATE_HZ 2000000000
static int mtk_mipi_tx_pll_enable(struct clk_hw *hw)
{
struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
void __iomem *base = mipi_tx->regs;
u32 voltage = RG_DSI_PRD_REF_MINI;
u32 pres = MIPITX_PRESERVED_MINI;
unsigned long long pcw_calc;
unsigned int txdiv, txdiv0;
u32 pcw;
dev_dbg(mipi_tx->dev, "enable: %u bps\n", mipi_tx->data_rate);
if (mipi_tx->data_rate >= DSI_PHY_PLL_MAX_RATE_HZ) {
/* Select higher signaling voltage for fast data rates */
voltage = RG_DSI_PRD_REF_DEF;
pres = MIPITX_PRESERVED_DEF;
txdiv = 1;
txdiv0 = 0;
} else if (mipi_tx->data_rate >= 1000000000) {
txdiv = 2;
txdiv0 = 1;
} else if (mipi_tx->data_rate >= 500000000) {
txdiv = 4;
txdiv0 = 2;
} else if (mipi_tx->data_rate > 250000000) {
txdiv = 8;
txdiv0 = 3;
} else if (mipi_tx->data_rate >= 125000000) {
txdiv = 16;
txdiv0 = 4;
} else {
return -EINVAL;
}
pcw_calc = ((u64)(mipi_tx->data_rate / 2) * txdiv) << 24;
pcw_calc = div_u64(pcw_calc, DSI_PHY_XTAL_CLK_HZ);
if (pcw_calc > U32_MAX) {
dev_err(mipi_tx->dev, "Calculated PCW=%llu overflow!\n", pcw_calc);
return -EINVAL;
}
pcw = (u32)pcw_calc;
mtk_phy_update_field(base + MIPITX_VOLTAGE_SEL, RG_DSI_PRD_REF_SEL, voltage);
writel(pres, base + MIPITX_PRESERVED);
/* Enable the SDM and wait for power to stabilize */
mtk_phy_set_bits(base + MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON);
mtk_phy_clear_bits(base + MIPITX_PLL_CON1, RG_DSI_PLL_EN);
udelay(30);
/* Disable isolation and program PLL's PCW and dividers */
mtk_phy_clear_bits(base + MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN);
writel(pcw, base + MIPITX_PLL_CON0);
mtk_phy_update_field(base + MIPITX_PLL_CON1, RG_DSI_PLL_POSDIV, txdiv0);
/* Enable the PLL and wait for the clock output to stabilize */
mtk_phy_set_bits(base + MIPITX_PLL_CON1, RG_DSI_PLL_EN);
udelay(30);
return 0;
}
static void mtk_mipi_tx_pll_disable(struct clk_hw *hw)
{
struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
void __iomem *base = mipi_tx->regs;
mtk_phy_clear_bits(base + MIPITX_PLL_CON1, RG_DSI_PLL_EN);
mtk_phy_set_bits(base + MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN);
mtk_phy_clear_bits(base + MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON);
}
static int mtk_mipi_tx_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
req->rate = clamp_val(req->rate,
DSI_PHY_PLL_MIN_RATE_HZ, DSI_PHY_PLL_MAX_RATE_HZ);
return 0;
}
static const struct clk_ops mtk_mipi_tx_pll_ops = {
.enable = mtk_mipi_tx_pll_enable,
.disable = mtk_mipi_tx_pll_disable,
.determine_rate = mtk_mipi_tx_pll_determine_rate,
.set_rate = mtk_mipi_tx_pll_set_rate,
.recalc_rate = mtk_mipi_tx_pll_recalc_rate,
};
static void mtk_mipi_tx_power_on_signal(struct phy *phy)
{
struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
void __iomem *base = mipi_tx->regs;
/* BG_LPF_EN / BG_CORE_EN */
writel(RG_DSI_PAD_TIEL_SEL | RG_DSI_BG_CORE_EN, base + MIPITX_LANE_CON);
/* Wait for MIPI core to enable */
usleep_range(30, 100);
writel(RG_DSI_BG_CORE_EN | RG_DSI_BG_LPF_EN, base + MIPITX_LANE_CON);
/* Switch OFF each Lane */
mtk_phy_clear_bits(base + MIPITX_D0_SW_CTL_EN, DSI_SW_CTL_EN);
mtk_phy_clear_bits(base + MIPITX_D1_SW_CTL_EN, DSI_SW_CTL_EN);
mtk_phy_clear_bits(base + MIPITX_D2_SW_CTL_EN, DSI_SW_CTL_EN);
mtk_phy_clear_bits(base + MIPITX_D3_SW_CTL_EN, DSI_SW_CTL_EN);
mtk_phy_clear_bits(base + MIPITX_CK_SW_CTL_EN, DSI_SW_CTL_EN);
/*
* The MIPI TX drive strength is in the range of 3000 ~ 6000 microamps:
* RG_DSI_HSTX_LDO_REF_SEL expresses an offset from the minimum drive
* strength (3000uA) and can add a maximum offset of 3000uA, reaching a
* maximum drive strength of 3000+3000=6000uA.
*/
mtk_phy_update_field(base + MIPITX_VOLTAGE_SEL, RG_DSI_HSTX_LDO_REF_SEL,
(mipi_tx->mipitx_drive - 3000) / 200);
mtk_phy_set_bits(base + MIPITX_CK_CKMODE_EN, DSI_CK_CKMODE_EN);
}
static void mtk_mipi_tx_power_off_signal(struct phy *phy)
{
struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
void __iomem *base = mipi_tx->regs;
/* Switch ON each lane one by one */
mtk_phy_set_bits(base + MIPITX_D0_SW_CTL_EN, DSI_SW_CTL_EN);
mtk_phy_set_bits(base + MIPITX_D1_SW_CTL_EN, DSI_SW_CTL_EN);
mtk_phy_set_bits(base + MIPITX_D2_SW_CTL_EN, DSI_SW_CTL_EN);
mtk_phy_set_bits(base + MIPITX_D3_SW_CTL_EN, DSI_SW_CTL_EN);
mtk_phy_set_bits(base + MIPITX_CK_SW_CTL_EN, DSI_SW_CTL_EN);
writel(RG_DSI_PAD_TIEL_SEL | RG_DSI_BG_CORE_EN, base + MIPITX_LANE_CON);
writel(RG_DSI_PAD_TIEL_SEL, base + MIPITX_LANE_CON);
}
const struct mtk_mipitx_data mt8196_mipitx_data = {
.mipi_tx_clk_ops = &mtk_mipi_tx_pll_ops,
.mipi_tx_enable_signal = mtk_mipi_tx_power_on_signal,
.mipi_tx_disable_signal = mtk_mipi_tx_power_off_signal,
};

View File

@@ -183,6 +183,7 @@ static const struct of_device_id mtk_mipi_tx_match[] = {
{ .compatible = "mediatek,mt2701-mipi-tx", .data = &mt2701_mipitx_data },
{ .compatible = "mediatek,mt8173-mipi-tx", .data = &mt8173_mipitx_data },
{ .compatible = "mediatek,mt8183-mipi-tx", .data = &mt8183_mipitx_data },
{ .compatible = "mediatek,mt8196-mipi-tx", .data = &mt8196_mipitx_data },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mtk_mipi_tx_match);

View File

@@ -42,5 +42,5 @@ unsigned long mtk_mipi_tx_pll_recalc_rate(struct clk_hw *hw,
extern const struct mtk_mipitx_data mt2701_mipitx_data;
extern const struct mtk_mipitx_data mt8173_mipitx_data;
extern const struct mtk_mipitx_data mt8183_mipitx_data;
extern const struct mtk_mipitx_data mt8196_mipitx_data;
#endif

View File

@@ -198,7 +198,7 @@ static int can_transceiver_phy_probe(struct platform_device *pdev)
if (drvdata->flags & CAN_TRANSCEIVER_SILENT_PRESENT) {
silent_gpio = devm_gpiod_get_index_optional(dev, "silent", i,
GPIOD_OUT_LOW);
GPIOD_OUT_HIGH);
if (IS_ERR(silent_gpio))
return PTR_ERR(silent_gpio);
can_transceiver_phy->silent_gpio = silent_gpio;

View File

@@ -77,6 +77,16 @@ config PHY_QCOM_QMP_PCIE
Enable this to support the QMP PCIe PHY transceiver that is used
with PCIe controllers on Qualcomm chips.
config PHY_QCOM_QMP_PCIE_MULTIPHY
tristate "Qualcomm QMP PCIe Multi PHY Driver"
depends on PCI || COMPILE_TEST
select GENERIC_PHY
help
Enable this to support the QMP PCIe PHY transceiver that is used
with PCIe controllers on Qualcomm chips. This PHY is a single
multi-lane QMP block that can be configured either as one wide
link or as multiple narrower independent links (bifurcation).
config PHY_QCOM_QMP_PCIE_8996
tristate "Qualcomm QMP PCIe 8996 PHY Driver"
depends on PCI || COMPILE_TEST

View File

@@ -10,6 +10,7 @@ obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o
obj-$(CONFIG_PHY_QCOM_QMP_COMBO) += phy-qcom-qmp-combo.o phy-qcom-qmp-usbc.o
obj-$(CONFIG_PHY_QCOM_QMP_PCIE) += phy-qcom-qmp-pcie.o
obj-$(CONFIG_PHY_QCOM_QMP_PCIE_MULTIPHY) += phy-qcom-qmp-pcie-multiphy.o
obj-$(CONFIG_PHY_QCOM_QMP_PCIE_8996) += phy-qcom-qmp-pcie-msm8996.o
obj-$(CONFIG_PHY_QCOM_QMP_UFS) += phy-qcom-qmp-ufs.o
obj-$(CONFIG_PHY_QCOM_QMP_USB) += phy-qcom-qmp-usb.o

View File

@@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2026, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_COM_AON_V10_H_
#define QCOM_PHY_QMP_COM_AON_V10_H_
/* Only for QMP V10 PHY - COM AON registers */
#define QPHY_V10_COM_AON_USB3_AON_TOGGLE_ENABLE 0x00
#define QPHY_V10_COM_AON_DP_AON_TOGGLE_ENABLE 0x04
#define QPHY_V10_COM_AON_DUMMY_STATUS 0x08
#endif

View File

@@ -32,6 +32,7 @@
#include "phy-qcom-qmp.h"
#include "phy-qcom-qmp-pcs-aon-v6.h"
#include "phy-qcom-qmp-pcs-aon-v8.h"
#include "phy-qcom-qmp-pcs-aon-v10.h"
#include "phy-qcom-qmp-pcs-misc-v3.h"
#include "phy-qcom-qmp-pcs-misc-v4.h"
#include "phy-qcom-qmp-pcs-misc-v5.h"
@@ -40,6 +41,7 @@
#include "phy-qcom-qmp-pcs-usb-v5.h"
#include "phy-qcom-qmp-pcs-usb-v6.h"
#include "phy-qcom-qmp-pcs-usb-v8.h"
#include "phy-qcom-qmp-pcs-usb-v10.h"
#include "phy-qcom-qmp-dp-com-v3.h"
@@ -49,9 +51,12 @@
#include "phy-qcom-qmp-dp-phy-v5.h"
#include "phy-qcom-qmp-dp-phy-v6.h"
#include "phy-qcom-qmp-dp-phy-v8.h"
#include "phy-qcom-qmp-dp-phy-v10.h"
#include "phy-qcom-qmp-usb43-pcs-v8.h"
#include "phy-qcom-qmp-com-aon-v10.h"
/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */
/* DP PHY soft reset */
#define SW_DPPHY_RESET BIT(0)
@@ -268,6 +273,36 @@ static const unsigned int qmp_v8_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_TX_TRANSCEIVER_BIAS_EN] = QSERDES_V8_TX_TRANSCEIVER_BIAS_EN,
};
static const unsigned int qmp_v10_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_SW_RESET] = QPHY_V10_PCS_SW_RESET,
[QPHY_START_CTRL] = QPHY_V10_PCS_START_CONTROL,
[QPHY_PCS_STATUS] = QPHY_V10_PCS_PCS_STATUS1,
[QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V10_PCS_POWER_DOWN_CONTROL,
/* In PCS_USB */
[QPHY_PCS_AUTONOMOUS_MODE_CTRL] = QPHY_V10_PCS_USB3_AUTONOMOUS_MODE_CTRL,
[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V10_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR,
[QPHY_PCS_CLAMP_ENABLE] = QPHY_V10_PCS_AON_CLAMP_ENABLE,
[QPHY_AON_TOGGLE_ENABLE] = QPHY_V10_COM_AON_USB3_AON_TOGGLE_ENABLE,
[QPHY_DP_AON_TOGGLE_ENABLE] = QPHY_V10_COM_AON_DP_AON_TOGGLE_ENABLE,
[QPHY_COM_RESETSM_CNTRL] = QSERDES_V10_COM_RESETSM_CNTRL,
[QPHY_COM_C_READY_STATUS] = QSERDES_V10_COM_C_READY_STATUS,
[QPHY_COM_CMN_STATUS] = QSERDES_V10_COM_CMN_STATUS,
[QPHY_COM_BIAS_EN_CLKBUFLR_EN] = QSERDES_V10_COM_BIAS_EN_CLKBUFLR_EN,
[QPHY_DP_PHY_STATUS] = QSERDES_V10_DP_PHY_STATUS,
[QPHY_DP_PHY_VCO_DIV] = QSERDES_V10_DP_PHY_VCO_DIV,
[QPHY_TX_TX_POL_INV] = QSERDES_V10_TX_TX_POL_INV,
[QPHY_TX_TX_DRV_LVL] = QSERDES_V10_TX_TX_DRV_LVL,
[QPHY_TX_TX_EMP_POST1_LVL] = QSERDES_V10_TX_TX_EMP_POST1_LVL,
[QPHY_TX_HIGHZ_DRVR_EN] = QSERDES_V10_TX_HIGHZ_DRVR_EN,
[QPHY_TX_TRANSCEIVER_BIAS_EN] = QSERDES_V10_TX_TRANSCEIVER_BIAS_EN,
};
static const unsigned int qmp_v8_n3_usb43dpphy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_SW_RESET] = QPHY_V8_USB43_PCS_SW_RESET,
[QPHY_START_CTRL] = QPHY_V8_USB43_PCS_START_CONTROL,
@@ -1063,6 +1098,55 @@ static const struct qmp_phy_init_tbl sm8350_usb3_pcs_usb_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07),
};
static const struct qmp_phy_init_tbl sm8475_usb3_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_FO_GAIN, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SO_GAIN, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_PI_CONTROLS, 0x99),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SB2_THRESH1, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SB2_THRESH2, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SB2_GAIN1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SB2_GAIN2, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_AUX_DATA_TCOARSE_TFINE, 0xa0),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_VGA_CAL_CNTRL1, 0x54),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_VGA_CAL_CNTRL2, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_GM_CAL, 0x13),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_IDAC_TSETTLE_LOW, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_IDAC_TSETTLE_HIGH, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_SIGDET_CNTRL, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_SIGDET_DEGLITCH_CNTRL, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_LOW, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH2, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH3, 0xdf),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH4, 0xfe),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_LOW, 0xdc),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH, 0x5c),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH2, 0x9c),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH3, 0x1d),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH4, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_DFE_EN_TIMER, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_DCC_CTRL1, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_VTH_CODE, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_SIGDET_CAL_CTRL1, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_SIGDET_CAL_TRIM, 0x08),
};
static const struct qmp_phy_init_tbl sm8475_usb3_pcs_usb_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V6_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_USB3_RCVR_DTCT_DLY_U3_L, 0x40),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_USB3_RCVR_DTCT_DLY_U3_H, 0x00),
};
static const struct qmp_phy_init_tbl sm8550_usb3_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE1, 0xc0),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE1, 0x01),
@@ -1337,6 +1421,29 @@ static const struct qmp_phy_init_tbl qmp_v5_5nm_dp_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V5_5NM_TX_TX_BAND, 0x01),
};
static const struct qmp_phy_init_tbl qmp_v6_dp_v1_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SVS_MODE_CLK_SEL, 0x15),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0x3b),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYS_CLK_CTRL, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_ENABLE1, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_BUF_ENABLE, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_SELECT, 0x30),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x12),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_BG_TIMER, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CORE_CLK_DIV_MODE0, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_CTRL, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN, 0x17),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0x0f),
};
static const struct qmp_phy_init_tbl qmp_v6_dp_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SVS_MODE_CLK_SEL, 0x15),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0x3b),
@@ -1471,6 +1578,54 @@ static const struct qmp_phy_init_tbl qmp_v8_n3p_dp_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_RESTRIM_POST_CAL_OFFSET, 0x10),
};
static const struct qmp_phy_init_tbl qmp_v6_dp_v1_serdes_tbl_rbr[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x69),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0x80),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x6f),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xe2),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x18),
};
static const struct qmp_phy_init_tbl qmp_v6_dp_v1_serdes_tbl_hbr[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x69),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0x80),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xe2),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x18),
};
static const struct qmp_phy_init_tbl qmp_v6_dp_v1_serdes_tbl_hbr2[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x8c),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x1c),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x2e),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x21),
};
static const struct qmp_phy_init_tbl qmp_v6_dp_v1_serdes_tbl_hbr3[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x69),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0x80),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x2f),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x2a),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xe2),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x18),
};
static const struct qmp_phy_init_tbl qmp_v6_dp_serdes_tbl_rbr[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x34),
@@ -2058,6 +2213,141 @@ static const struct qmp_phy_init_tbl x1e80100_usb43dp_pcs_usb_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V6_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07),
};
static const struct qmp_phy_init_tbl hawi_usb3_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SSC_STEP_SIZE1_MODE1, 0xc0),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SSC_STEP_SIZE2_MODE1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_CP_CTRL_MODE1, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_PLL_RCTRL_MODE1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_PLL_CCTRL_MODE1, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_CORECLK_DIV_MODE1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_LOCK_CMP1_MODE1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_LOCK_CMP2_MODE1, 0x41),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DEC_START_MODE1, 0x41),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DEC_START_MSB_MODE1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DIV_FRAC_START1_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DIV_FRAC_START2_MODE1, 0x75),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DIV_FRAC_START3_MODE1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_HSCLK_SEL_1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_VCO_TUNE1_MODE1, 0x25),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_VCO_TUNE2_MODE1, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0x5c),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x5c),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SSC_STEP_SIZE1_MODE0, 0xc0),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SSC_STEP_SIZE2_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_CP_CTRL_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_PLL_CCTRL_MODE0, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_PLL_CORE_CLK_DIV_MODE0, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_LOCK_CMP1_MODE0, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_LOCK_CMP2_MODE0, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DEC_START_MODE0, 0x41),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DEC_START_MSB_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DIV_FRAC_START1_MODE0, 0x55),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DIV_FRAC_START2_MODE0, 0x75),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DIV_FRAC_START3_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_VCO_TUNE1_MODE0, 0x25),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_VCO_TUNE2_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_BG_TIMER, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SSC_EN_CENTER, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SSC_PER1, 0x62),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SSC_PER2, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SYSCLK_BUF_ENABLE, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SYSCLK_EN_SEL, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_LOCK_CMP_CFG, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_VCO_TUNE_MAP, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_CORE_CLK_EN, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_CMN_CONFIG_1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_AUTO_GAIN_ADJ_CTRL_1, 0xb6),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_AUTO_GAIN_ADJ_CTRL_2, 0x4a),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_AUTO_GAIN_ADJ_CTRL_3, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_ADDITIONAL_MISC, 0x0c),
};
static const struct qmp_phy_init_tbl hawi_usb3_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V10_TX_RES_CODE_LANE_TX, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_TX_RES_CODE_LANE_RX, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_TX_RES_CODE_LANE_OFFSET_TX, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_V10_TX_RES_CODE_LANE_OFFSET_RX, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V10_TX_LANE_MODE_1, 0xe5),
QMP_PHY_INIT_CFG(QSERDES_V10_TX_LANE_MODE_2, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V10_TX_LANE_MODE_3, 0x11),
QMP_PHY_INIT_CFG(QSERDES_V10_TX_LANE_MODE_4, 0x31),
QMP_PHY_INIT_CFG(QSERDES_V10_TX_LANE_MODE_5, 0x5d),
QMP_PHY_INIT_CFG(QSERDES_V10_TX_RCV_DETECT_LVL_2, 0x12),
QMP_PHY_INIT_CFG_LANE(QSERDES_V10_TX_PI_QEC_CTRL, 0x21, 1),
QMP_PHY_INIT_CFG_LANE(QSERDES_V10_TX_PI_QEC_CTRL, 0x05, 2),
};
static const struct qmp_phy_init_tbl hawi_usb3_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V10_RX_UCDR_FO_GAIN, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_UCDR_SO_GAIN, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_UCDR_PI_CONTROLS, 0x99),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_UCDR_SB2_THRESH1, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_UCDR_SB2_THRESH2, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_UCDR_SB2_GAIN1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_UCDR_SB2_GAIN2, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_AUX_DATA_TCOARSE_TFINE, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_VGA_CAL_CNTRL1, 0x54),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_VGA_CAL_CNTRL2, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_GM_CAL, 0x13),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_IDAC_TSETTLE_LOW, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_IDAC_TSETTLE_HIGH, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x27),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_SIGDET_ENABLES, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_SIGDET_CNTRL, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_SIGDET_DEGLITCH_CNTRL, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_00_LOW, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_00_HIGH, 0xbf),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_00_HIGH2, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_00_HIGH3, 0xdf),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_00_HIGH4, 0xed),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_01_LOW, 0x19),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_01_HIGH, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_01_HIGH2, 0x91),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_01_HIGH3, 0xb7),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_01_HIGH4, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_DFE_EN_TIMER, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_DCC_CTRL1, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_VTH_CODE, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_SIGDET_CAL_CTRL1, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_SIGDET_CAL_TRIM, 0x08),
};
static const struct qmp_phy_init_tbl hawi_usb3_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V10_PCS_LOCK_DETECT_CONFIG1, 0xc4),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_LOCK_DETECT_CONFIG2, 0x89),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_LOCK_DETECT_CONFIG3, 0x20),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_LOCK_DETECT_CONFIG6, 0x13),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_REFGEN_REQ_CONFIG1, 0x21),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_RX_SIGDET_LVL, 0x55),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_RX_CONFIG, 0x0a),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_ALIGN_DETECT_CONFIG1, 0x88),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_ALIGN_DETECT_CONFIG2, 0x13),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_PCS_TX_RX_CONFIG, 0x04),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_PCS_TX_RX_CONFIG2, 0x01),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_EQ_CONFIG1, 0x4b),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_EQ_CONFIG5, 0x10),
};
static const struct qmp_phy_init_tbl hawi_usb3_pcs_usb_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V10_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_USB3_RCVR_DTCT_DLY_U3_L, 0x40),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_USB3_RCVR_DTCT_DLY_U3_H, 0x00),
};
/* list of regulators */
static struct regulator_bulk_data qmp_phy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 21800, },
@@ -2108,7 +2398,7 @@ static const u8 qmp_dp_v4_pre_emphasis_hbr3_hbr2[4][4] = {
static const u8 qmp_dp_v4_pre_emphasis_hbr_rbr[4][4] = {
{ 0x00, 0x0d, 0x14, 0x1a },
{ 0x00, 0x0e, 0x15, 0xff },
{ 0x00, 0x0d, 0xff, 0xff },
{ 0x00, 0x0e, 0xff, 0xff },
{ 0x03, 0xff, 0xff, 0xff }
};
@@ -2198,6 +2488,7 @@ struct qmp_combo_offsets {
u16 dp_txa;
u16 dp_txb;
u16 dp_dp_phy;
u16 aon_toggle;
};
struct qmp_phy_cfg {
@@ -2270,6 +2561,7 @@ struct qmp_combo {
const struct qmp_phy_cfg *cfg;
void __iomem *com;
void __iomem *aon_toggle;
void __iomem *serdes;
void __iomem *tx;
@@ -2325,7 +2617,6 @@ static int qmp_v3_calibrate_dp_phy(struct qmp_combo *qmp);
static void qmp_v4_dp_aux_init(struct qmp_combo *qmp);
static void qmp_v4_configure_dp_tx(struct qmp_combo *qmp);
static int qmp_v4_configure_dp_phy(struct qmp_combo *qmp);
static int qmp_v4_calibrate_dp_phy(struct qmp_combo *qmp);
static void qmp_v8_dp_aux_init(struct qmp_combo *qmp);
static int qmp_v8_configure_dp_clocks(struct qmp_combo *qmp);
@@ -2416,6 +2707,24 @@ static const struct qmp_combo_offsets qmp_combo_offsets_v8 = {
.dp_dp_phy = 0x3c00,
};
static const struct qmp_combo_offsets qmp_combo_offsets_v10 = {
.com = 0x0000,
.aon_toggle = 0x0400,
.txa = 0x1400,
.rxa = 0x1600,
.txb = 0x1800,
.rxb = 0x1a00,
.usb3_serdes = 0x1000,
.usb3_pcs_misc = 0x1c00,
.usb3_pcs = 0x1e00,
.usb3_pcs_aon = 0x2000,
.usb3_pcs_usb = 0x2100,
.dp_serdes = 0x3000,
.dp_txa = 0x3400,
.dp_txb = 0x3800,
.dp_dp_phy = 0x3c00,
};
static const struct qmp_combo_offsets qmp_combo_usb43dp_offsets_v8 = {
.com = 0x0000,
.usb3_pcs_aon = 0x0100,
@@ -2466,7 +2775,6 @@ static const struct qmp_phy_cfg sar2130p_usb3dpphy_cfg = {
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
.regs = qmp_v6_usb3phy_regs_layout,
.reset_list = msm8996_usb3phy_reset_l,
@@ -2603,7 +2911,6 @@ static const struct qmp_phy_cfg sc8180x_usb3dpphy_cfg = {
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
.reset_list = msm8996_usb3phy_reset_l,
.num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
@@ -2650,7 +2957,6 @@ static const struct qmp_phy_cfg sc8280xp_usb43dpphy_cfg = {
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
.reset_list = msm8996_usb3phy_reset_l,
.num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
@@ -2696,7 +3002,6 @@ static const struct qmp_phy_cfg x1e80100_usb3dpphy_cfg = {
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
.reset_list = msm8996_usb3phy_reset_l,
.num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
@@ -2705,6 +3010,27 @@ static const struct qmp_phy_cfg x1e80100_usb3dpphy_cfg = {
.regs = qmp_v6_n4_usb3phy_regs_layout,
};
static const struct qmp_phy_cfg hawi_usb3dpphy_cfg = {
.offsets = &qmp_combo_offsets_v10,
.serdes_tbl = hawi_usb3_serdes_tbl,
.serdes_tbl_num = ARRAY_SIZE(hawi_usb3_serdes_tbl),
.tx_tbl = hawi_usb3_tx_tbl,
.tx_tbl_num = ARRAY_SIZE(hawi_usb3_tx_tbl),
.rx_tbl = hawi_usb3_rx_tbl,
.rx_tbl_num = ARRAY_SIZE(hawi_usb3_rx_tbl),
.pcs_tbl = hawi_usb3_pcs_tbl,
.pcs_tbl_num = ARRAY_SIZE(hawi_usb3_pcs_tbl),
.pcs_usb_tbl = hawi_usb3_pcs_usb_tbl,
.pcs_usb_tbl_num = ARRAY_SIZE(hawi_usb3_pcs_usb_tbl),
.regs = qmp_v10_usb3phy_regs_layout,
.reset_list = msm8996_usb3phy_reset_l,
.num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
};
static const struct qmp_phy_cfg sm6350_usb3dpphy_cfg = {
.offsets = &qmp_combo_offsets_v3,
@@ -2785,7 +3111,6 @@ static const struct qmp_phy_cfg sm8250_usb3dpphy_cfg = {
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
.reset_list = msm8996_usb3phy_reset_l,
.num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
@@ -2834,7 +3159,6 @@ static const struct qmp_phy_cfg sm8350_usb3dpphy_cfg = {
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
.reset_list = msm8996_usb3phy_reset_l,
.num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
@@ -2845,6 +3169,51 @@ static const struct qmp_phy_cfg sm8350_usb3dpphy_cfg = {
.has_pwrdn_delay = true,
};
static const struct qmp_phy_cfg sm8475_usb3dpphy_cfg = {
.offsets = &qmp_combo_offsets_v3,
.serdes_tbl = sar2130p_usb3_serdes_tbl,
.serdes_tbl_num = ARRAY_SIZE(sar2130p_usb3_serdes_tbl),
.tx_tbl = sm8550_usb3_tx_tbl,
.tx_tbl_num = ARRAY_SIZE(sm8550_usb3_tx_tbl),
.rx_tbl = sm8475_usb3_rx_tbl,
.rx_tbl_num = ARRAY_SIZE(sm8475_usb3_rx_tbl),
.pcs_tbl = sm8550_usb3_pcs_tbl,
.pcs_tbl_num = ARRAY_SIZE(sm8550_usb3_pcs_tbl),
.pcs_usb_tbl = sm8475_usb3_pcs_usb_tbl,
.pcs_usb_tbl_num = ARRAY_SIZE(sm8475_usb3_pcs_usb_tbl),
.dp_serdes_tbl = qmp_v6_dp_v1_serdes_tbl,
.dp_serdes_tbl_num = ARRAY_SIZE(qmp_v6_dp_v1_serdes_tbl),
.dp_tx_tbl = qmp_v6_dp_tx_tbl,
.dp_tx_tbl_num = ARRAY_SIZE(qmp_v6_dp_tx_tbl),
.serdes_tbl_rbr = qmp_v6_dp_v1_serdes_tbl_rbr,
.serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v6_dp_v1_serdes_tbl_rbr),
.serdes_tbl_hbr = qmp_v6_dp_v1_serdes_tbl_hbr,
.serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v6_dp_v1_serdes_tbl_hbr),
.serdes_tbl_hbr2 = qmp_v6_dp_v1_serdes_tbl_hbr2,
.serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v6_dp_v1_serdes_tbl_hbr2),
.serdes_tbl_hbr3 = qmp_v6_dp_v1_serdes_tbl_hbr3,
.serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v6_dp_v1_serdes_tbl_hbr3),
.swing_hbr_rbr = &qmp_dp_v5_voltage_swing_hbr_rbr,
.pre_emphasis_hbr_rbr = &qmp_dp_v6_pre_emphasis_hbr_rbr,
.swing_hbr3_hbr2 = &qmp_dp_v5_voltage_swing_hbr3_hbr2,
.pre_emphasis_hbr3_hbr2 = &qmp_dp_v5_pre_emphasis_hbr3_hbr2,
.dp_aux_init = qmp_v4_dp_aux_init,
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.regs = qmp_v6_usb3phy_regs_layout,
.reset_list = msm8996_usb3phy_reset_l,
.num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
};
static const struct qmp_phy_cfg sm8550_usb3dpphy_cfg = {
.offsets = &qmp_combo_offsets_v3,
@@ -2882,7 +3251,6 @@ static const struct qmp_phy_cfg sm8550_usb3dpphy_cfg = {
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
.regs = qmp_v6_usb3phy_regs_layout,
.reset_list = msm8996_usb3phy_reset_l,
@@ -2928,7 +3296,6 @@ static const struct qmp_phy_cfg sm8650_usb3dpphy_cfg = {
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
.regs = qmp_v6_usb3phy_regs_layout,
.reset_list = msm8996_usb3phy_reset_l,
@@ -2974,7 +3341,6 @@ static const struct qmp_phy_cfg sm8750_usb3dpphy_cfg = {
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
.regs = qmp_v8_usb3phy_regs_layout,
.reset_list = msm8996_usb3phy_reset_l,
@@ -3020,7 +3386,6 @@ static const struct qmp_phy_cfg glymur_usb3dpphy_cfg = {
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v8_configure_dp_clocks,
.configure_dp_phy = qmp_v8_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
.regs = qmp_v8_n3_usb43dpphy_regs_layout,
.reset_list = msm8996_usb3phy_reset_l,
@@ -3316,7 +3681,6 @@ static void qmp_v4_dp_aux_init(struct qmp_combo *qmp)
writel(0x03, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG7);
writel(0xb7, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG8);
writel(0x03, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG9);
qmp->dp_aux_cfg = 0;
writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
@@ -3345,7 +3709,6 @@ static void qmp_v8_dp_aux_init(struct qmp_combo *qmp)
writel(0x03, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG7);
writel(0xb7, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG8);
writel(0x03, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG9);
qmp->dp_aux_cfg = 0;
writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
@@ -3605,24 +3968,6 @@ static int qmp_v8_configure_dp_phy(struct qmp_combo *qmp)
return 0;
}
/*
* We need to calibrate the aux setting here as many times
* as the caller tries
*/
static int qmp_v4_calibrate_dp_phy(struct qmp_combo *qmp)
{
static const u8 cfg1_settings[] = { 0x20, 0x13, 0x23, 0x1d };
u8 val;
qmp->dp_aux_cfg++;
qmp->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings);
val = cfg1_settings[qmp->dp_aux_cfg];
writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG1);
return 0;
}
static int qmp_combo_dp_configure(struct phy *phy, union phy_configure_opts *opts)
{
const struct phy_configure_opts_dp *dp_opts = &opts->dp;
@@ -3662,13 +4007,18 @@ static int qmp_combo_com_init(struct qmp_combo *qmp, bool force)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
void __iomem *com = qmp->com;
void __iomem *pcs_aon = qmp->pcs_aon;
void __iomem *aon_toggle;
int ret;
u32 val;
if (!force && qmp->init_count++)
return 0;
if (qmp->aon_toggle)
aon_toggle = qmp->aon_toggle;
else
aon_toggle = qmp->pcs_aon;
ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
if (ret) {
dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
@@ -3706,9 +4056,9 @@ static int qmp_combo_com_init(struct qmp_combo *qmp, bool force)
SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
/* override hardware control for reset of qmp phy */
if (pcs_aon && cfg->regs[QPHY_AON_TOGGLE_ENABLE]) {
qphy_clrbits(pcs_aon, cfg->regs[QPHY_AON_TOGGLE_ENABLE], 0x1);
qphy_clrbits(pcs_aon, cfg->regs[QPHY_DP_AON_TOGGLE_ENABLE], 0x1);
if (aon_toggle && cfg->regs[QPHY_AON_TOGGLE_ENABLE]) {
qphy_clrbits(aon_toggle, cfg->regs[QPHY_AON_TOGGLE_ENABLE], 0x1);
qphy_clrbits(aon_toggle, cfg->regs[QPHY_DP_AON_TOGGLE_ENABLE], 0x1);
}
/* Use software based port select and switch on typec orientation */
@@ -4735,6 +5085,9 @@ static int qmp_combo_parse_dt(struct qmp_combo *qmp)
}
qmp->dp_dp_phy = base + offs->dp_dp_phy;
if (offs->aon_toggle)
qmp->aon_toggle = base + offs->aon_toggle;
ret = qmp_combo_clk_init(qmp);
if (ret)
return ret;
@@ -4934,10 +5287,16 @@ static int qmp_combo_probe(struct platform_device *pdev)
if (ret)
goto err_node_put;
/*
* Enable runtime PM before creating the PHYs, phy_create() only enables
* it on the PHY devices if already enabled on the parent. Hold a usage
* reference so callbacks cannot run until the PHY is ready.
*/
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
ret = devm_pm_runtime_enable(dev);
if (ret)
goto err_node_put;
goto err_pm_put;
/*
* Prevent runtime pm from being ON by default. Users can enable
* it using power/control in sysfs.
@@ -4946,14 +5305,13 @@ static int qmp_combo_probe(struct platform_device *pdev)
ret = qmp_combo_register_clocks(qmp, usb_np, dp_np);
if (ret)
goto err_node_put;
goto err_pm_put;
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);
dev_err(dev, "failed to create USB PHY: %d\n", ret);
goto err_node_put;
goto err_pm_put;
}
phy_set_drvdata(qmp->usb_phy, qmp);
@@ -4962,7 +5320,7 @@ static int qmp_combo_probe(struct platform_device *pdev)
if (IS_ERR(qmp->dp_phy)) {
ret = PTR_ERR(qmp->dp_phy);
dev_err(dev, "failed to create DP PHY: %d\n", ret);
goto err_node_put;
goto err_pm_put;
}
phy_set_drvdata(qmp->dp_phy, qmp);
@@ -4972,11 +5330,20 @@ static int qmp_combo_probe(struct platform_device *pdev)
else
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(phy_provider)) {
ret = PTR_ERR(phy_provider);
goto err_pm_put;
}
of_node_put(usb_np);
of_node_put(dp_np);
return PTR_ERR_OR_ZERO(phy_provider);
pm_runtime_put(dev);
return 0;
err_pm_put:
pm_runtime_put_noidle(dev);
err_node_put:
of_node_put(usb_np);
of_node_put(dp_np);
@@ -4988,6 +5355,10 @@ static const struct of_device_id qmp_combo_of_match_table[] = {
.compatible = "qcom,glymur-qmp-usb3-dp-phy",
.data = &glymur_usb3dpphy_cfg,
},
{
.compatible = "qcom,hawi-qmp-usb3-dp-phy",
.data = &hawi_usb3dpphy_cfg,
},
{
.compatible = "qcom,sar2130p-qmp-usb3-dp-phy",
.data = &sar2130p_usb3dpphy_cfg,
@@ -5032,6 +5403,10 @@ static const struct of_device_id qmp_combo_of_match_table[] = {
.compatible = "qcom,sm8450-qmp-usb3-dp-phy",
.data = &sm8350_usb3dpphy_cfg,
},
{
.compatible = "qcom,sm8475-qmp-usb3-dp-phy",
.data = &sm8475_usb3dpphy_cfg,
},
{
.compatible = "qcom,sm8550-qmp-usb3-dp-phy",
.data = &sm8550_usb3dpphy_cfg,

View File

@@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2026, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_DP_PHY_V10_H_
#define QCOM_PHY_QMP_DP_PHY_V10_H_
/* Only for QMP V10 PHY - DP PHY registers */
#define QSERDES_V10_DP_PHY_VCO_DIV 0x070
#define QSERDES_V10_DP_PHY_AUX_INTERRUPT_STATUS 0x0e0
#define QSERDES_V10_DP_PHY_STATUS 0x0e4
#endif

View File

@@ -1,52 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2025 Linaro Ltd.
*/
#ifndef QCOM_PHY_QMP_DP_QSERDES_COM_V8_H_
#define QCOM_PHY_QMP_DP_QSERDES_COM_V8_H_
/* Only for DP QMP V8 PHY - QSERDES COM registers */
#define DP_QSERDES_V8_COM_HSCLK_SEL_1 0x03c
#define DP_QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE0 0x058
#define DP_QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE0 0x05c
#define DP_QSERDES_V8_COM_SSC_STEP_SIZE1_MODE0 0x060
#define DP_QSERDES_V8_COM_SSC_STEP_SIZE2_MODE0 0x064
#define DP_QSERDES_V8_COM_CP_CTRL_MODE0 0x070
#define DP_QSERDES_V8_COM_PLL_RCTRL_MODE0 0x074
#define DP_QSERDES_V8_COM_PLL_CCTRL_MODE0 0x078
#define DP_QSERDES_V8_COM_CORECLK_DIV_MODE0 0x07c
#define DP_QSERDES_V8_COM_LOCK_CMP1_MODE0 0x080
#define DP_QSERDES_V8_COM_LOCK_CMP2_MODE0 0x084
#define DP_QSERDES_V8_COM_DEC_START_MODE0 0x088
#define DP_QSERDES_V8_COM_DIV_FRAC_START1_MODE0 0x090
#define DP_QSERDES_V8_COM_DIV_FRAC_START2_MODE0 0x094
#define DP_QSERDES_V8_COM_DIV_FRAC_START3_MODE0 0x098
#define DP_QSERDES_V8_COM_INTEGLOOP_GAIN0_MODE0 0x0a0
#define DP_QSERDES_V8_COM_VCO_TUNE1_MODE0 0x0a8
#define DP_QSERDES_V8_COM_INTEGLOOP_GAIN1_MODE0 0x0a4
#define DP_QSERDES_V8_COM_VCO_TUNE2_MODE0 0x0ac
#define DP_QSERDES_V8_COM_BG_TIMER 0x0bc
#define DP_QSERDES_V8_COM_SSC_EN_CENTER 0x0c0
#define DP_QSERDES_V8_COM_SSC_ADJ_PER1 0x0c4
#define DP_QSERDES_V8_COM_SSC_PER1 0x0cc
#define DP_QSERDES_V8_COM_SSC_PER2 0x0d0
#define DP_QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN 0x0dc
#define DP_QSERDES_V8_COM_CLK_ENABLE1 0x0e0
#define DP_QSERDES_V8_COM_SYS_CLK_CTRL 0x0e4
#define DP_QSERDES_V8_COM_SYSCLK_BUF_ENABLE 0x0e8
#define DP_QSERDES_V8_COM_PLL_IVCO 0x0f4
#define DP_QSERDES_V8_COM_SYSCLK_EN_SEL 0x110
#define DP_QSERDES_V8_COM_RESETSM_CNTRL 0x118
#define DP_QSERDES_V8_COM_LOCK_CMP_EN 0x120
#define DP_QSERDES_V8_COM_VCO_TUNE_CTRL 0x13c
#define DP_QSERDES_V8_COM_VCO_TUNE_MAP 0x140
#define DP_QSERDES_V8_COM_CLK_SELECT 0x164
#define DP_QSERDES_V8_COM_CORE_CLK_EN 0x170
#define DP_QSERDES_V8_COM_CMN_CONFIG_1 0x174
#define DP_QSERDES_V8_COM_SVS_MODE_CLK_SEL 0x180
#define DP_QSERDES_V8_COM_CLK_FWD_CONFIG_1 0x2f4
#define DP_QSERDES_V8_COM_CMN_STATUS 0x314
#define DP_QSERDES_V8_COM_C_READY_STATUS 0x33c
#endif

View File

@@ -0,0 +1,743 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
#include <linux/slab.h>
#include "phy-qcom-qmp.h"
#define PHY_INIT_COMPLETE_TIMEOUT_US 10000
enum qmp_pcie_glymur_link_mode {
QMP_PCIE_GLYMUR_MODE_X8,
QMP_PCIE_GLYMUR_MODE_X4X4,
};
enum qphy_reg_layout {
QPHY_PCS_STATUS,
QPHY_LAYOUT_SIZE
};
static const unsigned int pciephy_v8_50_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_STATUS] = QPHY_V8_50_PCS_STATUS1,
};
struct qmp_pcie_offsets {
u16 pcs;
};
struct qmp_phy_cfg {
const struct qmp_pcie_offsets *offsets;
const char * const *reg_names;
int num_regs;
const char * const *pd_names;
int num_pds;
const char * const *nocsr_reset_list;
int num_nocsr_resets;
const char * const *vreg_list;
int num_vregs;
const unsigned int *regs;
unsigned int phy_status;
const char * const *clk_list;
int num_clks;
const char * const *pipe_clk_list;
int num_pipe_clks;
};
struct qmp_pcie {
struct device *dev;
const struct qmp_phy_cfg *cfg;
void __iomem **base;
struct clk_bulk_data *clks;
struct clk_bulk_data *pipe_clks;
struct reset_control_bulk_data *nocsr_resets;
struct regulator_bulk_data *vregs;
struct device **pd_devs;
};
struct qmp_pcie_multiphy {
struct phy **phys;
const struct qmp_pcie_link_mode_cfg *mode_cfg;
int num_pipe_outputs;
struct clk_fixed_rate *pipe_out_clks;
};
struct qmp_pcie_link_mode_cfg {
const struct qmp_phy_cfg * const *cfgs;
u32 num_phys;
};
struct qmp_pcie_match_data {
const struct qmp_pcie_link_mode_cfg *mode_cfgs;
u32 num_modes;
};
static const char * const glymur_pciephy_clk_l[] = {
"aux", "cfg_ahb", "ref", "rchng", "phy_b_aux",
};
static const char * const glymur_pciephy_a_clk_l[] = {
"aux", "cfg_ahb", "ref", "rchng",
};
static const char * const glymur_pciephy_b_clk_l[] = {
"phy_b_aux", "cfg_ahb_b", "ref", "rchng_b",
};
static const char * const glymur_pciephy_pipeclk_l[] = {
"pipe",
};
static const char * const glymur_pipephy_b_pipeclk_l[] = {
"pipe_b", "pipediv2_b",
};
static const char * const glymur_vreg_l[] = {
"vdda-phy", "vdda-pll", "vdda-refgen0p9", "vdda-refgen1p2",
};
static const char * const glymur_pciephy_a_reg_l[] = {
"port_a",
};
static const char * const glymur_pciephy_b_reg_l[] = {
"port_b",
};
static const char * const glymur_pciephy_reg_l[] = {
"port_a", "port_b",
};
static const char * const glymur_pciephy_a_pd_l[] = {
"port_a",
};
static const char * const glymur_pciephy_b_pd_l[] = {
"port_b",
};
static const char * const glymur_pciephy_pd_l[] = {
"port_a", "port_b",
};
static const char * const glymur_pciephy_a_nocsr_reset_l[] = {
"port_a_nocsr",
};
static const char * const glymur_pciephy_nocsr_reset_l[] = {
"port_a_nocsr", "port_b_nocsr",
};
static const char * const glymur_pciephy_b_nocsr_reset_l[] = {
"port_b_nocsr",
};
static const struct qmp_pcie_offsets glymur_pcie_offsets_v8_50 = {
.pcs = 0x9000,
};
static const struct qmp_phy_cfg glymur_qmp_gen5x4_pciephy_a_cfg = {
.offsets = &glymur_pcie_offsets_v8_50,
.reg_names = glymur_pciephy_a_reg_l,
.num_regs = ARRAY_SIZE(glymur_pciephy_a_reg_l),
.pd_names = glymur_pciephy_a_pd_l,
.num_pds = ARRAY_SIZE(glymur_pciephy_a_pd_l),
.nocsr_reset_list = glymur_pciephy_a_nocsr_reset_l,
.num_nocsr_resets = ARRAY_SIZE(glymur_pciephy_a_nocsr_reset_l),
.vreg_list = glymur_vreg_l,
.num_vregs = ARRAY_SIZE(glymur_vreg_l),
.regs = pciephy_v8_50_regs_layout,
.phy_status = PHYSTATUS_4_20,
.pipe_clk_list = glymur_pciephy_pipeclk_l,
.num_pipe_clks = ARRAY_SIZE(glymur_pciephy_pipeclk_l),
.clk_list = glymur_pciephy_a_clk_l,
.num_clks = ARRAY_SIZE(glymur_pciephy_a_clk_l),
};
static const struct qmp_phy_cfg glymur_qmp_gen5x4_pciephy_b_cfg = {
.offsets = &glymur_pcie_offsets_v8_50,
.reg_names = glymur_pciephy_b_reg_l,
.num_regs = ARRAY_SIZE(glymur_pciephy_b_reg_l),
.pd_names = glymur_pciephy_b_pd_l,
.num_pds = ARRAY_SIZE(glymur_pciephy_b_pd_l),
.nocsr_reset_list = glymur_pciephy_b_nocsr_reset_l,
.num_nocsr_resets = ARRAY_SIZE(glymur_pciephy_b_nocsr_reset_l),
.vreg_list = glymur_vreg_l,
.num_vregs = ARRAY_SIZE(glymur_vreg_l),
.regs = pciephy_v8_50_regs_layout,
.phy_status = PHYSTATUS_4_20,
.pipe_clk_list = glymur_pipephy_b_pipeclk_l,
.num_pipe_clks = ARRAY_SIZE(glymur_pipephy_b_pipeclk_l),
.clk_list = glymur_pciephy_b_clk_l,
.num_clks = ARRAY_SIZE(glymur_pciephy_b_clk_l),
};
static const struct qmp_phy_cfg glymur_qmp_gen5x8_pciephy_cfg = {
.offsets = &glymur_pcie_offsets_v8_50,
.reg_names = glymur_pciephy_reg_l,
.num_regs = ARRAY_SIZE(glymur_pciephy_reg_l),
.pd_names = glymur_pciephy_pd_l,
.num_pds = ARRAY_SIZE(glymur_pciephy_pd_l),
.nocsr_reset_list = glymur_pciephy_nocsr_reset_l,
.num_nocsr_resets = ARRAY_SIZE(glymur_pciephy_nocsr_reset_l),
.vreg_list = glymur_vreg_l,
.num_vregs = ARRAY_SIZE(glymur_vreg_l),
.regs = pciephy_v8_50_regs_layout,
.phy_status = PHYSTATUS_4_20,
.pipe_clk_list = glymur_pciephy_pipeclk_l,
.num_pipe_clks = ARRAY_SIZE(glymur_pciephy_pipeclk_l),
.clk_list = glymur_pciephy_clk_l,
.num_clks = ARRAY_SIZE(glymur_pciephy_clk_l),
};
static const struct qmp_phy_cfg * const glymur_qmp_gen5x8_mode_x8_cfgs[] = {
&glymur_qmp_gen5x8_pciephy_cfg,
};
static const struct qmp_phy_cfg * const glymur_qmp_gen5x8_mode_x4x4_cfgs[] = {
&glymur_qmp_gen5x4_pciephy_a_cfg,
&glymur_qmp_gen5x4_pciephy_b_cfg,
};
static const struct qmp_pcie_link_mode_cfg glymur_qmp_gen5x8_mode_cfgs[] = {
[QMP_PCIE_GLYMUR_MODE_X8] = {
.cfgs = glymur_qmp_gen5x8_mode_x8_cfgs,
.num_phys = ARRAY_SIZE(glymur_qmp_gen5x8_mode_x8_cfgs),
},
[QMP_PCIE_GLYMUR_MODE_X4X4] = {
.cfgs = glymur_qmp_gen5x8_mode_x4x4_cfgs,
.num_phys = ARRAY_SIZE(glymur_qmp_gen5x8_mode_x4x4_cfgs),
},
};
static const struct qmp_pcie_match_data glymur_qmp_gen5x8_match_data = {
.mode_cfgs = glymur_qmp_gen5x8_mode_cfgs,
.num_modes = ARRAY_SIZE(glymur_qmp_gen5x8_mode_cfgs),
};
static int qmp_pcie_pd_power_on(struct qmp_pcie *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
int i, ret;
for (i = 0; i < cfg->num_pds; i++) {
ret = pm_runtime_resume_and_get(qmp->pd_devs[i]);
if (ret < 0) {
dev_err(qmp->dev, "failed to power on %s domain: %d\n",
cfg->pd_names[i], ret);
goto err_power_off;
}
}
return 0;
err_power_off:
while (--i >= 0)
pm_runtime_put(qmp->pd_devs[i]);
return ret;
}
static void qmp_pcie_pd_power_off(struct qmp_pcie *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
int i;
for (i = cfg->num_pds - 1; i >= 0; i--)
pm_runtime_put(qmp->pd_devs[i]);
}
static int qmp_pcie_init(struct phy *phy)
{
struct qmp_pcie *qmp = phy_get_drvdata(phy);
const struct qmp_phy_cfg *cfg = qmp->cfg;
int ret;
ret = qmp_pcie_pd_power_on(qmp);
if (ret)
return ret;
ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
if (ret) {
dev_err(qmp->dev, "failed to enable regulators: %d\n", ret);
goto err_pd_power_off;
}
ret = reset_control_bulk_assert(qmp->cfg->num_nocsr_resets, qmp->nocsr_resets);
if (ret) {
dev_err(qmp->dev, "no-csr reset assert failed: %d\n", ret);
goto err_disable_regulators;
}
usleep_range(200, 300);
ret = clk_bulk_prepare_enable(qmp->cfg->num_clks, qmp->clks);
if (ret)
goto err_disable_regulators;
return 0;
err_disable_regulators:
regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
err_pd_power_off:
qmp_pcie_pd_power_off(qmp);
return ret;
}
static int qmp_pcie_exit(struct phy *phy)
{
struct qmp_pcie *qmp = phy_get_drvdata(phy);
const struct qmp_phy_cfg *cfg = qmp->cfg;
reset_control_bulk_assert(qmp->cfg->num_nocsr_resets, qmp->nocsr_resets);
clk_bulk_disable_unprepare(qmp->cfg->num_clks, qmp->clks);
regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
qmp_pcie_pd_power_off(qmp);
return 0;
}
static int qmp_pcie_power_on(struct phy *phy)
{
struct qmp_pcie *qmp = phy_get_drvdata(phy);
const struct qmp_phy_cfg *cfg = qmp->cfg;
const struct qmp_pcie_offsets *offs = cfg->offsets;
void __iomem *status;
unsigned int val;
int i, ret;
ret = clk_bulk_prepare_enable(qmp->cfg->num_pipe_clks, qmp->pipe_clks);
if (ret)
return ret;
ret = reset_control_bulk_deassert(qmp->cfg->num_nocsr_resets, qmp->nocsr_resets);
if (ret) {
dev_err(qmp->dev, "no-csr reset deassert failed: %d\n", ret);
goto err_disable_pipe_clk;
}
for (i = 0; i < cfg->num_regs; i++) {
status = qmp->base[i] + offs->pcs + cfg->regs[QPHY_PCS_STATUS];
ret = readl_poll_timeout(status, val, !(val & cfg->phy_status), 200,
PHY_INIT_COMPLETE_TIMEOUT_US);
if (ret) {
dev_err(qmp->dev, "PHY power on timed-out (%s): %d\n",
cfg->reg_names[i], ret);
goto err_disable_pipe_clk;
}
}
return 0;
err_disable_pipe_clk:
clk_bulk_disable_unprepare(qmp->cfg->num_pipe_clks, qmp->pipe_clks);
return ret;
}
static int qmp_pcie_power_off(struct phy *phy)
{
struct qmp_pcie *qmp = phy_get_drvdata(phy);
clk_bulk_disable_unprepare(qmp->cfg->num_pipe_clks, qmp->pipe_clks);
return 0;
}
static int qmp_pcie_enable(struct phy *phy)
{
int ret;
ret = qmp_pcie_init(phy);
if (ret)
return ret;
ret = qmp_pcie_power_on(phy);
if (ret)
qmp_pcie_exit(phy);
return ret;
}
static int qmp_pcie_disable(struct phy *phy)
{
int ret;
ret = qmp_pcie_power_off(phy);
if (ret)
return ret;
return qmp_pcie_exit(phy);
}
static const struct phy_ops qmp_pcie_phy_ops = {
.power_on = qmp_pcie_enable,
.power_off = qmp_pcie_disable,
.owner = THIS_MODULE,
};
static void qmp_pcie_pd_detach(void *data)
{
struct qmp_pcie *qmp = data;
const struct qmp_phy_cfg *cfg = qmp->cfg;
int i;
for (i = 0; i < cfg->num_pds; i++) {
if (!IS_ERR_OR_NULL(qmp->pd_devs[i]))
dev_pm_domain_detach(qmp->pd_devs[i], true);
}
}
static int qmp_pcie_pd_init(struct qmp_pcie *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
struct device *dev = qmp->dev;
int i, ret;
if (!cfg->num_pds)
return 0;
qmp->pd_devs = devm_kcalloc(dev, cfg->num_pds, sizeof(*qmp->pd_devs),
GFP_KERNEL);
if (!qmp->pd_devs)
return -ENOMEM;
for (i = 0; i < cfg->num_pds; i++) {
qmp->pd_devs[i] = dev_pm_domain_attach_by_name(dev,
cfg->pd_names[i]);
if (IS_ERR_OR_NULL(qmp->pd_devs[i])) {
ret = PTR_ERR(qmp->pd_devs[i]) ? : -ENODATA;
goto err_detach;
}
}
return devm_add_action_or_reset(dev, qmp_pcie_pd_detach, qmp);
err_detach:
while (--i >= 0)
dev_pm_domain_detach(qmp->pd_devs[i], false);
return ret;
}
static int qmp_pcie_vreg_init(struct qmp_pcie *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
struct device *dev = qmp->dev;
int i;
qmp->vregs = devm_kcalloc(dev, cfg->num_vregs, sizeof(*qmp->vregs),
GFP_KERNEL);
if (!qmp->vregs)
return -ENOMEM;
for (i = 0; i < cfg->num_vregs; i++)
qmp->vregs[i].supply = cfg->vreg_list[i];
return devm_regulator_bulk_get(dev, cfg->num_vregs, qmp->vregs);
}
static int qmp_pcie_reset_init(struct qmp_pcie *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
struct device *dev = qmp->dev;
int i, ret;
qmp->nocsr_resets = devm_kcalloc(dev, cfg->num_nocsr_resets,
sizeof(*qmp->nocsr_resets),
GFP_KERNEL);
if (!qmp->nocsr_resets)
return -ENOMEM;
for (i = 0; i < cfg->num_nocsr_resets; i++)
qmp->nocsr_resets[i].id = cfg->nocsr_reset_list[i];
ret = devm_reset_control_bulk_get_exclusive(dev,
cfg->num_nocsr_resets,
qmp->nocsr_resets);
if (ret)
return dev_err_probe(dev, ret, "failed to get no-csr resets\n");
return 0;
}
static int qmp_pcie_clk_init(struct qmp_pcie *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
struct device *dev = qmp->dev;
int i, ret;
qmp->clks = devm_kcalloc(dev, cfg->num_clks, sizeof(*qmp->clks),
GFP_KERNEL);
if (!qmp->clks)
return -ENOMEM;
for (i = 0; i < cfg->num_clks; i++)
qmp->clks[i].id = cfg->clk_list[i];
ret = devm_clk_bulk_get_optional(dev, cfg->num_clks, qmp->clks);
if (ret)
return ret;
qmp->pipe_clks = devm_kcalloc(dev, cfg->num_pipe_clks,
sizeof(*qmp->pipe_clks), GFP_KERNEL);
if (!qmp->pipe_clks)
return -ENOMEM;
for (i = 0; i < cfg->num_pipe_clks; i++)
qmp->pipe_clks[i].id = cfg->pipe_clk_list[i];
return devm_clk_bulk_get_optional(dev, cfg->num_pipe_clks,
qmp->pipe_clks);
}
static int __phy_pipe_clk_register(struct device *dev, struct device_node *np,
int idx, struct clk_fixed_rate *fixed)
{
struct clk_init_data init = { };
int ret;
ret = of_property_read_string_index(np, "clock-output-names", idx,
&init.name);
if (ret) {
dev_err(dev, "%pOFn: No clock-output-names\n", np);
return ret;
}
init.ops = &clk_fixed_rate_ops;
fixed->fixed_rate = 125000000;
fixed->hw.init = &init;
return devm_clk_hw_register(dev, &fixed->hw);
}
static struct clk_hw *
qmp_pcie_multiphy_clk_hw_get(struct of_phandle_args *clkspec, void *data)
{
struct qmp_pcie_multiphy *qmp_data = data;
unsigned int idx = 0;
if (clkspec->args_count)
idx = clkspec->args[0];
if (idx < (unsigned int)qmp_data->num_pipe_outputs)
return &qmp_data->pipe_out_clks[idx].hw;
return ERR_PTR(-EINVAL);
}
static int qmp_pcie_multiphy_register_clocks(struct device *dev,
struct device_node *np,
struct qmp_pcie_multiphy *qmp_data)
{
int num_pipe_outputs;
int i, ret;
num_pipe_outputs = of_property_count_strings(np, "clock-output-names");
qmp_data->num_pipe_outputs = num_pipe_outputs;
qmp_data->pipe_out_clks = devm_kcalloc(dev, num_pipe_outputs,
sizeof(*qmp_data->pipe_out_clks),
GFP_KERNEL);
if (!qmp_data->pipe_out_clks)
return -ENOMEM;
for (i = 0; i < num_pipe_outputs; i++) {
ret = __phy_pipe_clk_register(dev, np, i,
&qmp_data->pipe_out_clks[i]);
if (ret)
return ret;
}
return devm_of_clk_add_hw_provider(dev, qmp_pcie_multiphy_clk_hw_get, qmp_data);
}
static int qmp_pcie_get_mmio(struct qmp_pcie *qmp)
{
struct platform_device *pdev = to_platform_device(qmp->dev);
const struct qmp_phy_cfg *cfg = qmp->cfg;
struct device *dev = qmp->dev;
void __iomem *base;
int i;
qmp->base = devm_kcalloc(dev, cfg->num_regs, sizeof(*qmp->base),
GFP_KERNEL);
if (!qmp->base)
return -ENOMEM;
for (i = 0; i < cfg->num_regs; i++) {
base = devm_platform_ioremap_resource_byname(pdev, cfg->reg_names[i]);
if (IS_ERR(base))
return PTR_ERR(base);
qmp->base[i] = base;
}
return 0;
}
static int qmp_pcie_read_link_mode(struct device *dev, unsigned int *link_mode)
{
struct regmap *map;
unsigned int args[1];
map = syscon_regmap_lookup_by_phandle_args(dev->of_node, "qcom,link-mode",
ARRAY_SIZE(args), args);
if (IS_ERR(map))
return PTR_ERR(map);
return regmap_read(map, args[0], link_mode);
}
static struct phy *qmp_pcie_multiphy_xlate(struct device *dev,
const struct of_phandle_args *args)
{
struct qmp_pcie_multiphy *qmp_data = dev_get_drvdata(dev);
unsigned int idx;
if (!qmp_data || args->args_count < 1)
return ERR_PTR(-EINVAL);
idx = args->args[0];
if (idx < (unsigned int)qmp_data->mode_cfg->num_phys)
return qmp_data->phys[idx] ?: ERR_PTR(-EINVAL);
return ERR_PTR(-EINVAL);
}
static int qmp_pcie_probe_phy(struct qmp_pcie *qmp, struct device_node *np,
struct phy **out_phy)
{
int ret;
ret = qmp_pcie_get_mmio(qmp);
if (ret)
return ret;
ret = qmp_pcie_clk_init(qmp);
if (ret)
return ret;
ret = qmp_pcie_reset_init(qmp);
if (ret)
return ret;
ret = qmp_pcie_vreg_init(qmp);
if (ret)
return ret;
ret = qmp_pcie_pd_init(qmp);
if (ret)
return ret;
*out_phy = devm_phy_create(qmp->dev, np, &qmp_pcie_phy_ops);
if (IS_ERR(*out_phy))
return PTR_ERR(*out_phy);
phy_set_drvdata(*out_phy, qmp);
return 0;
}
static int qmp_pcie_multiphy_probe(struct platform_device *pdev)
{
const struct qmp_pcie_match_data *match_data;
struct qmp_pcie_multiphy *qmp_data;
struct phy_provider *phy_provider;
struct device *dev = &pdev->dev;
unsigned int link_mode;
struct qmp_pcie *qmp;
struct phy **phys;
int phy_index;
int ret;
qmp_data = devm_kzalloc(dev, sizeof(*qmp_data), GFP_KERNEL);
match_data = of_device_get_match_data(dev);
if (!match_data)
return -EINVAL;
if (!qmp_data)
return -ENOMEM;
ret = qmp_pcie_read_link_mode(dev, &link_mode);
if (ret)
return dev_err_probe(dev, ret, "failed to read qcom,link-mode\n");
if (link_mode >= match_data->num_modes)
return dev_err_probe(dev, -EINVAL, "invalid qcom,link-mode: %u\n",
link_mode);
qmp_data->mode_cfg = &match_data->mode_cfgs[link_mode];
qmp = devm_kcalloc(dev, qmp_data->mode_cfg->num_phys, sizeof(*qmp), GFP_KERNEL);
if (!qmp)
return -ENOMEM;
phys = devm_kcalloc(dev, qmp_data->mode_cfg->num_phys, sizeof(*phys), GFP_KERNEL);
if (!phys)
return -ENOMEM;
qmp_data->phys = phys;
dev_set_drvdata(dev, qmp_data);
for (phy_index = 0; phy_index < qmp_data->mode_cfg->num_phys; phy_index++) {
qmp[phy_index].dev = dev;
qmp[phy_index].cfg = qmp_data->mode_cfg->cfgs[phy_index];
ret = qmp_pcie_probe_phy(&qmp[phy_index], dev->of_node, &phys[phy_index]);
if (ret)
return ret;
}
ret = qmp_pcie_multiphy_register_clocks(dev, dev->of_node, qmp_data);
if (ret)
return ret;
phy_provider = devm_of_phy_provider_register(dev, qmp_pcie_multiphy_xlate);
return PTR_ERR_OR_ZERO(phy_provider);
}
static const struct of_device_id qmp_pcie_multiphy_of_match_table[] = {
{
.compatible = "qcom,glymur-qmp-gen5x8-pcie-phy",
.data = &glymur_qmp_gen5x8_match_data,
},
{ }
};
MODULE_DEVICE_TABLE(of, qmp_pcie_multiphy_of_match_table);
static struct platform_driver qmp_pcie_multiphy_driver = {
.probe = qmp_pcie_multiphy_probe,
.driver = {
.name = "qcom-qmp-pcie-multiphy",
.of_match_table = qmp_pcie_multiphy_of_match_table,
},
};
module_platform_driver(qmp_pcie_multiphy_driver);
MODULE_AUTHOR("Qiang Yu <qiang.yu@oss.qualcomm.com>");
MODULE_DESCRIPTION("Qualcomm QMP PCIe Multi-PHY driver for Glymur");
MODULE_LICENSE("GPL");

View File

@@ -40,6 +40,8 @@
#include "phy-qcom-qmp-qserdes-com-v8.h"
#include "phy-qcom-qmp-pcs-pcie-v8.h"
#include "phy-qcom-qmp-qserdes-txrx-pcie-v8.h"
#include "phy-qcom-qmp-pcs-pcie-v10.h"
#include "phy-qcom-qmp-pcs-pcie-v10_60.h"
#define PHY_INIT_COMPLETE_TIMEOUT 10000
@@ -116,6 +118,20 @@ static const unsigned int pciephy_v8_50_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V8_50_PCS_POWER_DOWN_CONTROL,
};
static const unsigned int pciephy_v10_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_SW_RESET] = QPHY_V10_PCS_SW_RESET,
[QPHY_START_CTRL] = QPHY_V10_PCS_START_CONTROL,
[QPHY_PCS_STATUS] = QPHY_V10_PCS_PCS_STATUS1,
[QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V10_PCS_POWER_DOWN_CONTROL,
};
static const unsigned int pciephy_v10_60_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_SW_RESET] = QPHY_V10_60_PCS_SW_RESET,
[QPHY_START_CTRL] = QPHY_V10_60_PCS_START_CONTROL,
[QPHY_PCS_STATUS] = QPHY_V10_60_PCS_PCS_STATUS1,
[QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V10_60_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),
@@ -620,6 +636,89 @@ static const struct qmp_phy_init_tbl ipq8074_pcie_gen3_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
};
static const struct qmp_phy_init_tbl ipq5210_gen3x1_pcie_ep_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TIMER, 0x02),
QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CLKBUFLR_EN, 0x18),
QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_BUF_ENABLE, 0x07),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_IVCO, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE0, 0xff),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE0, 0x04),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE1, 0xff),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE1, 0x09),
QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TRIM, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE0, 0x23),
QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE1, 0x23),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE0, 0x10),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE1, 0x10),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CTRL_BY_PSM, 0x01),
QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_EN_SEL, 0x00),
QMP_PHY_INIT_CFG(QSERDES_PLL_RESETSM_CNTRL, 0x20),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP_EN, 0x42),
QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE0, 0x19),
QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE1, 0x14),
QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE0, 0xfe),
QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN1_MODE0, 0x03),
QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE1, 0xfe),
QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN1_MODE1, 0x03),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE0, 0x24),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE1, 0xb4),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE1, 0x03),
QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x01),
QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x00),
QMP_PHY_INIT_CFG(QSERDES_PLL_CMN_CONFIG, 0x06),
QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05),
QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV_MODE1, 0x08),
QMP_PHY_INIT_CFG(QSERDES_PLL_SYS_CLK_CTRL, 0x07),
QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_EN_SEL, 0x10),
};
static const struct qmp_phy_init_tbl ipq5210_gen3x1_pcie_ep_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x61),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1e),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x73),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xf0),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x2f),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0xd3),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x40),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xc8),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb1),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xc8),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0xb1),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04),
};
static const struct qmp_phy_init_tbl ipq5210_gen3x1_pcie_ep_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG2, 0x04),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG4, 0x07),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_EQ_CONFIG1, 0x11),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_CONFIG1, 0x02),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_CONFIG4, 0xff),
};
static const struct qmp_phy_init_tbl ipq9574_gen3x1_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CLKBUFLR_EN, 0x18),
QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CTRL_BY_PSM, 0x01),
@@ -857,6 +956,152 @@ static const struct qmp_phy_init_tbl ipq9574_gen3x2_pcie_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
};
static const struct qmp_phy_init_tbl ipq9650_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CTRL_BY_PSM, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_MODE, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x42),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_RESETSM_CNTRL, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_TIMER1, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_TIMER2, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x68),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0xab),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0xd4),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SVS_MODE_CLK_SEL, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x0b),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x90),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x53),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x29),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE1, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0xb4),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SVS_MODE_CLK_SEL, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORE_CLK_EN, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x7d),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xa2),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x13),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xb5),
};
static const struct qmp_phy_init_tbl ipq9650_pcie_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12),
QMP_PHY_INIT_CFG(QSERDES_V4_TX_HIGHZ_DRVR_EN, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xb5),
QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x00),
};
static const struct qmp_phy_init_tbl ipq9650_pcie_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0x30),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x11),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x1c),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x1e),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_VGA_GAIN2_LSB, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_VGA_GAIN2_MSB, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_TX_ADAPT_PRE_THRESH1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_TX_ADAPT_PRE_THRESH2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_TX_ADAPT_POST_THRESH, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_TX_ADAPT_MAIN_THRESH, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xd4),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x54),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xdb),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x3b),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0x31),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x24),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xe4),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xec),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x3b),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x67),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x3a),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0),
};
static const struct qmp_phy_init_tbl ipq9650_pcie_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x25),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_G12S1_TXDEEMPH_M3P5DB, 0x10),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_RATE_SLEW_CNTRL1, 0x03),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG2, 0x0f),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_DCC_CAL_CONFIG, 0x00),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0x77),
};
static const struct qmp_phy_init_tbl ipq9650_pcie_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG2, 0x0d),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG4, 0x07),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_EQ_CONFIG1, 0x1c),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_EQ_CONFIG2, 0x0b),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P2_P3_POST, 0x34),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P6_P7_PRE, 0x33),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P6_P7_POST, 0x40),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58),
};
static const struct qmp_phy_init_tbl qcs615_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CLKBUFLR_EN, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_ENABLE1, 0x10),
@@ -2454,6 +2699,82 @@ static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_ep_pcs_misc_tbl[] =
QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_OSC_DTCT_MODE2_CONFIG5, 0x08),
};
static const struct qmp_phy_init_tbl sm8475_qmp_gen3x1_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x31),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER2, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE1, 0x4c),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE1, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_ENABLE1, 0x90),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYS_CLK_CTRL, 0x82),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_BG_TIMER, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x42),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x34),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x82),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x68),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE0, 0xab),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0xea),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE1, 0xab),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE1, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE1, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_SELECT, 0x34),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORECLK_DIV_MODE1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_ADDITIONAL_MISC_3, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0xa0),
};
static const struct qmp_phy_init_tbl sm8475_qmp_gen3x1_pcie_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_GM_CAL, 0x11),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH, 0xbf),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH2, 0xbf),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH3, 0xb7),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH4, 0xea),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_LOW, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH, 0x5c),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH2, 0x9c),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH3, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH4, 0x89),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_LOW, 0xdc),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH, 0x94),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH2, 0x5b),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH3, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH4, 0x89),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_TX_ADAPT_POST_THRESH, 0xf0),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_FO_GAIN, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SO_GAIN, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SB2_THRESH1, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SB2_THRESH2, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_VGA_CAL_CNTRL2, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_SIDGET_ENABLES, 0x1c),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_IDAC_TSETTLE_LOW, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_SIGDET_CAL_TRIM, 0x08),
};
static const struct qmp_phy_init_tbl sm8475_qmp_gen3x1_pcie_pcs_misc_tbl[] = {
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 sm8550_qmp_gen3x2_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x62),
@@ -3326,6 +3647,287 @@ static const struct qmp_phy_init_tbl kaanapali_qmp_gen3x2_pcie_pcs_misc_tbl[] =
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_POWER_STATE_CONFIG6, 0x1f),
};
static const struct qmp_phy_init_tbl hawi_qmp_gen3x2_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SSC_EN_CENTER, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SSC_PER1, 0x62),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SSC_PER2, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SSC_STEP_SIZE1_MODE0, 0xf8),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SSC_STEP_SIZE2_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SSC_STEP_SIZE1_MODE1, 0x93),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SSC_STEP_SIZE2_MODE1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_CLK_ENABLE1, 0x90),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SYS_CLK_CTRL, 0x82),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_PLL_IVCO, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_CP_CTRL_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_CP_CTRL_MODE1, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_PLL_RCTRL_MODE1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_PLL_CCTRL_MODE0, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_PLL_CCTRL_MODE1, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_SYSCLK_EN_SEL, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_BG_TIMER, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_LOCK_CMP_EN, 0x42),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_LOCK_CMP1_MODE0, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_LOCK_CMP2_MODE0, 0x0d),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_LOCK_CMP1_MODE1, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_LOCK_CMP2_MODE1, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DEC_START_MODE0, 0x41),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DEC_START_MODE1, 0x34),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DIV_FRAC_START1_MODE0, 0xab),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DIV_FRAC_START2_MODE0, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DIV_FRAC_START3_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DIV_FRAC_START1_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DIV_FRAC_START2_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_DIV_FRAC_START3_MODE1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_VCO_TUNE_MAP, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_CLK_SELECT, 0x34),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_HSCLK_SEL_1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_CORECLK_DIV_MODE1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_CMN_CONFIG_1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_ADDITIONAL_MISC_3, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V10_COM_CORE_CLK_EN, 0xa0),
};
static const struct qmp_phy_init_tbl hawi_qmp_gen3x2_pcie_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V10_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_GM_CAL, 0x11),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_00_HIGH, 0xbf),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_00_HIGH2, 0xbf),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_00_HIGH3, 0xb7),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_00_HIGH4, 0xec),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_00_LOW, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_01_HIGH, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_01_HIGH2, 0x49),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_01_HIGH3, 0x1b),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_01_HIGH4, 0x9c),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_01_LOW, 0xd1),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_10_HIGH, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_10_HIGH2, 0x49),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_10_HIGH3, 0x1b),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_10_HIGH4, 0x9c),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_MODE_10_LOW, 0xd1),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_TX_ADAPT_PRE_THRESH1, 0x3e),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_TX_ADAPT_PRE_THRESH2, 0x1e),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_TX_ADAPT_POST_THRESH, 0xd2),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_UCDR_FO_GAIN, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_UCDR_SO_GAIN, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_UCDR_SB2_THRESH1, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_UCDR_SB2_THRESH2, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_VGA_CAL_CNTRL2, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_SIGDET_ENABLES, 0x1c),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_SIGDET_CNTRL, 0x60),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_RX_IDAC_TSETTLE_LOW, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V10_RX_SIGDET_CAL_TRIM, 0x08),
};
static const struct qmp_phy_init_tbl hawi_qmp_gen3x2_pcie_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V10_TX_LANE_MODE_1, 0x25),
QMP_PHY_INIT_CFG(QSERDES_V10_TX_LANE_MODE_3, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V10_TX_LANE_MODE_4, 0x31),
QMP_PHY_INIT_CFG(QSERDES_V10_TX_LANE_MODE_5, 0x7d),
QMP_PHY_INIT_CFG(QSERDES_V10_TX_PI_QEC_CTRL, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V10_TX_RES_CODE_LANE_OFFSET_RX, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V10_TX_RES_CODE_LANE_OFFSET_TX, 0x14),
};
static const struct qmp_phy_init_tbl hawi_qmp_gen3x2_pcie_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V10_PCS_REFGEN_REQ_CONFIG1, 0x05),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_RX_SIGDET_LVL, 0x77),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_RATE_SLEW_CNTRL1, 0x0b),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_EQ_CONFIG2, 0x0f),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_PCS_TX_RX_CONFIG, 0x8c),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_G12S1_TXDEEMPH_M6DB, 0x17),
QMP_PHY_INIT_CFG(QPHY_V10_PCS_G3S2_PRE_GAIN, 0x2e),
};
static const struct qmp_phy_init_tbl hawi_qmp_gen3x2_pcie_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_PCS_EQ_CONFIG1, 0x1e),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_PCS_RXEQEVAL_TIME, 0x27),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_PCS_POWER_STATE_CONFIG2, 0x1d),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_PCS_POWER_STATE_CONFIG4, 0x07),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_PCS_POWER_STATE_CONFIG6, 0x1f),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_PCS_ENDPOINT_REFCLK_DRIVE, 0xc1),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_PCS_OSC_DTCT_ACTIONS, 0x00),
};
static const struct qmp_phy_init_tbl hawi_qmp_gen4x1_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_SSC_STEP_SIZE1_MODE1, 0x93),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_SSC_STEP_SIZE2_MODE1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_CP_CTRL_MODE1, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_PLL_RCTRL_MODE1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_PLL_CCTRL_MODE1, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_CORECLK_DIV_MODE1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_LOCK_CMP1_MODE1, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_LOCK_CMP2_MODE1, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_DEC_START_MODE1, 0x34),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_DIV_FRAC_START1_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_DIV_FRAC_START2_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_DIV_FRAC_START3_MODE1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_HSCLK_SEL_1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_SSC_STEP_SIZE1_MODE0, 0xf8),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_SSC_STEP_SIZE2_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_CP_CTRL_MODE0, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_PLL_CCTRL_MODE0, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_CORECLK_DIV_MODE0, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_LOCK_CMP1_MODE0, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_LOCK_CMP2_MODE0, 0x0d),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_DEC_START_MODE0, 0x41),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_DIV_FRAC_START1_MODE0, 0xab),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_DIV_FRAC_START2_MODE0, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_DIV_FRAC_START3_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_HSCLK_HS_SWITCH_SEL_1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_BG_TIMER, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_SSC_PER1, 0x62),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_SSC_PER2, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_BIAS_EN_CLKBUFLR_EN, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_CLK_ENABLE1, 0x90),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_SYS_CLK_CTRL, 0x82),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_PLL_IVCO, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_SYSCLK_EN_SEL, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_LOCK_CMP_EN, 0x46),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_LOCK_CMP_CFG, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_VCO_TUNE_MAP, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_CLK_SELECT, 0x34),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_CORE_CLK_EN, 0xa0),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_CMN_CONFIG_1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_CMN_MISC1, 0x88),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_CMN_MODE, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_VCO_DC_LEVEL_CTRL, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V10_60_COM_PLL_SPARE_FOR_ECO, 0x02),
};
static const struct qmp_phy_init_tbl hawi_qmp_gen4x1_pcie_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RES_CODE_LANE_OFFSET_TX, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RES_CODE_LANE_OFFSET_RX, 0x12),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_SIGDET_CAL_CTRL1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_SIGDET_CAL_CTRL2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_SIGDET_CAL_TRIM, 0x66),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_TX_BAND0, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_TX_BAND1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_SEL_10B_8B, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_SEL_20B_10B, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_EQ_RCF_CTRL_RATE3, 0x22),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_EQ_RCF_CTRL_RATE4, 0x22),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_PHPRE_CTRL, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_FASTLOCK_FO_GAIN_RATE1, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_FASTLOCK_FO_GAIN_RATE2, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_FASTLOCK_FO_GAIN_RATE3, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_FASTLOCK_FO_GAIN_RATE4, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_FASTLOCK_SO_GAIN_RATE1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_FASTLOCK_SO_GAIN_RATE2, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_FASTLOCK_SO_GAIN_RATE3, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_FASTLOCK_SO_GAIN_RATE4, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_PI_CTRL1, 0x40),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_PI_CTRL2, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_PI_CTRL3, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_PI_CTRL4, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_SVS_MODE_CTRL, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RXCLK_DIV2_CTRL, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_BAND_CTRL0, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_TERM_BW_CTRL0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_TERM_BW_CTRL1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_FO_GAIN_RATE1, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_FO_GAIN_RATE2, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_FO_GAIN_RATE3, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_FO_GAIN_RATE4, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_SO_GAIN_RATE1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_SO_GAIN_RATE2, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_SO_GAIN_RATE3, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_SO_GAIN_RATE4, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_UCDR_PI_CONTROLS, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_AUXDATA_BIN_RATE3, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_AUXDATA_BIN_RATE4, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_EOM_MAX_ERR_LIMIT_LSB, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_EOM_MAX_ERR_LIMIT_MSB, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_VGA_CAL_CNTRL1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_VGA_CAL_MAN_VAL, 0x8e),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_GM_CAL, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_EQU_ADAPTOR_CNTRL6, 0xca),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_SIGDET_ENABLES, 0x1c),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_SIGDET_CNTRL, 0x6f),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_SIGDET_LVL, 0x84),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_SIGDET_DEGLITCH_CNTRL, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_Q_PI_INTRINSIC_BIAS_RATE32, 0x11),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_Q_PI_INTRINSIC_BIAS_RATE45, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B0, 0xc2),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B1, 0xc2),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B2, 0xd8),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B3, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B4, 0x98),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B5, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B6, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B7, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B8, 0xc0),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B9, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B10, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE2_B0, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE2_B1, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE2_B2, 0xd8),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE2_B3, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE2_B4, 0x98),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE2_B5, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE2_B6, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE2_B7, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE2_B8, 0xc0),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE2_B9, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE2_B10, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE3_B0, 0x13),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE3_B1, 0xd3),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE3_B2, 0xc0),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE3_B3, 0x13),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE3_B4, 0x13),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE3_B5, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE3_B6, 0x4c),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE3_B7, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE3_B8, 0xc0),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE3_B9, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE3_B10, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B0, 0x24),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B1, 0x24),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B2, 0xc0),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B3, 0x0b),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B4, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B5, 0x24),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B6, 0x2c),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B7, 0x86),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B8, 0x83),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B9, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B10, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_LANE_MODE_1, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_LANE_MODE_2, 0xc0),
QMP_PHY_INIT_CFG(QSERDES_V10_60_TXRX_LANE_MODE_3, 0x00),
};
static const struct qmp_phy_init_tbl hawi_qmp_gen4x1_pcie_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V10_60_PCS_G12S1_TXDEEMPH_M6DB, 0x17),
QMP_PHY_INIT_CFG(QPHY_V10_60_PCS_G3S2_PRE_GAIN, 0x2e),
QMP_PHY_INIT_CFG(QPHY_V10_60_PCS_RX_SIGDET_LVL, 0xcc),
QMP_PHY_INIT_CFG(QPHY_V10_60_PCS_ELECIDLE_DLY_SEL, 0x40),
QMP_PHY_INIT_CFG(QPHY_V10_60_PCS_PCS_TX_RX_CONFIG1, 0x04),
QMP_PHY_INIT_CFG(QPHY_V10_60_PCS_PCS_TX_RX_CONFIG2, 0x02),
QMP_PHY_INIT_CFG(QPHY_V10_60_PCS_EQ_CONFIG4, 0x00),
QMP_PHY_INIT_CFG(QPHY_V10_60_PCS_EQ_CONFIG5, 0x22),
};
static const struct qmp_phy_init_tbl hawi_qmp_gen4x1_pcie_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_60_PCS_POWER_STATE_CONFIG2, 0x1d),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_60_PCS_TX_RX_CONFIG, 0xc0),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_60_PCS_ENDPOINT_REFCLK_DRIVE, 0xc1),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_60_PCS_OSC_DTCT_ACTIONS, 0x00),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_60_PCS_EQ_CONFIG1, 0x16),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_60_PCS_G3_RXEQEVAL_TIME, 0x27),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_60_PCS_G4_RXEQEVAL_TIME, 0x27),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_60_PCS_G4_EQ_CONFIG5, 0x02),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_60_PCS_G4_PRE_GAIN, 0x2e),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_60_PCS_RX_MARGINING_CONFIG1, 0x03),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_60_PCS_RX_MARGINING_CONFIG3, 0x28),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_60_PCS_RX_MARGINING_CONFIG5, 0x0f),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_60_PCS_G3_FOM_EQ_CONFIG5, 0xf2),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_60_PCS_G4_FOM_EQ_CONFIG5, 0xf2),
QMP_PHY_INIT_CFG(QPHY_PCIE_V10_60_PCS_POWER_STATE_CONFIG6, 0x1f),
};
struct qmp_pcie_offsets {
u16 serdes;
u16 pcs;
@@ -3484,6 +4086,10 @@ static const char * const qmp_phy_vreg_l[] = {
"vdda-phy", "vdda-pll",
};
static const char * const ipq9650_qmp_phy_vreg_l[] = {
"refgen",
};
static const char * const sm8550_qmp_phy_vreg_l[] = {
"vdda-phy", "vdda-pll", "vdda-qref",
};
@@ -3527,6 +4133,14 @@ static const struct qmp_pcie_offsets qmp_pcie_offsets_v4x1 = {
.rx = 0x0400,
};
static const struct qmp_pcie_offsets qmp_pcie_offsets_9650_v4x1 = {
.serdes = 0,
.pcs = 0x0600,
.pcs_misc = 0x0a00,
.tx = 0x0200,
.rx = 0x0400,
};
static const struct qmp_pcie_offsets qmp_pcie_offsets_v4x2 = {
.serdes = 0,
.pcs = 0x0a00,
@@ -3554,6 +4168,7 @@ static const struct qmp_pcie_offsets qmp_pcie_offsets_v5 = {
.pcs_misc = 0x0600,
.tx = 0x0e00,
.rx = 0x1000,
.pcs_lane1 = 0x1400,
.tx2 = 0x1600,
.rx2 = 0x1800,
};
@@ -3638,6 +4253,24 @@ static const struct qmp_pcie_offsets qmp_pcie_offsets_v8_50 = {
.txrxz = 0xd000,
};
static const struct qmp_pcie_offsets qmp_pcie_offsets_v10_0 = {
.serdes = 0x0000,
.pcs = 0x0400,
.pcs_misc = 0x0800,
.tx = 0x1000,
.rx = 0x1200,
.tx2 = 0x1800,
.rx2 = 0x1a00,
};
static const struct qmp_pcie_offsets qmp_pcie_offsets_v10_60 = {
.tx = 0x0000,
/* no .rx; tx and rx share the same register block */
.serdes = 0x1000,
.pcs = 0x1400,
.pcs_misc = 0x1800,
};
static const struct qmp_phy_cfg eliza_qmp_gen3x1_pciephy_cfg = {
.lanes = 1,
@@ -3746,6 +4379,49 @@ static const struct qmp_phy_cfg ipq6018_pciephy_cfg = {
.phy_status = PHYSTATUS,
};
static const struct qmp_phy_cfg ipq5210_gen3x1_pciephy_cfg = {
.lanes = 1,
.offsets = &qmp_pcie_offsets_v4x1,
.tbls = {
.serdes = ipq9574_gen3x1_pcie_serdes_tbl,
.serdes_num = ARRAY_SIZE(ipq9574_gen3x1_pcie_serdes_tbl),
.tx = ipq8074_pcie_gen3_tx_tbl,
.tx_num = ARRAY_SIZE(ipq8074_pcie_gen3_tx_tbl),
.rx = ipq9574_pcie_rx_tbl,
.rx_num = ARRAY_SIZE(ipq9574_pcie_rx_tbl),
.pcs = ipq9574_gen3x1_pcie_pcs_tbl,
.pcs_num = ARRAY_SIZE(ipq9574_gen3x1_pcie_pcs_tbl),
.pcs_misc = ipq9574_gen3x1_pcie_pcs_misc_tbl,
.pcs_misc_num = ARRAY_SIZE(ipq9574_gen3x1_pcie_pcs_misc_tbl),
},
.tbls_ep = &(const struct qmp_phy_cfg_tbls) {
.serdes = ipq5210_gen3x1_pcie_ep_serdes_tbl,
.serdes_num = ARRAY_SIZE(ipq5210_gen3x1_pcie_ep_serdes_tbl),
.tx = ipq6018_pcie_tx_tbl,
.tx_num = ARRAY_SIZE(ipq6018_pcie_tx_tbl),
.rx = ipq5210_gen3x1_pcie_ep_rx_tbl,
.rx_num = ARRAY_SIZE(ipq5210_gen3x1_pcie_ep_rx_tbl),
.pcs = ipq6018_pcie_pcs_tbl,
.pcs_num = ARRAY_SIZE(ipq6018_pcie_pcs_tbl),
.pcs_misc = ipq5210_gen3x1_pcie_ep_pcs_misc_tbl,
.pcs_misc_num = ARRAY_SIZE(ipq5210_gen3x1_pcie_ep_pcs_misc_tbl),
},
.reset_list = ipq8074_pciephy_reset_l,
.num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l),
.vreg_list = NULL,
.num_vregs = 0,
.regs = pciephy_v4_regs_layout,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS,
.pipe_clock_rate = 250000000,
};
static const struct qmp_phy_cfg ipq9574_gen3x1_pciephy_cfg = {
.lanes = 1,
@@ -3802,6 +4478,62 @@ static const struct qmp_phy_cfg ipq9574_gen3x2_pciephy_cfg = {
.pipe_clock_rate = 250000000,
};
static const struct qmp_phy_cfg ipq9650_gen3x1_pciephy_cfg = {
.lanes = 1,
.offsets = &qmp_pcie_offsets_9650_v4x1,
.tbls = {
.serdes = ipq9650_pcie_serdes_tbl,
.serdes_num = ARRAY_SIZE(ipq9650_pcie_serdes_tbl),
.tx = ipq9650_pcie_tx_tbl,
.tx_num = ARRAY_SIZE(ipq9650_pcie_tx_tbl),
.rx = ipq9650_pcie_rx_tbl,
.rx_num = ARRAY_SIZE(ipq9650_pcie_rx_tbl),
.pcs = ipq9650_pcie_pcs_tbl,
.pcs_num = ARRAY_SIZE(ipq9650_pcie_pcs_tbl),
.pcs_misc = ipq9650_pcie_pcs_misc_tbl,
.pcs_misc_num = ARRAY_SIZE(ipq9650_pcie_pcs_misc_tbl),
},
.reset_list = ipq8074_pciephy_reset_l,
.num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l),
.vreg_list = ipq9650_qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(ipq9650_qmp_phy_vreg_l),
.regs = pciephy_v4_regs_layout,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS,
.pipe_clock_rate = 250000000,
};
static const struct qmp_phy_cfg ipq9650_gen3x2_pciephy_cfg = {
.lanes = 2,
.offsets = &qmp_pcie_offsets_v4x2,
.tbls = {
.serdes = ipq9650_pcie_serdes_tbl,
.serdes_num = ARRAY_SIZE(ipq9650_pcie_serdes_tbl),
.tx = ipq9650_pcie_tx_tbl,
.tx_num = ARRAY_SIZE(ipq9650_pcie_tx_tbl),
.rx = ipq9650_pcie_rx_tbl,
.rx_num = ARRAY_SIZE(ipq9650_pcie_rx_tbl),
.pcs = ipq9650_pcie_pcs_tbl,
.pcs_num = ARRAY_SIZE(ipq9650_pcie_pcs_tbl),
.pcs_misc = ipq9650_pcie_pcs_misc_tbl,
.pcs_misc_num = ARRAY_SIZE(ipq9650_pcie_pcs_misc_tbl),
},
.reset_list = ipq8074_pciephy_reset_l,
.num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l),
.vreg_list = ipq9650_qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(ipq9650_qmp_phy_vreg_l),
.regs = pciephy_v4_regs_layout,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS,
.pipe_clock_rate = 250000000,
};
static const struct qmp_phy_cfg qcs615_pciephy_cfg = {
.lanes = 1,
@@ -4405,6 +5137,35 @@ static const struct qmp_phy_cfg sm8450_qmp_gen4x2_pciephy_cfg = {
.aux_clock_rate = 20000000,
};
static const struct qmp_phy_cfg sm8475_qmp_gen3x1_pciephy_cfg = {
.lanes = 1,
.offsets = &qmp_pcie_offsets_v5,
.tbls = {
.serdes = sm8475_qmp_gen3x1_pcie_serdes_tbl,
.serdes_num = ARRAY_SIZE(sm8475_qmp_gen3x1_pcie_serdes_tbl),
.tx = sm8550_qmp_gen3x2_pcie_tx_tbl,
.tx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_tx_tbl),
.rx = sm8475_qmp_gen3x1_pcie_rx_tbl,
.rx_num = ARRAY_SIZE(sm8475_qmp_gen3x1_pcie_rx_tbl),
.pcs = sm8550_qmp_gen3x2_pcie_pcs_tbl,
.pcs_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_tbl),
.pcs_misc = sm8475_qmp_gen3x1_pcie_pcs_misc_tbl,
.pcs_misc_num = ARRAY_SIZE(sm8475_qmp_gen3x1_pcie_pcs_misc_tbl),
.pcs_lane1 = sar2130p_qmp_gen3x2_pcie_pcs_lane1_tbl,
.pcs_lane1_num = ARRAY_SIZE(sar2130p_qmp_gen3x2_pcie_pcs_lane1_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_v6_regs_layout,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS,
};
static const struct qmp_phy_cfg sm8550_qmp_gen3x2_pciephy_cfg = {
.lanes = 2,
@@ -4781,6 +5542,60 @@ static const struct qmp_phy_cfg glymur_qmp_gen4x2_pciephy_cfg = {
.phy_status = PHYSTATUS_4_20,
};
static const struct qmp_phy_cfg hawi_qmp_gen3x2_pciephy_cfg = {
.lanes = 2,
.offsets = &qmp_pcie_offsets_v10_0,
.tbls = {
.serdes = hawi_qmp_gen3x2_pcie_serdes_tbl,
.serdes_num = ARRAY_SIZE(hawi_qmp_gen3x2_pcie_serdes_tbl),
.tx = hawi_qmp_gen3x2_pcie_tx_tbl,
.tx_num = ARRAY_SIZE(hawi_qmp_gen3x2_pcie_tx_tbl),
.rx = hawi_qmp_gen3x2_pcie_rx_tbl,
.rx_num = ARRAY_SIZE(hawi_qmp_gen3x2_pcie_rx_tbl),
.pcs = hawi_qmp_gen3x2_pcie_pcs_tbl,
.pcs_num = ARRAY_SIZE(hawi_qmp_gen3x2_pcie_pcs_tbl),
.pcs_misc = hawi_qmp_gen3x2_pcie_pcs_misc_tbl,
.pcs_misc_num = ARRAY_SIZE(hawi_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_v10_regs_layout,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS,
};
static const struct qmp_phy_cfg hawi_qmp_gen4x1_pciephy_cfg = {
.lanes = 1,
.offsets = &qmp_pcie_offsets_v10_60,
.tbls = {
.serdes = hawi_qmp_gen4x1_pcie_serdes_tbl,
.serdes_num = ARRAY_SIZE(hawi_qmp_gen4x1_pcie_serdes_tbl),
.tx = hawi_qmp_gen4x1_pcie_tx_tbl,
.tx_num = ARRAY_SIZE(hawi_qmp_gen4x1_pcie_tx_tbl),
.pcs = hawi_qmp_gen4x1_pcie_pcs_tbl,
.pcs_num = ARRAY_SIZE(hawi_qmp_gen4x1_pcie_pcs_tbl),
.pcs_misc = hawi_qmp_gen4x1_pcie_pcs_misc_tbl,
.pcs_misc_num = ARRAY_SIZE(hawi_qmp_gen4x1_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_v10_60_regs_layout,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS_4_20,
};
static void qmp_pcie_init_port_b(struct qmp_pcie *qmp, const struct qmp_phy_cfg_tbls *tbls)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
@@ -4862,6 +5677,7 @@ static int qmp_pcie_init(struct phy *phy)
struct qmp_pcie *qmp = phy_get_drvdata(phy);
const struct qmp_phy_cfg *cfg = qmp->cfg;
void __iomem *pcs = qmp->pcs;
bool skip_reset;
int ret;
/*
@@ -4877,6 +5693,9 @@ static int qmp_pcie_init(struct phy *phy)
qphy_checkbits(pcs, cfg->regs[QPHY_START_CTRL], SERDES_START | PCS_START) &&
qphy_checkbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], cfg->pwrdn_ctrl);
skip_reset = qmp->skip_init && !qphy_checkbits(pcs, cfg->regs[QPHY_PCS_STATUS],
cfg->phy_status);
if (!qmp->skip_init && !cfg->tbls.serdes_num) {
dev_err(qmp->dev, "Init sequence not available\n");
return -ENODATA;
@@ -4900,13 +5719,15 @@ static int qmp_pcie_init(struct phy *phy)
}
}
ret = reset_control_assert(qmp->nocsr_reset);
if (ret) {
dev_err(qmp->dev, "no-csr reset assert failed\n");
goto err_assert_reset;
}
if (!skip_reset) {
ret = reset_control_assert(qmp->nocsr_reset);
if (ret) {
dev_err(qmp->dev, "no-csr reset assert failed\n");
goto err_assert_reset;
}
usleep_range(200, 300);
usleep_range(200, 300);
}
if (!qmp->skip_init) {
ret = reset_control_bulk_deassert(cfg->num_resets, qmp->resets);
@@ -4956,8 +5777,11 @@ static int qmp_pcie_power_on(struct phy *phy)
void __iomem *pcs = qmp->pcs;
void __iomem *status;
unsigned int mask, val;
bool skip_reset;
int ret;
skip_reset = qmp->skip_init && !qphy_checkbits(pcs, cfg->regs[QPHY_PCS_STATUS],
cfg->phy_status);
/*
* Write CSR register for PHY that doesn't support no_csr reset or has not
* been initialized.
@@ -4981,10 +5805,12 @@ static int qmp_pcie_power_on(struct phy *phy)
if (ret)
return ret;
ret = reset_control_deassert(qmp->nocsr_reset);
if (ret) {
dev_err(qmp->dev, "no-csr reset deassert failed\n");
goto err_disable_pipe_clk;
if (!skip_reset) {
ret = reset_control_deassert(qmp->nocsr_reset);
if (ret) {
dev_err(qmp->dev, "no-csr reset deassert failed\n");
goto err_disable_pipe_clk;
}
}
if (qmp->skip_init)
@@ -5543,6 +6369,15 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
}, {
.compatible = "qcom,glymur-qmp-gen5x4-pcie-phy",
.data = &glymur_qmp_gen5x4_pciephy_cfg,
}, {
.compatible = "qcom,hawi-qmp-gen3x2-pcie-phy",
.data = &hawi_qmp_gen3x2_pciephy_cfg,
}, {
.compatible = "qcom,hawi-qmp-gen4x1-pcie-phy",
.data = &hawi_qmp_gen4x1_pciephy_cfg,
}, {
.compatible = "qcom,ipq5210-qmp-gen3x1-pcie-phy",
.data = &ipq5210_gen3x1_pciephy_cfg,
}, {
.compatible = "qcom,ipq6018-qmp-pcie-phy",
.data = &ipq6018_pciephy_cfg,
@@ -5558,6 +6393,12 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
}, {
.compatible = "qcom,ipq9574-qmp-gen3x2-pcie-phy",
.data = &ipq9574_gen3x2_pciephy_cfg,
}, {
.compatible = "qcom,ipq9650-qmp-gen3x1-pcie-phy",
.data = &ipq9650_gen3x1_pciephy_cfg,
}, {
.compatible = "qcom,ipq9650-qmp-gen3x2-pcie-phy",
.data = &ipq9650_gen3x2_pciephy_cfg,
}, {
.compatible = "qcom,kaanapali-qmp-gen3x2-pcie-phy",
.data = &qmp_v8_gen3x2_pciephy_cfg,
@@ -5630,6 +6471,9 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
}, {
.compatible = "qcom,sm8450-qmp-gen4x2-pcie-phy",
.data = &sm8450_qmp_gen4x2_pciephy_cfg,
}, {
.compatible = "qcom,sm8475-qmp-gen3x1-pcie-phy",
.data = &sm8475_qmp_gen3x1_pciephy_cfg,
}, {
.compatible = "qcom,sm8550-qmp-gen3x2-pcie-phy",
.data = &sm8550_qmp_gen3x2_pciephy_cfg,

View File

@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2026, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_PCS_AON_V10_H_
#define QCOM_PHY_QMP_PCS_AON_V10_H_
/* Only for QMP V10 PHY - PCS AON registers */
#define QPHY_V10_PCS_AON_CLAMP_ENABLE 0x00
#endif

View File

@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef QCOM_PHY_QMP_PCS_PCIE_V10_H_
#define QCOM_PHY_QMP_PCS_PCIE_V10_H_
/* Only for QMP V10 PHY - PCIE PCS registers */
#define QPHY_PCIE_V10_PCS_POWER_STATE_CONFIG2 0x00c
#define QPHY_PCIE_V10_PCS_POWER_STATE_CONFIG4 0x014
#define QPHY_PCIE_V10_PCS_ENDPOINT_REFCLK_DRIVE 0x020
#define QPHY_PCIE_V10_PCS_OSC_DTCT_ACTIONS 0x094
#define QPHY_PCIE_V10_PCS_EQ_CONFIG1 0x0a4
#define QPHY_PCIE_V10_PCS_RXEQEVAL_TIME 0x0f4
#define QPHY_PCIE_V10_PCS_POWER_STATE_CONFIG6 0x0f8
#endif

View File

@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef QCOM_PHY_QMP_PCS_PCIE_V10_60_H_
#define QCOM_PHY_QMP_PCS_PCIE_V10_60_H_
/* Only for QMP V10_60 PHY - PCIE PCS registers */
#define QPHY_PCIE_V10_60_PCS_POWER_STATE_CONFIG2 0x00c
#define QPHY_PCIE_V10_60_PCS_TX_RX_CONFIG 0x018
#define QPHY_PCIE_V10_60_PCS_ENDPOINT_REFCLK_DRIVE 0x01c
#define QPHY_PCIE_V10_60_PCS_OSC_DTCT_ACTIONS 0x090
#define QPHY_PCIE_V10_60_PCS_EQ_CONFIG1 0x0a0
#define QPHY_PCIE_V10_60_PCS_G3_RXEQEVAL_TIME 0x0f0
#define QPHY_PCIE_V10_60_PCS_G4_RXEQEVAL_TIME 0x0f4
#define QPHY_PCIE_V10_60_PCS_G4_EQ_CONFIG5 0x108
#define QPHY_PCIE_V10_60_PCS_G4_PRE_GAIN 0x15c
#define QPHY_PCIE_V10_60_PCS_RX_MARGINING_CONFIG1 0x17c
#define QPHY_PCIE_V10_60_PCS_RX_MARGINING_CONFIG3 0x184
#define QPHY_PCIE_V10_60_PCS_RX_MARGINING_CONFIG5 0x18c
#define QPHY_PCIE_V10_60_PCS_G3_FOM_EQ_CONFIG5 0x1ac
#define QPHY_PCIE_V10_60_PCS_G4_FOM_EQ_CONFIG5 0x1c0
#define QPHY_PCIE_V10_60_PCS_POWER_STATE_CONFIG6 0x1d0
#endif

View File

@@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2026, The Linux Foundation. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_PCS_UFS_V7_H_
#define QCOM_PHY_QMP_PCS_UFS_V7_H_
/* Only for QMP V7 PHY - UFS PCS registers */
#define QPHY_V7_PCS_UFS_PHY_START 0x000
#define QPHY_V7_PCS_UFS_POWER_DOWN_CONTROL 0x004
#define QPHY_V7_PCS_UFS_SW_RESET 0x008
#define QPHY_V7_PCS_UFS_PCS_CTRL1 0x01c
#define QPHY_V7_PCS_UFS_PLL_CNTL 0x028
#define QPHY_V7_PCS_UFS_TX_LARGE_AMP_DRV_LVL 0x02c
#define QPHY_V7_PCS_UFS_TX_HSGEAR_CAPABILITY 0x060
#define QPHY_V7_PCS_UFS_RX_HSGEAR_CAPABILITY 0x094
#define QPHY_V7_PCS_UFS_LINECFG_DISABLE 0x140
#define QPHY_V7_PCS_UFS_RX_SIGDET_CTRL2 0x150
#define QPHY_V7_PCS_UFS_READY_STATUS 0x16c
#define QPHY_V7_PCS_UFS_TX_MID_TERM_CTRL1 0x1b8
#define QPHY_V7_PCS_UFS_MULTI_LANE_CTRL1 0x1c0
#endif

View File

@@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2026, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_PCS_USB_V10_H_
#define QCOM_PHY_QMP_PCS_USB_V10_H_
/* Only for QMP V10 PHY - USB PCS registers */
#define QPHY_V10_PCS_USB3_POWER_STATE_CONFIG1 0x00
#define QPHY_V10_PCS_USB3_AUTONOMOUS_MODE_CTRL 0x08
#define QPHY_V10_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR 0x14
#define QPHY_V10_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL 0x18
#define QPHY_V10_PCS_USB3_RXEQTRAINING_DFE_TIME_S2 0x3c
#define QPHY_V10_PCS_USB3_RCVR_DTCT_DLY_U3_L 0x40
#define QPHY_V10_PCS_USB3_RCVR_DTCT_DLY_U3_H 0x44
#endif

View File

@@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef QCOM_PHY_QMP_PCS_V10_H_
#define QCOM_PHY_QMP_PCS_V10_H_
/* Only for QMP V10 PHY - PCS registers */
#define QPHY_V10_PCS_SW_RESET 0x000
#define QPHY_V10_PCS_PCS_STATUS1 0x014
#define QPHY_V10_PCS_POWER_DOWN_CONTROL 0x040
#define QPHY_V10_PCS_START_CONTROL 0x044
#define QPHY_V10_PCS_POWER_STATE_CONFIG1 0x090
#define QPHY_V10_PCS_LOCK_DETECT_CONFIG1 0x0c4
#define QPHY_V10_PCS_LOCK_DETECT_CONFIG2 0x0c8
#define QPHY_V10_PCS_LOCK_DETECT_CONFIG3 0x0cc
#define QPHY_V10_PCS_LOCK_DETECT_CONFIG6 0x0d8
#define QPHY_V10_PCS_REFGEN_REQ_CONFIG1 0x0dc
#define QPHY_V10_PCS_G12S1_TXDEEMPH_M6DB 0x168
#define QPHY_V10_PCS_G3S2_PRE_GAIN 0x170
#define QPHY_V10_PCS_RX_SIGDET_LVL 0x188
#define QPHY_V10_PCS_RCVR_DTCT_DLY_P1U2_L 0x190
#define QPHY_V10_PCS_RCVR_DTCT_DLY_P1U2_H 0x194
#define QPHY_V10_PCS_RATE_SLEW_CNTRL1 0x198
#define QPHY_V10_PCS_RX_CONFIG 0x1b0
#define QPHY_V10_PCS_ALIGN_DETECT_CONFIG1 0x1c0
#define QPHY_V10_PCS_ALIGN_DETECT_CONFIG2 0x1c4
#define QPHY_V10_PCS_PCS_TX_RX_CONFIG 0x1d0
#define QPHY_V10_PCS_PCS_TX_RX_CONFIG2 0x1d4
#define QPHY_V10_PCS_EQ_CONFIG1 0x1e0
#define QPHY_V10_PCS_EQ_CONFIG2 0x1e4
#define QPHY_V10_PCS_EQ_CONFIG5 0x1f0
#endif

View File

@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef QCOM_PHY_QMP_PCS_V10_60_H_
#define QCOM_PHY_QMP_PCS_V10_60_H_
/* Only for QMP V10_60 PHY - PCIe PCS registers */
#define QPHY_V10_60_PCS_SW_RESET 0x000
#define QPHY_V10_60_PCS_PCS_STATUS1 0x014
#define QPHY_V10_60_PCS_POWER_DOWN_CONTROL 0x040
#define QPHY_V10_60_PCS_START_CONTROL 0x044
#define QPHY_V10_60_PCS_G12S1_TXDEEMPH_M6DB 0x170
#define QPHY_V10_60_PCS_G3S2_PRE_GAIN 0x178
#define QPHY_V10_60_PCS_RX_SIGDET_LVL 0x190
#define QPHY_V10_60_PCS_ELECIDLE_DLY_SEL 0x1b8
#define QPHY_V10_60_PCS_PCS_TX_RX_CONFIG1 0x1dc
#define QPHY_V10_60_PCS_PCS_TX_RX_CONFIG2 0x1e0
#define QPHY_V10_60_PCS_EQ_CONFIG4 0x1f8
#define QPHY_V10_60_PCS_EQ_CONFIG5 0x1fc
#endif

View File

@@ -0,0 +1,89 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef QCOM_PHY_QMP_QSERDES_COM_V10_H_
#define QCOM_PHY_QMP_QSERDES_COM_V10_H_
/* Only for QMP V10 PHY - QSERDES COM registers */
#define QSERDES_V10_COM_SSC_STEP_SIZE1_MODE1 0x00
#define QSERDES_V10_COM_SSC_STEP_SIZE2_MODE1 0x04
#define QSERDES_V10_COM_CP_CTRL_MODE1 0x10
#define QSERDES_V10_COM_PLL_RCTRL_MODE1 0x14
#define QSERDES_V10_COM_PLL_CCTRL_MODE1 0x18
#define QSERDES_V10_COM_CORECLK_DIV_MODE1 0x1c
#define QSERDES_V10_COM_LOCK_CMP1_MODE1 0x20
#define QSERDES_V10_COM_LOCK_CMP2_MODE1 0x24
#define QSERDES_V10_COM_DEC_START_MODE1 0x28
#define QSERDES_V10_COM_DEC_START_MSB_MODE1 0x2c
#define QSERDES_V10_COM_DIV_FRAC_START1_MODE1 0x30
#define QSERDES_V10_COM_DIV_FRAC_START2_MODE1 0x34
#define QSERDES_V10_COM_DIV_FRAC_START3_MODE1 0x38
#define QSERDES_V10_COM_HSCLK_SEL_1 0x3c
#define QSERDES_V10_COM_INTEGLOOP_GAIN0_MODE1 0x40
#define QSERDES_V10_COM_INTEGLOOP_GAIN1_MODE1 0x44
#define QSERDES_V10_COM_VCO_TUNE1_MODE1 0x48
#define QSERDES_V10_COM_VCO_TUNE2_MODE1 0x4c
#define QSERDES_V10_COM_BIN_VCOCAL_CMP_CODE1_MODE1 0x50
#define QSERDES_V10_COM_BIN_VCOCAL_CMP_CODE2_MODE1 0x54
#define QSERDES_V10_COM_BIN_VCOCAL_CMP_CODE1_MODE0 0x58
#define QSERDES_V10_COM_BIN_VCOCAL_CMP_CODE2_MODE0 0x5c
#define QSERDES_V10_COM_SSC_STEP_SIZE1_MODE0 0x60
#define QSERDES_V10_COM_SSC_STEP_SIZE2_MODE0 0x64
#define QSERDES_V10_COM_CP_CTRL_MODE0 0x70
#define QSERDES_V10_COM_PLL_RCTRL_MODE0 0x74
#define QSERDES_V10_COM_PLL_CCTRL_MODE0 0x78
#define QSERDES_V10_COM_PLL_CORE_CLK_DIV_MODE0 0x7c
#define QSERDES_V10_COM_LOCK_CMP1_MODE0 0x80
#define QSERDES_V10_COM_LOCK_CMP2_MODE0 0x84
#define QSERDES_V10_COM_DEC_START_MODE0 0x88
#define QSERDES_V10_COM_DEC_START_MSB_MODE0 0x8c
#define QSERDES_V10_COM_DIV_FRAC_START1_MODE0 0x90
#define QSERDES_V10_COM_DIV_FRAC_START2_MODE0 0x94
#define QSERDES_V10_COM_DIV_FRAC_START3_MODE0 0x98
#define QSERDES_V10_COM_HSCLK_HS_SWITCH_SEL_1 0x9c
#define QSERDES_V10_COM_INTEGLOOP_GAIN0_MODE0 0xa0
#define QSERDES_V10_COM_INTEGLOOP_GAIN1_MODE0 0xa4
#define QSERDES_V10_COM_VCO_TUNE1_MODE0 0xa8
#define QSERDES_V10_COM_VCO_TUNE2_MODE0 0xac
#define QSERDES_V10_COM_BG_TIMER 0xbc
#define QSERDES_V10_COM_SSC_EN_CENTER 0xc0
#define QSERDES_V10_COM_SSC_ADJ_PER1 0xc4
#define QSERDES_V10_COM_SSC_PER1 0xcc
#define QSERDES_V10_COM_SSC_PER2 0xd0
#define QSERDES_V10_COM_POST_DIV_MUX 0xd8
#define QSERDES_V10_COM_BIAS_EN_CLKBUFLR_EN 0xdc
#define QSERDES_V10_COM_CLK_ENABLE1 0xe0
#define QSERDES_V10_COM_SYS_CLK_CTRL 0xe4
#define QSERDES_V10_COM_SYSCLK_BUF_ENABLE 0xe8
#define QSERDES_V10_COM_PLL_IVCO 0xf4
#define QSERDES_V10_COM_PLL_IVCO_MODE1 0xf8
#define QSERDES_V10_COM_CMN_IETRIM 0xfc
#define QSERDES_V10_COM_CMN_IPTRIM 0x100
#define QSERDES_V10_COM_SYSCLK_EN_SEL 0x110
#define QSERDES_V10_COM_RESETSM_CNTRL 0x118
#define QSERDES_V10_COM_LOCK_CMP_EN 0x120
#define QSERDES_V10_COM_LOCK_CMP_CFG 0x124
#define QSERDES_V10_COM_VCO_TUNE_CTRL 0x13c
#define QSERDES_V10_COM_VCO_TUNE_MAP 0x140
#define QSERDES_V10_COM_VCO_TUNE_INITVAL2 0x148
#define QSERDES_V10_COM_VCO_TUNE_MAXVAL2 0x158
#define QSERDES_V10_COM_CLK_SELECT 0x164
#define QSERDES_V10_COM_CORE_CLK_EN 0x170
#define QSERDES_V10_COM_CMN_CONFIG_1 0x174
#define QSERDES_V10_COM_SVS_MODE_CLK_SEL 0x17c
#define QSERDES_V10_COM_CMN_MISC_1 0x184
#define QSERDES_V10_COM_CMN_MODE 0x188
#define QSERDES_V10_COM_PLL_VCO_DC_LEVEL_CTRL 0x198
#define QSERDES_V10_COM_AUTO_GAIN_ADJ_CTRL_1 0x1a4
#define QSERDES_V10_COM_AUTO_GAIN_ADJ_CTRL_2 0x1a8
#define QSERDES_V10_COM_AUTO_GAIN_ADJ_CTRL_3 0x1ac
#define QSERDES_V10_COM_ADDITIONAL_MISC 0x1b4
#define QSERDES_V10_COM_ADDITIONAL_MISC_2 0x1b8
#define QSERDES_V10_COM_ADDITIONAL_MISC_3 0x1bc
#define QSERDES_V10_COM_CMN_STATUS 0x2c8
#define QSERDES_V10_COM_C_READY_STATUS 0x2f0
#endif

View File

@@ -0,0 +1,55 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef QCOM_PHY_QMP_QSERDES_COM_V10_60_H_
#define QCOM_PHY_QMP_QSERDES_COM_V10_60_H_
/* Only for QMP V10_60 PHY - QSERDES COM registers */
#define QSERDES_V10_60_COM_SSC_STEP_SIZE1_MODE1 0x00
#define QSERDES_V10_60_COM_SSC_STEP_SIZE2_MODE1 0x04
#define QSERDES_V10_60_COM_CP_CTRL_MODE1 0x10
#define QSERDES_V10_60_COM_PLL_RCTRL_MODE1 0x14
#define QSERDES_V10_60_COM_PLL_CCTRL_MODE1 0x18
#define QSERDES_V10_60_COM_CORECLK_DIV_MODE1 0x1c
#define QSERDES_V10_60_COM_LOCK_CMP1_MODE1 0x20
#define QSERDES_V10_60_COM_LOCK_CMP2_MODE1 0x24
#define QSERDES_V10_60_COM_DEC_START_MODE1 0x28
#define QSERDES_V10_60_COM_DIV_FRAC_START1_MODE1 0x30
#define QSERDES_V10_60_COM_DIV_FRAC_START2_MODE1 0x34
#define QSERDES_V10_60_COM_DIV_FRAC_START3_MODE1 0x38
#define QSERDES_V10_60_COM_HSCLK_SEL_1 0x3c
#define QSERDES_V10_60_COM_SSC_STEP_SIZE1_MODE0 0x60
#define QSERDES_V10_60_COM_SSC_STEP_SIZE2_MODE0 0x64
#define QSERDES_V10_60_COM_CP_CTRL_MODE0 0x70
#define QSERDES_V10_60_COM_PLL_RCTRL_MODE0 0x74
#define QSERDES_V10_60_COM_PLL_CCTRL_MODE0 0x78
#define QSERDES_V10_60_COM_CORECLK_DIV_MODE0 0x7c
#define QSERDES_V10_60_COM_LOCK_CMP1_MODE0 0x80
#define QSERDES_V10_60_COM_LOCK_CMP2_MODE0 0x84
#define QSERDES_V10_60_COM_DEC_START_MODE0 0x88
#define QSERDES_V10_60_COM_DIV_FRAC_START1_MODE0 0x90
#define QSERDES_V10_60_COM_DIV_FRAC_START2_MODE0 0x94
#define QSERDES_V10_60_COM_DIV_FRAC_START3_MODE0 0x98
#define QSERDES_V10_60_COM_HSCLK_HS_SWITCH_SEL_1 0x9c
#define QSERDES_V10_60_COM_BG_TIMER 0xbc
#define QSERDES_V10_60_COM_SSC_PER1 0xcc
#define QSERDES_V10_60_COM_SSC_PER2 0xd0
#define QSERDES_V10_60_COM_BIAS_EN_CLKBUFLR_EN 0xdc
#define QSERDES_V10_60_COM_CLK_ENABLE1 0xe0
#define QSERDES_V10_60_COM_SYS_CLK_CTRL 0xe4
#define QSERDES_V10_60_COM_PLL_IVCO 0xf4
#define QSERDES_V10_60_COM_SYSCLK_EN_SEL 0x110
#define QSERDES_V10_60_COM_LOCK_CMP_EN 0x120
#define QSERDES_V10_60_COM_LOCK_CMP_CFG 0x124
#define QSERDES_V10_60_COM_VCO_TUNE_MAP 0x140
#define QSERDES_V10_60_COM_CLK_SELECT 0x164
#define QSERDES_V10_60_COM_CORE_CLK_EN 0x170
#define QSERDES_V10_60_COM_CMN_CONFIG_1 0x174
#define QSERDES_V10_60_COM_CMN_MISC1 0x184
#define QSERDES_V10_60_COM_CMN_MODE 0x188
#define QSERDES_V10_60_COM_VCO_DC_LEVEL_CTRL 0x198
#define QSERDES_V10_60_COM_PLL_SPARE_FOR_ECO 0x2b4
#endif

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2026, The Linux Foundation. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_QSERDES_COM_V8_H_
@@ -71,5 +71,16 @@
#define QSERDES_V8_COM_ADDITIONAL_MISC 0x1b4
#define QSERDES_V8_COM_CMN_STATUS 0x2c8
#define QSERDES_V8_COM_C_READY_STATUS 0x2f0
#define QSERDES_V8_COM_PLL_IVCO_MODE1 0xf8
#define QSERDES_V8_COM_CMN_IETRIM 0xfc
#define QSERDES_V8_COM_CMN_IPTRIM 0x100
#define QSERDES_V8_COM_VCO_TUNE_CTRL 0x13c
#define QSERDES_V8_COM_ADAPTIVE_ANALOG_CONFIG 0x268
#define QSERDES_V8_COM_CP_CTRL_ADAPTIVE_MODE0 0x26c
#define QSERDES_V8_COM_PLL_RCCTRL_ADAPTIVE_MODE0 0x270
#define QSERDES_V8_COM_PLL_CCTRL_ADAPTIVE_MODE0 0x274
#define QSERDES_V8_COM_CP_CTRL_ADAPTIVE_MODE1 0x278
#define QSERDES_V8_COM_PLL_RCCTRL_ADAPTIVE_MODE1 0x27c
#define QSERDES_V8_COM_PLL_CCTRL_ADAPTIVE_MODE1 0x280
#endif

View File

@@ -0,0 +1,37 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2026, The Linux Foundation. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_QSERDES_TXRX_UFS_V8_H_
#define QCOM_PHY_QMP_QSERDES_TXRX_UFS_V8_H_
#define QSERDES_UFS_V8_TX_RES_CODE_LANE_OFFSET_TX (0x34)
#define QSERDES_UFS_V8_TX_RES_CODE_LANE_OFFSET_RX (0x38)
#define QSERDES_UFS_V8_TX_LANE_MODE_1 (0x80)
#define QSERDES_UFS_V8_RX_UCDR_FO_GAIN_RATE2 (0x1bc)
#define QSERDES_UFS_V8_RX_UCDR_FO_GAIN_RATE4 (0x1c4)
#define QSERDES_UFS_V8_RX_UCDR_SO_GAIN_RATE4 (0x1dc)
#define QSERDES_UFS_V8_RX_EQ_OFFSET_ADAPTOR_CNTRL1 (0x2c8)
#define QSERDES_UFS_V8_RX_UCDR_PI_CONTROLS (0x1e4)
#define QSERDES_UFS_V8_RX_OFFSET_ADAPTOR_CNTRL3 (0x2d0)
#define QSERDES_UFS_V8_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE4 (0x120)
#define QSERDES_UFS_V8_RX_UCDR_FASTLOCK_FO_GAIN_RATE4 (0xd4)
#define QSERDES_UFS_V8_RX_UCDR_FASTLOCK_SO_GAIN_RATE4 (0xec)
#define QSERDES_UFS_V8_RX_VGA_CAL_MAN_VAL (0x288)
#define QSERDES_UFS_V8_RX_EQU_ADAPTOR_CNTRL4 (0x2b0)
#define QSERDES_UFS_V8_RX_MODE_RATE_0_1_B4 (0x324)
#define QSERDES_UFS_V8_RX_MODE_RATE4_SA_B7 (0x3b4)
#define QSERDES_UFS_V8_RX_MODE_RATE4_SA_B9 (0x3bc)
#define QSERDES_UFS_V8_RX_MODE_RATE4_SB_B7 (0x3e0)
#define QSERDES_UFS_V8_RX_MODE_RATE4_SB_B9 (0x3e8)
#define QSERDES_UFS_V8_RX_MODE_RATE5_SA_B7 (0x40c)
#define QSERDES_UFS_V8_RX_MODE_RATE5_SA_B9 (0x414)
#define QSERDES_UFS_V8_RX_MODE_RATE5_SB_B7 (0x438)
#define QSERDES_UFS_V8_RX_MODE_RATE5_SB_B9 (0x440)
#define QSERDES_UFS_V8_RX_UCDR_SO_SATURATION (0xf4)
#define QSERDES_UFS_V8_RX_TERM_BW_CTRL0 (0x1ac)
#define QSERDES_UFS_V8_RX_DLL0_FTUNE_CTRL (0x498)
#define QSERDES_UFS_V8_RX_SIGDET_CAL_TRIM (0x4d0)
#endif

View File

@@ -0,0 +1,91 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef QCOM_PHY_QMP_QSERDES_TXRX_V10_H_
#define QCOM_PHY_QMP_QSERDES_TXRX_V10_H_
/* Only for QMP V10 PHY - QSERDES TX/RX registers */
/* TX registers */
#define QSERDES_V10_TX_CLKBUF_ENABLE 0x08
#define QSERDES_V10_TX_TX_EMP_POST1_LVL 0x0c
#define QSERDES_V10_TX_TX_DRV_LVL 0x14
#define QSERDES_V10_TX_RESET_TSYNC_EN 0x1c
#define QSERDES_V10_TX_PRE_STALL_LDO_BOOST_EN 0x20
#define QSERDES_V10_TX_TX_BAND 0x24
#define QSERDES_V10_TX_INTERFACE_SELECT 0x2c
#define QSERDES_V10_TX_RES_CODE_LANE_TX 0x34
#define QSERDES_V10_TX_RES_CODE_LANE_RX 0x38
#define QSERDES_V10_TX_RES_CODE_LANE_OFFSET_TX 0x3c
#define QSERDES_V10_TX_RES_CODE_LANE_OFFSET_RX 0x40
#define QSERDES_V10_TX_TRANSCEIVER_BIAS_EN 0x54
#define QSERDES_V10_TX_HIGHZ_DRVR_EN 0x58
#define QSERDES_V10_TX_TX_POL_INV 0x5c
#define QSERDES_V10_TX_PARRATE_REC_DETECT_IDLE_EN 0x60
#define QSERDES_V10_TX_BIST_PATTERN7 0x7c
#define QSERDES_V10_TX_LANE_MODE_1 0x84
#define QSERDES_V10_TX_LANE_MODE_2 0x88
#define QSERDES_V10_TX_LANE_MODE_3 0x8c
#define QSERDES_V10_TX_LANE_MODE_4 0x90
#define QSERDES_V10_TX_LANE_MODE_5 0x94
#define QSERDES_V10_TX_RCV_DETECT_LVL_2 0xa4
#define QSERDES_V10_TX_TRAN_DRVR_EMP_EN 0xc0
#define QSERDES_V10_TX_TX_INTERFACE_MODE 0xc4
#define QSERDES_V10_TX_VMODE_CTRL1 0xc8
#define QSERDES_V10_TX_PI_QEC_CTRL 0xe4
/* RX registers */
#define QSERDES_V10_RX_UCDR_FO_GAIN 0x08
#define QSERDES_V10_RX_UCDR_SO_GAIN 0x14
#define QSERDES_V10_RX_UCDR_FASTLOCK_FO_GAIN 0x30
#define QSERDES_V10_RX_UCDR_SO_SATURATION_AND_ENABLE 0x34
#define QSERDES_V10_RX_UCDR_FASTLOCK_COUNT_LOW 0x3c
#define QSERDES_V10_RX_UCDR_FASTLOCK_COUNT_HIGH 0x40
#define QSERDES_V10_RX_UCDR_PI_CONTROLS 0x44
#define QSERDES_V10_RX_UCDR_SB2_THRESH1 0x4c
#define QSERDES_V10_RX_UCDR_SB2_THRESH2 0x50
#define QSERDES_V10_RX_UCDR_SB2_GAIN1 0x54
#define QSERDES_V10_RX_UCDR_SB2_GAIN2 0x58
#define QSERDES_V10_RX_AUX_DATA_TCOARSE_TFINE 0x60
#define QSERDES_V10_RX_TX_ADAPT_PRE_THRESH1 0xc4
#define QSERDES_V10_RX_TX_ADAPT_PRE_THRESH2 0xc8
#define QSERDES_V10_RX_TX_ADAPT_POST_THRESH 0xcc
#define QSERDES_V10_RX_VGA_CAL_CNTRL1 0xd4
#define QSERDES_V10_RX_VGA_CAL_CNTRL2 0xd8
#define QSERDES_V10_RX_GM_CAL 0xdc
#define QSERDES_V10_RX_RX_EQU_ADAPTOR_CNTRL2 0xec
#define QSERDES_V10_RX_RX_EQU_ADAPTOR_CNTRL3 0xf0
#define QSERDES_V10_RX_RX_EQU_ADAPTOR_CNTRL4 0xf4
#define QSERDES_V10_RX_RX_IDAC_TSETTLE_LOW 0xf8
#define QSERDES_V10_RX_RX_IDAC_TSETTLE_HIGH 0xfc
#define QSERDES_V10_RX_RX_IDAC_ENABLES 0x100
#define QSERDES_V10_RX_RX_TERM_AC_BYPASS_DC_COUPLE_OFFSET 0x104
#define QSERDES_V10_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x110
#define QSERDES_V10_RX_SIGDET_ENABLES 0x118
#define QSERDES_V10_RX_SIGDET_CNTRL 0x11c
#define QSERDES_V10_RX_SIGDET_DEGLITCH_CNTRL 0x124
#define QSERDES_V10_RX_RX_MODE_00_LOW 0x15c
#define QSERDES_V10_RX_RX_MODE_00_HIGH 0x160
#define QSERDES_V10_RX_RX_MODE_00_HIGH2 0x164
#define QSERDES_V10_RX_RX_MODE_00_HIGH3 0x168
#define QSERDES_V10_RX_RX_MODE_00_HIGH4 0x16c
#define QSERDES_V10_RX_RX_MODE_01_LOW 0x170
#define QSERDES_V10_RX_RX_MODE_01_HIGH 0x174
#define QSERDES_V10_RX_RX_MODE_01_HIGH2 0x178
#define QSERDES_V10_RX_RX_MODE_01_HIGH3 0x17c
#define QSERDES_V10_RX_RX_MODE_01_HIGH4 0x180
#define QSERDES_V10_RX_RX_MODE_10_LOW 0x184
#define QSERDES_V10_RX_RX_MODE_10_HIGH 0x188
#define QSERDES_V10_RX_RX_MODE_10_HIGH2 0x18c
#define QSERDES_V10_RX_RX_MODE_10_HIGH3 0x190
#define QSERDES_V10_RX_RX_MODE_10_HIGH4 0x194
#define QSERDES_V10_RX_DFE_EN_TIMER 0x1a0
#define QSERDES_V10_RX_DFE_CTLE_POST_CAL_OFFSET 0x1a4
#define QSERDES_V10_RX_DCC_CTRL1 0x1a8
#define QSERDES_V10_RX_VTH_CODE 0x1b0
#define QSERDES_V10_RX_SIGDET_CAL_CTRL1 0x1e4
#define QSERDES_V10_RX_SIGDET_CAL_TRIM 0x1f8
#endif

View File

@@ -0,0 +1,109 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef QCOM_PHY_QMP_QSERDES_TXRX_V10_60_H_
#define QCOM_PHY_QMP_QSERDES_TXRX_V10_60_H_
#define QSERDES_V10_60_TXRX_RES_CODE_LANE_OFFSET_TX 0x034
#define QSERDES_V10_60_TXRX_RES_CODE_LANE_OFFSET_RX 0x038
#define QSERDES_V10_60_TXRX_LANE_MODE_1 0x080
#define QSERDES_V10_60_TXRX_LANE_MODE_2 0x084
#define QSERDES_V10_60_TXRX_LANE_MODE_3 0x088
#define QSERDES_V10_60_TXRX_UCDR_FASTLOCK_FO_GAIN_RATE1 0x0c8
#define QSERDES_V10_60_TXRX_UCDR_FASTLOCK_FO_GAIN_RATE2 0x0cc
#define QSERDES_V10_60_TXRX_UCDR_FASTLOCK_FO_GAIN_RATE3 0x0d0
#define QSERDES_V10_60_TXRX_UCDR_FASTLOCK_FO_GAIN_RATE4 0x0d4
#define QSERDES_V10_60_TXRX_UCDR_FASTLOCK_SO_GAIN_RATE1 0x0e0
#define QSERDES_V10_60_TXRX_UCDR_FASTLOCK_SO_GAIN_RATE2 0x0e4
#define QSERDES_V10_60_TXRX_UCDR_FASTLOCK_SO_GAIN_RATE3 0x0e8
#define QSERDES_V10_60_TXRX_UCDR_FASTLOCK_SO_GAIN_RATE4 0x0ec
#define QSERDES_V10_60_TXRX_UCDR_PI_CTRL1 0x12c
#define QSERDES_V10_60_TXRX_UCDR_PI_CTRL2 0x130
#define QSERDES_V10_60_TXRX_UCDR_PI_CTRL3 0x134
#define QSERDES_V10_60_TXRX_UCDR_PI_CTRL4 0x138
#define QSERDES_V10_60_TXRX_SVS_MODE_CTRL 0x19c
#define QSERDES_V10_60_TXRX_RXCLK_DIV2_CTRL 0x1a0
#define QSERDES_V10_60_TXRX_RX_BAND_CTRL0 0x1a4
#define QSERDES_V10_60_TXRX_RX_TERM_BW_CTRL0 0x1ac
#define QSERDES_V10_60_TXRX_RX_TERM_BW_CTRL1 0x1b0
#define QSERDES_V10_60_TXRX_UCDR_FO_GAIN_RATE1 0x1b8
#define QSERDES_V10_60_TXRX_UCDR_FO_GAIN_RATE2 0x1bc
#define QSERDES_V10_60_TXRX_UCDR_FO_GAIN_RATE3 0x1c0
#define QSERDES_V10_60_TXRX_UCDR_FO_GAIN_RATE4 0x1c4
#define QSERDES_V10_60_TXRX_UCDR_SO_GAIN_RATE1 0x1d0
#define QSERDES_V10_60_TXRX_UCDR_SO_GAIN_RATE2 0x1d4
#define QSERDES_V10_60_TXRX_UCDR_SO_GAIN_RATE3 0x1d8
#define QSERDES_V10_60_TXRX_UCDR_SO_GAIN_RATE4 0x1dc
#define QSERDES_V10_60_TXRX_UCDR_PI_CONTROLS 0x1e4
#define QSERDES_V10_60_TXRX_AUXDATA_BIN_RATE3 0x200
#define QSERDES_V10_60_TXRX_AUXDATA_BIN_RATE4 0x204
#define QSERDES_V10_60_TXRX_EOM_MAX_ERR_LIMIT_LSB 0x218
#define QSERDES_V10_60_TXRX_EOM_MAX_ERR_LIMIT_MSB 0x21c
#define QSERDES_V10_60_TXRX_VGA_CAL_CNTRL1 0x280
#define QSERDES_V10_60_TXRX_VGA_CAL_MAN_VAL 0x288
#define QSERDES_V10_60_TXRX_GM_CAL 0x29c
#define QSERDES_V10_60_TXRX_RX_EQU_ADAPTOR_CNTRL6 0x2b8
#define QSERDES_V10_60_TXRX_SIGDET_ENABLES 0x2d4
#define QSERDES_V10_60_TXRX_SIGDET_CNTRL 0x2d8
#define QSERDES_V10_60_TXRX_SIGDET_LVL 0x2dc
#define QSERDES_V10_60_TXRX_SIGDET_DEGLITCH_CNTRL 0x2e0
#define QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B0 0x314
#define QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B1 0x318
#define QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B2 0x31c
#define QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B3 0x320
#define QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B4 0x324
#define QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B5 0x328
#define QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B6 0x32c
#define QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B7 0x330
#define QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B8 0x334
#define QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B9 0x338
#define QSERDES_V10_60_TXRX_RX_MODE_RATE_0_1_B10 0x33c
#define QSERDES_V10_60_TXRX_RX_MODE_RATE2_B0 0x340
#define QSERDES_V10_60_TXRX_RX_MODE_RATE2_B1 0x344
#define QSERDES_V10_60_TXRX_RX_MODE_RATE2_B2 0x348
#define QSERDES_V10_60_TXRX_RX_MODE_RATE2_B3 0x34c
#define QSERDES_V10_60_TXRX_RX_MODE_RATE2_B4 0x350
#define QSERDES_V10_60_TXRX_RX_MODE_RATE2_B5 0x354
#define QSERDES_V10_60_TXRX_RX_MODE_RATE2_B6 0x358
#define QSERDES_V10_60_TXRX_RX_MODE_RATE2_B7 0x35c
#define QSERDES_V10_60_TXRX_RX_MODE_RATE2_B8 0x360
#define QSERDES_V10_60_TXRX_RX_MODE_RATE2_B9 0x364
#define QSERDES_V10_60_TXRX_RX_MODE_RATE2_B10 0x368
#define QSERDES_V10_60_TXRX_RX_MODE_RATE3_B0 0x36c
#define QSERDES_V10_60_TXRX_RX_MODE_RATE3_B1 0x370
#define QSERDES_V10_60_TXRX_RX_MODE_RATE3_B2 0x374
#define QSERDES_V10_60_TXRX_RX_MODE_RATE3_B3 0x378
#define QSERDES_V10_60_TXRX_RX_MODE_RATE3_B4 0x37c
#define QSERDES_V10_60_TXRX_RX_MODE_RATE3_B5 0x380
#define QSERDES_V10_60_TXRX_RX_MODE_RATE3_B6 0x384
#define QSERDES_V10_60_TXRX_RX_MODE_RATE3_B7 0x388
#define QSERDES_V10_60_TXRX_RX_MODE_RATE3_B8 0x38c
#define QSERDES_V10_60_TXRX_RX_MODE_RATE3_B9 0x390
#define QSERDES_V10_60_TXRX_RX_MODE_RATE3_B10 0x394
#define QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B0 0x398
#define QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B1 0x39c
#define QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B2 0x3a0
#define QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B3 0x3a4
#define QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B4 0x3a8
#define QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B5 0x3ac
#define QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B6 0x3b0
#define QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B7 0x3b4
#define QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B8 0x3b8
#define QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B9 0x3bc
#define QSERDES_V10_60_TXRX_RX_MODE_RATE4_SA_B10 0x3c0
#define QSERDES_V10_60_TXRX_Q_PI_INTRINSIC_BIAS_RATE32 0x478
#define QSERDES_V10_60_TXRX_Q_PI_INTRINSIC_BIAS_RATE45 0x47c
#define QSERDES_V10_60_TXRX_SIGDET_CAL_CTRL1 0x4c8
#define QSERDES_V10_60_TXRX_SIGDET_CAL_CTRL2 0x4cc
#define QSERDES_V10_60_TXRX_SIGDET_CAL_TRIM 0x4d0
#define QSERDES_V10_60_TXRX_TX_BAND0 0x4e8
#define QSERDES_V10_60_TXRX_TX_BAND1 0x4ec
#define QSERDES_V10_60_TXRX_SEL_10B_8B 0x4f4
#define QSERDES_V10_60_TXRX_SEL_20B_10B 0x4f8
#define QSERDES_V10_60_TXRX_EQ_RCF_CTRL_RATE3 0x53c
#define QSERDES_V10_60_TXRX_EQ_RCF_CTRL_RATE4 0x540
#define QSERDES_V10_60_TXRX_PHPRE_CTRL 0x5e8
#endif

View File

@@ -29,9 +29,11 @@
#include "phy-qcom-qmp-pcs-ufs-v4.h"
#include "phy-qcom-qmp-pcs-ufs-v5.h"
#include "phy-qcom-qmp-pcs-ufs-v6.h"
#include "phy-qcom-qmp-pcs-ufs-v7.h"
#include "phy-qcom-qmp-qserdes-txrx-ufs-v6.h"
#include "phy-qcom-qmp-qserdes-txrx-ufs-v7.h"
#include "phy-qcom-qmp-qserdes-txrx-ufs-v8.h"
/* QPHY_PCS_READY_STATUS bit */
#define PCS_READY BIT(0)
@@ -84,6 +86,13 @@ static const unsigned int ufsphy_v6_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V6_PCS_UFS_POWER_DOWN_CONTROL,
};
static const unsigned int ufsphy_v7_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_START_CTRL] = QPHY_V7_PCS_UFS_PHY_START,
[QPHY_PCS_READY_STATUS] = QPHY_V7_PCS_UFS_READY_STATUS,
[QPHY_SW_RESET] = QPHY_V7_PCS_UFS_SW_RESET,
[QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V7_PCS_UFS_POWER_DOWN_CONTROL,
};
static const struct qmp_phy_init_tbl milos_ufsphy_serdes[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0xd9),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16),
@@ -1307,6 +1316,11 @@ static const struct regulator_bulk_data sm8750_ufsphy_vreg_l[] = {
{ .supply = "vdda-pll", .init_load_uA = 18300 },
};
static const struct regulator_bulk_data hawi_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 324000 },
{ .supply = "vdda-pll", .init_load_uA = 27000 },
};
static const struct qmp_ufs_offsets qmp_ufs_offsets = {
.serdes = 0,
.pcs = 0xc00,
@@ -1325,6 +1339,15 @@ static const struct qmp_ufs_offsets qmp_ufs_offsets_v6 = {
.rx2 = 0x1a00,
};
static const struct qmp_ufs_offsets qmp_ufs_offsets_v7 = {
.serdes = 0,
.pcs = 0x0400,
.tx = 0x2000,
.rx = 0x2000,
.tx2 = 0x3000,
.rx2 = 0x3000,
};
static const struct qmp_phy_cfg milos_ufsphy_cfg = {
.lanes = 2,
@@ -1845,6 +1868,119 @@ static const struct qmp_phy_cfg sm8750_ufsphy_cfg = {
};
static const struct qmp_phy_init_tbl hawi_ufsphy_serdes[] = {
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SYSCLK_EN_SEL, 0xd9),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CMN_CONFIG_1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_HSCLK_SEL_1, 0x11),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_HSCLK_HS_SWITCH_SEL_1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP_EN, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP_CFG, 0x60),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_IVCO, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_IVCO_MODE1, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CMN_IETRIM, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CMN_IPTRIM, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE_MAP, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE_CTRL, 0x40),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_ADAPTIVE_ANALOG_CONFIG, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DEC_START_MODE0, 0x41),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CP_CTRL_MODE0, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_RCTRL_MODE0, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_CCTRL_MODE0, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CP_CTRL_ADAPTIVE_MODE0, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_RCCTRL_ADAPTIVE_MODE0, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_CCTRL_ADAPTIVE_MODE0, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP1_MODE0, 0x7f),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP2_MODE0, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x92),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DEC_START_MODE1, 0x4c),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CP_CTRL_MODE1, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_RCTRL_MODE1, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_CCTRL_MODE1, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CP_CTRL_ADAPTIVE_MODE1, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_RCCTRL_ADAPTIVE_MODE1, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_CCTRL_ADAPTIVE_MODE1, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP1_MODE1, 0x99),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP2_MODE1, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xbe),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x23),
};
static const struct qmp_phy_init_tbl hawi_ufsphy_tx[] = {
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_TX_LANE_MODE_1, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_TX_RES_CODE_LANE_OFFSET_TX, 0x07),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_TX_RES_CODE_LANE_OFFSET_RX, 0x17),
};
static const struct qmp_phy_init_tbl hawi_ufsphy_rx[] = {
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_UCDR_FO_GAIN_RATE2, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_UCDR_FO_GAIN_RATE4, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_UCDR_SO_GAIN_RATE4, 0x04),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x14),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_UCDR_PI_CONTROLS, 0x07),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_OFFSET_ADAPTOR_CNTRL3, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE4, 0x02),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_UCDR_FASTLOCK_FO_GAIN_RATE4, 0x1c),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_UCDR_FASTLOCK_SO_GAIN_RATE4, 0x06),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_VGA_CAL_MAN_VAL, 0x8e),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_EQU_ADAPTOR_CNTRL4, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_MODE_RATE_0_1_B4, 0xb8),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_MODE_RATE4_SA_B7, 0x66),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_MODE_RATE4_SA_B9, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_MODE_RATE4_SB_B7, 0x66),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_MODE_RATE4_SB_B9, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_MODE_RATE5_SA_B7, 0x66),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_MODE_RATE5_SA_B9, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_MODE_RATE5_SB_B7, 0x66),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_MODE_RATE5_SB_B9, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_UCDR_SO_SATURATION, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_TERM_BW_CTRL0, 0xfa),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_DLL0_FTUNE_CTRL, 0x30),
QMP_PHY_INIT_CFG(QSERDES_UFS_V8_RX_SIGDET_CAL_TRIM, 0x77),
};
static const struct qmp_phy_init_tbl hawi_ufsphy_pcs[] = {
QMP_PHY_INIT_CFG(QPHY_V7_PCS_UFS_TX_MID_TERM_CTRL1, 0x43),
QMP_PHY_INIT_CFG(QPHY_V7_PCS_UFS_PCS_CTRL1, 0x42),
QMP_PHY_INIT_CFG(QPHY_V7_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f),
QMP_PHY_INIT_CFG(QPHY_V7_PCS_UFS_RX_SIGDET_CTRL2, 0x68),
QMP_PHY_INIT_CFG(QPHY_V7_PCS_UFS_MULTI_LANE_CTRL1, 0x02),
};
static const struct qmp_phy_init_tbl hawi_ufsphy_g5_pcs[] = {
QMP_PHY_INIT_CFG(QPHY_V7_PCS_UFS_PLL_CNTL, 0x3b),
QMP_PHY_INIT_CFG(QPHY_V7_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x05),
QMP_PHY_INIT_CFG(QPHY_V7_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x05),
};
static const struct qmp_phy_cfg hawi_ufsphy_cfg = {
.lanes = 2,
.offsets = &qmp_ufs_offsets_v7,
.max_supported_gear = UFS_HS_G5,
.tbls = {
.serdes = hawi_ufsphy_serdes,
.serdes_num = ARRAY_SIZE(hawi_ufsphy_serdes),
.tx = hawi_ufsphy_tx,
.tx_num = ARRAY_SIZE(hawi_ufsphy_tx),
.rx = hawi_ufsphy_rx,
.rx_num = ARRAY_SIZE(hawi_ufsphy_rx),
.pcs = hawi_ufsphy_pcs,
.pcs_num = ARRAY_SIZE(hawi_ufsphy_pcs),
},
.tbls_hs_overlay[0] = {
.pcs = hawi_ufsphy_g5_pcs,
.pcs_num = ARRAY_SIZE(hawi_ufsphy_g5_pcs),
.max_gear = UFS_HS_G5,
},
.vreg_list = hawi_ufsphy_vreg_l,
.num_vregs = ARRAY_SIZE(hawi_ufsphy_vreg_l),
.regs = ufsphy_v7_regs_layout,
};
static void qmp_ufs_serdes_init(struct qmp_ufs *qmp, const struct qmp_phy_cfg_tbls *tbls)
{
void __iomem *serdes = qmp->serdes;
@@ -2259,6 +2395,9 @@ static int qmp_ufs_probe(struct platform_device *pdev)
static const struct of_device_id qmp_ufs_of_match_table[] = {
{
.compatible = "qcom,hawi-qmp-ufs-phy",
.data = &hawi_ufsphy_cfg,
}, {
.compatible = "qcom,milos-qmp-ufs-phy",
.data = &milos_ufsphy_cfg,
}, {

View File

@@ -542,6 +542,8 @@ struct qmp_usb {
enum phy_mode mode;
bool phy_initialized;
struct phy *phy;
struct clk_fixed_rate pipe_clk_fixed;
@@ -895,6 +897,7 @@ static int qmp_usb_legacy_power_off(struct phy *phy)
static int qmp_usb_legacy_enable(struct phy *phy)
{
struct qmp_usb *qmp = phy_get_drvdata(phy);
int ret;
ret = qmp_usb_legacy_init(phy);
@@ -904,14 +907,19 @@ static int qmp_usb_legacy_enable(struct phy *phy)
ret = qmp_usb_legacy_power_on(phy);
if (ret)
qmp_usb_legacy_exit(phy);
else
qmp->phy_initialized = true;
return ret;
}
static int qmp_usb_legacy_disable(struct phy *phy)
{
struct qmp_usb *qmp = phy_get_drvdata(phy);
int ret;
qmp->phy_initialized = false;
ret = qmp_usb_legacy_power_off(phy);
if (ret)
return ret;
@@ -988,7 +996,7 @@ static int __maybe_unused qmp_usb_legacy_runtime_suspend(struct device *dev)
dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qmp->mode);
if (!qmp->phy->init_count) {
if (!qmp->phy_initialized) {
dev_vdbg(dev, "PHY not initialized, bailing out\n");
return 0;
}
@@ -1009,7 +1017,7 @@ static int __maybe_unused qmp_usb_legacy_runtime_resume(struct device *dev)
dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qmp->mode);
if (!qmp->phy->init_count) {
if (!qmp->phy_initialized) {
dev_vdbg(dev, "PHY not initialized, bailing out\n");
return 0;
}
@@ -1277,10 +1285,16 @@ static int qmp_usb_legacy_probe(struct platform_device *pdev)
if (ret)
goto err_node_put;
/*
* Enable runtime PM before creating the PHY, phy_create() only enables
* it on the PHY device if already enabled on the parent. Hold a usage
* reference so callbacks cannot run before qmp->phy is assigned.
*/
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
ret = devm_pm_runtime_enable(dev);
if (ret)
goto err_node_put;
goto err_pm_put;
/*
* Prevent runtime pm from being ON by default. Users can enable
* it using power/control in sysfs.
@@ -1289,23 +1303,31 @@ static int qmp_usb_legacy_probe(struct platform_device *pdev)
ret = phy_pipe_clk_register(qmp, np);
if (ret)
goto err_node_put;
goto err_pm_put;
qmp->phy = devm_phy_create(dev, np, &qmp_usb_legacy_phy_ops);
if (IS_ERR(qmp->phy)) {
ret = PTR_ERR(qmp->phy);
dev_err(dev, "failed to create PHY: %d\n", ret);
goto err_node_put;
goto err_pm_put;
}
phy_set_drvdata(qmp->phy, qmp);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(phy_provider)) {
ret = PTR_ERR(phy_provider);
goto err_pm_put;
}
of_node_put(np);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
pm_runtime_put(dev);
return PTR_ERR_OR_ZERO(phy_provider);
return 0;
err_pm_put:
pm_runtime_put_noidle(dev);
err_node_put:
of_node_put(np);
return ret;

View File

@@ -1434,6 +1434,8 @@ struct qmp_usb {
enum phy_mode mode;
bool phy_initialized;
struct phy *phy;
struct clk_fixed_rate pipe_clk_fixed;
@@ -2009,6 +2011,7 @@ static int qmp_usb_power_off(struct phy *phy)
static int qmp_usb_enable(struct phy *phy)
{
struct qmp_usb *qmp = phy_get_drvdata(phy);
int ret;
ret = qmp_usb_init(phy);
@@ -2018,14 +2021,19 @@ static int qmp_usb_enable(struct phy *phy)
ret = qmp_usb_power_on(phy);
if (ret)
qmp_usb_exit(phy);
else
qmp->phy_initialized = true;
return ret;
}
static int qmp_usb_disable(struct phy *phy)
{
struct qmp_usb *qmp = phy_get_drvdata(phy);
int ret;
qmp->phy_initialized = false;
ret = qmp_usb_power_off(phy);
if (ret)
return ret;
@@ -2101,7 +2109,7 @@ static int __maybe_unused qmp_usb_runtime_suspend(struct device *dev)
dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qmp->mode);
if (!qmp->phy->init_count) {
if (!qmp->phy_initialized) {
dev_vdbg(dev, "PHY not initialized, bailing out\n");
return 0;
}
@@ -2121,7 +2129,7 @@ static int __maybe_unused qmp_usb_runtime_resume(struct device *dev)
dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qmp->mode);
if (!qmp->phy->init_count) {
if (!qmp->phy_initialized) {
dev_vdbg(dev, "PHY not initialized, bailing out\n");
return 0;
}
@@ -2411,10 +2419,16 @@ static int qmp_usb_probe(struct platform_device *pdev)
if (ret)
goto err_node_put;
/*
* Enable runtime PM before creating the PHY, phy_create() only enables
* it on the PHY device if already enabled on the parent. Hold a usage
* reference so callbacks cannot run before qmp->phy is assigned.
*/
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
ret = devm_pm_runtime_enable(dev);
if (ret)
goto err_node_put;
goto err_pm_put;
/*
* Prevent runtime pm from being ON by default. Users can enable
* it using power/control in sysfs.
@@ -2423,23 +2437,31 @@ static int qmp_usb_probe(struct platform_device *pdev)
ret = phy_pipe_clk_register(qmp, np);
if (ret)
goto err_node_put;
goto err_pm_put;
qmp->phy = devm_phy_create(dev, np, &qmp_usb_phy_ops);
if (IS_ERR(qmp->phy)) {
ret = PTR_ERR(qmp->phy);
dev_err(dev, "failed to create PHY: %d\n", ret);
goto err_node_put;
goto err_pm_put;
}
phy_set_drvdata(qmp->phy, qmp);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(phy_provider)) {
ret = PTR_ERR(phy_provider);
goto err_pm_put;
}
of_node_put(np);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
pm_runtime_put(dev);
return PTR_ERR_OR_ZERO(phy_provider);
return 0;
err_pm_put:
pm_runtime_put_noidle(dev);
err_node_put:
of_node_put(np);
return ret;

View File

@@ -512,10 +512,14 @@ static const char * const usb3phy_reset_l[] = {
"phy_phy", "phy",
};
static const char * const usb3dpphy_reset_l[] = {
static const char * const qcs615_usb3dpphy_reset_l[] = {
"phy_phy", "dp_phy",
};
static const char * const shikra_usb3dpphy_reset_l[] = {
"phy_phy", "dp_phy", "phy",
};
static const struct regulator_bulk_data qmp_phy_msm8998_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 68600 },
{ .supply = "vdda-pll", .init_load_uA = 14200 },
@@ -680,8 +684,48 @@ static const struct qmp_phy_cfg qcs615_usb3dp_phy_cfg = {
.configure_dp_phy = qcs615_qmp_configure_dp_phy,
.calibrate_dp_phy = qcs615_qmp_calibrate_dp_phy,
.reset_list = usb3dpphy_reset_l,
.num_resets = ARRAY_SIZE(usb3dpphy_reset_l),
.reset_list = qcs615_usb3dpphy_reset_l,
.num_resets = ARRAY_SIZE(qcs615_usb3dpphy_reset_l),
.vreg_list = qmp_phy_qcs615_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_qcs615_vreg_l),
};
static const struct qmp_phy_cfg shikra_usb3dp_phy_cfg = {
.offsets = &qmp_usbc_usb3dp_offsets_qcs615,
.serdes_tbl = qcm2290_usb3_serdes_tbl,
.serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl),
.tx_tbl = qcm2290_usb3_tx_tbl,
.tx_tbl_num = ARRAY_SIZE(qcm2290_usb3_tx_tbl),
.rx_tbl = qcm2290_usb3_rx_tbl,
.rx_tbl_num = ARRAY_SIZE(qcm2290_usb3_rx_tbl),
.pcs_tbl = qcm2290_usb3_pcs_tbl,
.pcs_tbl_num = ARRAY_SIZE(qcm2290_usb3_pcs_tbl),
.regs = qmp_v3_usb3phy_regs_layout_qcm2290,
.dp_serdes_tbl = qcs615_dp_serdes_tbl,
.dp_serdes_tbl_num = ARRAY_SIZE(qcs615_dp_serdes_tbl),
.dp_tx_tbl = qcs615_dp_tx_tbl,
.dp_tx_tbl_num = ARRAY_SIZE(qcs615_dp_tx_tbl),
.serdes_tbl_rbr = qcs615_dp_serdes_tbl_rbr,
.serdes_tbl_rbr_num = ARRAY_SIZE(qcs615_dp_serdes_tbl_rbr),
.serdes_tbl_hbr = qcs615_dp_serdes_tbl_hbr,
.serdes_tbl_hbr_num = ARRAY_SIZE(qcs615_dp_serdes_tbl_hbr),
.serdes_tbl_hbr2 = qcs615_dp_serdes_tbl_hbr2,
.serdes_tbl_hbr2_num = ARRAY_SIZE(qcs615_dp_serdes_tbl_hbr2),
.swing_tbl = &qcs615_dp_voltage_swing_hbr2_rbr,
.pre_emphasis_tbl = &qcs615_dp_pre_emphasis_hbr2_rbr,
.dp_aux_init = qcs615_qmp_dp_aux_init,
.configure_dp_tx = qcs615_qmp_configure_dp_tx,
.configure_dp_phy = qcs615_qmp_configure_dp_phy,
.calibrate_dp_phy = qcs615_qmp_calibrate_dp_phy,
.reset_list = shikra_usb3dpphy_reset_l,
.num_resets = ARRAY_SIZE(shikra_usb3dpphy_reset_l),
.vreg_list = qmp_phy_qcs615_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_qcs615_vreg_l),
};
@@ -1959,10 +2003,16 @@ static int qmp_usbc_probe(struct platform_device *pdev)
if (ret)
goto err_node_put;
/*
* Enable runtime PM before creating the PHYs, phy_create() only enables
* it on the PHY devices if already enabled on the parent. Hold a usage
* reference so callbacks cannot run until the PHY is ready.
*/
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
ret = devm_pm_runtime_enable(dev);
if (ret)
goto err_node_put;
goto err_pm_put;
/*
* Prevent runtime pm from being ON by default. Users can enable
* it using power/control in sysfs.
@@ -1971,13 +2021,13 @@ static int qmp_usbc_probe(struct platform_device *pdev)
ret = qmp_usbc_register_clocks(qmp, np);
if (ret)
goto err_node_put;
goto err_pm_put;
qmp->usb_phy = devm_phy_create(dev, np, &qmp_usbc_usb_phy_ops);
if (IS_ERR(qmp->usb_phy)) {
ret = PTR_ERR(qmp->usb_phy);
dev_err(dev, "failed to create PHY: %d\n", ret);
goto err_node_put;
goto err_pm_put;
}
phy_set_drvdata(qmp->usb_phy, qmp);
@@ -1987,17 +2037,25 @@ static int qmp_usbc_probe(struct platform_device *pdev)
if (IS_ERR(qmp->dp_phy)) {
ret = PTR_ERR(qmp->dp_phy);
dev_err(dev, "failed to create PHY: %d\n", ret);
goto err_node_put;
goto err_pm_put;
}
phy_set_drvdata(qmp->dp_phy, qmp);
}
phy_provider = devm_of_phy_provider_register(dev, qmp_usbc_phy_xlate);
if (IS_ERR(phy_provider)) {
ret = PTR_ERR(phy_provider);
goto err_pm_put;
}
of_node_put(np);
phy_provider = devm_of_phy_provider_register(dev, qmp_usbc_phy_xlate);
pm_runtime_put(dev);
return PTR_ERR_OR_ZERO(phy_provider);
return 0;
err_pm_put:
pm_runtime_put_noidle(dev);
err_node_put:
of_node_put(np);
return ret;
@@ -2019,6 +2077,9 @@ static const struct of_device_id qmp_usbc_of_match_table[] = {
}, {
.compatible = "qcom,sdm660-qmp-usb3-phy",
.data = &sdm660_usb3phy_cfg,
}, {
.compatible = "qcom,shikra-qmp-usb3-dp-phy",
.data = &shikra_usb3dp_phy_cfg,
}, {
.compatible = "qcom,sm6115-qmp-usb3-phy",
.data = &qcm2290_usb3phy_cfg,

View File

@@ -36,6 +36,12 @@
#include "phy-qcom-qmp-qserdes-txrx-v8.h"
#include "phy-qcom-qmp-qserdes-lalb-v8.h"
#include "phy-qcom-qmp-qserdes-com-v10.h"
#include "phy-qcom-qmp-qserdes-txrx-v10.h"
#include "phy-qcom-qmp-qserdes-com-v10_60.h"
#include "phy-qcom-qmp-qserdes-txrx-v10_60.h"
#include "phy-qcom-qmp-qserdes-pll.h"
#include "phy-qcom-qmp-pcs-v2.h"
@@ -62,6 +68,10 @@
#include "phy-qcom-qmp-pcs-v8_50.h"
#include "phy-qcom-qmp-pcs-v10.h"
#include "phy-qcom-qmp-pcs-v10_60.h"
/* QPHY_SW_RESET bit */
#define SW_RESET BIT(0)
/* QPHY_POWER_DOWN_CONTROL */

View File

@@ -381,6 +381,17 @@ static const struct qusb2_phy_cfg sdm660_phy_cfg = {
.autoresume_en = BIT(3),
};
static const struct qusb2_phy_cfg shikra_phy_cfg = {
.tbl = qcs615_init_tbl,
.tbl_num = ARRAY_SIZE(qcs615_init_tbl),
.regs = msm8996_regs_layout,
.has_pll_test = true,
.se_clk_scheme_default = true,
.disable_ctrl = CLAMP_N_EN | FREEZIO_N | POWER_DOWN,
.mask_core_ready = PLL_LOCKED,
};
static const struct qusb2_phy_cfg sm6115_phy_cfg = {
.tbl = sm6115_init_tbl,
.tbl_num = ARRAY_SIZE(sm6115_init_tbl),
@@ -958,6 +969,9 @@ static const struct of_device_id qusb2_phy_of_match_table[] = {
}, {
.compatible = "qcom,sdm660-qusb2-phy",
.data = &sdm660_phy_cfg,
}, {
.compatible = "qcom,shikra-qusb2-phy",
.data = &shikra_phy_cfg,
}, {
.compatible = "qcom,sm4250-qusb2-phy",
.data = &sm6115_phy_cfg,

View File

@@ -11,6 +11,7 @@
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include "phy-qcom-qmp-pcs-sgmii.h"
#include "phy-qcom-qmp-qserdes-com-v5.h"
@@ -26,7 +27,15 @@
#define QSERDES_PCS_SGMIIPHY_READY BIT(7)
#define QSERDES_COM_C_PLL_LOCKED BIT(1)
static const struct regulator_bulk_data qcom_dwmac_sgmii_phy_vregs[] = {
{ .supply = "vdda-0p9", .init_load_uA = 46000 },
{ .supply = "vdda-1p2", .init_load_uA = 15000 },
};
#define QCOM_SGMII_NUM_SUPPLIES ARRAY_SIZE(qcom_dwmac_sgmii_phy_vregs)
struct qcom_dwmac_sgmii_phy_data {
struct regulator_bulk_data *vregs;
struct regmap *regmap;
struct clk *refclk;
phy_interface_t interface;
@@ -273,13 +282,24 @@ static int qcom_dwmac_sgmii_phy_power_on(struct phy *phy)
struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
int ret;
ret = clk_prepare_enable(data->refclk);
if (ret < 0)
ret = regulator_bulk_enable(QCOM_SGMII_NUM_SUPPLIES, data->vregs);
if (ret)
return ret;
ret = clk_prepare_enable(data->refclk);
if (ret)
goto err_disable_regulators;
ret = qcom_dwmac_sgmii_phy_calibrate(phy);
if (ret < 0)
clk_disable_unprepare(data->refclk);
if (ret)
goto err_disable_clk;
return 0;
err_disable_clk:
clk_disable_unprepare(data->refclk);
err_disable_regulators:
regulator_bulk_disable(QCOM_SGMII_NUM_SUPPLIES, data->vregs);
return ret;
}
@@ -296,6 +316,8 @@ static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy)
clk_disable_unprepare(data->refclk);
regulator_bulk_disable(QCOM_SGMII_NUM_SUPPLIES, data->vregs);
return 0;
}
@@ -357,6 +379,7 @@ static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev)
struct phy_provider *provider;
void __iomem *base;
struct phy *phy;
int ret;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
@@ -381,6 +404,12 @@ static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev)
if (IS_ERR(data->refclk))
return PTR_ERR(data->refclk);
ret = devm_regulator_bulk_get_const(dev, QCOM_SGMII_NUM_SUPPLIES,
qcom_dwmac_sgmii_phy_vregs,
&data->vregs);
if (ret)
return ret;
provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(provider))
return PTR_ERR(provider);

View File

@@ -599,8 +599,18 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev)
return dev_err_probe(dev, ret,
"failed to get regulator supplies\n");
/*
* Enable runtime PM before creating the PHY, phy_create() only enables
* it on the PHY device if already enabled on the parent. Hold a usage
* reference so callbacks cannot run before the PHY is ready.
*/
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
ret = devm_pm_runtime_enable(dev);
if (ret) {
pm_runtime_put_noidle(dev);
return ret;
}
/*
* Prevent runtime pm from being ON by default. Users can enable
* it using power/control in sysfs.
@@ -611,6 +621,7 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev)
if (IS_ERR(generic_phy)) {
ret = PTR_ERR(generic_phy);
dev_err(dev, "failed to create phy, %d\n", ret);
pm_runtime_put_noidle(dev);
return ret;
}
hsphy->phy = generic_phy;
@@ -620,12 +631,15 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev)
qcom_snps_hsphy_read_override_param_seq(dev);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (!IS_ERR(phy_provider))
dev_dbg(dev, "Registered Qcom-SNPS HS phy\n");
else
pm_runtime_disable(dev);
if (IS_ERR(phy_provider)) {
pm_runtime_put_noidle(dev);
return PTR_ERR(phy_provider);
}
return PTR_ERR_OR_ZERO(phy_provider);
dev_dbg(dev, "Registered Qcom-SNPS HS phy\n");
pm_runtime_put(dev);
return 0;
}
static struct platform_driver qcom_snps_hsphy_driver = {

View File

@@ -405,7 +405,6 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev)
data->gen2_phy_ops);
if (IS_ERR(phy->phy)) {
dev_err(dev, "Failed to create PHY\n");
of_node_put(np);
return PTR_ERR(phy->phy);
}
phy_set_drvdata(phy->phy, phy);

View File

@@ -721,6 +721,10 @@ static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = {
.compatible = "renesas,usb2-phy-r9a08g045",
.data = &rz_g3s_phy_usb2_data,
},
{
.compatible = "renesas,usb2-phy-r9a08g046",
.data = &rz_g3s_phy_usb2_data,
},
{
.compatible = "renesas,usb2-phy-r9a09g057",
.data = &rz_v2h_phy_usb2_data,
@@ -898,18 +902,29 @@ static int rcar_gen3_phy_usb2_vbus_regulator_get_exclusive_enable(struct rcar_ge
int ret;
channel->vbus = devm_regulator_get_exclusive(dev, "vbus");
if (IS_ERR(channel->vbus))
return PTR_ERR(channel->vbus);
if (IS_ERR(channel->vbus)) {
ret = PTR_ERR(channel->vbus);
/* If vbus-regulator node was present vbus regulator should be available */
if (channel->otg_internal_reg)
return ret;
if (ret == -EPROBE_DEFER)
return ret;
if (!enable)
return 0;
}
ret = regulator_enable(channel->vbus);
if (ret)
return ret;
if (enable) {
ret = regulator_enable(channel->vbus);
if (ret)
return ret;
}
return devm_add_action_or_reset(dev, rcar_gen3_phy_usb2_vbus_disable_action,
channel->vbus);
if (regulator_is_enabled(channel->vbus))
return devm_add_action_or_reset(dev, rcar_gen3_phy_usb2_vbus_disable_action,
channel->vbus);
return 0;
}
static int rcar_gen3_phy_usb2_vbus_regulator_register(struct rcar_gen3_chan *channel)

View File

@@ -69,6 +69,10 @@
#define RK1808_CSIDPHY_CLK_CALIB_EN 0x168
#define RK3568_CSIDPHY_CLK_CALIB_EN 0x168
#define CSIDPHY_LANE_CLK_3_PHASE 0x38
#define CSIDPHY_CLK_PHASE_MASK GENMASK(6, 4)
#define CSIDPHY_CLK_PHASE_DEFAULT 3
#define RESETS_MAX 2
/*
@@ -151,6 +155,7 @@ struct rockchip_inno_csidphy {
const struct dphy_drv_data *drv_data;
struct phy_configure_opts_mipi_dphy config;
u8 hsfreq;
int clk_phase;
};
static inline void write_grf_reg(struct rockchip_inno_csidphy *priv,
@@ -170,7 +175,7 @@ static const struct hsfreq_range rk1808_mipidphy_hsfreq_ranges[] = {
{ 299, 0x06}, { 399, 0x08}, { 499, 0x0b}, { 599, 0x0e},
{ 699, 0x10}, { 799, 0x12}, { 999, 0x16}, {1199, 0x1e},
{1399, 0x23}, {1599, 0x2d}, {1799, 0x32}, {1999, 0x37},
{2199, 0x3c}, {2399, 0x41}, {2499, 0x46}
{2199, 0x3c}, {2399, 0x41}, {2500, 0x46}
};
static const struct hsfreq_range rk3326_mipidphy_hsfreq_ranges[] = {
@@ -304,6 +309,13 @@ static int rockchip_inno_csidphy_power_on(struct phy *phy)
rockchip_inno_csidphy_ths_settle(priv, priv->hsfreq,
CSIDPHY_LANE_THS_SETTLE(i));
if (priv->clk_phase >= 0) {
val = readl(priv->phy_base + CSIDPHY_LANE_CLK_3_PHASE);
val &= ~CSIDPHY_CLK_PHASE_MASK;
val |= FIELD_PREP(CSIDPHY_CLK_PHASE_MASK, priv->clk_phase);
writel(val, priv->phy_base + CSIDPHY_LANE_CLK_3_PHASE);
}
write_grf_reg(priv, GRF_DPHY_CSIPHY_CLKLANE_EN, 0x1);
write_grf_reg(priv, GRF_DPHY_CSIPHY_DATALANE_EN,
GENMASK(priv->config.lanes - 1, 0));
@@ -449,6 +461,7 @@ static int rockchip_inno_csidphy_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct phy_provider *phy_provider;
struct phy *phy;
u32 phase;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -464,6 +477,18 @@ static int rockchip_inno_csidphy_probe(struct platform_device *pdev)
return -ENODEV;
}
priv->clk_phase = -1;
if (device_property_read_u32(dev, "rockchip,clk-lane-phase",
&phase) == 0) {
if (phase > 7) {
dev_warn(dev,
"invalid rockchip,clk-lane-phase %u, using default %u\n",
phase, CSIDPHY_CLK_PHASE_DEFAULT);
phase = CSIDPHY_CLK_PHASE_DEFAULT;
}
priv->clk_phase = phase;
}
priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
"rockchip,grf");
if (IS_ERR(priv->grf)) {

View File

@@ -245,6 +245,7 @@ struct inno_hdmi_phy {
struct clk *phyclk;
unsigned long pixclock;
unsigned long tmdsclock;
unsigned long opts_tmds_char_rate;
};
struct pre_pll_config {
@@ -554,19 +555,10 @@ static inline void inno_update_bits(struct inno_hdmi_phy *inno, u8 reg,
static unsigned long inno_hdmi_phy_get_tmdsclk(struct inno_hdmi_phy *inno,
unsigned long rate)
{
int bus_width = phy_get_bus_width(inno->phy);
if (inno->opts_tmds_char_rate)
return inno->opts_tmds_char_rate;
switch (bus_width) {
case 4:
case 5:
case 6:
case 10:
case 12:
case 16:
return (u64)rate * bus_width / 8;
default:
return rate;
}
return rate;
}
static irqreturn_t inno_hdmi_phy_rk3328_hardirq(int irq, void *dev_id)
@@ -602,6 +594,57 @@ static irqreturn_t inno_hdmi_phy_rk3328_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
/*
* phy_validate() is expected to be called from encoder atomic_check(), before
* the hdmiphy pixel clock is known. Without knowing the actual pixel clock, we
* cannot do full validation of the configuration. Instead, we do a simple check
* that the pre-pll table contains an entry for the requested TMDS char rate.
*/
static int inno_hdmi_phy_validate(struct phy *phy, enum phy_mode mode,
int submode, union phy_configure_opts *opts)
{
const struct pre_pll_config *cfg = pre_pll_cfg_table;
unsigned long tmdsclock;
if (!(mode == PHY_MODE_HDMI && submode == PHY_HDMI_MODE_TMDS))
return -EINVAL;
if (!opts)
return -EINVAL;
if (!opts->hdmi.tmds_char_rate || opts->hdmi.tmds_char_rate > 594000000)
return -EINVAL;
tmdsclock = opts->hdmi.tmds_char_rate;
for (; cfg->pixclock != 0; cfg++)
if (cfg->tmdsclock == tmdsclock)
return 0;
return -EINVAL;
}
/*
* phy_configure() is expected to be called from encoder atomic_set_mode(),
* before the hdmiphy pixel clock is known. Store the requested TMDS character
* rate, so that it can be used later in power_on() and/or set_rate() when the
* pixel clock is known.
*/
static int inno_hdmi_phy_configure(struct phy *phy,
union phy_configure_opts *opts)
{
struct inno_hdmi_phy *inno = phy_get_drvdata(phy);
int ret;
ret = inno_hdmi_phy_validate(phy, phy_get_mode(phy),
PHY_HDMI_MODE_TMDS, opts);
if (ret)
return ret;
inno->opts_tmds_char_rate = opts->hdmi.tmds_char_rate;
return 0;
}
static int inno_hdmi_phy_power_on(struct phy *phy)
{
struct inno_hdmi_phy *inno = phy_get_drvdata(phy);
@@ -670,6 +713,8 @@ static const struct phy_ops inno_hdmi_phy_ops = {
.owner = THIS_MODULE,
.power_on = inno_hdmi_phy_power_on,
.power_off = inno_hdmi_phy_power_off,
.configure = inno_hdmi_phy_configure,
.validate = inno_hdmi_phy_validate,
};
static const
@@ -1392,7 +1437,7 @@ static int inno_hdmi_phy_probe(struct platform_device *pdev)
}
phy_set_drvdata(inno->phy, inno);
phy_set_bus_width(inno->phy, 8);
phy_set_mode_ext(inno->phy, PHY_MODE_HDMI, PHY_HDMI_MODE_TMDS);
if (inno->plat_data->ops->init) {
ret = inno->plat_data->ops->init(inno);

View File

@@ -1526,7 +1526,7 @@ static const struct regmap_config samsung_mipi_dcphy_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.max_register = 0x10000,
.max_register = 0xfffc,
};
static struct phy *samsung_mipi_dcphy_xlate(struct device *dev,

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd.
* Copyright (c) 2024 Collabora Ltd.
* Copyright (c) 2024-2026 Collabora Ltd.
*
* Author: Algea Cao <algea.cao@rock-chips.com>
* Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
@@ -10,6 +10,7 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/hw_bitfield.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -52,6 +53,12 @@
/* CMN_REG(001e) */
#define LCPLL_PI_EN_MASK BIT(5)
#define LCPLL_100M_CLK_EN_MASK BIT(0)
/* CMN_REG(0022) */
#define ANA_LCPLL_PMS_PDIV_MASK GENMASK(7, 4)
#define ANA_LCPLL_PMS_REFDIV_MASK GENMASK(3, 0)
/* CMN_REG(0023) */
#define LCPLL_PMS_SDIV_RBR_MASK GENMASK(7, 4)
#define LCPLL_PMS_SDIV_HBR_MASK GENMASK(3, 0)
/* CMN_REG(0025) */
#define LCPLL_PMS_IQDIV_RSTN_MASK BIT(4)
/* CMN_REG(0028) */
@@ -413,7 +420,7 @@ struct rk_hdptx_phy {
/* clk provider */
struct clk_hw hw;
bool restrict_rate_change;
bool pll_config_dirty;
atomic_t usage_count;
@@ -949,7 +956,9 @@ static void rk_hdptx_pre_power_up(struct rk_hdptx_phy *hdptx)
reset_control_assert(hdptx->rsts[RST_CMN].rstc);
reset_control_assert(hdptx->rsts[RST_INIT].rstc);
val = (HDPTX_I_PLL_EN | HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16;
val = (FIELD_PREP_WM16(HDPTX_I_PLL_EN, 0) |
FIELD_PREP_WM16(HDPTX_I_BIAS_EN, 0) |
FIELD_PREP_WM16(HDPTX_I_BGR_EN, 0));
regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
}
@@ -960,8 +969,8 @@ static int rk_hdptx_post_enable_lane(struct rk_hdptx_phy *hdptx)
reset_control_deassert(hdptx->rsts[RST_LANE].rstc);
val = (HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16 |
HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN;
val = (FIELD_PREP_WM16(HDPTX_I_BIAS_EN, 1) |
FIELD_PREP_WM16(HDPTX_I_BGR_EN, 1));
regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
/* 3 lanes FRL mode */
@@ -990,16 +999,15 @@ static int rk_hdptx_post_enable_pll(struct rk_hdptx_phy *hdptx)
u32 val;
int ret;
val = (HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16 |
HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN;
val = (FIELD_PREP_WM16(HDPTX_I_BIAS_EN, 1) |
FIELD_PREP_WM16(HDPTX_I_BGR_EN, 1));
regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
usleep_range(10, 15);
reset_control_deassert(hdptx->rsts[RST_INIT].rstc);
usleep_range(10, 15);
val = HDPTX_I_PLL_EN << 16 | HDPTX_I_PLL_EN;
regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
regmap_write(hdptx->grf, GRF_HDPTX_CON0, FIELD_PREP_WM16(HDPTX_I_PLL_EN, 1));
usleep_range(10, 15);
reset_control_deassert(hdptx->rsts[RST_CMN].rstc);
@@ -1037,7 +1045,9 @@ static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx)
reset_control_assert(hdptx->rsts[RST_CMN].rstc);
reset_control_assert(hdptx->rsts[RST_INIT].rstc);
val = (HDPTX_I_PLL_EN | HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16;
val = (FIELD_PREP_WM16(HDPTX_I_PLL_EN, 0) |
FIELD_PREP_WM16(HDPTX_I_BIAS_EN, 0) |
FIELD_PREP_WM16(HDPTX_I_BGR_EN, 0));
regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
}
@@ -1135,7 +1145,7 @@ static int rk_hdptx_frl_lcpll_cmn_config(struct rk_hdptx_phy *hdptx)
rk_hdptx_pre_power_up(hdptx);
regmap_write(hdptx->grf, GRF_HDPTX_CON0, LC_REF_CLK_SEL << 16);
regmap_write(hdptx->grf, GRF_HDPTX_CON0, FIELD_PREP_WM16(LC_REF_CLK_SEL, 0));
rk_hdptx_multi_reg_write(hdptx, rk_hdptx_common_cmn_init_seq);
rk_hdptx_multi_reg_write(hdptx, rk_hdptx_frl_lcpll_cmn_init_seq);
@@ -1153,9 +1163,11 @@ static int rk_hdptx_frl_lcpll_cmn_config(struct rk_hdptx_phy *hdptx)
regmap_write(hdptx->regmap, CMN_REG(0020), cfg->pms_mdiv);
regmap_write(hdptx->regmap, CMN_REG(0021), cfg->pms_mdiv_afc);
regmap_write(hdptx->regmap, CMN_REG(0022),
(cfg->pms_pdiv << 4) | cfg->pms_refdiv);
FIELD_PREP(ANA_LCPLL_PMS_PDIV_MASK, cfg->pms_pdiv) |
FIELD_PREP(ANA_LCPLL_PMS_REFDIV_MASK, cfg->pms_refdiv));
regmap_write(hdptx->regmap, CMN_REG(0023),
(cfg->pms_sdiv << 4) | cfg->pms_sdiv);
FIELD_PREP(LCPLL_PMS_SDIV_RBR_MASK, cfg->pms_sdiv) |
FIELD_PREP(LCPLL_PMS_SDIV_HBR_MASK, cfg->pms_sdiv));
regmap_write(hdptx->regmap, CMN_REG(002a), cfg->sdm_deno);
regmap_write(hdptx->regmap, CMN_REG(002b), cfg->sdm_num_sign);
regmap_write(hdptx->regmap, CMN_REG(002c), cfg->sdm_num);
@@ -1178,8 +1190,7 @@ static int rk_hdptx_frl_lcpll_ropll_cmn_config(struct rk_hdptx_phy *hdptx)
rk_hdptx_pre_power_up(hdptx);
/* ROPLL input reference clock from LCPLL (cascade mode) */
regmap_write(hdptx->grf, GRF_HDPTX_CON0,
(LC_REF_CLK_SEL << 16) | LC_REF_CLK_SEL);
regmap_write(hdptx->grf, GRF_HDPTX_CON0, FIELD_PREP_WM16(LC_REF_CLK_SEL, 1));
rk_hdptx_multi_reg_write(hdptx, rk_hdptx_common_cmn_init_seq);
rk_hdptx_multi_reg_write(hdptx, rk_hdptx_frl_lcpll_ropll_cmn_init_seq);
@@ -1218,7 +1229,7 @@ static int rk_hdptx_tmds_ropll_cmn_config(struct rk_hdptx_phy *hdptx)
rk_hdptx_pre_power_up(hdptx);
regmap_write(hdptx->grf, GRF_HDPTX_CON0, LC_REF_CLK_SEL << 16);
regmap_write(hdptx->grf, GRF_HDPTX_CON0, FIELD_PREP_WM16(LC_REF_CLK_SEL, 0));
rk_hdptx_multi_reg_write(hdptx, rk_hdptx_common_cmn_init_seq);
rk_hdptx_multi_reg_write(hdptx, rk_hdptx_tmds_cmn_init_seq);
@@ -1226,8 +1237,10 @@ static int rk_hdptx_tmds_ropll_cmn_config(struct rk_hdptx_phy *hdptx)
regmap_write(hdptx->regmap, CMN_REG(0051), cfg->pms_mdiv);
regmap_write(hdptx->regmap, CMN_REG(0055), cfg->pms_mdiv_afc);
regmap_write(hdptx->regmap, CMN_REG(0059),
(cfg->pms_pdiv << 4) | cfg->pms_refdiv);
regmap_write(hdptx->regmap, CMN_REG(005a), cfg->pms_sdiv << 4);
FIELD_PREP(ANA_ROPLL_PMS_PDIV_MASK, cfg->pms_pdiv) |
FIELD_PREP(ANA_ROPLL_PMS_REFDIV_MASK, cfg->pms_refdiv));
regmap_write(hdptx->regmap, CMN_REG(005a),
FIELD_PREP(ROPLL_PMS_SDIV_RBR_MASK, cfg->pms_sdiv));
regmap_update_bits(hdptx->regmap, CMN_REG(005e), ROPLL_SDM_EN_MASK,
FIELD_PREP(ROPLL_SDM_EN_MASK, cfg->sdm_en));
@@ -1260,13 +1273,19 @@ static int rk_hdptx_tmds_ropll_cmn_config(struct rk_hdptx_phy *hdptx)
static int rk_hdptx_pll_cmn_config(struct rk_hdptx_phy *hdptx)
{
int ret;
if (hdptx->hdmi_cfg.rate <= HDMI20_MAX_RATE)
return rk_hdptx_tmds_ropll_cmn_config(hdptx);
ret = rk_hdptx_tmds_ropll_cmn_config(hdptx);
else if (hdptx->hdmi_cfg.rate == FRL_8G4L_RATE)
ret = rk_hdptx_frl_lcpll_ropll_cmn_config(hdptx);
else
ret = rk_hdptx_frl_lcpll_cmn_config(hdptx);
if (hdptx->hdmi_cfg.rate == FRL_8G4L_RATE)
return rk_hdptx_frl_lcpll_ropll_cmn_config(hdptx);
if (!ret)
hdptx->pll_config_dirty = false;
return rk_hdptx_frl_lcpll_cmn_config(hdptx);
return ret;
}
static int rk_hdptx_frl_lcpll_mode_config(struct rk_hdptx_phy *hdptx)
@@ -1330,11 +1349,9 @@ static void rk_hdptx_dp_reset(struct rk_hdptx_phy *hdptx)
FIELD_PREP(LN_TX_DRV_EI_EN_MASK, 0));
regmap_write(hdptx->grf, GRF_HDPTX_CON0,
HDPTX_I_PLL_EN << 16 | FIELD_PREP(HDPTX_I_PLL_EN, 0x0));
regmap_write(hdptx->grf, GRF_HDPTX_CON0,
HDPTX_I_BIAS_EN << 16 | FIELD_PREP(HDPTX_I_BIAS_EN, 0x0));
regmap_write(hdptx->grf, GRF_HDPTX_CON0,
HDPTX_I_BGR_EN << 16 | FIELD_PREP(HDPTX_I_BGR_EN, 0x0));
FIELD_PREP_WM16(HDPTX_I_PLL_EN, 0) |
FIELD_PREP_WM16(HDPTX_I_BIAS_EN, 0) |
FIELD_PREP_WM16(HDPTX_I_BGR_EN, 0));
}
static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx)
@@ -1347,25 +1364,22 @@ static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx)
return 0;
ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &status);
if (ret)
goto dec_usage;
if (status & HDPTX_O_PLL_LOCK_DONE)
dev_warn(hdptx->dev, "PLL locked by unknown consumer!\n");
if (ret) {
atomic_dec(&hdptx->usage_count);
return ret;
}
if (mode == PHY_MODE_DP) {
rk_hdptx_dp_reset(hdptx);
} else {
ret = rk_hdptx_pll_cmn_config(hdptx);
if (ret)
goto dec_usage;
/*
* Ignore PLL config errors at this point as pll_config_dirty
* was not reset and, therefore, operation will be retried.
*/
rk_hdptx_pll_cmn_config(hdptx);
}
return 0;
dec_usage:
atomic_dec(&hdptx->usage_count);
return ret;
}
static int rk_hdptx_phy_consumer_put(struct rk_hdptx_phy *hdptx, bool force)
@@ -1613,9 +1627,8 @@ static int rk_hdptx_dp_aux_init(struct rk_hdptx_phy *hdptx)
FIELD_PREP(OVRD_SB_VREG_EN_MASK, 0x1));
regmap_write(hdptx->grf, GRF_HDPTX_CON0,
HDPTX_I_BGR_EN << 16 | FIELD_PREP(HDPTX_I_BGR_EN, 0x1));
regmap_write(hdptx->grf, GRF_HDPTX_CON0,
HDPTX_I_BIAS_EN << 16 | FIELD_PREP(HDPTX_I_BIAS_EN, 0x1));
FIELD_PREP_WM16(HDPTX_I_BGR_EN, 1) |
FIELD_PREP_WM16(HDPTX_I_BIAS_EN, 1));
usleep_range(20, 25);
reset_control_deassert(hdptx->rsts[RST_INIT].rstc);
@@ -1656,29 +1669,13 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
enum phy_mode mode = phy_get_mode(phy);
int ret, lane;
if (mode != PHY_MODE_DP) {
if (!hdptx->hdmi_cfg.rate && hdptx->hdmi_cfg.mode != PHY_HDMI_MODE_FRL) {
/*
* FIXME: Temporary workaround to setup TMDS char rate
* from the RK DW HDMI QP bridge driver.
* Will be removed as soon the switch to the HDMI PHY
* configuration API has been completed on both ends.
*/
hdptx->hdmi_cfg.rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
hdptx->hdmi_cfg.rate *= 100;
}
dev_dbg(hdptx->dev, "%s rate=%llu bpc=%u\n", __func__,
hdptx->hdmi_cfg.rate, hdptx->hdmi_cfg.bpc);
}
ret = rk_hdptx_phy_consumer_get(hdptx);
if (ret)
return ret;
if (mode == PHY_MODE_DP) {
regmap_write(hdptx->grf, GRF_HDPTX_CON0,
HDPTX_MODE_SEL << 16 | FIELD_PREP(HDPTX_MODE_SEL, 0x1));
FIELD_PREP_WM16(HDPTX_MODE_SEL, 1));
for (lane = 0; lane < 4; lane++) {
regmap_update_bits(hdptx->regmap, LANE_REG(031e) + 0x400 * lane,
@@ -1697,21 +1694,27 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
rk_hdptx_dp_pll_init(hdptx);
ret = rk_hdptx_dp_aux_init(hdptx);
if (ret)
rk_hdptx_phy_consumer_put(hdptx, true);
} else {
regmap_write(hdptx->grf, GRF_HDPTX_CON0,
HDPTX_MODE_SEL << 16 | FIELD_PREP(HDPTX_MODE_SEL, 0x0));
dev_dbg(hdptx->dev, "%s rate=%llu bpc=%u\n", __func__,
hdptx->hdmi_cfg.rate, hdptx->hdmi_cfg.bpc);
if (hdptx->hdmi_cfg.mode == PHY_HDMI_MODE_FRL)
ret = rk_hdptx_frl_lcpll_mode_config(hdptx);
else
ret = rk_hdptx_tmds_ropll_mode_config(hdptx);
if (hdptx->pll_config_dirty)
ret = rk_hdptx_pll_cmn_config(hdptx);
if (ret)
rk_hdptx_phy_consumer_put(hdptx, true);
if (!ret) {
regmap_write(hdptx->grf, GRF_HDPTX_CON0,
FIELD_PREP_WM16(HDPTX_MODE_SEL, 0));
if (hdptx->hdmi_cfg.mode == PHY_HDMI_MODE_FRL)
ret = rk_hdptx_frl_lcpll_mode_config(hdptx);
else
ret = rk_hdptx_tmds_ropll_mode_config(hdptx);
}
}
if (ret)
rk_hdptx_phy_consumer_put(hdptx, true);
return ret;
}
@@ -1835,8 +1838,7 @@ static int rk_hdptx_phy_set_rate(struct rk_hdptx_phy *hdptx,
u32 bw, status;
int ret;
regmap_write(hdptx->grf, GRF_HDPTX_CON0,
HDPTX_I_PLL_EN << 16 | FIELD_PREP(HDPTX_I_PLL_EN, 0x0));
regmap_write(hdptx->grf, GRF_HDPTX_CON0, FIELD_PREP_WM16(HDPTX_I_PLL_EN, 0));
switch (dp->link_rate) {
case 1620:
@@ -1892,8 +1894,7 @@ static int rk_hdptx_phy_set_rate(struct rk_hdptx_phy *hdptx,
regmap_update_bits(hdptx->regmap, CMN_REG(0095), DP_TX_LINK_BW_MASK,
FIELD_PREP(DP_TX_LINK_BW_MASK, bw));
regmap_write(hdptx->grf, GRF_HDPTX_CON0,
HDPTX_I_PLL_EN << 16 | FIELD_PREP(HDPTX_I_PLL_EN, 0x1));
regmap_write(hdptx->grf, GRF_HDPTX_CON0, FIELD_PREP_WM16(HDPTX_I_PLL_EN, 1));
ret = regmap_read_poll_timeout(hdptx->grf, GRF_HDPTX_STATUS,
status, FIELD_GET(HDPTX_O_PLL_LOCK_DONE, status),
@@ -2080,8 +2081,10 @@ static int rk_hdptx_phy_configure(struct phy *phy, union phy_configure_opts *opt
if (ret) {
dev_err(hdptx->dev, "invalid hdmi params for phy configure\n");
} else {
hdptx->restrict_rate_change = true;
dev_dbg(hdptx->dev, "%s rate=%llu bpc=%u\n", __func__,
hdptx->pll_config_dirty = true;
dev_dbg(hdptx->dev, "%s %s rate=%llu bpc=%u\n", __func__,
hdptx->hdmi_cfg.mode ? "FRL" : "TMDS",
hdptx->hdmi_cfg.rate, hdptx->hdmi_cfg.bpc);
}
@@ -2168,7 +2171,7 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
struct lcpll_config lcpll_hw;
struct ropll_config ropll_hw;
u64 fout, sdm;
u32 mode, val;
u32 mode, bpc, val;
int ret, i;
ret = regmap_read(hdptx->regmap, CMN_REG(0008), &mode);
@@ -2184,7 +2187,7 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
ret = regmap_read(hdptx->regmap, CMN_REG(0023), &val);
if (ret)
return 0;
lcpll_hw.pms_sdiv = val & 0xf;
lcpll_hw.pms_sdiv = FIELD_GET(LCPLL_PMS_SDIV_HBR_MASK, val);
ret = regmap_read(hdptx->regmap, CMN_REG(002B), &val);
if (ret)
@@ -2204,18 +2207,33 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
ret = regmap_read(hdptx->regmap, CMN_REG(002D), &val);
if (ret)
return 0;
lcpll_hw.sdc_n = (val & LCPLL_SDC_N_MASK) >> 1;
lcpll_hw.sdc_n = FIELD_GET(LCPLL_SDC_N_MASK, val);
for (i = 0; i < ARRAY_SIZE(rk_hdptx_frl_lcpll_cfg); i++) {
const struct lcpll_config *cfg = &rk_hdptx_frl_lcpll_cfg[i];
ret = regmap_read(hdptx->grf, GRF_HDPTX_CON0, &val);
if (ret)
return 0;
if (cfg->pms_mdiv == lcpll_hw.pms_mdiv &&
cfg->pms_sdiv == lcpll_hw.pms_sdiv &&
cfg->sdm_num_sign == lcpll_hw.sdm_num_sign &&
cfg->sdm_num == lcpll_hw.sdm_num &&
cfg->sdm_deno == lcpll_hw.sdm_deno &&
cfg->sdc_n == lcpll_hw.sdc_n)
return cfg->rate;
if (val & LC_REF_CLK_SEL) {
if (lcpll_hw.pms_mdiv == 0x6b &&
lcpll_hw.sdm_num_sign == 0x01 &&
lcpll_hw.sdm_num == 0x02 &&
lcpll_hw.sdm_deno == 0x09 &&
lcpll_hw.sdc_n == FIELD_GET(LCPLL_SDC_N_MASK, 0x02))
return FRL_8G4L_RATE;
} else {
const struct lcpll_config *cfg;
for (i = 0; i < ARRAY_SIZE(rk_hdptx_frl_lcpll_cfg); i++) {
cfg = &rk_hdptx_frl_lcpll_cfg[i];
if (cfg->pms_mdiv == lcpll_hw.pms_mdiv &&
cfg->pms_sdiv == lcpll_hw.pms_sdiv &&
cfg->sdm_num_sign == lcpll_hw.sdm_num_sign &&
cfg->sdm_num == lcpll_hw.sdm_num &&
cfg->sdm_deno == lcpll_hw.sdm_deno &&
cfg->sdc_n == lcpll_hw.sdc_n)
return cfg->rate;
}
}
dev_dbg(hdptx->dev, "%s no FRL match found\n", __func__);
@@ -2230,12 +2248,12 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
ret = regmap_read(hdptx->regmap, CMN_REG(005E), &val);
if (ret)
return 0;
ropll_hw.sdm_en = val & ROPLL_SDM_EN_MASK;
ropll_hw.sdm_en = FIELD_GET(ROPLL_SDM_EN_MASK, val);
ret = regmap_read(hdptx->regmap, CMN_REG(0064), &val);
if (ret)
return 0;
ropll_hw.sdm_num_sign = val & ROPLL_SDM_NUM_SIGN_RBR_MASK;
ropll_hw.sdm_num_sign = FIELD_GET(ROPLL_SDM_NUM_SIGN_RBR_MASK, val);
ret = regmap_read(hdptx->regmap, CMN_REG(0065), &val);
if (ret)
@@ -2250,7 +2268,7 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
ret = regmap_read(hdptx->regmap, CMN_REG(0069), &val);
if (ret)
return 0;
ropll_hw.sdc_n = (val & ROPLL_SDC_N_RBR_MASK) + 3;
ropll_hw.sdc_n = FIELD_GET(ROPLL_SDC_N_RBR_MASK, val) + 3;
ret = regmap_read(hdptx->regmap, CMN_REG(006c), &val);
if (ret)
@@ -2265,22 +2283,43 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
ret = regmap_read(hdptx->regmap, CMN_REG(0086), &val);
if (ret)
return 0;
ropll_hw.pms_sdiv = ((val & PLL_PCG_POSTDIV_SEL_MASK) >> 4) + 1;
ropll_hw.pms_sdiv = FIELD_GET(PLL_PCG_POSTDIV_SEL_MASK, val) + 1;
bpc = (FIELD_GET(PLL_PCG_CLK_SEL_MASK, val) << 1) + 8;
fout = PLL_REF_CLK * ropll_hw.pms_mdiv;
if (ropll_hw.sdm_en) {
sdm = div_u64(PLL_REF_CLK * ropll_hw.sdc_deno *
ropll_hw.pms_mdiv * ropll_hw.sdm_num,
16 * ropll_hw.sdm_deno *
(ropll_hw.sdc_deno * ropll_hw.sdc_n - ropll_hw.sdc_num));
val = 16U * ropll_hw.sdm_deno *
(ropll_hw.sdc_deno * ropll_hw.sdc_n - ropll_hw.sdc_num);
if (!val) {
/*
* The PLL config currently stored in hardware can't be
* translated into a rate. The next .set_rate() should
* program a valid configuration and help with recovery.
*/
dev_dbg(hdptx->dev, "Invalid ROPLL hw state: deno == 0\n");
return 0;
}
sdm = div_u64(PLL_REF_CLK * ropll_hw.sdc_deno *
ropll_hw.pms_mdiv * ropll_hw.sdm_num, val);
if (ropll_hw.sdm_num_sign) {
if (sdm > fout) {
/*
* Similarly to the case above, it is expected
* the next .set_rate() will help with recovery.
*/
dev_dbg(hdptx->dev, "Invalid ROPLL hw state: sdm > fout\n");
return 0;
}
if (ropll_hw.sdm_num_sign)
fout = fout - sdm;
else
} else {
fout = fout + sdm;
}
}
return div_u64(fout * 2, ropll_hw.pms_sdiv * 10);
return DIV_ROUND_CLOSEST_ULL(fout * 2 * 8, ropll_hw.pms_sdiv * 10 * bpc);
}
static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
@@ -2288,19 +2327,13 @@ static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
{
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
u32 status;
u64 rate;
int ret;
ret = regmap_read(hdptx->grf, GRF_HDPTX_CON0, &status);
if (ret || !(status & HDPTX_I_PLL_EN))
return 0;
rate = rk_hdptx_phy_clk_calc_rate_from_pll_cfg(hdptx);
if (hdptx->hdmi_cfg.mode == PHY_HDMI_MODE_FRL)
return rate;
return DIV_ROUND_CLOSEST_ULL(rate * 8, hdptx->hdmi_cfg.bpc);
return rk_hdptx_phy_clk_calc_rate_from_pll_cfg(hdptx);
}
static int rk_hdptx_phy_clk_determine_rate(struct clk_hw *hw,
@@ -2308,31 +2341,18 @@ static int rk_hdptx_phy_clk_determine_rate(struct clk_hw *hw,
{
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
if (hdptx->hdmi_cfg.mode == PHY_HDMI_MODE_FRL)
return hdptx->hdmi_cfg.rate;
/*
* FIXME: Temporarily allow altering TMDS char rate via CCF.
* To be dropped as soon as the RK DW HDMI QP bridge driver
* switches to make use of phy_configure().
* For uncommitted PLL configuration, invalidate the current clock rate
* to ensure rk_hdptx_phy_clk_set_rate() will be always invoked.
* Otherwise, restrict the rate according to the PHY link setup.
*/
if (!hdptx->restrict_rate_change && req->rate != hdptx->hdmi_cfg.rate) {
struct phy_configure_opts_hdmi hdmi = {
.tmds_char_rate = req->rate,
};
int ret = rk_hdptx_phy_verify_hdmi_config(hdptx, &hdmi, &hdptx->hdmi_cfg);
if (ret)
return ret;
}
/*
* The TMDS char rate shall be adjusted via phy_configure() only,
* hence ensure rk_hdptx_phy_clk_set_rate() won't be invoked with
* a different rate argument.
*/
req->rate = DIV_ROUND_CLOSEST_ULL(hdptx->hdmi_cfg.rate * 8, hdptx->hdmi_cfg.bpc);
if (hdptx->pll_config_dirty)
req->rate = 0;
else if (hdptx->hdmi_cfg.mode == PHY_HDMI_MODE_FRL)
req->rate = hdptx->hdmi_cfg.rate;
else
req->rate = DIV_ROUND_CLOSEST_ULL(hdptx->hdmi_cfg.rate * 8,
hdptx->hdmi_cfg.bpc);
return 0;
}
@@ -2341,17 +2361,6 @@ static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
unsigned long long link_rate = rate;
if (hdptx->hdmi_cfg.mode != PHY_HDMI_MODE_FRL)
link_rate = DIV_ROUND_CLOSEST_ULL(rate * hdptx->hdmi_cfg.bpc, 8);
/* Revert any unlikely link rate change since determine_rate() */
if (hdptx->hdmi_cfg.rate != link_rate) {
dev_warn(hdptx->dev, "Reverting unexpected rate change from %llu to %llu\n",
link_rate, hdptx->hdmi_cfg.rate);
hdptx->hdmi_cfg.rate = link_rate;
}
/*
* The link rate would be normally programmed in HW during

View File

@@ -23,3 +23,19 @@ config PHY_SPACEMIT_K1_USB2
help
Enable this to support K1 USB 2.0 PHY driver. This driver takes care of
enabling and clock setup and will be used by K1 udc/ehci/otg/xhci driver.
config PHY_SPACEMIT_K3_COMMON_OPS
tristate
select MFD_SYSCON
select GENERIC_PHY
config PHY_SPACEMIT_K3_COMBO_PHY
tristate "SpacemiT K3 USB3/PCIe PHY support"
depends on (ARCH_SPACEMIT || COMPILE_TEST) && OF
depends on COMMON_CLK
select PHY_SPACEMIT_K3_COMMON_OPS
help
Enable this to support K3 USB3/PCIe combo PHY driver. This
driver takes care of enabling and clock setup and will be used
by K3 dwc3 driver.
If unsure, say N.

View File

@@ -1,3 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_PHY_SPACEMIT_K1_PCIE) += phy-k1-pcie.o
obj-$(CONFIG_PHY_SPACEMIT_K1_USB2) += phy-k1-usb2.o
obj-$(CONFIG_PHY_SPACEMIT_K3_COMBO_PHY) += phy-k3-combo.o
obj-$(CONFIG_PHY_SPACEMIT_K3_COMMON_OPS) += phy-k3-common.o

View File

@@ -0,0 +1,252 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* phy-k3-combo.c - SpacemiT K3 PCIe/USB3 Combo PHY Driver
*
* Copyright (c) 2025 SpacemiT Technology Co. Ltd
*/
#include <linux/bitfield.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/mfd/syscon.h>
#include <linux/iopoll.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/phy/phy.h>
#include <dt-bindings/phy/phy.h>
#include "phy-k3-common.h"
/*
* The PCIE/USB Subsystem on SpacemiT K3 have 3 single lane PIPE3 PHYs
* (PHY2/3/4) shared by PCIE PortC/D and USB3 PortB/C/D.
*
* PMUA_PCIE_SUBSYS_MGMT[4:0]
*
* bit4 = 0 : PCIe A X8 mode, all 8 lanes dedicated to PCIe Port A
* 1 : PHY lanes shared between PCIe or USB according to [3:0]
*
* All PHY matrix combinations according to [4:0]:
*
* 0x0X : PCIe-A X8
* 0x10 : PCIe-C x2 (PHY2+PHY3) + PCIe-D x1 (PHY4)
* 0x11 : PCIe-C x2 (PHY2+PHY3) + USB-D (PHY4)
* 0x12 : PCIe-C x1 (PHY2) + USB-C (PHY3)
* 0x13 : PCIe-C x1 (PHY2) + USB-C (PHY3) + USB-D (PHY4)
* 0x14 : PCIe-C x1 (PHY3) + USB-B (PHY2)
* 0x15 : PCIe-C x1 (PHY3) + USB-B (PHY2) + USB-D (PHY4)
* 0x16 : USB-B (PHY2) + USB-C (PHY3) + PCIe D x1 (PHY4)
* 0x17 : USB-B (PHY2) + USB-C (PHY3) + USB-D (PHY4)
*
* So any USB Port B/C/D operation requires PCIe A X8 mode to be disabled.
*/
#define PMUA_PCIE_SUBSYS_MGMT 0x1d8
#define PU_MATRIX_CONF_MASK GENMASK(4, 0)
#define COMBPHY_MAX_SUBPHYS 6
struct k3_combo_phy {
struct device *dev;
struct k3_lane_group groups[COMBPHY_MAX_SUBPHYS];
void __iomem *base;
struct regmap *apb_spare;
};
static const struct k3_phy_lane_group_data k3_combphy_lane_group0 = {
.lanes = 2,
.config = 0xff,
.mask = 0x00,
.offsets = {
0x0, 0x400
},
};
static const struct k3_phy_lane_group_data k3_combphy_lane_group1 = {
.lanes = 2,
.config = 0xff,
.mask = 0x00,
.offsets = {
0x100000, 0x100400
},
};
static const struct k3_phy_lane_group_data k3_combphy_lane_group2 = {
.lanes = 1,
.config = 0x14,
.mask = 0x14,
.offsets = {
0x200000
},
};
static const struct k3_phy_lane_group_data k3_combphy_lane_group3 = {
.lanes = 1,
.config = 0x12,
.mask = 0x12,
.offsets = {
0x300000
},
};
static const struct k3_phy_lane_group_data k3_combphy_lane_group4 = {
.lanes = 1,
.config = 0x11,
.mask = 0x11,
.offsets = {
0x400000
},
};
static const struct k3_phy_lane_group_data k3_combphy_lane_group5 = {
.lanes = 1,
.config = 0xff,
.mask = 0x00,
.offsets = {
0x500000
},
};
static const struct k3_phy_lane_group_data *k3_combphy_lane_datas[] = {
&k3_combphy_lane_group0,
&k3_combphy_lane_group1,
&k3_combphy_lane_group2,
&k3_combphy_lane_group3,
&k3_combphy_lane_group4,
&k3_combphy_lane_group5,
};
static int k3_combo_phy_init_lanes(struct k3_combo_phy *phy, unsigned int config)
{
int i;
for (i = 0; i < ARRAY_SIZE(k3_combphy_lane_datas); i++) {
const struct k3_phy_lane_group_data *data = k3_combphy_lane_datas[i];
struct k3_lane_group *lg = &phy->groups[i];
const struct phy_ops *ops;
bool is_usb;
is_usb = (data->mask & config) == data->config;
if (is_usb)
ops = &k3_usb3_phy_ops;
else
ops = &k3_pcie_phy_ops;
dev_dbg(phy->dev, "phy %d is %s\n", i, is_usb ? "usb" : "pcie");
lg->phy = devm_phy_create(phy->dev, NULL, ops);
if (IS_ERR(lg->phy))
return PTR_ERR(lg->phy);
lg->is_pcie = !is_usb;
lg->data = data;
lg->base = phy->base;
phy_set_drvdata(lg->phy, lg);
}
return 0;
}
static int k3_combo_phy_update_config(struct regmap *apmu, unsigned int config)
{
if (config & ~PU_MATRIX_CONF_MASK)
return -EINVAL;
return regmap_update_bits(apmu, PMUA_PCIE_SUBSYS_MGMT, PU_MATRIX_CONF_MASK, config);
}
static struct phy *k3_combo_phy_xlate(struct device *dev, const struct of_phandle_args *args)
{
struct k3_combo_phy *phy = dev_get_drvdata(dev);
struct k3_lane_group *lg;
if (args->args_count != 2) {
dev_err(dev, "Invalid number of arguments\n");
return ERR_PTR(-EINVAL);
}
if (args->args[0] >= ARRAY_SIZE(k3_combphy_lane_datas)) {
dev_err(dev, "Invalid PHY id\n");
return ERR_PTR(-EINVAL);
}
lg = &phy->groups[args->args[0]];
if ((lg->is_pcie && args->args[1] != PHY_TYPE_PCIE) ||
(!lg->is_pcie && args->args[1] != PHY_TYPE_USB3)) {
dev_err(dev, "Invalid PHY mode\n");
return ERR_PTR(-EINVAL);
}
return lg->phy;
}
static int k3_combo_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
struct phy_provider *provider;
struct k3_combo_phy *phy;
struct regmap *apmu;
u32 config = 0;
int ret;
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
if (!phy)
return -ENOMEM;
phy->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(phy->base))
return PTR_ERR(phy->base);
phy->apb_spare = syscon_regmap_lookup_by_phandle(node, "spacemit,apb-spare");
if (IS_ERR(phy->apb_spare))
return dev_err_probe(dev, PTR_ERR(phy->apb_spare),
"Failed to find APB SPARE syscon");
apmu = syscon_regmap_lookup_by_phandle_args(node, "spacemit,apmu", 1, &config);
if (IS_ERR(apmu))
return dev_err_probe(dev, PTR_ERR(apmu),
"Failed to find APMU syscon");
ret = k3_combo_phy_update_config(apmu, config);
if (ret < 0)
return dev_err_probe(dev, ret, "Failed to set lane configuration");
phy->dev = dev;
platform_set_drvdata(pdev, phy);
ret = k3_phy_calibrate(phy->apb_spare);
if (ret < 0)
return dev_err_probe(dev, ret, "Failed to calibrate phy");
ret = k3_combo_phy_init_lanes(phy, config);
if (ret < 0)
return dev_err_probe(dev, ret, "Failed to init lanes");
provider = devm_of_phy_provider_register(dev, k3_combo_phy_xlate);
if (IS_ERR(provider))
return dev_err_probe(dev, PTR_ERR(provider),
"Failed to register provider\n");
return 0;
}
static const struct of_device_id k3_combo_phy_of_match[] = {
{ .compatible = "spacemit,k3-combo-phy" },
{ },
};
MODULE_DEVICE_TABLE(of, k3_combo_phy_of_match);
static struct platform_driver k3_combo_phy_driver = {
.probe = k3_combo_phy_probe,
.driver = {
.name = "spacemit,k3-combo-phy",
.of_match_table = k3_combo_phy_of_match,
},
};
module_platform_driver(k3_combo_phy_driver);
MODULE_DESCRIPTION("SpacemiT K3 USB3/PCIe combo PHY driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,391 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/bitfield.h>
#include <linux/cleanup.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/usb.h>
#include <dt-bindings/phy/phy.h>
#include "phy-k3-common.h"
/* PHY Registers */
#define PHY_VERSION 0x0
#define PHY_RESET_CFG 0x04
#define PHY_RESET_RXBUF_RST BIT(0)
#define PHY_RESET_SOFT_RST_PCS BIT(1)
#define PHY_RESET_SOFT_RST_AHB BIT(2)
#define PHY_RESET_EN_SD_AFTER_LOCK BIT(6)
#define PHY_CLK_CFG 0x08
#define PHY_CLK_PLL_READY BIT(0)
#define PHY_CLK_TXCLK_INV BIT(2)
#define PHY_CLK_RXCLK_EN BIT(3)
#define PHY_CLK_TXCLK_EN BIT(4)
#define PHY_CLK_PCLK_EN BIT(5)
#define PHY_CLK_PIPE_PCLK_EN BIT(6)
#define PHY_CLK_REFCLK_FREQ GENMASK(10, 7)
#define PHY_CLK_REFCLK_24M 2
#define PHY_CLK_SW_INIT_DONE BIT(11)
#define PHY_CLK_PU_SSC_OUT BIT(23)
#define PHY_MODE_CFG 0x0C
#define PHY_MODE_PCIE_INT_EN BIT(0)
#define PHY_MODE_LFPS_TPERIOD GENMASK(9, 8)
#define PHY_MODE_LFPS_TPERIOD_USB 3
#define PHY_PU_SEL 0x40
#define PHY_PU_CFG_STATUS BIT(9)
#define PHY_PU_OVRD_STATUS BIT(10)
#define PHY_PU_CK_REG 0x54
#define PHY_PU_REFCLK_100 BIT(25)
#define PHY_PLL_REG1 0x58
#define PHY_PLL_FREF_SEL GENMASK(15, 13)
#define PHY_PLL_FREF_24M 0x1
#define PHY_PLL_SSC_DEP_SEL GENMASK(27, 24)
#define PHY_PLL_SSC_5000PPM 0xa
#define PHY_PLL_SSC_MODE GENMASK(29, 28)
#define PHY_PLL_SSC_MODE_CENTER_SPREAD 0
#define PHY_PLL_SSC_MODE_UP_SPREAD 1
#define PHY_PLL_SSC_MODE_DOWN_SPREAD 2
#define PHY_PLL_SSC_MODE_DOWN_SPREAD1 3
#define PHY_PLL_REG2 0x5c
#define PHY_PLL_SEL_REF100 BIT(21)
/* PHY RX Register Definitions */
#define PHY_RX_REG_A 0x60
#define PHY_RX_REG0_MASK GENMASK(7, 0)
#define PHY_RX_REG1_MASK GENMASK(15, 8)
#define PHY_RX_REG2_MASK GENMASK(23, 16)
#define PHY_RX_REG3_MASK GENMASK(31, 24)
#define PHY_RX_REG0_RLOAD BIT(4)
#define PHY_RX_REG1_RTERM GENMASK(11, 8)
#define PHY_RX_REG1_RC_CALI GENMASK(15, 12)
#define PHY_RX_REG2_CSEL GENMASK(19, 16)
#define PHY_RX_REG2_FORCE_CSEL BIT(20)
#define PHY_RX_REG2_PSEL GENMASK(23, 21)
#define PHY_RX_REG3_I_LOAD GENMASK(26, 24)
#define PHY_RX_REG3_SEL_CBOOST_CODE BIT(27)
#define PHY_RX_REG3_ADJ_BIAS GENMASK(29, 28)
#define PHY_RX_REG3_RDEG1 GENMASK(31, 30)
#define PHY_RX_REG_B 0x64
#define PHY_RX_REG4_MASK GENMASK(7, 0)
#define PHY_RX_REG5_MASK GENMASK(15, 8)
#define PHY_RX_REG6_MASK GENMASK(23, 16)
#define PHY_RX_REGB_MASK GENMASK(23, 0)
#define PHY_RX_REG4_RDEG2 GENMASK(2, 1)
#define PHY_RX_REG4_ENVOS BIT(4)
#define PHY_RX_REG4_RTERM_SEL BIT(5)
#define PHY_RX_REG4_MANUAL_CFG BIT(7)
#define PHY_RX_REG5_RCELL_VCM GENMASK(11, 8)
#define PHY_RX_REG5_RCELL_BIAS GENMASK(15, 12)
#define PHY_RX_REG6_H1_REG GENMASK(19, 16)
#define PHY_RX_REG6_ADAPT_GAIN GENMASK(21, 20)
#define PHY_RX_REG6_BYPASS_ADPT BIT(22)
#define PHY_ADPT_CFG0 0x140
#define PHY_ADPT_AFE_RST_OVRD_EN BIT(1)
#define PHY_ADPT_AFE_RST_OVRD_VAL BIT(4)
#define PHY_RXEQ_TIME 0xb4
#define PHY_RXEQ_TIME_OVRD_POST_C_SOC BIT(21)
#define PHY_RXEQ_TIME_CFG_AMP_SOC GENMASK(23, 22)
#define PHY_RXEQ_TIME_AMP_SOC_650M 0
#define PHY_RXEQ_TIME_AMP_SOC_800M 1
#define PHY_RXEQ_TIME_AMP_SOC_870M 2
#define PHY_RXEQ_TIME_AMP_SOC_900M 3
#define PHY_RXEQ_TIME_OVRD_AMP_SOC BIT(24)
#define PCIE_PU_ADDR_CLK_CFG 0x0008
#define PHY_CLK_PLL_READY BIT(0)
#define PCIE_INITAL_TIMER GENMASK(6, 3)
#define CFG_INTERNAL_TIMER_ADJ GENMASK(10, 7)
#define CFG_SW_PHY_INIT_DONE BIT(11)
/* Lane RX/TX configuration (perlane, at lane_base) */
#define PCIE_RX_REG1 0x050
#define PCIE_RX_REFCLK_MODE GENMASK(1, 0)
#define PCIE_RX_REFCLK_MODE_DRIVER 1
#define PCIE_RX_SEL_TRI_CODE BIT(2)
#define PCIE_RX_LEGACY GENMASK(15, 8)
#define PCIE_RX_LEGACY_DEFAULT 0x65
#define PCIE_TX_REG1 0x064
#define PCIE_PLL_TIMEOUT 500000
#define PCIE_POLL_DELAY 500
static int k3_usb3phy_init_single(struct k3_lane_group *lg, void __iomem *base)
{
struct phy *phy = lg->phy;
u32 val, tmp;
int ret;
/* Do not wait CDR lock before sampling data */
val = readl(base + PHY_RESET_CFG);
val = u32_replace_bits(val, 0, PHY_RESET_EN_SD_AFTER_LOCK);
writel(val, base + PHY_RESET_CFG);
/* Power down 100MHz refclk buffer */
val = readl(base + PHY_PU_CK_REG);
val = u32_replace_bits(val, 0, PHY_PU_REFCLK_100);
writel(val, base + PHY_PU_CK_REG);
/* Program PLL REG1 configure the SSC */
val = FIELD_PREP(PHY_PLL_SSC_MODE, PHY_PLL_SSC_MODE_DOWN_SPREAD1) |
FIELD_PREP(PHY_PLL_SSC_DEP_SEL, PHY_PLL_SSC_5000PPM) |
FIELD_PREP(PHY_PLL_FREF_SEL, PHY_PLL_FREF_24M);
writel(val, base + PHY_PLL_REG1);
/* Un-select 100MHz PLL reference */
val = readl(base + PHY_PLL_REG2);
val = u32_replace_bits(val, 0, PHY_PLL_SEL_REF100);
writel(val, base + PHY_PLL_REG2);
/* USB LFPS period configuration */
val = readl(base + PHY_MODE_CFG);
val = u32_replace_bits(val, PHY_MODE_LFPS_TPERIOD_USB, PHY_MODE_LFPS_TPERIOD);
writel(val, base + PHY_MODE_CFG);
/* Force AFE adaptation reset */
val = readl(base + PHY_ADPT_CFG0);
val |= PHY_ADPT_AFE_RST_OVRD_EN | PHY_ADPT_AFE_RST_OVRD_VAL;
writel(val, base + PHY_ADPT_CFG0);
/* Override driver amplitude value to 900m */
val = readl(base + PHY_RXEQ_TIME);
val |= PHY_RXEQ_TIME_OVRD_AMP_SOC;
val = u32_replace_bits(val, PHY_RXEQ_TIME_AMP_SOC_900M, PHY_RXEQ_TIME_CFG_AMP_SOC);
writel(val, base + PHY_RXEQ_TIME);
/* Configure RX parameters */
val = PHY_RX_REG0_RLOAD |
FIELD_PREP(PHY_RX_REG1_RTERM, 0x8) |
FIELD_PREP(PHY_RX_REG1_RC_CALI, 0x7) |
FIELD_PREP(PHY_RX_REG2_CSEL, 0x8) |
PHY_RX_REG2_FORCE_CSEL |
FIELD_PREP(PHY_RX_REG2_PSEL, 0x4) |
FIELD_PREP(PHY_RX_REG3_I_LOAD, 0x7) |
PHY_RX_REG3_SEL_CBOOST_CODE |
FIELD_PREP(PHY_RX_REG3_ADJ_BIAS, 0x1) |
FIELD_PREP(PHY_RX_REG3_RDEG1, 0x3);
writel(val, base + PHY_RX_REG_A);
val = readl(base + PHY_RX_REG_B);
tmp = FIELD_PREP(PHY_RX_REG4_RDEG2, 0x2) |
PHY_RX_REG4_ENVOS | PHY_RX_REG4_RTERM_SEL | PHY_RX_REG4_MANUAL_CFG |
FIELD_PREP(PHY_RX_REG5_RCELL_VCM, 0x8) |
FIELD_PREP(PHY_RX_REG5_RCELL_BIAS, 0x8) |
FIELD_PREP(PHY_RX_REG6_H1_REG, 0x8) |
FIELD_PREP(PHY_RX_REG6_ADAPT_GAIN, 0x2);
val = u32_replace_bits(val, tmp, PHY_RX_REGB_MASK);
writel(val, base + PHY_RX_REG_B);
/*
* Inform PHY that all PLL-related configuration is done.
* PLL will not start locking until PHY_CLK_SW_INIT_DONE is set.
*/
val = PHY_CLK_SW_INIT_DONE | PHY_CLK_PU_SSC_OUT |
FIELD_PREP(PHY_CLK_REFCLK_FREQ, PHY_CLK_REFCLK_24M) |
PHY_CLK_RXCLK_EN | PHY_CLK_TXCLK_EN |
PHY_CLK_PCLK_EN | PHY_CLK_PIPE_PCLK_EN;
writel(val, base + PHY_CLK_CFG);
ret = readl_poll_timeout(base + PHY_CLK_CFG, val,
(val & PHY_CLK_PLL_READY),
PCIE_POLL_DELAY, PCIE_PLL_TIMEOUT);
if (ret) {
dev_err(&phy->dev, "PHY PLL polling timeout\n");
return ret;
}
return 0;
}
static int k3_usb3phy_init(struct phy *phy)
{
struct k3_lane_group *lg = phy_get_drvdata(phy);
int ret, i;
for (i = 0; i < lg->data->lanes; i++) {
ret = k3_usb3phy_init_single(lg, lg->base + lg->data->offsets[i]);
if (ret < 0)
return ret;
}
return 0;
}
const struct phy_ops k3_usb3_phy_ops = {
.init = k3_usb3phy_init,
.owner = THIS_MODULE,
};
EXPORT_SYMBOL_GPL(k3_usb3_phy_ops);
static int k3_pcie_phy_init(struct phy *phy)
{
struct k3_lane_group *lg = phy_get_drvdata(phy);
void __iomem *phy_base = lg->base + lg->data->offsets[0];
u32 val;
int ret;
int i;
val = readl(phy_base + PHY_PLL_REG1);
val = u32_replace_bits(val, 0x2, GENMASK(15, 12));
writel(val, phy_base + PHY_PLL_REG1);
val = readl(phy_base + PHY_PLL_REG2);
val = u32_replace_bits(val, 0, BIT(21));
writel(val, phy_base + PHY_PLL_REG2);
for (i = 0; i < lg->data->lanes; i++) {
void __iomem *lane_base = lg->base + lg->data->offsets[i];
val = readl(lane_base + PCIE_RX_REG1);
val = u32_replace_bits(val, 0, 0x3);
writel(val, lane_base + PCIE_RX_REG1);
}
val = readl(phy_base + PHY_PLL_REG2);
val |= BIT(20);
writel(val, phy_base + PHY_PLL_REG2);
/* The write is needed as clock requires renegotiation */
val = FIELD_PREP(PCIE_RX_REFCLK_MODE, PCIE_RX_REFCLK_MODE_DRIVER) |
PCIE_RX_SEL_TRI_CODE |
FIELD_PREP(PCIE_RX_LEGACY, PCIE_RX_LEGACY_DEFAULT);
writel(val, phy_base + PCIE_RX_REG1);
/* pll_reg1 of lane0, disable SSC: pll[27:24] = 0 */
val = readl(phy_base + PHY_PLL_REG1);
val = u32_replace_bits(val, 0, GENMASK(27, 24));
writel(val, phy_base + PHY_PLL_REG1);
for (i = 0; i < lg->data->lanes; i++) {
void __iomem *lane_base = lg->base + lg->data->offsets[i];
/* set cfg_tx_send_dummy_data to be 1'b1 for disable dash data */
val = readl(lane_base + PHY_PU_SEL);
val = u32_replace_bits(val, 1, BIT(13));
writel(val, lane_base + PHY_PU_SEL);
/* disable en_sample_data_after_cdr_locked */
val = readl(lane_base + PHY_RESET_CFG);
val = u32_replace_bits(val, 0, BIT(6));
writel(val, lane_base + PHY_RESET_CFG);
/* Dynamic Lock */
val = readl(lane_base + PHY_MODE_CFG);
val = u32_replace_bits(val, 1, BIT(2));
writel(val, lane_base + PHY_MODE_CFG);
val = FIELD_PREP(PHY_RX_REG0_MASK, 0x10) |
FIELD_PREP(PHY_RX_REG1_MASK, 0x78) |
FIELD_PREP(PHY_RX_REG2_MASK, 0x98) |
FIELD_PREP(PHY_RX_REG3_MASK, 0xdf);
writel(val, lane_base + PHY_RX_REG_A);
val = readl(lane_base + PHY_RX_REG_B);
val &= ~PHY_RX_REGB_MASK;
val |= FIELD_PREP(PHY_RX_REG4_MASK, 0xb4) |
FIELD_PREP(PHY_RX_REG5_MASK, 0x88) |
FIELD_PREP(PHY_RX_REG6_MASK, 0x28);
writel(val, lane_base + PHY_RX_REG_B);
/* Set init done */
val = readl(lane_base + PCIE_PU_ADDR_CLK_CFG);
val = u32_replace_bits(val, 1, CFG_SW_PHY_INIT_DONE);
writel(val, lane_base + PCIE_PU_ADDR_CLK_CFG);
}
ret = readl_poll_timeout(phy_base + PCIE_PU_ADDR_CLK_CFG, val,
(val & PHY_CLK_PLL_READY), PCIE_POLL_DELAY,
PCIE_PLL_TIMEOUT);
if (ret) {
dev_err(&lg->phy->dev, "PHY PLL lock timeout\n");
return ret;
}
return 0;
}
const struct phy_ops k3_pcie_phy_ops = {
.init = k3_pcie_phy_init,
.owner = THIS_MODULE,
};
EXPORT_SYMBOL_GPL(k3_pcie_phy_ops);
/* PHY rcal init requires APB_SPARE regmap access */
#define APB_SPARE_PU_CAL 0x178
#define PU_CAL BIT(17)
#define APB_SPARE_RCAL_HSIO 0x17c
#define APB_SPARE_PU_CAL_DONE BIT(8)
#define RCAL_OVRD_PTRIM GENMASK(23, 20)
#define RCAL_OVRD_NTRIM GENMASK(27, 24)
#define RCAL_OVRD_PTRIM_EN BIT(28)
#define RCAL_OVRD_NTRIM_EN BIT(29)
#define RCAL_OVRD_STABLE_VAL BIT(30)
#define RCAL_OVRD_STABLE_EN BIT(31)
#define RCAL_OVRD_TRIM_EN (RCAL_OVRD_NTRIM_EN | RCAL_OVRD_PTRIM_EN)
#define RCAL_OVRD_TRIM_MASK (RCAL_OVRD_NTRIM | RCAL_OVRD_PTRIM)
#define PU_CAL_TIMEOUT 2000000
static DEFINE_MUTEX(calibrate_lock);
int k3_phy_calibrate(struct regmap *apb_spare)
{
unsigned int val = 0;
int ret;
guard(mutex)(&calibrate_lock);
regmap_read(apb_spare, APB_SPARE_RCAL_HSIO, &val);
if (val & APB_SPARE_PU_CAL_DONE)
return 0;
regmap_update_bits(apb_spare, APB_SPARE_PU_CAL, PU_CAL,
PU_CAL);
ret = regmap_read_poll_timeout(apb_spare, APB_SPARE_RCAL_HSIO,
val, (val & APB_SPARE_PU_CAL_DONE), PCIE_POLL_DELAY,
PU_CAL_TIMEOUT);
if (ret)
regmap_update_bits(apb_spare, APB_SPARE_RCAL_HSIO,
RCAL_OVRD_TRIM_EN | RCAL_OVRD_STABLE_VAL |
RCAL_OVRD_TRIM_MASK | RCAL_OVRD_STABLE_EN,
RCAL_OVRD_TRIM_EN | RCAL_OVRD_STABLE_VAL |
FIELD_PREP(RCAL_OVRD_NTRIM, 0x6) |
FIELD_PREP(RCAL_OVRD_PTRIM, 0xa) |
RCAL_OVRD_STABLE_EN);
return 0;
}
EXPORT_SYMBOL_GPL(k3_phy_calibrate);
MODULE_DESCRIPTION("SpacemiT K3 PHY common ops");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,27 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _PHY_K3_COMMON_H
#define _PHY_K3_COMMON_H
#include <linux/phy/phy.h>
struct k3_phy_lane_group_data {
u32 lanes;
u8 config;
u8 mask;
u32 offsets[] __counted_by(lanes);
};
struct k3_lane_group {
const struct k3_phy_lane_group_data *data;
void __iomem *base;
struct phy *phy;
bool is_pcie;
};
extern const struct phy_ops k3_pcie_phy_ops;
extern const struct phy_ops k3_usb3_phy_ops;
int k3_phy_calibrate(struct regmap *apb_spare);
#endif

View File

@@ -150,6 +150,7 @@ static int stf_dphy_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
struct stf_dphy *dphy;
int ret;
dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
if (!dphy)
@@ -190,7 +191,9 @@ static int stf_dphy_probe(struct platform_device *pdev)
return PTR_ERR(dphy->phy);
}
pm_runtime_enable(&pdev->dev);
ret = devm_pm_runtime_enable(&pdev->dev);
if (ret)
return ret;
phy_set_drvdata(dphy->phy, dphy);
phy_provider = devm_of_phy_provider_register(&pdev->dev,

View File

@@ -392,6 +392,7 @@ static int stf_dphy_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
struct stf_dphy *dphy;
int ret;
dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
if (!dphy)
@@ -406,7 +407,9 @@ static int stf_dphy_probe(struct platform_device *pdev)
if (IS_ERR(dphy->topsys))
return PTR_ERR(dphy->topsys);
pm_runtime_enable(&pdev->dev);
ret = devm_pm_runtime_enable(&pdev->dev);
if (ret)
return ret;
dphy->txesc_clk = devm_clk_get(&pdev->dev, "txesc");
if (IS_ERR(dphy->txesc_clk))

View File

@@ -116,11 +116,11 @@ static int sp_uphy_init(struct phy *phy)
ret = clk_prepare_enable(usbphy->phy_clk);
if (ret)
goto err_clk;
return ret;
ret = reset_control_deassert(usbphy->rstc);
if (ret)
goto err_reset;
goto err_clk;
/* Default value modification */
writel(HIGH_MASK_BITS | 0x4002, usbphy->moon4_regs + UPHY_CONTROL0);
@@ -129,7 +129,7 @@ static int sp_uphy_init(struct phy *phy)
/* disconnect voltage */
ret = update_disc_vol(usbphy);
if (ret < 0)
return ret;
goto err_reset;
/* board uphy 0 internal register modification for tid certification */
val = readl(usbphy->phy_regs + CONFIG9);