Merge tag 'phy-fix-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy

Pull generic phy driver fixes from Vinod Koul:

 - Qualcomm repeater override properties, qmp pcie bindings fix for
   clocks and initialization sequence for firmware power down case

 - Marvell comphy bindings clock and child node constraints

 - Tegra xusb device reference leaks fix

 - TI omap usb device ref leak on unbind and RGMII IS settings fix

* tag 'phy-fix-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy:
  phy: qcom: qmp-pcie: Fix PHY initialization when powered down by firmware
  phy: ti: gmii-sel: Always write the RGMII ID setting
  dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Update pcie phy bindings
  phy: ti-pipe3: fix device leak at unbind
  phy: ti: omap-usb2: fix device leak at unbind
  phy: tegra: xusb: fix device and OF node leak at probe
  dt-bindings: phy: marvell,comphy-cp110: Fix clock and child node constraints
  phy: qualcomm: phy-qcom-eusb2-repeater: fix override properties
This commit is contained in:
Linus Torvalds
2025-09-14 13:17:30 -07:00
8 changed files with 114 additions and 27 deletions

View File

@@ -47,21 +47,19 @@ properties:
const: 0
clocks:
minItems: 1
maxItems: 3
description: Reference clocks for CP110; MG clock, MG Core clock, AXI clock
clock-names:
items:
- const: mg_clk
- const: mg_core_clk
- const: axi_clk
minItems: 1
maxItems: 3
marvell,system-controller:
description: Phandle to the Marvell system controller (CP110 only)
$ref: /schemas/types.yaml#/definitions/phandle
patternProperties:
'^phy@[0-2]$':
'^phy@[0-5]$':
description: A COMPHY lane child node
type: object
additionalProperties: false
@@ -69,10 +67,14 @@ patternProperties:
properties:
reg:
description: COMPHY lane number
maximum: 5
'#phy-cells':
const: 1
connector:
type: object
required:
- reg
- '#phy-cells'
@@ -91,13 +93,24 @@ allOf:
then:
properties:
clocks: false
clock-names: false
clocks:
maxItems: 1
clock-names:
const: xtal
required:
- reg-names
else:
properties:
clocks:
minItems: 3
clock-names:
items:
- const: mg_clk
- const: mg_core_clk
- const: axi_clk
required:
- marvell,system-controller

View File

@@ -176,6 +176,8 @@ allOf:
compatible:
contains:
enum:
- qcom,sa8775p-qmp-gen4x2-pcie-phy
- qcom,sa8775p-qmp-gen4x4-pcie-phy
- qcom,sc8280xp-qmp-gen3x1-pcie-phy
- qcom,sc8280xp-qmp-gen3x2-pcie-phy
- qcom,sc8280xp-qmp-gen3x4-pcie-phy
@@ -197,8 +199,6 @@ allOf:
contains:
enum:
- qcom,qcs8300-qmp-gen4x2-pcie-phy
- qcom,sa8775p-qmp-gen4x2-pcie-phy
- qcom,sa8775p-qmp-gen4x4-pcie-phy
then:
properties:
clocks:

View File

@@ -127,13 +127,13 @@ static int eusb2_repeater_init(struct phy *phy)
rptr->cfg->init_tbl[i].value);
/* Override registers from devicetree values */
if (!of_property_read_u8(np, "qcom,tune-usb2-amplitude", &val))
if (!of_property_read_u8(np, "qcom,tune-usb2-preem", &val))
regmap_write(regmap, base + EUSB2_TUNE_USB2_PREEM, val);
if (!of_property_read_u8(np, "qcom,tune-usb2-disc-thres", &val))
regmap_write(regmap, base + EUSB2_TUNE_HSDISC, val);
if (!of_property_read_u8(np, "qcom,tune-usb2-preem", &val))
if (!of_property_read_u8(np, "qcom,tune-usb2-amplitude", &val))
regmap_write(regmap, base + EUSB2_TUNE_IUSB2, val);
/* Wait for status OK */

