From: Liu Changjie Document the MAE0621A PHY IDs (for the -Q2C and -Q3C variants) and their optional 125 MHz CLKOUT setting. Boards which do not provide the property retain the hardware strap or bootloader configuration. Only the 125 MHz setting is exposed because it is the only setting exercised on hardware. Signed-off-by: Liu Changjie [Andre: Add PHY-ID for -Q2C variant] Signed-off-by: Andre Przywara Reviewed-by: Krzysztof Kozlowski --- .../bindings/net/maxio,mae0621a.yaml | 40 +++++++++++++++++++ .../devicetree/bindings/vendor-prefixes.yaml | 2 + 2 files changed, 42 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/maxio,mae0621a.yaml diff --git a/Documentation/devicetree/bindings/net/maxio,mae0621a.yaml b/Documentation/devicetree/bindings/net/maxio,mae0621a.yaml new file mode 100644 index 0000000000000..c4d06c6261681 --- /dev/null +++ b/Documentation/devicetree/bindings/net/maxio,mae0621a.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/maxio,mae0621a.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxio MAE0621A Ethernet PHY + +maintainers: + - Liu Changjie + +allOf: + - $ref: ethernet-phy.yaml# + +properties: + compatible: + enum: + - ethernet-phy-id7b74.4411 + - ethernet-phy-id7b74.4412 + + maxio,clk-out-frequency-hz: + description: + Selects a 125 MHz clock on the CLKOUT pin. If the property is absent, + the hardware strap or bootloader configuration is preserved. + const: 125000000 + +unevaluatedProperties: false + +examples: + - | + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethernet-phy@1 { + compatible = "ethernet-phy-id7b74.4412"; + reg = <1>; + maxio,clk-out-frequency-hz = <125000000>; + }; + }; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index ba20029693734..8ea4d421719b0 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -1035,6 +1035,8 @@ patternProperties: description: MaxBotix Inc. "^maxim,.*": description: Maxim Integrated Products + "^maxio,.*": + description: Maxio Technology (Hangzhou) Co., Ltd. "^maxlinear,.*": description: MaxLinear Inc. "^maxtor,.*": -- 2.46.4 From: Liu Changjie Add exact PHY ID matching and optional 125 MHz CLKOUT configuration for the Maxio MAE0621A Gigabit Ethernet PHY. Preserve the existing hardware configuration when the firmware property is absent. Signed-off-by: Liu Changjie Signed-off-by: Andre Przywara Reviewed-by: Andrew Lunn --- drivers/net/phy/Kconfig | 8 +++ drivers/net/phy/Makefile | 1 + drivers/net/phy/maxio.c | 103 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 drivers/net/phy/maxio.c diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index b4ef927fd4a67..eb40276113a57 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -298,6 +298,14 @@ config MARVELL_88X2222_PHY Support for the Marvell 88X2222 Dual-port Multi-speed Ethernet Transceiver. +config MAXIO_PHY + tristate "Maxio Ethernet PHYs" + help + Support for Maxio Ethernet PHYs. Currently this driver supports the + MAE0621A Gigabit Ethernet PHY. The driver optionally selects a 125 MHz + clock on the CLKOUT pin while preserving the hardware configuration on + boards which do not request it. + config MAXLINEAR_GPHY tristate "Maxlinear Ethernet PHYs" select POLYNOMIAL if HWMON diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 25c4a3c2429f7..9730b8a6fa5b0 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -72,6 +72,7 @@ obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o obj-$(CONFIG_MARVELL_PHY) += marvell.o obj-$(CONFIG_MARVELL_88Q2XXX_PHY) += marvell-88q2xxx.o obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o +obj-$(CONFIG_MAXIO_PHY) += maxio.o obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o obj-$(CONFIG_MAXLINEAR_86110_PHY) += mxl-86110.o obj-y += mediatek/ diff --git a/drivers/net/phy/maxio.c b/drivers/net/phy/maxio.c new file mode 100644 index 0000000000000..d2cb238956460 --- /dev/null +++ b/drivers/net/phy/maxio.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Driver for Maxio Ethernet PHYs. */ + +#include +#include +#include +#include + +#define MAXIO_MAE0621A_PHY_ID 0x7b744412 + +#define MAXIO_PAGE_SELECT 0x1f +#define MAXIO_MAE0621A_PHYCR2_PAGE 0xa43 +#define MAXIO_MAE0621A_PHYCR2 0x19 +#define MAXIO_MAE0621A_CLKOUT_125M BIT(11) +#define MAXIO_MAE0621A_CLKOUT_ENABLE BIT(0) + +struct maxio_priv { + bool clk_out_125m; +}; + +static int maxio_read_page(struct phy_device *phydev) +{ + return __phy_read(phydev, MAXIO_PAGE_SELECT); +} + +static int maxio_write_page(struct phy_device *phydev, int page) +{ + return __phy_write(phydev, MAXIO_PAGE_SELECT, page); +} + +static int maxio_mae0621a_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct maxio_priv *priv; + u32 frequency; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + phydev->priv = priv; + + ret = device_property_read_u32(dev, "maxio,clk-out-frequency-hz", + &frequency); + if (ret == -EINVAL) + return 0; + if (ret) + return ret; + + if (frequency != 125000000) { + phydev_err(phydev, "invalid CLKOUT frequency %u\n", frequency); + return -EINVAL; + } + + priv->clk_out_125m = true; + + return 0; +} + +static int maxio_mae0621a_config_init(struct phy_device *phydev) +{ + struct maxio_priv *priv = phydev->priv; + int ret; + + if (!priv->clk_out_125m) + return 0; + + ret = phy_modify_paged_changed(phydev, MAXIO_MAE0621A_PHYCR2_PAGE, + MAXIO_MAE0621A_PHYCR2, + MAXIO_MAE0621A_CLKOUT_ENABLE | + MAXIO_MAE0621A_CLKOUT_125M, + MAXIO_MAE0621A_CLKOUT_ENABLE | + MAXIO_MAE0621A_CLKOUT_125M); + if (ret <= 0) + return ret; + + return genphy_soft_reset(phydev); +} + +static struct phy_driver maxio_drivers[] = { + { + PHY_ID_MATCH_EXACT(MAXIO_MAE0621A_PHY_ID), + .name = "Maxio MAE0621A", + .probe = maxio_mae0621a_probe, + .config_init = maxio_mae0621a_config_init, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_page = maxio_read_page, + .write_page = maxio_write_page, + }, +}; +module_phy_driver(maxio_drivers); + +static const struct mdio_device_id __maybe_unused maxio_tbl[] = { + { PHY_ID_MATCH_EXACT(MAXIO_MAE0621A_PHY_ID) }, + { } +}; +MODULE_DEVICE_TABLE(mdio, maxio_tbl); + +MODULE_AUTHOR("Liu Changjie "); +MODULE_DESCRIPTION("Maxio Ethernet PHY driver"); +MODULE_LICENSE("GPL"); -- 2.46.4 The probe routine for the Maxio PHY returns early if the optional maxio,clk-out-frequency-hz property is not found. That prevents looking for other properties. Refactor the routine to handle the property in an if-clause, to allow more actions in the probe routine later. Signed-off-by: Andre Przywara --- drivers/net/phy/maxio.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/net/phy/maxio.c b/drivers/net/phy/maxio.c index d2cb238956460..9ba82c1cd8b13 100644 --- a/drivers/net/phy/maxio.c +++ b/drivers/net/phy/maxio.c @@ -43,18 +43,20 @@ static int maxio_mae0621a_probe(struct phy_device *phydev) ret = device_property_read_u32(dev, "maxio,clk-out-frequency-hz", &frequency); - if (ret == -EINVAL) - return 0; - if (ret) - return ret; - - if (frequency != 125000000) { - phydev_err(phydev, "invalid CLKOUT frequency %u\n", frequency); - return -EINVAL; + if (ret) { + /* the property is optional, so ignore -EINVAL */ + if (ret != -EINVAL) + return ret; + } else { + if (frequency != 125000000) { + phydev_err(phydev, "invalid CLKOUT frequency %u\n", + frequency); + return -EINVAL; + } + + priv->clk_out_125m = true; } - priv->clk_out_125m = true; - return 0; } -- 2.46.4 The generic PHY DT binding features a clocks property, which describes the clock input to the PHY. Typically this is a crystal oscillator, so it works without software interaction. But some boards want to save some pennies on that part, and let a clock fanout pin from the SoC provide this clock signal. In this case the PHY probe routine needs to enable this clock explicitly. Look for a "clocks" property inside the PHY node and enable that clock, if one is provided. This allows boards with a SoC-driven PHY clock to use the PHY. Please note that without the clock enabled, the PHY will not be detected on the MDIO bus, so the PHY-ID needs to be explicitly named in the PHY compatible string: compatible = "ethernet-phy-id7b74.4411"; Signed-off-by: Andre Przywara --- drivers/net/phy/maxio.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/phy/maxio.c b/drivers/net/phy/maxio.c index 9ba82c1cd8b13..266be95b949a8 100644 --- a/drivers/net/phy/maxio.c +++ b/drivers/net/phy/maxio.c @@ -2,6 +2,7 @@ /* Driver for Maxio Ethernet PHYs. */ #include +#include #include #include #include @@ -15,6 +16,7 @@ #define MAXIO_MAE0621A_CLKOUT_ENABLE BIT(0) struct maxio_priv { + struct clk *clk; bool clk_out_125m; }; @@ -57,6 +59,11 @@ static int maxio_mae0621a_probe(struct phy_device *phydev) priv->clk_out_125m = true; } + /* PHY clock from the generic PHY binding */ + priv->clk = devm_clk_get_optional_enabled(&phydev->mdio.dev, NULL); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + return 0; } -- 2.46.4 Currently the maxio Ethernet PHY driver expects a Maxio MAE0621A-Q3C PHY matching exactly the one ID provided: 0x7b744412. There exist an earlier variant of the PHY, still used on some devices, its label differs by using the -Q2C suffix, and its PHY ID is 0x7b744411. Some vendor drivers floating around in the web suggest they are somewhat different, although for now this driver does not deal with any of those registers, and the 125M clock switch is identical between the two. Nevertheless prepare for future driver divergence by describing two drivers, although using the same functions for now. Signed-off-by: Andre Przywara --- drivers/net/phy/maxio.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/net/phy/maxio.c b/drivers/net/phy/maxio.c index 266be95b949a8..8c33c8433b127 100644 --- a/drivers/net/phy/maxio.c +++ b/drivers/net/phy/maxio.c @@ -7,7 +7,8 @@ #include #include -#define MAXIO_MAE0621A_PHY_ID 0x7b744412 +#define MAXIO_MAE0621A_Q2C_PHY_ID 0x7b744411 +#define MAXIO_MAE0621A_Q3C_PHY_ID 0x7b744412 #define MAXIO_PAGE_SELECT 0x1f #define MAXIO_MAE0621A_PHYCR2_PAGE 0xa43 @@ -89,8 +90,18 @@ static int maxio_mae0621a_config_init(struct phy_device *phydev) static struct phy_driver maxio_drivers[] = { { - PHY_ID_MATCH_EXACT(MAXIO_MAE0621A_PHY_ID), - .name = "Maxio MAE0621A", + PHY_ID_MATCH_EXACT(MAXIO_MAE0621A_Q2C_PHY_ID), + .name = "Maxio MAE0621A-Q2C", + .probe = maxio_mae0621a_probe, + .config_init = maxio_mae0621a_config_init, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_page = maxio_read_page, + .write_page = maxio_write_page, + }, + { + PHY_ID_MATCH_EXACT(MAXIO_MAE0621A_Q3C_PHY_ID), + .name = "Maxio MAE0621A-Q3C", .probe = maxio_mae0621a_probe, .config_init = maxio_mae0621a_config_init, .suspend = genphy_suspend, @@ -102,7 +113,8 @@ static struct phy_driver maxio_drivers[] = { module_phy_driver(maxio_drivers); static const struct mdio_device_id __maybe_unused maxio_tbl[] = { - { PHY_ID_MATCH_EXACT(MAXIO_MAE0621A_PHY_ID) }, + { PHY_ID_MATCH_EXACT(MAXIO_MAE0621A_Q2C_PHY_ID) }, + { PHY_ID_MATCH_EXACT(MAXIO_MAE0621A_Q3C_PHY_ID) }, { } }; MODULE_DEVICE_TABLE(mdio, maxio_tbl); -- 2.46.4