net: ethernet: motorcomm: Add yt6801 driver
This commit is contained in:
parent
7890b44243
commit
7dcad4642c
|
|
@ -43,6 +43,7 @@ source "drivers/net/ethernet/chelsio/Kconfig"
|
|||
source "drivers/net/ethernet/cirrus/Kconfig"
|
||||
source "drivers/net/ethernet/cisco/Kconfig"
|
||||
source "drivers/net/ethernet/cortina/Kconfig"
|
||||
source "drivers/net/ethernet/motorcomm/Kconfig"
|
||||
|
||||
config CX_ECAT
|
||||
tristate "Beckhoff CX5020 EtherCAT master support"
|
||||
|
|
|
|||
|
|
@ -95,3 +95,4 @@ obj-$(CONFIG_NET_VENDOR_XILINX) += xilinx/
|
|||
obj-$(CONFIG_NET_VENDOR_XIRCOM) += xircom/
|
||||
obj-$(CONFIG_NET_VENDOR_SYNOPSYS) += synopsys/
|
||||
obj-$(CONFIG_NET_VENDOR_PENSANDO) += pensando/
|
||||
obj-$(CONFIG_NET_VENDOR_MOTORCOMM) += motorcomm/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config NET_VENDOR_MOTORCOMM
|
||||
bool "Motorcomm devices"
|
||||
default y
|
||||
help
|
||||
If you have a network (Ethernet) device 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 devices. If you say Y, you will be asked
|
||||
for your specific device in the following questions.
|
||||
|
||||
if NET_VENDOR_MOTORCOMM
|
||||
|
||||
config FUXI
|
||||
tristate "motorcomm fuxi Ethernet support"
|
||||
|
||||
endif #NET_VENDOR_MOTORCOMM
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
# SUBARCH tells the usermode build what the underlying arch is. That is set
|
||||
# first, and if a usermode build is happening, the "ARCH=um" on the command
|
||||
# line overrides the setting of ARCH below. If a native build is happening,
|
||||
# then ARCH is assigned, getting whatever value it gets normally, and
|
||||
# SUBARCH is subsequently ignored.
|
||||
# eg:
|
||||
# x86(make modules or make)
|
||||
# arm(make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules)
|
||||
SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/s390x/s390/ -e s/parisc64/parisc/ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ -e s/riscv.*/riscv/)
|
||||
CURARCH ?= $(SUBARCH)
|
||||
ARCH ?= $(SUBARCH)
|
||||
CROSS_COMPILE ?=
|
||||
CONFIG_MODULE_SIG=n
|
||||
EXTRA_CFLAGS = -Wall -g -I$(CURDIR) -I$(subst fuxi-linux-release-package/module_fuxi/src,common,$(PWD)) -I$(PWD)
|
||||
EXTRA_CFLAGS += -DFXGMAC_DEBUG
|
||||
KSRC = /lib/modules/`uname -r`/build
|
||||
KDST = /lib/modules/`uname -r`/kernel/drivers/net/ethernet/motorcomm/
|
||||
KFILE = yt6801.ko
|
||||
ifneq ($(filter arm arm64, $(ARCH)),)
|
||||
ifeq ($(CURARCH), x86)
|
||||
# if you want to compile driver with linux kernel source code,you should specify the source path(KSRC), such as:
|
||||
# KSRC = /home/mxl/ti-processor-sdk-linux-am57xx-evm-06.03.00.106/board-support/linux-4.19.94+gitAUTOINC+be5389fd85-gbe5389fd85
|
||||
endif
|
||||
endif
|
||||
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
|
||||
obj-m += yt6801.o
|
||||
modules:
|
||||
make -C $(KSRC) M=$(PWD) modules
|
||||
install:
|
||||
sudo install -d $(KDST)
|
||||
sudo install $(KFILE) $(KDST)
|
||||
sudo depmod -a
|
||||
@file $(KDST)$(KFILE)
|
||||
@echo install done.
|
||||
uninstall:
|
||||
sudo rm $(KDST)$(KFILE)
|
||||
sudo ls -l $(KDST)
|
||||
clean:
|
||||
make -C $(KSRC) M=$(PWD) clean
|
||||
.PHONY:modules install uninstall clean
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
obj-$(CONFIG_FUXI) += fuxi.o
|
||||
fuxi-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
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
=============================================================================
|
||||
|
||||
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.
|
||||
|
||||
=============================================================================
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
PACKAGE_NAME="yt6801"
|
||||
PACKAGE_VERSION="1.0.21"
|
||||
CLEAN="make clean"
|
||||
MAKE[0]="make"
|
||||
BUILT_MODULE_NAME[0]="yt6801"
|
||||
DEST_MODULE_LOCATION[0]="/kernel/drivers/motorcomm"
|
||||
AUTOINSTALL="yes"
|
||||
|
|
@ -0,0 +1,520 @@
|
|||
/*++
|
||||
|
||||
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-os.h"
|
||||
|
||||
#if defined(UEFI)
|
||||
#include <Library/UefiLib.h>
|
||||
#include "fuxi-dbg.h"
|
||||
|
||||
|
||||
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 "precomp.h"
|
||||
#include <ntddk.h>
|
||||
#include <ndis.h>
|
||||
#include <stdio.h>
|
||||
#include "fuxi-gmac-reg.h"
|
||||
#include "fuxi-dbg.h"
|
||||
#include "fuxi-gmac.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 = 0; // 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!", __FUNCTION__, 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"].", __FUNCTION__,
|
||||
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)
|
||||
#include "fuxi-dbg.h"
|
||||
#ifdef DBG
|
||||
u32 MPDebugLevel = MP_LOUD;
|
||||
#endif
|
||||
#else
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,271 @@
|
|||
/*++
|
||||
|
||||
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
|
||||
#include "fuxi-os.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
|
||||
|
||||
#if defined(UEFI)
|
||||
|
||||
//#pragma warning(disable:4100) //warning C4100: 'xxx': unreferenced formal parameter
|
||||
//#pragma warning(disable:4101) //warning C4101: 'xxx': unreferenced local variable
|
||||
//#pragma warning(disable:4189) //warning C4189: 'xxx': local variable is initialized but not referenced
|
||||
//#pragma warning(disable:4213) //warning C4213: nonstandard extension used: cast on l-value.
|
||||
//#pragma warning(disable:4201) //warning C4201: nonstandard extension used: nameless struct/union
|
||||
|
||||
#define NIC_DBG_STRING "FUXI: "
|
||||
#define STR_FORMAT "%a"
|
||||
extern UINT32 MPDebugLevel;
|
||||
#if DBG
|
||||
#define DbgPrintF(level, ...) \
|
||||
{ \
|
||||
if (level <= MPDebugLevel) \
|
||||
{ \
|
||||
AsciiPrint(NIC_DBG_STRING ##__VA_ARGS__); \
|
||||
AsciiPrint("\n"); \
|
||||
} \
|
||||
}
|
||||
#define DBGPRINT(Level, Fmt) \
|
||||
{ \
|
||||
if (Level <= MPDebugLevel) \
|
||||
{ \
|
||||
/*DbgPrint(NIC_DBG_STRING);*/ \
|
||||
AsciiPrint Fmt; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define DBGPRINT(Level, Fmt)
|
||||
#define DbgPrintF(level, ...)
|
||||
#endif
|
||||
#define DBGPRINT_RAW(Level, Fmt)
|
||||
#define DBGPRINT_S(Status, Fmt)
|
||||
#define DBGPRINT_UNICODE(Level, UString)
|
||||
#define Dump(p,cb,fAddress,ulGroup)
|
||||
|
||||
void fxgmac_dump_buffer(unsigned char *skb, unsigned int len, int tx_rx);
|
||||
|
||||
#elif defined(_WIN64) || defined(_WIN32)
|
||||
|
||||
//#pragma warning(disable:4100) //warning C4100: 'xxx': unreferenced formal parameter
|
||||
//#pragma warning(disable:4101) //warning C4101: 'xxx': unreferenced local variable
|
||||
//#pragma warning(disable:4189) //warning C4189: 'xxx': local variable is initialized but not referenced
|
||||
//#pragma warning(disable:4213) //warning C4213: nonstandard extension used: cast on l-value.
|
||||
#pragma warning(disable:4201) //warning C4201: nonstandard extension used: nameless struct/union
|
||||
|
||||
#define STR_FORMAT "%s"
|
||||
// Define a macro so DbgPrint can work on win9x, 32-bit/64-bit NT's
|
||||
#ifdef _WIN64
|
||||
#define PTR_FORMAT "%p"
|
||||
#else
|
||||
#define PTR_FORMAT "%x"
|
||||
#endif
|
||||
|
||||
#define NIC_TAG ((ULONG)'FUXI')
|
||||
#define NIC_DBG_STRING "FUXI: "
|
||||
|
||||
|
||||
#if DBG
|
||||
|
||||
extern ULONG MPDebugLevel;
|
||||
extern BOOLEAN MPInitDone;
|
||||
extern NDIS_SPIN_LOCK MPMemoryLock;
|
||||
|
||||
#define DbgPrintF(Level, ...) \
|
||||
{ \
|
||||
if (Level <= MPDebugLevel) \
|
||||
{ \
|
||||
DbgPrint(NIC_DBG_STRING ##__VA_ARGS__); \
|
||||
DbgPrint("\n"); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DBGPRINT(Level, Fmt) \
|
||||
{ \
|
||||
if (Level <= MPDebugLevel) \
|
||||
{ \
|
||||
/*DbgPrint(NIC_DBG_STRING);*/ \
|
||||
DbgPrint Fmt; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DBGPRINT_RAW(Level, Fmt) \
|
||||
{ \
|
||||
if (Level <= MPDebugLevel) \
|
||||
{ \
|
||||
DbgPrint Fmt; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DBGPRINT_S(Status, Fmt) \
|
||||
{ \
|
||||
ULONG dbglevel; \
|
||||
if(Status == NDIS_STATUS_SUCCESS || Status == NDIS_STATUS_PENDING) dbglevel = MP_TRACE; \
|
||||
else dbglevel = MP_ERROR; \
|
||||
DBGPRINT(dbglevel, Fmt); \
|
||||
}
|
||||
|
||||
#define DBGPRINT_UNICODE(Level, UString) \
|
||||
{ \
|
||||
if (Level <= MPDebugLevel) \
|
||||
{ \
|
||||
/* DbgPrint(NIC_DBG_STRING); */ \
|
||||
mpDbgPrintUnicodeString(UString); \
|
||||
} \
|
||||
}
|
||||
|
||||
#undef ASSERT
|
||||
#define ASSERT(x) if(!(x)) { \
|
||||
DBGPRINT(MP_ERROR, ("Assertion failed: %s:%d %s\n", __FILE__, __LINE__, #x)); \
|
||||
/*DbgBreakPoint();*/ }
|
||||
|
||||
VOID
|
||||
DbgPrintOidName(
|
||||
_In_ NDIS_OID Oid
|
||||
);
|
||||
|
||||
VOID
|
||||
DbgPrintAddress(
|
||||
_In_reads_bytes_(ETH_LENGTH_OF_ADDRESS) PUCHAR Address)
|
||||
;
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(16)
|
||||
//
|
||||
// The MP_ALLOCATION structure stores all info about MPAuditAllocMemTag
|
||||
//
|
||||
typedef struct _MP_ALLOCATION
|
||||
{
|
||||
LIST_ENTRY List;
|
||||
ULONG Signature;
|
||||
CHAR* FileNumber;
|
||||
ULONG LineNumber;
|
||||
ULONG Size;
|
||||
ULONGLONG dummy; // for 64 bit alignment
|
||||
union {
|
||||
ULONGLONG Alignment;
|
||||
UCHAR UserData;
|
||||
};
|
||||
} MP_ALLOCATION, *PMP_ALLOCATION;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
PVOID
|
||||
MPAuditAllocMemTag(
|
||||
UINT Size,
|
||||
CHAR* FileNumber,
|
||||
ULONG LineNumber,
|
||||
NDIS_HANDLE MiniportAdapterHandle
|
||||
);
|
||||
|
||||
VOID MPAuditFreeMem(
|
||||
PVOID Pointer
|
||||
);
|
||||
|
||||
VOID mpDbgPrintUnicodeString(
|
||||
IN PUNICODE_STRING UnicodeString);
|
||||
|
||||
|
||||
VOID
|
||||
Dump(
|
||||
__in_bcount(cb) CHAR* p,
|
||||
ULONG cb,
|
||||
BOOLEAN fAddress,
|
||||
ULONG ulGroup );
|
||||
|
||||
void fxgmac_dump_buffer(unsigned char* skb, unsigned int len, int tx_rx);
|
||||
|
||||
VOID
|
||||
DumpLine(
|
||||
__in_bcount(cb) CHAR* p,
|
||||
ULONG cb,
|
||||
BOOLEAN fAddress,
|
||||
ULONG ulGroup);
|
||||
|
||||
|
||||
#else // !DBG
|
||||
|
||||
#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 )
|
||||
#endif // DBG
|
||||
|
||||
#elif defined(LINUX)
|
||||
|
||||
#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 )
|
||||
|
||||
#elif defined(UBOOT)
|
||||
#ifdef UBOOT_DEBUG
|
||||
extern u32 MPDebugLevel;
|
||||
#define NIC_DBG_STRING "YT6801: "
|
||||
#define STR_FORMAT "%s"
|
||||
#define PTR_FORMAT "%x"
|
||||
//#define DBGPRINT(Level, Fmt) printf Fmt
|
||||
#define DbgPrintF(Level, fmt, args...) \
|
||||
{ \
|
||||
if (Level <= MPDebugLevel) \
|
||||
{ \
|
||||
printf(NIC_DBG_STRING fmt,##args); \
|
||||
printf("\n"); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define DbgPrintF(Level, ...)
|
||||
#endif
|
||||
#else
|
||||
|
||||
//#pragma warning(disable:4100) //warning C4100: 'xxx': unreferenced formal parameter
|
||||
//#pragma warning(disable:4101) //warning C4101: 'xxx': unreferenced local variable
|
||||
//#pragma warning(disable:4189) //warning C4189: 'xxx': local variable is initialized but not referenced
|
||||
//#pragma warning(disable:4213) //warning C4213: nonstandard extension used: cast on l-value.
|
||||
#pragma warning(disable:4201) //warning C4201: nonstandard extension used: nameless struct/union
|
||||
#pragma warning(disable:4002) //warning C4002: too many actual parameters for macro
|
||||
|
||||
|
||||
#endif // ifdef UEFI.
|
||||
|
||||
#endif // _MP_DBG_H
|
||||
|
|
@ -0,0 +1,972 @@
|
|||
|
||||
/*++
|
||||
|
||||
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"
|
||||
#if defined(UEFI)
|
||||
#include "nic_sw.h"
|
||||
#elif defined(LINUX)
|
||||
#elif defined(_WIN32) || defined(_WIN64)
|
||||
#elif defined(UBOOT)
|
||||
#include "fuxi-dbg.h"
|
||||
#else
|
||||
#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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
/*++
|
||||
|
||||
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__
|
||||
|
|
@ -0,0 +1,935 @@
|
|||
/*++
|
||||
|
||||
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 <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#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)");
|
||||
/*yz comments out 0425
|
||||
static const */
|
||||
u32 default_msg_level = 0;
|
||||
/*(NETIF_MSG_LINK | NETIF_MSG_IFDOWN |
|
||||
NETIF_MSG_IFUP);
|
||||
*/
|
||||
|
||||
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;
|
||||
DPRINTK("read mac from eFuse\n");
|
||||
|
||||
// if efuse have mac addr,use it.if not,use static mac address.
|
||||
fxgmac_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;
|
||||
#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;
|
||||
|
||||
strlcpy(pdata->drv_name, FXGMAC_DRV_NAME, sizeof(pdata->drv_name));
|
||||
strlcpy(pdata->drv_ver, FXGMAC_DRV_VERSION, sizeof(pdata->drv_ver));
|
||||
|
||||
DPRINTK("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 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);
|
||||
memcpy(netdev->dev_addr, pdata->mac_addr, netdev->addr_len);
|
||||
|
||||
/* Set all the function pointers */
|
||||
fxgmac_init_all_ops(pdata);
|
||||
|
||||
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 = FXGMAC_MSIX_Q_VECTORS;
|
||||
#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
|
||||
fxgmac_read_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->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;
|
||||
}
|
||||
|
||||
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;
|
||||
pdata->int_flags = 0; //default legacy
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
pdata->int_flags = pcidev_int_mode;
|
||||
|
||||
//20210526 for MSIx
|
||||
if(pdata->int_flags & (FXGMAC_FLAG_MSIX_CAPABLE | FXGMAC_FLAG_MSIX_ENABLED)) {
|
||||
pdata->p_msix_entries = msix_entries;
|
||||
pdata->num_msix_vectors = req_vectors;
|
||||
pdata->per_channel_irq = 1;
|
||||
} else if (pdata->int_flags & (FXGMAC_FLAG_MSI_CAPABLE | FXGMAC_FLAG_MSI_ENABLED)) {
|
||||
pdata->dev_irq = pdata->pdev->irq;
|
||||
}
|
||||
#endif
|
||||
pdata->current_state = CURRENT_STATE_INIT;
|
||||
|
||||
//pdata->msg_enable = netif_msg_init(debug, default_msg_level);
|
||||
//pdata->msg_enable = NETIF_MSG_DRV | NETIF_MSG_RX_STATUS | NETIF_MSG_PKTDATA; //base info only
|
||||
//pdata->msg_enable = NETIF_MSG_DRV | NETIF_MSG_TX_DONE; //base info only
|
||||
pdata->msg_enable = NETIF_MSG_DRV;
|
||||
DPRINTK("fxgamc_drv_prob netif msg_enable init to %08x,netif_msg_rx_status=%d,netif_msg_pktdata=%d\n", pdata->msg_enable, netif_msg_rx_status(pdata), netif_msg_pktdata(pdata));
|
||||
|
||||
pdata->mac_regs = res->addr;
|
||||
pdata->base_mem = res->addr;
|
||||
pdata->mac_regs = pdata->mac_regs + FUXI_MAC_REGS_OFFSET;//0x3000/* asic implement */;
|
||||
if(netif_msg_drv(pdata)) DPRINTK("drv_probe, pdata base_mem=%p, mac_regs=%p\n", pdata->base_mem, pdata->mac_regs);
|
||||
//if(netif_msg_drv(pdata)) DPRINTK("drv_probe,base_mem+0x2110=%x, base_mem+0x1000=%x\n", readl(pdata->base_mem + 0x2110), readl(pdata->base_mem + 0x1000));
|
||||
//if(netif_msg_drv(pdata)) DPRINTK("drv_probe,mac_regs+0x110=%x, mac_regs-0x2000+0x1000=%x\n", readl(pdata->mac_regs + 0x110), readl(pdata->mac_regs - 0x1000));
|
||||
|
||||
mutex_init(&pdata->rss_mutex);
|
||||
spin_lock_init(&pdata->txpoll_lock);
|
||||
|
||||
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 ("check mac regs, get offset 0x110,ver=%#x,mac_regs=%p\n", readl(pdata->mac_regs + 0x110), pdata->mac_regs);
|
||||
|
||||
/* 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_RAVSEL_POS,
|
||||
MAC_HWF1R_RAVSEL_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");
|
||||
}
|
||||
|
|
@ -0,0 +1,645 @@
|
|||
/*++
|
||||
|
||||
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"
|
||||
#ifdef HAVE_FXGMAC_DEBUG_FS
|
||||
#include <linux/debugfs.h>
|
||||
#endif
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/socket.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/inet.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/udp.h>
|
||||
|
||||
#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
|
||||
|
||||
//char fxgmac_driver_name[] = "fuxi";
|
||||
static char fxgmac_dbg_netdev_ops_buf[256] = "";
|
||||
|
||||
/**
|
||||
* 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,
|
||||
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(fxgmac_dbg_netdev_ops_buf))
|
||||
return -ENOSPC;
|
||||
|
||||
len = simple_write_to_buffer(fxgmac_dbg_netdev_ops_buf,
|
||||
sizeof(fxgmac_dbg_netdev_ops_buf)-1,
|
||||
ppos,
|
||||
buffer,
|
||||
count);
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
fxgmac_dbg_netdev_ops_buf[len] = '\0';
|
||||
|
||||
if (strncmp(fxgmac_dbg_netdev_ops_buf, "tx_timeout", 10) == 0) {
|
||||
DPRINTK("tx_timeout called\n");
|
||||
} else {
|
||||
FXGMAC_PR("Unknown command: %s\n", 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->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->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->fxgmac_test_last_tso_len = offload_len % skb_shinfo(skb)->gso_size + headTotalLen;
|
||||
}
|
||||
pdata->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->fxgmac_test_packet_len = skb_shinfo(skb)->gso_size + headTotalLen;
|
||||
}else{
|
||||
/* set non-TSO packet parameters */
|
||||
pdata->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;
|
||||
//DPRINTK("FXG:fxgmac_test_skb_arr_in_index=%d, fxgmac_test_skb_arr_out_index=%d", fxgmac_test_skb_arr_in_index, fxgmac_test_skb_arr_out_index);
|
||||
while(pdata->fxgmac_test_skb_arr_in_index != pdata->fxgmac_test_skb_arr_out_index){
|
||||
/* get received skb data */
|
||||
rx_skb = pdata->fxgmac_test_skb_array[pdata->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->fxgmac_test_skb_arr_out_index + 1) % FXGMAC_MAX_DBG_TEST_PKT == pdata->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->fxgmac_test_skb_array[pdata->fxgmac_test_skb_arr_out_index] = NULL;
|
||||
|
||||
/* update gCurSkbOutIndex */
|
||||
pdata->fxgmac_test_skb_arr_out_index = (pdata->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
|
||||
}
|
||||
|
||||
long fxgmac_dbg_netdev_ops_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int ret = FXGMAC_SUCCESS;
|
||||
struct fxgmac_pdata *pdata = file->private_data;
|
||||
struct ext_ioctl_data * pcmd = NULL;
|
||||
int in_total_size, in_data_size, out_total_size;
|
||||
int ioctl_cmd_size = sizeof(struct ext_ioctl_data);
|
||||
struct sk_buff *tmpskb;
|
||||
u8* data = NULL;
|
||||
u8 *buf = (u8*)kzalloc(FXGMAC_MAX_DBG_BUF_LEN, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
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(arg != 0 && copy_from_user((void*)buf, (void*)arg, ioctl_cmd_size))
|
||||
{
|
||||
DPRINTK("copy data from user fail... \n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
pcmd = (struct ext_ioctl_data *)buf;
|
||||
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;
|
||||
data = (u8*)arg + ioctl_cmd_size;
|
||||
#if 0
|
||||
/* check R/W */
|
||||
if (_IOC_DIR(cmd) & _IOC_READ || _IOC_DIR(cmd) & _IOC_WRITE)
|
||||
ret= access_ok((void __user *)arg, _IOC_SIZE(cmd));
|
||||
if (!ret)
|
||||
return -EFAULT;
|
||||
#endif
|
||||
|
||||
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(pdata->fxgmac_test_skb_arr_in_index !=
|
||||
pdata->fxgmac_test_skb_arr_out_index)
|
||||
{
|
||||
tmpskb = pdata->fxgmac_test_skb_array[pdata->fxgmac_test_skb_arr_out_index];
|
||||
if(tmpskb)
|
||||
{
|
||||
kfree_skb(tmpskb);
|
||||
pdata->fxgmac_test_skb_array[pdata->fxgmac_test_skb_arr_out_index] = NULL;
|
||||
}
|
||||
|
||||
pdata->fxgmac_test_skb_arr_out_index = (pdata->fxgmac_test_skb_arr_out_index + 1) % FXGMAC_MAX_DBG_TEST_PKT;
|
||||
}
|
||||
|
||||
/* init loopback test parameters */
|
||||
pdata->fxgmac_test_skb_arr_in_index = 0;
|
||||
pdata->fxgmac_test_skb_arr_out_index = 0;
|
||||
pdata->fxgmac_test_tso_flag = false;
|
||||
pdata->fxgmac_test_tso_seg_num = 0;
|
||||
pdata->fxgmac_test_last_tso_len = 0;
|
||||
pdata->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_PR("Debugfs received diag tx pkt command.\n");
|
||||
if(copy_from_user((void *)buf, (void *)arg, in_total_size))
|
||||
{
|
||||
DPRINTK("copy data from user fail... \n");
|
||||
}
|
||||
fxgmac_dbg_tx_pkt(pdata, buf);
|
||||
//fxgmac_dbg_tx_pkt(pdata, (u8 *)arg);
|
||||
break;
|
||||
|
||||
/* ioctl diag rx pkt */
|
||||
case FUXI_DFS_IOCTL_DIAG_RX_PKT:
|
||||
//DPRINTK("Debugfs received diag rx pkt command.\n")
|
||||
fxgmac_dbg_rx_pkt(pdata, buf);
|
||||
//fxgmac_dbg_rx_pkt(pdata, (u8 *)arg);
|
||||
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");
|
||||
if (copy_from_user(&pdata->led, data, in_data_size))
|
||||
goto err;
|
||||
fxgmac_restart_dev(pdata);
|
||||
break;
|
||||
|
||||
case FXGMAC_EFUSE_UPDATE_LED_CFG:
|
||||
DPRINTK("Debugfs received device led update command.\n");
|
||||
if (copy_from_user(&pdata->ledconfig, data, in_data_size))
|
||||
goto err;
|
||||
ret = pdata->hw_ops.write_led_config(pdata) ? FXGMAC_SUCCESS : FXGMAC_FAIL;
|
||||
pdata->hw_ops.read_led_config(pdata);
|
||||
pdata->hw_ops.led_under_active(pdata);
|
||||
break;
|
||||
|
||||
case FXGMAC_EFUSE_WRITE_LED:
|
||||
if (copy_from_user(&pdata->ex_cmd_data, data, in_data_size))
|
||||
goto err;
|
||||
DPRINTK("FXGMAC_EFUSE_WRITE_LED, val = 0x%x\n", pdata->ex_cmd_data.val0);
|
||||
ret = pdata->hw_ops.write_led(pdata, pdata->ex_cmd_data.val0) ? FXGMAC_SUCCESS : FXGMAC_FAIL;
|
||||
break;
|
||||
|
||||
case FXGMAC_EFUSE_WRITE_OOB:
|
||||
DPRINTK("FXGMAC_EFUSE_WRITE_OOB.\n");
|
||||
ret = pdata->hw_ops.write_oob(pdata) ? FXGMAC_SUCCESS : FXGMAC_FAIL;
|
||||
break;
|
||||
|
||||
case FXGMAC_EFUSE_READ_REGIONABC:
|
||||
if (copy_from_user((void*)buf, (void*)arg, in_total_size))
|
||||
goto err;
|
||||
memcpy(&pdata->ex_cmd_data, (void*)buf + ioctl_cmd_size, in_data_size);
|
||||
ret = pdata->hw_ops.read_efuse_data(pdata, pdata->ex_cmd_data.val0, &pdata->ex_cmd_data.val1) ? FXGMAC_SUCCESS : FXGMAC_FAIL;
|
||||
DPRINTK("FXGMAC_EFUSE_READ_REGIONABC, address = 0x%x, val = 0x%x\n",
|
||||
pdata->ex_cmd_data.val0,
|
||||
pdata->ex_cmd_data.val1);
|
||||
if (ret == FXGMAC_SUCCESS) {
|
||||
memcpy((void*)(buf + ioctl_cmd_size), &pdata->ex_cmd_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:
|
||||
if (copy_from_user(&pdata->ex_cmd_data, data, in_data_size))
|
||||
goto err;
|
||||
DPRINTK("FXGMAC_EFUSE_WRITE_PATCH_REG, address = 0x%x, val = 0x%x\n",
|
||||
pdata->ex_cmd_data.val0,
|
||||
pdata->ex_cmd_data.val1);
|
||||
ret = pdata->hw_ops.write_patch_to_efuse(pdata, pdata->ex_cmd_data.val0, pdata->ex_cmd_data.val1) ? FXGMAC_SUCCESS : FXGMAC_FAIL;
|
||||
break;
|
||||
|
||||
case FXGMAC_EFUSE_READ_PATCH_REG:
|
||||
if (copy_from_user((void*)buf, (void*)arg, in_total_size))
|
||||
goto err;
|
||||
memcpy(&pdata->ex_cmd_data, (void*)buf + ioctl_cmd_size, in_data_size);
|
||||
ret = pdata->hw_ops.read_patch_from_efuse(pdata, pdata->ex_cmd_data.val0, &pdata->ex_cmd_data.val1) ? FXGMAC_SUCCESS : FXGMAC_FAIL;
|
||||
DPRINTK("FXGMAC_EFUSE_READ_PATCH_REG, address = 0x%x, val = 0x%x\n",
|
||||
pdata->ex_cmd_data.val0,
|
||||
pdata->ex_cmd_data.val1);
|
||||
if (ret == FXGMAC_SUCCESS) {
|
||||
memcpy((void*)(buf + ioctl_cmd_size), &pdata->ex_cmd_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:
|
||||
if (copy_from_user(&pdata->per_reg_data, data, in_data_size))
|
||||
goto err;
|
||||
ret = pdata->hw_ops.write_patch_to_efuse_per_index(pdata, pdata->per_reg_data.data[0],
|
||||
pdata->per_reg_data.address,
|
||||
pdata->per_reg_data.value) ? FXGMAC_SUCCESS : FXGMAC_FAIL;
|
||||
DPRINTK("FXGMAC_EFUSE_WRITE_PATCH_PER_INDEX, index = %d, address = 0x%x, val = 0x%x\n",
|
||||
pdata->per_reg_data.data[0],
|
||||
pdata->per_reg_data.address,
|
||||
pdata->per_reg_data.value);
|
||||
break;
|
||||
|
||||
case FXGMAC_EFUSE_READ_PATCH_PER_INDEX:
|
||||
if (copy_from_user((void*)buf, (void*)arg, in_total_size))
|
||||
goto err;
|
||||
memcpy(&pdata->per_reg_data, (void*)buf + ioctl_cmd_size, in_data_size);
|
||||
ret = pdata->hw_ops.read_patch_from_efuse_per_index(pdata, pdata->per_reg_data.data[0],
|
||||
&pdata->per_reg_data.address,
|
||||
&pdata->per_reg_data.value) ? FXGMAC_SUCCESS : FXGMAC_FAIL;
|
||||
DPRINTK("FXGMAC_EFUSE_READ_PATCH_PER_INDEX, address = 0x%x, val = 0x%x\n",
|
||||
pdata->per_reg_data.address,
|
||||
pdata->per_reg_data.value);
|
||||
if (ret == FXGMAC_SUCCESS) {
|
||||
memcpy((void*)(buf + ioctl_cmd_size), &pdata->per_reg_data, sizeof(PER_REG_INFO));
|
||||
out_total_size = ioctl_cmd_size + sizeof(PER_REG_INFO);
|
||||
if (copy_to_user((void*)arg, (void*)buf, out_total_size))
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
|
||||
case FXGMAC_EFUSE_LOAD:
|
||||
DPRINTK("FXGMAC_EFUSE_LOAD.\n");
|
||||
ret = pdata->hw_ops.efuse_load(pdata) ? FXGMAC_SUCCESS : FXGMAC_FAIL;
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINTK("Debugfs received invalid command: %x.\n", pcmd->cmd_type);
|
||||
ret = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (buf)
|
||||
kfree(buf);
|
||||
return ret;
|
||||
|
||||
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->dbg_adapter = debugfs_create_dir(name, pdata->fxgmac_dbg_root);
|
||||
if (pdata->dbg_adapter) {
|
||||
pfile = debugfs_create_file("netdev_ops", 0600,
|
||||
pdata->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->dbg_adapter)
|
||||
debugfs_remove_recursive(pdata->dbg_adapter);
|
||||
pdata->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->fxgmac_dbg_root = debugfs_lookup(file_name, NULL);
|
||||
if (!pdata->fxgmac_dbg_root)
|
||||
{
|
||||
/* create file */
|
||||
pdata->fxgmac_dbg_root = debugfs_create_dir(file_name, NULL);
|
||||
if (IS_ERR(pdata->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->fxgmac_dbg_root)
|
||||
debugfs_remove_recursive(pdata->fxgmac_dbg_root);
|
||||
}
|
||||
|
||||
#endif /* HAVE_XLGMAC_DEBUG_FS */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,504 @@
|
|||
/*++
|
||||
|
||||
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 <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
/* for file operation */
|
||||
#include <linux/fs.h>
|
||||
|
||||
#include "fuxi-gmac.h"
|
||||
#include "fuxi-gmac-reg.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
u32 pcidev_int_mode; // for msix
|
||||
|
||||
//for MSIx, 20210526
|
||||
struct msix_entry *msix_entries = NULL;
|
||||
int req_vectors = 0;
|
||||
#endif
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
/*
|
||||
* since kernel does not clear the MSI mask bits and
|
||||
* this function clear MSI mask bits when MSI is enabled.
|
||||
*/
|
||||
int fxgmac_pci_config_modify(struct pci_dev *pdev)
|
||||
{
|
||||
//struct net_device *netdev = dev_get_drvdata(&pdev->dev);
|
||||
//struct fxgmac_pdata *pdata = netdev_priv(netdev);
|
||||
u16 pcie_cap_offset;
|
||||
u32 pcie_msi_mask_bits;
|
||||
int ret;
|
||||
|
||||
pcie_cap_offset = pci_find_capability(pdev, 0x05 /*MSI Capability ID*/);
|
||||
if (pcie_cap_offset) {
|
||||
ret = pci_read_config_dword(pdev,
|
||||
pcie_cap_offset + 0x10 /* MSI mask bits */,
|
||||
&pcie_msi_mask_bits);
|
||||
if (ret)
|
||||
{
|
||||
DPRINTK(KERN_ERR "fxgmac_pci_config_modify read pci config space MSI cap. failed, %d\n", ret);
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
ret = pci_write_config_word(pdev, pcie_cap_offset + 0xc /* MSI data */, 0x1234/* random val */);
|
||||
ret = pci_write_config_dword(pdev, pcie_cap_offset + 0x10 /* MSI mask bits */, (pcie_msi_mask_bits & 0xffff0000) /*clear mask bits*/);
|
||||
if (ret)
|
||||
{
|
||||
DPRINTK(KERN_ERR "fxgmac_pci_config_modify write pci config space MSI mask failed, %d\n", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
//for MSIx, 20210526
|
||||
int vectors, rc;
|
||||
#endif
|
||||
|
||||
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;
|
||||
/*if (0x100 != pci_resource_len(pcidev, i))
|
||||
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];
|
||||
DPRINTK(KERN_INFO "fxgmac_probe res.addr=%p,val=%#x\n",res.addr,/*(int)(*((int*)(res.addr)))*/0);
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
/* added for MSIx feature, 20210526 */
|
||||
pcidev_int_mode = 0; //init to legacy interrupt, and MSIx has the first priority
|
||||
|
||||
/* 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("fxgmac_probe, num of cpu=%d\n", vectors);
|
||||
if(vectors >= FXGMAC_MAX_DMA_CHANNELS) {
|
||||
#if FXGMAC_TX_INTERRUPT_EN
|
||||
req_vectors = FXGMAC_MAX_DMA_CHANNELS_PLUS_1TX;
|
||||
#else
|
||||
req_vectors = FXGMAC_MAX_DMA_CHANNELS;
|
||||
#endif
|
||||
msix_entries = kcalloc(/*vectors 20220211*/req_vectors,
|
||||
sizeof(struct msix_entry),
|
||||
GFP_KERNEL);
|
||||
if (!msix_entries) {
|
||||
DPRINTK("fxgmac_probe, MSIx, kcalloc err for msix entries, rollback to MSI..\n");
|
||||
goto enable_msi_interrupt;
|
||||
}else {
|
||||
for (i = 0; i < /*vectors 20220211*/req_vectors; i++)
|
||||
msix_entries[i].entry = i;
|
||||
#if 0
|
||||
/* follow the requirement from pci_enable_msix():
|
||||
*
|
||||
* Setup the MSI-X capability structure of device function with the number
|
||||
* of requested irqs upon its software driver call to request for
|
||||
* MSI-X mode enabled on its hardware device function. A return of zero
|
||||
* indicates the successful configuration of MSI-X capability structure
|
||||
* with new allocated MSI-X irqs. A return of < 0 indicates a failure.
|
||||
* Or a return of > 0 indicates that driver request is exceeding the number
|
||||
* of irqs or MSI-X vectors available. Driver should use the returned value to
|
||||
* re-send its request.
|
||||
*/
|
||||
req_vectors = vectors;
|
||||
do {
|
||||
rc = pci_enable_msix(pcidev, msix_entries, req_vectors);
|
||||
if (rc < 0) {
|
||||
//failure
|
||||
//DPRINTK("fxgmac_probe, enable MSIx failed,%d.\n", rc);
|
||||
rc = 0; //stop the loop
|
||||
req_vectors = 0; //indicate failure
|
||||
} else if (rc > 0) {
|
||||
//re-request with new number
|
||||
req_vectors = rc;
|
||||
}
|
||||
} while (rc);
|
||||
#else
|
||||
rc = pci_enable_msix_range(pcidev, msix_entries, req_vectors, req_vectors);
|
||||
if (rc < 0) {
|
||||
//failure
|
||||
DPRINTK("fxgmac_probe, enable MSIx failed,%d.\n", rc);
|
||||
req_vectors = 0; //indicate failure
|
||||
} else {
|
||||
req_vectors = rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FXGMAC_TX_INTERRUPT_EN
|
||||
if(req_vectors >= FXGMAC_MAX_DMA_CHANNELS_PLUS_1TX) {
|
||||
#else
|
||||
if(req_vectors >= FXGMAC_MAX_DMA_CHANNELS) {
|
||||
#endif
|
||||
DPRINTK("fxgmac_probe, enable MSIx ok, cpu=%d,vectors=%d.\n", vectors, req_vectors);
|
||||
pcidev_int_mode = FXGMAC_FLAG_MSIX_CAPABLE | FXGMAC_FLAG_MSIX_ENABLED;
|
||||
goto drv_probe;
|
||||
}else if (req_vectors){
|
||||
DPRINTK("fxgmac_probe, enable MSIx with only %d vector, while we need %d, rollback to MSI.\n", req_vectors, vectors);
|
||||
//roll back to msi
|
||||
pci_disable_msix(pcidev);
|
||||
kfree(msix_entries);
|
||||
msix_entries = NULL;
|
||||
}else {
|
||||
DPRINTK("fxgmac_probe, enable MSIx failure and clear msix entries.\n");
|
||||
//roll back to msi
|
||||
kfree(msix_entries);
|
||||
msix_entries = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enable_msi_interrupt:
|
||||
rc = pci_enable_msi(pcidev);
|
||||
if (rc < 0)
|
||||
DPRINTK("fxgmac_probe, enable MSI failure, rollback to LEGACY.\n");
|
||||
else {
|
||||
pcidev_int_mode = FXGMAC_FLAG_MSI_CAPABLE | FXGMAC_FLAG_MSI_ENABLED;
|
||||
DPRINTK("fxgmac_probe, enable MSI ok, irq=%d.\n", pcidev->irq);
|
||||
}
|
||||
|
||||
drv_probe:
|
||||
#endif
|
||||
|
||||
//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);
|
||||
|
||||
fxgmac_drv_remove(&pcidev->dev);
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
//20210526
|
||||
if(pcidev_int_mode & (FXGMAC_FLAG_MSIX_CAPABLE | FXGMAC_FLAG_MSIX_ENABLED)){
|
||||
pci_disable_msix(pcidev);
|
||||
kfree(msix_entries);
|
||||
msix_entries = NULL;
|
||||
req_vectors = 0;
|
||||
}
|
||||
pcidev_int_mode = 0;
|
||||
#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->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->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->current_state = CURRENT_STATE_SUSPEND;
|
||||
retval = __fxgmac_shutdown(pdev, &wake);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
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->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->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 <Frank.Sae@motor-comm.com>");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
|
@ -0,0 +1,428 @@
|
|||
/*++
|
||||
|
||||
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 <linux/timer.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
//DPRINTK ("8614 status adjust call in...\n");
|
||||
*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;
|
||||
}
|
||||
//DPRINTK (KERN_INFO "8521 status adjust call out,regval=0x%04x,mode=%s,speed=%dm...\n", val,is_utp?"utp":"fiber", phydev->speed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 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;
|
||||
}
|
||||
//DPRINTK (KERN_INFO "8614 read status call out,link=%d,linkmode=%d\n", ret_link, link_mode_8614[lport] );
|
||||
return 0;
|
||||
|
||||
busy_exit:
|
||||
DPRINTK("fxgmac_ephy_status_get exit due to ephy reg access fail.\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/* phy reg 1 bit2: link state */
|
||||
if((ephy_val1 & 0x4) != (ephy_val2 & 0x4))
|
||||
{
|
||||
pdata->stats.ephy_link_change_cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#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, 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->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->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->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");
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,24 @@
|
|||
/*++
|
||||
|
||||
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__
|
||||
|
||||
#define LINUX
|
||||
|
||||
#define PCIE_LP_ASPM_L0S 1
|
||||
#define PCIE_LP_ASPM_L1 2
|
||||
#define PCIE_LP_ASPM_L1SS 4
|
||||
#define PCIE_LP_ASPM_LTR 8
|
||||
|
||||
|
||||
#endif //__FUXI_OS_H__
|
||||
|
||||
Loading…
Reference in New Issue