phy-for-5.14 version 2

- Updates:
         - Yaml conversion for renesas,rcar-gen3 pcie phy and
           rockchip-usb-phy bindings
         - Support for devm_phy_get() taking NULL phy name
 
   - New support:
         - PCIe phy for Qualcomm IPQ60xx
         - PCIe phy for Qualcomm SDX55
         - USB phy for RK3308
         - CAN transceivers phy for TI TCAN104x
         - Innosilicon-based CSI dphy for rockchip
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAmDS5/MACgkQfBQHDyUj
 g0cMZhAAjtAeYe7R8r2M8NACd2HRnBMBcHFJtz6Os7ZZa4dRMLyq6TkStZ8k1Mat
 2dEUb3Wb8G18WqECXUlcJp/CYlK1ea1GDwgTLd09tGo7PAn6p3RBG7ujf+aCWoil
 TLhsE9Sb7d3pr8qVsy6DQc/TIWxfCTeqZrIRzt2UQXxK6P/3CtdN1g/TEdq1r/h9
 A/xkDnyT2QQOJTgFMUh9RF85vXfptm9+gVxNdgyHGVvdaEhSURUytEfubrQYjd1P
 sM5BhsNPEKHqL/kYlgMAgnENtQBrXBwfEzP02M32zyhTLvaZMcV87Z8LXxmrPDn/
 jtYLlSYTQTDKA9tHBw1W8NogaLS9INeTjDhqt0hBsT/lh1vL5KMk0IGsSxUaJ27h
 6on3NmjsxI/HKosdrQzRizURS0xixOWDnZN7UPFaHFJbA8GMIlQlDidZOJTl87cc
 inIuSdB29YA0FNGbXOq/HR3y1qChlwAewxFYCzFtKfuHmZWJNy7osUvQNHodEAGl
 BGjerYgJUNNiWlxmoggUcLtAdbqYVH8fvvz3WUyClUePVqioX8gS6UDRx8LrgGV2
 FvLSKgetbqH3iQtRO+2RtwMJEMmC3eW7esjUv/fEgKym+2JvORpE0p2n5sWTgRMc
 VWFDVqOp5JJXmarRkly2MMppO5x25d3wE9DLR0/Re7hNPGUsz4M=
 =Col+
 -----END PGP SIGNATURE-----

Merge tag 'phy-for-5.14_v2' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy into char-misc-next

Vinod writes:

phy-for-5.14 version 2

  - Updates:
        - Yaml conversion for renesas,rcar-gen3 pcie phy and
          rockchip-usb-phy bindings
        - Support for devm_phy_get() taking NULL phy name

  - New support:
        - PCIe phy for Qualcomm IPQ60xx
        - PCIe phy for Qualcomm SDX55
        - USB phy for RK3308
        - CAN transceivers phy for TI TCAN104x
        - Innosilicon-based CSI dphy for rockchip

* tag 'phy-for-5.14_v2' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (36 commits)
  phy: Revert "phy: ralink: Kconfig: convert mt7621-pci-phy into 'bool'"
  phy: ti: dm816x: Fix the error handling path in 'dm816x_usb_phy_probe()
  phy: uniphier-pcie: Fix updating phy parameters
  phy/rockchip: add Innosilicon-based CSI dphy
  dt-bindings: phy: add yaml binding for rockchip-inno-csi-dphy
  phy: rockchip: remove redundant initialization of pointer cfg
  phy: phy-can-transceiver: Add support for generic CAN transceiver driver
  dt-bindings: phy: Add binding for TI TCAN104x CAN transceivers
  phy: core: Reword the comment specifying the units of max_link_rate to be Mbps
  phy: phy-mtk-hdmi: Remove redundant dev_err call in mtk_hdmi_phy_probe()
  phy: phy-mtk-mipi-dsi: Remove redundant dev_err call in mtk_mipi_tx_probe()
  phy: phy-mmp3-hsic: Remove redundant dev_err call in mmp3_hsic_phy_probe()
  phy: bcm-ns-usb3: Remove redundant dev_err call in bcm_ns_usb3_mdio_probe()
  MAINTAINERS: update marvell,armada-3700-utmi-phy.yaml reference
  phy: phy-twl4030-usb: use DEVICE_ATTR_RO macro
  dt-bindings: phy: convert rockchip-usb-phy.txt to YAML
  phy: phy-rockchip-inno-usb2: add support for RK3308 USB phy
  dt-bindings: phy: rockchip-inno-usb2: add compatible for rk3308 USB phy
  phy: stm32: manage optional vbus regulator on phy_power_on/off
  dt-bindings: phy: add vbus-supply optional property to phy-stm32-usbphyc
  ...
This commit is contained in:
Greg Kroah-Hartman 2021-06-23 10:33:34 +02:00
commit 5471a81235
36 changed files with 1601 additions and 136 deletions

View File

@ -14,6 +14,7 @@
- "qcom,pcie-qcs404" for qcs404
- "qcom,pcie-sdm845" for sdm845
- "qcom,pcie-sm8250" for sm8250
- "qcom,pcie-ipq6018" for ipq6018
- reg:
Usage: required
@ -123,6 +124,16 @@
- "ahb" AHB clock
- "aux" Auxiliary clock
- clock-names:
Usage: required for ipq6018
Value type: <stringlist>
Definition: Should contain the following entries
- "iface" PCIe to SysNOC BIU clock
- "axi_m" AXI Master clock
- "axi_s" AXI Slave clock
- "axi_bridge" AXI bridge clock
- "rchng"
- clock-names:
Usage: required for qcs404
Value type: <stringlist>
@ -209,6 +220,19 @@
- "ahb" AHB Reset
- "axi_m_sticky" AXI Master Sticky reset
- reset-names:
Usage: required for ipq6018
Value type: <stringlist>
Definition: Should contain the following entries
- "pipe" PIPE reset
- "sleep" Sleep reset
- "sticky" Core Sticky reset
- "axi_m" AXI Master reset
- "axi_s" AXI Slave reset
- "ahb" AHB Reset
- "axi_m_sticky" AXI Master Sticky reset
- "axi_s_sticky" AXI Slave Sticky reset
- reset-names:
Usage: required for qcs404
Value type: <stringlist>

View File

@ -16,6 +16,9 @@ properties:
reg:
maxItems: 1
clocks:
maxItems: 1
"#phy-cells":
const: 1
description: selects if the phy is dual-ported
@ -23,6 +26,7 @@ properties:
required:
- compatible
- reg
- clocks
- "#phy-cells"
additionalProperties: false
@ -32,5 +36,6 @@ examples:
pcie0_phy: pcie-phy@1e149000 {
compatible = "mediatek,mt7621-pci-phy";
reg = <0x1e149000 0x0700>;
clocks = <&sysc 0>;
#phy-cells = <1>;
};

View File

@ -14,6 +14,7 @@ properties:
enum:
- rockchip,px30-usb2phy
- rockchip,rk3228-usb2phy
- rockchip,rk3308-usb2phy
- rockchip,rk3328-usb2phy
- rockchip,rk3366-usb2phy
- rockchip,rk3399-usb2phy

View File

