diff options
Diffstat (limited to 'target/linux/generic')
16 files changed, 5062 insertions, 0 deletions
diff --git a/target/linux/generic/backport-5.10/780-v5.11-net-usb-r8152-Provide-missing-documentation-for-some.patch b/target/linux/generic/backport-5.10/780-v5.11-net-usb-r8152-Provide-missing-documentation-for-some.patch new file mode 100644 index 0000000000..bec2867a48 --- /dev/null +++ b/target/linux/generic/backport-5.10/780-v5.11-net-usb-r8152-Provide-missing-documentation-for-some.patch @@ -0,0 +1,72 @@ +From 586f04ce6a391419ca3cc9cef6b6f38570cede88 Mon Sep 17 00:00:00 2001 +From: Lee Jones <lee.jones@linaro.org> +Date: Mon, 2 Nov 2020 11:45:04 +0000 +Subject: [PATCH] net: usb: r8152: Provide missing documentation for + some struct members + +commit 34e653efb602e0651867fb5ab14369b555a61dcd upstream. + +Fixes the following W=1 kernel build warning(s): + + drivers/net/usb/r8152.c:934: warning: Function parameter or member 'blk_hdr' not described in 'fw_mac' + drivers/net/usb/r8152.c:934: warning: Function parameter or member 'reserved' not described in 'fw_mac' + drivers/net/usb/r8152.c:947: warning: Function parameter or member 'blk_hdr' not described in 'fw_phy_patch_key' + drivers/net/usb/r8152.c:947: warning: Function parameter or member 'reserved' not described in 'fw_phy_patch_key' + drivers/net/usb/r8152.c:986: warning: Function parameter or member 'blk_hdr' not described in 'fw_phy_nc' + drivers/net/usb/r8152.c:986: warning: Function parameter or member 'mode_pre' not described in 'fw_phy_nc' + drivers/net/usb/r8152.c:986: warning: Function parameter or member 'mode_post' not described in 'fw_phy_nc' + drivers/net/usb/r8152.c:986: warning: Function parameter or member 'reserved' not described in 'fw_phy_nc' + +Signed-off-by: Lee Jones <lee.jones@linaro.org> +Acked-by: Hayes Wang <hayeswang@realtek.com> +Link: https://lore.kernel.org/r/20201102114512.1062724-23-lee.jones@linaro.org +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +--- + drivers/net/usb/r8152.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -899,6 +899,7 @@ struct fw_header { + * struct fw_mac - a firmware block used by RTL_FW_PLA and RTL_FW_USB. + * The layout of the firmware block is: + * <struct fw_mac> + <info> + <firmware data>. ++ * @blk_hdr: firmware descriptor (type, length) + * @fw_offset: offset of the firmware binary data. The start address of + * the data would be the address of struct fw_mac + @fw_offset. + * @fw_reg: the register to load the firmware. Depends on chip. +@@ -912,6 +913,7 @@ struct fw_header { + * @bp_num: the break point number which needs to be set for this firmware. + * Depends on the firmware. + * @bp: break points. Depends on firmware. ++ * @reserved: reserved space (unused) + * @fw_ver_reg: the register to store the fw version. + * @fw_ver_data: the firmware version of the current type. + * @info: additional information for debugging, and is followed by the +@@ -937,8 +939,10 @@ struct fw_mac { + /** + * struct fw_phy_patch_key - a firmware block used by RTL_FW_PHY_START. + * This is used to set patch key when loading the firmware of PHY. ++ * @blk_hdr: firmware descriptor (type, length) + * @key_reg: the register to write the patch key. + * @key_data: patch key. ++ * @reserved: reserved space (unused) + */ + struct fw_phy_patch_key { + struct fw_block blk_hdr; +@@ -951,6 +955,7 @@ struct fw_phy_patch_key { + * struct fw_phy_nc - a firmware block used by RTL_FW_PHY_NC. + * The layout of the firmware block is: + * <struct fw_phy_nc> + <info> + <firmware data>. ++ * @blk_hdr: firmware descriptor (type, length) + * @fw_offset: offset of the firmware binary data. The start address of + * the data would be the address of struct fw_phy_nc + @fw_offset. + * @fw_reg: the register to load the firmware. Depends on chip. +@@ -961,6 +966,7 @@ struct fw_phy_patch_key { + * @mode_reg: the regitster of switching the mode. + * @mod_pre: the mode needing to be set before loading the firmware. + * @mod_post: the mode to be set when finishing to load the firmware. ++ * @reserved: reserved space (unused) + * @bp_start: the start register of break points. Depends on chip. + * @bp_num: the break point number which needs to be set for this firmware. + * Depends on the firmware. diff --git a/target/linux/generic/backport-5.10/781-v5.11-net-usb-r8152-Fix-a-couple-of-spelling-errors-in-fw_.patch b/target/linux/generic/backport-5.10/781-v5.11-net-usb-r8152-Fix-a-couple-of-spelling-errors-in-fw_.patch new file mode 100644 index 0000000000..aa2763e7de --- /dev/null +++ b/target/linux/generic/backport-5.10/781-v5.11-net-usb-r8152-Fix-a-couple-of-spelling-errors-in-fw_.patch @@ -0,0 +1,34 @@ +From 5fcfa846181de6676509696c4cd7b60a22e74077 Mon Sep 17 00:00:00 2001 +From: Lee Jones <lee.jones@linaro.org> +Date: Mon, 2 Nov 2020 11:45:09 +0000 +Subject: [PATCH] net: usb: r8152: Fix a couple of spelling errors in + fw_phy_nc's docs + +commit 9f07814d01ad085b2d9f1d55b4ce532fb2c27110 upstream. + +Fixes the following W=1 kernel build warning(s): + + drivers/net/usb/r8152.c:992: warning: Function parameter or member 'mode_pre' not described in 'fw_phy_nc' + drivers/net/usb/r8152.c:992: warning: Function parameter or member 'mode_post' not described in 'fw_phy_nc' + +Signed-off-by: Lee Jones <lee.jones@linaro.org> +Acked-by: Hayes Wang <hayeswang@realtek.com> +Link: https://lore.kernel.org/r/20201102114512.1062724-28-lee.jones@linaro.org +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +--- + drivers/net/usb/r8152.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -964,8 +964,8 @@ struct fw_phy_patch_key { + * @patch_en_addr: the register of enabling patch mode. Depends on chip. + * @patch_en_value: patch mode enabled mask. Depends on the firmware. + * @mode_reg: the regitster of switching the mode. +- * @mod_pre: the mode needing to be set before loading the firmware. +- * @mod_post: the mode to be set when finishing to load the firmware. ++ * @mode_pre: the mode needing to be set before loading the firmware. ++ * @mode_post: the mode to be set when finishing to load the firmware. + * @reserved: reserved space (unused) + * @bp_start: the start register of break points. Depends on chip. + * @bp_num: the break point number which needs to be set for this firmware. diff --git a/target/linux/generic/backport-5.10/782-v5.11-net-usb-r8153_ecm-support-ECM-mode-for-RTL8153.patch b/target/linux/generic/backport-5.10/782-v5.11-net-usb-r8153_ecm-support-ECM-mode-for-RTL8153.patch new file mode 100644 index 0000000000..789de8e6fd --- /dev/null +++ b/target/linux/generic/backport-5.10/782-v5.11-net-usb-r8153_ecm-support-ECM-mode-for-RTL8153.patch @@ -0,0 +1,320 @@ +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 */ diff --git a/target/linux/generic/backport-5.10/783-v5.12-net-usb-r8152-use-new-tasklet-API.patch b/target/linux/generic/backport-5.10/783-v5.12-net-usb-r8152-use-new-tasklet-API.patch new file mode 100644 index 0000000000..b625d5ea99 --- /dev/null +++ b/target/linux/generic/backport-5.10/783-v5.12-net-usb-r8152-use-new-tasklet-API.patch @@ -0,0 +1,41 @@ +From 90f1afc7f96c8f7cf19c82e5f4b39e61a63b053d Mon Sep 17 00:00:00 2001 +From: Emil Renner Berthing <kernel@esmil.dk> +Date: Sun, 31 Jan 2021 00:47:29 +0100 +Subject: [PATCH] net: usb: r8152: use new tasklet API + +commit f3163f1cb87141c7a41a15a5d4c98b353f807b04 upstream. + +This converts the driver to use the new tasklet API introduced in +commit 12cc923f1ccc ("tasklet: Introduce new initialization API") + +Signed-off-by: Emil Renner Berthing <kernel@esmil.dk> +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +--- + drivers/net/usb/r8152.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -2394,11 +2394,9 @@ static void tx_bottom(struct r8152 *tp) + } while (res == 0); + } + +-static void bottom_half(unsigned long data) ++static void bottom_half(struct tasklet_struct *t) + { +- struct r8152 *tp; +- +- tp = (struct r8152 *)data; ++ struct r8152 *tp = from_tasklet(tp, t, tx_tl); + + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return; +@@ -6718,7 +6716,7 @@ static int rtl8152_probe(struct usb_inte + mutex_init(&tp->control); + INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t); + INIT_DELAYED_WORK(&tp->hw_phy_work, rtl_hw_phy_work_func_t); +- tasklet_init(&tp->tx_tl, bottom_half, (unsigned long)tp); ++ tasklet_setup(&tp->tx_tl, bottom_half); + tasklet_disable(&tp->tx_tl); + + netdev->netdev_ops = &rtl8152_netdev_ops; diff --git a/target/linux/generic/backport-5.10/784-v5.12-r8152-replace-several-functions-about-phy-patch-requ.patch b/target/linux/generic/backport-5.10/784-v5.12-r8152-replace-several-functions-about-phy-patch-requ.patch new file mode 100644 index 0000000000..bbb2b5c0c9 --- /dev/null +++ b/target/linux/generic/backport-5.10/784-v5.12-r8152-replace-several-functions-about-phy-patch-requ.patch @@ -0,0 +1,198 @@ +From 86b98abf4f8c691c260c5113d6a2d32f5377caca Mon Sep 17 00:00:00 2001 +From: Hayes Wang <hayeswang@realtek.com> +Date: Wed, 3 Feb 2021 17:14:28 +0800 +Subject: [PATCH] r8152: replace several functions about phy patch + request + +commit a08c0d309d8c078d22717d815cf9853f6f2c07bd upstream. + +Replace r8153_patch_request() with rtl_phy_patch_request(). +Replace r8153_pre_ram_code() with rtl_pre_ram_code(). +Replace r8153_post_ram_code() with rtl_post_ram_code(). +Add rtl_patch_key_set(). + +The new functions have an additional parameter. It is used to wait +the patch request command finished. When the PHY is resumed from +the state of power cut, the PHY is at a safe mode and the +OCP_PHY_PATCH_STAT wouldn't be updated. For this situation, it is +safe to set patch request command without waiting OCP_PHY_PATCH_STAT. + +Signed-off-by: Hayes Wang <hayeswang@realtek.com> +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +--- + drivers/net/usb/r8152.c | 84 ++++++++++++++++++++++++----------------- + 1 file changed, 50 insertions(+), 34 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -3444,59 +3444,76 @@ static void rtl_clear_bp(struct r8152 *t + ocp_write_word(tp, type, PLA_BP_BA, 0); + } + +-static int r8153_patch_request(struct r8152 *tp, bool request) ++static int rtl_phy_patch_request(struct r8152 *tp, bool request, bool wait) + { +- u16 data; ++ u16 data, check; + int i; + + data = ocp_reg_read(tp, OCP_PHY_PATCH_CMD); +- if (request) ++ if (request) { + data |= PATCH_REQUEST; +- else ++ check = 0; ++ } else { + data &= ~PATCH_REQUEST; ++ check = PATCH_READY; ++ } + ocp_reg_write(tp, OCP_PHY_PATCH_CMD, data); + +- for (i = 0; request && i < 5000; i++) { ++ for (i = 0; wait && i < 5000; i++) { ++ u32 ocp_data; ++ + usleep_range(1000, 2000); +- if (ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY) ++ ocp_data = ocp_reg_read(tp, OCP_PHY_PATCH_STAT); ++ if ((ocp_data & PATCH_READY) ^ check) + break; + } + +- if (request && !(ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY)) { +- netif_err(tp, drv, tp->netdev, "patch request fail\n"); +- r8153_patch_request(tp, false); ++ if (request && wait && ++ !(ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY)) { ++ dev_err(&tp->intf->dev, "PHY patch request fail\n"); ++ rtl_phy_patch_request(tp, false, false); + return -ETIME; + } else { + return 0; + } + } + +-static int r8153_pre_ram_code(struct r8152 *tp, u16 key_addr, u16 patch_key) ++static void rtl_patch_key_set(struct r8152 *tp, u16 key_addr, u16 patch_key) + { +- if (r8153_patch_request(tp, true)) { +- dev_err(&tp->intf->dev, "patch request fail\n"); +- return -ETIME; +- } ++ if (patch_key && key_addr) { ++ sram_write(tp, key_addr, patch_key); ++ sram_write(tp, SRAM_PHY_LOCK, PHY_PATCH_LOCK); ++ } else if (key_addr) { ++ u16 data; + +- sram_write(tp, key_addr, patch_key); +- sram_write(tp, SRAM_PHY_LOCK, PHY_PATCH_LOCK); ++ sram_write(tp, 0x0000, 0x0000); + +- return 0; ++ data = ocp_reg_read(tp, OCP_PHY_LOCK); ++ data &= ~PATCH_LOCK; ++ ocp_reg_write(tp, OCP_PHY_LOCK, data); ++ ++ sram_write(tp, key_addr, 0x0000); ++ } else { ++ WARN_ON_ONCE(1); ++ } + } + +-static int r8153_post_ram_code(struct r8152 *tp, u16 key_addr) ++static int ++rtl_pre_ram_code(struct r8152 *tp, u16 key_addr, u16 patch_key, bool wait) + { +- u16 data; ++ if (rtl_phy_patch_request(tp, true, wait)) ++ return -ETIME; + +- sram_write(tp, 0x0000, 0x0000); ++ rtl_patch_key_set(tp, key_addr, patch_key); + +- data = ocp_reg_read(tp, OCP_PHY_LOCK); +- data &= ~PATCH_LOCK; +- ocp_reg_write(tp, OCP_PHY_LOCK, data); ++ return 0; ++} + +- sram_write(tp, key_addr, 0x0000); ++static int rtl_post_ram_code(struct r8152 *tp, u16 key_addr, bool wait) ++{ ++ rtl_patch_key_set(tp, key_addr, 0); + +- r8153_patch_request(tp, false); ++ rtl_phy_patch_request(tp, false, wait); + + ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, tp->ocp_base); + +@@ -3981,7 +3998,7 @@ static void rtl8152_fw_mac_apply(struct + dev_dbg(&tp->intf->dev, "successfully applied %s\n", mac->info); + } + +-static void rtl8152_apply_firmware(struct r8152 *tp) ++static void rtl8152_apply_firmware(struct r8152 *tp, bool power_cut) + { + struct rtl_fw *rtl_fw = &tp->rtl_fw; + const struct firmware *fw; +@@ -4012,12 +4029,11 @@ static void rtl8152_apply_firmware(struc + case RTL_FW_PHY_START: + key = (struct fw_phy_patch_key *)block; + key_addr = __le16_to_cpu(key->key_reg); +- r8153_pre_ram_code(tp, key_addr, +- __le16_to_cpu(key->key_data)); ++ rtl_pre_ram_code(tp, key_addr, __le16_to_cpu(key->key_data), !power_cut); + break; + case RTL_FW_PHY_STOP: + WARN_ON(!key_addr); +- r8153_post_ram_code(tp, key_addr); ++ rtl_post_ram_code(tp, key_addr, !power_cut); + break; + case RTL_FW_PHY_NC: + rtl8152_fw_phy_nc_apply(tp, (struct fw_phy_nc *)block); +@@ -4222,7 +4238,7 @@ static void rtl8152_disable(struct r8152 + + static void r8152b_hw_phy_cfg(struct r8152 *tp) + { +- rtl8152_apply_firmware(tp); ++ rtl8152_apply_firmware(tp, false); + rtl_eee_enable(tp, tp->eee_en); + r8152_aldps_en(tp, true); + r8152b_enable_fc(tp); +@@ -4504,7 +4520,7 @@ static void r8153_hw_phy_cfg(struct r815 + /* disable EEE before updating the PHY parameters */ + rtl_eee_enable(tp, false); + +- rtl8152_apply_firmware(tp); ++ rtl8152_apply_firmware(tp, false); + + if (tp->version == RTL_VER_03) { + data = ocp_reg_read(tp, OCP_EEE_CFG); +@@ -4578,7 +4594,7 @@ static void r8153b_hw_phy_cfg(struct r81 + /* disable EEE before updating the PHY parameters */ + rtl_eee_enable(tp, false); + +- rtl8152_apply_firmware(tp); ++ rtl8152_apply_firmware(tp, false); + + r8153b_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags)); + +@@ -4619,7 +4635,7 @@ static void r8153b_hw_phy_cfg(struct r81 + ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); + + /* Advnace EEE */ +- if (!r8153_patch_request(tp, true)) { ++ if (!rtl_phy_patch_request(tp, true, true)) { + data = ocp_reg_read(tp, OCP_POWER_CFG); + data |= EEE_CLKDIV_EN; + ocp_reg_write(tp, OCP_POWER_CFG, data); +@@ -4636,7 +4652,7 @@ static void r8153b_hw_phy_cfg(struct r81 + ocp_reg_write(tp, OCP_SYSCLK_CFG, clk_div_expo(5)); + tp->ups_info._250m_ckdiv = true; + +- r8153_patch_request(tp, false); ++ rtl_phy_patch_request(tp, false, true); + } + + if (tp->eee_en) diff --git a/target/linux/generic/backport-5.10/785-v5.12-r8152-adjust-the-flow-of-power-cut-for-RTL8153B.patch b/target/linux/generic/backport-5.10/785-v5.12-r8152-adjust-the-flow-of-power-cut-for-RTL8153B.patch new file mode 100644 index 0000000000..b28e89a43f --- /dev/null +++ b/target/linux/generic/backport-5.10/785-v5.12-r8152-adjust-the-flow-of-power-cut-for-RTL8153B.patch @@ -0,0 +1,134 @@ +From 29a61d8564ad3439d03c7ec135016a4e70072af1 Mon Sep 17 00:00:00 2001 +From: Hayes Wang <hayeswang@realtek.com> +Date: Wed, 3 Feb 2021 17:14:29 +0800 +Subject: [PATCH] r8152: adjust the flow of power cut for RTL8153B + +commit 80fd850b31f09263ad175b2f640d5c5c6f76ed41 upstream. + +For runtime resuming, the RTL8153B may be resumed from the state +of power cut, when enabling the feature of UPS. Then, the PHY +would be reset, so it is necessary to be initailized again. + +Besides, the USB_U1U2_TIMER also has to be set again, so I move +it from r8153b_init() to r8153b_hw_phy_cfg(). + +Signed-off-by: Hayes Wang <hayeswang@realtek.com> +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +--- + drivers/net/usb/r8152.c | 68 ++++++++++++++++++++++++----------------- + 1 file changed, 40 insertions(+), 28 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -1372,6 +1372,10 @@ void write_mii_word(struct net_device *n + static int + r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags); + ++static int ++rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex, ++ u32 advertising); ++ + static int rtl8152_set_mac_address(struct net_device *netdev, void *p) + { + struct r8152 *tp = netdev_priv(netdev); +@@ -3183,8 +3187,6 @@ static void r8153b_ups_en(struct r8152 * + ocp_data |= BIT(0); + ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data); + } else { +- u16 data; +- + ocp_data &= ~(UPS_EN | USP_PREWAKE); + ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); + +@@ -3192,31 +3194,20 @@ static void r8153b_ups_en(struct r8152 * + ocp_data &= ~BIT(0); + ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data); + +- ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); +- ocp_data &= ~PCUT_STATUS; +- ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); ++ if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) { ++ int i; + +- data = r8153_phy_status(tp, 0); ++ for (i = 0; i < 500; i++) { ++ if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & ++ AUTOLOAD_DONE) ++ break; ++ msleep(20); ++ } + +- switch (data) { +- case PHY_STAT_PWRDN: +- case PHY_STAT_EXT_INIT: +- r8153b_green_en(tp, +- test_bit(GREEN_ETHERNET, &tp->flags)); +- +- data = r8152_mdio_read(tp, MII_BMCR); +- data &= ~BMCR_PDOWN; +- data |= BMCR_RESET; +- r8152_mdio_write(tp, MII_BMCR, data); ++ tp->rtl_ops.hw_phy_cfg(tp); + +- data = r8153_phy_status(tp, PHY_STAT_LAN_ON); +- fallthrough; +- +- default: +- if (data != PHY_STAT_LAN_ON) +- netif_warn(tp, link, tp->netdev, +- "PHY not ready"); +- break; ++ rtl8152_set_speed(tp, tp->autoneg, tp->speed, ++ tp->duplex, tp->advertising); + } + } + } +@@ -4588,13 +4579,37 @@ static void r8153b_hw_phy_cfg(struct r81 + u32 ocp_data; + u16 data; + ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); ++ if (ocp_data & PCUT_STATUS) { ++ ocp_data &= ~PCUT_STATUS; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); ++ } ++ + /* disable ALDPS before updating the PHY parameters */ + r8153_aldps_en(tp, false); + + /* disable EEE before updating the PHY parameters */ + rtl_eee_enable(tp, false); + +- rtl8152_apply_firmware(tp, false); ++ /* U1/U2/L1 idle timer. 500 us */ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500); ++ ++ data = r8153_phy_status(tp, 0); ++ ++ switch (data) { ++ case PHY_STAT_PWRDN: ++ case PHY_STAT_EXT_INIT: ++ rtl8152_apply_firmware(tp, true); ++ ++ data = r8152_mdio_read(tp, MII_BMCR); ++ data &= ~BMCR_PDOWN; ++ r8152_mdio_write(tp, MII_BMCR, data); ++ break; ++ case PHY_STAT_LAN_ON: ++ default: ++ rtl8152_apply_firmware(tp, false); ++ break; ++ } + + r8153b_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags)); + +@@ -5543,9 +5558,6 @@ static void r8153b_init(struct r8152 *tp + /* MSC timer = 0xfff * 8ms = 32760 ms */ + ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff); + +- /* U1/U2/L1 idle timer. 500 us */ +- ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500); +- + r8153b_power_cut_en(tp, false); + r8153b_ups_en(tp, false); + r8153_queue_wake(tp, false); diff --git a/target/linux/generic/backport-5.10/786-v5.12-r8152-enable-U1-U2-for-USB_SPEED_SUPER.patch b/target/linux/generic/backport-5.10/786-v5.12-r8152-enable-U1-U2-for-USB_SPEED_SUPER.patch new file mode 100644 index 0000000000..8cf91c3893 --- /dev/null +++ b/target/linux/generic/backport-5.10/786-v5.12-r8152-enable-U1-U2-for-USB_SPEED_SUPER.patch @@ -0,0 +1,47 @@ +From 69b4339c0b9f3edc6a8f681f05efaaf4add1bb0e Mon Sep 17 00:00:00 2001 +From: Hayes Wang <hayeswang@realtek.com> +Date: Fri, 19 Feb 2021 17:04:40 +0800 +Subject: [PATCH] r8152: enable U1/U2 for USB_SPEED_SUPER + +commit 7a0ae61acde2cebd69665837170405eced86a6c7 upstream. + +U1/U2 shoued be enabled for USB 3.0 or later. The USB 2.0 doesn't +support it. + +Signed-off-by: Hayes Wang <hayeswang@realtek.com> +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +--- + drivers/net/usb/r8152.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -3336,7 +3336,7 @@ static void rtl8153b_runtime_enable(stru + r8153b_ups_en(tp, false); + r8153_queue_wake(tp, false); + rtl_runtime_suspend_enable(tp, false); +- if (tp->udev->speed != USB_SPEED_HIGH) ++ if (tp->udev->speed >= USB_SPEED_SUPER) + r8153b_u1u2en(tp, true); + } + } +@@ -5029,7 +5029,7 @@ static void rtl8153b_up(struct r8152 *tp + + r8153_aldps_en(tp, true); + +- if (tp->udev->speed != USB_SPEED_HIGH) ++ if (tp->udev->speed >= USB_SPEED_SUPER) + r8153b_u1u2en(tp, true); + } + +@@ -5571,8 +5571,9 @@ static void r8153b_init(struct r8152 *tp + ocp_data |= POLL_LINK_CHG; + ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data); + +- if (tp->udev->speed != USB_SPEED_HIGH) ++ if (tp->udev->speed >= USB_SPEED_SUPER) + r8153b_u1u2en(tp, true); ++ + usb_enable_lpm(tp->udev); + + /* MAC clock speed down */ diff --git a/target/linux/generic/backport-5.10/787-v5.12-r8152-check-if-the-pointer-of-the-function-exists.patch b/target/linux/generic/backport-5.10/787-v5.12-r8152-check-if-the-pointer-of-the-function-exists.patch new file mode 100644 index 0000000000..5bc4e2b0a1 --- /dev/null +++ b/target/linux/generic/backport-5.10/787-v5.12-r8152-check-if-the-pointer-of-the-function-exists.patch @@ -0,0 +1,51 @@ +From e78b75f5be204a0a235da995d01c778dc282bb42 Mon Sep 17 00:00:00 2001 +From: Hayes Wang <hayeswang@realtek.com> +Date: Fri, 19 Feb 2021 17:04:41 +0800 +Subject: [PATCH] r8152: check if the pointer of the function exists + +commit c79515e47935c747282c6ed2ee5b2ef039756eeb upstream. + +Return error code if autosuspend_en, eee_get, or eee_set don't exist. + +Signed-off-by: Hayes Wang <hayeswang@realtek.com> +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +--- + drivers/net/usb/r8152.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -5758,6 +5758,9 @@ static int rtl8152_runtime_suspend(struc + struct net_device *netdev = tp->netdev; + int ret = 0; + ++ if (!tp->rtl_ops.autosuspend_en) ++ return -EBUSY; ++ + set_bit(SELECTIVE_SUSPEND, &tp->flags); + smp_mb__after_atomic(); + +@@ -6157,6 +6160,11 @@ rtl_ethtool_get_eee(struct net_device *n + struct r8152 *tp = netdev_priv(net); + int ret; + ++ if (!tp->rtl_ops.eee_get) { ++ ret = -EOPNOTSUPP; ++ goto out; ++ } ++ + ret = usb_autopm_get_interface(tp->intf); + if (ret < 0) + goto out; +@@ -6179,6 +6187,11 @@ rtl_ethtool_set_eee(struct net_device *n + struct r8152 *tp = netdev_priv(net); + int ret; + ++ if (!tp->rtl_ops.eee_set) { ++ ret = -EOPNOTSUPP; ++ goto out; ++ } ++ + ret = usb_autopm_get_interface(tp->intf); + if (ret < 0) + goto out; diff --git a/target/linux/generic/backport-5.10/788-v5.12-r8152-replace-netif_err-with-dev_err.patch b/target/linux/generic/backport-5.10/788-v5.12-r8152-replace-netif_err-with-dev_err.patch new file mode 100644 index 0000000000..967b4ccc16 --- /dev/null +++ b/target/linux/generic/backport-5.10/788-v5.12-r8152-replace-netif_err-with-dev_err.patch @@ -0,0 +1,36 @@ +From 38e44c7926512cff0b2809dc329de2a8e769e523 Mon Sep 17 00:00:00 2001 +From: Hayes Wang <hayeswang@realtek.com> +Date: Fri, 19 Feb 2021 17:04:42 +0800 +Subject: [PATCH] r8152: replace netif_err with dev_err + +commit 156c3207611262266f0eea589ac3f00c5657320e upstream. + +Some messages are before calling register_netdev(), so replace +netif_err() with dev_err(). + +Signed-off-by: Hayes Wang <hayeswang@realtek.com> +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +--- + drivers/net/usb/r8152.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -6594,7 +6594,7 @@ static int rtl_ops_init(struct r8152 *tp + + default: + ret = -ENODEV; +- netif_err(tp, probe, tp->netdev, "Unknown Device\n"); ++ dev_err(&tp->intf->dev, "Unknown Device\n"); + break; + } + +@@ -6851,7 +6851,7 @@ static int rtl8152_probe(struct usb_inte + + ret = register_netdev(netdev); + if (ret != 0) { +- netif_err(tp, probe, netdev, "couldn't register the device\n"); ++ dev_err(&intf->dev, "couldn't register the device\n"); + goto out1; + } + diff --git a/target/linux/generic/backport-5.10/789-v5.12-r8152-spilt-rtl_set_eee_plus-and-r8153b_green_en.patch b/target/linux/generic/backport-5.10/789-v5.12-r8152-spilt-rtl_set_eee_plus-and-r8153b_green_en.patch new file mode 100644 index 0000000000..c49a4ce5b6 --- /dev/null +++ b/target/linux/generic/backport-5.10/789-v5.12-r8152-spilt-rtl_set_eee_plus-and-r8153b_green_en.patch @@ -0,0 +1,89 @@ +From 260814de2d6cb958767785ffcb2e76915d1be32b Mon Sep 17 00:00:00 2001 +From: Hayes Wang <hayeswang@realtek.com> +Date: Fri, 19 Feb 2021 17:04:43 +0800 +Subject: [PATCH] r8152: spilt rtl_set_eee_plus and r8153b_green_en + +commit 40fa7568ac230446d888b7ad402cff9e20fe3ad5 upstream. + +Add rtl_eee_plus_en() and rtl_green_en(). + +Signed-off-by: Hayes Wang <hayeswang@realtek.com> +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +--- + drivers/net/usb/r8152.c | 43 ++++++++++++++++++++++++++--------------- + 1 file changed, 27 insertions(+), 16 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -2633,21 +2633,24 @@ static inline u8 rtl8152_get_speed(struc + return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS); + } + +-static void rtl_set_eee_plus(struct r8152 *tp) ++static void rtl_eee_plus_en(struct r8152 *tp, bool enable) + { + u32 ocp_data; +- u8 speed; + +- speed = rtl8152_get_speed(tp); +- if (speed & _10bps) { +- ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); ++ if (enable) + ocp_data |= EEEP_CR_EEEP_TX; +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); +- } else { +- ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); ++ else + ocp_data &= ~EEEP_CR_EEEP_TX; +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); +- } ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); ++} ++ ++static void rtl_set_eee_plus(struct r8152 *tp) ++{ ++ if (rtl8152_get_speed(tp) & _10bps) ++ rtl_eee_plus_en(tp, true); ++ else ++ rtl_eee_plus_en(tp, false); + } + + static void rxdy_gated_en(struct r8152 *tp, bool enable) +@@ -3128,10 +3131,22 @@ static void r8153b_ups_flags(struct r815 + ocp_write_dword(tp, MCU_TYPE_USB, USB_UPS_FLAGS, ups_flags); + } + +-static void r8153b_green_en(struct r8152 *tp, bool enable) ++static void rtl_green_en(struct r8152 *tp, bool enable) + { + u16 data; + ++ data = sram_read(tp, SRAM_GREEN_CFG); ++ if (enable) ++ data |= GREEN_ETH_EN; ++ else ++ data &= ~GREEN_ETH_EN; ++ sram_write(tp, SRAM_GREEN_CFG, data); ++ ++ tp->ups_info.green = enable; ++} ++ ++static void r8153b_green_en(struct r8152 *tp, bool enable) ++{ + if (enable) { + sram_write(tp, 0x8045, 0); /* 10M abiq&ldvbias */ + sram_write(tp, 0x804d, 0x1222); /* 100M short abiq&ldvbias */ +@@ -3142,11 +3157,7 @@ static void r8153b_green_en(struct r8152 + sram_write(tp, 0x805d, 0x2444); /* 1000M short abiq&ldvbias */ + } + +- data = sram_read(tp, SRAM_GREEN_CFG); +- data |= GREEN_ETH_EN; +- sram_write(tp, SRAM_GREEN_CFG, data); +- +- tp->ups_info.green = enable; ++ rtl_green_en(tp, true); + } + + static u16 r8153_phy_status(struct r8152 *tp, u16 desired) diff --git a/target/linux/generic/backport-5.10/790-v5.13-r8152-set-inter-fram-gap-time-depending-on-speed.patch b/target/linux/generic/backport-5.10/790-v5.13-r8152-set-inter-fram-gap-time-depending-on-speed.patch new file mode 100644 index 0000000000..f2593e8f00 --- /dev/null +++ b/target/linux/generic/backport-5.10/790-v5.13-r8152-set-inter-fram-gap-time-depending-on-speed.patch @@ -0,0 +1,75 @@ +From f1bbbb260a8016373adf239c716d2da90e6ced0b Mon Sep 17 00:00:00 2001 +From: Hayes Wang <hayeswang@realtek.com> +Date: Fri, 16 Apr 2021 16:04:32 +0800 +Subject: [PATCH] r8152: set inter fram gap time depending on speed + +commit 5133bcc7481528e36fff0a3b056601efb704fb32 upstream. + +Set the maximum inter frame gap time (144ns) for speed 10M/half and +100M/half. It improves the performance for those speeds. And, there +is no effect for the other speeds. + +For 10M/half and 100M/half, the fast inter frame gap time let the +device couldn't use the feature of the aggregation effectively, +because the transfer would be completed fastly. Therefore, use the +maximum value to improve the effect of the aggregation. However, you +may not feel the improvement for fast CPUs, because they compensate +for the effect of the aggregation. + +Signed-off-by: Hayes Wang <hayeswang@realtek.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/usb/r8152.c | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -250,6 +250,9 @@ + + /* PLA_TCR1 */ + #define VERSION_MASK 0x7cf0 ++#define IFG_MASK (BIT(3) | BIT(9) | BIT(8)) ++#define IFG_144NS BIT(9) ++#define IFG_96NS (BIT(9) | BIT(8)) + + /* PLA_MTPS */ + #define MTPS_JUMBO (12 * 1024 / 64) +@@ -2748,6 +2751,29 @@ static int rtl_stop_rx(struct r8152 *tp) + return 0; + } + ++static void rtl_set_ifg(struct r8152 *tp, u16 speed) ++{ ++ u32 ocp_data; ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR1); ++ ocp_data &= ~IFG_MASK; ++ if ((speed & (_10bps | _100bps)) && !(speed & FULL_DUP)) { ++ ocp_data |= IFG_144NS; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR1, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); ++ ocp_data &= ~TX10MIDLE_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); ++ } else { ++ ocp_data |= IFG_96NS; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR1, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); ++ ocp_data |= TX10MIDLE_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); ++ } ++} ++ + static inline void r8153b_rx_agg_chg_indicate(struct r8152 *tp) + { + ocp_write_byte(tp, MCU_TYPE_USB, USB_UPT_RXDMA_OWN, +@@ -2851,6 +2877,8 @@ static int rtl8153_enable(struct r8152 * + r8153_set_rx_early_timeout(tp); + r8153_set_rx_early_size(tp); + ++ rtl_set_ifg(tp, rtl8152_get_speed(tp)); ++ + if (tp->version == RTL_VER_09) { + u32 ocp_data; + diff --git a/target/linux/generic/backport-5.10/791-v5.13-r8152-adjust-rtl8152_check_firmware-function.patch b/target/linux/generic/backport-5.10/791-v5.13-r8152-adjust-rtl8152_check_firmware-function.patch new file mode 100644 index 0000000000..cddd39ea94 --- /dev/null +++ b/target/linux/generic/backport-5.10/791-v5.13-r8152-adjust-rtl8152_check_firmware-function.patch @@ -0,0 +1,152 @@ +From f10c9edf47d3fa240d965e151a48c670f5035b73 Mon Sep 17 00:00:00 2001 +From: Hayes Wang <hayeswang@realtek.com> +Date: Fri, 16 Apr 2021 16:04:33 +0800 +Subject: [PATCH] r8152: adjust rtl8152_check_firmware function + +commit a8a7be178e81a3d4b6972cbeb0ccd091ca2f9f89 upstream. + +Use bits operations to record and check the firmware. + +Signed-off-by: Hayes Wang <hayeswang@realtek.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/usb/r8152.c | 51 +++++++++++++++++++++++------------------ + 1 file changed, 29 insertions(+), 22 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -875,6 +875,14 @@ struct fw_header { + struct fw_block blocks[]; + } __packed; + ++enum rtl8152_fw_flags { ++ FW_FLAGS_USB = 0, ++ FW_FLAGS_PLA, ++ FW_FLAGS_START, ++ FW_FLAGS_STOP, ++ FW_FLAGS_NC, ++}; ++ + /** + * struct fw_mac - a firmware block used by RTL_FW_PLA and RTL_FW_USB. + * The layout of the firmware block is: +@@ -3801,10 +3809,7 @@ static long rtl8152_check_firmware(struc + { + const struct firmware *fw = rtl_fw->fw; + struct fw_header *fw_hdr = (struct fw_header *)fw->data; +- struct fw_mac *pla = NULL, *usb = NULL; +- struct fw_phy_patch_key *start = NULL; +- struct fw_phy_nc *phy_nc = NULL; +- struct fw_block *stop = NULL; ++ unsigned long fw_flags = 0; + long ret = -EFAULT; + int i; + +@@ -3833,50 +3838,52 @@ static long rtl8152_check_firmware(struc + goto fail; + goto fw_end; + case RTL_FW_PLA: +- if (pla) { ++ if (test_bit(FW_FLAGS_PLA, &fw_flags)) { + dev_err(&tp->intf->dev, + "multiple PLA firmware encountered"); + goto fail; + } + +- pla = (struct fw_mac *)block; +- if (!rtl8152_is_fw_mac_ok(tp, pla)) { ++ if (!rtl8152_is_fw_mac_ok(tp, (struct fw_mac *)block)) { + dev_err(&tp->intf->dev, + "check PLA firmware failed\n"); + goto fail; + } ++ __set_bit(FW_FLAGS_PLA, &fw_flags); + break; + case RTL_FW_USB: +- if (usb) { ++ if (test_bit(FW_FLAGS_USB, &fw_flags)) { + dev_err(&tp->intf->dev, + "multiple USB firmware encountered"); + goto fail; + } + +- usb = (struct fw_mac *)block; +- if (!rtl8152_is_fw_mac_ok(tp, usb)) { ++ if (!rtl8152_is_fw_mac_ok(tp, (struct fw_mac *)block)) { + dev_err(&tp->intf->dev, + "check USB firmware failed\n"); + goto fail; + } ++ __set_bit(FW_FLAGS_USB, &fw_flags); + break; + case RTL_FW_PHY_START: +- if (start || phy_nc || stop) { ++ if (test_bit(FW_FLAGS_START, &fw_flags) || ++ test_bit(FW_FLAGS_NC, &fw_flags) || ++ test_bit(FW_FLAGS_STOP, &fw_flags)) { + dev_err(&tp->intf->dev, + "check PHY_START fail\n"); + goto fail; + } + +- if (__le32_to_cpu(block->length) != sizeof(*start)) { ++ if (__le32_to_cpu(block->length) != sizeof(struct fw_phy_patch_key)) { + dev_err(&tp->intf->dev, + "Invalid length for PHY_START\n"); + goto fail; + } +- +- start = (struct fw_phy_patch_key *)block; ++ __set_bit(FW_FLAGS_START, &fw_flags); + break; + case RTL_FW_PHY_STOP: +- if (stop || !start) { ++ if (test_bit(FW_FLAGS_STOP, &fw_flags) || ++ !test_bit(FW_FLAGS_START, &fw_flags)) { + dev_err(&tp->intf->dev, + "Check PHY_STOP fail\n"); + goto fail; +@@ -3887,28 +3894,28 @@ static long rtl8152_check_firmware(struc + "Invalid length for PHY_STOP\n"); + goto fail; + } +- +- stop = block; ++ __set_bit(FW_FLAGS_STOP, &fw_flags); + break; + case RTL_FW_PHY_NC: +- if (!start || stop) { ++ if (!test_bit(FW_FLAGS_START, &fw_flags) || ++ test_bit(FW_FLAGS_STOP, &fw_flags)) { + dev_err(&tp->intf->dev, + "check PHY_NC fail\n"); + goto fail; + } + +- if (phy_nc) { ++ if (test_bit(FW_FLAGS_NC, &fw_flags)) { + dev_err(&tp->intf->dev, + "multiple PHY NC encountered\n"); + goto fail; + } + +- phy_nc = (struct fw_phy_nc *)block; +- if (!rtl8152_is_fw_phy_nc_ok(tp, phy_nc)) { ++ if (!rtl8152_is_fw_phy_nc_ok(tp, (struct fw_phy_nc *)block)) { + dev_err(&tp->intf->dev, + "check PHY NC firmware failed\n"); + goto fail; + } ++ __set_bit(FW_FLAGS_NC, &fw_flags); + + break; + default: +@@ -3922,7 +3929,7 @@ static long rtl8152_check_firmware(struc + } + + fw_end: +- if ((phy_nc || start) && !stop) { ++ if (test_bit(FW_FLAGS_START, &fw_flags) && !test_bit(FW_FLAGS_STOP, &fw_flags)) { + dev_err(&tp->intf->dev, "without PHY_STOP\n"); + goto fail; + } diff --git a/target/linux/generic/backport-5.10/792-v5.13-r8152-add-help-function-to-change-mtu.patch b/target/linux/generic/backport-5.10/792-v5.13-r8152-add-help-function-to-change-mtu.patch new file mode 100644 index 0000000000..3559e3b95a --- /dev/null +++ b/target/linux/generic/backport-5.10/792-v5.13-r8152-add-help-function-to-change-mtu.patch @@ -0,0 +1,157 @@ +From f010a7d51cbb42bdb956f0a28b8868b15d7a3816 Mon Sep 17 00:00:00 2001 +From: Hayes Wang <hayeswang@realtek.com> +Date: Fri, 16 Apr 2021 16:04:34 +0800 +Subject: [PATCH] r8152: add help function to change mtu + +commit 67ce1a806f164e59a074fea8809725d3411eaa20 upstream. + +The different chips may have different requests when changing mtu. +Therefore, add a new help function of rtl_ops to change mtu. Besides, +reset the tx/rx after changing mtu. + +Additionally, add mtu_to_size() and size_to_mtu() macros to simplify +the code. + +Signed-off-by: Hayes Wang <hayeswang@realtek.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/usb/r8152.c | 53 ++++++++++++++++++++++++----------------- + 1 file changed, 31 insertions(+), 22 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -658,15 +658,13 @@ enum rtl_register_content { + + #define INTR_LINK 0x0004 + +-#define RTL8153_MAX_PACKET 9216 /* 9K */ +-#define RTL8153_MAX_MTU (RTL8153_MAX_PACKET - VLAN_ETH_HLEN - \ +- ETH_FCS_LEN) + #define RTL8152_RMS (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) + #define RTL8153_RMS RTL8153_MAX_PACKET + #define RTL8152_TX_TIMEOUT (5 * HZ) + #define RTL8152_NAPI_WEIGHT 64 +-#define rx_reserved_size(x) ((x) + VLAN_ETH_HLEN + ETH_FCS_LEN + \ +- sizeof(struct rx_desc) + RX_ALIGN) ++#define mtu_to_size(m) ((m) + VLAN_ETH_HLEN + ETH_FCS_LEN) ++#define size_to_mtu(s) ((s) - VLAN_ETH_HLEN - ETH_FCS_LEN) ++#define rx_reserved_size(x) (mtu_to_size(x) + sizeof(struct rx_desc) + RX_ALIGN) + + /* rtl8152 flags */ + enum rtl8152_flags { +@@ -796,6 +794,7 @@ struct r8152 { + bool (*in_nway)(struct r8152 *tp); + void (*hw_phy_cfg)(struct r8152 *tp); + void (*autosuspend_en)(struct r8152 *tp, bool enable); ++ void (*change_mtu)(struct r8152 *tp); + } rtl_ops; + + struct ups_info { +@@ -1022,8 +1021,7 @@ enum tx_csum_stat { + static const int multicast_filter_limit = 32; + static unsigned int agg_buf_sz = 16384; + +-#define RTL_LIMITED_TSO_SIZE (agg_buf_sz - sizeof(struct tx_desc) - \ +- VLAN_ETH_HLEN - ETH_FCS_LEN) ++#define RTL_LIMITED_TSO_SIZE (size_to_mtu(agg_buf_sz) - sizeof(struct tx_desc)) + + static + int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) +@@ -2633,10 +2631,7 @@ static void rtl8152_nic_reset(struct r81 + + static void set_tx_qlen(struct r8152 *tp) + { +- struct net_device *netdev = tp->netdev; +- +- tp->tx_qlen = agg_buf_sz / (netdev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN + +- sizeof(struct tx_desc)); ++ tp->tx_qlen = agg_buf_sz / (mtu_to_size(tp->netdev->mtu) + sizeof(struct tx_desc)); + } + + static inline u8 rtl8152_get_speed(struct r8152 *tp) +@@ -4725,6 +4720,12 @@ static void r8153b_hw_phy_cfg(struct r81 + set_bit(PHY_RESET, &tp->flags); + } + ++static void rtl8153_change_mtu(struct r8152 *tp) ++{ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, mtu_to_size(tp->netdev->mtu)); ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO); ++} ++ + static void r8153_first_init(struct r8152 *tp) + { + u32 ocp_data; +@@ -4757,9 +4758,7 @@ static void r8153_first_init(struct r815 + + rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX); + +- ocp_data = tp->netdev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data); +- ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO); ++ rtl8153_change_mtu(tp); + + ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0); + ocp_data |= TCR0_AUTO_FIFO; +@@ -4794,8 +4793,7 @@ static void r8153_enter_oob(struct r8152 + + wait_oob_link_list_ready(tp); + +- ocp_data = tp->netdev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, mtu_to_size(tp->netdev->mtu)); + + switch (tp->version) { + case RTL_VER_03: +@@ -6518,12 +6516,21 @@ static int rtl8152_change_mtu(struct net + dev->mtu = new_mtu; + + if (netif_running(dev)) { +- u32 rms = new_mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; +- +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, rms); ++ if (tp->rtl_ops.change_mtu) ++ tp->rtl_ops.change_mtu(tp); + +- if (netif_carrier_ok(dev)) +- r8153_set_rx_early_size(tp); ++ if (netif_carrier_ok(dev)) { ++ netif_stop_queue(dev); ++ napi_disable(&tp->napi); ++ tasklet_disable(&tp->tx_tl); ++ tp->rtl_ops.disable(tp); ++ tp->rtl_ops.enable(tp); ++ rtl_start_rx(tp); ++ tasklet_enable(&tp->tx_tl); ++ napi_enable(&tp->napi); ++ rtl8152_set_rx_mode(dev); ++ netif_wake_queue(dev); ++ } + } + + mutex_unlock(&tp->control); +@@ -6612,6 +6619,7 @@ static int rtl_ops_init(struct r8152 *tp + ops->in_nway = rtl8153_in_nway; + ops->hw_phy_cfg = r8153_hw_phy_cfg; + ops->autosuspend_en = rtl8153_runtime_enable; ++ ops->change_mtu = rtl8153_change_mtu; + if (tp->udev->speed < USB_SPEED_SUPER) + tp->rx_buf_sz = 16 * 1024; + else +@@ -6633,6 +6641,7 @@ static int rtl_ops_init(struct r8152 *tp + ops->in_nway = rtl8153_in_nway; + ops->hw_phy_cfg = r8153b_hw_phy_cfg; + ops->autosuspend_en = rtl8153b_runtime_enable; ++ ops->change_mtu = rtl8153_change_mtu; + tp->rx_buf_sz = 32 * 1024; + tp->eee_en = true; + tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; +@@ -6853,7 +6862,7 @@ static int rtl8152_probe(struct usb_inte + netdev->max_mtu = ETH_DATA_LEN; + break; + default: +- netdev->max_mtu = RTL8153_MAX_MTU; ++ netdev->max_mtu = size_to_mtu(9 * 1024); + break; + } + diff --git a/target/linux/generic/backport-5.10/793-v5.13-r8152-support-new-chips.patch b/target/linux/generic/backport-5.10/793-v5.13-r8152-support-new-chips.patch new file mode 100644 index 0000000000..06a141b451 --- /dev/null +++ b/target/linux/generic/backport-5.10/793-v5.13-r8152-support-new-chips.patch @@ -0,0 +1,2886 @@ +From e7439e7fd384f55f55837f7e4866e74d8dca3827 Mon Sep 17 00:00:00 2001 +From: Hayes Wang <hayeswang@realtek.com> +Date: Fri, 16 Apr 2021 16:04:35 +0800 +Subject: [PATCH] r8152: support new chips + +commit 195aae321c829dd1945900d75561e6aa79cce208 upstream. + +Support RTL8153C, RTL8153D, RTL8156A, and RTL8156B. The RTL8156A +and RTL8156B are the 2.5G ethernet. + +Signed-off-by: Hayes Wang <hayeswang@realtek.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/usb/r8152.c | 2634 +++++++++++++++++++++++++++++++++++---- + 1 file changed, 2359 insertions(+), 275 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -44,10 +44,14 @@ + + #define PLA_IDR 0xc000 + #define PLA_RCR 0xc010 ++#define PLA_RCR1 0xc012 + #define PLA_RMS 0xc016 + #define PLA_RXFIFO_CTRL0 0xc0a0 ++#define PLA_RXFIFO_FULL 0xc0a2 + #define PLA_RXFIFO_CTRL1 0xc0a4 ++#define PLA_RX_FIFO_FULL 0xc0a6 + #define PLA_RXFIFO_CTRL2 0xc0a8 ++#define PLA_RX_FIFO_EMPTY 0xc0aa + #define PLA_DMY_REG0 0xc0b0 + #define PLA_FMC 0xc0b4 + #define PLA_CFG_WOL 0xc0b6 +@@ -64,6 +68,8 @@ + #define PLA_MACDBG_PRE 0xd38c /* RTL_VER_04 only */ + #define PLA_MACDBG_POST 0xd38e /* RTL_VER_04 only */ + #define PLA_EXTRA_STATUS 0xd398 ++#define PLA_GPHY_CTRL 0xd3ae ++#define PLA_POL_GPIO_CTRL 0xdc6a + #define PLA_EFUSE_DATA 0xdd00 + #define PLA_EFUSE_CMD 0xdd02 + #define PLA_LEDSEL 0xdd90 +@@ -73,6 +79,8 @@ + #define PLA_LWAKE_CTRL_REG 0xe007 + #define PLA_GPHY_INTR_IMR 0xe022 + #define PLA_EEE_CR 0xe040 ++#define PLA_EEE_TXTWSYS 0xe04c ++#define PLA_EEE_TXTWSYS_2P5G 0xe058 + #define PLA_EEEP_CR 0xe080 + #define PLA_MAC_PWR_CTRL 0xe0c0 + #define PLA_MAC_PWR_CTRL2 0xe0ca +@@ -83,6 +91,7 @@ + #define PLA_TCR1 0xe612 + #define PLA_MTPS 0xe615 + #define PLA_TXFIFO_CTRL 0xe618 ++#define PLA_TXFIFO_FULL 0xe61a + #define PLA_RSTTALLY 0xe800 + #define PLA_CR 0xe813 + #define PLA_CRWECR 0xe81c +@@ -99,6 +108,7 @@ + #define PLA_SFF_STS_7 0xe8de + #define PLA_PHYSTATUS 0xe908 + #define PLA_CONFIG6 0xe90a /* CONFIG6 */ ++#define PLA_USB_CFG 0xe952 + #define PLA_BP_BA 0xfc26 + #define PLA_BP_0 0xfc28 + #define PLA_BP_1 0xfc2a +@@ -113,6 +123,7 @@ + #define USB_USB2PHY 0xb41e + #define USB_SSPHYLINK1 0xb426 + #define USB_SSPHYLINK2 0xb428 ++#define USB_L1_CTRL 0xb45e + #define USB_U2P3_CTRL 0xb460 + #define USB_CSR_DUMMY1 0xb464 + #define USB_CSR_DUMMY2 0xb466 +@@ -123,7 +134,12 @@ + #define USB_FW_FIX_EN0 0xcfca + #define USB_FW_FIX_EN1 0xcfcc + #define USB_LPM_CONFIG 0xcfd8 ++#define USB_ECM_OPTION 0xcfee + #define USB_CSTMR 0xcfef /* RTL8153A */ ++#define USB_MISC_2 0xcfff ++#define USB_ECM_OP 0xd26b ++#define USB_GPHY_CTRL 0xd284 ++#define USB_SPEED_OPTION 0xd32a + #define USB_FW_CTRL 0xd334 /* RTL8153B */ + #define USB_FC_TIMER 0xd340 + #define USB_USB_CTRL 0xd406 +@@ -137,16 +153,20 @@ + #define USB_RX_EXTRA_AGGR_TMR 0xd432 /* RTL8153B */ + #define USB_TX_DMA 0xd434 + #define USB_UPT_RXDMA_OWN 0xd437 ++#define USB_UPHY3_MDCMDIO 0xd480 + #define USB_TOLERANCE 0xd490 + #define USB_LPM_CTRL 0xd41a + #define USB_BMU_RESET 0xd4b0 ++#define USB_BMU_CONFIG 0xd4b4 + #define USB_U1U2_TIMER 0xd4da + #define USB_FW_TASK 0xd4e8 /* RTL8153B */ ++#define USB_RX_AGGR_NUM 0xd4ee + #define USB_UPS_CTRL 0xd800 + #define USB_POWER_CUT 0xd80a + #define USB_MISC_0 0xd81a + #define USB_MISC_1 0xd81f + #define USB_AFE_CTRL2 0xd824 ++#define USB_UPHY_XTAL 0xd826 + #define USB_UPS_CFG 0xd842 + #define USB_UPS_FLAGS 0xd848 + #define USB_WDT1_CTRL 0xe404 +@@ -189,6 +209,9 @@ + #define OCP_EEE_ABLE 0xa5c4 + #define OCP_EEE_ADV 0xa5d0 + #define OCP_EEE_LPABLE 0xa5d2 ++#define OCP_10GBT_CTRL 0xa5d4 ++#define OCP_10GBT_STAT 0xa5d6 ++#define OCP_EEE_ADV2 0xa6d4 + #define OCP_PHY_STATE 0xa708 /* nway state for 8153 */ + #define OCP_PHY_PATCH_STAT 0xb800 + #define OCP_PHY_PATCH_CMD 0xb820 +@@ -200,6 +223,7 @@ + /* SRAM Register */ + #define SRAM_GREEN_CFG 0x8011 + #define SRAM_LPF_CFG 0x8012 ++#define SRAM_GPHY_FW_VER 0x801e + #define SRAM_10M_AMP1 0x8080 + #define SRAM_10M_AMP2 0x8082 + #define SRAM_IMPEDANCE 0x8084 +@@ -211,11 +235,19 @@ + #define RCR_AM 0x00000004 + #define RCR_AB 0x00000008 + #define RCR_ACPT_ALL (RCR_AAP | RCR_APM | RCR_AM | RCR_AB) ++#define SLOT_EN BIT(11) ++ ++/* PLA_RCR1 */ ++#define OUTER_VLAN BIT(7) ++#define INNER_VLAN BIT(6) + + /* PLA_RXFIFO_CTRL0 */ + #define RXFIFO_THR1_NORMAL 0x00080002 + #define RXFIFO_THR1_OOB 0x01800003 + ++/* PLA_RXFIFO_FULL */ ++#define RXFIFO_FULL_MASK 0xfff ++ + /* PLA_RXFIFO_CTRL1 */ + #define RXFIFO_THR2_FULL 0x00000060 + #define RXFIFO_THR2_HIGH 0x00000038 +@@ -286,6 +318,7 @@ + #define MCU_BORW_EN 0x4000 + + /* PLA_CPCR */ ++#define FLOW_CTRL_EN BIT(0) + #define CPCR_RX_VLAN 0x0040 + + /* PLA_CFG_WOL */ +@@ -311,6 +344,10 @@ + /* PLA_CONFIG6 */ + #define LANWAKE_CLR_EN BIT(0) + ++/* PLA_USB_CFG */ ++#define EN_XG_LIP BIT(1) ++#define EN_G_LIP BIT(2) ++ + /* PLA_CONFIG5 */ + #define BWF_EN 0x0040 + #define MWF_EN 0x0020 +@@ -334,6 +371,7 @@ + /* PLA_MAC_PWR_CTRL2 */ + #define EEE_SPDWN_RATIO 0x8007 + #define MAC_CLK_SPDWN_EN BIT(15) ++#define EEE_SPDWN_RATIO_MASK 0xff + + /* PLA_MAC_PWR_CTRL3 */ + #define PLA_MCU_SPDWN_EN BIT(14) +@@ -346,6 +384,7 @@ + #define PWRSAVE_SPDWN_EN 0x1000 + #define RXDV_SPDWN_EN 0x0800 + #define TX10MIDLE_EN 0x0100 ++#define IDLE_SPDWN_EN BIT(6) + #define TP100_SPDWN_EN 0x0020 + #define TP500_SPDWN_EN 0x0010 + #define TP1000_SPDWN_EN 0x0008 +@@ -386,6 +425,13 @@ + #define LINK_CHANGE_FLAG BIT(8) + #define POLL_LINK_CHG BIT(0) + ++/* PLA_GPHY_CTRL */ ++#define GPHY_FLASH BIT(1) ++ ++/* PLA_POL_GPIO_CTRL */ ++#define DACK_DET_EN BIT(15) ++#define POL_GPHY_PATCH BIT(4) ++ + /* USB_USB2PHY */ + #define USB2PHY_SUSPEND 0x0001 + #define USB2PHY_L1 0x0002 +@@ -434,6 +480,9 @@ + #define BMU_RESET_EP_IN 0x01 + #define BMU_RESET_EP_OUT 0x02 + ++/* USB_BMU_CONFIG */ ++#define ACT_ODMA BIT(1) ++ + /* USB_UPT_RXDMA_OWN */ + #define OWN_UPDATE BIT(0) + #define OWN_CLEAR BIT(1) +@@ -441,27 +490,52 @@ + /* USB_FW_TASK */ + #define FC_PATCH_TASK BIT(1) + ++/* USB_RX_AGGR_NUM */ ++#define RX_AGGR_NUM_MASK 0x1ff ++ + /* USB_UPS_CTRL */ + #define POWER_CUT 0x0100 + + /* USB_PM_CTRL_STATUS */ + #define RESUME_INDICATE 0x0001 + ++/* USB_ECM_OPTION */ ++#define BYPASS_MAC_RESET BIT(5) ++ + /* USB_CSTMR */ + #define FORCE_SUPER BIT(0) + ++/* USB_MISC_2 */ ++#define UPS_FORCE_PWR_DOWN BIT(0) ++ ++/* USB_ECM_OP */ ++#define EN_ALL_SPEED BIT(0) ++ ++/* USB_GPHY_CTRL */ ++#define GPHY_PATCH_DONE BIT(2) ++#define BYPASS_FLASH BIT(5) ++#define BACKUP_RESTRORE BIT(6) ++ ++/* USB_SPEED_OPTION */ ++#define RG_PWRDN_EN BIT(8) ++#define ALL_SPEED_OFF BIT(9) ++ + /* USB_FW_CTRL */ + #define FLOW_CTRL_PATCH_OPT BIT(1) ++#define AUTO_SPEEDUP BIT(3) ++#define FLOW_CTRL_PATCH_2 BIT(8) + + /* USB_FC_TIMER */ + #define CTRL_TIMER_EN BIT(15) + + /* USB_USB_CTRL */ ++#define CDC_ECM_EN BIT(3) + #define RX_AGG_DISABLE 0x0010 + #define RX_ZERO_EN 0x0080 + + /* USB_U2P3_CTRL */ + #define U2P3_ENABLE 0x0001 ++#define RX_DETECT8 BIT(3) + + /* USB_POWER_CUT */ + #define PWR_EN 0x0001 +@@ -497,8 +571,12 @@ + #define SEN_VAL_NORMAL 0xa000 + #define SEL_RXIDLE 0x0100 + ++/* USB_UPHY_XTAL */ ++#define OOBS_POLLING BIT(8) ++ + /* USB_UPS_CFG */ + #define SAW_CNT_1MS_MASK 0x0fff ++#define MID_REVERSE BIT(5) /* RTL8156A */ + + /* USB_UPS_FLAGS */ + #define UPS_FLAGS_R_TUNE BIT(0) +@@ -506,6 +584,7 @@ + #define UPS_FLAGS_250M_CKDIV BIT(2) + #define UPS_FLAGS_EN_ALDPS BIT(3) + #define UPS_FLAGS_CTAP_SHORT_DIS BIT(4) ++#define UPS_FLAGS_SPEED_MASK (0xf << 16) + #define ups_flags_speed(x) ((x) << 16) + #define UPS_FLAGS_EN_EEE BIT(20) + #define UPS_FLAGS_EN_500M_EEE BIT(21) +@@ -526,6 +605,8 @@ enum spd_duplex { + FORCE_10M_FULL, + FORCE_100M_HALF, + FORCE_100M_FULL, ++ FORCE_1000M_FULL, ++ NWAY_2500M_FULL, + }; + + /* OCP_ALDPS_CONFIG */ +@@ -590,6 +671,9 @@ enum spd_duplex { + #define EN_10M_CLKDIV BIT(11) + #define EN_10M_BGOFF 0x0080 + ++/* OCP_10GBT_CTRL */ ++#define RTL_ADV2_5G_F_R BIT(5) /* Advertise 2.5GBASE-T fast-retrain */ ++ + /* OCP_PHY_STATE */ + #define TXDIS_STATE 0x01 + #define ABD_STATE 0x02 +@@ -609,7 +693,8 @@ enum spd_duplex { + #define EN_EMI_L 0x0040 + + /* OCP_SYSCLK_CFG */ +-#define clk_div_expo(x) (min(x, 5) << 8) ++#define sysclk_div_expo(x) (min(x, 5) << 8) ++#define clk_div_expo(x) (min(x, 5) << 4) + + /* SRAM_GREEN_CFG */ + #define GREEN_ETH_EN BIT(15) +@@ -640,6 +725,11 @@ enum spd_duplex { + #define BP4_SUPER_ONLY 0x1578 /* RTL_VER_04 only */ + + enum rtl_register_content { ++ _2500bps = BIT(10), ++ _1250bps = BIT(9), ++ _500bps = BIT(8), ++ _tx_flow = BIT(6), ++ _rx_flow = BIT(5), + _1000bps = 0x10, + _100bps = 0x08, + _10bps = 0x04, +@@ -647,6 +737,9 @@ enum rtl_register_content { + FULL_DUP = 0x01, + }; + ++#define is_speed_2500(_speed) (((_speed) & (_2500bps | LINK_STATUS)) == (_2500bps | LINK_STATUS)) ++#define is_flow_control(_speed) (((_speed) & (_tx_flow | _rx_flow)) == (_tx_flow | _rx_flow)) ++ + #define RTL8152_MAX_TX 4 + #define RTL8152_MAX_RX 10 + #define INTBUFSIZE 2 +@@ -661,7 +754,6 @@ enum rtl_register_content { + #define RTL8152_RMS (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) + #define RTL8153_RMS RTL8153_MAX_PACKET + #define RTL8152_TX_TIMEOUT (5 * HZ) +-#define RTL8152_NAPI_WEIGHT 64 + #define mtu_to_size(m) ((m) + VLAN_ETH_HLEN + ETH_FCS_LEN) + #define size_to_mtu(s) ((s) - VLAN_ETH_HLEN - ETH_FCS_LEN) + #define rx_reserved_size(x) (mtu_to_size(x) + sizeof(struct rx_desc) + RX_ALIGN) +@@ -798,6 +890,7 @@ struct r8152 { + } rtl_ops; + + struct ups_info { ++ u32 r_tune:1; + u32 _10m_ckdiv:1; + u32 _250m_ckdiv:1; + u32 aldps:1; +@@ -839,7 +932,9 @@ struct r8152 { + u32 rx_buf_sz; + u32 rx_copybreak; + u32 rx_pending; ++ u32 fc_pause_on, fc_pause_off; + ++ u32 support_2500full:1; + u16 ocp_base; + u16 speed; + u16 eee_adv; +@@ -999,6 +1094,15 @@ enum rtl_version { + RTL_VER_07, + RTL_VER_08, + RTL_VER_09, ++ ++ RTL_TEST_01, ++ RTL_VER_10, ++ RTL_VER_11, ++ RTL_VER_12, ++ RTL_VER_13, ++ RTL_VER_14, ++ RTL_VER_15, ++ + RTL_VER_MAX + }; + +@@ -1014,6 +1118,7 @@ enum tx_csum_stat { + #define RTL_ADVERTISED_100_FULL BIT(3) + #define RTL_ADVERTISED_1000_HALF BIT(4) + #define RTL_ADVERTISED_1000_FULL BIT(5) ++#define RTL_ADVERTISED_2500_FULL BIT(6) + + /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). + * The RTL chips use a 64 element hash table based on the Ethernet CRC. +@@ -2607,7 +2712,7 @@ static netdev_tx_t rtl8152_start_xmit(st + + static void r8152b_reset_packet_filter(struct r8152 *tp) + { +- u32 ocp_data; ++ u32 ocp_data; + + ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_FMC); + ocp_data &= ~FMC_FCR_MCU_EN; +@@ -2618,14 +2723,47 @@ static void r8152b_reset_packet_filter(s + + static void rtl8152_nic_reset(struct r8152 *tp) + { +- int i; ++ u32 ocp_data; ++ int i; + +- ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, CR_RST); ++ switch (tp->version) { ++ case RTL_TEST_01: ++ case RTL_VER_10: ++ case RTL_VER_11: ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR); ++ ocp_data &= ~CR_TE; ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_BMU_RESET); ++ ocp_data &= ~BMU_RESET_EP_IN; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_BMU_RESET, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); ++ ocp_data |= CDC_ECM_EN; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR); ++ ocp_data &= ~CR_RE; ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_BMU_RESET); ++ ocp_data |= BMU_RESET_EP_IN; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_BMU_RESET, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); ++ ocp_data &= ~CDC_ECM_EN; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); ++ break; + +- for (i = 0; i < 1000; i++) { +- if (!(ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR) & CR_RST)) +- break; +- usleep_range(100, 400); ++ default: ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, CR_RST); ++ ++ for (i = 0; i < 1000; i++) { ++ if (!(ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR) & CR_RST)) ++ break; ++ usleep_range(100, 400); ++ } ++ break; + } + } + +@@ -2634,9 +2772,9 @@ static void set_tx_qlen(struct r8152 *tp + tp->tx_qlen = agg_buf_sz / (mtu_to_size(tp->netdev->mtu) + sizeof(struct tx_desc)); + } + +-static inline u8 rtl8152_get_speed(struct r8152 *tp) ++static inline u16 rtl8152_get_speed(struct r8152 *tp) + { +- return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS); ++ return ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHYSTATUS); + } + + static void rtl_eee_plus_en(struct r8152 *tp, bool enable) +@@ -2796,6 +2934,7 @@ static int rtl_enable(struct r8152 *tp) + switch (tp->version) { + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_VER_14: + r8153b_rx_agg_chg_indicate(tp); + break; + default: +@@ -2833,6 +2972,7 @@ static void r8153_set_rx_early_timeout(s + + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_VER_14: + /* The RTL8153B uses USB_RX_EXTRA_AGGR_TMR for rx timeout + * primarily. For USB_RX_EARLY_TIMEOUT, we fix it to 128ns. + */ +@@ -2842,6 +2982,18 @@ static void r8153_set_rx_early_timeout(s + ocp_data); + break; + ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: ++ ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_TIMEOUT, ++ 640 / 8); ++ ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EXTRA_AGGR_TMR, ++ ocp_data); ++ r8153b_rx_agg_chg_indicate(tp); ++ break; ++ + default: + break; + } +@@ -2861,8 +3013,19 @@ static void r8153_set_rx_early_size(stru + break; + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_VER_14: ++ ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE, ++ ocp_data / 8); ++ break; ++ case RTL_TEST_01: ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: + ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE, + ocp_data / 8); ++ r8153b_rx_agg_chg_indicate(tp); + break; + default: + WARN_ON_ONCE(1); +@@ -2872,6 +3035,8 @@ static void r8153_set_rx_early_size(stru + + static int rtl8153_enable(struct r8152 *tp) + { ++ u32 ocp_data; ++ + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return -ENODEV; + +@@ -2882,15 +3047,18 @@ static int rtl8153_enable(struct r8152 * + + rtl_set_ifg(tp, rtl8152_get_speed(tp)); + +- if (tp->version == RTL_VER_09) { +- u32 ocp_data; +- ++ switch (tp->version) { ++ case RTL_VER_09: ++ case RTL_VER_14: + ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK); + ocp_data &= ~FC_PATCH_TASK; + ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); + usleep_range(1000, 2000); + ocp_data |= FC_PATCH_TASK; + ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); ++ break; ++ default: ++ break; + } + + return rtl_enable(tp); +@@ -2955,12 +3123,40 @@ static void rtl_rx_vlan_en(struct r8152 + { + u32 ocp_data; + +- ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR); +- if (enable) +- ocp_data |= CPCR_RX_VLAN; +- else +- ocp_data &= ~CPCR_RX_VLAN; +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data); ++ switch (tp->version) { ++ case RTL_VER_01: ++ case RTL_VER_02: ++ case RTL_VER_03: ++ case RTL_VER_04: ++ case RTL_VER_05: ++ case RTL_VER_06: ++ case RTL_VER_07: ++ case RTL_VER_08: ++ case RTL_VER_09: ++ case RTL_VER_14: ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR); ++ if (enable) ++ ocp_data |= CPCR_RX_VLAN; ++ else ++ ocp_data &= ~CPCR_RX_VLAN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data); ++ break; ++ ++ case RTL_TEST_01: ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: ++ default: ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_RCR1); ++ if (enable) ++ ocp_data |= OUTER_VLAN | INNER_VLAN; ++ else ++ ocp_data &= ~(OUTER_VLAN | INNER_VLAN); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RCR1, ocp_data); ++ break; ++ } + } + + static int rtl8152_set_features(struct net_device *dev, +@@ -3053,6 +3249,40 @@ static void __rtl_set_wol(struct r8152 * + device_set_wakeup_enable(&tp->udev->dev, false); + } + ++static void r8153_mac_clk_speed_down(struct r8152 *tp, bool enable) ++{ ++ u32 ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2); ++ ++ /* MAC clock speed down */ ++ if (enable) ++ ocp_data |= MAC_CLK_SPDWN_EN; ++ else ++ ocp_data &= ~MAC_CLK_SPDWN_EN; ++ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data); ++} ++ ++static void r8156_mac_clk_spd(struct r8152 *tp, bool enable) ++{ ++ u32 ocp_data; ++ ++ /* MAC clock speed down */ ++ if (enable) { ++ /* aldps_spdwn_ratio, tp10_spdwn_ratio */ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, ++ 0x0403); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2); ++ ocp_data &= ~EEE_SPDWN_RATIO_MASK; ++ ocp_data |= MAC_CLK_SPDWN_EN | 0x03; /* eee_spdwn_ratio */ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data); ++ } else { ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2); ++ ocp_data &= ~MAC_CLK_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data); ++ } ++} ++ + static void r8153_u1u2en(struct r8152 *tp, bool enable) + { + u8 u1u2[8]; +@@ -3112,6 +3342,9 @@ static void r8153b_ups_flags(struct r815 + if (tp->ups_info.eee_cmod_lv) + ups_flags |= UPS_FLAGS_EEE_CMOD_LV_EN; + ++ if (tp->ups_info.r_tune) ++ ups_flags |= UPS_FLAGS_R_TUNE; ++ + if (tp->ups_info._10m_ckdiv) + ups_flags |= UPS_FLAGS_EN_10M_CKDIV; + +@@ -3162,6 +3395,88 @@ static void r8153b_ups_flags(struct r815 + ocp_write_dword(tp, MCU_TYPE_USB, USB_UPS_FLAGS, ups_flags); + } + ++static void r8156_ups_flags(struct r8152 *tp) ++{ ++ u32 ups_flags = 0; ++ ++ if (tp->ups_info.green) ++ ups_flags |= UPS_FLAGS_EN_GREEN; ++ ++ if (tp->ups_info.aldps) ++ ups_flags |= UPS_FLAGS_EN_ALDPS; ++ ++ if (tp->ups_info.eee) ++ ups_flags |= UPS_FLAGS_EN_EEE; ++ ++ if (tp->ups_info.flow_control) ++ ups_flags |= UPS_FLAGS_EN_FLOW_CTR; ++ ++ if (tp->ups_info.eee_ckdiv) ++ ups_flags |= UPS_FLAGS_EN_EEE_CKDIV; ++ ++ if (tp->ups_info._10m_ckdiv) ++ ups_flags |= UPS_FLAGS_EN_10M_CKDIV; ++ ++ if (tp->ups_info.eee_plloff_100) ++ ups_flags |= UPS_FLAGS_EEE_PLLOFF_100; ++ ++ if (tp->ups_info.eee_plloff_giga) ++ ups_flags |= UPS_FLAGS_EEE_PLLOFF_GIGA; ++ ++ if (tp->ups_info._250m_ckdiv) ++ ups_flags |= UPS_FLAGS_250M_CKDIV; ++ ++ switch (tp->ups_info.speed_duplex) { ++ case FORCE_10M_HALF: ++ ups_flags |= ups_flags_speed(0); ++ break; ++ case FORCE_10M_FULL: ++ ups_flags |= ups_flags_speed(1); ++ break; ++ case FORCE_100M_HALF: ++ ups_flags |= ups_flags_speed(2); ++ break; ++ case FORCE_100M_FULL: ++ ups_flags |= ups_flags_speed(3); ++ break; ++ case NWAY_10M_HALF: ++ ups_flags |= ups_flags_speed(4); ++ break; ++ case NWAY_10M_FULL: ++ ups_flags |= ups_flags_speed(5); ++ break; ++ case NWAY_100M_HALF: ++ ups_flags |= ups_flags_speed(6); ++ break; ++ case NWAY_100M_FULL: ++ ups_flags |= ups_flags_speed(7); ++ break; ++ case NWAY_1000M_FULL: ++ ups_flags |= ups_flags_speed(8); ++ break; ++ case NWAY_2500M_FULL: ++ ups_flags |= ups_flags_speed(9); ++ break; ++ default: ++ break; ++ } ++ ++ switch (tp->ups_info.lite_mode) { ++ case 1: ++ ups_flags |= 0 << 5; ++ break; ++ case 2: ++ ups_flags |= 2 << 5; ++ break; ++ case 0: ++ default: ++ ups_flags |= 1 << 5; ++ break; ++ } ++ ++ ocp_write_dword(tp, MCU_TYPE_USB, USB_UPS_FLAGS, ups_flags); ++} ++ + static void rtl_green_en(struct r8152 *tp, bool enable) + { + u16 data; +@@ -3225,16 +3540,16 @@ static void r8153b_ups_en(struct r8152 * + ocp_data |= UPS_EN | USP_PREWAKE | PHASE2_EN; + ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); + +- ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, 0xcfff); +- ocp_data |= BIT(0); +- ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data); ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); ++ ocp_data |= UPS_FORCE_PWR_DOWN; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); + } else { + ocp_data &= ~(UPS_EN | USP_PREWAKE); + ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); + +- ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, 0xcfff); +- ocp_data &= ~BIT(0); +- ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data); ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); ++ ocp_data &= ~UPS_FORCE_PWR_DOWN; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); + + if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) { + int i; +@@ -3254,6 +3569,95 @@ static void r8153b_ups_en(struct r8152 * + } + } + ++static void r8153c_ups_en(struct r8152 *tp, bool enable) ++{ ++ u32 ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_POWER_CUT); ++ ++ if (enable) { ++ r8153b_ups_flags(tp); ++ ++ ocp_data |= UPS_EN | USP_PREWAKE | PHASE2_EN; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); ++ ocp_data |= UPS_FORCE_PWR_DOWN; ++ ocp_data &= ~BIT(7); ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); ++ } else { ++ ocp_data &= ~(UPS_EN | USP_PREWAKE); ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); ++ ocp_data &= ~UPS_FORCE_PWR_DOWN; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); ++ ++ if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) { ++ int i; ++ ++ for (i = 0; i < 500; i++) { ++ if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & ++ AUTOLOAD_DONE) ++ break; ++ msleep(20); ++ } ++ ++ tp->rtl_ops.hw_phy_cfg(tp); ++ ++ rtl8152_set_speed(tp, tp->autoneg, tp->speed, ++ tp->duplex, tp->advertising); ++ } ++ ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34); ++ ocp_data |= BIT(8); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data); ++ ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML); ++ } ++} ++ ++static void r8156_ups_en(struct r8152 *tp, bool enable) ++{ ++ u32 ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_POWER_CUT); ++ ++ if (enable) { ++ r8156_ups_flags(tp); ++ ++ ocp_data |= UPS_EN | USP_PREWAKE | PHASE2_EN; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); ++ ocp_data |= UPS_FORCE_PWR_DOWN; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); ++ ++ switch (tp->version) { ++ case RTL_VER_13: ++ case RTL_VER_15: ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPHY_XTAL); ++ ocp_data &= ~OOBS_POLLING; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_UPHY_XTAL, ocp_data); ++ break; ++ default: ++ break; ++ } ++ } else { ++ ocp_data &= ~(UPS_EN | USP_PREWAKE); ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); ++ ocp_data &= ~UPS_FORCE_PWR_DOWN; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); ++ ++ if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) { ++ tp->rtl_ops.hw_phy_cfg(tp); ++ ++ rtl8152_set_speed(tp, tp->autoneg, tp->speed, ++ tp->duplex, tp->advertising); ++ } ++ } ++} ++ + static void r8153_power_cut_en(struct r8152 *tp, bool enable) + { + u32 ocp_data; +@@ -3383,6 +3787,38 @@ static void rtl8153b_runtime_enable(stru + } + } + ++static void rtl8153c_runtime_enable(struct r8152 *tp, bool enable) ++{ ++ if (enable) { ++ r8153_queue_wake(tp, true); ++ r8153b_u1u2en(tp, false); ++ r8153_u2p3en(tp, false); ++ rtl_runtime_suspend_enable(tp, true); ++ r8153c_ups_en(tp, true); ++ } else { ++ r8153c_ups_en(tp, false); ++ r8153_queue_wake(tp, false); ++ rtl_runtime_suspend_enable(tp, false); ++ r8153b_u1u2en(tp, true); ++ } ++} ++ ++static void rtl8156_runtime_enable(struct r8152 *tp, bool enable) ++{ ++ if (enable) { ++ r8153_queue_wake(tp, true); ++ r8153b_u1u2en(tp, false); ++ r8153_u2p3en(tp, false); ++ rtl_runtime_suspend_enable(tp, true); ++ } else { ++ r8153_queue_wake(tp, false); ++ rtl_runtime_suspend_enable(tp, false); ++ r8153_u2p3en(tp, true); ++ if (tp->udev->speed >= USB_SPEED_SUPER) ++ r8153b_u1u2en(tp, true); ++ } ++} ++ + static void r8153_teredo_off(struct r8152 *tp) + { + u32 ocp_data; +@@ -3403,14 +3839,19 @@ static void r8153_teredo_off(struct r815 + + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_TEST_01: ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_14: ++ case RTL_VER_15: ++ default: + /* The bit 0 ~ 7 are relative with teredo settings. They are + * W1C (write 1 to clear), so set all 1 to disable it. + */ + ocp_write_byte(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, 0xff); + break; +- +- default: +- break; + } + + ocp_write_word(tp, MCU_TYPE_PLA, PLA_WDT6_CTRL, WDT6_SET_MODE); +@@ -3445,6 +3886,12 @@ static void rtl_clear_bp(struct r8152 *t + break; + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_14: ++ case RTL_VER_15: + default: + if (type == MCU_TYPE_USB) { + ocp_write_word(tp, MCU_TYPE_USB, USB_BP2_EN, 0); +@@ -3654,6 +4101,11 @@ static bool rtl8152_is_fw_mac_ok(struct + case RTL_VER_06: + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_14: ++ case RTL_VER_15: + fw_reg = 0xf800; + bp_ba_addr = PLA_BP_BA; + bp_en_addr = PLA_BP_EN; +@@ -3677,6 +4129,11 @@ static bool rtl8152_is_fw_mac_ok(struct + break; + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_14: ++ case RTL_VER_15: + fw_reg = 0xe600; + bp_ba_addr = USB_BP_BA; + bp_en_addr = USB_BP2_EN; +@@ -4216,6 +4673,22 @@ static void r8153_eee_en(struct r8152 *t + tp->ups_info.eee = enable; + } + ++static void r8156_eee_en(struct r8152 *tp, bool enable) ++{ ++ u16 config; ++ ++ r8153_eee_en(tp, enable); ++ ++ config = ocp_reg_read(tp, OCP_EEE_ADV2); ++ ++ if (enable) ++ config |= MDIO_EEE_2_5GT; ++ else ++ config &= ~MDIO_EEE_2_5GT; ++ ++ ocp_reg_write(tp, OCP_EEE_ADV2, config); ++} ++ + static void rtl_eee_enable(struct r8152 *tp, bool enable) + { + switch (tp->version) { +@@ -4237,6 +4710,7 @@ static void rtl_eee_enable(struct r8152 + case RTL_VER_06: + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_VER_14: + if (enable) { + r8153_eee_en(tp, true); + ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv); +@@ -4245,6 +4719,19 @@ static void rtl_eee_enable(struct r8152 + ocp_reg_write(tp, OCP_EEE_ADV, 0); + } + break; ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: ++ if (enable) { ++ r8156_eee_en(tp, true); ++ ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv); ++ } else { ++ r8156_eee_en(tp, false); ++ ocp_reg_write(tp, OCP_EEE_ADV, 0); ++ } ++ break; + default: + break; + } +@@ -4291,6 +4778,20 @@ static void wait_oob_link_list_ready(str + } + } + ++static void r8156b_wait_loading_flash(struct r8152 *tp) ++{ ++ if ((ocp_read_word(tp, MCU_TYPE_PLA, PLA_GPHY_CTRL) & GPHY_FLASH) && ++ !(ocp_read_word(tp, MCU_TYPE_USB, USB_GPHY_CTRL) & BYPASS_FLASH)) { ++ int i; ++ ++ for (i = 0; i < 100; i++) { ++ if (ocp_read_word(tp, MCU_TYPE_USB, USB_GPHY_CTRL) & GPHY_PATCH_DONE) ++ break; ++ usleep_range(1000, 2000); ++ } ++ } ++} ++ + static void r8152b_exit_oob(struct r8152 *tp) + { + u32 ocp_data; +@@ -4341,7 +4842,7 @@ static void r8152b_exit_oob(struct r8152 + } + + /* TX share fifo free credit full threshold */ +- ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL); ++ ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL2); + + ocp_write_byte(tp, MCU_TYPE_USB, USB_TX_AGG, TX_AGG_MAX_THRESHOLD); + ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_HIGH); +@@ -4518,6 +5019,21 @@ static int r8153b_post_firmware_1(struct + return 0; + } + ++static int r8153c_post_firmware_1(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_CTRL); ++ ocp_data |= FLOW_CTRL_PATCH_2; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_CTRL, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK); ++ ocp_data |= FC_PATCH_TASK; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); ++ ++ return 0; ++} ++ + static void r8153_aldps_en(struct r8152 *tp, bool enable) + { + u16 data; +@@ -4720,6 +5236,13 @@ static void r8153b_hw_phy_cfg(struct r81 + set_bit(PHY_RESET, &tp->flags); + } + ++static void r8153c_hw_phy_cfg(struct r8152 *tp) ++{ ++ r8153b_hw_phy_cfg(tp); ++ ++ tp->ups_info.r_tune = true; ++} ++ + static void rtl8153_change_mtu(struct r8152 *tp) + { + ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, mtu_to_size(tp->netdev->mtu)); +@@ -4807,6 +5330,7 @@ static void r8153_enter_oob(struct r8152 + + case RTL_VER_08: + case RTL_VER_09: ++ case RTL_VER_14: + /* Clear teredo wake event. bit[15:8] is the teredo wakeup + * type. Set it to zero. bits[7:0] are the W1C bits about + * the events. Set them to all 1 to clear them. +@@ -4843,6 +5367,96 @@ static void rtl8153_disable(struct r8152 + r8153_aldps_en(tp, true); + } + ++static int rtl8156_enable(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ u16 speed; ++ ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return -ENODEV; ++ ++ set_tx_qlen(tp); ++ rtl_set_eee_plus(tp); ++ r8153_set_rx_early_timeout(tp); ++ r8153_set_rx_early_size(tp); ++ ++ speed = rtl8152_get_speed(tp); ++ rtl_set_ifg(tp, speed); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); ++ if (speed & _2500bps) ++ ocp_data &= ~IDLE_SPDWN_EN; ++ else ++ ocp_data |= IDLE_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); ++ ++ if (speed & _1000bps) ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x11); ++ else if (speed & _500bps) ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS, 0x3d); ++ ++ if (tp->udev->speed == USB_SPEED_HIGH) { ++ /* USB 0xb45e[3:0] l1_nyet_hird */ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_L1_CTRL); ++ ocp_data &= ~0xf; ++ if (is_flow_control(speed)) ++ ocp_data |= 0xf; ++ else ++ ocp_data |= 0x1; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_L1_CTRL, ocp_data); ++ } ++ ++ return rtl_enable(tp); ++} ++ ++static int rtl8156b_enable(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ u16 speed; ++ ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return -ENODEV; ++ ++ set_tx_qlen(tp); ++ rtl_set_eee_plus(tp); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_RX_AGGR_NUM); ++ ocp_data &= ~RX_AGGR_NUM_MASK; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_RX_AGGR_NUM, ocp_data); ++ ++ r8153_set_rx_early_timeout(tp); ++ r8153_set_rx_early_size(tp); ++ ++ speed = rtl8152_get_speed(tp); ++ rtl_set_ifg(tp, speed); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); ++ if (speed & _2500bps) ++ ocp_data &= ~IDLE_SPDWN_EN; ++ else ++ ocp_data |= IDLE_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); ++ ++ if (tp->udev->speed == USB_SPEED_HIGH) { ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_L1_CTRL); ++ ocp_data &= ~0xf; ++ if (is_flow_control(speed)) ++ ocp_data |= 0xf; ++ else ++ ocp_data |= 0x1; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_L1_CTRL, ocp_data); ++ } ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK); ++ ocp_data &= ~FC_PATCH_TASK; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); ++ usleep_range(1000, 2000); ++ ocp_data |= FC_PATCH_TASK; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); ++ ++ return rtl_enable(tp); ++} ++ + static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex, + u32 advertising) + { +@@ -4891,58 +5505,73 @@ static int rtl8152_set_speed(struct r815 + + tp->mii.force_media = 1; + } else { +- u16 anar, tmp1; ++ u16 orig, new1; + u32 support; + + support = RTL_ADVERTISED_10_HALF | RTL_ADVERTISED_10_FULL | + RTL_ADVERTISED_100_HALF | RTL_ADVERTISED_100_FULL; + +- if (tp->mii.supports_gmii) ++ if (tp->mii.supports_gmii) { + support |= RTL_ADVERTISED_1000_FULL; + ++ if (tp->support_2500full) ++ support |= RTL_ADVERTISED_2500_FULL; ++ } ++ + if (!(advertising & support)) + return -EINVAL; + +- anar = r8152_mdio_read(tp, MII_ADVERTISE); +- tmp1 = anar & ~(ADVERTISE_10HALF | ADVERTISE_10FULL | ++ orig = r8152_mdio_read(tp, MII_ADVERTISE); ++ new1 = orig & ~(ADVERTISE_10HALF | ADVERTISE_10FULL | + ADVERTISE_100HALF | ADVERTISE_100FULL); + if (advertising & RTL_ADVERTISED_10_HALF) { +- tmp1 |= ADVERTISE_10HALF; ++ new1 |= ADVERTISE_10HALF; + tp->ups_info.speed_duplex = NWAY_10M_HALF; + } + if (advertising & RTL_ADVERTISED_10_FULL) { +- tmp1 |= ADVERTISE_10FULL; ++ new1 |= ADVERTISE_10FULL; + tp->ups_info.speed_duplex = NWAY_10M_FULL; + } + + if (advertising & RTL_ADVERTISED_100_HALF) { +- tmp1 |= ADVERTISE_100HALF; ++ new1 |= ADVERTISE_100HALF; + tp->ups_info.speed_duplex = NWAY_100M_HALF; + } + if (advertising & RTL_ADVERTISED_100_FULL) { +- tmp1 |= ADVERTISE_100FULL; ++ new1 |= ADVERTISE_100FULL; + tp->ups_info.speed_duplex = NWAY_100M_FULL; + } + +- if (anar != tmp1) { +- r8152_mdio_write(tp, MII_ADVERTISE, tmp1); +- tp->mii.advertising = tmp1; ++ if (orig != new1) { ++ r8152_mdio_write(tp, MII_ADVERTISE, new1); ++ tp->mii.advertising = new1; + } + + if (tp->mii.supports_gmii) { +- u16 gbcr; +- +- gbcr = r8152_mdio_read(tp, MII_CTRL1000); +- tmp1 = gbcr & ~(ADVERTISE_1000FULL | ++ orig = r8152_mdio_read(tp, MII_CTRL1000); ++ new1 = orig & ~(ADVERTISE_1000FULL | + ADVERTISE_1000HALF); + + if (advertising & RTL_ADVERTISED_1000_FULL) { +- tmp1 |= ADVERTISE_1000FULL; ++ new1 |= ADVERTISE_1000FULL; + tp->ups_info.speed_duplex = NWAY_1000M_FULL; + } + +- if (gbcr != tmp1) +- r8152_mdio_write(tp, MII_CTRL1000, tmp1); ++ if (orig != new1) ++ r8152_mdio_write(tp, MII_CTRL1000, new1); ++ } ++ ++ if (tp->support_2500full) { ++ orig = ocp_reg_read(tp, OCP_10GBT_CTRL); ++ new1 = orig & ~MDIO_AN_10GBT_CTRL_ADV2_5G; ++ ++ if (advertising & RTL_ADVERTISED_2500_FULL) { ++ new1 |= MDIO_AN_10GBT_CTRL_ADV2_5G; ++ tp->ups_info.speed_duplex = NWAY_2500M_FULL; ++ } ++ ++ if (orig != new1) ++ ocp_reg_write(tp, OCP_10GBT_CTRL, new1); + } + + bmcr = BMCR_ANENABLE | BMCR_ANRESTART; +@@ -5098,6 +5727,253 @@ static void rtl8153b_down(struct r8152 * + r8153_aldps_en(tp, true); + } + ++static void rtl8153c_change_mtu(struct r8152 *tp) ++{ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, mtu_to_size(tp->netdev->mtu)); ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, 10 * 1024 / 64); ++ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, 512 / 64); ++ ++ /* Adjust the tx fifo free credit full threshold, otherwise ++ * the fifo would be too small to send a jumbo frame packet. ++ */ ++ if (tp->netdev->mtu < 8000) ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_FULL, 2048 / 8); ++ else ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_FULL, 900 / 8); ++} ++ ++static void rtl8153c_up(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return; ++ ++ r8153b_u1u2en(tp, false); ++ r8153_u2p3en(tp, false); ++ r8153_aldps_en(tp, false); ++ ++ rxdy_gated_en(tp, true); ++ r8153_teredo_off(tp); ++ ++ ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); ++ ocp_data &= ~RCR_ACPT_ALL; ++ ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); ++ ++ rtl8152_nic_reset(tp); ++ rtl_reset_bmu(tp); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); ++ ocp_data &= ~NOW_IS_OOB; ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7); ++ ocp_data &= ~MCU_BORW_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data); ++ ++ wait_oob_link_list_ready(tp); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7); ++ ocp_data |= RE_INIT_LL; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data); ++ ++ wait_oob_link_list_ready(tp); ++ ++ rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX); ++ ++ rtl8153c_change_mtu(tp); ++ ++ rtl8152_nic_reset(tp); ++ ++ /* rx share fifo credit full threshold */ ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, 0x02); ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_RXFIFO_FULL, 0x08); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_NORMAL); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_NORMAL); ++ ++ ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_B); ++ ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34); ++ ocp_data |= BIT(8); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data); ++ ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); ++ ocp_data &= ~PLA_MCU_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); ++ ++ r8153_aldps_en(tp, true); ++ r8153b_u1u2en(tp, true); ++} ++ ++static inline u32 fc_pause_on_auto(struct r8152 *tp) ++{ ++ return (ALIGN(mtu_to_size(tp->netdev->mtu), 1024) + 6 * 1024); ++} ++ ++static inline u32 fc_pause_off_auto(struct r8152 *tp) ++{ ++ return (ALIGN(mtu_to_size(tp->netdev->mtu), 1024) + 14 * 1024); ++} ++ ++static void r8156_fc_parameter(struct r8152 *tp) ++{ ++ u32 pause_on = tp->fc_pause_on ? tp->fc_pause_on : fc_pause_on_auto(tp); ++ u32 pause_off = tp->fc_pause_off ? tp->fc_pause_off : fc_pause_off_auto(tp); ++ ++ switch (tp->version) { ++ case RTL_VER_10: ++ case RTL_VER_11: ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, pause_on / 8); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, pause_off / 8); ++ break; ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, pause_on / 16); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, pause_off / 16); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void rtl8156_change_mtu(struct r8152 *tp) ++{ ++ u32 rx_max_size = mtu_to_size(tp->netdev->mtu); ++ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, rx_max_size); ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO); ++ r8156_fc_parameter(tp); ++ ++ /* TX share fifo free credit full threshold */ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, 512 / 64); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TXFIFO_FULL, ++ ALIGN(rx_max_size + sizeof(struct tx_desc), 1024) / 16); ++} ++ ++static void rtl8156_up(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return; ++ ++ r8153b_u1u2en(tp, false); ++ r8153_u2p3en(tp, false); ++ r8153_aldps_en(tp, false); ++ ++ rxdy_gated_en(tp, true); ++ r8153_teredo_off(tp); ++ ++ ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); ++ ocp_data &= ~RCR_ACPT_ALL; ++ ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); ++ ++ rtl8152_nic_reset(tp); ++ rtl_reset_bmu(tp); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); ++ ocp_data &= ~NOW_IS_OOB; ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7); ++ ocp_data &= ~MCU_BORW_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data); ++ ++ rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX); ++ ++ rtl8156_change_mtu(tp); ++ ++ switch (tp->version) { ++ case RTL_TEST_01: ++ case RTL_VER_10: ++ case RTL_VER_11: ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_BMU_CONFIG); ++ ocp_data |= ACT_ODMA; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_BMU_CONFIG, ocp_data); ++ break; ++ default: ++ break; ++ } ++ ++ /* share FIFO settings */ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_FULL); ++ ocp_data &= ~RXFIFO_FULL_MASK; ++ ocp_data |= 0x08; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_FULL, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); ++ ocp_data &= ~PLA_MCU_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION); ++ ocp_data &= ~(RG_PWRDN_EN | ALL_SPEED_OFF); ++ ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, ocp_data); ++ ++ ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, 0x00600400); ++ ++ if (tp->saved_wolopts != __rtl_get_wol(tp)) { ++ netif_warn(tp, ifup, tp->netdev, "wol setting is changed\n"); ++ __rtl_set_wol(tp, tp->saved_wolopts); ++ } ++ ++ r8153_aldps_en(tp, true); ++ r8153_u2p3en(tp, true); ++ ++ if (tp->udev->speed >= USB_SPEED_SUPER) ++ r8153b_u1u2en(tp, true); ++} ++ ++static void rtl8156_down(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) { ++ rtl_drop_queued_tx(tp); ++ return; ++ } ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); ++ ocp_data |= PLA_MCU_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); ++ ++ r8153b_u1u2en(tp, false); ++ r8153_u2p3en(tp, false); ++ r8153b_power_cut_en(tp, false); ++ r8153_aldps_en(tp, false); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); ++ ocp_data &= ~NOW_IS_OOB; ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); ++ ++ rtl_disable(tp); ++ rtl_reset_bmu(tp); ++ ++ /* Clear teredo wake event. bit[15:8] is the teredo wakeup ++ * type. Set it to zero. bits[7:0] are the W1C bits about ++ * the events. Set them to all 1 to clear them. ++ */ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_WAKE_BASE, 0x00ff); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); ++ ocp_data |= NOW_IS_OOB; ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); ++ ++ rtl_rx_vlan_en(tp, true); ++ rxdy_gated_en(tp, false); ++ ++ ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); ++ ocp_data |= RCR_APM | RCR_AM | RCR_AB; ++ ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); ++ ++ r8153_aldps_en(tp, true); ++} ++ + static bool rtl8152_in_nway(struct r8152 *tp) + { + u16 nway_state; +@@ -5128,7 +6004,7 @@ static void set_carrier(struct r8152 *tp + { + struct net_device *netdev = tp->netdev; + struct napi_struct *napi = &tp->napi; +- u8 speed; ++ u16 speed; + + speed = rtl8152_get_speed(tp); + +@@ -5141,7 +6017,7 @@ static void set_carrier(struct r8152 *tp + rtl_start_rx(tp); + clear_bit(RTL8152_SET_RX_MODE, &tp->flags); + _rtl8152_set_rx_mode(netdev); +- napi_enable(&tp->napi); ++ napi_enable(napi); + netif_wake_queue(netdev); + netif_info(tp, link, netdev, "carrier on\n"); + } else if (netif_queue_stopped(netdev) && +@@ -5521,14 +6397,9 @@ static void r8153_init(struct r8152 *tp) + + ocp_write_word(tp, MCU_TYPE_USB, USB_CONNECT_TIMER, 0x0001); + +- /* MAC clock speed down */ +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, 0); +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, 0); +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, 0); +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, 0); +- + r8153_power_cut_en(tp, false); + rtl_runtime_suspend_enable(tp, false); ++ r8153_mac_clk_speed_down(tp, false); + r8153_u1u2en(tp, true); + usb_enable_lpm(tp->udev); + +@@ -5621,9 +6492,7 @@ static void r8153b_init(struct r8152 *tp + usb_enable_lpm(tp->udev); + + /* MAC clock speed down */ +- ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2); +- ocp_data |= MAC_CLK_SPDWN_EN; +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data); ++ r8153_mac_clk_speed_down(tp, true); + + ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); + ocp_data &= ~PLA_MCU_SPDWN_EN; +@@ -5652,6 +6521,1069 @@ static void r8153b_init(struct r8152 *tp + r8152_led_configuration(tp); + } + ++static void r8153c_init(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ u16 data; ++ int i; ++ ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return; ++ ++ r8153b_u1u2en(tp, false); ++ ++ /* Disable spi_en */ ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG5); ++ ocp_data &= ~BIT(3); ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG5, ocp_data); ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, 0xcbf0); ++ ocp_data |= BIT(1); ++ ocp_write_word(tp, MCU_TYPE_USB, 0xcbf0, ocp_data); ++ ++ for (i = 0; i < 500; i++) { ++ if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & ++ AUTOLOAD_DONE) ++ break; ++ ++ msleep(20); ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return; ++ } ++ ++ data = r8153_phy_status(tp, 0); ++ ++ data = r8152_mdio_read(tp, MII_BMCR); ++ if (data & BMCR_PDOWN) { ++ data &= ~BMCR_PDOWN; ++ r8152_mdio_write(tp, MII_BMCR, data); ++ } ++ ++ data = r8153_phy_status(tp, PHY_STAT_LAN_ON); ++ ++ r8153_u2p3en(tp, false); ++ ++ /* MSC timer = 0xfff * 8ms = 32760 ms */ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff); ++ ++ r8153b_power_cut_en(tp, false); ++ r8153c_ups_en(tp, false); ++ r8153_queue_wake(tp, false); ++ rtl_runtime_suspend_enable(tp, false); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS); ++ if (rtl8152_get_speed(tp) & LINK_STATUS) ++ ocp_data |= CUR_LINK_OK; ++ else ++ ocp_data &= ~CUR_LINK_OK; ++ ++ ocp_data |= POLL_LINK_CHG; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data); ++ ++ r8153b_u1u2en(tp, true); ++ ++ usb_enable_lpm(tp->udev); ++ ++ /* MAC clock speed down */ ++ r8153_mac_clk_speed_down(tp, true); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_2); ++ ocp_data &= ~BIT(7); ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_MISC_2, ocp_data); ++ ++ set_bit(GREEN_ETHERNET, &tp->flags); ++ ++ /* rx aggregation */ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); ++ ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); ++ ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); ++ ++ rtl_tally_reset(tp); ++ ++ tp->coalesce = 15000; /* 15 us */ ++} ++ ++static void r8156_hw_phy_cfg(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ u16 data; ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); ++ if (ocp_data & PCUT_STATUS) { ++ ocp_data &= ~PCUT_STATUS; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); ++ } ++ ++ data = r8153_phy_status(tp, 0); ++ switch (data) { ++ case PHY_STAT_EXT_INIT: ++ rtl8152_apply_firmware(tp, true); ++ ++ data = ocp_reg_read(tp, 0xa468); ++ data &= ~(BIT(3) | BIT(1)); ++ ocp_reg_write(tp, 0xa468, data); ++ break; ++ case PHY_STAT_LAN_ON: ++ case PHY_STAT_PWRDN: ++ default: ++ rtl8152_apply_firmware(tp, false); ++ break; ++ } ++ ++ /* disable ALDPS before updating the PHY parameters */ ++ r8153_aldps_en(tp, false); ++ ++ /* disable EEE before updating the PHY parameters */ ++ rtl_eee_enable(tp, false); ++ ++ data = r8153_phy_status(tp, PHY_STAT_LAN_ON); ++ WARN_ON_ONCE(data != PHY_STAT_LAN_ON); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR); ++ ocp_data |= PFM_PWM_SWITCH; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); ++ ++ switch (tp->version) { ++ case RTL_VER_10: ++ data = ocp_reg_read(tp, 0xad40); ++ data &= ~0x3ff; ++ data |= BIT(7) | BIT(2); ++ ocp_reg_write(tp, 0xad40, data); ++ ++ data = ocp_reg_read(tp, 0xad4e); ++ data |= BIT(4); ++ ocp_reg_write(tp, 0xad4e, data); ++ data = ocp_reg_read(tp, 0xad16); ++ data &= ~0x3ff; ++ data |= 0x6; ++ ocp_reg_write(tp, 0xad16, data); ++ data = ocp_reg_read(tp, 0xad32); ++ data &= ~0x3f; ++ data |= 6; ++ ocp_reg_write(tp, 0xad32, data); ++ data = ocp_reg_read(tp, 0xac08); ++ data &= ~(BIT(12) | BIT(8)); ++ ocp_reg_write(tp, 0xac08, data); ++ data = ocp_reg_read(tp, 0xac8a); ++ data |= BIT(12) | BIT(13) | BIT(14); ++ data &= ~BIT(15); ++ ocp_reg_write(tp, 0xac8a, data); ++ data = ocp_reg_read(tp, 0xad18); ++ data |= BIT(10); ++ ocp_reg_write(tp, 0xad18, data); ++ data = ocp_reg_read(tp, 0xad1a); ++ data |= 0x3ff; ++ ocp_reg_write(tp, 0xad1a, data); ++ data = ocp_reg_read(tp, 0xad1c); ++ data |= 0x3ff; ++ ocp_reg_write(tp, 0xad1c, data); ++ ++ data = sram_read(tp, 0x80ea); ++ data &= ~0xff00; ++ data |= 0xc400; ++ sram_write(tp, 0x80ea, data); ++ data = sram_read(tp, 0x80eb); ++ data &= ~0x0700; ++ data |= 0x0300; ++ sram_write(tp, 0x80eb, data); ++ data = sram_read(tp, 0x80f8); ++ data &= ~0xff00; ++ data |= 0x1c00; ++ sram_write(tp, 0x80f8, data); ++ data = sram_read(tp, 0x80f1); ++ data &= ~0xff00; ++ data |= 0x3000; ++ sram_write(tp, 0x80f1, data); ++ ++ data = sram_read(tp, 0x80fe); ++ data &= ~0xff00; ++ data |= 0xa500; ++ sram_write(tp, 0x80fe, data); ++ data = sram_read(tp, 0x8102); ++ data &= ~0xff00; ++ data |= 0x5000; ++ sram_write(tp, 0x8102, data); ++ data = sram_read(tp, 0x8015); ++ data &= ~0xff00; ++ data |= 0x3300; ++ sram_write(tp, 0x8015, data); ++ data = sram_read(tp, 0x8100); ++ data &= ~0xff00; ++ data |= 0x7000; ++ sram_write(tp, 0x8100, data); ++ data = sram_read(tp, 0x8014); ++ data &= ~0xff00; ++ data |= 0xf000; ++ sram_write(tp, 0x8014, data); ++ data = sram_read(tp, 0x8016); ++ data &= ~0xff00; ++ data |= 0x6500; ++ sram_write(tp, 0x8016, data); ++ data = sram_read(tp, 0x80dc); ++ data &= ~0xff00; ++ data |= 0xed00; ++ sram_write(tp, 0x80dc, data); ++ data = sram_read(tp, 0x80df); ++ data |= BIT(8); ++ sram_write(tp, 0x80df, data); ++ data = sram_read(tp, 0x80e1); ++ data &= ~BIT(8); ++ sram_write(tp, 0x80e1, data); ++ ++ data = ocp_reg_read(tp, 0xbf06); ++ data &= ~0x003f; ++ data |= 0x0038; ++ ocp_reg_write(tp, 0xbf06, data); ++ ++ sram_write(tp, 0x819f, 0xddb6); ++ ++ ocp_reg_write(tp, 0xbc34, 0x5555); ++ data = ocp_reg_read(tp, 0xbf0a); ++ data &= ~0x0e00; ++ data |= 0x0a00; ++ ocp_reg_write(tp, 0xbf0a, data); ++ ++ data = ocp_reg_read(tp, 0xbd2c); ++ data &= ~BIT(13); ++ ocp_reg_write(tp, 0xbd2c, data); ++ break; ++ case RTL_VER_11: ++ data = ocp_reg_read(tp, 0xad16); ++ data |= 0x3ff; ++ ocp_reg_write(tp, 0xad16, data); ++ data = ocp_reg_read(tp, 0xad32); ++ data &= ~0x3f; ++ data |= 6; ++ ocp_reg_write(tp, 0xad32, data); ++ data = ocp_reg_read(tp, 0xac08); ++ data &= ~(BIT(12) | BIT(8)); ++ ocp_reg_write(tp, 0xac08, data); ++ data = ocp_reg_read(tp, 0xacc0); ++ data &= ~0x3; ++ data |= BIT(1); ++ ocp_reg_write(tp, 0xacc0, data); ++ data = ocp_reg_read(tp, 0xad40); ++ data &= ~0xe7; ++ data |= BIT(6) | BIT(2); ++ ocp_reg_write(tp, 0xad40, data); ++ data = ocp_reg_read(tp, 0xac14); ++ data &= ~BIT(7); ++ ocp_reg_write(tp, 0xac14, data); ++ data = ocp_reg_read(tp, 0xac80); ++ data &= ~(BIT(8) | BIT(9)); ++ ocp_reg_write(tp, 0xac80, data); ++ data = ocp_reg_read(tp, 0xac5e); ++ data &= ~0x7; ++ data |= BIT(1); ++ ocp_reg_write(tp, 0xac5e, data); ++ ocp_reg_write(tp, 0xad4c, 0x00a8); ++ ocp_reg_write(tp, 0xac5c, 0x01ff); ++ data = ocp_reg_read(tp, 0xac8a); ++ data &= ~0xf0; ++ data |= BIT(4) | BIT(5); ++ ocp_reg_write(tp, 0xac8a, data); ++ ocp_reg_write(tp, 0xb87c, 0x8157); ++ data = ocp_reg_read(tp, 0xb87e); ++ data &= ~0xff00; ++ data |= 0x0500; ++ ocp_reg_write(tp, 0xb87e, data); ++ ocp_reg_write(tp, 0xb87c, 0x8159); ++ data = ocp_reg_read(tp, 0xb87e); ++ data &= ~0xff00; ++ data |= 0x0700; ++ ocp_reg_write(tp, 0xb87e, data); ++ ++ /* AAGC */ ++ ocp_reg_write(tp, 0xb87c, 0x80a2); ++ ocp_reg_write(tp, 0xb87e, 0x0153); ++ ocp_reg_write(tp, 0xb87c, 0x809c); ++ ocp_reg_write(tp, 0xb87e, 0x0153); ++ ++ /* EEE parameter */ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_TXTWSYS_2P5G, 0x0056); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_USB_CFG); ++ ocp_data |= EN_XG_LIP | EN_G_LIP; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_USB_CFG, ocp_data); ++ ++ sram_write(tp, 0x8257, 0x020f); /* XG PLL */ ++ sram_write(tp, 0x80ea, 0x7843); /* GIGA Master */ ++ ++ if (rtl_phy_patch_request(tp, true, true)) ++ return; ++ ++ /* Advance EEE */ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); ++ ocp_data |= EEE_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); ++ ++ data = ocp_reg_read(tp, OCP_DOWN_SPEED); ++ data &= ~(EN_EEE_100 | EN_EEE_1000); ++ data |= EN_10M_CLKDIV; ++ ocp_reg_write(tp, OCP_DOWN_SPEED, data); ++ tp->ups_info._10m_ckdiv = true; ++ tp->ups_info.eee_plloff_100 = false; ++ tp->ups_info.eee_plloff_giga = false; ++ ++ data = ocp_reg_read(tp, OCP_POWER_CFG); ++ data &= ~EEE_CLKDIV_EN; ++ ocp_reg_write(tp, OCP_POWER_CFG, data); ++ tp->ups_info.eee_ckdiv = false; ++ ++ ocp_reg_write(tp, OCP_SYSCLK_CFG, 0); ++ ocp_reg_write(tp, OCP_SYSCLK_CFG, sysclk_div_expo(5)); ++ tp->ups_info._250m_ckdiv = false; ++ ++ rtl_phy_patch_request(tp, false, true); ++ ++ /* enable ADC Ibias Cal */ ++ data = ocp_reg_read(tp, 0xd068); ++ data |= BIT(13); ++ ocp_reg_write(tp, 0xd068, data); ++ ++ /* enable Thermal Sensor */ ++ data = sram_read(tp, 0x81a2); ++ data &= ~BIT(8); ++ sram_write(tp, 0x81a2, data); ++ data = ocp_reg_read(tp, 0xb54c); ++ data &= ~0xff00; ++ data |= 0xdb00; ++ ocp_reg_write(tp, 0xb54c, data); ++ ++ /* Nway 2.5G Lite */ ++ data = ocp_reg_read(tp, 0xa454); ++ data &= ~BIT(0); ++ ocp_reg_write(tp, 0xa454, data); ++ ++ /* CS DSP solution */ ++ data = ocp_reg_read(tp, OCP_10GBT_CTRL); ++ data |= RTL_ADV2_5G_F_R; ++ ocp_reg_write(tp, OCP_10GBT_CTRL, data); ++ data = ocp_reg_read(tp, 0xad4e); ++ data &= ~BIT(4); ++ ocp_reg_write(tp, 0xad4e, data); ++ data = ocp_reg_read(tp, 0xa86a); ++ data &= ~BIT(0); ++ ocp_reg_write(tp, 0xa86a, data); ++ ++ /* MDI SWAP */ ++ if ((ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CFG) & MID_REVERSE) && ++ (ocp_reg_read(tp, 0xd068) & BIT(1))) { ++ u16 swap_a, swap_b; ++ ++ data = ocp_reg_read(tp, 0xd068); ++ data &= ~0x1f; ++ data |= 0x1; /* p0 */ ++ ocp_reg_write(tp, 0xd068, data); ++ swap_a = ocp_reg_read(tp, 0xd06a); ++ data &= ~0x18; ++ data |= 0x18; /* p3 */ ++ ocp_reg_write(tp, 0xd068, data); ++ swap_b = ocp_reg_read(tp, 0xd06a); ++ data &= ~0x18; /* p0 */ ++ ocp_reg_write(tp, 0xd068, data); ++ ocp_reg_write(tp, 0xd06a, ++ (swap_a & ~0x7ff) | (swap_b & 0x7ff)); ++ data |= 0x18; /* p3 */ ++ ocp_reg_write(tp, 0xd068, data); ++ ocp_reg_write(tp, 0xd06a, ++ (swap_b & ~0x7ff) | (swap_a & 0x7ff)); ++ data &= ~0x18; ++ data |= 0x08; /* p1 */ ++ ocp_reg_write(tp, 0xd068, data); ++ swap_a = ocp_reg_read(tp, 0xd06a); ++ data &= ~0x18; ++ data |= 0x10; /* p2 */ ++ ocp_reg_write(tp, 0xd068, data); ++ swap_b = ocp_reg_read(tp, 0xd06a); ++ data &= ~0x18; ++ data |= 0x08; /* p1 */ ++ ocp_reg_write(tp, 0xd068, data); ++ ocp_reg_write(tp, 0xd06a, ++ (swap_a & ~0x7ff) | (swap_b & 0x7ff)); ++ data &= ~0x18; ++ data |= 0x10; /* p2 */ ++ ocp_reg_write(tp, 0xd068, data); ++ ocp_reg_write(tp, 0xd06a, ++ (swap_b & ~0x7ff) | (swap_a & 0x7ff)); ++ swap_a = ocp_reg_read(tp, 0xbd5a); ++ swap_b = ocp_reg_read(tp, 0xbd5c); ++ ocp_reg_write(tp, 0xbd5a, (swap_a & ~0x1f1f) | ++ ((swap_b & 0x1f) << 8) | ++ ((swap_b >> 8) & 0x1f)); ++ ocp_reg_write(tp, 0xbd5c, (swap_b & ~0x1f1f) | ++ ((swap_a & 0x1f) << 8) | ++ ((swap_a >> 8) & 0x1f)); ++ swap_a = ocp_reg_read(tp, 0xbc18); ++ swap_b = ocp_reg_read(tp, 0xbc1a); ++ ocp_reg_write(tp, 0xbc18, (swap_a & ~0x1f1f) | ++ ((swap_b & 0x1f) << 8) | ++ ((swap_b >> 8) & 0x1f)); ++ ocp_reg_write(tp, 0xbc1a, (swap_b & ~0x1f1f) | ++ ((swap_a & 0x1f) << 8) | ++ ((swap_a >> 8) & 0x1f)); ++ } ++ break; ++ default: ++ break; ++ } ++ ++ rtl_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags)); ++ ++ data = ocp_reg_read(tp, 0xa428); ++ data &= ~BIT(9); ++ ocp_reg_write(tp, 0xa428, data); ++ data = ocp_reg_read(tp, 0xa5ea); ++ data &= ~BIT(0); ++ ocp_reg_write(tp, 0xa5ea, data); ++ tp->ups_info.lite_mode = 0; ++ ++ if (tp->eee_en) ++ rtl_eee_enable(tp, true); ++ ++ r8153_aldps_en(tp, true); ++ r8152b_enable_fc(tp); ++ r8153_u2p3en(tp, true); ++ ++ set_bit(PHY_RESET, &tp->flags); ++} ++ ++static void r8156b_hw_phy_cfg(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ u16 data; ++ ++ switch (tp->version) { ++ case RTL_VER_12: ++ ocp_reg_write(tp, 0xbf86, 0x9000); ++ data = ocp_reg_read(tp, 0xc402); ++ data |= BIT(10); ++ ocp_reg_write(tp, 0xc402, data); ++ data &= ~BIT(10); ++ ocp_reg_write(tp, 0xc402, data); ++ ocp_reg_write(tp, 0xbd86, 0x1010); ++ ocp_reg_write(tp, 0xbd88, 0x1010); ++ data = ocp_reg_read(tp, 0xbd4e); ++ data &= ~(BIT(10) | BIT(11)); ++ data |= BIT(11); ++ ocp_reg_write(tp, 0xbd4e, data); ++ data = ocp_reg_read(tp, 0xbf46); ++ data &= ~0xf00; ++ data |= 0x700; ++ ocp_reg_write(tp, 0xbf46, data); ++ break; ++ case RTL_VER_13: ++ case RTL_VER_15: ++ r8156b_wait_loading_flash(tp); ++ break; ++ default: ++ break; ++ } ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); ++ if (ocp_data & PCUT_STATUS) { ++ ocp_data &= ~PCUT_STATUS; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); ++ } ++ ++ data = r8153_phy_status(tp, 0); ++ switch (data) { ++ case PHY_STAT_EXT_INIT: ++ rtl8152_apply_firmware(tp, true); ++ ++ data = ocp_reg_read(tp, 0xa466); ++ data &= ~BIT(0); ++ ocp_reg_write(tp, 0xa466, data); ++ ++ data = ocp_reg_read(tp, 0xa468); ++ data &= ~(BIT(3) | BIT(1)); ++ ocp_reg_write(tp, 0xa468, data); ++ break; ++ case PHY_STAT_LAN_ON: ++ case PHY_STAT_PWRDN: ++ default: ++ rtl8152_apply_firmware(tp, false); ++ break; ++ } ++ ++ data = r8152_mdio_read(tp, MII_BMCR); ++ if (data & BMCR_PDOWN) { ++ data &= ~BMCR_PDOWN; ++ r8152_mdio_write(tp, MII_BMCR, data); ++ } ++ ++ /* disable ALDPS before updating the PHY parameters */ ++ r8153_aldps_en(tp, false); ++ ++ /* disable EEE before updating the PHY parameters */ ++ rtl_eee_enable(tp, false); ++ ++ data = r8153_phy_status(tp, PHY_STAT_LAN_ON); ++ WARN_ON_ONCE(data != PHY_STAT_LAN_ON); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR); ++ ocp_data |= PFM_PWM_SWITCH; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); ++ ++ switch (tp->version) { ++ case RTL_VER_12: ++ data = ocp_reg_read(tp, 0xbc08); ++ data |= BIT(3) | BIT(2); ++ ocp_reg_write(tp, 0xbc08, data); ++ ++ data = sram_read(tp, 0x8fff); ++ data &= ~0xff00; ++ data |= 0x0400; ++ sram_write(tp, 0x8fff, data); ++ ++ data = ocp_reg_read(tp, 0xacda); ++ data |= 0xff00; ++ ocp_reg_write(tp, 0xacda, data); ++ data = ocp_reg_read(tp, 0xacde); ++ data |= 0xf000; ++ ocp_reg_write(tp, 0xacde, data); ++ ocp_reg_write(tp, 0xac8c, 0x0ffc); ++ ocp_reg_write(tp, 0xac46, 0xb7b4); ++ ocp_reg_write(tp, 0xac50, 0x0fbc); ++ ocp_reg_write(tp, 0xac3c, 0x9240); ++ ocp_reg_write(tp, 0xac4e, 0x0db4); ++ ocp_reg_write(tp, 0xacc6, 0x0707); ++ ocp_reg_write(tp, 0xacc8, 0xa0d3); ++ ocp_reg_write(tp, 0xad08, 0x0007); ++ ++ ocp_reg_write(tp, 0xb87c, 0x8560); ++ ocp_reg_write(tp, 0xb87e, 0x19cc); ++ ocp_reg_write(tp, 0xb87c, 0x8562); ++ ocp_reg_write(tp, 0xb87e, 0x19cc); ++ ocp_reg_write(tp, 0xb87c, 0x8564); ++ ocp_reg_write(tp, 0xb87e, 0x19cc); ++ ocp_reg_write(tp, 0xb87c, 0x8566); ++ ocp_reg_write(tp, 0xb87e, 0x147d); ++ ocp_reg_write(tp, 0xb87c, 0x8568); ++ ocp_reg_write(tp, 0xb87e, 0x147d); ++ ocp_reg_write(tp, 0xb87c, 0x856a); ++ ocp_reg_write(tp, 0xb87e, 0x147d); ++ ocp_reg_write(tp, 0xb87c, 0x8ffe); ++ ocp_reg_write(tp, 0xb87e, 0x0907); ++ ocp_reg_write(tp, 0xb87c, 0x80d6); ++ ocp_reg_write(tp, 0xb87e, 0x2801); ++ ocp_reg_write(tp, 0xb87c, 0x80f2); ++ ocp_reg_write(tp, 0xb87e, 0x2801); ++ ocp_reg_write(tp, 0xb87c, 0x80f4); ++ ocp_reg_write(tp, 0xb87e, 0x6077); ++ ocp_reg_write(tp, 0xb506, 0x01e7); ++ ++ ocp_reg_write(tp, 0xb87c, 0x8013); ++ ocp_reg_write(tp, 0xb87e, 0x0700); ++ ocp_reg_write(tp, 0xb87c, 0x8fb9); ++ ocp_reg_write(tp, 0xb87e, 0x2801); ++ ocp_reg_write(tp, 0xb87c, 0x8fba); ++ ocp_reg_write(tp, 0xb87e, 0x0100); ++ ocp_reg_write(tp, 0xb87c, 0x8fbc); ++ ocp_reg_write(tp, 0xb87e, 0x1900); ++ ocp_reg_write(tp, 0xb87c, 0x8fbe); ++ ocp_reg_write(tp, 0xb87e, 0xe100); ++ ocp_reg_write(tp, 0xb87c, 0x8fc0); ++ ocp_reg_write(tp, 0xb87e, 0x0800); ++ ocp_reg_write(tp, 0xb87c, 0x8fc2); ++ ocp_reg_write(tp, 0xb87e, 0xe500); ++ ocp_reg_write(tp, 0xb87c, 0x8fc4); ++ ocp_reg_write(tp, 0xb87e, 0x0f00); ++ ocp_reg_write(tp, 0xb87c, 0x8fc6); ++ ocp_reg_write(tp, 0xb87e, 0xf100); ++ ocp_reg_write(tp, 0xb87c, 0x8fc8); ++ ocp_reg_write(tp, 0xb87e, 0x0400); ++ ocp_reg_write(tp, 0xb87c, 0x8fca); ++ ocp_reg_write(tp, 0xb87e, 0xf300); ++ ocp_reg_write(tp, 0xb87c, 0x8fcc); ++ ocp_reg_write(tp, 0xb87e, 0xfd00); ++ ocp_reg_write(tp, 0xb87c, 0x8fce); ++ ocp_reg_write(tp, 0xb87e, 0xff00); ++ ocp_reg_write(tp, 0xb87c, 0x8fd0); ++ ocp_reg_write(tp, 0xb87e, 0xfb00); ++ ocp_reg_write(tp, 0xb87c, 0x8fd2); ++ ocp_reg_write(tp, 0xb87e, 0x0100); ++ ocp_reg_write(tp, 0xb87c, 0x8fd4); ++ ocp_reg_write(tp, 0xb87e, 0xf400); ++ ocp_reg_write(tp, 0xb87c, 0x8fd6); ++ ocp_reg_write(tp, 0xb87e, 0xff00); ++ ocp_reg_write(tp, 0xb87c, 0x8fd8); ++ ocp_reg_write(tp, 0xb87e, 0xf600); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_USB_CFG); ++ ocp_data |= EN_XG_LIP | EN_G_LIP; ++ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_USB_CFG, ocp_data); ++ ocp_reg_write(tp, 0xb87c, 0x813d); ++ ocp_reg_write(tp, 0xb87e, 0x390e); ++ ocp_reg_write(tp, 0xb87c, 0x814f); ++ ocp_reg_write(tp, 0xb87e, 0x790e); ++ ocp_reg_write(tp, 0xb87c, 0x80b0); ++ ocp_reg_write(tp, 0xb87e, 0x0f31); ++ data = ocp_reg_read(tp, 0xbf4c); ++ data |= BIT(1); ++ ocp_reg_write(tp, 0xbf4c, data); ++ data = ocp_reg_read(tp, 0xbcca); ++ data |= BIT(9) | BIT(8); ++ ocp_reg_write(tp, 0xbcca, data); ++ ocp_reg_write(tp, 0xb87c, 0x8141); ++ ocp_reg_write(tp, 0xb87e, 0x320e); ++ ocp_reg_write(tp, 0xb87c, 0x8153); ++ ocp_reg_write(tp, 0xb87e, 0x720e); ++ ocp_reg_write(tp, 0xb87c, 0x8529); ++ ocp_reg_write(tp, 0xb87e, 0x050e); ++ data = ocp_reg_read(tp, OCP_EEE_CFG); ++ data &= ~CTAP_SHORT_EN; ++ ocp_reg_write(tp, OCP_EEE_CFG, data); ++ ++ sram_write(tp, 0x816c, 0xc4a0); ++ sram_write(tp, 0x8170, 0xc4a0); ++ sram_write(tp, 0x8174, 0x04a0); ++ sram_write(tp, 0x8178, 0x04a0); ++ sram_write(tp, 0x817c, 0x0719); ++ sram_write(tp, 0x8ff4, 0x0400); ++ sram_write(tp, 0x8ff1, 0x0404); ++ ++ ocp_reg_write(tp, 0xbf4a, 0x001b); ++ ocp_reg_write(tp, 0xb87c, 0x8033); ++ ocp_reg_write(tp, 0xb87e, 0x7c13); ++ ocp_reg_write(tp, 0xb87c, 0x8037); ++ ocp_reg_write(tp, 0xb87e, 0x7c13); ++ ocp_reg_write(tp, 0xb87c, 0x803b); ++ ocp_reg_write(tp, 0xb87e, 0xfc32); ++ ocp_reg_write(tp, 0xb87c, 0x803f); ++ ocp_reg_write(tp, 0xb87e, 0x7c13); ++ ocp_reg_write(tp, 0xb87c, 0x8043); ++ ocp_reg_write(tp, 0xb87e, 0x7c13); ++ ocp_reg_write(tp, 0xb87c, 0x8047); ++ ocp_reg_write(tp, 0xb87e, 0x7c13); ++ ++ ocp_reg_write(tp, 0xb87c, 0x8145); ++ ocp_reg_write(tp, 0xb87e, 0x370e); ++ ocp_reg_write(tp, 0xb87c, 0x8157); ++ ocp_reg_write(tp, 0xb87e, 0x770e); ++ ocp_reg_write(tp, 0xb87c, 0x8169); ++ ocp_reg_write(tp, 0xb87e, 0x0d0a); ++ ocp_reg_write(tp, 0xb87c, 0x817b); ++ ocp_reg_write(tp, 0xb87e, 0x1d0a); ++ ++ data = sram_read(tp, 0x8217); ++ data &= ~0xff00; ++ data |= 0x5000; ++ sram_write(tp, 0x8217, data); ++ data = sram_read(tp, 0x821a); ++ data &= ~0xff00; ++ data |= 0x5000; ++ sram_write(tp, 0x821a, data); ++ sram_write(tp, 0x80da, 0x0403); ++ data = sram_read(tp, 0x80dc); ++ data &= ~0xff00; ++ data |= 0x1000; ++ sram_write(tp, 0x80dc, data); ++ sram_write(tp, 0x80b3, 0x0384); ++ sram_write(tp, 0x80b7, 0x2007); ++ data = sram_read(tp, 0x80ba); ++ data &= ~0xff00; ++ data |= 0x6c00; ++ sram_write(tp, 0x80ba, data); ++ sram_write(tp, 0x80b5, 0xf009); ++ data = sram_read(tp, 0x80bd); ++ data &= ~0xff00; ++ data |= 0x9f00; ++ sram_write(tp, 0x80bd, data); ++ sram_write(tp, 0x80c7, 0xf083); ++ sram_write(tp, 0x80dd, 0x03f0); ++ data = sram_read(tp, 0x80df); ++ data &= ~0xff00; ++ data |= 0x1000; ++ sram_write(tp, 0x80df, data); ++ sram_write(tp, 0x80cb, 0x2007); ++ data = sram_read(tp, 0x80ce); ++ data &= ~0xff00; ++ data |= 0x6c00; ++ sram_write(tp, 0x80ce, data); ++ sram_write(tp, 0x80c9, 0x8009); ++ data = sram_read(tp, 0x80d1); ++ data &= ~0xff00; ++ data |= 0x8000; ++ sram_write(tp, 0x80d1, data); ++ sram_write(tp, 0x80a3, 0x200a); ++ sram_write(tp, 0x80a5, 0xf0ad); ++ sram_write(tp, 0x809f, 0x6073); ++ sram_write(tp, 0x80a1, 0x000b); ++ data = sram_read(tp, 0x80a9); ++ data &= ~0xff00; ++ data |= 0xc000; ++ sram_write(tp, 0x80a9, data); ++ ++ if (rtl_phy_patch_request(tp, true, true)) ++ return; ++ ++ data = ocp_reg_read(tp, 0xb896); ++ data &= ~BIT(0); ++ ocp_reg_write(tp, 0xb896, data); ++ data = ocp_reg_read(tp, 0xb892); ++ data &= ~0xff00; ++ ocp_reg_write(tp, 0xb892, data); ++ ocp_reg_write(tp, 0xb88e, 0xc23e); ++ ocp_reg_write(tp, 0xb890, 0x0000); ++ ocp_reg_write(tp, 0xb88e, 0xc240); ++ ocp_reg_write(tp, 0xb890, 0x0103); ++ ocp_reg_write(tp, 0xb88e, 0xc242); ++ ocp_reg_write(tp, 0xb890, 0x0507); ++ ocp_reg_write(tp, 0xb88e, 0xc244); ++ ocp_reg_write(tp, 0xb890, 0x090b); ++ ocp_reg_write(tp, 0xb88e, 0xc246); ++ ocp_reg_write(tp, 0xb890, 0x0c0e); ++ ocp_reg_write(tp, 0xb88e, 0xc248); ++ ocp_reg_write(tp, 0xb890, 0x1012); ++ ocp_reg_write(tp, 0xb88e, 0xc24a); ++ ocp_reg_write(tp, 0xb890, 0x1416); ++ data = ocp_reg_read(tp, 0xb896); ++ data |= BIT(0); ++ ocp_reg_write(tp, 0xb896, data); ++ ++ rtl_phy_patch_request(tp, false, true); ++ ++ data = ocp_reg_read(tp, 0xa86a); ++ data |= BIT(0); ++ ocp_reg_write(tp, 0xa86a, data); ++ data = ocp_reg_read(tp, 0xa6f0); ++ data |= BIT(0); ++ ocp_reg_write(tp, 0xa6f0, data); ++ ++ ocp_reg_write(tp, 0xbfa0, 0xd70d); ++ ocp_reg_write(tp, 0xbfa2, 0x4100); ++ ocp_reg_write(tp, 0xbfa4, 0xe868); ++ ocp_reg_write(tp, 0xbfa6, 0xdc59); ++ ocp_reg_write(tp, 0xb54c, 0x3c18); ++ data = ocp_reg_read(tp, 0xbfa4); ++ data &= ~BIT(5); ++ ocp_reg_write(tp, 0xbfa4, data); ++ data = sram_read(tp, 0x817d); ++ data |= BIT(12); ++ sram_write(tp, 0x817d, data); ++ break; ++ case RTL_VER_13: ++ /* 2.5G INRX */ ++ data = ocp_reg_read(tp, 0xac46); ++ data &= ~0x00f0; ++ data |= 0x0090; ++ ocp_reg_write(tp, 0xac46, data); ++ data = ocp_reg_read(tp, 0xad30); ++ data &= ~0x0003; ++ data |= 0x0001; ++ ocp_reg_write(tp, 0xad30, data); ++ fallthrough; ++ case RTL_VER_15: ++ /* EEE parameter */ ++ ocp_reg_write(tp, 0xb87c, 0x80f5); ++ ocp_reg_write(tp, 0xb87e, 0x760e); ++ ocp_reg_write(tp, 0xb87c, 0x8107); ++ ocp_reg_write(tp, 0xb87e, 0x360e); ++ ocp_reg_write(tp, 0xb87c, 0x8551); ++ data = ocp_reg_read(tp, 0xb87e); ++ data &= ~0xff00; ++ data |= 0x0800; ++ ocp_reg_write(tp, 0xb87e, data); ++ ++ /* ADC_PGA parameter */ ++ data = ocp_reg_read(tp, 0xbf00); ++ data &= ~0xe000; ++ data |= 0xa000; ++ ocp_reg_write(tp, 0xbf00, data); ++ data = ocp_reg_read(tp, 0xbf46); ++ data &= ~0x0f00; ++ data |= 0x0300; ++ ocp_reg_write(tp, 0xbf46, data); ++ ++ /* Green Table-PGA, 1G full viterbi */ ++ sram_write(tp, 0x8044, 0x2417); ++ sram_write(tp, 0x804a, 0x2417); ++ sram_write(tp, 0x8050, 0x2417); ++ sram_write(tp, 0x8056, 0x2417); ++ sram_write(tp, 0x805c, 0x2417); ++ sram_write(tp, 0x8062, 0x2417); ++ sram_write(tp, 0x8068, 0x2417); ++ sram_write(tp, 0x806e, 0x2417); ++ sram_write(tp, 0x8074, 0x2417); ++ sram_write(tp, 0x807a, 0x2417); ++ ++ /* XG PLL */ ++ data = ocp_reg_read(tp, 0xbf84); ++ data &= ~0xe000; ++ data |= 0xa000; ++ ocp_reg_write(tp, 0xbf84, data); ++ break; ++ default: ++ break; ++ } ++ ++ if (rtl_phy_patch_request(tp, true, true)) ++ return; ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4); ++ ocp_data |= EEE_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, ocp_data); ++ ++ data = ocp_reg_read(tp, OCP_DOWN_SPEED); ++ data &= ~(EN_EEE_100 | EN_EEE_1000); ++ data |= EN_10M_CLKDIV; ++ ocp_reg_write(tp, OCP_DOWN_SPEED, data); ++ tp->ups_info._10m_ckdiv = true; ++ tp->ups_info.eee_plloff_100 = false; ++ tp->ups_info.eee_plloff_giga = false; ++ ++ data = ocp_reg_read(tp, OCP_POWER_CFG); ++ data &= ~EEE_CLKDIV_EN; ++ ocp_reg_write(tp, OCP_POWER_CFG, data); ++ tp->ups_info.eee_ckdiv = false; ++ ++ rtl_phy_patch_request(tp, false, true); ++ ++ rtl_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags)); ++ ++ data = ocp_reg_read(tp, 0xa428); ++ data &= ~BIT(9); ++ ocp_reg_write(tp, 0xa428, data); ++ data = ocp_reg_read(tp, 0xa5ea); ++ data &= ~BIT(0); ++ ocp_reg_write(tp, 0xa5ea, data); ++ tp->ups_info.lite_mode = 0; ++ ++ if (tp->eee_en) ++ rtl_eee_enable(tp, true); ++ ++ r8153_aldps_en(tp, true); ++ r8152b_enable_fc(tp); ++ r8153_u2p3en(tp, true); ++ ++ set_bit(PHY_RESET, &tp->flags); ++} ++ ++static void r8156_init(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ u16 data; ++ int i; ++ ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return; ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_ECM_OP); ++ ocp_data &= ~EN_ALL_SPEED; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_ECM_OP, ocp_data); ++ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_ECM_OPTION); ++ ocp_data |= BYPASS_MAC_RESET; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_ECM_OPTION, ocp_data); ++ ++ r8153b_u1u2en(tp, false); ++ ++ for (i = 0; i < 500; i++) { ++ if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & ++ AUTOLOAD_DONE) ++ break; ++ ++ msleep(20); ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return; ++ } ++ ++ data = r8153_phy_status(tp, 0); ++ if (data == PHY_STAT_EXT_INIT) { ++ data = ocp_reg_read(tp, 0xa468); ++ data &= ~(BIT(3) | BIT(1)); ++ ocp_reg_write(tp, 0xa468, data); ++ } ++ ++ data = r8152_mdio_read(tp, MII_BMCR); ++ if (data & BMCR_PDOWN) { ++ data &= ~BMCR_PDOWN; ++ r8152_mdio_write(tp, MII_BMCR, data); ++ } ++ ++ data = r8153_phy_status(tp, PHY_STAT_LAN_ON); ++ WARN_ON_ONCE(data != PHY_STAT_LAN_ON); ++ ++ r8153_u2p3en(tp, false); ++ ++ /* MSC timer = 0xfff * 8ms = 32760 ms */ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff); ++ ++ /* U1/U2/L1 idle timer. 500 us */ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500); ++ ++ r8153b_power_cut_en(tp, false); ++ r8156_ups_en(tp, false); ++ r8153_queue_wake(tp, false); ++ rtl_runtime_suspend_enable(tp, false); ++ ++ if (tp->udev->speed >= USB_SPEED_SUPER) ++ r8153b_u1u2en(tp, true); ++ ++ usb_enable_lpm(tp->udev); ++ ++ r8156_mac_clk_spd(tp, true); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); ++ ocp_data &= ~PLA_MCU_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS); ++ if (rtl8152_get_speed(tp) & LINK_STATUS) ++ ocp_data |= CUR_LINK_OK; ++ else ++ ocp_data &= ~CUR_LINK_OK; ++ ocp_data |= POLL_LINK_CHG; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data); ++ ++ set_bit(GREEN_ETHERNET, &tp->flags); ++ ++ /* rx aggregation */ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); ++ ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); ++ ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_BMU_CONFIG); ++ ocp_data |= ACT_ODMA; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_BMU_CONFIG, ocp_data); ++ ++ rtl_tally_reset(tp); ++ ++ tp->coalesce = 15000; /* 15 us */ ++} ++ ++static void r8156b_init(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ u16 data; ++ int i; ++ ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return; ++ ++ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_ECM_OP); ++ ocp_data &= ~EN_ALL_SPEED; ++ ocp_write_byte(tp, MCU_TYPE_USB, USB_ECM_OP, ocp_data); ++ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_SPEED_OPTION, 0); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_ECM_OPTION); ++ ocp_data |= BYPASS_MAC_RESET; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_ECM_OPTION, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL); ++ ocp_data |= RX_DETECT8; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data); ++ ++ r8153b_u1u2en(tp, false); ++ ++ switch (tp->version) { ++ case RTL_VER_13: ++ case RTL_VER_15: ++ r8156b_wait_loading_flash(tp); ++ break; ++ default: ++ break; ++ } ++ ++ for (i = 0; i < 500; i++) { ++ if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & ++ AUTOLOAD_DONE) ++ break; ++ ++ msleep(20); ++ if (test_bit(RTL8152_UNPLUG, &tp->flags)) ++ return; ++ } ++ ++ data = r8153_phy_status(tp, 0); ++ if (data == PHY_STAT_EXT_INIT) { ++ data = ocp_reg_read(tp, 0xa468); ++ data &= ~(BIT(3) | BIT(1)); ++ ocp_reg_write(tp, 0xa468, data); ++ ++ data = ocp_reg_read(tp, 0xa466); ++ data &= ~BIT(0); ++ ocp_reg_write(tp, 0xa466, data); ++ } ++ ++ data = r8152_mdio_read(tp, MII_BMCR); ++ if (data & BMCR_PDOWN) { ++ data &= ~BMCR_PDOWN; ++ r8152_mdio_write(tp, MII_BMCR, data); ++ } ++ ++ data = r8153_phy_status(tp, PHY_STAT_LAN_ON); ++ ++ r8153_u2p3en(tp, false); ++ ++ /* MSC timer = 0xfff * 8ms = 32760 ms */ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff); ++ ++ /* U1/U2/L1 idle timer. 500 us */ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500); ++ ++ r8153b_power_cut_en(tp, false); ++ r8156_ups_en(tp, false); ++ r8153_queue_wake(tp, false); ++ rtl_runtime_suspend_enable(tp, false); ++ ++ if (tp->udev->speed >= USB_SPEED_SUPER) ++ r8153b_u1u2en(tp, true); ++ ++ usb_enable_lpm(tp->udev); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_RCR); ++ ocp_data &= ~SLOT_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR); ++ ocp_data |= FLOW_CTRL_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data); ++ ++ /* enable fc timer and set timer to 600 ms. */ ++ ocp_write_word(tp, MCU_TYPE_USB, USB_FC_TIMER, ++ CTRL_TIMER_EN | (600 / 8)); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_CTRL); ++ if (!(ocp_read_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL) & DACK_DET_EN)) ++ ocp_data |= FLOW_CTRL_PATCH_2; ++ ocp_data &= ~AUTO_SPEEDUP; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_CTRL, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK); ++ ocp_data |= FC_PATCH_TASK; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data); ++ ++ r8156_mac_clk_spd(tp, true); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); ++ ocp_data &= ~PLA_MCU_SPDWN_EN; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS); ++ if (rtl8152_get_speed(tp) & LINK_STATUS) ++ ocp_data |= CUR_LINK_OK; ++ else ++ ocp_data &= ~CUR_LINK_OK; ++ ocp_data |= POLL_LINK_CHG; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data); ++ ++ set_bit(GREEN_ETHERNET, &tp->flags); ++ ++ /* rx aggregation */ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); ++ ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); ++ ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); ++ ++ rtl_tally_reset(tp); ++ ++ tp->coalesce = 15000; /* 15 us */ ++} ++ + static int rtl8152_pre_reset(struct usb_interface *intf) + { + struct r8152 *tp = usb_get_intfdata(intf); +@@ -6015,6 +7947,22 @@ int rtl8152_get_link_ksettings(struct ne + + mii_ethtool_get_link_ksettings(&tp->mii, cmd); + ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ cmd->link_modes.supported, tp->support_2500full); ++ ++ if (tp->support_2500full) { ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ cmd->link_modes.advertising, ++ ocp_reg_read(tp, OCP_10GBT_CTRL) & MDIO_AN_10GBT_CTRL_ADV2_5G); ++ ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ cmd->link_modes.lp_advertising, ++ ocp_reg_read(tp, OCP_10GBT_STAT) & MDIO_AN_10GBT_STAT_LP2_5G); ++ ++ if (is_speed_2500(rtl8152_get_speed(tp))) ++ cmd->base.speed = SPEED_2500; ++ } ++ + mutex_unlock(&tp->control); + + usb_autopm_put_interface(tp->intf); +@@ -6058,6 +8006,10 @@ static int rtl8152_set_link_ksettings(st + cmd->link_modes.advertising)) + advertising |= RTL_ADVERTISED_1000_FULL; + ++ if (test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ cmd->link_modes.advertising)) ++ advertising |= RTL_ADVERTISED_2500_FULL; ++ + mutex_lock(&tp->control); + + ret = rtl8152_set_speed(tp, cmd->base.autoneg, cmd->base.speed, +@@ -6647,6 +8599,67 @@ static int rtl_ops_init(struct r8152 *tp + tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; + break; + ++ case RTL_VER_11: ++ tp->eee_en = true; ++ tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; ++ fallthrough; ++ case RTL_VER_10: ++ ops->init = r8156_init; ++ ops->enable = rtl8156_enable; ++ ops->disable = rtl8153_disable; ++ ops->up = rtl8156_up; ++ ops->down = rtl8156_down; ++ ops->unload = rtl8153_unload; ++ ops->eee_get = r8153_get_eee; ++ ops->eee_set = r8152_set_eee; ++ ops->in_nway = rtl8153_in_nway; ++ ops->hw_phy_cfg = r8156_hw_phy_cfg; ++ ops->autosuspend_en = rtl8156_runtime_enable; ++ ops->change_mtu = rtl8156_change_mtu; ++ tp->rx_buf_sz = 48 * 1024; ++ tp->support_2500full = 1; ++ break; ++ ++ case RTL_VER_12: ++ case RTL_VER_13: ++ tp->support_2500full = 1; ++ fallthrough; ++ case RTL_VER_15: ++ tp->eee_en = true; ++ tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; ++ ops->init = r8156b_init; ++ ops->enable = rtl8156b_enable; ++ ops->disable = rtl8153_disable; ++ ops->up = rtl8156_up; ++ ops->down = rtl8156_down; ++ ops->unload = rtl8153_unload; ++ ops->eee_get = r8153_get_eee; ++ ops->eee_set = r8152_set_eee; ++ ops->in_nway = rtl8153_in_nway; ++ ops->hw_phy_cfg = r8156b_hw_phy_cfg; ++ ops->autosuspend_en = rtl8156_runtime_enable; ++ ops->change_mtu = rtl8156_change_mtu; ++ tp->rx_buf_sz = 48 * 1024; ++ break; ++ ++ case RTL_VER_14: ++ ops->init = r8153c_init; ++ ops->enable = rtl8153_enable; ++ ops->disable = rtl8153_disable; ++ ops->up = rtl8153c_up; ++ ops->down = rtl8153b_down; ++ ops->unload = rtl8153_unload; ++ ops->eee_get = r8153_get_eee; ++ ops->eee_set = r8152_set_eee; ++ ops->in_nway = rtl8153_in_nway; ++ ops->hw_phy_cfg = r8153c_hw_phy_cfg; ++ ops->autosuspend_en = rtl8153c_runtime_enable; ++ ops->change_mtu = rtl8153c_change_mtu; ++ tp->rx_buf_sz = 32 * 1024; ++ tp->eee_en = true; ++ tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; ++ break; ++ + default: + ret = -ENODEV; + dev_err(&tp->intf->dev, "Unknown Device\n"); +@@ -6660,11 +8673,13 @@ static int rtl_ops_init(struct r8152 *tp + #define FIRMWARE_8153A_3 "rtl_nic/rtl8153a-3.fw" + #define FIRMWARE_8153A_4 "rtl_nic/rtl8153a-4.fw" + #define FIRMWARE_8153B_2 "rtl_nic/rtl8153b-2.fw" ++#define FIRMWARE_8153C_1 "rtl_nic/rtl8153c-1.fw" + + MODULE_FIRMWARE(FIRMWARE_8153A_2); + MODULE_FIRMWARE(FIRMWARE_8153A_3); + MODULE_FIRMWARE(FIRMWARE_8153A_4); + MODULE_FIRMWARE(FIRMWARE_8153B_2); ++MODULE_FIRMWARE(FIRMWARE_8153C_1); + + static int rtl_fw_init(struct r8152 *tp) + { +@@ -6690,6 +8705,11 @@ static int rtl_fw_init(struct r8152 *tp) + rtl_fw->pre_fw = r8153b_pre_firmware_1; + rtl_fw->post_fw = r8153b_post_firmware_1; + break; ++ case RTL_VER_14: ++ rtl_fw->fw_name = FIRMWARE_8153C_1; ++ rtl_fw->pre_fw = r8153b_pre_firmware_1; ++ rtl_fw->post_fw = r8153c_post_firmware_1; ++ break; + default: + break; + } +@@ -6745,6 +8765,27 @@ u8 rtl8152_get_version(struct usb_interf + case 0x6010: + version = RTL_VER_09; + break; ++ case 0x7010: ++ version = RTL_TEST_01; ++ break; ++ case 0x7020: ++ version = RTL_VER_10; ++ break; ++ case 0x7030: ++ version = RTL_VER_11; ++ break; ++ case 0x7400: ++ version = RTL_VER_12; ++ break; ++ case 0x7410: ++ version = RTL_VER_13; ++ break; ++ case 0x6400: ++ version = RTL_VER_14; ++ break; ++ case 0x7420: ++ version = RTL_VER_15; ++ break; + default: + version = RTL_VER_UNKNOWN; + dev_info(&intf->dev, "Unknown version 0x%04x\n", ocp_data); +@@ -6857,12 +8898,29 @@ static int rtl8152_probe(struct usb_inte + /* MTU range: 68 - 1500 or 9194 */ + netdev->min_mtu = ETH_MIN_MTU; + switch (tp->version) { ++ case RTL_VER_03: ++ case RTL_VER_04: ++ case RTL_VER_05: ++ case RTL_VER_06: ++ case RTL_VER_08: ++ case RTL_VER_09: ++ case RTL_VER_14: ++ netdev->max_mtu = size_to_mtu(9 * 1024); ++ break; ++ case RTL_VER_10: ++ case RTL_VER_11: ++ netdev->max_mtu = size_to_mtu(15 * 1024); ++ break; ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: ++ netdev->max_mtu = size_to_mtu(16 * 1024); ++ break; + case RTL_VER_01: + case RTL_VER_02: +- netdev->max_mtu = ETH_DATA_LEN; +- break; ++ case RTL_VER_07: + default: +- netdev->max_mtu = size_to_mtu(9 * 1024); ++ netdev->max_mtu = ETH_DATA_LEN; + break; + } + +@@ -6878,7 +8936,13 @@ static int rtl8152_probe(struct usb_inte + tp->advertising = RTL_ADVERTISED_10_HALF | RTL_ADVERTISED_10_FULL | + RTL_ADVERTISED_100_HALF | RTL_ADVERTISED_100_FULL; + if (tp->mii.supports_gmii) { +- tp->speed = SPEED_1000; ++ if (tp->support_2500full && ++ tp->udev->speed >= USB_SPEED_SUPER) { ++ tp->speed = SPEED_2500; ++ tp->advertising |= RTL_ADVERTISED_2500_FULL; ++ } else { ++ tp->speed = SPEED_1000; ++ } + tp->advertising |= RTL_ADVERTISED_1000_FULL; + } + tp->duplex = DUPLEX_FULL; +@@ -6902,7 +8966,11 @@ static int rtl8152_probe(struct usb_inte + set_ethernet_addr(tp); + + usb_set_intfdata(intf, tp); +- netif_napi_add(netdev, &tp->napi, r8152_poll, RTL8152_NAPI_WEIGHT); ++ ++ if (tp->support_2500full) ++ netif_napi_add(netdev, &tp->napi, r8152_poll, 256); ++ else ++ netif_napi_add(netdev, &tp->napi, r8152_poll, 64); + + ret = register_netdev(netdev); + if (ret != 0) { +@@ -6938,7 +9006,8 @@ static void rtl8152_disconnect(struct us + unregister_netdev(tp->netdev); + tasklet_kill(&tp->tx_tl); + cancel_delayed_work_sync(&tp->hw_phy_work); +- tp->rtl_ops.unload(tp); ++ if (tp->rtl_ops.unload) ++ tp->rtl_ops.unload(tp); + rtl8152_release_firmware(tp); + free_netdev(tp->netdev); + } +@@ -6958,13 +9027,28 @@ static void rtl8152_disconnect(struct us + .idProduct = (prod), \ + .bInterfaceClass = USB_CLASS_COMM, \ + .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \ ++ .bInterfaceProtocol = USB_CDC_PROTO_NONE \ ++}, \ ++{ \ ++ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | \ ++ USB_DEVICE_ID_MATCH_DEVICE, \ ++ .idVendor = (vend), \ ++ .idProduct = (prod), \ ++ .bInterfaceClass = USB_CLASS_COMM, \ ++ .bInterfaceSubClass = USB_CDC_SUBCLASS_NCM, \ + .bInterfaceProtocol = USB_CDC_PROTO_NONE + + /* table of devices that work with this driver */ + static const struct usb_device_id rtl8152_table[] = { ++ /* Realtek */ + {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8050)}, ++ {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8053)}, + {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152)}, + {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)}, ++ {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8155)}, ++ {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8156)}, ++ ++ /* Microsoft */ + {REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab)}, + {REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6)}, + {REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0927)}, diff --git a/target/linux/generic/backport-5.10/794-v5.13-r8152-support-PHY-firmware-for-RTL8156-series.patch b/target/linux/generic/backport-5.10/794-v5.13-r8152-support-PHY-firmware-for-RTL8156-series.patch new file mode 100644 index 0000000000..943c821b82 --- /dev/null +++ b/target/linux/generic/backport-5.10/794-v5.13-r8152-support-PHY-firmware-for-RTL8156-series.patch @@ -0,0 +1,691 @@ +From ca09589a72a0aa17389754fb75a5cd1a5d46818f Mon Sep 17 00:00:00 2001 +From: Hayes Wang <hayeswang@realtek.com> +Date: Fri, 16 Apr 2021 16:04:36 +0800 +Subject: [PATCH] r8152: support PHY firmware for RTL8156 series + +commit 4a51b0e8a0143b0e83d51d9c58c6416c3818a9f2 upstream. + +Support new firmware type and method for RTL8156 series. + +Signed-off-by: Hayes Wang <hayeswang@realtek.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/usb/r8152.c | 563 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 561 insertions(+), 2 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -975,8 +975,60 @@ enum rtl8152_fw_flags { + FW_FLAGS_START, + FW_FLAGS_STOP, + FW_FLAGS_NC, ++ FW_FLAGS_NC1, ++ FW_FLAGS_NC2, ++ FW_FLAGS_UC2, ++ FW_FLAGS_UC, ++ FW_FLAGS_SPEED_UP, ++ FW_FLAGS_VER, + }; + ++enum rtl8152_fw_fixup_cmd { ++ FW_FIXUP_AND = 0, ++ FW_FIXUP_OR, ++ FW_FIXUP_NOT, ++ FW_FIXUP_XOR, ++}; ++ ++struct fw_phy_set { ++ __le16 addr; ++ __le16 data; ++} __packed; ++ ++struct fw_phy_speed_up { ++ struct fw_block blk_hdr; ++ __le16 fw_offset; ++ __le16 version; ++ __le16 fw_reg; ++ __le16 reserved; ++ char info[]; ++} __packed; ++ ++struct fw_phy_ver { ++ struct fw_block blk_hdr; ++ struct fw_phy_set ver; ++ __le32 reserved; ++} __packed; ++ ++struct fw_phy_fixup { ++ struct fw_block blk_hdr; ++ struct fw_phy_set setting; ++ __le16 bit_cmd; ++ __le16 reserved; ++} __packed; ++ ++struct fw_phy_union { ++ struct fw_block blk_hdr; ++ __le16 fw_offset; ++ __le16 fw_reg; ++ struct fw_phy_set pre_set[2]; ++ struct fw_phy_set bp[8]; ++ struct fw_phy_set bp_en; ++ u8 pre_num; ++ u8 bp_num; ++ char info[]; ++} __packed; ++ + /** + * struct fw_mac - a firmware block used by RTL_FW_PLA and RTL_FW_USB. + * The layout of the firmware block is: +@@ -1081,6 +1133,15 @@ enum rtl_fw_type { + RTL_FW_PHY_START, + RTL_FW_PHY_STOP, + RTL_FW_PHY_NC, ++ RTL_FW_PHY_FIXUP, ++ RTL_FW_PHY_UNION_NC, ++ RTL_FW_PHY_UNION_NC1, ++ RTL_FW_PHY_UNION_NC2, ++ RTL_FW_PHY_UNION_UC2, ++ RTL_FW_PHY_UNION_UC, ++ RTL_FW_PHY_UNION_MISC, ++ RTL_FW_PHY_SPEED_UP, ++ RTL_FW_PHY_VER, + }; + + enum rtl_version { +@@ -4000,6 +4061,162 @@ static int rtl_post_ram_code(struct r815 + return 0; + } + ++static bool rtl8152_is_fw_phy_speed_up_ok(struct r8152 *tp, struct fw_phy_speed_up *phy) ++{ ++ u16 fw_offset; ++ u32 length; ++ bool rc = false; ++ ++ switch (tp->version) { ++ case RTL_VER_01: ++ case RTL_VER_02: ++ case RTL_VER_03: ++ case RTL_VER_04: ++ case RTL_VER_05: ++ case RTL_VER_06: ++ case RTL_VER_07: ++ case RTL_VER_08: ++ case RTL_VER_09: ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_14: ++ goto out; ++ case RTL_VER_13: ++ case RTL_VER_15: ++ default: ++ break; ++ } ++ ++ fw_offset = __le16_to_cpu(phy->fw_offset); ++ length = __le32_to_cpu(phy->blk_hdr.length); ++ if (fw_offset < sizeof(*phy) || length <= fw_offset) { ++ dev_err(&tp->intf->dev, "invalid fw_offset\n"); ++ goto out; ++ } ++ ++ length -= fw_offset; ++ if (length & 3) { ++ dev_err(&tp->intf->dev, "invalid block length\n"); ++ goto out; ++ } ++ ++ if (__le16_to_cpu(phy->fw_reg) != 0x9A00) { ++ dev_err(&tp->intf->dev, "invalid register to load firmware\n"); ++ goto out; ++ } ++ ++ rc = true; ++out: ++ return rc; ++} ++ ++static bool rtl8152_is_fw_phy_ver_ok(struct r8152 *tp, struct fw_phy_ver *ver) ++{ ++ bool rc = false; ++ ++ switch (tp->version) { ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: ++ break; ++ default: ++ goto out; ++ } ++ ++ if (__le32_to_cpu(ver->blk_hdr.length) != sizeof(*ver)) { ++ dev_err(&tp->intf->dev, "invalid block length\n"); ++ goto out; ++ } ++ ++ if (__le16_to_cpu(ver->ver.addr) != SRAM_GPHY_FW_VER) { ++ dev_err(&tp->intf->dev, "invalid phy ver addr\n"); ++ goto out; ++ } ++ ++ rc = true; ++out: ++ return rc; ++} ++ ++static bool rtl8152_is_fw_phy_fixup_ok(struct r8152 *tp, struct fw_phy_fixup *fix) ++{ ++ bool rc = false; ++ ++ switch (tp->version) { ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: ++ break; ++ default: ++ goto out; ++ } ++ ++ if (__le32_to_cpu(fix->blk_hdr.length) != sizeof(*fix)) { ++ dev_err(&tp->intf->dev, "invalid block length\n"); ++ goto out; ++ } ++ ++ if (__le16_to_cpu(fix->setting.addr) != OCP_PHY_PATCH_CMD || ++ __le16_to_cpu(fix->setting.data) != BIT(7)) { ++ dev_err(&tp->intf->dev, "invalid phy fixup\n"); ++ goto out; ++ } ++ ++ rc = true; ++out: ++ return rc; ++} ++ ++static bool rtl8152_is_fw_phy_union_ok(struct r8152 *tp, struct fw_phy_union *phy) ++{ ++ u16 fw_offset; ++ u32 length; ++ bool rc = false; ++ ++ switch (tp->version) { ++ case RTL_VER_10: ++ case RTL_VER_11: ++ case RTL_VER_12: ++ case RTL_VER_13: ++ case RTL_VER_15: ++ break; ++ default: ++ goto out; ++ } ++ ++ fw_offset = __le16_to_cpu(phy->fw_offset); ++ length = __le32_to_cpu(phy->blk_hdr.length); ++ if (fw_offset < sizeof(*phy) || length <= fw_offset) { ++ dev_err(&tp->intf->dev, "invalid fw_offset\n"); ++ goto out; ++ } ++ ++ length -= fw_offset; ++ if (length & 1) { ++ dev_err(&tp->intf->dev, "invalid block length\n"); ++ goto out; ++ } ++ ++ if (phy->pre_num > 2) { ++ dev_err(&tp->intf->dev, "invalid pre_num %d\n", phy->pre_num); ++ goto out; ++ } ++ ++ if (phy->bp_num > 8) { ++ dev_err(&tp->intf->dev, "invalid bp_num %d\n", phy->bp_num); ++ goto out; ++ } ++ ++ rc = true; ++out: ++ return rc; ++} ++ + static bool rtl8152_is_fw_phy_nc_ok(struct r8152 *tp, struct fw_phy_nc *phy) + { + u32 length; +@@ -4320,6 +4537,10 @@ static long rtl8152_check_firmware(struc + case RTL_FW_PHY_START: + if (test_bit(FW_FLAGS_START, &fw_flags) || + test_bit(FW_FLAGS_NC, &fw_flags) || ++ test_bit(FW_FLAGS_NC1, &fw_flags) || ++ test_bit(FW_FLAGS_NC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC, &fw_flags) || + test_bit(FW_FLAGS_STOP, &fw_flags)) { + dev_err(&tp->intf->dev, + "check PHY_START fail\n"); +@@ -4368,7 +4589,153 @@ static long rtl8152_check_firmware(struc + goto fail; + } + __set_bit(FW_FLAGS_NC, &fw_flags); ++ break; ++ case RTL_FW_PHY_UNION_NC: ++ if (!test_bit(FW_FLAGS_START, &fw_flags) || ++ test_bit(FW_FLAGS_NC1, &fw_flags) || ++ test_bit(FW_FLAGS_NC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC, &fw_flags) || ++ test_bit(FW_FLAGS_STOP, &fw_flags)) { ++ dev_err(&tp->intf->dev, "PHY_UNION_NC out of order\n"); ++ goto fail; ++ } ++ ++ if (test_bit(FW_FLAGS_NC, &fw_flags)) { ++ dev_err(&tp->intf->dev, "multiple PHY_UNION_NC encountered\n"); ++ goto fail; ++ } + ++ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { ++ dev_err(&tp->intf->dev, "check PHY_UNION_NC failed\n"); ++ goto fail; ++ } ++ __set_bit(FW_FLAGS_NC, &fw_flags); ++ break; ++ case RTL_FW_PHY_UNION_NC1: ++ if (!test_bit(FW_FLAGS_START, &fw_flags) || ++ test_bit(FW_FLAGS_NC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC, &fw_flags) || ++ test_bit(FW_FLAGS_STOP, &fw_flags)) { ++ dev_err(&tp->intf->dev, "PHY_UNION_NC1 out of order\n"); ++ goto fail; ++ } ++ ++ if (test_bit(FW_FLAGS_NC1, &fw_flags)) { ++ dev_err(&tp->intf->dev, "multiple PHY NC1 encountered\n"); ++ goto fail; ++ } ++ ++ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { ++ dev_err(&tp->intf->dev, "check PHY_UNION_NC1 failed\n"); ++ goto fail; ++ } ++ __set_bit(FW_FLAGS_NC1, &fw_flags); ++ break; ++ case RTL_FW_PHY_UNION_NC2: ++ if (!test_bit(FW_FLAGS_START, &fw_flags) || ++ test_bit(FW_FLAGS_UC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC, &fw_flags) || ++ test_bit(FW_FLAGS_STOP, &fw_flags)) { ++ dev_err(&tp->intf->dev, "PHY_UNION_NC2 out of order\n"); ++ goto fail; ++ } ++ ++ if (test_bit(FW_FLAGS_NC2, &fw_flags)) { ++ dev_err(&tp->intf->dev, "multiple PHY NC2 encountered\n"); ++ goto fail; ++ } ++ ++ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { ++ dev_err(&tp->intf->dev, "check PHY_UNION_NC2 failed\n"); ++ goto fail; ++ } ++ __set_bit(FW_FLAGS_NC2, &fw_flags); ++ break; ++ case RTL_FW_PHY_UNION_UC2: ++ if (!test_bit(FW_FLAGS_START, &fw_flags) || ++ test_bit(FW_FLAGS_UC, &fw_flags) || ++ test_bit(FW_FLAGS_STOP, &fw_flags)) { ++ dev_err(&tp->intf->dev, "PHY_UNION_UC2 out of order\n"); ++ goto fail; ++ } ++ ++ if (test_bit(FW_FLAGS_UC2, &fw_flags)) { ++ dev_err(&tp->intf->dev, "multiple PHY UC2 encountered\n"); ++ goto fail; ++ } ++ ++ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { ++ dev_err(&tp->intf->dev, "check PHY_UNION_UC2 failed\n"); ++ goto fail; ++ } ++ __set_bit(FW_FLAGS_UC2, &fw_flags); ++ break; ++ case RTL_FW_PHY_UNION_UC: ++ if (!test_bit(FW_FLAGS_START, &fw_flags) || ++ test_bit(FW_FLAGS_STOP, &fw_flags)) { ++ dev_err(&tp->intf->dev, "PHY_UNION_UC out of order\n"); ++ goto fail; ++ } ++ ++ if (test_bit(FW_FLAGS_UC, &fw_flags)) { ++ dev_err(&tp->intf->dev, "multiple PHY UC encountered\n"); ++ goto fail; ++ } ++ ++ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { ++ dev_err(&tp->intf->dev, "check PHY_UNION_UC failed\n"); ++ goto fail; ++ } ++ __set_bit(FW_FLAGS_UC, &fw_flags); ++ break; ++ case RTL_FW_PHY_UNION_MISC: ++ if (!rtl8152_is_fw_phy_union_ok(tp, (struct fw_phy_union *)block)) { ++ dev_err(&tp->intf->dev, "check RTL_FW_PHY_UNION_MISC failed\n"); ++ goto fail; ++ } ++ break; ++ case RTL_FW_PHY_FIXUP: ++ if (!rtl8152_is_fw_phy_fixup_ok(tp, (struct fw_phy_fixup *)block)) { ++ dev_err(&tp->intf->dev, "check PHY fixup failed\n"); ++ goto fail; ++ } ++ break; ++ case RTL_FW_PHY_SPEED_UP: ++ if (test_bit(FW_FLAGS_SPEED_UP, &fw_flags)) { ++ dev_err(&tp->intf->dev, "multiple PHY firmware encountered"); ++ goto fail; ++ } ++ ++ if (!rtl8152_is_fw_phy_speed_up_ok(tp, (struct fw_phy_speed_up *)block)) { ++ dev_err(&tp->intf->dev, "check PHY speed up failed\n"); ++ goto fail; ++ } ++ __set_bit(FW_FLAGS_SPEED_UP, &fw_flags); ++ break; ++ case RTL_FW_PHY_VER: ++ if (test_bit(FW_FLAGS_START, &fw_flags) || ++ test_bit(FW_FLAGS_NC, &fw_flags) || ++ test_bit(FW_FLAGS_NC1, &fw_flags) || ++ test_bit(FW_FLAGS_NC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC2, &fw_flags) || ++ test_bit(FW_FLAGS_UC, &fw_flags) || ++ test_bit(FW_FLAGS_STOP, &fw_flags)) { ++ dev_err(&tp->intf->dev, "Invalid order to set PHY version\n"); ++ goto fail; ++ } ++ ++ if (test_bit(FW_FLAGS_VER, &fw_flags)) { ++ dev_err(&tp->intf->dev, "multiple PHY version encountered"); ++ goto fail; ++ } ++ ++ if (!rtl8152_is_fw_phy_ver_ok(tp, (struct fw_phy_ver *)block)) { ++ dev_err(&tp->intf->dev, "check PHY version failed\n"); ++ goto fail; ++ } ++ __set_bit(FW_FLAGS_VER, &fw_flags); + break; + default: + dev_warn(&tp->intf->dev, "Unknown type %u is found\n", +@@ -4391,6 +4758,143 @@ fail: + return ret; + } + ++static void rtl_ram_code_speed_up(struct r8152 *tp, struct fw_phy_speed_up *phy, bool wait) ++{ ++ u32 len; ++ u8 *data; ++ ++ if (sram_read(tp, SRAM_GPHY_FW_VER) >= __le16_to_cpu(phy->version)) { ++ dev_dbg(&tp->intf->dev, "PHY firmware has been the newest\n"); ++ return; ++ } ++ ++ len = __le32_to_cpu(phy->blk_hdr.length); ++ len -= __le16_to_cpu(phy->fw_offset); ++ data = (u8 *)phy + __le16_to_cpu(phy->fw_offset); ++ ++ if (rtl_phy_patch_request(tp, true, wait)) ++ return; ++ ++ while (len) { ++ u32 ocp_data, size; ++ int i; ++ ++ if (len < 2048) ++ size = len; ++ else ++ size = 2048; ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_GPHY_CTRL); ++ ocp_data |= GPHY_PATCH_DONE | BACKUP_RESTRORE; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_GPHY_CTRL, ocp_data); ++ ++ generic_ocp_write(tp, __le16_to_cpu(phy->fw_reg), 0xff, size, data, MCU_TYPE_USB); ++ ++ data += size; ++ len -= size; ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL); ++ ocp_data |= POL_GPHY_PATCH; ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL, ocp_data); ++ ++ for (i = 0; i < 1000; i++) { ++ if (!(ocp_read_word(tp, MCU_TYPE_PLA, PLA_POL_GPIO_CTRL) & POL_GPHY_PATCH)) ++ break; ++ } ++ ++ if (i == 1000) { ++ dev_err(&tp->intf->dev, "ram code speedup mode timeout\n"); ++ return; ++ } ++ } ++ ++ ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, tp->ocp_base); ++ rtl_phy_patch_request(tp, false, wait); ++ ++ if (sram_read(tp, SRAM_GPHY_FW_VER) == __le16_to_cpu(phy->version)) ++ dev_dbg(&tp->intf->dev, "successfully applied %s\n", phy->info); ++ else ++ dev_err(&tp->intf->dev, "ram code speedup mode fail\n"); ++} ++ ++static int rtl8152_fw_phy_ver(struct r8152 *tp, struct fw_phy_ver *phy_ver) ++{ ++ u16 ver_addr, ver; ++ ++ ver_addr = __le16_to_cpu(phy_ver->ver.addr); ++ ver = __le16_to_cpu(phy_ver->ver.data); ++ ++ if (sram_read(tp, ver_addr) >= ver) { ++ dev_dbg(&tp->intf->dev, "PHY firmware has been the newest\n"); ++ return 0; ++ } ++ ++ sram_write(tp, ver_addr, ver); ++ ++ dev_dbg(&tp->intf->dev, "PHY firmware version %x\n", ver); ++ ++ return ver; ++} ++ ++static void rtl8152_fw_phy_fixup(struct r8152 *tp, struct fw_phy_fixup *fix) ++{ ++ u16 addr, data; ++ ++ addr = __le16_to_cpu(fix->setting.addr); ++ data = ocp_reg_read(tp, addr); ++ ++ switch (__le16_to_cpu(fix->bit_cmd)) { ++ case FW_FIXUP_AND: ++ data &= __le16_to_cpu(fix->setting.data); ++ break; ++ case FW_FIXUP_OR: ++ data |= __le16_to_cpu(fix->setting.data); ++ break; ++ case FW_FIXUP_NOT: ++ data &= ~__le16_to_cpu(fix->setting.data); ++ break; ++ case FW_FIXUP_XOR: ++ data ^= __le16_to_cpu(fix->setting.data); ++ break; ++ default: ++ return; ++ } ++ ++ ocp_reg_write(tp, addr, data); ++ ++ dev_dbg(&tp->intf->dev, "applied ocp %x %x\n", addr, data); ++} ++ ++static void rtl8152_fw_phy_union_apply(struct r8152 *tp, struct fw_phy_union *phy) ++{ ++ __le16 *data; ++ u32 length; ++ int i, num; ++ ++ num = phy->pre_num; ++ for (i = 0; i < num; i++) ++ sram_write(tp, __le16_to_cpu(phy->pre_set[i].addr), ++ __le16_to_cpu(phy->pre_set[i].data)); ++ ++ length = __le32_to_cpu(phy->blk_hdr.length); ++ length -= __le16_to_cpu(phy->fw_offset); ++ num = length / 2; ++ data = (__le16 *)((u8 *)phy + __le16_to_cpu(phy->fw_offset)); ++ ++ ocp_reg_write(tp, OCP_SRAM_ADDR, __le16_to_cpu(phy->fw_reg)); ++ for (i = 0; i < num; i++) ++ ocp_reg_write(tp, OCP_SRAM_DATA, __le16_to_cpu(data[i])); ++ ++ num = phy->bp_num; ++ for (i = 0; i < num; i++) ++ sram_write(tp, __le16_to_cpu(phy->bp[i].addr), __le16_to_cpu(phy->bp[i].data)); ++ ++ if (phy->bp_num && phy->bp_en.addr) ++ sram_write(tp, __le16_to_cpu(phy->bp_en.addr), __le16_to_cpu(phy->bp_en.data)); ++ ++ dev_dbg(&tp->intf->dev, "successfully applied %s\n", phy->info); ++} ++ + static void rtl8152_fw_phy_nc_apply(struct r8152 *tp, struct fw_phy_nc *phy) + { + u16 mode_reg, bp_index; +@@ -4444,6 +4948,12 @@ static void rtl8152_fw_mac_apply(struct + return; + } + ++ fw_ver_reg = __le16_to_cpu(mac->fw_ver_reg); ++ if (fw_ver_reg && ocp_read_byte(tp, MCU_TYPE_USB, fw_ver_reg) >= mac->fw_ver_data) { ++ dev_dbg(&tp->intf->dev, "%s firmware has been the newest\n", type ? "PLA" : "USB"); ++ return; ++ } ++ + rtl_clear_bp(tp, type); + + /* Enable backup/restore of MACDBG. This is required after clearing PLA +@@ -4479,7 +4989,6 @@ static void rtl8152_fw_mac_apply(struct + ocp_write_word(tp, type, bp_en_addr, + __le16_to_cpu(mac->bp_en_value)); + +- fw_ver_reg = __le16_to_cpu(mac->fw_ver_reg); + if (fw_ver_reg) + ocp_write_byte(tp, MCU_TYPE_USB, fw_ver_reg, + mac->fw_ver_data); +@@ -4494,7 +5003,7 @@ static void rtl8152_apply_firmware(struc + struct fw_header *fw_hdr; + struct fw_phy_patch_key *key; + u16 key_addr = 0; +- int i; ++ int i, patch_phy = 1; + + if (IS_ERR_OR_NULL(rtl_fw->fw)) + return; +@@ -4516,17 +5025,40 @@ static void rtl8152_apply_firmware(struc + rtl8152_fw_mac_apply(tp, (struct fw_mac *)block); + break; + case RTL_FW_PHY_START: ++ if (!patch_phy) ++ break; + key = (struct fw_phy_patch_key *)block; + key_addr = __le16_to_cpu(key->key_reg); + rtl_pre_ram_code(tp, key_addr, __le16_to_cpu(key->key_data), !power_cut); + break; + case RTL_FW_PHY_STOP: ++ if (!patch_phy) ++ break; + WARN_ON(!key_addr); + rtl_post_ram_code(tp, key_addr, !power_cut); + break; + case RTL_FW_PHY_NC: + rtl8152_fw_phy_nc_apply(tp, (struct fw_phy_nc *)block); + break; ++ case RTL_FW_PHY_VER: ++ patch_phy = rtl8152_fw_phy_ver(tp, (struct fw_phy_ver *)block); ++ break; ++ case RTL_FW_PHY_UNION_NC: ++ case RTL_FW_PHY_UNION_NC1: ++ case RTL_FW_PHY_UNION_NC2: ++ case RTL_FW_PHY_UNION_UC2: ++ case RTL_FW_PHY_UNION_UC: ++ case RTL_FW_PHY_UNION_MISC: ++ if (patch_phy) ++ rtl8152_fw_phy_union_apply(tp, (struct fw_phy_union *)block); ++ break; ++ case RTL_FW_PHY_FIXUP: ++ if (patch_phy) ++ rtl8152_fw_phy_fixup(tp, (struct fw_phy_fixup *)block); ++ break; ++ case RTL_FW_PHY_SPEED_UP: ++ rtl_ram_code_speed_up(tp, (struct fw_phy_speed_up *)block, !power_cut); ++ break; + default: + break; + } +@@ -5034,6 +5566,21 @@ static int r8153c_post_firmware_1(struct + return 0; + } + ++static int r8156a_post_firmware_1(struct r8152 *tp) ++{ ++ u32 ocp_data; ++ ++ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_FIX_EN1); ++ ocp_data |= FW_IP_RESET_EN; ++ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_FIX_EN1, ocp_data); ++ ++ /* Modify U3PHY parameter for compatibility issue */ ++ ocp_write_dword(tp, MCU_TYPE_USB, USB_UPHY3_MDCMDIO, 0x4026840e); ++ ocp_write_dword(tp, MCU_TYPE_USB, USB_UPHY3_MDCMDIO, 0x4001acc9); ++ ++ return 0; ++} ++ + static void r8153_aldps_en(struct r8152 *tp, bool enable) + { + u16 data; +@@ -8674,12 +9221,16 @@ static int rtl_ops_init(struct r8152 *tp + #define FIRMWARE_8153A_4 "rtl_nic/rtl8153a-4.fw" + #define FIRMWARE_8153B_2 "rtl_nic/rtl8153b-2.fw" + #define FIRMWARE_8153C_1 "rtl_nic/rtl8153c-1.fw" ++#define FIRMWARE_8156A_2 "rtl_nic/rtl8156a-2.fw" ++#define FIRMWARE_8156B_2 "rtl_nic/rtl8156b-2.fw" + + MODULE_FIRMWARE(FIRMWARE_8153A_2); + MODULE_FIRMWARE(FIRMWARE_8153A_3); + MODULE_FIRMWARE(FIRMWARE_8153A_4); + MODULE_FIRMWARE(FIRMWARE_8153B_2); + MODULE_FIRMWARE(FIRMWARE_8153C_1); ++MODULE_FIRMWARE(FIRMWARE_8156A_2); ++MODULE_FIRMWARE(FIRMWARE_8156B_2); + + static int rtl_fw_init(struct r8152 *tp) + { +@@ -8705,6 +9256,14 @@ static int rtl_fw_init(struct r8152 *tp) + rtl_fw->pre_fw = r8153b_pre_firmware_1; + rtl_fw->post_fw = r8153b_post_firmware_1; + break; ++ case RTL_VER_11: ++ rtl_fw->fw_name = FIRMWARE_8156A_2; ++ rtl_fw->post_fw = r8156a_post_firmware_1; ++ break; ++ case RTL_VER_13: ++ case RTL_VER_15: ++ rtl_fw->fw_name = FIRMWARE_8156B_2; ++ break; + case RTL_VER_14: + rtl_fw->fw_name = FIRMWARE_8153C_1; + rtl_fw->pre_fw = r8153b_pre_firmware_1; diff --git a/target/linux/generic/backport-5.10/795-v5.13-r8152-search-the-configuration-of-vendor-mode.patch b/target/linux/generic/backport-5.10/795-v5.13-r8152-search-the-configuration-of-vendor-mode.patch new file mode 100644 index 0000000000..9ce0e778cf --- /dev/null +++ b/target/linux/generic/backport-5.10/795-v5.13-r8152-search-the-configuration-of-vendor-mode.patch @@ -0,0 +1,79 @@ +From 579f58dd2819910354753bc5489fc1588fe9cfe2 Mon Sep 17 00:00:00 2001 +From: Hayes Wang <hayeswang@realtek.com> +Date: Fri, 16 Apr 2021 16:04:37 +0800 +Subject: [PATCH] r8152: search the configuration of vendor mode + +commit c2198943e33b100ed21dfb636c8fa6baef841e9d upstream. + +The vendor mode is not always at config #1, so it is necessary to +set the correct configuration number. + +Signed-off-by: Hayes Wang <hayeswang@realtek.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/usb/r8152.c | 39 +++++++++++++++++++++++++++++++++++---- + 1 file changed, 35 insertions(+), 4 deletions(-) + +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -30,7 +30,7 @@ + #include <linux/usb/r8152.h> + + /* Information for net-next */ +-#define NETNEXT_VERSION "11" ++#define NETNEXT_VERSION "12" + + /* Information for net */ + #define NET_VERSION "11" +@@ -8131,6 +8131,39 @@ static void r8156b_init(struct r8152 *tp + tp->coalesce = 15000; /* 15 us */ + } + ++static bool rtl_vendor_mode(struct usb_interface *intf) ++{ ++ struct usb_host_interface *alt = intf->cur_altsetting; ++ struct usb_device *udev; ++ struct usb_host_config *c; ++ int i, num_configs; ++ ++ if (alt->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) ++ return true; ++ ++ /* The vendor mode is not always config #1, so to find it out. */ ++ udev = interface_to_usbdev(intf); ++ c = udev->config; ++ num_configs = udev->descriptor.bNumConfigurations; ++ for (i = 0; i < num_configs; (i++, c++)) { ++ struct usb_interface_descriptor *desc = NULL; ++ ++ if (c->desc.bNumInterfaces > 0) ++ desc = &c->intf_cache[0]->altsetting->desc; ++ else ++ continue; ++ ++ if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC) { ++ usb_driver_set_configuration(udev, c->desc.bConfigurationValue); ++ break; ++ } ++ } ++ ++ WARN_ON_ONCE(i == num_configs); ++ ++ return false; ++} ++ + static int rtl8152_pre_reset(struct usb_interface *intf) + { + struct r8152 *tp = usb_get_intfdata(intf); +@@ -9369,10 +9402,8 @@ static int rtl8152_probe(struct usb_inte + if (version == RTL_VER_UNKNOWN) + return -ENODEV; + +- if (udev->actconfig->desc.bConfigurationValue != 1) { +- usb_driver_set_configuration(udev, 1); ++ if (!rtl_vendor_mode(intf)) + return -ENODEV; +- } + + if (intf->cur_altsetting->desc.bNumEndpoints < 3) + return -ENODEV; |