+++ /dev/null
-From foo@baz Mon Apr 10 17:43:56 CEST 2017
-From: alexander.levin@verizon.com
-Date: Tue, 4 Apr 2017 19:32:23 +0000
-Subject: amd-xgbe: Prepare for working with more than one type of phy
-To: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
-Cc: "stable@vger.kernel.org" <stable@vger.kernel.org>
-Message-ID: <20170404193158.19041-57-alexander.levin@verizon.com>
-
-From: "Lendacky, Thomas" <Thomas.Lendacky@amd.com>
-
-[ Upstream commit e57f7a3feaef0e9e196801f1625bca1337405421 ]
-
-Prepare the code to be able to work with more than one type of phy by
-adding additional callable functions into the phy interface and removing
-phy specific settings/functions from non-phy related files.
-
-Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/net/ethernet/amd/xgbe/Makefile | 3
- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 58 -
- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 6
- drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 19
- drivers/net/ethernet/amd/xgbe/xgbe-main.c | 214 ++-----
- drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 543 +++++------------
- drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c | 821 +++++++++++++++++++++++++++
- drivers/net/ethernet/amd/xgbe/xgbe.h | 130 ++--
- 8 files changed, 1137 insertions(+), 657 deletions(-)
- create mode 100644 drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c
-
---- a/drivers/net/ethernet/amd/xgbe/Makefile
-+++ b/drivers/net/ethernet/amd/xgbe/Makefile
-@@ -2,7 +2,8 @@ obj-$(CONFIG_AMD_XGBE) += amd-xgbe.o
-
- amd-xgbe-objs := xgbe-main.o xgbe-drv.o xgbe-dev.o \
- xgbe-desc.o xgbe-ethtool.o xgbe-mdio.o \
-- xgbe-ptp.o
-+ xgbe-ptp.o \
-+ xgbe-phy-v1.o
-
- amd-xgbe-$(CONFIG_AMD_XGBE_DCB) += xgbe-dcb.o
- amd-xgbe-$(CONFIG_DEBUG_FS) += xgbe-debugfs.o
---- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
-+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
-@@ -704,32 +704,26 @@ static void xgbe_enable_mac_interrupts(s
- XGMAC_IOWRITE_BITS(pdata, MMC_TIER, ALL_INTERRUPTS, 0xffffffff);
- }
-
--static int xgbe_set_gmii_speed(struct xgbe_prv_data *pdata)
-+static int xgbe_set_speed(struct xgbe_prv_data *pdata, int speed)
- {
-- if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0x3)
-- return 0;
--
-- XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x3);
--
-- return 0;
--}
--
--static int xgbe_set_gmii_2500_speed(struct xgbe_prv_data *pdata)
--{
-- if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0x2)
-- return 0;
-+ unsigned int ss;
-
-- XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x2);
--
-- return 0;
--}
--
--static int xgbe_set_xgmii_speed(struct xgbe_prv_data *pdata)
--{
-- if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0)
-- return 0;
-+ switch (speed) {
-+ case SPEED_1000:
-+ ss = 0x03;
-+ break;
-+ case SPEED_2500:
-+ ss = 0x02;
-+ break;
-+ case SPEED_10000:
-+ ss = 0x00;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-
-- XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0);
-+ if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) != ss)
-+ XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, ss);
-
- return 0;
- }
-@@ -2177,19 +2171,7 @@ static void xgbe_config_jumbo_enable(str
-
- static void xgbe_config_mac_speed(struct xgbe_prv_data *pdata)
- {
-- switch (pdata->phy_speed) {
-- case SPEED_10000:
-- xgbe_set_xgmii_speed(pdata);
-- break;
--
-- case SPEED_2500:
-- xgbe_set_gmii_2500_speed(pdata);
-- break;
--
-- case SPEED_1000:
-- xgbe_set_gmii_speed(pdata);
-- break;
-- }
-+ xgbe_set_speed(pdata, pdata->phy_speed);
- }
-
- static void xgbe_config_checksum_offload(struct xgbe_prv_data *pdata)
-@@ -2905,9 +2887,7 @@ void xgbe_init_function_ptrs_dev(struct
- hw_if->read_mmd_regs = xgbe_read_mmd_regs;
- hw_if->write_mmd_regs = xgbe_write_mmd_regs;
-
-- hw_if->set_gmii_speed = xgbe_set_gmii_speed;
-- hw_if->set_gmii_2500_speed = xgbe_set_gmii_2500_speed;
-- hw_if->set_xgmii_speed = xgbe_set_xgmii_speed;
-+ hw_if->set_speed = xgbe_set_speed;
-
- hw_if->enable_tx = xgbe_enable_tx;
- hw_if->disable_tx = xgbe_disable_tx;
---- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
-+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
-@@ -783,7 +783,7 @@ static void xgbe_free_rx_data(struct xgb
- DBGPR("<--xgbe_free_rx_data\n");
- }
-
--static int xgbe_phy_init(struct xgbe_prv_data *pdata)
-+static int xgbe_phy_reset(struct xgbe_prv_data *pdata)
- {
- pdata->phy_link = -1;
- pdata->phy_speed = SPEED_UNKNOWN;
-@@ -1297,8 +1297,8 @@ static int xgbe_open(struct net_device *
-
- DBGPR("-->xgbe_open\n");
-
-- /* Initialize the phy */
-- ret = xgbe_phy_init(pdata);
-+ /* Reset the phy settings */
-+ ret = xgbe_phy_reset(pdata);
- if (ret)
- return ret;
-
---- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
-+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
-@@ -316,24 +316,7 @@ static int xgbe_set_settings(struct net_
- }
-
- if (cmd->autoneg == AUTONEG_DISABLE) {
-- switch (speed) {
-- case SPEED_10000:
-- break;
-- case SPEED_2500:
-- if (pdata->speed_set != XGBE_SPEEDSET_2500_10000) {
-- netdev_err(netdev, "unsupported speed %u\n",
-- speed);
-- return -EINVAL;
-- }
-- break;
-- case SPEED_1000:
-- if (pdata->speed_set != XGBE_SPEEDSET_1000_10000) {
-- netdev_err(netdev, "unsupported speed %u\n",
-- speed);
-- return -EINVAL;
-- }
-- break;
-- default:
-+ if (!pdata->phy_if.phy_valid_speed(pdata, speed)) {
- netdev_err(netdev, "unsupported speed %u\n", speed);
- return -EINVAL;
- }
---- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
-+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
-@@ -125,6 +125,7 @@
- #include <linux/of_net.h>
- #include <linux/of_address.h>
- #include <linux/of_platform.h>
-+#include <linux/of_device.h>
- #include <linux/clk.h>
- #include <linux/property.h>
- #include <linux/acpi.h>
-@@ -145,42 +146,6 @@ MODULE_PARM_DESC(debug, " Network interf
- static const u32 default_msg_level = (NETIF_MSG_LINK | NETIF_MSG_IFDOWN |
- NETIF_MSG_IFUP);
-
--static const u32 xgbe_serdes_blwc[] = {
-- XGBE_SPEED_1000_BLWC,
-- XGBE_SPEED_2500_BLWC,
-- XGBE_SPEED_10000_BLWC,
--};
--
--static const u32 xgbe_serdes_cdr_rate[] = {
-- XGBE_SPEED_1000_CDR,
-- XGBE_SPEED_2500_CDR,
-- XGBE_SPEED_10000_CDR,
--};
--
--static const u32 xgbe_serdes_pq_skew[] = {
-- XGBE_SPEED_1000_PQ,
-- XGBE_SPEED_2500_PQ,
-- XGBE_SPEED_10000_PQ,
--};
--
--static const u32 xgbe_serdes_tx_amp[] = {
-- XGBE_SPEED_1000_TXAMP,
-- XGBE_SPEED_2500_TXAMP,
-- XGBE_SPEED_10000_TXAMP,
--};
--
--static const u32 xgbe_serdes_dfe_tap_cfg[] = {
-- XGBE_SPEED_1000_DFE_TAP_CONFIG,
-- XGBE_SPEED_2500_DFE_TAP_CONFIG,
-- XGBE_SPEED_10000_DFE_TAP_CONFIG,
--};
--
--static const u32 xgbe_serdes_dfe_tap_ena[] = {
-- XGBE_SPEED_1000_DFE_TAP_ENABLE,
-- XGBE_SPEED_2500_DFE_TAP_ENABLE,
-- XGBE_SPEED_10000_DFE_TAP_ENABLE,
--};
--
- static void xgbe_default_config(struct xgbe_prv_data *pdata)
- {
- DBGPR("-->xgbe_default_config\n");
-@@ -207,9 +172,22 @@ static void xgbe_init_all_fptrs(struct x
- xgbe_init_function_ptrs_dev(&pdata->hw_if);
- xgbe_init_function_ptrs_phy(&pdata->phy_if);
- xgbe_init_function_ptrs_desc(&pdata->desc_if);
-+
-+ pdata->vdata->init_function_ptrs_phy_impl(&pdata->phy_if);
- }
-
- #ifdef CONFIG_ACPI
-+static const struct acpi_device_id xgbe_acpi_match[];
-+
-+static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata)
-+{
-+ const struct acpi_device_id *id;
-+
-+ id = acpi_match_device(xgbe_acpi_match, pdata->dev);
-+
-+ return id ? (struct xgbe_version_data *)id->driver_data : NULL;
-+}
-+
- static int xgbe_acpi_support(struct xgbe_prv_data *pdata)
- {
- struct device *dev = pdata->dev;
-@@ -237,6 +215,11 @@ static int xgbe_acpi_support(struct xgbe
- return 0;
- }
- #else /* CONFIG_ACPI */
-+static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata)
-+{
-+ return NULL;
-+}
-+
- static int xgbe_acpi_support(struct xgbe_prv_data *pdata)
- {
- return -EINVAL;
-@@ -244,6 +227,17 @@ static int xgbe_acpi_support(struct xgbe
- #endif /* CONFIG_ACPI */
-
- #ifdef CONFIG_OF
-+static const struct of_device_id xgbe_of_match[];
-+
-+static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata)
-+{
-+ const struct of_device_id *id;
-+
-+ id = of_match_device(xgbe_of_match, pdata->dev);
-+
-+ return id ? (struct xgbe_version_data *)id->data : NULL;
-+}
-+
- static int xgbe_of_support(struct xgbe_prv_data *pdata)
- {
- struct device *dev = pdata->dev;
-@@ -292,6 +286,11 @@ static struct platform_device *xgbe_of_g
- return phy_pdev;
- }
- #else /* CONFIG_OF */
-+static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata)
-+{
-+ return NULL;
-+}
-+
- static int xgbe_of_support(struct xgbe_prv_data *pdata)
- {
- return -EINVAL;
-@@ -333,11 +332,17 @@ static struct platform_device *xgbe_get_
- return phy_pdev;
- }
-
-+static struct xgbe_version_data *xgbe_get_vdata(struct xgbe_prv_data *pdata)
-+{
-+ return pdata->use_acpi ? xgbe_acpi_vdata(pdata)
-+ : xgbe_of_vdata(pdata);
-+}
-+
- static int xgbe_probe(struct platform_device *pdev)
- {
- struct xgbe_prv_data *pdata;
- struct net_device *netdev;
-- struct device *dev = &pdev->dev, *phy_dev;
-+ struct device *dev = &pdev->dev;
- struct platform_device *phy_pdev;
- struct resource *res;
- const char *phy_mode;
-@@ -374,13 +379,17 @@ static int xgbe_probe(struct platform_de
- /* Check if we should use ACPI or DT */
- pdata->use_acpi = dev->of_node ? 0 : 1;
-
-+ /* Get the version data */
-+ pdata->vdata = xgbe_get_vdata(pdata);
-+
- phy_pdev = xgbe_get_phy_pdev(pdata);
- if (!phy_pdev) {
- dev_err(dev, "unable to obtain phy device\n");
- ret = -EINVAL;
- goto err_phydev;
- }
-- phy_dev = &phy_pdev->dev;
-+ pdata->phy_pdev = phy_pdev;
-+ pdata->phy_dev = &phy_pdev->dev;
-
- if (pdev == phy_pdev) {
- /* New style device tree or ACPI:
-@@ -492,115 +501,6 @@ static int xgbe_probe(struct platform_de
- if (device_property_present(dev, XGBE_DMA_IRQS_PROPERTY))
- pdata->per_channel_irq = 1;
-
-- /* Retrieve the PHY speedset */
-- ret = device_property_read_u32(phy_dev, XGBE_SPEEDSET_PROPERTY,
-- &pdata->speed_set);
-- if (ret) {
-- dev_err(dev, "invalid %s property\n", XGBE_SPEEDSET_PROPERTY);
-- goto err_io;
-- }
--
-- switch (pdata->speed_set) {
-- case XGBE_SPEEDSET_1000_10000:
-- case XGBE_SPEEDSET_2500_10000:
-- break;
-- default:
-- dev_err(dev, "invalid %s property\n", XGBE_SPEEDSET_PROPERTY);
-- ret = -EINVAL;
-- goto err_io;
-- }
--
-- /* Retrieve the PHY configuration properties */
-- if (device_property_present(phy_dev, XGBE_BLWC_PROPERTY)) {
-- ret = device_property_read_u32_array(phy_dev,
-- XGBE_BLWC_PROPERTY,
-- pdata->serdes_blwc,
-- XGBE_SPEEDS);
-- if (ret) {
-- dev_err(dev, "invalid %s property\n",
-- XGBE_BLWC_PROPERTY);
-- goto err_io;
-- }
-- } else {
-- memcpy(pdata->serdes_blwc, xgbe_serdes_blwc,
-- sizeof(pdata->serdes_blwc));
-- }
--
-- if (device_property_present(phy_dev, XGBE_CDR_RATE_PROPERTY)) {
-- ret = device_property_read_u32_array(phy_dev,
-- XGBE_CDR_RATE_PROPERTY,
-- pdata->serdes_cdr_rate,
-- XGBE_SPEEDS);
-- if (ret) {
-- dev_err(dev, "invalid %s property\n",
-- XGBE_CDR_RATE_PROPERTY);
-- goto err_io;
-- }
-- } else {
-- memcpy(pdata->serdes_cdr_rate, xgbe_serdes_cdr_rate,
-- sizeof(pdata->serdes_cdr_rate));
-- }
--
-- if (device_property_present(phy_dev, XGBE_PQ_SKEW_PROPERTY)) {
-- ret = device_property_read_u32_array(phy_dev,
-- XGBE_PQ_SKEW_PROPERTY,
-- pdata->serdes_pq_skew,
-- XGBE_SPEEDS);
-- if (ret) {
-- dev_err(dev, "invalid %s property\n",
-- XGBE_PQ_SKEW_PROPERTY);
-- goto err_io;
-- }
-- } else {
-- memcpy(pdata->serdes_pq_skew, xgbe_serdes_pq_skew,
-- sizeof(pdata->serdes_pq_skew));
-- }
--
-- if (device_property_present(phy_dev, XGBE_TX_AMP_PROPERTY)) {
-- ret = device_property_read_u32_array(phy_dev,
-- XGBE_TX_AMP_PROPERTY,
-- pdata->serdes_tx_amp,
-- XGBE_SPEEDS);
-- if (ret) {
-- dev_err(dev, "invalid %s property\n",
-- XGBE_TX_AMP_PROPERTY);
-- goto err_io;
-- }
-- } else {
-- memcpy(pdata->serdes_tx_amp, xgbe_serdes_tx_amp,
-- sizeof(pdata->serdes_tx_amp));
-- }
--
-- if (device_property_present(phy_dev, XGBE_DFE_CFG_PROPERTY)) {
-- ret = device_property_read_u32_array(phy_dev,
-- XGBE_DFE_CFG_PROPERTY,
-- pdata->serdes_dfe_tap_cfg,
-- XGBE_SPEEDS);
-- if (ret) {
-- dev_err(dev, "invalid %s property\n",
-- XGBE_DFE_CFG_PROPERTY);
-- goto err_io;
-- }
-- } else {
-- memcpy(pdata->serdes_dfe_tap_cfg, xgbe_serdes_dfe_tap_cfg,
-- sizeof(pdata->serdes_dfe_tap_cfg));
-- }
--
-- if (device_property_present(phy_dev, XGBE_DFE_ENA_PROPERTY)) {
-- ret = device_property_read_u32_array(phy_dev,
-- XGBE_DFE_ENA_PROPERTY,
-- pdata->serdes_dfe_tap_ena,
-- XGBE_SPEEDS);
-- if (ret) {
-- dev_err(dev, "invalid %s property\n",
-- XGBE_DFE_ENA_PROPERTY);
-- goto err_io;
-- }
-- } else {
-- memcpy(pdata->serdes_dfe_tap_ena, xgbe_serdes_dfe_tap_ena,
-- sizeof(pdata->serdes_dfe_tap_ena));
-- }
--
- /* Obtain device settings unique to ACPI/OF */
- if (pdata->use_acpi)
- ret = xgbe_acpi_support(pdata);
-@@ -704,7 +604,9 @@ static int xgbe_probe(struct platform_de
- XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1);
-
- /* Call MDIO/PHY initialization routine */
-- pdata->phy_if.phy_init(pdata);
-+ ret = pdata->phy_if.phy_init(pdata);
-+ if (ret)
-+ goto err_io;
-
- /* Set device operations */
- netdev->netdev_ops = xgbe_get_netdev_ops();
-@@ -777,8 +679,6 @@ static int xgbe_probe(struct platform_de
-
- xgbe_debugfs_init(pdata);
-
-- platform_device_put(phy_pdev);
--
- netdev_notice(netdev, "net device enabled\n");
-
- DBGPR("<-- xgbe_probe\n");
-@@ -814,6 +714,8 @@ static int xgbe_remove(struct platform_d
-
- xgbe_ptp_unregister(pdata);
-
-+ pdata->phy_if.phy_exit(pdata);
-+
- flush_workqueue(pdata->an_workqueue);
- destroy_workqueue(pdata->an_workqueue);
-
-@@ -822,6 +724,8 @@ static int xgbe_remove(struct platform_d
-
- unregister_netdev(netdev);
-
-+ platform_device_put(pdata->phy_pdev);
-+
- free_netdev(netdev);
-
- DBGPR("<--xgbe_remove\n");
-@@ -876,9 +780,14 @@ static int xgbe_resume(struct device *de
- }
- #endif /* CONFIG_PM_SLEEP */
-
-+static const struct xgbe_version_data xgbe_v1 = {
-+ .init_function_ptrs_phy_impl = xgbe_init_function_ptrs_phy_v1,
-+};
-+
- #ifdef CONFIG_ACPI
- static const struct acpi_device_id xgbe_acpi_match[] = {
-- { "AMDI8001", 0 },
-+ { .id = "AMDI8001",
-+ .driver_data = (kernel_ulong_t)&xgbe_v1 },
- {},
- };
-
-@@ -887,7 +796,8 @@ MODULE_DEVICE_TABLE(acpi, xgbe_acpi_matc
-
- #ifdef CONFIG_OF
- static const struct of_device_id xgbe_of_match[] = {
-- { .compatible = "amd,xgbe-seattle-v1a", },
-+ { .compatible = "amd,xgbe-seattle-v1a",
-+ .data = &xgbe_v1 },
- {},
- };
-
---- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
-+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
-@@ -145,280 +145,91 @@ static void xgbe_an_disable_kr_training(
- XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
- }
-
--static void xgbe_pcs_power_cycle(struct xgbe_prv_data *pdata)
-+static void xgbe_kr_mode(struct xgbe_prv_data *pdata)
- {
-- unsigned int reg;
--
-- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
--
-- reg |= MDIO_CTRL1_LPOWER;
-- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
--
-- usleep_range(75, 100);
--
-- reg &= ~MDIO_CTRL1_LPOWER;
-- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
--}
--
--static void xgbe_serdes_start_ratechange(struct xgbe_prv_data *pdata)
--{
-- /* Assert Rx and Tx ratechange */
-- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 1);
--}
--
--static void xgbe_serdes_complete_ratechange(struct xgbe_prv_data *pdata)
--{
-- unsigned int wait;
-- u16 status;
--
-- /* Release Rx and Tx ratechange */
-- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 0);
--
-- /* Wait for Rx and Tx ready */
-- wait = XGBE_RATECHANGE_COUNT;
-- while (wait--) {
-- usleep_range(50, 75);
--
-- status = XSIR0_IOREAD(pdata, SIR0_STATUS);
-- if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) &&
-- XSIR_GET_BITS(status, SIR0_STATUS, TX_READY))
-- goto rx_reset;
-- }
--
-- netif_dbg(pdata, link, pdata->netdev, "SerDes rx/tx not ready (%#hx)\n",
-- status);
--
--rx_reset:
-- /* Perform Rx reset for the DFE changes */
-- XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 0);
-- XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 1);
--}
--
--static void xgbe_xgmii_mode(struct xgbe_prv_data *pdata)
--{
-- unsigned int reg;
--
- /* Enable KR training */
- xgbe_an_enable_kr_training(pdata);
-
- /* Set MAC to 10G speed */
-- pdata->hw_if.set_xgmii_speed(pdata);
--
-- /* Set PCS to KR/10G speed */
-- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
-- reg &= ~MDIO_PCS_CTRL2_TYPE;
-- reg |= MDIO_PCS_CTRL2_10GBR;
-- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
--
-- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-- reg &= ~MDIO_CTRL1_SPEEDSEL;
-- reg |= MDIO_CTRL1_SPEED10G;
-- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
--
-- xgbe_pcs_power_cycle(pdata);
--
-- /* Set SerDes to 10G speed */
-- xgbe_serdes_start_ratechange(pdata);
--
-- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_10000_RATE);
-- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_10000_WORD);
-- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_10000_PLL);
--
-- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
-- pdata->serdes_cdr_rate[XGBE_SPEED_10000]);
-- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
-- pdata->serdes_tx_amp[XGBE_SPEED_10000]);
-- XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
-- pdata->serdes_blwc[XGBE_SPEED_10000]);
-- XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
-- pdata->serdes_pq_skew[XGBE_SPEED_10000]);
-- XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
-- pdata->serdes_dfe_tap_cfg[XGBE_SPEED_10000]);
-- XRXTX_IOWRITE(pdata, RXTX_REG22,
-- pdata->serdes_dfe_tap_ena[XGBE_SPEED_10000]);
--
-- xgbe_serdes_complete_ratechange(pdata);
-+ pdata->hw_if.set_speed(pdata, SPEED_10000);
-
-- netif_dbg(pdata, link, pdata->netdev, "10GbE KR mode set\n");
-+ /* Call PHY implementation support to complete rate change */
-+ pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KR);
- }
-
--static void xgbe_gmii_2500_mode(struct xgbe_prv_data *pdata)
-+static void xgbe_kx_2500_mode(struct xgbe_prv_data *pdata)
- {
-- unsigned int reg;
--
- /* Disable KR training */
- xgbe_an_disable_kr_training(pdata);
-
- /* Set MAC to 2.5G speed */
-- pdata->hw_if.set_gmii_2500_speed(pdata);
--
-- /* Set PCS to KX/1G speed */
-- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
-- reg &= ~MDIO_PCS_CTRL2_TYPE;
-- reg |= MDIO_PCS_CTRL2_10GBX;
-- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
--
-- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-- reg &= ~MDIO_CTRL1_SPEEDSEL;
-- reg |= MDIO_CTRL1_SPEED1G;
-- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
--
-- xgbe_pcs_power_cycle(pdata);
--
-- /* Set SerDes to 2.5G speed */
-- xgbe_serdes_start_ratechange(pdata);
--
-- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_2500_RATE);
-- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_2500_WORD);
-- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_2500_PLL);
--
-- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
-- pdata->serdes_cdr_rate[XGBE_SPEED_2500]);
-- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
-- pdata->serdes_tx_amp[XGBE_SPEED_2500]);
-- XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
-- pdata->serdes_blwc[XGBE_SPEED_2500]);
-- XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
-- pdata->serdes_pq_skew[XGBE_SPEED_2500]);
-- XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
-- pdata->serdes_dfe_tap_cfg[XGBE_SPEED_2500]);
-- XRXTX_IOWRITE(pdata, RXTX_REG22,
-- pdata->serdes_dfe_tap_ena[XGBE_SPEED_2500]);
--
-- xgbe_serdes_complete_ratechange(pdata);
-+ pdata->hw_if.set_speed(pdata, SPEED_2500);
-
-- netif_dbg(pdata, link, pdata->netdev, "2.5GbE KX mode set\n");
-+ /* Call PHY implementation support to complete rate change */
-+ pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_2500);
- }
-
--static void xgbe_gmii_mode(struct xgbe_prv_data *pdata)
-+static void xgbe_kx_1000_mode(struct xgbe_prv_data *pdata)
- {
-- unsigned int reg;
--
- /* Disable KR training */
- xgbe_an_disable_kr_training(pdata);
-
- /* Set MAC to 1G speed */
-- pdata->hw_if.set_gmii_speed(pdata);
--
-- /* Set PCS to KX/1G speed */
-- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
-- reg &= ~MDIO_PCS_CTRL2_TYPE;
-- reg |= MDIO_PCS_CTRL2_10GBX;
-- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
--
-- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-- reg &= ~MDIO_CTRL1_SPEEDSEL;
-- reg |= MDIO_CTRL1_SPEED1G;
-- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
--
-- xgbe_pcs_power_cycle(pdata);
--
-- /* Set SerDes to 1G speed */
-- xgbe_serdes_start_ratechange(pdata);
--
-- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE);
-- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD);
-- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL);
--
-- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
-- pdata->serdes_cdr_rate[XGBE_SPEED_1000]);
-- XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
-- pdata->serdes_tx_amp[XGBE_SPEED_1000]);
-- XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
-- pdata->serdes_blwc[XGBE_SPEED_1000]);
-- XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
-- pdata->serdes_pq_skew[XGBE_SPEED_1000]);
-- XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
-- pdata->serdes_dfe_tap_cfg[XGBE_SPEED_1000]);
-- XRXTX_IOWRITE(pdata, RXTX_REG22,
-- pdata->serdes_dfe_tap_ena[XGBE_SPEED_1000]);
-+ pdata->hw_if.set_speed(pdata, SPEED_1000);
-
-- xgbe_serdes_complete_ratechange(pdata);
--
-- netif_dbg(pdata, link, pdata->netdev, "1GbE KX mode set\n");
-+ /* Call PHY implementation support to complete rate change */
-+ pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_1000);
- }
-
--static void xgbe_cur_mode(struct xgbe_prv_data *pdata,
-- enum xgbe_mode *mode)
-+static enum xgbe_mode xgbe_cur_mode(struct xgbe_prv_data *pdata)
- {
-- unsigned int reg;
--
-- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
-- if ((reg & MDIO_PCS_CTRL2_TYPE) == MDIO_PCS_CTRL2_10GBR)
-- *mode = XGBE_MODE_KR;
-- else
-- *mode = XGBE_MODE_KX;
-+ return pdata->phy_if.phy_impl.cur_mode(pdata);
- }
-
- static bool xgbe_in_kr_mode(struct xgbe_prv_data *pdata)
- {
-- enum xgbe_mode mode;
--
-- xgbe_cur_mode(pdata, &mode);
--
-- return (mode == XGBE_MODE_KR);
-+ return (xgbe_cur_mode(pdata) == XGBE_MODE_KR);
- }
-
--static void xgbe_switch_mode(struct xgbe_prv_data *pdata)
-+static void xgbe_change_mode(struct xgbe_prv_data *pdata,
-+ enum xgbe_mode mode)
- {
-- /* If we are in KR switch to KX, and vice-versa */
-- if (xgbe_in_kr_mode(pdata)) {
-- if (pdata->speed_set == XGBE_SPEEDSET_1000_10000)
-- xgbe_gmii_mode(pdata);
-- else
-- xgbe_gmii_2500_mode(pdata);
-- } else {
-- xgbe_xgmii_mode(pdata);
-+ switch (mode) {
-+ case XGBE_MODE_KX_1000:
-+ xgbe_kx_1000_mode(pdata);
-+ break;
-+ case XGBE_MODE_KX_2500:
-+ xgbe_kx_2500_mode(pdata);
-+ break;
-+ case XGBE_MODE_KR:
-+ xgbe_kr_mode(pdata);
-+ break;
-+ case XGBE_MODE_UNKNOWN:
-+ break;
-+ default:
-+ netif_dbg(pdata, link, pdata->netdev,
-+ "invalid operation mode requested (%u)\n", mode);
- }
- }
-
--static void xgbe_set_mode(struct xgbe_prv_data *pdata,
-- enum xgbe_mode mode)
--{
-- enum xgbe_mode cur_mode;
--
-- xgbe_cur_mode(pdata, &cur_mode);
-- if (mode != cur_mode)
-- xgbe_switch_mode(pdata);
--}
--
--static bool xgbe_use_xgmii_mode(struct xgbe_prv_data *pdata)
-+static void xgbe_switch_mode(struct xgbe_prv_data *pdata)
- {
-- if (pdata->phy.autoneg == AUTONEG_ENABLE) {
-- if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full)
-- return true;
-- } else {
-- if (pdata->phy.speed == SPEED_10000)
-- return true;
-- }
--
-- return false;
-+ xgbe_change_mode(pdata, pdata->phy_if.phy_impl.switch_mode(pdata));
- }
-
--static bool xgbe_use_gmii_2500_mode(struct xgbe_prv_data *pdata)
-+static void xgbe_set_mode(struct xgbe_prv_data *pdata,
-+ enum xgbe_mode mode)
- {
-- if (pdata->phy.autoneg == AUTONEG_ENABLE) {
-- if (pdata->phy.advertising & ADVERTISED_2500baseX_Full)
-- return true;
-- } else {
-- if (pdata->phy.speed == SPEED_2500)
-- return true;
-- }
-+ if (mode == xgbe_cur_mode(pdata))
-+ return;
-
-- return false;
-+ xgbe_change_mode(pdata, mode);
- }
-
--static bool xgbe_use_gmii_mode(struct xgbe_prv_data *pdata)
-+static bool xgbe_use_mode(struct xgbe_prv_data *pdata,
-+ enum xgbe_mode mode)
- {
-- if (pdata->phy.autoneg == AUTONEG_ENABLE) {
-- if (pdata->phy.advertising & ADVERTISED_1000baseKX_Full)
-- return true;
-- } else {
-- if (pdata->phy.speed == SPEED_1000)
-- return true;
-- }
--
-- return false;
-+ return pdata->phy_if.phy_impl.use_mode(pdata, mode);
- }
-
- static void xgbe_set_an(struct xgbe_prv_data *pdata, bool enable, bool restart)
-@@ -476,13 +287,15 @@ static enum xgbe_an xgbe_an_tx_training(
- /* Start KR training */
- reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
- if (reg & XGBE_KR_TRAINING_ENABLE) {
-- XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 1);
-+ if (pdata->phy_if.phy_impl.kr_training_pre)
-+ pdata->phy_if.phy_impl.kr_training_pre(pdata);
-
- reg |= XGBE_KR_TRAINING_START;
- XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL,
- reg);
-
-- XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 0);
-+ if (pdata->phy_if.phy_impl.kr_training_post)
-+ pdata->phy_if.phy_impl.kr_training_post(pdata);
-
- netif_dbg(pdata, link, pdata->netdev,
- "KR training initiated\n");
-@@ -571,7 +384,7 @@ static enum xgbe_an xgbe_an_page_receive
- }
-
- state = xgbe_in_kr_mode(pdata) ? &pdata->kr_state
-- : &pdata->kx_state;
-+ : &pdata->kx_state;
-
- switch (*state) {
- case XGBE_RX_BPA:
-@@ -907,24 +720,28 @@ static void xgbe_phy_adjust_link(struct
- xgbe_phy_print_status(pdata);
- }
-
-+static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
-+{
-+ return pdata->phy_if.phy_impl.valid_speed(pdata, speed);
-+}
-+
- static int xgbe_phy_config_fixed(struct xgbe_prv_data *pdata)
- {
-+ enum xgbe_mode mode;
-+
- netif_dbg(pdata, link, pdata->netdev, "fixed PHY configuration\n");
-
- /* Disable auto-negotiation */
- xgbe_disable_an(pdata);
-
-- /* Validate/Set specified speed */
-- switch (pdata->phy.speed) {
-- case SPEED_10000:
-- xgbe_set_mode(pdata, XGBE_MODE_KR);
-- break;
--
-- case SPEED_2500:
-- case SPEED_1000:
-- xgbe_set_mode(pdata, XGBE_MODE_KX);
-+ /* Set specified mode for specified speed */
-+ mode = pdata->phy_if.phy_impl.get_mode(pdata, pdata->phy.speed);
-+ switch (mode) {
-+ case XGBE_MODE_KX_1000:
-+ case XGBE_MODE_KX_2500:
-+ case XGBE_MODE_KR:
- break;
--
-+ case XGBE_MODE_UNKNOWN:
- default:
- return -EINVAL;
- }
-@@ -933,6 +750,8 @@ static int xgbe_phy_config_fixed(struct
- if (pdata->phy.duplex != DUPLEX_FULL)
- return -EINVAL;
-
-+ xgbe_set_mode(pdata, mode);
-+
- return 0;
- }
-
-@@ -950,11 +769,12 @@ static int __xgbe_phy_config_aneg(struct
- disable_irq(pdata->an_irq);
-
- /* Start auto-negotiation in a supported mode */
-- if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full) {
-+ if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
- xgbe_set_mode(pdata, XGBE_MODE_KR);
-- } else if ((pdata->phy.advertising & ADVERTISED_1000baseKX_Full) ||
-- (pdata->phy.advertising & ADVERTISED_2500baseX_Full)) {
-- xgbe_set_mode(pdata, XGBE_MODE_KX);
-+ } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
-+ xgbe_set_mode(pdata, XGBE_MODE_KX_2500);
-+ } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
-+ xgbe_set_mode(pdata, XGBE_MODE_KX_1000);
- } else {
- enable_irq(pdata->an_irq);
- return -EINVAL;
-@@ -1016,108 +836,45 @@ static void xgbe_check_link_timeout(stru
- }
- }
-
--static void xgbe_phy_status_force(struct xgbe_prv_data *pdata)
-+static enum xgbe_mode xgbe_phy_status_aneg(struct xgbe_prv_data *pdata)
- {
-- if (xgbe_in_kr_mode(pdata)) {
-- pdata->phy.speed = SPEED_10000;
-- } else {
-- switch (pdata->speed_set) {
-- case XGBE_SPEEDSET_1000_10000:
-- pdata->phy.speed = SPEED_1000;
-- break;
--
-- case XGBE_SPEEDSET_2500_10000:
-- pdata->phy.speed = SPEED_2500;
-- break;
-- }
-- }
-- pdata->phy.duplex = DUPLEX_FULL;
-+ return pdata->phy_if.phy_impl.an_outcome(pdata);
- }
-
--static void xgbe_phy_status_aneg(struct xgbe_prv_data *pdata)
-+static void xgbe_phy_status_result(struct xgbe_prv_data *pdata)
- {
-- unsigned int ad_reg, lp_reg;
-+ enum xgbe_mode mode;
-
- pdata->phy.lp_advertising = 0;
-
- if ((pdata->phy.autoneg != AUTONEG_ENABLE) || pdata->parallel_detect)
-- return xgbe_phy_status_force(pdata);
--
-- pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
-- pdata->phy.lp_advertising |= ADVERTISED_Backplane;
--
-- /* Compare Advertisement and Link Partner register 1 */
-- ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
-- lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
-- if (lp_reg & 0x400)
-- pdata->phy.lp_advertising |= ADVERTISED_Pause;
-- if (lp_reg & 0x800)
-- pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
--
-- if (pdata->phy.pause_autoneg) {
-- /* Set flow control based on auto-negotiation result */
-- pdata->phy.tx_pause = 0;
-- pdata->phy.rx_pause = 0;
--
-- if (ad_reg & lp_reg & 0x400) {
-- pdata->phy.tx_pause = 1;
-- pdata->phy.rx_pause = 1;
-- } else if (ad_reg & lp_reg & 0x800) {
-- if (ad_reg & 0x400)
-- pdata->phy.rx_pause = 1;
-- else if (lp_reg & 0x400)
-- pdata->phy.tx_pause = 1;
-- }
-- }
--
-- /* Compare Advertisement and Link Partner register 2 */
-- ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
-- lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
-- if (lp_reg & 0x80)
-- pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
-- if (lp_reg & 0x20) {
-- switch (pdata->speed_set) {
-- case XGBE_SPEEDSET_1000_10000:
-- pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
-- break;
-- case XGBE_SPEEDSET_2500_10000:
-- pdata->phy.lp_advertising |= ADVERTISED_2500baseX_Full;
-- break;
-- }
-- }
-+ mode = xgbe_cur_mode(pdata);
-+ else
-+ mode = xgbe_phy_status_aneg(pdata);
-
-- ad_reg &= lp_reg;
-- if (ad_reg & 0x80) {
-+ switch (mode) {
-+ case XGBE_MODE_KX_1000:
-+ pdata->phy.speed = SPEED_1000;
-+ break;
-+ case XGBE_MODE_KX_2500:
-+ pdata->phy.speed = SPEED_2500;
-+ break;
-+ case XGBE_MODE_KR:
- pdata->phy.speed = SPEED_10000;
-- xgbe_set_mode(pdata, XGBE_MODE_KR);
-- } else if (ad_reg & 0x20) {
-- switch (pdata->speed_set) {
-- case XGBE_SPEEDSET_1000_10000:
-- pdata->phy.speed = SPEED_1000;
-- break;
--
-- case XGBE_SPEEDSET_2500_10000:
-- pdata->phy.speed = SPEED_2500;
-- break;
-- }
--
-- xgbe_set_mode(pdata, XGBE_MODE_KX);
-- } else {
-+ break;
-+ case XGBE_MODE_UNKNOWN:
-+ default:
- pdata->phy.speed = SPEED_UNKNOWN;
- }
-
-- /* Compare Advertisement and Link Partner register 3 */
-- ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
-- lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
-- if (lp_reg & 0xc000)
-- pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
--
- pdata->phy.duplex = DUPLEX_FULL;
-+
-+ xgbe_set_mode(pdata, mode);
- }
-
- static void xgbe_phy_status(struct xgbe_prv_data *pdata)
- {
-- unsigned int reg, link_aneg;
-+ unsigned int link_aneg;
-
- if (test_bit(XGBE_LINK_ERR, &pdata->dev_state)) {
- netif_carrier_off(pdata->netdev);
-@@ -1128,20 +885,14 @@ static void xgbe_phy_status(struct xgbe_
-
- link_aneg = (pdata->phy.autoneg == AUTONEG_ENABLE);
-
-- /* Get the link status. Link status is latched low, so read
-- * once to clear and then read again to get current state
-- */
-- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
-- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
-- pdata->phy.link = (reg & MDIO_STAT1_LSTATUS) ? 1 : 0;
--
-+ pdata->phy.link = pdata->phy_if.phy_impl.link_status(pdata);
- if (pdata->phy.link) {
- if (link_aneg && !xgbe_phy_aneg_done(pdata)) {
- xgbe_check_link_timeout(pdata);
- return;
- }
-
-- xgbe_phy_status_aneg(pdata);
-+ xgbe_phy_status_result(pdata);
-
- if (test_bit(XGBE_LINK_INIT, &pdata->dev_state))
- clear_bit(XGBE_LINK_INIT, &pdata->dev_state);
-@@ -1155,7 +906,7 @@ static void xgbe_phy_status(struct xgbe_
- return;
- }
-
-- xgbe_phy_status_aneg(pdata);
-+ xgbe_phy_status_result(pdata);
-
- netif_carrier_off(pdata->netdev);
- }
-@@ -1168,6 +919,12 @@ static void xgbe_phy_stop(struct xgbe_pr
- {
- netif_dbg(pdata, link, pdata->netdev, "stopping PHY\n");
-
-+ if (!pdata->phy_started)
-+ return;
-+
-+ /* Indicate the PHY is down */
-+ pdata->phy_started = 0;
-+
- /* Disable auto-negotiation */
- xgbe_disable_an(pdata);
-
-@@ -1176,6 +933,8 @@ static void xgbe_phy_stop(struct xgbe_pr
-
- devm_free_irq(pdata->dev, pdata->an_irq, pdata);
-
-+ pdata->phy_if.phy_impl.stop(pdata);
-+
- pdata->phy.link = 0;
- netif_carrier_off(pdata->netdev);
-
-@@ -1189,28 +948,35 @@ static int xgbe_phy_start(struct xgbe_pr
-
- netif_dbg(pdata, link, pdata->netdev, "starting PHY\n");
-
-+ ret = pdata->phy_if.phy_impl.start(pdata);
-+ if (ret)
-+ return ret;
-+
- ret = devm_request_irq(pdata->dev, pdata->an_irq,
- xgbe_an_isr, 0, pdata->an_name,
- pdata);
- if (ret) {
- netdev_err(netdev, "phy irq request failed\n");
-- return ret;
-+ goto err_stop;
- }
-
- /* Set initial mode - call the mode setting routines
- * directly to insure we are properly configured
- */
-- if (xgbe_use_xgmii_mode(pdata)) {
-- xgbe_xgmii_mode(pdata);
-- } else if (xgbe_use_gmii_mode(pdata)) {
-- xgbe_gmii_mode(pdata);
-- } else if (xgbe_use_gmii_2500_mode(pdata)) {
-- xgbe_gmii_2500_mode(pdata);
-+ if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
-+ xgbe_kr_mode(pdata);
-+ } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
-+ xgbe_kx_2500_mode(pdata);
-+ } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
-+ xgbe_kx_1000_mode(pdata);
- } else {
- ret = -EINVAL;
- goto err_irq;
- }
-
-+ /* Indicate the PHY is up and running */
-+ pdata->phy_started = 1;
-+
- /* Set up advertisement registers based on current settings */
- xgbe_an_init(pdata);
-
-@@ -1222,25 +988,19 @@ static int xgbe_phy_start(struct xgbe_pr
- err_irq:
- devm_free_irq(pdata->dev, pdata->an_irq, pdata);
-
-+err_stop:
-+ pdata->phy_if.phy_impl.stop(pdata);
-+
- return ret;
- }
-
- static int xgbe_phy_reset(struct xgbe_prv_data *pdata)
- {
-- unsigned int count, reg;
--
-- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-- reg |= MDIO_CTRL1_RESET;
-- XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
--
-- count = 50;
-- do {
-- msleep(20);
-- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-- } while ((reg & MDIO_CTRL1_RESET) && --count);
-+ int ret;
-
-- if (reg & MDIO_CTRL1_RESET)
-- return -ETIMEDOUT;
-+ ret = pdata->phy_if.phy_impl.reset(pdata);
-+ if (ret)
-+ return ret;
-
- /* Disable auto-negotiation for now */
- xgbe_disable_an(pdata);
-@@ -1290,41 +1050,57 @@ static void xgbe_dump_phy_registers(stru
- dev_dbg(dev, "\n*************************************************\n");
- }
-
--static void xgbe_phy_init(struct xgbe_prv_data *pdata)
-+static int xgbe_phy_best_advertised_speed(struct xgbe_prv_data *pdata)
-+{
-+ if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full)
-+ return SPEED_10000;
-+ else if (pdata->phy.advertising & ADVERTISED_2500baseX_Full)
-+ return SPEED_2500;
-+ else if (pdata->phy.advertising & ADVERTISED_1000baseKX_Full)
-+ return SPEED_1000;
-+
-+ return SPEED_UNKNOWN;
-+}
-+
-+static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
- {
-+ xgbe_phy_stop(pdata);
-+
-+ pdata->phy_if.phy_impl.exit(pdata);
-+}
-+
-+static int xgbe_phy_init(struct xgbe_prv_data *pdata)
-+{
-+ int ret;
-+
- mutex_init(&pdata->an_mutex);
- INIT_WORK(&pdata->an_irq_work, xgbe_an_irq_work);
- INIT_WORK(&pdata->an_work, xgbe_an_state_machine);
- pdata->mdio_mmd = MDIO_MMD_PCS;
-
-- /* Initialize supported features */
-- pdata->phy.supported = SUPPORTED_Autoneg;
-- pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
-- pdata->phy.supported |= SUPPORTED_Backplane;
-- pdata->phy.supported |= SUPPORTED_10000baseKR_Full;
-- switch (pdata->speed_set) {
-- case XGBE_SPEEDSET_1000_10000:
-- pdata->phy.supported |= SUPPORTED_1000baseKX_Full;
-- break;
-- case XGBE_SPEEDSET_2500_10000:
-- pdata->phy.supported |= SUPPORTED_2500baseX_Full;
-- break;
-- }
--
-+ /* Check for FEC support */
- pdata->fec_ability = XMDIO_READ(pdata, MDIO_MMD_PMAPMD,
- MDIO_PMA_10GBR_FECABLE);
- pdata->fec_ability &= (MDIO_PMA_10GBR_FECABLE_ABLE |
- MDIO_PMA_10GBR_FECABLE_ERRABLE);
-- if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
-- pdata->phy.supported |= SUPPORTED_10000baseR_FEC;
-
-+ /* Setup the phy (including supported features) */
-+ ret = pdata->phy_if.phy_impl.init(pdata);
-+ if (ret)
-+ return ret;
- pdata->phy.advertising = pdata->phy.supported;
-
- pdata->phy.address = 0;
-
-- pdata->phy.autoneg = AUTONEG_ENABLE;
-- pdata->phy.speed = SPEED_UNKNOWN;
-- pdata->phy.duplex = DUPLEX_UNKNOWN;
-+ if (pdata->phy.advertising & ADVERTISED_Autoneg) {
-+ pdata->phy.autoneg = AUTONEG_ENABLE;
-+ pdata->phy.speed = SPEED_UNKNOWN;
-+ pdata->phy.duplex = DUPLEX_UNKNOWN;
-+ } else {
-+ pdata->phy.autoneg = AUTONEG_DISABLE;
-+ pdata->phy.speed = xgbe_phy_best_advertised_speed(pdata);
-+ pdata->phy.duplex = DUPLEX_FULL;
-+ }
-
- pdata->phy.link = 0;
-
-@@ -1346,11 +1122,14 @@ static void xgbe_phy_init(struct xgbe_pr
-
- if (netif_msg_drv(pdata))
- xgbe_dump_phy_registers(pdata);
-+
-+ return 0;
- }
-
- void xgbe_init_function_ptrs_phy(struct xgbe_phy_if *phy_if)
- {
- phy_if->phy_init = xgbe_phy_init;
-+ phy_if->phy_exit = xgbe_phy_exit;
-
- phy_if->phy_reset = xgbe_phy_reset;
- phy_if->phy_start = xgbe_phy_start;
-@@ -1358,4 +1137,6 @@ void xgbe_init_function_ptrs_phy(struct
-
- phy_if->phy_status = xgbe_phy_status;
- phy_if->phy_config_aneg = xgbe_phy_config_aneg;
-+
-+ phy_if->phy_valid_speed = xgbe_phy_valid_speed;
- }
---- /dev/null
-+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c
-@@ -0,0 +1,821 @@
-+/*
-+ * AMD 10Gb Ethernet driver
-+ *
-+ * This file is available to you under your choice of the following two
-+ * licenses:
-+ *
-+ * License 1: GPLv2
-+ *
-+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
-+ *
-+ * This file is free software; you may copy, redistribute 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.
-+ *
-+ * This file is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
-+ *
-+ * This file incorporates work covered by the following copyright and
-+ * permission notice:
-+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation
-+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
-+ * Inc. unless otherwise expressly agreed to in writing between Synopsys
-+ * and you.
-+ *
-+ * The Software IS NOT an item of Licensed Software or Licensed Product
-+ * under any End User Software License Agreement or Agreement for Licensed
-+ * Product with Synopsys or any supplement thereto. Permission is hereby
-+ * granted, free of charge, to any person obtaining a copy of this software
-+ * annotated with this license and the Software, to deal in the Software
-+ * without restriction, including without limitation the rights to use,
-+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-+ * of the Software, and to permit persons to whom the Software is furnished
-+ * to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included
-+ * in all copies or substantial portions of the Software.
-+ *
-+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
-+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
-+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-+ * THE POSSIBILITY OF SUCH DAMAGE.
-+ *
-+ *
-+ * License 2: Modified BSD
-+ *
-+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions are met:
-+ * * Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ * * Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in the
-+ * documentation and/or other materials provided with the distribution.
-+ * * Neither the name of Advanced Micro Devices, Inc. nor the
-+ * names of its contributors may be used to endorse or promote products
-+ * derived from this software without specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
-+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *
-+ * This file incorporates work covered by the following copyright and
-+ * permission notice:
-+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation
-+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
-+ * Inc. unless otherwise expressly agreed to in writing between Synopsys
-+ * and you.
-+ *
-+ * The Software IS NOT an item of Licensed Software or Licensed Product
-+ * under any End User Software License Agreement or Agreement for Licensed
-+ * Product with Synopsys or any supplement thereto. Permission is hereby
-+ * granted, free of charge, to any person obtaining a copy of this software
-+ * annotated with this license and the Software, to deal in the Software
-+ * without restriction, including without limitation the rights to use,
-+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-+ * of the Software, and to permit persons to whom the Software is furnished
-+ * to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included
-+ * in all copies or substantial portions of the Software.
-+ *
-+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
-+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
-+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-+ * THE POSSIBILITY OF SUCH DAMAGE.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kmod.h>
-+#include <linux/device.h>
-+#include <linux/property.h>
-+#include <linux/mdio.h>
-+#include <linux/phy.h>
-+
-+#include "xgbe.h"
-+#include "xgbe-common.h"
-+
-+#define XGBE_BLWC_PROPERTY "amd,serdes-blwc"
-+#define XGBE_CDR_RATE_PROPERTY "amd,serdes-cdr-rate"
-+#define XGBE_PQ_SKEW_PROPERTY "amd,serdes-pq-skew"
-+#define XGBE_TX_AMP_PROPERTY "amd,serdes-tx-amp"
-+#define XGBE_DFE_CFG_PROPERTY "amd,serdes-dfe-tap-config"
-+#define XGBE_DFE_ENA_PROPERTY "amd,serdes-dfe-tap-enable"
-+
-+/* Default SerDes settings */
-+#define XGBE_SPEED_1000_BLWC 1
-+#define XGBE_SPEED_1000_CDR 0x2
-+#define XGBE_SPEED_1000_PLL 0x0
-+#define XGBE_SPEED_1000_PQ 0xa
-+#define XGBE_SPEED_1000_RATE 0x3
-+#define XGBE_SPEED_1000_TXAMP 0xf
-+#define XGBE_SPEED_1000_WORD 0x1
-+#define XGBE_SPEED_1000_DFE_TAP_CONFIG 0x3
-+#define XGBE_SPEED_1000_DFE_TAP_ENABLE 0x0
-+
-+#define XGBE_SPEED_2500_BLWC 1
-+#define XGBE_SPEED_2500_CDR 0x2
-+#define XGBE_SPEED_2500_PLL 0x0
-+#define XGBE_SPEED_2500_PQ 0xa
-+#define XGBE_SPEED_2500_RATE 0x1
-+#define XGBE_SPEED_2500_TXAMP 0xf
-+#define XGBE_SPEED_2500_WORD 0x1
-+#define XGBE_SPEED_2500_DFE_TAP_CONFIG 0x3
-+#define XGBE_SPEED_2500_DFE_TAP_ENABLE 0x0
-+
-+#define XGBE_SPEED_10000_BLWC 0
-+#define XGBE_SPEED_10000_CDR 0x7
-+#define XGBE_SPEED_10000_PLL 0x1
-+#define XGBE_SPEED_10000_PQ 0x12
-+#define XGBE_SPEED_10000_RATE 0x0
-+#define XGBE_SPEED_10000_TXAMP 0xa
-+#define XGBE_SPEED_10000_WORD 0x7
-+#define XGBE_SPEED_10000_DFE_TAP_CONFIG 0x1
-+#define XGBE_SPEED_10000_DFE_TAP_ENABLE 0x7f
-+
-+/* Rate-change complete wait/retry count */
-+#define XGBE_RATECHANGE_COUNT 500
-+
-+static const u32 xgbe_phy_blwc[] = {
-+ XGBE_SPEED_1000_BLWC,
-+ XGBE_SPEED_2500_BLWC,
-+ XGBE_SPEED_10000_BLWC,
-+};
-+
-+static const u32 xgbe_phy_cdr_rate[] = {
-+ XGBE_SPEED_1000_CDR,
-+ XGBE_SPEED_2500_CDR,
-+ XGBE_SPEED_10000_CDR,
-+};
-+
-+static const u32 xgbe_phy_pq_skew[] = {
-+ XGBE_SPEED_1000_PQ,
-+ XGBE_SPEED_2500_PQ,
-+ XGBE_SPEED_10000_PQ,
-+};
-+
-+static const u32 xgbe_phy_tx_amp[] = {
-+ XGBE_SPEED_1000_TXAMP,
-+ XGBE_SPEED_2500_TXAMP,
-+ XGBE_SPEED_10000_TXAMP,
-+};
-+
-+static const u32 xgbe_phy_dfe_tap_cfg[] = {
-+ XGBE_SPEED_1000_DFE_TAP_CONFIG,
-+ XGBE_SPEED_2500_DFE_TAP_CONFIG,
-+ XGBE_SPEED_10000_DFE_TAP_CONFIG,
-+};
-+
-+static const u32 xgbe_phy_dfe_tap_ena[] = {
-+ XGBE_SPEED_1000_DFE_TAP_ENABLE,
-+ XGBE_SPEED_2500_DFE_TAP_ENABLE,
-+ XGBE_SPEED_10000_DFE_TAP_ENABLE,
-+};
-+
-+struct xgbe_phy_data {
-+ /* 1000/10000 vs 2500/10000 indicator */
-+ unsigned int speed_set;
-+
-+ /* SerDes UEFI configurable settings.
-+ * Switching between modes/speeds requires new values for some
-+ * SerDes settings. The values can be supplied as device
-+ * properties in array format. The first array entry is for
-+ * 1GbE, second for 2.5GbE and third for 10GbE
-+ */
-+ u32 blwc[XGBE_SPEEDS];
-+ u32 cdr_rate[XGBE_SPEEDS];
-+ u32 pq_skew[XGBE_SPEEDS];
-+ u32 tx_amp[XGBE_SPEEDS];
-+ u32 dfe_tap_cfg[XGBE_SPEEDS];
-+ u32 dfe_tap_ena[XGBE_SPEEDS];
-+};
-+
-+static void xgbe_phy_kr_training_pre(struct xgbe_prv_data *pdata)
-+{
-+ XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 1);
-+}
-+
-+static void xgbe_phy_kr_training_post(struct xgbe_prv_data *pdata)
-+{
-+ XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 0);
-+}
-+
-+static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
-+{
-+ struct xgbe_phy_data *phy_data = pdata->phy_data;
-+ enum xgbe_mode mode;
-+ unsigned int ad_reg, lp_reg;
-+
-+ pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
-+ pdata->phy.lp_advertising |= ADVERTISED_Backplane;
-+
-+ /* Compare Advertisement and Link Partner register 1 */
-+ ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
-+ lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
-+ if (lp_reg & 0x400)
-+ pdata->phy.lp_advertising |= ADVERTISED_Pause;
-+ if (lp_reg & 0x800)
-+ pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
-+
-+ if (pdata->phy.pause_autoneg) {
-+ /* Set flow control based on auto-negotiation result */
-+ pdata->phy.tx_pause = 0;
-+ pdata->phy.rx_pause = 0;
-+
-+ if (ad_reg & lp_reg & 0x400) {
-+ pdata->phy.tx_pause = 1;
-+ pdata->phy.rx_pause = 1;
-+ } else if (ad_reg & lp_reg & 0x800) {
-+ if (ad_reg & 0x400)
-+ pdata->phy.rx_pause = 1;
-+ else if (lp_reg & 0x400)
-+ pdata->phy.tx_pause = 1;
-+ }
-+ }
-+
-+ /* Compare Advertisement and Link Partner register 2 */
-+ ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
-+ lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
-+ if (lp_reg & 0x80)
-+ pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
-+ if (lp_reg & 0x20) {
-+ if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
-+ pdata->phy.lp_advertising |= ADVERTISED_2500baseX_Full;
-+ else
-+ pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
-+ }
-+
-+ ad_reg &= lp_reg;
-+ if (ad_reg & 0x80) {
-+ mode = XGBE_MODE_KR;
-+ } else if (ad_reg & 0x20) {
-+ if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
-+ mode = XGBE_MODE_KX_2500;
-+ else
-+ mode = XGBE_MODE_KX_1000;
-+ } else {
-+ mode = XGBE_MODE_UNKNOWN;
-+ }
-+
-+ /* Compare Advertisement and Link Partner register 3 */
-+ ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
-+ lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
-+ if (lp_reg & 0xc000)
-+ pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
-+
-+ return mode;
-+}
-+
-+static void xgbe_phy_pcs_power_cycle(struct xgbe_prv_data *pdata)
-+{
-+ unsigned int reg;
-+
-+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-+
-+ reg |= MDIO_CTRL1_LPOWER;
-+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
-+
-+ usleep_range(75, 100);
-+
-+ reg &= ~MDIO_CTRL1_LPOWER;
-+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
-+}
-+
-+static void xgbe_phy_start_ratechange(struct xgbe_prv_data *pdata)
-+{
-+ /* Assert Rx and Tx ratechange */
-+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 1);
-+}
-+
-+static void xgbe_phy_complete_ratechange(struct xgbe_prv_data *pdata)
-+{
-+ unsigned int wait;
-+ u16 status;
-+
-+ /* Release Rx and Tx ratechange */
-+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 0);
-+
-+ /* Wait for Rx and Tx ready */
-+ wait = XGBE_RATECHANGE_COUNT;
-+ while (wait--) {
-+ usleep_range(50, 75);
-+
-+ status = XSIR0_IOREAD(pdata, SIR0_STATUS);
-+ if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) &&
-+ XSIR_GET_BITS(status, SIR0_STATUS, TX_READY))
-+ goto rx_reset;
-+ }
-+
-+ netif_dbg(pdata, link, pdata->netdev, "SerDes rx/tx not ready (%#hx)\n",
-+ status);
-+
-+rx_reset:
-+ /* Perform Rx reset for the DFE changes */
-+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 0);
-+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 1);
-+}
-+
-+static void xgbe_phy_kr_mode(struct xgbe_prv_data *pdata)
-+{
-+ struct xgbe_phy_data *phy_data = pdata->phy_data;
-+ unsigned int reg;
-+
-+ /* Set PCS to KR/10G speed */
-+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
-+ reg &= ~MDIO_PCS_CTRL2_TYPE;
-+ reg |= MDIO_PCS_CTRL2_10GBR;
-+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
-+
-+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-+ reg &= ~MDIO_CTRL1_SPEEDSEL;
-+ reg |= MDIO_CTRL1_SPEED10G;
-+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
-+
-+ xgbe_phy_pcs_power_cycle(pdata);
-+
-+ /* Set SerDes to 10G speed */
-+ xgbe_phy_start_ratechange(pdata);
-+
-+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_10000_RATE);
-+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_10000_WORD);
-+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_10000_PLL);
-+
-+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
-+ phy_data->cdr_rate[XGBE_SPEED_10000]);
-+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
-+ phy_data->tx_amp[XGBE_SPEED_10000]);
-+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
-+ phy_data->blwc[XGBE_SPEED_10000]);
-+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
-+ phy_data->pq_skew[XGBE_SPEED_10000]);
-+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
-+ phy_data->dfe_tap_cfg[XGBE_SPEED_10000]);
-+ XRXTX_IOWRITE(pdata, RXTX_REG22,
-+ phy_data->dfe_tap_ena[XGBE_SPEED_10000]);
-+
-+ xgbe_phy_complete_ratechange(pdata);
-+
-+ netif_dbg(pdata, link, pdata->netdev, "10GbE KR mode set\n");
-+}
-+
-+static void xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata)
-+{
-+ struct xgbe_phy_data *phy_data = pdata->phy_data;
-+ unsigned int reg;
-+
-+ /* Set PCS to KX/1G speed */
-+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
-+ reg &= ~MDIO_PCS_CTRL2_TYPE;
-+ reg |= MDIO_PCS_CTRL2_10GBX;
-+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
-+
-+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-+ reg &= ~MDIO_CTRL1_SPEEDSEL;
-+ reg |= MDIO_CTRL1_SPEED1G;
-+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
-+
-+ xgbe_phy_pcs_power_cycle(pdata);
-+
-+ /* Set SerDes to 2.5G speed */
-+ xgbe_phy_start_ratechange(pdata);
-+
-+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_2500_RATE);
-+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_2500_WORD);
-+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_2500_PLL);
-+
-+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
-+ phy_data->cdr_rate[XGBE_SPEED_2500]);
-+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
-+ phy_data->tx_amp[XGBE_SPEED_2500]);
-+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
-+ phy_data->blwc[XGBE_SPEED_2500]);
-+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
-+ phy_data->pq_skew[XGBE_SPEED_2500]);
-+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
-+ phy_data->dfe_tap_cfg[XGBE_SPEED_2500]);
-+ XRXTX_IOWRITE(pdata, RXTX_REG22,
-+ phy_data->dfe_tap_ena[XGBE_SPEED_2500]);
-+
-+ xgbe_phy_complete_ratechange(pdata);
-+
-+ netif_dbg(pdata, link, pdata->netdev, "2.5GbE KX mode set\n");
-+}
-+
-+static void xgbe_phy_kx_1000_mode(struct xgbe_prv_data *pdata)
-+{
-+ struct xgbe_phy_data *phy_data = pdata->phy_data;
-+ unsigned int reg;
-+
-+ /* Set PCS to KX/1G speed */
-+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
-+ reg &= ~MDIO_PCS_CTRL2_TYPE;
-+ reg |= MDIO_PCS_CTRL2_10GBX;
-+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
-+
-+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-+ reg &= ~MDIO_CTRL1_SPEEDSEL;
-+ reg |= MDIO_CTRL1_SPEED1G;
-+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
-+
-+ xgbe_phy_pcs_power_cycle(pdata);
-+
-+ /* Set SerDes to 1G speed */
-+ xgbe_phy_start_ratechange(pdata);
-+
-+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE);
-+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD);
-+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL);
-+
-+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
-+ phy_data->cdr_rate[XGBE_SPEED_1000]);
-+ XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
-+ phy_data->tx_amp[XGBE_SPEED_1000]);
-+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
-+ phy_data->blwc[XGBE_SPEED_1000]);
-+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
-+ phy_data->pq_skew[XGBE_SPEED_1000]);
-+ XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
-+ phy_data->dfe_tap_cfg[XGBE_SPEED_1000]);
-+ XRXTX_IOWRITE(pdata, RXTX_REG22,
-+ phy_data->dfe_tap_ena[XGBE_SPEED_1000]);
-+
-+ xgbe_phy_complete_ratechange(pdata);
-+
-+ netif_dbg(pdata, link, pdata->netdev, "1GbE KX mode set\n");
-+}
-+
-+static enum xgbe_mode xgbe_phy_cur_mode(struct xgbe_prv_data *pdata)
-+{
-+ struct xgbe_phy_data *phy_data = pdata->phy_data;
-+ enum xgbe_mode mode;
-+ unsigned int reg;
-+
-+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
-+ reg &= MDIO_PCS_CTRL2_TYPE;
-+
-+ if (reg == MDIO_PCS_CTRL2_10GBR) {
-+ mode = XGBE_MODE_KR;
-+ } else {
-+ if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
-+ mode = XGBE_MODE_KX_2500;
-+ else
-+ mode = XGBE_MODE_KX_1000;
-+ }
-+
-+ return mode;
-+}
-+
-+static enum xgbe_mode xgbe_phy_switch_mode(struct xgbe_prv_data *pdata)
-+{
-+ struct xgbe_phy_data *phy_data = pdata->phy_data;
-+ enum xgbe_mode mode;
-+
-+ /* If we are in KR switch to KX, and vice-versa */
-+ if (xgbe_phy_cur_mode(pdata) == XGBE_MODE_KR) {
-+ if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
-+ mode = XGBE_MODE_KX_2500;
-+ else
-+ mode = XGBE_MODE_KX_1000;
-+ } else {
-+ mode = XGBE_MODE_KR;
-+ }
-+
-+ return mode;
-+}
-+
-+static enum xgbe_mode xgbe_phy_get_mode(struct xgbe_prv_data *pdata,
-+ int speed)
-+{
-+ struct xgbe_phy_data *phy_data = pdata->phy_data;
-+
-+ switch (speed) {
-+ case SPEED_1000:
-+ return (phy_data->speed_set == XGBE_SPEEDSET_1000_10000)
-+ ? XGBE_MODE_KX_1000 : XGBE_MODE_UNKNOWN;
-+ case SPEED_2500:
-+ return (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
-+ ? XGBE_MODE_KX_2500 : XGBE_MODE_UNKNOWN;
-+ case SPEED_10000:
-+ return XGBE_MODE_KR;
-+ default:
-+ return XGBE_MODE_UNKNOWN;
-+ }
-+}
-+
-+static void xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
-+{
-+ switch (mode) {
-+ case XGBE_MODE_KX_1000:
-+ xgbe_phy_kx_1000_mode(pdata);
-+ break;
-+ case XGBE_MODE_KX_2500:
-+ xgbe_phy_kx_2500_mode(pdata);
-+ break;
-+ case XGBE_MODE_KR:
-+ xgbe_phy_kr_mode(pdata);
-+ break;
-+ default:
-+ break;
-+ }
-+}
-+
-+static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata,
-+ enum xgbe_mode mode, u32 advert)
-+{
-+ if (pdata->phy.autoneg == AUTONEG_ENABLE) {
-+ if (pdata->phy.advertising & advert)
-+ return true;
-+ } else {
-+ enum xgbe_mode cur_mode;
-+
-+ cur_mode = xgbe_phy_get_mode(pdata, pdata->phy.speed);
-+ if (cur_mode == mode)
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+static bool xgbe_phy_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
-+{
-+ switch (mode) {
-+ case XGBE_MODE_KX_1000:
-+ return xgbe_phy_check_mode(pdata, mode,
-+ ADVERTISED_1000baseKX_Full);
-+ case XGBE_MODE_KX_2500:
-+ return xgbe_phy_check_mode(pdata, mode,
-+ ADVERTISED_2500baseX_Full);
-+ case XGBE_MODE_KR:
-+ return xgbe_phy_check_mode(pdata, mode,
-+ ADVERTISED_10000baseKR_Full);
-+ default:
-+ return false;
-+ }
-+}
-+
-+static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
-+{
-+ struct xgbe_phy_data *phy_data = pdata->phy_data;
-+
-+ switch (speed) {
-+ case SPEED_1000:
-+ if (phy_data->speed_set != XGBE_SPEEDSET_1000_10000)
-+ return false;
-+ return true;
-+ case SPEED_2500:
-+ if (phy_data->speed_set != XGBE_SPEEDSET_2500_10000)
-+ return false;
-+ return true;
-+ case SPEED_10000:
-+ return true;
-+ default:
-+ return false;
-+ }
-+}
-+
-+static int xgbe_phy_link_status(struct xgbe_prv_data *pdata)
-+{
-+ unsigned int reg;
-+
-+ /* Link status is latched low, so read once to clear
-+ * and then read again to get current state
-+ */
-+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
-+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
-+
-+ return (reg & MDIO_STAT1_LSTATUS) ? 1 : 0;
-+}
-+
-+static void xgbe_phy_stop(struct xgbe_prv_data *pdata)
-+{
-+ /* Nothing uniquely required for stop */
-+}
-+
-+static int xgbe_phy_start(struct xgbe_prv_data *pdata)
-+{
-+ /* Nothing uniquely required for start */
-+ return 0;
-+}
-+
-+static int xgbe_phy_reset(struct xgbe_prv_data *pdata)
-+{
-+ unsigned int reg, count;
-+
-+ /* Perform a software reset of the PCS */
-+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-+ reg |= MDIO_CTRL1_RESET;
-+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
-+
-+ count = 50;
-+ do {
-+ msleep(20);
-+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-+ } while ((reg & MDIO_CTRL1_RESET) && --count);
-+
-+ if (reg & MDIO_CTRL1_RESET)
-+ return -ETIMEDOUT;
-+
-+ return 0;
-+}
-+
-+static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
-+{
-+ /* Nothing uniquely required for exit */
-+}
-+
-+static int xgbe_phy_init(struct xgbe_prv_data *pdata)
-+{
-+ struct xgbe_phy_data *phy_data;
-+ int ret;
-+
-+ phy_data = devm_kzalloc(pdata->dev, sizeof(*phy_data), GFP_KERNEL);
-+ if (!phy_data)
-+ return -ENOMEM;
-+
-+ /* Retrieve the PHY speedset */
-+ ret = device_property_read_u32(pdata->phy_dev, XGBE_SPEEDSET_PROPERTY,
-+ &phy_data->speed_set);
-+ if (ret) {
-+ dev_err(pdata->dev, "invalid %s property\n",
-+ XGBE_SPEEDSET_PROPERTY);
-+ return ret;
-+ }
-+
-+ switch (phy_data->speed_set) {
-+ case XGBE_SPEEDSET_1000_10000:
-+ case XGBE_SPEEDSET_2500_10000:
-+ break;
-+ default:
-+ dev_err(pdata->dev, "invalid %s property\n",
-+ XGBE_SPEEDSET_PROPERTY);
-+ return -EINVAL;
-+ }
-+
-+ /* Retrieve the PHY configuration properties */
-+ if (device_property_present(pdata->phy_dev, XGBE_BLWC_PROPERTY)) {
-+ ret = device_property_read_u32_array(pdata->phy_dev,
-+ XGBE_BLWC_PROPERTY,
-+ phy_data->blwc,
-+ XGBE_SPEEDS);
-+ if (ret) {
-+ dev_err(pdata->dev, "invalid %s property\n",
-+ XGBE_BLWC_PROPERTY);
-+ return ret;
-+ }
-+ } else {
-+ memcpy(phy_data->blwc, xgbe_phy_blwc,
-+ sizeof(phy_data->blwc));
-+ }
-+
-+ if (device_property_present(pdata->phy_dev, XGBE_CDR_RATE_PROPERTY)) {
-+ ret = device_property_read_u32_array(pdata->phy_dev,
-+ XGBE_CDR_RATE_PROPERTY,
-+ phy_data->cdr_rate,
-+ XGBE_SPEEDS);
-+ if (ret) {
-+ dev_err(pdata->dev, "invalid %s property\n",
-+ XGBE_CDR_RATE_PROPERTY);
-+ return ret;
-+ }
-+ } else {
-+ memcpy(phy_data->cdr_rate, xgbe_phy_cdr_rate,
-+ sizeof(phy_data->cdr_rate));
-+ }
-+
-+ if (device_property_present(pdata->phy_dev, XGBE_PQ_SKEW_PROPERTY)) {
-+ ret = device_property_read_u32_array(pdata->phy_dev,
-+ XGBE_PQ_SKEW_PROPERTY,
-+ phy_data->pq_skew,
-+ XGBE_SPEEDS);
-+ if (ret) {
-+ dev_err(pdata->dev, "invalid %s property\n",
-+ XGBE_PQ_SKEW_PROPERTY);
-+ return ret;
-+ }
-+ } else {
-+ memcpy(phy_data->pq_skew, xgbe_phy_pq_skew,
-+ sizeof(phy_data->pq_skew));
-+ }
-+
-+ if (device_property_present(pdata->phy_dev, XGBE_TX_AMP_PROPERTY)) {
-+ ret = device_property_read_u32_array(pdata->phy_dev,
-+ XGBE_TX_AMP_PROPERTY,
-+ phy_data->tx_amp,
-+ XGBE_SPEEDS);
-+ if (ret) {
-+ dev_err(pdata->dev, "invalid %s property\n",
-+ XGBE_TX_AMP_PROPERTY);
-+ return ret;
-+ }
-+ } else {
-+ memcpy(phy_data->tx_amp, xgbe_phy_tx_amp,
-+ sizeof(phy_data->tx_amp));
-+ }
-+
-+ if (device_property_present(pdata->phy_dev, XGBE_DFE_CFG_PROPERTY)) {
-+ ret = device_property_read_u32_array(pdata->phy_dev,
-+ XGBE_DFE_CFG_PROPERTY,
-+ phy_data->dfe_tap_cfg,
-+ XGBE_SPEEDS);
-+ if (ret) {
-+ dev_err(pdata->dev, "invalid %s property\n",
-+ XGBE_DFE_CFG_PROPERTY);
-+ return ret;
-+ }
-+ } else {
-+ memcpy(phy_data->dfe_tap_cfg, xgbe_phy_dfe_tap_cfg,
-+ sizeof(phy_data->dfe_tap_cfg));
-+ }
-+
-+ if (device_property_present(pdata->phy_dev, XGBE_DFE_ENA_PROPERTY)) {
-+ ret = device_property_read_u32_array(pdata->phy_dev,
-+ XGBE_DFE_ENA_PROPERTY,
-+ phy_data->dfe_tap_ena,
-+ XGBE_SPEEDS);
-+ if (ret) {
-+ dev_err(pdata->dev, "invalid %s property\n",
-+ XGBE_DFE_ENA_PROPERTY);
-+ return ret;
-+ }
-+ } else {
-+ memcpy(phy_data->dfe_tap_ena, xgbe_phy_dfe_tap_ena,
-+ sizeof(phy_data->dfe_tap_ena));
-+ }
-+
-+ /* Initialize supported features */
-+ pdata->phy.supported = SUPPORTED_Autoneg;
-+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
-+ pdata->phy.supported |= SUPPORTED_Backplane;
-+ pdata->phy.supported |= SUPPORTED_10000baseKR_Full;
-+ switch (phy_data->speed_set) {
-+ case XGBE_SPEEDSET_1000_10000:
-+ pdata->phy.supported |= SUPPORTED_1000baseKX_Full;
-+ break;
-+ case XGBE_SPEEDSET_2500_10000:
-+ pdata->phy.supported |= SUPPORTED_2500baseX_Full;
-+ break;
-+ }
-+
-+ if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
-+ pdata->phy.supported |= SUPPORTED_10000baseR_FEC;
-+
-+ pdata->phy_data = phy_data;
-+
-+ return 0;
-+}
-+
-+void xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *phy_if)
-+{
-+ struct xgbe_phy_impl_if *phy_impl = &phy_if->phy_impl;
-+
-+ phy_impl->init = xgbe_phy_init;
-+ phy_impl->exit = xgbe_phy_exit;
-+
-+ phy_impl->reset = xgbe_phy_reset;
-+ phy_impl->start = xgbe_phy_start;
-+ phy_impl->stop = xgbe_phy_stop;
-+
-+ phy_impl->link_status = xgbe_phy_link_status;
-+
-+ phy_impl->valid_speed = xgbe_phy_valid_speed;
-+
-+ phy_impl->use_mode = xgbe_phy_use_mode;
-+ phy_impl->set_mode = xgbe_phy_set_mode;
-+ phy_impl->get_mode = xgbe_phy_get_mode;
-+ phy_impl->switch_mode = xgbe_phy_switch_mode;
-+ phy_impl->cur_mode = xgbe_phy_cur_mode;
-+
-+ phy_impl->an_outcome = xgbe_phy_an_outcome;
-+
-+ phy_impl->kr_training_pre = xgbe_phy_kr_training_pre;
-+ phy_impl->kr_training_post = xgbe_phy_kr_training_post;
-+}
---- a/drivers/net/ethernet/amd/xgbe/xgbe.h
-+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
-@@ -129,7 +129,7 @@
- #include <net/dcbnl.h>
-
- #define XGBE_DRV_NAME "amd-xgbe"
--#define XGBE_DRV_VERSION "1.0.2"
-+#define XGBE_DRV_VERSION "1.0.3"
- #define XGBE_DRV_DESC "AMD 10 Gigabit Ethernet Driver"
-
- /* Descriptor related defines */
-@@ -183,12 +183,6 @@
- #define XGBE_PHY_MODE_PROPERTY "phy-mode"
- #define XGBE_DMA_IRQS_PROPERTY "amd,per-channel-interrupt"
- #define XGBE_SPEEDSET_PROPERTY "amd,speed-set"
--#define XGBE_BLWC_PROPERTY "amd,serdes-blwc"
--#define XGBE_CDR_RATE_PROPERTY "amd,serdes-cdr-rate"
--#define XGBE_PQ_SKEW_PROPERTY "amd,serdes-pq-skew"
--#define XGBE_TX_AMP_PROPERTY "amd,serdes-tx-amp"
--#define XGBE_DFE_CFG_PROPERTY "amd,serdes-dfe-tap-config"
--#define XGBE_DFE_ENA_PROPERTY "amd,serdes-dfe-tap-enable"
-
- /* Device-tree clock names */
- #define XGBE_DMA_CLOCK "dma_clk"
-@@ -251,40 +245,6 @@
- #define XGBE_AN_PG_RCV 0x04
- #define XGBE_AN_INT_MASK 0x07
-
--/* Rate-change complete wait/retry count */
--#define XGBE_RATECHANGE_COUNT 500
--
--/* Default SerDes settings */
--#define XGBE_SPEED_10000_BLWC 0
--#define XGBE_SPEED_10000_CDR 0x7
--#define XGBE_SPEED_10000_PLL 0x1
--#define XGBE_SPEED_10000_PQ 0x12
--#define XGBE_SPEED_10000_RATE 0x0
--#define XGBE_SPEED_10000_TXAMP 0xa
--#define XGBE_SPEED_10000_WORD 0x7
--#define XGBE_SPEED_10000_DFE_TAP_CONFIG 0x1
--#define XGBE_SPEED_10000_DFE_TAP_ENABLE 0x7f
--
--#define XGBE_SPEED_2500_BLWC 1
--#define XGBE_SPEED_2500_CDR 0x2
--#define XGBE_SPEED_2500_PLL 0x0
--#define XGBE_SPEED_2500_PQ 0xa
--#define XGBE_SPEED_2500_RATE 0x1
--#define XGBE_SPEED_2500_TXAMP 0xf
--#define XGBE_SPEED_2500_WORD 0x1
--#define XGBE_SPEED_2500_DFE_TAP_CONFIG 0x3
--#define XGBE_SPEED_2500_DFE_TAP_ENABLE 0x0
--
--#define XGBE_SPEED_1000_BLWC 1
--#define XGBE_SPEED_1000_CDR 0x2
--#define XGBE_SPEED_1000_PLL 0x0
--#define XGBE_SPEED_1000_PQ 0xa
--#define XGBE_SPEED_1000_RATE 0x3
--#define XGBE_SPEED_1000_TXAMP 0xf
--#define XGBE_SPEED_1000_WORD 0x1
--#define XGBE_SPEED_1000_DFE_TAP_CONFIG 0x3
--#define XGBE_SPEED_1000_DFE_TAP_ENABLE 0x0
--
- struct xgbe_prv_data;
-
- struct xgbe_packet_data {
-@@ -504,8 +464,10 @@ enum xgbe_rx {
- };
-
- enum xgbe_mode {
-- XGBE_MODE_KR = 0,
-- XGBE_MODE_KX,
-+ XGBE_MODE_KX_1000 = 0,
-+ XGBE_MODE_KX_2500,
-+ XGBE_MODE_KR,
-+ XGBE_MODE_UNKNOWN,
- };
-
- enum xgbe_speedset {
-@@ -601,9 +563,7 @@ struct xgbe_hw_if {
-
- int (*read_mmd_regs)(struct xgbe_prv_data *, int, int);
- void (*write_mmd_regs)(struct xgbe_prv_data *, int, int, int);
-- int (*set_gmii_speed)(struct xgbe_prv_data *);
-- int (*set_gmii_2500_speed)(struct xgbe_prv_data *);
-- int (*set_xgmii_speed)(struct xgbe_prv_data *);
-+ int (*set_speed)(struct xgbe_prv_data *, int);
-
- void (*enable_tx)(struct xgbe_prv_data *);
- void (*disable_tx)(struct xgbe_prv_data *);
-@@ -684,9 +644,50 @@ struct xgbe_hw_if {
- int (*set_rss_lookup_table)(struct xgbe_prv_data *, const u32 *);
- };
-
-+/* This structure represents implementation specific routines for an
-+ * implementation of a PHY. All routines are required unless noted below.
-+ * Optional routines:
-+ * kr_training_pre, kr_training_post
-+ */
-+struct xgbe_phy_impl_if {
-+ /* Perform Setup/teardown actions */
-+ int (*init)(struct xgbe_prv_data *);
-+ void (*exit)(struct xgbe_prv_data *);
-+
-+ /* Perform start/stop specific actions */
-+ int (*reset)(struct xgbe_prv_data *);
-+ int (*start)(struct xgbe_prv_data *);
-+ void (*stop)(struct xgbe_prv_data *);
-+
-+ /* Return the link status */
-+ int (*link_status)(struct xgbe_prv_data *);
-+
-+ /* Indicate if a particular speed is valid */
-+ bool (*valid_speed)(struct xgbe_prv_data *, int);
-+
-+ /* Check if the specified mode can/should be used */
-+ bool (*use_mode)(struct xgbe_prv_data *, enum xgbe_mode);
-+ /* Switch the PHY into various modes */
-+ void (*set_mode)(struct xgbe_prv_data *, enum xgbe_mode);
-+ /* Retrieve mode needed for a specific speed */
-+ enum xgbe_mode (*get_mode)(struct xgbe_prv_data *, int);
-+ /* Retrieve new/next mode when trying to auto-negotiate */
-+ enum xgbe_mode (*switch_mode)(struct xgbe_prv_data *);
-+ /* Retrieve current mode */
-+ enum xgbe_mode (*cur_mode)(struct xgbe_prv_data *);
-+
-+ /* Process results of auto-negotiation */
-+ enum xgbe_mode (*an_outcome)(struct xgbe_prv_data *);
-+
-+ /* Pre/Post KR training enablement support */
-+ void (*kr_training_pre)(struct xgbe_prv_data *);
-+ void (*kr_training_post)(struct xgbe_prv_data *);
-+};
-+
- struct xgbe_phy_if {
-- /* For initial PHY setup */
-- void (*phy_init)(struct xgbe_prv_data *);
-+ /* For PHY setup/teardown */
-+ int (*phy_init)(struct xgbe_prv_data *);
-+ void (*phy_exit)(struct xgbe_prv_data *);
-
- /* For PHY support when setting device up/down */
- int (*phy_reset)(struct xgbe_prv_data *);
-@@ -696,6 +697,12 @@ struct xgbe_phy_if {
- /* For PHY support while device is up */
- void (*phy_status)(struct xgbe_prv_data *);
- int (*phy_config_aneg)(struct xgbe_prv_data *);
-+
-+ /* For PHY settings validation */
-+ bool (*phy_valid_speed)(struct xgbe_prv_data *, int);
-+
-+ /* PHY implementation specific services */
-+ struct xgbe_phy_impl_if phy_impl;
- };
-
- struct xgbe_desc_if {
-@@ -755,11 +762,20 @@ struct xgbe_hw_features {
- unsigned int aux_snap_num; /* Number of Aux snapshot inputs */
- };
-
-+struct xgbe_version_data {
-+ void (*init_function_ptrs_phy_impl)(struct xgbe_phy_if *);
-+};
-+
- struct xgbe_prv_data {
- struct net_device *netdev;
- struct platform_device *pdev;
- struct acpi_device *adev;
- struct device *dev;
-+ struct platform_device *phy_pdev;
-+ struct device *phy_dev;
-+
-+ /* Version related data */
-+ struct xgbe_version_data *vdata;
-
- /* ACPI or DT flag */
- unsigned int use_acpi;
-@@ -901,6 +917,8 @@ struct xgbe_prv_data {
- int phy_speed;
-
- /* MDIO/PHY related settings */
-+ unsigned int phy_started;
-+ void *phy_data;
- struct xgbe_phy phy;
- int mdio_mmd;
- unsigned long link_check;
-@@ -911,21 +929,6 @@ struct xgbe_prv_data {
- int an_irq;
- struct work_struct an_irq_work;
-
-- unsigned int speed_set;
--
-- /* SerDes UEFI configurable settings.
-- * Switching between modes/speeds requires new values for some
-- * SerDes settings. The values can be supplied as device
-- * properties in array format. The first array entry is for
-- * 1GbE, second for 2.5GbE and third for 10GbE
-- */
-- u32 serdes_blwc[XGBE_SPEEDS];
-- u32 serdes_cdr_rate[XGBE_SPEEDS];
-- u32 serdes_pq_skew[XGBE_SPEEDS];
-- u32 serdes_tx_amp[XGBE_SPEEDS];
-- u32 serdes_dfe_tap_cfg[XGBE_SPEEDS];
-- u32 serdes_dfe_tap_ena[XGBE_SPEEDS];
--
- /* Auto-negotiation state machine support */
- unsigned int an_int;
- struct mutex an_mutex;
-@@ -955,6 +958,7 @@ struct xgbe_prv_data {
-
- void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *);
- void xgbe_init_function_ptrs_phy(struct xgbe_phy_if *);
-+void xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *);
- void xgbe_init_function_ptrs_desc(struct xgbe_desc_if *);
- const struct net_device_ops *xgbe_get_netdev_ops(void);
- const struct ethtool_ops *xgbe_get_ethtool_ops(void);