@ -74,6 +74,13 @@ patternProperties:
"#phy-cells":
enum: [ 0x0, 0x1 ]
connector:
type: object
allOf:
- $ref: ../connector/usb-connector.yaml
properties:
vbus-supply: true
allOf:
- if:
properties:
@ -130,6 +137,10 @@ examples:
reg = <0>;
phy-supply = <&vdd_usb>;
#phy-cells = <0>;
connector {
compatible = "usb-a-connector";
vbus-supply = <&vbus_sw>;
};
};
usbphyc_port1: usb-phy@1 {

View File

@ -17,6 +17,7 @@ description:
properties:
compatible:
enum:
- qcom,ipq6018-qmp-pcie-phy
- qcom,ipq8074-qmp-pcie-phy
- qcom,ipq8074-qmp-usb3-phy
- qcom,msm8996-qmp-pcie-phy
@ -45,6 +46,7 @@ properties:
- qcom,sm8350-qmp-ufs-phy
- qcom,sm8350-qmp-usb3-phy
- qcom,sm8350-qmp-usb3-uni-phy
- qcom,sdx55-qmp-pcie-phy
- qcom,sdx55-qmp-usb3-uni-phy
reg:
@ -296,6 +298,30 @@ allOf:
items:
- const: phy
- const: common
- if:
properties:
compatible:
contains:
enum:
- qcom,ipq6018-qmp-pcie-phy
then:
properties:
clocks:
items:
- description: Phy aux clock.
- description: Phy config clock.
clock-names:
items:
- const: aux
- const: cfg_ahb
resets:
items:
- description: reset of phy block.
- description: phy common block reset.
reset-names:
items:
- const: phy
- const: common
- if:
properties:
compatible:
@ -303,6 +329,7 @@ allOf:
enum:
- qcom,sdm845-qhp-pcie-phy
- qcom,sdm845-qmp-pcie-phy
- qcom,sdx55-qmp-pcie-phy
- qcom,sm8250-qmp-gen3x1-pcie-phy
- qcom,sm8250-qmp-gen3x2-pcie-phy
- qcom,sm8250-qmp-modem-pcie-phy

View File

@ -1,24 +0,0 @@
* Renesas R-Car generation 3 PCIe PHY
This file provides information on what the device node for the R-Car
generation 3 PCIe PHY contains.
Required properties:
- compatible: "renesas,r8a77980-pcie-phy" if the device is a part of the
R8A77980 SoC.
- reg: offset and length of the register block.
- clocks: clock phandle and specifier pair.
- power-domains: power domain phandle and specifier pair.
- resets: reset phandle and specifier pair.
- #phy-cells: see phy-bindings.txt in the same directory, must be <0>.
Example (R-Car V3H):
pcie-phy@e65d0000 {
compatible = "renesas,r8a77980-pcie-phy";
reg = <0 0xe65d0000 0 0x8000>;
#phy-cells = <0>;
clocks = <&cpg CPG_MOD 319>;
power-domains = <&sysc 32>;
resets = <&cpg 319>;
};

View File

@ -0,0 +1,53 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/renesas,rcar-gen3-pcie-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas R-Car Generation 3 PCIe PHY
maintainers:
- Sergei Shtylyov <sergei.shtylyov@gmail.com>
properties:
compatible:
const: renesas,r8a77980-pcie-phy
reg:
maxItems: 1
clocks:
maxItems: 1
power-domains:
maxItems: 1
resets:
maxItems: 1
'#phy-cells':
const: 0
required:
- compatible
- reg
- clocks
- power-domains
- resets
- '#phy-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/r8a77980-cpg-mssr.h>
#include <dt-bindings/power/r8a77980-sysc.h>
pcie-phy@e65d0000 {
compatible = "renesas,r8a77980-pcie-phy";
reg = <0xe65d0000 0x8000>;
#phy-cells = <0>;
clocks = <&cpg CPG_MOD 319>;
power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
resets = <&cpg 319>;
};

View File

@ -0,0 +1,79 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/rockchip-inno-csi-dphy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Rockchip SoC MIPI RX0 D-PHY Device Tree Bindings
maintainers:
- Heiko Stuebner <heiko@sntech.de>
description: |
The Rockchip SoC has a MIPI CSI D-PHY based on an Innosilicon IP wich
connects to the ISP1 (Image Signal Processing unit v1.0) for CSI cameras.
properties:
compatible:
enum:
- rockchip,px30-csi-dphy
- rockchip,rk1808-csi-dphy
- rockchip,rk3326-csi-dphy
- rockchip,rk3368-csi-dphy
reg:
maxItems: 1
clocks:
maxItems: 1
clock-names:
const: pclk
'#phy-cells':
const: 0
power-domains:
description: Video in/out power domain.
maxItems: 1
resets:
items:
- description: exclusive PHY reset line
reset-names:
items:
- const: apb
rockchip,grf:
$ref: /schemas/types.yaml#/definitions/phandle
description:
Some additional phy settings are access through GRF regs.
required:
- compatible
- reg
- clocks
- clock-names
- '#phy-cells'
- power-domains
- resets
- reset-names
- rockchip,grf
additionalProperties: false
examples:
- |
csi_dphy: phy@ff2f0000 {
compatible = "rockchip,px30-csi-dphy";
reg = <0xff2f0000 0x4000>;
clocks = <&cru 1>;
clock-names = "pclk";
#phy-cells = <0>;
power-domains = <&power 1>;
resets = <&cru 1>;
reset-names = "apb";
rockchip,grf = <&grf>;
};

View File

@ -1,52 +0,0 @@
ROCKCHIP USB2 PHY
Required properties:
- compatible: matching the soc type, one of
"rockchip,rk3066a-usb-phy"
"rockchip,rk3188-usb-phy"
"rockchip,rk3288-usb-phy"
- #address-cells: should be 1
- #size-cells: should be 0
Deprecated properties:
- rockchip,grf : phandle to the syscon managing the "general
register files" - phy should be a child of the GRF instead
Sub-nodes:
Each PHY should be represented as a sub-node.
Sub-nodes
required properties:
- #phy-cells: should be 0
- reg: PHY configure reg address offset in GRF
"0x320" - for PHY attach to OTG controller
"0x334" - for PHY attach to HOST0 controller
"0x348" - for PHY attach to HOST1 controller
Optional Properties:
- clocks : phandle + clock specifier for the phy clocks
- clock-names: string, clock name, must be "phyclk"
- #clock-cells: for users of the phy-pll, should be 0
- reset-names: Only allow the following entries:
- phy-reset
- resets: Must contain an entry for each entry in reset-names.
- vbus-supply: power-supply phandle for vbus power source
Example:
grf: syscon@ff770000 {
compatible = "rockchip,rk3288-grf", "syscon", "simple-mfd";
...
usbphy: phy {
compatible = "rockchip,rk3288-usb-phy";
#address-cells = <1>;
#size-cells = <0>;
usbphy0: usb-phy0 {
#phy-cells = <0>;
reg = <0x320>;
};
};
};

View File

@ -0,0 +1,81 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/rockchip-usb-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Rockchip USB2.0 phy
maintainers:
- Heiko Stuebner <heiko@sntech.de>
properties:
compatible:
oneOf:
- const: rockchip,rk3288-usb-phy
- items:
- enum:
- rockchip,rk3066a-usb-phy
- rockchip,rk3188-usb-phy
- const: rockchip,rk3288-usb-phy
"#address-cells":
const: 1
"#size-cells":
const: 0
required:
- compatible
- "#address-cells"
- "#size-cells"
additionalProperties: false
patternProperties:
"usb-phy@[0-9a-f]+$":
type: object
properties:
reg:
maxItems: 1
"#phy-cells":
const: 0
clocks:
maxItems: 1
clock-names:
const: phyclk
"#clock-cells":
const: 0
resets:
maxItems: 1
reset-names:
const: phy-reset
vbus-supply:
description: phandle for vbus power source
required:
- reg
- "#phy-cells"
additionalProperties: false
examples:
- |
usbphy: usbphy {
compatible = "rockchip,rk3288-usb-phy";
#address-cells = <1>;
#size-cells = <0>;
usbphy0: usb-phy@320 {
reg = <0x320>;
#phy-cells = <0>;
};
};

View File

@ -0,0 +1,56 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/phy/ti,tcan104x-can.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: TCAN104x CAN TRANSCEIVER PHY
maintainers:
- Aswath Govindraju <a-govindraju@ti.com>
properties:
$nodename:
pattern: "^can-phy"
compatible:
enum:
- ti,tcan1042
- ti,tcan1043
'#phy-cells':
const: 0
standby-gpios:
description:
gpio node to toggle standby signal on transceiver
maxItems: 1
enable-gpios:
description:
gpio node to toggle enable signal on transceiver
maxItems: 1
max-bitrate:
$ref: /schemas/types.yaml#/definitions/uint32
description:
max bit rate supported in bps
minimum: 1
required:
- compatible
- '#phy-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
transceiver1: can-phy {
compatible = "ti,tcan1043";
#phy-cells = <0>;
max-bitrate = <5000000>;
standby-gpios = <&wakeup_gpio1 16 GPIO_ACTIVE_LOW>;
enable-gpios = <&main_gpio1 67 GPIO_ACTIVE_HIGH>;
};

View File

@ -4041,7 +4041,9 @@ W: https://github.com/linux-can
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git
F: Documentation/devicetree/bindings/net/can/
F: Documentation/devicetree/bindings/phy/ti,tcan104x-can.yaml
F: drivers/net/can/
F: drivers/phy/phy-can-transceiver.c
F: include/linux/can/bittiming.h
F: include/linux/can/dev.h
F: include/linux/can/led.h
@ -10897,7 +10899,7 @@ MARVELL ARMADA 3700 PHY DRIVERS
M: Miquel Raynal <miquel.raynal@bootlin.com>
S: Maintained
F: Documentation/devicetree/bindings/phy/phy-mvebu-comphy.txt
F: Documentation/devicetree/bindings/phy/phy-mvebu-utmi.txt
F: Documentation/devicetree/bindings/phy/marvell,armada-3700-utmi-phy.yaml
F: drivers/phy/marvell/phy-mvebu-a3700-comphy.c
F: drivers/phy/marvell/phy-mvebu-a3700-utmi.c

View File

@ -61,6 +61,15 @@ config USB_LGM_PHY
interface to interact with USB GEN-II and USB 3.x PHY that is part
of the Intel network SOC.
config PHY_CAN_TRANSCEIVER
tristate "CAN transceiver PHY"
select GENERIC_PHY
help
This option enables support for CAN transceivers as a PHY. This
driver provides function for putting the transceivers in various
functional modes using gpios and sets the attribute max link
rate, for CAN drivers.
source "drivers/phy/allwinner/Kconfig"
source "drivers/phy/amlogic/Kconfig"
source "drivers/phy/broadcom/Kconfig"

View File

@ -5,6 +5,7 @@
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o
obj-$(CONFIG_PHY_CAN_TRANSCEIVER) += phy-can-transceiver.o
obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o

View File

@ -215,10 +215,8 @@ static int bcm_ns_usb3_mdio_probe(struct mdio_device *mdiodev)
return err;
usb3->dmp = devm_ioremap_resource(dev, &res);
if (IS_ERR(usb3->dmp)) {
dev_err(dev, "Failed to map DMP regs\n");
if (IS_ERR(usb3->dmp))
return PTR_ERR(usb3->dmp);
}
usb3->phy = devm_phy_create(dev, NULL, &ops);
if (IS_ERR(usb3->phy)) {

View File

@ -47,10 +47,8 @@ static int mmp3_hsic_phy_probe(struct platform_device *pdev)
resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, resource);
if (IS_ERR(base)) {
dev_err(dev, "failed to remap PHY regs\n");
if (IS_ERR(base))
return PTR_ERR(base);
}
phy = devm_phy_create(dev, NULL, &mmp3_hsic_phy_ops);
if (IS_ERR(phy)) {

View File

@ -119,9 +119,7 @@ static int mtk_hdmi_phy_probe(struct platform_device *pdev)
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hdmi_phy->regs = devm_ioremap_resource(dev, mem);
if (IS_ERR(hdmi_phy->regs)) {
ret = PTR_ERR(hdmi_phy->regs);
dev_err(dev, "Failed to get memory resource: %d\n", ret);
return ret;
return PTR_ERR(hdmi_phy->regs);
}
ref_clk = devm_clk_get(dev, "pll_ref");

View File

@ -151,9 +151,7 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mipi_tx->regs = devm_ioremap_resource(dev, mem);
if (IS_ERR(mipi_tx->regs)) {
ret = PTR_ERR(mipi_tx->regs);
dev_err(dev, "Failed to get memory resource: %d\n", ret);
return ret;
return PTR_ERR(mipi_tx->regs);
}
ref_clk = devm_clk_get(dev, NULL);

View File

@ -0,0 +1,146 @@
// SPDX-License-Identifier: GPL-2.0
/*
* phy-can-transceiver.c - phy driver for CAN transceivers
*
* Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com
*
*/
#include<linux/phy/phy.h>
#include<linux/platform_device.h>
#include<linux/module.h>
#include<linux/gpio.h>
#include<linux/gpio/consumer.h>
struct can_transceiver_data {
u32 flags;
#define CAN_TRANSCEIVER_STB_PRESENT BIT(0)
#define CAN_TRANSCEIVER_EN_PRESENT BIT(1)
};
struct can_transceiver_phy {
struct phy *generic_phy;
struct gpio_desc *standby_gpio;
struct gpio_desc *enable_gpio;
};
/* Power on function */
static int can_transceiver_phy_power_on(struct phy *phy)
{
struct can_transceiver_phy *can_transceiver_phy = phy_get_drvdata(phy);
if (can_transceiver_phy->standby_gpio)
gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio, 0);
if (can_transceiver_phy->enable_gpio)
gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio, 1);
return 0;
}
/* Power off function */
static int can_transceiver_phy_power_off(struct phy *phy)
{
struct can_transceiver_phy *can_transceiver_phy = phy_get_drvdata(phy);
if (can_transceiver_phy->standby_gpio)
gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio, 1);
if (can_transceiver_phy->enable_gpio)
gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio, 0);
return 0;
}
static const struct phy_ops can_transceiver_phy_ops = {
.power_on = can_transceiver_phy_power_on,
.power_off = can_transceiver_phy_power_off,
.owner = THIS_MODULE,
};
static const struct can_transceiver_data tcan1042_drvdata = {
.flags = CAN_TRANSCEIVER_STB_PRESENT,
};
static const struct can_transceiver_data tcan1043_drvdata = {
.flags = CAN_TRANSCEIVER_STB_PRESENT | CAN_TRANSCEIVER_EN_PRESENT,
};
static const struct of_device_id can_transceiver_phy_ids[] = {
{
.compatible = "ti,tcan1042",
.data = &tcan1042_drvdata
},
{
.compatible = "ti,tcan1043",
.data = &tcan1043_drvdata
},
{ }
};
MODULE_DEVICE_TABLE(of, can_transceiver_phy_ids);
static int can_transceiver_phy_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
struct device *dev = &pdev->dev;
struct can_transceiver_phy *can_transceiver_phy;
const struct can_transceiver_data *drvdata;
const struct of_device_id *match;
struct phy *phy;
struct gpio_desc *standby_gpio;
struct gpio_desc *enable_gpio;
u32 max_bitrate = 0;
can_transceiver_phy = devm_kzalloc(dev, sizeof(struct can_transceiver_phy), GFP_KERNEL);
if (!can_transceiver_phy)
return -ENOMEM;
match = of_match_node(can_transceiver_phy_ids, pdev->dev.of_node);
drvdata = match->data;
phy = devm_phy_create(dev, dev->of_node,
&can_transceiver_phy_ops);
if (IS_ERR(phy)) {
dev_err(dev, "failed to create can transceiver phy\n");
return PTR_ERR(phy);
}
device_property_read_u32(dev, "max-bitrate", &max_bitrate);
if (!max_bitrate)
dev_warn(dev, "Invalid value for transceiver max bitrate. Ignoring bitrate limit\n");
phy->attrs.max_link_rate = max_bitrate;
can_transceiver_phy->generic_phy = phy;
if (drvdata->flags & CAN_TRANSCEIVER_STB_PRESENT) {
standby_gpio = devm_gpiod_get(dev, "standby", GPIOD_OUT_HIGH);
if (IS_ERR(standby_gpio))
return PTR_ERR(standby_gpio);
can_transceiver_phy->standby_gpio = standby_gpio;
}
if (drvdata->flags & CAN_TRANSCEIVER_EN_PRESENT) {
enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
if (IS_ERR(enable_gpio))
return PTR_ERR(enable_gpio);
can_transceiver_phy->enable_gpio = enable_gpio;
}
phy_set_drvdata(can_transceiver_phy->generic_phy, can_transceiver_phy);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
return PTR_ERR_OR_ZERO(phy_provider);
}
static struct platform_driver can_transceiver_phy_driver = {
.probe = can_transceiver_phy_probe,
.driver = {
.name = "can-transceiver-phy",
.of_match_table = can_transceiver_phy_ids,
},
};
module_platform_driver(can_transceiver_phy_driver);
MODULE_AUTHOR("Faiz Abbas <faiz_abbas@ti.com>");
MODULE_AUTHOR("Aswath Govindraju <a-govindraju@ti.com>");
MODULE_DESCRIPTION("CAN TRANSCEIVER PHY driver");
MODULE_LICENSE("GPL v2");

