First working version of RTL8169 driver on 5.10

This commit is contained in:
Richard Hacker
2022-01-14 19:27:37 +01:00
parent 3ee5e50a48
commit c8f303f38c
11 changed files with 10136 additions and 15 deletions

View File

@@ -235,7 +235,7 @@ AC_ARG_WITH([8139too-kernel],
if test "x${enable8139too}" = "x1"; then
AC_MSG_CHECKING([for kernel for 8139too driver])
kernels=`ls -1 ${srcdir}/devices/ | grep -oE "^8139too-.*-" | cut -d "-" -f 2 | uniq`
kernels=`ls -1 ${srcdir}/devices/realtek | grep -oE "^8139too-.*-" | cut -d "-" -f 2 | uniq`
found=0
for k in $kernels; do
if test "$kernel8139too" = "$k"; then
@@ -523,7 +523,7 @@ AC_ARG_WITH([r8169-kernel],
if test "x${enable_r8169}" = "x1"; then
AC_MSG_CHECKING([for kernel for r8169 driver])
kernels=`ls -1 ${srcdir}/devices/ | grep -oE "^r8169-.*-" | cut -d "-" -f 2 | uniq`
kernels=`ls -1 ${srcdir}/devices/realtek/ | grep -oE "^r8169_main-.*-" | cut -d "-" -f 2 | uniq`
found=0
for k in $kernels; do
if test "$kernel_r8169" = "$k"; then
@@ -1196,6 +1196,8 @@ AC_CONFIG_FILES([
devices/e1000e/Makefile
devices/igb/Kbuild
devices/igb/Makefile
devices/realtek/Kbuild
devices/realtek/Makefile
ethercat.spec
examples/Kbuild
examples/Makefile

View File

@@ -44,11 +44,22 @@ ifeq (@ENABLE_GENERIC@,1)
CFLAGS_$(EC_GENERIC_OBJ) = -DREV=$(REV)
endif
ifeq (@ENABLE_8139TOO@,1)
EC_8139TOO_OBJ := 8139too-@KERNEL_8139TOO@-ethercat.o
obj-m += ec_8139too.o
ec_8139too-objs := $(EC_8139TOO_OBJ)
CFLAGS_$(EC_8139TOO_OBJ) = -DREV=$(REV)
ifeq (1,1)
obj-m += realtek/
else
ifeq (@ENABLE_8139TOO@,1)
EC_8139TOO_OBJ := 8139too-@KERNEL_8139TOO@-ethercat.o
obj-m += ec_8139too.o
ec_8139too-objs := $(EC_8139TOO_OBJ)
CFLAGS_$(EC_8139TOO_OBJ) = -DREV=$(REV)
endif
ifeq (@ENABLE_R8169@,1)
EC_R8169_OBJ := r8169-@KERNEL_R8169@-ethercat.o
obj-m += ec_r8169.o
ec_r8169-objs := $(EC_R8169_OBJ)
CFLAGS_$(EC_R8169_OBJ) = -DREV=$(REV)
endif
endif
ifeq (@ENABLE_CCAT@,1)
@@ -74,13 +85,6 @@ ifeq (@ENABLE_IGB@,1)
obj-m += igb/
endif
ifeq (@ENABLE_R8169@,1)
EC_R8169_OBJ := r8169-@KERNEL_R8169@-ethercat.o
obj-m += ec_r8169.o
ec_r8169-objs := $(EC_R8169_OBJ)
CFLAGS_$(EC_R8169_OBJ) = -DREV=$(REV)
endif
KBUILD_EXTRA_SYMBOLS := \
@abs_top_builddir@/$(LINUX_SYMVERS) \
@abs_top_builddir@/master/$(LINUX_SYMVERS)

View File

@@ -32,7 +32,8 @@ SUBDIRS = \
ccat \
e1000 \
e1000e \
igb
igb \
realtek
# using HEADERS to enable tags target
noinst_HEADERS = \

File diff suppressed because it is too large Load Diff

77
devices/realtek/Kbuild.in Normal file
View File

@@ -0,0 +1,77 @@
#------------------------------------------------------------------------------
#
# $Id$
#
# Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
#
# This file is part of the IgH EtherCAT Master.
#
# The IgH EtherCAT Master is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 2, as
# published by the Free Software Foundation.
#
# The IgH EtherCAT Master is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with the IgH EtherCAT Master; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ---
#
# The license mentioned above concerns the source code only. Using the
# EtherCAT technology and brand is only permitted in compliance with the
# industrial property and similar rights of Beckhoff Automation GmbH.
#
# ---
#
# vim: syntax=make
#
#------------------------------------------------------------------------------
TOPDIR := $(src)/../..
REV := $(shell if test -s $(TOPDIR)/revision; then \
cat $(TOPDIR)/revision; \
else \
git -C $(TOPDIR) describe 2>/dev/null || echo "unknown"; \
fi)
#ifeq (@ENABLE_8139CP@,1)
# EC_8139CP_OBJ := 8139cp-@KERNEL_8139CP@-ethercat.o
# obj-m += ec_8139cp.o
# ec_8139cp-objs := $(EC_8139CP_OBJ)
# CFLAGS_$(EC_8139CP_OBJ) = -DREV=$(REV)
#endif
#ifeq (@ENABLE_8139CP@,1)
# EC_8139CP_OBJ := 8139cp-@KERNEL_8139CP@-ethercat.o
# obj-m += ec_8139cp.o
# ec_8139cp-objs := $(EC_8139CP_OBJ)
# CFLAGS_$(EC_8139CP_OBJ) = -DREV=$(REV)
#endif
ifeq (@ENABLE_8139TOO@,1)
EC_8139TOO_OBJ := 8139too-@KERNEL_8139TOO@-ethercat.o
obj-m += ec_8139too.o
ec_8139too-objs := $(EC_8139TOO_OBJ)
CFLAGS_$(EC_8139TOO_OBJ) = -DREV=$(REV)
endif
ifeq (@ENABLE_R8169@,1)
EC_R8169_OBJ := \
r8169_main-@KERNEL_R8169@-ethercat.o \
r8169_firmware-@KERNEL_R8169@-ethercat.o \
r8169_phy_config-@KERNEL_R8169@-ethercat.o
obj-m += ec_r8169.o
ec_r8169-objs := $(EC_R8169_OBJ)
CFLAGS_$(EC_R8169_OBJ) = -DREV=$(REV)
endif
KBUILD_EXTRA_SYMBOLS := \
@abs_top_builddir@/$(LINUX_SYMVERS) \
@abs_top_builddir@/master/$(LINUX_SYMVERS)
#------------------------------------------------------------------------------

View File

@@ -0,0 +1,33 @@
#------------------------------------------------------------------------------
#
# $Id: Makefile.am,v 792892ab4806 2014/10/28 15:54:59 fp $
#
# Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
#
# This file is part of the IgH EtherCAT Master.
#
# The IgH EtherCAT Master is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 2, as
# published by the Free Software Foundation.
#
# The IgH EtherCAT Master is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with the IgH EtherCAT Master; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ---
#
# The license mentioned above concerns the source code only. Using the
# EtherCAT technology and brand is only permitted in compliance with the
# industrial property and similar rights of Beckhoff Automation GmbH.
#
#------------------------------------------------------------------------------
include $(top_srcdir)/Makefile.kbuild
EXTRA_DIST =
#------------------------------------------------------------------------------

View File

@@ -0,0 +1,78 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* r8169.h: RealTek 8169/8168/8101 ethernet driver.
*
* Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
* Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
* Copyright (c) a lot of people too. Please respect their work.
*
* See MAINTAINERS file for support contact information.
*/
#include <linux/types.h>
#include <linux/phy.h>
enum mac_version {
/* support for ancient RTL_GIGA_MAC_VER_01 has been removed */
RTL_GIGA_MAC_VER_02,
RTL_GIGA_MAC_VER_03,
RTL_GIGA_MAC_VER_04,
RTL_GIGA_MAC_VER_05,
RTL_GIGA_MAC_VER_06,
RTL_GIGA_MAC_VER_07,
RTL_GIGA_MAC_VER_08,
RTL_GIGA_MAC_VER_09,
RTL_GIGA_MAC_VER_10,
RTL_GIGA_MAC_VER_11,
RTL_GIGA_MAC_VER_12,
RTL_GIGA_MAC_VER_13,
RTL_GIGA_MAC_VER_14,
RTL_GIGA_MAC_VER_16,
RTL_GIGA_MAC_VER_17,
RTL_GIGA_MAC_VER_18,
RTL_GIGA_MAC_VER_19,
RTL_GIGA_MAC_VER_20,
RTL_GIGA_MAC_VER_21,
RTL_GIGA_MAC_VER_22,
RTL_GIGA_MAC_VER_23,
RTL_GIGA_MAC_VER_24,
RTL_GIGA_MAC_VER_25,
RTL_GIGA_MAC_VER_26,
RTL_GIGA_MAC_VER_27,
RTL_GIGA_MAC_VER_28,
RTL_GIGA_MAC_VER_29,
RTL_GIGA_MAC_VER_30,
RTL_GIGA_MAC_VER_31,
RTL_GIGA_MAC_VER_32,
RTL_GIGA_MAC_VER_33,
RTL_GIGA_MAC_VER_34,
RTL_GIGA_MAC_VER_35,
RTL_GIGA_MAC_VER_36,
RTL_GIGA_MAC_VER_37,
RTL_GIGA_MAC_VER_38,
RTL_GIGA_MAC_VER_39,
RTL_GIGA_MAC_VER_40,
RTL_GIGA_MAC_VER_41,
RTL_GIGA_MAC_VER_42,
RTL_GIGA_MAC_VER_43,
RTL_GIGA_MAC_VER_44,
RTL_GIGA_MAC_VER_45,
RTL_GIGA_MAC_VER_46,
RTL_GIGA_MAC_VER_47,
RTL_GIGA_MAC_VER_48,
RTL_GIGA_MAC_VER_49,
RTL_GIGA_MAC_VER_50,
RTL_GIGA_MAC_VER_51,
RTL_GIGA_MAC_VER_52,
RTL_GIGA_MAC_VER_60,
RTL_GIGA_MAC_VER_61,
RTL_GIGA_MAC_VER_63,
RTL_GIGA_MAC_NONE
};
struct rtl8169_private;
void r8169_apply_firmware(struct rtl8169_private *tp);
u16 rtl8168h_2_get_adc_bias_ioffset(struct rtl8169_private *tp);
u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr);
void r8169_hw_phy_config(struct rtl8169_private *tp, struct phy_device *phydev,
enum mac_version ver);

View File

@@ -0,0 +1,236 @@
// SPDX-License-Identifier: GPL-2.0-only
/* r8169_firmware.c: RealTek 8169/8168/8101 ethernet driver.
*
* Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
* Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
* Copyright (c) a lot of people too. Please respect their work.
*
* See MAINTAINERS file for support contact information.
*/
#include <linux/delay.h>
#include <linux/firmware.h>
#include "r8169_firmware-5.10-ethercat.h"
enum rtl_fw_opcode {
PHY_READ = 0x0,
PHY_DATA_OR = 0x1,
PHY_DATA_AND = 0x2,
PHY_BJMPN = 0x3,
PHY_MDIO_CHG = 0x4,
PHY_CLEAR_READCOUNT = 0x7,
PHY_WRITE = 0x8,
PHY_READCOUNT_EQ_SKIP = 0x9,
PHY_COMP_EQ_SKIPN = 0xa,
PHY_COMP_NEQ_SKIPN = 0xb,
PHY_WRITE_PREVIOUS = 0xc,
PHY_SKIPN = 0xd,
PHY_DELAY_MS = 0xe,
};
struct fw_info {
u32 magic;
char version[RTL_VER_SIZE];
__le32 fw_start;
__le32 fw_len;
u8 chksum;
} __packed;
#define FW_OPCODE_SIZE sizeof_field(struct rtl_fw_phy_action, code[0])
static bool rtl_fw_format_ok(struct rtl_fw *rtl_fw)
{
const struct firmware *fw = rtl_fw->fw;
struct fw_info *fw_info = (struct fw_info *)fw->data;
struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
if (fw->size < FW_OPCODE_SIZE)
return false;
if (!fw_info->magic) {
size_t i, size, start;
u8 checksum = 0;
if (fw->size < sizeof(*fw_info))
return false;
for (i = 0; i < fw->size; i++)
checksum += fw->data[i];
if (checksum != 0)
return false;
start = le32_to_cpu(fw_info->fw_start);
if (start > fw->size)
return false;
size = le32_to_cpu(fw_info->fw_len);
if (size > (fw->size - start) / FW_OPCODE_SIZE)
return false;
strscpy(rtl_fw->version, fw_info->version, RTL_VER_SIZE);
pa->code = (__le32 *)(fw->data + start);
pa->size = size;
} else {
if (fw->size % FW_OPCODE_SIZE)
return false;
strscpy(rtl_fw->version, rtl_fw->fw_name, RTL_VER_SIZE);
pa->code = (__le32 *)fw->data;
pa->size = fw->size / FW_OPCODE_SIZE;
}
return true;
}
static bool rtl_fw_data_ok(struct rtl_fw *rtl_fw)
{
struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
size_t index;
for (index = 0; index < pa->size; index++) {
u32 action = le32_to_cpu(pa->code[index]);
u32 val = action & 0x0000ffff;
u32 regno = (action & 0x0fff0000) >> 16;
switch (action >> 28) {
case PHY_READ:
case PHY_DATA_OR:
case PHY_DATA_AND:
case PHY_CLEAR_READCOUNT:
case PHY_WRITE:
case PHY_WRITE_PREVIOUS:
case PHY_DELAY_MS:
break;
case PHY_MDIO_CHG:
if (val > 1)
goto out;
break;
case PHY_BJMPN:
if (regno > index)
goto out;
break;
case PHY_READCOUNT_EQ_SKIP:
if (index + 2 >= pa->size)
goto out;
break;
case PHY_COMP_EQ_SKIPN:
case PHY_COMP_NEQ_SKIPN:
case PHY_SKIPN:
if (index + 1 + regno >= pa->size)
goto out;
break;
default:
dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action);
return false;
}
}
return true;
out:
dev_err(rtl_fw->dev, "Out of range of firmware\n");
return false;
}
void rtl_fw_write_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
{
struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
rtl_fw_write_t fw_write = rtl_fw->phy_write;
rtl_fw_read_t fw_read = rtl_fw->phy_read;
int predata = 0, count = 0;
size_t index;
for (index = 0; index < pa->size; index++) {
u32 action = le32_to_cpu(pa->code[index]);
u32 data = action & 0x0000ffff;
u32 regno = (action & 0x0fff0000) >> 16;
enum rtl_fw_opcode opcode = action >> 28;
if (!action)
break;
switch (opcode) {
case PHY_READ:
predata = fw_read(tp, regno);
count++;
break;
case PHY_DATA_OR:
predata |= data;
break;
case PHY_DATA_AND:
predata &= data;
break;
case PHY_BJMPN:
index -= (regno + 1);
break;
case PHY_MDIO_CHG:
if (data) {
fw_write = rtl_fw->mac_mcu_write;
fw_read = rtl_fw->mac_mcu_read;
} else {
fw_write = rtl_fw->phy_write;
fw_read = rtl_fw->phy_read;
}
break;
case PHY_CLEAR_READCOUNT:
count = 0;
break;
case PHY_WRITE:
fw_write(tp, regno, data);
break;
case PHY_READCOUNT_EQ_SKIP:
if (count == data)
index++;
break;
case PHY_COMP_EQ_SKIPN:
if (predata == data)
index += regno;
break;
case PHY_COMP_NEQ_SKIPN:
if (predata != data)
index += regno;
break;
case PHY_WRITE_PREVIOUS:
fw_write(tp, regno, predata);
break;
case PHY_SKIPN:
index += regno;
break;
case PHY_DELAY_MS:
msleep(data);
break;
}
}
}
void rtl_fw_release_firmware(struct rtl_fw *rtl_fw)
{
release_firmware(rtl_fw->fw);
}
int rtl_fw_request_firmware(struct rtl_fw *rtl_fw)
{
int rc;
rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev);
if (rc < 0)
goto out;
if (!rtl_fw_format_ok(rtl_fw) || !rtl_fw_data_ok(rtl_fw)) {
release_firmware(rtl_fw->fw);
rc = -EINVAL;
goto out;
}
return 0;
out:
dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n",
rtl_fw->fw_name, rc);
return rc;
}

View File

@@ -0,0 +1,39 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* r8169_firmware.h: RealTek 8169/8168/8101 ethernet driver.
*
* Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
* Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
* Copyright (c) a lot of people too. Please respect their work.
*
* See MAINTAINERS file for support contact information.
*/
#include <linux/device.h>
#include <linux/firmware.h>
struct rtl8169_private;
typedef void (*rtl_fw_write_t)(struct rtl8169_private *tp, int reg, int val);
typedef int (*rtl_fw_read_t)(struct rtl8169_private *tp, int reg);
#define RTL_VER_SIZE 32
struct rtl_fw {
rtl_fw_write_t phy_write;
rtl_fw_read_t phy_read;
rtl_fw_write_t mac_mcu_write;
rtl_fw_read_t mac_mcu_read;
const struct firmware *fw;
const char *fw_name;
struct device *dev;
char version[RTL_VER_SIZE];
struct rtl_fw_phy_action {
__le32 *code;
size_t size;
} phy_action;
};
int rtl_fw_request_firmware(struct rtl_fw *rtl_fw);
void rtl_fw_release_firmware(struct rtl_fw *rtl_fw);
void rtl_fw_write_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff