From d93bb3feeaf2715a328610f6cc316d295aa8ba85 Mon Sep 17 00:00:00 2001 From: Tianling Shen Date: Mon, 6 Feb 2023 06:04:11 +0800 Subject: [PATCH] rockchip: revert motorcomm driver Signed-off-by: Tianling Shen --- .../src/arch/arm/dts/rk3328-nanopi-r2c.dts | 5 - .../arm/dts/rk3328-orangepi-r1-plus-lts.dts | 5 - .../boot/dts/rockchip/rk3328-nanopi-r2c.dts | 5 - .../rockchip/rk3328-orangepi-r1-plus-lts.dts | 5 - .../files/drivers/net/phy/motorcomm.c | 420 ++++ .../files/include/linux/motorcomm_phy.h | 73 + ....0-net-mii-add-mii_bmcr_encode_fixed.patch | 55 - ...or-Motorcomm-yt8521-gigabit-ethernet.patch | 1724 ----------------- ...fix-yt8521-duplicated-argument-to-or.patch | 49 - ...net-phy-add-Motorcomm-YT8531S-phy-id.patch | 140 -- ...fix-the-spelling-problem-of-Sentinel.patch | 26 - ...nge-the-phy-id-of-yt8521-and-yt8531s.patch | 29 - ...-for-Motorcomm-yt8521-yt8531-gigabit.patch | 107 - ...support-for-Motorcomm-yt8521-gigabit.patch | 343 ---- ...upport-for-Motorcomm-yt8531s-gigabit.patch | 100 - ...or-Motorcomm-yt8531-gigabit-ethernet.patch | 302 --- 16 files changed, 493 insertions(+), 2895 deletions(-) create mode 100644 target/linux/rockchip/files/drivers/net/phy/motorcomm.c create mode 100644 target/linux/rockchip/files/include/linux/motorcomm_phy.h delete mode 100644 target/linux/rockchip/patches-5.15/011-01-v6.0-net-mii-add-mii_bmcr_encode_fixed.patch delete mode 100644 target/linux/rockchip/patches-5.15/011-02-v6.2-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch delete mode 100644 target/linux/rockchip/patches-5.15/011-03-v6.2-net-phy-fix-yt8521-duplicated-argument-to-or.patch delete mode 100644 target/linux/rockchip/patches-5.15/011-04-v6.2-net-phy-add-Motorcomm-YT8531S-phy-id.patch delete mode 100644 target/linux/rockchip/patches-5.15/011-05-v6.3-net-phy-fix-the-spelling-problem-of-Sentinel.patch delete mode 100644 target/linux/rockchip/patches-5.15/011-06-v6.3-net-phy-motorcomm-change-the-phy-id-of-yt8521-and-yt8531s.patch delete mode 100644 target/linux/rockchip/patches-5.15/011-07-v6.3-net-phy-Add-BIT-macro-for-Motorcomm-yt8521-yt8531-gigabit.patch delete mode 100644 target/linux/rockchip/patches-5.15/011-08-v6.3-net-phy-Add-dts-support-for-Motorcomm-yt8521-gigabit.patch delete mode 100644 target/linux/rockchip/patches-5.15/011-09-v6.3-net-phy-Add-dts-support-for-Motorcomm-yt8531s-gigabit.patch delete mode 100644 target/linux/rockchip/patches-5.15/011-10-v6.3-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch diff --git a/package/boot/uboot-rockchip/src/arch/arm/dts/rk3328-nanopi-r2c.dts b/package/boot/uboot-rockchip/src/arch/arm/dts/rk3328-nanopi-r2c.dts index 9daca33a29..e12da77a25 100644 --- a/package/boot/uboot-rockchip/src/arch/arm/dts/rk3328-nanopi-r2c.dts +++ b/package/boot/uboot-rockchip/src/arch/arm/dts/rk3328-nanopi-r2c.dts @@ -31,11 +31,6 @@ compatible = "ethernet-phy-id0000.011a", "ethernet-phy-ieee802.3-c22"; reg = <3>; - - motorcomm,clk-out-frequency-hz = <125000000>; - motorcomm,keep-pll-enabled; - motorcomm,auto-sleep-disabled; - pinctrl-0 = <ð_phy_reset_pin>; pinctrl-names = "default"; reset-assert-us = <10000>; diff --git a/package/boot/uboot-rockchip/src/arch/arm/dts/rk3328-orangepi-r1-plus-lts.dts b/package/boot/uboot-rockchip/src/arch/arm/dts/rk3328-orangepi-r1-plus-lts.dts index f7a0ae542d..8b4b64ae18 100644 --- a/package/boot/uboot-rockchip/src/arch/arm/dts/rk3328-orangepi-r1-plus-lts.dts +++ b/package/boot/uboot-rockchip/src/arch/arm/dts/rk3328-orangepi-r1-plus-lts.dts @@ -27,11 +27,6 @@ compatible = "ethernet-phy-id4f51.e91b", "ethernet-phy-ieee802.3-c22"; reg = <0>; - - motorcomm,clk-out-frequency-hz = <125000000>; - motorcomm,keep-pll-enabled; - motorcomm,auto-sleep-disabled; - pinctrl-0 = <ð_phy_reset_pin>; pinctrl-names = "default"; reset-assert-us = <15000>; diff --git a/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dts b/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dts index 5c1b3568ce..9a58824abb 100644 --- a/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dts +++ b/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dts @@ -31,11 +31,6 @@ compatible = "ethernet-phy-id0000.011a", "ethernet-phy-ieee802.3-c22"; reg = <3>; - - motorcomm,clk-out-frequency-hz = <125000000>; - motorcomm,keep-pll-enabled; - motorcomm,auto-sleep-disabled; - pinctrl-0 = <ð_phy_reset_pin>; pinctrl-names = "default"; reset-assert-us = <10000>; diff --git a/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts b/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts index 78e0802bbe..e66b8bde5c 100644 --- a/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts +++ b/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts @@ -42,11 +42,6 @@ compatible = "ethernet-phy-id4f51.e91b", "ethernet-phy-ieee802.3-c22"; reg = <0>; - - motorcomm,clk-out-frequency-hz = <125000000>; - motorcomm,keep-pll-enabled; - motorcomm,auto-sleep-disabled; - pinctrl-0 = <ð_phy_reset_pin>; pinctrl-names = "default"; reset-assert-us = <15000>; diff --git a/target/linux/rockchip/files/drivers/net/phy/motorcomm.c b/target/linux/rockchip/files/drivers/net/phy/motorcomm.c new file mode 100644 index 0000000000..475a53e179 --- /dev/null +++ b/target/linux/rockchip/files/drivers/net/phy/motorcomm.c @@ -0,0 +1,420 @@ +/* + * drivers/net/phy/motorcomm.c + * + * Driver for Motorcomm PHYs + * + * Author: Leilei Zhao + * + * Copyright (c) 2019 Motorcomm, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Support : Motorcomm Phys: + * Giga phys: yt8511, yt8521 + * 100/10 Phys : yt8512, yt8512b, yt8510 + * Automotive 100Mb Phys : yt8010 + * Automotive 100/10 hyper range Phys: yt8510 + */ + +#include +#include +#include +#include +#include +#include + +static int ytphy_read_ext(struct phy_device *phydev, u32 regnum) +{ + int ret; + int val; + + ret = phy_write(phydev, REG_DEBUG_ADDR_OFFSET, regnum); + if (ret < 0) + return ret; + + val = phy_read(phydev, REG_DEBUG_DATA); + + return val; +} + +static int ytphy_write_ext(struct phy_device *phydev, u32 regnum, u16 val) +{ + int ret; + + ret = phy_write(phydev, REG_DEBUG_ADDR_OFFSET, regnum); + if (ret < 0) + return ret; + + ret = phy_write(phydev, REG_DEBUG_DATA, val); + + return ret; +} + +static int yt8010_config_aneg(struct phy_device *phydev) +{ + phydev->speed = SPEED_100; + return 0; +} + +static int yt8511_config_init(struct phy_device *phydev) +{ + int ret; + int val; + + /* disable auto sleep */ + val = ytphy_read_ext(phydev, YT8511_EXTREG_SLEEP_CONTROL1); + if (val < 0) + return val; + + val &= (~BIT(YT8511_EN_SLEEP_SW_BIT)); + ret = ytphy_write_ext(phydev, YT8511_EXTREG_SLEEP_CONTROL1, val); + if (ret < 0) + return ret; + + /* output SyncE clock (125mhz) even link is down */ + ret = ytphy_write_ext(phydev, 0xa012, 0xd0); + if (ret < 0) + return ret; + + /* enable RXC clock when no wire plug */ + val = ytphy_read_ext(phydev, 0xc); + if (val < 0) + return val; + + /* ext reg 0xc.b[2:1] + 00-----25M from pll; + 01---- 25M from xtl;(default) + 10-----62.5M from pll; + 11----125M from pll(here set to this value) + */ + val |= (3 << 1); + ret = ytphy_write_ext(phydev, 0xc, val); + if (ret < 0) + return ret; + + /* LED0: Unused/Off, LED1: Link, LED2: Activity, 8Hz */ + ytphy_write_ext(phydev, 0xa00b, 0xe004); + ytphy_write_ext(phydev, 0xa00c, 0); + ytphy_write_ext(phydev, 0xa00d, 0x2600); + ytphy_write_ext(phydev, 0xa00e, 0x0070); + ytphy_write_ext(phydev, 0xa00f, 0x000a); + + return 0; +} + +static int yt8512_clk_init(struct phy_device *phydev) +{ + int ret; + int val; + + val = ytphy_read_ext(phydev, YT8512_EXTREG_AFE_PLL); + if (val < 0) + return val; + + val |= YT8512_CONFIG_PLL_REFCLK_SEL_EN; + + ret = ytphy_write_ext(phydev, YT8512_EXTREG_AFE_PLL, val); + if (ret < 0) + return ret; + + val = ytphy_read_ext(phydev, YT8512_EXTREG_EXTEND_COMBO); + if (val < 0) + return val; + + val |= YT8512_CONTROL1_RMII_EN; + + ret = ytphy_write_ext(phydev, YT8512_EXTREG_EXTEND_COMBO, val); + if (ret < 0) + return ret; + + val = phy_read(phydev, MII_BMCR); + if (val < 0) + return val; + + val |= YT_SOFTWARE_RESET; + ret = phy_write(phydev, MII_BMCR, val); + + return ret; +} + +static int yt8512_led_init(struct phy_device *phydev) +{ + int ret; + int val; + int mask; + + val = ytphy_read_ext(phydev, YT8512_EXTREG_LED0); + if (val < 0) + return val; + + val |= YT8512_LED0_ACT_BLK_IND; + + mask = YT8512_LED0_DIS_LED_AN_TRY | YT8512_LED0_BT_BLK_EN | + YT8512_LED0_HT_BLK_EN | YT8512_LED0_COL_BLK_EN | + YT8512_LED0_BT_ON_EN; + val &= ~mask; + + ret = ytphy_write_ext(phydev, YT8512_EXTREG_LED0, val); + if (ret < 0) + return ret; + + val = ytphy_read_ext(phydev, YT8512_EXTREG_LED1); + if (val < 0) + return val; + + val |= YT8512_LED1_BT_ON_EN; + + mask = YT8512_LED1_TXACT_BLK_EN | YT8512_LED1_RXACT_BLK_EN; + val &= ~mask; + + ret = ytphy_write_ext(phydev, YT8512_LED1_BT_ON_EN, val); + + return ret; +} + +static int yt8512_config_init(struct phy_device *phydev) +{ + int ret; + int val; + + ret = yt8512_clk_init(phydev); + if (ret < 0) + return ret; + + ret = yt8512_led_init(phydev); + + /* disable auto sleep */ + val = ytphy_read_ext(phydev, YT8512_EXTREG_SLEEP_CONTROL1); + if (val < 0) + return val; + + val &= (~BIT(YT8512_EN_SLEEP_SW_BIT)); + + ret = ytphy_write_ext(phydev, YT8512_EXTREG_SLEEP_CONTROL1, val); + if (ret < 0) + return ret; + + return ret; +} + +static int yt8512_read_status(struct phy_device *phydev) +{ + int ret; + int val; + int speed, speed_mode, duplex; + + ret = genphy_update_link(phydev); + if (ret) + return ret; + + val = phy_read(phydev, REG_PHY_SPEC_STATUS); + if (val < 0) + return val; + + duplex = (val & YT8512_DUPLEX) >> YT8512_DUPLEX_BIT; + speed_mode = (val & YT8512_SPEED_MODE) >> YT8512_SPEED_MODE_BIT; + switch (speed_mode) { + case 0: + speed = SPEED_10; + break; + case 1: + speed = SPEED_100; + break; + case 2: + case 3: + default: + speed = SPEED_UNKNOWN; + break; + } + + phydev->speed = speed; + phydev->duplex = duplex; + + return 0; +} + +static int yt8521_config_init(struct phy_device *phydev) +{ + int ret; + int val; + + /* disable auto sleep */ + val = ytphy_read_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1); + if (val < 0) + return val; + + val &= (~BIT(YT8521_EN_SLEEP_SW_BIT)); + ret = ytphy_write_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1, val); + if (ret < 0) + return ret; + + /* switch to access UTP */ + ret = ytphy_write_ext(phydev, 0xa000, 0); + if (ret < 0) + return ret; + + /* enable RXC clock when no wire plug */ + val = ytphy_read_ext(phydev, 0xc); + if (val < 0) + return val; + + val &= ~(1 << 12); + ret = ytphy_write_ext(phydev, 0xc, val); + if (ret < 0) + return ret; + + /* output SyncE clock (125mhz) even link is down */ + ret = ytphy_write_ext(phydev, 0xa012, 0x38); + if (ret < 0) + return ret; + + /* disable rgmii clk 2ns delay */ + val = ytphy_read_ext(phydev, 0xa001); + if (val < 0) + return val; + + val &= ~(1 << 8); + ret = ytphy_write_ext(phydev, 0xa001, val); + if (ret < 0) + return ret; + + /* setup delay */ + val = (1 << 10) | (0xf << 4) | 5; + ret = ytphy_write_ext(phydev, 0xa003, val); + if (ret < 0) + return ret; + + /* LED0: Unused/Off, LED1: Link, LED2: Activity, 8Hz */ + ytphy_write_ext(phydev, 0xa00b, 0xe004); + ytphy_write_ext(phydev, 0xa00c, 0); + ytphy_write_ext(phydev, 0xa00d, 0x2600); + ytphy_write_ext(phydev, 0xa00e, 0x0070); + ytphy_write_ext(phydev, 0xa00f, 0x000a); + + return 0; +} + +static int yt8521_config_intr(struct phy_device *phydev) +{ + int val; + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) + val = BIT(14) | BIT(13) | BIT(11) | BIT(10); + else + val = 0; + + return phy_write(phydev, REG_INT_MASK, val); +} + +static irqreturn_t yt8521_ack_interrupt(struct phy_device *phydev) +{ + int val; + + val = phy_read(phydev, REG_INT_STATUS); + phydev_dbg(phydev, "intr status 0x04%x\n", val); + + if (val < 0) { + phy_error(phydev); + return IRQ_NONE; + } + + phy_trigger_machine(phydev); + return IRQ_HANDLED; +} + +static struct phy_driver ytphy_drvs[] = { + { + .phy_id = PHY_ID_YT8010, + .name = "YT8010 Automotive Ethernet", + .phy_id_mask = MOTORCOMM_PHY_ID_MASK, + .features = PHY_BASIC_FEATURES, + .config_aneg = yt8010_config_aneg, + .read_status = genphy_read_status, + }, { + .phy_id = PHY_ID_YT8510, + .name = "YT8510 100/10Mb Ethernet", + .phy_id_mask = MOTORCOMM_PHY_ID_MASK, + .features = PHY_BASIC_FEATURES, + .read_status = genphy_read_status, + }, { + .phy_id = PHY_ID_YT8511, + .name = "YT8511 Gigabit Ethernet", + .phy_id_mask = MOTORCOMM_PHY_ID_MASK, + .features = PHY_GBIT_FEATURES, + .read_status = genphy_read_status, + .suspend = genphy_suspend, + .resume = genphy_resume, + }, { + .phy_id = PHY_ID_YT8512, + .name = "YT8512 Ethernet", + .phy_id_mask = MOTORCOMM_PHY_ID_MASK, + .features = PHY_BASIC_FEATURES, + .config_init = yt8512_config_init, + .read_status = yt8512_read_status, + .suspend = genphy_suspend, + .resume = genphy_resume, + }, { + .phy_id = PHY_ID_YT8512B, + .name = "YT8512B Ethernet", + .phy_id_mask = MOTORCOMM_PHY_ID_MASK, + .features = PHY_BASIC_FEATURES, + .config_init = yt8512_config_init, + .read_status = yt8512_read_status, + .suspend = genphy_suspend, + .resume = genphy_resume, + }, { + .phy_id = PHY_ID_YT8521, + .name = "YT8521 Ethernet", + .phy_id_mask = MOTORCOMM_PHY_ID_MASK, + /* PHY_GBIT_FEATURES */ + .config_init = yt8521_config_init, + .handle_interrupt = yt8521_ack_interrupt, + .config_intr = yt8521_config_intr, + .suspend = genphy_suspend, + .resume = genphy_resume, + }, { + /* same as 8521 */ + .phy_id = PHY_ID_YT8531S, + .name = "YT8531S Ethernet", + .phy_id_mask = MOTORCOMM_PHY_ID_MASK, + /* PHY_GBIT_FEATURES */ + .config_init = yt8521_config_init, + .handle_interrupt = yt8521_ack_interrupt, + .config_intr = yt8521_config_intr, + .suspend = genphy_suspend, + .resume = genphy_resume, + }, { + /* same as 8511 */ + .phy_id = PHY_ID_YT8531, + .name = "YT8531 Gigabit Ethernet", + .phy_id_mask = MOTORCOMM_PHY_ID_MASK, + .features = PHY_GBIT_FEATURES, + .config_init = yt8511_config_init, + .read_status = genphy_read_status, + .suspend = genphy_suspend, + .resume = genphy_resume, + }, +}; + +module_phy_driver(ytphy_drvs); + +MODULE_DESCRIPTION("Motorcomm PHY driver"); +MODULE_AUTHOR("Leilei Zhao"); +MODULE_LICENSE("GPL"); + +static struct mdio_device_id __maybe_unused motorcomm_tbl[] = { + { PHY_ID_YT8010, MOTORCOMM_PHY_ID_MASK }, + { PHY_ID_YT8510, MOTORCOMM_PHY_ID_MASK }, + { PHY_ID_YT8511, MOTORCOMM_PHY_ID_MASK }, + { PHY_ID_YT8512, MOTORCOMM_PHY_ID_MASK }, + { PHY_ID_YT8512B, MOTORCOMM_PHY_ID_MASK }, + { PHY_ID_YT8521, MOTORCOMM_PHY_ID_MASK }, + { PHY_ID_YT8531S, MOTORCOMM_PHY_ID_8531_MASK }, + { PHY_ID_YT8531, MOTORCOMM_PHY_ID_8531_MASK }, + { } +}; + +MODULE_DEVICE_TABLE(mdio, motorcomm_tbl); diff --git a/target/linux/rockchip/files/include/linux/motorcomm_phy.h b/target/linux/rockchip/files/include/linux/motorcomm_phy.h new file mode 100644 index 0000000000..4ef801c81f --- /dev/null +++ b/target/linux/rockchip/files/include/linux/motorcomm_phy.h @@ -0,0 +1,73 @@ +/* + * include/linux/motorcomm_phy.h + * + * Motorcomm PHY IDs + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef _MOTORCOMM_PHY_H +#define _MOTORCOMM_PHY_H + +#define MOTORCOMM_PHY_ID_MASK 0x00000fff +#define MOTORCOMM_PHY_ID_8531_MASK 0xffffffff + +#define PHY_ID_YT8010 0x00000309 +#define PHY_ID_YT8510 0x00000109 +#define PHY_ID_YT8511 0x0000010a +#define PHY_ID_YT8512 0x00000118 +#define PHY_ID_YT8512B 0x00000128 +#define PHY_ID_YT8521 0x0000011a +#define PHY_ID_YT8531S 0x4f51e91a +#define PHY_ID_YT8531 0x4f51e91b + +#define REG_PHY_SPEC_STATUS 0x11 +#define REG_INT_MASK 0x12 +#define REG_INT_STATUS 0x13 +#define REG_DEBUG_ADDR_OFFSET 0x1e +#define REG_DEBUG_DATA 0x1f + +#define YT8511_EXTREG_SLEEP_CONTROL1 0x27 +#define YT8511_EN_SLEEP_SW_BIT 15 + +#define YT8512_EXTREG_AFE_PLL 0x50 +#define YT8512_EXTREG_EXTEND_COMBO 0x4000 +#define YT8512_EXTREG_LED0 0x40c0 +#define YT8512_EXTREG_LED1 0x40c3 + +#define YT8512_EXTREG_SLEEP_CONTROL1 0x2027 + +#define YT_SOFTWARE_RESET 0x8000 + +#define YT8512_CONFIG_PLL_REFCLK_SEL_EN 0x0040 +#define YT8512_CONTROL1_RMII_EN 0x0001 +#define YT8512_LED0_ACT_BLK_IND 0x1000 +#define YT8512_LED0_DIS_LED_AN_TRY 0x0001 +#define YT8512_LED0_BT_BLK_EN 0x0002 +#define YT8512_LED0_HT_BLK_EN 0x0004 +#define YT8512_LED0_COL_BLK_EN 0x0008 +#define YT8512_LED0_BT_ON_EN 0x0010 +#define YT8512_LED1_BT_ON_EN 0x0010 +#define YT8512_LED1_TXACT_BLK_EN 0x0100 +#define YT8512_LED1_RXACT_BLK_EN 0x0200 +#define YT8512_SPEED_MODE 0xc000 +#define YT8512_DUPLEX 0x2000 + +#define YT8512_SPEED_MODE_BIT 14 +#define YT8512_DUPLEX_BIT 13 +#define YT8512_EN_SLEEP_SW_BIT 15 + +#define YT8521_EXTREG_SLEEP_CONTROL1 0x27 +#define YT8521_EN_SLEEP_SW_BIT 15 + +#define YT8521_SPEED_MODE 0xc000 +#define YT8521_DUPLEX 0x2000 +#define YT8521_SPEED_MODE_BIT 14 +#define YT8521_DUPLEX_BIT 13 +#define YT8521_LINK_STATUS_BIT 10 + +#endif /* _MOTORCOMM_PHY_H */ diff --git a/target/linux/rockchip/patches-5.15/011-01-v6.0-net-mii-add-mii_bmcr_encode_fixed.patch b/target/linux/rockchip/patches-5.15/011-01-v6.0-net-mii-add-mii_bmcr_encode_fixed.patch deleted file mode 100644 index 87d7ff6154..0000000000 --- a/target/linux/rockchip/patches-5.15/011-01-v6.0-net-mii-add-mii_bmcr_encode_fixed.patch +++ /dev/null @@ -1,55 +0,0 @@ -From bdb6cfe7512f7a214815a3092f0be50963dcacbc Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Sat, 18 Jun 2022 11:28:32 +0100 -Subject: [PATCH] net: mii: add mii_bmcr_encode_fixed() - -Add a function to encode a fixed speed/duplex to a BMCR value. - -Signed-off-by: Russell King (Oracle) -Signed-off-by: David S. Miller ---- - include/linux/mii.h | 35 +++++++++++++++++++++++++++++++++++ - 1 file changed, 35 insertions(+) - ---- a/include/linux/mii.h -+++ b/include/linux/mii.h -@@ -595,4 +595,39 @@ static inline u8 mii_resolve_flowctrl_fd - return cap; - } - -+/** -+ * mii_bmcr_encode_fixed - encode fixed speed/duplex settings to a BMCR value -+ * @speed: a SPEED_* value -+ * @duplex: a DUPLEX_* value -+ * -+ * Encode the speed and duplex to a BMCR value. 2500, 1000, 100 and 10 Mbps are -+ * supported. 2500Mbps is encoded to 1000Mbps. Other speeds are encoded as 10 -+ * Mbps. Unknown duplex values are encoded to half-duplex. -+ */ -+static inline u16 mii_bmcr_encode_fixed(int speed, int duplex) -+{ -+ u16 bmcr; -+ -+ switch (speed) { -+ case SPEED_2500: -+ case SPEED_1000: -+ bmcr = BMCR_SPEED1000; -+ break; -+ -+ case SPEED_100: -+ bmcr = BMCR_SPEED100; -+ break; -+ -+ case SPEED_10: -+ default: -+ bmcr = BMCR_SPEED10; -+ break; -+ } -+ -+ if (duplex == DUPLEX_FULL) -+ bmcr |= BMCR_FULLDPLX; -+ -+ return bmcr; -+} -+ - #endif /* __LINUX_MII_H__ */ diff --git a/target/linux/rockchip/patches-5.15/011-02-v6.2-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch b/target/linux/rockchip/patches-5.15/011-02-v6.2-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch deleted file mode 100644 index a9fe17376f..0000000000 --- a/target/linux/rockchip/patches-5.15/011-02-v6.2-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch +++ /dev/null @@ -1,1724 +0,0 @@ -From 70479a40954cf353e87a486997a3477108c75aa9 Mon Sep 17 00:00:00 2001 -From: Frank -Date: Fri, 28 Oct 2022 17:26:21 +0800 -Subject: [PATCH] net: phy: Add driver for Motorcomm yt8521 gigabit ethernet - phy - -Add a driver for the motorcomm yt8521 gigabit ethernet phy. We have verified - the driver on StarFive VisionFive development board, which is developed by - Shanghai StarFive Technology Co., Ltd.. On the board, yt8521 gigabit ethernet - phy works in utp mode, RGMII interface, supports 1000M/100M/10M speeds, and - wol(magic package). - -Signed-off-by: Frank -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - MAINTAINERS | 1 + - drivers/net/phy/Kconfig | 2 +- - drivers/net/phy/motorcomm.c | 1635 ++++++++++++++++++++++++++++++++++- - 3 files changed, 1635 insertions(+), 3 deletions(-) - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -12697,6 +12697,7 @@ F: include/uapi/linux/meye.h - - MOTORCOMM PHY DRIVER - M: Peter Geis -+M: Frank - L: netdev@vger.kernel.org - S: Maintained - F: drivers/net/phy/motorcomm.c ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -319,7 +319,7 @@ config MOTORCOMM_PHY - tristate "Motorcomm PHYs" - help - Enables support for Motorcomm network PHYs. -- Currently supports the YT8511 gigabit PHY. -+ Currently supports the YT8511, YT8521 Gigabit Ethernet PHYs. - - config NATIONAL_PHY - tristate "National Semiconductor PHYs" ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -1,15 +1,106 @@ - // SPDX-License-Identifier: GPL-2.0+ - /* -- * Driver for Motorcomm PHYs -+ * Motorcomm 8511/8521 PHY driver. - * - * Author: Peter Geis -+ * Author: Frank - */ - -+#include - #include - #include - #include - - #define PHY_ID_YT8511 0x0000010a -+#define PHY_ID_YT8521 0x0000011A -+ -+/* YT8521 Register Overview -+ * UTP Register space | FIBER Register space -+ * ------------------------------------------------------------ -+ * | UTP MII | FIBER MII | -+ * | UTP MMD | | -+ * | UTP Extended | FIBER Extended | -+ * ------------------------------------------------------------ -+ * | Common Extended | -+ * ------------------------------------------------------------ -+ */ -+ -+/* 0x10 ~ 0x15 , 0x1E and 0x1F are common MII registers of yt phy */ -+ -+/* Specific Function Control Register */ -+#define YTPHY_SPECIFIC_FUNCTION_CONTROL_REG 0x10 -+ -+/* 2b00 Manual MDI configuration -+ * 2b01 Manual MDIX configuration -+ * 2b10 Reserved -+ * 2b11 Enable automatic crossover for all modes *default* -+ */ -+#define YTPHY_SFCR_MDI_CROSSOVER_MODE_MASK (BIT(6) | BIT(5)) -+#define YTPHY_SFCR_CROSSOVER_EN BIT(3) -+#define YTPHY_SFCR_SQE_TEST_EN BIT(2) -+#define YTPHY_SFCR_POLARITY_REVERSAL_EN BIT(1) -+#define YTPHY_SFCR_JABBER_DIS BIT(0) -+ -+/* Specific Status Register */ -+#define YTPHY_SPECIFIC_STATUS_REG 0x11 -+#define YTPHY_SSR_SPEED_MODE_OFFSET 14 -+ -+#define YTPHY_SSR_SPEED_MODE_MASK (BIT(15) | BIT(14)) -+#define YTPHY_SSR_SPEED_10M 0x0 -+#define YTPHY_SSR_SPEED_100M 0x1 -+#define YTPHY_SSR_SPEED_1000M 0x2 -+#define YTPHY_SSR_DUPLEX_OFFSET 13 -+#define YTPHY_SSR_DUPLEX BIT(13) -+#define YTPHY_SSR_PAGE_RECEIVED BIT(12) -+#define YTPHY_SSR_SPEED_DUPLEX_RESOLVED BIT(11) -+#define YTPHY_SSR_LINK BIT(10) -+#define YTPHY_SSR_MDIX_CROSSOVER BIT(6) -+#define YTPHY_SSR_DOWNGRADE BIT(5) -+#define YTPHY_SSR_TRANSMIT_PAUSE BIT(3) -+#define YTPHY_SSR_RECEIVE_PAUSE BIT(2) -+#define YTPHY_SSR_POLARITY BIT(1) -+#define YTPHY_SSR_JABBER BIT(0) -+ -+/* Interrupt enable Register */ -+#define YTPHY_INTERRUPT_ENABLE_REG 0x12 -+#define YTPHY_IER_WOL BIT(6) -+ -+/* Interrupt Status Register */ -+#define YTPHY_INTERRUPT_STATUS_REG 0x13 -+#define YTPHY_ISR_AUTONEG_ERR BIT(15) -+#define YTPHY_ISR_SPEED_CHANGED BIT(14) -+#define YTPHY_ISR_DUPLEX_CHANGED BIT(13) -+#define YTPHY_ISR_PAGE_RECEIVED BIT(12) -+#define YTPHY_ISR_LINK_FAILED BIT(11) -+#define YTPHY_ISR_LINK_SUCCESSED BIT(10) -+#define YTPHY_ISR_WOL BIT(6) -+#define YTPHY_ISR_WIRESPEED_DOWNGRADE BIT(5) -+#define YTPHY_ISR_SERDES_LINK_FAILED BIT(3) -+#define YTPHY_ISR_SERDES_LINK_SUCCESSED BIT(2) -+#define YTPHY_ISR_POLARITY_CHANGED BIT(1) -+#define YTPHY_ISR_JABBER_HAPPENED BIT(0) -+ -+/* Speed Auto Downgrade Control Register */ -+#define YTPHY_SPEED_AUTO_DOWNGRADE_CONTROL_REG 0x14 -+#define YTPHY_SADCR_SPEED_DOWNGRADE_EN BIT(5) -+ -+/* If these bits are set to 3, the PHY attempts five times ( 3(set value) + -+ * additional 2) before downgrading, default 0x3 -+ */ -+#define YTPHY_SADCR_SPEED_RETRY_LIMIT (0x3 << 2) -+ -+/* Rx Error Counter Register */ -+#define YTPHY_RX_ERROR_COUNTER_REG 0x15 -+ -+/* Extended Register's Address Offset Register */ -+#define YTPHY_PAGE_SELECT 0x1E -+ -+/* Extended Register's Data Register */ -+#define YTPHY_PAGE_DATA 0x1F -+ -+/* FIBER Auto-Negotiation link partner ability */ -+#define YTPHY_FLPA_PAUSE (0x3 << 7) -+#define YTPHY_FLPA_ASYM_PAUSE (0x2 << 7) - - #define YT8511_PAGE_SELECT 0x1e - #define YT8511_PAGE 0x1f -@@ -38,6 +129,352 @@ - #define YT8511_DELAY_FE_TX_EN (0xf << 12) - #define YT8511_DELAY_FE_TX_DIS (0x2 << 12) - -+/* Extended register is different from MMD Register and MII Register. -+ * We can use ytphy_read_ext/ytphy_write_ext/ytphy_modify_ext function to -+ * operate extended register. -+ * Extended Register start -+ */ -+ -+/* Phy gmii clock gating Register */ -+#define YT8521_CLOCK_GATING_REG 0xC -+#define YT8521_CGR_RX_CLK_EN BIT(12) -+ -+#define YT8521_EXTREG_SLEEP_CONTROL1_REG 0x27 -+#define YT8521_ESC1R_SLEEP_SW BIT(15) -+#define YT8521_ESC1R_PLLON_SLP BIT(14) -+ -+/* Phy fiber Link timer cfg2 Register */ -+#define YT8521_LINK_TIMER_CFG2_REG 0xA5 -+#define YT8521_LTCR_EN_AUTOSEN BIT(15) -+ -+/* 0xA000, 0xA001, 0xA003 ,and 0xA006 ~ 0xA00A are common ext registers -+ * of yt8521 phy. There is no need to switch reg space when operating these -+ * registers. -+ */ -+ -+#define YT8521_REG_SPACE_SELECT_REG 0xA000 -+#define YT8521_RSSR_SPACE_MASK BIT(1) -+#define YT8521_RSSR_FIBER_SPACE (0x1 << 1) -+#define YT8521_RSSR_UTP_SPACE (0x0 << 1) -+#define YT8521_RSSR_TO_BE_ARBITRATED (0xFF) -+ -+#define YT8521_CHIP_CONFIG_REG 0xA001 -+#define YT8521_CCR_SW_RST BIT(15) -+ -+#define YT8521_CCR_MODE_SEL_MASK (BIT(2) | BIT(1) | BIT(0)) -+#define YT8521_CCR_MODE_UTP_TO_RGMII 0 -+#define YT8521_CCR_MODE_FIBER_TO_RGMII 1 -+#define YT8521_CCR_MODE_UTP_FIBER_TO_RGMII 2 -+#define YT8521_CCR_MODE_UTP_TO_SGMII 3 -+#define YT8521_CCR_MODE_SGPHY_TO_RGMAC 4 -+#define YT8521_CCR_MODE_SGMAC_TO_RGPHY 5 -+#define YT8521_CCR_MODE_UTP_TO_FIBER_AUTO 6 -+#define YT8521_CCR_MODE_UTP_TO_FIBER_FORCE 7 -+ -+/* 3 phy polling modes,poll mode combines utp and fiber mode*/ -+#define YT8521_MODE_FIBER 0x1 -+#define YT8521_MODE_UTP 0x2 -+#define YT8521_MODE_POLL 0x3 -+ -+#define YT8521_RGMII_CONFIG1_REG 0xA003 -+ -+/* TX Gig-E Delay is bits 3:0, default 0x1 -+ * TX Fast-E Delay is bits 7:4, default 0xf -+ * RX Delay is bits 13:10, default 0x0 -+ * Delay = 150ps * N -+ * On = 2250ps, off = 0ps -+ */ -+#define YT8521_RC1R_RX_DELAY_MASK (0xF << 10) -+#define YT8521_RC1R_RX_DELAY_EN (0xF << 10) -+#define YT8521_RC1R_RX_DELAY_DIS (0x0 << 10) -+#define YT8521_RC1R_FE_TX_DELAY_MASK (0xF << 4) -+#define YT8521_RC1R_FE_TX_DELAY_EN (0xF << 4) -+#define YT8521_RC1R_FE_TX_DELAY_DIS (0x0 << 4) -+#define YT8521_RC1R_GE_TX_DELAY_MASK (0xF << 0) -+#define YT8521_RC1R_GE_TX_DELAY_EN (0xF << 0) -+#define YT8521_RC1R_GE_TX_DELAY_DIS (0x0 << 0) -+ -+#define YTPHY_MISC_CONFIG_REG 0xA006 -+#define YTPHY_MCR_FIBER_SPEED_MASK BIT(0) -+#define YTPHY_MCR_FIBER_1000BX (0x1 << 0) -+#define YTPHY_MCR_FIBER_100FX (0x0 << 0) -+ -+/* WOL MAC ADDR: MACADDR2(highest), MACADDR1(middle), MACADDR0(lowest) */ -+#define YTPHY_WOL_MACADDR2_REG 0xA007 -+#define YTPHY_WOL_MACADDR1_REG 0xA008 -+#define YTPHY_WOL_MACADDR0_REG 0xA009 -+ -+#define YTPHY_WOL_CONFIG_REG 0xA00A -+#define YTPHY_WCR_INTR_SEL BIT(6) -+#define YTPHY_WCR_ENABLE BIT(3) -+ -+/* 2b00 84ms -+ * 2b01 168ms *default* -+ * 2b10 336ms -+ * 2b11 672ms -+ */ -+#define YTPHY_WCR_PULSE_WIDTH_MASK (BIT(2) | BIT(1)) -+#define YTPHY_WCR_PULSE_WIDTH_672MS (BIT(2) | BIT(1)) -+ -+/* 1b0 Interrupt and WOL events is level triggered and active LOW *default* -+ * 1b1 Interrupt and WOL events is pulse triggered and active LOW -+ */ -+#define YTPHY_WCR_TYPE_PULSE BIT(0) -+ -+/* Extended Register end */ -+ -+struct yt8521_priv { -+ /* combo_advertising is used for case of YT8521 in combo mode, -+ * this means that yt8521 may work in utp or fiber mode which depends -+ * on which media is connected (YT8521_RSSR_TO_BE_ARBITRATED). -+ */ -+ __ETHTOOL_DECLARE_LINK_MODE_MASK(combo_advertising); -+ -+ /* YT8521_MODE_FIBER / YT8521_MODE_UTP / YT8521_MODE_POLL*/ -+ u8 polling_mode; -+ u8 strap_mode; /* 8 working modes */ -+ /* current reg page of yt8521 phy: -+ * YT8521_RSSR_UTP_SPACE -+ * YT8521_RSSR_FIBER_SPACE -+ * YT8521_RSSR_TO_BE_ARBITRATED -+ */ -+ u8 reg_page; -+}; -+ -+/** -+ * ytphy_read_ext() - read a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to read -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns the value of regnum reg or negative error code -+ */ -+static int ytphy_read_ext(struct phy_device *phydev, u16 regnum) -+{ -+ int ret; -+ -+ ret = __phy_write(phydev, YTPHY_PAGE_SELECT, regnum); -+ if (ret < 0) -+ return ret; -+ -+ return __phy_read(phydev, YTPHY_PAGE_DATA); -+} -+ -+/** -+ * ytphy_read_ext_with_lock() - read a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to read -+ * -+ * returns the value of regnum reg or negative error code -+ */ -+static int ytphy_read_ext_with_lock(struct phy_device *phydev, u16 regnum) -+{ -+ int ret; -+ -+ phy_lock_mdio_bus(phydev); -+ ret = ytphy_read_ext(phydev, regnum); -+ phy_unlock_mdio_bus(phydev); -+ -+ return ret; -+} -+ -+/** -+ * ytphy_write_ext() - write a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to write -+ * @val: value to write to @regnum -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative error code -+ */ -+static int ytphy_write_ext(struct phy_device *phydev, u16 regnum, u16 val) -+{ -+ int ret; -+ -+ ret = __phy_write(phydev, YTPHY_PAGE_SELECT, regnum); -+ if (ret < 0) -+ return ret; -+ -+ return __phy_write(phydev, YTPHY_PAGE_DATA, val); -+} -+ -+/** -+ * ytphy_write_ext_with_lock() - write a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to write -+ * @val: value to write to @regnum -+ * -+ * returns 0 or negative error code -+ */ -+static int ytphy_write_ext_with_lock(struct phy_device *phydev, u16 regnum, -+ u16 val) -+{ -+ int ret; -+ -+ phy_lock_mdio_bus(phydev); -+ ret = ytphy_write_ext(phydev, regnum, val); -+ phy_unlock_mdio_bus(phydev); -+ -+ return ret; -+} -+ -+/** -+ * ytphy_modify_ext() - bits modify a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to write -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ * -+ * NOTE: Convenience function which allows a PHY's extended register to be -+ * modified as new register value = (old register value & ~mask) | set. -+ * The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative error code -+ */ -+static int ytphy_modify_ext(struct phy_device *phydev, u16 regnum, u16 mask, -+ u16 set) -+{ -+ int ret; -+ -+ ret = __phy_write(phydev, YTPHY_PAGE_SELECT, regnum); -+ if (ret < 0) -+ return ret; -+ -+ return __phy_modify(phydev, YTPHY_PAGE_DATA, mask, set); -+} -+ -+/** -+ * ytphy_modify_ext_with_lock() - bits modify a PHY's extended register -+ * @phydev: a pointer to a &struct phy_device -+ * @regnum: register number to write -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ * -+ * NOTE: Convenience function which allows a PHY's extended register to be -+ * modified as new register value = (old register value & ~mask) | set. -+ * -+ * returns 0 or negative error code -+ */ -+static int ytphy_modify_ext_with_lock(struct phy_device *phydev, u16 regnum, -+ u16 mask, u16 set) -+{ -+ int ret; -+ -+ phy_lock_mdio_bus(phydev); -+ ret = ytphy_modify_ext(phydev, regnum, mask, set); -+ phy_unlock_mdio_bus(phydev); -+ -+ return ret; -+} -+ -+/** -+ * ytphy_get_wol() - report whether wake-on-lan is enabled -+ * @phydev: a pointer to a &struct phy_device -+ * @wol: a pointer to a &struct ethtool_wolinfo -+ * -+ * NOTE: YTPHY_WOL_CONFIG_REG is common ext reg. -+ */ -+static void ytphy_get_wol(struct phy_device *phydev, -+ struct ethtool_wolinfo *wol) -+{ -+ int wol_config; -+ -+ wol->supported = WAKE_MAGIC; -+ wol->wolopts = 0; -+ -+ wol_config = ytphy_read_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG); -+ if (wol_config < 0) -+ return; -+ -+ if (wol_config & YTPHY_WCR_ENABLE) -+ wol->wolopts |= WAKE_MAGIC; -+} -+ -+/** -+ * ytphy_set_wol() - turn wake-on-lan on or off -+ * @phydev: a pointer to a &struct phy_device -+ * @wol: a pointer to a &struct ethtool_wolinfo -+ * -+ * NOTE: YTPHY_WOL_CONFIG_REG, YTPHY_WOL_MACADDR2_REG, YTPHY_WOL_MACADDR1_REG -+ * and YTPHY_WOL_MACADDR0_REG are common ext reg. The -+ * YTPHY_INTERRUPT_ENABLE_REG of UTP is special, fiber also use this register. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) -+{ -+ struct net_device *p_attached_dev; -+ const u16 mac_addr_reg[] = { -+ YTPHY_WOL_MACADDR2_REG, -+ YTPHY_WOL_MACADDR1_REG, -+ YTPHY_WOL_MACADDR0_REG, -+ }; -+ const u8 *mac_addr; -+ int old_page; -+ int ret = 0; -+ u16 mask; -+ u16 val; -+ u8 i; -+ -+ if (wol->wolopts & WAKE_MAGIC) { -+ p_attached_dev = phydev->attached_dev; -+ if (!p_attached_dev) -+ return -ENODEV; -+ -+ mac_addr = (const u8 *)p_attached_dev->dev_addr; -+ if (!is_valid_ether_addr(mac_addr)) -+ return -EINVAL; -+ -+ /* lock mdio bus then switch to utp reg space */ -+ old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ /* Store the device address for the magic packet */ -+ for (i = 0; i < 3; i++) { -+ ret = ytphy_write_ext(phydev, mac_addr_reg[i], -+ ((mac_addr[i * 2] << 8)) | -+ (mac_addr[i * 2 + 1])); -+ if (ret < 0) -+ goto err_restore_page; -+ } -+ -+ /* Enable WOL feature */ -+ mask = YTPHY_WCR_PULSE_WIDTH_MASK | YTPHY_WCR_INTR_SEL; -+ val = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL; -+ val |= YTPHY_WCR_TYPE_PULSE | YTPHY_WCR_PULSE_WIDTH_672MS; -+ ret = ytphy_modify_ext(phydev, YTPHY_WOL_CONFIG_REG, mask, val); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ /* Enable WOL interrupt */ -+ ret = __phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG, 0, -+ YTPHY_IER_WOL); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ } else { -+ old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ /* Disable WOL feature */ -+ mask = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL; -+ ret = ytphy_modify_ext(phydev, YTPHY_WOL_CONFIG_REG, mask, 0); -+ -+ /* Disable WOL interrupt */ -+ ret = __phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG, -+ YTPHY_IER_WOL, 0); -+ if (ret < 0) -+ goto err_restore_page; -+ } -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ - static int yt8511_read_page(struct phy_device *phydev) - { - return __phy_read(phydev, YT8511_PAGE_SELECT); -@@ -111,6 +548,1181 @@ err_restore_page: - return phy_restore_page(phydev, oldpage, ret); - } - -+/** -+ * yt8521_read_page() - read reg page -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns current reg space of yt8521 (YT8521_RSSR_FIBER_SPACE/ -+ * YT8521_RSSR_UTP_SPACE) or negative errno code -+ */ -+static int yt8521_read_page(struct phy_device *phydev) -+{ -+ int old_page; -+ -+ old_page = ytphy_read_ext(phydev, YT8521_REG_SPACE_SELECT_REG); -+ if (old_page < 0) -+ return old_page; -+ -+ if ((old_page & YT8521_RSSR_SPACE_MASK) == YT8521_RSSR_FIBER_SPACE) -+ return YT8521_RSSR_FIBER_SPACE; -+ -+ return YT8521_RSSR_UTP_SPACE; -+}; -+ -+/** -+ * yt8521_write_page() - write reg page -+ * @phydev: a pointer to a &struct phy_device -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to write. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_write_page(struct phy_device *phydev, int page) -+{ -+ int mask = YT8521_RSSR_SPACE_MASK; -+ int set; -+ -+ if ((page & YT8521_RSSR_SPACE_MASK) == YT8521_RSSR_FIBER_SPACE) -+ set = YT8521_RSSR_FIBER_SPACE; -+ else -+ set = YT8521_RSSR_UTP_SPACE; -+ -+ return ytphy_modify_ext(phydev, YT8521_REG_SPACE_SELECT_REG, mask, set); -+}; -+ -+/** -+ * yt8521_probe() - read chip config then set suitable polling_mode -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_probe(struct phy_device *phydev) -+{ -+ struct device *dev = &phydev->mdio.dev; -+ struct yt8521_priv *priv; -+ int chip_config; -+ int ret; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ phydev->priv = priv; -+ -+ chip_config = ytphy_read_ext_with_lock(phydev, YT8521_CHIP_CONFIG_REG); -+ if (chip_config < 0) -+ return chip_config; -+ -+ priv->strap_mode = chip_config & YT8521_CCR_MODE_SEL_MASK; -+ switch (priv->strap_mode) { -+ case YT8521_CCR_MODE_FIBER_TO_RGMII: -+ case YT8521_CCR_MODE_SGPHY_TO_RGMAC: -+ case YT8521_CCR_MODE_SGMAC_TO_RGPHY: -+ priv->polling_mode = YT8521_MODE_FIBER; -+ priv->reg_page = YT8521_RSSR_FIBER_SPACE; -+ phydev->port = PORT_FIBRE; -+ break; -+ case YT8521_CCR_MODE_UTP_FIBER_TO_RGMII: -+ case YT8521_CCR_MODE_UTP_TO_FIBER_AUTO: -+ case YT8521_CCR_MODE_UTP_TO_FIBER_FORCE: -+ priv->polling_mode = YT8521_MODE_POLL; -+ priv->reg_page = YT8521_RSSR_TO_BE_ARBITRATED; -+ phydev->port = PORT_NONE; -+ break; -+ case YT8521_CCR_MODE_UTP_TO_SGMII: -+ case YT8521_CCR_MODE_UTP_TO_RGMII: -+ priv->polling_mode = YT8521_MODE_UTP; -+ priv->reg_page = YT8521_RSSR_UTP_SPACE; -+ phydev->port = PORT_TP; -+ break; -+ } -+ /* set default reg space */ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ ret = ytphy_write_ext_with_lock(phydev, -+ YT8521_REG_SPACE_SELECT_REG, -+ priv->reg_page); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * ytphy_utp_read_lpa() - read LPA then setup lp_advertising for utp -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_utp_read_lpa(struct phy_device *phydev) -+{ -+ int lpa, lpagb; -+ -+ if (phydev->autoneg == AUTONEG_ENABLE) { -+ if (!phydev->autoneg_complete) { -+ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, -+ 0); -+ mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, 0); -+ return 0; -+ } -+ -+ if (phydev->is_gigabit_capable) { -+ lpagb = __phy_read(phydev, MII_STAT1000); -+ if (lpagb < 0) -+ return lpagb; -+ -+ if (lpagb & LPA_1000MSFAIL) { -+ int adv = __phy_read(phydev, MII_CTRL1000); -+ -+ if (adv < 0) -+ return adv; -+ -+ if (adv & CTL1000_ENABLE_MASTER) -+ phydev_err(phydev, "Master/Slave resolution failed, maybe conflicting manual settings?\n"); -+ else -+ phydev_err(phydev, "Master/Slave resolution failed\n"); -+ return -ENOLINK; -+ } -+ -+ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, -+ lpagb); -+ } -+ -+ lpa = __phy_read(phydev, MII_LPA); -+ if (lpa < 0) -+ return lpa; -+ -+ mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, lpa); -+ } else { -+ linkmode_zero(phydev->lp_advertising); -+ } -+ -+ return 0; -+} -+ -+/** -+ * yt8521_adjust_status() - update speed and duplex to phydev. when in fiber -+ * mode, adjust speed and duplex. -+ * @phydev: a pointer to a &struct phy_device -+ * @status: yt8521 status read from YTPHY_SPECIFIC_STATUS_REG -+ * @is_utp: false(yt8521 work in fiber mode) or true(yt8521 work in utp mode) -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 -+ */ -+static int yt8521_adjust_status(struct phy_device *phydev, int status, -+ bool is_utp) -+{ -+ int speed_mode, duplex; -+ int speed; -+ int err; -+ int lpa; -+ -+ if (is_utp) -+ duplex = (status & YTPHY_SSR_DUPLEX) >> YTPHY_SSR_DUPLEX_OFFSET; -+ else -+ duplex = DUPLEX_FULL; /* for fiber, it always DUPLEX_FULL */ -+ -+ speed_mode = (status & YTPHY_SSR_SPEED_MODE_MASK) >> -+ YTPHY_SSR_SPEED_MODE_OFFSET; -+ -+ switch (speed_mode) { -+ case YTPHY_SSR_SPEED_10M: -+ if (is_utp) -+ speed = SPEED_10; -+ else -+ /* for fiber, it will never run here, default to -+ * SPEED_UNKNOWN -+ */ -+ speed = SPEED_UNKNOWN; -+ break; -+ case YTPHY_SSR_SPEED_100M: -+ speed = SPEED_100; -+ break; -+ case YTPHY_SSR_SPEED_1000M: -+ speed = SPEED_1000; -+ break; -+ default: -+ speed = SPEED_UNKNOWN; -+ break; -+ } -+ -+ phydev->speed = speed; -+ phydev->duplex = duplex; -+ -+ if (is_utp) { -+ err = ytphy_utp_read_lpa(phydev); -+ if (err < 0) -+ return err; -+ -+ phy_resolve_aneg_pause(phydev); -+ } else { -+ lpa = __phy_read(phydev, MII_LPA); -+ if (lpa < 0) -+ return lpa; -+ -+ /* only support 1000baseX Full */ -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, -+ phydev->lp_advertising, lpa & LPA_1000XFULL); -+ -+ if (!(lpa & YTPHY_FLPA_PAUSE)) { -+ phydev->pause = 0; -+ phydev->asym_pause = 0; -+ } else if ((lpa & YTPHY_FLPA_ASYM_PAUSE)) { -+ phydev->pause = 1; -+ phydev->asym_pause = 1; -+ } else { -+ phydev->pause = 1; -+ phydev->asym_pause = 0; -+ } -+ } -+ -+ return 0; -+} -+ -+/** -+ * yt8521_read_status_paged() - determines the speed and duplex of one page -+ * @phydev: a pointer to a &struct phy_device -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to -+ * operate. -+ * -+ * returns 1 (utp or fiber link),0 (no link) or negative errno code -+ */ -+static int yt8521_read_status_paged(struct phy_device *phydev, int page) -+{ -+ int fiber_latch_val; -+ int fiber_curr_val; -+ int old_page; -+ int ret = 0; -+ int status; -+ int link; -+ -+ linkmode_zero(phydev->lp_advertising); -+ phydev->duplex = DUPLEX_UNKNOWN; -+ phydev->speed = SPEED_UNKNOWN; -+ phydev->asym_pause = 0; -+ phydev->pause = 0; -+ -+ /* YT8521 has two reg space (utp/fiber) for linkup with utp/fiber -+ * respectively. but for utp/fiber combo mode, reg space should be -+ * arbitrated based on media priority. by default, utp takes -+ * priority. reg space should be properly set before read -+ * YTPHY_SPECIFIC_STATUS_REG. -+ */ -+ -+ page &= YT8521_RSSR_SPACE_MASK; -+ old_page = phy_select_page(phydev, page); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ /* Read YTPHY_SPECIFIC_STATUS_REG, which indicates the speed and duplex -+ * of the PHY is actually using. -+ */ -+ ret = __phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ status = ret; -+ link = !!(status & YTPHY_SSR_LINK); -+ -+ /* When PHY is in fiber mode, speed transferred from 1000Mbps to -+ * 100Mbps,there is not link down from YTPHY_SPECIFIC_STATUS_REG, so -+ * we need check MII_BMSR to identify such case. -+ */ -+ if (page == YT8521_RSSR_FIBER_SPACE) { -+ ret = __phy_read(phydev, MII_BMSR); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ fiber_latch_val = ret; -+ ret = __phy_read(phydev, MII_BMSR); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ fiber_curr_val = ret; -+ if (link && fiber_latch_val != fiber_curr_val) { -+ link = 0; -+ phydev_info(phydev, -+ "%s, fiber link down detect, latch = %04x, curr = %04x\n", -+ __func__, fiber_latch_val, fiber_curr_val); -+ } -+ } else { -+ /* Read autonegotiation status */ -+ ret = __phy_read(phydev, MII_BMSR); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ phydev->autoneg_complete = ret & BMSR_ANEGCOMPLETE ? 1 : 0; -+ } -+ -+ if (link) { -+ if (page == YT8521_RSSR_UTP_SPACE) -+ yt8521_adjust_status(phydev, status, true); -+ else -+ yt8521_adjust_status(phydev, status, false); -+ } -+ return phy_restore_page(phydev, old_page, link); -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_read_status() - determines the negotiated speed and duplex -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_read_status(struct phy_device *phydev) -+{ -+ struct yt8521_priv *priv = phydev->priv; -+ int link_fiber = 0; -+ int link_utp; -+ int link; -+ int ret; -+ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ link = yt8521_read_status_paged(phydev, priv->reg_page); -+ if (link < 0) -+ return link; -+ } else { -+ /* when page is YT8521_RSSR_TO_BE_ARBITRATED, arbitration is -+ * needed. by default, utp is higher priority. -+ */ -+ -+ link_utp = yt8521_read_status_paged(phydev, -+ YT8521_RSSR_UTP_SPACE); -+ if (link_utp < 0) -+ return link_utp; -+ -+ if (!link_utp) { -+ link_fiber = yt8521_read_status_paged(phydev, -+ YT8521_RSSR_FIBER_SPACE); -+ if (link_fiber < 0) -+ return link_fiber; -+ } -+ -+ link = link_utp || link_fiber; -+ } -+ -+ if (link) { -+ if (phydev->link == 0) { -+ /* arbitrate reg space based on linkup media type. */ -+ if (priv->polling_mode == YT8521_MODE_POLL && -+ priv->reg_page == YT8521_RSSR_TO_BE_ARBITRATED) { -+ if (link_fiber) -+ priv->reg_page = -+ YT8521_RSSR_FIBER_SPACE; -+ else -+ priv->reg_page = YT8521_RSSR_UTP_SPACE; -+ -+ ret = ytphy_write_ext_with_lock(phydev, -+ YT8521_REG_SPACE_SELECT_REG, -+ priv->reg_page); -+ if (ret < 0) -+ return ret; -+ -+ phydev->port = link_fiber ? PORT_FIBRE : PORT_TP; -+ -+ phydev_info(phydev, "%s, link up, media: %s\n", -+ __func__, -+ (phydev->port == PORT_TP) ? -+ "UTP" : "Fiber"); -+ } -+ } -+ phydev->link = 1; -+ } else { -+ if (phydev->link == 1) { -+ phydev_info(phydev, "%s, link down, media: %s\n", -+ __func__, (phydev->port == PORT_TP) ? -+ "UTP" : "Fiber"); -+ -+ /* When in YT8521_MODE_POLL mode, need prepare for next -+ * arbitration. -+ */ -+ if (priv->polling_mode == YT8521_MODE_POLL) { -+ priv->reg_page = YT8521_RSSR_TO_BE_ARBITRATED; -+ phydev->port = PORT_NONE; -+ } -+ } -+ -+ phydev->link = 0; -+ } -+ -+ return 0; -+} -+ -+/** -+ * yt8521_modify_bmcr_paged - bits modify a PHY's BMCR register of one page -+ * @phydev: the phy_device struct -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to operate -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ * -+ * NOTE: Convenience function which allows a PHY's BMCR register to be -+ * modified as new register value = (old register value & ~mask) | set. -+ * YT8521 has two space (utp/fiber) and three mode (utp/fiber/poll), each space -+ * has MII_BMCR. poll mode combines utp and faber,so need do both. -+ * If it is reset, it will wait for completion. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_modify_bmcr_paged(struct phy_device *phydev, int page, -+ u16 mask, u16 set) -+{ -+ int max_cnt = 500; /* the max wait time of reset ~ 500 ms */ -+ int old_page; -+ int ret = 0; -+ -+ old_page = phy_select_page(phydev, page & YT8521_RSSR_SPACE_MASK); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ ret = __phy_modify(phydev, MII_BMCR, mask, set); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ /* If it is reset, need to wait for the reset to complete */ -+ if (set == BMCR_RESET) { -+ while (max_cnt--) { -+ usleep_range(1000, 1100); -+ ret = __phy_read(phydev, MII_BMCR); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ if (!(ret & BMCR_RESET)) -+ return phy_restore_page(phydev, old_page, 0); -+ } -+ } -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_modify_utp_fiber_bmcr - bits modify a PHY's BMCR register -+ * @phydev: the phy_device struct -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ * -+ * NOTE: Convenience function which allows a PHY's BMCR register to be -+ * modified as new register value = (old register value & ~mask) | set. -+ * YT8521 has two space (utp/fiber) and three mode (utp/fiber/poll), each space -+ * has MII_BMCR. poll mode combines utp and faber,so need do both. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_modify_utp_fiber_bmcr(struct phy_device *phydev, u16 mask, -+ u16 set) -+{ -+ struct yt8521_priv *priv = phydev->priv; -+ int ret; -+ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ ret = yt8521_modify_bmcr_paged(phydev, priv->reg_page, mask, -+ set); -+ if (ret < 0) -+ return ret; -+ } else { -+ ret = yt8521_modify_bmcr_paged(phydev, YT8521_RSSR_UTP_SPACE, -+ mask, set); -+ if (ret < 0) -+ return ret; -+ -+ ret = yt8521_modify_bmcr_paged(phydev, YT8521_RSSR_FIBER_SPACE, -+ mask, set); -+ if (ret < 0) -+ return ret; -+ } -+ return 0; -+} -+ -+/** -+ * yt8521_soft_reset() - called to issue a PHY software reset -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_soft_reset(struct phy_device *phydev) -+{ -+ return yt8521_modify_utp_fiber_bmcr(phydev, 0, BMCR_RESET); -+} -+ -+/** -+ * yt8521_suspend() - suspend the hardware -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_suspend(struct phy_device *phydev) -+{ -+ int wol_config; -+ -+ /* YTPHY_WOL_CONFIG_REG is common ext reg */ -+ wol_config = ytphy_read_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG); -+ if (wol_config < 0) -+ return wol_config; -+ -+ /* if wol enable, do nothing */ -+ if (wol_config & YTPHY_WCR_ENABLE) -+ return 0; -+ -+ return yt8521_modify_utp_fiber_bmcr(phydev, 0, BMCR_PDOWN); -+} -+ -+/** -+ * yt8521_resume() - resume the hardware -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_resume(struct phy_device *phydev) -+{ -+ int ret; -+ int wol_config; -+ -+ /* disable auto sleep */ -+ ret = ytphy_modify_ext_with_lock(phydev, -+ YT8521_EXTREG_SLEEP_CONTROL1_REG, -+ YT8521_ESC1R_SLEEP_SW, 0); -+ if (ret < 0) -+ return ret; -+ -+ wol_config = ytphy_read_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG); -+ if (wol_config < 0) -+ return wol_config; -+ -+ /* if wol enable, do nothing */ -+ if (wol_config & YTPHY_WCR_ENABLE) -+ return 0; -+ -+ return yt8521_modify_utp_fiber_bmcr(phydev, BMCR_PDOWN, 0); -+} -+ -+/** -+ * yt8521_config_init() - called to initialize the PHY -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_config_init(struct phy_device *phydev) -+{ -+ int old_page; -+ int ret = 0; -+ u16 val; -+ -+ old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ switch (phydev->interface) { -+ case PHY_INTERFACE_MODE_RGMII: -+ val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_GE_TX_DELAY_DIS; -+ val |= YT8521_RC1R_RX_DELAY_DIS; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_GE_TX_DELAY_DIS; -+ val |= YT8521_RC1R_RX_DELAY_EN; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_GE_TX_DELAY_EN; -+ val |= YT8521_RC1R_RX_DELAY_DIS; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_GE_TX_DELAY_EN; -+ val |= YT8521_RC1R_RX_DELAY_EN; -+ break; -+ case PHY_INTERFACE_MODE_SGMII: -+ break; -+ default: /* do not support other modes */ -+ ret = -EOPNOTSUPP; -+ goto err_restore_page; -+ } -+ -+ /* set rgmii delay mode */ -+ if (phydev->interface != PHY_INTERFACE_MODE_SGMII) { -+ ret = ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, -+ (YT8521_RC1R_RX_DELAY_MASK | -+ YT8521_RC1R_FE_TX_DELAY_MASK | -+ YT8521_RC1R_GE_TX_DELAY_MASK), -+ val); -+ if (ret < 0) -+ goto err_restore_page; -+ } -+ -+ /* disable auto sleep */ -+ ret = ytphy_modify_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1_REG, -+ YT8521_ESC1R_SLEEP_SW, 0); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ /* enable RXC clock when no wire plug */ -+ ret = ytphy_modify_ext(phydev, YT8521_CLOCK_GATING_REG, -+ YT8521_CGR_RX_CLK_EN, 0); -+ if (ret < 0) -+ goto err_restore_page; -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_prepare_fiber_features() - A small helper function that setup -+ * fiber's features. -+ * @phydev: a pointer to a &struct phy_device -+ * @dst: a pointer to store fiber's features -+ */ -+static void yt8521_prepare_fiber_features(struct phy_device *phydev, -+ unsigned long *dst) -+{ -+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT, dst); -+ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, dst); -+ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, dst); -+ linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, dst); -+} -+ -+/** -+ * yt8521_fiber_setup_forced - configures/forces speed from @phydev -+ * @phydev: target phy_device struct -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_fiber_setup_forced(struct phy_device *phydev) -+{ -+ u16 val; -+ int ret; -+ -+ if (phydev->speed == SPEED_1000) -+ val = YTPHY_MCR_FIBER_1000BX; -+ else if (phydev->speed == SPEED_100) -+ val = YTPHY_MCR_FIBER_100FX; -+ else -+ return -EINVAL; -+ -+ ret = __phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0); -+ if (ret < 0) -+ return ret; -+ -+ /* disable Fiber auto sensing */ -+ ret = ytphy_modify_ext(phydev, YT8521_LINK_TIMER_CFG2_REG, -+ YT8521_LTCR_EN_AUTOSEN, 0); -+ if (ret < 0) -+ return ret; -+ -+ ret = ytphy_modify_ext(phydev, YTPHY_MISC_CONFIG_REG, -+ YTPHY_MCR_FIBER_SPEED_MASK, val); -+ if (ret < 0) -+ return ret; -+ -+ return ytphy_modify_ext(phydev, YT8521_CHIP_CONFIG_REG, -+ YT8521_CCR_SW_RST, 0); -+} -+ -+/** -+ * ytphy_check_and_restart_aneg - Enable and restart auto-negotiation -+ * @phydev: target phy_device struct -+ * @restart: whether aneg restart is requested -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_check_and_restart_aneg(struct phy_device *phydev, bool restart) -+{ -+ int ret; -+ -+ if (!restart) { -+ /* Advertisement hasn't changed, but maybe aneg was never on to -+ * begin with? Or maybe phy was isolated? -+ */ -+ ret = __phy_read(phydev, MII_BMCR); -+ if (ret < 0) -+ return ret; -+ -+ if (!(ret & BMCR_ANENABLE) || (ret & BMCR_ISOLATE)) -+ restart = true; -+ } -+ /* Enable and Restart Autonegotiation -+ * Don't isolate the PHY if we're negotiating -+ */ -+ if (restart) -+ return __phy_modify(phydev, MII_BMCR, BMCR_ISOLATE, -+ BMCR_ANENABLE | BMCR_ANRESTART); -+ -+ return 0; -+} -+ -+/** -+ * yt8521_fiber_config_aneg - restart auto-negotiation or write -+ * YTPHY_MISC_CONFIG_REG. -+ * @phydev: target phy_device struct -+ * -+ * NOTE:The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_fiber_config_aneg(struct phy_device *phydev) -+{ -+ int err, changed = 0; -+ int bmcr; -+ u16 adv; -+ -+ if (phydev->autoneg != AUTONEG_ENABLE) -+ return yt8521_fiber_setup_forced(phydev); -+ -+ /* enable Fiber auto sensing */ -+ err = ytphy_modify_ext(phydev, YT8521_LINK_TIMER_CFG2_REG, -+ 0, YT8521_LTCR_EN_AUTOSEN); -+ if (err < 0) -+ return err; -+ -+ err = ytphy_modify_ext(phydev, YT8521_CHIP_CONFIG_REG, -+ YT8521_CCR_SW_RST, 0); -+ if (err < 0) -+ return err; -+ -+ bmcr = __phy_read(phydev, MII_BMCR); -+ if (bmcr < 0) -+ return bmcr; -+ -+ /* When it is coming from fiber forced mode, add bmcr power down -+ * and power up to let aneg work fine. -+ */ -+ if (!(bmcr & BMCR_ANENABLE)) { -+ __phy_modify(phydev, MII_BMCR, 0, BMCR_PDOWN); -+ usleep_range(1000, 1100); -+ __phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0); -+ } -+ -+ adv = linkmode_adv_to_mii_adv_x(phydev->advertising, -+ ETHTOOL_LINK_MODE_1000baseX_Full_BIT); -+ -+ /* Setup fiber advertisement */ -+ err = __phy_modify_changed(phydev, MII_ADVERTISE, -+ ADVERTISE_1000XHALF | ADVERTISE_1000XFULL | -+ ADVERTISE_1000XPAUSE | -+ ADVERTISE_1000XPSE_ASYM, -+ adv); -+ if (err < 0) -+ return err; -+ -+ if (err > 0) -+ changed = 1; -+ -+ return ytphy_check_and_restart_aneg(phydev, changed); -+} -+ -+/** -+ * ytphy_setup_master_slave -+ * @phydev: target phy_device struct -+ * -+ * NOTE: The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_setup_master_slave(struct phy_device *phydev) -+{ -+ u16 ctl = 0; -+ -+ if (!phydev->is_gigabit_capable) -+ return 0; -+ -+ switch (phydev->master_slave_set) { -+ case MASTER_SLAVE_CFG_MASTER_PREFERRED: -+ ctl |= CTL1000_PREFER_MASTER; -+ break; -+ case MASTER_SLAVE_CFG_SLAVE_PREFERRED: -+ break; -+ case MASTER_SLAVE_CFG_MASTER_FORCE: -+ ctl |= CTL1000_AS_MASTER; -+ fallthrough; -+ case MASTER_SLAVE_CFG_SLAVE_FORCE: -+ ctl |= CTL1000_ENABLE_MASTER; -+ break; -+ case MASTER_SLAVE_CFG_UNKNOWN: -+ case MASTER_SLAVE_CFG_UNSUPPORTED: -+ return 0; -+ default: -+ phydev_warn(phydev, "Unsupported Master/Slave mode\n"); -+ return -EOPNOTSUPP; -+ } -+ -+ return __phy_modify_changed(phydev, MII_CTRL1000, -+ (CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER | -+ CTL1000_PREFER_MASTER), ctl); -+} -+ -+/** -+ * ytphy_utp_config_advert - sanitize and advertise auto-negotiation parameters -+ * @phydev: target phy_device struct -+ * -+ * NOTE: Writes MII_ADVERTISE with the appropriate values, -+ * after sanitizing the values to make sure we only advertise -+ * what is supported. Returns < 0 on error, 0 if the PHY's advertisement -+ * hasn't changed, and > 0 if it has changed. -+ * The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_utp_config_advert(struct phy_device *phydev) -+{ -+ int err, bmsr, changed = 0; -+ u32 adv; -+ -+ /* Only allow advertising what this PHY supports */ -+ linkmode_and(phydev->advertising, phydev->advertising, -+ phydev->supported); -+ -+ adv = linkmode_adv_to_mii_adv_t(phydev->advertising); -+ -+ /* Setup standard advertisement */ -+ err = __phy_modify_changed(phydev, MII_ADVERTISE, -+ ADVERTISE_ALL | ADVERTISE_100BASE4 | -+ ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM, -+ adv); -+ if (err < 0) -+ return err; -+ if (err > 0) -+ changed = 1; -+ -+ bmsr = __phy_read(phydev, MII_BMSR); -+ if (bmsr < 0) -+ return bmsr; -+ -+ /* Per 802.3-2008, Section 22.2.4.2.16 Extended status all -+ * 1000Mbits/sec capable PHYs shall have the BMSR_ESTATEN bit set to a -+ * logical 1. -+ */ -+ if (!(bmsr & BMSR_ESTATEN)) -+ return changed; -+ -+ adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); -+ -+ err = __phy_modify_changed(phydev, MII_CTRL1000, -+ ADVERTISE_1000FULL | ADVERTISE_1000HALF, -+ adv); -+ if (err < 0) -+ return err; -+ if (err > 0) -+ changed = 1; -+ -+ return changed; -+} -+ -+/** -+ * ytphy_utp_config_aneg - restart auto-negotiation or write BMCR -+ * @phydev: target phy_device struct -+ * @changed: whether autoneg is requested -+ * -+ * NOTE: If auto-negotiation is enabled, we configure the -+ * advertising, and then restart auto-negotiation. If it is not -+ * enabled, then we write the BMCR. -+ * The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_utp_config_aneg(struct phy_device *phydev, bool changed) -+{ -+ int err; -+ u16 ctl; -+ -+ err = ytphy_setup_master_slave(phydev); -+ if (err < 0) -+ return err; -+ else if (err) -+ changed = true; -+ -+ if (phydev->autoneg != AUTONEG_ENABLE) { -+ /* configures/forces speed/duplex from @phydev */ -+ -+ ctl = mii_bmcr_encode_fixed(phydev->speed, phydev->duplex); -+ -+ return __phy_modify(phydev, MII_BMCR, ~(BMCR_LOOPBACK | -+ BMCR_ISOLATE | BMCR_PDOWN), ctl); -+ } -+ -+ err = ytphy_utp_config_advert(phydev); -+ if (err < 0) /* error */ -+ return err; -+ else if (err) -+ changed = true; -+ -+ return ytphy_check_and_restart_aneg(phydev, changed); -+} -+ -+/** -+ * yt8521_config_aneg_paged() - switch reg space then call genphy_config_aneg -+ * of one page -+ * @phydev: a pointer to a &struct phy_device -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to -+ * operate. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_config_aneg_paged(struct phy_device *phydev, int page) -+{ -+ __ETHTOOL_DECLARE_LINK_MODE_MASK(fiber_supported); -+ struct yt8521_priv *priv = phydev->priv; -+ int old_page; -+ int ret = 0; -+ -+ page &= YT8521_RSSR_SPACE_MASK; -+ -+ old_page = phy_select_page(phydev, page); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ /* If reg_page is YT8521_RSSR_TO_BE_ARBITRATED, -+ * phydev->advertising should be updated. -+ */ -+ if (priv->reg_page == YT8521_RSSR_TO_BE_ARBITRATED) { -+ linkmode_zero(fiber_supported); -+ yt8521_prepare_fiber_features(phydev, fiber_supported); -+ -+ /* prepare fiber_supported, then setup advertising. */ -+ if (page == YT8521_RSSR_FIBER_SPACE) { -+ linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, -+ fiber_supported); -+ linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, -+ fiber_supported); -+ linkmode_and(phydev->advertising, -+ priv->combo_advertising, fiber_supported); -+ } else { -+ /* ETHTOOL_LINK_MODE_Autoneg_BIT is also used in utp */ -+ linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ fiber_supported); -+ linkmode_andnot(phydev->advertising, -+ priv->combo_advertising, -+ fiber_supported); -+ } -+ } -+ -+ if (page == YT8521_RSSR_FIBER_SPACE) -+ ret = yt8521_fiber_config_aneg(phydev); -+ else -+ ret = ytphy_utp_config_aneg(phydev, false); -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_config_aneg() - change reg space then call yt8521_config_aneg_paged -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_config_aneg(struct phy_device *phydev) -+{ -+ struct yt8521_priv *priv = phydev->priv; -+ int ret; -+ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ ret = yt8521_config_aneg_paged(phydev, priv->reg_page); -+ if (ret < 0) -+ return ret; -+ } else { -+ /* If reg_page is YT8521_RSSR_TO_BE_ARBITRATED, -+ * phydev->advertising need to be saved at first run. -+ * Because it contains the advertising which supported by both -+ * mac and yt8521(utp and fiber). -+ */ -+ if (linkmode_empty(priv->combo_advertising)) { -+ linkmode_copy(priv->combo_advertising, -+ phydev->advertising); -+ } -+ -+ ret = yt8521_config_aneg_paged(phydev, YT8521_RSSR_UTP_SPACE); -+ if (ret < 0) -+ return ret; -+ -+ ret = yt8521_config_aneg_paged(phydev, YT8521_RSSR_FIBER_SPACE); -+ if (ret < 0) -+ return ret; -+ -+ /* we don't known which will be link, so restore -+ * phydev->advertising as default value. -+ */ -+ linkmode_copy(phydev->advertising, priv->combo_advertising); -+ } -+ return 0; -+} -+ -+/** -+ * yt8521_aneg_done_paged() - determines the auto negotiation result of one -+ * page. -+ * @phydev: a pointer to a &struct phy_device -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to -+ * operate. -+ * -+ * returns 0(no link)or 1(fiber or utp link) or negative errno code -+ */ -+static int yt8521_aneg_done_paged(struct phy_device *phydev, int page) -+{ -+ int old_page; -+ int ret = 0; -+ int link; -+ -+ old_page = phy_select_page(phydev, page & YT8521_RSSR_SPACE_MASK); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ ret = __phy_read(phydev, YTPHY_SPECIFIC_STATUS_REG); -+ if (ret < 0) -+ goto err_restore_page; -+ -+ link = !!(ret & YTPHY_SSR_LINK); -+ ret = link; -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_aneg_done() - determines the auto negotiation result -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0(no link)or 1(fiber or utp link) or negative errno code -+ */ -+static int yt8521_aneg_done(struct phy_device *phydev) -+{ -+ struct yt8521_priv *priv = phydev->priv; -+ int link_fiber = 0; -+ int link_utp; -+ int link; -+ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ link = yt8521_aneg_done_paged(phydev, priv->reg_page); -+ } else { -+ link_utp = yt8521_aneg_done_paged(phydev, -+ YT8521_RSSR_UTP_SPACE); -+ if (link_utp < 0) -+ return link_utp; -+ -+ if (!link_utp) { -+ link_fiber = yt8521_aneg_done_paged(phydev, -+ YT8521_RSSR_FIBER_SPACE); -+ if (link_fiber < 0) -+ return link_fiber; -+ } -+ link = link_fiber || link_utp; -+ phydev_info(phydev, "%s, link_fiber: %d, link_utp: %d\n", -+ __func__, link_fiber, link_utp); -+ } -+ -+ return link; -+} -+ -+/** -+ * ytphy_utp_read_abilities - read PHY abilities from Clause 22 registers -+ * @phydev: target phy_device struct -+ * -+ * NOTE: Reads the PHY's abilities and populates -+ * phydev->supported accordingly. -+ * The caller must have taken the MDIO bus lock. -+ * -+ * returns 0 or negative errno code -+ */ -+static int ytphy_utp_read_abilities(struct phy_device *phydev) -+{ -+ int val; -+ -+ linkmode_set_bit_array(phy_basic_ports_array, -+ ARRAY_SIZE(phy_basic_ports_array), -+ phydev->supported); -+ -+ val = __phy_read(phydev, MII_BMSR); -+ if (val < 0) -+ return val; -+ -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported, -+ val & BMSR_ANEGCAPABLE); -+ -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, phydev->supported, -+ val & BMSR_100FULL); -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, phydev->supported, -+ val & BMSR_100HALF); -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, phydev->supported, -+ val & BMSR_10FULL); -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, phydev->supported, -+ val & BMSR_10HALF); -+ -+ if (val & BMSR_ESTATEN) { -+ val = __phy_read(phydev, MII_ESTATUS); -+ if (val < 0) -+ return val; -+ -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, -+ phydev->supported, val & ESTATUS_1000_TFULL); -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, -+ phydev->supported, val & ESTATUS_1000_THALF); -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, -+ phydev->supported, val & ESTATUS_1000_XFULL); -+ } -+ -+ return 0; -+} -+ -+/** -+ * yt8521_get_features_paged() - read supported link modes for one page -+ * @phydev: a pointer to a &struct phy_device -+ * @page: The reg page(YT8521_RSSR_FIBER_SPACE/YT8521_RSSR_UTP_SPACE) to -+ * operate. -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_get_features_paged(struct phy_device *phydev, int page) -+{ -+ int old_page; -+ int ret = 0; -+ -+ page &= YT8521_RSSR_SPACE_MASK; -+ old_page = phy_select_page(phydev, page); -+ if (old_page < 0) -+ goto err_restore_page; -+ -+ if (page == YT8521_RSSR_FIBER_SPACE) { -+ linkmode_zero(phydev->supported); -+ yt8521_prepare_fiber_features(phydev, phydev->supported); -+ } else { -+ ret = ytphy_utp_read_abilities(phydev); -+ if (ret < 0) -+ goto err_restore_page; -+ } -+ -+err_restore_page: -+ return phy_restore_page(phydev, old_page, ret); -+} -+ -+/** -+ * yt8521_get_features - switch reg space then call yt8521_get_features_paged -+ * @phydev: target phy_device struct -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8521_get_features(struct phy_device *phydev) -+{ -+ struct yt8521_priv *priv = phydev->priv; -+ int ret; -+ -+ if (priv->reg_page != YT8521_RSSR_TO_BE_ARBITRATED) { -+ ret = yt8521_get_features_paged(phydev, priv->reg_page); -+ } else { -+ ret = yt8521_get_features_paged(phydev, -+ YT8521_RSSR_UTP_SPACE); -+ if (ret < 0) -+ return ret; -+ -+ /* add fiber's features to phydev->supported */ -+ yt8521_prepare_fiber_features(phydev, phydev->supported); -+ } -+ return ret; -+} -+ - static struct phy_driver motorcomm_phy_drvs[] = { - { - PHY_ID_MATCH_EXACT(PHY_ID_YT8511), -@@ -121,16 +1733,35 @@ static struct phy_driver motorcomm_phy_d - .read_page = yt8511_read_page, - .write_page = yt8511_write_page, - }, -+ { -+ PHY_ID_MATCH_EXACT(PHY_ID_YT8521), -+ .name = "YT8521 Gigabit Ethernet", -+ .get_features = yt8521_get_features, -+ .probe = yt8521_probe, -+ .read_page = yt8521_read_page, -+ .write_page = yt8521_write_page, -+ .get_wol = ytphy_get_wol, -+ .set_wol = ytphy_set_wol, -+ .config_aneg = yt8521_config_aneg, -+ .aneg_done = yt8521_aneg_done, -+ .config_init = yt8521_config_init, -+ .read_status = yt8521_read_status, -+ .soft_reset = yt8521_soft_reset, -+ .suspend = yt8521_suspend, -+ .resume = yt8521_resume, -+ }, - }; - - module_phy_driver(motorcomm_phy_drvs); - --MODULE_DESCRIPTION("Motorcomm PHY driver"); -+MODULE_DESCRIPTION("Motorcomm 8511/8521 PHY driver"); - MODULE_AUTHOR("Peter Geis"); -+MODULE_AUTHOR("Frank"); - MODULE_LICENSE("GPL"); - - static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = { - { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, -+ { PHY_ID_MATCH_EXACT(PHY_ID_YT8521) }, - { /* sentinal */ } - }; - diff --git a/target/linux/rockchip/patches-5.15/011-03-v6.2-net-phy-fix-yt8521-duplicated-argument-to-or.patch b/target/linux/rockchip/patches-5.15/011-03-v6.2-net-phy-fix-yt8521-duplicated-argument-to-or.patch deleted file mode 100644 index cce71c8d84..0000000000 --- a/target/linux/rockchip/patches-5.15/011-03-v6.2-net-phy-fix-yt8521-duplicated-argument-to-or.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 4e0243e7128c9b25ea2739136076a95d6adaba5e Mon Sep 17 00:00:00 2001 -From: Frank -Date: Fri, 4 Nov 2022 16:44:41 +0800 -Subject: [PATCH] net: phy: fix yt8521 duplicated argument to & or | - -cocci warnings: (new ones prefixed by >>) ->> drivers/net/phy/motorcomm.c:1122:8-35: duplicated argument to & or | - drivers/net/phy/motorcomm.c:1126:8-35: duplicated argument to & or | - drivers/net/phy/motorcomm.c:1130:8-34: duplicated argument to & or | - drivers/net/phy/motorcomm.c:1134:8-34: duplicated argument to & or | - - The second YT8521_RC1R_GE_TX_DELAY_xx should be YT8521_RC1R_FE_TX_DELAY_xx. - -Fixes: 70479a40954c ("net: phy: Add driver for Motorcomm yt8521 gigabit ethernet phy") -Reported-by: kernel test robot -Reported-by: Julia Lawall -Signed-off-by: Frank -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/motorcomm.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -1119,19 +1119,19 @@ static int yt8521_config_init(struct phy - - switch (phydev->interface) { - case PHY_INTERFACE_MODE_RGMII: -- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_GE_TX_DELAY_DIS; -+ val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS; - val |= YT8521_RC1R_RX_DELAY_DIS; - break; - case PHY_INTERFACE_MODE_RGMII_RXID: -- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_GE_TX_DELAY_DIS; -+ val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS; - val |= YT8521_RC1R_RX_DELAY_EN; - break; - case PHY_INTERFACE_MODE_RGMII_TXID: -- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_GE_TX_DELAY_EN; -+ val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN; - val |= YT8521_RC1R_RX_DELAY_DIS; - break; - case PHY_INTERFACE_MODE_RGMII_ID: -- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_GE_TX_DELAY_EN; -+ val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN; - val |= YT8521_RC1R_RX_DELAY_EN; - break; - case PHY_INTERFACE_MODE_SGMII: diff --git a/target/linux/rockchip/patches-5.15/011-04-v6.2-net-phy-add-Motorcomm-YT8531S-phy-id.patch b/target/linux/rockchip/patches-5.15/011-04-v6.2-net-phy-add-Motorcomm-YT8531S-phy-id.patch deleted file mode 100644 index 226ad789df..0000000000 --- a/target/linux/rockchip/patches-5.15/011-04-v6.2-net-phy-add-Motorcomm-YT8531S-phy-id.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 813abcd98fb1b2cccf850cdfa092a4bfc50b2363 Mon Sep 17 00:00:00 2001 -From: Frank -Date: Tue, 22 Nov 2022 16:42:32 +0800 -Subject: [PATCH] net: phy: add Motorcomm YT8531S phy id. - -We added patch for motorcomm.c to support YT8531S. This patch has -been tested on AM335x platform which has one YT8531S interface -card and passed all test cases. -The tested cases indluding: YT8531S UTP function with support of -10M/100M/1000M; YT8531S Fiber function with support of 100M/1000M; -and YT8531S Combo function that supports auto detection of media type. - -Since most functions of YT8531S are similar to YT8521 and we reuse some -codes for YT8521 in the patch file. - -Signed-off-by: Frank -Signed-off-by: David S. Miller ---- - drivers/net/phy/Kconfig | 2 +- - drivers/net/phy/motorcomm.c | 52 +++++++++++++++++++++++++++++++++---- - 2 files changed, 48 insertions(+), 6 deletions(-) - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -319,7 +319,7 @@ config MOTORCOMM_PHY - tristate "Motorcomm PHYs" - help - Enables support for Motorcomm network PHYs. -- Currently supports the YT8511, YT8521 Gigabit Ethernet PHYs. -+ Currently supports the YT8511, YT8521, YT8531S Gigabit Ethernet PHYs. - - config NATIONAL_PHY - tristate "National Semiconductor PHYs" ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0+ - /* -- * Motorcomm 8511/8521 PHY driver. -+ * Motorcomm 8511/8521/8531S PHY driver. - * - * Author: Peter Geis - * Author: Frank -@@ -12,9 +12,10 @@ - #include - - #define PHY_ID_YT8511 0x0000010a --#define PHY_ID_YT8521 0x0000011A -+#define PHY_ID_YT8521 0x0000011A -+#define PHY_ID_YT8531S 0x4F51E91A - --/* YT8521 Register Overview -+/* YT8521/YT8531S Register Overview - * UTP Register space | FIBER Register space - * ------------------------------------------------------------ - * | UTP MII | FIBER MII | -@@ -147,7 +148,7 @@ - #define YT8521_LINK_TIMER_CFG2_REG 0xA5 - #define YT8521_LTCR_EN_AUTOSEN BIT(15) - --/* 0xA000, 0xA001, 0xA003 ,and 0xA006 ~ 0xA00A are common ext registers -+/* 0xA000, 0xA001, 0xA003, 0xA006 ~ 0xA00A and 0xA012 are common ext registers - * of yt8521 phy. There is no need to switch reg space when operating these - * registers. - */ -@@ -221,6 +222,9 @@ - */ - #define YTPHY_WCR_TYPE_PULSE BIT(0) - -+#define YT8531S_SYNCE_CFG_REG 0xA012 -+#define YT8531S_SCR_SYNCE_ENABLE BIT(6) -+ - /* Extended Register end */ - - struct yt8521_priv { -@@ -648,6 +652,26 @@ static int yt8521_probe(struct phy_devic - } - - /** -+ * yt8531s_probe() - read chip config then set suitable polling_mode -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * returns 0 or negative errno code -+ */ -+static int yt8531s_probe(struct phy_device *phydev) -+{ -+ int ret; -+ -+ /* Disable SyncE clock output by default */ -+ ret = ytphy_modify_ext_with_lock(phydev, YT8531S_SYNCE_CFG_REG, -+ YT8531S_SCR_SYNCE_ENABLE, 0); -+ if (ret < 0) -+ return ret; -+ -+ /* same as yt8521_probe */ -+ return yt8521_probe(phydev); -+} -+ -+/** - * ytphy_utp_read_lpa() - read LPA then setup lp_advertising for utp - * @phydev: a pointer to a &struct phy_device - * -@@ -1750,11 +1774,28 @@ static struct phy_driver motorcomm_phy_d - .suspend = yt8521_suspend, - .resume = yt8521_resume, - }, -+ { -+ PHY_ID_MATCH_EXACT(PHY_ID_YT8531S), -+ .name = "YT8531S Gigabit Ethernet", -+ .get_features = yt8521_get_features, -+ .probe = yt8531s_probe, -+ .read_page = yt8521_read_page, -+ .write_page = yt8521_write_page, -+ .get_wol = ytphy_get_wol, -+ .set_wol = ytphy_set_wol, -+ .config_aneg = yt8521_config_aneg, -+ .aneg_done = yt8521_aneg_done, -+ .config_init = yt8521_config_init, -+ .read_status = yt8521_read_status, -+ .soft_reset = yt8521_soft_reset, -+ .suspend = yt8521_suspend, -+ .resume = yt8521_resume, -+ }, - }; - - module_phy_driver(motorcomm_phy_drvs); - --MODULE_DESCRIPTION("Motorcomm 8511/8521 PHY driver"); -+MODULE_DESCRIPTION("Motorcomm 8511/8521/8531S PHY driver"); - MODULE_AUTHOR("Peter Geis"); - MODULE_AUTHOR("Frank"); - MODULE_LICENSE("GPL"); -@@ -1762,6 +1803,7 @@ MODULE_LICENSE("GPL"); - static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = { - { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, - { PHY_ID_MATCH_EXACT(PHY_ID_YT8521) }, -+ { PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) }, - { /* sentinal */ } - }; - diff --git a/target/linux/rockchip/patches-5.15/011-05-v6.3-net-phy-fix-the-spelling-problem-of-Sentinel.patch b/target/linux/rockchip/patches-5.15/011-05-v6.3-net-phy-fix-the-spelling-problem-of-Sentinel.patch deleted file mode 100644 index 94fc32aadb..0000000000 --- a/target/linux/rockchip/patches-5.15/011-05-v6.3-net-phy-fix-the-spelling-problem-of-Sentinel.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 4104a713204d62aca482eebb0c6226d82a0721eb Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Sat, 28 Jan 2023 14:35:57 +0800 -Subject: [PATCH] net: phy: fix the spelling problem of Sentinel - -CHECK: 'sentinal' may be misspelled - perhaps 'sentinel'? - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Link: https://lore.kernel.org/r/20230128063558.5850-1-Frank.Sae@motor-comm.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/motorcomm.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -1804,7 +1804,7 @@ static const struct mdio_device_id __may - { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, - { PHY_ID_MATCH_EXACT(PHY_ID_YT8521) }, - { PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) }, -- { /* sentinal */ } -+ { /* sentinel */ } - }; - - MODULE_DEVICE_TABLE(mdio, motorcomm_tbl); diff --git a/target/linux/rockchip/patches-5.15/011-06-v6.3-net-phy-motorcomm-change-the-phy-id-of-yt8521-and-yt8531s.patch b/target/linux/rockchip/patches-5.15/011-06-v6.3-net-phy-motorcomm-change-the-phy-id-of-yt8521-and-yt8531s.patch deleted file mode 100644 index 076fa82d26..0000000000 --- a/target/linux/rockchip/patches-5.15/011-06-v6.3-net-phy-motorcomm-change-the-phy-id-of-yt8521-and-yt8531s.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 3c1dc22162d673d595855d24f95200ed2643f88f Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Sat, 28 Jan 2023 14:35:58 +0800 -Subject: [PATCH] net: phy: motorcomm: change the phy id of yt8521 and yt8531s - to lowercase - -The phy id is usually defined in lower case. - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Link: https://lore.kernel.org/r/20230128063558.5850-2-Frank.Sae@motor-comm.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/motorcomm.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -12,8 +12,8 @@ - #include - - #define PHY_ID_YT8511 0x0000010a --#define PHY_ID_YT8521 0x0000011A --#define PHY_ID_YT8531S 0x4F51E91A -+#define PHY_ID_YT8521 0x0000011a -+#define PHY_ID_YT8531S 0x4f51e91a - - /* YT8521/YT8531S Register Overview - * UTP Register space | FIBER Register space diff --git a/target/linux/rockchip/patches-5.15/011-07-v6.3-net-phy-Add-BIT-macro-for-Motorcomm-yt8521-yt8531-gigabit.patch b/target/linux/rockchip/patches-5.15/011-07-v6.3-net-phy-Add-BIT-macro-for-Motorcomm-yt8521-yt8531-gigabit.patch deleted file mode 100644 index ba9a6ab4cc..0000000000 --- a/target/linux/rockchip/patches-5.15/011-07-v6.3-net-phy-Add-BIT-macro-for-Motorcomm-yt8521-yt8531-gigabit.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 4869a146cd60fc8115230f0a45e15e534c531922 Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Thu, 2 Feb 2023 11:00:34 +0800 -Subject: [PATCH] net: phy: Add BIT macro for Motorcomm yt8521/yt8531 gigabit - ethernet phy - -Add BIT macro for Motorcomm yt8521/yt8531 gigabit ethernet phy. - This is a preparatory patch. Add BIT macro for 0xA012 reg, and - supplement for 0xA001 and 0xA003 reg. These will be used to support dts. - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/motorcomm.c | 55 ++++++++++++++++++++++++++++++++++--- - 1 file changed, 51 insertions(+), 4 deletions(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -161,6 +161,11 @@ - - #define YT8521_CHIP_CONFIG_REG 0xA001 - #define YT8521_CCR_SW_RST BIT(15) -+/* 1b0 disable 1.9ns rxc clock delay *default* -+ * 1b1 enable 1.9ns rxc clock delay -+ */ -+#define YT8521_CCR_RXC_DLY_EN BIT(8) -+#define YT8521_CCR_RXC_DLY_1_900_NS 1900 - - #define YT8521_CCR_MODE_SEL_MASK (BIT(2) | BIT(1) | BIT(0)) - #define YT8521_CCR_MODE_UTP_TO_RGMII 0 -@@ -178,22 +183,41 @@ - #define YT8521_MODE_POLL 0x3 - - #define YT8521_RGMII_CONFIG1_REG 0xA003 -- -+/* 1b0 use original tx_clk_rgmii *default* -+ * 1b1 use inverted tx_clk_rgmii. -+ */ -+#define YT8521_RC1R_TX_CLK_SEL_INVERTED BIT(14) - /* TX Gig-E Delay is bits 3:0, default 0x1 - * TX Fast-E Delay is bits 7:4, default 0xf - * RX Delay is bits 13:10, default 0x0 - * Delay = 150ps * N - * On = 2250ps, off = 0ps - */ --#define YT8521_RC1R_RX_DELAY_MASK (0xF << 10) -+#define YT8521_RC1R_RX_DELAY_MASK GENMASK(13, 10) - #define YT8521_RC1R_RX_DELAY_EN (0xF << 10) - #define YT8521_RC1R_RX_DELAY_DIS (0x0 << 10) --#define YT8521_RC1R_FE_TX_DELAY_MASK (0xF << 4) -+#define YT8521_RC1R_FE_TX_DELAY_MASK GENMASK(7, 4) - #define YT8521_RC1R_FE_TX_DELAY_EN (0xF << 4) - #define YT8521_RC1R_FE_TX_DELAY_DIS (0x0 << 4) --#define YT8521_RC1R_GE_TX_DELAY_MASK (0xF << 0) -+#define YT8521_RC1R_GE_TX_DELAY_MASK GENMASK(3, 0) - #define YT8521_RC1R_GE_TX_DELAY_EN (0xF << 0) - #define YT8521_RC1R_GE_TX_DELAY_DIS (0x0 << 0) -+#define YT8521_RC1R_RGMII_0_000_NS 0 -+#define YT8521_RC1R_RGMII_0_150_NS 1 -+#define YT8521_RC1R_RGMII_0_300_NS 2 -+#define YT8521_RC1R_RGMII_0_450_NS 3 -+#define YT8521_RC1R_RGMII_0_600_NS 4 -+#define YT8521_RC1R_RGMII_0_750_NS 5 -+#define YT8521_RC1R_RGMII_0_900_NS 6 -+#define YT8521_RC1R_RGMII_1_050_NS 7 -+#define YT8521_RC1R_RGMII_1_200_NS 8 -+#define YT8521_RC1R_RGMII_1_350_NS 9 -+#define YT8521_RC1R_RGMII_1_500_NS 10 -+#define YT8521_RC1R_RGMII_1_650_NS 11 -+#define YT8521_RC1R_RGMII_1_800_NS 12 -+#define YT8521_RC1R_RGMII_1_950_NS 13 -+#define YT8521_RC1R_RGMII_2_100_NS 14 -+#define YT8521_RC1R_RGMII_2_250_NS 15 - - #define YTPHY_MISC_CONFIG_REG 0xA006 - #define YTPHY_MCR_FIBER_SPEED_MASK BIT(0) -@@ -222,6 +246,29 @@ - */ - #define YTPHY_WCR_TYPE_PULSE BIT(0) - -+#define YTPHY_SYNCE_CFG_REG 0xA012 -+#define YT8521_SCR_SYNCE_ENABLE BIT(5) -+/* 1b0 output 25m clock -+ * 1b1 output 125m clock *default* -+ */ -+#define YT8521_SCR_CLK_FRE_SEL_125M BIT(3) -+#define YT8521_SCR_CLK_SRC_MASK GENMASK(2, 1) -+#define YT8521_SCR_CLK_SRC_PLL_125M 0 -+#define YT8521_SCR_CLK_SRC_UTP_RX 1 -+#define YT8521_SCR_CLK_SRC_SDS_RX 2 -+#define YT8521_SCR_CLK_SRC_REF_25M 3 -+#define YT8531_SCR_SYNCE_ENABLE BIT(6) -+/* 1b0 output 25m clock *default* -+ * 1b1 output 125m clock -+ */ -+#define YT8531_SCR_CLK_FRE_SEL_125M BIT(4) -+#define YT8531_SCR_CLK_SRC_MASK GENMASK(3, 1) -+#define YT8531_SCR_CLK_SRC_PLL_125M 0 -+#define YT8531_SCR_CLK_SRC_UTP_RX 1 -+#define YT8531_SCR_CLK_SRC_SDS_RX 2 -+#define YT8531_SCR_CLK_SRC_CLOCK_FROM_DIGITAL 3 -+#define YT8531_SCR_CLK_SRC_REF_25M 4 -+#define YT8531_SCR_CLK_SRC_SSC_25M 5 - #define YT8531S_SYNCE_CFG_REG 0xA012 - #define YT8531S_SCR_SYNCE_ENABLE BIT(6) - diff --git a/target/linux/rockchip/patches-5.15/011-08-v6.3-net-phy-Add-dts-support-for-Motorcomm-yt8521-gigabit.patch b/target/linux/rockchip/patches-5.15/011-08-v6.3-net-phy-Add-dts-support-for-Motorcomm-yt8521-gigabit.patch deleted file mode 100644 index 85166126ec..0000000000 --- a/target/linux/rockchip/patches-5.15/011-08-v6.3-net-phy-Add-dts-support-for-Motorcomm-yt8521-gigabit.patch +++ /dev/null @@ -1,343 +0,0 @@ -From a6e68f0f8769f79c67cdcfb6302feecd36197dec Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Thu, 2 Feb 2023 11:00:35 +0800 -Subject: [PATCH] net: phy: Add dts support for Motorcomm yt8521 gigabit - ethernet phy - -Add dts support for Motorcomm yt8521 gigabit ethernet phy. - Add ytphy_rgmii_clk_delay_config function to support dst config for - the delay of rgmii clk. This funciont is common for yt8521, yt8531s - and yt8531. - This patch has been verified on AM335x platform. - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/motorcomm.c | 253 ++++++++++++++++++++++++++++-------- - 1 file changed, 199 insertions(+), 54 deletions(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - #define PHY_ID_YT8511 0x0000010a - #define PHY_ID_YT8521 0x0000011a -@@ -187,21 +188,9 @@ - * 1b1 use inverted tx_clk_rgmii. - */ - #define YT8521_RC1R_TX_CLK_SEL_INVERTED BIT(14) --/* TX Gig-E Delay is bits 3:0, default 0x1 -- * TX Fast-E Delay is bits 7:4, default 0xf -- * RX Delay is bits 13:10, default 0x0 -- * Delay = 150ps * N -- * On = 2250ps, off = 0ps -- */ - #define YT8521_RC1R_RX_DELAY_MASK GENMASK(13, 10) --#define YT8521_RC1R_RX_DELAY_EN (0xF << 10) --#define YT8521_RC1R_RX_DELAY_DIS (0x0 << 10) - #define YT8521_RC1R_FE_TX_DELAY_MASK GENMASK(7, 4) --#define YT8521_RC1R_FE_TX_DELAY_EN (0xF << 4) --#define YT8521_RC1R_FE_TX_DELAY_DIS (0x0 << 4) - #define YT8521_RC1R_GE_TX_DELAY_MASK GENMASK(3, 0) --#define YT8521_RC1R_GE_TX_DELAY_EN (0xF << 0) --#define YT8521_RC1R_GE_TX_DELAY_DIS (0x0 << 0) - #define YT8521_RC1R_RGMII_0_000_NS 0 - #define YT8521_RC1R_RGMII_0_150_NS 1 - #define YT8521_RC1R_RGMII_0_300_NS 2 -@@ -274,6 +263,10 @@ - - /* Extended Register end */ - -+#define YTPHY_DTS_OUTPUT_CLK_DIS 0 -+#define YTPHY_DTS_OUTPUT_CLK_25M 25000000 -+#define YTPHY_DTS_OUTPUT_CLK_125M 125000000 -+ - struct yt8521_priv { - /* combo_advertising is used for case of YT8521 in combo mode, - * this means that yt8521 may work in utp or fiber mode which depends -@@ -641,6 +634,142 @@ static int yt8521_write_page(struct phy_ - }; - - /** -+ * struct ytphy_cfg_reg_map - map a config value to a register value -+ * @cfg: value in device configuration -+ * @reg: value in the register -+ */ -+struct ytphy_cfg_reg_map { -+ u32 cfg; -+ u32 reg; -+}; -+ -+static const struct ytphy_cfg_reg_map ytphy_rgmii_delays[] = { -+ /* for tx delay / rx delay with YT8521_CCR_RXC_DLY_EN is not set. */ -+ { 0, YT8521_RC1R_RGMII_0_000_NS }, -+ { 150, YT8521_RC1R_RGMII_0_150_NS }, -+ { 300, YT8521_RC1R_RGMII_0_300_NS }, -+ { 450, YT8521_RC1R_RGMII_0_450_NS }, -+ { 600, YT8521_RC1R_RGMII_0_600_NS }, -+ { 750, YT8521_RC1R_RGMII_0_750_NS }, -+ { 900, YT8521_RC1R_RGMII_0_900_NS }, -+ { 1050, YT8521_RC1R_RGMII_1_050_NS }, -+ { 1200, YT8521_RC1R_RGMII_1_200_NS }, -+ { 1350, YT8521_RC1R_RGMII_1_350_NS }, -+ { 1500, YT8521_RC1R_RGMII_1_500_NS }, -+ { 1650, YT8521_RC1R_RGMII_1_650_NS }, -+ { 1800, YT8521_RC1R_RGMII_1_800_NS }, -+ { 1950, YT8521_RC1R_RGMII_1_950_NS }, /* default tx/rx delay */ -+ { 2100, YT8521_RC1R_RGMII_2_100_NS }, -+ { 2250, YT8521_RC1R_RGMII_2_250_NS }, -+ -+ /* only for rx delay with YT8521_CCR_RXC_DLY_EN is set. */ -+ { 0 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_000_NS }, -+ { 150 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_150_NS }, -+ { 300 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_300_NS }, -+ { 450 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_450_NS }, -+ { 600 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_600_NS }, -+ { 750 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_750_NS }, -+ { 900 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_0_900_NS }, -+ { 1050 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_050_NS }, -+ { 1200 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_200_NS }, -+ { 1350 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_350_NS }, -+ { 1500 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_500_NS }, -+ { 1650 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_650_NS }, -+ { 1800 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_800_NS }, -+ { 1950 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_1_950_NS }, -+ { 2100 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_2_100_NS }, -+ { 2250 + YT8521_CCR_RXC_DLY_1_900_NS, YT8521_RC1R_RGMII_2_250_NS } -+}; -+ -+static u32 ytphy_get_delay_reg_value(struct phy_device *phydev, -+ const char *prop_name, -+ const struct ytphy_cfg_reg_map *tbl, -+ int tb_size, -+ u16 *rxc_dly_en, -+ u32 dflt) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ int tb_size_half = tb_size / 2; -+ u32 val; -+ int i; -+ -+ if (of_property_read_u32(node, prop_name, &val)) -+ goto err_dts_val; -+ -+ /* when rxc_dly_en is NULL, it is get the delay for tx, only half of -+ * tb_size is valid. -+ */ -+ if (!rxc_dly_en) -+ tb_size = tb_size_half; -+ -+ for (i = 0; i < tb_size; i++) { -+ if (tbl[i].cfg == val) { -+ if (rxc_dly_en && i < tb_size_half) -+ *rxc_dly_en = 0; -+ return tbl[i].reg; -+ } -+ } -+ -+ phydev_warn(phydev, "Unsupported value %d for %s using default (%u)\n", -+ val, prop_name, dflt); -+ -+err_dts_val: -+ /* when rxc_dly_en is not NULL, it is get the delay for rx. -+ * The rx default in dts and ytphy_rgmii_clk_delay_config is 1950 ps, -+ * so YT8521_CCR_RXC_DLY_EN should not be set. -+ */ -+ if (rxc_dly_en) -+ *rxc_dly_en = 0; -+ -+ return dflt; -+} -+ -+static int ytphy_rgmii_clk_delay_config(struct phy_device *phydev) -+{ -+ int tb_size = ARRAY_SIZE(ytphy_rgmii_delays); -+ u16 rxc_dly_en = YT8521_CCR_RXC_DLY_EN; -+ u32 rx_reg, tx_reg; -+ u16 mask, val = 0; -+ int ret; -+ -+ rx_reg = ytphy_get_delay_reg_value(phydev, "rx-internal-delay-ps", -+ ytphy_rgmii_delays, tb_size, -+ &rxc_dly_en, -+ YT8521_RC1R_RGMII_1_950_NS); -+ tx_reg = ytphy_get_delay_reg_value(phydev, "tx-internal-delay-ps", -+ ytphy_rgmii_delays, tb_size, NULL, -+ YT8521_RC1R_RGMII_1_950_NS); -+ -+ switch (phydev->interface) { -+ case PHY_INTERFACE_MODE_RGMII: -+ rxc_dly_en = 0; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ val |= FIELD_PREP(YT8521_RC1R_RX_DELAY_MASK, rx_reg); -+ break; -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ rxc_dly_en = 0; -+ val |= FIELD_PREP(YT8521_RC1R_GE_TX_DELAY_MASK, tx_reg); -+ break; -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ val |= FIELD_PREP(YT8521_RC1R_RX_DELAY_MASK, rx_reg) | -+ FIELD_PREP(YT8521_RC1R_GE_TX_DELAY_MASK, tx_reg); -+ break; -+ default: /* do not support other modes */ -+ return -EOPNOTSUPP; -+ } -+ -+ ret = ytphy_modify_ext(phydev, YT8521_CHIP_CONFIG_REG, -+ YT8521_CCR_RXC_DLY_EN, rxc_dly_en); -+ if (ret < 0) -+ return ret; -+ -+ /* Generally, it is not necessary to adjust YT8521_RC1R_FE_TX_DELAY */ -+ mask = YT8521_RC1R_RX_DELAY_MASK | YT8521_RC1R_GE_TX_DELAY_MASK; -+ return ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, mask, val); -+} -+ -+/** - * yt8521_probe() - read chip config then set suitable polling_mode - * @phydev: a pointer to a &struct phy_device - * -@@ -648,9 +777,12 @@ static int yt8521_write_page(struct phy_ - */ - static int yt8521_probe(struct phy_device *phydev) - { -+ struct device_node *node = phydev->mdio.dev.of_node; - struct device *dev = &phydev->mdio.dev; - struct yt8521_priv *priv; - int chip_config; -+ u16 mask, val; -+ u32 freq; - int ret; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -@@ -695,7 +827,45 @@ static int yt8521_probe(struct phy_devic - return ret; - } - -- return 0; -+ if (of_property_read_u32(node, "motorcomm,clk-out-frequency-hz-hz", &freq)) -+ freq = YTPHY_DTS_OUTPUT_CLK_DIS; -+ -+ if (phydev->drv->phy_id == PHY_ID_YT8521) { -+ switch (freq) { -+ case YTPHY_DTS_OUTPUT_CLK_DIS: -+ mask = YT8521_SCR_SYNCE_ENABLE; -+ val = 0; -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_25M: -+ mask = YT8521_SCR_SYNCE_ENABLE | -+ YT8521_SCR_CLK_SRC_MASK | -+ YT8521_SCR_CLK_FRE_SEL_125M; -+ val = YT8521_SCR_SYNCE_ENABLE | -+ FIELD_PREP(YT8521_SCR_CLK_SRC_MASK, -+ YT8521_SCR_CLK_SRC_REF_25M); -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_125M: -+ mask = YT8521_SCR_SYNCE_ENABLE | -+ YT8521_SCR_CLK_SRC_MASK | -+ YT8521_SCR_CLK_FRE_SEL_125M; -+ val = YT8521_SCR_SYNCE_ENABLE | -+ YT8521_SCR_CLK_FRE_SEL_125M | -+ FIELD_PREP(YT8521_SCR_CLK_SRC_MASK, -+ YT8521_SCR_CLK_SRC_PLL_125M); -+ break; -+ default: -+ phydev_warn(phydev, "Freq err:%u\n", freq); -+ return -EINVAL; -+ } -+ } else if (phydev->drv->phy_id == PHY_ID_YT8531S) { -+ return 0; -+ } else { -+ phydev_warn(phydev, "PHY id err\n"); -+ return -EINVAL; -+ } -+ -+ return ytphy_modify_ext_with_lock(phydev, YTPHY_SYNCE_CFG_REG, mask, -+ val); - } - - /** -@@ -1180,61 +1350,36 @@ static int yt8521_resume(struct phy_devi - */ - static int yt8521_config_init(struct phy_device *phydev) - { -+ struct device_node *node = phydev->mdio.dev.of_node; - int old_page; - int ret = 0; -- u16 val; - - old_page = phy_select_page(phydev, YT8521_RSSR_UTP_SPACE); - if (old_page < 0) - goto err_restore_page; - -- switch (phydev->interface) { -- case PHY_INTERFACE_MODE_RGMII: -- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS; -- val |= YT8521_RC1R_RX_DELAY_DIS; -- break; -- case PHY_INTERFACE_MODE_RGMII_RXID: -- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS; -- val |= YT8521_RC1R_RX_DELAY_EN; -- break; -- case PHY_INTERFACE_MODE_RGMII_TXID: -- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN; -- val |= YT8521_RC1R_RX_DELAY_DIS; -- break; -- case PHY_INTERFACE_MODE_RGMII_ID: -- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN; -- val |= YT8521_RC1R_RX_DELAY_EN; -- break; -- case PHY_INTERFACE_MODE_SGMII: -- break; -- default: /* do not support other modes */ -- ret = -EOPNOTSUPP; -- goto err_restore_page; -- } -- - /* set rgmii delay mode */ - if (phydev->interface != PHY_INTERFACE_MODE_SGMII) { -- ret = ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, -- (YT8521_RC1R_RX_DELAY_MASK | -- YT8521_RC1R_FE_TX_DELAY_MASK | -- YT8521_RC1R_GE_TX_DELAY_MASK), -- val); -+ ret = ytphy_rgmii_clk_delay_config(phydev); - if (ret < 0) - goto err_restore_page; - } - -- /* disable auto sleep */ -- ret = ytphy_modify_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1_REG, -- YT8521_ESC1R_SLEEP_SW, 0); -- if (ret < 0) -- goto err_restore_page; -- -- /* enable RXC clock when no wire plug */ -- ret = ytphy_modify_ext(phydev, YT8521_CLOCK_GATING_REG, -- YT8521_CGR_RX_CLK_EN, 0); -- if (ret < 0) -- goto err_restore_page; -+ if (of_property_read_bool(node, "motorcomm,auto-sleep-disabled")) { -+ /* disable auto sleep */ -+ ret = ytphy_modify_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1_REG, -+ YT8521_ESC1R_SLEEP_SW, 0); -+ if (ret < 0) -+ goto err_restore_page; -+ } - -+ if (of_property_read_bool(node, "motorcomm,keep-pll-enabled")) { -+ /* enable RXC clock when no wire plug */ -+ ret = ytphy_modify_ext(phydev, YT8521_CLOCK_GATING_REG, -+ YT8521_CGR_RX_CLK_EN, 0); -+ if (ret < 0) -+ goto err_restore_page; -+ } - err_restore_page: - return phy_restore_page(phydev, old_page, ret); - } diff --git a/target/linux/rockchip/patches-5.15/011-09-v6.3-net-phy-Add-dts-support-for-Motorcomm-yt8531s-gigabit.patch b/target/linux/rockchip/patches-5.15/011-09-v6.3-net-phy-Add-dts-support-for-Motorcomm-yt8531s-gigabit.patch deleted file mode 100644 index 86fc04695c..0000000000 --- a/target/linux/rockchip/patches-5.15/011-09-v6.3-net-phy-Add-dts-support-for-Motorcomm-yt8531s-gigabit.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 36152f87dda4af221b16258751451d9cd3d0fb0b Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Thu, 2 Feb 2023 11:00:36 +0800 -Subject: [PATCH] net: phy: Add dts support for Motorcomm yt8531s gigabit - ethernet phy - -Add dts support for Motorcomm yt8531s gigabit ethernet phy. - Change yt8521_probe to support clk config of yt8531s. Becase - yt8521_probe does the things which yt8531s is needed, so - removed yt8531s function. - This patch has been verified on AM335x platform with yt8531s board. - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/motorcomm.c | 51 ++++++++++++++++++++----------------- - 1 file changed, 27 insertions(+), 24 deletions(-) - ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -258,8 +258,6 @@ - #define YT8531_SCR_CLK_SRC_CLOCK_FROM_DIGITAL 3 - #define YT8531_SCR_CLK_SRC_REF_25M 4 - #define YT8531_SCR_CLK_SRC_SSC_25M 5 --#define YT8531S_SYNCE_CFG_REG 0xA012 --#define YT8531S_SCR_SYNCE_ENABLE BIT(6) - - /* Extended Register end */ - -@@ -858,7 +856,32 @@ static int yt8521_probe(struct phy_devic - return -EINVAL; - } - } else if (phydev->drv->phy_id == PHY_ID_YT8531S) { -- return 0; -+ switch (freq) { -+ case YTPHY_DTS_OUTPUT_CLK_DIS: -+ mask = YT8531_SCR_SYNCE_ENABLE; -+ val = 0; -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_25M: -+ mask = YT8531_SCR_SYNCE_ENABLE | -+ YT8531_SCR_CLK_SRC_MASK | -+ YT8531_SCR_CLK_FRE_SEL_125M; -+ val = YT8531_SCR_SYNCE_ENABLE | -+ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, -+ YT8531_SCR_CLK_SRC_REF_25M); -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_125M: -+ mask = YT8531_SCR_SYNCE_ENABLE | -+ YT8531_SCR_CLK_SRC_MASK | -+ YT8531_SCR_CLK_FRE_SEL_125M; -+ val = YT8531_SCR_SYNCE_ENABLE | -+ YT8531_SCR_CLK_FRE_SEL_125M | -+ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, -+ YT8531_SCR_CLK_SRC_PLL_125M); -+ break; -+ default: -+ phydev_warn(phydev, "Freq err:%u\n", freq); -+ return -EINVAL; -+ } - } else { - phydev_warn(phydev, "PHY id err\n"); - return -EINVAL; -@@ -869,26 +892,6 @@ static int yt8521_probe(struct phy_devic - } - - /** -- * yt8531s_probe() - read chip config then set suitable polling_mode -- * @phydev: a pointer to a &struct phy_device -- * -- * returns 0 or negative errno code -- */ --static int yt8531s_probe(struct phy_device *phydev) --{ -- int ret; -- -- /* Disable SyncE clock output by default */ -- ret = ytphy_modify_ext_with_lock(phydev, YT8531S_SYNCE_CFG_REG, -- YT8531S_SCR_SYNCE_ENABLE, 0); -- if (ret < 0) -- return ret; -- -- /* same as yt8521_probe */ -- return yt8521_probe(phydev); --} -- --/** - * ytphy_utp_read_lpa() - read LPA then setup lp_advertising for utp - * @phydev: a pointer to a &struct phy_device - * -@@ -1970,7 +1973,7 @@ static struct phy_driver motorcomm_phy_d - PHY_ID_MATCH_EXACT(PHY_ID_YT8531S), - .name = "YT8531S Gigabit Ethernet", - .get_features = yt8521_get_features, -- .probe = yt8531s_probe, -+ .probe = yt8521_probe, - .read_page = yt8521_read_page, - .write_page = yt8521_write_page, - .get_wol = ytphy_get_wol, diff --git a/target/linux/rockchip/patches-5.15/011-10-v6.3-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch b/target/linux/rockchip/patches-5.15/011-10-v6.3-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch deleted file mode 100644 index 24605b85d6..0000000000 --- a/target/linux/rockchip/patches-5.15/011-10-v6.3-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch +++ /dev/null @@ -1,302 +0,0 @@ -From 4ac94f728a588e7096dd5010cd7141a309ea7805 Mon Sep 17 00:00:00 2001 -From: Frank Sae -Date: Thu, 2 Feb 2023 11:00:37 +0800 -Subject: [PATCH] net: phy: Add driver for Motorcomm yt8531 gigabit ethernet - phy - -Add a driver for the motorcomm yt8531 gigabit ethernet phy. We have - verified the driver on AM335x platform with yt8531 board. On the - board, yt8531 gigabit ethernet phy works in utp mode, RGMII - interface, supports 1000M/100M/10M speeds, and wol(magic package). - -Signed-off-by: Frank Sae -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/Kconfig | 2 +- - drivers/net/phy/motorcomm.c | 208 +++++++++++++++++++++++++++++++++++- - 2 files changed, 207 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -319,7 +319,7 @@ config MOTORCOMM_PHY - tristate "Motorcomm PHYs" - help - Enables support for Motorcomm network PHYs. -- Currently supports the YT8511, YT8521, YT8531S Gigabit Ethernet PHYs. -+ Currently supports YT85xx Gigabit Ethernet PHYs. - - config NATIONAL_PHY - tristate "National Semiconductor PHYs" ---- a/drivers/net/phy/motorcomm.c -+++ b/drivers/net/phy/motorcomm.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0+ - /* -- * Motorcomm 8511/8521/8531S PHY driver. -+ * Motorcomm 8511/8521/8531/8531S PHY driver. - * - * Author: Peter Geis - * Author: Frank -@@ -14,6 +14,7 @@ - - #define PHY_ID_YT8511 0x0000010a - #define PHY_ID_YT8521 0x0000011a -+#define PHY_ID_YT8531 0x4f51e91b - #define PHY_ID_YT8531S 0x4f51e91a - - /* YT8521/YT8531S Register Overview -@@ -517,6 +518,61 @@ err_restore_page: - return phy_restore_page(phydev, old_page, ret); - } - -+static int yt8531_set_wol(struct phy_device *phydev, -+ struct ethtool_wolinfo *wol) -+{ -+ const u16 mac_addr_reg[] = { -+ YTPHY_WOL_MACADDR2_REG, -+ YTPHY_WOL_MACADDR1_REG, -+ YTPHY_WOL_MACADDR0_REG, -+ }; -+ const u8 *mac_addr; -+ u16 mask, val; -+ int ret; -+ u8 i; -+ -+ if (wol->wolopts & WAKE_MAGIC) { -+ mac_addr = phydev->attached_dev->dev_addr; -+ -+ /* Store the device address for the magic packet */ -+ for (i = 0; i < 3; i++) { -+ ret = ytphy_write_ext_with_lock(phydev, mac_addr_reg[i], -+ ((mac_addr[i * 2] << 8)) | -+ (mac_addr[i * 2 + 1])); -+ if (ret < 0) -+ return ret; -+ } -+ -+ /* Enable WOL feature */ -+ mask = YTPHY_WCR_PULSE_WIDTH_MASK | YTPHY_WCR_INTR_SEL; -+ val = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL; -+ val |= YTPHY_WCR_TYPE_PULSE | YTPHY_WCR_PULSE_WIDTH_672MS; -+ ret = ytphy_modify_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG, -+ mask, val); -+ if (ret < 0) -+ return ret; -+ -+ /* Enable WOL interrupt */ -+ ret = phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG, 0, -+ YTPHY_IER_WOL); -+ if (ret < 0) -+ return ret; -+ } else { -+ /* Disable WOL feature */ -+ mask = YTPHY_WCR_ENABLE | YTPHY_WCR_INTR_SEL; -+ ret = ytphy_modify_ext_with_lock(phydev, YTPHY_WOL_CONFIG_REG, -+ mask, 0); -+ -+ /* Disable WOL interrupt */ -+ ret = phy_modify(phydev, YTPHY_INTERRUPT_ENABLE_REG, -+ YTPHY_IER_WOL, 0); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ - static int yt8511_read_page(struct phy_device *phydev) - { - return __phy_read(phydev, YT8511_PAGE_SELECT); -@@ -767,6 +823,17 @@ static int ytphy_rgmii_clk_delay_config( - return ytphy_modify_ext(phydev, YT8521_RGMII_CONFIG1_REG, mask, val); - } - -+static int ytphy_rgmii_clk_delay_config_with_lock(struct phy_device *phydev) -+{ -+ int ret; -+ -+ phy_lock_mdio_bus(phydev); -+ ret = ytphy_rgmii_clk_delay_config(phydev); -+ phy_unlock_mdio_bus(phydev); -+ -+ return ret; -+} -+ - /** - * yt8521_probe() - read chip config then set suitable polling_mode - * @phydev: a pointer to a &struct phy_device -@@ -891,6 +958,43 @@ static int yt8521_probe(struct phy_devic - val); - } - -+static int yt8531_probe(struct phy_device *phydev) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ u16 mask, val; -+ u32 freq; -+ -+ if (of_property_read_u32(node, "motorcomm,clk-out-frequency-hz-hz", &freq)) -+ freq = YTPHY_DTS_OUTPUT_CLK_DIS; -+ -+ switch (freq) { -+ case YTPHY_DTS_OUTPUT_CLK_DIS: -+ mask = YT8531_SCR_SYNCE_ENABLE; -+ val = 0; -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_25M: -+ mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK | -+ YT8531_SCR_CLK_FRE_SEL_125M; -+ val = YT8531_SCR_SYNCE_ENABLE | -+ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, -+ YT8531_SCR_CLK_SRC_REF_25M); -+ break; -+ case YTPHY_DTS_OUTPUT_CLK_125M: -+ mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK | -+ YT8531_SCR_CLK_FRE_SEL_125M; -+ val = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_FRE_SEL_125M | -+ FIELD_PREP(YT8531_SCR_CLK_SRC_MASK, -+ YT8531_SCR_CLK_SRC_PLL_125M); -+ break; -+ default: -+ phydev_warn(phydev, "Freq err:%u\n", freq); -+ return -EINVAL; -+ } -+ -+ return ytphy_modify_ext_with_lock(phydev, YTPHY_SYNCE_CFG_REG, mask, -+ val); -+} -+ - /** - * ytphy_utp_read_lpa() - read LPA then setup lp_advertising for utp - * @phydev: a pointer to a &struct phy_device -@@ -1387,6 +1491,94 @@ err_restore_page: - return phy_restore_page(phydev, old_page, ret); - } - -+static int yt8531_config_init(struct phy_device *phydev) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ int ret; -+ -+ ret = ytphy_rgmii_clk_delay_config_with_lock(phydev); -+ if (ret < 0) -+ return ret; -+ -+ if (of_property_read_bool(node, "motorcomm,auto-sleep-disabled")) { -+ /* disable auto sleep */ -+ ret = ytphy_modify_ext_with_lock(phydev, -+ YT8521_EXTREG_SLEEP_CONTROL1_REG, -+ YT8521_ESC1R_SLEEP_SW, 0); -+ if (ret < 0) -+ return ret; -+ } -+ -+ if (of_property_read_bool(node, "motorcomm,keep-pll-enabled")) { -+ /* enable RXC clock when no wire plug */ -+ ret = ytphy_modify_ext_with_lock(phydev, -+ YT8521_CLOCK_GATING_REG, -+ YT8521_CGR_RX_CLK_EN, 0); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * yt8531_link_change_notify() - Adjust the tx clock direction according to -+ * the current speed and dts config. -+ * @phydev: a pointer to a &struct phy_device -+ * -+ * NOTE: This function is only used to adapt to VF2 with JH7110 SoC. Please -+ * keep "motorcomm,tx-clk-adj-enabled" not exist in dts when the soc is not -+ * JH7110. -+ */ -+static void yt8531_link_change_notify(struct phy_device *phydev) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ bool tx_clk_adj_enabled = false; -+ bool tx_clk_1000_inverted; -+ bool tx_clk_100_inverted; -+ bool tx_clk_10_inverted; -+ u16 val = 0; -+ int ret; -+ -+ if (of_property_read_bool(node, "motorcomm,tx-clk-adj-enabled")) -+ tx_clk_adj_enabled = true; -+ -+ if (!tx_clk_adj_enabled) -+ return; -+ -+ if (of_property_read_bool(node, "motorcomm,tx-clk-10-inverted")) -+ tx_clk_10_inverted = true; -+ if (of_property_read_bool(node, "motorcomm,tx-clk-100-inverted")) -+ tx_clk_100_inverted = true; -+ if (of_property_read_bool(node, "motorcomm,tx-clk-1000-inverted")) -+ tx_clk_1000_inverted = true; -+ -+ if (phydev->speed < 0) -+ return; -+ -+ switch (phydev->speed) { -+ case SPEED_1000: -+ if (tx_clk_1000_inverted) -+ val = YT8521_RC1R_TX_CLK_SEL_INVERTED; -+ break; -+ case SPEED_100: -+ if (tx_clk_100_inverted) -+ val = YT8521_RC1R_TX_CLK_SEL_INVERTED; -+ break; -+ case SPEED_10: -+ if (tx_clk_10_inverted) -+ val = YT8521_RC1R_TX_CLK_SEL_INVERTED; -+ break; -+ default: -+ return; -+ } -+ -+ ret = ytphy_modify_ext_with_lock(phydev, YT8521_RGMII_CONFIG1_REG, -+ YT8521_RC1R_TX_CLK_SEL_INVERTED, val); -+ if (ret < 0) -+ phydev_warn(phydev, "Modify TX_CLK_SEL err:%d\n", ret); -+} -+ - /** - * yt8521_prepare_fiber_features() - A small helper function that setup - * fiber's features. -@@ -1970,6 +2162,17 @@ static struct phy_driver motorcomm_phy_d - .resume = yt8521_resume, - }, - { -+ PHY_ID_MATCH_EXACT(PHY_ID_YT8531), -+ .name = "YT8531 Gigabit Ethernet", -+ .probe = yt8531_probe, -+ .config_init = yt8531_config_init, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .get_wol = ytphy_get_wol, -+ .set_wol = yt8531_set_wol, -+ .link_change_notify = yt8531_link_change_notify, -+ }, -+ { - PHY_ID_MATCH_EXACT(PHY_ID_YT8531S), - .name = "YT8531S Gigabit Ethernet", - .get_features = yt8521_get_features, -@@ -1990,7 +2193,7 @@ static struct phy_driver motorcomm_phy_d - - module_phy_driver(motorcomm_phy_drvs); - --MODULE_DESCRIPTION("Motorcomm 8511/8521/8531S PHY driver"); -+MODULE_DESCRIPTION("Motorcomm 8511/8521/8531/8531S PHY driver"); - MODULE_AUTHOR("Peter Geis"); - MODULE_AUTHOR("Frank"); - MODULE_LICENSE("GPL"); -@@ -1998,6 +2201,7 @@ MODULE_LICENSE("GPL"); - static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = { - { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, - { PHY_ID_MATCH_EXACT(PHY_ID_YT8521) }, -+ { PHY_ID_MATCH_EXACT(PHY_ID_YT8531) }, - { PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) }, - { /* sentinel */ } - };