View File

@@ -3067,6 +3067,14 @@ struct qmp_pcie {
struct clk_fixed_rate aux_clk_fixed;
};
static bool qphy_checkbits(const void __iomem *base, u32 offset, u32 val)
{
u32 reg;
reg = readl(base + offset);
return (reg & val) == val;
}
static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
{
u32 reg;
@@ -4339,16 +4347,21 @@ static int qmp_pcie_init(struct phy *phy)
struct qmp_pcie *qmp = phy_get_drvdata(phy);
const struct qmp_phy_cfg *cfg = qmp->cfg;
void __iomem *pcs = qmp->pcs;
bool phy_initialized = !!(readl(pcs + cfg->regs[QPHY_START_CTRL]));
int ret;
qmp->skip_init = qmp->nocsr_reset && phy_initialized;
/*
* We need to check the existence of init sequences in two cases:
* 1. The PHY doesn't support no_csr reset.
* 2. The PHY supports no_csr reset but isn't initialized by bootloader.
* As we can't skip init in these two cases.
* We can skip PHY initialization if all of the following conditions
* are met:
* 1. The PHY supports the nocsr_reset that preserves the PHY config.
* 2. The PHY was started (and not powered down again) by the
* bootloader, with all of the expected bits set correctly.
* In this case, we can continue without having the init sequence
* defined in the driver.
*/
qmp->skip_init = qmp->nocsr_reset &&
qphy_checkbits(pcs, cfg->regs[QPHY_START_CTRL], SERDES_START | PCS_START) &&
qphy_checkbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], cfg->pwrdn_ctrl);
if (!qmp->skip_init && !cfg->tbls.serdes_num) {
dev_err(qmp->dev, "Init sequence not available\n");
return -ENODATA;

View File

@@ -3164,18 +3164,22 @@ tegra210_xusb_padctl_probe(struct device *dev,
}
pdev = of_find_device_by_node(np);
of_node_put(np);
if (!pdev) {
dev_warn(dev, "PMC device is not available\n");
goto out;
}
if (!platform_get_drvdata(pdev))
if (!platform_get_drvdata(pdev)) {
put_device(&pdev->dev);
return ERR_PTR(-EPROBE_DEFER);
}
padctl->regmap = dev_get_regmap(&pdev->dev, "usb_sleepwalk");
if (!padctl->regmap)
dev_info(dev, "failed to find PMC regmap\n");
put_device(&pdev->dev);
out:
return &padctl->base;
}

View File