View File

@ -15,7 +15,7 @@
/*
* Minimum D-PHY timings based on MIPI D-PHY specification. Derived
* from the valid ranges specified in Section 6.9, Table 14, Page 41
* of the D-PHY specification (v2.1).
* of the D-PHY specification (v1.2).
*/
int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
unsigned int bpp,

View File

@ -697,16 +697,18 @@ struct phy *phy_get(struct device *dev, const char *string)
struct phy *phy;
struct device_link *link;
if (dev->of_node) {
if (string)
index = of_property_match_string(dev->of_node, "phy-names",
string);
else
index = 0;
phy = _of_phy_get(dev->of_node, index);
} else {
if (string == NULL) {
dev_WARN(dev, "missing string\n");
return ERR_PTR(-EINVAL);
}
if (dev->of_node) {
index = of_property_match_string(dev->of_node, "phy-names",
string);
phy = _of_phy_get(dev->of_node, index);
} else {
phy = phy_find(dev, string);
}
if (IS_ERR(phy))

View File

@ -961,7 +961,8 @@ static void xgene_phy_sata_cfg_lanes(struct xgene_phy_ctx *ctx)
serdes_wr(ctx, lane, RXTX_REG1, val);
/* Latch VTT value based on the termination to ground and
enable TX FIFO */
* enable TX FIFO
*/
serdes_rd(ctx, lane, RXTX_REG2, &val);
val = RXTX_REG2_VTT_ENA_SET(val, 0x1);
val = RXTX_REG2_VTT_SEL_SET(val, 0x1);

View File

@ -35,6 +35,7 @@
#define PLL_READY_GATE_EN BIT(3)
/* QPHY_PCS_STATUS bit */
#define PHYSTATUS BIT(6)
#define PHYSTATUS_4_20 BIT(7)
/* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */
#define PCS_READY BIT(0)
@ -143,6 +144,13 @@ static const unsigned int msm8996_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_READY_STATUS] = 0x168,
};
static const unsigned int ipq_pciephy_gen3_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_SW_RESET] = 0x00,
[QPHY_START_CTRL] = 0x44,
[QPHY_PCS_STATUS] = 0x14,
[QPHY_PCS_POWER_DOWN_CONTROL] = 0x40,
};
static const unsigned int pciephy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_COM_SW_RESET] = 0x400,
[QPHY_COM_POWER_DOWN_CONTROL] = 0x404,
@ -614,6 +622,113 @@ static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG2, 0x08),
};
static const struct qmp_phy_init_tbl ipq6018_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER1, 0x7d),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER2, 0x01),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE0, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE0, 0x05),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE1, 0x08),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CLKBUFLR_EN, 0x18),
QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x90),
QMP_PHY_INIT_CFG(QSERDES_PLL_SYS_CLK_CTRL, 0x02),
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, 0xd4),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE0, 0x14),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE1, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE1, 0x29),
QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TRIM, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE0, 0x09),
QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE1, 0x09),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE0, 0x28),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE1, 0x28),
QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CTRL_BY_PSM, 0x01),
QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_EN_SEL, 0x08),
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, 0x68),
QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE1, 0x53),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE0, 0xab),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE0, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE1, 0x05),
QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE0, 0xa0),
QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE1, 0xa0),
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_CLK_SELECT, 0x32),
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),
};
static const struct qmp_phy_init_tbl ipq6018_pcie_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_TX0_RES_CODE_LANE_OFFSET_TX, 0x02),
QMP_PHY_INIT_CFG(QSERDES_TX0_LANE_MODE_1, 0x06),
QMP_PHY_INIT_CFG(QSERDES_TX0_RCV_DETECT_LVL_2, 0x12),
};
static const struct qmp_phy_init_tbl ipq6018_pcie_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_FO_GAIN, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_GAIN, 0x02),
QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_SATURATION_AND_ENABLE, 0x7f),
QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_PI_CONTROLS, 0x70),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL2, 0x61),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL3, 0x04),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL4, 0x1e),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_LOW, 0xc0),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_HIGH, 0x00),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x73),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_ENABLES, 0x1c),
QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_CNTRL, 0x03),
QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_DEGLITCH_CNTRL, 0x14),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_LOW, 0xf0),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH, 0x01),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH2, 0x2f),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH3, 0xd3),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH4, 0x40),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_LOW, 0x01),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH, 0x02),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH2, 0xc8),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH3, 0x09),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH4, 0xb1),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_LOW, 0x00),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH, 0x02),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH2, 0xc8),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH3, 0x09),
QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH4, 0xb1),
QMP_PHY_INIT_CFG(QSERDES_RX0_DFE_EN_TIMER, 0x04),
};
static const struct qmp_phy_init_tbl ipq6018_pcie_pcs_tbl[] = {
QMP_PHY_INIT_CFG(PCS_COM_FLL_CNTRL1, 0x01),
QMP_PHY_INIT_CFG(PCS_COM_REFGEN_REQ_CONFIG1, 0x0d),
QMP_PHY_INIT_CFG(PCS_COM_G12S1_TXDEEMPH_M3P5DB, 0x10),
QMP_PHY_INIT_CFG(PCS_COM_RX_SIGDET_LVL, 0xaa),
QMP_PHY_INIT_CFG(PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
QMP_PHY_INIT_CFG(PCS_COM_RX_DCC_CAL_CONFIG, 0x01),
QMP_PHY_INIT_CFG(PCS_COM_EQ_CONFIG5, 0x01),
QMP_PHY_INIT_CFG(PCS_PCIE_POWER_STATE_CONFIG2, 0x0d),
QMP_PHY_INIT_CFG(PCS_PCIE_POWER_STATE_CONFIG4, 0x07),
QMP_PHY_INIT_CFG(PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
QMP_PHY_INIT_CFG(PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
QMP_PHY_INIT_CFG(PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
QMP_PHY_INIT_CFG(PCS_PCIE_OSC_DTCT_ACTIONS, 0x00),
QMP_PHY_INIT_CFG(PCS_PCIE_EQ_CONFIG1, 0x11),
QMP_PHY_INIT_CFG(PCS_PCIE_PRESET_P10_PRE, 0x00),
QMP_PHY_INIT_CFG(PCS_PCIE_PRESET_P10_POST, 0x58),
};
static const struct qmp_phy_init_tbl ipq8074_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x18),
QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10),
@ -2110,6 +2225,101 @@ static const struct qmp_phy_init_tbl sdx55_usb3_uniphy_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f),
};
static const struct qmp_phy_init_tbl sdx55_qmp_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x19),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x19),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x46),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_CFG, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x7f),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x4b),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x50),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0xfb),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE1, 0xfb),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x12),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE0, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_MISC1, 0x88),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTERNAL_DIG_CORECLK_DIV, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_MODE, 0x17),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_DC_LEVEL_CTRL, 0x0b),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x56),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1d),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0x4b),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x22),
};
static const struct qmp_phy_init_tbl sdx55_qmp_pcie_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_1, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_2, 0xf6),
QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_3, 0x13),
QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_VMODE_CTRL1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_PI_QEC_CTRL, 0x00),
};
static const struct qmp_phy_init_tbl sdx55_qmp_pcie_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_FO_GAIN_RATE2, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_UCDR_PI_CONTROLS, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_AUX_DATA_TCOARSE_TFINE, 0x7f),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_3, 0x55),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_DAC_ENABLE1, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_DAC_ENABLE2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_VGA_CAL_CNTRL2, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x27),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B1, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B2, 0x5a),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B3, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B4, 0x37),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B0, 0xbd),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B1, 0xf9),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B2, 0xbf),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B3, 0xce),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B4, 0x62),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B0, 0xbf),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B1, 0x7d),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B2, 0xbf),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B3, 0xcf),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B4, 0xd6),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_PHPRE_CTRL, 0xa0),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_MARG_COARSE_CTRL2, 0x12),
};
static const struct qmp_phy_init_tbl sdx55_qmp_pcie_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_RX_SIGDET_LVL, 0x77),
QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG2, 0x01),
QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG4, 0x16),
QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG5, 0x02),
};
static const struct qmp_phy_init_tbl sdx55_qmp_pcie_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_EQ_CONFIG1, 0x17),
QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G3_RXEQEVAL_TIME, 0x13),
QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_RXEQEVAL_TIME, 0x13),
QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG2, 0x01),
QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG5, 0x02),
QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_SW_CTRL2, 0x00),
QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_MX_CTRL2, 0x00),
};
static const struct qmp_phy_init_tbl sm8350_ufsphy_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0xd9),
QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x11),
@ -2411,6 +2621,8 @@ struct qmp_phy_cfg {
unsigned int start_ctrl;
unsigned int pwrdn_ctrl;
unsigned int mask_com_pcs_ready;
/* bit offset of PHYSTATUS in QPHY_PCS_STATUS register */
unsigned int phy_status;
/* true, if PHY has a separate PHY_COM control block */
bool has_phy_com_ctrl;
@ -2624,6 +2836,7 @@ static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = {
.start_ctrl = SERDES_START | PCS_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS,
};
static const struct qmp_phy_cfg msm8996_pciephy_cfg = {
@ -2649,6 +2862,7 @@ static const struct qmp_phy_cfg msm8996_pciephy_cfg = {
.start_ctrl = PCS_START | PLL_READY_GATE_EN,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.mask_com_pcs_ready = PCS_READY,
.phy_status = PHYSTATUS,
.has_phy_com_ctrl = true,
.has_lane_rst = true,
@ -2678,6 +2892,7 @@ static const struct qmp_phy_cfg msm8996_ufs_cfg = {
.start_ctrl = SERDES_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS,
.no_pcs_sw_reset = true,
};
@ -2704,6 +2919,7 @@ static const struct qmp_phy_cfg msm8996_usb3phy_cfg = {
.start_ctrl = SERDES_START | PCS_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS,
};
static const char * const ipq8074_pciephy_clk_l[] = {
@ -2734,6 +2950,37 @@ static const struct qmp_phy_cfg ipq8074_pciephy_cfg = {
.num_vregs = 0,
.regs = pciephy_regs_layout,
.start_ctrl = SERDES_START | PCS_START,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS,
.has_phy_com_ctrl = false,
.has_lane_rst = false,
.has_pwrdn_delay = true,
.pwrdn_delay_min = 995, /* us */
.pwrdn_delay_max = 1005, /* us */
};
static const struct qmp_phy_cfg ipq6018_pciephy_cfg = {
.type = PHY_TYPE_PCIE,
.nlanes = 1,
.serdes_tbl = ipq6018_pcie_serdes_tbl,
.serdes_tbl_num = ARRAY_SIZE(ipq6018_pcie_serdes_tbl),
.tx_tbl = ipq6018_pcie_tx_tbl,
.tx_tbl_num = ARRAY_SIZE(ipq6018_pcie_tx_tbl),
.rx_tbl = ipq6018_pcie_rx_tbl,
.rx_tbl_num = ARRAY_SIZE(ipq6018_pcie_rx_tbl),
.pcs_tbl = ipq6018_pcie_pcs_tbl,
.pcs_tbl_num = ARRAY_SIZE(ipq6018_pcie_pcs_tbl),
.clk_list = ipq8074_pciephy_clk_l,
.num_clks = ARRAY_SIZE(ipq8074_pciephy_clk_l),
.reset_list = ipq8074_pciephy_reset_l,
.num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l),
.vreg_list = NULL,
.num_vregs = 0,
.regs = ipq_pciephy_gen3_regs_layout,
.start_ctrl = SERDES_START | PCS_START,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
@ -2768,6 +3015,7 @@ static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = {
.start_ctrl = PCS_START | SERDES_START,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS,
.has_pwrdn_delay = true,
.pwrdn_delay_min = 995, /* us */
@ -2796,6 +3044,7 @@ static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = {
.start_ctrl = PCS_START | SERDES_START,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS,
.has_pwrdn_delay = true,
.pwrdn_delay_min = 995, /* us */
@ -2834,6 +3083,7 @@ static const struct qmp_phy_cfg sm8250_qmp_gen3x1_pciephy_cfg = {
.start_ctrl = PCS_START | SERDES_START,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS,
.has_pwrdn_delay = true,
.pwrdn_delay_min = 995, /* us */
@ -2872,6 +3122,7 @@ static const struct qmp_phy_cfg sm8250_qmp_gen3x2_pciephy_cfg = {
.start_ctrl = PCS_START | SERDES_START,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS,
.is_dual_lane_phy = true,
.has_pwrdn_delay = true,
@ -2901,6 +3152,7 @@ static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = {
.start_ctrl = SERDES_START | PCS_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS,
.has_pwrdn_delay = true,
.pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN,
@ -2932,6 +3184,7 @@ static const struct qmp_phy_cfg sc7180_usb3phy_cfg = {
.start_ctrl = SERDES_START | PCS_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS,
.has_pwrdn_delay = true,
.pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN,
@ -3003,6 +3256,7 @@ static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = {
.start_ctrl = SERDES_START | PCS_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS,
.has_pwrdn_delay = true,
.pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN,
@ -3029,6 +3283,7 @@ static const struct qmp_phy_cfg sdm845_ufsphy_cfg = {
.start_ctrl = SERDES_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS,
.is_dual_lane_phy = true,
.no_pcs_sw_reset = true,
@ -3056,6 +3311,7 @@ static const struct qmp_phy_cfg msm8998_pciephy_cfg = {
.start_ctrl = SERDES_START | PCS_START,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS,
};
static const struct qmp_phy_cfg msm8998_usb3phy_cfg = {
@ -3080,6 +3336,7 @@ static const struct qmp_phy_cfg msm8998_usb3phy_cfg = {
.start_ctrl = SERDES_START | PCS_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS,
.is_dual_lane_phy = true,
};
@ -3104,6 +3361,7 @@ static const struct qmp_phy_cfg sm8150_ufsphy_cfg = {
.start_ctrl = SERDES_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS,
.is_dual_lane_phy = true,
};
@ -3130,6 +3388,8 @@ static const struct qmp_phy_cfg sm8150_usb3phy_cfg = {
.start_ctrl = SERDES_START | PCS_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS,
.has_pwrdn_delay = true,
.pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN,
@ -3161,6 +3421,7 @@ static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = {
.start_ctrl = SERDES_START | PCS_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS,
.has_pwrdn_delay = true,
.pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN,
@ -3189,6 +3450,7 @@ static const struct qmp_phy_cfg sm8250_usb3phy_cfg = {
.start_ctrl = SERDES_START | PCS_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS,
.has_pwrdn_delay = true,
.pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN,
@ -3220,6 +3482,7 @@ static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = {
.start_ctrl = SERDES_START | PCS_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS,
.has_pwrdn_delay = true,
.pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN,
@ -3288,12 +3551,45 @@ static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = {
.start_ctrl = SERDES_START | PCS_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS,
.has_pwrdn_delay = true,
.pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN,
.pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX,
};
static const struct qmp_phy_cfg sdx55_qmp_pciephy_cfg = {
.type = PHY_TYPE_PCIE,
.nlanes = 2,
.serdes_tbl = sdx55_qmp_pcie_serdes_tbl,
.serdes_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_serdes_tbl),
.tx_tbl = sdx55_qmp_pcie_tx_tbl,
.tx_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_tx_tbl),
.rx_tbl = sdx55_qmp_pcie_rx_tbl,
.rx_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_rx_tbl),
.pcs_tbl = sdx55_qmp_pcie_pcs_tbl,
.pcs_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_tbl),
.pcs_misc_tbl = sdx55_qmp_pcie_pcs_misc_tbl,
.pcs_misc_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_misc_tbl),
.clk_list = sdm845_pciephy_clk_l,
.num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l),
.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 = sm8250_pcie_regs_layout,
.start_ctrl = PCS_START | SERDES_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS_4_20,
.is_dual_lane_phy = true,
.has_pwrdn_delay = true,
.pwrdn_delay_min = 995, /* us */
.pwrdn_delay_max = 1005, /* us */
};
static const struct qmp_phy_cfg sm8350_ufsphy_cfg = {
.type = PHY_TYPE_UFS,
.nlanes = 2,
@ -3314,6 +3610,7 @@ static const struct qmp_phy_cfg sm8350_ufsphy_cfg = {
.start_ctrl = SERDES_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS,
.is_dual_lane_phy = true,
};
@ -3340,6 +3637,7 @@ static const struct qmp_phy_cfg sm8350_usb3phy_cfg = {
.start_ctrl = SERDES_START | PCS_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS,
.has_pwrdn_delay = true,
.pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN,
@ -3371,6 +3669,7 @@ static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = {
.start_ctrl = SERDES_START | PCS_START,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS,
.has_pwrdn_delay = true,
.pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN,
@ -3993,10 +4292,8 @@ static int qcom_qmp_phy_com_init(struct qmp_phy *qphy)
}
ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks);
if (ret) {
dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret);
if (ret)
goto err_rst;
}
if (cfg->has_phy_dp_com_ctrl) {
qphy_setbits(dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL,
@ -4238,7 +4535,7 @@ static int qcom_qmp_phy_power_on(struct phy *phy)
ready = PCS_READY;
} else {
status = pcs + cfg->regs[QPHY_PCS_STATUS];
mask = PHYSTATUS;
mask = cfg->phy_status;
ready = 0;
}
@ -4430,10 +4727,8 @@ static int __maybe_unused qcom_qmp_phy_runtime_resume(struct device *dev)
}
ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks);
if (ret) {
dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret);
if (ret)
return ret;
}
ret = clk_prepare_enable(qphy->pipe_clk);
if (ret) {
@ -4927,6 +5222,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
}, {
.compatible = "qcom,ipq8074-qmp-pcie-phy",
.data = &ipq8074_pciephy_cfg,
}, {
.compatible = "qcom,ipq6018-qmp-pcie-phy",
.data = &ipq6018_pciephy_cfg,
}, {
.compatible = "qcom,sc7180-qmp-usb3-phy",
.data = &sc7180_usb3phy_cfg,
@ -4990,6 +5288,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
}, {
.compatible = "qcom,sm8250-qmp-modem-pcie-phy",
.data = &sm8250_qmp_gen3x2_pciephy_cfg,
}, {
.compatible = "qcom,sdx55-qmp-pcie-phy",
.data = &sdx55_qmp_pciephy_cfg,
}, {
.compatible = "qcom,sdx55-qmp-usb3-uni-phy",
.data = &sdx55_usb3_uniphy_cfg,

View File

@ -6,6 +6,138 @@
#ifndef QCOM_PHY_QMP_H_
#define QCOM_PHY_QMP_H_
/* QMP V2 PHY for PCIE gen3 ports - QSERDES PLL registers */
#define QSERDES_PLL_BG_TIMER 0x00c
#define QSERDES_PLL_SSC_PER1 0x01c
#define QSERDES_PLL_SSC_PER2 0x020
#define QSERDES_PLL_SSC_STEP_SIZE1_MODE0 0x024
#define QSERDES_PLL_SSC_STEP_SIZE2_MODE0 0x028
#define QSERDES_PLL_SSC_STEP_SIZE1_MODE1 0x02c
#define QSERDES_PLL_SSC_STEP_SIZE2_MODE1 0x030
#define QSERDES_PLL_BIAS_EN_CLKBUFLR_EN 0x03c
#define QSERDES_PLL_CLK_ENABLE1 0x040
#define QSERDES_PLL_SYS_CLK_CTRL 0x044
#define QSERDES_PLL_SYSCLK_BUF_ENABLE 0x048
#define QSERDES_PLL_PLL_IVCO 0x050
#define QSERDES_PLL_LOCK_CMP1_MODE0 0x054
#define QSERDES_PLL_LOCK_CMP2_MODE0 0x058
#define QSERDES_PLL_LOCK_CMP1_MODE1 0x060
#define QSERDES_PLL_LOCK_CMP2_MODE1 0x064
#define QSERDES_PLL_BG_TRIM 0x074
#define QSERDES_PLL_CLK_EP_DIV_MODE0 0x078
#define QSERDES_PLL_CLK_EP_DIV_MODE1 0x07c
#define QSERDES_PLL_CP_CTRL_MODE0 0x080
#define QSERDES_PLL_CP_CTRL_MODE1 0x084
#define QSERDES_PLL_PLL_RCTRL_MODE0 0x088
#define QSERDES_PLL_PLL_RCTRL_MODE1 0x08C
#define QSERDES_PLL_PLL_CCTRL_MODE0 0x090
#define QSERDES_PLL_PLL_CCTRL_MODE1 0x094
#define QSERDES_PLL_BIAS_EN_CTRL_BY_PSM 0x0a4
#define QSERDES_PLL_SYSCLK_EN_SEL 0x0a8
#define QSERDES_PLL_RESETSM_CNTRL 0x0b0
#define QSERDES_PLL_LOCK_CMP_EN 0x0c4
#define QSERDES_PLL_DEC_START_MODE0 0x0cc
#define QSERDES_PLL_DEC_START_MODE1 0x0d0
#define QSERDES_PLL_DIV_FRAC_START1_MODE0 0x0d8
#define QSERDES_PLL_DIV_FRAC_START2_MODE0 0x0dc
#define QSERDES_PLL_DIV_FRAC_START3_MODE0 0x0e0
#define QSERDES_PLL_DIV_FRAC_START1_MODE1 0x0e4
#define QSERDES_PLL_DIV_FRAC_START2_MODE1 0x0e8
#define QSERDES_PLL_DIV_FRAC_START3_MODE1 0x0eC
#define QSERDES_PLL_INTEGLOOP_GAIN0_MODE0 0x100
#define QSERDES_PLL_INTEGLOOP_GAIN1_MODE0 0x104
#define QSERDES_PLL_INTEGLOOP_GAIN0_MODE1 0x108
#define QSERDES_PLL_INTEGLOOP_GAIN1_MODE1 0x10c
#define QSERDES_PLL_VCO_TUNE_MAP 0x120
#define QSERDES_PLL_VCO_TUNE1_MODE0 0x124
#define QSERDES_PLL_VCO_TUNE2_MODE0 0x128
#define QSERDES_PLL_VCO_TUNE1_MODE1 0x12c
#define QSERDES_PLL_VCO_TUNE2_MODE1 0x130
#define QSERDES_PLL_VCO_TUNE_TIMER1 0x13c
#define QSERDES_PLL_VCO_TUNE_TIMER2 0x140
#define QSERDES_PLL_CLK_SELECT 0x16c
#define QSERDES_PLL_HSCLK_SEL 0x170
#define QSERDES_PLL_CORECLK_DIV 0x17c
#define QSERDES_PLL_CORE_CLK_EN 0x184
#define QSERDES_PLL_CMN_CONFIG 0x18c
#define QSERDES_PLL_SVS_MODE_CLK_SEL 0x194
#define QSERDES_PLL_CORECLK_DIV_MODE1 0x1b4
/* QMP V2 PHY for PCIE gen3 ports - QSERDES TX registers */
#define QSERDES_TX0_RES_CODE_LANE_OFFSET_TX 0x03c
#define QSERDES_TX0_HIGHZ_DRVR_EN 0x058
#define QSERDES_TX0_LANE_MODE_1 0x084
#define QSERDES_TX0_RCV_DETECT_LVL_2 0x09c
/* QMP V2 PHY for PCIE gen3 ports - QSERDES RX registers */
#define QSERDES_RX0_UCDR_FO_GAIN 0x008
#define QSERDES_RX0_UCDR_SO_GAIN 0x014
#define QSERDES_RX0_UCDR_SO_SATURATION_AND_ENABLE 0x034
#define QSERDES_RX0_UCDR_PI_CONTROLS 0x044
#define QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL2 0x0ec
#define QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL3 0x0f0
#define QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL4 0x0f4
#define QSERDES_RX0_RX_IDAC_TSETTLE_LOW 0x0f8
#define QSERDES_RX0_RX_IDAC_TSETTLE_HIGH 0x0fc
#define QSERDES_RX0_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x110
#define QSERDES_RX0_RX_OFFSET_ADAPTOR_CNTRL2 0x114
#define QSERDES_RX0_SIGDET_ENABLES 0x118
#define QSERDES_RX0_SIGDET_CNTRL 0x11c
#define QSERDES_RX0_SIGDET_DEGLITCH_CNTRL 0x124
#define QSERDES_RX0_RX_MODE_00_LOW 0x170
#define QSERDES_RX0_RX_MODE_00_HIGH 0x174
#define QSERDES_RX0_RX_MODE_00_HIGH2 0x178
#define QSERDES_RX0_RX_MODE_00_HIGH3 0x17c
#define QSERDES_RX0_RX_MODE_00_HIGH4 0x180
#define QSERDES_RX0_RX_MODE_01_LOW 0x184
#define QSERDES_RX0_RX_MODE_01_HIGH 0x188
#define QSERDES_RX0_RX_MODE_01_HIGH2 0x18c
#define QSERDES_RX0_RX_MODE_01_HIGH3 0x190
#define QSERDES_RX0_RX_MODE_01_HIGH4 0x194
#define QSERDES_RX0_RX_MODE_10_LOW 0x198
#define QSERDES_RX0_RX_MODE_10_HIGH 0x19c
#define QSERDES_RX0_RX_MODE_10_HIGH2 0x1a0
#define QSERDES_RX0_RX_MODE_10_HIGH3 0x1a4
#define QSERDES_RX0_RX_MODE_10_HIGH4 0x1a8
#define QSERDES_RX0_DFE_EN_TIMER 0x1b4
/* QMP V2 PHY for PCIE gen3 ports - PCS registers */
#define PCS_COM_FLL_CNTRL1 0x098
#define PCS_COM_FLL_CNTRL2 0x09c
#define PCS_COM_FLL_CNT_VAL_L 0x0a0
#define PCS_COM_FLL_CNT_VAL_H_TOL 0x0a4
#define PCS_COM_FLL_MAN_CODE 0x0a8
#define PCS_COM_REFGEN_REQ_CONFIG1 0x0dc
#define PCS_COM_G12S1_TXDEEMPH_M3P5DB 0x16c
#define PCS_COM_RX_SIGDET_LVL 0x188
#define PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_L 0x1a4
#define PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_H 0x1a8
#define PCS_COM_RX_DCC_CAL_CONFIG 0x1d8
#define PCS_COM_EQ_CONFIG5 0x1ec
/* QMP V2 PHY for PCIE gen3 ports - PCS Misc registers */
#define PCS_PCIE_POWER_STATE_CONFIG2 0x40c
#define PCS_PCIE_POWER_STATE_CONFIG4 0x414
#define PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x41c
#define PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L 0x440
#define PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_H 0x444
#define PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L 0x448
#define PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_H 0x44c
#define PCS_PCIE_OSC_DTCT_CONFIG2 0x45c
#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG2 0x478
#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG4 0x480
#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG5 0x484
#define PCS_PCIE_OSC_DTCT_ACTIONS 0x490
#define PCS_PCIE_EQ_CONFIG1 0x4a0
#define PCS_PCIE_EQ_CONFIG2 0x4a4
#define PCS_PCIE_PRESET_P10_PRE 0x4bc
#define PCS_PCIE_PRESET_P10_POST 0x4e0
/* Only for QMP V2 PHY - QSERDES COM registers */
#define QSERDES_COM_BG_TIMER 0x00c
#define QSERDES_COM_SSC_EN_CENTER 0x010
@ -420,6 +552,7 @@
#define QSERDES_V4_COM_SYSCLK_EN_SEL 0x094
#define QSERDES_V4_COM_RESETSM_CNTRL 0x09c
#define QSERDES_V4_COM_LOCK_CMP_EN 0x0a4
#define QSERDES_V4_COM_LOCK_CMP_CFG 0x0a8
#define QSERDES_V4_COM_LOCK_CMP1_MODE0 0x0ac
#define QSERDES_V4_COM_LOCK_CMP2_MODE0 0x0b0
#define QSERDES_V4_COM_LOCK_CMP1_MODE1 0x0b4
@ -434,6 +567,8 @@
#define QSERDES_V4_COM_DIV_FRAC_START3_MODE1 0x0e0
#define QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0 0x0ec
#define QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0 0x0f0
#define QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE1 0x0f4
#define QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE1 0x0f8
#define QSERDES_V4_COM_VCO_TUNE_CTRL 0x108
#define QSERDES_V4_COM_VCO_TUNE_MAP 0x10c
#define QSERDES_V4_COM_VCO_TUNE1_MODE0 0x110
@ -451,11 +586,15 @@
#define QSERDES_V4_COM_C_READY_STATUS 0x178
#define QSERDES_V4_COM_CMN_CONFIG 0x17c
#define QSERDES_V4_COM_SVS_MODE_CLK_SEL 0x184
#define QSERDES_V4_COM_CMN_MISC1 0x19c
#define QSERDES_V4_COM_INTERNAL_DIG_CORECLK_DIV 0x1a0
#define QSERDES_V4_COM_CMN_MODE 0x1a4
#define QSERDES_V4_COM_VCO_DC_LEVEL_CTRL 0x1a8
#define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0 0x1ac
#define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0 0x1b0
#define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1 0x1b4
#define QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL 0x1bc
#define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1 0x1b8
#define QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL 0x1bc
/* Only for QMP V4 PHY - TX registers */
#define QSERDES_V4_TX_CLKBUF_ENABLE 0x08
@ -485,6 +624,13 @@
#define QSERDES_V4_TX_VMODE_CTRL1 0xe8
#define QSERDES_V4_TX_PI_QEC_CTRL 0x104
/* Only for QMP V4_20 PHY - TX registers */
#define QSERDES_V4_20_TX_LANE_MODE_1 0x88
#define QSERDES_V4_20_TX_LANE_MODE_2 0x8c
#define QSERDES_V4_20_TX_LANE_MODE_3 0x90
#define QSERDES_V4_20_TX_VMODE_CTRL1 0xc4
#define QSERDES_V4_20_TX_PI_QEC_CTRL 0xe0
/* Only for QMP V4 PHY - RX registers */
#define QSERDES_V4_RX_UCDR_FO_GAIN 0x008
#define QSERDES_V4_RX_UCDR_SO_GAIN 0x014
@ -551,6 +697,33 @@
#define QSERDES_V4_DP_PHY_AUX_INTERRUPT_STATUS 0x0d8
#define QSERDES_V4_DP_PHY_STATUS 0x0dc
/* Only for QMP V4_20 PHY - RX registers */
#define QSERDES_V4_20_RX_FO_GAIN_RATE2 0x008
#define QSERDES_V4_20_RX_UCDR_PI_CONTROLS 0x058
#define QSERDES_V4_20_RX_AUX_DATA_TCOARSE_TFINE 0x0ac
#define QSERDES_V4_20_RX_DFE_3 0x110
#define QSERDES_V4_20_RX_DFE_DAC_ENABLE1 0x134
#define QSERDES_V4_20_RX_DFE_DAC_ENABLE2 0x138
#define QSERDES_V4_20_RX_VGA_CAL_CNTRL2 0x150
#define QSERDES_V4_20_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x178
#define QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B1 0x1c8
#define QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B2 0x1cc
#define QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B3 0x1d0
#define QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B4 0x1d4
#define QSERDES_V4_20_RX_RX_MODE_RATE2_B0 0x1d8
#define QSERDES_V4_20_RX_RX_MODE_RATE2_B1 0x1dc
#define QSERDES_V4_20_RX_RX_MODE_RATE2_B2 0x1e0
#define QSERDES_V4_20_RX_RX_MODE_RATE2_B3 0x1e4
#define QSERDES_V4_20_RX_RX_MODE_RATE2_B4 0x1e8
#define QSERDES_V4_20_RX_RX_MODE_RATE3_B0 0x1ec
#define QSERDES_V4_20_RX_RX_MODE_RATE3_B1 0x1f0
#define QSERDES_V4_20_RX_RX_MODE_RATE3_B2 0x1f4
#define QSERDES_V4_20_RX_RX_MODE_RATE3_B3 0x1f8
#define QSERDES_V4_20_RX_RX_MODE_RATE3_B4 0x1fc
#define QSERDES_V4_20_RX_PHPRE_CTRL 0x200
#define QSERDES_V4_20_RX_DFE_CTLE_POST_CAL_OFFSET 0x20c
#define QSERDES_V4_20_RX_MARG_COARSE_CTRL2 0x23c
/* Only for QMP V4 PHY - UFS PCS registers */
#define QPHY_V4_PCS_UFS_PHY_START 0x000
#define QPHY_V4_PCS_UFS_POWER_DOWN_CONTROL 0x004
@ -836,6 +1009,12 @@
#define QPHY_V4_PCS_USB3_SIGDET_STARTUP_TIMER_VAL 0x354
#define QPHY_V4_PCS_USB3_TEST_CONTROL 0x358
/* Only for QMP V4_20 PHY - USB/PCIe PCS registers */
#define QPHY_V4_20_PCS_RX_SIGDET_LVL 0x188
#define QPHY_V4_20_PCS_EQ_CONFIG2 0x1d8
#define QPHY_V4_20_PCS_EQ_CONFIG4 0x1e0
#define QPHY_V4_20_PCS_EQ_CONFIG5 0x1e4
/* Only for QMP V4 PHY - UNI has 0x300 offset for PCS_USB3 regs */
#define QPHY_V4_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL 0x618
#define QPHY_V4_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2 0x638
@ -861,6 +1040,14 @@
#define QPHY_V4_PCS_PCIE_PRESET_P10_PRE 0xbc
#define QPHY_V4_PCS_PCIE_PRESET_P10_POST 0xe0
#define QPHY_V4_20_PCS_PCIE_EQ_CONFIG1 0x0a0
#define QPHY_V4_20_PCS_PCIE_G3_RXEQEVAL_TIME 0x0f0
#define QPHY_V4_20_PCS_PCIE_G4_RXEQEVAL_TIME 0x0f4
#define QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG2 0x0fc
#define QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG5 0x108
#define QPHY_V4_20_PCS_LANE1_INSIG_SW_CTRL2 0x824
#define QPHY_V4_20_PCS_LANE1_INSIG_MX_CTRL2 0x828
/* Only for QMP V5 PHY - QSERDES COM registers */
#define QSERDES_V5_COM_PLL_IVCO 0x058
#define QSERDES_V5_COM_CP_CTRL_MODE0 0x074

View File

@ -4,7 +4,7 @@
#
config PHY_MT7621_PCI
tristate "MediaTek MT7621 PCI PHY Driver"
depends on RALINK && OF
depends on (RALINK && OF) || COMPILE_TEST
select GENERIC_PHY
select REGMAP_MMIO
help

View File

@ -5,6 +5,7 @@
*/
#include <dt-bindings/phy/phy.h>
#include <linux/clk.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/module.h>
@ -14,8 +15,6 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/sys_soc.h>
#include <mt7621.h>
#include <ralink_regs.h>
#define RG_PE1_PIPE_REG 0x02c
#define RG_PE1_PIPE_RST BIT(12)
@ -62,8 +61,6 @@
#define RG_PE1_FRC_MSTCKDIV BIT(5)
#define XTAL_MASK GENMASK(8, 6)
#define MAX_PHYS 2
/**
@ -71,6 +68,7 @@
* @dev: pointer to device
* @regmap: kernel regmap pointer
* @phy: pointer to the kernel PHY device
* @sys_clk: pointer to the system XTAL clock
* @port_base: base register
* @has_dual_port: if the phy has dual ports.
* @bypass_pipe_rst: mark if 'mt7621_bypass_pipe_rst'
@ -80,6 +78,7 @@ struct mt7621_pci_phy {
struct device *dev;
struct regmap *regmap;
struct phy *phy;
struct clk *sys_clk;
void __iomem *port_base;
bool has_dual_port;
bool bypass_pipe_rst;
@ -116,12 +115,14 @@ static void mt7621_bypass_pipe_rst(struct mt7621_pci_phy *phy)
}
}
static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy)
static int mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy)
{
struct device *dev = phy->dev;
u32 xtal_mode;
unsigned long clk_rate;
xtal_mode = FIELD_GET(XTAL_MASK, rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0));
clk_rate = clk_get_rate(phy->sys_clk);
if (!clk_rate)
return -EINVAL;
/* Set PCIe Port PHY to disable SSC */
/* Debug Xtal Type */
@ -139,13 +140,13 @@ static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy)
RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN);
}
if (xtal_mode <= 5 && xtal_mode >= 3) { /* 40MHz Xtal */
if (clk_rate == 40000000) { /* 40MHz Xtal */
/* Set Pre-divider ratio (for host mode) */
mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, RG_PE1_H_PLL_PREDIV,
FIELD_PREP(RG_PE1_H_PLL_PREDIV, 0x01));
dev_dbg(dev, "Xtal is 40MHz\n");
} else if (xtal_mode >= 6) { /* 25MHz Xal */
} else if (clk_rate == 25000000) { /* 25MHz Xal */
mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, RG_PE1_H_PLL_PREDIV,
FIELD_PREP(RG_PE1_H_PLL_PREDIV, 0x00));
@ -196,13 +197,15 @@ static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy)
mt7621_phy_rmw(phy, RG_PE1_H_PLL_BR_REG, RG_PE1_H_PLL_BR,
FIELD_PREP(RG_PE1_H_PLL_BR, 0x00));
if (xtal_mode <= 5 && xtal_mode >= 3) { /* 40MHz Xtal */
if (clk_rate == 40000000) { /* 40MHz Xtal */
/* set force mode enable of da_pe1_mstckdiv */
mt7621_phy_rmw(phy, RG_PE1_MSTCKDIV_REG,
RG_PE1_MSTCKDIV | RG_PE1_FRC_MSTCKDIV,
FIELD_PREP(RG_PE1_MSTCKDIV, 0x01) |
RG_PE1_FRC_MSTCKDIV);
}
return 0;
}
static int mt7621_pci_phy_init(struct phy *phy)
@ -212,9 +215,7 @@ static int mt7621_pci_phy_init(struct phy *phy)
if (mphy->bypass_pipe_rst)
mt7621_bypass_pipe_rst(mphy);
mt7621_set_phy_for_ssc(mphy);
return 0;
return mt7621_set_phy_for_ssc(mphy);
}
static int mt7621_pci_phy_power_on(struct phy *phy)
@ -272,8 +273,8 @@ static struct phy *mt7621_pcie_phy_of_xlate(struct device *dev,
mt7621_phy->has_dual_port = args->args[0];
dev_info(dev, "PHY for 0x%08x (dual port = %d)\n",
(unsigned int)mt7621_phy->port_base, mt7621_phy->has_dual_port);
dev_dbg(dev, "PHY for 0x%px (dual port = %d)\n",
mt7621_phy->port_base, mt7621_phy->has_dual_port);
return mt7621_phy->phy;
}
@ -324,6 +325,12 @@ static int mt7621_pci_phy_probe(struct platform_device *pdev)
return PTR_ERR(phy->phy);
}
phy->sys_clk = devm_clk_get(dev, NULL);
if (IS_ERR(phy->sys_clk)) {
dev_err(dev, "failed to get phy clock\n");
return PTR_ERR(phy->sys_clk);
}
phy_set_drvdata(phy->phy, phy);
provider = devm_of_phy_provider_register(dev, mt7621_pcie_phy_of_xlate);

View File

@ -48,6 +48,15 @@ config PHY_ROCKCHIP_INNO_USB2
help
Support for Rockchip USB2.0 PHY with Innosilicon IP block.
config PHY_ROCKCHIP_INNO_CSIDPHY
tristate "Rockchip Innosilicon MIPI CSI PHY driver"
depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
select GENERIC_PHY
select GENERIC_PHY_MIPI_DPHY
help
Enable this to support the Rockchip MIPI CSI PHY with
Innosilicon IP block.
config PHY_ROCKCHIP_INNO_DSIDPHY
tristate "Rockchip Innosilicon MIPI/LVDS/TTL PHY driver"
depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF

View File

@ -2,6 +2,7 @@
obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o
obj-$(CONFIG_PHY_ROCKCHIP_DPHY_RX0) += phy-rockchip-dphy-rx0.o
obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o
obj-$(CONFIG_PHY_ROCKCHIP_INNO_CSIDPHY) += phy-rockchip-inno-csidphy.o
obj-$(CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY) += phy-rockchip-inno-dsidphy.o
obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += phy-rockchip-inno-hdmi.o
obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o

View File

@ -0,0 +1,459 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Rockchip MIPI RX Innosilicon DPHY driver
*
* Copyright (C) 2021 Fuzhou Rockchip Electronics Co., Ltd.
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/phy/phy.h>
#include <linux/phy/phy-mipi-dphy.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/reset.h>
/* GRF */
#define RK1808_GRF_PD_VI_CON_OFFSET 0x0430
#define RK3326_GRF_PD_VI_CON_OFFSET 0x0430
#define RK3368_GRF_SOC_CON6_OFFSET 0x0418
/* PHY */
#define CSIDPHY_CTRL_LANE_ENABLE 0x00
#define CSIDPHY_CTRL_LANE_ENABLE_CK BIT(6)
#define CSIDPHY_CTRL_LANE_ENABLE_MASK GENMASK(5, 2)
#define CSIDPHY_CTRL_LANE_ENABLE_UNDEFINED BIT(0)
/* not present on all variants */
#define CSIDPHY_CTRL_PWRCTL 0x04
#define CSIDPHY_CTRL_PWRCTL_UNDEFINED GENMASK(7, 5)
#define CSIDPHY_CTRL_PWRCTL_SYNCRST BIT(2)
#define CSIDPHY_CTRL_PWRCTL_LDO_PD BIT(1)
#define CSIDPHY_CTRL_PWRCTL_PLL_PD BIT(0)
#define CSIDPHY_CTRL_DIG_RST 0x80
#define CSIDPHY_CTRL_DIG_RST_UNDEFINED 0x1e
#define CSIDPHY_CTRL_DIG_RST_RESET BIT(0)
/* offset after ths_settle_offset */
#define CSIDPHY_CLK_THS_SETTLE 0
#define CSIDPHY_LANE_THS_SETTLE(n) (((n) + 1) * 0x80)
#define CSIDPHY_THS_SETTLE_MASK GENMASK(6, 0)
/* offset after calib_offset */
#define CSIDPHY_CLK_CALIB_EN 0
#define CSIDPHY_LANE_CALIB_EN(n) (((n) + 1) * 0x80)
#define CSIDPHY_CALIB_EN BIT(7)
/* Configure the count time of the THS-SETTLE by protocol. */
#define RK1808_CSIDPHY_CLK_WR_THS_SETTLE 0x160
#define RK3326_CSIDPHY_CLK_WR_THS_SETTLE 0x100
#define RK3368_CSIDPHY_CLK_WR_THS_SETTLE 0x100
/* Calibration reception enable */
#define RK1808_CSIDPHY_CLK_CALIB_EN 0x168
/*
* The higher 16-bit of this register is used for write protection
* only if BIT(x + 16) set to 1 the BIT(x) can be written.
*/
#define HIWORD_UPDATE(val, mask, shift) \
((val) << (shift) | (mask) << ((shift) + 16))
#define HZ_TO_MHZ(freq) div_u64(freq, 1000 * 1000)
enum dphy_reg_id {
/* rk1808 & rk3326 */
GRF_DPHY_CSIPHY_FORCERXMODE,
GRF_DPHY_CSIPHY_CLKLANE_EN,
GRF_DPHY_CSIPHY_DATALANE_EN,
};
struct dphy_reg {
u32 offset;
u32 mask;
u32 shift;
};
#define PHY_REG(_offset, _width, _shift) \
{ .offset = _offset, .mask = BIT(_width) - 1, .shift = _shift, }
static const struct dphy_reg rk1808_grf_dphy_regs[] = {
[GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK1808_GRF_PD_VI_CON_OFFSET, 4, 0),
[GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RK1808_GRF_PD_VI_CON_OFFSET, 1, 8),
[GRF_DPHY_CSIPHY_DATALANE_EN] = PHY_REG(RK1808_GRF_PD_VI_CON_OFFSET, 4, 4),
};
static const struct dphy_reg rk3326_grf_dphy_regs[] = {
[GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK3326_GRF_PD_VI_CON_OFFSET, 4, 0),
[GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RK3326_GRF_PD_VI_CON_OFFSET, 1, 8),
[GRF_DPHY_CSIPHY_DATALANE_EN] = PHY_REG(RK3326_GRF_PD_VI_CON_OFFSET, 4, 4),
};
static const struct dphy_reg rk3368_grf_dphy_regs[] = {
[GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK3368_GRF_SOC_CON6_OFFSET, 4, 8),
};
struct hsfreq_range {
u32 range_h;
u8 cfg_bit;
};
struct dphy_drv_data {
int pwrctl_offset;
int ths_settle_offset;
int calib_offset;
const struct hsfreq_range *hsfreq_ranges;
int num_hsfreq_ranges;
const struct dphy_reg *grf_regs;
};
struct rockchip_inno_csidphy {
struct device *dev;
void __iomem *phy_base;
struct clk *pclk;
struct regmap *grf;
struct reset_control *rst;
const struct dphy_drv_data *drv_data;
struct phy_configure_opts_mipi_dphy config;
u8 hsfreq;
};
static inline void write_grf_reg(struct rockchip_inno_csidphy *priv,
int index, u8 value)
{
const struct dphy_drv_data *drv_data = priv->drv_data;
const struct dphy_reg *reg = &drv_data->grf_regs[index];
if (reg->offset)
regmap_write(priv->grf, reg->offset,
HIWORD_UPDATE(value, reg->mask, reg->shift));
}
/* These tables must be sorted by .range_h ascending. */
static const struct hsfreq_range rk1808_mipidphy_hsfreq_ranges[] = {
{ 109, 0x02}, { 149, 0x03}, { 199, 0x06}, { 249, 0x06},
{ 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}
};
static const struct hsfreq_range rk3326_mipidphy_hsfreq_ranges[] = {
{ 109, 0x00}, { 149, 0x01}, { 199, 0x02}, { 249, 0x03},
{ 299, 0x04}, { 399, 0x05}, { 499, 0x06}, { 599, 0x07},
{ 699, 0x08}, { 799, 0x09}, { 899, 0x0a}, {1099, 0x0b},
{1249, 0x0c}, {1349, 0x0d}, {1500, 0x0e}
};
static const struct hsfreq_range rk3368_mipidphy_hsfreq_ranges[] = {
{ 109, 0x00}, { 149, 0x01}, { 199, 0x02}, { 249, 0x03},
{ 299, 0x04}, { 399, 0x05}, { 499, 0x06}, { 599, 0x07},
{ 699, 0x08}, { 799, 0x09}, { 899, 0x0a}, {1099, 0x0b},
{1249, 0x0c}, {1349, 0x0d}, {1500, 0x0e}
};
static void rockchip_inno_csidphy_ths_settle(struct rockchip_inno_csidphy *priv,
int hsfreq, int offset)
{
const struct dphy_drv_data *drv_data = priv->drv_data;
u32 val;
val = readl(priv->phy_base + drv_data->ths_settle_offset + offset);
val &= ~CSIDPHY_THS_SETTLE_MASK;
val |= hsfreq;
writel(val, priv->phy_base + drv_data->ths_settle_offset + offset);
}
static int rockchip_inno_csidphy_configure(struct phy *phy,
union phy_configure_opts *opts)
{
struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy);
const struct dphy_drv_data *drv_data = priv->drv_data;
struct phy_configure_opts_mipi_dphy *config = &opts->mipi_dphy;
unsigned int hsfreq = 0;
unsigned int i;
u64 data_rate_mbps;
int ret;
/* pass with phy_mipi_dphy_get_default_config (with pixel rate?) */
ret = phy_mipi_dphy_config_validate(config);
if (ret)
return ret;
data_rate_mbps = HZ_TO_MHZ(config->hs_clk_rate);
dev_dbg(priv->dev, "lanes %d - data_rate_mbps %llu\n",
config->lanes, data_rate_mbps);
for (i = 0; i < drv_data->num_hsfreq_ranges; i++) {
if (drv_data->hsfreq_ranges[i].range_h >= data_rate_mbps) {
hsfreq = drv_data->hsfreq_ranges[i].cfg_bit;
break;
}
}
if (!hsfreq)
return -EINVAL;
priv->hsfreq = hsfreq;
priv->config = *config;
return 0;
}
static int rockchip_inno_csidphy_power_on(struct phy *phy)
{
struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy);
const struct dphy_drv_data *drv_data = priv->drv_data;
u64 data_rate_mbps = HZ_TO_MHZ(priv->config.hs_clk_rate);
u32 val;
int ret, i;
ret = clk_enable(priv->pclk);
if (ret < 0)
return ret;
ret = pm_runtime_resume_and_get(priv->dev);
if (ret < 0) {
clk_disable(priv->pclk);
return ret;
}
/* phy start */
if (drv_data->pwrctl_offset >= 0)
writel(CSIDPHY_CTRL_PWRCTL_UNDEFINED |
CSIDPHY_CTRL_PWRCTL_SYNCRST,
priv->phy_base + drv_data->pwrctl_offset);
/* set data lane num and enable clock lane */
val = FIELD_PREP(CSIDPHY_CTRL_LANE_ENABLE_MASK, GENMASK(priv->config.lanes - 1, 0)) |
FIELD_PREP(CSIDPHY_CTRL_LANE_ENABLE_CK, 1) |
FIELD_PREP(CSIDPHY_CTRL_LANE_ENABLE_UNDEFINED, 1);
writel(val, priv->phy_base + CSIDPHY_CTRL_LANE_ENABLE);
/* Reset dphy analog part */
if (drv_data->pwrctl_offset >= 0)
writel(CSIDPHY_CTRL_PWRCTL_UNDEFINED,
priv->phy_base + drv_data->pwrctl_offset);
usleep_range(500, 1000);
/* Reset dphy digital part */
writel(CSIDPHY_CTRL_DIG_RST_UNDEFINED,
priv->phy_base + CSIDPHY_CTRL_DIG_RST);
writel(CSIDPHY_CTRL_DIG_RST_UNDEFINED + CSIDPHY_CTRL_DIG_RST_RESET,
priv->phy_base + CSIDPHY_CTRL_DIG_RST);
/* not into receive mode/wait stopstate */
write_grf_reg(priv, GRF_DPHY_CSIPHY_FORCERXMODE, 0x0);
/* enable calibration */
if (data_rate_mbps > 1500 && drv_data->calib_offset >= 0) {
writel(CSIDPHY_CALIB_EN,
priv->phy_base + drv_data->calib_offset +
CSIDPHY_CLK_CALIB_EN);
for (i = 0; i < priv->config.lanes; i++)
writel(CSIDPHY_CALIB_EN,
priv->phy_base + drv_data->calib_offset +
CSIDPHY_LANE_CALIB_EN(i));
}
rockchip_inno_csidphy_ths_settle(priv, priv->hsfreq,
CSIDPHY_CLK_THS_SETTLE);
for (i = 0; i < priv->config.lanes; i++)
rockchip_inno_csidphy_ths_settle(priv, priv->hsfreq,
CSIDPHY_LANE_THS_SETTLE(i));
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));
return 0;
}
static int rockchip_inno_csidphy_power_off(struct phy *phy)
{
struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy);
const struct dphy_drv_data *drv_data = priv->drv_data;
/* disable all lanes */
writel(CSIDPHY_CTRL_LANE_ENABLE_UNDEFINED,
priv->phy_base + CSIDPHY_CTRL_LANE_ENABLE);
/* disable pll and ldo */
if (drv_data->pwrctl_offset >= 0)
writel(CSIDPHY_CTRL_PWRCTL_UNDEFINED |
CSIDPHY_CTRL_PWRCTL_LDO_PD |
CSIDPHY_CTRL_PWRCTL_PLL_PD,
priv->phy_base + drv_data->pwrctl_offset);
usleep_range(500, 1000);
pm_runtime_put(priv->dev);
clk_disable(priv->pclk);
return 0;
}
static int rockchip_inno_csidphy_init(struct phy *phy)
{
struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy);
return clk_prepare(priv->pclk);
}
static int rockchip_inno_csidphy_exit(struct phy *phy)
{
struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy);
clk_unprepare(priv->pclk);
return 0;
}
static const struct phy_ops rockchip_inno_csidphy_ops = {
.power_on = rockchip_inno_csidphy_power_on,
.power_off = rockchip_inno_csidphy_power_off,
.init = rockchip_inno_csidphy_init,
.exit = rockchip_inno_csidphy_exit,
.configure = rockchip_inno_csidphy_configure,
.owner = THIS_MODULE,
};
static const struct dphy_drv_data rk1808_mipidphy_drv_data = {
.pwrctl_offset = -1,
.ths_settle_offset = RK1808_CSIDPHY_CLK_WR_THS_SETTLE,
.calib_offset = RK1808_CSIDPHY_CLK_CALIB_EN,
.hsfreq_ranges = rk1808_mipidphy_hsfreq_ranges,
.num_hsfreq_ranges = ARRAY_SIZE(rk1808_mipidphy_hsfreq_ranges),
.grf_regs = rk1808_grf_dphy_regs,
};
static const struct dphy_drv_data rk3326_mipidphy_drv_data = {
.pwrctl_offset = CSIDPHY_CTRL_PWRCTL,
.ths_settle_offset = RK3326_CSIDPHY_CLK_WR_THS_SETTLE,
.calib_offset = -1,
.hsfreq_ranges = rk3326_mipidphy_hsfreq_ranges,
.num_hsfreq_ranges = ARRAY_SIZE(rk3326_mipidphy_hsfreq_ranges),
.grf_regs = rk3326_grf_dphy_regs,
};
static const struct dphy_drv_data rk3368_mipidphy_drv_data = {
.pwrctl_offset = CSIDPHY_CTRL_PWRCTL,
.ths_settle_offset = RK3368_CSIDPHY_CLK_WR_THS_SETTLE,
.calib_offset = -1,
.hsfreq_ranges = rk3368_mipidphy_hsfreq_ranges,
.num_hsfreq_ranges = ARRAY_SIZE(rk3368_mipidphy_hsfreq_ranges),
.grf_regs = rk3368_grf_dphy_regs,
};
static const struct of_device_id rockchip_inno_csidphy_match_id[] = {
{
.compatible = "rockchip,px30-csi-dphy",
.data = &rk3326_mipidphy_drv_data,
},
{
.compatible = "rockchip,rk1808-csi-dphy",
.data = &rk1808_mipidphy_drv_data,
},
{
.compatible = "rockchip,rk3326-csi-dphy",
.data = &rk3326_mipidphy_drv_data,
},
{
.compatible = "rockchip,rk3368-csi-dphy",
.data = &rk3368_mipidphy_drv_data,
},
{}
};
MODULE_DEVICE_TABLE(of, rockchip_inno_csidphy_match_id);
static int rockchip_inno_csidphy_probe(struct platform_device *pdev)
{
struct rockchip_inno_csidphy *priv;
struct device *dev = &pdev->dev;
struct phy_provider *phy_provider;
struct phy *phy;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->dev = dev;
platform_set_drvdata(pdev, priv);
priv->drv_data = of_device_get_match_data(dev);
if (!priv->drv_data) {
dev_err(dev, "Can't find device data\n");
return -ENODEV;
}
priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
"rockchip,grf");
if (IS_ERR(priv->grf)) {
dev_err(dev, "Can't find GRF syscon\n");
return PTR_ERR(priv->grf);
}
priv->phy_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->phy_base))
return PTR_ERR(priv->phy_base);
priv->pclk = devm_clk_get(dev, "pclk");
if (IS_ERR(priv->pclk)) {
dev_err(dev, "failed to get pclk\n");
return PTR_ERR(priv->pclk);
}
priv->rst = devm_reset_control_get(dev, "apb");
if (IS_ERR(priv->rst)) {
dev_err(dev, "failed to get system reset control\n");
return PTR_ERR(priv->rst);
}
phy = devm_phy_create(dev, NULL, &rockchip_inno_csidphy_ops);
if (IS_ERR(phy)) {
dev_err(dev, "failed to create phy\n");
return PTR_ERR(phy);
}
phy_set_drvdata(phy, priv);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(phy_provider)) {
dev_err(dev, "failed to register phy provider\n");
return PTR_ERR(phy_provider);
}
pm_runtime_enable(dev);
return 0;
}
static int rockchip_inno_csidphy_remove(struct platform_device *pdev)
{
struct rockchip_inno_csidphy *priv = platform_get_drvdata(pdev);
pm_runtime_disable(priv->dev);
return 0;
}
static struct platform_driver rockchip_inno_csidphy_driver = {
.driver = {
.name = "rockchip-inno-csidphy",
.of_match_table = rockchip_inno_csidphy_match_id,
},
.probe = rockchip_inno_csidphy_probe,
.remove = rockchip_inno_csidphy_remove,
};
module_platform_driver(rockchip_inno_csidphy_driver);
MODULE_AUTHOR("Heiko Stuebner <heiko.stuebner@theobroma-systems.com>");
MODULE_DESCRIPTION("Rockchip MIPI Innosilicon CSI-DPHY driver");
MODULE_LICENSE("GPL v2");

