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) 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) 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/pci.h> 1208c2ecf20Sopenharmony_ci#include <linux/log2.h> 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci#include "xgbe.h" 1238c2ecf20Sopenharmony_ci#include "xgbe-common.h" 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic int xgbe_config_multi_msi(struct xgbe_prv_data *pdata) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci unsigned int vector_count; 1288c2ecf20Sopenharmony_ci unsigned int i, j; 1298c2ecf20Sopenharmony_ci int ret; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci vector_count = XGBE_MSI_BASE_COUNT; 1328c2ecf20Sopenharmony_ci vector_count += max(pdata->rx_ring_count, 1338c2ecf20Sopenharmony_ci pdata->tx_ring_count); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci ret = pci_alloc_irq_vectors(pdata->pcidev, XGBE_MSI_MIN_COUNT, 1368c2ecf20Sopenharmony_ci vector_count, PCI_IRQ_MSI | PCI_IRQ_MSIX); 1378c2ecf20Sopenharmony_ci if (ret < 0) { 1388c2ecf20Sopenharmony_ci dev_info(pdata->dev, "multi MSI/MSI-X enablement failed\n"); 1398c2ecf20Sopenharmony_ci return ret; 1408c2ecf20Sopenharmony_ci } 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci pdata->isr_as_tasklet = 1; 1438c2ecf20Sopenharmony_ci pdata->irq_count = ret; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci pdata->dev_irq = pci_irq_vector(pdata->pcidev, 0); 1468c2ecf20Sopenharmony_ci pdata->ecc_irq = pci_irq_vector(pdata->pcidev, 1); 1478c2ecf20Sopenharmony_ci pdata->i2c_irq = pci_irq_vector(pdata->pcidev, 2); 1488c2ecf20Sopenharmony_ci pdata->an_irq = pci_irq_vector(pdata->pcidev, 3); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci for (i = XGBE_MSI_BASE_COUNT, j = 0; i < ret; i++, j++) 1518c2ecf20Sopenharmony_ci pdata->channel_irq[j] = pci_irq_vector(pdata->pcidev, i); 1528c2ecf20Sopenharmony_ci pdata->channel_irq_count = j; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci pdata->per_channel_irq = 1; 1558c2ecf20Sopenharmony_ci pdata->channel_irq_mode = XGBE_IRQ_MODE_LEVEL; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci if (netif_msg_probe(pdata)) 1588c2ecf20Sopenharmony_ci dev_dbg(pdata->dev, "multi %s interrupts enabled\n", 1598c2ecf20Sopenharmony_ci pdata->pcidev->msix_enabled ? "MSI-X" : "MSI"); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci return 0; 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic int xgbe_config_irqs(struct xgbe_prv_data *pdata) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci int ret; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci ret = xgbe_config_multi_msi(pdata); 1698c2ecf20Sopenharmony_ci if (!ret) 1708c2ecf20Sopenharmony_ci goto out; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci ret = pci_alloc_irq_vectors(pdata->pcidev, 1, 1, 1738c2ecf20Sopenharmony_ci PCI_IRQ_LEGACY | PCI_IRQ_MSI); 1748c2ecf20Sopenharmony_ci if (ret < 0) { 1758c2ecf20Sopenharmony_ci dev_info(pdata->dev, "single IRQ enablement failed\n"); 1768c2ecf20Sopenharmony_ci return ret; 1778c2ecf20Sopenharmony_ci } 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci pdata->isr_as_tasklet = pdata->pcidev->msi_enabled ? 1 : 0; 1808c2ecf20Sopenharmony_ci pdata->irq_count = 1; 1818c2ecf20Sopenharmony_ci pdata->channel_irq_count = 1; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci pdata->dev_irq = pci_irq_vector(pdata->pcidev, 0); 1848c2ecf20Sopenharmony_ci pdata->ecc_irq = pci_irq_vector(pdata->pcidev, 0); 1858c2ecf20Sopenharmony_ci pdata->i2c_irq = pci_irq_vector(pdata->pcidev, 0); 1868c2ecf20Sopenharmony_ci pdata->an_irq = pci_irq_vector(pdata->pcidev, 0); 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci if (netif_msg_probe(pdata)) 1898c2ecf20Sopenharmony_ci dev_dbg(pdata->dev, "single %s interrupt enabled\n", 1908c2ecf20Sopenharmony_ci pdata->pcidev->msi_enabled ? "MSI" : "legacy"); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ciout: 1938c2ecf20Sopenharmony_ci if (netif_msg_probe(pdata)) { 1948c2ecf20Sopenharmony_ci unsigned int i; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci dev_dbg(pdata->dev, " dev irq=%d\n", pdata->dev_irq); 1978c2ecf20Sopenharmony_ci dev_dbg(pdata->dev, " ecc irq=%d\n", pdata->ecc_irq); 1988c2ecf20Sopenharmony_ci dev_dbg(pdata->dev, " i2c irq=%d\n", pdata->i2c_irq); 1998c2ecf20Sopenharmony_ci dev_dbg(pdata->dev, " an irq=%d\n", pdata->an_irq); 2008c2ecf20Sopenharmony_ci for (i = 0; i < pdata->channel_irq_count; i++) 2018c2ecf20Sopenharmony_ci dev_dbg(pdata->dev, " dma%u irq=%d\n", 2028c2ecf20Sopenharmony_ci i, pdata->channel_irq[i]); 2038c2ecf20Sopenharmony_ci } 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci return 0; 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic int xgbe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci struct xgbe_prv_data *pdata; 2118c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 2128c2ecf20Sopenharmony_ci void __iomem * const *iomap_table; 2138c2ecf20Sopenharmony_ci struct pci_dev *rdev; 2148c2ecf20Sopenharmony_ci unsigned int ma_lo, ma_hi; 2158c2ecf20Sopenharmony_ci unsigned int reg; 2168c2ecf20Sopenharmony_ci int bar_mask; 2178c2ecf20Sopenharmony_ci int ret; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci pdata = xgbe_alloc_pdata(dev); 2208c2ecf20Sopenharmony_ci if (IS_ERR(pdata)) { 2218c2ecf20Sopenharmony_ci ret = PTR_ERR(pdata); 2228c2ecf20Sopenharmony_ci goto err_alloc; 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci pdata->pcidev = pdev; 2268c2ecf20Sopenharmony_ci pci_set_drvdata(pdev, pdata); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci /* Get the version data */ 2298c2ecf20Sopenharmony_ci pdata->vdata = (struct xgbe_version_data *)id->driver_data; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci ret = pcim_enable_device(pdev); 2328c2ecf20Sopenharmony_ci if (ret) { 2338c2ecf20Sopenharmony_ci dev_err(dev, "pcim_enable_device failed\n"); 2348c2ecf20Sopenharmony_ci goto err_pci_enable; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci /* Obtain the mmio areas for the device */ 2388c2ecf20Sopenharmony_ci bar_mask = pci_select_bars(pdev, IORESOURCE_MEM); 2398c2ecf20Sopenharmony_ci ret = pcim_iomap_regions(pdev, bar_mask, XGBE_DRV_NAME); 2408c2ecf20Sopenharmony_ci if (ret) { 2418c2ecf20Sopenharmony_ci dev_err(dev, "pcim_iomap_regions failed\n"); 2428c2ecf20Sopenharmony_ci goto err_pci_enable; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci iomap_table = pcim_iomap_table(pdev); 2468c2ecf20Sopenharmony_ci if (!iomap_table) { 2478c2ecf20Sopenharmony_ci dev_err(dev, "pcim_iomap_table failed\n"); 2488c2ecf20Sopenharmony_ci ret = -ENOMEM; 2498c2ecf20Sopenharmony_ci goto err_pci_enable; 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci pdata->xgmac_regs = iomap_table[XGBE_XGMAC_BAR]; 2538c2ecf20Sopenharmony_ci if (!pdata->xgmac_regs) { 2548c2ecf20Sopenharmony_ci dev_err(dev, "xgmac ioremap failed\n"); 2558c2ecf20Sopenharmony_ci ret = -ENOMEM; 2568c2ecf20Sopenharmony_ci goto err_pci_enable; 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci pdata->xprop_regs = pdata->xgmac_regs + XGBE_MAC_PROP_OFFSET; 2598c2ecf20Sopenharmony_ci pdata->xi2c_regs = pdata->xgmac_regs + XGBE_I2C_CTRL_OFFSET; 2608c2ecf20Sopenharmony_ci if (netif_msg_probe(pdata)) { 2618c2ecf20Sopenharmony_ci dev_dbg(dev, "xgmac_regs = %p\n", pdata->xgmac_regs); 2628c2ecf20Sopenharmony_ci dev_dbg(dev, "xprop_regs = %p\n", pdata->xprop_regs); 2638c2ecf20Sopenharmony_ci dev_dbg(dev, "xi2c_regs = %p\n", pdata->xi2c_regs); 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci pdata->xpcs_regs = iomap_table[XGBE_XPCS_BAR]; 2678c2ecf20Sopenharmony_ci if (!pdata->xpcs_regs) { 2688c2ecf20Sopenharmony_ci dev_err(dev, "xpcs ioremap failed\n"); 2698c2ecf20Sopenharmony_ci ret = -ENOMEM; 2708c2ecf20Sopenharmony_ci goto err_pci_enable; 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci if (netif_msg_probe(pdata)) 2738c2ecf20Sopenharmony_ci dev_dbg(dev, "xpcs_regs = %p\n", pdata->xpcs_regs); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci /* Set the PCS indirect addressing definition registers */ 2768c2ecf20Sopenharmony_ci rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0)); 2778c2ecf20Sopenharmony_ci if (rdev && 2788c2ecf20Sopenharmony_ci (rdev->vendor == PCI_VENDOR_ID_AMD) && (rdev->device == 0x15d0)) { 2798c2ecf20Sopenharmony_ci pdata->xpcs_window_def_reg = PCS_V2_RV_WINDOW_DEF; 2808c2ecf20Sopenharmony_ci pdata->xpcs_window_sel_reg = PCS_V2_RV_WINDOW_SELECT; 2818c2ecf20Sopenharmony_ci } else { 2828c2ecf20Sopenharmony_ci pdata->xpcs_window_def_reg = PCS_V2_WINDOW_DEF; 2838c2ecf20Sopenharmony_ci pdata->xpcs_window_sel_reg = PCS_V2_WINDOW_SELECT; 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci pci_dev_put(rdev); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci /* Configure the PCS indirect addressing support */ 2888c2ecf20Sopenharmony_ci reg = XPCS32_IOREAD(pdata, pdata->xpcs_window_def_reg); 2898c2ecf20Sopenharmony_ci pdata->xpcs_window = XPCS_GET_BITS(reg, PCS_V2_WINDOW_DEF, OFFSET); 2908c2ecf20Sopenharmony_ci pdata->xpcs_window <<= 6; 2918c2ecf20Sopenharmony_ci pdata->xpcs_window_size = XPCS_GET_BITS(reg, PCS_V2_WINDOW_DEF, SIZE); 2928c2ecf20Sopenharmony_ci pdata->xpcs_window_size = 1 << (pdata->xpcs_window_size + 7); 2938c2ecf20Sopenharmony_ci pdata->xpcs_window_mask = pdata->xpcs_window_size - 1; 2948c2ecf20Sopenharmony_ci if (netif_msg_probe(pdata)) { 2958c2ecf20Sopenharmony_ci dev_dbg(dev, "xpcs window def = %#010x\n", 2968c2ecf20Sopenharmony_ci pdata->xpcs_window_def_reg); 2978c2ecf20Sopenharmony_ci dev_dbg(dev, "xpcs window sel = %#010x\n", 2988c2ecf20Sopenharmony_ci pdata->xpcs_window_sel_reg); 2998c2ecf20Sopenharmony_ci dev_dbg(dev, "xpcs window = %#010x\n", 3008c2ecf20Sopenharmony_ci pdata->xpcs_window); 3018c2ecf20Sopenharmony_ci dev_dbg(dev, "xpcs window size = %#010x\n", 3028c2ecf20Sopenharmony_ci pdata->xpcs_window_size); 3038c2ecf20Sopenharmony_ci dev_dbg(dev, "xpcs window mask = %#010x\n", 3048c2ecf20Sopenharmony_ci pdata->xpcs_window_mask); 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci pci_set_master(pdev); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci /* Enable all interrupts in the hardware */ 3108c2ecf20Sopenharmony_ci XP_IOWRITE(pdata, XP_INT_EN, 0x1fffff); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci /* Retrieve the MAC address */ 3138c2ecf20Sopenharmony_ci ma_lo = XP_IOREAD(pdata, XP_MAC_ADDR_LO); 3148c2ecf20Sopenharmony_ci ma_hi = XP_IOREAD(pdata, XP_MAC_ADDR_HI); 3158c2ecf20Sopenharmony_ci pdata->mac_addr[0] = ma_lo & 0xff; 3168c2ecf20Sopenharmony_ci pdata->mac_addr[1] = (ma_lo >> 8) & 0xff; 3178c2ecf20Sopenharmony_ci pdata->mac_addr[2] = (ma_lo >> 16) & 0xff; 3188c2ecf20Sopenharmony_ci pdata->mac_addr[3] = (ma_lo >> 24) & 0xff; 3198c2ecf20Sopenharmony_ci pdata->mac_addr[4] = ma_hi & 0xff; 3208c2ecf20Sopenharmony_ci pdata->mac_addr[5] = (ma_hi >> 8) & 0xff; 3218c2ecf20Sopenharmony_ci if (!XP_GET_BITS(ma_hi, XP_MAC_ADDR_HI, VALID) || 3228c2ecf20Sopenharmony_ci !is_valid_ether_addr(pdata->mac_addr)) { 3238c2ecf20Sopenharmony_ci dev_err(dev, "invalid mac address\n"); 3248c2ecf20Sopenharmony_ci ret = -EINVAL; 3258c2ecf20Sopenharmony_ci goto err_pci_enable; 3268c2ecf20Sopenharmony_ci } 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci /* Clock settings */ 3298c2ecf20Sopenharmony_ci pdata->sysclk_rate = XGBE_V2_DMA_CLOCK_FREQ; 3308c2ecf20Sopenharmony_ci pdata->ptpclk_rate = XGBE_V2_PTP_CLOCK_FREQ; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci /* Set the DMA coherency values */ 3338c2ecf20Sopenharmony_ci pdata->coherent = 1; 3348c2ecf20Sopenharmony_ci pdata->arcr = XGBE_DMA_PCI_ARCR; 3358c2ecf20Sopenharmony_ci pdata->awcr = XGBE_DMA_PCI_AWCR; 3368c2ecf20Sopenharmony_ci pdata->awarcr = XGBE_DMA_PCI_AWARCR; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci /* Read the port property registers */ 3398c2ecf20Sopenharmony_ci pdata->pp0 = XP_IOREAD(pdata, XP_PROP_0); 3408c2ecf20Sopenharmony_ci pdata->pp1 = XP_IOREAD(pdata, XP_PROP_1); 3418c2ecf20Sopenharmony_ci pdata->pp2 = XP_IOREAD(pdata, XP_PROP_2); 3428c2ecf20Sopenharmony_ci pdata->pp3 = XP_IOREAD(pdata, XP_PROP_3); 3438c2ecf20Sopenharmony_ci pdata->pp4 = XP_IOREAD(pdata, XP_PROP_4); 3448c2ecf20Sopenharmony_ci if (netif_msg_probe(pdata)) { 3458c2ecf20Sopenharmony_ci dev_dbg(dev, "port property 0 = %#010x\n", pdata->pp0); 3468c2ecf20Sopenharmony_ci dev_dbg(dev, "port property 1 = %#010x\n", pdata->pp1); 3478c2ecf20Sopenharmony_ci dev_dbg(dev, "port property 2 = %#010x\n", pdata->pp2); 3488c2ecf20Sopenharmony_ci dev_dbg(dev, "port property 3 = %#010x\n", pdata->pp3); 3498c2ecf20Sopenharmony_ci dev_dbg(dev, "port property 4 = %#010x\n", pdata->pp4); 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci /* Set the maximum channels and queues */ 3538c2ecf20Sopenharmony_ci pdata->tx_max_channel_count = XP_GET_BITS(pdata->pp1, XP_PROP_1, 3548c2ecf20Sopenharmony_ci MAX_TX_DMA); 3558c2ecf20Sopenharmony_ci pdata->rx_max_channel_count = XP_GET_BITS(pdata->pp1, XP_PROP_1, 3568c2ecf20Sopenharmony_ci MAX_RX_DMA); 3578c2ecf20Sopenharmony_ci pdata->tx_max_q_count = XP_GET_BITS(pdata->pp1, XP_PROP_1, 3588c2ecf20Sopenharmony_ci MAX_TX_QUEUES); 3598c2ecf20Sopenharmony_ci pdata->rx_max_q_count = XP_GET_BITS(pdata->pp1, XP_PROP_1, 3608c2ecf20Sopenharmony_ci MAX_RX_QUEUES); 3618c2ecf20Sopenharmony_ci if (netif_msg_probe(pdata)) { 3628c2ecf20Sopenharmony_ci dev_dbg(dev, "max tx/rx channel count = %u/%u\n", 3638c2ecf20Sopenharmony_ci pdata->tx_max_channel_count, 3648c2ecf20Sopenharmony_ci pdata->rx_max_channel_count); 3658c2ecf20Sopenharmony_ci dev_dbg(dev, "max tx/rx hw queue count = %u/%u\n", 3668c2ecf20Sopenharmony_ci pdata->tx_max_q_count, pdata->rx_max_q_count); 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci /* Set the hardware channel and queue counts */ 3708c2ecf20Sopenharmony_ci xgbe_set_counts(pdata); 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci /* Set the maximum fifo amounts */ 3738c2ecf20Sopenharmony_ci pdata->tx_max_fifo_size = XP_GET_BITS(pdata->pp2, XP_PROP_2, 3748c2ecf20Sopenharmony_ci TX_FIFO_SIZE); 3758c2ecf20Sopenharmony_ci pdata->tx_max_fifo_size *= 16384; 3768c2ecf20Sopenharmony_ci pdata->tx_max_fifo_size = min(pdata->tx_max_fifo_size, 3778c2ecf20Sopenharmony_ci pdata->vdata->tx_max_fifo_size); 3788c2ecf20Sopenharmony_ci pdata->rx_max_fifo_size = XP_GET_BITS(pdata->pp2, XP_PROP_2, 3798c2ecf20Sopenharmony_ci RX_FIFO_SIZE); 3808c2ecf20Sopenharmony_ci pdata->rx_max_fifo_size *= 16384; 3818c2ecf20Sopenharmony_ci pdata->rx_max_fifo_size = min(pdata->rx_max_fifo_size, 3828c2ecf20Sopenharmony_ci pdata->vdata->rx_max_fifo_size); 3838c2ecf20Sopenharmony_ci if (netif_msg_probe(pdata)) 3848c2ecf20Sopenharmony_ci dev_dbg(dev, "max tx/rx max fifo size = %u/%u\n", 3858c2ecf20Sopenharmony_ci pdata->tx_max_fifo_size, pdata->rx_max_fifo_size); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci /* Configure interrupt support */ 3888c2ecf20Sopenharmony_ci ret = xgbe_config_irqs(pdata); 3898c2ecf20Sopenharmony_ci if (ret) 3908c2ecf20Sopenharmony_ci goto err_pci_enable; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci /* Configure the netdev resource */ 3938c2ecf20Sopenharmony_ci ret = xgbe_config_netdev(pdata); 3948c2ecf20Sopenharmony_ci if (ret) 3958c2ecf20Sopenharmony_ci goto err_irq_vectors; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci netdev_notice(pdata->netdev, "net device enabled\n"); 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci return 0; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_cierr_irq_vectors: 4028c2ecf20Sopenharmony_ci pci_free_irq_vectors(pdata->pcidev); 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_cierr_pci_enable: 4058c2ecf20Sopenharmony_ci xgbe_free_pdata(pdata); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_cierr_alloc: 4088c2ecf20Sopenharmony_ci dev_notice(dev, "net device not enabled\n"); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci return ret; 4118c2ecf20Sopenharmony_ci} 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_cistatic void xgbe_pci_remove(struct pci_dev *pdev) 4148c2ecf20Sopenharmony_ci{ 4158c2ecf20Sopenharmony_ci struct xgbe_prv_data *pdata = pci_get_drvdata(pdev); 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci xgbe_deconfig_netdev(pdata); 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci pci_free_irq_vectors(pdata->pcidev); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci xgbe_free_pdata(pdata); 4228c2ecf20Sopenharmony_ci} 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_cistatic int __maybe_unused xgbe_pci_suspend(struct device *dev) 4258c2ecf20Sopenharmony_ci{ 4268c2ecf20Sopenharmony_ci struct xgbe_prv_data *pdata = dev_get_drvdata(dev); 4278c2ecf20Sopenharmony_ci struct net_device *netdev = pdata->netdev; 4288c2ecf20Sopenharmony_ci int ret = 0; 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci if (netif_running(netdev)) 4318c2ecf20Sopenharmony_ci ret = xgbe_powerdown(netdev, XGMAC_DRIVER_CONTEXT); 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci pdata->lpm_ctrl = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); 4348c2ecf20Sopenharmony_ci pdata->lpm_ctrl |= MDIO_CTRL1_LPOWER; 4358c2ecf20Sopenharmony_ci XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci return ret; 4388c2ecf20Sopenharmony_ci} 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_cistatic int __maybe_unused xgbe_pci_resume(struct device *dev) 4418c2ecf20Sopenharmony_ci{ 4428c2ecf20Sopenharmony_ci struct xgbe_prv_data *pdata = dev_get_drvdata(dev); 4438c2ecf20Sopenharmony_ci struct net_device *netdev = pdata->netdev; 4448c2ecf20Sopenharmony_ci int ret = 0; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci XP_IOWRITE(pdata, XP_INT_EN, 0x1fffff); 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci pdata->lpm_ctrl &= ~MDIO_CTRL1_LPOWER; 4498c2ecf20Sopenharmony_ci XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl); 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci if (netif_running(netdev)) { 4528c2ecf20Sopenharmony_ci ret = xgbe_powerup(netdev, XGMAC_DRIVER_CONTEXT); 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci /* Schedule a restart in case the link or phy state changed 4558c2ecf20Sopenharmony_ci * while we were powered down. 4568c2ecf20Sopenharmony_ci */ 4578c2ecf20Sopenharmony_ci schedule_work(&pdata->restart_work); 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci return ret; 4618c2ecf20Sopenharmony_ci} 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_cistatic const struct xgbe_version_data xgbe_v2a = { 4648c2ecf20Sopenharmony_ci .init_function_ptrs_phy_impl = xgbe_init_function_ptrs_phy_v2, 4658c2ecf20Sopenharmony_ci .xpcs_access = XGBE_XPCS_ACCESS_V2, 4668c2ecf20Sopenharmony_ci .mmc_64bit = 1, 4678c2ecf20Sopenharmony_ci .tx_max_fifo_size = 229376, 4688c2ecf20Sopenharmony_ci .rx_max_fifo_size = 229376, 4698c2ecf20Sopenharmony_ci .tx_tstamp_workaround = 1, 4708c2ecf20Sopenharmony_ci .ecc_support = 1, 4718c2ecf20Sopenharmony_ci .i2c_support = 1, 4728c2ecf20Sopenharmony_ci .irq_reissue_support = 1, 4738c2ecf20Sopenharmony_ci .tx_desc_prefetch = 5, 4748c2ecf20Sopenharmony_ci .rx_desc_prefetch = 5, 4758c2ecf20Sopenharmony_ci .an_cdr_workaround = 1, 4768c2ecf20Sopenharmony_ci}; 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_cistatic const struct xgbe_version_data xgbe_v2b = { 4798c2ecf20Sopenharmony_ci .init_function_ptrs_phy_impl = xgbe_init_function_ptrs_phy_v2, 4808c2ecf20Sopenharmony_ci .xpcs_access = XGBE_XPCS_ACCESS_V2, 4818c2ecf20Sopenharmony_ci .mmc_64bit = 1, 4828c2ecf20Sopenharmony_ci .tx_max_fifo_size = 65536, 4838c2ecf20Sopenharmony_ci .rx_max_fifo_size = 65536, 4848c2ecf20Sopenharmony_ci .tx_tstamp_workaround = 1, 4858c2ecf20Sopenharmony_ci .ecc_support = 1, 4868c2ecf20Sopenharmony_ci .i2c_support = 1, 4878c2ecf20Sopenharmony_ci .irq_reissue_support = 1, 4888c2ecf20Sopenharmony_ci .tx_desc_prefetch = 5, 4898c2ecf20Sopenharmony_ci .rx_desc_prefetch = 5, 4908c2ecf20Sopenharmony_ci .an_cdr_workaround = 1, 4918c2ecf20Sopenharmony_ci}; 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_cistatic const struct pci_device_id xgbe_pci_table[] = { 4948c2ecf20Sopenharmony_ci { PCI_VDEVICE(AMD, 0x1458), 4958c2ecf20Sopenharmony_ci .driver_data = (kernel_ulong_t)&xgbe_v2a }, 4968c2ecf20Sopenharmony_ci { PCI_VDEVICE(AMD, 0x1459), 4978c2ecf20Sopenharmony_ci .driver_data = (kernel_ulong_t)&xgbe_v2b }, 4988c2ecf20Sopenharmony_ci /* Last entry must be zero */ 4998c2ecf20Sopenharmony_ci { 0, } 5008c2ecf20Sopenharmony_ci}; 5018c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, xgbe_pci_table); 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(xgbe_pci_pm_ops, xgbe_pci_suspend, xgbe_pci_resume); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_cistatic struct pci_driver xgbe_driver = { 5068c2ecf20Sopenharmony_ci .name = XGBE_DRV_NAME, 5078c2ecf20Sopenharmony_ci .id_table = xgbe_pci_table, 5088c2ecf20Sopenharmony_ci .probe = xgbe_pci_probe, 5098c2ecf20Sopenharmony_ci .remove = xgbe_pci_remove, 5108c2ecf20Sopenharmony_ci .driver = { 5118c2ecf20Sopenharmony_ci .pm = &xgbe_pci_pm_ops, 5128c2ecf20Sopenharmony_ci } 5138c2ecf20Sopenharmony_ci}; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ciint xgbe_pci_init(void) 5168c2ecf20Sopenharmony_ci{ 5178c2ecf20Sopenharmony_ci return pci_register_driver(&xgbe_driver); 5188c2ecf20Sopenharmony_ci} 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_civoid xgbe_pci_exit(void) 5218c2ecf20Sopenharmony_ci{ 5228c2ecf20Sopenharmony_ci pci_unregister_driver(&xgbe_driver); 5238c2ecf20Sopenharmony_ci} 524