You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
net: ethernet: motorcomm: Add yt6801 driver
This commit is contained in:
@@ -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/
|
||||
|
||||
18
drivers/net/ethernet/motorcomm/Kconfig
Executable file
18
drivers/net/ethernet/motorcomm/Kconfig
Executable file
@@ -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
|
||||
40
drivers/net/ethernet/motorcomm/Makefile
Executable file
40
drivers/net/ethernet/motorcomm/Makefile
Executable file
@@ -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
|
||||
4
drivers/net/ethernet/motorcomm/Makefile_into_kernel
Executable file
4
drivers/net/ethernet/motorcomm/Makefile_into_kernel
Executable file
@@ -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
|
||||
30
drivers/net/ethernet/motorcomm/Notice.txt
Executable file
30
drivers/net/ethernet/motorcomm/Notice.txt
Executable file
@@ -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.
|
||||
|
||||
=============================================================================
|
||||
|
||||
|
||||
7
drivers/net/ethernet/motorcomm/dkms.conf
Executable file
7
drivers/net/ethernet/motorcomm/dkms.conf
Executable file
@@ -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"
|
||||
520
drivers/net/ethernet/motorcomm/fuxi-dbg.c
Executable file
520
drivers/net/ethernet/motorcomm/fuxi-dbg.c
Executable file
File diff suppressed because it is too large
Load Diff
271
drivers/net/ethernet/motorcomm/fuxi-dbg.h
Executable file
271
drivers/net/ethernet/motorcomm/fuxi-dbg.h
Executable file
@@ -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
|
||||
972
drivers/net/ethernet/motorcomm/fuxi-efuse.c
Executable file
972
drivers/net/ethernet/motorcomm/fuxi-efuse.c
Executable file
File diff suppressed because it is too large
Load Diff
33
drivers/net/ethernet/motorcomm/fuxi-efuse.h
Executable file
33
drivers/net/ethernet/motorcomm/fuxi-efuse.h
Executable file
@@ -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__
|
||||
935
drivers/net/ethernet/motorcomm/fuxi-gmac-common.c
Executable file
935
drivers/net/ethernet/motorcomm/fuxi-gmac-common.c
Executable file
File diff suppressed because it is too large
Load Diff
645
drivers/net/ethernet/motorcomm/fuxi-gmac-debugfs.c
Executable file
645
drivers/net/ethernet/motorcomm/fuxi-gmac-debugfs.c
Executable file
File diff suppressed because it is too large
Load Diff
1249
drivers/net/ethernet/motorcomm/fuxi-gmac-desc.c
Executable file
1249
drivers/net/ethernet/motorcomm/fuxi-gmac-desc.c
Executable file
File diff suppressed because it is too large
Load Diff
1310
drivers/net/ethernet/motorcomm/fuxi-gmac-ethtool.c
Executable file
1310
drivers/net/ethernet/motorcomm/fuxi-gmac-ethtool.c
Executable file
File diff suppressed because it is too large
Load Diff
6453
drivers/net/ethernet/motorcomm/fuxi-gmac-hw.c
Executable file
6453
drivers/net/ethernet/motorcomm/fuxi-gmac-hw.c
Executable file
File diff suppressed because it is too large
Load Diff
2299
drivers/net/ethernet/motorcomm/fuxi-gmac-net.c
Executable file
2299
drivers/net/ethernet/motorcomm/fuxi-gmac-net.c
Executable file
File diff suppressed because it is too large
Load Diff
504
drivers/net/ethernet/motorcomm/fuxi-gmac-pci.c
Executable file
504
drivers/net/ethernet/motorcomm/fuxi-gmac-pci.c
Executable file
File diff suppressed because it is too large
Load Diff
428
drivers/net/ethernet/motorcomm/fuxi-gmac-phy.c
Executable file
428
drivers/net/ethernet/motorcomm/fuxi-gmac-phy.c
Executable file
@@ -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");
|
||||
}
|
||||
1818
drivers/net/ethernet/motorcomm/fuxi-gmac-reg.h
Executable file
1818
drivers/net/ethernet/motorcomm/fuxi-gmac-reg.h
Executable file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user