This commit moves the patches for the r8152.c driver to the generic directory. Previously they were only available on the bcm27xx target. With these patches the Realtek RTL8153C, RTL8153D, RTL8156A and RTL8156B chips are supported on all targets by the kmod-usb-net-rtl8152 module. The RTL8156A and RTL8156B are the 2.5Gb/s Ethernet adapters. The patches have been tested on TP-Link UE300 (RTL8153A) and UNITEK 1313B (RTL8156B). Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>
321 lines
8.3 KiB
Diff
321 lines
8.3 KiB
Diff
From 0ef50460f7f053bd2a911ec53e01bfda646a5574 Mon Sep 17 00:00:00 2001
|
|
From: Hayes Wang <hayeswang@realtek.com>
|
|
Date: Wed, 4 Nov 2020 10:19:22 +0800
|
|
Subject: [PATCH] net/usb/r8153_ecm: support ECM mode for RTL8153
|
|
|
|
commit c1aedf015ebdd0232757a66e2daccf1246bd609c upstream.
|
|
|
|
Support ECM mode based on cdc_ether with relative mii functions,
|
|
when CONFIG_USB_RTL8152 is not set, or the device is not supported
|
|
by r8152 driver.
|
|
|
|
Both r8152 and r8153_ecm would check the return value of
|
|
rtl8152_get_version() in porbe(). If rtl8152_get_version()
|
|
return none zero value, the r8152 is used for the device
|
|
with vendor mode. Otherwise, the r8153_ecm is used for the
|
|
device with ECM mode.
|
|
|
|
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
|
|
Link: https://lore.kernel.org/r/1394712342-15778-392-Taiwan-albertk@realtek.com
|
|
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
---
|
|
drivers/net/usb/Makefile | 2 +-
|
|
drivers/net/usb/r8152.c | 30 +------
|
|
drivers/net/usb/r8153_ecm.c | 162 ++++++++++++++++++++++++++++++++++++
|
|
include/linux/usb/r8152.h | 37 ++++++++
|
|
4 files changed, 204 insertions(+), 27 deletions(-)
|
|
create mode 100644 drivers/net/usb/r8153_ecm.c
|
|
create mode 100644 include/linux/usb/r8152.h
|
|
|
|
--- a/drivers/net/usb/Makefile
|
|
+++ b/drivers/net/usb/Makefile
|
|
@@ -13,7 +13,7 @@ obj-$(CONFIG_USB_LAN78XX) += lan78xx.o
|
|
obj-$(CONFIG_USB_NET_AX8817X) += asix.o
|
|
asix-y := asix_devices.o asix_common.o ax88172a.o
|
|
obj-$(CONFIG_USB_NET_AX88179_178A) += ax88179_178a.o
|
|
-obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o
|
|
+obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o r8153_ecm.o
|
|
obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o
|
|
obj-$(CONFIG_USB_NET_DM9601) += dm9601.o
|
|
obj-$(CONFIG_USB_NET_SR9700) += sr9700.o
|
|
--- a/drivers/net/usb/r8152.c
|
|
+++ b/drivers/net/usb/r8152.c
|
|
@@ -27,6 +27,7 @@
|
|
#include <linux/acpi.h>
|
|
#include <linux/firmware.h>
|
|
#include <crypto/hash.h>
|
|
+#include <linux/usb/r8152.h>
|
|
|
|
/* Information for net-next */
|
|
#define NETNEXT_VERSION "11"
|
|
@@ -654,18 +655,6 @@ enum rtl_register_content {
|
|
|
|
#define INTR_LINK 0x0004
|
|
|
|
-#define RTL8152_REQT_READ 0xc0
|
|
-#define RTL8152_REQT_WRITE 0x40
|
|
-#define RTL8152_REQ_GET_REGS 0x05
|
|
-#define RTL8152_REQ_SET_REGS 0x05
|
|
-
|
|
-#define BYTE_EN_DWORD 0xff
|
|
-#define BYTE_EN_WORD 0x33
|
|
-#define BYTE_EN_BYTE 0x11
|
|
-#define BYTE_EN_SIX_BYTES 0x3f
|
|
-#define BYTE_EN_START_MASK 0x0f
|
|
-#define BYTE_EN_END_MASK 0xf0
|
|
-
|
|
#define RTL8153_MAX_PACKET 9216 /* 9K */
|
|
#define RTL8153_MAX_MTU (RTL8153_MAX_PACKET - VLAN_ETH_HLEN - \
|
|
ETH_FCS_LEN)
|
|
@@ -690,21 +679,9 @@ enum rtl8152_flags {
|
|
LENOVO_MACPASSTHRU,
|
|
};
|
|
|
|
-/* Define these values to match your device */
|
|
-#define VENDOR_ID_REALTEK 0x0bda
|
|
-#define VENDOR_ID_MICROSOFT 0x045e
|
|
-#define VENDOR_ID_SAMSUNG 0x04e8
|
|
-#define VENDOR_ID_LENOVO 0x17ef
|
|
-#define VENDOR_ID_LINKSYS 0x13b1
|
|
-#define VENDOR_ID_NVIDIA 0x0955
|
|
-#define VENDOR_ID_TPLINK 0x2357
|
|
-
|
|
#define DEVICE_ID_THINKPAD_THUNDERBOLT3_DOCK_GEN2 0x3082
|
|
#define DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2 0xa387
|
|
|
|
-#define MCU_TYPE_PLA 0x0100
|
|
-#define MCU_TYPE_USB 0x0000
|
|
-
|
|
struct tally_counter {
|
|
__le64 tx_packets;
|
|
__le64 rx_packets;
|
|
@@ -6625,7 +6602,7 @@ static int rtl_fw_init(struct r8152 *tp)
|
|
return 0;
|
|
}
|
|
|
|
-static u8 rtl_get_version(struct usb_interface *intf)
|
|
+u8 rtl8152_get_version(struct usb_interface *intf)
|
|
{
|
|
struct usb_device *udev = interface_to_usbdev(intf);
|
|
u32 ocp_data = 0;
|
|
@@ -6683,12 +6660,13 @@ static u8 rtl_get_version(struct usb_int
|
|
|
|
return version;
|
|
}
|
|
+EXPORT_SYMBOL_GPL(rtl8152_get_version);
|
|
|
|
static int rtl8152_probe(struct usb_interface *intf,
|
|
const struct usb_device_id *id)
|
|
{
|
|
struct usb_device *udev = interface_to_usbdev(intf);
|
|
- u8 version = rtl_get_version(intf);
|
|
+ u8 version = rtl8152_get_version(intf);
|
|
struct r8152 *tp;
|
|
struct net_device *netdev;
|
|
int ret;
|
|
--- /dev/null
|
|
+++ b/drivers/net/usb/r8153_ecm.c
|
|
@@ -0,0 +1,162 @@
|
|
+// SPDX-License-Identifier: GPL-2.0-or-later
|
|
+#include <linux/module.h>
|
|
+#include <linux/netdevice.h>
|
|
+#include <linux/mii.h>
|
|
+#include <linux/usb.h>
|
|
+#include <linux/usb/cdc.h>
|
|
+#include <linux/usb/usbnet.h>
|
|
+#include <linux/usb/r8152.h>
|
|
+
|
|
+#define OCP_BASE 0xe86c
|
|
+
|
|
+static int pla_read_word(struct usbnet *dev, u16 index)
|
|
+{
|
|
+ u16 byen = BYTE_EN_WORD;
|
|
+ u8 shift = index & 2;
|
|
+ __le32 tmp;
|
|
+ int ret;
|
|
+
|
|
+ if (shift)
|
|
+ byen <<= shift;
|
|
+
|
|
+ index &= ~3;
|
|
+
|
|
+ ret = usbnet_read_cmd(dev, RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, index,
|
|
+ MCU_TYPE_PLA | byen, &tmp, sizeof(tmp));
|
|
+ if (ret < 0)
|
|
+ goto out;
|
|
+
|
|
+ ret = __le32_to_cpu(tmp);
|
|
+ ret >>= (shift * 8);
|
|
+ ret &= 0xffff;
|
|
+
|
|
+out:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int pla_write_word(struct usbnet *dev, u16 index, u32 data)
|
|
+{
|
|
+ u32 mask = 0xffff;
|
|
+ u16 byen = BYTE_EN_WORD;
|
|
+ u8 shift = index & 2;
|
|
+ __le32 tmp;
|
|
+ int ret;
|
|
+
|
|
+ data &= mask;
|
|
+
|
|
+ if (shift) {
|
|
+ byen <<= shift;
|
|
+ mask <<= (shift * 8);
|
|
+ data <<= (shift * 8);
|
|
+ }
|
|
+
|
|
+ index &= ~3;
|
|
+
|
|
+ ret = usbnet_read_cmd(dev, RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, index,
|
|
+ MCU_TYPE_PLA | byen, &tmp, sizeof(tmp));
|
|
+
|
|
+ if (ret < 0)
|
|
+ goto out;
|
|
+
|
|
+ data |= __le32_to_cpu(tmp) & ~mask;
|
|
+ tmp = __cpu_to_le32(data);
|
|
+
|
|
+ ret = usbnet_write_cmd(dev, RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE, index,
|
|
+ MCU_TYPE_PLA | byen, &tmp, sizeof(tmp));
|
|
+
|
|
+out:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int r8153_ecm_mdio_read(struct net_device *netdev, int phy_id, int reg)
|
|
+{
|
|
+ struct usbnet *dev = netdev_priv(netdev);
|
|
+ int ret;
|
|
+
|
|
+ ret = pla_write_word(dev, OCP_BASE, 0xa000);
|
|
+ if (ret < 0)
|
|
+ goto out;
|
|
+
|
|
+ ret = pla_read_word(dev, 0xb400 + reg * 2);
|
|
+
|
|
+out:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void r8153_ecm_mdio_write(struct net_device *netdev, int phy_id, int reg, int val)
|
|
+{
|
|
+ struct usbnet *dev = netdev_priv(netdev);
|
|
+ int ret;
|
|
+
|
|
+ ret = pla_write_word(dev, OCP_BASE, 0xa000);
|
|
+ if (ret < 0)
|
|
+ return;
|
|
+
|
|
+ ret = pla_write_word(dev, 0xb400 + reg * 2, val);
|
|
+}
|
|
+
|
|
+static int r8153_bind(struct usbnet *dev, struct usb_interface *intf)
|
|
+{
|
|
+ int status;
|
|
+
|
|
+ status = usbnet_cdc_bind(dev, intf);
|
|
+ if (status < 0)
|
|
+ return status;
|
|
+
|
|
+ dev->mii.dev = dev->net;
|
|
+ dev->mii.mdio_read = r8153_ecm_mdio_read;
|
|
+ dev->mii.mdio_write = r8153_ecm_mdio_write;
|
|
+ dev->mii.reg_num_mask = 0x1f;
|
|
+ dev->mii.supports_gmii = 1;
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+static const struct driver_info r8153_info = {
|
|
+ .description = "RTL8153 ECM Device",
|
|
+ .flags = FLAG_ETHER,
|
|
+ .bind = r8153_bind,
|
|
+ .unbind = usbnet_cdc_unbind,
|
|
+ .status = usbnet_cdc_status,
|
|
+ .manage_power = usbnet_manage_power,
|
|
+};
|
|
+
|
|
+static const struct usb_device_id products[] = {
|
|
+{
|
|
+ USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID_REALTEK, 0x8153, USB_CLASS_COMM,
|
|
+ USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
|
+ .driver_info = (unsigned long)&r8153_info,
|
|
+},
|
|
+
|
|
+ { }, /* END */
|
|
+};
|
|
+MODULE_DEVICE_TABLE(usb, products);
|
|
+
|
|
+static int rtl8153_ecm_probe(struct usb_interface *intf,
|
|
+ const struct usb_device_id *id)
|
|
+{
|
|
+#if IS_REACHABLE(CONFIG_USB_RTL8152)
|
|
+ if (rtl8152_get_version(intf))
|
|
+ return -ENODEV;
|
|
+#endif
|
|
+
|
|
+ return usbnet_probe(intf, id);
|
|
+}
|
|
+
|
|
+static struct usb_driver r8153_ecm_driver = {
|
|
+ .name = "r8153_ecm",
|
|
+ .id_table = products,
|
|
+ .probe = rtl8153_ecm_probe,
|
|
+ .disconnect = usbnet_disconnect,
|
|
+ .suspend = usbnet_suspend,
|
|
+ .resume = usbnet_resume,
|
|
+ .reset_resume = usbnet_resume,
|
|
+ .supports_autosuspend = 1,
|
|
+ .disable_hub_initiated_lpm = 1,
|
|
+};
|
|
+
|
|
+module_usb_driver(r8153_ecm_driver);
|
|
+
|
|
+MODULE_AUTHOR("Hayes Wang");
|
|
+MODULE_DESCRIPTION("Realtek USB ECM device");
|
|
+MODULE_LICENSE("GPL");
|
|
--- /dev/null
|
|
+++ b/include/linux/usb/r8152.h
|
|
@@ -0,0 +1,37 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0-only */
|
|
+/*
|
|
+ * Copyright (c) 2020 Realtek Semiconductor Corp. All rights reserved.
|
|
+ */
|
|
+
|
|
+#ifndef __LINUX_R8152_H
|
|
+#define __LINUX_R8152_H
|
|
+
|
|
+#define RTL8152_REQT_READ 0xc0
|
|
+#define RTL8152_REQT_WRITE 0x40
|
|
+#define RTL8152_REQ_GET_REGS 0x05
|
|
+#define RTL8152_REQ_SET_REGS 0x05
|
|
+
|
|
+#define BYTE_EN_DWORD 0xff
|
|
+#define BYTE_EN_WORD 0x33
|
|
+#define BYTE_EN_BYTE 0x11
|
|
+#define BYTE_EN_SIX_BYTES 0x3f
|
|
+#define BYTE_EN_START_MASK 0x0f
|
|
+#define BYTE_EN_END_MASK 0xf0
|
|
+
|
|
+#define MCU_TYPE_PLA 0x0100
|
|
+#define MCU_TYPE_USB 0x0000
|
|
+
|
|
+/* Define these values to match your device */
|
|
+#define VENDOR_ID_REALTEK 0x0bda
|
|
+#define VENDOR_ID_MICROSOFT 0x045e
|
|
+#define VENDOR_ID_SAMSUNG 0x04e8
|
|
+#define VENDOR_ID_LENOVO 0x17ef
|
|
+#define VENDOR_ID_LINKSYS 0x13b1
|
|
+#define VENDOR_ID_NVIDIA 0x0955
|
|
+#define VENDOR_ID_TPLINK 0x2357
|
|
+
|
|
+#if IS_REACHABLE(CONFIG_USB_RTL8152)
|
|
+extern u8 rtl8152_get_version(struct usb_interface *intf);
|
|
+#endif
|
|
+
|
|
+#endif /* __LINUX_R8152_H */
|