From a4eda44942a96368d0637a0edfad02beeba2faf0 Mon Sep 17 00:00:00 2001 From: Yanteng Si Date: Wed, 17 Jul 2024 18:41:19 +0800 Subject: [PATCH 1/2] Revert "ethernet: bundle module for Motorcomm YT6801" This reverts commit 78c0f53e1e9ff0386321b11e7c0eee10ce32f9ce. --- .../configs/deepin_arm64_desktop_defconfig | 1 - .../deepin_loongarch_desktop_defconfig | 1 - arch/x86/configs/deepin_x86_desktop_defconfig | 1 - drivers/net/ethernet/Kconfig | 1 - drivers/net/ethernet/Makefile | 1 - drivers/net/ethernet/motorcomm/Kconfig | 29 - drivers/net/ethernet/motorcomm/Makefile | 1 - .../net/ethernet/motorcomm/yt6801/Makefile | 23 - .../net/ethernet/motorcomm/yt6801/Notice.txt | 30 - drivers/net/ethernet/motorcomm/yt6801/README | 89 - .../net/ethernet/motorcomm/yt6801/fuxi-dbg.c | 502 -- .../net/ethernet/motorcomm/yt6801/fuxi-dbg.h | 24 - .../ethernet/motorcomm/yt6801/fuxi-efuse.c | 968 --- .../ethernet/motorcomm/yt6801/fuxi-efuse.h | 33 - .../motorcomm/yt6801/fuxi-gmac-common.c | 1012 --- .../motorcomm/yt6801/fuxi-gmac-debugfs.c | 760 -- .../motorcomm/yt6801/fuxi-gmac-desc.c | 1254 --- .../motorcomm/yt6801/fuxi-gmac-ethtool.c | 1255 --- .../ethernet/motorcomm/yt6801/fuxi-gmac-hw.c | 6714 ----------------- .../ethernet/motorcomm/yt6801/fuxi-gmac-net.c | 2366 ------ .../ethernet/motorcomm/yt6801/fuxi-gmac-pci.c | 365 - .../ethernet/motorcomm/yt6801/fuxi-gmac-phy.c | 422 -- .../ethernet/motorcomm/yt6801/fuxi-gmac-reg.h | 1876 ----- .../net/ethernet/motorcomm/yt6801/fuxi-gmac.h | 924 --- .../net/ethernet/motorcomm/yt6801/fuxi-os.h | 560 -- 25 files changed, 19212 deletions(-) delete mode 100644 drivers/net/ethernet/motorcomm/Kconfig delete mode 100644 drivers/net/ethernet/motorcomm/Makefile delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/Makefile delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/Notice.txt delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/README delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-dbg.c delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-dbg.h delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.c delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.h delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-common.c delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-debugfs.c delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-desc.c delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-ethtool.c delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-hw.c delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-net.c delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-pci.c delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-phy.c delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-reg.h delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac.h delete mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-os.h diff --git a/arch/arm64/configs/deepin_arm64_desktop_defconfig b/arch/arm64/configs/deepin_arm64_desktop_defconfig index 45c7d1b27a274..d2b271b97b23b 100644 --- a/arch/arm64/configs/deepin_arm64_desktop_defconfig +++ b/arch/arm64/configs/deepin_arm64_desktop_defconfig @@ -1446,7 +1446,6 @@ CONFIG_ENC28J60=m CONFIG_ENC28J60_WRITEVERIFY=y CONFIG_ENCX24J600=m CONFIG_LAN743X=m -CONFIG_YT6801=m CONFIG_MSCC_OCELOT_SWITCH=m CONFIG_MYRI10GE=m CONFIG_FEALNX=m diff --git a/arch/loongarch/configs/deepin_loongarch_desktop_defconfig b/arch/loongarch/configs/deepin_loongarch_desktop_defconfig index 3758a631a2cc8..0bd110e30568e 100644 --- a/arch/loongarch/configs/deepin_loongarch_desktop_defconfig +++ b/arch/loongarch/configs/deepin_loongarch_desktop_defconfig @@ -1383,7 +1383,6 @@ CONFIG_ENC28J60=m CONFIG_ENCX24J600=m CONFIG_LAN743X=m CONFIG_LAN966X_SWITCH=m -CONFIG_YT6801=m CONFIG_MSCC_OCELOT_SWITCH=m CONFIG_MYRI10GE=m CONFIG_FEALNX=m diff --git a/arch/x86/configs/deepin_x86_desktop_defconfig b/arch/x86/configs/deepin_x86_desktop_defconfig index 4c64d78ceb1cb..3027cf0952f36 100644 --- a/arch/x86/configs/deepin_x86_desktop_defconfig +++ b/arch/x86/configs/deepin_x86_desktop_defconfig @@ -1340,7 +1340,6 @@ CONFIG_KSZ884X_PCI=m CONFIG_ENC28J60=m CONFIG_ENCX24J600=m CONFIG_LAN743X=m -CONFIG_YT6801=m CONFIG_MYRI10GE=m CONFIG_FEALNX=m CONFIG_NI_XGE_MANAGEMENT_ENET=m diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index f921b1a3f62e2..1af5a19f453e6 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -127,7 +127,6 @@ source "drivers/net/ethernet/mediatek/Kconfig" source "drivers/net/ethernet/mellanox/Kconfig" source "drivers/net/ethernet/micrel/Kconfig" source "drivers/net/ethernet/microchip/Kconfig" -source "drivers/net/ethernet/motorcomm/Kconfig" source "drivers/net/ethernet/mscc/Kconfig" source "drivers/net/ethernet/microsoft/Kconfig" source "drivers/net/ethernet/moxa/Kconfig" diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index b91633e4e4016..43bf769a97ad5 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -61,7 +61,6 @@ obj-$(CONFIG_NET_VENDOR_MEDIATEK) += mediatek/ obj-$(CONFIG_NET_VENDOR_MELLANOX) += mellanox/ obj-$(CONFIG_NET_VENDOR_MICREL) += micrel/ obj-$(CONFIG_NET_VENDOR_MICROCHIP) += microchip/ -obj-$(CONFIG_NET_VENDOR_MOTORCOMM) += motorcomm/ obj-$(CONFIG_NET_VENDOR_MICROSEMI) += mscc/ obj-$(CONFIG_NET_VENDOR_MOXART) += moxa/ obj-$(CONFIG_NET_VENDOR_MYRI) += myricom/ diff --git a/drivers/net/ethernet/motorcomm/Kconfig b/drivers/net/ethernet/motorcomm/Kconfig deleted file mode 100644 index 30fc2eabd2bef..0000000000000 --- a/drivers/net/ethernet/motorcomm/Kconfig +++ /dev/null @@ -1,29 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Motorcomm network device configuration -# - -config NET_VENDOR_MOTORCOMM - bool "Motorcomm devices" - default y - depends on PCI - help - If you have a network (Ethernet) card belonging to this class, say Y. - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about Motorcomm cards. If you say Y, you will be asked - for your specific card in the following questions. - -if NET_VENDOR_MOTORCOMM - -config YT6801 - tristate "Motorcomm YT6801 Ethernet support" - depends on PCI - help - If you have a network (Ethernet) controller of this type, say Y here. - - To compile this driver as a module, choose M here. The module - will be called forcedeth. - -endif # NET_VENDOR_MOTORCOMM diff --git a/drivers/net/ethernet/motorcomm/Makefile b/drivers/net/ethernet/motorcomm/Makefile deleted file mode 100644 index e6c5865b1f5d5..0000000000000 --- a/drivers/net/ethernet/motorcomm/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_YT6801) += yt6801/ diff --git a/drivers/net/ethernet/motorcomm/yt6801/Makefile b/drivers/net/ethernet/motorcomm/yt6801/Makefile deleted file mode 100644 index 5f25a4eda63c5..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -################################################################################ -# -# Copyright (c) 2023 Motorcomm, Inc. -# Motorcomm Confidential and Proprietary. -# -# This is Motorcomm NIC driver relevant files. Please don't copy, modify, -# distribute without commercial permission. -# -################################################################################ - -obj-$(CONFIG_YT6801) += yt6801.o - -yt6801-objs := fuxi-gmac-common.o \ - fuxi-gmac-desc.o \ - fuxi-gmac-ethtool.o \ - fuxi-gmac-hw.o \ - fuxi-gmac-net.o \ - fuxi-gmac-pci.o \ - fuxi-gmac-phy.o \ - fuxi-efuse.o \ - fuxi-dbg.o \ - fuxi-gmac-debugfs.o diff --git a/drivers/net/ethernet/motorcomm/yt6801/Notice.txt b/drivers/net/ethernet/motorcomm/yt6801/Notice.txt deleted file mode 100644 index 230978a186357..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/Notice.txt +++ /dev/null @@ -1,30 +0,0 @@ -============================================================================= - -This file contains certain notices of software components included with -the software that Motorcomm, Inc. ("Motorcomm") is required to -provide you. Except where prohibited by the open source license, the -content of this file is provided solely to satisfy Motorcomm's attribution -and notice requirement; your use of these software components -together with the Motorcomm software ("Software") is subject to the terms -of your license from Motorcomm. Compliance with all copyright laws and -software license agreements included in the notice section of this -file are the responsibility of the user. Except as may be granted by -separate express written agreement, this file provides no license to -any patents, trademarks, copyrights, or other intellectual property -of Motorcomm or any of its subsidiaries. - -Software provided with this notice is NOT A CONTRIBUTION to any open -source project. If alternative licensing is available for any of the -components with licenses or attributions provided below, a license -choice is made for receiving such code by Motorcomm. - -Copyright (c) 2021 Motorcomm, Inc. All rights reserved. - -Motorcomm is a trademark of Motorcomm Incorporated, registered in China -and other countries. All Motorcomm Incorporated trademarks -are used with permission. Other products and brand names may be -trademarks or registered trademarks of their respective owners. - -============================================================================= - - diff --git a/drivers/net/ethernet/motorcomm/yt6801/README b/drivers/net/ethernet/motorcomm/yt6801/README deleted file mode 100644 index fb76cff20c1ce..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/README +++ /dev/null @@ -1,89 +0,0 @@ - - - This is the Linux device driver released for Motorcomm YT6801 Gigabit - Ethernet controllers with PCI-Express interface. - - - 1. Set manually - a. Set the IP address of your machine. - - # ifconfig ethX "the IP address of your machine" - - b. Set the IP address of DNS. - - Insert the following configuration in /etc/resolv.conf. - - nameserver "the IP address of DNS" - - c. Set the IP address of gateway. - - # route add default gw "the IP address of gateway" - - 2. Set by doing configurations in /etc/sysconfig/network-scripts - /ifcfg-ethX for Redhat and Fedora, or /etc/sysconfig/network - /ifcfg-ethX for SuSE. There are two examples to set network - configurations. - - a. Fixed IP address: - DEVICE=eth0 - BOOTPROTO=static - ONBOOT=yes - TYPE=ethernet - NETMASK=255.255.255.0 - IPADDR=192.168.1.1 - GATEWAY=192.168.1.254 - BROADCAST=192.168.1.255 - - b. DHCP: - DEVICE=eth0 - BOOTPROTO=dhcp - ONBOOT=yes - - - There are two ways to modify the MAC address of the NIC. - 1. Use ifconfig: - - # ifconfig ethX hw ether YY:YY:YY:YY:YY:YY - - ,where X is the device number assigned by Linux kernel, and - YY:YY:YY:YY:YY:YY is the MAC address assigned by the user. - - 2. Use ip: - - # ip link set ethX address YY:YY:YY:YY:YY:YY - - ,where X is the device number assigned by Linux kernel, and - YY:YY:YY:YY:YY:YY is the MAC address assigned by the user. - - - - Force the link status by using ethtool. - a. Insert the driver first. - b. Make sure that ethtool exists in /sbin. - c. Force the link status as the following command. - - # ethtool -s ethX speed SPEED_MODE duplex DUPLEX_MODE autoneg NWAY_OPTION - - ,where - SPEED_MODE = 1000 for 1000Mbps - = 100 for 100Mbps - = 10 for 10Mbps - DUPLEX_MODE = half for half-duplex - = full for full-duplex - NWAY_OPTION = off for auto-negotiation off (true force) - = on for auto-negotiation on (nway force) - - For example: - - # ethtool -s eth0 speed 100 duplex full autoneg on - - will force PHY to operate in 100Mpbs Full-duplex(nway force). - - - Transmitting Jumbo Frames, whose packet size is bigger than 1500 bytes, please change mtu by the following command. - - # ifconfig ethX mtu MTU - - , where X=0,1,2,..., and MTU is configured by user. - - YT6801 supports Jumbo Frame size up to 9 kBytes. diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-dbg.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-dbg.c deleted file mode 100644 index 5fee2b9a42b47..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-dbg.c +++ /dev/null @@ -1,502 +0,0 @@ -/*++ - -Copyright (c) 2021 Motorcomm Corporation. -Confidential and Proprietary. All rights reserved. - -This is Motorcomm Corporation NIC driver relevant files. Please don't copy, modify, -distribute without commercial permission. - -Module Name: - mp_dbg.c - -Abstract: - This module contains all debug-related code. - -Revision History: - -Notes: - ---*/ - -#include "fuxi-gmac.h" - -#if defined(UEFI) -#include - -UINT32 MPDebugLevel = MP_LOUD; - -void DbgPrintAddress(unsigned char *Address) -{ - // If your MAC address has a different size, adjust the printf accordingly. - //{ASSERT(ETH_LENGTH_OF_ADDRESS == 6); } - - DbgPrintF(MP_LOUD, "%02x-%02x-%02x-%02x-%02x-%02x.", \ - Address[0], Address[1], Address[2], \ - Address[3], Address[4], Address[5]); -} - -void fxgmac_dump_buffer(unsigned char *skb, unsigned int len, int tx_rx) -{ -#define ZDbgPrintF(Level, ...) AsciiPrint("fx-pat " __VA_ARGS__); \ - - //unsigned char buffer[128]; - unsigned int i, j; - char *caption[3] = { "Tx", - "Rx", - "Buffer"}; - - if (tx_rx > 2) - tx_rx = 2; - - ZDbgPrintF(MP_TRACE, " ************** Data dump start ****************\n"); - ZDbgPrintF(MP_TRACE, " %a data of %d bytes\n", caption[tx_rx], len); - - for (i = 0; i < len; i += 32) { - unsigned int len_line = min(len - i, 32U); - - for (j = 0; j < len_line; j++) - { - AsciiPrint("%02x ", (u8)skb[i + j]); - } - AsciiPrint("\n"); - } - - ZDbgPrintF(MP_TRACE, " ************** Data dump end ****************\n"); -} - -#elif defined(_WIN64) || defined(_WIN32) -#include "fuxi-gmac-reg.h" -#include "fuxi-mp.h" -#if DBG - -/** -Constants -**/ - -#define _FILENUMBER 'GBED' - -// Bytes to appear on each line of dump output. -// -#define DUMP_BytesPerLine 16 - -ULONG MPDebugLevel = MP_LOUD; -ULONG MPAllocCount; // the number of outstanding allocs -NDIS_SPIN_LOCK MPMemoryLock; // spinlock for the debug mem list -LIST_ENTRY MPMemoryList; -BOOLEAN MPInitDone = FALSE; // debug mem list init flag - -PVOID -MPAuditAllocMemTag( - UINT Size, - CHAR *FileNumber, - ULONG LineNumber, - NDIS_HANDLE MiniportAdapterHandle - ) -{ - PMP_ALLOCATION pAllocInfo; - PVOID Pointer; - - if (!MPInitDone) - { - NdisAllocateSpinLock(&MPMemoryLock); - InitializeListHead(&MPMemoryList); - MPInitDone = TRUE; - } - - pAllocInfo = NdisAllocateMemoryWithTagPriority( - MiniportAdapterHandle, - (UINT)(Size + sizeof(MP_ALLOCATION)), - NIC_TAG, - LowPoolPriority);//leileiz - - if (pAllocInfo == (PMP_ALLOCATION)NULL) - { - Pointer = NULL; - - DbgPrintF(MP_LOUD, "%s - file %s, line %d, Size %d failed!", __func__, FileNumber, LineNumber, Size); - } else - { - Pointer = (PVOID)&pAllocInfo->UserData; - MP_MEMSET(Pointer, Size, 0xc); - - pAllocInfo->Signature = 'DOOG'; - pAllocInfo->FileNumber = FileNumber; - pAllocInfo->LineNumber = LineNumber; - pAllocInfo->Size = Size; - - NdisAcquireSpinLock(&MPMemoryLock); - InsertTailList(&MPMemoryList, &pAllocInfo->List); - MPAllocCount++; - NdisReleaseSpinLock(&MPMemoryLock); - } - - DbgPrintF(MP_LOUD, - "%s - file %s, line %d, %d bytes, [0x" PTR_FORMAT "].", __func__, - FileNumber, LineNumber, Size, Pointer); - - return(Pointer); -} - -VOID MPAuditFreeMem( - IN PVOID Pointer - ) -{ - PMP_ALLOCATION pAllocInfo; - - pAllocInfo = CONTAINING_RECORD(Pointer, MP_ALLOCATION, UserData); - - ASSERT(pAllocInfo->Signature == (ULONG)'DOOG'); - - NdisAcquireSpinLock(&MPMemoryLock); - pAllocInfo->Signature = (ULONG)'DEAD'; - RemoveEntryList(&pAllocInfo->List); - MPAllocCount--; - NdisReleaseSpinLock(&MPMemoryLock); - - NdisFreeMemory(pAllocInfo, 0, 0); -} - -VOID mpDbgPrintUnicodeString( - IN PUNICODE_STRING UnicodeString - ) -{ - UCHAR Buffer[256]; - - USHORT i; - - for (i = 0; (i < UnicodeString->Length / 2) && (i < 255); i++) - { - Buffer[i] = (UCHAR)UnicodeString->Buffer[i]; - } - -#pragma prefast(suppress : __WARNING_POTENTIAL_BUFFER_OVERFLOW, "i is bounded by 255"); - Buffer[i] = '\0'; - - DbgPrint("%s", Buffer); -} - - -// Hex dump 'cb' bytes starting at 'p' grouping 'ulGroup' bytes together. -// For example, with 'ulGroup' of 1, 2, and 4: -// -// 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -// 0000 0000 0000 0000 0000 0000 0000 0000 |................| -// 00000000 00000000 00000000 00000000 |................| -// -// If 'fAddress' is true, the memory address dumped is prepended to each -// line. -// -VOID -Dump( - __in_bcount(cb) IN CHAR *p, - IN ULONG cb, - IN BOOLEAN fAddress, - IN ULONG ulGroup - ) -{ - INT cbLine; - - while (cb) - { - cbLine = (cb < DUMP_BytesPerLine) ? cb : DUMP_BytesPerLine; -#pragma prefast(suppress : __WARNING_POTENTIAL_BUFFER_OVERFLOW, "p is bounded by cb bytes"); - DumpLine(p, cbLine, fAddress, ulGroup); - cb -= cbLine; - p += cbLine; - } -} - -VOID -DumpLine( - __in_bcount(cb) IN CHAR *p, - IN ULONG cb, - IN BOOLEAN fAddress, - IN ULONG ulGroup - ) -{ - CHAR *pszDigits = "0123456789ABCDEF"; - CHAR szHex[((2 + 1) * DUMP_BytesPerLine) + 1]; - CHAR *pszHex = szHex; - CHAR szAscii[DUMP_BytesPerLine + 1]; - CHAR *pszAscii = szAscii; - ULONG ulGrouped = 0; - - if (fAddress) - { - DbgPrint("RLTK: %p: ", p); - } else - { - DbgPrint("RLTK: "); - } - - while (cb) - { -#pragma prefast(suppress : __WARNING_POTENTIAL_BUFFER_OVERFLOW, "pszHex accessed is always within bounds"); - *pszHex++ = pszDigits[((UCHAR)*p) / 16]; - *pszHex++ = pszDigits[((UCHAR)*p) % 16]; - - if (++ulGrouped >= ulGroup) - { - *pszHex++ = ' '; - ulGrouped = 0; - } - -#pragma prefast(suppress : __WARNING_POTENTIAL_BUFFER_OVERFLOW, "pszAscii is bounded by cb bytes"); - *pszAscii++ = (*p >= 32 && *p < 128) ? *p : '.'; - - ++p; - --cb; - } - - *pszHex = '\0'; - *pszAscii = '\0'; - - DbgPrint( - "%-*s|%-*s|\n", - (2 * DUMP_BytesPerLine) + (DUMP_BytesPerLine / ulGroup), szHex, - DUMP_BytesPerLine, szAscii); -} - -void fxgmac_dump_buffer(unsigned char *skb, unsigned int len, int tx_rx) -{ - #define ZDbgPrintF(Level, ...) DbgPrint("fx-pat " ##__VA_ARGS__); - - unsigned char buffer[128]; - unsigned int i, j; - char *caption[3] = { "Tx", - "Rx", - "Buffer"}; - - if (tx_rx > 2) - tx_rx = 2; - - ZDbgPrintF(MP_TRACE, " ************** Data dump start ****************\n"); - ZDbgPrintF(MP_TRACE, " %s data of %d bytes\n", caption[tx_rx], len); - - for (i = 0; i < len; i += 32) { - unsigned int len_line = min(len - i, 32U); - - for (j = 0; j < len_line; j++) - { - sprintf((char *)&buffer[j * 3], " %02x", (u8)skb[i + j]); - } - buffer[j * 3] = '\0'; - ZDbgPrintF(MP_TRACE, " %#06x: %s\n", i, buffer); - } - - ZDbgPrintF(MP_TRACE, " ************** Data dump end ****************\n"); -} - -VOID -DbgPrintOidName( - _In_ NDIS_OID Oid) -{ - PCHAR oidName = NULL; - - switch (Oid) { -#undef MAKECASE -#define MAKECASE(oidx) case oidx: oidName = NIC_DBG_STRING #oidx "\n"; break; - - /* Operational OIDs */ - MAKECASE(OID_GEN_SUPPORTED_LIST) - MAKECASE(OID_GEN_HARDWARE_STATUS) - MAKECASE(OID_GEN_MEDIA_SUPPORTED) - MAKECASE(OID_GEN_MEDIA_IN_USE) - MAKECASE(OID_GEN_MAXIMUM_LOOKAHEAD) - MAKECASE(OID_GEN_MAXIMUM_FRAME_SIZE) - MAKECASE(OID_GEN_LINK_SPEED) - MAKECASE(OID_GEN_TRANSMIT_BUFFER_SPACE) - MAKECASE(OID_GEN_RECEIVE_BUFFER_SPACE) - MAKECASE(OID_GEN_TRANSMIT_BLOCK_SIZE) - MAKECASE(OID_GEN_RECEIVE_BLOCK_SIZE) - MAKECASE(OID_GEN_VENDOR_ID) - MAKECASE(OID_GEN_VENDOR_DESCRIPTION) - MAKECASE(OID_GEN_VENDOR_DRIVER_VERSION) - MAKECASE(OID_GEN_CURRENT_PACKET_FILTER) - MAKECASE(OID_GEN_CURRENT_LOOKAHEAD) - MAKECASE(OID_GEN_DRIVER_VERSION) - MAKECASE(OID_GEN_MAXIMUM_TOTAL_SIZE) - MAKECASE(OID_GEN_PROTOCOL_OPTIONS) - MAKECASE(OID_GEN_MAC_OPTIONS) - MAKECASE(OID_GEN_MEDIA_CONNECT_STATUS) - MAKECASE(OID_GEN_MAXIMUM_SEND_PACKETS) - MAKECASE(OID_GEN_SUPPORTED_GUIDS) - MAKECASE(OID_GEN_NETWORK_LAYER_ADDRESSES) - MAKECASE(OID_GEN_TRANSPORT_HEADER_OFFSET) - MAKECASE(OID_GEN_MEDIA_CAPABILITIES) - MAKECASE(OID_GEN_PHYSICAL_MEDIUM) - MAKECASE(OID_GEN_MACHINE_NAME) - MAKECASE(OID_GEN_VLAN_ID) - MAKECASE(OID_GEN_RECEIVE_SCALE_PARAMETERS) - MAKECASE(OID_GEN_RECEIVE_SCALE_CAPABILITIES) - MAKECASE(OID_GEN_RECEIVE_HASH) -#if (NTDDI_VERSION >= NTDDI_WINBLUE) || (NDIS_SUPPORT_NDIS640) - MAKECASE(OID_GEN_ISOLATION_PARAMETERS) // query only -#endif - MAKECASE(OID_GEN_RNDIS_CONFIG_PARAMETER) - - /* Operational OIDs for NDIS 6.0 */ - MAKECASE(OID_GEN_MAX_LINK_SPEED) - MAKECASE(OID_GEN_LINK_STATE) - MAKECASE(OID_GEN_LINK_PARAMETERS) - MAKECASE(OID_GEN_MINIPORT_RESTART_ATTRIBUTES) - MAKECASE(OID_GEN_ENUMERATE_PORTS) - MAKECASE(OID_GEN_PORT_STATE) - MAKECASE(OID_GEN_PORT_AUTHENTICATION_PARAMETERS) - MAKECASE(OID_GEN_INTERRUPT_MODERATION) - MAKECASE(OID_GEN_PHYSICAL_MEDIUM_EX) - - /* Statistical OIDs */ - MAKECASE(OID_GEN_XMIT_OK) - MAKECASE(OID_GEN_RCV_OK) - MAKECASE(OID_GEN_XMIT_ERROR) - MAKECASE(OID_GEN_RCV_ERROR) - MAKECASE(OID_GEN_RCV_NO_BUFFER) - MAKECASE(OID_GEN_DIRECTED_BYTES_XMIT) - MAKECASE(OID_GEN_DIRECTED_FRAMES_XMIT) - MAKECASE(OID_GEN_MULTICAST_BYTES_XMIT) - MAKECASE(OID_GEN_MULTICAST_FRAMES_XMIT) - MAKECASE(OID_GEN_BROADCAST_BYTES_XMIT) - MAKECASE(OID_GEN_BROADCAST_FRAMES_XMIT) - MAKECASE(OID_GEN_DIRECTED_BYTES_RCV) - MAKECASE(OID_GEN_DIRECTED_FRAMES_RCV) - MAKECASE(OID_GEN_MULTICAST_BYTES_RCV) - MAKECASE(OID_GEN_MULTICAST_FRAMES_RCV) - MAKECASE(OID_GEN_BROADCAST_BYTES_RCV) - MAKECASE(OID_GEN_BROADCAST_FRAMES_RCV) - MAKECASE(OID_GEN_RCV_CRC_ERROR) - MAKECASE(OID_GEN_TRANSMIT_QUEUE_LENGTH) - - /* Statistical OIDs for NDIS 6.0 */ - MAKECASE(OID_GEN_STATISTICS) - MAKECASE(OID_GEN_BYTES_RCV) - MAKECASE(OID_GEN_BYTES_XMIT) - MAKECASE(OID_GEN_RCV_DISCARDS) - MAKECASE(OID_GEN_XMIT_DISCARDS) - - /* Misc OIDs */ - MAKECASE(OID_GEN_GET_TIME_CAPS) - MAKECASE(OID_GEN_GET_NETCARD_TIME) - MAKECASE(OID_GEN_NETCARD_LOAD) - MAKECASE(OID_GEN_DEVICE_PROFILE) - MAKECASE(OID_GEN_INIT_TIME_MS) - MAKECASE(OID_GEN_RESET_COUNTS) - MAKECASE(OID_GEN_MEDIA_SENSE_COUNTS) - - /* PnP power management operational OIDs */ - MAKECASE(OID_PNP_SET_POWER) - MAKECASE(OID_PNP_QUERY_POWER) - MAKECASE(OID_PNP_CAPABILITIES) - MAKECASE(OID_PNP_ADD_WAKE_UP_PATTERN) - MAKECASE(OID_PNP_REMOVE_WAKE_UP_PATTERN) - MAKECASE(OID_PNP_ENABLE_WAKE_UP) - MAKECASE(OID_PM_HARDWARE_CAPABILITIES) - MAKECASE(OID_PM_ADD_WOL_PATTERN) - MAKECASE(OID_PM_REMOVE_WOL_PATTERN) - MAKECASE(OID_PM_PARAMETERS) - MAKECASE(OID_PM_WOL_PATTERN_LIST) - MAKECASE(OID_PM_ADD_PROTOCOL_OFFLOAD) - MAKECASE(OID_PM_REMOVE_PROTOCOL_OFFLOAD) - MAKECASE(OID_PM_PROTOCOL_OFFLOAD_LIST) - - MAKECASE(OID_PNP_WAKE_UP_PATTERN_LIST) - /* PnP power management statistical OIDs */ - MAKECASE(OID_PNP_WAKE_UP_ERROR) - MAKECASE(OID_PNP_WAKE_UP_OK) - - /* Ethernet operational OIDs */ - MAKECASE(OID_802_3_PERMANENT_ADDRESS) - MAKECASE(OID_802_3_CURRENT_ADDRESS) - MAKECASE(OID_802_3_MULTICAST_LIST) - MAKECASE(OID_802_3_MAXIMUM_LIST_SIZE) - MAKECASE(OID_802_3_MAC_OPTIONS) - - /* Ethernet operational OIDs for NDIS 6.0 */ - MAKECASE(OID_802_3_ADD_MULTICAST_ADDRESS) - MAKECASE(OID_802_3_DELETE_MULTICAST_ADDRESS) - - /* Ethernet statistical OIDs */ - MAKECASE(OID_802_3_RCV_ERROR_ALIGNMENT) - MAKECASE(OID_802_3_XMIT_ONE_COLLISION) - MAKECASE(OID_802_3_XMIT_MORE_COLLISIONS) - MAKECASE(OID_802_3_XMIT_DEFERRED) - MAKECASE(OID_802_3_XMIT_MAX_COLLISIONS) - MAKECASE(OID_802_3_RCV_OVERRUN) - MAKECASE(OID_802_3_XMIT_UNDERRUN) - MAKECASE(OID_802_3_XMIT_HEARTBEAT_FAILURE) - MAKECASE(OID_802_3_XMIT_TIMES_CRS_LOST) - MAKECASE(OID_802_3_XMIT_LATE_COLLISIONS) - - /* TCP/IP OIDs */ - MAKECASE(OID_TCP_TASK_OFFLOAD) - MAKECASE(OID_TCP_TASK_IPSEC_ADD_SA) - MAKECASE(OID_TCP_TASK_IPSEC_DELETE_SA) - MAKECASE(OID_TCP_SAN_SUPPORT) - MAKECASE(OID_TCP_TASK_IPSEC_ADD_UDPESP_SA) - MAKECASE(OID_TCP_TASK_IPSEC_DELETE_UDPESP_SA) - MAKECASE(OID_TCP4_OFFLOAD_STATS) - MAKECASE(OID_TCP6_OFFLOAD_STATS) - MAKECASE(OID_IP4_OFFLOAD_STATS) - MAKECASE(OID_IP6_OFFLOAD_STATS) - - /* TCP offload OIDs for NDIS 6 */ - MAKECASE(OID_TCP_OFFLOAD_CURRENT_CONFIG) - MAKECASE(OID_TCP_OFFLOAD_PARAMETERS) - MAKECASE(OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES) - MAKECASE(OID_TCP_CONNECTION_OFFLOAD_CURRENT_CONFIG) - MAKECASE(OID_TCP_CONNECTION_OFFLOAD_HARDWARE_CAPABILITIES) - MAKECASE(OID_OFFLOAD_ENCAPSULATION) - -#if (NDIS_SUPPORT_NDIS620) - /* VMQ OIDs for NDIS 6.20 */ - MAKECASE(OID_RECEIVE_FILTER_FREE_QUEUE) - MAKECASE(OID_RECEIVE_FILTER_CLEAR_FILTER) - MAKECASE(OID_RECEIVE_FILTER_ALLOCATE_QUEUE) - MAKECASE(OID_RECEIVE_FILTER_QUEUE_ALLOCATION_COMPLETE) - MAKECASE(OID_RECEIVE_FILTER_SET_FILTER) -#endif - -#if (NDIS_SUPPORT_NDIS630 || NDIS_SUPPORT_NDIS680) - /* NDIS QoS OIDs for NDIS 6.30 */ - MAKECASE(OID_QOS_PARAMETERS) -#endif - -#if (NDIS_SUPPORT_NDIS680) - /* RSSv2 OIDS*/ - MAKECASE(OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES) - MAKECASE(OID_GEN_RECEIVE_SCALE_PARAMETERS_V2) -#endif - } - - if (oidName) - { - DbgPrintF(MP_LOUD, "%s", oidName); - } else - { - DbgPrintF(MP_LOUD, "<** Unknown OID 0x%08x **>.", Oid); - } -} - -VOID -DbgPrintAddress( - _In_reads_bytes_(ETH_LENGTH_OF_ADDRESS) PUCHAR Address) -{ - // If your MAC address has a different size, adjust the printf accordingly. - //{ASSERT(ETH_LENGTH_OF_ADDRESS == 6); } - - DbgPrintF(MP_LOUD, "%02x-%02x-%02x-%02x-%02x-%02x.", - Address[0], Address[1], Address[2], - Address[3], Address[4], Address[5]); -} -#endif - -#elif defined(LINUX) - -#elif defined(UBOOT) -#ifdef DBG -u32 MPDebugLevel = MP_LOUD; -#endif -#else - -#endif - diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-dbg.h b/drivers/net/ethernet/motorcomm/yt6801/fuxi-dbg.h deleted file mode 100644 index a8c42369e7837..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-dbg.h +++ /dev/null @@ -1,24 +0,0 @@ -/*++ - -Copyright (c) 2021 Motorcomm Corporation. -Confidential and Proprietary. All rights reserved. - -This is Motorcomm Corporation NIC driver relevant files. Please don't copy, modify, -distribute without commercial permission. - ---*/ - -#ifndef _MP_DBG_H -#define _MP_DBG_H - -// -// Message verbosity: lower values indicate higher urgency -// -#define MP_OFF 0 -#define MP_ERROR 1 -#define MP_WARN 2 -#define MP_TRACE 3 -#define MP_INFO 4 -#define MP_LOUD 5 - -#endif // _MP_DBG_H \ No newline at end of file diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.c deleted file mode 100644 index a91734fd84d70..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.c +++ /dev/null @@ -1,968 +0,0 @@ - -/*++ - -Copyright (c) 2021 Motorcomm Corporation. -Confidential and Proprietary. All rights reserved. - -This is Motorcomm Corporation NIC driver relevant files. Please don't copy, modify, -distribute without commercial permission. - ---*/ - -#include "fuxi-gmac.h" -#include "fuxi-gmac-reg.h" -#include "fuxi-efuse.h" - -#ifdef UEFI -#include "nic_sw.h" -#endif - -bool fxgmac_read_patch_from_efuse_per_index(struct fxgmac_pdata* pdata, u8 index, u32* offset, u32* value) /* read patch per index. */ -{ - unsigned int wait, i; - u32 regval = 0; - bool succeed = false; - - if (index >= FUXI_EFUSE_MAX_ENTRY) { - FXGMAC_PR("Reading efuse out of range, index %d\n", index); - return false; - } - - if (offset) { - *offset = 0; - } - for (i = EFUSE_PATCH_ADDR_START_BYTE; i < EFUSE_PATCH_DATA_START_BYTE; i++) { - regval = 0; - regval = FXGMAC_SET_REG_BITS(regval, EFUSE_OP_ADDR_POS, EFUSE_OP_ADDR_LEN, EFUSE_REGION_A_B_LENGTH + index * EFUSE_EACH_PATH_SIZE + i); - regval = FXGMAC_SET_REG_BITS(regval, EFUSE_OP_START_POS, EFUSE_OP_START_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, EFUSE_OP_MODE_POS, EFUSE_OP_MODE_LEN, EFUSE_OP_MODE_ROW_READ); - writereg(pdata->pAdapter, regval, pdata->base_mem + EFUSE_OP_CTRL_0); - wait = 1000; - while (wait--) { - usleep_range_ex(pdata->pAdapter, 20, 50); - regval = readreg(pdata->pAdapter, pdata->base_mem + EFUSE_OP_CTRL_1); - if (FXGMAC_GET_REG_BITS(regval, EFUSE_OP_DONE_POS, EFUSE_OP_DONE_LEN)) { - succeed = true; - break; - } - } - if (succeed) { - if (offset) { - *offset |= (FXGMAC_GET_REG_BITS(regval, EFUSE_OP_RD_DATA_POS, EFUSE_OP_RD_DATA_LEN) << (i << 3)); - } - } - else { - FXGMAC_PR("Fail to reading efuse Byte%d\n", index * EFUSE_EACH_PATH_SIZE + i); - return succeed; - } - } - - if (value) { - *value = 0; - } - for (i = EFUSE_PATCH_DATA_START_BYTE; i < EFUSE_EACH_PATH_SIZE; i++) { - regval = 0; - regval = FXGMAC_SET_REG_BITS(regval, EFUSE_OP_ADDR_POS, EFUSE_OP_ADDR_LEN, EFUSE_REGION_A_B_LENGTH + index * EFUSE_EACH_PATH_SIZE + i); - regval = FXGMAC_SET_REG_BITS(regval, EFUSE_OP_START_POS, EFUSE_OP_START_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, EFUSE_OP_MODE_POS, EFUSE_OP_MODE_LEN, EFUSE_OP_MODE_ROW_READ); - writereg(pdata->pAdapter, regval, pdata->base_mem + EFUSE_OP_CTRL_0); - wait = 1000; - while (wait--) { - usleep_range_ex(pdata->pAdapter, 20, 50); - regval = readreg(pdata->pAdapter, pdata->base_mem + EFUSE_OP_CTRL_1); - if (FXGMAC_GET_REG_BITS(regval, EFUSE_OP_DONE_POS, EFUSE_OP_DONE_LEN)) { - succeed = true; - break; - } - } - if (succeed) { - if (value) { - *value |= (FXGMAC_GET_REG_BITS(regval, EFUSE_OP_RD_DATA_POS, EFUSE_OP_RD_DATA_LEN) << ((i - 2) << 3)); - } - } - else { - FXGMAC_PR("Fail to reading efuse Byte%d\n", index * EFUSE_EACH_PATH_SIZE + i); - return succeed; - } - } - - return succeed; -} - -bool fxgmac_read_patch_from_efuse(struct fxgmac_pdata* pdata, u32 offset, u32* value) /* read patch per index. */ -{ - u32 reg_offset, reg_val; - u32 cur_val = 0; - bool succeed = true; - u8 index = 0; - - if(offset >> 16){ - FXGMAC_PR("Reading efuse out of range, reg %d. reg must be 2bytes.\n", index); - return false; - } - - for (index = 0; index < FUXI_EFUSE_MAX_ENTRY; index++) { - if (!fxgmac_read_patch_from_efuse_per_index(pdata, index, ®_offset, ®_val)) { - succeed = false; - break; - } else if (reg_offset == offset) { - cur_val = reg_val; - } else if (0 == reg_offset && 0 == reg_val) { - break; // first blank. We should write here. - } - } - - if (value) { - *value = cur_val; - } - - return succeed; -} - -bool fxgmac_write_patch_to_efuse_per_index(struct fxgmac_pdata* pdata, u8 index, u32 offset, u32 value) -{ - unsigned int wait, i; - u32 reg_val; - bool succeed = false; - u32 cur_reg, cur_val; - u8 max_index = FUXI_EFUSE_MAX_ENTRY; - - if(offset >> 16){ - FXGMAC_PR("Reading efuse out of range, reg %d. reg must be 2bytes.\n", index); - return false; - } - - fxgmac_efuse_read_data(pdata, EFUSE_LED_ADDR, ®_val); - if (EFUSE_LED_COMMON_SOLUTION == reg_val) { - max_index = FUXI_EFUSE_MAX_ENTRY_UNDER_LED_COMMON; - } - - if (index >= max_index) { - FXGMAC_PR("Writing efuse out of range, index %d max index %d\n", index, max_index); - return false; - } - - if (fxgmac_read_patch_from_efuse_per_index(pdata, index, &cur_reg, &cur_val)) { - if(cur_reg != 0 || cur_val != 0){ - FXGMAC_PR(" The index %d has writed value, cannot rewrite it.\n", index); - return false; - } - }else{ - FXGMAC_PR("Cannot read index %d.\n", index); - return false; - } - - for (i = EFUSE_PATCH_ADDR_START_BYTE; i < EFUSE_PATCH_DATA_START_BYTE; i++) { - reg_val = 0; - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_ADDR_POS, EFUSE_OP_ADDR_LEN, EFUSE_REGION_A_B_LENGTH + index * EFUSE_EACH_PATH_SIZE + i); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_WR_DATA_POS, EFUSE_OP_WR_DATA_LEN, (offset >> (i << 3)) & 0xFF); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, EFUSE_OP_START_LEN, 1); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, EFUSE_OP_MODE_LEN, EFUSE_OP_MODE_ROW_WRITE); - writereg(pdata->pAdapter, reg_val, pdata->base_mem + EFUSE_OP_CTRL_0); - - succeed = false; - wait = 1000; - while (wait--) { - usleep_range_ex(pdata->pAdapter, 20, 50); - reg_val = readreg(pdata->pAdapter, pdata->base_mem + EFUSE_OP_CTRL_1); - if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, EFUSE_OP_DONE_LEN)) { - succeed = true; - break; - } - } - if (!succeed) { - FXGMAC_PR("Fail to writing efuse Byte%d\n", index * EFUSE_EACH_PATH_SIZE + i); - return succeed; - } - } - - for (i = 2; i < 6; i++) { - reg_val = 0; - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_ADDR_POS, EFUSE_OP_ADDR_LEN, 18 + index * 6 + i); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_WR_DATA_POS, EFUSE_OP_WR_DATA_LEN, (value >> ((i - 2) << 3)) & 0xFF); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, EFUSE_OP_START_LEN, 1); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, EFUSE_OP_MODE_LEN, EFUSE_OP_MODE_ROW_WRITE); - writereg(pdata->pAdapter, reg_val, pdata->base_mem + EFUSE_OP_CTRL_0); - - succeed = false; - wait = 1000; - while (wait--) { - usleep_range_ex(pdata->pAdapter, 20, 50); - reg_val = readreg(pdata->pAdapter, pdata->base_mem + EFUSE_OP_CTRL_1); - if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, EFUSE_OP_DONE_LEN)) { - succeed = true; - break; - } - } - if (!succeed) { - FXGMAC_PR("Fail to writing efuse Byte%d\n", index * EFUSE_EACH_PATH_SIZE + i); - return succeed; - } - } - - return succeed; -} - -bool fxgmac_write_patch_to_efuse(struct fxgmac_pdata* pdata, u32 offset, u32 value) -{ - unsigned int wait, i; - u32 reg_offset, reg_val; - u32 cur_offset = 0, cur_val = 0; - bool succeed = false; - u8 index = 0; - - if(offset >> 16){ - FXGMAC_PR("Reading efuse out of range, reg %d. reg must be 2bytes.\n", index); - return false; - } - - for (index = 0; ; index++) { - if (!fxgmac_read_patch_from_efuse_per_index(pdata, index, ®_offset, ®_val)) { - return false; - } else if (reg_offset == offset) { - cur_offset = reg_offset; - cur_val = reg_val; - } else if (0 == reg_offset && 0 == reg_val) { - break; // first blank. We should write here. - } - } - - if (cur_offset == offset) { - if (cur_val == value) { - FXGMAC_PR("0x%x -> Reg0x%x already exists, ignore.\n", value, offset); - return true; - } else { - FXGMAC_PR("Reg0x%x entry current value 0x%x, reprogram.\n", offset, value); - } - } - - for (i = EFUSE_PATCH_ADDR_START_BYTE; i < EFUSE_PATCH_DATA_START_BYTE; i++) { - reg_val = 0; - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_ADDR_POS, EFUSE_OP_ADDR_LEN, EFUSE_REGION_A_B_LENGTH + index * EFUSE_EACH_PATH_SIZE + i); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_WR_DATA_POS, EFUSE_OP_WR_DATA_LEN, (offset >> (i << 3)) & 0xFF ); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, EFUSE_OP_START_LEN, 1); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, EFUSE_OP_MODE_LEN, EFUSE_OP_MODE_ROW_WRITE); - writereg(pdata->pAdapter, reg_val, pdata->base_mem + EFUSE_OP_CTRL_0); - - succeed = false; - wait = 1000; - while (wait--) { - usleep_range_ex(pdata->pAdapter, 20, 50); - reg_val = readreg(pdata->pAdapter, pdata->base_mem + EFUSE_OP_CTRL_1); - if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, EFUSE_OP_DONE_LEN)) { - succeed = true; - break; - } - } - if (!succeed) { - FXGMAC_PR("Fail to writing efuse Byte%d\n", index * EFUSE_EACH_PATH_SIZE + i); - return succeed; - } - } - - for (i = EFUSE_PATCH_DATA_START_BYTE; i < EFUSE_EACH_PATH_SIZE; i++) { - reg_val = 0; - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_ADDR_POS, EFUSE_OP_ADDR_LEN, EFUSE_REGION_A_B_LENGTH + index * EFUSE_EACH_PATH_SIZE + i); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_WR_DATA_POS, EFUSE_OP_WR_DATA_LEN, (value >> ((i - 2) << 3)) & 0xFF); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, EFUSE_OP_START_LEN, 1); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, EFUSE_OP_MODE_LEN, EFUSE_OP_MODE_ROW_WRITE); - writereg(pdata->pAdapter, reg_val, pdata->base_mem + EFUSE_OP_CTRL_0); - - succeed = false; - wait = 1000; - while (wait--) { - usleep_range_ex(pdata->pAdapter, 20, 50); - reg_val = readreg(pdata->pAdapter, pdata->base_mem + EFUSE_OP_CTRL_1); - if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, EFUSE_OP_DONE_LEN)) { - succeed = true; - break; - } - } - if (!succeed) { - FXGMAC_PR("Fail to writing efuse Byte%d\n", index * EFUSE_EACH_PATH_SIZE + i); - return succeed; - } - } - - return succeed; -} - -bool fxgmac_read_mac_subsys_from_efuse(struct fxgmac_pdata* pdata, u8* mac_addr, u32* subsys, u32* revid) -{ - u32 offset = 0, value = 0; - u32 machr = 0, maclr = 0; - bool succeed = true; - u8 index = 0; - - for (index = 0; ; index++) { - if (!fxgmac_read_patch_from_efuse_per_index(pdata, index, &offset, &value)) { - succeed = false; - break; // reach the last item. - } - if (0x00 == offset) { - break; // reach the blank. - } - if (MACA0LR_FROM_EFUSE == offset) { - maclr = value; - } - if (MACA0HR_FROM_EFUSE == offset) { - machr = value; - } - - if ((0x08 == offset) && revid) { - *revid = value; - } - if ((0x2C == offset) && subsys) { - *subsys = value; - } - } - if (mac_addr) { - mac_addr[5] = (u8)(maclr & 0xFF); - mac_addr[4] = (u8)((maclr >> 8) & 0xFF); - mac_addr[3] = (u8)((maclr >> 16) & 0xFF); - mac_addr[2] = (u8)((maclr >> 24) & 0xFF); - mac_addr[1] = (u8)(machr & 0xFF); - mac_addr[0] = (u8)((machr >> 8) & 0xFF); - } - - return succeed; -} - -bool fxgmac_write_mac_subsys_to_efuse(struct fxgmac_pdata* pdata, u8* mac_addr, u32* subsys, u32* revid) -{ - u32 machr = 0, maclr = 0,pcie_cfg_ctrl= PCIE_CFG_CTRL_DEFAULT_VAL; - bool succeed = true; - if (mac_addr) { - machr = readreg(pdata->pAdapter, pdata->base_mem + MACA0HR_FROM_EFUSE); - maclr = readreg(pdata->pAdapter, pdata->base_mem + MACA0LR_FROM_EFUSE); - DPRINTK("Current mac address from efuse is %02x-%02x-%02x-%02x-%02x-%02x.\n", - (machr >> 8) & 0xFF, machr & 0xFF, (maclr >> 24) & 0xFF, (maclr >> 16) & 0xFF, (maclr >> 8) & 0xFF, maclr & 0xFF); - - if(!fxgmac_write_patch_to_efuse(pdata, MACA0HR_FROM_EFUSE, (((u32)mac_addr[0]) << 8) | mac_addr[1])){ - succeed = false; - } - if(!fxgmac_write_patch_to_efuse(pdata, MACA0LR_FROM_EFUSE, (((u32)mac_addr[2]) << 24) | (((u32)mac_addr[3]) << 16) | (((u32)mac_addr[4]) << 8) | mac_addr[5])){ - succeed = false; - } - } - - if (revid) { - if(!fxgmac_write_patch_to_efuse(pdata, EFUSE_REVID_REGISTER, *revid)){ - succeed = false; - } - } - if (subsys) { - pcie_cfg_ctrl = FXGMAC_SET_REG_BITS(pcie_cfg_ctrl, MGMT_PCIE_CFG_CTRL_CS_EN_POS, MGMT_PCIE_CFG_CTRL_CS_EN_LEN, 1); - if (!fxgmac_write_patch_to_efuse(pdata, MGMT_PCIE_CFG_CTRL, pcie_cfg_ctrl)){ - succeed = false; - } - if(!fxgmac_write_patch_to_efuse(pdata, EFUSE_SUBSYS_REGISTER, *subsys)){ - succeed = false; - } - pcie_cfg_ctrl = FXGMAC_SET_REG_BITS(pcie_cfg_ctrl, MGMT_PCIE_CFG_CTRL_CS_EN_POS, MGMT_PCIE_CFG_CTRL_CS_EN_LEN, 0); - if (!fxgmac_write_patch_to_efuse(pdata, MGMT_PCIE_CFG_CTRL, pcie_cfg_ctrl)){ - succeed = false; - } - } - return succeed; -} - -bool fxgmac_write_mac_addr_to_efuse(struct fxgmac_pdata* pdata, u8* mac_addr) -{ - u32 machr = 0, maclr = 0; - bool succeed = true; - - if (mac_addr) { - machr = readreg(pdata->pAdapter, pdata->base_mem + MACA0HR_FROM_EFUSE); - maclr = readreg(pdata->pAdapter, pdata->base_mem + MACA0LR_FROM_EFUSE); - DPRINTK("Current mac address from efuse is %02x-%02x-%02x-%02x-%02x-%02x.\n", - (machr >> 8) & 0xFF, machr & 0xFF, (maclr >> 24) & 0xFF, (maclr >> 16) & 0xFF, (maclr >> 8) & 0xFF, maclr & 0xFF); - - if(!fxgmac_write_patch_to_efuse(pdata, MACA0HR_FROM_EFUSE, (((u32)mac_addr[0]) << 8) | mac_addr[1])){ - succeed = false; - } - if(!fxgmac_write_patch_to_efuse(pdata, MACA0LR_FROM_EFUSE, (((u32)mac_addr[2]) << 24) | (((u32)mac_addr[3]) << 16) | (((u32)mac_addr[4]) << 8) | mac_addr[5])){ - succeed = false; - } - } - - return succeed; -} - -bool fxgmac_read_subsys_from_efuse(struct fxgmac_pdata* pdata, u32* subsys, u32* revid) -{ - u32 offset = 0, value = 0; - u8 index; - bool succeed = true; - - for (index = 0; ; index++) { - if (!fxgmac_read_patch_from_efuse_per_index(pdata, index, &offset, &value)) { - succeed = false; - break; // reach the last item. - } - if (0x00 == offset) { - break; // reach the blank. - } - - if ((EFUSE_REVID_REGISTER == offset) && revid) { - *revid = value; - }else{ - succeed = false; - } - if ((EFUSE_SUBSYS_REGISTER == offset) && subsys) { - *subsys = value; - }else{ - succeed = false; - } - } - - return succeed; -} - -bool fxgmac_write_subsys_to_efuse(struct fxgmac_pdata* pdata, u32* subsys, u32* revid) -{ - bool succeed = true; - - /* write subsys info */ - if (revid) { - if(!fxgmac_write_patch_to_efuse(pdata, EFUSE_REVID_REGISTER, *revid)){ - succeed = false; - } - } - if (subsys) { - if(!fxgmac_write_patch_to_efuse(pdata, EFUSE_SUBSYS_REGISTER, *subsys)){ - succeed = false; - } - } - return succeed; -} - -bool fxgmac_efuse_load(struct fxgmac_pdata* pdata) -{ - bool succeed = false; - unsigned int wait; - u32 reg_val = 0; - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, EFUSE_OP_START_LEN, 1); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, EFUSE_OP_MODE_LEN, EFUSE_OP_MODE_AUTO_LOAD); - writereg(pdata->pAdapter, reg_val, pdata->base_mem + EFUSE_OP_CTRL_0); - - wait = 1000; - while (wait--) { - usleep_range_ex(pdata->pAdapter, 20, 50); - reg_val = readreg(pdata->pAdapter, pdata->base_mem + EFUSE_OP_CTRL_1); - if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, EFUSE_OP_DONE_LEN)) { - succeed = true; - break; - } - } - if (!succeed) { - FXGMAC_PR("Fail to loading efuse, ctrl_1 0x%08x\n", reg_val); - } - return succeed; -} - -bool fxgmac_efuse_read_data(struct fxgmac_pdata* pdata, u32 offset, u32* value) -{ - bool succeed = false; - unsigned int wait; - u32 reg_val = 0; - - //if (reg >= EFUSE_REGION_A_B_LENGTH) { - // FXGMAC_PR("Read addr out of range %d", reg); - // return succeed; - //} - - if (value) { - *value = 0; - } - - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_ADDR_POS, EFUSE_OP_ADDR_LEN, offset); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, EFUSE_OP_START_LEN, 1); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, EFUSE_OP_MODE_LEN, EFUSE_OP_MODE_ROW_READ); - writereg(pdata->pAdapter, reg_val, pdata->base_mem + EFUSE_OP_CTRL_0); - wait = 1000; - while (wait--) { - usleep_range_ex(pdata->pAdapter, 20, 50); - reg_val = readreg(pdata->pAdapter, pdata->base_mem + EFUSE_OP_CTRL_1); - if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, EFUSE_OP_DONE_LEN)) { - succeed = true; - break; - } - } - - if (succeed) { - if (value) { - *value = FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_RD_DATA_POS, EFUSE_OP_RD_DATA_LEN); - } - } - else { - FXGMAC_PR("Fail to reading efuse Byte%d\n", offset); - } - - return succeed; -} - -bool fxgmac_efuse_write_oob(struct fxgmac_pdata* pdata) -{ - bool succeed = false; - unsigned int wait; - u32 reg_val, value; - - if (!fxgmac_efuse_read_data(pdata, EFUSE_OOB_ADDR, ®_val)) { - return succeed; - } - - if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OOB_POS, EFUSE_OOB_LEN)) { - FXGMAC_PR("OOB Ctrl bit already exists"); - return true; - } - - value = 0; - value = FXGMAC_SET_REG_BITS(value, EFUSE_OOB_POS, EFUSE_OOB_LEN, 1); - - reg_val = 0; - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_ADDR_POS, EFUSE_OP_ADDR_LEN, EFUSE_OOB_ADDR); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_WR_DATA_POS, EFUSE_OP_WR_DATA_LEN, value & 0xFF); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, EFUSE_OP_START_LEN, 1); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, EFUSE_OP_MODE_LEN, EFUSE_OP_MODE_ROW_WRITE); - writereg(pdata->pAdapter, reg_val, pdata->base_mem + EFUSE_OP_CTRL_0); - - wait = 1000; - while (wait--) { - usleep_range_ex(pdata->pAdapter, 20, 50); - reg_val = readreg(pdata->pAdapter, pdata->base_mem + EFUSE_OP_CTRL_1); - if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, EFUSE_OP_DONE_LEN)) { - succeed = true; - break; - } - } - - if (!succeed) { - FXGMAC_PR("Fail to writing efuse Byte OOB"); - } - - return succeed; -} - -bool fxgmac_efuse_write_led(struct fxgmac_pdata* pdata, u32 value) -{ - bool succeed = false; - unsigned int wait; - u32 reg_val; - - if (!fxgmac_efuse_read_data(pdata, EFUSE_LED_ADDR, ®_val)) { - return succeed; - } - - if (reg_val == value) { - FXGMAC_PR("Led Ctrl option already exists"); - return true; - } - - reg_val = 0; - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_ADDR_POS, EFUSE_OP_ADDR_LEN, EFUSE_LED_ADDR); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_WR_DATA_POS, EFUSE_OP_WR_DATA_LEN, value & 0xFF); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, EFUSE_OP_START_LEN, 1); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, EFUSE_OP_MODE_LEN, EFUSE_OP_MODE_ROW_WRITE); - writereg(pdata->pAdapter, reg_val, pdata->base_mem + EFUSE_OP_CTRL_0); - - wait = 1000; - while (wait--) { - usleep_range_ex(pdata->pAdapter, 20, 50); - reg_val = readreg(pdata->pAdapter, pdata->base_mem + EFUSE_OP_CTRL_1); - if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, EFUSE_OP_DONE_LEN)) { - succeed = true; - break; - } - } - - if (!succeed) { - FXGMAC_PR("Fail to writing efuse Byte LED"); - } - - return succeed; -} - -bool fxgmac_efuse_write_data(struct fxgmac_pdata* pdata, u32 offset, u32 value) -{ - bool succeed = false; - unsigned int wait; - u32 reg_val; - - if (!fxgmac_efuse_read_data(pdata, offset, ®_val)) { - return succeed; - } - - if (reg_val == value) { - FXGMAC_PR("offset 0x%x already exists", offset); - return true; - } - - reg_val = 0; - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_ADDR_POS, EFUSE_OP_ADDR_LEN, offset & 0xFF); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_WR_DATA_POS, EFUSE_OP_WR_DATA_LEN, value & 0xFF); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, EFUSE_OP_START_LEN, 1); - reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, EFUSE_OP_MODE_LEN, EFUSE_OP_MODE_ROW_WRITE); - writereg(pdata->pAdapter, reg_val, pdata->base_mem + EFUSE_OP_CTRL_0); - - wait = 1000; - while (wait--) { - usleep_range_ex(pdata->pAdapter, 20, 50); - reg_val = readreg(pdata->pAdapter, pdata->base_mem + EFUSE_OP_CTRL_1); - if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, EFUSE_OP_DONE_LEN)) { - succeed = true; - break; - } - } - - if (!succeed) { - FXGMAC_PR("Fail to writing efuse 0x%x Byte LED", offset); - } - - return succeed; -} - -static void fxgmac_read_led_efuse_config(struct fxgmac_pdata* pdata, struct led_setting* pfirst, struct led_setting* psecond) -{ - u32 val_high = 0, val_low = 0; - - //read first area - fxgmac_efuse_read_data(pdata, EFUSE_FISRT_UPDATE_ADDR, &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 1), &val_low); - pfirst->disable_led_setting[4] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 2), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 3), &val_low); - pfirst->disable_led_setting[3] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 4), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 5), &val_low); - pfirst->disable_led_setting[2] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 6), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 7), &val_low); - pfirst->disable_led_setting[1] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 8), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 9), &val_low); - pfirst->disable_led_setting[0] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 10), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 11), &val_low); - pfirst->s5_led_setting[4] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 12), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 13), &val_low); - pfirst->s5_led_setting[3] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 14), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 15), &val_low); - pfirst->s5_led_setting[2] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 16), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 17), &val_low); - pfirst->s5_led_setting[1] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 18), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 19), &val_low); - pfirst->s5_led_setting[0] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 20), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 21), &val_low); - pfirst->s3_led_setting[4] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 22), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 23), &val_low); - pfirst->s3_led_setting[3] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 24), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 25), &val_low); - pfirst->s3_led_setting[2] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 26), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 27), &val_low); - pfirst->s3_led_setting[1] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 28), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 29), &val_low); - pfirst->s3_led_setting[0] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 30), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 31), &val_low); - pfirst->s0_led_setting[4] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 32), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 33), &val_low); - pfirst->s0_led_setting[3] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 34), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 35), &val_low); - pfirst->s0_led_setting[2] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 36), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 37), &val_low); - pfirst->s0_led_setting[1] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 38), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 39), &val_low); - pfirst->s0_led_setting[0] = ((val_high << 8) + val_low); - - //read second area - fxgmac_efuse_read_data(pdata, EFUSE_SECOND_UPDATE_ADDR, &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 1), &val_low); - psecond->disable_led_setting[4] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 2), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 3), &val_low); - psecond->disable_led_setting[3] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 4), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 5), &val_low); - psecond->disable_led_setting[2] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 6), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 7), &val_low); - psecond->disable_led_setting[1] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 8), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 9), &val_low); - psecond->disable_led_setting[0] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 10), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 11), &val_low); - psecond->s5_led_setting[4] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 12), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 13), &val_low); - psecond->s5_led_setting[3] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 14), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 15), &val_low); - psecond->s5_led_setting[2] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 16), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 17), &val_low); - psecond->s5_led_setting[1] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 18), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 19), &val_low); - psecond->s5_led_setting[0] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 20), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 21), &val_low); - psecond->s3_led_setting[4] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 22), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 23), &val_low); - psecond->s3_led_setting[3] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 24), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 25), &val_low); - psecond->s3_led_setting[2] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 26), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 27), &val_low); - psecond->s3_led_setting[1] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 28), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 29), &val_low); - psecond->s3_led_setting[0] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 30), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 31), &val_low); - psecond->s0_led_setting[4] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 32), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 33), &val_low); - psecond->s0_led_setting[3] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 34), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 35), &val_low); - psecond->s0_led_setting[2] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 36), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 37), &val_low); - psecond->s0_led_setting[1] = ((val_high << 8) + val_low); - - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 38), &val_high); - fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 39), &val_low); - psecond->s0_led_setting[0] = ((val_high << 8) + val_low); -} - -bool fxgmac_write_led_setting_to_efuse(struct fxgmac_pdata* pdata) -{ - struct led_setting led_config_first; - struct led_setting led_config_second; - bool bfirstflag = false, bsecondflag = false; - bool bsucceed = false; - - fxgmac_read_led_efuse_config(pdata, &led_config_first, &led_config_second); - - if (0x00 == led_config_first.s0_led_setting[0] && 0x00 == led_config_first.s0_led_setting[1] && 0x00 == led_config_first.s0_led_setting[2] && 0x00 == led_config_first.s0_led_setting[3] && 0x00 == led_config_first.s0_led_setting[4] - && 0x00 == led_config_first.s3_led_setting[0] && 0x00 == led_config_first.s3_led_setting[1] && 0x00 == led_config_first.s3_led_setting[2] && 0x00 == led_config_first.s3_led_setting[3] && 0x00 == led_config_first.s3_led_setting[4] - && 0x00 == led_config_first.s5_led_setting[0] && 0x00 == led_config_first.s5_led_setting[1] && 0x00 == led_config_first.s5_led_setting[2] && 0x00 == led_config_first.s5_led_setting[3] && 0x00 == led_config_first.s5_led_setting[4] - && 0x00 == led_config_first.disable_led_setting[0] && 0x00 == led_config_first.disable_led_setting[1] && 0x00 == led_config_first.disable_led_setting[2] && 0x00 == led_config_first.disable_led_setting[3] && 0x00 == led_config_first.disable_led_setting[4] - ) { - bfirstflag = true; - } - - if (0x00 == led_config_second.s0_led_setting[0] && 0x00 == led_config_second.s0_led_setting[1] && 0x00 == led_config_second.s0_led_setting[2] && 0x00 == led_config_second.s0_led_setting[3] && 0x00 == led_config_second.s0_led_setting[4] - && 0x00 == led_config_second.s3_led_setting[0] && 0x00 == led_config_second.s3_led_setting[1] && 0x00 == led_config_second.s3_led_setting[2] && 0x00 == led_config_second.s3_led_setting[3] && 0x00 == led_config_second.s3_led_setting[4] - && 0x00 == led_config_second.s5_led_setting[0] && 0x00 == led_config_second.s5_led_setting[1] && 0x00 == led_config_second.s5_led_setting[2] && 0x00 == led_config_second.s5_led_setting[3] && 0x00 == led_config_second.s5_led_setting[4] - && 0x00 == led_config_second.disable_led_setting[0] && 0x00 == led_config_second.disable_led_setting[1] && 0x00 == led_config_second.disable_led_setting[2] && 0x00 == led_config_second.disable_led_setting[3] && 0x00 == led_config_second.disable_led_setting[4] - ) { - bsecondflag = true; - } - -#ifndef LINUX - DbgPrintF(MP_TRACE, "%s s0 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x", __FUNCTION__, pdata->ledconfig.s0_led_setting[0], pdata->ledconfig.s0_led_setting[1], pdata->ledconfig.s0_led_setting[2], pdata->ledconfig.s0_led_setting[3], pdata->ledconfig.s0_led_setting[4]); - DbgPrintF(MP_TRACE, "%s s3 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x", __FUNCTION__, pdata->ledconfig.s3_led_setting[0], pdata->ledconfig.s3_led_setting[1], pdata->ledconfig.s3_led_setting[2], pdata->ledconfig.s3_led_setting[3], pdata->ledconfig.s3_led_setting[4]); - DbgPrintF(MP_TRACE, "%s s5 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x", __FUNCTION__, pdata->ledconfig.s5_led_setting[0], pdata->ledconfig.s5_led_setting[1], pdata->ledconfig.s5_led_setting[2], pdata->ledconfig.s5_led_setting[3], pdata->ledconfig.s5_led_setting[4]); - DbgPrintF(MP_TRACE, "%s disable 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x", __FUNCTION__, pdata->ledconfig.disable_led_setting[0], pdata->ledconfig.disable_led_setting[1], pdata->ledconfig.disable_led_setting[2], pdata->ledconfig.disable_led_setting[3], pdata->ledconfig.disable_led_setting[4]); -#endif - - if (bfirstflag && bsecondflag) { - //update first area - fxgmac_efuse_write_data(pdata, EFUSE_FISRT_UPDATE_ADDR, (pdata->ledconfig.disable_led_setting[4]>>8)&0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 1), pdata->ledconfig.disable_led_setting[4]); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 2), (pdata->ledconfig.disable_led_setting[3] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 3), pdata->ledconfig.disable_led_setting[3]); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 4), (pdata->ledconfig.disable_led_setting[2] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 5), pdata->ledconfig.disable_led_setting[2]); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 6), (pdata->ledconfig.disable_led_setting[1] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 7), pdata->ledconfig.disable_led_setting[1]); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 8), (pdata->ledconfig.disable_led_setting[0] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 9), pdata->ledconfig.disable_led_setting[0]); - - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 10), (pdata->ledconfig.s5_led_setting[4] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 11), pdata->ledconfig.s5_led_setting[4]); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 12), (pdata->ledconfig.s5_led_setting[3] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 13), pdata->ledconfig.s5_led_setting[3]); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 14), (pdata->ledconfig.s5_led_setting[2] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 15), pdata->ledconfig.s5_led_setting[2]); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 16), (pdata->ledconfig.s5_led_setting[1] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 17), pdata->ledconfig.s5_led_setting[1]); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 18), (pdata->ledconfig.s5_led_setting[0] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 19), pdata->ledconfig.s5_led_setting[0]); - - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 20), (pdata->ledconfig.s3_led_setting[4] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 21), pdata->ledconfig.s3_led_setting[4]); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 22), (pdata->ledconfig.s3_led_setting[3] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 23), pdata->ledconfig.s3_led_setting[3]); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 24), (pdata->ledconfig.s3_led_setting[2] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 25), pdata->ledconfig.s3_led_setting[2]); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 26), (pdata->ledconfig.s3_led_setting[1] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 27), pdata->ledconfig.s3_led_setting[1]); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 28), (pdata->ledconfig.s3_led_setting[0] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 29), pdata->ledconfig.s3_led_setting[0]); - - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 30), (pdata->ledconfig.s0_led_setting[4] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 31), pdata->ledconfig.s0_led_setting[4]); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 32), (pdata->ledconfig.s0_led_setting[3] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 33), pdata->ledconfig.s0_led_setting[3]); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 34), (pdata->ledconfig.s0_led_setting[2] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 35), pdata->ledconfig.s0_led_setting[2]); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 36), (pdata->ledconfig.s0_led_setting[1] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 37), pdata->ledconfig.s0_led_setting[1]); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 38), (pdata->ledconfig.s0_led_setting[0] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 39), pdata->ledconfig.s0_led_setting[0]); - - bsucceed = true; - } - else if (!bfirstflag && bsecondflag) { - //update second area - fxgmac_efuse_write_data(pdata, EFUSE_SECOND_UPDATE_ADDR, (pdata->ledconfig.disable_led_setting[4] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 1), pdata->ledconfig.disable_led_setting[4]); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 2), (pdata->ledconfig.disable_led_setting[3] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 3), pdata->ledconfig.disable_led_setting[3]); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 4), (pdata->ledconfig.disable_led_setting[2] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 5), pdata->ledconfig.disable_led_setting[2]); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 6), (pdata->ledconfig.disable_led_setting[1] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 7), pdata->ledconfig.disable_led_setting[1]); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 8), (pdata->ledconfig.disable_led_setting[0] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 9), pdata->ledconfig.disable_led_setting[0]); - - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 10), (pdata->ledconfig.s5_led_setting[4] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 11), pdata->ledconfig.s5_led_setting[4]); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 12), (pdata->ledconfig.s5_led_setting[3] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 13), pdata->ledconfig.s5_led_setting[3]); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 14), (pdata->ledconfig.s5_led_setting[2] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 15), pdata->ledconfig.s5_led_setting[2]); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 16), (pdata->ledconfig.s5_led_setting[1] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 17), pdata->ledconfig.s5_led_setting[1]); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 18), (pdata->ledconfig.s5_led_setting[0] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 19), pdata->ledconfig.s5_led_setting[0]); - - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 20), (pdata->ledconfig.s3_led_setting[4] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 21), pdata->ledconfig.s3_led_setting[4]); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 22), (pdata->ledconfig.s3_led_setting[3] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 23), pdata->ledconfig.s3_led_setting[3]); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 24), (pdata->ledconfig.s3_led_setting[2] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 25), pdata->ledconfig.s3_led_setting[2]); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 26), (pdata->ledconfig.s3_led_setting[1] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 27), pdata->ledconfig.s3_led_setting[1]); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 28), (pdata->ledconfig.s3_led_setting[0] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 29), pdata->ledconfig.s3_led_setting[0]); - - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 30), (pdata->ledconfig.s0_led_setting[4] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 31), pdata->ledconfig.s0_led_setting[4]); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 32), (pdata->ledconfig.s0_led_setting[3] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 33), pdata->ledconfig.s0_led_setting[3]); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 34), (pdata->ledconfig.s0_led_setting[2] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 35), pdata->ledconfig.s0_led_setting[2]); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 36), (pdata->ledconfig.s0_led_setting[1] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 37), pdata->ledconfig.s0_led_setting[1]); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 38), (pdata->ledconfig.s0_led_setting[0] >> 8) & 0xFF); - fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 39), pdata->ledconfig.s0_led_setting[0]); - - bsucceed = true; - } - - return bsucceed; -} - -bool fxgmac_read_led_setting_from_efuse(struct fxgmac_pdata* pdata) -{ - struct led_setting led_config_first; - struct led_setting led_config_second; - bool bfirstflag = false, bsecondflag = false; - bool bsucceed = false; - - fxgmac_read_led_efuse_config(pdata, &led_config_first, &led_config_second); - - if (0x00 == led_config_first.s0_led_setting[0] && 0x00 == led_config_first.s0_led_setting[1] && 0x00 == led_config_first.s0_led_setting[2] && 0x00 == led_config_first.s0_led_setting[3] && 0x00 == led_config_first.s0_led_setting[4] - && 0x00 == led_config_first.s3_led_setting[0] && 0x00 == led_config_first.s3_led_setting[1] && 0x00 == led_config_first.s3_led_setting[2] && 0x00 == led_config_first.s3_led_setting[3] && 0x00 == led_config_first.s3_led_setting[4] - && 0x00 == led_config_first.s5_led_setting[0] && 0x00 == led_config_first.s5_led_setting[1] && 0x00 == led_config_first.s5_led_setting[2] && 0x00 == led_config_first.s5_led_setting[3] && 0x00 == led_config_first.s5_led_setting[4] - && 0x00 == led_config_first.disable_led_setting[0] && 0x00 == led_config_first.disable_led_setting[1] && 0x00 == led_config_first.disable_led_setting[2] && 0x00 == led_config_first.disable_led_setting[3] && 0x00 == led_config_first.disable_led_setting[4] - ) { - bfirstflag = true; - } - - if (0x00 == led_config_second.s0_led_setting[0] && 0x00 == led_config_second.s0_led_setting[1] && 0x00 == led_config_second.s0_led_setting[2] && 0x00 == led_config_second.s0_led_setting[3] && 0x00 == led_config_second.s0_led_setting[4] - && 0x00 == led_config_second.s3_led_setting[0] && 0x00 == led_config_second.s3_led_setting[1] && 0x00 == led_config_second.s3_led_setting[2] && 0x00 == led_config_second.s3_led_setting[3] && 0x00 == led_config_second.s3_led_setting[4] - && 0x00 == led_config_second.s5_led_setting[0] && 0x00 == led_config_second.s5_led_setting[1] && 0x00 == led_config_second.s5_led_setting[2] && 0x00 == led_config_second.s5_led_setting[3] && 0x00 == led_config_second.s5_led_setting[4] - && 0x00 == led_config_second.disable_led_setting[0] && 0x00 == led_config_second.disable_led_setting[1] && 0x00 == led_config_second.disable_led_setting[2] && 0x00 == led_config_second.disable_led_setting[3] && 0x00 == led_config_second.disable_led_setting[4] - ) { - bsecondflag = true; - } - - if (!bfirstflag && bsecondflag) { - //read first area - memcpy(&pdata->led, &led_config_first, sizeof(struct led_setting)); - bsucceed = true; - } - else if (!bfirstflag && !bsecondflag) { - //read second area - memcpy(&pdata->led, &led_config_second, sizeof(struct led_setting)); - bsucceed = true; - } - -#ifndef LINUX - DbgPrintF(MP_TRACE, "%s s0 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x", __FUNCTION__, pdata->led.s0_led_setting[0], pdata->led.s0_led_setting[1], pdata->led.s0_led_setting[2], pdata->led.s0_led_setting[3], pdata->led.s0_led_setting[4]); - DbgPrintF(MP_TRACE, "%s s3 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x", __FUNCTION__, pdata->led.s3_led_setting[0], pdata->led.s3_led_setting[1], pdata->led.s3_led_setting[2], pdata->led.s3_led_setting[3], pdata->led.s3_led_setting[4]); - DbgPrintF(MP_TRACE, "%s s5 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x", __FUNCTION__, pdata->led.s5_led_setting[0], pdata->led.s5_led_setting[1], pdata->led.s5_led_setting[2], pdata->led.s5_led_setting[3], pdata->led.s5_led_setting[4]); - DbgPrintF(MP_TRACE, "%s disable 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x", __FUNCTION__, pdata->led.disable_led_setting[0], pdata->led.disable_led_setting[1], pdata->led.disable_led_setting[2], pdata->led.disable_led_setting[3], pdata->led.disable_led_setting[4]); -#endif - - return bsucceed; -} \ No newline at end of file diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.h b/drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.h deleted file mode 100644 index 7832028e51684..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.h +++ /dev/null @@ -1,33 +0,0 @@ - -/*++ - -Copyright (c) 2021 Motorcomm Corporation. -Confidential and Proprietary. All rights reserved. - -This is Motorcomm Corporation NIC driver relevant files. Please don't copy, modify, -distribute without commercial permission. - ---*/ - -#ifndef __FUXI_EFUSE_H__ -#define __FUXI_EFUSE_H__ - - -bool fxgmac_read_patch_from_efuse(struct fxgmac_pdata* pdata, u32 offset, u32* value); /* read patch per register offset. */ -bool fxgmac_read_patch_from_efuse_per_index(struct fxgmac_pdata* pdata, u8 index, u32* offset, u32* value); /* read patch per 0-based index. */ -bool fxgmac_write_patch_to_efuse(struct fxgmac_pdata* pdata, u32 offset, u32 value); -bool fxgmac_write_patch_to_efuse_per_index(struct fxgmac_pdata* pdata, u8 index, u32 offset, u32 value); -bool fxgmac_read_mac_subsys_from_efuse(struct fxgmac_pdata* pdata, u8* mac_addr, u32* subsys, u32* revid); -bool fxgmac_write_mac_subsys_to_efuse(struct fxgmac_pdata* pdata, u8* mac_addr, u32* subsys, u32* revid); -bool fxgmac_write_mac_addr_to_efuse(struct fxgmac_pdata* pdata, u8* mac_addr); -bool fxgmac_read_subsys_from_efuse(struct fxgmac_pdata* pdata, u32* subsys, u32* revid); -bool fxgmac_write_subsys_to_efuse(struct fxgmac_pdata* pdata, u32* subsys, u32* revid); -bool fxgmac_efuse_load(struct fxgmac_pdata* pdata); -bool fxgmac_efuse_read_data(struct fxgmac_pdata* pdata, u32 offset, u32* value); -bool fxgmac_efuse_write_data(struct fxgmac_pdata* pdata, u32 offset, u32 value); -bool fxgmac_efuse_write_oob(struct fxgmac_pdata* pdata); -bool fxgmac_efuse_write_led(struct fxgmac_pdata* pdata, u32 value); -bool fxgmac_read_led_setting_from_efuse(struct fxgmac_pdata* pdata); -bool fxgmac_write_led_setting_to_efuse(struct fxgmac_pdata* pdata); - -#endif // __FUXI_EFUSE_H__ \ No newline at end of file diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-common.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-common.c deleted file mode 100644 index b62e05232be53..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-common.c +++ /dev/null @@ -1,1012 +0,0 @@ -/*++ - -Copyright (c) 2021 Motor-comm Corporation. -Confidential and Proprietary. All rights reserved. - -This is Motor-comm Corporation NIC driver relevant files. Please don't copy, modify, -distribute without commercial permission. - ---*/ - -#include -#include - -#include "fuxi-os.h" -#include "fuxi-gmac.h" -#include "fuxi-gmac-reg.h" - -MODULE_LICENSE("Dual BSD/GPL"); - -static int debug = 16; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "FUXI ethernet debug level (0=none,...,16=all)"); - -static unsigned char dev_addr[6] = {0, 0x55, 0x7b, 0xb5, 0x7d, 0xf7}; - -static void fxgmac_read_mac_addr(struct fxgmac_pdata *pdata) -{ - struct net_device *netdev = pdata->netdev; - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - - DPRINTK("read mac from eFuse\n"); - - // if efuse have mac addr,use it.if not,use static mac address. - hw_ops->read_mac_subsys_from_efuse(pdata, pdata->mac_addr, NULL, NULL); - if (ETH_IS_ZEROADDRESS(pdata->mac_addr)) { - /* Currently it uses a static mac address for test */ - memcpy(pdata->mac_addr, dev_addr, netdev->addr_len); - } -} - -static void fxgmac_default_config(struct fxgmac_pdata *pdata) -{ - pdata->tx_osp_mode = DMA_OSP_ENABLE; - pdata->tx_sf_mode = MTL_TSF_ENABLE; - pdata->rx_sf_mode = MTL_RSF_DISABLE;//MTL_RSF_DISABLE 20210514 - pdata->pblx8 = DMA_PBL_X8_ENABLE;//DMA_PBL_X8_ENABLE 20210514 - pdata->tx_pbl = DMA_PBL_32; - pdata->rx_pbl = DMA_PBL_32;//DMA_PBL_32 20210514 - pdata->tx_threshold = MTL_TX_THRESHOLD_128; - pdata->rx_threshold = MTL_RX_THRESHOLD_128; -#if 1 - pdata->tx_pause = 1; - pdata->rx_pause = 1; -#else - pdata->tx_pause = 0; - pdata->rx_pause = 0; -#endif -#if FXGMAC_RSS_FEATURE_ENABLED - pdata->rss = 1; -#else - pdata->rss = 0; -#endif - // open interrupt moderation default - pdata->intr_mod = 1; - pdata->crc_check = 1; - - //yzhang, set based on phy status. pdata->phy_speed = SPEED_1000; - pdata->sysclk_rate = FXGMAC_SYSCLOCK; - pdata->phy_autoeng = AUTONEG_ENABLE; // default to autoneg - pdata->phy_duplex = DUPLEX_FULL; - pdata->expansion.phy_link = false; - pdata->phy_speed = SPEED_1000; - - // default to magic - pdata->expansion.wol = WAKE_MAGIC; - - strscpy(pdata->drv_name, FXGMAC_DRV_NAME, sizeof(pdata->drv_name)); - strscpy(pdata->drv_ver, FXGMAC_DRV_VERSION, sizeof(pdata->drv_ver)); - - printk("FXGMAC_DRV_NAME:%s, FXGMAC_DRV_VERSION:%s\n", FXGMAC_DRV_NAME, FXGMAC_DRV_VERSION); -} - -static void fxgmac_init_all_ops(struct fxgmac_pdata *pdata) -{ - fxgmac_init_desc_ops(&pdata->desc_ops); - fxgmac_init_hw_ops(&pdata->hw_ops); - - DPRINTK("register desc_ops and hw ops\n"); -} - -int fxgmac_init(struct fxgmac_pdata *pdata, bool save_private_reg) -{ - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - struct net_device *netdev = pdata->netdev; - unsigned int i, dma_width; - int ret; - - /* Set all the function pointers */ - fxgmac_init_all_ops(pdata); - - /* Set default configuration data */ - fxgmac_default_config(pdata); - - /* Set irq, base_addr, MAC address, */ - netdev->irq = pdata->dev_irq; - netdev->base_addr = (unsigned long)pdata->base_mem; - fxgmac_read_mac_addr(pdata); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)) - eth_hw_addr_set(netdev, pdata->mac_addr); -#else - memcpy(netdev->dev_addr, pdata->mac_addr, netdev->addr_len); -#endif - - if (save_private_reg) { - hw_ops->save_nonstick_reg(pdata); - } - - // reset here to get hw features correctly - hw_ops->exit(pdata); - - /* Populate the hardware features */ - fxgmac_get_all_hw_features(pdata); - fxgmac_print_all_hw_features(pdata); - - /* TODO: Set the PHY mode to XLGMII */ - - /* Set the DMA mask */ -#ifdef CONFIG_ARM64 - dma_width = FUXI_DMA_BIT_MASK; -#else - dma_width = pdata->hw_feat.dma_width; -#endif - ret = dma_set_mask_and_coherent(pdata->dev, - DMA_BIT_MASK(dma_width)); - if (ret) { - dev_err(pdata->dev, "dma_set_mask_and_coherent failed\n"); - return ret; - } - - /* Channel and ring params initializtion - * pdata->channel_count; - * pdata->tx_ring_count; - * pdata->rx_ring_count; - * pdata->tx_desc_count; - * pdata->rx_desc_count; - */ - BUILD_BUG_ON_NOT_POWER_OF_2(FXGMAC_TX_DESC_CNT); - pdata->tx_desc_count = FXGMAC_TX_DESC_CNT; - if (pdata->tx_desc_count & (pdata->tx_desc_count - 1)) { - dev_err(pdata->dev, "tx descriptor count (%d) is not valid\n", - pdata->tx_desc_count); - ret = -EINVAL; - return ret; - } - BUILD_BUG_ON_NOT_POWER_OF_2(FXGMAC_RX_DESC_CNT); - pdata->rx_desc_count = FXGMAC_RX_DESC_CNT; - if (pdata->rx_desc_count & (pdata->rx_desc_count - 1)) { - dev_err(pdata->dev, "rx descriptor count (%d) is not valid\n", - pdata->rx_desc_count); - ret = -EINVAL; - return ret; - } - - pdata->tx_ring_count = min_t(unsigned int, num_online_cpus(), - pdata->hw_feat.tx_ch_cnt); - pdata->tx_ring_count = min_t(unsigned int, pdata->tx_ring_count, - pdata->hw_feat.tx_q_cnt); - pdata->tx_q_count = pdata->tx_ring_count; - -#if !(FXGMAC_NUM_OF_TX_Q_USED) - ret = netif_set_real_num_tx_queues(netdev, pdata->tx_q_count); -#else - ret = netif_set_real_num_tx_queues(netdev, FXGMAC_NUM_OF_TX_Q_USED /*pdata->tx_q_count*/); -#endif - - DPRINTK("num_online_cpus:%u, tx_ch_cnt:%u, tx_q_cnt:%u, tx_ring_count:%u\n", - num_online_cpus(), pdata->hw_feat.tx_ch_cnt, pdata->hw_feat.tx_q_cnt, - pdata->tx_ring_count); - - if (ret) { - dev_err(pdata->dev, "error setting real tx queue count\n"); - return ret; - } -#if 0 - DPRINTK("num_online_cpus:%u, tx_ch_cnt:%u, tx_q_cnt:%u, tx_ring_count:%u\n", - num_online_cpus(), pdata->hw_feat.tx_ch_cnt, pdata->hw_feat.tx_q_cnt, - pdata->tx_ring_count); -#endif - - pdata->rx_ring_count = min_t(unsigned int, - netif_get_num_default_rss_queues(), - pdata->hw_feat.rx_ch_cnt); -#ifdef FXGMAC_ONE_CHANNEL - pdata->rx_ring_count = 1; - pdata->hw_feat.rx_q_cnt = pdata->rx_ring_count; -#else - pdata->rx_ring_count = min_t(unsigned int, pdata->rx_ring_count, - pdata->hw_feat.rx_q_cnt); -#endif - pdata->rx_q_count = pdata->rx_ring_count; - ret = netif_set_real_num_rx_queues(netdev, pdata->rx_q_count); - if (ret) { - dev_err(pdata->dev, "error setting real rx queue count\n"); - return ret; - } - - pdata->channel_count = - max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count); - - DPRINTK("default rss queues:%u, rx_ch_cnt:%u, rx_q_cnt:%u, rx_ring_count:%u\n", - netif_get_num_default_rss_queues(), pdata->hw_feat.rx_ch_cnt, pdata->hw_feat.rx_q_cnt, - pdata->rx_ring_count); - DPRINTK("channel_count:%u, netdev tx channel_num=%u\n", pdata->channel_count, netdev->num_tx_queues); - - /* Initialize RSS hash key and lookup table */ -#if FXGMAC_RSS_HASH_KEY_LINUX - netdev_rss_key_fill(pdata->rss_key, sizeof(pdata->rss_key)); -#else - //this is for test only. HW does not want to change Hash key, 20210617 - hw_ops->get_rss_hash_key(pdata, (u8 *)pdata->rss_key); -#endif - -#if FXGMAC_MSIX_CH0RXDIS_EN - for (i = 0; i < FXGMAC_RSS_MAX_TABLE_SIZE; i++) { - pdata->rss_table[i] = FXGMAC_SET_REG_BITS( - pdata->rss_table[i], - MAC_RSSDR_DMCH_POS, - MAC_RSSDR_DMCH_LEN, - (i % 3) + 1); //eliminate ch0 - } -#else - for (i = 0; i < FXGMAC_RSS_MAX_TABLE_SIZE; i++) { - pdata->rss_table[i] = FXGMAC_SET_REG_BITS( - pdata->rss_table[i], - MAC_RSSDR_DMCH_POS, - MAC_RSSDR_DMCH_LEN, - i % pdata->rx_ring_count); //note, rx_ring_count should be equal to IRQ requsted for MSIx, 4 - } -#endif - - pdata->rss_options = FXGMAC_SET_REG_BITS( - pdata->rss_options, - MAC_RSSCR_IP4TE_POS, - MAC_RSSCR_IP4TE_LEN, 1); - pdata->rss_options = FXGMAC_SET_REG_BITS( - pdata->rss_options, - MAC_RSSCR_TCP4TE_POS, - MAC_RSSCR_TCP4TE_LEN, 1); - pdata->rss_options = FXGMAC_SET_REG_BITS( - pdata->rss_options, - MAC_RSSCR_UDP4TE_POS, - MAC_RSSCR_UDP4TE_LEN, 1); - - /* config MTU supported, 20210726 */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) - netdev->min_mtu = ETH_MIN_MTU; - netdev->max_mtu = FXGMAC_JUMBO_PACKET_MTU + (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN); -#endif - /* - netdev->extended->min_mtu = netdev->min_mtu; - netdev->extended->max_mtu = netdev->max_mtu; - */ - - DPRINTK("rss_options:0x%x\n", pdata->rss_options); - - /* Set device operations */ - netdev->netdev_ops = fxgmac_get_netdev_ops(); - netdev->ethtool_ops = fxgmac_get_ethtool_ops(); - - /* Set device features */ - if (pdata->hw_feat.tso) { - netdev->hw_features = NETIF_F_TSO; - netdev->hw_features |= NETIF_F_TSO6; - netdev->hw_features |= NETIF_F_SG; - netdev->hw_features |= NETIF_F_IP_CSUM; - netdev->hw_features |= NETIF_F_IPV6_CSUM; - } else if (pdata->hw_feat.tx_coe) { - netdev->hw_features = NETIF_F_IP_CSUM; - netdev->hw_features |= NETIF_F_IPV6_CSUM; - } - - if (pdata->hw_feat.rx_coe) { - netdev->hw_features |= NETIF_F_RXCSUM; - netdev->hw_features |= NETIF_F_GRO; - } - - if (pdata->hw_feat.rss) { - netdev->hw_features |= NETIF_F_RXHASH; //it is NETIF_F_RXHASH_BIT finally - } - - netdev->vlan_features |= netdev->hw_features; - - netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX; - pdata->vlan_strip = 1; - if (pdata->hw_feat.sa_vlan_ins) { - netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX; - } -#if FXGMAC_FILTER_SINGLE_VLAN_ENABLED - /* only can filter one vlan id */ - pdata->hw_feat.vlhash = 1 ; -#else - pdata->hw_feat.vlhash = 0 ; -#endif - - if (pdata->hw_feat.vlhash) { - netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER; - pdata->vlan_filter = 1; - } - - netdev->features |= netdev->hw_features; - pdata->expansion.netdev_features = netdev->features; - - netdev->priv_flags |= IFF_UNICAST_FLT; - - /* Use default watchdog timeout */ - netdev->watchdog_timeo = msecs_to_jiffies(5000);//refer to sunxi-gmac, 5s - netdev->gso_max_size = NIC_MAX_TCP_OFFLOAD_SIZE; - - /* Tx coalesce parameters initialization */ - pdata->tx_usecs = FXGMAC_INIT_DMA_TX_USECS; - pdata->tx_frames = FXGMAC_INIT_DMA_TX_FRAMES; - - /* Rx coalesce parameters initialization */ - pdata->rx_riwt = hw_ops->usec_to_riwt(pdata, FXGMAC_INIT_DMA_RX_USECS); - - pdata->rx_usecs = FXGMAC_INIT_DMA_RX_USECS; - pdata->rx_frames = FXGMAC_INIT_DMA_RX_FRAMES; - - DPRINTK("fxgmac_init callout,ok.\n"); - - return 0; -} - -static void fxgmac_init_interrupt_scheme(struct fxgmac_pdata *pdata) -{ -#ifdef CONFIG_PCI_MSI - int vectors, rc, i, req_vectors; - /* check cpu core number. - * since we have 4 channels, we must ensure the number of cpu core > 4 - * otherwise, just roll back to legacy - */ - vectors = num_online_cpus(); - DPRINTK("num of cpu=%d\n", vectors); - if(vectors >= FXGMAC_MAX_DMA_CHANNELS) { - // 0-3 for rx, 4 for tx, 5 for phy - req_vectors = FXGMAC_MSIX_INT_NUMS; - pdata->expansion.msix_entries = kcalloc(req_vectors, - sizeof(struct msix_entry), - GFP_KERNEL); - if (!pdata->expansion.msix_entries) { - DPRINTK("MSIx, kcalloc err for msix entries, rollback to MSI..\n"); - goto enable_msi_interrupt; - }else { - for (i = 0; i < req_vectors; i++) - pdata->expansion.msix_entries[i].entry = i; - - rc = pci_enable_msix_range(pdata->pdev, - pdata->expansion.msix_entries, - req_vectors, - req_vectors); - if (rc < 0) { - DPRINTK("enable MSIx failed,%d.\n", rc); - req_vectors = 0; //indicate failure - } else { - req_vectors = rc; - } - - if(req_vectors >= FXGMAC_MAX_DMA_CHANNELS_PLUS_1TX) { - DPRINTK("enable MSIx ok, cpu=%d,vectors=%d.\n", - vectors, req_vectors); - pdata->expansion.int_flags = FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_INTERRUPT_POS, - FXGMAC_FLAG_INTERRUPT_LEN, - FXGMAC_FLAG_MSIX_ENABLED); - pdata->per_channel_irq = 1; - pdata->expansion.phy_irq = - pdata->expansion.msix_entries[MSI_ID_PHY_OTHER].vector; - return; - }else if (req_vectors){ - DPRINTK("enable MSIx with only %d vector, while we need %d, rollback to MSI.\n", req_vectors, vectors); - //roll back to msi - pci_disable_msix(pdata->pdev); - kfree(pdata->expansion.msix_entries); - pdata->expansion.msix_entries = NULL; - req_vectors = 0; - }else { - DPRINTK("enable MSIx failure and clear msix entries.\n"); - //roll back to msi - kfree(pdata->expansion.msix_entries); - pdata->expansion.msix_entries = NULL; - req_vectors = 0; - } - } - } - -enable_msi_interrupt: - rc = pci_enable_msi(pdata->pdev); - if (rc < 0) { - pdata->expansion.int_flags = FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_INTERRUPT_POS, - FXGMAC_FLAG_INTERRUPT_LEN, - FXGMAC_FLAG_LEGACY_ENABLED); - DPRINTK("enable MSI failure, rollback to LEGACY.\n"); - } else { - pdata->expansion.int_flags = FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_INTERRUPT_POS, - FXGMAC_FLAG_INTERRUPT_LEN, - FXGMAC_FLAG_MSI_ENABLED); - pdata->dev_irq = pdata->pdev->irq; - DPRINTK("enable MSI ok, irq=%d.\n", pdata->pdev->irq); - } -#else - pdata = pdata; -#endif -} - -int fxgmac_drv_probe(struct device *dev, struct fxgmac_resources *res) -{ - struct fxgmac_pdata *pdata; - struct net_device *netdev; - int ret; - - netdev = alloc_etherdev_mq(sizeof(struct fxgmac_pdata), - FXGMAC_MAX_DMA_CHANNELS); - - if (!netdev) { - dev_err(dev, "alloc_etherdev failed\n"); - return -ENOMEM; - } - - SET_NETDEV_DEV(netdev, dev); - dev_set_drvdata(dev, netdev); - pdata = netdev_priv(netdev); - pdata->dev = dev; - pdata->pdev = to_pci_dev(dev); - pdata->netdev = netdev; - - pdata->dev_irq = res->irq; - - // default to legacy interrupt - pdata->expansion.int_flags = FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_INTERRUPT_POS, - FXGMAC_FLAG_INTERRUPT_LEN, - FXGMAC_FLAG_LEGACY_ENABLED); - pdata->expansion.phy_irq = pdata->dev_irq; - - fxgmac_init_interrupt_scheme(pdata); - - pdata->expansion.current_state = CURRENT_STATE_INIT; - - pdata->msg_enable = NETIF_MSG_DRV; - DPRINTK("netif msg_enable init to %08x\n", pdata->msg_enable); - - pdata->mac_regs = res->addr; - pdata->base_mem = res->addr; - pdata->mac_regs = pdata->mac_regs + FUXI_MAC_REGS_OFFSET; - - ret = fxgmac_init(pdata, true); - if (ret) { - dev_err(dev, "fxgmac init failed\n"); - goto err_free_netdev; - } - - pdata->hw_ops.read_led_config(pdata); - - netif_carrier_off(netdev); - ret = register_netdev(netdev); - if (ret) { - dev_err(dev, "net device registration failed\n"); - goto err_free_netdev; - } - if(netif_msg_drv(pdata)) DPRINTK("fxgamc_drv_prob callout, netdev num_tx_q=%u\n", netdev->num_tx_queues); - -#ifdef HAVE_FXGMAC_DEBUG_FS - fxgmac_dbg_init(pdata); - fxgmac_dbg_adapter_init(pdata); -#endif /* HAVE_FXGMAC_DEBUG_FS */ - - return 0; - -err_free_netdev: - free_netdev(netdev); - DPRINTK("fxgamc_drv_prob callout with err \n"); - - return ret; -} - -int fxgmac_drv_remove(struct device *dev) -{ - struct net_device *netdev = dev_get_drvdata(dev); - struct fxgmac_pdata * pdata = netdev_priv(netdev); - struct fxgmac_hw_ops* hw_ops = &pdata->hw_ops; - -#ifdef HAVE_FXGMAC_DEBUG_FS - fxgmac_dbg_adapter_exit(pdata); -#endif /*HAVE_FXGMAC_DEBUG_FS */ - hw_ops->led_under_shutdown(pdata); - - unregister_netdev(netdev); - free_netdev(netdev); - - return 0; -} - -void fxgmac_dump_tx_desc(struct fxgmac_pdata *pdata, - struct fxgmac_ring *ring, - unsigned int idx, - unsigned int count, - unsigned int flag) -{ - struct fxgmac_desc_data *desc_data; - struct fxgmac_dma_desc *dma_desc; - - while (count--) { - desc_data = FXGMAC_GET_DESC_DATA(ring, idx); - dma_desc = desc_data->dma_desc; - - netdev_dbg(pdata->netdev, "TX: dma_desc=%p, dma_desc_addr=%pad\n", - desc_data->dma_desc, &desc_data->dma_desc_addr); - netdev_dbg(pdata->netdev, - "TX_NORMAL_DESC[%d %s] = %08x:%08x:%08x:%08x\n", idx, - (flag == 1) ? "QUEUED FOR TX" : "TX BY DEVICE", - le32_to_cpu(dma_desc->desc0), - le32_to_cpu(dma_desc->desc1), - le32_to_cpu(dma_desc->desc2), - le32_to_cpu(dma_desc->desc3)); - - idx++; - } -} - -void fxgmac_dump_rx_desc(struct fxgmac_pdata *pdata, - struct fxgmac_ring *ring, - unsigned int idx) -{ - struct fxgmac_desc_data *desc_data; - struct fxgmac_dma_desc *dma_desc; - - desc_data = FXGMAC_GET_DESC_DATA(ring, idx); - dma_desc = desc_data->dma_desc; - - netdev_dbg(pdata->netdev, "RX: dma_desc=%p, dma_desc_addr=%pad\n", - desc_data->dma_desc, &desc_data->dma_desc_addr); - netdev_dbg(pdata->netdev, - "RX_NORMAL_DESC[%d RX BY DEVICE] = %08x:%08x:%08x:%08x\n", - idx, - le32_to_cpu(dma_desc->desc0), - le32_to_cpu(dma_desc->desc1), - le32_to_cpu(dma_desc->desc2), - le32_to_cpu(dma_desc->desc3)); -} - -void fxgmac_dbg_pkt(struct net_device *netdev, - struct sk_buff *skb, bool tx_rx) -{ - struct ethhdr *eth = (struct ethhdr *)skb->data; - unsigned char buffer[128]; - unsigned int i; - - netdev_dbg(netdev, "\n************** SKB dump ****************\n"); - - netdev_dbg(netdev, "%s packet of %d bytes\n", - (tx_rx ? "TX" : "RX"), skb->len); - - netdev_dbg(netdev, "Dst MAC addr: %pM\n", eth->h_dest); - netdev_dbg(netdev, "Src MAC addr: %pM\n", eth->h_source); - netdev_dbg(netdev, "Protocol: %#06hx\n", ntohs(eth->h_proto)); - - for (i = 0; i < skb->len; i += 32) { - unsigned int len = min(skb->len - i, 32U); - - hex_dump_to_buffer(&skb->data[i], len, 32, 1, - buffer, sizeof(buffer), false); - netdev_dbg(netdev, " %#06x: %s\n", i, buffer); - } - - netdev_dbg(netdev, "\n************** SKB dump ****************\n"); -} - -void fxgmac_print_pkt(struct net_device *netdev, - struct sk_buff *skb, bool tx_rx) -{ -#ifdef FXGMAC_DEBUG - struct ethhdr *eth = (struct ethhdr *)skb->data; -#endif - unsigned char buffer[128]; - unsigned int i; - - DPRINTK("\n************** SKB dump ****************\n"); - DPRINTK("%s packet of %d bytes\n", - (tx_rx ? "TX" : "RX"), skb->len); - -#ifdef FXGMAC_DEBUG - DPRINTK("Dst MAC addr: %pM\n", eth->h_dest); - DPRINTK("Src MAC addr: %pM\n", eth->h_source); - DPRINTK("Protocol: %#06hx\n", ntohs(eth->h_proto)); -#endif - for (i = 0; i < skb->len; i += 32) { - unsigned int len = min(skb->len - i, 32U); - - hex_dump_to_buffer(&skb->data[i], len, 32, 1, - buffer, sizeof(buffer), false); - DPRINTK(" %#06x: %s\n", i, buffer); - } - - DPRINTK("\n************** SKB dump ****************\n"); -} - -void fxgmac_get_all_hw_features(struct fxgmac_pdata *pdata) -{ - struct fxgmac_hw_features *hw_feat = &pdata->hw_feat; - unsigned int mac_hfr0, mac_hfr1, mac_hfr2, mac_hfr3; - - mac_hfr0 = readl(pdata->mac_regs + MAC_HWF0R); - mac_hfr1 = readl(pdata->mac_regs + MAC_HWF1R); - mac_hfr2 = readl(pdata->mac_regs + MAC_HWF2R); - mac_hfr3 = readl(pdata->mac_regs + MAC_HWF3R); - - memset(hw_feat, 0, sizeof(*hw_feat)); - - hw_feat->version = readl(pdata->mac_regs + MAC_VR); - if(netif_msg_drv(pdata)) DPRINTK ("get offset 0x110,ver=%#x\n", readl(pdata->mac_regs + 0x110)); - - /* Hardware feature register 0 */ - hw_feat->phyifsel = FXGMAC_GET_REG_BITS(mac_hfr0, - MAC_HWF0R_ACTPHYIFSEL_POS, - MAC_HWF0R_ACTPHYIFSEL_LEN); - hw_feat->vlhash = FXGMAC_GET_REG_BITS(mac_hfr0, - MAC_HWF0R_VLHASH_POS, - MAC_HWF0R_VLHASH_LEN); - hw_feat->sma = FXGMAC_GET_REG_BITS(mac_hfr0, - MAC_HWF0R_SMASEL_POS, - MAC_HWF0R_SMASEL_LEN); - hw_feat->rwk = FXGMAC_GET_REG_BITS(mac_hfr0, - MAC_HWF0R_RWKSEL_POS, - MAC_HWF0R_RWKSEL_LEN); - hw_feat->mgk = FXGMAC_GET_REG_BITS(mac_hfr0, - MAC_HWF0R_MGKSEL_POS, - MAC_HWF0R_MGKSEL_LEN); - hw_feat->mmc = FXGMAC_GET_REG_BITS(mac_hfr0, - MAC_HWF0R_MMCSEL_POS, - MAC_HWF0R_MMCSEL_LEN); - hw_feat->aoe = FXGMAC_GET_REG_BITS(mac_hfr0, - MAC_HWF0R_ARPOFFSEL_POS, - MAC_HWF0R_ARPOFFSEL_LEN); - hw_feat->ts = FXGMAC_GET_REG_BITS(mac_hfr0, - MAC_HWF0R_TSSEL_POS, - MAC_HWF0R_TSSEL_LEN); - hw_feat->eee = FXGMAC_GET_REG_BITS(mac_hfr0, - MAC_HWF0R_EEESEL_POS, - MAC_HWF0R_EEESEL_LEN); - hw_feat->tx_coe = FXGMAC_GET_REG_BITS(mac_hfr0, - MAC_HWF0R_TXCOESEL_POS, - MAC_HWF0R_TXCOESEL_LEN); - hw_feat->rx_coe = FXGMAC_GET_REG_BITS(mac_hfr0, - MAC_HWF0R_RXCOESEL_POS, - MAC_HWF0R_RXCOESEL_LEN); - hw_feat->addn_mac = FXGMAC_GET_REG_BITS(mac_hfr0, - MAC_HWF0R_ADDMACADRSEL_POS, - MAC_HWF0R_ADDMACADRSEL_LEN); - hw_feat->ts_src = FXGMAC_GET_REG_BITS(mac_hfr0, - MAC_HWF0R_TSSTSSEL_POS, - MAC_HWF0R_TSSTSSEL_LEN); - hw_feat->sa_vlan_ins = FXGMAC_GET_REG_BITS(mac_hfr0, - MAC_HWF0R_SAVLANINS_POS, - MAC_HWF0R_SAVLANINS_LEN); - - /* Hardware feature register 1 */ - hw_feat->rx_fifo_size = FXGMAC_GET_REG_BITS(mac_hfr1, - MAC_HWF1R_RXFIFOSIZE_POS, - MAC_HWF1R_RXFIFOSIZE_LEN); - hw_feat->tx_fifo_size = FXGMAC_GET_REG_BITS(mac_hfr1, - MAC_HWF1R_TXFIFOSIZE_POS, - MAC_HWF1R_TXFIFOSIZE_LEN); - hw_feat->adv_ts_hi = FXGMAC_GET_REG_BITS(mac_hfr1, - MAC_HWF1R_ADVTHWORD_POS, - MAC_HWF1R_ADVTHWORD_LEN); - hw_feat->dma_width = FXGMAC_GET_REG_BITS(mac_hfr1, - MAC_HWF1R_ADDR64_POS, - MAC_HWF1R_ADDR64_LEN); - hw_feat->dcb = FXGMAC_GET_REG_BITS(mac_hfr1, - MAC_HWF1R_DCBEN_POS, - MAC_HWF1R_DCBEN_LEN); - hw_feat->sph = FXGMAC_GET_REG_BITS(mac_hfr1, - MAC_HWF1R_SPHEN_POS, - MAC_HWF1R_SPHEN_LEN); -#if (0 /*LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)*/) - hw_feat->tso = 0; //bypass tso -#else - hw_feat->tso = FXGMAC_GET_REG_BITS(mac_hfr1, - MAC_HWF1R_TSOEN_POS, - MAC_HWF1R_TSOEN_LEN); -#endif - hw_feat->dma_debug = FXGMAC_GET_REG_BITS(mac_hfr1, - MAC_HWF1R_DBGMEMA_POS, - MAC_HWF1R_DBGMEMA_LEN); -#if (FXGMAC_RSS_FEATURE_ENABLED) - hw_feat->rss = 1; -#else - hw_feat->rss = 0; /* = FXGMAC_GET_REG_BITS(mac_hfr1, - MAC_HWF1R_RSSEN_POS, - MAC_HWF1R_RSSEN_LEN);*/ -#endif - hw_feat->tc_cnt = 3/*1, yzhang try,0412*/; /* FXGMAC_GET_REG_BITS(mac_hfr1, - MAC_HWF1R_NUMTC_POS, - MAC_HWF1R_NUMTC_LEN); */ - hw_feat->avsel = FXGMAC_GET_REG_BITS(mac_hfr1, - MAC_HWF1R_AVSEL_POS, - MAC_HWF1R_AVSEL_LEN); - hw_feat->ravsel = FXGMAC_GET_REG_BITS(mac_hfr1, - MAC_HWF1R_RAVSEL_POS, - MAC_HWF1R_RAVSEL_LEN); - hw_feat->hash_table_size = FXGMAC_GET_REG_BITS(mac_hfr1, - MAC_HWF1R_HASHTBLSZ_POS, - MAC_HWF1R_HASHTBLSZ_LEN); - hw_feat->l3l4_filter_num = FXGMAC_GET_REG_BITS(mac_hfr1, - MAC_HWF1R_L3L4FNUM_POS, - MAC_HWF1R_L3L4FNUM_LEN); - - /* Hardware feature register 2 */ -#if 1 /* hw implement only 1 Q, but from software we see 4 logical Qs. hardcode to 4 Qs. */ - hw_feat->rx_q_cnt = 3/*FXGMAC_GET_REG_BITS(mac_hfr2, - MAC_HWF2R_RXQCNT_POS, - MAC_HWF2R_RXQCNT_LEN)*/; -#else - hw_feat->rx_q_cnt = FXGMAC_GET_REG_BITS(mac_hfr2, - MAC_HWF2R_RXQCNT_POS, - MAC_HWF2R_RXQCNT_LEN); -#endif - hw_feat->tx_q_cnt = FXGMAC_GET_REG_BITS(mac_hfr2, - MAC_HWF2R_TXQCNT_POS, - MAC_HWF2R_TXQCNT_LEN); -#if 0 /*yzhang for debug. only 1 rx channl and q*/ - hw_feat->rx_ch_cnt = 0 /*FXGMAC_GET_REG_BITS(mac_hfr2, - MAC_HWF2R_RXCHCNT_POS, - MAC_HWF2R_RXCHCNT_LEN)*/; -#else - hw_feat->rx_ch_cnt = FXGMAC_GET_REG_BITS(mac_hfr2, - MAC_HWF2R_RXCHCNT_POS, - MAC_HWF2R_RXCHCNT_LEN); -#endif - hw_feat->tx_ch_cnt = FXGMAC_GET_REG_BITS(mac_hfr2, - MAC_HWF2R_TXCHCNT_POS, - MAC_HWF2R_TXCHCNT_LEN); - hw_feat->pps_out_num = FXGMAC_GET_REG_BITS(mac_hfr2, - MAC_HWF2R_PPSOUTNUM_POS, - MAC_HWF2R_PPSOUTNUM_LEN); - hw_feat->aux_snap_num = FXGMAC_GET_REG_BITS(mac_hfr2, - MAC_HWF2R_AUXSNAPNUM_POS, - MAC_HWF2R_AUXSNAPNUM_LEN); - - /* 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; - } - - /* Translate the address width setting into actual number */ - switch (hw_feat->dma_width) { - case 0: - hw_feat->dma_width = 32; - break; - case 1: - hw_feat->dma_width = 40; - break; - case 2: - hw_feat->dma_width = 48; - break; - default: - hw_feat->dma_width = 32; - } - - /* 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++; - - hw_feat->hwfr3 = mac_hfr3; - DPRINTK("HWFR3: %u\n", mac_hfr3); -} - -void fxgmac_print_all_hw_features(struct fxgmac_pdata *pdata) -{ - char *str = NULL; - - DPRINTK("\n"); - DPRINTK("=====================================================\n"); - DPRINTK("\n"); - DPRINTK("HW support following features,ver=%#x\n",pdata->hw_feat.version); - DPRINTK("\n"); - /* HW Feature Register0 */ - DPRINTK("VLAN Hash Filter Selected : %s\n", - pdata->hw_feat.vlhash ? "YES" : "NO"); - DPRINTK("SMA (MDIO) Interface : %s\n", - pdata->hw_feat.sma ? "YES" : "NO"); - DPRINTK("PMT Remote Wake-up Packet Enable : %s\n", - pdata->hw_feat.rwk ? "YES" : "NO"); - DPRINTK("PMT Magic Packet Enable : %s\n", - pdata->hw_feat.mgk ? "YES" : "NO"); - DPRINTK("RMON/MMC Module Enable : %s\n", - pdata->hw_feat.mmc ? "YES" : "NO"); - DPRINTK("ARP Offload Enabled : %s\n", - pdata->hw_feat.aoe ? "YES" : "NO"); - DPRINTK("IEEE 1588-2008 Timestamp Enabled : %s\n", - pdata->hw_feat.ts ? "YES" : "NO"); - DPRINTK("Energy Efficient Ethernet Enabled : %s\n", - pdata->hw_feat.eee ? "YES" : "NO"); - DPRINTK("Transmit Checksum Offload Enabled : %s\n", - pdata->hw_feat.tx_coe ? "YES" : "NO"); - DPRINTK("Receive Checksum Offload Enabled : %s\n", - pdata->hw_feat.rx_coe ? "YES" : "NO"); - DPRINTK("Additional MAC Addresses 1-31 Selected : %s\n", - pdata->hw_feat.addn_mac ? "YES" : "NO"); - - switch (pdata->hw_feat.ts_src) { - case 0: - str = "RESERVED"; - break; - case 1: - str = "INTERNAL"; - break; - case 2: - str = "EXTERNAL"; - break; - case 3: - str = "BOTH"; - break; - } - DPRINTK("Timestamp System Time Source : %s\n", str); - - DPRINTK("Source Address or VLAN Insertion Enable : %s\n", - pdata->hw_feat.sa_vlan_ins ? "YES" : "NO"); - - /* HW Feature Register1 */ - switch (pdata->hw_feat.rx_fifo_size) { - case 0: - str = "128 bytes"; - break; - case 1: - str = "256 bytes"; - break; - case 2: - str = "512 bytes"; - break; - case 3: - str = "1 KBytes"; - break; - case 4: - str = "2 KBytes"; - break; - case 5: - str = "4 KBytes"; - break; - case 6: - str = "8 KBytes"; - break; - case 7: - str = "16 KBytes"; - break; - case 8: - str = "32 kBytes"; - break; - case 9: - str = "64 KBytes"; - break; - case 10: - str = "128 KBytes"; - break; - case 11: - str = "256 KBytes"; - break; - default: - str = "RESERVED"; - } - DPRINTK("MTL Receive FIFO Size : %s\n", str); - - switch (pdata->hw_feat.tx_fifo_size) { - case 0: - str = "128 bytes"; - break; - case 1: - str = "256 bytes"; - break; - case 2: - str = "512 bytes"; - break; - case 3: - str = "1 KBytes"; - break; - case 4: - str = "2 KBytes"; - break; - case 5: - str = "4 KBytes"; - break; - case 6: - str = "8 KBytes"; - break; - case 7: - str = "16 KBytes"; - break; - case 8: - str = "32 kBytes"; - break; - case 9: - str = "64 KBytes"; - break; - case 10: - str = "128 KBytes"; - break; - case 11: - str = "256 KBytes"; - break; - default: - str = "RESERVED"; - } - DPRINTK("MTL Transmit FIFO Size : %s\n", str); - - DPRINTK("IEEE 1588 High Word Register Enable : %s\n", - pdata->hw_feat.adv_ts_hi ? "YES" : "NO"); - DPRINTK("Address width : %u\n", - pdata->hw_feat.dma_width); - DPRINTK("DCB Feature Enable : %s\n", - pdata->hw_feat.dcb ? "YES" : "NO"); - DPRINTK("Split Header Feature Enable : %s\n", - pdata->hw_feat.sph ? "YES" : "NO"); - DPRINTK("TCP Segmentation Offload Enable : %s\n", - pdata->hw_feat.tso ? "YES" : "NO"); - DPRINTK("DMA Debug Registers Enabled : %s\n", - pdata->hw_feat.dma_debug ? "YES" : "NO"); - DPRINTK("RSS Feature Enabled : %s\n", - pdata->hw_feat.rss ? "YES" : "NO"); - DPRINTK("*TODO*Number of Traffic classes : %u\n", - (pdata->hw_feat.tc_cnt)); - DPRINTK("AV Feature Enabled : %s\n", - pdata->hw_feat.avsel ? "YES" : "NO"); - DPRINTK("Rx Side Only AV Feature Enabled : %s\n", - (pdata->hw_feat.ravsel ? "YES": "NO")); - DPRINTK("Hash Table Size : %u\n", - pdata->hw_feat.hash_table_size); - DPRINTK("Total number of L3 or L4 Filters : %u\n", - pdata->hw_feat.l3l4_filter_num); - - /* HW Feature Register2 */ - DPRINTK("Number of MTL Receive Queues : %u\n", - pdata->hw_feat.rx_q_cnt); - DPRINTK("Number of MTL Transmit Queues : %u\n", - pdata->hw_feat.tx_q_cnt); - DPRINTK("Number of DMA Receive Channels : %u\n", - pdata->hw_feat.rx_ch_cnt); - DPRINTK("Number of DMA Transmit Channels : %u\n", - pdata->hw_feat.tx_ch_cnt); - - switch (pdata->hw_feat.pps_out_num) { - case 0: - str = "No PPS output"; - break; - case 1: - str = "1 PPS output"; - break; - case 2: - str = "2 PPS output"; - break; - case 3: - str = "3 PPS output"; - break; - case 4: - str = "4 PPS output"; - break; - default: - str = "RESERVED"; - } - DPRINTK("Number of PPS Outputs : %s\n", str); - - switch (pdata->hw_feat.aux_snap_num) { - case 0: - str = "No auxiliary input"; - break; - case 1: - str = "1 auxiliary input"; - break; - case 2: - str = "2 auxiliary input"; - break; - case 3: - str = "3 auxiliary input"; - break; - case 4: - str = "4 auxiliary input"; - break; - default: - str = "RESERVED"; - } - DPRINTK("Number of Auxiliary Snapshot Inputs : %s", str); - - DPRINTK("\n"); - DPRINTK("=====================================================\n"); - DPRINTK("\n"); -} diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-debugfs.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-debugfs.c deleted file mode 100644 index 6e3a8684c4237..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-debugfs.c +++ /dev/null @@ -1,760 +0,0 @@ -/*++ - -Copyright (c) 2021 Motor-comm Corporation. -Confidential and Proprietary. All rights reserved. - -This is Motor-comm Corporation NIC driver relevant files. Please don't copy, modify, -distribute without commercial permission. - ---*/ - - - -#include "fuxi-gmac.h" -#include "fuxi-gmac-reg.h" -#ifdef HAVE_FXGMAC_DEBUG_FS -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TEST_MAC_HEAD 14 -#define TEST_TCP_HEAD_LEN_OFFSET 12 -#define TEST_TCP_OFFLOAD_LEN_OFFSET 48 -#define TEST_TCP_FIX_HEAD_LEN 24 -#define TEST_TCP_MSS_OFFSET 56 - -#define DF_MAX_NIC_NUM 16 - -#ifdef HAVE_FXGMAC_DEBUG_FS - -/** - * fxgmac_dbg_netdev_ops_read - read for netdev_ops datum - * @filp: the opened file - * @buffer: where to write the data for the user to read - * @count: the size of the user's buffer - * @ppos: file position offset - **/ -static ssize_t fxgmac_dbg_netdev_ops_read(struct file *filp, - char __user *buffer, - size_t count, loff_t *ppos) -{ - struct fxgmac_pdata *pdata = filp->private_data; - char *buf; - int len; - - /* don't allow partial reads */ - if (*ppos != 0) - return 0; - - buf = kasprintf(GFP_KERNEL, "%s: %s\n", - pdata->netdev->name, - pdata->expansion.fxgmac_dbg_netdev_ops_buf); - 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; -} - -/** - * fxgmac_dbg_netdev_ops_write - write into netdev_ops datum - * @filp: the opened file - * @buffer: where to find the user's data - * @count: the length of the user's data - * @ppos: file position offset - **/ -static ssize_t fxgmac_dbg_netdev_ops_write(struct file *filp, - const char __user *buffer, - size_t count, loff_t *ppos) -{ - struct fxgmac_pdata *pdata = filp->private_data; - int len; - - /* don't allow partial writes */ - if (*ppos != 0) - return 0; - if (count >= sizeof(pdata->expansion.fxgmac_dbg_netdev_ops_buf)) - return -ENOSPC; - - len = simple_write_to_buffer(pdata->expansion.fxgmac_dbg_netdev_ops_buf, - sizeof(pdata->expansion.fxgmac_dbg_netdev_ops_buf)-1, - ppos, - buffer, - count); - if (len < 0) - return len; - - pdata->expansion.fxgmac_dbg_netdev_ops_buf[len] = '\0'; - - if (strncmp(pdata->expansion.fxgmac_dbg_netdev_ops_buf, "tx_timeout", 10) == 0) { - DPRINTK("tx_timeout called\n"); - } else { - FXGMAC_PR("Unknown command: %s\n", pdata->expansion.fxgmac_dbg_netdev_ops_buf); - FXGMAC_PR("Available commands:\n"); - FXGMAC_PR(" tx_timeout\n"); - } - return count; -} -#endif - -static void fxgmac_dbg_tx_pkt(struct fxgmac_pdata *pdata, u8 *pcmd_data) -{ - unsigned int pktLen = 0; - struct sk_buff *skb; - pfxgmac_test_packet pPkt; - u8 * pTx_data = NULL; - u8 * pSkb_data = NULL; - u32 offload_len = 0; - u8 ipHeadLen, tcpHeadLen, headTotalLen; - static u32 lastGsoSize = 806;//initial default value - //int i = 0; - - /* get fxgmac_test_packet */ - pPkt = (pfxgmac_test_packet)(pcmd_data + sizeof(struct ext_ioctl_data)); - pktLen = pPkt->length; - - /* get pkt data */ - pTx_data = (u8 *)pPkt + sizeof(fxgmac_test_packet); - -#if 0 //for debug - DPRINTK("Send packet len is %d, data:\n", pktLen); -#if 1 - for(i = 0; i < 70 ; i++) - { - DPRINTK("%2x ", pTx_data[i]); - } -#endif -#endif - - /* alloc sk_buff */ - skb = alloc_skb(pktLen, GFP_ATOMIC); - if (!skb){ - DPRINTK("alloc skb fail\n"); - return; - } - - /* copy data to skb */ - pSkb_data = skb_put(skb, pktLen); - memset(pSkb_data, 0, pktLen); - memcpy(pSkb_data, pTx_data, pktLen); - - /* set skb parameters */ - skb->dev = pdata->netdev; - skb->pkt_type = PACKET_OUTGOING; - skb->protocol = ntohs(ETH_P_IP); - skb->no_fcs = 1; - skb->ip_summed = CHECKSUM_PARTIAL; - if(skb->len > 1514){ - /* TSO packet */ - /* set tso test flag */ - pdata->expansion.fxgmac_test_tso_flag = true; - - /* get protocol head length */ - ipHeadLen = (pSkb_data[TEST_MAC_HEAD] & 0xF) * 4; - tcpHeadLen = (pSkb_data[TEST_MAC_HEAD + ipHeadLen + TEST_TCP_HEAD_LEN_OFFSET] >> 4 & 0xF) * 4; - headTotalLen = TEST_MAC_HEAD + ipHeadLen + tcpHeadLen; - offload_len = (pSkb_data[TEST_TCP_OFFLOAD_LEN_OFFSET] << 8 | - pSkb_data[TEST_TCP_OFFLOAD_LEN_OFFSET + 1]) & 0xFFFF; - /* set tso skb parameters */ - //skb->ip_summed = CHECKSUM_PARTIAL; - skb->transport_header = ipHeadLen + TEST_MAC_HEAD; - skb->network_header = TEST_MAC_HEAD; - skb->inner_network_header = TEST_MAC_HEAD; - skb->mac_len = TEST_MAC_HEAD; - - /* set skb_shinfo parameters */ - if(tcpHeadLen > TEST_TCP_FIX_HEAD_LEN){ - skb_shinfo(skb)->gso_size = (pSkb_data[TEST_TCP_MSS_OFFSET] << 8 | - pSkb_data[TEST_TCP_MSS_OFFSET + 1]) & 0xFFFF; - }else{ - skb_shinfo(skb)->gso_size = 0; - } - if(skb_shinfo(skb)->gso_size != 0){ - lastGsoSize = skb_shinfo(skb)->gso_size; - }else{ - skb_shinfo(skb)->gso_size = lastGsoSize; - } - //DPRINTK("offload_len is %d, skb_shinfo(skb)->gso_size is %d", offload_len, skb_shinfo(skb)->gso_size); - /* get segment size */ - if(offload_len % skb_shinfo(skb)->gso_size == 0){ - skb_shinfo(skb)->gso_segs = offload_len / skb_shinfo(skb)->gso_size; - pdata->expansion.fxgmac_test_last_tso_len = skb_shinfo(skb)->gso_size + headTotalLen; - }else{ - skb_shinfo(skb)->gso_segs = offload_len / skb_shinfo(skb)->gso_size + 1; - pdata->expansion.fxgmac_test_last_tso_len = offload_len % skb_shinfo(skb)->gso_size + headTotalLen; - } - pdata->expansion.fxgmac_test_tso_seg_num = skb_shinfo(skb)->gso_segs; - - skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4 ; - skb_shinfo(skb)->frag_list = NULL; - skb->csum_start = skb_headroom(skb) + TEST_MAC_HEAD + ipHeadLen; - skb->csum_offset = skb->len - TEST_MAC_HEAD - ipHeadLen; - - pdata->expansion.fxgmac_test_packet_len = skb_shinfo(skb)->gso_size + headTotalLen; - }else{ - /* set non-TSO packet parameters */ - pdata->expansion.fxgmac_test_packet_len = skb->len; - } - - /* send data */ - if(dev_queue_xmit(skb) != NET_XMIT_SUCCESS){ - DPRINTK("xmit data fail \n"); - } -} - -static void fxgmac_dbg_rx_pkt(struct fxgmac_pdata *pdata, u8 *pcmd_data) -{ - unsigned int totalLen = 0; - struct sk_buff *rx_skb; - struct ext_ioctl_data *pcmd; - fxgmac_test_packet pkt; - void* addr = 0; - u8 *rx_data = (u8*)kzalloc(FXGMAC_MAX_DBG_RX_DATA, GFP_KERNEL); - if (!rx_data) - return; - //int i; - - /* initial dest data region */ - pcmd = (struct ext_ioctl_data *)pcmd_data; - addr = pcmd->cmd_buf.buf; - while(pdata->expansion.fxgmac_test_skb_arr_in_index != pdata->expansion.fxgmac_test_skb_arr_out_index){ - /* get received skb data */ - rx_skb = pdata->expansion.fxgmac_test_skb_array[pdata->expansion.fxgmac_test_skb_arr_out_index]; - - if(rx_skb->len + sizeof(fxgmac_test_packet) + totalLen < 64000){ - pkt.length = rx_skb->len; - pkt.type = 0x80; - pkt.buf[0].offset = totalLen + sizeof(fxgmac_test_packet); - pkt.buf[0].length = rx_skb->len; - - /* get data from skb */ - //DPRINTK("FXG:rx_skb->len=%d", rx_skb->len); - memcpy(rx_data, rx_skb->data, rx_skb->len); - - /* update next pointer */ - if((pdata->expansion.fxgmac_test_skb_arr_out_index + 1) % FXGMAC_MAX_DBG_TEST_PKT == pdata->expansion.fxgmac_test_skb_arr_in_index) - { - pkt.next = NULL; - } - else - { - pkt.next = (pfxgmac_test_packet)(addr + totalLen + sizeof(fxgmac_test_packet) + pkt.length); - } - - /* copy data to user space */ - if(copy_to_user((void *)(addr + totalLen), (void*)(&pkt), sizeof(fxgmac_test_packet))) - { - DPRINTK("cppy pkt data to user fail..."); - } - //FXGMAC_PR("FXG:rx_skb->len=%d", rx_skb->len); - if(copy_to_user((void *)(addr + totalLen + sizeof(fxgmac_test_packet)), (void*)rx_data, rx_skb->len)) - { - DPRINTK("cppy data to user fail..."); - } - - /* update total length */ - totalLen += (sizeof(fxgmac_test_packet) + rx_skb->len); - - /* free skb */ - kfree_skb(rx_skb); - pdata->expansion.fxgmac_test_skb_array[pdata->expansion.fxgmac_test_skb_arr_out_index] = NULL; - - /* update gCurSkbOutIndex */ - pdata->expansion.fxgmac_test_skb_arr_out_index = (pdata->expansion.fxgmac_test_skb_arr_out_index + 1) % FXGMAC_MAX_DBG_TEST_PKT; - }else{ - DPRINTK("receive data more receive buffer... \n"); - break; - } - } - - if (rx_data) - kfree(rx_data); -#if 0 - pPkt = (pfxgmac_test_packet)buf; - DPRINTK("FXG: pPkt->Length is %d", pPkt->length); - DPRINTK("FXG: pPkt->Length is %d", pPkt->length); - DPRINTK("pPkt: %p, buf is %lx",pPkt, pcmd->cmd_buf.buf); - for(i = 0; i < 30; i++){ - DPRINTK("%x",*(((u8*)pPkt + sizeof(fxgmac_test_packet)) + i)); - } -#endif -} - -// Based on the current application scenario,we only use CMD_DATA for data. -// if you use other struct, you should recalculate in_total_size -long fxgmac_dbg_netdev_ops_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - bool ret = true; - int regval = 0; - struct fxgmac_pdata *pdata = file->private_data; - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - FXGMAC_PDATA_OF_PLATFORM *ex = &pdata->expansion; - CMD_DATA ex_data; - struct ext_ioctl_data pcmd; - u8* data = NULL; - u8* buf = NULL; - int in_total_size, in_data_size, out_total_size; - int ioctl_cmd_size = sizeof(struct ext_ioctl_data); - u8 mac[ETH_ALEN] = {0}; - struct sk_buff *tmpskb; - - if (!arg) { - DPRINTK("[%s] command arg is %lx !\n", __func__, arg); - goto err; - } - - /* check device type */ - if (_IOC_TYPE(cmd) != IOC_MAGIC) { - DPRINTK("[%s] command type [%c] error!\n", __func__, _IOC_TYPE(cmd)); - goto err; - } - - /* check command number*/ - if (_IOC_NR(cmd) > IOC_MAXNR) { - DPRINTK("[%s] command numer [%d] exceeded!\n", __func__, _IOC_NR(cmd)); - goto err; - } - - //buf = (u8*)kzalloc(FXGMAC_MAX_DBG_BUF_LEN, GFP_KERNEL); - if(copy_from_user(&pcmd, (void*)arg, ioctl_cmd_size)) { - DPRINTK("copy data from user fail... \n"); - goto err; - } - - in_total_size = pcmd.cmd_buf.size_in; - in_data_size = in_total_size - ioctl_cmd_size; - out_total_size = pcmd.cmd_buf.size_out; - - buf = (u8*)kzalloc(in_total_size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - if(copy_from_user(buf, (void*)arg, in_total_size)) { - DPRINTK("copy data from user fail... \n"); - goto err; - } - data = buf + ioctl_cmd_size; - - if(arg != 0) { - switch(pcmd.cmd_type) { - /* ioctl diag begin */ - case FUXI_DFS_IOCTL_DIAG_BEGIN: - DPRINTK("Debugfs received diag begin command.\n"); - if (netif_running(pdata->netdev)){ - fxgmac_restart_dev(pdata); - } - - /* release last loopback test abnormal exit buffer */ - while(ex->fxgmac_test_skb_arr_in_index != - ex->fxgmac_test_skb_arr_out_index) - { - tmpskb = ex->fxgmac_test_skb_array[ex->fxgmac_test_skb_arr_out_index]; - if(tmpskb) - { - kfree_skb(tmpskb); - ex->fxgmac_test_skb_array[ex->fxgmac_test_skb_arr_out_index] = NULL; - } - - ex->fxgmac_test_skb_arr_out_index = (ex->fxgmac_test_skb_arr_out_index + 1) % FXGMAC_MAX_DBG_TEST_PKT; - } - - /* init loopback test parameters */ - ex->fxgmac_test_skb_arr_in_index = 0; - ex->fxgmac_test_skb_arr_out_index = 0; - ex->fxgmac_test_tso_flag = false; - ex->fxgmac_test_tso_seg_num = 0; - ex->fxgmac_test_last_tso_len = 0; - ex->fxgmac_test_packet_len = 0; - break; - - /* ioctl diag end */ - case FUXI_DFS_IOCTL_DIAG_END: - DPRINTK("Debugfs received diag end command.\n"); - if (netif_running(pdata->netdev)){ - fxgmac_restart_dev(pdata); - } - break; - - /* ioctl diag tx pkt */ - case FUXI_DFS_IOCTL_DIAG_TX_PKT: - fxgmac_dbg_tx_pkt(pdata, buf); - break; - - /* ioctl diag rx pkt */ - case FUXI_DFS_IOCTL_DIAG_RX_PKT: - fxgmac_dbg_rx_pkt(pdata, buf); - break; - - /* ioctl device reset */ - case FUXI_DFS_IOCTL_DEVICE_RESET: - DPRINTK("Debugfs received device reset command.\n"); - if (netif_running(pdata->netdev)){ - fxgmac_restart_dev(pdata); - } - break; - - case FXGMAC_EFUSE_LED_TEST: - DPRINTK("Debugfs received device led test command.\n"); - memcpy(&pdata->led, data, sizeof(struct led_setting)); - fxgmac_restart_dev(pdata); - break; - - case FXGMAC_EFUSE_UPDATE_LED_CFG: - DPRINTK("Debugfs received device led update command.\n"); - memcpy(&pdata->ledconfig, data, sizeof(struct led_setting)); - ret = hw_ops->write_led_config(pdata); - hw_ops->read_led_config(pdata); - hw_ops->led_under_active(pdata); - break; - - case FXGMAC_EFUSE_WRITE_LED: - memcpy(&ex_data, data, sizeof(CMD_DATA)); - DPRINTK("FXGMAC_EFUSE_WRITE_LED, val = 0x%x\n", ex_data.val0); - ret = hw_ops->write_led(pdata, ex_data.val0); - break; - - case FXGMAC_EFUSE_WRITE_OOB: - DPRINTK("FXGMAC_EFUSE_WRITE_OOB.\n"); - ret = hw_ops->write_oob(pdata); - break; - - case FXGMAC_EFUSE_READ_REGIONABC: - memcpy(&ex_data, data, sizeof(CMD_DATA)); - ret = hw_ops->read_efuse_data(pdata, ex_data.val0, &ex_data.val1); - DPRINTK("FXGMAC_EFUSE_READ_REGIONABC, address = 0x%x, val = 0x%x\n", - ex_data.val0, - ex_data.val1); - if (ret) { - memcpy(data, &ex_data, sizeof(CMD_DATA)); - out_total_size = ioctl_cmd_size + sizeof(CMD_DATA); - if (copy_to_user((void*)arg, (void*)buf, out_total_size)) - goto err; - } - break; - - case FXGMAC_EFUSE_WRITE_PATCH_REG: - memcpy(&ex_data, data, sizeof(CMD_DATA)); - DPRINTK("FXGMAC_EFUSE_WRITE_PATCH_REG, address = 0x%x, val = 0x%x\n", - ex_data.val0, - ex_data.val1); - ret = hw_ops->write_patch_to_efuse(pdata, ex_data.val0, ex_data.val1); - break; - - case FXGMAC_EFUSE_READ_PATCH_REG: - memcpy(&ex_data, data, sizeof(CMD_DATA)); - ret = hw_ops->read_patch_from_efuse(pdata, ex_data.val0, &ex_data.val1); - DPRINTK("FXGMAC_EFUSE_READ_PATCH_REG, address = 0x%x, val = 0x%x\n", - ex_data.val0, ex_data.val1); - if (ret) { - memcpy(data, &ex_data, sizeof(CMD_DATA)); - out_total_size = ioctl_cmd_size + sizeof(CMD_DATA); - if (copy_to_user((void*)arg, (void*)buf, out_total_size)) - goto err; - } - break; - - case FXGMAC_EFUSE_WRITE_PATCH_PER_INDEX: - memcpy(&ex_data, data, sizeof(CMD_DATA)); - ret = hw_ops->write_patch_to_efuse_per_index(pdata, ex_data.val0, - ex_data.val1, - ex_data.val2); - DPRINTK("FXGMAC_EFUSE_WRITE_PATCH_PER_INDEX, index = %d, address = 0x%x, val = 0x%x\n", - ex_data.val0, ex_data.val1, ex_data.val2); - break; - - case FXGMAC_EFUSE_READ_PATCH_PER_INDEX: - memcpy(&ex_data, data, sizeof(CMD_DATA)); - ret = hw_ops->read_patch_from_efuse_per_index(pdata,ex_data.val0, - &ex_data.val1, - &ex_data.val2); - DPRINTK("FXGMAC_EFUSE_READ_PATCH_PER_INDEX, address = 0x%x, val = 0x%x\n", - ex_data.val1, ex_data.val2); - if (ret) { - memcpy(data, &ex_data, sizeof(CMD_DATA)); - out_total_size = ioctl_cmd_size + sizeof(CMD_DATA); - if (copy_to_user((void*)arg, (void*)buf, out_total_size)) - goto err; - } - break; - - case FXGMAC_EFUSE_LOAD: - DPRINTK("FXGMAC_EFUSE_LOAD.\n"); - ret = hw_ops->efuse_load(pdata); - break; - - case FXGMAC_GET_MAC_DATA: - ret = hw_ops->read_mac_subsys_from_efuse(pdata, mac, NULL, NULL); - if (ret) { - memcpy(data, mac, ETH_ALEN); - out_total_size = ioctl_cmd_size + ETH_ALEN; - if (copy_to_user((void*)arg, (void*)buf, out_total_size)) - goto err; - } - break; - - case FXGMAC_SET_MAC_DATA: - if (in_data_size != ETH_ALEN) - goto err; - memcpy(mac, data, ETH_ALEN); - ret = hw_ops->write_mac_subsys_to_efuse(pdata, mac, NULL, NULL); - if (ret) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0)) - eth_hw_addr_set(pdata->netdev, mac); -#else - memcpy(pdata->netdev->dev_addr, mac, ETH_ALEN); -#endif - - memcpy(pdata->mac_addr, mac, ETH_ALEN); - - hw_ops->set_mac_address(pdata, mac); - hw_ops->set_mac_hash(pdata); - } - break; - - case FXGMAC_GET_SUBSYS_ID: - memcpy(&ex_data, data, sizeof(CMD_DATA)); - ret = hw_ops->read_mac_subsys_from_efuse(pdata, - NULL, - &ex_data.val0, - NULL); - if (ret) { - ex_data.val1 = 0xFFFF; // invalid value - memcpy(data, &ex_data, sizeof(CMD_DATA)); - out_total_size = ioctl_cmd_size + sizeof(CMD_DATA); - if (copy_to_user((void*)arg, (void*)buf, out_total_size)) - goto err; - } - break; - - case FXGMAC_SET_SUBSYS_ID: - memcpy(&ex_data, data, sizeof(CMD_DATA)); - ret = hw_ops->write_mac_subsys_to_efuse(pdata, - NULL, - &ex_data.val0, - NULL); - break; - - case FXGMAC_GET_GMAC_REG: - memcpy(&ex_data, data, sizeof(CMD_DATA)); - ex_data.val1 = hw_ops->get_gmac_register(pdata, - (u8*)(pdata->mac_regs + ex_data.val0)); - memcpy(data, &ex_data, sizeof(CMD_DATA)); - out_total_size = ioctl_cmd_size + sizeof(CMD_DATA); - if (copy_to_user((void*)arg, (void*)buf, out_total_size)) - goto err; - break; - - case FXGMAC_SET_GMAC_REG: - memcpy(&ex_data, data, sizeof(CMD_DATA)); - regval = hw_ops->set_gmac_register(pdata, - (u8*)(pdata->mac_regs + ex_data.val0), - ex_data.val1); - ret = (regval == 0 ? true : false); - break; - - case FXGMAC_GET_PHY_REG: - memcpy(&ex_data, data, sizeof(CMD_DATA)); - regval = hw_ops->read_ephy_reg(pdata, ex_data.val0, &ex_data.val1); - if (regval != -1) { - memcpy(data, &ex_data, sizeof(CMD_DATA)); - out_total_size = ioctl_cmd_size + sizeof(CMD_DATA); - if (copy_to_user((void*)arg, (void*)buf, out_total_size)) - goto err; - } - ret = (regval == -1 ? false : true); - break; - - case FXGMAC_SET_PHY_REG: - memcpy(&ex_data, data, sizeof(CMD_DATA)); - regval = hw_ops->write_ephy_reg(pdata, ex_data.val0, ex_data.val1); - ret = (regval == 0 ? true : false); - break; - - case FXGMAC_GET_PCIE_LOCATION: - ex_data.val0 = pdata->pdev->bus->number; - ex_data.val1 = PCI_SLOT(pdata->pdev->devfn); - ex_data.val2 = PCI_FUNC(pdata->pdev->devfn); - memcpy(data, &ex_data, sizeof(CMD_DATA)); - out_total_size = ioctl_cmd_size + sizeof(CMD_DATA); - if (copy_to_user((void*)arg, (void*)buf, out_total_size)) - goto err; - break; - - case FXGMAC_GET_GSO_SIZE: - ex_data.val0 = pdata->netdev->gso_max_size; - memcpy(data, &ex_data, sizeof(CMD_DATA)); - out_total_size = ioctl_cmd_size + sizeof(CMD_DATA); - if (copy_to_user((void*)arg, (void*)buf, out_total_size)) - goto err; - break; - - case FXGMAC_SET_GSO_SIZE: - memcpy(&ex_data, data, sizeof(CMD_DATA)); - pdata->netdev->gso_max_size = ex_data.val0; - break; - - case FXGMAC_SET_RX_MODERATION: - memcpy(&ex_data, data, sizeof(CMD_DATA)); - regval = readreg(pdata->pAdapter, pdata->base_mem + INT_MOD); - regval = FXGMAC_SET_REG_BITS(regval, INT_MOD_RX_POS, INT_MOD_RX_LEN, ex_data.val0); - writereg(pdata->pAdapter, regval, pdata->base_mem + INT_MOD); - break; - - case FXGMAC_SET_TX_MODERATION: - memcpy(&ex_data, data, sizeof(CMD_DATA)); - regval = readreg(pdata->pAdapter, pdata->base_mem + INT_MOD); - regval = FXGMAC_SET_REG_BITS(regval, INT_MOD_TX_POS, INT_MOD_TX_LEN, ex_data.val0); - writereg(pdata->pAdapter, regval, pdata->base_mem + INT_MOD); - break; - - case FXGMAC_GET_TXRX_MODERATION: - regval = readreg(pdata->pAdapter, pdata->base_mem + INT_MOD); - ex_data.val0 = FXGMAC_GET_REG_BITS(regval, INT_MOD_RX_POS, INT_MOD_RX_LEN); - ex_data.val1 = FXGMAC_GET_REG_BITS(regval, INT_MOD_TX_POS, INT_MOD_TX_LEN); - memcpy(data, &ex_data, sizeof(CMD_DATA)); - out_total_size = ioctl_cmd_size + sizeof(CMD_DATA); - if (copy_to_user((void*)arg, (void*)buf, out_total_size)) - goto err; - break; - - default: - DPRINTK("Debugfs received invalid command: %x.\n", pcmd.cmd_type); - ret = false; - break; - } - } - - if (buf) - kfree(buf); - return ret ? FXGMAC_SUCCESS : FXGMAC_FAIL; - -err: - if (buf) - kfree(buf); - return FXGMAC_FAIL; -} - -#ifdef HAVE_FXGMAC_DEBUG_FS - -static struct file_operations fxgmac_dbg_netdev_ops_fops = { - .owner = THIS_MODULE, - .open = simple_open, - .read = fxgmac_dbg_netdev_ops_read, - .write = fxgmac_dbg_netdev_ops_write, - .unlocked_ioctl = fxgmac_dbg_netdev_ops_ioctl, -}; - -/** - * fxgmac_dbg_adapter_init - setup the debugfs directory for the adapter - * @adapter: the adapter that is starting up - **/ -void fxgmac_dbg_adapter_init(struct fxgmac_pdata *pdata) -{ - const char *name = pdata->drv_name; - struct dentry *pfile; - - pdata->expansion.dbg_adapter = debugfs_create_dir(name, pdata->expansion.fxgmac_dbg_root); - if (pdata->expansion.dbg_adapter) { - pfile = debugfs_create_file("netdev_ops", 0600, - pdata->expansion.dbg_adapter, pdata, - &fxgmac_dbg_netdev_ops_fops); - if (!pfile) - DPRINTK("debugfs netdev_ops for %s failed\n", name); - } else { - DPRINTK("debugfs entry for %s failed\n", name); - } -} - -/** - * fxgmac_dbg_adapter_exit - clear out the adapter's debugfs entries - * @adapter: board private structure - **/ -void fxgmac_dbg_adapter_exit(struct fxgmac_pdata *pdata) -{ - if (pdata->expansion.dbg_adapter) - debugfs_remove_recursive(pdata->expansion.dbg_adapter); - pdata->expansion.dbg_adapter = NULL; -} - -/** - * fxgmac_dbg_init - start up debugfs for the driver - **/ -void fxgmac_dbg_init(struct fxgmac_pdata *pdata) -{ - unsigned int i; - char num[3]; - const char debug_path[] = "/sys/kernel/debug/"; - const char file_prefix[] = "fuxi_"; - char file_path[50]; - char file_name[8]; - - /* init file_path */ - memset(file_path, '\0', sizeof(file_path)); - memcpy(file_path, debug_path, sizeof(debug_path)); - - for(i = 0; i < DF_MAX_NIC_NUM; i++) - { - /* init num and filename */ - memset(num, '\0', sizeof(num)); - memset(file_name, '\0', sizeof(file_name)); - - /* int to string */ - sprintf(num, "%d", i); - - /* file name */ - memcpy(file_name, file_prefix, sizeof(file_prefix)); - memcpy(file_name + strlen(file_prefix), num, sizeof(num)); - - /* file path */ - memcpy(file_path + sizeof(debug_path) - 1, file_name, sizeof(file_name)); - //DPRINTK("FXG: file_path is %s", file_path); - - /* whether file exist */ - pdata->expansion.fxgmac_dbg_root = debugfs_lookup(file_name, NULL); - if (!pdata->expansion.fxgmac_dbg_root) - { - /* create file */ - pdata->expansion.fxgmac_dbg_root = debugfs_create_dir(file_name, NULL); - if (IS_ERR(pdata->expansion.fxgmac_dbg_root)) - DPRINTK("fxgmac init of debugfs failed\n"); - - break; - } - } -} - -/** - * fxgmac_dbg_exit - clean out the driver's debugfs entries - **/ -void fxgmac_dbg_exit(struct fxgmac_pdata *pdata) -{ - if (pdata->expansion.fxgmac_dbg_root) - debugfs_remove_recursive(pdata->expansion.fxgmac_dbg_root); -} - -#endif /* HAVE_XLGMAC_DEBUG_FS */ diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-desc.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-desc.c deleted file mode 100644 index d030b6eb9fc3c..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-desc.c +++ /dev/null @@ -1,1254 +0,0 @@ -/*++ - -Copyright (c) 2021 Motorcomm Corporation. -Confidential and Proprietary. All rights reserved. - -This is Motorcomm Corporation NIC driver relevant files. Please don't copy, modify, -distribute without commercial permission. - ---*/ - - -#include "fuxi-gmac.h" -#include "fuxi-gmac-reg.h" - -#if defined(UEFI) -#include "nic_sw.h" -#elif defined(_WIN32) || defined(_WIN64) -#include "fuxi-mp.h" -#endif - -static void fxgmac_unmap_desc_data(struct fxgmac_pdata* pdata, - struct fxgmac_desc_data* desc_data) -{ -#ifndef LINUX - pdata = pdata; - desc_data = desc_data; -#else - if (desc_data->skb_dma) { - if (desc_data->mapped_as_page) { - dma_unmap_page(pdata->dev, desc_data->skb_dma, - desc_data->skb_dma_len, DMA_TO_DEVICE); - } - else { - dma_unmap_single(pdata->dev, desc_data->skb_dma, - desc_data->skb_dma_len, DMA_TO_DEVICE); - } - desc_data->skb_dma = 0; - desc_data->skb_dma_len = 0; - } - - if (desc_data->rx.buf.dma_base) { - dma_unmap_single(pdata->dev, desc_data->rx.buf.dma_base, - pdata->rx_buf_size, DMA_FROM_DEVICE); - desc_data->rx.buf.dma_base = 0; - } - - if (desc_data->skb) { - dev_kfree_skb_any(desc_data->skb); - desc_data->skb = NULL; - } - -#if 0 - if (desc_data->rx.hdr.pa.pages) - put_page(desc_data->rx.hdr.pa.pages); - - if (desc_data->rx.hdr.pa_unmap.pages) { - dma_unmap_page(pdata->dev, desc_data->rx.hdr.pa_unmap.pages_dma, - desc_data->rx.hdr.pa_unmap.pages_len, - DMA_FROM_DEVICE); - put_page(desc_data->rx.hdr.pa_unmap.pages); - } - - if (desc_data->rx.buf.pa.pages) - put_page(desc_data->rx.buf.pa.pages); - - if (desc_data->rx.buf.pa_unmap.pages) { - dma_unmap_page(pdata->dev, desc_data->rx.buf.pa_unmap.pages_dma, - desc_data->rx.buf.pa_unmap.pages_len, - DMA_FROM_DEVICE); - put_page(desc_data->rx.buf.pa_unmap.pages); - } -#endif - memset(&desc_data->tx, 0, sizeof(desc_data->tx)); - memset(&desc_data->rx, 0, sizeof(desc_data->rx)); - - desc_data->mapped_as_page = 0; - - if (desc_data->state_saved) { - desc_data->state_saved = 0; - desc_data->state.skb = NULL; - desc_data->state.len = 0; - desc_data->state.error = 0; - } -#endif -} - -static void fxgmac_free_ring(struct fxgmac_pdata* pdata, - struct fxgmac_ring* ring) -{ -#ifndef LINUX - pdata = pdata; - - if (!ring) - return; -#else - struct fxgmac_desc_data* desc_data; - unsigned int i; - - if (!ring) - return; - - if (ring->desc_data_head) { - for (i = 0; i < ring->dma_desc_count; i++) { - desc_data = FXGMAC_GET_DESC_DATA(ring, i); - fxgmac_unmap_desc_data(pdata, desc_data); - } - - kfree(ring->desc_data_head); - ring->desc_data_head = NULL; - } - -#if 0 - 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; - } -#endif - - if (ring->dma_desc_head) { - dma_free_coherent(pdata->dev, - (sizeof(struct fxgmac_dma_desc) * - ring->dma_desc_count), - ring->dma_desc_head, - ring->dma_desc_head_addr); - ring->dma_desc_head = NULL; - } -#endif -} - -static int fxgmac_init_ring(struct fxgmac_pdata* pdata, - struct fxgmac_ring* ring, - unsigned int dma_desc_count) -{ - if (!ring) - return 0; - -#ifndef LINUX - pdata = pdata; - dma_desc_count = dma_desc_count; - ring->dma_desc_count = 0; - - return 0; -#else - /* Descriptors */ - ring->dma_desc_count = dma_desc_count; - ring->dma_desc_head = dma_alloc_coherent(pdata->dev, - (sizeof(struct fxgmac_dma_desc) * - dma_desc_count), - &ring->dma_desc_head_addr, - GFP_KERNEL); - if (!ring->dma_desc_head) - return -ENOMEM; - - /* Array of descriptor data */ - ring->desc_data_head = kcalloc(dma_desc_count, - sizeof(struct fxgmac_desc_data), - GFP_KERNEL); - if (!ring->desc_data_head) - return -ENOMEM; - - netif_dbg(pdata, drv, pdata->netdev, - "dma_desc_head=%p, dma_desc_head_addr=%pad, desc_data_head=%p\n", - ring->dma_desc_head, - &ring->dma_desc_head_addr, - ring->desc_data_head); - - return 0; -#endif -} - -static void fxgmac_free_rings(struct fxgmac_pdata* pdata) -{ - struct fxgmac_channel* channel; - unsigned int i; - - if (!pdata->channel_head) - return; - - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - fxgmac_free_ring(pdata, channel->tx_ring); - fxgmac_free_ring(pdata, channel->rx_ring); - } -} - -static int fxgmac_alloc_rings(struct fxgmac_pdata* pdata) -{ - struct fxgmac_channel* channel; - unsigned int i; - int ret; - - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - netif_dbg(pdata, drv, pdata->netdev, "%s - Tx ring:\n", - channel->name); - - if (i < pdata->tx_ring_count) - { - ret = fxgmac_init_ring(pdata, channel->tx_ring, - pdata->tx_desc_count); - - if (ret) { - netdev_alert(pdata->netdev, "error initializing Tx ring"); - goto err_init_ring; - } - } - - netif_dbg(pdata, drv, pdata->netdev, "%s - Rx ring:\n", channel->name); - - ret = fxgmac_init_ring(pdata, channel->rx_ring, - pdata->rx_desc_count); - if (ret) { - netdev_alert(pdata->netdev, - "error initializing Rx ring\n"); - goto err_init_ring; - } - if(netif_msg_drv(pdata)) DPRINTK("fxgmac_alloc_ring..ch=%u,tx_desc_cnt=%u,rx_desc_cnt=%u\n",i,pdata->tx_desc_count,pdata->rx_desc_count); - } - if(netif_msg_drv(pdata)) DPRINTK("alloc_rings callout ok\n"); - - return 0; - -err_init_ring: - fxgmac_free_rings(pdata); - - DPRINTK("alloc_rings callout err,%d\n",ret); - return ret; -} - -#ifdef LINUX -static void fxgmac_free_channels(struct fxgmac_pdata *pdata) -{ - if (!pdata->channel_head) - return; - if(netif_msg_drv(pdata)) DPRINTK("free_channels,tx_ring=%p\n", pdata->channel_head->tx_ring); - kfree(pdata->channel_head->tx_ring); - pdata->channel_head->tx_ring = NULL; - - if(netif_msg_drv(pdata)) DPRINTK("free_channels,rx_ring=%p\n", pdata->channel_head->rx_ring); - kfree(pdata->channel_head->rx_ring); - pdata->channel_head->rx_ring = NULL; - - if(netif_msg_drv(pdata)) DPRINTK("free_channels,channel=%p\n", pdata->channel_head); - kfree(pdata->channel_head); - - pdata->channel_head = NULL; - //comment out below line for that, channel_count is initialized only once in hw_init() - //pdata->channel_count = 0; -} -#else -static void fxgmac_free_channels(struct fxgmac_pdata* pdata) -{ - if (!pdata->channel_head) - return; - - //kfree(pdata->channel_head->tx_ring); - pdata->channel_head->tx_ring = NULL; - - //kfree(pdata->channel_head->rx_ring); - pdata->channel_head->rx_ring = NULL; - - //kfree(pdata->channel_head); - - pdata->channel_head = NULL; - pdata->channel_count = 0; -} -#endif - -#if defined(UEFI) -static int fxgmac_alloc_channels(struct fxgmac_pdata* pdata) -{ - struct fxgmac_channel* channel_head, * channel; - struct fxgmac_ring* tx_ring, * rx_ring; - int ret = -ENOMEM; - unsigned int i; - EFI_STATUS Status; - UINT64 vir_addr; - UINT64 cache_sz = CACHE_ALIGN_SZ; - PADAPTER adpt = (PADAPTER)pdata->pAdapter; - // - // Allocate memory for transmit and receive resources. - // - DEBUGPRINT(INIT, "[%a,%a,%d]:\n",__FILE__, __func__,__LINE__); - Status = adpt->Io_Function->AllocateBuffer( - adpt->Io_Function, - AllocateAnyPages, - EfiRuntimeServicesData, - UNDI_MEM_PAGES(CHANNEL_MEMORY_NEEDED), - (VOID**)&(adpt->MemoryChannelPtr), - 0 - ); - - if (EFI_ERROR(Status)) { - DEBUGPRINT(INIT, ("Error PCI IO AllocateBuffer returns \n")); - goto err; - } - - DEBUGPRINT(INIT, "[%a,%a,%d]:status=%x,MemoryChannelPtr=%llx\n",__FILE__, __func__,__LINE__,Status,adpt->MemoryChannelPtr); - vir_addr = (adpt->MemoryChannelPtr + cache_sz) & (~(cache_sz - 1)); -#ifdef UEFI_64 - channel_head = (struct fxgmac_channel*)vir_addr; -#else - channel_head = (struct fxgmac_channel*)(UINT32)vir_addr; -#endif - - DEBUGPRINT(INIT, "[%a,%a,%d]:Channel_head=%llx,vir_addr=%llx\n",__FILE__, __func__,__LINE__,channel_head,vir_addr); - netif_dbg(pdata, drv, pdata->netdev, - "channel_head=%p\n", channel_head); - - vir_addr = (vir_addr + 4 * sizeof(struct fxgmac_channel) + cache_sz) & (~(cache_sz - 1)); -#ifdef UEFI_64 - tx_ring = (struct fxgmac_ring*)vir_addr; -#else - tx_ring = (struct fxgmac_ring*)(UINT32)vir_addr; -#endif - - - vir_addr = (vir_addr + 4 * sizeof(struct fxgmac_ring) + cache_sz) & (~(cache_sz - 1)); -#ifdef UEFI_64 - rx_ring = (struct fxgmac_ring*)vir_addr; -#else - rx_ring = (struct fxgmac_ring*)(UINT32)vir_addr; -#endif - - DEBUGPRINT(INIT, "[%a,%a,%d]:Channel_head=%llx,*channel_head=%llx,vir_addr=%llx,tx_ring=%llx,rx_ring=%llx,channelcount=%llx,pdata=%llx\n",__FILE__, __func__,__LINE__,channel_head,*channel_head,vir_addr,tx_ring,rx_ring,pdata->channel_count,&channel_head->pdata); - for (i = 0, channel = channel_head; i < pdata->channel_count; - i++, channel++) { - //snprintf(channel->name, sizeof(channel->name), "channel-%u", i); - //RtlStringCchPrintfA(channel->name, sizeof(channel->name), "channel-%u", i); - //netif_dbg(pdata, drv, pdata->netdev,"channel-%u\n", i); - - DEBUGPRINT(INIT, "[%a,%a,%d]:channel=%llx,&channel->pdata=%llx\n",__FILE__, __func__,__LINE__,channel,&channel->pdata); - channel->pdata = pdata; - DEBUGPRINT(INIT, "[%a,%d]:channel->pdata:%llx,pdata:%llx\n",__func__,__LINE__,channel->pdata,pdata); - channel->queue_index = i; - channel->dma_regs = pdata->mac_regs + DMA_CH_BASE + - (DMA_CH_INC * i); - - if (pdata->per_channel_irq) { - /* Get the per DMA interrupt */ - ret = pdata->channel_irq[i]; - if (ret < 0) { - netdev_err(pdata->netdev, - "get_irq %u failed\n", - i + 1); - goto err; - } - channel->dma_irq = ret; - } - - if (i < pdata->tx_ring_count) - channel->tx_ring = tx_ring++; - - if (i < pdata->rx_ring_count) - channel->rx_ring = rx_ring++; - netif_dbg(pdata, drv, pdata->netdev, - ""STR_FORMAT": dma_regs=%p, tx_ring=%p, rx_ring=%p\n", - channel->name, channel->dma_regs, - channel->tx_ring, channel->rx_ring); - - DEBUGPRINT(INIT, "[%a,%d]:Channel_dma_regs=%llx,channel txring=%llx,channel rx_ring=%llx,i=%llx,channel_count=%llx\n", __func__,__LINE__,channel->dma_regs,channel->tx_ring,channel->rx_ring,i,pdata->channel_count); - } - - pdata->channel_head = channel_head; - - return 0; - - err: - return ret; -} -#elif defined(LINUX) -static int fxgmac_alloc_channels(struct fxgmac_pdata *pdata) -{ - struct fxgmac_channel *channel_head, *channel; - struct fxgmac_ring *tx_ring, *rx_ring; - int ret = -ENOMEM; - unsigned int i; - -#ifdef CONFIG_PCI_MSI - u32 msix = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_MSIX_POS, - FXGMAC_FLAG_MSIX_LEN); -#endif - - channel_head = kcalloc(pdata->channel_count, - sizeof(struct fxgmac_channel), GFP_KERNEL); - if(netif_msg_drv(pdata)) DPRINTK("alloc_channels,channel_head=%p,size=%d*%ld\n", channel_head, pdata->channel_count,sizeof(struct fxgmac_channel)); - - if (!channel_head) - return ret; - - netif_dbg(pdata, drv, pdata->netdev, - "channel_head=%p\n", channel_head); - - tx_ring = kcalloc(pdata->tx_ring_count, sizeof(struct fxgmac_ring), - GFP_KERNEL); - if (!tx_ring) - goto err_tx_ring; - - if(netif_msg_drv(pdata)) DPRINTK("alloc_channels,tx_ring=%p,size=%d*%ld\n", tx_ring, pdata->tx_ring_count,sizeof(struct fxgmac_ring)); - rx_ring = kcalloc(pdata->rx_ring_count, sizeof(struct fxgmac_ring), - GFP_KERNEL); - if (!rx_ring) - goto err_rx_ring; - - if(netif_msg_drv(pdata)) DPRINTK("alloc_channels,rx_ring=%p,size=%d*%ld\n", rx_ring, pdata->rx_ring_count,sizeof(struct fxgmac_ring)); - //DPRINTK("fxgmac_alloc_channels ch_num=%d,rxring=%d,txring=%d\n",pdata->channel_count, pdata->rx_ring_count,pdata->tx_ring_count); - - for (i = 0, channel = channel_head; i < pdata->channel_count; - i++, channel++) { - snprintf(channel->name, sizeof(channel->name), "channel-%u", i); - channel->pdata = pdata; - channel->queue_index = i; - channel->dma_regs = pdata->mac_regs + DMA_CH_BASE + - (DMA_CH_INC * i); - - if (pdata->per_channel_irq) { - /* Get the per DMA interrupt */ -#ifdef CONFIG_PCI_MSI - //20210526 for MSIx - if(msix) { - pdata->channel_irq[i] = pdata->expansion.msix_entries[i].vector; - if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { - pdata->channel_irq[FXGMAC_MAX_DMA_CHANNELS] = pdata->expansion.msix_entries[FXGMAC_MAX_DMA_CHANNELS].vector; - - if (pdata->channel_irq[FXGMAC_MAX_DMA_CHANNELS] < 0) { - netdev_err(pdata->netdev, - "get_irq %u for tx failed\n", - i + 1); - goto err_irq; - } - - channel->expansion.dma_irq_tx = pdata->channel_irq[FXGMAC_MAX_DMA_CHANNELS]; - DPRINTK("fxgmac_alloc_channels, for MSIx, channel %d dma_irq_tx=%u\n", i, channel->expansion.dma_irq_tx); - } - } -#endif - ret = pdata->channel_irq[i]; - if (ret < 0) { - netdev_err(pdata->netdev, - "get_irq %u failed\n", - i + 1); - goto err_irq; - } - channel->dma_irq = ret; - DPRINTK("fxgmac_alloc_channels, for MSIx, channel %d dma_irq=%u\n", i, channel->dma_irq); - } - - if (i < pdata->tx_ring_count) - channel->tx_ring = tx_ring++; - - if (i < pdata->rx_ring_count) - channel->rx_ring = rx_ring++; - - netif_dbg(pdata, drv, pdata->netdev, - "%s: dma_regs=%p, tx_ring=%p, rx_ring=%p\n", - channel->name, channel->dma_regs, - channel->tx_ring, channel->rx_ring); - } - - pdata->channel_head = channel_head; - - if(netif_msg_drv(pdata)) DPRINTK("alloc_channels callout ok\n"); - return 0; - -err_irq: - kfree(rx_ring); - -err_rx_ring: - kfree(tx_ring); - -err_tx_ring: - kfree(channel_head); - - DPRINTK("fxgmac alloc_channels callout err,%d\n",ret); - return ret; -} -#elif defined(_WIN32) || defined(_WIN64) -static int fxgmac_alloc_channels(struct fxgmac_pdata* pdata) -{ - struct fxgmac_channel* channel_head, * channel; - struct fxgmac_ring* tx_ring, * rx_ring; - PMP_ADAPTER pAdapter = (PMP_ADAPTER)pdata->pAdapter; - int ret = -ENOMEM; - unsigned int i; - - //channel_head = kcalloc(pdata->channel_count, - // sizeof(struct fxgmac_channel), GFP_KERNEL); - //if (!channel_head) - // return ret; - - channel_head = &pAdapter->MpChannelRingResources.fx_channel[0]; - - netif_dbg(pdata, drv, pdata->netdev, - "channel_head=%p\n", channel_head); - - //tx_ring = kcalloc(pdata->tx_ring_count, sizeof(struct fxgmac_ring), - // GFP_KERNEL); - //if (!tx_ring) - // goto err_tx_ring; - tx_ring = &pAdapter->MpChannelRingResources.fx_tx_ring[0]; - - //rx_ring = kcalloc(pdata->rx_ring_count, sizeof(struct fxgmac_ring), - // GFP_KERNEL); - //if (!rx_ring) - // goto err_rx_ring; - rx_ring = &pAdapter->MpChannelRingResources.fx_rx_ring[0]; - - for (i = 0, channel = channel_head; i < pdata->channel_count; - i++, channel++) { - //snprintf(channel->name, sizeof(channel->name), "channel-%u", i); - RtlStringCchPrintfA(channel->name, sizeof(channel->name), "channel-%u", i); - - channel->pdata = pdata; - channel->queue_index = i; - channel->dma_regs = pdata->mac_regs + DMA_CH_BASE + - (DMA_CH_INC * i); - - if (pdata->per_channel_irq) { - /* Get the per DMA interrupt */ - ret = pdata->channel_irq[i]; - if (ret < 0) { - netdev_err(pdata->netdev, - "get_irq %u failed\n", - i + 1); - goto err_irq; - } - channel->dma_irq = ret; - } - - if (i < pdata->tx_ring_count) - channel->tx_ring = tx_ring++; - - if (i < pdata->rx_ring_count) - channel->rx_ring = rx_ring++; - - netif_dbg(pdata, drv, pdata->netdev, - "%s: dma_regs=%p, tx_ring=%p, rx_ring=%p\n", - channel->name, channel->dma_regs, - channel->tx_ring, channel->rx_ring); - } - - pdata->channel_head = channel_head; - - return 0; - -err_irq: - //kfree(rx_ring); - -//err_rx_ring: - //kfree(tx_ring); - -//err_tx_ring: - //kfree(channel_head); - - return ret; - -} -#elif defined(UBOOT) -static int fxgmac_alloc_channels(struct fxgmac_pdata* pdata) -{ - struct fxgmac_channel * channel; - unsigned int i; - - for (i = 0; i < pdata->channel_count; i++) - { - //snprintf(channel->name, sizeof(channel->name), "channel-%u", i); - //RtlStringCchPrintfA(channel->name, sizeof(channel->name), "channel-%u" , i); - //netif_dbg(pdata, drv, pdata->netdev,"channel-%u\n", i); - channel = pdata->channel_head; - - channel->pdata = pdata; - channel->queue_index = i; - channel->dma_regs = pdata->mac_regs + DMA_CH_BASE + - (DMA_CH_INC * i); - - /* set tx/rx channel*/ -#if 1 - pdata->expansion.tx_channel = pdata->channel_head; - - pdata->expansion.rx_channel = pdata->channel_head; -#else - if(i == 0) - pdata->tx_channel = &pdata->channel_head[i]; - else - pdata->rx_channel = &pdata->channel_head[i]; -#endif - } - return 0; -} -#else -static struct fxgmac_channel fx_channel[4]; -static struct fxgmac_ring fx_tx_ring[4]; -static struct fxgmac_ring fx_rx_ring[4]; - -static int fxgmac_alloc_channels(struct fxgmac_pdata* pdata) -{ - struct fxgmac_channel* channel_head, * channel; - struct fxgmac_ring* tx_ring, * rx_ring; - int ret = -ENOMEM; - unsigned int i; - - //channel_head = kcalloc(pdata->channel_count, - // sizeof(struct fxgmac_channel), GFP_KERNEL); - //if (!channel_head) - // return ret; - channel_head = &fx_channel[0]; - - netif_dbg(pdata, drv, pdata->netdev, - "channel_head=%p\n", channel_head); - - //tx_ring = kcalloc(pdata->tx_ring_count, sizeof(struct fxgmac_ring), - // GFP_KERNEL); - //if (!tx_ring) - // goto err_tx_ring; - tx_ring = &fx_tx_ring[0]; - - //rx_ring = kcalloc(pdata->rx_ring_count, sizeof(struct fxgmac_ring), - // GFP_KERNEL); - //if (!rx_ring) - // goto err_rx_ring; - rx_ring = &fx_rx_ring[0]; - - for (i = 0, channel = channel_head; i < pdata->channel_count; - i++, channel++) { - //snprintf(channel->name, sizeof(channel->name), "channel-%u", i); - //RtlStringCchPrintfA(channel->name, sizeof(channel->name), "channel-%u", i); - - channel->pdata = pdata; - channel->queue_index = i; - channel->dma_regs = pdata->mac_regs + DMA_CH_BASE + - (DMA_CH_INC * i); - - if (pdata->per_channel_irq) { - /* Get the per DMA interrupt */ - ret = pdata->channel_irq[i]; - if (ret < 0) { - netdev_err(pdata->netdev, - "get_irq %u failed\n", - i + 1); - goto err_irq; - } - channel->dma_irq = ret; - } - - if (i < pdata->tx_ring_count) - channel->tx_ring = tx_ring++; - - if (i < pdata->rx_ring_count) - channel->rx_ring = rx_ring++; - - netif_dbg(pdata, drv, pdata->netdev, - "%s: dma_regs=%p, tx_ring=%p, rx_ring=%p\n", - channel->name, channel->dma_regs, - channel->tx_ring, channel->rx_ring); - } - - pdata->channel_head = channel_head; - - return 0; - -err_irq: - //kfree(rx_ring); - - //err_rx_ring: - //kfree(tx_ring); - - //err_tx_ring: - //kfree(channel_head); - - return ret; -} -#endif - -static void fxgmac_free_channels_and_rings(struct fxgmac_pdata* pdata) -{ - fxgmac_free_rings(pdata); - - fxgmac_free_channels(pdata); -} - -static int fxgmac_alloc_channels_and_rings(struct fxgmac_pdata* pdata) -{ - int ret; - - ret = fxgmac_alloc_channels(pdata); - if (ret) - goto err_alloc; - - ret = fxgmac_alloc_rings(pdata); - if (ret) - goto err_alloc; - - return 0; - -err_alloc: - fxgmac_free_channels_and_rings(pdata); - - return ret; -} - -#if 0 -static int fxgmac_alloc_pages(struct fxgmac_pdata *pdata, - struct fxgmac_page_alloc *pa, - gfp_t gfp, int order) -{ - struct page *pages = NULL; - dma_addr_t pages_dma; - - /* Try to obtain pages, decreasing order if necessary */ - gfp |= __GFP_COMP | __GFP_NOWARN; - 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); - if (dma_mapping_error(pdata->dev, pages_dma)) { - put_page(pages); - return -ENOMEM; - } - - pa->pages = pages; - pa->pages_len = PAGE_SIZE << order; - pa->pages_offset = 0; - pa->pages_dma = pages_dma; - - return 0; -} -#endif -#if !(defined(UEFI) || defined(LINUX) || defined(UBOOT)) -static void fxgmac_set_buffer_data(struct fxgmac_buffer_data* bd, - struct fxgmac_page_alloc* pa, - unsigned int len) -{ -#ifndef LINUX - bd = bd; - pa = pa; - len = len; -#else - get_page(pa->pages); - bd->pa = *pa; - - bd->dma_base = pa->pages_dma; - bd->dma_off = 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; - } -#endif -} -#endif - -static int fxgmac_map_rx_buffer(struct fxgmac_pdata* pdata, - struct fxgmac_ring* ring, - struct fxgmac_desc_data* desc_data) -{ -#ifndef LINUX - pdata = pdata; - ring = ring; - desc_data = desc_data; -#else -#if 0 - int order, ret; - - if (!ring->rx_hdr_pa.pages) { - ret = fxgmac_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 = fxgmac_alloc_pages(pdata, &ring->rx_buf_pa, - GFP_ATOMIC, order); - if (ret) - return ret; - } - - /* Set up the header page info */ - fxgmac_set_buffer_data(&desc_data->rx.hdr, &ring->rx_hdr_pa, - FXGMAC_SKB_ALLOC_SIZE); - - /* Set up the buffer page info */ - fxgmac_set_buffer_data(&desc_data->rx.buf, &ring->rx_buf_pa, - pdata->rx_buf_size); -#endif - struct sk_buff *skb; - skb = __netdev_alloc_skb_ip_align(pdata->netdev, pdata->rx_buf_size, GFP_ATOMIC); - if (!skb) { - netdev_err(pdata->netdev, - "%s: Rx init fails; skb is NULL\n", __func__); - return -ENOMEM; - } - - desc_data->skb = skb; - desc_data->rx.buf.dma_base = dma_map_single(pdata->dev, skb->data, pdata->rx_buf_size, DMA_FROM_DEVICE); - if (dma_mapping_error(pdata->dev, desc_data->rx.buf.dma_base)) { - netdev_err(pdata->netdev, "%s: DMA mapping error\n", __func__); - dev_kfree_skb_any(skb); - return -EINVAL; - } - -#endif - return 0; -} - -#ifdef UBOOT -static void yt6801_desc_reset(struct fxgmac_dma_desc *desc_data) -{ - /* 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) - */ - desc_data->desc0 = 0; - desc_data->desc1 = 0; - desc_data->desc2 = 0; - desc_data->desc3 = 0; - - /* Make sure ownership is written to the descriptor */ - //dma_wmb(); -} - -static void fxgmac_hw_tx_desc_init(struct fxgmac_channel *channel) -{ - struct fxgmac_dma_desc *desc_data; - struct fxgmac_pdata * pdata = channel->pdata; - unsigned int i; - - /* Initialize all descriptors */ - for (i = 0; i < NIC_DEF_TBDS; i++) { - desc_data = pdata->expansion.tx_desc_list + i; - - /* Initialize Tx descriptor */ - yt6801_desc_reset(desc_data); - } - - ///* Update the total number of Tx descriptors */ - writereg(pdata->pAdapter, NIC_DEF_TBDS - 1, FXGMAC_DMA_REG(channel, DMA_CH_TDRLR)); - -#if 0 - DbgPrintF(MP_TRACE, "tx_desc_list:%p\n", pdata->tx_desc_list); - DbgPrintF(MP_TRACE, "bus_to_phys:%llx\n", bus_to_phys(pdata->pdev, - (pci_addr_t)(unsigned long)pdata->tx_desc_list));//adpt->TbdPhyAddr - DbgPrintF(MP_TRACE, "lower_32_bits:%x\n", lower_32_bits(bus_to_phys(pdata->pdev, - (pci_addr_t)(unsigned long)pdata->tx_desc_list)));//adpt->TbdPhyAddr - DbgPrintF(MP_TRACE, "dma tdlr lo:%p\n", FXGMAC_DMA_REG(channel, DMA_CH_TDLR_LO)); -#endif - /* Update the starting address of descriptor ring */ - writereg(pdata->pAdapter, upper_32_bits(cpu_to_le64(bus_to_phys(pdata->pdev, - (pci_addr_t)(unsigned long)pdata->expansion.tx_desc_list))),//adpt->TbdPhyAddr - FXGMAC_DMA_REG(channel, DMA_CH_TDLR_HI)); - writereg(pdata->pAdapter, lower_32_bits(cpu_to_le64(bus_to_phys(pdata->pdev, - (pci_addr_t)(unsigned long)pdata->expansion.tx_desc_list))),//adpt->TbdPhyAddr - FXGMAC_DMA_REG(channel, DMA_CH_TDLR_LO)); -#if 0 - DbgPrintF(MP_TRACE, "Read tx starting high address:%x\n", - readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_TDLR_HI))); - DbgPrintF(MP_TRACE, "Read tx starting low address:%x\n", - readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_TDLR_LO))); -#endif -} - -static void fxgmac_tx_desc_init(struct fxgmac_pdata* pdata) -{ - fxgmac_hw_tx_desc_init(pdata->expansion.tx_channel); -} - -static void fxgmac_hw_rx_desc_init(struct fxgmac_channel *channel) -{ - struct fxgmac_pdata *pdata = channel->pdata; - struct fxgmac_dma_desc *desc_data; - unsigned int i; - uint64_t HwRbdPa; - - /* Initialize all descriptors */ - for (i = 0; i < NIC_DEF_RECV_BUFFERS; i++) { - desc_data = pdata->expansion.rx_desc_list + i; - - /* Initialize Rx descriptor */ - yt6801_desc_reset(desc_data); - desc_data->desc0 = lower_32_bits(bus_to_phys(pdata->pdev, (pci_addr_t)(unsigned long)(pdata->expansion.rx_buffer))); - desc_data->desc1 = upper_32_bits(bus_to_phys(pdata->pdev, (pci_addr_t)(unsigned long)(pdata->expansion.rx_buffer))); - desc_data->desc3 = FXGMAC_SET_REG_BITS_LE( - desc_data->desc3, - RX_NORMAL_DESC3_BUF2V_POS, - RX_NORMAL_DESC3_BUF2V_LEN, - 1); - desc_data->desc3 = FXGMAC_SET_REG_BITS_LE( - desc_data->desc3, - RX_NORMAL_DESC3_BUF1V_POS, - RX_NORMAL_DESC3_BUF1V_LEN, - 1); - desc_data->desc3 = FXGMAC_SET_REG_BITS_LE( - desc_data->desc3, - RX_NORMAL_DESC3_OWN_POS, - RX_NORMAL_DESC3_OWN_LEN, - 1); - } - - /* Update the total number of Rx descriptors */ - writereg(pdata->pAdapter, NIC_DEF_RECV_BUFFERS - 1, FXGMAC_DMA_REG(channel, DMA_CH_RDRLR)); -#if 0 - DbgPrintF(MP_TRACE, "rx_desc_list:%p\n", pdata->rx_desc_list); - DbgPrintF(MP_TRACE, "bus_to_phys:%llx\n", bus_to_phys(pdata->pdev, - (pci_addr_t)(unsigned long)pdata->rx_desc_list));//adpt->TbdPhyAddr - DbgPrintF(MP_TRACE, "lower_32_bits:%x\n", lower_32_bits(bus_to_phys(pdata->pdev, - (pci_addr_t)(unsigned long)pdata->rx_desc_list)));//adpt->TbdPhyAddr - DbgPrintF(MP_TRACE, "dma rdlr lo:%p\n", FXGMAC_DMA_REG(channel, DMA_CH_RDLR_LO)); -#endif - /* Update the starting address of descriptor ring */ - writereg(pdata->pAdapter, upper_32_bits(cpu_to_le64(bus_to_phys(pdata->pdev, - (pci_addr_t)(unsigned long)pdata->expansion.rx_desc_list))), - FXGMAC_DMA_REG(channel, DMA_CH_RDLR_HI)); - writereg(pdata->pAdapter, lower_32_bits(cpu_to_le64(bus_to_phys(pdata->pdev, - (pci_addr_t)(unsigned long)pdata->expansion.rx_desc_list))), - FXGMAC_DMA_REG(channel, DMA_CH_RDLR_LO)); -#if 0 - DbgPrintF(MP_TRACE, "Read rx starting high address:%x\n", - readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_RDLR_HI))); - DbgPrintF(MP_TRACE, "Read rx starting low address:%x\n", - readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_RDLR_LO))); -#endif - - HwRbdPa = (uint64_t)pdata->expansion.rx_desc_list + (NIC_DEF_RECV_BUFFERS) * sizeof(struct fxgmac_dma_desc); - /* Update the Rx Descriptor Tail Pointer */ - writereg(pdata->pAdapter, lower_32_bits((unsigned long)HwRbdPa), FXGMAC_DMA_REG(channel, DMA_CH_RDTR_LO)); - -} - - -static void fxgmac_rx_desc_init(struct fxgmac_pdata* pdata) -{ - fxgmac_hw_rx_desc_init(pdata->expansion.rx_channel); -} - -#else -static void fxgmac_tx_desc_init(struct fxgmac_pdata* pdata) -{ -#ifndef LINUX - struct fxgmac_hw_ops* hw_ops = &pdata->hw_ops; - struct fxgmac_channel* channel; - channel = pdata->channel_head; - hw_ops->tx_desc_init(channel); -#else - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - struct fxgmac_desc_data *desc_data; - struct fxgmac_dma_desc *dma_desc; - struct fxgmac_channel *channel; - struct fxgmac_ring *ring; - dma_addr_t dma_desc_addr; - unsigned int i, j; - - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - ring = channel->tx_ring; - if (!ring) - break; - - /* reset the tx timer status. 20220104 */ - channel->tx_timer_active = 0; - - dma_desc = ring->dma_desc_head; - dma_desc_addr = ring->dma_desc_head_addr; - - for (j = 0; j < ring->dma_desc_count; j++) { - desc_data = FXGMAC_GET_DESC_DATA(ring, j); - - desc_data->dma_desc = dma_desc; - desc_data->dma_desc_addr = dma_desc_addr; - - dma_desc++; - dma_desc_addr += sizeof(struct fxgmac_dma_desc); - } - - ring->cur = 0; - ring->dirty = 0; - memset(&ring->tx, 0, sizeof(ring->tx)); - - hw_ops->tx_desc_init(channel); - } -#endif -} - -static void fxgmac_rx_desc_init(struct fxgmac_pdata* pdata) -{ -#ifndef LINUX - struct fxgmac_hw_ops* hw_ops = &pdata->hw_ops; - struct fxgmac_channel* channel; - int Qid = 0; - - channel = pdata->channel_head; - for (Qid = 0; Qid < RSS_Q_COUNT; Qid++) - { - hw_ops->rx_desc_init(channel + Qid); - } -#else - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - struct fxgmac_desc_data *desc_data; - struct fxgmac_dma_desc *dma_desc; - struct fxgmac_channel *channel; - struct fxgmac_ring *ring; - dma_addr_t dma_desc_addr; - unsigned int i, j; - - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - ring = channel->rx_ring; - if (!ring) - break; - - dma_desc = ring->dma_desc_head; - dma_desc_addr = ring->dma_desc_head_addr; - - for (j = 0; j < ring->dma_desc_count; j++) { - desc_data = FXGMAC_GET_DESC_DATA(ring, j); - - desc_data->dma_desc = dma_desc; - desc_data->dma_desc_addr = dma_desc_addr; - - if (fxgmac_map_rx_buffer(pdata, ring, desc_data)) - break; - - dma_desc++; - dma_desc_addr += sizeof(struct fxgmac_dma_desc); - } - - ring->cur = 0; - ring->dirty = 0; - - hw_ops->rx_desc_init(channel); - } -#endif -} -#endif -#ifdef LINUX -static int fxgmac_map_tx_skb(struct fxgmac_channel *channel, - struct sk_buff *skb) -{ - struct fxgmac_pdata *pdata = channel->pdata; - struct fxgmac_ring *ring = channel->tx_ring; - unsigned int start_index, cur_index; - struct fxgmac_desc_data *desc_data; - unsigned int offset, datalen, len; - struct fxgmac_pkt_info *pkt_info; -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) ) - skb_frag_t *frag; -#else - struct skb_frag_struct *frag; -#endif - unsigned int tso, vlan; - dma_addr_t skb_dma; - unsigned int i; -#if 0 - void* addr; - struct skb_shared_info *info = skb_shinfo(skb); -#endif - - offset = 0; - start_index = ring->cur; - cur_index = ring->cur; - - pkt_info = &ring->pkt_info; - pkt_info->desc_count = 0; - pkt_info->length = 0; - - tso = FXGMAC_GET_REG_BITS(pkt_info->attributes, - TX_PACKET_ATTRIBUTES_TSO_ENABLE_POS, - TX_PACKET_ATTRIBUTES_TSO_ENABLE_LEN); - vlan = FXGMAC_GET_REG_BITS(pkt_info->attributes, - TX_PACKET_ATTRIBUTES_VLAN_CTAG_POS, - TX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN); - - /* Save space for a context descriptor if needed */ - if ((tso && (pkt_info->mss != ring->tx.cur_mss)) || - (vlan && (pkt_info->vlan_ctag != ring->tx.cur_vlan_ctag))) - { - cur_index = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); - } - desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); - - if (tso) { - /* Map the TSO header */ - skb_dma = dma_map_single(pdata->dev, skb->data, - pkt_info->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; - } - desc_data->skb_dma = skb_dma; - desc_data->skb_dma_len = pkt_info->header_len; - netif_dbg(pdata, tx_queued, pdata->netdev, - "skb header: index=%u, dma=%pad, len=%u\n", - cur_index, &skb_dma, pkt_info->header_len); - - offset = pkt_info->header_len; - - pkt_info->length += pkt_info->header_len; - - cur_index = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); - desc_data = FXGMAC_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, FXGMAC_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; - } - desc_data->skb_dma = skb_dma; - desc_data->skb_dma_len = len; - netif_dbg(pdata, tx_queued, pdata->netdev, - "skb data: index=%u, dma=%pad, len=%u\n", - cur_index, &skb_dma, len); - - datalen -= len; - offset += len; - - pkt_info->length += len; - - cur_index = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); - desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); - } - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - netif_dbg(pdata, tx_queued, pdata->netdev, - "mapping frag %u\n", i); -#if 0 - frag = info->frags + i; - len = skb_frag_size(frag); - addr = skb_frag_address(frag); -#else - frag = &skb_shinfo(skb)->frags[i]; -#endif - offset = 0; - - for (datalen = skb_frag_size(frag); datalen; ) { - len = min_t(unsigned int, datalen, - FXGMAC_TX_MAX_BUF_SIZE); - -#if 1 - skb_dma = skb_frag_dma_map(pdata->dev, frag, offset, - len, DMA_TO_DEVICE); -#else - skb_dma = dma_map_single(pdata->dev, addr + offset, len, DMA_TO_DEVICE); -#endif - if (dma_mapping_error(pdata->dev, skb_dma)) { - netdev_alert(pdata->netdev, - "skb_frag_dma_map failed\n"); - goto err_out; - } - desc_data->skb_dma = skb_dma; - desc_data->skb_dma_len = len; -#if 1 - desc_data->mapped_as_page = 1; -#endif - netif_dbg(pdata, tx_queued, pdata->netdev, - "skb frag: index=%u, dma=%pad, len=%u\n", - cur_index, &skb_dma, len); - - datalen -= len; - offset += len; - - pkt_info->length += len; - - cur_index = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); - desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); - } - } - - /* Save the skb address in the last entry. We always have some data - * that has been mapped so desc_data is always advanced past the last - * piece of mapped data - use the entry pointed to by cur_index - 1. - */ - desc_data = FXGMAC_GET_DESC_DATA(ring, (cur_index - 1) & (ring->dma_desc_count - 1)); - desc_data->skb = skb; - - /* Save the number of descriptor entries used */ - if (start_index <= cur_index) - pkt_info->desc_count = cur_index - start_index; - else - pkt_info->desc_count = ring->dma_desc_count - start_index + cur_index; - - return pkt_info->desc_count; - -err_out: - while (start_index < cur_index) { - desc_data = FXGMAC_GET_DESC_DATA(ring, start_index); - start_index = FXGMAC_GET_ENTRY(start_index, ring->dma_desc_count); - fxgmac_unmap_desc_data(pdata, desc_data); - } - - return 0; -} -#endif - -void fxgmac_init_desc_ops(struct fxgmac_desc_ops* desc_ops) -{ -#ifdef UBOOT - desc_ops->alloc_channles_and_rings = fxgmac_alloc_channels; -#else - desc_ops->alloc_channles_and_rings = fxgmac_alloc_channels_and_rings; -#endif - desc_ops->free_channels_and_rings = fxgmac_free_channels_and_rings; -#ifndef LINUX - desc_ops->map_tx_skb = NULL; -#else - desc_ops->map_tx_skb = fxgmac_map_tx_skb; -#endif - desc_ops->map_rx_buffer = fxgmac_map_rx_buffer; - desc_ops->unmap_desc_data = fxgmac_unmap_desc_data; - desc_ops->tx_desc_init = fxgmac_tx_desc_init; - desc_ops->rx_desc_init = fxgmac_rx_desc_init; -} diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-ethtool.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-ethtool.c deleted file mode 100644 index 58c9dc5e8927c..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-ethtool.c +++ /dev/null @@ -1,1255 +0,0 @@ -/*++ - -Copyright (c) 2021 Motor-comm Corporation. -Confidential and Proprietary. All rights reserved. - -This is Motor-comm Corporation NIC driver relevant files. Please don't copy, modify, -distribute without commercial permission. - ---*/ - - -#include -#include -#include - -#include "fuxi-gmac.h" -#include "fuxi-gmac-reg.h" - -struct fxgmac_stats_desc { - char stat_string[ETH_GSTRING_LEN]; - int stat_offset; -}; - -#define FXGMAC_STAT(str, var) \ - { \ - str, \ - offsetof(struct fxgmac_pdata, stats.var), \ - } - -static const struct fxgmac_stats_desc fxgmac_gstring_stats[] = { - /* MMC TX counters */ - FXGMAC_STAT("tx_bytes", txoctetcount_gb), - FXGMAC_STAT("tx_bytes_good", txoctetcount_g), - FXGMAC_STAT("tx_packets", txframecount_gb), - FXGMAC_STAT("tx_packets_good", txframecount_g), - FXGMAC_STAT("tx_unicast_packets", txunicastframes_gb), - FXGMAC_STAT("tx_broadcast_packets", txbroadcastframes_gb), - FXGMAC_STAT("tx_broadcast_packets_good", txbroadcastframes_g), - FXGMAC_STAT("tx_multicast_packets", txmulticastframes_gb), - FXGMAC_STAT("tx_multicast_packets_good", txmulticastframes_g), - FXGMAC_STAT("tx_vlan_packets_good", txvlanframes_g), - FXGMAC_STAT("tx_64_byte_packets", tx64octets_gb), - FXGMAC_STAT("tx_65_to_127_byte_packets", tx65to127octets_gb), - FXGMAC_STAT("tx_128_to_255_byte_packets", tx128to255octets_gb), - FXGMAC_STAT("tx_256_to_511_byte_packets", tx256to511octets_gb), - FXGMAC_STAT("tx_512_to_1023_byte_packets", tx512to1023octets_gb), - FXGMAC_STAT("tx_1024_to_max_byte_packets", tx1024tomaxoctets_gb), - FXGMAC_STAT("tx_underflow_errors", txunderflowerror), - FXGMAC_STAT("tx_pause_frames", txpauseframes), - FXGMAC_STAT("tx_single_collision", txsinglecollision_g), - FXGMAC_STAT("tx_multiple_collision", txmultiplecollision_g), - FXGMAC_STAT("tx_deferred_frames", txdeferredframes), - FXGMAC_STAT("tx_late_collision_frames", txlatecollisionframes), - FXGMAC_STAT("tx_excessive_collision_frames", txexcessivecollisionframes), - FXGMAC_STAT("tx_carrier_error_frames", txcarriererrorframes), - FXGMAC_STAT("tx_excessive_deferral_error", txexcessivedeferralerror), - FXGMAC_STAT("tx_oversize_frames_good", txoversize_g), - - /* MMC RX counters */ - FXGMAC_STAT("rx_bytes", rxoctetcount_gb), - FXGMAC_STAT("rx_bytes_good", rxoctetcount_g), - FXGMAC_STAT("rx_packets", rxframecount_gb), - FXGMAC_STAT("rx_unicast_packets_good", rxunicastframes_g), - FXGMAC_STAT("rx_broadcast_packets_good", rxbroadcastframes_g), - FXGMAC_STAT("rx_multicast_packets_good", rxmulticastframes_g), - FXGMAC_STAT("rx_vlan_packets_mac", rxvlanframes_gb), - FXGMAC_STAT("rx_64_byte_packets", rx64octets_gb), - FXGMAC_STAT("rx_65_to_127_byte_packets", rx65to127octets_gb), - FXGMAC_STAT("rx_128_to_255_byte_packets", rx128to255octets_gb), - FXGMAC_STAT("rx_256_to_511_byte_packets", rx256to511octets_gb), - FXGMAC_STAT("rx_512_to_1023_byte_packets", rx512to1023octets_gb), - FXGMAC_STAT("rx_1024_to_max_byte_packets", rx1024tomaxoctets_gb), - FXGMAC_STAT("rx_undersize_packets_good", rxundersize_g), - FXGMAC_STAT("rx_oversize_packets_good", rxoversize_g), - FXGMAC_STAT("rx_crc_errors", rxcrcerror), - FXGMAC_STAT("rx_align_error", rxalignerror), - FXGMAC_STAT("rx_crc_errors_small_packets", rxrunterror), - FXGMAC_STAT("rx_crc_errors_giant_packets", rxjabbererror), - FXGMAC_STAT("rx_length_errors", rxlengtherror), - FXGMAC_STAT("rx_out_of_range_errors", rxoutofrangetype), - FXGMAC_STAT("rx_fifo_overflow_errors", rxfifooverflow), - FXGMAC_STAT("rx_watchdog_errors", rxwatchdogerror), - FXGMAC_STAT("rx_pause_frames", rxpauseframes), - FXGMAC_STAT("rx_receive_error_frames", rxreceiveerrorframe), - FXGMAC_STAT("rx_control_frames_good", rxcontrolframe_g), - - /* Extra counters */ - FXGMAC_STAT("tx_tso_packets", tx_tso_packets), - FXGMAC_STAT("rx_split_header_packets", rx_split_header_packets), - FXGMAC_STAT("tx_process_stopped", tx_process_stopped), - FXGMAC_STAT("rx_process_stopped", rx_process_stopped), - FXGMAC_STAT("tx_buffer_unavailable", tx_buffer_unavailable), - FXGMAC_STAT("rx_buffer_unavailable", rx_buffer_unavailable), - FXGMAC_STAT("fatal_bus_error", fatal_bus_error), - FXGMAC_STAT("tx_vlan_packets_net", tx_vlan_packets), - FXGMAC_STAT("rx_vlan_packets_net", rx_vlan_packets), - FXGMAC_STAT("napi_poll_isr", napi_poll_isr), - FXGMAC_STAT("napi_poll_txtimer", napi_poll_txtimer), - FXGMAC_STAT("alive_cnt_txtimer", cnt_alive_txtimer), - - FXGMAC_STAT("ephy_poll_timer", ephy_poll_timer_cnt), - FXGMAC_STAT("mgmt_int_isr", mgmt_int_isr), -}; - -#define FXGMAC_STATS_COUNT ARRAY_SIZE(fxgmac_gstring_stats) - -static void fxgmac_ethtool_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *drvinfo) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - u32 ver = pdata->hw_feat.version; - u32 sver, devid, userver; - - strscpy(drvinfo->driver, pdata->drv_name, sizeof(drvinfo->driver)); - strscpy(drvinfo->version, pdata->drv_ver, sizeof(drvinfo->version)); - strscpy(drvinfo->bus_info, dev_name(pdata->dev), - sizeof(drvinfo->bus_info)); - /* - * D|DEVID: Indicates the Device family - * U|USERVER: User-defined Version - */ - sver = FXGMAC_GET_REG_BITS(ver, MAC_VR_SVER_POS, - MAC_VR_SVER_LEN); - devid = FXGMAC_GET_REG_BITS(ver, MAC_VR_DEVID_POS, - MAC_VR_DEVID_LEN); - userver = FXGMAC_GET_REG_BITS(ver, MAC_VR_USERVER_POS, - MAC_VR_USERVER_LEN); - /*DPRINTK("xlgma: No userver (%x) here, sver (%x) should be 0x51\n", userver, sver);*/ - snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), - "S.D.U: %x.%x.%x", sver, devid, userver); -} - -static u32 fxgmac_ethtool_get_msglevel(struct net_device *netdev) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - - return pdata->msg_enable; -} - -static void fxgmac_ethtool_set_msglevel(struct net_device *netdev, - u32 msglevel) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - - DPRINTK("fxmac, set msglvl from %08x to %08x\n", pdata->msg_enable, msglevel); - pdata->msg_enable = msglevel; -} - -static void fxgmac_ethtool_get_channels(struct net_device *netdev, - struct ethtool_channels *channel) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); -#if (FXGMAC_RSS_FEATURE_ENABLED) - /* report maximum channels */ - channel->max_combined = FXGMAC_MAX_DMA_CHANNELS; - channel->max_other = 0; - channel->other_count = 0; - - /* record RSS queues */ - channel->combined_count = FXGMAC_MAX_DMA_CHANNELS; - - /* nothing else to report if RSS is disabled */ - if (channel->combined_count == 1) - return; - DPRINTK("fxmac rss, get channels max=(combined %d,other %d),count(combined %d,other %d)\n", channel->max_combined, channel->max_other, channel->combined_count, channel->other_count); -#endif - - channel->max_rx = FXGMAC_MAX_DMA_CHANNELS; - channel->max_tx = FXGMAC_MAX_DMA_CHANNELS; - channel->rx_count = pdata->rx_q_count; - channel->tx_count = pdata->tx_q_count; - DPRINTK("fxmac, get channels max=(rx %d,tx %d),count(%d,%d)\n", channel->max_rx, channel->max_tx, channel->rx_count, channel->tx_count); -} - -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0) ) -static int fxgmac_ethtool_get_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ec, - struct kernel_ethtool_coalesce *kernel_coal, - struct netlink_ext_ack *extack) -#else -static int fxgmac_ethtool_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) -#endif -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - - memset(ec, 0, sizeof(struct ethtool_coalesce)); - ec->rx_coalesce_usecs = pdata->rx_usecs; - ec->tx_coalesce_usecs = pdata->tx_usecs; - /*If we need to assign values to other members, - * we need to modify the supported_coalesce_params of fxgmac_ethtool_ops synchronously - */ - //ec->rx_max_coalesced_frames = pdata->rx_frames; - //ec->tx_max_coalesced_frames = pdata->tx_frames; - - DPRINTK("fxmac, get coalesce\n"); - return 0; -} - -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0) ) -static int fxgmac_ethtool_set_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ec, - struct kernel_ethtool_coalesce *kernel_coal, - struct netlink_ext_ack *extack) -#else -static int fxgmac_ethtool_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) -#endif -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - unsigned int rx_frames, rx_riwt, rx_usecs; - unsigned int tx_frames; - - /* Check for not supported parameters */ - if ((ec->rx_coalesce_usecs_irq) || (ec->rx_max_coalesced_frames_irq) || - (ec->tx_coalesce_usecs_high) || - (ec->tx_max_coalesced_frames_irq) || (ec->tx_coalesce_usecs_irq) || - (ec->stats_block_coalesce_usecs) || (ec->pkt_rate_low) || - (ec->use_adaptive_rx_coalesce) || (ec->use_adaptive_tx_coalesce) || - (ec->rx_max_coalesced_frames_low) || (ec->rx_coalesce_usecs_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_max_coalesced_frames_high) || - (ec->rate_sample_interval)) - return -EOPNOTSUPP; - - rx_usecs = ec->rx_coalesce_usecs; - rx_riwt = hw_ops->usec_to_riwt(pdata, rx_usecs); - rx_frames = ec->rx_max_coalesced_frames; - tx_frames = ec->tx_max_coalesced_frames; - - if ((rx_riwt > FXGMAC_MAX_DMA_RIWT) || - (rx_riwt < FXGMAC_MIN_DMA_RIWT) || - (rx_frames > pdata->rx_desc_count)) - return -EINVAL; - - if (tx_frames > pdata->tx_desc_count) - return -EINVAL; - - pdata->rx_riwt = rx_riwt; - pdata->rx_usecs = rx_usecs; - pdata->rx_frames = rx_frames; - hw_ops->config_rx_coalesce(pdata); - - pdata->tx_frames = tx_frames; - hw_ops->config_tx_coalesce(pdata); - - pdata->tx_usecs = ec->tx_coalesce_usecs; - hw_ops->set_interrupt_moderation(pdata); - - DPRINTK("fxmac, set coalesce\n"); - return 0; -} - -#if (FXGMAC_RSS_FEATURE_ENABLED) -static u32 fxgmac_get_rxfh_key_size(struct net_device *netdev) -{ - return FXGMAC_RSS_HASH_KEY_SIZE; -} - -static u32 fxgmac_rss_indir_size(struct net_device *netdev) -{ - return FXGMAC_RSS_MAX_TABLE_SIZE; -} - -static void fxgmac_get_reta(struct fxgmac_pdata *pdata, u32 *indir) -{ - int i, reta_size = FXGMAC_RSS_MAX_TABLE_SIZE; - u16 rss_m; -#ifdef FXGMAC_ONE_CHANNLE - rss_m = FXGMAC_MAX_DMA_CHANNELS; -#else - rss_m = FXGMAC_MAX_DMA_CHANNELS - 1; //mask for index of channel, 0-3 -#endif - - for (i = 0; i < reta_size; i++) - indir[i] = pdata->rss_table[i] & rss_m; -} - -static int fxgmac_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, - u8 *hfunc) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - - /* - ETH_RSS_HASH_TOP __ETH_RSS_HASH(TOP) - ETH_RSS_HASH_XOR __ETH_RSS_HASH(XOR) - ETH_RSS_HASH_CRC32 __ETH_RSS_HASH(CRC32) - */ - if (hfunc) - { - //*hfunc = ETH_RSS_HASH_XOR; - *hfunc = ETH_RSS_HASH_TOP; - DPRINTK("fxmac, get_rxfh for hash function\n"); - } - - if (indir) - { - fxgmac_get_reta(pdata, indir); - DPRINTK("fxmac, get_rxfh for indirection tab\n"); - } - - if (key) - { - memcpy(key, pdata->rss_key, fxgmac_get_rxfh_key_size(netdev)); - DPRINTK("fxmac, get_rxfh for hash key\n"); - } - - return 0; -} - -static int fxgmac_set_rxfh(struct net_device *netdev, const u32 *indir, - const u8 *key, const u8 hfunc) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - int i; - u32 reta_entries = fxgmac_rss_indir_size(netdev); - int max_queues = FXGMAC_MAX_DMA_CHANNELS; - - DPRINTK("fxmac, set_rxfh callin, indir=%lx, key=%lx, func=%02x\n", (unsigned long)indir, (unsigned long)key, hfunc); - - if (hfunc) - return -EINVAL; - - /* Fill out the redirection table */ - if (indir) { -#if FXGMAC_MSIX_CH0RXDIS_EN - max_queues = max_queues; // kill warning - reta_entries = reta_entries; - i = i; - DPRINTK("fxmac, set_rxfh, change of indirect talbe is not supported.\n"); - return -EINVAL; -#else - /* double check user input. */ - for (i = 0; i < reta_entries; i++) - if (indir[i] >= max_queues) - return -EINVAL; - - for (i = 0; i < reta_entries; i++) - pdata->rss_table[i] = indir[i]; - - hw_ops->write_rss_lookup_table(pdata); -#endif - } - - /* Fill out the rss hash key */ - if (FXGMAC_RSS_HASH_KEY_LINUX && key) { - hw_ops->set_rss_hash_key(pdata, key); - } - - return 0; -} - -#if 0 -static int fxgmac_get_rxfh(struct net_device *netdev, - struct ethtool_rxfh_param *rxfh) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - - /* - ETH_RSS_HASH_TOP __ETH_RSS_HASH(TOP) - ETH_RSS_HASH_XOR __ETH_RSS_HASH(XOR) - ETH_RSS_HASH_CRC32 __ETH_RSS_HASH(CRC32) - */ - if (rxfh->hfunc) - { - //rxfh->hfunc = ETH_RSS_HASH_XOR; - rxfh->hfunc = ETH_RSS_HASH_TOP; - DPRINTK("fxmac, get_rxfh for hash function\n"); - } - - if (rxfh->indir) - { - fxgmac_get_reta(pdata, rxfh->indir); - DPRINTK("fxmac, get_rxfh for indirection tab\n"); - } - - if (rxfh->key) - { - memcpy(rxfh->key, pdata->rss_key, fxgmac_get_rxfh_key_size(netdev)); - DPRINTK("fxmac, get_rxfh for hash key\n"); - } - - return 0; -} - -static int fxgmac_set_rxfh(struct net_device *netdev, - struct ethtool_rxfh_param *rxfh, - struct netlink_ext_ack *extack) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - int i; - u32 reta_entries = fxgmac_rss_indir_size(netdev); - int max_queues = FXGMAC_MAX_DMA_CHANNELS; - - DPRINTK("fxmac, set_rxfh callin, indir=%lx, key=%lx, func=%02x\n", (unsigned long)rxfh->indir, (unsigned long)rxfh->key, rxfh->hfunc); - - if (rxfh->hfunc) - return -EINVAL; - - /* Fill out the redirection table */ - if (rxfh->indir) { -#if FXGMAC_MSIX_CH0RXDIS_EN - max_queues = max_queues; // kill warning - reta_entries = reta_entries; - i = i; - DPRINTK("fxmac, set_rxfh, change of indirect talbe is not supported.\n"); - return -EINVAL; -#else - /* double check user input. */ - for (i = 0; i < reta_entries; i++) - if (rxfh->indir[i] >= max_queues) - return -EINVAL; - - for (i = 0; i < reta_entries; i++) - pdata->rss_table[i] = rxfh->indir[i]; - - hw_ops->write_rss_lookup_table(pdata); -#endif - } - - /* Fill out the rss hash key */ - if (FXGMAC_RSS_HASH_KEY_LINUX && rxfh->key) { - hw_ops->set_rss_hash_key(pdata, rxfh->key); - } - - return 0; -} -#endif - -static int fxgmac_get_rss_hash_opts(struct fxgmac_pdata *pdata, - struct ethtool_rxnfc *cmd) -{ - u32 reg_opt; - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - cmd->data = 0; - - reg_opt = hw_ops->get_rss_options(pdata); - DPRINTK ("fxgmac_get_rss_hash_opts, hw=%02x, %02x\n", reg_opt, pdata->rss_options); - - if(reg_opt != pdata->rss_options) - { - DPRINTK ("fxgmac_get_rss_hash_opts, warning, options are not consistent\n"); - } - - /* Report default options for RSS */ - switch (cmd->flow_type) { - case TCP_V4_FLOW: - case UDP_V4_FLOW: - if(((TCP_V4_FLOW == (cmd->flow_type)) && (FXGMAC_GET_REG_BITS(pdata->rss_options, MAC_RSSCR_TCP4TE_POS, MAC_RSSCR_TCP4TE_LEN))) || - ((UDP_V4_FLOW == (cmd->flow_type)) && (FXGMAC_GET_REG_BITS(pdata->rss_options, MAC_RSSCR_UDP4TE_POS, MAC_RSSCR_UDP4TE_LEN)))) - { - cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - } - fallthrough; - case SCTP_V4_FLOW: - case AH_ESP_V4_FLOW: - case AH_V4_FLOW: - case ESP_V4_FLOW: - case IPV4_FLOW: - if(((TCP_V4_FLOW == (cmd->flow_type)) && (FXGMAC_GET_REG_BITS(pdata->rss_options, MAC_RSSCR_TCP4TE_POS, MAC_RSSCR_TCP4TE_LEN))) || - ((UDP_V4_FLOW == (cmd->flow_type)) && (FXGMAC_GET_REG_BITS(pdata->rss_options, MAC_RSSCR_UDP4TE_POS, MAC_RSSCR_UDP4TE_LEN))) || - (FXGMAC_GET_REG_BITS(pdata->rss_options, MAC_RSSCR_IP4TE_POS, MAC_RSSCR_IP4TE_LEN))) - { - cmd->data |= RXH_IP_SRC | RXH_IP_DST; - } - break; - case TCP_V6_FLOW: - case UDP_V6_FLOW: - if(((TCP_V6_FLOW == (cmd->flow_type)) && (FXGMAC_GET_REG_BITS(pdata->rss_options, MAC_RSSCR_TCP6TE_POS, MAC_RSSCR_TCP6TE_LEN))) || - ((UDP_V6_FLOW == (cmd->flow_type)) && (FXGMAC_GET_REG_BITS(pdata->rss_options, MAC_RSSCR_UDP6TE_POS, MAC_RSSCR_UDP6TE_LEN)))) - { - cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - } - fallthrough; - case SCTP_V6_FLOW: - case AH_ESP_V6_FLOW: - case AH_V6_FLOW: - case ESP_V6_FLOW: - case IPV6_FLOW: - if(((TCP_V6_FLOW == (cmd->flow_type)) && (FXGMAC_GET_REG_BITS(pdata->rss_options, MAC_RSSCR_TCP6TE_POS, MAC_RSSCR_TCP6TE_LEN))) || - ((UDP_V6_FLOW == (cmd->flow_type)) && (FXGMAC_GET_REG_BITS(pdata->rss_options, MAC_RSSCR_UDP6TE_POS, MAC_RSSCR_UDP6TE_LEN))) || - (FXGMAC_GET_REG_BITS(pdata->rss_options, MAC_RSSCR_IP6TE_POS, MAC_RSSCR_IP6TE_LEN))) - { - cmd->data |= RXH_IP_SRC | RXH_IP_DST; - } - break; - default: - return -EINVAL; - } - - return 0; -} - -static int fxgmac_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, - u32 *rule_locs) -{ - struct fxgmac_pdata *pdata = netdev_priv(dev); - int ret = -EOPNOTSUPP; - - switch (cmd->cmd) { - case ETHTOOL_GRXRINGS: - cmd->data = pdata->rx_q_count; - ret = 0; - DPRINTK("fxmac, get_rxnfc for rx ring cnt\n"); - break; - case ETHTOOL_GRXCLSRLCNT: - cmd->rule_cnt = 0; - ret = 0; - DPRINTK("fxmac, get_rxnfc for classify rule cnt\n"); - break; - case ETHTOOL_GRXCLSRULE: - DPRINTK("fxmac, get_rxnfc for classify rules\n"); - ret = 0;//ixgbe_get_ethtool_fdir_entry(adapter, cmd); - break; - case ETHTOOL_GRXCLSRLALL: - cmd->rule_cnt = 0; - ret = 0; - /*ret = ixgbe_get_ethtool_fdir_all(adapter, cmd, - (u32 *)rule_locs); - */ - DPRINTK("fxmac, get_rxnfc for classify both cnt and rules\n"); - break; - case ETHTOOL_GRXFH: - ret = fxgmac_get_rss_hash_opts(pdata, cmd); - DPRINTK("fxmac, get_rxnfc for hash options\n"); - break; - default: - break; - } - - return ret; -} - -#define UDP_RSS_FLAGS (BIT(MAC_RSSCR_UDP4TE_POS) | \ - BIT(MAC_RSSCR_UDP6TE_POS)) -static int fxgmac_set_rss_hash_opt(struct fxgmac_pdata *pdata, - struct ethtool_rxnfc *nfc) -{ - u32 rssopt = 0; //pdata->rss_options; - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - - DPRINTK("fxgmac_set_rss_hash_opt call in,nfc_data=%llx,cur opt=%x\n", nfc->data, pdata->rss_options); - - /* - * For RSS, it does not support anything other than hashing - * to queues on src,dst IPs and L4 ports - */ - if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | - RXH_L4_B_0_1 | RXH_L4_B_2_3)) - return -EINVAL; - - switch (nfc->flow_type) { - case TCP_V4_FLOW: - case TCP_V6_FLOW: - /* default to TCP flow and do nothting */ - if (!(nfc->data & RXH_IP_SRC) || - !(nfc->data & RXH_IP_DST) || - !(nfc->data & RXH_L4_B_0_1) || - !(nfc->data & RXH_L4_B_2_3)) - return -EINVAL; - if(TCP_V4_FLOW == (nfc->flow_type)) - { - rssopt = FXGMAC_SET_REG_BITS( - rssopt, - MAC_RSSCR_IP4TE_POS, - MAC_RSSCR_IP4TE_LEN, 1); - rssopt = FXGMAC_SET_REG_BITS( - rssopt, - MAC_RSSCR_TCP4TE_POS, - MAC_RSSCR_TCP4TE_LEN, 1); - } - - if(TCP_V6_FLOW == (nfc->flow_type)) - { - rssopt = FXGMAC_SET_REG_BITS( - rssopt, - MAC_RSSCR_IP6TE_POS, - MAC_RSSCR_IP6TE_LEN, 1); - rssopt = FXGMAC_SET_REG_BITS( - rssopt, - MAC_RSSCR_TCP6TE_POS, - MAC_RSSCR_TCP6TE_LEN, 1); - } - break; - - case UDP_V4_FLOW: - if (!(nfc->data & RXH_IP_SRC) || - !(nfc->data & RXH_IP_DST)) - return -EINVAL; - rssopt = FXGMAC_SET_REG_BITS( - rssopt, - MAC_RSSCR_IP4TE_POS, - MAC_RSSCR_IP4TE_LEN, 1); - switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): - rssopt = FXGMAC_SET_REG_BITS( - rssopt, - MAC_RSSCR_UDP4TE_POS, - MAC_RSSCR_UDP4TE_LEN, 1); - break; - default: - return -EINVAL; - } - break; - case UDP_V6_FLOW: - if (!(nfc->data & RXH_IP_SRC) || - !(nfc->data & RXH_IP_DST)) - return -EINVAL; - rssopt = FXGMAC_SET_REG_BITS( - rssopt, - MAC_RSSCR_IP6TE_POS, - MAC_RSSCR_IP6TE_LEN, 1); - - switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): - rssopt = FXGMAC_SET_REG_BITS( - rssopt, - MAC_RSSCR_UDP6TE_POS, - MAC_RSSCR_UDP6TE_LEN, 1); - break; - default: - return -EINVAL; - } - break; - case AH_ESP_V4_FLOW: - case AH_V4_FLOW: - case ESP_V4_FLOW: - case SCTP_V4_FLOW: - case AH_ESP_V6_FLOW: - case AH_V6_FLOW: - case ESP_V6_FLOW: - case SCTP_V6_FLOW: - if (!(nfc->data & RXH_IP_SRC) || - !(nfc->data & RXH_IP_DST) || - (nfc->data & RXH_L4_B_0_1) || - (nfc->data & RXH_L4_B_2_3)) - return -EINVAL; - break; - default: - return -EINVAL; - } - - /* if options are changed, then update to hw */ - if (rssopt != pdata->rss_options) { - if ((rssopt & UDP_RSS_FLAGS) && - !(pdata->rss_options & UDP_RSS_FLAGS)) - DPRINTK("enabling UDP RSS: fragmented packets" - " may arrive out of order to the stack above\n"); - - DPRINTK("rss option changed from %x to %x\n", pdata->rss_options, rssopt); - pdata->rss_options = rssopt; -#if 1 - hw_ops->set_rss_options(pdata); -#else - /* Perform hash on these packet types */ - mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4 - | IXGBE_MRQC_RSS_FIELD_IPV4_TCP - | IXGBE_MRQC_RSS_FIELD_IPV6 - | IXGBE_MRQC_RSS_FIELD_IPV6_TCP; - - mrqc &= ~(IXGBE_MRQC_RSS_FIELD_IPV4_UDP | - IXGBE_MRQC_RSS_FIELD_IPV6_UDP); - - if (flags2 & IXGBE_FLAG2_RSS_FIELD_IPV4_UDP) - mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP; - - if (flags2 & IXGBE_FLAG2_RSS_FIELD_IPV6_UDP) - mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; - - if ((hw->mac.type >= ixgbe_mac_X550) && - (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) - IXGBE_WRITE_REG(hw, IXGBE_PFVFMRQC(pf_pool), mrqc); - else - IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); -#endif - } - - return 0; -} - -static int fxgmac_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) -{ - struct fxgmac_pdata *pdata = netdev_priv(dev); - - int ret = -EOPNOTSUPP; - - switch (cmd->cmd) { - case ETHTOOL_SRXCLSRLINS: - //no support. rx classifier rule insert - //ret = ixgbe_add_ethtool_fdir_entry(adapter, cmd); - DPRINTK("set_rxnfc for rx cls rule insert-n\\a\n"); - break; - case ETHTOOL_SRXCLSRLDEL: - //no support. rx classifier rule delete - //ret = ixgbe_del_ethtool_fdir_entry(adapter, cmd); - DPRINTK("set_rxnfc for rx cls rule del-n\\a\n"); - break; - case ETHTOOL_SRXFH: - DPRINTK("set_rxnfc for rx rss option\n"); - ret = fxgmac_set_rss_hash_opt(pdata, cmd); - break; - default: - break; - } - - return ret; -} -#endif //FXGMAC_RSS_FEATURE_ENABLED - -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0) ) -static void fxgmac_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring, - struct kernel_ethtool_ringparam *kernel_ring, - struct netlink_ext_ack *exact) - -#else -static void fxgmac_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -#endif -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - - DPRINTK("fxmac, get_ringparam callin\n"); - - ring->rx_max_pending = FXGMAC_RX_DESC_CNT; - ring->tx_max_pending = FXGMAC_TX_DESC_CNT; - ring->rx_mini_max_pending = 0; - ring->rx_jumbo_max_pending = 0; - ring->rx_pending = pdata->rx_desc_count; - ring->tx_pending = pdata->tx_desc_count; - ring->rx_mini_pending = 0; - ring->rx_jumbo_pending = 0; -} - -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0) ) -static int fxgmac_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring, - struct kernel_ethtool_ringparam *kernel_ring, - struct netlink_ext_ack *exact) - -#else -static int fxgmac_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -#endif -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_desc_ops *desc_ops = &pdata->desc_ops; - - DPRINTK("fxmac, set_ringparam callin\n"); - - pdata->tx_desc_count = ring->tx_pending; - pdata->rx_desc_count = ring->rx_pending; - - fxgmac_stop(pdata); - fxgmac_free_tx_data(pdata); - fxgmac_free_rx_data(pdata); - desc_ops->alloc_channles_and_rings(pdata); - fxgmac_start(pdata); - - return 0; -} - -#if FXGMAC_WOL_FEATURE_ENABLED -static void fxgmac_get_wol(struct net_device *netdev, - struct ethtool_wolinfo *wol) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - - /* for further feature implementation - wol->supported = WAKE_PHY | WAKE_UCAST | WAKE_MCAST | - WAKE_BCAST | WAKE_MAGIC; - */ - - wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC | WAKE_ARP; -#if FXGMAC_WOL_UPON_EPHY_LINK - wol->supported |= WAKE_PHY; -#endif - - wol->wolopts = 0; - if (!(pdata->hw_feat.rwk) || !device_can_wakeup(/*pci_dev_to_dev*/(pdata->dev))) { - DPRINTK("fxgmac get_wol, pci does not support wakeup\n"); - return; - } -#if 0 - wol->wolopts |= WAKE_UCAST; - wol->wolopts |= WAKE_MCAST; - wol->wolopts |= WAKE_BCAST; - wol->wolopts |= WAKE_MAGIC; -#else - wol->wolopts = pdata->expansion.wol; -#endif - DPRINTK("fxmac, get_wol, 0x%x, 0x%x\n", wol->wolopts, pdata->expansion.wol); -} - -static int fxgmac_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - - //currently, we do not support these options -#if FXGMAC_WOL_UPON_EPHY_LINK -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,0)) - if (wol->wolopts & (WAKE_MAGICSECURE | WAKE_FILTER)) { -#else - if (wol->wolopts & WAKE_MAGICSECURE) { -#endif -#else -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,0)) - if (wol->wolopts & (WAKE_PHY | WAKE_MAGICSECURE | WAKE_FILTER)) { -#else - if (wol->wolopts & (WAKE_PHY | WAKE_MAGICSECURE)) { -#endif -#endif - DPRINTK("fxmac, set_wol, not supported wol options, 0x%x\n", wol->wolopts); - return -EOPNOTSUPP; - } - - if (!(pdata->hw_feat.rwk)) { - DPRINTK("fxmac, set_wol, hw wol feature is n/a\n"); - return (wol->wolopts ? -EOPNOTSUPP : 0); - } - -#if 1 /* normally, pls set this to 1. */ - pdata->expansion.wol = 0; - if (wol->wolopts & WAKE_UCAST) - pdata->expansion.wol |= WAKE_UCAST; - - if (wol->wolopts & WAKE_MCAST) - pdata->expansion.wol |= WAKE_MCAST; - - if (wol->wolopts & WAKE_BCAST) - pdata->expansion.wol |= WAKE_BCAST; - - if (wol->wolopts & WAKE_MAGIC) - pdata->expansion.wol |= WAKE_MAGIC; - - if (wol->wolopts & WAKE_PHY) - pdata->expansion.wol |= WAKE_PHY; - - if (wol->wolopts & WAKE_ARP) - pdata->expansion.wol |= WAKE_ARP; - - hw_ops->set_pattern_data(pdata); - - hw_ops->config_wol(pdata, (!!(pdata->expansion.wol))); -#else - - /* for test only... */ - if (wol->wolopts & WAKE_UCAST) { - DPRINTK("fxmac, set_wol, ucast\n"); - //fxgmac_net_powerdown(pdata, pdata->wol); - //fxgmac_update_aoe_ipv4addr(pdata, (u8 *)NULL); - //fxgmac_get_netdev_ip6addr(pdata, NULL, NULL); - fxgmac_update_ns_offload_ipv6addr(pdata, FXGMAC_NS_IFA_LOCAL_LINK); - } - - if (wol->wolopts & WAKE_MAGIC) { - DPRINTK("fxmac, set_wol, magic\n"); - //fxgmac_net_powerup(pdata); - //fxgmac_update_aoe_ipv4addr(pdata, (u8 *)"192.168.3.33"); - fxgmac_update_ns_offload_ipv6addr(pdata, FXGMAC_NS_IFA_GLOBAL_UNICAST); - } - /* - if (wol->wolopts & WAKE_BCAST) { - extern int fxgmac_disable_pci_msi_config(struct pci_dev *pdev); - DPRINTK("fxmac, set_wol, broadcast\n"); - fxgmac_disable_pci_msi_config(struct pci_dev *pdev); - } - */ -#endif - DPRINTK("fxmac, set_wol, opt=0x%x, 0x%x\n", wol->wolopts, pdata->expansion.wol); - - return 0; -} -#endif /*FXGMAC_WOL_FEATURE_ENABLED*/ - -static int fxgmac_get_regs_len(struct net_device __always_unused *netdev) -{ - return FXGMAC_EPHY_REGS_LEN * sizeof(u32); -} - -static void fxgmac_get_regs(struct net_device *netdev, struct ethtool_regs *regs, - void *p) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - - u32 *regs_buff = p; - u8 i; - - memset(p, 0, FXGMAC_EPHY_REGS_LEN * sizeof(u32)); - for (i = REG_MII_BMCR; i < FXGMAC_EPHY_REGS_LEN; i++) { - hw_ops->read_ephy_reg(pdata, i, (unsigned int *)®s_buff[i]); - } - regs->version = regs_buff[REG_MII_PHYSID1] << 16 | regs_buff[REG_MII_PHYSID2]; - - //fxgmac_ephy_soft_reset(pdata); -} - -#if FXGMAC_PAUSE_FEATURE_ENABLED -static int fxgmac_get_link_ksettings(struct net_device *netdev, - struct ethtool_link_ksettings *cmd) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - u32 duplex, regval, link_status; - u32 adv = 0xFFFFFFFF; - - regval = fxgmac_ephy_autoneg_ability_get(pdata, &adv); - if (regval) - return -ETIMEDOUT; - - ethtool_link_ksettings_zero_link_mode(cmd, supported); - ethtool_link_ksettings_zero_link_mode(cmd, advertising); - - /* set the supported link speeds */ - ethtool_link_ksettings_add_link_mode(cmd, supported, 1000baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, supported, 100baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, supported, 100baseT_Half); - ethtool_link_ksettings_add_link_mode(cmd, supported, 10baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, supported, 10baseT_Half); - - /* Indicate pause support */ - ethtool_link_ksettings_add_link_mode(cmd, supported, Pause); - ethtool_link_ksettings_add_link_mode(cmd, supported, Asym_Pause); - ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause); - ethtool_link_ksettings_add_link_mode(cmd, advertising, Asym_Pause); - - ethtool_link_ksettings_add_link_mode(cmd, supported, MII); - cmd->base.port = PORT_MII; - - ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg); - hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, ®val); - regval = FXGMAC_GET_REG_BITS(regval, PHY_CR_AUTOENG_POS, PHY_CR_AUTOENG_LEN); - if (regval) { - if (pdata->phy_autoeng) - ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg); - else - clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, cmd->link_modes.advertising); - - if (adv & FXGMAC_ADVERTISE_10HALF) - ethtool_link_ksettings_add_link_mode(cmd, advertising, 10baseT_Half); - if (adv & FXGMAC_ADVERTISE_10FULL) - ethtool_link_ksettings_add_link_mode(cmd, advertising, 10baseT_Full); - if (adv & FXGMAC_ADVERTISE_100HALF) - ethtool_link_ksettings_add_link_mode(cmd, advertising, 100baseT_Half); - if (adv & FXGMAC_ADVERTISE_100FULL) - ethtool_link_ksettings_add_link_mode(cmd, advertising, 100baseT_Full); - if (adv & FXGMAC_ADVERTISE_1000FULL) - ethtool_link_ksettings_add_link_mode(cmd, advertising, 1000baseT_Full); - } - else { - clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, cmd->link_modes.advertising); - switch (pdata->phy_speed) { - case SPEED_1000M: - if (pdata->phy_duplex) - ethtool_link_ksettings_add_link_mode(cmd, advertising, 1000baseT_Full); - else - ethtool_link_ksettings_add_link_mode(cmd, advertising, 1000baseT_Half); - break; - case SPEED_100M: - if (pdata->phy_duplex) - ethtool_link_ksettings_add_link_mode(cmd, advertising, 100baseT_Full); - else - ethtool_link_ksettings_add_link_mode(cmd, advertising, 100baseT_Half); - break; - case SPEED_10M: - if (pdata->phy_duplex) - ethtool_link_ksettings_add_link_mode(cmd, advertising, 10baseT_Full); - else - ethtool_link_ksettings_add_link_mode(cmd, advertising, 10baseT_Half); - break; - default: - break; - } - } - cmd->base.autoneg = pdata->phy_autoeng ? regval : 0; - - hw_ops->read_ephy_reg(pdata, REG_MII_SPEC_STATUS, ®val); - link_status = regval & (BIT(FUXI_EPHY_LINK_STATUS_BIT)); - if (link_status) { - duplex = FXGMAC_GET_REG_BITS(regval, PHY_MII_SPEC_DUPLEX_POS, PHY_MII_SPEC_DUPLEX_LEN); - cmd->base.duplex = duplex; - cmd->base.speed = pdata->phy_speed; - }else { - cmd->base.duplex = DUPLEX_UNKNOWN; - cmd->base.speed = SPEED_UNKNOWN; - } - - return 0; -} - -static int fxgmac_set_link_ksettings(struct net_device *netdev, - const struct ethtool_link_ksettings *cmd) -{ - u32 advertising, support, adv; - int ret; - struct fxphy_ag_adv; - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - - if (cmd->base.speed == SPEED_1000 && cmd->base.duplex == DUPLEX_HALF) - return -EINVAL; - - pdata->phy_autoeng = cmd->base.autoneg; - - ethtool_convert_link_mode_to_legacy_u32(&advertising, cmd->link_modes.advertising); - ethtool_convert_link_mode_to_legacy_u32(&support, cmd->link_modes.supported); - advertising &= support; - - if (pdata->phy_autoeng || (!pdata->phy_autoeng && cmd->base.speed == SPEED_1000)){ - ret = hw_ops->read_ephy_reg(pdata, REG_MII_ADVERTISE, &adv); - if (ret < 0) - return -ETIMEDOUT; - adv &= ~REG_BIT_ADVERTISE_100_10_CAP; - adv |= ethtool_adv_to_mii_adv_t(advertising); - ret = hw_ops->write_ephy_reg(pdata, REG_MII_ADVERTISE, adv); - if (ret < 0) - return -ETIMEDOUT; - ret = hw_ops->read_ephy_reg(pdata, REG_MII_CTRL1000, &adv); - if (ret < 0) - return -ETIMEDOUT; - adv &= ~REG_BIT_ADVERTISE_1000_CAP; - adv |= ethtool_adv_to_mii_ctrl1000_t(advertising); - ret = hw_ops->write_ephy_reg(pdata, REG_MII_CTRL1000, adv); - if (ret < 0) - return -ETIMEDOUT; - - ret = hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, &adv); - if (ret < 0) - return -ETIMEDOUT; - adv = FXGMAC_SET_REG_BITS(adv, PHY_CR_AUTOENG_POS, PHY_CR_AUTOENG_LEN, 1); - ret = hw_ops->write_ephy_reg(pdata, REG_MII_BMCR, adv); - if (ret < 0) - return -ETIMEDOUT; - - ret = hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, &adv); - if (ret < 0) - return -ETIMEDOUT; - adv = FXGMAC_SET_REG_BITS(adv, PHY_CR_RE_AUTOENG_POS, PHY_CR_RE_AUTOENG_LEN, 1); - ret = hw_ops->write_ephy_reg(pdata, REG_MII_BMCR, adv); - if (ret < 0) - return -ETIMEDOUT; - } else { - pdata->phy_duplex = cmd->base.duplex; - pdata->phy_speed = cmd->base.speed; - fxgmac_phy_force_speed(pdata, pdata->phy_speed); - fxgmac_phy_force_duplex(pdata, pdata->phy_duplex); - fxgmac_phy_force_autoneg(pdata, pdata->phy_autoeng); - //hw_ops->config_mac_speed(pdata); - } - - ret = fxgmac_ephy_soft_reset(pdata); - if (ret) { - printk("%s: ephy soft reset timeout.\n", __func__); - return -ETIMEDOUT; - } - - return 0; -} - -static void fxgmac_get_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - - pause->autoneg = 1; - pause->rx_pause = pdata->rx_pause; - pause->tx_pause = pdata->tx_pause; - - DPRINTK("fxmac get_pauseparam done, rx=%d, tx=%d\n", pdata->rx_pause, pdata->tx_pause); -} - -static int fxgmac_set_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - unsigned int pre_rx_pause = pdata->rx_pause; - unsigned int pre_tx_pause = pdata->tx_pause; - - //if (pause->autoneg == AUTONEG_ENABLE) - //DPRINTK("fxgmac set pause parameter, autoneg=%d\n", pause->autoneg); - - pdata->rx_pause = pause->rx_pause; - pdata->tx_pause = pause->tx_pause; - - if(pre_rx_pause != pdata->rx_pause) { - hw_ops->config_rx_flow_control(pdata); - DPRINTK("fxgmac set pause parameter, rx from %d to %d\n", pre_rx_pause, pdata->rx_pause); - } - if(pre_tx_pause != pdata->tx_pause) { - hw_ops->config_tx_flow_control(pdata); - DPRINTK("fxgmac set pause parameter, tx from %d to %d\n", pre_tx_pause, pdata->tx_pause); - } - - /* - if (netif_running(netdev)) - fxgmac_restart_dev(pdata); - */ - DPRINTK("fxgmac set pause parameter, autoneg=%d, rx=%d, tx=%d\n", pause->autoneg, pause->rx_pause, pause->tx_pause); - - return 0; -} -#endif /*FXGMAC_PAUSE_FEATURE_ENABLED*/ - - -/* yzhang added for debug sake. descriptors status checking - * 2021.03.29 - */ -#define FXGMAC_ETH_GSTRING_LEN 32 - -#if 0 -static char fxgmac_gstrings_test[1024*7][FXGMAC_ETH_GSTRING_LEN]= { -}; - -static char fxgmac_gstrings_header[7][10]= { - "Channel:", "curDesc:", - "baseMem:", "desc0 :", - "desc1 :", "desc2 :", - "desc3 :" -}; -#endif - -#define FXGMAC_TEST_LEN (sizeof(fxgmac_gstrings_test) / FXGMAC_ETH_GSTRING_LEN) -#define DBG_ETHTOOL_CHECK_NUM_OF_DESC 5 -//static u16 fxgmac_ethtool_test_len = DBG_ETHTOOL_CHECK_NUM_OF_DESC; //default value, yzhang - -static void fxgmac_ethtool_get_strings(struct net_device *netdev, - u32 stringset, u8 *data) -{ - int i; - - switch (stringset) { - case ETH_SS_STATS: - for (i = 0; i < FXGMAC_STATS_COUNT; i++) { - memcpy(data, fxgmac_gstring_stats[i].stat_string, - strlen(fxgmac_gstring_stats[i].stat_string)); - data += ETH_GSTRING_LEN; - } - break; - default: - WARN_ON(1); - break; - } -} - -static int fxgmac_ethtool_get_sset_count(struct net_device *netdev, - int stringset) -{ - int ret; - - switch (stringset) { - case ETH_SS_STATS: - ret = FXGMAC_STATS_COUNT; - break; - - default: - ret = -EOPNOTSUPP; - } - - return ret; -} - -static void fxgmac_ethtool_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, - u64 *data) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - u8 *stat; - int i; - -#if FXGMAC_PM_FEATURE_ENABLED - /* 20210709 for net power down */ - if(!test_bit(FXGMAC_POWER_STATE_DOWN, &pdata->expansion.powerstate)) -#endif - { - //DPRINTK("fxgmac_ethtool_get_ethtool_stats, here\n"); - pdata->hw_ops.read_mmc_stats(pdata); - } - - for (i = 0; i < FXGMAC_STATS_COUNT; i++) { - stat = (u8 *)pdata + fxgmac_gstring_stats[i].stat_offset; - *data++ = *(u64 *)stat; - } -} - -static inline bool fxgmac_removed(void __iomem *addr) -{ - return unlikely(!addr); -} -#define FXGMAC_REMOVED(a) fxgmac_removed(a) - -static const struct ethtool_ops fxgmac_ethtool_ops = { - .get_drvinfo = fxgmac_ethtool_get_drvinfo, - .get_link = ethtool_op_get_link, - .get_msglevel = fxgmac_ethtool_get_msglevel, - .set_msglevel = fxgmac_ethtool_set_msglevel, - .get_channels = fxgmac_ethtool_get_channels, - .get_coalesce = fxgmac_ethtool_get_coalesce, - .set_coalesce = fxgmac_ethtool_set_coalesce, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0)) - /* - * The process of set is to get first and then set, - * and the result of get is preserved for values that have not been modified. - * - * Therefore, when using, it is necessary to ensure that this macro and the - * assignment operation in the get_coalesce are one-to-one correspondence, - * otherwise the macro and parameters will be verified when set, and the error - * of "Operation not supported " will be reported if the verification fails - */ -#ifdef ETHTOOL_COALESCE_USECS - .supported_coalesce_params = ETHTOOL_COALESCE_USECS, -#endif -#endif - .get_strings = fxgmac_ethtool_get_strings, - .get_sset_count = fxgmac_ethtool_get_sset_count, - .get_ethtool_stats = fxgmac_ethtool_get_ethtool_stats, - .get_regs_len = fxgmac_get_regs_len, - .get_regs = fxgmac_get_regs, - .get_ringparam = fxgmac_get_ringparam, - .set_ringparam = fxgmac_set_ringparam, -#if (FXGMAC_RSS_FEATURE_ENABLED) - .get_rxnfc = fxgmac_get_rxnfc, - .set_rxnfc = fxgmac_set_rxnfc, - .get_rxfh_indir_size = fxgmac_rss_indir_size, - .get_rxfh_key_size = fxgmac_get_rxfh_key_size, - .get_rxfh = fxgmac_get_rxfh, - .set_rxfh = fxgmac_set_rxfh, -#endif -#if (FXGMAC_WOL_FEATURE_ENABLED) - .get_wol = fxgmac_get_wol, - .set_wol = fxgmac_set_wol, -#endif -#if (FXGMAC_PAUSE_FEATURE_ENABLED) -#ifdef ETHTOOL_GLINKSETTINGS - .get_link_ksettings = fxgmac_get_link_ksettings, - .set_link_ksettings = fxgmac_set_link_ksettings, -#endif /* ETHTOOL_GLINKSETTINGS */ - .get_pauseparam = fxgmac_get_pauseparam, - .set_pauseparam = fxgmac_set_pauseparam, -#endif -}; - -const struct ethtool_ops *fxgmac_get_ethtool_ops(void) -{ - return &fxgmac_ethtool_ops; -} diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-hw.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-hw.c deleted file mode 100644 index f63dbb0c9e0b0..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-hw.c +++ /dev/null @@ -1,6714 +0,0 @@ -/*++ - -Copyright (c) 2021 Motorcomm, Inc. -Motorcomm Confidential and Proprietary. - -This is Motorcomm NIC driver relevant files. Please don't copy, modify, -distribute without commercial permission. - ---*/ - -#include "fuxi-gmac.h" -#include "fuxi-gmac-reg.h" -#include "fuxi-efuse.h" - -#if defined(UEFI) -#include "nic_sw.h" -#elif defined(_WIN64) || defined(_WIN32) -#include "fuxi-mp.h" -#elif defined(PXE) -#include "fuxi_undi.h" -#endif - - -void fxgmac_release_phy(struct fxgmac_pdata* pdata); -static void fxgmac_pwr_clock_ungate(struct fxgmac_pdata* pdata); -static void fxgmac_pwr_clock_gate(struct fxgmac_pdata* pdata); - -static int fxgmac_tx_complete(struct fxgmac_dma_desc *dma_desc) -{ -#ifdef LINUX -#if (FXGMAC_DUMMY_TX_DEBUG) - return 1; -#endif -#endif - return !FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, - TX_NORMAL_DESC3_OWN_POS, - TX_NORMAL_DESC3_OWN_LEN); -} - -static int fxgmac_disable_rx_csum(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_IPC_POS, - MAC_CR_IPC_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); - - DPRINTK("fxgmac disable rx checksum.\n"); - return 0; -} - -static int fxgmac_enable_rx_csum(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_IPC_POS, - MAC_CR_IPC_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); - - DPRINTK("fxgmac enable rx checksum.\n"); - return 0; -} - -static int fxgmac_set_mac_address(struct fxgmac_pdata *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); - - writereg(pdata->pAdapter, mac_addr_hi, pdata->mac_regs + MAC_MACA0HR); - writereg(pdata->pAdapter, mac_addr_lo, pdata->mac_regs + MAC_MACA0LR); - - return 0; -} - -#if !defined(DPDK) -static void fxgmac_set_mac_reg(struct fxgmac_pdata *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]; - - netif_dbg(pdata, drv, pdata->netdev, - "adding mac address %pM at %#x\n", - ha->addr, *mac_reg); - - mac_addr_hi = FXGMAC_SET_REG_BITS(mac_addr_hi, - MAC_MACA1HR_AE_POS, - MAC_MACA1HR_AE_LEN, - 1); - } - - writereg(pdata->pAdapter, mac_addr_hi, pdata->mac_regs + *mac_reg); - *mac_reg += MAC_MACA_INC; - writereg(pdata->pAdapter, mac_addr_lo, pdata->mac_regs + *mac_reg); - *mac_reg += MAC_MACA_INC; -} -#endif - -static int fxgmac_enable_tx_vlan(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANIR); - /* Indicate that VLAN Tx CTAGs come from mac_vlan_incl register */ - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_VLTI_POS, - MAC_VLANIR_VLTI_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_CSVL_POS, - MAC_VLANIR_CSVL_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_VLP_POS, - MAC_VLANIR_VLP_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_VLC_POS, - MAC_VLANIR_VLC_LEN, 2); - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_VLT_POS, - MAC_VLANIR_VLT_LEN, pdata->vlan); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_VLANIR); - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANTR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_VL_POS, - MAC_VLANTR_VL_LEN, pdata->vlan); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_VLANTR); - - return 0; -} - -static int fxgmac_disable_tx_vlan(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANIR); - - /* Indicate that VLAN Tx CTAGs come from mac_vlan_incl register */ - //Set VLAN Tag input enable - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_CSVL_POS, - MAC_VLANIR_CSVL_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_VLTI_POS, - MAC_VLANIR_VLTI_LEN, /*0*/1); - //Set VLAN priority control disable - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_VLP_POS, - MAC_VLANIR_VLP_LEN, /*1*/0); - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_VLC_POS, - MAC_VLANIR_VLC_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_VLANIR); - - /* 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. - */ - //2022-04-19 xiaojiang comment - //If it enable the following code and enable vlan filter, then the MAC only receive the packet of VLAN ID "1" - /*regval = readreg(pdata->mac_regs + MAC_VLANTR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_VL_POS, - MAC_VLANTR_VL_LEN, 1); - writereg(regval, pdata->mac_regs + MAC_VLANTR);*/ - - return 0; -} - -static int fxgmac_enable_rx_vlan_stripping(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANTR); - /* Put the VLAN tag in the Rx descriptor */ - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_EVLRXS_POS, - MAC_VLANTR_EVLRXS_LEN, 1); - /* Don't check the VLAN type */ - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_DOVLTC_POS, - MAC_VLANTR_DOVLTC_LEN, 1); - /* Check only C-TAG (0x8100) packets */ - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_ERSVLM_POS, - MAC_VLANTR_ERSVLM_LEN, 0); - /* Don't consider an S-TAG (0x88A8) packet as a VLAN packet */ - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_ESVL_POS, - MAC_VLANTR_ESVL_LEN, 0); - /* Enable VLAN tag stripping */ - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_EVLS_POS, - MAC_VLANTR_EVLS_LEN, 0x3); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_VLANTR); - DPRINTK("fxgmac enable MAC rx vlan stripping.\n"); - - return 0; -} - -static int fxgmac_disable_rx_vlan_stripping(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANTR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_EVLS_POS, - MAC_VLANTR_EVLS_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_VLANTR); - DPRINTK("fxgmac disable MAC rx vlan stripping.\n"); - - return 0; -} - -static int fxgmac_enable_rx_vlan_filtering(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PFR); - /* Enable VLAN filtering */ - regval = FXGMAC_SET_REG_BITS(regval, MAC_PFR_VTFE_POS, - MAC_PFR_VTFE_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PFR); - -//2022-04-25 xiaojiang comment -//FXGMAC_FILTER_SINGLE_VLAN_ENABLED is used for Linux driver -//In Linux driver it uses VLAN Filter to filter packet, In windows driver it uses SW method to filter packet. -#if FXGMAC_FILTER_SINGLE_VLAN_ENABLED - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANTR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_VL_POS, - MAC_VLANTR_VL_LEN, pdata->vlan); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_VLANTR); -#else - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANTR); - /* Enable VLAN Hash Table filtering */ - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_VTHM_POS, - MAC_VLANTR_VTHM_LEN, 1); - /* Disable VLAN tag inverse matching */ - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_VTIM_POS, - MAC_VLANTR_VTIM_LEN, 0); - /* Only filter on the lower 12-bits of the VLAN tag */ - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_ETV_POS, - MAC_VLANTR_ETV_LEN, 1); -#endif - - return 0; -} - -static int fxgmac_disable_rx_vlan_filtering(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PFR); - /* Disable VLAN filtering */ - regval = FXGMAC_SET_REG_BITS(regval, MAC_PFR_VTFE_POS, - MAC_PFR_VTFE_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PFR); - -#if FXGMAC_FILTER_SINGLE_VLAN_ENABLED - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANTR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_VL_POS, - MAC_VLANTR_VL_LEN, pdata->vlan); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_VLANTR); -#endif - - return 0; -} - -#if FXGMAC_FILTER_MULTIPLE_VLAN_ENABLED -static u32 fxgmac_vid_crc32_le(__le16 vid_le) -{ - unsigned char *data = (unsigned char *)&vid_le; - unsigned char data_byte = 0; - u32 crc = ~0; - u32 temp = 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 ^= CRC32_POLY_LE; - } - - return crc; -} -#endif - -static int fxgmac_update_vlan_hash_table(struct fxgmac_pdata *pdata) -{ - u16 vlan_hash_table = 0; - u32 regval; - //Linux also support multiple VLAN -#if FXGMAC_FILTER_MULTIPLE_VLAN_ENABLED - __le16 vid_le; - u32 crc; - u16 vid; - /* 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(~fxgmac_vid_crc32_le(vid_le)) >> 28; - - vlan_hash_table |= (1 << crc); - } -#endif - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANHTR); - /* Set the VLAN Hash Table filtering register */ - regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANHTR_VLHT_POS, - MAC_VLANHTR_VLHT_LEN, vlan_hash_table); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_VLANHTR); - - DPRINTK("fxgmac_update_vlan_hash_tabl done,hash tbl=%08x.\n",vlan_hash_table); - return 0; -} - -static int fxgmac_set_promiscuous_mode(struct fxgmac_pdata *pdata, - unsigned int enable) -{ - unsigned int val = enable ? 1 : 0; - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PFR); - - if (FXGMAC_GET_REG_BITS(regval, MAC_PFR_PR_POS, MAC_PFR_PR_LEN) == val) { - return 0; - } - netif_dbg(pdata, drv, pdata->netdev, ""STR_FORMAT" promiscuous mode\n", - enable ? "entering" : "leaving"); - - regval = FXGMAC_SET_REG_BITS(regval, MAC_PFR_PR_POS, MAC_PFR_PR_LEN, val); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PFR); - - DbgPrintF(MP_TRACE, ""STR_FORMAT" - promiscuous mode=%d, reg=%x.", __FUNCTION__, enable, regval); - DbgPrintF(MP_TRACE, ""STR_FORMAT" - note, vlan filter is called when set promiscuous mode=%d.", __FUNCTION__, enable); - - /* Hardware will still perform VLAN filtering in promiscuous mode */ - if (enable) { - fxgmac_disable_rx_vlan_filtering(pdata); - } else { - #ifdef LINUX - if(pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER) - #else - if (0) - #endif - { - fxgmac_enable_rx_vlan_filtering(pdata); - } - } - - DPRINTK("fxgmac set promisc mode=%d\n", enable); - return 0; -} - -static int fxgmac_enable_rx_broadcast(struct fxgmac_pdata *pdata, - unsigned int enable) -{ - unsigned int val = enable ? 0 : 1; //mac reg bit is disable,,so invert the val. - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PFR); - - if (FXGMAC_GET_REG_BITS(regval, MAC_PFR_DBF_POS, MAC_PFR_DBF_LEN) == val) { - return 0; - } - - regval = FXGMAC_SET_REG_BITS(regval, MAC_PFR_DBF_POS, MAC_PFR_DBF_LEN, val); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PFR); - - DbgPrintF(MP_TRACE, "%s - bcast en=%d, bit-val=%d, reg=%x.", __FUNCTION__, enable, val, regval); - return 0; -} - -static int fxgmac_set_all_multicast_mode(struct fxgmac_pdata *pdata, - unsigned int enable) -{ - unsigned int val = enable ? 1 : 0; - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PFR); - if (FXGMAC_GET_REG_BITS(regval, MAC_PFR_PM_POS, MAC_PFR_PM_LEN) == val) { - return 0; - } - netif_dbg(pdata, drv, pdata->netdev, ""STR_FORMAT" allmulti mode\n", - enable ? "entering" : "leaving"); - - regval = FXGMAC_SET_REG_BITS(regval, MAC_PFR_PM_POS, MAC_PFR_PM_LEN, val); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PFR); - - DbgPrintF(MP_TRACE, ""STR_FORMAT" - Enable all Multicast=%d, regval=%#x.", __FUNCTION__, enable, regval); - - return 0; -} - -static void fxgmac_set_mac_addn_addrs(struct fxgmac_pdata *pdata) -{ -#ifndef DPDK -#if FXGMAC_FILTER_MULTIPLE_MAC_ADDR_ENABLED - struct net_device *netdev = pdata->netdev; - struct netdev_hw_addr *ha; -#endif - unsigned int addn_macs; - unsigned int mac_reg; - - mac_reg = MAC_MACA1HR; - addn_macs = pdata->hw_feat.addn_mac; -#if FXGMAC_FILTER_MULTIPLE_MAC_ADDR_ENABLED - DPRINTK("xlgamc add mac addr callin\n"); - if (netdev_uc_count(netdev) > addn_macs) { - fxgmac_set_promiscuous_mode(pdata, 1); - } else { - netdev_for_each_uc_addr(ha, netdev) { - fxgmac_set_mac_reg(pdata, ha, &mac_reg); - addn_macs--; - } - - if (netdev_mc_count(netdev) > addn_macs) { - fxgmac_set_all_multicast_mode(pdata, 1); - } else { - netdev_for_each_mc_addr(ha, netdev) { - fxgmac_set_mac_reg(pdata, ha, &mac_reg); - addn_macs--; - } - } - } -#endif - /* Clear remaining additional MAC address entries */ - while (addn_macs--) { - fxgmac_set_mac_reg(pdata, NULL, &mac_reg); - } -#else - (void)pdata; -#endif -} - -#define GET_REG_AND_BIT_POS(reversalval, regOut, bitOut) \ - do { \ - regOut = (((reversalval) >> 5) & 0x7); \ - bitOut = ((reversalval) & 0x1f); \ - }while(0) - -static u32 fxgmac_crc32(unsigned char *Data, int Length) -{ - u32 Crc = (u32)~0; /* Initial value. 0xFFFFFFFF */ - - while (--Length >= 0) { - unsigned char Byte = *Data++; - int Bit; - - for (Bit = 8; --Bit >= 0; Byte >>= 1) { - if ((Crc ^ Byte) & 1) { - Crc >>= 1; - Crc ^= 0xedb88320; - } - else { - Crc >>= 1; - } - } - } - - return ~Crc; -} - -/* - * configure multicast hash table, reg 0x2010~202c - * input: pmc_mac, pointer to mcast MAC. if it is null, then clean all registers. - * b_add, 1 to set the bit; 0 to clear the bit. - */ -static void fxgmac_config_multicast_mac_hash_table(struct fxgmac_pdata *pdata, unsigned char *pmc_mac, int b_add) -{ - unsigned int hash_reg, reg_bit; - unsigned int j; - u32 crc, reversal_crc, regval; - - if(!pmc_mac) - { - for(j = 0; j < FXGMAC_MAC_HASH_TABLE_SIZE; j++) - { - hash_reg = j; - hash_reg = (MAC_HTR0 + hash_reg * MAC_HTR_INC); - writereg(pdata->pAdapter, 0, pdata->mac_regs + hash_reg); - //DBGPRINT(MP_TRACE, ("fxgmac_config_mcast_mac_hash_table, reg %04x=0x%x\n", FUXI_MAC_REGS_OFFSET + hash_reg, readreg(pdata->mac_regs + hash_reg))); - } - DBGPRINT(MP_TRACE, (">24), hash_reg, reg_bit); - /* Set the MAC Hash Table registers */ - hash_reg = (MAC_HTR0 + hash_reg * MAC_HTR_INC); - regval = readreg(pdata->pAdapter, pdata->mac_regs + hash_reg); - - regval = FXGMAC_SET_REG_BITS(regval, reg_bit, 1, (b_add ? 1 : 0)); - - writereg(pdata->pAdapter, regval, pdata->mac_regs + hash_reg); - -#if 0 - DBGPRINT(MP_TRACE, ("netdev; - struct netdev_hw_addr *ha; -#if 0 - u32 hash_table[FXGMAC_MAC_HASH_TABLE_SIZE]; - unsigned int hash_reg; - unsigned int i; - u32 crc; -#endif - netdev_for_each_mc_addr(ha, netdev) - { - fxgmac_config_multicast_mac_hash_table(pdata, ha->addr, 1); - } -#endif - -#if 0 //TODO - 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++) { - writereg(pdata->pAdapter, hash_table[i], pdata->mac_regs + hash_reg); - hash_reg += MAC_HTR_INC; - } - - //if(hash_table[i]) - // DPRINTK("fxgmac_set_mac_hash_tabl[%d]=%08x.\n", i, hash_table[i]); -#else - pdata = pdata; -#endif - -#else - (void)pdata; -#endif -} - -static int fxgmac_add_mac_addresses(struct fxgmac_pdata *pdata) -{ - if (pdata->hw_feat.hash_table_size) - fxgmac_set_mac_hash_table(pdata); - else - fxgmac_set_mac_addn_addrs(pdata); - - return 0; -} - -static void fxgmac_config_mac_address(struct fxgmac_pdata *pdata) -{ - u32 regval; - //KdBreakPoint(); - fxgmac_set_mac_address(pdata, pdata->mac_addr); - //fxgmac_set_mac_address(pdata, (u8*)"\x00\x55\x7b\xb5\x7d\xf7");// pdata->netdev->dev_addr); - //fxgmac_set_mac_address(pdata, (u8*)"\xf7\x7d\xb5\x7b\x55\x00"); - - /* Filtering is done using perfect filtering and hash filtering */ - if (pdata->hw_feat.hash_table_size) { - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PFR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_PFR_HPF_POS, - MAC_PFR_HPF_LEN, 1); -#if FUXI_MAC_HASH_TABLE - regval = FXGMAC_SET_REG_BITS(regval, MAC_PFR_HUC_POS, - MAC_PFR_HUC_LEN, 1); -#endif - regval = FXGMAC_SET_REG_BITS(regval, MAC_PFR_HMC_POS, - MAC_PFR_HMC_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PFR); - } -} - -static int fxgmac_config_crc_check(struct fxgmac_pdata *pdata) -{ - u32 regval, value; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_ECR); - value = (pdata->crc_check) ? 0 : 1; - regval = FXGMAC_SET_REG_BITS(regval, MAC_ECR_DCRCC_POS, - MAC_ECR_DCRCC_LEN, value); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_ECR); - - return 0; -} - -static int fxgmac_config_jumbo(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_JE_POS, - MAC_CR_JE_LEN, pdata->jumbo); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); - return 0; -} - -static void fxgmac_config_checksum_offload(struct fxgmac_pdata *pdata) -{ -#ifdef LINUX - if (pdata->netdev->features & NETIF_F_RXCSUM) -#else - if (1) -#endif - fxgmac_enable_rx_csum(pdata); - else - fxgmac_disable_rx_csum(pdata); -} - -static void fxgmac_config_vlan_support(struct fxgmac_pdata *pdata) -{ - /*if (pdata->vlan_exist) - fxgmac_enable_tx_vlan(pdata); - else*/ - fxgmac_disable_tx_vlan(pdata); // configure dynamical vlanID from TX Context. - - /* Set the current VLAN Hash Table register value */ - fxgmac_update_vlan_hash_table(pdata); - - //2022-04-26 xiaojiang comment - //Windows driver set vlan_filter disable, but in Linux driver it enable vlan_filter - if (pdata->vlan_filter) //disable vlan rx filter by default - fxgmac_enable_rx_vlan_filtering(pdata); - else - fxgmac_disable_rx_vlan_filtering(pdata); - - if (pdata->vlan_strip) //enable vlan rx strip by default - fxgmac_enable_rx_vlan_stripping(pdata); - else - fxgmac_disable_rx_vlan_stripping(pdata); - -} - -static int fxgmac_config_rx_mode(struct fxgmac_pdata *pdata) -{ -#ifdef LINUX - struct net_device *netdev = pdata->netdev; -#endif - unsigned int pr_mode, am_mode; - -#ifdef LINUX - pr_mode = ((netdev->flags & IFF_PROMISC) != 0); - am_mode = ((netdev->flags & IFF_ALLMULTI) != 0); -#else - pr_mode = 1;// ((netdev->flags & IFF_PROMISC) != 0); //TODO - am_mode = 1;// ((netdev->flags & IFF_ALLMULTI) != 0);//TODO -#endif - - fxgmac_set_promiscuous_mode(pdata, pr_mode); - fxgmac_set_all_multicast_mode(pdata, am_mode); - - fxgmac_add_mac_addresses(pdata); - - return 0; -} - -static void fxgmac_prepare_tx_stop(struct fxgmac_pdata *pdata, - struct fxgmac_channel *channel) -{ -#ifdef LINUX - unsigned int tx_dsr, tx_pos, tx_qidx; - unsigned long tx_timeout; - unsigned int tx_status; - - pdata = pdata; - - /* 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_LEN) + - 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_LEN) + - DMA_DSRX_TPS_START; - } - //2022-04-19 xiaojiang comment - //Windows os not have wait Tx Stop operation. - /* 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... - */ -#if FXGMAC_TX_HANG_TIMER_EN - tx_timeout = jiffies + msecs_to_jiffies(100); /* 100ms */ -#else - tx_timeout = jiffies + (FXGMAC_DMA_STOP_TIMEOUT * HZ); -#endif - while (time_before(jiffies, tx_timeout)) { - tx_status = readreg(pdata->pAdapter, pdata->mac_regs + tx_dsr); - tx_status = FXGMAC_GET_REG_BITS(tx_status, tx_pos, - DMA_DSR_TPS_LEN); - if ((tx_status == DMA_TPS_STOPPED) || - (tx_status == DMA_TPS_SUSPENDED)) - break; - - usleep_range_ex(pdata->pAdapter, 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); -#else - pdata = pdata; - channel = channel; -#endif -} - -static void fxgmac_enable_tx(struct fxgmac_pdata *pdata) -{ -#ifndef DPDK - struct fxgmac_channel *channel; -#endif - unsigned int i; - u32 regval; - -#if FXGMAC_TX_HANG_TIMER_EN - pdata->tx_hang_restart_queuing = 0; -#endif - - /* Enable each Tx DMA channel */ -#ifndef DPDK - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { -#ifndef UBOOT //uboot unuse tx_ring - if (!channel->tx_ring) - break; -#endif - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_TCR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_TCR_ST_POS, - DMA_CH_TCR_ST_LEN, 1); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_TCR)); - } -#else - PMD_INIT_FUNC_TRACE(); - struct fxgmac_tx_queue *txq; - struct rte_eth_dev *dev = pdata->expansion.eth_dev; - - for (i = 0; i < dev->data->nb_tx_queues; i++) { - txq = dev->data->tx_queues[i]; - /* Enable Tx DMA channel */ - FXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, ST, 1); - } -#endif - - /* Enable each Tx queue */ - for (i = 0; i < pdata->tx_q_count; i++) { - regval = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); - regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_TXQEN_POS, - MTL_Q_TQOMR_TXQEN_LEN, - MTL_Q_ENABLED); - writereg(pdata->pAdapter, regval, FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); - } - - /* Enable MAC Tx */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_TE_POS, - MAC_CR_TE_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); -} - -static void fxgmac_disable_tx(struct fxgmac_pdata *pdata) -{ -#ifndef DPDK - struct fxgmac_channel *channel; -#endif - unsigned int i; - u32 regval; - - /* Prepare for Tx DMA channel stop */ -#ifndef DPDK - channel = pdata->channel_head; - if (channel != NULL) { - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) - break; - - fxgmac_prepare_tx_stop(pdata, channel); - -#if FXGMAC_TX_HANG_TIMER_EN - pdata->tx_hang_restart_queuing = 0; -#endif - } - } - -#else - PMD_INIT_FUNC_TRACE(); - struct fxgmac_tx_queue *txq; - struct rte_eth_dev *dev = pdata->expansion.eth_dev; - - for (i = 0; i < pdata->tx_q_count; i++) { - txq = dev->data->tx_queues[i]; - fxgmac_txq_prepare_tx_stop(pdata, i); - } -#endif - - /* Disable MAC Tx */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_TE_POS, - MAC_CR_TE_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); - - /* Disable each Tx queue */ - for (i = 0; i < pdata->tx_q_count; i++) { - regval = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); - regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_TXQEN_POS, - MTL_Q_TQOMR_TXQEN_LEN, 0); - writereg(pdata->pAdapter, regval, FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); - } - - /* Disable each Tx DMA channel */ -#ifndef DPDK - channel = pdata->channel_head; - if (channel != NULL) { - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) - break; - - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_TCR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_TCR_ST_POS, - DMA_CH_TCR_ST_LEN, 0); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_TCR)); - } - } -#else - for (i = 0; i < dev->data->nb_tx_queues; i++) { - txq = dev->data->tx_queues[i]; - FXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, ST, 0); - } -#endif -} - -static void fxgmac_prepare_rx_stop(struct fxgmac_pdata *pdata, - unsigned int queue) -{ - unsigned int rx_status, prxq; -#if defined(LINUX) || defined(DPDK) - unsigned int rxqsts; - unsigned long rx_timeout; -#if defined(DPDK) - unsigned long jiffies = rte_get_timer_cycles(); -#endif - /* The Rx engine cannot be stopped if it is actively processing - * packets. Wait for the Rx queue to empty the Rx fifo. Don't - * wait forever though... - */ -#if FXGMAC_TX_HANG_TIMER_EN - rx_timeout = jiffies + msecs_to_jiffies(500); /* 500ms, larger is better */ -#else - rx_timeout = jiffies + (FXGMAC_DMA_STOP_TIMEOUT * HZ); -#endif - while (time_before(jiffies, rx_timeout)) { - rx_status = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, queue, MTL_Q_RQDR)); - prxq = FXGMAC_GET_REG_BITS(rx_status, MTL_Q_RQDR_PRXQ_POS, - MTL_Q_RQDR_PRXQ_LEN); - rxqsts = FXGMAC_GET_REG_BITS(rx_status, MTL_Q_RQDR_RXQSTS_POS, - MTL_Q_RQDR_RXQSTS_LEN); - if ((prxq == 0) && (rxqsts == 0)) - break; - - usleep_range_ex(pdata->pAdapter, 500, 1000); - } - - if (!time_before(jiffies, rx_timeout)) - netdev_info(pdata->netdev, - "timed out waiting for Rx queue %u to empty\n", - queue); -#else - unsigned int busy = 100; - do { - rx_status = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, queue, MTL_Q_RQDR)); - prxq = FXGMAC_GET_REG_BITS(rx_status, MTL_Q_RQDR_PRXQ_POS, MTL_Q_RQDR_PRXQ_LEN); - busy--; - usleep_range_ex(pdata->pAdapter, 500, 1000); - } while ((prxq) && (busy)); - if (0 == busy) { - rx_status = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, queue, MTL_Q_RQDR)); - DbgPrintF(MP_WARN, "warning !!!timed out waiting for Rx queue %u to empty\n", queue); - } -#endif -} - -static void fxgmac_enable_rx(struct fxgmac_pdata *pdata) -{ -#ifndef DPDK - struct fxgmac_channel *channel; -#endif - unsigned int regval, i; - - /* Enable each Rx DMA channel */ -#ifndef DPDK - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { -#ifndef UBOOT //uboot unuse rx_ring - if (!channel->rx_ring) - break; -#endif - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_RCR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_RCR_SR_POS, - DMA_CH_RCR_SR_LEN, 1); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_RCR)); - } - -#else - PMD_INIT_FUNC_TRACE(); - struct fxgmac_rx_queue *rxq; - struct rte_eth_dev *dev = pdata->expansion.eth_dev; - //struct fxgmac_pdata *pdata = pdata->dev->data->dev_private; - - for (i = 0; i < dev->data->nb_rx_queues; i++) { - rxq = dev->data->rx_queues[i]; - /* Enable Rx DMA channel */ - FXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_RCR, SR, 1); - } -#endif - - /* Enable each Rx queue */ - regval = 0; - for (i = 0; i < pdata->rx_q_count; i++) - regval |= (0x02 << (i << 1)); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_RQC0R); - -#ifndef DPDK - /* Enable MAC Rx */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_CST_POS, - MAC_CR_CST_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_ACS_POS, - MAC_CR_ACS_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_RE_POS, - MAC_CR_RE_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); -#else - /* Enable MAC Rx */ - FXGMAC_IOWRITE_BITS(pdata, MAC_ECR, DCRCC, 1); - - /* Frame is forwarded after stripping CRC to application*/ - if (pdata->expansion.crc_strip_enable) { - FXGMAC_IOWRITE_BITS(pdata, MAC_CR, CST, 1); - FXGMAC_IOWRITE_BITS(pdata, MAC_CR, ACS, 1); - } - FXGMAC_IOWRITE_BITS(pdata, MAC_CR, RE, 1); -#endif -} -static void fxgmac_enable_channel_rx(struct fxgmac_pdata* pdata, unsigned int queue) -{ - struct fxgmac_channel* channel; - unsigned int regval; - - /* Enable Rx DMA channel */ - channel = pdata->channel_head + queue; - - if (!channel->rx_ring) - return; - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_RCR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_RCR_SR_POS, - DMA_CH_RCR_SR_LEN, 1); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_RCR)); - /* Enable Rx queue */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_RQC0R); - regval |= (0x02 << (queue << 1)); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_RQC0R); - - /* Enable MAC Rx */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); - if (!(regval&((0x01<< MAC_CR_CST_POS)|(0x01 << MAC_CR_ACS_POS)|(0x01<< MAC_CR_RE_POS)))) - { - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_CST_POS, - MAC_CR_CST_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_ACS_POS, - MAC_CR_ACS_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_RE_POS, - MAC_CR_RE_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); - } -} - -static void fxgmac_disable_rx(struct fxgmac_pdata *pdata) -{ -#ifndef DPDK - struct fxgmac_channel *channel; -#endif - unsigned int i; - u32 regval; - - /* Disable MAC Rx */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_CST_POS, - MAC_CR_CST_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_ACS_POS, - MAC_CR_ACS_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_RE_POS, - MAC_CR_RE_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); - - /* Prepare for Rx DMA channel stop */ -#ifndef DPDK - for (i = 0; i < pdata->rx_q_count; i++) - fxgmac_prepare_rx_stop(pdata, i); -#else - PMD_INIT_FUNC_TRACE(); - struct fxgmac_rx_queue *rxq; - struct rte_eth_dev *dev = pdata->expansion.eth_dev; - - for (i = 0; i < dev->data->nb_rx_queues; i++) { - rxq = dev->data->rx_queues[i]; - fxgmac_prepare_rx_stop(pdata, i); - } -#endif - - /* Disable each Rx queue */ - writereg(pdata->pAdapter, 0, pdata->mac_regs + MAC_RQC0R); - - /* Disable each Rx DMA channel */ -#ifndef DPDK - channel = pdata->channel_head; - if (channel != NULL) { - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->rx_ring) - break; - - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_RCR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_RCR_SR_POS, - DMA_CH_RCR_SR_LEN, 0); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_RCR)); - } - } -#else - for (i = 0; i < dev->data->nb_rx_queues; i++) { - rxq = dev->data->rx_queues[i]; - FXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_RCR, SR, 0); - } -#endif -} - -#ifdef LINUX -static void fxgmac_tx_start_xmit(struct fxgmac_channel *channel, - struct fxgmac_ring *ring) -{ - struct fxgmac_pdata *pdata = channel->pdata; - struct fxgmac_desc_data *desc_data; - - /* Make sure everything is written before the register write */ - wmb(); - - /* Issue a poll command to Tx DMA by writing address - * of next immediate free descriptor - */ - desc_data = FXGMAC_GET_DESC_DATA(ring, ring->cur); - //DPRINTK("tx_start_xmit: dump before wr reg,descs-%08x,%08x,%08x,%08x\n",desc_data->dma_desc->desc0,desc_data->dma_desc->desc1,desc_data->dma_desc->desc2,desc_data->dma_desc->desc3); -#if !(FXGMAC_DUMMY_TX_DEBUG) - writereg(pdata->pAdapter, lower_32_bits(desc_data->dma_desc_addr), - FXGMAC_DMA_REG(channel, DMA_CH_TDTR_LO)); -#else - DPRINTK("dummy tx, fxgmac_tx_start_xmit, tail reg=0x%lx,val=%08x\n", FXGMAC_DMA_REG(channel, DMA_CH_TDTR_LO) - pdata->mac_regs, (u32)lower_32_bits(desc_data->dma_desc_addr)); -#endif - if(netif_msg_tx_done(pdata)) DPRINTK("tx_start_xmit: dump before wr reg,dma base=0x%016llx,reg=0x%08x, tx timer usecs=%u,tx_timer_active=%u\n", - desc_data->dma_desc_addr, readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_TDTR_LO)), pdata->tx_usecs, channel->tx_timer_active); - - ring->tx.xmit_more = 0; -} -#endif - -#ifdef LINUX -static void fxgmac_dev_xmit(struct fxgmac_channel *channel) -{ - struct fxgmac_pdata *pdata = channel->pdata; - struct fxgmac_ring *ring = channel->tx_ring; - unsigned int tso_context, vlan_context; - struct fxgmac_desc_data *desc_data; - struct fxgmac_dma_desc *dma_desc; - struct fxgmac_pkt_info *pkt_info; - unsigned int csum, tso, vlan; - int start_index = ring->cur; - int cur_index = ring->cur; - int i; - - if(netif_msg_tx_done(pdata)) DPRINTK("dev_xmit callin, desc cur=%d\n", cur_index); - - pkt_info = &ring->pkt_info; - csum = FXGMAC_GET_REG_BITS(pkt_info->attributes, - TX_PACKET_ATTRIBUTES_CSUM_ENABLE_POS, - TX_PACKET_ATTRIBUTES_CSUM_ENABLE_LEN); - tso = FXGMAC_GET_REG_BITS(pkt_info->attributes, - TX_PACKET_ATTRIBUTES_TSO_ENABLE_POS, - TX_PACKET_ATTRIBUTES_TSO_ENABLE_LEN); - vlan = FXGMAC_GET_REG_BITS(pkt_info->attributes, - TX_PACKET_ATTRIBUTES_VLAN_CTAG_POS, - TX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN); - - if (tso && (pkt_info->mss != ring->tx.cur_mss)) - tso_context = 1; - else - tso_context = 0; - - //if(tso && (netif_msg_tx_done(pdata))) - if((tso_context) && (netif_msg_tx_done(pdata))) { - //tso is initialized to start... - DPRINTK("fxgmac_dev_xmit,tso_%s tso=0x%x,pkt_mss=%d,cur_mss=%d\n",(pkt_info->mss)?"start":"stop", tso, pkt_info->mss, ring->tx.cur_mss); - } - - if (vlan && (pkt_info->vlan_ctag != ring->tx.cur_vlan_ctag)) - vlan_context = 1; - else - vlan_context = 0; - - if(vlan && (netif_msg_tx_done(pdata))) DPRINTK("fxgmac_dev_xmi:pkt vlan=%d, ring vlan=%d, vlan_context=%d\n", pkt_info->vlan_ctag, ring->tx.cur_vlan_ctag, vlan_context); - - desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); - dma_desc = desc_data->dma_desc; - - /* Create a context descriptor if this is a TSO pkt_info */ - if (tso_context || vlan_context) { - if (tso_context) { -#if 0 - netif_dbg(pdata, tx_queued, pdata->netdev, - "TSO context descriptor, mss=%u\n", - pkt_info->mss); -#else - if (netif_msg_tx_done(pdata)) DPRINTK("xlgamc dev xmit,construct tso context descriptor, mss=%u\n", - pkt_info->mss); -#endif - - /* Set the MSS size */ - dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc2, - TX_CONTEXT_DESC2_MSS_POS, - TX_CONTEXT_DESC2_MSS_LEN, - pkt_info->mss); - - /* Mark it as a CONTEXT descriptor */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_CONTEXT_DESC3_CTXT_POS, - TX_CONTEXT_DESC3_CTXT_LEN, - 1); - - /* Indicate this descriptor contains the MSS */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_CONTEXT_DESC3_TCMSSV_POS, - TX_CONTEXT_DESC3_TCMSSV_LEN, - 1); - - ring->tx.cur_mss = pkt_info->mss; - } - - if (vlan_context) { - netif_dbg(pdata, tx_queued, pdata->netdev, - "VLAN context descriptor, ctag=%u\n", - pkt_info->vlan_ctag); - - /* Mark it as a CONTEXT descriptor */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_CONTEXT_DESC3_CTXT_POS, - TX_CONTEXT_DESC3_CTXT_LEN, - 1); - - /* Set the VLAN tag */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_CONTEXT_DESC3_VT_POS, - TX_CONTEXT_DESC3_VT_LEN, - pkt_info->vlan_ctag); - - /* Indicate this descriptor contains the VLAN tag */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_CONTEXT_DESC3_VLTV_POS, - TX_CONTEXT_DESC3_VLTV_LEN, - 1); - - ring->tx.cur_vlan_ctag = pkt_info->vlan_ctag; - } - - //cur_index++; - cur_index = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); - desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); - dma_desc = desc_data->dma_desc; - } - - /* Update buffer address (for TSO this is the header) */ - dma_desc->desc0 = cpu_to_le32(lower_32_bits(desc_data->skb_dma)); - dma_desc->desc1 = cpu_to_le32(upper_32_bits(desc_data->skb_dma)); - - /* Update the buffer length */ - dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc2, - TX_NORMAL_DESC2_HL_B1L_POS, - TX_NORMAL_DESC2_HL_B1L_LEN, - desc_data->skb_dma_len); - - /* VLAN tag insertion check */ - if (vlan) { - dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc2, - TX_NORMAL_DESC2_VTIR_POS, - TX_NORMAL_DESC2_VTIR_LEN, - TX_NORMAL_DESC2_VLAN_INSERT); - pdata->stats.tx_vlan_packets++; - } - - /* Timestamp enablement check */ - if (FXGMAC_GET_REG_BITS(pkt_info->attributes, - TX_PACKET_ATTRIBUTES_PTP_POS, - TX_PACKET_ATTRIBUTES_PTP_LEN)) - dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc2, - TX_NORMAL_DESC2_TTSE_POS, - TX_NORMAL_DESC2_TTSE_LEN, - 1); - - /* Mark it as First Descriptor */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_NORMAL_DESC3_FD_POS, - TX_NORMAL_DESC3_FD_LEN, - 1); - - /* Mark it as a NORMAL descriptor */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_NORMAL_DESC3_CTXT_POS, - TX_NORMAL_DESC3_CTXT_LEN, - 0); - - /* Set OWN bit if not the first descriptor */ - if (cur_index != start_index) - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_NORMAL_DESC3_OWN_POS, - TX_NORMAL_DESC3_OWN_LEN, - 1); - - if (tso) { - /* Enable TSO */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_NORMAL_DESC3_TSE_POS, - TX_NORMAL_DESC3_TSE_LEN, 1); - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_NORMAL_DESC3_TCPPL_POS, - TX_NORMAL_DESC3_TCPPL_LEN, - pkt_info->tcp_payload_len); - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_NORMAL_DESC3_TCPHDRLEN_POS, - TX_NORMAL_DESC3_TCPHDRLEN_LEN, - pkt_info->tcp_header_len / 4); - - pdata->stats.tx_tso_packets++; - } else { - /* Enable CRC and Pad Insertion */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_NORMAL_DESC3_CPC_POS, - TX_NORMAL_DESC3_CPC_LEN, 0); - - /* Enable HW CSUM */ - if (csum) - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_NORMAL_DESC3_CIC_POS, - TX_NORMAL_DESC3_CIC_LEN, - 0x3); - - /* Set the total length to be transmitted */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_NORMAL_DESC3_FL_POS, - TX_NORMAL_DESC3_FL_LEN, - pkt_info->length); - } - if(netif_msg_tx_done(pdata)) DPRINTK("dev_xmit before more descs, desc cur=%d, start=%d, desc=%#x,%#x,%#x,%#x\n", - cur_index, start_index, dma_desc->desc0, dma_desc->desc1, dma_desc->desc2, dma_desc->desc3); - - if (start_index <= cur_index) - i = cur_index - start_index + 1; - else - i = ring->dma_desc_count - start_index + cur_index; - - for (; i < pkt_info->desc_count; i++) { - cur_index = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); - - desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); - dma_desc = desc_data->dma_desc; - - /* Update buffer address */ - dma_desc->desc0 = - cpu_to_le32(lower_32_bits(desc_data->skb_dma)); - dma_desc->desc1 = - cpu_to_le32(upper_32_bits(desc_data->skb_dma)); - - /* Update the buffer length */ - dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc2, - TX_NORMAL_DESC2_HL_B1L_POS, - TX_NORMAL_DESC2_HL_B1L_LEN, - desc_data->skb_dma_len); - - /* Set OWN bit */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_NORMAL_DESC3_OWN_POS, - TX_NORMAL_DESC3_OWN_LEN, 1); - - /* Mark it as NORMAL descriptor */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_NORMAL_DESC3_CTXT_POS, - TX_NORMAL_DESC3_CTXT_LEN, 0); - - /* Enable HW CSUM */ - if (csum) - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_NORMAL_DESC3_CIC_POS, - TX_NORMAL_DESC3_CIC_LEN, - 0x3); - } - - /* Set LAST bit for the last descriptor */ - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_NORMAL_DESC3_LD_POS, - TX_NORMAL_DESC3_LD_LEN, 1); - - dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc2, - TX_NORMAL_DESC2_IC_POS, - TX_NORMAL_DESC2_IC_LEN, 1); - - /* Save the Tx info to report back during cleanup */ - desc_data->tx.packets = pkt_info->tx_packets; - desc_data->tx.bytes = pkt_info->tx_bytes; - - if(netif_msg_tx_done(pdata)) DPRINTK("dev_xmit last descs, desc cur=%d, desc=%#x,%#x,%#x,%#x\n", - cur_index, dma_desc->desc0, dma_desc->desc1, dma_desc->desc2, dma_desc->desc3); - - /* 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 - */ - dma_wmb(); - - /* Set OWN bit for the first descriptor */ - desc_data = FXGMAC_GET_DESC_DATA(ring, start_index); - dma_desc = desc_data->dma_desc; - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - TX_NORMAL_DESC3_OWN_POS, - TX_NORMAL_DESC3_OWN_LEN, 1); - - if(netif_msg_tx_done(pdata)) DPRINTK("dev_xmit first descs, start=%d, desc=%#x,%#x,%#x,%#x\n", - start_index, dma_desc->desc0, dma_desc->desc1, dma_desc->desc2, dma_desc->desc3); - - if (netif_msg_tx_queued(pdata)) - fxgmac_dump_tx_desc(pdata, ring, start_index, - pkt_info->desc_count, 1); -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) ) - if(netif_msg_tx_done(pdata)) DPRINTK("dev_xmit about to call tx_start_xmit, ring xmit_more=%d,txq_stopped=%x\n",ring->tx.xmit_more, netif_xmit_stopped(netdev_get_tx_queue(pdata->netdev, channel->queue_index))); -#else /* ( LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,165) )*/ - if(netif_msg_tx_done(pdata)) DPRINTK("dev_xmit about to call tx_start_xmit, pkt xmit_more=%d,txq_stopped=%x\n",pkt_info->skb->xmit_more, netif_xmit_stopped(netdev_get_tx_queue(pdata->netdev, channel->queue_index))); -#endif - - /* Make sure ownership is written to the descriptor */ - smp_wmb(); - - //ring->cur = cur_index + 1; - ring->cur = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); - -#if 0 -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) ) - if (!ring->tx.xmit_more || netif_xmit_stopped(netdev_get_tx_queue(pdata->netdev, - channel->queue_index))) -#elif ( LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,1) ) - if (!pkt_info->skb->xmit_more || - netif_xmit_stopped(netdev_get_tx_queue(pdata->netdev, - channel->queue_index))) -#else - if (netif_xmit_stopped(netdev_get_tx_queue(pdata->netdev, - channel->queue_index))) -#endif - { - fxgmac_tx_start_xmit(channel, ring); - } - else - ring->tx.xmit_more = 1; -#endif - - fxgmac_tx_start_xmit(channel, ring); - - /* yzhang for reduce debug output */ - if(netif_msg_tx_done(pdata)){ - DPRINTK("dev_xmit callout %s: descriptors %u to %u written\n", - channel->name, start_index & (ring->dma_desc_count - 1), - (ring->cur - 1) & (ring->dma_desc_count - 1)); - } -} -#endif -#ifdef LINUX -static void fxgmac_get_rx_tstamp(struct fxgmac_pkt_info *pkt_info, - struct fxgmac_dma_desc *dma_desc) -{ - //u32 tsa, tsd; - u64 nsec; -#if 0 - tsa = FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, - RX_CONTEXT_DESC3_TSA_POS, - RX_CONTEXT_DESC3_TSA_LEN); - tsd = FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, - RX_CONTEXT_DESC3_TSD_POS, - RX_CONTEXT_DESC3_TSD_LEN); - if (tsa && !tsd) { -#endif - nsec = le32_to_cpu(dma_desc->desc1); - nsec <<= 32; - nsec |= le32_to_cpu(dma_desc->desc0); - if (nsec != 0xffffffffffffffffULL) { - pkt_info->rx_tstamp = nsec; - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_RX_TSTAMP_POS, - RX_PACKET_ATTRIBUTES_RX_TSTAMP_LEN, - 1); - } - //} -} -#endif - -static void fxgmac_tx_desc_reset(struct fxgmac_desc_data *desc_data) -{ - struct fxgmac_dma_desc *dma_desc = desc_data->dma_desc; - - /* 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) - */ - dma_desc->desc0 = 0; - dma_desc->desc1 = 0; - dma_desc->desc2 = 0; - dma_desc->desc3 = 0; - - /* Make sure ownership is written to the descriptor */ - dma_wmb(); -} - -static void fxgmac_tx_desc_init(struct fxgmac_channel *channel) -{ - struct fxgmac_ring *ring = channel->tx_ring; - struct fxgmac_desc_data *desc_data; - int start_index = ring->cur; - unsigned int i; - start_index = start_index; - //DEBUGPRINT(INIT, "["STR_FORMAT","STR_FORMAT",%d]:dma_desc_count=%d,0x%x\n",__FILE__, __func__,__LINE__,ring->dma_desc_count,channel->tx_ring); - - /* Initialize all descriptors */ - for (i = 0; i < ring->dma_desc_count; i++) { - desc_data = FXGMAC_GET_DESC_DATA(ring, i); - - /* Initialize Tx descriptor */ - fxgmac_tx_desc_reset(desc_data); - } - - ///* Update the total number of Tx descriptors */ - //writereg(ring->dma_desc_count - 1, FXGMAC_DMA_REG(channel, DMA_CH_TDRLR)); - writereg(channel->pdata->pAdapter, channel->pdata->tx_desc_count - 1, FXGMAC_DMA_REG(channel, DMA_CH_TDRLR)); - -/* Update the starting address of descriptor ring */ -#if defined(LINUX) - desc_data = FXGMAC_GET_DESC_DATA(ring, start_index); - writereg(channel->pdata->pAdapter, upper_32_bits(desc_data->dma_desc_addr), - FXGMAC_DMA_REG(channel, DMA_CH_TDLR_HI)); - writereg(channel->pdata->pAdapter, lower_32_bits(desc_data->dma_desc_addr), - FXGMAC_DMA_REG(channel, DMA_CH_TDLR_LO)); -#elif defined(UEFI) - writereg(channel->pdata->pAdapter, GetPhyAddrHigh(((PADAPTER)channel->pdata->pAdapter)->TbdPhyAddr),//adpt->TbdPhyAddr - FXGMAC_DMA_REG(channel, DMA_CH_TDLR_HI)); - writereg(channel->pdata->pAdapter, GetPhyAddrLow(((PADAPTER)channel->pdata->pAdapter)->TbdPhyAddr), - FXGMAC_DMA_REG(channel, DMA_CH_TDLR_LO)); -#elif defined(PXE) - -#elif defined(UBOOT) - -#elif defined(DPDK) - -#else //netadaptercx & ndis - writereg(channel->pdata->pAdapter, NdisGetPhysicalAddressHigh(((PMP_ADAPTER)channel->pdata->pAdapter)->HwTbdBasePa), - FXGMAC_DMA_REG(channel, DMA_CH_TDLR_HI)); - writereg(channel->pdata->pAdapter, NdisGetPhysicalAddressLow(((PMP_ADAPTER)channel->pdata->pAdapter)->HwTbdBasePa), - FXGMAC_DMA_REG(channel, DMA_CH_TDLR_LO)); -#endif - -} - -static void fxgmac_rx_desc_reset(struct fxgmac_pdata *pdata, - struct fxgmac_desc_data *desc_data, - unsigned int index) -{ -#ifdef LINUX - struct fxgmac_dma_desc *dma_desc = desc_data->dma_desc; - - /* 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 - */ - //hdr_dma = desc_data->rx.hdr.dma_base + desc_data->rx.hdr.dma_off; - //buf_dma = desc_data->rx.buf.dma_base + desc_data->rx.buf.dma_off; - dma_desc->desc0 = cpu_to_le32(lower_32_bits(desc_data->rx.buf.dma_base)); - dma_desc->desc1 = cpu_to_le32(upper_32_bits(desc_data->rx.buf.dma_base)); - dma_desc->desc2 = 0;//cpu_to_le32(lower_32_bits(buf_dma)); - dma_desc->desc3 = 0;//cpu_to_le32(upper_32_bits(buf_dma)); - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - RX_NORMAL_DESC3_INTE_POS, - RX_NORMAL_DESC3_INTE_LEN, - 1); - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - RX_NORMAL_DESC3_BUF2V_POS, - RX_NORMAL_DESC3_BUF2V_LEN, - 0); - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - RX_NORMAL_DESC3_BUF1V_POS, - RX_NORMAL_DESC3_BUF1V_LEN, - 1); - - /* 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 - */ - dma_wmb(); - - dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( - dma_desc->desc3, - RX_NORMAL_DESC3_OWN_POS, - RX_NORMAL_DESC3_OWN_LEN, - 1); - - /* Make sure ownership is written to the descriptor */ - dma_wmb(); -#else - pdata = pdata; - desc_data = desc_data; - index = index; -#endif -} - -static void fxgmac_rx_desc_init(struct fxgmac_channel *channel) -{ - struct fxgmac_pdata *pdata = channel->pdata; - struct fxgmac_ring *ring = channel->rx_ring; -#ifdef LINUX - unsigned int start_index = ring->cur; -#endif - struct fxgmac_desc_data *desc_data; - unsigned int i; -#if defined(UEFI) - UINT64 HwRbdPa; -#elif defined(_WIN64) || defined(_WIN32) - unsigned int Qid; - NDIS_PHYSICAL_ADDRESS HwRbdPa; -#elif defined(PXE) -#endif - - - /* Initialize all descriptors */ - for (i = 0; i < ring->dma_desc_count; i++) { - desc_data = FXGMAC_GET_DESC_DATA(ring, i); - - /* Initialize Rx descriptor */ - fxgmac_rx_desc_reset(pdata, desc_data, i); - } - -#if defined(LINUX) - /* Update the total number of Rx descriptors */ - writereg(pdata->pAdapter, ring->dma_desc_count - 1, FXGMAC_DMA_REG(channel, DMA_CH_RDRLR)); - - /* Update the starting address of descriptor ring */ - desc_data = FXGMAC_GET_DESC_DATA(ring, start_index); - writereg(pdata->pAdapter, upper_32_bits(desc_data->dma_desc_addr), - FXGMAC_DMA_REG(channel, DMA_CH_RDLR_HI)); - writereg(pdata->pAdapter, lower_32_bits(desc_data->dma_desc_addr), - FXGMAC_DMA_REG(channel, DMA_CH_RDLR_LO)); - - /* Update the Rx Descriptor Tail Pointer */ - desc_data = FXGMAC_GET_DESC_DATA(ring, start_index + - ring->dma_desc_count - 1); - writereg(pdata->pAdapter, lower_32_bits(desc_data->dma_desc_addr), - FXGMAC_DMA_REG(channel, DMA_CH_RDTR_LO)); -#elif defined(UEFI) - writereg(pdata->pAdapter, pdata->rx_desc_count - 1, - FXGMAC_DMA_REG(channel, DMA_CH_RDRLR)); - /* Update the starting address of descriptor ring */ - writereg(pdata->pAdapter, GetPhyAddrHigh(((PADAPTER)channel->pdata->pAdapter)->RbdPhyAddr), - FXGMAC_DMA_REG(channel, DMA_CH_RDLR_HI)); - writereg(pdata->pAdapter, GetPhyAddrLow(((PADAPTER)channel->pdata->pAdapter)->RbdPhyAddr), - FXGMAC_DMA_REG(channel, DMA_CH_RDLR_LO)); - - - HwRbdPa = ((PADAPTER)channel->pdata->pAdapter)->RbdPhyAddr + (pdata->rx_desc_count - 1) * sizeof(struct fxgmac_dma_desc); - - /* Update the Rx Descriptor Tail Pointer */ - writereg(pdata->pAdapter, GetPhyAddrLow(HwRbdPa), FXGMAC_DMA_REG(channel, DMA_CH_RDTR_LO)); -#elif defined(PXE) -#elif defined(UBOOT) -#elif defined(DPDK) -#else //netadaptercx & ndis - Qid = (unsigned int)(channel - pdata->channel_head); - DbgPrintF(MP_TRACE, ""STR_FORMAT": %d, Qid =%d\n", __FUNCTION__, __LINE__, Qid); - - writereg(channel->pdata->pAdapter, ((PMP_ADAPTER)channel->pdata->pAdapter)->RxQueue[Qid].NumHwRecvBuffers - 1, - FXGMAC_DMA_REG(channel, DMA_CH_RDRLR)); - - /* Update the starting address of descriptor ring */ - writereg(channel->pdata->pAdapter, NdisGetPhysicalAddressHigh(((PMP_ADAPTER)channel->pdata->pAdapter)->RxQueue[Qid].HwRbdBasePa), - FXGMAC_DMA_REG(channel, DMA_CH_RDLR_HI)); - writereg(channel->pdata->pAdapter, NdisGetPhysicalAddressLow(((PMP_ADAPTER)channel->pdata->pAdapter)->RxQueue[Qid].HwRbdBasePa), - FXGMAC_DMA_REG(channel, DMA_CH_RDLR_LO)); - - #if defined(NIC_NET_ADAPETERCX) - /* Update the Rx Descriptor Tail Pointer */ - writereg(channel->pdata->pAdapter, NdisGetPhysicalAddressLow(((PMP_ADAPTER)channel->pdata->pAdapter)->RxQueue[Qid].HwRbdBasePa), - FXGMAC_DMA_REG(channel, DMA_CH_RDTR_LO)); - HwRbdPa.QuadPart = 0; - #else - HwRbdPa.QuadPart = ((PMP_ADAPTER)channel->pdata->pAdapter)->RxQueue[Qid].HwRbdBasePa.QuadPart - + (((PMP_ADAPTER)channel->pdata->pAdapter)->RxQueue[Qid].NumHwRecvBuffers - 1) * sizeof(HW_RBD); - - /* Update the Rx Descriptor Tail Pointer */ - writereg(channel->pdata->pAdapter, NdisGetPhysicalAddressLow(HwRbdPa), FXGMAC_DMA_REG(channel, DMA_CH_RDTR_LO)); - #endif -#endif -} - -static int fxgmac_is_context_desc(struct fxgmac_dma_desc *dma_desc) -{ - /* Rx and Tx share CTXT bit, so check TDES3.CTXT bit */ - return FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, - TX_NORMAL_DESC3_CTXT_POS, - TX_NORMAL_DESC3_CTXT_LEN); -} - -static int fxgmac_is_last_desc(struct fxgmac_dma_desc *dma_desc) -{ - /* Rx and Tx share LD bit, so check TDES3.LD bit */ - return FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, - TX_NORMAL_DESC3_LD_POS, - TX_NORMAL_DESC3_LD_LEN); -} - -static int fxgmac_disable_tx_flow_control(struct fxgmac_pdata *pdata) -{ - unsigned int max_q_count, q_count; - unsigned int reg, regval; - unsigned int i; - - /* Clear MTL flow control */ - for (i = 0; i < pdata->rx_q_count; i++) { - regval = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); - regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_EHFC_POS, - MTL_Q_RQOMR_EHFC_LEN, 0); - writereg(pdata->pAdapter, regval, FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); - } - - /* Clear MAC flow control */ - max_q_count = FXGMAC_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++) { - regval = readreg(pdata->pAdapter, pdata->mac_regs + reg); - regval = FXGMAC_SET_REG_BITS(regval, - MAC_Q0TFCR_TFE_POS, - MAC_Q0TFCR_TFE_LEN, - 0); - writereg(pdata->pAdapter, regval, pdata->mac_regs + reg); - - reg += MAC_QTFCR_INC; - } - - return 0; -} - -static int fxgmac_enable_tx_flow_control(struct fxgmac_pdata *pdata) -{ - unsigned int max_q_count, q_count; - unsigned int reg, regval; - unsigned int i; - - /* Set MTL flow control */ - for (i = 0; i < pdata->rx_q_count; i++) { - regval = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); - regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_EHFC_POS, - MTL_Q_RQOMR_EHFC_LEN, 1); - writereg(pdata->pAdapter, regval, FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); - } - - /* Set MAC flow control */ - max_q_count = FXGMAC_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++) { - regval = readreg(pdata->pAdapter, pdata->mac_regs + reg); - - /* Enable transmit flow control */ - regval = FXGMAC_SET_REG_BITS(regval, MAC_Q0TFCR_TFE_POS, - MAC_Q0TFCR_TFE_LEN, 1); - /* Set pause time */ - regval = FXGMAC_SET_REG_BITS(regval, MAC_Q0TFCR_PT_POS, - MAC_Q0TFCR_PT_LEN, 0xffff); - - writereg(pdata->pAdapter, regval, pdata->mac_regs + reg); - - reg += MAC_QTFCR_INC; - } - - return 0; -} - -static int fxgmac_disable_rx_flow_control(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_RFCR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_RFCR_RFE_POS, - MAC_RFCR_RFE_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_RFCR); - - return 0; -} - -static int fxgmac_enable_rx_flow_control(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_RFCR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_RFCR_RFE_POS, - MAC_RFCR_RFE_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_RFCR); - - return 0; -} - -static int fxgmac_config_tx_flow_control(struct fxgmac_pdata *pdata) -{ - if (pdata->tx_pause) - fxgmac_enable_tx_flow_control(pdata); - else - fxgmac_disable_tx_flow_control(pdata); - - return 0; -} - -static int fxgmac_config_rx_flow_control(struct fxgmac_pdata *pdata) -{ - if (pdata->rx_pause) - fxgmac_enable_rx_flow_control(pdata); - else - fxgmac_disable_rx_flow_control(pdata); - - return 0; -} - -static int fxgmac_config_rx_coalesce(struct fxgmac_pdata *pdata) -{ -#ifndef DPDK - struct fxgmac_channel *channel; - unsigned int i; - u32 regval; - - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->rx_ring) - break; - - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_RIWT)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_RIWT_RWT_POS, - DMA_CH_RIWT_RWT_LEN, - pdata->rx_riwt); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_RIWT)); - } -#else - struct fxgmac_rx_queue *rxq; - unsigned int i; - - for (i = 0; i < pdata->expansion.eth_dev->data->nb_rx_queues; i++) { - rxq = pdata->expansion.eth_dev->data->rx_queues[i]; - FXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_RIWT, RWT, - pdata->rx_riwt); - } -#endif - - return 0; -} - -static void fxgmac_config_rx_fep_disable(struct fxgmac_pdata *pdata) -{ - unsigned int i; - u32 regval; - - for (i = 0; i < pdata->rx_q_count; i++) { - regval = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); - regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_FEP_POS, - MTL_Q_RQOMR_FEP_LEN, MTL_FEP_ENABLE);// 1:enable the rx queue forward packet with error status(crc error,gmii_er,watch dog timeout.or overflow) - writereg(pdata->pAdapter, regval, FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); - } -} - -static void fxgmac_config_rx_fup_enable(struct fxgmac_pdata *pdata) -{ - unsigned int i; - u32 regval; - - for (i = 0; i < pdata->rx_q_count; i++) { - regval = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); - regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_FUP_POS, - MTL_Q_RQOMR_FUP_LEN, 1); - writereg(pdata->pAdapter, regval, FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); - } -} - -static int fxgmac_config_tx_coalesce(struct fxgmac_pdata *pdata) -{ - pdata = pdata; - return 0; -} - -static void fxgmac_config_rx_buffer_size(struct fxgmac_pdata *pdata) -{ -#ifndef DPDK - struct fxgmac_channel *channel; - unsigned int i; - u32 regval; - - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->rx_ring) - break; - - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_RCR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_RCR_RBSZ_POS, - DMA_CH_RCR_RBSZ_LEN, - pdata->rx_buf_size); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_RCR)); - } -#else - struct fxgmac_rx_queue *rxq; - unsigned int i; - - for (i = 0; i < pdata->expansion.eth_dev->data->nb_rx_queues; i++) { - rxq = pdata->expansion.eth_dev->data->rx_queues[i]; - - rxq->buf_size = rte_pktmbuf_data_room_size(rxq->mb_pool) - - RTE_PKTMBUF_HEADROOM; - rxq->buf_size = (rxq->buf_size + FXGMAC_RX_BUF_ALIGN - 1) & - ~(FXGMAC_RX_BUF_ALIGN - 1); - - if (rxq->buf_size > pdata->rx_buf_size) - pdata->rx_buf_size = rxq->buf_size; - - FXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_RCR, RBSZ, - rxq->buf_size); - } -#endif -} - -static void fxgmac_config_tso_mode(struct fxgmac_pdata *pdata) -{ -#ifndef DPDK - struct fxgmac_channel *channel; - unsigned int i; - u32 regval; - - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) - break; - - if (pdata->hw_feat.tso) { - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_TCR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_TCR_TSE_POS, - DMA_CH_TCR_TSE_LEN, 1); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_TCR)); - } - } -#else - struct fxgmac_tx_queue *txq; - unsigned int i; - for (i = 0; i < pdata->expansion.eth_dev->data->nb_tx_queues; i++) { - txq = pdata->expansion.eth_dev->data->tx_queues[i]; - FXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, TSE, - pdata->tx_pbl); - } -#endif -} - -static void fxgmac_config_sph_mode(struct fxgmac_pdata *pdata) -{ - unsigned int i; - u32 regval; - -#ifndef DPDK - struct fxgmac_channel *channel; - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->rx_ring) - break; - - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_CR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_CR_SPH_POS, - DMA_CH_CR_SPH_LEN, 0); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_CR)); - } -#else - struct fxgmac_rx_queue *rxq; - - for (i = 0; i < pdata->expansion.eth_dev->data->nb_rx_queues; i++) { - rxq = pdata->expansion.eth_dev->data->rx_queues[i]; - FXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_CR, SPH, - pdata->rx_pbl); - } -#endif - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_ECR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_ECR_HDSMS_POS, - MAC_ECR_HDSMS_LEN, - FXGMAC_SPH_HDSMS_SIZE); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_ECR); -} - -static unsigned int fxgmac_usec_to_riwt(struct fxgmac_pdata *pdata, - unsigned int usec) -{ - unsigned long rate; - unsigned int ret; - - 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; - - return ret; -} - -static unsigned int fxgmac_riwt_to_usec(struct fxgmac_pdata *pdata, - unsigned int riwt) -{ - unsigned long rate; - unsigned int ret; - - 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); - - return ret; -} - -static int fxgmac_config_rx_threshold(struct fxgmac_pdata *pdata, - unsigned int val) -{ - unsigned int i; - u32 regval; - - for (i = 0; i < pdata->rx_q_count; i++) { - regval = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); - regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_RTC_POS, - MTL_Q_RQOMR_RTC_LEN, val); - writereg(pdata->pAdapter, regval, FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); - } - - return 0; -} - -static void fxgmac_config_mtl_mode(struct fxgmac_pdata *pdata) -{ - unsigned int i; - u32 regval; - - /* Set Tx to weighted round robin scheduling algorithm */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MTL_OMR); - regval = FXGMAC_SET_REG_BITS(regval, MTL_OMR_ETSALG_POS, - MTL_OMR_ETSALG_LEN, MTL_ETSALG_WRR); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MTL_OMR); -#if 1 - /* Set Tx traffic classes to use WRR algorithm with equal weights */ - for (i = 0; i < pdata->tx_q_count/*hw_feat.tc_cnt*/; i++) { - //regval = readreg(FXGMAC_MTL_REG(pdata, i, MTL_TC_ETSCR)); - //regval = FXGMAC_SET_REG_BITS(regval, MTL_TC_ETSCR_TSA_POS, - // MTL_TC_ETSCR_TSA_LEN, MTL_TSA_ETS); - //writereg(regval, FXGMAC_MTL_REG(pdata, i, MTL_TC_ETSCR)); - - regval = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_TC_QWR)); - regval = FXGMAC_SET_REG_BITS(regval, MTL_TC_QWR_QW_POS, - MTL_TC_QWR_QW_LEN, 1); - writereg(pdata->pAdapter, regval, FXGMAC_MTL_REG(pdata, i, MTL_TC_QWR)); - } -#endif - /* Set Rx to strict priority algorithm */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MTL_OMR); - regval = FXGMAC_SET_REG_BITS(regval, MTL_OMR_RAA_POS, - MTL_OMR_RAA_LEN, MTL_RAA_SP); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MTL_OMR); -} - -static void fxgmac_config_queue_mapping(struct fxgmac_pdata *pdata) -{ - unsigned int ppq, ppq_extra, prio, prio_queues; - //unsigned int qptc, qptc_extra; - unsigned int queue; - unsigned int reg, regval; - unsigned int mask; - unsigned int i, j; - - /* Map the MTL Tx Queues to Traffic Classes - * Note: Tx Queues >= Traffic Classes - */ -#if 0 - 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++) { - netif_dbg(pdata, drv, pdata->netdev, - "TXq%u mapped to TC%u\n", queue, i); - regval = readreg(FXGMAC_MTL_REG(pdata, queue, - MTL_Q_TQOMR)); - regval = FXGMAC_SET_REG_BITS(regval, - MTL_Q_TQOMR_Q2TCMAP_POS, - MTL_Q_TQOMR_Q2TCMAP_LEN, - i); - writereg(regval, FXGMAC_MTL_REG(pdata, queue, - MTL_Q_TQOMR)); - queue++; - } - - if (i < qptc_extra) { - netif_dbg(pdata, drv, pdata->netdev, - "TXq%u mapped to TC%u\n", queue, i); - regval = readreg(FXGMAC_MTL_REG(pdata, queue, - MTL_Q_TQOMR)); - regval = FXGMAC_SET_REG_BITS(regval, - MTL_Q_TQOMR_Q2TCMAP_POS, - MTL_Q_TQOMR_Q2TCMAP_LEN, - i); - writereg(regval, FXGMAC_MTL_REG(pdata, queue, - MTL_Q_TQOMR)); - queue++; - } - } -#else - queue = 0; - DPRINTK("need to map TXq(%u) to TC\n", queue); -#endif - /* 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; - regval = 0; - for (i = 0, prio = 0; i < prio_queues;) { - mask = 0; - for (j = 0; j < ppq; j++) { - netif_dbg(pdata, drv, pdata->netdev, - "PRIO%u mapped to RXq%u\n", prio, i); - mask |= (1 << prio); - prio++; - } - - if (i < ppq_extra) { - netif_dbg(pdata, drv, pdata->netdev, - "PRIO%u mapped to RXq%u\n", prio, i); - mask |= (1 << prio); - prio++; - } - - regval |= (mask << ((i++ % MAC_RQC2_Q_PER_REG) << 3)); - - if ((i % MAC_RQC2_Q_PER_REG) && (i != prio_queues)) - continue; - - writereg(pdata->pAdapter, regval, pdata->mac_regs + reg); - reg += MAC_RQC2_INC; - regval = 0; - } - - /* Configure one to one, MTL Rx queue to DMA Rx channel mapping - * ie Q0 <--> CH0, Q1 <--> CH1 ... Q11 <--> CH11 - */ - reg = MTL_RQDCM0R; - regval = readreg(pdata->pAdapter, pdata->mac_regs + reg); - regval |= (MTL_RQDCM0R_Q0MDMACH | MTL_RQDCM0R_Q1MDMACH | - MTL_RQDCM0R_Q2MDMACH | MTL_RQDCM0R_Q3MDMACH); - - if (pdata->rss) - { - /* in version later 0617, need to enable DA-based DMA Channel Selection to let RSS work, - * ie, bit4,12,20,28 for Q0,1,2,3 individual - */ - regval |= (MTL_RQDCM0R_Q0DDMACH | MTL_RQDCM0R_Q1DDMACH | - MTL_RQDCM0R_Q2DDMACH | MTL_RQDCM0R_Q3DDMACH); - } - - writereg(pdata->pAdapter, regval, pdata->mac_regs + reg); - - reg += MTL_RQDCM_INC; - regval = readreg(pdata->pAdapter, pdata->mac_regs + reg); - regval |= (MTL_RQDCM1R_Q4MDMACH | MTL_RQDCM1R_Q5MDMACH | - MTL_RQDCM1R_Q6MDMACH | MTL_RQDCM1R_Q7MDMACH); - writereg(pdata->pAdapter, regval, pdata->mac_regs + reg); -#if 0 - reg += MTL_RQDCM_INC; - regval = readreg(pdata->mac_regs + reg); - regval |= (MTL_RQDCM2R_Q8MDMACH | MTL_RQDCM2R_Q9MDMACH | - MTL_RQDCM2R_Q10MDMACH | MTL_RQDCM2R_Q11MDMACH); - writereg(regval, pdata->mac_regs + reg); -#endif -} - -static unsigned int fxgmac_calculate_per_queue_fifo( - unsigned int fifo_size, - unsigned int queue_count) -{ - unsigned int q_fifo_size; - unsigned int p_fifo; - - /* Calculate the configured fifo size */ - q_fifo_size = 1 << (fifo_size + 7); - - /* The configured value may not be the actual amount of fifo RAM */ - q_fifo_size = min_t(unsigned int, FXGMAC_MAX_FIFO, q_fifo_size); - - q_fifo_size = q_fifo_size / queue_count; - - /* Each increment in the queue fifo size represents 256 bytes of - * fifo, with 0 representing 256 bytes. Distribute the fifo equally - * between the queues. - */ - p_fifo = q_fifo_size / 256; - if (p_fifo) - p_fifo--; - - return p_fifo; -} - -static void fxgmac_config_tx_fifo_size(struct fxgmac_pdata *pdata) -{ - unsigned int fifo_size; - unsigned int i; - u32 regval; - - fifo_size = fxgmac_calculate_per_queue_fifo( - pdata->hw_feat.tx_fifo_size, - pdata->tx_q_count); - - for (i = 0; i < pdata->tx_q_count; i++) { - regval = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); - regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_TQS_POS, - MTL_Q_TQOMR_TQS_LEN, fifo_size); - writereg(pdata->pAdapter, regval, FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); - } - - netif_info(pdata, drv, pdata->netdev, - "%d Tx hardware queues, %d byte fifo per queue\n", - pdata->tx_q_count, ((fifo_size + 1) * 256)); -} - -static void fxgmac_config_rx_fifo_size(struct fxgmac_pdata *pdata) -{ - unsigned int fifo_size; - unsigned int i; - u32 regval; - - fifo_size = fxgmac_calculate_per_queue_fifo( - pdata->hw_feat.rx_fifo_size, - pdata->rx_q_count); - - for (i = 0; i < pdata->rx_q_count; i++) { - regval = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); - regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_RQS_POS, - MTL_Q_RQOMR_RQS_LEN, fifo_size); - writereg(pdata->pAdapter, regval, FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); - } - - netif_info(pdata, drv, pdata->netdev, - "%d Rx hardware queues, %d byte fifo per queue\n", - pdata->rx_q_count, ((fifo_size + 1) * 256)); -} - -static void fxgmac_config_flow_control_threshold(struct fxgmac_pdata *pdata) -{ - unsigned int i; - u32 regval; - - for (i = 0; i < pdata->rx_q_count; i++) { - regval = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); - /* Activate flow control when less than 6k left in fifo */ - //In windows driver,it sets the value 6, but in Linux it sets the value 10. Here it uses value that exists in windows driver - regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_RFA_POS, MTL_Q_RQOMR_RFA_LEN, 6); - /* De-activate flow control when more than 10k left in fifo */ - regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_RFD_POS, MTL_Q_RQOMR_RFD_LEN, 10); - writereg(pdata->pAdapter, regval, FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); - } -} - -static int fxgmac_config_tx_threshold(struct fxgmac_pdata *pdata, - unsigned int val) -{ - unsigned int i; - u32 regval; - - for (i = 0; i < pdata->tx_q_count; i++) { - regval = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); - regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_TTC_POS, - MTL_Q_TQOMR_TTC_LEN, val); - writereg(pdata->pAdapter, regval, FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); - } - - return 0; -} - -static int fxgmac_config_rsf_mode(struct fxgmac_pdata *pdata, - unsigned int val) -{ - unsigned int i; - u32 regval; - - for (i = 0; i < pdata->rx_q_count; i++) { - regval = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); - regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_RSF_POS, - MTL_Q_RQOMR_RSF_LEN, val); - writereg(pdata->pAdapter, regval, FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); - } - - return 0; -} - -static int fxgmac_config_tsf_mode(struct fxgmac_pdata *pdata, - unsigned int val) -{ - unsigned int i; - u32 regval; - - for (i = 0; i < pdata->tx_q_count; i++) { - regval = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); - regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_TSF_POS, - MTL_Q_TQOMR_TSF_LEN, val); - writereg(pdata->pAdapter, regval, FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); - } - - return 0; -} - -static int fxgmac_config_osp_mode(struct fxgmac_pdata *pdata) -{ -#ifndef DPDK - struct fxgmac_channel *channel; - unsigned int i; - u32 regval; - - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) - break; - - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_TCR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_TCR_OSP_POS, - DMA_CH_TCR_OSP_LEN, - pdata->tx_osp_mode); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_TCR)); - } -#else - /* Force DMA to operate on second packet before closing descriptors - * of first packet - */ - struct fxgmac_tx_queue *txq; - unsigned int i; - - for (i = 0; i < pdata->expansion.eth_dev->data->nb_tx_queues; i++) { - txq = pdata->expansion.eth_dev->data->tx_queues[i]; - FXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, OSP, - pdata->tx_osp_mode); - } -#endif - return 0; -} - -static int fxgmac_config_pblx8(struct fxgmac_pdata *pdata) -{ -#ifndef DPDK - struct fxgmac_channel *channel; - unsigned int i; - u32 regval; - - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_CR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_CR_PBLX8_POS, - DMA_CH_CR_PBLX8_LEN, - pdata->pblx8); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_CR)); - } -#else - struct fxgmac_tx_queue *txq; - unsigned int i; - - for (i = 0; i < pdata->expansion.eth_dev->data->nb_tx_queues; i++) { - txq = pdata->expansion.eth_dev->data->tx_queues[i]; - FXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_CR, PBLX8, - pdata->pblx8); - } -#endif - - return 0; -} - -static int fxgmac_get_tx_pbl_val(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(pdata->channel_head, DMA_CH_TCR)); - regval = FXGMAC_GET_REG_BITS(regval, DMA_CH_TCR_PBL_POS, - DMA_CH_TCR_PBL_LEN); - return regval; -} - -static int fxgmac_config_tx_pbl_val(struct fxgmac_pdata *pdata) -{ -#ifndef DPDK - struct fxgmac_channel *channel; - unsigned int i; - u32 regval; - - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) - break; - - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_TCR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_TCR_PBL_POS, - DMA_CH_TCR_PBL_LEN, - pdata->tx_pbl); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_TCR)); - } -#else - struct fxgmac_tx_queue *txq; - unsigned int i; - - for (i = 0; i < pdata->expansion.eth_dev->data->nb_tx_queues; i++) { - txq = pdata->expansion.eth_dev->data->tx_queues[i]; - FXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, PBL, - pdata->tx_pbl); - } -#endif - - return 0; -} - -static int fxgmac_get_rx_pbl_val(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(pdata->channel_head, DMA_CH_RCR)); - regval = FXGMAC_GET_REG_BITS(regval, DMA_CH_RCR_PBL_POS, - DMA_CH_RCR_PBL_LEN); - return regval; -} - -static int fxgmac_config_rx_pbl_val(struct fxgmac_pdata *pdata) -{ -#ifndef DPDK - struct fxgmac_channel *channel; - unsigned int i; - u32 regval; - - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->rx_ring) - break; - - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_RCR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_RCR_PBL_POS, - DMA_CH_RCR_PBL_LEN, - pdata->rx_pbl); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_RCR)); - } -#else - struct fxgmac_rx_queue *rxq; - unsigned int i; - - for (i = 0; i < pdata->expansion.eth_dev->data->nb_rx_queues; i++) { - rxq = pdata->expansion.eth_dev->data->rx_queues[i]; - FXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_RCR, PBL, - pdata->rx_pbl); - } -#endif - - return 0; -} - -static u64 fxgmac_mmc_read(struct fxgmac_pdata *pdata, unsigned int reg_lo) -{ - /* bool read_hi; */ - u64 val; -#if 0 - 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; - } -#endif - val = (u64)readreg(pdata->pAdapter, pdata->mac_regs + reg_lo); - - /* - if (read_hi) - val |= ((u64)readreg(pdata->mac_regs + reg_lo + 4) << 32); - */ - - return val; -} - -static void fxgmac_tx_mmc_int(struct fxgmac_pdata *pdata) -{ - unsigned int mmc_isr = readreg(pdata->pAdapter, pdata->mac_regs + MMC_TISR); - struct fxgmac_stats *stats = &pdata->stats; - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXOCTETCOUNT_GB_POS, - MMC_TISR_TXOCTETCOUNT_GB_LEN)) - stats->txoctetcount_gb += - fxgmac_mmc_read(pdata, MMC_TXOCTETCOUNT_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXFRAMECOUNT_GB_POS, - MMC_TISR_TXFRAMECOUNT_GB_LEN)) - stats->txframecount_gb += - fxgmac_mmc_read(pdata, MMC_TXFRAMECOUNT_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXBROADCASTFRAMES_G_POS, - MMC_TISR_TXBROADCASTFRAMES_G_LEN)) - stats->txbroadcastframes_g += - fxgmac_mmc_read(pdata, MMC_TXBROADCASTFRAMES_G_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXMULTICASTFRAMES_G_POS, - MMC_TISR_TXMULTICASTFRAMES_G_LEN)) - stats->txmulticastframes_g += - fxgmac_mmc_read(pdata, MMC_TXMULTICASTFRAMES_G_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TX64OCTETS_GB_POS, - MMC_TISR_TX64OCTETS_GB_LEN)) - stats->tx64octets_gb += - fxgmac_mmc_read(pdata, MMC_TX64OCTETS_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TX65TO127OCTETS_GB_POS, - MMC_TISR_TX65TO127OCTETS_GB_LEN)) - stats->tx65to127octets_gb += - fxgmac_mmc_read(pdata, MMC_TX65TO127OCTETS_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TX128TO255OCTETS_GB_POS, - MMC_TISR_TX128TO255OCTETS_GB_LEN)) - stats->tx128to255octets_gb += - fxgmac_mmc_read(pdata, MMC_TX128TO255OCTETS_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TX256TO511OCTETS_GB_POS, - MMC_TISR_TX256TO511OCTETS_GB_LEN)) - stats->tx256to511octets_gb += - fxgmac_mmc_read(pdata, MMC_TX256TO511OCTETS_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TX512TO1023OCTETS_GB_POS, - MMC_TISR_TX512TO1023OCTETS_GB_LEN)) - stats->tx512to1023octets_gb += - fxgmac_mmc_read(pdata, MMC_TX512TO1023OCTETS_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TX1024TOMAXOCTETS_GB_POS, - MMC_TISR_TX1024TOMAXOCTETS_GB_LEN)) - stats->tx1024tomaxoctets_gb += - fxgmac_mmc_read(pdata, MMC_TX1024TOMAXOCTETS_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXUNICASTFRAMES_GB_POS, - MMC_TISR_TXUNICASTFRAMES_GB_LEN)) - stats->txunicastframes_gb += - fxgmac_mmc_read(pdata, MMC_TXUNICASTFRAMES_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXMULTICASTFRAMES_GB_POS, - MMC_TISR_TXMULTICASTFRAMES_GB_LEN)) - stats->txmulticastframes_gb += - fxgmac_mmc_read(pdata, MMC_TXMULTICASTFRAMES_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXBROADCASTFRAMES_GB_POS, - MMC_TISR_TXBROADCASTFRAMES_GB_LEN)) - stats->txbroadcastframes_g += - fxgmac_mmc_read(pdata, MMC_TXBROADCASTFRAMES_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXUNDERFLOWERROR_POS, - MMC_TISR_TXUNDERFLOWERROR_LEN)) - stats->txunderflowerror += - fxgmac_mmc_read(pdata, MMC_TXUNDERFLOWERROR_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXSINGLECOLLISION_G_POS, - MMC_TISR_TXSINGLECOLLISION_G_LEN)) - stats->txsinglecollision_g += - fxgmac_mmc_read(pdata, MMC_TXSINGLECOLLISION_G); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXMULTIPLECOLLISION_G_POS, - MMC_TISR_TXMULTIPLECOLLISION_G_LEN)) - stats->txmultiplecollision_g += - fxgmac_mmc_read(pdata, MMC_TXMULTIPLECOLLISION_G); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXDEFERREDFRAMES_POS, - MMC_TISR_TXDEFERREDFRAMES_LEN)) - stats->txdeferredframes += - fxgmac_mmc_read(pdata, MMC_TXDEFERREDFRAMES); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXLATECOLLISIONFRAMES_POS, - MMC_TISR_TXLATECOLLISIONFRAMES_LEN)) - stats->txlatecollisionframes += - fxgmac_mmc_read(pdata, MMC_TXLATECOLLISIONFRAMES); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXEXCESSIVECOLLISIONFRAMES_POS, - MMC_TISR_TXEXCESSIVECOLLISIONFRAMES_LEN)) - stats->txexcessivecollisionframes += - fxgmac_mmc_read(pdata, MMC_TXEXCESSIVECOLLSIONFRAMES); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXCARRIERERRORFRAMES_POS, - MMC_TISR_TXCARRIERERRORFRAMES_LEN)) - stats->txcarriererrorframes += - fxgmac_mmc_read(pdata, MMC_TXCARRIERERRORFRAMES); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXOCTETCOUNT_G_POS, - MMC_TISR_TXOCTETCOUNT_G_LEN)) - stats->txoctetcount_g += - fxgmac_mmc_read(pdata, MMC_TXOCTETCOUNT_G_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXFRAMECOUNT_G_POS, - MMC_TISR_TXFRAMECOUNT_G_LEN)) - stats->txframecount_g += - fxgmac_mmc_read(pdata, MMC_TXFRAMECOUNT_G_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXEXCESSIVEDEFERRALFRAMES_POS, - MMC_TISR_TXEXCESSIVEDEFERRALFRAMES_LEN)) - stats->txexcessivedeferralerror += - fxgmac_mmc_read(pdata, MMC_TXEXCESSIVEDEFERRALERROR); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXPAUSEFRAMES_POS, - MMC_TISR_TXPAUSEFRAMES_LEN)) - stats->txpauseframes += - fxgmac_mmc_read(pdata, MMC_TXPAUSEFRAMES_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXVLANFRAMES_G_POS, - MMC_TISR_TXVLANFRAMES_G_LEN)) - stats->txvlanframes_g += - fxgmac_mmc_read(pdata, MMC_TXVLANFRAMES_G_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_TISR_TXOVERSIZE_G_POS, - MMC_TISR_TXOVERSIZE_G_LEN)) - stats->txoversize_g += - fxgmac_mmc_read(pdata, MMC_TXOVERSIZEFRAMES); -} - -static void fxgmac_rx_mmc_int(struct fxgmac_pdata *pdata) -{ - unsigned int mmc_isr = readreg(pdata->pAdapter, pdata->mac_regs + MMC_RISR); - struct fxgmac_stats *stats = &pdata->stats; - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXFRAMECOUNT_GB_POS, - MMC_RISR_RXFRAMECOUNT_GB_LEN)) - stats->rxframecount_gb += - fxgmac_mmc_read(pdata, MMC_RXFRAMECOUNT_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXOCTETCOUNT_GB_POS, - MMC_RISR_RXOCTETCOUNT_GB_LEN)) - stats->rxoctetcount_gb += - fxgmac_mmc_read(pdata, MMC_RXOCTETCOUNT_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXOCTETCOUNT_G_POS, - MMC_RISR_RXOCTETCOUNT_G_LEN)) - stats->rxoctetcount_g += - fxgmac_mmc_read(pdata, MMC_RXOCTETCOUNT_G_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXBROADCASTFRAMES_G_POS, - MMC_RISR_RXBROADCASTFRAMES_G_LEN)) - stats->rxbroadcastframes_g += - fxgmac_mmc_read(pdata, MMC_RXBROADCASTFRAMES_G_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXMULTICASTFRAMES_G_POS, - MMC_RISR_RXMULTICASTFRAMES_G_LEN)) - stats->rxmulticastframes_g += - fxgmac_mmc_read(pdata, MMC_RXMULTICASTFRAMES_G_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXCRCERROR_POS, - MMC_RISR_RXCRCERROR_LEN)) - stats->rxcrcerror += - fxgmac_mmc_read(pdata, MMC_RXCRCERROR_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXALIGNERROR_POS, - MMC_RISR_RXALIGNERROR_LEN)) - stats->rxalignerror += - fxgmac_mmc_read(pdata, MMC_RXALIGNERROR); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXRUNTERROR_POS, - MMC_RISR_RXRUNTERROR_LEN)) - stats->rxrunterror += - fxgmac_mmc_read(pdata, MMC_RXRUNTERROR); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXJABBERERROR_POS, - MMC_RISR_RXJABBERERROR_LEN)) - stats->rxjabbererror += - fxgmac_mmc_read(pdata, MMC_RXJABBERERROR); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXUNDERSIZE_G_POS, - MMC_RISR_RXUNDERSIZE_G_LEN)) - stats->rxundersize_g += - fxgmac_mmc_read(pdata, MMC_RXUNDERSIZE_G); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXOVERSIZE_G_POS, - MMC_RISR_RXOVERSIZE_G_LEN)) - stats->rxoversize_g += - fxgmac_mmc_read(pdata, MMC_RXOVERSIZE_G); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RX64OCTETS_GB_POS, - MMC_RISR_RX64OCTETS_GB_LEN)) - stats->rx64octets_gb += - fxgmac_mmc_read(pdata, MMC_RX64OCTETS_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RX65TO127OCTETS_GB_POS, - MMC_RISR_RX65TO127OCTETS_GB_LEN)) - stats->rx65to127octets_gb += - fxgmac_mmc_read(pdata, MMC_RX65TO127OCTETS_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RX128TO255OCTETS_GB_POS, - MMC_RISR_RX128TO255OCTETS_GB_LEN)) - stats->rx128to255octets_gb += - fxgmac_mmc_read(pdata, MMC_RX128TO255OCTETS_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RX256TO511OCTETS_GB_POS, - MMC_RISR_RX256TO511OCTETS_GB_LEN)) - stats->rx256to511octets_gb += - fxgmac_mmc_read(pdata, MMC_RX256TO511OCTETS_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RX512TO1023OCTETS_GB_POS, - MMC_RISR_RX512TO1023OCTETS_GB_LEN)) - stats->rx512to1023octets_gb += - fxgmac_mmc_read(pdata, MMC_RX512TO1023OCTETS_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RX1024TOMAXOCTETS_GB_POS, - MMC_RISR_RX1024TOMAXOCTETS_GB_LEN)) - stats->rx1024tomaxoctets_gb += - fxgmac_mmc_read(pdata, MMC_RX1024TOMAXOCTETS_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXUNICASTFRAMES_G_POS, - MMC_RISR_RXUNICASTFRAMES_G_LEN)) - stats->rxunicastframes_g += - fxgmac_mmc_read(pdata, MMC_RXUNICASTFRAMES_G_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXLENGTHERROR_POS, - MMC_RISR_RXLENGTHERROR_LEN)) - stats->rxlengtherror += - fxgmac_mmc_read(pdata, MMC_RXLENGTHERROR_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXOUTOFRANGETYPE_POS, - MMC_RISR_RXOUTOFRANGETYPE_LEN)) - stats->rxoutofrangetype += - fxgmac_mmc_read(pdata, MMC_RXOUTOFRANGETYPE_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXPAUSEFRAMES_POS, - MMC_RISR_RXPAUSEFRAMES_LEN)) - stats->rxpauseframes += - fxgmac_mmc_read(pdata, MMC_RXPAUSEFRAMES_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXFIFOOVERFLOW_POS, - MMC_RISR_RXFIFOOVERFLOW_LEN)) - stats->rxfifooverflow += - fxgmac_mmc_read(pdata, MMC_RXFIFOOVERFLOW_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXVLANFRAMES_GB_POS, - MMC_RISR_RXVLANFRAMES_GB_LEN)) - stats->rxvlanframes_gb += - fxgmac_mmc_read(pdata, MMC_RXVLANFRAMES_GB_LO); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXWATCHDOGERROR_POS, - MMC_RISR_RXWATCHDOGERROR_LEN)) - stats->rxwatchdogerror += - fxgmac_mmc_read(pdata, MMC_RXWATCHDOGERROR); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXERRORFRAMES_POS, - MMC_RISR_RXERRORFRAMES_LEN)) - stats->rxreceiveerrorframe += - fxgmac_mmc_read(pdata, MMC_RXRECEIVEERRORFRAME); - - if (FXGMAC_GET_REG_BITS(mmc_isr, - MMC_RISR_RXERRORCONTROLFRAMES_POS, - MMC_RISR_RXERRORCONTROLFRAMES_LEN)) - stats->rxcontrolframe_g += - fxgmac_mmc_read(pdata, MMC_RXCONTROLFRAME_G); -} - -static void fxgmac_read_mmc_stats(struct fxgmac_pdata *pdata) -{ - struct fxgmac_stats *stats = &pdata->stats; - u32 regval; - - /* Freeze counters */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MMC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MMC_CR_MCF_POS, - MMC_CR_MCF_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MMC_CR); - - stats->txoctetcount_gb += - fxgmac_mmc_read(pdata, MMC_TXOCTETCOUNT_GB_LO); - - stats->txframecount_gb += - fxgmac_mmc_read(pdata, MMC_TXFRAMECOUNT_GB_LO); - - stats->txbroadcastframes_g += - fxgmac_mmc_read(pdata, MMC_TXBROADCASTFRAMES_G_LO); - - stats->txmulticastframes_g += - fxgmac_mmc_read(pdata, MMC_TXMULTICASTFRAMES_G_LO); - - stats->tx64octets_gb += - fxgmac_mmc_read(pdata, MMC_TX64OCTETS_GB_LO); - - stats->tx65to127octets_gb += - fxgmac_mmc_read(pdata, MMC_TX65TO127OCTETS_GB_LO); - - stats->tx128to255octets_gb += - fxgmac_mmc_read(pdata, MMC_TX128TO255OCTETS_GB_LO); - - stats->tx256to511octets_gb += - fxgmac_mmc_read(pdata, MMC_TX256TO511OCTETS_GB_LO); - - stats->tx512to1023octets_gb += - fxgmac_mmc_read(pdata, MMC_TX512TO1023OCTETS_GB_LO); - - stats->tx1024tomaxoctets_gb += - fxgmac_mmc_read(pdata, MMC_TX1024TOMAXOCTETS_GB_LO); - - stats->txunicastframes_gb += - fxgmac_mmc_read(pdata, MMC_TXUNICASTFRAMES_GB_LO); - - stats->txmulticastframes_gb += - fxgmac_mmc_read(pdata, MMC_TXMULTICASTFRAMES_GB_LO); - - stats->txbroadcastframes_g += - fxgmac_mmc_read(pdata, MMC_TXBROADCASTFRAMES_GB_LO); - - stats->txunderflowerror += - fxgmac_mmc_read(pdata, MMC_TXUNDERFLOWERROR_LO); - - stats->txsinglecollision_g += - fxgmac_mmc_read(pdata, MMC_TXSINGLECOLLISION_G); - - stats->txmultiplecollision_g += - fxgmac_mmc_read(pdata, MMC_TXMULTIPLECOLLISION_G); - - stats->txdeferredframes += - fxgmac_mmc_read(pdata, MMC_TXDEFERREDFRAMES); - - stats->txlatecollisionframes += - fxgmac_mmc_read(pdata, MMC_TXLATECOLLISIONFRAMES); - - stats->txexcessivecollisionframes += - fxgmac_mmc_read(pdata, MMC_TXEXCESSIVECOLLSIONFRAMES); - - stats->txcarriererrorframes += - fxgmac_mmc_read(pdata, MMC_TXCARRIERERRORFRAMES); - - stats->txoctetcount_g += - fxgmac_mmc_read(pdata, MMC_TXOCTETCOUNT_G_LO); - - stats->txframecount_g += - fxgmac_mmc_read(pdata, MMC_TXFRAMECOUNT_G_LO); - - stats->txexcessivedeferralerror += - fxgmac_mmc_read(pdata, MMC_TXEXCESSIVEDEFERRALERROR); - - stats->txpauseframes += - fxgmac_mmc_read(pdata, MMC_TXPAUSEFRAMES_LO); - - stats->txvlanframes_g += - fxgmac_mmc_read(pdata, MMC_TXVLANFRAMES_G_LO); - - stats->txoversize_g += - fxgmac_mmc_read(pdata, MMC_TXOVERSIZEFRAMES); - - stats->rxframecount_gb += - fxgmac_mmc_read(pdata, MMC_RXFRAMECOUNT_GB_LO); - - stats->rxoctetcount_gb += - fxgmac_mmc_read(pdata, MMC_RXOCTETCOUNT_GB_LO); - - stats->rxoctetcount_g += - fxgmac_mmc_read(pdata, MMC_RXOCTETCOUNT_G_LO); - - stats->rxbroadcastframes_g += - fxgmac_mmc_read(pdata, MMC_RXBROADCASTFRAMES_G_LO); - - stats->rxmulticastframes_g += - fxgmac_mmc_read(pdata, MMC_RXMULTICASTFRAMES_G_LO); - - stats->rxcrcerror += - fxgmac_mmc_read(pdata, MMC_RXCRCERROR_LO); - - stats->rxalignerror += - fxgmac_mmc_read(pdata, MMC_RXALIGNERROR); - - stats->rxrunterror += - fxgmac_mmc_read(pdata, MMC_RXRUNTERROR); - - stats->rxjabbererror += - fxgmac_mmc_read(pdata, MMC_RXJABBERERROR); - - stats->rxundersize_g += - fxgmac_mmc_read(pdata, MMC_RXUNDERSIZE_G); - - stats->rxoversize_g += - fxgmac_mmc_read(pdata, MMC_RXOVERSIZE_G); - - stats->rx64octets_gb += - fxgmac_mmc_read(pdata, MMC_RX64OCTETS_GB_LO); - - stats->rx65to127octets_gb += - fxgmac_mmc_read(pdata, MMC_RX65TO127OCTETS_GB_LO); - - stats->rx128to255octets_gb += - fxgmac_mmc_read(pdata, MMC_RX128TO255OCTETS_GB_LO); - - stats->rx256to511octets_gb += - fxgmac_mmc_read(pdata, MMC_RX256TO511OCTETS_GB_LO); - - stats->rx512to1023octets_gb += - fxgmac_mmc_read(pdata, MMC_RX512TO1023OCTETS_GB_LO); - - stats->rx1024tomaxoctets_gb += - fxgmac_mmc_read(pdata, MMC_RX1024TOMAXOCTETS_GB_LO); - - stats->rxunicastframes_g += - fxgmac_mmc_read(pdata, MMC_RXUNICASTFRAMES_G_LO); - - stats->rxlengtherror += - fxgmac_mmc_read(pdata, MMC_RXLENGTHERROR_LO); - - stats->rxoutofrangetype += - fxgmac_mmc_read(pdata, MMC_RXOUTOFRANGETYPE_LO); - - stats->rxpauseframes += - fxgmac_mmc_read(pdata, MMC_RXPAUSEFRAMES_LO); - - stats->rxfifooverflow += - fxgmac_mmc_read(pdata, MMC_RXFIFOOVERFLOW_LO); - - stats->rxvlanframes_gb += - fxgmac_mmc_read(pdata, MMC_RXVLANFRAMES_GB_LO); - - stats->rxwatchdogerror += - fxgmac_mmc_read(pdata, MMC_RXWATCHDOGERROR); - - stats->rxreceiveerrorframe += - fxgmac_mmc_read(pdata, MMC_RXRECEIVEERRORFRAME); - - stats->rxcontrolframe_g += - fxgmac_mmc_read(pdata, MMC_RXCONTROLFRAME_G); - - /* Un-freeze counters */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MMC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MMC_CR_MCF_POS, - MMC_CR_MCF_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MMC_CR); -} - -static void fxgmac_config_mmc(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MMC_CR); - /* Set counters to reset on read */ - regval = FXGMAC_SET_REG_BITS(regval, MMC_CR_ROR_POS, - MMC_CR_ROR_LEN, 1); - /* Reset the counters */ - regval = FXGMAC_SET_REG_BITS(regval, MMC_CR_CR_POS, - MMC_CR_CR_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MMC_CR); - -#if defined(FUXI_MISC_INT_HANDLE_FEATURE_EN) && FUXI_MISC_INT_HANDLE_FEATURE_EN - //disable interrupts for rx Tcp and ip good pkt counter which is not read by MMC counter process. - //regval = readreg(pdata->mac_regs + 0x800); - writereg(pdata->pAdapter, 0xffffffff, pdata->mac_regs + MMC_IPCRXINTMASK); -#endif -} - -static int fxgmac_write_rss_reg(struct fxgmac_pdata *pdata, unsigned int type, - unsigned int index, unsigned int val) -{ - int ret = 0; - type = type; - - writereg(pdata->pAdapter, val, (pdata->base_mem+ index)); - - return ret; -} - -static u32 fxgmac_read_rss_options(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_RSS_CTRL); - - /* Get the RSS options bits */ - regval = FXGMAC_GET_REG_BITS(regval, MGMT_RSS_CTRL_OPT_POS, MGMT_RSS_CTRL_OPT_LEN); - - return regval; -} - -static int fxgmac_write_rss_options(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_RSS_CTRL); - - /* Set the RSS options */ - regval = FXGMAC_SET_REG_BITS(regval, MGMT_RSS_CTRL_OPT_POS, - MGMT_RSS_CTRL_OPT_LEN, pdata->rss_options); - - writereg(pdata->pAdapter, regval, (pdata->base_mem + MGMT_RSS_CTRL)); - - return 0; -} - -#if !defined(DPDK) -static int fxgmac_read_rss_hash_key(struct fxgmac_pdata *pdata, u8 *key_buf) -{ - //struct net_device *netdev = pdata->netdev; - unsigned int key_regs = sizeof(pdata->rss_key) / sizeof(u32); - u32 *key = (u32 *)key_buf; - - while (key_regs--) { - (*key) = cpu_to_be32(readreg(pdata->pAdapter, pdata->base_mem + (MGMT_RSS_KEY0 + key_regs * MGMT_RSS_KEY_REG_INC))) ; - - DBGPRINT(MP_LOUD, ("fxgmac_read_rss_hash_key: idx=%d, reg=%x, key=0x%08x\n", - key_regs, MGMT_RSS_KEY0 + key_regs * MGMT_RSS_KEY_REG_INC, (u32)(*key))); - key++; - } - - return 0; -} -#endif - -static int fxgmac_write_rss_hash_key(struct fxgmac_pdata *pdata) -{ - unsigned int key_regs = sizeof(pdata->rss_key) / sizeof(u32); - u32 *key = (u32 *)&pdata->rss_key; - int ret; - - while (key_regs--) { - ret = fxgmac_write_rss_reg(pdata, FXGMAC_RSS_HASH_KEY_TYPE, - MGMT_RSS_KEY0 + key_regs * MGMT_RSS_KEY_REG_INC, cpu_to_be32 (*key)); - if (ret) - return ret; - key++; - } - - return 0; -} - -static int fxgmac_write_rss_lookup_table(struct fxgmac_pdata *pdata) -{ - unsigned int i, j; - u32 regval = 0; - int ret; - - for (i = 0, j = 0; i < ARRAY_SIZE(pdata->rss_table); i++, j++) { - if(j < MGMT_RSS_IDT_ENTRY_PER_REG) - { - regval |= ((pdata->rss_table[i] & MGMT_RSS_IDT_ENTRY_MASK) << (j * 2)); - }else{ - ret = fxgmac_write_rss_reg(pdata, - FXGMAC_RSS_LOOKUP_TABLE_TYPE, MGMT_RSS_IDT + (i / MGMT_RSS_IDT_ENTRY_PER_REG - 1) * MGMT_RSS_IDT_REG_INC, - regval); - if (ret) - return ret; - - regval = pdata->rss_table[i]; - j = 0; - } - } - - if (j == MGMT_RSS_IDT_ENTRY_PER_REG) - { - //last IDT - fxgmac_write_rss_reg(pdata, - FXGMAC_RSS_LOOKUP_TABLE_TYPE, MGMT_RSS_IDT + (i / MGMT_RSS_IDT_ENTRY_PER_REG - 1) * MGMT_RSS_IDT_REG_INC, - regval); - } - - return 0; -} - -static int fxgmac_set_rss_hash_key(struct fxgmac_pdata *pdata, const u8 *key) -{ - memcpy(pdata->rss_key, key, sizeof(pdata->rss_key));//CopyMem - - return fxgmac_write_rss_hash_key(pdata); -} - -static int fxgmac_set_rss_lookup_table(struct fxgmac_pdata *pdata, - const u32 *table) -{ - unsigned int i; - u32 tval; - -#if FXGMAC_MSIX_CH0RXDIS_EN - DPRINTK("Set_rss_table, rss ctrl eth=0x%08x\n", 0); - - return 0; -#endif - - for (i = 0; i < ARRAY_SIZE(pdata->rss_table); i++) { - tval = table[i]; - pdata->rss_table[i] = FXGMAC_SET_REG_BITS( - pdata->rss_table[i], - MAC_RSSDR_DMCH_POS, - MAC_RSSDR_DMCH_LEN, - tval); - } - - return fxgmac_write_rss_lookup_table(pdata); -} - -static u32 log2ex(u32 value) -{ - u32 i = 31; - while (i > 0) - { - if (value & 0x80000000) - { - break; - } - value <<= 1; - i--; - } - return i; -} - -static int fxgmac_enable_rss(struct fxgmac_pdata* pdata) -{ - u32 regval; - u32 size = 0; - -#ifdef LINUX - int ret; - - if (!pdata->hw_feat.rss) { - return -EOPNOTSUPP; - } - - /* Program the hash key */ - ret = fxgmac_write_rss_hash_key(pdata); - if (ret) { - return ret; - } - - /* Program the lookup table */ - ret = fxgmac_write_rss_lookup_table(pdata); - if (ret) { - return ret; - } -#endif - - regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_RSS_CTRL); - - //2022-04-19 xiaojiang comment - //In Linux driver, it does not set the IDT table size, but windos implement it, so linux driver follow it. - /* Set RSS IDT table size */ - size = log2ex(FXGMAC_RSS_MAX_TABLE_SIZE) - 1; - regval = FXGMAC_SET_REG_BITS(regval, MGMT_RSS_CTRL_TBL_SIZE_POS, - MGMT_RSS_CTRL_TBL_SIZE_LEN, size); - -#if FXGMAC_MSIX_CH0RXDIS_EN - /* set default cpu id to 1 */ - regval = FXGMAC_SET_REG_BITS(regval, 8, - 2, 1); -#endif - /* Enable RSS */ - regval = FXGMAC_SET_REG_BITS(regval, MAC_RSSCR_RSSE_POS, - MAC_RSSCR_RSSE_LEN, 1); - - /* Set the RSS options */ - regval = FXGMAC_SET_REG_BITS(regval, MGMT_RSS_CTRL_OPT_POS, - MGMT_RSS_CTRL_OPT_LEN, pdata->rss_options); - - writereg(pdata->pAdapter, regval, (pdata->base_mem + MGMT_RSS_CTRL)); - DPRINTK("enable_rss callout, rss ctrl reg=0x%08x\n", regval); - - return 0; -} - -static int fxgmac_disable_rss(struct fxgmac_pdata *pdata) -{ - u32 regval; - - if (!pdata->hw_feat.rss) - return -EOPNOTSUPP; - -#if FXGMAC_MSIX_CH0RXDIS_EN - DPRINTK("Disable_rss, rss ctrl eth=0x%08x\n", 0); - - return 0; -#endif - - regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_RSS_CTRL); - regval = FXGMAC_SET_REG_BITS(regval, MAC_RSSCR_RSSE_POS, - MAC_RSSCR_RSSE_LEN, 0); - - writereg(pdata->pAdapter, regval, (pdata->base_mem + MGMT_RSS_CTRL)); - DPRINTK("disable_rss, rss ctrl reg=0x%08x\n", regval); - - return 0; -} - -static void fxgmac_config_rss(struct fxgmac_pdata *pdata) -{ - int ret; - - if (!pdata->hw_feat.rss) - return; - - if (pdata->rss) - ret = fxgmac_enable_rss(pdata); - else - ret = fxgmac_disable_rss(pdata); - - if (ret) - DBGPRINT(MP_ERROR, ("fxgmac_config_rss: error configuring RSS\n")); -} - -#if defined(LINUX) || defined(_WIN64) || defined(_WIN32) -// -void fxgmac_update_aoe_ipv4addr(struct fxgmac_pdata* pdata, u8* ip_addr) -{ - unsigned int regval, ipval = 0; - - /* enable or disable ARP offload engine. */ - if (!pdata->hw_feat.aoe) { - netdev_err(pdata->netdev, "error update ip addr - arp offload not supported.\n"); - return; - } - -#if 0 - if(ip_addr) { - sscanf(ip_addr, "%x.%x.%x.%x", (unsigned int *)&tmp32[0], (unsigned int *)&tmp32[1], (unsigned int *)&tmp32[2], (unsigned int *)&tmp32[3]); - tmp[0] = (uint8_t)tmp32[0]; - tmp[1] = (uint8_t)tmp32[1]; - tmp[2] = (uint8_t)tmp32[2]; - tmp[3] = (uint8_t)tmp32[3]; - } else - { - ipval = 0; //0xc0a801ca; //here just hard code to 192.168.1.202 - } -#endif - - if(ip_addr) { - //inet_aton((const char *)ip_addr, (struct in_addr *)&ipval); - //ipval = (unsigned int)in_aton((const char *)ip_addr); - ipval = (ip_addr[0] << 24) | (ip_addr[1] << 16) | (ip_addr[2] << 8) | (ip_addr[3] << 0); - DPRINTK("%s, covert IP dotted-addr %s to binary 0x%08x ok.\n", __FUNCTION__, ip_addr, cpu_to_be32(ipval)); - } else - { -#ifdef LINUX - /* get ipv4 addr from net device */ - //2022-04-25 xiaojiang Linux Driver behavior - ipval = fxgmac_get_netdev_ip4addr(pdata); - DPRINTK("%s, Get net device binary IP ok, 0x%08x\n", __FUNCTION__, cpu_to_be32(ipval)); - - ipval = cpu_to_be32(ipval); -#endif - } - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_ARP_PROTO_ADDR); - if(regval != /*cpu_to_be32*/(ipval)) { - writereg(pdata->pAdapter, /*cpu_to_be32*/(ipval), pdata->mac_regs + MAC_ARP_PROTO_ADDR); - DPRINTK("%s, update arp ipaddr reg from 0x%08x to 0x%08x\n", __FUNCTION__, regval, /*cpu_to_be32*/(ipval)); - } -} - -void fxgmac_config_arp_offload(struct fxgmac_pdata *pdata, int en) -{ - unsigned int regval = 0; - - /* enable or disable ARP offload engine. */ - if (!pdata->hw_feat.aoe) { - netdev_err(pdata->netdev, "error configuring ARP offload - not supported.\n"); - return; - } - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_ARPEN_POS, MAC_CR_ARPEN_LEN, en ? 1 : 0); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); - - DPRINTK("config_aoe, reg val=0x%08x, arp offload en=%d\n", regval, en); -} - -static int fxgmac_enable_arp_offload(struct fxgmac_pdata* pdata) -{ - u32 regval; - - if (!pdata->hw_feat.aoe) - return -EOPNOTSUPP; - - /* Enable arpoffload */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_ARPEN_POS, - MAC_CR_ARPEN_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); - - return 0; -} - -static int fxgmac_disable_arp_offload(struct fxgmac_pdata* pdata) -{ - u32 regval; - - if (!pdata->hw_feat.aoe) - return -EOPNOTSUPP; - /* disable arpoffload */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_ARPEN_POS, - MAC_CR_ARPEN_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); - - return 0; -} - -/* this function config register for NS offload function - * parameters: - * index - 0~1, index to NS look up table. one entry of the lut is like this |remote|solicited|target0|target1| - * remote_addr - ipv6 addr where fuxi gets the NS solicitation pkt(request). in common, it is 0 to match any remote machine. - * solicited_addr - the solicited node multicast group address which fuxi computes and joins. - * target_addr1 - it is the target address in NS solicitation pkt. - * target_addr2 - second target address, any address (with last 6B same with target address?). - */ -static int fxgmac_set_ns_offload(struct fxgmac_pdata* pdata,unsigned int index, unsigned char* remote_addr,unsigned char* solicited_addr,unsigned char*target_addr1,unsigned char *target_addr2,unsigned char *mac_addr) -//static int fxgmac_set_ns_offload(struct nic_pdata* pdata,unsigned char index, PIPV6NSPARAMETERS PIPv6NSPara) - -{ - u32 regval; - u32 Address[4],mac_addr_hi,mac_addr_lo; - u8 i, remote_not_zero = 0; - -#if 1 - regval = readreg(pdata->pAdapter, pdata->base_mem + NS_TPID_PRO); - regval = FXGMAC_SET_REG_BITS(regval, NS_TPID_PRO_STPID_POS, - NS_TPID_PRO_STPID_LEN, 0X8100); - regval = FXGMAC_SET_REG_BITS(regval, NS_TPID_PRO_CTPID_POS, - NS_TPID_PRO_CTPID_LEN, 0X9100); - writereg(pdata->pAdapter, regval, pdata->base_mem + NS_TPID_PRO); - regval = readreg(pdata->pAdapter, pdata->base_mem + 0X38 * index + NS_LUT_MAC_ADDR_CTL ); - regval = FXGMAC_SET_REG_BITS(regval, NS_LUT_DST_CMP_TYPE_POS, - NS_LUT_DST_CMP_TYPE_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, NS_LUT_DST_IGNORED_POS, - NS_LUT_DST_IGNORED_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, NS_LUT_REMOTE_AWARED_POS, - NS_LUT_REMOTE_AWARED_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, NS_LUT_TARGET_ISANY_POS, - NS_LUT_TARGET_ISANY_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->base_mem + 0X38 * index + NS_LUT_MAC_ADDR_CTL); - - //AR - for (i = 0; i < 16/4; i++) - { - Address[i] = (remote_addr[i * 4 + 0] << 24) | (remote_addr[i * 4 + 1] << 16) | (remote_addr[i * 4 + 2] << 8) | (remote_addr[i * 4 + 3] << 0); - writereg(pdata->pAdapter, Address[i], pdata->base_mem + 0X38 * index + NS_LUT_ROMOTE0 + 4 * i); - if(Address[i] ) - { - remote_not_zero = 1; - } - Address[i] = (target_addr1[i * 4 + 0] << 24) | (target_addr1[i * 4 + 1] << 16) | (target_addr1[i * 4 + 2] << 8) | (target_addr1[i * 4 + 3] << 0); - writereg(pdata->pAdapter, Address[i], pdata->base_mem + 0X38 * index + NS_LUT_TARGET0 + 4 * i); - Address[i] = (solicited_addr[i * 4 + 0] << 24) | (solicited_addr[i * 4 + 1] << 16) | (solicited_addr[i * 4 + 2] << 8) | (solicited_addr[i * 4 + 3] << 0); - writereg(pdata->pAdapter, Address[i], pdata->base_mem + 0X38 * index + NS_LUT_SOLICITED0 + 4 * i); - Address[i] = (target_addr2[i * 4 + 0] << 24) | (target_addr2[i * 4 + 1] << 16) | (target_addr2[i * 4 + 2] << 8) | (target_addr2[i * 4 + 3] << 0); - writereg(pdata->pAdapter, Address[i], pdata->base_mem + 0X10 * index + NS_LUT_TARGET4 + 4 * i); - - } - mac_addr_hi = (mac_addr[0] << 24) | (mac_addr[1] << 16)|(mac_addr[2] << 8) | (mac_addr[3] << 0); - mac_addr_lo = (mac_addr[4] << 8) | (mac_addr[5] << 0); - - writereg(pdata->pAdapter, mac_addr_hi, pdata->base_mem + 0X38 * index + NS_LUT_MAC_ADDR); - if(remote_not_zero==0) - { - regval = readreg(pdata->pAdapter, pdata->base_mem + 0X38 * index + NS_LUT_MAC_ADDR_CTL ); - regval = FXGMAC_SET_REG_BITS(regval, NS_LUT_REMOTE_AWARED_POS, - NS_LUT_REMOTE_AWARED_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, NS_LUT_MAC_ADDR_LOW_POS, - NS_LUT_MAC_ADDR_LOW_LEN, mac_addr_lo); - writereg(pdata->pAdapter, regval, pdata->base_mem + 0X38 * index + NS_LUT_MAC_ADDR_CTL); - } - else - { - regval = readreg(pdata->pAdapter, pdata->base_mem + 0X38 * index + NS_LUT_MAC_ADDR_CTL ); - regval = FXGMAC_SET_REG_BITS(regval, NS_LUT_REMOTE_AWARED_POS, - NS_LUT_REMOTE_AWARED_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, NS_LUT_MAC_ADDR_LOW_POS, - NS_LUT_MAC_ADDR_LOW_LEN, mac_addr_lo); - writereg(pdata->pAdapter, regval, pdata->base_mem + 0X38 * index + NS_LUT_MAC_ADDR_CTL); - } - -#else - regval = readreg(pdata->mac_regs -0x2000 + NS_TPID_PRO); - regval = FXGMAC_SET_REG_BITS(regval, NS_TPID_PRO_STPID_POS, - NS_TPID_PRO_STPID_LEN, 0X8100); - regval = FXGMAC_SET_REG_BITS(regval, NS_TPID_PRO_CTPID_POS, - NS_TPID_PRO_CTPID_LEN, 0X9100); - writereg(regval, pdata->mac_regs - 0x2000 + NS_TPID_PRO); - //AR - writereg(0X20000000, pdata->mac_regs - 0x2000 + NS_LUT_ROMOTE0); - writereg(0X00000000, pdata->mac_regs - 0x2000 + NS_LUT_ROMOTE1); - writereg(0X00000000, pdata->mac_regs - 0x2000 + NS_LUT_ROMOTE2); - writereg(0X00000001, pdata->mac_regs - 0x2000 + NS_LUT_ROMOTE3); - writereg(0X20000000, pdata->mac_regs - 0x2000 + NS_LUT_TARGET0); - writereg(0X00000000, pdata->mac_regs - 0x2000 + NS_LUT_TARGET1); - writereg(0X00000000, pdata->mac_regs - 0x2000 + NS_LUT_TARGET2); - writereg(0X00000002, pdata->mac_regs - 0x2000 + NS_LUT_TARGET3); - writereg(0Xff020000, pdata->mac_regs - 0x2000 + NS_LUT_SOLICITED0); - writereg(0X00000000, pdata->mac_regs - 0x2000 + NS_LUT_SOLICITED1); - writereg(0X00000001, pdata->mac_regs - 0x2000 + NS_LUT_SOLICITED2); - writereg(0Xff000002, pdata->mac_regs - 0x2000 + NS_LUT_SOLICITED3); - writereg(0X00e0fc69, pdata->mac_regs - 0x2000 + NS_LUT_MAC_ADDR); - writereg(0X00033381, pdata->mac_regs - 0x2000 + NS_LUT_MAC_ADDR_CTL); - - //NUD - writereg(0X20000000, pdata->mac_regs - 0x2000 + 0X38 * 2 + NS_LUT_ROMOTE0); - writereg(0X00000000, pdata->mac_regs - 0x2000 + 0X38 * 2 + NS_LUT_ROMOTE1); - writereg(0X00000000, pdata->mac_regs - 0x2000 + 0X38 * 2 + NS_LUT_ROMOTE2); - writereg(0X00000001, pdata->mac_regs - 0x2000 + 0X38 * 2 + NS_LUT_ROMOTE3); - writereg(0X20000000, pdata->mac_regs - 0x2000 + 0X38 * 2 + NS_LUT_TARGET0); - writereg(0X00000000, pdata->mac_regs - 0x2000 + 0X38 * 2 + NS_LUT_TARGET1); - writereg(0X00000000, pdata->mac_regs - 0x2000 + 0X38 * 2 + NS_LUT_TARGET2); - writereg(0X00000002, pdata->mac_regs - 0x2000 + 0X38 * 2 + NS_LUT_TARGET3); - writereg(0X20000000, pdata->mac_regs - 0x2000 + 0X38 * 2 + NS_LUT_SOLICITED0); - writereg(0X00000000, pdata->mac_regs - 0x2000 + 0X38 * 2 + NS_LUT_SOLICITED1); - writereg(0X00000000, pdata->mac_regs - 0x2000 + 0X38 * 2 + NS_LUT_SOLICITED2); - writereg(0X00000002, pdata->mac_regs - 0x2000 + 0X38 * 2 + NS_LUT_SOLICITED3); - writereg(0X00e0fc69, pdata->mac_regs - 0x2000 + 0X38 * 2 + NS_LUT_MAC_ADDR); - writereg(0X00033382, pdata->mac_regs - 0x2000 + 0X38 * 2 + NS_LUT_MAC_ADDR_CTL); - - //DAD - writereg(0X00000000, pdata->mac_regs - 0x2000 + 0X38 * 3 + NS_LUT_ROMOTE0); - writereg(0X00000000, pdata->mac_regs - 0x2000 + 0X38 * 3 + NS_LUT_ROMOTE1); - writereg(0X00000000, pdata->mac_regs - 0x2000 + 0X38 * 3 + NS_LUT_ROMOTE2); - writereg(0X00000000, pdata->mac_regs - 0x2000 + 0X38 * 3 + NS_LUT_ROMOTE3); - writereg(0X20000000, pdata->mac_regs - 0x2000 + 0X38 * 3 + NS_LUT_TARGET0); - writereg(0X00000000, pdata->mac_regs - 0x2000 + 0X38 * 3 + NS_LUT_TARGET1); - writereg(0X00000000, pdata->mac_regs - 0x2000 + 0X38 * 3 + NS_LUT_TARGET2); - writereg(0X00000002, pdata->mac_regs - 0x2000 + 0X38 * 3 + NS_LUT_TARGET3); - writereg(0Xff020000, pdata->mac_regs - 0x2000 + 0X38 * 3 + NS_LUT_SOLICITED0); - writereg(0X00000000, pdata->mac_regs - 0x2000 + 0X38 * 3 + NS_LUT_SOLICITED1); - writereg(0X00000001, pdata->mac_regs - 0x2000 + 0X38 * 3 + NS_LUT_SOLICITED2); - writereg(0Xff000002, pdata->mac_regs - 0x2000 + 0X38 * 3 + NS_LUT_SOLICITED3); - writereg(0X00e0fc69, pdata->mac_regs - 0x2000 + 0X38 * 3 + NS_LUT_MAC_ADDR); - writereg(0X00033381, pdata->mac_regs - 0x2000 + 0X38 * 3 + NS_LUT_MAC_ADDR_CTL); - - writereg(0X00000001, pdata->mac_regs - 0x2000 + NS_OF_GLB_CTL); -#endif - return 0; -} - -#ifdef LINUX -void fxgmac_update_ns_offload_ipv6addr(struct fxgmac_pdata *pdata, unsigned int param) -{ - struct net_device *netdev = pdata->netdev; - unsigned char addr_buf[5][16]; - - unsigned char * remote_addr = (unsigned char *)&addr_buf[0][0]; - unsigned char * solicited_addr = (unsigned char *)&addr_buf[1][0]; - unsigned char * target_addr1 = (unsigned char *)&addr_buf[2][0]; - //unsigned char * target_addr2 = (unsigned char *)&addr_buf[3][0]; - unsigned char * mac_addr = (unsigned char *)&addr_buf[4][0]; - - /* get ipv6 addr from net device */ - if (NULL == fxgmac_get_netdev_ip6addr(pdata, target_addr1, solicited_addr, (FXGMAC_NS_IFA_LOCAL_LINK | FXGMAC_NS_IFA_GLOBAL_UNICAST) & param)) - { - DPRINTK("%s, get net device ipv6 addr with err and ignore NS offload.\n", __FUNCTION__); - - return; - } - - DPRINTK("%s, Get net device binary IPv6 ok, local-link=%pI6\n", __FUNCTION__, target_addr1); - DPRINTK("%s, Get net device binary IPv6 ok, solicited =%pI6\n", __FUNCTION__, solicited_addr); - - memcpy(mac_addr, netdev->dev_addr, netdev->addr_len); - DPRINTK("%s, Get net device MAC addr ok, ns_tab idx=%d, %02x:%02x:%02x:%02x:%02x:%02x\n", - __FUNCTION__, pdata->expansion.ns_offload_tab_idx, mac_addr[0], mac_addr[1], - mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); - - memset(remote_addr, 0, 16); - fxgmac_set_ns_offload(pdata, pdata->expansion.ns_offload_tab_idx++, - remote_addr, solicited_addr, target_addr1, - target_addr1, mac_addr); - if(pdata->expansion.ns_offload_tab_idx >= 2) pdata->expansion.ns_offload_tab_idx = 0; - -} -#endif - -static int fxgmac_enable_ns_offload(struct fxgmac_pdata* pdata) -{ - writereg(pdata->pAdapter, 0X00000011, pdata->base_mem + NS_OF_GLB_CTL); - return 0; -} - - -static int fxgmac_disable_ns_offload(struct fxgmac_pdata* pdata) -{ - writereg(pdata->pAdapter, 0X00000000, pdata->base_mem + NS_OF_GLB_CTL); - return 0; -} - -static int fxgmac_check_wake_pattern_fifo_pointer(struct fxgmac_pdata* pdata) -{ - u32 regval; - int ret = 0; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); - regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_RWKFILTERST_POS, MAC_PMT_STA_RWKFILTERST_LEN,1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PMT_STA); - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); - regval = FXGMAC_GET_REG_BITS(regval, MAC_PMT_STA_RWKPTR_POS, MAC_PMT_STA_RWKPTR_LEN); - if (regval != 0) { - DPRINTK("Remote fifo pointer is not 0\n"); - ret = -EINVAL; - } - return ret; -} - -static int fxgmac_set_wake_pattern_mask(struct fxgmac_pdata* pdata, u32 filter_index, u8 register_index,u32 Data) -{ - const u16 address_offset[16][3] = { - {0x1020, 0x1024, 0x1028}, - {0x102c, 0x1030, 0x1034}, - {0x1038, 0x103c, 0x1040}, - {0x1044, 0x1050, 0x1054}, - {0x1058, 0x105c, 0x1060}, - {0x1064, 0x1068, 0x106c}, - {0x1070, 0x1074, 0x1078}, - {0x107c, 0x1080, 0x1084}, - {0x1088, 0x108c, 0x1090}, - {0x1134, 0x113c, 0x1140}, - {0x1208, 0x1200, 0x1204}, - {0x1218, 0x1210, 0x1214}, - {0x1228, 0x1220, 0x1224}, - {0x1238, 0x1230, 0x1234}, - {0x1248, 0x1240, 0x1244}, - {0x1258, 0x1250, 0x1254}, - }; - if (filter_index > 15||register_index > 2) { - DbgPrintF(MP_TRACE, "%s - Remote mask pointer is over range, filter_index:%d, register_index:0x%x\n", - __FUNCTION__, filter_index, register_index); - return -1; - } - writereg(pdata->pAdapter, Data, pdata->base_mem + address_offset[filter_index][register_index]); - return 0; -} - -static u16 wol_crc16(u8* pucframe, u16 uslen) -{ - int i; - - union type16 { - u16 raw; - struct { - u16 bit_0 : 1; - u16 bit_1 : 1; - u16 bit_2 : 1; - u16 bit_3 : 1; - u16 bit_4 : 1; - u16 bit_5 : 1; - u16 bit_6 : 1; - u16 bit_7 : 1; - u16 bit_8 : 1; - u16 bit_9 : 1; - u16 bit_10 : 1; - u16 bit_11 : 1; - u16 bit_12 : 1; - u16 bit_13 : 1; - u16 bit_14 : 1; - u16 bit_15 : 1; - }bits; - }; - - union type8 { - u16 raw; - - struct { - u16 bit_0 : 1; - u16 bit_1 : 1; - u16 bit_2 : 1; - u16 bit_3 : 1; - u16 bit_4 : 1; - u16 bit_5 : 1; - u16 bit_6 : 1; - u16 bit_7 : 1; - }bits; - }; - - union type16 crc, crc_comb; - union type8 next_crc, rrpe_data; - next_crc.raw = 0; - crc.raw = 0xffff; - for (i = 0; i < uslen;i++) { - rrpe_data.raw = pucframe[i]; - next_crc.bits.bit_0 = crc.bits.bit_15 ^ rrpe_data.bits.bit_0; - next_crc.bits.bit_1 = crc.bits.bit_14 ^ next_crc.bits.bit_0 ^ rrpe_data.bits.bit_1; - next_crc.bits.bit_2 = crc.bits.bit_13 ^ next_crc.bits.bit_1 ^ rrpe_data.bits.bit_2; - next_crc.bits.bit_3 = crc.bits.bit_12 ^ next_crc.bits.bit_2 ^ rrpe_data.bits.bit_3; - next_crc.bits.bit_4 = crc.bits.bit_11 ^ next_crc.bits.bit_3 ^ rrpe_data.bits.bit_4; - next_crc.bits.bit_5 = crc.bits.bit_10 ^ next_crc.bits.bit_4 ^ rrpe_data.bits.bit_5; - next_crc.bits.bit_6 = crc.bits.bit_9 ^ next_crc.bits.bit_5 ^ rrpe_data.bits.bit_6; - next_crc.bits.bit_7 = crc.bits.bit_8 ^ next_crc.bits.bit_6 ^ rrpe_data.bits.bit_7; - - crc_comb.bits.bit_15 = crc.bits.bit_7 ^ next_crc.bits.bit_7; - crc_comb.bits.bit_14 = crc.bits.bit_6; - crc_comb.bits.bit_13 = crc.bits.bit_5; - crc_comb.bits.bit_12 = crc.bits.bit_4; - crc_comb.bits.bit_11 = crc.bits.bit_3; - crc_comb.bits.bit_10 = crc.bits.bit_2; - crc_comb.bits.bit_9 = crc.bits.bit_1 ^ next_crc.bits.bit_0; - crc_comb.bits.bit_8 = crc.bits.bit_0 ^ next_crc.bits.bit_1; - crc_comb.bits.bit_7 = next_crc.bits.bit_0 ^ next_crc.bits.bit_2; - crc_comb.bits.bit_6 = next_crc.bits.bit_1 ^ next_crc.bits.bit_3; - crc_comb.bits.bit_5 = next_crc.bits.bit_2 ^ next_crc.bits.bit_4; - crc_comb.bits.bit_4 = next_crc.bits.bit_3 ^ next_crc.bits.bit_5; - crc_comb.bits.bit_3 = next_crc.bits.bit_4 ^ next_crc.bits.bit_6; - crc_comb.bits.bit_2 = next_crc.bits.bit_5 ^ next_crc.bits.bit_7; - crc_comb.bits.bit_1 = next_crc.bits.bit_6; - crc_comb.bits.bit_0 = next_crc.bits.bit_7; - crc.raw = crc_comb.raw; - } - return crc.raw; -} - -static int fxgmac_set_wake_pattern( - struct fxgmac_pdata* pdata, - struct wol_bitmap_pattern* wol_pattern, - u32 pattern_cnt) -{ - u32 i, j, kp, km, mask_index; - int z; - u16 map_index; - u8 mask[MAX_PATTERN_SIZE]; - u32 regval = 0; - u32 total_cnt = 0, pattern_inherited_cnt = 0; - u8* ptdata, * ptmask; - - if (pattern_cnt > MAX_PATTERN_COUNT) { - DbgPrintF(MP_TRACE, "%s - Error: %d patterns, exceed %d, not supported!\n", - __FUNCTION__, pattern_cnt, MAX_PATTERN_COUNT); - return -1; - } - - /* Reset the FIFO head pointer. */ - if (fxgmac_check_wake_pattern_fifo_pointer(pdata)) { - DbgPrintF(MP_TRACE, "%s - Warning: the remote pattern array pointer is not be 0\n", __FUNCTION__); - return -1; - } - - for (i = 0; i < pattern_cnt; i++) { - memcpy(&pdata->pattern[i], wol_pattern + i, sizeof(wol_pattern[0])); - if (pattern_cnt + pattern_inherited_cnt < MAX_PATTERN_COUNT) - { - if (wol_pattern[i].pattern_offset || !(wol_pattern[i].mask_info[0] & 0x01)) { - memcpy(&pdata->pattern[pattern_cnt + pattern_inherited_cnt], - wol_pattern + i, - sizeof(wol_pattern[0])); - pattern_inherited_cnt++; - } - } - } - total_cnt = pattern_cnt + pattern_inherited_cnt; - - /* - * calculate the crc-16 of the mask pattern - * print the pattern and mask for debug purpose. - */ - for (i = 0; i < total_cnt; i++) { - /* Please program pattern[i] to NIC for pattern match wakeup. - * pattern_size, pattern_info, mask_info - */ - //save the mask pattern - mask_index = 0; - map_index = 0; - for (j = 0; j < pdata->pattern[i].mask_size; j++) { - for (z = 0; z < ((j == (MAX_PATTERN_SIZE / 8 - 1)) ? 7 : 8); z++) { - if (pdata->pattern[i].mask_info[j] & (0x01 << z)) { - mask[map_index] = pdata->pattern[i].pattern_info[pdata->pattern[i].pattern_offset + mask_index]; - map_index++; - } - mask_index++; - } - } - //calculate the crc-16 of the mask pattern - pdata->pattern[i].pattern_crc = wol_crc16(mask, map_index); - - // Print pattern match, for debug purpose. - DbgPrintF(MP_LOUD, "%s - Pattern[%d]:", __FUNCTION__, i); - for (kp = 0, km = 0; kp < sizeof(pdata->pattern[i].pattern_info); kp += 16, km += 2) { - ptdata = &pdata->pattern[i].pattern_info[kp]; - ptmask = &pdata->pattern[i].mask_info[km]; - DBGPRINT(MP_LOUD, ("\n %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x Mask %02x-%02x", - ptdata[0], ptdata[1], ptdata[2], ptdata[3], ptdata[4], ptdata[5], ptdata[6], ptdata[7], - ptdata[8], ptdata[9], ptdata[10], ptdata[11], ptdata[12], ptdata[13], ptdata[14], ptdata[15], - ptmask[0], ptmask[1])); - } - //fxgmac_dump_buffer(mask, map_index, 2); - DbgPrintF(MP_LOUD, "WritePatternToNic62 the %d patterns crc = %x mask length = %d, mask_offset=%x.\n", - i, pdata->pattern[i].pattern_crc, map_index, - pdata->pattern[i].pattern_offset); - memset(mask, 0, sizeof(mask)); - } - - // Write patterns by FIFO block. - for (i = 0; i < (total_cnt + 3) / 4; i++) { - // 1. Write the first 4Bytes of Filter. - writereg(pdata->pAdapter, - ((pdata->pattern[i * 4 + 0].mask_info[3] & 0x7f) << 24) | - (pdata->pattern[i * 4 + 0].mask_info[2] << 16) | - (pdata->pattern[i * 4 + 0].mask_info[1] << 8) | - (pdata->pattern[i * 4 + 0].mask_info[0] << 0), - pdata->mac_regs + MAC_RWK_PAC); - - writereg(pdata->pAdapter, - ((pdata->pattern[i * 4 + 1].mask_info[3] & 0x7f) << 24) | - (pdata->pattern[i * 4 + 1].mask_info[2] << 16) | - (pdata->pattern[i * 4 + 1].mask_info[1] << 8) | - (pdata->pattern[i * 4 + 1].mask_info[0] << 0), - pdata->mac_regs + MAC_RWK_PAC); - - writereg(pdata->pAdapter, - ((pdata->pattern[i * 4 + 2].mask_info[3] & 0x7f) << 24) | - (pdata->pattern[i * 4 + 2].mask_info[2] << 16) | - (pdata->pattern[i * 4 + 2].mask_info[1] << 8) | - (pdata->pattern[i * 4 + 2].mask_info[0] << 0), - pdata->mac_regs + MAC_RWK_PAC); - - writereg(pdata->pAdapter, - ((pdata->pattern[i * 4 + 3].mask_info[3] & 0x7f) << 24) | - (pdata->pattern[i * 4 + 3].mask_info[2] << 16) | - (pdata->pattern[i * 4 + 3].mask_info[1] << 8) | - (pdata->pattern[i * 4 + 3].mask_info[0] << 0), - pdata->mac_regs + MAC_RWK_PAC); - - // 2. Write the Filter Command. - regval = 0; - // Set filter enable bit. - regval |= ((i * 4 + 0) < total_cnt) ? (0x1 << 0) : 0x0; - regval |= ((i * 4 + 1) < total_cnt) ? (0x1 << 8) : 0x0; - regval |= ((i * 4 + 2) < total_cnt) ? (0x1 << 16) : 0x0; - regval |= ((i * 4 + 3) < total_cnt) ? (0x1 << 24) : 0x0; - // Set filter address type, 0- unicast, 1 - multicast. - regval |= (i * 4 + 0 >= total_cnt) ? 0x0 : - (i * 4 + 0 >= pattern_cnt) ? (0x1 << (3 + 0)) : - pdata->pattern[i * 4 + 0].pattern_offset ? 0x0 : - !(pdata->pattern[i * 4 + 0].mask_info[0] & 0x01) ? 0x0 : - (pdata->pattern[i * 4 + 0].pattern_info[0] & 0x01) ? (0x1 << (3 + 0)) : 0x0; - regval |= (i * 4 + 1 >= total_cnt) ? 0x0 : - (i * 4 + 1 >= pattern_cnt) ? (0x1 << (3 + 8)) : - pdata->pattern[i * 4 + 1].pattern_offset ? 0x0 : - !(pdata->pattern[i * 4 + 1].mask_info[0] & 0x01) ? 0x0 : - (pdata->pattern[i * 4 + 1].pattern_info[0] & 0x01) ? (0x1 << (3 + 8)) : 0x0; - regval |= (i * 4 + 2 >= total_cnt) ? 0x0 : - (i * 4 + 2 >= pattern_cnt) ? (0x1 << (3 + 16)) : - pdata->pattern[i * 4 + 2].pattern_offset ? 0x0 : - !(pdata->pattern[i * 4 + 2].mask_info[0] & 0x01) ? 0x0 : - (pdata->pattern[i * 4 + 2].pattern_info[0] & 0x01) ? (0x1 << (3 + 16)) : 0x0; - regval |= (i * 4 + 3 >= total_cnt) ? 0x0 : - (i * 4 + 3 >= pattern_cnt) ? (0x1 << (3 + 24)) : - pdata->pattern[i * 4 + 3].pattern_offset ? 0x0 : - !(pdata->pattern[i * 4 + 3].mask_info[0] & 0x01) ? 0x0 : - (pdata->pattern[i * 4 + 3].pattern_info[0] & 0x01) ? (0x1 << (3 + 24)) : 0x0; - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_RWK_PAC); - //DbgPrintF(MP_LOUD, "FilterCMD 0x%08x", regval); - - // 3. Write the mask offset. - writereg(pdata->pAdapter, - (pdata->pattern[i * 4 + 3].pattern_offset << 24) | - (pdata->pattern[i * 4 + 2].pattern_offset << 16) | - (pdata->pattern[i * 4 + 1].pattern_offset << 8) | - (pdata->pattern[i * 4 + 0].pattern_offset << 0), - pdata->mac_regs + MAC_RWK_PAC); - - // 4. Write the masked data CRC. - writereg(pdata->pAdapter, - (pdata->pattern[i * 4 + 1].pattern_crc << 16) | - (pdata->pattern[i * 4 + 0].pattern_crc << 0), - pdata->mac_regs + MAC_RWK_PAC); - writereg(pdata->pAdapter, - (pdata->pattern[i * 4 + 3].pattern_crc << 16) | - (pdata->pattern[i * 4 + 2].pattern_crc << 0), - pdata->mac_regs + MAC_RWK_PAC); - } - - for (i = 0; i < total_cnt; i++) { - fxgmac_set_wake_pattern_mask(pdata, i, 0, - ((pdata->pattern[i].mask_info[7] & 0x7f) << (24 + 1)) | - (pdata->pattern[i].mask_info[6] << (16 + 1)) | - (pdata->pattern[i].mask_info[5] << (8 + 1)) | - (pdata->pattern[i].mask_info[4] << (0 + 1)) | - ((pdata->pattern[i].mask_info[3] & 0x80) >> 7));//global manager regitster mask bit 31~62 - fxgmac_set_wake_pattern_mask(pdata, i, 1, - ((pdata->pattern[i].mask_info[11] & 0x7f) << (24 + 1)) | - (pdata->pattern[i].mask_info[10] << (16 + 1)) | - (pdata->pattern[i].mask_info[9] << (8 + 1)) | - (pdata->pattern[i].mask_info[8] << (0 + 1)) | - ((pdata->pattern[i].mask_info[7] & 0x80) >> 7));//global manager regitster mask bit 63~94 - fxgmac_set_wake_pattern_mask(pdata, i, 2, \ - ((pdata->pattern[i].mask_info[15] & 0x7f) << (24 + 1)) | - (pdata->pattern[i].mask_info[14] << (16 + 1)) | - (pdata->pattern[i].mask_info[13] << (8 + 1)) | - (pdata->pattern[i].mask_info[12] << (0 + 1)) | - ((pdata->pattern[i].mask_info[11] & 0x80) >> 7));//global manager regitster mask bit 95~126 - } - - return 0; -} - -static int fxgmac_enable_wake_pattern(struct fxgmac_pdata* pdata) -{ - u32 regval; - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); - regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_RWKFILTERST_POS, MAC_PMT_STA_RWKFILTERST_LEN,1); - regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_RWKPKTEN_POS, MAC_PMT_STA_RWKPKTEN_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PMT_STA); - regval = readreg(pdata->pAdapter, pdata->base_mem + WOL_CTL); - regval = FXGMAC_SET_REG_BITS(regval, WOL_PKT_EN_POS, WOL_PKT_EN_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->base_mem + WOL_CTL); - return 0; -} - -static int fxgmac_disable_wake_pattern(struct fxgmac_pdata* pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); - regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_RWKFILTERST_POS, MAC_PMT_STA_RWKFILTERST_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_RWKPKTEN_POS, MAC_PMT_STA_RWKPKTEN_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PMT_STA); - regval = readreg(pdata->pAdapter, pdata->base_mem + WOL_CTL); - regval = FXGMAC_SET_REG_BITS(regval, WOL_PKT_EN_POS, WOL_PKT_EN_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->base_mem + WOL_CTL); - return 0; -} -static int fxgmac_enable_wake_magic_pattern(struct fxgmac_pdata* pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); - regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_MGKPKTEN_POS, MAC_PMT_STA_MGKPKTEN_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PMT_STA); - regval = readreg(pdata->pAdapter, pdata->base_mem + WOL_CTL); - regval = FXGMAC_SET_REG_BITS(regval, WOL_PKT_EN_POS, WOL_PKT_EN_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->base_mem + WOL_CTL); - - /* Enable PME Enable Bit. */ - cfg_r32(pdata, REG_PM_STATCTRL, ®val); - regval = FXGMAC_SET_REG_BITS(regval, PM_CTRLSTAT_PME_EN_POS, PM_CTRLSTAT_PME_EN_LEN, 1); - cfg_w32(pdata, REG_PM_STATCTRL, regval); - - return 0; -} - -static int fxgmac_disable_wake_magic_pattern(struct fxgmac_pdata* pdata) -{ - u32 regval; - regval = readreg(pdata->pAdapter, pdata->base_mem + WOL_CTL); - regval = FXGMAC_SET_REG_BITS(regval, WOL_PKT_EN_POS, WOL_PKT_EN_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->base_mem + WOL_CTL); - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); - regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_MGKPKTEN_POS, MAC_PMT_STA_MGKPKTEN_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PMT_STA); - return 0; -} - -#if defined(FUXI_PM_WPI_READ_FEATURE_EN) && FUXI_PM_WPI_READ_FEATURE_EN -/* - * enable Wake packet indication. called to enable before sleep/hibernation - * and no needed to call disable for that, fxgmac_get_wake_packet_indication will clear to normal once done. - */ -static void fxgmac_enable_wake_packet_indication(struct fxgmac_pdata* pdata, int en) -{ - u32 val_wpi_crtl0; - - /* read-clear WoL event. */ - readreg(pdata->pAdapter, pdata->base_mem + MGMT_WOL_CTRL); - - /* get wake packet information */ - val_wpi_crtl0 = (u32)readreg(pdata->pAdapter, pdata->base_mem + MGMT_WPI_CTRL0); - - /* prepare to write packet data by write wpi_mode to 1 */ - val_wpi_crtl0 = FXGMAC_SET_REG_BITS(val_wpi_crtl0, - MGMT_WPI_CTRL0_WPI_MODE_POS, - MGMT_WPI_CTRL0_WPI_MODE_LEN, (en ? MGMT_WPI_CTRL0_WPI_MODE_WR : MGMT_WPI_CTRL0_WPI_MODE_NORMAL)); - writereg(pdata->pAdapter, val_wpi_crtl0, pdata->base_mem + MGMT_WPI_CTRL0); - - DbgPrintF(MP_TRACE, "%s - WPI pkt enable=%d, reg=%08x.\n", __FUNCTION__, en, val_wpi_crtl0); - - return; -} - -/* - * this function read Wake up packet after MDIS resume - * input: - * pdata - * wpi_buf container of a packet. - * buf_size size of the packet container. since HW limit to 14bits, ie 16KB all together. - * output: - * wake_reason from HW, we can indentify 1)magic packet, or 2)pattern(remote wake packet) or WAKE_REASON_HW_ERR indicates err - * packet_size length of the wake packet. 0 indicates exception. - * - */ -static void fxgmac_get_wake_packet_indication(struct fxgmac_pdata* pdata, int* wake_reason, u32* wake_pattern_number, u8* wpi_buf, u32 buf_size, u32* packet_size) -{ - u32 i, regval, val_wpi_crtl0, *dw_wpi_buf; - u32 data_len, data_len_dw, b_need_pkt = 0; - - *wake_reason = WAKE_REASON_NONE; - *packet_size = 0; - fxgmac_release_phy(pdata); -#if 1 - /* try to check wake reason. GMAC reg 20c0 only tells Magic or remote-pattern - * read from MGMT_WOL_CTRL, 1530 instead. - */ - regval = (u32)readreg(pdata->pAdapter, pdata->base_mem + MGMT_WOL_CTRL); - DbgPrintF(MP_TRACE, "%s - 0x1530=%x.\n", __FUNCTION__, regval); - if (!regval) { - DbgPrintF(MP_TRACE, "%s - nothing for WPI pkt.\n", __FUNCTION__); - return; - } - - if (regval & MGMT_WOL_CTRL_WPI_MGC_PKT) { - *wake_reason = WAKE_REASON_MAGIC; - b_need_pkt = 1; - } else if (regval & MGMT_WOL_CTRL_WPI_RWK_PKT) { - *wake_reason = WAKE_REASON_PATTERNMATCH; - b_need_pkt = 1; - *wake_pattern_number = 0; - - /* - * wake_pattern_number, HW should tell,,tbd - */ - for (i = 0;i < MAX_PATTERN_COUNT;i++) { - if (regval & (MGMT_WOL_CTRL_WPI_RWK_PKT_NUMBER << i)) { - *wake_pattern_number = i; - break; - } - } - //*wake_pattern_number = regval&MGMT_WOL_CTRL_WPI_RWK_PKT_NUMBER; - - } else if (regval & MGMT_WOL_CTRL_WPI_LINK_CHG) { - *wake_reason = WAKE_REASON_LINK; - } - -#else - /* for 20c0 */ - regval = (u32)readreg(pdata->mac_regs + MAC_PMT_STA); - DbgPrintF(MP_TRACE, "%s - 0x20c0=%x.\n", __FUNCTION__, regval); - if (FXGMAC_GET_REG_BITS(regval, - MAC_PMT_STA_MGKPRCVD_POS, - MAC_PMT_STA_MGKPRCVD_LEN)) { - *wake_reason = WAKE_REASON_MAGIC; - b_need_pkt = 1; - DbgPrintF(MP_TRACE, "%s - waken up by Magic.\n", __FUNCTION__); - } else if (FXGMAC_GET_REG_BITS(regval, - MAC_PMT_STA_RWKPRCVD_POS, - MAC_PMT_STA_RWKPRCVD_LEN)) { - *wake_reason = WAKE_REASON_PATTERNMATCH; - b_need_pkt = 1; - DbgPrintF(MP_TRACE, "%s - waken up by Pattern.\n", __FUNCTION__); - } -#endif - - if (!b_need_pkt) { - DbgPrintF(MP_TRACE, "%s - wake by link and no WPI pkt.\n", __FUNCTION__); - return; - } - - /* get wake packet information */ - val_wpi_crtl0 = (u32)readreg(pdata->pAdapter, pdata->base_mem + MGMT_WPI_CTRL0); - - if (val_wpi_crtl0 & MGMT_WPI_CTRL0_WPI_FAIL) { - *wake_reason = WAKE_REASON_HW_ERR; - DbgPrintF(MP_TRACE, "%s - WPI pkt fail from hw.\n", __FUNCTION__); - return; - } - - *packet_size = FXGMAC_GET_REG_BITS(val_wpi_crtl0, - MGMT_WPI_CTRL0_WPI_PKT_LEN_POS, - MGMT_WPI_CTRL0_WPI_PKT_LEN_LEN); - - if (0 == *packet_size) { - *wake_reason = WAKE_REASON_HW_ERR; - DbgPrintF(MP_TRACE, "%s - WPI pkt len is 0 from hw.\n", __FUNCTION__); - return; - } - - - DbgPrintF(MP_TRACE, "%s - WPI pkt len from hw, *packet_size=%u.\n", __FUNCTION__, *packet_size); - - if (buf_size < *packet_size) { - DbgPrintF(MP_WARN, "%s - too small buf_size=%u, WPI pkt len is %u.\n", __FUNCTION__, buf_size, *packet_size); - data_len = buf_size; - } else { - data_len = *packet_size; - } - - /* prepare to read packet data by write wpi_mode to 2 */ - val_wpi_crtl0 = FXGMAC_SET_REG_BITS(val_wpi_crtl0, - MGMT_WPI_CTRL0_WPI_MODE_POS, - MGMT_WPI_CTRL0_WPI_MODE_LEN, MGMT_WPI_CTRL0_WPI_MODE_RD); - writereg(pdata->pAdapter, val_wpi_crtl0, pdata->base_mem + MGMT_WPI_CTRL0); - - dw_wpi_buf = (u32*)wpi_buf; - data_len_dw = (data_len + 3) / 4; - - i = 0; - DbgPrintF(MP_TRACE, "%s - before retrieve, len=%d, len_dw=%d, reg_wpi_ctrl0=%08x.\n", - __FUNCTION__, data_len, data_len_dw, val_wpi_crtl0); - while ((0 == (val_wpi_crtl0 & MGMT_WPI_CTRL0_WPI_OP_DONE))) { - if (i < data_len_dw) { - regval = (u32)readreg(pdata->pAdapter, pdata->base_mem + MGMT_WPI_CTRL1_DATA); - /*dw_wpi_buf[i] = SWAP_BYTES_32(regval);*/ - dw_wpi_buf[i] = regval; - - //DbgPrintF(MP_TRACE, "%s - read data, reg=%x, data[%d]=%08x.\n", __FUNCTION__, MGMT_WPI_CTRL1_DATA, i, dw_wpi_buf[i]); - } else { - break; - } - - val_wpi_crtl0 = (u32)readreg(pdata->pAdapter, pdata->base_mem + MGMT_WPI_CTRL0); - i++; - } - if (*packet_size <= MAC_CRC_LENGTH) - { - DbgPrintF(MP_TRACE, "%s - Warning, WPI pkt len is less 4 from hw.\n", __FUNCTION__); - return; - } - *packet_size -= MAC_CRC_LENGTH; - - /* once read data complete and write wpi_mode to 0, normal */ - val_wpi_crtl0 = FXGMAC_SET_REG_BITS(val_wpi_crtl0, - MGMT_WPI_CTRL0_WPI_MODE_POS, - MGMT_WPI_CTRL0_WPI_MODE_LEN, MGMT_WPI_CTRL0_WPI_MODE_NORMAL); - writereg(pdata->pAdapter, val_wpi_crtl0, pdata->base_mem + MGMT_WPI_CTRL0); - - DbgPrintF(MP_TRACE, "%s - WPI done and back to normal mode, reg=%08x, read data=%dB.\n", __FUNCTION__, val_wpi_crtl0, i * 4); - - return; -} -#endif /* FUXI_PM_WPI_READ_FEATURE_EN */ - -static int fxgmac_enable_wake_link_change(struct fxgmac_pdata* pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->base_mem + WOL_CTL); - regval = FXGMAC_SET_REG_BITS(regval, WOL_LINKCHG_EN_POS, WOL_LINKCHG_EN_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->base_mem + WOL_CTL); - return 0; -} -static int fxgmac_disable_wake_link_change(struct fxgmac_pdata* pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->base_mem + WOL_CTL); - regval = FXGMAC_SET_REG_BITS(regval, WOL_LINKCHG_EN_POS, WOL_LINKCHG_EN_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->base_mem + WOL_CTL); - return 0; -} -#endif // LINUX/_WIN64/_WIN32 - -#ifdef LINUX -static void fxgmac_config_wol(struct fxgmac_pdata *pdata, int en) -{ - /* enable or disable WOL. this function only set wake-up type, and power related configure - * will be in other place, see power management. - */ - if (!pdata->hw_feat.rwk) { - netdev_err(pdata->netdev, "error configuring WOL - not supported.\n"); - return; - } - - fxgmac_disable_wake_magic_pattern(pdata); - fxgmac_disable_wake_pattern(pdata); - fxgmac_disable_wake_link_change(pdata); - - if(en) { - /* config mac address for rx of magic or ucast */ - fxgmac_set_mac_address(pdata, (u8*)(pdata->netdev->dev_addr)); - - /* Enable Magic packet */ - if (pdata->expansion.wol & WAKE_MAGIC) { - fxgmac_enable_wake_magic_pattern(pdata); - } - - /* Enable global unicast packet */ - if (pdata->expansion.wol & WAKE_UCAST - || pdata->expansion.wol & WAKE_MCAST - || pdata->expansion.wol & WAKE_BCAST - || pdata->expansion.wol & WAKE_ARP) { - fxgmac_enable_wake_pattern(pdata); - } - - /* Enable ephy link change */ - if ((FXGMAC_WOL_UPON_EPHY_LINK) && (pdata->expansion.wol & WAKE_PHY)) { - fxgmac_enable_wake_link_change(pdata); - } - } - device_set_wakeup_enable(/*pci_dev_to_dev*/(pdata->dev), en); - - DPRINTK("config_wol callout\n"); -} -#endif - -static int fxgmac_get_ephy_state(struct fxgmac_pdata* pdata) -{ - u32 value; - value = readreg(pdata->pAdapter, pdata->base_mem + MGMT_EPHY_CTRL); - return value; -} - -static void fxgmac_enable_dma_interrupts(struct fxgmac_pdata *pdata) -{ -#ifndef DPDK - unsigned int dma_ch_isr, dma_ch_ier; - struct fxgmac_channel *channel; - unsigned int i; - -#ifdef NIC_NET_ADAPETERCX - u32 regval; - //config interrupt to level signal - regval = (u32)readreg(pdata->pAdapter, pdata->mac_regs + DMA_MR); - regval = FXGMAC_SET_REG_BITS(regval, DMA_MR_INTM_POS, DMA_MR_INTM_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, DMA_MR_QUREAD_POS, DMA_MR_QUREAD_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + DMA_MR); -#endif - - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - /* Clear all the interrupts which are set */ - dma_ch_isr = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_SR)); - writereg(pdata->pAdapter, dma_ch_isr, FXGMAC_DMA_REG(channel, DMA_CH_SR)); - - /* 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 - */ - dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, - DMA_CH_IER_NIE_POS, - DMA_CH_IER_NIE_LEN, 1); - /* - dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, - DMA_CH_IER_AIE_POS, - DMA_CH_IER_AIE_LEN, 1); - */ - dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, - DMA_CH_IER_FBEE_POS, - DMA_CH_IER_FBEE_LEN, 1); - - if (channel->tx_ring) { - /* Enable the following Tx interrupts - * TIE - Transmit Interrupt Enable (unless using - * per channel interrupts) - */ - if (!pdata->per_channel_irq) - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, - DMA_CH_IER_TIE_POS, - DMA_CH_IER_TIE_LEN, - 1); - if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { - if (pdata->per_channel_irq) { - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, - DMA_CH_IER_TIE_POS, - DMA_CH_IER_TIE_LEN, - 1); - - /*dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, - DMA_CH_IER_TBUE_POS, - DMA_CH_IER_TBUE_LEN, - 1);*/ - } - } - } - if (channel->rx_ring) { - /* Enable following Rx interrupts - * RBUE - Receive Buffer Unavailable Enable - * RIE - Receive Interrupt Enable (unless using - * per channel interrupts) - */ - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, - DMA_CH_IER_RBUE_POS, - DMA_CH_IER_RBUE_LEN, - 1); - //2022-04-20 xiaojiang comment - //windows driver set the per_channel_irq to be zero, Linux driver also comment this, so comment it directly - //if (!pdata->per_channel_irq) - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, - DMA_CH_IER_RIE_POS, - DMA_CH_IER_RIE_LEN, - 1); - } - - writereg(pdata->pAdapter, dma_ch_ier, FXGMAC_DMA_REG(channel, DMA_CH_IER)); - } -#else - struct fxgmac_tx_queue *txq; - unsigned int dma_ch_isr, dma_ch_ier; - unsigned int i; - - for (i = 0; i < pdata->expansion.eth_dev->data->nb_tx_queues; i++) { - txq = pdata->expansion.eth_dev->data->tx_queues[i]; - - /* Clear all the interrupts which are set */ - dma_ch_isr = FXGMAC_DMA_IOREAD(txq, DMA_CH_SR); - FXGMAC_DMA_IOWRITE(txq, 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 - */ - FXGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, NIE, 1);//0 fx 1 - FXGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, AIE, 1); - FXGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, FBEE, 1); - - /* Enable following Rx interrupts - * RBUE - Receive Buffer Unavailable Enable - * RIE - Receive Interrupt Enable (unless using - * per channel interrupts in edge triggered - * mode) - */ - FXGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1);//0 fx 1 - FXGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 0);// 0 fx 1 - - FXGMAC_DMA_IOWRITE(txq, DMA_CH_IER, dma_ch_ier); - } -#endif -} - -static void fxgmac_enable_mtl_interrupts(struct fxgmac_pdata *pdata) -{ - unsigned int q_count, i; - unsigned int mtl_q_isr; - - 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 = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_Q_ISR)); - writereg(pdata->pAdapter, mtl_q_isr, FXGMAC_MTL_REG(pdata, i, MTL_Q_ISR)); - - /* No MTL interrupts to be enabled */ - writereg(pdata->pAdapter, 0, FXGMAC_MTL_REG(pdata, i, MTL_Q_IER)); - } -} - -static void fxgmac_enable_mac_interrupts(struct fxgmac_pdata *pdata) -{ - unsigned int mac_ier = 0; - u32 regval; - - /* Enable Timestamp interrupt */ - mac_ier = FXGMAC_SET_REG_BITS(mac_ier, MAC_IER_TSIE_POS, - MAC_IER_TSIE_LEN, 1); - - writereg(pdata->pAdapter, mac_ier, pdata->mac_regs + MAC_IER); - - /* Enable all counter interrupts */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MMC_RIER); - regval = FXGMAC_SET_REG_BITS(regval, MMC_RIER_ALL_INTERRUPTS_POS, - MMC_RIER_ALL_INTERRUPTS_LEN, 0xffffffff); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MMC_RIER); - regval = readreg(pdata->pAdapter, pdata->mac_regs + MMC_TIER); - regval = FXGMAC_SET_REG_BITS(regval, MMC_TIER_ALL_INTERRUPTS_POS, - MMC_TIER_ALL_INTERRUPTS_LEN, 0xffffffff); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MMC_TIER); -} - -static int fxgmac_set_fxgmii_2500_speed(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_PS_POS, - MAC_CR_PS_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_FES_POS, - MAC_CR_FES_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_DM_POS, - MAC_CR_DM_LEN , pdata->phy_duplex); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); - - return 0; -} - -static int fxgmac_set_fxgmii_1000_speed(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_PS_POS, - MAC_CR_PS_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_FES_POS, - MAC_CR_FES_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_DM_POS, - MAC_CR_DM_LEN , pdata->phy_duplex); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); - - return 0; -} - -static int fxgmac_set_fxgmii_100_speed(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_PS_POS, - MAC_CR_PS_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_FES_POS, - MAC_CR_FES_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_DM_POS, - MAC_CR_DM_LEN , pdata->phy_duplex); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); - - return 0; -} - -static int fxgmac_set_fxgmii_10_speed(struct fxgmac_pdata *pdata) -{ - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_PS_POS, - MAC_CR_PS_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_FES_POS, - MAC_CR_FES_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_DM_POS, - MAC_CR_DM_LEN , pdata->phy_duplex); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); - - return 0; -} - - /** - * fxgmac_check_phy_link - Get link/speed status - * @pdata: pointer to gmac structure - * @speed: pointer to link speed - * @link_up: true is link is up, false otherwise - * @link_up_wait_to_complete: bool used to wait for link up or not - * - * Reads the links register to determine if link is up and the current speed - **/ -static int fxgmac_check_phy_link(struct fxgmac_pdata *pdata, - u32 *speed, bool *link_up, - bool link_up_wait_to_complete) -{ -#if defined(LINUX) || defined(DPDK) - u16 link_reg = 0; - - //DPRINTK("fxgmac_check_phy_link callin\n"); - -#ifndef DPDK - struct net_device *netdev = pdata->netdev; - if (netdev->base_addr) { - link_reg = (u16)(* ((u32 *)(netdev->base_addr + MGMT_EPHY_CTRL))); -#else - (void) link_up_wait_to_complete; - if (pdata->base_mem) { - link_reg = (u16)readreg(pdata->pAdapter, pdata->base_mem + MGMT_EPHY_CTRL); - - pdata->phy_duplex = !!(link_reg&0x4);//need check -#endif - /* - * check register address 0x1004 - * b[6:5] ephy_pause - * b[4:3] ephy_speed 0b10 1000m 0b01 100m - * b[2] ephy_duplex - * b[1] ephy_link - * b[0] ephy_reset. should be set to 1 before use phy. - */ - *link_up = false; - if (link_reg & MGMT_EPHY_CTRL_STA_EPHY_RELEASE) { - if(link_up) { - *link_up = (link_reg & MGMT_EPHY_CTRL_STA_EPHY_LINKUP) ? true : false; - } - if(speed) *speed = (link_reg & MGMT_EPHY_CTRL_STA_SPEED_MASK) >> MGMT_EPHY_CTRL_STA_SPEED_POS; - } else { - DPRINTK("fxgmac_check_phy_link ethernet PHY not released.\n"); - return -1; - } - }else { - DPRINTK("fxgmac_check_phy_link null base addr err\n"); - return -1; - } - //DPRINTK("fxgmac_check_phy_link callout, reg=%#x\n", link_reg); -#else - pdata = pdata; - speed = speed; - link_up = link_up; - link_up_wait_to_complete = link_up_wait_to_complete; -#endif - - return 0; -} - -static int fxgmac_config_mac_speed(struct fxgmac_pdata *pdata) -{ - switch (pdata->phy_speed) { - case SPEED_2500: - fxgmac_set_fxgmii_2500_speed(pdata); - break; - case SPEED_1000: - fxgmac_set_fxgmii_1000_speed(pdata); - break; - case SPEED_100: - fxgmac_set_fxgmii_100_speed(pdata); - break; - case SPEED_10: - fxgmac_set_fxgmii_10_speed(pdata); - break; - } - return 0; -} - -static int fxgmac_write_ephy_reg(struct fxgmac_pdata* pdata, u32 reg_id, u32 data) -{ - u32 regval; - u32 mdioctrl = reg_id * 0x10000 + 0x8000205; - int busy = 15; - - writereg(pdata->pAdapter, data, pdata->mac_regs + MAC_MDIO_DATA); - writereg(pdata->pAdapter, mdioctrl, pdata->mac_regs + MAC_MDIO_ADDRESS); - do { - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_MDIO_ADDRESS); - busy--; - }while((regval & MAC_MDIO_ADDRESS_BUSY) && (busy)); - - DPRINTK("fxgmac_write_ephy_reg id %d %s, ctrl=0x%08x, data=0x%08x\n", reg_id, (regval & 0x1)?"err" : "ok", regval, data); - - return (regval & MAC_MDIO_ADDRESS_BUSY) ? -1 : 0; //-1 indicates err -} - -static int fxgmac_read_ephy_reg(struct fxgmac_pdata* pdata, u32 reg_id, u32*data) -{ - u32 regval = 0, regret; - u32 mdioctrl = reg_id * 0x10000 + 0x800020d; - int busy = 15; - - writereg(pdata->pAdapter, mdioctrl, pdata->mac_regs + MAC_MDIO_ADDRESS); - do { - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_MDIO_ADDRESS); - busy--; - //DPRINTK("fxgmac_read_ephy_reg, check busy %d, ctrl=0x%08x\n", busy, regval); - }while((regval & MAC_MDIO_ADDRESS_BUSY) && (busy)); - - if (0 == (regval & MAC_MDIO_ADDRESS_BUSY)) { - regret = readreg(pdata->pAdapter, pdata->mac_regs + MAC_MDIO_DATA); - if(data) *data = regret; - //DPRINTK("fxgmac_read_ephy_reg ok, reg=0x%02x, ctrl=0x%08x, data=0x%08x\n", reg_id, regval, *data); - return regret; - } - - DPRINTK("fxgmac_read_ephy_reg id=0x%02x err, busy=%d, ctrl=0x%08x.\n", reg_id, busy, regval); - return -1; -} - -static int fxgmac_write_ephy_mmd_reg(struct fxgmac_pdata* pdata, u32 reg_id, u32 mmd, u32 data) -{ - u32 regval; - u32 mdioctrl = (mmd << 16) + 0x8000207; - u32 regdata = (reg_id << 16) + data; - //for phy mmd reg r/w operation, set more delay time than phy mii reg r/w - int busy = 60; - - writereg(pdata->pAdapter, regdata, pdata->mac_regs + MAC_MDIO_DATA); - writereg(pdata->pAdapter, mdioctrl, pdata->mac_regs + MAC_MDIO_ADDRESS); - do { - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_MDIO_ADDRESS); - busy--; - } while ((regval & MAC_MDIO_ADDRESS_BUSY) && (busy)); - - DPRINTK("fxgmac_write_ephy_mmd_reg id %d mmd %d %s, ctrl=0x%08x, data=0x%08x\n", reg_id, mmd, (regval & 0x1) ? "err" : "ok", regval, data); - //DbgPrintF(MP_TRACE, "fxgmac_write_ephy_mmd_reg id %d %s, ctrl=0x%08x, data=0x%08x busy %d", reg_id, (regval & 0x1) ? "err" : "ok", regval, data, busy); - - return (regval & MAC_MDIO_ADDRESS_BUSY) ? -1 : 0; //-1 indicates err -} - -#if !defined(LINUX) && !defined(DPDK) -static int fxgmac_read_ephy_mmd_reg(struct fxgmac_pdata* pdata, u32 reg_id, u32 mmd, u32* data) -{ - u32 regval = 0, regret; - u32 mdioctrl = (mmd << 16) + 0x800020f; - u32 regdata = (reg_id << 16); - //for phy mmd reg r/w operation, set more delay time than phy mii reg r/w - int busy = 60; - - writereg(pdata->pAdapter, regdata, pdata->mac_regs + MAC_MDIO_DATA); - writereg(pdata->pAdapter, mdioctrl, pdata->mac_regs + MAC_MDIO_ADDRESS); - - do { - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_MDIO_ADDRESS); - busy--; - } while ((regval & MAC_MDIO_ADDRESS_BUSY) && (busy)); - - if (0 == (regval & MAC_MDIO_ADDRESS_BUSY)) { - regret = readreg(pdata->pAdapter, pdata->mac_regs + MAC_MDIO_DATA); - if (data) *data = (regret & 0xffff); - return regret; - } - - DPRINTK("fxgmac_read_ephy_mmd_reg id=0x%02x mmd %d err, busy=%d, ctrl=0x%08x\n", reg_id, mmd, busy, regval); - //DbgPrintF(MP_TRACE, "fxgmac_read_ephy_mmd_reg id=0x%02x err, busy=%d, ctrl=0x%08x\n", reg_id, busy, regval); - return -1; -} -#endif - -static void fxgmac_config_flow_control(struct fxgmac_pdata* pdata) -{ -#ifndef UEFI - u32 regval = 0; -#endif - - fxgmac_config_tx_flow_control(pdata); - fxgmac_config_rx_flow_control(pdata); - -#ifndef UEFI - fxgmac_read_ephy_reg(pdata, REG_MII_ADVERTISE, ®val); - //set auto negotiation advertisement pause ability - if (pdata->tx_pause || pdata->rx_pause) { - regval = FXGMAC_SET_REG_BITS(regval, PHY_MII_ADVERTISE_PAUSE_POS, PHY_MII_ADVERTISE_PAUSE_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, PHY_MII_ADVERTISE_ASYPAUSE_POS, PHY_MII_ADVERTISE_ASYPAUSE_LEN, 1); - } else { - regval = FXGMAC_SET_REG_BITS(regval, PHY_MII_ADVERTISE_PAUSE_POS, PHY_MII_ADVERTISE_PAUSE_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, PHY_MII_ADVERTISE_ASYPAUSE_POS, PHY_MII_ADVERTISE_ASYPAUSE_LEN, 0); - } - fxgmac_write_ephy_reg(pdata, REG_MII_ADVERTISE, regval); - //after change the auto negotiation advertisement need to soft reset - fxgmac_read_ephy_reg(pdata, REG_MII_BMCR, ®val); - regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_RESET_POS, PHY_CR_RESET_LEN, 1); - fxgmac_write_ephy_reg(pdata, REG_MII_BMCR, regval); -#endif -} - -static int fxgmac_set_ephy_autoneg_advertise(struct fxgmac_pdata* pdata, struct fxphy_ag_adv phy_ag_adv) -{ - u32 regval = 0, ret = 0; - - if (phy_ag_adv.auto_neg_en) { - fxgmac_read_ephy_reg(pdata, REG_MII_BMCR, ®val); - regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_AUTOENG_POS, PHY_CR_AUTOENG_LEN, 1); - ret |= fxgmac_write_ephy_reg(pdata, REG_MII_BMCR, regval); - } else { - fxgmac_read_ephy_reg(pdata, REG_MII_BMCR, ®val); - regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_AUTOENG_POS, PHY_CR_AUTOENG_LEN, 0); - ret |= fxgmac_write_ephy_reg(pdata, REG_MII_BMCR, regval); - } - - fxgmac_read_ephy_reg(pdata, REG_MII_CTRL1000, ®val); - if (phy_ag_adv.full_1000m) { - regval = FXGMAC_SET_REG_BITS(regval, PHY_MII_CTRL1000_1000FULL_POS, PHY_MII_CTRL1000_1000FULL_LEN, 1); - } else { - regval = FXGMAC_SET_REG_BITS(regval, PHY_MII_CTRL1000_1000FULL_POS, PHY_MII_CTRL1000_1000FULL_LEN, 0); - } - if (phy_ag_adv.half_1000m) { - regval = FXGMAC_SET_REG_BITS(regval, PHY_MII_CTRL1000_1000HALF_POS, PHY_MII_CTRL1000_1000HALF_LEN, 1); - } else { - regval = FXGMAC_SET_REG_BITS(regval, PHY_MII_CTRL1000_1000HALF_POS, PHY_MII_CTRL1000_1000HALF_LEN, 0); - } - ret |= fxgmac_write_ephy_reg(pdata, REG_MII_CTRL1000, regval); - - fxgmac_read_ephy_reg(pdata, REG_MII_ADVERTISE, ®val); - - if (phy_ag_adv.full_100m) { - regval = FXGMAC_SET_REG_BITS(regval, PHY_MII_ADVERTISE_100FULL_POS, PHY_MII_ADVERTISE_100FULL_LEN, 1); - } else { - regval = FXGMAC_SET_REG_BITS(regval, PHY_MII_ADVERTISE_100FULL_POS, PHY_MII_ADVERTISE_100FULL_LEN, 0); - } - if (phy_ag_adv.half_100m) { - regval = FXGMAC_SET_REG_BITS(regval, PHY_MII_ADVERTISE_100HALF_POS, PHY_MII_ADVERTISE_100HALF_LEN, 1); - } else { - regval = FXGMAC_SET_REG_BITS(regval, PHY_MII_ADVERTISE_100HALF_POS, PHY_MII_ADVERTISE_100HALF_LEN, 0); - } - if (phy_ag_adv.full_10m) { - regval = FXGMAC_SET_REG_BITS(regval, PHY_MII_ADVERTISE_10FULL_POS, PHY_MII_ADVERTISE_10FULL_LEN, 1); - } else { - regval = FXGMAC_SET_REG_BITS(regval, PHY_MII_ADVERTISE_10FULL_POS, PHY_MII_ADVERTISE_10FULL_LEN, 0); - } - if (phy_ag_adv.half_10m) { - regval = FXGMAC_SET_REG_BITS(regval, PHY_MII_ADVERTISE_10HALF_POS, PHY_MII_ADVERTISE_10HALF_LEN, 1); - } else { - regval = FXGMAC_SET_REG_BITS(regval, PHY_MII_ADVERTISE_10HALF_POS, PHY_MII_ADVERTISE_10HALF_LEN, 0); - } - - ret |= fxgmac_write_ephy_reg(pdata, REG_MII_ADVERTISE, regval); - //after change the auto negotiation advertisement need to soft reset - fxgmac_read_ephy_reg(pdata, REG_MII_BMCR, ®val); - regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_RESET_POS, PHY_CR_RESET_LEN, 1); - ret |= fxgmac_write_ephy_reg(pdata, REG_MII_BMCR, regval); - - return ret; -} - -static int fxgmac_phy_config(struct fxgmac_pdata* pdata) -{ - struct fxphy_ag_adv phy_ag_adv; - - if (pdata->phy_autoeng) { - phy_ag_adv.auto_neg_en = 1; - } else { - phy_ag_adv.auto_neg_en = 0; - } - switch (pdata->phy_speed) - { - case SPEED_1000: - phy_ag_adv.full_1000m = 1, phy_ag_adv.half_1000m = 0, phy_ag_adv.full_100m = 1, phy_ag_adv.half_100m = 1, phy_ag_adv.full_10m = 1, phy_ag_adv.half_10m = 1; - break; - - case SPEED_100: - phy_ag_adv.full_1000m = 0, phy_ag_adv.half_1000m = 0; - if (pdata->phy_duplex) { - phy_ag_adv.full_100m = 1; - } else { - phy_ag_adv.full_100m = 0; - } - phy_ag_adv.half_100m = 1, phy_ag_adv.full_10m = 1, phy_ag_adv.half_10m = 1; - break; - - case SPEED_10: - phy_ag_adv.full_1000m = 0, phy_ag_adv.half_1000m = 0; - phy_ag_adv.full_100m = 0, phy_ag_adv.half_100m = 0; - if (pdata->phy_duplex) { - phy_ag_adv.full_10m = 1; - } else { - phy_ag_adv.full_10m = 0; - } - phy_ag_adv.half_10m = 1; - break; - - default: - break; - } - return fxgmac_set_ephy_autoneg_advertise(pdata, phy_ag_adv); -} - -static void fxgmac_phy_green_ethernet(struct fxgmac_pdata* pdata) -{ - u32 regval = 0; - //GREEN - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_REG_PMA_DBG0_ADC); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_ENABLE_GIGA_POWER_SAVING_FOR_SHORT_CABLE); - - //CLD - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_REG_CLD_REG0); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_ENABLE_CLD_NP_WP); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_REG_CLD_REG1); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_ENABLE_CLD_GT_HT_BT); - - //after change green ethernet & CLD need to soft reset - fxgmac_read_ephy_reg(pdata, REG_MII_BMCR, ®val); - regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_RESET_POS, PHY_CR_RESET_LEN, 1); - fxgmac_write_ephy_reg(pdata, REG_MII_BMCR, regval); -} - -static void fxgmac_phy_eee_feature(struct fxgmac_pdata* pdata) -{ - u32 regval = 0; - - regval = readreg(pdata->pAdapter, pdata->mac_regs + DMA_SBMR); - regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_EN_LPI_POS, DMA_SBMR_EN_LPI_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_LPI_XIT_PKT_POS, DMA_SBMR_LPI_XIT_PKT_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_AALE_POS, DMA_SBMR_AALE_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + DMA_SBMR); - - //regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_IER); - //regval = FXGMAC_SET_REG_BITS(regval, MAC_LPIIE_POS, MAC_LPIIE_LEN, 1); - //writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_IER); - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_LPI_STA); - regval = FXGMAC_SET_REG_BITS(regval, MAC_LPIATE_POS, MAC_LPIATE_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, MAC_LPITXA_POS, MAC_LPITXA_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, MAC_PLS_POS, MAC_PLS_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, MAC_LPIEN_POS, MAC_LPIEN_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_LPI_STA); - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_LPI_TIMER); - regval = FXGMAC_SET_REG_BITS(regval, MAC_LPIET_POS, MAC_LPIET_LEN, MAC_LPI_ENTRY_TIMER); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_LPI_TIMER); - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_LPI_CONTROL); - regval = FXGMAC_SET_REG_BITS(regval, MAC_TWT_POS, MAC_TWT_LEN, MAC_TWT_TIMER); - regval = FXGMAC_SET_REG_BITS(regval, MAC_LST_POS, MAC_LST_LEN, MAC_LST_TIMER); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_LPI_CONTROL); - - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_MS_TIC_COUNTER); - regval = FXGMAC_SET_REG_BITS(regval, MAC_MS_TIC_POS, MAC_MS_TIC_LEN, MAC_MS_TIC); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_MS_TIC_COUNTER); - - //usleep_range_ex(pdata->pAdapter, 1500, 1500); - - fxgmac_write_ephy_mmd_reg(pdata, REG_MMD_EEE_ABILITY_REG, 0x07, REG_MMD_EEE_ABILITY_VALUE); - - //after change EEE need to soft reset - fxgmac_read_ephy_reg(pdata, REG_MII_BMCR, ®val); - regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_RESET_POS, PHY_CR_RESET_LEN, 1); - fxgmac_write_ephy_reg(pdata, REG_MII_BMCR, regval); -} - -static void fxgmac_reset_phy(struct fxgmac_pdata* pdata) -{ - u32 value = 0; - - value = FXGMAC_SET_REG_BITS(value, MGMT_EPHY_CTRL_RESET_POS, MGMT_EPHY_CTRL_RESET_LEN, MGMT_EPHY_CTRL_STA_EPHY_RESET); - writereg(pdata->pAdapter, value, pdata->base_mem + MGMT_EPHY_CTRL); - usleep_range_ex(pdata->pAdapter, 1500, 1500); -} - -void fxgmac_release_phy(struct fxgmac_pdata* pdata) -{ - u32 value = 0; - - value = FXGMAC_SET_REG_BITS(value, MGMT_EPHY_CTRL_RESET_POS, MGMT_EPHY_CTRL_RESET_LEN, MGMT_EPHY_CTRL_STA_EPHY_RELEASE); - writereg(pdata->pAdapter, value, pdata->base_mem + MGMT_EPHY_CTRL); - usleep_range_ex(pdata->pAdapter, 100, 150); - value = readreg(pdata->pAdapter, pdata->base_mem + MGMT_EPHY_CTRL); - DBGPRINT(MP_LOUD, ("0x1004: 0x%x\n", value)); -#ifdef AISC_MODE - fxgmac_read_ephy_reg(pdata, REG_MII_SPEC_CTRL, &value);// read phy specific control - value = FXGMAC_SET_REG_BITS(value, PHY_MII_SPEC_CTRL_CRS_ON_POS, PHY_MII_SPEC_CTRL_CRS_ON_LEN, 1);//set on crs on - fxgmac_write_ephy_reg(pdata, REG_MII_SPEC_CTRL, value);// phy specific control set on crs on - - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_ANALOG_CFG3); - fxgmac_read_ephy_reg(pdata, REG_MII_EXT_DATA, &value); - // VGA bandwidth, default is 2 after reset. Set to 0 to mitigate unstable issue in 130m. - value = FXGMAC_SET_REG_BITS(value, MII_EXT_ANALOG_CFG3_ADC_START_CFG_POS, - MII_EXT_ANALOG_CFG3_ADC_START_CFG_LEN, MII_EXT_ANALOG_CFG3_ADC_START_CFG_DEFAULT); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, value); - -#if 0 - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_PMA_DEBUG_KCOEF); - fxgmac_read_ephy_reg(pdata, REG_MII_EXT_DATA, &value); - /* After reset, it's 0x10. We need change it to 0x20 to make it easier to linkup in gigabit mode with long cable. But this is has side effect.*/ - value = FXGMAC_SET_REG_BITS(value, MII_EXT_PMA_DEBUG_KCOEF_IPR_KCOEF_GE_LNG_POS, - MII_EXT_PMA_DEBUG_KCOEF_IPR_KCOEF_GE_LNG_LEN, MII_EXT_PMA_DEBUG_KCOEF_IPR_KCOEF_GE_LNG_DEFAULT); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, value); -#endif - - fxgmac_efuse_read_data(pdata, EFUSE_LED_ADDR, &value); - //led index use bit0~bit5 - value = FXGMAC_GET_REG_BITS(value, EFUSE_LED_POS, EFUSE_LED_LEN); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_ANALOG_CFG2); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_ANALOG_CFG2_LED_VALUE); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_ANALOG_CFG8); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_ANALOG_CFG8_LED_VALUE); - - if (EFUSE_LED_COMMON_SOLUTION != value) { - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED0_CFG); - switch (value) { - case EFUSE_LED_SOLUTION1: - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_COMMON_LED0_CFG_VALUE_SOLUTION1); - break; - case EFUSE_LED_SOLUTION2: - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_COMMON_LED0_CFG_VALUE_SOLUTION2); - break; - case EFUSE_LED_SOLUTION3: - case EFUSE_LED_SOLUTION4: - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_COMMON_LED0_CFG_VALUE_SOLUTION3); - break; - default: - //default solution - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_COMMON_LED0_CFG_VALUE_SOLUTION0); - break; - } - - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED1_CFG); - switch (value) { - case EFUSE_LED_SOLUTION1: - case EFUSE_LED_SOLUTION4: - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_COMMON_LED1_CFG_VALUE_SOLUTION1); - break; - case EFUSE_LED_SOLUTION2: - case EFUSE_LED_SOLUTION3: - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_COMMON_LED1_CFG_VALUE_SOLUTION2); - break; - default: - //default solution - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_COMMON_LED1_CFG_VALUE_SOLUTION0); - break; - } - - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED2_CFG); - switch (value) { - case EFUSE_LED_SOLUTION1: - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION0); - break; - case EFUSE_LED_SOLUTION2: - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION2); - break; - case EFUSE_LED_SOLUTION3: - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION3); - break; - case EFUSE_LED_SOLUTION4: - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION4); - break; - default: - //default solution - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION0); - break; - } - - if (EFUSE_LED_SOLUTION2 == value) { - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED_BLINK_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_COMMON_LED_BLINK_CFG_SOLUTION2); - } - } -#endif -} - -#if !defined(UEFI) -static void fxgmac_enable_phy_check(struct fxgmac_pdata* pdata) -{ - u32 value = 0; - //value = 0xa8d0; - - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_PKG_CFG0); - fxgmac_read_ephy_reg(pdata, REG_MII_EXT_DATA, &value); - value = FXGMAC_SET_REG_BITS(value, REG_MII_EXT_PKG_CHECK_POS, REG_MII_EXT_PKG_CHECK_LEN, REG_MII_EXT_PKG_ENABLE_CHECK); - - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_PKG_CFG0); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, value); -} - -static void fxgmac_disable_phy_check(struct fxgmac_pdata* pdata) -{ - u32 value = 0; - //value = 0x68d0; - - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_PKG_CFG0); - fxgmac_read_ephy_reg(pdata, REG_MII_EXT_DATA, &value); - value = FXGMAC_SET_REG_BITS(value, REG_MII_EXT_PKG_CHECK_POS, REG_MII_EXT_PKG_CHECK_LEN, REG_MII_EXT_PKG_DISABLE_CHECK); - - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_PKG_CFG0); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, value); -} - -static void fxgmac_setup_cable_loopback(struct fxgmac_pdata* pdata) -{ - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_SLEEP_CONTROL_REG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_SLEEP_REG_ENABLE_LOOPBACK); - - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_LPBK_REG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_LPBK_REG_ENABLE_LOOPBACK); - - fxgmac_write_ephy_reg(pdata, REG_MII_BMCR, REG_MII_BMCR_ENABLE_LOOPBACK); -} - -static void fxgmac_clean_cable_loopback(struct fxgmac_pdata* pdata) -{ - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_SLEEP_CONTROL_REG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_SLEEP_REG_CLEAN_LOOPBACK); - - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_LPBK_REG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_LPBK_REG_CLEAN_LOOPBACK); - - fxgmac_write_ephy_reg(pdata, REG_MII_BMCR, REG_MII_BMCR_DISABLE_LOOPBACK); -} - -static void fxgmac_disable_phy_sleep(struct fxgmac_pdata* pdata) -{ - u32 value = 0; - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_SLEEP_CONTROL_REG); - fxgmac_read_ephy_reg(pdata, REG_MII_EXT_DATA, &value); - - value = FXGMAC_SET_REG_BITS(value, MII_EXT_SLEEP_CONTROL1_EN_POS, MII_EXT_SLEEP_CONTROL1_EN_LEN, 0); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_SLEEP_CONTROL_REG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, value); -} - -static void fxgmac_enable_phy_sleep(struct fxgmac_pdata* pdata) -{ - u32 value = 0; - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_SLEEP_CONTROL_REG); - fxgmac_read_ephy_reg(pdata, REG_MII_EXT_DATA, &value); - - value = FXGMAC_SET_REG_BITS(value, MII_EXT_SLEEP_CONTROL1_EN_POS, MII_EXT_SLEEP_CONTROL1_EN_LEN, 1); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_SLEEP_CONTROL_REG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, value); -} -#endif - -static void fxgmac_close_phy_led(struct fxgmac_pdata* pdata) -{ - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED0_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, 0x00); - - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED1_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, 0x00); - - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED2_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, 0x00); -} - -static void fxmgac_config_led_under_active(struct fxgmac_pdata* pdata) -{ - u32 regval = 0; - fxgmac_efuse_read_data(pdata, EFUSE_LED_ADDR, ®val); - //led index use bit0~bit5 - regval = FXGMAC_GET_REG_BITS(regval, EFUSE_LED_POS, EFUSE_LED_LEN); - if (EFUSE_LED_COMMON_SOLUTION == regval) { - DbgPrintF(MP_TRACE, "%s >>>", __FUNCTION__); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.s0_led_setting[0]); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED0_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.s0_led_setting[1]); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED1_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.s0_led_setting[2]); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED2_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.s0_led_setting[3]); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED_BLINK_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.s0_led_setting[4]); - } -} - -static void fxgmac_config_led_under_sleep(struct fxgmac_pdata* pdata) -{ - u32 regval = 0; - fxgmac_efuse_read_data(pdata, EFUSE_LED_ADDR, ®val); - //led index use bit0~bit5 - regval = FXGMAC_GET_REG_BITS(regval, EFUSE_LED_POS, EFUSE_LED_LEN); - if (EFUSE_LED_COMMON_SOLUTION == regval) { - DbgPrintF(MP_TRACE, "%s >>>", __FUNCTION__); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.s3_led_setting[0]); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED0_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.s3_led_setting[1]); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED1_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.s3_led_setting[2]); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED2_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.s3_led_setting[3]); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED_BLINK_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.s3_led_setting[4]); - } -} - -static void fxgmac_config_led_under_shutdown(struct fxgmac_pdata* pdata) -{ - u32 regval = 0; - fxgmac_efuse_read_data(pdata, EFUSE_LED_ADDR, ®val); - //led index use bit0~bit5 - regval = FXGMAC_GET_REG_BITS(regval, EFUSE_LED_POS, EFUSE_LED_LEN); - if (EFUSE_LED_COMMON_SOLUTION == regval) { - DbgPrintF(MP_TRACE, "%s >>>", __FUNCTION__); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.s5_led_setting[0]); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED0_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.s5_led_setting[1]); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED1_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.s5_led_setting[2]); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED2_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.s5_led_setting[3]); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED_BLINK_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.s5_led_setting[4]); - } -} - -static void fxgmac_config_led_under_disable(struct fxgmac_pdata* pdata) -{ - u32 regval = 0; - fxgmac_efuse_read_data(pdata, EFUSE_LED_ADDR, ®val); - //led index use bit0~bit5 - regval = FXGMAC_GET_REG_BITS(regval, EFUSE_LED_POS, EFUSE_LED_LEN); - if (EFUSE_LED_COMMON_SOLUTION == regval) { - DbgPrintF(MP_TRACE, "%s >>>", __FUNCTION__); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.disable_led_setting[0]); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED0_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.disable_led_setting[1]); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED1_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.disable_led_setting[2]); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED2_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.disable_led_setting[3]); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED_BLINK_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, pdata->led.disable_led_setting[4]); - } - else { - //http://redmine.motor-comm.com/issues/4101 - //for disable case,reset phy to close LED - fxgmac_reset_phy(pdata); - } -} - -#ifdef LINUX -extern void fxgmac_diag_get_rx_info(struct fxgmac_channel *channel); - -static int fxgmac_dev_read(struct fxgmac_channel *channel) -{ - struct fxgmac_pdata *pdata = channel->pdata; - struct fxgmac_ring *ring = channel->rx_ring; - struct net_device *netdev = pdata->netdev; - struct fxgmac_desc_data *desc_data; - struct fxgmac_dma_desc *dma_desc; - struct fxgmac_pkt_info *pkt_info; - unsigned int err, etlt, l34t; - - //unsigned int i; - static unsigned int cnt_incomplete = 0; - - desc_data = FXGMAC_GET_DESC_DATA(ring, ring->cur); - dma_desc = desc_data->dma_desc; - pkt_info = &ring->pkt_info; - - /* Check for data availability */ - if (FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, - RX_NORMAL_DESC3_OWN_POS, - RX_NORMAL_DESC3_OWN_LEN)) - { - return 1; - } - - /* Make sure descriptor fields are read after reading the OWN bit */ - dma_rmb(); - - if (netif_msg_rx_status(pdata)) - fxgmac_dump_rx_desc(pdata, ring, ring->cur); - - if (FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, - RX_NORMAL_DESC3_CTXT_POS, - RX_NORMAL_DESC3_CTXT_LEN)) { - /* Timestamp Context Descriptor */ - fxgmac_get_rx_tstamp(pkt_info, dma_desc); - - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_CONTEXT_POS, - RX_PACKET_ATTRIBUTES_CONTEXT_LEN, - 1); - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_POS, - RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_LEN, - 0); - if(netif_msg_rx_status(pdata)) DPRINTK("dev_read context desc,ch=%s\n",channel->name); - return 0; - } - - /* Normal Descriptor, be sure Context Descriptor bit is off */ - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_CONTEXT_POS, - RX_PACKET_ATTRIBUTES_CONTEXT_LEN, - 0); - - /* Indicate if a Context Descriptor is next */ -#if 0 - if (FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, - RX_NORMAL_DESC3_CDA_POS, - RX_NORMAL_DESC3_CDA_LEN)) - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_POS, - RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_LEN, - 1); -#endif - /* Get the header length */ - if (FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, - RX_NORMAL_DESC3_FD_POS, - RX_NORMAL_DESC3_FD_LEN)) { - desc_data->rx.hdr_len = FXGMAC_GET_REG_BITS_LE(dma_desc->desc2, - RX_NORMAL_DESC2_HL_POS, - RX_NORMAL_DESC2_HL_LEN); - if (desc_data->rx.hdr_len) - pdata->stats.rx_split_header_packets++; - } - l34t = 0; - -#if 0 //(FXGMAC_RSS_FEATURE_ENABLED) //20210608 - /* Get the RSS hash */ - if (FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, - RX_NORMAL_DESC3_RSV_POS, - RX_NORMAL_DESC3_RSV_LEN)) { - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_RSS_HASH_POS, - RX_PACKET_ATTRIBUTES_RSS_HASH_LEN, - 1); - - pkt_info->rss_hash = le32_to_cpu(dma_desc->desc1); - - l34t = FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, - RX_NORMAL_DESC3_L34T_POS, - RX_NORMAL_DESC3_L34T_LEN); - 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: - pkt_info->rss_hash_type = PKT_HASH_TYPE_L4; - break; - default: - pkt_info->rss_hash_type = PKT_HASH_TYPE_L3; - } - } -#endif - /* Get the pkt_info length */ - desc_data->rx.len = FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, - RX_NORMAL_DESC3_PL_POS, - RX_NORMAL_DESC3_PL_LEN); - //DPRINTK("dev_read upon FD=1, pkt_len=%u\n",desc_data->rx.len); - - if (!FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, - RX_NORMAL_DESC3_LD_POS, - RX_NORMAL_DESC3_LD_LEN)) { - /* Not all the data has been transferred for this pkt_info */ - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_INCOMPLETE_POS, - RX_PACKET_ATTRIBUTES_INCOMPLETE_LEN, - 1); - cnt_incomplete++; - if ((cnt_incomplete < 2) && netif_msg_rx_status(pdata)) - DPRINTK("dev_read NOT last desc,pkt incomplete yet,%u\n", cnt_incomplete); - - return 0; - } - if ((cnt_incomplete) && netif_msg_rx_status(pdata)) - DPRINTK("dev_read rx back to normal and incomplete cnt=%u\n", cnt_incomplete); - cnt_incomplete = 0; //when back to normal, reset cnt - - /* This is the last of the data for this pkt_info */ - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_INCOMPLETE_POS, - RX_PACKET_ATTRIBUTES_INCOMPLETE_LEN, - 0); - - /* Set checksum done indicator as appropriate */ - if (netdev->features & NETIF_F_RXCSUM) - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_CSUM_DONE_POS, - RX_PACKET_ATTRIBUTES_CSUM_DONE_LEN, - 1); - - /* Check for errors (only valid in last descriptor) */ - err = FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, - RX_NORMAL_DESC3_ES_POS, - RX_NORMAL_DESC3_ES_LEN); - etlt = FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, - RX_NORMAL_DESC3_ETLT_POS, - RX_NORMAL_DESC3_ETLT_LEN); - //netif_dbg(pdata, rx_status, netdev, "err=%u, etlt=%#x\n", err, etlt); - if((err) && netif_msg_rx_status(pdata)) { - DPRINTK("dev_read:head_len=%u,pkt_len=%u,err=%u, etlt=%#x,desc2=0x%08x,desc3=0x%08x\n",desc_data->rx.hdr_len, desc_data->rx.len, err, - etlt, dma_desc->desc2, dma_desc->desc3); - } - - if (!err || !etlt) { - /* No error if err is 0 or etlt is 0 */ - if ((etlt == 0x4 /*yzhang changed to 0x4, 0x09*/) && - (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) { - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_VLAN_CTAG_POS, - RX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN, 1); - pkt_info->vlan_ctag = - FXGMAC_GET_REG_BITS_LE(dma_desc->desc0, - RX_NORMAL_DESC0_OVT_POS, - RX_NORMAL_DESC0_OVT_LEN); - netif_dbg(pdata, rx_status, netdev, "vlan-ctag=%#06x\n", - pkt_info->vlan_ctag); - } - } else { - if (etlt == 0x05 || etlt == 0x06) - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_CSUM_DONE_POS, - RX_PACKET_ATTRIBUTES_CSUM_DONE_LEN, 0); - else - pkt_info->errors = FXGMAC_SET_REG_BITS( - pkt_info->errors, RX_PACKET_ERRORS_FRAME_POS, - RX_PACKET_ERRORS_FRAME_LEN, 1); - } - - return 0; -} -#endif - -static int fxgmac_enable_int(struct fxgmac_channel *channel, - enum fxgmac_int int_id) -{ - unsigned int dma_ch_ier; - - dma_ch_ier = readreg(channel->pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_IER)); - - switch (int_id) { - case FXGMAC_INT_DMA_CH_SR_TI: - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_TIE_POS, - DMA_CH_IER_TIE_LEN, 1); - break; - case FXGMAC_INT_DMA_CH_SR_TPS: - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_TXSE_POS, - DMA_CH_IER_TXSE_LEN, 1); - break; - case FXGMAC_INT_DMA_CH_SR_TBU: - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_TBUE_POS, - DMA_CH_IER_TBUE_LEN, 1); - break; - case FXGMAC_INT_DMA_CH_SR_RI: - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_RIE_POS, - DMA_CH_IER_RIE_LEN, 1); - break; - case FXGMAC_INT_DMA_CH_SR_RBU: - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_RBUE_POS, - DMA_CH_IER_RBUE_LEN, 1); - break; - case FXGMAC_INT_DMA_CH_SR_RPS: - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_RSE_POS, - DMA_CH_IER_RSE_LEN, 1); - break; - case FXGMAC_INT_DMA_CH_SR_TI_RI: - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_TIE_POS, - DMA_CH_IER_TIE_LEN, 1); - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_RIE_POS, - DMA_CH_IER_RIE_LEN, 1); - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_NIE_POS, - DMA_CH_IER_NIE_LEN, 1); - break; - case FXGMAC_INT_DMA_CH_SR_FBE: - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_FBEE_POS, - DMA_CH_IER_FBEE_LEN, 1); - break; - case FXGMAC_INT_DMA_ALL: - dma_ch_ier |= channel->saved_ier; - break; - default: - return -1; - } - - writereg(channel->pdata->pAdapter, dma_ch_ier, FXGMAC_DMA_REG(channel, DMA_CH_IER)); - - return 0; -} - -static int fxgmac_disable_int(struct fxgmac_channel *channel, - enum fxgmac_int int_id) -{ - unsigned int dma_ch_ier; - - dma_ch_ier = readreg(channel->pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_IER)); - - switch (int_id) { - case FXGMAC_INT_DMA_CH_SR_TI: - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_TIE_POS, - DMA_CH_IER_TIE_LEN, 0); - break; - case FXGMAC_INT_DMA_CH_SR_TPS: - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_TXSE_POS, - DMA_CH_IER_TXSE_LEN, 0); - break; - case FXGMAC_INT_DMA_CH_SR_TBU: - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_TBUE_POS, - DMA_CH_IER_TBUE_LEN, 0); - break; - case FXGMAC_INT_DMA_CH_SR_RI: - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_RIE_POS, - DMA_CH_IER_RIE_LEN, 0); - break; - case FXGMAC_INT_DMA_CH_SR_RBU: - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_RBUE_POS, - DMA_CH_IER_RBUE_LEN, 0); - break; - case FXGMAC_INT_DMA_CH_SR_RPS: - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_RSE_POS, - DMA_CH_IER_RSE_LEN, 0); - break; - case FXGMAC_INT_DMA_CH_SR_TI_RI: - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_TIE_POS, - DMA_CH_IER_TIE_LEN, 0); - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_RIE_POS, - DMA_CH_IER_RIE_LEN, 0); - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_NIE_POS, - DMA_CH_IER_NIE_LEN, 0); - break; - case FXGMAC_INT_DMA_CH_SR_FBE: - dma_ch_ier = FXGMAC_SET_REG_BITS( - dma_ch_ier, DMA_CH_IER_FBEE_POS, - DMA_CH_IER_FBEE_LEN, 0); - break; - case FXGMAC_INT_DMA_ALL: - channel->saved_ier = dma_ch_ier & FXGMAC_DMA_INTERRUPT_MASK; - dma_ch_ier &= ~FXGMAC_DMA_INTERRUPT_MASK; - break; - default: - return -1; - } - - writereg(channel->pdata->pAdapter, dma_ch_ier, FXGMAC_DMA_REG(channel, DMA_CH_IER)); - - return 0; -} - -#ifdef LINUX -static int fxgmac_dismiss_DMA_int(struct fxgmac_channel *channel, int int_id) -{ - unsigned int dma_ch_ier; - - int_id = int_id; - dma_ch_ier = readreg(channel->pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_SR /*1160*/)); - writereg(channel->pdata->pAdapter, dma_ch_ier, FXGMAC_DMA_REG(channel, DMA_CH_SR)); - - return 0; -} - -static void fxgmac_dismiss_MTL_Q_int(struct fxgmac_pdata *pdata) -{ - unsigned int q_count, i; - unsigned int mtl_q_isr; - - 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 = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_Q_ISR)); - writereg(pdata->pAdapter, mtl_q_isr, FXGMAC_MTL_REG(pdata, i, MTL_Q_ISR)); - } -} - -static int fxgmac_dismiss_MAC_int(struct fxgmac_pdata *pdata) -{ - u32 regval,regErrVal; - - /* all MAC interrupts in 0xb0 */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_ISR); - /* MAC tx/rx error interrupts in 0xb8 */ - regErrVal = readreg(pdata->pAdapter, pdata->mac_regs + MAC_TX_RX_STA); -#if 0 //write clear - if(FXGMAC_GET_REG_BITS(readreg(pdata->mac_regs + MAC_CSR_SW_CTRL), - 0/*rcwe*/, - 1)) - { - writereg(regval, pdata->mac_regs + MAC_ISR); - writereg(regErrVal, pdata->mac_regs + MAC_TX_RX_STA); - } -#endif - return 0; -} - -static int fxgmac_dismiss_MAC_PMT_int(struct fxgmac_pdata *pdata) -{ - u32 regval; - - /* MAC PMT interrupts in 0xc0 */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); -#if 0 //write clear - if(FXGMAC_GET_REG_BITS(readreg(pdata->mac_regs + MAC_CSR_SW_CTRL), - 0/*rcwe*/, - 1)) - { - writereg(regval, pdata->mac_regs + MAC_PMT_STA); - } - -#endif - return 0; -} - -static int fxgmac_dismiss_MAC_LPI_int(struct fxgmac_pdata *pdata) -{ - u32 regval; - - /* MAC PMT interrupts in 0xc0 */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_LPI_STA); -#if 0 //write clear - if(FXGMAC_GET_REG_BITS(readreg(pdata->mac_regs + MAC_CSR_SW_CTRL), - 0/*rcwe*/, - 1)) - { - writereg(regval, pdata->mac_regs + MAC_LPI_STA); - } - -#endif - return 0; -} - -static int fxgmac_dismiss_MAC_DBG_int(struct fxgmac_pdata *pdata) -{ - u32 regval; - - /* MAC PMT interrupts in 0xc0 */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_DBG_STA); -#if 1 //write clear - { - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_DBG_STA); - } - -#endif - return 0; -} -#endif - -int fxgmac_dismiss_all_int(struct fxgmac_pdata *pdata) -{ -#ifdef LINUX - struct fxgmac_channel *channel; - unsigned int i, regval; - struct net_device *netdev = pdata->netdev; - - if (netif_msg_drv(pdata)) { DPRINTK("fxgmac_dismiss_all_int callin\n"); } - - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - fxgmac_dismiss_DMA_int(channel, 0); - } - fxgmac_dismiss_MTL_Q_int(pdata); - fxgmac_dismiss_MAC_int(pdata); - fxgmac_dismiss_MAC_PMT_int(pdata); - fxgmac_dismiss_MAC_LPI_int(pdata); - fxgmac_dismiss_MAC_DBG_int(pdata); - - //control module int to PCIe slot - if (netdev->base_addr) { - regval = (unsigned int)(* ((u32 *)(netdev->base_addr + MGMT_INT_CTRL0))); - } -#else - pdata = pdata; -#endif - return 0; -} - -static void fxgmac_set_interrupt_moderation(struct fxgmac_pdata* pdata) -{ - u32 value = 0, time; -#if defined (UEFI) - pdata->intr_mod_timer = INT_MOD_IN_US; -#elif defined (_WIN32) || defined (_WIN64) - // the Windows driver initializes it somewhere else -#else - pdata->intr_mod_timer = INT_MOD_IN_US; -#endif - - time = (pdata->intr_mod) ? pdata->intr_mod_timer : 0; -#ifdef LINUX - time = (pdata->intr_mod) ? pdata->tx_usecs : 0; -#endif - value = FXGMAC_SET_REG_BITS(value, INT_MOD_TX_POS, INT_MOD_TX_LEN, time); - -#ifdef LINUX - time = (pdata->intr_mod) ? pdata->rx_usecs : 0; -#endif - - value = FXGMAC_SET_REG_BITS(value, INT_MOD_RX_POS, INT_MOD_RX_LEN, time); - writereg(pdata->pAdapter, value, pdata->base_mem + INT_MOD); -} -static void fxgmac_enable_msix_rxtxinterrupt(struct fxgmac_pdata* pdata) -{ - u32 intid; - - for (intid = 0; intid < MSIX_TBL_RXTX_NUM; intid++) { - writereg(pdata->pAdapter, 0, pdata->base_mem + MSIX_TBL_BASE_ADDR + MSIX_TBL_MASK_OFFSET + intid * 16); - } -} -static void fxgmac_disable_msix_interrupt(struct fxgmac_pdata* pdata) -{ - u32 intid; - - for (intid = 0; intid < MSIX_TBL_MAX_NUM; intid++) { - writereg(pdata->pAdapter, 0x1, pdata->base_mem + MSIX_TBL_BASE_ADDR + MSIX_TBL_MASK_OFFSET + intid * 16); - } -} -static void fxgmac_enable_msix_rxtxphyinterrupt(struct fxgmac_pdata* pdata) -{ - u32 intid, regval = 0; -#if !(FUXI_EPHY_INTERRUPT_D0_OFF) - struct fxgmac_hw_ops* hw_ops = &pdata->hw_ops; -#endif - - for (intid = 0; intid < MSIX_TBL_RXTX_NUM; intid++) { - writereg(pdata->pAdapter, 0, pdata->base_mem + MSIX_TBL_BASE_ADDR + MSIX_TBL_MASK_OFFSET + intid * 16); - } - writereg(pdata->pAdapter, 0, pdata->base_mem + MSIX_TBL_BASE_ADDR + MSIX_TBL_MASK_OFFSET + MSI_ID_PHY_OTHER * 16); -#if !(FUXI_EPHY_INTERRUPT_D0_OFF) - hw_ops->read_ephy_reg(pdata, REG_MII_INT_STATUS, NULL);// clear phy interrupt - regval = FXGMAC_SET_REG_BITS(0, PHY_INT_MASK_LINK_UP_POS, PHY_INT_MASK_LINK_UP_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, PHY_INT_MASK_LINK_DOWN_POS, PHY_INT_MASK_LINK_DOWN_LEN, 1); - hw_ops->write_ephy_reg(pdata, REG_MII_INT_MASK, regval);//enable phy interrupt ASIC bit10 linkup bit11 linkdown -#endif -} -static void fxgmac_enable_msix_one_interrupt(struct fxgmac_pdata* pdata,u32 intid) -{ - writereg(pdata->pAdapter, 0, pdata->base_mem + MSIX_TBL_BASE_ADDR + MSIX_TBL_MASK_OFFSET + intid * 16); - //DbgPrintF(MP_LOUD, "%s - Ephy, MsgId %d is enabled.", __FUNCTION__, IntId); -} - -static void fxgmac_disable_msix_one_interrupt(struct fxgmac_pdata* pdata, u32 intid) -{ - writereg(pdata->pAdapter, 0x01, pdata->base_mem + MSIX_TBL_BASE_ADDR + MSIX_TBL_MASK_OFFSET + intid * 16); - //DbgPrintF(MP_LOUD, "%s - Ephy, MsgId %d is disabled.", __FUNCTION__, IntId); -} - -static bool fxgmac_enable_mgm_interrupt(struct fxgmac_pdata* pdata) -{ - writereg(pdata->pAdapter, 0xf0000000, pdata->base_mem + MGMT_INT_CTRL0); - return true; -} - -static bool fxgmac_disable_mgm_interrupt(struct fxgmac_pdata* pdata) -{ - writereg(pdata->pAdapter, 0xffff0000, pdata->base_mem + MGMT_INT_CTRL0); - return true; -} - -static int fxgmac_flush_tx_queues(struct fxgmac_pdata *pdata) -{ - unsigned int i, count; - u32 regval; - - for (i = 0; i < pdata->tx_q_count; i++) { - regval = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); - regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_FTQ_POS, - MTL_Q_TQOMR_FTQ_LEN, 1); - writereg(pdata->pAdapter, regval, FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); - DPRINTK("fxgmac_flush_tx_queues, reg=0x%p, val=0x%08x\n", FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR), regval); - } - - //2022-04-20 xiaojiang comment - //the following windows implement has some unreasonable part - //Take Linux implement method instead - /* Poll Until Poll Condition */ - /*for (i = 0; i < pdata->tx_q_count; i++) { - count = 2000; - regval = readreg(FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); - regval = FXGMAC_GET_REG_BITS(regval, MTL_Q_TQOMR_FTQ_POS, - MTL_Q_TQOMR_FTQ_LEN); - while (--count && regval) { - usleep_range(pdata->pAdapter, 500, 600); - } - - DPRINTK("fxgmac_flush_tx_queues wait... reg=0x%p, val=0x%08x\n", FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR), regval); - - if (!count) - return -EBUSY; - }*/ - for (i = 0; i < pdata->tx_q_count; i++) { - count = 2000; - //regval = 1; //reset is not cleared.... - do { - usleep_range_ex(pdata->pAdapter, 40, 50); - regval = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); - regval = FXGMAC_GET_REG_BITS(regval, MTL_Q_TQOMR_FTQ_POS, - MTL_Q_TQOMR_FTQ_LEN); - - } while (--count && regval); - DPRINTK("fxgmac_flush_tx_queues wait... reg=0x%p, val=0x%08x\n", FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR), regval); - if (regval) {/*(!count)*/ - return -EBUSY; - } - } - - return 0; -} - -static void fxgmac_config_dma_bus(struct fxgmac_pdata *pdata) -{ - u32 regval; -#if 1//set no fix burst length - regval = readreg(pdata->pAdapter, pdata->mac_regs + DMA_SBMR); - /* Set enhanced addressing mode */ - regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_EAME_POS, - DMA_SBMR_EAME_LEN, 1); - /* Set the System Bus mode */ - regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_FB_POS, - DMA_SBMR_FB_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_BLEN_4_POS, - DMA_SBMR_BLEN_4_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_BLEN_8_POS, - DMA_SBMR_BLEN_8_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_BLEN_16_POS, - DMA_SBMR_BLEN_16_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_BLEN_32_POS, - DMA_SBMR_BLEN_32_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + DMA_SBMR); - -#else - regval = readreg(pdata->mac_regs + DMA_SBMR); - /* Set enhanced addressing mode */ - regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_EAME_POS, - DMA_SBMR_EAME_LEN, 1); - /* Set the System Bus mode */ - regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_FB_POS, - DMA_SBMR_FB_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_BLEN_256_POS, - DMA_SBMR_BLEN_256_LEN, 1); - writereg(regval, pdata->mac_regs + DMA_SBMR); -#endif -} - -static void fxgmac_legacy_link_speed_setting(struct fxgmac_pdata* pdata) -{ - unsigned int i = 0, regval = 0; - - fxgmac_phy_config(pdata); - for (i = 0, regval = fxgmac_get_ephy_state(pdata); - (!(regval & MGMT_EPHY_CTRL_STA_EPHY_RELEASE) || !(regval & MGMT_EPHY_CTRL_STA_EPHY_LINKUP)) && (i < PHY_LINK_TIMEOUT); - regval = fxgmac_get_ephy_state(pdata), i++) - { - usleep_range_ex(pdata->pAdapter, 2000, 2000); - } - fxgmac_read_ephy_reg(pdata, REG_MII_INT_STATUS, NULL); // clear phy interrupt. -} - -static void fxgmac_pre_powerdown(struct fxgmac_pdata* pdata, bool phyloopback) -{ - unsigned int regval = 0; - - fxgmac_disable_rx(pdata); - - /* HERE, WE NEED TO CONSIDER PHY CONFIG...TBD */ - DPRINTK("fxgmac_config_powerdown, phy and mac status update\n"); - //2022-11-09 xiaojiang comment - //for phy cable loopback,it can't configure phy speed, it will cause os resume again by link change although it has finished speed setting, - if (!phyloopback) { - -#ifndef LINUX -#if defined(UEFI) -#elif defined(DPDK) - (void) i; -#elif defined(_WIN32) || defined(_WIN64) - LONGLONG tick_interval; - ULONG tick_inc; - LARGE_INTEGER tick_count; - unsigned int i = 0; - if ((ULONG)pdata->phy_speed != ((PMP_ADAPTER)pdata->pAdapter)->usLinkSpeed) - { - DbgPrintF(MP_TRACE, "%s change phy speed", __FUNCTION__); - - if (((PMP_ADAPTER)pdata->pAdapter)->RegParameter.LinkChgWol) - { - fxgmac_phy_config(pdata); - //sleep fixed value(6s) - for (i = 0; i < PHY_LINK_TIMEOUT; i++) - { - usleep_range_ex(pdata->pAdapter, 2000, 2000); - } - - fxgmac_read_ephy_reg(pdata, REG_MII_INT_STATUS, NULL); // clear phy interrupt. - } - else - { - regval = fxgmac_get_ephy_state(pdata); - KeQueryTickCount(&tick_count); - tick_inc = KeQueryTimeIncrement(); - tick_interval = tick_count.QuadPart - ((PMP_ADAPTER)pdata->pAdapter)->D0_entry_tick_count.QuadPart; - tick_interval *= tick_inc; - tick_interval /= 10; - - /*DbgPrintF(MP_TRACE, "base tick %lld", ((PMP_ADAPTER)pdata->pAdapter)->D0_entry_tick_count.QuadPart); - DbgPrintF(MP_TRACE, "current tick %lld", tick_count.QuadPart); - DbgPrintF(MP_TRACE, "tick inc is %u", tick_inc); - DbgPrintF(MP_TRACE, "tick_interval is %lld", tick_interval);*/ - if (((regval & MGMT_EPHY_CTRL_STA_EPHY_RELEASE) && (regval & MGMT_EPHY_CTRL_STA_EPHY_LINKUP)) - || ((regval & MGMT_EPHY_CTRL_STA_EPHY_RELEASE) && !(regval & MGMT_EPHY_CTRL_STA_EPHY_LINKUP) && (tick_interval < RESUME_MAX_TIME) && (MediaConnectStateConnected == ((PMP_ADAPTER)pdata->pAdapter)->PreMediaState)) - ) - { - fxgmac_legacy_link_speed_setting(pdata); - } - } - } -#else -#endif -#endif - - /* - When the Linux platform enters the s4 state, it goes through the suspend->resume->suspend process. - The process of suspending again after resume is fast, and PHY auto-negotiation is not yet complete, - so the auto-negotiation of PHY must be carried out again.Windows platforms and UEFI platforms do - not need to auto-negotiate again, as they will not have such a process. - - When the Linux platform enters the s4 state, force speed to 10M. - */ -#ifdef UEFI - fxgmac_legacy_link_speed_setting(pdata); -#elif defined(_WIN32) || defined(_WIN64) - -#elif defined(LINUX) - pdata->phy_speed = SPEED_10; - fxgmac_legacy_link_speed_setting(pdata); -#else - fxgmac_legacy_link_speed_setting(pdata); -#endif - } - - fxgmac_config_mac_speed(pdata); - - /* After enable OOB_WOL from efuse, mac will loopcheck phy status, and lead to panic sometimes. - So we should disable it from powerup, enable it from power down.*/ - regval = (u32)readreg(pdata->pAdapter, pdata->base_mem + OOB_WOL_CTRL); - regval = FXGMAC_SET_REG_BITS(regval, OOB_WOL_CTRL_DIS_POS, OOB_WOL_CTRL_DIS_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->base_mem + OOB_WOL_CTRL); - usleep_range_ex(pdata->pAdapter, 2000, 2000); - - //after enable OOB_WOL,recofigure mac addr again - fxgmac_set_mac_address(pdata, pdata->mac_addr); - //fxgmac_suspend_clock_gate(pdata); -} - -#if defined(LINUX) -// only supports four patterns, and patterns will be cleared on every call -static void fxgmac_set_pattern_data(struct fxgmac_pdata *pdata) -{ - u32 ip_addr, i = 0; - u8 type_offset, op_offset, tip_offset; - struct pattern_packet packet; - struct wol_bitmap_pattern pattern[4]; // for WAKE_UCAST, WAKE_BCAST, WAKE_MCAST, WAKE_ARP. - - memset(pattern, 0, sizeof(struct wol_bitmap_pattern) * 4); - - //config ucast - if (pdata->expansion.wol & WAKE_UCAST) { - pattern[i].mask_info[0] = 0x3F; - pattern[i].mask_size = sizeof(pattern[0].mask_info); - memcpy(pattern[i].pattern_info, pdata->mac_addr, ETH_ALEN); - pattern[i].pattern_offset = 0; - i++; - } - - // config bcast - if (pdata->expansion.wol & WAKE_BCAST) { - pattern[i].mask_info[0] = 0x3F; - pattern[i].mask_size = sizeof(pattern[0].mask_info); - memset(pattern[i].pattern_info, 0xFF, ETH_ALEN); - pattern[i].pattern_offset = 0; - i++; - } - - // config mcast - if (pdata->expansion.wol & WAKE_MCAST) { - pattern[i].mask_info[0] = 0x7; - pattern[i].mask_size = sizeof(pattern[0].mask_info); - pattern[i].pattern_info[0] = 0x1; - pattern[i].pattern_info[1] = 0x0; - pattern[i].pattern_info[2] = 0x5E; - pattern[i].pattern_offset = 0; - i++; - } - - // config arp - if (pdata->expansion.wol & WAKE_ARP) { - memset(pattern[i].mask_info, 0, sizeof(pattern[0].mask_info)); - type_offset = offsetof(struct pattern_packet, ar_pro); - pattern[i].mask_info[type_offset / 8] |= 1 << type_offset % 8; - type_offset++; - pattern[i].mask_info[type_offset / 8] |= 1 << type_offset % 8; - op_offset = offsetof(struct pattern_packet, ar_op); - pattern[i].mask_info[op_offset / 8] |= 1 << op_offset % 8; - op_offset++; - pattern[i].mask_info[op_offset / 8] |= 1 << op_offset % 8; - tip_offset = offsetof(struct pattern_packet, ar_tip); - pattern[i].mask_info[tip_offset / 8] |= 1 << tip_offset % 8; - tip_offset++; - pattern[i].mask_info[tip_offset / 8] |= 1 << type_offset % 8; - tip_offset++; - pattern[i].mask_info[tip_offset / 8] |= 1 << type_offset % 8; - tip_offset++; - pattern[i].mask_info[tip_offset / 8] |= 1 << type_offset % 8; - - packet.ar_pro = 0x0 << 8 | 0x08; // arp type is 0x0800, notice that ar_pro and ar_op is big endian - packet.ar_op = 0x1 << 8; // 1 is arp request,2 is arp replay, 3 is rarp request, 4 is rarp replay - ip_addr = fxgmac_get_netdev_ip4addr(pdata); - packet.ar_tip[0] = ip_addr & 0xFF; - packet.ar_tip[1] = (ip_addr >> 8) & 0xFF; - packet.ar_tip[2] = (ip_addr >> 16) & 0xFF; - packet.ar_tip[3] = (ip_addr >> 24) & 0xFF; - memcpy(pattern[i].pattern_info, &packet, MAX_PATTERN_SIZE); - pattern[i].mask_size = sizeof(pattern[0].mask_info); - pattern[i].pattern_offset = 0; - i++; - } - - fxgmac_set_wake_pattern(pdata, pattern, i); -} - -static void fxgmac_config_powerdown(struct fxgmac_pdata *pdata, unsigned int wol) -#else -static void fxgmac_config_powerdown(struct fxgmac_pdata* pdata, unsigned int offloadcount, bool magic_en, bool remote_pattern_en) -#endif -{ - u32 regval = 0; - - fxgmac_disable_tx(pdata); - fxgmac_disable_rx(pdata); - - /* performs fxgmac power down sequence - * 1. set led - * 2. check wol. - * 3. check arp offloading - * 4. disable gmac rx - * 5. set gmac power down - */ - - //Close LED when entering the S3,S4,S5 except solution3 - fxgmac_efuse_read_data(pdata, EFUSE_LED_ADDR, ®val); - //led index use bit0~bit5 - regval = FXGMAC_GET_REG_BITS(regval, EFUSE_LED_POS, EFUSE_LED_LEN); - if (EFUSE_LED_COMMON_SOLUTION != regval) { - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED0_CFG); - if (EFUSE_LED_SOLUTION3 == regval) { - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, REG_MII_EXT_COMMON_LED0_CFG_VALUE_SLEEP_SOLUTION3); - } - else { - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, 0x00); - } - - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED1_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, 0x00); - - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_COMMON_LED2_CFG); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, 0x00); - } - -#if defined(LINUX) - if(!test_bit(FXGMAC_POWER_STATE_DOWN, &pdata->expansion.powerstate)) { - netdev_err(pdata->netdev, - "fxgmac powerstate is %lu when config power to down.\n", pdata->expansion.powerstate); - } - -#if FXGMAC_WOL_FEATURE_ENABLED - fxgmac_config_wol(pdata, wol); -#endif -#if FXGMAC_AOE_FEATURE_ENABLED - /* use default arp offloading feature */ - fxgmac_update_aoe_ipv4addr(pdata, (u8 *)NULL); - fxgmac_enable_arp_offload(pdata); -#endif - -#if FXGMAC_NS_OFFLOAD_ENABLED - /* pls do not change the seq below */ - fxgmac_update_ns_offload_ipv6addr(pdata, FXGMAC_NS_IFA_GLOBAL_UNICAST); - fxgmac_update_ns_offload_ipv6addr(pdata, FXGMAC_NS_IFA_LOCAL_LINK); - fxgmac_enable_ns_offload(pdata); -#endif -#endif // LINUX. - -#if defined(_WIN32) || defined(_WIN64) - fxgmac_enable_wake_packet_indication(pdata, 1); -#endif - /* Enable MAC Rx TX */ -#if defined(LINUX) - if (1) { -#else - if (magic_en || remote_pattern_en || offloadcount) { -#endif - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_RE_POS, MAC_CR_RE_LEN, 1); -#if defined(LINUX) - if(pdata->hw_feat.aoe) { -#else - if (offloadcount) { -#endif - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_TE_POS, MAC_CR_TE_LEN, 1); - } - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); - } - - /* Enable fast link mode. - ECO to fix it.*/ -#if 0 - cfg_r32(pdata, REG_POWER_EIOS, ®val); - regval = FXGMAC_SET_REG_BITS(regval, POWER_EIOS_POS, POWER_EIOS_LEN, 1); - cfg_w32(pdata, REG_POWER_EIOS, regval); -#endif - - regval = readreg(pdata->pAdapter, pdata->base_mem + LPW_CTRL); - regval = FXGMAC_SET_REG_BITS(regval, LPW_CTRL_ASPM_LPW_EN_POS, LPW_CTRL_ASPM_LPW_EN_LEN, 1); // Enable PCIE PM_L23. -#if 0 - regval = FXGMAC_SET_REG_BITS(regval, LPW_CTRL_ASPM_L0S_EN_POS, LPW_CTRL_ASPM_L0S_EN_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, LPW_CTRL_ASPM_L1_EN_POS, LPW_CTRL_ASPM_L1_EN_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, LPW_CTRL_L1SS_EN_POS, LPW_CTRL_L1SS_EN_LEN, 0); -#endif - writereg(pdata->pAdapter, regval, pdata->base_mem + LPW_CTRL); - - /* set gmac power down */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); - regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_PWRDWN_POS, MAC_PMT_STA_PWRDWN_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PMT_STA); - -#ifdef LINUX - /*adjust sigdet threshold*/ - //redmine.motor-comm.com/issues/5093 - // fix issue can not wake up os on some FT-D2000 platform, this modification is only temporary - // if it is 55mv, wol maybe failed. - - regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_SIGDET); - regval = FXGMAC_SET_REG_BITS(regval, MGMT_SIGDET_POS, MGMT_SIGDET_LEN, MGMT_SIGDET_40MV); - writereg(pdata->pAdapter, regval, pdata->base_mem + MGMT_SIGDET); -#endif - DPRINTK("fxgmac_config_powerdown callout, reg=0x%08x\n", regval); -} - -static void fxgmac_config_powerup(struct fxgmac_pdata* pdata) -{ - u32 regval = 0; - -#if defined(LINUX) - if (test_bit(FXGMAC_POWER_STATE_DOWN, &pdata->expansion.powerstate)) { - netdev_err(pdata->netdev, "fxgmac powerstate is %lu when config power to up.\n", pdata->expansion.powerstate); - } -#endif - - /* After enable OOB_WOL from efuse, mac will loopcheck phy status, and lead to panic sometimes. - So we should disable it from powerup, enable it from power down.*/ - regval = (u32)readreg(pdata->pAdapter, pdata->base_mem + OOB_WOL_CTRL); - regval = FXGMAC_SET_REG_BITS(regval, OOB_WOL_CTRL_DIS_POS, OOB_WOL_CTRL_DIS_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->base_mem + OOB_WOL_CTRL); - - /* clear wpi mode whether or not waked by WOL, write reset value */ - regval = (u32)readreg(pdata->pAdapter, pdata->base_mem + MGMT_WPI_CTRL0); - - regval = FXGMAC_SET_REG_BITS(regval, - MGMT_WPI_CTRL0_WPI_MODE_POS, - MGMT_WPI_CTRL0_WPI_MODE_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->base_mem + MGMT_WPI_CTRL0); - /* read pmt_status register to De-assert the pmt_intr_o */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); - /* wether or not waked up by WOL, write reset value */ - regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_PWRDWN_POS, MAC_PMT_STA_PWRDWN_LEN, 0); - /* write register to synchronized always-on block */ - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PMT_STA); - - /* Disable fast link mode*/ - cfg_r32(pdata, REG_POWER_EIOS, ®val); - regval = FXGMAC_SET_REG_BITS(regval, POWER_EIOS_POS, POWER_EIOS_LEN, 0); - cfg_w32(pdata, REG_POWER_EIOS, regval); - - fxgmac_pwr_clock_gate(pdata); -} - -#if FXGMAC_SANITY_CHECK_ENABLED -/* - * fxgmac_diag_sanity_check - * check if there is any error like tx q hang - * return: 0 normal and other fatal error - */ -static int fxgmac_diag_sanity_check(struct fxgmac_pdata *pdata) -{ - u32 reg_q_val, reg_tail_val; - static u32 reg_tail_pre = 0; - static int cnt = 0; - - reg_q_val = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, 0/* tx channe 0 */, 0x8/* 0x2d08 */)); - if (!(reg_q_val & 0x10)) { //tx q is empty - return 0; - } - reg_tail_val = readreg(pdata->pAdapter, FXGMAC_DMA_REG(pdata->channel_head, DMA_CH_TDTR_LO)); - if(reg_tail_pre != reg_tail_val) { - reg_tail_pre = reg_tail_val; - cnt = 0; - } else { - cnt++; - } - - if(cnt > 10) { - reg_q_val = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, 0/* tx channe 0 */, 0x8/* 0x2d08 */)); - if(reg_q_val & 0x10) { //double check - DPRINTK("fxgmac, WARNing, tx Q status is 0x%x and tail keeps unchanged for %d times, 0x%x\n", reg_q_val, cnt, reg_tail_val); - return 1; - } - } - - return 0; -} -#endif -static void fxgmac_pwr_clock_gate(struct fxgmac_pdata* pdata) -{ - u32 regval = 0; - - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_SLEEP_CONTROL1); - fxgmac_read_ephy_reg(pdata, REG_MII_EXT_DATA, ®val); - // close pll in sleep mode - regval = FXGMAC_SET_REG_BITS(regval, MII_EXT_SLEEP_CONTROL1_PLLON_IN_SLP_POS, - MII_EXT_SLEEP_CONTROL1_PLLON_IN_SLP_LEN, 0); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, regval); - - /*regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_XST_OSC_CTRL); - regval = FXGMAC_SET_REG_BITS(regval, MGMT_XST_OSC_CTRL_XST_OSC_SEL_POS, - MGMT_XST_OSC_CTRL_XST_OSC_SEL_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->base_mem + MGMT_XST_OSC_CTRL); - regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_XST_OSC_CTRL); - regval = FXGMAC_SET_REG_BITS(regval, MGMT_XST_OSC_CTRL_EN_XST_POS, - MGMT_XST_OSC_CTRL_EN_XST_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->base_mem + MGMT_XST_OSC_CTRL);*/ -} -static void fxgmac_pwr_clock_ungate(struct fxgmac_pdata* pdata) -{ - u32 regval = 0; - - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_SLEEP_CONTROL1); - fxgmac_read_ephy_reg(pdata, REG_MII_EXT_DATA, ®val); - // keep pll in sleep mode - regval = FXGMAC_SET_REG_BITS(regval, MII_EXT_SLEEP_CONTROL1_PLLON_IN_SLP_POS, - MII_EXT_SLEEP_CONTROL1_PLLON_IN_SLP_LEN, 1); - fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, regval); - - /*regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_XST_OSC_CTRL); - regval = FXGMAC_SET_REG_BITS(regval, MGMT_XST_OSC_CTRL_EN_XST_POS, - MGMT_XST_OSC_CTRL_EN_XST_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->base_mem + MGMT_XST_OSC_CTRL); - regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_XST_OSC_CTRL); - regval = FXGMAC_SET_REG_BITS(regval, MGMT_XST_OSC_CTRL_XST_OSC_SEL_POS, - MGMT_XST_OSC_CTRL_XST_OSC_SEL_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->base_mem + MGMT_XST_OSC_CTRL);*/ -} -static unsigned char fxgmac_suspend_int(void* context) -// context - pointer to struct nic_pdata. -{ - //ULONG_PTR addr; - u32 intid; -#if FUXI_EPHY_INTERRUPT_D0_OFF - u32 regval = 0; -#endif - u32 val_mgmt_intcrtl0; - struct fxgmac_pdata* pdata = (struct fxgmac_pdata*)context; - - val_mgmt_intcrtl0 = (u32)readreg(pdata->pAdapter, pdata->base_mem + MGMT_INT_CTRL0); - //disable management interrupts. enable only pmt interrupts. - val_mgmt_intcrtl0 = FXGMAC_SET_REG_BITS(val_mgmt_intcrtl0, MGMT_INT_CTRL0_INT_MASK_POS, - MGMT_INT_CTRL0_INT_MASK_LEN, - MGMT_INT_CTRL0_INT_MASK_EX_PMT); - writereg(pdata->pAdapter, val_mgmt_intcrtl0, pdata->base_mem + MGMT_INT_CTRL0); - - for (intid = 0; intid < MSIX_TBL_MAX_NUM; intid++) { // disable all msix - writereg(pdata->pAdapter, 0x1, pdata->base_mem + MSIX_TBL_BASE_ADDR + MSIX_TBL_MASK_OFFSET + intid * 16); - } - - //enable pmt msix - writereg(pdata->pAdapter, 0x0, pdata->base_mem + MSIX_TBL_BASE_ADDR + MSIX_TBL_MASK_OFFSET + MSI_ID_PHY_OTHER * 16); - readreg(pdata->pAdapter, pdata->base_mem + MGMT_WOL_CTRL);// read clear wake up reason - //since Msix interrupt masked now, enable EPHY interrupt for case of link change wakeup - fxgmac_read_ephy_reg(pdata, REG_MII_INT_STATUS, NULL); // clear phy interrupt -#if FUXI_EPHY_INTERRUPT_D0_OFF - regval = FXGMAC_SET_REG_BITS(0, PHY_INT_MASK_LINK_UP_POS, PHY_INT_MASK_LINK_UP_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, PHY_INT_MASK_LINK_DOWN_POS, PHY_INT_MASK_LINK_DOWN_LEN, 1); - fxgmac_write_ephy_reg(pdata, REG_MII_INT_MASK, regval);//enable phy interrupt -#endif - - return true; -} -static int fxgmac_suspend_txrx(struct fxgmac_pdata* pdata) -{ - struct fxgmac_channel* channel; - unsigned int i; - u32 regval; - int busy = 15; - /* Prepare for Tx DMA channel stop */ - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) { - break; - } - fxgmac_prepare_tx_stop(pdata, channel); - } - - /* Disable each Tx DMA channel */ - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) { - break; - } - - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_TCR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_TCR_ST_POS, - DMA_CH_TCR_ST_LEN, 0); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_TCR)); - DBGPRINT(MP_TRACE, (" %s disable tx dma", __FUNCTION__)); - } - - do { - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_DBG_STA); - busy--; - } while ((regval & MAC_DBG_STA_TX_BUSY) && (busy)); - - if (0 != (regval & MAC_DBG_STA_TX_BUSY)) { - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_DBG_STA); - DbgPrintF(MP_WARN, "warning !!!timed out waiting for Tx MAC to stop\n"); - return -1; - } - /* wait empty Tx queue */ - for (i = 0; i < pdata->tx_q_count; i++) { - do { - - regval = readreg(pdata->pAdapter, FXGMAC_MTL_REG(pdata, i, MTL_TXQ_DEG)); - busy--; - } while ((regval & MTL_TXQ_DEG_TX_BUSY) && (busy)); - if (0 != (regval & MTL_TXQ_DEG_TX_BUSY)) { - regval = readreg(pdata->pAdapter, pdata->mac_regs + MTL_TXQ_DEG); - DbgPrintF(MP_WARN, "warning !!!timed out waiting for tx queue %u to empty\n", - i); - return -1; - } - } - - /* Disable MAC TxRx */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_TE_POS, - MAC_CR_TE_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_RE_POS, - MAC_CR_RE_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); - - /* Prepare for Rx DMA channel stop */ - for (i = 0; i < pdata->rx_q_count; i++) { - fxgmac_prepare_rx_stop(pdata, i); - } - /* Disable each Rx DMA channel */ - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->rx_ring) { - break; - } - - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_RCR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_RCR_SR_POS, - DMA_CH_RCR_SR_LEN, 0); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_RCR)); - DBGPRINT(MP_TRACE, (" %s disable rx dma", __FUNCTION__)); - } - return 0; -} -static void fxgmac_resume_int(struct fxgmac_pdata* pdata) -{ - u32 intid, regval = 0; - u32 val_mgmt_intcrtl0; - - val_mgmt_intcrtl0 = (u32)readreg(pdata->pAdapter, pdata->base_mem + MGMT_INT_CTRL0); - //disable management interrupts. enable only pmt interrupts. - val_mgmt_intcrtl0 = FXGMAC_SET_REG_BITS(val_mgmt_intcrtl0, MGMT_INT_CTRL0_INT_MASK_POS, - MGMT_INT_CTRL0_INT_MASK_LEN, - MGMT_INT_CTRL0_INT_MASK_DISABLE); - writereg(pdata->pAdapter, val_mgmt_intcrtl0, pdata->base_mem + MGMT_INT_CTRL0); - - for (intid = 0; intid < MSIX_TBL_RXTX_NUM; intid++) { - writereg(pdata->pAdapter, 0, pdata->base_mem + MSIX_TBL_BASE_ADDR + MSIX_TBL_MASK_OFFSET + intid * 16); - } - - for (intid = MSIX_TBL_RXTX_NUM; intid < MSIX_TBL_MAX_NUM; intid++) { // disable some msix - writereg(pdata->pAdapter, 0, pdata->base_mem + MSIX_TBL_BASE_ADDR + MSIX_TBL_MASK_OFFSET + intid * 16); - } - -#if FUXI_EPHY_INTERRUPT_D0_OFF - fxgmac_write_ephy_reg(pdata, REG_MII_INT_MASK,0x0); //disable phy interrupt - fxgmac_read_ephy_reg(pdata, REG_MII_INT_STATUS, NULL); // clear phy interrupt -#else - //hw_ops->read_ephy_reg(pdata, REG_MII_INT_STATUS, NULL);// clear phy interrupt - regval = FXGMAC_SET_REG_BITS(0, PHY_INT_MASK_LINK_UP_POS, PHY_INT_MASK_LINK_UP_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, PHY_INT_MASK_LINK_DOWN_POS, PHY_INT_MASK_LINK_DOWN_LEN, 1); - fxgmac_write_ephy_reg(pdata, REG_MII_INT_MASK, regval);//enable phy interrupt -#endif -} - -static int fxgmac_hw_init(struct fxgmac_pdata *pdata) -{ - struct fxgmac_desc_ops *desc_ops = &pdata->desc_ops; - int ret; - u32 regval = 0; - - if (netif_msg_drv(pdata)) { DPRINTK("fxgmac hw init call in\n"); } - - /* Flush Tx queues */ - ret = fxgmac_flush_tx_queues(pdata); - if (ret) { - if (netif_msg_drv(pdata)) { DPRINTK("fxgmac_hw_init call flush tx queue err.\n"); } -#ifdef LINUX - return ret; -#endif - } - - /* Initialize DMA related features */ - fxgmac_config_dma_bus(pdata); - fxgmac_config_osp_mode(pdata); - fxgmac_config_pblx8(pdata); - fxgmac_config_tx_pbl_val(pdata); - fxgmac_config_rx_pbl_val(pdata); - fxgmac_config_rx_coalesce(pdata); - fxgmac_config_tx_coalesce(pdata); - fxgmac_config_rx_buffer_size(pdata); - fxgmac_config_tso_mode(pdata); - fxgmac_config_sph_mode(pdata); - fxgmac_config_rss(pdata); - -#ifdef LINUX - fxgmac_config_wol(pdata, pdata->expansion.wol); -#endif - - desc_ops->tx_desc_init(pdata); - desc_ops->rx_desc_init(pdata); - fxgmac_enable_dma_interrupts(pdata); - - /* Initialize MTL related features */ - fxgmac_config_mtl_mode(pdata); - fxgmac_config_queue_mapping(pdata); - fxgmac_config_tsf_mode(pdata, pdata->tx_sf_mode); - fxgmac_config_rsf_mode(pdata, pdata->rx_sf_mode); - fxgmac_config_tx_threshold(pdata, pdata->tx_threshold); - fxgmac_config_rx_threshold(pdata, pdata->rx_threshold); - fxgmac_config_tx_fifo_size(pdata); - fxgmac_config_rx_fifo_size(pdata); - fxgmac_config_flow_control_threshold(pdata); - fxgmac_config_rx_fep_disable(pdata); - fxgmac_config_rx_fup_enable(pdata); - fxgmac_enable_mtl_interrupts(pdata); - - /* Initialize MAC related features */ - fxgmac_config_mac_address(pdata); - fxgmac_config_crc_check(pdata); - fxgmac_config_rx_mode(pdata); - fxgmac_config_jumbo(pdata); - fxgmac_config_flow_control(pdata); - fxgmac_config_mac_speed(pdata); - fxgmac_config_checksum_offload(pdata); - fxgmac_config_vlan_support(pdata); - fxgmac_config_mmc(pdata); - fxgmac_enable_mac_interrupts(pdata); - - /* enable EPhy link change interrupt */ - fxgmac_read_ephy_reg(pdata, REG_MII_INT_STATUS, NULL);// clear phy interrupt - regval = FXGMAC_SET_REG_BITS(0, PHY_INT_MASK_LINK_UP_POS, PHY_INT_MASK_LINK_UP_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, PHY_INT_MASK_LINK_DOWN_POS, PHY_INT_MASK_LINK_DOWN_LEN, 1); - fxgmac_write_ephy_reg(pdata, REG_MII_INT_MASK, regval);//enable phy interrupt - - if (netif_msg_drv(pdata)) { DPRINTK("fxgmac hw init callout\n"); } - return 0; -} - -static void fxgmac_save_nonstick_reg(struct fxgmac_pdata* pdata) -{ - u32 i; - for (i = REG_PCIE_TRIGGER; i < MSI_PBA_REG; i += 4) { - pdata->reg_nonstick[(i - REG_PCIE_TRIGGER) >> 2] = readreg(pdata->pAdapter, pdata->base_mem + i); - } - -#if defined(UBOOT) - /* PCI config space info */ - dm_pci_read_config16(pdata->pdev, PCI_VENDOR_ID, &pdata->expansion.pci_venid); - dm_pci_read_config16(pdata->pdev, PCI_DEVICE_ID, &pdata->expansion.pci_devid); - dm_pci_read_config16(pdata->pdev, PCI_SUBSYSTEM_VENDOR_ID, &pdata->expansion.SubVendorID); - dm_pci_read_config16(pdata->pdev, PCI_SUBSYSTEM_ID, &pdata->expansion.SubSystemID); - - dm_pci_read_config8(pdata->pdev, PCI_REVISION_ID, &pdata->expansion.pci_revid); - //dm_pci_read_config16(pdata->pdev, PCI_COMMAND, &pdata->pci_cmd_word); - - DbgPrintF(MP_TRACE, "VenId is %x, Devid is %x, SubId is %x, SubSysId is %x, Revid is %x.\n", - pdata->expansion.pci_venid, pdata->expansion.pci_devid, pdata->expansion.SubVendorID, - pdata->expansion.SubSystemID, pdata->expansion.pci_revid); - -#elif !defined(UEFI) && !defined(PXE) && !defined(DPDK) - cfg_r32(pdata, REG_PCI_COMMAND, &pdata->expansion.cfg_pci_cmd); - cfg_r32(pdata, REG_CACHE_LINE_SIZE, &pdata->expansion.cfg_cache_line_size); - cfg_r32(pdata, REG_MEM_BASE, &pdata->expansion.cfg_mem_base); - cfg_r32(pdata, REG_MEM_BASE_HI, &pdata->expansion.cfg_mem_base_hi); - cfg_r32(pdata, REG_IO_BASE, &pdata->expansion.cfg_io_base); - cfg_r32(pdata, REG_INT_LINE, &pdata->expansion.cfg_int_line); - cfg_r32(pdata, REG_DEVICE_CTRL1, &pdata->expansion.cfg_device_ctrl1); - cfg_r32(pdata, REG_PCI_LINK_CTRL, &pdata->expansion.cfg_pci_link_ctrl); - cfg_r32(pdata, REG_DEVICE_CTRL2, &pdata->expansion.cfg_device_ctrl2); - cfg_r32(pdata, REG_MSIX_CAPABILITY, &pdata->expansion.cfg_msix_capability); - - DbgPrintF(MP_TRACE, "%s:\nCFG%02x-%02x\nCFG%02x-%02x\nCFG%02x-%02x\nCFG%02x-%02x\nCFG%02x-%02x\nCFG%02x-%02x\nCFG%02x-%02x\nCFG%02x-%02x\nCFG%02x-%02x\nCFG%02x-%02x\n", - __FUNCTION__, - REG_PCI_COMMAND, pdata->expansion.cfg_pci_cmd, - REG_CACHE_LINE_SIZE, pdata->expansion.cfg_cache_line_size, - REG_MEM_BASE, pdata->expansion.cfg_mem_base, - REG_MEM_BASE_HI, pdata->expansion.cfg_mem_base_hi, - REG_IO_BASE, pdata->expansion.cfg_io_base, - REG_INT_LINE, pdata->expansion.cfg_int_line, - REG_DEVICE_CTRL1, pdata->expansion.cfg_device_ctrl1, - REG_PCI_LINK_CTRL, pdata->expansion.cfg_pci_link_ctrl, - REG_DEVICE_CTRL2, pdata->expansion.cfg_device_ctrl2, - REG_MSIX_CAPABILITY, pdata->expansion.cfg_msix_capability); -#endif -} - -static void fxgmac_restore_nonstick_reg(struct fxgmac_pdata* pdata) -{ - u32 i; - for (i = REG_PCIE_TRIGGER; i < MSI_PBA_REG; i += 4) { - writereg(pdata->pAdapter, pdata->reg_nonstick[(i - REG_PCIE_TRIGGER) >> 2], pdata->base_mem + i); - } -} - -#if !defined(UEFI) && !defined(PXE) && !defined(DPDK) -static void fxgmac_esd_restore_pcie_cfg(struct fxgmac_pdata* pdata) -{ - cfg_w32(pdata, REG_PCI_COMMAND, pdata->expansion.cfg_pci_cmd); - cfg_w32(pdata, REG_CACHE_LINE_SIZE, pdata->expansion.cfg_cache_line_size); - cfg_w32(pdata, REG_MEM_BASE, pdata->expansion.cfg_mem_base); - cfg_w32(pdata, REG_MEM_BASE_HI, pdata->expansion.cfg_mem_base_hi); - cfg_w32(pdata, REG_IO_BASE, pdata->expansion.cfg_io_base); - cfg_w32(pdata, REG_INT_LINE, pdata->expansion.cfg_int_line); - cfg_w32(pdata, REG_DEVICE_CTRL1, pdata->expansion.cfg_device_ctrl1); - cfg_w32(pdata, REG_PCI_LINK_CTRL, pdata->expansion.cfg_pci_link_ctrl); - cfg_w32(pdata, REG_DEVICE_CTRL2, pdata->expansion.cfg_device_ctrl2); - cfg_w32(pdata, REG_MSIX_CAPABILITY, pdata->expansion.cfg_msix_capability); -} -#endif - -static int fxgmac_hw_exit(struct fxgmac_pdata *pdata) -{ - //unsigned int count = 2000; - u32 regval; - u32 value = 0; -#if 1 - cfg_r32(pdata, REG_PCI_LINK_CTRL, ®val); - pdata->pcie_link_status = FXGMAC_GET_REG_BITS(regval, PCI_LINK_CTRL_ASPM_CONTROL_POS, PCI_LINK_CTRL_ASPM_CONTROL_LEN); - if (PCI_LINK_CTRL_L1_STATUS == (pdata->pcie_link_status & 0x02)) - { - regval = FXGMAC_SET_REG_BITS(regval, PCI_LINK_CTRL_ASPM_CONTROL_POS, PCI_LINK_CTRL_ASPM_CONTROL_LEN, 0); - cfg_w32(pdata, REG_PCI_LINK_CTRL, regval); - } - - /* Issue a CHIP reset */ - regval = readreg(pdata->pAdapter, pdata->base_mem + SYS_RESET_REG); - DPRINTK("CHIP_RESET 0x%x\n", regval); - /* reg152c bit31 1->reset, self-clear, if read it again, it still set 1. */ - regval = FXGMAC_SET_REG_BITS(regval, SYS_RESET_POS, SYS_RESET_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->base_mem + SYS_RESET_REG); - - usleep_range_ex(pdata->pAdapter, 9000, 10000); //usleep_range_ex(pdata->pAdapter, 10, 15); - - /* reg152c reset will reset trigger circuit and reload efuse patch 0x1004=0x16,need to release ephy reset again */ - value = FXGMAC_SET_REG_BITS(value, MGMT_EPHY_CTRL_RESET_POS, MGMT_EPHY_CTRL_RESET_LEN, MGMT_EPHY_CTRL_STA_EPHY_RELEASE); - writereg(pdata->pAdapter, value, pdata->base_mem + MGMT_EPHY_CTRL); - usleep_range_ex(pdata->pAdapter, 100, 150); - - fxgmac_restore_nonstick_reg(pdata); // reset will clear nonstick registers. -#else - /* Issue a software reset */ - regval = readreg(pdata->pAdapter, pdata->mac_regs + DMA_MR); DPRINTK("DMA_MR 0x%x\n", regval); - regval = FXGMAC_SET_REG_BITS(regval, DMA_MR_SWR_POS, - DMA_MR_SWR_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, DMA_MR_INTM_POS, - DMA_MR_INTM_LEN, 0); - writereg(pdata->pAdapter, regval, pdata->mac_regs + DMA_MR); - - usleep_range_ex(pdata->pAdapter, 10, 15); - - /* Poll Until Poll Condition */ - while (--count && - FXGMAC_GET_REG_BITS(readreg(pdata->pAdapter, pdata->mac_regs + DMA_MR), - DMA_MR_SWR_POS, DMA_MR_SWR_LEN)) { - usleep_range_ex(pdata->pAdapter, 500, 600); - } - - DPRINTK("Soft reset count %d\n", count); - if (!count) { - return -EBUSY; - } -#endif - return 0; -} - -#if defined(UEFI) || defined(PXE) -static int fxgmac_set_gmac_register(struct fxgmac_pdata* pdata, u32 address, unsigned int data) -#else -static int fxgmac_set_gmac_register(struct fxgmac_pdata* pdata, u8* address, unsigned int data) -#endif -{ -#if defined(UEFI) || defined(PXE) - if (address < (u32)(pdata->base_mem)) -#else - if (address < (u8*)(pdata->base_mem)) -#endif - { - return -1; - } - writereg(pdata->pAdapter, data, address); - return 0; -} - -#if defined(UEFI) || defined(PXE) -static u32 fxgmac_get_gmac_register(struct fxgmac_pdata* pdata, u32 address) -#else -static u32 fxgmac_get_gmac_register(struct fxgmac_pdata* pdata, u8* address) -#endif -{ - u32 regval = 0; - -#if defined(UEFI) || defined(PXE) - if (address > (u32)(pdata->base_mem)) -#else - if (address > (u8*)(pdata->base_mem)) -#endif - { - regval = readreg(pdata->pAdapter, address); - } - return regval; -} - -static int fxgmac_pcie_init(struct fxgmac_pdata* pdata, bool ltr_en, bool aspm_l1ss_en, bool aspm_l1_en, bool aspm_l0s_en) -{ - //DbgPrintF(MP_TRACE, "%s ltr_en %d aspm_l1ss_en %d aspm_l1_en %d aspm_l0s_en %d", __FUNCTION__, ltr_en, aspm_l1ss_en, aspm_l1_en, aspm_l0s_en); - u32 regval = 0; - u32 deviceid = 0; - - cfg_r32(pdata, REG_PCI_LINK_CTRL, ®val); - if (PCI_LINK_CTRL_L1_STATUS == (pdata->pcie_link_status & 0x02) - && 0x00 == FXGMAC_GET_REG_BITS(regval, PCI_LINK_CTRL_ASPM_CONTROL_POS, PCI_LINK_CTRL_ASPM_CONTROL_LEN) - ) - { - regval = FXGMAC_SET_REG_BITS(regval, PCI_LINK_CTRL_ASPM_CONTROL_POS, PCI_LINK_CTRL_ASPM_CONTROL_LEN, pdata->pcie_link_status); - cfg_w32(pdata, REG_PCI_LINK_CTRL, regval); - } - - regval = FXGMAC_SET_REG_BITS(0, LTR_IDLE_ENTER_REQUIRE_POS, LTR_IDLE_ENTER_REQUIRE_LEN, LTR_IDLE_ENTER_REQUIRE); - regval = FXGMAC_SET_REG_BITS(regval, LTR_IDLE_ENTER_SCALE_POS, LTR_IDLE_ENTER_SCALE_LEN, LTR_IDLE_ENTER_SCALE); - regval = FXGMAC_SET_REG_BITS(regval, LTR_IDLE_ENTER_POS, LTR_IDLE_ENTER_LEN, LTR_IDLE_ENTER_USVAL); - regval = (regval << 16) + regval; /* snoopy + non-snoopy */ - writereg(pdata->pAdapter, regval, pdata->base_mem + LTR_IDLE_ENTER); - - regval = 0; - regval = FXGMAC_SET_REG_BITS(0, LTR_IDLE_EXIT_REQUIRE_POS, LTR_IDLE_EXIT_REQUIRE_LEN, LTR_IDLE_EXIT_REQUIRE); - regval = FXGMAC_SET_REG_BITS(regval, LTR_IDLE_EXIT_SCALE_POS, LTR_IDLE_EXIT_SCALE_LEN, LTR_IDLE_EXIT_SCALE); - regval = FXGMAC_SET_REG_BITS(regval, LTR_IDLE_EXIT_POS, LTR_IDLE_EXIT_LEN, LTR_IDLE_EXIT_USVAL); - regval = (regval << 16) + regval; /* snoopy + non-snoopy */ - writereg(pdata->pAdapter, regval, pdata->base_mem + LTR_IDLE_EXIT); - - regval = readreg(pdata->pAdapter, pdata->base_mem + LTR_CTRL); - if (ltr_en) { - regval = FXGMAC_SET_REG_BITS(regval, LTR_CTRL_EN_POS, LTR_CTRL_EN_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, LTR_CTRL_IDLE_THRE_TIMER_POS, LTR_CTRL_IDLE_THRE_TIMER_LEN, LTR_CTRL_IDLE_THRE_TIMER_VAL); - } else { - regval = FXGMAC_SET_REG_BITS(regval, LTR_CTRL_EN_POS, LTR_CTRL_EN_LEN, 0); - } - writereg(pdata->pAdapter, regval, pdata->base_mem + LTR_CTRL); - - regval = readreg(pdata->pAdapter, pdata->base_mem + LPW_CTRL); - regval = FXGMAC_SET_REG_BITS(regval, LPW_CTRL_ASPM_L0S_EN_POS, LPW_CTRL_ASPM_L0S_EN_LEN, aspm_l0s_en ? 1 : 0); - regval = FXGMAC_SET_REG_BITS(regval, LPW_CTRL_ASPM_L1_EN_POS, LPW_CTRL_ASPM_L1_EN_LEN, aspm_l1_en ? 1 : 0); - regval = FXGMAC_SET_REG_BITS(regval, LPW_CTRL_L1SS_EN_POS, LPW_CTRL_L1SS_EN_LEN, aspm_l1ss_en ? 1 : 0); - writereg(pdata->pAdapter, regval, pdata->base_mem + LPW_CTRL); - - cfg_r32(pdata, REG_ASPM_CONTROL, ®val); - regval = FXGMAC_SET_REG_BITS(regval, ASPM_L1_IDLE_THRESHOLD_POS, ASPM_L1_IDLE_THRESHOLD_LEN, ASPM_L1_IDLE_THRESHOLD_1US); - cfg_w32(pdata, REG_ASPM_CONTROL, regval); - - regval = 0; - regval = FXGMAC_SET_REG_BITS(regval, PCIE_SERDES_PLL_AUTOOFF_POS, PCIE_SERDES_PLL_AUTOOFF_LEN, 1); - writereg(pdata->pAdapter, regval, pdata->base_mem + REG_PCIE_SERDES_PLL); - - /*fuxi nto adjust sigdet threshold*/ - cfg_r8(pdata, REG_PCI_REVID, ®val); - cfg_r16(pdata, REG_PCI_DEVICE_ID, &deviceid); - if (FUXI_REV_01 == regval && PCI_DEVICE_ID_FUXI == deviceid) - { - regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_SIGDET); - regval = FXGMAC_SET_REG_BITS(regval, MGMT_SIGDET_POS, MGMT_SIGDET_LEN, MGMT_SIGDET_55MV); - writereg(pdata->pAdapter, regval, pdata->base_mem + MGMT_SIGDET); - } - - return 0; -} - - -static void fxgmac_trigger_pcie(struct fxgmac_pdata* pdata, u32 code) -{ - writereg(pdata->pAdapter, code, pdata->base_mem + REG_PCIE_TRIGGER); -} - -void fxgmac_init_hw_ops(struct fxgmac_hw_ops *hw_ops) -{ - hw_ops->init = fxgmac_hw_init; - hw_ops->exit = fxgmac_hw_exit; - hw_ops->save_nonstick_reg = fxgmac_save_nonstick_reg; - hw_ops->restore_nonstick_reg = fxgmac_restore_nonstick_reg; -#if !defined(UEFI) && !defined(PXE) && !defined(DPDK) - hw_ops->esd_restore_pcie_cfg = fxgmac_esd_restore_pcie_cfg; -#endif - - hw_ops->set_gmac_register = fxgmac_set_gmac_register; - hw_ops->get_gmac_register = fxgmac_get_gmac_register; - - hw_ops->tx_complete = fxgmac_tx_complete; - hw_ops->enable_tx = fxgmac_enable_tx; - hw_ops->disable_tx = fxgmac_disable_tx; - hw_ops->enable_rx = fxgmac_enable_rx; - hw_ops->disable_rx = fxgmac_disable_rx; - hw_ops->enable_channel_rx = fxgmac_enable_channel_rx; - -#ifdef LINUX - hw_ops->dev_xmit = fxgmac_dev_xmit; - hw_ops->dev_read = fxgmac_dev_read; - hw_ops->config_tso = fxgmac_config_tso_mode; -#endif - hw_ops->enable_int = fxgmac_enable_int; - hw_ops->disable_int = fxgmac_disable_int; - hw_ops->set_interrupt_moderation = fxgmac_set_interrupt_moderation; - hw_ops->enable_msix_rxtxinterrupt = fxgmac_enable_msix_rxtxinterrupt; - hw_ops->disable_msix_interrupt = fxgmac_disable_msix_interrupt; - hw_ops->enable_msix_rxtxphyinterrupt = fxgmac_enable_msix_rxtxphyinterrupt; - hw_ops->enable_msix_one_interrupt = fxgmac_enable_msix_one_interrupt; - hw_ops->disable_msix_one_interrupt = fxgmac_disable_msix_one_interrupt; - hw_ops->enable_mgm_interrupt = fxgmac_enable_mgm_interrupt; - hw_ops->disable_mgm_interrupt = fxgmac_disable_mgm_interrupt; - - hw_ops->set_mac_address = fxgmac_set_mac_address; - hw_ops->set_mac_hash = fxgmac_add_mac_addresses; - hw_ops->config_rx_mode = fxgmac_config_rx_mode; - hw_ops->enable_rx_csum = fxgmac_enable_rx_csum; - hw_ops->disable_rx_csum = fxgmac_disable_rx_csum; - - /* For MII speed configuration */ - hw_ops->config_mac_speed = fxgmac_config_mac_speed; - hw_ops->get_xlgmii_phy_status = fxgmac_check_phy_link; - - /* For descriptor related operation */ - hw_ops->tx_desc_init = fxgmac_tx_desc_init; - hw_ops->rx_desc_init = fxgmac_rx_desc_init; - hw_ops->tx_desc_reset = fxgmac_tx_desc_reset; - hw_ops->rx_desc_reset = fxgmac_rx_desc_reset; - hw_ops->is_last_desc = fxgmac_is_last_desc; - hw_ops->is_context_desc = fxgmac_is_context_desc; -#ifdef LINUX - hw_ops->tx_start_xmit = fxgmac_tx_start_xmit; - hw_ops->set_pattern_data = fxgmac_set_pattern_data; - hw_ops->config_wol = fxgmac_config_wol; - hw_ops->get_rss_hash_key = fxgmac_read_rss_hash_key; - hw_ops->write_rss_lookup_table = fxgmac_write_rss_lookup_table; -#if FXGMAC_SANITY_CHECK_ENABLED - hw_ops->diag_sanity_check = fxgmac_diag_sanity_check; -#endif -#endif - - /* For Flow Control */ - hw_ops->config_tx_flow_control = fxgmac_config_tx_flow_control; - hw_ops->config_rx_flow_control = fxgmac_config_rx_flow_control; - - /*For Jumbo Frames*/ - hw_ops->enable_jumbo = fxgmac_config_jumbo; - - /* For Vlan related config */ - hw_ops->enable_tx_vlan = fxgmac_enable_tx_vlan; - hw_ops->disable_tx_vlan = fxgmac_disable_tx_vlan; - hw_ops->enable_rx_vlan_stripping = fxgmac_enable_rx_vlan_stripping; - hw_ops->disable_rx_vlan_stripping = fxgmac_disable_rx_vlan_stripping; - hw_ops->enable_rx_vlan_filtering = fxgmac_enable_rx_vlan_filtering; - hw_ops->disable_rx_vlan_filtering = fxgmac_disable_rx_vlan_filtering; - hw_ops->update_vlan_hash_table = fxgmac_update_vlan_hash_table; - - /* For RX coalescing */ - hw_ops->config_rx_coalesce = fxgmac_config_rx_coalesce; - hw_ops->config_tx_coalesce = fxgmac_config_tx_coalesce; - hw_ops->usec_to_riwt = fxgmac_usec_to_riwt; - hw_ops->riwt_to_usec = fxgmac_riwt_to_usec; - - /* For RX and TX threshold config */ - hw_ops->config_rx_threshold = fxgmac_config_rx_threshold; - hw_ops->config_tx_threshold = fxgmac_config_tx_threshold; - - /* For RX and TX Store and Forward Mode config */ - hw_ops->config_rsf_mode = fxgmac_config_rsf_mode; - hw_ops->config_tsf_mode = fxgmac_config_tsf_mode; - - /* For TX DMA Operating on Second Frame config */ - hw_ops->config_osp_mode = fxgmac_config_osp_mode; - - /* For RX and TX PBL config */ - hw_ops->config_rx_pbl_val = fxgmac_config_rx_pbl_val; - hw_ops->get_rx_pbl_val = fxgmac_get_rx_pbl_val; - hw_ops->config_tx_pbl_val = fxgmac_config_tx_pbl_val; - hw_ops->get_tx_pbl_val = fxgmac_get_tx_pbl_val; - hw_ops->config_pblx8 = fxgmac_config_pblx8; - - /* For MMC statistics support */ - hw_ops->tx_mmc_int = fxgmac_tx_mmc_int; - hw_ops->rx_mmc_int = fxgmac_rx_mmc_int; - hw_ops->read_mmc_stats = fxgmac_read_mmc_stats; -#if defined(UEFI) -#elif defined(_WIN32) || defined(_WIN64) - hw_ops->update_stats_counters = fxgmac_update_stats_counters; -#endif - - /* For Receive Side Scaling */ - hw_ops->enable_rss = fxgmac_enable_rss; - hw_ops->disable_rss = fxgmac_disable_rss; - hw_ops->get_rss_options = fxgmac_read_rss_options; - hw_ops->set_rss_options = fxgmac_write_rss_options; - hw_ops->set_rss_hash_key = fxgmac_set_rss_hash_key; - hw_ops->set_rss_lookup_table = fxgmac_set_rss_lookup_table; - - /*For Offload*/ -#if defined(LINUX) || defined(_WIN64) || defined(_WIN32) - hw_ops->set_arp_offload = fxgmac_update_aoe_ipv4addr; - hw_ops->enable_arp_offload = fxgmac_enable_arp_offload; - hw_ops->disable_arp_offload = fxgmac_disable_arp_offload; - - hw_ops->set_ns_offload = fxgmac_set_ns_offload; - hw_ops->enable_ns_offload = fxgmac_enable_ns_offload; - hw_ops->disable_ns_offload = fxgmac_disable_ns_offload; - - hw_ops->enable_wake_magic_pattern = fxgmac_enable_wake_magic_pattern; - hw_ops->disable_wake_magic_pattern = fxgmac_disable_wake_magic_pattern; - - hw_ops->enable_wake_link_change = fxgmac_enable_wake_link_change; - hw_ops->disable_wake_link_change = fxgmac_disable_wake_link_change; - - hw_ops->check_wake_pattern_fifo_pointer = fxgmac_check_wake_pattern_fifo_pointer; - hw_ops->set_wake_pattern = fxgmac_set_wake_pattern; - hw_ops->enable_wake_pattern = fxgmac_enable_wake_pattern; - hw_ops->disable_wake_pattern = fxgmac_disable_wake_pattern; - hw_ops->set_wake_pattern_mask = fxgmac_set_wake_pattern_mask; -#if defined(FUXI_PM_WPI_READ_FEATURE_EN) && FUXI_PM_WPI_READ_FEATURE_EN - hw_ops->enable_wake_packet_indication = fxgmac_enable_wake_packet_indication; - hw_ops->get_wake_packet_indication = fxgmac_get_wake_packet_indication; -#endif -#endif - - /*For phy write /read*/ - hw_ops->reset_phy = fxgmac_reset_phy; - hw_ops->release_phy = fxgmac_release_phy; - hw_ops->get_ephy_state = fxgmac_get_ephy_state; - hw_ops->write_ephy_reg = fxgmac_write_ephy_reg; - hw_ops->read_ephy_reg = fxgmac_read_ephy_reg; - hw_ops->set_ephy_autoneg_advertise = fxgmac_set_ephy_autoneg_advertise; - hw_ops->phy_config = fxgmac_phy_config; - hw_ops->close_phy_led = fxgmac_close_phy_led; - hw_ops->led_under_active = fxmgac_config_led_under_active; - hw_ops->led_under_sleep = fxgmac_config_led_under_sleep; - hw_ops->led_under_shutdown = fxgmac_config_led_under_shutdown; - hw_ops->led_under_disable = fxgmac_config_led_under_disable; -#if !defined(UEFI) - hw_ops->enable_phy_check = fxgmac_enable_phy_check; - hw_ops->disable_phy_check = fxgmac_disable_phy_check; - hw_ops->setup_cable_loopback = fxgmac_setup_cable_loopback; - hw_ops->clean_cable_loopback = fxgmac_clean_cable_loopback; - hw_ops->disable_phy_sleep = fxgmac_disable_phy_sleep; - hw_ops->enable_phy_sleep = fxgmac_enable_phy_sleep; - hw_ops->phy_green_ethernet = fxgmac_phy_green_ethernet; - hw_ops->phy_eee_feature = fxgmac_phy_eee_feature; -#endif - - /* For power management */ - hw_ops->pre_power_down = fxgmac_pre_powerdown; - hw_ops->config_power_down = fxgmac_config_powerdown; - hw_ops->config_power_up = fxgmac_config_powerup; - hw_ops->set_suspend_int = fxgmac_suspend_int; - hw_ops->set_resume_int = fxgmac_resume_int; - hw_ops->set_suspend_txrx = fxgmac_suspend_txrx; - hw_ops->set_pwr_clock_gate = fxgmac_pwr_clock_gate; - hw_ops->set_pwr_clock_ungate = fxgmac_pwr_clock_ungate; - - hw_ops->set_all_multicast_mode = fxgmac_set_all_multicast_mode; - hw_ops->config_multicast_mac_hash_table = fxgmac_config_multicast_mac_hash_table; - hw_ops->set_promiscuous_mode = fxgmac_set_promiscuous_mode; - hw_ops->enable_rx_broadcast = fxgmac_enable_rx_broadcast; - - /* efuse relevant operation. */ - hw_ops->read_patch_from_efuse = fxgmac_read_patch_from_efuse; /* read patch per register. */ - hw_ops->read_patch_from_efuse_per_index = fxgmac_read_patch_from_efuse_per_index; /* read patch per index. */ - hw_ops->write_patch_to_efuse = fxgmac_write_patch_to_efuse; - hw_ops->write_patch_to_efuse_per_index = fxgmac_write_patch_to_efuse_per_index; - hw_ops->read_mac_subsys_from_efuse = fxgmac_read_mac_subsys_from_efuse; - hw_ops->write_mac_subsys_to_efuse = fxgmac_write_mac_subsys_to_efuse; - hw_ops->efuse_load = fxgmac_efuse_load; - hw_ops->read_efuse_data = fxgmac_efuse_read_data; - hw_ops->write_oob = fxgmac_efuse_write_oob; - hw_ops->write_led = fxgmac_efuse_write_led; - hw_ops->write_led_config = fxgmac_write_led_setting_to_efuse; - hw_ops->read_led_config = fxgmac_read_led_setting_from_efuse; - - /* */ - hw_ops->pcie_init = fxgmac_pcie_init; - hw_ops->trigger_pcie = fxgmac_trigger_pcie; -} diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-net.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-net.c deleted file mode 100644 index 905bb997a2abf..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-net.c +++ /dev/null @@ -1,2366 +0,0 @@ -/*++ - -Copyright (c) 2021 Motor-comm Corporation. -Confidential and Proprietary. All rights reserved. - -This is Motor-comm Corporation NIC driver relevant files. Please don't copy, modify, -distribute without commercial permission. - ---*/ - - -#include -#include -#include -#include -#include -#include - -#include "fuxi-gmac.h" -#include "fuxi-gmac-reg.h" - - -static int fxgmac_one_poll_rx(struct napi_struct *, int); -static int fxgmac_one_poll_tx(struct napi_struct *, int); -static int fxgmac_all_poll(struct napi_struct *, int); - -unsigned int fxgmac_get_netdev_ip4addr(struct fxgmac_pdata *pdata) -{ - struct net_device *netdev = pdata->netdev; - struct in_ifaddr *ifa; - unsigned int ipval = 0xc0a801ca; //here just hard code to 192.168.1.202 - - rcu_read_lock(); - /* we only get the first IPv4 addr. */ - ifa = rcu_dereference(netdev->ip_ptr->ifa_list); - if(ifa) { - /* binary ipv4 addr with __be */ - ipval = (unsigned int)ifa->ifa_address; - - DPRINTK("%s, netdev %s IPv4 address %pI4, mask: %pI4\n",__FUNCTION__, ifa->ifa_label, &ifa->ifa_address, &ifa->ifa_mask); - } - // ifa = rcu_dereference(ifa->ifa_next); // more ipv4 addr - rcu_read_unlock(); - - return ipval; -} - -unsigned char * fxgmac_get_netdev_ip6addr(struct fxgmac_pdata *pdata, unsigned char *ipval, unsigned char *ip6addr_solicited, unsigned int ifa_flag) -{ - struct net_device *netdev = pdata->netdev; - struct inet6_dev *i6dev; - struct inet6_ifaddr *ifp; - unsigned char local_ipval[16] = {0}; - unsigned char solicited_ipval[16] = {0}; - struct in6_addr *addr_ip6 = (struct in6_addr *)local_ipval; - struct in6_addr *addr_ip6_solicited = (struct in6_addr *)solicited_ipval; - int err = -EADDRNOTAVAIL; - - //in6_pton("fe80::35c6:dd1b:9745:fc9b", -1, (u8*)ipval, -1, NULL); //here just hard code for default - if(ipval) { - addr_ip6 = (struct in6_addr *)ipval; - } - - if(ip6addr_solicited) { - addr_ip6_solicited = (struct in6_addr *)ip6addr_solicited; - } - - in6_pton("fe80::4808:8ffb:d93e:d753", -1, (u8*)addr_ip6, -1, NULL); //here just hard code for default - - if (ifa_flag & FXGMAC_NS_IFA_GLOBAL_UNICAST) - DPRINTK ("%s FXGMAC_NS_IFA_GLOBAL_UNICAST is set, %x\n", __FUNCTION__, ifa_flag); - - if (ifa_flag & FXGMAC_NS_IFA_LOCAL_LINK) - DPRINTK ("%s FXGMAC_NS_IFA_LOCAL_LINK is set, %x\n", __FUNCTION__, ifa_flag); - - rcu_read_lock(); - i6dev = __in6_dev_get(netdev); - if (i6dev != NULL) { - read_lock_bh(&i6dev->lock); - list_for_each_entry(ifp, &i6dev->addr_list, if_list) { - - /* here we need only the ll addr, use scope to filter out it. */ - if (((ifa_flag & FXGMAC_NS_IFA_GLOBAL_UNICAST) && (ifp->scope != IFA_LINK)) || ((ifa_flag & FXGMAC_NS_IFA_LOCAL_LINK) && (ifp->scope == IFA_LINK)/* && - !(ifp->flags & IFA_F_TENTATIVE)*/)) { - - memcpy(addr_ip6, &ifp->addr, 16); - addrconf_addr_solict_mult(addr_ip6, addr_ip6_solicited); - err = 0; - - //DPRINTK("%s, netdev %s IPv6 local-link address %pI6\n",__FUNCTION__, netdev->name, addr_ip6); - //DPRINTK("%s, netdev %s IPv6 solicited-node add %pI6\n",__FUNCTION__, netdev->name, addr_ip6_solicited); - break; - } - } - read_unlock_bh(&i6dev->lock); - } - rcu_read_unlock(); - - if(err) DPRINTK("%s get ipv6 addr failed, use default.\n", __FUNCTION__); - - //DPRINTK("%s, netdev %s IPv6 local-link address %pI6\n",__FUNCTION__, netdev->name, addr_ip6); - //DPRINTK("%s, netdev %s IPv6 solicited-node adr %pI6\n",__FUNCTION__, netdev->name, addr_ip6_solicited); - - return (err ? NULL : ipval); -} - -inline unsigned int fxgmac_tx_avail_desc(struct fxgmac_ring *ring) -{ - //return (ring->dma_desc_count - (ring->cur - ring->dirty)); - unsigned int avail; - - if (ring->dirty > ring->cur) - avail = ring->dirty - ring->cur; - else - avail = ring->dma_desc_count - ring->cur + ring->dirty; - - return avail; -} - -inline unsigned int fxgmac_rx_dirty_desc(struct fxgmac_ring *ring) -{ - //return (ring->cur - ring->dirty); - unsigned int dirty; - - if (ring->dirty <= ring->cur) - dirty = ring->cur - ring->dirty; - else - dirty = ring->dma_desc_count - ring->dirty + ring->cur; - - return dirty; -} - -static int fxgmac_maybe_stop_tx_queue( - struct fxgmac_channel *channel, - struct fxgmac_ring *ring, - unsigned int count) -{ - struct fxgmac_pdata *pdata = channel->pdata; - - if (count > fxgmac_tx_avail_desc(ring)) { - netif_info(pdata, drv, pdata->netdev, - "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_ops.tx_start_xmit(channel, ring); - if(netif_msg_tx_done(pdata)) DPRINTK("about stop tx q, ret BUSY\n"); - - return NETDEV_TX_BUSY; - } - - return 0; -} - -static void fxgmac_prep_vlan(struct sk_buff *skb, - struct fxgmac_pkt_info *pkt_info) -{ - if (skb_vlan_tag_present(skb)) - pkt_info->vlan_ctag = skb_vlan_tag_get(skb); -} - -static int fxgmac_prep_tso(struct fxgmac_pdata *pdata, struct sk_buff *skb, - struct fxgmac_pkt_info *pkt_info) -{ - int ret; - - if (!FXGMAC_GET_REG_BITS(pkt_info->attributes, - TX_PACKET_ATTRIBUTES_TSO_ENABLE_POS, - TX_PACKET_ATTRIBUTES_TSO_ENABLE_LEN)) - return 0; - - ret = skb_cow_head(skb, 0); - if (ret) - return ret; - - pkt_info->header_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - pkt_info->tcp_header_len = tcp_hdrlen(skb); - pkt_info->tcp_payload_len = skb->len - pkt_info->header_len; - pkt_info->mss = skb_shinfo(skb)->gso_size; - - if(netif_msg_tx_done(pdata)){ - DPRINTK("header_len=%u\n", pkt_info->header_len); - DPRINTK("tcp_header_len=%u, tcp_payload_len=%u\n", - pkt_info->tcp_header_len, pkt_info->tcp_payload_len); - DPRINTK("mss=%u\n", pkt_info->mss); - } - /* Update the number of packets that will ultimately be transmitted - * along with the extra bytes for each extra packet - */ - pkt_info->tx_packets = skb_shinfo(skb)->gso_segs; - pkt_info->tx_bytes += (pkt_info->tx_packets - 1) * pkt_info->header_len; - - return 0; -} - -static int fxgmac_is_tso(struct sk_buff *skb) -{ - if (skb->ip_summed != CHECKSUM_PARTIAL) - return 0; - - if (!skb_is_gso(skb)) - return 0; - - return 1; -} - -static void fxgmac_prep_tx_pkt(struct fxgmac_pdata *pdata, - struct fxgmac_ring *ring, - struct sk_buff *skb, - struct fxgmac_pkt_info *pkt_info) -{ -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) ) - skb_frag_t *frag; -#else - struct skb_frag_struct *frag; -#endif - unsigned int context_desc; - unsigned int len; - unsigned int i; - - pkt_info->skb = skb; - - context_desc = 0; - pkt_info->desc_count = 0; - - pkt_info->tx_packets = 1; - pkt_info->tx_bytes = skb->len; - if(netif_msg_tx_done(pdata)) - DPRINTK ("fxgmac_prep_tx_pkt callin,pkt desc cnt=%d,skb len=%d, skbheadlen=%d\n", pkt_info->desc_count, skb->len, skb_headlen(skb)); - - if (fxgmac_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; - pkt_info->desc_count++; - } - if(netif_msg_tx_done(pdata)) - DPRINTK("fxgmac_is_tso=%d, ip_summed=%d,skb gso=%d\n",((skb->ip_summed == CHECKSUM_PARTIAL) && (skb_is_gso(skb)))?1:0, skb->ip_summed, skb_is_gso(skb)?1:0); - - /* TSO requires an extra descriptor for TSO header */ - pkt_info->desc_count++; - - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - TX_PACKET_ATTRIBUTES_TSO_ENABLE_POS, - TX_PACKET_ATTRIBUTES_TSO_ENABLE_LEN, - 1); - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - TX_PACKET_ATTRIBUTES_CSUM_ENABLE_POS, - TX_PACKET_ATTRIBUTES_CSUM_ENABLE_LEN, - 1); - if(netif_msg_tx_done(pdata)) DPRINTK ("fxgmac_prep_tx_pkt,tso, pkt desc cnt=%d\n", pkt_info->desc_count); - } else if (skb->ip_summed == CHECKSUM_PARTIAL) - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - TX_PACKET_ATTRIBUTES_CSUM_ENABLE_POS, - TX_PACKET_ATTRIBUTES_CSUM_ENABLE_LEN, - 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; - pkt_info->desc_count++; - } - - pkt_info->attributes = FXGMAC_SET_REG_BITS( - pkt_info->attributes, - TX_PACKET_ATTRIBUTES_VLAN_CTAG_POS, - TX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN, - 1); - if(netif_msg_tx_done(pdata)) DPRINTK ("fxgmac_prep_tx_pkt,VLAN, pkt desc cnt=%d,vlan=0x%04x\n", pkt_info->desc_count, skb_vlan_tag_get(skb)); - } - - for (len = skb_headlen(skb); len;) { - pkt_info->desc_count++; - len -= min_t(unsigned int, len, FXGMAC_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; ) { - pkt_info->desc_count++; - len -= min_t(unsigned int, len, FXGMAC_TX_MAX_BUF_SIZE); - } - } - if(netif_msg_tx_done(pdata)) - DPRINTK ("fxgmac_prep_tx_pkt callout,pkt desc cnt=%d,skb len=%d, skbheadlen=%d,frags=%d\n", pkt_info->desc_count, skb->len, skb_headlen(skb), skb_shinfo(skb)->nr_frags); -} - -static int fxgmac_calc_rx_buf_size(struct net_device *netdev, unsigned int mtu) -{ - unsigned int rx_buf_size; - - if (mtu > FXGMAC_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, FXGMAC_RX_MIN_BUF_SIZE, PAGE_SIZE * 4 /* follow yonggang's suggestion */); - - rx_buf_size = (rx_buf_size + FXGMAC_RX_BUF_ALIGN - 1) & - ~(FXGMAC_RX_BUF_ALIGN - 1); - - return rx_buf_size; -} - -static void fxgmac_enable_rx_tx_ints(struct fxgmac_pdata *pdata) -{ - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - struct fxgmac_channel *channel; - enum fxgmac_int int_id; - unsigned int i; - - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (channel->tx_ring && channel->rx_ring) - int_id = FXGMAC_INT_DMA_CH_SR_TI_RI; - else if (channel->tx_ring) - int_id = FXGMAC_INT_DMA_CH_SR_TI; - else if (channel->rx_ring) - int_id = FXGMAC_INT_DMA_CH_SR_RI; - else - continue; - - hw_ops->enable_int(channel, int_id); - } -} - -#if 0 -static void fxgmac_disable_rx_tx_ints(struct fxgmac_pdata *pdata) -{ - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - struct fxgmac_channel *channel; - enum fxgmac_int int_id; - unsigned int i; - - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (channel->tx_ring && channel->rx_ring) - int_id = FXGMAC_INT_DMA_CH_SR_TI_RI; - else if (channel->tx_ring) - int_id = FXGMAC_INT_DMA_CH_SR_TI; - else if (channel->rx_ring) - int_id = FXGMAC_INT_DMA_CH_SR_RI; - else - continue; - - hw_ops->disable_int(channel, int_id); - } -} -#endif - -static void fxgmac_phy_process(struct fxgmac_pdata *pdata) -{ - int cur_link = 0; - int regval = 0; - int cur_speed = 0; - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - - regval = hw_ops->get_ephy_state(pdata); - - // We should make sure that PHY is done with the reset - if (regval & MGMT_EPHY_CTRL_STA_EPHY_RESET) { - pdata->expansion.phy_link = false; - return; - } - - cur_link = FXGMAC_GET_REG_BITS(regval, - MGMT_EPHY_CTRL_STA_EPHY_LINKUP_POS, - MGMT_EPHY_CTRL_STA_EPHY_LINKUP_LEN); - if (pdata->expansion.phy_link != cur_link) { - pdata->expansion.phy_link = cur_link; - if (pdata->expansion.phy_link) { - cur_speed = FXGMAC_GET_REG_BITS(regval, - MGMT_EPHY_CTRL_STA_SPEED_POS, - MGMT_EPHY_CTRL_STA_SPEED_LEN); - pdata->phy_speed = (cur_speed == 2) ? SPEED_1000 : - (cur_speed == 1) ? SPEED_100 : SPEED_10; - pdata->phy_duplex = FXGMAC_GET_REG_BITS(regval, - MGMT_EPHY_CTRL_STA_EPHY_DUPLEX_POS, - MGMT_EPHY_CTRL_STA_EPHY_DUPLEX_LEN); - hw_ops->config_mac_speed(pdata); - - hw_ops->enable_rx(pdata); - hw_ops->enable_tx(pdata); - netif_carrier_on(pdata->netdev); - if (netif_running(pdata->netdev)) - { - netif_tx_wake_all_queues(pdata->netdev); - DPRINTK("%s now is link up, mac_speed=%d.\n", FXGMAC_DRV_NAME, - pdata->phy_speed); - } - }else { - netif_carrier_off(pdata->netdev); - netif_tx_stop_all_queues(pdata->netdev); - pdata->phy_speed = SPEED_UNKNOWN; - pdata->phy_duplex = DUPLEX_UNKNOWN; - hw_ops->disable_rx(pdata); - hw_ops->disable_tx(pdata); - DPRINTK("%s now is link down\n", FXGMAC_DRV_NAME); - } - } -} - -static int fxgmac_phy_poll(struct napi_struct *napi, int budget) -{ - struct fxgmac_pdata *pdata = container_of(napi, - struct fxgmac_pdata, - expansion.napi_phy); - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - - fxgmac_phy_process(pdata); - if (napi_complete_done(napi, 0)) - hw_ops->enable_msix_one_interrupt(pdata, MSI_ID_PHY_OTHER); - - return 0; -} - -static irqreturn_t fxgmac_phy_isr(int irq, void *data) -{ - struct fxgmac_pdata *pdata = data; - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - u32 regval; - - regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_INT_CTRL0); - if (!(regval & MGMT_INT_CTRL0_INT_STATUS_PHY)) - return IRQ_HANDLED; - - hw_ops->disable_msix_one_interrupt(pdata, MSI_ID_PHY_OTHER); - hw_ops->read_ephy_reg(pdata, REG_MII_INT_STATUS, NULL); - if (napi_schedule_prep(&pdata->expansion.napi_phy)) { - __napi_schedule_irqoff(&pdata->expansion.napi_phy); - } - - return IRQ_HANDLED; -} - -static irqreturn_t fxgmac_isr(int irq, void *data) -{ - unsigned int dma_isr, dma_ch_isr, mac_isr; - struct fxgmac_pdata *pdata = data; - struct fxgmac_channel *channel; - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - unsigned int i, ti, ri; - u32 val; - - dma_isr = readreg(pdata->pAdapter, pdata->mac_regs + DMA_ISR); - - val = readreg(pdata->pAdapter, pdata->base_mem + MGMT_INT_CTRL0); - if (!(val & MGMT_INT_CTRL0_INT_STATUS_RXTXPHY_MASK)) - return IRQ_HANDLED; - - hw_ops->disable_mgm_interrupt(pdata); - pdata->expansion.mgm_intctrl_val = val; - - pdata->stats.mgmt_int_isr++; - - for (i = 0; i < pdata->channel_count; i++) { - channel = pdata->channel_head + i; - - dma_ch_isr = readl(FXGMAC_DMA_REG(channel, DMA_CH_SR)); - netif_dbg(pdata, intr, pdata->netdev, "DMA_CH%u_ISR=%#010x\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. - */ - ti = FXGMAC_GET_REG_BITS(dma_ch_isr, DMA_CH_SR_TI_POS, - DMA_CH_SR_TI_LEN); - ri = FXGMAC_GET_REG_BITS(dma_ch_isr, DMA_CH_SR_RI_POS, - DMA_CH_SR_RI_LEN); - if (!pdata->per_channel_irq && (ti || ri)) { - if (napi_schedule_prep(&pdata->expansion.napi)) { - pdata->stats.napi_poll_isr++; - /* Turn on polling */ - __napi_schedule_irqoff(&pdata->expansion.napi); - } - } - - if (FXGMAC_GET_REG_BITS(dma_ch_isr, DMA_CH_SR_TPS_POS, - DMA_CH_SR_TPS_LEN)) - pdata->stats.tx_process_stopped++; - - if (FXGMAC_GET_REG_BITS(dma_ch_isr, DMA_CH_SR_RPS_POS, - DMA_CH_SR_RPS_LEN)) - pdata->stats.rx_process_stopped++; - - if (FXGMAC_GET_REG_BITS(dma_ch_isr, DMA_CH_SR_TBU_POS, - DMA_CH_SR_TBU_LEN)) - pdata->stats.tx_buffer_unavailable++; - - if (FXGMAC_GET_REG_BITS(dma_ch_isr, DMA_CH_SR_RBU_POS, - DMA_CH_SR_RBU_LEN)) - pdata->stats.rx_buffer_unavailable++; - - /* Restart the device on a Fatal Bus Error */ - if (FXGMAC_GET_REG_BITS(dma_ch_isr, DMA_CH_SR_FBE_POS, - DMA_CH_SR_FBE_LEN)) { - pdata->stats.fatal_bus_error++; - schedule_work(&pdata->expansion.restart_work); - } - - /* Clear all interrupt signals */ - writel(dma_ch_isr, FXGMAC_DMA_REG(channel, DMA_CH_SR)); - } - - if (FXGMAC_GET_REG_BITS(dma_isr, DMA_ISR_MACIS_POS, - DMA_ISR_MACIS_LEN)) { - mac_isr = readl(pdata->mac_regs + MAC_ISR); - - if (FXGMAC_GET_REG_BITS(mac_isr, MAC_ISR_MMCTXIS_POS, - MAC_ISR_MMCTXIS_LEN)) - hw_ops->tx_mmc_int(pdata); - - if (FXGMAC_GET_REG_BITS(mac_isr, MAC_ISR_MMCRXIS_POS, - MAC_ISR_MMCRXIS_LEN)) - hw_ops->rx_mmc_int(pdata); - - /* Clear all interrupt signals */ - writel(mac_isr, (pdata->mac_regs + MAC_ISR)); - } - - if (pdata->expansion.mgm_intctrl_val & MGMT_INT_CTRL0_INT_STATUS_PHY) { - hw_ops->read_ephy_reg(pdata, REG_MII_INT_STATUS, &val); - if (napi_schedule_prep(&pdata->expansion.napi)) { - pdata->stats.napi_poll_isr++; - /* Turn on polling */ - __napi_schedule_irqoff(&pdata->expansion.napi); - } - } - - return IRQ_HANDLED; - -} - -static irqreturn_t fxgmac_dma_isr(int irq, void *data) -{ - struct fxgmac_channel *channel = data; - struct fxgmac_pdata *pdata = channel->pdata; - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - u32 regval; - int message_id; - - if (irq == channel->expansion.dma_irq_tx) { - message_id = MSI_ID_TXQ0; - hw_ops->disable_msix_one_interrupt(pdata, message_id); - regval = 0; - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_SR_TI_POS, DMA_CH_SR_TI_LEN, 1); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_SR)); - if (napi_schedule_prep(&channel->expansion.napi_tx)) { - __napi_schedule_irqoff(&channel->expansion.napi_tx); - } - } else { - message_id = channel->queue_index; - hw_ops->disable_msix_one_interrupt(pdata, message_id); - regval = 0; - regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_SR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_SR_RI_POS, DMA_CH_SR_RI_LEN, 1); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_SR)); - if (napi_schedule_prep(&channel->expansion.napi_rx)) { - __napi_schedule_irqoff(&channel->expansion.napi_rx); - } - } - - return IRQ_HANDLED; -} - -#if 0 -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)) -static void fxgmac_tx_timer(struct timer_list *t) -#else -static void fxgmac_tx_timer(unsigned long data) -#endif -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)) - struct fxgmac_channel *channel = from_timer(channel, t, tx_timer); -#else - struct fxgmac_channel *channel = (struct fxgmac_channel *)data; -#endif - - //for msix. since this function is defined for MSIx, it is no need to brace by macro CONFIG_PCI_MSI - struct fxgmac_pdata *pdata = channel->pdata; - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - u32 regval; - - if (pdata->per_channel_irq) { - hw_ops->disable_msix_one_interrupt(pdata, MSI_ID_TXQ0); - regval = 0; - regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_SR_TI_POS, DMA_CH_SR_TI_LEN, 1); - writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_SR)); - if (napi_schedule_prep(&channel->expansion.napi_tx)) { - pdata->stats.napi_poll_txtimer++; - __napi_schedule(&channel->expansion.napi_tx); - } - } else { - fxgmac_disable_rx_tx_ints(pdata); - if (napi_schedule_prep(&pdata->expansion.napi)) { - pdata->stats.napi_poll_txtimer++; - __napi_schedule(&pdata->expansion.napi); - } - } - - pdata->stats.cnt_alive_txtimer++; - channel->tx_timer_active = 0; -} -#endif - -#if FXGMAC_TX_HANG_TIMER_EN -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)) -static void fxgmac_tx_hang_timer_handler(struct timer_list *t) -#else -static void fxgmac_tx_hang_timer_handler(unsigned long data) -#endif -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)) - struct fxgmac_channel *channel = from_timer(channel, t, expansion.tx_hang_timer); -#else - struct fxgmac_channel *channel = (struct fxgmac_channel *)data; -#endif - -#if FXGMAC_TX_HANG_CHECH_DIRTY - struct fxgmac_ring *ring = channel->tx_ring; -#endif - struct fxgmac_pdata *pdata = channel->pdata; - struct net_device *netdev = pdata->netdev; - unsigned int hw_reg_cur; - unsigned int regval; - -#if FXGMAC_TX_HANG_CHECH_DIRTY - hw_reg_cur = ring->dirty; -#else - hw_reg_cur = readl(FXGMAC_DMA_REG(channel, 0x44/* tx desc curr pointer reg */)); -#endif - if(hw_reg_cur == channel->expansion.tx_hang_hw_cur) { - - /* hw current desc still stucked */ - if(!pdata->tx_hang_restart_queuing) { - pdata->tx_hang_restart_queuing = 1; - DPRINTK("tx_hang_timer_handler: restart scheduled, at desc %u, queuing=%u.\n", channel->expansion.tx_hang_hw_cur, pdata->tx_hang_restart_queuing); - - netif_tx_stop_all_queues(netdev); - - /* Disable MAC Rx */ - regval = readl(pdata->mac_regs + MAC_CR); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_CST_POS, - MAC_CR_CST_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_ACS_POS, - MAC_CR_ACS_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_RE_POS, - MAC_CR_RE_LEN, 0); - writel(regval, pdata->mac_regs + MAC_CR); - - schedule_work(&pdata->expansion.restart_work); - } - } - - channel->expansion.tx_hang_timer_active = 0; -} - -static void fxgmac_tx_hang_timer_start(struct fxgmac_channel *channel) -{ - struct fxgmac_pdata *pdata = channel->pdata; - - /* Start the Tx hang timer */ - if (1 && !channel->expansion.tx_hang_timer_active) { - channel->expansion.tx_hang_timer_active = 1; - - /* FXGMAC_INIT_DMA_TX_USECS is desc3 polling period, we give 2 more checking period */ - mod_timer(&channel->expansion.tx_hang_timer, - jiffies + usecs_to_jiffies(FXGMAC_INIT_DMA_TX_USECS * 10)); - } -} -#endif - -#if 0 -static void fxgmac_init_timers(struct fxgmac_pdata *pdata) -{ - struct fxgmac_channel *channel; - unsigned int i; - - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) - break; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)) - timer_setup(&channel->tx_timer, fxgmac_tx_timer, 0); -#else - setup_timer(&channel->tx_timer, fxgmac_tx_timer, (unsigned long)channel); -#endif -#if FXGMAC_TX_HANG_TIMER_EN - channel->tx_hang_timer_active = 0; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)) - timer_setup(&channel->tx_hang_timer, fxgmac_tx_hang_timer_handler, 0); -#else - setup_timer(&channel->tx_hang_timer, fxgmac_tx_hang_timer_handler, (unsigned long)channel); -#endif -#endif - } -} - -static void fxgmac_stop_timers(struct fxgmac_pdata *pdata) -{ - struct fxgmac_channel *channel; - unsigned int i; - - channel = pdata->channel_head; - if (channel != NULL) { - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) - break; - - del_timer_sync(&channel->tx_timer); -#if FXGMAC_TX_HANG_TIMER_EN - del_timer_sync(&channel->tx_hang_timer); - channel->tx_hang_timer_active = 0; -#endif - } - } -} -#endif - -static void fxgmac_napi_enable(struct fxgmac_pdata *pdata, unsigned int add) -{ - struct fxgmac_channel *channel; - unsigned int i; - - if (pdata->per_channel_irq) { - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (add) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0)) - netif_napi_add_weight(pdata->netdev, &channel->expansion.napi_rx, - fxgmac_one_poll_rx, NAPI_POLL_WEIGHT); -#else - netif_napi_add(pdata->netdev, &channel->expansion.napi_rx, - fxgmac_one_poll_rx, NAPI_POLL_WEIGHT); -#endif - } - napi_enable(&channel->expansion.napi_rx); - - if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0)) - netif_napi_add_weight(pdata->netdev, &channel->expansion.napi_tx, - fxgmac_one_poll_tx, NAPI_POLL_WEIGHT); -#else - netif_napi_add(pdata->netdev, &channel->expansion.napi_tx, - fxgmac_one_poll_tx, NAPI_POLL_WEIGHT); -#endif - napi_enable(&channel->expansion.napi_tx); - } - if(netif_msg_drv(pdata)) DPRINTK("napi_enable, msix ch%d napi enabled done,add=%d\n", i, add); - } - - // for phy -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0)) - netif_napi_add_weight(pdata->netdev, &pdata->expansion.napi_phy, - fxgmac_phy_poll, NAPI_POLL_WEIGHT); -#else - netif_napi_add(pdata->netdev, &pdata->expansion.napi_phy, - fxgmac_phy_poll, NAPI_POLL_WEIGHT); -#endif - napi_enable(&pdata->expansion.napi_phy); - } else { - i = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_LEGACY_NAPI_FREE_POS, - FXGMAC_FLAG_LEGACY_NAPI_FREE_LEN); - if (!i) { - if (add) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0)) - netif_napi_add_weight(pdata->netdev, &pdata->expansion.napi, - fxgmac_all_poll, NAPI_POLL_WEIGHT); -#else - netif_napi_add(pdata->netdev, &pdata->expansion.napi, - fxgmac_all_poll, NAPI_POLL_WEIGHT); -#endif - } - - napi_enable(&pdata->expansion.napi); - pdata->expansion.int_flags = FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_LEGACY_NAPI_FREE_POS, - FXGMAC_FLAG_LEGACY_NAPI_FREE_LEN, - 1); - } - } -} - -static void fxgmac_napi_disable(struct fxgmac_pdata *pdata, unsigned int del) -{ - struct fxgmac_channel *channel; - unsigned int i; - - if (pdata->per_channel_irq) { - channel = pdata->channel_head; - if (channel != NULL) { - for (i = 0; i < pdata->channel_count; i++, channel++) { - napi_disable(&channel->expansion.napi_rx); - - if (del) { - netif_napi_del(&channel->expansion.napi_rx); - } - - if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { - napi_disable(&channel->expansion.napi_tx); - netif_napi_del(&channel->expansion.napi_tx); - } - if(netif_msg_drv(pdata)) DPRINTK("napi_disable, msix ch%d napi disabled done,del=%d\n", i, del); - } - - napi_disable(&pdata->expansion.napi_phy); - netif_napi_del(&pdata->expansion.napi_phy); - } - } else { - i = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_LEGACY_NAPI_FREE_POS, - FXGMAC_FLAG_LEGACY_NAPI_FREE_LEN); - if (i) { - napi_disable(&pdata->expansion.napi); - - if (del) - netif_napi_del(&pdata->expansion.napi); - pdata->expansion.int_flags = FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_LEGACY_NAPI_FREE_POS, - FXGMAC_FLAG_LEGACY_NAPI_FREE_LEN, - 0); - - } - } -} - -static int fxgmac_request_irqs(struct fxgmac_pdata *pdata) -{ - struct net_device *netdev = pdata->netdev; - struct fxgmac_channel *channel; - unsigned int i; - int ret; - u32 msi, msix, need_free; - - msi = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_MSI_POS, - FXGMAC_FLAG_MSI_LEN); - - msix = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_MSIX_POS, - FXGMAC_FLAG_MSIX_LEN); - - need_free = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_LEGACY_IRQ_FREE_POS, - FXGMAC_FLAG_LEGACY_IRQ_FREE_LEN); - - if(!msix) { - if (!need_free) { - ret = devm_request_irq(pdata->dev, pdata->dev_irq, fxgmac_isr, - msi ? 0 : IRQF_SHARED, - netdev->name, pdata); - if (ret) { - netdev_alert(netdev, "error requesting irq %d, ret = %d\n", pdata->dev_irq, ret); - return ret; - } - - pdata->expansion.int_flags = FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_LEGACY_IRQ_FREE_POS, - FXGMAC_FLAG_LEGACY_IRQ_FREE_LEN, - 1); - } - } - - if (!pdata->per_channel_irq) - return 0; - - ret = devm_request_irq(pdata->dev, pdata->expansion.phy_irq, fxgmac_phy_isr, 0, netdev->name, pdata); - if (ret) { - netdev_alert(netdev, "error requesting phy irq %d, ret = %d\n", pdata->expansion.phy_irq, ret); - return ret; - } - - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) { - snprintf(channel->expansion.dma_irq_name, - sizeof(channel->expansion.dma_irq_name) - 1, - "%s-ch%d-Rx-%u", netdev_name(netdev), i, - channel->queue_index); - if(FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { - snprintf(channel->expansion.dma_irq_name_tx, - sizeof(channel->expansion.dma_irq_name_tx) - 1, - "%s-ch%d-Tx-%u", netdev_name(netdev), i, - channel->queue_index); - - ret = devm_request_irq(pdata->dev, channel->expansion.dma_irq_tx, - fxgmac_dma_isr, 0, - channel->expansion.dma_irq_name_tx, channel); - - if (ret) { - DPRINTK("fxgmac_req_irqs, err with MSIx irq request for ch %d tx, ret=%d\n", i, ret); - /* Using an unsigned int, 'i' will go to UINT_MAX and exit */ - devm_free_irq(pdata->dev, channel->expansion.dma_irq_tx, channel); - //devm_free_irq(pdata->dev, pdata->dev_irq, pdata); - return ret; - } - - if(netif_msg_drv(pdata)) - DPRINTK("fxgmac_req_irqs, MSIx irq_tx request ok, ch=%d, irq=%d,%s\n", - i, channel->expansion.dma_irq_tx, channel->expansion.dma_irq_name_tx); - } - ret = devm_request_irq(pdata->dev, channel->dma_irq, - fxgmac_dma_isr, 0, - channel->expansion.dma_irq_name, channel); - if (ret) { - netdev_alert(netdev, "error requesting irq %d\n", - channel->dma_irq); - goto err_irq; - } - } - - if(netif_msg_drv(pdata)) DPRINTK("fxgmac_req_irqs, MSIx irq request ok, total=%d,%d~%d\n", i, (pdata->channel_head)[0].dma_irq, (pdata->channel_head)[i-1].dma_irq); - return 0; - -err_irq: - DPRINTK("fxgmac_req_irqs, err with MSIx irq request at %d, ret=%d\n", i, ret); - - if (pdata->per_channel_irq) { - for (i--, channel--; i < pdata->channel_count; i--, channel--) { - if(FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { - devm_free_irq(pdata->dev, channel->expansion.dma_irq_tx, channel); - } - devm_free_irq(pdata->dev, channel->dma_irq, channel); - } - - devm_free_irq(pdata->dev, pdata->expansion.phy_irq, pdata); - } - return ret; -} - -static void fxgmac_free_irqs(struct fxgmac_pdata *pdata) -{ - struct fxgmac_channel *channel; - unsigned int i = 0; - u32 need_free, msix; - - msix = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_MSIX_POS, - FXGMAC_FLAG_MSIX_LEN); - - need_free = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_LEGACY_IRQ_FREE_POS, - FXGMAC_FLAG_LEGACY_IRQ_FREE_LEN); - - if(!msix) { - if (need_free) { - devm_free_irq(pdata->dev, pdata->dev_irq, pdata); - pdata->expansion.int_flags = FXGMAC_SET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_LEGACY_IRQ_FREE_POS, - FXGMAC_FLAG_LEGACY_IRQ_FREE_LEN, - 0); - } - } - - if (!pdata->per_channel_irq) - return; - - channel = pdata->channel_head; - if (channel != NULL) { - for (i = 0; i < pdata->channel_count; i++, channel++) { - if(FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { - devm_free_irq(pdata->dev, channel->expansion.dma_irq_tx, channel); - if(netif_msg_drv(pdata)) DPRINTK("fxgmac_free_irqs, MSIx irq_tx clear done, ch=%d\n", i); - } - devm_free_irq(pdata->dev, channel->dma_irq, channel); - } - - devm_free_irq(pdata->dev, pdata->expansion.phy_irq, pdata); - } - if(netif_msg_drv(pdata)) DPRINTK("fxgmac_free_irqs, MSIx rx irq clear done, total=%d\n", i); -} - -void fxgmac_free_tx_data(struct fxgmac_pdata *pdata) -{ - struct fxgmac_desc_ops *desc_ops = &pdata->desc_ops; - struct fxgmac_desc_data *desc_data; - struct fxgmac_channel *channel; - struct fxgmac_ring *ring; - unsigned int i, j; - - channel = pdata->channel_head; - if (channel != NULL) { - for (i = 0; i < pdata->channel_count; i++, channel++) { - ring = channel->tx_ring; - if (!ring) - break; - - for (j = 0; j < ring->dma_desc_count; j++) { - desc_data = FXGMAC_GET_DESC_DATA(ring, j); - desc_ops->unmap_desc_data(pdata, desc_data); - } - } - } -} - -void fxgmac_free_rx_data(struct fxgmac_pdata *pdata) -{ - struct fxgmac_desc_ops *desc_ops = &pdata->desc_ops; - struct fxgmac_desc_data *desc_data; - struct fxgmac_channel *channel; - struct fxgmac_ring *ring; - unsigned int i, j; - - channel = pdata->channel_head; - if (channel != NULL) { - for (i = 0; i < pdata->channel_count; i++, channel++) { - ring = channel->rx_ring; - if (!ring) - break; - - for (j = 0; j < ring->dma_desc_count; j++) { - desc_data = FXGMAC_GET_DESC_DATA(ring, j); - desc_ops->unmap_desc_data(pdata, desc_data); - } - } - } -} - -/* - * since kernel does not clear the MSI mask bits and - * this function clear MSI mask bits when MSI is enabled. - */ -static int fxgmac_disable_pci_msi_config(struct pci_dev *pdev) -{ - u16 pcie_cap_offset; - u32 pcie_msi_mask_bits; - int ret = 0; - - pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_MSI); - if (pcie_cap_offset) { - ret = pci_read_config_dword(pdev, pcie_cap_offset, &pcie_msi_mask_bits); - if (ret) { - printk(KERN_ERR "read pci config space MSI cap. failed, %d\n", ret); - ret = -EFAULT; - } - } - - pcie_msi_mask_bits = FXGMAC_SET_REG_BITS(pcie_msi_mask_bits, - PCI_CAP_ID_MSI_ENABLE_POS, - PCI_CAP_ID_MSI_ENABLE_LEN, - 0); - ret = pci_write_config_dword(pdev, pcie_cap_offset, pcie_msi_mask_bits); - if (ret) { - printk(KERN_ERR "write pci config space MSI mask failed, %d\n", ret); - ret = -EFAULT; - } - - return ret; -} - -static int fxgmac_disable_pci_msix_config(struct pci_dev *pdev) -{ - u16 pcie_cap_offset; - u32 pcie_msi_mask_bits; - int ret = 0; - - pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_MSIX); - if (pcie_cap_offset) { - ret = pci_read_config_dword(pdev, pcie_cap_offset, &pcie_msi_mask_bits); - if (ret) { - printk(KERN_ERR "read pci config space MSIX cap. failed, %d\n", ret); - ret = -EFAULT; - } - } - - pcie_msi_mask_bits = FXGMAC_SET_REG_BITS(pcie_msi_mask_bits, - PCI_CAP_ID_MSIX_ENABLE_POS, - PCI_CAP_ID_MSIX_ENABLE_LEN, - 0); - ret = pci_write_config_dword(pdev, pcie_cap_offset, pcie_msi_mask_bits); - if (ret) { - printk(KERN_ERR "write pci config space MSIX mask failed, %d\n", ret); - ret = -EFAULT; - } - - return ret; -} - -extern int fxgmac_dismiss_all_int(struct fxgmac_pdata *pdata); - -int fxgmac_start(struct fxgmac_pdata *pdata) -{ - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - struct net_device *netdev = pdata->netdev; - int ret; - unsigned int pcie_low_power = 0; - u32 regval; - - if(netif_msg_drv(pdata)) DPRINTK("fxgmac start callin here.\n"); - - /* must reset software again here, to avoid flushing tx queue error caused by the system only run probe - * when installing driver on the arm platform. - */ - hw_ops->exit(pdata); - - if (FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_LEGACY_POS, - FXGMAC_FLAG_LEGACY_LEN)) { - /* - * we should disable msi and msix here when we use legacy interrupt,for two reasons: - * 1. Exit will restore msi and msix config regisiter, that may enable them. - * 2. When the driver that uses the msix interrupt by default is compiled - * into the OS, uninstall the driver through rmmod, and then install the - * driver that uses the legacy interrupt, at which time the msix enable - * will be turned on again by default after waking up from S4 on some platform. - * such as UOS platform. - */ - ret = fxgmac_disable_pci_msi_config(pdata->pdev); - ret |= fxgmac_disable_pci_msix_config(pdata->pdev); - if (ret) - return ret; - } - - hw_ops->reset_phy(pdata); - hw_ops->release_phy(pdata); - hw_ops->pcie_init(pdata, - pcie_low_power & PCIE_LP_ASPM_LTR, - pcie_low_power & PCIE_LP_ASPM_L1SS, - pcie_low_power & PCIE_LP_ASPM_L1, - pcie_low_power & PCIE_LP_ASPM_L0S); - hw_ops->config_power_up(pdata); - - fxgmac_dismiss_all_int(pdata); - - ret = hw_ops->init(pdata); - if (ret) { - printk("fxgmac hw init error.\n"); - return ret; - } - fxgmac_napi_enable(pdata, 1); - - ret = fxgmac_request_irqs(pdata); - if (ret) - goto err_napi; - - hw_ops->enable_tx(pdata); - hw_ops->enable_rx(pdata); - - //config interrupt to level signal - regval = (u32)readl((const volatile void *)(pdata->mac_regs + DMA_MR)); - regval = FXGMAC_SET_REG_BITS(regval, DMA_MR_INTM_POS, - DMA_MR_INTM_LEN, 1); - regval = FXGMAC_SET_REG_BITS(regval, DMA_MR_QUREAD_POS, - DMA_MR_QUREAD_LEN, 1); - writel(regval, pdata->mac_regs + DMA_MR); - - writel(0xF0000000, (volatile void *)(netdev->base_addr + MGMT_INT_CTRL0)); - - hw_ops->set_interrupt_moderation(pdata); - - if (pdata->per_channel_irq) - hw_ops->enable_msix_rxtxphyinterrupt(pdata); - - fxgmac_enable_rx_tx_ints(pdata); - -#if 0 - netif_tx_start_all_queues(netdev); -#endif - - hw_ops->led_under_active(pdata); - - return 0; - -err_napi: - fxgmac_napi_disable(pdata, 1); - hw_ops->exit(pdata); - DPRINTK("fxgmac start callout with irq err.\n"); - return ret; -} - -void fxgmac_stop(struct fxgmac_pdata *pdata) -{ - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - struct net_device *netdev = pdata->netdev; - struct fxgmac_channel *channel; - struct netdev_queue *txq; - unsigned int i; - - if (pdata->per_channel_irq) { - hw_ops->disable_msix_interrupt(pdata); - } - else { - hw_ops->disable_mgm_interrupt(pdata); - } - - pdata->expansion.phy_link = false; - - netif_carrier_off(netdev);//yzhang added, 0324 - netif_tx_stop_all_queues(netdev); -#if 0 - fxgmac_stop_timers(pdata); -#endif - hw_ops->disable_tx(pdata); - hw_ops->disable_rx(pdata); - fxgmac_free_irqs(pdata); - fxgmac_napi_disable(pdata, 1); - - channel = pdata->channel_head; - if (channel != NULL) { - 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); - } - } - - switch (pdata->expansion.current_state) { - case CURRENT_STATE_SUSPEND: - hw_ops->led_under_sleep(pdata); - break; - case CURRENT_STATE_SHUTDOWN: - case CURRENT_STATE_RESTART: - hw_ops->led_under_shutdown(pdata); - break; - case CURRENT_STATE_CLOSE: - //hw_ops->led_under_disable(pdata); - break; - default: - break; - } -} - -void fxgmac_restart_dev(struct fxgmac_pdata *pdata) -{ - int ret; - - /* If not running, "restart" will happen on open */ - if (!netif_running(pdata->netdev)) - return; - - pdata->expansion.current_state = CURRENT_STATE_RESTART; - fxgmac_stop(pdata); - - fxgmac_free_tx_data(pdata); - fxgmac_free_rx_data(pdata); - - ret = fxgmac_start(pdata); - if (ret) { - printk("fxgmac_restart_dev: fxgmac_start failed.\n"); - } -} - -static void fxgmac_restart(struct work_struct *work) -{ - struct fxgmac_pdata *pdata = container_of(work, - struct fxgmac_pdata, - expansion.restart_work); - - rtnl_lock(); - - fxgmac_restart_dev(pdata); - - rtnl_unlock(); -} - -void fxgmac_net_powerup(struct fxgmac_pdata *pdata) -{ - int ret; - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - - if(netif_msg_drv(pdata)) DPRINTK("fxgmac_net_powerup callin\n"); - - /* signal that we are up now */ - pdata->expansion.powerstate = 0; //clear all bits as normal now - if (__test_and_set_bit(FXGMAC_POWER_STATE_UP, &pdata->expansion.powerstate)) { - return; /* do nothing if already up */ - } - - ret = fxgmac_start(pdata); - if (ret) { - printk("fxgmac_net_powerup: fxgmac_start error\n"); - return; - } - - // must call it after fxgmac_start,because it will be enable in fxgmac_start - hw_ops->disable_arp_offload(pdata); - - if(netif_msg_drv(pdata)) { - DPRINTK("fxgmac_net_powerup callout, powerstate=%ld.\n", pdata->expansion.powerstate); - } -} - -void fxgmac_net_powerdown(struct fxgmac_pdata *pdata, unsigned int wol) -{ - struct net_device *netdev = pdata->netdev; - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - - if(netif_msg_drv(pdata)) DPRINTK("fxgmac_net_powerdown callin here.\n"); - - /* signal that we are down to the interrupt handler */ - if (__test_and_set_bit(FXGMAC_POWER_STATE_DOWN, &pdata->expansion.powerstate)) - return; /* do nothing if already down */ - - if(netif_msg_drv(pdata)) DPRINTK("fxgmac_net_powerdown continue with down process.\n"); - /* phy polling timer should detect the state of fxgmac and stop link status polling accordingly */ - - __clear_bit(FXGMAC_POWER_STATE_UP, &pdata->expansion.powerstate); - -#if 1 - /* Shut off incoming Tx traffic */ - netif_tx_stop_all_queues(netdev); - - /* call carrier off first to avoid false dev_watchdog timeouts */ - netif_carrier_off(netdev); - netif_tx_disable(netdev); - - /* Disable Rx */ - hw_ops->disable_rx(pdata); - - /* synchronize_rcu() needed for pending XDP buffers to drain */ - //if (adapter->xdp_ring[0]) 20210709 - synchronize_rcu(); - - fxgmac_stop(pdata); //some works are redundent in this call -#endif - // must call it after software reset - hw_ops->pre_power_down(pdata, false); - - /* set mac to lowpower mode and enable wol accordingly */ - hw_ops->config_power_down(pdata, wol); - -#if 1 - //handle vfs if it is envolved - - //similar work as in restart() for that, we do need a resume laterly - fxgmac_free_tx_data(pdata); - fxgmac_free_rx_data(pdata); -#endif - if(netif_msg_drv(pdata)) DPRINTK("fxgmac_net_powerdown callout, powerstate=%ld.\n", pdata->expansion.powerstate); -} - -static int fxgmac_open(struct net_device *netdev) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_desc_ops *desc_ops; - int ret; - - if(netif_msg_drv(pdata)) DPRINTK("fxgmac_open callin\n"); - - desc_ops = &pdata->desc_ops; - - /* TODO: Initialize the phy */ - - /* Calculate the Rx buffer size before allocating rings */ - //DPRINTK("fxgmac_open, b4 calc rx buf size, mtu,min,max=%d,%d,%d.\n", netdev->mtu, netdev->min_mtu, netdev->max_mtu); - ret = fxgmac_calc_rx_buf_size(netdev, netdev->mtu); - if (ret < 0) - return ret; - pdata->rx_buf_size = ret; - - /* Allocate the channels and rings */ - ret = desc_ops->alloc_channles_and_rings(pdata); - if (ret) - return ret; - - INIT_WORK(&pdata->expansion.restart_work, fxgmac_restart); -#if 0 - fxgmac_init_timers(pdata); -#endif - ret = fxgmac_start(pdata); - if (ret) - goto err_channels_and_rings; - - if(netif_msg_drv(pdata)) DPRINTK("fxgmac_open callout\n"); - - return 0; - -err_channels_and_rings: - desc_ops->free_channels_and_rings(pdata); - DPRINTK("fxgmac_open callout with channel alloc err\n"); - return ret; -} - -static int fxgmac_close(struct net_device *netdev) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_desc_ops *desc_ops; - - if(netif_msg_drv(pdata)) DPRINTK("fxgmac_close callin\n"); - - desc_ops = &pdata->desc_ops; - - pdata->expansion.current_state = (pdata->expansion.current_state == CURRENT_STATE_SHUTDOWN) ? - pdata->expansion.current_state : CURRENT_STATE_CLOSE; - - /* Stop the device */ - fxgmac_stop(pdata); - - /* Free the channels and rings */ - desc_ops->free_channels_and_rings(pdata); - - pdata->hw_ops.reset_phy(pdata); - - if(netif_msg_drv(pdata)) DPRINTK("fxgmac_close callout\n"); - - return 0; -} - -#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4,0,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(5,6,0))) -static void fxgmac_tx_timeout(struct net_device *netdev) -#else -static void fxgmac_tx_timeout(struct net_device *netdev, unsigned int unused) -#endif -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - - netdev_warn(netdev, "tx timeout, device restarting\n"); -#if FXGMAC_TX_HANG_TIMER_EN - if(!pdata->tx_hang_restart_queuing) - schedule_work(&pdata->expansion.restart_work); -#else - schedule_work(&pdata->expansion.restart_work); -#endif -} - -static int fxgmac_xmit(struct sk_buff *skb, struct net_device *netdev) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_pkt_info *tx_pkt_info; - struct fxgmac_desc_ops *desc_ops; - struct fxgmac_channel *channel; - struct fxgmac_hw_ops *hw_ops; - struct netdev_queue *txq; - struct fxgmac_ring *ring; - int ret; - - desc_ops = &pdata->desc_ops; - hw_ops = &pdata->hw_ops; - - //yzhang disabled - if(netif_msg_tx_done(pdata)) DPRINTK("xmit callin, skb->len=%d,q=%d\n", skb->len, skb->queue_mapping); - - channel = pdata->channel_head + skb->queue_mapping; - txq = netdev_get_tx_queue(netdev, channel->queue_index); - ring = channel->tx_ring; - tx_pkt_info = &ring->pkt_info; -#if 0 - if (1/*yzhang dbg skb->len == 0*/) { - netif_err(pdata, tx_err, netdev, - "empty skb received from stack\n"); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } -#else - if (skb->len == 0) { - netif_err(pdata, tx_err, netdev, - "empty skb received from stack\n"); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } -#endif - /* Prepare preliminary packet info for TX */ - memset(tx_pkt_info, 0, sizeof(*tx_pkt_info)); - fxgmac_prep_tx_pkt(pdata, ring, skb, tx_pkt_info); - - /* Check that there are enough descriptors available */ - ret = fxgmac_maybe_stop_tx_queue(channel, ring, - tx_pkt_info->desc_count); - if (ret) - { - return ret; - } - - ret = fxgmac_prep_tso(pdata, skb, tx_pkt_info); - if (ret) { - netif_err(pdata, tx_err, netdev, - "error processing TSO packet\n"); - DPRINTK("dev_xmit,tx err for TSO\n"); - dev_kfree_skb_any(skb); - return ret; - } - fxgmac_prep_vlan(skb, tx_pkt_info); - - if (!desc_ops->map_tx_skb(channel, skb)) { - dev_kfree_skb_any(skb); - DPRINTK("xmit, map tx skb err\n"); - return NETDEV_TX_OK; - } - - /* Report on the actual number of bytes (to be) sent */ - netdev_tx_sent_queue(txq, tx_pkt_info->tx_bytes); - if(netif_msg_tx_done(pdata)) DPRINTK("xmit,before hw_xmit, byte len=%d\n", tx_pkt_info->tx_bytes); - - /* Configure required descriptor fields for transmission */ - hw_ops->dev_xmit(channel); -#if FXGMAC_DUMMY_TX_DEBUG - DPRINTK("tx hw_ops->dev_xmit ok\n"); -#endif - if (netif_msg_pktdata(pdata)) - fxgmac_dbg_pkt(netdev, skb, true); - - /* Stop the queue in advance if there may not be enough descriptors */ - fxgmac_maybe_stop_tx_queue(channel, ring, FXGMAC_TX_MAX_DESC_NR); - - return NETDEV_TX_OK; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0)) -static void fxgmac_get_stats64(struct net_device *netdev, - struct rtnl_link_stats64 *s) -#else -static struct rtnl_link_stats64 * fxgmac_get_stats64(struct net_device *netdev, - struct rtnl_link_stats64 *s) -#endif -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_stats *pstats = &pdata->stats; - -#if FXGMAC_PM_FEATURE_ENABLED - /* 20210709 for net power down */ - if(!test_bit(FXGMAC_POWER_STATE_DOWN, &pdata->expansion.powerstate)) -#endif - { - //DPRINTK("get_stats64, ndo op, callin\n"); - pdata->hw_ops.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; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0)) - return s; -#endif -} - -static int fxgmac_set_mac_address(struct net_device *netdev, void *addr) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - struct sockaddr *saddr = addr; - - if (!is_valid_ether_addr(saddr->sa_data)) - return -EADDRNOTAVAIL; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0)) - eth_hw_addr_set(netdev, saddr->sa_data); -#else - memcpy(netdev->dev_addr, saddr->sa_data, netdev->addr_len); -#endif - memcpy(pdata->mac_addr, saddr->sa_data, netdev->addr_len); - - hw_ops->set_mac_address(pdata, saddr->sa_data); - hw_ops->set_mac_hash(pdata); - - DPRINTK("fxgmac,set mac addr to %02x:%02x:%02x:%02x:%02x:%02x\n",netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], - netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); - return 0; -} - -// cmd = [0x89F0, 0x89FF] -static int fxgmac_ioctl(struct net_device *netdev, - struct ifreq *ifr, int cmd) -{ - struct file f; - int ret = FXGMAC_SUCCESS; - struct fxgmac_pdata *pdata = netdev_priv(netdev); - - if (!netif_running(netdev)) - return -ENODEV; - - f.private_data = pdata; - - switch (cmd) { - case FXGMAC_DEV_CMD: - ret = fxgmac_dbg_netdev_ops_ioctl(&f, FXGMAC_IOCTL_DFS_COMMAND, (unsigned long)(ifr->ifr_data)); - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0) ) -static int fxgmac_siocdevprivate(struct net_device *dev, - struct ifreq *ifr, - void __user *data, - int cmd) -{ - return fxgmac_ioctl(dev, ifr, cmd); -} -#endif - -static int fxgmac_change_mtu(struct net_device *netdev, int mtu) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - int ret; -#ifdef FXGMAC_DEBUG - int old_mtu = netdev->mtu; -#endif - - fxgmac_stop(pdata); - fxgmac_free_tx_data(pdata); - - // We must unmap rx desc's dma before we change rx_buf_size. - // Becaues the size of the unmapped DMA is set according to rx_buf_size - fxgmac_free_rx_data(pdata); - - pdata->jumbo = mtu > ETH_DATA_LEN ? 1 : 0; - - ret = fxgmac_calc_rx_buf_size(netdev, mtu); - if (ret < 0) - return ret; - - pdata->rx_buf_size = ret; - netdev->mtu = mtu; - - if (netif_running(netdev)) - fxgmac_start(pdata); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) - DPRINTK("fxgmac,set MTU from %d to %d. min, max=(%d,%d)\n",old_mtu, netdev->mtu, netdev->min_mtu, netdev->max_mtu); -#else - DPRINTK("fxgmac,set MTU from %d to %d.\n",old_mtu, netdev->mtu); -#endif - - return 0; -} - -static int fxgmac_vlan_rx_add_vid(struct net_device *netdev, - __be16 proto, - u16 vid) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - - set_bit(vid, pdata->active_vlans); -#if FXGMAC_FILTER_SINGLE_VLAN_ENABLED - pdata->vlan = vid; - hw_ops->enable_rx_vlan_filtering(pdata); -#else - hw_ops->update_vlan_hash_table(pdata); -#endif - DPRINTK("fxgmac,add rx vlan %d\n", vid); - return 0; -} - -static int fxgmac_vlan_rx_kill_vid(struct net_device *netdev, - __be16 proto, - u16 vid) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - - clear_bit(vid, pdata->active_vlans); -#if FXGMAC_FILTER_SINGLE_VLAN_ENABLED - pdata->vlan = 0; - hw_ops->disable_rx_vlan_filtering(pdata); -#else - hw_ops->update_vlan_hash_table(pdata); -#endif - - DPRINTK("fxgmac,del rx vlan %d\n", vid); - return 0; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void fxgmac_poll_controller(struct net_device *netdev) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_channel *channel; - unsigned int i; - - if (pdata->per_channel_irq) { - channel = pdata->channel_head; - for (i = 0; i < pdata->channel_count; i++, channel++) - fxgmac_dma_isr(channel->dma_irq, channel); - } else { - disable_irq(pdata->dev_irq); - fxgmac_isr(pdata->dev_irq, pdata); - enable_irq(pdata->dev_irq); - } -} -#endif /* CONFIG_NET_POLL_CONTROLLER */ - -static int fxgmac_set_features(struct net_device *netdev, - netdev_features_t features) -{ - netdev_features_t rxhash, rxcsum, rxvlan, rxvlan_filter, tso; - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - int ret = 0; - - rxhash = pdata->expansion.netdev_features & NETIF_F_RXHASH; - rxcsum = pdata->expansion.netdev_features & NETIF_F_RXCSUM; - rxvlan = pdata->expansion.netdev_features & NETIF_F_HW_VLAN_CTAG_RX; - rxvlan_filter = pdata->expansion.netdev_features & NETIF_F_HW_VLAN_CTAG_FILTER; - tso = pdata->expansion.netdev_features & (NETIF_F_TSO | NETIF_F_TSO6); - - if ((features & (NETIF_F_TSO | NETIF_F_TSO6)) && !tso) { - printk("enable tso.\n"); - pdata->hw_feat.tso = 1; - hw_ops->config_tso(pdata); - } else if (!(features & (NETIF_F_TSO | NETIF_F_TSO6)) && tso) { - printk("disable tso.\n"); - pdata->hw_feat.tso = 0; - hw_ops->config_tso(pdata); - } - - if ((features & NETIF_F_RXHASH) && !rxhash) - ret = hw_ops->enable_rss(pdata); - else if (!(features & NETIF_F_RXHASH) && rxhash) - ret = hw_ops->disable_rss(pdata); - if (ret) - return ret; - - if ((features & NETIF_F_RXCSUM) && !rxcsum) - hw_ops->enable_rx_csum(pdata); - else if (!(features & NETIF_F_RXCSUM) && rxcsum) - hw_ops->disable_rx_csum(pdata); - - if ((features & NETIF_F_HW_VLAN_CTAG_RX) && !rxvlan) - hw_ops->enable_rx_vlan_stripping(pdata); - else if (!(features & NETIF_F_HW_VLAN_CTAG_RX) && rxvlan) - hw_ops->disable_rx_vlan_stripping(pdata); - - if ((features & NETIF_F_HW_VLAN_CTAG_FILTER) && !rxvlan_filter) - hw_ops->enable_rx_vlan_filtering(pdata); - else if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER) && rxvlan_filter) - hw_ops->disable_rx_vlan_filtering(pdata); - - pdata->expansion.netdev_features = features; - - DPRINTK("fxgmac,set features done,%llx\n", (u64)features); - return 0; -} - -static void fxgmac_set_rx_mode(struct net_device *netdev) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - - hw_ops->config_rx_mode(pdata); -} - -static const struct net_device_ops fxgmac_netdev_ops = { - .ndo_open = fxgmac_open, - .ndo_stop = fxgmac_close, - .ndo_start_xmit = fxgmac_xmit, - .ndo_tx_timeout = fxgmac_tx_timeout, - .ndo_get_stats64 = fxgmac_get_stats64, - .ndo_change_mtu = fxgmac_change_mtu, - .ndo_set_mac_address = fxgmac_set_mac_address, - .ndo_validate_addr = eth_validate_addr, - .ndo_do_ioctl = fxgmac_ioctl, -#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0) ) - .ndo_siocdevprivate = fxgmac_siocdevprivate, -#endif - .ndo_vlan_rx_add_vid = fxgmac_vlan_rx_add_vid, - .ndo_vlan_rx_kill_vid = fxgmac_vlan_rx_kill_vid, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = fxgmac_poll_controller, -#endif - .ndo_set_features = fxgmac_set_features, - .ndo_set_rx_mode = fxgmac_set_rx_mode, -}; - -const struct net_device_ops *fxgmac_get_netdev_ops(void) -{ - return &fxgmac_netdev_ops; -} - -static void fxgmac_rx_refresh(struct fxgmac_channel *channel) -{ - struct fxgmac_pdata *pdata = channel->pdata; - struct fxgmac_ring *ring = channel->rx_ring; - struct fxgmac_desc_data *desc_data; -#if 0 - struct fxgmac_desc_ops *desc_ops = &pdata->desc_ops; -#endif - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - - while (ring->dirty != ring->cur) { - desc_data = FXGMAC_GET_DESC_DATA(ring, ring->dirty); -#if 0 - /* Reset desc_data values */ - desc_ops->unmap_desc_data(pdata, desc_data); - - if (desc_ops->map_rx_buffer(pdata, ring, desc_data)) - break; -#endif - hw_ops->rx_desc_reset(pdata, desc_data, ring->dirty); - ring->dirty = FXGMAC_GET_ENTRY(ring->dirty, ring->dma_desc_count); - } - - /* Make sure everything is written before the register write */ - wmb(); - - /* Update the Rx Tail Pointer Register with address of - * the last cleaned entry - */ - desc_data = FXGMAC_GET_DESC_DATA(ring, (ring->dirty - 1) & (ring->dma_desc_count - 1)); - writel(lower_32_bits(desc_data->dma_desc_addr), FXGMAC_DMA_REG(channel, DMA_CH_RDTR_LO)); -} - -static struct sk_buff *fxgmac_create_skb(struct fxgmac_pdata *pdata, - struct napi_struct *napi, - struct fxgmac_desc_data *desc_data, - unsigned int len) -{ -#if 0 - unsigned int copy_len; - struct sk_buff *skb; - u8 *packet; - - skb = napi_alloc_skb(napi, desc_data->rx.hdr.dma_len); - if (!skb) - return NULL; - - /* Start with the header buffer which may contain just the header - * or the header plus data - */ - dma_sync_single_range_for_cpu(pdata->dev, desc_data->rx.hdr.dma_base, - desc_data->rx.hdr.dma_off, - desc_data->rx.hdr.dma_len, - DMA_FROM_DEVICE); - - packet = page_address(desc_data->rx.hdr.pa.pages) + - desc_data->rx.hdr.pa.pages_offset; - copy_len = (desc_data->rx.hdr_len) ? desc_data->rx.hdr_len : len; - copy_len = min(desc_data->rx.hdr.dma_len, copy_len); - skb_copy_to_linear_data(skb, packet, copy_len); - skb_put(skb, copy_len); - - len -= copy_len; - if (len) { - /* Add the remaining data as a frag */ - dma_sync_single_range_for_cpu(pdata->dev, - desc_data->rx.buf.dma_base, - desc_data->rx.buf.dma_off, - desc_data->rx.buf.dma_len, - DMA_FROM_DEVICE); - - skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, - desc_data->rx.buf.pa.pages, - desc_data->rx.buf.pa.pages_offset, - len, desc_data->rx.buf.dma_len); - desc_data->rx.buf.pa.pages = NULL; - } - - return skb; -#endif - struct sk_buff *skb; - skb = __netdev_alloc_skb_ip_align(pdata->netdev, len, GFP_ATOMIC); - if (!skb) { - netdev_err(pdata->netdev, "%s: Rx init fails; skb is NULL\n", __func__); - return NULL; - } - - dma_sync_single_for_cpu(pdata->dev, desc_data->rx.buf.dma_base, len, DMA_FROM_DEVICE); - skb_copy_to_linear_data(skb, desc_data->skb->data, len); - skb_put(skb, len); - dma_sync_single_for_device(pdata->dev, desc_data->rx.buf.dma_base, len, DMA_FROM_DEVICE); - - return skb; -} - -static int fxgmac_tx_poll(struct fxgmac_channel *channel) -{ - struct fxgmac_pdata *pdata = channel->pdata; - struct fxgmac_ring *ring = channel->tx_ring; - struct net_device *netdev = pdata->netdev; - unsigned int tx_packets = 0, tx_bytes = 0; - struct fxgmac_desc_data *desc_data; - struct fxgmac_dma_desc *dma_desc; - struct fxgmac_desc_ops *desc_ops; - struct fxgmac_hw_ops *hw_ops; - struct netdev_queue *txq; - int processed = 0; - unsigned int cur; - - static int fxgmac_restart_need = 0; - static u32 change_cnt = 0; - static u32 reg_cur_pre = 0xffffffff; - -#if FXGMAC_TX_HANG_TIMER_EN - static u32 reg_cur = 0; -#endif - - desc_ops = &pdata->desc_ops; - hw_ops = &pdata->hw_ops; - - /* Nothing to do if there isn't a Tx ring for this channel */ - if (!ring){ - if(netif_msg_tx_done(pdata) && (channel->queue_index < pdata->tx_q_count)) DPRINTK("tx_poll, null point to ring %d\n", channel->queue_index); - return 0; - } - if((ring->cur != ring->dirty) && (netif_msg_tx_done(pdata))) - DPRINTK("tx_poll callin, ring_cur=%d,ring_dirty=%d,qIdx=%d\n", ring->cur, ring->dirty, channel->queue_index); - - cur = ring->cur; - - /* Be sure we get ring->cur before accessing descriptor data */ - smp_rmb(); - - txq = netdev_get_tx_queue(netdev, channel->queue_index); - - while (ring->dirty != cur) { - desc_data = FXGMAC_GET_DESC_DATA(ring, ring->dirty); - dma_desc = desc_data->dma_desc; - - if (!hw_ops->tx_complete(dma_desc)) { -#if FXGMAC_TRIGGER_TX_HANG - struct net_device *netdev = pdata->netdev; - #define FXGMAC_HANG_THRESHOLD 1 - //static u32 reg_tail = 0, reg_tail_pre = 0xffffffff; - - reg_cur = readl(FXGMAC_DMA_REG(channel, 0x44/* tx desc curr pointer reg */)); - - if(reg_cur != reg_cur_pre){ - reg_cur_pre = reg_cur; - change_cnt = 0; - } else { - change_cnt++; - } - - if (change_cnt > 2) - { - //change_cnt = 0; - - DPRINTK("after complete check, cur=%d, dirty=%d,qIdx=%d, hw desc cur=%#x, pre=%#x\n", ring->cur, ring->dirty, channel->queue_index, - reg_cur, reg_cur_pre); - - if((ring->cur > ring->dirty) && ((ring->cur - ring->dirty) > FXGMAC_HANG_THRESHOLD) ) { - DPRINTK("after complete check warning..., too many TBD occupied by HW, 0xdbbb, %d.\n", (ring->cur - ring->dirty)); - (* ((u32 *)(netdev->base_addr + 0x1000))) = 0xdbbb; - - if(!fxgmac_restart_need ) { - schedule_work(&pdata->expansion.restart_work); - fxgmac_restart_need = 1; - change_cnt = 0; - } - }else if((ring->cur < ring->dirty) && ((ring->cur + (ring->dma_desc_count - ring->dirty)) > FXGMAC_HANG_THRESHOLD) ) { - DPRINTK("after complete check warning..., too many TBD occupied by HW, 0xdb00, %d.\n", (ring->cur + (ring->dma_desc_count - ring->dirty))); - (* ((u32 *)(netdev->base_addr + 0x1000))) = 0xdb00; - - if(!fxgmac_restart_need ) { - schedule_work(&pdata->expansion.restart_work); - fxgmac_restart_need = 1; - change_cnt = 0; - } - } - } -#endif -#if FXGMAC_TX_HANG_TIMER_EN - if((!pdata->tx_hang_restart_queuing) && (!channel->expansion.tx_hang_timer_active)) { - reg_cur = ring->dirty; - if(reg_cur_pre != reg_cur) { - reg_cur_pre = reg_cur; - change_cnt = 0; - }else { - change_cnt++; - } - - if (change_cnt > 4) - { -#if FXGMAC_TX_HANG_CHECH_DIRTY - channel->expansion.tx_hang_hw_cur = ring->dirty; -#else - channel->expansion.tx_hang_hw_cur = readl(FXGMAC_DMA_REG(channel, 0x44/* tx desc curr pointer reg */)); -#endif - /* double check for race conditione */ - if ((!pdata->tx_hang_restart_queuing) && (!channel->expansion.tx_hang_timer_active)) { - DPRINTK("tx_hang polling: start timer at desc %u, timer act=%u, queuing=%u, qidx=%u.\n", reg_cur, channel->expansion.tx_hang_timer_active, pdata->tx_hang_restart_queuing, channel->queue_index); - fxgmac_tx_hang_timer_start(channel); - } - } - }else if (pdata->tx_hang_restart_queuing) { - //if(netif_msg_drv(pdata)) DPRINTK("tx_hang_timer_handler: restart scheduled.\n"); - } -#endif - - break; - } - - reg_cur_pre = 0xffffffff; - fxgmac_restart_need = 0; - change_cnt = 0; - - /* Make sure descriptor fields are read after reading - * the OWN bit - */ - dma_rmb(); - - if (netif_msg_tx_done(pdata)) - fxgmac_dump_tx_desc(pdata, ring, ring->dirty, 1, 0); - - if (hw_ops->is_last_desc(dma_desc)) { - tx_packets += desc_data->tx.packets; - tx_bytes += desc_data->tx.bytes; - } - - /* Free the SKB and reset the descriptor for re-use */ - desc_ops->unmap_desc_data(pdata, desc_data); - hw_ops->tx_desc_reset(desc_data); - - processed++; - //ring->dirty++; - ring->dirty = FXGMAC_GET_ENTRY(ring->dirty, ring->dma_desc_count); - } - - if (!processed) - return 0; - - netdev_tx_completed_queue(txq, tx_packets, tx_bytes); - - if ((ring->tx.queue_stopped == 1) && - (fxgmac_tx_avail_desc(ring) > FXGMAC_TX_DESC_MIN_FREE)) { - ring->tx.queue_stopped = 0; - netif_tx_wake_queue(txq); - } - - //yzhang comment out to reduce print - if(netif_msg_tx_done(pdata)){ - DPRINTK("tx_poll callout, processed=%d\n", processed); - } - - return processed; -} -extern void fxgmac_print_pkt(struct net_device *netdev, - struct sk_buff *skb, bool tx_rx); - -static int fxgmac_rx_poll(struct fxgmac_channel *channel, int budget) -{ - struct fxgmac_pdata *pdata = channel->pdata; - struct fxgmac_ring *ring = channel->rx_ring; - struct net_device *netdev = pdata->netdev; - unsigned int len; - unsigned int context_next, context; - struct fxgmac_desc_data *desc_data; - struct fxgmac_pkt_info *pkt_info; - unsigned int incomplete; - struct fxgmac_hw_ops *hw_ops; - struct napi_struct *napi; - struct sk_buff *skb; - int packet_count = 0; - u32 ipce,iphe; - - hw_ops = &pdata->hw_ops; - - /* Nothing to do if there isn't a Rx ring for this channel */ - if (!ring) - return 0; - - incomplete = 0; - context_next = 0; - - napi = (pdata->per_channel_irq) ? &channel->expansion.napi_rx : &pdata->expansion.napi; - - desc_data = FXGMAC_GET_DESC_DATA(ring, ring->cur); - pkt_info = &ring->pkt_info; - - while (packet_count < budget) { - memset(pkt_info, 0, sizeof(*pkt_info)); - skb = NULL; - len = 0; - - read_again: - desc_data = FXGMAC_GET_DESC_DATA(ring, ring->cur); - - if (fxgmac_rx_dirty_desc(ring) > FXGMAC_RX_DESC_MAX_DIRTY) - fxgmac_rx_refresh(channel); - - if (hw_ops->dev_read(channel)) - break; - - ring->cur = FXGMAC_GET_ENTRY(ring->cur, ring->dma_desc_count); - - incomplete = FXGMAC_GET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_INCOMPLETE_POS, - RX_PACKET_ATTRIBUTES_INCOMPLETE_LEN); - context_next = FXGMAC_GET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_POS, - RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_LEN); - context = FXGMAC_GET_REG_BITS( - pkt_info->attributes, - RX_PACKET_ATTRIBUTES_CONTEXT_POS, - RX_PACKET_ATTRIBUTES_CONTEXT_LEN); - - if (incomplete || context_next) - goto read_again; - - if (pkt_info->errors) { - netif_err(pdata, rx_err, netdev, "error in received packet\n"); - dev_kfree_skb(skb); - goto next_packet; - } - - if (!context) { - len = desc_data->rx.len; - if (len > pdata->rx_buf_size) { - if (net_ratelimit()) - netdev_err(pdata->netdev,"len %d larger than size (%d)\n", len, pdata->rx_buf_size); - pdata->netdev->stats.rx_dropped++; - goto next_packet; - } - - if (len == 0) { - if (net_ratelimit()) - netdev_err(pdata->netdev,"A packet of length 0 was received\n"); - pdata->netdev->stats.rx_length_errors++; - goto next_packet; - } - - if (len && !skb) { - skb = fxgmac_create_skb(pdata, napi, desc_data, len); - if (unlikely(!skb)) { - if (net_ratelimit()) - netdev_warn(pdata->netdev, "create skb failed\n"); - goto next_packet; - } - } - } - - if (!skb) - goto next_packet; - - if(netif_msg_pktdata(pdata)) - fxgmac_print_pkt(netdev, skb, false); - - skb_checksum_none_assert(skb); - if (netdev->features & NETIF_F_RXCSUM) - { - ipce = FXGMAC_GET_REG_BITS_LE(desc_data->dma_desc->desc1, - RX_NORMAL_DESC1_WB_IPCE_POS, - RX_NORMAL_DESC1_WB_IPCE_LEN); - iphe = FXGMAC_GET_REG_BITS_LE(desc_data->dma_desc->desc1, - RX_NORMAL_DESC1_WB_IPHE_POS, - RX_NORMAL_DESC1_WB_IPHE_LEN); - /* if csum error,let the stack verify checksum errors.otherwise don't verify */ - if (!ipce && !iphe && FXGMAC_GET_REG_BITS(pkt_info->attributes, - RX_PACKET_ATTRIBUTES_CSUM_DONE_POS, - RX_PACKET_ATTRIBUTES_CSUM_DONE_LEN)) - skb->ip_summed = CHECKSUM_UNNECESSARY; - } - - if (FXGMAC_GET_REG_BITS(pkt_info->attributes, - RX_PACKET_ATTRIBUTES_VLAN_CTAG_POS, - RX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN)) { - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), - pkt_info->vlan_ctag); - pdata->stats.rx_vlan_packets++; - } - - if (FXGMAC_GET_REG_BITS(pkt_info->attributes, - RX_PACKET_ATTRIBUTES_RSS_HASH_POS, - RX_PACKET_ATTRIBUTES_RSS_HASH_LEN)) - skb_set_hash(skb, pkt_info->rss_hash, - pkt_info->rss_hash_type); - - skb->dev = netdev; - skb->protocol = eth_type_trans(skb, netdev); - skb_record_rx_queue(skb, channel->queue_index); - - if(pdata->expansion.fxgmac_test_tso_flag) - { - /* tso test */ - if(pdata->expansion.fxgmac_test_tso_seg_num == 1) - { - /* last segment */ - if(pdata->expansion.fxgmac_test_last_tso_len == skb->len + FXGMAC_TEST_MAC_HEAD_LEN) - { - /* receive last segment, reset flag */ - pdata->expansion.fxgmac_test_tso_flag = false; - pdata->expansion.fxgmac_test_tso_seg_num = 0; - pdata->expansion.fxgmac_test_packet_len = 0; - pdata->expansion.fxgmac_test_last_tso_len = 0; - - /* process packet */ - if((pdata->expansion.fxgmac_test_skb_arr_in_index + 1) % FXGMAC_MAX_DBG_TEST_PKT != pdata->expansion.fxgmac_test_skb_arr_out_index){ - struct sk_buff *tmpskb = skb_copy(skb, GFP_ATOMIC); - skb_push(tmpskb, FXGMAC_TEST_MAC_HEAD_LEN); - - pdata->expansion.fxgmac_test_skb_array[pdata->expansion.fxgmac_test_skb_arr_in_index] = tmpskb; - pdata->expansion.fxgmac_test_skb_arr_in_index = (pdata->expansion.fxgmac_test_skb_arr_in_index + 1) % FXGMAC_MAX_DBG_TEST_PKT; - } - else{ - DPRINTK("loopback test buffer is full."); - } - } - } - else /* non last segment */ - { - if(pdata->expansion.fxgmac_test_packet_len == skb->len + FXGMAC_TEST_MAC_HEAD_LEN){ - /* receive a segment */ - pdata->expansion.fxgmac_test_tso_seg_num--; - - /* process packet */ - if((pdata->expansion.fxgmac_test_skb_arr_in_index + 1) % FXGMAC_MAX_DBG_TEST_PKT != pdata->expansion.fxgmac_test_skb_arr_out_index){ - struct sk_buff *tmpskb = skb_copy(skb, GFP_ATOMIC); - skb_push(tmpskb, FXGMAC_TEST_MAC_HEAD_LEN); - - pdata->expansion.fxgmac_test_skb_array[pdata->expansion.fxgmac_test_skb_arr_in_index] = tmpskb; - pdata->expansion.fxgmac_test_skb_arr_in_index = (pdata->expansion.fxgmac_test_skb_arr_in_index + 1) % FXGMAC_MAX_DBG_TEST_PKT; - } - else{ - DPRINTK("loopback test buffer is full."); - } - } - } - } - else if(pdata->expansion.fxgmac_test_packet_len != 0) - { - /* xsum and phy loopback test */ - if(pdata->expansion.fxgmac_test_packet_len == skb->len + FXGMAC_TEST_MAC_HEAD_LEN) - { - /* reset fxg_packet_len */ - pdata->expansion.fxgmac_test_packet_len = 0; - - if((pdata->expansion.fxgmac_test_skb_arr_in_index + 1) % FXGMAC_MAX_DBG_TEST_PKT != pdata->expansion.fxgmac_test_skb_arr_out_index){ - struct sk_buff *tmpskb = skb_copy(skb, GFP_ATOMIC); - skb_push(tmpskb, FXGMAC_TEST_MAC_HEAD_LEN); - - pdata->expansion.fxgmac_test_skb_array[pdata->expansion.fxgmac_test_skb_arr_in_index] = tmpskb; - pdata->expansion.fxgmac_test_skb_arr_in_index = (pdata->expansion.fxgmac_test_skb_arr_in_index + 1) % FXGMAC_MAX_DBG_TEST_PKT; - } - else{ - DPRINTK("loopback test buffer is full."); - } - } - } -#if 1 - napi_gro_receive(napi, skb); -#else - netif_receive_skb(skb); -#endif - -next_packet: - packet_count++; - - pdata->netdev->stats.rx_packets++; - pdata->netdev->stats.rx_bytes += len; - } - - fxgmac_rx_refresh(channel); - - return packet_count; -} - -static int fxgmac_one_poll_tx(struct napi_struct *napi, int budget) -{ - struct fxgmac_channel *channel = container_of(napi, - struct fxgmac_channel, - expansion.napi_tx); - int ret = 0; - struct fxgmac_pdata *pdata = channel->pdata; - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - - ret = fxgmac_tx_poll(channel); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) - if (napi_complete_done(napi, 0)) { - hw_ops->enable_msix_one_interrupt(pdata, MSI_ID_TXQ0); - } -#else - napi_complete(napi); - hw_ops->enable_msix_one_interrupt(pdata, MSI_ID_TXQ0); -#endif - return 0; - -} - -static int fxgmac_one_poll_rx(struct napi_struct *napi, int budget) -{ - struct fxgmac_channel *channel = container_of(napi, - struct fxgmac_channel, - expansion.napi_rx); - int processed = 0; - struct fxgmac_pdata *pdata = channel->pdata; - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - - processed = fxgmac_rx_poll(channel, budget); - if (processed < budget) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) - /* if there no interrupt occured when this interrupt running,struct napi's state is NAPIF_STATE_SCHED, - * napi_complete_done return true and we can enable irq,it will not cause unbalanced iqr issure. - * if there more interrupt occured when this interrupt running,struct napi's state is NAPIF_STATE_SCHED | NAPIF_STATE_MISSED - * because napi_schedule_prep will make it. At this time napi_complete_done will return false and - * schedule poll again because of NAPIF_STATE_MISSED,it will cause unbalanced irq issure. - */ - if (napi_complete_done(napi, processed)) { - hw_ops->enable_msix_one_interrupt(pdata, channel->queue_index); - } -#else - napi_complete(napi); - hw_ops->enable_msix_one_interrupt(pdata, channel->queue_index); -#endif - } - - return processed; -} - -static int fxgmac_all_poll(struct napi_struct *napi, int budget) -{ - struct fxgmac_pdata *pdata = container_of(napi, - struct fxgmac_pdata, - expansion.napi); - struct fxgmac_channel *channel; - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - int processed; - unsigned int i; - - //yzhang comment out - if(netif_msg_rx_status(pdata)){ - DPRINTK("rx all_poll callin budget=%d\n", budget); - } - - processed = 0; - do { - channel = pdata->channel_head; - /* Cleanup Tx ring first */ - /*since only 1 tx channel supported in this version, poll ch 0 always. */ - fxgmac_tx_poll(pdata->channel_head + 0); - for (i = 0; i < pdata->channel_count; i++, channel++) { - processed += fxgmac_rx_poll(channel, budget); - } - } while (false); - - // for phy, we needn't to process any packet,so processed will be 0 - if (pdata->expansion.mgm_intctrl_val & MGMT_INT_CTRL0_INT_STATUS_PHY) { - fxgmac_phy_process(pdata); - pdata->expansion.mgm_intctrl_val &= ~MGMT_INT_CTRL0_INT_STATUS_PHY; - } - - /* If we processed everything, we are done */ - if (processed < budget) { - /* Turn off polling */ - if (napi_complete_done(napi, processed)) - hw_ops->enable_mgm_interrupt(pdata); - } - - if((processed) && (netif_msg_rx_status(pdata))) { //yzhang for debug - DPRINTK("rx all_poll callout received = %d\n", processed); - } - - return processed; -} diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-pci.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-pci.c deleted file mode 100644 index 7233de3438d7e..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-pci.c +++ /dev/null @@ -1,365 +0,0 @@ -/*++ - -Copyright (c) 2021 Motor-comm Corporation. -Confidential and Proprietary. All rights reserved. - -This is Motor-comm Corporation NIC driver relevant files. Please don't copy, modify, -distribute without commercial permission. - ---*/ - - -#include -#include -#include - -/* for file operation */ -#include - -#include "fuxi-gmac.h" -#include "fuxi-gmac-reg.h" - -#define FXGMAC_DBG 0 -/* for power state debug using, 20210629. */ -#if FXGMAC_DBG -static struct file *dbg_file = NULL; -#define FXGMAC_DBG_BUF_SIZE 128 -static char log_buf[FXGMAC_DBG_BUF_SIZE + 2]; -#endif - -#if FXGMAC_DBG -static char * file_name = "/home/fxgmac/fxgmac_dbg.log"; -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,13,0)) -#if FXGMAC_DBG -#define fxgmac_dbg_log(logstr, arg...) \ - do { \ - static struct kstat dbg_stat; \ - static loff_t pos = 0; \ - if (!(IS_ERR(dbg_file))) { \ - mm_segment_t previous_fs; /*for address-space switch */ \ - sprintf (&log_buf[0], (logstr), ##arg); \ - previous_fs = get_fs(); \ - set_fs(KERNEL_DS); \ - vfs_stat(file_name, &dbg_stat); \ - pos = (loff_t)dbg_stat.size; \ - kernel_write(dbg_file, (const char*)log_buf, strlen(log_buf) > FXGMAC_DBG_BUF_SIZE ? FXGMAC_DBG_BUF_SIZE : strlen(log_buf), /*&dbg_file->f_pos*/&pos)/**/; \ - /*DPRINTK("kernel write done, file size=%d, s=%s", (int)dbg_stat.size, log_buf)*/; \ - set_fs(previous_fs); \ - /*dbg_file->f_op->flush(dbg_file)*/; \ - } \ - }while(0) -#else -#define fxgmac_dbg_log(logstr, arg...) \ - do { \ - /*nothing*/; \ - }while(0) -#endif - -#else -#if FXGMAC_DBG -/* in kernel 5.14, get_fs/set_fs are removed. */ -#define fxgmac_dbg_log(logstr, arg...) \ - do { \ - static struct kstat dbg_stat; \ - static loff_t pos = 0; \ - fxgmac_dbg_log_init(); \ - if (!(IS_ERR(dbg_file))) { \ - sprintf (&log_buf[0], (logstr), ##arg); \ - vfs_getattr(&(dbg_file->f_path), &dbg_stat, 0, 0); \ - pos = (loff_t)dbg_stat.size; \ - kernel_write(dbg_file, (const char*)log_buf, strlen(log_buf) > FXGMAC_DBG_BUF_SIZE ? FXGMAC_DBG_BUF_SIZE : strlen(log_buf), /*&dbg_file->f_pos*/&pos)/**/; \ - /*DPRINTK("kernel write done, file size=%d, s=%s", (int)dbg_stat.size, log_buf)*/; \ - /*dbg_file->f_op->flush(dbg_file)*/; \ - } \ - fxgmac_dbg_log_uninit();\ - }while(0) - -#else -#define fxgmac_dbg_log(logstr, arg...) \ - do { \ - /*nothing*/; \ - }while(0) -#endif -#endif - -/* declarations */ -static void fxgmac_shutdown(struct pci_dev *pdev); - -/* - * functions definitions - */ -int fxgmac_dbg_log_init( void ) -{ -#if FXGMAC_DBG - dbg_file = filp_open(file_name, O_RDWR | O_CREAT, 0644); - if (IS_ERR(dbg_file)) - { - DPRINTK("File fxgmac_dbg.log open or created failed.\n"); - return PTR_ERR(dbg_file); - } -#endif - - return 0; -} - -int fxgmac_dbg_log_uninit( void ) -{ -#if FXGMAC_DBG - if(IS_ERR(dbg_file)) - { - DPRINTK("Invalid fd for file fxgmac_dbg.log, %p.\n", dbg_file); - dbg_file= NULL; - return PTR_ERR(dbg_file); - } - - filp_close(dbg_file, NULL); - dbg_file= NULL; -#endif - - return 0; -} - -static int fxgmac_probe(struct pci_dev *pcidev, const struct pci_device_id *id) -{ - struct device *dev = &pcidev->dev; - struct fxgmac_resources res; - int i, ret; - - ret = pcim_enable_device(pcidev); - if (ret) { - dev_err(dev, "ERROR: fxgmac_probe failed to enable device\n"); - return ret; - } - - for (i = 0; i <= PCI_STD_RESOURCE_END; i++) { - if (pci_resource_len(pcidev, i) == 0) - continue; - - ret = pcim_iomap_regions(pcidev, BIT(i), FXGMAC_DRV_NAME); - if (ret) - { - DPRINTK(KERN_INFO "fxgmac_probe pcim_iomap_regions failed\n"); - return ret; - } - DPRINTK(KERN_INFO "fxgmac_probe iomap_region i=%#x,ret=%#x\n",(int)i,(int)ret); - break; - } - - pci_set_master(pcidev); - - memset(&res, 0, sizeof(res)); - res.irq = pcidev->irq; - res.addr = pcim_iomap_table(pcidev)[i]; - - //fxgmac_dbg_log_init(); - fxgmac_dbg_log("fxpm,_fxgmac_probe\n"); - - return fxgmac_drv_probe(&pcidev->dev, &res); -} - -static void fxgmac_remove(struct pci_dev *pcidev) -{ - struct net_device *netdev = dev_get_drvdata(&pcidev->dev); - struct fxgmac_pdata * pdata = netdev_priv(netdev); - -#ifdef CONFIG_PCI_MSI - u32 msix = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, - FXGMAC_FLAG_MSIX_POS, - FXGMAC_FLAG_MSIX_LEN); -#endif - - fxgmac_drv_remove(&pcidev->dev); -#ifdef CONFIG_PCI_MSI - if(msix){ - pci_disable_msix(pcidev); - kfree(pdata->expansion.msix_entries); - pdata->expansion.msix_entries = NULL; - } -#endif - - fxgmac_dbg_log("fxpm,_fxgmac_remove\n"); - -#ifdef HAVE_FXGMAC_DEBUG_FS - fxgmac_dbg_exit(pdata); -#endif /* HAVE_FXGMAC_DEBUG_FS */ - - //fxgmac_dbg_log_uninit(); -} - -/* for Power management, 20210628 */ -static int __fxgmac_shutdown(struct pci_dev *pdev, bool *enable_wake) -{ - struct net_device *netdev = dev_get_drvdata(&pdev->dev); - struct fxgmac_pdata *pdata = netdev_priv(netdev); - u32 wufc = pdata->expansion.wol; -#ifdef CONFIG_PM - int retval = 0; -#endif - - DPRINTK("fxpm,_fxgmac_shutdown, callin\n"); - fxgmac_dbg_log("fxpm,_fxgmac_shutdown, callin.\n"); - - rtnl_lock(); - - /* for linux shutdown, we just treat it as power off wol can be ignored - * for suspend, we do need recovery by wol - */ - fxgmac_net_powerdown(pdata, (unsigned int)!!wufc); - netif_device_detach(netdev); - rtnl_unlock(); - -#ifdef CONFIG_PM - retval = pci_save_state(pdev); - if (retval) { - DPRINTK("fxpm,_fxgmac_shutdown, save pci state failed.\n"); - return retval; - } -#endif - - DPRINTK("fxpm,_fxgmac_shutdown, save pci state done.\n"); - fxgmac_dbg_log("fxpm,_fxgmac_shutdown, save pci state done.\n"); - - pci_wake_from_d3(pdev, !!wufc); - *enable_wake = !!wufc; - - pci_disable_device(pdev); - - DPRINTK("fxpm,_fxgmac_shutdown callout, enable wake=%d.\n", *enable_wake); - fxgmac_dbg_log("fxpm,_fxgmac_shutdown callout, enable wake=%d.\n", *enable_wake); - - return 0; -} - -static void fxgmac_shutdown(struct pci_dev *pdev) -{ - bool wake; - struct net_device *netdev = dev_get_drvdata(&pdev->dev); - struct fxgmac_pdata *pdata = netdev_priv(netdev); - - DPRINTK("fxpm, fxgmac_shutdown callin\n"); - fxgmac_dbg_log("fxpm, fxgmac_shutdown callin\n"); - - pdata->expansion.current_state = CURRENT_STATE_SHUTDOWN; - __fxgmac_shutdown(pdev, &wake); - - if (system_state == SYSTEM_POWER_OFF) { - pci_wake_from_d3(pdev, wake); - pci_set_power_state(pdev, PCI_D3hot); - } - DPRINTK("fxpm, fxgmac_shutdown callout, system power off=%d\n", (system_state == SYSTEM_POWER_OFF)? 1 : 0); - fxgmac_dbg_log("fxpm, fxgmac_shutdown callout, system power off=%d\n", (system_state == SYSTEM_POWER_OFF)? 1 : 0); -} - -#ifdef CONFIG_PM -/* yzhang, 20210628 for PM */ -static int fxgmac_suspend(struct pci_dev *pdev, - pm_message_t __always_unused state) -{ - int retval; - bool wake; - struct net_device *netdev = dev_get_drvdata(&pdev->dev); - struct fxgmac_pdata *pdata = netdev_priv(netdev); - - DPRINTK("fxpm, fxgmac_suspend callin\n"); - fxgmac_dbg_log("fxpm, fxgmac_suspend callin\n"); - - pdata->expansion.current_state = CURRENT_STATE_SUSPEND; - - if (netif_running(netdev)) { - retval = __fxgmac_shutdown(pdev, &wake); - if (retval) - return retval; - } else { - wake = !!(pdata->expansion.wol); - } - - if (wake) { - pci_prepare_to_sleep(pdev); - } else { - pci_wake_from_d3(pdev, false); - pci_set_power_state(pdev, PCI_D3hot); - } - - DPRINTK("fxpm, fxgmac_suspend callout to %s\n", wake ? "sleep" : "D3hot"); - fxgmac_dbg_log("fxpm, fxgmac_suspend callout to %s\n", wake ? "sleep" : "D3hot"); - - return 0; -} - -static int fxgmac_resume(struct pci_dev *pdev) -{ - struct fxgmac_pdata *pdata; - struct net_device *netdev; - u32 err; - - DPRINTK("fxpm, fxgmac_resume callin\n"); - fxgmac_dbg_log("fxpm, fxgmac_resume callin\n"); - - netdev = dev_get_drvdata(&pdev->dev); - pdata = netdev_priv(netdev); - - pdata->expansion.current_state = CURRENT_STATE_RESUME; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - /* - * pci_restore_state clears dev->state_saved so call - * pci_save_state to restore it. - */ - pci_save_state(pdev); - - err = pci_enable_device_mem(pdev); - if (err) { - dev_err(pdata->dev, "fxgmac_resume, failed to enable PCI device from suspend\n"); - return err; - } - smp_mb__before_atomic(); - __clear_bit(FXGMAC_POWER_STATE_DOWN, &pdata->expansion.powerstate); - pci_set_master(pdev); - - pci_wake_from_d3(pdev, false); - - rtnl_lock(); - err = 0;//ixgbe_init_interrupt_scheme(adapter); - if (!err && netif_running(netdev)) - fxgmac_net_powerup(pdata); - - if (!err) - netif_device_attach(netdev); - - rtnl_unlock(); - - DPRINTK("fxpm, fxgmac_resume callout\n"); - fxgmac_dbg_log("fxpm, fxgmac_resume callout\n"); - - return err; -} -#endif - -static const struct pci_device_id fxgmac_pci_tbl[] = { - { PCI_DEVICE(0x1f0a, 0x6801) }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, fxgmac_pci_tbl); - -static struct pci_driver fxgmac_pci_driver = { - .name = FXGMAC_DRV_NAME, - .id_table = fxgmac_pci_tbl, - .probe = fxgmac_probe, - .remove = fxgmac_remove, -#ifdef CONFIG_PM - /* currently, we only use USE_LEGACY_PM_SUPPORT */ - .suspend = fxgmac_suspend, - .resume = fxgmac_resume, -#endif - .shutdown = fxgmac_shutdown, -}; - -module_pci_driver(fxgmac_pci_driver); - -MODULE_DESCRIPTION(FXGMAC_DRV_DESC); -MODULE_VERSION(FXGMAC_DRV_VERSION); -MODULE_AUTHOR("Frank "); -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-phy.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-phy.c deleted file mode 100644 index 59b017a37f41e..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-phy.c +++ /dev/null @@ -1,422 +0,0 @@ -/*++ - -Copyright (c) 2021 Motor-comm Corporation. -Confidential and Proprietary. All rights reserved. - -This is Motor-comm Corporation NIC driver relevant files. Please don't copy, modify, -distribute without commercial permission. - ---*/ - - -#include -#include - -#include "fuxi-gmac.h" -#include "fuxi-gmac-reg.h" - -void fxgmac_phy_force_speed(struct fxgmac_pdata *pdata, int speed) -{ - struct fxgmac_hw_ops* hw_ops = &pdata->hw_ops; - u32 regval = 0; - unsigned int high_bit = 0, low_bit = 0; - - switch (speed) - { - case SPEED_1000: - high_bit = 1, low_bit = 0; - break; - case SPEED_100: - high_bit = 0, low_bit = 1; - break; - case SPEED_10: - high_bit = 0, low_bit = 0; - break; - default: - break; - } - - /* disable autoneg */ - hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, ®val); - regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_AUTOENG_POS, PHY_CR_AUTOENG_LEN, 0); - regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_SPEED_SEL_H_POS, PHY_CR_SPEED_SEL_H_LEN, high_bit); - regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_SPEED_SEL_L_POS, PHY_CR_SPEED_SEL_L_LEN, low_bit); - hw_ops->write_ephy_reg(pdata, REG_MII_BMCR, regval); - -} - -void fxgmac_phy_force_duplex(struct fxgmac_pdata *pdata, int duplex) -{ - struct fxgmac_hw_ops* hw_ops = &pdata->hw_ops; - u32 regval = 0; - hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, ®val); - regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_DUPLEX_POS, PHY_CR_DUPLEX_LEN, (duplex ? 1 : 0)); - hw_ops->write_ephy_reg(pdata, REG_MII_BMCR, regval); - -} - -void fxgmac_phy_force_autoneg(struct fxgmac_pdata *pdata, int autoneg) -{ - struct fxgmac_hw_ops* hw_ops = &pdata->hw_ops; - u32 regval = 0; - hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, ®val); - regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_AUTOENG_POS, PHY_CR_AUTOENG_LEN, (autoneg? 1 : 0)); - hw_ops->write_ephy_reg(pdata, REG_MII_BMCR, regval); -} - - -/* - * input: lport - * output: - * cap_mask, bit definitions: - * pause capbility and 100/10 capbilitys follow the definition of mii reg4. - * for 1000M capability, bit0=1000M half; bit1=1000M full, refer to mii reg9.[9:8]. - */ -int fxgmac_ephy_autoneg_ability_get(struct fxgmac_pdata *pdata, unsigned int *cap_mask) -{ - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - unsigned int val; - unsigned int reg; - - if((!hw_ops->read_ephy_reg) || (!hw_ops->write_ephy_reg)) - return -1; - - reg = REG_MII_ADVERTISE; - if(hw_ops->read_ephy_reg(pdata, reg, &val) < 0) - goto busy_exit; - - //DPRINTK("fxgmac_ephy_autoneg_ability_get, reg %d=0x%04x\n", reg, val); - - if(FXGMAC_ADVERTISE_10HALF & val) - { - *cap_mask |= FXGMAC_ADVERTISE_10HALF; - } - else - { - *cap_mask &= ~FXGMAC_ADVERTISE_10HALF; - } - - if(FXGMAC_ADVERTISE_10FULL & val) - { - *cap_mask |= FXGMAC_ADVERTISE_10FULL; - } - else - { - *cap_mask &= ~FXGMAC_ADVERTISE_10FULL; - } - - if(FXGMAC_ADVERTISE_100HALF & val) - { - *cap_mask |= FXGMAC_ADVERTISE_100HALF; - } - else - { - *cap_mask &= ~FXGMAC_ADVERTISE_100HALF; - } - - if(FXGMAC_ADVERTISE_100FULL & val) - { - *cap_mask |= FXGMAC_ADVERTISE_100FULL; - } - else - { - *cap_mask &= ~FXGMAC_ADVERTISE_100FULL; - } - - if(FXGMAC_ADVERTISE_PAUSE_CAP & val) - { - *cap_mask |= FXGMAC_ADVERTISE_PAUSE_CAP; - } - else - { - *cap_mask &= ~FXGMAC_ADVERTISE_PAUSE_CAP; - } - - if(FXGMAC_ADVERTISE_PAUSE_ASYM & val) - { - *cap_mask |= FXGMAC_ADVERTISE_PAUSE_ASYM; - } - else - { - *cap_mask &= ~FXGMAC_ADVERTISE_PAUSE_ASYM; - } - - reg = REG_MII_CTRL1000; - if(hw_ops->read_ephy_reg(pdata, reg, &val) < 0) - goto busy_exit; - - //DPRINTK("fxgmac_ephy_autoneg_ability_get, reg %d=0x%04x\n", reg, val); - if(REG_BIT_ADVERTISE_1000HALF & val ) - { - *cap_mask |= FXGMAC_ADVERTISE_1000HALF; - } - else - { - *cap_mask &= ~FXGMAC_ADVERTISE_1000HALF; - } - - if(REG_BIT_ADVERTISE_1000FULL & val ) - { - *cap_mask |= FXGMAC_ADVERTISE_1000FULL; - } - else - { - *cap_mask &= ~FXGMAC_ADVERTISE_1000FULL; - } - - //DPRINTK("fxgmac_ephy_autoneg_ability_get done, 0x%08x.\n", *cap_mask); - - return 0; - -busy_exit: - DPRINTK("fxgmac_ephy_autoneg_ability_get exit due to ephy reg access fail.\n"); - - return -1; -} - -int fxgmac_ephy_soft_reset(struct fxgmac_pdata *pdata) -{ - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - int ret; - volatile unsigned int val; - int busy = 15; - - ret = hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, (unsigned int *)&val); - if (0 > ret) - goto busy_exit; - - ret = hw_ops->write_ephy_reg(pdata, REG_MII_BMCR, (val | 0x8000)); - if (0 > ret) - goto busy_exit; - - do { - ret = hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, (unsigned int *)&val); - busy--; - //DPRINTK("fxgmac_ephy_soft_reset, check busy=%d.\n", busy); - }while((ret >= 0) && (0 != (val & 0x8000)) && (busy)); - - if(0 == (val & 0x8000)) return 0; - - DPRINTK("fxgmac_ephy_soft_reset, timeout, busy=%d.\n", busy); - return -EBUSY; - -busy_exit: - DPRINTK("fxgmac_ephy_soft_reset exit due to ephy reg access fail.\n"); - - return ret; -} - -/* this function used to double check the speed. for fiber, to correct there is no 10M */ -static int fxgmac_ephy_adjust_status(u32 lport, int val, int is_utp, int* speed, int* duplex) -{ - int speed_mode; - - *speed = -1; - *duplex = (val & BIT(FUXI_EPHY_DUPLEX_BIT)) >> FUXI_EPHY_DUPLEX_BIT; - speed_mode = (val & FUXI_EPHY_SPEED_MODE) >> FUXI_EPHY_SPEED_MODE_BIT; - switch (speed_mode) { - case 0: - if (is_utp) - *speed = SPEED_10M; - break; - case 1: - *speed = SPEED_100M; - break; - case 2: - *speed = SPEED_1000M; - break; - case 3: - break; - default: - break; - } - - return 0; -} - -/* - * this function for polling to get status of ephy link. - * output: - * speed: SPEED_10M, SPEED_100M, SPEED_1000M or -1; - * duplex: 0 or 1, see reg 0x11, bit YT8614_DUPLEX_BIT. - * ret_link: 0 or 1, link down or up. - * media: only valid when ret_link=1, (YT8614_SMI_SEL_SDS_SGMII + 1) for fiber; (YT8614_SMI_SEL_PHY + 1) for utp. -1 for link down. - */ -int fxgmac_ephy_status_get(struct fxgmac_pdata *pdata, int* speed, int* duplex, int* ret_link, int *media) -{ - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - int ret; - u16 reg; - volatile unsigned int val; - volatile int link; - int link_utp = 0, link_fiber = 0; - - reg = REG_MII_SPEC_STATUS; - ret = hw_ops->read_ephy_reg(pdata, reg, (unsigned int *)&val); - if (0 > ret) - goto busy_exit; - - link = val & (BIT(FUXI_EPHY_LINK_STATUS_BIT)); - if (link) { - link_utp = 1; - fxgmac_ephy_adjust_status(0, val, 1, speed, duplex); - } else { - link_utp = 0; - } - - if (link_utp || link_fiber) { - /* case of fiber of priority */ - if(link_utp) *media = (FUXI_EPHY_SMI_SEL_PHY + 1); - if(link_fiber) *media = (FUXI_EPHY_SMI_SEL_SDS_SGMII + 1); - - *ret_link = 1; - } else - { - *ret_link = 0; - *media = -1; - *speed= -1; - *duplex = -1; - } - - return 0; - -busy_exit: - DPRINTK("fxgmac_ephy_status_get exit due to ephy reg access fail.\n"); - - return ret; -} - -#if 0 -/** - * fxgmac_phy_update_link - update the phy link status - * @adapter: pointer to the device adapter structure - **/ -static void fxgmac_phy_update_link(struct net_device *netdev) -{ - struct fxgmac_pdata *pdata = netdev_priv(netdev); - struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; - bool b_linkup = false; - u32 phy_speed = 0, ephy_val1, ephy_val2; - u32 pre_phy_speed = 0xff; - - if (hw_ops->get_xlgmii_phy_status) { - hw_ops->get_xlgmii_phy_status(pdata, (u32*)&phy_speed, (bool *)&b_linkup, 0); - } else { - /* always assume link is down, if no check link function */ - } - - pre_phy_speed = ((SPEED_1000 == pdata->phy_speed) ? 2 : ((SPEED_100 == pdata->phy_speed) ? 1 : 0) ); - - if(pre_phy_speed != phy_speed) - { - DPRINTK("fuxi_phy link phy speed changed,%d->%d\n", pre_phy_speed, phy_speed); - switch(phy_speed){ - case 2: - pdata->phy_speed = SPEED_1000; - break; - case 1: - pdata->phy_speed = SPEED_100; - break; - case 0: - pdata->phy_speed = SPEED_10; - break; - default: - pdata->phy_speed = SPEED_1000; - break; - } - fxgmac_config_mac_speed(pdata); - pre_phy_speed = phy_speed; - } - - if(pdata->phy_link != b_linkup) - { - pdata->phy_link = b_linkup; - fxgmac_act_phy_link(pdata); - - if(b_linkup && (hw_ops->read_ephy_reg)) - { - hw_ops->read_ephy_reg(pdata, 0x1/* ephy latched status */, (unsigned int *)&ephy_val1); - hw_ops->read_ephy_reg(pdata, 0x1/* ephy latched status */, (unsigned int *)&ephy_val2); - DPRINTK("%s phy reg1=0x%04x, 0x%04x\n", __FUNCTION__, ephy_val1 & 0xffff, ephy_val2 & 0xffff); - } - } -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,15,0)) -static void fxgmac_phy_link_poll(struct timer_list *t) -#else -static void fxgmac_phy_link_poll(unsigned long data) -#endif -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,15,0)) - struct fxgmac_pdata *pdata = from_timer(pdata, t, expansion.phy_poll_tm); -#else - struct fxgmac_pdata *pdata = (struct fxgmac_pdata*)data; -#endif - - if(NULL == pdata->netdev) - { - DPRINTK("fuxi_phy_timer polling with NULL netdev %lx\n",(unsigned long)(pdata->netdev)); - return; - } - - pdata->stats.ephy_poll_timer_cnt++; - -#if FXGMAC_PM_FEATURE_ENABLED - /* 20210709 for net power down */ - if(!test_bit(FXGMAC_POWER_STATE_DOWN, &pdata->expansion.powerstate)) -#endif - { - //yzhang if(2 > pdata->stats.ephy_poll_timer_cnt) - { - mod_timer(&pdata->phy_poll_tm,jiffies + HZ / 2); - } - fxgmac_phy_update_link(pdata->netdev); - }else { - DPRINTK("fuxi_phy_timer polling, powerstate changed, %ld, netdev=%lx, tm=%lx\n", pdata->expansion.powerstate, (unsigned long)(pdata->netdev), (unsigned long)&pdata->phy_poll_tm); - } - - //DPRINTK("fuxi_phy_timer polled,%d\n",cnt_polling); -} - -/* - * used when fxgmac is powerdown and resume - * 20210709 for net power down - */ -void fxgmac_phy_timer_resume(struct fxgmac_pdata *pdata) -{ - if(NULL == pdata->netdev) - { - DPRINTK("fxgmac_phy_timer_resume, failed due to NULL netdev %lx\n",(unsigned long)(pdata->netdev)); - return; - } - - mod_timer(&pdata->phy_poll_tm,jiffies + HZ / 2); - - DPRINTK("fxgmac_phy_timer_resume ok, fxgmac powerstate=%ld, netdev=%lx, tm=%lx\n", pdata->expansion.powerstate, (unsigned long)(pdata->netdev), (unsigned long)&pdata->phy_poll_tm); -} - -int fxgmac_phy_timer_init(struct fxgmac_pdata *pdata) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,15,0)) - init_timer_key(&pdata->phy_poll_tm,NULL/*function*/,0/*flags*/,"fuxi_phy_link_update_timer"/*name*/,NULL/*class lock key*/); -#else - init_timer_key(&pdata->phy_poll_tm,0/*flags*/,"fuxi_phy_link_update_timer"/*name*/,NULL/*class lock key*/); -#endif - pdata->phy_poll_tm.expires = jiffies + HZ / 2; - pdata->phy_poll_tm.function = (void *)(fxgmac_phy_link_poll); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) - pdata->phy_poll_tm.data = (unsigned long)pdata; -#endif - add_timer(&pdata->phy_poll_tm); - - DPRINTK("fuxi_phy_timer started, %lx\n", jiffies); - return 0; -} - -void fxgmac_phy_timer_destroy(struct fxgmac_pdata *pdata) -{ - del_timer_sync(&pdata->phy_poll_tm); - DPRINTK("fuxi_phy_timer removed\n"); -} -#endif diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-reg.h b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-reg.h deleted file mode 100644 index 5977de44f7b9e..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-reg.h +++ /dev/null @@ -1,1876 +0,0 @@ -/*++ - -Copyright (c) 2021 Motorcomm, Inc. -Motorcomm Confidential and Proprietary. - -This is Motorcomm NIC driver relevant files. Please don't copy, modify, -distribute without commercial permission. - ---*/ - -#ifndef __FUXI_GMAC_REG_H__ -#define __FUXI_GMAC_REG_H__ - -#define AISC_MODE - -#define FUXI_REV_01 0x01 // The first NTO version. -#define FUXI_REV_03 0x03 // ECO back on 07/2023. - -/* MAC register offsets */ -#define MAC_OFFSET 0x2000 -#define MAC_CR 0x0000 //The MAC Configuration Register -#define MAC_ECR 0x0004 -#define MAC_PFR 0x0008 -#define MAC_HTR0 0x0010 -#define MAC_VLANTR 0x0050 -#define MAC_VLANHTR 0x0058 -#define MAC_VLANIR 0x0060 -#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_TX_RX_STA 0x00b8 -#define MAC_PMT_STA 0x00c0 -#define MAC_RWK_PAC 0x00c4 // This is the FIFO address, the pointer will be increased automatically after writting. -#define MAC_LPI_STA 0x00d0 -#define MAC_LPI_CONTROL 0x00d4 -#define MAC_LPI_TIMER 0x00d8 -#define MAC_MS_TIC_COUNTER 0x00dc -#define MAC_AN_SR 0x00E4 -#define MAC_PHYIF_STA 0x00F8 -#define MAC_VR 0x0110 -#define MAC_DBG_STA 0x0114 -#define MAC_HWF0R 0x011c -#define MAC_HWF1R 0x0120 -#define MAC_HWF2R 0x0124 -#define MAC_HWF3R 0x0128 -#define MAC_MDIO_ADDRESS 0x0200 -#define MAC_MDIO_DATA 0x0204 -#define MAC_GPIO_SR 0x020c -#define MAC_ARP_PROTO_ADDR 0x0210 -#define MAC_CSR_SW_CTRL 0x0230 - -#define MAC_MACA0HR 0x0300 // mac[5]->bit15:8, mac[4]->bit7:0 -#define MAC_MACA0LR 0x0304 // mac[0]->bit7:0, mac[1]->bit15:8, mac[2]->bit23:16, mac[3]->bit31:24 - -#define MAC_MACA1HR 0x0308 -#define MAC_MACA1HR_AE_POS 31 -#define MAC_MACA1HR_AE_LEN 1 - -#define MAC_MACA1LR 0x030c - - -#define MAC_RSSCR 0x3c80//TODO -#define MAC_RSSAR 0x3c88//TODO -#define MAC_RSSDR 0x3c8c//TODO - - - -#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_POS 18 -#define MAC_HWF0R_ADDMACADRSEL_LEN 5 -#define MAC_HWF0R_ARPOFFSEL_POS 9 -#define MAC_HWF0R_ARPOFFSEL_LEN 1 -#define MAC_HWF0R_EEESEL_POS 13 -#define MAC_HWF0R_EEESEL_LEN 1 -#define MAC_HWF0R_ACTPHYIFSEL_POS 28 -#define MAC_HWF0R_ACTPHYIFSEL_LEN 3 -#define MAC_HWF0R_MGKSEL_POS 7 -#define MAC_HWF0R_MGKSEL_LEN 1 -#define MAC_HWF0R_MMCSEL_POS 8 -#define MAC_HWF0R_MMCSEL_LEN 1 -#define MAC_HWF0R_RWKSEL_POS 6 -#define MAC_HWF0R_RWKSEL_LEN 1 -#define MAC_HWF0R_RXCOESEL_POS 16 -#define MAC_HWF0R_RXCOESEL_LEN 1 -#define MAC_HWF0R_SAVLANINS_POS 27 -#define MAC_HWF0R_SAVLANINS_LEN 1 -#define MAC_HWF0R_SMASEL_POS 5 -#define MAC_HWF0R_SMASEL_LEN 1 -#define MAC_HWF0R_TSSEL_POS 12 -#define MAC_HWF0R_TSSEL_LEN 1 -#define MAC_HWF0R_TSSTSSEL_POS 25 -#define MAC_HWF0R_TSSTSSEL_LEN 2 -#define MAC_HWF0R_TXCOESEL_POS 14 -#define MAC_HWF0R_TXCOESEL_LEN 1 -#define MAC_HWF0R_VLHASH_POS 4 -#define MAC_HWF0R_VLHASH_LEN 1 -#define MAC_HWF1R_ADDR64_POS 14 -#define MAC_HWF1R_ADDR64_LEN 2 -#define MAC_HWF1R_ADVTHWORD_POS 13 -#define MAC_HWF1R_ADVTHWORD_LEN 1 -#define MAC_HWF1R_DBGMEMA_POS 19 -#define MAC_HWF1R_DBGMEMA_LEN 1 -#define MAC_HWF1R_DCBEN_POS 16 -#define MAC_HWF1R_DCBEN_LEN 1 -#define MAC_HWF1R_HASHTBLSZ_POS 24 -#define MAC_HWF1R_HASHTBLSZ_LEN 2 -#define MAC_HWF1R_L3L4FNUM_POS 27 -#define MAC_HWF1R_L3L4FNUM_LEN 4 -//#define MAC_HWF1R_NUMTC_POS 21 -//#define MAC_HWF1R_NUMTC_LEN 3 -//#define MAC_HWF1R_RSSEN_POS 20 -//#define MAC_HWF1R_RSSEN_LEN 1 -#define MAC_HWF1R_RAVSEL_POS 21 -#define MAC_HWF1R_RAVSEL_LEN 1 -#define MAC_HWF1R_AVSEL_POS 20 -#define MAC_HWF1R_AVSEL_LEN 1 -#define MAC_HWF1R_RXFIFOSIZE_POS 0 -#define MAC_HWF1R_RXFIFOSIZE_LEN 5 -#define MAC_HWF1R_SPHEN_POS 17 -#define MAC_HWF1R_SPHEN_LEN 1 -#define MAC_HWF1R_TSOEN_POS 18 -#define MAC_HWF1R_TSOEN_LEN 1 -#define MAC_HWF1R_TXFIFOSIZE_POS 6 -#define MAC_HWF1R_TXFIFOSIZE_LEN 5 -#define MAC_HWF2R_AUXSNAPNUM_POS 28 -#define MAC_HWF2R_AUXSNAPNUM_LEN 3 -#define MAC_HWF2R_PPSOUTNUM_POS 24 -#define MAC_HWF2R_PPSOUTNUM_LEN 3 -#define MAC_HWF2R_RXCHCNT_POS 12 -#define MAC_HWF2R_RXCHCNT_LEN 4 -#define MAC_HWF2R_RXQCNT_POS 0 -#define MAC_HWF2R_RXQCNT_LEN 4 -#define MAC_HWF2R_TXCHCNT_POS 18 -#define MAC_HWF2R_TXCHCNT_LEN 4 -#define MAC_HWF2R_TXQCNT_POS 6 -#define MAC_HWF2R_TXQCNT_LEN 4 -#define MAC_IER_TSIE_POS 12 -#define MAC_IER_TSIE_LEN 1 -#define MAC_ISR_MMCRXIS_POS 9 -#define MAC_ISR_MMCRXIS_LEN 1 -#define MAC_ISR_MMCTXIS_POS 10 -#define MAC_ISR_MMCTXIS_LEN 1 -#define MAC_ISR_PMTIS_POS 4 -#define MAC_ISR_PMTIS_LEN 1 -#define MAC_ISR_TSIS_POS 12 -#define MAC_ISR_TSIS_LEN 1 -#define MAC_MACA1HR_AE_POS 31 -#define MAC_MACA1HR_AE_LEN 1 -#define MAC_PFR_HMC_POS 2 -#define MAC_PFR_HMC_LEN 1 -#define MAC_PFR_HPF_POS 10 -#define MAC_PFR_HPF_LEN 1 -#define MAC_PFR_PM_POS 4 // Pass all Multicast. -#define MAC_PFR_PM_LEN 1 -#define MAC_PFR_DBF_POS 5 // Disable Broadcast Packets. -#define MAC_PFR_DBF_LEN 1 -#define MAC_PFR_HUC_POS 1 // Hash Unicast. 0x0 (DISABLE). compares the DA field with the values programmed in DA registers. -#define MAC_PFR_HUC_LEN 1 -#define MAC_PFR_PR_POS 0 // Enable Promiscuous Mode. -#define MAC_PFR_PR_LEN 1 -#define MAC_PFR_VTFE_POS 16 -#define MAC_PFR_VTFE_LEN 1 -#define MAC_Q0TFCR_PT_POS 16 -#define MAC_Q0TFCR_PT_LEN 16 -#define MAC_Q0TFCR_TFE_POS 1 -#define MAC_Q0TFCR_TFE_LEN 1 -#define MAC_CR_ARPEN_POS 31 -#define MAC_CR_ARPEN_LEN 1 -#define MAC_CR_ACS_POS 20 -#define MAC_CR_ACS_LEN 1 -#define MAC_CR_CST_POS 21 -#define MAC_CR_CST_LEN 1 -#define MAC_CR_IPC_POS 27 -#define MAC_CR_IPC_LEN 1 -#define MAC_CR_JE_POS 16 -#define MAC_CR_JE_LEN 1 -#define MAC_CR_LM_POS 12 -#define MAC_CR_LM_LEN 1 -#define MAC_CR_RE_POS 0 -#define MAC_CR_RE_LEN 1 -#define MAC_CR_PS_POS 15 -#define MAC_CR_PS_LEN 1 -#define MAC_CR_FES_POS 14 -#define MAC_CR_FES_LEN 1 -#define MAC_CR_DM_POS 13 -#define MAC_CR_DM_LEN 1 -#define MAC_CR_TE_POS 1 -#define MAC_CR_TE_LEN 1 -#define MAC_ECR_DCRCC_POS 16 -#define MAC_ECR_DCRCC_LEN 1 -#define MAC_ECR_HDSMS_POS 20 -#define MAC_ECR_HDSMS_LEN 3 -#define MAC_RFCR_PFCE_POS 8 -#define MAC_RFCR_PFCE_LEN 1 -#define MAC_RFCR_RFE_POS 0 -#define MAC_RFCR_RFE_LEN 1 -#define MAC_RFCR_UP_POS 1 -#define MAC_RFCR_UP_LEN 1 -#define MAC_RQC0R_RXQ0EN_POS 0 -#define MAC_RQC0R_RXQ0EN_LEN 2 -#define MAC_LPIIE_POS 5 -#define MAC_LPIIE_LEN 1 -#define MAC_LPIATE_POS 20 -#define MAC_LPIATE_LEN 1 -#define MAC_LPITXA_POS 19 -#define MAC_LPITXA_LEN 1 -#define MAC_PLS_POS 17 -#define MAC_PLS_LEN 1 -#define MAC_LPIEN_POS 16 -#define MAC_LPIEN_LEN 1 -#define MAC_LPI_ENTRY_TIMER 8 -#define MAC_LPIET_POS 3 -#define MAC_LPIET_LEN 17 -#define MAC_TWT_TIMER 0x10 -#define MAC_TWT_POS 0 -#define MAC_TWT_LEN 16 -#define MAC_LST_TIMER 2 -#define MAC_LST_POS 16 -#define MAC_LST_LEN 10 -#define MAC_MS_TIC 24 -#define MAC_MS_TIC_POS 0 -#define MAC_MS_TIC_LEN 12 - -/* RSS table */ -#define MAC_RSSAR_ADDRT_POS 2 -#define MAC_RSSAR_ADDRT_LEN 1 -#define MAC_RSSAR_CT_POS 1 -#define MAC_RSSAR_CT_LEN 1 -#define MAC_RSSAR_OB_POS 0 -#define MAC_RSSAR_OB_LEN 1 -#define MAC_RSSAR_RSSIA_POS 8 -#define MAC_RSSAR_RSSIA_LEN 8 -/* RSS control and options */ -/* note, below options definitions are used only for pdata->options, - * not for register, so the position is not consistent with register. - * [0] ipv4 - * [1] tcpv4 - * [2] udpv4 - * [3] ipv6 - * [4] tcpv6 - * [5] udpv6 - */ -#define MAC_RSSCR_IP4TE_POS 0 -#define MAC_RSSCR_IP4TE_LEN 1 -#define MAC_RSSCR_IP6TE_POS 3 -#define MAC_RSSCR_IP6TE_LEN 1 -#define MAC_RSSCR_TCP4TE_POS 1 -#define MAC_RSSCR_TCP4TE_LEN 1 -#define MAC_RSSCR_UDP4TE_POS 2 -#define MAC_RSSCR_UDP4TE_LEN 1 -#define MAC_RSSCR_TCP6TE_POS 4 -#define MAC_RSSCR_TCP6TE_LEN 1 -#define MAC_RSSCR_UDP6TE_POS 5 -#define MAC_RSSCR_UDP6TE_LEN 1 - -/* RSS indirection table */ -#define MAC_RSSDR_DMCH_POS 0 -#define MAC_RSSDR_DMCH_LEN 2 - -#define MAC_VLANHTR_VLHT_POS 0 -#define MAC_VLANHTR_VLHT_LEN 16 -#define MAC_VLANIR_VLTI_POS 20 -#define MAC_VLANIR_VLTI_LEN 1 -#define MAC_VLANIR_CSVL_POS 19 -#define MAC_VLANIR_CSVL_LEN 1 -#define MAC_VLANIR_VLP_POS 18 -#define MAC_VLANIR_VLP_LEN 1 -#define MAC_VLANIR_VLC_POS 16 -#define MAC_VLANIR_VLC_LEN 2 -#define MAC_VLANIR_VLT_POS 0 -#define MAC_VLANIR_VLT_LEN 16 -#define MAC_VLANTR_DOVLTC_POS 20 -#define MAC_VLANTR_DOVLTC_LEN 1 -#define MAC_VLANTR_ERSVLM_POS 19 -#define MAC_VLANTR_ERSVLM_LEN 1 -#define MAC_VLANTR_ESVL_POS 18 -#define MAC_VLANTR_ESVL_LEN 1 -#define MAC_VLANTR_ETV_POS 16 -#define MAC_VLANTR_ETV_LEN 1 -#define MAC_VLANTR_EVLS_POS 21 -#define MAC_VLANTR_EVLS_LEN 2 -#define MAC_VLANTR_EVLRXS_POS 24 -#define MAC_VLANTR_EVLRXS_LEN 1 -#define MAC_VLANTR_VL_POS 0 -#define MAC_VLANTR_VL_LEN 16 -#define MAC_VLANTR_VTHM_POS 25 -#define MAC_VLANTR_VTHM_LEN 1 -#define MAC_VLANTR_VTIM_POS 17 -#define MAC_VLANTR_VTIM_LEN 1 -#define MAC_VR_DEVID_POS 16 -#define MAC_VR_DEVID_LEN 16 -#define MAC_VR_SVER_POS 0 -#define MAC_VR_SVER_LEN 8 -#define MAC_VR_USERVER_POS 8 -#define MAC_VR_USERVER_LEN 8 - -#define MAC_DBG_STA_TX_BUSY 0x70000 -#define MTL_TXQ_DEG_TX_BUSY 0x10 - -#define MAC_MDIO_ADDRESS_BUSY 1 //bit 0 - -#define MAC_MDIO_ADDR_GOC_POS 2 -#define MAC_MDIO_ADDR_GOC_LEN 2 -#define MAC_MDIO_ADDR_GB_POS 0 -#define MAC_MDIO_ADDR_GB_LEN 1 - -#define MAC_MDIO_DATA_RA_POS 16 -#define MAC_MDIO_DATA_RA_LEN 16 -#define MAC_MDIO_DATA_GD_POS 0 -#define MAC_MDIO_DATA_GD_LEN 16 - -/* bit definitions for PMT and WOL, 20210622 */ -#define MAC_PMT_STA_PWRDWN_POS 0 -#define MAC_PMT_STA_PWRDWN_LEN 1 -#define MAC_PMT_STA_MGKPKTEN_POS 1 -#define MAC_PMT_STA_MGKPKTEN_LEN 1 -#define MAC_PMT_STA_RWKPKTEN_POS 2 -#define MAC_PMT_STA_RWKPKTEN_LEN 1 -#define MAC_PMT_STA_MGKPRCVD_POS 5 -#define MAC_PMT_STA_MGKPRCVD_LEN 1 -#define MAC_PMT_STA_RWKPRCVD_POS 6 -#define MAC_PMT_STA_RWKPRCVD_LEN 1 -#define MAC_PMT_STA_GLBLUCAST_POS 9 -#define MAC_PMT_STA_GLBLUCAST_LEN 1 -#define MAC_PMT_STA_RWKPTR_POS 24 -#define MAC_PMT_STA_RWKPTR_LEN 4 -#define MAC_PMT_STA_RWKFILTERST_POS 31 -#define MAC_PMT_STA_RWKFILTERST_LEN 1 -/* MMC register offsets */ -#define MMC_CR 0x0700 -#define MMC_RISR 0x0704 -#define MMC_TISR 0x0708 -#define MMC_RIER 0x070c -#define MMC_TIER 0x0710 -#define MMC_TXOCTETCOUNT_GB_LO 0x0714 -#define MMC_TXFRAMECOUNT_GB_LO 0x0718 -#define MMC_TXBROADCASTFRAMES_G_LO 0x071c -#define MMC_TXMULTICASTFRAMES_G_LO 0x0720 -#define MMC_TX64OCTETS_GB_LO 0x0724 -#define MMC_TX65TO127OCTETS_GB_LO 0x0728 -#define MMC_TX128TO255OCTETS_GB_LO 0x072c -#define MMC_TX256TO511OCTETS_GB_LO 0x0730 -#define MMC_TX512TO1023OCTETS_GB_LO 0x0734 -#define MMC_TX1024TOMAXOCTETS_GB_LO 0x0738 -#define MMC_TXUNICASTFRAMES_GB_LO 0x073c -#define MMC_TXMULTICASTFRAMES_GB_LO 0x0740 -#define MMC_TXBROADCASTFRAMES_GB_LO 0x0744 -#define MMC_TXUNDERFLOWERROR_LO 0x0748 -#define MMC_TXSINGLECOLLISION_G 0x074c -#define MMC_TXMULTIPLECOLLISION_G 0x0750 -#define MMC_TXDEFERREDFRAMES 0x0754 -#define MMC_TXLATECOLLISIONFRAMES 0x0758 -#define MMC_TXEXCESSIVECOLLSIONFRAMES 0x075c -#define MMC_TXCARRIERERRORFRAMES 0x0760 -#define MMC_TXOCTETCOUNT_G_LO 0x0764 -#define MMC_TXFRAMECOUNT_G_LO 0x0768 -#define MMC_TXEXCESSIVEDEFERRALERROR 0x076c -#define MMC_TXPAUSEFRAMES_LO 0x0770 -#define MMC_TXVLANFRAMES_G_LO 0x0774 -#define MMC_TXOVERSIZEFRAMES 0x0778 -#define MMC_RXFRAMECOUNT_GB_LO 0x0780 -#define MMC_RXOCTETCOUNT_GB_LO 0x0784 -#define MMC_RXOCTETCOUNT_G_LO 0x0788 -#define MMC_RXBROADCASTFRAMES_G_LO 0x078c -#define MMC_RXMULTICASTFRAMES_G_LO 0x0790 -#define MMC_RXCRCERROR_LO 0x0794 -#define MMC_RXALIGNERROR 0x0798 -#define MMC_RXRUNTERROR 0x079c -#define MMC_RXJABBERERROR 0x07a0 -#define MMC_RXUNDERSIZE_G 0x07a4 -#define MMC_RXOVERSIZE_G 0x07a8 -#define MMC_RX64OCTETS_GB_LO 0x07ac -#define MMC_RX65TO127OCTETS_GB_LO 0x07b0 -#define MMC_RX128TO255OCTETS_GB_LO 0x07b4 -#define MMC_RX256TO511OCTETS_GB_LO 0x07b8 -#define MMC_RX512TO1023OCTETS_GB_LO 0x07bc -#define MMC_RX1024TOMAXOCTETS_GB_LO 0x07c0 -#define MMC_RXUNICASTFRAMES_G_LO 0x07c4 -#define MMC_RXLENGTHERROR_LO 0x07c8 -#define MMC_RXOUTOFRANGETYPE_LO 0x07cc -#define MMC_RXPAUSEFRAMES_LO 0x07d0 -#define MMC_RXFIFOOVERFLOW_LO 0x07d4 -#define MMC_RXVLANFRAMES_GB_LO 0x07d8 -#define MMC_RXWATCHDOGERROR 0x07dc -#define MMC_RXRECEIVEERRORFRAME 0x07e0 -#define MMC_RXCONTROLFRAME_G 0x07e4 - -#define MMC_IPCRXINTMASK 0x800 -#define MMC_IPCRXINT 0x808 - -/* MMC register entry bit positions and sizes */ -#define MMC_CR_CR_POS 0 -#define MMC_CR_CR_LEN 1 -#define MMC_CR_CSR_POS 1 -#define MMC_CR_CSR_LEN 1 -#define MMC_CR_ROR_POS 2 -#define MMC_CR_ROR_LEN 1 -#define MMC_CR_MCF_POS 3 -#define MMC_CR_MCF_LEN 1 -//#define MMC_CR_MCT_POS 4 -//#define MMC_CR_MCT_LEN 2 -#define MMC_RIER_ALL_INTERRUPTS_POS 0 -#define MMC_RIER_ALL_INTERRUPTS_LEN 26 -#define MMC_RISR_RXFRAMECOUNT_GB_POS 0 -#define MMC_RISR_RXFRAMECOUNT_GB_LEN 1 -#define MMC_RISR_RXOCTETCOUNT_GB_POS 1 -#define MMC_RISR_RXOCTETCOUNT_GB_LEN 1 -#define MMC_RISR_RXOCTETCOUNT_G_POS 2 -#define MMC_RISR_RXOCTETCOUNT_G_LEN 1 -#define MMC_RISR_RXBROADCASTFRAMES_G_POS 3 -#define MMC_RISR_RXBROADCASTFRAMES_G_LEN 1 -#define MMC_RISR_RXMULTICASTFRAMES_G_POS 4 -#define MMC_RISR_RXMULTICASTFRAMES_G_LEN 1 -#define MMC_RISR_RXCRCERROR_POS 5 -#define MMC_RISR_RXCRCERROR_LEN 1 -#define MMC_RISR_RXALIGNERROR_POS 6 -#define MMC_RISR_RXALIGNERROR_LEN 1 -#define MMC_RISR_RXRUNTERROR_POS 7 -#define MMC_RISR_RXRUNTERROR_LEN 1 -#define MMC_RISR_RXJABBERERROR_POS 8 -#define MMC_RISR_RXJABBERERROR_LEN 1 -#define MMC_RISR_RXUNDERSIZE_G_POS 9 -#define MMC_RISR_RXUNDERSIZE_G_LEN 1 -#define MMC_RISR_RXOVERSIZE_G_POS 10 -#define MMC_RISR_RXOVERSIZE_G_LEN 1 -#define MMC_RISR_RX64OCTETS_GB_POS 11 -#define MMC_RISR_RX64OCTETS_GB_LEN 1 -#define MMC_RISR_RX65TO127OCTETS_GB_POS 12 -#define MMC_RISR_RX65TO127OCTETS_GB_LEN 1 -#define MMC_RISR_RX128TO255OCTETS_GB_POS 13 -#define MMC_RISR_RX128TO255OCTETS_GB_LEN 1 -#define MMC_RISR_RX256TO511OCTETS_GB_POS 14 -#define MMC_RISR_RX256TO511OCTETS_GB_LEN 1 -#define MMC_RISR_RX512TO1023OCTETS_GB_POS 15 -#define MMC_RISR_RX512TO1023OCTETS_GB_LEN 1 -#define MMC_RISR_RX1024TOMAXOCTETS_GB_POS 16 -#define MMC_RISR_RX1024TOMAXOCTETS_GB_LEN 1 -#define MMC_RISR_RXUNICASTFRAMES_G_POS 17 -#define MMC_RISR_RXUNICASTFRAMES_G_LEN 1 -#define MMC_RISR_RXLENGTHERROR_POS 18 -#define MMC_RISR_RXLENGTHERROR_LEN 1 -#define MMC_RISR_RXOUTOFRANGETYPE_POS 19 -#define MMC_RISR_RXOUTOFRANGETYPE_LEN 1 -#define MMC_RISR_RXPAUSEFRAMES_POS 20 -#define MMC_RISR_RXPAUSEFRAMES_LEN 1 -#define MMC_RISR_RXFIFOOVERFLOW_POS 21 -#define MMC_RISR_RXFIFOOVERFLOW_LEN 1 -#define MMC_RISR_RXVLANFRAMES_GB_POS 22 -#define MMC_RISR_RXVLANFRAMES_GB_LEN 1 -#define MMC_RISR_RXWATCHDOGERROR_POS 23 -#define MMC_RISR_RXWATCHDOGERROR_LEN 1 -#define MMC_RISR_RXERRORFRAMES_POS 24 -#define MMC_RISR_RXERRORFRAMES_LEN 1 -#define MMC_RISR_RXERRORCONTROLFRAMES_POS 25 -#define MMC_RISR_RXERRORCONTROLFRAMES_LEN 1 -#define MMC_RISR_RXLPIMICROSECOND_POS 26 //no counter register -#define MMC_RISR_RXLPIMICROSECOND_LEN 1 -#define MMC_RISR_RXLPITRANSITION_POS 27 //no counter register -#define MMC_RISR_RXLPITRANSITION_LEN 1 - -#define MMC_TIER_ALL_INTERRUPTS_POS 0 -#define MMC_TIER_ALL_INTERRUPTS_LEN 26 -#define MMC_TISR_TXOCTETCOUNT_GB_POS 0 -#define MMC_TISR_TXOCTETCOUNT_GB_LEN 1 -#define MMC_TISR_TXFRAMECOUNT_GB_POS 1 -#define MMC_TISR_TXFRAMECOUNT_GB_LEN 1 -#define MMC_TISR_TXBROADCASTFRAMES_G_POS 2 -#define MMC_TISR_TXBROADCASTFRAMES_G_LEN 1 -#define MMC_TISR_TXMULTICASTFRAMES_G_POS 3 -#define MMC_TISR_TXMULTICASTFRAMES_G_LEN 1 -#define MMC_TISR_TX64OCTETS_GB_POS 4 -#define MMC_TISR_TX64OCTETS_GB_LEN 1 -#define MMC_TISR_TX65TO127OCTETS_GB_POS 5 -#define MMC_TISR_TX65TO127OCTETS_GB_LEN 1 -#define MMC_TISR_TX128TO255OCTETS_GB_POS 6 -#define MMC_TISR_TX128TO255OCTETS_GB_LEN 1 -#define MMC_TISR_TX256TO511OCTETS_GB_POS 7 -#define MMC_TISR_TX256TO511OCTETS_GB_LEN 1 -#define MMC_TISR_TX512TO1023OCTETS_GB_POS 8 -#define MMC_TISR_TX512TO1023OCTETS_GB_LEN 1 -#define MMC_TISR_TX1024TOMAXOCTETS_GB_POS 9 -#define MMC_TISR_TX1024TOMAXOCTETS_GB_LEN 1 -#define MMC_TISR_TXUNICASTFRAMES_GB_POS 10 -#define MMC_TISR_TXUNICASTFRAMES_GB_LEN 1 -#define MMC_TISR_TXMULTICASTFRAMES_GB_POS 11 -#define MMC_TISR_TXMULTICASTFRAMES_GB_LEN 1 -#define MMC_TISR_TXBROADCASTFRAMES_GB_POS 12 -#define MMC_TISR_TXBROADCASTFRAMES_GB_LEN 1 -#define MMC_TISR_TXUNDERFLOWERROR_POS 13 -#define MMC_TISR_TXUNDERFLOWERROR_LEN 1 -#define MMC_TISR_TXSINGLECOLLISION_G_POS 14 -#define MMC_TISR_TXSINGLECOLLISION_G_LEN 1 -#define MMC_TISR_TXMULTIPLECOLLISION_G_POS 15 -#define MMC_TISR_TXMULTIPLECOLLISION_G_LEN 1 -#define MMC_TISR_TXDEFERREDFRAMES_POS 16 -#define MMC_TISR_TXDEFERREDFRAMES_LEN 1 -#define MMC_TISR_TXLATECOLLISIONFRAMES_POS 17 -#define MMC_TISR_TXLATECOLLISIONFRAMES_LEN 1 -#define MMC_TISR_TXEXCESSIVECOLLISIONFRAMES_POS 18 -#define MMC_TISR_TXEXCESSIVECOLLISIONFRAMES_LEN 1 -#define MMC_TISR_TXCARRIERERRORFRAMES_POS 19 -#define MMC_TISR_TXCARRIERERRORFRAMES_LEN 1 -#define MMC_TISR_TXOCTETCOUNT_G_POS 20 -#define MMC_TISR_TXOCTETCOUNT_G_LEN 1 -#define MMC_TISR_TXFRAMECOUNT_G_POS 21 -#define MMC_TISR_TXFRAMECOUNT_G_LEN 1 -#define MMC_TISR_TXEXCESSIVEDEFERRALFRAMES_POS 22 -#define MMC_TISR_TXEXCESSIVEDEFERRALFRAMES_LEN 1 -#define MMC_TISR_TXPAUSEFRAMES_POS 23 -#define MMC_TISR_TXPAUSEFRAMES_LEN 1 -#define MMC_TISR_TXVLANFRAMES_G_POS 24 -#define MMC_TISR_TXVLANFRAMES_G_LEN 1 -#define MMC_TISR_TXOVERSIZE_G_POS 25 -#define MMC_TISR_TXOVERSIZE_G_LEN 1 -#define MMC_TISR_TXLPIMICROSECOND_POS 26 //no counter register -#define MMC_TISR_TXLPIMICROSECOND_LEN 1 -#define MMC_TISR_TXLPITRANSITION_POS 27 //no counter register -#define MMC_TISR_TXLPITRANSITION_LEN 1 - -/* MTL register offsets */ -#define MTL_OMR 0x0c00 -#define MTL_FDDR 0x0c10 -#define MTL_INT_SR 0x0c20 -#define MTL_RQDCM0R 0x0c30 -#define MTL_ECC_INT_SR 0x0ccc - -#define MTL_RQDCM_INC 4 -#define MTL_RQDCM_Q_PER_REG 4 - -/* MTL register entry bit positions and sizes */ -#define MTL_OMR_ETSALG_POS 5 -#define MTL_OMR_ETSALG_LEN 2 -#define MTL_OMR_RAA_POS 2 -#define MTL_OMR_RAA_LEN 1 - -/* MTL queue register offsets - * Multiple queues can be active. The first queue has registers - * that begin at 0x0d00. Each subsequent queue has registers that - * are accessed using an offset of 0x40 from the previous queue. - */ -#define MTL_Q_BASE 0x0d00 -#define MTL_Q_INC 0x40 -#define MTL_Q_INT_CTL_SR 0x0d2c - -#define MTL_Q_TQOMR 0x00 -#define MTL_Q_RQOMR 0x30 -#define MTL_Q_RQDR 0x38 -#define MTL_Q_IER 0x2c -#define MTL_Q_ISR 0x2c //no isr register -#define MTL_TXQ_DEG 0x08 //transmit debug - -/* MTL queue register entry bit positions and sizes */ -#define MTL_Q_RQDR_PRXQ_POS 16 -#define MTL_Q_RQDR_PRXQ_LEN 14 -#define MTL_Q_RQDR_RXQSTS_POS 4 -#define MTL_Q_RQDR_RXQSTS_LEN 2 -#define MTL_Q_RQOMR_RFA_POS 8 -#define MTL_Q_RQOMR_RFA_LEN 6 -#define MTL_Q_RQOMR_RFD_POS 14 -#define MTL_Q_RQOMR_RFD_LEN 6 -#define MTL_Q_RQOMR_EHFC_POS 7 -#define MTL_Q_RQOMR_EHFC_LEN 1 -#define MTL_Q_RQOMR_RQS_POS 20 -#define MTL_Q_RQOMR_RQS_LEN 9 -#define MTL_Q_RQOMR_RSF_POS 5 -#define MTL_Q_RQOMR_RSF_LEN 1 -#define MTL_Q_RQOMR_FEP_POS 4 -#define MTL_Q_RQOMR_FEP_LEN 1 -#define MTL_Q_RQOMR_FUP_POS 3 -#define MTL_Q_RQOMR_FUP_LEN 1 -#define MTL_Q_RQOMR_RTC_POS 0 -#define MTL_Q_RQOMR_RTC_LEN 2 -#define MTL_Q_TQOMR_FTQ_POS 0 -#define MTL_Q_TQOMR_FTQ_LEN 1 -//#define MTL_Q_TQOMR_Q2TCMAP_POS 8 // no register -//#define MTL_Q_TQOMR_Q2TCMAP_LEN 3 // no register -#define MTL_Q_TQOMR_TQS_POS 16 -#define MTL_Q_TQOMR_TQS_LEN 7 -#define MTL_Q_TQOMR_TSF_POS 1 -#define MTL_Q_TQOMR_TSF_LEN 1 -#define MTL_Q_TQOMR_TTC_POS 4 -#define MTL_Q_TQOMR_TTC_LEN 3 -#define MTL_Q_TQOMR_TXQEN_POS 2 -#define MTL_Q_TQOMR_TXQEN_LEN 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_FEP_DISABLE 0x00 -#define MTL_FEP_ENABLE 0x01 - -#define MTL_RX_THRESHOLD_64 0x00 -#define MTL_RX_THRESHOLD_32 0x01 -#define MTL_RX_THRESHOLD_96 0x02 -#define MTL_RX_THRESHOLD_128 0x03 -#define MTL_TX_THRESHOLD_32 0x00 -#define MTL_TX_THRESHOLD_64 0x01 -#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_ETSALG_SP 0x03 - -#define MTL_RAA_SP 0x00 -#define MTL_RAA_WSP 0x01 - -#define MTL_Q_DISABLED 0x00 -#define MTL_Q_EN_IF_AV 0x01 -#define MTL_Q_ENABLED 0x02 - -#define MTL_RQDCM0R_Q0MDMACH 0x0 -#define MTL_RQDCM0R_Q1MDMACH 0x00000100 -#define MTL_RQDCM0R_Q2MDMACH 0x00020000 -#define MTL_RQDCM0R_Q3MDMACH 0x03000000 -#define MTL_RQDCM1R_Q4MDMACH 0x00000004 -#define MTL_RQDCM1R_Q5MDMACH 0x00000500 -#define MTL_RQDCM1R_Q6MDMACH 0x00060000 -#define MTL_RQDCM1R_Q7MDMACH 0x07000000 -#define MTL_RQDCM2R_Q8MDMACH 0x00000008 -#define MTL_RQDCM2R_Q9MDMACH 0x00000900 -#define MTL_RQDCM2R_Q10MDMACH 0x000A0000 -#define MTL_RQDCM2R_Q11MDMACH 0x0B000000 - -#define MTL_RQDCM0R_Q0DDMACH 0x10 -#define MTL_RQDCM0R_Q1DDMACH 0x00001000 -#define MTL_RQDCM0R_Q2DDMACH 0x00100000 -#define MTL_RQDCM0R_Q3DDMACH 0x10000000 -#define MTL_RQDCM1R_Q4DDMACH 0x00000010 -#define MTL_RQDCM1R_Q5DDMACH 0x00001000 -#define MTL_RQDCM1R_Q6DDMACH 0x00100000 -#define MTL_RQDCM1R_Q7DDMACH 0x10000000 - - -/* 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. - */ -/* NO TRAFFIC CLASS REGISTER DESCRIPTION */ -#if 1 -#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_POS 0 -#define MTL_TC_ETSCR_TSA_LEN 2 -#define MTL_TC_QWR_QW_POS 0 -#define MTL_TC_QWR_QW_LEN 21 - -/* MTL traffic class register value */ -#define MTL_TSA_SP 0x00 -#define MTL_TSA_ETS 0x02 -#endif - -/* DMA register offsets */ -#define DMA_MR 0x1000 -#define DMA_SBMR 0x1004 -#define DMA_ISR 0x1008 -#define DMA_DSR0 0x100c -#define DMA_DSR1 0x1010 -#define DMA_DSR2 0x1014 -#define DMA_ECC_INT_SR 0x1088 - -/* DMA register entry bit positions and sizes */ -#define DMA_ISR_MACIS_POS 17 -#define DMA_ISR_MACIS_LEN 1 -#define DMA_ISR_MTLIS_POS 16 -#define DMA_ISR_MTLIS_LEN 1 -#define DMA_MR_SWR_POS 0 -#define DMA_MR_SWR_LEN 1 -#define DMA_MR_INTM_POS 16 -#define DMA_MR_INTM_LEN 2 -#define DMA_MR_QUREAD_POS 19 -#define DMA_MR_QUREAD_LEN 1 - -#define DMA_SBMR_EN_LPI_POS 31 -#define DMA_SBMR_EN_LPI_LEN 1 -#define DMA_SBMR_LPI_XIT_PKT_POS 30 -#define DMA_SBMR_LPI_XIT_PKT_LEN 1 -#define DMA_SBMR_WR_OSR_LMT_POS 24 -#define DMA_SBMR_WR_OSR_LMT_LEN 6 -#define DMA_SBMR_RD_OSR_LMT_POS 16 -#define DMA_SBMR_RD_OSR_LMT_LEN 8 -#define DMA_SBMR_EAME_POS 11 -#define DMA_SBMR_EAME_LEN 1 -#define DMA_SBMR_AALE_POS 10 -#define DMA_SBMR_AALE_LEN 1 -#define DMA_SBMR_BLEN_4_POS 1 -#define DMA_SBMR_BLEN_4_LEN 1 -#define DMA_SBMR_BLEN_8_POS 2 -#define DMA_SBMR_BLEN_8_LEN 1 -#define DMA_SBMR_BLEN_16_POS 3 -#define DMA_SBMR_BLEN_16_LEN 1 -#define DMA_SBMR_BLEN_32_POS 4 -#define DMA_SBMR_BLEN_32_LEN 1 -#define DMA_SBMR_BLEN_64_POS 5 -#define DMA_SBMR_BLEN_64_LEN 1 -#define DMA_SBMR_BLEN_128_POS 6 -#define DMA_SBMR_BLEN_128_LEN 1 -#define DMA_SBMR_BLEN_256_POS 7 -#define DMA_SBMR_BLEN_256_LEN 1 -#define DMA_SBMR_FB_POS 0 -#define DMA_SBMR_FB_LEN 1 - -/* DMA register values */ -#define DMA_DSR_RPS_LEN 4 -#define DMA_DSR_TPS_LEN 4 -#define DMA_DSR_Q_LEN (DMA_DSR_RPS_LEN + DMA_DSR_TPS_LEN) -#define DMA_DSR0_TPS_START 12 -#define DMA_DSRX_FIRST_QUEUE 3 -#define DMA_DSRX_INC 4 -#define DMA_DSRX_QPR 4 // no definition -#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 0x1100. Each subsequent channel has registers that - * are accessed using an offset of 0x80 from the previous channel. - */ -#define DMA_CH_BASE 0x1100 -#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 0x20 -#define DMA_CH_RDTR_LO 0x28 -#define DMA_CH_TDRLR 0x2c -#define DMA_CH_RDRLR 0x30 -#define DMA_CH_IER 0x34 -#define DMA_CH_RIWT 0x38 -#define DMA_CH_SR 0x60 - -/* DMA channel register entry bit positions and sizes */ -#define DMA_CH_CR_PBLX8_POS 16 -#define DMA_CH_CR_PBLX8_LEN 1 -#define DMA_CH_CR_SPH_POS 24 -#define DMA_CH_CR_SPH_LEN 1 -#define DMA_CH_IER_AIE_POS 14 -#define DMA_CH_IER_AIE_LEN 1 -#define DMA_CH_IER_FBEE_POS 12 -#define DMA_CH_IER_FBEE_LEN 1 -#define DMA_CH_IER_NIE_POS 15 -#define DMA_CH_IER_NIE_LEN 1 -#define DMA_CH_IER_RBUE_POS 7 -#define DMA_CH_IER_RBUE_LEN 1 -#define DMA_CH_IER_RIE_POS 6 -#define DMA_CH_IER_RIE_LEN 1 -#define DMA_CH_IER_RSE_POS 8 -#define DMA_CH_IER_RSE_LEN 1 -#define DMA_CH_IER_TBUE_POS 2 -#define DMA_CH_IER_TBUE_LEN 1 -#define DMA_CH_IER_TIE_POS 0 -#define DMA_CH_IER_TIE_LEN 1 -#define DMA_CH_IER_TXSE_POS 1 -#define DMA_CH_IER_TXSE_LEN 1 -#define DMA_CH_RCR_PBL_POS 16 -#define DMA_CH_RCR_PBL_LEN 6 -#define DMA_CH_RCR_RBSZ_POS 1 -#define DMA_CH_RCR_RBSZ_LEN 14 -#define DMA_CH_RCR_SR_POS 0 -#define DMA_CH_RCR_SR_LEN 1 -#define DMA_CH_RIWT_RWT_POS 0 -#define DMA_CH_RIWT_RWT_LEN 8 -#define DMA_CH_SR_FBE_POS 12 -#define DMA_CH_SR_FBE_LEN 1 -#define DMA_CH_SR_RBU_POS 7 -#define DMA_CH_SR_RBU_LEN 1 -#define DMA_CH_SR_RI_POS 6 -#define DMA_CH_SR_RI_LEN 1 -#define DMA_CH_SR_RPS_POS 8 -#define DMA_CH_SR_RPS_LEN 1 -#define DMA_CH_SR_TBU_POS 2 -#define DMA_CH_SR_TBU_LEN 1 -#define DMA_CH_SR_TI_POS 0 -#define DMA_CH_SR_TI_LEN 1 -#define DMA_CH_SR_TPS_POS 1 -#define DMA_CH_SR_TPS_LEN 1 -#define DMA_CH_TCR_OSP_POS 4 -#define DMA_CH_TCR_OSP_LEN 1 -#define DMA_CH_TCR_PBL_POS 16 -#define DMA_CH_TCR_PBL_LEN 6 -#define DMA_CH_TCR_ST_POS 0 -#define DMA_CH_TCR_ST_LEN 1 -#define DMA_CH_TCR_TSE_POS 12 -#define DMA_CH_TCR_TSE_LEN 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 -#define DMA_PBL_128 128 -#define DMA_PBL_256 256 -#define DMA_PBL_X8_DISABLE 0x00 -#define DMA_PBL_X8_ENABLE 0x01 - -/* Descriptor/Packet entry bit positions and sizes */ -#define RX_PACKET_ERRORS_CRC_POS 2 -#define RX_PACKET_ERRORS_CRC_LEN 1 -#define RX_PACKET_ERRORS_FRAME_POS 3 -#define RX_PACKET_ERRORS_FRAME_LEN 1 -#define RX_PACKET_ERRORS_LENGTH_POS 0 -#define RX_PACKET_ERRORS_LENGTH_LEN 1 -#define RX_PACKET_ERRORS_OVERRUN_POS 1 -#define RX_PACKET_ERRORS_OVERRUN_LEN 1 - -#define RX_PACKET_ATTRIBUTES_CSUM_DONE_POS 0 -#define RX_PACKET_ATTRIBUTES_CSUM_DONE_LEN 1 -#define RX_PACKET_ATTRIBUTES_VLAN_CTAG_POS 1 -#define RX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN 1 -#define RX_PACKET_ATTRIBUTES_INCOMPLETE_POS 2 -#define RX_PACKET_ATTRIBUTES_INCOMPLETE_LEN 1 -#define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_POS 3 -#define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_LEN 1 -#define RX_PACKET_ATTRIBUTES_CONTEXT_POS 4 -#define RX_PACKET_ATTRIBUTES_CONTEXT_LEN 1 -#define RX_PACKET_ATTRIBUTES_RX_TSTAMP_POS 5 -#define RX_PACKET_ATTRIBUTES_RX_TSTAMP_LEN 1 -#define RX_PACKET_ATTRIBUTES_RSS_HASH_POS 6 -#define RX_PACKET_ATTRIBUTES_RSS_HASH_LEN 1 - -#define RX_NORMAL_DESC0_OVT_POS 0 -#define RX_NORMAL_DESC0_OVT_LEN 16 -#define RX_NORMAL_DESC2_HL_POS 0 -#define RX_NORMAL_DESC2_HL_LEN 10 -//#define RX_NORMAL_DESC3_CDA_POS 27// -#define RX_NORMAL_DESC3_CDA_LEN 1 -#define RX_NORMAL_DESC3_CTXT_POS 30 -#define RX_NORMAL_DESC3_CTXT_LEN 1 -#define RX_NORMAL_DESC3_ES_POS 15 -#define RX_NORMAL_DESC3_ES_LEN 1 -#define RX_NORMAL_DESC3_ETLT_POS 16 -#define RX_NORMAL_DESC3_ETLT_LEN 3 -#define RX_NORMAL_DESC3_FD_POS 29 -#define RX_NORMAL_DESC3_FD_LEN 1 -#define RX_NORMAL_DESC3_INTE_POS 30 -#define RX_NORMAL_DESC3_INTE_LEN 1 -//#define RX_NORMAL_DESC3_L34T_POS 20// -#define RX_NORMAL_DESC3_L34T_LEN 4 -#define RX_NORMAL_DESC3_LD_POS 28 -#define RX_NORMAL_DESC3_LD_LEN 1 -#define RX_NORMAL_DESC3_OWN_POS 31 -#define RX_NORMAL_DESC3_OWN_LEN 1 -#define RX_NORMAL_DESC3_BUF2V_POS 25 -#define RX_NORMAL_DESC3_BUF2V_LEN 1 -#define RX_NORMAL_DESC3_BUF1V_POS 24 -#define RX_NORMAL_DESC3_BUF1V_LEN 1 -#define RX_NORMAL_DESC3_PL_POS 0 -#define RX_NORMAL_DESC3_PL_LEN 15 -//#define RX_NORMAL_DESC3_RSV_POS 26 // -#define RX_NORMAL_DESC3_RSV_LEN 1 - -#define RX_NORMAL_DESC0_WB_IVT_POS 16 // Inner VLAN Tag. Valid only when Double VLAN tag processing and VLAN tag stripping are enabled. -#define RX_NORMAL_DESC0_WB_IVT_LEN 16 -#define RX_NORMAL_DESC0_WB_OVT_POS 0 // Outer VLAN Tag. -#define RX_NORMAL_DESC0_WB_OVT_LEN 16 -#define RX_NORMAL_DESC0_WB_OVT_VLANID_POS 0 // Outer VLAN ID. -#define RX_NORMAL_DESC0_WB_OVT_VLANID_LEN 12 -#define RX_NORMAL_DESC0_WB_OVT_CFI_POS 12 // Outer VLAN CFI. -#define RX_NORMAL_DESC0_WB_OVT_CFI_LEN 1 -#define RX_NORMAL_DESC0_WB_OVT_PRIO_POS 13 // Outer VLAN Priority. -#define RX_NORMAL_DESC0_WB_OVT_PRIO_LEN 3 - -#define RX_NORMAL_DESC1_WB_IPCE_POS 7 // IP Payload Error. -#define RX_NORMAL_DESC1_WB_IPCE_LEN 1 -#define RX_NORMAL_DESC1_WB_IPV6_POS 5 // IPV6 Header Present. -#define RX_NORMAL_DESC1_WB_IPV6_LEN 1 -#define RX_NORMAL_DESC1_WB_IPV4_POS 4 // IPV4 Header Present. -#define RX_NORMAL_DESC1_WB_IPV4_LEN 1 -#define RX_NORMAL_DESC1_WB_IPHE_POS 3 // IP Header Error. -#define RX_NORMAL_DESC1_WB_IPHE_LEN 1 -#define RX_NORMAL_DESC1_WB_PT_POS 0 // -#define RX_NORMAL_DESC1_WB_PT_LEN 3 - -#define RX_NORMAL_DESC2_WB_HF_POS 18 // Hash Filter Status. When this bit is set, it indicates that the packet passed the MAC address hash filter -#define RX_NORMAL_DESC2_WB_HF_LEN 1 -#define RX_NORMAL_DESC2_WB_DAF_POS 17 /* Destination Address Filter Fail. When Flexible RX Parser is disabled, and this bit is set, it indicates that the packet failed - the DA Filter in the MAC.*/ -#define RX_NORMAL_DESC2_WB_DAF_LEN 1 - -#define RX_NORMAL_DESC3_WB_LD_POS 28 -#define RX_NORMAL_DESC3_WB_LD_LEN 1 -#define RX_NORMAL_DESC3_WB_RS0V_POS 25 // When this bit is set, it indicates that the status in RDES0 is valid and it is written by the DMA. -#define RX_NORMAL_DESC3_WB_RS0V_LEN 1 -#define RX_NORMAL_DESC3_WB_CE_POS 24 // When this bit is set, it indicates that a Cyclic Redundancy Check (CRC) Error occurred on the -//received packet.This field is valid only when the LD bit of RDES3 is set. -#define RX_NORMAL_DESC3_WB_CE_LEN 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_DESC1_PT_UDP 1 -#define RX_DESC1_PT_TCP 2 -#define RX_DESC1_PT_ICMP 3 -#define RX_DESC1_PT_AV_TAG_DATA 6 -#define RX_DESC1_PT_AV_TAG_CTRL 7 -#define RX_DESC1_PT_AV_NOTAG_CTRL 5 - - - - -//#define RX_CONTEXT_DESC3_TSA_POS 4// -#define RX_CONTEXT_DESC3_TSA_LEN 1 -//#define RX_CONTEXT_DESC3_TSD_POS 6// -#define RX_CONTEXT_DESC3_TSD_LEN 1 - -#define TX_PACKET_ATTRIBUTES_CSUM_ENABLE_POS 0 -#define TX_PACKET_ATTRIBUTES_CSUM_ENABLE_LEN 1 -#define TX_PACKET_ATTRIBUTES_TSO_ENABLE_POS 1 -#define TX_PACKET_ATTRIBUTES_TSO_ENABLE_LEN 1 -#define TX_PACKET_ATTRIBUTES_VLAN_CTAG_POS 2 -#define TX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN 1 -#define TX_PACKET_ATTRIBUTES_PTP_POS 3 -#define TX_PACKET_ATTRIBUTES_PTP_LEN 1 - -#define TX_CONTEXT_DESC2_MSS_POS 0 -#define TX_CONTEXT_DESC2_MSS_LEN 14 -#define TX_CONTEXT_DESC2_IVLTV_POS 16 // Inner VLAN Tag. -#define TX_CONTEXT_DESC2_IVLTV_LEN 16 - -#define TX_CONTEXT_DESC3_CTXT_POS 30 -#define TX_CONTEXT_DESC3_CTXT_LEN 1 -#define TX_CONTEXT_DESC3_TCMSSV_POS 26 -#define TX_CONTEXT_DESC3_TCMSSV_LEN 1 -#define TX_CONTEXT_DESC3_IVTIR_POS 18 -#define TX_CONTEXT_DESC3_IVTIR_LEN 2 -#define TX_CONTEXT_DESC3_IVTIR_INSERT 2 // Insert an inner VLAN tag with the tag value programmed in the MAC_Inner_VLAN_Incl register or context descriptor. -#define TX_CONTEXT_DESC3_IVLTV_POS 17 // Indicates that the Inner VLAN TAG, IVLTV field of context TDES2 is valid. -#define TX_CONTEXT_DESC3_IVLTV_LEN 1 -#define TX_CONTEXT_DESC3_VLTV_POS 16 // Indicates that the VT field of context TDES3 is valid. -#define TX_CONTEXT_DESC3_VLTV_LEN 1 -#define TX_CONTEXT_DESC3_VT_POS 0 -#define TX_CONTEXT_DESC3_VT_LEN 16 - -#define TX_NORMAL_DESC2_HL_B1L_POS 0 // Header Length or Buffer 1 Length. -#define TX_NORMAL_DESC2_HL_B1L_LEN 14 -#define TX_NORMAL_DESC2_IC_POS 31 // Interrupt on Completion. -#define TX_NORMAL_DESC2_IC_LEN 1 -#define TX_NORMAL_DESC2_TTSE_POS 30 // Transmit Timestamp Enable or External TSO Memory Write Enable. -#define TX_NORMAL_DESC2_TTSE_LEN 1 -#define TX_NORMAL_DESC2_VTIR_POS 14 //LAN Tag Insertion or Replacement. -#define TX_NORMAL_DESC2_VTIR_LEN 2 -#define TX_NORMAL_DESC2_VLAN_INSERT 0x2 - -#define TX_NORMAL_DESC3_TCPPL_POS 0 -#define TX_NORMAL_DESC3_TCPPL_LEN 18 -#define TX_NORMAL_DESC3_FL_POS 0 // Frame Length or TCP Payload Length. -#define TX_NORMAL_DESC3_FL_LEN 15 -#define TX_NORMAL_DESC3_CIC_POS 16 /* Checksum Insertion Control or TCP Payload Length. - 2'b00: Checksum Insertion Disabled. - 2'b01: Only IP header checksum calculation and insertion are enabled. - 2'b10: IP header checksum and payload checksum calculation and insertion are - enabled, but pseudo-header checksum is not calculated in hardware. - 2'b11: IP Header checksum and payload checksum calculation and insertion are - enabled, and pseudo - header checksum is calculated in hardware. */ -#define TX_NORMAL_DESC3_CIC_LEN 2 -#define TX_NORMAL_DESC3_TSE_POS 18 // TCP Segmentation Enable. -#define TX_NORMAL_DESC3_TSE_LEN 1 -#define TX_NORMAL_DESC3_TCPHDRLEN_POS 19 /* THL: TCP/UDP Header Length.If the TSE bit is set, this field contains - the length of the TCP / UDP header.The minimum value of this field must - be 5 for TCP header.The value must be equal to 2 for UDP header. This - field is valid only for the first descriptor.*/ -#define TX_NORMAL_DESC3_TCPHDRLEN_LEN 4 -#define TX_NORMAL_DESC3_CPC_POS 26 // CRC Pad Control. -#define TX_NORMAL_DESC3_CPC_LEN 2 -#define TX_NORMAL_DESC3_LD_POS 28 // Last Descriptor. -#define TX_NORMAL_DESC3_LD_LEN 1 -#define TX_NORMAL_DESC3_FD_POS 29 // First Descriptor. -#define TX_NORMAL_DESC3_FD_LEN 1 -#define TX_NORMAL_DESC3_CTXT_POS 30 // Context Type.This bit should be set to 1'b0 for normal descriptor. -#define TX_NORMAL_DESC3_CTXT_LEN 1 -#define TX_NORMAL_DESC3_OWN_POS 31 // Own Bit. -#define TX_NORMAL_DESC3_OWN_LEN 1 - -/* for ephy generic register definitions */ -#define FXGMAC_EPHY_REGS_LEN 32 //32 ethernet phy registers under spec - -#define REG_MII_BMCR 0x00 /* Basic mode control register */ -#define PHY_CR_RESET_POS 15 -#define PHY_CR_RESET_LEN 1 -#define PHY_CR_SPEED_SEL_H_POS 6 -#define PHY_CR_SPEED_SEL_H_LEN 1 -#define PHY_CR_SPEED_SEL_L_POS 13 -#define PHY_CR_SPEED_SEL_L_LEN 1 -#define PHY_CR_AUTOENG_POS 12 -#define PHY_CR_AUTOENG_LEN 1 -#define PHY_CR_RE_AUTOENG_POS 9 -#define PHY_CR_RE_AUTOENG_LEN 1 -#define PHY_CR_DUPLEX_POS 8 -#define PHY_CR_DUPLEX_LEN 1 -#define REG_MII_BMCR_ENABLE_LOOPBACK 0x8140 -#define REG_MII_BMCR_DISABLE_LOOPBACK 0x9140 -#define REG_MII_BMSR 0x01 /* Basic mode status register */ -#define REG_MII_PHYSID1 0x02 /* PHYS ID 1 */ -#define REG_MII_PHYSID2 0x03 /* PHYS ID 2 */ -#define REG_MII_ADVERTISE 0x04 /* Advertisement control reg */ -#define PHY_MII_ADVERTISE_ASYPAUSE_POS 11 -#define PHY_MII_ADVERTISE_ASYPAUSE_LEN 1 -#define PHY_MII_ADVERTISE_PAUSE_POS 10 -#define PHY_MII_ADVERTISE_PAUSE_LEN 1 -#define PHY_MII_ADVERTISE_100FULL_POS 8 -#define PHY_MII_ADVERTISE_100FULL_LEN 1 -#define PHY_MII_ADVERTISE_100HALF_POS 7 -#define PHY_MII_ADVERTISE_100HALF_LEN 1 -#define PHY_MII_ADVERTISE_10FULL_POS 6 -#define PHY_MII_ADVERTISE_10FULL_LEN 1 -#define PHY_MII_ADVERTISE_10HALF_POS 5 -#define PHY_MII_ADVERTISE_10HALF_LEN 1 -#define REG_MII_LPA 0x05 /* Link partner ability reg */ -#define REG_MII_EXPANSION 0x06 /* Expansion register */ -#define REG_MII_NEXT_PAGE 0x07 /* Next page register */ -#define REG_MII_LPR_NEXT_PAGE 0x08 /* LPR next page register */ -#define REG_MII_CTRL1000 0x09 /* 1000BASE-T control */ -#define PHY_MII_CTRL1000_1000FULL_POS 9 -#define PHY_MII_CTRL1000_1000FULL_LEN 1 -#define PHY_MII_CTRL1000_1000HALF_POS 8 -#define PHY_MII_CTRL1000_1000HALF_LEN 1 -#define REG_MII_STAT1000 0x0A /* 1000BASE-T status */ -#define PHY_MII_STAT1000_CFG_ERROR_POS 15 -#define PHY_MII_STAT1000_CFG_ERROR_LEN 1 - -#define REG_MII_MMD_CTRL 0x0D /* MMD access control register */ -#define REG_MII_MMD_DATA 0x0E /* MMD access data register */ - -#define REG_MII_ESTATUS 0x0F /* Extended Status */ - -#define REG_MII_SPEC_CTRL 0x10 /* PHY specific func control */ -#define PHY_MII_SPEC_CTRL_CRS_ON_POS 3 -#define PHY_MII_SPEC_CTRL_CRS_ON_LEN 1 -#define REG_MII_SPEC_STATUS 0x11 /* PHY specific status */ -#define PHY_MII_SPEC_DUPLEX_POS 13 -#define PHY_MII_SPEC_DUPLEX_LEN 1 -#define REG_MII_INT_MASK 0x12 /* Interrupt mask register */ - -#ifdef AISC_MODE -#define PHY_INT_MASK_LINK_UP_POS 10 -#define PHY_INT_MASK_LINK_UP_LEN 1 -#define PHY_INT_MASK_LINK_DOWN_POS 11 -#define PHY_INT_MASK_LINK_DOWN_LEN 1 -#else //FPGA_MODE -#define PHY_INT_MASK_LINK_UP_POS 1 -#define PHY_INT_MASK_LINK_UP_LEN 1 -#define PHY_INT_MASK_LINK_DOWN_POS 0 -#define PHY_INT_MASK_LINK_DOWN_LEN 1 -#endif -#define REG_MII_INT_STATUS 0x13 /* Interrupt status register */ -#define PHY_INT_STAT_LINK_UP_POS 1 -#define PHY_INT_STAT_LINK_UP_LEN 1 -#define PHY_INT_STAT_LINK_DOWN_POS 0 -#define PHY_INT_STAT_LINK_DOWN_LEN 1 -#define REG_MII_DOWNG_CTRL 0x14 /* Speed auto downgrade control*/ -#define REG_MII_RERRCOUNTER 0x15 /* Receive error counter */ - -#define REG_MII_EXT_ADDR 0x1E /* Extended reg's address */ -#define REG_MII_EXT_DATA 0x1F /* Extended reg's date */ - -#define FXGMAC_EPHY_ID_MASK 0x0000ffff - -/* for ephy link capability - * Advertisement control register(0x04) - */ - /* Advertisement control register(0x04) */ -#define FXGMAC_ADVERTISE_SLCT 0x001f /* Selector bits */ -#define FXGMAC_ADVERTISE_CSMA 0x0001 /* Only selector supported */ -#define FXGMAC_ADVERTISE_1000FULL 0x0004 /* trt fir 1000BASE-T full duplex */ -#define FXGMAC_ADVERTISE_1000HALF 0x0008 /* try for 1000BASE-T half duplex */ -#define FXGMAC_ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ -#define FXGMAC_ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ -#define FXGMAC_ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ -#define FXGMAC_ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ -#define FXGMAC_ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */ -#define FXGMAC_ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */ -#define FXGMAC_ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */ -#define FXGMAC_ADVERTISE_RESV 0x1000 /* Unused... */ -#define FXGMAC_ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */ -#define FXGMAC_ADVERTISE_LPACK 0x4000 /* Ack link partners response */ -#define FXGMAC_ADVERTISE_NPAGE 0x8000 /* Next page bit */ - -/* 1000BASE-T Control register(0x09) */ -#define REG_BIT_ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */ -#define REG_BIT_ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */ - -#define REG_BIT_ADVERTISE_1000_CAP (REG_BIT_ADVERTISE_1000FULL | REG_BIT_ADVERTISE_1000HALF) -#define REG_BIT_ADVERTISE_100_10_CAP (FXGMAC_ADVERTISE_100FULL | FXGMAC_ADVERTISE_100HALF | FXGMAC_ADVERTISE_10FULL | FXGMAC_ADVERTISE_10HALF ) - -#ifndef SPEED_1000M -#define SPEED_1000M 1000 -#endif -#ifndef SPEED_100M -#define SPEED_100M 100 -#endif -#ifndef SPEED_10M -#define SPEED_10M 10 -#endif - -#ifndef SPEED_UNKNOWN -#define SPEED_UNKNOWN 0xffff -#endif - -#ifndef DUPLEX_FULL -#define DUPLEX_FULL 1 -#endif -#ifndef DUPLEX_HALF -#define DUPLEX_HALF 0 -#endif - -#ifndef BIT -#define BIT(n) (0x1<<(n)) -#endif - -#ifndef FUXI_EPHY_SPEED_MODE_BIT -#define FUXI_EPHY_SPEED_MODE 0xc000 -#define FUXI_EPHY_DUPLEX 0x2000 -#define FUXI_EPHY_SPEED_MODE_BIT 14 -#define FUXI_EPHY_DUPLEX_BIT 13 -#define FUXI_EPHY_LINK_STATUS_BIT 10 - -#endif - -#define FUXI_EPHY_SMI_SEL_PHY 0x0 -#define FUXI_EPHY_SMI_SEL_SDS_QSGMII 0x02 -#define FUXI_EPHY_SMI_SEL_SDS_SGMII 0x03 - -#define REG_MII_EXT_ANALOG_CFG3 0x52 -#define MII_EXT_ANALOG_CFG3_ADC_START_CFG_POS 14 -#define MII_EXT_ANALOG_CFG3_ADC_START_CFG_LEN 2 -// VGA bandwidth, default is 2 after reset. Set to 0 to mitigate unstable issue in 130m. -#define MII_EXT_ANALOG_CFG3_ADC_START_CFG_DEFAULT 0x0 -#define MII_EXT_ANALOG_CFG3_ON_TIME_CFG_POS 12 -#define MII_EXT_ANALOG_CFG3_ON_TIME_CFG_LEN 2 -#define MII_EXT_ANALOG_CFG3_VGA_AMP_GAIN_CFG_POS 8 -#define MII_EXT_ANALOG_CFG3_VGA_AMP_GAIN_CFG_LEN 4 -#define MII_EXT_ANALOG_CFG3_VGA_IBIAS_CFG_POS 4 -#define MII_EXT_ANALOG_CFG3_VGA_IBIAS_CFG_LEN 3 -#define MII_EXT_ANALOG_CFG3_OCP_CFG_POS 2 -#define MII_EXT_ANALOG_CFG3_OCP_CFG_LEN 2 -#define MII_EXT_ANALOG_CFG3_VGA_LPF_CFG_POS 0 -#define MII_EXT_ANALOG_CFG3_VGA_LPF_CFG_LEN 2 - -#define REG_MII_EXT_PMA_DEBUG_KCOEF 0x78 -#define MII_EXT_PMA_DEBUG_KCOEF_IPR_KCOEF_GE_LNG_POS 8 -#define MII_EXT_PMA_DEBUG_KCOEF_IPR_KCOEF_GE_LNG_LEN 6 -// After reset, it's 0x10. We need change it to 0x20 to make it easier to linkup in gigabit mode with long cable. -#define MII_EXT_PMA_DEBUG_KCOEF_IPR_KCOEF_GE_LNG_DEFAULT 0x20 -#define MII_EXT_PMA_DEBUG_KCOEF_IPR_KCOEF_DEFAULT_POS 0 -#define MII_EXT_PMA_DEBUG_KCOEF_IPR_KCOEF_DEFAULT_LEN 6 - -#define REG_MII_EXT_LPBK_REG 0x0a -#define REG_MII_EXT_LPBK_REG_ENABLE_LOOPBACK 0x3a18 -#define REG_MII_EXT_LPBK_REG_CLEAN_LOOPBACK 0x3a08 -#define REG_MII_EXT_SLEEP_CONTROL_REG 0x27 -#define REG_MII_EXT_SLEEP_REG_ENABLE_LOOPBACK 0x6812 -#define REG_MII_EXT_SLEEP_REG_CLEAN_LOOPBACK 0xe812 - -#define REG_MII_EXT_ANALOG_CFG2 0x51 -#define REG_MII_EXT_ANALOG_CFG2_LED_VALUE 0x4a9 -#define REG_MII_EXT_ANALOG_CFG8 0x57 -#define REG_MII_EXT_ANALOG_CFG8_LED_VALUE 0x274c - -#define REG_MII_EXT_COMMON_LED_CFG 0xA00B -#define REG_MII_EXT_COMMON_LED0_CFG 0xA00C -#define REG_MII_EXT_COMMON_LED0_CFG_VALUE_SOLUTION0 0x2600 -#define REG_MII_EXT_COMMON_LED0_CFG_VALUE_SOLUTION1 0x00 -#define REG_MII_EXT_COMMON_LED0_CFG_VALUE_SOLUTION2 0x20 -#define REG_MII_EXT_COMMON_LED0_CFG_VALUE_SOLUTION3 0x2600 -#define REG_MII_EXT_COMMON_LED1_CFG 0xA00D -#define REG_MII_EXT_COMMON_LED1_CFG_VALUE_SOLUTION0 0x1800 -#define REG_MII_EXT_COMMON_LED1_CFG_VALUE_SOLUTION1 0x00 -#define REG_MII_EXT_COMMON_LED1_CFG_VALUE_SOLUTION2 0x40 -#define REG_MII_EXT_COMMON_LED2_CFG 0xA00E -#define REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION0 0x00 -#define REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION2 0x07 -#define REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION3 0x20 -#define REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION4 0x1800 -#define REG_MII_EXT_COMMON_LED_BLINK_CFG 0xA00F -#define REG_MII_EXT_COMMON_LED_BLINK_CFG_SOLUTION2 0x0F - -#define REG_MII_EXT_COMMON_LED0_CFG_VALUE_SLEEP_SOLUTION3 0x2600 - -#define REG_MII_EXT_PKG_CFG0 0xA0 -#define REG_MII_EXT_PKG_CHECK_POS 14 -#define REG_MII_EXT_PKG_CHECK_LEN 2 -#define REG_MII_EXT_PKG_ENABLE_CHECK 0x2 -#define REG_MII_EXT_PKG_DISABLE_CHECK 0x1 -#define REG_MII_EXT_SLEEP_CONTROL1 0x27 -#define MII_EXT_SLEEP_CONTROL1_EN_POS 15 -#define MII_EXT_SLEEP_CONTROL1_EN_LEN 1 -#define MII_EXT_SLEEP_CONTROL1_PLLON_IN_SLP_POS 14 -#define MII_EXT_SLEEP_CONTROL1_PLLON_IN_SLP_LEN 1 -#define REG_MII_EXT_PKG_RX_VALID0 0xA3 -#define REG_MII_EXT_REG_RX_VALID1 0xA4 -#define REG_MII_EXT_REG_RX_OS0 0xA5 -#define REG_MII_EXT_REG_RX_OS1 0xA6 -#define REG_MII_EXT_REG_RX_US0 0xA7 -#define REG_MII_EXT_REG_RX_US1 0xA8 -#define REG_MII_EXT_REG_RX_ERR 0xA9 -#define REG_MII_EXT_REG_RX_0S_BAD 0xAA -#define REG_MII_EXT_REG_RX_FRAGMENT 0xAB -#define REG_MII_EXT_REG_RX_NOSFD 0xAC -#define REG_MII_EXT_REG_TX_VALID0 0xAD -#define REG_MII_EXT_REG_TX_VALID1 0xAE -#define REG_MII_EXT_REG_TX_OS0 0xAF -#define REG_MII_EXT_REG_TX_OS1 0xB0 -#define REG_MII_EXT_REG_TX_US0 0xB1 -#define REG_MII_EXT_REG_TX_US1 0xB2 -#define REG_MII_EXT_REG_TX_ERR 0xB3 -#define REG_MII_EXT_REG_TX_OS_BAD 0xB4 -#define REG_MII_EXT_REG_TX_FRAGMENT 0xB5 -#define REG_MII_EXT_REG_TX_NOSFD 0xB6 -#define REG_MII_EXT_REG_PMA_DBG0_ADC 0x13 -#define REG_MII_EXT_ENABLE_GIGA_POWER_SAVING_FOR_SHORT_CABLE 0x3538 -#define REG_MII_EXT_REG_CLD_REG0 0x3A0 -#define REG_MII_EXT_ENABLE_CLD_NP_WP 0xEB24 -#define REG_MII_EXT_REG_CLD_REG1 0x3CC -#define REG_MII_EXT_ENABLE_CLD_GT_HT_BT 0x7001 -#define REG_MMD_EEE_ABILITY_REG 0x3C -#define REG_MMD_EEE_ABILITY_VALUE 0x06 - -/* Below registers don't belong to GMAC, it has zero offset, not 0x2000 offset. mem_base + REG_XXX. */ -/***When issue happens, driver write this register to trigger pcie sniffer. ***/ -#define REG_PCIE_TRIGGER 0x1000 -#define PCIE_TRIGGER_CODE_TX_HANG 0x00000002 -#define PCIE_TRIGGER_CODE_LINKDOWN 0x00000003 - - -#define MGMT_EPHY_CTRL 0x1004 -/* check register address 0x1004 -* b[6:5] ephy_pause -* b[4:3] ephy_speed 0b10 1000m 0b01 100m -* b[2] ephy_duplex -* b[1] ephy_link -* b[0] ephy_reset.0-reset, 1-unreset. Should be set to 1 before use phy. -*/ -#define MGMT_EPHY_CTRL_RESET_POS 0 -#define MGMT_EPHY_CTRL_RESET_LEN 1 -#define MGMT_EPHY_CTRL_STA_EPHY_RESET 0 // 0: reset state. -#define MGMT_EPHY_CTRL_STA_EPHY_RELEASE 1 // 1: release state. -#define MGMT_EPHY_CTRL_STA_EPHY_LINKUP 2 // 1: link up; 0: link down. -#define MGMT_EPHY_CTRL_STA_EPHY_LINKUP_POS 1 -#define MGMT_EPHY_CTRL_STA_EPHY_LINKUP_LEN 1 -#define MGMT_EPHY_CTRL_STA_EPHY_DUPLEX_POS 2 // ephy duplex -#define MGMT_EPHY_CTRL_STA_EPHY_DUPLEX_LEN 1 // - -#define MGMT_EPHY_CTRL_STA_SPEED_POS 3 -#define MGMT_EPHY_CTRL_STA_SPEED_LEN 2 -#define MGMT_EPHY_CTRL_STA_SPEED_MASK 0x18 - -#define MGMT_EPHY_CTRL_ERROR_VAULE 0xFFFFFFFF - -#define MGMT_PCIE_EP_CTRL 0x1008 - -#define MGMT_PCIE_EP_CTRL_DBI_CS_EN_POS 0 -#define MGMT_PCIE_EP_CTRL_DBI_CS_EN_LEN 1 - -#define MGMT_PCIE_CFG_CTRL 0x8BC -#define PCIE_CFG_CTRL_DEFAULT_VAL 0x7ff40 - -#define MGMT_PCIE_CFG_CTRL_CS_EN_POS 0 -#define MGMT_PCIE_CFG_CTRL_CS_EN_LEN 1 - -/***power management ***/ -#define WOL_CTL 0x100C -#define WOL_PKT_EN_POS 1 //set means magic and remote packet wakeup enable -#define WOL_PKT_EN_LEN 1 -#define WOL_LINKCHG_EN_POS 0 //set means link change wakeup enable -#define WOL_LINKCHG_EN_LEN 1 - -#define OOB_WOL_CTRL 0x1010 -#define OOB_WOL_CTRL_DIS_POS 0 -#define OOB_WOL_CTRL_DIS_LEN 1 - -#define MGMT_INT_CTRL0 0x1100 -/* b3:0 per rx ch interrupt - * b7:4 per tx ch interrupt - * b8 Safety interrupt signal for un-correctable error - * b9 Safety interrupt signal for correctable error - * b10 Interrupt signal to host system - * b11 Magic Packet Received or Remote Wake-up Packet Received - * b12 ethernet phy interrupt - */ - -/* MAC management registers bit positions and sizes */ -#define MGMT_INT_CTRL0_INT_MASK_POS 16 -#define MGMT_INT_CTRL0_INT_MASK_LEN 16 -#define MGMT_INT_CTRL0_INT_MASK_MASK 0xFFFF -#define MGMT_INT_CTRL0_INT_MASK_RXCH 0xF -#define MGMT_INT_CTRL0_INT_MASK_TXCH 0x10 -#define MGMT_INT_CTRL0_INT_MASK_EX_PMT 0xF7FF -#define MGMT_INT_CTRL0_INT_MASK_DISABLE 0xF000 - -#define MGMT_INT_CTRL0_INT_STATUS_POS 0 -#define MGMT_INT_CTRL0_INT_STATUS_LEN 16 -#define MGMT_INT_CTRL0_INT_STATUS_MASK 0xFFFF -#define MGMT_INT_CTRL0_INT_STATUS_RX 0x0001 -#define MGMT_INT_CTRL0_INT_STATUS_TX 0x0010 -#define MGMT_INI_CTRL0_INT_STATUS_TX_INVERSE 0xFFEF -#define MGMG_INT_CTRL0_INT_STATUS_PHY_INVERSE 0xFFDF -#define MGMT_INT_CTRL0_INT_STATUS_PHY 0x0020 - -#define MGMT_INT_CTRL0_INT_MASK_RXCH_POS 16 -#define MGMT_INT_CTRL0_INT_STATUS_RXCH_POS 0 -#define MGMT_INT_CTRL0_INT_STATUS_RXCH_LEN 4 -#define MGMT_INT_CTRL0_INT_STATUS_RXCH_MASK 0xF -#define MGMT_INT_CTRL0_INT_STATUS_RXTX_LEN 5 -#define MGMT_INT_CTRL0_INT_STATUS_RXTX_MASK 0x1F -#define MGMT_INT_CTRL0_INT_STATUS_RXTXPHY_MASK 0x3F - -#define MGMT_INT_CTRL0_INT_MASK_TXCH_POS 20 -#define MGMT_INT_CTRL0_INT_STATUS_TXCH_POS 4 -#define MGMT_INT_CTRL0_INT_STATUS_TXCH_LEN 1 -#define MGMT_INT_CTRL0_INT_STATUS_TXCH_MASK 0x1 - - -/* Interrupt Ctrl1 */ -#define INT_CTRL1 0x1104 -#define INT_CTRL1_TMR_CNT_CFG_MAX_POS 0 /* Timer counter cfg max. Default 0x19, 1us. */ -#define INT_CTRL1_TMR_CNT_CFG_MAX_LEN 10 -#define INT_CTRL1_TMR_CNT_CFG_DEF_VAL 0x19 -#define INT_CTRL1_MSI_AIO_EN_POS 16 -#define INT_CTRL1_MSI_AIO_EN_LEN 1 - -/* Interrupt Moderation */ -#define INT_MOD 0x1108 -#define INT_MOD_TX_POS 16 -#define INT_MOD_TX_LEN 12 -#define INT_MOD_RX_POS 0 -#define INT_MOD_RX_LEN 12 -#define INT_MOD_IN_US 200 /*in us*/ - -/* PCIE LTR 2 working modes: -Two working mode: -1. SW trigger -LTR idle threshold timer set as 0, enable LTR enable will trigger one LTR message -Note: PCIe cfg enable should set in initilization before enable LTR. -2. HW auto trigger -LTR idle threshold timer set as one non-zero value, HW monitor system status, -when system idle timer over threshold, HW send out LTR message -system exit idle state, send out one LTR exit message. -*/ -#define LTR_CTRL 0x1130 -#define LTR_CTRL_IDLE_THRE_TIMER_POS 16 -#define LTR_CTRL_IDLE_THRE_TIMER_LEN 14 /* in 8ns units*/ -#define LTR_CTRL_IDLE_THRE_TIMER_VAL 0x3FFF -#define LTR_CTRL_EN_POS 0 -#define LTR_CTRL_EN_LEN 1 - -#define LTR_CTRL1 0x1134 /* LTR latency message, only for SW enable. */ -#define LTR_CTRL1_LTR_MSG_POS 0 -#define LTR_CTRL1_LTR_MSG_LEN 32 - -#define LTR_CTRL2 0x1138 -#define LTR_CTRL2_DBG_DATA_POS 0 -#define LTR_CTRL2_DBG_DATA_LEN 32 - -#define LTR_IDLE_ENTER 0x113C /* LTR_CTRL3, LTR latency message, only for System IDLE Start. */ -#define LTR_IDLE_ENTER_POS 0 -#define LTR_IDLE_ENTER_LEN 10 -#define LTR_IDLE_ENTER_USVAL 900 -#define LTR_IDLE_ENTER_SCALE_POS 10 -#define LTR_IDLE_ENTER_SCALE_LEN 5 -#define LTR_IDLE_ENTER_SCALE 2 /* 0-1ns, 1-32ns, 2-1024ns, 3-32,768ns, 4-1,048,576ns, 5-33,554,432ns, 110-111-Not Permitted.*/ -#define LTR_IDLE_ENTER_REQUIRE_POS 15 -#define LTR_IDLE_ENTER_REQUIRE_LEN 1 -#define LTR_IDLE_ENTER_REQUIRE 1 - -#define LTR_IDLE_EXIT 0x1140 /* LTR_CTRL4, LTR latency message, only for System IDLE End. */ -#define LTR_IDLE_EXIT_POS 0 -#define LTR_IDLE_EXIT_LEN 10 -#define LTR_IDLE_EXIT_USVAL 2 -#define LTR_IDLE_EXIT_SCALE_POS 10 -#define LTR_IDLE_EXIT_SCALE_LEN 5 -#define LTR_IDLE_EXIT_SCALE 2 -#define LTR_IDLE_EXIT_REQUIRE_POS 15 -#define LTR_IDLE_EXIT_REQUIRE_LEN 1 -#define LTR_IDLE_EXIT_REQUIRE 1 - -#define LPW_CTRL 0x1188 -#define LPW_CTRL_L1SS_EN_POS 22 -#define LPW_CTRL_L1SS_EN_LEN 1 -#define LPW_CTRL_L1SS_SEL_POS 21 /* 0 - up to both CFG0x158 and reg1188 L1ss setting. 1 - up to CFG0x158 L1ss setting. */ -#define LPW_CTRL_L1SS_SEL_LEN 1 -#define LPW_CTRL_L1SS_SEL_CFG 1 /* */ -#define LPW_CTRL_ASPM_L1_CPM_POS 19 /*L1.CPM mode enable bit. Default 0,set as 1 enable this mode. clkreq pin need to connect RC*/ -#define LPW_CTRL_ASPM_L1_CPM_LEN 1 -#define LPW_CTRL_ASPM_L0S_EN_POS 17 -#define LPW_CTRL_ASPM_L0S_EN_LEN 1 -#define LPW_CTRL_ASPM_L1_EN_POS 16 -#define LPW_CTRL_ASPM_L1_EN_LEN 1 -#define LPW_CTRL_ASPM_LPW_EN_POS 9 /* application ready to enter L23. */ -#define LPW_CTRL_ASPM_LPW_EN_LEN 1 -#define LPW_CTRL_SYS_CLK_125_SEL_POS 8 /* system 125M select: 125M or 62.5MHz. Default: 125MHz.*/ -#define LPW_CTRL_SYS_CLK_125_SEL_LEN 1 -#define LPW_CTRL_PCIE_RADM_CG_EN_POS 5 /* clock gating enable bit of PCIe Radm clock. Default 1; set as 1, enable gating.*/ -#define LPW_CTRL_PCIE_RADM_CG_EN_LEN 1 -#define LPW_CTRL_PCIE_CORE_CG_EN_POS 4 /* clock gating enable bit of PCIe Core clock. Default 1; set as 1, enable gating.*/ -#define LPW_CTRL_PCIE_CORE_CG_EN_LEN 1 -#define LPW_CTRL_PCIE_AXI_CG_EN_POS 3 /* clock gating enable bit of PCIe AXI clock.Default 1; set as 1, enable gating.*/ -#define LPW_CTRL_PCIE_AXI_CG_EN_LEN 1 -#define LPW_CTRL_GMAC_AXI_CG_EN_POS 2 /* clock gating enable bit of GMAC AXI clock. Default 1; set as 1, enable gating.*/ -#define LPW_CTRL_GMAC_AXI_CG_EN_LEN 1 -#define LPW_CTRL_MDIO2APB_CG_EN_POS 1 /* clock gating enable bit of MDIO2APB, default 1. Set as 1, enable clock gating feature. */ -#define LPW_CTRL_MDIO2APB_CG_EN_LEN 1 -#define LPW_CTRL_OTP_CLK_ON_POS 0 /* Turn on before SW OTP operation, default 1. */ -#define LPW_CTRL_OTP_CLK_ON_LEN 1 - -#define MSI_PBA_REG 0x1300 -#define SYS_RESET_REG 0x152C -#define SYS_RESET_POS 31 -#define SYS_RESET_LEN 1 - -#define REG_PCIE_PSM_STATE 0x1994 /* PCIe PHY power state. */ -#define PCIE_PSM_STATE_POS 0 -#define PCIE_PSM_STATE_LEN 4 -#define PCIE_PSM_STATE_P0 2 -#define PCIE_PSM_STATE_P0s 3 -#define PCIE_PSM_STATE_P1 4 -#define PCIE_PSM_STATE_P1_CPM 5 -#define PCIE_PSM_STATE_P1_1 6 -#define PCIE_PSM_STATE_P1_2 7 -#define PCIE_PSM_STATE_P2 8 - -#define REG_PCIE_SERDES_STATUS 0x1998 -#define PCIE_SERDES_STATUS_DRV_ON_POS 11 -#define PCIE_SERDES_STATUS_DRV_ON_LEN 1 -#define PCIE_SERDES_STATUS_RX_PD_POS 10 -#define PCIE_SERDES_STATUS_RX_PD_LEN 1 -#define PCIE_SERDES_STATUS_PI_PD_POS 9 -#define PCIE_SERDES_STATUS_PI_PD_LEN 1 -#define PCIE_SERDES_STATUS_SIGDET_ON_POS 8 -#define PCIE_SERDES_STATUS_SIGDET_ON_LEN 1 -#define PCIE_SERDES_STATUS_TX_VCM_POS 7 -#define PCIE_SERDES_STATUS_TX_VCM_LEN 1 -#define PCIE_SERDES_STATUS_RX_RT50_POS 6 -#define PCIE_SERDES_STATUS_RX_RT50_LEN 1 -#define PCIE_SERDES_STATUS_BEACON_ON_POS 5 -#define PCIE_SERDES_STATUS_BEACON_ON_LEN 1 -#define PCIE_SERDES_STATUS_PLL_ON_POS 4 -#define PCIE_SERDES_STATUS_PLL_ON_LEN 1 -#define PCIE_SERDES_STATUS_REFCLK_ON_POS 3 -#define PCIE_SERDES_STATUS_REFCLK_ON_LEN 1 -#define PCIE_SERDES_STATUS_LDO_ON_POS 2 -#define PCIE_SERDES_STATUS_LDO_ON_LEN 1 -#define PCIE_SERDES_STATUS_HW_EN_SDS_BIAS_POS 1 -#define PCIE_SERDES_STATUS_HW_EN_SDS_BIAS_LEN 1 -#define PCIE_SERDES_STATUS_HW_BIAS_ON_POS 0 -#define PCIE_SERDES_STATUS_HW_BIAS_ON_LEN 1 - -#define REG_PCIE_SERDES_PLL 0x199C -#define PCIE_SERDES_PLL_AUTOOFF_POS 0 -#define PCIE_SERDES_PLL_AUTOOFF_LEN 1 - -#define NS_OF_GLB_CTL 0x1B00 -#define NS_TPID_PRO 0x1B04 -#define NS_LUT_ROMOTE0 0x1B08 -#define NS_LUT_ROMOTE1 0X1B0C -#define NS_LUT_ROMOTE2 0X1B10 -#define NS_LUT_ROMOTE3 0X1B14 -#define NS_LUT_TARGET0 0X1B18 -#define NS_LUT_TARGET1 0X1B1C -#define NS_LUT_TARGET2 0X1B20 -#define NS_LUT_TARGET3 0X1B24 -#define NS_LUT_SOLICITED0 0X1B28 -#define NS_LUT_SOLICITED1 0X1B2C -#define NS_LUT_SOLICITED2 0X1B30 -#define NS_LUT_SOLICITED3 0X1B34 -#define NS_LUT_MAC_ADDR 0X1B38 -#define NS_LUT_MAC_ADDR_CTL 0X1B3C -#define NS_LUT_TARGET4 0X1B78 -#define NS_LUT_TARGET5 0X1B7c -#define NS_LUT_TARGET6 0X1B80 -#define NS_LUT_TARGET7 0X1B84 - -#define NS_OF_GLB_CTL_TX_CLK_EN_POS 2 -#define NS_OF_GLB_CTL_TX_CLK_EN_LEN 1 -#define NS_OF_GLB_CTL_RX_CLK_EN_POS 1 -#define NS_OF_GLB_CTL_RX_CLK_EN_LEN 1 -#define NS_OF_GLB_CTL_EN_POS 0 -#define NS_OF_GLB_CTL_EN_ELN 1 -#define NS_TPID_PRO_STPID_POS 16 -#define NS_TPID_PRO_STPID_LEN 16 -#define NS_TPID_PRO_CTPID_POS 0 -#define NS_TPID_PRO_CTPID_LEN 16 -#define NS_LUT_DST_CMP_TYPE_POS 19 -#define NS_LUT_DST_CMP_TYPE_LEN 1 -#define NS_LUT_DST_IGNORED_POS 18 -#define NS_LUT_DST_IGNORED_LEN 1 -#define NS_LUT_REMOTE_AWARED_POS 17 -#define NS_LUT_REMOTE_AWARED_LEN 1 -#define NS_LUT_TARGET_ISANY_POS 16 -#define NS_LUT_TARGET_ISANY_LEN 1 -#define NS_LUT_MAC_ADDR_LOW_POS 0 -#define NS_LUT_MAC_ADDR_LOW_LEN 16 - -/* RSS implementation registers, 20210817 */ - -/* 10 RSS key registers */ -#define MGMT_RSS_KEY0 0x1020 -#define MGMT_RSS_KEY9 0x1044 -#define MGMT_RSS_KEY_REG_INC 0x4 - -/* RSS control register */ -#define MGMT_RSS_CTRL 0x1048 -/* b31 enable - * b12:10 indirection table size. 2^(val+1) - * b9:8 default Queue NO. - * b7:0 hash type or options - */ - -/* RSS ctrl register bit definitions. - * [0] ipv4 - * [1] tcpv4 - * [2] udpv4 - * [3] ipv6 - * [4] tcpv6 - * [5] udpv6 -* [6] only ipv4 udp check IP hash -* [7] only ipv6 udp check IP hash - */ -#define MGMT_RSS_CTRL_OPT_POS 0 -#define MGMT_RSS_CTRL_OPT_LEN 8 -#define MGMT_RSS_CTRL_OPT_MASK 0xFF -#define MGMT_RSS_CTRL_IPV4_EN 0x01 -#define MGMT_RSS_CTRL_TCPV4_EN 0x02 -#define MGMT_RSS_CTRL_UDPV4_EN 0x04 -#define MGMT_RSS_CTRL_IPV6_EN 0x08 -#define MGMT_RSS_CTRL_TCPV6_EN 0x10 -#define MGMT_RSS_CTRL_UDPV6_EN 0x20 -#define MGMT_RSS_CTRL_IPV4 0x0 -#define MGMT_RSS_CTRL_IPV4 0x0 - -#define MGMT_RSS_CTRL_DEFAULT_Q_POS 8 -#define MGMT_RSS_CTRL_DEFAULT_Q_LEN 2 -#define MGMT_RSS_CTRL_DEFAULT_Q_MASK 0x3 - -#define MGMT_RSS_CTRL_TBL_SIZE_POS 10 -#define MGMT_RSS_CTRL_TBL_SIZE_LEN 3 -#define MGMT_RSS_CTRL_TBL_SIZE_MASK 0x7 - -#define MAC_RSSCR_RSSE_POS 31 -#define MAC_RSSCR_RSSE_LEN 1 - -/* rss indirection table (IDT) */ -#define MGMT_RSS_IDT 0x1050 -/* b0:1 entry0 - * b2:3 entry1 - * ... - */ -#define MGMT_RSS_IDT_REG_INC 4 -#define MGMT_RSS_IDT_ENTRY_PER_REG 16 -#define MGMT_RSS_IDT_ENTRY_MASK 0x3 -#define MAC_CRC_LENGTH 4 - - /* osc_ctrl */ -#define MGMT_XST_OSC_CTRL 0x1158 -#define MGMT_XST_OSC_CTRL_XST_OSC_SEL_POS 2 -#define MGMT_XST_OSC_CTRL_XST_OSC_SEL_LEN 1 -#define MGMT_XST_OSC_CTRL_EN_OSC_POS 1 -#define MGMT_XST_OSC_CTRL_EN_OSC_LEN 1 -#define MGMT_XST_OSC_CTRL_EN_XST_POS 0 -#define MGMT_XST_OSC_CTRL_EN_XST_LEN 1 - -/* for WPI, yzhang, 20210826 */ -#define MGMT_WPI_CTRL0 0x1160 - /* b1:0 wpi_mode "2b00: normal working mode; 2b01: WPI write mode, work in sleep mode; 2b10: WPI read mode, work after sleep before normal working mode;" - * b2 ram_op_done Each row ram read done, SW can start read after done; - * b3 wpi_op_done WPI read done for the total packet; - * b17:4 wpi_pkt_len WOL packet length, unit byte; - * b31 wpi_fail Error status in Sleep mode; - */ -#define MGMT_WPI_CTRL0_WPI_MODE_POS 0 -#define MGMT_WPI_CTRL0_WPI_MODE_LEN 2 -#define MGMT_WPI_CTRL0_WPI_MODE_NORMAL 0x00 // normal working mode. -#define MGMT_WPI_CTRL0_WPI_MODE_WR 0x01 // WPI write mode, work in sleep mode. -#define MGMT_WPI_CTRL0_WPI_MODE_RD 0x02 // WPI read mode, work after sleep before normal working mode. -#define MGMT_WPI_CTRL0_RAM_OP_DONE 0x4 -#define MGMT_WPI_CTRL0_WPI_OP_DONE 0x8 -#define MGMT_WPI_CTRL0_WPI_PKT_LEN_POS 4 -#define MGMT_WPI_CTRL0_WPI_PKT_LEN_LEN 14 -#define MGMT_WPI_CTRL0_WPI_FAIL 0x80000000 - -#define MGMT_WPI_CTRL1_DATA 0x1164 - -#define MGMT_WOL_CTRL 0x1530 - /* b0 link_chg_status 1: waken by link-change - * b1 mgk_pkt_status 1: waken by magic-packet - * b2 rwk_pkt_status 1: waken by remote patten packet - */ -#define MGMT_WOL_CTRL_WPI_LINK_CHG 1 -#define MGMT_WOL_CTRL_WPI_MGC_PKT 2 -#define MGMT_WOL_CTRL_WPI_RWK_PKT 4 -#define MGMT_WOL_CTRL_WPI_RWK_PKT_NUMBER 0x010000 - -#define MGMT_RMK_CTRL 0x1400 - -#define MGMT_SIGDET 0x17F8 -#define MGMT_SIGDET_POS 13 -#define MGMT_SIGDET_LEN 3 -#define MGMT_SIGDET_55MV 7 -#define MGMT_SIGDET_50MV 6 -#define MGMT_SIGDET_45MV 5 //default value -#define MGMT_SIGDET_40MV 4 -#define MGMT_SIGDET_35MV 3 -#define MGMT_SIGDET_30MV 2 -#define MGMT_SIGDET_25MV 1 -#define MGMT_SIGDET_20MV 0 - -#define FXGMAC_MTL_REG(pdata, n, reg) \ - ((pdata)->mac_regs + MTL_Q_BASE + ((n) * MTL_Q_INC) + (reg)) - -#define FXGMAC_DMA_REG(channel, reg) ((channel)->dma_regs + (reg)) - -//#define RSS_Q_COUNT 4 -#define MSI_ID_RXQ0 0 -#define MSI_ID_RXQ1 1 -#define MSI_ID_RXQ2 2 -#define MSI_ID_RXQ3 3 -#define MSI_ID_TXQ0 4 - -#if 1//msi table modify to 6 0~3 rx 4 tx 5 phy/other -#define MSI_ID_PHY_OTHER 5 -//#define MSI_ID_TXQ2 6 -//#define MSI_ID_TXQ3 7 -//#define MSI_ID_SFTUE 8 -//#define MSI_ID_SFTCE 9 -//#define MSI_ID_SBD 10 -//#define MSI_ID_PMT 11 -//#define MSI_ID_PHY 12 - -#define MSIX_TBL_MAX_NUM 6 -#define MSIX_TBL_RXTX_NUM 5 - -#else -#define MSI_ID_TXQ1 5 -#define MSI_ID_TXQ2 6 -#define MSI_ID_TXQ3 7 -#define MSI_ID_SFTUE 8 -#define MSI_ID_SFTCE 9 -#define MSI_ID_SBD 10 -#define MSI_ID_PMT 11 -#define MSI_ID_PHY 12 - -#define MSIX_TBL_MAX_NUM 16 -#define MSIX_TBL_RXTX_NUM 8 -#endif -#define MSIX_TBL_BASE_ADDR 0x1200 -#define MSIX_TBL_MASK_OFFSET 0xC -#define MSIX_TBL_DATA_OFFSET 0x8 -#define MSIX_TBL_ADDR_OFFSET 0x0 - -/******************************************************************* - efuse entry. val31:0 -> offset15:0 - offset7:0 - offset15:8 - val7:0 - val15:8 - val23:16 - val31:24 -*******************************************************************/ -#define EFUSE_OP_CTRL_0 0x1500 -#define EFUSE_OP_WR_DATA_POS 16 -#define EFUSE_OP_WR_DATA_LEN 8 -#define EFUSE_OP_ADDR_POS 8 -#define EFUSE_OP_ADDR_LEN 8 -#define EFUSE_OP_START_POS 2 -#define EFUSE_OP_START_LEN 1 -#define EFUSE_OP_MODE_POS 0 -#define EFUSE_OP_MODE_LEN 2 -#define EFUSE_OP_MODE_ROW_WRITE 0x0 -#define EFUSE_OP_MODE_ROW_READ 0x1 -#define EFUSE_OP_MODE_AUTO_LOAD 0x2 -#define EFUSE_OP_MODE_READ_BLANK 0x3 - -#define EFUSE_OP_CTRL_1 0x1504 -#define EFUSE_OP_RD_DATA_POS 24 -#define EFUSE_OP_RD_DATA_LEN 8 -#define EFUSE_OP_BIST_ERR_ADDR_POS 16 -#define EFUSE_OP_BIST_ERR_ADDR_LEN 8 -#define EFUSE_OP_BIST_ERR_CNT_POS 8 -#define EFUSE_OP_BIST_ERR_CNT_LEN 8 -#define EFUSE_OP_PGM_PASS_POS 2 -#define EFUSE_OP_PGM_PASS_LEN 1 -#define EFUSE_OP_DONE_POS 1 -#define EFUSE_OP_DONE_LEN 1 - -//efuse layout refer to http://redmine.motor-comm.com/issues/3856 -#define EFUSE_FISRT_UPDATE_ADDR 255 -#define EFUSE_SECOND_UPDATE_ADDR 209 -#define FUXI_EFUSE_MAX_ENTRY 39 -#define FUXI_EFUSE_MAX_ENTRY_UNDER_LED_COMMON 24 -#define EFUSE_PATCH_ADDR_START_BYTE 0 -#define EFUSE_PATCH_DATA_START_BYTE 2 -#define EFUSE_REGION_A_B_LENGTH 18 -#define EFUSE_EACH_PATH_SIZE 6 - -#define EFUSE_REVID_REGISTER 0x0008 -#define EFUSE_SUBSYS_REGISTER 0x002C -#define MACA0LR_FROM_EFUSE 0x1520 //mac[5]->bit7:0, mac[4]->bit15:8, mac[3]->bit23:16, mac[2]->bit31:24. -#define MACA0HR_FROM_EFUSE 0x1524 //mac[1]->bit7:0, mac[0]->bit15:8. mac[6] = {00, 01, 02, 03, 04, 05} 00-01-02-03-04-05. - -#define EFUSE_LED_ADDR 0x00 -#define EFUSE_LED_POS 0 -#define EFUSE_LED_LEN 5 -#define EFUSE_OOB_ADDR 0x07 -#define EFUSE_OOB_POS 2 -#define EFUSE_OOB_LEN 1 -#define EFUSE_LED_SOLUTION0 0 -#define EFUSE_LED_SOLUTION1 1 -#define EFUSE_LED_SOLUTION2 2 -#define EFUSE_LED_SOLUTION3 3 -#define EFUSE_LED_SOLUTION4 4 -#define EFUSE_LED_COMMON_SOLUTION 0x1F - -/******************** Below for pcie configuration register. *********************/ -#define REG_PCI_VENDOR_ID 0x0 /* WORD reg */ -#define REG_PCI_DEVICE_ID 0x2 /* WORD reg */ -#define PCI_DEVICE_ID_FUXI 0x6801 - -#define REG_PCI_COMMAND 0x4 -#define PCI_COMMAND_IO_SPACE_POS 0 -#define PCI_COMMAND_IO_SPACE_LEN 1 -#define PCI_COMAMND_MEM_SPACE_POS 1 -#define PCI_COMAMND_MEM_SPACE_LEN 1 -#define PCI_COMMAND_MASTER_POS 2 -#define PCI_COMMAND_MASTER_LEN 1 -#define PCI_COMMAND_DIS_INT_POS 10 -#define PCI_COMMAND_DIS_INT_LEN 1 -#define PCI_COMMAND_INTX_STATUS_POS 19 -#define PCI_COMMAND_INTX_STATUS_LEN 1 - -#define REG_PCI_REVID 0x8 /* BYTE reg */ -#define REG_PCI_PROGRAM_INTF 0x9 /* BYTE reg */ /* PCI Class Program Interface */ -#define REG_PCI_SUB_CLASS 0xA /* BYTE reg */ -#define REG_PCI_BASE_CLASS 0xB /* BYTE reg */ -#define REG_CACHE_LINE_SIZE 0xC - - -#define REG_MEM_BASE 0x10 /* DWORD or QWORD reg */ -#define REG_MEM_BASE_HI 0x14 /* DWORD or QWORD reg */ - -#define REG_IO_BASE 0x20 /* DWORD reg */ - -#define REG_PCI_SUB_VENDOR_ID 0x2C /* WORD reg */ -#define REG_PCI_SUB_DEVICE_ID 0x2E /* WORD reg */ - -#define REG_INT_LINE 0x3C /* BYTE reg */ - -#define REG_PM_STATCTRL 0x44 /* WORD reg */ -#define PM_STATCTRL_PWR_STAT_POS 0 -#define PM_STATCTRL_PWR_STAT_LEN 2 -#define PM_STATCTRL_PWR_STAT_D3 3 -#define PM_STATCTRL_PWR_STAT_D0 0 -#define PM_CTRLSTAT_PME_EN_POS 8 -#define PM_CTRLSTAT_PME_EN_LEN 1 -#define PM_CTRLSTAT_DATA_SEL_POS 9 -#define PM_CTRLSTAT_DATA_SEL_LEN 4 -#define PM_CTRLSTAT_DATA_SCAL_POS 13 -#define PM_CTRLSTAT_DATA_SCAL_LEN 2 -#define PM_CTRLSTAT_PME_STAT_POS 15 -#define PM_CTRLSTAT_PME_STAT_LEN 1 - -#define REG_DEVICE_CTRL1 0x78 -#define DEVICE_CTRL1_CONTROL_POS 0 -#define DEVICE_CTRL1_CONTROL_LEN 16 -#define DEVICE_CTRL1_STATUS_POS 16 -#define DEVICE_CTRL1_STATUS_LEN 16 - -#define REG_PCI_LINK_CTRL 0x80 -#define PCI_LINK_CTRL_CONTROL_POS 0 -#define PCI_LINK_CTRL_CONTROL_LEN 16 -#define PCI_LINK_CTRL_ASPM_CONTROL_POS 0 -#define PCI_LINK_CTRL_ASPM_CONTROL_LEN 2 -#define PCI_LINK_CTRL_L1_STATUS 2 -#define PCI_LINK_CTRL_CONTROL_CPM_POS 8 /*L1.CPM mode enable bit. Default 0,set as 1 enable this mode. clkreq pin need to connect RC*/ -#define PCI_LINK_CTRL_CONTROL_CPM_LEN 1 -#define PCI_LINK_CTRL_STATUS_POS 16 -#define PCI_LINK_CTRL_STATUS_LEN 16 - -#define REG_DEVICE_CTRL2 0x98 /* WORD reg */ -#define DEVICE_CTRL2_LTR_EN_POS 10 /* Enable from BIOS side. */ -#define DEVICE_CTRL2_LTR_EN_LEN 1 - -#define REG_MSIX_CAPABILITY 0xB0 - -/* ASPM L1ss PM Substates */ -#define REG_ASPM_L1SS_CAP 0x154 /* Capabilities Register */ -#define ASPM_L1SS_CAP_PCIPM_L1_2_POS 0 /* PCI-PM L1.2 Supported */ -#define ASPM_L1SS_CAP_PCIPM_L1_2_LEN 1 -#define ASPM_L1SS_CAP_PCIPM_L1_1_POS 1 /* PCI-PM L1.1 Supported */ -#define ASPM_L1SS_CAP_PCIPM_L1_1_LEN 1 -#define ASPM_L1SS_CAP_ASPM_L1_2_POS 2 /* ASPM L1.2 Supported */ -#define ASPM_L1SS_CAP_ASPM_L1_2_LEN 1 -#define ASPM_L1SS_CAP_ASPM_L1_1_POS 3 /* ASPM L1.1 Supported */ -#define ASPM_L1SS_CAP_ASPM_L1_1_LEN 1 -#define ASPM_L1SS_CAP_L1_PM_SS_POS 4 /* L1 PM Substates Supported */ -#define ASPM_L1SS_CAP_L1_PM_SS_LEN 1 -#define ASPM_L1SS_CAP_CM_RESTORE_TIME_POS 8 /* Port Common_Mode_Restore_Time */ -#define ASPM_L1SS_CAP_CM_RESTORE_TIME_LEN 8 -#define ASPM_L1SS_CAP_P_PWR_ON_SCALE_POS 16 /* Port T_POWER_ON scale */ -#define ASPM_L1SS_CAP_P_PWR_ON_SCALE_LEN 2 -#define ASPM_L1SS_CAP_P_PWR_ON_VALUE_POS 19 /* Port T_POWER_ON value */ -#define ASPM_L1SS_CAP_P_PWR_ON_VALUE_LEN 5 - -#define REG_ASPM_L1SS_CTRL1 0x158 -#define REG_ASPM_L1SS_CTRL1_VALUE 0x405e000f -#define ASPM_L1SS_CTRL1_L12_PCIPM_EN_POS 0 /* L1.2 in D3 state. */ -#define ASPM_L1SS_CTRL1_L12_PCIPM_EN_LEN 1 -#define ASPM_L1SS_CTRL1_L11_PCIPM_EN_POS 1 /* L1.1 in D3 state. */ -#define ASPM_L1SS_CTRL1_L11_PCIPM_EN_LEN 1 -#define ASPM_L1SS_CTRL1_L12_EN_POS 2 -#define ASPM_L1SS_CTRL1_L12_EN_LEN 1 -#define ASPM_L1SS_CTRL1_L11_EN_POS 3 -#define ASPM_L1SS_CTRL1_L11_EN_LEN 1 -#define ASPM_L1SS_CTRL1_CM_RESTORE_TIME_POS 8 /* Common_Mode_Restore_Time */ -#define ASPM_L1SS_CTRL1_CM_RESTORE_TIME_LEN 8 -#define ASPM_L1SS_CTRL1_LTR_L12_TH_VALUE_POS 16 /* LTR_L1.2_THRESHOLD_Value */ -#define ASPM_L1SS_CTRL1_LTR_L12_TH_VALUE_LEN 10 -#define ASPM_L1SS_CTRL1_L12_TH_SCALE_POS 29 /* LTR_L1.2_THRESHOLD_Scale */ -#define ASPM_L1SS_CTRL1_L12_TH_SCALE_LEN 3 - -#define REG_ASPM_L1SS_CTL2 0x15c /* Control 2 Register */ - -#define REG_ASPM_CONTROL 0x70C -#define ASPM_L1_IDLE_THRESHOLD_POS 27 -#define ASPM_L1_IDLE_THRESHOLD_LEN 3 -#define ASPM_L1_IDLE_THRESHOLD_1US 0 -#define ASPM_L1_IDLE_THRESHOLD_2US 1 -#define ASPM_L1_IDLE_THRESHOLD_4US 2 -#define ASPM_L1_IDLE_THRESHOLD_8US 3 /* default value after reset. */ -#define ASPM_L1_IDLE_THRESHOLD_16US 4 -#define ASPM_L1_IDLE_THRESHOLD_32US 5 -#define ASPM_L1_IDLE_THRESHOLD_64US 6 - -#define REG_POWER_EIOS 0x710 -#define POWER_EIOS_POS 7 -#define POWER_EIOS_LEN 1 - -#endif /* __FUXI_GMAC_REG_H__ */ diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac.h b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac.h deleted file mode 100644 index 855a82bd11be6..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac.h +++ /dev/null @@ -1,924 +0,0 @@ -/*++ - -Copyright (c) 2021 Motorcomm, Inc. -Motorcomm Confidential and Proprietary. - -This is Motorcomm NIC driver relevant files. Please don't copy, modify, -distribute without commercial permission. - ---*/ - -#ifndef __FUXI_GMAC_H__ -#define __FUXI_GMAC_H__ - -#include "fuxi-os.h" - -// For fpga before 20210507 -#define FXGMAC_FPGA_VER_B4_0507 0 -#define FXGMAC_FPGA_VER_20210507 1 - -#define FXGMAC_DRV_NAME "yt6801" - -#define FXGMAC_DRV_DESC "Motorcomm FUXI GMAC Driver" - -#define FUXI_MAC_REGS_OFFSET 0x2000 - -#define FUXI_EPHY_INTERRUPT_D0_OFF 0 //1: in normal D0 state, turn off ephy link change interrupt. -#define FUXI_ALLOC_NEW_RECBUFFER 0 //1:when rec buffer is not enough,to create rbd and rec buffer ,but the rdb need to be continus with the intialized rdb,so close the feature - -#define RESUME_MAX_TIME 3000000 -#define PHY_LINK_TIMEOUT 3000 -#define ESD_RESET_MAXIMUM 0 - -#define REGWR_RETRY_MAXIMUM 2600 -#define PCIE_LINKDOWN_VALUE 0xFFFFFFFF - -#define FXGMAC_MSIX_Q_VECTORS 4 - -#define FXGMAC_IS_CHANNEL_WITH_TX_IRQ(chId) (0 == (chId) ? 1 : 0) - -/* flags for ipv6 NS offload address, local link or Global unicast */ -#define FXGMAC_NS_IFA_LOCAL_LINK 1 -#define FXGMAC_NS_IFA_GLOBAL_UNICAST 2 - -#define FXGMAX_ASPM_WAR_EN -/* Descriptor related parameters */ -#if FXGMAC_TX_HANG_TIMER_EN -#define FXGMAC_TX_DESC_CNT 1024 -#else -#define FXGMAC_TX_DESC_CNT 256 //256 to make sure the tx ring is in the 4k range when FXGMAC_TX_HANG_TIMER_EN is 0 -#endif -#define FXGMAC_TX_DESC_MIN_FREE (FXGMAC_TX_DESC_CNT >> 3) -#define FXGMAC_TX_DESC_MAX_PROC (FXGMAC_TX_DESC_CNT >> 1) -#define FXGMAC_RX_DESC_CNT 1024 -#define FXGMAC_RX_DESC_MAX_DIRTY (FXGMAC_RX_DESC_CNT >> 3) - -/* Descriptors required for maximum contiguous TSO/GSO packet */ -#define FXGMAC_TX_MAX_SPLIT ((GSO_MAX_SIZE / FXGMAC_TX_MAX_BUF_SIZE) + 1) - -/* Maximum possible descriptors needed for a SKB */ -#define FXGMAC_TX_MAX_DESC_NR (MAX_SKB_FRAGS + FXGMAC_TX_MAX_SPLIT + 2) - -#define FXGMAC_TX_MAX_BUF_SIZE (0x3fff & ~(64 - 1)) -#define FXGMAC_RX_MIN_BUF_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN) -#define FXGMAC_RX_BUF_ALIGN 64 - -/* Maximum Size for Splitting the Header Data - * Keep in sync with SKB_ALLOC_SIZE - * 3'b000: 64 bytes, 3'b001: 128 bytes - * 3'b010: 256 bytes, 3'b011: 512 bytes - * 3'b100: 1023 bytes , 3'b101'3'b111: Reserved - */ -#define FXGMAC_SPH_HDSMS_SIZE 3 -#define FXGMAC_SKB_ALLOC_SIZE 512 - -//2022-04-22 xiaojiang comment -//In Linux Driver, it set MAX_FIFO size 131072, here it uses the same value as windows driver -#define FXGMAC_MAX_FIFO 81920 - -#define FXGMAC_MAX_DMA_CHANNELS FXGMAC_MSIX_Q_VECTORS -#define FXGMAC_DMA_STOP_TIMEOUT 5 -#define FXGMAC_DMA_INTERRUPT_MASK 0x31c7 -#define FXGMAC_MAX_DMA_CHANNELS_PLUS_1TX (FXGMAC_MAX_DMA_CHANNELS + 1) - -/* Default coalescing parameters */ -//2022-04-22 xiaojiang comment -//In Windows Driver, the DMA_TX_USECS is not used, here it uses the linux driver value -#define FXGMAC_INIT_DMA_TX_USECS INT_MOD_IN_US -#define FXGMAC_INIT_DMA_TX_FRAMES 25 -#define FXGMAC_INIT_DMA_RX_USECS INT_MOD_IN_US -#define FXGMAC_INIT_DMA_RX_FRAMES 25 -#define FXGMAC_MAX_DMA_RIWT 0xff -#define FXGMAC_MIN_DMA_RIWT 0x01 - -/* Flow control queue count */ -#define FXGMAC_MAX_FLOW_CONTROL_QUEUES 8 - -/* System clock is 125 MHz */ -#define FXGMAC_SYSCLOCK 125000000 - -/* Maximum MAC address hash table size (256 bits = 8 bytes) */ -#define FXGMAC_MAC_HASH_TABLE_SIZE 8 - -/* wol pattern settings */ -#define MAX_PATTERN_SIZE 128 // PATTERN length -#define MAX_PATTERN_COUNT 16 // pattern count -#define MAX_LPP_ARP_OFFLOAD_COUNT 1 -#define MAX_LPP_NS_OFFLOAD_COUNT 2 - -#define MAX_WPI_LENGTH_SIZE 1536 // WPI packet. -#define PM_WAKE_PKT_ALIGN 8 // try use 64 bit boundary... - -/* Receive Side Scaling */ -#define FXGMAC_RSS_HASH_KEY_SIZE 40 -#define FXGMAC_RSS_MAX_TABLE_SIZE 128 -#define FXGMAC_RSS_LOOKUP_TABLE_TYPE 0 -#define FXGMAC_RSS_HASH_KEY_TYPE 1 -#define MAX_MSI_COUNT 16 // Max Msi/Msix supported. - -#define FXGMAC_STD_PACKET_MTU 1500 -#define FXGMAC_JUMBO_PACKET_MTU 9014 - -#define NIC_MAX_TCP_OFFLOAD_SIZE 7300 -#define NIC_MIN_LSO_SEGMENT_COUNT 2 - -/* power management */ -#define FXGMAC_POWER_STATE_DOWN 0 -#define FXGMAC_POWER_STATE_UP 1 - -// Don't change the member variables or types, this inherits from Windows OS. -struct wol_bitmap_pattern -{ - u32 flags; - u32 pattern_size; - u32 mask_size; - u8 mask_info[MAX_PATTERN_SIZE / 8]; - u8 pattern_info[MAX_PATTERN_SIZE]; - u8 pattern_offset; - u16 pattern_crc; -}; - -struct led_setting -{ - u32 s0_led_setting[5]; - u32 s3_led_setting[5]; - u32 s5_led_setting[5]; - u32 disable_led_setting[5]; -}; - -typedef struct led_setting LED_SETTING; -typedef struct wol_bitmap_pattern WOL_BITMAP_PATTERN; - -typedef enum -{ - WAKE_REASON_NONE = 0, - WAKE_REASON_MAGIC, - WAKE_REASON_PATTERNMATCH, - WAKE_REASON_LINK, - WAKE_REASON_TCPSYNV4, - WAKE_REASON_TCPSYNV6, - WAKE_REASON_TBD, //for wake up method like Link-change, for that, GMAC cannot identify and need more checking. - WAKE_REASON_HW_ERR, -} WAKE_REASON; //note, maybe we should refer to NDIS_PM_WAKE_REASON_TYPE to avoid duplication definition.... - -/* Helper macro for descriptor handling - * Always use FXGMAC_GET_DESC_DATA to access the descriptor data - */ -#if 0 //No need to round -#define FXGMAC_GET_DESC_DATA(ring, idx) ({ \ - typeof(ring) _ring = (ring); \ - ((_ring)->desc_data_head + \ - ((idx) & ((_ring)->dma_desc_count - 1))); \ -}) -#endif - -#define FXGMAC_GET_DESC_DATA(ring, idx) ((ring)->desc_data_head + (idx)) -#define FXGMAC_GET_ENTRY(x, size) ((x + 1) & (size - 1)) - -struct fxgmac_pdata; - -enum fxgmac_int { - FXGMAC_INT_DMA_CH_SR_TI, - FXGMAC_INT_DMA_CH_SR_TPS, - FXGMAC_INT_DMA_CH_SR_TBU, - FXGMAC_INT_DMA_CH_SR_RI, - FXGMAC_INT_DMA_CH_SR_RBU, - FXGMAC_INT_DMA_CH_SR_RPS, - FXGMAC_INT_DMA_CH_SR_TI_RI, - FXGMAC_INT_DMA_CH_SR_FBE, - FXGMAC_INT_DMA_ALL, -}; - -struct fxgmac_stats { - /* MMC TX counters */ - 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 txsinglecollision_g; - u64 txmultiplecollision_g; - u64 txdeferredframes; - u64 txlatecollisionframes; - u64 txexcessivecollisionframes; - u64 txcarriererrorframes; - u64 txoctetcount_g; - u64 txframecount_g; - u64 txexcessivedeferralerror; - u64 txpauseframes; - u64 txvlanframes_g; - u64 txoversize_g; - - /* MMC RX counters */ - u64 rxframecount_gb; - u64 rxoctetcount_gb; - u64 rxoctetcount_g; - u64 rxbroadcastframes_g; - u64 rxmulticastframes_g; - u64 rxcrcerror; - u64 rxalignerror; - 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; - u64 rxreceiveerrorframe; - u64 rxcontrolframe_g; - - /* Extra counters */ - u64 tx_tso_packets; - u64 rx_split_header_packets; - u64 tx_process_stopped; - u64 rx_process_stopped; - u64 tx_buffer_unavailable; - u64 rx_buffer_unavailable; - u64 fatal_bus_error; - u64 tx_vlan_packets; - u64 rx_vlan_packets; - u64 napi_poll_isr; - u64 napi_poll_txtimer; - u64 cnt_alive_txtimer; - - u64 ephy_poll_timer_cnt; - u64 mgmt_int_isr; -}; - -struct fxgmac_ring_buf { - struct sk_buff* skb; - DMA_ADDR_T skb_dma; - unsigned int skb_len; -}; - -/* Common Tx and Rx DMA hardware descriptor */ -struct fxgmac_dma_desc { - __le32 desc0; - __le32 desc1; - __le32 desc2; - __le32 desc3; -}; - -/* Page allocation related values */ -struct fxgmac_page_alloc { - struct page* pages; - unsigned int pages_len; - unsigned int pages_offset; - DMA_ADDR_T pages_dma; -}; - -/* Ring entry buffer data */ -struct fxgmac_buffer_data { - struct fxgmac_page_alloc pa; - struct fxgmac_page_alloc pa_unmap; - - DMA_ADDR_T dma_base; - unsigned long dma_off; - unsigned int dma_len; -}; - -/* Tx-related desc data */ -struct fxgmac_tx_desc_data { - unsigned int packets; /* BQL packet count */ - unsigned int bytes; /* BQL byte count */ -}; - -/* Rx-related desc data */ -struct fxgmac_rx_desc_data { - struct fxgmac_buffer_data hdr; /* Header locations */ - struct fxgmac_buffer_data buf; /* Payload locations */ - - unsigned short hdr_len; /* Length of received header */ - unsigned short len; /* Length of received packet */ -}; - -struct fxgmac_pkt_info { - struct sk_buff* skb; - - unsigned int attributes; - - unsigned int errors; - - /* descriptors needed for this packet */ - unsigned int desc_count; - unsigned int length; - - unsigned int tx_packets; - unsigned int tx_bytes; - - 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; - RSS_HASH_TYPE rss_hash_type; -}; - -struct fxgmac_desc_data { - /* dma_desc: Virtual address of descriptor - * dma_desc_addr: DMA address of descriptor - */ - struct fxgmac_dma_desc* dma_desc; - DMA_ADDR_T dma_desc_addr; - - /* skb: Virtual address of SKB - * skb_dma: DMA address of SKB data - * skb_dma_len: Length of SKB DMA area - */ - struct sk_buff* skb; - DMA_ADDR_T skb_dma; - unsigned int skb_dma_len; - - /* Tx/Rx -related data */ - struct fxgmac_tx_desc_data tx; - struct fxgmac_rx_desc_data rx; - - 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 { - struct sk_buff* skb; - unsigned int len; - unsigned int error; - } state; -}; - -struct fxgmac_ring { - /* Per packet related information */ - struct fxgmac_pkt_info pkt_info; - - /* Virtual/DMA addresses of DMA descriptor list and the total count */ - struct fxgmac_dma_desc *dma_desc_head; - DMA_ADDR_T dma_desc_head_addr; - unsigned int dma_desc_count; - - /* Array of descriptor data corresponding the DMA descriptor - * (always use the FXGMAC_GET_DESC_DATA macro to access this data) - */ - struct fxgmac_desc_data *desc_data_head; - - /* Page allocation for RX buffers */ - struct fxgmac_page_alloc rx_hdr_pa; - struct fxgmac_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; - - struct { - unsigned int xmit_more; - unsigned int queue_stopped; - unsigned short cur_mss; - unsigned short cur_vlan_ctag; - } tx; -} ____cacheline_aligned; - -struct fxgmac_channel { - char name[16]; - - /* Address of private data area for device */ - struct fxgmac_pdata* pdata; - - /* Queue index and base address of queue's DMA registers */ - unsigned int queue_index; - - IOMEM dma_regs; - - /* Per channel interrupt irq number */ - u32 dma_irq; - FXGMAC_CHANNEL_OF_PLATFORM expansion; - - unsigned int saved_ier; - - unsigned int tx_timer_active; - - struct fxgmac_ring *tx_ring; - struct fxgmac_ring *rx_ring; -} ____cacheline_aligned; - -struct fxphy_ag_adv { - u8 auto_neg_en : 1; - u8 full_1000m : 1; - u8 half_1000m : 1; - u8 full_100m : 1; - u8 half_100m : 1; - u8 full_10m : 1; - u8 half_10m : 1; -}; - -struct fxgmac_desc_ops { - int (*alloc_channles_and_rings)(struct fxgmac_pdata* pdata); - void (*free_channels_and_rings)(struct fxgmac_pdata* pdata); - int (*map_tx_skb)(struct fxgmac_channel* channel, - struct sk_buff* skb); - int (*map_rx_buffer)(struct fxgmac_pdata* pdata, - struct fxgmac_ring* ring, - struct fxgmac_desc_data* desc_data); - void (*unmap_desc_data)(struct fxgmac_pdata* pdata, - struct fxgmac_desc_data* desc_data); - void (*tx_desc_init)(struct fxgmac_pdata* pdata); - void (*rx_desc_init)(struct fxgmac_pdata* pdata); -}; - -struct fxgmac_hw_ops { - int (*init)(struct fxgmac_pdata* pdata); - int (*exit)(struct fxgmac_pdata* pdata); - void (*save_nonstick_reg)(struct fxgmac_pdata* pdata); - void (*restore_nonstick_reg)(struct fxgmac_pdata* pdata); -#if defined(UEFI) || defined(PXE) - int (*set_gmac_register)(struct fxgmac_pdata* pdata, u32 address, unsigned int data); - u32 (*get_gmac_register)(struct fxgmac_pdata* pdata, u32 address); -#else - int (*set_gmac_register)(struct fxgmac_pdata* pdata, u8* address, unsigned int data); - u32 (*get_gmac_register)(struct fxgmac_pdata* pdata, u8* address); - void (*esd_restore_pcie_cfg)(struct fxgmac_pdata* pdata); -#endif - - int (*tx_complete)(struct fxgmac_dma_desc* dma_desc); - - void (*enable_tx)(struct fxgmac_pdata* pdata); - void (*disable_tx)(struct fxgmac_pdata* pdata); - void (*enable_rx)(struct fxgmac_pdata* pdata); - void (*disable_rx)(struct fxgmac_pdata* pdata); - void (*enable_channel_rx)(struct fxgmac_pdata* pdata, unsigned int queue); - - int (*enable_int)(struct fxgmac_channel* channel, - enum fxgmac_int int_id); - int (*disable_int)(struct fxgmac_channel* channel, - enum fxgmac_int int_id); - void (*set_interrupt_moderation)(struct fxgmac_pdata* pdata); - void (*enable_msix_rxtxinterrupt)(struct fxgmac_pdata* pdata); - void (*disable_msix_interrupt)(struct fxgmac_pdata* pdata); - void (*enable_msix_rxtxphyinterrupt)(struct fxgmac_pdata* pdata); - void (*enable_msix_one_interrupt)(struct fxgmac_pdata* pdata, u32 intid); - void (*disable_msix_one_interrupt)(struct fxgmac_pdata* pdata, u32 intid); - bool (*enable_mgm_interrupt)(struct fxgmac_pdata* pdata); - bool (*disable_mgm_interrupt)(struct fxgmac_pdata* pdata); - - void (*dev_xmit)(struct fxgmac_channel* channel); - int (*dev_read)(struct fxgmac_channel* channel); - - int (*set_mac_address)(struct fxgmac_pdata* pdata, u8* addr); - int (*set_mac_hash)(struct fxgmac_pdata* pdata); - int (*config_rx_mode)(struct fxgmac_pdata* pdata); - int (*enable_rx_csum)(struct fxgmac_pdata* pdata); - int (*disable_rx_csum)(struct fxgmac_pdata* pdata); - void (*config_tso)(struct fxgmac_pdata *pdata); - - /* For MII speed configuration */ - int (*config_mac_speed)(struct fxgmac_pdata* pdata); - int (*set_xlgmii_2500_speed)(struct fxgmac_pdata *pdata); - int (*set_xlgmii_1000_speed)(struct fxgmac_pdata *pdata); - int (*set_xlgmii_100_speed)(struct fxgmac_pdata *pdata); - int (*get_xlgmii_phy_status)(struct fxgmac_pdata *pdata, u32 *speed, bool *link_up, bool link_up_wait_to_complete); - - /* For descriptor related operation */ - void (*tx_desc_init)(struct fxgmac_channel* channel); - void (*rx_desc_init)(struct fxgmac_channel* channel); - void (*tx_desc_reset)(struct fxgmac_desc_data* desc_data); - void (*rx_desc_reset)(struct fxgmac_pdata* pdata, - struct fxgmac_desc_data* desc_data, - unsigned int index); - int (*is_last_desc)(struct fxgmac_dma_desc* dma_desc); - int (*is_context_desc)(struct fxgmac_dma_desc* dma_desc); - void (*tx_start_xmit)(struct fxgmac_channel* channel, - struct fxgmac_ring* ring); - void (*set_pattern_data)(struct fxgmac_pdata* pdata); - void (*config_wol)(struct fxgmac_pdata *pdata, int en); - - /* For Flow Control */ - int (*config_tx_flow_control)(struct fxgmac_pdata* pdata); - int (*config_rx_flow_control)(struct fxgmac_pdata* pdata); - - /* For Jumbo Frames */ - int (*config_mtu)(struct fxgmac_pdata* pdata); - int (*enable_jumbo)(struct fxgmac_pdata* pdata); - - /* For Vlan related config */ - int (*enable_tx_vlan)(struct fxgmac_pdata* pdata); - int (*disable_tx_vlan)(struct fxgmac_pdata* pdata); - int (*enable_rx_vlan_stripping)(struct fxgmac_pdata* pdata); - int (*disable_rx_vlan_stripping)(struct fxgmac_pdata* pdata); - int (*enable_rx_vlan_filtering)(struct fxgmac_pdata* pdata); - int (*disable_rx_vlan_filtering)(struct fxgmac_pdata* pdata); - int (*update_vlan_hash_table)(struct fxgmac_pdata* pdata); - - /* For RX coalescing */ - int (*config_rx_coalesce)(struct fxgmac_pdata* pdata); - int (*config_tx_coalesce)(struct fxgmac_pdata* pdata); - unsigned int (*usec_to_riwt)(struct fxgmac_pdata* pdata, - unsigned int usec); - unsigned int (*riwt_to_usec)(struct fxgmac_pdata* pdata, - unsigned int riwt); - - /* For RX and TX threshold config */ - int (*config_rx_threshold)(struct fxgmac_pdata* pdata, - unsigned int val); - int (*config_tx_threshold)(struct fxgmac_pdata* pdata, - unsigned int val); - - /* For RX and TX Store and Forward Mode config */ - int (*config_rsf_mode)(struct fxgmac_pdata* pdata, - unsigned int val); - int (*config_tsf_mode)(struct fxgmac_pdata* pdata, - unsigned int val); - - /* For TX DMA Operate on Second Frame config */ - int (*config_osp_mode)(struct fxgmac_pdata* pdata); - - /* For RX and TX PBL config */ - int (*config_rx_pbl_val)(struct fxgmac_pdata* pdata); - int (*get_rx_pbl_val)(struct fxgmac_pdata* pdata); - int (*config_tx_pbl_val)(struct fxgmac_pdata* pdata); - int (*get_tx_pbl_val)(struct fxgmac_pdata* pdata); - int (*config_pblx8)(struct fxgmac_pdata* pdata); - - /* For MMC statistics */ - void (*rx_mmc_int)(struct fxgmac_pdata* pdata); - void (*tx_mmc_int)(struct fxgmac_pdata* pdata); - void (*read_mmc_stats)(struct fxgmac_pdata* pdata); - bool (*update_stats_counters)(struct fxgmac_pdata* pdata, bool ephy_check_en); - - /* For Receive Side Scaling */ - int (*enable_rss)(struct fxgmac_pdata* pdata); - int (*disable_rss)(struct fxgmac_pdata* pdata); - u32(*get_rss_options)(struct fxgmac_pdata* pdata); - int (*set_rss_options)(struct fxgmac_pdata* pdata); - int (*set_rss_hash_key)(struct fxgmac_pdata* pdata, const u8* key); - int (*set_rss_lookup_table)(struct fxgmac_pdata* pdata, const u32* table); - - /*For Offload*/ -#if defined(LINUX) || defined(_WIN64) || defined(_WIN32) - void (*set_arp_offload)(struct fxgmac_pdata* pdata, unsigned char* ip_addr); - int (*enable_arp_offload)(struct fxgmac_pdata* pdata); - int (*disable_arp_offload)(struct fxgmac_pdata* pdata); - - /*NS offload*/ - int (*set_ns_offload)( - struct fxgmac_pdata* pdata, - unsigned int index, - unsigned char* remote_addr, - unsigned char* solicited_addr, - unsigned char* target_addr1, - unsigned char* target_addr2, - unsigned char* mac_addr); - int (*enable_ns_offload)(struct fxgmac_pdata* pdata); - int (*disable_ns_offload)(struct fxgmac_pdata* pdata); - - int (*enable_wake_magic_pattern)(struct fxgmac_pdata* pdata); - int (*disable_wake_magic_pattern)(struct fxgmac_pdata* pdata); - - int (*enable_wake_link_change)(struct fxgmac_pdata* pdata); - int (*disable_wake_link_change)(struct fxgmac_pdata* pdata); - - int (*check_wake_pattern_fifo_pointer)(struct fxgmac_pdata* pdata); - int (*set_wake_pattern)(struct fxgmac_pdata* pdata, struct wol_bitmap_pattern* wol_pattern, u32 pattern_cnt); - int (*enable_wake_pattern)(struct fxgmac_pdata* pdata);//int XlgmacEnableArpload(struct fxgmac_pdata* pdata,unsigned char *ip_addr) - int (*disable_wake_pattern)(struct fxgmac_pdata* pdata); - int (*set_wake_pattern_mask)(struct fxgmac_pdata* pdata, u32 filter_index, u8 register_index, u32 Data); -#if defined(FUXI_PM_WPI_READ_FEATURE_EN) && FUXI_PM_WPI_READ_FEATURE_EN - void (*get_wake_packet_indication)(struct fxgmac_pdata* pdata, int* wake_reason, u32* wake_pattern_number, u8* wpi_buf, u32 buf_size, u32* packet_size); - void (*enable_wake_packet_indication)(struct fxgmac_pdata* pdata, int en); -#endif -#endif - - void (*reset_phy)(struct fxgmac_pdata* pdata); - /*for release phy,phy write and read, and provide clock to GMAC. */ - void (*release_phy)(struct fxgmac_pdata* pdata); -#if !defined(UEFI) - void (*enable_phy_check)(struct fxgmac_pdata* pdata); - void (*disable_phy_check)(struct fxgmac_pdata* pdata); - void (*setup_cable_loopback)(struct fxgmac_pdata* pdata); - void (*clean_cable_loopback)(struct fxgmac_pdata* pdata); - void (*disable_phy_sleep)(struct fxgmac_pdata* pdata); - void (*enable_phy_sleep)(struct fxgmac_pdata* pdata); - void (*phy_green_ethernet)(struct fxgmac_pdata* pdata); - void (*phy_eee_feature)(struct fxgmac_pdata* pdata); -#endif - int (*get_ephy_state)(struct fxgmac_pdata* pdata); - int (*write_ephy_reg)(struct fxgmac_pdata* pdata, u32 val, u32 data); - int (*read_ephy_reg)(struct fxgmac_pdata* pdata, u32 val, u32 *data); - int (*set_ephy_autoneg_advertise)(struct fxgmac_pdata* pdata, struct fxphy_ag_adv phy_ag_adv); - int (*phy_config)(struct fxgmac_pdata* pdata); - void (*close_phy_led)(struct fxgmac_pdata* pdata); - void (*led_under_active)(struct fxgmac_pdata* pdata); - void (*led_under_sleep)(struct fxgmac_pdata* pdata); - void (*led_under_shutdown)(struct fxgmac_pdata* pdata); - void (*led_under_disable)(struct fxgmac_pdata* pdata); - - /* For power management */ - void (*pre_power_down)(struct fxgmac_pdata* pdata, bool phyloopback); -#if defined(LINUX) - int (*diag_sanity_check)(struct fxgmac_pdata *pdata); - int (*write_rss_lookup_table)(struct fxgmac_pdata *pdata); - int (*get_rss_hash_key)(struct fxgmac_pdata *pdata, u8 *key_buf); - void (*config_power_down)(struct fxgmac_pdata *pdata, unsigned int wol); -#else - void (*config_power_down)(struct fxgmac_pdata* pdata, unsigned int offloadcount, bool magic_en, bool remote_pattern_en); -#endif - void (*config_power_up)(struct fxgmac_pdata* pdata); - unsigned char (*set_suspend_int)(void* pdata); - void(*set_resume_int)(struct fxgmac_pdata* pdata); - int (*set_suspend_txrx)(struct fxgmac_pdata* pdata); - void (*set_pwr_clock_gate)(struct fxgmac_pdata* pdata); - void (*set_pwr_clock_ungate)(struct fxgmac_pdata* pdata); - - /* for multicast address list */ - int (*set_all_multicast_mode)(struct fxgmac_pdata* pdata, unsigned int enable); - void (*config_multicast_mac_hash_table)(struct fxgmac_pdata* pdata, unsigned char* pmc_mac, int b_add); - - /* for packet filter-promiscuous and broadcast */ - int (*set_promiscuous_mode)(struct fxgmac_pdata* pdata, unsigned int enable); - int (*enable_rx_broadcast)(struct fxgmac_pdata* pdata, unsigned int enable); - - /* efuse relevant operation. */ - bool (*read_patch_from_efuse)(struct fxgmac_pdata* pdata, u32 offset, u32* value); /* read patch per index. */ - bool (*read_patch_from_efuse_per_index)(struct fxgmac_pdata* pdata, u8 index, u32* offset, u32* value); /* read patch per index. */ - bool (*write_patch_to_efuse)(struct fxgmac_pdata* pdata, u32 offset, u32 value); - bool (*write_patch_to_efuse_per_index)(struct fxgmac_pdata* pdata, u8 index, u32 offset, u32 value); - bool (*read_mac_subsys_from_efuse)(struct fxgmac_pdata* pdata, u8* mac_addr, u32* subsys, u32* revid); - bool (*write_mac_subsys_to_efuse)(struct fxgmac_pdata* pdata, u8* mac_addr, u32* subsys, u32* revid); - bool (*read_mac_addr_from_efuse)(struct fxgmac_pdata* pdata, u8* mac_addr); - bool (*write_mac_addr_to_efuse)(struct fxgmac_pdata* pdata, u8* mac_addr); - bool (*efuse_load)(struct fxgmac_pdata* pdata); - bool (*read_efuse_data)(struct fxgmac_pdata* pdata, u32 offset, u32* value); - bool (*write_oob)(struct fxgmac_pdata* pdata); - bool (*write_led)(struct fxgmac_pdata* pdata, u32 value); - bool (*read_led_config)(struct fxgmac_pdata* pdata); - bool (*write_led_config)(struct fxgmac_pdata* pdata); - - int (*pcie_init)(struct fxgmac_pdata* pdata, bool ltr_en, bool aspm_l1ss_en, bool aspm_l1_en, bool aspm_l0s_en); - void (*trigger_pcie)(struct fxgmac_pdata* pdata, u32 code); // To trigger pcie sniffer for analysis. -#ifdef DPDK - int (*phy_init)(struct fxgmac_pdata *); - int (*phy_start)(struct fxgmac_pdata *); - void (*phy_stop)(struct fxgmac_pdata *); - void (*phy_status)(struct fxgmac_pdata *); - void (*an_isr)(struct fxgmac_pdata *); /* phy_if->an_isr For single interrupt support */ -#endif -}; - -/* This structure contains flags that indicate what hardware features - * or configurations are present in the device. - */ -struct fxgmac_hw_features { - /* HW Version */ - unsigned int version; - - /* HW Feature Register0 */ - unsigned int phyifsel; /* PHY interface 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 Advanced 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 dma_width; /* DMA width */ - 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 avsel; /* AV Feature Enable */ - unsigned int ravsel; /* Rx Side Only AV Feature Enable */ - 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 */ - - /* HW Feature Register3 */ - u32 hwfr3; -}; - -struct fxgmac_resources { - IOMEM addr; - int irq; -}; - -struct fxgmac_pdata { - struct net_device *netdev; - struct device *dev; - PCI_DEV *pdev; - void *pAdapter; - - struct fxgmac_hw_ops hw_ops; - struct fxgmac_desc_ops desc_ops; - - /* Device statistics */ - struct fxgmac_stats stats; - - u32 msg_enable; - u32 reg_nonstick[0x300 >> 2]; - - /* MAC registers base */ - IOMEM mac_regs; - IOMEM base_mem; - - /* Hardware features of the device */ - struct fxgmac_hw_features hw_feat; - - /* Rings for Tx/Rx on a DMA channel */ - struct fxgmac_channel *channel_head; - unsigned int channel_count; - unsigned int tx_ring_count; - unsigned int rx_ring_count; - unsigned int tx_desc_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; -#if FXGMAC_TX_HANG_TIMER_EN - /* for tx hang checking. 20211227 */ - unsigned int tx_hang_restart_queuing; -#endif - - /* 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_usecs; - unsigned int rx_frames; - - /* Current Rx buffer size */ - unsigned int rx_buf_size; - - /* Flow control settings */ - unsigned int tx_pause; - unsigned int rx_pause; - - /* Jumbo frames */ - unsigned int mtu; - unsigned int jumbo; - - /* CRC checking */ - unsigned int crc_check; - - /* MSIX */ - unsigned int msix; - - /* RSS */ - unsigned int rss; - - /* VlanID */ - unsigned int vlan; - unsigned int vlan_exist; - unsigned int vlan_filter; - unsigned int vlan_strip; - - /* Interrupt Moderation */ - unsigned int intr_mod; - unsigned int intr_mod_timer; - - /* Device interrupt number */ - int dev_irq; - unsigned int per_channel_irq; - u32 channel_irq[FXGMAC_MAX_DMA_CHANNELS_PLUS_1TX]; // change type from int to u32 to match MSIx, p_msix_entry.vector; - - /* Netdev related settings */ - unsigned char mac_addr[ETH_ALEN]; - - /* Filtering support */ -#if FXGMAC_FILTER_MULTIPLE_VLAN_ENABLED - unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; -#endif - - /* Device clocks */ - unsigned long sysclk_rate; - - /* Receive Side Scaling settings */ - u8 rss_key[FXGMAC_RSS_HASH_KEY_SIZE]; - u32 rss_table[FXGMAC_RSS_MAX_TABLE_SIZE]; - u32 rss_options; - - int phy_speed; - int phy_duplex; - int phy_autoeng; - - char drv_name[32]; - char drv_ver[32]; - - struct wol_bitmap_pattern pattern[MAX_PATTERN_COUNT]; - - struct led_setting led; - struct led_setting ledconfig; - - FXGMAC_PDATA_OF_PLATFORM expansion; - - u32 pcie_link_status; -}; - -//#ifdef CONFIG_PCI_MSI -#if 1 -#define FXGMAC_FLAG_MSI_CAPABLE (u32)(1 << 0) // bit0 -#define FXGMAC_FLAG_MSI_ENABLED (u32)(1 << 1) // bit1 -#define FXGMAC_FLAG_MSIX_CAPABLE (u32)(1 << 2) // bit2 -#define FXGMAC_FLAG_MSIX_ENABLED (u32)(1 << 3) // bit3 -#define FXGMAC_FLAG_LEGACY_ENABLED (u32)(1 << 4) // bit4 - -#define FXGMAC_FLAG_INTERRUPT_POS 0 -#define FXGMAC_FLAG_INTERRUPT_LEN 5 - -#define FXGMAC_FLAG_MSI_POS 1 -#define FXGMAC_FLAG_MSI_LEN 1 -#define FXGMAC_FLAG_MSIX_POS 3 -#define FXGMAC_FLAG_MSIX_LEN 1 -#define FXGMAC_FLAG_LEGACY_POS 4 -#define FXGMAC_FLAG_LEGACY_LEN 1 -#define FXGMAC_FLAG_LEGACY_IRQ_FREE_POS 31 //bit31 -#define FXGMAC_FLAG_LEGACY_IRQ_FREE_LEN 1 -#define FXGMAC_FLAG_LEGACY_NAPI_FREE_POS 30 //bit30 -#define FXGMAC_FLAG_LEGACY_NAPI_FREE_LEN 1 -#endif - -void fxgmac_init_desc_ops(struct fxgmac_desc_ops *desc_ops); -void fxgmac_init_hw_ops(struct fxgmac_hw_ops *hw_ops); -const struct net_device_ops *fxgmac_get_netdev_ops(void); -const struct ethtool_ops *fxgmac_get_ethtool_ops(void); -void fxgmac_dump_tx_desc(struct fxgmac_pdata *pdata, - struct fxgmac_ring *ring, - unsigned int idx, - unsigned int count, - unsigned int flag); -void fxgmac_dump_rx_desc(struct fxgmac_pdata *pdata, - struct fxgmac_ring *ring, - unsigned int idx); -void fxgmac_dbg_pkt(struct net_device *netdev, - struct sk_buff *skb, bool tx_rx); -void fxgmac_get_all_hw_features(struct fxgmac_pdata *pdata); -void fxgmac_print_all_hw_features(struct fxgmac_pdata *pdata); -int fxgmac_drv_probe(struct device *dev, - struct fxgmac_resources *res); -int fxgmac_drv_remove(struct device *dev); - -#endif /* __FUXI_GMAC_H__ */ diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-os.h b/drivers/net/ethernet/motorcomm/yt6801/fuxi-os.h deleted file mode 100644 index 6a47741718ebf..0000000000000 --- a/drivers/net/ethernet/motorcomm/yt6801/fuxi-os.h +++ /dev/null @@ -1,560 +0,0 @@ -/*++ - -Copyright (c) 2021 Motor-comm Corporation. -Confidential and Proprietary. All rights reserved. - -This is Motor-comm Corporation NIC driver relevant files. -Please don't copy, modify,distribute without commercial permission. - ---*/ - - -#ifndef __FUXI_OS_H__ -#define __FUXI_OS_H__ - -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_PCI_MSI -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#define LINUX - -#ifndef LINUX_VERSION_CODE -#include -#else -#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,0)) -#include -#endif - -#include "fuxi-dbg.h" - -struct fxgmac_ring; -struct fxgmac_pdata; - -#define FXGMAC_DRV_VERSION "1.0.27" - -#ifdef CONFIG_PCI_MSI -//#undef CONFIG_PCI_MSI //undefined for legacy interupt mode -#endif - -#define PCIE_LP_ASPM_L0S 1 -#define PCIE_LP_ASPM_L1 2 -#define PCIE_LP_ASPM_L1SS 4 -#define PCIE_LP_ASPM_LTR 8 - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0)) -/* - * There are multiple 16-bit CRC polynomials in common use, but this is - * *the* standard CRC-32 polynomial, first popularized by Ethernet. - * x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0 - */ -#define CRC32_POLY_LE 0xedb88320 -#define CRC32_POLY_BE 0x04c11db7 - -/* - * This is the CRC32c polynomial, as outlined by Castagnoli. - * x^32+x^28+x^27+x^26+x^25+x^23+x^22+x^20+x^19+x^18+x^14+x^13+x^11+x^10+x^9+ - * x^8+x^6+x^0 - */ -#define CRC32C_POLY_LE 0x82F63B78 -#endif - -#define FXGMAC_FAIL -1 -#define FXGMAC_SUCCESS 0 -#define FXGMAC_DEV_CMD (SIOCDEVPRIVATE + 1) -#define FXGMAC_IOCTL_DFS_COMMAND _IOWR('M', 0x80, struct ext_ioctl_data) - -#define FXGMAC_MAX_DBG_TEST_PKT 150 -#define FXGMAC_MAX_DBG_BUF_LEN 64000 -#define FXGMAC_MAX_DBG_RX_DATA 1600 -#define FXGMAC_NETDEV_OPS_BUF_LEN 256 - -#define FXGMAC_TEST_MAC_HEAD_LEN 14 - -#define FUXI_PM_WPI_READ_FEATURE_EN 1 - -#define RSS_Q_COUNT 4 - -//#define FXGMAC_TX_INTERRUPT_EN 1 -#define FXGMAC_TX_HANG_TIMER_EN 0 -/* only for debug. for normal run, pls keep them both 0 */ -//0: use default tx q; other: specify txq-1: 1 txq; -#define FXGMAC_NUM_OF_TX_Q_USED 0 -//1 to enable a dummy tx,ie, no tail for gmac; -#define FXGMAC_DUMMY_TX_DEBUG 0 -//1 to trigger(write reg 0x1000) for sniffer stop -#define FXGMAC_TRIGGER_TX_HANG 0 - -/* driver feature configuration */ -#if FXGMAC_TX_HANG_TIMER_EN -//0: check hw current desc; 1: check software dirty -#define FXGMAC_TX_HANG_CHECH_DIRTY 0 -#endif - -// 1:poll tx of 4 channels; 0: since only 1 tx channel supported in this -// version, poll ch 0 always. -#define FXGMAC_FULL_TX_CHANNEL 0 - -#ifdef CONFIG_ARM64 -// when you want to run this driver on 64bit arm,you should open this,otherwise -// dma's mask cannot be set successfully. -#define FUXI_DMA_BIT_MASK 64 -#endif - -#ifdef CONFIG_PCI_MSI -//should be same as FXGMAC_MAX_DMA_CHANNELS + 1 tx_irq -#define FXGMAC_MAX_MSIX_Q_VECTORS (FXGMAC_MSIX_Q_VECTORS + 1) -#define FXGMAC_MSIX_CH0RXDIS_EN 0 //set to 1 for ch0 unbalance fix; -#define FXGMAC_MSIX_INTCTRL_EN 1 - -#define FXGMAC_PHY_INT_NUM 1 -#define FXGMAC_MSIX_INT_NUMS (FXGMAC_MAX_MSIX_Q_VECTORS + FXGMAC_PHY_INT_NUM) -#else //for case of no CONFIG_PCI_MSI -#define FXGMAC_MSIX_CH0RXDIS_EN 0 //NO modification needed! for non-MSI, set to 0 always -#define FXGMAC_MSIX_INTCTRL_EN 0 -#endif - -/*RSS features*/ -#ifdef FXGMAC_ONE_CHANNEL -#define FXGMAC_RSS_FEATURE_ENABLED 0 // 1:enable rss ; 0: rss not included. -#else -#define FXGMAC_RSS_FEATURE_ENABLED 1 // 1:enable rss ; 0: rss not included. -#endif -#define FXGMAC_RSS_HASH_KEY_LINUX 1 // 0:hard to default rss key ;1: normal hash key process from Linux. - -/*WOL features*/ -#define FXGMAC_WOL_FEATURE_ENABLED 1 // 1:enable wol ; 0: wol not included. -/*since wol upon link will cause issue, disabled it always. */ -#define FXGMAC_WOL_UPON_EPHY_LINK 1 // 1:enable ephy link change wol ; 0: ephy link change wol is not supported. - -/*Pause features*/ -#define FXGMAC_PAUSE_FEATURE_ENABLED 1 // 1:enable flow control/pause framce ; 0: flow control/pause frame not included. - -/*ARP offload engine (AOE)*/ -#define FXGMAC_AOE_FEATURE_ENABLED 1 // 1:enable arp offload engine ; 0: aoe is not included. - -/*NS offload engine*/ -#define FXGMAC_NS_OFFLOAD_ENABLED 1 // 1:enable NS offload for IPv6 ; 0: NS is not included. - -/*for fpga ver after, which needs release phy before set of MAC tx/rx */ -#define FXGMAC_TXRX_EN_AFTER_PHY_RELEASE 1 // 1:release ephy before mac tx/rx bits are set. - -/*power management features*/ -#define FXGMAC_PM_FEATURE_ENABLED 1 // 1:enable PM ; 0: PM not included. - -/*sanity check*/ -#define FXGMAC_SANITY_CHECK_ENABLED 0 // 1:enable health checking ; - -/*vlan id filter*/ -#define FXGMAC_FILTER_SINGLE_VLAN_ENABLED 1 // 1:enable health checking ; - -//Linux driver implement VLAN HASH Table feature to support mutliple VLAN feautre -#define FXGMAC_FILTER_MULTIPLE_VLAN_ENABLED 1 - -//Linux driver implement MAC HASH Table feature -#define FUXI_MAC_HASH_TABLE 1 - -//Linux driver implement write multiple mac addr -#define FXGMAC_FILTER_MULTIPLE_MAC_ADDR_ENABLED 1 - -//Linux driver disable MISC Interrupt -#define FUXI_MISC_INT_HANDLE_FEATURE_EN 1 - -#define HAVE_FXGMAC_DEBUG_FS - -#ifndef offsetof -#define offsetof(TYPE, MEMBER) ((size_t) &(((TYPE*)0)->MEMBER)) -#endif - -#define ETH_IS_ZEROADDRESS(Address) \ - ((((u8*)(Address))[0] == ((u8)0x00)) \ - && (((u8*)(Address))[1] == ((u8)0x00)) \ - && (((u8*)(Address))[2] == ((u8)0x00)) \ - && (((u8*)(Address))[3] == ((u8)0x00)) \ - && (((u8*)(Address))[4] == ((u8)0x00)) \ - && (((u8*)(Address))[5] == ((u8)0x00))) - - /* read from 8bit register via pci config space */ -#define cfg_r8(_pdata, reg, pdat) pci_read_config_byte((_pdata)->pdev, (reg), (u8 *)(pdat)) - - /* read from 16bit register via pci config space */ -#define cfg_r16(_pdata, reg, pdat) pci_read_config_word((_pdata)->pdev, (reg), (u16 *)(pdat)) - - /* read from 32bit register via pci config space */ -#define cfg_r32(_pdata, reg, pdat) pci_read_config_dword((_pdata)->pdev, (reg), (u32 *)(pdat)) - -/* write to 8bit register via pci config space */ -#define cfg_w8(_pdata, reg, val) pci_write_config_byte((_pdata)->pdev, (reg), (u8)(val)) - -/* write to 16bit register via pci config space */ -#define cfg_w16(_pdata, reg, val) pci_write_config_word((_pdata)->pdev, (reg), (u16)(val)) - -/* write to 32bit register via pci config space */ -#define cfg_w32(_pdata, reg, val) pci_write_config_dword((_pdata)->pdev, (reg), (u32)(val)) - -#define readreg(pAdapter, addr) (readl(addr)) -#define writereg(pAdapter, val, addr) (writel(val, addr)) -#define usleep_range_ex(pAdapter, a, b) (usleep_range(a, b)) -#define _CR(Record, TYPE, Field) ((TYPE *) ((char *) (Record) - (char *) &(((TYPE *) 0)->Field))) - -#define FXGMAC_GET_REG_BITS(var, pos, len) ({ \ - typeof(pos) _pos = (pos); \ - typeof(len) _len = (len); \ - ((var) & GENMASK(_pos + _len - 1, _pos)) >> (_pos); \ -}) - -#define FXGMAC_GET_REG_BITS_LE(var, pos, len) ({ \ - typeof(pos) _pos = (pos); \ - typeof(len) _len = (len); \ - typeof(var) _var = le32_to_cpu((var)); \ - ((_var) & GENMASK(_pos + _len - 1, _pos)) >> (_pos); \ -}) - -#define FXGMAC_SET_REG_BITS(var, pos, len, val) ({ \ - typeof(var) _var = (var); \ - typeof(pos) _pos = (pos); \ - typeof(len) _len = (len); \ - typeof(val) _val = (val); \ - _val = (_val << _pos) & GENMASK(_pos + _len - 1, _pos); \ - _var = (_var & ~GENMASK(_pos + _len - 1, _pos)) | _val; \ -}) - -#define FXGMAC_SET_REG_BITS_LE(var, pos, len, val) ({ \ - typeof(var) _var = (var); \ - typeof(pos) _pos = (pos); \ - typeof(len) _len = (len); \ - typeof(val) _val = (val); \ - _val = (_val << _pos) & GENMASK(_pos + _len - 1, _pos); \ - _var = (_var & ~GENMASK(_pos + _len - 1, _pos)) | _val; \ - cpu_to_le32(_var); \ -}) - -#define STR_FORMAT "%s" - -#define DbgPrintF(level, fmt, ...) -#define DBGPRINT(Level, Fmt) -#define DBGPRINT_RAW(Level, Fmt) -#define DBGPRINT_S(Status, Fmt) -#define DBGPRINT_UNICODE(Level, UString) -#define Dump(p,cb,fAddress,ulGroup) - -#undef ASSERT -#define ASSERT(x) - -#define DbgPrintOidName(_Oid) -#define DbgPrintAddress(_pAddress) - -#define fxgmac_dump_buffer(_skb, _len, _tx_rx) -#define DumpLine(_p, _cbLine, _fAddress, _ulGroup ) - -#ifndef FXGMAC_DEBUG -#define FXGMAC_DEBUG -#endif - -/* For debug prints */ -#ifdef FXGMAC_DEBUG -#define FXGMAC_PR(fmt, args...) \ - pr_alert("[%s,%d]:" fmt, __func__, __LINE__, ## args) - -#define DPRINTK printk -#else -#define FXGMAC_PR(x...) do { } while (0) -#define DPRINTK(x...) -#endif - -#define IOC_MAGIC 'M' -#define IOC_MAXNR (0x80 + 5) - -#define FUXI_DFS_IOCTL_DEVICE_INACTIVE 0x10001 -#define FUXI_DFS_IOCTL_DEVICE_RESET 0x10002 -#define FUXI_DFS_IOCTL_DIAG_BEGIN 0x10003 -#define FUXI_DFS_IOCTL_DIAG_END 0x10004 -#define FUXI_DFS_IOCTL_DIAG_TX_PKT 0x10005 -#define FUXI_DFS_IOCTL_DIAG_RX_PKT 0x10006 - -#define FXGMAC_EFUSE_UPDATE_LED_CFG 0x10007 -#define FXGMAC_EFUSE_WRITE_LED 0x10008 -#define FXGMAC_EFUSE_WRITE_PATCH_REG 0x10009 -#define FXGMAC_EFUSE_WRITE_PATCH_PER_INDEX 0x1000A -#define FXGMAC_EFUSE_WRITE_OOB 0x1000B -#define FXGMAC_EFUSE_LOAD 0x1000C -#define FXGMAC_EFUSE_READ_REGIONABC 0x1000D -#define FXGMAC_EFUSE_READ_PATCH_REG 0x1000E -#define FXGMAC_EFUSE_READ_PATCH_PER_INDEX 0x1000F -#define FXGMAC_EFUSE_LED_TEST 0x10010 - -#define FXGMAC_GET_MAC_DATA 0x10011 -#define FXGMAC_SET_MAC_DATA 0x10012 -#define FXGMAC_GET_SUBSYS_ID 0x10013 -#define FXGMAC_SET_SUBSYS_ID 0x10014 -#define FXGMAC_GET_GMAC_REG 0x10015 -#define FXGMAC_SET_GMAC_REG 0x10016 -#define FXGMAC_GET_PHY_REG 0x10017 -#define FXGMAC_SET_PHY_REG 0x10018 -#define FXGMAC_EPHYSTATISTICS 0x10019 -#define FXGMAC_GET_STATISTICS 0x1001A -#define FXGMAC_GET_PCIE_LOCATION 0x1001B - -#define FXGMAC_GET_GSO_SIZE 0x1001C -#define FXGMAC_SET_GSO_SIZE 0x1001D -#define FXGMAC_SET_RX_MODERATION 0x1001E -#define FXGMAC_SET_TX_MODERATION 0x1001F -#define FXGMAC_GET_TXRX_MODERATION 0x10020 - -#define MAX_PKT_BUF 1 -#define FXGAMC_MAX_DATA_SIZE (1024 * 4 + 16) - -#ifndef PCI_CAP_ID_MSI -#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */ -#endif - -#ifndef PCI_CAP_ID_MSIX -#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ -#endif - -#define PCI_CAP_ID_MSI_ENABLE_POS 0x10 -#define PCI_CAP_ID_MSI_ENABLE_LEN 0x1 -#define PCI_CAP_ID_MSIX_ENABLE_POS 0x1F -#define PCI_CAP_ID_MSIX_ENABLE_LEN 0x1 - -#ifndef fallthrough -#if __has_attribute(__fallthrough__) -# define fallthrough __attribute__((__fallthrough__)) -#else -# define fallthrough do {} while (0) /* fallthrough */ -#endif -#endif - - -#pragma pack(1) -// it's better to make this struct's size to 128byte. -struct pattern_packet{ - u8 ether_daddr[ETH_ALEN]; - u8 ether_saddr[ETH_ALEN]; - u16 ether_type; - - __be16 ar_hrd; /* format of hardware address */ - __be16 ar_pro; /* format of protocol */ - unsigned char ar_hln; /* length of hardware address */ - unsigned char ar_pln; /* length of protocol address */ - __be16 ar_op; /* ARP opcode (command) */ - unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */ - unsigned char ar_sip[4]; /* sender IP address */ - unsigned char ar_tha[ETH_ALEN]; /* target hardware address */ - unsigned char ar_tip[4]; /* target IP address */ - - u8 reverse[86]; -}; -#pragma pack() - -typedef enum -{ - CURRENT_STATE_SHUTDOWN = 0, - CURRENT_STATE_RESUME = 1, - CURRENT_STATE_INIT = 2, - CURRENT_STATE_SUSPEND = 3, - CURRENT_STATE_CLOSE = 4, - CURRENT_STATE_OPEN = 5, - CURRENT_STATE_RESTART = 6, - CURRENT_STATE_REMOVE = 7, -}CURRENT_STATE; - -typedef dma_addr_t DMA_ADDR_T; -typedef enum pkt_hash_types RSS_HASH_TYPE; -typedef void __iomem* IOMEM; -typedef struct pci_dev PCI_DEV; - -struct ext_command_buf { - void* buf; - u32 size_in; - u32 size_out; -}; - -struct ext_command_mac { - u32 num; - union { - u32 val32; - u16 val16; - u8 val8; - }; -}; - -struct ext_command_mii { - u16 dev; - u16 num; - u16 val; -}; - -struct ext_ioctl_data { - u32 cmd_type; - struct ext_command_buf cmd_buf; -}; - -typedef struct _fxgmac_test_buf { - u8* addr; - u32 offset; - u32 length; -} fxgmac_test_buf, *pfxgmac_test_buf; - -typedef struct _fxgmac_test_packet { - struct _fxgmac_test_packet * next; - u32 length; /* total length of the packet(buffers) */ - u32 type; /* packet type, vlan, ip checksum, TSO, etc. */ - - fxgmac_test_buf buf[MAX_PKT_BUF]; - fxgmac_test_buf sGList[MAX_PKT_BUF]; - u16 vlanID; - u16 mss; - u32 hash; - u16 cpuNum; - u16 xsum; /* rx, ip-payload checksum */ - u16 csumStart; /* custom checksum offset to the mac-header */ - u16 csumPos; /* custom checksom position (to the mac_header) */ - void* upLevelReserved[4]; - void* lowLevelReserved[4]; -} fxgmac_test_packet, *pfxgmac_test_packet; - -typedef struct fxgmac_channel_of_platform -{ - char dma_irq_name[IFNAMSIZ + 32]; - - u32 dma_irq_tx; //for MSIx to match the type of struct msix_entry.vector - char dma_irq_name_tx[IFNAMSIZ + 32]; - - /* Netdev related settings */ - struct napi_struct napi_tx; - - /* Netdev related settings */ - struct napi_struct napi_rx; - struct timer_list tx_timer; - -#if FXGMAC_TX_HANG_TIMER_EN - unsigned int tx_hang_timer_active; - struct timer_list tx_hang_timer; - unsigned int tx_hang_hw_cur; -#endif -}FXGMAC_CHANNEL_OF_PLATFORM; - -typedef struct per_regisiter_info -{ - unsigned int size; - unsigned int address; - unsigned int value; - unsigned char data[FXGAMC_MAX_DATA_SIZE]; -}PER_REG_INFO; - -// for FXGMAC_EFUSE_WRITE_PATCH_PER_INDEX,val0 is index, val1 is offset, -// val2 is value -typedef struct ext_command_data { - u32 val0; - u32 val1; - u32 val2; -}CMD_DATA; - -typedef struct fxgmac_pdata_of_platform -{ - u32 cfg_pci_cmd; - u32 cfg_cache_line_size; - u32 cfg_mem_base; - u32 cfg_mem_base_hi; - u32 cfg_io_base; - u32 cfg_int_line; - u32 cfg_device_ctrl1; - u32 cfg_pci_link_ctrl; - u32 cfg_device_ctrl2; - u32 cfg_msix_capability; - - struct work_struct restart_work; - u32 int_flags; //legacy, msi or msix - int phy_irq; -#ifdef CONFIG_PCI_MSI - struct msix_entry *msix_entries; -#endif - - /* power management and wol*/ - u32 wol; //wol options - unsigned long powerstate; //power state - unsigned int ns_offload_tab_idx; //for ns-offload table. 2 entries supported. - CURRENT_STATE current_state; - netdev_features_t netdev_features; - struct napi_struct napi; - struct napi_struct napi_phy; - u32 mgm_intctrl_val; - bool phy_link; - bool fxgmac_test_tso_flag; - u32 fxgmac_test_tso_seg_num; - u32 fxgmac_test_last_tso_len; - u32 fxgmac_test_packet_len; - volatile u32 fxgmac_test_skb_arr_in_index; - volatile u32 fxgmac_test_skb_arr_out_index; - //CMD_DATA ex_cmd_data; - //PER_REG_INFO per_reg_data; - struct sk_buff *fxgmac_test_skb_array[FXGMAC_MAX_DBG_TEST_PKT]; -#ifdef HAVE_FXGMAC_DEBUG_FS - struct dentry *dbg_adapter; - struct dentry *fxgmac_dbg_root; - char fxgmac_dbg_netdev_ops_buf[FXGMAC_NETDEV_OPS_BUF_LEN]; -#endif -}FXGMAC_PDATA_OF_PLATFORM; - - -#ifdef HAVE_FXGMAC_DEBUG_FS -void fxgmac_dbg_adapter_init(struct fxgmac_pdata *pdata); -void fxgmac_dbg_adapter_exit(struct fxgmac_pdata *pdata); -void fxgmac_dbg_init(struct fxgmac_pdata *pdata); -void fxgmac_dbg_exit(struct fxgmac_pdata *pdata); -#endif /* HAVE_FXGMAC_DEBUG_FS */ - -void fxgmac_restart_dev(struct fxgmac_pdata *pdata); -long fxgmac_dbg_netdev_ops_ioctl(struct file *file, unsigned int cmd, - unsigned long arg); - -int fxgmac_init(struct fxgmac_pdata *pdata, bool save_private_reg); -/* for phy interface */ -int fxgmac_ephy_autoneg_ability_get(struct fxgmac_pdata *pdata, - unsigned int *cap_mask); -int fxgmac_ephy_status_get(struct fxgmac_pdata *pdata, int* speed, - int *duplex, int *ret_link, int *media); -int fxgmac_ephy_soft_reset(struct fxgmac_pdata *pdata); -void fxgmac_phy_force_speed(struct fxgmac_pdata *pdata, int speed); -void fxgmac_phy_force_duplex(struct fxgmac_pdata *pdata, int duplex); -void fxgmac_phy_force_autoneg(struct fxgmac_pdata *pdata, int autoneg); - -unsigned int fxgmac_get_netdev_ip4addr(struct fxgmac_pdata *pdata); -unsigned char *fxgmac_get_netdev_ip6addr(struct fxgmac_pdata *pdata, - unsigned char *ipval, - unsigned char *ip6addr_solicited, - unsigned int ifa_flag); - -#if FXGMAC_PM_FEATURE_ENABLED -void fxgmac_net_powerdown(struct fxgmac_pdata *pdata, unsigned int wol); -void fxgmac_net_powerup(struct fxgmac_pdata *pdata); -#endif - -inline unsigned int fxgmac_tx_avail_desc(struct fxgmac_ring *ring); -inline unsigned int fxgmac_rx_dirty_desc(struct fxgmac_ring *ring); -int fxgmac_start(struct fxgmac_pdata *pdata); -void fxgmac_stop(struct fxgmac_pdata *pdata); -void fxgmac_free_rx_data(struct fxgmac_pdata *pdata); -void fxgmac_free_tx_data(struct fxgmac_pdata *pdata); - -#endif //__FUXI_OS_H__ - From aed70813d410f28fca55146c631de1c467422939 Mon Sep 17 00:00:00 2001 From: Yanteng Si Date: Wed, 17 Jul 2024 18:25:37 +0800 Subject: [PATCH 2/2] ethernet: Add motorcomm yt6801 support - The Asus XC-LS3A6M motherboard(Loongson 3A6000),CE720Z2,CE720Z... uses a yt6801 controller. - This patch introduces an out of tree module to provide support for this NIC. [^1] - Refactor module tree to make it work with Kconfig. [^2] - Drop unneeded installation script (yt_nic_install.sh). - Drop README. some day,we can write a yt6801.rst in kenenl doc. - enable YT6801 for x86 arm64 and loongarch as module - Refactor according to the kernel code style [^1]: Ref: https://www.motor-comm.com/Public/Uploads/uploadfile/files/20240104/yt6801-linux-driver-1.0.27.zip [^2]: CONFIG_NET_VENDOR_MOTORCOMM =(y)=> CONFIG_YT8601 (tristate). Co-authored-by: Mingcong Bai Co-authored-by: Xiaotian Wu Signed-off-by: Yanteng Si --- .../configs/deepin_arm64_desktop_defconfig | 1 + .../deepin_loongarch_desktop_defconfig | 1 + arch/loongarch/configs/loongson3_defconfig | 1 + arch/x86/configs/deepin_x86_desktop_defconfig | 1 + drivers/net/ethernet/Kconfig | 1 + drivers/net/ethernet/Makefile | 1 + drivers/net/ethernet/motorcomm/Kconfig | 27 + drivers/net/ethernet/motorcomm/Makefile | 4 + .../net/ethernet/motorcomm/yt6801/Makefile | 15 + .../net/ethernet/motorcomm/yt6801/fuxi-dbg.h | 15 + .../ethernet/motorcomm/yt6801/fuxi-efuse.c | 1344 ++++ .../ethernet/motorcomm/yt6801/fuxi-efuse.h | 25 + .../motorcomm/yt6801/fuxi-gmac-common.c | 939 +++ .../motorcomm/yt6801/fuxi-gmac-debugfs.c | 787 +++ .../motorcomm/yt6801/fuxi-gmac-desc.c | 601 ++ .../motorcomm/yt6801/fuxi-gmac-ethtool.c | 1114 +++ .../ethernet/motorcomm/yt6801/fuxi-gmac-hw.c | 6256 +++++++++++++++++ .../ethernet/motorcomm/yt6801/fuxi-gmac-net.c | 2329 ++++++ .../ethernet/motorcomm/yt6801/fuxi-gmac-pci.c | 250 + .../ethernet/motorcomm/yt6801/fuxi-gmac-phy.c | 256 + .../ethernet/motorcomm/yt6801/fuxi-gmac-reg.h | 1894 +++++ .../net/ethernet/motorcomm/yt6801/fuxi-gmac.h | 934 +++ .../net/ethernet/motorcomm/yt6801/fuxi-os.h | 515 ++ 23 files changed, 17311 insertions(+) create mode 100644 drivers/net/ethernet/motorcomm/Kconfig create mode 100644 drivers/net/ethernet/motorcomm/Makefile create mode 100644 drivers/net/ethernet/motorcomm/yt6801/Makefile create mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-dbg.h create mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.c create mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.h create mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-common.c create mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-debugfs.c create mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-desc.c create mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-ethtool.c create mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-hw.c create mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-net.c create mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-pci.c create mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-phy.c create mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-reg.h create mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac.h create mode 100644 drivers/net/ethernet/motorcomm/yt6801/fuxi-os.h diff --git a/arch/arm64/configs/deepin_arm64_desktop_defconfig b/arch/arm64/configs/deepin_arm64_desktop_defconfig index d2b271b97b23b..45c7d1b27a274 100644 --- a/arch/arm64/configs/deepin_arm64_desktop_defconfig +++ b/arch/arm64/configs/deepin_arm64_desktop_defconfig @@ -1446,6 +1446,7 @@ CONFIG_ENC28J60=m CONFIG_ENC28J60_WRITEVERIFY=y CONFIG_ENCX24J600=m CONFIG_LAN743X=m +CONFIG_YT6801=m CONFIG_MSCC_OCELOT_SWITCH=m CONFIG_MYRI10GE=m CONFIG_FEALNX=m diff --git a/arch/loongarch/configs/deepin_loongarch_desktop_defconfig b/arch/loongarch/configs/deepin_loongarch_desktop_defconfig index 0bd110e30568e..b709e4d71b52b 100644 --- a/arch/loongarch/configs/deepin_loongarch_desktop_defconfig +++ b/arch/loongarch/configs/deepin_loongarch_desktop_defconfig @@ -1415,6 +1415,7 @@ CONFIG_8139TOO=y CONFIG_8139TOO_TUNE_TWISTER=y CONFIG_8139TOO_8129=y CONFIG_R8169=m +CONFIG_YT6801=m CONFIG_ROCKER=m CONFIG_SXGBE_ETH=m CONFIG_SC92031=m diff --git a/arch/loongarch/configs/loongson3_defconfig b/arch/loongarch/configs/loongson3_defconfig index 5ad2b2a254d18..98475952cb905 100644 --- a/arch/loongarch/configs/loongson3_defconfig +++ b/arch/loongarch/configs/loongson3_defconfig @@ -871,6 +871,7 @@ CONFIG_8139TOO=m # CONFIG_8139TOO_PIO is not set CONFIG_8139TOO_8129=y CONFIG_R8169=m +CONFIG_YT6801=m # CONFIG_NET_VENDOR_RENESAS is not set # CONFIG_NET_VENDOR_ROCKER is not set # CONFIG_NET_VENDOR_SAMSUNG is not set diff --git a/arch/x86/configs/deepin_x86_desktop_defconfig b/arch/x86/configs/deepin_x86_desktop_defconfig index 3027cf0952f36..4c64d78ceb1cb 100644 --- a/arch/x86/configs/deepin_x86_desktop_defconfig +++ b/arch/x86/configs/deepin_x86_desktop_defconfig @@ -1340,6 +1340,7 @@ CONFIG_KSZ884X_PCI=m CONFIG_ENC28J60=m CONFIG_ENCX24J600=m CONFIG_LAN743X=m +CONFIG_YT6801=m CONFIG_MYRI10GE=m CONFIG_FEALNX=m CONFIG_NI_XGE_MANAGEMENT_ENET=m diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index 1af5a19f453e6..f921b1a3f62e2 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -127,6 +127,7 @@ source "drivers/net/ethernet/mediatek/Kconfig" source "drivers/net/ethernet/mellanox/Kconfig" source "drivers/net/ethernet/micrel/Kconfig" source "drivers/net/ethernet/microchip/Kconfig" +source "drivers/net/ethernet/motorcomm/Kconfig" source "drivers/net/ethernet/mscc/Kconfig" source "drivers/net/ethernet/microsoft/Kconfig" source "drivers/net/ethernet/moxa/Kconfig" diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index 43bf769a97ad5..b91633e4e4016 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_NET_VENDOR_MEDIATEK) += mediatek/ obj-$(CONFIG_NET_VENDOR_MELLANOX) += mellanox/ obj-$(CONFIG_NET_VENDOR_MICREL) += micrel/ obj-$(CONFIG_NET_VENDOR_MICROCHIP) += microchip/ +obj-$(CONFIG_NET_VENDOR_MOTORCOMM) += motorcomm/ obj-$(CONFIG_NET_VENDOR_MICROSEMI) += mscc/ obj-$(CONFIG_NET_VENDOR_MOXART) += moxa/ obj-$(CONFIG_NET_VENDOR_MYRI) += myricom/ diff --git a/drivers/net/ethernet/motorcomm/Kconfig b/drivers/net/ethernet/motorcomm/Kconfig new file mode 100644 index 0000000000000..2d058928936f0 --- /dev/null +++ b/drivers/net/ethernet/motorcomm/Kconfig @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2023 Motorcomm, Inc. + +config NET_VENDOR_MOTORCOMM + bool "Motorcomm devices" + default y + depends on PCI + help + If you have a network (Ethernet) card belonging to this class, say Y. + + Note that the answer to this question doesn't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about Motorcomm cards. If you say Y, you will be asked + for your specific card in the following questions. + +if NET_VENDOR_MOTORCOMM + +config YT6801 + tristate "Motorcomm YT6801 Ethernet support" + depends on PCI + help + If you have a network (Ethernet) controller of this type, say Y here. + + To compile this driver as a module, choose M here. The module + will be called forcedeth. + +endif # NET_VENDOR_MOTORCOMM diff --git a/drivers/net/ethernet/motorcomm/Makefile b/drivers/net/ethernet/motorcomm/Makefile new file mode 100644 index 0000000000000..af0a439d54a16 --- /dev/null +++ b/drivers/net/ethernet/motorcomm/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2023 Motorcomm, Inc. + +obj-$(CONFIG_YT6801) += yt6801/ diff --git a/drivers/net/ethernet/motorcomm/yt6801/Makefile b/drivers/net/ethernet/motorcomm/yt6801/Makefile new file mode 100644 index 0000000000000..93b5c4510eb05 --- /dev/null +++ b/drivers/net/ethernet/motorcomm/yt6801/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2023 Motorcomm, Inc. + + +obj-$(CONFIG_YT6801) += yt6801.o + +yt6801-objs := fuxi-gmac-common.o \ + fuxi-gmac-desc.o \ + fuxi-gmac-ethtool.o \ + fuxi-gmac-hw.o \ + fuxi-gmac-net.o \ + fuxi-gmac-pci.o \ + fuxi-gmac-phy.o \ + fuxi-efuse.o \ + fuxi-gmac-debugfs.o diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-dbg.h b/drivers/net/ethernet/motorcomm/yt6801/fuxi-dbg.h new file mode 100644 index 0000000000000..24282f8e22303 --- /dev/null +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-dbg.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021 Motorcomm Corporation. */ + +#ifndef _MP_DBG_H +#define _MP_DBG_H + +/* Message verbosity: lower values indicate higher urgency */ +#define MP_OFF 0 +#define MP_ERROR 1 +#define MP_WARN 2 +#define MP_TRACE 3 +#define MP_INFO 4 +#define MP_LOUD 5 + +#endif /* _MP_DBG_H */ \ No newline at end of file diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.c new file mode 100644 index 0000000000000..ae4ca3d59ac4c --- /dev/null +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.c @@ -0,0 +1,1344 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021 Motorcomm Corporation. */ + +#include "fuxi-gmac.h" +#include "fuxi-gmac-reg.h" +#include "fuxi-efuse.h" + +/* read patch per index. */ +bool fxgmac_read_patch_from_efuse_per_index(struct fxgmac_pdata *pdata, + u8 index, u32 *offset, u32 *value) +{ + unsigned int wait, i; + u32 regval = 0; + bool succeed = false; + + if (index >= FUXI_EFUSE_MAX_ENTRY) { + FXGMAC_PR("Reading efuse out of range, index %d\n", index); + return false; + } + + if (offset) { + *offset = 0; + } + for (i = EFUSE_PATCH_ADDR_START_BYTE; i < EFUSE_PATCH_DATA_START_BYTE; + i++) { + regval = 0; + regval = FXGMAC_SET_REG_BITS( + regval, EFUSE_OP_ADDR_POS, EFUSE_OP_ADDR_LEN, + EFUSE_REGION_A_B_LENGTH + index * EFUSE_EACH_PATH_SIZE + + i); + regval = FXGMAC_SET_REG_BITS(regval, EFUSE_OP_START_POS, + EFUSE_OP_START_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, EFUSE_OP_MODE_POS, + EFUSE_OP_MODE_LEN, + EFUSE_OP_MODE_ROW_READ); + writereg(pdata->pAdapter, regval, + pdata->base_mem + EFUSE_OP_CTRL_0); + wait = 1000; + while (wait--) { + usleep_range_ex(pdata->pAdapter, 20, 50); + regval = readreg(pdata->pAdapter, + pdata->base_mem + EFUSE_OP_CTRL_1); + if (FXGMAC_GET_REG_BITS(regval, EFUSE_OP_DONE_POS, + EFUSE_OP_DONE_LEN)) { + succeed = true; + break; + } + } + if (succeed) { + if (offset) { + *offset |= + (FXGMAC_GET_REG_BITS( + regval, EFUSE_OP_RD_DATA_POS, + EFUSE_OP_RD_DATA_LEN) + << (i << 3)); + } + } else { + FXGMAC_PR("Fail to reading efuse Byte%d\n", + index * EFUSE_EACH_PATH_SIZE + i); + return succeed; + } + } + + if (value) { + *value = 0; + } + for (i = EFUSE_PATCH_DATA_START_BYTE; i < EFUSE_EACH_PATH_SIZE; i++) { + regval = 0; + regval = FXGMAC_SET_REG_BITS( + regval, EFUSE_OP_ADDR_POS, EFUSE_OP_ADDR_LEN, + EFUSE_REGION_A_B_LENGTH + index * EFUSE_EACH_PATH_SIZE + + i); + regval = FXGMAC_SET_REG_BITS(regval, EFUSE_OP_START_POS, + EFUSE_OP_START_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, EFUSE_OP_MODE_POS, + EFUSE_OP_MODE_LEN, + EFUSE_OP_MODE_ROW_READ); + writereg(pdata->pAdapter, regval, + pdata->base_mem + EFUSE_OP_CTRL_0); + wait = 1000; + while (wait--) { + usleep_range_ex(pdata->pAdapter, 20, 50); + regval = readreg(pdata->pAdapter, + pdata->base_mem + EFUSE_OP_CTRL_1); + if (FXGMAC_GET_REG_BITS(regval, EFUSE_OP_DONE_POS, + EFUSE_OP_DONE_LEN)) { + succeed = true; + break; + } + } + if (succeed) { + if (value) { + *value |= (FXGMAC_GET_REG_BITS( + regval, EFUSE_OP_RD_DATA_POS, + EFUSE_OP_RD_DATA_LEN) + << ((i - 2) << 3)); + } + } else { + FXGMAC_PR("Fail to reading efuse Byte%d\n", + index * EFUSE_EACH_PATH_SIZE + i); + return succeed; + } + } + + return succeed; +} + +bool fxgmac_read_patch_from_efuse(struct fxgmac_pdata *pdata, u32 offset, + u32 *value) /* read patch per index. */ +{ + u32 reg_offset, reg_val; + u32 cur_val = 0; + bool succeed = true; + u8 index = 0; + + if (offset >> 16) { + FXGMAC_PR( + "Reading efuse out of range, reg %d. reg must be 2bytes.\n", + index); + return false; + } + + for (index = 0; index < FUXI_EFUSE_MAX_ENTRY; index++) { + if (!fxgmac_read_patch_from_efuse_per_index( + pdata, index, ®_offset, ®_val)) { + succeed = false; + break; + } else if (reg_offset == offset) { + cur_val = reg_val; + } else if (0 == reg_offset && 0 == reg_val) { + break; /* first blank. We should write here. */ + } + } + + if (value) { + *value = cur_val; + } + + return succeed; +} + +bool fxgmac_write_patch_to_efuse_per_index(struct fxgmac_pdata *pdata, u8 index, + u32 offset, u32 value) +{ + unsigned int wait, i; + u32 reg_val; + bool succeed = false; + u32 cur_reg, cur_val; + u8 max_index = FUXI_EFUSE_MAX_ENTRY; + + if (offset >> 16) { + FXGMAC_PR( + "Reading efuse out of range, reg %d. reg must be 2bytes.\n", + index); + return false; + } + + fxgmac_efuse_read_data(pdata, EFUSE_LED_ADDR, ®_val); + if (EFUSE_LED_COMMON_SOLUTION == reg_val) { + max_index = FUXI_EFUSE_MAX_ENTRY_UNDER_LED_COMMON; + } + + if (index >= max_index) { + FXGMAC_PR("Writing efuse out of range, index %d max index %d\n", + index, max_index); + return false; + } + + if (fxgmac_read_patch_from_efuse_per_index(pdata, index, &cur_reg, + &cur_val)) { + if (cur_reg != 0 || cur_val != 0) { + FXGMAC_PR( + " The index %d has writed value, cannot rewrite it.\n", + index); + return false; + } + } else { + FXGMAC_PR("Cannot read index %d.\n", index); + return false; + } + + for (i = EFUSE_PATCH_ADDR_START_BYTE; i < EFUSE_PATCH_DATA_START_BYTE; + i++) { + reg_val = 0; + reg_val = FXGMAC_SET_REG_BITS( + reg_val, EFUSE_OP_ADDR_POS, EFUSE_OP_ADDR_LEN, + EFUSE_REGION_A_B_LENGTH + index * EFUSE_EACH_PATH_SIZE + + i); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_WR_DATA_POS, + EFUSE_OP_WR_DATA_LEN, + (offset >> (i << 3)) & 0xFF); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, + EFUSE_OP_START_LEN, 1); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, + EFUSE_OP_MODE_LEN, + EFUSE_OP_MODE_ROW_WRITE); + writereg(pdata->pAdapter, reg_val, + pdata->base_mem + EFUSE_OP_CTRL_0); + + succeed = false; + wait = 1000; + while (wait--) { + usleep_range_ex(pdata->pAdapter, 20, 50); + reg_val = readreg(pdata->pAdapter, + pdata->base_mem + EFUSE_OP_CTRL_1); + if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, + EFUSE_OP_DONE_LEN)) { + succeed = true; + break; + } + } + if (!succeed) { + FXGMAC_PR("Fail to writing efuse Byte%d\n", + index * EFUSE_EACH_PATH_SIZE + i); + return succeed; + } + } + + for (i = 2; i < 6; i++) { + reg_val = 0; + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_ADDR_POS, + EFUSE_OP_ADDR_LEN, + 18 + index * 6 + i); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_WR_DATA_POS, + EFUSE_OP_WR_DATA_LEN, + (value >> ((i - 2) << 3)) & 0xFF); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, + EFUSE_OP_START_LEN, 1); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, + EFUSE_OP_MODE_LEN, + EFUSE_OP_MODE_ROW_WRITE); + writereg(pdata->pAdapter, reg_val, + pdata->base_mem + EFUSE_OP_CTRL_0); + + succeed = false; + wait = 1000; + while (wait--) { + usleep_range_ex(pdata->pAdapter, 20, 50); + reg_val = readreg(pdata->pAdapter, + pdata->base_mem + EFUSE_OP_CTRL_1); + if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, + EFUSE_OP_DONE_LEN)) { + succeed = true; + break; + } + } + if (!succeed) { + FXGMAC_PR("Fail to writing efuse Byte%d\n", + index * EFUSE_EACH_PATH_SIZE + i); + return succeed; + } + } + + return succeed; +} + +bool fxgmac_write_patch_to_efuse(struct fxgmac_pdata *pdata, u32 offset, + u32 value) +{ + unsigned int wait, i; + u32 reg_offset, reg_val; + u32 cur_offset = 0, cur_val = 0; + bool succeed = false; + u8 index = 0; + + if (offset >> 16) { + FXGMAC_PR( + "Reading efuse out of range, reg %d. reg must be 2bytes.\n", + index); + return false; + } + + for (index = 0;; index++) { + if (!fxgmac_read_patch_from_efuse_per_index( + pdata, index, ®_offset, ®_val)) { + return false; + } else if (reg_offset == offset) { + cur_offset = reg_offset; + cur_val = reg_val; + } else if (0 == reg_offset && 0 == reg_val) { + break; /* first blank. We should write here. */ + } + } + + if (cur_offset == offset) { + if (cur_val == value) { + FXGMAC_PR("0x%x -> Reg0x%x already exists, ignore.\n", + value, offset); + return true; + } else { + FXGMAC_PR( + "Reg0x%x entry current value 0x%x, reprogram.\n", + offset, value); + } + } + + for (i = EFUSE_PATCH_ADDR_START_BYTE; i < EFUSE_PATCH_DATA_START_BYTE; + i++) { + reg_val = 0; + reg_val = FXGMAC_SET_REG_BITS( + reg_val, EFUSE_OP_ADDR_POS, EFUSE_OP_ADDR_LEN, + EFUSE_REGION_A_B_LENGTH + index * EFUSE_EACH_PATH_SIZE + + i); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_WR_DATA_POS, + EFUSE_OP_WR_DATA_LEN, + (offset >> (i << 3)) & 0xFF); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, + EFUSE_OP_START_LEN, 1); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, + EFUSE_OP_MODE_LEN, + EFUSE_OP_MODE_ROW_WRITE); + writereg(pdata->pAdapter, reg_val, + pdata->base_mem + EFUSE_OP_CTRL_0); + + succeed = false; + wait = 1000; + while (wait--) { + usleep_range_ex(pdata->pAdapter, 20, 50); + reg_val = readreg(pdata->pAdapter, + pdata->base_mem + EFUSE_OP_CTRL_1); + if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, + EFUSE_OP_DONE_LEN)) { + succeed = true; + break; + } + } + if (!succeed) { + FXGMAC_PR("Fail to writing efuse Byte%d\n", + index * EFUSE_EACH_PATH_SIZE + i); + return succeed; + } + } + + for (i = EFUSE_PATCH_DATA_START_BYTE; i < EFUSE_EACH_PATH_SIZE; i++) { + reg_val = 0; + reg_val = FXGMAC_SET_REG_BITS( + reg_val, EFUSE_OP_ADDR_POS, EFUSE_OP_ADDR_LEN, + EFUSE_REGION_A_B_LENGTH + index * EFUSE_EACH_PATH_SIZE + + i); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_WR_DATA_POS, + EFUSE_OP_WR_DATA_LEN, + (value >> ((i - 2) << 3)) & 0xFF); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, + EFUSE_OP_START_LEN, 1); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, + EFUSE_OP_MODE_LEN, + EFUSE_OP_MODE_ROW_WRITE); + writereg(pdata->pAdapter, reg_val, + pdata->base_mem + EFUSE_OP_CTRL_0); + + succeed = false; + wait = 1000; + while (wait--) { + usleep_range_ex(pdata->pAdapter, 20, 50); + reg_val = readreg(pdata->pAdapter, + pdata->base_mem + EFUSE_OP_CTRL_1); + if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, + EFUSE_OP_DONE_LEN)) { + succeed = true; + break; + } + } + if (!succeed) { + FXGMAC_PR("Fail to writing efuse Byte%d\n", + index * EFUSE_EACH_PATH_SIZE + i); + return succeed; + } + } + + return succeed; +} + +bool fxgmac_read_mac_subsys_from_efuse(struct fxgmac_pdata *pdata, u8 *mac_addr, + u32 *subsys, u32 *revid) +{ + u32 offset = 0, value = 0; + u32 machr = 0, maclr = 0; + bool succeed = true; + u8 index = 0; + + for (index = 0;; index++) { + if (!fxgmac_read_patch_from_efuse_per_index(pdata, index, + &offset, &value)) { + succeed = false; + break; /* reach the last item. */ + } + if (0x00 == offset) { + break; /* reach the blank. */ + } + if (MACA0LR_FROM_EFUSE == offset) { + maclr = value; + } + if (MACA0HR_FROM_EFUSE == offset) { + machr = value; + } + + if ((0x08 == offset) && revid) { + *revid = value; + } + if ((0x2C == offset) && subsys) { + *subsys = value; + } + } + if (mac_addr) { + mac_addr[5] = (u8)(maclr & 0xFF); + mac_addr[4] = (u8)((maclr >> 8) & 0xFF); + mac_addr[3] = (u8)((maclr >> 16) & 0xFF); + mac_addr[2] = (u8)((maclr >> 24) & 0xFF); + mac_addr[1] = (u8)(machr & 0xFF); + mac_addr[0] = (u8)((machr >> 8) & 0xFF); + } + + return succeed; +} + +bool fxgmac_write_mac_subsys_to_efuse(struct fxgmac_pdata *pdata, u8 *mac_addr, + u32 *subsys, u32 *revid) +{ + u32 machr = 0, maclr = 0, pcie_cfg_ctrl = PCIE_CFG_CTRL_DEFAULT_VAL; + bool succeed = true; + if (mac_addr) { + machr = readreg(pdata->pAdapter, + pdata->base_mem + MACA0HR_FROM_EFUSE); + maclr = readreg(pdata->pAdapter, + pdata->base_mem + MACA0LR_FROM_EFUSE); + DPRINTK("Current mac address from efuse is %02x-%02x-%02x-%02x-%02x-%02x.\n", + (machr >> 8) & 0xFF, machr & 0xFF, (maclr >> 24) & 0xFF, + (maclr >> 16) & 0xFF, (maclr >> 8) & 0xFF, + maclr & 0xFF); + + if (!fxgmac_write_patch_to_efuse(pdata, MACA0HR_FROM_EFUSE, + (((u32)mac_addr[0]) << 8) | + mac_addr[1])) { + succeed = false; + } + if (!fxgmac_write_patch_to_efuse( + pdata, MACA0LR_FROM_EFUSE, + (((u32)mac_addr[2]) << 24) | + (((u32)mac_addr[3]) << 16) | + (((u32)mac_addr[4]) << 8) | mac_addr[5])) { + succeed = false; + } + } + + if (revid) { + if (!fxgmac_write_patch_to_efuse(pdata, EFUSE_REVID_REGISTER, + *revid)) { + succeed = false; + } + } + if (subsys) { + pcie_cfg_ctrl = FXGMAC_SET_REG_BITS( + pcie_cfg_ctrl, MGMT_PCIE_CFG_CTRL_CS_EN_POS, + MGMT_PCIE_CFG_CTRL_CS_EN_LEN, 1); + if (!fxgmac_write_patch_to_efuse(pdata, MGMT_PCIE_CFG_CTRL, + pcie_cfg_ctrl)) { + succeed = false; + } + if (!fxgmac_write_patch_to_efuse(pdata, EFUSE_SUBSYS_REGISTER, + *subsys)) { + succeed = false; + } + pcie_cfg_ctrl = FXGMAC_SET_REG_BITS( + pcie_cfg_ctrl, MGMT_PCIE_CFG_CTRL_CS_EN_POS, + MGMT_PCIE_CFG_CTRL_CS_EN_LEN, 0); + if (!fxgmac_write_patch_to_efuse(pdata, MGMT_PCIE_CFG_CTRL, + pcie_cfg_ctrl)) { + succeed = false; + } + } + return succeed; +} + +bool fxgmac_write_mac_addr_to_efuse(struct fxgmac_pdata *pdata, u8 *mac_addr) +{ + u32 machr = 0, maclr = 0; + bool succeed = true; + + if (mac_addr) { + machr = readreg(pdata->pAdapter, + pdata->base_mem + MACA0HR_FROM_EFUSE); + maclr = readreg(pdata->pAdapter, + pdata->base_mem + MACA0LR_FROM_EFUSE); + DPRINTK("Current mac address from efuse is %02x-%02x-%02x-%02x-%02x-%02x.\n", + (machr >> 8) & 0xFF, machr & 0xFF, (maclr >> 24) & 0xFF, + (maclr >> 16) & 0xFF, (maclr >> 8) & 0xFF, + maclr & 0xFF); + + if (!fxgmac_write_patch_to_efuse(pdata, MACA0HR_FROM_EFUSE, + (((u32)mac_addr[0]) << 8) | + mac_addr[1])) { + succeed = false; + } + if (!fxgmac_write_patch_to_efuse( + pdata, MACA0LR_FROM_EFUSE, + (((u32)mac_addr[2]) << 24) | + (((u32)mac_addr[3]) << 16) | + (((u32)mac_addr[4]) << 8) | mac_addr[5])) { + succeed = false; + } + } + + return succeed; +} + +bool fxgmac_read_subsys_from_efuse(struct fxgmac_pdata *pdata, u32 *subsys, + u32 *revid) +{ + u32 offset = 0, value = 0; + u8 index; + bool succeed = true; + + for (index = 0;; index++) { + if (!fxgmac_read_patch_from_efuse_per_index(pdata, index, + &offset, &value)) { + succeed = false; + break; /* reach the last item. */ + } + if (0x00 == offset) { + break; /* reach the blank. */ + } + + if ((EFUSE_REVID_REGISTER == offset) && revid) { + *revid = value; + } else { + succeed = false; + } + if ((EFUSE_SUBSYS_REGISTER == offset) && subsys) { + *subsys = value; + } else { + succeed = false; + } + } + + return succeed; +} + +bool fxgmac_write_subsys_to_efuse(struct fxgmac_pdata *pdata, u32 *subsys, + u32 *revid) +{ + bool succeed = true; + + /* write subsys info */ + if (revid) { + if (!fxgmac_write_patch_to_efuse(pdata, EFUSE_REVID_REGISTER, + *revid)) { + succeed = false; + } + } + if (subsys) { + if (!fxgmac_write_patch_to_efuse(pdata, EFUSE_SUBSYS_REGISTER, + *subsys)) { + succeed = false; + } + } + return succeed; +} + +bool fxgmac_efuse_load(struct fxgmac_pdata *pdata) +{ + bool succeed = false; + unsigned int wait; + u32 reg_val = 0; + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, + EFUSE_OP_START_LEN, 1); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, + EFUSE_OP_MODE_LEN, + EFUSE_OP_MODE_AUTO_LOAD); + writereg(pdata->pAdapter, reg_val, pdata->base_mem + EFUSE_OP_CTRL_0); + + wait = 1000; + while (wait--) { + usleep_range_ex(pdata->pAdapter, 20, 50); + reg_val = readreg(pdata->pAdapter, + pdata->base_mem + EFUSE_OP_CTRL_1); + if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, + EFUSE_OP_DONE_LEN)) { + succeed = true; + break; + } + } + if (!succeed) { + FXGMAC_PR("Fail to loading efuse, ctrl_1 0x%08x\n", reg_val); + } + return succeed; +} + +bool fxgmac_efuse_read_data(struct fxgmac_pdata *pdata, u32 offset, u32 *value) +{ + bool succeed = false; + unsigned int wait; + u32 reg_val = 0; + + if (value) { + *value = 0; + } + + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_ADDR_POS, + EFUSE_OP_ADDR_LEN, offset); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, + EFUSE_OP_START_LEN, 1); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, + EFUSE_OP_MODE_LEN, + EFUSE_OP_MODE_ROW_READ); + writereg(pdata->pAdapter, reg_val, pdata->base_mem + EFUSE_OP_CTRL_0); + wait = 1000; + while (wait--) { + usleep_range_ex(pdata->pAdapter, 20, 50); + reg_val = readreg(pdata->pAdapter, + pdata->base_mem + EFUSE_OP_CTRL_1); + if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, + EFUSE_OP_DONE_LEN)) { + succeed = true; + break; + } + } + + if (succeed) { + if (value) { + *value = FXGMAC_GET_REG_BITS(reg_val, + EFUSE_OP_RD_DATA_POS, + EFUSE_OP_RD_DATA_LEN); + } + } else { + FXGMAC_PR("Fail to reading efuse Byte%d\n", offset); + } + + return succeed; +} + +bool fxgmac_efuse_write_oob(struct fxgmac_pdata *pdata) +{ + bool succeed = false; + unsigned int wait; + u32 reg_val, value; + + if (!fxgmac_efuse_read_data(pdata, EFUSE_OOB_ADDR, ®_val)) { + return succeed; + } + + if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OOB_POS, EFUSE_OOB_LEN)) { + FXGMAC_PR("OOB Ctrl bit already exists"); + return true; + } + + value = 0; + value = FXGMAC_SET_REG_BITS(value, EFUSE_OOB_POS, EFUSE_OOB_LEN, 1); + + reg_val = 0; + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_ADDR_POS, + EFUSE_OP_ADDR_LEN, EFUSE_OOB_ADDR); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_WR_DATA_POS, + EFUSE_OP_WR_DATA_LEN, value & 0xFF); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, + EFUSE_OP_START_LEN, 1); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, + EFUSE_OP_MODE_LEN, + EFUSE_OP_MODE_ROW_WRITE); + writereg(pdata->pAdapter, reg_val, pdata->base_mem + EFUSE_OP_CTRL_0); + + wait = 1000; + while (wait--) { + usleep_range_ex(pdata->pAdapter, 20, 50); + reg_val = readreg(pdata->pAdapter, + pdata->base_mem + EFUSE_OP_CTRL_1); + if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, + EFUSE_OP_DONE_LEN)) { + succeed = true; + break; + } + } + + if (!succeed) { + FXGMAC_PR("Fail to writing efuse Byte OOB"); + } + + return succeed; +} + +bool fxgmac_efuse_write_led(struct fxgmac_pdata *pdata, u32 value) +{ + bool succeed = false; + unsigned int wait; + u32 reg_val; + + if (!fxgmac_efuse_read_data(pdata, EFUSE_LED_ADDR, ®_val)) { + return succeed; + } + + if (reg_val == value) { + FXGMAC_PR("Led Ctrl option already exists"); + return true; + } + + reg_val = 0; + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_ADDR_POS, + EFUSE_OP_ADDR_LEN, EFUSE_LED_ADDR); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_WR_DATA_POS, + EFUSE_OP_WR_DATA_LEN, value & 0xFF); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, + EFUSE_OP_START_LEN, 1); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, + EFUSE_OP_MODE_LEN, + EFUSE_OP_MODE_ROW_WRITE); + writereg(pdata->pAdapter, reg_val, pdata->base_mem + EFUSE_OP_CTRL_0); + + wait = 1000; + while (wait--) { + usleep_range_ex(pdata->pAdapter, 20, 50); + reg_val = readreg(pdata->pAdapter, + pdata->base_mem + EFUSE_OP_CTRL_1); + if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, + EFUSE_OP_DONE_LEN)) { + succeed = true; + break; + } + } + + if (!succeed) { + FXGMAC_PR("Fail to writing efuse Byte LED"); + } + + return succeed; +} + +bool fxgmac_efuse_write_data(struct fxgmac_pdata *pdata, u32 offset, u32 value) +{ + bool succeed = false; + unsigned int wait; + u32 reg_val; + + if (!fxgmac_efuse_read_data(pdata, offset, ®_val)) { + return succeed; + } + + if (reg_val == value) { + FXGMAC_PR("offset 0x%x already exists", offset); + return true; + } + + reg_val = 0; + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_ADDR_POS, + EFUSE_OP_ADDR_LEN, offset & 0xFF); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_WR_DATA_POS, + EFUSE_OP_WR_DATA_LEN, value & 0xFF); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_START_POS, + EFUSE_OP_START_LEN, 1); + reg_val = FXGMAC_SET_REG_BITS(reg_val, EFUSE_OP_MODE_POS, + EFUSE_OP_MODE_LEN, + EFUSE_OP_MODE_ROW_WRITE); + writereg(pdata->pAdapter, reg_val, pdata->base_mem + EFUSE_OP_CTRL_0); + + wait = 1000; + while (wait--) { + usleep_range_ex(pdata->pAdapter, 20, 50); + reg_val = readreg(pdata->pAdapter, + pdata->base_mem + EFUSE_OP_CTRL_1); + if (FXGMAC_GET_REG_BITS(reg_val, EFUSE_OP_DONE_POS, + EFUSE_OP_DONE_LEN)) { + succeed = true; + break; + } + } + + if (!succeed) { + FXGMAC_PR("Fail to writing efuse 0x%x Byte LED", offset); + } + + return succeed; +} + +static void fxgmac_read_led_efuse_config(struct fxgmac_pdata *pdata, + struct led_setting *pfirst, + struct led_setting *psecond) +{ + u32 val_high = 0, val_low = 0; + + /* read first area */ + fxgmac_efuse_read_data(pdata, EFUSE_FISRT_UPDATE_ADDR, &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 1), &val_low); + pfirst->disable_led_setting[4] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 2), &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 3), &val_low); + pfirst->disable_led_setting[3] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 4), &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 5), &val_low); + pfirst->disable_led_setting[2] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 6), &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 7), &val_low); + pfirst->disable_led_setting[1] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 8), &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 9), &val_low); + pfirst->disable_led_setting[0] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 10), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 11), &val_low); + pfirst->s5_led_setting[4] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 12), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 13), &val_low); + pfirst->s5_led_setting[3] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 14), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 15), &val_low); + pfirst->s5_led_setting[2] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 16), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 17), &val_low); + pfirst->s5_led_setting[1] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 18), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 19), &val_low); + pfirst->s5_led_setting[0] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 20), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 21), &val_low); + pfirst->s3_led_setting[4] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 22), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 23), &val_low); + pfirst->s3_led_setting[3] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 24), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 25), &val_low); + pfirst->s3_led_setting[2] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 26), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 27), &val_low); + pfirst->s3_led_setting[1] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 28), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 29), &val_low); + pfirst->s3_led_setting[0] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 30), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 31), &val_low); + pfirst->s0_led_setting[4] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 32), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 33), &val_low); + pfirst->s0_led_setting[3] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 34), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 35), &val_low); + pfirst->s0_led_setting[2] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 36), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 37), &val_low); + pfirst->s0_led_setting[1] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 38), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 39), &val_low); + pfirst->s0_led_setting[0] = ((val_high << 8) + val_low); + + /* read second area */ + fxgmac_efuse_read_data(pdata, EFUSE_SECOND_UPDATE_ADDR, &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 1), &val_low); + psecond->disable_led_setting[4] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 2), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 3), &val_low); + psecond->disable_led_setting[3] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 4), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 5), &val_low); + psecond->disable_led_setting[2] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 6), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 7), &val_low); + psecond->disable_led_setting[1] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 8), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 9), &val_low); + psecond->disable_led_setting[0] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 10), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 11), + &val_low); + psecond->s5_led_setting[4] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 12), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 13), + &val_low); + psecond->s5_led_setting[3] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 14), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 15), + &val_low); + psecond->s5_led_setting[2] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 16), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 17), + &val_low); + psecond->s5_led_setting[1] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 18), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 19), + &val_low); + psecond->s5_led_setting[0] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 20), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 21), + &val_low); + psecond->s3_led_setting[4] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 22), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 23), + &val_low); + psecond->s3_led_setting[3] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 24), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 25), + &val_low); + psecond->s3_led_setting[2] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 26), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 27), + &val_low); + psecond->s3_led_setting[1] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 28), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 29), + &val_low); + psecond->s3_led_setting[0] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 30), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 31), + &val_low); + psecond->s0_led_setting[4] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 32), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 33), + &val_low); + psecond->s0_led_setting[3] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 34), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 35), + &val_low); + psecond->s0_led_setting[2] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 36), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 37), + &val_low); + psecond->s0_led_setting[1] = ((val_high << 8) + val_low); + + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 38), + &val_high); + fxgmac_efuse_read_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 39), + &val_low); + psecond->s0_led_setting[0] = ((val_high << 8) + val_low); +} + +bool fxgmac_write_led_setting_to_efuse(struct fxgmac_pdata *pdata) +{ + struct led_setting led_config_first; + struct led_setting led_config_second; + bool bfirstflag = false, bsecondflag = false; + bool bsucceed = false; + + fxgmac_read_led_efuse_config(pdata, &led_config_first, + &led_config_second); + + if (0x00 == led_config_first.s0_led_setting[0] && + 0x00 == led_config_first.s0_led_setting[1] && + 0x00 == led_config_first.s0_led_setting[2] && + 0x00 == led_config_first.s0_led_setting[3] && + 0x00 == led_config_first.s0_led_setting[4] && + 0x00 == led_config_first.s3_led_setting[0] && + 0x00 == led_config_first.s3_led_setting[1] && + 0x00 == led_config_first.s3_led_setting[2] && + 0x00 == led_config_first.s3_led_setting[3] && + 0x00 == led_config_first.s3_led_setting[4] && + 0x00 == led_config_first.s5_led_setting[0] && + 0x00 == led_config_first.s5_led_setting[1] && + 0x00 == led_config_first.s5_led_setting[2] && + 0x00 == led_config_first.s5_led_setting[3] && + 0x00 == led_config_first.s5_led_setting[4] && + 0x00 == led_config_first.disable_led_setting[0] && + 0x00 == led_config_first.disable_led_setting[1] && + 0x00 == led_config_first.disable_led_setting[2] && + 0x00 == led_config_first.disable_led_setting[3] && + 0x00 == led_config_first.disable_led_setting[4]) { + bfirstflag = true; + } + + if (0x00 == led_config_second.s0_led_setting[0] && + 0x00 == led_config_second.s0_led_setting[1] && + 0x00 == led_config_second.s0_led_setting[2] && + 0x00 == led_config_second.s0_led_setting[3] && + 0x00 == led_config_second.s0_led_setting[4] && + 0x00 == led_config_second.s3_led_setting[0] && + 0x00 == led_config_second.s3_led_setting[1] && + 0x00 == led_config_second.s3_led_setting[2] && + 0x00 == led_config_second.s3_led_setting[3] && + 0x00 == led_config_second.s3_led_setting[4] && + 0x00 == led_config_second.s5_led_setting[0] && + 0x00 == led_config_second.s5_led_setting[1] && + 0x00 == led_config_second.s5_led_setting[2] && + 0x00 == led_config_second.s5_led_setting[3] && + 0x00 == led_config_second.s5_led_setting[4] && + 0x00 == led_config_second.disable_led_setting[0] && + 0x00 == led_config_second.disable_led_setting[1] && + 0x00 == led_config_second.disable_led_setting[2] && + 0x00 == led_config_second.disable_led_setting[3] && + 0x00 == led_config_second.disable_led_setting[4]) { + bsecondflag = true; + } + + if (bfirstflag && bsecondflag) { + /* update first area */ + fxgmac_efuse_write_data( + pdata, EFUSE_FISRT_UPDATE_ADDR, + (pdata->ledconfig.disable_led_setting[4] >> 8) & 0xFF); + fxgmac_efuse_write_data( + pdata, (EFUSE_FISRT_UPDATE_ADDR - 1), + pdata->ledconfig.disable_led_setting[4]); + fxgmac_efuse_write_data( + pdata, (EFUSE_FISRT_UPDATE_ADDR - 2), + (pdata->ledconfig.disable_led_setting[3] >> 8) & 0xFF); + fxgmac_efuse_write_data( + pdata, (EFUSE_FISRT_UPDATE_ADDR - 3), + pdata->ledconfig.disable_led_setting[3]); + fxgmac_efuse_write_data( + pdata, (EFUSE_FISRT_UPDATE_ADDR - 4), + (pdata->ledconfig.disable_led_setting[2] >> 8) & 0xFF); + fxgmac_efuse_write_data( + pdata, (EFUSE_FISRT_UPDATE_ADDR - 5), + pdata->ledconfig.disable_led_setting[2]); + fxgmac_efuse_write_data( + pdata, (EFUSE_FISRT_UPDATE_ADDR - 6), + (pdata->ledconfig.disable_led_setting[1] >> 8) & 0xFF); + fxgmac_efuse_write_data( + pdata, (EFUSE_FISRT_UPDATE_ADDR - 7), + pdata->ledconfig.disable_led_setting[1]); + fxgmac_efuse_write_data( + pdata, (EFUSE_FISRT_UPDATE_ADDR - 8), + (pdata->ledconfig.disable_led_setting[0] >> 8) & 0xFF); + fxgmac_efuse_write_data( + pdata, (EFUSE_FISRT_UPDATE_ADDR - 9), + pdata->ledconfig.disable_led_setting[0]); + + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 10), + (pdata->ledconfig.s5_led_setting[4] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 11), + pdata->ledconfig.s5_led_setting[4]); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 12), + (pdata->ledconfig.s5_led_setting[3] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 13), + pdata->ledconfig.s5_led_setting[3]); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 14), + (pdata->ledconfig.s5_led_setting[2] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 15), + pdata->ledconfig.s5_led_setting[2]); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 16), + (pdata->ledconfig.s5_led_setting[1] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 17), + pdata->ledconfig.s5_led_setting[1]); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 18), + (pdata->ledconfig.s5_led_setting[0] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 19), + pdata->ledconfig.s5_led_setting[0]); + + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 20), + (pdata->ledconfig.s3_led_setting[4] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 21), + pdata->ledconfig.s3_led_setting[4]); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 22), + (pdata->ledconfig.s3_led_setting[3] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 23), + pdata->ledconfig.s3_led_setting[3]); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 24), + (pdata->ledconfig.s3_led_setting[2] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 25), + pdata->ledconfig.s3_led_setting[2]); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 26), + (pdata->ledconfig.s3_led_setting[1] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 27), + pdata->ledconfig.s3_led_setting[1]); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 28), + (pdata->ledconfig.s3_led_setting[0] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 29), + pdata->ledconfig.s3_led_setting[0]); + + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 30), + (pdata->ledconfig.s0_led_setting[4] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 31), + pdata->ledconfig.s0_led_setting[4]); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 32), + (pdata->ledconfig.s0_led_setting[3] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 33), + pdata->ledconfig.s0_led_setting[3]); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 34), + (pdata->ledconfig.s0_led_setting[2] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 35), + pdata->ledconfig.s0_led_setting[2]); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 36), + (pdata->ledconfig.s0_led_setting[1] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 37), + pdata->ledconfig.s0_led_setting[1]); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 38), + (pdata->ledconfig.s0_led_setting[0] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_FISRT_UPDATE_ADDR - 39), + pdata->ledconfig.s0_led_setting[0]); + + bsucceed = true; + } else if (!bfirstflag && bsecondflag) { + /* update second area */ + fxgmac_efuse_write_data( + pdata, EFUSE_SECOND_UPDATE_ADDR, + (pdata->ledconfig.disable_led_setting[4] >> 8) & 0xFF); + fxgmac_efuse_write_data( + pdata, (EFUSE_SECOND_UPDATE_ADDR - 1), + pdata->ledconfig.disable_led_setting[4]); + fxgmac_efuse_write_data( + pdata, (EFUSE_SECOND_UPDATE_ADDR - 2), + (pdata->ledconfig.disable_led_setting[3] >> 8) & 0xFF); + fxgmac_efuse_write_data( + pdata, (EFUSE_SECOND_UPDATE_ADDR - 3), + pdata->ledconfig.disable_led_setting[3]); + fxgmac_efuse_write_data( + pdata, (EFUSE_SECOND_UPDATE_ADDR - 4), + (pdata->ledconfig.disable_led_setting[2] >> 8) & 0xFF); + fxgmac_efuse_write_data( + pdata, (EFUSE_SECOND_UPDATE_ADDR - 5), + pdata->ledconfig.disable_led_setting[2]); + fxgmac_efuse_write_data( + pdata, (EFUSE_SECOND_UPDATE_ADDR - 6), + (pdata->ledconfig.disable_led_setting[1] >> 8) & 0xFF); + fxgmac_efuse_write_data( + pdata, (EFUSE_SECOND_UPDATE_ADDR - 7), + pdata->ledconfig.disable_led_setting[1]); + fxgmac_efuse_write_data( + pdata, (EFUSE_SECOND_UPDATE_ADDR - 8), + (pdata->ledconfig.disable_led_setting[0] >> 8) & 0xFF); + fxgmac_efuse_write_data( + pdata, (EFUSE_SECOND_UPDATE_ADDR - 9), + pdata->ledconfig.disable_led_setting[0]); + + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 10), + (pdata->ledconfig.s5_led_setting[4] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 11), + pdata->ledconfig.s5_led_setting[4]); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 12), + (pdata->ledconfig.s5_led_setting[3] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 13), + pdata->ledconfig.s5_led_setting[3]); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 14), + (pdata->ledconfig.s5_led_setting[2] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 15), + pdata->ledconfig.s5_led_setting[2]); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 16), + (pdata->ledconfig.s5_led_setting[1] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 17), + pdata->ledconfig.s5_led_setting[1]); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 18), + (pdata->ledconfig.s5_led_setting[0] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 19), + pdata->ledconfig.s5_led_setting[0]); + + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 20), + (pdata->ledconfig.s3_led_setting[4] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 21), + pdata->ledconfig.s3_led_setting[4]); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 22), + (pdata->ledconfig.s3_led_setting[3] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 23), + pdata->ledconfig.s3_led_setting[3]); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 24), + (pdata->ledconfig.s3_led_setting[2] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 25), + pdata->ledconfig.s3_led_setting[2]); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 26), + (pdata->ledconfig.s3_led_setting[1] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 27), + pdata->ledconfig.s3_led_setting[1]); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 28), + (pdata->ledconfig.s3_led_setting[0] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 29), + pdata->ledconfig.s3_led_setting[0]); + + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 30), + (pdata->ledconfig.s0_led_setting[4] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 31), + pdata->ledconfig.s0_led_setting[4]); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 32), + (pdata->ledconfig.s0_led_setting[3] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 33), + pdata->ledconfig.s0_led_setting[3]); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 34), + (pdata->ledconfig.s0_led_setting[2] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 35), + pdata->ledconfig.s0_led_setting[2]); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 36), + (pdata->ledconfig.s0_led_setting[1] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 37), + pdata->ledconfig.s0_led_setting[1]); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 38), + (pdata->ledconfig.s0_led_setting[0] >> + 8) & 0xFF); + fxgmac_efuse_write_data(pdata, (EFUSE_SECOND_UPDATE_ADDR - 39), + pdata->ledconfig.s0_led_setting[0]); + + bsucceed = true; + } + + return bsucceed; +} + +bool fxgmac_read_led_setting_from_efuse(struct fxgmac_pdata *pdata) +{ + struct led_setting led_config_first; + struct led_setting led_config_second; + bool bfirstflag = false, bsecondflag = false; + bool bsucceed = false; + + fxgmac_read_led_efuse_config(pdata, &led_config_first, + &led_config_second); + + if (0x00 == led_config_first.s0_led_setting[0] && + 0x00 == led_config_first.s0_led_setting[1] && + 0x00 == led_config_first.s0_led_setting[2] && + 0x00 == led_config_first.s0_led_setting[3] && + 0x00 == led_config_first.s0_led_setting[4] && + 0x00 == led_config_first.s3_led_setting[0] && + 0x00 == led_config_first.s3_led_setting[1] && + 0x00 == led_config_first.s3_led_setting[2] && + 0x00 == led_config_first.s3_led_setting[3] && + 0x00 == led_config_first.s3_led_setting[4] && + 0x00 == led_config_first.s5_led_setting[0] && + 0x00 == led_config_first.s5_led_setting[1] && + 0x00 == led_config_first.s5_led_setting[2] && + 0x00 == led_config_first.s5_led_setting[3] && + 0x00 == led_config_first.s5_led_setting[4] && + 0x00 == led_config_first.disable_led_setting[0] && + 0x00 == led_config_first.disable_led_setting[1] && + 0x00 == led_config_first.disable_led_setting[2] && + 0x00 == led_config_first.disable_led_setting[3] && + 0x00 == led_config_first.disable_led_setting[4]) { + bfirstflag = true; + } + + if (0x00 == led_config_second.s0_led_setting[0] && + 0x00 == led_config_second.s0_led_setting[1] && + 0x00 == led_config_second.s0_led_setting[2] && + 0x00 == led_config_second.s0_led_setting[3] && + 0x00 == led_config_second.s0_led_setting[4] && + 0x00 == led_config_second.s3_led_setting[0] && + 0x00 == led_config_second.s3_led_setting[1] && + 0x00 == led_config_second.s3_led_setting[2] && + 0x00 == led_config_second.s3_led_setting[3] && + 0x00 == led_config_second.s3_led_setting[4] && + 0x00 == led_config_second.s5_led_setting[0] && + 0x00 == led_config_second.s5_led_setting[1] && + 0x00 == led_config_second.s5_led_setting[2] && + 0x00 == led_config_second.s5_led_setting[3] && + 0x00 == led_config_second.s5_led_setting[4] && + 0x00 == led_config_second.disable_led_setting[0] && + 0x00 == led_config_second.disable_led_setting[1] && + 0x00 == led_config_second.disable_led_setting[2] && + 0x00 == led_config_second.disable_led_setting[3] && + 0x00 == led_config_second.disable_led_setting[4]) { + bsecondflag = true; + } + + if (!bfirstflag && bsecondflag) { + /* read first area */ + memcpy(&pdata->led, &led_config_first, + sizeof(struct led_setting)); + bsucceed = true; + } else if (!bfirstflag && !bsecondflag) { + /* read second area */ + memcpy(&pdata->led, &led_config_second, + sizeof(struct led_setting)); + bsucceed = true; + } + + return bsucceed; +} \ No newline at end of file diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.h b/drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.h new file mode 100644 index 0000000000000..fa0446958719c --- /dev/null +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-efuse.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021 Motorcomm Corporation. */ + +#ifndef __FUXI_EFUSE_H__ +#define __FUXI_EFUSE_H__ + + +bool fxgmac_read_patch_from_efuse(struct fxgmac_pdata *pdata, u32 offset, u32 *value); /* read patch per register offset. */ +bool fxgmac_read_patch_from_efuse_per_index(struct fxgmac_pdata *pdata, u8 index, u32 *offset, u32 *value); /* read patch per 0-based index. */ +bool fxgmac_write_patch_to_efuse(struct fxgmac_pdata *pdata, u32 offset, u32 value); +bool fxgmac_write_patch_to_efuse_per_index(struct fxgmac_pdata *pdata, u8 index, u32 offset, u32 value); +bool fxgmac_read_mac_subsys_from_efuse(struct fxgmac_pdata *pdata, u8 *mac_addr, u32 *subsys, u32 *revid); +bool fxgmac_write_mac_subsys_to_efuse(struct fxgmac_pdata *pdata, u8 *mac_addr, u32 *subsys, u32 *revid); +bool fxgmac_write_mac_addr_to_efuse(struct fxgmac_pdata *pdata, u8 *mac_addr); +bool fxgmac_read_subsys_from_efuse(struct fxgmac_pdata *pdata, u32 *subsys, u32 *revid); +bool fxgmac_write_subsys_to_efuse(struct fxgmac_pdata *pdata, u32 *subsys, u32 *revid); +bool fxgmac_efuse_load(struct fxgmac_pdata *pdata); +bool fxgmac_efuse_read_data(struct fxgmac_pdata *pdata, u32 offset, u32 *value); +bool fxgmac_efuse_write_data(struct fxgmac_pdata *pdata, u32 offset, u32 value); +bool fxgmac_efuse_write_oob(struct fxgmac_pdata *pdata); +bool fxgmac_efuse_write_led(struct fxgmac_pdata *pdata, u32 value); +bool fxgmac_read_led_setting_from_efuse(struct fxgmac_pdata *pdata); +bool fxgmac_write_led_setting_to_efuse(struct fxgmac_pdata *pdata); + +#endif /* __FUXI_EFUSE_H__ */ \ No newline at end of file diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-common.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-common.c new file mode 100644 index 0000000000000..63cbf948cbfa2 --- /dev/null +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-common.c @@ -0,0 +1,939 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021 Motorcomm Corporation. */ + +#include +#include + +#include "fuxi-os.h" +#include "fuxi-gmac.h" +#include "fuxi-gmac-reg.h" + +MODULE_LICENSE("Dual BSD/GPL"); + +static int debug = 16; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "FUXI ethernet debug level (0=none,...,16=all)"); + +static unsigned char dev_addr[6] = { 0, 0x55, 0x7b, 0xb5, 0x7d, 0xf7 }; + +static void fxgmac_read_mac_addr(struct fxgmac_pdata *pdata) +{ + struct net_device *netdev = pdata->netdev; + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + + DPRINTK("read mac from eFuse\n"); + + /* if efuse have mac addr, use it.if not, use static mac address. */ + hw_ops->read_mac_subsys_from_efuse(pdata, pdata->mac_addr, NULL, NULL); + if (ETH_IS_ZEROADDRESS(pdata->mac_addr)) { + /* Currently it uses a static mac address for test */ + memcpy(pdata->mac_addr, dev_addr, netdev->addr_len); + } +} + +static void fxgmac_default_config(struct fxgmac_pdata *pdata) +{ + pdata->tx_osp_mode = DMA_OSP_ENABLE; + pdata->tx_sf_mode = MTL_TSF_ENABLE; + pdata->rx_sf_mode = MTL_RSF_DISABLE; /* MTL_RSF_DISABLE 20210514 */ + pdata->pblx8 = DMA_PBL_X8_ENABLE; /* DMA_PBL_X8_ENABLE 20210514 */ + pdata->tx_pbl = DMA_PBL_32; + pdata->rx_pbl = DMA_PBL_32; /* DMA_PBL_32 20210514 */ + pdata->tx_threshold = MTL_TX_THRESHOLD_128; + pdata->rx_threshold = MTL_RX_THRESHOLD_128; + pdata->tx_pause = 1; + pdata->rx_pause = 1; + +#if FXGMAC_RSS_FEATURE_ENABLED + pdata->rss = 1; +#else + pdata->rss = 0; +#endif + /* open interrupt moderation default */ + pdata->intr_mod = 1; + pdata->crc_check = 1; + + /* set based on phy status. pdata->phy_speed = SPEED_1000; */ + pdata->sysclk_rate = FXGMAC_SYSCLOCK; + pdata->phy_autoeng = AUTONEG_ENABLE; /* default to autoneg */ + pdata->phy_duplex = DUPLEX_FULL; + pdata->expansion.phy_link = false; + pdata->phy_speed = SPEED_1000; + + /* default to magic */ + pdata->expansion.wol = WAKE_MAGIC; + + strscpy(pdata->drv_name, FXGMAC_DRV_NAME, sizeof(pdata->drv_name)); + strscpy(pdata->drv_ver, FXGMAC_DRV_VERSION, sizeof(pdata->drv_ver)); + + printk("FXGMAC_DRV_NAME:%s, FXGMAC_DRV_VERSION:%s\n", FXGMAC_DRV_NAME, + FXGMAC_DRV_VERSION); +} + +static void fxgmac_init_all_ops(struct fxgmac_pdata *pdata) +{ + fxgmac_init_desc_ops(&pdata->desc_ops); + fxgmac_init_hw_ops(&pdata->hw_ops); + + DPRINTK("register desc_ops and hw ops\n"); +} + +int fxgmac_init(struct fxgmac_pdata *pdata, bool save_private_reg) +{ + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + struct net_device *netdev = pdata->netdev; + unsigned int i, dma_width; + int ret; + + /* Set all the function pointers */ + fxgmac_init_all_ops(pdata); + + /* Set default configuration data */ + fxgmac_default_config(pdata); + + /* Set irq, base_addr, MAC address, */ + netdev->irq = pdata->dev_irq; + netdev->base_addr = (unsigned long)pdata->base_mem; + fxgmac_read_mac_addr(pdata); + eth_hw_addr_set(netdev, pdata->mac_addr); + + if (save_private_reg) { + hw_ops->save_nonstick_reg(pdata); + } + + /* reset here to get hw features correctly */ + hw_ops->exit(pdata); + + /* Populate the hardware features */ + fxgmac_get_all_hw_features(pdata); + fxgmac_print_all_hw_features(pdata); + + /* TODO: Set the PHY mode to XLGMII */ + + /* Set the DMA mask */ +#ifdef CONFIG_ARM64 + dma_width = FUXI_DMA_BIT_MASK; +#else + dma_width = pdata->hw_feat.dma_width; +#endif + ret = dma_set_mask_and_coherent(pdata->dev, DMA_BIT_MASK(dma_width)); + if (ret) { + dev_err(pdata->dev, "dma_set_mask_and_coherent failed\n"); + return ret; + } + + /* Channel and ring params initializtion + * pdata->channel_count; + * pdata->tx_ring_count; + * pdata->rx_ring_count; + * pdata->tx_desc_count; + * pdata->rx_desc_count; + */ + BUILD_BUG_ON_NOT_POWER_OF_2(FXGMAC_TX_DESC_CNT); + pdata->tx_desc_count = FXGMAC_TX_DESC_CNT; + if (pdata->tx_desc_count & (pdata->tx_desc_count - 1)) { + dev_err(pdata->dev, "tx descriptor count (%d) is not valid\n", + pdata->tx_desc_count); + ret = -EINVAL; + return ret; + } + BUILD_BUG_ON_NOT_POWER_OF_2(FXGMAC_RX_DESC_CNT); + pdata->rx_desc_count = FXGMAC_RX_DESC_CNT; + if (pdata->rx_desc_count & (pdata->rx_desc_count - 1)) { + dev_err(pdata->dev, "rx descriptor count (%d) is not valid\n", + pdata->rx_desc_count); + ret = -EINVAL; + return ret; + } + + pdata->tx_ring_count = min_t(unsigned int, num_online_cpus(), + pdata->hw_feat.tx_ch_cnt); + pdata->tx_ring_count = min_t(unsigned int, pdata->tx_ring_count, + pdata->hw_feat.tx_q_cnt); + pdata->tx_q_count = pdata->tx_ring_count; + +#if !(FXGMAC_NUM_OF_TX_Q_USED) + ret = netif_set_real_num_tx_queues(netdev, pdata->tx_q_count); +#else + ret = netif_set_real_num_tx_queues( + netdev, FXGMAC_NUM_OF_TX_Q_USED /*pdata->tx_q_count*/); +#endif + + DPRINTK("num_online_cpus:%u, tx_ch_cnt:%u, tx_q_cnt:%u, tx_ring_count:%u\n", + num_online_cpus(), pdata->hw_feat.tx_ch_cnt, + pdata->hw_feat.tx_q_cnt, pdata->tx_ring_count); + + if (ret) { + dev_err(pdata->dev, "error setting real tx queue count\n"); + return ret; + } + + pdata->rx_ring_count = min_t(unsigned int, + netif_get_num_default_rss_queues(), + pdata->hw_feat.rx_ch_cnt); +#ifdef FXGMAC_ONE_CHANNEL + pdata->rx_ring_count = 1; + pdata->hw_feat.rx_q_cnt = pdata->rx_ring_count; +#else + pdata->rx_ring_count = min_t(unsigned int, pdata->rx_ring_count, + pdata->hw_feat.rx_q_cnt); +#endif + pdata->rx_q_count = pdata->rx_ring_count; + ret = netif_set_real_num_rx_queues(netdev, pdata->rx_q_count); + if (ret) { + dev_err(pdata->dev, "error setting real rx queue count\n"); + return ret; + } + + pdata->channel_count = + max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count); + + DPRINTK("default rss queues:%u, rx_ch_cnt:%u, rx_q_cnt:%u, rx_ring_count:%u\n", + netif_get_num_default_rss_queues(), pdata->hw_feat.rx_ch_cnt, + pdata->hw_feat.rx_q_cnt, pdata->rx_ring_count); + DPRINTK("channel_count:%u, netdev tx channel_num=%u\n", + pdata->channel_count, netdev->num_tx_queues); + + /* Initialize RSS hash key and lookup table */ +#if FXGMAC_RSS_HASH_KEY_LINUX + netdev_rss_key_fill(pdata->rss_key, sizeof(pdata->rss_key)); +#else + /* this is for test only. HW does not want to change Hash key */ + hw_ops->get_rss_hash_key(pdata, (u8 *)pdata->rss_key); +#endif + +#if FXGMAC_MSIX_CH0RXDIS_EN + for (i = 0; i < FXGMAC_RSS_MAX_TABLE_SIZE; i++) { + pdata->rss_table[i] = FXGMAC_SET_REG_BITS( + pdata->rss_table[i], MAC_RSSDR_DMCH_POS, + MAC_RSSDR_DMCH_LEN, (i % 3) + 1); /* eliminate ch0 */ + } +#else + for (i = 0; i < FXGMAC_RSS_MAX_TABLE_SIZE; i++) { + pdata->rss_table[i] = FXGMAC_SET_REG_BITS( + pdata->rss_table[i], MAC_RSSDR_DMCH_POS, + MAC_RSSDR_DMCH_LEN, + /* note, rx_ring_count should be equal to IRQ requsted + * for MSIx, 4 + */ + i % pdata->rx_ring_count); + } +#endif + + pdata->rss_options = FXGMAC_SET_REG_BITS(pdata->rss_options, + MAC_RSSCR_IP4TE_POS, + MAC_RSSCR_IP4TE_LEN, 1); + pdata->rss_options = FXGMAC_SET_REG_BITS(pdata->rss_options, + MAC_RSSCR_TCP4TE_POS, + MAC_RSSCR_TCP4TE_LEN, 1); + pdata->rss_options = FXGMAC_SET_REG_BITS(pdata->rss_options, + MAC_RSSCR_UDP4TE_POS, + MAC_RSSCR_UDP4TE_LEN, 1); + + /* config MTU supported, 20210726 */ + netdev->min_mtu = ETH_MIN_MTU; + netdev->max_mtu = + FXGMAC_JUMBO_PACKET_MTU + (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN); + /* + * netdev->extended->min_mtu = netdev->min_mtu; + * netdev->extended->max_mtu = netdev->max_mtu; + */ + + DPRINTK("rss_options:0x%x\n", pdata->rss_options); + + /* Set device operations */ + netdev->netdev_ops = fxgmac_get_netdev_ops(); + netdev->ethtool_ops = fxgmac_get_ethtool_ops(); + + /* Set device features */ + if (pdata->hw_feat.tso) { + netdev->hw_features = NETIF_F_TSO; + netdev->hw_features |= NETIF_F_TSO6; + netdev->hw_features |= NETIF_F_SG; + netdev->hw_features |= NETIF_F_IP_CSUM; + netdev->hw_features |= NETIF_F_IPV6_CSUM; + } else if (pdata->hw_feat.tx_coe) { + netdev->hw_features = NETIF_F_IP_CSUM; + netdev->hw_features |= NETIF_F_IPV6_CSUM; + } + + if (pdata->hw_feat.rx_coe) { + netdev->hw_features |= NETIF_F_RXCSUM; + netdev->hw_features |= NETIF_F_GRO; + } + + if (pdata->hw_feat.rss) { + netdev->hw_features |= + NETIF_F_RXHASH; /* it is NETIF_F_RXHASH_BIT finally */ + } + + netdev->vlan_features |= netdev->hw_features; + + netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX; + pdata->vlan_strip = 1; + if (pdata->hw_feat.sa_vlan_ins) { + netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX; + } +#if FXGMAC_FILTER_SINGLE_VLAN_ENABLED + /* only can filter one vlan id */ + pdata->hw_feat.vlhash = 1; +#else + pdata->hw_feat.vlhash = 0; +#endif + + if (pdata->hw_feat.vlhash) { + netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER; + pdata->vlan_filter = 1; + } + + netdev->features |= netdev->hw_features; + pdata->expansion.netdev_features = netdev->features; + + netdev->priv_flags |= IFF_UNICAST_FLT; + + /* Use default watchdog timeout */ + netdev->watchdog_timeo = + msecs_to_jiffies(5000); /* refer to sunxi-gmac, 5s */ + netdev->gso_max_size = NIC_MAX_TCP_OFFLOAD_SIZE; + + /* Tx coalesce parameters initialization */ + pdata->tx_usecs = FXGMAC_INIT_DMA_TX_USECS; + pdata->tx_frames = FXGMAC_INIT_DMA_TX_FRAMES; + + /* Rx coalesce parameters initialization */ + pdata->rx_riwt = hw_ops->usec_to_riwt(pdata, FXGMAC_INIT_DMA_RX_USECS); + + pdata->rx_usecs = FXGMAC_INIT_DMA_RX_USECS; + pdata->rx_frames = FXGMAC_INIT_DMA_RX_FRAMES; + + DPRINTK("fxgmac_init callout, ok.\n"); + + return 0; +} + +static void fxgmac_init_interrupt_scheme(struct fxgmac_pdata *pdata) +{ +#ifdef CONFIG_PCI_MSI + int vectors, rc, i, req_vectors; + /* check cpu core number. + * since we have 4 channels, we must ensure the number of cpu core > 4 + * otherwise, just roll back to legacy + */ + vectors = num_online_cpus(); + DPRINTK("num of cpu=%d\n", vectors); + if (vectors >= FXGMAC_MAX_DMA_CHANNELS) { + /* 0-3 for rx, 4 for tx, 5 for phy */ + req_vectors = FXGMAC_MSIX_INT_NUMS; + pdata->expansion.msix_entries = kcalloc( + req_vectors, sizeof(struct msix_entry), GFP_KERNEL); + if (!pdata->expansion.msix_entries) { + DPRINTK("MSIx, kcalloc err for msix entries, rollback to MSI..\n"); + goto enable_msi_interrupt; + } else { + for (i = 0; i < req_vectors; i++) + pdata->expansion.msix_entries[i].entry = i; + + rc = pci_enable_msix_range( + pdata->pdev, pdata->expansion.msix_entries, + req_vectors, req_vectors); + if (rc < 0) { + DPRINTK("enable MSIx failed,%d.\n", rc); + req_vectors = 0; /* indicate failure */ + } else { + req_vectors = rc; + } + + if (req_vectors >= FXGMAC_MAX_DMA_CHANNELS_PLUS_1TX) { + DPRINTK("enable MSIx ok, cpu=%d, vectors=%d.\n", + vectors, req_vectors); + pdata->expansion.int_flags = + FXGMAC_SET_REG_BITS( + pdata->expansion.int_flags, + FXGMAC_FLAG_INTERRUPT_POS, + FXGMAC_FLAG_INTERRUPT_LEN, + FXGMAC_FLAG_MSIX_ENABLED); + pdata->per_channel_irq = 1; + pdata->expansion.phy_irq = + pdata->expansion + .msix_entries[MSI_ID_PHY_OTHER] + .vector; + return; + } else if (req_vectors) { + DPRINTK("enable MSIx with only %d vector, while we need %d, rollback to MSI.\n", + req_vectors, vectors); + /* roll back to msi */ + pci_disable_msix(pdata->pdev); + kfree(pdata->expansion.msix_entries); + pdata->expansion.msix_entries = NULL; + req_vectors = 0; + } else { + DPRINTK("enable MSIx failure and clear msix entries.\n"); + /* roll back to msi */ + kfree(pdata->expansion.msix_entries); + pdata->expansion.msix_entries = NULL; + req_vectors = 0; + } + } + } + +enable_msi_interrupt: + rc = pci_enable_msi(pdata->pdev); + if (rc < 0) { + pdata->expansion.int_flags = FXGMAC_SET_REG_BITS( + pdata->expansion.int_flags, FXGMAC_FLAG_INTERRUPT_POS, + FXGMAC_FLAG_INTERRUPT_LEN, FXGMAC_FLAG_LEGACY_ENABLED); + DPRINTK("enable MSI failure, rollback to LEGACY.\n"); + } else { + pdata->expansion.int_flags = FXGMAC_SET_REG_BITS( + pdata->expansion.int_flags, FXGMAC_FLAG_INTERRUPT_POS, + FXGMAC_FLAG_INTERRUPT_LEN, FXGMAC_FLAG_MSI_ENABLED); + pdata->dev_irq = pdata->pdev->irq; + DPRINTK("enable MSI ok, irq=%d.\n", pdata->pdev->irq); + } +#else + pdata = pdata; +#endif +} + +int fxgmac_drv_probe(struct device *dev, struct fxgmac_resources *res) +{ + struct fxgmac_pdata *pdata; + struct net_device *netdev; + int ret; + + netdev = alloc_etherdev_mq(sizeof(struct fxgmac_pdata), + FXGMAC_MAX_DMA_CHANNELS); + + if (!netdev) { + dev_err(dev, "alloc_etherdev failed\n"); + return -ENOMEM; + } + + SET_NETDEV_DEV(netdev, dev); + dev_set_drvdata(dev, netdev); + pdata = netdev_priv(netdev); + pdata->dev = dev; + pdata->pdev = to_pci_dev(dev); + pdata->netdev = netdev; + + pdata->dev_irq = res->irq; + + /* default to legacy interrupt */ + pdata->expansion.int_flags = FXGMAC_SET_REG_BITS( + pdata->expansion.int_flags, FXGMAC_FLAG_INTERRUPT_POS, + FXGMAC_FLAG_INTERRUPT_LEN, FXGMAC_FLAG_LEGACY_ENABLED); + pdata->expansion.phy_irq = pdata->dev_irq; + + fxgmac_init_interrupt_scheme(pdata); + + pdata->expansion.current_state = CURRENT_STATE_INIT; + + pdata->msg_enable = NETIF_MSG_DRV; + DPRINTK("netif msg_enable init to %08x\n", pdata->msg_enable); + + pdata->mac_regs = res->addr; + pdata->base_mem = res->addr; + pdata->mac_regs = pdata->mac_regs + FUXI_MAC_REGS_OFFSET; + + ret = fxgmac_init(pdata, true); + if (ret) { + dev_err(dev, "fxgmac init failed\n"); + goto err_free_netdev; + } + + pdata->hw_ops.read_led_config(pdata); + + netif_carrier_off(netdev); + ret = register_netdev(netdev); + if (ret) { + dev_err(dev, "net device registration failed\n"); + goto err_free_netdev; + } + if (netif_msg_drv(pdata)) + DPRINTK("fxgamc_drv_prob callout, netdev num_tx_q=%u\n", + netdev->num_tx_queues); + +#ifdef HAVE_FXGMAC_DEBUG_FS + fxgmac_dbg_init(pdata); + fxgmac_dbg_adapter_init(pdata); +#endif /* HAVE_FXGMAC_DEBUG_FS */ + + return 0; + +err_free_netdev: + free_netdev(netdev); + DPRINTK("fxgamc_drv_prob callout with err \n"); + + return ret; +} + +int fxgmac_drv_remove(struct device *dev) +{ + struct net_device *netdev = dev_get_drvdata(dev); + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + +#ifdef HAVE_FXGMAC_DEBUG_FS + fxgmac_dbg_adapter_exit(pdata); +#endif /*HAVE_FXGMAC_DEBUG_FS */ + hw_ops->led_under_shutdown(pdata); + + unregister_netdev(netdev); + free_netdev(netdev); + + return 0; +} + +void fxgmac_dump_tx_desc(struct fxgmac_pdata *pdata, struct fxgmac_ring *ring, + unsigned int idx, unsigned int count, + unsigned int flag) +{ + struct fxgmac_desc_data *desc_data; + struct fxgmac_dma_desc *dma_desc; + + while (count--) { + desc_data = FXGMAC_GET_DESC_DATA(ring, idx); + dma_desc = desc_data->dma_desc; + + netdev_dbg(pdata->netdev, + "TX: dma_desc=%p, dma_desc_addr=%pad\n", + desc_data->dma_desc, &desc_data->dma_desc_addr); + netdev_dbg(pdata->netdev, + "TX_NORMAL_DESC[%d %s] = %08x:%08x:%08x:%08x\n", idx, + (flag == 1) ? "QUEUED FOR TX" : "TX BY DEVICE", + le32_to_cpu(dma_desc->desc0), + le32_to_cpu(dma_desc->desc1), + le32_to_cpu(dma_desc->desc2), + le32_to_cpu(dma_desc->desc3)); + + idx++; + } +} + +void fxgmac_dump_rx_desc(struct fxgmac_pdata *pdata, struct fxgmac_ring *ring, + unsigned int idx) +{ + struct fxgmac_desc_data *desc_data; + struct fxgmac_dma_desc *dma_desc; + + desc_data = FXGMAC_GET_DESC_DATA(ring, idx); + dma_desc = desc_data->dma_desc; + + netdev_dbg(pdata->netdev, "RX: dma_desc=%p, dma_desc_addr=%pad\n", + desc_data->dma_desc, &desc_data->dma_desc_addr); + netdev_dbg(pdata->netdev, + "RX_NORMAL_DESC[%d RX BY DEVICE] = %08x:%08x:%08x:%08x\n", + idx, le32_to_cpu(dma_desc->desc0), + le32_to_cpu(dma_desc->desc1), le32_to_cpu(dma_desc->desc2), + le32_to_cpu(dma_desc->desc3)); +} + +void fxgmac_dbg_pkt(struct net_device *netdev, struct sk_buff *skb, bool tx_rx) +{ + struct ethhdr *eth = (struct ethhdr *)skb->data; + unsigned char buffer[128]; + unsigned int i; + + netdev_dbg(netdev, "\n************** SKB dump ****************\n"); + + netdev_dbg(netdev, "%s packet of %d bytes\n", (tx_rx ? "TX" : "RX"), + skb->len); + + netdev_dbg(netdev, "Dst MAC addr: %pM\n", eth->h_dest); + netdev_dbg(netdev, "Src MAC addr: %pM\n", eth->h_source); + netdev_dbg(netdev, "Protocol: %#06hx\n", ntohs(eth->h_proto)); + + for (i = 0; i < skb->len; i += 32) { + unsigned int len = min(skb->len - i, 32U); + + hex_dump_to_buffer(&skb->data[i], len, 32, 1, buffer, + sizeof(buffer), false); + netdev_dbg(netdev, " %#06x: %s\n", i, buffer); + } + + netdev_dbg(netdev, "\n************** SKB dump ****************\n"); +} + +void fxgmac_print_pkt(struct net_device *netdev, struct sk_buff *skb, + bool tx_rx) +{ + unsigned char buffer[128]; + unsigned int i; + + for (i = 0; i < skb->len; i += 32) { + unsigned int len = min(skb->len - i, 32U); + + hex_dump_to_buffer(&skb->data[i], len, 32, 1, buffer, + sizeof(buffer), false); + DPRINTK(" %#06x: %s\n", i, buffer); + } +} + +void fxgmac_get_all_hw_features(struct fxgmac_pdata *pdata) +{ + struct fxgmac_hw_features *hw_feat = &pdata->hw_feat; + unsigned int mac_hfr0, mac_hfr1, mac_hfr2, mac_hfr3; + + mac_hfr0 = readl(pdata->mac_regs + MAC_HWF0R); + mac_hfr1 = readl(pdata->mac_regs + MAC_HWF1R); + mac_hfr2 = readl(pdata->mac_regs + MAC_HWF2R); + mac_hfr3 = readl(pdata->mac_regs + MAC_HWF3R); + + memset(hw_feat, 0, sizeof(*hw_feat)); + + hw_feat->version = readl(pdata->mac_regs + MAC_VR); + if (netif_msg_drv(pdata)) + DPRINTK("get offset 0x110, ver=%#x\n", + readl(pdata->mac_regs + 0x110)); + + /* Hardware feature register 0 */ + hw_feat->phyifsel = FXGMAC_GET_REG_BITS( + mac_hfr0, MAC_HWF0R_ACTPHYIFSEL_POS, MAC_HWF0R_ACTPHYIFSEL_LEN); + hw_feat->vlhash = FXGMAC_GET_REG_BITS(mac_hfr0, MAC_HWF0R_VLHASH_POS, + MAC_HWF0R_VLHASH_LEN); + hw_feat->sma = FXGMAC_GET_REG_BITS(mac_hfr0, MAC_HWF0R_SMASEL_POS, + MAC_HWF0R_SMASEL_LEN); + hw_feat->rwk = FXGMAC_GET_REG_BITS(mac_hfr0, MAC_HWF0R_RWKSEL_POS, + MAC_HWF0R_RWKSEL_LEN); + hw_feat->mgk = FXGMAC_GET_REG_BITS(mac_hfr0, MAC_HWF0R_MGKSEL_POS, + MAC_HWF0R_MGKSEL_LEN); + hw_feat->mmc = FXGMAC_GET_REG_BITS(mac_hfr0, MAC_HWF0R_MMCSEL_POS, + MAC_HWF0R_MMCSEL_LEN); + hw_feat->aoe = FXGMAC_GET_REG_BITS(mac_hfr0, MAC_HWF0R_ARPOFFSEL_POS, + MAC_HWF0R_ARPOFFSEL_LEN); + hw_feat->ts = FXGMAC_GET_REG_BITS(mac_hfr0, MAC_HWF0R_TSSEL_POS, + MAC_HWF0R_TSSEL_LEN); + hw_feat->eee = FXGMAC_GET_REG_BITS(mac_hfr0, MAC_HWF0R_EEESEL_POS, + MAC_HWF0R_EEESEL_LEN); + hw_feat->tx_coe = FXGMAC_GET_REG_BITS(mac_hfr0, MAC_HWF0R_TXCOESEL_POS, + MAC_HWF0R_TXCOESEL_LEN); + hw_feat->rx_coe = FXGMAC_GET_REG_BITS(mac_hfr0, MAC_HWF0R_RXCOESEL_POS, + MAC_HWF0R_RXCOESEL_LEN); + hw_feat->addn_mac = FXGMAC_GET_REG_BITS(mac_hfr0, + MAC_HWF0R_ADDMACADRSEL_POS, + MAC_HWF0R_ADDMACADRSEL_LEN); + hw_feat->ts_src = FXGMAC_GET_REG_BITS(mac_hfr0, MAC_HWF0R_TSSTSSEL_POS, + MAC_HWF0R_TSSTSSEL_LEN); + hw_feat->sa_vlan_ins = FXGMAC_GET_REG_BITS( + mac_hfr0, MAC_HWF0R_SAVLANINS_POS, MAC_HWF0R_SAVLANINS_LEN); + + /* Hardware feature register 1 */ + hw_feat->rx_fifo_size = FXGMAC_GET_REG_BITS( + mac_hfr1, MAC_HWF1R_RXFIFOSIZE_POS, MAC_HWF1R_RXFIFOSIZE_LEN); + hw_feat->tx_fifo_size = FXGMAC_GET_REG_BITS( + mac_hfr1, MAC_HWF1R_TXFIFOSIZE_POS, MAC_HWF1R_TXFIFOSIZE_LEN); + hw_feat->adv_ts_hi = FXGMAC_GET_REG_BITS( + mac_hfr1, MAC_HWF1R_ADVTHWORD_POS, MAC_HWF1R_ADVTHWORD_LEN); + hw_feat->dma_width = FXGMAC_GET_REG_BITS(mac_hfr1, MAC_HWF1R_ADDR64_POS, + MAC_HWF1R_ADDR64_LEN); + hw_feat->dcb = FXGMAC_GET_REG_BITS(mac_hfr1, MAC_HWF1R_DCBEN_POS, + MAC_HWF1R_DCBEN_LEN); + hw_feat->sph = FXGMAC_GET_REG_BITS(mac_hfr1, MAC_HWF1R_SPHEN_POS, + MAC_HWF1R_SPHEN_LEN); + hw_feat->tso = FXGMAC_GET_REG_BITS(mac_hfr1, MAC_HWF1R_TSOEN_POS, + MAC_HWF1R_TSOEN_LEN); + hw_feat->dma_debug = FXGMAC_GET_REG_BITS( + mac_hfr1, MAC_HWF1R_DBGMEMA_POS, MAC_HWF1R_DBGMEMA_LEN); +#if (FXGMAC_RSS_FEATURE_ENABLED) + hw_feat->rss = 1; +#else + /* = FXGMAC_GET_REG_BITS(mac_hfr1, + * MAC_HWF1R_RSSEN_POS, + * MAC_HWF1R_RSSEN_LEN); + */ + hw_feat->rss = 0; +#endif + /* FXGMAC_GET_REG_BITS(mac_hfr1, + * MAC_HWF1R_NUMTC_POS, + * MAC_HWF1R_NUMTC_LEN); + */ + hw_feat->tc_cnt = 3; + hw_feat->avsel = FXGMAC_GET_REG_BITS(mac_hfr1, MAC_HWF1R_AVSEL_POS, + MAC_HWF1R_AVSEL_LEN); + hw_feat->ravsel = FXGMAC_GET_REG_BITS(mac_hfr1, MAC_HWF1R_RAVSEL_POS, + MAC_HWF1R_RAVSEL_LEN); + hw_feat->hash_table_size = FXGMAC_GET_REG_BITS( + mac_hfr1, MAC_HWF1R_HASHTBLSZ_POS, MAC_HWF1R_HASHTBLSZ_LEN); + hw_feat->l3l4_filter_num = FXGMAC_GET_REG_BITS( + mac_hfr1, MAC_HWF1R_L3L4FNUM_POS, MAC_HWF1R_L3L4FNUM_LEN); + + + /* Hardware feature register 2 + * FXGMAC_GET_REG_BITS(mac_hfr2, + * MAC_HWF2R_RXQCNT_POS, + * MAC_HWF2R_RXQCNT_LEN) + */ + hw_feat->rx_q_cnt = 3; + hw_feat->tx_q_cnt = FXGMAC_GET_REG_BITS(mac_hfr2, MAC_HWF2R_TXQCNT_POS, + MAC_HWF2R_TXQCNT_LEN); + hw_feat->rx_ch_cnt = FXGMAC_GET_REG_BITS( + mac_hfr2, MAC_HWF2R_RXCHCNT_POS, MAC_HWF2R_RXCHCNT_LEN); + hw_feat->tx_ch_cnt = FXGMAC_GET_REG_BITS( + mac_hfr2, MAC_HWF2R_TXCHCNT_POS, MAC_HWF2R_TXCHCNT_LEN); + hw_feat->pps_out_num = FXGMAC_GET_REG_BITS( + mac_hfr2, MAC_HWF2R_PPSOUTNUM_POS, MAC_HWF2R_PPSOUTNUM_LEN); + hw_feat->aux_snap_num = FXGMAC_GET_REG_BITS( + mac_hfr2, MAC_HWF2R_AUXSNAPNUM_POS, MAC_HWF2R_AUXSNAPNUM_LEN); + + /* 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; + } + + /* Translate the address width setting into actual number */ + switch (hw_feat->dma_width) { + case 0: + hw_feat->dma_width = 32; + break; + case 1: + hw_feat->dma_width = 40; + break; + case 2: + hw_feat->dma_width = 48; + break; + default: + hw_feat->dma_width = 32; + } + + /* 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++; + + hw_feat->hwfr3 = mac_hfr3; + DPRINTK("HWFR3: %u\n", mac_hfr3); +} + +void fxgmac_print_all_hw_features(struct fxgmac_pdata *pdata) +{ + char *str = NULL; + + DPRINTK("\n"); + DPRINTK("=====================================================\n"); + DPRINTK("\n"); + DPRINTK("HW support following features, ver=%#x\n", + pdata->hw_feat.version); + DPRINTK("\n"); + /* HW Feature Register0 */ + DPRINTK("VLAN Hash Filter Selected : %s\n", + pdata->hw_feat.vlhash ? "YES" : "NO"); + DPRINTK("SMA (MDIO) Interface : %s\n", + pdata->hw_feat.sma ? "YES" : "NO"); + DPRINTK("PMT Remote Wake-up Packet Enable : %s\n", + pdata->hw_feat.rwk ? "YES" : "NO"); + DPRINTK("PMT Magic Packet Enable : %s\n", + pdata->hw_feat.mgk ? "YES" : "NO"); + DPRINTK("RMON/MMC Module Enable : %s\n", + pdata->hw_feat.mmc ? "YES" : "NO"); + DPRINTK("ARP Offload Enabled : %s\n", + pdata->hw_feat.aoe ? "YES" : "NO"); + DPRINTK("IEEE 1588-2008 Timestamp Enabled : %s\n", + pdata->hw_feat.ts ? "YES" : "NO"); + DPRINTK("Energy Efficient Ethernet Enabled : %s\n", + pdata->hw_feat.eee ? "YES" : "NO"); + DPRINTK("Transmit Checksum Offload Enabled : %s\n", + pdata->hw_feat.tx_coe ? "YES" : "NO"); + DPRINTK("Receive Checksum Offload Enabled : %s\n", + pdata->hw_feat.rx_coe ? "YES" : "NO"); + DPRINTK("Additional MAC Addresses 1-31 Selected : %s\n", + pdata->hw_feat.addn_mac ? "YES" : "NO"); + + switch (pdata->hw_feat.ts_src) { + case 0: + str = "RESERVED"; + break; + case 1: + str = "INTERNAL"; + break; + case 2: + str = "EXTERNAL"; + break; + case 3: + str = "BOTH"; + break; + } + DPRINTK("Timestamp System Time Source : %s\n", str); + + DPRINTK("Source Address or VLAN Insertion Enable : %s\n", + pdata->hw_feat.sa_vlan_ins ? "YES" : "NO"); + + /* HW Feature Register1 */ + switch (pdata->hw_feat.rx_fifo_size) { + case 0: + str = "128 bytes"; + break; + case 1: + str = "256 bytes"; + break; + case 2: + str = "512 bytes"; + break; + case 3: + str = "1 KBytes"; + break; + case 4: + str = "2 KBytes"; + break; + case 5: + str = "4 KBytes"; + break; + case 6: + str = "8 KBytes"; + break; + case 7: + str = "16 KBytes"; + break; + case 8: + str = "32 kBytes"; + break; + case 9: + str = "64 KBytes"; + break; + case 10: + str = "128 KBytes"; + break; + case 11: + str = "256 KBytes"; + break; + default: + str = "RESERVED"; + } + DPRINTK("MTL Receive FIFO Size : %s\n", str); + + switch (pdata->hw_feat.tx_fifo_size) { + case 0: + str = "128 bytes"; + break; + case 1: + str = "256 bytes"; + break; + case 2: + str = "512 bytes"; + break; + case 3: + str = "1 KBytes"; + break; + case 4: + str = "2 KBytes"; + break; + case 5: + str = "4 KBytes"; + break; + case 6: + str = "8 KBytes"; + break; + case 7: + str = "16 KBytes"; + break; + case 8: + str = "32 kBytes"; + break; + case 9: + str = "64 KBytes"; + break; + case 10: + str = "128 KBytes"; + break; + case 11: + str = "256 KBytes"; + break; + default: + str = "RESERVED"; + } + DPRINTK("MTL Transmit FIFO Size : %s\n", str); + + DPRINTK("IEEE 1588 High Word Register Enable : %s\n", + pdata->hw_feat.adv_ts_hi ? "YES" : "NO"); + DPRINTK("Address width : %u\n", + pdata->hw_feat.dma_width); + DPRINTK("DCB Feature Enable : %s\n", + pdata->hw_feat.dcb ? "YES" : "NO"); + DPRINTK("Split Header Feature Enable : %s\n", + pdata->hw_feat.sph ? "YES" : "NO"); + DPRINTK("TCP Segmentation Offload Enable : %s\n", + pdata->hw_feat.tso ? "YES" : "NO"); + DPRINTK("DMA Debug Registers Enabled : %s\n", + pdata->hw_feat.dma_debug ? "YES" : "NO"); + DPRINTK("RSS Feature Enabled : %s\n", + pdata->hw_feat.rss ? "YES" : "NO"); + DPRINTK("*TODO*Number of Traffic classes : %u\n", + (pdata->hw_feat.tc_cnt)); + DPRINTK("AV Feature Enabled : %s\n", + pdata->hw_feat.avsel ? "YES" : "NO"); + DPRINTK("Rx Side Only AV Feature Enabled : %s\n", + (pdata->hw_feat.ravsel ? "YES" : "NO")); + DPRINTK("Hash Table Size : %u\n", + pdata->hw_feat.hash_table_size); + DPRINTK("Total number of L3 or L4 Filters : %u\n", + pdata->hw_feat.l3l4_filter_num); + + /* HW Feature Register2 */ + DPRINTK("Number of MTL Receive Queues : %u\n", + pdata->hw_feat.rx_q_cnt); + DPRINTK("Number of MTL Transmit Queues : %u\n", + pdata->hw_feat.tx_q_cnt); + DPRINTK("Number of DMA Receive Channels : %u\n", + pdata->hw_feat.rx_ch_cnt); + DPRINTK("Number of DMA Transmit Channels : %u\n", + pdata->hw_feat.tx_ch_cnt); + + switch (pdata->hw_feat.pps_out_num) { + case 0: + str = "No PPS output"; + break; + case 1: + str = "1 PPS output"; + break; + case 2: + str = "2 PPS output"; + break; + case 3: + str = "3 PPS output"; + break; + case 4: + str = "4 PPS output"; + break; + default: + str = "RESERVED"; + } + DPRINTK("Number of PPS Outputs : %s\n", str); + + switch (pdata->hw_feat.aux_snap_num) { + case 0: + str = "No auxiliary input"; + break; + case 1: + str = "1 auxiliary input"; + break; + case 2: + str = "2 auxiliary input"; + break; + case 3: + str = "3 auxiliary input"; + break; + case 4: + str = "4 auxiliary input"; + break; + default: + str = "RESERVED"; + } + DPRINTK("Number of Auxiliary Snapshot Inputs : %s", str); + + DPRINTK("\n"); + DPRINTK("=====================================================\n"); + DPRINTK("\n"); +} diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-debugfs.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-debugfs.c new file mode 100644 index 0000000000000..4596d91b6e282 --- /dev/null +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-debugfs.c @@ -0,0 +1,787 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021 Motorcomm Corporation. */ + +#include "fuxi-gmac.h" +#include "fuxi-gmac-reg.h" +#ifdef HAVE_FXGMAC_DEBUG_FS +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TEST_MAC_HEAD 14 +#define TEST_TCP_HEAD_LEN_OFFSET 12 +#define TEST_TCP_OFFLOAD_LEN_OFFSET 48 +#define TEST_TCP_FIX_HEAD_LEN 24 +#define TEST_TCP_MSS_OFFSET 56 + +#define DF_MAX_NIC_NUM 16 + +#ifdef HAVE_FXGMAC_DEBUG_FS + +/** + * fxgmac_dbg_netdev_ops_read - read for netdev_ops datum + * @filp: the opened file + * @buffer: where to write the data for the user to read + * @count: the size of the user's buffer + * @ppos: file position offset + **/ +static ssize_t fxgmac_dbg_netdev_ops_read(struct file *filp, + char __user *buffer, size_t count, + loff_t *ppos) +{ + struct fxgmac_pdata *pdata = filp->private_data; + char *buf; + int len; + + /* don't allow partial reads */ + if (*ppos != 0) + return 0; + + buf = kasprintf(GFP_KERNEL, "%s: %s\n", pdata->netdev->name, + pdata->expansion.fxgmac_dbg_netdev_ops_buf); + 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; +} + +/** + * fxgmac_dbg_netdev_ops_write - write into netdev_ops datum + * @filp: the opened file + * @buffer: where to find the user's data + * @count: the length of the user's data + * @ppos: file position offset + **/ +static ssize_t fxgmac_dbg_netdev_ops_write(struct file *filp, + const char __user *buffer, + size_t count, loff_t *ppos) +{ + struct fxgmac_pdata *pdata = filp->private_data; + int len; + + /* don't allow partial writes */ + if (*ppos != 0) + return 0; + if (count >= sizeof(pdata->expansion.fxgmac_dbg_netdev_ops_buf)) + return -ENOSPC; + + len = simple_write_to_buffer( + pdata->expansion.fxgmac_dbg_netdev_ops_buf, + sizeof(pdata->expansion.fxgmac_dbg_netdev_ops_buf) - 1, ppos, + buffer, count); + if (len < 0) + return len; + + pdata->expansion.fxgmac_dbg_netdev_ops_buf[len] = '\0'; + + if (strncmp(pdata->expansion.fxgmac_dbg_netdev_ops_buf, "tx_timeout", + 10) == 0) { + DPRINTK("tx_timeout called\n"); + } else { + FXGMAC_PR("Unknown command: %s\n", + pdata->expansion.fxgmac_dbg_netdev_ops_buf); + FXGMAC_PR("Available commands:\n"); + FXGMAC_PR(" tx_timeout\n"); + } + return count; +} +#endif + +static void fxgmac_dbg_tx_pkt(struct fxgmac_pdata *pdata, u8 *pcmd_data) +{ + unsigned int pktLen = 0; + struct sk_buff *skb; + pfxgmac_test_packet pPkt; + u8 *pTx_data = NULL; + u8 *pSkb_data = NULL; + u32 offload_len = 0; + u8 ipHeadLen, tcpHeadLen, headTotalLen; + static u32 lastGsoSize = 806; /* initial default value */ + + /* get fxgmac_test_packet */ + pPkt = (pfxgmac_test_packet)(pcmd_data + sizeof(struct ext_ioctl_data)); + pktLen = pPkt->length; + + /* get pkt data */ + pTx_data = (u8 *)pPkt + sizeof(fxgmac_test_packet); + + /* alloc sk_buff */ + skb = alloc_skb(pktLen, GFP_ATOMIC); + if (!skb) { + DPRINTK("alloc skb fail\n"); + return; + } + + /* copy data to skb */ + pSkb_data = skb_put(skb, pktLen); + memset(pSkb_data, 0, pktLen); + memcpy(pSkb_data, pTx_data, pktLen); + + /* set skb parameters */ + skb->dev = pdata->netdev; + skb->pkt_type = PACKET_OUTGOING; + skb->protocol = ntohs(ETH_P_IP); + skb->no_fcs = 1; + skb->ip_summed = CHECKSUM_PARTIAL; + if (skb->len > 1514) { + /* TSO packet */ + /* set tso test flag */ + pdata->expansion.fxgmac_test_tso_flag = true; + + /* get protocol head length */ + ipHeadLen = (pSkb_data[TEST_MAC_HEAD] & 0xF) * 4; + tcpHeadLen = (pSkb_data[TEST_MAC_HEAD + ipHeadLen + + TEST_TCP_HEAD_LEN_OFFSET] >> + 4 & + 0xF) * + 4; + headTotalLen = TEST_MAC_HEAD + ipHeadLen + tcpHeadLen; + offload_len = (pSkb_data[TEST_TCP_OFFLOAD_LEN_OFFSET] << 8 | + pSkb_data[TEST_TCP_OFFLOAD_LEN_OFFSET + 1]) & + 0xFFFF; + /* set tso skb parameters */ + skb->transport_header = ipHeadLen + TEST_MAC_HEAD; + skb->network_header = TEST_MAC_HEAD; + skb->inner_network_header = TEST_MAC_HEAD; + skb->mac_len = TEST_MAC_HEAD; + + /* set skb_shinfo parameters */ + if (tcpHeadLen > TEST_TCP_FIX_HEAD_LEN) { + skb_shinfo(skb)->gso_size = + (pSkb_data[TEST_TCP_MSS_OFFSET] << 8 | + pSkb_data[TEST_TCP_MSS_OFFSET + 1]) & + 0xFFFF; + } else { + skb_shinfo(skb)->gso_size = 0; + } + if (skb_shinfo(skb)->gso_size != 0) { + lastGsoSize = skb_shinfo(skb)->gso_size; + } else { + skb_shinfo(skb)->gso_size = lastGsoSize; + } + /* get segment size */ + if (offload_len % skb_shinfo(skb)->gso_size == 0) { + skb_shinfo(skb)->gso_segs = + offload_len / skb_shinfo(skb)->gso_size; + pdata->expansion.fxgmac_test_last_tso_len = + skb_shinfo(skb)->gso_size + headTotalLen; + } else { + skb_shinfo(skb)->gso_segs = + offload_len / skb_shinfo(skb)->gso_size + 1; + pdata->expansion.fxgmac_test_last_tso_len = + offload_len % skb_shinfo(skb)->gso_size + + headTotalLen; + } + pdata->expansion.fxgmac_test_tso_seg_num = + skb_shinfo(skb)->gso_segs; + + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; + skb_shinfo(skb)->frag_list = NULL; + skb->csum_start = skb_headroom(skb) + TEST_MAC_HEAD + ipHeadLen; + skb->csum_offset = skb->len - TEST_MAC_HEAD - ipHeadLen; + + pdata->expansion.fxgmac_test_packet_len = + skb_shinfo(skb)->gso_size + headTotalLen; + } else { + /* set non-TSO packet parameters */ + pdata->expansion.fxgmac_test_packet_len = skb->len; + } + + /* send data */ + if (dev_queue_xmit(skb) != NET_XMIT_SUCCESS) { + DPRINTK("xmit data fail \n"); + } +} + +static void fxgmac_dbg_rx_pkt(struct fxgmac_pdata *pdata, u8 *pcmd_data) +{ + unsigned int totalLen = 0; + struct sk_buff *rx_skb; + struct ext_ioctl_data *pcmd; + fxgmac_test_packet pkt; + void *addr = 0; + u8 *rx_data = (u8 *)kzalloc(FXGMAC_MAX_DBG_RX_DATA, GFP_KERNEL); + if (!rx_data) + return; + + /* initial dest data region */ + pcmd = (struct ext_ioctl_data *)pcmd_data; + addr = pcmd->cmd_buf.buf; + while (pdata->expansion.fxgmac_test_skb_arr_in_index != + pdata->expansion.fxgmac_test_skb_arr_out_index) { + /* get received skb data */ + rx_skb = + pdata->expansion.fxgmac_test_skb_array + [pdata->expansion.fxgmac_test_skb_arr_out_index]; + + if (rx_skb->len + sizeof(fxgmac_test_packet) + totalLen < + 64000) { + pkt.length = rx_skb->len; + pkt.type = 0x80; + pkt.buf[0].offset = + totalLen + sizeof(fxgmac_test_packet); + pkt.buf[0].length = rx_skb->len; + + /* get data from skb */ + memcpy(rx_data, rx_skb->data, rx_skb->len); + + /* update next pointer */ + if ((pdata->expansion.fxgmac_test_skb_arr_out_index + + 1) % FXGMAC_MAX_DBG_TEST_PKT == + pdata->expansion.fxgmac_test_skb_arr_in_index) { + pkt.next = NULL; + } else { + pkt.next = + (pfxgmac_test_packet)(addr + totalLen + + sizeof(fxgmac_test_packet) + + pkt.length); + } + + /* copy data to user space */ + if (copy_to_user((void *)(addr + totalLen), + (void *)(&pkt), + sizeof(fxgmac_test_packet))) { + DPRINTK("cppy pkt data to user fail..."); + } + if (copy_to_user((void *)(addr + totalLen + + sizeof(fxgmac_test_packet)), + (void *)rx_data, rx_skb->len)) { + DPRINTK("cppy data to user fail..."); + } + + /* update total length */ + totalLen += (sizeof(fxgmac_test_packet) + rx_skb->len); + + /* free skb */ + kfree_skb(rx_skb); + pdata->expansion.fxgmac_test_skb_array + [pdata->expansion.fxgmac_test_skb_arr_out_index] = + NULL; + + /* update gCurSkbOutIndex */ + pdata->expansion.fxgmac_test_skb_arr_out_index = + (pdata->expansion.fxgmac_test_skb_arr_out_index + + 1) % + FXGMAC_MAX_DBG_TEST_PKT; + } else { + DPRINTK("receive data more receive buffer... \n"); + break; + } + } + + if (rx_data) + kfree(rx_data); +} + +/* Based on the current application scenario, we only use CMD_DATA for data. + * if you use other struct, you should recalculate in_total_size + */ +long fxgmac_dbg_netdev_ops_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + bool ret = true; + int regval = 0; + struct fxgmac_pdata *pdata = file->private_data; + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + FXGMAC_PDATA_OF_PLATFORM *ex = &pdata->expansion; + CMD_DATA ex_data; + struct ext_ioctl_data pcmd; + u8 *data = NULL; + u8 *buf = NULL; + int in_total_size, in_data_size, out_total_size; + int ioctl_cmd_size = sizeof(struct ext_ioctl_data); + u8 mac[ETH_ALEN] = { 0 }; + struct sk_buff *tmpskb; + + if (!arg) { + DPRINTK("[%s] command arg is %lx !\n", __func__, arg); + goto err; + } + + /* check device type */ + if (_IOC_TYPE(cmd) != IOC_MAGIC) { + DPRINTK("[%s] command type [%c] error!\n", __func__, + _IOC_TYPE(cmd)); + goto err; + } + + /* check command number*/ + if (_IOC_NR(cmd) > IOC_MAXNR) { + DPRINTK("[%s] command numer [%d] exceeded!\n", __func__, + _IOC_NR(cmd)); + goto err; + } + + if (copy_from_user(&pcmd, (void *)arg, ioctl_cmd_size)) { + DPRINTK("copy data from user fail... \n"); + goto err; + } + + in_total_size = pcmd.cmd_buf.size_in; + in_data_size = in_total_size - ioctl_cmd_size; + out_total_size = pcmd.cmd_buf.size_out; + + buf = (u8 *)kzalloc(in_total_size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + if (copy_from_user(buf, (void *)arg, in_total_size)) { + DPRINTK("copy data from user fail... \n"); + goto err; + } + data = buf + ioctl_cmd_size; + + if (arg != 0) { + switch (pcmd.cmd_type) { + /* ioctl diag begin */ + case FUXI_DFS_IOCTL_DIAG_BEGIN: + DPRINTK("Debugfs received diag begin command.\n"); + if (netif_running(pdata->netdev)) { + fxgmac_restart_dev(pdata); + } + + /* release last loopback test abnormal exit buffer */ + while (ex->fxgmac_test_skb_arr_in_index != + ex->fxgmac_test_skb_arr_out_index) { + tmpskb = + ex->fxgmac_test_skb_array + [ex->fxgmac_test_skb_arr_out_index]; + if (tmpskb) { + kfree_skb(tmpskb); + ex->fxgmac_test_skb_array + [ex->fxgmac_test_skb_arr_out_index] = + NULL; + } + + ex->fxgmac_test_skb_arr_out_index = + (ex->fxgmac_test_skb_arr_out_index + + 1) % + FXGMAC_MAX_DBG_TEST_PKT; + } + + /* init loopback test parameters */ + ex->fxgmac_test_skb_arr_in_index = 0; + ex->fxgmac_test_skb_arr_out_index = 0; + ex->fxgmac_test_tso_flag = false; + ex->fxgmac_test_tso_seg_num = 0; + ex->fxgmac_test_last_tso_len = 0; + ex->fxgmac_test_packet_len = 0; + break; + + /* ioctl diag end */ + case FUXI_DFS_IOCTL_DIAG_END: + DPRINTK("Debugfs received diag end command.\n"); + if (netif_running(pdata->netdev)) { + fxgmac_restart_dev(pdata); + } + break; + + /* ioctl diag tx pkt */ + case FUXI_DFS_IOCTL_DIAG_TX_PKT: + fxgmac_dbg_tx_pkt(pdata, buf); + break; + + /* ioctl diag rx pkt */ + case FUXI_DFS_IOCTL_DIAG_RX_PKT: + fxgmac_dbg_rx_pkt(pdata, buf); + break; + + /* ioctl device reset */ + case FUXI_DFS_IOCTL_DEVICE_RESET: + DPRINTK("Debugfs received device reset command.\n"); + if (netif_running(pdata->netdev)) { + fxgmac_restart_dev(pdata); + } + break; + + case FXGMAC_EFUSE_LED_TEST: + DPRINTK("Debugfs received device led test command.\n"); + memcpy(&pdata->led, data, sizeof(struct led_setting)); + fxgmac_restart_dev(pdata); + break; + + case FXGMAC_EFUSE_UPDATE_LED_CFG: + DPRINTK("Debugfs received device led update command.\n"); + memcpy(&pdata->ledconfig, data, + sizeof(struct led_setting)); + ret = hw_ops->write_led_config(pdata); + hw_ops->read_led_config(pdata); + hw_ops->led_under_active(pdata); + break; + + case FXGMAC_EFUSE_WRITE_LED: + memcpy(&ex_data, data, sizeof(CMD_DATA)); + DPRINTK("FXGMAC_EFUSE_WRITE_LED, val = 0x%x\n", + ex_data.val0); + ret = hw_ops->write_led(pdata, ex_data.val0); + break; + + case FXGMAC_EFUSE_WRITE_OOB: + DPRINTK("FXGMAC_EFUSE_WRITE_OOB.\n"); + ret = hw_ops->write_oob(pdata); + break; + + case FXGMAC_EFUSE_READ_REGIONABC: + memcpy(&ex_data, data, sizeof(CMD_DATA)); + ret = hw_ops->read_efuse_data(pdata, ex_data.val0, + &ex_data.val1); + DPRINTK("FXGMAC_EFUSE_READ_REGIONABC, address = 0x%x, val = 0x%x\n", + ex_data.val0, ex_data.val1); + if (ret) { + memcpy(data, &ex_data, sizeof(CMD_DATA)); + out_total_size = + ioctl_cmd_size + sizeof(CMD_DATA); + if (copy_to_user((void *)arg, (void *)buf, + out_total_size)) + goto err; + } + break; + + case FXGMAC_EFUSE_WRITE_PATCH_REG: + memcpy(&ex_data, data, sizeof(CMD_DATA)); + DPRINTK("FXGMAC_EFUSE_WRITE_PATCH_REG, address = 0x%x, val = 0x%x\n", + ex_data.val0, ex_data.val1); + ret = hw_ops->write_patch_to_efuse(pdata, ex_data.val0, + ex_data.val1); + break; + + case FXGMAC_EFUSE_READ_PATCH_REG: + memcpy(&ex_data, data, sizeof(CMD_DATA)); + ret = hw_ops->read_patch_from_efuse(pdata, ex_data.val0, + &ex_data.val1); + DPRINTK("FXGMAC_EFUSE_READ_PATCH_REG, address = 0x%x, val = 0x%x\n", + ex_data.val0, ex_data.val1); + if (ret) { + memcpy(data, &ex_data, sizeof(CMD_DATA)); + out_total_size = + ioctl_cmd_size + sizeof(CMD_DATA); + if (copy_to_user((void *)arg, (void *)buf, + out_total_size)) + goto err; + } + break; + + case FXGMAC_EFUSE_WRITE_PATCH_PER_INDEX: + memcpy(&ex_data, data, sizeof(CMD_DATA)); + ret = hw_ops->write_patch_to_efuse_per_index( + pdata, ex_data.val0, ex_data.val1, + ex_data.val2); + DPRINTK("FXGMAC_EFUSE_WRITE_PATCH_PER_INDEX, index = %d, address = 0x%x, val = 0x%x\n", + ex_data.val0, ex_data.val1, ex_data.val2); + break; + + case FXGMAC_EFUSE_READ_PATCH_PER_INDEX: + memcpy(&ex_data, data, sizeof(CMD_DATA)); + ret = hw_ops->read_patch_from_efuse_per_index( + pdata, ex_data.val0, &ex_data.val1, + &ex_data.val2); + DPRINTK("FXGMAC_EFUSE_READ_PATCH_PER_INDEX, address = 0x%x, val = 0x%x\n", + ex_data.val1, ex_data.val2); + if (ret) { + memcpy(data, &ex_data, sizeof(CMD_DATA)); + out_total_size = + ioctl_cmd_size + sizeof(CMD_DATA); + if (copy_to_user((void *)arg, (void *)buf, + out_total_size)) + goto err; + } + break; + + case FXGMAC_EFUSE_LOAD: + DPRINTK("FXGMAC_EFUSE_LOAD.\n"); + ret = hw_ops->efuse_load(pdata); + break; + + case FXGMAC_GET_MAC_DATA: + ret = hw_ops->read_mac_subsys_from_efuse(pdata, mac, + NULL, NULL); + if (ret) { + memcpy(data, mac, ETH_ALEN); + out_total_size = ioctl_cmd_size + ETH_ALEN; + if (copy_to_user((void *)arg, (void *)buf, + out_total_size)) + goto err; + } + break; + + case FXGMAC_SET_MAC_DATA: + if (in_data_size != ETH_ALEN) + goto err; + memcpy(mac, data, ETH_ALEN); + ret = hw_ops->write_mac_subsys_to_efuse(pdata, mac, + NULL, NULL); + if (ret) { + eth_hw_addr_set(pdata->netdev, mac); + memcpy(pdata->mac_addr, mac, ETH_ALEN); + hw_ops->set_mac_address(pdata, mac); + hw_ops->set_mac_hash(pdata); + } + break; + + case FXGMAC_GET_SUBSYS_ID: + memcpy(&ex_data, data, sizeof(CMD_DATA)); + ret = hw_ops->read_mac_subsys_from_efuse( + pdata, NULL, &ex_data.val0, NULL); + if (ret) { + ex_data.val1 = 0xFFFF; /* invalid value */ + memcpy(data, &ex_data, sizeof(CMD_DATA)); + out_total_size = + ioctl_cmd_size + sizeof(CMD_DATA); + if (copy_to_user((void *)arg, (void *)buf, + out_total_size)) + goto err; + } + break; + + case FXGMAC_SET_SUBSYS_ID: + memcpy(&ex_data, data, sizeof(CMD_DATA)); + ret = hw_ops->write_mac_subsys_to_efuse( + pdata, NULL, &ex_data.val0, NULL); + break; + + case FXGMAC_GET_GMAC_REG: + memcpy(&ex_data, data, sizeof(CMD_DATA)); + ex_data.val1 = hw_ops->get_gmac_register( + pdata, (u8 *)(pdata->mac_regs + ex_data.val0)); + memcpy(data, &ex_data, sizeof(CMD_DATA)); + out_total_size = ioctl_cmd_size + sizeof(CMD_DATA); + if (copy_to_user((void *)arg, (void *)buf, + out_total_size)) + goto err; + break; + + case FXGMAC_SET_GMAC_REG: + memcpy(&ex_data, data, sizeof(CMD_DATA)); + regval = hw_ops->set_gmac_register( + pdata, (u8 *)(pdata->mac_regs + ex_data.val0), + ex_data.val1); + ret = (regval == 0 ? true : false); + break; + + case FXGMAC_GET_PHY_REG: + memcpy(&ex_data, data, sizeof(CMD_DATA)); + regval = hw_ops->read_ephy_reg(pdata, ex_data.val0, + &ex_data.val1); + if (regval != -1) { + memcpy(data, &ex_data, sizeof(CMD_DATA)); + out_total_size = + ioctl_cmd_size + sizeof(CMD_DATA); + if (copy_to_user((void *)arg, (void *)buf, + out_total_size)) + goto err; + } + ret = (regval == -1 ? false : true); + break; + + case FXGMAC_SET_PHY_REG: + memcpy(&ex_data, data, sizeof(CMD_DATA)); + regval = hw_ops->write_ephy_reg(pdata, ex_data.val0, + ex_data.val1); + ret = (regval == 0 ? true : false); + break; + + case FXGMAC_GET_PCIE_LOCATION: + ex_data.val0 = pdata->pdev->bus->number; + ex_data.val1 = PCI_SLOT(pdata->pdev->devfn); + ex_data.val2 = PCI_FUNC(pdata->pdev->devfn); + memcpy(data, &ex_data, sizeof(CMD_DATA)); + out_total_size = ioctl_cmd_size + sizeof(CMD_DATA); + if (copy_to_user((void *)arg, (void *)buf, + out_total_size)) + goto err; + break; + + case FXGMAC_GET_GSO_SIZE: + ex_data.val0 = pdata->netdev->gso_max_size; + memcpy(data, &ex_data, sizeof(CMD_DATA)); + out_total_size = ioctl_cmd_size + sizeof(CMD_DATA); + if (copy_to_user((void *)arg, (void *)buf, + out_total_size)) + goto err; + break; + + case FXGMAC_SET_GSO_SIZE: + memcpy(&ex_data, data, sizeof(CMD_DATA)); + pdata->netdev->gso_max_size = ex_data.val0; + break; + + case FXGMAC_SET_RX_MODERATION: + memcpy(&ex_data, data, sizeof(CMD_DATA)); + regval = readreg(pdata->pAdapter, + pdata->base_mem + INT_MOD); + regval = FXGMAC_SET_REG_BITS(regval, INT_MOD_RX_POS, + INT_MOD_RX_LEN, + ex_data.val0); + writereg(pdata->pAdapter, regval, + pdata->base_mem + INT_MOD); + break; + + case FXGMAC_SET_TX_MODERATION: + memcpy(&ex_data, data, sizeof(CMD_DATA)); + regval = readreg(pdata->pAdapter, + pdata->base_mem + INT_MOD); + regval = FXGMAC_SET_REG_BITS(regval, INT_MOD_TX_POS, + INT_MOD_TX_LEN, + ex_data.val0); + writereg(pdata->pAdapter, regval, + pdata->base_mem + INT_MOD); + break; + + case FXGMAC_GET_TXRX_MODERATION: + regval = readreg(pdata->pAdapter, + pdata->base_mem + INT_MOD); + ex_data.val0 = FXGMAC_GET_REG_BITS( + regval, INT_MOD_RX_POS, INT_MOD_RX_LEN); + ex_data.val1 = FXGMAC_GET_REG_BITS( + regval, INT_MOD_TX_POS, INT_MOD_TX_LEN); + memcpy(data, &ex_data, sizeof(CMD_DATA)); + out_total_size = ioctl_cmd_size + sizeof(CMD_DATA); + if (copy_to_user((void *)arg, (void *)buf, + out_total_size)) + goto err; + break; + + default: + DPRINTK("Debugfs received invalid command: %x.\n", + pcmd.cmd_type); + ret = false; + break; + } + } + + if (buf) + kfree(buf); + return ret ? FXGMAC_SUCCESS : FXGMAC_FAIL; + +err: + if (buf) + kfree(buf); + return FXGMAC_FAIL; +} + +#ifdef HAVE_FXGMAC_DEBUG_FS + +static struct file_operations fxgmac_dbg_netdev_ops_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = fxgmac_dbg_netdev_ops_read, + .write = fxgmac_dbg_netdev_ops_write, + .unlocked_ioctl = fxgmac_dbg_netdev_ops_ioctl, +}; + +/** + * fxgmac_dbg_adapter_init - setup the debugfs directory for the adapter + * @adapter: the adapter that is starting up + **/ +void fxgmac_dbg_adapter_init(struct fxgmac_pdata *pdata) +{ + const char *name = pdata->drv_name; + struct dentry *pfile; + + pdata->expansion.dbg_adapter = + debugfs_create_dir(name, pdata->expansion.fxgmac_dbg_root); + if (pdata->expansion.dbg_adapter) { + pfile = debugfs_create_file("netdev_ops", 0600, + pdata->expansion.dbg_adapter, pdata, + &fxgmac_dbg_netdev_ops_fops); + if (!pfile) + DPRINTK("debugfs netdev_ops for %s failed\n", name); + } else { + DPRINTK("debugfs entry for %s failed\n", name); + } +} + +/** + * fxgmac_dbg_adapter_exit - clear out the adapter's debugfs entries + * @adapter: board private structure + **/ +void fxgmac_dbg_adapter_exit(struct fxgmac_pdata *pdata) +{ + if (pdata->expansion.dbg_adapter) + debugfs_remove_recursive(pdata->expansion.dbg_adapter); + pdata->expansion.dbg_adapter = NULL; +} + +/** + * fxgmac_dbg_init - start up debugfs for the driver + **/ +void fxgmac_dbg_init(struct fxgmac_pdata *pdata) +{ + unsigned int i; + char num[3]; + const char debug_path[] = "/sys/kernel/debug/"; + const char file_prefix[] = "fuxi_"; + char file_path[50]; + char file_name[8]; + + /* init file_path */ + memset(file_path, '\0', sizeof(file_path)); + memcpy(file_path, debug_path, sizeof(debug_path)); + + for (i = 0; i < DF_MAX_NIC_NUM; i++) { + /* init num and filename */ + memset(num, '\0', sizeof(num)); + memset(file_name, '\0', sizeof(file_name)); + + /* int to string */ + sprintf(num, "%d", i); + + /* file name */ + memcpy(file_name, file_prefix, sizeof(file_prefix)); + memcpy(file_name + strlen(file_prefix), num, sizeof(num)); + + /* file path */ + memcpy(file_path + sizeof(debug_path) - 1, file_name, + sizeof(file_name)); + + /* whether file exist */ + pdata->expansion.fxgmac_dbg_root = + debugfs_lookup(file_name, NULL); + if (!pdata->expansion.fxgmac_dbg_root) { + /* create file */ + pdata->expansion.fxgmac_dbg_root = + debugfs_create_dir(file_name, NULL); + if (IS_ERR(pdata->expansion.fxgmac_dbg_root)) + DPRINTK("fxgmac init of debugfs failed\n"); + + break; + } + } +} + +/** + * fxgmac_dbg_exit - clean out the driver's debugfs entries + **/ +void fxgmac_dbg_exit(struct fxgmac_pdata *pdata) +{ + if (pdata->expansion.fxgmac_dbg_root) + debugfs_remove_recursive(pdata->expansion.fxgmac_dbg_root); +} + +#endif /* HAVE_XLGMAC_DEBUG_FS */ diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-desc.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-desc.c new file mode 100644 index 0000000000000..969d84eb44e2a --- /dev/null +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-desc.c @@ -0,0 +1,601 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021 Motorcomm Corporation. */ + +#include "fuxi-gmac.h" +#include "fuxi-gmac-reg.h" + +static void fxgmac_unmap_desc_data(struct fxgmac_pdata *pdata, + struct fxgmac_desc_data *desc_data) +{ + if (desc_data->skb_dma) { + if (desc_data->mapped_as_page) { + dma_unmap_page(pdata->dev, desc_data->skb_dma, + desc_data->skb_dma_len, DMA_TO_DEVICE); + } else { + dma_unmap_single(pdata->dev, desc_data->skb_dma, + desc_data->skb_dma_len, DMA_TO_DEVICE); + } + desc_data->skb_dma = 0; + desc_data->skb_dma_len = 0; + } + + if (desc_data->rx.buf.dma_base) { + dma_unmap_single(pdata->dev, desc_data->rx.buf.dma_base, + pdata->rx_buf_size, DMA_FROM_DEVICE); + desc_data->rx.buf.dma_base = 0; + } + + if (desc_data->skb) { + dev_kfree_skb_any(desc_data->skb); + desc_data->skb = NULL; + } + + memset(&desc_data->tx, 0, sizeof(desc_data->tx)); + memset(&desc_data->rx, 0, sizeof(desc_data->rx)); + + desc_data->mapped_as_page = 0; + + if (desc_data->state_saved) { + desc_data->state_saved = 0; + desc_data->state.skb = NULL; + desc_data->state.len = 0; + desc_data->state.error = 0; + } +} + +static void fxgmac_free_ring(struct fxgmac_pdata *pdata, + struct fxgmac_ring *ring) +{ + struct fxgmac_desc_data *desc_data; + unsigned int i; + + if (!ring) + return; + + if (ring->desc_data_head) { + for (i = 0; i < ring->dma_desc_count; i++) { + desc_data = FXGMAC_GET_DESC_DATA(ring, i); + fxgmac_unmap_desc_data(pdata, desc_data); + } + + kfree(ring->desc_data_head); + ring->desc_data_head = NULL; + } + + if (ring->dma_desc_head) { + dma_free_coherent( + pdata->dev, + (sizeof(struct fxgmac_dma_desc) * ring->dma_desc_count), + ring->dma_desc_head, ring->dma_desc_head_addr); + ring->dma_desc_head = NULL; + } +} + +static int fxgmac_init_ring(struct fxgmac_pdata *pdata, + struct fxgmac_ring *ring, + unsigned int dma_desc_count) +{ + if (!ring) + return 0; + /* Descriptors */ + ring->dma_desc_count = dma_desc_count; + ring->dma_desc_head = dma_alloc_coherent( + pdata->dev, (sizeof(struct fxgmac_dma_desc) * dma_desc_count), + &ring->dma_desc_head_addr, GFP_KERNEL); + if (!ring->dma_desc_head) + return -ENOMEM; + + /* Array of descriptor data */ + ring->desc_data_head = kcalloc( + dma_desc_count, sizeof(struct fxgmac_desc_data), GFP_KERNEL); + if (!ring->desc_data_head) + return -ENOMEM; + + netif_dbg( + pdata, drv, pdata->netdev, + "dma_desc_head=%p, dma_desc_head_addr=%pad, desc_data_head=%p\n", + ring->dma_desc_head, &ring->dma_desc_head_addr, + ring->desc_data_head); + + return 0; +} + +static void fxgmac_free_rings(struct fxgmac_pdata *pdata) +{ + struct fxgmac_channel *channel; + unsigned int i; + + if (!pdata->channel_head) + return; + + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + fxgmac_free_ring(pdata, channel->tx_ring); + fxgmac_free_ring(pdata, channel->rx_ring); + } +} + +static int fxgmac_alloc_rings(struct fxgmac_pdata *pdata) +{ + struct fxgmac_channel *channel; + unsigned int i; + int ret; + + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + netif_dbg(pdata, drv, pdata->netdev, "%s - Tx ring:\n", + channel->name); + + if (i < pdata->tx_ring_count) { + ret = fxgmac_init_ring(pdata, channel->tx_ring, + pdata->tx_desc_count); + + if (ret) { + netdev_alert(pdata->netdev, + "error initializing Tx ring"); + goto err_init_ring; + } + } + + netif_dbg(pdata, drv, pdata->netdev, "%s - Rx ring:\n", + channel->name); + + ret = fxgmac_init_ring(pdata, channel->rx_ring, + pdata->rx_desc_count); + if (ret) { + netdev_alert(pdata->netdev, + "error initializing Rx ring\n"); + goto err_init_ring; + } + if (netif_msg_drv(pdata)) + DPRINTK("fxgmac_alloc_ring..ch=%u, tx_desc_cnt=%u, rx_desc_cnt=%u\n", + i, pdata->tx_desc_count, pdata->rx_desc_count); + } + if (netif_msg_drv(pdata)) + DPRINTK("alloc_rings callout ok\n"); + + return 0; + +err_init_ring: + fxgmac_free_rings(pdata); + + DPRINTK("alloc_rings callout err,%d\n", ret); + return ret; +} + +static void fxgmac_free_channels(struct fxgmac_pdata *pdata) +{ + if (!pdata->channel_head) + return; + if (netif_msg_drv(pdata)) + DPRINTK("free_channels, tx_ring=%p\n", + pdata->channel_head->tx_ring); + kfree(pdata->channel_head->tx_ring); + pdata->channel_head->tx_ring = NULL; + + if (netif_msg_drv(pdata)) + DPRINTK("free_channels, rx_ring=%p\n", + pdata->channel_head->rx_ring); + kfree(pdata->channel_head->rx_ring); + pdata->channel_head->rx_ring = NULL; + + if (netif_msg_drv(pdata)) + DPRINTK("free_channels, channel=%p\n", pdata->channel_head); + kfree(pdata->channel_head); + + pdata->channel_head = NULL; +} + +static int fxgmac_alloc_channels(struct fxgmac_pdata *pdata) +{ + struct fxgmac_channel *channel_head, *channel; + struct fxgmac_ring *tx_ring, *rx_ring; + int ret = -ENOMEM; + unsigned int i; + +#ifdef CONFIG_PCI_MSI + u32 msix = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_MSIX_POS, + FXGMAC_FLAG_MSIX_LEN); +#endif + + channel_head = kcalloc(pdata->channel_count, + sizeof(struct fxgmac_channel), GFP_KERNEL); + if (netif_msg_drv(pdata)) + DPRINTK("alloc_channels, channel_head=%p, size=%d*%ld\n", + channel_head, pdata->channel_count, + sizeof(struct fxgmac_channel)); + + if (!channel_head) + return ret; + + netif_dbg(pdata, drv, pdata->netdev, "channel_head=%p\n", channel_head); + + tx_ring = kcalloc(pdata->tx_ring_count, sizeof(struct fxgmac_ring), + GFP_KERNEL); + if (!tx_ring) + goto err_tx_ring; + + if (netif_msg_drv(pdata)) + DPRINTK("alloc_channels, tx_ring=%p, size=%d*%ld\n", tx_ring, + pdata->tx_ring_count, sizeof(struct fxgmac_ring)); + rx_ring = kcalloc(pdata->rx_ring_count, sizeof(struct fxgmac_ring), + GFP_KERNEL); + if (!rx_ring) + goto err_rx_ring; + + if (netif_msg_drv(pdata)) + DPRINTK("alloc_channels, rx_ring=%p, size=%d*%ld\n", rx_ring, + pdata->rx_ring_count, sizeof(struct fxgmac_ring)); + + for (i = 0, channel = channel_head; i < pdata->channel_count; + i++, channel++) { + snprintf(channel->name, sizeof(channel->name), "channel-%u", i); + channel->pdata = pdata; + channel->queue_index = i; + channel->dma_regs = + pdata->mac_regs + DMA_CH_BASE + (DMA_CH_INC * i); + + if (pdata->per_channel_irq) { + /* Get the per DMA interrupt */ +#ifdef CONFIG_PCI_MSI + if (msix) { + pdata->channel_irq[i] = + pdata->expansion.msix_entries[i].vector; + if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { + pdata->channel_irq + [FXGMAC_MAX_DMA_CHANNELS] = + pdata->expansion + .msix_entries + [FXGMAC_MAX_DMA_CHANNELS] + .vector; + + if (pdata->channel_irq + [FXGMAC_MAX_DMA_CHANNELS] < + 0) { + netdev_err( + pdata->netdev, + "get_irq %u for tx failed\n", + i + 1); + goto err_irq; + } + + channel->expansion.dma_irq_tx = + pdata->channel_irq + [FXGMAC_MAX_DMA_CHANNELS]; + DPRINTK("fxgmac_alloc_channels, for MSIx, channel %d dma_irq_tx=%u\n", + i, + channel->expansion.dma_irq_tx); + } + } +#endif + ret = pdata->channel_irq[i]; + if (ret < 0) { + netdev_err(pdata->netdev, "get_irq %u failed\n", + i + 1); + goto err_irq; + } + channel->dma_irq = ret; + DPRINTK("fxgmac_alloc_channels, for MSIx, channel %d dma_irq=%u\n", + i, channel->dma_irq); + } + + if (i < pdata->tx_ring_count) + channel->tx_ring = tx_ring++; + + if (i < pdata->rx_ring_count) + channel->rx_ring = rx_ring++; + + netif_dbg(pdata, drv, pdata->netdev, + "%s: dma_regs=%p, tx_ring=%p, rx_ring=%p\n", + channel->name, channel->dma_regs, channel->tx_ring, + channel->rx_ring); + } + + pdata->channel_head = channel_head; + + if (netif_msg_drv(pdata)) + DPRINTK("alloc_channels callout ok\n"); + return 0; + +err_irq: + kfree(rx_ring); + +err_rx_ring: + kfree(tx_ring); + +err_tx_ring: + kfree(channel_head); + + DPRINTK("fxgmac alloc_channels callout err,%d\n", ret); + return ret; +} + +static void fxgmac_free_channels_and_rings(struct fxgmac_pdata *pdata) +{ + fxgmac_free_rings(pdata); + + fxgmac_free_channels(pdata); +} + +static int fxgmac_alloc_channels_and_rings(struct fxgmac_pdata *pdata) +{ + int ret; + + ret = fxgmac_alloc_channels(pdata); + if (ret) + goto err_alloc; + + ret = fxgmac_alloc_rings(pdata); + if (ret) + goto err_alloc; + + return 0; + +err_alloc: + fxgmac_free_channels_and_rings(pdata); + + return ret; +} + +static int fxgmac_map_rx_buffer(struct fxgmac_pdata *pdata, + struct fxgmac_ring *ring, + struct fxgmac_desc_data *desc_data) +{ + struct sk_buff *skb; + skb = __netdev_alloc_skb_ip_align(pdata->netdev, pdata->rx_buf_size, + GFP_ATOMIC); + if (!skb) { + netdev_err(pdata->netdev, "%s: Rx init fails; skb is NULL\n", + __func__); + return -ENOMEM; + } + + desc_data->skb = skb; + desc_data->rx.buf.dma_base = dma_map_single( + pdata->dev, skb->data, pdata->rx_buf_size, DMA_FROM_DEVICE); + if (dma_mapping_error(pdata->dev, desc_data->rx.buf.dma_base)) { + netdev_err(pdata->netdev, "%s: DMA mapping error\n", __func__); + dev_kfree_skb_any(skb); + return -EINVAL; + } + + return 0; +} + +static void fxgmac_tx_desc_init(struct fxgmac_pdata *pdata) +{ + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + struct fxgmac_desc_data *desc_data; + struct fxgmac_dma_desc *dma_desc; + struct fxgmac_channel *channel; + struct fxgmac_ring *ring; + dma_addr_t dma_desc_addr; + unsigned int i, j; + + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + ring = channel->tx_ring; + if (!ring) + break; + + /* reset the tx timer status. 20220104 */ + channel->tx_timer_active = 0; + + dma_desc = ring->dma_desc_head; + dma_desc_addr = ring->dma_desc_head_addr; + + for (j = 0; j < ring->dma_desc_count; j++) { + desc_data = FXGMAC_GET_DESC_DATA(ring, j); + + desc_data->dma_desc = dma_desc; + desc_data->dma_desc_addr = dma_desc_addr; + + dma_desc++; + dma_desc_addr += sizeof(struct fxgmac_dma_desc); + } + + ring->cur = 0; + ring->dirty = 0; + memset(&ring->tx, 0, sizeof(ring->tx)); + + hw_ops->tx_desc_init(channel); + } +} + +static void fxgmac_rx_desc_init(struct fxgmac_pdata *pdata) +{ + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + struct fxgmac_desc_data *desc_data; + struct fxgmac_dma_desc *dma_desc; + struct fxgmac_channel *channel; + struct fxgmac_ring *ring; + dma_addr_t dma_desc_addr; + unsigned int i, j; + + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + ring = channel->rx_ring; + if (!ring) + break; + + dma_desc = ring->dma_desc_head; + dma_desc_addr = ring->dma_desc_head_addr; + + for (j = 0; j < ring->dma_desc_count; j++) { + desc_data = FXGMAC_GET_DESC_DATA(ring, j); + + desc_data->dma_desc = dma_desc; + desc_data->dma_desc_addr = dma_desc_addr; + + if (fxgmac_map_rx_buffer(pdata, ring, desc_data)) + break; + + dma_desc++; + dma_desc_addr += sizeof(struct fxgmac_dma_desc); + } + + ring->cur = 0; + ring->dirty = 0; + + hw_ops->rx_desc_init(channel); + } +} + +static int fxgmac_map_tx_skb(struct fxgmac_channel *channel, + struct sk_buff *skb) +{ + struct fxgmac_pdata *pdata = channel->pdata; + struct fxgmac_ring *ring = channel->tx_ring; + unsigned int start_index, cur_index; + struct fxgmac_desc_data *desc_data; + unsigned int offset, datalen, len; + struct fxgmac_pkt_info *pkt_info; + skb_frag_t *frag; + unsigned int tso, vlan; + dma_addr_t skb_dma; + unsigned int i; + + offset = 0; + start_index = ring->cur; + cur_index = ring->cur; + + pkt_info = &ring->pkt_info; + pkt_info->desc_count = 0; + pkt_info->length = 0; + + tso = FXGMAC_GET_REG_BITS(pkt_info->attributes, + TX_PACKET_ATTRIBUTES_TSO_ENABLE_POS, + TX_PACKET_ATTRIBUTES_TSO_ENABLE_LEN); + vlan = FXGMAC_GET_REG_BITS(pkt_info->attributes, + TX_PACKET_ATTRIBUTES_VLAN_CTAG_POS, + TX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN); + + /* Save space for a context descriptor if needed */ + if ((tso && (pkt_info->mss != ring->tx.cur_mss)) || + (vlan && (pkt_info->vlan_ctag != ring->tx.cur_vlan_ctag))) { + cur_index = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); + } + desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); + + if (tso) { + /* Map the TSO header */ + skb_dma = dma_map_single(pdata->dev, skb->data, + pkt_info->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; + } + desc_data->skb_dma = skb_dma; + desc_data->skb_dma_len = pkt_info->header_len; + netif_dbg(pdata, tx_queued, pdata->netdev, + "skb header: index=%u, dma=%pad, len=%u\n", cur_index, + &skb_dma, pkt_info->header_len); + + offset = pkt_info->header_len; + + pkt_info->length += pkt_info->header_len; + + cur_index = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); + desc_data = FXGMAC_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, FXGMAC_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; + } + desc_data->skb_dma = skb_dma; + desc_data->skb_dma_len = len; + netif_dbg(pdata, tx_queued, pdata->netdev, + "skb data: index=%u, dma=%pad, len=%u\n", cur_index, + &skb_dma, len); + + datalen -= len; + offset += len; + + pkt_info->length += len; + + cur_index = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); + desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); + } + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + netif_dbg(pdata, tx_queued, pdata->netdev, "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, + FXGMAC_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; + } + desc_data->skb_dma = skb_dma; + desc_data->skb_dma_len = len; + desc_data->mapped_as_page = 1; + netif_dbg(pdata, tx_queued, pdata->netdev, + "skb frag: index=%u, dma=%pad, len=%u\n", + cur_index, &skb_dma, len); + + datalen -= len; + offset += len; + + pkt_info->length += len; + + cur_index = FXGMAC_GET_ENTRY(cur_index, + ring->dma_desc_count); + desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); + } + } + + /* Save the skb address in the last entry. We always have some data + * that has been mapped so desc_data is always advanced past the last + * piece of mapped data - use the entry pointed to by cur_index - 1. + */ + desc_data = FXGMAC_GET_DESC_DATA( + ring, (cur_index - 1) & (ring->dma_desc_count - 1)); + desc_data->skb = skb; + + /* Save the number of descriptor entries used */ + if (start_index <= cur_index) + pkt_info->desc_count = cur_index - start_index; + else + pkt_info->desc_count = + ring->dma_desc_count - start_index + cur_index; + + return pkt_info->desc_count; + +err_out: + while (start_index < cur_index) { + desc_data = FXGMAC_GET_DESC_DATA(ring, start_index); + start_index = + FXGMAC_GET_ENTRY(start_index, ring->dma_desc_count); + fxgmac_unmap_desc_data(pdata, desc_data); + } + + return 0; +} + +void fxgmac_init_desc_ops(struct fxgmac_desc_ops *desc_ops) +{ + desc_ops->alloc_channles_and_rings = fxgmac_alloc_channels_and_rings; + desc_ops->free_channels_and_rings = fxgmac_free_channels_and_rings; + desc_ops->map_tx_skb = fxgmac_map_tx_skb; + desc_ops->map_rx_buffer = fxgmac_map_rx_buffer; + desc_ops->unmap_desc_data = fxgmac_unmap_desc_data; + desc_ops->tx_desc_init = fxgmac_tx_desc_init; + desc_ops->rx_desc_init = fxgmac_rx_desc_init; +} diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-ethtool.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-ethtool.c new file mode 100644 index 0000000000000..05aa42f90ad83 --- /dev/null +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-ethtool.c @@ -0,0 +1,1114 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021 Motorcomm Corporation. */ + +#include +#include +#include + +#include "fuxi-gmac.h" +#include "fuxi-gmac-reg.h" + +struct fxgmac_stats_desc { + char stat_string[ETH_GSTRING_LEN]; + int stat_offset; +}; + +#define FXGMAC_STAT(str, var) \ + { \ + str, offsetof(struct fxgmac_pdata, stats.var), \ + } + +static const struct fxgmac_stats_desc fxgmac_gstring_stats[] = { + /* MMC TX counters */ + FXGMAC_STAT("tx_bytes", txoctetcount_gb), + FXGMAC_STAT("tx_bytes_good", txoctetcount_g), + FXGMAC_STAT("tx_packets", txframecount_gb), + FXGMAC_STAT("tx_packets_good", txframecount_g), + FXGMAC_STAT("tx_unicast_packets", txunicastframes_gb), + FXGMAC_STAT("tx_broadcast_packets", txbroadcastframes_gb), + FXGMAC_STAT("tx_broadcast_packets_good", txbroadcastframes_g), + FXGMAC_STAT("tx_multicast_packets", txmulticastframes_gb), + FXGMAC_STAT("tx_multicast_packets_good", txmulticastframes_g), + FXGMAC_STAT("tx_vlan_packets_good", txvlanframes_g), + FXGMAC_STAT("tx_64_byte_packets", tx64octets_gb), + FXGMAC_STAT("tx_65_to_127_byte_packets", tx65to127octets_gb), + FXGMAC_STAT("tx_128_to_255_byte_packets", tx128to255octets_gb), + FXGMAC_STAT("tx_256_to_511_byte_packets", tx256to511octets_gb), + FXGMAC_STAT("tx_512_to_1023_byte_packets", tx512to1023octets_gb), + FXGMAC_STAT("tx_1024_to_max_byte_packets", tx1024tomaxoctets_gb), + FXGMAC_STAT("tx_underflow_errors", txunderflowerror), + FXGMAC_STAT("tx_pause_frames", txpauseframes), + FXGMAC_STAT("tx_single_collision", txsinglecollision_g), + FXGMAC_STAT("tx_multiple_collision", txmultiplecollision_g), + FXGMAC_STAT("tx_deferred_frames", txdeferredframes), + FXGMAC_STAT("tx_late_collision_frames", txlatecollisionframes), + FXGMAC_STAT("tx_excessive_collision_frames", + txexcessivecollisionframes), + FXGMAC_STAT("tx_carrier_error_frames", txcarriererrorframes), + FXGMAC_STAT("tx_excessive_deferral_error", txexcessivedeferralerror), + FXGMAC_STAT("tx_oversize_frames_good", txoversize_g), + + /* MMC RX counters */ + FXGMAC_STAT("rx_bytes", rxoctetcount_gb), + FXGMAC_STAT("rx_bytes_good", rxoctetcount_g), + FXGMAC_STAT("rx_packets", rxframecount_gb), + FXGMAC_STAT("rx_unicast_packets_good", rxunicastframes_g), + FXGMAC_STAT("rx_broadcast_packets_good", rxbroadcastframes_g), + FXGMAC_STAT("rx_multicast_packets_good", rxmulticastframes_g), + FXGMAC_STAT("rx_vlan_packets_mac", rxvlanframes_gb), + FXGMAC_STAT("rx_64_byte_packets", rx64octets_gb), + FXGMAC_STAT("rx_65_to_127_byte_packets", rx65to127octets_gb), + FXGMAC_STAT("rx_128_to_255_byte_packets", rx128to255octets_gb), + FXGMAC_STAT("rx_256_to_511_byte_packets", rx256to511octets_gb), + FXGMAC_STAT("rx_512_to_1023_byte_packets", rx512to1023octets_gb), + FXGMAC_STAT("rx_1024_to_max_byte_packets", rx1024tomaxoctets_gb), + FXGMAC_STAT("rx_undersize_packets_good", rxundersize_g), + FXGMAC_STAT("rx_oversize_packets_good", rxoversize_g), + FXGMAC_STAT("rx_crc_errors", rxcrcerror), + FXGMAC_STAT("rx_align_error", rxalignerror), + FXGMAC_STAT("rx_crc_errors_small_packets", rxrunterror), + FXGMAC_STAT("rx_crc_errors_giant_packets", rxjabbererror), + FXGMAC_STAT("rx_length_errors", rxlengtherror), + FXGMAC_STAT("rx_out_of_range_errors", rxoutofrangetype), + FXGMAC_STAT("rx_fifo_overflow_errors", rxfifooverflow), + FXGMAC_STAT("rx_watchdog_errors", rxwatchdogerror), + FXGMAC_STAT("rx_pause_frames", rxpauseframes), + FXGMAC_STAT("rx_receive_error_frames", rxreceiveerrorframe), + FXGMAC_STAT("rx_control_frames_good", rxcontrolframe_g), + + /* Extra counters */ + FXGMAC_STAT("tx_tso_packets", tx_tso_packets), + FXGMAC_STAT("rx_split_header_packets", rx_split_header_packets), + FXGMAC_STAT("tx_process_stopped", tx_process_stopped), + FXGMAC_STAT("rx_process_stopped", rx_process_stopped), + FXGMAC_STAT("tx_buffer_unavailable", tx_buffer_unavailable), + FXGMAC_STAT("rx_buffer_unavailable", rx_buffer_unavailable), + FXGMAC_STAT("fatal_bus_error", fatal_bus_error), + FXGMAC_STAT("tx_vlan_packets_net", tx_vlan_packets), + FXGMAC_STAT("rx_vlan_packets_net", rx_vlan_packets), + FXGMAC_STAT("napi_poll_isr", napi_poll_isr), + FXGMAC_STAT("napi_poll_txtimer", napi_poll_txtimer), + FXGMAC_STAT("alive_cnt_txtimer", cnt_alive_txtimer), + + FXGMAC_STAT("ephy_poll_timer", ephy_poll_timer_cnt), + FXGMAC_STAT("mgmt_int_isr", mgmt_int_isr), +}; + +#define FXGMAC_STATS_COUNT ARRAY_SIZE(fxgmac_gstring_stats) + +static void fxgmac_ethtool_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *drvinfo) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + u32 ver = pdata->hw_feat.version; + u32 sver, devid, userver; + + strscpy(drvinfo->driver, pdata->drv_name, sizeof(drvinfo->driver)); + strscpy(drvinfo->version, pdata->drv_ver, sizeof(drvinfo->version)); + strscpy(drvinfo->bus_info, dev_name(pdata->dev), + sizeof(drvinfo->bus_info)); + /* + * D|DEVID: Indicates the Device family + * U|USERVER: User-defined Version + */ + sver = FXGMAC_GET_REG_BITS(ver, MAC_VR_SVER_POS, MAC_VR_SVER_LEN); + devid = FXGMAC_GET_REG_BITS(ver, MAC_VR_DEVID_POS, MAC_VR_DEVID_LEN); + userver = FXGMAC_GET_REG_BITS(ver, MAC_VR_USERVER_POS, + MAC_VR_USERVER_LEN); + /*DPRINTK("xlgma: No userver (%x) here, sver (%x) should be 0x51\n", userver, sver);*/ + snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), + "S.D.U: %x.%x.%x", sver, devid, userver); +} + +static u32 fxgmac_ethtool_get_msglevel(struct net_device *netdev) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + + return pdata->msg_enable; +} + +static void fxgmac_ethtool_set_msglevel(struct net_device *netdev, u32 msglevel) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + + DPRINTK("fxmac, set msglvl from %08x to %08x\n", pdata->msg_enable, + msglevel); + pdata->msg_enable = msglevel; +} + +static void fxgmac_ethtool_get_channels(struct net_device *netdev, + struct ethtool_channels *channel) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); +#if (FXGMAC_RSS_FEATURE_ENABLED) + /* report maximum channels */ + channel->max_combined = FXGMAC_MAX_DMA_CHANNELS; + channel->max_other = 0; + channel->other_count = 0; + + /* record RSS queues */ + channel->combined_count = FXGMAC_MAX_DMA_CHANNELS; + + /* nothing else to report if RSS is disabled */ + if (channel->combined_count == 1) + return; + DPRINTK("fxmac rss, get channels max=(combined %d, other %d), count(combined %d, other %d)\n", + channel->max_combined, channel->max_other, + channel->combined_count, channel->other_count); +#endif + + channel->max_rx = FXGMAC_MAX_DMA_CHANNELS; + channel->max_tx = FXGMAC_MAX_DMA_CHANNELS; + channel->rx_count = pdata->rx_q_count; + channel->tx_count = pdata->tx_q_count; + DPRINTK("fxmac, get channels max=(rx %d, tx %d), count(%d,%d)\n", + channel->max_rx, channel->max_tx, channel->rx_count, + channel->tx_count); +} + +static int +fxgmac_ethtool_get_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec, + struct kernel_ethtool_coalesce *kernel_coal, + struct netlink_ext_ack *extack) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + + memset(ec, 0, sizeof(struct ethtool_coalesce)); + ec->rx_coalesce_usecs = pdata->rx_usecs; + ec->tx_coalesce_usecs = pdata->tx_usecs; + /*If we need to assign values to other members, + * we need to modify the supported_coalesce_params of fxgmac_ethtool_ops synchronously + */ + DPRINTK("fxmac, get coalesce\n"); + return 0; +} + +static int +fxgmac_ethtool_set_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec, + struct kernel_ethtool_coalesce *kernel_coal, + struct netlink_ext_ack *extack) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + unsigned int rx_frames, rx_riwt, rx_usecs; + unsigned int tx_frames; + + /* Check for not supported parameters */ + if ((ec->rx_coalesce_usecs_irq) || (ec->rx_max_coalesced_frames_irq) || + (ec->tx_coalesce_usecs_high) || (ec->tx_max_coalesced_frames_irq) || + (ec->tx_coalesce_usecs_irq) || (ec->stats_block_coalesce_usecs) || + (ec->pkt_rate_low) || (ec->use_adaptive_rx_coalesce) || + (ec->use_adaptive_tx_coalesce) || + (ec->rx_max_coalesced_frames_low) || (ec->rx_coalesce_usecs_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_max_coalesced_frames_high) || (ec->rate_sample_interval)) + return -EOPNOTSUPP; + + rx_usecs = ec->rx_coalesce_usecs; + rx_riwt = hw_ops->usec_to_riwt(pdata, rx_usecs); + rx_frames = ec->rx_max_coalesced_frames; + tx_frames = ec->tx_max_coalesced_frames; + + if ((rx_riwt > FXGMAC_MAX_DMA_RIWT) || + (rx_riwt < FXGMAC_MIN_DMA_RIWT) || + (rx_frames > pdata->rx_desc_count)) + return -EINVAL; + + if (tx_frames > pdata->tx_desc_count) + return -EINVAL; + + pdata->rx_riwt = rx_riwt; + pdata->rx_usecs = rx_usecs; + pdata->rx_frames = rx_frames; + hw_ops->config_rx_coalesce(pdata); + + pdata->tx_frames = tx_frames; + hw_ops->config_tx_coalesce(pdata); + + pdata->tx_usecs = ec->tx_coalesce_usecs; + hw_ops->set_interrupt_moderation(pdata); + + DPRINTK("fxmac, set coalesce\n"); + return 0; +} + +#if (FXGMAC_RSS_FEATURE_ENABLED) +static u32 fxgmac_get_rxfh_key_size(struct net_device *netdev) +{ + return FXGMAC_RSS_HASH_KEY_SIZE; +} + +static u32 fxgmac_rss_indir_size(struct net_device *netdev) +{ + return FXGMAC_RSS_MAX_TABLE_SIZE; +} + +static void fxgmac_get_reta(struct fxgmac_pdata *pdata, u32 *indir) +{ + int i, reta_size = FXGMAC_RSS_MAX_TABLE_SIZE; + u16 rss_m; +#ifdef FXGMAC_ONE_CHANNLE + rss_m = FXGMAC_MAX_DMA_CHANNELS; +#else + rss_m = FXGMAC_MAX_DMA_CHANNELS - + 1; /* mask for index of channel, 0-3 */ +#endif + + for (i = 0; i < reta_size; i++) + indir[i] = pdata->rss_table[i] & rss_m; +} + +static int fxgmac_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, + u8 *hfunc) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + + /* ETH_RSS_HASH_TOP __ETH_RSS_HASH(TOP) + * ETH_RSS_HASH_XOR __ETH_RSS_HASH(XOR) + * ETH_RSS_HASH_CRC32 __ETH_RSS_HASH(CRC32) + */ + if (hfunc) { + *hfunc = ETH_RSS_HASH_TOP; + DPRINTK("fxmac, get_rxfh for hash function\n"); + } + + if (indir) { + fxgmac_get_reta(pdata, indir); + DPRINTK("fxmac, get_rxfh for indirection tab\n"); + } + + if (key) { + memcpy(key, pdata->rss_key, fxgmac_get_rxfh_key_size(netdev)); + DPRINTK("fxmac, get_rxfh for hash key\n"); + } + + return 0; +} + +static int fxgmac_set_rxfh(struct net_device *netdev, const u32 *indir, + const u8 *key, const u8 hfunc) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + int i; + u32 reta_entries = fxgmac_rss_indir_size(netdev); + int max_queues = FXGMAC_MAX_DMA_CHANNELS; + + DPRINTK("fxmac, set_rxfh callin, indir=%lx, key=%lx, func=%02x\n", + (unsigned long)indir, (unsigned long)key, hfunc); + + if (hfunc) + return -EINVAL; + + /* Fill out the redirection table */ + if (indir) { +#if FXGMAC_MSIX_CH0RXDIS_EN + max_queues = max_queues; + reta_entries = reta_entries; + i = i; + DPRINTK("fxmac, set_rxfh, change of indirect talbe is not supported.\n"); + return -EINVAL; +#else + /* double check user input. */ + for (i = 0; i < reta_entries; i++) + if (indir[i] >= max_queues) + return -EINVAL; + + for (i = 0; i < reta_entries; i++) + pdata->rss_table[i] = indir[i]; + + hw_ops->write_rss_lookup_table(pdata); +#endif + } + + /* Fill out the rss hash key */ + if (FXGMAC_RSS_HASH_KEY_LINUX && key) + hw_ops->set_rss_hash_key(pdata, key); + + return 0; +} + +static int fxgmac_get_rss_hash_opts(struct fxgmac_pdata *pdata, + struct ethtool_rxnfc *cmd) +{ + u32 reg_opt; + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + cmd->data = 0; + + reg_opt = hw_ops->get_rss_options(pdata); + DPRINTK("fxgmac_get_rss_hash_opts, hw=%02x, %02x\n", reg_opt, + pdata->rss_options); + + if (reg_opt != pdata->rss_options) { + DPRINTK("fxgmac_get_rss_hash_opts, warning, options are not consistent\n"); + } + + /* Report default options for RSS */ + switch (cmd->flow_type) { + case TCP_V4_FLOW: + case UDP_V4_FLOW: + if (((TCP_V4_FLOW == (cmd->flow_type)) && + (FXGMAC_GET_REG_BITS(pdata->rss_options, + MAC_RSSCR_TCP4TE_POS, + MAC_RSSCR_TCP4TE_LEN))) || + ((UDP_V4_FLOW == (cmd->flow_type)) && + (FXGMAC_GET_REG_BITS(pdata->rss_options, + MAC_RSSCR_UDP4TE_POS, + MAC_RSSCR_UDP4TE_LEN)))) { + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + } + fallthrough; + case SCTP_V4_FLOW: + case AH_ESP_V4_FLOW: + case AH_V4_FLOW: + case ESP_V4_FLOW: + case IPV4_FLOW: + if (((TCP_V4_FLOW == (cmd->flow_type)) && + (FXGMAC_GET_REG_BITS(pdata->rss_options, + MAC_RSSCR_TCP4TE_POS, + MAC_RSSCR_TCP4TE_LEN))) || + ((UDP_V4_FLOW == (cmd->flow_type)) && + (FXGMAC_GET_REG_BITS(pdata->rss_options, + MAC_RSSCR_UDP4TE_POS, + MAC_RSSCR_UDP4TE_LEN))) || + (FXGMAC_GET_REG_BITS(pdata->rss_options, + MAC_RSSCR_IP4TE_POS, + MAC_RSSCR_IP4TE_LEN))) { + cmd->data |= RXH_IP_SRC | RXH_IP_DST; + } + break; + case TCP_V6_FLOW: + case UDP_V6_FLOW: + if (((TCP_V6_FLOW == (cmd->flow_type)) && + (FXGMAC_GET_REG_BITS(pdata->rss_options, + MAC_RSSCR_TCP6TE_POS, + MAC_RSSCR_TCP6TE_LEN))) || + ((UDP_V6_FLOW == (cmd->flow_type)) && + (FXGMAC_GET_REG_BITS(pdata->rss_options, + MAC_RSSCR_UDP6TE_POS, + MAC_RSSCR_UDP6TE_LEN)))) { + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + } + fallthrough; + case SCTP_V6_FLOW: + case AH_ESP_V6_FLOW: + case AH_V6_FLOW: + case ESP_V6_FLOW: + case IPV6_FLOW: + if (((TCP_V6_FLOW == (cmd->flow_type)) && + (FXGMAC_GET_REG_BITS(pdata->rss_options, + MAC_RSSCR_TCP6TE_POS, + MAC_RSSCR_TCP6TE_LEN))) || + ((UDP_V6_FLOW == (cmd->flow_type)) && + (FXGMAC_GET_REG_BITS(pdata->rss_options, + MAC_RSSCR_UDP6TE_POS, + MAC_RSSCR_UDP6TE_LEN))) || + (FXGMAC_GET_REG_BITS(pdata->rss_options, + MAC_RSSCR_IP6TE_POS, + MAC_RSSCR_IP6TE_LEN))) { + cmd->data |= RXH_IP_SRC | RXH_IP_DST; + } + break; + default: + return -EINVAL; + } + + return 0; +} + +static int fxgmac_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, + u32 *rule_locs) +{ + struct fxgmac_pdata *pdata = netdev_priv(dev); + int ret = -EOPNOTSUPP; + + switch (cmd->cmd) { + case ETHTOOL_GRXRINGS: + cmd->data = pdata->rx_q_count; + ret = 0; + DPRINTK("fxmac, get_rxnfc for rx ring cnt\n"); + break; + case ETHTOOL_GRXCLSRLCNT: + cmd->rule_cnt = 0; + ret = 0; + DPRINTK("fxmac, get_rxnfc for classify rule cnt\n"); + break; + case ETHTOOL_GRXCLSRULE: + DPRINTK("fxmac, get_rxnfc for classify rules\n"); + ret = 0; /* ixgbe_get_ethtool_fdir_entry(adapter, cmd); */ + break; + case ETHTOOL_GRXCLSRLALL: + cmd->rule_cnt = 0; + ret = 0; + /*ret = ixgbe_get_ethtool_fdir_all(adapter, cmd, + (u32 *)rule_locs); + */ + DPRINTK("fxmac, get_rxnfc for classify both cnt and rules\n"); + break; + case ETHTOOL_GRXFH: + ret = fxgmac_get_rss_hash_opts(pdata, cmd); + DPRINTK("fxmac, get_rxnfc for hash options\n"); + break; + default: + break; + } + + return ret; +} + +#define UDP_RSS_FLAGS (BIT(MAC_RSSCR_UDP4TE_POS) | BIT(MAC_RSSCR_UDP6TE_POS)) +static int fxgmac_set_rss_hash_opt(struct fxgmac_pdata *pdata, + struct ethtool_rxnfc *nfc) +{ + u32 rssopt = 0; /* pdata->rss_options; */ + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + + DPRINTK("fxgmac_set_rss_hash_opt call in, nfc_data=%llx, cur opt=%x\n", + nfc->data, pdata->rss_options); + + /* For RSS, it does not support anything other than hashing + * to queues on src, dst IPs and L4 ports + */ + if (nfc->data & + ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3)) + return -EINVAL; + + switch (nfc->flow_type) { + case TCP_V4_FLOW: + case TCP_V6_FLOW: + /* default to TCP flow and do nothting */ + if (!(nfc->data & RXH_IP_SRC) || !(nfc->data & RXH_IP_DST) || + !(nfc->data & RXH_L4_B_0_1) || !(nfc->data & RXH_L4_B_2_3)) + return -EINVAL; + if (TCP_V4_FLOW == (nfc->flow_type)) { + rssopt = FXGMAC_SET_REG_BITS(rssopt, + MAC_RSSCR_IP4TE_POS, + MAC_RSSCR_IP4TE_LEN, 1); + rssopt = FXGMAC_SET_REG_BITS(rssopt, + MAC_RSSCR_TCP4TE_POS, + MAC_RSSCR_TCP4TE_LEN, 1); + } + + if (TCP_V6_FLOW == (nfc->flow_type)) { + rssopt = FXGMAC_SET_REG_BITS(rssopt, + MAC_RSSCR_IP6TE_POS, + MAC_RSSCR_IP6TE_LEN, 1); + rssopt = FXGMAC_SET_REG_BITS(rssopt, + MAC_RSSCR_TCP6TE_POS, + MAC_RSSCR_TCP6TE_LEN, 1); + } + break; + + case UDP_V4_FLOW: + if (!(nfc->data & RXH_IP_SRC) || !(nfc->data & RXH_IP_DST)) + return -EINVAL; + rssopt = FXGMAC_SET_REG_BITS(rssopt, MAC_RSSCR_IP4TE_POS, + MAC_RSSCR_IP4TE_LEN, 1); + switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + case 0: + break; + case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + rssopt = FXGMAC_SET_REG_BITS(rssopt, + MAC_RSSCR_UDP4TE_POS, + MAC_RSSCR_UDP4TE_LEN, 1); + break; + default: + return -EINVAL; + } + break; + case UDP_V6_FLOW: + if (!(nfc->data & RXH_IP_SRC) || !(nfc->data & RXH_IP_DST)) + return -EINVAL; + rssopt = FXGMAC_SET_REG_BITS(rssopt, MAC_RSSCR_IP6TE_POS, + MAC_RSSCR_IP6TE_LEN, 1); + + switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + case 0: + break; + case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + rssopt = FXGMAC_SET_REG_BITS(rssopt, + MAC_RSSCR_UDP6TE_POS, + MAC_RSSCR_UDP6TE_LEN, 1); + break; + default: + return -EINVAL; + } + break; + case AH_ESP_V4_FLOW: + case AH_V4_FLOW: + case ESP_V4_FLOW: + case SCTP_V4_FLOW: + case AH_ESP_V6_FLOW: + case AH_V6_FLOW: + case ESP_V6_FLOW: + case SCTP_V6_FLOW: + if (!(nfc->data & RXH_IP_SRC) || !(nfc->data & RXH_IP_DST) || + (nfc->data & RXH_L4_B_0_1) || (nfc->data & RXH_L4_B_2_3)) + return -EINVAL; + break; + default: + return -EINVAL; + } + + /* if options are changed, then update to hw */ + if (rssopt != pdata->rss_options) { + if ((rssopt & UDP_RSS_FLAGS) && + !(pdata->rss_options & UDP_RSS_FLAGS)) + DPRINTK("enabling UDP RSS: fragmented packets" + " may arrive out of order to the stack above\n"); + + DPRINTK("rss option changed from %x to %x\n", + pdata->rss_options, rssopt); + pdata->rss_options = rssopt; + hw_ops->set_rss_options(pdata); + } + + return 0; +} + +static int fxgmac_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) +{ + struct fxgmac_pdata *pdata = netdev_priv(dev); + + int ret = -EOPNOTSUPP; + + switch (cmd->cmd) { + case ETHTOOL_SRXCLSRLINS: + /* no support. rx classifier rule insert */ + DPRINTK("set_rxnfc for rx cls rule insert-n\\a\n"); + break; + case ETHTOOL_SRXCLSRLDEL: + /* no support. rx classifier rule delete */ + DPRINTK("set_rxnfc for rx cls rule del-n\\a\n"); + break; + case ETHTOOL_SRXFH: + DPRINTK("set_rxnfc for rx rss option\n"); + ret = fxgmac_set_rss_hash_opt(pdata, cmd); + break; + default: + break; + } + + return ret; +} +#endif /* FXGMAC_RSS_FEATURE_ENABLED */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)) +static void fxgmac_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring, + struct kernel_ethtool_ringparam *kernel_ring, + struct netlink_ext_ack *exact) + +#else +static void fxgmac_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +#endif +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + + DPRINTK("fxmac, get_ringparam callin\n"); + + ring->rx_max_pending = FXGMAC_RX_DESC_CNT; + ring->tx_max_pending = FXGMAC_TX_DESC_CNT; + ring->rx_mini_max_pending = 0; + ring->rx_jumbo_max_pending = 0; + ring->rx_pending = pdata->rx_desc_count; + ring->tx_pending = pdata->tx_desc_count; + ring->rx_mini_pending = 0; + ring->rx_jumbo_pending = 0; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)) +static int fxgmac_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring, + struct kernel_ethtool_ringparam *kernel_ring, + struct netlink_ext_ack *exact) + +#else +static int fxgmac_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +#endif +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_desc_ops *desc_ops = &pdata->desc_ops; + + DPRINTK("fxmac, set_ringparam callin\n"); + + pdata->tx_desc_count = ring->tx_pending; + pdata->rx_desc_count = ring->rx_pending; + + fxgmac_stop(pdata); + fxgmac_free_tx_data(pdata); + fxgmac_free_rx_data(pdata); + desc_ops->alloc_channles_and_rings(pdata); + fxgmac_start(pdata); + + return 0; +} + +#if FXGMAC_WOL_FEATURE_ENABLED +static void fxgmac_get_wol(struct net_device *netdev, + struct ethtool_wolinfo *wol) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + + /* for further feature implementation + * wol->supported = WAKE_PHY | WAKE_UCAST | WAKE_MCAST | + * WAKE_BCAST | WAKE_MAGIC; + */ + + wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC | + WAKE_ARP; +#if FXGMAC_WOL_UPON_EPHY_LINK + wol->supported |= WAKE_PHY; +#endif + + wol->wolopts = 0; + if (!(pdata->hw_feat.rwk) || + !device_can_wakeup(/*pci_dev_to_dev*/ (pdata->dev))) { + DPRINTK("fxgmac get_wol, pci does not support wakeup\n"); + return; + } + wol->wolopts = pdata->expansion.wol; + DPRINTK("fxmac, get_wol, 0x%x, 0x%x\n", wol->wolopts, + pdata->expansion.wol); +} + +static int fxgmac_set_wol(struct net_device *netdev, + struct ethtool_wolinfo *wol) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + int ret; + + /* currently, we do not support these options */ +#if FXGMAC_WOL_UPON_EPHY_LINK +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) + if (wol->wolopts & (WAKE_MAGICSECURE | WAKE_FILTER)) { +#else + if (wol->wolopts & WAKE_MAGICSECURE) { +#endif +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) + if (wol->wolopts & (WAKE_PHY | WAKE_MAGICSECURE | WAKE_FILTER)) { +#else + if (wol->wolopts & (WAKE_PHY | WAKE_MAGICSECURE)) { +#endif +#endif + DPRINTK("fxmac, set_wol, not supported wol options, 0x%x\n", + wol->wolopts); + return -EOPNOTSUPP; + } + + if (!(pdata->hw_feat.rwk)) { + DPRINTK("fxmac, set_wol, hw wol feature is n/a\n"); + ret = (wol->wolopts ? -EOPNOTSUPP : 0); + return ret; + } + + pdata->expansion.wol = 0; + if (wol->wolopts & WAKE_UCAST) + pdata->expansion.wol |= WAKE_UCAST; + + if (wol->wolopts & WAKE_MCAST) + pdata->expansion.wol |= WAKE_MCAST; + + if (wol->wolopts & WAKE_BCAST) + pdata->expansion.wol |= WAKE_BCAST; + + if (wol->wolopts & WAKE_MAGIC) + pdata->expansion.wol |= WAKE_MAGIC; + + if (wol->wolopts & WAKE_PHY) + pdata->expansion.wol |= WAKE_PHY; + + if (wol->wolopts & WAKE_ARP) + pdata->expansion.wol |= WAKE_ARP; + + hw_ops->set_pattern_data(pdata); + + hw_ops->config_wol(pdata, (!!(pdata->expansion.wol))); + + DPRINTK("fxmac, set_wol, opt=0x%x, 0x%x\n", wol->wolopts, + pdata->expansion.wol); + + return 0; +} +#endif /*FXGMAC_WOL_FEATURE_ENABLED*/ + +static int fxgmac_get_regs_len(struct net_device __always_unused *netdev) +{ + return FXGMAC_EPHY_REGS_LEN * sizeof(u32); +} + +static void fxgmac_get_regs(struct net_device *netdev, + struct ethtool_regs *regs, void *p) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + + u32 *regs_buff = p; + u8 i; + + memset(p, 0, FXGMAC_EPHY_REGS_LEN * sizeof(u32)); + for (i = REG_MII_BMCR; i < FXGMAC_EPHY_REGS_LEN; i++) { + hw_ops->read_ephy_reg(pdata, i, (unsigned int *)®s_buff[i]); + } + regs->version = regs_buff[REG_MII_PHYSID1] << 16 | + regs_buff[REG_MII_PHYSID2]; +} + +#if FXGMAC_PAUSE_FEATURE_ENABLED +static int fxgmac_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings *cmd) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + u32 duplex, regval, link_status; + u32 adv = 0xFFFFFFFF; + + regval = fxgmac_ephy_autoneg_ability_get(pdata, &adv); + if (regval) + return -ETIMEDOUT; + + ethtool_link_ksettings_zero_link_mode(cmd, supported); + ethtool_link_ksettings_zero_link_mode(cmd, advertising); + + /* set the supported link speeds */ + ethtool_link_ksettings_add_link_mode(cmd, supported, 1000baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, 100baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, 100baseT_Half); + ethtool_link_ksettings_add_link_mode(cmd, supported, 10baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, 10baseT_Half); + + /* Indicate pause support */ + ethtool_link_ksettings_add_link_mode(cmd, supported, Pause); + ethtool_link_ksettings_add_link_mode(cmd, supported, Asym_Pause); + ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause); + ethtool_link_ksettings_add_link_mode(cmd, advertising, Asym_Pause); + + ethtool_link_ksettings_add_link_mode(cmd, supported, MII); + cmd->base.port = PORT_MII; + + ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg); + hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, ®val); + regval = FXGMAC_GET_REG_BITS(regval, PHY_CR_AUTOENG_POS, + PHY_CR_AUTOENG_LEN); + if (regval) { + if (pdata->phy_autoeng) + ethtool_link_ksettings_add_link_mode(cmd, advertising, + Autoneg); + else + clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, + cmd->link_modes.advertising); + + if (adv & FXGMAC_ADVERTISE_10HALF) + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10baseT_Half); + if (adv & FXGMAC_ADVERTISE_10FULL) + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10baseT_Full); + if (adv & FXGMAC_ADVERTISE_100HALF) + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 100baseT_Half); + if (adv & FXGMAC_ADVERTISE_100FULL) + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 100baseT_Full); + if (adv & FXGMAC_ADVERTISE_1000FULL) + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 1000baseT_Full); + } else { + clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, + cmd->link_modes.advertising); + switch (pdata->phy_speed) { + case SPEED_1000M: + if (pdata->phy_duplex) + ethtool_link_ksettings_add_link_mode( + cmd, advertising, 1000baseT_Full); + else + ethtool_link_ksettings_add_link_mode( + cmd, advertising, 1000baseT_Half); + break; + case SPEED_100M: + if (pdata->phy_duplex) + ethtool_link_ksettings_add_link_mode( + cmd, advertising, 100baseT_Full); + else + ethtool_link_ksettings_add_link_mode( + cmd, advertising, 100baseT_Half); + break; + case SPEED_10M: + if (pdata->phy_duplex) + ethtool_link_ksettings_add_link_mode( + cmd, advertising, 10baseT_Full); + else + ethtool_link_ksettings_add_link_mode( + cmd, advertising, 10baseT_Half); + break; + default: + break; + } + } + cmd->base.autoneg = pdata->phy_autoeng ? regval : 0; + + hw_ops->read_ephy_reg(pdata, REG_MII_SPEC_STATUS, ®val); + link_status = regval & (BIT(FUXI_EPHY_LINK_STATUS_BIT)); + if (link_status) { + duplex = FXGMAC_GET_REG_BITS(regval, PHY_MII_SPEC_DUPLEX_POS, + PHY_MII_SPEC_DUPLEX_LEN); + cmd->base.duplex = duplex; + cmd->base.speed = pdata->phy_speed; + } else { + cmd->base.duplex = DUPLEX_UNKNOWN; + cmd->base.speed = SPEED_UNKNOWN; + } + + return 0; +} + +static int fxgmac_set_link_ksettings(struct net_device *netdev, + const struct ethtool_link_ksettings *cmd) +{ + u32 advertising, support, adv; + int ret; + struct fxphy_ag_adv; + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + + if (cmd->base.speed == SPEED_1000 && cmd->base.duplex == DUPLEX_HALF) + return -EINVAL; + + pdata->phy_autoeng = cmd->base.autoneg; + + ethtool_convert_link_mode_to_legacy_u32(&advertising, + cmd->link_modes.advertising); + ethtool_convert_link_mode_to_legacy_u32(&support, + cmd->link_modes.supported); + advertising &= support; + + if (pdata->phy_autoeng || + (!pdata->phy_autoeng && cmd->base.speed == SPEED_1000)) { + ret = hw_ops->read_ephy_reg(pdata, REG_MII_ADVERTISE, &adv); + if (ret < 0) + return -ETIMEDOUT; + adv &= ~REG_BIT_ADVERTISE_100_10_CAP; + adv |= ethtool_adv_to_mii_adv_t(advertising); + ret = hw_ops->write_ephy_reg(pdata, REG_MII_ADVERTISE, adv); + if (ret < 0) + return -ETIMEDOUT; + ret = hw_ops->read_ephy_reg(pdata, REG_MII_CTRL1000, &adv); + if (ret < 0) + return -ETIMEDOUT; + adv &= ~REG_BIT_ADVERTISE_1000_CAP; + adv |= ethtool_adv_to_mii_ctrl1000_t(advertising); + ret = hw_ops->write_ephy_reg(pdata, REG_MII_CTRL1000, adv); + if (ret < 0) + return -ETIMEDOUT; + + ret = hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, &adv); + if (ret < 0) + return -ETIMEDOUT; + adv = FXGMAC_SET_REG_BITS(adv, PHY_CR_AUTOENG_POS, + PHY_CR_AUTOENG_LEN, 1); + ret = hw_ops->write_ephy_reg(pdata, REG_MII_BMCR, adv); + if (ret < 0) + return -ETIMEDOUT; + + ret = hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, &adv); + if (ret < 0) + return -ETIMEDOUT; + adv = FXGMAC_SET_REG_BITS(adv, PHY_CR_RE_AUTOENG_POS, + PHY_CR_RE_AUTOENG_LEN, 1); + ret = hw_ops->write_ephy_reg(pdata, REG_MII_BMCR, adv); + if (ret < 0) + return -ETIMEDOUT; + } else { + pdata->phy_duplex = cmd->base.duplex; + pdata->phy_speed = cmd->base.speed; + fxgmac_phy_force_speed(pdata, pdata->phy_speed); + fxgmac_phy_force_duplex(pdata, pdata->phy_duplex); + fxgmac_phy_force_autoneg(pdata, pdata->phy_autoeng); + } + + ret = fxgmac_ephy_soft_reset(pdata); + if (ret) { + printk("%s: ephy soft reset timeout.\n", __func__); + return -ETIMEDOUT; + } + + return 0; +} + +static void fxgmac_get_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + + pause->autoneg = 1; + pause->rx_pause = pdata->rx_pause; + pause->tx_pause = pdata->tx_pause; + + DPRINTK("fxmac get_pauseparam done, rx=%d, tx=%d\n", pdata->rx_pause, + pdata->tx_pause); +} + +static int fxgmac_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + unsigned int pre_rx_pause = pdata->rx_pause; + unsigned int pre_tx_pause = pdata->tx_pause; + + pdata->rx_pause = pause->rx_pause; + pdata->tx_pause = pause->tx_pause; + + if (pre_rx_pause != pdata->rx_pause) { + hw_ops->config_rx_flow_control(pdata); + DPRINTK("fxgmac set pause parameter, rx from %d to %d\n", + pre_rx_pause, pdata->rx_pause); + } + if (pre_tx_pause != pdata->tx_pause) { + hw_ops->config_tx_flow_control(pdata); + DPRINTK("fxgmac set pause parameter, tx from %d to %d\n", + pre_tx_pause, pdata->tx_pause); + } + + DPRINTK("fxgmac set pause parameter, autoneg=%d, rx=%d, tx=%d\n", + pause->autoneg, pause->rx_pause, pause->tx_pause); + + return 0; +} +#endif /*FXGMAC_PAUSE_FEATURE_ENABLED*/ + +/* yzhang added for debug sake. descriptors status checking + * 2021.03.29 + */ +#define FXGMAC_ETH_GSTRING_LEN 32 + +#define FXGMAC_TEST_LEN (sizeof(fxgmac_gstrings_test) / FXGMAC_ETH_GSTRING_LEN) +#define DBG_ETHTOOL_CHECK_NUM_OF_DESC 5 + +static void fxgmac_ethtool_get_strings(struct net_device *netdev, u32 stringset, + u8 *data) +{ + int i; + + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < FXGMAC_STATS_COUNT; i++) { + memcpy(data, fxgmac_gstring_stats[i].stat_string, + strlen(fxgmac_gstring_stats[i].stat_string)); + data += ETH_GSTRING_LEN; + } + break; + default: + WARN_ON(1); + break; + } +} + +static int fxgmac_ethtool_get_sset_count(struct net_device *netdev, + int stringset) +{ + int ret; + + switch (stringset) { + case ETH_SS_STATS: + ret = FXGMAC_STATS_COUNT; + break; + + default: + ret = -EOPNOTSUPP; + } + + return ret; +} + +static void fxgmac_ethtool_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, + u64 *data) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + u8 *stat; + int i; + +#if FXGMAC_PM_FEATURE_ENABLED + /* 20210709 for net power down */ + if (!test_bit(FXGMAC_POWER_STATE_DOWN, &pdata->expansion.powerstate)) +#endif + { + pdata->hw_ops.read_mmc_stats(pdata); + } + + for (i = 0; i < FXGMAC_STATS_COUNT; i++) { + stat = (u8 *)pdata + fxgmac_gstring_stats[i].stat_offset; + *data++ = *(u64 *)stat; + } +} + +static inline bool fxgmac_removed(void __iomem *addr) +{ + return unlikely(!addr); +} +#define FXGMAC_REMOVED(a) fxgmac_removed(a) + +static const struct ethtool_ops fxgmac_ethtool_ops = { + .get_drvinfo = fxgmac_ethtool_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_msglevel = fxgmac_ethtool_get_msglevel, + .set_msglevel = fxgmac_ethtool_set_msglevel, + .get_channels = fxgmac_ethtool_get_channels, + .get_coalesce = fxgmac_ethtool_get_coalesce, + .set_coalesce = fxgmac_ethtool_set_coalesce, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) + +/* The process of set is to get first and then set, + * and the result of get is preserved for values that have not been modified. + * + * Therefore, when using, it is necessary to ensure that this macro and the + * assignment operation in the get_coalesce are one-to-one correspondence, + * otherwise the macro and parameters will be verified when set, and the error + * of "Operation not supported " will be reported if the verification fails + */ +#ifdef ETHTOOL_COALESCE_USECS + .supported_coalesce_params = ETHTOOL_COALESCE_USECS, +#endif +#endif + .get_strings = fxgmac_ethtool_get_strings, + .get_sset_count = fxgmac_ethtool_get_sset_count, + .get_ethtool_stats = fxgmac_ethtool_get_ethtool_stats, + .get_regs_len = fxgmac_get_regs_len, + .get_regs = fxgmac_get_regs, + .get_ringparam = fxgmac_get_ringparam, + .set_ringparam = fxgmac_set_ringparam, +#if (FXGMAC_RSS_FEATURE_ENABLED) + .get_rxnfc = fxgmac_get_rxnfc, + .set_rxnfc = fxgmac_set_rxnfc, + .get_rxfh_indir_size = fxgmac_rss_indir_size, + .get_rxfh_key_size = fxgmac_get_rxfh_key_size, + .get_rxfh = fxgmac_get_rxfh, + .set_rxfh = fxgmac_set_rxfh, +#endif +#if (FXGMAC_WOL_FEATURE_ENABLED) + .get_wol = fxgmac_get_wol, + .set_wol = fxgmac_set_wol, +#endif +#if (FXGMAC_PAUSE_FEATURE_ENABLED) +#ifdef ETHTOOL_GLINKSETTINGS + .get_link_ksettings = fxgmac_get_link_ksettings, + .set_link_ksettings = fxgmac_set_link_ksettings, +#endif /* ETHTOOL_GLINKSETTINGS */ + .get_pauseparam = fxgmac_get_pauseparam, + .set_pauseparam = fxgmac_set_pauseparam, +#endif +}; + +const struct ethtool_ops *fxgmac_get_ethtool_ops(void) +{ + return &fxgmac_ethtool_ops; +} diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-hw.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-hw.c new file mode 100644 index 0000000000000..0517968365d74 --- /dev/null +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-hw.c @@ -0,0 +1,6256 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021 Motorcomm Corporation. */ + +#include "fuxi-os.h" +#include "fuxi-gmac.h" +#include "fuxi-gmac-reg.h" +#include "fuxi-efuse.h" + +void fxgmac_release_phy(struct fxgmac_pdata *pdata); +static void fxgmac_pwr_clock_ungate(struct fxgmac_pdata *pdata); +static void fxgmac_pwr_clock_gate(struct fxgmac_pdata *pdata); + +static int fxgmac_tx_complete(struct fxgmac_dma_desc *dma_desc) +{ +#if (FXGMAC_DUMMY_TX_DEBUG) + return 1; +#endif + return !FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, TX_NORMAL_DESC3_OWN_POS, + TX_NORMAL_DESC3_OWN_LEN); +} + +static int fxgmac_disable_rx_csum(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_IPC_POS, MAC_CR_IPC_LEN, 0); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); + + DPRINTK("fxgmac disable rx checksum.\n"); + return 0; +} + +static int fxgmac_enable_rx_csum(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_IPC_POS, MAC_CR_IPC_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); + + DPRINTK("fxgmac enable rx checksum.\n"); + return 0; +} + +static int fxgmac_set_mac_address(struct fxgmac_pdata *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); + + writereg(pdata->pAdapter, mac_addr_hi, pdata->mac_regs + MAC_MACA0HR); + writereg(pdata->pAdapter, mac_addr_lo, pdata->mac_regs + MAC_MACA0LR); + + return 0; +} + +#if !defined(DPDK) +static void fxgmac_set_mac_reg(struct fxgmac_pdata *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]; + + netif_dbg(pdata, drv, pdata->netdev, + "adding mac address %pM at %#x\n", ha->addr, + *mac_reg); + + mac_addr_hi = FXGMAC_SET_REG_BITS( + mac_addr_hi, MAC_MACA1HR_AE_POS, MAC_MACA1HR_AE_LEN, 1); + } + + writereg(pdata->pAdapter, mac_addr_hi, pdata->mac_regs + *mac_reg); + *mac_reg += MAC_MACA_INC; + writereg(pdata->pAdapter, mac_addr_lo, pdata->mac_regs + *mac_reg); + *mac_reg += MAC_MACA_INC; +} +#endif + +static int fxgmac_enable_tx_vlan(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANIR); + /* Indicate that VLAN Tx CTAGs come from mac_vlan_incl register */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_VLTI_POS, + MAC_VLANIR_VLTI_LEN, 0); + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_CSVL_POS, + MAC_VLANIR_CSVL_LEN, 0); + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_VLP_POS, + MAC_VLANIR_VLP_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_VLC_POS, + MAC_VLANIR_VLC_LEN, 2); + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_VLT_POS, + MAC_VLANIR_VLT_LEN, pdata->vlan); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_VLANIR); + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANTR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_VL_POS, + MAC_VLANTR_VL_LEN, pdata->vlan); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_VLANTR); + + return 0; +} + +static int fxgmac_disable_tx_vlan(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANIR); + + /* Indicate that VLAN Tx CTAGs come from mac_vlan_incl register + * Set VLAN Tag input enable + */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_CSVL_POS, + MAC_VLANIR_CSVL_LEN, 0); + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_VLTI_POS, + MAC_VLANIR_VLTI_LEN, /*0*/ 1); + /* Set VLAN priority control disable */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_VLP_POS, + MAC_VLANIR_VLP_LEN, /*1*/ 0); + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANIR_VLC_POS, + MAC_VLANIR_VLC_LEN, 0); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_VLANIR); + + return 0; +} + +static int fxgmac_enable_rx_vlan_stripping(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANTR); + /* Put the VLAN tag in the Rx descriptor */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_EVLRXS_POS, + MAC_VLANTR_EVLRXS_LEN, 1); + /* Don't check the VLAN type */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_DOVLTC_POS, + MAC_VLANTR_DOVLTC_LEN, 1); + /* Check only C-TAG (0x8100) packets */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_ERSVLM_POS, + MAC_VLANTR_ERSVLM_LEN, 0); + /* Don't consider an S-TAG (0x88A8) packet as a VLAN packet */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_ESVL_POS, + MAC_VLANTR_ESVL_LEN, 0); + /* Enable VLAN tag stripping */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_EVLS_POS, + MAC_VLANTR_EVLS_LEN, 0x3); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_VLANTR); + DPRINTK("fxgmac enable MAC rx vlan stripping.\n"); + + return 0; +} + +static int fxgmac_disable_rx_vlan_stripping(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANTR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_EVLS_POS, + MAC_VLANTR_EVLS_LEN, 0); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_VLANTR); + DPRINTK("fxgmac disable MAC rx vlan stripping.\n"); + + return 0; +} + +static int fxgmac_enable_rx_vlan_filtering(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PFR); + /* Enable VLAN filtering */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_PFR_VTFE_POS, MAC_PFR_VTFE_LEN, + 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PFR); + +#if FXGMAC_FILTER_SINGLE_VLAN_ENABLED + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANTR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_VL_POS, + MAC_VLANTR_VL_LEN, pdata->vlan); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_VLANTR); +#else + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANTR); + /* Enable VLAN Hash Table filtering */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_VTHM_POS, + MAC_VLANTR_VTHM_LEN, 1); + /* Disable VLAN tag inverse matching */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_VTIM_POS, + MAC_VLANTR_VTIM_LEN, 0); + /* Only filter on the lower 12-bits of the VLAN tag */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_ETV_POS, + MAC_VLANTR_ETV_LEN, 1); +#endif + + return 0; +} + +static int fxgmac_disable_rx_vlan_filtering(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PFR); + /* Disable VLAN filtering */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_PFR_VTFE_POS, MAC_PFR_VTFE_LEN, + 0); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PFR); + +#if FXGMAC_FILTER_SINGLE_VLAN_ENABLED + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANTR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANTR_VL_POS, + MAC_VLANTR_VL_LEN, pdata->vlan); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_VLANTR); +#endif + + return 0; +} + +#if FXGMAC_FILTER_MULTIPLE_VLAN_ENABLED +static u32 fxgmac_vid_crc32_le(__le16 vid_le) +{ + unsigned char *data = (unsigned char *)&vid_le; + unsigned char data_byte = 0; + u32 crc = ~0; + u32 temp = 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 ^= CRC32_POLY_LE; + } + + return crc; +} +#endif + +static int fxgmac_update_vlan_hash_table(struct fxgmac_pdata *pdata) +{ + u16 vlan_hash_table = 0; + u32 regval; +#if FXGMAC_FILTER_MULTIPLE_VLAN_ENABLED + __le16 vid_le; + u32 crc; + u16 vid; + /* 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(~fxgmac_vid_crc32_le(vid_le)) >> 28; + + vlan_hash_table |= (1 << crc); + } +#endif + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_VLANHTR); + /* Set the VLAN Hash Table filtering register */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_VLANHTR_VLHT_POS, + MAC_VLANHTR_VLHT_LEN, vlan_hash_table); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_VLANHTR); + + DPRINTK("fxgmac_update_vlan_hash_tabl done, hash tbl=%08x.\n", + vlan_hash_table); + return 0; +} + +static int fxgmac_set_promiscuous_mode(struct fxgmac_pdata *pdata, + unsigned int enable) +{ + unsigned int val = enable ? 1 : 0; + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PFR); + + if (FXGMAC_GET_REG_BITS(regval, MAC_PFR_PR_POS, MAC_PFR_PR_LEN) == + val) { + return 0; + } + netif_dbg(pdata, drv, pdata->netdev, + "" STR_FORMAT " promiscuous mode\n", + enable ? "entering" : "leaving"); + + regval = FXGMAC_SET_REG_BITS(regval, MAC_PFR_PR_POS, MAC_PFR_PR_LEN, + val); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PFR); + + DbgPrintF(MP_TRACE, "" STR_FORMAT " - promiscuous mode=%d, reg=%x.", + __FUNCTION__, enable, regval); + DbgPrintF( + MP_TRACE, + "" STR_FORMAT + " - note, vlan filter is called when set promiscuous mode=%d.", + __FUNCTION__, enable); + + /* Hardware will still perform VLAN filtering in promiscuous mode */ + if (enable) { + fxgmac_disable_rx_vlan_filtering(pdata); + } else { + if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER) { + fxgmac_enable_rx_vlan_filtering(pdata); + } + } + + DPRINTK("fxgmac set promisc mode=%d\n", enable); + return 0; +} + +static int fxgmac_enable_rx_broadcast(struct fxgmac_pdata *pdata, + unsigned int enable) +{ + /* mac reg bit is disable, so invert the val. */ + unsigned int val = enable ? 0 : 1; + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PFR); + + if (FXGMAC_GET_REG_BITS(regval, MAC_PFR_DBF_POS, MAC_PFR_DBF_LEN) == + val) { + return 0; + } + + regval = FXGMAC_SET_REG_BITS(regval, MAC_PFR_DBF_POS, MAC_PFR_DBF_LEN, + val); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PFR); + + DbgPrintF(MP_TRACE, "%s - bcast en=%d, bit-val=%d, reg=%x.", + __FUNCTION__, enable, val, regval); + return 0; +} + +static int fxgmac_set_all_multicast_mode(struct fxgmac_pdata *pdata, + unsigned int enable) +{ + unsigned int val = enable ? 1 : 0; + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PFR); + if (FXGMAC_GET_REG_BITS(regval, MAC_PFR_PM_POS, MAC_PFR_PM_LEN) == + val) { + return 0; + } + netif_dbg(pdata, drv, pdata->netdev, "" STR_FORMAT " allmulti mode\n", + enable ? "entering" : "leaving"); + + regval = FXGMAC_SET_REG_BITS(regval, MAC_PFR_PM_POS, MAC_PFR_PM_LEN, + val); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PFR); + + DbgPrintF(MP_TRACE, + "" STR_FORMAT " - Enable all Multicast=%d, regval=%#x.", + __FUNCTION__, enable, regval); + + return 0; +} + +static void fxgmac_set_mac_addn_addrs(struct fxgmac_pdata *pdata) +{ +#ifndef DPDK +#if FXGMAC_FILTER_MULTIPLE_MAC_ADDR_ENABLED + struct net_device *netdev = pdata->netdev; + struct netdev_hw_addr *ha; +#endif + unsigned int addn_macs; + unsigned int mac_reg; + + mac_reg = MAC_MACA1HR; + addn_macs = pdata->hw_feat.addn_mac; +#if FXGMAC_FILTER_MULTIPLE_MAC_ADDR_ENABLED + DPRINTK("xlgamc add mac addr callin\n"); + if (netdev_uc_count(netdev) > addn_macs) { + fxgmac_set_promiscuous_mode(pdata, 1); + } else { + netdev_for_each_uc_addr(ha, netdev) { + fxgmac_set_mac_reg(pdata, ha, &mac_reg); + addn_macs--; + } + + if (netdev_mc_count(netdev) > addn_macs) { + fxgmac_set_all_multicast_mode(pdata, 1); + } else { + netdev_for_each_mc_addr(ha, netdev) { + fxgmac_set_mac_reg(pdata, ha, &mac_reg); + addn_macs--; + } + } + } +#endif + /* Clear remaining additional MAC address entries */ + while (addn_macs--) { + fxgmac_set_mac_reg(pdata, NULL, &mac_reg); + } +#else + (void)pdata; +#endif +} + +#define GET_REG_AND_BIT_POS(reversalval, regOut, bitOut) \ + do { \ + regOut = (((reversalval) >> 5) & 0x7); \ + bitOut = ((reversalval) & 0x1f); \ + } while (0) + +static u32 fxgmac_crc32(unsigned char *Data, int Length) +{ + u32 Crc = (u32)~0; /* Initial value. 0xFFFFFFFF */ + + while (--Length >= 0) { + unsigned char Byte = *Data++; + int Bit; + + for (Bit = 8; --Bit >= 0; Byte >>= 1) { + if ((Crc ^ Byte) & 1) { + Crc >>= 1; + Crc ^= 0xedb88320; + } else { + Crc >>= 1; + } + } + } + + return ~Crc; +} + +/* + * configure multicast hash table, reg 0x2010~202c + * input: pmc_mac, pointer to mcast MAC. if it is null, then clean all registers. + * b_add, 1 to set the bit; 0 to clear the bit. + */ +static void fxgmac_config_multicast_mac_hash_table(struct fxgmac_pdata *pdata, + unsigned char *pmc_mac, + int b_add) +{ + unsigned int hash_reg, reg_bit; + unsigned int j; + u32 crc, reversal_crc, regval; + + if (!pmc_mac) { + for (j = 0; j < FXGMAC_MAC_HASH_TABLE_SIZE; j++) { + hash_reg = j; + hash_reg = (MAC_HTR0 + hash_reg * MAC_HTR_INC); + writereg(pdata->pAdapter, 0, + pdata->mac_regs + hash_reg); + } + DBGPRINT( + MP_TRACE, + ("> 24), hash_reg, reg_bit); + /* Set the MAC Hash Table registers */ + hash_reg = (MAC_HTR0 + hash_reg * MAC_HTR_INC); + regval = readreg(pdata->pAdapter, pdata->mac_regs + hash_reg); + + regval = FXGMAC_SET_REG_BITS(regval, reg_bit, 1, (b_add ? 1 : 0)); + + writereg(pdata->pAdapter, regval, pdata->mac_regs + hash_reg); +} + +static void fxgmac_set_mac_hash_table(struct fxgmac_pdata *pdata) +{ +#ifndef DPDK +#if FUXI_MAC_HASH_TABLE + struct net_device *netdev = pdata->netdev; + struct netdev_hw_addr *ha; + + netdev_for_each_mc_addr(ha, netdev) { + fxgmac_config_multicast_mac_hash_table(pdata, ha->addr, 1); + } +#endif + pdata = pdata; + +#else + (void)pdata; +#endif +} + +static int fxgmac_add_mac_addresses(struct fxgmac_pdata *pdata) +{ + if (pdata->hw_feat.hash_table_size) + fxgmac_set_mac_hash_table(pdata); + else + fxgmac_set_mac_addn_addrs(pdata); + + return 0; +} + +static void fxgmac_config_mac_address(struct fxgmac_pdata *pdata) +{ + u32 regval; + fxgmac_set_mac_address(pdata, pdata->mac_addr); + + /* Filtering is done using perfect filtering and hash filtering */ + if (pdata->hw_feat.hash_table_size) { + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PFR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_PFR_HPF_POS, + MAC_PFR_HPF_LEN, 1); +#if FUXI_MAC_HASH_TABLE + regval = FXGMAC_SET_REG_BITS(regval, MAC_PFR_HUC_POS, + MAC_PFR_HUC_LEN, 1); +#endif + regval = FXGMAC_SET_REG_BITS(regval, MAC_PFR_HMC_POS, + MAC_PFR_HMC_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PFR); + } +} + +static int fxgmac_config_crc_check(struct fxgmac_pdata *pdata) +{ + u32 regval, value; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_ECR); + value = (pdata->crc_check) ? 0 : 1; + regval = FXGMAC_SET_REG_BITS(regval, MAC_ECR_DCRCC_POS, + MAC_ECR_DCRCC_LEN, value); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_ECR); + + return 0; +} + +static int fxgmac_config_jumbo(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_JE_POS, MAC_CR_JE_LEN, + pdata->jumbo); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); + return 0; +} + +static void fxgmac_config_checksum_offload(struct fxgmac_pdata *pdata) +{ + if (pdata->netdev->features & NETIF_F_RXCSUM) + fxgmac_enable_rx_csum(pdata); + else + fxgmac_disable_rx_csum(pdata); +} + +static void fxgmac_config_vlan_support(struct fxgmac_pdata *pdata) +{ + fxgmac_disable_tx_vlan( + pdata); /* configure dynamical vlanID from TX Context. */ + + /* Set the current VLAN Hash Table register value */ + fxgmac_update_vlan_hash_table(pdata); + + if (pdata->vlan_filter) /* disable vlan rx filter by default */ + fxgmac_enable_rx_vlan_filtering(pdata); + else + fxgmac_disable_rx_vlan_filtering(pdata); + + if (pdata->vlan_strip) /* enable vlan rx strip by default */ + fxgmac_enable_rx_vlan_stripping(pdata); + else + fxgmac_disable_rx_vlan_stripping(pdata); +} + +static int fxgmac_config_rx_mode(struct fxgmac_pdata *pdata) +{ + struct net_device *netdev = pdata->netdev; + unsigned int pr_mode, am_mode; + + pr_mode = ((netdev->flags & IFF_PROMISC) != 0); + am_mode = ((netdev->flags & IFF_ALLMULTI) != 0); + + fxgmac_set_promiscuous_mode(pdata, pr_mode); + fxgmac_set_all_multicast_mode(pdata, am_mode); + + fxgmac_add_mac_addresses(pdata); + + return 0; +} + +static void fxgmac_prepare_tx_stop(struct fxgmac_pdata *pdata, + struct fxgmac_channel *channel) +{ + unsigned int tx_dsr, tx_pos, tx_qidx; + unsigned long tx_timeout; + unsigned int tx_status; + + pdata = pdata; + + /* 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_LEN) + + 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_LEN) + + DMA_DSRX_TPS_START; + } + +#if FXGMAC_TX_HANG_TIMER_EN + tx_timeout = jiffies + msecs_to_jiffies(100); /* 100ms */ +#else + tx_timeout = jiffies + (FXGMAC_DMA_STOP_TIMEOUT * HZ); +#endif + while (time_before(jiffies, tx_timeout)) { + tx_status = readreg(pdata->pAdapter, pdata->mac_regs + tx_dsr); + tx_status = + FXGMAC_GET_REG_BITS(tx_status, tx_pos, DMA_DSR_TPS_LEN); + if ((tx_status == DMA_TPS_STOPPED) || + (tx_status == DMA_TPS_SUSPENDED)) + break; + + usleep_range_ex(pdata->pAdapter, 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 fxgmac_enable_tx(struct fxgmac_pdata *pdata) +{ +#ifndef DPDK + struct fxgmac_channel *channel; +#endif + unsigned int i; + u32 regval; + +#if FXGMAC_TX_HANG_TIMER_EN + pdata->tx_hang_restart_queuing = 0; +#endif + + /* Enable each Tx DMA channel */ +#ifndef DPDK + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_TCR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_TCR_ST_POS, + DMA_CH_TCR_ST_LEN, 1); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_TCR)); + } +#else + PMD_INIT_FUNC_TRACE(); + struct fxgmac_tx_queue *txq; + struct rte_eth_dev *dev = pdata->expansion.eth_dev; + + for (i = 0; i < dev->data->nb_tx_queues; i++) { + txq = dev->data->tx_queues[i]; + /* Enable Tx DMA channel */ + FXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, ST, 1); + } +#endif + + /* Enable each Tx queue */ + for (i = 0; i < pdata->tx_q_count; i++) { + regval = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); + regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_TXQEN_POS, + MTL_Q_TQOMR_TXQEN_LEN, + MTL_Q_ENABLED); + writereg(pdata->pAdapter, regval, + FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); + } + + /* Enable MAC Tx */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_TE_POS, MAC_CR_TE_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); +} + +static void fxgmac_disable_tx(struct fxgmac_pdata *pdata) +{ +#ifndef DPDK + struct fxgmac_channel *channel; +#endif + unsigned int i; + u32 regval; + + /* Prepare for Tx DMA channel stop */ +#ifndef DPDK + channel = pdata->channel_head; + if (channel != NULL) { + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (!channel->tx_ring) + break; + + fxgmac_prepare_tx_stop(pdata, channel); + +#if FXGMAC_TX_HANG_TIMER_EN + pdata->tx_hang_restart_queuing = 0; +#endif + } + } + +#else + PMD_INIT_FUNC_TRACE(); + struct fxgmac_tx_queue *txq; + struct rte_eth_dev *dev = pdata->expansion.eth_dev; + + for (i = 0; i < pdata->tx_q_count; i++) { + txq = dev->data->tx_queues[i]; + fxgmac_txq_prepare_tx_stop(pdata, i); + } +#endif + + /* Disable MAC Tx */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_TE_POS, MAC_CR_TE_LEN, 0); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); + + /* Disable each Tx queue */ + for (i = 0; i < pdata->tx_q_count; i++) { + regval = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); + regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_TXQEN_POS, + MTL_Q_TQOMR_TXQEN_LEN, 0); + writereg(pdata->pAdapter, regval, + FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); + } + + /* Disable each Tx DMA channel */ +#ifndef DPDK + channel = pdata->channel_head; + if (channel != NULL) { + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (!channel->tx_ring) + break; + + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_TCR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_TCR_ST_POS, + DMA_CH_TCR_ST_LEN, 0); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_TCR)); + } + } +#else + for (i = 0; i < dev->data->nb_tx_queues; i++) { + txq = dev->data->tx_queues[i]; + FXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, ST, 0); + } +#endif +} + +static void fxgmac_prepare_rx_stop(struct fxgmac_pdata *pdata, + unsigned int queue) +{ + unsigned int rx_status, prxq; + unsigned int rxqsts; + unsigned long rx_timeout; + /* The Rx engine cannot be stopped if it is actively processing + * packets. Wait for the Rx queue to empty the Rx fifo. Don't + * wait forever though... + */ +#if FXGMAC_TX_HANG_TIMER_EN + rx_timeout = + jiffies + msecs_to_jiffies(500); /* 500ms, larger is better */ +#else + rx_timeout = jiffies + (FXGMAC_DMA_STOP_TIMEOUT * HZ); +#endif + while (time_before(jiffies, rx_timeout)) { + rx_status = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, queue, MTL_Q_RQDR)); + prxq = FXGMAC_GET_REG_BITS(rx_status, MTL_Q_RQDR_PRXQ_POS, + MTL_Q_RQDR_PRXQ_LEN); + rxqsts = FXGMAC_GET_REG_BITS(rx_status, MTL_Q_RQDR_RXQSTS_POS, + MTL_Q_RQDR_RXQSTS_LEN); + if ((prxq == 0) && (rxqsts == 0)) + break; + + usleep_range_ex(pdata->pAdapter, 500, 1000); + } + + if (!time_before(jiffies, rx_timeout)) + netdev_info(pdata->netdev, + "timed out waiting for Rx queue %u to empty\n", + queue); +} + +static void fxgmac_enable_rx(struct fxgmac_pdata *pdata) +{ +#ifndef DPDK + struct fxgmac_channel *channel; +#endif + unsigned int regval, i; + + /* Enable each Rx DMA channel */ +#ifndef DPDK + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_RCR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_RCR_SR_POS, + DMA_CH_RCR_SR_LEN, 1); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_RCR)); + } + +#else + PMD_INIT_FUNC_TRACE(); + struct fxgmac_rx_queue *rxq; + struct rte_eth_dev *dev = pdata->expansion.eth_dev; + + for (i = 0; i < dev->data->nb_rx_queues; i++) { + rxq = dev->data->rx_queues[i]; + /* Enable Rx DMA channel */ + FXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_RCR, SR, 1); + } +#endif + + /* Enable each Rx queue */ + regval = 0; + for (i = 0; i < pdata->rx_q_count; i++) + regval |= (0x02 << (i << 1)); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_RQC0R); + +#ifndef DPDK + /* Enable MAC Rx */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_CST_POS, MAC_CR_CST_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_ACS_POS, MAC_CR_ACS_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_RE_POS, MAC_CR_RE_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); +#else + /* Enable MAC Rx */ + FXGMAC_IOWRITE_BITS(pdata, MAC_ECR, DCRCC, 1); + + /* Frame is forwarded after stripping CRC to application*/ + if (pdata->expansion.crc_strip_enable) { + FXGMAC_IOWRITE_BITS(pdata, MAC_CR, CST, 1); + FXGMAC_IOWRITE_BITS(pdata, MAC_CR, ACS, 1); + } + FXGMAC_IOWRITE_BITS(pdata, MAC_CR, RE, 1); +#endif +} +static void fxgmac_enable_channel_rx(struct fxgmac_pdata *pdata, + unsigned int queue) +{ + struct fxgmac_channel *channel; + unsigned int regval; + + /* Enable Rx DMA channel */ + channel = pdata->channel_head + queue; + + if (!channel->rx_ring) + return; + regval = readreg(pdata->pAdapter, FXGMAC_DMA_REG(channel, DMA_CH_RCR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_RCR_SR_POS, + DMA_CH_RCR_SR_LEN, 1); + writereg(pdata->pAdapter, regval, FXGMAC_DMA_REG(channel, DMA_CH_RCR)); + /* Enable Rx queue */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_RQC0R); + regval |= (0x02 << (queue << 1)); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_RQC0R); + + /* Enable MAC Rx */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); + if (!(regval & ((0x01 << MAC_CR_CST_POS) | (0x01 << MAC_CR_ACS_POS) | + (0x01 << MAC_CR_RE_POS)))) { + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_CST_POS, + MAC_CR_CST_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_ACS_POS, + MAC_CR_ACS_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_RE_POS, + MAC_CR_RE_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); + } +} + +static void fxgmac_disable_rx(struct fxgmac_pdata *pdata) +{ +#ifndef DPDK + struct fxgmac_channel *channel; +#endif + unsigned int i; + u32 regval; + + /* Disable MAC Rx */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_CST_POS, MAC_CR_CST_LEN, 0); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_ACS_POS, MAC_CR_ACS_LEN, 0); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_RE_POS, MAC_CR_RE_LEN, 0); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); + + /* Prepare for Rx DMA channel stop */ +#ifndef DPDK + for (i = 0; i < pdata->rx_q_count; i++) + fxgmac_prepare_rx_stop(pdata, i); +#else + PMD_INIT_FUNC_TRACE(); + struct fxgmac_rx_queue *rxq; + struct rte_eth_dev *dev = pdata->expansion.eth_dev; + + for (i = 0; i < dev->data->nb_rx_queues; i++) { + rxq = dev->data->rx_queues[i]; + fxgmac_prepare_rx_stop(pdata, i); + } +#endif + + /* Disable each Rx queue */ + writereg(pdata->pAdapter, 0, pdata->mac_regs + MAC_RQC0R); + + /* Disable each Rx DMA channel */ +#ifndef DPDK + channel = pdata->channel_head; + if (channel != NULL) { + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (!channel->rx_ring) + break; + + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_RCR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_RCR_SR_POS, + DMA_CH_RCR_SR_LEN, 0); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_RCR)); + } + } +#else + for (i = 0; i < dev->data->nb_rx_queues; i++) { + rxq = dev->data->rx_queues[i]; + FXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_RCR, SR, 0); + } +#endif +} + +static void fxgmac_tx_start_xmit(struct fxgmac_channel *channel, + struct fxgmac_ring *ring) +{ + struct fxgmac_pdata *pdata = channel->pdata; + struct fxgmac_desc_data *desc_data; + + /* Make sure everything is written before the register write */ + wmb(); + + /* Issue a poll command to Tx DMA by writing address + * of next immediate free descriptor + */ + desc_data = FXGMAC_GET_DESC_DATA(ring, ring->cur); + +#if !(FXGMAC_DUMMY_TX_DEBUG) + writereg(pdata->pAdapter, lower_32_bits(desc_data->dma_desc_addr), + FXGMAC_DMA_REG(channel, DMA_CH_TDTR_LO)); +#else + DPRINTK("dummy tx, fxgmac_tx_start_xmit, tail reg=0x%lx, val=%08x\n", + FXGMAC_DMA_REG(channel, DMA_CH_TDTR_LO) - pdata->mac_regs, + (u32)lower_32_bits(desc_data->dma_desc_addr)); +#endif + if (netif_msg_tx_done(pdata)) + DPRINTK("tx_start_xmit: dump before wr reg, dma base=0x%016llx, reg=0x%08x, tx timer usecs=%u, tx_timer_active=%u\n", + desc_data->dma_desc_addr, + readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_TDTR_LO)), + pdata->tx_usecs, channel->tx_timer_active); + + ring->tx.xmit_more = 0; +} + +static void fxgmac_dev_xmit(struct fxgmac_channel *channel) +{ + struct fxgmac_pdata *pdata = channel->pdata; + struct fxgmac_ring *ring = channel->tx_ring; + unsigned int tso_context, vlan_context; + struct fxgmac_desc_data *desc_data; + struct fxgmac_dma_desc *dma_desc; + struct fxgmac_pkt_info *pkt_info; + unsigned int csum, tso, vlan; + int start_index = ring->cur; + int cur_index = ring->cur; + int i; + + if (netif_msg_tx_done(pdata)) + DPRINTK("dev_xmit callin, desc cur=%d\n", cur_index); + + pkt_info = &ring->pkt_info; + csum = FXGMAC_GET_REG_BITS(pkt_info->attributes, + TX_PACKET_ATTRIBUTES_CSUM_ENABLE_POS, + TX_PACKET_ATTRIBUTES_CSUM_ENABLE_LEN); + tso = FXGMAC_GET_REG_BITS(pkt_info->attributes, + TX_PACKET_ATTRIBUTES_TSO_ENABLE_POS, + TX_PACKET_ATTRIBUTES_TSO_ENABLE_LEN); + vlan = FXGMAC_GET_REG_BITS(pkt_info->attributes, + TX_PACKET_ATTRIBUTES_VLAN_CTAG_POS, + TX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN); + + if (tso && (pkt_info->mss != ring->tx.cur_mss)) + tso_context = 1; + else + tso_context = 0; + + if ((tso_context) && (netif_msg_tx_done(pdata))) { + /* tso is initialized to start... */ + DPRINTK("fxgmac_dev_xmit, tso_%s tso=0x%x, pkt_mss=%d, cur_mss=%d\n", + (pkt_info->mss) ? "start" : "stop", tso, pkt_info->mss, + ring->tx.cur_mss); + } + + if (vlan && (pkt_info->vlan_ctag != ring->tx.cur_vlan_ctag)) + vlan_context = 1; + else + vlan_context = 0; + + if (vlan && (netif_msg_tx_done(pdata))) + DPRINTK("fxgmac_dev_xmi:pkt vlan=%d, ring vlan=%d, vlan_context=%d\n", + pkt_info->vlan_ctag, ring->tx.cur_vlan_ctag, + vlan_context); + + desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); + dma_desc = desc_data->dma_desc; + + /* Create a context descriptor if this is a TSO pkt_info */ + if (tso_context || vlan_context) { + if (tso_context) { + if (netif_msg_tx_done(pdata)) + DPRINTK("xlgamc dev xmit, construct tso context descriptor, mss=%u\n", + pkt_info->mss); + + /* Set the MSS size */ + dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc2, TX_CONTEXT_DESC2_MSS_POS, + TX_CONTEXT_DESC2_MSS_LEN, pkt_info->mss); + + /* Mark it as a CONTEXT descriptor */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_CONTEXT_DESC3_CTXT_POS, + TX_CONTEXT_DESC3_CTXT_LEN, 1); + + /* Indicate this descriptor contains the MSS */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_CONTEXT_DESC3_TCMSSV_POS, + TX_CONTEXT_DESC3_TCMSSV_LEN, 1); + + ring->tx.cur_mss = pkt_info->mss; + } + + if (vlan_context) { + netif_dbg(pdata, tx_queued, pdata->netdev, + "VLAN context descriptor, ctag=%u\n", + pkt_info->vlan_ctag); + + /* Mark it as a CONTEXT descriptor */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_CONTEXT_DESC3_CTXT_POS, + TX_CONTEXT_DESC3_CTXT_LEN, 1); + + /* Set the VLAN tag */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_CONTEXT_DESC3_VT_POS, + TX_CONTEXT_DESC3_VT_LEN, pkt_info->vlan_ctag); + + /* Indicate this descriptor contains the VLAN tag */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_CONTEXT_DESC3_VLTV_POS, + TX_CONTEXT_DESC3_VLTV_LEN, 1); + + ring->tx.cur_vlan_ctag = pkt_info->vlan_ctag; + } + + cur_index = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); + desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); + dma_desc = desc_data->dma_desc; + } + + /* Update buffer address (for TSO this is the header) */ + dma_desc->desc0 = cpu_to_le32(lower_32_bits(desc_data->skb_dma)); + dma_desc->desc1 = cpu_to_le32(upper_32_bits(desc_data->skb_dma)); + + /* Update the buffer length */ + dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc2, + TX_NORMAL_DESC2_HL_B1L_POS, + TX_NORMAL_DESC2_HL_B1L_LEN, + desc_data->skb_dma_len); + + /* VLAN tag insertion check */ + if (vlan) { + dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc2, TX_NORMAL_DESC2_VTIR_POS, + TX_NORMAL_DESC2_VTIR_LEN, TX_NORMAL_DESC2_VLAN_INSERT); + pdata->stats.tx_vlan_packets++; + } + + /* Timestamp enablement check */ + if (FXGMAC_GET_REG_BITS(pkt_info->attributes, + TX_PACKET_ATTRIBUTES_PTP_POS, + TX_PACKET_ATTRIBUTES_PTP_LEN)) + dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc2, TX_NORMAL_DESC2_TTSE_POS, + TX_NORMAL_DESC2_TTSE_LEN, 1); + + /* Mark it as First Descriptor */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, + TX_NORMAL_DESC3_FD_POS, + TX_NORMAL_DESC3_FD_LEN, 1); + + /* Mark it as a NORMAL descriptor */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, + TX_NORMAL_DESC3_CTXT_POS, + TX_NORMAL_DESC3_CTXT_LEN, 0); + + /* Set OWN bit if not the first descriptor */ + if (cur_index != start_index) + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_OWN_POS, + TX_NORMAL_DESC3_OWN_LEN, 1); + + if (tso) { + /* Enable TSO */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_TSE_POS, + TX_NORMAL_DESC3_TSE_LEN, 1); + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_TCPPL_POS, + TX_NORMAL_DESC3_TCPPL_LEN, pkt_info->tcp_payload_len); + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_TCPHDRLEN_POS, + TX_NORMAL_DESC3_TCPHDRLEN_LEN, + pkt_info->tcp_header_len / 4); + + pdata->stats.tx_tso_packets++; + } else { + /* Enable CRC and Pad Insertion */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_CPC_POS, + TX_NORMAL_DESC3_CPC_LEN, 0); + + /* Enable HW CSUM */ + if (csum) + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_CIC_POS, + TX_NORMAL_DESC3_CIC_LEN, 0x3); + + /* Set the total length to be transmitted */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, + TX_NORMAL_DESC3_FL_POS, + TX_NORMAL_DESC3_FL_LEN, + pkt_info->length); + } + if (netif_msg_tx_done(pdata)) + DPRINTK("dev_xmit before more descs, desc cur=%d, start=%d, desc=%#x,%#x,%#x,%#x\n", + cur_index, start_index, dma_desc->desc0, + dma_desc->desc1, dma_desc->desc2, dma_desc->desc3); + + if (start_index <= cur_index) + i = cur_index - start_index + 1; + else + i = ring->dma_desc_count - start_index + cur_index; + + for (; i < pkt_info->desc_count; i++) { + cur_index = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); + + desc_data = FXGMAC_GET_DESC_DATA(ring, cur_index); + dma_desc = desc_data->dma_desc; + + /* Update buffer address */ + dma_desc->desc0 = + cpu_to_le32(lower_32_bits(desc_data->skb_dma)); + dma_desc->desc1 = + cpu_to_le32(upper_32_bits(desc_data->skb_dma)); + + /* Update the buffer length */ + dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc2, TX_NORMAL_DESC2_HL_B1L_POS, + TX_NORMAL_DESC2_HL_B1L_LEN, desc_data->skb_dma_len); + + /* Set OWN bit */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_OWN_POS, + TX_NORMAL_DESC3_OWN_LEN, 1); + + /* Mark it as NORMAL descriptor */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_CTXT_POS, + TX_NORMAL_DESC3_CTXT_LEN, 0); + + /* Enable HW CSUM */ + if (csum) + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE( + dma_desc->desc3, TX_NORMAL_DESC3_CIC_POS, + TX_NORMAL_DESC3_CIC_LEN, 0x3); + } + + /* Set LAST bit for the last descriptor */ + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, + TX_NORMAL_DESC3_LD_POS, + TX_NORMAL_DESC3_LD_LEN, 1); + + dma_desc->desc2 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc2, + TX_NORMAL_DESC2_IC_POS, + TX_NORMAL_DESC2_IC_LEN, 1); + + /* Save the Tx info to report back during cleanup */ + desc_data->tx.packets = pkt_info->tx_packets; + desc_data->tx.bytes = pkt_info->tx_bytes; + + if (netif_msg_tx_done(pdata)) + DPRINTK("dev_xmit last descs, desc cur=%d, desc=%#x,%#x,%#x,%#x\n", + cur_index, dma_desc->desc0, dma_desc->desc1, + dma_desc->desc2, dma_desc->desc3); + + /* 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 + */ + dma_wmb(); + + /* Set OWN bit for the first descriptor */ + desc_data = FXGMAC_GET_DESC_DATA(ring, start_index); + dma_desc = desc_data->dma_desc; + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, + TX_NORMAL_DESC3_OWN_POS, + TX_NORMAL_DESC3_OWN_LEN, 1); + + if (netif_msg_tx_done(pdata)) + DPRINTK("dev_xmit first descs, start=%d, desc=%#x,%#x,%#x,%#x\n", + start_index, dma_desc->desc0, dma_desc->desc1, + dma_desc->desc2, dma_desc->desc3); + + if (netif_msg_tx_queued(pdata)) + fxgmac_dump_tx_desc(pdata, ring, start_index, + pkt_info->desc_count, 1); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) + if (netif_msg_tx_done(pdata)) + DPRINTK("dev_xmit about to call tx_start_xmit, ring xmit_more=%d, txq_stopped=%x\n", + ring->tx.xmit_more, + netif_xmit_stopped(netdev_get_tx_queue( + pdata->netdev, channel->queue_index))); +#else /* ( LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,165))*/ + if (netif_msg_tx_done(pdata)) + DPRINTK("dev_xmit about to call tx_start_xmit, pkt xmit_more=%d, txq_stopped=%x\n", + pkt_info->skb->xmit_more, + netif_xmit_stopped(netdev_get_tx_queue( + pdata->netdev, channel->queue_index))); +#endif + + /* Make sure ownership is written to the descriptor */ + smp_wmb(); + + ring->cur = FXGMAC_GET_ENTRY(cur_index, ring->dma_desc_count); + + fxgmac_tx_start_xmit(channel, ring); + + /* yzhang for reduce debug output */ + if (netif_msg_tx_done(pdata)) { + DPRINTK("dev_xmit callout %s: descriptors %u to %u written\n", + channel->name, start_index & (ring->dma_desc_count - 1), + (ring->cur - 1) & (ring->dma_desc_count - 1)); + } +} + +static void fxgmac_get_rx_tstamp(struct fxgmac_pkt_info *pkt_info, + struct fxgmac_dma_desc *dma_desc) +{ + u64 nsec; + + nsec = le32_to_cpu(dma_desc->desc1); + nsec <<= 32; + nsec |= le32_to_cpu(dma_desc->desc0); + if (nsec != 0xffffffffffffffffULL) { + pkt_info->rx_tstamp = nsec; + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, + RX_PACKET_ATTRIBUTES_RX_TSTAMP_POS, + RX_PACKET_ATTRIBUTES_RX_TSTAMP_LEN, 1); + } +} + +static void fxgmac_tx_desc_reset(struct fxgmac_desc_data *desc_data) +{ + struct fxgmac_dma_desc *dma_desc = desc_data->dma_desc; + + /* 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) + */ + dma_desc->desc0 = 0; + dma_desc->desc1 = 0; + dma_desc->desc2 = 0; + dma_desc->desc3 = 0; + + /* Make sure ownership is written to the descriptor */ + dma_wmb(); +} + +static void fxgmac_tx_desc_init(struct fxgmac_channel *channel) +{ + struct fxgmac_ring *ring = channel->tx_ring; + struct fxgmac_desc_data *desc_data; + int start_index = ring->cur; + unsigned int i; + start_index = start_index; + + /* Initialize all descriptors */ + for (i = 0; i < ring->dma_desc_count; i++) { + desc_data = FXGMAC_GET_DESC_DATA(ring, i); + + /* Initialize Tx descriptor */ + fxgmac_tx_desc_reset(desc_data); + } + + writereg(channel->pdata->pAdapter, channel->pdata->tx_desc_count - 1, + FXGMAC_DMA_REG(channel, DMA_CH_TDRLR)); + + /* Update the starting address of descriptor ring */ + desc_data = FXGMAC_GET_DESC_DATA(ring, start_index); + writereg(channel->pdata->pAdapter, + upper_32_bits(desc_data->dma_desc_addr), + FXGMAC_DMA_REG(channel, DMA_CH_TDLR_HI)); + writereg(channel->pdata->pAdapter, + lower_32_bits(desc_data->dma_desc_addr), + FXGMAC_DMA_REG(channel, DMA_CH_TDLR_LO)); +} + +static void fxgmac_rx_desc_reset(struct fxgmac_pdata *pdata, + struct fxgmac_desc_data *desc_data, + unsigned int index) +{ + struct fxgmac_dma_desc *dma_desc = desc_data->dma_desc; + + /* 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 + */ + dma_desc->desc0 = + cpu_to_le32(lower_32_bits(desc_data->rx.buf.dma_base)); + dma_desc->desc1 = + cpu_to_le32(upper_32_bits(desc_data->rx.buf.dma_base)); + dma_desc->desc2 = 0; + dma_desc->desc3 = 0; + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, + RX_NORMAL_DESC3_INTE_POS, + RX_NORMAL_DESC3_INTE_LEN, 1); + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, + RX_NORMAL_DESC3_BUF2V_POS, + RX_NORMAL_DESC3_BUF2V_LEN, 0); + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, + RX_NORMAL_DESC3_BUF1V_POS, + RX_NORMAL_DESC3_BUF1V_LEN, 1); + + /* 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 + */ + dma_wmb(); + + dma_desc->desc3 = FXGMAC_SET_REG_BITS_LE(dma_desc->desc3, + RX_NORMAL_DESC3_OWN_POS, + RX_NORMAL_DESC3_OWN_LEN, 1); + + /* Make sure ownership is written to the descriptor */ + dma_wmb(); +} + +static void fxgmac_rx_desc_init(struct fxgmac_channel *channel) +{ + struct fxgmac_pdata *pdata = channel->pdata; + struct fxgmac_ring *ring = channel->rx_ring; + unsigned int start_index = ring->cur; + struct fxgmac_desc_data *desc_data; + unsigned int i; + + /* Initialize all descriptors */ + for (i = 0; i < ring->dma_desc_count; i++) { + desc_data = FXGMAC_GET_DESC_DATA(ring, i); + + /* Initialize Rx descriptor */ + fxgmac_rx_desc_reset(pdata, desc_data, i); + } + + /* Update the total number of Rx descriptors */ + writereg(pdata->pAdapter, ring->dma_desc_count - 1, + FXGMAC_DMA_REG(channel, DMA_CH_RDRLR)); + + /* Update the starting address of descriptor ring */ + desc_data = FXGMAC_GET_DESC_DATA(ring, start_index); + writereg(pdata->pAdapter, upper_32_bits(desc_data->dma_desc_addr), + FXGMAC_DMA_REG(channel, DMA_CH_RDLR_HI)); + writereg(pdata->pAdapter, lower_32_bits(desc_data->dma_desc_addr), + FXGMAC_DMA_REG(channel, DMA_CH_RDLR_LO)); + + /* Update the Rx Descriptor Tail Pointer */ + desc_data = FXGMAC_GET_DESC_DATA( + ring, start_index + ring->dma_desc_count - 1); + writereg(pdata->pAdapter, lower_32_bits(desc_data->dma_desc_addr), + FXGMAC_DMA_REG(channel, DMA_CH_RDTR_LO)); +} + +static int fxgmac_is_context_desc(struct fxgmac_dma_desc *dma_desc) +{ + /* Rx and Tx share CTXT bit, so check TDES3.CTXT bit */ + return FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, TX_NORMAL_DESC3_CTXT_POS, + TX_NORMAL_DESC3_CTXT_LEN); +} + +static int fxgmac_is_last_desc(struct fxgmac_dma_desc *dma_desc) +{ + /* Rx and Tx share LD bit, so check TDES3.LD bit */ + return FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, TX_NORMAL_DESC3_LD_POS, + TX_NORMAL_DESC3_LD_LEN); +} + +static int fxgmac_disable_tx_flow_control(struct fxgmac_pdata *pdata) +{ + unsigned int max_q_count, q_count; + unsigned int reg, regval; + unsigned int i; + + /* Clear MTL flow control */ + for (i = 0; i < pdata->rx_q_count; i++) { + regval = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); + regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_EHFC_POS, + MTL_Q_RQOMR_EHFC_LEN, 0); + writereg(pdata->pAdapter, regval, + FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); + } + + /* Clear MAC flow control */ + max_q_count = FXGMAC_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++) { + regval = readreg(pdata->pAdapter, pdata->mac_regs + reg); + regval = FXGMAC_SET_REG_BITS(regval, MAC_Q0TFCR_TFE_POS, + MAC_Q0TFCR_TFE_LEN, 0); + writereg(pdata->pAdapter, regval, pdata->mac_regs + reg); + + reg += MAC_QTFCR_INC; + } + + return 0; +} + +static int fxgmac_enable_tx_flow_control(struct fxgmac_pdata *pdata) +{ + unsigned int max_q_count, q_count; + unsigned int reg, regval; + unsigned int i; + + /* Set MTL flow control */ + for (i = 0; i < pdata->rx_q_count; i++) { + regval = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); + regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_EHFC_POS, + MTL_Q_RQOMR_EHFC_LEN, 1); + writereg(pdata->pAdapter, regval, + FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); + } + + /* Set MAC flow control */ + max_q_count = FXGMAC_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++) { + regval = readreg(pdata->pAdapter, pdata->mac_regs + reg); + + /* Enable transmit flow control */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_Q0TFCR_TFE_POS, + MAC_Q0TFCR_TFE_LEN, 1); + /* Set pause time */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_Q0TFCR_PT_POS, + MAC_Q0TFCR_PT_LEN, 0xffff); + + writereg(pdata->pAdapter, regval, pdata->mac_regs + reg); + + reg += MAC_QTFCR_INC; + } + + return 0; +} + +static int fxgmac_disable_rx_flow_control(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_RFCR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_RFCR_RFE_POS, MAC_RFCR_RFE_LEN, + 0); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_RFCR); + + return 0; +} + +static int fxgmac_enable_rx_flow_control(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_RFCR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_RFCR_RFE_POS, MAC_RFCR_RFE_LEN, + 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_RFCR); + + return 0; +} + +static int fxgmac_config_tx_flow_control(struct fxgmac_pdata *pdata) +{ + if (pdata->tx_pause) + fxgmac_enable_tx_flow_control(pdata); + else + fxgmac_disable_tx_flow_control(pdata); + + return 0; +} + +static int fxgmac_config_rx_flow_control(struct fxgmac_pdata *pdata) +{ + if (pdata->rx_pause) + fxgmac_enable_rx_flow_control(pdata); + else + fxgmac_disable_rx_flow_control(pdata); + + return 0; +} + +static int fxgmac_config_rx_coalesce(struct fxgmac_pdata *pdata) +{ +#ifndef DPDK + struct fxgmac_channel *channel; + unsigned int i; + u32 regval; + + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (!channel->rx_ring) + break; + + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_RIWT)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_RIWT_RWT_POS, + DMA_CH_RIWT_RWT_LEN, + pdata->rx_riwt); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_RIWT)); + } +#else + struct fxgmac_rx_queue *rxq; + unsigned int i; + + for (i = 0; i < pdata->expansion.eth_dev->data->nb_rx_queues; i++) { + rxq = pdata->expansion.eth_dev->data->rx_queues[i]; + FXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_RIWT, RWT, pdata->rx_riwt); + } +#endif + + return 0; +} + +static void fxgmac_config_rx_fep_disable(struct fxgmac_pdata *pdata) +{ + unsigned int i; + u32 regval; + + for (i = 0; i < pdata->rx_q_count; i++) { + regval = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); + /* 1:enable the rx queue forward packet with error + * status(crc error, gmii_er, watch dog timeout.or overflow) + */ + regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_FEP_POS, + MTL_Q_RQOMR_FEP_LEN, + MTL_FEP_ENABLE); + writereg(pdata->pAdapter, regval, + FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); + } +} + +static void fxgmac_config_rx_fup_enable(struct fxgmac_pdata *pdata) +{ + unsigned int i; + u32 regval; + + for (i = 0; i < pdata->rx_q_count; i++) { + regval = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); + regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_FUP_POS, + MTL_Q_RQOMR_FUP_LEN, 1); + writereg(pdata->pAdapter, regval, + FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); + } +} + +static int fxgmac_config_tx_coalesce(struct fxgmac_pdata *pdata) +{ + pdata = pdata; + return 0; +} + +static void fxgmac_config_rx_buffer_size(struct fxgmac_pdata *pdata) +{ +#ifndef DPDK + struct fxgmac_channel *channel; + unsigned int i; + u32 regval; + + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (!channel->rx_ring) + break; + + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_RCR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_RCR_RBSZ_POS, + DMA_CH_RCR_RBSZ_LEN, + pdata->rx_buf_size); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_RCR)); + } +#else + struct fxgmac_rx_queue *rxq; + unsigned int i; + + for (i = 0; i < pdata->expansion.eth_dev->data->nb_rx_queues; i++) { + rxq = pdata->expansion.eth_dev->data->rx_queues[i]; + + rxq->buf_size = rte_pktmbuf_data_room_size(rxq->mb_pool) - + RTE_PKTMBUF_HEADROOM; + rxq->buf_size = (rxq->buf_size + FXGMAC_RX_BUF_ALIGN - 1) & + ~(FXGMAC_RX_BUF_ALIGN - 1); + + if (rxq->buf_size > pdata->rx_buf_size) + pdata->rx_buf_size = rxq->buf_size; + + FXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_RCR, RBSZ, rxq->buf_size); + } +#endif +} + +static void fxgmac_config_tso_mode(struct fxgmac_pdata *pdata) +{ +#ifndef DPDK + struct fxgmac_channel *channel; + unsigned int i; + u32 regval; + + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (!channel->tx_ring) + break; + + if (pdata->hw_feat.tso) { + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_TCR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_TCR_TSE_POS, + DMA_CH_TCR_TSE_LEN, 1); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_TCR)); + } + } +#else + struct fxgmac_tx_queue *txq; + unsigned int i; + for (i = 0; i < pdata->expansion.eth_dev->data->nb_tx_queues; i++) { + txq = pdata->expansion.eth_dev->data->tx_queues[i]; + FXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, TSE, pdata->tx_pbl); + } +#endif +} + +static void fxgmac_config_sph_mode(struct fxgmac_pdata *pdata) +{ + unsigned int i; + u32 regval; + +#ifndef DPDK + struct fxgmac_channel *channel; + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (!channel->rx_ring) + break; + + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_CR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_CR_SPH_POS, + DMA_CH_CR_SPH_LEN, 0); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_CR)); + } +#else + struct fxgmac_rx_queue *rxq; + + for (i = 0; i < pdata->expansion.eth_dev->data->nb_rx_queues; i++) { + rxq = pdata->expansion.eth_dev->data->rx_queues[i]; + FXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_CR, SPH, pdata->rx_pbl); + } +#endif + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_ECR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_ECR_HDSMS_POS, + MAC_ECR_HDSMS_LEN, FXGMAC_SPH_HDSMS_SIZE); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_ECR); +} + +static unsigned int fxgmac_usec_to_riwt(struct fxgmac_pdata *pdata, + unsigned int usec) +{ + unsigned long rate; + unsigned int ret; + + 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; + + return ret; +} + +static unsigned int fxgmac_riwt_to_usec(struct fxgmac_pdata *pdata, + unsigned int riwt) +{ + unsigned long rate; + unsigned int ret; + + 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); + + return ret; +} + +static int fxgmac_config_rx_threshold(struct fxgmac_pdata *pdata, + unsigned int val) +{ + unsigned int i; + u32 regval; + + for (i = 0; i < pdata->rx_q_count; i++) { + regval = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); + regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_RTC_POS, + MTL_Q_RQOMR_RTC_LEN, val); + writereg(pdata->pAdapter, regval, + FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); + } + + return 0; +} + +static void fxgmac_config_mtl_mode(struct fxgmac_pdata *pdata) +{ + unsigned int i; + u32 regval; + + /* Set Tx to weighted round robin scheduling algorithm */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MTL_OMR); + regval = FXGMAC_SET_REG_BITS(regval, MTL_OMR_ETSALG_POS, + MTL_OMR_ETSALG_LEN, MTL_ETSALG_WRR); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MTL_OMR); + + /* Set Tx traffic classes to use WRR algorithm with equal weights */ + for (i = 0; i < pdata->tx_q_count /*hw_feat.tc_cnt*/; i++) { + regval = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_TC_QWR)); + regval = FXGMAC_SET_REG_BITS(regval, MTL_TC_QWR_QW_POS, + MTL_TC_QWR_QW_LEN, 1); + writereg(pdata->pAdapter, regval, + FXGMAC_MTL_REG(pdata, i, MTL_TC_QWR)); + } + + /* Set Rx to strict priority algorithm */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MTL_OMR); + regval = FXGMAC_SET_REG_BITS(regval, MTL_OMR_RAA_POS, MTL_OMR_RAA_LEN, + MTL_RAA_SP); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MTL_OMR); +} + +static void fxgmac_config_queue_mapping(struct fxgmac_pdata *pdata) +{ + unsigned int ppq, ppq_extra, prio, prio_queues; + unsigned int queue; + unsigned int reg, regval; + unsigned int mask; + unsigned int i, j; + + /* Map the MTL Tx Queues to Traffic Classes + * Note: Tx Queues >= Traffic Classes + */ + queue = 0; + DPRINTK("need to map TXq(%u) to TC\n", queue); + + /* 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; + regval = 0; + for (i = 0, prio = 0; i < prio_queues;) { + mask = 0; + for (j = 0; j < ppq; j++) { + netif_dbg(pdata, drv, pdata->netdev, + "PRIO%u mapped to RXq%u\n", prio, i); + mask |= (1 << prio); + prio++; + } + + if (i < ppq_extra) { + netif_dbg(pdata, drv, pdata->netdev, + "PRIO%u mapped to RXq%u\n", prio, i); + mask |= (1 << prio); + prio++; + } + + regval |= (mask << ((i++ % MAC_RQC2_Q_PER_REG) << 3)); + + if ((i % MAC_RQC2_Q_PER_REG) && (i != prio_queues)) + continue; + + writereg(pdata->pAdapter, regval, pdata->mac_regs + reg); + reg += MAC_RQC2_INC; + regval = 0; + } + + /* Configure one to one, MTL Rx queue to DMA Rx channel mapping + * ie Q0 <--> CH0, Q1 <--> CH1 ... Q11 <--> CH11 + */ + reg = MTL_RQDCM0R; + regval = readreg(pdata->pAdapter, pdata->mac_regs + reg); + regval |= (MTL_RQDCM0R_Q0MDMACH | MTL_RQDCM0R_Q1MDMACH | + MTL_RQDCM0R_Q2MDMACH | MTL_RQDCM0R_Q3MDMACH); + + if (pdata->rss) { + /* in version later 0617, need to enable DA-based DMA Channel Selection to let RSS work, + * ie, bit4,12,20,28 for Q0,1,2,3 individual + */ + regval |= (MTL_RQDCM0R_Q0DDMACH | MTL_RQDCM0R_Q1DDMACH | + MTL_RQDCM0R_Q2DDMACH | MTL_RQDCM0R_Q3DDMACH); + } + + writereg(pdata->pAdapter, regval, pdata->mac_regs + reg); + + reg += MTL_RQDCM_INC; + regval = readreg(pdata->pAdapter, pdata->mac_regs + reg); + regval |= (MTL_RQDCM1R_Q4MDMACH | MTL_RQDCM1R_Q5MDMACH | + MTL_RQDCM1R_Q6MDMACH | MTL_RQDCM1R_Q7MDMACH); + writereg(pdata->pAdapter, regval, pdata->mac_regs + reg); +} + +static unsigned int fxgmac_calculate_per_queue_fifo(unsigned int fifo_size, + unsigned int queue_count) +{ + unsigned int q_fifo_size; + unsigned int p_fifo; + + /* Calculate the configured fifo size */ + q_fifo_size = 1 << (fifo_size + 7); + + /* The configured value may not be the actual amount of fifo RAM */ + q_fifo_size = min_t(unsigned int, FXGMAC_MAX_FIFO, q_fifo_size); + + q_fifo_size = q_fifo_size / queue_count; + + /* Each increment in the queue fifo size represents 256 bytes of + * fifo, with 0 representing 256 bytes. Distribute the fifo equally + * between the queues. + */ + p_fifo = q_fifo_size / 256; + if (p_fifo) + p_fifo--; + + return p_fifo; +} + +static void fxgmac_config_tx_fifo_size(struct fxgmac_pdata *pdata) +{ + unsigned int fifo_size; + unsigned int i; + u32 regval; + + fifo_size = fxgmac_calculate_per_queue_fifo(pdata->hw_feat.tx_fifo_size, + pdata->tx_q_count); + + for (i = 0; i < pdata->tx_q_count; i++) { + regval = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); + regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_TQS_POS, + MTL_Q_TQOMR_TQS_LEN, fifo_size); + writereg(pdata->pAdapter, regval, + FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); + } + + netif_info(pdata, drv, pdata->netdev, + "%d Tx hardware queues, %d byte fifo per queue\n", + pdata->tx_q_count, ((fifo_size + 1) * 256)); +} + +static void fxgmac_config_rx_fifo_size(struct fxgmac_pdata *pdata) +{ + unsigned int fifo_size; + unsigned int i; + u32 regval; + + fifo_size = fxgmac_calculate_per_queue_fifo(pdata->hw_feat.rx_fifo_size, + pdata->rx_q_count); + + for (i = 0; i < pdata->rx_q_count; i++) { + regval = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); + regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_RQS_POS, + MTL_Q_RQOMR_RQS_LEN, fifo_size); + writereg(pdata->pAdapter, regval, + FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); + } + + netif_info(pdata, drv, pdata->netdev, + "%d Rx hardware queues, %d byte fifo per queue\n", + pdata->rx_q_count, ((fifo_size + 1) * 256)); +} + +static void fxgmac_config_flow_control_threshold(struct fxgmac_pdata *pdata) +{ + unsigned int i; + u32 regval; + + for (i = 0; i < pdata->rx_q_count; i++) { + regval = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); + /* Activate flow control when less than 6k left in fifo */ + regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_RFA_POS, + MTL_Q_RQOMR_RFA_LEN, 6); + /* De-activate flow control when more than 10k left in fifo */ + regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_RFD_POS, + MTL_Q_RQOMR_RFD_LEN, 10); + writereg(pdata->pAdapter, regval, + FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); + } +} + +static int fxgmac_config_tx_threshold(struct fxgmac_pdata *pdata, + unsigned int val) +{ + unsigned int i; + u32 regval; + + for (i = 0; i < pdata->tx_q_count; i++) { + regval = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); + regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_TTC_POS, + MTL_Q_TQOMR_TTC_LEN, val); + writereg(pdata->pAdapter, regval, + FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); + } + + return 0; +} + +static int fxgmac_config_rsf_mode(struct fxgmac_pdata *pdata, unsigned int val) +{ + unsigned int i; + u32 regval; + + for (i = 0; i < pdata->rx_q_count; i++) { + regval = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); + regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_RSF_POS, + MTL_Q_RQOMR_RSF_LEN, val); + writereg(pdata->pAdapter, regval, + FXGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR)); + } + + return 0; +} + +static int fxgmac_config_tsf_mode(struct fxgmac_pdata *pdata, unsigned int val) +{ + unsigned int i; + u32 regval; + + for (i = 0; i < pdata->tx_q_count; i++) { + regval = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); + regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_TSF_POS, + MTL_Q_TQOMR_TSF_LEN, val); + writereg(pdata->pAdapter, regval, + FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); + } + + return 0; +} + +static int fxgmac_config_osp_mode(struct fxgmac_pdata *pdata) +{ +#ifndef DPDK + struct fxgmac_channel *channel; + unsigned int i; + u32 regval; + + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (!channel->tx_ring) + break; + + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_TCR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_TCR_OSP_POS, + DMA_CH_TCR_OSP_LEN, + pdata->tx_osp_mode); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_TCR)); + } +#else + /* Force DMA to operate on second packet before closing descriptors + * of first packet + */ + struct fxgmac_tx_queue *txq; + unsigned int i; + + for (i = 0; i < pdata->expansion.eth_dev->data->nb_tx_queues; i++) { + txq = pdata->expansion.eth_dev->data->tx_queues[i]; + FXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, OSP, + pdata->tx_osp_mode); + } +#endif + return 0; +} + +static int fxgmac_config_pblx8(struct fxgmac_pdata *pdata) +{ +#ifndef DPDK + struct fxgmac_channel *channel; + unsigned int i; + u32 regval; + + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_CR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_CR_PBLX8_POS, + DMA_CH_CR_PBLX8_LEN, pdata->pblx8); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_CR)); + } +#else + struct fxgmac_tx_queue *txq; + unsigned int i; + + for (i = 0; i < pdata->expansion.eth_dev->data->nb_tx_queues; i++) { + txq = pdata->expansion.eth_dev->data->tx_queues[i]; + FXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_CR, PBLX8, pdata->pblx8); + } +#endif + + return 0; +} + +static int fxgmac_get_tx_pbl_val(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(pdata->channel_head, DMA_CH_TCR)); + regval = FXGMAC_GET_REG_BITS(regval, DMA_CH_TCR_PBL_POS, + DMA_CH_TCR_PBL_LEN); + return regval; +} + +static int fxgmac_config_tx_pbl_val(struct fxgmac_pdata *pdata) +{ +#ifndef DPDK + struct fxgmac_channel *channel; + unsigned int i; + u32 regval; + + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (!channel->tx_ring) + break; + + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_TCR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_TCR_PBL_POS, + DMA_CH_TCR_PBL_LEN, pdata->tx_pbl); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_TCR)); + } +#else + struct fxgmac_tx_queue *txq; + unsigned int i; + + for (i = 0; i < pdata->expansion.eth_dev->data->nb_tx_queues; i++) { + txq = pdata->expansion.eth_dev->data->tx_queues[i]; + FXGMAC_DMA_IOWRITE_BITS(txq, DMA_CH_TCR, PBL, pdata->tx_pbl); + } +#endif + + return 0; +} + +static int fxgmac_get_rx_pbl_val(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(pdata->channel_head, DMA_CH_RCR)); + regval = FXGMAC_GET_REG_BITS(regval, DMA_CH_RCR_PBL_POS, + DMA_CH_RCR_PBL_LEN); + return regval; +} + +static int fxgmac_config_rx_pbl_val(struct fxgmac_pdata *pdata) +{ +#ifndef DPDK + struct fxgmac_channel *channel; + unsigned int i; + u32 regval; + + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (!channel->rx_ring) + break; + + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_RCR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_RCR_PBL_POS, + DMA_CH_RCR_PBL_LEN, pdata->rx_pbl); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_RCR)); + } +#else + struct fxgmac_rx_queue *rxq; + unsigned int i; + + for (i = 0; i < pdata->expansion.eth_dev->data->nb_rx_queues; i++) { + rxq = pdata->expansion.eth_dev->data->rx_queues[i]; + FXGMAC_DMA_IOWRITE_BITS(rxq, DMA_CH_RCR, PBL, pdata->rx_pbl); + } +#endif + + return 0; +} + +static u64 fxgmac_mmc_read(struct fxgmac_pdata *pdata, unsigned int reg_lo) +{ + /* bool read_hi; */ + u64 val; + val = (u64)readreg(pdata->pAdapter, pdata->mac_regs + reg_lo); + + return val; +} + +static void fxgmac_tx_mmc_int(struct fxgmac_pdata *pdata) +{ + unsigned int mmc_isr = + readreg(pdata->pAdapter, pdata->mac_regs + MMC_TISR); + struct fxgmac_stats *stats = &pdata->stats; + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXOCTETCOUNT_GB_POS, + MMC_TISR_TXOCTETCOUNT_GB_LEN)) + stats->txoctetcount_gb += + fxgmac_mmc_read(pdata, MMC_TXOCTETCOUNT_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXFRAMECOUNT_GB_POS, + MMC_TISR_TXFRAMECOUNT_GB_LEN)) + stats->txframecount_gb += + fxgmac_mmc_read(pdata, MMC_TXFRAMECOUNT_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXBROADCASTFRAMES_G_POS, + MMC_TISR_TXBROADCASTFRAMES_G_LEN)) + stats->txbroadcastframes_g += + fxgmac_mmc_read(pdata, MMC_TXBROADCASTFRAMES_G_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXMULTICASTFRAMES_G_POS, + MMC_TISR_TXMULTICASTFRAMES_G_LEN)) + stats->txmulticastframes_g += + fxgmac_mmc_read(pdata, MMC_TXMULTICASTFRAMES_G_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TX64OCTETS_GB_POS, + MMC_TISR_TX64OCTETS_GB_LEN)) + stats->tx64octets_gb += + fxgmac_mmc_read(pdata, MMC_TX64OCTETS_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TX65TO127OCTETS_GB_POS, + MMC_TISR_TX65TO127OCTETS_GB_LEN)) + stats->tx65to127octets_gb += + fxgmac_mmc_read(pdata, MMC_TX65TO127OCTETS_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TX128TO255OCTETS_GB_POS, + MMC_TISR_TX128TO255OCTETS_GB_LEN)) + stats->tx128to255octets_gb += + fxgmac_mmc_read(pdata, MMC_TX128TO255OCTETS_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TX256TO511OCTETS_GB_POS, + MMC_TISR_TX256TO511OCTETS_GB_LEN)) + stats->tx256to511octets_gb += + fxgmac_mmc_read(pdata, MMC_TX256TO511OCTETS_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TX512TO1023OCTETS_GB_POS, + MMC_TISR_TX512TO1023OCTETS_GB_LEN)) + stats->tx512to1023octets_gb += + fxgmac_mmc_read(pdata, MMC_TX512TO1023OCTETS_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TX1024TOMAXOCTETS_GB_POS, + MMC_TISR_TX1024TOMAXOCTETS_GB_LEN)) + stats->tx1024tomaxoctets_gb += + fxgmac_mmc_read(pdata, MMC_TX1024TOMAXOCTETS_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXUNICASTFRAMES_GB_POS, + MMC_TISR_TXUNICASTFRAMES_GB_LEN)) + stats->txunicastframes_gb += + fxgmac_mmc_read(pdata, MMC_TXUNICASTFRAMES_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXMULTICASTFRAMES_GB_POS, + MMC_TISR_TXMULTICASTFRAMES_GB_LEN)) + stats->txmulticastframes_gb += + fxgmac_mmc_read(pdata, MMC_TXMULTICASTFRAMES_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXBROADCASTFRAMES_GB_POS, + MMC_TISR_TXBROADCASTFRAMES_GB_LEN)) + stats->txbroadcastframes_g += + fxgmac_mmc_read(pdata, MMC_TXBROADCASTFRAMES_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXUNDERFLOWERROR_POS, + MMC_TISR_TXUNDERFLOWERROR_LEN)) + stats->txunderflowerror += + fxgmac_mmc_read(pdata, MMC_TXUNDERFLOWERROR_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXSINGLECOLLISION_G_POS, + MMC_TISR_TXSINGLECOLLISION_G_LEN)) + stats->txsinglecollision_g += + fxgmac_mmc_read(pdata, MMC_TXSINGLECOLLISION_G); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXMULTIPLECOLLISION_G_POS, + MMC_TISR_TXMULTIPLECOLLISION_G_LEN)) + stats->txmultiplecollision_g += + fxgmac_mmc_read(pdata, MMC_TXMULTIPLECOLLISION_G); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXDEFERREDFRAMES_POS, + MMC_TISR_TXDEFERREDFRAMES_LEN)) + stats->txdeferredframes += + fxgmac_mmc_read(pdata, MMC_TXDEFERREDFRAMES); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXLATECOLLISIONFRAMES_POS, + MMC_TISR_TXLATECOLLISIONFRAMES_LEN)) + stats->txlatecollisionframes += + fxgmac_mmc_read(pdata, MMC_TXLATECOLLISIONFRAMES); + + if (FXGMAC_GET_REG_BITS(mmc_isr, + MMC_TISR_TXEXCESSIVECOLLISIONFRAMES_POS, + MMC_TISR_TXEXCESSIVECOLLISIONFRAMES_LEN)) + stats->txexcessivecollisionframes += + fxgmac_mmc_read(pdata, MMC_TXEXCESSIVECOLLSIONFRAMES); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXCARRIERERRORFRAMES_POS, + MMC_TISR_TXCARRIERERRORFRAMES_LEN)) + stats->txcarriererrorframes += + fxgmac_mmc_read(pdata, MMC_TXCARRIERERRORFRAMES); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXOCTETCOUNT_G_POS, + MMC_TISR_TXOCTETCOUNT_G_LEN)) + stats->txoctetcount_g += + fxgmac_mmc_read(pdata, MMC_TXOCTETCOUNT_G_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXFRAMECOUNT_G_POS, + MMC_TISR_TXFRAMECOUNT_G_LEN)) + stats->txframecount_g += + fxgmac_mmc_read(pdata, MMC_TXFRAMECOUNT_G_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXEXCESSIVEDEFERRALFRAMES_POS, + MMC_TISR_TXEXCESSIVEDEFERRALFRAMES_LEN)) + stats->txexcessivedeferralerror += + fxgmac_mmc_read(pdata, MMC_TXEXCESSIVEDEFERRALERROR); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXPAUSEFRAMES_POS, + MMC_TISR_TXPAUSEFRAMES_LEN)) + stats->txpauseframes += + fxgmac_mmc_read(pdata, MMC_TXPAUSEFRAMES_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXVLANFRAMES_G_POS, + MMC_TISR_TXVLANFRAMES_G_LEN)) + stats->txvlanframes_g += + fxgmac_mmc_read(pdata, MMC_TXVLANFRAMES_G_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_TISR_TXOVERSIZE_G_POS, + MMC_TISR_TXOVERSIZE_G_LEN)) + stats->txoversize_g += + fxgmac_mmc_read(pdata, MMC_TXOVERSIZEFRAMES); +} + +static void fxgmac_rx_mmc_int(struct fxgmac_pdata *pdata) +{ + unsigned int mmc_isr = + readreg(pdata->pAdapter, pdata->mac_regs + MMC_RISR); + struct fxgmac_stats *stats = &pdata->stats; + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXFRAMECOUNT_GB_POS, + MMC_RISR_RXFRAMECOUNT_GB_LEN)) + stats->rxframecount_gb += + fxgmac_mmc_read(pdata, MMC_RXFRAMECOUNT_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXOCTETCOUNT_GB_POS, + MMC_RISR_RXOCTETCOUNT_GB_LEN)) + stats->rxoctetcount_gb += + fxgmac_mmc_read(pdata, MMC_RXOCTETCOUNT_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXOCTETCOUNT_G_POS, + MMC_RISR_RXOCTETCOUNT_G_LEN)) + stats->rxoctetcount_g += + fxgmac_mmc_read(pdata, MMC_RXOCTETCOUNT_G_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXBROADCASTFRAMES_G_POS, + MMC_RISR_RXBROADCASTFRAMES_G_LEN)) + stats->rxbroadcastframes_g += + fxgmac_mmc_read(pdata, MMC_RXBROADCASTFRAMES_G_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXMULTICASTFRAMES_G_POS, + MMC_RISR_RXMULTICASTFRAMES_G_LEN)) + stats->rxmulticastframes_g += + fxgmac_mmc_read(pdata, MMC_RXMULTICASTFRAMES_G_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXCRCERROR_POS, + MMC_RISR_RXCRCERROR_LEN)) + stats->rxcrcerror += fxgmac_mmc_read(pdata, MMC_RXCRCERROR_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXALIGNERROR_POS, + MMC_RISR_RXALIGNERROR_LEN)) + stats->rxalignerror += fxgmac_mmc_read(pdata, MMC_RXALIGNERROR); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXRUNTERROR_POS, + MMC_RISR_RXRUNTERROR_LEN)) + stats->rxrunterror += fxgmac_mmc_read(pdata, MMC_RXRUNTERROR); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXJABBERERROR_POS, + MMC_RISR_RXJABBERERROR_LEN)) + stats->rxjabbererror += + fxgmac_mmc_read(pdata, MMC_RXJABBERERROR); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXUNDERSIZE_G_POS, + MMC_RISR_RXUNDERSIZE_G_LEN)) + stats->rxundersize_g += + fxgmac_mmc_read(pdata, MMC_RXUNDERSIZE_G); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXOVERSIZE_G_POS, + MMC_RISR_RXOVERSIZE_G_LEN)) + stats->rxoversize_g += fxgmac_mmc_read(pdata, MMC_RXOVERSIZE_G); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RX64OCTETS_GB_POS, + MMC_RISR_RX64OCTETS_GB_LEN)) + stats->rx64octets_gb += + fxgmac_mmc_read(pdata, MMC_RX64OCTETS_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RX65TO127OCTETS_GB_POS, + MMC_RISR_RX65TO127OCTETS_GB_LEN)) + stats->rx65to127octets_gb += + fxgmac_mmc_read(pdata, MMC_RX65TO127OCTETS_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RX128TO255OCTETS_GB_POS, + MMC_RISR_RX128TO255OCTETS_GB_LEN)) + stats->rx128to255octets_gb += + fxgmac_mmc_read(pdata, MMC_RX128TO255OCTETS_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RX256TO511OCTETS_GB_POS, + MMC_RISR_RX256TO511OCTETS_GB_LEN)) + stats->rx256to511octets_gb += + fxgmac_mmc_read(pdata, MMC_RX256TO511OCTETS_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RX512TO1023OCTETS_GB_POS, + MMC_RISR_RX512TO1023OCTETS_GB_LEN)) + stats->rx512to1023octets_gb += + fxgmac_mmc_read(pdata, MMC_RX512TO1023OCTETS_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RX1024TOMAXOCTETS_GB_POS, + MMC_RISR_RX1024TOMAXOCTETS_GB_LEN)) + stats->rx1024tomaxoctets_gb += + fxgmac_mmc_read(pdata, MMC_RX1024TOMAXOCTETS_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXUNICASTFRAMES_G_POS, + MMC_RISR_RXUNICASTFRAMES_G_LEN)) + stats->rxunicastframes_g += + fxgmac_mmc_read(pdata, MMC_RXUNICASTFRAMES_G_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXLENGTHERROR_POS, + MMC_RISR_RXLENGTHERROR_LEN)) + stats->rxlengtherror += + fxgmac_mmc_read(pdata, MMC_RXLENGTHERROR_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXOUTOFRANGETYPE_POS, + MMC_RISR_RXOUTOFRANGETYPE_LEN)) + stats->rxoutofrangetype += + fxgmac_mmc_read(pdata, MMC_RXOUTOFRANGETYPE_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXPAUSEFRAMES_POS, + MMC_RISR_RXPAUSEFRAMES_LEN)) + stats->rxpauseframes += + fxgmac_mmc_read(pdata, MMC_RXPAUSEFRAMES_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXFIFOOVERFLOW_POS, + MMC_RISR_RXFIFOOVERFLOW_LEN)) + stats->rxfifooverflow += + fxgmac_mmc_read(pdata, MMC_RXFIFOOVERFLOW_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXVLANFRAMES_GB_POS, + MMC_RISR_RXVLANFRAMES_GB_LEN)) + stats->rxvlanframes_gb += + fxgmac_mmc_read(pdata, MMC_RXVLANFRAMES_GB_LO); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXWATCHDOGERROR_POS, + MMC_RISR_RXWATCHDOGERROR_LEN)) + stats->rxwatchdogerror += + fxgmac_mmc_read(pdata, MMC_RXWATCHDOGERROR); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXERRORFRAMES_POS, + MMC_RISR_RXERRORFRAMES_LEN)) + stats->rxreceiveerrorframe += + fxgmac_mmc_read(pdata, MMC_RXRECEIVEERRORFRAME); + + if (FXGMAC_GET_REG_BITS(mmc_isr, MMC_RISR_RXERRORCONTROLFRAMES_POS, + MMC_RISR_RXERRORCONTROLFRAMES_LEN)) + stats->rxcontrolframe_g += + fxgmac_mmc_read(pdata, MMC_RXCONTROLFRAME_G); +} + +static void fxgmac_read_mmc_stats(struct fxgmac_pdata *pdata) +{ + struct fxgmac_stats *stats = &pdata->stats; + u32 regval; + + /* Freeze counters */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MMC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MMC_CR_MCF_POS, MMC_CR_MCF_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MMC_CR); + + stats->txoctetcount_gb += + fxgmac_mmc_read(pdata, MMC_TXOCTETCOUNT_GB_LO); + + stats->txframecount_gb += + fxgmac_mmc_read(pdata, MMC_TXFRAMECOUNT_GB_LO); + + stats->txbroadcastframes_g += + fxgmac_mmc_read(pdata, MMC_TXBROADCASTFRAMES_G_LO); + + stats->txmulticastframes_g += + fxgmac_mmc_read(pdata, MMC_TXMULTICASTFRAMES_G_LO); + + stats->tx64octets_gb += fxgmac_mmc_read(pdata, MMC_TX64OCTETS_GB_LO); + + stats->tx65to127octets_gb += + fxgmac_mmc_read(pdata, MMC_TX65TO127OCTETS_GB_LO); + + stats->tx128to255octets_gb += + fxgmac_mmc_read(pdata, MMC_TX128TO255OCTETS_GB_LO); + + stats->tx256to511octets_gb += + fxgmac_mmc_read(pdata, MMC_TX256TO511OCTETS_GB_LO); + + stats->tx512to1023octets_gb += + fxgmac_mmc_read(pdata, MMC_TX512TO1023OCTETS_GB_LO); + + stats->tx1024tomaxoctets_gb += + fxgmac_mmc_read(pdata, MMC_TX1024TOMAXOCTETS_GB_LO); + + stats->txunicastframes_gb += + fxgmac_mmc_read(pdata, MMC_TXUNICASTFRAMES_GB_LO); + + stats->txmulticastframes_gb += + fxgmac_mmc_read(pdata, MMC_TXMULTICASTFRAMES_GB_LO); + + stats->txbroadcastframes_g += + fxgmac_mmc_read(pdata, MMC_TXBROADCASTFRAMES_GB_LO); + + stats->txunderflowerror += + fxgmac_mmc_read(pdata, MMC_TXUNDERFLOWERROR_LO); + + stats->txsinglecollision_g += + fxgmac_mmc_read(pdata, MMC_TXSINGLECOLLISION_G); + + stats->txmultiplecollision_g += + fxgmac_mmc_read(pdata, MMC_TXMULTIPLECOLLISION_G); + + stats->txdeferredframes += fxgmac_mmc_read(pdata, MMC_TXDEFERREDFRAMES); + + stats->txlatecollisionframes += + fxgmac_mmc_read(pdata, MMC_TXLATECOLLISIONFRAMES); + + stats->txexcessivecollisionframes += + fxgmac_mmc_read(pdata, MMC_TXEXCESSIVECOLLSIONFRAMES); + + stats->txcarriererrorframes += + fxgmac_mmc_read(pdata, MMC_TXCARRIERERRORFRAMES); + + stats->txoctetcount_g += fxgmac_mmc_read(pdata, MMC_TXOCTETCOUNT_G_LO); + + stats->txframecount_g += fxgmac_mmc_read(pdata, MMC_TXFRAMECOUNT_G_LO); + + stats->txexcessivedeferralerror += + fxgmac_mmc_read(pdata, MMC_TXEXCESSIVEDEFERRALERROR); + + stats->txpauseframes += fxgmac_mmc_read(pdata, MMC_TXPAUSEFRAMES_LO); + + stats->txvlanframes_g += fxgmac_mmc_read(pdata, MMC_TXVLANFRAMES_G_LO); + + stats->txoversize_g += fxgmac_mmc_read(pdata, MMC_TXOVERSIZEFRAMES); + + stats->rxframecount_gb += + fxgmac_mmc_read(pdata, MMC_RXFRAMECOUNT_GB_LO); + + stats->rxoctetcount_gb += + fxgmac_mmc_read(pdata, MMC_RXOCTETCOUNT_GB_LO); + + stats->rxoctetcount_g += fxgmac_mmc_read(pdata, MMC_RXOCTETCOUNT_G_LO); + + stats->rxbroadcastframes_g += + fxgmac_mmc_read(pdata, MMC_RXBROADCASTFRAMES_G_LO); + + stats->rxmulticastframes_g += + fxgmac_mmc_read(pdata, MMC_RXMULTICASTFRAMES_G_LO); + + stats->rxcrcerror += fxgmac_mmc_read(pdata, MMC_RXCRCERROR_LO); + + stats->rxalignerror += fxgmac_mmc_read(pdata, MMC_RXALIGNERROR); + + stats->rxrunterror += fxgmac_mmc_read(pdata, MMC_RXRUNTERROR); + + stats->rxjabbererror += fxgmac_mmc_read(pdata, MMC_RXJABBERERROR); + + stats->rxundersize_g += fxgmac_mmc_read(pdata, MMC_RXUNDERSIZE_G); + + stats->rxoversize_g += fxgmac_mmc_read(pdata, MMC_RXOVERSIZE_G); + + stats->rx64octets_gb += fxgmac_mmc_read(pdata, MMC_RX64OCTETS_GB_LO); + + stats->rx65to127octets_gb += + fxgmac_mmc_read(pdata, MMC_RX65TO127OCTETS_GB_LO); + + stats->rx128to255octets_gb += + fxgmac_mmc_read(pdata, MMC_RX128TO255OCTETS_GB_LO); + + stats->rx256to511octets_gb += + fxgmac_mmc_read(pdata, MMC_RX256TO511OCTETS_GB_LO); + + stats->rx512to1023octets_gb += + fxgmac_mmc_read(pdata, MMC_RX512TO1023OCTETS_GB_LO); + + stats->rx1024tomaxoctets_gb += + fxgmac_mmc_read(pdata, MMC_RX1024TOMAXOCTETS_GB_LO); + + stats->rxunicastframes_g += + fxgmac_mmc_read(pdata, MMC_RXUNICASTFRAMES_G_LO); + + stats->rxlengtherror += fxgmac_mmc_read(pdata, MMC_RXLENGTHERROR_LO); + + stats->rxoutofrangetype += + fxgmac_mmc_read(pdata, MMC_RXOUTOFRANGETYPE_LO); + + stats->rxpauseframes += fxgmac_mmc_read(pdata, MMC_RXPAUSEFRAMES_LO); + + stats->rxfifooverflow += fxgmac_mmc_read(pdata, MMC_RXFIFOOVERFLOW_LO); + + stats->rxvlanframes_gb += + fxgmac_mmc_read(pdata, MMC_RXVLANFRAMES_GB_LO); + + stats->rxwatchdogerror += fxgmac_mmc_read(pdata, MMC_RXWATCHDOGERROR); + + stats->rxreceiveerrorframe += + fxgmac_mmc_read(pdata, MMC_RXRECEIVEERRORFRAME); + + stats->rxcontrolframe_g += fxgmac_mmc_read(pdata, MMC_RXCONTROLFRAME_G); + + /* Un-freeze counters */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MMC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MMC_CR_MCF_POS, MMC_CR_MCF_LEN, 0); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MMC_CR); +} + +static void fxgmac_config_mmc(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MMC_CR); + /* Set counters to reset on read */ + regval = FXGMAC_SET_REG_BITS(regval, MMC_CR_ROR_POS, MMC_CR_ROR_LEN, 1); + /* Reset the counters */ + regval = FXGMAC_SET_REG_BITS(regval, MMC_CR_CR_POS, MMC_CR_CR_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MMC_CR); + +#if defined(FUXI_MISC_INT_HANDLE_FEATURE_EN) && FUXI_MISC_INT_HANDLE_FEATURE_EN + writereg(pdata->pAdapter, 0xffffffff, + pdata->mac_regs + MMC_IPCRXINTMASK); +#endif +} + +static int fxgmac_write_rss_reg(struct fxgmac_pdata *pdata, unsigned int type, + unsigned int index, unsigned int val) +{ + int ret = 0; + type = type; + + writereg(pdata->pAdapter, val, (pdata->base_mem + index)); + + return ret; +} + +static u32 fxgmac_read_rss_options(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_RSS_CTRL); + + /* Get the RSS options bits */ + regval = FXGMAC_GET_REG_BITS(regval, MGMT_RSS_CTRL_OPT_POS, + MGMT_RSS_CTRL_OPT_LEN); + + return regval; +} + +static int fxgmac_write_rss_options(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_RSS_CTRL); + + /* Set the RSS options */ + regval = FXGMAC_SET_REG_BITS(regval, MGMT_RSS_CTRL_OPT_POS, + MGMT_RSS_CTRL_OPT_LEN, pdata->rss_options); + + writereg(pdata->pAdapter, regval, (pdata->base_mem + MGMT_RSS_CTRL)); + + return 0; +} + +#if !defined(DPDK) +static int fxgmac_read_rss_hash_key(struct fxgmac_pdata *pdata, u8 *key_buf) +{ + unsigned int key_regs = sizeof(pdata->rss_key) / sizeof(u32); + u32 *key = (u32 *)key_buf; + + while (key_regs--) { + (*key) = cpu_to_be32(readreg( + pdata->pAdapter, + pdata->base_mem + (MGMT_RSS_KEY0 + + key_regs * MGMT_RSS_KEY_REG_INC))); + + DBGPRINT( + MP_LOUD, + ("fxgmac_read_rss_hash_key: idx=%d, reg=%x, key=0x%08x\n", + key_regs, + MGMT_RSS_KEY0 + key_regs * MGMT_RSS_KEY_REG_INC, + (u32)(*key))); + key++; + } + + return 0; +} +#endif + +static int fxgmac_write_rss_hash_key(struct fxgmac_pdata *pdata) +{ + unsigned int key_regs = sizeof(pdata->rss_key) / sizeof(u32); + u32 *key = (u32 *)&pdata->rss_key; + int ret; + + while (key_regs--) { + ret = fxgmac_write_rss_reg( + pdata, FXGMAC_RSS_HASH_KEY_TYPE, + MGMT_RSS_KEY0 + key_regs * MGMT_RSS_KEY_REG_INC, + cpu_to_be32(*key)); + if (ret) + return ret; + key++; + } + + return 0; +} + +static int fxgmac_write_rss_lookup_table(struct fxgmac_pdata *pdata) +{ + unsigned int i, j; + u32 regval = 0; + int ret; + + for (i = 0, j = 0; i < ARRAY_SIZE(pdata->rss_table); i++, j++) { + if (j < MGMT_RSS_IDT_ENTRY_PER_REG) { + regval |= + ((pdata->rss_table[i] & MGMT_RSS_IDT_ENTRY_MASK) + << (j * 2)); + } else { + ret = fxgmac_write_rss_reg( + pdata, FXGMAC_RSS_LOOKUP_TABLE_TYPE, + MGMT_RSS_IDT + (i / MGMT_RSS_IDT_ENTRY_PER_REG - + 1) * MGMT_RSS_IDT_REG_INC, + regval); + if (ret) + return ret; + + regval = pdata->rss_table[i]; + j = 0; + } + } + + if (j == MGMT_RSS_IDT_ENTRY_PER_REG) { + /* last IDT */ + fxgmac_write_rss_reg( + pdata, FXGMAC_RSS_LOOKUP_TABLE_TYPE, + MGMT_RSS_IDT + (i / MGMT_RSS_IDT_ENTRY_PER_REG - 1) * + MGMT_RSS_IDT_REG_INC, + regval); + } + + return 0; +} + +static int fxgmac_set_rss_hash_key(struct fxgmac_pdata *pdata, const u8 *key) +{ + memcpy(pdata->rss_key, key, sizeof(pdata->rss_key)); + + return fxgmac_write_rss_hash_key(pdata); +} + +static int fxgmac_set_rss_lookup_table(struct fxgmac_pdata *pdata, + const u32 *table) +{ + unsigned int i; + u32 tval; + +#if FXGMAC_MSIX_CH0RXDIS_EN + DPRINTK("Set_rss_table, rss ctrl eth=0x%08x\n", 0); + + return 0; +#endif + + for (i = 0; i < ARRAY_SIZE(pdata->rss_table); i++) { + tval = table[i]; + pdata->rss_table[i] = FXGMAC_SET_REG_BITS(pdata->rss_table[i], + MAC_RSSDR_DMCH_POS, + MAC_RSSDR_DMCH_LEN, + tval); + } + + return fxgmac_write_rss_lookup_table(pdata); +} + +static u32 log2ex(u32 value) +{ + u32 i = 31; + while (i > 0) { + if (value & 0x80000000) { + break; + } + value <<= 1; + i--; + } + return i; +} + +static int fxgmac_enable_rss(struct fxgmac_pdata *pdata) +{ + u32 regval; + u32 size = 0; + + int ret; + + if (!pdata->hw_feat.rss) { + return -EOPNOTSUPP; + } + + /* Program the hash key */ + ret = fxgmac_write_rss_hash_key(pdata); + if (ret) { + return ret; + } + + /* Program the lookup table */ + ret = fxgmac_write_rss_lookup_table(pdata); + if (ret) { + return ret; + } + + regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_RSS_CTRL); + + /* Set RSS IDT table size */ + size = log2ex(FXGMAC_RSS_MAX_TABLE_SIZE) - 1; + regval = FXGMAC_SET_REG_BITS(regval, MGMT_RSS_CTRL_TBL_SIZE_POS, + MGMT_RSS_CTRL_TBL_SIZE_LEN, size); + +#if FXGMAC_MSIX_CH0RXDIS_EN + /* set default cpu id to 1 */ + regval = FXGMAC_SET_REG_BITS(regval, 8, 2, 1); +#endif + /* Enable RSS */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_RSSCR_RSSE_POS, + MAC_RSSCR_RSSE_LEN, 1); + + /* Set the RSS options */ + regval = FXGMAC_SET_REG_BITS(regval, MGMT_RSS_CTRL_OPT_POS, + MGMT_RSS_CTRL_OPT_LEN, pdata->rss_options); + + writereg(pdata->pAdapter, regval, (pdata->base_mem + MGMT_RSS_CTRL)); + DPRINTK("enable_rss callout, rss ctrl reg=0x%08x\n", regval); + + return 0; +} + +static int fxgmac_disable_rss(struct fxgmac_pdata *pdata) +{ + u32 regval; + + if (!pdata->hw_feat.rss) + return -EOPNOTSUPP; + +#if FXGMAC_MSIX_CH0RXDIS_EN + DPRINTK("Disable_rss, rss ctrl eth=0x%08x\n", 0); + + return 0; +#endif + + regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_RSS_CTRL); + regval = FXGMAC_SET_REG_BITS(regval, MAC_RSSCR_RSSE_POS, + MAC_RSSCR_RSSE_LEN, 0); + + writereg(pdata->pAdapter, regval, (pdata->base_mem + MGMT_RSS_CTRL)); + DPRINTK("disable_rss, rss ctrl reg=0x%08x\n", regval); + + return 0; +} + +static void fxgmac_config_rss(struct fxgmac_pdata *pdata) +{ + int ret; + + if (!pdata->hw_feat.rss) + return; + + if (pdata->rss) + ret = fxgmac_enable_rss(pdata); + else + ret = fxgmac_disable_rss(pdata); + + if (ret) { + DBGPRINT(MP_ERROR, + ("fxgmac_config_rss: error configuring RSS\n")); + } +} + +static void fxgmac_update_aoe_ipv4addr(struct fxgmac_pdata *pdata, u8 *ip_addr) +{ + unsigned int regval, ipval = 0; + + /* enable or disable ARP offload engine. */ + if (!pdata->hw_feat.aoe) { + netdev_err( + pdata->netdev, + "error update ip addr - arp offload not supported.\n"); + return; + } + + if (ip_addr) { + ipval = (ip_addr[0] << 24) | (ip_addr[1] << 16) | + (ip_addr[2] << 8) | (ip_addr[3] << 0); + DPRINTK("%s, covert IP dotted-addr %s to binary 0x%08x ok.\n", + __FUNCTION__, ip_addr, cpu_to_be32(ipval)); + } else { + /* get ipv4 addr from net device */ + ipval = fxgmac_get_netdev_ip4addr(pdata); + DPRINTK("%s, Get net device binary IP ok, 0x%08x\n", + __FUNCTION__, cpu_to_be32(ipval)); + + ipval = cpu_to_be32(ipval); + } + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_ARP_PROTO_ADDR); + if (regval != /*cpu_to_be32*/ (ipval)) { + writereg(pdata->pAdapter, /*cpu_to_be32*/ (ipval), + pdata->mac_regs + MAC_ARP_PROTO_ADDR); + DPRINTK("%s, update arp ipaddr reg from 0x%08x to 0x%08x\n", + __FUNCTION__, regval, /*cpu_to_be32*/ (ipval)); + } +} + +static int fxgmac_enable_arp_offload(struct fxgmac_pdata *pdata) +{ + u32 regval; + + if (!pdata->hw_feat.aoe) + return -EOPNOTSUPP; + + /* Enable arpoffload */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_ARPEN_POS, MAC_CR_ARPEN_LEN, + 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); + + return 0; +} + +static int fxgmac_disable_arp_offload(struct fxgmac_pdata *pdata) +{ + u32 regval; + + if (!pdata->hw_feat.aoe) + return -EOPNOTSUPP; + /* disable arpoffload */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_ARPEN_POS, MAC_CR_ARPEN_LEN, + 0); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); + + return 0; +} + +/* this function config register for NS offload function + * parameters: + * index - 0~1, index to NS look up table. one entry of the lut is like this |remote|solicited|target0|target1| + * remote_addr - ipv6 addr where fuxi gets the NS solicitation pkt(request). in common, it is 0 to match any remote machine. + * solicited_addr - the solicited node multicast group address which fuxi computes and joins. + * target_addr1 - it is the target address in NS solicitation pkt. + * target_addr2 - second target address, any address (with last 6B same with target address?). + */ +static int fxgmac_set_ns_offload(struct fxgmac_pdata *pdata, unsigned int index, + unsigned char *remote_addr, + unsigned char *solicited_addr, + unsigned char *target_addr1, + unsigned char *target_addr2, + unsigned char *mac_addr) +{ + u32 regval; + u32 Address[4], mac_addr_hi, mac_addr_lo; + u8 i, remote_not_zero = 0; + + regval = readreg(pdata->pAdapter, pdata->base_mem + NS_TPID_PRO); + regval = FXGMAC_SET_REG_BITS(regval, NS_TPID_PRO_STPID_POS, + NS_TPID_PRO_STPID_LEN, 0X8100); + regval = FXGMAC_SET_REG_BITS(regval, NS_TPID_PRO_CTPID_POS, + NS_TPID_PRO_CTPID_LEN, 0X9100); + writereg(pdata->pAdapter, regval, pdata->base_mem + NS_TPID_PRO); + regval = readreg(pdata->pAdapter, + pdata->base_mem + 0X38 * index + NS_LUT_MAC_ADDR_CTL); + regval = FXGMAC_SET_REG_BITS(regval, NS_LUT_DST_CMP_TYPE_POS, + NS_LUT_DST_CMP_TYPE_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, NS_LUT_DST_IGNORED_POS, + NS_LUT_DST_IGNORED_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, NS_LUT_REMOTE_AWARED_POS, + NS_LUT_REMOTE_AWARED_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, NS_LUT_TARGET_ISANY_POS, + NS_LUT_TARGET_ISANY_LEN, 0); + writereg(pdata->pAdapter, regval, + pdata->base_mem + 0X38 * index + NS_LUT_MAC_ADDR_CTL); + + /* AR */ + for (i = 0; i < 16 / 4; i++) { + Address[i] = (remote_addr[i * 4 + 0] << 24) | + (remote_addr[i * 4 + 1] << 16) | + (remote_addr[i * 4 + 2] << 8) | + (remote_addr[i * 4 + 3] << 0); + writereg(pdata->pAdapter, Address[i], + pdata->base_mem + 0X38 * index + NS_LUT_ROMOTE0 + + 4 * i); + if (Address[i]) { + remote_not_zero = 1; + } + Address[i] = (target_addr1[i * 4 + 0] << 24) | + (target_addr1[i * 4 + 1] << 16) | + (target_addr1[i * 4 + 2] << 8) | + (target_addr1[i * 4 + 3] << 0); + writereg(pdata->pAdapter, Address[i], + pdata->base_mem + 0X38 * index + NS_LUT_TARGET0 + + 4 * i); + Address[i] = (solicited_addr[i * 4 + 0] << 24) | + (solicited_addr[i * 4 + 1] << 16) | + (solicited_addr[i * 4 + 2] << 8) | + (solicited_addr[i * 4 + 3] << 0); + writereg(pdata->pAdapter, Address[i], + pdata->base_mem + 0X38 * index + NS_LUT_SOLICITED0 + + 4 * i); + Address[i] = (target_addr2[i * 4 + 0] << 24) | + (target_addr2[i * 4 + 1] << 16) | + (target_addr2[i * 4 + 2] << 8) | + (target_addr2[i * 4 + 3] << 0); + writereg(pdata->pAdapter, Address[i], + pdata->base_mem + 0X10 * index + NS_LUT_TARGET4 + + 4 * i); + } + mac_addr_hi = (mac_addr[0] << 24) | (mac_addr[1] << 16) | + (mac_addr[2] << 8) | (mac_addr[3] << 0); + mac_addr_lo = (mac_addr[4] << 8) | (mac_addr[5] << 0); + + writereg(pdata->pAdapter, mac_addr_hi, + pdata->base_mem + 0X38 * index + NS_LUT_MAC_ADDR); + if (remote_not_zero == 0) { + regval = readreg(pdata->pAdapter, pdata->base_mem + + 0X38 * index + + NS_LUT_MAC_ADDR_CTL); + regval = FXGMAC_SET_REG_BITS(regval, NS_LUT_REMOTE_AWARED_POS, + NS_LUT_REMOTE_AWARED_LEN, 0); + regval = FXGMAC_SET_REG_BITS(regval, NS_LUT_MAC_ADDR_LOW_POS, + NS_LUT_MAC_ADDR_LOW_LEN, + mac_addr_lo); + writereg(pdata->pAdapter, regval, + pdata->base_mem + 0X38 * index + NS_LUT_MAC_ADDR_CTL); + } else { + regval = readreg(pdata->pAdapter, pdata->base_mem + + 0X38 * index + + NS_LUT_MAC_ADDR_CTL); + regval = FXGMAC_SET_REG_BITS(regval, NS_LUT_REMOTE_AWARED_POS, + NS_LUT_REMOTE_AWARED_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, NS_LUT_MAC_ADDR_LOW_POS, + NS_LUT_MAC_ADDR_LOW_LEN, + mac_addr_lo); + writereg(pdata->pAdapter, regval, + pdata->base_mem + 0X38 * index + NS_LUT_MAC_ADDR_CTL); + } + return 0; +} + +static void fxgmac_update_ns_offload_ipv6addr(struct fxgmac_pdata *pdata, + unsigned int param) +{ + struct net_device *netdev = pdata->netdev; + unsigned char addr_buf[5][16]; + + unsigned char *remote_addr = (unsigned char *)&addr_buf[0][0]; + unsigned char *solicited_addr = (unsigned char *)&addr_buf[1][0]; + unsigned char *target_addr1 = (unsigned char *)&addr_buf[2][0]; + unsigned char *mac_addr = (unsigned char *)&addr_buf[4][0]; + + /* get ipv6 addr from net device */ + if (NULL == fxgmac_get_netdev_ip6addr(pdata, target_addr1, + solicited_addr, + (FXGMAC_NS_IFA_LOCAL_LINK | + FXGMAC_NS_IFA_GLOBAL_UNICAST) & + param)) { + DPRINTK("%s, get net device ipv6 addr with err and ignore NS offload.\n", + __FUNCTION__); + + return; + } + + DPRINTK("%s, Get net device binary IPv6 ok, local-link=%pI6\n", + __FUNCTION__, target_addr1); + DPRINTK("%s, Get net device binary IPv6 ok, solicited =%pI6\n", + __FUNCTION__, solicited_addr); + + memcpy(mac_addr, netdev->dev_addr, netdev->addr_len); + DPRINTK("%s, Get net device MAC addr ok, ns_tab idx=%d, %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, pdata->expansion.ns_offload_tab_idx, mac_addr[0], + mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], + mac_addr[5]); + + memset(remote_addr, 0, 16); + fxgmac_set_ns_offload(pdata, pdata->expansion.ns_offload_tab_idx++, + remote_addr, solicited_addr, target_addr1, + target_addr1, mac_addr); + if (pdata->expansion.ns_offload_tab_idx >= 2) + pdata->expansion.ns_offload_tab_idx = 0; +} + +static int fxgmac_enable_ns_offload(struct fxgmac_pdata *pdata) +{ + writereg(pdata->pAdapter, 0X00000011, pdata->base_mem + NS_OF_GLB_CTL); + return 0; +} + +static int fxgmac_disable_ns_offload(struct fxgmac_pdata *pdata) +{ + writereg(pdata->pAdapter, 0X00000000, pdata->base_mem + NS_OF_GLB_CTL); + return 0; +} + +static int fxgmac_check_wake_pattern_fifo_pointer(struct fxgmac_pdata *pdata) +{ + u32 regval; + int ret = 0; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); + regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_RWKFILTERST_POS, + MAC_PMT_STA_RWKFILTERST_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PMT_STA); + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); + regval = FXGMAC_GET_REG_BITS(regval, MAC_PMT_STA_RWKPTR_POS, + MAC_PMT_STA_RWKPTR_LEN); + if (regval != 0) { + DPRINTK("Remote fifo pointer is not 0\n"); + ret = -EINVAL; + } + return ret; +} + +static int fxgmac_set_wake_pattern_mask(struct fxgmac_pdata *pdata, + u32 filter_index, u8 register_index, + u32 Data) +{ + const u16 address_offset[16][3] = { + { 0x1020, 0x1024, 0x1028 }, { 0x102c, 0x1030, 0x1034 }, + { 0x1038, 0x103c, 0x1040 }, { 0x1044, 0x1050, 0x1054 }, + { 0x1058, 0x105c, 0x1060 }, { 0x1064, 0x1068, 0x106c }, + { 0x1070, 0x1074, 0x1078 }, { 0x107c, 0x1080, 0x1084 }, + { 0x1088, 0x108c, 0x1090 }, { 0x1134, 0x113c, 0x1140 }, + { 0x1208, 0x1200, 0x1204 }, { 0x1218, 0x1210, 0x1214 }, + { 0x1228, 0x1220, 0x1224 }, { 0x1238, 0x1230, 0x1234 }, + { 0x1248, 0x1240, 0x1244 }, { 0x1258, 0x1250, 0x1254 }, + }; + if (filter_index > 15 || register_index > 2) { + DbgPrintF( + MP_TRACE, + "%s - Remote mask pointer is over range, filter_index:%d, register_index:0x%x\n", + __FUNCTION__, filter_index, register_index); + return -1; + } + writereg(pdata->pAdapter, Data, + pdata->base_mem + + address_offset[filter_index][register_index]); + return 0; +} + +static u16 wol_crc16(u8 *pucframe, u16 uslen) +{ + int i; + + union type16 { + u16 raw; + struct { + u16 bit_0 : 1; + u16 bit_1 : 1; + u16 bit_2 : 1; + u16 bit_3 : 1; + u16 bit_4 : 1; + u16 bit_5 : 1; + u16 bit_6 : 1; + u16 bit_7 : 1; + u16 bit_8 : 1; + u16 bit_9 : 1; + u16 bit_10 : 1; + u16 bit_11 : 1; + u16 bit_12 : 1; + u16 bit_13 : 1; + u16 bit_14 : 1; + u16 bit_15 : 1; + } bits; + }; + + union type8 { + u16 raw; + + struct { + u16 bit_0 : 1; + u16 bit_1 : 1; + u16 bit_2 : 1; + u16 bit_3 : 1; + u16 bit_4 : 1; + u16 bit_5 : 1; + u16 bit_6 : 1; + u16 bit_7 : 1; + } bits; + }; + + union type16 crc, crc_comb; + union type8 next_crc, rrpe_data; + next_crc.raw = 0; + crc.raw = 0xffff; + for (i = 0; i < uslen; i++) { + rrpe_data.raw = pucframe[i]; + next_crc.bits.bit_0 = crc.bits.bit_15 ^ rrpe_data.bits.bit_0; + next_crc.bits.bit_1 = crc.bits.bit_14 ^ next_crc.bits.bit_0 ^ + rrpe_data.bits.bit_1; + next_crc.bits.bit_2 = crc.bits.bit_13 ^ next_crc.bits.bit_1 ^ + rrpe_data.bits.bit_2; + next_crc.bits.bit_3 = crc.bits.bit_12 ^ next_crc.bits.bit_2 ^ + rrpe_data.bits.bit_3; + next_crc.bits.bit_4 = crc.bits.bit_11 ^ next_crc.bits.bit_3 ^ + rrpe_data.bits.bit_4; + next_crc.bits.bit_5 = crc.bits.bit_10 ^ next_crc.bits.bit_4 ^ + rrpe_data.bits.bit_5; + next_crc.bits.bit_6 = crc.bits.bit_9 ^ next_crc.bits.bit_5 ^ + rrpe_data.bits.bit_6; + next_crc.bits.bit_7 = crc.bits.bit_8 ^ next_crc.bits.bit_6 ^ + rrpe_data.bits.bit_7; + + crc_comb.bits.bit_15 = crc.bits.bit_7 ^ next_crc.bits.bit_7; + crc_comb.bits.bit_14 = crc.bits.bit_6; + crc_comb.bits.bit_13 = crc.bits.bit_5; + crc_comb.bits.bit_12 = crc.bits.bit_4; + crc_comb.bits.bit_11 = crc.bits.bit_3; + crc_comb.bits.bit_10 = crc.bits.bit_2; + crc_comb.bits.bit_9 = crc.bits.bit_1 ^ next_crc.bits.bit_0; + crc_comb.bits.bit_8 = crc.bits.bit_0 ^ next_crc.bits.bit_1; + crc_comb.bits.bit_7 = next_crc.bits.bit_0 ^ next_crc.bits.bit_2; + crc_comb.bits.bit_6 = next_crc.bits.bit_1 ^ next_crc.bits.bit_3; + crc_comb.bits.bit_5 = next_crc.bits.bit_2 ^ next_crc.bits.bit_4; + crc_comb.bits.bit_4 = next_crc.bits.bit_3 ^ next_crc.bits.bit_5; + crc_comb.bits.bit_3 = next_crc.bits.bit_4 ^ next_crc.bits.bit_6; + crc_comb.bits.bit_2 = next_crc.bits.bit_5 ^ next_crc.bits.bit_7; + crc_comb.bits.bit_1 = next_crc.bits.bit_6; + crc_comb.bits.bit_0 = next_crc.bits.bit_7; + crc.raw = crc_comb.raw; + } + return crc.raw; +} + +static int fxgmac_set_wake_pattern(struct fxgmac_pdata *pdata, + struct wol_bitmap_pattern *wol_pattern, + u32 pattern_cnt) +{ + u32 i, j, kp, km, mask_index; + int z; + u16 map_index; + u8 mask[MAX_PATTERN_SIZE]; + u32 regval = 0; + u32 total_cnt = 0, pattern_inherited_cnt = 0; + u8 *ptdata, *ptmask; + + if (pattern_cnt > MAX_PATTERN_COUNT) { + DbgPrintF( + MP_TRACE, + "%s - Error: %d patterns, exceed %d, not supported!\n", + __FUNCTION__, pattern_cnt, MAX_PATTERN_COUNT); + return -1; + } + + /* Reset the FIFO head pointer. */ + if (fxgmac_check_wake_pattern_fifo_pointer(pdata)) { + DbgPrintF( + MP_TRACE, + "%s - Warning: the remote pattern array pointer is not be 0\n", + __FUNCTION__); + return -1; + } + + for (i = 0; i < pattern_cnt; i++) { + memcpy(&pdata->pattern[i], wol_pattern + i, + sizeof(wol_pattern[0])); + if (pattern_cnt + pattern_inherited_cnt < MAX_PATTERN_COUNT) { + if (wol_pattern[i].pattern_offset || + !(wol_pattern[i].mask_info[0] & 0x01)) { + memcpy(&pdata->pattern[pattern_cnt + + pattern_inherited_cnt], + wol_pattern + i, sizeof(wol_pattern[0])); + pattern_inherited_cnt++; + } + } + } + total_cnt = pattern_cnt + pattern_inherited_cnt; + + /* + * calculate the crc-16 of the mask pattern + * print the pattern and mask for debug purpose. + */ + for (i = 0; i < total_cnt; i++) { + /* Please program pattern[i] to NIC for pattern match wakeup. + * pattern_size, pattern_info, mask_info + */ + /* save the mask pattern */ + mask_index = 0; + map_index = 0; + for (j = 0; j < pdata->pattern[i].mask_size; j++) { + for (z = 0; + z < ((j == (MAX_PATTERN_SIZE / 8 - 1)) ? 7 : 8); + z++) { + if (pdata->pattern[i].mask_info[j] & + (0x01 << z)) { + mask[map_index] = + pdata->pattern[i].pattern_info + [pdata->pattern[i] + .pattern_offset + + mask_index]; + map_index++; + } + mask_index++; + } + } + /* calculate the crc-16 of the mask pattern */ + pdata->pattern[i].pattern_crc = wol_crc16(mask, map_index); + + /* Print pattern match, for debug purpose. */ + DbgPrintF(MP_LOUD, "%s - Pattern[%d]:", __FUNCTION__, i); + for (kp = 0, km = 0; + kp < sizeof(pdata->pattern[i].pattern_info); + kp += 16, km += 2) { + ptdata = &pdata->pattern[i].pattern_info[kp]; + ptmask = &pdata->pattern[i].mask_info[km]; + DBGPRINT( + MP_LOUD, + ("\n %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x Mask %02x-%02x", + ptdata[0], ptdata[1], ptdata[2], ptdata[3], + ptdata[4], ptdata[5], ptdata[6], ptdata[7], + ptdata[8], ptdata[9], ptdata[10], ptdata[11], + ptdata[12], ptdata[13], ptdata[14], ptdata[15], + ptmask[0], ptmask[1])); + } + DbgPrintF( + MP_LOUD, + "WritePatternToNic62 the %d patterns crc = %x mask length = %d, mask_offset=%x.\n", + i, pdata->pattern[i].pattern_crc, map_index, + pdata->pattern[i].pattern_offset); + memset(mask, 0, sizeof(mask)); + } + + /* Write patterns by FIFO block. */ + for (i = 0; i < (total_cnt + 3) / 4; i++) { + /* 1. Write the first 4Bytes of Filter. */ + writereg(pdata->pAdapter, + ((pdata->pattern[i * 4 + 0].mask_info[3] & 0x7f) + << 24) | + (pdata->pattern[i * 4 + 0].mask_info[2] + << 16) | + (pdata->pattern[i * 4 + 0].mask_info[1] << 8) | + (pdata->pattern[i * 4 + 0].mask_info[0] << 0), + pdata->mac_regs + MAC_RWK_PAC); + + writereg(pdata->pAdapter, + ((pdata->pattern[i * 4 + 1].mask_info[3] & 0x7f) + << 24) | + (pdata->pattern[i * 4 + 1].mask_info[2] + << 16) | + (pdata->pattern[i * 4 + 1].mask_info[1] << 8) | + (pdata->pattern[i * 4 + 1].mask_info[0] << 0), + pdata->mac_regs + MAC_RWK_PAC); + + writereg(pdata->pAdapter, + ((pdata->pattern[i * 4 + 2].mask_info[3] & 0x7f) + << 24) | + (pdata->pattern[i * 4 + 2].mask_info[2] + << 16) | + (pdata->pattern[i * 4 + 2].mask_info[1] << 8) | + (pdata->pattern[i * 4 + 2].mask_info[0] << 0), + pdata->mac_regs + MAC_RWK_PAC); + + writereg(pdata->pAdapter, + ((pdata->pattern[i * 4 + 3].mask_info[3] & 0x7f) + << 24) | + (pdata->pattern[i * 4 + 3].mask_info[2] + << 16) | + (pdata->pattern[i * 4 + 3].mask_info[1] << 8) | + (pdata->pattern[i * 4 + 3].mask_info[0] << 0), + pdata->mac_regs + MAC_RWK_PAC); + + /* 2. Write the Filter Command. */ + regval = 0; + /* Set filter enable bit. */ + regval |= ((i * 4 + 0) < total_cnt) ? (0x1 << 0) : 0x0; + regval |= ((i * 4 + 1) < total_cnt) ? (0x1 << 8) : 0x0; + regval |= ((i * 4 + 2) < total_cnt) ? (0x1 << 16) : 0x0; + regval |= ((i * 4 + 3) < total_cnt) ? (0x1 << 24) : 0x0; + /* Set filter address type, 0- unicast, 1 - multicast. */ + regval |= (i * 4 + 0 >= total_cnt) ? 0x0 : + (i * 4 + 0 >= pattern_cnt) ? (0x1 << (3 + 0)) : + pdata->pattern[i * 4 + 0].pattern_offset ? + 0x0 : + !(pdata->pattern[i * 4 + 0].mask_info[0] & 0x01) ? + 0x0 : + (pdata->pattern[i * 4 + 0].pattern_info[0] & 0x01) ? + (0x1 << (3 + 0)) : + 0x0; + regval |= (i * 4 + 1 >= total_cnt) ? 0x0 : + (i * 4 + 1 >= pattern_cnt) ? (0x1 << (3 + 8)) : + pdata->pattern[i * 4 + 1].pattern_offset ? + 0x0 : + !(pdata->pattern[i * 4 + 1].mask_info[0] & 0x01) ? + 0x0 : + (pdata->pattern[i * 4 + 1].pattern_info[0] & 0x01) ? + (0x1 << (3 + 8)) : + 0x0; + regval |= (i * 4 + 2 >= total_cnt) ? 0x0 : + (i * 4 + 2 >= pattern_cnt) ? (0x1 << (3 + 16)) : + pdata->pattern[i * 4 + 2].pattern_offset ? + 0x0 : + !(pdata->pattern[i * 4 + 2].mask_info[0] & 0x01) ? + 0x0 : + (pdata->pattern[i * 4 + 2].pattern_info[0] & 0x01) ? + (0x1 << (3 + 16)) : + 0x0; + regval |= (i * 4 + 3 >= total_cnt) ? 0x0 : + (i * 4 + 3 >= pattern_cnt) ? (0x1 << (3 + 24)) : + pdata->pattern[i * 4 + 3].pattern_offset ? + 0x0 : + !(pdata->pattern[i * 4 + 3].mask_info[0] & 0x01) ? + 0x0 : + (pdata->pattern[i * 4 + 3].pattern_info[0] & 0x01) ? + (0x1 << (3 + 24)) : + 0x0; + writereg(pdata->pAdapter, regval, + pdata->mac_regs + MAC_RWK_PAC); + + /* 3. Write the mask offset. */ + writereg(pdata->pAdapter, + (pdata->pattern[i * 4 + 3].pattern_offset << 24) | + (pdata->pattern[i * 4 + 2].pattern_offset + << 16) | + (pdata->pattern[i * 4 + 1].pattern_offset + << 8) | + (pdata->pattern[i * 4 + 0].pattern_offset + << 0), + pdata->mac_regs + MAC_RWK_PAC); + + /* 4. Write the masked data CRC. */ + writereg(pdata->pAdapter, + (pdata->pattern[i * 4 + 1].pattern_crc << 16) | + (pdata->pattern[i * 4 + 0].pattern_crc << 0), + pdata->mac_regs + MAC_RWK_PAC); + writereg(pdata->pAdapter, + (pdata->pattern[i * 4 + 3].pattern_crc << 16) | + (pdata->pattern[i * 4 + 2].pattern_crc << 0), + pdata->mac_regs + MAC_RWK_PAC); + } + + for (i = 0; i < total_cnt; i++) { + fxgmac_set_wake_pattern_mask( + pdata, i, 0, + ((pdata->pattern[i].mask_info[7] & 0x7f) << (24 + 1)) | + (pdata->pattern[i].mask_info[6] << (16 + 1)) | + (pdata->pattern[i].mask_info[5] << (8 + 1)) | + (pdata->pattern[i].mask_info[4] << (0 + 1)) | + ((pdata->pattern[i].mask_info[3] & 0x80) >> + 7)); /* global manager regitster mask bit 31~62 */ + fxgmac_set_wake_pattern_mask( + pdata, i, 1, + ((pdata->pattern[i].mask_info[11] & 0x7f) << (24 + 1)) | + (pdata->pattern[i].mask_info[10] << (16 + 1)) | + (pdata->pattern[i].mask_info[9] << (8 + 1)) | + (pdata->pattern[i].mask_info[8] << (0 + 1)) | + ((pdata->pattern[i].mask_info[7] & 0x80) >> + 7)); /* global manager regitster mask bit 63~94 */ + fxgmac_set_wake_pattern_mask( + pdata, i, 2, + ((pdata->pattern[i].mask_info[15] & 0x7f) << (24 + 1)) | + (pdata->pattern[i].mask_info[14] << (16 + 1)) | + (pdata->pattern[i].mask_info[13] << (8 + 1)) | + (pdata->pattern[i].mask_info[12] << (0 + 1)) | + ((pdata->pattern[i].mask_info[11] & 0x80) >> + 7)); /* global manager regitster mask bit 95~126 */ + } + + return 0; +} + +static int fxgmac_enable_wake_pattern(struct fxgmac_pdata *pdata) +{ + u32 regval; + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); + regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_RWKFILTERST_POS, + MAC_PMT_STA_RWKFILTERST_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_RWKPKTEN_POS, + MAC_PMT_STA_RWKPKTEN_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PMT_STA); + regval = readreg(pdata->pAdapter, pdata->base_mem + WOL_CTL); + regval = FXGMAC_SET_REG_BITS(regval, WOL_PKT_EN_POS, WOL_PKT_EN_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->base_mem + WOL_CTL); + return 0; +} + +static int fxgmac_disable_wake_pattern(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); + regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_RWKFILTERST_POS, + MAC_PMT_STA_RWKFILTERST_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_RWKPKTEN_POS, + MAC_PMT_STA_RWKPKTEN_LEN, 0); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PMT_STA); + regval = readreg(pdata->pAdapter, pdata->base_mem + WOL_CTL); + regval = FXGMAC_SET_REG_BITS(regval, WOL_PKT_EN_POS, WOL_PKT_EN_LEN, 0); + writereg(pdata->pAdapter, regval, pdata->base_mem + WOL_CTL); + return 0; +} + +static int fxgmac_enable_wake_magic_pattern(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); + regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_MGKPKTEN_POS, + MAC_PMT_STA_MGKPKTEN_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PMT_STA); + regval = readreg(pdata->pAdapter, pdata->base_mem + WOL_CTL); + regval = FXGMAC_SET_REG_BITS(regval, WOL_PKT_EN_POS, WOL_PKT_EN_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->base_mem + WOL_CTL); + + /* Enable PME Enable Bit. */ + cfg_r32(pdata, REG_PM_STATCTRL, ®val); + regval = FXGMAC_SET_REG_BITS(regval, PM_CTRLSTAT_PME_EN_POS, + PM_CTRLSTAT_PME_EN_LEN, 1); + cfg_w32(pdata, REG_PM_STATCTRL, regval); + + return 0; +} + +static int fxgmac_disable_wake_magic_pattern(struct fxgmac_pdata *pdata) +{ + u32 regval; + regval = readreg(pdata->pAdapter, pdata->base_mem + WOL_CTL); + regval = FXGMAC_SET_REG_BITS(regval, WOL_PKT_EN_POS, WOL_PKT_EN_LEN, 0); + writereg(pdata->pAdapter, regval, pdata->base_mem + WOL_CTL); + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); + regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_MGKPKTEN_POS, + MAC_PMT_STA_MGKPKTEN_LEN, 0); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PMT_STA); + return 0; +} + +#if defined(FUXI_PM_WPI_READ_FEATURE_EN) && FUXI_PM_WPI_READ_FEATURE_EN +/* + * enable Wake packet indication. called to enable before sleep/hibernation + * and no needed to call disable for that, fxgmac_get_wake_packet_indication will clear to normal once done. + */ +static void fxgmac_enable_wake_packet_indication(struct fxgmac_pdata *pdata, + int en) +{ + u32 val_wpi_crtl0; + + /* read-clear WoL event. */ + readreg(pdata->pAdapter, pdata->base_mem + MGMT_WOL_CTRL); + + /* get wake packet information */ + val_wpi_crtl0 = + (u32)readreg(pdata->pAdapter, pdata->base_mem + MGMT_WPI_CTRL0); + + /* prepare to write packet data by write wpi_mode to 1 */ + val_wpi_crtl0 = + FXGMAC_SET_REG_BITS(val_wpi_crtl0, MGMT_WPI_CTRL0_WPI_MODE_POS, + MGMT_WPI_CTRL0_WPI_MODE_LEN, + (en ? MGMT_WPI_CTRL0_WPI_MODE_WR : + MGMT_WPI_CTRL0_WPI_MODE_NORMAL)); + writereg(pdata->pAdapter, val_wpi_crtl0, + pdata->base_mem + MGMT_WPI_CTRL0); + + DbgPrintF(MP_TRACE, "%s - WPI pkt enable=%d, reg=%08x.\n", __FUNCTION__, + en, val_wpi_crtl0); + + return; +} + +/* + * this function read Wake up packet after MDIS resume + * input: + * pdata + * wpi_buf container of a packet. + * buf_size size of the packet container. since HW limit to 14bits, ie 16KB all together. + * output: + * wake_reason from HW, we can indentify 1)magic packet, or 2)pattern(remote wake packet) or WAKE_REASON_HW_ERR indicates err + * packet_size length of the wake packet. 0 indicates exception. + * + */ +static void fxgmac_get_wake_packet_indication(struct fxgmac_pdata *pdata, + int *wake_reason, + u32 *wake_pattern_number, + u8 *wpi_buf, u32 buf_size, + u32 *packet_size) +{ + u32 i, regval, val_wpi_crtl0, *dw_wpi_buf; + u32 data_len, data_len_dw, b_need_pkt = 0; + + *wake_reason = WAKE_REASON_NONE; + *packet_size = 0; + fxgmac_release_phy(pdata); + + /* try to check wake reason. GMAC reg 20c0 only tells Magic or remote-pattern + * read from MGMT_WOL_CTRL, 1530 instead. + */ + regval = (u32)readreg(pdata->pAdapter, pdata->base_mem + MGMT_WOL_CTRL); + DbgPrintF(MP_TRACE, "%s - 0x1530=%x.\n", __FUNCTION__, regval); + if (!regval) { + DbgPrintF(MP_TRACE, "%s - nothing for WPI pkt.\n", + __FUNCTION__); + return; + } + + if (regval & MGMT_WOL_CTRL_WPI_MGC_PKT) { + *wake_reason = WAKE_REASON_MAGIC; + b_need_pkt = 1; + } else if (regval & MGMT_WOL_CTRL_WPI_RWK_PKT) { + *wake_reason = WAKE_REASON_PATTERNMATCH; + b_need_pkt = 1; + *wake_pattern_number = 0; + + /* + * wake_pattern_number, HW should tell, tbd + */ + for (i = 0; i < MAX_PATTERN_COUNT; i++) { + if (regval & (MGMT_WOL_CTRL_WPI_RWK_PKT_NUMBER << i)) { + *wake_pattern_number = i; + break; + } + } + + } else if (regval & MGMT_WOL_CTRL_WPI_LINK_CHG) { + *wake_reason = WAKE_REASON_LINK; + } + + if (!b_need_pkt) { + DbgPrintF(MP_TRACE, "%s - wake by link and no WPI pkt.\n", + __FUNCTION__); + return; + } + + /* get wake packet information */ + val_wpi_crtl0 = + (u32)readreg(pdata->pAdapter, pdata->base_mem + MGMT_WPI_CTRL0); + + if (val_wpi_crtl0 & MGMT_WPI_CTRL0_WPI_FAIL) { + *wake_reason = WAKE_REASON_HW_ERR; + DbgPrintF(MP_TRACE, "%s - WPI pkt fail from hw.\n", + __FUNCTION__); + return; + } + + *packet_size = FXGMAC_GET_REG_BITS(val_wpi_crtl0, + MGMT_WPI_CTRL0_WPI_PKT_LEN_POS, + MGMT_WPI_CTRL0_WPI_PKT_LEN_LEN); + + if (0 == *packet_size) { + *wake_reason = WAKE_REASON_HW_ERR; + DbgPrintF(MP_TRACE, "%s - WPI pkt len is 0 from hw.\n", + __FUNCTION__); + return; + } + + DbgPrintF(MP_TRACE, "%s - WPI pkt len from hw, *packet_size=%u.\n", + __FUNCTION__, *packet_size); + + if (buf_size < *packet_size) { + DbgPrintF(MP_WARN, + "%s - too small buf_size=%u, WPI pkt len is %u.\n", + __FUNCTION__, buf_size, *packet_size); + data_len = buf_size; + } else { + data_len = *packet_size; + } + + /* prepare to read packet data by write wpi_mode to 2 */ + val_wpi_crtl0 = FXGMAC_SET_REG_BITS(val_wpi_crtl0, + MGMT_WPI_CTRL0_WPI_MODE_POS, + MGMT_WPI_CTRL0_WPI_MODE_LEN, + MGMT_WPI_CTRL0_WPI_MODE_RD); + writereg(pdata->pAdapter, val_wpi_crtl0, + pdata->base_mem + MGMT_WPI_CTRL0); + + dw_wpi_buf = (u32 *)wpi_buf; + data_len_dw = (data_len + 3) / 4; + + i = 0; + DbgPrintF( + MP_TRACE, + "%s - before retrieve, len=%d, len_dw=%d, reg_wpi_ctrl0=%08x.\n", + __FUNCTION__, data_len, data_len_dw, val_wpi_crtl0); + while ((0 == (val_wpi_crtl0 & MGMT_WPI_CTRL0_WPI_OP_DONE))) { + if (i < data_len_dw) { + regval = (u32)readreg(pdata->pAdapter, + pdata->base_mem + + MGMT_WPI_CTRL1_DATA); + /*dw_wpi_buf[i] = SWAP_BYTES_32(regval);*/ + dw_wpi_buf[i] = regval; + } else { + break; + } + + val_wpi_crtl0 = (u32)readreg(pdata->pAdapter, + pdata->base_mem + MGMT_WPI_CTRL0); + i++; + } + if (*packet_size <= MAC_CRC_LENGTH) { + DbgPrintF(MP_TRACE, + "%s - Warning, WPI pkt len is less 4 from hw.\n", + __FUNCTION__); + return; + } + *packet_size -= MAC_CRC_LENGTH; + + /* once read data complete and write wpi_mode to 0, normal */ + val_wpi_crtl0 = FXGMAC_SET_REG_BITS(val_wpi_crtl0, + MGMT_WPI_CTRL0_WPI_MODE_POS, + MGMT_WPI_CTRL0_WPI_MODE_LEN, + MGMT_WPI_CTRL0_WPI_MODE_NORMAL); + writereg(pdata->pAdapter, val_wpi_crtl0, + pdata->base_mem + MGMT_WPI_CTRL0); + + DbgPrintF( + MP_TRACE, + "%s - WPI done and back to normal mode, reg=%08x, read data=%dB.\n", + __FUNCTION__, val_wpi_crtl0, i * 4); + + return; +} +#endif /* FUXI_PM_WPI_READ_FEATURE_EN */ + +static int fxgmac_enable_wake_link_change(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->base_mem + WOL_CTL); + regval = FXGMAC_SET_REG_BITS(regval, WOL_LINKCHG_EN_POS, + WOL_LINKCHG_EN_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->base_mem + WOL_CTL); + return 0; +} +static int fxgmac_disable_wake_link_change(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->base_mem + WOL_CTL); + regval = FXGMAC_SET_REG_BITS(regval, WOL_LINKCHG_EN_POS, + WOL_LINKCHG_EN_LEN, 0); + writereg(pdata->pAdapter, regval, pdata->base_mem + WOL_CTL); + return 0; +} + +static void fxgmac_config_wol(struct fxgmac_pdata *pdata, int en) +{ + /* enable or disable WOL. this function only set wake-up type, and power related configure + * will be in other place, see power management. + */ + if (!pdata->hw_feat.rwk) { + netdev_err(pdata->netdev, + "error configuring WOL - not supported.\n"); + return; + } + + fxgmac_disable_wake_magic_pattern(pdata); + fxgmac_disable_wake_pattern(pdata); + fxgmac_disable_wake_link_change(pdata); + + if (en) { + /* config mac address for rx of magic or ucast */ + fxgmac_set_mac_address(pdata, (u8 *)(pdata->netdev->dev_addr)); + + /* Enable Magic packet */ + if (pdata->expansion.wol & WAKE_MAGIC) { + fxgmac_enable_wake_magic_pattern(pdata); + } + + /* Enable global unicast packet */ + if (pdata->expansion.wol & WAKE_UCAST || + pdata->expansion.wol & WAKE_MCAST || + pdata->expansion.wol & WAKE_BCAST || + pdata->expansion.wol & WAKE_ARP) { + fxgmac_enable_wake_pattern(pdata); + } + + /* Enable ephy link change */ + if ((FXGMAC_WOL_UPON_EPHY_LINK) && + (pdata->expansion.wol & WAKE_PHY)) { + fxgmac_enable_wake_link_change(pdata); + } + } + device_set_wakeup_enable(/*pci_dev_to_dev*/ (pdata->dev), en); + + DPRINTK("config_wol callout\n"); +} + +static int fxgmac_get_ephy_state(struct fxgmac_pdata *pdata) +{ + u32 value; + value = readreg(pdata->pAdapter, pdata->base_mem + MGMT_EPHY_CTRL); + return value; +} + +static void fxgmac_enable_dma_interrupts(struct fxgmac_pdata *pdata) +{ +#ifndef DPDK + unsigned int dma_ch_isr, dma_ch_ier; + struct fxgmac_channel *channel; + unsigned int i; + +#ifdef NIC_NET_ADAPETERCX + u32 regval; + /* config interrupt to level signal */ + regval = (u32)readreg(pdata->pAdapter, pdata->mac_regs + DMA_MR); + regval = FXGMAC_SET_REG_BITS(regval, DMA_MR_INTM_POS, DMA_MR_INTM_LEN, + 1); + regval = FXGMAC_SET_REG_BITS(regval, DMA_MR_QUREAD_POS, + DMA_MR_QUREAD_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + DMA_MR); +#endif + + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + /* Clear all the interrupts which are set */ + dma_ch_isr = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_SR)); + writereg(pdata->pAdapter, dma_ch_isr, + FXGMAC_DMA_REG(channel, DMA_CH_SR)); + + /* 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 + */ + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, DMA_CH_IER_NIE_POS, + DMA_CH_IER_NIE_LEN, 1); + /* dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, + * DMA_CH_IER_AIE_POS, DMA_CH_IER_AIE_LEN, 1); + */ + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, + DMA_CH_IER_FBEE_POS, + DMA_CH_IER_FBEE_LEN, 1); + + if (channel->tx_ring) { + /* Enable the following Tx interrupts + * TIE - Transmit Interrupt Enable (unless using + * per channel interrupts) + */ + if (!pdata->per_channel_irq) + dma_ch_ier = FXGMAC_SET_REG_BITS( + dma_ch_ier, DMA_CH_IER_TIE_POS, + DMA_CH_IER_TIE_LEN, 1); + if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { + if (pdata->per_channel_irq) { + dma_ch_ier = FXGMAC_SET_REG_BITS( + dma_ch_ier, DMA_CH_IER_TIE_POS, + DMA_CH_IER_TIE_LEN, 1); + } + } + } + if (channel->rx_ring) { + /* Enable following Rx interrupts + * RBUE - Receive Buffer Unavailable Enable + * RIE - Receive Interrupt Enable (unless using + * per channel interrupts) + */ + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, + DMA_CH_IER_RBUE_POS, + DMA_CH_IER_RBUE_LEN, + 1); + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, + DMA_CH_IER_RIE_POS, + DMA_CH_IER_RIE_LEN, 1); + } + + writereg(pdata->pAdapter, dma_ch_ier, + FXGMAC_DMA_REG(channel, DMA_CH_IER)); + } +#else + struct fxgmac_tx_queue *txq; + unsigned int dma_ch_isr, dma_ch_ier; + unsigned int i; + + for (i = 0; i < pdata->expansion.eth_dev->data->nb_tx_queues; i++) { + txq = pdata->expansion.eth_dev->data->tx_queues[i]; + + /* Clear all the interrupts which are set */ + dma_ch_isr = FXGMAC_DMA_IOREAD(txq, DMA_CH_SR); + FXGMAC_DMA_IOWRITE(txq, 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 + */ + FXGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, NIE, 1); /* 0 fx 1 */ + FXGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, AIE, 1); + FXGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, FBEE, 1); + + /* Enable following Rx interrupts + * RBUE - Receive Buffer Unavailable Enable + * RIE - Receive Interrupt Enable (unless using + * per channel interrupts in edge triggered + * mode) + */ + FXGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1); /* 0 fx 1 */ + FXGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 0); /* 0 fx 1 */ + + FXGMAC_DMA_IOWRITE(txq, DMA_CH_IER, dma_ch_ier); + } +#endif +} + +static void fxgmac_enable_mtl_interrupts(struct fxgmac_pdata *pdata) +{ + unsigned int q_count, i; + unsigned int mtl_q_isr; + + 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 = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_Q_ISR)); + writereg(pdata->pAdapter, mtl_q_isr, + FXGMAC_MTL_REG(pdata, i, MTL_Q_ISR)); + + /* No MTL interrupts to be enabled */ + writereg(pdata->pAdapter, 0, + FXGMAC_MTL_REG(pdata, i, MTL_Q_IER)); + } +} + +static void fxgmac_enable_mac_interrupts(struct fxgmac_pdata *pdata) +{ + unsigned int mac_ier = 0; + u32 regval; + + /* Enable Timestamp interrupt */ + mac_ier = FXGMAC_SET_REG_BITS(mac_ier, MAC_IER_TSIE_POS, + MAC_IER_TSIE_LEN, 1); + + writereg(pdata->pAdapter, mac_ier, pdata->mac_regs + MAC_IER); + + /* Enable all counter interrupts */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MMC_RIER); + regval = FXGMAC_SET_REG_BITS(regval, MMC_RIER_ALL_INTERRUPTS_POS, + MMC_RIER_ALL_INTERRUPTS_LEN, 0xffffffff); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MMC_RIER); + regval = readreg(pdata->pAdapter, pdata->mac_regs + MMC_TIER); + regval = FXGMAC_SET_REG_BITS(regval, MMC_TIER_ALL_INTERRUPTS_POS, + MMC_TIER_ALL_INTERRUPTS_LEN, 0xffffffff); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MMC_TIER); +} + +static int fxgmac_set_fxgmii_2500_speed(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_PS_POS, MAC_CR_PS_LEN, 0); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_FES_POS, MAC_CR_FES_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_DM_POS, MAC_CR_DM_LEN, + pdata->phy_duplex); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); + + return 0; +} + +static int fxgmac_set_fxgmii_1000_speed(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_PS_POS, MAC_CR_PS_LEN, 0); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_FES_POS, MAC_CR_FES_LEN, 0); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_DM_POS, MAC_CR_DM_LEN, + pdata->phy_duplex); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); + + return 0; +} + +static int fxgmac_set_fxgmii_100_speed(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_PS_POS, MAC_CR_PS_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_FES_POS, MAC_CR_FES_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_DM_POS, MAC_CR_DM_LEN, + pdata->phy_duplex); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); + + return 0; +} + +static int fxgmac_set_fxgmii_10_speed(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_PS_POS, MAC_CR_PS_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_FES_POS, MAC_CR_FES_LEN, 0); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_DM_POS, MAC_CR_DM_LEN, + pdata->phy_duplex); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); + + return 0; +} + +/** + * fxgmac_check_phy_link - Get link/speed status + * @pdata: pointer to gmac structure + * @speed: pointer to link speed + * @link_up: true is link is up, false otherwise + * @link_up_wait_to_complete: bool used to wait for link up or not + * + * Reads the links register to determine if link is up and the current speed + **/ +static int fxgmac_check_phy_link(struct fxgmac_pdata *pdata, u32 *speed, + bool *link_up, bool link_up_wait_to_complete) +{ + u16 link_reg = 0; + + struct net_device *netdev = pdata->netdev; + if (netdev->base_addr) { + link_reg = + (u16)(*((u32 *)(netdev->base_addr + MGMT_EPHY_CTRL))); + + /* + * check register address 0x1004 + * b[6:5] ephy_pause + * b[4:3] ephy_speed 0b10 1000m 0b01 100m + * b[2] ephy_duplex + * b[1] ephy_link + * b[0] ephy_reset. should be set to 1 before use phy. + */ + *link_up = false; + if (link_reg & MGMT_EPHY_CTRL_STA_EPHY_RELEASE) { + if (link_up) { + *link_up = (link_reg & + MGMT_EPHY_CTRL_STA_EPHY_LINKUP) ? + true : + false; + } + if (speed) + *speed = (link_reg & + MGMT_EPHY_CTRL_STA_SPEED_MASK) >> + MGMT_EPHY_CTRL_STA_SPEED_POS; + } else { + DPRINTK("fxgmac_check_phy_link ethernet PHY not released.\n"); + return -1; + } + } else { + DPRINTK("fxgmac_check_phy_link null base addr err\n"); + return -1; + } + + return 0; +} + +static int fxgmac_config_mac_speed(struct fxgmac_pdata *pdata) +{ + switch (pdata->phy_speed) { + case SPEED_2500: + fxgmac_set_fxgmii_2500_speed(pdata); + break; + case SPEED_1000: + fxgmac_set_fxgmii_1000_speed(pdata); + break; + case SPEED_100: + fxgmac_set_fxgmii_100_speed(pdata); + break; + case SPEED_10: + fxgmac_set_fxgmii_10_speed(pdata); + break; + } + return 0; +} + +static int fxgmac_write_ephy_reg(struct fxgmac_pdata *pdata, u32 reg_id, + u32 data) +{ + u32 regval; + u32 mdioctrl = reg_id * 0x10000 + 0x8000205; + int busy = 15; + + writereg(pdata->pAdapter, data, pdata->mac_regs + MAC_MDIO_DATA); + writereg(pdata->pAdapter, mdioctrl, pdata->mac_regs + MAC_MDIO_ADDRESS); + do { + regval = readreg(pdata->pAdapter, + pdata->mac_regs + MAC_MDIO_ADDRESS); + busy--; + } while ((regval & MAC_MDIO_ADDRESS_BUSY) && (busy)); + + DPRINTK("fxgmac_write_ephy_reg id %d %s, ctrl=0x%08x, data=0x%08x\n", + reg_id, (regval & 0x1) ? "err" : "ok", regval, data); + + return (regval & MAC_MDIO_ADDRESS_BUSY) ? -1 : 0; /* -1 indicates err */ +} + +static int fxgmac_read_ephy_reg(struct fxgmac_pdata *pdata, u32 reg_id, + u32 *data) +{ + u32 regval = 0, regret; + u32 mdioctrl = reg_id * 0x10000 + 0x800020d; + int busy = 15; + + writereg(pdata->pAdapter, mdioctrl, pdata->mac_regs + MAC_MDIO_ADDRESS); + do { + regval = readreg(pdata->pAdapter, + pdata->mac_regs + MAC_MDIO_ADDRESS); + busy--; + } while ((regval & MAC_MDIO_ADDRESS_BUSY) && (busy)); + + if (0 == (regval & MAC_MDIO_ADDRESS_BUSY)) { + regret = readreg(pdata->pAdapter, + pdata->mac_regs + MAC_MDIO_DATA); + if (data) + *data = regret; + return regret; + } + + DPRINTK("fxgmac_read_ephy_reg id=0x%02x err, busy=%d, ctrl=0x%08x.\n", + reg_id, busy, regval); + return -1; +} + +static int fxgmac_write_ephy_mmd_reg(struct fxgmac_pdata *pdata, u32 reg_id, + u32 mmd, u32 data) +{ + u32 regval; + u32 mdioctrl = (mmd << 16) + 0x8000207; + u32 regdata = (reg_id << 16) + data; + /* for phy mmd reg r/w operation, set more delay time than phy mii reg r/w */ + int busy = 60; + + writereg(pdata->pAdapter, regdata, pdata->mac_regs + MAC_MDIO_DATA); + writereg(pdata->pAdapter, mdioctrl, pdata->mac_regs + MAC_MDIO_ADDRESS); + do { + regval = readreg(pdata->pAdapter, + pdata->mac_regs + MAC_MDIO_ADDRESS); + busy--; + } while ((regval & MAC_MDIO_ADDRESS_BUSY) && (busy)); + + DPRINTK("fxgmac_write_ephy_mmd_reg id %d mmd %d %s, ctrl=0x%08x, data=0x%08x\n", + reg_id, mmd, (regval & 0x1) ? "err" : "ok", regval, data); + + return (regval & MAC_MDIO_ADDRESS_BUSY) ? -1 : 0; /* -1 indicates err */ +} + +static void fxgmac_config_flow_control(struct fxgmac_pdata *pdata) +{ + u32 regval = 0; + + fxgmac_config_tx_flow_control(pdata); + fxgmac_config_rx_flow_control(pdata); + + fxgmac_read_ephy_reg(pdata, REG_MII_ADVERTISE, ®val); + /* set auto negotiation advertisement pause ability */ + if (pdata->tx_pause || pdata->rx_pause) { + regval = FXGMAC_SET_REG_BITS(regval, + PHY_MII_ADVERTISE_PAUSE_POS, + PHY_MII_ADVERTISE_PAUSE_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, + PHY_MII_ADVERTISE_ASYPAUSE_POS, + PHY_MII_ADVERTISE_ASYPAUSE_LEN, 1); + } else { + regval = FXGMAC_SET_REG_BITS(regval, + PHY_MII_ADVERTISE_PAUSE_POS, + PHY_MII_ADVERTISE_PAUSE_LEN, 0); + regval = FXGMAC_SET_REG_BITS(regval, + PHY_MII_ADVERTISE_ASYPAUSE_POS, + PHY_MII_ADVERTISE_ASYPAUSE_LEN, 0); + } + fxgmac_write_ephy_reg(pdata, REG_MII_ADVERTISE, regval); + /* after change the auto negotiation advertisement need to soft reset */ + fxgmac_read_ephy_reg(pdata, REG_MII_BMCR, ®val); + regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_RESET_POS, PHY_CR_RESET_LEN, + 1); + fxgmac_write_ephy_reg(pdata, REG_MII_BMCR, regval); +} + +static int fxgmac_set_ephy_autoneg_advertise(struct fxgmac_pdata *pdata, + struct fxphy_ag_adv phy_ag_adv) +{ + u32 regval = 0, ret = 0; + + if (phy_ag_adv.auto_neg_en) { + fxgmac_read_ephy_reg(pdata, REG_MII_BMCR, ®val); + regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_AUTOENG_POS, + PHY_CR_AUTOENG_LEN, 1); + ret |= fxgmac_write_ephy_reg(pdata, REG_MII_BMCR, regval); + } else { + fxgmac_read_ephy_reg(pdata, REG_MII_BMCR, ®val); + regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_AUTOENG_POS, + PHY_CR_AUTOENG_LEN, 0); + ret |= fxgmac_write_ephy_reg(pdata, REG_MII_BMCR, regval); + } + + fxgmac_read_ephy_reg(pdata, REG_MII_CTRL1000, ®val); + if (phy_ag_adv.full_1000m) { + regval = FXGMAC_SET_REG_BITS(regval, + PHY_MII_CTRL1000_1000FULL_POS, + PHY_MII_CTRL1000_1000FULL_LEN, 1); + } else { + regval = FXGMAC_SET_REG_BITS(regval, + PHY_MII_CTRL1000_1000FULL_POS, + PHY_MII_CTRL1000_1000FULL_LEN, 0); + } + if (phy_ag_adv.half_1000m) { + regval = FXGMAC_SET_REG_BITS(regval, + PHY_MII_CTRL1000_1000HALF_POS, + PHY_MII_CTRL1000_1000HALF_LEN, 1); + } else { + regval = FXGMAC_SET_REG_BITS(regval, + PHY_MII_CTRL1000_1000HALF_POS, + PHY_MII_CTRL1000_1000HALF_LEN, 0); + } + ret |= fxgmac_write_ephy_reg(pdata, REG_MII_CTRL1000, regval); + + fxgmac_read_ephy_reg(pdata, REG_MII_ADVERTISE, ®val); + + if (phy_ag_adv.full_100m) { + regval = FXGMAC_SET_REG_BITS(regval, + PHY_MII_ADVERTISE_100FULL_POS, + PHY_MII_ADVERTISE_100FULL_LEN, 1); + } else { + regval = FXGMAC_SET_REG_BITS(regval, + PHY_MII_ADVERTISE_100FULL_POS, + PHY_MII_ADVERTISE_100FULL_LEN, 0); + } + if (phy_ag_adv.half_100m) { + regval = FXGMAC_SET_REG_BITS(regval, + PHY_MII_ADVERTISE_100HALF_POS, + PHY_MII_ADVERTISE_100HALF_LEN, 1); + } else { + regval = FXGMAC_SET_REG_BITS(regval, + PHY_MII_ADVERTISE_100HALF_POS, + PHY_MII_ADVERTISE_100HALF_LEN, 0); + } + if (phy_ag_adv.full_10m) { + regval = FXGMAC_SET_REG_BITS(regval, + PHY_MII_ADVERTISE_10FULL_POS, + PHY_MII_ADVERTISE_10FULL_LEN, 1); + } else { + regval = FXGMAC_SET_REG_BITS(regval, + PHY_MII_ADVERTISE_10FULL_POS, + PHY_MII_ADVERTISE_10FULL_LEN, 0); + } + if (phy_ag_adv.half_10m) { + regval = FXGMAC_SET_REG_BITS(regval, + PHY_MII_ADVERTISE_10HALF_POS, + PHY_MII_ADVERTISE_10HALF_LEN, 1); + } else { + regval = FXGMAC_SET_REG_BITS(regval, + PHY_MII_ADVERTISE_10HALF_POS, + PHY_MII_ADVERTISE_10HALF_LEN, 0); + } + + ret |= fxgmac_write_ephy_reg(pdata, REG_MII_ADVERTISE, regval); + /* after change the auto negotiation advertisement need to soft reset */ + fxgmac_read_ephy_reg(pdata, REG_MII_BMCR, ®val); + regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_RESET_POS, PHY_CR_RESET_LEN, + 1); + ret |= fxgmac_write_ephy_reg(pdata, REG_MII_BMCR, regval); + + return ret; +} + +static int fxgmac_phy_config(struct fxgmac_pdata *pdata) +{ + struct fxphy_ag_adv phy_ag_adv; + + if (pdata->phy_autoeng) { + phy_ag_adv.auto_neg_en = 1; + } else { + phy_ag_adv.auto_neg_en = 0; + } + switch (pdata->phy_speed) { + case SPEED_1000: + phy_ag_adv.full_1000m = 1, phy_ag_adv.half_1000m = 0, + phy_ag_adv.full_100m = 1, phy_ag_adv.half_100m = 1, + phy_ag_adv.full_10m = 1, phy_ag_adv.half_10m = 1; + break; + + case SPEED_100: + phy_ag_adv.full_1000m = 0, phy_ag_adv.half_1000m = 0; + if (pdata->phy_duplex) { + phy_ag_adv.full_100m = 1; + } else { + phy_ag_adv.full_100m = 0; + } + phy_ag_adv.half_100m = 1, phy_ag_adv.full_10m = 1, + phy_ag_adv.half_10m = 1; + break; + + case SPEED_10: + phy_ag_adv.full_1000m = 0, phy_ag_adv.half_1000m = 0; + phy_ag_adv.full_100m = 0, phy_ag_adv.half_100m = 0; + if (pdata->phy_duplex) { + phy_ag_adv.full_10m = 1; + } else { + phy_ag_adv.full_10m = 0; + } + phy_ag_adv.half_10m = 1; + break; + + default: + break; + } + return fxgmac_set_ephy_autoneg_advertise(pdata, phy_ag_adv); +} + +static void fxgmac_phy_green_ethernet(struct fxgmac_pdata *pdata) +{ + u32 regval = 0; + /* GREEN */ + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_REG_PMA_DBG0_ADC); + fxgmac_write_ephy_reg( + pdata, REG_MII_EXT_DATA, + REG_MII_EXT_ENABLE_GIGA_POWER_SAVING_FOR_SHORT_CABLE); + + /* CLD */ + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_REG_CLD_REG0); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + REG_MII_EXT_ENABLE_CLD_NP_WP); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_REG_CLD_REG1); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + REG_MII_EXT_ENABLE_CLD_GT_HT_BT); + + /* after change green ethernet & CLD need to soft reset */ + fxgmac_read_ephy_reg(pdata, REG_MII_BMCR, ®val); + regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_RESET_POS, PHY_CR_RESET_LEN, + 1); + fxgmac_write_ephy_reg(pdata, REG_MII_BMCR, regval); +} + +static void fxgmac_phy_eee_feature(struct fxgmac_pdata *pdata) +{ + u32 regval = 0; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + DMA_SBMR); + regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_EN_LPI_POS, + DMA_SBMR_EN_LPI_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_LPI_XIT_PKT_POS, + DMA_SBMR_LPI_XIT_PKT_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_AALE_POS, + DMA_SBMR_AALE_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + DMA_SBMR); + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_LPI_STA); + regval = FXGMAC_SET_REG_BITS(regval, MAC_LPIATE_POS, MAC_LPIATE_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, MAC_LPITXA_POS, MAC_LPITXA_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, MAC_PLS_POS, MAC_PLS_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, MAC_LPIEN_POS, MAC_LPIEN_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_LPI_STA); + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_LPI_TIMER); + regval = FXGMAC_SET_REG_BITS(regval, MAC_LPIET_POS, MAC_LPIET_LEN, + MAC_LPI_ENTRY_TIMER); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_LPI_TIMER); + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_LPI_CONTROL); + regval = FXGMAC_SET_REG_BITS(regval, MAC_TWT_POS, MAC_TWT_LEN, + MAC_TWT_TIMER); + regval = FXGMAC_SET_REG_BITS(regval, MAC_LST_POS, MAC_LST_LEN, + MAC_LST_TIMER); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_LPI_CONTROL); + + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_MS_TIC_COUNTER); + regval = FXGMAC_SET_REG_BITS(regval, MAC_MS_TIC_POS, MAC_MS_TIC_LEN, + MAC_MS_TIC); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_MS_TIC_COUNTER); + + fxgmac_write_ephy_mmd_reg(pdata, REG_MMD_EEE_ABILITY_REG, 0x07, + REG_MMD_EEE_ABILITY_VALUE); + + /* after change EEE need to soft reset */ + fxgmac_read_ephy_reg(pdata, REG_MII_BMCR, ®val); + regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_RESET_POS, PHY_CR_RESET_LEN, + 1); + fxgmac_write_ephy_reg(pdata, REG_MII_BMCR, regval); +} + +static void fxgmac_reset_phy(struct fxgmac_pdata *pdata) +{ + u32 value = 0; + + value = FXGMAC_SET_REG_BITS(value, MGMT_EPHY_CTRL_RESET_POS, + MGMT_EPHY_CTRL_RESET_LEN, + MGMT_EPHY_CTRL_STA_EPHY_RESET); + writereg(pdata->pAdapter, value, pdata->base_mem + MGMT_EPHY_CTRL); + usleep_range_ex(pdata->pAdapter, 1500, 1500); +} + +void fxgmac_release_phy(struct fxgmac_pdata *pdata) +{ + u32 value = 0; + + value = FXGMAC_SET_REG_BITS(value, MGMT_EPHY_CTRL_RESET_POS, + MGMT_EPHY_CTRL_RESET_LEN, + MGMT_EPHY_CTRL_STA_EPHY_RELEASE); + writereg(pdata->pAdapter, value, pdata->base_mem + MGMT_EPHY_CTRL); + usleep_range_ex(pdata->pAdapter, 100, 150); + value = readreg(pdata->pAdapter, pdata->base_mem + MGMT_EPHY_CTRL); + DBGPRINT(MP_LOUD, ("0x1004: 0x%x\n", value)); +#ifdef AISC_MODE + fxgmac_read_ephy_reg(pdata, REG_MII_SPEC_CTRL, + &value); /* read phy specific control */ + value = FXGMAC_SET_REG_BITS(value, PHY_MII_SPEC_CTRL_CRS_ON_POS, + PHY_MII_SPEC_CTRL_CRS_ON_LEN, + 1); /* set on crs on */ + fxgmac_write_ephy_reg(pdata, REG_MII_SPEC_CTRL, + value); /* phy specific control set on crs on */ + + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_ANALOG_CFG3); + fxgmac_read_ephy_reg(pdata, REG_MII_EXT_DATA, &value); + /* VGA bandwidth, default is 2 after reset. Set to 0 to mitigate unstable issue in 130m. */ + value = FXGMAC_SET_REG_BITS(value, + MII_EXT_ANALOG_CFG3_ADC_START_CFG_POS, + MII_EXT_ANALOG_CFG3_ADC_START_CFG_LEN, + MII_EXT_ANALOG_CFG3_ADC_START_CFG_DEFAULT); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, value); + + fxgmac_efuse_read_data(pdata, EFUSE_LED_ADDR, &value); + /* led index use bit0~bit5 */ + value = FXGMAC_GET_REG_BITS(value, EFUSE_LED_POS, EFUSE_LED_LEN); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_ANALOG_CFG2); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + REG_MII_EXT_ANALOG_CFG2_LED_VALUE); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_ANALOG_CFG8); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + REG_MII_EXT_ANALOG_CFG8_LED_VALUE); + + if (EFUSE_LED_COMMON_SOLUTION != value) { + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED0_CFG); + switch (value) { + case EFUSE_LED_SOLUTION1: + fxgmac_write_ephy_reg( + pdata, REG_MII_EXT_DATA, + REG_MII_EXT_COMMON_LED0_CFG_VALUE_SOLUTION1); + break; + case EFUSE_LED_SOLUTION2: + fxgmac_write_ephy_reg( + pdata, REG_MII_EXT_DATA, + REG_MII_EXT_COMMON_LED0_CFG_VALUE_SOLUTION2); + break; + case EFUSE_LED_SOLUTION3: + case EFUSE_LED_SOLUTION4: + fxgmac_write_ephy_reg( + pdata, REG_MII_EXT_DATA, + REG_MII_EXT_COMMON_LED0_CFG_VALUE_SOLUTION3); + break; + default: + /* default solution */ + fxgmac_write_ephy_reg( + pdata, REG_MII_EXT_DATA, + REG_MII_EXT_COMMON_LED0_CFG_VALUE_SOLUTION0); + break; + } + + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED1_CFG); + switch (value) { + case EFUSE_LED_SOLUTION1: + case EFUSE_LED_SOLUTION4: + fxgmac_write_ephy_reg( + pdata, REG_MII_EXT_DATA, + REG_MII_EXT_COMMON_LED1_CFG_VALUE_SOLUTION1); + break; + case EFUSE_LED_SOLUTION2: + case EFUSE_LED_SOLUTION3: + fxgmac_write_ephy_reg( + pdata, REG_MII_EXT_DATA, + REG_MII_EXT_COMMON_LED1_CFG_VALUE_SOLUTION2); + break; + default: + /* default solution */ + fxgmac_write_ephy_reg( + pdata, REG_MII_EXT_DATA, + REG_MII_EXT_COMMON_LED1_CFG_VALUE_SOLUTION0); + break; + } + + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED2_CFG); + switch (value) { + case EFUSE_LED_SOLUTION1: + fxgmac_write_ephy_reg( + pdata, REG_MII_EXT_DATA, + REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION0); + break; + case EFUSE_LED_SOLUTION2: + fxgmac_write_ephy_reg( + pdata, REG_MII_EXT_DATA, + REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION2); + break; + case EFUSE_LED_SOLUTION3: + fxgmac_write_ephy_reg( + pdata, REG_MII_EXT_DATA, + REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION3); + break; + case EFUSE_LED_SOLUTION4: + fxgmac_write_ephy_reg( + pdata, REG_MII_EXT_DATA, + REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION4); + break; + default: + /* default solution */ + fxgmac_write_ephy_reg( + pdata, REG_MII_EXT_DATA, + REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION0); + break; + } + + if (EFUSE_LED_SOLUTION2 == value) { + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED_BLINK_CFG); + fxgmac_write_ephy_reg( + pdata, REG_MII_EXT_DATA, + REG_MII_EXT_COMMON_LED_BLINK_CFG_SOLUTION2); + } + } +#endif +} + +static void fxgmac_enable_phy_check(struct fxgmac_pdata *pdata) +{ + u32 value = 0; + + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_PKG_CFG0); + fxgmac_read_ephy_reg(pdata, REG_MII_EXT_DATA, &value); + value = FXGMAC_SET_REG_BITS(value, REG_MII_EXT_PKG_CHECK_POS, + REG_MII_EXT_PKG_CHECK_LEN, + REG_MII_EXT_PKG_ENABLE_CHECK); + + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_PKG_CFG0); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, value); +} + +static void fxgmac_disable_phy_check(struct fxgmac_pdata *pdata) +{ + u32 value = 0; + + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_PKG_CFG0); + fxgmac_read_ephy_reg(pdata, REG_MII_EXT_DATA, &value); + value = FXGMAC_SET_REG_BITS(value, REG_MII_EXT_PKG_CHECK_POS, + REG_MII_EXT_PKG_CHECK_LEN, + REG_MII_EXT_PKG_DISABLE_CHECK); + + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_PKG_CFG0); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, value); +} + +static void fxgmac_setup_cable_loopback(struct fxgmac_pdata *pdata) +{ + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_SLEEP_CONTROL_REG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + REG_MII_EXT_SLEEP_REG_ENABLE_LOOPBACK); + + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_LPBK_REG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + REG_MII_EXT_LPBK_REG_ENABLE_LOOPBACK); + + fxgmac_write_ephy_reg(pdata, REG_MII_BMCR, + REG_MII_BMCR_ENABLE_LOOPBACK); +} + +static void fxgmac_clean_cable_loopback(struct fxgmac_pdata *pdata) +{ + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_SLEEP_CONTROL_REG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + REG_MII_EXT_SLEEP_REG_CLEAN_LOOPBACK); + + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, REG_MII_EXT_LPBK_REG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + REG_MII_EXT_LPBK_REG_CLEAN_LOOPBACK); + + fxgmac_write_ephy_reg(pdata, REG_MII_BMCR, + REG_MII_BMCR_DISABLE_LOOPBACK); +} + +static void fxgmac_disable_phy_sleep(struct fxgmac_pdata *pdata) +{ + u32 value = 0; + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_SLEEP_CONTROL_REG); + fxgmac_read_ephy_reg(pdata, REG_MII_EXT_DATA, &value); + + value = FXGMAC_SET_REG_BITS(value, MII_EXT_SLEEP_CONTROL1_EN_POS, + MII_EXT_SLEEP_CONTROL1_EN_LEN, 0); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_SLEEP_CONTROL_REG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, value); +} + +static void fxgmac_enable_phy_sleep(struct fxgmac_pdata *pdata) +{ + u32 value = 0; + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_SLEEP_CONTROL_REG); + fxgmac_read_ephy_reg(pdata, REG_MII_EXT_DATA, &value); + + value = FXGMAC_SET_REG_BITS(value, MII_EXT_SLEEP_CONTROL1_EN_POS, + MII_EXT_SLEEP_CONTROL1_EN_LEN, 1); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_SLEEP_CONTROL_REG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, value); +} + +static void fxgmac_close_phy_led(struct fxgmac_pdata *pdata) +{ + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED0_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, 0x00); + + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED1_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, 0x00); + + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED2_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, 0x00); +} + +static void fxmgac_config_led_under_active(struct fxgmac_pdata *pdata) +{ + u32 regval = 0; + fxgmac_efuse_read_data(pdata, EFUSE_LED_ADDR, ®val); + /* led index use bit0~bit5 */ + regval = FXGMAC_GET_REG_BITS(regval, EFUSE_LED_POS, EFUSE_LED_LEN); + if (EFUSE_LED_COMMON_SOLUTION == regval) { + DbgPrintF(MP_TRACE, "%s >>>", __FUNCTION__); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.s0_led_setting[0]); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED0_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.s0_led_setting[1]); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED1_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.s0_led_setting[2]); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED2_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.s0_led_setting[3]); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED_BLINK_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.s0_led_setting[4]); + } +} + +static void fxgmac_config_led_under_sleep(struct fxgmac_pdata *pdata) +{ + u32 regval = 0; + fxgmac_efuse_read_data(pdata, EFUSE_LED_ADDR, ®val); + /* led index use bit0~bit5 */ + regval = FXGMAC_GET_REG_BITS(regval, EFUSE_LED_POS, EFUSE_LED_LEN); + if (EFUSE_LED_COMMON_SOLUTION == regval) { + DbgPrintF(MP_TRACE, "%s >>>", __FUNCTION__); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.s3_led_setting[0]); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED0_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.s3_led_setting[1]); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED1_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.s3_led_setting[2]); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED2_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.s3_led_setting[3]); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED_BLINK_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.s3_led_setting[4]); + } +} + +static void fxgmac_config_led_under_shutdown(struct fxgmac_pdata *pdata) +{ + u32 regval = 0; + fxgmac_efuse_read_data(pdata, EFUSE_LED_ADDR, ®val); + /* led index use bit0~bit5 */ + regval = FXGMAC_GET_REG_BITS(regval, EFUSE_LED_POS, EFUSE_LED_LEN); + if (EFUSE_LED_COMMON_SOLUTION == regval) { + DbgPrintF(MP_TRACE, "%s >>>", __FUNCTION__); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.s5_led_setting[0]); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED0_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.s5_led_setting[1]); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED1_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.s5_led_setting[2]); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED2_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.s5_led_setting[3]); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED_BLINK_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.s5_led_setting[4]); + } +} + +static void fxgmac_config_led_under_disable(struct fxgmac_pdata *pdata) +{ + u32 regval = 0; + fxgmac_efuse_read_data(pdata, EFUSE_LED_ADDR, ®val); + /* led index use bit0~bit5 */ + regval = FXGMAC_GET_REG_BITS(regval, EFUSE_LED_POS, EFUSE_LED_LEN); + if (EFUSE_LED_COMMON_SOLUTION == regval) { + DbgPrintF(MP_TRACE, "%s >>>", __FUNCTION__); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.disable_led_setting[0]); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED0_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.disable_led_setting[1]); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED1_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.disable_led_setting[2]); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED2_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.disable_led_setting[3]); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED_BLINK_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, + pdata->led.disable_led_setting[4]); + } else { + /* http://redmine.motor-comm.com/issues/4101 */ + /* for disable case, reset phy to close LED */ + fxgmac_reset_phy(pdata); + } +} + +extern void fxgmac_diag_get_rx_info(struct fxgmac_channel *channel); + +static int fxgmac_dev_read(struct fxgmac_channel *channel) +{ + struct fxgmac_pdata *pdata = channel->pdata; + struct fxgmac_ring *ring = channel->rx_ring; + struct net_device *netdev = pdata->netdev; + struct fxgmac_desc_data *desc_data; + struct fxgmac_dma_desc *dma_desc; + struct fxgmac_pkt_info *pkt_info; + unsigned int err, etlt, l34t; + + static unsigned int cnt_incomplete; + + desc_data = FXGMAC_GET_DESC_DATA(ring, ring->cur); + dma_desc = desc_data->dma_desc; + pkt_info = &ring->pkt_info; + + /* Check for data availability */ + if (FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, RX_NORMAL_DESC3_OWN_POS, + RX_NORMAL_DESC3_OWN_LEN)) { + return 1; + } + + /* Make sure descriptor fields are read after reading the OWN bit */ + dma_rmb(); + + if (netif_msg_rx_status(pdata)) + fxgmac_dump_rx_desc(pdata, ring, ring->cur); + + if (FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, RX_NORMAL_DESC3_CTXT_POS, + RX_NORMAL_DESC3_CTXT_LEN)) { + /* Timestamp Context Descriptor */ + fxgmac_get_rx_tstamp(pkt_info, dma_desc); + + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, RX_PACKET_ATTRIBUTES_CONTEXT_POS, + RX_PACKET_ATTRIBUTES_CONTEXT_LEN, 1); + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, + RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_POS, + RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_LEN, 0); + if (netif_msg_rx_status(pdata)) + DPRINTK("dev_read context desc, ch=%s\n", channel->name); + return 0; + } + + /* Normal Descriptor, be sure Context Descriptor bit is off */ + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, RX_PACKET_ATTRIBUTES_CONTEXT_POS, + RX_PACKET_ATTRIBUTES_CONTEXT_LEN, 0); + + /* Get the header length */ + if (FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, RX_NORMAL_DESC3_FD_POS, + RX_NORMAL_DESC3_FD_LEN)) { + desc_data->rx.hdr_len = FXGMAC_GET_REG_BITS_LE( + dma_desc->desc2, RX_NORMAL_DESC2_HL_POS, + RX_NORMAL_DESC2_HL_LEN); + if (desc_data->rx.hdr_len) + pdata->stats.rx_split_header_packets++; + } + l34t = 0; + + /* Get the pkt_info length */ + desc_data->rx.len = FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, + RX_NORMAL_DESC3_PL_POS, + RX_NORMAL_DESC3_PL_LEN); + + if (!FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, RX_NORMAL_DESC3_LD_POS, + RX_NORMAL_DESC3_LD_LEN)) { + /* Not all the data has been transferred for this pkt_info */ + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, + RX_PACKET_ATTRIBUTES_INCOMPLETE_POS, + RX_PACKET_ATTRIBUTES_INCOMPLETE_LEN, 1); + cnt_incomplete++; + if ((cnt_incomplete < 2) && netif_msg_rx_status(pdata)) + DPRINTK("dev_read NOT last desc, pkt incomplete yet,%u\n", + cnt_incomplete); + + return 0; + } + if ((cnt_incomplete) && netif_msg_rx_status(pdata)) + DPRINTK("dev_read rx back to normal and incomplete cnt=%u\n", + cnt_incomplete); + cnt_incomplete = 0; /* when back to normal, reset cnt */ + + /* This is the last of the data for this pkt_info */ + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, RX_PACKET_ATTRIBUTES_INCOMPLETE_POS, + RX_PACKET_ATTRIBUTES_INCOMPLETE_LEN, 0); + + /* Set checksum done indicator as appropriate */ + if (netdev->features & NETIF_F_RXCSUM) + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, + RX_PACKET_ATTRIBUTES_CSUM_DONE_POS, + RX_PACKET_ATTRIBUTES_CSUM_DONE_LEN, 1); + + /* Check for errors (only valid in last descriptor) */ + err = FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, RX_NORMAL_DESC3_ES_POS, + RX_NORMAL_DESC3_ES_LEN); + etlt = FXGMAC_GET_REG_BITS_LE(dma_desc->desc3, RX_NORMAL_DESC3_ETLT_POS, + RX_NORMAL_DESC3_ETLT_LEN); + if ((err) && netif_msg_rx_status(pdata)) { + DPRINTK("dev_read:head_len=%u, pkt_len=%u, err=%u, etlt=%#x, desc2=0x%08x, desc3=0x%08x\n", + desc_data->rx.hdr_len, desc_data->rx.len, err, etlt, + dma_desc->desc2, dma_desc->desc3); + } + + if (!err || !etlt) { + /* No error if err is 0 or etlt is 0 */ + if ((etlt == 0x4 /*yzhang changed to 0x4, 0x09*/) && + (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) { + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, + RX_PACKET_ATTRIBUTES_VLAN_CTAG_POS, + RX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN, 1); + pkt_info->vlan_ctag = FXGMAC_GET_REG_BITS_LE( + dma_desc->desc0, RX_NORMAL_DESC0_OVT_POS, + RX_NORMAL_DESC0_OVT_LEN); + netif_dbg(pdata, rx_status, netdev, "vlan-ctag=%#06x\n", + pkt_info->vlan_ctag); + } + } else { + if (etlt == 0x05 || etlt == 0x06) + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, + RX_PACKET_ATTRIBUTES_CSUM_DONE_POS, + RX_PACKET_ATTRIBUTES_CSUM_DONE_LEN, 0); + else + pkt_info->errors = FXGMAC_SET_REG_BITS( + pkt_info->errors, RX_PACKET_ERRORS_FRAME_POS, + RX_PACKET_ERRORS_FRAME_LEN, 1); + } + + return 0; +} + +static int fxgmac_enable_int(struct fxgmac_channel *channel, + enum fxgmac_int int_id) +{ + unsigned int dma_ch_ier; + + dma_ch_ier = readreg(channel->pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_IER)); + + switch (int_id) { + case FXGMAC_INT_DMA_CH_SR_TI: + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, DMA_CH_IER_TIE_POS, + DMA_CH_IER_TIE_LEN, 1); + break; + case FXGMAC_INT_DMA_CH_SR_TPS: + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, + DMA_CH_IER_TXSE_POS, + DMA_CH_IER_TXSE_LEN, 1); + break; + case FXGMAC_INT_DMA_CH_SR_TBU: + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, + DMA_CH_IER_TBUE_POS, + DMA_CH_IER_TBUE_LEN, 1); + break; + case FXGMAC_INT_DMA_CH_SR_RI: + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, DMA_CH_IER_RIE_POS, + DMA_CH_IER_RIE_LEN, 1); + break; + case FXGMAC_INT_DMA_CH_SR_RBU: + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, + DMA_CH_IER_RBUE_POS, + DMA_CH_IER_RBUE_LEN, 1); + break; + case FXGMAC_INT_DMA_CH_SR_RPS: + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, DMA_CH_IER_RSE_POS, + DMA_CH_IER_RSE_LEN, 1); + break; + case FXGMAC_INT_DMA_CH_SR_TI_RI: + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, DMA_CH_IER_TIE_POS, + DMA_CH_IER_TIE_LEN, 1); + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, DMA_CH_IER_RIE_POS, + DMA_CH_IER_RIE_LEN, 1); + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, DMA_CH_IER_NIE_POS, + DMA_CH_IER_NIE_LEN, 1); + break; + case FXGMAC_INT_DMA_CH_SR_FBE: + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, + DMA_CH_IER_FBEE_POS, + DMA_CH_IER_FBEE_LEN, 1); + break; + case FXGMAC_INT_DMA_ALL: + dma_ch_ier |= channel->saved_ier; + break; + default: + return -1; + } + + writereg(channel->pdata->pAdapter, dma_ch_ier, + FXGMAC_DMA_REG(channel, DMA_CH_IER)); + + return 0; +} + +static int fxgmac_disable_int(struct fxgmac_channel *channel, + enum fxgmac_int int_id) +{ + unsigned int dma_ch_ier; + + dma_ch_ier = readreg(channel->pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_IER)); + + switch (int_id) { + case FXGMAC_INT_DMA_CH_SR_TI: + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, DMA_CH_IER_TIE_POS, + DMA_CH_IER_TIE_LEN, 0); + break; + case FXGMAC_INT_DMA_CH_SR_TPS: + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, + DMA_CH_IER_TXSE_POS, + DMA_CH_IER_TXSE_LEN, 0); + break; + case FXGMAC_INT_DMA_CH_SR_TBU: + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, + DMA_CH_IER_TBUE_POS, + DMA_CH_IER_TBUE_LEN, 0); + break; + case FXGMAC_INT_DMA_CH_SR_RI: + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, DMA_CH_IER_RIE_POS, + DMA_CH_IER_RIE_LEN, 0); + break; + case FXGMAC_INT_DMA_CH_SR_RBU: + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, + DMA_CH_IER_RBUE_POS, + DMA_CH_IER_RBUE_LEN, 0); + break; + case FXGMAC_INT_DMA_CH_SR_RPS: + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, DMA_CH_IER_RSE_POS, + DMA_CH_IER_RSE_LEN, 0); + break; + case FXGMAC_INT_DMA_CH_SR_TI_RI: + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, DMA_CH_IER_TIE_POS, + DMA_CH_IER_TIE_LEN, 0); + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, DMA_CH_IER_RIE_POS, + DMA_CH_IER_RIE_LEN, 0); + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, DMA_CH_IER_NIE_POS, + DMA_CH_IER_NIE_LEN, 0); + break; + case FXGMAC_INT_DMA_CH_SR_FBE: + dma_ch_ier = FXGMAC_SET_REG_BITS(dma_ch_ier, + DMA_CH_IER_FBEE_POS, + DMA_CH_IER_FBEE_LEN, 0); + break; + case FXGMAC_INT_DMA_ALL: + channel->saved_ier = dma_ch_ier & FXGMAC_DMA_INTERRUPT_MASK; + dma_ch_ier &= ~FXGMAC_DMA_INTERRUPT_MASK; + break; + default: + return -1; + } + + writereg(channel->pdata->pAdapter, dma_ch_ier, + FXGMAC_DMA_REG(channel, DMA_CH_IER)); + + return 0; +} + +static int fxgmac_dismiss_DMA_int(struct fxgmac_channel *channel, int int_id) +{ + unsigned int dma_ch_ier; + + int_id = int_id; + dma_ch_ier = readreg(channel->pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_SR /*1160*/)); + writereg(channel->pdata->pAdapter, dma_ch_ier, + FXGMAC_DMA_REG(channel, DMA_CH_SR)); + + return 0; +} + +static void fxgmac_dismiss_MTL_Q_int(struct fxgmac_pdata *pdata) +{ + unsigned int q_count, i; + unsigned int mtl_q_isr; + + 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 = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_Q_ISR)); + writereg(pdata->pAdapter, mtl_q_isr, + FXGMAC_MTL_REG(pdata, i, MTL_Q_ISR)); + } +} + +static int fxgmac_dismiss_MAC_int(struct fxgmac_pdata *pdata) +{ + u32 regval, regErrVal; + + /* all MAC interrupts in 0xb0 */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_ISR); + /* MAC tx/rx error interrupts in 0xb8 */ + regErrVal = readreg(pdata->pAdapter, pdata->mac_regs + MAC_TX_RX_STA); + return 0; +} + +static int fxgmac_dismiss_MAC_PMT_int(struct fxgmac_pdata *pdata) +{ + u32 regval; + + /* MAC PMT interrupts in 0xc0 */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); + return 0; +} + +static int fxgmac_dismiss_MAC_LPI_int(struct fxgmac_pdata *pdata) +{ + u32 regval; + + /* MAC PMT interrupts in 0xc0 */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_LPI_STA); + + return 0; +} + +static int fxgmac_dismiss_MAC_DBG_int(struct fxgmac_pdata *pdata) +{ + u32 regval; + + /* MAC PMT interrupts in 0xc0 */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_DBG_STA); + + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_DBG_STA); + + return 0; +} + +int fxgmac_dismiss_all_int(struct fxgmac_pdata *pdata) +{ + struct fxgmac_channel *channel; + unsigned int i, regval; + struct net_device *netdev = pdata->netdev; + + if (netif_msg_drv(pdata)) { + DPRINTK("fxgmac_dismiss_all_int callin\n"); + } + + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + fxgmac_dismiss_DMA_int(channel, 0); + } + fxgmac_dismiss_MTL_Q_int(pdata); + fxgmac_dismiss_MAC_int(pdata); + fxgmac_dismiss_MAC_PMT_int(pdata); + fxgmac_dismiss_MAC_LPI_int(pdata); + fxgmac_dismiss_MAC_DBG_int(pdata); + + /* control module int to PCIe slot */ + if (netdev->base_addr) { + regval = (unsigned int)(*( + (u32 *)(netdev->base_addr + MGMT_INT_CTRL0))); + } + return 0; +} + +static void fxgmac_set_interrupt_moderation(struct fxgmac_pdata *pdata) +{ + u32 value = 0, time; + + pdata->intr_mod_timer = INT_MOD_IN_US; + + time = (pdata->intr_mod) ? pdata->intr_mod_timer : 0; + time = (pdata->intr_mod) ? pdata->tx_usecs : 0; + value = FXGMAC_SET_REG_BITS(value, INT_MOD_TX_POS, INT_MOD_TX_LEN, + time); + time = (pdata->intr_mod) ? pdata->rx_usecs : 0; + value = FXGMAC_SET_REG_BITS(value, INT_MOD_RX_POS, INT_MOD_RX_LEN, + time); + writereg(pdata->pAdapter, value, pdata->base_mem + INT_MOD); +} +static void fxgmac_enable_msix_rxtxinterrupt(struct fxgmac_pdata *pdata) +{ + u32 intid; + + for (intid = 0; intid < MSIX_TBL_RXTX_NUM; intid++) { + writereg(pdata->pAdapter, 0, + pdata->base_mem + MSIX_TBL_BASE_ADDR + + MSIX_TBL_MASK_OFFSET + intid * 16); + } +} +static void fxgmac_disable_msix_interrupt(struct fxgmac_pdata *pdata) +{ + u32 intid; + + for (intid = 0; intid < MSIX_TBL_MAX_NUM; intid++) { + writereg(pdata->pAdapter, 0x1, + pdata->base_mem + MSIX_TBL_BASE_ADDR + + MSIX_TBL_MASK_OFFSET + intid * 16); + } +} +static void fxgmac_enable_msix_rxtxphyinterrupt(struct fxgmac_pdata *pdata) +{ + u32 intid, regval = 0; +#if !(FUXI_EPHY_INTERRUPT_D0_OFF) + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; +#endif + + for (intid = 0; intid < MSIX_TBL_RXTX_NUM; intid++) { + writereg(pdata->pAdapter, 0, + pdata->base_mem + MSIX_TBL_BASE_ADDR + + MSIX_TBL_MASK_OFFSET + intid * 16); + } + writereg(pdata->pAdapter, 0, + pdata->base_mem + MSIX_TBL_BASE_ADDR + MSIX_TBL_MASK_OFFSET + + MSI_ID_PHY_OTHER * 16); +#if !(FUXI_EPHY_INTERRUPT_D0_OFF) + hw_ops->read_ephy_reg(pdata, REG_MII_INT_STATUS, + NULL); /* clear phy interrupt */ + regval = FXGMAC_SET_REG_BITS(0, PHY_INT_MASK_LINK_UP_POS, + PHY_INT_MASK_LINK_UP_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, PHY_INT_MASK_LINK_DOWN_POS, + PHY_INT_MASK_LINK_DOWN_LEN, 1); + hw_ops->write_ephy_reg( + pdata, REG_MII_INT_MASK, + regval); /* enable phy interrupt ASIC bit10 linkup bit11 linkdown */ +#endif +} +static void fxgmac_enable_msix_one_interrupt(struct fxgmac_pdata *pdata, + u32 intid) +{ + writereg(pdata->pAdapter, 0, + pdata->base_mem + MSIX_TBL_BASE_ADDR + MSIX_TBL_MASK_OFFSET + + intid * 16); +} + +static void fxgmac_disable_msix_one_interrupt(struct fxgmac_pdata *pdata, + u32 intid) +{ + writereg(pdata->pAdapter, 0x01, + pdata->base_mem + MSIX_TBL_BASE_ADDR + MSIX_TBL_MASK_OFFSET + + intid * 16); +} + +static bool fxgmac_enable_mgm_interrupt(struct fxgmac_pdata *pdata) +{ + writereg(pdata->pAdapter, 0xf0000000, pdata->base_mem + MGMT_INT_CTRL0); + return true; +} + +static bool fxgmac_disable_mgm_interrupt(struct fxgmac_pdata *pdata) +{ + writereg(pdata->pAdapter, 0xffff0000, pdata->base_mem + MGMT_INT_CTRL0); + return true; +} + +static int fxgmac_flush_tx_queues(struct fxgmac_pdata *pdata) +{ + unsigned int i, count; + u32 regval; + + for (i = 0; i < pdata->tx_q_count; i++) { + regval = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); + regval = FXGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_FTQ_POS, + MTL_Q_TQOMR_FTQ_LEN, 1); + writereg(pdata->pAdapter, regval, + FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); + DPRINTK("fxgmac_flush_tx_queues, reg=0x%p, val=0x%08x\n", + FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR), regval); + } + + for (i = 0; i < pdata->tx_q_count; i++) { + count = 2000; + do { + usleep_range_ex(pdata->pAdapter, 40, 50); + regval = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR)); + regval = FXGMAC_GET_REG_BITS(regval, + MTL_Q_TQOMR_FTQ_POS, + MTL_Q_TQOMR_FTQ_LEN); + + } while (--count && regval); + DPRINTK("fxgmac_flush_tx_queues wait... reg=0x%p, val=0x%08x\n", + FXGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR), regval); + if (regval) { /*(!count)*/ + return -EBUSY; + } + } + + return 0; +} + +static void fxgmac_config_dma_bus(struct fxgmac_pdata *pdata) +{ + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->mac_regs + DMA_SBMR); + /* Set enhanced addressing mode */ + regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_EAME_POS, + DMA_SBMR_EAME_LEN, 1); + /* Set the System Bus mode */ + regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_FB_POS, DMA_SBMR_FB_LEN, + 0); + regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_BLEN_4_POS, + DMA_SBMR_BLEN_4_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_BLEN_8_POS, + DMA_SBMR_BLEN_8_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_BLEN_16_POS, + DMA_SBMR_BLEN_16_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, DMA_SBMR_BLEN_32_POS, + DMA_SBMR_BLEN_32_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + DMA_SBMR); +} + +static void fxgmac_legacy_link_speed_setting(struct fxgmac_pdata *pdata) +{ + unsigned int i = 0, regval = 0; + + fxgmac_phy_config(pdata); + for (i = 0, regval = fxgmac_get_ephy_state(pdata); + (!(regval & MGMT_EPHY_CTRL_STA_EPHY_RELEASE) || + !(regval & MGMT_EPHY_CTRL_STA_EPHY_LINKUP)) && + (i < PHY_LINK_TIMEOUT); + regval = fxgmac_get_ephy_state(pdata), i++) { + usleep_range_ex(pdata->pAdapter, 2000, 2000); + } + fxgmac_read_ephy_reg(pdata, REG_MII_INT_STATUS, + NULL); /* clear phy interrupt. */ +} + +static void fxgmac_pre_powerdown(struct fxgmac_pdata *pdata, bool phyloopback) +{ + unsigned int regval = 0; + + fxgmac_disable_rx(pdata); + + /* HERE, WE NEED TO CONSIDER PHY CONFIG...TBD */ + DPRINTK("fxgmac_config_powerdown, phy and mac status update\n"); + /* for phy cable loopback, it can't configure phy speed, it will cause os resume again by link change although it has finished speed setting, */ + if (!phyloopback) { + /* When the Linux platform enters the s4 state, it goes through + * the suspend->resume->suspend process. The process of + * suspending again after resume is fast, and PHY + * auto-negotiation is not yet complete, so the + * auto-negotiation of PHY must be carried out again. When the + * Linux platform enters the s4 state, force speed to 10M. + */ + pdata->phy_speed = SPEED_10; + fxgmac_legacy_link_speed_setting(pdata); + } + + fxgmac_config_mac_speed(pdata); + + /* After enable OOB_WOL from efuse, mac will loopcheck phy status, and + * lead to panic sometimes. So we should disable it from powerup, + * enable it from power down. + */ + regval = (u32)readreg(pdata->pAdapter, pdata->base_mem + OOB_WOL_CTRL); + regval = FXGMAC_SET_REG_BITS(regval, OOB_WOL_CTRL_DIS_POS, + OOB_WOL_CTRL_DIS_LEN, 0); + writereg(pdata->pAdapter, regval, pdata->base_mem + OOB_WOL_CTRL); + usleep_range_ex(pdata->pAdapter, 2000, 2000); + + /* after enable OOB_WOL, recofigure mac addr again */ + fxgmac_set_mac_address(pdata, pdata->mac_addr); +} + +/* only supports four patterns, and patterns will be cleared on every call */ +static void fxgmac_set_pattern_data(struct fxgmac_pdata *pdata) +{ + u32 ip_addr, i = 0; + u8 type_offset, op_offset, tip_offset; + struct pattern_packet packet; + struct wol_bitmap_pattern + pattern[4]; /* for WAKE_UCAST, WAKE_BCAST, WAKE_MCAST, WAKE_ARP. */ + + memset(pattern, 0, sizeof(struct wol_bitmap_pattern) * 4); + + /* config ucast */ + if (pdata->expansion.wol & WAKE_UCAST) { + pattern[i].mask_info[0] = 0x3F; + pattern[i].mask_size = sizeof(pattern[0].mask_info); + memcpy(pattern[i].pattern_info, pdata->mac_addr, ETH_ALEN); + pattern[i].pattern_offset = 0; + i++; + } + + /* config bcast */ + if (pdata->expansion.wol & WAKE_BCAST) { + pattern[i].mask_info[0] = 0x3F; + pattern[i].mask_size = sizeof(pattern[0].mask_info); + memset(pattern[i].pattern_info, 0xFF, ETH_ALEN); + pattern[i].pattern_offset = 0; + i++; + } + + /* config mcast */ + if (pdata->expansion.wol & WAKE_MCAST) { + pattern[i].mask_info[0] = 0x7; + pattern[i].mask_size = sizeof(pattern[0].mask_info); + pattern[i].pattern_info[0] = 0x1; + pattern[i].pattern_info[1] = 0x0; + pattern[i].pattern_info[2] = 0x5E; + pattern[i].pattern_offset = 0; + i++; + } + + /* config arp */ + if (pdata->expansion.wol & WAKE_ARP) { + memset(pattern[i].mask_info, 0, sizeof(pattern[0].mask_info)); + type_offset = offsetof(struct pattern_packet, ar_pro); + pattern[i].mask_info[type_offset / 8] |= 1 << type_offset % 8; + type_offset++; + pattern[i].mask_info[type_offset / 8] |= 1 << type_offset % 8; + op_offset = offsetof(struct pattern_packet, ar_op); + pattern[i].mask_info[op_offset / 8] |= 1 << op_offset % 8; + op_offset++; + pattern[i].mask_info[op_offset / 8] |= 1 << op_offset % 8; + tip_offset = offsetof(struct pattern_packet, ar_tip); + pattern[i].mask_info[tip_offset / 8] |= 1 << tip_offset % 8; + tip_offset++; + pattern[i].mask_info[tip_offset / 8] |= 1 << type_offset % 8; + tip_offset++; + pattern[i].mask_info[tip_offset / 8] |= 1 << type_offset % 8; + tip_offset++; + pattern[i].mask_info[tip_offset / 8] |= 1 << type_offset % 8; + + packet.ar_pro = + 0x0 << 8 | + 0x08; /* arp type is 0x0800, notice that ar_pro and ar_op is big endian */ + packet.ar_op = + 0x1 + << 8; /* 1 is arp request,2 is arp replay, 3 is rarp request, 4 is rarp replay */ + ip_addr = fxgmac_get_netdev_ip4addr(pdata); + packet.ar_tip[0] = ip_addr & 0xFF; + packet.ar_tip[1] = (ip_addr >> 8) & 0xFF; + packet.ar_tip[2] = (ip_addr >> 16) & 0xFF; + packet.ar_tip[3] = (ip_addr >> 24) & 0xFF; + memcpy(pattern[i].pattern_info, &packet, MAX_PATTERN_SIZE); + pattern[i].mask_size = sizeof(pattern[0].mask_info); + pattern[i].pattern_offset = 0; + i++; + } + + fxgmac_set_wake_pattern(pdata, pattern, i); +} + +static void fxgmac_config_powerdown(struct fxgmac_pdata *pdata, + unsigned int wol) +{ + u32 regval = 0; + + fxgmac_disable_tx(pdata); + fxgmac_disable_rx(pdata); + + /* performs fxgmac power down sequence + * 1. set led + * 2. check wol. + * 3. check arp offloading + * 4. disable gmac rx + * 5. set gmac power down + */ + + /* Close LED when entering the S3, S4, S5 except solution3 */ + fxgmac_efuse_read_data(pdata, EFUSE_LED_ADDR, ®val); + /* led index use bit0~bit5 */ + regval = FXGMAC_GET_REG_BITS(regval, EFUSE_LED_POS, EFUSE_LED_LEN); + if (EFUSE_LED_COMMON_SOLUTION != regval) { + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED0_CFG); + if (EFUSE_LED_SOLUTION3 == regval) { + fxgmac_write_ephy_reg( + pdata, REG_MII_EXT_DATA, + REG_MII_EXT_COMMON_LED0_CFG_VALUE_SLEEP_SOLUTION3); + } else { + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, 0x00); + } + + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED1_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, 0x00); + + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_COMMON_LED2_CFG); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, 0x00); + } + + if (!test_bit(FXGMAC_POWER_STATE_DOWN, &pdata->expansion.powerstate)) { + netdev_err( + pdata->netdev, + "fxgmac powerstate is %lu when config power to down.\n", + pdata->expansion.powerstate); + } + +#if FXGMAC_WOL_FEATURE_ENABLED + fxgmac_config_wol(pdata, wol); +#endif +#if FXGMAC_AOE_FEATURE_ENABLED + /* use default arp offloading feature */ + fxgmac_update_aoe_ipv4addr(pdata, (u8 *)NULL); + fxgmac_enable_arp_offload(pdata); +#endif + +#if FXGMAC_NS_OFFLOAD_ENABLED + /* pls do not change the seq below */ + fxgmac_update_ns_offload_ipv6addr(pdata, FXGMAC_NS_IFA_GLOBAL_UNICAST); + fxgmac_update_ns_offload_ipv6addr(pdata, FXGMAC_NS_IFA_LOCAL_LINK); + fxgmac_enable_ns_offload(pdata); +#endif + + /* Enable MAC Rx TX */ + if (1) { + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_RE_POS, + MAC_CR_RE_LEN, 1); + if (pdata->hw_feat.aoe) { + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_TE_POS, + MAC_CR_TE_LEN, 1); + } + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); + } + + regval = readreg(pdata->pAdapter, pdata->base_mem + LPW_CTRL); + regval = FXGMAC_SET_REG_BITS(regval, LPW_CTRL_ASPM_LPW_EN_POS, + LPW_CTRL_ASPM_LPW_EN_LEN, + 1); /* Enable PCIE PM_L23. */ + + writereg(pdata->pAdapter, regval, pdata->base_mem + LPW_CTRL); + + /* set gmac power down */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); + regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_PWRDWN_POS, + MAC_PMT_STA_PWRDWN_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PMT_STA); + + /* adjust sigdet threshold + * redmine.motor-comm.com/issues/5093 + * fix issue can not wake up os on some FT-D2000 platform, y + * this modification is only temporarif it is 55mv, wol maybe failed. + */ + + regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_SIGDET); + regval = FXGMAC_SET_REG_BITS(regval, MGMT_SIGDET_POS, MGMT_SIGDET_LEN, + MGMT_SIGDET_40MV); + writereg(pdata->pAdapter, regval, pdata->base_mem + MGMT_SIGDET); + DPRINTK("fxgmac_config_powerdown callout, reg=0x%08x\n", regval); +} + +static void fxgmac_config_powerup(struct fxgmac_pdata *pdata) +{ + u32 regval = 0; + + if (test_bit(FXGMAC_POWER_STATE_DOWN, &pdata->expansion.powerstate)) { + netdev_err( + pdata->netdev, + "fxgmac powerstate is %lu when config power to up.\n", + pdata->expansion.powerstate); + } + + /* After enable OOB_WOL from efuse, mac will loopcheck phy status, and lead to panic sometimes. + * So we should disable it from powerup, enable it from power down. + */ + regval = (u32)readreg(pdata->pAdapter, pdata->base_mem + OOB_WOL_CTRL); + regval = FXGMAC_SET_REG_BITS(regval, OOB_WOL_CTRL_DIS_POS, + OOB_WOL_CTRL_DIS_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->base_mem + OOB_WOL_CTRL); + + /* clear wpi mode whether or not waked by WOL, write reset value */ + regval = + (u32)readreg(pdata->pAdapter, pdata->base_mem + MGMT_WPI_CTRL0); + + regval = FXGMAC_SET_REG_BITS(regval, MGMT_WPI_CTRL0_WPI_MODE_POS, + MGMT_WPI_CTRL0_WPI_MODE_LEN, 0); + writereg(pdata->pAdapter, regval, pdata->base_mem + MGMT_WPI_CTRL0); + /* read pmt_status register to De-assert the pmt_intr_o */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_PMT_STA); + /* wether or not waked up by WOL, write reset value */ + regval = FXGMAC_SET_REG_BITS(regval, MAC_PMT_STA_PWRDWN_POS, + MAC_PMT_STA_PWRDWN_LEN, 0); + /* write register to synchronized always-on block */ + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_PMT_STA); + + /* Disable fast link mode*/ + cfg_r32(pdata, REG_POWER_EIOS, ®val); + regval = FXGMAC_SET_REG_BITS(regval, POWER_EIOS_POS, POWER_EIOS_LEN, 0); + cfg_w32(pdata, REG_POWER_EIOS, regval); + + fxgmac_pwr_clock_gate(pdata); +} + +#if FXGMAC_SANITY_CHECK_ENABLED +/* + * fxgmac_diag_sanity_check + * check if there is any error like tx q hang + * return: 0 normal and other fatal error + */ +static int fxgmac_diag_sanity_check(struct fxgmac_pdata *pdata) +{ + u32 reg_q_val, reg_tail_val; + static u32 reg_tail_pre; + static int cnt; + + reg_q_val = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, 0 /* tx channe 0 */, + 0x8 /* 0x2d08 */)); + if (!(reg_q_val & 0x10)) { /* tx q is empty */ + return 0; + } + reg_tail_val = + readreg(pdata->pAdapter, + FXGMAC_DMA_REG(pdata->channel_head, DMA_CH_TDTR_LO)); + if (reg_tail_pre != reg_tail_val) { + reg_tail_pre = reg_tail_val; + cnt = 0; + } else { + cnt++; + } + + if (cnt > 10) { + reg_q_val = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, 0 /* tx channe 0 */, + 0x8 /* 0x2d08 */)); + if (reg_q_val & 0x10) { /* double check */ + DPRINTK("fxgmac, WARNing, tx Q status is 0x%x and tail keeps unchanged for %d times, 0x%x\n", + reg_q_val, cnt, reg_tail_val); + return 1; + } + } + + return 0; +} +#endif +static void fxgmac_pwr_clock_gate(struct fxgmac_pdata *pdata) +{ + u32 regval = 0; + + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_SLEEP_CONTROL1); + fxgmac_read_ephy_reg(pdata, REG_MII_EXT_DATA, ®val); + /* close pll in sleep mode */ + regval = FXGMAC_SET_REG_BITS(regval, + MII_EXT_SLEEP_CONTROL1_PLLON_IN_SLP_POS, + MII_EXT_SLEEP_CONTROL1_PLLON_IN_SLP_LEN, + 0); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, regval); +} +static void fxgmac_pwr_clock_ungate(struct fxgmac_pdata *pdata) +{ + u32 regval = 0; + + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_ADDR, + REG_MII_EXT_SLEEP_CONTROL1); + fxgmac_read_ephy_reg(pdata, REG_MII_EXT_DATA, ®val); + /* keep pll in sleep mode */ + regval = FXGMAC_SET_REG_BITS(regval, + MII_EXT_SLEEP_CONTROL1_PLLON_IN_SLP_POS, + MII_EXT_SLEEP_CONTROL1_PLLON_IN_SLP_LEN, + 1); + fxgmac_write_ephy_reg(pdata, REG_MII_EXT_DATA, regval); +} + +/* context - pointer to struct nic_pdata. */ +static unsigned char fxgmac_suspend_int(void *context) +{ + /* ULONG_PTR addr; */ + u32 intid; +#if FUXI_EPHY_INTERRUPT_D0_OFF + u32 regval = 0; +#endif + u32 val_mgmt_intcrtl0; + struct fxgmac_pdata *pdata = (struct fxgmac_pdata *)context; + + val_mgmt_intcrtl0 = + (u32)readreg(pdata->pAdapter, pdata->base_mem + MGMT_INT_CTRL0); + /* disable management interrupts. enable only pmt interrupts. */ + val_mgmt_intcrtl0 = FXGMAC_SET_REG_BITS(val_mgmt_intcrtl0, + MGMT_INT_CTRL0_INT_MASK_POS, + MGMT_INT_CTRL0_INT_MASK_LEN, + MGMT_INT_CTRL0_INT_MASK_EX_PMT); + writereg(pdata->pAdapter, val_mgmt_intcrtl0, + pdata->base_mem + MGMT_INT_CTRL0); + + for (intid = 0; intid < MSIX_TBL_MAX_NUM; + intid++) { /* disable all msix */ + writereg(pdata->pAdapter, 0x1, + pdata->base_mem + MSIX_TBL_BASE_ADDR + + MSIX_TBL_MASK_OFFSET + intid * 16); + } + + /* enable pmt msix */ + writereg(pdata->pAdapter, 0x0, + pdata->base_mem + MSIX_TBL_BASE_ADDR + MSIX_TBL_MASK_OFFSET + + MSI_ID_PHY_OTHER * 16); + readreg(pdata->pAdapter, + pdata->base_mem + + MGMT_WOL_CTRL); /* read clear wake up reason */ + /* since Msix interrupt masked now, enable EPHY interrupt for case of link change wakeup */ + fxgmac_read_ephy_reg(pdata, REG_MII_INT_STATUS, + NULL); /* clear phy interrupt */ +#if FUXI_EPHY_INTERRUPT_D0_OFF + regval = FXGMAC_SET_REG_BITS(0, PHY_INT_MASK_LINK_UP_POS, + PHY_INT_MASK_LINK_UP_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, PHY_INT_MASK_LINK_DOWN_POS, + PHY_INT_MASK_LINK_DOWN_LEN, 1); + fxgmac_write_ephy_reg(pdata, REG_MII_INT_MASK, + regval); /* enable phy interrupt */ +#endif + + return true; +} +static int fxgmac_suspend_txrx(struct fxgmac_pdata *pdata) +{ + struct fxgmac_channel *channel; + unsigned int i; + u32 regval; + int busy = 15; + /* Prepare for Tx DMA channel stop */ + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (!channel->tx_ring) { + break; + } + fxgmac_prepare_tx_stop(pdata, channel); + } + + /* Disable each Tx DMA channel */ + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (!channel->tx_ring) { + break; + } + + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_TCR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_TCR_ST_POS, + DMA_CH_TCR_ST_LEN, 0); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_TCR)); + DBGPRINT(MP_TRACE, (" %s disable tx dma", __FUNCTION__)); + } + + do { + regval = + readreg(pdata->pAdapter, pdata->mac_regs + MAC_DBG_STA); + busy--; + } while ((regval & MAC_DBG_STA_TX_BUSY) && (busy)); + + if (0 != (regval & MAC_DBG_STA_TX_BUSY)) { + regval = + readreg(pdata->pAdapter, pdata->mac_regs + MAC_DBG_STA); + DbgPrintF(MP_WARN, + "warning !!!timed out waiting for Tx MAC to stop\n"); + return -1; + } + /* wait empty Tx queue */ + for (i = 0; i < pdata->tx_q_count; i++) { + do { + regval = readreg(pdata->pAdapter, + FXGMAC_MTL_REG(pdata, i, MTL_TXQ_DEG)); + busy--; + } while ((regval & MTL_TXQ_DEG_TX_BUSY) && (busy)); + if (0 != (regval & MTL_TXQ_DEG_TX_BUSY)) { + regval = readreg(pdata->pAdapter, + pdata->mac_regs + MTL_TXQ_DEG); + DbgPrintF( + MP_WARN, + "warning !!!timed out waiting for tx queue %u to empty\n", + i); + return -1; + } + } + + /* Disable MAC TxRx */ + regval = readreg(pdata->pAdapter, pdata->mac_regs + MAC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_TE_POS, MAC_CR_TE_LEN, 0); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_RE_POS, MAC_CR_RE_LEN, 0); + writereg(pdata->pAdapter, regval, pdata->mac_regs + MAC_CR); + + /* Prepare for Rx DMA channel stop */ + for (i = 0; i < pdata->rx_q_count; i++) { + fxgmac_prepare_rx_stop(pdata, i); + } + /* Disable each Rx DMA channel */ + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (!channel->rx_ring) { + break; + } + + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_RCR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_RCR_SR_POS, + DMA_CH_RCR_SR_LEN, 0); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_RCR)); + DBGPRINT(MP_TRACE, (" %s disable rx dma", __FUNCTION__)); + } + return 0; +} +static void fxgmac_resume_int(struct fxgmac_pdata *pdata) +{ + u32 intid, regval = 0; + u32 val_mgmt_intcrtl0; + + val_mgmt_intcrtl0 = + (u32)readreg(pdata->pAdapter, pdata->base_mem + MGMT_INT_CTRL0); + /* disable management interrupts. enable only pmt interrupts. */ + val_mgmt_intcrtl0 = FXGMAC_SET_REG_BITS( + val_mgmt_intcrtl0, MGMT_INT_CTRL0_INT_MASK_POS, + MGMT_INT_CTRL0_INT_MASK_LEN, MGMT_INT_CTRL0_INT_MASK_DISABLE); + writereg(pdata->pAdapter, val_mgmt_intcrtl0, + pdata->base_mem + MGMT_INT_CTRL0); + + for (intid = 0; intid < MSIX_TBL_RXTX_NUM; intid++) { + writereg(pdata->pAdapter, 0, + pdata->base_mem + MSIX_TBL_BASE_ADDR + + MSIX_TBL_MASK_OFFSET + intid * 16); + } + + for (intid = MSIX_TBL_RXTX_NUM; intid < MSIX_TBL_MAX_NUM; + intid++) { /* disable some msix */ + writereg(pdata->pAdapter, 0, + pdata->base_mem + MSIX_TBL_BASE_ADDR + + MSIX_TBL_MASK_OFFSET + intid * 16); + } + +#if FUXI_EPHY_INTERRUPT_D0_OFF + fxgmac_write_ephy_reg(pdata, REG_MII_INT_MASK, + 0x0); /* disable phy interrupt */ + fxgmac_read_ephy_reg(pdata, REG_MII_INT_STATUS, + NULL); /* clear phy interrupt */ +#else + regval = FXGMAC_SET_REG_BITS(0, PHY_INT_MASK_LINK_UP_POS, + PHY_INT_MASK_LINK_UP_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, PHY_INT_MASK_LINK_DOWN_POS, + PHY_INT_MASK_LINK_DOWN_LEN, 1); + fxgmac_write_ephy_reg(pdata, REG_MII_INT_MASK, + regval); /* enable phy interrupt */ +#endif +} + +static int fxgmac_hw_init(struct fxgmac_pdata *pdata) +{ + struct fxgmac_desc_ops *desc_ops = &pdata->desc_ops; + int ret; + u32 regval = 0; + + if (netif_msg_drv(pdata)) { + DPRINTK("fxgmac hw init call in\n"); + } + + /* Flush Tx queues */ + ret = fxgmac_flush_tx_queues(pdata); + if (ret) { + if (netif_msg_drv(pdata)) { + DPRINTK("fxgmac_hw_init call flush tx queue err.\n"); + } + return ret; + } + + /* Initialize DMA related features */ + fxgmac_config_dma_bus(pdata); + fxgmac_config_osp_mode(pdata); + fxgmac_config_pblx8(pdata); + fxgmac_config_tx_pbl_val(pdata); + fxgmac_config_rx_pbl_val(pdata); + fxgmac_config_rx_coalesce(pdata); + fxgmac_config_tx_coalesce(pdata); + fxgmac_config_rx_buffer_size(pdata); + fxgmac_config_tso_mode(pdata); + fxgmac_config_sph_mode(pdata); + fxgmac_config_rss(pdata); + fxgmac_config_wol(pdata, pdata->expansion.wol); + + desc_ops->tx_desc_init(pdata); + desc_ops->rx_desc_init(pdata); + fxgmac_enable_dma_interrupts(pdata); + + /* Initialize MTL related features */ + fxgmac_config_mtl_mode(pdata); + fxgmac_config_queue_mapping(pdata); + fxgmac_config_tsf_mode(pdata, pdata->tx_sf_mode); + fxgmac_config_rsf_mode(pdata, pdata->rx_sf_mode); + fxgmac_config_tx_threshold(pdata, pdata->tx_threshold); + fxgmac_config_rx_threshold(pdata, pdata->rx_threshold); + fxgmac_config_tx_fifo_size(pdata); + fxgmac_config_rx_fifo_size(pdata); + fxgmac_config_flow_control_threshold(pdata); + fxgmac_config_rx_fep_disable(pdata); + fxgmac_config_rx_fup_enable(pdata); + fxgmac_enable_mtl_interrupts(pdata); + + /* Initialize MAC related features */ + fxgmac_config_mac_address(pdata); + fxgmac_config_crc_check(pdata); + fxgmac_config_rx_mode(pdata); + fxgmac_config_jumbo(pdata); + fxgmac_config_flow_control(pdata); + fxgmac_config_mac_speed(pdata); + fxgmac_config_checksum_offload(pdata); + fxgmac_config_vlan_support(pdata); + fxgmac_config_mmc(pdata); + fxgmac_enable_mac_interrupts(pdata); + + /* enable EPhy link change interrupt */ + fxgmac_read_ephy_reg(pdata, REG_MII_INT_STATUS, + NULL); /* clear phy interrupt */ + regval = FXGMAC_SET_REG_BITS(0, PHY_INT_MASK_LINK_UP_POS, + PHY_INT_MASK_LINK_UP_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, PHY_INT_MASK_LINK_DOWN_POS, + PHY_INT_MASK_LINK_DOWN_LEN, 1); + fxgmac_write_ephy_reg(pdata, REG_MII_INT_MASK, + regval); /* enable phy interrupt */ + + if (netif_msg_drv(pdata)) { + DPRINTK("fxgmac hw init callout\n"); + } + return 0; +} + +static void fxgmac_save_nonstick_reg(struct fxgmac_pdata *pdata) +{ + u32 i; + for (i = REG_PCIE_TRIGGER; i < MSI_PBA_REG; i += 4) { + pdata->reg_nonstick[(i - REG_PCIE_TRIGGER) >> 2] = + readreg(pdata->pAdapter, pdata->base_mem + i); + } +} + +static void fxgmac_restore_nonstick_reg(struct fxgmac_pdata *pdata) +{ + u32 i; + for (i = REG_PCIE_TRIGGER; i < MSI_PBA_REG; i += 4) { + writereg(pdata->pAdapter, + pdata->reg_nonstick[(i - REG_PCIE_TRIGGER) >> 2], + pdata->base_mem + i); + } +} + +static void fxgmac_esd_restore_pcie_cfg(struct fxgmac_pdata *pdata) +{ + cfg_w32(pdata, REG_PCI_COMMAND, pdata->expansion.cfg_pci_cmd); + cfg_w32(pdata, REG_CACHE_LINE_SIZE, + pdata->expansion.cfg_cache_line_size); + cfg_w32(pdata, REG_MEM_BASE, pdata->expansion.cfg_mem_base); + cfg_w32(pdata, REG_MEM_BASE_HI, pdata->expansion.cfg_mem_base_hi); + cfg_w32(pdata, REG_IO_BASE, pdata->expansion.cfg_io_base); + cfg_w32(pdata, REG_INT_LINE, pdata->expansion.cfg_int_line); + cfg_w32(pdata, REG_DEVICE_CTRL1, pdata->expansion.cfg_device_ctrl1); + cfg_w32(pdata, REG_PCI_LINK_CTRL, pdata->expansion.cfg_pci_link_ctrl); + cfg_w32(pdata, REG_DEVICE_CTRL2, pdata->expansion.cfg_device_ctrl2); + cfg_w32(pdata, REG_MSIX_CAPABILITY, + pdata->expansion.cfg_msix_capability); +} + +static int fxgmac_hw_exit(struct fxgmac_pdata *pdata) +{ + u32 regval; + u32 value = 0; + + cfg_r32(pdata, REG_PCI_LINK_CTRL, ®val); + pdata->pcie_link_status = + FXGMAC_GET_REG_BITS(regval, PCI_LINK_CTRL_ASPM_CONTROL_POS, + PCI_LINK_CTRL_ASPM_CONTROL_LEN); + if (PCI_LINK_CTRL_L1_STATUS == (pdata->pcie_link_status & 0x02)) { + regval = FXGMAC_SET_REG_BITS(regval, + PCI_LINK_CTRL_ASPM_CONTROL_POS, + PCI_LINK_CTRL_ASPM_CONTROL_LEN, 0); + cfg_w32(pdata, REG_PCI_LINK_CTRL, regval); + } + + /* Issue a CHIP reset */ + regval = readreg(pdata->pAdapter, pdata->base_mem + SYS_RESET_REG); + DPRINTK("CHIP_RESET 0x%x\n", regval); + /* reg152c bit31 1->reset, self-clear, if read it again, it still set 1. */ + regval = FXGMAC_SET_REG_BITS(regval, SYS_RESET_POS, SYS_RESET_LEN, 1); + writereg(pdata->pAdapter, regval, pdata->base_mem + SYS_RESET_REG); + + usleep_range_ex(pdata->pAdapter, 9000, 10000); + + /* reg152c reset will reset trigger circuit and reload efuse patch 0x1004=0x16, need to release ephy reset again */ + value = FXGMAC_SET_REG_BITS(value, MGMT_EPHY_CTRL_RESET_POS, + MGMT_EPHY_CTRL_RESET_LEN, + MGMT_EPHY_CTRL_STA_EPHY_RELEASE); + writereg(pdata->pAdapter, value, pdata->base_mem + MGMT_EPHY_CTRL); + usleep_range_ex(pdata->pAdapter, 100, 150); + + fxgmac_restore_nonstick_reg( + pdata); /* reset will clear nonstick registers. */ + + return 0; +} + +static int fxgmac_set_gmac_register(struct fxgmac_pdata *pdata, u8 *address, + unsigned int data) +{ + if (address < (u8 *)(pdata->base_mem)) { + return -1; + } + writereg(pdata->pAdapter, data, address); + return 0; +} + +static u32 fxgmac_get_gmac_register(struct fxgmac_pdata *pdata, u8 *address) +{ + u32 regval = 0; + + if (address > (u8 *)(pdata->base_mem)) { + regval = readreg(pdata->pAdapter, address); + } + return regval; +} + +static int fxgmac_pcie_init(struct fxgmac_pdata *pdata, bool ltr_en, + bool aspm_l1ss_en, bool aspm_l1_en, + bool aspm_l0s_en) +{ + u32 regval = 0; + u32 deviceid = 0; + + cfg_r32(pdata, REG_PCI_LINK_CTRL, ®val); + if (PCI_LINK_CTRL_L1_STATUS == (pdata->pcie_link_status & 0x02) && + 0x00 == FXGMAC_GET_REG_BITS(regval, PCI_LINK_CTRL_ASPM_CONTROL_POS, + PCI_LINK_CTRL_ASPM_CONTROL_LEN)) { + regval = FXGMAC_SET_REG_BITS(regval, + PCI_LINK_CTRL_ASPM_CONTROL_POS, + PCI_LINK_CTRL_ASPM_CONTROL_LEN, + pdata->pcie_link_status); + cfg_w32(pdata, REG_PCI_LINK_CTRL, regval); + } + + regval = FXGMAC_SET_REG_BITS(0, LTR_IDLE_ENTER_REQUIRE_POS, + LTR_IDLE_ENTER_REQUIRE_LEN, + LTR_IDLE_ENTER_REQUIRE); + regval = FXGMAC_SET_REG_BITS(regval, LTR_IDLE_ENTER_SCALE_POS, + LTR_IDLE_ENTER_SCALE_LEN, + LTR_IDLE_ENTER_SCALE); + regval = FXGMAC_SET_REG_BITS(regval, LTR_IDLE_ENTER_POS, + LTR_IDLE_ENTER_LEN, LTR_IDLE_ENTER_USVAL); + regval = (regval << 16) + regval; /* snoopy + non-snoopy */ + writereg(pdata->pAdapter, regval, pdata->base_mem + LTR_IDLE_ENTER); + + regval = 0; + regval = FXGMAC_SET_REG_BITS(0, LTR_IDLE_EXIT_REQUIRE_POS, + LTR_IDLE_EXIT_REQUIRE_LEN, + LTR_IDLE_EXIT_REQUIRE); + regval = FXGMAC_SET_REG_BITS(regval, LTR_IDLE_EXIT_SCALE_POS, + LTR_IDLE_EXIT_SCALE_LEN, + LTR_IDLE_EXIT_SCALE); + regval = FXGMAC_SET_REG_BITS(regval, LTR_IDLE_EXIT_POS, + LTR_IDLE_EXIT_LEN, LTR_IDLE_EXIT_USVAL); + regval = (regval << 16) + regval; /* snoopy + non-snoopy */ + writereg(pdata->pAdapter, regval, pdata->base_mem + LTR_IDLE_EXIT); + + regval = readreg(pdata->pAdapter, pdata->base_mem + LTR_CTRL); + if (ltr_en) { + regval = FXGMAC_SET_REG_BITS(regval, LTR_CTRL_EN_POS, + LTR_CTRL_EN_LEN, 1); + regval = FXGMAC_SET_REG_BITS(regval, + LTR_CTRL_IDLE_THRE_TIMER_POS, + LTR_CTRL_IDLE_THRE_TIMER_LEN, + LTR_CTRL_IDLE_THRE_TIMER_VAL); + } else { + regval = FXGMAC_SET_REG_BITS(regval, LTR_CTRL_EN_POS, + LTR_CTRL_EN_LEN, 0); + } + writereg(pdata->pAdapter, regval, pdata->base_mem + LTR_CTRL); + + regval = readreg(pdata->pAdapter, pdata->base_mem + LPW_CTRL); + regval = FXGMAC_SET_REG_BITS(regval, LPW_CTRL_ASPM_L0S_EN_POS, + LPW_CTRL_ASPM_L0S_EN_LEN, + aspm_l0s_en ? 1 : 0); + regval = FXGMAC_SET_REG_BITS(regval, LPW_CTRL_ASPM_L1_EN_POS, + LPW_CTRL_ASPM_L1_EN_LEN, + aspm_l1_en ? 1 : 0); + regval = FXGMAC_SET_REG_BITS(regval, LPW_CTRL_L1SS_EN_POS, + LPW_CTRL_L1SS_EN_LEN, + aspm_l1ss_en ? 1 : 0); + writereg(pdata->pAdapter, regval, pdata->base_mem + LPW_CTRL); + + cfg_r32(pdata, REG_ASPM_CONTROL, ®val); + regval = FXGMAC_SET_REG_BITS(regval, ASPM_L1_IDLE_THRESHOLD_POS, + ASPM_L1_IDLE_THRESHOLD_LEN, + ASPM_L1_IDLE_THRESHOLD_1US); + cfg_w32(pdata, REG_ASPM_CONTROL, regval); + + regval = 0; + regval = FXGMAC_SET_REG_BITS(regval, PCIE_SERDES_PLL_AUTOOFF_POS, + PCIE_SERDES_PLL_AUTOOFF_LEN, 1); + writereg(pdata->pAdapter, regval, + pdata->base_mem + REG_PCIE_SERDES_PLL); + + /*fuxi nto adjust sigdet threshold*/ + cfg_r8(pdata, REG_PCI_REVID, ®val); + cfg_r16(pdata, REG_PCI_DEVICE_ID, &deviceid); + if (FUXI_REV_01 == regval && PCI_DEVICE_ID_FUXI == deviceid) { + regval = + readreg(pdata->pAdapter, pdata->base_mem + MGMT_SIGDET); + regval = FXGMAC_SET_REG_BITS(regval, MGMT_SIGDET_POS, + MGMT_SIGDET_LEN, MGMT_SIGDET_55MV); + writereg(pdata->pAdapter, regval, + pdata->base_mem + MGMT_SIGDET); + } + + return 0; +} + +static void fxgmac_trigger_pcie(struct fxgmac_pdata *pdata, u32 code) +{ + writereg(pdata->pAdapter, code, pdata->base_mem + REG_PCIE_TRIGGER); +} + +void fxgmac_init_hw_ops(struct fxgmac_hw_ops *hw_ops) +{ + hw_ops->init = fxgmac_hw_init; + hw_ops->exit = fxgmac_hw_exit; + hw_ops->save_nonstick_reg = fxgmac_save_nonstick_reg; + hw_ops->restore_nonstick_reg = fxgmac_restore_nonstick_reg; + hw_ops->esd_restore_pcie_cfg = fxgmac_esd_restore_pcie_cfg; + + hw_ops->set_gmac_register = fxgmac_set_gmac_register; + hw_ops->get_gmac_register = fxgmac_get_gmac_register; + + hw_ops->tx_complete = fxgmac_tx_complete; + hw_ops->enable_tx = fxgmac_enable_tx; + hw_ops->disable_tx = fxgmac_disable_tx; + hw_ops->enable_rx = fxgmac_enable_rx; + hw_ops->disable_rx = fxgmac_disable_rx; + hw_ops->enable_channel_rx = fxgmac_enable_channel_rx; + hw_ops->dev_xmit = fxgmac_dev_xmit; + hw_ops->dev_read = fxgmac_dev_read; + hw_ops->config_tso = fxgmac_config_tso_mode; + hw_ops->enable_int = fxgmac_enable_int; + hw_ops->disable_int = fxgmac_disable_int; + hw_ops->set_interrupt_moderation = fxgmac_set_interrupt_moderation; + hw_ops->enable_msix_rxtxinterrupt = fxgmac_enable_msix_rxtxinterrupt; + hw_ops->disable_msix_interrupt = fxgmac_disable_msix_interrupt; + hw_ops->enable_msix_rxtxphyinterrupt = + fxgmac_enable_msix_rxtxphyinterrupt; + hw_ops->enable_msix_one_interrupt = fxgmac_enable_msix_one_interrupt; + hw_ops->disable_msix_one_interrupt = fxgmac_disable_msix_one_interrupt; + hw_ops->enable_mgm_interrupt = fxgmac_enable_mgm_interrupt; + hw_ops->disable_mgm_interrupt = fxgmac_disable_mgm_interrupt; + + hw_ops->set_mac_address = fxgmac_set_mac_address; + hw_ops->set_mac_hash = fxgmac_add_mac_addresses; + hw_ops->config_rx_mode = fxgmac_config_rx_mode; + hw_ops->enable_rx_csum = fxgmac_enable_rx_csum; + hw_ops->disable_rx_csum = fxgmac_disable_rx_csum; + + /* For MII speed configuration */ + hw_ops->config_mac_speed = fxgmac_config_mac_speed; + hw_ops->get_xlgmii_phy_status = fxgmac_check_phy_link; + + /* For descriptor related operation */ + hw_ops->tx_desc_init = fxgmac_tx_desc_init; + hw_ops->rx_desc_init = fxgmac_rx_desc_init; + hw_ops->tx_desc_reset = fxgmac_tx_desc_reset; + hw_ops->rx_desc_reset = fxgmac_rx_desc_reset; + hw_ops->is_last_desc = fxgmac_is_last_desc; + hw_ops->is_context_desc = fxgmac_is_context_desc; + hw_ops->tx_start_xmit = fxgmac_tx_start_xmit; + hw_ops->set_pattern_data = fxgmac_set_pattern_data; + hw_ops->config_wol = fxgmac_config_wol; + hw_ops->get_rss_hash_key = fxgmac_read_rss_hash_key; + hw_ops->write_rss_lookup_table = fxgmac_write_rss_lookup_table; +#if FXGMAC_SANITY_CHECK_ENABLED + hw_ops->diag_sanity_check = fxgmac_diag_sanity_check; +#endif + + /* For Flow Control */ + hw_ops->config_tx_flow_control = fxgmac_config_tx_flow_control; + hw_ops->config_rx_flow_control = fxgmac_config_rx_flow_control; + + /*For Jumbo Frames*/ + hw_ops->enable_jumbo = fxgmac_config_jumbo; + + /* For Vlan related config */ + hw_ops->enable_tx_vlan = fxgmac_enable_tx_vlan; + hw_ops->disable_tx_vlan = fxgmac_disable_tx_vlan; + hw_ops->enable_rx_vlan_stripping = fxgmac_enable_rx_vlan_stripping; + hw_ops->disable_rx_vlan_stripping = fxgmac_disable_rx_vlan_stripping; + hw_ops->enable_rx_vlan_filtering = fxgmac_enable_rx_vlan_filtering; + hw_ops->disable_rx_vlan_filtering = fxgmac_disable_rx_vlan_filtering; + hw_ops->update_vlan_hash_table = fxgmac_update_vlan_hash_table; + + /* For RX coalescing */ + hw_ops->config_rx_coalesce = fxgmac_config_rx_coalesce; + hw_ops->config_tx_coalesce = fxgmac_config_tx_coalesce; + hw_ops->usec_to_riwt = fxgmac_usec_to_riwt; + hw_ops->riwt_to_usec = fxgmac_riwt_to_usec; + + /* For RX and TX threshold config */ + hw_ops->config_rx_threshold = fxgmac_config_rx_threshold; + hw_ops->config_tx_threshold = fxgmac_config_tx_threshold; + + /* For RX and TX Store and Forward Mode config */ + hw_ops->config_rsf_mode = fxgmac_config_rsf_mode; + hw_ops->config_tsf_mode = fxgmac_config_tsf_mode; + + /* For TX DMA Operating on Second Frame config */ + hw_ops->config_osp_mode = fxgmac_config_osp_mode; + + /* For RX and TX PBL config */ + hw_ops->config_rx_pbl_val = fxgmac_config_rx_pbl_val; + hw_ops->get_rx_pbl_val = fxgmac_get_rx_pbl_val; + hw_ops->config_tx_pbl_val = fxgmac_config_tx_pbl_val; + hw_ops->get_tx_pbl_val = fxgmac_get_tx_pbl_val; + hw_ops->config_pblx8 = fxgmac_config_pblx8; + + /* For MMC statistics support */ + hw_ops->tx_mmc_int = fxgmac_tx_mmc_int; + hw_ops->rx_mmc_int = fxgmac_rx_mmc_int; + hw_ops->read_mmc_stats = fxgmac_read_mmc_stats; + + /* For Receive Side Scaling */ + hw_ops->enable_rss = fxgmac_enable_rss; + hw_ops->disable_rss = fxgmac_disable_rss; + hw_ops->get_rss_options = fxgmac_read_rss_options; + hw_ops->set_rss_options = fxgmac_write_rss_options; + hw_ops->set_rss_hash_key = fxgmac_set_rss_hash_key; + hw_ops->set_rss_lookup_table = fxgmac_set_rss_lookup_table; + + /*For Offload*/ + hw_ops->set_arp_offload = fxgmac_update_aoe_ipv4addr; + hw_ops->enable_arp_offload = fxgmac_enable_arp_offload; + hw_ops->disable_arp_offload = fxgmac_disable_arp_offload; + + hw_ops->set_ns_offload = fxgmac_set_ns_offload; + hw_ops->enable_ns_offload = fxgmac_enable_ns_offload; + hw_ops->disable_ns_offload = fxgmac_disable_ns_offload; + + hw_ops->enable_wake_magic_pattern = fxgmac_enable_wake_magic_pattern; + hw_ops->disable_wake_magic_pattern = fxgmac_disable_wake_magic_pattern; + + hw_ops->enable_wake_link_change = fxgmac_enable_wake_link_change; + hw_ops->disable_wake_link_change = fxgmac_disable_wake_link_change; + + hw_ops->check_wake_pattern_fifo_pointer = + fxgmac_check_wake_pattern_fifo_pointer; + hw_ops->set_wake_pattern = fxgmac_set_wake_pattern; + hw_ops->enable_wake_pattern = fxgmac_enable_wake_pattern; + hw_ops->disable_wake_pattern = fxgmac_disable_wake_pattern; + hw_ops->set_wake_pattern_mask = fxgmac_set_wake_pattern_mask; +#if defined(FUXI_PM_WPI_READ_FEATURE_EN) && FUXI_PM_WPI_READ_FEATURE_EN + hw_ops->enable_wake_packet_indication = + fxgmac_enable_wake_packet_indication; + hw_ops->get_wake_packet_indication = fxgmac_get_wake_packet_indication; +#endif + + /*For phy write /read*/ + hw_ops->reset_phy = fxgmac_reset_phy; + hw_ops->release_phy = fxgmac_release_phy; + hw_ops->get_ephy_state = fxgmac_get_ephy_state; + hw_ops->write_ephy_reg = fxgmac_write_ephy_reg; + hw_ops->read_ephy_reg = fxgmac_read_ephy_reg; + hw_ops->set_ephy_autoneg_advertise = fxgmac_set_ephy_autoneg_advertise; + hw_ops->phy_config = fxgmac_phy_config; + hw_ops->close_phy_led = fxgmac_close_phy_led; + hw_ops->led_under_active = fxmgac_config_led_under_active; + hw_ops->led_under_sleep = fxgmac_config_led_under_sleep; + hw_ops->led_under_shutdown = fxgmac_config_led_under_shutdown; + hw_ops->led_under_disable = fxgmac_config_led_under_disable; + hw_ops->enable_phy_check = fxgmac_enable_phy_check; + hw_ops->disable_phy_check = fxgmac_disable_phy_check; + hw_ops->setup_cable_loopback = fxgmac_setup_cable_loopback; + hw_ops->clean_cable_loopback = fxgmac_clean_cable_loopback; + hw_ops->disable_phy_sleep = fxgmac_disable_phy_sleep; + hw_ops->enable_phy_sleep = fxgmac_enable_phy_sleep; + hw_ops->phy_green_ethernet = fxgmac_phy_green_ethernet; + hw_ops->phy_eee_feature = fxgmac_phy_eee_feature; + + /* For power management */ + hw_ops->pre_power_down = fxgmac_pre_powerdown; + hw_ops->config_power_down = fxgmac_config_powerdown; + hw_ops->config_power_up = fxgmac_config_powerup; + hw_ops->set_suspend_int = fxgmac_suspend_int; + hw_ops->set_resume_int = fxgmac_resume_int; + hw_ops->set_suspend_txrx = fxgmac_suspend_txrx; + hw_ops->set_pwr_clock_gate = fxgmac_pwr_clock_gate; + hw_ops->set_pwr_clock_ungate = fxgmac_pwr_clock_ungate; + + hw_ops->set_all_multicast_mode = fxgmac_set_all_multicast_mode; + hw_ops->config_multicast_mac_hash_table = + fxgmac_config_multicast_mac_hash_table; + hw_ops->set_promiscuous_mode = fxgmac_set_promiscuous_mode; + hw_ops->enable_rx_broadcast = fxgmac_enable_rx_broadcast; + + /* efuse relevant operation. */ + hw_ops->read_patch_from_efuse = + fxgmac_read_patch_from_efuse; /* read patch per register. */ + hw_ops->read_patch_from_efuse_per_index = + fxgmac_read_patch_from_efuse_per_index; /* read patch per index. */ + hw_ops->write_patch_to_efuse = fxgmac_write_patch_to_efuse; + hw_ops->write_patch_to_efuse_per_index = + fxgmac_write_patch_to_efuse_per_index; + hw_ops->read_mac_subsys_from_efuse = fxgmac_read_mac_subsys_from_efuse; + hw_ops->write_mac_subsys_to_efuse = fxgmac_write_mac_subsys_to_efuse; + hw_ops->efuse_load = fxgmac_efuse_load; + hw_ops->read_efuse_data = fxgmac_efuse_read_data; + hw_ops->write_oob = fxgmac_efuse_write_oob; + hw_ops->write_led = fxgmac_efuse_write_led; + hw_ops->write_led_config = fxgmac_write_led_setting_to_efuse; + hw_ops->read_led_config = fxgmac_read_led_setting_from_efuse; + + /* */ + hw_ops->pcie_init = fxgmac_pcie_init; + hw_ops->trigger_pcie = fxgmac_trigger_pcie; +} diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-net.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-net.c new file mode 100644 index 0000000000000..b8734efb36426 --- /dev/null +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-net.c @@ -0,0 +1,2329 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021 Motorcomm Corporation. */ + +#include +#include +#include +#include +#include +#include + +#include "fuxi-os.h" +#include "fuxi-gmac.h" +#include "fuxi-gmac-reg.h" + +static int fxgmac_one_poll_rx(struct napi_struct *, int); +static int fxgmac_one_poll_tx(struct napi_struct *, int); +static int fxgmac_all_poll(struct napi_struct *, int); + +unsigned int fxgmac_get_netdev_ip4addr(struct fxgmac_pdata *pdata) +{ + struct net_device *netdev = pdata->netdev; + struct in_ifaddr *ifa; + unsigned int ipval = + 0xc0a801ca; /* here just hard code to 192.168.1.202 */ + + rcu_read_lock(); + /* we only get the first IPv4 addr. */ + ifa = rcu_dereference(netdev->ip_ptr->ifa_list); + if (ifa) { + /* binary ipv4 addr with __be */ + ipval = (unsigned int)ifa->ifa_address; + + DPRINTK("%s, netdev %s IPv4 address %pI4, mask: %pI4\n", + __FUNCTION__, ifa->ifa_label, &ifa->ifa_address, + &ifa->ifa_mask); + } + rcu_read_unlock(); + + return ipval; +} + +unsigned char *fxgmac_get_netdev_ip6addr(struct fxgmac_pdata *pdata, + unsigned char *ipval, + unsigned char *ip6addr_solicited, + unsigned int ifa_flag) +{ + struct net_device *netdev = pdata->netdev; + struct inet6_dev *i6dev; + struct inet6_ifaddr *ifp; + unsigned char local_ipval[16] = { 0 }; + unsigned char solicited_ipval[16] = { 0 }; + struct in6_addr *addr_ip6 = (struct in6_addr *)local_ipval; + struct in6_addr *addr_ip6_solicited = + (struct in6_addr *)solicited_ipval; + int err = -EADDRNOTAVAIL; + unsigned char *ret; + + if (ipval) { + addr_ip6 = (struct in6_addr *)ipval; + } + + if (ip6addr_solicited) { + addr_ip6_solicited = (struct in6_addr *)ip6addr_solicited; + } + + in6_pton("fe80::4808:8ffb:d93e:d753", -1, (u8 *)addr_ip6, -1, + NULL); /* here just hard code for default */ + + if (ifa_flag & FXGMAC_NS_IFA_GLOBAL_UNICAST) + DPRINTK("%s FXGMAC_NS_IFA_GLOBAL_UNICAST is set, %x\n", + __FUNCTION__, ifa_flag); + + if (ifa_flag & FXGMAC_NS_IFA_LOCAL_LINK) + DPRINTK("%s FXGMAC_NS_IFA_LOCAL_LINK is set, %x\n", + __FUNCTION__, ifa_flag); + + rcu_read_lock(); + i6dev = __in6_dev_get(netdev); + if (i6dev != NULL) { + read_lock_bh(&i6dev->lock); + list_for_each_entry(ifp, &i6dev->addr_list, if_list) { + /* here we need only the ll addr, use scope to filter out it. */ + if (((ifa_flag & FXGMAC_NS_IFA_GLOBAL_UNICAST) && (ifp->scope != IFA_LINK)) || ((ifa_flag & FXGMAC_NS_IFA_LOCAL_LINK) && (ifp->scope == IFA_LINK)/* && + !(ifp->flags & IFA_F_TENTATIVE)*/)) { + memcpy(addr_ip6, &ifp->addr, 16); + addrconf_addr_solict_mult(addr_ip6, + addr_ip6_solicited); + err = 0; + + break; + } + } + read_unlock_bh(&i6dev->lock); + } + rcu_read_unlock(); + + if (err) + DPRINTK("%s get ipv6 addr failed, use default.\n", + __FUNCTION__); + + ret = (err ? NULL : ipval); + + return ret; +} + +inline unsigned int fxgmac_tx_avail_desc(struct fxgmac_ring *ring) +{ + unsigned int avail; + + if (ring->dirty > ring->cur) + avail = ring->dirty - ring->cur; + else + avail = ring->dma_desc_count - ring->cur + ring->dirty; + + return avail; +} + +inline unsigned int fxgmac_rx_dirty_desc(struct fxgmac_ring *ring) +{ + unsigned int dirty; + + if (ring->dirty <= ring->cur) + dirty = ring->cur - ring->dirty; + else + dirty = ring->dma_desc_count - ring->dirty + ring->cur; + + return dirty; +} + +static int fxgmac_maybe_stop_tx_queue(struct fxgmac_channel *channel, + struct fxgmac_ring *ring, + unsigned int count) +{ + struct fxgmac_pdata *pdata = channel->pdata; + + if (count > fxgmac_tx_avail_desc(ring)) { + netif_info( + pdata, drv, pdata->netdev, + "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_ops.tx_start_xmit(channel, ring); + if (netif_msg_tx_done(pdata)) + DPRINTK("about stop tx q, ret BUSY\n"); + + return NETDEV_TX_BUSY; + } + + return 0; +} + +static void fxgmac_prep_vlan(struct sk_buff *skb, + struct fxgmac_pkt_info *pkt_info) +{ + if (skb_vlan_tag_present(skb)) + pkt_info->vlan_ctag = skb_vlan_tag_get(skb); +} + +static int fxgmac_prep_tso(struct fxgmac_pdata *pdata, struct sk_buff *skb, + struct fxgmac_pkt_info *pkt_info) +{ + int ret; + + if (!FXGMAC_GET_REG_BITS(pkt_info->attributes, + TX_PACKET_ATTRIBUTES_TSO_ENABLE_POS, + TX_PACKET_ATTRIBUTES_TSO_ENABLE_LEN)) + return 0; + + ret = skb_cow_head(skb, 0); + if (ret) + return ret; + + pkt_info->header_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + pkt_info->tcp_header_len = tcp_hdrlen(skb); + pkt_info->tcp_payload_len = skb->len - pkt_info->header_len; + pkt_info->mss = skb_shinfo(skb)->gso_size; + + if (netif_msg_tx_done(pdata)) { + DPRINTK("header_len=%u\n", pkt_info->header_len); + DPRINTK("tcp_header_len=%u, tcp_payload_len=%u\n", + pkt_info->tcp_header_len, pkt_info->tcp_payload_len); + DPRINTK("mss=%u\n", pkt_info->mss); + } + /* Update the number of packets that will ultimately be transmitted + * along with the extra bytes for each extra packet + */ + pkt_info->tx_packets = skb_shinfo(skb)->gso_segs; + pkt_info->tx_bytes += (pkt_info->tx_packets - 1) * pkt_info->header_len; + + return 0; +} + +static int fxgmac_is_tso(struct sk_buff *skb) +{ + if (skb->ip_summed != CHECKSUM_PARTIAL) + return 0; + + if (!skb_is_gso(skb)) + return 0; + + return 1; +} + +static void fxgmac_prep_tx_pkt(struct fxgmac_pdata *pdata, + struct fxgmac_ring *ring, struct sk_buff *skb, + struct fxgmac_pkt_info *pkt_info) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) + skb_frag_t *frag; +#else + struct skb_frag_struct *frag; +#endif + unsigned int context_desc; + unsigned int len; + unsigned int i; + + pkt_info->skb = skb; + + context_desc = 0; + pkt_info->desc_count = 0; + + pkt_info->tx_packets = 1; + pkt_info->tx_bytes = skb->len; + if (netif_msg_tx_done(pdata)) + DPRINTK("fxgmac_prep_tx_pkt callin, pkt desc cnt=%d, skb len=%d, skbheadlen=%d\n", + pkt_info->desc_count, skb->len, skb_headlen(skb)); + + if (fxgmac_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; + pkt_info->desc_count++; + } + if (netif_msg_tx_done(pdata)) + DPRINTK("fxgmac_is_tso=%d, ip_summed=%d, skb gso=%d\n", + ((skb->ip_summed == CHECKSUM_PARTIAL) && + (skb_is_gso(skb))) ? + 1 : + 0, + skb->ip_summed, skb_is_gso(skb) ? 1 : 0); + + /* TSO requires an extra descriptor for TSO header */ + pkt_info->desc_count++; + + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, + TX_PACKET_ATTRIBUTES_TSO_ENABLE_POS, + TX_PACKET_ATTRIBUTES_TSO_ENABLE_LEN, 1); + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, + TX_PACKET_ATTRIBUTES_CSUM_ENABLE_POS, + TX_PACKET_ATTRIBUTES_CSUM_ENABLE_LEN, 1); + if (netif_msg_tx_done(pdata)) + DPRINTK("fxgmac_prep_tx_pkt, tso, pkt desc cnt=%d\n", + pkt_info->desc_count); + } else if (skb->ip_summed == CHECKSUM_PARTIAL) + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, + TX_PACKET_ATTRIBUTES_CSUM_ENABLE_POS, + TX_PACKET_ATTRIBUTES_CSUM_ENABLE_LEN, 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; + pkt_info->desc_count++; + } + + pkt_info->attributes = FXGMAC_SET_REG_BITS( + pkt_info->attributes, + TX_PACKET_ATTRIBUTES_VLAN_CTAG_POS, + TX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN, 1); + if (netif_msg_tx_done(pdata)) + DPRINTK("fxgmac_prep_tx_pkt, VLAN, pkt desc cnt=%d, vlan=0x%04x\n", + pkt_info->desc_count, skb_vlan_tag_get(skb)); + } + + for (len = skb_headlen(skb); len;) { + pkt_info->desc_count++; + len -= min_t(unsigned int, len, FXGMAC_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;) { + pkt_info->desc_count++; + len -= min_t(unsigned int, len, FXGMAC_TX_MAX_BUF_SIZE); + } + } + if (netif_msg_tx_done(pdata)) + DPRINTK("fxgmac_prep_tx_pkt callout, pkt desc cnt=%d, skb len=%d, skbheadlen=%d, frags=%d\n", + pkt_info->desc_count, skb->len, skb_headlen(skb), + skb_shinfo(skb)->nr_frags); +} + +static int fxgmac_calc_rx_buf_size(struct net_device *netdev, unsigned int mtu) +{ + unsigned int rx_buf_size; + + if (mtu > FXGMAC_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, FXGMAC_RX_MIN_BUF_SIZE, + PAGE_SIZE * 4 /* follow yonggang's suggestion */); + + rx_buf_size = (rx_buf_size + FXGMAC_RX_BUF_ALIGN - 1) & + ~(FXGMAC_RX_BUF_ALIGN - 1); + + return rx_buf_size; +} + +static void fxgmac_enable_rx_tx_ints(struct fxgmac_pdata *pdata) +{ + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + struct fxgmac_channel *channel; + enum fxgmac_int int_id; + unsigned int i; + + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (channel->tx_ring && channel->rx_ring) + int_id = FXGMAC_INT_DMA_CH_SR_TI_RI; + else if (channel->tx_ring) + int_id = FXGMAC_INT_DMA_CH_SR_TI; + else if (channel->rx_ring) + int_id = FXGMAC_INT_DMA_CH_SR_RI; + else + continue; + + hw_ops->enable_int(channel, int_id); + } +} + +static void fxgmac_phy_process(struct fxgmac_pdata *pdata) +{ + int cur_link = 0; + int regval = 0; + int cur_speed = 0; + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + + regval = hw_ops->get_ephy_state(pdata); + + /* We should make sure that PHY is done with the reset */ + if (regval & MGMT_EPHY_CTRL_STA_EPHY_RESET) { + pdata->expansion.phy_link = false; + return; + } + + cur_link = FXGMAC_GET_REG_BITS(regval, + MGMT_EPHY_CTRL_STA_EPHY_LINKUP_POS, + MGMT_EPHY_CTRL_STA_EPHY_LINKUP_LEN); + if (pdata->expansion.phy_link != cur_link) { + pdata->expansion.phy_link = cur_link; + if (pdata->expansion.phy_link) { + cur_speed = FXGMAC_GET_REG_BITS( + regval, MGMT_EPHY_CTRL_STA_SPEED_POS, + MGMT_EPHY_CTRL_STA_SPEED_LEN); + pdata->phy_speed = (cur_speed == 2) ? SPEED_1000 : + (cur_speed == 1) ? SPEED_100 : + SPEED_10; + pdata->phy_duplex = FXGMAC_GET_REG_BITS( + regval, MGMT_EPHY_CTRL_STA_EPHY_DUPLEX_POS, + MGMT_EPHY_CTRL_STA_EPHY_DUPLEX_LEN); + hw_ops->config_mac_speed(pdata); + + hw_ops->enable_rx(pdata); + hw_ops->enable_tx(pdata); + netif_carrier_on(pdata->netdev); + if (netif_running(pdata->netdev)) { + netif_tx_wake_all_queues(pdata->netdev); + DPRINTK("%s now is link up, mac_speed=%d.\n", + FXGMAC_DRV_NAME, pdata->phy_speed); + } + } else { + netif_carrier_off(pdata->netdev); + netif_tx_stop_all_queues(pdata->netdev); + pdata->phy_speed = SPEED_UNKNOWN; + pdata->phy_duplex = DUPLEX_UNKNOWN; + hw_ops->disable_rx(pdata); + hw_ops->disable_tx(pdata); + DPRINTK("%s now is link down\n", FXGMAC_DRV_NAME); + } + } +} + +static int fxgmac_phy_poll(struct napi_struct *napi, int budget) +{ + struct fxgmac_pdata *pdata = + container_of(napi, struct fxgmac_pdata, expansion.napi_phy); + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + + fxgmac_phy_process(pdata); + if (napi_complete_done(napi, 0)) + hw_ops->enable_msix_one_interrupt(pdata, MSI_ID_PHY_OTHER); + + return 0; +} + +static irqreturn_t fxgmac_phy_isr(int irq, void *data) +{ + struct fxgmac_pdata *pdata = data; + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + u32 regval; + + regval = readreg(pdata->pAdapter, pdata->base_mem + MGMT_INT_CTRL0); + if (!(regval & MGMT_INT_CTRL0_INT_STATUS_PHY)) + return IRQ_HANDLED; + + hw_ops->disable_msix_one_interrupt(pdata, MSI_ID_PHY_OTHER); + hw_ops->read_ephy_reg(pdata, REG_MII_INT_STATUS, NULL); + if (napi_schedule_prep(&pdata->expansion.napi_phy)) { + __napi_schedule_irqoff(&pdata->expansion.napi_phy); + } + + return IRQ_HANDLED; +} + +static irqreturn_t fxgmac_isr(int irq, void *data) +{ + unsigned int dma_isr, dma_ch_isr, mac_isr; + struct fxgmac_pdata *pdata = data; + struct fxgmac_channel *channel; + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + unsigned int i, ti, ri; + u32 val; + + dma_isr = readreg(pdata->pAdapter, pdata->mac_regs + DMA_ISR); + + val = readreg(pdata->pAdapter, pdata->base_mem + MGMT_INT_CTRL0); + if (!(val & MGMT_INT_CTRL0_INT_STATUS_RXTXPHY_MASK)) + return IRQ_HANDLED; + + hw_ops->disable_mgm_interrupt(pdata); + pdata->expansion.mgm_intctrl_val = val; + + pdata->stats.mgmt_int_isr++; + + for (i = 0; i < pdata->channel_count; i++) { + channel = pdata->channel_head + i; + + dma_ch_isr = readl(FXGMAC_DMA_REG(channel, DMA_CH_SR)); + netif_dbg(pdata, intr, pdata->netdev, "DMA_CH%u_ISR=%#010x\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. + */ + ti = FXGMAC_GET_REG_BITS(dma_ch_isr, DMA_CH_SR_TI_POS, + DMA_CH_SR_TI_LEN); + ri = FXGMAC_GET_REG_BITS(dma_ch_isr, DMA_CH_SR_RI_POS, + DMA_CH_SR_RI_LEN); + if (!pdata->per_channel_irq && (ti || ri)) { + if (napi_schedule_prep(&pdata->expansion.napi)) { + pdata->stats.napi_poll_isr++; + /* Turn on polling */ + __napi_schedule_irqoff(&pdata->expansion.napi); + } + } + + if (FXGMAC_GET_REG_BITS(dma_ch_isr, DMA_CH_SR_TPS_POS, + DMA_CH_SR_TPS_LEN)) + pdata->stats.tx_process_stopped++; + + if (FXGMAC_GET_REG_BITS(dma_ch_isr, DMA_CH_SR_RPS_POS, + DMA_CH_SR_RPS_LEN)) + pdata->stats.rx_process_stopped++; + + if (FXGMAC_GET_REG_BITS(dma_ch_isr, DMA_CH_SR_TBU_POS, + DMA_CH_SR_TBU_LEN)) + pdata->stats.tx_buffer_unavailable++; + + if (FXGMAC_GET_REG_BITS(dma_ch_isr, DMA_CH_SR_RBU_POS, + DMA_CH_SR_RBU_LEN)) + pdata->stats.rx_buffer_unavailable++; + + /* Restart the device on a Fatal Bus Error */ + if (FXGMAC_GET_REG_BITS(dma_ch_isr, DMA_CH_SR_FBE_POS, + DMA_CH_SR_FBE_LEN)) { + pdata->stats.fatal_bus_error++; + schedule_work(&pdata->expansion.restart_work); + } + + /* Clear all interrupt signals */ + writel(dma_ch_isr, FXGMAC_DMA_REG(channel, DMA_CH_SR)); + } + + if (FXGMAC_GET_REG_BITS(dma_isr, DMA_ISR_MACIS_POS, + DMA_ISR_MACIS_LEN)) { + mac_isr = readl(pdata->mac_regs + MAC_ISR); + + if (FXGMAC_GET_REG_BITS(mac_isr, MAC_ISR_MMCTXIS_POS, + MAC_ISR_MMCTXIS_LEN)) + hw_ops->tx_mmc_int(pdata); + + if (FXGMAC_GET_REG_BITS(mac_isr, MAC_ISR_MMCRXIS_POS, + MAC_ISR_MMCRXIS_LEN)) + hw_ops->rx_mmc_int(pdata); + + /* Clear all interrupt signals */ + writel(mac_isr, (pdata->mac_regs + MAC_ISR)); + } + + if (pdata->expansion.mgm_intctrl_val & MGMT_INT_CTRL0_INT_STATUS_PHY) { + hw_ops->read_ephy_reg(pdata, REG_MII_INT_STATUS, &val); + if (napi_schedule_prep(&pdata->expansion.napi)) { + pdata->stats.napi_poll_isr++; + /* Turn on polling */ + __napi_schedule_irqoff(&pdata->expansion.napi); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t fxgmac_dma_isr(int irq, void *data) +{ + struct fxgmac_channel *channel = data; + struct fxgmac_pdata *pdata = channel->pdata; + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + u32 regval; + int message_id; + + if (irq == channel->expansion.dma_irq_tx) { + message_id = MSI_ID_TXQ0; + hw_ops->disable_msix_one_interrupt(pdata, message_id); + regval = 0; + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_SR_TI_POS, + DMA_CH_SR_TI_LEN, 1); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_SR)); + if (napi_schedule_prep(&channel->expansion.napi_tx)) { + __napi_schedule_irqoff(&channel->expansion.napi_tx); + } + } else { + message_id = channel->queue_index; + hw_ops->disable_msix_one_interrupt(pdata, message_id); + regval = 0; + regval = readreg(pdata->pAdapter, + FXGMAC_DMA_REG(channel, DMA_CH_SR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_CH_SR_RI_POS, + DMA_CH_SR_RI_LEN, 1); + writereg(pdata->pAdapter, regval, + FXGMAC_DMA_REG(channel, DMA_CH_SR)); + if (napi_schedule_prep(&channel->expansion.napi_rx)) { + __napi_schedule_irqoff(&channel->expansion.napi_rx); + } + } + + return IRQ_HANDLED; +} + +#if FXGMAC_TX_HANG_TIMER_EN +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) +static void fxgmac_tx_hang_timer_handler(struct timer_list *t) +#else +static void fxgmac_tx_hang_timer_handler(unsigned long data) +#endif +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) + struct fxgmac_channel *channel = + from_timer(channel, t, expansion.tx_hang_timer); +#else + struct fxgmac_channel *channel = (struct fxgmac_channel *)data; +#endif + +#if FXGMAC_TX_HANG_CHECH_DIRTY + struct fxgmac_ring *ring = channel->tx_ring; +#endif + struct fxgmac_pdata *pdata = channel->pdata; + struct net_device *netdev = pdata->netdev; + unsigned int hw_reg_cur; + unsigned int regval; + +#if FXGMAC_TX_HANG_CHECH_DIRTY + hw_reg_cur = ring->dirty; +#else + hw_reg_cur = readl( + FXGMAC_DMA_REG(channel, 0x44 /* tx desc curr pointer reg */)); +#endif + if (hw_reg_cur == channel->expansion.tx_hang_hw_cur) { + /* hw current desc still stucked */ + if (!pdata->tx_hang_restart_queuing) { + pdata->tx_hang_restart_queuing = 1; + DPRINTK("tx_hang_timer_handler: restart scheduled, at desc %u, queuing=%u.\n", + channel->expansion.tx_hang_hw_cur, + pdata->tx_hang_restart_queuing); + + netif_tx_stop_all_queues(netdev); + + /* Disable MAC Rx */ + regval = readl(pdata->mac_regs + MAC_CR); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_CST_POS, + MAC_CR_CST_LEN, 0); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_ACS_POS, + MAC_CR_ACS_LEN, 0); + regval = FXGMAC_SET_REG_BITS(regval, MAC_CR_RE_POS, + MAC_CR_RE_LEN, 0); + writel(regval, pdata->mac_regs + MAC_CR); + + schedule_work(&pdata->expansion.restart_work); + } + } + + channel->expansion.tx_hang_timer_active = 0; +} + +static void fxgmac_tx_hang_timer_start(struct fxgmac_channel *channel) +{ + struct fxgmac_pdata *pdata = channel->pdata; + + /* Start the Tx hang timer */ + if (1 && !channel->expansion.tx_hang_timer_active) { + channel->expansion.tx_hang_timer_active = 1; + + /* FXGMAC_INIT_DMA_TX_USECS is desc3 polling period, we give 2 more checking period */ + mod_timer(&channel->expansion.tx_hang_timer, + jiffies + usecs_to_jiffies(FXGMAC_INIT_DMA_TX_USECS * + 10)); + } +} +#endif + +static void fxgmac_napi_enable(struct fxgmac_pdata *pdata, unsigned int add) +{ + struct fxgmac_channel *channel; + unsigned int i; + + if (pdata->per_channel_irq) { + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (add) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) + netif_napi_add_weight( + pdata->netdev, + &channel->expansion.napi_rx, + fxgmac_one_poll_rx, NAPI_POLL_WEIGHT); +#else + netif_napi_add(pdata->netdev, + &channel->expansion.napi_rx, + fxgmac_one_poll_rx, + NAPI_POLL_WEIGHT); +#endif + } + napi_enable(&channel->expansion.napi_rx); + + if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) + netif_napi_add_weight( + pdata->netdev, + &channel->expansion.napi_tx, + fxgmac_one_poll_tx, NAPI_POLL_WEIGHT); +#else + netif_napi_add(pdata->netdev, + &channel->expansion.napi_tx, + fxgmac_one_poll_tx, + NAPI_POLL_WEIGHT); +#endif + napi_enable(&channel->expansion.napi_tx); + } + if (netif_msg_drv(pdata)) + DPRINTK("napi_enable, msix ch%d napi enabled done, add=%d\n", + i, add); + } + + /* for phy */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) + netif_napi_add_weight(pdata->netdev, &pdata->expansion.napi_phy, + fxgmac_phy_poll, NAPI_POLL_WEIGHT); +#else + netif_napi_add(pdata->netdev, &pdata->expansion.napi_phy, + fxgmac_phy_poll, NAPI_POLL_WEIGHT); +#endif + napi_enable(&pdata->expansion.napi_phy); + } else { + i = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_LEGACY_NAPI_FREE_POS, + FXGMAC_FLAG_LEGACY_NAPI_FREE_LEN); + if (!i) { + if (add) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) + netif_napi_add_weight(pdata->netdev, + &pdata->expansion.napi, + fxgmac_all_poll, + NAPI_POLL_WEIGHT); +#else + netif_napi_add(pdata->netdev, + &pdata->expansion.napi, + fxgmac_all_poll, + NAPI_POLL_WEIGHT); +#endif + } + + napi_enable(&pdata->expansion.napi); + pdata->expansion.int_flags = FXGMAC_SET_REG_BITS( + pdata->expansion.int_flags, + FXGMAC_FLAG_LEGACY_NAPI_FREE_POS, + FXGMAC_FLAG_LEGACY_NAPI_FREE_LEN, 1); + } + } +} + +static void fxgmac_napi_disable(struct fxgmac_pdata *pdata, unsigned int del) +{ + struct fxgmac_channel *channel; + unsigned int i; + + if (pdata->per_channel_irq) { + channel = pdata->channel_head; + if (channel != NULL) { + for (i = 0; i < pdata->channel_count; i++, channel++) { + napi_disable(&channel->expansion.napi_rx); + + if (del) { + netif_napi_del( + &channel->expansion.napi_rx); + } + + if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { + napi_disable( + &channel->expansion.napi_tx); + netif_napi_del( + &channel->expansion.napi_tx); + } + if (netif_msg_drv(pdata)) + DPRINTK("napi_disable, msix ch%d napi disabled done, del=%d\n", + i, del); + } + + napi_disable(&pdata->expansion.napi_phy); + netif_napi_del(&pdata->expansion.napi_phy); + } + } else { + i = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_LEGACY_NAPI_FREE_POS, + FXGMAC_FLAG_LEGACY_NAPI_FREE_LEN); + if (i) { + napi_disable(&pdata->expansion.napi); + + if (del) + netif_napi_del(&pdata->expansion.napi); + pdata->expansion.int_flags = FXGMAC_SET_REG_BITS( + pdata->expansion.int_flags, + FXGMAC_FLAG_LEGACY_NAPI_FREE_POS, + FXGMAC_FLAG_LEGACY_NAPI_FREE_LEN, 0); + } + } +} + +static int fxgmac_request_irqs(struct fxgmac_pdata *pdata) +{ + struct net_device *netdev = pdata->netdev; + struct fxgmac_channel *channel; + unsigned int i; + int ret; + u32 msi, msix, need_free; + + msi = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_MSI_POS, FXGMAC_FLAG_MSI_LEN); + + msix = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_MSIX_POS, FXGMAC_FLAG_MSIX_LEN); + + need_free = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_LEGACY_IRQ_FREE_POS, + FXGMAC_FLAG_LEGACY_IRQ_FREE_LEN); + + if (!msix) { + if (!need_free) { + ret = devm_request_irq(pdata->dev, pdata->dev_irq, + fxgmac_isr, + msi ? 0 : IRQF_SHARED, + netdev->name, pdata); + if (ret) { + netdev_alert( + netdev, + "error requesting irq %d, ret = %d\n", + pdata->dev_irq, ret); + return ret; + } + + pdata->expansion.int_flags = FXGMAC_SET_REG_BITS( + pdata->expansion.int_flags, + FXGMAC_FLAG_LEGACY_IRQ_FREE_POS, + FXGMAC_FLAG_LEGACY_IRQ_FREE_LEN, 1); + } + } + + if (!pdata->per_channel_irq) + return 0; + + ret = devm_request_irq(pdata->dev, pdata->expansion.phy_irq, + fxgmac_phy_isr, 0, netdev->name, pdata); + if (ret) { + netdev_alert(netdev, "error requesting phy irq %d, ret = %d\n", + pdata->expansion.phy_irq, ret); + return ret; + } + + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) { + snprintf(channel->expansion.dma_irq_name, + sizeof(channel->expansion.dma_irq_name) - 1, + "%s-ch%d-Rx-%u", netdev_name(netdev), i, + channel->queue_index); + if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { + snprintf(channel->expansion.dma_irq_name_tx, + sizeof(channel->expansion.dma_irq_name_tx) - 1, + "%s-ch%d-Tx-%u", netdev_name(netdev), i, + channel->queue_index); + + ret = devm_request_irq( + pdata->dev, channel->expansion.dma_irq_tx, + fxgmac_dma_isr, 0, + channel->expansion.dma_irq_name_tx, channel); + + if (ret) { + DPRINTK("fxgmac_req_irqs, err with MSIx irq request for ch %d tx, ret=%d\n", + i, ret); + /* Using an unsigned int, 'i' will go to UINT_MAX and exit */ + devm_free_irq(pdata->dev, + channel->expansion.dma_irq_tx, + channel); + return ret; + } + + if (netif_msg_drv(pdata)) + DPRINTK("fxgmac_req_irqs, MSIx irq_tx request ok, ch=%d, irq=%d,%s\n", + i, channel->expansion.dma_irq_tx, + channel->expansion.dma_irq_name_tx); + } + ret = devm_request_irq(pdata->dev, channel->dma_irq, + fxgmac_dma_isr, 0, + channel->expansion.dma_irq_name, + channel); + if (ret) { + netdev_alert(netdev, "error requesting irq %d\n", + channel->dma_irq); + goto err_irq; + } + } + + if (netif_msg_drv(pdata)) + DPRINTK("fxgmac_req_irqs, MSIx irq request ok, total=%d,%d~%d\n", + i, (pdata->channel_head)[0].dma_irq, + (pdata->channel_head)[i - 1].dma_irq); + return 0; + +err_irq: + DPRINTK("fxgmac_req_irqs, err with MSIx irq request at %d, ret=%d\n", i, + ret); + + if (pdata->per_channel_irq) { + for (i--, channel--; i < pdata->channel_count; i--, channel--) { + if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { + devm_free_irq(pdata->dev, + channel->expansion.dma_irq_tx, + channel); + } + devm_free_irq(pdata->dev, channel->dma_irq, channel); + } + + devm_free_irq(pdata->dev, pdata->expansion.phy_irq, pdata); + } + return ret; +} + +static void fxgmac_free_irqs(struct fxgmac_pdata *pdata) +{ + struct fxgmac_channel *channel; + unsigned int i = 0; + u32 need_free, msix; + + msix = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_MSIX_POS, FXGMAC_FLAG_MSIX_LEN); + + need_free = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_LEGACY_IRQ_FREE_POS, + FXGMAC_FLAG_LEGACY_IRQ_FREE_LEN); + + if (!msix) { + if (need_free) { + devm_free_irq(pdata->dev, pdata->dev_irq, pdata); + pdata->expansion.int_flags = FXGMAC_SET_REG_BITS( + pdata->expansion.int_flags, + FXGMAC_FLAG_LEGACY_IRQ_FREE_POS, + FXGMAC_FLAG_LEGACY_IRQ_FREE_LEN, 0); + } + } + + if (!pdata->per_channel_irq) + return; + + channel = pdata->channel_head; + if (channel != NULL) { + for (i = 0; i < pdata->channel_count; i++, channel++) { + if (FXGMAC_IS_CHANNEL_WITH_TX_IRQ(i)) { + devm_free_irq(pdata->dev, + channel->expansion.dma_irq_tx, + channel); + if (netif_msg_drv(pdata)) + DPRINTK("fxgmac_free_irqs, MSIx irq_tx clear done, ch=%d\n", + i); + } + devm_free_irq(pdata->dev, channel->dma_irq, channel); + } + + devm_free_irq(pdata->dev, pdata->expansion.phy_irq, pdata); + } + if (netif_msg_drv(pdata)) + DPRINTK("fxgmac_free_irqs, MSIx rx irq clear done, total=%d\n", + i); +} + +void fxgmac_free_tx_data(struct fxgmac_pdata *pdata) +{ + struct fxgmac_desc_ops *desc_ops = &pdata->desc_ops; + struct fxgmac_desc_data *desc_data; + struct fxgmac_channel *channel; + struct fxgmac_ring *ring; + unsigned int i, j; + + channel = pdata->channel_head; + if (channel != NULL) { + for (i = 0; i < pdata->channel_count; i++, channel++) { + ring = channel->tx_ring; + if (!ring) + break; + + for (j = 0; j < ring->dma_desc_count; j++) { + desc_data = FXGMAC_GET_DESC_DATA(ring, j); + desc_ops->unmap_desc_data(pdata, desc_data); + } + } + } +} + +void fxgmac_free_rx_data(struct fxgmac_pdata *pdata) +{ + struct fxgmac_desc_ops *desc_ops = &pdata->desc_ops; + struct fxgmac_desc_data *desc_data; + struct fxgmac_channel *channel; + struct fxgmac_ring *ring; + unsigned int i, j; + + channel = pdata->channel_head; + if (channel != NULL) { + for (i = 0; i < pdata->channel_count; i++, channel++) { + ring = channel->rx_ring; + if (!ring) + break; + + for (j = 0; j < ring->dma_desc_count; j++) { + desc_data = FXGMAC_GET_DESC_DATA(ring, j); + desc_ops->unmap_desc_data(pdata, desc_data); + } + } + } +} + +/* + * since kernel does not clear the MSI mask bits and + * this function clear MSI mask bits when MSI is enabled. + */ +static int fxgmac_disable_pci_msi_config(struct pci_dev *pdev) +{ + u16 pcie_cap_offset; + u32 pcie_msi_mask_bits; + int ret = 0; + + pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_MSI); + if (pcie_cap_offset) { + ret = pci_read_config_dword(pdev, pcie_cap_offset, + &pcie_msi_mask_bits); + if (ret) { + printk(KERN_ERR + "read pci config space MSI cap. failed, %d\n", + ret); + ret = -EFAULT; + } + } + + pcie_msi_mask_bits = FXGMAC_SET_REG_BITS(pcie_msi_mask_bits, + PCI_CAP_ID_MSI_ENABLE_POS, + PCI_CAP_ID_MSI_ENABLE_LEN, 0); + ret = pci_write_config_dword(pdev, pcie_cap_offset, pcie_msi_mask_bits); + if (ret) { + printk(KERN_ERR "write pci config space MSI mask failed, %d\n", + ret); + ret = -EFAULT; + } + + return ret; +} + +static int fxgmac_disable_pci_msix_config(struct pci_dev *pdev) +{ + u16 pcie_cap_offset; + u32 pcie_msi_mask_bits; + int ret = 0; + + pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_MSIX); + if (pcie_cap_offset) { + ret = pci_read_config_dword(pdev, pcie_cap_offset, + &pcie_msi_mask_bits); + if (ret) { + printk(KERN_ERR + "read pci config space MSIX cap. failed, %d\n", + ret); + ret = -EFAULT; + } + } + + pcie_msi_mask_bits = FXGMAC_SET_REG_BITS(pcie_msi_mask_bits, + PCI_CAP_ID_MSIX_ENABLE_POS, + PCI_CAP_ID_MSIX_ENABLE_LEN, 0); + ret = pci_write_config_dword(pdev, pcie_cap_offset, pcie_msi_mask_bits); + if (ret) { + printk(KERN_ERR "write pci config space MSIX mask failed, %d\n", + ret); + ret = -EFAULT; + } + + return ret; +} + +int fxgmac_start(struct fxgmac_pdata *pdata) +{ + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + struct net_device *netdev = pdata->netdev; + int ret; + unsigned int pcie_low_power = 0; + u32 regval; + + if (netif_msg_drv(pdata)) + DPRINTK("fxgmac start callin here.\n"); + + /* must reset software again here, to avoid flushing tx queue error caused by the system only run probe + * when installing driver on the arm platform. + */ + hw_ops->exit(pdata); + + if (FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_LEGACY_POS, + FXGMAC_FLAG_LEGACY_LEN)) { + /* + * we should disable msi and msix here when we use legacy interrupt, for two reasons: + * 1. Exit will restore msi and msix config regisiter, that may enable them. + * 2. When the driver that uses the msix interrupt by default is compiled + * into the OS, uninstall the driver through rmmod, and then install the + * driver that uses the legacy interrupt, at which time the msix enable + * will be turned on again by default after waking up from S4 on some platform. + * such as UOS platform. + */ + ret = fxgmac_disable_pci_msi_config(pdata->pdev); + ret |= fxgmac_disable_pci_msix_config(pdata->pdev); + if (ret) + return ret; + } + + hw_ops->reset_phy(pdata); + hw_ops->release_phy(pdata); + hw_ops->pcie_init(pdata, pcie_low_power & PCIE_LP_ASPM_LTR, + pcie_low_power & PCIE_LP_ASPM_L1SS, + pcie_low_power & PCIE_LP_ASPM_L1, + pcie_low_power & PCIE_LP_ASPM_L0S); + hw_ops->config_power_up(pdata); + + fxgmac_dismiss_all_int(pdata); + + ret = hw_ops->init(pdata); + if (ret) { + printk("fxgmac hw init error.\n"); + return ret; + } + fxgmac_napi_enable(pdata, 1); + + ret = fxgmac_request_irqs(pdata); + if (ret) + goto err_napi; + + hw_ops->enable_tx(pdata); + hw_ops->enable_rx(pdata); + + /* config interrupt to level signal */ + regval = (u32)readl((const volatile void *)(pdata->mac_regs + DMA_MR)); + regval = FXGMAC_SET_REG_BITS(regval, DMA_MR_INTM_POS, DMA_MR_INTM_LEN, + 1); + regval = FXGMAC_SET_REG_BITS(regval, DMA_MR_QUREAD_POS, + DMA_MR_QUREAD_LEN, 1); + writel(regval, pdata->mac_regs + DMA_MR); + + writel(0xF0000000, + (volatile void *)(netdev->base_addr + MGMT_INT_CTRL0)); + + hw_ops->set_interrupt_moderation(pdata); + + if (pdata->per_channel_irq) + hw_ops->enable_msix_rxtxphyinterrupt(pdata); + + fxgmac_enable_rx_tx_ints(pdata); + + hw_ops->led_under_active(pdata); + + return 0; + +err_napi: + fxgmac_napi_disable(pdata, 1); + hw_ops->exit(pdata); + DPRINTK("fxgmac start callout with irq err.\n"); + return ret; +} + +void fxgmac_stop(struct fxgmac_pdata *pdata) +{ + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + struct net_device *netdev = pdata->netdev; + struct fxgmac_channel *channel; + struct netdev_queue *txq; + unsigned int i; + + if (pdata->per_channel_irq) { + hw_ops->disable_msix_interrupt(pdata); + } else { + hw_ops->disable_mgm_interrupt(pdata); + } + + pdata->expansion.phy_link = false; + + netif_carrier_off(netdev); + netif_tx_stop_all_queues(netdev); + + hw_ops->disable_tx(pdata); + hw_ops->disable_rx(pdata); + fxgmac_free_irqs(pdata); + fxgmac_napi_disable(pdata, 1); + + channel = pdata->channel_head; + if (channel != NULL) { + 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); + } + } + + switch (pdata->expansion.current_state) { + case CURRENT_STATE_SUSPEND: + hw_ops->led_under_sleep(pdata); + break; + case CURRENT_STATE_SHUTDOWN: + case CURRENT_STATE_RESTART: + hw_ops->led_under_shutdown(pdata); + break; + case CURRENT_STATE_CLOSE: + break; + default: + break; + } +} + +void fxgmac_restart_dev(struct fxgmac_pdata *pdata) +{ + int ret; + + /* If not running, "restart" will happen on open */ + if (!netif_running(pdata->netdev)) + return; + + pdata->expansion.current_state = CURRENT_STATE_RESTART; + fxgmac_stop(pdata); + + fxgmac_free_tx_data(pdata); + fxgmac_free_rx_data(pdata); + + ret = fxgmac_start(pdata); + if (ret) { + printk("fxgmac_restart_dev: fxgmac_start failed.\n"); + } +} + +static void fxgmac_restart(struct work_struct *work) +{ + struct fxgmac_pdata *pdata = + container_of(work, struct fxgmac_pdata, expansion.restart_work); + + rtnl_lock(); + + fxgmac_restart_dev(pdata); + + rtnl_unlock(); +} + +void fxgmac_net_powerup(struct fxgmac_pdata *pdata) +{ + int ret; + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + + if (netif_msg_drv(pdata)) + DPRINTK("fxgmac_net_powerup callin\n"); + + /* signal that we are up now */ + pdata->expansion.powerstate = 0; /* clear all bits as normal now */ + if (__test_and_set_bit(FXGMAC_POWER_STATE_UP, + &pdata->expansion.powerstate)) { + return; /* do nothing if already up */ + } + + ret = fxgmac_start(pdata); + if (ret) { + printk("fxgmac_net_powerup: fxgmac_start error\n"); + return; + } + + /* must call it after fxgmac_start, because it will be enable in fxgmac_start */ + hw_ops->disable_arp_offload(pdata); + + if (netif_msg_drv(pdata)) { + DPRINTK("fxgmac_net_powerup callout, powerstate=%ld.\n", + pdata->expansion.powerstate); + } +} + +void fxgmac_net_powerdown(struct fxgmac_pdata *pdata, unsigned int wol) +{ + struct net_device *netdev = pdata->netdev; + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + + if (netif_msg_drv(pdata)) + DPRINTK("fxgmac_net_powerdown callin here.\n"); + + /* signal that we are down to the interrupt handler */ + if (__test_and_set_bit(FXGMAC_POWER_STATE_DOWN, + &pdata->expansion.powerstate)) + return; /* do nothing if already down */ + + if (netif_msg_drv(pdata)) + DPRINTK("fxgmac_net_powerdown continue with down process.\n"); + /* phy polling timer should detect the state of fxgmac and stop link status polling accordingly */ + + __clear_bit(FXGMAC_POWER_STATE_UP, &pdata->expansion.powerstate); + + /* Shut off incoming Tx traffic */ + netif_tx_stop_all_queues(netdev); + + /* call carrier off first to avoid false dev_watchdog timeouts */ + netif_carrier_off(netdev); + netif_tx_disable(netdev); + + /* Disable Rx */ + hw_ops->disable_rx(pdata); + + /* synchronize_rcu() needed for pending XDP buffers to drain */ + synchronize_rcu(); + + fxgmac_stop(pdata); /* some works are redundent in this call */ + + /* must call it after software reset */ + hw_ops->pre_power_down(pdata, false); + + /* set mac to lowpower mode and enable wol accordingly */ + hw_ops->config_power_down(pdata, wol); + + /* handle vfs if it is envolved */ + + /* similar work as in restart() for that, we do need a resume laterly */ + fxgmac_free_tx_data(pdata); + fxgmac_free_rx_data(pdata); + + if (netif_msg_drv(pdata)) + DPRINTK("fxgmac_net_powerdown callout, powerstate=%ld.\n", + pdata->expansion.powerstate); +} + +static int fxgmac_open(struct net_device *netdev) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_desc_ops *desc_ops; + int ret; + + if (netif_msg_drv(pdata)) + DPRINTK("fxgmac_open callin\n"); + + desc_ops = &pdata->desc_ops; + + /* TODO: Initialize the phy */ + + /* Calculate the Rx buffer size before allocating rings */ + ret = fxgmac_calc_rx_buf_size(netdev, netdev->mtu); + if (ret < 0) + return ret; + pdata->rx_buf_size = ret; + + /* Allocate the channels and rings */ + ret = desc_ops->alloc_channles_and_rings(pdata); + if (ret) + return ret; + + INIT_WORK(&pdata->expansion.restart_work, fxgmac_restart); + + ret = fxgmac_start(pdata); + if (ret) + goto err_channels_and_rings; + + if (netif_msg_drv(pdata)) + DPRINTK("fxgmac_open callout\n"); + + return 0; + +err_channels_and_rings: + desc_ops->free_channels_and_rings(pdata); + DPRINTK("fxgmac_open callout with channel alloc err\n"); + return ret; +} + +static int fxgmac_close(struct net_device *netdev) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_desc_ops *desc_ops; + + if (netif_msg_drv(pdata)) + DPRINTK("fxgmac_close callin\n"); + + desc_ops = &pdata->desc_ops; + + pdata->expansion.current_state = + (pdata->expansion.current_state == CURRENT_STATE_SHUTDOWN) ? + pdata->expansion.current_state : + CURRENT_STATE_CLOSE; + + /* Stop the device */ + fxgmac_stop(pdata); + + /* Free the channels and rings */ + desc_ops->free_channels_and_rings(pdata); + + pdata->hw_ops.reset_phy(pdata); + + if (netif_msg_drv(pdata)) + DPRINTK("fxgmac_close callout\n"); + + return 0; +} + +#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 0, 0)) && \ + (LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0))) +static void fxgmac_tx_timeout(struct net_device *netdev) +#else +static void fxgmac_tx_timeout(struct net_device *netdev, unsigned int unused) +#endif +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + + netdev_warn(netdev, "tx timeout, device restarting\n"); +#if FXGMAC_TX_HANG_TIMER_EN + if (!pdata->tx_hang_restart_queuing) + schedule_work(&pdata->expansion.restart_work); +#else + schedule_work(&pdata->expansion.restart_work); +#endif +} + +static int fxgmac_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_pkt_info *tx_pkt_info; + struct fxgmac_desc_ops *desc_ops; + struct fxgmac_channel *channel; + struct fxgmac_hw_ops *hw_ops; + struct netdev_queue *txq; + struct fxgmac_ring *ring; + int ret; + + desc_ops = &pdata->desc_ops; + hw_ops = &pdata->hw_ops; + + if (netif_msg_tx_done(pdata)) + DPRINTK("xmit callin, skb->len=%d, q=%d\n", skb->len, + skb->queue_mapping); + + channel = pdata->channel_head + skb->queue_mapping; + txq = netdev_get_tx_queue(netdev, channel->queue_index); + ring = channel->tx_ring; + tx_pkt_info = &ring->pkt_info; + + if (skb->len == 0) { + netif_err(pdata, tx_err, netdev, + "empty skb received from stack\n"); + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + /* Prepare preliminary packet info for TX */ + memset(tx_pkt_info, 0, sizeof(*tx_pkt_info)); + fxgmac_prep_tx_pkt(pdata, ring, skb, tx_pkt_info); + + /* Check that there are enough descriptors available */ + ret = fxgmac_maybe_stop_tx_queue(channel, ring, + tx_pkt_info->desc_count); + if (ret) { + return ret; + } + + ret = fxgmac_prep_tso(pdata, skb, tx_pkt_info); + if (ret) { + netif_err(pdata, tx_err, netdev, + "error processing TSO packet\n"); + DPRINTK("dev_xmit, tx err for TSO\n"); + dev_kfree_skb_any(skb); + return ret; + } + fxgmac_prep_vlan(skb, tx_pkt_info); + + if (!desc_ops->map_tx_skb(channel, skb)) { + dev_kfree_skb_any(skb); + DPRINTK("xmit, map tx skb err\n"); + return NETDEV_TX_OK; + } + + /* Report on the actual number of bytes (to be) sent */ + netdev_tx_sent_queue(txq, tx_pkt_info->tx_bytes); + if (netif_msg_tx_done(pdata)) + DPRINTK("xmit, before hw_xmit, byte len=%d\n", + tx_pkt_info->tx_bytes); + + /* Configure required descriptor fields for transmission */ + hw_ops->dev_xmit(channel); +#if FXGMAC_DUMMY_TX_DEBUG + DPRINTK("tx hw_ops->dev_xmit ok\n"); +#endif + if (netif_msg_pktdata(pdata)) + fxgmac_dbg_pkt(netdev, skb, true); + + /* Stop the queue in advance if there may not be enough descriptors */ + fxgmac_maybe_stop_tx_queue(channel, ring, FXGMAC_TX_MAX_DESC_NR); + + return NETDEV_TX_OK; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) +static void fxgmac_get_stats64(struct net_device *netdev, + struct rtnl_link_stats64 *s) +#else +static struct rtnl_link_stats64 *fxgmac_get_stats64(struct net_device *netdev, + struct rtnl_link_stats64 *s) +#endif +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_stats *pstats = &pdata->stats; + +#if FXGMAC_PM_FEATURE_ENABLED + /* 20210709 for net power down */ + if (!test_bit(FXGMAC_POWER_STATE_DOWN, &pdata->expansion.powerstate)) +#endif + { + pdata->hw_ops.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; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) + return s; +#endif +} + +static int fxgmac_set_mac_address(struct net_device *netdev, void *addr) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + struct sockaddr *saddr = addr; + + if (!is_valid_ether_addr(saddr->sa_data)) + return -EADDRNOTAVAIL; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)) + eth_hw_addr_set(netdev, saddr->sa_data); +#else + memcpy(netdev->dev_addr, saddr->sa_data, netdev->addr_len); +#endif + memcpy(pdata->mac_addr, saddr->sa_data, netdev->addr_len); + + hw_ops->set_mac_address(pdata, saddr->sa_data); + hw_ops->set_mac_hash(pdata); + + DPRINTK("fxgmac, set mac addr to %02x:%02x:%02x:%02x:%02x:%02x\n", + netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], + netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); + return 0; +} + +/* cmd = [0x89F0, 0x89FF] */ +static int fxgmac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + struct file f; + int ret = FXGMAC_SUCCESS; + struct fxgmac_pdata *pdata = netdev_priv(netdev); + + if (!netif_running(netdev)) + return -ENODEV; + + f.private_data = pdata; + + switch (cmd) { + case FXGMAC_DEV_CMD: + ret = fxgmac_dbg_netdev_ops_ioctl( + &f, FXGMAC_IOCTL_DFS_COMMAND, + (unsigned long)(ifr->ifr_data)); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)) +static int fxgmac_siocdevprivate(struct net_device *dev, struct ifreq *ifr, + void __user *data, int cmd) +{ + return fxgmac_ioctl(dev, ifr, cmd); +} +#endif + +static int fxgmac_change_mtu(struct net_device *netdev, int mtu) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + int ret; +#ifdef FXGMAC_DEBUG + int old_mtu = netdev->mtu; +#endif + + fxgmac_stop(pdata); + fxgmac_free_tx_data(pdata); + + /* We must unmap rx desc's dma before we change rx_buf_size. */ + /* Becaues the size of the unmapped DMA is set according to rx_buf_size */ + fxgmac_free_rx_data(pdata); + + pdata->jumbo = mtu > ETH_DATA_LEN ? 1 : 0; + + ret = fxgmac_calc_rx_buf_size(netdev, mtu); + if (ret < 0) + return ret; + + pdata->rx_buf_size = ret; + netdev->mtu = mtu; + + if (netif_running(netdev)) + fxgmac_start(pdata); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) + DPRINTK("fxgmac, set MTU from %d to %d. min, max=(%d,%d)\n", old_mtu, + netdev->mtu, netdev->min_mtu, netdev->max_mtu); +#else + DPRINTK("fxgmac, set MTU from %d to %d.\n", old_mtu, netdev->mtu); +#endif + + return 0; +} + +static int fxgmac_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, + u16 vid) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + + set_bit(vid, pdata->active_vlans); +#if FXGMAC_FILTER_SINGLE_VLAN_ENABLED + pdata->vlan = vid; + hw_ops->enable_rx_vlan_filtering(pdata); +#else + hw_ops->update_vlan_hash_table(pdata); +#endif + DPRINTK("fxgmac, add rx vlan %d\n", vid); + return 0; +} + +static int fxgmac_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, + u16 vid) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + + clear_bit(vid, pdata->active_vlans); +#if FXGMAC_FILTER_SINGLE_VLAN_ENABLED + pdata->vlan = 0; + hw_ops->disable_rx_vlan_filtering(pdata); +#else + hw_ops->update_vlan_hash_table(pdata); +#endif + + DPRINTK("fxgmac, del rx vlan %d\n", vid); + return 0; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void fxgmac_poll_controller(struct net_device *netdev) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_channel *channel; + unsigned int i; + + if (pdata->per_channel_irq) { + channel = pdata->channel_head; + for (i = 0; i < pdata->channel_count; i++, channel++) + fxgmac_dma_isr(channel->dma_irq, channel); + } else { + disable_irq(pdata->dev_irq); + fxgmac_isr(pdata->dev_irq, pdata); + enable_irq(pdata->dev_irq); + } +} +#endif /* CONFIG_NET_POLL_CONTROLLER */ + +static int fxgmac_set_features(struct net_device *netdev, + netdev_features_t features) +{ + netdev_features_t rxhash, rxcsum, rxvlan, rxvlan_filter, tso; + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + int ret = 0; + + rxhash = pdata->expansion.netdev_features & NETIF_F_RXHASH; + rxcsum = pdata->expansion.netdev_features & NETIF_F_RXCSUM; + rxvlan = pdata->expansion.netdev_features & NETIF_F_HW_VLAN_CTAG_RX; + rxvlan_filter = pdata->expansion.netdev_features & + NETIF_F_HW_VLAN_CTAG_FILTER; + tso = pdata->expansion.netdev_features & (NETIF_F_TSO | NETIF_F_TSO6); + + if ((features & (NETIF_F_TSO | NETIF_F_TSO6)) && !tso) { + printk("enable tso.\n"); + pdata->hw_feat.tso = 1; + hw_ops->config_tso(pdata); + } else if (!(features & (NETIF_F_TSO | NETIF_F_TSO6)) && tso) { + printk("disable tso.\n"); + pdata->hw_feat.tso = 0; + hw_ops->config_tso(pdata); + } + + if ((features & NETIF_F_RXHASH) && !rxhash) + ret = hw_ops->enable_rss(pdata); + else if (!(features & NETIF_F_RXHASH) && rxhash) + ret = hw_ops->disable_rss(pdata); + if (ret) + return ret; + + if ((features & NETIF_F_RXCSUM) && !rxcsum) + hw_ops->enable_rx_csum(pdata); + else if (!(features & NETIF_F_RXCSUM) && rxcsum) + hw_ops->disable_rx_csum(pdata); + + if ((features & NETIF_F_HW_VLAN_CTAG_RX) && !rxvlan) + hw_ops->enable_rx_vlan_stripping(pdata); + else if (!(features & NETIF_F_HW_VLAN_CTAG_RX) && rxvlan) + hw_ops->disable_rx_vlan_stripping(pdata); + + if ((features & NETIF_F_HW_VLAN_CTAG_FILTER) && !rxvlan_filter) + hw_ops->enable_rx_vlan_filtering(pdata); + else if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER) && rxvlan_filter) + hw_ops->disable_rx_vlan_filtering(pdata); + + pdata->expansion.netdev_features = features; + + DPRINTK("fxgmac, set features done,%llx\n", (u64)features); + return 0; +} + +static void fxgmac_set_rx_mode(struct net_device *netdev) +{ + struct fxgmac_pdata *pdata = netdev_priv(netdev); + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + + hw_ops->config_rx_mode(pdata); +} + +static const struct net_device_ops fxgmac_netdev_ops = { + .ndo_open = fxgmac_open, + .ndo_stop = fxgmac_close, + .ndo_start_xmit = fxgmac_xmit, + .ndo_tx_timeout = fxgmac_tx_timeout, + .ndo_get_stats64 = fxgmac_get_stats64, + .ndo_change_mtu = fxgmac_change_mtu, + .ndo_set_mac_address = fxgmac_set_mac_address, + .ndo_validate_addr = eth_validate_addr, + .ndo_do_ioctl = fxgmac_ioctl, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)) + .ndo_siocdevprivate = fxgmac_siocdevprivate, +#endif + .ndo_vlan_rx_add_vid = fxgmac_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = fxgmac_vlan_rx_kill_vid, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = fxgmac_poll_controller, +#endif + .ndo_set_features = fxgmac_set_features, + .ndo_set_rx_mode = fxgmac_set_rx_mode, +}; + +const struct net_device_ops *fxgmac_get_netdev_ops(void) +{ + return &fxgmac_netdev_ops; +} + +static void fxgmac_rx_refresh(struct fxgmac_channel *channel) +{ + struct fxgmac_pdata *pdata = channel->pdata; + struct fxgmac_ring *ring = channel->rx_ring; + struct fxgmac_desc_data *desc_data; + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + + while (ring->dirty != ring->cur) { + desc_data = FXGMAC_GET_DESC_DATA(ring, ring->dirty); + hw_ops->rx_desc_reset(pdata, desc_data, ring->dirty); + ring->dirty = + FXGMAC_GET_ENTRY(ring->dirty, ring->dma_desc_count); + } + + /* Make sure everything is written before the register write */ + wmb(); + + /* Update the Rx Tail Pointer Register with address of + * the last cleaned entry + */ + desc_data = FXGMAC_GET_DESC_DATA( + ring, (ring->dirty - 1) & (ring->dma_desc_count - 1)); + writel(lower_32_bits(desc_data->dma_desc_addr), + FXGMAC_DMA_REG(channel, DMA_CH_RDTR_LO)); +} + +static struct sk_buff *fxgmac_create_skb(struct fxgmac_pdata *pdata, + struct napi_struct *napi, + struct fxgmac_desc_data *desc_data, + unsigned int len) +{ + struct sk_buff *skb; + skb = __netdev_alloc_skb_ip_align(pdata->netdev, len, GFP_ATOMIC); + if (!skb) { + netdev_err(pdata->netdev, "%s: Rx init fails; skb is NULL\n", + __func__); + return NULL; + } + + dma_sync_single_for_cpu(pdata->dev, desc_data->rx.buf.dma_base, len, + DMA_FROM_DEVICE); + skb_copy_to_linear_data(skb, desc_data->skb->data, len); + skb_put(skb, len); + dma_sync_single_for_device(pdata->dev, desc_data->rx.buf.dma_base, len, + DMA_FROM_DEVICE); + + return skb; +} + +static int fxgmac_tx_poll(struct fxgmac_channel *channel) +{ + struct fxgmac_pdata *pdata = channel->pdata; + struct fxgmac_ring *ring = channel->tx_ring; + struct net_device *netdev = pdata->netdev; + unsigned int tx_packets = 0, tx_bytes = 0; + struct fxgmac_desc_data *desc_data; + struct fxgmac_dma_desc *dma_desc; + struct fxgmac_desc_ops *desc_ops; + struct fxgmac_hw_ops *hw_ops; + struct netdev_queue *txq; + int processed = 0; + unsigned int cur; + + static int fxgmac_restart_need; + static u32 change_cnt; + static u32 reg_cur_pre = 0xffffffff; + +#if FXGMAC_TX_HANG_TIMER_EN + static u32 reg_cur; +#endif + + desc_ops = &pdata->desc_ops; + hw_ops = &pdata->hw_ops; + + /* Nothing to do if there isn't a Tx ring for this channel */ + if (!ring) { + if (netif_msg_tx_done(pdata) && + (channel->queue_index < pdata->tx_q_count)) + DPRINTK("tx_poll, null point to ring %d\n", + channel->queue_index); + return 0; + } + if ((ring->cur != ring->dirty) && (netif_msg_tx_done(pdata))) + DPRINTK("tx_poll callin, ring_cur=%d, ring_dirty=%d, qIdx=%d\n", + ring->cur, ring->dirty, channel->queue_index); + + cur = ring->cur; + + /* Be sure we get ring->cur before accessing descriptor data */ + smp_rmb(); + + txq = netdev_get_tx_queue(netdev, channel->queue_index); + + while (ring->dirty != cur) { + desc_data = FXGMAC_GET_DESC_DATA(ring, ring->dirty); + dma_desc = desc_data->dma_desc; + + if (!hw_ops->tx_complete(dma_desc)) { +#if FXGMAC_TRIGGER_TX_HANG + struct net_device *netdev = pdata->netdev; +#define FXGMAC_HANG_THRESHOLD 1 + reg_cur = readl(FXGMAC_DMA_REG( + channel, 0x44 /* tx desc curr pointer reg */)); + + if (reg_cur != reg_cur_pre) { + reg_cur_pre = reg_cur; + change_cnt = 0; + } else { + change_cnt++; + } + + if (change_cnt > 2) { + DPRINTK("after complete check, cur=%d, dirty=%d, qIdx=%d, hw desc cur=%#x, pre=%#x\n", + ring->cur, ring->dirty, + channel->queue_index, reg_cur, + reg_cur_pre); + + if ((ring->cur > ring->dirty) && + ((ring->cur - ring->dirty) > + FXGMAC_HANG_THRESHOLD)) { + DPRINTK("after complete check warning..., too many TBD occupied by HW, 0xdbbb, %d.\n", + (ring->cur - ring->dirty)); + (*((u32 *)(netdev->base_addr + + 0x1000))) = 0xdbbb; + + if (!fxgmac_restart_need) { + schedule_work( + &pdata->expansion + .restart_work); + fxgmac_restart_need = 1; + change_cnt = 0; + } + } else if ((ring->cur < ring->dirty) && + ((ring->cur + (ring->dma_desc_count - + ring->dirty)) > + FXGMAC_HANG_THRESHOLD)) { + DPRINTK("after complete check warning..., too many TBD occupied by HW, 0xdb00, %d.\n", + (ring->cur + + (ring->dma_desc_count - + ring->dirty))); + (*((u32 *)(netdev->base_addr + + 0x1000))) = 0xdb00; + + if (!fxgmac_restart_need) { + schedule_work( + &pdata->expansion + .restart_work); + fxgmac_restart_need = 1; + change_cnt = 0; + } + } + } +#endif +#if FXGMAC_TX_HANG_TIMER_EN + if ((!pdata->tx_hang_restart_queuing) && + (!channel->expansion.tx_hang_timer_active)) { + reg_cur = ring->dirty; + if (reg_cur_pre != reg_cur) { + reg_cur_pre = reg_cur; + change_cnt = 0; + } else { + change_cnt++; + } + + if (change_cnt > 4) { +#if FXGMAC_TX_HANG_CHECH_DIRTY + channel->expansion.tx_hang_hw_cur = + ring->dirty; +#else + channel->expansion + .tx_hang_hw_cur = readl(FXGMAC_DMA_REG( + channel, + 0x44 /* tx desc curr pointer reg */)); +#endif + /* double check for race conditione */ + if ((!pdata->tx_hang_restart_queuing) && + (!channel->expansion + .tx_hang_timer_active)) { + DPRINTK("tx_hang polling: start timer at desc %u, timer act=%u, queuing=%u, qidx=%u.\n", + reg_cur, + channel->expansion + .tx_hang_timer_active, + pdata->tx_hang_restart_queuing, + channel->queue_index); + fxgmac_tx_hang_timer_start( + channel); + } + } + } +#endif + + break; + } + + reg_cur_pre = 0xffffffff; + fxgmac_restart_need = 0; + change_cnt = 0; + + /* Make sure descriptor fields are read after reading + * the OWN bit + */ + dma_rmb(); + + if (netif_msg_tx_done(pdata)) + fxgmac_dump_tx_desc(pdata, ring, ring->dirty, 1, 0); + + if (hw_ops->is_last_desc(dma_desc)) { + tx_packets += desc_data->tx.packets; + tx_bytes += desc_data->tx.bytes; + } + + /* Free the SKB and reset the descriptor for re-use */ + desc_ops->unmap_desc_data(pdata, desc_data); + hw_ops->tx_desc_reset(desc_data); + + processed++; + ring->dirty = + FXGMAC_GET_ENTRY(ring->dirty, ring->dma_desc_count); + } + + if (!processed) + return 0; + + netdev_tx_completed_queue(txq, tx_packets, tx_bytes); + + if ((ring->tx.queue_stopped == 1) && + (fxgmac_tx_avail_desc(ring) > FXGMAC_TX_DESC_MIN_FREE)) { + ring->tx.queue_stopped = 0; + netif_tx_wake_queue(txq); + } + + if (netif_msg_tx_done(pdata)) { + DPRINTK("tx_poll callout, processed=%d\n", processed); + } + + return processed; +} + +static int fxgmac_rx_poll(struct fxgmac_channel *channel, int budget) +{ + struct fxgmac_pdata *pdata = channel->pdata; + struct fxgmac_ring *ring = channel->rx_ring; + struct net_device *netdev = pdata->netdev; + unsigned int len; + unsigned int context_next, context; + struct fxgmac_desc_data *desc_data; + struct fxgmac_pkt_info *pkt_info; + unsigned int incomplete; + struct fxgmac_hw_ops *hw_ops; + struct napi_struct *napi; + struct sk_buff *skb; + int packet_count = 0; + u32 ipce, iphe; + + hw_ops = &pdata->hw_ops; + + /* Nothing to do if there isn't a Rx ring for this channel */ + if (!ring) + return 0; + + incomplete = 0; + context_next = 0; + + napi = (pdata->per_channel_irq) ? &channel->expansion.napi_rx : + &pdata->expansion.napi; + + desc_data = FXGMAC_GET_DESC_DATA(ring, ring->cur); + pkt_info = &ring->pkt_info; + + while (packet_count < budget) { + memset(pkt_info, 0, sizeof(*pkt_info)); + skb = NULL; + len = 0; + +read_again: + desc_data = FXGMAC_GET_DESC_DATA(ring, ring->cur); + + if (fxgmac_rx_dirty_desc(ring) > FXGMAC_RX_DESC_MAX_DIRTY) + fxgmac_rx_refresh(channel); + + if (hw_ops->dev_read(channel)) + break; + + ring->cur = FXGMAC_GET_ENTRY(ring->cur, ring->dma_desc_count); + + incomplete = FXGMAC_GET_REG_BITS( + pkt_info->attributes, + RX_PACKET_ATTRIBUTES_INCOMPLETE_POS, + RX_PACKET_ATTRIBUTES_INCOMPLETE_LEN); + context_next = FXGMAC_GET_REG_BITS( + pkt_info->attributes, + RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_POS, + RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_LEN); + context = FXGMAC_GET_REG_BITS(pkt_info->attributes, + RX_PACKET_ATTRIBUTES_CONTEXT_POS, + RX_PACKET_ATTRIBUTES_CONTEXT_LEN); + + if (incomplete || context_next) + goto read_again; + + if (pkt_info->errors) { + netif_err(pdata, rx_err, netdev, + "error in received packet\n"); + dev_kfree_skb(skb); + goto next_packet; + } + + if (!context) { + len = desc_data->rx.len; + if (len > pdata->rx_buf_size) { + if (net_ratelimit()) + netdev_err( + pdata->netdev, + "len %d larger than size (%d)\n", + len, pdata->rx_buf_size); + pdata->netdev->stats.rx_dropped++; + goto next_packet; + } + + if (len == 0) { + if (net_ratelimit()) + netdev_err( + pdata->netdev, + "A packet of length 0 was received\n"); + pdata->netdev->stats.rx_length_errors++; + goto next_packet; + } + + if (len && !skb) { + skb = fxgmac_create_skb(pdata, napi, desc_data, + len); + if (unlikely(!skb)) { + if (net_ratelimit()) + netdev_warn( + pdata->netdev, + "create skb failed\n"); + goto next_packet; + } + } + } + + if (!skb) + goto next_packet; + + if (netif_msg_pktdata(pdata)) + fxgmac_print_pkt(netdev, skb, false); + + skb_checksum_none_assert(skb); + if (netdev->features & NETIF_F_RXCSUM) { + ipce = FXGMAC_GET_REG_BITS_LE( + desc_data->dma_desc->desc1, + RX_NORMAL_DESC1_WB_IPCE_POS, + RX_NORMAL_DESC1_WB_IPCE_LEN); + iphe = FXGMAC_GET_REG_BITS_LE( + desc_data->dma_desc->desc1, + RX_NORMAL_DESC1_WB_IPHE_POS, + RX_NORMAL_DESC1_WB_IPHE_LEN); + /* if csum error, let the stack verify checksum errors.otherwise don't verify */ + if (!ipce && !iphe && + FXGMAC_GET_REG_BITS( + pkt_info->attributes, + RX_PACKET_ATTRIBUTES_CSUM_DONE_POS, + RX_PACKET_ATTRIBUTES_CSUM_DONE_LEN)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + } + + if (FXGMAC_GET_REG_BITS(pkt_info->attributes, + RX_PACKET_ATTRIBUTES_VLAN_CTAG_POS, + RX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN)) { + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), + pkt_info->vlan_ctag); + pdata->stats.rx_vlan_packets++; + } + + if (FXGMAC_GET_REG_BITS(pkt_info->attributes, + RX_PACKET_ATTRIBUTES_RSS_HASH_POS, + RX_PACKET_ATTRIBUTES_RSS_HASH_LEN)) + skb_set_hash(skb, pkt_info->rss_hash, + pkt_info->rss_hash_type); + + skb->dev = netdev; + skb->protocol = eth_type_trans(skb, netdev); + skb_record_rx_queue(skb, channel->queue_index); + + if (pdata->expansion.fxgmac_test_tso_flag) { + /* tso test */ + if (pdata->expansion.fxgmac_test_tso_seg_num == 1) { + /* last segment */ + if (pdata->expansion.fxgmac_test_last_tso_len == + skb->len + FXGMAC_TEST_MAC_HEAD_LEN) { + /* receive last segment, reset flag */ + pdata->expansion.fxgmac_test_tso_flag = + false; + pdata->expansion + .fxgmac_test_tso_seg_num = 0; + pdata->expansion.fxgmac_test_packet_len = + 0; + pdata->expansion + .fxgmac_test_last_tso_len = 0; + + /* process packet */ + if ((pdata->expansion + .fxgmac_test_skb_arr_in_index + + 1) % FXGMAC_MAX_DBG_TEST_PKT != + pdata->expansion + .fxgmac_test_skb_arr_out_index) { + struct sk_buff *tmpskb = + skb_copy(skb, + GFP_ATOMIC); + skb_push( + tmpskb, + FXGMAC_TEST_MAC_HEAD_LEN); + + pdata->expansion.fxgmac_test_skb_array + [pdata->expansion + .fxgmac_test_skb_arr_in_index] = + tmpskb; + pdata->expansion + .fxgmac_test_skb_arr_in_index = + (pdata->expansion + .fxgmac_test_skb_arr_in_index + + 1) % + FXGMAC_MAX_DBG_TEST_PKT; + } else { + DPRINTK("loopback test buffer is full."); + } + } + } else { /* non last segment */ + if (pdata->expansion.fxgmac_test_packet_len == + skb->len + FXGMAC_TEST_MAC_HEAD_LEN) { + /* receive a segment */ + pdata->expansion + .fxgmac_test_tso_seg_num--; + + /* process packet */ + if ((pdata->expansion + .fxgmac_test_skb_arr_in_index + + 1) % FXGMAC_MAX_DBG_TEST_PKT != + pdata->expansion + .fxgmac_test_skb_arr_out_index) { + struct sk_buff *tmpskb = + skb_copy(skb, + GFP_ATOMIC); + skb_push( + tmpskb, + FXGMAC_TEST_MAC_HEAD_LEN); + + pdata->expansion.fxgmac_test_skb_array + [pdata->expansion + .fxgmac_test_skb_arr_in_index] = + tmpskb; + pdata->expansion + .fxgmac_test_skb_arr_in_index = + (pdata->expansion + .fxgmac_test_skb_arr_in_index + + 1) % + FXGMAC_MAX_DBG_TEST_PKT; + } else { + DPRINTK("loopback test buffer is full."); + } + } + } + } else if (pdata->expansion.fxgmac_test_packet_len != 0) { + /* xsum and phy loopback test */ + if (pdata->expansion.fxgmac_test_packet_len == + skb->len + FXGMAC_TEST_MAC_HEAD_LEN) { + /* reset fxg_packet_len */ + pdata->expansion.fxgmac_test_packet_len = 0; + + if ((pdata->expansion + .fxgmac_test_skb_arr_in_index + + 1) % FXGMAC_MAX_DBG_TEST_PKT != + pdata->expansion + .fxgmac_test_skb_arr_out_index) { + struct sk_buff *tmpskb = + skb_copy(skb, GFP_ATOMIC); + skb_push(tmpskb, + FXGMAC_TEST_MAC_HEAD_LEN); + + pdata->expansion.fxgmac_test_skb_array + [pdata->expansion + .fxgmac_test_skb_arr_in_index] = + tmpskb; + pdata->expansion + .fxgmac_test_skb_arr_in_index = + (pdata->expansion + .fxgmac_test_skb_arr_in_index + + 1) % + FXGMAC_MAX_DBG_TEST_PKT; + } else { + DPRINTK("loopback test buffer is full."); + } + } + } + napi_gro_receive(napi, skb); + +next_packet: + packet_count++; + + pdata->netdev->stats.rx_packets++; + pdata->netdev->stats.rx_bytes += len; + } + + fxgmac_rx_refresh(channel); + + return packet_count; +} + +static int fxgmac_one_poll_tx(struct napi_struct *napi, int budget) +{ + struct fxgmac_channel *channel = + container_of(napi, struct fxgmac_channel, expansion.napi_tx); + int ret = 0; + struct fxgmac_pdata *pdata = channel->pdata; + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + + ret = fxgmac_tx_poll(channel); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) + if (napi_complete_done(napi, 0)) { + hw_ops->enable_msix_one_interrupt(pdata, MSI_ID_TXQ0); + } +#else + napi_complete(napi); + hw_ops->enable_msix_one_interrupt(pdata, MSI_ID_TXQ0); +#endif + return 0; +} + +static int fxgmac_one_poll_rx(struct napi_struct *napi, int budget) +{ + struct fxgmac_channel *channel = + container_of(napi, struct fxgmac_channel, expansion.napi_rx); + int processed = 0; + struct fxgmac_pdata *pdata = channel->pdata; + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + + processed = fxgmac_rx_poll(channel, budget); + if (processed < budget) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) + /* if there no interrupt occured when this interrupt running, struct napi's state is NAPIF_STATE_SCHED, + * napi_complete_done return true and we can enable irq, it will not cause unbalanced iqr issure. + * if there more interrupt occured when this interrupt running, struct napi's state is NAPIF_STATE_SCHED | NAPIF_STATE_MISSED + * because napi_schedule_prep will make it. At this time napi_complete_done will return false and + * schedule poll again because of NAPIF_STATE_MISSED, it will cause unbalanced irq issure. + */ + if (napi_complete_done(napi, processed)) { + hw_ops->enable_msix_one_interrupt(pdata, + channel->queue_index); + } +#else + napi_complete(napi); + hw_ops->enable_msix_one_interrupt(pdata, channel->queue_index); +#endif + } + + return processed; +} + +static int fxgmac_all_poll(struct napi_struct *napi, int budget) +{ + struct fxgmac_pdata *pdata = + container_of(napi, struct fxgmac_pdata, expansion.napi); + struct fxgmac_channel *channel; + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + int processed; + unsigned int i; + + if (netif_msg_rx_status(pdata)) { + DPRINTK("rx all_poll callin budget=%d\n", budget); + } + + processed = 0; + do { + channel = pdata->channel_head; + /* Cleanup Tx ring first */ + /*since only 1 tx channel supported in this version, poll ch 0 always. */ + fxgmac_tx_poll(pdata->channel_head + 0); + for (i = 0; i < pdata->channel_count; i++, channel++) { + processed += fxgmac_rx_poll(channel, budget); + } + } while (false); + + /* for phy, we needn't to process any packet, so processed will be 0 */ + if (pdata->expansion.mgm_intctrl_val & MGMT_INT_CTRL0_INT_STATUS_PHY) { + fxgmac_phy_process(pdata); + pdata->expansion.mgm_intctrl_val &= + ~MGMT_INT_CTRL0_INT_STATUS_PHY; + } + + /* If we processed everything, we are done */ + if (processed < budget) { + /* Turn off polling */ + if (napi_complete_done(napi, processed)) + hw_ops->enable_mgm_interrupt(pdata); + } + + if ((processed) && (netif_msg_rx_status(pdata))) { + DPRINTK("rx all_poll callout received = %d\n", processed); + } + + return processed; +} diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-pci.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-pci.c new file mode 100644 index 0000000000000..f6f8f4f6a5e9b --- /dev/null +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-pci.c @@ -0,0 +1,250 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021 Motorcomm Corporation. */ + +#include +#include +#include + +/* for file operation */ +#include + +#include "fuxi-gmac.h" +#include "fuxi-gmac-reg.h" + +#define FXGMAC_DBG 0 + +/* declarations */ +static void fxgmac_shutdown(struct pci_dev *pdev); + +static int fxgmac_probe(struct pci_dev *pcidev, const struct pci_device_id *id) +{ + struct device *dev = &pcidev->dev; + struct fxgmac_resources res; + int i, ret; + + ret = pcim_enable_device(pcidev); + if (ret) { + dev_err(dev, "ERROR: fxgmac_probe failed to enable device\n"); + return ret; + } + + for (i = 0; i <= PCI_STD_RESOURCE_END; i++) { + if (pci_resource_len(pcidev, i) == 0) + continue; + ret = pcim_iomap_regions(pcidev, BIT(i), FXGMAC_DRV_NAME); + if (ret) + goto err_disable_device; + break; + } + + pci_set_master(pcidev); + + memset(&res, 0, sizeof(res)); + res.irq = pcidev->irq; + res.addr = pcim_iomap_table(pcidev)[i]; + + ret = fxgmac_drv_probe(&pcidev->dev, &res); + if (ret) + goto err_disable_device; + + return ret; + +err_disable_device: + pci_disable_device(pcidev); + return ret; +} + +static void fxgmac_remove(struct pci_dev *pcidev) +{ + struct net_device *netdev = dev_get_drvdata(&pcidev->dev); + struct fxgmac_pdata *pdata = netdev_priv(netdev); + +#ifdef CONFIG_PCI_MSI + u32 msix = FXGMAC_GET_REG_BITS(pdata->expansion.int_flags, + FXGMAC_FLAG_MSIX_POS, + FXGMAC_FLAG_MSIX_LEN); +#endif + + fxgmac_drv_remove(&pcidev->dev); +#ifdef CONFIG_PCI_MSI + if (msix) { + pci_disable_msix(pcidev); + kfree(pdata->expansion.msix_entries); + pdata->expansion.msix_entries = NULL; + } +#endif + +#ifdef HAVE_FXGMAC_DEBUG_FS + fxgmac_dbg_exit(pdata); +#endif /* HAVE_FXGMAC_DEBUG_FS */ +} + +/* for Power management, 20210628 */ +static int __fxgmac_shutdown(struct pci_dev *pdev, bool *enable_wake) +{ + struct net_device *netdev = dev_get_drvdata(&pdev->dev); + struct fxgmac_pdata *pdata = netdev_priv(netdev); + u32 wufc = pdata->expansion.wol; +#ifdef CONFIG_PM + int retval = 0; +#endif + + DPRINTK("fxpm,_fxgmac_shutdown, callin\n"); + + rtnl_lock(); + + /* for linux shutdown, we just treat it as power off wol can be ignored + * for suspend, we do need recovery by wol + */ + fxgmac_net_powerdown(pdata, (unsigned int)!!wufc); + netif_device_detach(netdev); + rtnl_unlock(); + +#ifdef CONFIG_PM + retval = pci_save_state(pdev); + if (retval) { + DPRINTK("fxpm,_fxgmac_shutdown, save pci state failed.\n"); + return retval; + } +#endif + + DPRINTK("fxpm,_fxgmac_shutdown, save pci state done.\n"); + + pci_wake_from_d3(pdev, !!wufc); + *enable_wake = !!wufc; + + pci_disable_device(pdev); + + DPRINTK("fxpm,_fxgmac_shutdown callout, enable wake=%d.\n", + *enable_wake); + + return 0; +} + +static void fxgmac_shutdown(struct pci_dev *pdev) +{ + bool wake; + struct net_device *netdev = dev_get_drvdata(&pdev->dev); + struct fxgmac_pdata *pdata = netdev_priv(netdev); + + DPRINTK("fxpm, fxgmac_shutdown callin\n"); + + pdata->expansion.current_state = CURRENT_STATE_SHUTDOWN; + __fxgmac_shutdown(pdev, &wake); + + if (system_state == SYSTEM_POWER_OFF) { + pci_wake_from_d3(pdev, wake); + pci_set_power_state(pdev, PCI_D3hot); + } + DPRINTK("fxpm, fxgmac_shutdown callout, system power off=%d\n", + (system_state == SYSTEM_POWER_OFF) ? 1 : 0); +} + +#ifdef CONFIG_PM +/* yzhang, 20210628 for PM */ +static int fxgmac_suspend(struct pci_dev *pdev, + pm_message_t __always_unused state) +{ + int retval; + bool wake; + struct net_device *netdev = dev_get_drvdata(&pdev->dev); + struct fxgmac_pdata *pdata = netdev_priv(netdev); + + DPRINTK("fxpm, fxgmac_suspend callin\n"); + + pdata->expansion.current_state = CURRENT_STATE_SUSPEND; + + if (netif_running(netdev)) { + retval = __fxgmac_shutdown(pdev, &wake); + if (retval) + return retval; + } else { + wake = !!(pdata->expansion.wol); + } + + if (wake) { + pci_prepare_to_sleep(pdev); + } else { + pci_wake_from_d3(pdev, false); + pci_set_power_state(pdev, PCI_D3hot); + } + + DPRINTK("fxpm, fxgmac_suspend callout to %s\n", + wake ? "sleep" : "D3hot"); + + return 0; +} + +static int fxgmac_resume(struct pci_dev *pdev) +{ + struct fxgmac_pdata *pdata; + struct net_device *netdev; + u32 err; + + DPRINTK("fxpm, fxgmac_resume callin\n"); + + netdev = dev_get_drvdata(&pdev->dev); + pdata = netdev_priv(netdev); + + pdata->expansion.current_state = CURRENT_STATE_RESUME; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + /* + * pci_restore_state clears dev->state_saved so call + * pci_save_state to restore it. + */ + pci_save_state(pdev); + + err = pci_enable_device_mem(pdev); + if (err) { + dev_err(pdata->dev, + "fxgmac_resume, failed to enable PCI device from suspend\n"); + return err; + } + smp_mb__before_atomic(); + __clear_bit(FXGMAC_POWER_STATE_DOWN, &pdata->expansion.powerstate); + pci_set_master(pdev); + + pci_wake_from_d3(pdev, false); + + rtnl_lock(); + err = 0; + if (!err && netif_running(netdev)) + fxgmac_net_powerup(pdata); + + if (!err) + netif_device_attach(netdev); + + rtnl_unlock(); + + DPRINTK("fxpm, fxgmac_resume callout\n"); + + return err; +} +#endif + +static const struct pci_device_id fxgmac_pci_tbl[] = { { PCI_DEVICE(0x1f0a, + 0x6801) }, + { 0 } }; +MODULE_DEVICE_TABLE(pci, fxgmac_pci_tbl); + +static struct pci_driver fxgmac_pci_driver = { + .name = FXGMAC_DRV_NAME, + .id_table = fxgmac_pci_tbl, + .probe = fxgmac_probe, + .remove = fxgmac_remove, +#ifdef CONFIG_PM + /* currently, we only use USE_LEGACY_PM_SUPPORT */ + .suspend = fxgmac_suspend, + .resume = fxgmac_resume, +#endif + .shutdown = fxgmac_shutdown, +}; + +module_pci_driver(fxgmac_pci_driver); + +MODULE_DESCRIPTION(FXGMAC_DRV_DESC); +MODULE_VERSION(FXGMAC_DRV_VERSION); +MODULE_AUTHOR("Frank "); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-phy.c b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-phy.c new file mode 100644 index 0000000000000..88066a110f410 --- /dev/null +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-phy.c @@ -0,0 +1,256 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021 Motorcomm Corporation. */ + +#include +#include + +#include "fuxi-gmac.h" +#include "fuxi-gmac-reg.h" + +void fxgmac_phy_force_speed(struct fxgmac_pdata *pdata, int speed) +{ + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + u32 regval = 0; + unsigned int high_bit = 0, low_bit = 0; + + switch (speed) { + case SPEED_1000: + high_bit = 1, low_bit = 0; + break; + case SPEED_100: + high_bit = 0, low_bit = 1; + break; + case SPEED_10: + high_bit = 0, low_bit = 0; + break; + default: + break; + } + + /* disable autoneg */ + hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, ®val); + regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_AUTOENG_POS, + PHY_CR_AUTOENG_LEN, 0); + regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_SPEED_SEL_H_POS, + PHY_CR_SPEED_SEL_H_LEN, high_bit); + regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_SPEED_SEL_L_POS, + PHY_CR_SPEED_SEL_L_LEN, low_bit); + hw_ops->write_ephy_reg(pdata, REG_MII_BMCR, regval); +} + +void fxgmac_phy_force_duplex(struct fxgmac_pdata *pdata, int duplex) +{ + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + u32 regval = 0; + hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, ®val); + regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_DUPLEX_POS, + PHY_CR_DUPLEX_LEN, (duplex ? 1 : 0)); + hw_ops->write_ephy_reg(pdata, REG_MII_BMCR, regval); +} + +void fxgmac_phy_force_autoneg(struct fxgmac_pdata *pdata, int autoneg) +{ + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + u32 regval = 0; + hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, ®val); + regval = FXGMAC_SET_REG_BITS(regval, PHY_CR_AUTOENG_POS, + PHY_CR_AUTOENG_LEN, (autoneg ? 1 : 0)); + hw_ops->write_ephy_reg(pdata, REG_MII_BMCR, regval); +} + +/* + * input: lport + * output: + * cap_mask, bit definitions: + * pause capbility and 100/10 capbilitys follow the definition of mii reg4. + * for 1000M capability, bit0=1000M half; bit1=1000M full, refer to mii reg9.[9:8]. + */ +int fxgmac_ephy_autoneg_ability_get(struct fxgmac_pdata *pdata, + unsigned int *cap_mask) +{ + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + unsigned int val; + unsigned int reg; + + if ((!hw_ops->read_ephy_reg) || (!hw_ops->write_ephy_reg)) + return -1; + + reg = REG_MII_ADVERTISE; + if (hw_ops->read_ephy_reg(pdata, reg, &val) < 0) + goto busy_exit; + + if (FXGMAC_ADVERTISE_10HALF & val) { + *cap_mask |= FXGMAC_ADVERTISE_10HALF; + } else { + *cap_mask &= ~FXGMAC_ADVERTISE_10HALF; + } + + if (FXGMAC_ADVERTISE_10FULL & val) { + *cap_mask |= FXGMAC_ADVERTISE_10FULL; + } else { + *cap_mask &= ~FXGMAC_ADVERTISE_10FULL; + } + + if (FXGMAC_ADVERTISE_100HALF & val) { + *cap_mask |= FXGMAC_ADVERTISE_100HALF; + } else { + *cap_mask &= ~FXGMAC_ADVERTISE_100HALF; + } + + if (FXGMAC_ADVERTISE_100FULL & val) { + *cap_mask |= FXGMAC_ADVERTISE_100FULL; + } else { + *cap_mask &= ~FXGMAC_ADVERTISE_100FULL; + } + + if (FXGMAC_ADVERTISE_PAUSE_CAP & val) { + *cap_mask |= FXGMAC_ADVERTISE_PAUSE_CAP; + } else { + *cap_mask &= ~FXGMAC_ADVERTISE_PAUSE_CAP; + } + + if (FXGMAC_ADVERTISE_PAUSE_ASYM & val) { + *cap_mask |= FXGMAC_ADVERTISE_PAUSE_ASYM; + } else { + *cap_mask &= ~FXGMAC_ADVERTISE_PAUSE_ASYM; + } + + reg = REG_MII_CTRL1000; + if (hw_ops->read_ephy_reg(pdata, reg, &val) < 0) + goto busy_exit; + + if (REG_BIT_ADVERTISE_1000HALF & val) { + *cap_mask |= FXGMAC_ADVERTISE_1000HALF; + } else { + *cap_mask &= ~FXGMAC_ADVERTISE_1000HALF; + } + + if (REG_BIT_ADVERTISE_1000FULL & val) { + *cap_mask |= FXGMAC_ADVERTISE_1000FULL; + } else { + *cap_mask &= ~FXGMAC_ADVERTISE_1000FULL; + } + + return 0; + +busy_exit: + DPRINTK("fxgmac_ephy_autoneg_ability_get exit due to ephy reg access fail.\n"); + + return -1; +} + +int fxgmac_ephy_soft_reset(struct fxgmac_pdata *pdata) +{ + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + int ret; + volatile unsigned int val; + int busy = 15; + + ret = hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, (unsigned int *)&val); + if (0 > ret) + goto busy_exit; + + ret = hw_ops->write_ephy_reg(pdata, REG_MII_BMCR, (val | 0x8000)); + if (0 > ret) + goto busy_exit; + + do { + ret = hw_ops->read_ephy_reg(pdata, REG_MII_BMCR, + (unsigned int *)&val); + busy--; + } while ((ret >= 0) && (0 != (val & 0x8000)) && (busy)); + + if (0 == (val & 0x8000)) + return 0; + + DPRINTK("fxgmac_ephy_soft_reset, timeout, busy=%d.\n", busy); + return -EBUSY; + +busy_exit: + DPRINTK("fxgmac_ephy_soft_reset exit due to ephy reg access fail.\n"); + + return ret; +} + +/* this function used to double check the speed. for fiber, to correct there is no 10M */ +static int fxgmac_ephy_adjust_status(u32 lport, int val, int is_utp, int *speed, + int *duplex) +{ + int speed_mode; + + *speed = -1; + *duplex = (val & BIT(FUXI_EPHY_DUPLEX_BIT)) >> FUXI_EPHY_DUPLEX_BIT; + speed_mode = (val & FUXI_EPHY_SPEED_MODE) >> FUXI_EPHY_SPEED_MODE_BIT; + switch (speed_mode) { + case 0: + if (is_utp) + *speed = SPEED_10M; + break; + case 1: + *speed = SPEED_100M; + break; + case 2: + *speed = SPEED_1000M; + break; + case 3: + break; + default: + break; + } + + return 0; +} + +/* + * this function for polling to get status of ephy link. + * output: + * speed: SPEED_10M, SPEED_100M, SPEED_1000M or -1; + * duplex: 0 or 1, see reg 0x11, bit YT8614_DUPLEX_BIT. + * ret_link: 0 or 1, link down or up. + * media: only valid when ret_link=1, (YT8614_SMI_SEL_SDS_SGMII + 1) for fiber; (YT8614_SMI_SEL_PHY + 1) for utp. -1 for link down. + */ +int fxgmac_ephy_status_get(struct fxgmac_pdata *pdata, int *speed, int *duplex, + int *ret_link, int *media) +{ + struct fxgmac_hw_ops *hw_ops = &pdata->hw_ops; + int ret; + u16 reg; + volatile unsigned int val; + volatile int link; + int link_utp = 0, link_fiber = 0; + + reg = REG_MII_SPEC_STATUS; + ret = hw_ops->read_ephy_reg(pdata, reg, (unsigned int *)&val); + if (0 > ret) + goto busy_exit; + + link = val & (BIT(FUXI_EPHY_LINK_STATUS_BIT)); + if (link) { + link_utp = 1; + fxgmac_ephy_adjust_status(0, val, 1, speed, duplex); + } else { + link_utp = 0; + } + + if (link_utp || link_fiber) { + /* case of fiber of priority */ + if (link_utp) + *media = (FUXI_EPHY_SMI_SEL_PHY + 1); + if (link_fiber) + *media = (FUXI_EPHY_SMI_SEL_SDS_SGMII + 1); + + *ret_link = 1; + } else { + *ret_link = 0; + *media = -1; + *speed = -1; + *duplex = -1; + } + + return 0; + +busy_exit: + DPRINTK("fxgmac_ephy_status_get exit due to ephy reg access fail.\n"); + + return ret; +} diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-reg.h b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-reg.h new file mode 100644 index 0000000000000..65d6288e6869a --- /dev/null +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac-reg.h @@ -0,0 +1,1894 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021 Motorcomm Corporation. */ + +#ifndef __FUXI_GMAC_REG_H__ +#define __FUXI_GMAC_REG_H__ + +#define AISC_MODE + +#define FUXI_REV_01 0x01 /* The first NTO version. */ +#define FUXI_REV_03 0x03 /* ECO back on 07/2023. */ + +/* MAC register offsets */ +#define MAC_OFFSET 0x2000 +#define MAC_CR 0x0000 /* The MAC Configuration Register */ +#define MAC_ECR 0x0004 +#define MAC_PFR 0x0008 +#define MAC_HTR0 0x0010 +#define MAC_VLANTR 0x0050 +#define MAC_VLANHTR 0x0058 +#define MAC_VLANIR 0x0060 +#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_TX_RX_STA 0x00b8 +#define MAC_PMT_STA 0x00c0 +/* This is the FIFO address, the pointer will be increased + * automatically after writting. + */ +#define MAC_RWK_PAC 0x00c4 +#define MAC_LPI_STA 0x00d0 +#define MAC_LPI_CONTROL 0x00d4 +#define MAC_LPI_TIMER 0x00d8 +#define MAC_MS_TIC_COUNTER 0x00dc +#define MAC_AN_SR 0x00E4 +#define MAC_PHYIF_STA 0x00F8 +#define MAC_VR 0x0110 +#define MAC_DBG_STA 0x0114 +#define MAC_HWF0R 0x011c +#define MAC_HWF1R 0x0120 +#define MAC_HWF2R 0x0124 +#define MAC_HWF3R 0x0128 +#define MAC_MDIO_ADDRESS 0x0200 +#define MAC_MDIO_DATA 0x0204 +#define MAC_GPIO_SR 0x020c +#define MAC_ARP_PROTO_ADDR 0x0210 +#define MAC_CSR_SW_CTRL 0x0230 + +/* mac[5]->bit15:8, mac[4]->bit7:0 */ +#define MAC_MACA0HR 0x0300 +/* mac[0]->bit7:0, mac[1]->bit15:8, mac[2]->bit23:16, mac[3]->bit31:24 */ +#define MAC_MACA0LR 0x0304 + +#define MAC_MACA1HR 0x0308 +#define MAC_MACA1HR_AE_POS 31 +#define MAC_MACA1HR_AE_LEN 1 + +#define MAC_MACA1LR 0x030c + + +#define MAC_RSSCR 0x3c80 +#define MAC_RSSAR 0x3c88 +#define MAC_RSSDR 0x3c8c + + + +#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_POS 18 +#define MAC_HWF0R_ADDMACADRSEL_LEN 5 +#define MAC_HWF0R_ARPOFFSEL_POS 9 +#define MAC_HWF0R_ARPOFFSEL_LEN 1 +#define MAC_HWF0R_EEESEL_POS 13 +#define MAC_HWF0R_EEESEL_LEN 1 +#define MAC_HWF0R_ACTPHYIFSEL_POS 28 +#define MAC_HWF0R_ACTPHYIFSEL_LEN 3 +#define MAC_HWF0R_MGKSEL_POS 7 +#define MAC_HWF0R_MGKSEL_LEN 1 +#define MAC_HWF0R_MMCSEL_POS 8 +#define MAC_HWF0R_MMCSEL_LEN 1 +#define MAC_HWF0R_RWKSEL_POS 6 +#define MAC_HWF0R_RWKSEL_LEN 1 +#define MAC_HWF0R_RXCOESEL_POS 16 +#define MAC_HWF0R_RXCOESEL_LEN 1 +#define MAC_HWF0R_SAVLANINS_POS 27 +#define MAC_HWF0R_SAVLANINS_LEN 1 +#define MAC_HWF0R_SMASEL_POS 5 +#define MAC_HWF0R_SMASEL_LEN 1 +#define MAC_HWF0R_TSSEL_POS 12 +#define MAC_HWF0R_TSSEL_LEN 1 +#define MAC_HWF0R_TSSTSSEL_POS 25 +#define MAC_HWF0R_TSSTSSEL_LEN 2 +#define MAC_HWF0R_TXCOESEL_POS 14 +#define MAC_HWF0R_TXCOESEL_LEN 1 +#define MAC_HWF0R_VLHASH_POS 4 +#define MAC_HWF0R_VLHASH_LEN 1 +#define MAC_HWF1R_ADDR64_POS 14 +#define MAC_HWF1R_ADDR64_LEN 2 +#define MAC_HWF1R_ADVTHWORD_POS 13 +#define MAC_HWF1R_ADVTHWORD_LEN 1 +#define MAC_HWF1R_DBGMEMA_POS 19 +#define MAC_HWF1R_DBGMEMA_LEN 1 +#define MAC_HWF1R_DCBEN_POS 16 +#define MAC_HWF1R_DCBEN_LEN 1 +#define MAC_HWF1R_HASHTBLSZ_POS 24 +#define MAC_HWF1R_HASHTBLSZ_LEN 2 +#define MAC_HWF1R_L3L4FNUM_POS 27 +#define MAC_HWF1R_L3L4FNUM_LEN 4 +#define MAC_HWF1R_RAVSEL_POS 21 +#define MAC_HWF1R_RAVSEL_LEN 1 +#define MAC_HWF1R_AVSEL_POS 20 +#define MAC_HWF1R_AVSEL_LEN 1 +#define MAC_HWF1R_RXFIFOSIZE_POS 0 +#define MAC_HWF1R_RXFIFOSIZE_LEN 5 +#define MAC_HWF1R_SPHEN_POS 17 +#define MAC_HWF1R_SPHEN_LEN 1 +#define MAC_HWF1R_TSOEN_POS 18 +#define MAC_HWF1R_TSOEN_LEN 1 +#define MAC_HWF1R_TXFIFOSIZE_POS 6 +#define MAC_HWF1R_TXFIFOSIZE_LEN 5 +#define MAC_HWF2R_AUXSNAPNUM_POS 28 +#define MAC_HWF2R_AUXSNAPNUM_LEN 3 +#define MAC_HWF2R_PPSOUTNUM_POS 24 +#define MAC_HWF2R_PPSOUTNUM_LEN 3 +#define MAC_HWF2R_RXCHCNT_POS 12 +#define MAC_HWF2R_RXCHCNT_LEN 4 +#define MAC_HWF2R_RXQCNT_POS 0 +#define MAC_HWF2R_RXQCNT_LEN 4 +#define MAC_HWF2R_TXCHCNT_POS 18 +#define MAC_HWF2R_TXCHCNT_LEN 4 +#define MAC_HWF2R_TXQCNT_POS 6 +#define MAC_HWF2R_TXQCNT_LEN 4 +#define MAC_IER_TSIE_POS 12 +#define MAC_IER_TSIE_LEN 1 +#define MAC_ISR_MMCRXIS_POS 9 +#define MAC_ISR_MMCRXIS_LEN 1 +#define MAC_ISR_MMCTXIS_POS 10 +#define MAC_ISR_MMCTXIS_LEN 1 +#define MAC_ISR_PMTIS_POS 4 +#define MAC_ISR_PMTIS_LEN 1 +#define MAC_ISR_TSIS_POS 12 +#define MAC_ISR_TSIS_LEN 1 +#define MAC_MACA1HR_AE_POS 31 +#define MAC_MACA1HR_AE_LEN 1 +#define MAC_PFR_HMC_POS 2 +#define MAC_PFR_HMC_LEN 1 +#define MAC_PFR_HPF_POS 10 +#define MAC_PFR_HPF_LEN 1 +#define MAC_PFR_PM_POS 4 /* Pass all Multicast. */ +#define MAC_PFR_PM_LEN 1 +#define MAC_PFR_DBF_POS 5 /* Disable Broadcast Packets. */ +#define MAC_PFR_DBF_LEN 1 +/* Hash Unicast. 0x0 (DISABLE). compares the DA field with + * the values programmed in DA registers. + */ +#define MAC_PFR_HUC_POS 1 +#define MAC_PFR_HUC_LEN 1 +#define MAC_PFR_PR_POS 0 /* Enable Promiscuous Mode. */ +#define MAC_PFR_PR_LEN 1 +#define MAC_PFR_VTFE_POS 16 +#define MAC_PFR_VTFE_LEN 1 +#define MAC_Q0TFCR_PT_POS 16 +#define MAC_Q0TFCR_PT_LEN 16 +#define MAC_Q0TFCR_TFE_POS 1 +#define MAC_Q0TFCR_TFE_LEN 1 +#define MAC_CR_ARPEN_POS 31 +#define MAC_CR_ARPEN_LEN 1 +#define MAC_CR_ACS_POS 20 +#define MAC_CR_ACS_LEN 1 +#define MAC_CR_CST_POS 21 +#define MAC_CR_CST_LEN 1 +#define MAC_CR_IPC_POS 27 +#define MAC_CR_IPC_LEN 1 +#define MAC_CR_JE_POS 16 +#define MAC_CR_JE_LEN 1 +#define MAC_CR_LM_POS 12 +#define MAC_CR_LM_LEN 1 +#define MAC_CR_RE_POS 0 +#define MAC_CR_RE_LEN 1 +#define MAC_CR_PS_POS 15 +#define MAC_CR_PS_LEN 1 +#define MAC_CR_FES_POS 14 +#define MAC_CR_FES_LEN 1 +#define MAC_CR_DM_POS 13 +#define MAC_CR_DM_LEN 1 +#define MAC_CR_TE_POS 1 +#define MAC_CR_TE_LEN 1 +#define MAC_ECR_DCRCC_POS 16 +#define MAC_ECR_DCRCC_LEN 1 +#define MAC_ECR_HDSMS_POS 20 +#define MAC_ECR_HDSMS_LEN 3 +#define MAC_RFCR_PFCE_POS 8 +#define MAC_RFCR_PFCE_LEN 1 +#define MAC_RFCR_RFE_POS 0 +#define MAC_RFCR_RFE_LEN 1 +#define MAC_RFCR_UP_POS 1 +#define MAC_RFCR_UP_LEN 1 +#define MAC_RQC0R_RXQ0EN_POS 0 +#define MAC_RQC0R_RXQ0EN_LEN 2 +#define MAC_LPIIE_POS 5 +#define MAC_LPIIE_LEN 1 +#define MAC_LPIATE_POS 20 +#define MAC_LPIATE_LEN 1 +#define MAC_LPITXA_POS 19 +#define MAC_LPITXA_LEN 1 +#define MAC_PLS_POS 17 +#define MAC_PLS_LEN 1 +#define MAC_LPIEN_POS 16 +#define MAC_LPIEN_LEN 1 +#define MAC_LPI_ENTRY_TIMER 8 +#define MAC_LPIET_POS 3 +#define MAC_LPIET_LEN 17 +#define MAC_TWT_TIMER 0x10 +#define MAC_TWT_POS 0 +#define MAC_TWT_LEN 16 +#define MAC_LST_TIMER 2 +#define MAC_LST_POS 16 +#define MAC_LST_LEN 10 +#define MAC_MS_TIC 24 +#define MAC_MS_TIC_POS 0 +#define MAC_MS_TIC_LEN 12 + +/* RSS table */ +#define MAC_RSSAR_ADDRT_POS 2 +#define MAC_RSSAR_ADDRT_LEN 1 +#define MAC_RSSAR_CT_POS 1 +#define MAC_RSSAR_CT_LEN 1 +#define MAC_RSSAR_OB_POS 0 +#define MAC_RSSAR_OB_LEN 1 +#define MAC_RSSAR_RSSIA_POS 8 +#define MAC_RSSAR_RSSIA_LEN 8 +/* RSS control and options */ +/* note, below options definitions are used only for pdata->options, + * not for register, so the position is not consistent with register. + * [0] ipv4 + * [1] tcpv4 + * [2] udpv4 + * [3] ipv6 + * [4] tcpv6 + * [5] udpv6 + */ +#define MAC_RSSCR_IP4TE_POS 0 +#define MAC_RSSCR_IP4TE_LEN 1 +#define MAC_RSSCR_IP6TE_POS 3 +#define MAC_RSSCR_IP6TE_LEN 1 +#define MAC_RSSCR_TCP4TE_POS 1 +#define MAC_RSSCR_TCP4TE_LEN 1 +#define MAC_RSSCR_UDP4TE_POS 2 +#define MAC_RSSCR_UDP4TE_LEN 1 +#define MAC_RSSCR_TCP6TE_POS 4 +#define MAC_RSSCR_TCP6TE_LEN 1 +#define MAC_RSSCR_UDP6TE_POS 5 +#define MAC_RSSCR_UDP6TE_LEN 1 + +/* RSS indirection table */ +#define MAC_RSSDR_DMCH_POS 0 +#define MAC_RSSDR_DMCH_LEN 2 + +#define MAC_VLANHTR_VLHT_POS 0 +#define MAC_VLANHTR_VLHT_LEN 16 +#define MAC_VLANIR_VLTI_POS 20 +#define MAC_VLANIR_VLTI_LEN 1 +#define MAC_VLANIR_CSVL_POS 19 +#define MAC_VLANIR_CSVL_LEN 1 +#define MAC_VLANIR_VLP_POS 18 +#define MAC_VLANIR_VLP_LEN 1 +#define MAC_VLANIR_VLC_POS 16 +#define MAC_VLANIR_VLC_LEN 2 +#define MAC_VLANIR_VLT_POS 0 +#define MAC_VLANIR_VLT_LEN 16 +#define MAC_VLANTR_DOVLTC_POS 20 +#define MAC_VLANTR_DOVLTC_LEN 1 +#define MAC_VLANTR_ERSVLM_POS 19 +#define MAC_VLANTR_ERSVLM_LEN 1 +#define MAC_VLANTR_ESVL_POS 18 +#define MAC_VLANTR_ESVL_LEN 1 +#define MAC_VLANTR_ETV_POS 16 +#define MAC_VLANTR_ETV_LEN 1 +#define MAC_VLANTR_EVLS_POS 21 +#define MAC_VLANTR_EVLS_LEN 2 +#define MAC_VLANTR_EVLRXS_POS 24 +#define MAC_VLANTR_EVLRXS_LEN 1 +#define MAC_VLANTR_VL_POS 0 +#define MAC_VLANTR_VL_LEN 16 +#define MAC_VLANTR_VTHM_POS 25 +#define MAC_VLANTR_VTHM_LEN 1 +#define MAC_VLANTR_VTIM_POS 17 +#define MAC_VLANTR_VTIM_LEN 1 +#define MAC_VR_DEVID_POS 16 +#define MAC_VR_DEVID_LEN 16 +#define MAC_VR_SVER_POS 0 +#define MAC_VR_SVER_LEN 8 +#define MAC_VR_USERVER_POS 8 +#define MAC_VR_USERVER_LEN 8 + +#define MAC_DBG_STA_TX_BUSY 0x70000 +#define MTL_TXQ_DEG_TX_BUSY 0x10 + +#define MAC_MDIO_ADDRESS_BUSY 1 /* bit 0 */ + +#define MAC_MDIO_ADDR_GOC_POS 2 +#define MAC_MDIO_ADDR_GOC_LEN 2 +#define MAC_MDIO_ADDR_GB_POS 0 +#define MAC_MDIO_ADDR_GB_LEN 1 + +#define MAC_MDIO_DATA_RA_POS 16 +#define MAC_MDIO_DATA_RA_LEN 16 +#define MAC_MDIO_DATA_GD_POS 0 +#define MAC_MDIO_DATA_GD_LEN 16 + +/* bit definitions for PMT and WOL, 20210622 */ +#define MAC_PMT_STA_PWRDWN_POS 0 +#define MAC_PMT_STA_PWRDWN_LEN 1 +#define MAC_PMT_STA_MGKPKTEN_POS 1 +#define MAC_PMT_STA_MGKPKTEN_LEN 1 +#define MAC_PMT_STA_RWKPKTEN_POS 2 +#define MAC_PMT_STA_RWKPKTEN_LEN 1 +#define MAC_PMT_STA_MGKPRCVD_POS 5 +#define MAC_PMT_STA_MGKPRCVD_LEN 1 +#define MAC_PMT_STA_RWKPRCVD_POS 6 +#define MAC_PMT_STA_RWKPRCVD_LEN 1 +#define MAC_PMT_STA_GLBLUCAST_POS 9 +#define MAC_PMT_STA_GLBLUCAST_LEN 1 +#define MAC_PMT_STA_RWKPTR_POS 24 +#define MAC_PMT_STA_RWKPTR_LEN 4 +#define MAC_PMT_STA_RWKFILTERST_POS 31 +#define MAC_PMT_STA_RWKFILTERST_LEN 1 +/* MMC register offsets */ +#define MMC_CR 0x0700 +#define MMC_RISR 0x0704 +#define MMC_TISR 0x0708 +#define MMC_RIER 0x070c +#define MMC_TIER 0x0710 +#define MMC_TXOCTETCOUNT_GB_LO 0x0714 +#define MMC_TXFRAMECOUNT_GB_LO 0x0718 +#define MMC_TXBROADCASTFRAMES_G_LO 0x071c +#define MMC_TXMULTICASTFRAMES_G_LO 0x0720 +#define MMC_TX64OCTETS_GB_LO 0x0724 +#define MMC_TX65TO127OCTETS_GB_LO 0x0728 +#define MMC_TX128TO255OCTETS_GB_LO 0x072c +#define MMC_TX256TO511OCTETS_GB_LO 0x0730 +#define MMC_TX512TO1023OCTETS_GB_LO 0x0734 +#define MMC_TX1024TOMAXOCTETS_GB_LO 0x0738 +#define MMC_TXUNICASTFRAMES_GB_LO 0x073c +#define MMC_TXMULTICASTFRAMES_GB_LO 0x0740 +#define MMC_TXBROADCASTFRAMES_GB_LO 0x0744 +#define MMC_TXUNDERFLOWERROR_LO 0x0748 +#define MMC_TXSINGLECOLLISION_G 0x074c +#define MMC_TXMULTIPLECOLLISION_G 0x0750 +#define MMC_TXDEFERREDFRAMES 0x0754 +#define MMC_TXLATECOLLISIONFRAMES 0x0758 +#define MMC_TXEXCESSIVECOLLSIONFRAMES 0x075c +#define MMC_TXCARRIERERRORFRAMES 0x0760 +#define MMC_TXOCTETCOUNT_G_LO 0x0764 +#define MMC_TXFRAMECOUNT_G_LO 0x0768 +#define MMC_TXEXCESSIVEDEFERRALERROR 0x076c +#define MMC_TXPAUSEFRAMES_LO 0x0770 +#define MMC_TXVLANFRAMES_G_LO 0x0774 +#define MMC_TXOVERSIZEFRAMES 0x0778 +#define MMC_RXFRAMECOUNT_GB_LO 0x0780 +#define MMC_RXOCTETCOUNT_GB_LO 0x0784 +#define MMC_RXOCTETCOUNT_G_LO 0x0788 +#define MMC_RXBROADCASTFRAMES_G_LO 0x078c +#define MMC_RXMULTICASTFRAMES_G_LO 0x0790 +#define MMC_RXCRCERROR_LO 0x0794 +#define MMC_RXALIGNERROR 0x0798 +#define MMC_RXRUNTERROR 0x079c +#define MMC_RXJABBERERROR 0x07a0 +#define MMC_RXUNDERSIZE_G 0x07a4 +#define MMC_RXOVERSIZE_G 0x07a8 +#define MMC_RX64OCTETS_GB_LO 0x07ac +#define MMC_RX65TO127OCTETS_GB_LO 0x07b0 +#define MMC_RX128TO255OCTETS_GB_LO 0x07b4 +#define MMC_RX256TO511OCTETS_GB_LO 0x07b8 +#define MMC_RX512TO1023OCTETS_GB_LO 0x07bc +#define MMC_RX1024TOMAXOCTETS_GB_LO 0x07c0 +#define MMC_RXUNICASTFRAMES_G_LO 0x07c4 +#define MMC_RXLENGTHERROR_LO 0x07c8 +#define MMC_RXOUTOFRANGETYPE_LO 0x07cc +#define MMC_RXPAUSEFRAMES_LO 0x07d0 +#define MMC_RXFIFOOVERFLOW_LO 0x07d4 +#define MMC_RXVLANFRAMES_GB_LO 0x07d8 +#define MMC_RXWATCHDOGERROR 0x07dc +#define MMC_RXRECEIVEERRORFRAME 0x07e0 +#define MMC_RXCONTROLFRAME_G 0x07e4 + +#define MMC_IPCRXINTMASK 0x800 +#define MMC_IPCRXINT 0x808 + +/* MMC register entry bit positions and sizes */ +#define MMC_CR_CR_POS 0 +#define MMC_CR_CR_LEN 1 +#define MMC_CR_CSR_POS 1 +#define MMC_CR_CSR_LEN 1 +#define MMC_CR_ROR_POS 2 +#define MMC_CR_ROR_LEN 1 +#define MMC_CR_MCF_POS 3 +#define MMC_CR_MCF_LEN 1 +#define MMC_RIER_ALL_INTERRUPTS_POS 0 +#define MMC_RIER_ALL_INTERRUPTS_LEN 26 +#define MMC_RISR_RXFRAMECOUNT_GB_POS 0 +#define MMC_RISR_RXFRAMECOUNT_GB_LEN 1 +#define MMC_RISR_RXOCTETCOUNT_GB_POS 1 +#define MMC_RISR_RXOCTETCOUNT_GB_LEN 1 +#define MMC_RISR_RXOCTETCOUNT_G_POS 2 +#define MMC_RISR_RXOCTETCOUNT_G_LEN 1 +#define MMC_RISR_RXBROADCASTFRAMES_G_POS 3 +#define MMC_RISR_RXBROADCASTFRAMES_G_LEN 1 +#define MMC_RISR_RXMULTICASTFRAMES_G_POS 4 +#define MMC_RISR_RXMULTICASTFRAMES_G_LEN 1 +#define MMC_RISR_RXCRCERROR_POS 5 +#define MMC_RISR_RXCRCERROR_LEN 1 +#define MMC_RISR_RXALIGNERROR_POS 6 +#define MMC_RISR_RXALIGNERROR_LEN 1 +#define MMC_RISR_RXRUNTERROR_POS 7 +#define MMC_RISR_RXRUNTERROR_LEN 1 +#define MMC_RISR_RXJABBERERROR_POS 8 +#define MMC_RISR_RXJABBERERROR_LEN 1 +#define MMC_RISR_RXUNDERSIZE_G_POS 9 +#define MMC_RISR_RXUNDERSIZE_G_LEN 1 +#define MMC_RISR_RXOVERSIZE_G_POS 10 +#define MMC_RISR_RXOVERSIZE_G_LEN 1 +#define MMC_RISR_RX64OCTETS_GB_POS 11 +#define MMC_RISR_RX64OCTETS_GB_LEN 1 +#define MMC_RISR_RX65TO127OCTETS_GB_POS 12 +#define MMC_RISR_RX65TO127OCTETS_GB_LEN 1 +#define MMC_RISR_RX128TO255OCTETS_GB_POS 13 +#define MMC_RISR_RX128TO255OCTETS_GB_LEN 1 +#define MMC_RISR_RX256TO511OCTETS_GB_POS 14 +#define MMC_RISR_RX256TO511OCTETS_GB_LEN 1 +#define MMC_RISR_RX512TO1023OCTETS_GB_POS 15 +#define MMC_RISR_RX512TO1023OCTETS_GB_LEN 1 +#define MMC_RISR_RX1024TOMAXOCTETS_GB_POS 16 +#define MMC_RISR_RX1024TOMAXOCTETS_GB_LEN 1 +#define MMC_RISR_RXUNICASTFRAMES_G_POS 17 +#define MMC_RISR_RXUNICASTFRAMES_G_LEN 1 +#define MMC_RISR_RXLENGTHERROR_POS 18 +#define MMC_RISR_RXLENGTHERROR_LEN 1 +#define MMC_RISR_RXOUTOFRANGETYPE_POS 19 +#define MMC_RISR_RXOUTOFRANGETYPE_LEN 1 +#define MMC_RISR_RXPAUSEFRAMES_POS 20 +#define MMC_RISR_RXPAUSEFRAMES_LEN 1 +#define MMC_RISR_RXFIFOOVERFLOW_POS 21 +#define MMC_RISR_RXFIFOOVERFLOW_LEN 1 +#define MMC_RISR_RXVLANFRAMES_GB_POS 22 +#define MMC_RISR_RXVLANFRAMES_GB_LEN 1 +#define MMC_RISR_RXWATCHDOGERROR_POS 23 +#define MMC_RISR_RXWATCHDOGERROR_LEN 1 +#define MMC_RISR_RXERRORFRAMES_POS 24 +#define MMC_RISR_RXERRORFRAMES_LEN 1 +#define MMC_RISR_RXERRORCONTROLFRAMES_POS 25 +#define MMC_RISR_RXERRORCONTROLFRAMES_LEN 1 +#define MMC_RISR_RXLPIMICROSECOND_POS 26 /* no counter register */ +#define MMC_RISR_RXLPIMICROSECOND_LEN 1 +#define MMC_RISR_RXLPITRANSITION_POS 27 /* no counter register */ +#define MMC_RISR_RXLPITRANSITION_LEN 1 + +#define MMC_TIER_ALL_INTERRUPTS_POS 0 +#define MMC_TIER_ALL_INTERRUPTS_LEN 26 +#define MMC_TISR_TXOCTETCOUNT_GB_POS 0 +#define MMC_TISR_TXOCTETCOUNT_GB_LEN 1 +#define MMC_TISR_TXFRAMECOUNT_GB_POS 1 +#define MMC_TISR_TXFRAMECOUNT_GB_LEN 1 +#define MMC_TISR_TXBROADCASTFRAMES_G_POS 2 +#define MMC_TISR_TXBROADCASTFRAMES_G_LEN 1 +#define MMC_TISR_TXMULTICASTFRAMES_G_POS 3 +#define MMC_TISR_TXMULTICASTFRAMES_G_LEN 1 +#define MMC_TISR_TX64OCTETS_GB_POS 4 +#define MMC_TISR_TX64OCTETS_GB_LEN 1 +#define MMC_TISR_TX65TO127OCTETS_GB_POS 5 +#define MMC_TISR_TX65TO127OCTETS_GB_LEN 1 +#define MMC_TISR_TX128TO255OCTETS_GB_POS 6 +#define MMC_TISR_TX128TO255OCTETS_GB_LEN 1 +#define MMC_TISR_TX256TO511OCTETS_GB_POS 7 +#define MMC_TISR_TX256TO511OCTETS_GB_LEN 1 +#define MMC_TISR_TX512TO1023OCTETS_GB_POS 8 +#define MMC_TISR_TX512TO1023OCTETS_GB_LEN 1 +#define MMC_TISR_TX1024TOMAXOCTETS_GB_POS 9 +#define MMC_TISR_TX1024TOMAXOCTETS_GB_LEN 1 +#define MMC_TISR_TXUNICASTFRAMES_GB_POS 10 +#define MMC_TISR_TXUNICASTFRAMES_GB_LEN 1 +#define MMC_TISR_TXMULTICASTFRAMES_GB_POS 11 +#define MMC_TISR_TXMULTICASTFRAMES_GB_LEN 1 +#define MMC_TISR_TXBROADCASTFRAMES_GB_POS 12 +#define MMC_TISR_TXBROADCASTFRAMES_GB_LEN 1 +#define MMC_TISR_TXUNDERFLOWERROR_POS 13 +#define MMC_TISR_TXUNDERFLOWERROR_LEN 1 +#define MMC_TISR_TXSINGLECOLLISION_G_POS 14 +#define MMC_TISR_TXSINGLECOLLISION_G_LEN 1 +#define MMC_TISR_TXMULTIPLECOLLISION_G_POS 15 +#define MMC_TISR_TXMULTIPLECOLLISION_G_LEN 1 +#define MMC_TISR_TXDEFERREDFRAMES_POS 16 +#define MMC_TISR_TXDEFERREDFRAMES_LEN 1 +#define MMC_TISR_TXLATECOLLISIONFRAMES_POS 17 +#define MMC_TISR_TXLATECOLLISIONFRAMES_LEN 1 +#define MMC_TISR_TXEXCESSIVECOLLISIONFRAMES_POS 18 +#define MMC_TISR_TXEXCESSIVECOLLISIONFRAMES_LEN 1 +#define MMC_TISR_TXCARRIERERRORFRAMES_POS 19 +#define MMC_TISR_TXCARRIERERRORFRAMES_LEN 1 +#define MMC_TISR_TXOCTETCOUNT_G_POS 20 +#define MMC_TISR_TXOCTETCOUNT_G_LEN 1 +#define MMC_TISR_TXFRAMECOUNT_G_POS 21 +#define MMC_TISR_TXFRAMECOUNT_G_LEN 1 +#define MMC_TISR_TXEXCESSIVEDEFERRALFRAMES_POS 22 +#define MMC_TISR_TXEXCESSIVEDEFERRALFRAMES_LEN 1 +#define MMC_TISR_TXPAUSEFRAMES_POS 23 +#define MMC_TISR_TXPAUSEFRAMES_LEN 1 +#define MMC_TISR_TXVLANFRAMES_G_POS 24 +#define MMC_TISR_TXVLANFRAMES_G_LEN 1 +#define MMC_TISR_TXOVERSIZE_G_POS 25 +#define MMC_TISR_TXOVERSIZE_G_LEN 1 +#define MMC_TISR_TXLPIMICROSECOND_POS 26 /* no counter register */ +#define MMC_TISR_TXLPIMICROSECOND_LEN 1 +#define MMC_TISR_TXLPITRANSITION_POS 27 /* no counter register */ +#define MMC_TISR_TXLPITRANSITION_LEN 1 + +/* MTL register offsets */ +#define MTL_OMR 0x0c00 +#define MTL_FDDR 0x0c10 +#define MTL_INT_SR 0x0c20 +#define MTL_RQDCM0R 0x0c30 +#define MTL_ECC_INT_SR 0x0ccc + +#define MTL_RQDCM_INC 4 +#define MTL_RQDCM_Q_PER_REG 4 + +/* MTL register entry bit positions and sizes */ +#define MTL_OMR_ETSALG_POS 5 +#define MTL_OMR_ETSALG_LEN 2 +#define MTL_OMR_RAA_POS 2 +#define MTL_OMR_RAA_LEN 1 + +/* MTL queue register offsets + * Multiple queues can be active. The first queue has registers + * that begin at 0x0d00. Each subsequent queue has registers that + * are accessed using an offset of 0x40 from the previous queue. + */ +#define MTL_Q_BASE 0x0d00 +#define MTL_Q_INC 0x40 +#define MTL_Q_INT_CTL_SR 0x0d2c + +#define MTL_Q_TQOMR 0x00 +#define MTL_Q_RQOMR 0x30 +#define MTL_Q_RQDR 0x38 +#define MTL_Q_IER 0x2c +#define MTL_Q_ISR 0x2c /* no isr register */ +#define MTL_TXQ_DEG 0x08 /* transmit debug */ + +/* MTL queue register entry bit positions and sizes */ +#define MTL_Q_RQDR_PRXQ_POS 16 +#define MTL_Q_RQDR_PRXQ_LEN 14 +#define MTL_Q_RQDR_RXQSTS_POS 4 +#define MTL_Q_RQDR_RXQSTS_LEN 2 +#define MTL_Q_RQOMR_RFA_POS 8 +#define MTL_Q_RQOMR_RFA_LEN 6 +#define MTL_Q_RQOMR_RFD_POS 14 +#define MTL_Q_RQOMR_RFD_LEN 6 +#define MTL_Q_RQOMR_EHFC_POS 7 +#define MTL_Q_RQOMR_EHFC_LEN 1 +#define MTL_Q_RQOMR_RQS_POS 20 +#define MTL_Q_RQOMR_RQS_LEN 9 +#define MTL_Q_RQOMR_RSF_POS 5 +#define MTL_Q_RQOMR_RSF_LEN 1 +#define MTL_Q_RQOMR_FEP_POS 4 +#define MTL_Q_RQOMR_FEP_LEN 1 +#define MTL_Q_RQOMR_FUP_POS 3 +#define MTL_Q_RQOMR_FUP_LEN 1 +#define MTL_Q_RQOMR_RTC_POS 0 +#define MTL_Q_RQOMR_RTC_LEN 2 +#define MTL_Q_TQOMR_FTQ_POS 0 +#define MTL_Q_TQOMR_FTQ_LEN 1 +#define MTL_Q_TQOMR_TQS_POS 16 +#define MTL_Q_TQOMR_TQS_LEN 7 +#define MTL_Q_TQOMR_TSF_POS 1 +#define MTL_Q_TQOMR_TSF_LEN 1 +#define MTL_Q_TQOMR_TTC_POS 4 +#define MTL_Q_TQOMR_TTC_LEN 3 +#define MTL_Q_TQOMR_TXQEN_POS 2 +#define MTL_Q_TQOMR_TXQEN_LEN 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_FEP_DISABLE 0x00 +#define MTL_FEP_ENABLE 0x01 + +#define MTL_RX_THRESHOLD_64 0x00 +#define MTL_RX_THRESHOLD_32 0x01 +#define MTL_RX_THRESHOLD_96 0x02 +#define MTL_RX_THRESHOLD_128 0x03 +#define MTL_TX_THRESHOLD_32 0x00 +#define MTL_TX_THRESHOLD_64 0x01 +#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_ETSALG_SP 0x03 + +#define MTL_RAA_SP 0x00 +#define MTL_RAA_WSP 0x01 + +#define MTL_Q_DISABLED 0x00 +#define MTL_Q_EN_IF_AV 0x01 +#define MTL_Q_ENABLED 0x02 + +#define MTL_RQDCM0R_Q0MDMACH 0x0 +#define MTL_RQDCM0R_Q1MDMACH 0x00000100 +#define MTL_RQDCM0R_Q2MDMACH 0x00020000 +#define MTL_RQDCM0R_Q3MDMACH 0x03000000 +#define MTL_RQDCM1R_Q4MDMACH 0x00000004 +#define MTL_RQDCM1R_Q5MDMACH 0x00000500 +#define MTL_RQDCM1R_Q6MDMACH 0x00060000 +#define MTL_RQDCM1R_Q7MDMACH 0x07000000 +#define MTL_RQDCM2R_Q8MDMACH 0x00000008 +#define MTL_RQDCM2R_Q9MDMACH 0x00000900 +#define MTL_RQDCM2R_Q10MDMACH 0x000A0000 +#define MTL_RQDCM2R_Q11MDMACH 0x0B000000 + +#define MTL_RQDCM0R_Q0DDMACH 0x10 +#define MTL_RQDCM0R_Q1DDMACH 0x00001000 +#define MTL_RQDCM0R_Q2DDMACH 0x00100000 +#define MTL_RQDCM0R_Q3DDMACH 0x10000000 +#define MTL_RQDCM1R_Q4DDMACH 0x00000010 +#define MTL_RQDCM1R_Q5DDMACH 0x00001000 +#define MTL_RQDCM1R_Q6DDMACH 0x00100000 +#define MTL_RQDCM1R_Q7DDMACH 0x10000000 + + +/* 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. + */ +/* NO TRAFFIC CLASS REGISTER DESCRIPTION */ +#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_POS 0 +#define MTL_TC_ETSCR_TSA_LEN 2 +#define MTL_TC_QWR_QW_POS 0 +#define MTL_TC_QWR_QW_LEN 21 + +/* MTL traffic class register value */ +#define MTL_TSA_SP 0x00 +#define MTL_TSA_ETS 0x02 + +/* DMA register offsets */ +#define DMA_MR 0x1000 +#define DMA_SBMR 0x1004 +#define DMA_ISR 0x1008 +#define DMA_DSR0 0x100c +#define DMA_DSR1 0x1010 +#define DMA_DSR2 0x1014 +#define DMA_ECC_INT_SR 0x1088 + +/* DMA register entry bit positions and sizes */ +#define DMA_ISR_MACIS_POS 17 +#define DMA_ISR_MACIS_LEN 1 +#define DMA_ISR_MTLIS_POS 16 +#define DMA_ISR_MTLIS_LEN 1 +#define DMA_MR_SWR_POS 0 +#define DMA_MR_SWR_LEN 1 +#define DMA_MR_INTM_POS 16 +#define DMA_MR_INTM_LEN 2 +#define DMA_MR_QUREAD_POS 19 +#define DMA_MR_QUREAD_LEN 1 + +#define DMA_SBMR_EN_LPI_POS 31 +#define DMA_SBMR_EN_LPI_LEN 1 +#define DMA_SBMR_LPI_XIT_PKT_POS 30 +#define DMA_SBMR_LPI_XIT_PKT_LEN 1 +#define DMA_SBMR_WR_OSR_LMT_POS 24 +#define DMA_SBMR_WR_OSR_LMT_LEN 6 +#define DMA_SBMR_RD_OSR_LMT_POS 16 +#define DMA_SBMR_RD_OSR_LMT_LEN 8 +#define DMA_SBMR_EAME_POS 11 +#define DMA_SBMR_EAME_LEN 1 +#define DMA_SBMR_AALE_POS 10 +#define DMA_SBMR_AALE_LEN 1 +#define DMA_SBMR_BLEN_4_POS 1 +#define DMA_SBMR_BLEN_4_LEN 1 +#define DMA_SBMR_BLEN_8_POS 2 +#define DMA_SBMR_BLEN_8_LEN 1 +#define DMA_SBMR_BLEN_16_POS 3 +#define DMA_SBMR_BLEN_16_LEN 1 +#define DMA_SBMR_BLEN_32_POS 4 +#define DMA_SBMR_BLEN_32_LEN 1 +#define DMA_SBMR_BLEN_64_POS 5 +#define DMA_SBMR_BLEN_64_LEN 1 +#define DMA_SBMR_BLEN_128_POS 6 +#define DMA_SBMR_BLEN_128_LEN 1 +#define DMA_SBMR_BLEN_256_POS 7 +#define DMA_SBMR_BLEN_256_LEN 1 +#define DMA_SBMR_FB_POS 0 +#define DMA_SBMR_FB_LEN 1 + +/* DMA register values */ +#define DMA_DSR_RPS_LEN 4 +#define DMA_DSR_TPS_LEN 4 +#define DMA_DSR_Q_LEN (DMA_DSR_RPS_LEN + DMA_DSR_TPS_LEN) +#define DMA_DSR0_TPS_START 12 +#define DMA_DSRX_FIRST_QUEUE 3 +#define DMA_DSRX_INC 4 +#define DMA_DSRX_QPR 4 /* no definition */ +#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 0x1100. Each subsequent channel has registers that + * are accessed using an offset of 0x80 from the previous channel. + */ +#define DMA_CH_BASE 0x1100 +#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 0x20 +#define DMA_CH_RDTR_LO 0x28 +#define DMA_CH_TDRLR 0x2c +#define DMA_CH_RDRLR 0x30 +#define DMA_CH_IER 0x34 +#define DMA_CH_RIWT 0x38 +#define DMA_CH_SR 0x60 + +/* DMA channel register entry bit positions and sizes */ +#define DMA_CH_CR_PBLX8_POS 16 +#define DMA_CH_CR_PBLX8_LEN 1 +#define DMA_CH_CR_SPH_POS 24 +#define DMA_CH_CR_SPH_LEN 1 +#define DMA_CH_IER_AIE_POS 14 +#define DMA_CH_IER_AIE_LEN 1 +#define DMA_CH_IER_FBEE_POS 12 +#define DMA_CH_IER_FBEE_LEN 1 +#define DMA_CH_IER_NIE_POS 15 +#define DMA_CH_IER_NIE_LEN 1 +#define DMA_CH_IER_RBUE_POS 7 +#define DMA_CH_IER_RBUE_LEN 1 +#define DMA_CH_IER_RIE_POS 6 +#define DMA_CH_IER_RIE_LEN 1 +#define DMA_CH_IER_RSE_POS 8 +#define DMA_CH_IER_RSE_LEN 1 +#define DMA_CH_IER_TBUE_POS 2 +#define DMA_CH_IER_TBUE_LEN 1 +#define DMA_CH_IER_TIE_POS 0 +#define DMA_CH_IER_TIE_LEN 1 +#define DMA_CH_IER_TXSE_POS 1 +#define DMA_CH_IER_TXSE_LEN 1 +#define DMA_CH_RCR_PBL_POS 16 +#define DMA_CH_RCR_PBL_LEN 6 +#define DMA_CH_RCR_RBSZ_POS 1 +#define DMA_CH_RCR_RBSZ_LEN 14 +#define DMA_CH_RCR_SR_POS 0 +#define DMA_CH_RCR_SR_LEN 1 +#define DMA_CH_RIWT_RWT_POS 0 +#define DMA_CH_RIWT_RWT_LEN 8 +#define DMA_CH_SR_FBE_POS 12 +#define DMA_CH_SR_FBE_LEN 1 +#define DMA_CH_SR_RBU_POS 7 +#define DMA_CH_SR_RBU_LEN 1 +#define DMA_CH_SR_RI_POS 6 +#define DMA_CH_SR_RI_LEN 1 +#define DMA_CH_SR_RPS_POS 8 +#define DMA_CH_SR_RPS_LEN 1 +#define DMA_CH_SR_TBU_POS 2 +#define DMA_CH_SR_TBU_LEN 1 +#define DMA_CH_SR_TI_POS 0 +#define DMA_CH_SR_TI_LEN 1 +#define DMA_CH_SR_TPS_POS 1 +#define DMA_CH_SR_TPS_LEN 1 +#define DMA_CH_TCR_OSP_POS 4 +#define DMA_CH_TCR_OSP_LEN 1 +#define DMA_CH_TCR_PBL_POS 16 +#define DMA_CH_TCR_PBL_LEN 6 +#define DMA_CH_TCR_ST_POS 0 +#define DMA_CH_TCR_ST_LEN 1 +#define DMA_CH_TCR_TSE_POS 12 +#define DMA_CH_TCR_TSE_LEN 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 +#define DMA_PBL_128 128 +#define DMA_PBL_256 256 +#define DMA_PBL_X8_DISABLE 0x00 +#define DMA_PBL_X8_ENABLE 0x01 + +/* Descriptor/Packet entry bit positions and sizes */ +#define RX_PACKET_ERRORS_CRC_POS 2 +#define RX_PACKET_ERRORS_CRC_LEN 1 +#define RX_PACKET_ERRORS_FRAME_POS 3 +#define RX_PACKET_ERRORS_FRAME_LEN 1 +#define RX_PACKET_ERRORS_LENGTH_POS 0 +#define RX_PACKET_ERRORS_LENGTH_LEN 1 +#define RX_PACKET_ERRORS_OVERRUN_POS 1 +#define RX_PACKET_ERRORS_OVERRUN_LEN 1 + +#define RX_PACKET_ATTRIBUTES_CSUM_DONE_POS 0 +#define RX_PACKET_ATTRIBUTES_CSUM_DONE_LEN 1 +#define RX_PACKET_ATTRIBUTES_VLAN_CTAG_POS 1 +#define RX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN 1 +#define RX_PACKET_ATTRIBUTES_INCOMPLETE_POS 2 +#define RX_PACKET_ATTRIBUTES_INCOMPLETE_LEN 1 +#define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_POS 3 +#define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_LEN 1 +#define RX_PACKET_ATTRIBUTES_CONTEXT_POS 4 +#define RX_PACKET_ATTRIBUTES_CONTEXT_LEN 1 +#define RX_PACKET_ATTRIBUTES_RX_TSTAMP_POS 5 +#define RX_PACKET_ATTRIBUTES_RX_TSTAMP_LEN 1 +#define RX_PACKET_ATTRIBUTES_RSS_HASH_POS 6 +#define RX_PACKET_ATTRIBUTES_RSS_HASH_LEN 1 + +#define RX_NORMAL_DESC0_OVT_POS 0 +#define RX_NORMAL_DESC0_OVT_LEN 16 +#define RX_NORMAL_DESC2_HL_POS 0 +#define RX_NORMAL_DESC2_HL_LEN 10 +#define RX_NORMAL_DESC3_CDA_LEN 1 +#define RX_NORMAL_DESC3_CTXT_POS 30 +#define RX_NORMAL_DESC3_CTXT_LEN 1 +#define RX_NORMAL_DESC3_ES_POS 15 +#define RX_NORMAL_DESC3_ES_LEN 1 +#define RX_NORMAL_DESC3_ETLT_POS 16 +#define RX_NORMAL_DESC3_ETLT_LEN 3 +#define RX_NORMAL_DESC3_FD_POS 29 +#define RX_NORMAL_DESC3_FD_LEN 1 +#define RX_NORMAL_DESC3_INTE_POS 30 +#define RX_NORMAL_DESC3_INTE_LEN 1 +#define RX_NORMAL_DESC3_L34T_LEN 4 +#define RX_NORMAL_DESC3_LD_POS 28 +#define RX_NORMAL_DESC3_LD_LEN 1 +#define RX_NORMAL_DESC3_OWN_POS 31 +#define RX_NORMAL_DESC3_OWN_LEN 1 +#define RX_NORMAL_DESC3_BUF2V_POS 25 +#define RX_NORMAL_DESC3_BUF2V_LEN 1 +#define RX_NORMAL_DESC3_BUF1V_POS 24 +#define RX_NORMAL_DESC3_BUF1V_LEN 1 +#define RX_NORMAL_DESC3_PL_POS 0 +#define RX_NORMAL_DESC3_PL_LEN 15 +#define RX_NORMAL_DESC3_RSV_LEN 1 + +/* Inner VLAN Tag. Valid only when Double VLAN tag processing + * and VLAN tag stripping are enabled. + */ +#define RX_NORMAL_DESC0_WB_IVT_POS 16 +#define RX_NORMAL_DESC0_WB_IVT_LEN 16 +#define RX_NORMAL_DESC0_WB_OVT_POS 0 /* Outer VLAN Tag. */ +#define RX_NORMAL_DESC0_WB_OVT_LEN 16 +#define RX_NORMAL_DESC0_WB_OVT_VLANID_POS 0 /* Outer VLAN ID. */ +#define RX_NORMAL_DESC0_WB_OVT_VLANID_LEN 12 +#define RX_NORMAL_DESC0_WB_OVT_CFI_POS 12 /* Outer VLAN CFI. */ +#define RX_NORMAL_DESC0_WB_OVT_CFI_LEN 1 +#define RX_NORMAL_DESC0_WB_OVT_PRIO_POS 13 /* Outer VLAN Priority. */ +#define RX_NORMAL_DESC0_WB_OVT_PRIO_LEN 3 + +#define RX_NORMAL_DESC1_WB_IPCE_POS 7 /* IP Payload Error. */ +#define RX_NORMAL_DESC1_WB_IPCE_LEN 1 +#define RX_NORMAL_DESC1_WB_IPV6_POS 5 /* IPV6 Header Present. */ +#define RX_NORMAL_DESC1_WB_IPV6_LEN 1 +#define RX_NORMAL_DESC1_WB_IPV4_POS 4 /* IPV4 Header Present. */ +#define RX_NORMAL_DESC1_WB_IPV4_LEN 1 +#define RX_NORMAL_DESC1_WB_IPHE_POS 3 /* P Header Error. */ +#define RX_NORMAL_DESC1_WB_IPHE_LEN 1 +#define RX_NORMAL_DESC1_WB_PT_POS 0 +#define RX_NORMAL_DESC1_WB_PT_LEN 3 + +/* Hash Filter Status. When this bit is set, it indicates + * that the packet passed the MAC address hash filter. + */ +#define RX_NORMAL_DESC2_WB_HF_POS 18 +#define RX_NORMAL_DESC2_WB_HF_LEN 1 +/* Destination Address Filter Fail. When Flexible RX Parser + * is disabled, and this bit is set, it indicates that the packet + * failed the DA Filter in the MAC. + */ +#define RX_NORMAL_DESC2_WB_DAF_POS 17 +#define RX_NORMAL_DESC2_WB_DAF_LEN 1 + +#define RX_NORMAL_DESC3_WB_LD_POS 28 +#define RX_NORMAL_DESC3_WB_LD_LEN 1 +/* When this bit is set, it indicates that the status in + * RDES0 is valid and it is written by the DMA. + */ +#define RX_NORMAL_DESC3_WB_RS0V_POS 25 +#define RX_NORMAL_DESC3_WB_RS0V_LEN 1 +/* When this bit is set, it indicates that a Cyclic Redundancy + * Check (CRC) Error occurred on the received packet. This field + * is valid only when the LD bit of RDES3 is set. + */ +#define RX_NORMAL_DESC3_WB_CE_POS 24 +#define RX_NORMAL_DESC3_WB_CE_LEN 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_DESC1_PT_UDP 1 +#define RX_DESC1_PT_TCP 2 +#define RX_DESC1_PT_ICMP 3 +#define RX_DESC1_PT_AV_TAG_DATA 6 +#define RX_DESC1_PT_AV_TAG_CTRL 7 +#define RX_DESC1_PT_AV_NOTAG_CTRL 5 + +#define RX_CONTEXT_DESC3_TSA_LEN 1 +#define RX_CONTEXT_DESC3_TSD_LEN 1 + +#define TX_PACKET_ATTRIBUTES_CSUM_ENABLE_POS 0 +#define TX_PACKET_ATTRIBUTES_CSUM_ENABLE_LEN 1 +#define TX_PACKET_ATTRIBUTES_TSO_ENABLE_POS 1 +#define TX_PACKET_ATTRIBUTES_TSO_ENABLE_LEN 1 +#define TX_PACKET_ATTRIBUTES_VLAN_CTAG_POS 2 +#define TX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN 1 +#define TX_PACKET_ATTRIBUTES_PTP_POS 3 +#define TX_PACKET_ATTRIBUTES_PTP_LEN 1 + +#define TX_CONTEXT_DESC2_MSS_POS 0 +#define TX_CONTEXT_DESC2_MSS_LEN 14 +#define TX_CONTEXT_DESC2_IVLTV_POS 16 /* Inner VLAN Tag. */ +#define TX_CONTEXT_DESC2_IVLTV_LEN 16 + +#define TX_CONTEXT_DESC3_CTXT_POS 30 +#define TX_CONTEXT_DESC3_CTXT_LEN 1 +#define TX_CONTEXT_DESC3_TCMSSV_POS 26 +#define TX_CONTEXT_DESC3_TCMSSV_LEN 1 +#define TX_CONTEXT_DESC3_IVTIR_POS 18 +#define TX_CONTEXT_DESC3_IVTIR_LEN 2 +/* Insert an inner VLAN tag with the tag value programmed + * in the MAC_Instxner_VLAN_Incl register or context + * descriptor. + */ +#define TX_CONTEXT_DESC3_IVTIR_INSERT 2 +/* Indicates that the Inner VLAN TAG, IVLTV field of context TDES2 is valid. */ +#define TX_CONTEXT_DESC3_IVLTV_POS 17 +#define TX_CONTEXT_DESC3_IVLTV_LEN 1 +/* Indicates that the VT field of context TDES3 is valid. */ +#define TX_CONTEXT_DESC3_VLTV_POS 16 +#define TX_CONTEXT_DESC3_VLTV_LEN 1 +#define TX_CONTEXT_DESC3_VT_POS 0 +#define TX_CONTEXT_DESC3_VT_LEN 16 + +/* Header Length or Buffer 1 Length. */ +#define TX_NORMAL_DESC2_HL_B1L_POS 0 +#define TX_NORMAL_DESC2_HL_B1L_LEN 14 +/* Interrupt on Completion. */ +#define TX_NORMAL_DESC2_IC_POS 31 +#define TX_NORMAL_DESC2_IC_LEN 1 +/* Transmit Timestamp Enable or External TSO Memory Write Enable. */ +#define TX_NORMAL_DESC2_TTSE_POS 30 +#define TX_NORMAL_DESC2_TTSE_LEN 1 +/* LAN Tag Insertion or Replacement. */ +#define TX_NORMAL_DESC2_VTIR_POS 14 +#define TX_NORMAL_DESC2_VTIR_LEN 2 +#define TX_NORMAL_DESC2_VLAN_INSERT 0x2 + +#define TX_NORMAL_DESC3_TCPPL_POS 0 +#define TX_NORMAL_DESC3_TCPPL_LEN 18 +/* Frame Length or TCP Payload Length. */ +#define TX_NORMAL_DESC3_FL_POS 0 +#define TX_NORMAL_DESC3_FL_LEN 15 +/* Checksum Insertion Control or TCP Payload Length. + * 2'b00: Checksum Insertion Disabled. + * 2'b01: Only IP header checksum calculation and insertion are enabled. + * 2'b10: IP header checksum and payload checksum calculation and insertion are + * enabled, but pseudo-header checksum is not calculated in hardware. + * 2'b11: IP Header checksum and payload checksum calculation and insertion are + * enabled, and pseudo - header checksum is calculated in hardware. */ +#define TX_NORMAL_DESC3_CIC_POS 16 +#define TX_NORMAL_DESC3_CIC_LEN 2 +/* TCP Segmentation Enable. */ +#define TX_NORMAL_DESC3_TSE_POS 18 +#define TX_NORMAL_DESC3_TSE_LEN 1 +/* THL: TCP/UDP Header Length.If the TSE bit is set, this field contains + * the length of the TCP / UDP header.The minimum value of this field must + * be 5 for TCP header.The value must be equal to 2 for UDP header. This + * field is valid only for the first descriptor. + */ +#define TX_NORMAL_DESC3_TCPHDRLEN_POS 19 +#define TX_NORMAL_DESC3_TCPHDRLEN_LEN 4 +#define TX_NORMAL_DESC3_CPC_POS 26 /* CRC Pad Control. */ +#define TX_NORMAL_DESC3_CPC_LEN 2 +#define TX_NORMAL_DESC3_LD_POS 28 /* Last Descriptor. */ +#define TX_NORMAL_DESC3_LD_LEN 1 +#define TX_NORMAL_DESC3_FD_POS 29 /* First Descriptor. */ +#define TX_NORMAL_DESC3_FD_LEN 1 +/* Context Type.This bit should be set to 1'b0 for normal descriptor. */ +#define TX_NORMAL_DESC3_CTXT_POS 30 +#define TX_NORMAL_DESC3_CTXT_LEN 1 +#define TX_NORMAL_DESC3_OWN_POS 31 /* Own Bit. */ +#define TX_NORMAL_DESC3_OWN_LEN 1 + +/* for ephy generic register definitions */ + +#define FXGMAC_EPHY_REGS_LEN 32 /* 32 ethernet phy registers under spec */ +#define REG_MII_BMCR 0x00 /* Basic mode control register */ +#define PHY_CR_RESET_POS 15 +#define PHY_CR_RESET_LEN 1 +#define PHY_CR_SPEED_SEL_H_POS 6 +#define PHY_CR_SPEED_SEL_H_LEN 1 +#define PHY_CR_SPEED_SEL_L_POS 13 +#define PHY_CR_SPEED_SEL_L_LEN 1 +#define PHY_CR_AUTOENG_POS 12 +#define PHY_CR_AUTOENG_LEN 1 +#define PHY_CR_RE_AUTOENG_POS 9 +#define PHY_CR_RE_AUTOENG_LEN 1 +#define PHY_CR_DUPLEX_POS 8 +#define PHY_CR_DUPLEX_LEN 1 +#define REG_MII_BMCR_ENABLE_LOOPBACK 0x8140 +#define REG_MII_BMCR_DISABLE_LOOPBACK 0x9140 +#define REG_MII_BMSR 0x01 /* Basic mode status register */ +#define REG_MII_PHYSID1 0x02 /* PHYS ID 1 */ +#define REG_MII_PHYSID2 0x03 /* PHYS ID 2 */ +#define REG_MII_ADVERTISE 0x04 /* Advertisement control reg */ +#define PHY_MII_ADVERTISE_ASYPAUSE_POS 11 +#define PHY_MII_ADVERTISE_ASYPAUSE_LEN 1 +#define PHY_MII_ADVERTISE_PAUSE_POS 10 +#define PHY_MII_ADVERTISE_PAUSE_LEN 1 +#define PHY_MII_ADVERTISE_100FULL_POS 8 +#define PHY_MII_ADVERTISE_100FULL_LEN 1 +#define PHY_MII_ADVERTISE_100HALF_POS 7 +#define PHY_MII_ADVERTISE_100HALF_LEN 1 +#define PHY_MII_ADVERTISE_10FULL_POS 6 +#define PHY_MII_ADVERTISE_10FULL_LEN 1 +#define PHY_MII_ADVERTISE_10HALF_POS 5 +#define PHY_MII_ADVERTISE_10HALF_LEN 1 +#define REG_MII_LPA 0x05 /* Link partner ability reg */ +#define REG_MII_EXPANSION 0x06 /* Expansion register */ +#define REG_MII_NEXT_PAGE 0x07 /* Next page register */ +#define REG_MII_LPR_NEXT_PAGE 0x08 /* LPR next page register */ +#define REG_MII_CTRL1000 0x09 /* 1000BASE-T control */ +#define PHY_MII_CTRL1000_1000FULL_POS 9 +#define PHY_MII_CTRL1000_1000FULL_LEN 1 +#define PHY_MII_CTRL1000_1000HALF_POS 8 +#define PHY_MII_CTRL1000_1000HALF_LEN 1 +#define REG_MII_STAT1000 0x0A /* 1000BASE-T status */ +#define PHY_MII_STAT1000_CFG_ERROR_POS 15 +#define PHY_MII_STAT1000_CFG_ERROR_LEN 1 + +#define REG_MII_MMD_CTRL 0x0D /* MMD access control register */ +#define REG_MII_MMD_DATA 0x0E /* MMD access data register */ + +#define REG_MII_ESTATUS 0x0F /* Extended Status */ + +#define REG_MII_SPEC_CTRL 0x10 /* PHY specific func control */ +#define PHY_MII_SPEC_CTRL_CRS_ON_POS 3 +#define PHY_MII_SPEC_CTRL_CRS_ON_LEN 1 +#define REG_MII_SPEC_STATUS 0x11 /* PHY specific status */ +#define PHY_MII_SPEC_DUPLEX_POS 13 +#define PHY_MII_SPEC_DUPLEX_LEN 1 +#define REG_MII_INT_MASK 0x12 /* Interrupt mask register */ + +#ifdef AISC_MODE +#define PHY_INT_MASK_LINK_UP_POS 10 +#define PHY_INT_MASK_LINK_UP_LEN 1 +#define PHY_INT_MASK_LINK_DOWN_POS 11 +#define PHY_INT_MASK_LINK_DOWN_LEN 1 +#else /* FPGA_MODE */ +#define PHY_INT_MASK_LINK_UP_POS 1 +#define PHY_INT_MASK_LINK_UP_LEN 1 +#define PHY_INT_MASK_LINK_DOWN_POS 0 +#define PHY_INT_MASK_LINK_DOWN_LEN 1 +#endif +#define REG_MII_INT_STATUS 0x13 /* Interrupt status register */ +#define PHY_INT_STAT_LINK_UP_POS 1 +#define PHY_INT_STAT_LINK_UP_LEN 1 +#define PHY_INT_STAT_LINK_DOWN_POS 0 +#define PHY_INT_STAT_LINK_DOWN_LEN 1 +#define REG_MII_DOWNG_CTRL 0x14 /* Speed auto downgrade control*/ +#define REG_MII_RERRCOUNTER 0x15 /* Receive error counter */ + +#define REG_MII_EXT_ADDR 0x1E /* Extended reg's address */ +#define REG_MII_EXT_DATA 0x1F /* Extended reg's date */ + +#define FXGMAC_EPHY_ID_MASK 0x0000ffff + +/* for ephy link capability + * Advertisement control register(0x04) + */ + /* Advertisement control register(0x04) */ +#define FXGMAC_ADVERTISE_SLCT 0x001f /* Selector bits */ +#define FXGMAC_ADVERTISE_CSMA 0x0001 /* Only selector supported */ +#define FXGMAC_ADVERTISE_1000FULL 0x0004 /* trt fir 1000BASE-T full duplex */ +#define FXGMAC_ADVERTISE_1000HALF 0x0008 /* try for 1000BASE-T half duplex */ +#define FXGMAC_ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ +#define FXGMAC_ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ +#define FXGMAC_ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ +#define FXGMAC_ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ +#define FXGMAC_ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */ +#define FXGMAC_ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */ +#define FXGMAC_ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */ +#define FXGMAC_ADVERTISE_RESV 0x1000 /* Unused... */ +#define FXGMAC_ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */ +#define FXGMAC_ADVERTISE_LPACK 0x4000 /* Ack link partners response */ +#define FXGMAC_ADVERTISE_NPAGE 0x8000 /* Next page bit */ + +/* 1000BASE-T Control register(0x09) */ +#define REG_BIT_ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */ +#define REG_BIT_ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */ + +#define REG_BIT_ADVERTISE_1000_CAP (REG_BIT_ADVERTISE_1000FULL | REG_BIT_ADVERTISE_1000HALF) +#define REG_BIT_ADVERTISE_100_10_CAP (FXGMAC_ADVERTISE_100FULL | FXGMAC_ADVERTISE_100HALF | FXGMAC_ADVERTISE_10FULL | FXGMAC_ADVERTISE_10HALF) + +#ifndef SPEED_1000M +#define SPEED_1000M 1000 +#endif +#ifndef SPEED_100M +#define SPEED_100M 100 +#endif +#ifndef SPEED_10M +#define SPEED_10M 10 +#endif + +#ifndef SPEED_UNKNOWN +#define SPEED_UNKNOWN 0xffff +#endif + +#ifndef DUPLEX_FULL +#define DUPLEX_FULL 1 +#endif +#ifndef DUPLEX_HALF +#define DUPLEX_HALF 0 +#endif + +#ifndef BIT +#define BIT(n) (0x1<<(n)) +#endif + +#ifndef FUXI_EPHY_SPEED_MODE_BIT +#define FUXI_EPHY_SPEED_MODE 0xc000 +#define FUXI_EPHY_DUPLEX 0x2000 +#define FUXI_EPHY_SPEED_MODE_BIT 14 +#define FUXI_EPHY_DUPLEX_BIT 13 +#define FUXI_EPHY_LINK_STATUS_BIT 10 + +#endif + +#define FUXI_EPHY_SMI_SEL_PHY 0x0 +#define FUXI_EPHY_SMI_SEL_SDS_QSGMII 0x02 +#define FUXI_EPHY_SMI_SEL_SDS_SGMII 0x03 + +#define REG_MII_EXT_ANALOG_CFG3 0x52 +#define MII_EXT_ANALOG_CFG3_ADC_START_CFG_POS 14 +#define MII_EXT_ANALOG_CFG3_ADC_START_CFG_LEN 2 +/* VGA bandwidth, default is 2 after reset. Set to 0 to mitigate + * unstable issue in 130m. + */ +#define MII_EXT_ANALOG_CFG3_ADC_START_CFG_DEFAULT 0x0 +#define MII_EXT_ANALOG_CFG3_ON_TIME_CFG_POS 12 +#define MII_EXT_ANALOG_CFG3_ON_TIME_CFG_LEN 2 +#define MII_EXT_ANALOG_CFG3_VGA_AMP_GAIN_CFG_POS 8 +#define MII_EXT_ANALOG_CFG3_VGA_AMP_GAIN_CFG_LEN 4 +#define MII_EXT_ANALOG_CFG3_VGA_IBIAS_CFG_POS 4 +#define MII_EXT_ANALOG_CFG3_VGA_IBIAS_CFG_LEN 3 +#define MII_EXT_ANALOG_CFG3_OCP_CFG_POS 2 +#define MII_EXT_ANALOG_CFG3_OCP_CFG_LEN 2 +#define MII_EXT_ANALOG_CFG3_VGA_LPF_CFG_POS 0 +#define MII_EXT_ANALOG_CFG3_VGA_LPF_CFG_LEN 2 + +#define REG_MII_EXT_PMA_DEBUG_KCOEF 0x78 +#define MII_EXT_PMA_DEBUG_KCOEF_IPR_KCOEF_GE_LNG_POS 8 +#define MII_EXT_PMA_DEBUG_KCOEF_IPR_KCOEF_GE_LNG_LEN 6 +/* After reset, it's 0x10. We need change it to 0x20 to make it + * easier to linkup in gigabit mode with long cable. + */ +#define MII_EXT_PMA_DEBUG_KCOEF_IPR_KCOEF_GE_LNG_DEFAULT 0x20 +#define MII_EXT_PMA_DEBUG_KCOEF_IPR_KCOEF_DEFAULT_POS 0 +#define MII_EXT_PMA_DEBUG_KCOEF_IPR_KCOEF_DEFAULT_LEN 6 + +#define REG_MII_EXT_LPBK_REG 0x0a +#define REG_MII_EXT_LPBK_REG_ENABLE_LOOPBACK 0x3a18 +#define REG_MII_EXT_LPBK_REG_CLEAN_LOOPBACK 0x3a08 +#define REG_MII_EXT_SLEEP_CONTROL_REG 0x27 +#define REG_MII_EXT_SLEEP_REG_ENABLE_LOOPBACK 0x6812 +#define REG_MII_EXT_SLEEP_REG_CLEAN_LOOPBACK 0xe812 + +#define REG_MII_EXT_ANALOG_CFG2 0x51 +#define REG_MII_EXT_ANALOG_CFG2_LED_VALUE 0x4a9 +#define REG_MII_EXT_ANALOG_CFG8 0x57 +#define REG_MII_EXT_ANALOG_CFG8_LED_VALUE 0x274c + +#define REG_MII_EXT_COMMON_LED_CFG 0xA00B +#define REG_MII_EXT_COMMON_LED0_CFG 0xA00C +#define REG_MII_EXT_COMMON_LED0_CFG_VALUE_SOLUTION0 0x2600 +#define REG_MII_EXT_COMMON_LED0_CFG_VALUE_SOLUTION1 0x00 +#define REG_MII_EXT_COMMON_LED0_CFG_VALUE_SOLUTION2 0x20 +#define REG_MII_EXT_COMMON_LED0_CFG_VALUE_SOLUTION3 0x2600 +#define REG_MII_EXT_COMMON_LED1_CFG 0xA00D +#define REG_MII_EXT_COMMON_LED1_CFG_VALUE_SOLUTION0 0x1800 +#define REG_MII_EXT_COMMON_LED1_CFG_VALUE_SOLUTION1 0x00 +#define REG_MII_EXT_COMMON_LED1_CFG_VALUE_SOLUTION2 0x40 +#define REG_MII_EXT_COMMON_LED2_CFG 0xA00E +#define REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION0 0x00 +#define REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION2 0x07 +#define REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION3 0x20 +#define REG_MII_EXT_COMMON_LED2_CFG_VALUE_SOLUTION4 0x1800 +#define REG_MII_EXT_COMMON_LED_BLINK_CFG 0xA00F +#define REG_MII_EXT_COMMON_LED_BLINK_CFG_SOLUTION2 0x0F + +#define REG_MII_EXT_COMMON_LED0_CFG_VALUE_SLEEP_SOLUTION3 0x2600 + +#define REG_MII_EXT_PKG_CFG0 0xA0 +#define REG_MII_EXT_PKG_CHECK_POS 14 +#define REG_MII_EXT_PKG_CHECK_LEN 2 +#define REG_MII_EXT_PKG_ENABLE_CHECK 0x2 +#define REG_MII_EXT_PKG_DISABLE_CHECK 0x1 +#define REG_MII_EXT_SLEEP_CONTROL1 0x27 +#define MII_EXT_SLEEP_CONTROL1_EN_POS 15 +#define MII_EXT_SLEEP_CONTROL1_EN_LEN 1 +#define MII_EXT_SLEEP_CONTROL1_PLLON_IN_SLP_POS 14 +#define MII_EXT_SLEEP_CONTROL1_PLLON_IN_SLP_LEN 1 +#define REG_MII_EXT_PKG_RX_VALID0 0xA3 +#define REG_MII_EXT_REG_RX_VALID1 0xA4 +#define REG_MII_EXT_REG_RX_OS0 0xA5 +#define REG_MII_EXT_REG_RX_OS1 0xA6 +#define REG_MII_EXT_REG_RX_US0 0xA7 +#define REG_MII_EXT_REG_RX_US1 0xA8 +#define REG_MII_EXT_REG_RX_ERR 0xA9 +#define REG_MII_EXT_REG_RX_0S_BAD 0xAA +#define REG_MII_EXT_REG_RX_FRAGMENT 0xAB +#define REG_MII_EXT_REG_RX_NOSFD 0xAC +#define REG_MII_EXT_REG_TX_VALID0 0xAD +#define REG_MII_EXT_REG_TX_VALID1 0xAE +#define REG_MII_EXT_REG_TX_OS0 0xAF +#define REG_MII_EXT_REG_TX_OS1 0xB0 +#define REG_MII_EXT_REG_TX_US0 0xB1 +#define REG_MII_EXT_REG_TX_US1 0xB2 +#define REG_MII_EXT_REG_TX_ERR 0xB3 +#define REG_MII_EXT_REG_TX_OS_BAD 0xB4 +#define REG_MII_EXT_REG_TX_FRAGMENT 0xB5 +#define REG_MII_EXT_REG_TX_NOSFD 0xB6 +#define REG_MII_EXT_REG_PMA_DBG0_ADC 0x13 +#define REG_MII_EXT_ENABLE_GIGA_POWER_SAVING_FOR_SHORT_CABLE 0x3538 +#define REG_MII_EXT_REG_CLD_REG0 0x3A0 +#define REG_MII_EXT_ENABLE_CLD_NP_WP 0xEB24 +#define REG_MII_EXT_REG_CLD_REG1 0x3CC +#define REG_MII_EXT_ENABLE_CLD_GT_HT_BT 0x7001 +#define REG_MMD_EEE_ABILITY_REG 0x3C +#define REG_MMD_EEE_ABILITY_VALUE 0x06 + +/* Below registers don't belong to GMAC, it has zero offset, not 0x2000 offset. mem_base + REG_XXX. */ +/***When issue happens, driver write this register to trigger pcie sniffer. ***/ +#define REG_PCIE_TRIGGER 0x1000 +#define PCIE_TRIGGER_CODE_TX_HANG 0x00000002 +#define PCIE_TRIGGER_CODE_LINKDOWN 0x00000003 + + +#define MGMT_EPHY_CTRL 0x1004 +/* check register address 0x1004 +* b[6:5] ephy_pause +* b[4:3] ephy_speed 0b10 1000m 0b01 100m +* b[2] ephy_duplex +* b[1] ephy_link +* b[0] ephy_reset.0-reset, 1-unreset. Should be set to 1 before use phy. +*/ +#define MGMT_EPHY_CTRL_RESET_POS 0 +#define MGMT_EPHY_CTRL_RESET_LEN 1 +#define MGMT_EPHY_CTRL_STA_EPHY_RESET 0 /* 0: reset state. */ +#define MGMT_EPHY_CTRL_STA_EPHY_RELEASE 1 /* 1: release state. */ +#define MGMT_EPHY_CTRL_STA_EPHY_LINKUP 2 /* 1: link up; 0: link down. */ +#define MGMT_EPHY_CTRL_STA_EPHY_LINKUP_POS 1 +#define MGMT_EPHY_CTRL_STA_EPHY_LINKUP_LEN 1 +#define MGMT_EPHY_CTRL_STA_EPHY_DUPLEX_POS 2 /* ephy duplex */ +#define MGMT_EPHY_CTRL_STA_EPHY_DUPLEX_LEN 1 + +#define MGMT_EPHY_CTRL_STA_SPEED_POS 3 +#define MGMT_EPHY_CTRL_STA_SPEED_LEN 2 +#define MGMT_EPHY_CTRL_STA_SPEED_MASK 0x18 + +#define MGMT_EPHY_CTRL_ERROR_VAULE 0xFFFFFFFF + +#define MGMT_PCIE_EP_CTRL 0x1008 + +#define MGMT_PCIE_EP_CTRL_DBI_CS_EN_POS 0 +#define MGMT_PCIE_EP_CTRL_DBI_CS_EN_LEN 1 + +#define MGMT_PCIE_CFG_CTRL 0x8BC +#define PCIE_CFG_CTRL_DEFAULT_VAL 0x7ff40 + +#define MGMT_PCIE_CFG_CTRL_CS_EN_POS 0 +#define MGMT_PCIE_CFG_CTRL_CS_EN_LEN 1 + +/***power management ***/ +#define WOL_CTL 0x100C +/* set means magic and remote packet wakeup enable */ +#define WOL_PKT_EN_POS 1 +#define WOL_PKT_EN_LEN 1 +/* set means link change wakeup enable */ +#define WOL_LINKCHG_EN_POS 0 +#define WOL_LINKCHG_EN_LEN 1 + +#define OOB_WOL_CTRL 0x1010 +#define OOB_WOL_CTRL_DIS_POS 0 +#define OOB_WOL_CTRL_DIS_LEN 1 + +/* b3:0 per rx ch interrupt + * b7:4 per tx ch interrupt + * b8 Safety interrupt signal for un-correctable error + * b9 Safety interrupt signal for correctable error + * b10 Interrupt signal to host system + * b11 Magic Packet Received or Remote Wake-up Packet Received + * b12 ethernet phy interrupt + */ +#define MGMT_INT_CTRL0 0x1100 + +/* MAC management registers bit positions and sizes */ +#define MGMT_INT_CTRL0_INT_MASK_POS 16 +#define MGMT_INT_CTRL0_INT_MASK_LEN 16 +#define MGMT_INT_CTRL0_INT_MASK_MASK 0xFFFF +#define MGMT_INT_CTRL0_INT_MASK_RXCH 0xF +#define MGMT_INT_CTRL0_INT_MASK_TXCH 0x10 +#define MGMT_INT_CTRL0_INT_MASK_EX_PMT 0xF7FF +#define MGMT_INT_CTRL0_INT_MASK_DISABLE 0xF000 + +#define MGMT_INT_CTRL0_INT_STATUS_POS 0 +#define MGMT_INT_CTRL0_INT_STATUS_LEN 16 +#define MGMT_INT_CTRL0_INT_STATUS_MASK 0xFFFF +#define MGMT_INT_CTRL0_INT_STATUS_RX 0x0001 +#define MGMT_INT_CTRL0_INT_STATUS_TX 0x0010 +#define MGMT_INI_CTRL0_INT_STATUS_TX_INVERSE 0xFFEF +#define MGMG_INT_CTRL0_INT_STATUS_PHY_INVERSE 0xFFDF +#define MGMT_INT_CTRL0_INT_STATUS_PHY 0x0020 + +#define MGMT_INT_CTRL0_INT_MASK_RXCH_POS 16 +#define MGMT_INT_CTRL0_INT_STATUS_RXCH_POS 0 +#define MGMT_INT_CTRL0_INT_STATUS_RXCH_LEN 4 +#define MGMT_INT_CTRL0_INT_STATUS_RXCH_MASK 0xF +#define MGMT_INT_CTRL0_INT_STATUS_RXTX_LEN 5 +#define MGMT_INT_CTRL0_INT_STATUS_RXTX_MASK 0x1F +#define MGMT_INT_CTRL0_INT_STATUS_RXTXPHY_MASK 0x3F + +#define MGMT_INT_CTRL0_INT_MASK_TXCH_POS 20 +#define MGMT_INT_CTRL0_INT_STATUS_TXCH_POS 4 +#define MGMT_INT_CTRL0_INT_STATUS_TXCH_LEN 1 +#define MGMT_INT_CTRL0_INT_STATUS_TXCH_MASK 0x1 + + +/* Interrupt Ctrl1 */ +#define INT_CTRL1 0x1104 +#define INT_CTRL1_TMR_CNT_CFG_MAX_POS 0 /* Timer counter cfg max. Default 0x19, 1us. */ +#define INT_CTRL1_TMR_CNT_CFG_MAX_LEN 10 +#define INT_CTRL1_TMR_CNT_CFG_DEF_VAL 0x19 +#define INT_CTRL1_MSI_AIO_EN_POS 16 +#define INT_CTRL1_MSI_AIO_EN_LEN 1 + +/* Interrupt Moderation */ +#define INT_MOD 0x1108 +#define INT_MOD_TX_POS 16 +#define INT_MOD_TX_LEN 12 +#define INT_MOD_RX_POS 0 +#define INT_MOD_RX_LEN 12 +#define INT_MOD_IN_US 200 /*in us*/ + +/* PCIE LTR 2 working modes: +Two working mode: +1. SW trigger +LTR idle threshold timer set as 0, enable LTR enable will trigger one LTR message +Note: PCIe cfg enable should set in initilization before enable LTR. +2. HW auto trigger +LTR idle threshold timer set as one non-zero value, HW monitor system status, +when system idle timer over threshold, HW send out LTR message +system exit idle state, send out one LTR exit message. +*/ +#define LTR_CTRL 0x1130 +#define LTR_CTRL_IDLE_THRE_TIMER_POS 16 +#define LTR_CTRL_IDLE_THRE_TIMER_LEN 14 /* in 8ns units*/ +#define LTR_CTRL_IDLE_THRE_TIMER_VAL 0x3FFF +#define LTR_CTRL_EN_POS 0 +#define LTR_CTRL_EN_LEN 1 + +#define LTR_CTRL1 0x1134 /* LTR latency message, only for SW enable. */ +#define LTR_CTRL1_LTR_MSG_POS 0 +#define LTR_CTRL1_LTR_MSG_LEN 32 + +#define LTR_CTRL2 0x1138 +#define LTR_CTRL2_DBG_DATA_POS 0 +#define LTR_CTRL2_DBG_DATA_LEN 32 + +#define LTR_IDLE_ENTER 0x113C /* LTR_CTRL3, LTR latency message, only for System IDLE Start. */ +#define LTR_IDLE_ENTER_POS 0 +#define LTR_IDLE_ENTER_LEN 10 +#define LTR_IDLE_ENTER_USVAL 900 +#define LTR_IDLE_ENTER_SCALE_POS 10 +#define LTR_IDLE_ENTER_SCALE_LEN 5 +#define LTR_IDLE_ENTER_SCALE 2 /* 0-1ns, 1-32ns, 2-1024ns, 3-32,768ns, 4-1,048,576ns, 5-33,554,432ns, 110-111-Not Permitted.*/ +#define LTR_IDLE_ENTER_REQUIRE_POS 15 +#define LTR_IDLE_ENTER_REQUIRE_LEN 1 +#define LTR_IDLE_ENTER_REQUIRE 1 + +#define LTR_IDLE_EXIT 0x1140 /* LTR_CTRL4, LTR latency message, only for System IDLE End. */ +#define LTR_IDLE_EXIT_POS 0 +#define LTR_IDLE_EXIT_LEN 10 +#define LTR_IDLE_EXIT_USVAL 2 +#define LTR_IDLE_EXIT_SCALE_POS 10 +#define LTR_IDLE_EXIT_SCALE_LEN 5 +#define LTR_IDLE_EXIT_SCALE 2 +#define LTR_IDLE_EXIT_REQUIRE_POS 15 +#define LTR_IDLE_EXIT_REQUIRE_LEN 1 +#define LTR_IDLE_EXIT_REQUIRE 1 + +#define LPW_CTRL 0x1188 +#define LPW_CTRL_L1SS_EN_POS 22 +#define LPW_CTRL_L1SS_EN_LEN 1 +#define LPW_CTRL_L1SS_SEL_POS 21 /* 0 - up to both CFG0x158 and reg1188 L1ss setting. 1 - up to CFG0x158 L1ss setting. */ +#define LPW_CTRL_L1SS_SEL_LEN 1 +#define LPW_CTRL_L1SS_SEL_CFG 1 +#define LPW_CTRL_ASPM_L1_CPM_POS 19 /*L1.CPM mode enable bit. Default 0, set as 1 enable this mode. clkreq pin need to connect RC*/ +#define LPW_CTRL_ASPM_L1_CPM_LEN 1 +#define LPW_CTRL_ASPM_L0S_EN_POS 17 +#define LPW_CTRL_ASPM_L0S_EN_LEN 1 +#define LPW_CTRL_ASPM_L1_EN_POS 16 +#define LPW_CTRL_ASPM_L1_EN_LEN 1 +#define LPW_CTRL_ASPM_LPW_EN_POS 9 /* application ready to enter L23. */ +#define LPW_CTRL_ASPM_LPW_EN_LEN 1 +#define LPW_CTRL_SYS_CLK_125_SEL_POS 8 /* system 125M select: 125M or 62.5MHz. Default: 125MHz.*/ +#define LPW_CTRL_SYS_CLK_125_SEL_LEN 1 +#define LPW_CTRL_PCIE_RADM_CG_EN_POS 5 /* clock gating enable bit of PCIe Radm clock. Default 1; set as 1, enable gating.*/ +#define LPW_CTRL_PCIE_RADM_CG_EN_LEN 1 +#define LPW_CTRL_PCIE_CORE_CG_EN_POS 4 /* clock gating enable bit of PCIe Core clock. Default 1; set as 1, enable gating.*/ +#define LPW_CTRL_PCIE_CORE_CG_EN_LEN 1 +#define LPW_CTRL_PCIE_AXI_CG_EN_POS 3 /* clock gating enable bit of PCIe AXI clock.Default 1; set as 1, enable gating.*/ +#define LPW_CTRL_PCIE_AXI_CG_EN_LEN 1 +#define LPW_CTRL_GMAC_AXI_CG_EN_POS 2 /* clock gating enable bit of GMAC AXI clock. Default 1; set as 1, enable gating.*/ +#define LPW_CTRL_GMAC_AXI_CG_EN_LEN 1 +#define LPW_CTRL_MDIO2APB_CG_EN_POS 1 /* clock gating enable bit of MDIO2APB, default 1. Set as 1, enable clock gating feature. */ +#define LPW_CTRL_MDIO2APB_CG_EN_LEN 1 +#define LPW_CTRL_OTP_CLK_ON_POS 0 /* Turn on before SW OTP operation, default 1. */ +#define LPW_CTRL_OTP_CLK_ON_LEN 1 + +#define MSI_PBA_REG 0x1300 +#define SYS_RESET_REG 0x152C +#define SYS_RESET_POS 31 +#define SYS_RESET_LEN 1 + +#define REG_PCIE_PSM_STATE 0x1994 /* PCIe PHY power state. */ +#define PCIE_PSM_STATE_POS 0 +#define PCIE_PSM_STATE_LEN 4 +#define PCIE_PSM_STATE_P0 2 +#define PCIE_PSM_STATE_P0s 3 +#define PCIE_PSM_STATE_P1 4 +#define PCIE_PSM_STATE_P1_CPM 5 +#define PCIE_PSM_STATE_P1_1 6 +#define PCIE_PSM_STATE_P1_2 7 +#define PCIE_PSM_STATE_P2 8 + +#define REG_PCIE_SERDES_STATUS 0x1998 +#define PCIE_SERDES_STATUS_DRV_ON_POS 11 +#define PCIE_SERDES_STATUS_DRV_ON_LEN 1 +#define PCIE_SERDES_STATUS_RX_PD_POS 10 +#define PCIE_SERDES_STATUS_RX_PD_LEN 1 +#define PCIE_SERDES_STATUS_PI_PD_POS 9 +#define PCIE_SERDES_STATUS_PI_PD_LEN 1 +#define PCIE_SERDES_STATUS_SIGDET_ON_POS 8 +#define PCIE_SERDES_STATUS_SIGDET_ON_LEN 1 +#define PCIE_SERDES_STATUS_TX_VCM_POS 7 +#define PCIE_SERDES_STATUS_TX_VCM_LEN 1 +#define PCIE_SERDES_STATUS_RX_RT50_POS 6 +#define PCIE_SERDES_STATUS_RX_RT50_LEN 1 +#define PCIE_SERDES_STATUS_BEACON_ON_POS 5 +#define PCIE_SERDES_STATUS_BEACON_ON_LEN 1 +#define PCIE_SERDES_STATUS_PLL_ON_POS 4 +#define PCIE_SERDES_STATUS_PLL_ON_LEN 1 +#define PCIE_SERDES_STATUS_REFCLK_ON_POS 3 +#define PCIE_SERDES_STATUS_REFCLK_ON_LEN 1 +#define PCIE_SERDES_STATUS_LDO_ON_POS 2 +#define PCIE_SERDES_STATUS_LDO_ON_LEN 1 +#define PCIE_SERDES_STATUS_HW_EN_SDS_BIAS_POS 1 +#define PCIE_SERDES_STATUS_HW_EN_SDS_BIAS_LEN 1 +#define PCIE_SERDES_STATUS_HW_BIAS_ON_POS 0 +#define PCIE_SERDES_STATUS_HW_BIAS_ON_LEN 1 + +#define REG_PCIE_SERDES_PLL 0x199C +#define PCIE_SERDES_PLL_AUTOOFF_POS 0 +#define PCIE_SERDES_PLL_AUTOOFF_LEN 1 + +#define NS_OF_GLB_CTL 0x1B00 +#define NS_TPID_PRO 0x1B04 +#define NS_LUT_ROMOTE0 0x1B08 +#define NS_LUT_ROMOTE1 0X1B0C +#define NS_LUT_ROMOTE2 0X1B10 +#define NS_LUT_ROMOTE3 0X1B14 +#define NS_LUT_TARGET0 0X1B18 +#define NS_LUT_TARGET1 0X1B1C +#define NS_LUT_TARGET2 0X1B20 +#define NS_LUT_TARGET3 0X1B24 +#define NS_LUT_SOLICITED0 0X1B28 +#define NS_LUT_SOLICITED1 0X1B2C +#define NS_LUT_SOLICITED2 0X1B30 +#define NS_LUT_SOLICITED3 0X1B34 +#define NS_LUT_MAC_ADDR 0X1B38 +#define NS_LUT_MAC_ADDR_CTL 0X1B3C +#define NS_LUT_TARGET4 0X1B78 +#define NS_LUT_TARGET5 0X1B7c +#define NS_LUT_TARGET6 0X1B80 +#define NS_LUT_TARGET7 0X1B84 + +#define NS_OF_GLB_CTL_TX_CLK_EN_POS 2 +#define NS_OF_GLB_CTL_TX_CLK_EN_LEN 1 +#define NS_OF_GLB_CTL_RX_CLK_EN_POS 1 +#define NS_OF_GLB_CTL_RX_CLK_EN_LEN 1 +#define NS_OF_GLB_CTL_EN_POS 0 +#define NS_OF_GLB_CTL_EN_ELN 1 +#define NS_TPID_PRO_STPID_POS 16 +#define NS_TPID_PRO_STPID_LEN 16 +#define NS_TPID_PRO_CTPID_POS 0 +#define NS_TPID_PRO_CTPID_LEN 16 +#define NS_LUT_DST_CMP_TYPE_POS 19 +#define NS_LUT_DST_CMP_TYPE_LEN 1 +#define NS_LUT_DST_IGNORED_POS 18 +#define NS_LUT_DST_IGNORED_LEN 1 +#define NS_LUT_REMOTE_AWARED_POS 17 +#define NS_LUT_REMOTE_AWARED_LEN 1 +#define NS_LUT_TARGET_ISANY_POS 16 +#define NS_LUT_TARGET_ISANY_LEN 1 +#define NS_LUT_MAC_ADDR_LOW_POS 0 +#define NS_LUT_MAC_ADDR_LOW_LEN 16 + +/* RSS implementation registers, 20210817 */ + +/* 10 RSS key registers */ +#define MGMT_RSS_KEY0 0x1020 +#define MGMT_RSS_KEY9 0x1044 +#define MGMT_RSS_KEY_REG_INC 0x4 + +/* RSS control register */ +#define MGMT_RSS_CTRL 0x1048 +/* b31 enable + * b12:10 indirection table size. 2^(val+1) + * b9:8 default Queue NO. + * b7:0 hash type or options + */ + +/* RSS ctrl register bit definitions. + * [0] ipv4 + * [1] tcpv4 + * [2] udpv4 + * [3] ipv6 + * [4] tcpv6 + * [5] udpv6 +* [6] only ipv4 udp check IP hash +* [7] only ipv6 udp check IP hash + */ +#define MGMT_RSS_CTRL_OPT_POS 0 +#define MGMT_RSS_CTRL_OPT_LEN 8 +#define MGMT_RSS_CTRL_OPT_MASK 0xFF +#define MGMT_RSS_CTRL_IPV4_EN 0x01 +#define MGMT_RSS_CTRL_TCPV4_EN 0x02 +#define MGMT_RSS_CTRL_UDPV4_EN 0x04 +#define MGMT_RSS_CTRL_IPV6_EN 0x08 +#define MGMT_RSS_CTRL_TCPV6_EN 0x10 +#define MGMT_RSS_CTRL_UDPV6_EN 0x20 +#define MGMT_RSS_CTRL_IPV4 0x0 +#define MGMT_RSS_CTRL_IPV4 0x0 + +#define MGMT_RSS_CTRL_DEFAULT_Q_POS 8 +#define MGMT_RSS_CTRL_DEFAULT_Q_LEN 2 +#define MGMT_RSS_CTRL_DEFAULT_Q_MASK 0x3 + +#define MGMT_RSS_CTRL_TBL_SIZE_POS 10 +#define MGMT_RSS_CTRL_TBL_SIZE_LEN 3 +#define MGMT_RSS_CTRL_TBL_SIZE_MASK 0x7 + +#define MAC_RSSCR_RSSE_POS 31 +#define MAC_RSSCR_RSSE_LEN 1 + +/* rss indirection table (IDT) */ +#define MGMT_RSS_IDT 0x1050 +/* b0:1 entry0 + * b2:3 entry1 + * ... + */ +#define MGMT_RSS_IDT_REG_INC 4 +#define MGMT_RSS_IDT_ENTRY_PER_REG 16 +#define MGMT_RSS_IDT_ENTRY_MASK 0x3 +#define MAC_CRC_LENGTH 4 + + /* osc_ctrl */ +#define MGMT_XST_OSC_CTRL 0x1158 +#define MGMT_XST_OSC_CTRL_XST_OSC_SEL_POS 2 +#define MGMT_XST_OSC_CTRL_XST_OSC_SEL_LEN 1 +#define MGMT_XST_OSC_CTRL_EN_OSC_POS 1 +#define MGMT_XST_OSC_CTRL_EN_OSC_LEN 1 +#define MGMT_XST_OSC_CTRL_EN_XST_POS 0 +#define MGMT_XST_OSC_CTRL_EN_XST_LEN 1 + +/* for WPI, yzhang, 20210826 */ +#define MGMT_WPI_CTRL0 0x1160 + /* b1:0 wpi_mode "2b00: normal working mode; 2b01: WPI write mode, work in sleep mode; 2b10: WPI read mode, work after sleep before normal working mode;" + * b2 ram_op_done Each row ram read done, SW can start read after done; + * b3 wpi_op_done WPI read done for the total packet; + * b17:4 wpi_pkt_len WOL packet length, unit byte; + * b31 wpi_fail Error status in Sleep mode; + */ +#define MGMT_WPI_CTRL0_WPI_MODE_POS 0 +#define MGMT_WPI_CTRL0_WPI_MODE_LEN 2 +#define MGMT_WPI_CTRL0_WPI_MODE_NORMAL 0x00 /* normal working mode. */ +/* WPI write mode, work in sleep mode. */ +#define MGMT_WPI_CTRL0_WPI_MODE_WR 0x01 +/* WPI read mode, work after sleep before normal working mode. */ +#define MGMT_WPI_CTRL0_WPI_MODE_RD 0x02 +#define MGMT_WPI_CTRL0_RAM_OP_DONE 0x4 +#define MGMT_WPI_CTRL0_WPI_OP_DONE 0x8 +#define MGMT_WPI_CTRL0_WPI_PKT_LEN_POS 4 +#define MGMT_WPI_CTRL0_WPI_PKT_LEN_LEN 14 +#define MGMT_WPI_CTRL0_WPI_FAIL 0x80000000 + +#define MGMT_WPI_CTRL1_DATA 0x1164 + +#define MGMT_WOL_CTRL 0x1530 + /* b0 link_chg_status 1: waken by link-change + * b1 mgk_pkt_status 1: waken by magic-packet + * b2 rwk_pkt_status 1: waken by remote patten packet + */ +#define MGMT_WOL_CTRL_WPI_LINK_CHG 1 +#define MGMT_WOL_CTRL_WPI_MGC_PKT 2 +#define MGMT_WOL_CTRL_WPI_RWK_PKT 4 +#define MGMT_WOL_CTRL_WPI_RWK_PKT_NUMBER 0x010000 + +#define MGMT_RMK_CTRL 0x1400 + +#define MGMT_SIGDET 0x17F8 +#define MGMT_SIGDET_POS 13 +#define MGMT_SIGDET_LEN 3 +#define MGMT_SIGDET_55MV 7 +#define MGMT_SIGDET_50MV 6 +#define MGMT_SIGDET_45MV 5 /* default value */ +#define MGMT_SIGDET_40MV 4 +#define MGMT_SIGDET_35MV 3 +#define MGMT_SIGDET_30MV 2 +#define MGMT_SIGDET_25MV 1 +#define MGMT_SIGDET_20MV 0 + +#define FXGMAC_MTL_REG(pdata, n, reg) \ + ((pdata)->mac_regs + MTL_Q_BASE + ((n) * MTL_Q_INC) + (reg)) + +#define FXGMAC_DMA_REG(channel, reg) ((channel)->dma_regs + (reg)) + +#define MSI_ID_RXQ0 0 +#define MSI_ID_RXQ1 1 +#define MSI_ID_RXQ2 2 +#define MSI_ID_RXQ3 3 +#define MSI_ID_TXQ0 4 + +#if 1/* msi table modify to 6 0~3 rx 4 tx 5 phy/other */ +#define MSI_ID_PHY_OTHER 5 + +#define MSIX_TBL_MAX_NUM 6 +#define MSIX_TBL_RXTX_NUM 5 + +#else +#define MSI_ID_TXQ1 5 +#define MSI_ID_TXQ2 6 +#define MSI_ID_TXQ3 7 +#define MSI_ID_SFTUE 8 +#define MSI_ID_SFTCE 9 +#define MSI_ID_SBD 10 +#define MSI_ID_PMT 11 +#define MSI_ID_PHY 12 + +#define MSIX_TBL_MAX_NUM 16 +#define MSIX_TBL_RXTX_NUM 8 +#endif +#define MSIX_TBL_BASE_ADDR 0x1200 +#define MSIX_TBL_MASK_OFFSET 0xC +#define MSIX_TBL_DATA_OFFSET 0x8 +#define MSIX_TBL_ADDR_OFFSET 0x0 + +/******************************************************************* + efuse entry. val31:0 -> offset15:0 + offset7:0 + offset15:8 + val7:0 + val15:8 + val23:16 + val31:24 +*******************************************************************/ +#define EFUSE_OP_CTRL_0 0x1500 +#define EFUSE_OP_WR_DATA_POS 16 +#define EFUSE_OP_WR_DATA_LEN 8 +#define EFUSE_OP_ADDR_POS 8 +#define EFUSE_OP_ADDR_LEN 8 +#define EFUSE_OP_START_POS 2 +#define EFUSE_OP_START_LEN 1 +#define EFUSE_OP_MODE_POS 0 +#define EFUSE_OP_MODE_LEN 2 +#define EFUSE_OP_MODE_ROW_WRITE 0x0 +#define EFUSE_OP_MODE_ROW_READ 0x1 +#define EFUSE_OP_MODE_AUTO_LOAD 0x2 +#define EFUSE_OP_MODE_READ_BLANK 0x3 + +#define EFUSE_OP_CTRL_1 0x1504 +#define EFUSE_OP_RD_DATA_POS 24 +#define EFUSE_OP_RD_DATA_LEN 8 +#define EFUSE_OP_BIST_ERR_ADDR_POS 16 +#define EFUSE_OP_BIST_ERR_ADDR_LEN 8 +#define EFUSE_OP_BIST_ERR_CNT_POS 8 +#define EFUSE_OP_BIST_ERR_CNT_LEN 8 +#define EFUSE_OP_PGM_PASS_POS 2 +#define EFUSE_OP_PGM_PASS_LEN 1 +#define EFUSE_OP_DONE_POS 1 +#define EFUSE_OP_DONE_LEN 1 + +/* efuse layout refer to http://redmine.motor-comm.com/issues/3856 */ +#define EFUSE_FISRT_UPDATE_ADDR 255 +#define EFUSE_SECOND_UPDATE_ADDR 209 +#define FUXI_EFUSE_MAX_ENTRY 39 +#define FUXI_EFUSE_MAX_ENTRY_UNDER_LED_COMMON 24 +#define EFUSE_PATCH_ADDR_START_BYTE 0 +#define EFUSE_PATCH_DATA_START_BYTE 2 +#define EFUSE_REGION_A_B_LENGTH 18 +#define EFUSE_EACH_PATH_SIZE 6 + +#define EFUSE_REVID_REGISTER 0x0008 +#define EFUSE_SUBSYS_REGISTER 0x002C +/* mac[5]->bit7:0, mac[4]->bit15:8, mac[3]->bit23:16, mac[2]->bit31:24. */ +#define MACA0LR_FROM_EFUSE 0x1520 +/* mac[1]->bit7:0, mac[0]->bit15:8. mac[6] = + * {00, 01, 02, 03, 04, 05} 00-01-02-03-04-05. + */ +#define MACA0HR_FROM_EFUSE 0x1524 + +#define EFUSE_LED_ADDR 0x00 +#define EFUSE_LED_POS 0 +#define EFUSE_LED_LEN 5 +#define EFUSE_OOB_ADDR 0x07 +#define EFUSE_OOB_POS 2 +#define EFUSE_OOB_LEN 1 +#define EFUSE_LED_SOLUTION0 0 +#define EFUSE_LED_SOLUTION1 1 +#define EFUSE_LED_SOLUTION2 2 +#define EFUSE_LED_SOLUTION3 3 +#define EFUSE_LED_SOLUTION4 4 +#define EFUSE_LED_COMMON_SOLUTION 0x1F + +/******************** Below for pcie configuration register. *********************/ +#define REG_PCI_VENDOR_ID 0x0 /* WORD reg */ +#define REG_PCI_DEVICE_ID 0x2 /* WORD reg */ +#define PCI_DEVICE_ID_FUXI 0x6801 + +#define REG_PCI_COMMAND 0x4 +#define PCI_COMMAND_IO_SPACE_POS 0 +#define PCI_COMMAND_IO_SPACE_LEN 1 +#define PCI_COMAMND_MEM_SPACE_POS 1 +#define PCI_COMAMND_MEM_SPACE_LEN 1 +#define PCI_COMMAND_MASTER_POS 2 +#define PCI_COMMAND_MASTER_LEN 1 +#define PCI_COMMAND_DIS_INT_POS 10 +#define PCI_COMMAND_DIS_INT_LEN 1 +#define PCI_COMMAND_INTX_STATUS_POS 19 +#define PCI_COMMAND_INTX_STATUS_LEN 1 + +#define REG_PCI_REVID 0x8 /* BYTE reg */ +#define REG_PCI_PROGRAM_INTF 0x9 /* BYTE reg */ /* PCI Class Program Interface */ +#define REG_PCI_SUB_CLASS 0xA /* BYTE reg */ +#define REG_PCI_BASE_CLASS 0xB /* BYTE reg */ +#define REG_CACHE_LINE_SIZE 0xC + + +#define REG_MEM_BASE 0x10 /* DWORD or QWORD reg */ +#define REG_MEM_BASE_HI 0x14 /* DWORD or QWORD reg */ + +#define REG_IO_BASE 0x20 /* DWORD reg */ + +#define REG_PCI_SUB_VENDOR_ID 0x2C /* WORD reg */ +#define REG_PCI_SUB_DEVICE_ID 0x2E /* WORD reg */ + +#define REG_INT_LINE 0x3C /* BYTE reg */ + +#define REG_PM_STATCTRL 0x44 /* WORD reg */ +#define PM_STATCTRL_PWR_STAT_POS 0 +#define PM_STATCTRL_PWR_STAT_LEN 2 +#define PM_STATCTRL_PWR_STAT_D3 3 +#define PM_STATCTRL_PWR_STAT_D0 0 +#define PM_CTRLSTAT_PME_EN_POS 8 +#define PM_CTRLSTAT_PME_EN_LEN 1 +#define PM_CTRLSTAT_DATA_SEL_POS 9 +#define PM_CTRLSTAT_DATA_SEL_LEN 4 +#define PM_CTRLSTAT_DATA_SCAL_POS 13 +#define PM_CTRLSTAT_DATA_SCAL_LEN 2 +#define PM_CTRLSTAT_PME_STAT_POS 15 +#define PM_CTRLSTAT_PME_STAT_LEN 1 + +#define REG_DEVICE_CTRL1 0x78 +#define DEVICE_CTRL1_CONTROL_POS 0 +#define DEVICE_CTRL1_CONTROL_LEN 16 +#define DEVICE_CTRL1_STATUS_POS 16 +#define DEVICE_CTRL1_STATUS_LEN 16 + +#define REG_PCI_LINK_CTRL 0x80 +#define PCI_LINK_CTRL_CONTROL_POS 0 +#define PCI_LINK_CTRL_CONTROL_LEN 16 +#define PCI_LINK_CTRL_ASPM_CONTROL_POS 0 +#define PCI_LINK_CTRL_ASPM_CONTROL_LEN 2 +#define PCI_LINK_CTRL_L1_STATUS 2 +#define PCI_LINK_CTRL_CONTROL_CPM_POS 8 /*L1.CPM mode enable bit. Default 0, set as 1 enable this mode. clkreq pin need to connect RC*/ +#define PCI_LINK_CTRL_CONTROL_CPM_LEN 1 +#define PCI_LINK_CTRL_STATUS_POS 16 +#define PCI_LINK_CTRL_STATUS_LEN 16 + +#define REG_DEVICE_CTRL2 0x98 /* WORD reg */ +#define DEVICE_CTRL2_LTR_EN_POS 10 /* Enable from BIOS side. */ +#define DEVICE_CTRL2_LTR_EN_LEN 1 + +#define REG_MSIX_CAPABILITY 0xB0 + +/* ASPM L1ss PM Substates */ +#define REG_ASPM_L1SS_CAP 0x154 /* Capabilities Register */ +#define ASPM_L1SS_CAP_PCIPM_L1_2_POS 0 /* PCI-PM L1.2 Supported */ +#define ASPM_L1SS_CAP_PCIPM_L1_2_LEN 1 +#define ASPM_L1SS_CAP_PCIPM_L1_1_POS 1 /* PCI-PM L1.1 Supported */ +#define ASPM_L1SS_CAP_PCIPM_L1_1_LEN 1 +#define ASPM_L1SS_CAP_ASPM_L1_2_POS 2 /* ASPM L1.2 Supported */ +#define ASPM_L1SS_CAP_ASPM_L1_2_LEN 1 +#define ASPM_L1SS_CAP_ASPM_L1_1_POS 3 /* ASPM L1.1 Supported */ +#define ASPM_L1SS_CAP_ASPM_L1_1_LEN 1 +#define ASPM_L1SS_CAP_L1_PM_SS_POS 4 /* L1 PM Substates Supported */ +#define ASPM_L1SS_CAP_L1_PM_SS_LEN 1 +#define ASPM_L1SS_CAP_CM_RESTORE_TIME_POS 8 /* Port Common_Mode_Restore_Time */ +#define ASPM_L1SS_CAP_CM_RESTORE_TIME_LEN 8 +#define ASPM_L1SS_CAP_P_PWR_ON_SCALE_POS 16 /* Port T_POWER_ON scale */ +#define ASPM_L1SS_CAP_P_PWR_ON_SCALE_LEN 2 +#define ASPM_L1SS_CAP_P_PWR_ON_VALUE_POS 19 /* Port T_POWER_ON value */ +#define ASPM_L1SS_CAP_P_PWR_ON_VALUE_LEN 5 + +#define REG_ASPM_L1SS_CTRL1 0x158 +#define REG_ASPM_L1SS_CTRL1_VALUE 0x405e000f +#define ASPM_L1SS_CTRL1_L12_PCIPM_EN_POS 0 /* L1.2 in D3 state. */ +#define ASPM_L1SS_CTRL1_L12_PCIPM_EN_LEN 1 +#define ASPM_L1SS_CTRL1_L11_PCIPM_EN_POS 1 /* L1.1 in D3 state. */ +#define ASPM_L1SS_CTRL1_L11_PCIPM_EN_LEN 1 +#define ASPM_L1SS_CTRL1_L12_EN_POS 2 +#define ASPM_L1SS_CTRL1_L12_EN_LEN 1 +#define ASPM_L1SS_CTRL1_L11_EN_POS 3 +#define ASPM_L1SS_CTRL1_L11_EN_LEN 1 +#define ASPM_L1SS_CTRL1_CM_RESTORE_TIME_POS 8 /* Common_Mode_Restore_Time */ +#define ASPM_L1SS_CTRL1_CM_RESTORE_TIME_LEN 8 +#define ASPM_L1SS_CTRL1_LTR_L12_TH_VALUE_POS 16 /* LTR_L1.2_THRESHOLD_Value */ +#define ASPM_L1SS_CTRL1_LTR_L12_TH_VALUE_LEN 10 +#define ASPM_L1SS_CTRL1_L12_TH_SCALE_POS 29 /* LTR_L1.2_THRESHOLD_Scale */ +#define ASPM_L1SS_CTRL1_L12_TH_SCALE_LEN 3 + +#define REG_ASPM_L1SS_CTL2 0x15c /* Control 2 Register */ + +#define REG_ASPM_CONTROL 0x70C +#define ASPM_L1_IDLE_THRESHOLD_POS 27 +#define ASPM_L1_IDLE_THRESHOLD_LEN 3 +#define ASPM_L1_IDLE_THRESHOLD_1US 0 +#define ASPM_L1_IDLE_THRESHOLD_2US 1 +#define ASPM_L1_IDLE_THRESHOLD_4US 2 +#define ASPM_L1_IDLE_THRESHOLD_8US 3 /* default value after reset. */ +#define ASPM_L1_IDLE_THRESHOLD_16US 4 +#define ASPM_L1_IDLE_THRESHOLD_32US 5 +#define ASPM_L1_IDLE_THRESHOLD_64US 6 + +#define REG_POWER_EIOS 0x710 +#define POWER_EIOS_POS 7 +#define POWER_EIOS_LEN 1 + +#endif /* __FUXI_GMAC_REG_H__ */ diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac.h b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac.h new file mode 100644 index 0000000000000..ea01ebdadc4e3 --- /dev/null +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-gmac.h @@ -0,0 +1,934 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021 Motorcomm Corporation. */ + +#ifndef __FUXI_GMAC_H__ +#define __FUXI_GMAC_H__ + +#include "fuxi-os.h" + +/* For fpga before 20210507 */ +#define FXGMAC_FPGA_VER_B4_0507 0 +#define FXGMAC_FPGA_VER_20210507 1 + +#define FXGMAC_DRV_NAME "yt6801" + +#define FXGMAC_DRV_DESC "Motorcomm FUXI GMAC Driver" + +#define FUXI_MAC_REGS_OFFSET 0x2000 + +/* 1: in normal D0 state, turn off ephy link change interrupt. */ +#define FUXI_EPHY_INTERRUPT_D0_OFF 0 +/* 1:when rec buffer is not enough, to create rbd and rec buffer, + * but the rdb need to be continus with the intialized rdb, so + * close the feature + */ +#define FUXI_ALLOC_NEW_RECBUFFER 0 + +#define RESUME_MAX_TIME 3000000 +#define PHY_LINK_TIMEOUT 3000 +#define ESD_RESET_MAXIMUM 0 + +#define REGWR_RETRY_MAXIMUM 2600 +#define PCIE_LINKDOWN_VALUE 0xFFFFFFFF + +#define FXGMAC_MSIX_Q_VECTORS 4 + +#define FXGMAC_IS_CHANNEL_WITH_TX_IRQ(chId) (0 == (chId) ? 1 : 0) + +/* flags for ipv6 NS offload address, local link or Global unicast */ +#define FXGMAC_NS_IFA_LOCAL_LINK 1 +#define FXGMAC_NS_IFA_GLOBAL_UNICAST 2 + +#define FXGMAX_ASPM_WAR_EN +/* Descriptor related parameters */ +#if FXGMAC_TX_HANG_TIMER_EN +#define FXGMAC_TX_DESC_CNT 1024 +#else +/* 256 to make sure the tx ring is in the 4k range when + * FXGMAC_TX_HANG_TIMER_EN is 0 + */ +#define FXGMAC_TX_DESC_CNT 256 +#endif +#define FXGMAC_TX_DESC_MIN_FREE (FXGMAC_TX_DESC_CNT >> 3) +#define FXGMAC_TX_DESC_MAX_PROC (FXGMAC_TX_DESC_CNT >> 1) +#define FXGMAC_RX_DESC_CNT 1024 +#define FXGMAC_RX_DESC_MAX_DIRTY (FXGMAC_RX_DESC_CNT >> 3) + +/* Descriptors required for maximum contiguous TSO/GSO packet */ +#define FXGMAC_TX_MAX_SPLIT ((GSO_MAX_SIZE / FXGMAC_TX_MAX_BUF_SIZE) + 1) + +/* Maximum possible descriptors needed for a SKB */ +#define FXGMAC_TX_MAX_DESC_NR (MAX_SKB_FRAGS + FXGMAC_TX_MAX_SPLIT + 2) + +#define FXGMAC_TX_MAX_BUF_SIZE (0x3fff & ~(64 - 1)) +#define FXGMAC_RX_MIN_BUF_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN) +#define FXGMAC_RX_BUF_ALIGN 64 + +/* Maximum Size for Splitting the Header Data + * Keep in sync with SKB_ALLOC_SIZE + * 3'b000: 64 bytes, 3'b001: 128 bytes + * 3'b010: 256 bytes, 3'b011: 512 bytes + * 3'b100: 1023 bytes , 3'b101'3'b111: Reserved + */ +#define FXGMAC_SPH_HDSMS_SIZE 3 +#define FXGMAC_SKB_ALLOC_SIZE 512 + +/* In Linux Driver, it set MAX_FIFO size 131072, here it uses + * the same value as windows driver + */ +#define FXGMAC_MAX_FIFO 81920 + +#define FXGMAC_MAX_DMA_CHANNELS FXGMAC_MSIX_Q_VECTORS +#define FXGMAC_DMA_STOP_TIMEOUT 5 +#define FXGMAC_DMA_INTERRUPT_MASK 0x31c7 +#define FXGMAC_MAX_DMA_CHANNELS_PLUS_1TX (FXGMAC_MAX_DMA_CHANNELS + 1) + +/* Default coalescing parameters */ +#define FXGMAC_INIT_DMA_TX_USECS INT_MOD_IN_US +#define FXGMAC_INIT_DMA_TX_FRAMES 25 +#define FXGMAC_INIT_DMA_RX_USECS INT_MOD_IN_US +#define FXGMAC_INIT_DMA_RX_FRAMES 25 +#define FXGMAC_MAX_DMA_RIWT 0xff +#define FXGMAC_MIN_DMA_RIWT 0x01 + +/* Flow control queue count */ +#define FXGMAC_MAX_FLOW_CONTROL_QUEUES 8 + +/* System clock is 125 MHz */ +#define FXGMAC_SYSCLOCK 125000000 + +/* Maximum MAC address hash table size (256 bits = 8 bytes) */ +#define FXGMAC_MAC_HASH_TABLE_SIZE 8 + +/* wol pattern settings */ +#define MAX_PATTERN_SIZE 128 /* PATTERN length */ +#define MAX_PATTERN_COUNT 16 /* pattern count */ +#define MAX_LPP_ARP_OFFLOAD_COUNT 1 +#define MAX_LPP_NS_OFFLOAD_COUNT 2 + +#define MAX_WPI_LENGTH_SIZE 1536 /* WPI packet. */ +#define PM_WAKE_PKT_ALIGN 8 /* try use 64 bit boundary... */ + +/* Receive Side Scaling */ +#define FXGMAC_RSS_HASH_KEY_SIZE 40 +#define FXGMAC_RSS_MAX_TABLE_SIZE 128 +#define FXGMAC_RSS_LOOKUP_TABLE_TYPE 0 +#define FXGMAC_RSS_HASH_KEY_TYPE 1 +#define MAX_MSI_COUNT 16 /* Max Msi/Msix supported. */ + +#define FXGMAC_STD_PACKET_MTU 1500 +#define FXGMAC_JUMBO_PACKET_MTU 9014 + +#define NIC_MAX_TCP_OFFLOAD_SIZE 7300 +#define NIC_MIN_LSO_SEGMENT_COUNT 2 + +/* power management */ +#define FXGMAC_POWER_STATE_DOWN 0 +#define FXGMAC_POWER_STATE_UP 1 + +struct wol_bitmap_pattern { + u32 flags; + u32 pattern_size; + u32 mask_size; + u8 mask_info[MAX_PATTERN_SIZE / 8]; + u8 pattern_info[MAX_PATTERN_SIZE]; + u8 pattern_offset; + u16 pattern_crc; +}; + +struct led_setting { + u32 s0_led_setting[5]; + u32 s3_led_setting[5]; + u32 s5_led_setting[5]; + u32 disable_led_setting[5]; +}; + +typedef struct led_setting LED_SETTING; +typedef struct wol_bitmap_pattern WOL_BITMAP_PATTERN; + +/* note, maybe we should refer to NDIS_PM_WAKE_REASON_TYPE + * to avoid duplication definition.... + */ +typedef enum { + WAKE_REASON_NONE = 0, + WAKE_REASON_MAGIC, + WAKE_REASON_PATTERNMATCH, + WAKE_REASON_LINK, + WAKE_REASON_TCPSYNV4, + WAKE_REASON_TCPSYNV6, + /* for wake up method like Link-change, for that, + * GMAC cannot identify and need more checking. + */ + WAKE_REASON_TBD, + WAKE_REASON_HW_ERR, +} WAKE_REASON; + +/* Helper macro for descriptor handling + * Always use FXGMAC_GET_DESC_DATA to access the descriptor data + */ +#define FXGMAC_GET_DESC_DATA(ring, idx) ((ring)->desc_data_head + (idx)) +#define FXGMAC_GET_ENTRY(x, size) ((x + 1) & (size - 1)) + +struct fxgmac_pdata; + +enum fxgmac_int { + FXGMAC_INT_DMA_CH_SR_TI, + FXGMAC_INT_DMA_CH_SR_TPS, + FXGMAC_INT_DMA_CH_SR_TBU, + FXGMAC_INT_DMA_CH_SR_RI, + FXGMAC_INT_DMA_CH_SR_RBU, + FXGMAC_INT_DMA_CH_SR_RPS, + FXGMAC_INT_DMA_CH_SR_TI_RI, + FXGMAC_INT_DMA_CH_SR_FBE, + FXGMAC_INT_DMA_ALL, +}; + +struct fxgmac_stats { + /* MMC TX counters */ + 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 txsinglecollision_g; + u64 txmultiplecollision_g; + u64 txdeferredframes; + u64 txlatecollisionframes; + u64 txexcessivecollisionframes; + u64 txcarriererrorframes; + u64 txoctetcount_g; + u64 txframecount_g; + u64 txexcessivedeferralerror; + u64 txpauseframes; + u64 txvlanframes_g; + u64 txoversize_g; + + /* MMC RX counters */ + u64 rxframecount_gb; + u64 rxoctetcount_gb; + u64 rxoctetcount_g; + u64 rxbroadcastframes_g; + u64 rxmulticastframes_g; + u64 rxcrcerror; + u64 rxalignerror; + 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; + u64 rxreceiveerrorframe; + u64 rxcontrolframe_g; + + /* Extra counters */ + u64 tx_tso_packets; + u64 rx_split_header_packets; + u64 tx_process_stopped; + u64 rx_process_stopped; + u64 tx_buffer_unavailable; + u64 rx_buffer_unavailable; + u64 fatal_bus_error; + u64 tx_vlan_packets; + u64 rx_vlan_packets; + u64 napi_poll_isr; + u64 napi_poll_txtimer; + u64 cnt_alive_txtimer; + + u64 ephy_poll_timer_cnt; + u64 mgmt_int_isr; +}; + +struct fxgmac_ring_buf { + struct sk_buff *skb; + DMA_ADDR_T skb_dma; + unsigned int skb_len; +}; + +/* Common Tx and Rx DMA hardware descriptor */ +struct fxgmac_dma_desc { + __le32 desc0; + __le32 desc1; + __le32 desc2; + __le32 desc3; +}; + +/* Page allocation related values */ +struct fxgmac_page_alloc { + struct page *pages; + unsigned int pages_len; + unsigned int pages_offset; + DMA_ADDR_T pages_dma; +}; + +/* Ring entry buffer data */ +struct fxgmac_buffer_data { + struct fxgmac_page_alloc pa; + struct fxgmac_page_alloc pa_unmap; + + DMA_ADDR_T dma_base; + unsigned long dma_off; + unsigned int dma_len; +}; + +/* Tx-related desc data */ +struct fxgmac_tx_desc_data { + unsigned int packets; /* BQL packet count */ + unsigned int bytes; /* BQL byte count */ +}; + +/* Rx-related desc data */ +struct fxgmac_rx_desc_data { + struct fxgmac_buffer_data hdr; /* Header locations */ + struct fxgmac_buffer_data buf; /* Payload locations */ + + unsigned short hdr_len; /* Length of received header */ + unsigned short len; /* Length of received packet */ +}; + +struct fxgmac_pkt_info { + struct sk_buff *skb; + + unsigned int attributes; + + unsigned int errors; + + /* descriptors needed for this packet */ + unsigned int desc_count; + unsigned int length; + + unsigned int tx_packets; + unsigned int tx_bytes; + + 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; + RSS_HASH_TYPE rss_hash_type; +}; + +struct fxgmac_desc_data { + /* dma_desc: Virtual address of descriptor + * dma_desc_addr: DMA address of descriptor + */ + struct fxgmac_dma_desc *dma_desc; + DMA_ADDR_T dma_desc_addr; + + /* skb: Virtual address of SKB + * skb_dma: DMA address of SKB data + * skb_dma_len: Length of SKB DMA area + */ + struct sk_buff *skb; + DMA_ADDR_T skb_dma; + unsigned int skb_dma_len; + + /* Tx/Rx -related data */ + struct fxgmac_tx_desc_data tx; + struct fxgmac_rx_desc_data rx; + + 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 { + struct sk_buff *skb; + unsigned int len; + unsigned int error; + } state; +}; + +struct fxgmac_ring { + /* Per packet related information */ + struct fxgmac_pkt_info pkt_info; + + /* Virtual/DMA addresses of DMA descriptor list and the total count */ + struct fxgmac_dma_desc *dma_desc_head; + DMA_ADDR_T dma_desc_head_addr; + unsigned int dma_desc_count; + + /* Array of descriptor data corresponding the DMA descriptor + * (always use the FXGMAC_GET_DESC_DATA macro to access this data) + */ + struct fxgmac_desc_data *desc_data_head; + + /* Page allocation for RX buffers */ + struct fxgmac_page_alloc rx_hdr_pa; + struct fxgmac_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; + + struct { + unsigned int xmit_more; + unsigned int queue_stopped; + unsigned short cur_mss; + unsigned short cur_vlan_ctag; + } tx; +} ____cacheline_aligned; + +struct fxgmac_channel { + char name[16]; + + /* Address of private data area for device */ + struct fxgmac_pdata *pdata; + + /* Queue index and base address of queue's DMA registers */ + unsigned int queue_index; + + IOMEM dma_regs; + + /* Per channel interrupt irq number */ + u32 dma_irq; + FXGMAC_CHANNEL_OF_PLATFORM expansion; + + unsigned int saved_ier; + + unsigned int tx_timer_active; + + struct fxgmac_ring *tx_ring; + struct fxgmac_ring *rx_ring; +} ____cacheline_aligned; + +struct fxphy_ag_adv { + u8 auto_neg_en : 1; + u8 full_1000m : 1; + u8 half_1000m : 1; + u8 full_100m : 1; + u8 half_100m : 1; + u8 full_10m : 1; + u8 half_10m : 1; +}; + +struct fxgmac_desc_ops { + int (*alloc_channles_and_rings)(struct fxgmac_pdata *pdata); + void (*free_channels_and_rings)(struct fxgmac_pdata *pdata); + int (*map_tx_skb)(struct fxgmac_channel *channel, struct sk_buff *skb); + int (*map_rx_buffer)(struct fxgmac_pdata *pdata, + struct fxgmac_ring *ring, + struct fxgmac_desc_data *desc_data); + void (*unmap_desc_data)(struct fxgmac_pdata *pdata, + struct fxgmac_desc_data *desc_data); + void (*tx_desc_init)(struct fxgmac_pdata *pdata); + void (*rx_desc_init)(struct fxgmac_pdata *pdata); +}; + +struct fxgmac_hw_ops { + int (*init)(struct fxgmac_pdata *pdata); + int (*exit)(struct fxgmac_pdata *pdata); + void (*save_nonstick_reg)(struct fxgmac_pdata *pdata); + void (*restore_nonstick_reg)(struct fxgmac_pdata *pdata); + int (*set_gmac_register)(struct fxgmac_pdata *pdata, u8 *address, + unsigned int data); + u32 (*get_gmac_register)(struct fxgmac_pdata *pdata, u8 *address); + void (*esd_restore_pcie_cfg)(struct fxgmac_pdata *pdata); + + int (*tx_complete)(struct fxgmac_dma_desc *dma_desc); + + void (*enable_tx)(struct fxgmac_pdata *pdata); + void (*disable_tx)(struct fxgmac_pdata *pdata); + void (*enable_rx)(struct fxgmac_pdata *pdata); + void (*disable_rx)(struct fxgmac_pdata *pdata); + void (*enable_channel_rx)(struct fxgmac_pdata *pdata, + unsigned int queue); + + int (*enable_int)(struct fxgmac_channel *channel, + enum fxgmac_int int_id); + int (*disable_int)(struct fxgmac_channel *channel, + enum fxgmac_int int_id); + void (*set_interrupt_moderation)(struct fxgmac_pdata *pdata); + void (*enable_msix_rxtxinterrupt)(struct fxgmac_pdata *pdata); + void (*disable_msix_interrupt)(struct fxgmac_pdata *pdata); + void (*enable_msix_rxtxphyinterrupt)(struct fxgmac_pdata *pdata); + void (*enable_msix_one_interrupt)(struct fxgmac_pdata *pdata, + u32 intid); + void (*disable_msix_one_interrupt)(struct fxgmac_pdata *pdata, + u32 intid); + bool (*enable_mgm_interrupt)(struct fxgmac_pdata *pdata); + bool (*disable_mgm_interrupt)(struct fxgmac_pdata *pdata); + + void (*dev_xmit)(struct fxgmac_channel *channel); + int (*dev_read)(struct fxgmac_channel *channel); + + int (*set_mac_address)(struct fxgmac_pdata *pdata, u8 *addr); + int (*set_mac_hash)(struct fxgmac_pdata *pdata); + int (*config_rx_mode)(struct fxgmac_pdata *pdata); + int (*enable_rx_csum)(struct fxgmac_pdata *pdata); + int (*disable_rx_csum)(struct fxgmac_pdata *pdata); + void (*config_tso)(struct fxgmac_pdata *pdata); + + /* For MII speed configuration */ + int (*config_mac_speed)(struct fxgmac_pdata *pdata); + int (*set_xlgmii_2500_speed)(struct fxgmac_pdata *pdata); + int (*set_xlgmii_1000_speed)(struct fxgmac_pdata *pdata); + int (*set_xlgmii_100_speed)(struct fxgmac_pdata *pdata); + int (*get_xlgmii_phy_status)(struct fxgmac_pdata *pdata, u32 *speed, + bool *link_up, + bool link_up_wait_to_complete); + + /* For descriptor related operation */ + void (*tx_desc_init)(struct fxgmac_channel *channel); + void (*rx_desc_init)(struct fxgmac_channel *channel); + void (*tx_desc_reset)(struct fxgmac_desc_data *desc_data); + void (*rx_desc_reset)(struct fxgmac_pdata *pdata, + struct fxgmac_desc_data *desc_data, + unsigned int index); + int (*is_last_desc)(struct fxgmac_dma_desc *dma_desc); + int (*is_context_desc)(struct fxgmac_dma_desc *dma_desc); + void (*tx_start_xmit)(struct fxgmac_channel *channel, + struct fxgmac_ring *ring); + void (*set_pattern_data)(struct fxgmac_pdata *pdata); + void (*config_wol)(struct fxgmac_pdata *pdata, int en); + + /* For Flow Control */ + int (*config_tx_flow_control)(struct fxgmac_pdata *pdata); + int (*config_rx_flow_control)(struct fxgmac_pdata *pdata); + + /* For Jumbo Frames */ + int (*config_mtu)(struct fxgmac_pdata *pdata); + int (*enable_jumbo)(struct fxgmac_pdata *pdata); + + /* For Vlan related config */ + int (*enable_tx_vlan)(struct fxgmac_pdata *pdata); + int (*disable_tx_vlan)(struct fxgmac_pdata *pdata); + int (*enable_rx_vlan_stripping)(struct fxgmac_pdata *pdata); + int (*disable_rx_vlan_stripping)(struct fxgmac_pdata *pdata); + int (*enable_rx_vlan_filtering)(struct fxgmac_pdata *pdata); + int (*disable_rx_vlan_filtering)(struct fxgmac_pdata *pdata); + int (*update_vlan_hash_table)(struct fxgmac_pdata *pdata); + + /* For RX coalescing */ + int (*config_rx_coalesce)(struct fxgmac_pdata *pdata); + int (*config_tx_coalesce)(struct fxgmac_pdata *pdata); + unsigned int (*usec_to_riwt)(struct fxgmac_pdata *pdata, + unsigned int usec); + unsigned int (*riwt_to_usec)(struct fxgmac_pdata *pdata, + unsigned int riwt); + + /* For RX and TX threshold config */ + int (*config_rx_threshold)(struct fxgmac_pdata *pdata, + unsigned int val); + int (*config_tx_threshold)(struct fxgmac_pdata *pdata, + unsigned int val); + + /* For RX and TX Store and Forward Mode config */ + int (*config_rsf_mode)(struct fxgmac_pdata *pdata, unsigned int val); + int (*config_tsf_mode)(struct fxgmac_pdata *pdata, unsigned int val); + + /* For TX DMA Operate on Second Frame config */ + int (*config_osp_mode)(struct fxgmac_pdata *pdata); + + /* For RX and TX PBL config */ + int (*config_rx_pbl_val)(struct fxgmac_pdata *pdata); + int (*get_rx_pbl_val)(struct fxgmac_pdata *pdata); + int (*config_tx_pbl_val)(struct fxgmac_pdata *pdata); + int (*get_tx_pbl_val)(struct fxgmac_pdata *pdata); + int (*config_pblx8)(struct fxgmac_pdata *pdata); + + /* For MMC statistics */ + void (*rx_mmc_int)(struct fxgmac_pdata *pdata); + void (*tx_mmc_int)(struct fxgmac_pdata *pdata); + void (*read_mmc_stats)(struct fxgmac_pdata *pdata); + bool (*update_stats_counters)(struct fxgmac_pdata *pdata, + bool ephy_check_en); + + /* For Receive Side Scaling */ + int (*enable_rss)(struct fxgmac_pdata *pdata); + int (*disable_rss)(struct fxgmac_pdata *pdata); + u32 (*get_rss_options)(struct fxgmac_pdata *pdata); + int (*set_rss_options)(struct fxgmac_pdata *pdata); + int (*set_rss_hash_key)(struct fxgmac_pdata *pdata, const u8 *key); + int (*set_rss_lookup_table)(struct fxgmac_pdata *pdata, + const u32 *table); + + /*For Offload*/ + void (*set_arp_offload)(struct fxgmac_pdata *pdata, + unsigned char *ip_addr); + int (*enable_arp_offload)(struct fxgmac_pdata *pdata); + int (*disable_arp_offload)(struct fxgmac_pdata *pdata); + + /*NS offload*/ + int (*set_ns_offload)(struct fxgmac_pdata *pdata, unsigned int index, + unsigned char *remote_addr, + unsigned char *solicited_addr, + unsigned char *target_addr1, + unsigned char *target_addr2, + unsigned char *mac_addr); + int (*enable_ns_offload)(struct fxgmac_pdata *pdata); + int (*disable_ns_offload)(struct fxgmac_pdata *pdata); + + int (*enable_wake_magic_pattern)(struct fxgmac_pdata *pdata); + int (*disable_wake_magic_pattern)(struct fxgmac_pdata *pdata); + + int (*enable_wake_link_change)(struct fxgmac_pdata *pdata); + int (*disable_wake_link_change)(struct fxgmac_pdata *pdata); + + int (*check_wake_pattern_fifo_pointer)(struct fxgmac_pdata *pdata); + int (*set_wake_pattern)(struct fxgmac_pdata *pdata, + struct wol_bitmap_pattern *wol_pattern, + u32 pattern_cnt); + int (*enable_wake_pattern)(struct fxgmac_pdata *pdata); + int (*disable_wake_pattern)(struct fxgmac_pdata *pdata); + int (*set_wake_pattern_mask)(struct fxgmac_pdata *pdata, + u32 filter_index, u8 register_index, + u32 Data); +#if defined(FUXI_PM_WPI_READ_FEATURE_EN) && FUXI_PM_WPI_READ_FEATURE_EN + void (*get_wake_packet_indication)(struct fxgmac_pdata *pdata, + int *wake_reason, + u32 *wake_pattern_number, + u8 *wpi_buf, u32 buf_size, + u32 *packet_size); + void (*enable_wake_packet_indication)(struct fxgmac_pdata *pdata, + int en); +#endif + + void (*reset_phy)(struct fxgmac_pdata *pdata); + /*for release phy, phy write and read, and provide clock to GMAC. */ + void (*release_phy)(struct fxgmac_pdata *pdata); + void (*enable_phy_check)(struct fxgmac_pdata *pdata); + void (*disable_phy_check)(struct fxgmac_pdata *pdata); + void (*setup_cable_loopback)(struct fxgmac_pdata *pdata); + void (*clean_cable_loopback)(struct fxgmac_pdata *pdata); + void (*disable_phy_sleep)(struct fxgmac_pdata *pdata); + void (*enable_phy_sleep)(struct fxgmac_pdata *pdata); + void (*phy_green_ethernet)(struct fxgmac_pdata *pdata); + void (*phy_eee_feature)(struct fxgmac_pdata *pdata); + int (*get_ephy_state)(struct fxgmac_pdata *pdata); + int (*write_ephy_reg)(struct fxgmac_pdata *pdata, u32 val, u32 data); + int (*read_ephy_reg)(struct fxgmac_pdata *pdata, u32 val, u32 *data); + int (*set_ephy_autoneg_advertise)(struct fxgmac_pdata *pdata, + struct fxphy_ag_adv phy_ag_adv); + int (*phy_config)(struct fxgmac_pdata *pdata); + void (*close_phy_led)(struct fxgmac_pdata *pdata); + void (*led_under_active)(struct fxgmac_pdata *pdata); + void (*led_under_sleep)(struct fxgmac_pdata *pdata); + void (*led_under_shutdown)(struct fxgmac_pdata *pdata); + void (*led_under_disable)(struct fxgmac_pdata *pdata); + + /* For power management */ + void (*pre_power_down)(struct fxgmac_pdata *pdata, bool phyloopback); + int (*diag_sanity_check)(struct fxgmac_pdata *pdata); + int (*write_rss_lookup_table)(struct fxgmac_pdata *pdata); + int (*get_rss_hash_key)(struct fxgmac_pdata *pdata, u8 *key_buf); + void (*config_power_down)(struct fxgmac_pdata *pdata, unsigned int wol); + void (*config_power_up)(struct fxgmac_pdata *pdata); + unsigned char (*set_suspend_int)(void *pdata); + void (*set_resume_int)(struct fxgmac_pdata *pdata); + int (*set_suspend_txrx)(struct fxgmac_pdata *pdata); + void (*set_pwr_clock_gate)(struct fxgmac_pdata *pdata); + void (*set_pwr_clock_ungate)(struct fxgmac_pdata *pdata); + + /* for multicast address list */ + int (*set_all_multicast_mode)(struct fxgmac_pdata *pdata, + unsigned int enable); + void (*config_multicast_mac_hash_table)(struct fxgmac_pdata *pdata, + unsigned char *pmc_mac, + int b_add); + + /* for packet filter-promiscuous and broadcast */ + int (*set_promiscuous_mode)(struct fxgmac_pdata *pdata, + unsigned int enable); + int (*enable_rx_broadcast)(struct fxgmac_pdata *pdata, + unsigned int enable); + + /* efuse relevant operation. */ + bool (*read_patch_from_efuse)(struct fxgmac_pdata *pdata, u32 offset, + u32 *value); /* read patch per index. */ + bool (*read_patch_from_efuse_per_index)( + struct fxgmac_pdata *pdata, u8 index, u32 *offset, + u32 *value); /* read patch per index. */ + bool (*write_patch_to_efuse)(struct fxgmac_pdata *pdata, u32 offset, + u32 value); + bool (*write_patch_to_efuse_per_index)(struct fxgmac_pdata *pdata, + u8 index, u32 offset, u32 value); + bool (*read_mac_subsys_from_efuse)(struct fxgmac_pdata *pdata, + u8 *mac_addr, u32 *subsys, + u32 *revid); + bool (*write_mac_subsys_to_efuse)(struct fxgmac_pdata *pdata, + u8 *mac_addr, u32 *subsys, + u32 *revid); + bool (*read_mac_addr_from_efuse)(struct fxgmac_pdata *pdata, + u8 *mac_addr); + bool (*write_mac_addr_to_efuse)(struct fxgmac_pdata *pdata, + u8 *mac_addr); + bool (*efuse_load)(struct fxgmac_pdata *pdata); + bool (*read_efuse_data)(struct fxgmac_pdata *pdata, u32 offset, + u32 *value); + bool (*write_oob)(struct fxgmac_pdata *pdata); + bool (*write_led)(struct fxgmac_pdata *pdata, u32 value); + bool (*read_led_config)(struct fxgmac_pdata *pdata); + bool (*write_led_config)(struct fxgmac_pdata *pdata); + + int (*pcie_init)(struct fxgmac_pdata *pdata, bool ltr_en, + bool aspm_l1ss_en, bool aspm_l1_en, bool aspm_l0s_en); + void (*trigger_pcie)( + struct fxgmac_pdata *pdata, + u32 code); /* To trigger pcie sniffer for analysis. */ +#ifdef DPDK + int (*phy_init)(struct fxgmac_pdata *); + int (*phy_start)(struct fxgmac_pdata *); + void (*phy_stop)(struct fxgmac_pdata *); + void (*phy_status)(struct fxgmac_pdata *); + void (*an_isr)( + struct fxgmac_pdata + *); /* phy_if->an_isr For single interrupt support */ +#endif +}; + +/* This structure contains flags that indicate what hardware features + * or configurations are present in the device. + */ +struct fxgmac_hw_features { + /* HW Version */ + unsigned int version; + + /* HW Feature Register0 */ + unsigned int phyifsel; /* PHY interface 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 Advanced 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 dma_width; /* DMA width */ + 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 avsel; /* AV Feature Enable */ + unsigned int ravsel; /* Rx Side Only AV Feature Enable */ + 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 */ + + /* HW Feature Register3 */ + u32 hwfr3; +}; + +struct fxgmac_resources { + IOMEM addr; + int irq; +}; + +struct fxgmac_pdata { + struct net_device *netdev; + struct device *dev; + PCI_DEV *pdev; + void *pAdapter; + + struct fxgmac_hw_ops hw_ops; + struct fxgmac_desc_ops desc_ops; + + /* Device statistics */ + struct fxgmac_stats stats; + + u32 msg_enable; + u32 reg_nonstick[0x300 >> 2]; + + /* MAC registers base */ + IOMEM mac_regs; + IOMEM base_mem; + + /* Hardware features of the device */ + struct fxgmac_hw_features hw_feat; + + /* Rings for Tx/Rx on a DMA channel */ + struct fxgmac_channel *channel_head; + unsigned int channel_count; + unsigned int tx_ring_count; + unsigned int rx_ring_count; + unsigned int tx_desc_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; +#if FXGMAC_TX_HANG_TIMER_EN + /* for tx hang checking. 20211227 */ + unsigned int tx_hang_restart_queuing; +#endif + + /* 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_usecs; + unsigned int rx_frames; + + /* Current Rx buffer size */ + unsigned int rx_buf_size; + + /* Flow control settings */ + unsigned int tx_pause; + unsigned int rx_pause; + + /* Jumbo frames */ + unsigned int mtu; + unsigned int jumbo; + + /* CRC checking */ + unsigned int crc_check; + + /* MSIX */ + unsigned int msix; + + /* RSS */ + unsigned int rss; + + /* VlanID */ + unsigned int vlan; + unsigned int vlan_exist; + unsigned int vlan_filter; + unsigned int vlan_strip; + + /* Interrupt Moderation */ + unsigned int intr_mod; + unsigned int intr_mod_timer; + + /* Device interrupt number */ + int dev_irq; + unsigned int per_channel_irq; + /* change type from int to u32 to match MSIx, p_msix_entry.vector; */ + u32 channel_irq[FXGMAC_MAX_DMA_CHANNELS_PLUS_1TX]; + + /* Netdev related settings */ + unsigned char mac_addr[ETH_ALEN]; + + /* Filtering support */ +#if FXGMAC_FILTER_MULTIPLE_VLAN_ENABLED + unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; +#endif + + /* Device clocks */ + unsigned long sysclk_rate; + + /* Receive Side Scaling settings */ + u8 rss_key[FXGMAC_RSS_HASH_KEY_SIZE]; + u32 rss_table[FXGMAC_RSS_MAX_TABLE_SIZE]; + u32 rss_options; + + int phy_speed; + int phy_duplex; + int phy_autoeng; + + char drv_name[32]; + char drv_ver[32]; + + struct wol_bitmap_pattern pattern[MAX_PATTERN_COUNT]; + + struct led_setting led; + struct led_setting ledconfig; + + FXGMAC_PDATA_OF_PLATFORM expansion; + + u32 pcie_link_status; +}; + +#define FXGMAC_FLAG_MSI_CAPABLE ((u32)(1 << 0)) /* bit0 */ +#define FXGMAC_FLAG_MSI_ENABLED ((u32)(1 << 1)) /* bit1 */ +#define FXGMAC_FLAG_MSIX_CAPABLE ((u32)(1 << 2)) /* bit2 */ +#define FXGMAC_FLAG_MSIX_ENABLED ((u32)(1 << 3)) /* bit3 */ +#define FXGMAC_FLAG_LEGACY_ENABLED ((u32)(1 << 4)) /* bit4 */ + +#define FXGMAC_FLAG_INTERRUPT_POS 0 +#define FXGMAC_FLAG_INTERRUPT_LEN 5 + +#define FXGMAC_FLAG_MSI_POS 1 +#define FXGMAC_FLAG_MSI_LEN 1 +#define FXGMAC_FLAG_MSIX_POS 3 +#define FXGMAC_FLAG_MSIX_LEN 1 +#define FXGMAC_FLAG_LEGACY_POS 4 +#define FXGMAC_FLAG_LEGACY_LEN 1 +#define FXGMAC_FLAG_LEGACY_IRQ_FREE_POS 31 /* bit31 */ +#define FXGMAC_FLAG_LEGACY_IRQ_FREE_LEN 1 +#define FXGMAC_FLAG_LEGACY_NAPI_FREE_POS 30 /* bit30 */ +#define FXGMAC_FLAG_LEGACY_NAPI_FREE_LEN 1 + +void fxgmac_init_desc_ops(struct fxgmac_desc_ops *desc_ops); +void fxgmac_init_hw_ops(struct fxgmac_hw_ops *hw_ops); +const struct net_device_ops *fxgmac_get_netdev_ops(void); +const struct ethtool_ops *fxgmac_get_ethtool_ops(void); +void fxgmac_dump_tx_desc(struct fxgmac_pdata *pdata, struct fxgmac_ring *ring, + unsigned int idx, unsigned int count, + unsigned int flag); +void fxgmac_dump_rx_desc(struct fxgmac_pdata *pdata, struct fxgmac_ring *ring, + unsigned int idx); +void fxgmac_dbg_pkt(struct net_device *netdev, struct sk_buff *skb, bool tx_rx); +void fxgmac_get_all_hw_features(struct fxgmac_pdata *pdata); +void fxgmac_print_all_hw_features(struct fxgmac_pdata *pdata); +int fxgmac_drv_probe(struct device *dev, struct fxgmac_resources *res); +int fxgmac_drv_remove(struct device *dev); + +#endif /* __FUXI_GMAC_H__ */ diff --git a/drivers/net/ethernet/motorcomm/yt6801/fuxi-os.h b/drivers/net/ethernet/motorcomm/yt6801/fuxi-os.h new file mode 100644 index 0000000000000..1a40267e1fa2e --- /dev/null +++ b/drivers/net/ethernet/motorcomm/yt6801/fuxi-os.h @@ -0,0 +1,515 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021 Motorcomm Corporation. */ + + +#ifndef __FUXI_OS_H__ +#define __FUXI_OS_H__ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_PCI_MSI +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fuxi-dbg.h" + +struct fxgmac_ring; +struct fxgmac_pdata; + +#define FXGMAC_DRV_VERSION "1.0.27" + +#define PCIE_LP_ASPM_L0S 1 +#define PCIE_LP_ASPM_L1 2 +#define PCIE_LP_ASPM_L1SS 4 +#define PCIE_LP_ASPM_LTR 8 + +#define FXGMAC_FAIL -1 +#define FXGMAC_SUCCESS 0 +#define FXGMAC_DEV_CMD (SIOCDEVPRIVATE + 1) +#define FXGMAC_IOCTL_DFS_COMMAND _IOWR('M', 0x80, struct ext_ioctl_data) + +#define FXGMAC_MAX_DBG_TEST_PKT 150 +#define FXGMAC_MAX_DBG_BUF_LEN 64000 +#define FXGMAC_MAX_DBG_RX_DATA 1600 +#define FXGMAC_NETDEV_OPS_BUF_LEN 256 + +#define FXGMAC_TEST_MAC_HEAD_LEN 14 + +#define FUXI_PM_WPI_READ_FEATURE_EN 1 + +#define RSS_Q_COUNT 4 + +#define FXGMAC_TX_HANG_TIMER_EN 0 +/* only for debug. for normal run, pls keep them both 0 + * 0: use default tx q; other: specify txq-1: 1 txq; + */ +#define FXGMAC_NUM_OF_TX_Q_USED 0 +/* 1 to enable a dummy tx, ie, no tail for gmac; */ +#define FXGMAC_DUMMY_TX_DEBUG 0 +/* 1 to trigger(write reg 0x1000) for sniffer stop */ +#define FXGMAC_TRIGGER_TX_HANG 0 + +/* driver feature configuration */ +#if FXGMAC_TX_HANG_TIMER_EN +/* 0: check hw current desc; 1: check software dirty */ +#define FXGMAC_TX_HANG_CHECH_DIRTY 0 +#endif + +/* 1:poll tx of 4 channels; 0: since only 1 tx channel supported in this + * version, poll ch 0 always. + */ + +#define FXGMAC_FULL_TX_CHANNEL 0 + +#ifdef CONFIG_ARM64 +/* when you want to run this driver on 64bit arm, you should open this, + * otherwise dma's mask cannot be set successfully. + */ +#define FUXI_DMA_BIT_MASK 64 +#endif + +#ifdef CONFIG_PCI_MSI +/* should be same as FXGMAC_MAX_DMA_CHANNELS + 1 tx_irq */ +#define FXGMAC_MAX_MSIX_Q_VECTORS (FXGMAC_MSIX_Q_VECTORS + 1) +#define FXGMAC_MSIX_CH0RXDIS_EN 0 /* set to 1 for ch0 unbalance fix; */ +#define FXGMAC_MSIX_INTCTRL_EN 1 + +#define FXGMAC_PHY_INT_NUM 1 +#define FXGMAC_MSIX_INT_NUMS (FXGMAC_MAX_MSIX_Q_VECTORS + FXGMAC_PHY_INT_NUM) +#else /* for case of no CONFIG_PCI_MSI */ +/* NO modification needed! for non-MSI, set to 0 always */ +#define FXGMAC_MSIX_CH0RXDIS_EN 0 +#define FXGMAC_MSIX_INTCTRL_EN 0 +#endif + +/*RSS features*/ +#ifdef FXGMAC_ONE_CHANNEL +#define FXGMAC_RSS_FEATURE_ENABLED 0 /* 1:enable rss ; 0: rss not included. */ +#else +#define FXGMAC_RSS_FEATURE_ENABLED 1 /* 1:enable rss ; 0: rss not included. */ +#endif +#define FXGMAC_RSS_HASH_KEY_LINUX 1 /* 0:hard to default rss key ;1: normal hash key process from Linux. */ + +/*WOL features*/ +#define FXGMAC_WOL_FEATURE_ENABLED 1 /* 1:enable wol ; 0: wol not included. */ +/*since wol upon link will cause issue, disabled it always. */ +#define FXGMAC_WOL_UPON_EPHY_LINK 1 /* 1:enable ephy link change wol ; 0: ephy link change wol is not supported. */ + +/*Pause features*/ +#define FXGMAC_PAUSE_FEATURE_ENABLED 1 /* 1:enable flow control/pause framce ; 0: flow control/pause frame not included. */ + +/*ARP offload engine (AOE)*/ +#define FXGMAC_AOE_FEATURE_ENABLED 1 /* 1:enable arp offload engine ; 0: aoe is not included. */ + +/*NS offload engine*/ +#define FXGMAC_NS_OFFLOAD_ENABLED 1 /* 1:enable NS offload for IPv6 ; 0: NS is not included. */ + +/*for fpga ver after, which needs release phy before set of MAC tx/rx */ +#define FXGMAC_TXRX_EN_AFTER_PHY_RELEASE 1 /* 1:release ephy before mac tx/rx bits are set. */ + +/*power management features*/ +#define FXGMAC_PM_FEATURE_ENABLED 1 /* 1:enable PM ; 0: PM not included. */ + +/*sanity check*/ +#define FXGMAC_SANITY_CHECK_ENABLED 0 /* 1:enable health checking; */ + +/*vlan id filter*/ +#define FXGMAC_FILTER_SINGLE_VLAN_ENABLED 1 /* 1:enable health checking; */ +#define FXGMAC_FILTER_MULTIPLE_VLAN_ENABLED 1 +#define FUXI_MAC_HASH_TABLE 1 +#define FXGMAC_FILTER_MULTIPLE_MAC_ADDR_ENABLED 1 +#define FUXI_MISC_INT_HANDLE_FEATURE_EN 1 + +#define HAVE_FXGMAC_DEBUG_FS + +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &(((TYPE *)0)->MEMBER)) +#endif + +#define ETH_IS_ZEROADDRESS(Address) \ + ((((u8 *)(Address))[0] == ((u8)0x00)) \ + && (((u8 *)(Address))[1] == ((u8)0x00)) \ + && (((u8 *)(Address))[2] == ((u8)0x00)) \ + && (((u8 *)(Address))[3] == ((u8)0x00)) \ + && (((u8 *)(Address))[4] == ((u8)0x00)) \ + && (((u8 *)(Address))[5] == ((u8)0x00))) + + /* read from 8bit register via pci config space */ +#define cfg_r8(_pdata, reg, pdat) pci_read_config_byte((_pdata)->pdev, (reg), (u8 *)(pdat)) + + /* read from 16bit register via pci config space */ +#define cfg_r16(_pdata, reg, pdat) pci_read_config_word((_pdata)->pdev, (reg), (u16 *)(pdat)) + + /* read from 32bit register via pci config space */ +#define cfg_r32(_pdata, reg, pdat) pci_read_config_dword((_pdata)->pdev, (reg), (u32 *)(pdat)) + +/* write to 8bit register via pci config space */ +#define cfg_w8(_pdata, reg, val) pci_write_config_byte((_pdata)->pdev, (reg), (u8)(val)) + +/* write to 16bit register via pci config space */ +#define cfg_w16(_pdata, reg, val) pci_write_config_word((_pdata)->pdev, (reg), (u16)(val)) + +/* write to 32bit register via pci config space */ +#define cfg_w32(_pdata, reg, val) pci_write_config_dword((_pdata)->pdev, (reg), (u32)(val)) + +#define readreg(pAdapter, addr) (readl(addr)) +#define writereg(pAdapter, val, addr) (writel(val, addr)) +#define usleep_range_ex(pAdapter, a, b) (usleep_range(a, b)) +#define _CR(Record, TYPE, Field) ((TYPE *) ((char *) (Record) - (char *) &(((TYPE *) 0)->Field))) + +#define FXGMAC_GET_REG_BITS(var, pos, len) ({ \ + typeof(pos) _pos = (pos); \ + typeof(len) _len = (len); \ + ((var) & GENMASK(_pos + _len - 1, _pos)) >> (_pos); \ +}) + +#define FXGMAC_GET_REG_BITS_LE(var, pos, len) ({ \ + typeof(pos) _pos = (pos); \ + typeof(len) _len = (len); \ + typeof(var) _var = le32_to_cpu((var)); \ + ((_var) & GENMASK(_pos + _len - 1, _pos)) >> (_pos); \ +}) + +#define FXGMAC_SET_REG_BITS(var, pos, len, val) ({ \ + typeof(var) _var = (var); \ + typeof(pos) _pos = (pos); \ + typeof(len) _len = (len); \ + typeof(val) _val = (val); \ + _val = (_val << _pos) & GENMASK(_pos + _len - 1, _pos); \ + _var = (_var & ~GENMASK(_pos + _len - 1, _pos)) | _val; \ +}) + +#define FXGMAC_SET_REG_BITS_LE(var, pos, len, val) ({ \ + typeof(var) _var = (var); \ + typeof(pos) _pos = (pos); \ + typeof(len) _len = (len); \ + typeof(val) _val = (val); \ + _val = (_val << _pos) & GENMASK(_pos + _len - 1, _pos); \ + _var = (_var & ~GENMASK(_pos + _len - 1, _pos)) | _val; \ + cpu_to_le32(_var); \ +}) + +#define STR_FORMAT "%s" + +#define DbgPrintF(level, fmt, ...) +#define DBGPRINT(Level, Fmt) +#define DBGPRINT_RAW(Level, Fmt) +#define DBGPRINT_S(Status, Fmt) +#define DBGPRINT_UNICODE(Level, UString) +#define Dump(p, cb, fAddress, ulGroup) + +#undef ASSERT +#define ASSERT(x) + +#define DbgPrintOidName(_Oid) +#define DbgPrintAddress(_pAddress) + +#define fxgmac_dump_buffer(_skb, _len, _tx_rx) +#define DumpLine(_p, _cbLine, _fAddress, _ulGroup) + +#ifndef FXGMAC_DEBUG +#define FXGMAC_DEBUG +#endif + +/* For debug prints */ +#ifdef FXGMAC_DEBUG +#define FXGMAC_PR(fmt, args...) \ + pr_alert("[%s,%d]:" fmt, __func__, __LINE__, ## args) + +#define DPRINTK printk +#else +#define FXGMAC_PR(x...) do { } while (0) +#define DPRINTK(x...) +#endif + +#define IOC_MAGIC 'M' +#define IOC_MAXNR (0x80 + 5) + +#define FUXI_DFS_IOCTL_DEVICE_INACTIVE 0x10001 +#define FUXI_DFS_IOCTL_DEVICE_RESET 0x10002 +#define FUXI_DFS_IOCTL_DIAG_BEGIN 0x10003 +#define FUXI_DFS_IOCTL_DIAG_END 0x10004 +#define FUXI_DFS_IOCTL_DIAG_TX_PKT 0x10005 +#define FUXI_DFS_IOCTL_DIAG_RX_PKT 0x10006 + +#define FXGMAC_EFUSE_UPDATE_LED_CFG 0x10007 +#define FXGMAC_EFUSE_WRITE_LED 0x10008 +#define FXGMAC_EFUSE_WRITE_PATCH_REG 0x10009 +#define FXGMAC_EFUSE_WRITE_PATCH_PER_INDEX 0x1000A +#define FXGMAC_EFUSE_WRITE_OOB 0x1000B +#define FXGMAC_EFUSE_LOAD 0x1000C +#define FXGMAC_EFUSE_READ_REGIONABC 0x1000D +#define FXGMAC_EFUSE_READ_PATCH_REG 0x1000E +#define FXGMAC_EFUSE_READ_PATCH_PER_INDEX 0x1000F +#define FXGMAC_EFUSE_LED_TEST 0x10010 + +#define FXGMAC_GET_MAC_DATA 0x10011 +#define FXGMAC_SET_MAC_DATA 0x10012 +#define FXGMAC_GET_SUBSYS_ID 0x10013 +#define FXGMAC_SET_SUBSYS_ID 0x10014 +#define FXGMAC_GET_GMAC_REG 0x10015 +#define FXGMAC_SET_GMAC_REG 0x10016 +#define FXGMAC_GET_PHY_REG 0x10017 +#define FXGMAC_SET_PHY_REG 0x10018 +#define FXGMAC_EPHYSTATISTICS 0x10019 +#define FXGMAC_GET_STATISTICS 0x1001A +#define FXGMAC_GET_PCIE_LOCATION 0x1001B + +#define FXGMAC_GET_GSO_SIZE 0x1001C +#define FXGMAC_SET_GSO_SIZE 0x1001D +#define FXGMAC_SET_RX_MODERATION 0x1001E +#define FXGMAC_SET_TX_MODERATION 0x1001F +#define FXGMAC_GET_TXRX_MODERATION 0x10020 + +#define MAX_PKT_BUF 1 +#define FXGAMC_MAX_DATA_SIZE (1024 * 4 + 16) + +#ifndef PCI_CAP_ID_MSI +#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */ +#endif + +#ifndef PCI_CAP_ID_MSIX +#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ +#endif + +#define PCI_CAP_ID_MSI_ENABLE_POS 0x10 +#define PCI_CAP_ID_MSI_ENABLE_LEN 0x1 +#define PCI_CAP_ID_MSIX_ENABLE_POS 0x1F +#define PCI_CAP_ID_MSIX_ENABLE_LEN 0x1 + +#ifndef fallthrough +#if __has_attribute(__fallthrough__) +# define fallthrough __attribute__((__fallthrough__)) +#else +# define fallthrough do {} while (0) /* fallthrough */ +#endif +#endif + + +#pragma pack(1) +/* it's better to make this struct's size to 128byte. */ +struct pattern_packet{ + u8 ether_daddr[ETH_ALEN]; + u8 ether_saddr[ETH_ALEN]; + u16 ether_type; + + __be16 ar_hrd; /* format of hardware address */ + __be16 ar_pro; /* format of protocol */ + unsigned char ar_hln; /* length of hardware address */ + unsigned char ar_pln; /* length of protocol address */ + __be16 ar_op; /* ARP opcode (command) */ + unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */ + unsigned char ar_sip[4]; /* sender IP address */ + unsigned char ar_tha[ETH_ALEN]; /* target hardware address */ + unsigned char ar_tip[4]; /* target IP address */ + + u8 reverse[86]; +}; +#pragma pack() + +typedef enum { + CURRENT_STATE_SHUTDOWN = 0, + CURRENT_STATE_RESUME = 1, + CURRENT_STATE_INIT = 2, + CURRENT_STATE_SUSPEND = 3, + CURRENT_STATE_CLOSE = 4, + CURRENT_STATE_OPEN = 5, + CURRENT_STATE_RESTART = 6, + CURRENT_STATE_REMOVE = 7, +} CURRENT_STATE; + +typedef dma_addr_t DMA_ADDR_T; +typedef enum pkt_hash_types RSS_HASH_TYPE; +typedef void __iomem *IOMEM; +typedef struct pci_dev PCI_DEV; + +struct ext_command_buf { + void *buf; + u32 size_in; + u32 size_out; +}; + +struct ext_command_mac { + u32 num; + union { + u32 val32; + u16 val16; + u8 val8; + }; +}; + +struct ext_command_mii { + u16 dev; + u16 num; + u16 val; +}; + +struct ext_ioctl_data { + u32 cmd_type; + struct ext_command_buf cmd_buf; +}; + +typedef struct _fxgmac_test_buf { + u8 *addr; + u32 offset; + u32 length; +} fxgmac_test_buf, *pfxgmac_test_buf; + +typedef struct _fxgmac_test_packet { + struct _fxgmac_test_packet *next; + u32 length; /* total length of the packet(buffers) */ + u32 type; /* packet type, vlan, ip checksum, TSO, etc. */ + + fxgmac_test_buf buf[MAX_PKT_BUF]; + fxgmac_test_buf sGList[MAX_PKT_BUF]; + u16 vlanID; + u16 mss; + u32 hash; + u16 cpuNum; + u16 xsum; /* rx, ip-payload checksum */ + u16 csumStart; /* custom checksum offset to the mac-header */ + u16 csumPos; /* custom checksom position (to the mac_header) */ + void *upLevelReserved[4]; + void *lowLevelReserved[4]; +} fxgmac_test_packet, *pfxgmac_test_packet; + +typedef struct fxgmac_channel_of_platform { + char dma_irq_name[IFNAMSIZ + 32]; + + /* for MSIx to match the type of struct msix_entry.vector */ + u32 dma_irq_tx; + char dma_irq_name_tx[IFNAMSIZ + 32]; + + /* Netdev related settings */ + struct napi_struct napi_tx; + + /* Netdev related settings */ + struct napi_struct napi_rx; + struct timer_list tx_timer; + +#if FXGMAC_TX_HANG_TIMER_EN + unsigned int tx_hang_timer_active; + struct timer_list tx_hang_timer; + unsigned int tx_hang_hw_cur; +#endif +} FXGMAC_CHANNEL_OF_PLATFORM; + +typedef struct per_regisiter_info { + unsigned int size; + unsigned int address; + unsigned int value; + unsigned char data[FXGAMC_MAX_DATA_SIZE]; +} PER_REG_INFO; + +/* for FXGMAC_EFUSE_WRITE_PATCH_PER_INDEX, val0 is index, val1 is offset, + * val2 is value. + */ +typedef struct ext_command_data { + u32 val0; + u32 val1; + u32 val2; +} CMD_DATA; + +typedef struct fxgmac_pdata_of_platform { + u32 cfg_pci_cmd; + u32 cfg_cache_line_size; + u32 cfg_mem_base; + u32 cfg_mem_base_hi; + u32 cfg_io_base; + u32 cfg_int_line; + u32 cfg_device_ctrl1; + u32 cfg_pci_link_ctrl; + u32 cfg_device_ctrl2; + u32 cfg_msix_capability; + + struct work_struct restart_work; + u32 int_flags; /* legacy, msi or msix */ + int phy_irq; +#ifdef CONFIG_PCI_MSI + struct msix_entry *msix_entries; +#endif + + /* power management and wol*/ + u32 wol; /* wol options */ + unsigned long powerstate; /* power state */ + unsigned int ns_offload_tab_idx; /* for ns-offload table. 2 entries supported. */ + CURRENT_STATE current_state; + netdev_features_t netdev_features; + struct napi_struct napi; + struct napi_struct napi_phy; + u32 mgm_intctrl_val; + bool phy_link; + bool fxgmac_test_tso_flag; + u32 fxgmac_test_tso_seg_num; + u32 fxgmac_test_last_tso_len; + u32 fxgmac_test_packet_len; + volatile u32 fxgmac_test_skb_arr_in_index; + volatile u32 fxgmac_test_skb_arr_out_index; + struct sk_buff *fxgmac_test_skb_array[FXGMAC_MAX_DBG_TEST_PKT]; +#ifdef HAVE_FXGMAC_DEBUG_FS + struct dentry *dbg_adapter; + struct dentry *fxgmac_dbg_root; + char fxgmac_dbg_netdev_ops_buf[FXGMAC_NETDEV_OPS_BUF_LEN]; +#endif +} FXGMAC_PDATA_OF_PLATFORM; + +void fxgmac_print_pkt(struct net_device *netdev, struct sk_buff *skb, + bool tx_rx); +int fxgmac_dismiss_all_int(struct fxgmac_pdata *pdata); + +#ifdef HAVE_FXGMAC_DEBUG_FS +void fxgmac_dbg_adapter_init(struct fxgmac_pdata *pdata); +void fxgmac_dbg_adapter_exit(struct fxgmac_pdata *pdata); +void fxgmac_dbg_init(struct fxgmac_pdata *pdata); +void fxgmac_dbg_exit(struct fxgmac_pdata *pdata); +#endif /* HAVE_FXGMAC_DEBUG_FS */ + +void fxgmac_restart_dev(struct fxgmac_pdata *pdata); +long fxgmac_dbg_netdev_ops_ioctl(struct file *file, unsigned int cmd, + unsigned long arg); + +int fxgmac_init(struct fxgmac_pdata *pdata, bool save_private_reg); +/* for phy interface */ +int fxgmac_ephy_autoneg_ability_get(struct fxgmac_pdata *pdata, + unsigned int *cap_mask); +int fxgmac_ephy_status_get(struct fxgmac_pdata *pdata, int *speed, + int *duplex, int *ret_link, int *media); +int fxgmac_ephy_soft_reset(struct fxgmac_pdata *pdata); +void fxgmac_phy_force_speed(struct fxgmac_pdata *pdata, int speed); +void fxgmac_phy_force_duplex(struct fxgmac_pdata *pdata, int duplex); +void fxgmac_phy_force_autoneg(struct fxgmac_pdata *pdata, int autoneg); + +unsigned int fxgmac_get_netdev_ip4addr(struct fxgmac_pdata *pdata); +unsigned char *fxgmac_get_netdev_ip6addr(struct fxgmac_pdata *pdata, + unsigned char *ipval, + unsigned char *ip6addr_solicited, + unsigned int ifa_flag); + +#if FXGMAC_PM_FEATURE_ENABLED +void fxgmac_net_powerdown(struct fxgmac_pdata *pdata, unsigned int wol); +void fxgmac_net_powerup(struct fxgmac_pdata *pdata); +#endif + +inline unsigned int fxgmac_tx_avail_desc(struct fxgmac_ring *ring); +inline unsigned int fxgmac_rx_dirty_desc(struct fxgmac_ring *ring); +int fxgmac_start(struct fxgmac_pdata *pdata); +void fxgmac_stop(struct fxgmac_pdata *pdata); +void fxgmac_free_rx_data(struct fxgmac_pdata *pdata); +void fxgmac_free_tx_data(struct fxgmac_pdata *pdata); + +#endif /* __FUXI_OS_H__ */