Commit fbb86b0d authored by Linus Torvalds's avatar Linus Torvalds

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

Pull phy updates from Vinod Koul:
 "New hw support:
   - Rcar usb2 support for RZ/G3S SoC
   - Nuvoton MA35 SoC USB 2.0 PHY driver

  Removed:
   - obsolete qcom,usb-8x16-phy bindings

  Updates:
   - 4 lane PCIe support for Qualcomm X1E80100
   - Constify structure in subsystem update
   - Subsystem simplification with scoped for each OF child loop update
   - Yaml conversion for Qualcomm sata phy, Hiilicon hi3798cv200-combphy
     bindings"

* tag 'phy-for-6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (40 commits)
  phy: renesas: rcar-gen3-usb2: Add support for the RZ/G3S SoC
  dt-bindings: phy: renesas,usb2-phy: Document RZ/G3S phy bindings
  phy: renesas: rcar-gen3-usb2: Add support to initialize the bus
  phy: ti: j721e-wiz: Simplify with scoped for each OF child loop
  phy: ti: j721e-wiz: Drop OF node reference earlier for simpler code
  phy: ti: gmii-sel: Simplify with dev_err_probe()
  phy: ti: am654-serdes: Use scoped device node handling to simplify error paths
  phy: qcom: qmp-pcie-msm8996: Simplify with scoped for each OF child loop
  phy: mediatek: xsphy: Simplify with scoped for each OF child loop
  phy: mediatek: tphy: Simplify with scoped for each OF child loop
  phy: hisilicon: usb2: Simplify with scoped for each OF child loop
  phy: cadence: sierra: Simplify with scoped for each OF child loop
  phy: broadcom: brcm-sata: Simplify with scoped for each OF child loop
  phy: broadcom: bcm-cygnus-pcie: Simplify with scoped for each OF child loop
  phy: nuvoton: add new driver for the Nuvoton MA35 SoC USB 2.0 PHY
  dt-bindings: phy: nuvoton,ma35-usb2-phy: add new bindings
  phy: qcom: qmp-pcie: Configure all tables on port B PHY
  phy: airoha: adjust initialization delay in airoha_pcie_phy_init()
  dt-bindings: phy: socionext,uniphier: add top-level constraints
  phy: qcom: qmp-pcie: Add Gen4 4-lanes mode for X1E80100
  ...