@@ -34,6 +34,7 @@ enum {
PHY_GMII_SEL_PORT_MODE = 0,
PHY_GMII_SEL_RGMII_ID_MODE,
PHY_GMII_SEL_RMII_IO_CLK_EN,
PHY_GMII_SEL_FIXED_TX_DELAY,
PHY_GMII_SEL_LAST,
};
@@ -127,6 +128,11 @@ static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode)
goto unsupported;
}
/* With a fixed delay, some modes are not supported at all. */
if (soc_data->features & BIT(PHY_GMII_SEL_FIXED_TX_DELAY) &&
rgmii_id != 0)
return -EINVAL;
if_phy->phy_if_mode = submode;
dev_dbg(dev, "%s id:%u mode:%u rgmii_id:%d rmii_clk_ext:%d\n",
@@ -210,25 +216,46 @@ struct phy_gmii_sel_soc_data phy_gmii_sel_soc_dm814 = {
static const
struct reg_field phy_gmii_sel_fields_am654[][PHY_GMII_SEL_LAST] = {
{ [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x0, 0, 2), },
{ [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x4, 0, 2), },
{ [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x8, 0, 2), },
{ [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0xC, 0, 2), },
{ [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x10, 0, 2), },
{ [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x14, 0, 2), },
{ [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x18, 0, 2), },
{ [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x1C, 0, 2), },
{
[PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x0, 0, 2),
[PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x0, 4, 4),
}, {
[PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x4, 0, 2),
[PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x4, 4, 4),
}, {
[PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x8, 0, 2),
[PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x8, 4, 4),
}, {
[PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0xC, 0, 2),
[PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0xC, 4, 4),
}, {
[PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x10, 0, 2),
[PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x10, 4, 4),
}, {
[PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x14, 0, 2),
[PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x14, 4, 4),
}, {
[PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x18, 0, 2),
[PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x18, 4, 4),
}, {
[PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x1C, 0, 2),
[PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x1C, 4, 4),
},
};
static const
struct phy_gmii_sel_soc_data phy_gmii_sel_soc_am654 = {
.use_of_data = true,
.features = BIT(PHY_GMII_SEL_RGMII_ID_MODE) |
BIT(PHY_GMII_SEL_FIXED_TX_DELAY),
.regfields = phy_gmii_sel_fields_am654,
};
static const
struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw5g_soc_j7200 = {
.use_of_data = true,
.features = BIT(PHY_GMII_SEL_RGMII_ID_MODE) |
BIT(PHY_GMII_SEL_FIXED_TX_DELAY),
.regfields = phy_gmii_sel_fields_am654,
.extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII) |
BIT(PHY_INTERFACE_MODE_USXGMII),
@@ -239,6 +266,8 @@ struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw5g_soc_j7200 = {
static const
struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j721e = {
.use_of_data = true,
.features = BIT(PHY_GMII_SEL_RGMII_ID_MODE) |
BIT(PHY_GMII_SEL_FIXED_TX_DELAY),
.regfields = phy_gmii_sel_fields_am654,
.extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII),
.num_ports = 8,
@@ -248,6 +277,8 @@ struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j721e = {
static const
struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j784s4 = {
.use_of_data = true,
.features = BIT(PHY_GMII_SEL_RGMII_ID_MODE) |
BIT(PHY_GMII_SEL_FIXED_TX_DELAY),
.regfields = phy_gmii_sel_fields_am654,
.extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII) |
BIT(PHY_INTERFACE_MODE_USXGMII),

View File

@@ -363,6 +363,13 @@ static void omap_usb2_init_errata(struct omap_usb *phy)
phy->flags |= OMAP_USB2_DISABLE_CHRG_DET;
}
static void omap_usb2_put_device(void *_dev)
{
struct device *dev = _dev;
put_device(dev);
}
static int omap_usb2_probe(struct platform_device *pdev)
{
struct omap_usb *phy;
@@ -373,6 +380,7 @@ static int omap_usb2_probe(struct platform_device *pdev)
struct device_node *control_node;
struct platform_device *control_pdev;
const struct usb_phy_data *phy_data;
int ret;
phy_data = device_get_match_data(&pdev->dev);
if (!phy_data)
@@ -423,6 +431,11 @@ static int omap_usb2_probe(struct platform_device *pdev)
return -EINVAL;
}
phy->control_dev = &control_pdev->dev;
ret = devm_add_action_or_reset(&pdev->dev, omap_usb2_put_device,
phy->control_dev);
if (ret)
return ret;
} else {
if (of_property_read_u32_index(node,
"syscon-phy-power", 1,

View File

@@ -667,12 +667,20 @@ static int ti_pipe3_get_clk(struct ti_pipe3 *phy)
return 0;
}
static void ti_pipe3_put_device(void *_dev)
{
struct device *dev = _dev;
put_device(dev);
}
static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy)
{
struct device *dev = phy->dev;
struct device_node *node = dev->of_node;
struct device_node *control_node;
struct platform_device *control_pdev;
int ret;
phy->phy_power_syscon = syscon_regmap_lookup_by_phandle(node,
"syscon-phy-power");
@@ -704,6 +712,11 @@ static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy)
}
phy->control_dev = &control_pdev->dev;
ret = devm_add_action_or_reset(dev, ti_pipe3_put_device,
phy->control_dev);
if (ret)
return ret;
}
if (phy->mode == PIPE3_MODE_PCIE) {