View File

@ -620,7 +620,7 @@ static int inno_hdmi_phy_rk3228_clk_set_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
const struct pre_pll_config *cfg = pre_pll_cfg_table;
const struct pre_pll_config *cfg;
unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
u32 v;
int ret;
@ -774,7 +774,7 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
const struct pre_pll_config *cfg = pre_pll_cfg_table;
const struct pre_pll_config *cfg;
unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
u32 val;
int ret;

View File

@ -1256,6 +1256,49 @@ static const struct rockchip_usb2phy_cfg rk3228_phy_cfgs[] = {
{ /* sentinel */ }
};
static const struct rockchip_usb2phy_cfg rk3308_phy_cfgs[] = {
{
.reg = 0x100,
.num_ports = 2,
.clkout_ctl = { 0x108, 4, 4, 1, 0 },
.port_cfgs = {
[USB2PHY_PORT_OTG] = {
.phy_sus = { 0x0100, 8, 0, 0, 0x1d1 },
.bvalid_det_en = { 0x3020, 2, 2, 0, 1 },
.bvalid_det_st = { 0x3024, 2, 2, 0, 1 },
.bvalid_det_clr = { 0x3028, 2, 2, 0, 1 },
.ls_det_en = { 0x3020, 0, 0, 0, 1 },
.ls_det_st = { 0x3024, 0, 0, 0, 1 },
.ls_det_clr = { 0x3028, 0, 0, 0, 1 },
.utmi_avalid = { 0x0120, 10, 10, 0, 1 },
.utmi_bvalid = { 0x0120, 9, 9, 0, 1 },
.utmi_ls = { 0x0120, 5, 4, 0, 1 },
},
[USB2PHY_PORT_HOST] = {
.phy_sus = { 0x0104, 8, 0, 0, 0x1d1 },
.ls_det_en = { 0x3020, 1, 1, 0, 1 },
.ls_det_st = { 0x3024, 1, 1, 0, 1 },
.ls_det_clr = { 0x3028, 1, 1, 0, 1 },
.utmi_ls = { 0x0120, 17, 16, 0, 1 },
.utmi_hstdet = { 0x0120, 19, 19, 0, 1 }
}
},
.chg_det = {
.opmode = { 0x0100, 3, 0, 5, 1 },
.cp_det = { 0x0120, 24, 24, 0, 1 },
.dcp_det = { 0x0120, 23, 23, 0, 1 },
.dp_det = { 0x0120, 25, 25, 0, 1 },
.idm_sink_en = { 0x0108, 8, 8, 0, 1 },
.idp_sink_en = { 0x0108, 7, 7, 0, 1 },
.idp_src_en = { 0x0108, 9, 9, 0, 1 },
.rdm_pdwn_en = { 0x0108, 10, 10, 0, 1 },
.vdm_src_en = { 0x0108, 12, 12, 0, 1 },
.vdp_src_en = { 0x0108, 11, 11, 0, 1 },
},
},
{ /* sentinel */ }
};
static const struct rockchip_usb2phy_cfg rk3328_phy_cfgs[] = {
{
.reg = 0x100,
@ -1425,6 +1468,7 @@ static const struct rockchip_usb2phy_cfg rv1108_phy_cfgs[] = {
static const struct of_device_id rockchip_usb2phy_dt_match[] = {
{ .compatible = "rockchip,px30-usb2phy", .data = &rk3328_phy_cfgs },
{ .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs },
{ .compatible = "rockchip,rk3308-usb2phy", .data = &rk3308_phy_cfgs },
{ .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
{ .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
{ .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },

View File

@ -24,11 +24,13 @@
#define PORT_SEL_1 FIELD_PREP(PORT_SEL_MASK, 1)
#define PCL_PHY_TEST_I 0x2000
#define PCL_PHY_TEST_O 0x2004
#define TESTI_DAT_MASK GENMASK(13, 6)
#define TESTI_ADR_MASK GENMASK(5, 1)
#define TESTI_WR_EN BIT(0)
#define PCL_PHY_TEST_O 0x2004
#define TESTO_DAT_MASK GENMASK(7, 0)
#define PCL_PHY_RESET 0x200c
#define PCL_PHY_RESET_N_MNMODE BIT(8) /* =1:manual */
#define PCL_PHY_RESET_N BIT(0) /* =1:deasssert */
@ -77,11 +79,12 @@ static void uniphier_pciephy_set_param(struct uniphier_pciephy_priv *priv,
val = FIELD_PREP(TESTI_DAT_MASK, 1);
val |= FIELD_PREP(TESTI_ADR_MASK, reg);
uniphier_pciephy_testio_write(priv, val);
val = readl(priv->base + PCL_PHY_TEST_O);
val = readl(priv->base + PCL_PHY_TEST_O) & TESTO_DAT_MASK;
/* update value */
val &= ~FIELD_PREP(TESTI_DAT_MASK, mask);
val = FIELD_PREP(TESTI_DAT_MASK, mask & param);
val &= ~mask;
val |= mask & param;
val = FIELD_PREP(TESTI_DAT_MASK, val);
val |= FIELD_PREP(TESTI_ADR_MASK, reg);
uniphier_pciephy_testio_write(priv, val);
uniphier_pciephy_testio_write(priv, val | TESTI_WR_EN);

View File

@ -57,6 +57,7 @@ struct pll_params {
struct stm32_usbphyc_phy {
struct phy *phy;
struct stm32_usbphyc *usbphyc;
struct regulator *vbus;
u32 index;
bool active;
};
@ -291,9 +292,31 @@ static int stm32_usbphyc_phy_exit(struct phy *phy)
return stm32_usbphyc_pll_disable(usbphyc);
}
static int stm32_usbphyc_phy_power_on(struct phy *phy)
{
struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy);
if (usbphyc_phy->vbus)
return regulator_enable(usbphyc_phy->vbus);
return 0;
}
static int stm32_usbphyc_phy_power_off(struct phy *phy)
{
struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy);
if (usbphyc_phy->vbus)
return regulator_disable(usbphyc_phy->vbus);
return 0;
}
static const struct phy_ops stm32_usbphyc_phy_ops = {
.init = stm32_usbphyc_phy_init,
.exit = stm32_usbphyc_phy_exit,
.power_on = stm32_usbphyc_phy_power_on,
.power_off = stm32_usbphyc_phy_power_off,
.owner = THIS_MODULE,
};
@ -519,6 +542,14 @@ static int stm32_usbphyc_probe(struct platform_device *pdev)
usbphyc->phys[port]->index = index;
usbphyc->phys[port]->active = false;
usbphyc->phys[port]->vbus = devm_regulator_get_optional(&phy->dev, "vbus");
if (IS_ERR(usbphyc->phys[port]->vbus)) {
ret = PTR_ERR(usbphyc->phys[port]->vbus);
if (ret == -EPROBE_DEFER)
goto put_child;
usbphyc->phys[port]->vbus = NULL;
}
port++;
}

View File

@ -242,19 +242,28 @@ static int dm816x_usb_phy_probe(struct platform_device *pdev)
pm_runtime_enable(phy->dev);
generic_phy = devm_phy_create(phy->dev, NULL, &ops);
if (IS_ERR(generic_phy))
return PTR_ERR(generic_phy);
if (IS_ERR(generic_phy)) {
error = PTR_ERR(generic_phy);
goto clk_unprepare;
}
phy_set_drvdata(generic_phy, phy);
phy_provider = devm_of_phy_provider_register(phy->dev,
of_phy_simple_xlate);
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
if (IS_ERR(phy_provider)) {
error = PTR_ERR(phy_provider);
goto clk_unprepare;
}
usb_add_phy_dev(&phy->phy);
return 0;
clk_unprepare:
pm_runtime_disable(phy->dev);
clk_unprepare(phy->refclk);
return error;
}
static int dm816x_usb_phy_remove(struct platform_device *pdev)

View File

@ -544,7 +544,7 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
return 0;
}
static ssize_t twl4030_usb_vbus_show(struct device *dev,
static ssize_t vbus_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct twl4030_usb *twl = dev_get_drvdata(dev);
@ -557,7 +557,7 @@ static ssize_t twl4030_usb_vbus_show(struct device *dev,
return ret;
}
static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL);
static DEVICE_ATTR_RO(vbus);
static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
{

View File

@ -125,7 +125,7 @@ struct phy_ops {
/**
* struct phy_attrs - represents phy attributes
* @bus_width: Data path width implemented by PHY
* @max_link_rate: Maximum link rate supported by PHY (in Mbps)
* @max_link_rate: Maximum link rate supported by PHY (units to be decided by producer and consumer)
* @mode: PHY mode
*/
struct phy_attrs {