parents 7116747a 3c2ea12a
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/hisilicon,hi3798cv200-combphy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: HiSilicon STB PCIE/SATA/USB3 PHY
maintainers:
- Shawn Guo <shawn.guo@linaro.org>
properties:
compatible:
const: hisilicon,hi3798cv200-combphy
reg:
maxItems: 1
'#phy-cells':
description: The cell contains the PHY mode
const: 1
clocks:
maxItems: 1
resets:
maxItems: 1
hisilicon,fixed-mode:
description: If the phy device doesn't support mode select but a fixed mode
setting, the property should be present to specify the particular mode.
$ref: /schemas/types.yaml#/definitions/uint32
enum: [ 1, 2, 4] # SATA, PCIE, USB3
hisilicon,mode-select-bits:
description: If the phy device support mode select, this property should be
present to specify the register bits in peripheral controller.
items:
- description: register_offset
- description: bit shift
- description: bit mask
required:
- compatible
- reg
- '#phy-cells'
- clocks
- resets
oneOf:
- required: ['hisilicon,fixed-mode']
- required: ['hisilicon,mode-select-bits']
additionalProperties: false
...
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/nuvoton,ma35d1-usb2-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Nuvoton MA35D1 USB2 phy
maintainers:
- Hui-Ping Chen <hpchen0nvt@gmail.com>
properties:
compatible:
enum:
- nuvoton,ma35d1-usb2-phy
"#phy-cells":
const: 0
clocks:
maxItems: 1
nuvoton,sys:
$ref: /schemas/types.yaml#/definitions/phandle
description:
phandle to syscon for checking the PHY clock status.
required:
- compatible
- "#phy-cells"
- clocks
- nuvoton,sys
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/nuvoton,ma35d1-clk.h>
usb_phy: usb-phy {
compatible = "nuvoton,ma35d1-usb2-phy";
clocks = <&clk USBD_GATE>;
nuvoton,sys = <&sys>;
#phy-cells = <0>;
};
HiSilicon STB PCIE/SATA/USB3 PHY
Required properties:
- compatible: Should be "hisilicon,hi3798cv200-combphy"
- reg: Should be the address space for COMBPHY configuration and state
registers in peripheral controller, e.g. PERI_COMBPHY0_CFG and
PERI_COMBPHY0_STATE for COMBPHY0 Hi3798CV200 SoC.
- #phy-cells: Should be 1. The cell number is used to select the phy mode
as defined in <dt-bindings/phy/phy.h>.
- clocks: The phandle to clock provider and clock specifier pair.
- resets: The phandle to reset controller and reset specifier pair.
Refer to phy/phy-bindings.txt for the generic PHY binding properties.
Optional properties:
- hisilicon,fixed-mode: If the phy device doesn't support mode select
but a fixed mode setting, the property should be present to specify
the particular mode.
- hisilicon,mode-select-bits: If the phy device support mode select,
this property should be present to specify the register bits in
peripheral controller, as a 3 integers tuple:
<register_offset bit_shift bit_mask>.
Notes:
- Between hisilicon,fixed-mode and hisilicon,mode-select-bits, one and only
one of them should be present.
- The device node should be a child of peripheral controller that contains
COMBPHY configuration/state and PERI_CTRL register used to select PHY mode.
Refer to arm/hisilicon/hisilicon.txt for the parent peripheral controller
bindings.
Examples:
perictrl: peripheral-controller@8a20000 {
compatible = "hisilicon,hi3798cv200-perictrl", "syscon",
"simple-mfd";
reg = <0x8a20000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x8a20000 0x1000>;
combphy0: phy@850 {
compatible = "hisilicon,hi3798cv200-combphy";
reg = <0x850 0x8>;
#phy-cells = <1>;
clocks = <&crg HISTB_COMBPHY0_CLK>;
resets = <&crg 0x188 4>;
hisilicon,fixed-mode = <PHY_TYPE_USB3>;
};
combphy1: phy@858 {
compatible = "hisilicon,hi3798cv200-combphy";
reg = <0x858 0x8>;
#phy-cells = <1>;
clocks = <&crg HISTB_COMBPHY1_CLK>;
resets = <&crg 0x188 12>;
hisilicon,mode-select-bits = <0x0008 11 (0x3 << 11)>;
};
};
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/qcom,sata-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm SATA PHY Controller
maintainers:
- Bjorn Andersson <andersson@kernel.org>
- Konrad Dybcio <konrad.dybcio@linaro.org>
description:
The Qualcomm SATA PHY describes on-chip SATA Physical layer controllers.
properties:
compatible:
enum:
- qcom,ipq806x-sata-phy
- qcom,apq8064-sata-phy
reg:
maxItems: 1
clocks:
maxItems: 1
clock-names:
const: cfg
'#phy-cells':
const: 0
required:
- compatible
- reg
- clocks
- clock-names
- '#phy-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,gcc-ipq806x.h>
sata_phy: sata-phy@1b400000 {
compatible = "qcom,ipq806x-sata-phy";
reg = <0x1b400000 0x200>;
clocks = <&gcc SATA_PHY_CFG_CLK>;
clock-names = "cfg";
#phy-cells = <0>;
};
...@@ -40,6 +40,7 @@ properties: ...@@ -40,6 +40,7 @@ properties:
- qcom,sm8650-qmp-gen4x2-pcie-phy - qcom,sm8650-qmp-gen4x2-pcie-phy
- qcom,x1e80100-qmp-gen3x2-pcie-phy - qcom,x1e80100-qmp-gen3x2-pcie-phy
- qcom,x1e80100-qmp-gen4x2-pcie-phy - qcom,x1e80100-qmp-gen4x2-pcie-phy
- qcom,x1e80100-qmp-gen4x4-pcie-phy
reg: reg:
minItems: 1 minItems: 1
...@@ -118,6 +119,7 @@ allOf: ...@@ -118,6 +119,7 @@ allOf:
contains: contains:
enum: enum:
- qcom,sc8280xp-qmp-gen3x4-pcie-phy - qcom,sc8280xp-qmp-gen3x4-pcie-phy
- qcom,x1e80100-qmp-gen4x4-pcie-phy
then: then:
properties: properties:
reg: reg:
...@@ -169,6 +171,7 @@ allOf: ...@@ -169,6 +171,7 @@ allOf:
- qcom,sc8280xp-qmp-gen3x1-pcie-phy - qcom,sc8280xp-qmp-gen3x1-pcie-phy
- qcom,sc8280xp-qmp-gen3x2-pcie-phy - qcom,sc8280xp-qmp-gen3x2-pcie-phy
- qcom,sc8280xp-qmp-gen3x4-pcie-phy - qcom,sc8280xp-qmp-gen3x4-pcie-phy
- qcom,x1e80100-qmp-gen4x4-pcie-phy
then: then:
properties: properties:
clocks: clocks:
......
Qualcomm's APQ8016/MSM8916 USB transceiver controller
- compatible:
Usage: required
Value type: <string>
Definition: Should contain "qcom,usb-8x16-phy".
- reg:
Usage: required
Value type: <prop-encoded-array>
Definition: USB PHY base address and length of the register map
- clocks:
Usage: required
Value type: <prop-encoded-array>
Definition: See clock-bindings.txt section "consumers". List of
two clock specifiers for interface and core controller
clocks.
- clock-names:
Usage: required
Value type: <string>
Definition: Must contain "iface" and "core" strings.
- vddcx-supply:
Usage: required
Value type: <phandle>
Definition: phandle to the regulator VDCCX supply node.
- v1p8-supply:
Usage: required
Value type: <phandle>
Definition: phandle to the regulator 1.8V supply node.
- v3p3-supply:
Usage: required
Value type: <phandle>
Definition: phandle to the regulator 3.3V supply node.
- resets:
Usage: required
Value type: <prop-encoded-array>
Definition: See reset.txt section "consumers". PHY reset specifier.
- reset-names:
Usage: required
Value type: <string>
Definition: Must contain "phy" string.
- switch-gpio:
Usage: optional
Value type: <prop-encoded-array>
Definition: Some boards are using Dual SPDT USB Switch, witch is
controlled by GPIO to de/multiplex D+/D- USB lines
between connectors.
Example:
usb_phy: phy@78d9000 {
compatible = "qcom,usb-8x16-phy";
reg = <0x78d9000 0x400>;
vddcx-supply = <&pm8916_s1_corner>;
v1p8-supply = <&pm8916_l7>;
v3p3-supply = <&pm8916_l13>;
clocks = <&gcc GCC_USB_HS_AHB_CLK>,
<&gcc GCC_USB_HS_SYSTEM_CLK>;
clock-names = "iface", "core";
resets = <&gcc GCC_USB2A_PHY_BCR>;
reset-names = "phy";
// D+/D- lines: 1 - Routed to HUB, 0 - Device connector
switch-gpio = <&pm8916_gpios 4 GPIO_ACTIVE_HIGH>;
};
Qualcomm APQ8064 SATA PHY Controller
------------------------------------
SATA PHY nodes are defined to describe on-chip SATA Physical layer controllers.
Each SATA PHY controller should have its own node.
Required properties:
- compatible: compatible list, contains "qcom,apq8064-sata-phy".
- reg: offset and length of the SATA PHY register set;
- #phy-cells: must be zero
- clocks: a list of phandles and clock-specifier pairs, one for each entry in
clock-names.
- clock-names: must be "cfg" for phy config clock.
Example:
sata_phy: sata-phy@1b400000 {
compatible = "qcom,apq8064-sata-phy";
reg = <0x1b400000 0x200>;
clocks = <&gcc SATA_PHY_CFG_CLK>;
clock-names = "cfg";
#phy-cells = <0>;
};
Qualcomm IPQ806x SATA PHY Controller
------------------------------------
SATA PHY nodes are defined to describe on-chip SATA Physical layer controllers.
Each SATA PHY controller should have its own node.
Required properties:
- compatible: compatible list, contains "qcom,ipq806x-sata-phy"
- reg: offset and length of the SATA PHY register set;
- #phy-cells: must be zero
- clocks: must be exactly one entry
- clock-names: must be "cfg"
Example:
sata_phy: sata-phy@1b400000 {
compatible = "qcom,ipq806x-sata-phy";
reg = <0x1b400000 0x200>;
clocks = <&gcc SATA_PHY_CFG_CLK>;
clock-names = "cfg";
#phy-cells = <0>;
};
...@@ -13,7 +13,9 @@ properties: ...@@ -13,7 +13,9 @@ properties:
compatible: compatible:
oneOf: oneOf:
- items: - items:
- const: renesas,usb2-phy-r8a77470 # RZ/G1C - enum:
- renesas,usb2-phy-r8a77470 # RZ/G1C
- renesas,usb2-phy-r9a08g045 # RZ/G3S
- items: - items:
- enum: - enum:
......
...@@ -27,6 +27,9 @@ properties: ...@@ -27,6 +27,9 @@ properties:
- const: ref - const: ref
- const: apb - const: apb
"#clock-cells":
const: 0
"#phy-cells": "#phy-cells":
const: 0 const: 0
......
...@@ -30,13 +30,17 @@ properties: ...@@ -30,13 +30,17 @@ properties:
minItems: 1 minItems: 1
maxItems: 2 maxItems: 2
clock-names: true clock-names:
minItems: 1
maxItems: 6
resets: resets:
minItems: 2 minItems: 2
maxItems: 6 maxItems: 6
reset-names: true reset-names:
minItems: 2
maxItems: 6
allOf: allOf:
- if: - if:
......
...@@ -31,13 +31,17 @@ properties: ...@@ -31,13 +31,17 @@ properties:
minItems: 1 minItems: 1
maxItems: 2 maxItems: 2
clock-names: true clock-names:
minItems: 1
maxItems: 2
resets: resets:
minItems: 1 minItems: 1
maxItems: 2 maxItems: 2
reset-names: true reset-names:
minItems: 1
maxItems: 2
socionext,syscon: socionext,syscon:
$ref: /schemas/types.yaml#/definitions/phandle $ref: /schemas/types.yaml#/definitions/phandle
......
...@@ -34,12 +34,15 @@ properties: ...@@ -34,12 +34,15 @@ properties:
minItems: 2 minItems: 2
maxItems: 3 maxItems: 3
clock-names: true clock-names:
minItems: 2
maxItems: 3
resets: resets:
maxItems: 2 maxItems: 2
reset-names: true reset-names:
maxItems: 2
vbus-supply: vbus-supply:
description: A phandle to the regulator for USB VBUS description: A phandle to the regulator for USB VBUS
......
...@@ -35,12 +35,15 @@ properties: ...@@ -35,12 +35,15 @@ properties:
minItems: 2 minItems: 2
maxItems: 3 maxItems: 3
clock-names: true clock-names:
minItems: 2
maxItems: 3
resets: resets:
maxItems: 2 maxItems: 2
reset-names: true reset-names:
maxItems: 2
vbus-supply: vbus-supply:
description: A phandle to the regulator for USB VBUS, only for USB host description: A phandle to the regulator for USB VBUS, only for USB host
......
...@@ -95,6 +95,7 @@ source "drivers/phy/mediatek/Kconfig" ...@@ -95,6 +95,7 @@ source "drivers/phy/mediatek/Kconfig"
source "drivers/phy/microchip/Kconfig" source "drivers/phy/microchip/Kconfig"
source "drivers/phy/motorola/Kconfig" source "drivers/phy/motorola/Kconfig"
source "drivers/phy/mscc/Kconfig" source "drivers/phy/mscc/Kconfig"
source "drivers/phy/nuvoton/Kconfig"
source "drivers/phy/qualcomm/Kconfig" source "drivers/phy/qualcomm/Kconfig"
source "drivers/phy/ralink/Kconfig" source "drivers/phy/ralink/Kconfig"
source "drivers/phy/realtek/Kconfig" source "drivers/phy/realtek/Kconfig"
......
...@@ -25,6 +25,7 @@ obj-y += allwinner/ \ ...@@ -25,6 +25,7 @@ obj-y += allwinner/ \
microchip/ \ microchip/ \
motorola/ \ motorola/ \
mscc/ \ mscc/ \
nuvoton/ \
qualcomm/ \ qualcomm/ \
ralink/ \ ralink/ \
realtek/ \ realtek/ \
......
...@@ -113,11 +113,10 @@ static const struct phy_ops cygnus_pcie_phy_ops = { ...@@ -113,11 +113,10 @@ static const struct phy_ops cygnus_pcie_phy_ops = {
static int cygnus_pcie_phy_probe(struct platform_device *pdev) static int cygnus_pcie_phy_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node, *child; struct device_node *node = dev->of_node;
struct cygnus_pcie_phy_core *core; struct cygnus_pcie_phy_core *core;
struct phy_provider *provider; struct phy_provider *provider;
unsigned cnt = 0; unsigned cnt = 0;
int ret;
if (of_get_child_count(node) == 0) { if (of_get_child_count(node) == 0) {
dev_err(dev, "PHY no child node\n"); dev_err(dev, "PHY no child node\n");
...@@ -136,35 +135,31 @@ static int cygnus_pcie_phy_probe(struct platform_device *pdev) ...@@ -136,35 +135,31 @@ static int cygnus_pcie_phy_probe(struct platform_device *pdev)
mutex_init(&core->lock); mutex_init(&core->lock);
for_each_available_child_of_node(node, child) { for_each_available_child_of_node_scoped(node, child) {
unsigned int id; unsigned int id;
struct cygnus_pcie_phy *p; struct cygnus_pcie_phy *p;
if (of_property_read_u32(child, "reg", &id)) { if (of_property_read_u32(child, "reg", &id)) {
dev_err(dev, "missing reg property for %pOFn\n", dev_err(dev, "missing reg property for %pOFn\n",
child); child);
ret = -EINVAL; return -EINVAL;
goto put_child;
} }
if (id >= MAX_NUM_PHYS) { if (id >= MAX_NUM_PHYS) {
dev_err(dev, "invalid PHY id: %u\n", id); dev_err(dev, "invalid PHY id: %u\n", id);
ret = -EINVAL; return -EINVAL;
goto put_child;
} }
if (core->phys[id].phy) { if (core->phys[id].phy) {
dev_err(dev, "duplicated PHY id: %u\n", id); dev_err(dev, "duplicated PHY id: %u\n", id);
ret = -EINVAL; return -EINVAL;
goto put_child;
} }
p = &core->phys[id]; p = &core->phys[id];
p->phy = devm_phy_create(dev, child, &cygnus_pcie_phy_ops); p->phy = devm_phy_create(dev, child, &cygnus_pcie_phy_ops);
if (IS_ERR(p->phy)) { if (IS_ERR(p->phy)) {
dev_err(dev, "failed to create PHY\n"); dev_err(dev, "failed to create PHY\n");
ret = PTR_ERR(p->phy); return PTR_ERR(p->phy);
goto put_child;
} }
p->core = core; p->core = core;
...@@ -184,9 +179,6 @@ static int cygnus_pcie_phy_probe(struct platform_device *pdev) ...@@ -184,9 +179,6 @@ static int cygnus_pcie_phy_probe(struct platform_device *pdev)
dev_dbg(dev, "registered %u PCIe PHY(s)\n", cnt); dev_dbg(dev, "registered %u PCIe PHY(s)\n", cnt);
return 0; return 0;
put_child:
of_node_put(child);
return ret;
} }
static const struct of_device_id cygnus_pcie_phy_match_table[] = { static const struct of_device_id cygnus_pcie_phy_match_table[] = {
......
...@@ -751,11 +751,11 @@ static int brcm_sata_phy_probe(struct platform_device *pdev) ...@@ -751,11 +751,11 @@ static int brcm_sata_phy_probe(struct platform_device *pdev)
{ {
const char *rxaeq_mode; const char *rxaeq_mode;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *dn = dev->of_node, *child; struct device_node *dn = dev->of_node;
const struct of_device_id *of_id; const struct of_device_id *of_id;
struct brcm_sata_phy *priv; struct brcm_sata_phy *priv;
struct phy_provider *provider; struct phy_provider *provider;
int ret, count = 0; int count = 0;
if (of_get_child_count(dn) == 0) if (of_get_child_count(dn) == 0)
return -ENODEV; return -ENODEV;
...@@ -782,26 +782,23 @@ static int brcm_sata_phy_probe(struct platform_device *pdev) ...@@ -782,26 +782,23 @@ static int brcm_sata_phy_probe(struct platform_device *pdev)
return PTR_ERR(priv->ctrl_base); return PTR_ERR(priv->ctrl_base);
} }
for_each_available_child_of_node(dn, child) { for_each_available_child_of_node_scoped(dn, child) {
unsigned int id; unsigned int id;
struct brcm_sata_port *port; struct brcm_sata_port *port;
if (of_property_read_u32(child, "reg", &id)) { if (of_property_read_u32(child, "reg", &id)) {
dev_err(dev, "missing reg property in node %pOFn\n", dev_err(dev, "missing reg property in node %pOFn\n",
child); child);
ret = -EINVAL; return -EINVAL;
goto put_child;
} }
if (id >= MAX_PORTS) { if (id >= MAX_PORTS) {
dev_err(dev, "invalid reg: %u\n", id); dev_err(dev, "invalid reg: %u\n", id);
ret = -EINVAL; return -EINVAL;
goto put_child;
} }
if (priv->phys[id].phy) { if (priv->phys[id].phy) {
dev_err(dev, "already registered port %u\n", id); dev_err(dev, "already registered port %u\n", id);
ret = -EINVAL; return -EINVAL;
goto put_child;
} }
port = &priv->phys[id]; port = &priv->phys[id];
...@@ -822,8 +819,7 @@ static int brcm_sata_phy_probe(struct platform_device *pdev) ...@@ -822,8 +819,7 @@ static int brcm_sata_phy_probe(struct platform_device *pdev)
port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc"); port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc");
if (IS_ERR(port->phy)) { if (IS_ERR(port->phy)) {
dev_err(dev, "failed to create PHY\n"); dev_err(dev, "failed to create PHY\n");
ret = PTR_ERR(port->phy); return PTR_ERR(port->phy);
goto put_child;
} }
phy_set_drvdata(port->phy, port); phy_set_drvdata(port->phy, port);
...@@ -839,9 +835,6 @@ static int brcm_sata_phy_probe(struct platform_device *pdev) ...@@ -839,9 +835,6 @@ static int brcm_sata_phy_probe(struct platform_device *pdev)
dev_info(dev, "registered %d port(s)\n", count); dev_info(dev, "registered %d port(s)\n", count);
return 0; return 0;
put_child:
of_node_put(child);
return ret;
} }
static struct platform_driver brcm_sata_phy_driver = { static struct platform_driver brcm_sata_phy_driver = {
......
This diff is collapsed.
This diff is collapsed.
...@@ -138,7 +138,6 @@ static int hisi_inno_phy_probe(struct platform_device *pdev) ...@@ -138,7 +138,6 @@ static int hisi_inno_phy_probe(struct platform_device *pdev)
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct hisi_inno_phy_priv *priv; struct hisi_inno_phy_priv *priv;
struct phy_provider *provider; struct phy_provider *provider;
struct device_node *child;
int i = 0; int i = 0;
int ret; int ret;
...@@ -162,24 +161,20 @@ static int hisi_inno_phy_probe(struct platform_device *pdev) ...@@ -162,24 +161,20 @@ static int hisi_inno_phy_probe(struct platform_device *pdev)
priv->type = (uintptr_t) of_device_get_match_data(dev); priv->type = (uintptr_t) of_device_get_match_data(dev);
for_each_child_of_node(np, child) { for_each_child_of_node_scoped(np, child) {
struct reset_control *rst; struct reset_control *rst;
struct phy *phy; struct phy *phy;
rst = of_reset_control_get_exclusive(child, NULL); rst = of_reset_control_get_exclusive(child, NULL);
if (IS_ERR(rst)) { if (IS_ERR(rst))
of_node_put(child);
return PTR_ERR(rst); return PTR_ERR(rst);
}
priv->ports[i].utmi_rst = rst; priv->ports[i].utmi_rst = rst;
priv->ports[i].priv = priv; priv->ports[i].priv = priv;
phy = devm_phy_create(dev, child, &hisi_inno_phy_ops); phy = devm_phy_create(dev, child, &hisi_inno_phy_ops);
if (IS_ERR(phy)) { if (IS_ERR(phy))
of_node_put(child);
return PTR_ERR(phy); return PTR_ERR(phy);
}
phy_set_bus_width(phy, 8); phy_set_bus_width(phy, 8);
phy_set_drvdata(phy, &priv->ports[i]); phy_set_drvdata(phy, &priv->ports[i]);
...@@ -187,7 +182,6 @@ static int hisi_inno_phy_probe(struct platform_device *pdev) ...@@ -187,7 +182,6 @@ static int hisi_inno_phy_probe(struct platform_device *pdev)
if (i >= INNO_PHY_PORT_NUM) { if (i >= INNO_PHY_PORT_NUM) {
dev_warn(dev, "Support %d ports in maximum\n", i); dev_warn(dev, "Support %d ports in maximum\n", i);
of_node_put(child);
break; break;
} }
} }
......
...@@ -244,8 +244,8 @@ static const struct mvebu_comphy_conf mvebu_comphy_cp110_modes[] = { ...@@ -244,8 +244,8 @@ static const struct mvebu_comphy_conf mvebu_comphy_cp110_modes[] = {
GEN_CONF(4, 1, PHY_MODE_USB_HOST_SS, COMPHY_FW_MODE_USB3H), GEN_CONF(4, 1, PHY_MODE_USB_HOST_SS, COMPHY_FW_MODE_USB3H),
GEN_CONF(4, 1, PHY_MODE_PCIE, COMPHY_FW_MODE_PCIE), GEN_CONF(4, 1, PHY_MODE_PCIE, COMPHY_FW_MODE_PCIE),
ETH_CONF(4, 1, PHY_INTERFACE_MODE_SGMII, 0x1, COMPHY_FW_MODE_SGMII), ETH_CONF(4, 1, PHY_INTERFACE_MODE_SGMII, 0x1, COMPHY_FW_MODE_SGMII),
ETH_CONF(4, 1, PHY_INTERFACE_MODE_2500BASEX, -1, COMPHY_FW_MODE_2500BASEX), ETH_CONF(4, 1, PHY_INTERFACE_MODE_2500BASEX, 0x1, COMPHY_FW_MODE_2500BASEX),
ETH_CONF(4, 1, PHY_INTERFACE_MODE_5GBASER, -1, COMPHY_FW_MODE_XFI), ETH_CONF(4, 1, PHY_INTERFACE_MODE_5GBASER, 0x1, COMPHY_FW_MODE_XFI),
ETH_CONF(4, 1, PHY_INTERFACE_MODE_10GBASER, -1, COMPHY_FW_MODE_XFI), ETH_CONF(4, 1, PHY_INTERFACE_MODE_10GBASER, -1, COMPHY_FW_MODE_XFI),
/* lane 5 */ /* lane 5 */
ETH_CONF(5, 1, PHY_INTERFACE_MODE_RXAUI, 0x2, COMPHY_FW_MODE_RXAUI), ETH_CONF(5, 1, PHY_INTERFACE_MODE_RXAUI, 0x2, COMPHY_FW_MODE_RXAUI),
......
...@@ -1577,12 +1577,11 @@ static int mtk_tphy_probe(struct platform_device *pdev) ...@@ -1577,12 +1577,11 @@ static int mtk_tphy_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct device_node *child_np;
struct phy_provider *provider; struct phy_provider *provider;
struct resource *sif_res; struct resource *sif_res;
struct mtk_tphy *tphy; struct mtk_tphy *tphy;
struct resource res; struct resource res;
int port, retval; int port;
tphy = devm_kzalloc(dev, sizeof(*tphy), GFP_KERNEL); tphy = devm_kzalloc(dev, sizeof(*tphy), GFP_KERNEL);
if (!tphy) if (!tphy)
...@@ -1623,25 +1622,23 @@ static int mtk_tphy_probe(struct platform_device *pdev) ...@@ -1623,25 +1622,23 @@ static int mtk_tphy_probe(struct platform_device *pdev)
} }
port = 0; port = 0;
for_each_child_of_node(np, child_np) { for_each_child_of_node_scoped(np, child_np) {
struct mtk_phy_instance *instance; struct mtk_phy_instance *instance;
struct clk_bulk_data *clks; struct clk_bulk_data *clks;
struct device *subdev; struct device *subdev;
struct phy *phy; struct phy *phy;
int retval;
instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL); instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
if (!instance) { if (!instance)
retval = -ENOMEM; return -ENOMEM;
goto put_child;
}
tphy->phys[port] = instance; tphy->phys[port] = instance;
phy = devm_phy_create(dev, child_np, &mtk_tphy_ops); phy = devm_phy_create(dev, child_np, &mtk_tphy_ops);
if (IS_ERR(phy)) { if (IS_ERR(phy)) {
dev_err(dev, "failed to create phy\n"); dev_err(dev, "failed to create phy\n");
retval = PTR_ERR(phy); return PTR_ERR(phy);
goto put_child;
} }
subdev = &phy->dev; subdev = &phy->dev;
...@@ -1649,14 +1646,12 @@ static int mtk_tphy_probe(struct platform_device *pdev) ...@@ -1649,14 +1646,12 @@ static int mtk_tphy_probe(struct platform_device *pdev)
if (retval) { if (retval) {
dev_err(subdev, "failed to get address resource(id-%d)\n", dev_err(subdev, "failed to get address resource(id-%d)\n",
port); port);
goto put_child; return retval;
} }
instance->port_base = devm_ioremap_resource(subdev, &res); instance->port_base = devm_ioremap_resource(subdev, &res);
if (IS_ERR(instance->port_base)) { if (IS_ERR(instance->port_base))
retval = PTR_ERR(instance->port_base); return PTR_ERR(instance->port_base);
goto put_child;
}
instance->phy = phy; instance->phy = phy;
instance->index = port; instance->index = port;
...@@ -1668,19 +1663,16 @@ static int mtk_tphy_probe(struct platform_device *pdev) ...@@ -1668,19 +1663,16 @@ static int mtk_tphy_probe(struct platform_device *pdev)
clks[1].id = "da_ref"; /* analog clock */ clks[1].id = "da_ref"; /* analog clock */
retval = devm_clk_bulk_get_optional(subdev, TPHY_CLKS_CNT, clks); retval = devm_clk_bulk_get_optional(subdev, TPHY_CLKS_CNT, clks);
if (retval) if (retval)
goto put_child; return retval;
retval = phy_type_syscon_get(instance, child_np); retval = phy_type_syscon_get(instance, child_np);
if (retval) if (retval)
goto put_child; return retval;
} }
provider = devm_of_phy_provider_register(dev, mtk_phy_xlate); provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
return PTR_ERR_OR_ZERO(provider); return PTR_ERR_OR_ZERO(provider);
put_child:
of_node_put(child_np);
return retval;
} }
static struct platform_driver mtk_tphy_driver = { static struct platform_driver mtk_tphy_driver = {
......
...@@ -432,12 +432,11 @@ static int mtk_xsphy_probe(struct platform_device *pdev) ...@@ -432,12 +432,11 @@ static int mtk_xsphy_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct device_node *child_np;
struct phy_provider *provider; struct phy_provider *provider;
struct resource *glb_res; struct resource *glb_res;
struct mtk_xsphy *xsphy; struct mtk_xsphy *xsphy;
struct resource res; struct resource res;
int port, retval; int port;
xsphy = devm_kzalloc(dev, sizeof(*xsphy), GFP_KERNEL); xsphy = devm_kzalloc(dev, sizeof(*xsphy), GFP_KERNEL);
if (!xsphy) if (!xsphy)
...@@ -471,37 +470,34 @@ static int mtk_xsphy_probe(struct platform_device *pdev) ...@@ -471,37 +470,34 @@ static int mtk_xsphy_probe(struct platform_device *pdev)
device_property_read_u32(dev, "mediatek,src-coef", &xsphy->src_coef); device_property_read_u32(dev, "mediatek,src-coef", &xsphy->src_coef);
port = 0; port = 0;
for_each_child_of_node(np, child_np) { for_each_child_of_node_scoped(np, child_np) {
struct xsphy_instance *inst; struct xsphy_instance *inst;
struct phy *phy; struct phy *phy;
int retval;
inst = devm_kzalloc(dev, sizeof(*inst), GFP_KERNEL); inst = devm_kzalloc(dev, sizeof(*inst), GFP_KERNEL);
if (!inst) { if (!inst)
retval = -ENOMEM; return -ENOMEM;
goto put_child;
}
xsphy->phys[port] = inst; xsphy->phys[port] = inst;
phy = devm_phy_create(dev, child_np, &mtk_xsphy_ops); phy = devm_phy_create(dev, child_np, &mtk_xsphy_ops);
if (IS_ERR(phy)) { if (IS_ERR(phy)) {
dev_err(dev, "failed to create phy\n"); dev_err(dev, "failed to create phy\n");
retval = PTR_ERR(phy); return PTR_ERR(phy);
goto put_child;
} }
retval = of_address_to_resource(child_np, 0, &res); retval = of_address_to_resource(child_np, 0, &res);
if (retval) { if (retval) {
dev_err(dev, "failed to get address resource(id-%d)\n", dev_err(dev, "failed to get address resource(id-%d)\n",
port); port);
goto put_child; return retval;
} }
inst->port_base = devm_ioremap_resource(&phy->dev, &res); inst->port_base = devm_ioremap_resource(&phy->dev, &res);
if (IS_ERR(inst->port_base)) { if (IS_ERR(inst->port_base)) {
dev_err(dev, "failed to remap phy regs\n"); dev_err(dev, "failed to remap phy regs\n");
retval = PTR_ERR(inst->port_base); return PTR_ERR(inst->port_base);
goto put_child;
} }
inst->phy = phy; inst->phy = phy;
...@@ -512,17 +508,12 @@ static int mtk_xsphy_probe(struct platform_device *pdev) ...@@ -512,17 +508,12 @@ static int mtk_xsphy_probe(struct platform_device *pdev)
inst->ref_clk = devm_clk_get(&phy->dev, "ref"); inst->ref_clk = devm_clk_get(&phy->dev, "ref");
if (IS_ERR(inst->ref_clk)) { if (IS_ERR(inst->ref_clk)) {
dev_err(dev, "failed to get ref_clk(id-%d)\n", port); dev_err(dev, "failed to get ref_clk(id-%d)\n", port);
retval = PTR_ERR(inst->ref_clk); return PTR_ERR(inst->ref_clk);
goto put_child;
} }
} }
provider = devm_of_phy_provider_register(dev, mtk_phy_xlate); provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
return PTR_ERR_OR_ZERO(provider); return PTR_ERR_OR_ZERO(provider);
put_child:
of_node_put(child_np);
return retval;
} }
static struct platform_driver mtk_xsphy_driver = { static struct platform_driver mtk_xsphy_driver = {
......
# SPDX-License-Identifier: GPL-2.0-only
#
# PHY drivers for Nuvoton MA35 platforms
#
config PHY_MA35_USB
tristate "Nuvoton MA35 USB2.0 PHY driver"
depends on ARCH_MA35 || COMPILE_TEST
depends on OF
select GENERIC_PHY
help
Enable this to support the USB2.0 PHY on the Nuvoton MA35
series SoCs.
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_MA35_USB) += phy-ma35d1-usb2.o
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2024 Nuvoton Technology Corp.
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/kernel.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/regmap.h>
/* USB PHY Miscellaneous Control Register */
#define MA35_SYS_REG_USBPMISCR 0x60
#define PHY0POR BIT(0) /* PHY Power-On Reset Control Bit */
#define PHY0SUSPEND BIT(1) /* PHY Suspend; 0: suspend, 1: operaion */
#define PHY0COMN BIT(2) /* PHY Common Block Power-Down Control */
#define PHY0DEVCKSTB BIT(10) /* PHY 60 MHz UTMI clock stable bit */
struct ma35_usb_phy {
struct clk *clk;
struct device *dev;
struct regmap *sysreg;
};
static int ma35_usb_phy_power_on(struct phy *phy)
{
struct ma35_usb_phy *p_phy = phy_get_drvdata(phy);
unsigned int val;
int ret;
ret = clk_prepare_enable(p_phy->clk);
if (ret < 0) {
dev_err(p_phy->dev, "Failed to enable PHY clock: %d\n", ret);
return ret;
}
regmap_read(p_phy->sysreg, MA35_SYS_REG_USBPMISCR, &val);
if (val & PHY0SUSPEND) {
/*
* USB PHY0 is in operation mode already
* make sure USB PHY 60 MHz UTMI Interface Clock ready
*/
ret = regmap_read_poll_timeout(p_phy->sysreg, MA35_SYS_REG_USBPMISCR, val,
val & PHY0DEVCKSTB, 10, 1000);
if (ret == 0)
return 0;
}
/*
* reset USB PHY0.
* wait until USB PHY0 60 MHz UTMI Interface Clock ready
*/
regmap_update_bits(p_phy->sysreg, MA35_SYS_REG_USBPMISCR, 0x7, (PHY0POR | PHY0SUSPEND));
udelay(20);
/* make USB PHY0 enter operation mode */
regmap_update_bits(p_phy->sysreg, MA35_SYS_REG_USBPMISCR, 0x7, PHY0SUSPEND);
/* make sure USB PHY 60 MHz UTMI Interface Clock ready */
ret = regmap_read_poll_timeout(p_phy->sysreg, MA35_SYS_REG_USBPMISCR, val,
val & PHY0DEVCKSTB, 10, 1000);
if (ret == -ETIMEDOUT) {
dev_err(p_phy->dev, "Check PHY clock, Timeout: %d\n", ret);
clk_disable_unprepare(p_phy->clk);
return ret;
}
return 0;
}
static int ma35_usb_phy_power_off(struct phy *phy)
{
struct ma35_usb_phy *p_phy = phy_get_drvdata(phy);
clk_disable_unprepare(p_phy->clk);
return 0;
}
static const struct phy_ops ma35_usb_phy_ops = {
.power_on = ma35_usb_phy_power_on,
.power_off = ma35_usb_phy_power_off,
.owner = THIS_MODULE,
};
static int ma35_usb_phy_probe(struct platform_device *pdev)
{
struct phy_provider *provider;
struct ma35_usb_phy *p_phy;
struct phy *phy;
p_phy = devm_kzalloc(&pdev->dev, sizeof(*p_phy), GFP_KERNEL);
if (!p_phy)
return -ENOMEM;
p_phy->dev = &pdev->dev;
platform_set_drvdata(pdev, p_phy);
p_phy->sysreg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "nuvoton,sys");
if (IS_ERR(p_phy->sysreg))
return dev_err_probe(&pdev->dev, PTR_ERR(p_phy->sysreg),
"Failed to get SYS registers\n");
p_phy->clk = of_clk_get(pdev->dev.of_node, 0);
if (IS_ERR(p_phy->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(p_phy->clk),
"failed to find usb_phy clock\n");
phy = devm_phy_create(&pdev->dev, NULL, &ma35_usb_phy_ops);
if (IS_ERR(phy))
return dev_err_probe(&pdev->dev, PTR_ERR(phy), "Failed to create PHY\n");
phy_set_drvdata(phy, p_phy);
provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
if (IS_ERR(provider))
return dev_err_probe(&pdev->dev, PTR_ERR(provider),
"Failed to register PHY provider\n");
return 0;
}
static const struct of_device_id ma35_usb_phy_of_match[] = {
{ .compatible = "nuvoton,ma35d1-usb2-phy", },
{ },
};
MODULE_DEVICE_TABLE(of, ma35_usb_phy_of_match);
static struct platform_driver ma35_usb_phy_driver = {
.probe = ma35_usb_phy_probe,
.driver = {
.name = "ma35d1-usb2-phy",
.of_match_table = ma35_usb_phy_of_match,
},
};
module_platform_driver(ma35_usb_phy_driver);
MODULE_DESCRIPTION("Nuvoton ma35d1 USB2.0 PHY driver");
MODULE_AUTHOR("Hui-Ping Chen <hpchen0nvt@gmail.com>");
MODULE_LICENSE("GPL");
...@@ -18,6 +18,9 @@ ...@@ -18,6 +18,9 @@
#define LEQ_LEN_CTRL_MAX_VAL 7 #define LEQ_LEN_CTRL_MAX_VAL 7
#define FREQ_LOCK_MAX_ATTEMPT 10 #define FREQ_LOCK_MAX_ATTEMPT 10
/* PCIe-PHY initialization time in ms needed by the hw to complete */
#define PHY_HW_INIT_TIME_MS 30
enum airoha_pcie_port_gen { enum airoha_pcie_port_gen {
PCIE_PORT_GEN1 = 1, PCIE_PORT_GEN1 = 1,
PCIE_PORT_GEN2, PCIE_PORT_GEN2,
...@@ -1181,7 +1184,8 @@ static int airoha_pcie_phy_init(struct phy *phy) ...@@ -1181,7 +1184,8 @@ static int airoha_pcie_phy_init(struct phy *phy)
airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0, airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0,
PCIE_DA_XPON_CDR_PR_PWDB); PCIE_DA_XPON_CDR_PR_PWDB);
usleep_range(100, 200); /* Wait for the PCIe PHY to complete initialization before returning */
msleep(PHY_HW_INIT_TIME_MS);
return 0; return 0;
} }
......
...@@ -2190,23 +2190,24 @@ static int qmp_combo_dp_serdes_init(struct qmp_combo *qmp) ...@@ -2190,23 +2190,24 @@ static int qmp_combo_dp_serdes_init(struct qmp_combo *qmp)
void __iomem *serdes = qmp->dp_serdes; void __iomem *serdes = qmp->dp_serdes;
const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
qmp_configure(serdes, cfg->dp_serdes_tbl, cfg->dp_serdes_tbl_num); qmp_configure(qmp->dev, serdes, cfg->dp_serdes_tbl,
cfg->dp_serdes_tbl_num);
switch (dp_opts->link_rate) { switch (dp_opts->link_rate) {
case 1620: case 1620:
qmp_configure(serdes, cfg->serdes_tbl_rbr, qmp_configure(qmp->dev, serdes, cfg->serdes_tbl_rbr,
cfg->serdes_tbl_rbr_num); cfg->serdes_tbl_rbr_num);
break; break;
case 2700: case 2700:
qmp_configure(serdes, cfg->serdes_tbl_hbr, qmp_configure(qmp->dev, serdes, cfg->serdes_tbl_hbr,
cfg->serdes_tbl_hbr_num); cfg->serdes_tbl_hbr_num);
break; break;
case 5400: case 5400:
qmp_configure(serdes, cfg->serdes_tbl_hbr2, qmp_configure(qmp->dev, serdes, cfg->serdes_tbl_hbr2,
cfg->serdes_tbl_hbr2_num); cfg->serdes_tbl_hbr2_num);
break; break;
case 8100: case 8100:
qmp_configure(serdes, cfg->serdes_tbl_hbr3, qmp_configure(qmp->dev, serdes, cfg->serdes_tbl_hbr3,
cfg->serdes_tbl_hbr3_num); cfg->serdes_tbl_hbr3_num);
break; break;
default: default:
...@@ -2807,8 +2808,8 @@ static int qmp_combo_dp_power_on(struct phy *phy) ...@@ -2807,8 +2808,8 @@ static int qmp_combo_dp_power_on(struct phy *phy)
qmp_combo_dp_serdes_init(qmp); qmp_combo_dp_serdes_init(qmp);
qmp_configure_lane(tx, cfg->dp_tx_tbl, cfg->dp_tx_tbl_num, 1); qmp_configure_lane(qmp->dev, tx, cfg->dp_tx_tbl, cfg->dp_tx_tbl_num, 1);
qmp_configure_lane(tx2, cfg->dp_tx_tbl, cfg->dp_tx_tbl_num, 2); qmp_configure_lane(qmp->dev, tx2, cfg->dp_tx_tbl, cfg->dp_tx_tbl_num, 2);
/* Configure special DP tx tunings */ /* Configure special DP tx tunings */
cfg->configure_dp_tx(qmp); cfg->configure_dp_tx(qmp);
...@@ -2850,7 +2851,7 @@ static int qmp_combo_usb_power_on(struct phy *phy) ...@@ -2850,7 +2851,7 @@ static int qmp_combo_usb_power_on(struct phy *phy)
unsigned int val; unsigned int val;
int ret; int ret;
qmp_configure(serdes, cfg->serdes_tbl, cfg->serdes_tbl_num); qmp_configure(qmp->dev, serdes, cfg->serdes_tbl, cfg->serdes_tbl_num);
ret = clk_prepare_enable(qmp->pipe_clk); ret = clk_prepare_enable(qmp->pipe_clk);
if (ret) { if (ret) {
...@@ -2859,16 +2860,17 @@ static int qmp_combo_usb_power_on(struct phy *phy) ...@@ -2859,16 +2860,17 @@ static int qmp_combo_usb_power_on(struct phy *phy)
} }
/* Tx, Rx, and PCS configurations */ /* Tx, Rx, and PCS configurations */
qmp_configure_lane(tx, cfg->tx_tbl, cfg->tx_tbl_num, 1); qmp_configure_lane(qmp->dev, tx, cfg->tx_tbl, cfg->tx_tbl_num, 1);
qmp_configure_lane(tx2, cfg->tx_tbl, cfg->tx_tbl_num, 2); qmp_configure_lane(qmp->dev, tx2, cfg->tx_tbl, cfg->tx_tbl_num, 2);
qmp_configure_lane(rx, cfg->rx_tbl, cfg->rx_tbl_num, 1); qmp_configure_lane(qmp->dev, rx, cfg->rx_tbl, cfg->rx_tbl_num, 1);
qmp_configure_lane(rx2, cfg->rx_tbl, cfg->rx_tbl_num, 2); qmp_configure_lane(qmp->dev, rx2, cfg->rx_tbl, cfg->rx_tbl_num, 2);
qmp_configure(pcs, cfg->pcs_tbl, cfg->pcs_tbl_num); qmp_configure(qmp->dev, pcs, cfg->pcs_tbl, cfg->pcs_tbl_num);
if (pcs_usb) if (pcs_usb)
qmp_configure(pcs_usb, cfg->pcs_usb_tbl, cfg->pcs_usb_tbl_num); qmp_configure(qmp->dev, pcs_usb, cfg->pcs_usb_tbl,
cfg->pcs_usb_tbl_num);
if (cfg->has_pwrdn_delay) if (cfg->has_pwrdn_delay)
usleep_range(10, 20); usleep_range(10, 20);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
struct qmp_phy_init_tbl { struct qmp_phy_init_tbl {
unsigned int offset; unsigned int offset;
unsigned int val; unsigned int val;
char *name;
/* /*
* mask of lanes for which this register is written * mask of lanes for which this register is written
* for cases when second lane needs different values * for cases when second lane needs different values
...@@ -20,6 +21,7 @@ struct qmp_phy_init_tbl { ...@@ -20,6 +21,7 @@ struct qmp_phy_init_tbl {
{ \ { \
.offset = o, \ .offset = o, \
.val = v, \ .val = v, \
.name = #o, \
.lane_mask = 0xff, \ .lane_mask = 0xff, \
} }
...@@ -27,13 +29,13 @@ struct qmp_phy_init_tbl { ...@@ -27,13 +29,13 @@ struct qmp_phy_init_tbl {
{ \ { \
.offset = o, \ .offset = o, \
.val = v, \ .val = v, \
.name = #o, \
.lane_mask = l, \ .lane_mask = l, \
} }
static inline void qmp_configure_lane(void __iomem *base, static inline void qmp_configure_lane(struct device *dev, void __iomem *base,
const struct qmp_phy_init_tbl tbl[], const struct qmp_phy_init_tbl tbl[],
int num, int num, u8 lane_mask)
u8 lane_mask)
{ {
int i; int i;
const struct qmp_phy_init_tbl *t = tbl; const struct qmp_phy_init_tbl *t = tbl;
...@@ -45,15 +47,16 @@ static inline void qmp_configure_lane(void __iomem *base, ...@@ -45,15 +47,16 @@ static inline void qmp_configure_lane(void __iomem *base,
if (!(t->lane_mask & lane_mask)) if (!(t->lane_mask & lane_mask))
continue; continue;
dev_dbg(dev, "Writing Reg: %s Offset: 0x%04x Val: 0x%02x\n",
t->name, t->offset, t->val);
writel(t->val, base + t->offset); writel(t->val, base + t->offset);
} }
} }
static inline void qmp_configure(void __iomem *base, static inline void qmp_configure(struct device *dev, void __iomem *base,
const struct qmp_phy_init_tbl tbl[], const struct qmp_phy_init_tbl tbl[], int num)
int num)
{ {
qmp_configure_lane(base, tbl, num, 0xff); qmp_configure_lane(dev, base, tbl, num, 0xff);
} }
#endif #endif
...@@ -288,7 +288,7 @@ static int qmp_pcie_msm8996_serdes_init(struct qmp_phy *qphy) ...@@ -288,7 +288,7 @@ static int qmp_pcie_msm8996_serdes_init(struct qmp_phy *qphy)
unsigned int val; unsigned int val;
int ret; int ret;
qmp_configure(serdes, serdes_tbl, serdes_tbl_num); qmp_configure(qmp->dev, serdes, serdes_tbl, serdes_tbl_num);
qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET); qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET);
qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL],
...@@ -431,9 +431,9 @@ static int qmp_pcie_msm8996_power_on(struct phy *phy) ...@@ -431,9 +431,9 @@ static int qmp_pcie_msm8996_power_on(struct phy *phy)
} }
/* Tx, Rx, and PCS configurations */ /* Tx, Rx, and PCS configurations */
qmp_configure_lane(tx, cfg->tx_tbl, cfg->tx_tbl_num, 1); qmp_configure_lane(qmp->dev, tx, cfg->tx_tbl, cfg->tx_tbl_num, 1);
qmp_configure_lane(rx, cfg->rx_tbl, cfg->rx_tbl_num, 1); qmp_configure_lane(qmp->dev, rx, cfg->rx_tbl, cfg->rx_tbl_num, 1);
qmp_configure(pcs, cfg->pcs_tbl, cfg->pcs_tbl_num); qmp_configure(qmp->dev, pcs, cfg->pcs_tbl, cfg->pcs_tbl_num);
/* /*
* Pull out PHY from POWER DOWN state. * Pull out PHY from POWER DOWN state.
...@@ -725,7 +725,6 @@ static int qmp_pcie_msm8996_probe(struct platform_device *pdev) ...@@ -725,7 +725,6 @@ static int qmp_pcie_msm8996_probe(struct platform_device *pdev)
{ {
struct qcom_qmp *qmp; struct qcom_qmp *qmp;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *child;
struct phy_provider *phy_provider; struct phy_provider *phy_provider;
void __iomem *serdes; void __iomem *serdes;
const struct qmp_phy_cfg *cfg = NULL; const struct qmp_phy_cfg *cfg = NULL;
...@@ -773,13 +772,13 @@ static int qmp_pcie_msm8996_probe(struct platform_device *pdev) ...@@ -773,13 +772,13 @@ static int qmp_pcie_msm8996_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
id = 0; id = 0;
for_each_available_child_of_node(dev->of_node, child) { for_each_available_child_of_node_scoped(dev->of_node, child) {
/* Create per-lane phy */ /* Create per-lane phy */
ret = qmp_pcie_msm8996_create(dev, child, id, serdes, cfg); ret = qmp_pcie_msm8996_create(dev, child, id, serdes, cfg);
if (ret) { if (ret) {
dev_err(dev, "failed to create lane%d phy, %d\n", dev_err(dev, "failed to create lane%d phy, %d\n",
id, ret); id, ret);
goto err_node_put; return ret;
} }
/* /*
...@@ -790,7 +789,7 @@ static int qmp_pcie_msm8996_probe(struct platform_device *pdev) ...@@ -790,7 +789,7 @@ static int qmp_pcie_msm8996_probe(struct platform_device *pdev)
if (ret) { if (ret) {
dev_err(qmp->dev, dev_err(qmp->dev,
"failed to register pipe clock source\n"); "failed to register pipe clock source\n");
goto err_node_put; return ret;
} }
id++; id++;
...@@ -799,10 +798,6 @@ static int qmp_pcie_msm8996_probe(struct platform_device *pdev) ...@@ -799,10 +798,6 @@ static int qmp_pcie_msm8996_probe(struct platform_device *pdev)
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
return PTR_ERR_OR_ZERO(phy_provider); return PTR_ERR_OR_ZERO(phy_provider);
err_node_put:
of_node_put(child);
return ret;
} }
static struct platform_driver qmp_pcie_msm8996_driver = { static struct platform_driver qmp_pcie_msm8996_driver = {
......
...@@ -1242,6 +1242,10 @@ static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_serdes_tbl[] = { ...@@ -1242,6 +1242,10 @@ static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_VCO_DC_LEVEL_CTRL, 0x0f), QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_VCO_DC_LEVEL_CTRL, 0x0f),
}; };
static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x4_pcie_serdes_4ln_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN, 0x1c),
};
static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl[] = { static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RXCLK_DIV2_CTRL, 0x01), QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RXCLK_DIV2_CTRL, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_DFE_DAC_ENABLE1, 0x88), QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_DFE_DAC_ENABLE1, 0x88),
...@@ -3654,6 +3658,41 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x2_pciephy_cfg = { ...@@ -3654,6 +3658,41 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x2_pciephy_cfg = {
.ln_shrd = x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl, .ln_shrd = x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl,
.ln_shrd_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl), .ln_shrd_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl),
}, },
.reset_list = sdm845_pciephy_reset_l,
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
.vreg_list = sm8550_qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l),
.regs = pciephy_v6_regs_layout,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS_4_20,
.has_nocsr_reset = true,
};
static const struct qmp_phy_cfg x1e80100_qmp_gen4x4_pciephy_cfg = {
.lanes = 4,
.offsets = &qmp_pcie_offsets_v6_20,
.tbls = {
.serdes = x1e80100_qmp_gen4x2_pcie_serdes_tbl,
.serdes_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_serdes_tbl),
.tx = x1e80100_qmp_gen4x2_pcie_tx_tbl,
.tx_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_tx_tbl),
.rx = x1e80100_qmp_gen4x2_pcie_rx_tbl,
.rx_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_rx_tbl),
.pcs = x1e80100_qmp_gen4x2_pcie_pcs_tbl,
.pcs_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_pcs_tbl),
.pcs_misc = x1e80100_qmp_gen4x2_pcie_pcs_misc_tbl,
.pcs_misc_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_pcs_misc_tbl),
.ln_shrd = x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl,
.ln_shrd_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl),
},
.serdes_4ln_tbl = x1e80100_qmp_gen4x4_pcie_serdes_4ln_tbl,
.serdes_4ln_num = ARRAY_SIZE(x1e80100_qmp_gen4x4_pcie_serdes_4ln_tbl),
.reset_list = sdm845_pciephy_reset_l, .reset_list = sdm845_pciephy_reset_l,
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
.vreg_list = sm8550_qmp_phy_vreg_l, .vreg_list = sm8550_qmp_phy_vreg_l,
...@@ -3669,18 +3708,30 @@ static void qmp_pcie_init_port_b(struct qmp_pcie *qmp, const struct qmp_phy_cfg_ ...@@ -3669,18 +3708,30 @@ static void qmp_pcie_init_port_b(struct qmp_pcie *qmp, const struct qmp_phy_cfg_
{ {
const struct qmp_phy_cfg *cfg = qmp->cfg; const struct qmp_phy_cfg *cfg = qmp->cfg;
const struct qmp_pcie_offsets *offs = cfg->offsets; const struct qmp_pcie_offsets *offs = cfg->offsets;
void __iomem *tx3, *rx3, *tx4, *rx4; void __iomem *serdes, *tx3, *rx3, *tx4, *rx4, *pcs, *pcs_misc, *ln_shrd;
serdes = qmp->port_b + offs->serdes;
tx3 = qmp->port_b + offs->tx; tx3 = qmp->port_b + offs->tx;
rx3 = qmp->port_b + offs->rx; rx3 = qmp->port_b + offs->rx;
tx4 = qmp->port_b + offs->tx2; tx4 = qmp->port_b + offs->tx2;
rx4 = qmp->port_b + offs->rx2; rx4 = qmp->port_b + offs->rx2;
pcs = qmp->port_b + offs->pcs;
pcs_misc = qmp->port_b + offs->pcs_misc;
ln_shrd = qmp->port_b + offs->ln_shrd;
qmp_configure_lane(tx3, tbls->tx, tbls->tx_num, 1); qmp_configure(qmp->dev, serdes, tbls->serdes, tbls->serdes_num);
qmp_configure_lane(rx3, tbls->rx, tbls->rx_num, 1); qmp_configure(qmp->dev, serdes, cfg->serdes_4ln_tbl, cfg->serdes_4ln_num);
qmp_configure_lane(tx4, tbls->tx, tbls->tx_num, 2); qmp_configure_lane(qmp->dev, tx3, tbls->tx, tbls->tx_num, 1);
qmp_configure_lane(rx4, tbls->rx, tbls->rx_num, 2); qmp_configure_lane(qmp->dev, rx3, tbls->rx, tbls->rx_num, 1);
qmp_configure_lane(qmp->dev, tx4, tbls->tx, tbls->tx_num, 2);
qmp_configure_lane(qmp->dev, rx4, tbls->rx, tbls->rx_num, 2);
qmp_configure(qmp->dev, pcs, tbls->pcs, tbls->pcs_num);
qmp_configure(qmp->dev, pcs_misc, tbls->pcs_misc, tbls->pcs_misc_num);
qmp_configure(qmp->dev, ln_shrd, tbls->ln_shrd, tbls->ln_shrd_num);
} }
static void qmp_pcie_init_registers(struct qmp_pcie *qmp, const struct qmp_phy_cfg_tbls *tbls) static void qmp_pcie_init_registers(struct qmp_pcie *qmp, const struct qmp_phy_cfg_tbls *tbls)
...@@ -3698,25 +3749,26 @@ static void qmp_pcie_init_registers(struct qmp_pcie *qmp, const struct qmp_phy_c ...@@ -3698,25 +3749,26 @@ static void qmp_pcie_init_registers(struct qmp_pcie *qmp, const struct qmp_phy_c
if (!tbls) if (!tbls)
return; return;
qmp_configure(serdes, tbls->serdes, tbls->serdes_num); qmp_configure(qmp->dev, serdes, tbls->serdes, tbls->serdes_num);
qmp_configure_lane(tx, tbls->tx, tbls->tx_num, 1); qmp_configure_lane(qmp->dev, tx, tbls->tx, tbls->tx_num, 1);
qmp_configure_lane(rx, tbls->rx, tbls->rx_num, 1); qmp_configure_lane(qmp->dev, rx, tbls->rx, tbls->rx_num, 1);
if (cfg->lanes >= 2) { if (cfg->lanes >= 2) {
qmp_configure_lane(tx2, tbls->tx, tbls->tx_num, 2); qmp_configure_lane(qmp->dev, tx2, tbls->tx, tbls->tx_num, 2);
qmp_configure_lane(rx2, tbls->rx, tbls->rx_num, 2); qmp_configure_lane(qmp->dev, rx2, tbls->rx, tbls->rx_num, 2);
} }
qmp_configure(pcs, tbls->pcs, tbls->pcs_num); qmp_configure(qmp->dev, pcs, tbls->pcs, tbls->pcs_num);
qmp_configure(pcs_misc, tbls->pcs_misc, tbls->pcs_misc_num); qmp_configure(qmp->dev, pcs_misc, tbls->pcs_misc, tbls->pcs_misc_num);
if (cfg->lanes >= 4 && qmp->tcsr_4ln_config) { if (cfg->lanes >= 4 && qmp->tcsr_4ln_config) {
qmp_configure(serdes, cfg->serdes_4ln_tbl, cfg->serdes_4ln_num); qmp_configure(qmp->dev, serdes, cfg->serdes_4ln_tbl,
cfg->serdes_4ln_num);
qmp_pcie_init_port_b(qmp, tbls); qmp_pcie_init_port_b(qmp, tbls);
} }
qmp_configure(ln_shrd, tbls->ln_shrd, tbls->ln_shrd_num); qmp_configure(qmp->dev, ln_shrd, tbls->ln_shrd, tbls->ln_shrd_num);
} }
static int qmp_pcie_init(struct phy *phy) static int qmp_pcie_init(struct phy *phy)
...@@ -4423,6 +4475,9 @@ static const struct of_device_id qmp_pcie_of_match_table[] = { ...@@ -4423,6 +4475,9 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
}, { }, {
.compatible = "qcom,x1e80100-qmp-gen4x2-pcie-phy", .compatible = "qcom,x1e80100-qmp-gen4x2-pcie-phy",
.data = &x1e80100_qmp_gen4x2_pciephy_cfg, .data = &x1e80100_qmp_gen4x2_pciephy_cfg,
}, {
.compatible = "qcom,x1e80100-qmp-gen4x4-pcie-phy",
.data = &x1e80100_qmp_gen4x4_pciephy_cfg,
}, },
{ }, { },
}; };
......
...@@ -1527,7 +1527,7 @@ static void qmp_ufs_serdes_init(struct qmp_ufs *qmp, const struct qmp_phy_cfg_tb ...@@ -1527,7 +1527,7 @@ static void qmp_ufs_serdes_init(struct qmp_ufs *qmp, const struct qmp_phy_cfg_tb
{ {
void __iomem *serdes = qmp->serdes; void __iomem *serdes = qmp->serdes;
qmp_configure(serdes, tbls->serdes, tbls->serdes_num); qmp_configure(qmp->dev, serdes, tbls->serdes, tbls->serdes_num);
} }
static void qmp_ufs_lanes_init(struct qmp_ufs *qmp, const struct qmp_phy_cfg_tbls *tbls) static void qmp_ufs_lanes_init(struct qmp_ufs *qmp, const struct qmp_phy_cfg_tbls *tbls)
...@@ -1536,12 +1536,12 @@ static void qmp_ufs_lanes_init(struct qmp_ufs *qmp, const struct qmp_phy_cfg_tbl ...@@ -1536,12 +1536,12 @@ static void qmp_ufs_lanes_init(struct qmp_ufs *qmp, const struct qmp_phy_cfg_tbl
void __iomem *tx = qmp->tx; void __iomem *tx = qmp->tx;
void __iomem *rx = qmp->rx; void __iomem *rx = qmp->rx;
qmp_configure_lane(tx, tbls->tx, tbls->tx_num, 1); qmp_configure_lane(qmp->dev, tx, tbls->tx, tbls->tx_num, 1);
qmp_configure_lane(rx, tbls->rx, tbls->rx_num, 1); qmp_configure_lane(qmp->dev, rx, tbls->rx, tbls->rx_num, 1);
if (cfg->lanes >= 2) { if (cfg->lanes >= 2) {
qmp_configure_lane(qmp->tx2, tbls->tx, tbls->tx_num, 2); qmp_configure_lane(qmp->dev, qmp->tx2, tbls->tx, tbls->tx_num, 2);
qmp_configure_lane(qmp->rx2, tbls->rx, tbls->rx_num, 2); qmp_configure_lane(qmp->dev, qmp->rx2, tbls->rx, tbls->rx_num, 2);
} }
} }
...@@ -1549,7 +1549,7 @@ static void qmp_ufs_pcs_init(struct qmp_ufs *qmp, const struct qmp_phy_cfg_tbls ...@@ -1549,7 +1549,7 @@ static void qmp_ufs_pcs_init(struct qmp_ufs *qmp, const struct qmp_phy_cfg_tbls
{ {
void __iomem *pcs = qmp->pcs; void __iomem *pcs = qmp->pcs;
qmp_configure(pcs, tbls->pcs, tbls->pcs_num); qmp_configure(qmp->dev, pcs, tbls->pcs, tbls->pcs_num);
} }
static int qmp_ufs_get_gear_overlay(struct qmp_ufs *qmp, const struct qmp_phy_cfg *cfg) static int qmp_ufs_get_gear_overlay(struct qmp_ufs *qmp, const struct qmp_phy_cfg *cfg)
......
...@@ -1649,7 +1649,7 @@ static int qmp_usb_serdes_init(struct qmp_usb *qmp) ...@@ -1649,7 +1649,7 @@ static int qmp_usb_serdes_init(struct qmp_usb *qmp)
const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl;
int serdes_tbl_num = cfg->serdes_tbl_num; int serdes_tbl_num = cfg->serdes_tbl_num;
qmp_configure(serdes, serdes_tbl, serdes_tbl_num); qmp_configure(qmp->dev, serdes, serdes_tbl, serdes_tbl_num);
return 0; return 0;
} }
...@@ -1730,13 +1730,13 @@ static int qmp_usb_power_on(struct phy *phy) ...@@ -1730,13 +1730,13 @@ static int qmp_usb_power_on(struct phy *phy)
} }
/* Tx, Rx, and PCS configurations */ /* Tx, Rx, and PCS configurations */
qmp_configure_lane(tx, cfg->tx_tbl, cfg->tx_tbl_num, 1); qmp_configure_lane(qmp->dev, tx, cfg->tx_tbl, cfg->tx_tbl_num, 1);
qmp_configure_lane(rx, cfg->rx_tbl, cfg->rx_tbl_num, 1); qmp_configure_lane(qmp->dev, rx, cfg->rx_tbl, cfg->rx_tbl_num, 1);
qmp_configure(pcs, cfg->pcs_tbl, cfg->pcs_tbl_num); qmp_configure(qmp->dev, pcs, cfg->pcs_tbl, cfg->pcs_tbl_num);
if (pcs_usb) if (pcs_usb)
qmp_configure(pcs_usb, cfg->pcs_usb_tbl, cfg->pcs_usb_tbl_num); qmp_configure(qmp->dev, pcs_usb, cfg->pcs_usb_tbl, cfg->pcs_usb_tbl_num);
if (cfg->has_pwrdn_delay) if (cfg->has_pwrdn_delay)
usleep_range(10, 20); usleep_range(10, 20);
......
...@@ -526,7 +526,8 @@ static int qmp_usbc_power_on(struct phy *phy) ...@@ -526,7 +526,8 @@ static int qmp_usbc_power_on(struct phy *phy)
unsigned int val; unsigned int val;
int ret; int ret;
qmp_configure(qmp->serdes, cfg->serdes_tbl, cfg->serdes_tbl_num); qmp_configure(qmp->dev, qmp->serdes, cfg->serdes_tbl,
cfg->serdes_tbl_num);
ret = clk_prepare_enable(qmp->pipe_clk); ret = clk_prepare_enable(qmp->pipe_clk);
if (ret) { if (ret) {
...@@ -535,13 +536,13 @@ static int qmp_usbc_power_on(struct phy *phy) ...@@ -535,13 +536,13 @@ static int qmp_usbc_power_on(struct phy *phy)
} }
/* Tx, Rx, and PCS configurations */ /* Tx, Rx, and PCS configurations */
qmp_configure_lane(qmp->tx, cfg->tx_tbl, cfg->tx_tbl_num, 1); qmp_configure_lane(qmp->dev, qmp->tx, cfg->tx_tbl, cfg->tx_tbl_num, 1);
qmp_configure_lane(qmp->rx, cfg->rx_tbl, cfg->rx_tbl_num, 1); qmp_configure_lane(qmp->dev, qmp->rx, cfg->rx_tbl, cfg->rx_tbl_num, 1);
qmp_configure_lane(qmp->tx2, cfg->tx_tbl, cfg->tx_tbl_num, 2); qmp_configure_lane(qmp->dev, qmp->tx2, cfg->tx_tbl, cfg->tx_tbl_num, 2);
qmp_configure_lane(qmp->rx2, cfg->rx_tbl, cfg->rx_tbl_num, 2); qmp_configure_lane(qmp->dev, qmp->rx2, cfg->rx_tbl, cfg->rx_tbl_num, 2);
qmp_configure(qmp->pcs, cfg->pcs_tbl, cfg->pcs_tbl_num); qmp_configure(qmp->dev, qmp->pcs, cfg->pcs_tbl, cfg->pcs_tbl_num);
/* Pull PHY out of reset state */ /* Pull PHY out of reset state */
qphy_clrbits(qmp->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); qphy_clrbits(qmp->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
......
...@@ -19,12 +19,14 @@ ...@@ -19,12 +19,14 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/reset.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/usb/of.h> #include <linux/usb/of.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
/******* USB2.0 Host registers (original offset is +0x200) *******/ /******* USB2.0 Host registers (original offset is +0x200) *******/
#define USB2_INT_ENABLE 0x000 #define USB2_INT_ENABLE 0x000
#define USB2_AHB_BUS_CTR 0x008
#define USB2_USBCTR 0x00c #define USB2_USBCTR 0x00c
#define USB2_SPD_RSM_TIMSET 0x10c #define USB2_SPD_RSM_TIMSET 0x10c
#define USB2_OC_TIMSET 0x110 #define USB2_OC_TIMSET 0x110
...@@ -40,6 +42,10 @@ ...@@ -40,6 +42,10 @@
#define USB2_INT_ENABLE_USBH_INTB_EN BIT(2) /* For EHCI */ #define USB2_INT_ENABLE_USBH_INTB_EN BIT(2) /* For EHCI */
#define USB2_INT_ENABLE_USBH_INTA_EN BIT(1) /* For OHCI */ #define USB2_INT_ENABLE_USBH_INTA_EN BIT(1) /* For OHCI */
/* AHB_BUS_CTR */
#define USB2_AHB_BUS_CTR_MBL_MASK GENMASK(1, 0)
#define USB2_AHB_BUS_CTR_MBL_INCR4 2
/* USBCTR */ /* USBCTR */
#define USB2_USBCTR_DIRPD BIT(2) #define USB2_USBCTR_DIRPD BIT(2)
#define USB2_USBCTR_PLL_RST BIT(1) #define USB2_USBCTR_PLL_RST BIT(1)
...@@ -111,6 +117,7 @@ struct rcar_gen3_chan { ...@@ -111,6 +117,7 @@ struct rcar_gen3_chan {
struct extcon_dev *extcon; struct extcon_dev *extcon;
struct rcar_gen3_phy rphys[NUM_OF_PHYS]; struct rcar_gen3_phy rphys[NUM_OF_PHYS];
struct regulator *vbus; struct regulator *vbus;
struct reset_control *rstc;
struct work_struct work; struct work_struct work;
struct mutex lock; /* protects rphys[...].powered */ struct mutex lock; /* protects rphys[...].powered */
enum usb_dr_mode dr_mode; enum usb_dr_mode dr_mode;
...@@ -125,6 +132,7 @@ struct rcar_gen3_chan { ...@@ -125,6 +132,7 @@ struct rcar_gen3_chan {
struct rcar_gen3_phy_drv_data { struct rcar_gen3_phy_drv_data {
const struct phy_ops *phy_usb2_ops; const struct phy_ops *phy_usb2_ops;
bool no_adp_ctrl; bool no_adp_ctrl;
bool init_bus;
}; };
/* /*
...@@ -575,6 +583,12 @@ static const struct rcar_gen3_phy_drv_data rz_g2l_phy_usb2_data = { ...@@ -575,6 +583,12 @@ static const struct rcar_gen3_phy_drv_data rz_g2l_phy_usb2_data = {
.no_adp_ctrl = true, .no_adp_ctrl = true,
}; };
static const struct rcar_gen3_phy_drv_data rz_g3s_phy_usb2_data = {
.phy_usb2_ops = &rcar_gen3_phy_usb2_ops,
.no_adp_ctrl = true,
.init_bus = true,
};
static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = { static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = {
{ {
.compatible = "renesas,usb2-phy-r8a77470", .compatible = "renesas,usb2-phy-r8a77470",
...@@ -596,6 +610,10 @@ static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = { ...@@ -596,6 +610,10 @@ static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = {
.compatible = "renesas,rzg2l-usb2-phy", .compatible = "renesas,rzg2l-usb2-phy",
.data = &rz_g2l_phy_usb2_data, .data = &rz_g2l_phy_usb2_data,
}, },
{
.compatible = "renesas,usb2-phy-r9a08g045",
.data = &rz_g3s_phy_usb2_data,
},
{ {
.compatible = "renesas,rcar-gen3-usb2-phy", .compatible = "renesas,rcar-gen3-usb2-phy",
.data = &rcar_gen3_phy_usb2_data, .data = &rcar_gen3_phy_usb2_data,
...@@ -650,6 +668,35 @@ static enum usb_dr_mode rcar_gen3_get_dr_mode(struct device_node *np) ...@@ -650,6 +668,35 @@ static enum usb_dr_mode rcar_gen3_get_dr_mode(struct device_node *np)
return candidate; return candidate;
} }
static int rcar_gen3_phy_usb2_init_bus(struct rcar_gen3_chan *channel)
{
struct device *dev = channel->dev;
int ret;
u32 val;
channel->rstc = devm_reset_control_array_get_shared(dev);
if (IS_ERR(channel->rstc))
return PTR_ERR(channel->rstc);
ret = pm_runtime_resume_and_get(dev);
if (ret)
return ret;
ret = reset_control_deassert(channel->rstc);
if (ret)
goto rpm_put;
val = readl(channel->base + USB2_AHB_BUS_CTR);
val &= ~USB2_AHB_BUS_CTR_MBL_MASK;
val |= USB2_AHB_BUS_CTR_MBL_INCR4;
writel(val, channel->base + USB2_AHB_BUS_CTR);
rpm_put:
pm_runtime_put(dev);
return ret;
}
static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
{ {
const struct rcar_gen3_phy_drv_data *phy_data; const struct rcar_gen3_phy_drv_data *phy_data;
...@@ -703,6 +750,15 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) ...@@ -703,6 +750,15 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
goto error; goto error;
} }
platform_set_drvdata(pdev, channel);
channel->dev = dev;
if (phy_data->init_bus) {
ret = rcar_gen3_phy_usb2_init_bus(channel);
if (ret)
goto error;
}
channel->soc_no_adp_ctrl = phy_data->no_adp_ctrl; channel->soc_no_adp_ctrl = phy_data->no_adp_ctrl;
if (phy_data->no_adp_ctrl) if (phy_data->no_adp_ctrl)
channel->obint_enable_bits = USB2_OBINT_IDCHG_EN; channel->obint_enable_bits = USB2_OBINT_IDCHG_EN;
...@@ -733,9 +789,6 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) ...@@ -733,9 +789,6 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
channel->vbus = NULL; channel->vbus = NULL;
} }
platform_set_drvdata(pdev, channel);
channel->dev = dev;
provider = devm_of_phy_provider_register(dev, rcar_gen3_phy_usb2_xlate); provider = devm_of_phy_provider_register(dev, rcar_gen3_phy_usb2_xlate);
if (IS_ERR(provider)) { if (IS_ERR(provider)) {
dev_err(dev, "Failed to register PHY provider\n"); dev_err(dev, "Failed to register PHY provider\n");
...@@ -762,6 +815,7 @@ static void rcar_gen3_phy_usb2_remove(struct platform_device *pdev) ...@@ -762,6 +815,7 @@ static void rcar_gen3_phy_usb2_remove(struct platform_device *pdev)
if (channel->is_otg_channel) if (channel->is_otg_channel)
device_remove_file(&pdev->dev, &dev_attr_role); device_remove_file(&pdev->dev, &dev_attr_role);
reset_control_assert(channel->rstc);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
}; };
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
*/ */
#include <linux/bitfield.h> #include <linux/bitfield.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -15,6 +16,7 @@ ...@@ -15,6 +16,7 @@
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/phy/phy.h> #include <linux/phy/phy.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/rational.h> #include <linux/rational.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/reset.h> #include <linux/reset.h>
...@@ -190,6 +192,8 @@ ...@@ -190,6 +192,8 @@
#define LN3_TX_SER_RATE_SEL_HBR2 BIT(3) #define LN3_TX_SER_RATE_SEL_HBR2 BIT(3)
#define LN3_TX_SER_RATE_SEL_HBR3 BIT(2) #define LN3_TX_SER_RATE_SEL_HBR3 BIT(2)
#define HDMI20_MAX_RATE 600000000
struct lcpll_config { struct lcpll_config {
u32 bit_rate; u32 bit_rate;
u8 lcvco_mode_en; u8 lcvco_mode_en;
...@@ -272,6 +276,12 @@ struct rk_hdptx_phy { ...@@ -272,6 +276,12 @@ struct rk_hdptx_phy {
struct clk_bulk_data *clks; struct clk_bulk_data *clks;
int nr_clks; int nr_clks;
struct reset_control_bulk_data rsts[RST_MAX]; struct reset_control_bulk_data rsts[RST_MAX];
/* clk provider */
struct clk_hw hw;
unsigned long rate;
atomic_t usage_count;
}; };
static const struct ropll_config ropll_tmds_cfg[] = { static const struct ropll_config ropll_tmds_cfg[] = {
...@@ -759,6 +769,8 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx, ...@@ -759,6 +769,8 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
struct ropll_config rc = {0}; struct ropll_config rc = {0};
int i; int i;
hdptx->rate = rate * 100;
for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++) for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
if (rate == ropll_tmds_cfg[i].bit_rate) { if (rate == ropll_tmds_cfg[i].bit_rate) {
cfg = &ropll_tmds_cfg[i]; cfg = &ropll_tmds_cfg[i];
...@@ -822,19 +834,6 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx, ...@@ -822,19 +834,6 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx, static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
unsigned int rate) unsigned int rate)
{ {
u32 val;
int ret;
ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val);
if (ret)
return ret;
if (!(val & HDPTX_O_PLL_LOCK_DONE)) {
ret = rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
if (ret)
return ret;
}
rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq); rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq);
regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06); regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
...@@ -856,10 +855,68 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx, ...@@ -856,10 +855,68 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
return rk_hdptx_post_enable_lane(hdptx); return rk_hdptx_post_enable_lane(hdptx);
} }
static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx,
unsigned int rate)
{
u32 status;
int ret;
if (atomic_inc_return(&hdptx->usage_count) > 1)
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 (rate) {
ret = rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
if (ret)
goto dec_usage;
}
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)
{
u32 status;
int ret;
ret = atomic_dec_return(&hdptx->usage_count);
if (ret > 0)
return 0;
if (ret < 0) {
dev_warn(hdptx->dev, "Usage count underflow!\n");
ret = -EINVAL;
} else {
ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &status);
if (!ret) {
if (status & HDPTX_O_PLL_LOCK_DONE)
rk_hdptx_phy_disable(hdptx);
return 0;
} else if (force) {
return 0;
}
}
atomic_inc(&hdptx->usage_count);
return ret;
}
static int rk_hdptx_phy_power_on(struct phy *phy) static int rk_hdptx_phy_power_on(struct phy *phy)
{ {
struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy); struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
int ret, bus_width = phy_get_bus_width(hdptx->phy); int bus_width = phy_get_bus_width(hdptx->phy);
int ret;
/* /*
* FIXME: Temporary workaround to pass pixel_clk_rate * FIXME: Temporary workaround to pass pixel_clk_rate
* from the HDMI bridge driver until phy_configure_opts_hdmi * from the HDMI bridge driver until phy_configure_opts_hdmi
...@@ -870,15 +927,13 @@ static int rk_hdptx_phy_power_on(struct phy *phy) ...@@ -870,15 +927,13 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n", dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n",
__func__, bus_width, rate); __func__, bus_width, rate);
ret = pm_runtime_resume_and_get(hdptx->dev); ret = rk_hdptx_phy_consumer_get(hdptx, rate);
if (ret) { if (ret)
dev_err(hdptx->dev, "Failed to resume phy: %d\n", ret);
return ret; return ret;
}
ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate); ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate);
if (ret) if (ret)
pm_runtime_put(hdptx->dev); rk_hdptx_phy_consumer_put(hdptx, true);
return ret; return ret;
} }
...@@ -886,16 +941,8 @@ static int rk_hdptx_phy_power_on(struct phy *phy) ...@@ -886,16 +941,8 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
static int rk_hdptx_phy_power_off(struct phy *phy) static int rk_hdptx_phy_power_off(struct phy *phy)
{ {
struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy); struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
u32 val;
int ret;
ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val); return rk_hdptx_phy_consumer_put(hdptx, false);
if (ret == 0 && (val & HDPTX_O_PLL_LOCK_DONE))
rk_hdptx_phy_disable(hdptx);
pm_runtime_put(hdptx->dev);
return ret;
} }
static const struct phy_ops rk_hdptx_phy_ops = { static const struct phy_ops rk_hdptx_phy_ops = {
...@@ -904,6 +951,99 @@ static const struct phy_ops rk_hdptx_phy_ops = { ...@@ -904,6 +951,99 @@ static const struct phy_ops rk_hdptx_phy_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
static struct rk_hdptx_phy *to_rk_hdptx_phy(struct clk_hw *hw)
{
return container_of(hw, struct rk_hdptx_phy, hw);
}
static int rk_hdptx_phy_clk_prepare(struct clk_hw *hw)
{
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate / 100);
}
static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw)
{
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
rk_hdptx_phy_consumer_put(hdptx, true);
}
static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
return hdptx->rate;
}
static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
u32 bit_rate = rate / 100;
int i;
if (rate > HDMI20_MAX_RATE)
return rate;
for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
if (bit_rate == ropll_tmds_cfg[i].bit_rate)
break;
if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
!rk_hdptx_phy_clk_pll_calc(bit_rate, NULL))
return -EINVAL;
return rate;
}
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);
return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate / 100);
}
static const struct clk_ops hdptx_phy_clk_ops = {
.prepare = rk_hdptx_phy_clk_prepare,
.unprepare = rk_hdptx_phy_clk_unprepare,
.recalc_rate = rk_hdptx_phy_clk_recalc_rate,
.round_rate = rk_hdptx_phy_clk_round_rate,
.set_rate = rk_hdptx_phy_clk_set_rate,
};
static int rk_hdptx_phy_clk_register(struct rk_hdptx_phy *hdptx)
{
struct device *dev = hdptx->dev;
const char *name, *pname;
struct clk *refclk;
int ret, id;
refclk = devm_clk_get(dev, "ref");
if (IS_ERR(refclk))
return dev_err_probe(dev, PTR_ERR(refclk),
"Failed to get ref clock\n");
id = of_alias_get_id(dev->of_node, "hdptxphy");
name = id > 0 ? "clk_hdmiphy_pixel1" : "clk_hdmiphy_pixel0";
pname = __clk_get_name(refclk);
hdptx->hw.init = CLK_HW_INIT(name, pname, &hdptx_phy_clk_ops,
CLK_GET_RATE_NOCACHE);
ret = devm_clk_hw_register(dev, &hdptx->hw);
if (ret)
return dev_err_probe(dev, ret, "Failed to register clock\n");
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &hdptx->hw);
if (ret)
return dev_err_probe(dev, ret,
"Failed to register clk provider\n");
return 0;
}
static int rk_hdptx_phy_runtime_suspend(struct device *dev) static int rk_hdptx_phy_runtime_suspend(struct device *dev)
{ {
struct rk_hdptx_phy *hdptx = dev_get_drvdata(dev); struct rk_hdptx_phy *hdptx = dev_get_drvdata(dev);
...@@ -976,6 +1116,10 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev) ...@@ -976,6 +1116,10 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(hdptx->grf), return dev_err_probe(dev, PTR_ERR(hdptx->grf),
"Could not get GRF syscon\n"); "Could not get GRF syscon\n");
ret = devm_pm_runtime_enable(dev);
if (ret)
return dev_err_probe(dev, ret, "Failed to enable runtime PM\n");
hdptx->phy = devm_phy_create(dev, NULL, &rk_hdptx_phy_ops); hdptx->phy = devm_phy_create(dev, NULL, &rk_hdptx_phy_ops);
if (IS_ERR(hdptx->phy)) if (IS_ERR(hdptx->phy))
return dev_err_probe(dev, PTR_ERR(hdptx->phy), return dev_err_probe(dev, PTR_ERR(hdptx->phy),
...@@ -985,10 +1129,6 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev) ...@@ -985,10 +1129,6 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev)
phy_set_drvdata(hdptx->phy, hdptx); phy_set_drvdata(hdptx->phy, hdptx);
phy_set_bus_width(hdptx->phy, 8); phy_set_bus_width(hdptx->phy, 8);
ret = devm_pm_runtime_enable(dev);
if (ret)
return dev_err_probe(dev, ret, "Failed to enable runtime PM\n");
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(phy_provider)) if (IS_ERR(phy_provider))
return dev_err_probe(dev, PTR_ERR(phy_provider), return dev_err_probe(dev, PTR_ERR(phy_provider),
...@@ -998,7 +1138,7 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev) ...@@ -998,7 +1138,7 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev)
reset_control_deassert(hdptx->rsts[RST_CMN].rstc); reset_control_deassert(hdptx->rsts[RST_CMN].rstc);
reset_control_deassert(hdptx->rsts[RST_INIT].rstc); reset_control_deassert(hdptx->rsts[RST_INIT].rstc);
return 0; return rk_hdptx_phy_clk_register(hdptx);
} }
static const struct dev_pm_ops rk_hdptx_phy_pm_ops = { static const struct dev_pm_ops rk_hdptx_phy_pm_ops = {
......
...@@ -607,7 +607,7 @@ exynos5_usbdrd_usbdp_g2_v4_ctrl_pma_ready(struct exynos5_usbdrd_phy *phy_drd) ...@@ -607,7 +607,7 @@ exynos5_usbdrd_usbdp_g2_v4_ctrl_pma_ready(struct exynos5_usbdrd_phy *phy_drd)
reg = readl(regs_base + EXYNOS850_DRD_SECPMACTL); reg = readl(regs_base + EXYNOS850_DRD_SECPMACTL);
reg &= ~SECPMACTL_PMA_REF_FREQ_SEL; reg &= ~SECPMACTL_PMA_REF_FREQ_SEL;
reg |= FIELD_PREP_CONST(SECPMACTL_PMA_REF_FREQ_SEL, 1); reg |= FIELD_PREP(SECPMACTL_PMA_REF_FREQ_SEL, 1);
/* SFR reset */ /* SFR reset */
reg |= (SECPMACTL_PMA_LOW_PWR | SECPMACTL_PMA_APB_SW_RST); reg |= (SECPMACTL_PMA_LOW_PWR | SECPMACTL_PMA_APB_SW_RST);
reg &= ~(SECPMACTL_PMA_ROPLL_REF_CLK_SEL | reg &= ~(SECPMACTL_PMA_ROPLL_REF_CLK_SEL |
...@@ -1123,19 +1123,19 @@ static void exynos850_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd) ...@@ -1123,19 +1123,19 @@ static void exynos850_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
reg &= ~SSPPLLCTL_FSEL; reg &= ~SSPPLLCTL_FSEL;
switch (phy_drd->extrefclk) { switch (phy_drd->extrefclk) {
case EXYNOS5_FSEL_50MHZ: case EXYNOS5_FSEL_50MHZ:
reg |= FIELD_PREP_CONST(SSPPLLCTL_FSEL, 7); reg |= FIELD_PREP(SSPPLLCTL_FSEL, 7);
break; break;
case EXYNOS5_FSEL_26MHZ: case EXYNOS5_FSEL_26MHZ:
reg |= FIELD_PREP_CONST(SSPPLLCTL_FSEL, 6); reg |= FIELD_PREP(SSPPLLCTL_FSEL, 6);
break; break;
case EXYNOS5_FSEL_24MHZ: case EXYNOS5_FSEL_24MHZ:
reg |= FIELD_PREP_CONST(SSPPLLCTL_FSEL, 2); reg |= FIELD_PREP(SSPPLLCTL_FSEL, 2);
break; break;
case EXYNOS5_FSEL_20MHZ: case EXYNOS5_FSEL_20MHZ:
reg |= FIELD_PREP_CONST(SSPPLLCTL_FSEL, 1); reg |= FIELD_PREP(SSPPLLCTL_FSEL, 1);
break; break;
case EXYNOS5_FSEL_19MHZ2: case EXYNOS5_FSEL_19MHZ2:
reg |= FIELD_PREP_CONST(SSPPLLCTL_FSEL, 0); reg |= FIELD_PREP(SSPPLLCTL_FSEL, 0);
break; break;
default: default:
dev_warn(phy_drd->dev, "unsupported ref clk: %#.2x\n", dev_warn(phy_drd->dev, "unsupported ref clk: %#.2x\n",
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
*/ */
#include <dt-bindings/phy/phy.h> #include <dt-bindings/phy/phy.h>
#include <linux/cleanup.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -644,7 +645,6 @@ static int serdes_am654_clk_register(struct serdes_am654 *am654_phy, ...@@ -644,7 +645,6 @@ static int serdes_am654_clk_register(struct serdes_am654 *am654_phy,
struct device_node *node = am654_phy->of_node; struct device_node *node = am654_phy->of_node;
struct device *dev = am654_phy->dev; struct device *dev = am654_phy->dev;
struct serdes_am654_clk_mux *mux; struct serdes_am654_clk_mux *mux;
struct device_node *regmap_node;
const char **parent_names; const char **parent_names;
struct clk_init_data *init; struct clk_init_data *init;
unsigned int num_parents; unsigned int num_parents;
...@@ -652,7 +652,6 @@ static int serdes_am654_clk_register(struct serdes_am654 *am654_phy, ...@@ -652,7 +652,6 @@ static int serdes_am654_clk_register(struct serdes_am654 *am654_phy,
const __be32 *addr; const __be32 *addr;
unsigned int reg; unsigned int reg;
struct clk *clk; struct clk *clk;
int ret = 0;
mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL); mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
if (!mux) if (!mux)
...@@ -660,41 +659,30 @@ static int serdes_am654_clk_register(struct serdes_am654 *am654_phy, ...@@ -660,41 +659,30 @@ static int serdes_am654_clk_register(struct serdes_am654 *am654_phy,
init = &mux->clk_data; init = &mux->clk_data;
regmap_node = of_parse_phandle(node, "ti,serdes-clk", 0); struct device_node *regmap_node __free(device_node) =
if (!regmap_node) { of_parse_phandle(node, "ti,serdes-clk", 0);
dev_err(dev, "Fail to get serdes-clk node\n"); if (!regmap_node)
ret = -ENODEV; return dev_err_probe(dev, -ENODEV, "Fail to get serdes-clk node\n");
goto out_put_node;
}
regmap = syscon_node_to_regmap(regmap_node->parent); regmap = syscon_node_to_regmap(regmap_node->parent);
if (IS_ERR(regmap)) { if (IS_ERR(regmap))
dev_err(dev, "Fail to get Syscon regmap\n"); return dev_err_probe(dev, PTR_ERR(regmap),
ret = PTR_ERR(regmap); "Fail to get Syscon regmap\n");
goto out_put_node;
}
num_parents = of_clk_get_parent_count(node); num_parents = of_clk_get_parent_count(node);
if (num_parents < 2) { if (num_parents < 2)
dev_err(dev, "SERDES clock must have parents\n"); return dev_err_probe(dev, -EINVAL, "SERDES clock must have parents\n");
ret = -EINVAL;
goto out_put_node;
}
parent_names = devm_kzalloc(dev, (sizeof(char *) * num_parents), parent_names = devm_kzalloc(dev, (sizeof(char *) * num_parents),
GFP_KERNEL); GFP_KERNEL);
if (!parent_names) { if (!parent_names)
ret = -ENOMEM; return -ENOMEM;
goto out_put_node;
}
of_clk_parent_fill(node, parent_names, num_parents); of_clk_parent_fill(node, parent_names, num_parents);
addr = of_get_address(regmap_node, 0, NULL, NULL); addr = of_get_address(regmap_node, 0, NULL, NULL);
if (!addr) { if (!addr)
ret = -EINVAL; return -EINVAL;
goto out_put_node;
}
reg = be32_to_cpu(*addr); reg = be32_to_cpu(*addr);
...@@ -710,16 +698,12 @@ static int serdes_am654_clk_register(struct serdes_am654 *am654_phy, ...@@ -710,16 +698,12 @@ static int serdes_am654_clk_register(struct serdes_am654 *am654_phy,
mux->hw.init = init; mux->hw.init = init;
clk = devm_clk_register(dev, &mux->hw); clk = devm_clk_register(dev, &mux->hw);
if (IS_ERR(clk)) { if (IS_ERR(clk))
ret = PTR_ERR(clk); return PTR_ERR(clk);
goto out_put_node;
}
am654_phy->clks[clock_num] = clk; am654_phy->clks[clock_num] = clk;
out_put_node: return 0;
of_node_put(regmap_node);
return ret;
} }
static const struct of_device_id serdes_am654_id_table[] = { static const struct of_device_id serdes_am654_id_table[] = {
......
...@@ -468,11 +468,9 @@ static int phy_gmii_sel_probe(struct platform_device *pdev) ...@@ -468,11 +468,9 @@ static int phy_gmii_sel_probe(struct platform_device *pdev)
priv->regmap = syscon_node_to_regmap(node->parent); priv->regmap = syscon_node_to_regmap(node->parent);
if (IS_ERR(priv->regmap)) { if (IS_ERR(priv->regmap)) {
priv->regmap = device_node_to_regmap(node); priv->regmap = device_node_to_regmap(node);
if (IS_ERR(priv->regmap)) { if (IS_ERR(priv->regmap))
ret = PTR_ERR(priv->regmap); return dev_err_probe(dev, PTR_ERR(priv->regmap),
dev_err(dev, "Failed to get syscon %d\n", ret); "Failed to get syscon\n");
return ret;
}
priv->no_offset = true; priv->no_offset = true;
} }
...@@ -485,11 +483,9 @@ static int phy_gmii_sel_probe(struct platform_device *pdev) ...@@ -485,11 +483,9 @@ static int phy_gmii_sel_probe(struct platform_device *pdev)
priv->phy_provider = priv->phy_provider =
devm_of_phy_provider_register(dev, devm_of_phy_provider_register(dev,
phy_gmii_sel_of_xlate); phy_gmii_sel_of_xlate);
if (IS_ERR(priv->phy_provider)) { if (IS_ERR(priv->phy_provider))
ret = PTR_ERR(priv->phy_provider); return dev_err_probe(dev, PTR_ERR(priv->phy_provider),
dev_err(dev, "Failed to create phy provider %d\n", ret); "Failed to create phy provider\n");
return ret;
}
return 0; return 0;
} }
......
...@@ -1179,14 +1179,13 @@ static int wiz_clock_probe(struct wiz *wiz, struct device_node *node) ...@@ -1179,14 +1179,13 @@ static int wiz_clock_probe(struct wiz *wiz, struct device_node *node)
ret = wiz_mux_of_clk_register(wiz, clk_node, wiz->mux_sel_field[i], ret = wiz_mux_of_clk_register(wiz, clk_node, wiz->mux_sel_field[i],
clk_mux_sel[i].table); clk_mux_sel[i].table);
of_node_put(clk_node);
if (ret) { if (ret) {
dev_err_probe(dev, ret, "Failed to register %s clock\n", dev_err_probe(dev, ret, "Failed to register %s clock\n",
node_name); node_name);
of_node_put(clk_node);
goto err; goto err;
} }
of_node_put(clk_node);
} }
for (i = 0; i < wiz->clk_div_sel_num; i++) { for (i = 0; i < wiz->clk_div_sel_num; i++) {
...@@ -1199,14 +1198,12 @@ static int wiz_clock_probe(struct wiz *wiz, struct device_node *node) ...@@ -1199,14 +1198,12 @@ static int wiz_clock_probe(struct wiz *wiz, struct device_node *node)
ret = wiz_div_clk_register(wiz, clk_node, wiz->div_sel_field[i], ret = wiz_div_clk_register(wiz, clk_node, wiz->div_sel_field[i],
clk_div_sel[i].table); clk_div_sel[i].table);
of_node_put(clk_node);
if (ret) { if (ret) {
dev_err_probe(dev, ret, "Failed to register %s clock\n", dev_err_probe(dev, ret, "Failed to register %s clock\n",
node_name); node_name);
of_node_put(clk_node);
goto err; goto err;
} }
of_node_put(clk_node);
} }
return 0; return 0;
...@@ -1407,7 +1404,7 @@ MODULE_DEVICE_TABLE(of, wiz_id_table); ...@@ -1407,7 +1404,7 @@ MODULE_DEVICE_TABLE(of, wiz_id_table);
static int wiz_get_lane_phy_types(struct device *dev, struct wiz *wiz) static int wiz_get_lane_phy_types(struct device *dev, struct wiz *wiz)
{ {
struct device_node *serdes, *subnode; struct device_node *serdes;
serdes = of_get_child_by_name(dev->of_node, "serdes"); serdes = of_get_child_by_name(dev->of_node, "serdes");
if (!serdes) { if (!serdes) {
...@@ -1415,7 +1412,7 @@ static int wiz_get_lane_phy_types(struct device *dev, struct wiz *wiz) ...@@ -1415,7 +1412,7 @@ static int wiz_get_lane_phy_types(struct device *dev, struct wiz *wiz)
return -EINVAL; return -EINVAL;
} }
for_each_child_of_node(serdes, subnode) { for_each_child_of_node_scoped(serdes, subnode) {
u32 reg, num_lanes = 1, phy_type = PHY_NONE; u32 reg, num_lanes = 1, phy_type = PHY_NONE;
int ret, i; int ret, i;
...@@ -1425,7 +1422,6 @@ static int wiz_get_lane_phy_types(struct device *dev, struct wiz *wiz) ...@@ -1425,7 +1422,6 @@ static int wiz_get_lane_phy_types(struct device *dev, struct wiz *wiz)
ret = of_property_read_u32(subnode, "reg", &reg); ret = of_property_read_u32(subnode, "reg", &reg);
if (ret) { if (ret) {
of_node_put(subnode);
dev_err(dev, dev_err(dev,
"%s: Reading \"reg\" from \"%s\" failed: %d\n", "%s: Reading \"reg\" from \"%s\" failed: %d\n",
__func__, subnode->name, ret); __func__, subnode->name, ret);
...@@ -1578,8 +1574,8 @@ static int wiz_probe(struct platform_device *pdev) ...@@ -1578,8 +1574,8 @@ static int wiz_probe(struct platform_device *pdev)
phy_reset_dev = &wiz->wiz_phy_reset_dev; phy_reset_dev = &wiz->wiz_phy_reset_dev;
phy_reset_dev->dev = dev; phy_reset_dev->dev = dev;
phy_reset_dev->ops = &wiz_phy_reset_ops, phy_reset_dev->ops = &wiz_phy_reset_ops;
phy_reset_dev->owner = THIS_MODULE, phy_reset_dev->owner = THIS_MODULE;
phy_reset_dev->of_node = node; phy_reset_dev->of_node = node;
/* Reset for each of the lane and one for the entire SERDES */ /* Reset for each of the lane and one for the entire SERDES */
phy_reset_dev->nr_resets = num_lanes + 1; phy_reset_dev->nr_resets = num_lanes + 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment