18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * AMD 10Gb Ethernet driver
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * This file is available to you under your choice of the following two
58c2ecf20Sopenharmony_ci * licenses:
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * License 1: GPLv2
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * This file is free software; you may copy, redistribute and/or modify
128c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License as published by
138c2ecf20Sopenharmony_ci * the Free Software Foundation, either version 2 of the License, or (at
148c2ecf20Sopenharmony_ci * your option) any later version.
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci * This file is distributed in the hope that it will be useful, but
178c2ecf20Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of
188c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
198c2ecf20Sopenharmony_ci * General Public License for more details.
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci * You should have received a copy of the GNU General Public License
228c2ecf20Sopenharmony_ci * along with this program.  If not, see <http://www.gnu.org/licenses/>.
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci * This file incorporates work covered by the following copyright and
258c2ecf20Sopenharmony_ci * permission notice:
268c2ecf20Sopenharmony_ci *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
278c2ecf20Sopenharmony_ci *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
288c2ecf20Sopenharmony_ci *     Inc. unless otherwise expressly agreed to in writing between Synopsys
298c2ecf20Sopenharmony_ci *     and you.
308c2ecf20Sopenharmony_ci *
318c2ecf20Sopenharmony_ci *     The Software IS NOT an item of Licensed Software or Licensed Product
328c2ecf20Sopenharmony_ci *     under any End User Software License Agreement or Agreement for Licensed
338c2ecf20Sopenharmony_ci *     Product with Synopsys or any supplement thereto.  Permission is hereby
348c2ecf20Sopenharmony_ci *     granted, free of charge, to any person obtaining a copy of this software
358c2ecf20Sopenharmony_ci *     annotated with this license and the Software, to deal in the Software
368c2ecf20Sopenharmony_ci *     without restriction, including without limitation the rights to use,
378c2ecf20Sopenharmony_ci *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
388c2ecf20Sopenharmony_ci *     of the Software, and to permit persons to whom the Software is furnished
398c2ecf20Sopenharmony_ci *     to do so, subject to the following conditions:
408c2ecf20Sopenharmony_ci *
418c2ecf20Sopenharmony_ci *     The above copyright notice and this permission notice shall be included
428c2ecf20Sopenharmony_ci *     in all copies or substantial portions of the Software.
438c2ecf20Sopenharmony_ci *
448c2ecf20Sopenharmony_ci *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
458c2ecf20Sopenharmony_ci *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
468c2ecf20Sopenharmony_ci *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
478c2ecf20Sopenharmony_ci *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
488c2ecf20Sopenharmony_ci *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
498c2ecf20Sopenharmony_ci *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
508c2ecf20Sopenharmony_ci *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
518c2ecf20Sopenharmony_ci *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
528c2ecf20Sopenharmony_ci *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
538c2ecf20Sopenharmony_ci *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
548c2ecf20Sopenharmony_ci *     THE POSSIBILITY OF SUCH DAMAGE.
558c2ecf20Sopenharmony_ci *
568c2ecf20Sopenharmony_ci *
578c2ecf20Sopenharmony_ci * License 2: Modified BSD
588c2ecf20Sopenharmony_ci *
598c2ecf20Sopenharmony_ci * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
608c2ecf20Sopenharmony_ci * All rights reserved.
618c2ecf20Sopenharmony_ci *
628c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
638c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions are met:
648c2ecf20Sopenharmony_ci *     * Redistributions of source code must retain the above copyright
658c2ecf20Sopenharmony_ci *       notice, this list of conditions and the following disclaimer.
668c2ecf20Sopenharmony_ci *     * Redistributions in binary form must reproduce the above copyright
678c2ecf20Sopenharmony_ci *       notice, this list of conditions and the following disclaimer in the
688c2ecf20Sopenharmony_ci *       documentation and/or other materials provided with the distribution.
698c2ecf20Sopenharmony_ci *     * Neither the name of Advanced Micro Devices, Inc. nor the
708c2ecf20Sopenharmony_ci *       names of its contributors may be used to endorse or promote products
718c2ecf20Sopenharmony_ci *       derived from this software without specific prior written permission.
728c2ecf20Sopenharmony_ci *
738c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
748c2ecf20Sopenharmony_ci * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
758c2ecf20Sopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
768c2ecf20Sopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
778c2ecf20Sopenharmony_ci * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
788c2ecf20Sopenharmony_ci * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
798c2ecf20Sopenharmony_ci * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
808c2ecf20Sopenharmony_ci * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
818c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
828c2ecf20Sopenharmony_ci * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
838c2ecf20Sopenharmony_ci *
848c2ecf20Sopenharmony_ci * This file incorporates work covered by the following copyright and
858c2ecf20Sopenharmony_ci * permission notice:
868c2ecf20Sopenharmony_ci *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
878c2ecf20Sopenharmony_ci *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
888c2ecf20Sopenharmony_ci *     Inc. unless otherwise expressly agreed to in writing between Synopsys
898c2ecf20Sopenharmony_ci *     and you.
908c2ecf20Sopenharmony_ci *
918c2ecf20Sopenharmony_ci *     The Software IS NOT an item of Licensed Software or Licensed Product
928c2ecf20Sopenharmony_ci *     under any End User Software License Agreement or Agreement for Licensed
938c2ecf20Sopenharmony_ci *     Product with Synopsys or any supplement thereto.  Permission is hereby
948c2ecf20Sopenharmony_ci *     granted, free of charge, to any person obtaining a copy of this software
958c2ecf20Sopenharmony_ci *     annotated with this license and the Software, to deal in the Software
968c2ecf20Sopenharmony_ci *     without restriction, including without limitation the rights to use,
978c2ecf20Sopenharmony_ci *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
988c2ecf20Sopenharmony_ci *     of the Software, and to permit persons to whom the Software is furnished
998c2ecf20Sopenharmony_ci *     to do so, subject to the following conditions:
1008c2ecf20Sopenharmony_ci *
1018c2ecf20Sopenharmony_ci *     The above copyright notice and this permission notice shall be included
1028c2ecf20Sopenharmony_ci *     in all copies or substantial portions of the Software.
1038c2ecf20Sopenharmony_ci *
1048c2ecf20Sopenharmony_ci *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
1058c2ecf20Sopenharmony_ci *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1068c2ecf20Sopenharmony_ci *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
1078c2ecf20Sopenharmony_ci *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
1088c2ecf20Sopenharmony_ci *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1098c2ecf20Sopenharmony_ci *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1108c2ecf20Sopenharmony_ci *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1118c2ecf20Sopenharmony_ci *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1128c2ecf20Sopenharmony_ci *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1138c2ecf20Sopenharmony_ci *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
1148c2ecf20Sopenharmony_ci *     THE POSSIBILITY OF SUCH DAMAGE.
1158c2ecf20Sopenharmony_ci */
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci#include <linux/module.h>
1188c2ecf20Sopenharmony_ci#include <linux/device.h>
1198c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
1208c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
1218c2ecf20Sopenharmony_ci#include <linux/etherdevice.h>
1228c2ecf20Sopenharmony_ci#include <linux/io.h>
1238c2ecf20Sopenharmony_ci#include <linux/notifier.h>
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci#include "xgbe.h"
1268c2ecf20Sopenharmony_ci#include "xgbe-common.h"
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ciMODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>");
1298c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
1308c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(XGBE_DRV_DESC);
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_cistatic int debug = -1;
1338c2ecf20Sopenharmony_cimodule_param(debug, int, 0644);
1348c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, " Network interface message level setting");
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cistatic const u32 default_msg_level = (NETIF_MSG_LINK | NETIF_MSG_IFDOWN |
1378c2ecf20Sopenharmony_ci				      NETIF_MSG_IFUP);
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_cistatic void xgbe_default_config(struct xgbe_prv_data *pdata)
1408c2ecf20Sopenharmony_ci{
1418c2ecf20Sopenharmony_ci	DBGPR("-->xgbe_default_config\n");
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	pdata->blen = DMA_SBMR_BLEN_64;
1448c2ecf20Sopenharmony_ci	pdata->pbl = DMA_PBL_128;
1458c2ecf20Sopenharmony_ci	pdata->aal = 1;
1468c2ecf20Sopenharmony_ci	pdata->rd_osr_limit = 8;
1478c2ecf20Sopenharmony_ci	pdata->wr_osr_limit = 8;
1488c2ecf20Sopenharmony_ci	pdata->tx_sf_mode = MTL_TSF_ENABLE;
1498c2ecf20Sopenharmony_ci	pdata->tx_threshold = MTL_TX_THRESHOLD_64;
1508c2ecf20Sopenharmony_ci	pdata->tx_osp_mode = DMA_OSP_ENABLE;
1518c2ecf20Sopenharmony_ci	pdata->rx_sf_mode = MTL_RSF_DISABLE;
1528c2ecf20Sopenharmony_ci	pdata->rx_threshold = MTL_RX_THRESHOLD_64;
1538c2ecf20Sopenharmony_ci	pdata->pause_autoneg = 1;
1548c2ecf20Sopenharmony_ci	pdata->tx_pause = 1;
1558c2ecf20Sopenharmony_ci	pdata->rx_pause = 1;
1568c2ecf20Sopenharmony_ci	pdata->phy_speed = SPEED_UNKNOWN;
1578c2ecf20Sopenharmony_ci	pdata->power_down = 0;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	DBGPR("<--xgbe_default_config\n");
1608c2ecf20Sopenharmony_ci}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_cistatic void xgbe_init_all_fptrs(struct xgbe_prv_data *pdata)
1638c2ecf20Sopenharmony_ci{
1648c2ecf20Sopenharmony_ci	xgbe_init_function_ptrs_dev(&pdata->hw_if);
1658c2ecf20Sopenharmony_ci	xgbe_init_function_ptrs_phy(&pdata->phy_if);
1668c2ecf20Sopenharmony_ci	xgbe_init_function_ptrs_i2c(&pdata->i2c_if);
1678c2ecf20Sopenharmony_ci	xgbe_init_function_ptrs_desc(&pdata->desc_if);
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	pdata->vdata->init_function_ptrs_phy_impl(&pdata->phy_if);
1708c2ecf20Sopenharmony_ci}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_cistruct xgbe_prv_data *xgbe_alloc_pdata(struct device *dev)
1738c2ecf20Sopenharmony_ci{
1748c2ecf20Sopenharmony_ci	struct xgbe_prv_data *pdata;
1758c2ecf20Sopenharmony_ci	struct net_device *netdev;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	netdev = alloc_etherdev_mq(sizeof(struct xgbe_prv_data),
1788c2ecf20Sopenharmony_ci				   XGBE_MAX_DMA_CHANNELS);
1798c2ecf20Sopenharmony_ci	if (!netdev) {
1808c2ecf20Sopenharmony_ci		dev_err(dev, "alloc_etherdev_mq failed\n");
1818c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
1828c2ecf20Sopenharmony_ci	}
1838c2ecf20Sopenharmony_ci	SET_NETDEV_DEV(netdev, dev);
1848c2ecf20Sopenharmony_ci	pdata = netdev_priv(netdev);
1858c2ecf20Sopenharmony_ci	pdata->netdev = netdev;
1868c2ecf20Sopenharmony_ci	pdata->dev = dev;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	spin_lock_init(&pdata->lock);
1898c2ecf20Sopenharmony_ci	spin_lock_init(&pdata->xpcs_lock);
1908c2ecf20Sopenharmony_ci	mutex_init(&pdata->rss_mutex);
1918c2ecf20Sopenharmony_ci	spin_lock_init(&pdata->tstamp_lock);
1928c2ecf20Sopenharmony_ci	mutex_init(&pdata->i2c_mutex);
1938c2ecf20Sopenharmony_ci	init_completion(&pdata->i2c_complete);
1948c2ecf20Sopenharmony_ci	init_completion(&pdata->mdio_complete);
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	pdata->msg_enable = netif_msg_init(debug, default_msg_level);
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	set_bit(XGBE_DOWN, &pdata->dev_state);
1998c2ecf20Sopenharmony_ci	set_bit(XGBE_STOPPED, &pdata->dev_state);
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	return pdata;
2028c2ecf20Sopenharmony_ci}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_civoid xgbe_free_pdata(struct xgbe_prv_data *pdata)
2058c2ecf20Sopenharmony_ci{
2068c2ecf20Sopenharmony_ci	struct net_device *netdev = pdata->netdev;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	free_netdev(netdev);
2098c2ecf20Sopenharmony_ci}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_civoid xgbe_set_counts(struct xgbe_prv_data *pdata)
2128c2ecf20Sopenharmony_ci{
2138c2ecf20Sopenharmony_ci	/* Set all the function pointers */
2148c2ecf20Sopenharmony_ci	xgbe_init_all_fptrs(pdata);
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	/* Populate the hardware features */
2178c2ecf20Sopenharmony_ci	xgbe_get_all_hw_features(pdata);
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	/* Set default max values if not provided */
2208c2ecf20Sopenharmony_ci	if (!pdata->tx_max_channel_count)
2218c2ecf20Sopenharmony_ci		pdata->tx_max_channel_count = pdata->hw_feat.tx_ch_cnt;
2228c2ecf20Sopenharmony_ci	if (!pdata->rx_max_channel_count)
2238c2ecf20Sopenharmony_ci		pdata->rx_max_channel_count = pdata->hw_feat.rx_ch_cnt;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	if (!pdata->tx_max_q_count)
2268c2ecf20Sopenharmony_ci		pdata->tx_max_q_count = pdata->hw_feat.tx_q_cnt;
2278c2ecf20Sopenharmony_ci	if (!pdata->rx_max_q_count)
2288c2ecf20Sopenharmony_ci		pdata->rx_max_q_count = pdata->hw_feat.rx_q_cnt;
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	/* Calculate the number of Tx and Rx rings to be created
2318c2ecf20Sopenharmony_ci	 *  -Tx (DMA) Channels map 1-to-1 to Tx Queues so set
2328c2ecf20Sopenharmony_ci	 *   the number of Tx queues to the number of Tx channels
2338c2ecf20Sopenharmony_ci	 *   enabled
2348c2ecf20Sopenharmony_ci	 *  -Rx (DMA) Channels do not map 1-to-1 so use the actual
2358c2ecf20Sopenharmony_ci	 *   number of Rx queues or maximum allowed
2368c2ecf20Sopenharmony_ci	 */
2378c2ecf20Sopenharmony_ci	pdata->tx_ring_count = min_t(unsigned int, num_online_cpus(),
2388c2ecf20Sopenharmony_ci				     pdata->hw_feat.tx_ch_cnt);
2398c2ecf20Sopenharmony_ci	pdata->tx_ring_count = min_t(unsigned int, pdata->tx_ring_count,
2408c2ecf20Sopenharmony_ci				     pdata->tx_max_channel_count);
2418c2ecf20Sopenharmony_ci	pdata->tx_ring_count = min_t(unsigned int, pdata->tx_ring_count,
2428c2ecf20Sopenharmony_ci				     pdata->tx_max_q_count);
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	pdata->tx_q_count = pdata->tx_ring_count;
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	pdata->rx_ring_count = min_t(unsigned int, num_online_cpus(),
2478c2ecf20Sopenharmony_ci				     pdata->hw_feat.rx_ch_cnt);
2488c2ecf20Sopenharmony_ci	pdata->rx_ring_count = min_t(unsigned int, pdata->rx_ring_count,
2498c2ecf20Sopenharmony_ci				     pdata->rx_max_channel_count);
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	pdata->rx_q_count = min_t(unsigned int, pdata->hw_feat.rx_q_cnt,
2528c2ecf20Sopenharmony_ci				  pdata->rx_max_q_count);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	if (netif_msg_probe(pdata)) {
2558c2ecf20Sopenharmony_ci		dev_dbg(pdata->dev, "TX/RX DMA channel count = %u/%u\n",
2568c2ecf20Sopenharmony_ci			pdata->tx_ring_count, pdata->rx_ring_count);
2578c2ecf20Sopenharmony_ci		dev_dbg(pdata->dev, "TX/RX hardware queue count = %u/%u\n",
2588c2ecf20Sopenharmony_ci			pdata->tx_q_count, pdata->rx_q_count);
2598c2ecf20Sopenharmony_ci	}
2608c2ecf20Sopenharmony_ci}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ciint xgbe_config_netdev(struct xgbe_prv_data *pdata)
2638c2ecf20Sopenharmony_ci{
2648c2ecf20Sopenharmony_ci	struct net_device *netdev = pdata->netdev;
2658c2ecf20Sopenharmony_ci	struct device *dev = pdata->dev;
2668c2ecf20Sopenharmony_ci	int ret;
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	netdev->irq = pdata->dev_irq;
2698c2ecf20Sopenharmony_ci	netdev->base_addr = (unsigned long)pdata->xgmac_regs;
2708c2ecf20Sopenharmony_ci	memcpy(netdev->dev_addr, pdata->mac_addr, netdev->addr_len);
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	/* Initialize ECC timestamps */
2738c2ecf20Sopenharmony_ci	pdata->tx_sec_period = jiffies;
2748c2ecf20Sopenharmony_ci	pdata->tx_ded_period = jiffies;
2758c2ecf20Sopenharmony_ci	pdata->rx_sec_period = jiffies;
2768c2ecf20Sopenharmony_ci	pdata->rx_ded_period = jiffies;
2778c2ecf20Sopenharmony_ci	pdata->desc_sec_period = jiffies;
2788c2ecf20Sopenharmony_ci	pdata->desc_ded_period = jiffies;
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	/* Issue software reset to device */
2818c2ecf20Sopenharmony_ci	ret = pdata->hw_if.exit(pdata);
2828c2ecf20Sopenharmony_ci	if (ret) {
2838c2ecf20Sopenharmony_ci		dev_err(dev, "software reset failed\n");
2848c2ecf20Sopenharmony_ci		return ret;
2858c2ecf20Sopenharmony_ci	}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	/* Set default configuration data */
2888c2ecf20Sopenharmony_ci	xgbe_default_config(pdata);
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	/* Set the DMA mask */
2918c2ecf20Sopenharmony_ci	ret = dma_set_mask_and_coherent(dev,
2928c2ecf20Sopenharmony_ci					DMA_BIT_MASK(pdata->hw_feat.dma_width));
2938c2ecf20Sopenharmony_ci	if (ret) {
2948c2ecf20Sopenharmony_ci		dev_err(dev, "dma_set_mask_and_coherent failed\n");
2958c2ecf20Sopenharmony_ci		return ret;
2968c2ecf20Sopenharmony_ci	}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	/* Set default max values if not provided */
2998c2ecf20Sopenharmony_ci	if (!pdata->tx_max_fifo_size)
3008c2ecf20Sopenharmony_ci		pdata->tx_max_fifo_size = pdata->hw_feat.tx_fifo_size;
3018c2ecf20Sopenharmony_ci	if (!pdata->rx_max_fifo_size)
3028c2ecf20Sopenharmony_ci		pdata->rx_max_fifo_size = pdata->hw_feat.rx_fifo_size;
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	/* Set and validate the number of descriptors for a ring */
3058c2ecf20Sopenharmony_ci	BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_TX_DESC_CNT);
3068c2ecf20Sopenharmony_ci	pdata->tx_desc_count = XGBE_TX_DESC_CNT;
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_RX_DESC_CNT);
3098c2ecf20Sopenharmony_ci	pdata->rx_desc_count = XGBE_RX_DESC_CNT;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	/* Adjust the number of queues based on interrupts assigned */
3128c2ecf20Sopenharmony_ci	if (pdata->channel_irq_count) {
3138c2ecf20Sopenharmony_ci		pdata->tx_ring_count = min_t(unsigned int, pdata->tx_ring_count,
3148c2ecf20Sopenharmony_ci					     pdata->channel_irq_count);
3158c2ecf20Sopenharmony_ci		pdata->rx_ring_count = min_t(unsigned int, pdata->rx_ring_count,
3168c2ecf20Sopenharmony_ci					     pdata->channel_irq_count);
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci		if (netif_msg_probe(pdata))
3198c2ecf20Sopenharmony_ci			dev_dbg(pdata->dev,
3208c2ecf20Sopenharmony_ci				"adjusted TX/RX DMA channel count = %u/%u\n",
3218c2ecf20Sopenharmony_ci				pdata->tx_ring_count, pdata->rx_ring_count);
3228c2ecf20Sopenharmony_ci	}
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	/* Initialize RSS hash key */
3258c2ecf20Sopenharmony_ci	netdev_rss_key_fill(pdata->rss_key, sizeof(pdata->rss_key));
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, IP2TE, 1);
3288c2ecf20Sopenharmony_ci	XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, TCP4TE, 1);
3298c2ecf20Sopenharmony_ci	XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1);
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	/* Call MDIO/PHY initialization routine */
3328c2ecf20Sopenharmony_ci	pdata->debugfs_an_cdr_workaround = pdata->vdata->an_cdr_workaround;
3338c2ecf20Sopenharmony_ci	ret = pdata->phy_if.phy_init(pdata);
3348c2ecf20Sopenharmony_ci	if (ret)
3358c2ecf20Sopenharmony_ci		return ret;
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	/* Set device operations */
3388c2ecf20Sopenharmony_ci	netdev->netdev_ops = xgbe_get_netdev_ops();
3398c2ecf20Sopenharmony_ci	netdev->ethtool_ops = xgbe_get_ethtool_ops();
3408c2ecf20Sopenharmony_ci#ifdef CONFIG_AMD_XGBE_DCB
3418c2ecf20Sopenharmony_ci	netdev->dcbnl_ops = xgbe_get_dcbnl_ops();
3428c2ecf20Sopenharmony_ci#endif
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	/* Set device features */
3458c2ecf20Sopenharmony_ci	netdev->hw_features = NETIF_F_SG |
3468c2ecf20Sopenharmony_ci			      NETIF_F_IP_CSUM |
3478c2ecf20Sopenharmony_ci			      NETIF_F_IPV6_CSUM |
3488c2ecf20Sopenharmony_ci			      NETIF_F_RXCSUM |
3498c2ecf20Sopenharmony_ci			      NETIF_F_TSO |
3508c2ecf20Sopenharmony_ci			      NETIF_F_TSO6 |
3518c2ecf20Sopenharmony_ci			      NETIF_F_GRO |
3528c2ecf20Sopenharmony_ci			      NETIF_F_HW_VLAN_CTAG_RX |
3538c2ecf20Sopenharmony_ci			      NETIF_F_HW_VLAN_CTAG_TX |
3548c2ecf20Sopenharmony_ci			      NETIF_F_HW_VLAN_CTAG_FILTER;
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	if (pdata->hw_feat.rss)
3578c2ecf20Sopenharmony_ci		netdev->hw_features |= NETIF_F_RXHASH;
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	if (pdata->hw_feat.vxn) {
3608c2ecf20Sopenharmony_ci		netdev->hw_enc_features = NETIF_F_SG |
3618c2ecf20Sopenharmony_ci					  NETIF_F_IP_CSUM |
3628c2ecf20Sopenharmony_ci					  NETIF_F_IPV6_CSUM |
3638c2ecf20Sopenharmony_ci					  NETIF_F_RXCSUM |
3648c2ecf20Sopenharmony_ci					  NETIF_F_TSO |
3658c2ecf20Sopenharmony_ci					  NETIF_F_TSO6 |
3668c2ecf20Sopenharmony_ci					  NETIF_F_GRO |
3678c2ecf20Sopenharmony_ci					  NETIF_F_GSO_UDP_TUNNEL |
3688c2ecf20Sopenharmony_ci					  NETIF_F_GSO_UDP_TUNNEL_CSUM;
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci		netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL |
3718c2ecf20Sopenharmony_ci				       NETIF_F_GSO_UDP_TUNNEL_CSUM;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci		netdev->udp_tunnel_nic_info = xgbe_get_udp_tunnel_info();
3748c2ecf20Sopenharmony_ci	}
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	netdev->vlan_features |= NETIF_F_SG |
3778c2ecf20Sopenharmony_ci				 NETIF_F_IP_CSUM |
3788c2ecf20Sopenharmony_ci				 NETIF_F_IPV6_CSUM |
3798c2ecf20Sopenharmony_ci				 NETIF_F_TSO |
3808c2ecf20Sopenharmony_ci				 NETIF_F_TSO6;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	netdev->features |= netdev->hw_features;
3838c2ecf20Sopenharmony_ci	pdata->netdev_features = netdev->features;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	netdev->priv_flags |= IFF_UNICAST_FLT;
3868c2ecf20Sopenharmony_ci	netdev->min_mtu = 0;
3878c2ecf20Sopenharmony_ci	netdev->max_mtu = XGMAC_JUMBO_PACKET_MTU;
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	/* Use default watchdog timeout */
3908c2ecf20Sopenharmony_ci	netdev->watchdog_timeo = 0;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	xgbe_init_rx_coalesce(pdata);
3938c2ecf20Sopenharmony_ci	xgbe_init_tx_coalesce(pdata);
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	netif_carrier_off(netdev);
3968c2ecf20Sopenharmony_ci	ret = register_netdev(netdev);
3978c2ecf20Sopenharmony_ci	if (ret) {
3988c2ecf20Sopenharmony_ci		dev_err(dev, "net device registration failed\n");
3998c2ecf20Sopenharmony_ci		return ret;
4008c2ecf20Sopenharmony_ci	}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	if (IS_REACHABLE(CONFIG_PTP_1588_CLOCK))
4038c2ecf20Sopenharmony_ci		xgbe_ptp_register(pdata);
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci	xgbe_debugfs_init(pdata);
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	netif_dbg(pdata, drv, pdata->netdev, "%u Tx software queues\n",
4088c2ecf20Sopenharmony_ci		  pdata->tx_ring_count);
4098c2ecf20Sopenharmony_ci	netif_dbg(pdata, drv, pdata->netdev, "%u Rx software queues\n",
4108c2ecf20Sopenharmony_ci		  pdata->rx_ring_count);
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	return 0;
4138c2ecf20Sopenharmony_ci}
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_civoid xgbe_deconfig_netdev(struct xgbe_prv_data *pdata)
4168c2ecf20Sopenharmony_ci{
4178c2ecf20Sopenharmony_ci	struct net_device *netdev = pdata->netdev;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	xgbe_debugfs_exit(pdata);
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	if (IS_REACHABLE(CONFIG_PTP_1588_CLOCK))
4228c2ecf20Sopenharmony_ci		xgbe_ptp_unregister(pdata);
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	unregister_netdev(netdev);
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	pdata->phy_if.phy_exit(pdata);
4278c2ecf20Sopenharmony_ci}
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_cistatic int xgbe_netdev_event(struct notifier_block *nb, unsigned long event,
4308c2ecf20Sopenharmony_ci			     void *data)
4318c2ecf20Sopenharmony_ci{
4328c2ecf20Sopenharmony_ci	struct net_device *netdev = netdev_notifier_info_to_dev(data);
4338c2ecf20Sopenharmony_ci	struct xgbe_prv_data *pdata = netdev_priv(netdev);
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	if (netdev->netdev_ops != xgbe_get_netdev_ops())
4368c2ecf20Sopenharmony_ci		goto out;
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	switch (event) {
4398c2ecf20Sopenharmony_ci	case NETDEV_CHANGENAME:
4408c2ecf20Sopenharmony_ci		xgbe_debugfs_rename(pdata);
4418c2ecf20Sopenharmony_ci		break;
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	default:
4448c2ecf20Sopenharmony_ci		break;
4458c2ecf20Sopenharmony_ci	}
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ciout:
4488c2ecf20Sopenharmony_ci	return NOTIFY_DONE;
4498c2ecf20Sopenharmony_ci}
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_cistatic struct notifier_block xgbe_netdev_notifier = {
4528c2ecf20Sopenharmony_ci	.notifier_call = xgbe_netdev_event,
4538c2ecf20Sopenharmony_ci};
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_cistatic int __init xgbe_mod_init(void)
4568c2ecf20Sopenharmony_ci{
4578c2ecf20Sopenharmony_ci	int ret;
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	ret = register_netdevice_notifier(&xgbe_netdev_notifier);
4608c2ecf20Sopenharmony_ci	if (ret)
4618c2ecf20Sopenharmony_ci		return ret;
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	ret = xgbe_platform_init();
4648c2ecf20Sopenharmony_ci	if (ret)
4658c2ecf20Sopenharmony_ci		goto err_platform_init;
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	ret = xgbe_pci_init();
4688c2ecf20Sopenharmony_ci	if (ret)
4698c2ecf20Sopenharmony_ci		goto err_pci_init;
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	return 0;
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_cierr_pci_init:
4748c2ecf20Sopenharmony_ci	xgbe_platform_exit();
4758c2ecf20Sopenharmony_cierr_platform_init:
4768c2ecf20Sopenharmony_ci	unregister_netdevice_notifier(&xgbe_netdev_notifier);
4778c2ecf20Sopenharmony_ci	return ret;
4788c2ecf20Sopenharmony_ci}
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_cistatic void __exit xgbe_mod_exit(void)
4818c2ecf20Sopenharmony_ci{
4828c2ecf20Sopenharmony_ci	xgbe_pci_exit();
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	xgbe_platform_exit();
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci	unregister_netdevice_notifier(&xgbe_netdev_notifier);
4878c2ecf20Sopenharmony_ci}
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_cimodule_init(xgbe_mod_init);
4908c2ecf20Sopenharmony_cimodule_exit(xgbe_mod_exit);
491