Merge branch 'net-phy-at803x-device-tree-binding'
Michael Walle says: ==================== net: phy: at803x device tree binding Adds a device tree binding to configure the clock and the RGMII voltage. Changes since v1: - rebased to latest net-next - renamed "Atheros" to "Qualcomm Atheros" - add a new patch to remove config_init() from AR9331 Changes since the RFC: - renamed the Kconfig entry to "Qualcomm Atheros.." and reordered the item - renamed the prefix from atheros to qca - use the correct name AR803x (instead of AT803x) in new files and dt-bindings. - listed the PHY maintainers in the new schema. Hopefully, thats ok. - fixed a typo in the bindings schema - run dtb_checks and dt_binding_check and fixed the schema - dropped the rgmii-io-1v8 property; instead provide two regulators vddh and vddio, add one consumer vddio-supply - fix the clock settings for the AR8030/AR8035 - only the AR8031 supports chaning the LDO and the PLL mode in software. Check if we have the correct PHY. - new patch to mention the AR8033 which is the same as the AR8031 just without PTP support - new patch which corrects any displayed PHY names and comments. Be consistent. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
16cf4222be
|
@ -0,0 +1,111 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/net/qca,ar803x.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Qualcomm Atheros AR803x PHY
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Andrew Lunn <andrew@lunn.ch>
|
||||||
|
- Florian Fainelli <f.fainelli@gmail.com>
|
||||||
|
- Heiner Kallweit <hkallweit1@gmail.com>
|
||||||
|
|
||||||
|
description: |
|
||||||
|
Bindings for Qualcomm Atheros AR803x PHYs
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: ethernet-phy.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
qca,clk-out-frequency:
|
||||||
|
description: Clock output frequency in Hertz.
|
||||||
|
allOf:
|
||||||
|
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||||
|
- enum: [ 25000000, 50000000, 62500000, 125000000 ]
|
||||||
|
|
||||||
|
qca,clk-out-strength:
|
||||||
|
description: Clock output driver strength.
|
||||||
|
allOf:
|
||||||
|
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||||
|
- enum: [ 0, 1, 2 ]
|
||||||
|
|
||||||
|
qca,keep-pll-enabled:
|
||||||
|
description: |
|
||||||
|
If set, keep the PLL enabled even if there is no link. Useful if you
|
||||||
|
want to use the clock output without an ethernet link.
|
||||||
|
|
||||||
|
Only supported on the AR8031.
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
vddio-supply:
|
||||||
|
description: |
|
||||||
|
RGMII I/O voltage regulator (see regulator/regulator.yaml).
|
||||||
|
|
||||||
|
The PHY supports RGMII I/O voltages of 1.5V, 1.8V and 2.5V. You can
|
||||||
|
either connect this to the vddio-regulator (1.5V / 1.8V) or the
|
||||||
|
vddh-regulator (2.5V).
|
||||||
|
|
||||||
|
Only supported on the AR8031.
|
||||||
|
|
||||||
|
vddio-regulator:
|
||||||
|
type: object
|
||||||
|
description:
|
||||||
|
Initial data for the VDDIO regulator. Set this to 1.5V or 1.8V.
|
||||||
|
allOf:
|
||||||
|
- $ref: /schemas/regulator/regulator.yaml
|
||||||
|
|
||||||
|
vddh-regulator:
|
||||||
|
type: object
|
||||||
|
description:
|
||||||
|
Dummy subnode to model the external connection of the PHY VDDH
|
||||||
|
regulator to VDDIO.
|
||||||
|
allOf:
|
||||||
|
- $ref: /schemas/regulator/regulator.yaml
|
||||||
|
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/net/qca-ar803x.h>
|
||||||
|
|
||||||
|
ethernet {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
phy-mode = "rgmii-id";
|
||||||
|
|
||||||
|
ethernet-phy@0 {
|
||||||
|
reg = <0>;
|
||||||
|
|
||||||
|
qca,clk-out-frequency = <125000000>;
|
||||||
|
qca,clk-out-strength = <AR803X_STRENGTH_FULL>;
|
||||||
|
|
||||||
|
vddio-supply = <&vddio>;
|
||||||
|
|
||||||
|
vddio: vddio-regulator {
|
||||||
|
regulator-min-microvolt = <1800000>;
|
||||||
|
regulator-max-microvolt = <1800000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/net/qca-ar803x.h>
|
||||||
|
|
||||||
|
ethernet {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
phy-mode = "rgmii-id";
|
||||||
|
|
||||||
|
ethernet-phy@0 {
|
||||||
|
reg = <0>;
|
||||||
|
|
||||||
|
qca,clk-out-frequency = <50000000>;
|
||||||
|
qca,keep-pll-enabled;
|
||||||
|
|
||||||
|
vddio-supply = <&vddh>;
|
||||||
|
|
||||||
|
vddh: vddh-regulator {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -6155,10 +6155,12 @@ S: Maintained
|
||||||
F: Documentation/ABI/testing/sysfs-class-net-phydev
|
F: Documentation/ABI/testing/sysfs-class-net-phydev
|
||||||
F: Documentation/devicetree/bindings/net/ethernet-phy.yaml
|
F: Documentation/devicetree/bindings/net/ethernet-phy.yaml
|
||||||
F: Documentation/devicetree/bindings/net/mdio*
|
F: Documentation/devicetree/bindings/net/mdio*
|
||||||
|
F: Documentation/devicetree/bindings/net/qca,ar803x.yaml
|
||||||
F: Documentation/networking/phy.rst
|
F: Documentation/networking/phy.rst
|
||||||
F: drivers/net/phy/
|
F: drivers/net/phy/
|
||||||
F: drivers/of/of_mdio.c
|
F: drivers/of/of_mdio.c
|
||||||
F: drivers/of/of_net.c
|
F: drivers/of/of_net.c
|
||||||
|
F: include/dt-bindings/net/qca-ar803x.h
|
||||||
F: include/linux/*mdio*.h
|
F: include/linux/*mdio*.h
|
||||||
F: include/linux/of_net.h
|
F: include/linux/of_net.h
|
||||||
F: include/linux/phy.h
|
F: include/linux/phy.h
|
||||||
|
|
|
@ -282,11 +282,6 @@ config AX88796B_PHY
|
||||||
Currently supports the Asix Electronics PHY found in the X-Surf 100
|
Currently supports the Asix Electronics PHY found in the X-Surf 100
|
||||||
AX88796B package.
|
AX88796B package.
|
||||||
|
|
||||||
config AT803X_PHY
|
|
||||||
tristate "AT803X PHYs"
|
|
||||||
---help---
|
|
||||||
Currently supports the AT8030 and AT8035 model
|
|
||||||
|
|
||||||
config BCM63XX_PHY
|
config BCM63XX_PHY
|
||||||
tristate "Broadcom 63xx SOCs internal PHY"
|
tristate "Broadcom 63xx SOCs internal PHY"
|
||||||
depends on BCM63XX || COMPILE_TEST
|
depends on BCM63XX || COMPILE_TEST
|
||||||
|
@ -444,6 +439,11 @@ config NXP_TJA11XX_PHY
|
||||||
---help---
|
---help---
|
||||||
Currently supports the NXP TJA1100 and TJA1101 PHY.
|
Currently supports the NXP TJA1100 and TJA1101 PHY.
|
||||||
|
|
||||||
|
config AT803X_PHY
|
||||||
|
tristate "Qualcomm Atheros AR803X PHYs"
|
||||||
|
help
|
||||||
|
Currently supports the AR8030, AR8031, AR8033 and AR8035 model
|
||||||
|
|
||||||
config QSEMI_PHY
|
config QSEMI_PHY
|
||||||
tristate "Quality Semiconductor PHYs"
|
tristate "Quality Semiconductor PHYs"
|
||||||
---help---
|
---help---
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
/*
|
/*
|
||||||
* drivers/net/phy/at803x.c
|
* drivers/net/phy/at803x.c
|
||||||
*
|
*
|
||||||
* Driver for Atheros 803x PHY
|
* Driver for Qualcomm Atheros AR803x PHY
|
||||||
*
|
*
|
||||||
* Author: Matus Ujhelyi <ujhelyi.m@gmail.com>
|
* Author: Matus Ujhelyi <ujhelyi.m@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
@ -13,7 +13,12 @@
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
#include <linux/etherdevice.h>
|
#include <linux/etherdevice.h>
|
||||||
#include <linux/of_gpio.h>
|
#include <linux/of_gpio.h>
|
||||||
|
#include <linux/bitfield.h>
|
||||||
#include <linux/gpio/consumer.h>
|
#include <linux/gpio/consumer.h>
|
||||||
|
#include <linux/regulator/of_regulator.h>
|
||||||
|
#include <linux/regulator/driver.h>
|
||||||
|
#include <linux/regulator/consumer.h>
|
||||||
|
#include <dt-bindings/net/qca-ar803x.h>
|
||||||
|
|
||||||
#define AT803X_SPECIFIC_STATUS 0x11
|
#define AT803X_SPECIFIC_STATUS 0x11
|
||||||
#define AT803X_SS_SPEED_MASK (3 << 14)
|
#define AT803X_SS_SPEED_MASK (3 << 14)
|
||||||
|
@ -62,16 +67,62 @@
|
||||||
#define AT803X_DEBUG_REG_5 0x05
|
#define AT803X_DEBUG_REG_5 0x05
|
||||||
#define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8)
|
#define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8)
|
||||||
|
|
||||||
|
#define AT803X_DEBUG_REG_1F 0x1F
|
||||||
|
#define AT803X_DEBUG_PLL_ON BIT(2)
|
||||||
|
#define AT803X_DEBUG_RGMII_1V8 BIT(3)
|
||||||
|
|
||||||
|
/* AT803x supports either the XTAL input pad, an internal PLL or the
|
||||||
|
* DSP as clock reference for the clock output pad. The XTAL reference
|
||||||
|
* is only used for 25 MHz output, all other frequencies need the PLL.
|
||||||
|
* The DSP as a clock reference is used in synchronous ethernet
|
||||||
|
* applications.
|
||||||
|
*
|
||||||
|
* By default the PLL is only enabled if there is a link. Otherwise
|
||||||
|
* the PHY will go into low power state and disabled the PLL. You can
|
||||||
|
* set the PLL_ON bit (see debug register 0x1f) to keep the PLL always
|
||||||
|
* enabled.
|
||||||
|
*/
|
||||||
|
#define AT803X_MMD7_CLK25M 0x8016
|
||||||
|
#define AT803X_CLK_OUT_MASK GENMASK(4, 2)
|
||||||
|
#define AT803X_CLK_OUT_25MHZ_XTAL 0
|
||||||
|
#define AT803X_CLK_OUT_25MHZ_DSP 1
|
||||||
|
#define AT803X_CLK_OUT_50MHZ_PLL 2
|
||||||
|
#define AT803X_CLK_OUT_50MHZ_DSP 3
|
||||||
|
#define AT803X_CLK_OUT_62_5MHZ_PLL 4
|
||||||
|
#define AT803X_CLK_OUT_62_5MHZ_DSP 5
|
||||||
|
#define AT803X_CLK_OUT_125MHZ_PLL 6
|
||||||
|
#define AT803X_CLK_OUT_125MHZ_DSP 7
|
||||||
|
|
||||||
|
/* The AR8035 has another mask which is compatible with the AR8031/AR8033 mask
|
||||||
|
* but doesn't support choosing between XTAL/PLL and DSP.
|
||||||
|
*/
|
||||||
|
#define AT8035_CLK_OUT_MASK GENMASK(4, 3)
|
||||||
|
|
||||||
|
#define AT803X_CLK_OUT_STRENGTH_MASK GENMASK(8, 7)
|
||||||
|
#define AT803X_CLK_OUT_STRENGTH_FULL 0
|
||||||
|
#define AT803X_CLK_OUT_STRENGTH_HALF 1
|
||||||
|
#define AT803X_CLK_OUT_STRENGTH_QUARTER 2
|
||||||
|
|
||||||
#define ATH9331_PHY_ID 0x004dd041
|
#define ATH9331_PHY_ID 0x004dd041
|
||||||
#define ATH8030_PHY_ID 0x004dd076
|
#define ATH8030_PHY_ID 0x004dd076
|
||||||
#define ATH8031_PHY_ID 0x004dd074
|
#define ATH8031_PHY_ID 0x004dd074
|
||||||
#define ATH8035_PHY_ID 0x004dd072
|
#define ATH8035_PHY_ID 0x004dd072
|
||||||
#define AT803X_PHY_ID_MASK 0xffffffef
|
#define AT803X_PHY_ID_MASK 0xffffffef
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Atheros 803x PHY driver");
|
MODULE_DESCRIPTION("Qualcomm Atheros AR803x PHY driver");
|
||||||
MODULE_AUTHOR("Matus Ujhelyi");
|
MODULE_AUTHOR("Matus Ujhelyi");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
struct at803x_priv {
|
||||||
|
int flags;
|
||||||
|
#define AT803X_KEEP_PLL_ENABLED BIT(0) /* don't turn off internal PLL */
|
||||||
|
u16 clk_25m_reg;
|
||||||
|
u16 clk_25m_mask;
|
||||||
|
struct regulator_dev *vddio_rdev;
|
||||||
|
struct regulator_dev *vddh_rdev;
|
||||||
|
struct regulator *vddio;
|
||||||
|
};
|
||||||
|
|
||||||
struct at803x_context {
|
struct at803x_context {
|
||||||
u16 bmcr;
|
u16 bmcr;
|
||||||
u16 advertise;
|
u16 advertise;
|
||||||
|
@ -237,6 +288,240 @@ static int at803x_resume(struct phy_device *phydev)
|
||||||
return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0);
|
return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int at803x_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev,
|
||||||
|
unsigned int selector)
|
||||||
|
{
|
||||||
|
struct phy_device *phydev = rdev_get_drvdata(rdev);
|
||||||
|
|
||||||
|
if (selector)
|
||||||
|
return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F,
|
||||||
|
0, AT803X_DEBUG_RGMII_1V8);
|
||||||
|
else
|
||||||
|
return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F,
|
||||||
|
AT803X_DEBUG_RGMII_1V8, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int at803x_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev)
|
||||||
|
{
|
||||||
|
struct phy_device *phydev = rdev_get_drvdata(rdev);
|
||||||
|
int val;
|
||||||
|
|
||||||
|
val = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_1F);
|
||||||
|
if (val < 0)
|
||||||
|
return val;
|
||||||
|
|
||||||
|
return (val & AT803X_DEBUG_RGMII_1V8) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct regulator_ops vddio_regulator_ops = {
|
||||||
|
.list_voltage = regulator_list_voltage_table,
|
||||||
|
.set_voltage_sel = at803x_rgmii_reg_set_voltage_sel,
|
||||||
|
.get_voltage_sel = at803x_rgmii_reg_get_voltage_sel,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned int vddio_voltage_table[] = {
|
||||||
|
1500000,
|
||||||
|
1800000,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regulator_desc vddio_desc = {
|
||||||
|
.name = "vddio",
|
||||||
|
.of_match = of_match_ptr("vddio-regulator"),
|
||||||
|
.n_voltages = ARRAY_SIZE(vddio_voltage_table),
|
||||||
|
.volt_table = vddio_voltage_table,
|
||||||
|
.ops = &vddio_regulator_ops,
|
||||||
|
.type = REGULATOR_VOLTAGE,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct regulator_ops vddh_regulator_ops = {
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regulator_desc vddh_desc = {
|
||||||
|
.name = "vddh",
|
||||||
|
.of_match = of_match_ptr("vddh-regulator"),
|
||||||
|
.n_voltages = 1,
|
||||||
|
.fixed_uV = 2500000,
|
||||||
|
.ops = &vddh_regulator_ops,
|
||||||
|
.type = REGULATOR_VOLTAGE,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int at8031_register_regulators(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
struct at803x_priv *priv = phydev->priv;
|
||||||
|
struct device *dev = &phydev->mdio.dev;
|
||||||
|
struct regulator_config config = { };
|
||||||
|
|
||||||
|
config.dev = dev;
|
||||||
|
config.driver_data = phydev;
|
||||||
|
|
||||||
|
priv->vddio_rdev = devm_regulator_register(dev, &vddio_desc, &config);
|
||||||
|
if (IS_ERR(priv->vddio_rdev)) {
|
||||||
|
phydev_err(phydev, "failed to register VDDIO regulator\n");
|
||||||
|
return PTR_ERR(priv->vddio_rdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->vddh_rdev = devm_regulator_register(dev, &vddh_desc, &config);
|
||||||
|
if (IS_ERR(priv->vddh_rdev)) {
|
||||||
|
phydev_err(phydev, "failed to register VDDH regulator\n");
|
||||||
|
return PTR_ERR(priv->vddh_rdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool at803x_match_phy_id(struct phy_device *phydev, u32 phy_id)
|
||||||
|
{
|
||||||
|
return (phydev->phy_id & phydev->drv->phy_id_mask)
|
||||||
|
== (phy_id & phydev->drv->phy_id_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int at803x_parse_dt(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
struct device_node *node = phydev->mdio.dev.of_node;
|
||||||
|
struct at803x_priv *priv = phydev->priv;
|
||||||
|
unsigned int sel, mask;
|
||||||
|
u32 freq, strength;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!IS_ENABLED(CONFIG_OF_MDIO))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = of_property_read_u32(node, "qca,clk-out-frequency", &freq);
|
||||||
|
if (!ret) {
|
||||||
|
mask = AT803X_CLK_OUT_MASK;
|
||||||
|
switch (freq) {
|
||||||
|
case 25000000:
|
||||||
|
sel = AT803X_CLK_OUT_25MHZ_XTAL;
|
||||||
|
break;
|
||||||
|
case 50000000:
|
||||||
|
sel = AT803X_CLK_OUT_50MHZ_PLL;
|
||||||
|
break;
|
||||||
|
case 62500000:
|
||||||
|
sel = AT803X_CLK_OUT_62_5MHZ_PLL;
|
||||||
|
break;
|
||||||
|
case 125000000:
|
||||||
|
sel = AT803X_CLK_OUT_125MHZ_PLL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
phydev_err(phydev, "invalid qca,clk-out-frequency\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->clk_25m_reg |= FIELD_PREP(mask, sel);
|
||||||
|
priv->clk_25m_mask |= mask;
|
||||||
|
|
||||||
|
/* Fixup for the AR8030/AR8035. This chip has another mask and
|
||||||
|
* doesn't support the DSP reference. Eg. the lowest bit of the
|
||||||
|
* mask. The upper two bits select the same frequencies. Mask
|
||||||
|
* the lowest bit here.
|
||||||
|
*
|
||||||
|
* Warning:
|
||||||
|
* There was no datasheet for the AR8030 available so this is
|
||||||
|
* just a guess. But the AR8035 is listed as pin compatible
|
||||||
|
* to the AR8030 so there might be a good chance it works on
|
||||||
|
* the AR8030 too.
|
||||||
|
*/
|
||||||
|
if (at803x_match_phy_id(phydev, ATH8030_PHY_ID) ||
|
||||||
|
at803x_match_phy_id(phydev, ATH8035_PHY_ID)) {
|
||||||
|
priv->clk_25m_reg &= ~AT8035_CLK_OUT_MASK;
|
||||||
|
priv->clk_25m_mask &= ~AT8035_CLK_OUT_MASK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = of_property_read_u32(node, "qca,clk-out-strength", &strength);
|
||||||
|
if (!ret) {
|
||||||
|
priv->clk_25m_mask |= AT803X_CLK_OUT_STRENGTH_MASK;
|
||||||
|
switch (strength) {
|
||||||
|
case AR803X_STRENGTH_FULL:
|
||||||
|
priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_FULL;
|
||||||
|
break;
|
||||||
|
case AR803X_STRENGTH_HALF:
|
||||||
|
priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_HALF;
|
||||||
|
break;
|
||||||
|
case AR803X_STRENGTH_QUARTER:
|
||||||
|
priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_QUARTER;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
phydev_err(phydev, "invalid qca,clk-out-strength\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping
|
||||||
|
* options.
|
||||||
|
*/
|
||||||
|
if (at803x_match_phy_id(phydev, ATH8031_PHY_ID)) {
|
||||||
|
if (of_property_read_bool(node, "qca,keep-pll-enabled"))
|
||||||
|
priv->flags |= AT803X_KEEP_PLL_ENABLED;
|
||||||
|
|
||||||
|
ret = at8031_register_regulators(phydev);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
priv->vddio = devm_regulator_get_optional(&phydev->mdio.dev,
|
||||||
|
"vddio");
|
||||||
|
if (IS_ERR(priv->vddio)) {
|
||||||
|
phydev_err(phydev, "failed to get VDDIO regulator\n");
|
||||||
|
return PTR_ERR(priv->vddio);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = regulator_enable(priv->vddio);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int at803x_probe(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
struct device *dev = &phydev->mdio.dev;
|
||||||
|
struct at803x_priv *priv;
|
||||||
|
|
||||||
|
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||||
|
if (!priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
phydev->priv = priv;
|
||||||
|
|
||||||
|
return at803x_parse_dt(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int at803x_clk_out_config(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
struct at803x_priv *priv = phydev->priv;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
if (!priv->clk_25m_mask)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
val = phy_read_mmd(phydev, MDIO_MMD_AN, AT803X_MMD7_CLK25M);
|
||||||
|
if (val < 0)
|
||||||
|
return val;
|
||||||
|
|
||||||
|
val &= ~priv->clk_25m_mask;
|
||||||
|
val |= priv->clk_25m_reg;
|
||||||
|
|
||||||
|
return phy_write_mmd(phydev, MDIO_MMD_AN, AT803X_MMD7_CLK25M, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int at8031_pll_config(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
struct at803x_priv *priv = phydev->priv;
|
||||||
|
|
||||||
|
/* The default after hardware reset is PLL OFF. After a soft reset, the
|
||||||
|
* values are retained.
|
||||||
|
*/
|
||||||
|
if (priv->flags & AT803X_KEEP_PLL_ENABLED)
|
||||||
|
return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F,
|
||||||
|
0, AT803X_DEBUG_PLL_ON);
|
||||||
|
else
|
||||||
|
return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F,
|
||||||
|
AT803X_DEBUG_PLL_ON, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static int at803x_config_init(struct phy_device *phydev)
|
static int at803x_config_init(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -259,8 +544,20 @@ static int at803x_config_init(struct phy_device *phydev)
|
||||||
ret = at803x_enable_tx_delay(phydev);
|
ret = at803x_enable_tx_delay(phydev);
|
||||||
else
|
else
|
||||||
ret = at803x_disable_tx_delay(phydev);
|
ret = at803x_disable_tx_delay(phydev);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
return ret;
|
ret = at803x_clk_out_config(phydev);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (at803x_match_phy_id(phydev, ATH8031_PHY_ID)) {
|
||||||
|
ret = at8031_pll_config(phydev);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int at803x_ack_interrupt(struct phy_device *phydev)
|
static int at803x_ack_interrupt(struct phy_device *phydev)
|
||||||
|
@ -409,10 +706,11 @@ static int at803x_read_status(struct phy_device *phydev)
|
||||||
|
|
||||||
static struct phy_driver at803x_driver[] = {
|
static struct phy_driver at803x_driver[] = {
|
||||||
{
|
{
|
||||||
/* ATHEROS 8035 */
|
/* Qualcomm Atheros AR8035 */
|
||||||
.phy_id = ATH8035_PHY_ID,
|
.phy_id = ATH8035_PHY_ID,
|
||||||
.name = "Atheros 8035 ethernet",
|
.name = "Qualcomm Atheros AR8035",
|
||||||
.phy_id_mask = AT803X_PHY_ID_MASK,
|
.phy_id_mask = AT803X_PHY_ID_MASK,
|
||||||
|
.probe = at803x_probe,
|
||||||
.config_init = at803x_config_init,
|
.config_init = at803x_config_init,
|
||||||
.set_wol = at803x_set_wol,
|
.set_wol = at803x_set_wol,
|
||||||
.get_wol = at803x_get_wol,
|
.get_wol = at803x_get_wol,
|
||||||
|
@ -423,10 +721,11 @@ static struct phy_driver at803x_driver[] = {
|
||||||
.ack_interrupt = at803x_ack_interrupt,
|
.ack_interrupt = at803x_ack_interrupt,
|
||||||
.config_intr = at803x_config_intr,
|
.config_intr = at803x_config_intr,
|
||||||
}, {
|
}, {
|
||||||
/* ATHEROS 8030 */
|
/* Qualcomm Atheros AR8030 */
|
||||||
.phy_id = ATH8030_PHY_ID,
|
.phy_id = ATH8030_PHY_ID,
|
||||||
.name = "Atheros 8030 ethernet",
|
.name = "Qualcomm Atheros AR8030",
|
||||||
.phy_id_mask = AT803X_PHY_ID_MASK,
|
.phy_id_mask = AT803X_PHY_ID_MASK,
|
||||||
|
.probe = at803x_probe,
|
||||||
.config_init = at803x_config_init,
|
.config_init = at803x_config_init,
|
||||||
.link_change_notify = at803x_link_change_notify,
|
.link_change_notify = at803x_link_change_notify,
|
||||||
.set_wol = at803x_set_wol,
|
.set_wol = at803x_set_wol,
|
||||||
|
@ -437,10 +736,11 @@ static struct phy_driver at803x_driver[] = {
|
||||||
.ack_interrupt = at803x_ack_interrupt,
|
.ack_interrupt = at803x_ack_interrupt,
|
||||||
.config_intr = at803x_config_intr,
|
.config_intr = at803x_config_intr,
|
||||||
}, {
|
}, {
|
||||||
/* ATHEROS 8031 */
|
/* Qualcomm Atheros AR8031/AR8033 */
|
||||||
.phy_id = ATH8031_PHY_ID,
|
.phy_id = ATH8031_PHY_ID,
|
||||||
.name = "Atheros 8031 ethernet",
|
.name = "Qualcomm Atheros AR8031/AR8033",
|
||||||
.phy_id_mask = AT803X_PHY_ID_MASK,
|
.phy_id_mask = AT803X_PHY_ID_MASK,
|
||||||
|
.probe = at803x_probe,
|
||||||
.config_init = at803x_config_init,
|
.config_init = at803x_config_init,
|
||||||
.set_wol = at803x_set_wol,
|
.set_wol = at803x_set_wol,
|
||||||
.get_wol = at803x_get_wol,
|
.get_wol = at803x_get_wol,
|
||||||
|
@ -454,8 +754,7 @@ static struct phy_driver at803x_driver[] = {
|
||||||
}, {
|
}, {
|
||||||
/* ATHEROS AR9331 */
|
/* ATHEROS AR9331 */
|
||||||
PHY_ID_MATCH_EXACT(ATH9331_PHY_ID),
|
PHY_ID_MATCH_EXACT(ATH9331_PHY_ID),
|
||||||
.name = "Atheros AR9331 built-in PHY",
|
.name = "Qualcomm Atheros AR9331 built-in PHY",
|
||||||
.config_init = at803x_config_init,
|
|
||||||
.suspend = at803x_suspend,
|
.suspend = at803x_suspend,
|
||||||
.resume = at803x_resume,
|
.resume = at803x_resume,
|
||||||
/* PHY_BASIC_FEATURES */
|
/* PHY_BASIC_FEATURES */
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Device Tree constants for the Qualcomm Atheros AR803x PHYs
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DT_BINDINGS_QCA_AR803X_H
|
||||||
|
#define _DT_BINDINGS_QCA_AR803X_H
|
||||||
|
|
||||||
|
#define AR803X_STRENGTH_FULL 0
|
||||||
|
#define AR803X_STRENGTH_HALF 1
|
||||||
|
#define AR803X_STRENGTH_QUARTER 2
|
||||||
|
|
||||||
|
#endif
|
Загрузка…
Ссылка в новой задаче