diff options
Diffstat (limited to 'common/dpdk/recipes-extended/dpdk/dpdk/dpdk-dev-v3-05-18-net-axgbe-add-phy-initialization-and-related-apis.patch')
-rw-r--r-- | common/dpdk/recipes-extended/dpdk/dpdk/dpdk-dev-v3-05-18-net-axgbe-add-phy-initialization-and-related-apis.patch | 1974 |
1 files changed, 0 insertions, 1974 deletions
diff --git a/common/dpdk/recipes-extended/dpdk/dpdk/dpdk-dev-v3-05-18-net-axgbe-add-phy-initialization-and-related-apis.patch b/common/dpdk/recipes-extended/dpdk/dpdk/dpdk-dev-v3-05-18-net-axgbe-add-phy-initialization-and-related-apis.patch deleted file mode 100644 index e5389e4c..00000000 --- a/common/dpdk/recipes-extended/dpdk/dpdk/dpdk-dev-v3-05-18-net-axgbe-add-phy-initialization-and-related-apis.patch +++ /dev/null @@ -1,1974 +0,0 @@ -From patchwork Fri Mar 9 08:42:21 2018 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [dpdk-dev, v3, - 05/18] net/axgbe: add phy initialization and related apis -From: Ravi Kumar <ravi1.kumar@amd.com> -X-Patchwork-Id: 35824 -X-Patchwork-Delegate: ferruh.yigit@intel.com -Message-Id: <1520584954-130575-5-git-send-email-Ravi1.kumar@amd.com> -List-Id: dev.dpdk.org -To: dev@dpdk.org -Cc: ferruh.yigit@intel.com -Date: Fri, 9 Mar 2018 03:42:21 -0500 - -Signed-off-by: Ravi Kumar <Ravi1.kumar@amd.com> ---- - drivers/net/axgbe/Makefile | 3 + - drivers/net/axgbe/axgbe_dev.c | 188 +++++++++ - drivers/net/axgbe/axgbe_ethdev.c | 11 + - drivers/net/axgbe/axgbe_ethdev.h | 172 ++++++++ - drivers/net/axgbe/axgbe_i2c.c | 453 +++++++++++++++++++++ - drivers/net/axgbe/axgbe_mdio.c | 203 ++++++++++ - drivers/net/axgbe/axgbe_phy_impl.c | 799 +++++++++++++++++++++++++++++++++++++ - 7 files changed, 1829 insertions(+) - create mode 100644 drivers/net/axgbe/axgbe_i2c.c - create mode 100644 drivers/net/axgbe/axgbe_mdio.c - create mode 100644 drivers/net/axgbe/axgbe_phy_impl.c - -diff --git a/drivers/net/axgbe/Makefile b/drivers/net/axgbe/Makefile -index ce2485d..a8f3358 100644 ---- a/drivers/net/axgbe/Makefile -+++ b/drivers/net/axgbe/Makefile -@@ -143,5 +143,8 @@ LIBABIVER := 1 - # - SRCS-$(CONFIG_RTE_LIBRTE_AXGBE_PMD) += axgbe_ethdev.c - SRCS-$(CONFIG_RTE_LIBRTE_AXGBE_PMD) += axgbe_dev.c -+SRCS-$(CONFIG_RTE_LIBRTE_AXGBE_PMD) += axgbe_mdio.c -+SRCS-$(CONFIG_RTE_LIBRTE_AXGBE_PMD) += axgbe_phy_impl.c -+SRCS-$(CONFIG_RTE_LIBRTE_AXGBE_PMD) += axgbe_i2c.c - - include $(RTE_SDK)/mk/rte.lib.mk -diff --git a/drivers/net/axgbe/axgbe_dev.c b/drivers/net/axgbe/axgbe_dev.c -index 8bf3b82..90a99c4 100644 ---- a/drivers/net/axgbe/axgbe_dev.c -+++ b/drivers/net/axgbe/axgbe_dev.c -@@ -129,6 +129,187 @@ - #include "axgbe_common.h" - #include "axgbe_phy.h" - -+/* query busy bit */ -+static int mdio_complete(struct axgbe_port *pdata) -+{ -+ if (!AXGMAC_IOREAD_BITS(pdata, MAC_MDIOSCCDR, BUSY)) -+ return 1; -+ -+ return 0; -+} -+ -+static int axgbe_write_ext_mii_regs(struct axgbe_port *pdata, int addr, -+ int reg, u16 val) -+{ -+ unsigned int mdio_sca, mdio_sccd; -+ uint64_t timeout; -+ -+ mdio_sca = 0; -+ AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg); -+ AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr); -+ AXGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca); -+ -+ mdio_sccd = 0; -+ AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, DATA, val); -+ AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, CMD, 1); -+ AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, BUSY, 1); -+ AXGMAC_IOWRITE(pdata, MAC_MDIOSCCDR, mdio_sccd); -+ -+ timeout = rte_get_timer_cycles() + rte_get_timer_hz(); -+ while (time_before(rte_get_timer_cycles(), timeout)) { -+ rte_delay_us(100); -+ if (mdio_complete(pdata)) -+ return 0; -+ } -+ -+ PMD_DRV_LOG(ERR, "Mdio write operation timed out"); -+ return -ETIMEDOUT; -+} -+ -+static int axgbe_read_ext_mii_regs(struct axgbe_port *pdata, int addr, -+ int reg) -+{ -+ unsigned int mdio_sca, mdio_sccd; -+ uint64_t timeout; -+ -+ mdio_sca = 0; -+ AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg); -+ AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr); -+ AXGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca); -+ -+ mdio_sccd = 0; -+ AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, CMD, 3); -+ AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, BUSY, 1); -+ AXGMAC_IOWRITE(pdata, MAC_MDIOSCCDR, mdio_sccd); -+ -+ timeout = rte_get_timer_cycles() + rte_get_timer_hz(); -+ -+ while (time_before(rte_get_timer_cycles(), timeout)) { -+ rte_delay_us(100); -+ if (mdio_complete(pdata)) -+ goto success; -+ } -+ -+ PMD_DRV_LOG(ERR, "Mdio read operation timed out"); -+ return -ETIMEDOUT; -+ -+success: -+ return AXGMAC_IOREAD_BITS(pdata, MAC_MDIOSCCDR, DATA); -+} -+ -+static int axgbe_set_ext_mii_mode(struct axgbe_port *pdata, unsigned int port, -+ enum axgbe_mdio_mode mode) -+{ -+ unsigned int reg_val = 0; -+ -+ switch (mode) { -+ case AXGBE_MDIO_MODE_CL22: -+ if (port > AXGMAC_MAX_C22_PORT) -+ return -EINVAL; -+ reg_val |= (1 << port); -+ break; -+ case AXGBE_MDIO_MODE_CL45: -+ break; -+ default: -+ return -EINVAL; -+ } -+ AXGMAC_IOWRITE(pdata, MAC_MDIOCL22R, reg_val); -+ -+ return 0; -+} -+ -+static int axgbe_read_mmd_regs_v2(struct axgbe_port *pdata, -+ int prtad __rte_unused, int mmd_reg) -+{ -+ unsigned int mmd_address, index, offset; -+ int mmd_data; -+ -+ if (mmd_reg & MII_ADDR_C45) -+ mmd_address = mmd_reg & ~MII_ADDR_C45; -+ else -+ mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff); -+ -+ /* The PCS registers are accessed using mmio. The underlying -+ * management interface uses indirect addressing to access the MMD -+ * register sets. This requires accessing of the PCS register in two -+ * phases, an address phase and a data phase. -+ * -+ * The mmio interface is based on 16-bit offsets and values. All -+ * register offsets must therefore be adjusted by left shifting the -+ * offset 1 bit and reading 16 bits of data. -+ */ -+ mmd_address <<= 1; -+ index = mmd_address & ~pdata->xpcs_window_mask; -+ offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask); -+ -+ pthread_mutex_lock(&pdata->xpcs_mutex); -+ -+ XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index); -+ mmd_data = XPCS16_IOREAD(pdata, offset); -+ -+ pthread_mutex_unlock(&pdata->xpcs_mutex); -+ -+ return mmd_data; -+} -+ -+static void axgbe_write_mmd_regs_v2(struct axgbe_port *pdata, -+ int prtad __rte_unused, -+ int mmd_reg, int mmd_data) -+{ -+ unsigned int mmd_address, index, offset; -+ -+ if (mmd_reg & MII_ADDR_C45) -+ mmd_address = mmd_reg & ~MII_ADDR_C45; -+ else -+ mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff); -+ -+ /* The PCS registers are accessed using mmio. The underlying -+ * management interface uses indirect addressing to access the MMD -+ * register sets. This requires accessing of the PCS register in two -+ * phases, an address phase and a data phase. -+ * -+ * The mmio interface is based on 16-bit offsets and values. All -+ * register offsets must therefore be adjusted by left shifting the -+ * offset 1 bit and writing 16 bits of data. -+ */ -+ mmd_address <<= 1; -+ index = mmd_address & ~pdata->xpcs_window_mask; -+ offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask); -+ -+ pthread_mutex_lock(&pdata->xpcs_mutex); -+ -+ XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index); -+ XPCS16_IOWRITE(pdata, offset, mmd_data); -+ -+ pthread_mutex_unlock(&pdata->xpcs_mutex); -+} -+ -+static int axgbe_read_mmd_regs(struct axgbe_port *pdata, int prtad, -+ int mmd_reg) -+{ -+ switch (pdata->vdata->xpcs_access) { -+ case AXGBE_XPCS_ACCESS_V1: -+ PMD_DRV_LOG(ERR, "PHY_Version 1 is not supported "); -+ return -1; -+ case AXGBE_XPCS_ACCESS_V2: -+ default: -+ return axgbe_read_mmd_regs_v2(pdata, prtad, mmd_reg); -+ } -+} -+ -+static void axgbe_write_mmd_regs(struct axgbe_port *pdata, int prtad, -+ int mmd_reg, int mmd_data) -+{ -+ switch (pdata->vdata->xpcs_access) { -+ case AXGBE_XPCS_ACCESS_V1: -+ PMD_DRV_LOG(ERR, "PHY_Version 1 is not supported "); -+ return; -+ case AXGBE_XPCS_ACCESS_V2: -+ default: -+ return axgbe_write_mmd_regs_v2(pdata, prtad, mmd_reg, mmd_data); -+ } -+} -+ - static int __axgbe_exit(struct axgbe_port *pdata) - { - unsigned int count = 2000; -@@ -164,4 +345,11 @@ static int axgbe_exit(struct axgbe_port *pdata) - void axgbe_init_function_ptrs_dev(struct axgbe_hw_if *hw_if) - { - hw_if->exit = axgbe_exit; -+ -+ hw_if->read_mmd_regs = axgbe_read_mmd_regs; -+ hw_if->write_mmd_regs = axgbe_write_mmd_regs; -+ -+ hw_if->set_ext_mii_mode = axgbe_set_ext_mii_mode; -+ hw_if->read_ext_mii_regs = axgbe_read_ext_mii_regs; -+ hw_if->write_ext_mii_regs = axgbe_write_ext_mii_regs; - } -diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c -index 786d929..0dc424d 100644 ---- a/drivers/net/axgbe/axgbe_ethdev.c -+++ b/drivers/net/axgbe/axgbe_ethdev.c -@@ -147,6 +147,7 @@ static const struct rte_pci_id pci_id_axgbe_map[] = { - }; - - static struct axgbe_version_data axgbe_v2a = { -+ .init_function_ptrs_phy_impl = axgbe_init_function_ptrs_phy_v2, - .xpcs_access = AXGBE_XPCS_ACCESS_V2, - .mmc_64bit = 1, - .tx_max_fifo_size = 229376, -@@ -157,6 +158,7 @@ static struct axgbe_version_data axgbe_v2a = { - }; - - static struct axgbe_version_data axgbe_v2b = { -+ .init_function_ptrs_phy_impl = axgbe_init_function_ptrs_phy_v2, - .xpcs_access = AXGBE_XPCS_ACCESS_V2, - .mmc_64bit = 1, - .tx_max_fifo_size = 65536, -@@ -271,6 +273,9 @@ static void axgbe_get_all_hw_features(struct axgbe_port *pdata) - static void axgbe_init_all_fptrs(struct axgbe_port *pdata) - { - axgbe_init_function_ptrs_dev(&pdata->hw_if); -+ axgbe_init_function_ptrs_phy(&pdata->phy_if); -+ axgbe_init_function_ptrs_i2c(&pdata->i2c_if); -+ pdata->vdata->init_function_ptrs_phy_impl(&pdata->phy_if); - } - - static void axgbe_set_counts(struct axgbe_port *pdata) -@@ -458,6 +463,12 @@ eth_axgbe_dev_init(struct rte_eth_dev *eth_dev) - pthread_mutex_init(&pdata->an_mutex, NULL); - pthread_mutex_init(&pdata->phy_mutex, NULL); - -+ ret = pdata->phy_if.phy_init(pdata); -+ if (ret) { -+ rte_free(eth_dev->data->mac_addrs); -+ return ret; -+ } -+ - PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x", - eth_dev->data->port_id, pci_dev->id.vendor_id, - pci_dev->id.device_id); -diff --git a/drivers/net/axgbe/axgbe_ethdev.h b/drivers/net/axgbe/axgbe_ethdev.h -index 5d20a1f..6cddb57 100644 ---- a/drivers/net/axgbe/axgbe_ethdev.h -+++ b/drivers/net/axgbe/axgbe_ethdev.h -@@ -311,6 +311,61 @@ enum axgbe_mdio_mode { - AXGBE_MDIO_MODE_CL45, - }; - -+struct axgbe_phy { -+ uint32_t supported; -+ uint32_t advertising; -+ uint32_t lp_advertising; -+ -+ int address; -+ -+ int autoneg; -+ int speed; -+ int duplex; -+ -+ int link; -+ -+ int pause_autoneg; -+ int tx_pause; -+ int rx_pause; -+}; -+ -+enum axgbe_i2c_cmd { -+ AXGBE_I2C_CMD_READ = 0, -+ AXGBE_I2C_CMD_WRITE, -+}; -+ -+struct axgbe_i2c_op { -+ enum axgbe_i2c_cmd cmd; -+ -+ unsigned int target; -+ -+ uint8_t *buf; -+ unsigned int len; -+}; -+ -+struct axgbe_i2c_op_state { -+ struct axgbe_i2c_op *op; -+ -+ unsigned int tx_len; -+ unsigned char *tx_buf; -+ -+ unsigned int rx_len; -+ unsigned char *rx_buf; -+ -+ unsigned int tx_abort_source; -+ -+ int ret; -+}; -+ -+struct axgbe_i2c { -+ unsigned int started; -+ unsigned int max_speed_mode; -+ unsigned int rx_fifo_size; -+ unsigned int tx_fifo_size; -+ -+ struct axgbe_i2c_op_state op_state; -+}; -+ - struct axgbe_hw_if { - void (*config_flow_control)(struct axgbe_port *); - int (*config_rx_mode)(struct axgbe_port *); -@@ -333,6 +388,89 @@ struct axgbe_hw_if { - int (*exit)(struct axgbe_port *); - }; - -+/* 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 axgbe_phy_impl_if { -+ /* Perform Setup/teardown actions */ -+ int (*init)(struct axgbe_port *); -+ void (*exit)(struct axgbe_port *); -+ -+ /* Perform start/stop specific actions */ -+ int (*reset)(struct axgbe_port *); -+ int (*start)(struct axgbe_port *); -+ void (*stop)(struct axgbe_port *); -+ -+ /* Return the link status */ -+ int (*link_status)(struct axgbe_port *, int *); -+ -+ /* Indicate if a particular speed is valid */ -+ int (*valid_speed)(struct axgbe_port *, int); -+ -+ /* Check if the specified mode can/should be used */ -+ bool (*use_mode)(struct axgbe_port *, enum axgbe_mode); -+ /* Switch the PHY into various modes */ -+ void (*set_mode)(struct axgbe_port *, enum axgbe_mode); -+ /* Retrieve mode needed for a specific speed */ -+ enum axgbe_mode (*get_mode)(struct axgbe_port *, int); -+ /* Retrieve new/next mode when trying to auto-negotiate */ -+ enum axgbe_mode (*switch_mode)(struct axgbe_port *); -+ /* Retrieve current mode */ -+ enum axgbe_mode (*cur_mode)(struct axgbe_port *); -+ -+ /* Retrieve current auto-negotiation mode */ -+ enum axgbe_an_mode (*an_mode)(struct axgbe_port *); -+ -+ /* Configure auto-negotiation settings */ -+ int (*an_config)(struct axgbe_port *); -+ -+ /* Set/override auto-negotiation advertisement settings */ -+ unsigned int (*an_advertising)(struct axgbe_port *port); -+ -+ /* Process results of auto-negotiation */ -+ enum axgbe_mode (*an_outcome)(struct axgbe_port *); -+ -+ /* Pre/Post KR training enablement support */ -+ void (*kr_training_pre)(struct axgbe_port *); -+ void (*kr_training_post)(struct axgbe_port *); -+}; -+ -+struct axgbe_phy_if { -+ /* For PHY setup/teardown */ -+ int (*phy_init)(struct axgbe_port *); -+ void (*phy_exit)(struct axgbe_port *); -+ -+ /* For PHY support when setting device up/down */ -+ int (*phy_reset)(struct axgbe_port *); -+ int (*phy_start)(struct axgbe_port *); -+ void (*phy_stop)(struct axgbe_port *); -+ -+ /* For PHY support while device is up */ -+ void (*phy_status)(struct axgbe_port *); -+ int (*phy_config_aneg)(struct axgbe_port *); -+ -+ /* For PHY settings validation */ -+ int (*phy_valid_speed)(struct axgbe_port *, int); -+ /* For single interrupt support */ -+ void (*an_isr)(struct axgbe_port *); -+ /* PHY implementation specific services */ -+ struct axgbe_phy_impl_if phy_impl; -+}; -+ -+struct axgbe_i2c_if { -+ /* For initial I2C setup */ -+ int (*i2c_init)(struct axgbe_port *); -+ -+ /* For I2C support when setting device up/down */ -+ int (*i2c_start)(struct axgbe_port *); -+ void (*i2c_stop)(struct axgbe_port *); -+ -+ /* For performing I2C operations */ -+ int (*i2c_xfer)(struct axgbe_port *, struct axgbe_i2c_op *); -+}; -+ - /* This structure contains flags that indicate what hardware features - * or configurations are present in the device. - */ -@@ -380,6 +518,7 @@ struct axgbe_hw_features { - }; - - struct axgbe_version_data { -+ void (*init_function_ptrs_phy_impl)(struct axgbe_phy_if *); - enum axgbe_xpcs_access xpcs_access; - unsigned int mmc_64bit; - unsigned int tx_max_fifo_size; -@@ -417,6 +556,8 @@ struct axgbe_port { - unsigned long dev_state; - - struct axgbe_hw_if hw_if; -+ struct axgbe_phy_if phy_if; -+ struct axgbe_i2c_if i2c_if; - - /* AXI DMA settings */ - unsigned int coherent; -@@ -488,7 +629,38 @@ struct axgbe_port { - struct axgbe_hw_features hw_feat; - - struct ether_addr mac_addr; -+ -+ /* MDIO/PHY related settings */ -+ unsigned int phy_started; -+ void *phy_data; -+ struct axgbe_phy phy; -+ int mdio_mmd; -+ unsigned long link_check; -+ volatile int mdio_completion; -+ -+ unsigned int kr_redrv; -+ -+ /* Auto-negotiation atate machine support */ -+ unsigned int an_int; -+ unsigned int an_status; -+ enum axgbe_an an_result; -+ enum axgbe_an an_state; -+ enum axgbe_rx kr_state; -+ enum axgbe_rx kx_state; -+ unsigned int an_supported; -+ unsigned int parallel_detect; -+ unsigned int fec_ability; -+ unsigned long an_start; -+ enum axgbe_an_mode an_mode; -+ -+ /* I2C support */ -+ struct axgbe_i2c i2c; -+ volatile int i2c_complete; - }; - - void axgbe_init_function_ptrs_dev(struct axgbe_hw_if *hw_if); -+void axgbe_init_function_ptrs_phy(struct axgbe_phy_if *phy_if); -+void axgbe_init_function_ptrs_phy_v2(struct axgbe_phy_if *phy_if); -+void axgbe_init_function_ptrs_i2c(struct axgbe_i2c_if *i2c_if); -+ - #endif /* RTE_ETH_AXGBE_H_ */ -diff --git a/drivers/net/axgbe/axgbe_i2c.c b/drivers/net/axgbe/axgbe_i2c.c -new file mode 100644 -index 0000000..468955e ---- /dev/null -+++ b/drivers/net/axgbe/axgbe_i2c.c -@@ -0,0 +1,453 @@ -+/*- -+ * Copyright(c) 2014-2017 Advanced Micro Devices, Inc. -+ * All rights reserved. -+ * -+ * AMD 10Gb Ethernet driver -+ * -+ * This file is available to you under your choice of the following two -+ * licenses: -+ * -+ * License 1: GPLv2 -+ * -+ * Copyright (c) 2017 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: -+ * -+ * Copyright (c) 2013 Synopsys, Inc. -+ * -+ * 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) 2017 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: -+ * -+ * Copyright (c) 2013 Synopsys, Inc. -+ * -+ * 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 "axgbe_ethdev.h" -+#include "axgbe_common.h" -+ -+#define AXGBE_ABORT_COUNT 500 -+#define AXGBE_DISABLE_COUNT 1000 -+ -+#define AXGBE_STD_SPEED 1 -+ -+#define AXGBE_INTR_RX_FULL BIT(IC_RAW_INTR_STAT_RX_FULL_INDEX) -+#define AXGBE_INTR_TX_EMPTY BIT(IC_RAW_INTR_STAT_TX_EMPTY_INDEX) -+#define AXGBE_INTR_TX_ABRT BIT(IC_RAW_INTR_STAT_TX_ABRT_INDEX) -+#define AXGBE_INTR_STOP_DET BIT(IC_RAW_INTR_STAT_STOP_DET_INDEX) -+#define AXGBE_DEFAULT_INT_MASK (AXGBE_INTR_RX_FULL | \ -+ AXGBE_INTR_TX_EMPTY | \ -+ AXGBE_INTR_TX_ABRT | \ -+ AXGBE_INTR_STOP_DET) -+ -+#define AXGBE_I2C_READ BIT(8) -+#define AXGBE_I2C_STOP BIT(9) -+ -+static int axgbe_i2c_abort(struct axgbe_port *pdata) -+{ -+ unsigned int wait = AXGBE_ABORT_COUNT; -+ -+ /* Must be enabled to recognize the abort request */ -+ XI2C_IOWRITE_BITS(pdata, IC_ENABLE, EN, 1); -+ -+ /* Issue the abort */ -+ XI2C_IOWRITE_BITS(pdata, IC_ENABLE, ABORT, 1); -+ -+ while (wait--) { -+ if (!XI2C_IOREAD_BITS(pdata, IC_ENABLE, ABORT)) -+ return 0; -+ rte_delay_us(500); -+ } -+ -+ return -EBUSY; -+} -+ -+static int axgbe_i2c_set_enable(struct axgbe_port *pdata, bool enable) -+{ -+ unsigned int wait = AXGBE_DISABLE_COUNT; -+ unsigned int mode = enable ? 1 : 0; -+ -+ while (wait--) { -+ XI2C_IOWRITE_BITS(pdata, IC_ENABLE, EN, mode); -+ if (XI2C_IOREAD_BITS(pdata, IC_ENABLE_STATUS, EN) == mode) -+ return 0; -+ -+ rte_delay_us(100); -+ } -+ -+ return -EBUSY; -+} -+ -+static int axgbe_i2c_disable(struct axgbe_port *pdata) -+{ -+ unsigned int ret; -+ -+ ret = axgbe_i2c_set_enable(pdata, false); -+ if (ret) { -+ /* Disable failed, try an abort */ -+ ret = axgbe_i2c_abort(pdata); -+ if (ret) -+ return ret; -+ -+ /* Abort succeeded, try to disable again */ -+ ret = axgbe_i2c_set_enable(pdata, false); -+ } -+ -+ return ret; -+} -+ -+static int axgbe_i2c_enable(struct axgbe_port *pdata) -+{ -+ return axgbe_i2c_set_enable(pdata, true); -+} -+ -+static void axgbe_i2c_clear_all_interrupts(struct axgbe_port *pdata) -+{ -+ XI2C_IOREAD(pdata, IC_CLR_INTR); -+} -+ -+static void axgbe_i2c_disable_interrupts(struct axgbe_port *pdata) -+{ -+ XI2C_IOWRITE(pdata, IC_INTR_MASK, 0); -+} -+ -+static void axgbe_i2c_enable_interrupts(struct axgbe_port *pdata) -+{ -+ XI2C_IOWRITE(pdata, IC_INTR_MASK, AXGBE_DEFAULT_INT_MASK); -+} -+ -+static void axgbe_i2c_write(struct axgbe_port *pdata) -+{ -+ struct axgbe_i2c_op_state *state = &pdata->i2c.op_state; -+ unsigned int tx_slots; -+ unsigned int cmd; -+ -+ /* Configured to never receive Rx overflows, so fill up Tx fifo */ -+ tx_slots = pdata->i2c.tx_fifo_size - XI2C_IOREAD(pdata, IC_TXFLR); -+ while (tx_slots && state->tx_len) { -+ if (state->op->cmd == AXGBE_I2C_CMD_READ) -+ cmd = AXGBE_I2C_READ; -+ else -+ cmd = *state->tx_buf++; -+ -+ if (state->tx_len == 1) -+ XI2C_SET_BITS(cmd, IC_DATA_CMD, STOP, 1); -+ -+ XI2C_IOWRITE(pdata, IC_DATA_CMD, cmd); -+ -+ tx_slots--; -+ state->tx_len--; -+ } -+ -+ /* No more Tx operations, so ignore TX_EMPTY and return */ -+ if (!state->tx_len) -+ XI2C_IOWRITE_BITS(pdata, IC_INTR_MASK, TX_EMPTY, 0); -+} -+ -+static void axgbe_i2c_read(struct axgbe_port *pdata) -+{ -+ struct axgbe_i2c_op_state *state = &pdata->i2c.op_state; -+ unsigned int rx_slots; -+ -+ /* Anything to be read? */ -+ if (state->op->cmd != AXGBE_I2C_CMD_READ) -+ return; -+ -+ rx_slots = XI2C_IOREAD(pdata, IC_RXFLR); -+ while (rx_slots && state->rx_len) { -+ *state->rx_buf++ = XI2C_IOREAD(pdata, IC_DATA_CMD); -+ state->rx_len--; -+ rx_slots--; -+ } -+} -+ -+static void axgbe_i2c_clear_isr_interrupts(struct axgbe_port *pdata, -+ unsigned int isr) -+{ -+ struct axgbe_i2c_op_state *state = &pdata->i2c.op_state; -+ -+ if (isr & AXGBE_INTR_TX_ABRT) { -+ state->tx_abort_source = XI2C_IOREAD(pdata, IC_TX_ABRT_SOURCE); -+ XI2C_IOREAD(pdata, IC_CLR_TX_ABRT); -+ } -+ -+ if (isr & AXGBE_INTR_STOP_DET) -+ XI2C_IOREAD(pdata, IC_CLR_STOP_DET); -+} -+ -+static int axgbe_i2c_isr(struct axgbe_port *pdata) -+{ -+ struct axgbe_i2c_op_state *state = &pdata->i2c.op_state; -+ unsigned int isr; -+ -+ isr = XI2C_IOREAD(pdata, IC_RAW_INTR_STAT); -+ -+ axgbe_i2c_clear_isr_interrupts(pdata, isr); -+ -+ if (isr & AXGBE_INTR_TX_ABRT) { -+ axgbe_i2c_disable_interrupts(pdata); -+ -+ state->ret = -EIO; -+ goto out; -+ } -+ -+ /* Check for data in the Rx fifo */ -+ axgbe_i2c_read(pdata); -+ -+ /* Fill up the Tx fifo next */ -+ axgbe_i2c_write(pdata); -+ -+out: -+ /* Complete on an error or STOP condition */ -+ if (state->ret || XI2C_GET_BITS(isr, IC_RAW_INTR_STAT, STOP_DET)) -+ return 1; -+ -+ return 0; -+} -+ -+static void axgbe_i2c_set_mode(struct axgbe_port *pdata) -+{ -+ unsigned int reg; -+ -+ reg = XI2C_IOREAD(pdata, IC_CON); -+ XI2C_SET_BITS(reg, IC_CON, MASTER_MODE, 1); -+ XI2C_SET_BITS(reg, IC_CON, SLAVE_DISABLE, 1); -+ XI2C_SET_BITS(reg, IC_CON, RESTART_EN, 1); -+ XI2C_SET_BITS(reg, IC_CON, SPEED, AXGBE_STD_SPEED); -+ XI2C_SET_BITS(reg, IC_CON, RX_FIFO_FULL_HOLD, 1); -+ XI2C_IOWRITE(pdata, IC_CON, reg); -+} -+ -+static void axgbe_i2c_get_features(struct axgbe_port *pdata) -+{ -+ struct axgbe_i2c *i2c = &pdata->i2c; -+ unsigned int reg; -+ -+ reg = XI2C_IOREAD(pdata, IC_COMP_PARAM_1); -+ i2c->max_speed_mode = XI2C_GET_BITS(reg, IC_COMP_PARAM_1, -+ MAX_SPEED_MODE); -+ i2c->rx_fifo_size = XI2C_GET_BITS(reg, IC_COMP_PARAM_1, -+ RX_BUFFER_DEPTH); -+ i2c->tx_fifo_size = XI2C_GET_BITS(reg, IC_COMP_PARAM_1, -+ TX_BUFFER_DEPTH); -+} -+ -+static void axgbe_i2c_set_target(struct axgbe_port *pdata, unsigned int addr) -+{ -+ XI2C_IOWRITE(pdata, IC_TAR, addr); -+} -+ -+static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op) -+{ -+ struct axgbe_i2c_op_state *state = &pdata->i2c.op_state; -+ int ret; -+ uint64_t timeout; -+ -+ pthread_mutex_lock(&pdata->i2c_mutex); -+ ret = axgbe_i2c_disable(pdata); -+ if (ret) { -+ PMD_DRV_LOG(ERR, "failed to disable i2c master"); -+ return ret; -+ } -+ -+ axgbe_i2c_set_target(pdata, op->target); -+ -+ memset(state, 0, sizeof(*state)); -+ state->op = op; -+ state->tx_len = op->len; -+ state->tx_buf = (unsigned char *)op->buf; -+ state->rx_len = op->len; -+ state->rx_buf = (unsigned char *)op->buf; -+ -+ axgbe_i2c_clear_all_interrupts(pdata); -+ ret = axgbe_i2c_enable(pdata); -+ if (ret) { -+ PMD_DRV_LOG(ERR, "failed to enable i2c master\n"); -+ return ret; -+ } -+ -+ /* Enabling the interrupts will cause the TX FIFO empty interrupt to -+ * fire and begin to process the command via the ISR. -+ */ -+ axgbe_i2c_enable_interrupts(pdata); -+ timeout = rte_get_timer_cycles() + rte_get_timer_hz(); -+ -+ while (time_before(rte_get_timer_cycles(), timeout)) { -+ rte_delay_us(100); -+ if (XI2C_IOREAD(pdata, IC_RAW_INTR_STAT)) { -+ if (axgbe_i2c_isr(pdata)) -+ goto success; -+ } -+ } -+ -+ PMD_DRV_LOG(ERR, "i2c operation timed out"); -+ axgbe_i2c_disable_interrupts(pdata); -+ axgbe_i2c_disable(pdata); -+ ret = -ETIMEDOUT; -+ goto unlock; -+ -+success: -+ ret = state->ret; -+ if (ret) { -+ if (state->tx_abort_source & IC_TX_ABRT_7B_ADDR_NOACK) -+ ret = -ENOTCONN; -+ else if (state->tx_abort_source & IC_TX_ABRT_ARB_LOST) -+ ret = -EAGAIN; -+ } -+ -+unlock: -+ pthread_mutex_unlock(&pdata->i2c_mutex); -+ return ret; -+} -+ -+static void axgbe_i2c_stop(struct axgbe_port *pdata) -+{ -+ if (!pdata->i2c.started) -+ return; -+ -+ pdata->i2c.started = 0; -+ axgbe_i2c_disable_interrupts(pdata); -+ axgbe_i2c_disable(pdata); -+ axgbe_i2c_clear_all_interrupts(pdata); -+} -+ -+static int axgbe_i2c_start(struct axgbe_port *pdata) -+{ -+ if (pdata->i2c.started) -+ return 0; -+ -+ pdata->i2c.started = 1; -+ -+ return 0; -+} -+ -+static int axgbe_i2c_init(struct axgbe_port *pdata) -+{ -+ int ret; -+ -+ axgbe_i2c_disable_interrupts(pdata); -+ -+ ret = axgbe_i2c_disable(pdata); -+ if (ret) { -+ PMD_DRV_LOG(ERR, "failed to disable i2c master"); -+ return ret; -+ } -+ -+ axgbe_i2c_get_features(pdata); -+ -+ axgbe_i2c_set_mode(pdata); -+ -+ axgbe_i2c_clear_all_interrupts(pdata); -+ -+ return 0; -+} -+ -+void axgbe_init_function_ptrs_i2c(struct axgbe_i2c_if *i2c_if) -+{ -+ i2c_if->i2c_init = axgbe_i2c_init; -+ i2c_if->i2c_start = axgbe_i2c_start; -+ i2c_if->i2c_stop = axgbe_i2c_stop; -+ i2c_if->i2c_xfer = axgbe_i2c_xfer; -+} -diff --git a/drivers/net/axgbe/axgbe_mdio.c b/drivers/net/axgbe/axgbe_mdio.c -new file mode 100644 -index 0000000..4fbf5c3 ---- /dev/null -+++ b/drivers/net/axgbe/axgbe_mdio.c -@@ -0,0 +1,203 @@ -+/*- -+ * Copyright(c) 2014-2017 Advanced Micro Devices, Inc. -+ * All rights reserved. -+ * -+ * AMD 10Gb Ethernet driver -+ * -+ * This file is available to you under your choice of the following two -+ * licenses: -+ * -+ * License 1: GPLv2 -+ * -+ * Copyright (c) 2017 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: -+ * -+ * Copyright (c) 2013 Synopsys, Inc. -+ * -+ * 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) 2017 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: -+ * -+ * Copyright (c) 2013 Synopsys, Inc. -+ * -+ * 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 "axgbe_ethdev.h" -+#include "axgbe_common.h" -+#include "axgbe_phy.h" -+ -+static int axgbe_phy_best_advertised_speed(struct axgbe_port *pdata) -+{ -+ if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full) -+ return SPEED_10000; -+ else if (pdata->phy.advertising & ADVERTISED_10000baseT_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; -+ else if (pdata->phy.advertising & ADVERTISED_1000baseT_Full) -+ return SPEED_1000; -+ else if (pdata->phy.advertising & ADVERTISED_100baseT_Full) -+ return SPEED_100; -+ -+ return SPEED_UNKNOWN; -+} -+ -+static int axgbe_phy_init(struct axgbe_port *pdata) -+{ -+ int ret; -+ -+ pdata->mdio_mmd = MDIO_MMD_PCS; -+ -+ /* 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); -+ -+ /* 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; -+ -+ 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 = axgbe_phy_best_advertised_speed(pdata); -+ pdata->phy.duplex = DUPLEX_FULL; -+ } -+ -+ pdata->phy.link = 0; -+ -+ pdata->phy.pause_autoneg = pdata->pause_autoneg; -+ pdata->phy.tx_pause = pdata->tx_pause; -+ pdata->phy.rx_pause = pdata->rx_pause; -+ -+ /* Fix up Flow Control advertising */ -+ pdata->phy.advertising &= ~ADVERTISED_Pause; -+ pdata->phy.advertising &= ~ADVERTISED_Asym_Pause; -+ -+ if (pdata->rx_pause) { -+ pdata->phy.advertising |= ADVERTISED_Pause; -+ pdata->phy.advertising |= ADVERTISED_Asym_Pause; -+ } -+ -+ if (pdata->tx_pause) -+ pdata->phy.advertising ^= ADVERTISED_Asym_Pause; -+ return 0; -+} -+ -+void axgbe_init_function_ptrs_phy(struct axgbe_phy_if *phy_if) -+{ -+ phy_if->phy_init = axgbe_phy_init; -+} -diff --git a/drivers/net/axgbe/axgbe_phy_impl.c b/drivers/net/axgbe/axgbe_phy_impl.c -new file mode 100644 -index 0000000..cea4266 ---- /dev/null -+++ b/drivers/net/axgbe/axgbe_phy_impl.c -@@ -0,0 +1,799 @@ -+/*- -+ * Copyright(c) 2014-2017 Advanced Micro Devices, Inc. -+ * All rights reserved. -+ * -+ * AMD 10Gb Ethernet driver -+ * -+ * This file is available to you under your choice of the following two -+ * licenses: -+ * -+ * License 1: GPLv2 -+ * -+ * Copyright (c) 2017 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: -+ * -+ * Copyright (c) 2013 Synopsys, Inc. -+ * -+ * 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) 2017 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: -+ * -+ * Copyright (c) 2013 Synopsys, Inc. -+ * -+ * 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 "axgbe_ethdev.h" -+#include "axgbe_common.h" -+#include "axgbe_phy.h" -+ -+#define AXGBE_PHY_PORT_SPEED_100 BIT(0) -+#define AXGBE_PHY_PORT_SPEED_1000 BIT(1) -+#define AXGBE_PHY_PORT_SPEED_2500 BIT(2) -+#define AXGBE_PHY_PORT_SPEED_10000 BIT(3) -+ -+#define AXGBE_MUTEX_RELEASE 0x80000000 -+ -+#define AXGBE_SFP_DIRECT 7 -+ -+/* I2C target addresses */ -+#define AXGBE_SFP_SERIAL_ID_ADDRESS 0x50 -+#define AXGBE_SFP_DIAG_INFO_ADDRESS 0x51 -+#define AXGBE_SFP_PHY_ADDRESS 0x56 -+#define AXGBE_GPIO_ADDRESS_PCA9555 0x20 -+ -+/* SFP sideband signal indicators */ -+#define AXGBE_GPIO_NO_TX_FAULT BIT(0) -+#define AXGBE_GPIO_NO_RATE_SELECT BIT(1) -+#define AXGBE_GPIO_NO_MOD_ABSENT BIT(2) -+#define AXGBE_GPIO_NO_RX_LOS BIT(3) -+ -+/* Rate-change complete wait/retry count */ -+#define AXGBE_RATECHANGE_COUNT 500 -+ -+enum axgbe_port_mode { -+ AXGBE_PORT_MODE_RSVD = 0, -+ AXGBE_PORT_MODE_BACKPLANE, -+ AXGBE_PORT_MODE_BACKPLANE_2500, -+ AXGBE_PORT_MODE_1000BASE_T, -+ AXGBE_PORT_MODE_1000BASE_X, -+ AXGBE_PORT_MODE_NBASE_T, -+ AXGBE_PORT_MODE_10GBASE_T, -+ AXGBE_PORT_MODE_10GBASE_R, -+ AXGBE_PORT_MODE_SFP, -+ AXGBE_PORT_MODE_MAX, -+}; -+ -+enum axgbe_conn_type { -+ AXGBE_CONN_TYPE_NONE = 0, -+ AXGBE_CONN_TYPE_SFP, -+ AXGBE_CONN_TYPE_MDIO, -+ AXGBE_CONN_TYPE_RSVD1, -+ AXGBE_CONN_TYPE_BACKPLANE, -+ AXGBE_CONN_TYPE_MAX, -+}; -+ -+/* SFP/SFP+ related definitions */ -+enum axgbe_sfp_comm { -+ AXGBE_SFP_COMM_DIRECT = 0, -+ AXGBE_SFP_COMM_PCA9545, -+}; -+ -+enum axgbe_sfp_cable { -+ AXGBE_SFP_CABLE_UNKNOWN = 0, -+ AXGBE_SFP_CABLE_ACTIVE, -+ AXGBE_SFP_CABLE_PASSIVE, -+}; -+ -+enum axgbe_sfp_base { -+ AXGBE_SFP_BASE_UNKNOWN = 0, -+ AXGBE_SFP_BASE_1000_T, -+ AXGBE_SFP_BASE_1000_SX, -+ AXGBE_SFP_BASE_1000_LX, -+ AXGBE_SFP_BASE_1000_CX, -+ AXGBE_SFP_BASE_10000_SR, -+ AXGBE_SFP_BASE_10000_LR, -+ AXGBE_SFP_BASE_10000_LRM, -+ AXGBE_SFP_BASE_10000_ER, -+ AXGBE_SFP_BASE_10000_CR, -+}; -+ -+enum axgbe_sfp_speed { -+ AXGBE_SFP_SPEED_UNKNOWN = 0, -+ AXGBE_SFP_SPEED_100_1000, -+ AXGBE_SFP_SPEED_1000, -+ AXGBE_SFP_SPEED_10000, -+}; -+ -+/* SFP Serial ID Base ID values relative to an offset of 0 */ -+#define AXGBE_SFP_BASE_ID 0 -+#define AXGBE_SFP_ID_SFP 0x03 -+ -+#define AXGBE_SFP_BASE_EXT_ID 1 -+#define AXGBE_SFP_EXT_ID_SFP 0x04 -+ -+#define AXGBE_SFP_BASE_10GBE_CC 3 -+#define AXGBE_SFP_BASE_10GBE_CC_SR BIT(4) -+#define AXGBE_SFP_BASE_10GBE_CC_LR BIT(5) -+#define AXGBE_SFP_BASE_10GBE_CC_LRM BIT(6) -+#define AXGBE_SFP_BASE_10GBE_CC_ER BIT(7) -+ -+#define AXGBE_SFP_BASE_1GBE_CC 6 -+#define AXGBE_SFP_BASE_1GBE_CC_SX BIT(0) -+#define AXGBE_SFP_BASE_1GBE_CC_LX BIT(1) -+#define AXGBE_SFP_BASE_1GBE_CC_CX BIT(2) -+#define AXGBE_SFP_BASE_1GBE_CC_T BIT(3) -+ -+#define AXGBE_SFP_BASE_CABLE 8 -+#define AXGBE_SFP_BASE_CABLE_PASSIVE BIT(2) -+#define AXGBE_SFP_BASE_CABLE_ACTIVE BIT(3) -+ -+#define AXGBE_SFP_BASE_BR 12 -+#define AXGBE_SFP_BASE_BR_1GBE_MIN 0x0a -+#define AXGBE_SFP_BASE_BR_1GBE_MAX 0x0d -+#define AXGBE_SFP_BASE_BR_10GBE_MIN 0x64 -+#define AXGBE_SFP_BASE_BR_10GBE_MAX 0x68 -+ -+#define AXGBE_SFP_BASE_CU_CABLE_LEN 18 -+ -+#define AXGBE_SFP_BASE_VENDOR_NAME 20 -+#define AXGBE_SFP_BASE_VENDOR_NAME_LEN 16 -+#define AXGBE_SFP_BASE_VENDOR_PN 40 -+#define AXGBE_SFP_BASE_VENDOR_PN_LEN 16 -+#define AXGBE_SFP_BASE_VENDOR_REV 56 -+#define AXGBE_SFP_BASE_VENDOR_REV_LEN 4 -+ -+#define AXGBE_SFP_BASE_CC 63 -+ -+/* SFP Serial ID Extended ID values relative to an offset of 64 */ -+#define AXGBE_SFP_BASE_VENDOR_SN 4 -+#define AXGBE_SFP_BASE_VENDOR_SN_LEN 16 -+ -+#define AXGBE_SFP_EXTD_DIAG 28 -+#define AXGBE_SFP_EXTD_DIAG_ADDR_CHANGE BIT(2) -+ -+#define AXGBE_SFP_EXTD_SFF_8472 30 -+ -+#define AXGBE_SFP_EXTD_CC 31 -+ -+struct axgbe_sfp_eeprom { -+ u8 base[64]; -+ u8 extd[32]; -+ u8 vendor[32]; -+}; -+ -+#define AXGBE_BEL_FUSE_VENDOR "BEL-FUSE" -+#define AXGBE_BEL_FUSE_PARTNO "1GBT-SFP06" -+ -+struct axgbe_sfp_ascii { -+ union { -+ char vendor[AXGBE_SFP_BASE_VENDOR_NAME_LEN + 1]; -+ char partno[AXGBE_SFP_BASE_VENDOR_PN_LEN + 1]; -+ char rev[AXGBE_SFP_BASE_VENDOR_REV_LEN + 1]; -+ char serno[AXGBE_SFP_BASE_VENDOR_SN_LEN + 1]; -+ } u; -+}; -+ -+/* MDIO PHY reset types */ -+enum axgbe_mdio_reset { -+ AXGBE_MDIO_RESET_NONE = 0, -+ AXGBE_MDIO_RESET_I2C_GPIO, -+ AXGBE_MDIO_RESET_INT_GPIO, -+ AXGBE_MDIO_RESET_MAX, -+}; -+ -+/* Re-driver related definitions */ -+enum axgbe_phy_redrv_if { -+ AXGBE_PHY_REDRV_IF_MDIO = 0, -+ AXGBE_PHY_REDRV_IF_I2C, -+ AXGBE_PHY_REDRV_IF_MAX, -+}; -+ -+enum axgbe_phy_redrv_model { -+ AXGBE_PHY_REDRV_MODEL_4223 = 0, -+ AXGBE_PHY_REDRV_MODEL_4227, -+ AXGBE_PHY_REDRV_MODEL_MAX, -+}; -+ -+enum axgbe_phy_redrv_mode { -+ AXGBE_PHY_REDRV_MODE_CX = 5, -+ AXGBE_PHY_REDRV_MODE_SR = 9, -+}; -+ -+#define AXGBE_PHY_REDRV_MODE_REG 0x12b0 -+ -+/* PHY related configuration information */ -+struct axgbe_phy_data { -+ enum axgbe_port_mode port_mode; -+ -+ unsigned int port_id; -+ -+ unsigned int port_speeds; -+ -+ enum axgbe_conn_type conn_type; -+ -+ enum axgbe_mode cur_mode; -+ enum axgbe_mode start_mode; -+ -+ unsigned int rrc_count; -+ -+ unsigned int mdio_addr; -+ -+ unsigned int comm_owned; -+ -+ /* SFP Support */ -+ enum axgbe_sfp_comm sfp_comm; -+ unsigned int sfp_mux_address; -+ unsigned int sfp_mux_channel; -+ -+ unsigned int sfp_gpio_address; -+ unsigned int sfp_gpio_mask; -+ unsigned int sfp_gpio_rx_los; -+ unsigned int sfp_gpio_tx_fault; -+ unsigned int sfp_gpio_mod_absent; -+ unsigned int sfp_gpio_rate_select; -+ -+ unsigned int sfp_rx_los; -+ unsigned int sfp_tx_fault; -+ unsigned int sfp_mod_absent; -+ unsigned int sfp_diags; -+ unsigned int sfp_changed; -+ unsigned int sfp_phy_avail; -+ unsigned int sfp_cable_len; -+ enum axgbe_sfp_base sfp_base; -+ enum axgbe_sfp_cable sfp_cable; -+ enum axgbe_sfp_speed sfp_speed; -+ struct axgbe_sfp_eeprom sfp_eeprom; -+ -+ /* External PHY support */ -+ enum axgbe_mdio_mode phydev_mode; -+ enum axgbe_mdio_reset mdio_reset; -+ unsigned int mdio_reset_addr; -+ unsigned int mdio_reset_gpio; -+ -+ /* Re-driver support */ -+ unsigned int redrv; -+ unsigned int redrv_if; -+ unsigned int redrv_addr; -+ unsigned int redrv_lane; -+ unsigned int redrv_model; -+}; -+ -+static void axgbe_phy_sfp_gpio_setup(struct axgbe_port *pdata) -+{ -+ struct axgbe_phy_data *phy_data = pdata->phy_data; -+ unsigned int reg; -+ -+ reg = XP_IOREAD(pdata, XP_PROP_3); -+ -+ phy_data->sfp_gpio_address = AXGBE_GPIO_ADDRESS_PCA9555 + -+ XP_GET_BITS(reg, XP_PROP_3, GPIO_ADDR); -+ -+ phy_data->sfp_gpio_mask = XP_GET_BITS(reg, XP_PROP_3, GPIO_MASK); -+ -+ phy_data->sfp_gpio_rx_los = XP_GET_BITS(reg, XP_PROP_3, -+ GPIO_RX_LOS); -+ phy_data->sfp_gpio_tx_fault = XP_GET_BITS(reg, XP_PROP_3, -+ GPIO_TX_FAULT); -+ phy_data->sfp_gpio_mod_absent = XP_GET_BITS(reg, XP_PROP_3, -+ GPIO_MOD_ABS); -+ phy_data->sfp_gpio_rate_select = XP_GET_BITS(reg, XP_PROP_3, -+ GPIO_RATE_SELECT); -+} -+ -+static void axgbe_phy_sfp_comm_setup(struct axgbe_port *pdata) -+{ -+ struct axgbe_phy_data *phy_data = pdata->phy_data; -+ unsigned int reg, mux_addr_hi, mux_addr_lo; -+ -+ reg = XP_IOREAD(pdata, XP_PROP_4); -+ -+ mux_addr_hi = XP_GET_BITS(reg, XP_PROP_4, MUX_ADDR_HI); -+ mux_addr_lo = XP_GET_BITS(reg, XP_PROP_4, MUX_ADDR_LO); -+ if (mux_addr_lo == AXGBE_SFP_DIRECT) -+ return; -+ -+ phy_data->sfp_comm = AXGBE_SFP_COMM_PCA9545; -+ phy_data->sfp_mux_address = (mux_addr_hi << 2) + mux_addr_lo; -+ phy_data->sfp_mux_channel = XP_GET_BITS(reg, XP_PROP_4, MUX_CHAN); -+} -+ -+static void axgbe_phy_sfp_setup(struct axgbe_port *pdata) -+{ -+ axgbe_phy_sfp_comm_setup(pdata); -+ axgbe_phy_sfp_gpio_setup(pdata); -+} -+ -+static bool axgbe_phy_redrv_error(struct axgbe_phy_data *phy_data) -+{ -+ if (!phy_data->redrv) -+ return false; -+ -+ if (phy_data->redrv_if >= AXGBE_PHY_REDRV_IF_MAX) -+ return true; -+ -+ switch (phy_data->redrv_model) { -+ case AXGBE_PHY_REDRV_MODEL_4223: -+ if (phy_data->redrv_lane > 3) -+ return true; -+ break; -+ case AXGBE_PHY_REDRV_MODEL_4227: -+ if (phy_data->redrv_lane > 1) -+ return true; -+ break; -+ default: -+ return true; -+ } -+ -+ return false; -+} -+ -+static int axgbe_phy_mdio_reset_setup(struct axgbe_port *pdata) -+{ -+ struct axgbe_phy_data *phy_data = pdata->phy_data; -+ unsigned int reg; -+ -+ if (phy_data->conn_type != AXGBE_CONN_TYPE_MDIO) -+ return 0; -+ reg = XP_IOREAD(pdata, XP_PROP_3); -+ phy_data->mdio_reset = XP_GET_BITS(reg, XP_PROP_3, MDIO_RESET); -+ switch (phy_data->mdio_reset) { -+ case AXGBE_MDIO_RESET_NONE: -+ case AXGBE_MDIO_RESET_I2C_GPIO: -+ case AXGBE_MDIO_RESET_INT_GPIO: -+ break; -+ default: -+ PMD_DRV_LOG(ERR, "unsupported MDIO reset (%#x)\n", -+ phy_data->mdio_reset); -+ return -EINVAL; -+ } -+ if (phy_data->mdio_reset == AXGBE_MDIO_RESET_I2C_GPIO) { -+ phy_data->mdio_reset_addr = AXGBE_GPIO_ADDRESS_PCA9555 + -+ XP_GET_BITS(reg, XP_PROP_3, -+ MDIO_RESET_I2C_ADDR); -+ phy_data->mdio_reset_gpio = XP_GET_BITS(reg, XP_PROP_3, -+ MDIO_RESET_I2C_GPIO); -+ } else if (phy_data->mdio_reset == AXGBE_MDIO_RESET_INT_GPIO) { -+ phy_data->mdio_reset_gpio = XP_GET_BITS(reg, XP_PROP_3, -+ MDIO_RESET_INT_GPIO); -+ } -+ -+ return 0; -+} -+ -+static bool axgbe_phy_port_mode_mismatch(struct axgbe_port *pdata) -+{ -+ struct axgbe_phy_data *phy_data = pdata->phy_data; -+ -+ switch (phy_data->port_mode) { -+ case AXGBE_PORT_MODE_BACKPLANE: -+ if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || -+ (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)) -+ return false; -+ break; -+ case AXGBE_PORT_MODE_BACKPLANE_2500: -+ if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500) -+ return false; -+ break; -+ case AXGBE_PORT_MODE_1000BASE_T: -+ if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || -+ (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000)) -+ return false; -+ break; -+ case AXGBE_PORT_MODE_1000BASE_X: -+ if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) -+ return false; -+ break; -+ case AXGBE_PORT_MODE_NBASE_T: -+ if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || -+ (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || -+ (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500)) -+ return false; -+ break; -+ case AXGBE_PORT_MODE_10GBASE_T: -+ if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || -+ (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || -+ (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)) -+ return false; -+ break; -+ case AXGBE_PORT_MODE_10GBASE_R: -+ if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) -+ return false; -+ break; -+ case AXGBE_PORT_MODE_SFP: -+ if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || -+ (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || -+ (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)) -+ return false; -+ break; -+ default: -+ break; -+ } -+ -+ return true; -+} -+ -+static bool axgbe_phy_conn_type_mismatch(struct axgbe_port *pdata) -+{ -+ struct axgbe_phy_data *phy_data = pdata->phy_data; -+ -+ switch (phy_data->port_mode) { -+ case AXGBE_PORT_MODE_BACKPLANE: -+ case AXGBE_PORT_MODE_BACKPLANE_2500: -+ if (phy_data->conn_type == AXGBE_CONN_TYPE_BACKPLANE) -+ return false; -+ break; -+ case AXGBE_PORT_MODE_1000BASE_T: -+ case AXGBE_PORT_MODE_1000BASE_X: -+ case AXGBE_PORT_MODE_NBASE_T: -+ case AXGBE_PORT_MODE_10GBASE_T: -+ case AXGBE_PORT_MODE_10GBASE_R: -+ if (phy_data->conn_type == AXGBE_CONN_TYPE_MDIO) -+ return false; -+ break; -+ case AXGBE_PORT_MODE_SFP: -+ if (phy_data->conn_type == AXGBE_CONN_TYPE_SFP) -+ return false; -+ break; -+ default: -+ break; -+ } -+ -+ return true; -+} -+ -+static bool axgbe_phy_port_enabled(struct axgbe_port *pdata) -+{ -+ unsigned int reg; -+ -+ reg = XP_IOREAD(pdata, XP_PROP_0); -+ if (!XP_GET_BITS(reg, XP_PROP_0, PORT_SPEEDS)) -+ return false; -+ if (!XP_GET_BITS(reg, XP_PROP_0, CONN_TYPE)) -+ return false; -+ -+ return true; -+} -+ -+static int axgbe_phy_init(struct axgbe_port *pdata) -+{ -+ struct axgbe_phy_data *phy_data; -+ unsigned int reg; -+ int ret; -+ -+ /* Check if enabled */ -+ if (!axgbe_phy_port_enabled(pdata)) { -+ PMD_DRV_LOG(ERR, "device is not enabled"); -+ return -ENODEV; -+ } -+ -+ /* Initialize the I2C controller */ -+ ret = pdata->i2c_if.i2c_init(pdata); -+ if (ret) -+ return ret; -+ -+ phy_data = rte_zmalloc("phy_data memory", sizeof(*phy_data), 0); -+ if (!phy_data) { -+ PMD_DRV_LOG(ERR, "phy_data allocation failed"); -+ return -ENOMEM; -+ } -+ pdata->phy_data = phy_data; -+ -+ reg = XP_IOREAD(pdata, XP_PROP_0); -+ phy_data->port_mode = XP_GET_BITS(reg, XP_PROP_0, PORT_MODE); -+ phy_data->port_id = XP_GET_BITS(reg, XP_PROP_0, PORT_ID); -+ phy_data->port_speeds = XP_GET_BITS(reg, XP_PROP_0, PORT_SPEEDS); -+ phy_data->conn_type = XP_GET_BITS(reg, XP_PROP_0, CONN_TYPE); -+ phy_data->mdio_addr = XP_GET_BITS(reg, XP_PROP_0, MDIO_ADDR); -+ -+ reg = XP_IOREAD(pdata, XP_PROP_4); -+ phy_data->redrv = XP_GET_BITS(reg, XP_PROP_4, REDRV_PRESENT); -+ phy_data->redrv_if = XP_GET_BITS(reg, XP_PROP_4, REDRV_IF); -+ phy_data->redrv_addr = XP_GET_BITS(reg, XP_PROP_4, REDRV_ADDR); -+ phy_data->redrv_lane = XP_GET_BITS(reg, XP_PROP_4, REDRV_LANE); -+ phy_data->redrv_model = XP_GET_BITS(reg, XP_PROP_4, REDRV_MODEL); -+ -+ /* Validate the connection requested */ -+ if (axgbe_phy_conn_type_mismatch(pdata)) { -+ PMD_DRV_LOG(ERR, "phy mode/connection mismatch (%#x/%#x)", -+ phy_data->port_mode, phy_data->conn_type); -+ return -EINVAL; -+ } -+ -+ /* Validate the mode requested */ -+ if (axgbe_phy_port_mode_mismatch(pdata)) { -+ PMD_DRV_LOG(ERR, "phy mode/speed mismatch (%#x/%#x)", -+ phy_data->port_mode, phy_data->port_speeds); -+ return -EINVAL; -+ } -+ -+ /* Check for and validate MDIO reset support */ -+ ret = axgbe_phy_mdio_reset_setup(pdata); -+ if (ret) -+ return ret; -+ -+ /* Validate the re-driver information */ -+ if (axgbe_phy_redrv_error(phy_data)) { -+ PMD_DRV_LOG(ERR, "phy re-driver settings error"); -+ return -EINVAL; -+ } -+ pdata->kr_redrv = phy_data->redrv; -+ -+ /* Indicate current mode is unknown */ -+ phy_data->cur_mode = AXGBE_MODE_UNKNOWN; -+ -+ /* Initialize supported features */ -+ pdata->phy.supported = 0; -+ -+ switch (phy_data->port_mode) { -+ /* Backplane support */ -+ case AXGBE_PORT_MODE_BACKPLANE: -+ pdata->phy.supported |= SUPPORTED_Autoneg; -+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; -+ pdata->phy.supported |= SUPPORTED_Backplane; -+ if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { -+ pdata->phy.supported |= SUPPORTED_1000baseKX_Full; -+ phy_data->start_mode = AXGBE_MODE_KX_1000; -+ } -+ if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) { -+ pdata->phy.supported |= SUPPORTED_10000baseKR_Full; -+ if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) -+ pdata->phy.supported |= -+ SUPPORTED_10000baseR_FEC; -+ phy_data->start_mode = AXGBE_MODE_KR; -+ } -+ -+ phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; -+ break; -+ case AXGBE_PORT_MODE_BACKPLANE_2500: -+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; -+ pdata->phy.supported |= SUPPORTED_Backplane; -+ pdata->phy.supported |= SUPPORTED_2500baseX_Full; -+ phy_data->start_mode = AXGBE_MODE_KX_2500; -+ -+ phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; -+ break; -+ -+ /* MDIO 1GBase-T support */ -+ case AXGBE_PORT_MODE_1000BASE_T: -+ pdata->phy.supported |= SUPPORTED_Autoneg; -+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; -+ pdata->phy.supported |= SUPPORTED_TP; -+ if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { -+ pdata->phy.supported |= SUPPORTED_100baseT_Full; -+ phy_data->start_mode = AXGBE_MODE_SGMII_100; -+ } -+ if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { -+ pdata->phy.supported |= SUPPORTED_1000baseT_Full; -+ phy_data->start_mode = AXGBE_MODE_SGMII_1000; -+ } -+ -+ phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22; -+ break; -+ -+ /* MDIO Base-X support */ -+ case AXGBE_PORT_MODE_1000BASE_X: -+ pdata->phy.supported |= SUPPORTED_Autoneg; -+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; -+ pdata->phy.supported |= SUPPORTED_FIBRE; -+ pdata->phy.supported |= SUPPORTED_1000baseT_Full; -+ phy_data->start_mode = AXGBE_MODE_X; -+ -+ phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22; -+ break; -+ -+ /* MDIO NBase-T support */ -+ case AXGBE_PORT_MODE_NBASE_T: -+ pdata->phy.supported |= SUPPORTED_Autoneg; -+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; -+ pdata->phy.supported |= SUPPORTED_TP; -+ if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { -+ pdata->phy.supported |= SUPPORTED_100baseT_Full; -+ phy_data->start_mode = AXGBE_MODE_SGMII_100; -+ } -+ if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { -+ pdata->phy.supported |= SUPPORTED_1000baseT_Full; -+ phy_data->start_mode = AXGBE_MODE_SGMII_1000; -+ } -+ if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500) { -+ pdata->phy.supported |= SUPPORTED_2500baseX_Full; -+ phy_data->start_mode = AXGBE_MODE_KX_2500; -+ } -+ -+ phy_data->phydev_mode = AXGBE_MDIO_MODE_CL45; -+ break; -+ -+ /* 10GBase-T support */ -+ case AXGBE_PORT_MODE_10GBASE_T: -+ pdata->phy.supported |= SUPPORTED_Autoneg; -+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; -+ pdata->phy.supported |= SUPPORTED_TP; -+ if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { -+ pdata->phy.supported |= SUPPORTED_100baseT_Full; -+ phy_data->start_mode = AXGBE_MODE_SGMII_100; -+ } -+ if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { -+ pdata->phy.supported |= SUPPORTED_1000baseT_Full; -+ phy_data->start_mode = AXGBE_MODE_SGMII_1000; -+ } -+ if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) { -+ pdata->phy.supported |= SUPPORTED_10000baseT_Full; -+ phy_data->start_mode = AXGBE_MODE_KR; -+ } -+ -+ phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; -+ break; -+ -+ /* 10GBase-R support */ -+ case AXGBE_PORT_MODE_10GBASE_R: -+ pdata->phy.supported |= SUPPORTED_Autoneg; -+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; -+ pdata->phy.supported |= SUPPORTED_TP; -+ pdata->phy.supported |= SUPPORTED_10000baseT_Full; -+ if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) -+ pdata->phy.supported |= SUPPORTED_10000baseR_FEC; -+ phy_data->start_mode = AXGBE_MODE_SFI; -+ -+ phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; -+ break; -+ -+ /* SFP support */ -+ case AXGBE_PORT_MODE_SFP: -+ pdata->phy.supported |= SUPPORTED_Autoneg; -+ pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; -+ pdata->phy.supported |= SUPPORTED_TP; -+ pdata->phy.supported |= SUPPORTED_FIBRE; -+ if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { -+ pdata->phy.supported |= SUPPORTED_100baseT_Full; -+ phy_data->start_mode = AXGBE_MODE_SGMII_100; -+ } -+ if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { -+ pdata->phy.supported |= SUPPORTED_1000baseT_Full; -+ phy_data->start_mode = AXGBE_MODE_SGMII_1000; -+ } -+ if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) { -+ pdata->phy.supported |= SUPPORTED_10000baseT_Full; -+ phy_data->start_mode = AXGBE_MODE_SFI; -+ if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) -+ pdata->phy.supported |= -+ SUPPORTED_10000baseR_FEC; -+ } -+ -+ phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22; -+ -+ axgbe_phy_sfp_setup(pdata); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ if ((phy_data->conn_type & AXGBE_CONN_TYPE_MDIO) && -+ (phy_data->phydev_mode != AXGBE_MDIO_MODE_NONE)) { -+ ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->mdio_addr, -+ phy_data->phydev_mode); -+ if (ret) { -+ PMD_DRV_LOG(ERR, "mdio port/clause not compatible (%d/%u)", -+ phy_data->mdio_addr, phy_data->phydev_mode); -+ return -EINVAL; -+ } -+ } -+ -+ if (phy_data->redrv && !phy_data->redrv_if) { -+ ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->redrv_addr, -+ AXGBE_MDIO_MODE_CL22); -+ if (ret) { -+ PMD_DRV_LOG(ERR, "redriver mdio port not compatible (%u)", -+ phy_data->redrv_addr); -+ return -EINVAL; -+ } -+ } -+ return 0; -+} -+void axgbe_init_function_ptrs_phy_v2(struct axgbe_phy_if *phy_if) -+{ -+ struct axgbe_phy_impl_if *phy_impl = &phy_if->phy_impl; -+ -+ phy_impl->init = axgbe_phy_init; -+} |