From 2698ac6cbef3be654bfb2fd65fd94165255ba076 Mon Sep 17 00:00:00 2001 From: Kevin Mihelich Date: Tue, 15 Mar 2016 00:05:57 +0000 Subject: [PATCH] core/linux-aarch64 to 4.5.0-1 --- ...d-xgbe-a0-Add-support-for-XGBE-on-A0.patch | 10393 ---------------- ...> 0001-arm64-acpi-drop-expert-patch.patch} | 8 +- ...hy-a0-Add-support-for-XGBE-PHY-on-A0.patch | 1870 --- ...gs-Document-qcom-msm-id-and-qcom-bo.patch} | 6 +- ...ts-Add-Qualcomm-MSM8916-MTP8916-ids.patch} | 12 +- ...64-dts-qcom-Add-APQ8016-SBC-support.patch} | 8 +- core/linux-aarch64/PKGBUILD | 43 +- core/linux-aarch64/config | 337 +- 8 files changed, 288 insertions(+), 12389 deletions(-) delete mode 100644 core/linux-aarch64/0001-amd-xgbe-a0-Add-support-for-XGBE-on-A0.patch rename core/linux-aarch64/{0003-arm64-acpi-drop-expert-patch.patch => 0001-arm64-acpi-drop-expert-patch.patch} (77%) delete mode 100644 core/linux-aarch64/0002-amd-xgbe-phy-a0-Add-support-for-XGBE-PHY-on-A0.patch rename core/linux-aarch64/{0004-devicetree-bindings-Document-qcom-msm-id-and-qcom-bo.patch => 0002-devicetree-bindings-Document-qcom-msm-id-and-qcom-bo.patch} (97%) rename core/linux-aarch64/{0005-arm64-dts-Add-Qualcomm-MSM8916-MTP8916-ids.patch => 0003-arm64-dts-Add-Qualcomm-MSM8916-MTP8916-ids.patch} (85%) rename core/linux-aarch64/{0006-arm64-dts-qcom-Add-APQ8016-SBC-support.patch => 0004-arm64-dts-qcom-Add-APQ8016-SBC-support.patch} (89%) diff --git a/core/linux-aarch64/0001-amd-xgbe-a0-Add-support-for-XGBE-on-A0.patch b/core/linux-aarch64/0001-amd-xgbe-a0-Add-support-for-XGBE-on-A0.patch deleted file mode 100644 index 2f719f339..000000000 --- a/core/linux-aarch64/0001-amd-xgbe-a0-Add-support-for-XGBE-on-A0.patch +++ /dev/null @@ -1,10393 +0,0 @@ -From db4cf374d2cf1ad168186bccc55c77cd51299642 Mon Sep 17 00:00:00 2001 -From: Tom Lendacky -Date: Thu, 28 May 2015 16:38:57 -0400 -Subject: [PATCH 1/6] amd-xgbe-a0: Add support for XGBE on A0 - -Add XGBE driver support for A0 hardware. - -Signed-off-by: Tom Lendacky -[fixup timespec -> timespec64] -[use device_dma_is_coherent] -Signed-off-by: Mark Salter ---- - drivers/net/ethernet/amd/Makefile | 1 + - drivers/net/ethernet/amd/xgbe-a0/Makefile | 8 + - drivers/net/ethernet/amd/xgbe-a0/xgbe-common.h | 1142 +++++++++ - drivers/net/ethernet/amd/xgbe-a0/xgbe-dcb.c | 269 +++ - drivers/net/ethernet/amd/xgbe-a0/xgbe-debugfs.c | 373 +++ - drivers/net/ethernet/amd/xgbe-a0/xgbe-desc.c | 636 +++++ - drivers/net/ethernet/amd/xgbe-a0/xgbe-dev.c | 2930 +++++++++++++++++++++++ - drivers/net/ethernet/amd/xgbe-a0/xgbe-drv.c | 2218 +++++++++++++++++ - drivers/net/ethernet/amd/xgbe-a0/xgbe-ethtool.c | 616 +++++ - drivers/net/ethernet/amd/xgbe-a0/xgbe-main.c | 620 +++++ - drivers/net/ethernet/amd/xgbe-a0/xgbe-mdio.c | 312 +++ - drivers/net/ethernet/amd/xgbe-a0/xgbe-ptp.c | 278 +++ - drivers/net/ethernet/amd/xgbe-a0/xgbe.h | 868 +++++++ - 13 files changed, 10271 insertions(+) - create mode 100644 drivers/net/ethernet/amd/xgbe-a0/Makefile - create mode 100644 drivers/net/ethernet/amd/xgbe-a0/xgbe-common.h - create mode 100644 drivers/net/ethernet/amd/xgbe-a0/xgbe-dcb.c - create mode 100644 drivers/net/ethernet/amd/xgbe-a0/xgbe-debugfs.c - create mode 100644 drivers/net/ethernet/amd/xgbe-a0/xgbe-desc.c - create mode 100644 drivers/net/ethernet/amd/xgbe-a0/xgbe-dev.c - create mode 100644 drivers/net/ethernet/amd/xgbe-a0/xgbe-drv.c - create mode 100644 drivers/net/ethernet/amd/xgbe-a0/xgbe-ethtool.c - create mode 100644 drivers/net/ethernet/amd/xgbe-a0/xgbe-main.c - create mode 100644 drivers/net/ethernet/amd/xgbe-a0/xgbe-mdio.c - create mode 100644 drivers/net/ethernet/amd/xgbe-a0/xgbe-ptp.c - create mode 100644 drivers/net/ethernet/amd/xgbe-a0/xgbe.h - -diff --git a/drivers/net/ethernet/amd/Makefile b/drivers/net/ethernet/amd/Makefile -index a38a2dc..bf0cf2f 100644 ---- a/drivers/net/ethernet/amd/Makefile -+++ b/drivers/net/ethernet/amd/Makefile -@@ -18,3 +18,4 @@ obj-$(CONFIG_PCNET32) += pcnet32.o - obj-$(CONFIG_SUN3LANCE) += sun3lance.o - obj-$(CONFIG_SUNLANCE) += sunlance.o - obj-$(CONFIG_AMD_XGBE) += xgbe/ -+obj-$(CONFIG_AMD_XGBE) += xgbe-a0/ -diff --git a/drivers/net/ethernet/amd/xgbe-a0/Makefile b/drivers/net/ethernet/amd/xgbe-a0/Makefile -new file mode 100644 -index 0000000..561116f ---- /dev/null -+++ b/drivers/net/ethernet/amd/xgbe-a0/Makefile -@@ -0,0 +1,8 @@ -+obj-$(CONFIG_AMD_XGBE) += amd-xgbe-a0.o -+ -+amd-xgbe-a0-objs := xgbe-main.o xgbe-drv.o xgbe-dev.o \ -+ xgbe-desc.o xgbe-ethtool.o xgbe-mdio.o \ -+ xgbe-ptp.o -+ -+amd-xgbe-a0-$(CONFIG_AMD_XGBE_DCB) += xgbe-dcb.o -+amd-xgbe-a0-$(CONFIG_DEBUG_FS) += xgbe-debugfs.o -diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-common.h b/drivers/net/ethernet/amd/xgbe-a0/xgbe-common.h -new file mode 100644 -index 0000000..75b08c6 ---- /dev/null -+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-common.h -@@ -0,0 +1,1142 @@ -+/* -+ * AMD 10Gb Ethernet driver -+ * -+ * This file is available to you under your choice of the following two -+ * licenses: -+ * -+ * License 1: GPLv2 -+ * -+ * Copyright (c) 2014 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 . -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * -+ * License 2: Modified BSD -+ * -+ * Copyright (c) 2014 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 BE LIABLE FOR ANY -+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef __XGBE_COMMON_H__ -+#define __XGBE_COMMON_H__ -+ -+/* DMA register offsets */ -+#define DMA_MR 0x3000 -+#define DMA_SBMR 0x3004 -+#define DMA_ISR 0x3008 -+#define DMA_AXIARCR 0x3010 -+#define DMA_AXIAWCR 0x3018 -+#define DMA_DSR0 0x3020 -+#define DMA_DSR1 0x3024 -+ -+/* DMA register entry bit positions and sizes */ -+#define DMA_AXIARCR_DRC_INDEX 0 -+#define DMA_AXIARCR_DRC_WIDTH 4 -+#define DMA_AXIARCR_DRD_INDEX 4 -+#define DMA_AXIARCR_DRD_WIDTH 2 -+#define DMA_AXIARCR_TEC_INDEX 8 -+#define DMA_AXIARCR_TEC_WIDTH 4 -+#define DMA_AXIARCR_TED_INDEX 12 -+#define DMA_AXIARCR_TED_WIDTH 2 -+#define DMA_AXIARCR_THC_INDEX 16 -+#define DMA_AXIARCR_THC_WIDTH 4 -+#define DMA_AXIARCR_THD_INDEX 20 -+#define DMA_AXIARCR_THD_WIDTH 2 -+#define DMA_AXIAWCR_DWC_INDEX 0 -+#define DMA_AXIAWCR_DWC_WIDTH 4 -+#define DMA_AXIAWCR_DWD_INDEX 4 -+#define DMA_AXIAWCR_DWD_WIDTH 2 -+#define DMA_AXIAWCR_RPC_INDEX 8 -+#define DMA_AXIAWCR_RPC_WIDTH 4 -+#define DMA_AXIAWCR_RPD_INDEX 12 -+#define DMA_AXIAWCR_RPD_WIDTH 2 -+#define DMA_AXIAWCR_RHC_INDEX 16 -+#define DMA_AXIAWCR_RHC_WIDTH 4 -+#define DMA_AXIAWCR_RHD_INDEX 20 -+#define DMA_AXIAWCR_RHD_WIDTH 2 -+#define DMA_AXIAWCR_TDC_INDEX 24 -+#define DMA_AXIAWCR_TDC_WIDTH 4 -+#define DMA_AXIAWCR_TDD_INDEX 28 -+#define DMA_AXIAWCR_TDD_WIDTH 2 -+#define DMA_ISR_MACIS_INDEX 17 -+#define DMA_ISR_MACIS_WIDTH 1 -+#define DMA_ISR_MTLIS_INDEX 16 -+#define DMA_ISR_MTLIS_WIDTH 1 -+#define DMA_MR_SWR_INDEX 0 -+#define DMA_MR_SWR_WIDTH 1 -+#define DMA_SBMR_EAME_INDEX 11 -+#define DMA_SBMR_EAME_WIDTH 1 -+#define DMA_SBMR_BLEN_256_INDEX 7 -+#define DMA_SBMR_BLEN_256_WIDTH 1 -+#define DMA_SBMR_UNDEF_INDEX 0 -+#define DMA_SBMR_UNDEF_WIDTH 1 -+ -+/* DMA register values */ -+#define DMA_DSR_RPS_WIDTH 4 -+#define DMA_DSR_TPS_WIDTH 4 -+#define DMA_DSR_Q_WIDTH (DMA_DSR_RPS_WIDTH + DMA_DSR_TPS_WIDTH) -+#define DMA_DSR0_RPS_START 8 -+#define DMA_DSR0_TPS_START 12 -+#define DMA_DSRX_FIRST_QUEUE 3 -+#define DMA_DSRX_INC 4 -+#define DMA_DSRX_QPR 4 -+#define DMA_DSRX_RPS_START 0 -+#define DMA_DSRX_TPS_START 4 -+#define DMA_TPS_STOPPED 0x00 -+#define DMA_TPS_SUSPENDED 0x06 -+ -+/* DMA channel register offsets -+ * Multiple channels can be active. The first channel has registers -+ * that begin at 0x3100. Each subsequent channel has registers that -+ * are accessed using an offset of 0x80 from the previous channel. -+ */ -+#define DMA_CH_BASE 0x3100 -+#define DMA_CH_INC 0x80 -+ -+#define DMA_CH_CR 0x00 -+#define DMA_CH_TCR 0x04 -+#define DMA_CH_RCR 0x08 -+#define DMA_CH_TDLR_HI 0x10 -+#define DMA_CH_TDLR_LO 0x14 -+#define DMA_CH_RDLR_HI 0x18 -+#define DMA_CH_RDLR_LO 0x1c -+#define DMA_CH_TDTR_LO 0x24 -+#define DMA_CH_RDTR_LO 0x2c -+#define DMA_CH_TDRLR 0x30 -+#define DMA_CH_RDRLR 0x34 -+#define DMA_CH_IER 0x38 -+#define DMA_CH_RIWT 0x3c -+#define DMA_CH_CATDR_LO 0x44 -+#define DMA_CH_CARDR_LO 0x4c -+#define DMA_CH_CATBR_HI 0x50 -+#define DMA_CH_CATBR_LO 0x54 -+#define DMA_CH_CARBR_HI 0x58 -+#define DMA_CH_CARBR_LO 0x5c -+#define DMA_CH_SR 0x60 -+ -+/* DMA channel register entry bit positions and sizes */ -+#define DMA_CH_CR_PBLX8_INDEX 16 -+#define DMA_CH_CR_PBLX8_WIDTH 1 -+#define DMA_CH_CR_SPH_INDEX 24 -+#define DMA_CH_CR_SPH_WIDTH 1 -+#define DMA_CH_IER_AIE_INDEX 15 -+#define DMA_CH_IER_AIE_WIDTH 1 -+#define DMA_CH_IER_FBEE_INDEX 12 -+#define DMA_CH_IER_FBEE_WIDTH 1 -+#define DMA_CH_IER_NIE_INDEX 16 -+#define DMA_CH_IER_NIE_WIDTH 1 -+#define DMA_CH_IER_RBUE_INDEX 7 -+#define DMA_CH_IER_RBUE_WIDTH 1 -+#define DMA_CH_IER_RIE_INDEX 6 -+#define DMA_CH_IER_RIE_WIDTH 1 -+#define DMA_CH_IER_RSE_INDEX 8 -+#define DMA_CH_IER_RSE_WIDTH 1 -+#define DMA_CH_IER_TBUE_INDEX 2 -+#define DMA_CH_IER_TBUE_WIDTH 1 -+#define DMA_CH_IER_TIE_INDEX 0 -+#define DMA_CH_IER_TIE_WIDTH 1 -+#define DMA_CH_IER_TXSE_INDEX 1 -+#define DMA_CH_IER_TXSE_WIDTH 1 -+#define DMA_CH_RCR_PBL_INDEX 16 -+#define DMA_CH_RCR_PBL_WIDTH 6 -+#define DMA_CH_RCR_RBSZ_INDEX 1 -+#define DMA_CH_RCR_RBSZ_WIDTH 14 -+#define DMA_CH_RCR_SR_INDEX 0 -+#define DMA_CH_RCR_SR_WIDTH 1 -+#define DMA_CH_RIWT_RWT_INDEX 0 -+#define DMA_CH_RIWT_RWT_WIDTH 8 -+#define DMA_CH_SR_FBE_INDEX 12 -+#define DMA_CH_SR_FBE_WIDTH 1 -+#define DMA_CH_SR_RBU_INDEX 7 -+#define DMA_CH_SR_RBU_WIDTH 1 -+#define DMA_CH_SR_RI_INDEX 6 -+#define DMA_CH_SR_RI_WIDTH 1 -+#define DMA_CH_SR_RPS_INDEX 8 -+#define DMA_CH_SR_RPS_WIDTH 1 -+#define DMA_CH_SR_TBU_INDEX 2 -+#define DMA_CH_SR_TBU_WIDTH 1 -+#define DMA_CH_SR_TI_INDEX 0 -+#define DMA_CH_SR_TI_WIDTH 1 -+#define DMA_CH_SR_TPS_INDEX 1 -+#define DMA_CH_SR_TPS_WIDTH 1 -+#define DMA_CH_TCR_OSP_INDEX 4 -+#define DMA_CH_TCR_OSP_WIDTH 1 -+#define DMA_CH_TCR_PBL_INDEX 16 -+#define DMA_CH_TCR_PBL_WIDTH 6 -+#define DMA_CH_TCR_ST_INDEX 0 -+#define DMA_CH_TCR_ST_WIDTH 1 -+#define DMA_CH_TCR_TSE_INDEX 12 -+#define DMA_CH_TCR_TSE_WIDTH 1 -+ -+/* DMA channel register values */ -+#define DMA_OSP_DISABLE 0x00 -+#define DMA_OSP_ENABLE 0x01 -+#define DMA_PBL_1 1 -+#define DMA_PBL_2 2 -+#define DMA_PBL_4 4 -+#define DMA_PBL_8 8 -+#define DMA_PBL_16 16 -+#define DMA_PBL_32 32 -+#define DMA_PBL_64 64 /* 8 x 8 */ -+#define DMA_PBL_128 128 /* 8 x 16 */ -+#define DMA_PBL_256 256 /* 8 x 32 */ -+#define DMA_PBL_X8_DISABLE 0x00 -+#define DMA_PBL_X8_ENABLE 0x01 -+ -+/* MAC register offsets */ -+#define MAC_TCR 0x0000 -+#define MAC_RCR 0x0004 -+#define MAC_PFR 0x0008 -+#define MAC_WTR 0x000c -+#define MAC_HTR0 0x0010 -+#define MAC_VLANTR 0x0050 -+#define MAC_VLANHTR 0x0058 -+#define MAC_VLANIR 0x0060 -+#define MAC_IVLANIR 0x0064 -+#define MAC_RETMR 0x006c -+#define MAC_Q0TFCR 0x0070 -+#define MAC_RFCR 0x0090 -+#define MAC_RQC0R 0x00a0 -+#define MAC_RQC1R 0x00a4 -+#define MAC_RQC2R 0x00a8 -+#define MAC_RQC3R 0x00ac -+#define MAC_ISR 0x00b0 -+#define MAC_IER 0x00b4 -+#define MAC_RTSR 0x00b8 -+#define MAC_PMTCSR 0x00c0 -+#define MAC_RWKPFR 0x00c4 -+#define MAC_LPICSR 0x00d0 -+#define MAC_LPITCR 0x00d4 -+#define MAC_VR 0x0110 -+#define MAC_DR 0x0114 -+#define MAC_HWF0R 0x011c -+#define MAC_HWF1R 0x0120 -+#define MAC_HWF2R 0x0124 -+#define MAC_GPIOCR 0x0278 -+#define MAC_GPIOSR 0x027c -+#define MAC_MACA0HR 0x0300 -+#define MAC_MACA0LR 0x0304 -+#define MAC_MACA1HR 0x0308 -+#define MAC_MACA1LR 0x030c -+#define MAC_RSSCR 0x0c80 -+#define MAC_RSSAR 0x0c88 -+#define MAC_RSSDR 0x0c8c -+#define MAC_TSCR 0x0d00 -+#define MAC_SSIR 0x0d04 -+#define MAC_STSR 0x0d08 -+#define MAC_STNR 0x0d0c -+#define MAC_STSUR 0x0d10 -+#define MAC_STNUR 0x0d14 -+#define MAC_TSAR 0x0d18 -+#define MAC_TSSR 0x0d20 -+#define MAC_TXSNR 0x0d30 -+#define MAC_TXSSR 0x0d34 -+ -+#define MAC_QTFCR_INC 4 -+#define MAC_MACA_INC 4 -+#define MAC_HTR_INC 4 -+ -+#define MAC_RQC2_INC 4 -+#define MAC_RQC2_Q_PER_REG 4 -+ -+/* MAC register entry bit positions and sizes */ -+#define MAC_HWF0R_ADDMACADRSEL_INDEX 18 -+#define MAC_HWF0R_ADDMACADRSEL_WIDTH 5 -+#define MAC_HWF0R_ARPOFFSEL_INDEX 9 -+#define MAC_HWF0R_ARPOFFSEL_WIDTH 1 -+#define MAC_HWF0R_EEESEL_INDEX 13 -+#define MAC_HWF0R_EEESEL_WIDTH 1 -+#define MAC_HWF0R_GMIISEL_INDEX 1 -+#define MAC_HWF0R_GMIISEL_WIDTH 1 -+#define MAC_HWF0R_MGKSEL_INDEX 7 -+#define MAC_HWF0R_MGKSEL_WIDTH 1 -+#define MAC_HWF0R_MMCSEL_INDEX 8 -+#define MAC_HWF0R_MMCSEL_WIDTH 1 -+#define MAC_HWF0R_RWKSEL_INDEX 6 -+#define MAC_HWF0R_RWKSEL_WIDTH 1 -+#define MAC_HWF0R_RXCOESEL_INDEX 16 -+#define MAC_HWF0R_RXCOESEL_WIDTH 1 -+#define MAC_HWF0R_SAVLANINS_INDEX 27 -+#define MAC_HWF0R_SAVLANINS_WIDTH 1 -+#define MAC_HWF0R_SMASEL_INDEX 5 -+#define MAC_HWF0R_SMASEL_WIDTH 1 -+#define MAC_HWF0R_TSSEL_INDEX 12 -+#define MAC_HWF0R_TSSEL_WIDTH 1 -+#define MAC_HWF0R_TSSTSSEL_INDEX 25 -+#define MAC_HWF0R_TSSTSSEL_WIDTH 2 -+#define MAC_HWF0R_TXCOESEL_INDEX 14 -+#define MAC_HWF0R_TXCOESEL_WIDTH 1 -+#define MAC_HWF0R_VLHASH_INDEX 4 -+#define MAC_HWF0R_VLHASH_WIDTH 1 -+#define MAC_HWF1R_ADVTHWORD_INDEX 13 -+#define MAC_HWF1R_ADVTHWORD_WIDTH 1 -+#define MAC_HWF1R_DBGMEMA_INDEX 19 -+#define MAC_HWF1R_DBGMEMA_WIDTH 1 -+#define MAC_HWF1R_DCBEN_INDEX 16 -+#define MAC_HWF1R_DCBEN_WIDTH 1 -+#define MAC_HWF1R_HASHTBLSZ_INDEX 24 -+#define MAC_HWF1R_HASHTBLSZ_WIDTH 3 -+#define MAC_HWF1R_L3L4FNUM_INDEX 27 -+#define MAC_HWF1R_L3L4FNUM_WIDTH 4 -+#define MAC_HWF1R_NUMTC_INDEX 21 -+#define MAC_HWF1R_NUMTC_WIDTH 3 -+#define MAC_HWF1R_RSSEN_INDEX 20 -+#define MAC_HWF1R_RSSEN_WIDTH 1 -+#define MAC_HWF1R_RXFIFOSIZE_INDEX 0 -+#define MAC_HWF1R_RXFIFOSIZE_WIDTH 5 -+#define MAC_HWF1R_SPHEN_INDEX 17 -+#define MAC_HWF1R_SPHEN_WIDTH 1 -+#define MAC_HWF1R_TSOEN_INDEX 18 -+#define MAC_HWF1R_TSOEN_WIDTH 1 -+#define MAC_HWF1R_TXFIFOSIZE_INDEX 6 -+#define MAC_HWF1R_TXFIFOSIZE_WIDTH 5 -+#define MAC_HWF2R_AUXSNAPNUM_INDEX 28 -+#define MAC_HWF2R_AUXSNAPNUM_WIDTH 3 -+#define MAC_HWF2R_PPSOUTNUM_INDEX 24 -+#define MAC_HWF2R_PPSOUTNUM_WIDTH 3 -+#define MAC_HWF2R_RXCHCNT_INDEX 12 -+#define MAC_HWF2R_RXCHCNT_WIDTH 4 -+#define MAC_HWF2R_RXQCNT_INDEX 0 -+#define MAC_HWF2R_RXQCNT_WIDTH 4 -+#define MAC_HWF2R_TXCHCNT_INDEX 18 -+#define MAC_HWF2R_TXCHCNT_WIDTH 4 -+#define MAC_HWF2R_TXQCNT_INDEX 6 -+#define MAC_HWF2R_TXQCNT_WIDTH 4 -+#define MAC_IER_TSIE_INDEX 12 -+#define MAC_IER_TSIE_WIDTH 1 -+#define MAC_ISR_MMCRXIS_INDEX 9 -+#define MAC_ISR_MMCRXIS_WIDTH 1 -+#define MAC_ISR_MMCTXIS_INDEX 10 -+#define MAC_ISR_MMCTXIS_WIDTH 1 -+#define MAC_ISR_PMTIS_INDEX 4 -+#define MAC_ISR_PMTIS_WIDTH 1 -+#define MAC_ISR_TSIS_INDEX 12 -+#define MAC_ISR_TSIS_WIDTH 1 -+#define MAC_MACA1HR_AE_INDEX 31 -+#define MAC_MACA1HR_AE_WIDTH 1 -+#define MAC_PFR_HMC_INDEX 2 -+#define MAC_PFR_HMC_WIDTH 1 -+#define MAC_PFR_HPF_INDEX 10 -+#define MAC_PFR_HPF_WIDTH 1 -+#define MAC_PFR_HUC_INDEX 1 -+#define MAC_PFR_HUC_WIDTH 1 -+#define MAC_PFR_PM_INDEX 4 -+#define MAC_PFR_PM_WIDTH 1 -+#define MAC_PFR_PR_INDEX 0 -+#define MAC_PFR_PR_WIDTH 1 -+#define MAC_PFR_VTFE_INDEX 16 -+#define MAC_PFR_VTFE_WIDTH 1 -+#define MAC_PMTCSR_MGKPKTEN_INDEX 1 -+#define MAC_PMTCSR_MGKPKTEN_WIDTH 1 -+#define MAC_PMTCSR_PWRDWN_INDEX 0 -+#define MAC_PMTCSR_PWRDWN_WIDTH 1 -+#define MAC_PMTCSR_RWKFILTRST_INDEX 31 -+#define MAC_PMTCSR_RWKFILTRST_WIDTH 1 -+#define MAC_PMTCSR_RWKPKTEN_INDEX 2 -+#define MAC_PMTCSR_RWKPKTEN_WIDTH 1 -+#define MAC_Q0TFCR_PT_INDEX 16 -+#define MAC_Q0TFCR_PT_WIDTH 16 -+#define MAC_Q0TFCR_TFE_INDEX 1 -+#define MAC_Q0TFCR_TFE_WIDTH 1 -+#define MAC_RCR_ACS_INDEX 1 -+#define MAC_RCR_ACS_WIDTH 1 -+#define MAC_RCR_CST_INDEX 2 -+#define MAC_RCR_CST_WIDTH 1 -+#define MAC_RCR_DCRCC_INDEX 3 -+#define MAC_RCR_DCRCC_WIDTH 1 -+#define MAC_RCR_HDSMS_INDEX 12 -+#define MAC_RCR_HDSMS_WIDTH 3 -+#define MAC_RCR_IPC_INDEX 9 -+#define MAC_RCR_IPC_WIDTH 1 -+#define MAC_RCR_JE_INDEX 8 -+#define MAC_RCR_JE_WIDTH 1 -+#define MAC_RCR_LM_INDEX 10 -+#define MAC_RCR_LM_WIDTH 1 -+#define MAC_RCR_RE_INDEX 0 -+#define MAC_RCR_RE_WIDTH 1 -+#define MAC_RFCR_PFCE_INDEX 8 -+#define MAC_RFCR_PFCE_WIDTH 1 -+#define MAC_RFCR_RFE_INDEX 0 -+#define MAC_RFCR_RFE_WIDTH 1 -+#define MAC_RFCR_UP_INDEX 1 -+#define MAC_RFCR_UP_WIDTH 1 -+#define MAC_RQC0R_RXQ0EN_INDEX 0 -+#define MAC_RQC0R_RXQ0EN_WIDTH 2 -+#define MAC_RSSAR_ADDRT_INDEX 2 -+#define MAC_RSSAR_ADDRT_WIDTH 1 -+#define MAC_RSSAR_CT_INDEX 1 -+#define MAC_RSSAR_CT_WIDTH 1 -+#define MAC_RSSAR_OB_INDEX 0 -+#define MAC_RSSAR_OB_WIDTH 1 -+#define MAC_RSSAR_RSSIA_INDEX 8 -+#define MAC_RSSAR_RSSIA_WIDTH 8 -+#define MAC_RSSCR_IP2TE_INDEX 1 -+#define MAC_RSSCR_IP2TE_WIDTH 1 -+#define MAC_RSSCR_RSSE_INDEX 0 -+#define MAC_RSSCR_RSSE_WIDTH 1 -+#define MAC_RSSCR_TCP4TE_INDEX 2 -+#define MAC_RSSCR_TCP4TE_WIDTH 1 -+#define MAC_RSSCR_UDP4TE_INDEX 3 -+#define MAC_RSSCR_UDP4TE_WIDTH 1 -+#define MAC_RSSDR_DMCH_INDEX 0 -+#define MAC_RSSDR_DMCH_WIDTH 4 -+#define MAC_SSIR_SNSINC_INDEX 8 -+#define MAC_SSIR_SNSINC_WIDTH 8 -+#define MAC_SSIR_SSINC_INDEX 16 -+#define MAC_SSIR_SSINC_WIDTH 8 -+#define MAC_TCR_SS_INDEX 29 -+#define MAC_TCR_SS_WIDTH 2 -+#define MAC_TCR_TE_INDEX 0 -+#define MAC_TCR_TE_WIDTH 1 -+#define MAC_TSCR_AV8021ASMEN_INDEX 28 -+#define MAC_TSCR_AV8021ASMEN_WIDTH 1 -+#define MAC_TSCR_SNAPTYPSEL_INDEX 16 -+#define MAC_TSCR_SNAPTYPSEL_WIDTH 2 -+#define MAC_TSCR_TSADDREG_INDEX 5 -+#define MAC_TSCR_TSADDREG_WIDTH 1 -+#define MAC_TSCR_TSCFUPDT_INDEX 1 -+#define MAC_TSCR_TSCFUPDT_WIDTH 1 -+#define MAC_TSCR_TSCTRLSSR_INDEX 9 -+#define MAC_TSCR_TSCTRLSSR_WIDTH 1 -+#define MAC_TSCR_TSENA_INDEX 0 -+#define MAC_TSCR_TSENA_WIDTH 1 -+#define MAC_TSCR_TSENALL_INDEX 8 -+#define MAC_TSCR_TSENALL_WIDTH 1 -+#define MAC_TSCR_TSEVNTENA_INDEX 14 -+#define MAC_TSCR_TSEVNTENA_WIDTH 1 -+#define MAC_TSCR_TSINIT_INDEX 2 -+#define MAC_TSCR_TSINIT_WIDTH 1 -+#define MAC_TSCR_TSIPENA_INDEX 11 -+#define MAC_TSCR_TSIPENA_WIDTH 1 -+#define MAC_TSCR_TSIPV4ENA_INDEX 13 -+#define MAC_TSCR_TSIPV4ENA_WIDTH 1 -+#define MAC_TSCR_TSIPV6ENA_INDEX 12 -+#define MAC_TSCR_TSIPV6ENA_WIDTH 1 -+#define MAC_TSCR_TSMSTRENA_INDEX 15 -+#define MAC_TSCR_TSMSTRENA_WIDTH 1 -+#define MAC_TSCR_TSVER2ENA_INDEX 10 -+#define MAC_TSCR_TSVER2ENA_WIDTH 1 -+#define MAC_TSCR_TXTSSTSM_INDEX 24 -+#define MAC_TSCR_TXTSSTSM_WIDTH 1 -+#define MAC_TSSR_TXTSC_INDEX 15 -+#define MAC_TSSR_TXTSC_WIDTH 1 -+#define MAC_TXSNR_TXTSSTSMIS_INDEX 31 -+#define MAC_TXSNR_TXTSSTSMIS_WIDTH 1 -+#define MAC_VLANHTR_VLHT_INDEX 0 -+#define MAC_VLANHTR_VLHT_WIDTH 16 -+#define MAC_VLANIR_VLTI_INDEX 20 -+#define MAC_VLANIR_VLTI_WIDTH 1 -+#define MAC_VLANIR_CSVL_INDEX 19 -+#define MAC_VLANIR_CSVL_WIDTH 1 -+#define MAC_VLANTR_DOVLTC_INDEX 20 -+#define MAC_VLANTR_DOVLTC_WIDTH 1 -+#define MAC_VLANTR_ERSVLM_INDEX 19 -+#define MAC_VLANTR_ERSVLM_WIDTH 1 -+#define MAC_VLANTR_ESVL_INDEX 18 -+#define MAC_VLANTR_ESVL_WIDTH 1 -+#define MAC_VLANTR_ETV_INDEX 16 -+#define MAC_VLANTR_ETV_WIDTH 1 -+#define MAC_VLANTR_EVLS_INDEX 21 -+#define MAC_VLANTR_EVLS_WIDTH 2 -+#define MAC_VLANTR_EVLRXS_INDEX 24 -+#define MAC_VLANTR_EVLRXS_WIDTH 1 -+#define MAC_VLANTR_VL_INDEX 0 -+#define MAC_VLANTR_VL_WIDTH 16 -+#define MAC_VLANTR_VTHM_INDEX 25 -+#define MAC_VLANTR_VTHM_WIDTH 1 -+#define MAC_VLANTR_VTIM_INDEX 17 -+#define MAC_VLANTR_VTIM_WIDTH 1 -+#define MAC_VR_DEVID_INDEX 8 -+#define MAC_VR_DEVID_WIDTH 8 -+#define MAC_VR_SNPSVER_INDEX 0 -+#define MAC_VR_SNPSVER_WIDTH 8 -+#define MAC_VR_USERVER_INDEX 16 -+#define MAC_VR_USERVER_WIDTH 8 -+ -+/* MMC register offsets */ -+#define MMC_CR 0x0800 -+#define MMC_RISR 0x0804 -+#define MMC_TISR 0x0808 -+#define MMC_RIER 0x080c -+#define MMC_TIER 0x0810 -+#define MMC_TXOCTETCOUNT_GB_LO 0x0814 -+#define MMC_TXOCTETCOUNT_GB_HI 0x0818 -+#define MMC_TXFRAMECOUNT_GB_LO 0x081c -+#define MMC_TXFRAMECOUNT_GB_HI 0x0820 -+#define MMC_TXBROADCASTFRAMES_G_LO 0x0824 -+#define MMC_TXBROADCASTFRAMES_G_HI 0x0828 -+#define MMC_TXMULTICASTFRAMES_G_LO 0x082c -+#define MMC_TXMULTICASTFRAMES_G_HI 0x0830 -+#define MMC_TX64OCTETS_GB_LO 0x0834 -+#define MMC_TX64OCTETS_GB_HI 0x0838 -+#define MMC_TX65TO127OCTETS_GB_LO 0x083c -+#define MMC_TX65TO127OCTETS_GB_HI 0x0840 -+#define MMC_TX128TO255OCTETS_GB_LO 0x0844 -+#define MMC_TX128TO255OCTETS_GB_HI 0x0848 -+#define MMC_TX256TO511OCTETS_GB_LO 0x084c -+#define MMC_TX256TO511OCTETS_GB_HI 0x0850 -+#define MMC_TX512TO1023OCTETS_GB_LO 0x0854 -+#define MMC_TX512TO1023OCTETS_GB_HI 0x0858 -+#define MMC_TX1024TOMAXOCTETS_GB_LO 0x085c -+#define MMC_TX1024TOMAXOCTETS_GB_HI 0x0860 -+#define MMC_TXUNICASTFRAMES_GB_LO 0x0864 -+#define MMC_TXUNICASTFRAMES_GB_HI 0x0868 -+#define MMC_TXMULTICASTFRAMES_GB_LO 0x086c -+#define MMC_TXMULTICASTFRAMES_GB_HI 0x0870 -+#define MMC_TXBROADCASTFRAMES_GB_LO 0x0874 -+#define MMC_TXBROADCASTFRAMES_GB_HI 0x0878 -+#define MMC_TXUNDERFLOWERROR_LO 0x087c -+#define MMC_TXUNDERFLOWERROR_HI 0x0880 -+#define MMC_TXOCTETCOUNT_G_LO 0x0884 -+#define MMC_TXOCTETCOUNT_G_HI 0x0888 -+#define MMC_TXFRAMECOUNT_G_LO 0x088c -+#define MMC_TXFRAMECOUNT_G_HI 0x0890 -+#define MMC_TXPAUSEFRAMES_LO 0x0894 -+#define MMC_TXPAUSEFRAMES_HI 0x0898 -+#define MMC_TXVLANFRAMES_G_LO 0x089c -+#define MMC_TXVLANFRAMES_G_HI 0x08a0 -+#define MMC_RXFRAMECOUNT_GB_LO 0x0900 -+#define MMC_RXFRAMECOUNT_GB_HI 0x0904 -+#define MMC_RXOCTETCOUNT_GB_LO 0x0908 -+#define MMC_RXOCTETCOUNT_GB_HI 0x090c -+#define MMC_RXOCTETCOUNT_G_LO 0x0910 -+#define MMC_RXOCTETCOUNT_G_HI 0x0914 -+#define MMC_RXBROADCASTFRAMES_G_LO 0x0918 -+#define MMC_RXBROADCASTFRAMES_G_HI 0x091c -+#define MMC_RXMULTICASTFRAMES_G_LO 0x0920 -+#define MMC_RXMULTICASTFRAMES_G_HI 0x0924 -+#define MMC_RXCRCERROR_LO 0x0928 -+#define MMC_RXCRCERROR_HI 0x092c -+#define MMC_RXRUNTERROR 0x0930 -+#define MMC_RXJABBERERROR 0x0934 -+#define MMC_RXUNDERSIZE_G 0x0938 -+#define MMC_RXOVERSIZE_G 0x093c -+#define MMC_RX64OCTETS_GB_LO 0x0940 -+#define MMC_RX64OCTETS_GB_HI 0x0944 -+#define MMC_RX65TO127OCTETS_GB_LO 0x0948 -+#define MMC_RX65TO127OCTETS_GB_HI 0x094c -+#define MMC_RX128TO255OCTETS_GB_LO 0x0950 -+#define MMC_RX128TO255OCTETS_GB_HI 0x0954 -+#define MMC_RX256TO511OCTETS_GB_LO 0x0958 -+#define MMC_RX256TO511OCTETS_GB_HI 0x095c -+#define MMC_RX512TO1023OCTETS_GB_LO 0x0960 -+#define MMC_RX512TO1023OCTETS_GB_HI 0x0964 -+#define MMC_RX1024TOMAXOCTETS_GB_LO 0x0968 -+#define MMC_RX1024TOMAXOCTETS_GB_HI 0x096c -+#define MMC_RXUNICASTFRAMES_G_LO 0x0970 -+#define MMC_RXUNICASTFRAMES_G_HI 0x0974 -+#define MMC_RXLENGTHERROR_LO 0x0978 -+#define MMC_RXLENGTHERROR_HI 0x097c -+#define MMC_RXOUTOFRANGETYPE_LO 0x0980 -+#define MMC_RXOUTOFRANGETYPE_HI 0x0984 -+#define MMC_RXPAUSEFRAMES_LO 0x0988 -+#define MMC_RXPAUSEFRAMES_HI 0x098c -+#define MMC_RXFIFOOVERFLOW_LO 0x0990 -+#define MMC_RXFIFOOVERFLOW_HI 0x0994 -+#define MMC_RXVLANFRAMES_GB_LO 0x0998 -+#define MMC_RXVLANFRAMES_GB_HI 0x099c -+#define MMC_RXWATCHDOGERROR 0x09a0 -+ -+/* MMC register entry bit positions and sizes */ -+#define MMC_CR_CR_INDEX 0 -+#define MMC_CR_CR_WIDTH 1 -+#define MMC_CR_CSR_INDEX 1 -+#define MMC_CR_CSR_WIDTH 1 -+#define MMC_CR_ROR_INDEX 2 -+#define MMC_CR_ROR_WIDTH 1 -+#define MMC_CR_MCF_INDEX 3 -+#define MMC_CR_MCF_WIDTH 1 -+#define MMC_CR_MCT_INDEX 4 -+#define MMC_CR_MCT_WIDTH 2 -+#define MMC_RIER_ALL_INTERRUPTS_INDEX 0 -+#define MMC_RIER_ALL_INTERRUPTS_WIDTH 23 -+#define MMC_RISR_RXFRAMECOUNT_GB_INDEX 0 -+#define MMC_RISR_RXFRAMECOUNT_GB_WIDTH 1 -+#define MMC_RISR_RXOCTETCOUNT_GB_INDEX 1 -+#define MMC_RISR_RXOCTETCOUNT_GB_WIDTH 1 -+#define MMC_RISR_RXOCTETCOUNT_G_INDEX 2 -+#define MMC_RISR_RXOCTETCOUNT_G_WIDTH 1 -+#define MMC_RISR_RXBROADCASTFRAMES_G_INDEX 3 -+#define MMC_RISR_RXBROADCASTFRAMES_G_WIDTH 1 -+#define MMC_RISR_RXMULTICASTFRAMES_G_INDEX 4 -+#define MMC_RISR_RXMULTICASTFRAMES_G_WIDTH 1 -+#define MMC_RISR_RXCRCERROR_INDEX 5 -+#define MMC_RISR_RXCRCERROR_WIDTH 1 -+#define MMC_RISR_RXRUNTERROR_INDEX 6 -+#define MMC_RISR_RXRUNTERROR_WIDTH 1 -+#define MMC_RISR_RXJABBERERROR_INDEX 7 -+#define MMC_RISR_RXJABBERERROR_WIDTH 1 -+#define MMC_RISR_RXUNDERSIZE_G_INDEX 8 -+#define MMC_RISR_RXUNDERSIZE_G_WIDTH 1 -+#define MMC_RISR_RXOVERSIZE_G_INDEX 9 -+#define MMC_RISR_RXOVERSIZE_G_WIDTH 1 -+#define MMC_RISR_RX64OCTETS_GB_INDEX 10 -+#define MMC_RISR_RX64OCTETS_GB_WIDTH 1 -+#define MMC_RISR_RX65TO127OCTETS_GB_INDEX 11 -+#define MMC_RISR_RX65TO127OCTETS_GB_WIDTH 1 -+#define MMC_RISR_RX128TO255OCTETS_GB_INDEX 12 -+#define MMC_RISR_RX128TO255OCTETS_GB_WIDTH 1 -+#define MMC_RISR_RX256TO511OCTETS_GB_INDEX 13 -+#define MMC_RISR_RX256TO511OCTETS_GB_WIDTH 1 -+#define MMC_RISR_RX512TO1023OCTETS_GB_INDEX 14 -+#define MMC_RISR_RX512TO1023OCTETS_GB_WIDTH 1 -+#define MMC_RISR_RX1024TOMAXOCTETS_GB_INDEX 15 -+#define MMC_RISR_RX1024TOMAXOCTETS_GB_WIDTH 1 -+#define MMC_RISR_RXUNICASTFRAMES_G_INDEX 16 -+#define MMC_RISR_RXUNICASTFRAMES_G_WIDTH 1 -+#define MMC_RISR_RXLENGTHERROR_INDEX 17 -+#define MMC_RISR_RXLENGTHERROR_WIDTH 1 -+#define MMC_RISR_RXOUTOFRANGETYPE_INDEX 18 -+#define MMC_RISR_RXOUTOFRANGETYPE_WIDTH 1 -+#define MMC_RISR_RXPAUSEFRAMES_INDEX 19 -+#define MMC_RISR_RXPAUSEFRAMES_WIDTH 1 -+#define MMC_RISR_RXFIFOOVERFLOW_INDEX 20 -+#define MMC_RISR_RXFIFOOVERFLOW_WIDTH 1 -+#define MMC_RISR_RXVLANFRAMES_GB_INDEX 21 -+#define MMC_RISR_RXVLANFRAMES_GB_WIDTH 1 -+#define MMC_RISR_RXWATCHDOGERROR_INDEX 22 -+#define MMC_RISR_RXWATCHDOGERROR_WIDTH 1 -+#define MMC_TIER_ALL_INTERRUPTS_INDEX 0 -+#define MMC_TIER_ALL_INTERRUPTS_WIDTH 18 -+#define MMC_TISR_TXOCTETCOUNT_GB_INDEX 0 -+#define MMC_TISR_TXOCTETCOUNT_GB_WIDTH 1 -+#define MMC_TISR_TXFRAMECOUNT_GB_INDEX 1 -+#define MMC_TISR_TXFRAMECOUNT_GB_WIDTH 1 -+#define MMC_TISR_TXBROADCASTFRAMES_G_INDEX 2 -+#define MMC_TISR_TXBROADCASTFRAMES_G_WIDTH 1 -+#define MMC_TISR_TXMULTICASTFRAMES_G_INDEX 3 -+#define MMC_TISR_TXMULTICASTFRAMES_G_WIDTH 1 -+#define MMC_TISR_TX64OCTETS_GB_INDEX 4 -+#define MMC_TISR_TX64OCTETS_GB_WIDTH 1 -+#define MMC_TISR_TX65TO127OCTETS_GB_INDEX 5 -+#define MMC_TISR_TX65TO127OCTETS_GB_WIDTH 1 -+#define MMC_TISR_TX128TO255OCTETS_GB_INDEX 6 -+#define MMC_TISR_TX128TO255OCTETS_GB_WIDTH 1 -+#define MMC_TISR_TX256TO511OCTETS_GB_INDEX 7 -+#define MMC_TISR_TX256TO511OCTETS_GB_WIDTH 1 -+#define MMC_TISR_TX512TO1023OCTETS_GB_INDEX 8 -+#define MMC_TISR_TX512TO1023OCTETS_GB_WIDTH 1 -+#define MMC_TISR_TX1024TOMAXOCTETS_GB_INDEX 9 -+#define MMC_TISR_TX1024TOMAXOCTETS_GB_WIDTH 1 -+#define MMC_TISR_TXUNICASTFRAMES_GB_INDEX 10 -+#define MMC_TISR_TXUNICASTFRAMES_GB_WIDTH 1 -+#define MMC_TISR_TXMULTICASTFRAMES_GB_INDEX 11 -+#define MMC_TISR_TXMULTICASTFRAMES_GB_WIDTH 1 -+#define MMC_TISR_TXBROADCASTFRAMES_GB_INDEX 12 -+#define MMC_TISR_TXBROADCASTFRAMES_GB_WIDTH 1 -+#define MMC_TISR_TXUNDERFLOWERROR_INDEX 13 -+#define MMC_TISR_TXUNDERFLOWERROR_WIDTH 1 -+#define MMC_TISR_TXOCTETCOUNT_G_INDEX 14 -+#define MMC_TISR_TXOCTETCOUNT_G_WIDTH 1 -+#define MMC_TISR_TXFRAMECOUNT_G_INDEX 15 -+#define MMC_TISR_TXFRAMECOUNT_G_WIDTH 1 -+#define MMC_TISR_TXPAUSEFRAMES_INDEX 16 -+#define MMC_TISR_TXPAUSEFRAMES_WIDTH 1 -+#define MMC_TISR_TXVLANFRAMES_G_INDEX 17 -+#define MMC_TISR_TXVLANFRAMES_G_WIDTH 1 -+ -+/* MTL register offsets */ -+#define MTL_OMR 0x1000 -+#define MTL_FDCR 0x1008 -+#define MTL_FDSR 0x100c -+#define MTL_FDDR 0x1010 -+#define MTL_ISR 0x1020 -+#define MTL_RQDCM0R 0x1030 -+#define MTL_TCPM0R 0x1040 -+#define MTL_TCPM1R 0x1044 -+ -+#define MTL_RQDCM_INC 4 -+#define MTL_RQDCM_Q_PER_REG 4 -+#define MTL_TCPM_INC 4 -+#define MTL_TCPM_TC_PER_REG 4 -+ -+/* MTL register entry bit positions and sizes */ -+#define MTL_OMR_ETSALG_INDEX 5 -+#define MTL_OMR_ETSALG_WIDTH 2 -+#define MTL_OMR_RAA_INDEX 2 -+#define MTL_OMR_RAA_WIDTH 1 -+ -+/* MTL queue register offsets -+ * Multiple queues can be active. The first queue has registers -+ * that begin at 0x1100. Each subsequent queue has registers that -+ * are accessed using an offset of 0x80 from the previous queue. -+ */ -+#define MTL_Q_BASE 0x1100 -+#define MTL_Q_INC 0x80 -+ -+#define MTL_Q_TQOMR 0x00 -+#define MTL_Q_TQUR 0x04 -+#define MTL_Q_TQDR 0x08 -+#define MTL_Q_RQOMR 0x40 -+#define MTL_Q_RQMPOCR 0x44 -+#define MTL_Q_RQDR 0x4c -+#define MTL_Q_IER 0x70 -+#define MTL_Q_ISR 0x74 -+ -+/* MTL queue register entry bit positions and sizes */ -+#define MTL_Q_RQOMR_EHFC_INDEX 7 -+#define MTL_Q_RQOMR_EHFC_WIDTH 1 -+#define MTL_Q_RQOMR_RFA_INDEX 8 -+#define MTL_Q_RQOMR_RFA_WIDTH 3 -+#define MTL_Q_RQOMR_RFD_INDEX 13 -+#define MTL_Q_RQOMR_RFD_WIDTH 3 -+#define MTL_Q_RQOMR_RQS_INDEX 16 -+#define MTL_Q_RQOMR_RQS_WIDTH 9 -+#define MTL_Q_RQOMR_RSF_INDEX 5 -+#define MTL_Q_RQOMR_RSF_WIDTH 1 -+#define MTL_Q_RQOMR_RTC_INDEX 0 -+#define MTL_Q_RQOMR_RTC_WIDTH 2 -+#define MTL_Q_TQOMR_FTQ_INDEX 0 -+#define MTL_Q_TQOMR_FTQ_WIDTH 1 -+#define MTL_Q_TQOMR_Q2TCMAP_INDEX 8 -+#define MTL_Q_TQOMR_Q2TCMAP_WIDTH 3 -+#define MTL_Q_TQOMR_TQS_INDEX 16 -+#define MTL_Q_TQOMR_TQS_WIDTH 10 -+#define MTL_Q_TQOMR_TSF_INDEX 1 -+#define MTL_Q_TQOMR_TSF_WIDTH 1 -+#define MTL_Q_TQOMR_TTC_INDEX 4 -+#define MTL_Q_TQOMR_TTC_WIDTH 3 -+#define MTL_Q_TQOMR_TXQEN_INDEX 2 -+#define MTL_Q_TQOMR_TXQEN_WIDTH 2 -+ -+/* MTL queue register value */ -+#define MTL_RSF_DISABLE 0x00 -+#define MTL_RSF_ENABLE 0x01 -+#define MTL_TSF_DISABLE 0x00 -+#define MTL_TSF_ENABLE 0x01 -+ -+#define MTL_RX_THRESHOLD_64 0x00 -+#define MTL_RX_THRESHOLD_96 0x02 -+#define MTL_RX_THRESHOLD_128 0x03 -+#define MTL_TX_THRESHOLD_32 0x01 -+#define MTL_TX_THRESHOLD_64 0x00 -+#define MTL_TX_THRESHOLD_96 0x02 -+#define MTL_TX_THRESHOLD_128 0x03 -+#define MTL_TX_THRESHOLD_192 0x04 -+#define MTL_TX_THRESHOLD_256 0x05 -+#define MTL_TX_THRESHOLD_384 0x06 -+#define MTL_TX_THRESHOLD_512 0x07 -+ -+#define MTL_ETSALG_WRR 0x00 -+#define MTL_ETSALG_WFQ 0x01 -+#define MTL_ETSALG_DWRR 0x02 -+#define MTL_RAA_SP 0x00 -+#define MTL_RAA_WSP 0x01 -+ -+#define MTL_Q_DISABLED 0x00 -+#define MTL_Q_ENABLED 0x02 -+ -+/* MTL traffic class register offsets -+ * Multiple traffic classes can be active. The first class has registers -+ * that begin at 0x1100. Each subsequent queue has registers that -+ * are accessed using an offset of 0x80 from the previous queue. -+ */ -+#define MTL_TC_BASE MTL_Q_BASE -+#define MTL_TC_INC MTL_Q_INC -+ -+#define MTL_TC_ETSCR 0x10 -+#define MTL_TC_ETSSR 0x14 -+#define MTL_TC_QWR 0x18 -+ -+/* MTL traffic class register entry bit positions and sizes */ -+#define MTL_TC_ETSCR_TSA_INDEX 0 -+#define MTL_TC_ETSCR_TSA_WIDTH 2 -+#define MTL_TC_QWR_QW_INDEX 0 -+#define MTL_TC_QWR_QW_WIDTH 21 -+ -+/* MTL traffic class register value */ -+#define MTL_TSA_SP 0x00 -+#define MTL_TSA_ETS 0x02 -+ -+/* PCS MMD select register offset -+ * The MMD select register is used for accessing PCS registers -+ * when the underlying APB3 interface is using indirect addressing. -+ * Indirect addressing requires accessing registers in two phases, -+ * an address phase and a data phase. The address phases requires -+ * writing an address selection value to the MMD select regiesters. -+ */ -+#define PCS_MMD_SELECT 0xff -+ -+/* Descriptor/Packet entry bit positions and sizes */ -+#define RX_PACKET_ERRORS_CRC_INDEX 2 -+#define RX_PACKET_ERRORS_CRC_WIDTH 1 -+#define RX_PACKET_ERRORS_FRAME_INDEX 3 -+#define RX_PACKET_ERRORS_FRAME_WIDTH 1 -+#define RX_PACKET_ERRORS_LENGTH_INDEX 0 -+#define RX_PACKET_ERRORS_LENGTH_WIDTH 1 -+#define RX_PACKET_ERRORS_OVERRUN_INDEX 1 -+#define RX_PACKET_ERRORS_OVERRUN_WIDTH 1 -+ -+#define RX_PACKET_ATTRIBUTES_CSUM_DONE_INDEX 0 -+#define RX_PACKET_ATTRIBUTES_CSUM_DONE_WIDTH 1 -+#define RX_PACKET_ATTRIBUTES_VLAN_CTAG_INDEX 1 -+#define RX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH 1 -+#define RX_PACKET_ATTRIBUTES_INCOMPLETE_INDEX 2 -+#define RX_PACKET_ATTRIBUTES_INCOMPLETE_WIDTH 1 -+#define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_INDEX 3 -+#define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_WIDTH 1 -+#define RX_PACKET_ATTRIBUTES_CONTEXT_INDEX 4 -+#define RX_PACKET_ATTRIBUTES_CONTEXT_WIDTH 1 -+#define RX_PACKET_ATTRIBUTES_RX_TSTAMP_INDEX 5 -+#define RX_PACKET_ATTRIBUTES_RX_TSTAMP_WIDTH 1 -+#define RX_PACKET_ATTRIBUTES_RSS_HASH_INDEX 6 -+#define RX_PACKET_ATTRIBUTES_RSS_HASH_WIDTH 1 -+ -+#define RX_NORMAL_DESC0_OVT_INDEX 0 -+#define RX_NORMAL_DESC0_OVT_WIDTH 16 -+#define RX_NORMAL_DESC2_HL_INDEX 0 -+#define RX_NORMAL_DESC2_HL_WIDTH 10 -+#define RX_NORMAL_DESC3_CDA_INDEX 27 -+#define RX_NORMAL_DESC3_CDA_WIDTH 1 -+#define RX_NORMAL_DESC3_CTXT_INDEX 30 -+#define RX_NORMAL_DESC3_CTXT_WIDTH 1 -+#define RX_NORMAL_DESC3_ES_INDEX 15 -+#define RX_NORMAL_DESC3_ES_WIDTH 1 -+#define RX_NORMAL_DESC3_ETLT_INDEX 16 -+#define RX_NORMAL_DESC3_ETLT_WIDTH 4 -+#define RX_NORMAL_DESC3_FD_INDEX 29 -+#define RX_NORMAL_DESC3_FD_WIDTH 1 -+#define RX_NORMAL_DESC3_INTE_INDEX 30 -+#define RX_NORMAL_DESC3_INTE_WIDTH 1 -+#define RX_NORMAL_DESC3_L34T_INDEX 20 -+#define RX_NORMAL_DESC3_L34T_WIDTH 4 -+#define RX_NORMAL_DESC3_LD_INDEX 28 -+#define RX_NORMAL_DESC3_LD_WIDTH 1 -+#define RX_NORMAL_DESC3_OWN_INDEX 31 -+#define RX_NORMAL_DESC3_OWN_WIDTH 1 -+#define RX_NORMAL_DESC3_PL_INDEX 0 -+#define RX_NORMAL_DESC3_PL_WIDTH 14 -+#define RX_NORMAL_DESC3_RSV_INDEX 26 -+#define RX_NORMAL_DESC3_RSV_WIDTH 1 -+ -+#define RX_DESC3_L34T_IPV4_TCP 1 -+#define RX_DESC3_L34T_IPV4_UDP 2 -+#define RX_DESC3_L34T_IPV4_ICMP 3 -+#define RX_DESC3_L34T_IPV6_TCP 9 -+#define RX_DESC3_L34T_IPV6_UDP 10 -+#define RX_DESC3_L34T_IPV6_ICMP 11 -+ -+#define RX_CONTEXT_DESC3_TSA_INDEX 4 -+#define RX_CONTEXT_DESC3_TSA_WIDTH 1 -+#define RX_CONTEXT_DESC3_TSD_INDEX 6 -+#define RX_CONTEXT_DESC3_TSD_WIDTH 1 -+ -+#define TX_PACKET_ATTRIBUTES_CSUM_ENABLE_INDEX 0 -+#define TX_PACKET_ATTRIBUTES_CSUM_ENABLE_WIDTH 1 -+#define TX_PACKET_ATTRIBUTES_TSO_ENABLE_INDEX 1 -+#define TX_PACKET_ATTRIBUTES_TSO_ENABLE_WIDTH 1 -+#define TX_PACKET_ATTRIBUTES_VLAN_CTAG_INDEX 2 -+#define TX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH 1 -+#define TX_PACKET_ATTRIBUTES_PTP_INDEX 3 -+#define TX_PACKET_ATTRIBUTES_PTP_WIDTH 1 -+ -+#define TX_CONTEXT_DESC2_MSS_INDEX 0 -+#define TX_CONTEXT_DESC2_MSS_WIDTH 15 -+#define TX_CONTEXT_DESC3_CTXT_INDEX 30 -+#define TX_CONTEXT_DESC3_CTXT_WIDTH 1 -+#define TX_CONTEXT_DESC3_TCMSSV_INDEX 26 -+#define TX_CONTEXT_DESC3_TCMSSV_WIDTH 1 -+#define TX_CONTEXT_DESC3_VLTV_INDEX 16 -+#define TX_CONTEXT_DESC3_VLTV_WIDTH 1 -+#define TX_CONTEXT_DESC3_VT_INDEX 0 -+#define TX_CONTEXT_DESC3_VT_WIDTH 16 -+ -+#define TX_NORMAL_DESC2_HL_B1L_INDEX 0 -+#define TX_NORMAL_DESC2_HL_B1L_WIDTH 14 -+#define TX_NORMAL_DESC2_IC_INDEX 31 -+#define TX_NORMAL_DESC2_IC_WIDTH 1 -+#define TX_NORMAL_DESC2_TTSE_INDEX 30 -+#define TX_NORMAL_DESC2_TTSE_WIDTH 1 -+#define TX_NORMAL_DESC2_VTIR_INDEX 14 -+#define TX_NORMAL_DESC2_VTIR_WIDTH 2 -+#define TX_NORMAL_DESC3_CIC_INDEX 16 -+#define TX_NORMAL_DESC3_CIC_WIDTH 2 -+#define TX_NORMAL_DESC3_CPC_INDEX 26 -+#define TX_NORMAL_DESC3_CPC_WIDTH 2 -+#define TX_NORMAL_DESC3_CTXT_INDEX 30 -+#define TX_NORMAL_DESC3_CTXT_WIDTH 1 -+#define TX_NORMAL_DESC3_FD_INDEX 29 -+#define TX_NORMAL_DESC3_FD_WIDTH 1 -+#define TX_NORMAL_DESC3_FL_INDEX 0 -+#define TX_NORMAL_DESC3_FL_WIDTH 15 -+#define TX_NORMAL_DESC3_LD_INDEX 28 -+#define TX_NORMAL_DESC3_LD_WIDTH 1 -+#define TX_NORMAL_DESC3_OWN_INDEX 31 -+#define TX_NORMAL_DESC3_OWN_WIDTH 1 -+#define TX_NORMAL_DESC3_TCPHDRLEN_INDEX 19 -+#define TX_NORMAL_DESC3_TCPHDRLEN_WIDTH 4 -+#define TX_NORMAL_DESC3_TCPPL_INDEX 0 -+#define TX_NORMAL_DESC3_TCPPL_WIDTH 18 -+#define TX_NORMAL_DESC3_TSE_INDEX 18 -+#define TX_NORMAL_DESC3_TSE_WIDTH 1 -+ -+#define TX_NORMAL_DESC2_VLAN_INSERT 0x2 -+ -+/* MDIO undefined or vendor specific registers */ -+#ifndef MDIO_AN_COMP_STAT -+#define MDIO_AN_COMP_STAT 0x0030 -+#endif -+ -+/* Bit setting and getting macros -+ * The get macro will extract the current bit field value from within -+ * the variable -+ * -+ * The set macro will clear the current bit field value within the -+ * variable and then set the bit field of the variable to the -+ * specified value -+ */ -+#define GET_BITS(_var, _index, _width) \ -+ (((_var) >> (_index)) & ((0x1 << (_width)) - 1)) -+ -+#define SET_BITS(_var, _index, _width, _val) \ -+do { \ -+ (_var) &= ~(((0x1 << (_width)) - 1) << (_index)); \ -+ (_var) |= (((_val) & ((0x1 << (_width)) - 1)) << (_index)); \ -+} while (0) -+ -+#define GET_BITS_LE(_var, _index, _width) \ -+ ((le32_to_cpu((_var)) >> (_index)) & ((0x1 << (_width)) - 1)) -+ -+#define SET_BITS_LE(_var, _index, _width, _val) \ -+do { \ -+ (_var) &= cpu_to_le32(~(((0x1 << (_width)) - 1) << (_index))); \ -+ (_var) |= cpu_to_le32((((_val) & \ -+ ((0x1 << (_width)) - 1)) << (_index))); \ -+} while (0) -+ -+/* Bit setting and getting macros based on register fields -+ * The get macro uses the bit field definitions formed using the input -+ * names to extract the current bit field value from within the -+ * variable -+ * -+ * The set macro uses the bit field definitions formed using the input -+ * names to set the bit field of the variable to the specified value -+ */ -+#define XGMAC_GET_BITS(_var, _prefix, _field) \ -+ GET_BITS((_var), \ -+ _prefix##_##_field##_INDEX, \ -+ _prefix##_##_field##_WIDTH) -+ -+#define XGMAC_SET_BITS(_var, _prefix, _field, _val) \ -+ SET_BITS((_var), \ -+ _prefix##_##_field##_INDEX, \ -+ _prefix##_##_field##_WIDTH, (_val)) -+ -+#define XGMAC_GET_BITS_LE(_var, _prefix, _field) \ -+ GET_BITS_LE((_var), \ -+ _prefix##_##_field##_INDEX, \ -+ _prefix##_##_field##_WIDTH) -+ -+#define XGMAC_SET_BITS_LE(_var, _prefix, _field, _val) \ -+ SET_BITS_LE((_var), \ -+ _prefix##_##_field##_INDEX, \ -+ _prefix##_##_field##_WIDTH, (_val)) -+ -+/* Macros for reading or writing registers -+ * The ioread macros will get bit fields or full values using the -+ * register definitions formed using the input names -+ * -+ * The iowrite macros will set bit fields or full values using the -+ * register definitions formed using the input names -+ */ -+#define XGMAC_IOREAD(_pdata, _reg) \ -+ ioread32((_pdata)->xgmac_regs + _reg) -+ -+#define XGMAC_IOREAD_BITS(_pdata, _reg, _field) \ -+ GET_BITS(XGMAC_IOREAD((_pdata), _reg), \ -+ _reg##_##_field##_INDEX, \ -+ _reg##_##_field##_WIDTH) -+ -+#define XGMAC_IOWRITE(_pdata, _reg, _val) \ -+ iowrite32((_val), (_pdata)->xgmac_regs + _reg) -+ -+#define XGMAC_IOWRITE_BITS(_pdata, _reg, _field, _val) \ -+do { \ -+ u32 reg_val = XGMAC_IOREAD((_pdata), _reg); \ -+ SET_BITS(reg_val, \ -+ _reg##_##_field##_INDEX, \ -+ _reg##_##_field##_WIDTH, (_val)); \ -+ XGMAC_IOWRITE((_pdata), _reg, reg_val); \ -+} while (0) -+ -+/* Macros for reading or writing MTL queue or traffic class registers -+ * Similar to the standard read and write macros except that the -+ * base register value is calculated by the queue or traffic class number -+ */ -+#define XGMAC_MTL_IOREAD(_pdata, _n, _reg) \ -+ ioread32((_pdata)->xgmac_regs + \ -+ MTL_Q_BASE + ((_n) * MTL_Q_INC) + _reg) -+ -+#define XGMAC_MTL_IOREAD_BITS(_pdata, _n, _reg, _field) \ -+ GET_BITS(XGMAC_MTL_IOREAD((_pdata), (_n), _reg), \ -+ _reg##_##_field##_INDEX, \ -+ _reg##_##_field##_WIDTH) -+ -+#define XGMAC_MTL_IOWRITE(_pdata, _n, _reg, _val) \ -+ iowrite32((_val), (_pdata)->xgmac_regs + \ -+ MTL_Q_BASE + ((_n) * MTL_Q_INC) + _reg) -+ -+#define XGMAC_MTL_IOWRITE_BITS(_pdata, _n, _reg, _field, _val) \ -+do { \ -+ u32 reg_val = XGMAC_MTL_IOREAD((_pdata), (_n), _reg); \ -+ SET_BITS(reg_val, \ -+ _reg##_##_field##_INDEX, \ -+ _reg##_##_field##_WIDTH, (_val)); \ -+ XGMAC_MTL_IOWRITE((_pdata), (_n), _reg, reg_val); \ -+} while (0) -+ -+/* Macros for reading or writing DMA channel registers -+ * Similar to the standard read and write macros except that the -+ * base register value is obtained from the ring -+ */ -+#define XGMAC_DMA_IOREAD(_channel, _reg) \ -+ ioread32((_channel)->dma_regs + _reg) -+ -+#define XGMAC_DMA_IOREAD_BITS(_channel, _reg, _field) \ -+ GET_BITS(XGMAC_DMA_IOREAD((_channel), _reg), \ -+ _reg##_##_field##_INDEX, \ -+ _reg##_##_field##_WIDTH) -+ -+#define XGMAC_DMA_IOWRITE(_channel, _reg, _val) \ -+ iowrite32((_val), (_channel)->dma_regs + _reg) -+ -+#define XGMAC_DMA_IOWRITE_BITS(_channel, _reg, _field, _val) \ -+do { \ -+ u32 reg_val = XGMAC_DMA_IOREAD((_channel), _reg); \ -+ SET_BITS(reg_val, \ -+ _reg##_##_field##_INDEX, \ -+ _reg##_##_field##_WIDTH, (_val)); \ -+ XGMAC_DMA_IOWRITE((_channel), _reg, reg_val); \ -+} while (0) -+ -+/* Macros for building, reading or writing register values or bits -+ * within the register values of XPCS registers. -+ */ -+#define XPCS_IOWRITE(_pdata, _off, _val) \ -+ iowrite32(_val, (_pdata)->xpcs_regs + (_off)) -+ -+#define XPCS_IOREAD(_pdata, _off) \ -+ ioread32((_pdata)->xpcs_regs + (_off)) -+ -+/* Macros for building, reading or writing register values or bits -+ * using MDIO. Different from above because of the use of standardized -+ * Linux include values. No shifting is performed with the bit -+ * operations, everything works on mask values. -+ */ -+#define XMDIO_READ(_pdata, _mmd, _reg) \ -+ ((_pdata)->hw_if.read_mmd_regs((_pdata), 0, \ -+ MII_ADDR_C45 | (_mmd << 16) | ((_reg) & 0xffff))) -+ -+#define XMDIO_READ_BITS(_pdata, _mmd, _reg, _mask) \ -+ (XMDIO_READ((_pdata), _mmd, _reg) & _mask) -+ -+#define XMDIO_WRITE(_pdata, _mmd, _reg, _val) \ -+ ((_pdata)->hw_if.write_mmd_regs((_pdata), 0, \ -+ MII_ADDR_C45 | (_mmd << 16) | ((_reg) & 0xffff), (_val))) -+ -+#define XMDIO_WRITE_BITS(_pdata, _mmd, _reg, _mask, _val) \ -+do { \ -+ u32 mmd_val = XMDIO_READ((_pdata), _mmd, _reg); \ -+ mmd_val &= ~_mask; \ -+ mmd_val |= (_val); \ -+ XMDIO_WRITE((_pdata), _mmd, _reg, mmd_val); \ -+} while (0) -+ -+#endif -diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-dcb.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-dcb.c -new file mode 100644 -index 0000000..343301c ---- /dev/null -+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-dcb.c -@@ -0,0 +1,269 @@ -+/* -+ * AMD 10Gb Ethernet driver -+ * -+ * This file is available to you under your choice of the following two -+ * licenses: -+ * -+ * License 1: GPLv2 -+ * -+ * Copyright (c) 2014 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 . -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * -+ * License 2: Modified BSD -+ * -+ * Copyright (c) 2014 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 BE LIABLE FOR ANY -+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+ -+#include "xgbe.h" -+#include "xgbe-common.h" -+ -+static int xgbe_dcb_ieee_getets(struct net_device *netdev, -+ struct ieee_ets *ets) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ -+ /* Set number of supported traffic classes */ -+ ets->ets_cap = pdata->hw_feat.tc_cnt; -+ -+ if (pdata->ets) { -+ ets->cbs = pdata->ets->cbs; -+ memcpy(ets->tc_tx_bw, pdata->ets->tc_tx_bw, -+ sizeof(ets->tc_tx_bw)); -+ memcpy(ets->tc_tsa, pdata->ets->tc_tsa, -+ sizeof(ets->tc_tsa)); -+ memcpy(ets->prio_tc, pdata->ets->prio_tc, -+ sizeof(ets->prio_tc)); -+ } -+ -+ return 0; -+} -+ -+static int xgbe_dcb_ieee_setets(struct net_device *netdev, -+ struct ieee_ets *ets) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ unsigned int i, tc_ets, tc_ets_weight; -+ -+ tc_ets = 0; -+ tc_ets_weight = 0; -+ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { -+ DBGPR(" TC%u: tx_bw=%hhu, rx_bw=%hhu, tsa=%hhu\n", i, -+ ets->tc_tx_bw[i], ets->tc_rx_bw[i], ets->tc_tsa[i]); -+ DBGPR(" PRIO%u: TC=%hhu\n", i, ets->prio_tc[i]); -+ -+ if ((ets->tc_tx_bw[i] || ets->tc_tsa[i]) && -+ (i >= pdata->hw_feat.tc_cnt)) -+ return -EINVAL; -+ -+ if (ets->prio_tc[i] >= pdata->hw_feat.tc_cnt) -+ return -EINVAL; -+ -+ switch (ets->tc_tsa[i]) { -+ case IEEE_8021QAZ_TSA_STRICT: -+ break; -+ case IEEE_8021QAZ_TSA_ETS: -+ tc_ets = 1; -+ tc_ets_weight += ets->tc_tx_bw[i]; -+ break; -+ -+ default: -+ return -EINVAL; -+ } -+ } -+ -+ /* Weights must add up to 100% */ -+ if (tc_ets && (tc_ets_weight != 100)) -+ return -EINVAL; -+ -+ if (!pdata->ets) { -+ pdata->ets = devm_kzalloc(pdata->dev, sizeof(*pdata->ets), -+ GFP_KERNEL); -+ if (!pdata->ets) -+ return -ENOMEM; -+ } -+ -+ memcpy(pdata->ets, ets, sizeof(*pdata->ets)); -+ -+ pdata->hw_if.config_dcb_tc(pdata); -+ -+ return 0; -+} -+ -+static int xgbe_dcb_ieee_getpfc(struct net_device *netdev, -+ struct ieee_pfc *pfc) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ -+ /* Set number of supported PFC traffic classes */ -+ pfc->pfc_cap = pdata->hw_feat.tc_cnt; -+ -+ if (pdata->pfc) { -+ pfc->pfc_en = pdata->pfc->pfc_en; -+ pfc->mbc = pdata->pfc->mbc; -+ pfc->delay = pdata->pfc->delay; -+ } -+ -+ return 0; -+} -+ -+static int xgbe_dcb_ieee_setpfc(struct net_device *netdev, -+ struct ieee_pfc *pfc) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ -+ DBGPR(" cap=%hhu, en=%hhx, mbc=%hhu, delay=%hhu\n", -+ pfc->pfc_cap, pfc->pfc_en, pfc->mbc, pfc->delay); -+ -+ if (!pdata->pfc) { -+ pdata->pfc = devm_kzalloc(pdata->dev, sizeof(*pdata->pfc), -+ GFP_KERNEL); -+ if (!pdata->pfc) -+ return -ENOMEM; -+ } -+ -+ memcpy(pdata->pfc, pfc, sizeof(*pdata->pfc)); -+ -+ pdata->hw_if.config_dcb_pfc(pdata); -+ -+ return 0; -+} -+ -+static u8 xgbe_dcb_getdcbx(struct net_device *netdev) -+{ -+ return DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE; -+} -+ -+static u8 xgbe_dcb_setdcbx(struct net_device *netdev, u8 dcbx) -+{ -+ u8 support = xgbe_dcb_getdcbx(netdev); -+ -+ DBGPR(" DCBX=%#hhx\n", dcbx); -+ -+ if (dcbx & ~support) -+ return 1; -+ -+ if ((dcbx & support) != support) -+ return 1; -+ -+ return 0; -+} -+ -+static const struct dcbnl_rtnl_ops xgbe_dcbnl_ops = { -+ /* IEEE 802.1Qaz std */ -+ .ieee_getets = xgbe_dcb_ieee_getets, -+ .ieee_setets = xgbe_dcb_ieee_setets, -+ .ieee_getpfc = xgbe_dcb_ieee_getpfc, -+ .ieee_setpfc = xgbe_dcb_ieee_setpfc, -+ -+ /* DCBX configuration */ -+ .getdcbx = xgbe_dcb_getdcbx, -+ .setdcbx = xgbe_dcb_setdcbx, -+}; -+ -+const struct dcbnl_rtnl_ops *xgbe_a0_get_dcbnl_ops(void) -+{ -+ return &xgbe_dcbnl_ops; -+} -diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-debugfs.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-debugfs.c -new file mode 100644 -index 0000000..ecfa6f9 ---- /dev/null -+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-debugfs.c -@@ -0,0 +1,373 @@ -+/* -+ * AMD 10Gb Ethernet driver -+ * -+ * This file is available to you under your choice of the following two -+ * licenses: -+ * -+ * License 1: GPLv2 -+ * -+ * Copyright (c) 2014 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 . -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * -+ * License 2: Modified BSD -+ * -+ * Copyright (c) 2014 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 BE LIABLE FOR ANY -+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include -+ -+#include "xgbe.h" -+#include "xgbe-common.h" -+ -+static ssize_t xgbe_common_read(char __user *buffer, size_t count, -+ loff_t *ppos, unsigned int value) -+{ -+ char *buf; -+ ssize_t len; -+ -+ if (*ppos != 0) -+ return 0; -+ -+ buf = kasprintf(GFP_KERNEL, "0x%08x\n", value); -+ if (!buf) -+ return -ENOMEM; -+ -+ if (count < strlen(buf)) { -+ kfree(buf); -+ return -ENOSPC; -+ } -+ -+ len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf)); -+ kfree(buf); -+ -+ return len; -+} -+ -+static ssize_t xgbe_common_write(const char __user *buffer, size_t count, -+ loff_t *ppos, unsigned int *value) -+{ -+ char workarea[32]; -+ ssize_t len; -+ int ret; -+ -+ if (*ppos != 0) -+ return 0; -+ -+ if (count >= sizeof(workarea)) -+ return -ENOSPC; -+ -+ len = simple_write_to_buffer(workarea, sizeof(workarea) - 1, ppos, -+ buffer, count); -+ if (len < 0) -+ return len; -+ -+ workarea[len] = '\0'; -+ ret = kstrtouint(workarea, 16, value); -+ if (ret) -+ return -EIO; -+ -+ return len; -+} -+ -+static ssize_t xgmac_reg_addr_read(struct file *filp, char __user *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct xgbe_prv_data *pdata = filp->private_data; -+ -+ return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xgmac_reg); -+} -+ -+static ssize_t xgmac_reg_addr_write(struct file *filp, -+ const char __user *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct xgbe_prv_data *pdata = filp->private_data; -+ -+ return xgbe_common_write(buffer, count, ppos, -+ &pdata->debugfs_xgmac_reg); -+} -+ -+static ssize_t xgmac_reg_value_read(struct file *filp, char __user *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct xgbe_prv_data *pdata = filp->private_data; -+ unsigned int value; -+ -+ value = XGMAC_IOREAD(pdata, pdata->debugfs_xgmac_reg); -+ -+ return xgbe_common_read(buffer, count, ppos, value); -+} -+ -+static ssize_t xgmac_reg_value_write(struct file *filp, -+ const char __user *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct xgbe_prv_data *pdata = filp->private_data; -+ unsigned int value; -+ ssize_t len; -+ -+ len = xgbe_common_write(buffer, count, ppos, &value); -+ if (len < 0) -+ return len; -+ -+ XGMAC_IOWRITE(pdata, pdata->debugfs_xgmac_reg, value); -+ -+ return len; -+} -+ -+static const struct file_operations xgmac_reg_addr_fops = { -+ .owner = THIS_MODULE, -+ .open = simple_open, -+ .read = xgmac_reg_addr_read, -+ .write = xgmac_reg_addr_write, -+}; -+ -+static const struct file_operations xgmac_reg_value_fops = { -+ .owner = THIS_MODULE, -+ .open = simple_open, -+ .read = xgmac_reg_value_read, -+ .write = xgmac_reg_value_write, -+}; -+ -+static ssize_t xpcs_mmd_read(struct file *filp, char __user *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct xgbe_prv_data *pdata = filp->private_data; -+ -+ return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xpcs_mmd); -+} -+ -+static ssize_t xpcs_mmd_write(struct file *filp, const char __user *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct xgbe_prv_data *pdata = filp->private_data; -+ -+ return xgbe_common_write(buffer, count, ppos, -+ &pdata->debugfs_xpcs_mmd); -+} -+ -+static ssize_t xpcs_reg_addr_read(struct file *filp, char __user *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct xgbe_prv_data *pdata = filp->private_data; -+ -+ return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xpcs_reg); -+} -+ -+static ssize_t xpcs_reg_addr_write(struct file *filp, const char __user *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct xgbe_prv_data *pdata = filp->private_data; -+ -+ return xgbe_common_write(buffer, count, ppos, -+ &pdata->debugfs_xpcs_reg); -+} -+ -+static ssize_t xpcs_reg_value_read(struct file *filp, char __user *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct xgbe_prv_data *pdata = filp->private_data; -+ unsigned int value; -+ -+ value = XMDIO_READ(pdata, pdata->debugfs_xpcs_mmd, -+ pdata->debugfs_xpcs_reg); -+ -+ return xgbe_common_read(buffer, count, ppos, value); -+} -+ -+static ssize_t xpcs_reg_value_write(struct file *filp, -+ const char __user *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct xgbe_prv_data *pdata = filp->private_data; -+ unsigned int value; -+ ssize_t len; -+ -+ len = xgbe_common_write(buffer, count, ppos, &value); -+ if (len < 0) -+ return len; -+ -+ XMDIO_WRITE(pdata, pdata->debugfs_xpcs_mmd, pdata->debugfs_xpcs_reg, -+ value); -+ -+ return len; -+} -+ -+static const struct file_operations xpcs_mmd_fops = { -+ .owner = THIS_MODULE, -+ .open = simple_open, -+ .read = xpcs_mmd_read, -+ .write = xpcs_mmd_write, -+}; -+ -+static const struct file_operations xpcs_reg_addr_fops = { -+ .owner = THIS_MODULE, -+ .open = simple_open, -+ .read = xpcs_reg_addr_read, -+ .write = xpcs_reg_addr_write, -+}; -+ -+static const struct file_operations xpcs_reg_value_fops = { -+ .owner = THIS_MODULE, -+ .open = simple_open, -+ .read = xpcs_reg_value_read, -+ .write = xpcs_reg_value_write, -+}; -+ -+void xgbe_a0_debugfs_init(struct xgbe_prv_data *pdata) -+{ -+ struct dentry *pfile; -+ char *buf; -+ -+ /* Set defaults */ -+ pdata->debugfs_xgmac_reg = 0; -+ pdata->debugfs_xpcs_mmd = 1; -+ pdata->debugfs_xpcs_reg = 0; -+ -+ buf = kasprintf(GFP_KERNEL, "amd-xgbe-a0-%s", pdata->netdev->name); -+ pdata->xgbe_debugfs = debugfs_create_dir(buf, NULL); -+ if (!pdata->xgbe_debugfs) { -+ netdev_err(pdata->netdev, "debugfs_create_dir failed\n"); -+ return; -+ } -+ -+ pfile = debugfs_create_file("xgmac_register", 0600, -+ pdata->xgbe_debugfs, pdata, -+ &xgmac_reg_addr_fops); -+ if (!pfile) -+ netdev_err(pdata->netdev, "debugfs_create_file failed\n"); -+ -+ pfile = debugfs_create_file("xgmac_register_value", 0600, -+ pdata->xgbe_debugfs, pdata, -+ &xgmac_reg_value_fops); -+ if (!pfile) -+ netdev_err(pdata->netdev, "debugfs_create_file failed\n"); -+ -+ pfile = debugfs_create_file("xpcs_mmd", 0600, -+ pdata->xgbe_debugfs, pdata, -+ &xpcs_mmd_fops); -+ if (!pfile) -+ netdev_err(pdata->netdev, "debugfs_create_file failed\n"); -+ -+ pfile = debugfs_create_file("xpcs_register", 0600, -+ pdata->xgbe_debugfs, pdata, -+ &xpcs_reg_addr_fops); -+ if (!pfile) -+ netdev_err(pdata->netdev, "debugfs_create_file failed\n"); -+ -+ pfile = debugfs_create_file("xpcs_register_value", 0600, -+ pdata->xgbe_debugfs, pdata, -+ &xpcs_reg_value_fops); -+ if (!pfile) -+ netdev_err(pdata->netdev, "debugfs_create_file failed\n"); -+ -+ kfree(buf); -+} -+ -+void xgbe_a0_debugfs_exit(struct xgbe_prv_data *pdata) -+{ -+ debugfs_remove_recursive(pdata->xgbe_debugfs); -+ pdata->xgbe_debugfs = NULL; -+} -diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-desc.c -new file mode 100644 -index 0000000..5dd5777 ---- /dev/null -+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-desc.c -@@ -0,0 +1,636 @@ -+/* -+ * AMD 10Gb Ethernet driver -+ * -+ * This file is available to you under your choice of the following two -+ * licenses: -+ * -+ * License 1: GPLv2 -+ * -+ * Copyright (c) 2014 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 . -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * -+ * License 2: Modified BSD -+ * -+ * Copyright (c) 2014 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 BE LIABLE FOR ANY -+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include "xgbe.h" -+#include "xgbe-common.h" -+ -+static void xgbe_unmap_rdata(struct xgbe_prv_data *, struct xgbe_ring_data *); -+ -+static void xgbe_free_ring(struct xgbe_prv_data *pdata, -+ struct xgbe_ring *ring) -+{ -+ struct xgbe_ring_data *rdata; -+ unsigned int i; -+ -+ if (!ring) -+ return; -+ -+ if (ring->rdata) { -+ for (i = 0; i < ring->rdesc_count; i++) { -+ rdata = XGBE_GET_DESC_DATA(ring, i); -+ xgbe_unmap_rdata(pdata, rdata); -+ } -+ -+ kfree(ring->rdata); -+ ring->rdata = NULL; -+ } -+ -+ if (ring->rx_hdr_pa.pages) { -+ dma_unmap_page(pdata->dev, ring->rx_hdr_pa.pages_dma, -+ ring->rx_hdr_pa.pages_len, DMA_FROM_DEVICE); -+ put_page(ring->rx_hdr_pa.pages); -+ -+ ring->rx_hdr_pa.pages = NULL; -+ ring->rx_hdr_pa.pages_len = 0; -+ ring->rx_hdr_pa.pages_offset = 0; -+ ring->rx_hdr_pa.pages_dma = 0; -+ } -+ -+ if (ring->rx_buf_pa.pages) { -+ dma_unmap_page(pdata->dev, ring->rx_buf_pa.pages_dma, -+ ring->rx_buf_pa.pages_len, DMA_FROM_DEVICE); -+ put_page(ring->rx_buf_pa.pages); -+ -+ ring->rx_buf_pa.pages = NULL; -+ ring->rx_buf_pa.pages_len = 0; -+ ring->rx_buf_pa.pages_offset = 0; -+ ring->rx_buf_pa.pages_dma = 0; -+ } -+ -+ if (ring->rdesc) { -+ dma_free_coherent(pdata->dev, -+ (sizeof(struct xgbe_ring_desc) * -+ ring->rdesc_count), -+ ring->rdesc, ring->rdesc_dma); -+ ring->rdesc = NULL; -+ } -+} -+ -+static void xgbe_free_ring_resources(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ DBGPR("-->xgbe_free_ring_resources\n"); -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ xgbe_free_ring(pdata, channel->tx_ring); -+ xgbe_free_ring(pdata, channel->rx_ring); -+ } -+ -+ DBGPR("<--xgbe_free_ring_resources\n"); -+} -+ -+static int xgbe_init_ring(struct xgbe_prv_data *pdata, -+ struct xgbe_ring *ring, unsigned int rdesc_count) -+{ -+ DBGPR("-->xgbe_init_ring\n"); -+ -+ if (!ring) -+ return 0; -+ -+ /* Descriptors */ -+ ring->rdesc_count = rdesc_count; -+ ring->rdesc = dma_alloc_coherent(pdata->dev, -+ (sizeof(struct xgbe_ring_desc) * -+ rdesc_count), &ring->rdesc_dma, -+ GFP_KERNEL); -+ if (!ring->rdesc) -+ return -ENOMEM; -+ -+ /* Descriptor information */ -+ ring->rdata = kcalloc(rdesc_count, sizeof(struct xgbe_ring_data), -+ GFP_KERNEL); -+ if (!ring->rdata) -+ return -ENOMEM; -+ -+ DBGPR(" rdesc=0x%p, rdesc_dma=0x%llx, rdata=0x%p\n", -+ ring->rdesc, ring->rdesc_dma, ring->rdata); -+ -+ DBGPR("<--xgbe_init_ring\n"); -+ -+ return 0; -+} -+ -+static int xgbe_alloc_ring_resources(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ int ret; -+ -+ DBGPR("-->xgbe_alloc_ring_resources\n"); -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ DBGPR(" %s - tx_ring:\n", channel->name); -+ ret = xgbe_init_ring(pdata, channel->tx_ring, -+ pdata->tx_desc_count); -+ if (ret) { -+ netdev_alert(pdata->netdev, -+ "error initializing Tx ring\n"); -+ goto err_ring; -+ } -+ -+ DBGPR(" %s - rx_ring:\n", channel->name); -+ ret = xgbe_init_ring(pdata, channel->rx_ring, -+ pdata->rx_desc_count); -+ if (ret) { -+ netdev_alert(pdata->netdev, -+ "error initializing Tx ring\n"); -+ goto err_ring; -+ } -+ } -+ -+ DBGPR("<--xgbe_alloc_ring_resources\n"); -+ -+ return 0; -+ -+err_ring: -+ xgbe_free_ring_resources(pdata); -+ -+ return ret; -+} -+ -+static int xgbe_alloc_pages(struct xgbe_prv_data *pdata, -+ struct xgbe_page_alloc *pa, gfp_t gfp, int order) -+{ -+ struct page *pages = NULL; -+ dma_addr_t pages_dma; -+ int ret; -+ -+ /* Try to obtain pages, decreasing order if necessary */ -+ gfp |= __GFP_COLD | __GFP_COMP; -+ while (order >= 0) { -+ pages = alloc_pages(gfp, order); -+ if (pages) -+ break; -+ -+ order--; -+ } -+ if (!pages) -+ return -ENOMEM; -+ -+ /* Map the pages */ -+ pages_dma = dma_map_page(pdata->dev, pages, 0, -+ PAGE_SIZE << order, DMA_FROM_DEVICE); -+ ret = dma_mapping_error(pdata->dev, pages_dma); -+ if (ret) { -+ put_page(pages); -+ return ret; -+ } -+ -+ pa->pages = pages; -+ pa->pages_len = PAGE_SIZE << order; -+ pa->pages_offset = 0; -+ pa->pages_dma = pages_dma; -+ -+ return 0; -+} -+ -+static void xgbe_set_buffer_data(struct xgbe_buffer_data *bd, -+ struct xgbe_page_alloc *pa, -+ unsigned int len) -+{ -+ get_page(pa->pages); -+ bd->pa = *pa; -+ -+ bd->dma = pa->pages_dma + pa->pages_offset; -+ bd->dma_len = len; -+ -+ pa->pages_offset += len; -+ if ((pa->pages_offset + len) > pa->pages_len) { -+ /* This data descriptor is responsible for unmapping page(s) */ -+ bd->pa_unmap = *pa; -+ -+ /* Get a new allocation next time */ -+ pa->pages = NULL; -+ pa->pages_len = 0; -+ pa->pages_offset = 0; -+ pa->pages_dma = 0; -+ } -+} -+ -+static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata, -+ struct xgbe_ring *ring, -+ struct xgbe_ring_data *rdata) -+{ -+ int order, ret; -+ -+ if (!ring->rx_hdr_pa.pages) { -+ ret = xgbe_alloc_pages(pdata, &ring->rx_hdr_pa, GFP_ATOMIC, 0); -+ if (ret) -+ return ret; -+ } -+ -+ if (!ring->rx_buf_pa.pages) { -+ order = max_t(int, PAGE_ALLOC_COSTLY_ORDER - 1, 0); -+ ret = xgbe_alloc_pages(pdata, &ring->rx_buf_pa, GFP_ATOMIC, -+ order); -+ if (ret) -+ return ret; -+ } -+ -+ /* Set up the header page info */ -+ xgbe_set_buffer_data(&rdata->rx.hdr, &ring->rx_hdr_pa, -+ XGBE_SKB_ALLOC_SIZE); -+ -+ /* Set up the buffer page info */ -+ xgbe_set_buffer_data(&rdata->rx.buf, &ring->rx_buf_pa, -+ pdata->rx_buf_size); -+ -+ return 0; -+} -+ -+static void xgbe_wrapper_tx_descriptor_init(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ struct xgbe_channel *channel; -+ struct xgbe_ring *ring; -+ struct xgbe_ring_data *rdata; -+ struct xgbe_ring_desc *rdesc; -+ dma_addr_t rdesc_dma; -+ unsigned int i, j; -+ -+ DBGPR("-->xgbe_wrapper_tx_descriptor_init\n"); -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ ring = channel->tx_ring; -+ if (!ring) -+ break; -+ -+ rdesc = ring->rdesc; -+ rdesc_dma = ring->rdesc_dma; -+ -+ for (j = 0; j < ring->rdesc_count; j++) { -+ rdata = XGBE_GET_DESC_DATA(ring, j); -+ -+ rdata->rdesc = rdesc; -+ rdata->rdesc_dma = rdesc_dma; -+ -+ rdesc++; -+ rdesc_dma += sizeof(struct xgbe_ring_desc); -+ } -+ -+ ring->cur = 0; -+ ring->dirty = 0; -+ memset(&ring->tx, 0, sizeof(ring->tx)); -+ -+ hw_if->tx_desc_init(channel); -+ } -+ -+ DBGPR("<--xgbe_wrapper_tx_descriptor_init\n"); -+} -+ -+static void xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ struct xgbe_channel *channel; -+ struct xgbe_ring *ring; -+ struct xgbe_ring_desc *rdesc; -+ struct xgbe_ring_data *rdata; -+ dma_addr_t rdesc_dma; -+ unsigned int i, j; -+ -+ DBGPR("-->xgbe_wrapper_rx_descriptor_init\n"); -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ ring = channel->rx_ring; -+ if (!ring) -+ break; -+ -+ rdesc = ring->rdesc; -+ rdesc_dma = ring->rdesc_dma; -+ -+ for (j = 0; j < ring->rdesc_count; j++) { -+ rdata = XGBE_GET_DESC_DATA(ring, j); -+ -+ rdata->rdesc = rdesc; -+ rdata->rdesc_dma = rdesc_dma; -+ -+ if (xgbe_map_rx_buffer(pdata, ring, rdata)) -+ break; -+ -+ rdesc++; -+ rdesc_dma += sizeof(struct xgbe_ring_desc); -+ } -+ -+ ring->cur = 0; -+ ring->dirty = 0; -+ -+ hw_if->rx_desc_init(channel); -+ } -+ -+ DBGPR("<--xgbe_wrapper_rx_descriptor_init\n"); -+} -+ -+static void xgbe_unmap_rdata(struct xgbe_prv_data *pdata, -+ struct xgbe_ring_data *rdata) -+{ -+ if (rdata->skb_dma) { -+ if (rdata->mapped_as_page) { -+ dma_unmap_page(pdata->dev, rdata->skb_dma, -+ rdata->skb_dma_len, DMA_TO_DEVICE); -+ } else { -+ dma_unmap_single(pdata->dev, rdata->skb_dma, -+ rdata->skb_dma_len, DMA_TO_DEVICE); -+ } -+ rdata->skb_dma = 0; -+ rdata->skb_dma_len = 0; -+ } -+ -+ if (rdata->skb) { -+ dev_kfree_skb_any(rdata->skb); -+ rdata->skb = NULL; -+ } -+ -+ if (rdata->rx.hdr.pa.pages) -+ put_page(rdata->rx.hdr.pa.pages); -+ -+ if (rdata->rx.hdr.pa_unmap.pages) { -+ dma_unmap_page(pdata->dev, rdata->rx.hdr.pa_unmap.pages_dma, -+ rdata->rx.hdr.pa_unmap.pages_len, -+ DMA_FROM_DEVICE); -+ put_page(rdata->rx.hdr.pa_unmap.pages); -+ } -+ -+ if (rdata->rx.buf.pa.pages) -+ put_page(rdata->rx.buf.pa.pages); -+ -+ if (rdata->rx.buf.pa_unmap.pages) { -+ dma_unmap_page(pdata->dev, rdata->rx.buf.pa_unmap.pages_dma, -+ rdata->rx.buf.pa_unmap.pages_len, -+ DMA_FROM_DEVICE); -+ put_page(rdata->rx.buf.pa_unmap.pages); -+ } -+ -+ memset(&rdata->tx, 0, sizeof(rdata->tx)); -+ memset(&rdata->rx, 0, sizeof(rdata->rx)); -+ -+ rdata->mapped_as_page = 0; -+ -+ if (rdata->state_saved) { -+ rdata->state_saved = 0; -+ rdata->state.incomplete = 0; -+ rdata->state.context_next = 0; -+ rdata->state.skb = NULL; -+ rdata->state.len = 0; -+ rdata->state.error = 0; -+ } -+} -+ -+static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb) -+{ -+ struct xgbe_prv_data *pdata = channel->pdata; -+ struct xgbe_ring *ring = channel->tx_ring; -+ struct xgbe_ring_data *rdata; -+ struct xgbe_packet_data *packet; -+ struct skb_frag_struct *frag; -+ dma_addr_t skb_dma; -+ unsigned int start_index, cur_index; -+ unsigned int offset, tso, vlan, datalen, len; -+ unsigned int i; -+ -+ DBGPR("-->xgbe_map_tx_skb: cur = %d\n", ring->cur); -+ -+ offset = 0; -+ start_index = ring->cur; -+ cur_index = ring->cur; -+ -+ packet = &ring->packet_data; -+ packet->rdesc_count = 0; -+ packet->length = 0; -+ -+ tso = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, -+ TSO_ENABLE); -+ vlan = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, -+ VLAN_CTAG); -+ -+ /* Save space for a context descriptor if needed */ -+ if ((tso && (packet->mss != ring->tx.cur_mss)) || -+ (vlan && (packet->vlan_ctag != ring->tx.cur_vlan_ctag))) -+ cur_index++; -+ rdata = XGBE_GET_DESC_DATA(ring, cur_index); -+ -+ if (tso) { -+ DBGPR(" TSO packet\n"); -+ -+ /* Map the TSO header */ -+ skb_dma = dma_map_single(pdata->dev, skb->data, -+ packet->header_len, DMA_TO_DEVICE); -+ if (dma_mapping_error(pdata->dev, skb_dma)) { -+ netdev_alert(pdata->netdev, "dma_map_single failed\n"); -+ goto err_out; -+ } -+ rdata->skb_dma = skb_dma; -+ rdata->skb_dma_len = packet->header_len; -+ -+ offset = packet->header_len; -+ -+ packet->length += packet->header_len; -+ -+ cur_index++; -+ rdata = XGBE_GET_DESC_DATA(ring, cur_index); -+ } -+ -+ /* Map the (remainder of the) packet */ -+ for (datalen = skb_headlen(skb) - offset; datalen; ) { -+ len = min_t(unsigned int, datalen, XGBE_TX_MAX_BUF_SIZE); -+ -+ skb_dma = dma_map_single(pdata->dev, skb->data + offset, len, -+ DMA_TO_DEVICE); -+ if (dma_mapping_error(pdata->dev, skb_dma)) { -+ netdev_alert(pdata->netdev, "dma_map_single failed\n"); -+ goto err_out; -+ } -+ rdata->skb_dma = skb_dma; -+ rdata->skb_dma_len = len; -+ DBGPR(" skb data: index=%u, dma=0x%llx, len=%u\n", -+ cur_index, skb_dma, len); -+ -+ datalen -= len; -+ offset += len; -+ -+ packet->length += len; -+ -+ cur_index++; -+ rdata = XGBE_GET_DESC_DATA(ring, cur_index); -+ } -+ -+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { -+ DBGPR(" mapping frag %u\n", i); -+ -+ frag = &skb_shinfo(skb)->frags[i]; -+ offset = 0; -+ -+ for (datalen = skb_frag_size(frag); datalen; ) { -+ len = min_t(unsigned int, datalen, -+ XGBE_TX_MAX_BUF_SIZE); -+ -+ skb_dma = skb_frag_dma_map(pdata->dev, frag, offset, -+ len, DMA_TO_DEVICE); -+ if (dma_mapping_error(pdata->dev, skb_dma)) { -+ netdev_alert(pdata->netdev, -+ "skb_frag_dma_map failed\n"); -+ goto err_out; -+ } -+ rdata->skb_dma = skb_dma; -+ rdata->skb_dma_len = len; -+ rdata->mapped_as_page = 1; -+ DBGPR(" skb data: index=%u, dma=0x%llx, len=%u\n", -+ cur_index, skb_dma, len); -+ -+ datalen -= len; -+ offset += len; -+ -+ packet->length += len; -+ -+ cur_index++; -+ rdata = XGBE_GET_DESC_DATA(ring, cur_index); -+ } -+ } -+ -+ /* Save the skb address in the last entry. We always have some data -+ * that has been mapped so rdata is always advanced past the last -+ * piece of mapped data - use the entry pointed to by cur_index - 1. -+ */ -+ rdata = XGBE_GET_DESC_DATA(ring, cur_index - 1); -+ rdata->skb = skb; -+ -+ /* Save the number of descriptor entries used */ -+ packet->rdesc_count = cur_index - start_index; -+ -+ DBGPR("<--xgbe_map_tx_skb: count=%u\n", packet->rdesc_count); -+ -+ return packet->rdesc_count; -+ -+err_out: -+ while (start_index < cur_index) { -+ rdata = XGBE_GET_DESC_DATA(ring, start_index++); -+ xgbe_unmap_rdata(pdata, rdata); -+ } -+ -+ DBGPR("<--xgbe_map_tx_skb: count=0\n"); -+ -+ return 0; -+} -+ -+void xgbe_a0_init_function_ptrs_desc(struct xgbe_desc_if *desc_if) -+{ -+ DBGPR("-->xgbe_a0_init_function_ptrs_desc\n"); -+ -+ desc_if->alloc_ring_resources = xgbe_alloc_ring_resources; -+ desc_if->free_ring_resources = xgbe_free_ring_resources; -+ desc_if->map_tx_skb = xgbe_map_tx_skb; -+ desc_if->map_rx_buffer = xgbe_map_rx_buffer; -+ desc_if->unmap_rdata = xgbe_unmap_rdata; -+ desc_if->wrapper_tx_desc_init = xgbe_wrapper_tx_descriptor_init; -+ desc_if->wrapper_rx_desc_init = xgbe_wrapper_rx_descriptor_init; -+ -+ DBGPR("<--xgbe_a0_init_function_ptrs_desc\n"); -+} -diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-dev.c -new file mode 100644 -index 0000000..2d88739 ---- /dev/null -+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-dev.c -@@ -0,0 +1,2930 @@ -+/* -+ * AMD 10Gb Ethernet driver -+ * -+ * This file is available to you under your choice of the following two -+ * licenses: -+ * -+ * License 1: GPLv2 -+ * -+ * Copyright (c) 2014 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 . -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * -+ * License 2: Modified BSD -+ * -+ * Copyright (c) 2014 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 BE LIABLE FOR ANY -+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "xgbe.h" -+#include "xgbe-common.h" -+ -+static unsigned int xgbe_usec_to_riwt(struct xgbe_prv_data *pdata, -+ unsigned int usec) -+{ -+ unsigned long rate; -+ unsigned int ret; -+ -+ DBGPR("-->xgbe_usec_to_riwt\n"); -+ -+ rate = pdata->sysclk_rate; -+ -+ /* -+ * Convert the input usec value to the watchdog timer value. Each -+ * watchdog timer value is equivalent to 256 clock cycles. -+ * Calculate the required value as: -+ * ( usec * ( system_clock_mhz / 10^6 ) / 256 -+ */ -+ ret = (usec * (rate / 1000000)) / 256; -+ -+ DBGPR("<--xgbe_usec_to_riwt\n"); -+ -+ return ret; -+} -+ -+static unsigned int xgbe_riwt_to_usec(struct xgbe_prv_data *pdata, -+ unsigned int riwt) -+{ -+ unsigned long rate; -+ unsigned int ret; -+ -+ DBGPR("-->xgbe_riwt_to_usec\n"); -+ -+ rate = pdata->sysclk_rate; -+ -+ /* -+ * Convert the input watchdog timer value to the usec value. Each -+ * watchdog timer value is equivalent to 256 clock cycles. -+ * Calculate the required value as: -+ * ( riwt * 256 ) / ( system_clock_mhz / 10^6 ) -+ */ -+ ret = (riwt * 256) / (rate / 1000000); -+ -+ DBGPR("<--xgbe_riwt_to_usec\n"); -+ -+ return ret; -+} -+ -+static int xgbe_config_pblx8(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) -+ XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_CR, PBLX8, -+ pdata->pblx8); -+ -+ return 0; -+} -+ -+static int xgbe_get_tx_pbl_val(struct xgbe_prv_data *pdata) -+{ -+ return XGMAC_DMA_IOREAD_BITS(pdata->channel, DMA_CH_TCR, PBL); -+} -+ -+static int xgbe_config_tx_pbl_val(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->tx_ring) -+ break; -+ -+ XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, PBL, -+ pdata->tx_pbl); -+ } -+ -+ return 0; -+} -+ -+static int xgbe_get_rx_pbl_val(struct xgbe_prv_data *pdata) -+{ -+ return XGMAC_DMA_IOREAD_BITS(pdata->channel, DMA_CH_RCR, PBL); -+} -+ -+static int xgbe_config_rx_pbl_val(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->rx_ring) -+ break; -+ -+ XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, PBL, -+ pdata->rx_pbl); -+ } -+ -+ return 0; -+} -+ -+static int xgbe_config_osp_mode(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->tx_ring) -+ break; -+ -+ XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, OSP, -+ pdata->tx_osp_mode); -+ } -+ -+ return 0; -+} -+ -+static int xgbe_config_rsf_mode(struct xgbe_prv_data *pdata, unsigned int val) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < pdata->rx_q_count; i++) -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RSF, val); -+ -+ return 0; -+} -+ -+static int xgbe_config_tsf_mode(struct xgbe_prv_data *pdata, unsigned int val) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < pdata->tx_q_count; i++) -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TSF, val); -+ -+ return 0; -+} -+ -+static int xgbe_config_rx_threshold(struct xgbe_prv_data *pdata, -+ unsigned int val) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < pdata->rx_q_count; i++) -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RTC, val); -+ -+ return 0; -+} -+ -+static int xgbe_config_tx_threshold(struct xgbe_prv_data *pdata, -+ unsigned int val) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < pdata->tx_q_count; i++) -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TTC, val); -+ -+ return 0; -+} -+ -+static int xgbe_config_rx_coalesce(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->rx_ring) -+ break; -+ -+ XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RIWT, RWT, -+ pdata->rx_riwt); -+ } -+ -+ return 0; -+} -+ -+static int xgbe_config_tx_coalesce(struct xgbe_prv_data *pdata) -+{ -+ return 0; -+} -+ -+static void xgbe_config_rx_buffer_size(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->rx_ring) -+ break; -+ -+ XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, RBSZ, -+ pdata->rx_buf_size); -+ } -+} -+ -+static void xgbe_config_tso_mode(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->tx_ring) -+ break; -+ -+ XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, TSE, 1); -+ } -+} -+ -+static void xgbe_config_sph_mode(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->rx_ring) -+ break; -+ -+ XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_CR, SPH, 1); -+ } -+ -+ XGMAC_IOWRITE_BITS(pdata, MAC_RCR, HDSMS, XGBE_SPH_HDSMS_SIZE); -+} -+ -+static int xgbe_write_rss_reg(struct xgbe_prv_data *pdata, unsigned int type, -+ unsigned int index, unsigned int val) -+{ -+ unsigned int wait; -+ int ret = 0; -+ -+ mutex_lock(&pdata->rss_mutex); -+ -+ if (XGMAC_IOREAD_BITS(pdata, MAC_RSSAR, OB)) { -+ ret = -EBUSY; -+ goto unlock; -+ } -+ -+ XGMAC_IOWRITE(pdata, MAC_RSSDR, val); -+ -+ XGMAC_IOWRITE_BITS(pdata, MAC_RSSAR, RSSIA, index); -+ XGMAC_IOWRITE_BITS(pdata, MAC_RSSAR, ADDRT, type); -+ XGMAC_IOWRITE_BITS(pdata, MAC_RSSAR, CT, 0); -+ XGMAC_IOWRITE_BITS(pdata, MAC_RSSAR, OB, 1); -+ -+ wait = 1000; -+ while (wait--) { -+ if (!XGMAC_IOREAD_BITS(pdata, MAC_RSSAR, OB)) -+ goto unlock; -+ -+ usleep_range(1000, 1500); -+ } -+ -+ ret = -EBUSY; -+ -+unlock: -+ mutex_unlock(&pdata->rss_mutex); -+ -+ return ret; -+} -+ -+static int xgbe_write_rss_hash_key(struct xgbe_prv_data *pdata) -+{ -+ unsigned int key_regs = sizeof(pdata->rss_key) / sizeof(u32); -+ unsigned int *key = (unsigned int *)&pdata->rss_key; -+ int ret; -+ -+ while (key_regs--) { -+ ret = xgbe_write_rss_reg(pdata, XGBE_RSS_HASH_KEY_TYPE, -+ key_regs, *key++); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int xgbe_write_rss_lookup_table(struct xgbe_prv_data *pdata) -+{ -+ unsigned int i; -+ int ret; -+ -+ for (i = 0; i < ARRAY_SIZE(pdata->rss_table); i++) { -+ ret = xgbe_write_rss_reg(pdata, -+ XGBE_RSS_LOOKUP_TABLE_TYPE, i, -+ pdata->rss_table[i]); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int xgbe_set_rss_hash_key(struct xgbe_prv_data *pdata, const u8 *key) -+{ -+ memcpy(pdata->rss_key, key, sizeof(pdata->rss_key)); -+ -+ return xgbe_write_rss_hash_key(pdata); -+} -+ -+static int xgbe_set_rss_lookup_table(struct xgbe_prv_data *pdata, -+ const u32 *table) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(pdata->rss_table); i++) -+ XGMAC_SET_BITS(pdata->rss_table[i], MAC_RSSDR, DMCH, table[i]); -+ -+ return xgbe_write_rss_lookup_table(pdata); -+} -+ -+static int xgbe_enable_rss(struct xgbe_prv_data *pdata) -+{ -+ int ret; -+ -+ if (!pdata->hw_feat.rss) -+ return -EOPNOTSUPP; -+ -+ /* Program the hash key */ -+ ret = xgbe_write_rss_hash_key(pdata); -+ if (ret) -+ return ret; -+ -+ /* Program the lookup table */ -+ ret = xgbe_write_rss_lookup_table(pdata); -+ if (ret) -+ return ret; -+ -+ /* Set the RSS options */ -+ XGMAC_IOWRITE(pdata, MAC_RSSCR, pdata->rss_options); -+ -+ /* Enable RSS */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_RSSCR, RSSE, 1); -+ -+ return 0; -+} -+ -+static int xgbe_disable_rss(struct xgbe_prv_data *pdata) -+{ -+ if (!pdata->hw_feat.rss) -+ return -EOPNOTSUPP; -+ -+ XGMAC_IOWRITE_BITS(pdata, MAC_RSSCR, RSSE, 0); -+ -+ return 0; -+} -+ -+static void xgbe_config_rss(struct xgbe_prv_data *pdata) -+{ -+ int ret; -+ -+ if (!pdata->hw_feat.rss) -+ return; -+ -+ if (pdata->netdev->features & NETIF_F_RXHASH) -+ ret = xgbe_enable_rss(pdata); -+ else -+ ret = xgbe_disable_rss(pdata); -+ -+ if (ret) -+ netdev_err(pdata->netdev, -+ "error configuring RSS, RSS disabled\n"); -+} -+ -+static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata) -+{ -+ unsigned int max_q_count, q_count; -+ unsigned int reg, reg_val; -+ unsigned int i; -+ -+ /* Clear MTL flow control */ -+ for (i = 0; i < pdata->rx_q_count; i++) -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, 0); -+ -+ /* Clear MAC flow control */ -+ max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES; -+ q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count); -+ reg = MAC_Q0TFCR; -+ for (i = 0; i < q_count; i++) { -+ reg_val = XGMAC_IOREAD(pdata, reg); -+ XGMAC_SET_BITS(reg_val, MAC_Q0TFCR, TFE, 0); -+ XGMAC_IOWRITE(pdata, reg, reg_val); -+ -+ reg += MAC_QTFCR_INC; -+ } -+ -+ return 0; -+} -+ -+static int xgbe_enable_tx_flow_control(struct xgbe_prv_data *pdata) -+{ -+ unsigned int max_q_count, q_count; -+ unsigned int reg, reg_val; -+ unsigned int i; -+ -+ /* Set MTL flow control */ -+ for (i = 0; i < pdata->rx_q_count; i++) -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, 1); -+ -+ /* Set MAC flow control */ -+ max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES; -+ q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count); -+ reg = MAC_Q0TFCR; -+ for (i = 0; i < q_count; i++) { -+ reg_val = XGMAC_IOREAD(pdata, reg); -+ -+ /* Enable transmit flow control */ -+ XGMAC_SET_BITS(reg_val, MAC_Q0TFCR, TFE, 1); -+ /* Set pause time */ -+ XGMAC_SET_BITS(reg_val, MAC_Q0TFCR, PT, 0xffff); -+ -+ XGMAC_IOWRITE(pdata, reg, reg_val); -+ -+ reg += MAC_QTFCR_INC; -+ } -+ -+ return 0; -+} -+ -+static int xgbe_disable_rx_flow_control(struct xgbe_prv_data *pdata) -+{ -+ XGMAC_IOWRITE_BITS(pdata, MAC_RFCR, RFE, 0); -+ -+ return 0; -+} -+ -+static int xgbe_enable_rx_flow_control(struct xgbe_prv_data *pdata) -+{ -+ XGMAC_IOWRITE_BITS(pdata, MAC_RFCR, RFE, 1); -+ -+ return 0; -+} -+ -+static int xgbe_config_tx_flow_control(struct xgbe_prv_data *pdata) -+{ -+ struct ieee_pfc *pfc = pdata->pfc; -+ -+ if (pdata->tx_pause || (pfc && pfc->pfc_en)) -+ xgbe_enable_tx_flow_control(pdata); -+ else -+ xgbe_disable_tx_flow_control(pdata); -+ -+ return 0; -+} -+ -+static int xgbe_config_rx_flow_control(struct xgbe_prv_data *pdata) -+{ -+ struct ieee_pfc *pfc = pdata->pfc; -+ -+ if (pdata->rx_pause || (pfc && pfc->pfc_en)) -+ xgbe_enable_rx_flow_control(pdata); -+ else -+ xgbe_disable_rx_flow_control(pdata); -+ -+ return 0; -+} -+ -+static void xgbe_config_flow_control(struct xgbe_prv_data *pdata) -+{ -+ struct ieee_pfc *pfc = pdata->pfc; -+ -+ xgbe_config_tx_flow_control(pdata); -+ xgbe_config_rx_flow_control(pdata); -+ -+ XGMAC_IOWRITE_BITS(pdata, MAC_RFCR, PFCE, -+ (pfc && pfc->pfc_en) ? 1 : 0); -+} -+ -+static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int dma_ch_isr, dma_ch_ier; -+ unsigned int i; -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ /* Clear all the interrupts which are set */ -+ dma_ch_isr = XGMAC_DMA_IOREAD(channel, DMA_CH_SR); -+ XGMAC_DMA_IOWRITE(channel, DMA_CH_SR, dma_ch_isr); -+ -+ /* Clear all interrupt enable bits */ -+ dma_ch_ier = 0; -+ -+ /* Enable following interrupts -+ * NIE - Normal Interrupt Summary Enable -+ * AIE - Abnormal Interrupt Summary Enable -+ * FBEE - Fatal Bus Error Enable -+ */ -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, NIE, 1); -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, AIE, 1); -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, FBEE, 1); -+ -+ if (channel->tx_ring) { -+ /* Enable the following Tx interrupts -+ * TIE - Transmit Interrupt Enable (unless using -+ * per channel interrupts) -+ */ -+ if (!pdata->per_channel_irq) -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1); -+ } -+ if (channel->rx_ring) { -+ /* Enable following Rx interrupts -+ * RBUE - Receive Buffer Unavailable Enable -+ * RIE - Receive Interrupt Enable (unless using -+ * per channel interrupts) -+ */ -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1); -+ if (!pdata->per_channel_irq) -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1); -+ } -+ -+ XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier); -+ } -+} -+ -+static void xgbe_enable_mtl_interrupts(struct xgbe_prv_data *pdata) -+{ -+ unsigned int mtl_q_isr; -+ unsigned int q_count, i; -+ -+ q_count = max(pdata->hw_feat.tx_q_cnt, pdata->hw_feat.rx_q_cnt); -+ for (i = 0; i < q_count; i++) { -+ /* Clear all the interrupts which are set */ -+ mtl_q_isr = XGMAC_MTL_IOREAD(pdata, i, MTL_Q_ISR); -+ XGMAC_MTL_IOWRITE(pdata, i, MTL_Q_ISR, mtl_q_isr); -+ -+ /* No MTL interrupts to be enabled */ -+ XGMAC_MTL_IOWRITE(pdata, i, MTL_Q_IER, 0); -+ } -+} -+ -+static void xgbe_enable_mac_interrupts(struct xgbe_prv_data *pdata) -+{ -+ unsigned int mac_ier = 0; -+ -+ /* Enable Timestamp interrupt */ -+ XGMAC_SET_BITS(mac_ier, MAC_IER, TSIE, 1); -+ -+ XGMAC_IOWRITE(pdata, MAC_IER, mac_ier); -+ -+ /* Enable all counter interrupts */ -+ XGMAC_IOWRITE_BITS(pdata, MMC_RIER, ALL_INTERRUPTS, 0xffffffff); -+ XGMAC_IOWRITE_BITS(pdata, MMC_TIER, ALL_INTERRUPTS, 0xffffffff); -+} -+ -+static int xgbe_set_gmii_speed(struct xgbe_prv_data *pdata) -+{ -+ if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0x3) -+ return 0; -+ -+ XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x3); -+ -+ return 0; -+} -+ -+static int xgbe_set_gmii_2500_speed(struct xgbe_prv_data *pdata) -+{ -+ if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0x2) -+ return 0; -+ -+ XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x2); -+ -+ return 0; -+} -+ -+static int xgbe_set_xgmii_speed(struct xgbe_prv_data *pdata) -+{ -+ if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0) -+ return 0; -+ -+ XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0); -+ -+ return 0; -+} -+ -+static int xgbe_set_promiscuous_mode(struct xgbe_prv_data *pdata, -+ unsigned int enable) -+{ -+ unsigned int val = enable ? 1 : 0; -+ -+ if (XGMAC_IOREAD_BITS(pdata, MAC_PFR, PR) == val) -+ return 0; -+ -+ DBGPR(" %s promiscuous mode\n", enable ? "entering" : "leaving"); -+ XGMAC_IOWRITE_BITS(pdata, MAC_PFR, PR, val); -+ -+ return 0; -+} -+ -+static int xgbe_set_all_multicast_mode(struct xgbe_prv_data *pdata, -+ unsigned int enable) -+{ -+ unsigned int val = enable ? 1 : 0; -+ -+ if (XGMAC_IOREAD_BITS(pdata, MAC_PFR, PM) == val) -+ return 0; -+ -+ DBGPR(" %s allmulti mode\n", enable ? "entering" : "leaving"); -+ XGMAC_IOWRITE_BITS(pdata, MAC_PFR, PM, val); -+ -+ return 0; -+} -+ -+static void xgbe_set_mac_reg(struct xgbe_prv_data *pdata, -+ struct netdev_hw_addr *ha, unsigned int *mac_reg) -+{ -+ unsigned int mac_addr_hi, mac_addr_lo; -+ u8 *mac_addr; -+ -+ mac_addr_lo = 0; -+ mac_addr_hi = 0; -+ -+ if (ha) { -+ mac_addr = (u8 *)&mac_addr_lo; -+ mac_addr[0] = ha->addr[0]; -+ mac_addr[1] = ha->addr[1]; -+ mac_addr[2] = ha->addr[2]; -+ mac_addr[3] = ha->addr[3]; -+ mac_addr = (u8 *)&mac_addr_hi; -+ mac_addr[0] = ha->addr[4]; -+ mac_addr[1] = ha->addr[5]; -+ -+ DBGPR(" adding mac address %pM at 0x%04x\n", ha->addr, -+ *mac_reg); -+ -+ XGMAC_SET_BITS(mac_addr_hi, MAC_MACA1HR, AE, 1); -+ } -+ -+ XGMAC_IOWRITE(pdata, *mac_reg, mac_addr_hi); -+ *mac_reg += MAC_MACA_INC; -+ XGMAC_IOWRITE(pdata, *mac_reg, mac_addr_lo); -+ *mac_reg += MAC_MACA_INC; -+} -+ -+static void xgbe_set_mac_addn_addrs(struct xgbe_prv_data *pdata) -+{ -+ struct net_device *netdev = pdata->netdev; -+ struct netdev_hw_addr *ha; -+ unsigned int mac_reg; -+ unsigned int addn_macs; -+ -+ mac_reg = MAC_MACA1HR; -+ addn_macs = pdata->hw_feat.addn_mac; -+ -+ if (netdev_uc_count(netdev) > addn_macs) { -+ xgbe_set_promiscuous_mode(pdata, 1); -+ } else { -+ netdev_for_each_uc_addr(ha, netdev) { -+ xgbe_set_mac_reg(pdata, ha, &mac_reg); -+ addn_macs--; -+ } -+ -+ if (netdev_mc_count(netdev) > addn_macs) { -+ xgbe_set_all_multicast_mode(pdata, 1); -+ } else { -+ netdev_for_each_mc_addr(ha, netdev) { -+ xgbe_set_mac_reg(pdata, ha, &mac_reg); -+ addn_macs--; -+ } -+ } -+ } -+ -+ /* Clear remaining additional MAC address entries */ -+ while (addn_macs--) -+ xgbe_set_mac_reg(pdata, NULL, &mac_reg); -+} -+ -+static void xgbe_set_mac_hash_table(struct xgbe_prv_data *pdata) -+{ -+ struct net_device *netdev = pdata->netdev; -+ struct netdev_hw_addr *ha; -+ unsigned int hash_reg; -+ unsigned int hash_table_shift, hash_table_count; -+ u32 hash_table[XGBE_MAC_HASH_TABLE_SIZE]; -+ u32 crc; -+ unsigned int i; -+ -+ hash_table_shift = 26 - (pdata->hw_feat.hash_table_size >> 7); -+ hash_table_count = pdata->hw_feat.hash_table_size / 32; -+ memset(hash_table, 0, sizeof(hash_table)); -+ -+ /* Build the MAC Hash Table register values */ -+ netdev_for_each_uc_addr(ha, netdev) { -+ crc = bitrev32(~crc32_le(~0, ha->addr, ETH_ALEN)); -+ crc >>= hash_table_shift; -+ hash_table[crc >> 5] |= (1 << (crc & 0x1f)); -+ } -+ -+ netdev_for_each_mc_addr(ha, netdev) { -+ crc = bitrev32(~crc32_le(~0, ha->addr, ETH_ALEN)); -+ crc >>= hash_table_shift; -+ hash_table[crc >> 5] |= (1 << (crc & 0x1f)); -+ } -+ -+ /* Set the MAC Hash Table registers */ -+ hash_reg = MAC_HTR0; -+ for (i = 0; i < hash_table_count; i++) { -+ XGMAC_IOWRITE(pdata, hash_reg, hash_table[i]); -+ hash_reg += MAC_HTR_INC; -+ } -+} -+ -+static int xgbe_add_mac_addresses(struct xgbe_prv_data *pdata) -+{ -+ if (pdata->hw_feat.hash_table_size) -+ xgbe_set_mac_hash_table(pdata); -+ else -+ xgbe_set_mac_addn_addrs(pdata); -+ -+ return 0; -+} -+ -+static int xgbe_set_mac_address(struct xgbe_prv_data *pdata, u8 *addr) -+{ -+ unsigned int mac_addr_hi, mac_addr_lo; -+ -+ mac_addr_hi = (addr[5] << 8) | (addr[4] << 0); -+ mac_addr_lo = (addr[3] << 24) | (addr[2] << 16) | -+ (addr[1] << 8) | (addr[0] << 0); -+ -+ XGMAC_IOWRITE(pdata, MAC_MACA0HR, mac_addr_hi); -+ XGMAC_IOWRITE(pdata, MAC_MACA0LR, mac_addr_lo); -+ -+ return 0; -+} -+ -+static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad, -+ int mmd_reg) -+{ -+ unsigned int mmd_address; -+ 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 implementation has reversed the devices in -+ * package registers so we need to change 05 to 06 and -+ * 06 to 05 if being read (these registers are readonly -+ * so no need to do this in the write function) -+ */ -+ if ((mmd_address & 0xffff) == 0x05) -+ mmd_address = (mmd_address & ~0xffff) | 0x06; -+ else if ((mmd_address & 0xffff) == 0x06) -+ mmd_address = (mmd_address & ~0xffff) | 0x05; -+ -+ /* The PCS registers are accessed using mmio. The underlying APB3 -+ * 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 32-bit offsets and values. All -+ * register offsets must therefore be adjusted by left shifting the -+ * offset 2 bits and reading 32 bits of data. -+ */ -+ mutex_lock(&pdata->xpcs_mutex); -+ XPCS_IOWRITE(pdata, PCS_MMD_SELECT << 2, mmd_address >> 8); -+ mmd_data = XPCS_IOREAD(pdata, (mmd_address & 0xff) << 2); -+ mutex_unlock(&pdata->xpcs_mutex); -+ -+ return mmd_data; -+} -+ -+static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad, -+ int mmd_reg, int mmd_data) -+{ -+ unsigned int mmd_address; -+ -+ if (mmd_reg & MII_ADDR_C45) -+ mmd_address = mmd_reg & ~MII_ADDR_C45; -+ else -+ mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff); -+ -+ /* If the PCS is changing modes, match the MAC speed to it */ -+ if (((mmd_address >> 16) == MDIO_MMD_PCS) && -+ ((mmd_address & 0xffff) == MDIO_CTRL2)) { -+ struct phy_device *phydev = pdata->phydev; -+ -+ if (mmd_data & MDIO_PCS_CTRL2_TYPE) { -+ /* KX mode */ -+ if (phydev->supported & SUPPORTED_1000baseKX_Full) -+ xgbe_set_gmii_speed(pdata); -+ else -+ xgbe_set_gmii_2500_speed(pdata); -+ } else { -+ /* KR mode */ -+ xgbe_set_xgmii_speed(pdata); -+ } -+ } -+ -+ /* The PCS registers are accessed using mmio. The underlying APB3 -+ * 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 32-bit offsets and values. All -+ * register offsets must therefore be adjusted by left shifting the -+ * offset 2 bits and reading 32 bits of data. -+ */ -+ mutex_lock(&pdata->xpcs_mutex); -+ XPCS_IOWRITE(pdata, PCS_MMD_SELECT << 2, mmd_address >> 8); -+ XPCS_IOWRITE(pdata, (mmd_address & 0xff) << 2, mmd_data); -+ mutex_unlock(&pdata->xpcs_mutex); -+} -+ -+static int xgbe_tx_complete(struct xgbe_ring_desc *rdesc) -+{ -+ return !XGMAC_GET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN); -+} -+ -+static int xgbe_disable_rx_csum(struct xgbe_prv_data *pdata) -+{ -+ XGMAC_IOWRITE_BITS(pdata, MAC_RCR, IPC, 0); -+ -+ return 0; -+} -+ -+static int xgbe_enable_rx_csum(struct xgbe_prv_data *pdata) -+{ -+ XGMAC_IOWRITE_BITS(pdata, MAC_RCR, IPC, 1); -+ -+ return 0; -+} -+ -+static int xgbe_enable_rx_vlan_stripping(struct xgbe_prv_data *pdata) -+{ -+ /* Put the VLAN tag in the Rx descriptor */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLRXS, 1); -+ -+ /* Don't check the VLAN type */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, DOVLTC, 1); -+ -+ /* Check only C-TAG (0x8100) packets */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ERSVLM, 0); -+ -+ /* Don't consider an S-TAG (0x88A8) packet as a VLAN packet */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ESVL, 0); -+ -+ /* Enable VLAN tag stripping */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLS, 0x3); -+ -+ return 0; -+} -+ -+static int xgbe_disable_rx_vlan_stripping(struct xgbe_prv_data *pdata) -+{ -+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLS, 0); -+ -+ return 0; -+} -+ -+static int xgbe_enable_rx_vlan_filtering(struct xgbe_prv_data *pdata) -+{ -+ /* Enable VLAN filtering */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 1); -+ -+ /* Enable VLAN Hash Table filtering */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTHM, 1); -+ -+ /* Disable VLAN tag inverse matching */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTIM, 0); -+ -+ /* Only filter on the lower 12-bits of the VLAN tag */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ETV, 1); -+ -+ /* In order for the VLAN Hash Table filtering to be effective, -+ * the VLAN tag identifier in the VLAN Tag Register must not -+ * be zero. Set the VLAN tag identifier to "1" to enable the -+ * VLAN Hash Table filtering. This implies that a VLAN tag of -+ * 1 will always pass filtering. -+ */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VL, 1); -+ -+ return 0; -+} -+ -+static int xgbe_disable_rx_vlan_filtering(struct xgbe_prv_data *pdata) -+{ -+ /* Disable VLAN filtering */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 0); -+ -+ return 0; -+} -+ -+#ifndef CRCPOLY_LE -+#define CRCPOLY_LE 0xedb88320 -+#endif -+static u32 xgbe_vid_crc32_le(__le16 vid_le) -+{ -+ u32 poly = CRCPOLY_LE; -+ u32 crc = ~0; -+ u32 temp = 0; -+ unsigned char *data = (unsigned char *)&vid_le; -+ unsigned char data_byte = 0; -+ int i, bits; -+ -+ bits = get_bitmask_order(VLAN_VID_MASK); -+ for (i = 0; i < bits; i++) { -+ if ((i % 8) == 0) -+ data_byte = data[i / 8]; -+ -+ temp = ((crc & 1) ^ data_byte) & 1; -+ crc >>= 1; -+ data_byte >>= 1; -+ -+ if (temp) -+ crc ^= poly; -+ } -+ -+ return crc; -+} -+ -+static int xgbe_update_vlan_hash_table(struct xgbe_prv_data *pdata) -+{ -+ u32 crc; -+ u16 vid; -+ __le16 vid_le; -+ u16 vlan_hash_table = 0; -+ -+ /* Generate the VLAN Hash Table value */ -+ for_each_set_bit(vid, pdata->active_vlans, VLAN_N_VID) { -+ /* Get the CRC32 value of the VLAN ID */ -+ vid_le = cpu_to_le16(vid); -+ crc = bitrev32(~xgbe_vid_crc32_le(vid_le)) >> 28; -+ -+ vlan_hash_table |= (1 << crc); -+ } -+ -+ /* Set the VLAN Hash Table filtering register */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANHTR, VLHT, vlan_hash_table); -+ -+ return 0; -+} -+ -+static void xgbe_tx_desc_reset(struct xgbe_ring_data *rdata) -+{ -+ struct xgbe_ring_desc *rdesc = rdata->rdesc; -+ -+ /* Reset the Tx descriptor -+ * Set buffer 1 (lo) address to zero -+ * Set buffer 1 (hi) address to zero -+ * Reset all other control bits (IC, TTSE, B2L & B1L) -+ * Reset all other control bits (OWN, CTXT, FD, LD, CPC, CIC, etc) -+ */ -+ rdesc->desc0 = 0; -+ rdesc->desc1 = 0; -+ rdesc->desc2 = 0; -+ rdesc->desc3 = 0; -+ -+ /* Make sure ownership is written to the descriptor */ -+ wmb(); -+} -+ -+static void xgbe_tx_desc_init(struct xgbe_channel *channel) -+{ -+ struct xgbe_ring *ring = channel->tx_ring; -+ struct xgbe_ring_data *rdata; -+ int i; -+ int start_index = ring->cur; -+ -+ DBGPR("-->tx_desc_init\n"); -+ -+ /* Initialze all descriptors */ -+ for (i = 0; i < ring->rdesc_count; i++) { -+ rdata = XGBE_GET_DESC_DATA(ring, i); -+ -+ /* Initialize Tx descriptor */ -+ xgbe_tx_desc_reset(rdata); -+ } -+ -+ /* Update the total number of Tx descriptors */ -+ XGMAC_DMA_IOWRITE(channel, DMA_CH_TDRLR, ring->rdesc_count - 1); -+ -+ /* Update the starting address of descriptor ring */ -+ rdata = XGBE_GET_DESC_DATA(ring, start_index); -+ XGMAC_DMA_IOWRITE(channel, DMA_CH_TDLR_HI, -+ upper_32_bits(rdata->rdesc_dma)); -+ XGMAC_DMA_IOWRITE(channel, DMA_CH_TDLR_LO, -+ lower_32_bits(rdata->rdesc_dma)); -+ -+ DBGPR("<--tx_desc_init\n"); -+} -+ -+static void xgbe_rx_desc_reset(struct xgbe_ring_data *rdata) -+{ -+ struct xgbe_ring_desc *rdesc = rdata->rdesc; -+ -+ /* Reset the Rx descriptor -+ * Set buffer 1 (lo) address to header dma address (lo) -+ * Set buffer 1 (hi) address to header dma address (hi) -+ * Set buffer 2 (lo) address to buffer dma address (lo) -+ * Set buffer 2 (hi) address to buffer dma address (hi) and -+ * set control bits OWN and INTE -+ */ -+ rdesc->desc0 = cpu_to_le32(lower_32_bits(rdata->rx.hdr.dma)); -+ rdesc->desc1 = cpu_to_le32(upper_32_bits(rdata->rx.hdr.dma)); -+ rdesc->desc2 = cpu_to_le32(lower_32_bits(rdata->rx.buf.dma)); -+ rdesc->desc3 = cpu_to_le32(upper_32_bits(rdata->rx.buf.dma)); -+ -+ XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, INTE, -+ rdata->interrupt ? 1 : 0); -+ -+ /* Since the Rx DMA engine is likely running, make sure everything -+ * is written to the descriptor(s) before setting the OWN bit -+ * for the descriptor -+ */ -+ wmb(); -+ -+ XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, OWN, 1); -+ -+ /* Make sure ownership is written to the descriptor */ -+ wmb(); -+} -+ -+static void xgbe_rx_desc_init(struct xgbe_channel *channel) -+{ -+ struct xgbe_prv_data *pdata = channel->pdata; -+ struct xgbe_ring *ring = channel->rx_ring; -+ struct xgbe_ring_data *rdata; -+ unsigned int start_index = ring->cur; -+ unsigned int rx_coalesce, rx_frames; -+ unsigned int i; -+ -+ DBGPR("-->rx_desc_init\n"); -+ -+ rx_coalesce = (pdata->rx_riwt || pdata->rx_frames) ? 1 : 0; -+ rx_frames = pdata->rx_frames; -+ -+ /* Initialize all descriptors */ -+ for (i = 0; i < ring->rdesc_count; i++) { -+ rdata = XGBE_GET_DESC_DATA(ring, i); -+ -+ /* Set interrupt on completion bit as appropriate */ -+ if (rx_coalesce && (!rx_frames || ((i + 1) % rx_frames))) -+ rdata->interrupt = 0; -+ else -+ rdata->interrupt = 1; -+ -+ /* Initialize Rx descriptor */ -+ xgbe_rx_desc_reset(rdata); -+ } -+ -+ /* Update the total number of Rx descriptors */ -+ XGMAC_DMA_IOWRITE(channel, DMA_CH_RDRLR, ring->rdesc_count - 1); -+ -+ /* Update the starting address of descriptor ring */ -+ rdata = XGBE_GET_DESC_DATA(ring, start_index); -+ XGMAC_DMA_IOWRITE(channel, DMA_CH_RDLR_HI, -+ upper_32_bits(rdata->rdesc_dma)); -+ XGMAC_DMA_IOWRITE(channel, DMA_CH_RDLR_LO, -+ lower_32_bits(rdata->rdesc_dma)); -+ -+ /* Update the Rx Descriptor Tail Pointer */ -+ rdata = XGBE_GET_DESC_DATA(ring, start_index + ring->rdesc_count - 1); -+ XGMAC_DMA_IOWRITE(channel, DMA_CH_RDTR_LO, -+ lower_32_bits(rdata->rdesc_dma)); -+ -+ DBGPR("<--rx_desc_init\n"); -+} -+ -+static void xgbe_update_tstamp_addend(struct xgbe_prv_data *pdata, -+ unsigned int addend) -+{ -+ /* Set the addend register value and tell the device */ -+ XGMAC_IOWRITE(pdata, MAC_TSAR, addend); -+ XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSADDREG, 1); -+ -+ /* Wait for addend update to complete */ -+ while (XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSADDREG)) -+ udelay(5); -+} -+ -+static void xgbe_set_tstamp_time(struct xgbe_prv_data *pdata, unsigned int sec, -+ unsigned int nsec) -+{ -+ /* Set the time values and tell the device */ -+ XGMAC_IOWRITE(pdata, MAC_STSUR, sec); -+ XGMAC_IOWRITE(pdata, MAC_STNUR, nsec); -+ XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSINIT, 1); -+ -+ /* Wait for time update to complete */ -+ while (XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSINIT)) -+ udelay(5); -+} -+ -+static u64 xgbe_get_tstamp_time(struct xgbe_prv_data *pdata) -+{ -+ u64 nsec; -+ -+ nsec = XGMAC_IOREAD(pdata, MAC_STSR); -+ nsec *= NSEC_PER_SEC; -+ nsec += XGMAC_IOREAD(pdata, MAC_STNR); -+ -+ return nsec; -+} -+ -+static u64 xgbe_get_tx_tstamp(struct xgbe_prv_data *pdata) -+{ -+ unsigned int tx_snr; -+ u64 nsec; -+ -+ tx_snr = XGMAC_IOREAD(pdata, MAC_TXSNR); -+ if (XGMAC_GET_BITS(tx_snr, MAC_TXSNR, TXTSSTSMIS)) -+ return 0; -+ -+ nsec = XGMAC_IOREAD(pdata, MAC_TXSSR); -+ nsec *= NSEC_PER_SEC; -+ nsec += tx_snr; -+ -+ return nsec; -+} -+ -+static void xgbe_get_rx_tstamp(struct xgbe_packet_data *packet, -+ struct xgbe_ring_desc *rdesc) -+{ -+ u64 nsec; -+ -+ if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSA) && -+ !XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSD)) { -+ nsec = le32_to_cpu(rdesc->desc1); -+ nsec <<= 32; -+ nsec |= le32_to_cpu(rdesc->desc0); -+ if (nsec != 0xffffffffffffffffULL) { -+ packet->rx_tstamp = nsec; -+ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, -+ RX_TSTAMP, 1); -+ } -+ } -+} -+ -+static int xgbe_config_tstamp(struct xgbe_prv_data *pdata, -+ unsigned int mac_tscr) -+{ -+ /* Set one nano-second accuracy */ -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCTRLSSR, 1); -+ -+ /* Set fine timestamp update */ -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCFUPDT, 1); -+ -+ /* Overwrite earlier timestamps */ -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TXTSSTSM, 1); -+ -+ XGMAC_IOWRITE(pdata, MAC_TSCR, mac_tscr); -+ -+ /* Exit if timestamping is not enabled */ -+ if (!XGMAC_GET_BITS(mac_tscr, MAC_TSCR, TSENA)) -+ return 0; -+ -+ /* Initialize time registers */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SSINC, XGBE_TSTAMP_SSINC); -+ XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SNSINC, XGBE_TSTAMP_SNSINC); -+ xgbe_update_tstamp_addend(pdata, pdata->tstamp_addend); -+ xgbe_set_tstamp_time(pdata, 0, 0); -+ -+ /* Initialize the timecounter */ -+ timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, -+ ktime_to_ns(ktime_get_real())); -+ -+ return 0; -+} -+ -+static void xgbe_config_dcb_tc(struct xgbe_prv_data *pdata) -+{ -+ struct ieee_ets *ets = pdata->ets; -+ unsigned int total_weight, min_weight, weight; -+ unsigned int i; -+ -+ if (!ets) -+ return; -+ -+ /* Set Tx to deficit weighted round robin scheduling algorithm (when -+ * traffic class is using ETS algorithm) -+ */ -+ XGMAC_IOWRITE_BITS(pdata, MTL_OMR, ETSALG, MTL_ETSALG_DWRR); -+ -+ /* Set Traffic Class algorithms */ -+ total_weight = pdata->netdev->mtu * pdata->hw_feat.tc_cnt; -+ min_weight = total_weight / 100; -+ if (!min_weight) -+ min_weight = 1; -+ -+ for (i = 0; i < pdata->hw_feat.tc_cnt; i++) { -+ switch (ets->tc_tsa[i]) { -+ case IEEE_8021QAZ_TSA_STRICT: -+ DBGPR(" TC%u using SP\n", i); -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA, -+ MTL_TSA_SP); -+ break; -+ case IEEE_8021QAZ_TSA_ETS: -+ weight = total_weight * ets->tc_tx_bw[i] / 100; -+ weight = clamp(weight, min_weight, total_weight); -+ -+ DBGPR(" TC%u using DWRR (weight %u)\n", i, weight); -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA, -+ MTL_TSA_ETS); -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_QWR, QW, -+ weight); -+ break; -+ } -+ } -+} -+ -+static void xgbe_config_dcb_pfc(struct xgbe_prv_data *pdata) -+{ -+ struct ieee_pfc *pfc = pdata->pfc; -+ struct ieee_ets *ets = pdata->ets; -+ unsigned int mask, reg, reg_val; -+ unsigned int tc, prio; -+ -+ if (!pfc || !ets) -+ return; -+ -+ for (tc = 0; tc < pdata->hw_feat.tc_cnt; tc++) { -+ mask = 0; -+ for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) { -+ if ((pfc->pfc_en & (1 << prio)) && -+ (ets->prio_tc[prio] == tc)) -+ mask |= (1 << prio); -+ } -+ mask &= 0xff; -+ -+ DBGPR(" TC%u PFC mask=%#x\n", tc, mask); -+ reg = MTL_TCPM0R + (MTL_TCPM_INC * (tc / MTL_TCPM_TC_PER_REG)); -+ reg_val = XGMAC_IOREAD(pdata, reg); -+ -+ reg_val &= ~(0xff << ((tc % MTL_TCPM_TC_PER_REG) << 3)); -+ reg_val |= (mask << ((tc % MTL_TCPM_TC_PER_REG) << 3)); -+ -+ XGMAC_IOWRITE(pdata, reg, reg_val); -+ } -+ -+ xgbe_config_flow_control(pdata); -+} -+ -+static void xgbe_tx_start_xmit(struct xgbe_channel *channel, -+ struct xgbe_ring *ring) -+{ -+ struct xgbe_prv_data *pdata = channel->pdata; -+ struct xgbe_ring_data *rdata; -+ -+ /* Issue a poll command to Tx DMA by writing address -+ * of next immediate free descriptor */ -+ rdata = XGBE_GET_DESC_DATA(ring, ring->cur); -+ XGMAC_DMA_IOWRITE(channel, DMA_CH_TDTR_LO, -+ lower_32_bits(rdata->rdesc_dma)); -+ -+ /* Start the Tx coalescing timer */ -+ if (pdata->tx_usecs && !channel->tx_timer_active) { -+ channel->tx_timer_active = 1; -+ hrtimer_start(&channel->tx_timer, -+ ktime_set(0, pdata->tx_usecs * NSEC_PER_USEC), -+ HRTIMER_MODE_REL); -+ } -+ -+ ring->tx.xmit_more = 0; -+} -+ -+static void xgbe_dev_xmit(struct xgbe_channel *channel) -+{ -+ struct xgbe_prv_data *pdata = channel->pdata; -+ struct xgbe_ring *ring = channel->tx_ring; -+ struct xgbe_ring_data *rdata; -+ struct xgbe_ring_desc *rdesc; -+ struct xgbe_packet_data *packet = &ring->packet_data; -+ unsigned int csum, tso, vlan; -+ unsigned int tso_context, vlan_context; -+ unsigned int tx_set_ic; -+ int start_index = ring->cur; -+ int cur_index = ring->cur; -+ int i; -+ -+ DBGPR("-->xgbe_dev_xmit\n"); -+ -+ csum = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, -+ CSUM_ENABLE); -+ tso = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, -+ TSO_ENABLE); -+ vlan = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, -+ VLAN_CTAG); -+ -+ if (tso && (packet->mss != ring->tx.cur_mss)) -+ tso_context = 1; -+ else -+ tso_context = 0; -+ -+ if (vlan && (packet->vlan_ctag != ring->tx.cur_vlan_ctag)) -+ vlan_context = 1; -+ else -+ vlan_context = 0; -+ -+ /* Determine if an interrupt should be generated for this Tx: -+ * Interrupt: -+ * - Tx frame count exceeds the frame count setting -+ * - Addition of Tx frame count to the frame count since the -+ * last interrupt was set exceeds the frame count setting -+ * No interrupt: -+ * - No frame count setting specified (ethtool -C ethX tx-frames 0) -+ * - Addition of Tx frame count to the frame count since the -+ * last interrupt was set does not exceed the frame count setting -+ */ -+ ring->coalesce_count += packet->tx_packets; -+ if (!pdata->tx_frames) -+ tx_set_ic = 0; -+ else if (packet->tx_packets > pdata->tx_frames) -+ tx_set_ic = 1; -+ else if ((ring->coalesce_count % pdata->tx_frames) < -+ packet->tx_packets) -+ tx_set_ic = 1; -+ else -+ tx_set_ic = 0; -+ -+ rdata = XGBE_GET_DESC_DATA(ring, cur_index); -+ rdesc = rdata->rdesc; -+ -+ /* Create a context descriptor if this is a TSO packet */ -+ if (tso_context || vlan_context) { -+ if (tso_context) { -+ DBGPR(" TSO context descriptor, mss=%u\n", -+ packet->mss); -+ -+ /* Set the MSS size */ -+ XGMAC_SET_BITS_LE(rdesc->desc2, TX_CONTEXT_DESC2, -+ MSS, packet->mss); -+ -+ /* Mark it as a CONTEXT descriptor */ -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_CONTEXT_DESC3, -+ CTXT, 1); -+ -+ /* Indicate this descriptor contains the MSS */ -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_CONTEXT_DESC3, -+ TCMSSV, 1); -+ -+ ring->tx.cur_mss = packet->mss; -+ } -+ -+ if (vlan_context) { -+ DBGPR(" VLAN context descriptor, ctag=%u\n", -+ packet->vlan_ctag); -+ -+ /* Mark it as a CONTEXT descriptor */ -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_CONTEXT_DESC3, -+ CTXT, 1); -+ -+ /* Set the VLAN tag */ -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_CONTEXT_DESC3, -+ VT, packet->vlan_ctag); -+ -+ /* Indicate this descriptor contains the VLAN tag */ -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_CONTEXT_DESC3, -+ VLTV, 1); -+ -+ ring->tx.cur_vlan_ctag = packet->vlan_ctag; -+ } -+ -+ cur_index++; -+ rdata = XGBE_GET_DESC_DATA(ring, cur_index); -+ rdesc = rdata->rdesc; -+ } -+ -+ /* Update buffer address (for TSO this is the header) */ -+ rdesc->desc0 = cpu_to_le32(lower_32_bits(rdata->skb_dma)); -+ rdesc->desc1 = cpu_to_le32(upper_32_bits(rdata->skb_dma)); -+ -+ /* Update the buffer length */ -+ XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, HL_B1L, -+ rdata->skb_dma_len); -+ -+ /* VLAN tag insertion check */ -+ if (vlan) -+ XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, VTIR, -+ TX_NORMAL_DESC2_VLAN_INSERT); -+ -+ /* Timestamp enablement check */ -+ if (XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP)) -+ XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, TTSE, 1); -+ -+ /* Mark it as First Descriptor */ -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, FD, 1); -+ -+ /* Mark it as a NORMAL descriptor */ -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, CTXT, 0); -+ -+ /* Set OWN bit if not the first descriptor */ -+ if (cur_index != start_index) -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN, 1); -+ -+ if (tso) { -+ /* Enable TSO */ -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, TSE, 1); -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, TCPPL, -+ packet->tcp_payload_len); -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, TCPHDRLEN, -+ packet->tcp_header_len / 4); -+ } else { -+ /* Enable CRC and Pad Insertion */ -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, CPC, 0); -+ -+ /* Enable HW CSUM */ -+ if (csum) -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, -+ CIC, 0x3); -+ -+ /* Set the total length to be transmitted */ -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, FL, -+ packet->length); -+ } -+ -+ for (i = cur_index - start_index + 1; i < packet->rdesc_count; i++) { -+ cur_index++; -+ rdata = XGBE_GET_DESC_DATA(ring, cur_index); -+ rdesc = rdata->rdesc; -+ -+ /* Update buffer address */ -+ rdesc->desc0 = cpu_to_le32(lower_32_bits(rdata->skb_dma)); -+ rdesc->desc1 = cpu_to_le32(upper_32_bits(rdata->skb_dma)); -+ -+ /* Update the buffer length */ -+ XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, HL_B1L, -+ rdata->skb_dma_len); -+ -+ /* Set OWN bit */ -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN, 1); -+ -+ /* Mark it as NORMAL descriptor */ -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, CTXT, 0); -+ -+ /* Enable HW CSUM */ -+ if (csum) -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, -+ CIC, 0x3); -+ } -+ -+ /* Set LAST bit for the last descriptor */ -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, LD, 1); -+ -+ /* Set IC bit based on Tx coalescing settings */ -+ if (tx_set_ic) -+ XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1); -+ -+ /* Save the Tx info to report back during cleanup */ -+ rdata->tx.packets = packet->tx_packets; -+ rdata->tx.bytes = packet->tx_bytes; -+ -+ /* In case the Tx DMA engine is running, make sure everything -+ * is written to the descriptor(s) before setting the OWN bit -+ * for the first descriptor -+ */ -+ wmb(); -+ -+ /* Set OWN bit for the first descriptor */ -+ rdata = XGBE_GET_DESC_DATA(ring, start_index); -+ rdesc = rdata->rdesc; -+ XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN, 1); -+ -+#ifdef XGMAC_ENABLE_TX_DESC_DUMP -+ xgbe_a0_dump_tx_desc(ring, start_index, packet->rdesc_count, 1); -+#endif -+ -+ /* Make sure ownership is written to the descriptor */ -+ wmb(); -+ -+ ring->cur = cur_index + 1; -+ if (!packet->skb->xmit_more || -+ netif_xmit_stopped(netdev_get_tx_queue(pdata->netdev, -+ channel->queue_index))) -+ xgbe_tx_start_xmit(channel, ring); -+ else -+ ring->tx.xmit_more = 1; -+ -+ DBGPR(" %s: descriptors %u to %u written\n", -+ channel->name, start_index & (ring->rdesc_count - 1), -+ (ring->cur - 1) & (ring->rdesc_count - 1)); -+ -+ DBGPR("<--xgbe_dev_xmit\n"); -+} -+ -+static int xgbe_dev_read(struct xgbe_channel *channel) -+{ -+ struct xgbe_ring *ring = channel->rx_ring; -+ struct xgbe_ring_data *rdata; -+ struct xgbe_ring_desc *rdesc; -+ struct xgbe_packet_data *packet = &ring->packet_data; -+ struct net_device *netdev = channel->pdata->netdev; -+ unsigned int err, etlt, l34t; -+ -+ DBGPR("-->xgbe_dev_read: cur = %d\n", ring->cur); -+ -+ rdata = XGBE_GET_DESC_DATA(ring, ring->cur); -+ rdesc = rdata->rdesc; -+ -+ /* Check for data availability */ -+ if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, OWN)) -+ return 1; -+ -+ /* Make sure descriptor fields are read after reading the OWN bit */ -+ rmb(); -+ -+#ifdef XGMAC_ENABLE_RX_DESC_DUMP -+ xgbe_a0_dump_rx_desc(ring, rdesc, ring->cur); -+#endif -+ -+ if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, CTXT)) { -+ /* Timestamp Context Descriptor */ -+ xgbe_get_rx_tstamp(packet, rdesc); -+ -+ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, -+ CONTEXT, 1); -+ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, -+ CONTEXT_NEXT, 0); -+ return 0; -+ } -+ -+ /* Normal Descriptor, be sure Context Descriptor bit is off */ -+ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, CONTEXT, 0); -+ -+ /* Indicate if a Context Descriptor is next */ -+ if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, CDA)) -+ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, -+ CONTEXT_NEXT, 1); -+ -+ /* Get the header length */ -+ if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, FD)) -+ rdata->rx.hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2, -+ RX_NORMAL_DESC2, HL); -+ -+ /* Get the RSS hash */ -+ if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, RSV)) { -+ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, -+ RSS_HASH, 1); -+ -+ packet->rss_hash = le32_to_cpu(rdesc->desc1); -+ -+ l34t = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, L34T); -+ switch (l34t) { -+ case RX_DESC3_L34T_IPV4_TCP: -+ case RX_DESC3_L34T_IPV4_UDP: -+ case RX_DESC3_L34T_IPV6_TCP: -+ case RX_DESC3_L34T_IPV6_UDP: -+ packet->rss_hash_type = PKT_HASH_TYPE_L4; -+ break; -+ default: -+ packet->rss_hash_type = PKT_HASH_TYPE_L3; -+ } -+ } -+ -+ /* Get the packet length */ -+ rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL); -+ -+ if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) { -+ /* Not all the data has been transferred for this packet */ -+ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, -+ INCOMPLETE, 1); -+ return 0; -+ } -+ -+ /* This is the last of the data for this packet */ -+ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, -+ INCOMPLETE, 0); -+ -+ /* Set checksum done indicator as appropriate */ -+ if (channel->pdata->netdev->features & NETIF_F_RXCSUM) -+ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, -+ CSUM_DONE, 1); -+ -+ /* Check for errors (only valid in last descriptor) */ -+ err = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, ES); -+ etlt = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, ETLT); -+ DBGPR(" err=%u, etlt=%#x\n", err, etlt); -+ -+ if (!err || !etlt) { -+ /* No error if err is 0 or etlt is 0 */ -+ if ((etlt == 0x09) && -+ (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) { -+ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, -+ VLAN_CTAG, 1); -+ packet->vlan_ctag = XGMAC_GET_BITS_LE(rdesc->desc0, -+ RX_NORMAL_DESC0, -+ OVT); -+ DBGPR(" vlan-ctag=0x%04x\n", packet->vlan_ctag); -+ } -+ } else { -+ if ((etlt == 0x05) || (etlt == 0x06)) -+ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, -+ CSUM_DONE, 0); -+ else -+ XGMAC_SET_BITS(packet->errors, RX_PACKET_ERRORS, -+ FRAME, 1); -+ } -+ -+ DBGPR("<--xgbe_dev_read: %s - descriptor=%u (cur=%d)\n", channel->name, -+ ring->cur & (ring->rdesc_count - 1), ring->cur); -+ -+ return 0; -+} -+ -+static int xgbe_is_context_desc(struct xgbe_ring_desc *rdesc) -+{ -+ /* Rx and Tx share CTXT bit, so check TDES3.CTXT bit */ -+ return XGMAC_GET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, CTXT); -+} -+ -+static int xgbe_is_last_desc(struct xgbe_ring_desc *rdesc) -+{ -+ /* Rx and Tx share LD bit, so check TDES3.LD bit */ -+ return XGMAC_GET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, LD); -+} -+ -+static int xgbe_enable_int(struct xgbe_channel *channel, -+ enum xgbe_int int_id) -+{ -+ unsigned int dma_ch_ier; -+ -+ dma_ch_ier = XGMAC_DMA_IOREAD(channel, DMA_CH_IER); -+ -+ switch (int_id) { -+ case XGMAC_INT_DMA_CH_SR_TI: -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1); -+ break; -+ case XGMAC_INT_DMA_CH_SR_TPS: -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TXSE, 1); -+ break; -+ case XGMAC_INT_DMA_CH_SR_TBU: -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TBUE, 1); -+ break; -+ case XGMAC_INT_DMA_CH_SR_RI: -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1); -+ break; -+ case XGMAC_INT_DMA_CH_SR_RBU: -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1); -+ break; -+ case XGMAC_INT_DMA_CH_SR_RPS: -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RSE, 1); -+ break; -+ case XGMAC_INT_DMA_CH_SR_TI_RI: -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1); -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1); -+ break; -+ case XGMAC_INT_DMA_CH_SR_FBE: -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, FBEE, 1); -+ break; -+ case XGMAC_INT_DMA_ALL: -+ dma_ch_ier |= channel->saved_ier; -+ break; -+ default: -+ return -1; -+ } -+ -+ XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier); -+ -+ return 0; -+} -+ -+static int xgbe_disable_int(struct xgbe_channel *channel, -+ enum xgbe_int int_id) -+{ -+ unsigned int dma_ch_ier; -+ -+ dma_ch_ier = XGMAC_DMA_IOREAD(channel, DMA_CH_IER); -+ -+ switch (int_id) { -+ case XGMAC_INT_DMA_CH_SR_TI: -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 0); -+ break; -+ case XGMAC_INT_DMA_CH_SR_TPS: -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TXSE, 0); -+ break; -+ case XGMAC_INT_DMA_CH_SR_TBU: -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TBUE, 0); -+ break; -+ case XGMAC_INT_DMA_CH_SR_RI: -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 0); -+ break; -+ case XGMAC_INT_DMA_CH_SR_RBU: -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 0); -+ break; -+ case XGMAC_INT_DMA_CH_SR_RPS: -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RSE, 0); -+ break; -+ case XGMAC_INT_DMA_CH_SR_TI_RI: -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 0); -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 0); -+ break; -+ case XGMAC_INT_DMA_CH_SR_FBE: -+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, FBEE, 0); -+ break; -+ case XGMAC_INT_DMA_ALL: -+ channel->saved_ier = dma_ch_ier & XGBE_DMA_INTERRUPT_MASK; -+ dma_ch_ier &= ~XGBE_DMA_INTERRUPT_MASK; -+ break; -+ default: -+ return -1; -+ } -+ -+ XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier); -+ -+ return 0; -+} -+ -+static int xgbe_exit(struct xgbe_prv_data *pdata) -+{ -+ unsigned int count = 2000; -+ -+ DBGPR("-->xgbe_exit\n"); -+ -+ /* Issue a software reset */ -+ XGMAC_IOWRITE_BITS(pdata, DMA_MR, SWR, 1); -+ usleep_range(10, 15); -+ -+ /* Poll Until Poll Condition */ -+ while (count-- && XGMAC_IOREAD_BITS(pdata, DMA_MR, SWR)) -+ usleep_range(500, 600); -+ -+ if (!count) -+ return -EBUSY; -+ -+ DBGPR("<--xgbe_exit\n"); -+ -+ return 0; -+} -+ -+static int xgbe_flush_tx_queues(struct xgbe_prv_data *pdata) -+{ -+ unsigned int i, count; -+ -+ if (XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER) < 0x21) -+ return 0; -+ -+ for (i = 0; i < pdata->tx_q_count; i++) -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, FTQ, 1); -+ -+ /* Poll Until Poll Condition */ -+ for (i = 0; i < pdata->tx_q_count; i++) { -+ count = 2000; -+ while (count-- && XGMAC_MTL_IOREAD_BITS(pdata, i, -+ MTL_Q_TQOMR, FTQ)) -+ usleep_range(500, 600); -+ -+ if (!count) -+ return -EBUSY; -+ } -+ -+ return 0; -+} -+ -+static void xgbe_config_dma_bus(struct xgbe_prv_data *pdata) -+{ -+ /* Set enhanced addressing mode */ -+ XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, EAME, 1); -+ -+ /* Set the System Bus mode */ -+ XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, UNDEF, 1); -+ XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, BLEN_256, 1); -+} -+ -+static void xgbe_config_dma_cache(struct xgbe_prv_data *pdata) -+{ -+ unsigned int arcache, awcache; -+ -+ arcache = 0; -+ XGMAC_SET_BITS(arcache, DMA_AXIARCR, DRC, pdata->arcache); -+ XGMAC_SET_BITS(arcache, DMA_AXIARCR, DRD, pdata->axdomain); -+ XGMAC_SET_BITS(arcache, DMA_AXIARCR, TEC, pdata->arcache); -+ XGMAC_SET_BITS(arcache, DMA_AXIARCR, TED, pdata->axdomain); -+ XGMAC_SET_BITS(arcache, DMA_AXIARCR, THC, pdata->arcache); -+ XGMAC_SET_BITS(arcache, DMA_AXIARCR, THD, pdata->axdomain); -+ XGMAC_IOWRITE(pdata, DMA_AXIARCR, arcache); -+ -+ awcache = 0; -+ XGMAC_SET_BITS(awcache, DMA_AXIAWCR, DWC, pdata->awcache); -+ XGMAC_SET_BITS(awcache, DMA_AXIAWCR, DWD, pdata->axdomain); -+ XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPC, pdata->awcache); -+ XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPD, pdata->axdomain); -+ XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHC, pdata->awcache); -+ XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHD, pdata->axdomain); -+ XGMAC_SET_BITS(awcache, DMA_AXIAWCR, TDC, pdata->awcache); -+ XGMAC_SET_BITS(awcache, DMA_AXIAWCR, TDD, pdata->axdomain); -+ XGMAC_IOWRITE(pdata, DMA_AXIAWCR, awcache); -+} -+ -+static void xgbe_config_mtl_mode(struct xgbe_prv_data *pdata) -+{ -+ unsigned int i; -+ -+ /* Set Tx to weighted round robin scheduling algorithm */ -+ XGMAC_IOWRITE_BITS(pdata, MTL_OMR, ETSALG, MTL_ETSALG_WRR); -+ -+ /* Set Tx traffic classes to use WRR algorithm with equal weights */ -+ for (i = 0; i < pdata->hw_feat.tc_cnt; i++) { -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA, -+ MTL_TSA_ETS); -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_QWR, QW, 1); -+ } -+ -+ /* Set Rx to strict priority algorithm */ -+ XGMAC_IOWRITE_BITS(pdata, MTL_OMR, RAA, MTL_RAA_SP); -+} -+ -+static unsigned int xgbe_calculate_per_queue_fifo(unsigned int fifo_size, -+ unsigned int queue_count) -+{ -+ unsigned int q_fifo_size = 0; -+ enum xgbe_mtl_fifo_size p_fifo = XGMAC_MTL_FIFO_SIZE_256; -+ -+ /* Calculate Tx/Rx fifo share per queue */ -+ switch (fifo_size) { -+ case 0: -+ q_fifo_size = XGBE_FIFO_SIZE_B(128); -+ break; -+ case 1: -+ q_fifo_size = XGBE_FIFO_SIZE_B(256); -+ break; -+ case 2: -+ q_fifo_size = XGBE_FIFO_SIZE_B(512); -+ break; -+ case 3: -+ q_fifo_size = XGBE_FIFO_SIZE_KB(1); -+ break; -+ case 4: -+ q_fifo_size = XGBE_FIFO_SIZE_KB(2); -+ break; -+ case 5: -+ q_fifo_size = XGBE_FIFO_SIZE_KB(4); -+ break; -+ case 6: -+ q_fifo_size = XGBE_FIFO_SIZE_KB(8); -+ break; -+ case 7: -+ q_fifo_size = XGBE_FIFO_SIZE_KB(16); -+ break; -+ case 8: -+ q_fifo_size = XGBE_FIFO_SIZE_KB(32); -+ break; -+ case 9: -+ q_fifo_size = XGBE_FIFO_SIZE_KB(64); -+ break; -+ case 10: -+ q_fifo_size = XGBE_FIFO_SIZE_KB(128); -+ break; -+ case 11: -+ q_fifo_size = XGBE_FIFO_SIZE_KB(256); -+ break; -+ } -+ -+ /* The configured value is not the actual amount of fifo RAM */ -+ q_fifo_size = min_t(unsigned int, XGBE_FIFO_MAX, q_fifo_size); -+ -+ q_fifo_size = q_fifo_size / queue_count; -+ -+ /* Set the queue fifo size programmable value */ -+ if (q_fifo_size >= XGBE_FIFO_SIZE_KB(256)) -+ p_fifo = XGMAC_MTL_FIFO_SIZE_256K; -+ else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(128)) -+ p_fifo = XGMAC_MTL_FIFO_SIZE_128K; -+ else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(64)) -+ p_fifo = XGMAC_MTL_FIFO_SIZE_64K; -+ else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(32)) -+ p_fifo = XGMAC_MTL_FIFO_SIZE_32K; -+ else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(16)) -+ p_fifo = XGMAC_MTL_FIFO_SIZE_16K; -+ else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(8)) -+ p_fifo = XGMAC_MTL_FIFO_SIZE_8K; -+ else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(4)) -+ p_fifo = XGMAC_MTL_FIFO_SIZE_4K; -+ else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(2)) -+ p_fifo = XGMAC_MTL_FIFO_SIZE_2K; -+ else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(1)) -+ p_fifo = XGMAC_MTL_FIFO_SIZE_1K; -+ else if (q_fifo_size >= XGBE_FIFO_SIZE_B(512)) -+ p_fifo = XGMAC_MTL_FIFO_SIZE_512; -+ else if (q_fifo_size >= XGBE_FIFO_SIZE_B(256)) -+ p_fifo = XGMAC_MTL_FIFO_SIZE_256; -+ -+ return p_fifo; -+} -+ -+static void xgbe_config_tx_fifo_size(struct xgbe_prv_data *pdata) -+{ -+ enum xgbe_mtl_fifo_size fifo_size; -+ unsigned int i; -+ -+ fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.tx_fifo_size, -+ pdata->tx_q_count); -+ -+ for (i = 0; i < pdata->tx_q_count; i++) -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TQS, fifo_size); -+ -+ netdev_notice(pdata->netdev, "%d Tx queues, %d byte fifo per queue\n", -+ pdata->tx_q_count, ((fifo_size + 1) * 256)); -+} -+ -+static void xgbe_config_rx_fifo_size(struct xgbe_prv_data *pdata) -+{ -+ enum xgbe_mtl_fifo_size fifo_size; -+ unsigned int i; -+ -+ fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.rx_fifo_size, -+ pdata->rx_q_count); -+ -+ for (i = 0; i < pdata->rx_q_count; i++) -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RQS, fifo_size); -+ -+ netdev_notice(pdata->netdev, "%d Rx queues, %d byte fifo per queue\n", -+ pdata->rx_q_count, ((fifo_size + 1) * 256)); -+} -+ -+static void xgbe_config_queue_mapping(struct xgbe_prv_data *pdata) -+{ -+ unsigned int qptc, qptc_extra, queue; -+ unsigned int prio_queues; -+ unsigned int ppq, ppq_extra, prio; -+ unsigned int mask; -+ unsigned int i, j, reg, reg_val; -+ -+ /* Map the MTL Tx Queues to Traffic Classes -+ * Note: Tx Queues >= Traffic Classes -+ */ -+ qptc = pdata->tx_q_count / pdata->hw_feat.tc_cnt; -+ qptc_extra = pdata->tx_q_count % pdata->hw_feat.tc_cnt; -+ -+ for (i = 0, queue = 0; i < pdata->hw_feat.tc_cnt; i++) { -+ for (j = 0; j < qptc; j++) { -+ DBGPR(" TXq%u mapped to TC%u\n", queue, i); -+ XGMAC_MTL_IOWRITE_BITS(pdata, queue, MTL_Q_TQOMR, -+ Q2TCMAP, i); -+ pdata->q2tc_map[queue++] = i; -+ } -+ -+ if (i < qptc_extra) { -+ DBGPR(" TXq%u mapped to TC%u\n", queue, i); -+ XGMAC_MTL_IOWRITE_BITS(pdata, queue, MTL_Q_TQOMR, -+ Q2TCMAP, i); -+ pdata->q2tc_map[queue++] = i; -+ } -+ } -+ -+ /* Map the 8 VLAN priority values to available MTL Rx queues */ -+ prio_queues = min_t(unsigned int, IEEE_8021QAZ_MAX_TCS, -+ pdata->rx_q_count); -+ ppq = IEEE_8021QAZ_MAX_TCS / prio_queues; -+ ppq_extra = IEEE_8021QAZ_MAX_TCS % prio_queues; -+ -+ reg = MAC_RQC2R; -+ reg_val = 0; -+ for (i = 0, prio = 0; i < prio_queues;) { -+ mask = 0; -+ for (j = 0; j < ppq; j++) { -+ DBGPR(" PRIO%u mapped to RXq%u\n", prio, i); -+ mask |= (1 << prio); -+ pdata->prio2q_map[prio++] = i; -+ } -+ -+ if (i < ppq_extra) { -+ DBGPR(" PRIO%u mapped to RXq%u\n", prio, i); -+ mask |= (1 << prio); -+ pdata->prio2q_map[prio++] = i; -+ } -+ -+ reg_val |= (mask << ((i++ % MAC_RQC2_Q_PER_REG) << 3)); -+ -+ if ((i % MAC_RQC2_Q_PER_REG) && (i != prio_queues)) -+ continue; -+ -+ XGMAC_IOWRITE(pdata, reg, reg_val); -+ reg += MAC_RQC2_INC; -+ reg_val = 0; -+ } -+ -+ /* Select dynamic mapping of MTL Rx queue to DMA Rx channel */ -+ reg = MTL_RQDCM0R; -+ reg_val = 0; -+ for (i = 0; i < pdata->rx_q_count;) { -+ reg_val |= (0x80 << ((i++ % MTL_RQDCM_Q_PER_REG) << 3)); -+ -+ if ((i % MTL_RQDCM_Q_PER_REG) && (i != pdata->rx_q_count)) -+ continue; -+ -+ XGMAC_IOWRITE(pdata, reg, reg_val); -+ -+ reg += MTL_RQDCM_INC; -+ reg_val = 0; -+ } -+} -+ -+static void xgbe_config_flow_control_threshold(struct xgbe_prv_data *pdata) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < pdata->rx_q_count; i++) { -+ /* Activate flow control when less than 4k left in fifo */ -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RFA, 2); -+ -+ /* De-activate flow control when more than 6k left in fifo */ -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RFD, 4); -+ } -+} -+ -+static void xgbe_config_mac_address(struct xgbe_prv_data *pdata) -+{ -+ xgbe_set_mac_address(pdata, pdata->netdev->dev_addr); -+ -+ /* Filtering is done using perfect filtering and hash filtering */ -+ if (pdata->hw_feat.hash_table_size) { -+ XGMAC_IOWRITE_BITS(pdata, MAC_PFR, HPF, 1); -+ XGMAC_IOWRITE_BITS(pdata, MAC_PFR, HUC, 1); -+ XGMAC_IOWRITE_BITS(pdata, MAC_PFR, HMC, 1); -+ } -+} -+ -+static void xgbe_config_jumbo_enable(struct xgbe_prv_data *pdata) -+{ -+ unsigned int val; -+ -+ val = (pdata->netdev->mtu > XGMAC_STD_PACKET_MTU) ? 1 : 0; -+ -+ XGMAC_IOWRITE_BITS(pdata, MAC_RCR, JE, val); -+} -+ -+static void xgbe_config_mac_speed(struct xgbe_prv_data *pdata) -+{ -+ switch (pdata->phy_speed) { -+ case SPEED_10000: -+ xgbe_set_xgmii_speed(pdata); -+ break; -+ -+ case SPEED_2500: -+ xgbe_set_gmii_2500_speed(pdata); -+ break; -+ -+ case SPEED_1000: -+ xgbe_set_gmii_speed(pdata); -+ break; -+ } -+} -+ -+static void xgbe_config_checksum_offload(struct xgbe_prv_data *pdata) -+{ -+ if (pdata->netdev->features & NETIF_F_RXCSUM) -+ xgbe_enable_rx_csum(pdata); -+ else -+ xgbe_disable_rx_csum(pdata); -+} -+ -+static void xgbe_config_vlan_support(struct xgbe_prv_data *pdata) -+{ -+ /* Indicate that VLAN Tx CTAGs come from context descriptors */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANIR, CSVL, 0); -+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANIR, VLTI, 1); -+ -+ /* Set the current VLAN Hash Table register value */ -+ xgbe_update_vlan_hash_table(pdata); -+ -+ if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER) -+ xgbe_enable_rx_vlan_filtering(pdata); -+ else -+ xgbe_disable_rx_vlan_filtering(pdata); -+ -+ if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) -+ xgbe_enable_rx_vlan_stripping(pdata); -+ else -+ xgbe_disable_rx_vlan_stripping(pdata); -+} -+ -+static u64 xgbe_mmc_read(struct xgbe_prv_data *pdata, unsigned int reg_lo) -+{ -+ bool read_hi; -+ u64 val; -+ -+ switch (reg_lo) { -+ /* These registers are always 64 bit */ -+ case MMC_TXOCTETCOUNT_GB_LO: -+ case MMC_TXOCTETCOUNT_G_LO: -+ case MMC_RXOCTETCOUNT_GB_LO: -+ case MMC_RXOCTETCOUNT_G_LO: -+ read_hi = true; -+ break; -+ -+ default: -+ read_hi = false; -+ }; -+ -+ val = XGMAC_IOREAD(pdata, reg_lo); -+ -+ if (read_hi) -+ val |= ((u64)XGMAC_IOREAD(pdata, reg_lo + 4) << 32); -+ -+ return val; -+} -+ -+static void xgbe_tx_mmc_int(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_mmc_stats *stats = &pdata->mmc_stats; -+ unsigned int mmc_isr = XGMAC_IOREAD(pdata, MMC_TISR); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXOCTETCOUNT_GB)) -+ stats->txoctetcount_gb += -+ xgbe_mmc_read(pdata, MMC_TXOCTETCOUNT_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXFRAMECOUNT_GB)) -+ stats->txframecount_gb += -+ xgbe_mmc_read(pdata, MMC_TXFRAMECOUNT_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXBROADCASTFRAMES_G)) -+ stats->txbroadcastframes_g += -+ xgbe_mmc_read(pdata, MMC_TXBROADCASTFRAMES_G_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXMULTICASTFRAMES_G)) -+ stats->txmulticastframes_g += -+ xgbe_mmc_read(pdata, MMC_TXMULTICASTFRAMES_G_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX64OCTETS_GB)) -+ stats->tx64octets_gb += -+ xgbe_mmc_read(pdata, MMC_TX64OCTETS_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX65TO127OCTETS_GB)) -+ stats->tx65to127octets_gb += -+ xgbe_mmc_read(pdata, MMC_TX65TO127OCTETS_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX128TO255OCTETS_GB)) -+ stats->tx128to255octets_gb += -+ xgbe_mmc_read(pdata, MMC_TX128TO255OCTETS_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX256TO511OCTETS_GB)) -+ stats->tx256to511octets_gb += -+ xgbe_mmc_read(pdata, MMC_TX256TO511OCTETS_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX512TO1023OCTETS_GB)) -+ stats->tx512to1023octets_gb += -+ xgbe_mmc_read(pdata, MMC_TX512TO1023OCTETS_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX1024TOMAXOCTETS_GB)) -+ stats->tx1024tomaxoctets_gb += -+ xgbe_mmc_read(pdata, MMC_TX1024TOMAXOCTETS_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXUNICASTFRAMES_GB)) -+ stats->txunicastframes_gb += -+ xgbe_mmc_read(pdata, MMC_TXUNICASTFRAMES_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXMULTICASTFRAMES_GB)) -+ stats->txmulticastframes_gb += -+ xgbe_mmc_read(pdata, MMC_TXMULTICASTFRAMES_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXBROADCASTFRAMES_GB)) -+ stats->txbroadcastframes_g += -+ xgbe_mmc_read(pdata, MMC_TXBROADCASTFRAMES_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXUNDERFLOWERROR)) -+ stats->txunderflowerror += -+ xgbe_mmc_read(pdata, MMC_TXUNDERFLOWERROR_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXOCTETCOUNT_G)) -+ stats->txoctetcount_g += -+ xgbe_mmc_read(pdata, MMC_TXOCTETCOUNT_G_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXFRAMECOUNT_G)) -+ stats->txframecount_g += -+ xgbe_mmc_read(pdata, MMC_TXFRAMECOUNT_G_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXPAUSEFRAMES)) -+ stats->txpauseframes += -+ xgbe_mmc_read(pdata, MMC_TXPAUSEFRAMES_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXVLANFRAMES_G)) -+ stats->txvlanframes_g += -+ xgbe_mmc_read(pdata, MMC_TXVLANFRAMES_G_LO); -+} -+ -+static void xgbe_rx_mmc_int(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_mmc_stats *stats = &pdata->mmc_stats; -+ unsigned int mmc_isr = XGMAC_IOREAD(pdata, MMC_RISR); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXFRAMECOUNT_GB)) -+ stats->rxframecount_gb += -+ xgbe_mmc_read(pdata, MMC_RXFRAMECOUNT_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXOCTETCOUNT_GB)) -+ stats->rxoctetcount_gb += -+ xgbe_mmc_read(pdata, MMC_RXOCTETCOUNT_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXOCTETCOUNT_G)) -+ stats->rxoctetcount_g += -+ xgbe_mmc_read(pdata, MMC_RXOCTETCOUNT_G_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXBROADCASTFRAMES_G)) -+ stats->rxbroadcastframes_g += -+ xgbe_mmc_read(pdata, MMC_RXBROADCASTFRAMES_G_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXMULTICASTFRAMES_G)) -+ stats->rxmulticastframes_g += -+ xgbe_mmc_read(pdata, MMC_RXMULTICASTFRAMES_G_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXCRCERROR)) -+ stats->rxcrcerror += -+ xgbe_mmc_read(pdata, MMC_RXCRCERROR_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXRUNTERROR)) -+ stats->rxrunterror += -+ xgbe_mmc_read(pdata, MMC_RXRUNTERROR); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXJABBERERROR)) -+ stats->rxjabbererror += -+ xgbe_mmc_read(pdata, MMC_RXJABBERERROR); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXUNDERSIZE_G)) -+ stats->rxundersize_g += -+ xgbe_mmc_read(pdata, MMC_RXUNDERSIZE_G); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXOVERSIZE_G)) -+ stats->rxoversize_g += -+ xgbe_mmc_read(pdata, MMC_RXOVERSIZE_G); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX64OCTETS_GB)) -+ stats->rx64octets_gb += -+ xgbe_mmc_read(pdata, MMC_RX64OCTETS_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX65TO127OCTETS_GB)) -+ stats->rx65to127octets_gb += -+ xgbe_mmc_read(pdata, MMC_RX65TO127OCTETS_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX128TO255OCTETS_GB)) -+ stats->rx128to255octets_gb += -+ xgbe_mmc_read(pdata, MMC_RX128TO255OCTETS_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX256TO511OCTETS_GB)) -+ stats->rx256to511octets_gb += -+ xgbe_mmc_read(pdata, MMC_RX256TO511OCTETS_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX512TO1023OCTETS_GB)) -+ stats->rx512to1023octets_gb += -+ xgbe_mmc_read(pdata, MMC_RX512TO1023OCTETS_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX1024TOMAXOCTETS_GB)) -+ stats->rx1024tomaxoctets_gb += -+ xgbe_mmc_read(pdata, MMC_RX1024TOMAXOCTETS_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXUNICASTFRAMES_G)) -+ stats->rxunicastframes_g += -+ xgbe_mmc_read(pdata, MMC_RXUNICASTFRAMES_G_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXLENGTHERROR)) -+ stats->rxlengtherror += -+ xgbe_mmc_read(pdata, MMC_RXLENGTHERROR_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXOUTOFRANGETYPE)) -+ stats->rxoutofrangetype += -+ xgbe_mmc_read(pdata, MMC_RXOUTOFRANGETYPE_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXPAUSEFRAMES)) -+ stats->rxpauseframes += -+ xgbe_mmc_read(pdata, MMC_RXPAUSEFRAMES_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXFIFOOVERFLOW)) -+ stats->rxfifooverflow += -+ xgbe_mmc_read(pdata, MMC_RXFIFOOVERFLOW_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXVLANFRAMES_GB)) -+ stats->rxvlanframes_gb += -+ xgbe_mmc_read(pdata, MMC_RXVLANFRAMES_GB_LO); -+ -+ if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXWATCHDOGERROR)) -+ stats->rxwatchdogerror += -+ xgbe_mmc_read(pdata, MMC_RXWATCHDOGERROR); -+} -+ -+static void xgbe_read_mmc_stats(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_mmc_stats *stats = &pdata->mmc_stats; -+ -+ /* Freeze counters */ -+ XGMAC_IOWRITE_BITS(pdata, MMC_CR, MCF, 1); -+ -+ stats->txoctetcount_gb += -+ xgbe_mmc_read(pdata, MMC_TXOCTETCOUNT_GB_LO); -+ -+ stats->txframecount_gb += -+ xgbe_mmc_read(pdata, MMC_TXFRAMECOUNT_GB_LO); -+ -+ stats->txbroadcastframes_g += -+ xgbe_mmc_read(pdata, MMC_TXBROADCASTFRAMES_G_LO); -+ -+ stats->txmulticastframes_g += -+ xgbe_mmc_read(pdata, MMC_TXMULTICASTFRAMES_G_LO); -+ -+ stats->tx64octets_gb += -+ xgbe_mmc_read(pdata, MMC_TX64OCTETS_GB_LO); -+ -+ stats->tx65to127octets_gb += -+ xgbe_mmc_read(pdata, MMC_TX65TO127OCTETS_GB_LO); -+ -+ stats->tx128to255octets_gb += -+ xgbe_mmc_read(pdata, MMC_TX128TO255OCTETS_GB_LO); -+ -+ stats->tx256to511octets_gb += -+ xgbe_mmc_read(pdata, MMC_TX256TO511OCTETS_GB_LO); -+ -+ stats->tx512to1023octets_gb += -+ xgbe_mmc_read(pdata, MMC_TX512TO1023OCTETS_GB_LO); -+ -+ stats->tx1024tomaxoctets_gb += -+ xgbe_mmc_read(pdata, MMC_TX1024TOMAXOCTETS_GB_LO); -+ -+ stats->txunicastframes_gb += -+ xgbe_mmc_read(pdata, MMC_TXUNICASTFRAMES_GB_LO); -+ -+ stats->txmulticastframes_gb += -+ xgbe_mmc_read(pdata, MMC_TXMULTICASTFRAMES_GB_LO); -+ -+ stats->txbroadcastframes_g += -+ xgbe_mmc_read(pdata, MMC_TXBROADCASTFRAMES_GB_LO); -+ -+ stats->txunderflowerror += -+ xgbe_mmc_read(pdata, MMC_TXUNDERFLOWERROR_LO); -+ -+ stats->txoctetcount_g += -+ xgbe_mmc_read(pdata, MMC_TXOCTETCOUNT_G_LO); -+ -+ stats->txframecount_g += -+ xgbe_mmc_read(pdata, MMC_TXFRAMECOUNT_G_LO); -+ -+ stats->txpauseframes += -+ xgbe_mmc_read(pdata, MMC_TXPAUSEFRAMES_LO); -+ -+ stats->txvlanframes_g += -+ xgbe_mmc_read(pdata, MMC_TXVLANFRAMES_G_LO); -+ -+ stats->rxframecount_gb += -+ xgbe_mmc_read(pdata, MMC_RXFRAMECOUNT_GB_LO); -+ -+ stats->rxoctetcount_gb += -+ xgbe_mmc_read(pdata, MMC_RXOCTETCOUNT_GB_LO); -+ -+ stats->rxoctetcount_g += -+ xgbe_mmc_read(pdata, MMC_RXOCTETCOUNT_G_LO); -+ -+ stats->rxbroadcastframes_g += -+ xgbe_mmc_read(pdata, MMC_RXBROADCASTFRAMES_G_LO); -+ -+ stats->rxmulticastframes_g += -+ xgbe_mmc_read(pdata, MMC_RXMULTICASTFRAMES_G_LO); -+ -+ stats->rxcrcerror += -+ xgbe_mmc_read(pdata, MMC_RXCRCERROR_LO); -+ -+ stats->rxrunterror += -+ xgbe_mmc_read(pdata, MMC_RXRUNTERROR); -+ -+ stats->rxjabbererror += -+ xgbe_mmc_read(pdata, MMC_RXJABBERERROR); -+ -+ stats->rxundersize_g += -+ xgbe_mmc_read(pdata, MMC_RXUNDERSIZE_G); -+ -+ stats->rxoversize_g += -+ xgbe_mmc_read(pdata, MMC_RXOVERSIZE_G); -+ -+ stats->rx64octets_gb += -+ xgbe_mmc_read(pdata, MMC_RX64OCTETS_GB_LO); -+ -+ stats->rx65to127octets_gb += -+ xgbe_mmc_read(pdata, MMC_RX65TO127OCTETS_GB_LO); -+ -+ stats->rx128to255octets_gb += -+ xgbe_mmc_read(pdata, MMC_RX128TO255OCTETS_GB_LO); -+ -+ stats->rx256to511octets_gb += -+ xgbe_mmc_read(pdata, MMC_RX256TO511OCTETS_GB_LO); -+ -+ stats->rx512to1023octets_gb += -+ xgbe_mmc_read(pdata, MMC_RX512TO1023OCTETS_GB_LO); -+ -+ stats->rx1024tomaxoctets_gb += -+ xgbe_mmc_read(pdata, MMC_RX1024TOMAXOCTETS_GB_LO); -+ -+ stats->rxunicastframes_g += -+ xgbe_mmc_read(pdata, MMC_RXUNICASTFRAMES_G_LO); -+ -+ stats->rxlengtherror += -+ xgbe_mmc_read(pdata, MMC_RXLENGTHERROR_LO); -+ -+ stats->rxoutofrangetype += -+ xgbe_mmc_read(pdata, MMC_RXOUTOFRANGETYPE_LO); -+ -+ stats->rxpauseframes += -+ xgbe_mmc_read(pdata, MMC_RXPAUSEFRAMES_LO); -+ -+ stats->rxfifooverflow += -+ xgbe_mmc_read(pdata, MMC_RXFIFOOVERFLOW_LO); -+ -+ stats->rxvlanframes_gb += -+ xgbe_mmc_read(pdata, MMC_RXVLANFRAMES_GB_LO); -+ -+ stats->rxwatchdogerror += -+ xgbe_mmc_read(pdata, MMC_RXWATCHDOGERROR); -+ -+ /* Un-freeze counters */ -+ XGMAC_IOWRITE_BITS(pdata, MMC_CR, MCF, 0); -+} -+ -+static void xgbe_config_mmc(struct xgbe_prv_data *pdata) -+{ -+ /* Set counters to reset on read */ -+ XGMAC_IOWRITE_BITS(pdata, MMC_CR, ROR, 1); -+ -+ /* Reset the counters */ -+ XGMAC_IOWRITE_BITS(pdata, MMC_CR, CR, 1); -+} -+ -+static void xgbe_prepare_tx_stop(struct xgbe_prv_data *pdata, -+ struct xgbe_channel *channel) -+{ -+ unsigned int tx_dsr, tx_pos, tx_qidx; -+ unsigned int tx_status; -+ unsigned long tx_timeout; -+ -+ /* Calculate the status register to read and the position within */ -+ if (channel->queue_index < DMA_DSRX_FIRST_QUEUE) { -+ tx_dsr = DMA_DSR0; -+ tx_pos = (channel->queue_index * DMA_DSR_Q_WIDTH) + -+ DMA_DSR0_TPS_START; -+ } else { -+ tx_qidx = channel->queue_index - DMA_DSRX_FIRST_QUEUE; -+ -+ tx_dsr = DMA_DSR1 + ((tx_qidx / DMA_DSRX_QPR) * DMA_DSRX_INC); -+ tx_pos = ((tx_qidx % DMA_DSRX_QPR) * DMA_DSR_Q_WIDTH) + -+ DMA_DSRX_TPS_START; -+ } -+ -+ /* The Tx engine cannot be stopped if it is actively processing -+ * descriptors. Wait for the Tx engine to enter the stopped or -+ * suspended state. Don't wait forever though... -+ */ -+ tx_timeout = jiffies + (XGBE_DMA_STOP_TIMEOUT * HZ); -+ while (time_before(jiffies, tx_timeout)) { -+ tx_status = XGMAC_IOREAD(pdata, tx_dsr); -+ tx_status = GET_BITS(tx_status, tx_pos, DMA_DSR_TPS_WIDTH); -+ if ((tx_status == DMA_TPS_STOPPED) || -+ (tx_status == DMA_TPS_SUSPENDED)) -+ break; -+ -+ usleep_range(500, 1000); -+ } -+ -+ if (!time_before(jiffies, tx_timeout)) -+ netdev_info(pdata->netdev, -+ "timed out waiting for Tx DMA channel %u to stop\n", -+ channel->queue_index); -+} -+ -+static void xgbe_enable_tx(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ /* Enable each Tx DMA channel */ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->tx_ring) -+ break; -+ -+ XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, ST, 1); -+ } -+ -+ /* Enable each Tx queue */ -+ for (i = 0; i < pdata->tx_q_count; i++) -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TXQEN, -+ MTL_Q_ENABLED); -+ -+ /* Enable MAC Tx */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 1); -+} -+ -+static void xgbe_disable_tx(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ /* Prepare for Tx DMA channel stop */ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->tx_ring) -+ break; -+ -+ xgbe_prepare_tx_stop(pdata, channel); -+ } -+ -+ /* Disable MAC Tx */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0); -+ -+ /* Disable each Tx queue */ -+ for (i = 0; i < pdata->tx_q_count; i++) -+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TXQEN, 0); -+ -+ /* Disable each Tx DMA channel */ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->tx_ring) -+ break; -+ -+ XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, ST, 0); -+ } -+} -+ -+static void xgbe_enable_rx(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int reg_val, i; -+ -+ /* Enable each Rx DMA channel */ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->rx_ring) -+ break; -+ -+ XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, SR, 1); -+ } -+ -+ /* Enable each Rx queue */ -+ reg_val = 0; -+ for (i = 0; i < pdata->rx_q_count; i++) -+ reg_val |= (0x02 << (i << 1)); -+ XGMAC_IOWRITE(pdata, MAC_RQC0R, reg_val); -+ -+ /* Enable MAC Rx */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_RCR, DCRCC, 1); -+ XGMAC_IOWRITE_BITS(pdata, MAC_RCR, CST, 1); -+ XGMAC_IOWRITE_BITS(pdata, MAC_RCR, ACS, 1); -+ XGMAC_IOWRITE_BITS(pdata, MAC_RCR, RE, 1); -+} -+ -+static void xgbe_disable_rx(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ /* Disable MAC Rx */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_RCR, DCRCC, 0); -+ XGMAC_IOWRITE_BITS(pdata, MAC_RCR, CST, 0); -+ XGMAC_IOWRITE_BITS(pdata, MAC_RCR, ACS, 0); -+ XGMAC_IOWRITE_BITS(pdata, MAC_RCR, RE, 0); -+ -+ /* Disable each Rx queue */ -+ XGMAC_IOWRITE(pdata, MAC_RQC0R, 0); -+ -+ /* Disable each Rx DMA channel */ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->rx_ring) -+ break; -+ -+ XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, SR, 0); -+ } -+} -+ -+static void xgbe_powerup_tx(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ /* Enable each Tx DMA channel */ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->tx_ring) -+ break; -+ -+ XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, ST, 1); -+ } -+ -+ /* Enable MAC Tx */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 1); -+} -+ -+static void xgbe_powerdown_tx(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ /* Prepare for Tx DMA channel stop */ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->tx_ring) -+ break; -+ -+ xgbe_prepare_tx_stop(pdata, channel); -+ } -+ -+ /* Disable MAC Tx */ -+ XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0); -+ -+ /* Disable each Tx DMA channel */ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->tx_ring) -+ break; -+ -+ XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_TCR, ST, 0); -+ } -+} -+ -+static void xgbe_powerup_rx(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ /* Enable each Rx DMA channel */ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->rx_ring) -+ break; -+ -+ XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, SR, 1); -+ } -+} -+ -+static void xgbe_powerdown_rx(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ /* Disable each Rx DMA channel */ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->rx_ring) -+ break; -+ -+ XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_RCR, SR, 0); -+ } -+} -+ -+static int xgbe_init(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_desc_if *desc_if = &pdata->desc_if; -+ int ret; -+ -+ DBGPR("-->xgbe_init\n"); -+ -+ /* Flush Tx queues */ -+ ret = xgbe_flush_tx_queues(pdata); -+ if (ret) -+ return ret; -+ -+ /* -+ * Initialize DMA related features -+ */ -+ xgbe_config_dma_bus(pdata); -+ xgbe_config_dma_cache(pdata); -+ xgbe_config_osp_mode(pdata); -+ xgbe_config_pblx8(pdata); -+ xgbe_config_tx_pbl_val(pdata); -+ xgbe_config_rx_pbl_val(pdata); -+ xgbe_config_rx_coalesce(pdata); -+ xgbe_config_tx_coalesce(pdata); -+ xgbe_config_rx_buffer_size(pdata); -+ xgbe_config_tso_mode(pdata); -+ xgbe_config_sph_mode(pdata); -+ xgbe_config_rss(pdata); -+ desc_if->wrapper_tx_desc_init(pdata); -+ desc_if->wrapper_rx_desc_init(pdata); -+ xgbe_enable_dma_interrupts(pdata); -+ -+ /* -+ * Initialize MTL related features -+ */ -+ xgbe_config_mtl_mode(pdata); -+ xgbe_config_queue_mapping(pdata); -+ xgbe_config_tsf_mode(pdata, pdata->tx_sf_mode); -+ xgbe_config_rsf_mode(pdata, pdata->rx_sf_mode); -+ xgbe_config_tx_threshold(pdata, pdata->tx_threshold); -+ xgbe_config_rx_threshold(pdata, pdata->rx_threshold); -+ xgbe_config_tx_fifo_size(pdata); -+ xgbe_config_rx_fifo_size(pdata); -+ xgbe_config_flow_control_threshold(pdata); -+ /*TODO: Error Packet and undersized good Packet forwarding enable -+ (FEP and FUP) -+ */ -+ xgbe_config_dcb_tc(pdata); -+ xgbe_config_dcb_pfc(pdata); -+ xgbe_enable_mtl_interrupts(pdata); -+ -+ /* -+ * Initialize MAC related features -+ */ -+ xgbe_config_mac_address(pdata); -+ xgbe_config_jumbo_enable(pdata); -+ xgbe_config_flow_control(pdata); -+ xgbe_config_mac_speed(pdata); -+ xgbe_config_checksum_offload(pdata); -+ xgbe_config_vlan_support(pdata); -+ xgbe_config_mmc(pdata); -+ xgbe_enable_mac_interrupts(pdata); -+ -+ DBGPR("<--xgbe_init\n"); -+ -+ return 0; -+} -+ -+void xgbe_a0_init_function_ptrs_dev(struct xgbe_hw_if *hw_if) -+{ -+ DBGPR("-->xgbe_a0_init_function_ptrs\n"); -+ -+ hw_if->tx_complete = xgbe_tx_complete; -+ -+ hw_if->set_promiscuous_mode = xgbe_set_promiscuous_mode; -+ hw_if->set_all_multicast_mode = xgbe_set_all_multicast_mode; -+ hw_if->add_mac_addresses = xgbe_add_mac_addresses; -+ hw_if->set_mac_address = xgbe_set_mac_address; -+ -+ hw_if->enable_rx_csum = xgbe_enable_rx_csum; -+ hw_if->disable_rx_csum = xgbe_disable_rx_csum; -+ -+ hw_if->enable_rx_vlan_stripping = xgbe_enable_rx_vlan_stripping; -+ hw_if->disable_rx_vlan_stripping = xgbe_disable_rx_vlan_stripping; -+ hw_if->enable_rx_vlan_filtering = xgbe_enable_rx_vlan_filtering; -+ hw_if->disable_rx_vlan_filtering = xgbe_disable_rx_vlan_filtering; -+ hw_if->update_vlan_hash_table = xgbe_update_vlan_hash_table; -+ -+ hw_if->read_mmd_regs = xgbe_read_mmd_regs; -+ hw_if->write_mmd_regs = xgbe_write_mmd_regs; -+ -+ hw_if->set_gmii_speed = xgbe_set_gmii_speed; -+ hw_if->set_gmii_2500_speed = xgbe_set_gmii_2500_speed; -+ hw_if->set_xgmii_speed = xgbe_set_xgmii_speed; -+ -+ hw_if->enable_tx = xgbe_enable_tx; -+ hw_if->disable_tx = xgbe_disable_tx; -+ hw_if->enable_rx = xgbe_enable_rx; -+ hw_if->disable_rx = xgbe_disable_rx; -+ -+ hw_if->powerup_tx = xgbe_powerup_tx; -+ hw_if->powerdown_tx = xgbe_powerdown_tx; -+ hw_if->powerup_rx = xgbe_powerup_rx; -+ hw_if->powerdown_rx = xgbe_powerdown_rx; -+ -+ hw_if->dev_xmit = xgbe_dev_xmit; -+ hw_if->dev_read = xgbe_dev_read; -+ hw_if->enable_int = xgbe_enable_int; -+ hw_if->disable_int = xgbe_disable_int; -+ hw_if->init = xgbe_init; -+ hw_if->exit = xgbe_exit; -+ -+ /* Descriptor related Sequences have to be initialized here */ -+ hw_if->tx_desc_init = xgbe_tx_desc_init; -+ hw_if->rx_desc_init = xgbe_rx_desc_init; -+ hw_if->tx_desc_reset = xgbe_tx_desc_reset; -+ hw_if->rx_desc_reset = xgbe_rx_desc_reset; -+ hw_if->is_last_desc = xgbe_is_last_desc; -+ hw_if->is_context_desc = xgbe_is_context_desc; -+ hw_if->tx_start_xmit = xgbe_tx_start_xmit; -+ -+ /* For FLOW ctrl */ -+ hw_if->config_tx_flow_control = xgbe_config_tx_flow_control; -+ hw_if->config_rx_flow_control = xgbe_config_rx_flow_control; -+ -+ /* For RX coalescing */ -+ hw_if->config_rx_coalesce = xgbe_config_rx_coalesce; -+ hw_if->config_tx_coalesce = xgbe_config_tx_coalesce; -+ hw_if->usec_to_riwt = xgbe_usec_to_riwt; -+ hw_if->riwt_to_usec = xgbe_riwt_to_usec; -+ -+ /* For RX and TX threshold config */ -+ hw_if->config_rx_threshold = xgbe_config_rx_threshold; -+ hw_if->config_tx_threshold = xgbe_config_tx_threshold; -+ -+ /* For RX and TX Store and Forward Mode config */ -+ hw_if->config_rsf_mode = xgbe_config_rsf_mode; -+ hw_if->config_tsf_mode = xgbe_config_tsf_mode; -+ -+ /* For TX DMA Operating on Second Frame config */ -+ hw_if->config_osp_mode = xgbe_config_osp_mode; -+ -+ /* For RX and TX PBL config */ -+ hw_if->config_rx_pbl_val = xgbe_config_rx_pbl_val; -+ hw_if->get_rx_pbl_val = xgbe_get_rx_pbl_val; -+ hw_if->config_tx_pbl_val = xgbe_config_tx_pbl_val; -+ hw_if->get_tx_pbl_val = xgbe_get_tx_pbl_val; -+ hw_if->config_pblx8 = xgbe_config_pblx8; -+ -+ /* For MMC statistics support */ -+ hw_if->tx_mmc_int = xgbe_tx_mmc_int; -+ hw_if->rx_mmc_int = xgbe_rx_mmc_int; -+ hw_if->read_mmc_stats = xgbe_read_mmc_stats; -+ -+ /* For PTP config */ -+ hw_if->config_tstamp = xgbe_config_tstamp; -+ hw_if->update_tstamp_addend = xgbe_update_tstamp_addend; -+ hw_if->set_tstamp_time = xgbe_set_tstamp_time; -+ hw_if->get_tstamp_time = xgbe_get_tstamp_time; -+ hw_if->get_tx_tstamp = xgbe_get_tx_tstamp; -+ -+ /* For Data Center Bridging config */ -+ hw_if->config_dcb_tc = xgbe_config_dcb_tc; -+ hw_if->config_dcb_pfc = xgbe_config_dcb_pfc; -+ -+ /* For Receive Side Scaling */ -+ hw_if->enable_rss = xgbe_enable_rss; -+ hw_if->disable_rss = xgbe_disable_rss; -+ hw_if->set_rss_hash_key = xgbe_set_rss_hash_key; -+ hw_if->set_rss_lookup_table = xgbe_set_rss_lookup_table; -+ -+ DBGPR("<--xgbe_a0_init_function_ptrs\n"); -+} -diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-drv.c -new file mode 100644 -index 0000000..ca4af9e ---- /dev/null -+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-drv.c -@@ -0,0 +1,2218 @@ -+/* -+ * AMD 10Gb Ethernet driver -+ * -+ * This file is available to you under your choice of the following two -+ * licenses: -+ * -+ * License 1: GPLv2 -+ * -+ * Copyright (c) 2014 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 . -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * -+ * License 2: Modified BSD -+ * -+ * Copyright (c) 2014 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 BE LIABLE FOR ANY -+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "xgbe.h" -+#include "xgbe-common.h" -+ -+static int xgbe_one_poll(struct napi_struct *, int); -+static int xgbe_all_poll(struct napi_struct *, int); -+static void xgbe_set_rx_mode(struct net_device *); -+ -+static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel_mem, *channel; -+ struct xgbe_ring *tx_ring, *rx_ring; -+ unsigned int count, i; -+ int ret = -ENOMEM; -+ -+ count = max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count); -+ -+ channel_mem = kcalloc(count, sizeof(struct xgbe_channel), GFP_KERNEL); -+ if (!channel_mem) -+ goto err_channel; -+ -+ tx_ring = kcalloc(pdata->tx_ring_count, sizeof(struct xgbe_ring), -+ GFP_KERNEL); -+ if (!tx_ring) -+ goto err_tx_ring; -+ -+ rx_ring = kcalloc(pdata->rx_ring_count, sizeof(struct xgbe_ring), -+ GFP_KERNEL); -+ if (!rx_ring) -+ goto err_rx_ring; -+ -+ for (i = 0, channel = channel_mem; i < count; i++, channel++) { -+ snprintf(channel->name, sizeof(channel->name), "channel-%d", i); -+ channel->pdata = pdata; -+ channel->queue_index = i; -+ channel->dma_regs = pdata->xgmac_regs + DMA_CH_BASE + -+ (DMA_CH_INC * i); -+ -+ if (pdata->per_channel_irq) { -+ /* Get the DMA interrupt (offset 1) */ -+ ret = platform_get_irq(pdata->pdev, i + 1); -+ if (ret < 0) { -+ netdev_err(pdata->netdev, -+ "platform_get_irq %u failed\n", -+ i + 1); -+ goto err_irq; -+ } -+ -+ channel->dma_irq = ret; -+ } -+ -+ if (i < pdata->tx_ring_count) { -+ spin_lock_init(&tx_ring->lock); -+ channel->tx_ring = tx_ring++; -+ } -+ -+ if (i < pdata->rx_ring_count) { -+ spin_lock_init(&rx_ring->lock); -+ channel->rx_ring = rx_ring++; -+ } -+ -+ DBGPR(" %s: queue=%u, dma_regs=%p, dma_irq=%d, tx=%p, rx=%p\n", -+ channel->name, channel->queue_index, channel->dma_regs, -+ channel->dma_irq, channel->tx_ring, channel->rx_ring); -+ } -+ -+ pdata->channel = channel_mem; -+ pdata->channel_count = count; -+ -+ return 0; -+ -+err_irq: -+ kfree(rx_ring); -+ -+err_rx_ring: -+ kfree(tx_ring); -+ -+err_tx_ring: -+ kfree(channel_mem); -+ -+err_channel: -+ return ret; -+} -+ -+static void xgbe_free_channels(struct xgbe_prv_data *pdata) -+{ -+ if (!pdata->channel) -+ return; -+ -+ kfree(pdata->channel->rx_ring); -+ kfree(pdata->channel->tx_ring); -+ kfree(pdata->channel); -+ -+ pdata->channel = NULL; -+ pdata->channel_count = 0; -+} -+ -+static inline unsigned int xgbe_tx_avail_desc(struct xgbe_ring *ring) -+{ -+ return (ring->rdesc_count - (ring->cur - ring->dirty)); -+} -+ -+static inline unsigned int xgbe_rx_dirty_desc(struct xgbe_ring *ring) -+{ -+ return (ring->cur - ring->dirty); -+} -+ -+static int xgbe_maybe_stop_tx_queue(struct xgbe_channel *channel, -+ struct xgbe_ring *ring, unsigned int count) -+{ -+ struct xgbe_prv_data *pdata = channel->pdata; -+ -+ if (count > xgbe_tx_avail_desc(ring)) { -+ DBGPR(" Tx queue stopped, not enough descriptors available\n"); -+ netif_stop_subqueue(pdata->netdev, channel->queue_index); -+ ring->tx.queue_stopped = 1; -+ -+ /* If we haven't notified the hardware because of xmit_more -+ * support, tell it now -+ */ -+ if (ring->tx.xmit_more) -+ pdata->hw_if.tx_start_xmit(channel, ring); -+ -+ return NETDEV_TX_BUSY; -+ } -+ -+ return 0; -+} -+ -+static int xgbe_calc_rx_buf_size(struct net_device *netdev, unsigned int mtu) -+{ -+ unsigned int rx_buf_size; -+ -+ if (mtu > XGMAC_JUMBO_PACKET_MTU) { -+ netdev_alert(netdev, "MTU exceeds maximum supported value\n"); -+ return -EINVAL; -+ } -+ -+ rx_buf_size = mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; -+ rx_buf_size = clamp_val(rx_buf_size, XGBE_RX_MIN_BUF_SIZE, PAGE_SIZE); -+ -+ rx_buf_size = (rx_buf_size + XGBE_RX_BUF_ALIGN - 1) & -+ ~(XGBE_RX_BUF_ALIGN - 1); -+ -+ return rx_buf_size; -+} -+ -+static void xgbe_enable_rx_tx_ints(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ struct xgbe_channel *channel; -+ enum xgbe_int int_id; -+ unsigned int i; -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (channel->tx_ring && channel->rx_ring) -+ int_id = XGMAC_INT_DMA_CH_SR_TI_RI; -+ else if (channel->tx_ring) -+ int_id = XGMAC_INT_DMA_CH_SR_TI; -+ else if (channel->rx_ring) -+ int_id = XGMAC_INT_DMA_CH_SR_RI; -+ else -+ continue; -+ -+ hw_if->enable_int(channel, int_id); -+ } -+} -+ -+static void xgbe_disable_rx_tx_ints(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ struct xgbe_channel *channel; -+ enum xgbe_int int_id; -+ unsigned int i; -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (channel->tx_ring && channel->rx_ring) -+ int_id = XGMAC_INT_DMA_CH_SR_TI_RI; -+ else if (channel->tx_ring) -+ int_id = XGMAC_INT_DMA_CH_SR_TI; -+ else if (channel->rx_ring) -+ int_id = XGMAC_INT_DMA_CH_SR_RI; -+ else -+ continue; -+ -+ hw_if->disable_int(channel, int_id); -+ } -+} -+ -+static irqreturn_t xgbe_isr(int irq, void *data) -+{ -+ struct xgbe_prv_data *pdata = data; -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ struct xgbe_channel *channel; -+ unsigned int dma_isr, dma_ch_isr; -+ unsigned int mac_isr, mac_tssr; -+ unsigned int i; -+ -+ /* The DMA interrupt status register also reports MAC and MTL -+ * interrupts. So for polling mode, we just need to check for -+ * this register to be non-zero -+ */ -+ dma_isr = XGMAC_IOREAD(pdata, DMA_ISR); -+ if (!dma_isr) -+ goto isr_done; -+ -+ DBGPR(" DMA_ISR = %08x\n", dma_isr); -+ -+ for (i = 0; i < pdata->channel_count; i++) { -+ if (!(dma_isr & (1 << i))) -+ continue; -+ -+ channel = pdata->channel + i; -+ -+ dma_ch_isr = XGMAC_DMA_IOREAD(channel, DMA_CH_SR); -+ DBGPR(" DMA_CH%u_ISR = %08x\n", i, dma_ch_isr); -+ -+ /* The TI or RI interrupt bits may still be set even if using -+ * per channel DMA interrupts. Check to be sure those are not -+ * enabled before using the private data napi structure. -+ */ -+ if (!pdata->per_channel_irq && -+ (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, TI) || -+ XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RI))) { -+ if (napi_schedule_prep(&pdata->napi)) { -+ /* Disable Tx and Rx interrupts */ -+ xgbe_disable_rx_tx_ints(pdata); -+ -+ /* Turn on polling */ -+ __napi_schedule(&pdata->napi); -+ } -+ } -+ -+ /* Restart the device on a Fatal Bus Error */ -+ if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, FBE)) -+ schedule_work(&pdata->restart_work); -+ -+ /* Clear all interrupt signals */ -+ XGMAC_DMA_IOWRITE(channel, DMA_CH_SR, dma_ch_isr); -+ } -+ -+ if (XGMAC_GET_BITS(dma_isr, DMA_ISR, MACIS)) { -+ mac_isr = XGMAC_IOREAD(pdata, MAC_ISR); -+ -+ if (XGMAC_GET_BITS(mac_isr, MAC_ISR, MMCTXIS)) -+ hw_if->tx_mmc_int(pdata); -+ -+ if (XGMAC_GET_BITS(mac_isr, MAC_ISR, MMCRXIS)) -+ hw_if->rx_mmc_int(pdata); -+ -+ if (XGMAC_GET_BITS(mac_isr, MAC_ISR, TSIS)) { -+ mac_tssr = XGMAC_IOREAD(pdata, MAC_TSSR); -+ -+ if (XGMAC_GET_BITS(mac_tssr, MAC_TSSR, TXTSC)) { -+ /* Read Tx Timestamp to clear interrupt */ -+ pdata->tx_tstamp = -+ hw_if->get_tx_tstamp(pdata); -+ schedule_work(&pdata->tx_tstamp_work); -+ } -+ } -+ } -+ -+ DBGPR(" DMA_ISR = %08x\n", XGMAC_IOREAD(pdata, DMA_ISR)); -+ -+isr_done: -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t xgbe_dma_isr(int irq, void *data) -+{ -+ struct xgbe_channel *channel = data; -+ -+ /* Per channel DMA interrupts are enabled, so we use the per -+ * channel napi structure and not the private data napi structure -+ */ -+ if (napi_schedule_prep(&channel->napi)) { -+ /* Disable Tx and Rx interrupts */ -+ disable_irq_nosync(channel->dma_irq); -+ -+ /* Turn on polling */ -+ __napi_schedule(&channel->napi); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static enum hrtimer_restart xgbe_tx_timer(struct hrtimer *timer) -+{ -+ struct xgbe_channel *channel = container_of(timer, -+ struct xgbe_channel, -+ tx_timer); -+ struct xgbe_prv_data *pdata = channel->pdata; -+ struct napi_struct *napi; -+ -+ DBGPR("-->xgbe_tx_timer\n"); -+ -+ napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi; -+ -+ if (napi_schedule_prep(napi)) { -+ /* Disable Tx and Rx interrupts */ -+ if (pdata->per_channel_irq) -+ disable_irq(channel->dma_irq); -+ else -+ xgbe_disable_rx_tx_ints(pdata); -+ -+ /* Turn on polling */ -+ __napi_schedule(napi); -+ } -+ -+ channel->tx_timer_active = 0; -+ -+ DBGPR("<--xgbe_tx_timer\n"); -+ -+ return HRTIMER_NORESTART; -+} -+ -+static void xgbe_init_tx_timers(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ DBGPR("-->xgbe_init_tx_timers\n"); -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->tx_ring) -+ break; -+ -+ DBGPR(" %s adding tx timer\n", channel->name); -+ hrtimer_init(&channel->tx_timer, CLOCK_MONOTONIC, -+ HRTIMER_MODE_REL); -+ channel->tx_timer.function = xgbe_tx_timer; -+ } -+ -+ DBGPR("<--xgbe_init_tx_timers\n"); -+} -+ -+static void xgbe_stop_tx_timers(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ DBGPR("-->xgbe_stop_tx_timers\n"); -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->tx_ring) -+ break; -+ -+ DBGPR(" %s deleting tx timer\n", channel->name); -+ channel->tx_timer_active = 0; -+ hrtimer_cancel(&channel->tx_timer); -+ } -+ -+ DBGPR("<--xgbe_stop_tx_timers\n"); -+} -+ -+void xgbe_a0_get_all_hw_features(struct xgbe_prv_data *pdata) -+{ -+ unsigned int mac_hfr0, mac_hfr1, mac_hfr2; -+ struct xgbe_hw_features *hw_feat = &pdata->hw_feat; -+ -+ DBGPR("-->xgbe_a0_get_all_hw_features\n"); -+ -+ mac_hfr0 = XGMAC_IOREAD(pdata, MAC_HWF0R); -+ mac_hfr1 = XGMAC_IOREAD(pdata, MAC_HWF1R); -+ mac_hfr2 = XGMAC_IOREAD(pdata, MAC_HWF2R); -+ -+ memset(hw_feat, 0, sizeof(*hw_feat)); -+ -+ hw_feat->version = XGMAC_IOREAD(pdata, MAC_VR); -+ -+ /* Hardware feature register 0 */ -+ hw_feat->gmii = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, GMIISEL); -+ hw_feat->vlhash = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, VLHASH); -+ hw_feat->sma = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, SMASEL); -+ hw_feat->rwk = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, RWKSEL); -+ hw_feat->mgk = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, MGKSEL); -+ hw_feat->mmc = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, MMCSEL); -+ hw_feat->aoe = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, ARPOFFSEL); -+ hw_feat->ts = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, TSSEL); -+ hw_feat->eee = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, EEESEL); -+ hw_feat->tx_coe = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, TXCOESEL); -+ hw_feat->rx_coe = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, RXCOESEL); -+ hw_feat->addn_mac = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, -+ ADDMACADRSEL); -+ hw_feat->ts_src = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, TSSTSSEL); -+ hw_feat->sa_vlan_ins = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, SAVLANINS); -+ -+ /* Hardware feature register 1 */ -+ hw_feat->rx_fifo_size = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, -+ RXFIFOSIZE); -+ hw_feat->tx_fifo_size = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, -+ TXFIFOSIZE); -+ hw_feat->dcb = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, DCBEN); -+ hw_feat->sph = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, SPHEN); -+ hw_feat->tso = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, TSOEN); -+ hw_feat->dma_debug = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, DBGMEMA); -+ hw_feat->rss = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, RSSEN); -+ hw_feat->tc_cnt = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, NUMTC); -+ hw_feat->hash_table_size = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, -+ HASHTBLSZ); -+ hw_feat->l3l4_filter_num = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, -+ L3L4FNUM); -+ -+ /* Hardware feature register 2 */ -+ hw_feat->rx_q_cnt = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, RXQCNT); -+ hw_feat->tx_q_cnt = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, TXQCNT); -+ hw_feat->rx_ch_cnt = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, RXCHCNT); -+ hw_feat->tx_ch_cnt = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, TXCHCNT); -+ hw_feat->pps_out_num = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, PPSOUTNUM); -+ hw_feat->aux_snap_num = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, AUXSNAPNUM); -+ -+ /* Translate the Hash Table size into actual number */ -+ switch (hw_feat->hash_table_size) { -+ case 0: -+ break; -+ case 1: -+ hw_feat->hash_table_size = 64; -+ break; -+ case 2: -+ hw_feat->hash_table_size = 128; -+ break; -+ case 3: -+ hw_feat->hash_table_size = 256; -+ break; -+ } -+ -+ /* The Queue, Channel and TC counts are zero based so increment them -+ * to get the actual number -+ */ -+ hw_feat->rx_q_cnt++; -+ hw_feat->tx_q_cnt++; -+ hw_feat->rx_ch_cnt++; -+ hw_feat->tx_ch_cnt++; -+ hw_feat->tc_cnt++; -+ -+#define XGBE_TC_CNT 2 -+ hw_feat->tc_cnt = XGBE_TC_CNT; -+ -+ DBGPR("<--xgbe_a0_get_all_hw_features\n"); -+} -+ -+static void xgbe_napi_enable(struct xgbe_prv_data *pdata, unsigned int add) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ if (pdata->per_channel_irq) { -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (add) -+ netif_napi_add(pdata->netdev, &channel->napi, -+ xgbe_one_poll, NAPI_POLL_WEIGHT); -+ -+ napi_enable(&channel->napi); -+ } -+ } else { -+ if (add) -+ netif_napi_add(pdata->netdev, &pdata->napi, -+ xgbe_all_poll, NAPI_POLL_WEIGHT); -+ -+ napi_enable(&pdata->napi); -+ } -+} -+ -+static void xgbe_napi_disable(struct xgbe_prv_data *pdata, unsigned int del) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ if (pdata->per_channel_irq) { -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ napi_disable(&channel->napi); -+ -+ if (del) -+ netif_napi_del(&channel->napi); -+ } -+ } else { -+ napi_disable(&pdata->napi); -+ -+ if (del) -+ netif_napi_del(&pdata->napi); -+ } -+} -+ -+static int xgbe_request_irqs(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ struct net_device *netdev = pdata->netdev; -+ unsigned int i; -+ int ret; -+ -+ ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0, -+ netdev->name, pdata); -+ if (ret) { -+ netdev_alert(netdev, "error requesting irq %d\n", -+ pdata->dev_irq); -+ return ret; -+ } -+ -+ if (!pdata->per_channel_irq) -+ return 0; -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ snprintf(channel->dma_irq_name, -+ sizeof(channel->dma_irq_name) - 1, -+ "%s-TxRx-%u", netdev_name(netdev), -+ channel->queue_index); -+ -+ ret = devm_request_irq(pdata->dev, channel->dma_irq, -+ xgbe_dma_isr, 0, -+ channel->dma_irq_name, channel); -+ if (ret) { -+ netdev_alert(netdev, "error requesting irq %d\n", -+ channel->dma_irq); -+ goto err_irq; -+ } -+ } -+ -+ return 0; -+ -+err_irq: -+ /* Using an unsigned int, 'i' will go to UINT_MAX and exit */ -+ for (i--, channel--; i < pdata->channel_count; i--, channel--) -+ devm_free_irq(pdata->dev, channel->dma_irq, channel); -+ -+ devm_free_irq(pdata->dev, pdata->dev_irq, pdata); -+ -+ return ret; -+} -+ -+static void xgbe_free_irqs(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ devm_free_irq(pdata->dev, pdata->dev_irq, pdata); -+ -+ if (!pdata->per_channel_irq) -+ return; -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) -+ devm_free_irq(pdata->dev, channel->dma_irq, channel); -+} -+ -+void xgbe_a0_init_tx_coalesce(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ -+ DBGPR("-->xgbe_a0_init_tx_coalesce\n"); -+ -+ pdata->tx_usecs = XGMAC_INIT_DMA_TX_USECS; -+ pdata->tx_frames = XGMAC_INIT_DMA_TX_FRAMES; -+ -+ hw_if->config_tx_coalesce(pdata); -+ -+ DBGPR("<--xgbe_a0_init_tx_coalesce\n"); -+} -+ -+void xgbe_a0_init_rx_coalesce(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ -+ DBGPR("-->xgbe_a0_init_rx_coalesce\n"); -+ -+ pdata->rx_riwt = hw_if->usec_to_riwt(pdata, XGMAC_INIT_DMA_RX_USECS); -+ pdata->rx_frames = XGMAC_INIT_DMA_RX_FRAMES; -+ -+ hw_if->config_rx_coalesce(pdata); -+ -+ DBGPR("<--xgbe_a0_init_rx_coalesce\n"); -+} -+ -+static void xgbe_free_tx_data(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_desc_if *desc_if = &pdata->desc_if; -+ struct xgbe_channel *channel; -+ struct xgbe_ring *ring; -+ struct xgbe_ring_data *rdata; -+ unsigned int i, j; -+ -+ DBGPR("-->xgbe_free_tx_data\n"); -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ ring = channel->tx_ring; -+ if (!ring) -+ break; -+ -+ for (j = 0; j < ring->rdesc_count; j++) { -+ rdata = XGBE_GET_DESC_DATA(ring, j); -+ desc_if->unmap_rdata(pdata, rdata); -+ } -+ } -+ -+ DBGPR("<--xgbe_free_tx_data\n"); -+} -+ -+static void xgbe_free_rx_data(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_desc_if *desc_if = &pdata->desc_if; -+ struct xgbe_channel *channel; -+ struct xgbe_ring *ring; -+ struct xgbe_ring_data *rdata; -+ unsigned int i, j; -+ -+ DBGPR("-->xgbe_free_rx_data\n"); -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ ring = channel->rx_ring; -+ if (!ring) -+ break; -+ -+ for (j = 0; j < ring->rdesc_count; j++) { -+ rdata = XGBE_GET_DESC_DATA(ring, j); -+ desc_if->unmap_rdata(pdata, rdata); -+ } -+ } -+ -+ DBGPR("<--xgbe_free_rx_data\n"); -+} -+ -+static void xgbe_adjust_link(struct net_device *netdev) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ struct phy_device *phydev = pdata->phydev; -+ int new_state = 0; -+ -+ if (!phydev) -+ return; -+ -+ if (phydev->link) { -+ /* Flow control support */ -+ if (pdata->pause_autoneg) { -+ if (phydev->pause || phydev->asym_pause) { -+ pdata->tx_pause = 1; -+ pdata->rx_pause = 1; -+ } else { -+ pdata->tx_pause = 0; -+ pdata->rx_pause = 0; -+ } -+ } -+ -+ if (pdata->tx_pause != pdata->phy_tx_pause) { -+ hw_if->config_tx_flow_control(pdata); -+ pdata->phy_tx_pause = pdata->tx_pause; -+ } -+ -+ if (pdata->rx_pause != pdata->phy_rx_pause) { -+ hw_if->config_rx_flow_control(pdata); -+ pdata->phy_rx_pause = pdata->rx_pause; -+ } -+ -+ /* Speed support */ -+ if (phydev->speed != pdata->phy_speed) { -+ new_state = 1; -+ -+ switch (phydev->speed) { -+ case SPEED_10000: -+ hw_if->set_xgmii_speed(pdata); -+ break; -+ -+ case SPEED_2500: -+ hw_if->set_gmii_2500_speed(pdata); -+ break; -+ -+ case SPEED_1000: -+ hw_if->set_gmii_speed(pdata); -+ break; -+ } -+ pdata->phy_speed = phydev->speed; -+ } -+ -+ if (phydev->link != pdata->phy_link) { -+ new_state = 1; -+ pdata->phy_link = 1; -+ } -+ } else if (pdata->phy_link) { -+ new_state = 1; -+ pdata->phy_link = 0; -+ pdata->phy_speed = SPEED_UNKNOWN; -+ } -+ -+ if (new_state) -+ phy_print_status(phydev); -+} -+ -+static int xgbe_phy_init(struct xgbe_prv_data *pdata) -+{ -+ struct net_device *netdev = pdata->netdev; -+ struct phy_device *phydev = pdata->phydev; -+ int ret; -+ -+ pdata->phy_link = -1; -+ pdata->phy_speed = SPEED_UNKNOWN; -+ pdata->phy_tx_pause = pdata->tx_pause; -+ pdata->phy_rx_pause = pdata->rx_pause; -+ -+ ret = phy_connect_direct(netdev, phydev, &xgbe_adjust_link, -+ pdata->phy_mode); -+ if (ret) { -+ netdev_err(netdev, "phy_connect_direct failed\n"); -+ return ret; -+ } -+ -+ if (!phydev->drv || (phydev->drv->phy_id == 0)) { -+ netdev_err(netdev, "phy_id not valid\n"); -+ ret = -ENODEV; -+ goto err_phy_connect; -+ } -+ DBGPR(" phy_connect_direct succeeded for PHY %s, link=%d\n", -+ dev_name(&phydev->dev), phydev->link); -+ -+ return 0; -+ -+err_phy_connect: -+ phy_disconnect(phydev); -+ -+ return ret; -+} -+ -+static void xgbe_phy_exit(struct xgbe_prv_data *pdata) -+{ -+ if (!pdata->phydev) -+ return; -+ -+ phy_disconnect(pdata->phydev); -+} -+ -+int xgbe_a0_powerdown(struct net_device *netdev, unsigned int caller) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ unsigned long flags; -+ -+ DBGPR("-->xgbe_a0_powerdown\n"); -+ -+ if (!netif_running(netdev) || -+ (caller == XGMAC_IOCTL_CONTEXT && pdata->power_down)) { -+ netdev_alert(netdev, "Device is already powered down\n"); -+ DBGPR("<--xgbe_a0_powerdown\n"); -+ return -EINVAL; -+ } -+ -+ spin_lock_irqsave(&pdata->lock, flags); -+ -+ if (caller == XGMAC_DRIVER_CONTEXT) -+ netif_device_detach(netdev); -+ -+ netif_tx_stop_all_queues(netdev); -+ -+ hw_if->powerdown_tx(pdata); -+ hw_if->powerdown_rx(pdata); -+ -+ xgbe_napi_disable(pdata, 0); -+ -+ phy_stop(pdata->phydev); -+ -+ pdata->power_down = 1; -+ -+ spin_unlock_irqrestore(&pdata->lock, flags); -+ -+ DBGPR("<--xgbe_a0_powerdown\n"); -+ -+ return 0; -+} -+ -+int xgbe_a0_powerup(struct net_device *netdev, unsigned int caller) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ unsigned long flags; -+ -+ DBGPR("-->xgbe_a0_powerup\n"); -+ -+ if (!netif_running(netdev) || -+ (caller == XGMAC_IOCTL_CONTEXT && !pdata->power_down)) { -+ netdev_alert(netdev, "Device is already powered up\n"); -+ DBGPR("<--xgbe_a0_powerup\n"); -+ return -EINVAL; -+ } -+ -+ spin_lock_irqsave(&pdata->lock, flags); -+ -+ pdata->power_down = 0; -+ -+ phy_start(pdata->phydev); -+ -+ xgbe_napi_enable(pdata, 0); -+ -+ hw_if->powerup_tx(pdata); -+ hw_if->powerup_rx(pdata); -+ -+ if (caller == XGMAC_DRIVER_CONTEXT) -+ netif_device_attach(netdev); -+ -+ netif_tx_start_all_queues(netdev); -+ -+ spin_unlock_irqrestore(&pdata->lock, flags); -+ -+ DBGPR("<--xgbe_a0_powerup\n"); -+ -+ return 0; -+} -+ -+static int xgbe_start(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ struct net_device *netdev = pdata->netdev; -+ int ret; -+ -+ DBGPR("-->xgbe_start\n"); -+ -+ xgbe_set_rx_mode(netdev); -+ -+ hw_if->init(pdata); -+ -+ phy_start(pdata->phydev); -+ -+ xgbe_napi_enable(pdata, 1); -+ -+ ret = xgbe_request_irqs(pdata); -+ if (ret) -+ goto err_napi; -+ -+ hw_if->enable_tx(pdata); -+ hw_if->enable_rx(pdata); -+ -+ xgbe_init_tx_timers(pdata); -+ -+ netif_tx_start_all_queues(netdev); -+ -+ DBGPR("<--xgbe_start\n"); -+ -+ return 0; -+ -+err_napi: -+ xgbe_napi_disable(pdata, 1); -+ -+ phy_stop(pdata->phydev); -+ -+ hw_if->exit(pdata); -+ -+ return ret; -+} -+ -+static void xgbe_stop(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ struct xgbe_channel *channel; -+ struct net_device *netdev = pdata->netdev; -+ struct netdev_queue *txq; -+ unsigned int i; -+ -+ DBGPR("-->xgbe_stop\n"); -+ -+ netif_tx_stop_all_queues(netdev); -+ -+ xgbe_stop_tx_timers(pdata); -+ -+ hw_if->disable_tx(pdata); -+ hw_if->disable_rx(pdata); -+ -+ xgbe_free_irqs(pdata); -+ -+ xgbe_napi_disable(pdata, 1); -+ -+ phy_stop(pdata->phydev); -+ -+ hw_if->exit(pdata); -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ if (!channel->tx_ring) -+ continue; -+ -+ txq = netdev_get_tx_queue(netdev, channel->queue_index); -+ netdev_tx_reset_queue(txq); -+ } -+ -+ DBGPR("<--xgbe_stop\n"); -+} -+ -+static void xgbe_restart_dev(struct xgbe_prv_data *pdata) -+{ -+ DBGPR("-->xgbe_restart_dev\n"); -+ -+ /* If not running, "restart" will happen on open */ -+ if (!netif_running(pdata->netdev)) -+ return; -+ -+ xgbe_stop(pdata); -+ -+ xgbe_free_tx_data(pdata); -+ xgbe_free_rx_data(pdata); -+ -+ xgbe_start(pdata); -+ -+ DBGPR("<--xgbe_restart_dev\n"); -+} -+ -+static void xgbe_restart(struct work_struct *work) -+{ -+ struct xgbe_prv_data *pdata = container_of(work, -+ struct xgbe_prv_data, -+ restart_work); -+ -+ rtnl_lock(); -+ -+ xgbe_restart_dev(pdata); -+ -+ rtnl_unlock(); -+} -+ -+static void xgbe_tx_tstamp(struct work_struct *work) -+{ -+ struct xgbe_prv_data *pdata = container_of(work, -+ struct xgbe_prv_data, -+ tx_tstamp_work); -+ struct skb_shared_hwtstamps hwtstamps; -+ u64 nsec; -+ unsigned long flags; -+ -+ if (pdata->tx_tstamp) { -+ nsec = timecounter_cyc2time(&pdata->tstamp_tc, -+ pdata->tx_tstamp); -+ -+ memset(&hwtstamps, 0, sizeof(hwtstamps)); -+ hwtstamps.hwtstamp = ns_to_ktime(nsec); -+ skb_tstamp_tx(pdata->tx_tstamp_skb, &hwtstamps); -+ } -+ -+ dev_kfree_skb_any(pdata->tx_tstamp_skb); -+ -+ spin_lock_irqsave(&pdata->tstamp_lock, flags); -+ pdata->tx_tstamp_skb = NULL; -+ spin_unlock_irqrestore(&pdata->tstamp_lock, flags); -+} -+ -+static int xgbe_get_hwtstamp_settings(struct xgbe_prv_data *pdata, -+ struct ifreq *ifreq) -+{ -+ if (copy_to_user(ifreq->ifr_data, &pdata->tstamp_config, -+ sizeof(pdata->tstamp_config))) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+static int xgbe_set_hwtstamp_settings(struct xgbe_prv_data *pdata, -+ struct ifreq *ifreq) -+{ -+ struct hwtstamp_config config; -+ unsigned int mac_tscr; -+ -+ if (copy_from_user(&config, ifreq->ifr_data, sizeof(config))) -+ return -EFAULT; -+ -+ if (config.flags) -+ return -EINVAL; -+ -+ mac_tscr = 0; -+ -+ switch (config.tx_type) { -+ case HWTSTAMP_TX_OFF: -+ break; -+ -+ case HWTSTAMP_TX_ON: -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); -+ break; -+ -+ default: -+ return -ERANGE; -+ } -+ -+ switch (config.rx_filter) { -+ case HWTSTAMP_FILTER_NONE: -+ break; -+ -+ case HWTSTAMP_FILTER_ALL: -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENALL, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); -+ break; -+ -+ /* PTP v2, UDP, any kind of event packet */ -+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); -+ /* PTP v1, UDP, any kind of event packet */ -+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); -+ break; -+ -+ /* PTP v2, UDP, Sync packet */ -+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); -+ /* PTP v1, UDP, Sync packet */ -+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); -+ break; -+ -+ /* PTP v2, UDP, Delay_req packet */ -+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); -+ /* PTP v1, UDP, Delay_req packet */ -+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); -+ break; -+ -+ /* 802.AS1, Ethernet, any kind of event packet */ -+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); -+ break; -+ -+ /* 802.AS1, Ethernet, Sync packet */ -+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); -+ break; -+ -+ /* 802.AS1, Ethernet, Delay_req packet */ -+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); -+ break; -+ -+ /* PTP v2/802.AS1, any layer, any kind of event packet */ -+ case HWTSTAMP_FILTER_PTP_V2_EVENT: -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); -+ break; -+ -+ /* PTP v2/802.AS1, any layer, Sync packet */ -+ case HWTSTAMP_FILTER_PTP_V2_SYNC: -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); -+ break; -+ -+ /* PTP v2/802.AS1, any layer, Delay_req packet */ -+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); -+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); -+ break; -+ -+ default: -+ return -ERANGE; -+ } -+ -+ pdata->hw_if.config_tstamp(pdata, mac_tscr); -+ -+ memcpy(&pdata->tstamp_config, &config, sizeof(config)); -+ -+ return 0; -+} -+ -+static void xgbe_prep_tx_tstamp(struct xgbe_prv_data *pdata, -+ struct sk_buff *skb, -+ struct xgbe_packet_data *packet) -+{ -+ unsigned long flags; -+ -+ if (XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP)) { -+ spin_lock_irqsave(&pdata->tstamp_lock, flags); -+ if (pdata->tx_tstamp_skb) { -+ /* Another timestamp in progress, ignore this one */ -+ XGMAC_SET_BITS(packet->attributes, -+ TX_PACKET_ATTRIBUTES, PTP, 0); -+ } else { -+ pdata->tx_tstamp_skb = skb_get(skb); -+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; -+ } -+ spin_unlock_irqrestore(&pdata->tstamp_lock, flags); -+ } -+ -+ if (!XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP)) -+ skb_tx_timestamp(skb); -+} -+ -+static void xgbe_prep_vlan(struct sk_buff *skb, struct xgbe_packet_data *packet) -+{ -+ if (skb_vlan_tag_present(skb)) -+ packet->vlan_ctag = skb_vlan_tag_get(skb); -+} -+ -+static int xgbe_prep_tso(struct sk_buff *skb, struct xgbe_packet_data *packet) -+{ -+ int ret; -+ -+ if (!XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, -+ TSO_ENABLE)) -+ return 0; -+ -+ ret = skb_cow_head(skb, 0); -+ if (ret) -+ return ret; -+ -+ packet->header_len = skb_transport_offset(skb) + tcp_hdrlen(skb); -+ packet->tcp_header_len = tcp_hdrlen(skb); -+ packet->tcp_payload_len = skb->len - packet->header_len; -+ packet->mss = skb_shinfo(skb)->gso_size; -+ DBGPR(" packet->header_len=%u\n", packet->header_len); -+ DBGPR(" packet->tcp_header_len=%u, packet->tcp_payload_len=%u\n", -+ packet->tcp_header_len, packet->tcp_payload_len); -+ DBGPR(" packet->mss=%u\n", packet->mss); -+ -+ /* Update the number of packets that will ultimately be transmitted -+ * along with the extra bytes for each extra packet -+ */ -+ packet->tx_packets = skb_shinfo(skb)->gso_segs; -+ packet->tx_bytes += (packet->tx_packets - 1) * packet->header_len; -+ -+ return 0; -+} -+ -+static int xgbe_is_tso(struct sk_buff *skb) -+{ -+ if (skb->ip_summed != CHECKSUM_PARTIAL) -+ return 0; -+ -+ if (!skb_is_gso(skb)) -+ return 0; -+ -+ DBGPR(" TSO packet to be processed\n"); -+ -+ return 1; -+} -+ -+static void xgbe_packet_info(struct xgbe_prv_data *pdata, -+ struct xgbe_ring *ring, struct sk_buff *skb, -+ struct xgbe_packet_data *packet) -+{ -+ struct skb_frag_struct *frag; -+ unsigned int context_desc; -+ unsigned int len; -+ unsigned int i; -+ -+ packet->skb = skb; -+ -+ context_desc = 0; -+ packet->rdesc_count = 0; -+ -+ packet->tx_packets = 1; -+ packet->tx_bytes = skb->len; -+ -+ if (xgbe_is_tso(skb)) { -+ /* TSO requires an extra descriptor if mss is different */ -+ if (skb_shinfo(skb)->gso_size != ring->tx.cur_mss) { -+ context_desc = 1; -+ packet->rdesc_count++; -+ } -+ -+ /* TSO requires an extra descriptor for TSO header */ -+ packet->rdesc_count++; -+ -+ XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, -+ TSO_ENABLE, 1); -+ XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, -+ CSUM_ENABLE, 1); -+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) -+ XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, -+ CSUM_ENABLE, 1); -+ -+ if (skb_vlan_tag_present(skb)) { -+ /* VLAN requires an extra descriptor if tag is different */ -+ if (skb_vlan_tag_get(skb) != ring->tx.cur_vlan_ctag) -+ /* We can share with the TSO context descriptor */ -+ if (!context_desc) { -+ context_desc = 1; -+ packet->rdesc_count++; -+ } -+ -+ XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, -+ VLAN_CTAG, 1); -+ } -+ -+ if ((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && -+ (pdata->tstamp_config.tx_type == HWTSTAMP_TX_ON)) -+ XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, -+ PTP, 1); -+ -+ for (len = skb_headlen(skb); len;) { -+ packet->rdesc_count++; -+ len -= min_t(unsigned int, len, XGBE_TX_MAX_BUF_SIZE); -+ } -+ -+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { -+ frag = &skb_shinfo(skb)->frags[i]; -+ for (len = skb_frag_size(frag); len; ) { -+ packet->rdesc_count++; -+ len -= min_t(unsigned int, len, XGBE_TX_MAX_BUF_SIZE); -+ } -+ } -+} -+ -+static int xgbe_open(struct net_device *netdev) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct xgbe_desc_if *desc_if = &pdata->desc_if; -+ int ret; -+ -+ DBGPR("-->xgbe_open\n"); -+ -+ /* Initialize the phy */ -+ ret = xgbe_phy_init(pdata); -+ if (ret) -+ return ret; -+ -+ /* Enable the clocks */ -+ ret = clk_prepare_enable(pdata->sysclk); -+ if (ret) { -+ netdev_alert(netdev, "dma clk_prepare_enable failed\n"); -+ goto err_phy_init; -+ } -+ -+ ret = clk_prepare_enable(pdata->ptpclk); -+ if (ret) { -+ netdev_alert(netdev, "ptp clk_prepare_enable failed\n"); -+ goto err_sysclk; -+ } -+ -+ /* Calculate the Rx buffer size before allocating rings */ -+ ret = xgbe_calc_rx_buf_size(netdev, netdev->mtu); -+ if (ret < 0) -+ goto err_ptpclk; -+ pdata->rx_buf_size = ret; -+ -+ /* Allocate the channel and ring structures */ -+ ret = xgbe_alloc_channels(pdata); -+ if (ret) -+ goto err_ptpclk; -+ -+ /* Allocate the ring descriptors and buffers */ -+ ret = desc_if->alloc_ring_resources(pdata); -+ if (ret) -+ goto err_channels; -+ -+ /* Initialize the device restart and Tx timestamp work struct */ -+ INIT_WORK(&pdata->restart_work, xgbe_restart); -+ INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp); -+ -+ ret = xgbe_start(pdata); -+ if (ret) -+ goto err_rings; -+ -+ DBGPR("<--xgbe_open\n"); -+ -+ return 0; -+ -+err_rings: -+ desc_if->free_ring_resources(pdata); -+ -+err_channels: -+ xgbe_free_channels(pdata); -+ -+err_ptpclk: -+ clk_disable_unprepare(pdata->ptpclk); -+ -+err_sysclk: -+ clk_disable_unprepare(pdata->sysclk); -+ -+err_phy_init: -+ xgbe_phy_exit(pdata); -+ -+ return ret; -+} -+ -+static int xgbe_close(struct net_device *netdev) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct xgbe_desc_if *desc_if = &pdata->desc_if; -+ -+ DBGPR("-->xgbe_close\n"); -+ -+ /* Stop the device */ -+ xgbe_stop(pdata); -+ -+ /* Free the ring descriptors and buffers */ -+ desc_if->free_ring_resources(pdata); -+ -+ /* Free the channel and ring structures */ -+ xgbe_free_channels(pdata); -+ -+ /* Disable the clocks */ -+ clk_disable_unprepare(pdata->ptpclk); -+ clk_disable_unprepare(pdata->sysclk); -+ -+ /* Release the phy */ -+ xgbe_phy_exit(pdata); -+ -+ DBGPR("<--xgbe_close\n"); -+ -+ return 0; -+} -+ -+static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ struct xgbe_desc_if *desc_if = &pdata->desc_if; -+ struct xgbe_channel *channel; -+ struct xgbe_ring *ring; -+ struct xgbe_packet_data *packet; -+ struct netdev_queue *txq; -+ int ret; -+ -+ DBGPR("-->xgbe_xmit: skb->len = %d\n", skb->len); -+ -+ channel = pdata->channel + skb->queue_mapping; -+ txq = netdev_get_tx_queue(netdev, channel->queue_index); -+ ring = channel->tx_ring; -+ packet = &ring->packet_data; -+ -+ ret = NETDEV_TX_OK; -+ -+ if (skb->len == 0) { -+ netdev_err(netdev, "empty skb received from stack\n"); -+ dev_kfree_skb_any(skb); -+ goto tx_netdev_return; -+ } -+ -+ /* Calculate preliminary packet info */ -+ memset(packet, 0, sizeof(*packet)); -+ xgbe_packet_info(pdata, ring, skb, packet); -+ -+ /* Check that there are enough descriptors available */ -+ ret = xgbe_maybe_stop_tx_queue(channel, ring, packet->rdesc_count); -+ if (ret) -+ goto tx_netdev_return; -+ -+ ret = xgbe_prep_tso(skb, packet); -+ if (ret) { -+ netdev_err(netdev, "error processing TSO packet\n"); -+ dev_kfree_skb_any(skb); -+ goto tx_netdev_return; -+ } -+ xgbe_prep_vlan(skb, packet); -+ -+ if (!desc_if->map_tx_skb(channel, skb)) { -+ dev_kfree_skb_any(skb); -+ goto tx_netdev_return; -+ } -+ -+ xgbe_prep_tx_tstamp(pdata, skb, packet); -+ -+ /* Report on the actual number of bytes (to be) sent */ -+ netdev_tx_sent_queue(txq, packet->tx_bytes); -+ -+ /* Configure required descriptor fields for transmission */ -+ hw_if->dev_xmit(channel); -+ -+#ifdef XGMAC_ENABLE_TX_PKT_DUMP -+ xgbe_a0_print_pkt(netdev, skb, true); -+#endif -+ -+ /* Stop the queue in advance if there may not be enough descriptors */ -+ xgbe_maybe_stop_tx_queue(channel, ring, XGBE_TX_MAX_DESCS); -+ -+ ret = NETDEV_TX_OK; -+ -+tx_netdev_return: -+ return ret; -+} -+ -+static void xgbe_set_rx_mode(struct net_device *netdev) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ unsigned int pr_mode, am_mode; -+ -+ DBGPR("-->xgbe_set_rx_mode\n"); -+ -+ pr_mode = ((netdev->flags & IFF_PROMISC) != 0); -+ am_mode = ((netdev->flags & IFF_ALLMULTI) != 0); -+ -+ hw_if->set_promiscuous_mode(pdata, pr_mode); -+ hw_if->set_all_multicast_mode(pdata, am_mode); -+ -+ hw_if->add_mac_addresses(pdata); -+ -+ DBGPR("<--xgbe_set_rx_mode\n"); -+} -+ -+static int xgbe_set_mac_address(struct net_device *netdev, void *addr) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ struct sockaddr *saddr = addr; -+ -+ DBGPR("-->xgbe_set_mac_address\n"); -+ -+ if (!is_valid_ether_addr(saddr->sa_data)) -+ return -EADDRNOTAVAIL; -+ -+ memcpy(netdev->dev_addr, saddr->sa_data, netdev->addr_len); -+ -+ hw_if->set_mac_address(pdata, netdev->dev_addr); -+ -+ DBGPR("<--xgbe_set_mac_address\n"); -+ -+ return 0; -+} -+ -+static int xgbe_ioctl(struct net_device *netdev, struct ifreq *ifreq, int cmd) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ int ret; -+ -+ switch (cmd) { -+ case SIOCGHWTSTAMP: -+ ret = xgbe_get_hwtstamp_settings(pdata, ifreq); -+ break; -+ -+ case SIOCSHWTSTAMP: -+ ret = xgbe_set_hwtstamp_settings(pdata, ifreq); -+ break; -+ -+ default: -+ ret = -EOPNOTSUPP; -+ } -+ -+ return ret; -+} -+ -+static int xgbe_change_mtu(struct net_device *netdev, int mtu) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ int ret; -+ -+ DBGPR("-->xgbe_change_mtu\n"); -+ -+ ret = xgbe_calc_rx_buf_size(netdev, mtu); -+ if (ret < 0) -+ return ret; -+ -+ pdata->rx_buf_size = ret; -+ netdev->mtu = mtu; -+ -+ xgbe_restart_dev(pdata); -+ -+ DBGPR("<--xgbe_change_mtu\n"); -+ -+ return 0; -+} -+ -+static struct rtnl_link_stats64 *xgbe_get_stats64(struct net_device *netdev, -+ struct rtnl_link_stats64 *s) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct xgbe_mmc_stats *pstats = &pdata->mmc_stats; -+ -+ DBGPR("-->%s\n", __func__); -+ -+ pdata->hw_if.read_mmc_stats(pdata); -+ -+ s->rx_packets = pstats->rxframecount_gb; -+ s->rx_bytes = pstats->rxoctetcount_gb; -+ s->rx_errors = pstats->rxframecount_gb - -+ pstats->rxbroadcastframes_g - -+ pstats->rxmulticastframes_g - -+ pstats->rxunicastframes_g; -+ s->multicast = pstats->rxmulticastframes_g; -+ s->rx_length_errors = pstats->rxlengtherror; -+ s->rx_crc_errors = pstats->rxcrcerror; -+ s->rx_fifo_errors = pstats->rxfifooverflow; -+ -+ s->tx_packets = pstats->txframecount_gb; -+ s->tx_bytes = pstats->txoctetcount_gb; -+ s->tx_errors = pstats->txframecount_gb - pstats->txframecount_g; -+ s->tx_dropped = netdev->stats.tx_dropped; -+ -+ DBGPR("<--%s\n", __func__); -+ -+ return s; -+} -+ -+static int xgbe_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, -+ u16 vid) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ -+ DBGPR("-->%s\n", __func__); -+ -+ set_bit(vid, pdata->active_vlans); -+ hw_if->update_vlan_hash_table(pdata); -+ -+ DBGPR("<--%s\n", __func__); -+ -+ return 0; -+} -+ -+static int xgbe_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, -+ u16 vid) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ -+ DBGPR("-->%s\n", __func__); -+ -+ clear_bit(vid, pdata->active_vlans); -+ hw_if->update_vlan_hash_table(pdata); -+ -+ DBGPR("<--%s\n", __func__); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_NET_POLL_CONTROLLER -+static void xgbe_poll_controller(struct net_device *netdev) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ DBGPR("-->xgbe_poll_controller\n"); -+ -+ if (pdata->per_channel_irq) { -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) -+ xgbe_dma_isr(channel->dma_irq, channel); -+ } else { -+ disable_irq(pdata->dev_irq); -+ xgbe_isr(pdata->dev_irq, pdata); -+ enable_irq(pdata->dev_irq); -+ } -+ -+ DBGPR("<--xgbe_poll_controller\n"); -+} -+#endif /* End CONFIG_NET_POLL_CONTROLLER */ -+ -+static int xgbe_setup_tc(struct net_device *netdev, u8 tc) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ unsigned int offset, queue; -+ u8 i; -+ -+ if (tc && (tc != pdata->hw_feat.tc_cnt)) -+ return -EINVAL; -+ -+ if (tc) { -+ netdev_set_num_tc(netdev, tc); -+ for (i = 0, queue = 0, offset = 0; i < tc; i++) { -+ while ((queue < pdata->tx_q_count) && -+ (pdata->q2tc_map[queue] == i)) -+ queue++; -+ -+ DBGPR(" TC%u using TXq%u-%u\n", i, offset, queue - 1); -+ netdev_set_tc_queue(netdev, i, queue - offset, offset); -+ offset = queue; -+ } -+ } else { -+ netdev_reset_tc(netdev); -+ } -+ -+ return 0; -+} -+ -+static int xgbe_set_features(struct net_device *netdev, -+ netdev_features_t features) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ netdev_features_t rxhash, rxcsum, rxvlan, rxvlan_filter; -+ int ret = 0; -+ -+ rxhash = pdata->netdev_features & NETIF_F_RXHASH; -+ rxcsum = pdata->netdev_features & NETIF_F_RXCSUM; -+ rxvlan = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_RX; -+ rxvlan_filter = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_FILTER; -+ -+ if ((features & NETIF_F_RXHASH) && !rxhash) -+ ret = hw_if->enable_rss(pdata); -+ else if (!(features & NETIF_F_RXHASH) && rxhash) -+ ret = hw_if->disable_rss(pdata); -+ if (ret) -+ return ret; -+ -+ if ((features & NETIF_F_RXCSUM) && !rxcsum) -+ hw_if->enable_rx_csum(pdata); -+ else if (!(features & NETIF_F_RXCSUM) && rxcsum) -+ hw_if->disable_rx_csum(pdata); -+ -+ if ((features & NETIF_F_HW_VLAN_CTAG_RX) && !rxvlan) -+ hw_if->enable_rx_vlan_stripping(pdata); -+ else if (!(features & NETIF_F_HW_VLAN_CTAG_RX) && rxvlan) -+ hw_if->disable_rx_vlan_stripping(pdata); -+ -+ if ((features & NETIF_F_HW_VLAN_CTAG_FILTER) && !rxvlan_filter) -+ hw_if->enable_rx_vlan_filtering(pdata); -+ else if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER) && rxvlan_filter) -+ hw_if->disable_rx_vlan_filtering(pdata); -+ -+ pdata->netdev_features = features; -+ -+ DBGPR("<--xgbe_set_features\n"); -+ -+ return 0; -+} -+ -+static const struct net_device_ops xgbe_netdev_ops = { -+ .ndo_open = xgbe_open, -+ .ndo_stop = xgbe_close, -+ .ndo_start_xmit = xgbe_xmit, -+ .ndo_set_rx_mode = xgbe_set_rx_mode, -+ .ndo_set_mac_address = xgbe_set_mac_address, -+ .ndo_validate_addr = eth_validate_addr, -+ .ndo_do_ioctl = xgbe_ioctl, -+ .ndo_change_mtu = xgbe_change_mtu, -+ .ndo_get_stats64 = xgbe_get_stats64, -+ .ndo_vlan_rx_add_vid = xgbe_vlan_rx_add_vid, -+ .ndo_vlan_rx_kill_vid = xgbe_vlan_rx_kill_vid, -+#ifdef CONFIG_NET_POLL_CONTROLLER -+ .ndo_poll_controller = xgbe_poll_controller, -+#endif -+ .ndo_setup_tc = xgbe_setup_tc, -+ .ndo_set_features = xgbe_set_features, -+}; -+ -+struct net_device_ops *xgbe_a0_get_netdev_ops(void) -+{ -+ return (struct net_device_ops *)&xgbe_netdev_ops; -+} -+ -+static void xgbe_rx_refresh(struct xgbe_channel *channel) -+{ -+ struct xgbe_prv_data *pdata = channel->pdata; -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ struct xgbe_desc_if *desc_if = &pdata->desc_if; -+ struct xgbe_ring *ring = channel->rx_ring; -+ struct xgbe_ring_data *rdata; -+ -+ while (ring->dirty != ring->cur) { -+ rdata = XGBE_GET_DESC_DATA(ring, ring->dirty); -+ -+ /* Reset rdata values */ -+ desc_if->unmap_rdata(pdata, rdata); -+ -+ if (desc_if->map_rx_buffer(pdata, ring, rdata)) -+ break; -+ -+ hw_if->rx_desc_reset(rdata); -+ -+ ring->dirty++; -+ } -+ -+ /* Update the Rx Tail Pointer Register with address of -+ * the last cleaned entry */ -+ rdata = XGBE_GET_DESC_DATA(ring, ring->dirty - 1); -+ XGMAC_DMA_IOWRITE(channel, DMA_CH_RDTR_LO, -+ lower_32_bits(rdata->rdesc_dma)); -+} -+ -+static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata, -+ struct xgbe_ring_data *rdata, -+ unsigned int *len) -+{ -+ struct net_device *netdev = pdata->netdev; -+ struct sk_buff *skb; -+ u8 *packet; -+ unsigned int copy_len; -+ -+ skb = netdev_alloc_skb_ip_align(netdev, rdata->rx.hdr.dma_len); -+ if (!skb) -+ return NULL; -+ -+ packet = page_address(rdata->rx.hdr.pa.pages) + -+ rdata->rx.hdr.pa.pages_offset; -+ copy_len = (rdata->rx.hdr_len) ? rdata->rx.hdr_len : *len; -+ copy_len = min(rdata->rx.hdr.dma_len, copy_len); -+ skb_copy_to_linear_data(skb, packet, copy_len); -+ skb_put(skb, copy_len); -+ -+ *len -= copy_len; -+ -+ return skb; -+} -+ -+static int xgbe_tx_poll(struct xgbe_channel *channel) -+{ -+ struct xgbe_prv_data *pdata = channel->pdata; -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ struct xgbe_desc_if *desc_if = &pdata->desc_if; -+ struct xgbe_ring *ring = channel->tx_ring; -+ struct xgbe_ring_data *rdata; -+ struct xgbe_ring_desc *rdesc; -+ struct net_device *netdev = pdata->netdev; -+ struct netdev_queue *txq; -+ int processed = 0; -+ unsigned int tx_packets = 0, tx_bytes = 0; -+ -+ DBGPR("-->xgbe_tx_poll\n"); -+ -+ /* Nothing to do if there isn't a Tx ring for this channel */ -+ if (!ring) -+ return 0; -+ -+ txq = netdev_get_tx_queue(netdev, channel->queue_index); -+ -+ while ((processed < XGBE_TX_DESC_MAX_PROC) && -+ (ring->dirty != ring->cur)) { -+ rdata = XGBE_GET_DESC_DATA(ring, ring->dirty); -+ rdesc = rdata->rdesc; -+ -+ if (!hw_if->tx_complete(rdesc)) -+ break; -+ -+ /* Make sure descriptor fields are read after reading the OWN -+ * bit */ -+ rmb(); -+ -+#ifdef XGMAC_ENABLE_TX_DESC_DUMP -+ xgbe_a0_dump_tx_desc(ring, ring->dirty, 1, 0); -+#endif -+ -+ if (hw_if->is_last_desc(rdesc)) { -+ tx_packets += rdata->tx.packets; -+ tx_bytes += rdata->tx.bytes; -+ } -+ -+ /* Free the SKB and reset the descriptor for re-use */ -+ desc_if->unmap_rdata(pdata, rdata); -+ hw_if->tx_desc_reset(rdata); -+ -+ processed++; -+ ring->dirty++; -+ } -+ -+ if (!processed) -+ return 0; -+ -+ netdev_tx_completed_queue(txq, tx_packets, tx_bytes); -+ -+ if ((ring->tx.queue_stopped == 1) && -+ (xgbe_tx_avail_desc(ring) > XGBE_TX_DESC_MIN_FREE)) { -+ ring->tx.queue_stopped = 0; -+ netif_tx_wake_queue(txq); -+ } -+ -+ DBGPR("<--xgbe_tx_poll: processed=%d\n", processed); -+ -+ return processed; -+} -+ -+static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) -+{ -+ struct xgbe_prv_data *pdata = channel->pdata; -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ struct xgbe_ring *ring = channel->rx_ring; -+ struct xgbe_ring_data *rdata; -+ struct xgbe_packet_data *packet; -+ struct net_device *netdev = pdata->netdev; -+ struct napi_struct *napi; -+ struct sk_buff *skb; -+ struct skb_shared_hwtstamps *hwtstamps; -+ unsigned int incomplete, error, context_next, context; -+ unsigned int len, put_len, max_len; -+ unsigned int received = 0; -+ int packet_count = 0; -+ -+ DBGPR("-->xgbe_rx_poll: budget=%d\n", budget); -+ -+ /* Nothing to do if there isn't a Rx ring for this channel */ -+ if (!ring) -+ return 0; -+ -+ napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi; -+ -+ rdata = XGBE_GET_DESC_DATA(ring, ring->cur); -+ packet = &ring->packet_data; -+ while (packet_count < budget) { -+ DBGPR(" cur = %d\n", ring->cur); -+ -+ /* First time in loop see if we need to restore state */ -+ if (!received && rdata->state_saved) { -+ incomplete = rdata->state.incomplete; -+ context_next = rdata->state.context_next; -+ skb = rdata->state.skb; -+ error = rdata->state.error; -+ len = rdata->state.len; -+ } else { -+ memset(packet, 0, sizeof(*packet)); -+ incomplete = 0; -+ context_next = 0; -+ skb = NULL; -+ error = 0; -+ len = 0; -+ } -+ -+read_again: -+ rdata = XGBE_GET_DESC_DATA(ring, ring->cur); -+ -+ if (xgbe_rx_dirty_desc(ring) > (XGBE_RX_DESC_CNT >> 3)) -+ xgbe_rx_refresh(channel); -+ -+ if (hw_if->dev_read(channel)) -+ break; -+ -+ received++; -+ ring->cur++; -+ -+ incomplete = XGMAC_GET_BITS(packet->attributes, -+ RX_PACKET_ATTRIBUTES, -+ INCOMPLETE); -+ context_next = XGMAC_GET_BITS(packet->attributes, -+ RX_PACKET_ATTRIBUTES, -+ CONTEXT_NEXT); -+ context = XGMAC_GET_BITS(packet->attributes, -+ RX_PACKET_ATTRIBUTES, -+ CONTEXT); -+ -+ /* Earlier error, just drain the remaining data */ -+ if ((incomplete || context_next) && error) -+ goto read_again; -+ -+ if (error || packet->errors) { -+ if (packet->errors) -+ DBGPR("Error in received packet\n"); -+ dev_kfree_skb(skb); -+ goto next_packet; -+ } -+ -+ if (!context) { -+ put_len = rdata->rx.len - len; -+ len += put_len; -+ -+ if (!skb) { -+ dma_sync_single_for_cpu(pdata->dev, -+ rdata->rx.hdr.dma, -+ rdata->rx.hdr.dma_len, -+ DMA_FROM_DEVICE); -+ -+ skb = xgbe_create_skb(pdata, rdata, &put_len); -+ if (!skb) { -+ error = 1; -+ goto skip_data; -+ } -+ } -+ -+ if (put_len) { -+ dma_sync_single_for_cpu(pdata->dev, -+ rdata->rx.buf.dma, -+ rdata->rx.buf.dma_len, -+ DMA_FROM_DEVICE); -+ -+ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, -+ rdata->rx.buf.pa.pages, -+ rdata->rx.buf.pa.pages_offset, -+ put_len, rdata->rx.buf.dma_len); -+ rdata->rx.buf.pa.pages = NULL; -+ } -+ } -+ -+skip_data: -+ if (incomplete || context_next) -+ goto read_again; -+ -+ if (!skb) -+ goto next_packet; -+ -+ /* Be sure we don't exceed the configured MTU */ -+ max_len = netdev->mtu + ETH_HLEN; -+ if (!(netdev->features & NETIF_F_HW_VLAN_CTAG_RX) && -+ (skb->protocol == htons(ETH_P_8021Q))) -+ max_len += VLAN_HLEN; -+ -+ if (skb->len > max_len) { -+ DBGPR("packet length exceeds configured MTU\n"); -+ dev_kfree_skb(skb); -+ goto next_packet; -+ } -+ -+#ifdef XGMAC_ENABLE_RX_PKT_DUMP -+ xgbe_a0_print_pkt(netdev, skb, false); -+#endif -+ -+ skb_checksum_none_assert(skb); -+ if (XGMAC_GET_BITS(packet->attributes, -+ RX_PACKET_ATTRIBUTES, CSUM_DONE)) -+ skb->ip_summed = CHECKSUM_UNNECESSARY; -+ -+ if (XGMAC_GET_BITS(packet->attributes, -+ RX_PACKET_ATTRIBUTES, VLAN_CTAG)) -+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), -+ packet->vlan_ctag); -+ -+ if (XGMAC_GET_BITS(packet->attributes, -+ RX_PACKET_ATTRIBUTES, RX_TSTAMP)) { -+ u64 nsec; -+ -+ nsec = timecounter_cyc2time(&pdata->tstamp_tc, -+ packet->rx_tstamp); -+ hwtstamps = skb_hwtstamps(skb); -+ hwtstamps->hwtstamp = ns_to_ktime(nsec); -+ } -+ -+ if (XGMAC_GET_BITS(packet->attributes, -+ RX_PACKET_ATTRIBUTES, RSS_HASH)) -+ skb_set_hash(skb, packet->rss_hash, -+ packet->rss_hash_type); -+ -+ skb->dev = netdev; -+ skb->protocol = eth_type_trans(skb, netdev); -+ skb_record_rx_queue(skb, channel->queue_index); -+ skb_mark_napi_id(skb, napi); -+ -+ netdev->last_rx = jiffies; -+ napi_gro_receive(napi, skb); -+ -+next_packet: -+ packet_count++; -+ } -+ -+ /* Check if we need to save state before leaving */ -+ if (received && (incomplete || context_next)) { -+ rdata = XGBE_GET_DESC_DATA(ring, ring->cur); -+ rdata->state_saved = 1; -+ rdata->state.incomplete = incomplete; -+ rdata->state.context_next = context_next; -+ rdata->state.skb = skb; -+ rdata->state.len = len; -+ rdata->state.error = error; -+ } -+ -+ DBGPR("<--xgbe_rx_poll: packet_count = %d\n", packet_count); -+ -+ return packet_count; -+} -+ -+static int xgbe_one_poll(struct napi_struct *napi, int budget) -+{ -+ struct xgbe_channel *channel = container_of(napi, struct xgbe_channel, -+ napi); -+ int processed = 0; -+ -+ DBGPR("-->xgbe_one_poll: budget=%d\n", budget); -+ -+ /* Cleanup Tx ring first */ -+ xgbe_tx_poll(channel); -+ -+ /* Process Rx ring next */ -+ processed = xgbe_rx_poll(channel, budget); -+ -+ /* If we processed everything, we are done */ -+ if (processed < budget) { -+ /* Turn off polling */ -+ napi_complete(napi); -+ -+ /* Enable Tx and Rx interrupts */ -+ enable_irq(channel->dma_irq); -+ } -+ -+ DBGPR("<--xgbe_one_poll: received = %d\n", processed); -+ -+ return processed; -+} -+ -+static int xgbe_all_poll(struct napi_struct *napi, int budget) -+{ -+ struct xgbe_prv_data *pdata = container_of(napi, struct xgbe_prv_data, -+ napi); -+ struct xgbe_channel *channel; -+ int ring_budget; -+ int processed, last_processed; -+ unsigned int i; -+ -+ DBGPR("-->xgbe_all_poll: budget=%d\n", budget); -+ -+ processed = 0; -+ ring_budget = budget / pdata->rx_ring_count; -+ do { -+ last_processed = processed; -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ /* Cleanup Tx ring first */ -+ xgbe_tx_poll(channel); -+ -+ /* Process Rx ring next */ -+ if (ring_budget > (budget - processed)) -+ ring_budget = budget - processed; -+ processed += xgbe_rx_poll(channel, ring_budget); -+ } -+ } while ((processed < budget) && (processed != last_processed)); -+ -+ /* If we processed everything, we are done */ -+ if (processed < budget) { -+ /* Turn off polling */ -+ napi_complete(napi); -+ -+ /* Enable Tx and Rx interrupts */ -+ xgbe_enable_rx_tx_ints(pdata); -+ } -+ -+ DBGPR("<--xgbe_all_poll: received = %d\n", processed); -+ -+ return processed; -+} -+ -+void xgbe_a0_dump_tx_desc(struct xgbe_ring *ring, unsigned int idx, -+ unsigned int count, unsigned int flag) -+{ -+ struct xgbe_ring_data *rdata; -+ struct xgbe_ring_desc *rdesc; -+ -+ while (count--) { -+ rdata = XGBE_GET_DESC_DATA(ring, idx); -+ rdesc = rdata->rdesc; -+ pr_alert("TX_NORMAL_DESC[%d %s] = %08x:%08x:%08x:%08x\n", idx, -+ (flag == 1) ? "QUEUED FOR TX" : "TX BY DEVICE", -+ le32_to_cpu(rdesc->desc0), le32_to_cpu(rdesc->desc1), -+ le32_to_cpu(rdesc->desc2), le32_to_cpu(rdesc->desc3)); -+ idx++; -+ } -+} -+ -+void xgbe_a0_dump_rx_desc(struct xgbe_ring *ring, struct xgbe_ring_desc *desc, -+ unsigned int idx) -+{ -+ pr_alert("RX_NORMAL_DESC[%d RX BY DEVICE] = %08x:%08x:%08x:%08x\n", idx, -+ le32_to_cpu(desc->desc0), le32_to_cpu(desc->desc1), -+ le32_to_cpu(desc->desc2), le32_to_cpu(desc->desc3)); -+} -+ -+void xgbe_a0_print_pkt(struct net_device *netdev, struct sk_buff *skb, bool tx_rx) -+{ -+ struct ethhdr *eth = (struct ethhdr *)skb->data; -+ unsigned char *buf = skb->data; -+ unsigned char buffer[128]; -+ unsigned int i, j; -+ -+ netdev_alert(netdev, "\n************** SKB dump ****************\n"); -+ -+ netdev_alert(netdev, "%s packet of %d bytes\n", -+ (tx_rx ? "TX" : "RX"), skb->len); -+ -+ netdev_alert(netdev, "Dst MAC addr: %pM\n", eth->h_dest); -+ netdev_alert(netdev, "Src MAC addr: %pM\n", eth->h_source); -+ netdev_alert(netdev, "Protocol: 0x%04hx\n", ntohs(eth->h_proto)); -+ -+ for (i = 0, j = 0; i < skb->len;) { -+ j += snprintf(buffer + j, sizeof(buffer) - j, "%02hhx", -+ buf[i++]); -+ -+ if ((i % 32) == 0) { -+ netdev_alert(netdev, " 0x%04x: %s\n", i - 32, buffer); -+ j = 0; -+ } else if ((i % 16) == 0) { -+ buffer[j++] = ' '; -+ buffer[j++] = ' '; -+ } else if ((i % 4) == 0) { -+ buffer[j++] = ' '; -+ } -+ } -+ if (i % 32) -+ netdev_alert(netdev, " 0x%04x: %s\n", i - (i % 32), buffer); -+ -+ netdev_alert(netdev, "\n************** SKB dump ****************\n"); -+} -diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-ethtool.c -new file mode 100644 -index 0000000..165ff1c ---- /dev/null -+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-ethtool.c -@@ -0,0 +1,616 @@ -+/* -+ * AMD 10Gb Ethernet driver -+ * -+ * This file is available to you under your choice of the following two -+ * licenses: -+ * -+ * License 1: GPLv2 -+ * -+ * Copyright (c) 2014 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 . -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * -+ * License 2: Modified BSD -+ * -+ * Copyright (c) 2014 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 BE LIABLE FOR ANY -+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include -+ -+#include "xgbe.h" -+#include "xgbe-common.h" -+ -+struct xgbe_stats { -+ char stat_string[ETH_GSTRING_LEN]; -+ int stat_size; -+ int stat_offset; -+}; -+ -+#define XGMAC_MMC_STAT(_string, _var) \ -+ { _string, \ -+ FIELD_SIZEOF(struct xgbe_mmc_stats, _var), \ -+ offsetof(struct xgbe_prv_data, mmc_stats._var), \ -+ } -+ -+static const struct xgbe_stats xgbe_gstring_stats[] = { -+ XGMAC_MMC_STAT("tx_bytes", txoctetcount_gb), -+ XGMAC_MMC_STAT("tx_packets", txframecount_gb), -+ XGMAC_MMC_STAT("tx_unicast_packets", txunicastframes_gb), -+ XGMAC_MMC_STAT("tx_broadcast_packets", txbroadcastframes_gb), -+ XGMAC_MMC_STAT("tx_multicast_packets", txmulticastframes_gb), -+ XGMAC_MMC_STAT("tx_vlan_packets", txvlanframes_g), -+ XGMAC_MMC_STAT("tx_64_byte_packets", tx64octets_gb), -+ XGMAC_MMC_STAT("tx_65_to_127_byte_packets", tx65to127octets_gb), -+ XGMAC_MMC_STAT("tx_128_to_255_byte_packets", tx128to255octets_gb), -+ XGMAC_MMC_STAT("tx_256_to_511_byte_packets", tx256to511octets_gb), -+ XGMAC_MMC_STAT("tx_512_to_1023_byte_packets", tx512to1023octets_gb), -+ XGMAC_MMC_STAT("tx_1024_to_max_byte_packets", tx1024tomaxoctets_gb), -+ XGMAC_MMC_STAT("tx_underflow_errors", txunderflowerror), -+ XGMAC_MMC_STAT("tx_pause_frames", txpauseframes), -+ -+ XGMAC_MMC_STAT("rx_bytes", rxoctetcount_gb), -+ XGMAC_MMC_STAT("rx_packets", rxframecount_gb), -+ XGMAC_MMC_STAT("rx_unicast_packets", rxunicastframes_g), -+ XGMAC_MMC_STAT("rx_broadcast_packets", rxbroadcastframes_g), -+ XGMAC_MMC_STAT("rx_multicast_packets", rxmulticastframes_g), -+ XGMAC_MMC_STAT("rx_vlan_packets", rxvlanframes_gb), -+ XGMAC_MMC_STAT("rx_64_byte_packets", rx64octets_gb), -+ XGMAC_MMC_STAT("rx_65_to_127_byte_packets", rx65to127octets_gb), -+ XGMAC_MMC_STAT("rx_128_to_255_byte_packets", rx128to255octets_gb), -+ XGMAC_MMC_STAT("rx_256_to_511_byte_packets", rx256to511octets_gb), -+ XGMAC_MMC_STAT("rx_512_to_1023_byte_packets", rx512to1023octets_gb), -+ XGMAC_MMC_STAT("rx_1024_to_max_byte_packets", rx1024tomaxoctets_gb), -+ XGMAC_MMC_STAT("rx_undersize_packets", rxundersize_g), -+ XGMAC_MMC_STAT("rx_oversize_packets", rxoversize_g), -+ XGMAC_MMC_STAT("rx_crc_errors", rxcrcerror), -+ XGMAC_MMC_STAT("rx_crc_errors_small_packets", rxrunterror), -+ XGMAC_MMC_STAT("rx_crc_errors_giant_packets", rxjabbererror), -+ XGMAC_MMC_STAT("rx_length_errors", rxlengtherror), -+ XGMAC_MMC_STAT("rx_out_of_range_errors", rxoutofrangetype), -+ XGMAC_MMC_STAT("rx_fifo_overflow_errors", rxfifooverflow), -+ XGMAC_MMC_STAT("rx_watchdog_errors", rxwatchdogerror), -+ XGMAC_MMC_STAT("rx_pause_frames", rxpauseframes), -+}; -+ -+#define XGBE_STATS_COUNT ARRAY_SIZE(xgbe_gstring_stats) -+ -+static void xgbe_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -+{ -+ int i; -+ -+ DBGPR("-->%s\n", __func__); -+ -+ switch (stringset) { -+ case ETH_SS_STATS: -+ for (i = 0; i < XGBE_STATS_COUNT; i++) { -+ memcpy(data, xgbe_gstring_stats[i].stat_string, -+ ETH_GSTRING_LEN); -+ data += ETH_GSTRING_LEN; -+ } -+ break; -+ } -+ -+ DBGPR("<--%s\n", __func__); -+} -+ -+static void xgbe_get_ethtool_stats(struct net_device *netdev, -+ struct ethtool_stats *stats, u64 *data) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ u8 *stat; -+ int i; -+ -+ DBGPR("-->%s\n", __func__); -+ -+ pdata->hw_if.read_mmc_stats(pdata); -+ for (i = 0; i < XGBE_STATS_COUNT; i++) { -+ stat = (u8 *)pdata + xgbe_gstring_stats[i].stat_offset; -+ *data++ = *(u64 *)stat; -+ } -+ -+ DBGPR("<--%s\n", __func__); -+} -+ -+static int xgbe_get_sset_count(struct net_device *netdev, int stringset) -+{ -+ int ret; -+ -+ DBGPR("-->%s\n", __func__); -+ -+ switch (stringset) { -+ case ETH_SS_STATS: -+ ret = XGBE_STATS_COUNT; -+ break; -+ -+ default: -+ ret = -EOPNOTSUPP; -+ } -+ -+ DBGPR("<--%s\n", __func__); -+ -+ return ret; -+} -+ -+static void xgbe_get_pauseparam(struct net_device *netdev, -+ struct ethtool_pauseparam *pause) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ -+ DBGPR("-->xgbe_get_pauseparam\n"); -+ -+ pause->autoneg = pdata->pause_autoneg; -+ pause->tx_pause = pdata->tx_pause; -+ pause->rx_pause = pdata->rx_pause; -+ -+ DBGPR("<--xgbe_get_pauseparam\n"); -+} -+ -+static int xgbe_set_pauseparam(struct net_device *netdev, -+ struct ethtool_pauseparam *pause) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct phy_device *phydev = pdata->phydev; -+ int ret = 0; -+ -+ DBGPR("-->xgbe_set_pauseparam\n"); -+ -+ DBGPR(" autoneg = %d, tx_pause = %d, rx_pause = %d\n", -+ pause->autoneg, pause->tx_pause, pause->rx_pause); -+ -+ pdata->pause_autoneg = pause->autoneg; -+ if (pause->autoneg) { -+ phydev->advertising |= ADVERTISED_Pause; -+ phydev->advertising |= ADVERTISED_Asym_Pause; -+ -+ } else { -+ phydev->advertising &= ~ADVERTISED_Pause; -+ phydev->advertising &= ~ADVERTISED_Asym_Pause; -+ -+ pdata->tx_pause = pause->tx_pause; -+ pdata->rx_pause = pause->rx_pause; -+ } -+ -+ if (netif_running(netdev)) -+ ret = phy_start_aneg(phydev); -+ -+ DBGPR("<--xgbe_set_pauseparam\n"); -+ -+ return ret; -+} -+ -+static int xgbe_get_settings(struct net_device *netdev, -+ struct ethtool_cmd *cmd) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ int ret; -+ -+ DBGPR("-->xgbe_get_settings\n"); -+ -+ if (!pdata->phydev) -+ return -ENODEV; -+ -+ ret = phy_ethtool_gset(pdata->phydev, cmd); -+ cmd->transceiver = XCVR_EXTERNAL; -+ -+ DBGPR("<--xgbe_get_settings\n"); -+ -+ return ret; -+} -+ -+static int xgbe_set_settings(struct net_device *netdev, -+ struct ethtool_cmd *cmd) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct phy_device *phydev = pdata->phydev; -+ u32 speed; -+ int ret; -+ -+ DBGPR("-->xgbe_set_settings\n"); -+ -+ if (!pdata->phydev) -+ return -ENODEV; -+ -+ speed = ethtool_cmd_speed(cmd); -+ -+ if (cmd->phy_address != phydev->addr) -+ return -EINVAL; -+ -+ if ((cmd->autoneg != AUTONEG_ENABLE) && -+ (cmd->autoneg != AUTONEG_DISABLE)) -+ return -EINVAL; -+ -+ if (cmd->autoneg == AUTONEG_DISABLE) { -+ switch (speed) { -+ case SPEED_10000: -+ case SPEED_2500: -+ case SPEED_1000: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ if (cmd->duplex != DUPLEX_FULL) -+ return -EINVAL; -+ } -+ -+ cmd->advertising &= phydev->supported; -+ if ((cmd->autoneg == AUTONEG_ENABLE) && !cmd->advertising) -+ return -EINVAL; -+ -+ ret = 0; -+ phydev->autoneg = cmd->autoneg; -+ phydev->speed = speed; -+ phydev->duplex = cmd->duplex; -+ phydev->advertising = cmd->advertising; -+ -+ if (cmd->autoneg == AUTONEG_ENABLE) -+ phydev->advertising |= ADVERTISED_Autoneg; -+ else -+ phydev->advertising &= ~ADVERTISED_Autoneg; -+ -+ if (netif_running(netdev)) -+ ret = phy_start_aneg(phydev); -+ -+ DBGPR("<--xgbe_set_settings\n"); -+ -+ return ret; -+} -+ -+static void xgbe_get_drvinfo(struct net_device *netdev, -+ struct ethtool_drvinfo *drvinfo) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct xgbe_hw_features *hw_feat = &pdata->hw_feat; -+ -+ strlcpy(drvinfo->driver, XGBE_DRV_NAME, sizeof(drvinfo->driver)); -+ strlcpy(drvinfo->version, XGBE_DRV_VERSION, sizeof(drvinfo->version)); -+ strlcpy(drvinfo->bus_info, dev_name(pdata->dev), -+ sizeof(drvinfo->bus_info)); -+ snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%d.%d.%d", -+ XGMAC_GET_BITS(hw_feat->version, MAC_VR, USERVER), -+ XGMAC_GET_BITS(hw_feat->version, MAC_VR, DEVID), -+ XGMAC_GET_BITS(hw_feat->version, MAC_VR, SNPSVER)); -+ drvinfo->n_stats = XGBE_STATS_COUNT; -+} -+ -+static int xgbe_get_coalesce(struct net_device *netdev, -+ struct ethtool_coalesce *ec) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ unsigned int riwt; -+ -+ DBGPR("-->xgbe_get_coalesce\n"); -+ -+ memset(ec, 0, sizeof(struct ethtool_coalesce)); -+ -+ riwt = pdata->rx_riwt; -+ ec->rx_coalesce_usecs = hw_if->riwt_to_usec(pdata, riwt); -+ ec->rx_max_coalesced_frames = pdata->rx_frames; -+ -+ ec->tx_coalesce_usecs = pdata->tx_usecs; -+ ec->tx_max_coalesced_frames = pdata->tx_frames; -+ -+ DBGPR("<--xgbe_get_coalesce\n"); -+ -+ return 0; -+} -+ -+static int xgbe_set_coalesce(struct net_device *netdev, -+ struct ethtool_coalesce *ec) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ unsigned int rx_frames, rx_riwt, rx_usecs; -+ unsigned int tx_frames, tx_usecs; -+ -+ DBGPR("-->xgbe_set_coalesce\n"); -+ -+ /* Check for not supported parameters */ -+ if ((ec->rx_coalesce_usecs_irq) || -+ (ec->rx_max_coalesced_frames_irq) || -+ (ec->tx_coalesce_usecs_irq) || -+ (ec->tx_max_coalesced_frames_irq) || -+ (ec->stats_block_coalesce_usecs) || -+ (ec->use_adaptive_rx_coalesce) || -+ (ec->use_adaptive_tx_coalesce) || -+ (ec->pkt_rate_low) || -+ (ec->rx_coalesce_usecs_low) || -+ (ec->rx_max_coalesced_frames_low) || -+ (ec->tx_coalesce_usecs_low) || -+ (ec->tx_max_coalesced_frames_low) || -+ (ec->pkt_rate_high) || -+ (ec->rx_coalesce_usecs_high) || -+ (ec->rx_max_coalesced_frames_high) || -+ (ec->tx_coalesce_usecs_high) || -+ (ec->tx_max_coalesced_frames_high) || -+ (ec->rate_sample_interval)) -+ return -EOPNOTSUPP; -+ -+ /* Can only change rx-frames when interface is down (see -+ * rx_descriptor_init in xgbe-dev.c) -+ */ -+ rx_frames = pdata->rx_frames; -+ if (rx_frames != ec->rx_max_coalesced_frames && netif_running(netdev)) { -+ netdev_alert(netdev, -+ "interface must be down to change rx-frames\n"); -+ return -EINVAL; -+ } -+ -+ rx_riwt = hw_if->usec_to_riwt(pdata, ec->rx_coalesce_usecs); -+ rx_frames = ec->rx_max_coalesced_frames; -+ -+ /* Use smallest possible value if conversion resulted in zero */ -+ if (ec->rx_coalesce_usecs && !rx_riwt) -+ rx_riwt = 1; -+ -+ /* Check the bounds of values for Rx */ -+ if (rx_riwt > XGMAC_MAX_DMA_RIWT) { -+ rx_usecs = hw_if->riwt_to_usec(pdata, XGMAC_MAX_DMA_RIWT); -+ netdev_alert(netdev, "rx-usec is limited to %d usecs\n", -+ rx_usecs); -+ return -EINVAL; -+ } -+ if (rx_frames > pdata->rx_desc_count) { -+ netdev_alert(netdev, "rx-frames is limited to %d frames\n", -+ pdata->rx_desc_count); -+ return -EINVAL; -+ } -+ -+ tx_usecs = ec->tx_coalesce_usecs; -+ tx_frames = ec->tx_max_coalesced_frames; -+ -+ /* Check the bounds of values for Tx */ -+ if (tx_frames > pdata->tx_desc_count) { -+ netdev_alert(netdev, "tx-frames is limited to %d frames\n", -+ pdata->tx_desc_count); -+ return -EINVAL; -+ } -+ -+ pdata->rx_riwt = rx_riwt; -+ pdata->rx_frames = rx_frames; -+ hw_if->config_rx_coalesce(pdata); -+ -+ pdata->tx_usecs = tx_usecs; -+ pdata->tx_frames = tx_frames; -+ hw_if->config_tx_coalesce(pdata); -+ -+ DBGPR("<--xgbe_set_coalesce\n"); -+ -+ return 0; -+} -+ -+static int xgbe_get_rxnfc(struct net_device *netdev, -+ struct ethtool_rxnfc *rxnfc, u32 *rule_locs) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ -+ switch (rxnfc->cmd) { -+ case ETHTOOL_GRXRINGS: -+ rxnfc->data = pdata->rx_ring_count; -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ -+ return 0; -+} -+ -+static u32 xgbe_get_rxfh_key_size(struct net_device *netdev) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ -+ return sizeof(pdata->rss_key); -+} -+ -+static u32 xgbe_get_rxfh_indir_size(struct net_device *netdev) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ -+ return ARRAY_SIZE(pdata->rss_table); -+} -+ -+static int xgbe_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, -+ u8 *hfunc) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ unsigned int i; -+ -+ if (indir) { -+ for (i = 0; i < ARRAY_SIZE(pdata->rss_table); i++) -+ indir[i] = XGMAC_GET_BITS(pdata->rss_table[i], -+ MAC_RSSDR, DMCH); -+ } -+ -+ if (key) -+ memcpy(key, pdata->rss_key, sizeof(pdata->rss_key)); -+ -+ if (hfunc) -+ *hfunc = ETH_RSS_HASH_TOP; -+ -+ return 0; -+} -+ -+static int xgbe_set_rxfh(struct net_device *netdev, const u32 *indir, -+ const u8 *key, const u8 hfunc) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ unsigned int ret; -+ -+ if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) -+ return -EOPNOTSUPP; -+ -+ if (indir) { -+ ret = hw_if->set_rss_lookup_table(pdata, indir); -+ if (ret) -+ return ret; -+ } -+ -+ if (key) { -+ ret = hw_if->set_rss_hash_key(pdata, key); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int xgbe_get_ts_info(struct net_device *netdev, -+ struct ethtool_ts_info *ts_info) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ -+ ts_info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | -+ SOF_TIMESTAMPING_RX_SOFTWARE | -+ SOF_TIMESTAMPING_SOFTWARE | -+ SOF_TIMESTAMPING_TX_HARDWARE | -+ SOF_TIMESTAMPING_RX_HARDWARE | -+ SOF_TIMESTAMPING_RAW_HARDWARE; -+ -+ if (pdata->ptp_clock) -+ ts_info->phc_index = ptp_clock_index(pdata->ptp_clock); -+ else -+ ts_info->phc_index = -1; -+ -+ ts_info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON); -+ ts_info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) | -+ (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) | -+ (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) | -+ (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) | -+ (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | -+ (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) | -+ (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) | -+ (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) | -+ (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) | -+ (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) | -+ (1 << HWTSTAMP_FILTER_ALL); -+ -+ return 0; -+} -+ -+static const struct ethtool_ops xgbe_ethtool_ops = { -+ .get_settings = xgbe_get_settings, -+ .set_settings = xgbe_set_settings, -+ .get_drvinfo = xgbe_get_drvinfo, -+ .get_link = ethtool_op_get_link, -+ .get_coalesce = xgbe_get_coalesce, -+ .set_coalesce = xgbe_set_coalesce, -+ .get_pauseparam = xgbe_get_pauseparam, -+ .set_pauseparam = xgbe_set_pauseparam, -+ .get_strings = xgbe_get_strings, -+ .get_ethtool_stats = xgbe_get_ethtool_stats, -+ .get_sset_count = xgbe_get_sset_count, -+ .get_rxnfc = xgbe_get_rxnfc, -+ .get_rxfh_key_size = xgbe_get_rxfh_key_size, -+ .get_rxfh_indir_size = xgbe_get_rxfh_indir_size, -+ .get_rxfh = xgbe_get_rxfh, -+ .set_rxfh = xgbe_set_rxfh, -+ .get_ts_info = xgbe_get_ts_info, -+}; -+ -+struct ethtool_ops *xgbe_a0_get_ethtool_ops(void) -+{ -+ return (struct ethtool_ops *)&xgbe_ethtool_ops; -+} -diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-main.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-main.c -new file mode 100644 -index 0000000..6a4af2d ---- /dev/null -+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-main.c -@@ -0,0 +1,620 @@ -+/* -+ * AMD 10Gb Ethernet driver -+ * -+ * This file is available to you under your choice of the following two -+ * licenses: -+ * -+ * License 1: GPLv2 -+ * -+ * Copyright (c) 2014 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 . -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * -+ * License 2: Modified BSD -+ * -+ * Copyright (c) 2014 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 BE LIABLE FOR ANY -+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "xgbe.h" -+#include "xgbe-common.h" -+ -+MODULE_AUTHOR("Tom Lendacky "); -+MODULE_LICENSE("Dual BSD/GPL"); -+MODULE_VERSION(XGBE_DRV_VERSION); -+MODULE_DESCRIPTION(XGBE_DRV_DESC); -+ -+unsigned int speed = 0; -+module_param(speed, uint, 0444); -+MODULE_PARM_DESC(speed, " Select operating speed (1=1GbE, 2=2.5GbE, 10=10GbE, any other value implies auto-negotiation"); -+ -+static void xgbe_default_config(struct xgbe_prv_data *pdata) -+{ -+ DBGPR("-->xgbe_default_config\n"); -+ -+ pdata->pblx8 = DMA_PBL_X8_ENABLE; -+ pdata->tx_sf_mode = MTL_TSF_ENABLE; -+ pdata->tx_threshold = MTL_TX_THRESHOLD_64; -+ pdata->tx_pbl = DMA_PBL_16; -+ pdata->tx_osp_mode = DMA_OSP_ENABLE; -+ pdata->rx_sf_mode = MTL_RSF_DISABLE; -+ pdata->rx_threshold = MTL_RX_THRESHOLD_64; -+ pdata->rx_pbl = DMA_PBL_16; -+ pdata->pause_autoneg = 1; -+ pdata->tx_pause = 1; -+ pdata->rx_pause = 1; -+ pdata->phy_speed = SPEED_UNKNOWN; -+ pdata->power_down = 0; -+ -+ if (speed == 10) { -+ pdata->default_autoneg = AUTONEG_DISABLE; -+ pdata->default_speed = SPEED_10000; -+ } else if (speed == 2) { -+ pdata->default_autoneg = AUTONEG_DISABLE; -+ pdata->default_speed = SPEED_2500; -+ } else if (speed == 1) { -+ pdata->default_autoneg = AUTONEG_DISABLE; -+ pdata->default_speed = SPEED_1000; -+ } else { -+ pdata->default_autoneg = AUTONEG_ENABLE; -+ pdata->default_speed = SPEED_10000; -+ } -+ -+ DBGPR("<--xgbe_default_config\n"); -+} -+ -+static void xgbe_init_all_fptrs(struct xgbe_prv_data *pdata) -+{ -+ xgbe_a0_init_function_ptrs_dev(&pdata->hw_if); -+ xgbe_a0_init_function_ptrs_desc(&pdata->desc_if); -+} -+ -+#ifdef CONFIG_ACPI -+static int xgbe_acpi_support(struct xgbe_prv_data *pdata) -+{ -+ struct device *dev = pdata->dev; -+ u32 property; -+ int ret; -+ -+ /* Obtain the system clock setting */ -+ ret = device_property_read_u32(dev, XGBE_ACPI_DMA_FREQ, &property); -+ if (ret) { -+ dev_err(dev, "unable to obtain %s property\n", -+ XGBE_ACPI_DMA_FREQ); -+ return ret; -+ } -+ pdata->sysclk_rate = property; -+ -+ /* Obtain the PTP clock setting */ -+ ret = device_property_read_u32(dev, XGBE_ACPI_PTP_FREQ, &property); -+ if (ret) { -+ dev_err(dev, "unable to obtain %s property\n", -+ XGBE_ACPI_PTP_FREQ); -+ return ret; -+ } -+ pdata->ptpclk_rate = property; -+ -+ return 0; -+} -+#else /* CONFIG_ACPI */ -+static int xgbe_acpi_support(struct xgbe_prv_data *pdata) -+{ -+ return -EINVAL; -+} -+#endif /* CONFIG_ACPI */ -+ -+#ifdef CONFIG_OF -+static int xgbe_of_support(struct xgbe_prv_data *pdata) -+{ -+ struct device *dev = pdata->dev; -+ -+ /* Obtain the system clock setting */ -+ pdata->sysclk = devm_clk_get(dev, XGBE_DMA_CLOCK); -+ if (IS_ERR(pdata->sysclk)) { -+ dev_err(dev, "dma devm_clk_get failed\n"); -+ return PTR_ERR(pdata->sysclk); -+ } -+ pdata->sysclk_rate = clk_get_rate(pdata->sysclk); -+ -+ /* Obtain the PTP clock setting */ -+ pdata->ptpclk = devm_clk_get(dev, XGBE_PTP_CLOCK); -+ if (IS_ERR(pdata->ptpclk)) { -+ dev_err(dev, "ptp devm_clk_get failed\n"); -+ return PTR_ERR(pdata->ptpclk); -+ } -+ pdata->ptpclk_rate = clk_get_rate(pdata->ptpclk); -+ -+ return 0; -+} -+#else /* CONFIG_OF */ -+static int xgbe_of_support(struct xgbe_prv_data *pdata) -+{ -+ return -EINVAL; -+} -+#endif /*CONFIG_OF */ -+ -+static int xgbe_probe(struct platform_device *pdev) -+{ -+ struct xgbe_prv_data *pdata; -+ struct xgbe_hw_if *hw_if; -+ struct xgbe_desc_if *desc_if; -+ struct net_device *netdev; -+ struct device *dev = &pdev->dev; -+ struct resource *res; -+ enum dev_dma_attr attr; -+ const char *phy_mode; -+ unsigned int i; -+ int ret; -+ -+ DBGPR("--> xgbe_probe\n"); -+ -+ netdev = alloc_etherdev_mq(sizeof(struct xgbe_prv_data), -+ XGBE_MAX_DMA_CHANNELS); -+ if (!netdev) { -+ dev_err(dev, "alloc_etherdev failed\n"); -+ ret = -ENOMEM; -+ goto err_alloc; -+ } -+ SET_NETDEV_DEV(netdev, dev); -+ pdata = netdev_priv(netdev); -+ pdata->netdev = netdev; -+ pdata->pdev = pdev; -+ pdata->adev = ACPI_COMPANION(dev); -+ pdata->dev = dev; -+ platform_set_drvdata(pdev, netdev); -+ -+ spin_lock_init(&pdata->lock); -+ mutex_init(&pdata->xpcs_mutex); -+ mutex_init(&pdata->rss_mutex); -+ spin_lock_init(&pdata->tstamp_lock); -+ -+ /* Check if we should use ACPI or DT */ -+ pdata->use_acpi = (!pdata->adev || acpi_disabled) ? 0 : 1; -+ -+ /* Set and validate the number of descriptors for a ring */ -+ BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_TX_DESC_CNT); -+ pdata->tx_desc_count = XGBE_TX_DESC_CNT; -+ if (pdata->tx_desc_count & (pdata->tx_desc_count - 1)) { -+ dev_err(dev, "tx descriptor count (%d) is not valid\n", -+ pdata->tx_desc_count); -+ ret = -EINVAL; -+ goto err_io; -+ } -+ BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_RX_DESC_CNT); -+ pdata->rx_desc_count = XGBE_RX_DESC_CNT; -+ if (pdata->rx_desc_count & (pdata->rx_desc_count - 1)) { -+ dev_err(dev, "rx descriptor count (%d) is not valid\n", -+ pdata->rx_desc_count); -+ ret = -EINVAL; -+ goto err_io; -+ } -+ -+ /* Obtain the mmio areas for the device */ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ pdata->xgmac_regs = devm_ioremap_resource(dev, res); -+ if (IS_ERR(pdata->xgmac_regs)) { -+ dev_err(dev, "xgmac ioremap failed\n"); -+ ret = PTR_ERR(pdata->xgmac_regs); -+ goto err_io; -+ } -+ DBGPR(" xgmac_regs = %p\n", pdata->xgmac_regs); -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); -+ pdata->xpcs_regs = devm_ioremap_resource(dev, res); -+ if (IS_ERR(pdata->xpcs_regs)) { -+ dev_err(dev, "xpcs ioremap failed\n"); -+ ret = PTR_ERR(pdata->xpcs_regs); -+ goto err_io; -+ } -+ DBGPR(" xpcs_regs = %p\n", pdata->xpcs_regs); -+ -+ /* Retrieve the MAC address */ -+ ret = device_property_read_u8_array(dev, XGBE_MAC_ADDR_PROPERTY, -+ pdata->mac_addr, -+ sizeof(pdata->mac_addr)); -+ if (ret || !is_valid_ether_addr(pdata->mac_addr)) { -+ dev_err(dev, "invalid %s property\n", XGBE_MAC_ADDR_PROPERTY); -+ if (!ret) -+ ret = -EINVAL; -+ goto err_io; -+ } -+ -+ /* Retrieve the PHY mode - it must be "xgmii" */ -+ ret = device_property_read_string(dev, XGBE_PHY_MODE_PROPERTY, -+ &phy_mode); -+ if (ret || strcmp(phy_mode, phy_modes(PHY_INTERFACE_MODE_XGMII))) { -+ dev_err(dev, "invalid %s property\n", XGBE_PHY_MODE_PROPERTY); -+ if (!ret) -+ ret = -EINVAL; -+ goto err_io; -+ } -+ pdata->phy_mode = PHY_INTERFACE_MODE_XGMII; -+ -+ /* Check for per channel interrupt support */ -+ if (device_property_present(dev, XGBE_DMA_IRQS_PROPERTY)) -+ pdata->per_channel_irq = 1; -+ -+ /* Obtain device settings unique to ACPI/OF */ -+ if (pdata->use_acpi) -+ ret = xgbe_acpi_support(pdata); -+ else -+ ret = xgbe_of_support(pdata); -+ if (ret) -+ goto err_io; -+ -+ /* Set the DMA coherency values */ -+ attr = device_get_dma_attr(pdata->dev); -+ pdata->coherent = (attr == DEV_DMA_COHERENT); -+ if (pdata->coherent) { -+ pdata->axdomain = XGBE_DMA_OS_AXDOMAIN; -+ pdata->arcache = XGBE_DMA_OS_ARCACHE; -+ pdata->awcache = XGBE_DMA_OS_AWCACHE; -+ } else { -+ pdata->axdomain = XGBE_DMA_SYS_AXDOMAIN; -+ pdata->arcache = XGBE_DMA_SYS_ARCACHE; -+ pdata->awcache = XGBE_DMA_SYS_AWCACHE; -+ } -+ -+ /* Set the DMA mask */ -+ if (!dev->dma_mask) -+ dev->dma_mask = &dev->coherent_dma_mask; -+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); -+ if (ret) { -+ dev_err(dev, "dma_set_mask_and_coherent failed\n"); -+ goto err_io; -+ } -+ -+ /* Get the device interrupt */ -+ ret = platform_get_irq(pdev, 0); -+ if (ret < 0) { -+ dev_err(dev, "platform_get_irq 0 failed\n"); -+ goto err_io; -+ } -+ pdata->dev_irq = ret; -+ -+ netdev->irq = pdata->dev_irq; -+ netdev->base_addr = (unsigned long)pdata->xgmac_regs; -+ memcpy(netdev->dev_addr, pdata->mac_addr, netdev->addr_len); -+ -+ /* Set all the function pointers */ -+ xgbe_init_all_fptrs(pdata); -+ hw_if = &pdata->hw_if; -+ desc_if = &pdata->desc_if; -+ -+ /* Issue software reset to device */ -+ hw_if->exit(pdata); -+ -+ /* Populate the hardware features */ -+ xgbe_a0_get_all_hw_features(pdata); -+ -+ /* Set default configuration data */ -+ xgbe_default_config(pdata); -+ -+ /* Calculate the number of Tx and Rx rings to be created -+ * -Tx (DMA) Channels map 1-to-1 to Tx Queues so set -+ * the number of Tx queues to the number of Tx channels -+ * enabled -+ * -Rx (DMA) Channels do not map 1-to-1 so use the actual -+ * number of Rx queues -+ */ -+ pdata->tx_ring_count = min_t(unsigned int, num_online_cpus(), -+ pdata->hw_feat.tx_ch_cnt); -+ pdata->tx_q_count = pdata->tx_ring_count; -+ ret = netif_set_real_num_tx_queues(netdev, pdata->tx_ring_count); -+ if (ret) { -+ dev_err(dev, "error setting real tx queue count\n"); -+ goto err_io; -+ } -+ -+ pdata->rx_ring_count = min_t(unsigned int, -+ netif_get_num_default_rss_queues(), -+ pdata->hw_feat.rx_ch_cnt); -+ pdata->rx_q_count = pdata->hw_feat.rx_q_cnt; -+ ret = netif_set_real_num_rx_queues(netdev, pdata->rx_ring_count); -+ if (ret) { -+ dev_err(dev, "error setting real rx queue count\n"); -+ goto err_io; -+ } -+ -+ /* Initialize RSS hash key and lookup table */ -+ netdev_rss_key_fill(pdata->rss_key, sizeof(pdata->rss_key)); -+ -+ for (i = 0; i < XGBE_RSS_MAX_TABLE_SIZE; i++) -+ XGMAC_SET_BITS(pdata->rss_table[i], MAC_RSSDR, DMCH, -+ i % pdata->rx_ring_count); -+ -+ XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, IP2TE, 1); -+ XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, TCP4TE, 1); -+ XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1); -+ -+ /* Prepare to regsiter with MDIO */ -+ pdata->mii_bus_id = kasprintf(GFP_KERNEL, "%s", pdev->name); -+ if (!pdata->mii_bus_id) { -+ dev_err(dev, "failed to allocate mii bus id\n"); -+ ret = -ENOMEM; -+ goto err_io; -+ } -+ ret = xgbe_a0_mdio_register(pdata); -+ if (ret) -+ goto err_bus_id; -+ -+ /* Set device operations */ -+ netdev->netdev_ops = xgbe_a0_get_netdev_ops(); -+ netdev->ethtool_ops = xgbe_a0_get_ethtool_ops(); -+#ifdef CONFIG_AMD_XGBE_DCB -+ netdev->dcbnl_ops = xgbe_a0_get_dcbnl_ops(); -+#endif -+ -+ /* Set device features */ -+ netdev->hw_features = NETIF_F_SG | -+ NETIF_F_IP_CSUM | -+ NETIF_F_IPV6_CSUM | -+ NETIF_F_RXCSUM | -+ NETIF_F_TSO | -+ NETIF_F_TSO6 | -+ NETIF_F_GRO | -+ NETIF_F_HW_VLAN_CTAG_RX | -+ NETIF_F_HW_VLAN_CTAG_TX | -+ NETIF_F_HW_VLAN_CTAG_FILTER; -+ -+ if (pdata->hw_feat.rss) -+ netdev->hw_features |= NETIF_F_RXHASH; -+ -+ netdev->vlan_features |= NETIF_F_SG | -+ NETIF_F_IP_CSUM | -+ NETIF_F_IPV6_CSUM | -+ NETIF_F_TSO | -+ NETIF_F_TSO6; -+ -+ netdev->features |= netdev->hw_features; -+ pdata->netdev_features = netdev->features; -+ -+ netdev->priv_flags |= IFF_UNICAST_FLT; -+ -+ xgbe_a0_init_rx_coalesce(pdata); -+ xgbe_a0_init_tx_coalesce(pdata); -+ -+ netif_carrier_off(netdev); -+ ret = register_netdev(netdev); -+ if (ret) { -+ dev_err(dev, "net device registration failed\n"); -+ goto err_reg_netdev; -+ } -+ -+ xgbe_a0_ptp_register(pdata); -+ -+ xgbe_a0_debugfs_init(pdata); -+ -+ netdev_notice(netdev, "net device enabled\n"); -+ -+ DBGPR("<-- xgbe_probe\n"); -+ -+ return 0; -+ -+err_reg_netdev: -+ xgbe_a0_mdio_unregister(pdata); -+ -+err_bus_id: -+ kfree(pdata->mii_bus_id); -+ -+err_io: -+ free_netdev(netdev); -+ -+err_alloc: -+ dev_notice(dev, "net device not enabled\n"); -+ -+ return ret; -+} -+ -+static int xgbe_remove(struct platform_device *pdev) -+{ -+ struct net_device *netdev = platform_get_drvdata(pdev); -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ -+ DBGPR("-->xgbe_remove\n"); -+ -+ xgbe_a0_debugfs_exit(pdata); -+ -+ xgbe_a0_ptp_unregister(pdata); -+ -+ unregister_netdev(netdev); -+ -+ xgbe_a0_mdio_unregister(pdata); -+ -+ kfree(pdata->mii_bus_id); -+ -+ free_netdev(netdev); -+ -+ DBGPR("<--xgbe_remove\n"); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int xgbe_suspend(struct device *dev) -+{ -+ struct net_device *netdev = dev_get_drvdata(dev); -+ int ret; -+ -+ DBGPR("-->xgbe_suspend\n"); -+ -+ if (!netif_running(netdev)) { -+ DBGPR("<--xgbe_dev_suspend\n"); -+ return -EINVAL; -+ } -+ -+ ret = xgbe_a0_powerdown(netdev, XGMAC_DRIVER_CONTEXT); -+ -+ DBGPR("<--xgbe_suspend\n"); -+ -+ return ret; -+} -+ -+static int xgbe_resume(struct device *dev) -+{ -+ struct net_device *netdev = dev_get_drvdata(dev); -+ int ret; -+ -+ DBGPR("-->xgbe_resume\n"); -+ -+ if (!netif_running(netdev)) { -+ DBGPR("<--xgbe_dev_resume\n"); -+ return -EINVAL; -+ } -+ -+ ret = xgbe_a0_powerup(netdev, XGMAC_DRIVER_CONTEXT); -+ -+ DBGPR("<--xgbe_resume\n"); -+ -+ return ret; -+} -+#endif /* CONFIG_PM */ -+ -+#ifdef CONFIG_ACPI -+static const struct acpi_device_id xgbe_a0_acpi_match[] = { -+ { "AMDI8000", 0 }, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(acpi, xgbe_a0_acpi_match); -+#endif -+ -+#ifdef CONFIG_OF -+static const struct of_device_id xgbe_a0_of_match[] = { -+ { .compatible = "amd,xgbe-seattle-v0a", }, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(of, xgbe_a0_of_match); -+#endif -+ -+static SIMPLE_DEV_PM_OPS(xgbe_pm_ops, xgbe_suspend, xgbe_resume); -+ -+static struct platform_driver xgbe_a0_driver = { -+ .driver = { -+ .name = "amd-xgbe-a0", -+#ifdef CONFIG_ACPI -+ .acpi_match_table = xgbe_a0_acpi_match, -+#endif -+#ifdef CONFIG_OF -+ .of_match_table = xgbe_a0_of_match, -+#endif -+ .pm = &xgbe_pm_ops, -+ }, -+ .probe = xgbe_probe, -+ .remove = xgbe_remove, -+}; -+ -+module_platform_driver(xgbe_a0_driver); -diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-mdio.c -new file mode 100644 -index 0000000..b84d048 ---- /dev/null -+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-mdio.c -@@ -0,0 +1,312 @@ -+/* -+ * AMD 10Gb Ethernet driver -+ * -+ * This file is available to you under your choice of the following two -+ * licenses: -+ * -+ * License 1: GPLv2 -+ * -+ * Copyright (c) 2014 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 . -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * -+ * License 2: Modified BSD -+ * -+ * Copyright (c) 2014 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 BE LIABLE FOR ANY -+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "xgbe.h" -+#include "xgbe-common.h" -+ -+static int xgbe_mdio_read(struct mii_bus *mii, int prtad, int mmd_reg) -+{ -+ struct xgbe_prv_data *pdata = mii->priv; -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ int mmd_data; -+ -+ DBGPR_MDIO("-->xgbe_mdio_read: prtad=%#x mmd_reg=%#x\n", -+ prtad, mmd_reg); -+ -+ mmd_data = hw_if->read_mmd_regs(pdata, prtad, mmd_reg); -+ -+ DBGPR_MDIO("<--xgbe_mdio_read: mmd_data=%#x\n", mmd_data); -+ -+ return mmd_data; -+} -+ -+static int xgbe_mdio_write(struct mii_bus *mii, int prtad, int mmd_reg, -+ u16 mmd_val) -+{ -+ struct xgbe_prv_data *pdata = mii->priv; -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; -+ int mmd_data = mmd_val; -+ -+ DBGPR_MDIO("-->xgbe_mdio_write: prtad=%#x mmd_reg=%#x mmd_data=%#x\n", -+ prtad, mmd_reg, mmd_data); -+ -+ hw_if->write_mmd_regs(pdata, prtad, mmd_reg, mmd_data); -+ -+ DBGPR_MDIO("<--xgbe_mdio_write\n"); -+ -+ return 0; -+} -+ -+void xgbe_a0_dump_phy_registers(struct xgbe_prv_data *pdata) -+{ -+ struct device *dev = pdata->dev; -+ struct phy_device *phydev = pdata->mii->phy_map[XGBE_PRTAD]; -+ int i; -+ -+ dev_alert(dev, "\n************* PHY Reg dump **********************\n"); -+ -+ dev_alert(dev, "PCS Control Reg (%#04x) = %#04x\n", MDIO_CTRL1, -+ XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1)); -+ dev_alert(dev, "PCS Status Reg (%#04x) = %#04x\n", MDIO_STAT1, -+ XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1)); -+ dev_alert(dev, "Phy Id (PHYS ID 1 %#04x)= %#04x\n", MDIO_DEVID1, -+ XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVID1)); -+ dev_alert(dev, "Phy Id (PHYS ID 2 %#04x)= %#04x\n", MDIO_DEVID2, -+ XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVID2)); -+ dev_alert(dev, "Devices in Package (%#04x)= %#04x\n", MDIO_DEVS1, -+ XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVS1)); -+ dev_alert(dev, "Devices in Package (%#04x)= %#04x\n", MDIO_DEVS2, -+ XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVS2)); -+ -+ dev_alert(dev, "Auto-Neg Control Reg (%#04x) = %#04x\n", MDIO_CTRL1, -+ XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_CTRL1)); -+ dev_alert(dev, "Auto-Neg Status Reg (%#04x) = %#04x\n", MDIO_STAT1, -+ XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_STAT1)); -+ dev_alert(dev, "Auto-Neg Ad Reg 1 (%#04x) = %#04x\n", -+ MDIO_AN_ADVERTISE, -+ XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE)); -+ dev_alert(dev, "Auto-Neg Ad Reg 2 (%#04x) = %#04x\n", -+ MDIO_AN_ADVERTISE + 1, -+ XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1)); -+ dev_alert(dev, "Auto-Neg Ad Reg 3 (%#04x) = %#04x\n", -+ MDIO_AN_ADVERTISE + 2, -+ XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2)); -+ dev_alert(dev, "Auto-Neg Completion Reg (%#04x) = %#04x\n", -+ MDIO_AN_COMP_STAT, -+ XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_COMP_STAT)); -+ -+ dev_alert(dev, "MMD Device Mask = %#x\n", -+ phydev->c45_ids.devices_in_package); -+ for (i = 0; i < ARRAY_SIZE(phydev->c45_ids.device_ids); i++) -+ dev_alert(dev, " MMD %d: ID = %#08x\n", i, -+ phydev->c45_ids.device_ids[i]); -+ -+ dev_alert(dev, "\n*************************************************\n"); -+} -+ -+int xgbe_a0_mdio_register(struct xgbe_prv_data *pdata) -+{ -+ struct mii_bus *mii; -+ struct phy_device *phydev; -+ int ret = 0; -+ -+ DBGPR("-->xgbe_a0_mdio_register\n"); -+ -+ mii = mdiobus_alloc(); -+ if (!mii) { -+ dev_err(pdata->dev, "mdiobus_alloc failed\n"); -+ return -ENOMEM; -+ } -+ -+ /* Register on the MDIO bus (don't probe any PHYs) */ -+ mii->name = XGBE_PHY_NAME; -+ mii->read = xgbe_mdio_read; -+ mii->write = xgbe_mdio_write; -+ snprintf(mii->id, sizeof(mii->id), "%s", pdata->mii_bus_id); -+ mii->priv = pdata; -+ mii->phy_mask = ~0; -+ mii->parent = pdata->dev; -+ ret = mdiobus_register(mii); -+ if (ret) { -+ dev_err(pdata->dev, "mdiobus_register failed\n"); -+ goto err_mdiobus_alloc; -+ } -+ DBGPR(" mdiobus_register succeeded for %s\n", pdata->mii_bus_id); -+ -+ /* Probe the PCS using Clause 45 */ -+ phydev = get_phy_device(mii, XGBE_PRTAD, true); -+ if (IS_ERR(phydev) || !phydev || -+ !phydev->c45_ids.device_ids[MDIO_MMD_PCS]) { -+ dev_err(pdata->dev, "get_phy_device failed\n"); -+ ret = phydev ? PTR_ERR(phydev) : -ENOLINK; -+ goto err_mdiobus_register; -+ } -+ request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT, -+ MDIO_ID_ARGS(phydev->c45_ids.device_ids[MDIO_MMD_PCS])); -+ -+ ret = phy_device_register(phydev); -+ if (ret) { -+ dev_err(pdata->dev, "phy_device_register failed\n"); -+ goto err_phy_device; -+ } -+ if (!phydev->dev.driver) { -+ dev_err(pdata->dev, "phy driver probe failed\n"); -+ ret = -EIO; -+ goto err_phy_device; -+ } -+ -+ /* Add a reference to the PHY driver so it can't be unloaded */ -+ pdata->phy_module = phydev->dev.driver->owner; -+ if (!try_module_get(pdata->phy_module)) { -+ dev_err(pdata->dev, "try_module_get failed\n"); -+ ret = -EIO; -+ goto err_phy_device; -+ } -+ -+ pdata->mii = mii; -+ pdata->mdio_mmd = MDIO_MMD_PCS; -+ -+ phydev->autoneg = pdata->default_autoneg; -+ if (phydev->autoneg == AUTONEG_DISABLE) { -+ phydev->speed = pdata->default_speed; -+ phydev->duplex = DUPLEX_FULL; -+ -+ phydev->advertising &= ~ADVERTISED_Autoneg; -+ } -+ -+ pdata->phydev = phydev; -+ -+ DBGPHY_REGS(pdata); -+ -+ DBGPR("<--xgbe_a0_mdio_register\n"); -+ -+ return 0; -+ -+err_phy_device: -+ phy_device_free(phydev); -+ -+err_mdiobus_register: -+ mdiobus_unregister(mii); -+ -+err_mdiobus_alloc: -+ mdiobus_free(mii); -+ -+ return ret; -+} -+ -+void xgbe_a0_mdio_unregister(struct xgbe_prv_data *pdata) -+{ -+ DBGPR("-->xgbe_a0_mdio_unregister\n"); -+ -+ pdata->phydev = NULL; -+ -+ module_put(pdata->phy_module); -+ pdata->phy_module = NULL; -+ -+ mdiobus_unregister(pdata->mii); -+ pdata->mii->priv = NULL; -+ -+ mdiobus_free(pdata->mii); -+ pdata->mii = NULL; -+ -+ DBGPR("<--xgbe_a0_mdio_unregister\n"); -+} -diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-ptp.c -new file mode 100644 -index 0000000..1016aeb ---- /dev/null -+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-ptp.c -@@ -0,0 +1,278 @@ -+/* -+ * AMD 10Gb Ethernet driver -+ * -+ * This file is available to you under your choice of the following two -+ * licenses: -+ * -+ * License 1: GPLv2 -+ * -+ * Copyright (c) 2014 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 . -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * -+ * License 2: Modified BSD -+ * -+ * Copyright (c) 2014 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 BE LIABLE FOR ANY -+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include "xgbe.h" -+#include "xgbe-common.h" -+ -+static cycle_t xgbe_cc_read(const struct cyclecounter *cc) -+{ -+ struct xgbe_prv_data *pdata = container_of(cc, -+ struct xgbe_prv_data, -+ tstamp_cc); -+ u64 nsec; -+ -+ nsec = pdata->hw_if.get_tstamp_time(pdata); -+ -+ return nsec; -+} -+ -+static int xgbe_adjfreq(struct ptp_clock_info *info, s32 delta) -+{ -+ struct xgbe_prv_data *pdata = container_of(info, -+ struct xgbe_prv_data, -+ ptp_clock_info); -+ unsigned long flags; -+ u64 adjust; -+ u32 addend, diff; -+ unsigned int neg_adjust = 0; -+ -+ if (delta < 0) { -+ neg_adjust = 1; -+ delta = -delta; -+ } -+ -+ adjust = pdata->tstamp_addend; -+ adjust *= delta; -+ diff = div_u64(adjust, 1000000000UL); -+ -+ addend = (neg_adjust) ? pdata->tstamp_addend - diff : -+ pdata->tstamp_addend + diff; -+ -+ spin_lock_irqsave(&pdata->tstamp_lock, flags); -+ -+ pdata->hw_if.update_tstamp_addend(pdata, addend); -+ -+ spin_unlock_irqrestore(&pdata->tstamp_lock, flags); -+ -+ return 0; -+} -+ -+static int xgbe_adjtime(struct ptp_clock_info *info, s64 delta) -+{ -+ struct xgbe_prv_data *pdata = container_of(info, -+ struct xgbe_prv_data, -+ ptp_clock_info); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&pdata->tstamp_lock, flags); -+ timecounter_adjtime(&pdata->tstamp_tc, delta); -+ spin_unlock_irqrestore(&pdata->tstamp_lock, flags); -+ -+ return 0; -+} -+ -+static int xgbe_gettime(struct ptp_clock_info *info, struct timespec64 *ts) -+{ -+ struct xgbe_prv_data *pdata = container_of(info, -+ struct xgbe_prv_data, -+ ptp_clock_info); -+ unsigned long flags; -+ u64 nsec; -+ -+ spin_lock_irqsave(&pdata->tstamp_lock, flags); -+ -+ nsec = timecounter_read(&pdata->tstamp_tc); -+ -+ spin_unlock_irqrestore(&pdata->tstamp_lock, flags); -+ -+ *ts = ns_to_timespec64(nsec); -+ -+ return 0; -+} -+ -+static int xgbe_settime(struct ptp_clock_info *info, const struct timespec64 *ts) -+{ -+ struct xgbe_prv_data *pdata = container_of(info, -+ struct xgbe_prv_data, -+ ptp_clock_info); -+ unsigned long flags; -+ u64 nsec; -+ -+ nsec = timespec64_to_ns(ts); -+ -+ spin_lock_irqsave(&pdata->tstamp_lock, flags); -+ -+ timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, nsec); -+ -+ spin_unlock_irqrestore(&pdata->tstamp_lock, flags); -+ -+ return 0; -+} -+ -+static int xgbe_enable(struct ptp_clock_info *info, -+ struct ptp_clock_request *request, int on) -+{ -+ return -EOPNOTSUPP; -+} -+ -+void xgbe_a0_ptp_register(struct xgbe_prv_data *pdata) -+{ -+ struct ptp_clock_info *info = &pdata->ptp_clock_info; -+ struct ptp_clock *clock; -+ struct cyclecounter *cc = &pdata->tstamp_cc; -+ u64 dividend; -+ -+ snprintf(info->name, sizeof(info->name), "%s", -+ netdev_name(pdata->netdev)); -+ info->owner = THIS_MODULE; -+ info->max_adj = pdata->ptpclk_rate; -+ info->adjfreq = xgbe_adjfreq; -+ info->adjtime = xgbe_adjtime; -+ info->gettime64 = xgbe_gettime; -+ info->settime64 = xgbe_settime; -+ info->enable = xgbe_enable; -+ -+ clock = ptp_clock_register(info, pdata->dev); -+ if (IS_ERR(clock)) { -+ dev_err(pdata->dev, "ptp_clock_register failed\n"); -+ return; -+ } -+ -+ pdata->ptp_clock = clock; -+ -+ /* Calculate the addend: -+ * addend = 2^32 / (PTP ref clock / 50Mhz) -+ * = (2^32 * 50Mhz) / PTP ref clock -+ */ -+ dividend = 50000000; -+ dividend <<= 32; -+ pdata->tstamp_addend = div_u64(dividend, pdata->ptpclk_rate); -+ -+ /* Setup the timecounter */ -+ cc->read = xgbe_cc_read; -+ cc->mask = CLOCKSOURCE_MASK(64); -+ cc->mult = 1; -+ cc->shift = 0; -+ -+ timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, -+ ktime_to_ns(ktime_get_real())); -+ -+ /* Disable all timestamping to start */ -+ XGMAC_IOWRITE(pdata, MAC_TCR, 0); -+ pdata->tstamp_config.tx_type = HWTSTAMP_TX_OFF; -+ pdata->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; -+} -+ -+void xgbe_a0_ptp_unregister(struct xgbe_prv_data *pdata) -+{ -+ if (pdata->ptp_clock) -+ ptp_clock_unregister(pdata->ptp_clock); -+} -diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe.h b/drivers/net/ethernet/amd/xgbe-a0/xgbe.h -new file mode 100644 -index 0000000..04c00d2 ---- /dev/null -+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe.h -@@ -0,0 +1,868 @@ -+/* -+ * AMD 10Gb Ethernet driver -+ * -+ * This file is available to you under your choice of the following two -+ * licenses: -+ * -+ * License 1: GPLv2 -+ * -+ * Copyright (c) 2014 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 . -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * -+ * License 2: Modified BSD -+ * -+ * Copyright (c) 2014 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 BE LIABLE FOR ANY -+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * This file incorporates work covered by the following copyright and -+ * permission notice: -+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation -+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys, -+ * Inc. unless otherwise expressly agreed to in writing between Synopsys -+ * and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product -+ * under any End User Software License Agreement or Agreement for Licensed -+ * Product with Synopsys or any supplement thereto. Permission is hereby -+ * granted, free of charge, to any person obtaining a copy of this software -+ * annotated with this license and the Software, to deal in the Software -+ * without restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies -+ * of the Software, and to permit persons to whom the Software is furnished -+ * to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included -+ * in all copies or substantial portions of the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" -+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS -+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -+ * THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef __XGBE_H__ -+#define __XGBE_H__ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define XGBE_DRV_NAME "amd-xgbe" -+#define XGBE_DRV_VERSION "0.0.0-a" -+#define XGBE_DRV_DESC "AMD 10 Gigabit Ethernet Driver" -+ -+/* Descriptor related defines */ -+#define XGBE_TX_DESC_CNT 512 -+#define XGBE_TX_DESC_MIN_FREE (XGBE_TX_DESC_CNT >> 3) -+#define XGBE_TX_DESC_MAX_PROC (XGBE_TX_DESC_CNT >> 1) -+#define XGBE_RX_DESC_CNT 512 -+ -+#define XGBE_TX_MAX_BUF_SIZE (0x3fff & ~(64 - 1)) -+ -+/* Descriptors required for maximum contigous TSO/GSO packet */ -+#define XGBE_TX_MAX_SPLIT ((GSO_MAX_SIZE / XGBE_TX_MAX_BUF_SIZE) + 1) -+ -+/* Maximum possible descriptors needed for an SKB: -+ * - Maximum number of SKB frags -+ * - Maximum descriptors for contiguous TSO/GSO packet -+ * - Possible context descriptor -+ * - Possible TSO header descriptor -+ */ -+#define XGBE_TX_MAX_DESCS (MAX_SKB_FRAGS + XGBE_TX_MAX_SPLIT + 2) -+ -+#define XGBE_RX_MIN_BUF_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN) -+#define XGBE_RX_BUF_ALIGN 64 -+#define XGBE_SKB_ALLOC_SIZE 256 -+#define XGBE_SPH_HDSMS_SIZE 2 /* Keep in sync with SKB_ALLOC_SIZE */ -+ -+#define XGBE_MAX_DMA_CHANNELS 16 -+#define XGBE_MAX_QUEUES 16 -+#define XGBE_DMA_STOP_TIMEOUT 5 -+ -+/* DMA cache settings - Outer sharable, write-back, write-allocate */ -+#define XGBE_DMA_OS_AXDOMAIN 0x2 -+#define XGBE_DMA_OS_ARCACHE 0xb -+#define XGBE_DMA_OS_AWCACHE 0xf -+ -+/* DMA cache settings - System, no caches used */ -+#define XGBE_DMA_SYS_AXDOMAIN 0x3 -+#define XGBE_DMA_SYS_ARCACHE 0x0 -+#define XGBE_DMA_SYS_AWCACHE 0x0 -+ -+#define XGBE_DMA_INTERRUPT_MASK 0x31c7 -+ -+#define XGMAC_MIN_PACKET 60 -+#define XGMAC_STD_PACKET_MTU 1500 -+#define XGMAC_MAX_STD_PACKET 1518 -+#define XGMAC_JUMBO_PACKET_MTU 9000 -+#define XGMAC_MAX_JUMBO_PACKET 9018 -+ -+/* MDIO bus phy name */ -+#define XGBE_PHY_NAME "amd_xgbe_phy_a0" -+#define XGBE_PRTAD 0 -+ -+/* Common property names */ -+#define XGBE_MAC_ADDR_PROPERTY "mac-address" -+#define XGBE_PHY_MODE_PROPERTY "phy-mode" -+#define XGBE_DMA_IRQS_PROPERTY "amd,per-channel-interrupt" -+ -+/* Device-tree clock names */ -+#define XGBE_DMA_CLOCK "dma_clk" -+#define XGBE_PTP_CLOCK "ptp_clk" -+ -+/* ACPI property names */ -+#define XGBE_ACPI_DMA_FREQ "amd,dma-freq" -+#define XGBE_ACPI_PTP_FREQ "amd,ptp-freq" -+ -+/* Timestamp support - values based on 50MHz PTP clock -+ * 50MHz => 20 nsec -+ */ -+#define XGBE_TSTAMP_SSINC 20 -+#define XGBE_TSTAMP_SNSINC 0 -+ -+/* Driver PMT macros */ -+#define XGMAC_DRIVER_CONTEXT 1 -+#define XGMAC_IOCTL_CONTEXT 2 -+ -+#define XGBE_FIFO_MAX 81920 -+#define XGBE_FIFO_SIZE_B(x) (x) -+#define XGBE_FIFO_SIZE_KB(x) (x * 1024) -+ -+#define XGBE_TC_MIN_QUANTUM 10 -+ -+/* Helper macro for descriptor handling -+ * Always use XGBE_GET_DESC_DATA to access the descriptor data -+ * since the index is free-running and needs to be and-ed -+ * with the descriptor count value of the ring to index to -+ * the proper descriptor data. -+ */ -+#define XGBE_GET_DESC_DATA(_ring, _idx) \ -+ ((_ring)->rdata + \ -+ ((_idx) & ((_ring)->rdesc_count - 1))) -+ -+/* Default coalescing parameters */ -+#define XGMAC_INIT_DMA_TX_USECS 50 -+#define XGMAC_INIT_DMA_TX_FRAMES 25 -+ -+#define XGMAC_MAX_DMA_RIWT 0xff -+#define XGMAC_INIT_DMA_RX_USECS 30 -+#define XGMAC_INIT_DMA_RX_FRAMES 25 -+ -+/* Flow control queue count */ -+#define XGMAC_MAX_FLOW_CONTROL_QUEUES 8 -+ -+/* Maximum MAC address hash table size (256 bits = 8 bytes) */ -+#define XGBE_MAC_HASH_TABLE_SIZE 8 -+ -+/* Receive Side Scaling */ -+#define XGBE_RSS_HASH_KEY_SIZE 40 -+#define XGBE_RSS_MAX_TABLE_SIZE 256 -+#define XGBE_RSS_LOOKUP_TABLE_TYPE 0 -+#define XGBE_RSS_HASH_KEY_TYPE 1 -+ -+struct xgbe_prv_data; -+ -+struct xgbe_packet_data { -+ struct sk_buff *skb; -+ -+ unsigned int attributes; -+ -+ unsigned int errors; -+ -+ unsigned int rdesc_count; -+ unsigned int length; -+ -+ unsigned int header_len; -+ unsigned int tcp_header_len; -+ unsigned int tcp_payload_len; -+ unsigned short mss; -+ -+ unsigned short vlan_ctag; -+ -+ u64 rx_tstamp; -+ -+ u32 rss_hash; -+ enum pkt_hash_types rss_hash_type; -+ -+ unsigned int tx_packets; -+ unsigned int tx_bytes; -+}; -+ -+/* Common Rx and Tx descriptor mapping */ -+struct xgbe_ring_desc { -+ __le32 desc0; -+ __le32 desc1; -+ __le32 desc2; -+ __le32 desc3; -+}; -+ -+/* Page allocation related values */ -+struct xgbe_page_alloc { -+ struct page *pages; -+ unsigned int pages_len; -+ unsigned int pages_offset; -+ -+ dma_addr_t pages_dma; -+}; -+ -+/* Ring entry buffer data */ -+struct xgbe_buffer_data { -+ struct xgbe_page_alloc pa; -+ struct xgbe_page_alloc pa_unmap; -+ -+ dma_addr_t dma; -+ unsigned int dma_len; -+}; -+ -+/* Tx-related ring data */ -+struct xgbe_tx_ring_data { -+ unsigned int packets; /* BQL packet count */ -+ unsigned int bytes; /* BQL byte count */ -+}; -+ -+/* Rx-related ring data */ -+struct xgbe_rx_ring_data { -+ struct xgbe_buffer_data hdr; /* Header locations */ -+ struct xgbe_buffer_data buf; /* Payload locations */ -+ -+ unsigned short hdr_len; /* Length of received header */ -+ unsigned short len; /* Length of received packet */ -+}; -+ -+/* Structure used to hold information related to the descriptor -+ * and the packet associated with the descriptor (always use -+ * use the XGBE_GET_DESC_DATA macro to access this data from the ring) -+ */ -+struct xgbe_ring_data { -+ struct xgbe_ring_desc *rdesc; /* Virtual address of descriptor */ -+ dma_addr_t rdesc_dma; /* DMA address of descriptor */ -+ -+ struct sk_buff *skb; /* Virtual address of SKB */ -+ dma_addr_t skb_dma; /* DMA address of SKB data */ -+ unsigned int skb_dma_len; /* Length of SKB DMA area */ -+ -+ struct xgbe_tx_ring_data tx; /* Tx-related data */ -+ struct xgbe_rx_ring_data rx; /* Rx-related data */ -+ -+ unsigned int interrupt; /* Interrupt indicator */ -+ -+ unsigned int mapped_as_page; -+ -+ /* Incomplete receive save location. If the budget is exhausted -+ * or the last descriptor (last normal descriptor or a following -+ * context descriptor) has not been DMA'd yet the current state -+ * of the receive processing needs to be saved. -+ */ -+ unsigned int state_saved; -+ struct { -+ unsigned int incomplete; -+ unsigned int context_next; -+ struct sk_buff *skb; -+ unsigned int len; -+ unsigned int error; -+ } state; -+}; -+ -+struct xgbe_ring { -+ /* Ring lock - used just for TX rings at the moment */ -+ spinlock_t lock; -+ -+ /* Per packet related information */ -+ struct xgbe_packet_data packet_data; -+ -+ /* Virtual/DMA addresses and count of allocated descriptor memory */ -+ struct xgbe_ring_desc *rdesc; -+ dma_addr_t rdesc_dma; -+ unsigned int rdesc_count; -+ -+ /* Array of descriptor data corresponding the descriptor memory -+ * (always use the XGBE_GET_DESC_DATA macro to access this data) -+ */ -+ struct xgbe_ring_data *rdata; -+ -+ /* Page allocation for RX buffers */ -+ struct xgbe_page_alloc rx_hdr_pa; -+ struct xgbe_page_alloc rx_buf_pa; -+ -+ /* Ring index values -+ * cur - Tx: index of descriptor to be used for current transfer -+ * Rx: index of descriptor to check for packet availability -+ * dirty - Tx: index of descriptor to check for transfer complete -+ * Rx: index of descriptor to check for buffer reallocation -+ */ -+ unsigned int cur; -+ unsigned int dirty; -+ -+ /* Coalesce frame count used for interrupt bit setting */ -+ unsigned int coalesce_count; -+ -+ union { -+ struct { -+ unsigned int queue_stopped; -+ unsigned int xmit_more; -+ unsigned short cur_mss; -+ unsigned short cur_vlan_ctag; -+ } tx; -+ }; -+} ____cacheline_aligned; -+ -+/* Structure used to describe the descriptor rings associated with -+ * a DMA channel. -+ */ -+struct xgbe_channel { -+ char name[16]; -+ -+ /* Address of private data area for device */ -+ struct xgbe_prv_data *pdata; -+ -+ /* Queue index and base address of queue's DMA registers */ -+ unsigned int queue_index; -+ void __iomem *dma_regs; -+ -+ /* Per channel interrupt irq number */ -+ int dma_irq; -+ char dma_irq_name[IFNAMSIZ + 32]; -+ -+ /* Netdev related settings */ -+ struct napi_struct napi; -+ -+ unsigned int saved_ier; -+ -+ unsigned int tx_timer_active; -+ struct hrtimer tx_timer; -+ -+ struct xgbe_ring *tx_ring; -+ struct xgbe_ring *rx_ring; -+} ____cacheline_aligned; -+ -+enum xgbe_int { -+ XGMAC_INT_DMA_CH_SR_TI, -+ XGMAC_INT_DMA_CH_SR_TPS, -+ XGMAC_INT_DMA_CH_SR_TBU, -+ XGMAC_INT_DMA_CH_SR_RI, -+ XGMAC_INT_DMA_CH_SR_RBU, -+ XGMAC_INT_DMA_CH_SR_RPS, -+ XGMAC_INT_DMA_CH_SR_TI_RI, -+ XGMAC_INT_DMA_CH_SR_FBE, -+ XGMAC_INT_DMA_ALL, -+}; -+ -+enum xgbe_int_state { -+ XGMAC_INT_STATE_SAVE, -+ XGMAC_INT_STATE_RESTORE, -+}; -+ -+enum xgbe_mtl_fifo_size { -+ XGMAC_MTL_FIFO_SIZE_256 = 0x00, -+ XGMAC_MTL_FIFO_SIZE_512 = 0x01, -+ XGMAC_MTL_FIFO_SIZE_1K = 0x03, -+ XGMAC_MTL_FIFO_SIZE_2K = 0x07, -+ XGMAC_MTL_FIFO_SIZE_4K = 0x0f, -+ XGMAC_MTL_FIFO_SIZE_8K = 0x1f, -+ XGMAC_MTL_FIFO_SIZE_16K = 0x3f, -+ XGMAC_MTL_FIFO_SIZE_32K = 0x7f, -+ XGMAC_MTL_FIFO_SIZE_64K = 0xff, -+ XGMAC_MTL_FIFO_SIZE_128K = 0x1ff, -+ XGMAC_MTL_FIFO_SIZE_256K = 0x3ff, -+}; -+ -+struct xgbe_mmc_stats { -+ /* Tx Stats */ -+ u64 txoctetcount_gb; -+ u64 txframecount_gb; -+ u64 txbroadcastframes_g; -+ u64 txmulticastframes_g; -+ u64 tx64octets_gb; -+ u64 tx65to127octets_gb; -+ u64 tx128to255octets_gb; -+ u64 tx256to511octets_gb; -+ u64 tx512to1023octets_gb; -+ u64 tx1024tomaxoctets_gb; -+ u64 txunicastframes_gb; -+ u64 txmulticastframes_gb; -+ u64 txbroadcastframes_gb; -+ u64 txunderflowerror; -+ u64 txoctetcount_g; -+ u64 txframecount_g; -+ u64 txpauseframes; -+ u64 txvlanframes_g; -+ -+ /* Rx Stats */ -+ u64 rxframecount_gb; -+ u64 rxoctetcount_gb; -+ u64 rxoctetcount_g; -+ u64 rxbroadcastframes_g; -+ u64 rxmulticastframes_g; -+ u64 rxcrcerror; -+ u64 rxrunterror; -+ u64 rxjabbererror; -+ u64 rxundersize_g; -+ u64 rxoversize_g; -+ u64 rx64octets_gb; -+ u64 rx65to127octets_gb; -+ u64 rx128to255octets_gb; -+ u64 rx256to511octets_gb; -+ u64 rx512to1023octets_gb; -+ u64 rx1024tomaxoctets_gb; -+ u64 rxunicastframes_g; -+ u64 rxlengtherror; -+ u64 rxoutofrangetype; -+ u64 rxpauseframes; -+ u64 rxfifooverflow; -+ u64 rxvlanframes_gb; -+ u64 rxwatchdogerror; -+}; -+ -+struct xgbe_hw_if { -+ int (*tx_complete)(struct xgbe_ring_desc *); -+ -+ int (*set_promiscuous_mode)(struct xgbe_prv_data *, unsigned int); -+ int (*set_all_multicast_mode)(struct xgbe_prv_data *, unsigned int); -+ int (*add_mac_addresses)(struct xgbe_prv_data *); -+ int (*set_mac_address)(struct xgbe_prv_data *, u8 *addr); -+ -+ int (*enable_rx_csum)(struct xgbe_prv_data *); -+ int (*disable_rx_csum)(struct xgbe_prv_data *); -+ -+ int (*enable_rx_vlan_stripping)(struct xgbe_prv_data *); -+ int (*disable_rx_vlan_stripping)(struct xgbe_prv_data *); -+ int (*enable_rx_vlan_filtering)(struct xgbe_prv_data *); -+ int (*disable_rx_vlan_filtering)(struct xgbe_prv_data *); -+ int (*update_vlan_hash_table)(struct xgbe_prv_data *); -+ -+ int (*read_mmd_regs)(struct xgbe_prv_data *, int, int); -+ void (*write_mmd_regs)(struct xgbe_prv_data *, int, int, int); -+ int (*set_gmii_speed)(struct xgbe_prv_data *); -+ int (*set_gmii_2500_speed)(struct xgbe_prv_data *); -+ int (*set_xgmii_speed)(struct xgbe_prv_data *); -+ -+ void (*enable_tx)(struct xgbe_prv_data *); -+ void (*disable_tx)(struct xgbe_prv_data *); -+ void (*enable_rx)(struct xgbe_prv_data *); -+ void (*disable_rx)(struct xgbe_prv_data *); -+ -+ void (*powerup_tx)(struct xgbe_prv_data *); -+ void (*powerdown_tx)(struct xgbe_prv_data *); -+ void (*powerup_rx)(struct xgbe_prv_data *); -+ void (*powerdown_rx)(struct xgbe_prv_data *); -+ -+ int (*init)(struct xgbe_prv_data *); -+ int (*exit)(struct xgbe_prv_data *); -+ -+ int (*enable_int)(struct xgbe_channel *, enum xgbe_int); -+ int (*disable_int)(struct xgbe_channel *, enum xgbe_int); -+ void (*dev_xmit)(struct xgbe_channel *); -+ int (*dev_read)(struct xgbe_channel *); -+ void (*tx_desc_init)(struct xgbe_channel *); -+ void (*rx_desc_init)(struct xgbe_channel *); -+ void (*rx_desc_reset)(struct xgbe_ring_data *); -+ void (*tx_desc_reset)(struct xgbe_ring_data *); -+ int (*is_last_desc)(struct xgbe_ring_desc *); -+ int (*is_context_desc)(struct xgbe_ring_desc *); -+ void (*tx_start_xmit)(struct xgbe_channel *, struct xgbe_ring *); -+ -+ /* For FLOW ctrl */ -+ int (*config_tx_flow_control)(struct xgbe_prv_data *); -+ int (*config_rx_flow_control)(struct xgbe_prv_data *); -+ -+ /* For RX coalescing */ -+ int (*config_rx_coalesce)(struct xgbe_prv_data *); -+ int (*config_tx_coalesce)(struct xgbe_prv_data *); -+ unsigned int (*usec_to_riwt)(struct xgbe_prv_data *, unsigned int); -+ unsigned int (*riwt_to_usec)(struct xgbe_prv_data *, unsigned int); -+ -+ /* For RX and TX threshold config */ -+ int (*config_rx_threshold)(struct xgbe_prv_data *, unsigned int); -+ int (*config_tx_threshold)(struct xgbe_prv_data *, unsigned int); -+ -+ /* For RX and TX Store and Forward Mode config */ -+ int (*config_rsf_mode)(struct xgbe_prv_data *, unsigned int); -+ int (*config_tsf_mode)(struct xgbe_prv_data *, unsigned int); -+ -+ /* For TX DMA Operate on Second Frame config */ -+ int (*config_osp_mode)(struct xgbe_prv_data *); -+ -+ /* For RX and TX PBL config */ -+ int (*config_rx_pbl_val)(struct xgbe_prv_data *); -+ int (*get_rx_pbl_val)(struct xgbe_prv_data *); -+ int (*config_tx_pbl_val)(struct xgbe_prv_data *); -+ int (*get_tx_pbl_val)(struct xgbe_prv_data *); -+ int (*config_pblx8)(struct xgbe_prv_data *); -+ -+ /* For MMC statistics */ -+ void (*rx_mmc_int)(struct xgbe_prv_data *); -+ void (*tx_mmc_int)(struct xgbe_prv_data *); -+ void (*read_mmc_stats)(struct xgbe_prv_data *); -+ -+ /* For Timestamp config */ -+ int (*config_tstamp)(struct xgbe_prv_data *, unsigned int); -+ void (*update_tstamp_addend)(struct xgbe_prv_data *, unsigned int); -+ void (*set_tstamp_time)(struct xgbe_prv_data *, unsigned int sec, -+ unsigned int nsec); -+ u64 (*get_tstamp_time)(struct xgbe_prv_data *); -+ u64 (*get_tx_tstamp)(struct xgbe_prv_data *); -+ -+ /* For Data Center Bridging config */ -+ void (*config_dcb_tc)(struct xgbe_prv_data *); -+ void (*config_dcb_pfc)(struct xgbe_prv_data *); -+ -+ /* For Receive Side Scaling */ -+ int (*enable_rss)(struct xgbe_prv_data *); -+ int (*disable_rss)(struct xgbe_prv_data *); -+ int (*set_rss_hash_key)(struct xgbe_prv_data *, const u8 *); -+ int (*set_rss_lookup_table)(struct xgbe_prv_data *, const u32 *); -+}; -+ -+struct xgbe_desc_if { -+ int (*alloc_ring_resources)(struct xgbe_prv_data *); -+ void (*free_ring_resources)(struct xgbe_prv_data *); -+ int (*map_tx_skb)(struct xgbe_channel *, struct sk_buff *); -+ int (*map_rx_buffer)(struct xgbe_prv_data *, struct xgbe_ring *, -+ struct xgbe_ring_data *); -+ void (*unmap_rdata)(struct xgbe_prv_data *, struct xgbe_ring_data *); -+ void (*wrapper_tx_desc_init)(struct xgbe_prv_data *); -+ void (*wrapper_rx_desc_init)(struct xgbe_prv_data *); -+}; -+ -+/* This structure contains flags that indicate what hardware features -+ * or configurations are present in the device. -+ */ -+struct xgbe_hw_features { -+ /* HW Version */ -+ unsigned int version; -+ -+ /* HW Feature Register0 */ -+ unsigned int gmii; /* 1000 Mbps support */ -+ unsigned int vlhash; /* VLAN Hash Filter */ -+ unsigned int sma; /* SMA(MDIO) Interface */ -+ unsigned int rwk; /* PMT remote wake-up packet */ -+ unsigned int mgk; /* PMT magic packet */ -+ unsigned int mmc; /* RMON module */ -+ unsigned int aoe; /* ARP Offload */ -+ unsigned int ts; /* IEEE 1588-2008 Adavanced Timestamp */ -+ unsigned int eee; /* Energy Efficient Ethernet */ -+ unsigned int tx_coe; /* Tx Checksum Offload */ -+ unsigned int rx_coe; /* Rx Checksum Offload */ -+ unsigned int addn_mac; /* Additional MAC Addresses */ -+ unsigned int ts_src; /* Timestamp Source */ -+ unsigned int sa_vlan_ins; /* Source Address or VLAN Insertion */ -+ -+ /* HW Feature Register1 */ -+ unsigned int rx_fifo_size; /* MTL Receive FIFO Size */ -+ unsigned int tx_fifo_size; /* MTL Transmit FIFO Size */ -+ unsigned int adv_ts_hi; /* Advance Timestamping High Word */ -+ unsigned int dcb; /* DCB Feature */ -+ unsigned int sph; /* Split Header Feature */ -+ unsigned int tso; /* TCP Segmentation Offload */ -+ unsigned int dma_debug; /* DMA Debug Registers */ -+ unsigned int rss; /* Receive Side Scaling */ -+ unsigned int tc_cnt; /* Number of Traffic Classes */ -+ unsigned int hash_table_size; /* Hash Table Size */ -+ unsigned int l3l4_filter_num; /* Number of L3-L4 Filters */ -+ -+ /* HW Feature Register2 */ -+ unsigned int rx_q_cnt; /* Number of MTL Receive Queues */ -+ unsigned int tx_q_cnt; /* Number of MTL Transmit Queues */ -+ unsigned int rx_ch_cnt; /* Number of DMA Receive Channels */ -+ unsigned int tx_ch_cnt; /* Number of DMA Transmit Channels */ -+ unsigned int pps_out_num; /* Number of PPS outputs */ -+ unsigned int aux_snap_num; /* Number of Aux snapshot inputs */ -+}; -+ -+struct xgbe_prv_data { -+ struct net_device *netdev; -+ struct platform_device *pdev; -+ struct acpi_device *adev; -+ struct device *dev; -+ -+ /* ACPI or DT flag */ -+ unsigned int use_acpi; -+ -+ /* XGMAC/XPCS related mmio registers */ -+ void __iomem *xgmac_regs; /* XGMAC CSRs */ -+ void __iomem *xpcs_regs; /* XPCS MMD registers */ -+ -+ /* Overall device lock */ -+ spinlock_t lock; -+ -+ /* XPCS indirect addressing mutex */ -+ struct mutex xpcs_mutex; -+ -+ /* RSS addressing mutex */ -+ struct mutex rss_mutex; -+ -+ int dev_irq; -+ unsigned int per_channel_irq; -+ -+ struct xgbe_hw_if hw_if; -+ struct xgbe_desc_if desc_if; -+ -+ /* AXI DMA settings */ -+ unsigned int coherent; -+ unsigned int axdomain; -+ unsigned int arcache; -+ unsigned int awcache; -+ -+ /* Rings for Tx/Rx on a DMA channel */ -+ struct xgbe_channel *channel; -+ unsigned int channel_count; -+ unsigned int tx_ring_count; -+ unsigned int tx_desc_count; -+ unsigned int rx_ring_count; -+ unsigned int rx_desc_count; -+ -+ unsigned int tx_q_count; -+ unsigned int rx_q_count; -+ -+ /* Tx/Rx common settings */ -+ unsigned int pblx8; -+ -+ /* Tx settings */ -+ unsigned int tx_sf_mode; -+ unsigned int tx_threshold; -+ unsigned int tx_pbl; -+ unsigned int tx_osp_mode; -+ -+ /* Rx settings */ -+ unsigned int rx_sf_mode; -+ unsigned int rx_threshold; -+ unsigned int rx_pbl; -+ -+ /* Tx coalescing settings */ -+ unsigned int tx_usecs; -+ unsigned int tx_frames; -+ -+ /* Rx coalescing settings */ -+ unsigned int rx_riwt; -+ unsigned int rx_frames; -+ -+ /* Current Rx buffer size */ -+ unsigned int rx_buf_size; -+ -+ /* Flow control settings */ -+ unsigned int pause_autoneg; -+ unsigned int tx_pause; -+ unsigned int rx_pause; -+ -+ /* Receive Side Scaling settings */ -+ u8 rss_key[XGBE_RSS_HASH_KEY_SIZE]; -+ u32 rss_table[XGBE_RSS_MAX_TABLE_SIZE]; -+ u32 rss_options; -+ -+ /* MDIO settings */ -+ struct module *phy_module; -+ char *mii_bus_id; -+ struct mii_bus *mii; -+ int mdio_mmd; -+ struct phy_device *phydev; -+ int default_autoneg; -+ int default_speed; -+ -+ /* Current PHY settings */ -+ phy_interface_t phy_mode; -+ int phy_link; -+ int phy_speed; -+ unsigned int phy_tx_pause; -+ unsigned int phy_rx_pause; -+ -+ /* Netdev related settings */ -+ unsigned char mac_addr[ETH_ALEN]; -+ netdev_features_t netdev_features; -+ struct napi_struct napi; -+ struct xgbe_mmc_stats mmc_stats; -+ -+ /* Filtering support */ -+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; -+ -+ /* Device clocks */ -+ struct clk *sysclk; -+ unsigned long sysclk_rate; -+ struct clk *ptpclk; -+ unsigned long ptpclk_rate; -+ -+ /* Timestamp support */ -+ spinlock_t tstamp_lock; -+ struct ptp_clock_info ptp_clock_info; -+ struct ptp_clock *ptp_clock; -+ struct hwtstamp_config tstamp_config; -+ struct cyclecounter tstamp_cc; -+ struct timecounter tstamp_tc; -+ unsigned int tstamp_addend; -+ struct work_struct tx_tstamp_work; -+ struct sk_buff *tx_tstamp_skb; -+ u64 tx_tstamp; -+ -+ /* DCB support */ -+ struct ieee_ets *ets; -+ struct ieee_pfc *pfc; -+ unsigned int q2tc_map[XGBE_MAX_QUEUES]; -+ unsigned int prio2q_map[IEEE_8021QAZ_MAX_TCS]; -+ -+ /* Hardware features of the device */ -+ struct xgbe_hw_features hw_feat; -+ -+ /* Device restart work structure */ -+ struct work_struct restart_work; -+ -+ /* Keeps track of power mode */ -+ unsigned int power_down; -+ -+#ifdef CONFIG_DEBUG_FS -+ struct dentry *xgbe_debugfs; -+ -+ unsigned int debugfs_xgmac_reg; -+ -+ unsigned int debugfs_xpcs_mmd; -+ unsigned int debugfs_xpcs_reg; -+#endif -+}; -+ -+/* Function prototypes*/ -+ -+void xgbe_a0_init_function_ptrs_dev(struct xgbe_hw_if *); -+void xgbe_a0_init_function_ptrs_desc(struct xgbe_desc_if *); -+struct net_device_ops *xgbe_a0_get_netdev_ops(void); -+struct ethtool_ops *xgbe_a0_get_ethtool_ops(void); -+#ifdef CONFIG_AMD_XGBE_DCB -+const struct dcbnl_rtnl_ops *xgbe_a0_get_dcbnl_ops(void); -+#endif -+ -+int xgbe_a0_mdio_register(struct xgbe_prv_data *); -+void xgbe_a0_mdio_unregister(struct xgbe_prv_data *); -+void xgbe_a0_dump_phy_registers(struct xgbe_prv_data *); -+void xgbe_a0_ptp_register(struct xgbe_prv_data *); -+void xgbe_a0_ptp_unregister(struct xgbe_prv_data *); -+void xgbe_a0_dump_tx_desc(struct xgbe_ring *, unsigned int, unsigned int, -+ unsigned int); -+void xgbe_a0_dump_rx_desc(struct xgbe_ring *, struct xgbe_ring_desc *, -+ unsigned int); -+void xgbe_a0_print_pkt(struct net_device *, struct sk_buff *, bool); -+void xgbe_a0_get_all_hw_features(struct xgbe_prv_data *); -+int xgbe_a0_powerup(struct net_device *, unsigned int); -+int xgbe_a0_powerdown(struct net_device *, unsigned int); -+void xgbe_a0_init_rx_coalesce(struct xgbe_prv_data *); -+void xgbe_a0_init_tx_coalesce(struct xgbe_prv_data *); -+ -+#ifdef CONFIG_DEBUG_FS -+void xgbe_a0_debugfs_init(struct xgbe_prv_data *); -+void xgbe_a0_debugfs_exit(struct xgbe_prv_data *); -+#else -+static inline void xgbe_a0_debugfs_init(struct xgbe_prv_data *pdata) {} -+static inline void xgbe_a0_debugfs_exit(struct xgbe_prv_data *pdata) {} -+#endif /* CONFIG_DEBUG_FS */ -+ -+/* NOTE: Uncomment for TX and RX DESCRIPTOR DUMP in KERNEL LOG */ -+#if 0 -+#define XGMAC_ENABLE_TX_DESC_DUMP -+#define XGMAC_ENABLE_RX_DESC_DUMP -+#endif -+ -+/* NOTE: Uncomment for TX and RX PACKET DUMP in KERNEL LOG */ -+#if 0 -+#define XGMAC_ENABLE_TX_PKT_DUMP -+#define XGMAC_ENABLE_RX_PKT_DUMP -+#endif -+ -+/* NOTE: Uncomment for function trace log messages in KERNEL LOG */ -+#if 0 -+#define YDEBUG -+#define YDEBUG_MDIO -+#endif -+ -+/* For debug prints */ -+#ifdef YDEBUG -+#define DBGPR(x...) pr_alert(x) -+#define DBGPHY_REGS(x...) xgbe_a0_dump_phy_registers(x) -+#else -+#define DBGPR(x...) do { } while (0) -+#define DBGPHY_REGS(x...) do { } while (0) -+#endif -+ -+#ifdef YDEBUG_MDIO -+#define DBGPR_MDIO(x...) pr_alert(x) -+#else -+#define DBGPR_MDIO(x...) do { } while (0) -+#endif -+ -+#endif --- -2.6.2 - diff --git a/core/linux-aarch64/0003-arm64-acpi-drop-expert-patch.patch b/core/linux-aarch64/0001-arm64-acpi-drop-expert-patch.patch similarity index 77% rename from core/linux-aarch64/0003-arm64-acpi-drop-expert-patch.patch rename to core/linux-aarch64/0001-arm64-acpi-drop-expert-patch.patch index c7302e670..bacba7c37 100644 --- a/core/linux-aarch64/0003-arm64-acpi-drop-expert-patch.patch +++ b/core/linux-aarch64/0001-arm64-acpi-drop-expert-patch.patch @@ -1,14 +1,14 @@ -From e3c8b5ee334c3620008f7d0bf72482a0b9a09dff Mon Sep 17 00:00:00 2001 +From c789031f4cfa8c7933c9857dd86f4151dae63a65 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Sun, 3 May 2015 18:35:23 +0100 -Subject: [PATCH 3/6] arm64: acpi drop expert patch +Subject: [PATCH 1/4] arm64: acpi drop expert patch --- drivers/acpi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig -index 25dbb76..a7ad01e 100644 +index 82b96ee..bf5dc1a 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -5,7 +5,7 @@ @@ -21,5 +21,5 @@ index 25dbb76..a7ad01e 100644 select PNP default y -- -2.6.2 +2.7.0 diff --git a/core/linux-aarch64/0002-amd-xgbe-phy-a0-Add-support-for-XGBE-PHY-on-A0.patch b/core/linux-aarch64/0002-amd-xgbe-phy-a0-Add-support-for-XGBE-PHY-on-A0.patch deleted file mode 100644 index e50191626..000000000 --- a/core/linux-aarch64/0002-amd-xgbe-phy-a0-Add-support-for-XGBE-PHY-on-A0.patch +++ /dev/null @@ -1,1870 +0,0 @@ -From bd26075fcf2937250f4f2a32cedc9ed823f8e66c Mon Sep 17 00:00:00 2001 -From: Tom Lendacky -Date: Tue, 17 Mar 2015 10:58:38 -0500 -Subject: [PATCH 2/6] amd-xgbe-phy-a0: Add support for XGBE PHY on A0 - -Add XGBE phy driver support for A0 hardware. - -Signed-off-by: Tom Lendacky -[Add back AMD_XGBE_PHY removed upstream for B0 driver] -Signed-off-by: Mark Salter ---- - drivers/net/phy/Kconfig | 7 + - drivers/net/phy/Makefile | 1 + - drivers/net/phy/amd-xgbe-phy-a0.c | 1814 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 1822 insertions(+) - create mode 100644 drivers/net/phy/amd-xgbe-phy-a0.c - -diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig -index 60994a8..a8d24ad 100644 ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -29,6 +29,13 @@ config AMD_PHY - ---help--- - Currently supports the am79c874 - -+config AMD_XGBE_PHY -+ tristate "Driver for the AMD 10GbE (amd-xgbe) PHYs" -+ depends on (OF || ACPI) && HAS_IOMEM -+ depends on ARM64 || COMPILE_TEST -+ ---help--- -+ Currently supports the AMD 10GbE PHY -+ - config MARVELL_PHY - tristate "Drivers for Marvell PHYs" - ---help--- -diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile -index f31a4e2..8daa873 100644 ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -34,6 +34,7 @@ obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o - obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o - obj-$(CONFIG_AT803X_PHY) += at803x.o - obj-$(CONFIG_AMD_PHY) += amd.o -+obj-$(CONFIG_AMD_XGBE_PHY) += amd-xgbe-phy-a0.o - obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o - obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o - obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o -diff --git a/drivers/net/phy/amd-xgbe-phy-a0.c b/drivers/net/phy/amd-xgbe-phy-a0.c -new file mode 100644 -index 0000000..c352d5c ---- /dev/null -+++ b/drivers/net/phy/amd-xgbe-phy-a0.c -@@ -0,0 +1,1814 @@ -+/* -+ * AMD 10Gb Ethernet PHY driver -+ * -+ * This file is available to you under your choice of the following two -+ * licenses: -+ * -+ * License 1: GPLv2 -+ * -+ * Copyright (c) 2014 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 . -+ * -+ * -+ * License 2: Modified BSD -+ * -+ * Copyright (c) 2014 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 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+MODULE_AUTHOR("Tom Lendacky "); -+MODULE_LICENSE("Dual BSD/GPL"); -+MODULE_VERSION("0.0.0-a"); -+MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver"); -+ -+#define XGBE_PHY_ID 0x7996ced0 -+#define XGBE_PHY_MASK 0xfffffff0 -+ -+#define XGBE_PHY_SERDES_RETRY 32 -+#define XGBE_PHY_CHANNEL_PROPERTY "amd,serdes-channel" -+#define XGBE_PHY_SPEEDSET_PROPERTY "amd,speed-set" -+#define XGBE_PHY_BLWC_PROPERTY "amd,serdes-blwc" -+#define XGBE_PHY_CDR_RATE_PROPERTY "amd,serdes-cdr-rate" -+#define XGBE_PHY_PQ_SKEW_PROPERTY "amd,serdes-pq-skew" -+#define XGBE_PHY_TX_AMP_PROPERTY "amd,serdes-tx-amp" -+ -+#define XGBE_PHY_SPEEDS 3 -+#define XGBE_PHY_SPEED_1000 0 -+#define XGBE_PHY_SPEED_2500 1 -+#define XGBE_PHY_SPEED_10000 2 -+ -+#define XGBE_AN_INT_CMPLT 0x01 -+#define XGBE_AN_INC_LINK 0x02 -+#define XGBE_AN_PG_RCV 0x04 -+#define XGBE_AN_INT_MASK 0x07 -+ -+#define XNP_MCF_NULL_MESSAGE 0x001 -+#define XNP_ACK_PROCESSED BIT(12) -+#define XNP_MP_FORMATTED BIT(13) -+#define XNP_NP_EXCHANGE BIT(15) -+ -+#define XGBE_PHY_RATECHANGE_COUNT 500 -+ -+#define XGBE_PHY_KR_TRAINING_START 0x01 -+#define XGBE_PHY_KR_TRAINING_ENABLE 0x02 -+ -+#define XGBE_PHY_FEC_ENABLE 0x01 -+#define XGBE_PHY_FEC_FORWARD 0x02 -+#define XGBE_PHY_FEC_MASK 0x03 -+ -+#ifndef MDIO_PMA_10GBR_PMD_CTRL -+#define MDIO_PMA_10GBR_PMD_CTRL 0x0096 -+#endif -+ -+#ifndef MDIO_PMA_10GBR_FEC_ABILITY -+#define MDIO_PMA_10GBR_FEC_ABILITY 0x00aa -+#endif -+ -+#ifndef MDIO_PMA_10GBR_FEC_CTRL -+#define MDIO_PMA_10GBR_FEC_CTRL 0x00ab -+#endif -+ -+#ifndef MDIO_AN_XNP -+#define MDIO_AN_XNP 0x0016 -+#endif -+ -+#ifndef MDIO_AN_LPX -+#define MDIO_AN_LPX 0x0019 -+#endif -+ -+#ifndef MDIO_AN_INTMASK -+#define MDIO_AN_INTMASK 0x8001 -+#endif -+ -+#ifndef MDIO_AN_INT -+#define MDIO_AN_INT 0x8002 -+#endif -+ -+#ifndef MDIO_AN_KR_CTRL -+#define MDIO_AN_KR_CTRL 0x8003 -+#endif -+ -+#ifndef MDIO_CTRL1_SPEED1G -+#define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100) -+#endif -+ -+#ifndef MDIO_KR_CTRL_PDETECT -+#define MDIO_KR_CTRL_PDETECT 0x01 -+#endif -+ -+#define GET_BITS(_var, _index, _width) \ -+ (((_var) >> (_index)) & ((0x1 << (_width)) - 1)) -+ -+#define SET_BITS(_var, _index, _width, _val) \ -+do { \ -+ (_var) &= ~(((0x1 << (_width)) - 1) << (_index)); \ -+ (_var) |= (((_val) & ((0x1 << (_width)) - 1)) << (_index)); \ -+} while (0) -+ -+#define XCMU_IOREAD(_priv, _reg) \ -+ ioread16((_priv)->cmu_regs + _reg) -+ -+#define XCMU_IOWRITE(_priv, _reg, _val) \ -+ iowrite16((_val), (_priv)->cmu_regs + _reg) -+ -+#define XRXTX_IOREAD(_priv, _reg) \ -+ ioread16((_priv)->rxtx_regs + _reg) -+ -+#define XRXTX_IOREAD_BITS(_priv, _reg, _field) \ -+ GET_BITS(XRXTX_IOREAD((_priv), _reg), \ -+ _reg##_##_field##_INDEX, \ -+ _reg##_##_field##_WIDTH) -+ -+#define XRXTX_IOWRITE(_priv, _reg, _val) \ -+ iowrite16((_val), (_priv)->rxtx_regs + _reg) -+ -+#define XRXTX_IOWRITE_BITS(_priv, _reg, _field, _val) \ -+do { \ -+ u16 reg_val = XRXTX_IOREAD((_priv), _reg); \ -+ SET_BITS(reg_val, \ -+ _reg##_##_field##_INDEX, \ -+ _reg##_##_field##_WIDTH, (_val)); \ -+ XRXTX_IOWRITE((_priv), _reg, reg_val); \ -+} while (0) -+ -+/* SerDes CMU register offsets */ -+#define CMU_REG15 0x003c -+#define CMU_REG16 0x0040 -+ -+/* SerDes CMU register entry bit positions and sizes */ -+#define CMU_REG16_TX_RATE_CHANGE_BASE 15 -+#define CMU_REG16_RX_RATE_CHANGE_BASE 14 -+#define CMU_REG16_RATE_CHANGE_DECR 2 -+ -+/* SerDes RxTx register offsets */ -+#define RXTX_REG2 0x0008 -+#define RXTX_REG3 0x000c -+#define RXTX_REG5 0x0014 -+#define RXTX_REG6 0x0018 -+#define RXTX_REG20 0x0050 -+#define RXTX_REG53 0x00d4 -+#define RXTX_REG114 0x01c8 -+#define RXTX_REG115 0x01cc -+#define RXTX_REG142 0x0238 -+ -+/* SerDes RxTx register entry bit positions and sizes */ -+#define RXTX_REG2_RESETB_INDEX 15 -+#define RXTX_REG2_RESETB_WIDTH 1 -+#define RXTX_REG3_TX_DATA_RATE_INDEX 14 -+#define RXTX_REG3_TX_DATA_RATE_WIDTH 2 -+#define RXTX_REG3_TX_WORD_MODE_INDEX 11 -+#define RXTX_REG3_TX_WORD_MODE_WIDTH 3 -+#define RXTX_REG5_TXAMP_CNTL_INDEX 7 -+#define RXTX_REG5_TXAMP_CNTL_WIDTH 4 -+#define RXTX_REG6_RX_DATA_RATE_INDEX 9 -+#define RXTX_REG6_RX_DATA_RATE_WIDTH 2 -+#define RXTX_REG6_RX_WORD_MODE_INDEX 11 -+#define RXTX_REG6_RX_WORD_MODE_WIDTH 3 -+#define RXTX_REG20_BLWC_ENA_INDEX 2 -+#define RXTX_REG20_BLWC_ENA_WIDTH 1 -+#define RXTX_REG53_RX_PLLSELECT_INDEX 15 -+#define RXTX_REG53_RX_PLLSELECT_WIDTH 1 -+#define RXTX_REG53_TX_PLLSELECT_INDEX 14 -+#define RXTX_REG53_TX_PLLSELECT_WIDTH 1 -+#define RXTX_REG53_PI_SPD_SEL_CDR_INDEX 10 -+#define RXTX_REG53_PI_SPD_SEL_CDR_WIDTH 4 -+#define RXTX_REG114_PQ_REG_INDEX 9 -+#define RXTX_REG114_PQ_REG_WIDTH 7 -+#define RXTX_REG115_FORCE_LAT_CAL_START_INDEX 2 -+#define RXTX_REG115_FORCE_LAT_CAL_START_WIDTH 1 -+#define RXTX_REG115_FORCE_SUM_CAL_START_INDEX 1 -+#define RXTX_REG115_FORCE_SUM_CAL_START_WIDTH 1 -+#define RXTX_REG142_SUM_CALIB_DONE_INDEX 15 -+#define RXTX_REG142_SUM_CALIB_DONE_WIDTH 1 -+#define RXTX_REG142_SUM_CALIB_ERR_INDEX 14 -+#define RXTX_REG142_SUM_CALIB_ERR_WIDTH 1 -+#define RXTX_REG142_LAT_CALIB_DONE_INDEX 11 -+#define RXTX_REG142_LAT_CALIB_DONE_WIDTH 1 -+ -+#define RXTX_FULL_RATE 0x0 -+#define RXTX_HALF_RATE 0x1 -+#define RXTX_FIFTH_RATE 0x3 -+#define RXTX_66BIT_WORD 0x7 -+#define RXTX_10BIT_WORD 0x1 -+#define RXTX_10G_BLWC 0x0 -+#define RXTX_1G_BLWC 0x1 -+#define RXTX_10G_TX_AMP 0xa -+#define RXTX_1G_TX_AMP 0xf -+#define RXTX_10G_CDR 0x7 -+#define RXTX_1G_CDR 0x2 -+#define RXTX_10G_PLL 0x1 -+#define RXTX_1G_PLL 0x0 -+#define RXTX_10G_PQ 0x1e -+#define RXTX_1G_PQ 0xa -+ -+DEFINE_SPINLOCK(cmu_lock); -+ -+static const u32 amd_xgbe_phy_serdes_blwc[] = { -+ RXTX_1G_BLWC, -+ RXTX_1G_BLWC, -+ RXTX_10G_BLWC, -+}; -+ -+static const u32 amd_xgbe_phy_serdes_cdr_rate[] = { -+ RXTX_1G_CDR, -+ RXTX_1G_CDR, -+ RXTX_10G_CDR, -+}; -+ -+static const u32 amd_xgbe_phy_serdes_pq_skew[] = { -+ RXTX_1G_PQ, -+ RXTX_1G_PQ, -+ RXTX_10G_PQ, -+}; -+ -+static const u32 amd_xgbe_phy_serdes_tx_amp[] = { -+ RXTX_1G_TX_AMP, -+ RXTX_1G_TX_AMP, -+ RXTX_10G_TX_AMP, -+}; -+ -+enum amd_xgbe_phy_an { -+ AMD_XGBE_AN_READY = 0, -+ AMD_XGBE_AN_PAGE_RECEIVED, -+ AMD_XGBE_AN_INCOMPAT_LINK, -+ AMD_XGBE_AN_COMPLETE, -+ AMD_XGBE_AN_NO_LINK, -+ AMD_XGBE_AN_ERROR, -+}; -+ -+enum amd_xgbe_phy_rx { -+ AMD_XGBE_RX_BPA = 0, -+ AMD_XGBE_RX_XNP, -+ AMD_XGBE_RX_COMPLETE, -+ AMD_XGBE_RX_ERROR, -+}; -+ -+enum amd_xgbe_phy_mode { -+ AMD_XGBE_MODE_KR, -+ AMD_XGBE_MODE_KX, -+}; -+ -+enum amd_xgbe_phy_speedset { -+ AMD_XGBE_PHY_SPEEDSET_1000_10000 = 0, -+ AMD_XGBE_PHY_SPEEDSET_2500_10000, -+}; -+ -+struct amd_xgbe_phy_priv { -+ struct platform_device *pdev; -+ struct acpi_device *adev; -+ struct device *dev; -+ -+ struct phy_device *phydev; -+ -+ /* SerDes related mmio resources */ -+ struct resource *rxtx_res; -+ struct resource *cmu_res; -+ -+ /* SerDes related mmio registers */ -+ void __iomem *rxtx_regs; /* SerDes Rx/Tx CSRs */ -+ void __iomem *cmu_regs; /* SerDes CMU CSRs */ -+ -+ int an_irq; -+ char an_irq_name[IFNAMSIZ + 32]; -+ struct work_struct an_irq_work; -+ unsigned int an_irq_allocated; -+ -+ unsigned int serdes_channel; -+ unsigned int speed_set; -+ -+ /* Maintain link status for re-starting auto-negotiation */ -+ unsigned int link; -+ -+ /* SerDes UEFI configurable settings. -+ * Switching between modes/speeds requires new values for some -+ * SerDes settings. The values can be supplied as device -+ * properties in array format. The first array entry is for -+ * 1GbE, second for 2.5GbE and third for 10GbE -+ */ -+ u32 serdes_blwc[XGBE_PHY_SPEEDS]; -+ u32 serdes_cdr_rate[XGBE_PHY_SPEEDS]; -+ u32 serdes_pq_skew[XGBE_PHY_SPEEDS]; -+ u32 serdes_tx_amp[XGBE_PHY_SPEEDS]; -+ -+ /* Auto-negotiation state machine support */ -+ struct mutex an_mutex; -+ enum amd_xgbe_phy_an an_result; -+ enum amd_xgbe_phy_an an_state; -+ enum amd_xgbe_phy_rx kr_state; -+ enum amd_xgbe_phy_rx kx_state; -+ struct work_struct an_work; -+ struct workqueue_struct *an_workqueue; -+ unsigned int an_supported; -+ unsigned int parallel_detect; -+ unsigned int fec_ability; -+ -+ unsigned int lpm_ctrl; /* CTRL1 for resume */ -+}; -+ -+static int amd_xgbe_an_disable_kr_training(struct phy_device *phydev) -+{ -+ int ret; -+ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL); -+ if (ret < 0) -+ return ret; -+ -+ ret &= ~XGBE_PHY_KR_TRAINING_ENABLE; -+ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, ret); -+ -+ return 0; -+} -+ -+static int amd_xgbe_phy_pcs_power_cycle(struct phy_device *phydev) -+{ -+ int ret; -+ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1); -+ if (ret < 0) -+ return ret; -+ -+ ret |= MDIO_CTRL1_LPOWER; -+ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, ret); -+ -+ usleep_range(75, 100); -+ -+ ret &= ~MDIO_CTRL1_LPOWER; -+ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, ret); -+ -+ return 0; -+} -+ -+static void amd_xgbe_phy_serdes_start_ratechange(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ u16 val, mask; -+ -+ /* Assert Rx and Tx ratechange in CMU_reg16 */ -+ val = XCMU_IOREAD(priv, CMU_REG16); -+ -+ mask = (1 << (CMU_REG16_TX_RATE_CHANGE_BASE - -+ (priv->serdes_channel * CMU_REG16_RATE_CHANGE_DECR))) | -+ (1 << (CMU_REG16_RX_RATE_CHANGE_BASE - -+ (priv->serdes_channel * CMU_REG16_RATE_CHANGE_DECR))); -+ val |= mask; -+ -+ XCMU_IOWRITE(priv, CMU_REG16, val); -+} -+ -+static void amd_xgbe_phy_serdes_complete_ratechange(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ u16 val, mask; -+ unsigned int wait; -+ -+ /* Release Rx and Tx ratechange for proper channel in CMU_reg16 */ -+ val = XCMU_IOREAD(priv, CMU_REG16); -+ -+ mask = (1 << (CMU_REG16_TX_RATE_CHANGE_BASE - -+ (priv->serdes_channel * CMU_REG16_RATE_CHANGE_DECR))) | -+ (1 << (CMU_REG16_RX_RATE_CHANGE_BASE - -+ (priv->serdes_channel * CMU_REG16_RATE_CHANGE_DECR))); -+ val &= ~mask; -+ -+ XCMU_IOWRITE(priv, CMU_REG16, val); -+ -+ /* Wait for Rx and Tx ready in CMU_reg15 */ -+ mask = (1 << priv->serdes_channel) | -+ (1 << (priv->serdes_channel + 8)); -+ wait = XGBE_PHY_RATECHANGE_COUNT; -+ while (wait--) { -+ udelay(50); -+ -+ val = XCMU_IOREAD(priv, CMU_REG15); -+ if ((val & mask) == mask) -+ return; -+ } -+ -+ netdev_dbg(phydev->attached_dev, "SerDes rx/tx not ready (%#hx)\n", -+ val); -+} -+ -+static int amd_xgbe_phy_xgmii_mode(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ int ret; -+ -+ /* Disable KR training */ -+ ret = amd_xgbe_an_disable_kr_training(phydev); -+ if (ret < 0) -+ return ret; -+ -+ /* Set PCS to KR/10G speed */ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2); -+ if (ret < 0) -+ return ret; -+ -+ ret &= ~MDIO_PCS_CTRL2_TYPE; -+ ret |= MDIO_PCS_CTRL2_10GBR; -+ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2, ret); -+ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1); -+ if (ret < 0) -+ return ret; -+ -+ ret &= ~MDIO_CTRL1_SPEEDSEL; -+ ret |= MDIO_CTRL1_SPEED10G; -+ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, ret); -+ -+ ret = amd_xgbe_phy_pcs_power_cycle(phydev); -+ if (ret < 0) -+ return ret; -+ -+ /* Set SerDes to 10G speed */ -+ spin_lock(&cmu_lock); -+ -+ amd_xgbe_phy_serdes_start_ratechange(phydev); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG3, TX_DATA_RATE, RXTX_FULL_RATE); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG3, TX_WORD_MODE, RXTX_66BIT_WORD); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG5, TXAMP_CNTL, -+ priv->serdes_tx_amp[XGBE_PHY_SPEED_10000]); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG6, RX_DATA_RATE, RXTX_FULL_RATE); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG6, RX_WORD_MODE, RXTX_66BIT_WORD); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG20, BLWC_ENA, -+ priv->serdes_blwc[XGBE_PHY_SPEED_10000]); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG53, RX_PLLSELECT, RXTX_10G_PLL); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG53, TX_PLLSELECT, RXTX_10G_PLL); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG53, PI_SPD_SEL_CDR, -+ priv->serdes_cdr_rate[XGBE_PHY_SPEED_10000]); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG114, PQ_REG, -+ priv->serdes_pq_skew[XGBE_PHY_SPEED_10000]); -+ -+ amd_xgbe_phy_serdes_complete_ratechange(phydev); -+ -+ spin_unlock(&cmu_lock); -+ -+ return 0; -+} -+ -+static int amd_xgbe_phy_gmii_2500_mode(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ int ret; -+ -+ /* Disable KR training */ -+ ret = amd_xgbe_an_disable_kr_training(phydev); -+ if (ret < 0) -+ return ret; -+ -+ /* Set PCS to KX/1G speed */ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2); -+ if (ret < 0) -+ return ret; -+ -+ ret &= ~MDIO_PCS_CTRL2_TYPE; -+ ret |= MDIO_PCS_CTRL2_10GBX; -+ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2, ret); -+ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1); -+ if (ret < 0) -+ return ret; -+ -+ ret &= ~MDIO_CTRL1_SPEEDSEL; -+ ret |= MDIO_CTRL1_SPEED1G; -+ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, ret); -+ -+ ret = amd_xgbe_phy_pcs_power_cycle(phydev); -+ if (ret < 0) -+ return ret; -+ -+ /* Set SerDes to 2.5G speed */ -+ spin_lock(&cmu_lock); -+ -+ amd_xgbe_phy_serdes_start_ratechange(phydev); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG3, TX_DATA_RATE, RXTX_HALF_RATE); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG3, TX_WORD_MODE, RXTX_10BIT_WORD); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG5, TXAMP_CNTL, -+ priv->serdes_tx_amp[XGBE_PHY_SPEED_2500]); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG6, RX_DATA_RATE, RXTX_HALF_RATE); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG6, RX_WORD_MODE, RXTX_10BIT_WORD); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG20, BLWC_ENA, -+ priv->serdes_blwc[XGBE_PHY_SPEED_2500]); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG53, RX_PLLSELECT, RXTX_1G_PLL); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG53, TX_PLLSELECT, RXTX_1G_PLL); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG53, PI_SPD_SEL_CDR, -+ priv->serdes_cdr_rate[XGBE_PHY_SPEED_2500]); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG114, PQ_REG, -+ priv->serdes_pq_skew[XGBE_PHY_SPEED_2500]); -+ -+ amd_xgbe_phy_serdes_complete_ratechange(phydev); -+ -+ spin_unlock(&cmu_lock); -+ -+ return 0; -+} -+ -+static int amd_xgbe_phy_gmii_mode(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ int ret; -+ -+ /* Disable KR training */ -+ ret = amd_xgbe_an_disable_kr_training(phydev); -+ if (ret < 0) -+ return ret; -+ -+ /* Set PCS to KX/1G speed */ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2); -+ if (ret < 0) -+ return ret; -+ -+ ret &= ~MDIO_PCS_CTRL2_TYPE; -+ ret |= MDIO_PCS_CTRL2_10GBX; -+ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2, ret); -+ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1); -+ if (ret < 0) -+ return ret; -+ -+ ret &= ~MDIO_CTRL1_SPEEDSEL; -+ ret |= MDIO_CTRL1_SPEED1G; -+ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, ret); -+ -+ ret = amd_xgbe_phy_pcs_power_cycle(phydev); -+ if (ret < 0) -+ return ret; -+ -+ /* Set SerDes to 1G speed */ -+ spin_lock(&cmu_lock); -+ -+ amd_xgbe_phy_serdes_start_ratechange(phydev); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG3, TX_DATA_RATE, RXTX_FIFTH_RATE); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG3, TX_WORD_MODE, RXTX_10BIT_WORD); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG5, TXAMP_CNTL, -+ priv->serdes_tx_amp[XGBE_PHY_SPEED_1000]); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG6, RX_DATA_RATE, RXTX_FIFTH_RATE); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG6, RX_WORD_MODE, RXTX_10BIT_WORD); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG20, BLWC_ENA, -+ priv->serdes_blwc[XGBE_PHY_SPEED_1000]); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG53, RX_PLLSELECT, RXTX_1G_PLL); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG53, TX_PLLSELECT, RXTX_1G_PLL); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG53, PI_SPD_SEL_CDR, -+ priv->serdes_cdr_rate[XGBE_PHY_SPEED_1000]); -+ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG114, PQ_REG, -+ priv->serdes_pq_skew[XGBE_PHY_SPEED_1000]); -+ -+ amd_xgbe_phy_serdes_complete_ratechange(phydev); -+ -+ spin_unlock(&cmu_lock); -+ -+ return 0; -+} -+ -+static int amd_xgbe_phy_cur_mode(struct phy_device *phydev, -+ enum amd_xgbe_phy_mode *mode) -+{ -+ int ret; -+ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2); -+ if (ret < 0) -+ return ret; -+ -+ if ((ret & MDIO_PCS_CTRL2_TYPE) == MDIO_PCS_CTRL2_10GBR) -+ *mode = AMD_XGBE_MODE_KR; -+ else -+ *mode = AMD_XGBE_MODE_KX; -+ -+ return 0; -+} -+ -+static bool amd_xgbe_phy_in_kr_mode(struct phy_device *phydev) -+{ -+ enum amd_xgbe_phy_mode mode; -+ -+ if (amd_xgbe_phy_cur_mode(phydev, &mode)) -+ return false; -+ -+ return (mode == AMD_XGBE_MODE_KR); -+} -+ -+static int amd_xgbe_phy_switch_mode(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ int ret; -+ -+ /* If we are in KR switch to KX, and vice-versa */ -+ if (amd_xgbe_phy_in_kr_mode(phydev)) { -+ if (priv->speed_set == AMD_XGBE_PHY_SPEEDSET_1000_10000) -+ ret = amd_xgbe_phy_gmii_mode(phydev); -+ else -+ ret = amd_xgbe_phy_gmii_2500_mode(phydev); -+ } else { -+ ret = amd_xgbe_phy_xgmii_mode(phydev); -+ } -+ -+ return ret; -+} -+ -+static int amd_xgbe_phy_set_mode(struct phy_device *phydev, -+ enum amd_xgbe_phy_mode mode) -+{ -+ enum amd_xgbe_phy_mode cur_mode; -+ int ret; -+ -+ ret = amd_xgbe_phy_cur_mode(phydev, &cur_mode); -+ if (ret) -+ return ret; -+ -+ if (mode != cur_mode) -+ ret = amd_xgbe_phy_switch_mode(phydev); -+ -+ return ret; -+} -+ -+static int amd_xgbe_phy_set_an(struct phy_device *phydev, bool enable, -+ bool restart) -+{ -+ int ret; -+ -+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1); -+ if (ret < 0) -+ return ret; -+ -+ ret &= ~MDIO_AN_CTRL1_ENABLE; -+ -+ if (enable) -+ ret |= MDIO_AN_CTRL1_ENABLE; -+ -+ if (restart) -+ ret |= MDIO_AN_CTRL1_RESTART; -+ -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, ret); -+ -+ return 0; -+} -+ -+static int amd_xgbe_phy_restart_an(struct phy_device *phydev) -+{ -+ return amd_xgbe_phy_set_an(phydev, true, true); -+} -+ -+static int amd_xgbe_phy_disable_an(struct phy_device *phydev) -+{ -+ return amd_xgbe_phy_set_an(phydev, false, false); -+} -+ -+static enum amd_xgbe_phy_an amd_xgbe_an_tx_training(struct phy_device *phydev, -+ enum amd_xgbe_phy_rx *state) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ int ad_reg, lp_reg, ret; -+ -+ *state = AMD_XGBE_RX_COMPLETE; -+ -+ /* If we're not in KR mode then we're done */ -+ if (!amd_xgbe_phy_in_kr_mode(phydev)) -+ return AMD_XGBE_AN_PAGE_RECEIVED; -+ -+ /* Enable/Disable FEC */ -+ ad_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); -+ if (ad_reg < 0) -+ return AMD_XGBE_AN_ERROR; -+ -+ lp_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPA + 2); -+ if (lp_reg < 0) -+ return AMD_XGBE_AN_ERROR; -+ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FEC_CTRL); -+ if (ret < 0) -+ return AMD_XGBE_AN_ERROR; -+ -+ ret &= ~XGBE_PHY_FEC_MASK; -+ if ((ad_reg & 0xc000) && (lp_reg & 0xc000)) -+ ret |= priv->fec_ability; -+ -+ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FEC_CTRL, ret); -+ -+ /* Start KR training */ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL); -+ if (ret < 0) -+ return AMD_XGBE_AN_ERROR; -+ -+ if (ret & XGBE_PHY_KR_TRAINING_ENABLE) { -+ ret |= XGBE_PHY_KR_TRAINING_START; -+ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, -+ ret); -+ } -+ -+ return AMD_XGBE_AN_PAGE_RECEIVED; -+} -+ -+static enum amd_xgbe_phy_an amd_xgbe_an_tx_xnp(struct phy_device *phydev, -+ enum amd_xgbe_phy_rx *state) -+{ -+ u16 msg; -+ -+ *state = AMD_XGBE_RX_XNP; -+ -+ msg = XNP_MCF_NULL_MESSAGE; -+ msg |= XNP_MP_FORMATTED; -+ -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_XNP + 2, 0); -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_XNP + 1, 0); -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_XNP, msg); -+ -+ return AMD_XGBE_AN_PAGE_RECEIVED; -+} -+ -+static enum amd_xgbe_phy_an amd_xgbe_an_rx_bpa(struct phy_device *phydev, -+ enum amd_xgbe_phy_rx *state) -+{ -+ unsigned int link_support; -+ int ret, ad_reg, lp_reg; -+ -+ /* Read Base Ability register 2 first */ -+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPA + 1); -+ if (ret < 0) -+ return AMD_XGBE_AN_ERROR; -+ -+ /* Check for a supported mode, otherwise restart in a different one */ -+ link_support = amd_xgbe_phy_in_kr_mode(phydev) ? 0x80 : 0x20; -+ if (!(ret & link_support)) -+ return AMD_XGBE_AN_INCOMPAT_LINK; -+ -+ /* Check Extended Next Page support */ -+ ad_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE); -+ if (ad_reg < 0) -+ return AMD_XGBE_AN_ERROR; -+ -+ lp_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPA); -+ if (lp_reg < 0) -+ return AMD_XGBE_AN_ERROR; -+ -+ return ((ad_reg & XNP_NP_EXCHANGE) || (lp_reg & XNP_NP_EXCHANGE)) ? -+ amd_xgbe_an_tx_xnp(phydev, state) : -+ amd_xgbe_an_tx_training(phydev, state); -+} -+ -+static enum amd_xgbe_phy_an amd_xgbe_an_rx_xnp(struct phy_device *phydev, -+ enum amd_xgbe_phy_rx *state) -+{ -+ int ad_reg, lp_reg; -+ -+ /* Check Extended Next Page support */ -+ ad_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_XNP); -+ if (ad_reg < 0) -+ return AMD_XGBE_AN_ERROR; -+ -+ lp_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPX); -+ if (lp_reg < 0) -+ return AMD_XGBE_AN_ERROR; -+ -+ return ((ad_reg & XNP_NP_EXCHANGE) || (lp_reg & XNP_NP_EXCHANGE)) ? -+ amd_xgbe_an_tx_xnp(phydev, state) : -+ amd_xgbe_an_tx_training(phydev, state); -+} -+ -+static enum amd_xgbe_phy_an amd_xgbe_an_page_received(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ enum amd_xgbe_phy_rx *state; -+ int ret; -+ -+ state = amd_xgbe_phy_in_kr_mode(phydev) ? &priv->kr_state -+ : &priv->kx_state; -+ -+ switch (*state) { -+ case AMD_XGBE_RX_BPA: -+ ret = amd_xgbe_an_rx_bpa(phydev, state); -+ break; -+ -+ case AMD_XGBE_RX_XNP: -+ ret = amd_xgbe_an_rx_xnp(phydev, state); -+ break; -+ -+ default: -+ ret = AMD_XGBE_AN_ERROR; -+ } -+ -+ return ret; -+} -+ -+static enum amd_xgbe_phy_an amd_xgbe_an_incompat_link(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ int ret; -+ -+ /* Be sure we aren't looping trying to negotiate */ -+ if (amd_xgbe_phy_in_kr_mode(phydev)) { -+ priv->kr_state = AMD_XGBE_RX_ERROR; -+ -+ if (!(phydev->supported & SUPPORTED_1000baseKX_Full) && -+ !(phydev->supported & SUPPORTED_2500baseX_Full)) -+ return AMD_XGBE_AN_NO_LINK; -+ -+ if (priv->kx_state != AMD_XGBE_RX_BPA) -+ return AMD_XGBE_AN_NO_LINK; -+ } else { -+ priv->kx_state = AMD_XGBE_RX_ERROR; -+ -+ if (!(phydev->supported & SUPPORTED_10000baseKR_Full)) -+ return AMD_XGBE_AN_NO_LINK; -+ -+ if (priv->kr_state != AMD_XGBE_RX_BPA) -+ return AMD_XGBE_AN_NO_LINK; -+ } -+ -+ ret = amd_xgbe_phy_disable_an(phydev); -+ if (ret) -+ return AMD_XGBE_AN_ERROR; -+ -+ ret = amd_xgbe_phy_switch_mode(phydev); -+ if (ret) -+ return AMD_XGBE_AN_ERROR; -+ -+ ret = amd_xgbe_phy_restart_an(phydev); -+ if (ret) -+ return AMD_XGBE_AN_ERROR; -+ -+ return AMD_XGBE_AN_INCOMPAT_LINK; -+} -+ -+static irqreturn_t amd_xgbe_an_isr(int irq, void *data) -+{ -+ struct amd_xgbe_phy_priv *priv = (struct amd_xgbe_phy_priv *)data; -+ -+ /* Interrupt reason must be read and cleared outside of IRQ context */ -+ disable_irq_nosync(priv->an_irq); -+ -+ queue_work(priv->an_workqueue, &priv->an_irq_work); -+ -+ return IRQ_HANDLED; -+} -+ -+static void amd_xgbe_an_irq_work(struct work_struct *work) -+{ -+ struct amd_xgbe_phy_priv *priv = container_of(work, -+ struct amd_xgbe_phy_priv, -+ an_irq_work); -+ -+ /* Avoid a race between enabling the IRQ and exiting the work by -+ * waiting for the work to finish and then queueing it -+ */ -+ flush_work(&priv->an_work); -+ queue_work(priv->an_workqueue, &priv->an_work); -+} -+ -+static void amd_xgbe_an_state_machine(struct work_struct *work) -+{ -+ struct amd_xgbe_phy_priv *priv = container_of(work, -+ struct amd_xgbe_phy_priv, -+ an_work); -+ struct phy_device *phydev = priv->phydev; -+ enum amd_xgbe_phy_an cur_state = priv->an_state; -+ int int_reg, int_mask; -+ -+ mutex_lock(&priv->an_mutex); -+ -+ /* Read the interrupt */ -+ int_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT); -+ if (!int_reg) -+ goto out; -+ -+next_int: -+ if (int_reg < 0) { -+ priv->an_state = AMD_XGBE_AN_ERROR; -+ int_mask = XGBE_AN_INT_MASK; -+ } else if (int_reg & XGBE_AN_PG_RCV) { -+ priv->an_state = AMD_XGBE_AN_PAGE_RECEIVED; -+ int_mask = XGBE_AN_PG_RCV; -+ } else if (int_reg & XGBE_AN_INC_LINK) { -+ priv->an_state = AMD_XGBE_AN_INCOMPAT_LINK; -+ int_mask = XGBE_AN_INC_LINK; -+ } else if (int_reg & XGBE_AN_INT_CMPLT) { -+ priv->an_state = AMD_XGBE_AN_COMPLETE; -+ int_mask = XGBE_AN_INT_CMPLT; -+ } else { -+ priv->an_state = AMD_XGBE_AN_ERROR; -+ int_mask = 0; -+ } -+ -+ /* Clear the interrupt to be processed */ -+ int_reg &= ~int_mask; -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, int_reg); -+ -+ priv->an_result = priv->an_state; -+ -+again: -+ cur_state = priv->an_state; -+ -+ switch (priv->an_state) { -+ case AMD_XGBE_AN_READY: -+ priv->an_supported = 0; -+ break; -+ -+ case AMD_XGBE_AN_PAGE_RECEIVED: -+ priv->an_state = amd_xgbe_an_page_received(phydev); -+ priv->an_supported++; -+ break; -+ -+ case AMD_XGBE_AN_INCOMPAT_LINK: -+ priv->an_supported = 0; -+ priv->parallel_detect = 0; -+ priv->an_state = amd_xgbe_an_incompat_link(phydev); -+ break; -+ -+ case AMD_XGBE_AN_COMPLETE: -+ priv->parallel_detect = priv->an_supported ? 0 : 1; -+ netdev_dbg(phydev->attached_dev, "%s successful\n", -+ priv->an_supported ? "Auto negotiation" -+ : "Parallel detection"); -+ break; -+ -+ case AMD_XGBE_AN_NO_LINK: -+ break; -+ -+ default: -+ priv->an_state = AMD_XGBE_AN_ERROR; -+ } -+ -+ if (priv->an_state == AMD_XGBE_AN_NO_LINK) { -+ /* Disable auto-negotiation for now - it will be -+ * re-enabled once a link is established -+ */ -+ amd_xgbe_phy_disable_an(phydev); -+ -+ int_reg = 0; -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0); -+ } else if (priv->an_state == AMD_XGBE_AN_ERROR) { -+ netdev_err(phydev->attached_dev, -+ "error during auto-negotiation, state=%u\n", -+ cur_state); -+ -+ int_reg = 0; -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0); -+ } -+ -+ if (priv->an_state >= AMD_XGBE_AN_COMPLETE) { -+ priv->an_result = priv->an_state; -+ priv->an_state = AMD_XGBE_AN_READY; -+ priv->kr_state = AMD_XGBE_RX_BPA; -+ priv->kx_state = AMD_XGBE_RX_BPA; -+ } -+ -+ if (cur_state != priv->an_state) -+ goto again; -+ -+ if (int_reg) -+ goto next_int; -+ -+out: -+ enable_irq(priv->an_irq); -+ -+ mutex_unlock(&priv->an_mutex); -+} -+ -+static int amd_xgbe_an_init(struct phy_device *phydev) -+{ -+ int ret; -+ -+ /* Set up Advertisement register 3 first */ -+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); -+ if (ret < 0) -+ return ret; -+ -+ if (phydev->supported & SUPPORTED_10000baseR_FEC) -+ ret |= 0xc000; -+ else -+ ret &= ~0xc000; -+ -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2, ret); -+ -+ /* Set up Advertisement register 2 next */ -+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1); -+ if (ret < 0) -+ return ret; -+ -+ if (phydev->supported & SUPPORTED_10000baseKR_Full) -+ ret |= 0x80; -+ else -+ ret &= ~0x80; -+ -+ if ((phydev->supported & SUPPORTED_1000baseKX_Full) || -+ (phydev->supported & SUPPORTED_2500baseX_Full)) -+ ret |= 0x20; -+ else -+ ret &= ~0x20; -+ -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1, ret); -+ -+ /* Set up Advertisement register 1 last */ -+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE); -+ if (ret < 0) -+ return ret; -+ -+ if (phydev->supported & SUPPORTED_Pause) -+ ret |= 0x400; -+ else -+ ret &= ~0x400; -+ -+ if (phydev->supported & SUPPORTED_Asym_Pause) -+ ret |= 0x800; -+ else -+ ret &= ~0x800; -+ -+ /* We don't intend to perform XNP */ -+ ret &= ~XNP_NP_EXCHANGE; -+ -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE, ret); -+ -+ return 0; -+} -+ -+static int amd_xgbe_phy_soft_reset(struct phy_device *phydev) -+{ -+ int count, ret; -+ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1); -+ if (ret < 0) -+ return ret; -+ -+ ret |= MDIO_CTRL1_RESET; -+ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, ret); -+ -+ count = 50; -+ do { -+ msleep(20); -+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1); -+ if (ret < 0) -+ return ret; -+ } while ((ret & MDIO_CTRL1_RESET) && --count); -+ -+ if (ret & MDIO_CTRL1_RESET) -+ return -ETIMEDOUT; -+ -+ /* Disable auto-negotiation for now */ -+ ret = amd_xgbe_phy_disable_an(phydev); -+ if (ret < 0) -+ return ret; -+ -+ /* Clear auto-negotiation interrupts */ -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0); -+ -+ return 0; -+} -+ -+static int amd_xgbe_phy_config_init(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ struct net_device *netdev = phydev->attached_dev; -+ int ret; -+ -+ if (!priv->an_irq_allocated) { -+ /* Allocate the auto-negotiation workqueue and interrupt */ -+ snprintf(priv->an_irq_name, sizeof(priv->an_irq_name) - 1, -+ "%s-pcs", netdev_name(netdev)); -+ -+ priv->an_workqueue = -+ create_singlethread_workqueue(priv->an_irq_name); -+ if (!priv->an_workqueue) { -+ netdev_err(netdev, "phy workqueue creation failed\n"); -+ return -ENOMEM; -+ } -+ -+ ret = devm_request_irq(priv->dev, priv->an_irq, -+ amd_xgbe_an_isr, 0, priv->an_irq_name, -+ priv); -+ if (ret) { -+ netdev_err(netdev, "phy irq request failed\n"); -+ destroy_workqueue(priv->an_workqueue); -+ return ret; -+ } -+ -+ priv->an_irq_allocated = 1; -+ } -+ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FEC_ABILITY); -+ if (ret < 0) -+ return ret; -+ priv->fec_ability = ret & XGBE_PHY_FEC_MASK; -+ -+ /* Initialize supported features */ -+ phydev->supported = SUPPORTED_Autoneg; -+ phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; -+ phydev->supported |= SUPPORTED_Backplane; -+ phydev->supported |= SUPPORTED_10000baseKR_Full; -+ switch (priv->speed_set) { -+ case AMD_XGBE_PHY_SPEEDSET_1000_10000: -+ phydev->supported |= SUPPORTED_1000baseKX_Full; -+ break; -+ case AMD_XGBE_PHY_SPEEDSET_2500_10000: -+ phydev->supported |= SUPPORTED_2500baseX_Full; -+ break; -+ } -+ -+ if (priv->fec_ability & XGBE_PHY_FEC_ENABLE) -+ phydev->supported |= SUPPORTED_10000baseR_FEC; -+ -+ phydev->advertising = phydev->supported; -+ -+ /* Set initial mode - call the mode setting routines -+ * directly to insure we are properly configured -+ */ -+ if (phydev->supported & SUPPORTED_10000baseKR_Full) -+ ret = amd_xgbe_phy_xgmii_mode(phydev); -+ else if (phydev->supported & SUPPORTED_1000baseKX_Full) -+ ret = amd_xgbe_phy_gmii_mode(phydev); -+ else if (phydev->supported & SUPPORTED_2500baseX_Full) -+ ret = amd_xgbe_phy_gmii_2500_mode(phydev); -+ else -+ ret = -EINVAL; -+ if (ret < 0) -+ return ret; -+ -+ /* Set up advertisement registers based on current settings */ -+ ret = amd_xgbe_an_init(phydev); -+ if (ret) -+ return ret; -+ -+ /* Enable auto-negotiation interrupts */ -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INTMASK, 0x07); -+ -+ return 0; -+} -+ -+static int amd_xgbe_phy_setup_forced(struct phy_device *phydev) -+{ -+ int ret; -+ -+ /* Disable auto-negotiation */ -+ ret = amd_xgbe_phy_disable_an(phydev); -+ if (ret < 0) -+ return ret; -+ -+ /* Validate/Set specified speed */ -+ switch (phydev->speed) { -+ case SPEED_10000: -+ ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KR); -+ break; -+ -+ case SPEED_2500: -+ case SPEED_1000: -+ ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KX); -+ break; -+ -+ default: -+ ret = -EINVAL; -+ } -+ -+ if (ret < 0) -+ return ret; -+ -+ /* Validate duplex mode */ -+ if (phydev->duplex != DUPLEX_FULL) -+ return -EINVAL; -+ -+ phydev->pause = 0; -+ phydev->asym_pause = 0; -+ -+ return 0; -+} -+ -+static int __amd_xgbe_phy_config_aneg(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ u32 mmd_mask = phydev->c45_ids.devices_in_package; -+ int ret; -+ -+ if (phydev->autoneg != AUTONEG_ENABLE) -+ return amd_xgbe_phy_setup_forced(phydev); -+ -+ /* Make sure we have the AN MMD present */ -+ if (!(mmd_mask & MDIO_DEVS_AN)) -+ return -EINVAL; -+ -+ /* Disable auto-negotiation interrupt */ -+ disable_irq(priv->an_irq); -+ -+ /* Start auto-negotiation in a supported mode */ -+ if (phydev->supported & SUPPORTED_10000baseKR_Full) -+ ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KR); -+ else if ((phydev->supported & SUPPORTED_1000baseKX_Full) || -+ (phydev->supported & SUPPORTED_2500baseX_Full)) -+ ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KX); -+ else -+ ret = -EINVAL; -+ if (ret < 0) { -+ enable_irq(priv->an_irq); -+ return ret; -+ } -+ -+ /* Disable and stop any in progress auto-negotiation */ -+ ret = amd_xgbe_phy_disable_an(phydev); -+ if (ret < 0) -+ return ret; -+ -+ /* Clear any auto-negotitation interrupts */ -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0); -+ -+ priv->an_result = AMD_XGBE_AN_READY; -+ priv->an_state = AMD_XGBE_AN_READY; -+ priv->kr_state = AMD_XGBE_RX_BPA; -+ priv->kx_state = AMD_XGBE_RX_BPA; -+ -+ /* Re-enable auto-negotiation interrupt */ -+ enable_irq(priv->an_irq); -+ -+ /* Set up advertisement registers based on current settings */ -+ ret = amd_xgbe_an_init(phydev); -+ if (ret) -+ return ret; -+ -+ /* Enable and start auto-negotiation */ -+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_KR_CTRL); -+ if (ret < 0) -+ return ret; -+ -+ ret |= MDIO_KR_CTRL_PDETECT; -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_KR_CTRL, ret); -+ -+ return amd_xgbe_phy_restart_an(phydev); -+} -+ -+static int amd_xgbe_phy_config_aneg(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ int ret; -+ -+ mutex_lock(&priv->an_mutex); -+ -+ ret = __amd_xgbe_phy_config_aneg(phydev); -+ -+ mutex_unlock(&priv->an_mutex); -+ -+ return ret; -+} -+ -+static int amd_xgbe_phy_aneg_done(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ -+ return (priv->an_result == AMD_XGBE_AN_COMPLETE); -+} -+ -+static int amd_xgbe_phy_update_link(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ unsigned int check_again, autoneg; -+ int ret; -+ -+ /* If we're doing auto-negotiation don't report link down */ -+ if (priv->an_state != AMD_XGBE_AN_READY) { -+ phydev->link = 1; -+ return 0; -+ } -+ -+ /* Since the device can be in the wrong mode when a link is -+ * (re-)established (cable connected after the interface is -+ * up, etc.), the link status may report no link. If there -+ * is no link, try switching modes and checking the status -+ * again if auto negotiation is enabled. -+ */ -+ check_again = (phydev->autoneg == AUTONEG_ENABLE) ? 1 : 0; -+again: -+ /* Link status is latched low, so read once to clear -+ * and then read again to get current state -+ */ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_STAT1); -+ if (ret < 0) -+ return ret; -+ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_STAT1); -+ if (ret < 0) -+ return ret; -+ -+ phydev->link = (ret & MDIO_STAT1_LSTATUS) ? 1 : 0; -+ -+ if (!phydev->link) { -+ if (check_again) { -+ ret = amd_xgbe_phy_switch_mode(phydev); -+ if (ret < 0) -+ return ret; -+ check_again = 0; -+ goto again; -+ } -+ } -+ -+ autoneg = (phydev->link && !priv->link) ? 1 : 0; -+ priv->link = phydev->link; -+ if (autoneg) { -+ /* Link is (back) up, re-start auto-negotiation */ -+ ret = amd_xgbe_phy_config_aneg(phydev); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int amd_xgbe_phy_read_status(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ u32 mmd_mask = phydev->c45_ids.devices_in_package; -+ int ret, ad_ret, lp_ret; -+ -+ ret = amd_xgbe_phy_update_link(phydev); -+ if (ret) -+ return ret; -+ -+ if ((phydev->autoneg == AUTONEG_ENABLE) && -+ !priv->parallel_detect) { -+ if (!(mmd_mask & MDIO_DEVS_AN)) -+ return -EINVAL; -+ -+ if (!amd_xgbe_phy_aneg_done(phydev)) -+ return 0; -+ -+ /* Compare Advertisement and Link Partner register 1 */ -+ ad_ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE); -+ if (ad_ret < 0) -+ return ad_ret; -+ lp_ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPA); -+ if (lp_ret < 0) -+ return lp_ret; -+ -+ ad_ret &= lp_ret; -+ phydev->pause = (ad_ret & 0x400) ? 1 : 0; -+ phydev->asym_pause = (ad_ret & 0x800) ? 1 : 0; -+ -+ /* Compare Advertisement and Link Partner register 2 */ -+ ad_ret = phy_read_mmd(phydev, MDIO_MMD_AN, -+ MDIO_AN_ADVERTISE + 1); -+ if (ad_ret < 0) -+ return ad_ret; -+ lp_ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPA + 1); -+ if (lp_ret < 0) -+ return lp_ret; -+ -+ ad_ret &= lp_ret; -+ if (ad_ret & 0x80) { -+ phydev->speed = SPEED_10000; -+ ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KR); -+ if (ret) -+ return ret; -+ } else { -+ switch (priv->speed_set) { -+ case AMD_XGBE_PHY_SPEEDSET_1000_10000: -+ phydev->speed = SPEED_1000; -+ break; -+ -+ case AMD_XGBE_PHY_SPEEDSET_2500_10000: -+ phydev->speed = SPEED_2500; -+ break; -+ } -+ -+ ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KX); -+ if (ret) -+ return ret; -+ } -+ -+ phydev->duplex = DUPLEX_FULL; -+ } else { -+ if (amd_xgbe_phy_in_kr_mode(phydev)) { -+ phydev->speed = SPEED_10000; -+ } else { -+ switch (priv->speed_set) { -+ case AMD_XGBE_PHY_SPEEDSET_1000_10000: -+ phydev->speed = SPEED_1000; -+ break; -+ -+ case AMD_XGBE_PHY_SPEEDSET_2500_10000: -+ phydev->speed = SPEED_2500; -+ break; -+ } -+ } -+ phydev->duplex = DUPLEX_FULL; -+ phydev->pause = 0; -+ phydev->asym_pause = 0; -+ } -+ -+ return 0; -+} -+ -+static int amd_xgbe_phy_suspend(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ int ret; -+ -+ mutex_lock(&phydev->lock); -+ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1); -+ if (ret < 0) -+ goto unlock; -+ -+ priv->lpm_ctrl = ret; -+ -+ ret |= MDIO_CTRL1_LPOWER; -+ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, ret); -+ -+ ret = 0; -+ -+unlock: -+ mutex_unlock(&phydev->lock); -+ -+ return ret; -+} -+ -+static int amd_xgbe_phy_resume(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ -+ mutex_lock(&phydev->lock); -+ -+ priv->lpm_ctrl &= ~MDIO_CTRL1_LPOWER; -+ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, priv->lpm_ctrl); -+ -+ mutex_unlock(&phydev->lock); -+ -+ return 0; -+} -+ -+static unsigned int amd_xgbe_phy_resource_count(struct platform_device *pdev, -+ unsigned int type) -+{ -+ unsigned int count; -+ int i; -+ -+ for (i = 0, count = 0; i < pdev->num_resources; i++) { -+ struct resource *r = &pdev->resource[i]; -+ -+ if (type == resource_type(r)) -+ count++; -+ } -+ -+ return count; -+} -+ -+static int amd_xgbe_phy_probe(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv; -+ struct platform_device *phy_pdev; -+ struct device *dev, *phy_dev; -+ unsigned int phy_resnum, phy_irqnum; -+ int ret; -+ -+ if (!phydev->bus || !phydev->bus->parent) -+ return -EINVAL; -+ -+ dev = phydev->bus->parent; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->pdev = to_platform_device(dev); -+ priv->adev = ACPI_COMPANION(dev); -+ priv->dev = dev; -+ priv->phydev = phydev; -+ mutex_init(&priv->an_mutex); -+ INIT_WORK(&priv->an_irq_work, amd_xgbe_an_irq_work); -+ INIT_WORK(&priv->an_work, amd_xgbe_an_state_machine); -+ -+ if (!priv->adev || acpi_disabled) { -+ struct device_node *bus_node; -+ struct device_node *phy_node; -+ -+ bus_node = priv->dev->of_node; -+ phy_node = of_parse_phandle(bus_node, "phy-handle", 0); -+ if (!phy_node) { -+ dev_err(dev, "unable to parse phy-handle\n"); -+ ret = -EINVAL; -+ goto err_priv; -+ } -+ -+ phy_pdev = of_find_device_by_node(phy_node); -+ of_node_put(phy_node); -+ -+ if (!phy_pdev) { -+ dev_err(dev, "unable to obtain phy device\n"); -+ ret = -EINVAL; -+ goto err_priv; -+ } -+ -+ phy_resnum = 0; -+ phy_irqnum = 0; -+ } else { -+ /* In ACPI, the XGBE and PHY resources are the grouped -+ * together with the PHY resources at the end -+ */ -+ phy_pdev = priv->pdev; -+ phy_resnum = amd_xgbe_phy_resource_count(phy_pdev, -+ IORESOURCE_MEM) - 2; -+ phy_irqnum = amd_xgbe_phy_resource_count(phy_pdev, -+ IORESOURCE_IRQ) - 1; -+ } -+ phy_dev = &phy_pdev->dev; -+ -+ /* Get the device mmio areas */ -+ priv->rxtx_res = platform_get_resource(phy_pdev, IORESOURCE_MEM, -+ phy_resnum++); -+ priv->rxtx_regs = devm_ioremap_resource(dev, priv->rxtx_res); -+ if (IS_ERR(priv->rxtx_regs)) { -+ dev_err(dev, "rxtx ioremap failed\n"); -+ ret = PTR_ERR(priv->rxtx_regs); -+ goto err_put; -+ } -+ -+ /* All xgbe phy devices share the CMU registers so retrieve -+ * the resource and do the ioremap directly rather than -+ * the devm_ioremap_resource call -+ */ -+ priv->cmu_res = platform_get_resource(phy_pdev, IORESOURCE_MEM, -+ phy_resnum++); -+ if (!priv->cmu_res) { -+ dev_err(dev, "cmu invalid resource\n"); -+ ret = -EINVAL; -+ goto err_rxtx; -+ } -+ priv->cmu_regs = devm_ioremap_nocache(dev, priv->cmu_res->start, -+ resource_size(priv->cmu_res)); -+ if (!priv->cmu_regs) { -+ dev_err(dev, "cmu ioremap failed\n"); -+ ret = -ENOMEM; -+ goto err_rxtx; -+ } -+ -+ /* Get the auto-negotiation interrupt */ -+ ret = platform_get_irq(phy_pdev, phy_irqnum); -+ if (ret < 0) { -+ dev_err(dev, "platform_get_irq failed\n"); -+ goto err_cmu; -+ } -+ if (priv->adev && !acpi_disabled && !phy_irqnum) { -+ struct irq_data *d = irq_get_irq_data(ret); -+ if (!d) { -+ dev_err(dev, "unable to set AN interrupt\n"); -+ ret = -EINVAL; -+ goto err_cmu; -+ } -+ -+#ifdef CONFIG_ACPI -+ ret = acpi_register_gsi(dev, d->hwirq - 2, -+ ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH); -+#else -+ ret = -EINVAL; -+#endif -+ if (ret < 0) { -+ dev_err(dev, "unable to set AN interrupt\n"); -+ goto err_cmu; -+ } -+ } -+ priv->an_irq = ret; -+ -+ /* Get the device serdes channel property */ -+ ret = device_property_read_u32(phy_dev, XGBE_PHY_CHANNEL_PROPERTY, -+ &priv->serdes_channel); -+ if (ret) { -+ dev_err(dev, "invalid %s property\n", -+ XGBE_PHY_CHANNEL_PROPERTY); -+ goto err_cmu; -+ } -+ -+ /* Get the device speed set property */ -+ ret = device_property_read_u32(phy_dev, XGBE_PHY_SPEEDSET_PROPERTY, -+ &priv->speed_set); -+ if (ret) { -+ dev_err(dev, "invalid %s property\n", -+ XGBE_PHY_SPEEDSET_PROPERTY); -+ goto err_cmu; -+ } -+ -+ switch (priv->speed_set) { -+ case AMD_XGBE_PHY_SPEEDSET_1000_10000: -+ case AMD_XGBE_PHY_SPEEDSET_2500_10000: -+ break; -+ default: -+ dev_err(dev, "invalid %s property\n", -+ XGBE_PHY_SPEEDSET_PROPERTY); -+ ret = -EINVAL; -+ goto err_cmu; -+ } -+ -+ if (device_property_present(phy_dev, XGBE_PHY_BLWC_PROPERTY)) { -+ ret = device_property_read_u32_array(phy_dev, -+ XGBE_PHY_BLWC_PROPERTY, -+ priv->serdes_blwc, -+ XGBE_PHY_SPEEDS); -+ if (ret) { -+ dev_err(dev, "invalid %s property\n", -+ XGBE_PHY_BLWC_PROPERTY); -+ goto err_cmu; -+ } -+ } else { -+ memcpy(priv->serdes_blwc, amd_xgbe_phy_serdes_blwc, -+ sizeof(priv->serdes_blwc)); -+ } -+ -+ if (device_property_present(phy_dev, XGBE_PHY_CDR_RATE_PROPERTY)) { -+ ret = device_property_read_u32_array(phy_dev, -+ XGBE_PHY_CDR_RATE_PROPERTY, -+ priv->serdes_cdr_rate, -+ XGBE_PHY_SPEEDS); -+ if (ret) { -+ dev_err(dev, "invalid %s property\n", -+ XGBE_PHY_CDR_RATE_PROPERTY); -+ goto err_cmu; -+ } -+ } else { -+ memcpy(priv->serdes_cdr_rate, amd_xgbe_phy_serdes_cdr_rate, -+ sizeof(priv->serdes_cdr_rate)); -+ } -+ -+ if (device_property_present(phy_dev, XGBE_PHY_PQ_SKEW_PROPERTY)) { -+ ret = device_property_read_u32_array(phy_dev, -+ XGBE_PHY_PQ_SKEW_PROPERTY, -+ priv->serdes_pq_skew, -+ XGBE_PHY_SPEEDS); -+ if (ret) { -+ dev_err(dev, "invalid %s property\n", -+ XGBE_PHY_PQ_SKEW_PROPERTY); -+ goto err_cmu; -+ } -+ } else { -+ memcpy(priv->serdes_pq_skew, amd_xgbe_phy_serdes_pq_skew, -+ sizeof(priv->serdes_pq_skew)); -+ } -+ -+ if (device_property_present(phy_dev, XGBE_PHY_TX_AMP_PROPERTY)) { -+ ret = device_property_read_u32_array(phy_dev, -+ XGBE_PHY_TX_AMP_PROPERTY, -+ priv->serdes_tx_amp, -+ XGBE_PHY_SPEEDS); -+ if (ret) { -+ dev_err(dev, "invalid %s property\n", -+ XGBE_PHY_TX_AMP_PROPERTY); -+ goto err_cmu; -+ } -+ } else { -+ memcpy(priv->serdes_tx_amp, amd_xgbe_phy_serdes_tx_amp, -+ sizeof(priv->serdes_tx_amp)); -+ } -+ -+ priv->link = 1; -+ -+ phydev->priv = priv; -+ -+ if (!priv->adev || acpi_disabled) -+ platform_device_put(phy_pdev); -+ -+ return 0; -+ -+err_cmu: -+ devm_iounmap(dev, priv->cmu_regs); -+ -+err_rxtx: -+ devm_iounmap(dev, priv->rxtx_regs); -+ devm_release_mem_region(dev, priv->rxtx_res->start, -+ resource_size(priv->rxtx_res)); -+ -+err_put: -+ if (!priv->adev || acpi_disabled) -+ platform_device_put(phy_pdev); -+ -+err_priv: -+ devm_kfree(dev, priv); -+ -+ return ret; -+} -+ -+static void amd_xgbe_phy_remove(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ struct device *dev = priv->dev; -+ -+ if (priv->an_irq_allocated) { -+ devm_free_irq(dev, priv->an_irq, priv); -+ -+ flush_workqueue(priv->an_workqueue); -+ destroy_workqueue(priv->an_workqueue); -+ } -+ -+ devm_iounmap(dev, priv->cmu_regs); -+ -+ devm_iounmap(dev, priv->rxtx_regs); -+ devm_release_mem_region(dev, priv->rxtx_res->start, -+ resource_size(priv->rxtx_res)); -+ -+ devm_kfree(dev, priv); -+} -+ -+static int amd_xgbe_match_phy_device(struct phy_device *phydev) -+{ -+ return phydev->c45_ids.device_ids[MDIO_MMD_PCS] == XGBE_PHY_ID; -+} -+ -+static struct phy_driver amd_xgbe_phy_a0_driver[] = { -+ { -+ .phy_id = XGBE_PHY_ID, -+ .phy_id_mask = XGBE_PHY_MASK, -+ .name = "AMD XGBE PHY A0", -+ .features = 0, -+ .probe = amd_xgbe_phy_probe, -+ .remove = amd_xgbe_phy_remove, -+ .soft_reset = amd_xgbe_phy_soft_reset, -+ .config_init = amd_xgbe_phy_config_init, -+ .suspend = amd_xgbe_phy_suspend, -+ .resume = amd_xgbe_phy_resume, -+ .config_aneg = amd_xgbe_phy_config_aneg, -+ .aneg_done = amd_xgbe_phy_aneg_done, -+ .read_status = amd_xgbe_phy_read_status, -+ .match_phy_device = amd_xgbe_match_phy_device, -+ .driver = { -+ .owner = THIS_MODULE, -+ }, -+ }, -+}; -+ -+module_phy_driver(amd_xgbe_phy_a0_driver); -+ -+static struct mdio_device_id __maybe_unused amd_xgbe_phy_a0_ids[] = { -+ { XGBE_PHY_ID, XGBE_PHY_MASK }, -+ { } -+}; -+MODULE_DEVICE_TABLE(mdio, amd_xgbe_phy_a0_ids); --- -2.6.2 - diff --git a/core/linux-aarch64/0004-devicetree-bindings-Document-qcom-msm-id-and-qcom-bo.patch b/core/linux-aarch64/0002-devicetree-bindings-Document-qcom-msm-id-and-qcom-bo.patch similarity index 97% rename from core/linux-aarch64/0004-devicetree-bindings-Document-qcom-msm-id-and-qcom-bo.patch rename to core/linux-aarch64/0002-devicetree-bindings-Document-qcom-msm-id-and-qcom-bo.patch index 13b4f7306..3421c1e08 100644 --- a/core/linux-aarch64/0004-devicetree-bindings-Document-qcom-msm-id-and-qcom-bo.patch +++ b/core/linux-aarch64/0002-devicetree-bindings-Document-qcom-msm-id-and-qcom-bo.patch @@ -1,7 +1,7 @@ -From 063df62f5946147912e520901d4e3efdc866c485 Mon Sep 17 00:00:00 2001 +From bf131edcef6243ffad675d6aa010c89a8e0c7331 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 3 Mar 2015 15:39:07 -0600 -Subject: [PATCH 4/6] devicetree: bindings: Document qcom,msm-id and +Subject: [PATCH 2/4] devicetree: bindings: Document qcom,msm-id and qcom,board-id The top level qcom,msm-id and qcom,board-id are utilized by bootloaders @@ -128,5 +128,5 @@ index 0000000..a18f34e + +#endif -- -2.6.2 +2.7.0 diff --git a/core/linux-aarch64/0005-arm64-dts-Add-Qualcomm-MSM8916-MTP8916-ids.patch b/core/linux-aarch64/0003-arm64-dts-Add-Qualcomm-MSM8916-MTP8916-ids.patch similarity index 85% rename from core/linux-aarch64/0005-arm64-dts-Add-Qualcomm-MSM8916-MTP8916-ids.patch rename to core/linux-aarch64/0003-arm64-dts-Add-Qualcomm-MSM8916-MTP8916-ids.patch index 4158bb432..78bc75b8d 100644 --- a/core/linux-aarch64/0005-arm64-dts-Add-Qualcomm-MSM8916-MTP8916-ids.patch +++ b/core/linux-aarch64/0003-arm64-dts-Add-Qualcomm-MSM8916-MTP8916-ids.patch @@ -1,7 +1,7 @@ -From c4fd48751761389b98b82b21842f18a63e1ebd10 Mon Sep 17 00:00:00 2001 +From 5a44db76201981d7afdc38ded3ff2100c8ec8370 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 11 Mar 2015 15:51:20 -0500 -Subject: [PATCH 5/6] arm64: dts: Add Qualcomm MSM8916 & MTP8916 ids +Subject: [PATCH 3/4] arm64: dts: Add Qualcomm MSM8916 & MTP8916 ids Add qcom,msm-id and qcom,board-id to allow bootloader to identify which device tree to boot on the MTP8916 boards. @@ -13,7 +13,7 @@ Signed-off-by: Kumar Gala 2 files changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/msm8916-mtp.dts b/arch/arm64/boot/dts/qcom/msm8916-mtp.dts -index fced77f..6c68b4e 100644 +index b0a064d..2cdaa65 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-mtp.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-mtp.dts @@ -13,10 +13,13 @@ @@ -25,13 +25,13 @@ index fced77f..6c68b4e 100644 / { model = "Qualcomm Technologies, Inc. MSM 8916 MTP"; - compatible = "qcom,msm8916-mtp", "qcom,msm8916-mtp-smb1360", + compatible = "qcom,msm8916-mtp", "qcom,msm8916-mtp/1", "qcom,msm8916", "qcom,mtp"; + qcom,board-id = , + ; }; diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi -index 8d184ff..c8e5372 100644 +index 9153214..719bd9f 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -14,10 +14,15 @@ @@ -51,5 +51,5 @@ index 8d184ff..c8e5372 100644 interrupt-parent = <&intc>; -- -2.6.2 +2.7.0 diff --git a/core/linux-aarch64/0006-arm64-dts-qcom-Add-APQ8016-SBC-support.patch b/core/linux-aarch64/0004-arm64-dts-qcom-Add-APQ8016-SBC-support.patch similarity index 89% rename from core/linux-aarch64/0006-arm64-dts-qcom-Add-APQ8016-SBC-support.patch rename to core/linux-aarch64/0004-arm64-dts-qcom-Add-APQ8016-SBC-support.patch index 028f2a1ba..9c9770dc3 100644 --- a/core/linux-aarch64/0006-arm64-dts-qcom-Add-APQ8016-SBC-support.patch +++ b/core/linux-aarch64/0004-arm64-dts-qcom-Add-APQ8016-SBC-support.patch @@ -1,7 +1,7 @@ -From 3ffcd0b59962b1d683543a7953ba132ab10f7f74 Mon Sep 17 00:00:00 2001 +From a3cc1740dc9a65fc2ce33eb128870cdd95ef5145 Mon Sep 17 00:00:00 2001 From: Andy Gross Date: Tue, 31 Mar 2015 14:26:15 -0500 -Subject: [PATCH 6/6] arm64: dts: qcom: Add APQ8016 SBC support +Subject: [PATCH 4/4] arm64: dts: qcom: Add APQ8016 SBC support This patch set adds support for the APQ8016 SBC. @@ -31,7 +31,7 @@ index 825f489..b0cac53 100644 + qcom,board-id = ; }; diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi -index c8e5372..1722a21 100644 +index 719bd9f..6716515 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -22,7 +22,9 @@ @@ -46,5 +46,5 @@ index c8e5372..1722a21 100644 interrupt-parent = <&intc>; -- -2.6.2 +2.7.0 diff --git a/core/linux-aarch64/PKGBUILD b/core/linux-aarch64/PKGBUILD index 3ea26d451..67f03be48 100644 --- a/core/linux-aarch64/PKGBUILD +++ b/core/linux-aarch64/PKGBUILD @@ -4,10 +4,10 @@ buildarch=8 pkgbase=linux-aarch64 -_srcname=linux-4.4 +_srcname=linux-4.5 _kernelname=${pkgbase#linux} _desc="AArch64 multi-platform" -pkgver=4.4.4 +pkgver=4.5.0 pkgrel=1 arch=('aarch64') url="http://www.kernel.org/" @@ -15,39 +15,32 @@ license=('GPL2') makedepends=('xmlto' 'docbook-xsl' 'kmod' 'inetutils' 'bc' 'git') options=('!strip') source=("http://www.kernel.org/pub/linux/kernel/v4.x/${_srcname}.tar.xz" - "http://www.kernel.org/pub/linux/kernel/v4.x/patch-${pkgver}.xz" - '0001-amd-xgbe-a0-Add-support-for-XGBE-on-A0.patch' - '0002-amd-xgbe-phy-a0-Add-support-for-XGBE-PHY-on-A0.patch' - '0003-arm64-acpi-drop-expert-patch.patch' - '0004-devicetree-bindings-Document-qcom-msm-id-and-qcom-bo.patch' - '0005-arm64-dts-Add-Qualcomm-MSM8916-MTP8916-ids.patch' - '0006-arm64-dts-qcom-Add-APQ8016-SBC-support.patch' + #"http://www.kernel.org/pub/linux/kernel/v4.x/patch-${pkgver}.xz" + '0001-arm64-acpi-drop-expert-patch.patch' + '0002-devicetree-bindings-Document-qcom-msm-id-and-qcom-bo.patch' + '0003-arm64-dts-Add-Qualcomm-MSM8916-MTP8916-ids.patch' + '0004-arm64-dts-qcom-Add-APQ8016-SBC-support.patch' 'config' 'linux.preset') -md5sums=('9a78fa2eb6c68ca5a40ed5af08142599' - '07e9b2c5d0daf7fc2a1ee26a52adcbc0' - '90e8c4300d263db370eb2155ee1a4b42' - '51c4dcc18641b9c4dfb824b98213c080' - 'dd04cf22c2b1dc946884cdb55efc6424' - '2a052b7347d21f8813c09931ea0ef495' - '4166c1a8edeec7eb8c7e69f42e561332' - '1891555762fc267cf2cd7a9a6d01f70d' - 'bcb7c0c453729f95b54dec819ccd8fb6' +md5sums=('a60d48eee08ec0536d5efb17ca819aef' + 'c8e84e01e8f88b47edba6a479942cc6e' + '66de90ece2f3dcae72ee4c27ddd37b38' + '29d5fafca011d80a8cfbffb5ebbfd327' + 'f2f044e19e0e8d5e81034e5870c644c7' + '02660c2c9f0b0efffbeff41496e1fdde' 'b5ef67d6086e20de7b82265f562f88b1') prepare() { cd "${srcdir}/${_srcname}" # add upstream patch - git apply --whitespace=nowarn ../patch-${pkgver} + #git apply --whitespace=nowarn ../patch-${pkgver} # ALARM patches - git apply ../0001-amd-xgbe-a0-Add-support-for-XGBE-on-A0.patch - git apply ../0002-amd-xgbe-phy-a0-Add-support-for-XGBE-PHY-on-A0.patch - git apply ../0003-arm64-acpi-drop-expert-patch.patch - git apply ../0004-devicetree-bindings-Document-qcom-msm-id-and-qcom-bo.patch - git apply ../0005-arm64-dts-Add-Qualcomm-MSM8916-MTP8916-ids.patch - git apply ../0006-arm64-dts-qcom-Add-APQ8016-SBC-support.patch + git apply ../0001-arm64-acpi-drop-expert-patch.patch + git apply ../0002-devicetree-bindings-Document-qcom-msm-id-and-qcom-bo.patch + git apply ../0003-arm64-dts-Add-Qualcomm-MSM8916-MTP8916-ids.patch + git apply ../0004-arm64-dts-qcom-Add-APQ8016-SBC-support.patch cat "${srcdir}/config" > ./.config diff --git a/core/linux-aarch64/config b/core/linux-aarch64/config index 03d7a566c..b771d9959 100644 --- a/core/linux-aarch64/config +++ b/core/linux-aarch64/config @@ -1,11 +1,15 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 4.4.0-rc5-1 Kernel Configuration +# Linux/arm64 4.5.0-rc7-1 Kernel Configuration # CONFIG_ARM64=y CONFIG_64BIT=y CONFIG_ARCH_PHYS_ADDR_T_64BIT=y CONFIG_MMU=y +CONFIG_ARCH_MMAP_RND_BITS_MIN=14 +CONFIG_ARCH_MMAP_RND_BITS_MAX=27 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=7 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 CONFIG_STACKTRACE_SUPPORT=y CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 CONFIG_LOCKDEP_SUPPORT=y @@ -88,6 +92,7 @@ CONFIG_HIGH_RES_TIMERS=y # CONFIG_TICK_CPU_ACCOUNTING=y # CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +# CONFIG_IRQ_TIME_ACCOUNTING is not set CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_TASKSTATS=y @@ -112,27 +117,26 @@ CONFIG_LOG_BUF_SHIFT=18 CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 CONFIG_GENERIC_SCHED_CLOCK=y CONFIG_CGROUPS=y -# CONFIG_CGROUP_DEBUG is not set -CONFIG_CGROUP_FREEZER=y -CONFIG_CGROUP_PIDS=y -CONFIG_CGROUP_DEVICE=y -CONFIG_CPUSETS=y -CONFIG_PROC_PID_CPUSET=y -CONFIG_CGROUP_CPUACCT=y CONFIG_PAGE_COUNTER=y CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y CONFIG_MEMCG_SWAP_ENABLED=y -CONFIG_MEMCG_KMEM=y -# CONFIG_CGROUP_HUGETLB is not set -CONFIG_CGROUP_PERF=y +CONFIG_BLK_CGROUP=y +# CONFIG_DEBUG_BLK_CGROUP is not set +CONFIG_CGROUP_WRITEBACK=y CONFIG_CGROUP_SCHED=y CONFIG_FAIR_GROUP_SCHED=y CONFIG_CFS_BANDWIDTH=y CONFIG_RT_GROUP_SCHED=y -CONFIG_BLK_CGROUP=y -# CONFIG_DEBUG_BLK_CGROUP is not set -CONFIG_CGROUP_WRITEBACK=y +CONFIG_CGROUP_PIDS=y +CONFIG_CGROUP_FREEZER=y +# CONFIG_CGROUP_HUGETLB is not set +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_PERF=y +# CONFIG_CGROUP_DEBUG is not set # CONFIG_CHECKPOINT_RESTORE is not set CONFIG_NAMESPACES=y CONFIG_UTS_NS=y @@ -203,7 +207,6 @@ CONFIG_JUMP_LABEL=y # CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_HAVE_ARCH_TRACEHOOK=y -CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_DMA_CONTIGUOUS=y CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_GENERIC_IDLE_POLL_SETUP=y @@ -227,9 +230,12 @@ CONFIG_CC_STACKPROTECTOR_NONE=y # CONFIG_CC_STACKPROTECTOR_STRONG is not set CONFIG_HAVE_CONTEXT_TRACKING=y CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y CONFIG_MODULES_USE_ELF_RELA=y CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_HAVE_ARCH_MMAP_RND_BITS=y +CONFIG_ARCH_MMAP_RND_BITS=14 CONFIG_CLONE_BACKWARDS=y # @@ -319,10 +325,12 @@ CONFIG_ARCH_HISI=y CONFIG_ARCH_QCOM=y # CONFIG_ARCH_ROCKCHIP is not set CONFIG_ARCH_SEATTLE=y +# CONFIG_ARCH_RENESAS is not set # CONFIG_ARCH_STRATIX10 is not set -# CONFIG_ARCH_TEGRA is not set +CONFIG_ARCH_TEGRA=y # CONFIG_ARCH_SPRD is not set # CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_UNIPHIER is not set CONFIG_ARCH_VEXPRESS=y CONFIG_ARCH_XGENE=y # CONFIG_ARCH_ZYNQMP is not set @@ -353,8 +361,8 @@ CONFIG_PCIE_DW=y CONFIG_PCI_HOST_GENERIC=y CONFIG_PCI_XGENE=y CONFIG_PCI_XGENE_MSI=y -# CONFIG_PCIE_IPROC is not set CONFIG_PCI_HISI=y +CONFIG_PCIE_QCOM=y CONFIG_PCIEPORTBUS=y CONFIG_HOTPLUG_PCI_PCIE=y CONFIG_PCIEAER=y @@ -415,7 +423,6 @@ CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_HAVE_ARCH_PFN_VALID=y CONFIG_HW_PERF_EVENTS=y CONFIG_SYS_SUPPORTS_HUGETLBFS=y -CONFIG_ARCH_WANT_GENERAL_HUGETLB=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_SELECT_MEMORY_MODEL=y CONFIG_SPARSEMEM_MANUAL=y @@ -456,6 +463,8 @@ CONFIG_GENERIC_EARLY_IOREMAP=y # CONFIG_IDLE_PAGE_TRACKING is not set CONFIG_FRAME_VECTOR=y CONFIG_SECCOMP=y +CONFIG_PARAVIRT=y +CONFIG_PARAVIRT_TIME_ACCOUNTING=y # CONFIG_XEN is not set CONFIG_FORCE_MAX_ZONEORDER=11 @@ -542,9 +551,11 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y # CONFIG_CPUFREQ_DT is not set # CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set # CONFIG_ARM_KIRKWOOD_CPUFREQ is not set +CONFIG_ARM_TEGRA20_CPUFREQ=y # CONFIG_ACPI_CPPC_CPUFREQ is not set CONFIG_NET=y CONFIG_NET_INGRESS=y +CONFIG_NET_EGRESS=y # # Networking options @@ -597,6 +608,7 @@ CONFIG_INET_LRO=y CONFIG_INET_DIAG=m CONFIG_INET_TCP_DIAG=m CONFIG_INET_UDP_DIAG=m +# CONFIG_INET_DIAG_DESTROY is not set CONFIG_TCP_CONG_ADVANCED=y CONFIG_TCP_CONG_BIC=m CONFIG_TCP_CONG_CUBIC=y @@ -717,6 +729,9 @@ CONFIG_NFT_QUEUE=m CONFIG_NFT_REJECT=m CONFIG_NFT_REJECT_INET=m CONFIG_NFT_COMPAT=m +CONFIG_NF_DUP_NETDEV=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m CONFIG_NETFILTER_XTABLES=y # @@ -1038,6 +1053,7 @@ CONFIG_IPDDP_ENCAP=y # CONFIG_LAPB is not set # CONFIG_PHONET is not set CONFIG_6LOWPAN=m +# CONFIG_6LOWPAN_DEBUGFS is not set CONFIG_6LOWPAN_NHC=m CONFIG_6LOWPAN_NHC_DEST=m CONFIG_6LOWPAN_NHC_FRAGMENT=m @@ -1046,6 +1062,12 @@ CONFIG_6LOWPAN_NHC_IPV6=m CONFIG_6LOWPAN_NHC_MOBILITY=m CONFIG_6LOWPAN_NHC_ROUTING=m CONFIG_6LOWPAN_NHC_UDP=m +CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m +CONFIG_6LOWPAN_GHC_UDP=m +CONFIG_6LOWPAN_GHC_ICMPV6=m +CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m +CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m +CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m CONFIG_IEEE802154=m # CONFIG_IEEE802154_NL802154_EXPERIMENTAL is not set CONFIG_IEEE802154_SOCKET=m @@ -1149,6 +1171,7 @@ CONFIG_NET_SWITCHDEV=y CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y +CONFIG_SOCK_CGROUP_DATA=y CONFIG_CGROUP_NET_PRIO=y CONFIG_CGROUP_NET_CLASSID=y CONFIG_NET_RX_BUSY_POLL=y @@ -1393,9 +1416,11 @@ CONFIG_NFC_MRVL_USB=m # CONFIG_NFC_MRVL_I2C is not set CONFIG_NFC_ST21NFCA=m CONFIG_NFC_ST21NFCA_I2C=m -# CONFIG_NFC_ST_NCI is not set +# CONFIG_NFC_ST_NCI_I2C is not set +# CONFIG_NFC_ST_NCI_SPI is not set # CONFIG_NFC_NXP_NCI is not set # CONFIG_NFC_S3FWRN5_I2C is not set +# CONFIG_NFC_ST95HF is not set CONFIG_LWTUNNEL=y CONFIG_HAVE_BPF_JIT=y @@ -1403,7 +1428,7 @@ CONFIG_HAVE_BPF_JIT=y # Device Drivers # CONFIG_ARM_AMBA=y -# CONFIG_TEGRA_AHB is not set +CONFIG_TEGRA_AHB=y # # Generic Driver Options @@ -1460,6 +1485,7 @@ CONFIG_MTD=m # CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set # CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set CONFIG_MTD_OF_PARTS=m # CONFIG_MTD_AR7_PARTS is not set @@ -1598,6 +1624,7 @@ CONFIG_VIRTIO_BLK=m CONFIG_BLK_DEV_RBD=m # CONFIG_BLK_DEV_RSXX is not set CONFIG_BLK_DEV_NVME=m +# CONFIG_BLK_DEV_NVME_SCSI is not set # # Misc devices @@ -1738,6 +1765,7 @@ CONFIG_SCSI_HPSA=m # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_HISI_SAS is not set CONFIG_SCSI_MVSAS=m # CONFIG_SCSI_MVSAS_DEBUG is not set CONFIG_SCSI_MVSAS_TASKLET=y @@ -1815,6 +1843,7 @@ CONFIG_SATA_PMP=y CONFIG_SATA_AHCI=y CONFIG_SATA_AHCI_PLATFORM=y # CONFIG_AHCI_CEVA is not set +# CONFIG_AHCI_TEGRA is not set CONFIG_AHCI_XGENE=y # CONFIG_AHCI_QORIQ is not set CONFIG_SATA_INIC162X=m @@ -1918,9 +1947,9 @@ CONFIG_BLK_DEV_DM=y # CONFIG_DM_MQ_DEFAULT is not set CONFIG_DM_DEBUG=y CONFIG_DM_BUFIO=y +# CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set CONFIG_DM_BIO_PRISON=m CONFIG_DM_PERSISTENT_DATA=m -# CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set CONFIG_DM_CRYPT=m CONFIG_DM_SNAPSHOT=y CONFIG_DM_THIN_PROVISIONING=m @@ -1940,6 +1969,7 @@ CONFIG_DM_DELAY=m CONFIG_DM_UEVENT=y CONFIG_DM_FLAKEY=m CONFIG_DM_VERITY=m +CONFIG_DM_VERITY_FEC=y CONFIG_DM_SWITCH=m CONFIG_DM_LOG_WRITES=m CONFIG_TARGET_CORE=m @@ -2020,7 +2050,7 @@ CONFIG_NET_VENDOR_AMD=y CONFIG_AMD8111_ETH=m CONFIG_PCNET32=m CONFIG_AMD_XGBE=m -# CONFIG_AMD_XGBE_DCB is not set +CONFIG_AMD_XGBE_DCB=y CONFIG_NET_XGENE=y CONFIG_NET_VENDOR_ARC=y CONFIG_ARC_EMAC_CORE=m @@ -2085,6 +2115,7 @@ CONFIG_IXGBE_DCB=y CONFIG_IXGBEVF=m CONFIG_I40E=m CONFIG_I40E_VXLAN=y +# CONFIG_I40E_GENEVE is not set # CONFIG_I40E_DCB is not set # CONFIG_I40E_FCOE is not set CONFIG_I40EVF=m @@ -2121,6 +2152,8 @@ CONFIG_FEALNX=m CONFIG_NET_VENDOR_NATSEMI=y CONFIG_NATSEMI=m CONFIG_NS83820=m +CONFIG_NET_VENDOR_NETRONOME=y +# CONFIG_NFP_NETVF is not set CONFIG_NET_VENDOR_8390=y CONFIG_NE2K_PCI=m CONFIG_NET_VENDOR_NVIDIA=y @@ -2187,7 +2220,6 @@ CONFIG_PHYLIB=y # CONFIG_AQUANTIA_PHY is not set CONFIG_AT803X_PHY=m CONFIG_AMD_PHY=m -CONFIG_AMD_XGBE_PHY=m CONFIG_MARVELL_PHY=m CONFIG_DAVICOM_PHY=m CONFIG_QSEMI_PHY=m @@ -2206,7 +2238,7 @@ CONFIG_NATIONAL_PHY=m CONFIG_STE10XP=m CONFIG_LSI_ET1011C_PHY=m CONFIG_MICREL_PHY=m -# CONFIG_DP83848_PHY is not set +CONFIG_DP83848_PHY=m CONFIG_DP83867_PHY=m CONFIG_MICROCHIP_PHY=m CONFIG_FIXED_PHY=y @@ -2259,6 +2291,7 @@ CONFIG_USB_NET_NET1080=m CONFIG_USB_NET_PLUSB=m CONFIG_USB_NET_MCS7830=m CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET_ENABLE=m CONFIG_USB_NET_CDC_SUBSET=m CONFIG_USB_ALI_M5632=y CONFIG_USB_AN2720=y @@ -2277,23 +2310,10 @@ CONFIG_USB_SIERRA_NET=m CONFIG_USB_VL600=m CONFIG_USB_NET_CH9200=m CONFIG_WLAN=y -CONFIG_LIBERTAS_THINFIRM=m -# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set -CONFIG_LIBERTAS_THINFIRM_USB=m -CONFIG_ATMEL=m -CONFIG_PCI_ATMEL=m -CONFIG_AT76C50X_USB=m -CONFIG_PRISM54=m -CONFIG_USB_ZD1201=m -CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_WLAN_VENDOR_ADMTEK=y CONFIG_ADM8211=m -CONFIG_RTL8180=m -CONFIG_RTL8187=m -CONFIG_RTL8187_LEDS=y -CONFIG_MAC80211_HWSIM=m -CONFIG_MWL8K=m CONFIG_ATH_COMMON=m -CONFIG_ATH_CARDS=m +CONFIG_WLAN_VENDOR_ATH=y # CONFIG_ATH_DEBUG is not set CONFIG_ATH5K=m CONFIG_ATH5K_DEBUG=y @@ -2314,6 +2334,7 @@ CONFIG_ATH9K_RFKILL=y CONFIG_ATH9K_PCOEM=y CONFIG_ATH9K_HTC=m # CONFIG_ATH9K_HTC_DEBUGFS is not set +CONFIG_ATH9K_HWRNG=y CONFIG_CARL9170=m CONFIG_CARL9170_LEDS=y # CONFIG_CARL9170_DEBUGFS is not set @@ -2335,6 +2356,11 @@ CONFIG_ATH10K_DEBUGFS=y # CONFIG_ATH10K_TRACING is not set CONFIG_WCN36XX=m # CONFIG_WCN36XX_DEBUGFS is not set +CONFIG_WLAN_VENDOR_ATMEL=y +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m +CONFIG_AT76C50X_USB=m +CONFIG_WLAN_VENDOR_BROADCOM=y CONFIG_B43=m CONFIG_B43_BCMA=y CONFIG_B43_SSB=y @@ -2374,11 +2400,8 @@ CONFIG_BRCMFMAC_USB=y CONFIG_BRCMFMAC_PCIE=y # CONFIG_BRCM_TRACING is not set # CONFIG_BRCMDBG is not set -CONFIG_HOSTAP=m -CONFIG_HOSTAP_FIRMWARE=y -# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set -CONFIG_HOSTAP_PLX=m -CONFIG_HOSTAP_PCI=m +CONFIG_WLAN_VENDOR_CISCO=y +CONFIG_WLAN_VENDOR_INTEL=y CONFIG_IPW2100=m CONFIG_IPW2100_MONITOR=y # CONFIG_IPW2100_DEBUG is not set @@ -2390,6 +2413,15 @@ CONFIG_IPW2200_QOS=y # CONFIG_IPW2200_DEBUG is not set CONFIG_LIBIPW=m # CONFIG_LIBIPW_DEBUG is not set +CONFIG_IWLEGACY=m +CONFIG_IWL4965=m +CONFIG_IWL3945=m + +# +# iwl3945 / iwl4965 Debugging Options +# +CONFIG_IWLEGACY_DEBUG=y +CONFIG_IWLEGACY_DEBUGFS=y CONFIG_IWLWIFI=m CONFIG_IWLWIFI_LEDS=y CONFIG_IWLDVM=m @@ -2405,21 +2437,12 @@ CONFIG_IWLWIFI_DEBUG=y CONFIG_IWLWIFI_DEBUGFS=y # CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE is not set # CONFIG_IWLWIFI_DEVICE_TRACING is not set -CONFIG_IWLEGACY=m -CONFIG_IWL4965=m -CONFIG_IWL3945=m - -# -# iwl3945 / iwl4965 Debugging Options -# -CONFIG_IWLEGACY_DEBUG=y -CONFIG_IWLEGACY_DEBUGFS=y -CONFIG_LIBERTAS=m -CONFIG_LIBERTAS_USB=m -CONFIG_LIBERTAS_SDIO=m -# CONFIG_LIBERTAS_SPI is not set -# CONFIG_LIBERTAS_DEBUG is not set -CONFIG_LIBERTAS_MESH=y +CONFIG_WLAN_VENDOR_INTERSIL=y +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m CONFIG_HERMES=m CONFIG_HERMES_PRISM=y CONFIG_HERMES_CACHE_FW_ON_INIT=y @@ -2433,6 +2456,25 @@ CONFIG_P54_USB=m CONFIG_P54_PCI=m # CONFIG_P54_SPI is not set CONFIG_P54_LEDS=y +CONFIG_PRISM54=m +CONFIG_WLAN_VENDOR_MARVELL=y +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_SDIO=m +# CONFIG_LIBERTAS_SPI is not set +# CONFIG_LIBERTAS_DEBUG is not set +CONFIG_LIBERTAS_MESH=y +CONFIG_LIBERTAS_THINFIRM=m +# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_MWIFIEX_PCIE=m +CONFIG_MWIFIEX_USB=m +CONFIG_MWL8K=m +CONFIG_WLAN_VENDOR_MEDIATEK=y +CONFIG_MT7601U=m +CONFIG_WLAN_VENDOR_RALINK=y CONFIG_RT2X00=m CONFIG_RT2400PCI=m CONFIG_RT2500PCI=m @@ -2462,8 +2504,10 @@ CONFIG_RT2X00_LIB_CRYPTO=y CONFIG_RT2X00_LIB_LEDS=y CONFIG_RT2X00_LIB_DEBUGFS=y # CONFIG_RT2X00_DEBUG is not set -CONFIG_WL_MEDIATEK=y -CONFIG_MT7601U=m +CONFIG_WLAN_VENDOR_REALTEK=y +CONFIG_RTL8180=m +CONFIG_RTL8187=m +CONFIG_RTL8187_LEDS=y CONFIG_RTL_CARDS=m CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m @@ -2483,20 +2527,26 @@ CONFIG_RTL8723_COMMON=m CONFIG_RTLBTCOEXIST=m CONFIG_RTL8XXXU=m # CONFIG_RTL8XXXU_UNTESTED is not set -# CONFIG_WL_TI is not set -CONFIG_ZD1211RW=m -# CONFIG_ZD1211RW_DEBUG is not set -CONFIG_MWIFIEX=m -CONFIG_MWIFIEX_SDIO=m -CONFIG_MWIFIEX_PCIE=m -CONFIG_MWIFIEX_USB=m -CONFIG_CW1200=m -CONFIG_CW1200_WLAN_SDIO=m -# CONFIG_CW1200_WLAN_SPI is not set +CONFIG_WLAN_VENDOR_RSI=y CONFIG_RSI_91X=m CONFIG_RSI_DEBUGFS=y CONFIG_RSI_SDIO=m CONFIG_RSI_USB=m +CONFIG_WLAN_VENDOR_ST=y +CONFIG_CW1200=m +CONFIG_CW1200_WLAN_SDIO=m +# CONFIG_CW1200_WLAN_SPI is not set +CONFIG_WLAN_VENDOR_TI=y +# CONFIG_WL1251 is not set +# CONFIG_WL12XX is not set +# CONFIG_WL18XX is not set +# CONFIG_WLCORE is not set +CONFIG_WLAN_VENDOR_ZYDAS=y +CONFIG_USB_ZD1201=m +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_MAC80211_HWSIM=m +CONFIG_USB_NET_RNDIS_WLAN=m # # Enable WiMAX (Networking options) to see the WiMAX drivers @@ -2508,6 +2558,7 @@ CONFIG_IEEE802154_FAKELB=m # CONFIG_IEEE802154_MRF24J40 is not set # CONFIG_IEEE802154_CC2520 is not set CONFIG_IEEE802154_ATUSB=m +# CONFIG_IEEE802154_ADF7242 is not set # CONFIG_VMXNET3 is not set # CONFIG_FUJITSU_ES is not set # CONFIG_ISDN is not set @@ -2555,6 +2606,7 @@ CONFIG_KEYBOARD_GPIO_POLLED=m # CONFIG_KEYBOARD_MCS is not set # CONFIG_KEYBOARD_MPR121 is not set # CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_TEGRA is not set # CONFIG_KEYBOARD_OPENCORES is not set # CONFIG_KEYBOARD_SAMSUNG is not set # CONFIG_KEYBOARD_STOWAWAY is not set @@ -2636,6 +2688,7 @@ CONFIG_TOUCHSCREEN_DYNAPRO=m # CONFIG_TOUCHSCREEN_HAMPSHIRE is not set CONFIG_TOUCHSCREEN_EETI=m CONFIG_TOUCHSCREEN_EGALAX=m +# CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set # CONFIG_TOUCHSCREEN_FT6236 is not set CONFIG_TOUCHSCREEN_FUJITSU=m # CONFIG_TOUCHSCREEN_GOODIX is not set @@ -2679,6 +2732,7 @@ CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y CONFIG_TOUCHSCREEN_USB_NEXIO=y CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y CONFIG_TOUCHSCREEN_TOUCHIT213=m +# CONFIG_TOUCHSCREEN_TS4800 is not set CONFIG_TOUCHSCREEN_TSC_SERIO=m # CONFIG_TOUCHSCREEN_TSC2004 is not set # CONFIG_TOUCHSCREEN_TSC2005 is not set @@ -2793,6 +2847,7 @@ CONFIG_SERIAL_8250_DW=y # CONFIG_SERIAL_8250_FINTEK is not set # CONFIG_SERIAL_8250_INGENIC is not set # CONFIG_SERIAL_8250_MID is not set +CONFIG_SERIAL_OF_PLATFORM=y # # Non-8250 serial port support @@ -2802,6 +2857,7 @@ CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST=y # CONFIG_SERIAL_KGDB_NMI is not set +CONFIG_SERIAL_TEGRA=y # CONFIG_SERIAL_MAX3100 is not set # CONFIG_SERIAL_MAX310X is not set # CONFIG_SERIAL_UARTLITE is not set @@ -2811,7 +2867,6 @@ CONFIG_CONSOLE_POLL=y CONFIG_SERIAL_JSM=m CONFIG_SERIAL_MSM=y CONFIG_SERIAL_MSM_CONSOLE=y -CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_SERIAL_SCCNXP is not set # CONFIG_SERIAL_SC16IS7XX is not set # CONFIG_SERIAL_ALTERA_JTAGUART is not set @@ -2927,6 +2982,7 @@ CONFIG_I2C_PCA_PLATFORM=m CONFIG_I2C_QUP=y # CONFIG_I2C_RK3X is not set CONFIG_I2C_SIMTEC=m +# CONFIG_I2C_TEGRA is not set CONFIG_I2C_VERSATILE=m # CONFIG_I2C_XILINX is not set @@ -2969,6 +3025,9 @@ CONFIG_SPI_PL022=y # CONFIG_SPI_ROCKCHIP is not set CONFIG_SPI_QUP=y # CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_TEGRA114 is not set +# CONFIG_SPI_TEGRA20_SFLASH is not set +# CONFIG_SPI_TEGRA20_SLINK is not set # CONFIG_SPI_XCOMM is not set # CONFIG_SPI_XILINX is not set # CONFIG_SPI_ZYNQMP_GQSPI is not set @@ -2978,6 +3037,7 @@ CONFIG_SPI_QUP=y # SPI Protocol Masters # CONFIG_SPI_SPIDEV=m +# CONFIG_SPI_LOOPBACK_TEST is not set # CONFIG_SPI_TLE62X0 is not set CONFIG_SPMI=y CONFIG_SPMI_MSM_PMIC_ARB=y @@ -3016,6 +3076,10 @@ CONFIG_GENERIC_PINCONF=y # CONFIG_DEBUG_PINCTRL is not set # CONFIG_PINCTRL_AMD is not set # CONFIG_PINCTRL_SINGLE is not set +CONFIG_PINCTRL_TEGRA=y +CONFIG_PINCTRL_TEGRA124=y +CONFIG_PINCTRL_TEGRA210=y +CONFIG_PINCTRL_TEGRA_XUSB=y # CONFIG_PINCTRL_BAYTRAIL is not set # CONFIG_PINCTRL_CHERRYVIEW is not set # CONFIG_PINCTRL_BROXTON is not set @@ -3028,6 +3092,7 @@ CONFIG_PINCTRL_MSM=y # CONFIG_PINCTRL_MSM8960 is not set # CONFIG_PINCTRL_MSM8X74 is not set CONFIG_PINCTRL_MSM8916=y +CONFIG_PINCTRL_MSM8996=y # CONFIG_PINCTRL_QDF2XXX is not set CONFIG_PINCTRL_QCOM_SPMI_PMIC=y CONFIG_PINCTRL_QCOM_SSBI_PMIC=y @@ -3228,7 +3293,6 @@ CONFIG_SENSORS_MAX6642=m CONFIG_SENSORS_MAX6650=m CONFIG_SENSORS_MAX6697=m # CONFIG_SENSORS_MAX31790 is not set -# CONFIG_SENSORS_HTU21 is not set CONFIG_SENSORS_MCP3021=m # CONFIG_SENSORS_ADCXX is not set CONFIG_SENSORS_LM63=m @@ -3261,6 +3325,7 @@ CONFIG_SENSORS_ADM1275=m CONFIG_SENSORS_LM25066=m CONFIG_SENSORS_LTC2978=m # CONFIG_SENSORS_LTC2978_REGULATOR is not set +# CONFIG_SENSORS_LTC3815 is not set CONFIG_SENSORS_MAX16064=m # CONFIG_SENSORS_MAX20751 is not set CONFIG_SENSORS_MAX34440=m @@ -3334,10 +3399,12 @@ CONFIG_CPU_THERMAL=y # CONFIG_THERMAL_EMULATION is not set CONFIG_HISI_THERMAL=y # CONFIG_IMX_THERMAL is not set +# CONFIG_TEGRA_SOCTHERM is not set CONFIG_QCOM_SPMI_TEMP_ALARM=y CONFIG_WATCHDOG=y CONFIG_WATCHDOG_CORE=y # CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_WATCHDOG_SYSFS is not set # # Watchdog Device Drivers @@ -3345,10 +3412,13 @@ CONFIG_WATCHDOG_CORE=y CONFIG_SOFT_WATCHDOG=m CONFIG_GPIO_WATCHDOG=m # CONFIG_XILINX_WATCHDOG is not set +# CONFIG_ZIIRAVE_WATCHDOG is not set CONFIG_ARM_SP805_WATCHDOG=m # CONFIG_CADENCE_WATCHDOG is not set CONFIG_DW_WATCHDOG=m +# CONFIG_TS4800_WATCHDOG is not set # CONFIG_MAX63XX_WATCHDOG is not set +# CONFIG_TEGRA_WATCHDOG is not set CONFIG_QCOM_WDT=m CONFIG_ALIM7101_WDT=m CONFIG_I6300ESB_WDT=m @@ -3378,7 +3448,6 @@ CONFIG_SSB_PCIHOST=y CONFIG_SSB_B43_PCI_BRIDGE=y CONFIG_SSB_SDIOHOST_POSSIBLE=y CONFIG_SSB_SDIOHOST=y -# CONFIG_SSB_HOST_SOC is not set # CONFIG_SSB_DEBUG is not set CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y CONFIG_SSB_DRIVER_PCICORE=y @@ -3521,6 +3590,8 @@ CONFIG_REGULATOR_GPIO=y # CONFIG_REGULATOR_MAX8973 is not set # CONFIG_REGULATOR_MT6311 is not set # CONFIG_REGULATOR_PFUZE100 is not set +# CONFIG_REGULATOR_PV88060 is not set +# CONFIG_REGULATOR_PV88090 is not set # CONFIG_REGULATOR_PWM is not set CONFIG_REGULATOR_QCOM_RPM=y CONFIG_REGULATOR_QCOM_SMD_RPM=y @@ -3543,6 +3614,7 @@ CONFIG_MEDIA_RADIO_SUPPORT=y CONFIG_MEDIA_SDR_SUPPORT=y CONFIG_MEDIA_RC_SUPPORT=y CONFIG_MEDIA_CONTROLLER=y +# CONFIG_MEDIA_CONTROLLER_DVB is not set CONFIG_VIDEO_DEV=m CONFIG_VIDEO_V4L2_SUBDEV_API=y CONFIG_VIDEO_V4L2=m @@ -3897,6 +3969,7 @@ CONFIG_VIDEO_TDA9840=m CONFIG_VIDEO_TEA6415C=m CONFIG_VIDEO_TEA6420=m CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS3308=m CONFIG_VIDEO_CS5345=m CONFIG_VIDEO_CS53L32A=m CONFIG_VIDEO_UDA1342=m @@ -4142,6 +4215,7 @@ CONFIG_DVB_AF9033=m # CONFIG_VGA_ARB=y CONFIG_VGA_ARB_MAX_GPUS=16 +# CONFIG_TEGRA_HOST1X is not set CONFIG_DRM=m CONFIG_DRM_MIPI_DSI=y CONFIG_DRM_KMS_HELPER=m @@ -4161,11 +4235,12 @@ CONFIG_DRM_I2C_NXP_TDA998X=m # CONFIG_DRM_R128 is not set CONFIG_DRM_RADEON=m CONFIG_DRM_RADEON_USERPTR=y -# CONFIG_DRM_RADEON_UMS is not set CONFIG_DRM_AMDGPU=m # CONFIG_DRM_AMDGPU_CIK is not set CONFIG_DRM_AMDGPU_USERPTR=y +# CONFIG_DRM_AMD_POWERPLAY is not set CONFIG_DRM_NOUVEAU=m +CONFIG_NOUVEAU_PLATFORM_DRIVER=y CONFIG_NOUVEAU_DEBUG=5 CONFIG_NOUVEAU_DEBUG_DEFAULT=3 CONFIG_DRM_NOUVEAU_BACKLIGHT=y @@ -4186,6 +4261,8 @@ CONFIG_DRM_MSM_DSI=y CONFIG_DRM_MSM_DSI_PLL=y CONFIG_DRM_MSM_DSI_28NM_PHY=y CONFIG_DRM_MSM_DSI_20NM_PHY=y +CONFIG_DRM_MSM_DSI_28NM_8960_PHY=y +# CONFIG_DRM_TEGRA is not set CONFIG_DRM_PANEL=y # @@ -4194,8 +4271,10 @@ CONFIG_DRM_PANEL=y CONFIG_DRM_PANEL_SIMPLE=m # CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set # CONFIG_DRM_PANEL_LG_LG4573 is not set +# CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set # CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set +# CONFIG_DRM_PANEL_SHARP_LS043T1LE01 is not set CONFIG_DRM_BRIDGE=y # @@ -4210,6 +4289,7 @@ CONFIG_DRM_BRIDGE=y CONFIG_FB=y # CONFIG_FIRMWARE_EDID is not set CONFIG_FB_CMDLINE=y +CONFIG_FB_NOTIFY=y # CONFIG_FB_DDC is not set # CONFIG_FB_BOOT_VESA_SUPPORT is not set CONFIG_FB_CFB_FILLRECT=y @@ -4436,6 +4516,7 @@ CONFIG_SND_YMFPCI=m # CONFIG_SND_HDA=m CONFIG_SND_HDA_INTEL=m +# CONFIG_SND_HDA_TEGRA is not set CONFIG_SND_HDA_HWDEP=y CONFIG_SND_HDA_RECONFIG=y CONFIG_SND_HDA_INPUT_BEEP=y @@ -4473,6 +4554,7 @@ CONFIG_SND_USB_PODHD=m CONFIG_SND_USB_TONEPORT=m CONFIG_SND_USB_VARIAX=m CONFIG_SND_SOC=m +CONFIG_SND_SOC_AMD_ACP=m # CONFIG_SND_ATMEL_SOC is not set # CONFIG_SND_DESIGNWARE_I2S is not set @@ -4489,6 +4571,7 @@ CONFIG_SND_SOC=m # CONFIG_SND_SOC_FSL_SPDIF is not set # CONFIG_SND_SOC_FSL_ESAI is not set # CONFIG_SND_SOC_IMX_AUDMUX is not set +# CONFIG_SND_SOC_IMG is not set CONFIG_SND_SOC_QCOM=m CONFIG_SND_SOC_LPASS_CPU=m CONFIG_SND_SOC_LPASS_PLATFORM=m @@ -4500,6 +4583,7 @@ CONFIG_SND_SOC_APQ8016_SBC=m # Allwinner SoC Audio support # # CONFIG_SND_SUN4I_CODEC is not set +# CONFIG_SND_SOC_TEGRA is not set # CONFIG_SND_SOC_XTFPGA_I2S is not set CONFIG_SND_SOC_I2C_AND_SPI=m @@ -4527,8 +4611,11 @@ CONFIG_SND_SOC_I2C_AND_SPI=m # CONFIG_SND_SOC_CS4349 is not set # CONFIG_SND_SOC_ES8328 is not set # CONFIG_SND_SOC_GTM601 is not set +# CONFIG_SND_SOC_INNO_RK3036 is not set # CONFIG_SND_SOC_PCM1681 is not set -# CONFIG_SND_SOC_PCM1792A is not set +# CONFIG_SND_SOC_PCM179X is not set +# CONFIG_SND_SOC_PCM3168A_I2C is not set +# CONFIG_SND_SOC_PCM3168A_SPI is not set # CONFIG_SND_SOC_PCM512x_I2C is not set # CONFIG_SND_SOC_PCM512x_SPI is not set # CONFIG_SND_SOC_RT5631 is not set @@ -4567,6 +4654,7 @@ CONFIG_SND_SOC_I2C_AND_SPI=m # CONFIG_SND_SOC_WM8804_SPI is not set # CONFIG_SND_SOC_WM8903 is not set # CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8974 is not set # CONFIG_SND_SOC_WM8978 is not set # CONFIG_SND_SOC_TPA6130A2 is not set CONFIG_SND_SIMPLE_CARD=m @@ -4715,6 +4803,7 @@ CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_PCI=y CONFIG_USB_EHCI_MSM=y +CONFIG_USB_EHCI_TEGRA=y CONFIG_USB_EHCI_HCD_PLATFORM=y # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set @@ -4777,29 +4866,51 @@ CONFIG_USBIP_CORE=m CONFIG_USBIP_VHCI_HCD=m CONFIG_USBIP_HOST=m # CONFIG_USBIP_DEBUG is not set -# CONFIG_USB_MUSB_HDRC is not set +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_HOST=y +# CONFIG_USB_MUSB_GADGET is not set +# CONFIG_USB_MUSB_DUAL_ROLE is not set + +# +# Platform Glue Layer +# + +# +# MUSB DMA mode +# +# CONFIG_MUSB_PIO_ONLY is not set CONFIG_USB_DWC3=y CONFIG_USB_DWC3_ULPI=y CONFIG_USB_DWC3_HOST=y +# CONFIG_USB_DWC3_GADGET is not set +# CONFIG_USB_DWC3_DUAL_ROLE is not set # # Platform Glue Driver Support # CONFIG_USB_DWC3_PCI=y -CONFIG_USB_DWC3_QCOM=y +CONFIG_USB_DWC3_OF_SIMPLE=y CONFIG_USB_DWC2=y CONFIG_USB_DWC2_HOST=y # # Gadget/Dual-role mode requires USB Gadget support to be enabled # +# CONFIG_USB_DWC2_PERIPHERAL is not set +# CONFIG_USB_DWC2_DUAL_ROLE is not set CONFIG_USB_DWC2_PCI=y # CONFIG_USB_DWC2_DEBUG is not set # CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set -# CONFIG_USB_CHIPIDEA is not set +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_OF=y +CONFIG_USB_CHIPIDEA_PCI=y +CONFIG_USB_CHIPIDEA_UDC=y +CONFIG_USB_CHIPIDEA_HOST=y CONFIG_USB_ISP1760=y CONFIG_USB_ISP1760_HCD=y CONFIG_USB_ISP1760_HOST_ROLE=y +# CONFIG_USB_ISP1760_GADGET_ROLE is not set +# CONFIG_USB_ISP1760_DUAL_ROLE is not set # # USB port drivers @@ -4917,12 +5028,13 @@ CONFIG_USB_MSM_OTG=y CONFIG_USB_QCOM_8X16_PHY=y CONFIG_USB_ULPI=y CONFIG_USB_ULPI_VIEWPORT=y -CONFIG_USB_GADGET=m +CONFIG_USB_GADGET=y # CONFIG_USB_GADGET_DEBUG is not set # CONFIG_USB_GADGET_DEBUG_FILES is not set # CONFIG_USB_GADGET_DEBUG_FS is not set CONFIG_USB_GADGET_VBUS_DRAW=500 CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +# CONFIG_U_SERIAL_CONSOLE is not set # # USB Peripheral Controller @@ -5000,12 +5112,14 @@ CONFIG_SDIO_UART=m CONFIG_MMC_ARMMMCI=y CONFIG_MMC_QCOM_DML=y CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y CONFIG_MMC_SDHCI_PCI=y CONFIG_MMC_RICOH_MMC=y # CONFIG_MMC_SDHCI_ACPI is not set CONFIG_MMC_SDHCI_PLTFM=y # CONFIG_MMC_SDHCI_OF_ARASAN is not set # CONFIG_MMC_SDHCI_OF_AT91 is not set +CONFIG_MMC_SDHCI_TEGRA=y # CONFIG_MMC_SDHCI_F_SDH30 is not set CONFIG_MMC_SDHCI_MSM=y CONFIG_MMC_TIFM_SD=y @@ -5150,6 +5264,7 @@ CONFIG_RTC_DRV_M41T80_WDT=y CONFIG_RTC_DRV_BQ32K=m # CONFIG_RTC_DRV_S35390A is not set CONFIG_RTC_DRV_FM3130=m +# CONFIG_RTC_DRV_RX8010 is not set CONFIG_RTC_DRV_RX8581=m CONFIG_RTC_DRV_RX8025=m CONFIG_RTC_DRV_EM3027=m @@ -5206,6 +5321,7 @@ CONFIG_RTC_DRV_V3020=m # CONFIG_RTC_DRV_PL030 is not set CONFIG_RTC_DRV_PL031=y CONFIG_RTC_DRV_PM8XXX=y +# CONFIG_RTC_DRV_TEGRA is not set # CONFIG_RTC_DRV_SNVS is not set CONFIG_RTC_DRV_XGENE=m @@ -5229,6 +5345,7 @@ CONFIG_DMA_OF=y # CONFIG_INTEL_IDMA64 is not set CONFIG_PL330_DMA=m CONFIG_QCOM_BAM_DMA=y +CONFIG_TEGRA20_APB_DMA=y CONFIG_XGENE_DMA=m CONFIG_DW_DMAC_CORE=m CONFIG_DW_DMAC=m @@ -5254,6 +5371,7 @@ CONFIG_UIO_PCI_GENERIC=m CONFIG_VFIO_IOMMU_TYPE1=m CONFIG_VFIO_VIRQFD=m CONFIG_VFIO=m +# CONFIG_VFIO_NOIOMMU is not set CONFIG_VFIO_PCI=m CONFIG_VFIO_PCI_MMAP=y CONFIG_VFIO_PCI_INTX=y @@ -5390,7 +5508,6 @@ CONFIG_ADE7854_SPI=m # Triggers - standalone # # CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set -# CONFIG_IIO_SIMPLE_DUMMY is not set # CONFIG_FB_SM750 is not set # CONFIG_FB_XGI is not set @@ -5399,6 +5516,7 @@ CONFIG_ADE7854_SPI=m # # CONFIG_SPEAKUP is not set # CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set +# CONFIG_MFD_NVEC is not set CONFIG_STAGING_MEDIA=y # CONFIG_I2C_BCM2048 is not set # CONFIG_DVB_CXD2099 is not set @@ -5426,7 +5544,8 @@ CONFIG_LIRC_ZILOG=m # CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set # CONFIG_FB_TFT is not set # CONFIG_FSL_MC_BUS is not set -# CONFIG_WILC1000_DRIVER is not set +# CONFIG_WILC1000_SDIO is not set +# CONFIG_WILC1000_SPI is not set # CONFIG_MOST is not set CONFIG_CHROME_PLATFORMS=y CONFIG_CLKDEV_LOOKUP=y @@ -5444,12 +5563,15 @@ CONFIG_CLK_VEXPRESS_OSC=y # CONFIG_COMMON_CLK_SI514 is not set # CONFIG_COMMON_CLK_SI570 is not set # CONFIG_COMMON_CLK_CDCE925 is not set +# CONFIG_COMMON_CLK_CS2000_CP is not set # CONFIG_CLK_QORIQ is not set CONFIG_COMMON_CLK_XGENE=y +# CONFIG_COMMON_CLK_NXP is not set # CONFIG_COMMON_CLK_PWM is not set # CONFIG_COMMON_CLK_PXA is not set # CONFIG_COMMON_CLK_CDCE706 is not set -# CONFIG_COMMON_CLK_HI6220 is not set +CONFIG_COMMON_CLK_HI6220=y +CONFIG_STUB_CLK_HI6220=y CONFIG_QCOM_GDSC=y CONFIG_COMMON_CLK_QCOM=y # CONFIG_APQ_GCC_8084 is not set @@ -5463,6 +5585,8 @@ CONFIG_MSM_GCC_8916=y # CONFIG_MSM_MMCC_8960 is not set # CONFIG_MSM_GCC_8974 is not set # CONFIG_MSM_MMCC_8974 is not set +# CONFIG_MSM_GCC_8996 is not set +# CONFIG_MSM_MMCC_8996 is not set CONFIG_HWSPINLOCK=y # @@ -5522,7 +5646,13 @@ CONFIG_QCOM_GSBI=y CONFIG_QCOM_SMEM=y CONFIG_QCOM_SMD=y CONFIG_QCOM_SMD_RPM=y +CONFIG_QCOM_SMEM_STATE=y +CONFIG_QCOM_SMP2P=y +CONFIG_QCOM_SMSM=y +CONFIG_QCOM_WCNSS_CTRL=y # CONFIG_SUNXI_SRAM is not set +CONFIG_ARCH_TEGRA_132_SOC=y +CONFIG_ARCH_TEGRA_210_SOC=y # CONFIG_SOC_TI is not set CONFIG_PM_DEVFREQ=y @@ -5545,6 +5675,7 @@ CONFIG_EXTCON=y # CONFIG_EXTCON_ADC_JACK=m CONFIG_EXTCON_GPIO=m +# CONFIG_EXTCON_MAX3355 is not set # CONFIG_EXTCON_RT8973A is not set # CONFIG_EXTCON_SM5502 is not set CONFIG_EXTCON_USB_GPIO=m @@ -5554,8 +5685,10 @@ CONFIG_IIO_BUFFER=y CONFIG_IIO_BUFFER_CB=y CONFIG_IIO_KFIFO_BUF=y CONFIG_IIO_TRIGGERED_BUFFER=y +CONFIG_IIO_CONFIGFS=m CONFIG_IIO_TRIGGER=y CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 +CONFIG_IIO_SW_TRIGGER=m CONFIG_IIO_TRIGGERED_EVENT=m # @@ -5571,11 +5704,15 @@ CONFIG_IIO_ST_ACCEL_I2C_3AXIS=m CONFIG_IIO_ST_ACCEL_SPI_3AXIS=m CONFIG_KXSD9=m CONFIG_KXCJK1013=m +CONFIG_MMA7455=m +CONFIG_MMA7455_I2C=m +CONFIG_MMA7455_SPI=m CONFIG_MMA8452=m CONFIG_MMA9551_CORE=m CONFIG_MMA9551=m CONFIG_MMA9553=m CONFIG_MXC4005=m +CONFIG_MXC6255=m CONFIG_STK8312=m CONFIG_STK8BA50=m @@ -5594,6 +5731,7 @@ CONFIG_AD7923=m CONFIG_AD799X=m CONFIG_CC10001_ADC=m CONFIG_HI8435=m +CONFIG_INA2XX_ADC=m CONFIG_MAX1027=m CONFIG_MAX1363=m CONFIG_MCP320X=m @@ -5603,6 +5741,7 @@ CONFIG_QCOM_SPMI_IADC=y CONFIG_QCOM_SPMI_VADC=y CONFIG_TI_ADC081C=m CONFIG_TI_ADC128S052=m +CONFIG_TI_ADS8688=m CONFIG_VF610_ADC=m CONFIG_VIPERBOARD_ADC=m @@ -5614,6 +5753,7 @@ CONFIG_AD8366=m # # Chemical Sensors # +# CONFIG_IAQCORE is not set CONFIG_VZ89X=m # @@ -5653,6 +5793,11 @@ CONFIG_MAX5821=m CONFIG_MCP4725=m CONFIG_MCP4922=m +# +# IIO dummy driver +# +# CONFIG_IIO_SIMPLE_DUMMY is not set + # # Frequency Synthesizers DDS/PLL # @@ -5684,6 +5829,11 @@ CONFIG_IIO_ST_GYRO_I2C_3AXIS=m CONFIG_IIO_ST_GYRO_SPI_3AXIS=m CONFIG_ITG3200=m +# +# Health sensors +# +CONFIG_MAX30100=m + # # Humidity sensors # @@ -5755,6 +5905,7 @@ CONFIG_HID_SENSOR_DEVICE_ROTATION=m # # Triggers - standalone # +CONFIG_IIO_HRTIMER_TRIGGER=m CONFIG_IIO_INTERRUPT_TRIGGER=m CONFIG_IIO_SYSFS_TRIGGER=m @@ -5803,13 +5954,19 @@ CONFIG_PWM=y CONFIG_PWM_SYSFS=y # CONFIG_PWM_FSL_FTM is not set # CONFIG_PWM_PCA9685 is not set +# CONFIG_PWM_TEGRA is not set CONFIG_IRQCHIP=y CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_MAX_NR=1 CONFIG_ARM_GIC_V2M=y CONFIG_ARM_GIC_V3=y CONFIG_ARM_GIC_V3_ITS=y +CONFIG_HISILICON_IRQ_MBIGEN=y +# CONFIG_TS4800_IRQ is not set # CONFIG_IPACK_BUS is not set +CONFIG_ARCH_HAS_RESET_CONTROLLER=y CONFIG_RESET_CONTROLLER=y +CONFIG_COMMON_RESET_HI6220=y CONFIG_FMC=m CONFIG_FMC_FAKEDEV=m CONFIG_FMC_TRIVIAL=m @@ -5823,6 +5980,7 @@ CONFIG_GENERIC_PHY=y # CONFIG_PHY_PXA_28NM_HSIC is not set # CONFIG_PHY_PXA_28NM_USB2 is not set # CONFIG_BCM_KONA_USB2_PHY is not set +# CONFIG_PHY_HI6220_USB is not set # CONFIG_PHY_SAMSUNG_USB2 is not set # CONFIG_PHY_QCOM_APQ8064_SATA is not set # CONFIG_PHY_QCOM_IPQ806X_SATA is not set @@ -5870,6 +6028,7 @@ CONFIG_DMIID=y CONFIG_DMI_SYSFS=y CONFIG_QCOM_SCM=y CONFIG_QCOM_SCM_64=y +CONFIG_HAVE_ARM_SMCCC=y # # EFI (Extensible Firmware Interface) Support @@ -5962,6 +6121,7 @@ CONFIG_F2FS_FS_SECURITY=y CONFIG_FS_POSIX_ACL=y CONFIG_EXPORTFS=y CONFIG_FILE_LOCKING=y +CONFIG_MANDATORY_FILE_LOCKING=y CONFIG_FSNOTIFY=y CONFIG_DNOTIFY=y CONFIG_INOTIFY_USER=y @@ -6267,6 +6427,7 @@ CONFIG_HAVE_DEBUG_KMEMLEAK=y CONFIG_DEBUG_VM=y # CONFIG_DEBUG_VM_VMACACHE is not set # CONFIG_DEBUG_VM_RB is not set +# CONFIG_DEBUG_VM_PGFLAGS is not set CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_DEBUG_PER_CPU_MAPS is not set CONFIG_HAVE_ARCH_KASAN=y @@ -6283,6 +6444,7 @@ CONFIG_DETECT_HUNG_TASK=y CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_WQ_WATCHDOG is not set # CONFIG_PANIC_ON_OOPS is not set CONFIG_PANIC_ON_OOPS_VALUE=0 CONFIG_PANIC_TIMEOUT=0 @@ -6329,9 +6491,11 @@ CONFIG_RCU_TORTURE_TEST=m CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_RCU_TRACE is not set # CONFIG_RCU_EQS_DEBUG is not set +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y @@ -6403,8 +6567,11 @@ CONFIG_KGDB_SERIAL_CONSOLE=y CONFIG_KGDB_TESTS=y # CONFIG_KGDB_TESTS_ON_BOOT is not set # CONFIG_KGDB_KDB is not set -# CONFIG_ARM64_PTDUMP is not set +# CONFIG_UBSAN is not set +CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y CONFIG_STRICT_DEVMEM=y +# CONFIG_IO_STRICT_DEVMEM is not set +# CONFIG_ARM64_PTDUMP is not set # CONFIG_PID_IN_CONTEXTIDR is not set # CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set # CONFIG_DEBUG_SET_MODULE_RONX is not set @@ -6572,6 +6739,7 @@ CONFIG_CRYPTO_USER_API_HASH=y CONFIG_CRYPTO_USER_API_SKCIPHER=y CONFIG_CRYPTO_USER_API_RNG=y CONFIG_CRYPTO_USER_API_AEAD=y +CONFIG_CRYPTO_HASH_INFO=y CONFIG_CRYPTO_HW=y CONFIG_CRYPTO_DEV_CCP=y CONFIG_CRYPTO_DEV_CCP_DD=m @@ -6671,6 +6839,7 @@ CONFIG_LRU_CACHE=m CONFIG_CLZ_TAB=y CONFIG_CORDIC=m # CONFIG_DDR is not set +CONFIG_IRQ_POLL=y CONFIG_MPILIB=m CONFIG_LIBFDT=y CONFIG_OID_REGISTRY=y