All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ted Chen <tedchen@realtek.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v4 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
Date: Thu, 14 Jan 2016 13:22:07 +0800	[thread overview]
Message-ID: <1452748927-60186-1-git-send-email-tedchen@realtek.com> (raw)
In-Reply-To: <201601140542.56223.marex@denx.de>

This patch adds driver support for the Realtek RTL8152B/RTL8153 USB
network adapters.

Signed-off-by: Ted Chen <tedchen@realtek.com>
[swarren, fixed a few compiler warnings]
[swarren, with permission, converted license header to SPDX]
[swarren, removed printf() spew during probe()]
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 drivers/usb/eth/Makefile    |    1 +
 drivers/usb/eth/r8152.c     | 1459 +++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/eth/r8152.h     |  623 ++++++++++++++++++
 drivers/usb/eth/r8152_fw.c  |  980 +++++++++++++++++++++++++++++
 drivers/usb/eth/usb_ether.c |    7 +
 include/usb_ether.h         |    6 +
 6 files changed, 3076 insertions(+)
 create mode 100644 drivers/usb/eth/r8152.c
 create mode 100644 drivers/usb/eth/r8152.h
 create mode 100644 drivers/usb/eth/r8152_fw.c

Changes for v2: Modified by Marek's comments.
- Remove pattern informations.
- Don't allocate & free when read/write register.
- relpace udelay to mdelay.
- pull firmware into global variable.
- code review.

Changes for v3: Modified by Marek's and Joe's comments.
- Remove driver version informations.
- separate firmware code to individual file.
- split extensive defines to r8152.h.
- code review.

Changes for v4: Modified by Marek's comments.
- remove the redundant code in generic_ocp_read and generic_ocp_write.
- remove redundant typecasting.
- collect the codes of busy waiting to rtl8152_reinit_ll and rtl8152_nic_reset.
- use ARRAY_SIZE() to avoid having 0x00 as a terminating entry of r8152_dongles.
- using if (!ep_in_found && (ep_addr & USB_DIR_IN)) ... to replace old version.
- code review.

diff --git a/drivers/usb/eth/Makefile b/drivers/usb/eth/Makefile
index c92d2b0..4c44efc 100644
--- a/drivers/usb/eth/Makefile
+++ b/drivers/usb/eth/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_USB_ETHER_ASIX) += asix.o
 obj-$(CONFIG_USB_ETHER_ASIX88179) += asix88179.o
 obj-$(CONFIG_USB_ETHER_MCS7830) += mcs7830.o
 obj-$(CONFIG_USB_ETHER_SMSC95XX) += smsc95xx.o
+obj-$(CONFIG_USB_ETHER_RTL8152) += r8152.o r8152_fw.o
diff --git a/drivers/usb/eth/r8152.c b/drivers/usb/eth/r8152.c
new file mode 100644
index 0000000..1b0f556
--- /dev/null
+++ b/drivers/usb/eth/r8152.c
@@ -0,0 +1,1459 @@
+/*
+ * Copyright (c) 2015 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ *
+  */
+
+#include <common.h>
+#include <errno.h>
+#include <malloc.h>
+#include <usb.h>
+#include <usb/lin_gadget_compat.h>
+#include <linux/mii.h>
+#include <linux/bitops.h>
+#include "usb_ether.h"
+#include "r8152.h"
+
+/* local vars */
+static int curr_eth_dev; /* index for name of next device detected */
+
+struct r8152_dongle {
+	unsigned short vendor;
+	unsigned short product;
+};
+
+static const struct r8152_dongle const r8152_dongles[] = {
+	/* Realtek */
+	{ 0x0bda, 0x8050 },
+	{ 0x0bda, 0x8152 },
+	{ 0x0bda, 0x8153 },
+
+	/* Samsung */
+	{ 0x04e8, 0xa101 },
+
+	/* Lenovo */
+	{ 0x17ef, 0x304f },
+	{ 0x17ef, 0x3052 },
+	{ 0x17ef, 0x3054 },
+	{ 0x17ef, 0x3057 },
+	{ 0x17ef, 0x7205 },
+	{ 0x17ef, 0x720a },
+	{ 0x17ef, 0x720b },
+	{ 0x17ef, 0x720c },
+
+	/* TP-LINK */
+	{ 0x2357, 0x0601 },
+
+	/* Nvidia */
+	{ 0x0955, 0x09ff },
+};
+
+static
+int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
+{
+	return usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0),
+			       RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
+			       value, index, data, size, 500);
+
+}
+
+static
+int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
+{
+	return usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0),
+			       RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE,
+			       value, index, data, size, 500);
+}
+
+int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
+		     void *data, u16 type)
+{
+	u16 burst_size = 64;
+	int ret;
+	int txsize;
+
+	/* both size and index must be 4 bytes align */
+	if ((size & 3) || !size || (index & 3) || !data)
+		return -EINVAL;
+
+	if (index + size > 0xffff)
+		return -EINVAL;
+
+	while (size) {
+		txsize = min(size, burst_size);
+		ret = get_registers(tp, index, type, txsize, data);
+		if (ret < 0)
+			break;
+
+		index += txsize;
+		data += txsize;
+		size -= txsize;
+	}
+
+	return ret;
+}
+
+int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
+		      u16 size, void *data, u16 type)
+{
+	int ret;
+	u16 byteen_start, byteen_end, byte_en_to_hw;
+	u16 burst_size = 512;
+	int txsize;
+
+	/* both size and index must be 4 bytes align */
+	if ((size & 3) || !size || (index & 3) || !data)
+		return -EINVAL;
+
+	if (index + size > 0xffff)
+		return -EINVAL;
+
+	byteen_start = byteen & BYTE_EN_START_MASK;
+	byteen_end = byteen & BYTE_EN_END_MASK;
+
+	byte_en_to_hw = byteen_start | (byteen_start << 4);
+	ret = set_registers(tp, index, type | byte_en_to_hw, 4, data);
+	if (ret < 0)
+		return ret;
+
+	index += 4;
+	data += 4;
+	size -= 4;
+
+	if (size) {
+		size -= 4;
+
+		while (size) {
+			txsize = min(size, burst_size);
+
+			ret = set_registers(tp, index,
+					    type | BYTE_EN_DWORD,
+					    txsize, data);
+			if (ret < 0)
+				return ret;
+
+			index += txsize;
+			data += txsize;
+			size -= txsize;
+		}
+
+		byte_en_to_hw = byteen_end | (byteen_end >> 4);
+		ret = set_registers(tp, index, type | byte_en_to_hw, 4, data);
+		if (ret < 0)
+			return ret;
+	}
+
+	return ret;
+}
+
+int pla_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data)
+{
+	return generic_ocp_read(tp, index, size, data, MCU_TYPE_PLA);
+}
+
+int pla_ocp_write(struct r8152 *tp, u16 index, u16 byteen, u16 size, void *data)
+{
+	return generic_ocp_write(tp, index, byteen, size, data, MCU_TYPE_PLA);
+}
+
+int usb_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data)
+{
+	return generic_ocp_read(tp, index, size, data, MCU_TYPE_USB);
+}
+
+int usb_ocp_write(struct r8152 *tp, u16 index, u16 byteen, u16 size, void *data)
+{
+	return generic_ocp_write(tp, index, byteen, size, data, MCU_TYPE_USB);
+}
+
+u32 ocp_read_dword(struct r8152 *tp, u16 type, u16 index)
+{
+	__le32 data;
+
+	generic_ocp_read(tp, index, sizeof(data), &data, type);
+
+	return __le32_to_cpu(data);
+}
+
+void ocp_write_dword(struct r8152 *tp, u16 type, u16 index, u32 data)
+{
+	__le32 tmp = __cpu_to_le32(data);
+
+	generic_ocp_write(tp, index, BYTE_EN_DWORD, sizeof(tmp), &tmp, type);
+}
+
+u16 ocp_read_word(struct r8152 *tp, u16 type, u16 index)
+{
+	u32 data;
+	__le32 tmp;
+	u8 shift = index & 2;
+
+	index &= ~3;
+
+	generic_ocp_read(tp, index, sizeof(tmp), &tmp, type);
+
+	data = __le32_to_cpu(tmp);
+	data >>= (shift * 8);
+	data &= 0xffff;
+
+	return data;
+}
+
+void ocp_write_word(struct r8152 *tp, u16 type, u16 index, u32 data)
+{
+	u32 mask = 0xffff;
+	__le32 tmp;
+	u16 byen = BYTE_EN_WORD;
+	u8 shift = index & 2;
+
+	data &= mask;
+
+	if (index & 2) {
+		byen <<= shift;
+		mask <<= (shift * 8);
+		data <<= (shift * 8);
+		index &= ~3;
+	}
+
+	tmp = __cpu_to_le32(data);
+
+	generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type);
+}
+
+u8 ocp_read_byte(struct r8152 *tp, u16 type, u16 index)
+{
+	u32 data;
+	__le32 tmp;
+	u8 shift = index & 3;
+
+	index &= ~3;
+
+	generic_ocp_read(tp, index, sizeof(tmp), &tmp, type);
+
+	data = __le32_to_cpu(tmp);
+	data >>= (shift * 8);
+	data &= 0xff;
+
+	return data;
+}
+
+void ocp_write_byte(struct r8152 *tp, u16 type, u16 index, u32 data)
+{
+	u32 mask = 0xff;
+	__le32 tmp;
+	u16 byen = BYTE_EN_BYTE;
+	u8 shift = index & 3;
+
+	data &= mask;
+
+	if (index & 3) {
+		byen <<= shift;
+		mask <<= (shift * 8);
+		data <<= (shift * 8);
+		index &= ~3;
+	}
+
+	tmp = __cpu_to_le32(data);
+
+	generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type);
+}
+
+u16 ocp_reg_read(struct r8152 *tp, u16 addr)
+{
+	u16 ocp_base, ocp_index;
+
+	ocp_base = addr & 0xf000;
+	if (ocp_base != tp->ocp_base) {
+		ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base);
+		tp->ocp_base = ocp_base;
+	}
+
+	ocp_index = (addr & 0x0fff) | 0xb000;
+	return ocp_read_word(tp, MCU_TYPE_PLA, ocp_index);
+}
+
+void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data)
+{
+	u16 ocp_base, ocp_index;
+
+	ocp_base = addr & 0xf000;
+	if (ocp_base != tp->ocp_base) {
+		ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base);
+		tp->ocp_base = ocp_base;
+	}
+
+	ocp_index = (addr & 0x0fff) | 0xb000;
+	ocp_write_word(tp, MCU_TYPE_PLA, ocp_index, data);
+}
+
+static void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value)
+{
+	ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value);
+}
+
+static int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)
+{
+	return ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2);
+}
+
+void sram_write(struct r8152 *tp, u16 addr, u16 data)
+{
+	ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
+	ocp_reg_write(tp, OCP_SRAM_DATA, data);
+}
+
+static void r8152b_reset_packet_filter(struct r8152 *tp)
+{
+	u32 ocp_data;
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_FMC);
+	ocp_data &= ~FMC_FCR_MCU_EN;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_FMC, ocp_data);
+	ocp_data |= FMC_FCR_MCU_EN;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_FMC, ocp_data);
+}
+
+static void rtl8152_wait_fifo_empty(struct r8152 *tp)
+{
+	int i;
+	u32 ocp_data;
+
+	for (i = 0; i < FIFO_EMPTY_TIMEOUT; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if ((ocp_data & FIFO_EMPTY) == FIFO_EMPTY)
+			break;
+
+		mdelay(1);
+	}
+
+	if (i == FIFO_EMPTY_TIMEOUT)
+		debug("Timeout waiting for FIFO empty\n");
+
+	for (i = 0; i < FIFO_EMPTY_TIMEOUT; i++) {
+		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0) & TCR0_TX_EMPTY)
+			break;
+		mdelay(1);
+	}
+
+	if (i == FIFO_EMPTY_TIMEOUT)
+		debug("Timeout waiting for TX empty\n");
+}
+
+static void rtl8152_nic_reset(struct r8152 *tp)
+{
+	int i;
+
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, PLA_CR_RST);
+
+	for (i = 0; i < NIC_RESET_TIMEOUT; i++) {
+		if (!(ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR) & PLA_CR_RST))
+			break;
+
+		mdelay(1);
+	}
+
+	if (i == NIC_RESET_TIMEOUT)
+		debug("Timeout waiting for NIC reset\n");
+}
+
+static u8 rtl8152_get_speed(struct r8152 *tp)
+{
+	return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS);
+}
+
+static void rtl_set_eee_plus(struct r8152 *tp)
+{
+	u32 ocp_data;
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR);
+	ocp_data &= ~EEEP_CR_EEEP_TX;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data);
+}
+
+static void rxdy_gated_en(struct r8152 *tp, bool enable)
+{
+	u32 ocp_data;
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
+	if (enable)
+		ocp_data |= RXDY_GATED_EN;
+	else
+		ocp_data &= ~RXDY_GATED_EN;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
+}
+
+static void rtl8152_set_rx_mode(struct r8152 *tp)
+{
+	u32 ocp_data;
+	__le32 tmp[2];
+
+	tmp[0] = 0xffffffff;
+	tmp[1] = 0xffffffff;
+
+	pla_ocp_write(tp, PLA_MAR, BYTE_EN_DWORD, sizeof(tmp), tmp);
+
+	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);
+}
+
+static int rtl_enable(struct r8152 *tp)
+{
+	u32 ocp_data;
+
+	r8152b_reset_packet_filter(tp);
+
+	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR);
+	ocp_data |= PLA_CR_RE | PLA_CR_TE;
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, ocp_data);
+
+	rxdy_gated_en(tp, false);
+
+	rtl8152_set_rx_mode(tp);
+
+	return 0;
+}
+
+static int rtl8152_enable(struct r8152 *tp)
+{
+	rtl_set_eee_plus(tp);
+
+	return rtl_enable(tp);
+}
+
+static void r8153_set_rx_early_timeout(struct r8152 *tp)
+{
+	u32 ocp_data = tp->coalesce / 8;
+
+	ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_TIMEOUT, ocp_data);
+}
+
+static void r8153_set_rx_early_size(struct r8152 *tp)
+{
+	u32 ocp_data = (RTL8152_AGG_BUF_SZ - RTL8153_RMS) / 4;
+
+	ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE, ocp_data);
+}
+
+static int rtl8153_enable(struct r8152 *tp)
+{
+	rtl_set_eee_plus(tp);
+	r8153_set_rx_early_timeout(tp);
+	r8153_set_rx_early_size(tp);
+
+	return rtl_enable(tp);
+}
+
+static void rtl_disable(struct r8152 *tp)
+{
+	u32 ocp_data;
+
+	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);
+
+	rxdy_gated_en(tp, true);
+
+	rtl8152_wait_fifo_empty(tp);
+	rtl8152_nic_reset(tp);
+}
+
+static void r8152_power_cut_en(struct r8152 *tp, bool enable)
+{
+	u32 ocp_data;
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CTRL);
+	if (enable)
+		ocp_data |= POWER_CUT;
+	else
+		ocp_data &= ~POWER_CUT;
+	ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CTRL, ocp_data);
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS);
+	ocp_data &= ~RESUME_INDICATE;
+	ocp_write_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS, ocp_data);
+}
+
+static void rtl_rx_vlan_en(struct r8152 *tp, bool enable)
+{
+	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);
+}
+
+static void r8153_u1u2en(struct r8152 *tp, bool enable)
+{
+	u8 u1u2[8];
+
+	if (enable)
+		memset(u1u2, 0xff, sizeof(u1u2));
+	else
+		memset(u1u2, 0x00, sizeof(u1u2));
+
+	usb_ocp_write(tp, USB_TOLERANCE, BYTE_EN_SIX_BYTES, sizeof(u1u2), u1u2);
+}
+
+static void r8153_u2p3en(struct r8152 *tp, bool enable)
+{
+	u32 ocp_data;
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL);
+	if (enable && tp->version != RTL_VER_03 && tp->version != RTL_VER_04)
+		ocp_data |= U2P3_ENABLE;
+	else
+		ocp_data &= ~U2P3_ENABLE;
+	ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data);
+}
+
+static void r8153_power_cut_en(struct r8152 *tp, bool enable)
+{
+	u32 ocp_data;
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_POWER_CUT);
+	if (enable)
+		ocp_data |= PWR_EN | PHASE2_EN;
+	else
+		ocp_data &= ~(PWR_EN | PHASE2_EN);
+	ocp_write_word(tp, MCU_TYPE_USB, USB_POWER_CUT, 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);
+}
+
+static int r8152_read_mac(struct r8152 *tp, unsigned char *macaddr)
+{
+	int ret;
+	unsigned char enetaddr[8] = {0};
+
+	ret = pla_ocp_read(tp, PLA_IDR, 8, enetaddr);
+	if (ret < 0)
+		return ret;
+
+	memcpy(macaddr, enetaddr, ETH_ALEN);
+	return 0;
+}
+
+static void r8152b_disable_aldps(struct r8152 *tp)
+{
+	ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA | DIS_SDSAVE);
+	mdelay(20);
+}
+
+static void r8152b_enable_aldps(struct r8152 *tp)
+{
+	ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPWRSAVE | ENPDNPS |
+		LINKENA | DIS_SDSAVE);
+}
+
+static void rtl8152_disable(struct r8152 *tp)
+{
+	r8152b_disable_aldps(tp);
+	rtl_disable(tp);
+	r8152b_enable_aldps(tp);
+}
+
+static void r8152b_hw_phy_cfg(struct r8152 *tp)
+{
+	u16 data;
+
+	data = r8152_mdio_read(tp, MII_BMCR);
+	if (data & BMCR_PDOWN) {
+		data &= ~BMCR_PDOWN;
+		r8152_mdio_write(tp, MII_BMCR, data);
+	}
+
+	r8152b_firmware(tp);
+}
+
+static void rtl8152_reinit_ll(struct r8152 *tp)
+{
+	u32 ocp_data;
+	int i;
+
+	for (i = 0; i < REINT_LL_TIMEOUT; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+
+		mdelay(1);
+	}
+
+	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);
+
+	for (i = 0; i < REINT_LL_TIMEOUT; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+
+		mdelay(1);
+	}
+
+	if (i == REINT_LL_TIMEOUT)
+		debug("Timeout waiting for reinit link list\n");
+}
+
+static void r8152b_exit_oob(struct r8152 *tp)
+{
+	u32 ocp_data;
+
+	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);
+
+	rxdy_gated_en(tp, true);
+	r8152b_hw_phy_cfg(tp);
+
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, 0x00);
+
+	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);
+
+	rtl8152_reinit_ll(tp);
+	rtl8152_nic_reset(tp);
+
+	/* rx share fifo credit full threshold */
+	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL);
+
+	if (tp->udev->speed == USB_SPEED_FULL ||
+	    tp->udev->speed == USB_SPEED_LOW) {
+		/* rx share fifo credit near full threshold */
+		ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1,
+				RXFIFO_THR2_FULL);
+		ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2,
+				RXFIFO_THR3_FULL);
+	} else {
+		/* rx share fifo credit near full threshold */
+		ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1,
+				RXFIFO_THR2_HIGH);
+		ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2,
+				RXFIFO_THR3_HIGH);
+	}
+
+	/* TX share fifo free credit full threshold */
+	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL);
+
+	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);
+	ocp_write_dword(tp, MCU_TYPE_USB, USB_TX_DMA,
+			TEST_MODE_DISABLE | TX_SIZE_ADJUST1);
+
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0);
+	ocp_data |= TCR0_AUTO_FIFO;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR0, ocp_data);
+}
+
+static void r8152b_enter_oob(struct r8152 *tp)
+{
+	u32 ocp_data;
+
+	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_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_OOB);
+	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_OOB);
+	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_OOB);
+
+	rtl_disable(tp);
+
+	rtl8152_reinit_ll(tp);
+
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
+
+	rtl_rx_vlan_en(tp, false);
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PAL_BDC_CR);
+	ocp_data |= ALDPS_PROXY_MODE;
+	ocp_write_word(tp, MCU_TYPE_PLA, PAL_BDC_CR, ocp_data);
+
+	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+	ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
+
+	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);
+}
+
+static void r8153_hw_phy_cfg(struct r8152 *tp)
+{
+	u32 ocp_data;
+	u16 data;
+
+	if (tp->version == RTL_VER_03 || tp->version == RTL_VER_04 ||
+	    tp->version == RTL_VER_05)
+		ocp_reg_write(tp, OCP_ADC_CFG, CKADSEL_L | ADC_EN | EN_EMI_L);
+
+	data = r8152_mdio_read(tp, MII_BMCR);
+	if (data & BMCR_PDOWN) {
+		data &= ~BMCR_PDOWN;
+		r8152_mdio_write(tp, MII_BMCR, data);
+	}
+
+	r8153_firmware(tp);
+
+	if (tp->version == RTL_VER_03) {
+		data = ocp_reg_read(tp, OCP_EEE_CFG);
+		data &= ~CTAP_SHORT_EN;
+		ocp_reg_write(tp, OCP_EEE_CFG, data);
+	}
+
+	data = ocp_reg_read(tp, OCP_POWER_CFG);
+	data |= EEE_CLKDIV_EN;
+	ocp_reg_write(tp, OCP_POWER_CFG, data);
+
+	data = ocp_reg_read(tp, OCP_DOWN_SPEED);
+	data |= EN_10M_BGOFF;
+	ocp_reg_write(tp, OCP_DOWN_SPEED, data);
+	data = ocp_reg_read(tp, OCP_POWER_CFG);
+	data |= EN_10M_PLLOFF;
+	ocp_reg_write(tp, OCP_POWER_CFG, data);
+	sram_write(tp, SRAM_IMPEDANCE, 0x0b13);
+
+	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);
+
+	/* Enable LPF corner auto tune */
+	sram_write(tp, SRAM_LPF_CFG, 0xf70f);
+
+	/* Adjust 10M Amplitude */
+	sram_write(tp, SRAM_10M_AMP1, 0x00af);
+	sram_write(tp, SRAM_10M_AMP2, 0x0208);
+}
+
+static void r8153_first_init(struct r8152 *tp)
+{
+	u32 ocp_data;
+
+	rxdy_gated_en(tp, true);
+
+	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);
+
+	r8153_hw_phy_cfg(tp);
+
+	rtl8152_nic_reset(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);
+
+	rtl8152_reinit_ll(tp);
+
+	rtl_rx_vlan_en(tp, false);
+
+	ocp_data = RTL8153_RMS;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data);
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO);
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0);
+	ocp_data |= TCR0_AUTO_FIFO;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR0, ocp_data);
+
+	rtl8152_nic_reset(tp);
+
+	/* rx share fifo credit full threshold */
+	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL);
+	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);
+	/* TX share fifo free credit full threshold */
+	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL2);
+
+	/* 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);
+}
+
+static void r8153_enter_oob(struct r8152 *tp)
+{
+	u32 ocp_data;
+
+	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);
+
+	rtl8152_reinit_ll(tp);
+
+	ocp_data = RTL8153_RMS;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data);
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
+	ocp_data &= ~TEREDO_WAKE_MASK;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
+
+	rtl_rx_vlan_en(tp, false);
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PAL_BDC_CR);
+	ocp_data |= ALDPS_PROXY_MODE;
+	ocp_write_word(tp, MCU_TYPE_PLA, PAL_BDC_CR, ocp_data);
+
+	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+	ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
+
+	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);
+}
+
+static void r8153_disable_aldps(struct r8152 *tp)
+{
+	u16 data;
+
+	data = ocp_reg_read(tp, OCP_POWER_CFG);
+	data &= ~EN_ALDPS;
+	ocp_reg_write(tp, OCP_POWER_CFG, data);
+	mdelay(20);
+}
+
+
+static void rtl8153_disable(struct r8152 *tp)
+{
+	r8153_disable_aldps(tp);
+	rtl_disable(tp);
+}
+
+static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
+{
+	u16 bmcr, anar, gbcr;
+
+	anar = r8152_mdio_read(tp, MII_ADVERTISE);
+	anar &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
+		  ADVERTISE_100HALF | ADVERTISE_100FULL);
+	if (tp->supports_gmii) {
+		gbcr = r8152_mdio_read(tp, MII_CTRL1000);
+		gbcr &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+	} else {
+		gbcr = 0;
+	}
+
+	if (autoneg == AUTONEG_DISABLE) {
+		if (speed == SPEED_10) {
+			bmcr = 0;
+			anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
+		} else if (speed == SPEED_100) {
+			bmcr = BMCR_SPEED100;
+			anar |= ADVERTISE_100HALF | ADVERTISE_100FULL;
+		} else if (speed == SPEED_1000 && tp->supports_gmii) {
+			bmcr = BMCR_SPEED1000;
+			gbcr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
+		} else {
+			return -EINVAL;
+		}
+
+		if (duplex == DUPLEX_FULL)
+			bmcr |= BMCR_FULLDPLX;
+	} else {
+		if (speed == SPEED_10) {
+			if (duplex == DUPLEX_FULL)
+				anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
+			else
+				anar |= ADVERTISE_10HALF;
+		} else if (speed == SPEED_100) {
+			if (duplex == DUPLEX_FULL) {
+				anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
+				anar |= ADVERTISE_100HALF | ADVERTISE_100FULL;
+			} else {
+				anar |= ADVERTISE_10HALF;
+				anar |= ADVERTISE_100HALF;
+			}
+		} else if (speed == SPEED_1000 && tp->supports_gmii) {
+			if (duplex == DUPLEX_FULL) {
+				anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
+				anar |= ADVERTISE_100HALF | ADVERTISE_100FULL;
+				gbcr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
+			} else {
+				anar |= ADVERTISE_10HALF;
+				anar |= ADVERTISE_100HALF;
+				gbcr |= ADVERTISE_1000HALF;
+			}
+		} else {
+			return -EINVAL;
+		}
+
+		bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
+	}
+
+	if (tp->supports_gmii)
+		r8152_mdio_write(tp, MII_CTRL1000, gbcr);
+
+	r8152_mdio_write(tp, MII_ADVERTISE, anar);
+	r8152_mdio_write(tp, MII_BMCR, bmcr);
+
+	return 0;
+}
+
+static void rtl8152_up(struct r8152 *tp)
+{
+	r8152b_disable_aldps(tp);
+	r8152b_exit_oob(tp);
+	r8152b_enable_aldps(tp);
+}
+
+static void rtl8152_down(struct r8152 *tp)
+{
+	r8152_power_cut_en(tp, false);
+	r8152b_disable_aldps(tp);
+	r8152b_enter_oob(tp);
+	r8152b_enable_aldps(tp);
+}
+
+static void rtl8153_up(struct r8152 *tp)
+{
+	r8153_u1u2en(tp, false);
+	r8153_disable_aldps(tp);
+	r8153_first_init(tp);
+	r8153_u2p3en(tp, false);
+}
+
+static void rtl8153_down(struct r8152 *tp)
+{
+	r8153_u1u2en(tp, false);
+	r8153_u2p3en(tp, false);
+	r8153_power_cut_en(tp, false);
+	r8153_disable_aldps(tp);
+	r8153_enter_oob(tp);
+}
+
+static void r8152b_get_version(struct r8152 *tp)
+{
+	u32 ocp_data;
+	u16 version;
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR1);
+	version = (u16)(ocp_data & VERSION_MASK);
+
+	switch (version) {
+	case 0x4c00:
+		tp->version = RTL_VER_01;
+		break;
+	case 0x4c10:
+		tp->version = RTL_VER_02;
+		break;
+	case 0x5c00:
+		tp->version = RTL_VER_03;
+		tp->supports_gmii = 1;
+		break;
+	case 0x5c10:
+		tp->version = RTL_VER_04;
+		tp->supports_gmii = 1;
+		break;
+	case 0x5c20:
+		tp->version = RTL_VER_05;
+		tp->supports_gmii = 1;
+		break;
+	case 0x5c30:
+		tp->version = RTL_VER_06;
+		tp->supports_gmii = 1;
+		break;
+	case 0x4800:
+		tp->version = RTL_VER_07;
+		break;
+	default:
+		printf("Unknown version 0x%04x\n", version);
+		break;
+	}
+}
+
+static void r8152b_enable_fc(struct r8152 *tp)
+{
+	u16 anar;
+	anar = r8152_mdio_read(tp, MII_ADVERTISE);
+	anar |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+	r8152_mdio_write(tp, MII_ADVERTISE, anar);
+}
+
+static void rtl_tally_reset(struct r8152 *tp)
+{
+	u32 ocp_data;
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY);
+	ocp_data |= TALLY_RESET;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY, ocp_data);
+}
+
+static void r8152b_init(struct r8152 *tp)
+{
+	u32 ocp_data;
+
+	r8152b_disable_aldps(tp);
+
+	if (tp->version == RTL_VER_01) {
+		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE);
+		ocp_data &= ~LED_MODE_MASK;
+		ocp_write_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data);
+	}
+
+	r8152_power_cut_en(tp, false);
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR);
+	ocp_data |= TX_10M_IDLE_EN | PFM_PWM_SWITCH;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data);
+	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL);
+	ocp_data &= ~MCU_CLK_RATIO_MASK;
+	ocp_data |= MCU_CLK_RATIO | D3_CLK_GATED_EN;
+	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, ocp_data);
+	ocp_data = GPHY_STS_MSK | SPEED_DOWN_MSK |
+		   SPDWN_RXDV_MSK | SPDWN_LINKCHG_MSK;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_GPHY_INTR_IMR, ocp_data);
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_TIMER);
+	ocp_data |= BIT(15);
+	ocp_write_word(tp, MCU_TYPE_USB, USB_USB_TIMER, ocp_data);
+	ocp_write_word(tp, MCU_TYPE_USB, 0xcbfc, 0x03e8);
+	ocp_data &= ~BIT(15);
+	ocp_write_word(tp, MCU_TYPE_USB, USB_USB_TIMER, ocp_data);
+
+	r8152b_enable_fc(tp);
+	rtl_tally_reset(tp);
+
+	/* enable 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);
+}
+
+static void r8153_init(struct r8152 *tp)
+{
+	u32 ocp_data;
+	int i;
+
+	r8153_disable_aldps(tp);
+	r8153_u1u2en(tp, false);
+
+	for (i = 0; i < 500; i++) {
+		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
+		    AUTOLOAD_DONE)
+			break;
+		mdelay(20);
+	}
+
+	for (i = 0; i < 500; i++) {
+		ocp_data = ocp_reg_read(tp, OCP_PHY_STATUS) & PHY_STAT_MASK;
+		if (ocp_data == PHY_STAT_LAN_ON || ocp_data == PHY_STAT_PWRDN)
+			break;
+		mdelay(20);
+	}
+
+	r8153_u2p3en(tp, false);
+
+	if (tp->version == RTL_VER_04) {
+		ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_SSPHYLINK2);
+		ocp_data &= ~pwd_dn_scale_mask;
+		ocp_data |= pwd_dn_scale(96);
+		ocp_write_word(tp, MCU_TYPE_USB, USB_SSPHYLINK2, ocp_data);
+
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_USB2PHY);
+		ocp_data |= USB2PHY_L1 | USB2PHY_SUSPEND;
+		ocp_write_byte(tp, MCU_TYPE_USB, USB_USB2PHY, ocp_data);
+	} else if (tp->version == RTL_VER_05) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_DMY_REG0);
+		ocp_data &= ~ECM_ALDPS;
+		ocp_write_byte(tp, MCU_TYPE_PLA, PLA_DMY_REG0, ocp_data);
+
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1);
+		if (ocp_read_word(tp, MCU_TYPE_USB, USB_BURST_SIZE) == 0)
+			ocp_data &= ~DYNAMIC_BURST;
+		else
+			ocp_data |= DYNAMIC_BURST;
+		ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1, ocp_data);
+	} else if (tp->version == RTL_VER_06) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1);
+		if (ocp_read_word(tp, MCU_TYPE_USB, USB_BURST_SIZE) == 0)
+			ocp_data &= ~DYNAMIC_BURST;
+		else
+			ocp_data |= DYNAMIC_BURST;
+		ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1, ocp_data);
+	}
+
+	ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY2);
+	ocp_data |= EP4_FULL_FC;
+	ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY2, ocp_data);
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL);
+	ocp_data &= ~TIMER11_EN;
+	ocp_write_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL, ocp_data);
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE);
+	ocp_data &= ~LED_MODE_MASK;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data);
+
+	ocp_data = FIFO_EMPTY_1FB | ROK_EXIT_LPM;
+	if (tp->version == RTL_VER_04 && tp->udev->speed != USB_SPEED_SUPER)
+		ocp_data |= LPM_TIMER_500MS;
+	else
+		ocp_data |= LPM_TIMER_500US;
+	ocp_write_byte(tp, MCU_TYPE_USB, USB_LPM_CTRL, ocp_data);
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_AFE_CTRL2);
+	ocp_data &= ~SEN_VAL_MASK;
+	ocp_data |= SEN_VAL_NORMAL | SEL_RXIDLE;
+	ocp_write_word(tp, MCU_TYPE_USB, USB_AFE_CTRL2, ocp_data);
+
+	ocp_write_word(tp, MCU_TYPE_USB, USB_CONNECT_TIMER, 0x0001);
+
+	r8153_power_cut_en(tp, false);
+
+	r8152b_enable_fc(tp);
+	rtl_tally_reset(tp);
+}
+
+static void rtl8152_unload(struct r8152 *tp)
+{
+	if (tp->version != RTL_VER_01)
+		r8152_power_cut_en(tp, true);
+}
+
+static void rtl8153_unload(struct r8152 *tp)
+{
+	r8153_power_cut_en(tp, false);
+}
+
+static int rtl_ops_init(struct r8152 *tp)
+{
+	struct rtl_ops *ops = &tp->rtl_ops;
+	int ret;
+
+	switch (tp->version) {
+	case RTL_VER_01:
+	case RTL_VER_02:
+	case RTL_VER_07:
+		ops->init		= r8152b_init;
+		ops->enable		= rtl8152_enable;
+		ops->disable		= rtl8152_disable;
+		ops->up			= rtl8152_up;
+		ops->down		= rtl8152_down;
+		ops->unload		= rtl8152_unload;
+		break;
+
+	case RTL_VER_03:
+	case RTL_VER_04:
+	case RTL_VER_05:
+	case RTL_VER_06:
+		ops->init		= r8153_init;
+		ops->enable		= rtl8153_enable;
+		ops->disable		= rtl8153_disable;
+		ops->up			= rtl8153_up;
+		ops->down		= rtl8153_down;
+		ops->unload		= rtl8153_unload;
+		break;
+
+	default:
+		ret = -ENODEV;
+		printf("Unknown Device\n");
+		break;
+	}
+
+	return ret;
+}
+
+static int r8152_init(struct eth_device *eth, bd_t *bd)
+{
+	struct ueth_data *dev = (struct ueth_data *)eth->priv;
+	struct r8152 *tp = (struct r8152 *)dev->dev_priv;
+
+	u8 speed;
+	int timeout = 0;
+	int link_detected;
+
+	debug("** %s()\n", __func__);
+
+	do {
+		speed = rtl8152_get_speed(tp);
+
+		link_detected = speed & LINK_STATUS;
+		if (!link_detected) {
+			if (timeout == 0)
+				printf("Waiting for Ethernet connection... ");
+			mdelay(TIMEOUT_RESOLUTION);
+			timeout += TIMEOUT_RESOLUTION;
+		}
+	} while (!link_detected && timeout < PHY_CONNECT_TIMEOUT);
+	if (link_detected) {
+		tp->rtl_ops.enable(tp);
+
+		if (timeout != 0)
+			printf("done.\n");
+	} else {
+		printf("unable to connect.\n");
+	}
+
+	return 0;
+}
+
+static int r8152_send(struct eth_device *eth, void *packet, int length)
+{
+	struct ueth_data *dev = (struct ueth_data *)eth->priv;
+
+	u32 opts1, opts2 = 0;
+
+	int err;
+
+	int actual_len;
+	unsigned char msg[PKTSIZE + sizeof(struct tx_desc)];
+	struct tx_desc *tx_desc = (struct tx_desc *)msg;
+
+	debug("** %s(), len %d\n", __func__, length);
+
+	opts1 = length | TX_FS | TX_LS;
+
+	tx_desc->opts2 = cpu_to_le32(opts2);
+	tx_desc->opts1 = cpu_to_le32(opts1);
+
+	memcpy(msg + sizeof(struct tx_desc), (void *)packet, length);
+
+	err = usb_bulk_msg(dev->pusb_dev,
+				usb_sndbulkpipe(dev->pusb_dev, dev->ep_out),
+				(void *)msg,
+				length + sizeof(struct tx_desc),
+				&actual_len,
+				USB_BULK_SEND_TIMEOUT);
+	debug("Tx: len = %zu, actual = %u, err = %d\n",
+	      length + sizeof(struct tx_desc), actual_len, err);
+
+	return err;
+}
+
+static int r8152_recv(struct eth_device *eth)
+{
+	struct ueth_data *dev = (struct ueth_data *)eth->priv;
+
+	static unsigned char  recv_buf[RTL8152_AGG_BUF_SZ];
+	unsigned char *pkt_ptr;
+	int err;
+	int actual_len;
+	u16 packet_len;
+
+	u32 bytes_process = 0;
+	struct rx_desc *rx_desc;
+
+	debug("** %s()\n", __func__);
+
+	err = usb_bulk_msg(dev->pusb_dev,
+				usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in),
+				(void *)recv_buf,
+				RTL8152_AGG_BUF_SZ,
+				&actual_len,
+				USB_BULK_RECV_TIMEOUT);
+	debug("Rx: len = %u, actual = %u, err = %d\n", RTL8152_AGG_BUF_SZ,
+	      actual_len, err);
+	if (err != 0) {
+		debug("Rx: failed to receive\n");
+		return -1;
+	}
+	if (actual_len > RTL8152_AGG_BUF_SZ) {
+		debug("Rx: received too many bytes %d\n", actual_len);
+		return -1;
+	}
+
+	while (bytes_process < actual_len) {
+		rx_desc = (struct rx_desc *)(recv_buf + bytes_process);
+		pkt_ptr = recv_buf + sizeof(struct rx_desc) + bytes_process;
+
+		packet_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
+		packet_len -= CRC_SIZE;
+
+		net_process_received_packet(pkt_ptr, packet_len);
+
+		bytes_process +=
+			(packet_len + sizeof(struct rx_desc) + CRC_SIZE);
+
+		if (bytes_process % 8)
+			bytes_process = bytes_process + 8 - (bytes_process % 8);
+	}
+
+	return 0;
+}
+
+static void r8152_halt(struct eth_device *eth)
+{
+	struct ueth_data *dev = (struct ueth_data *)eth->priv;
+	struct r8152 *tp = (struct r8152 *)dev->dev_priv;
+
+	debug("** %s()\n", __func__);
+
+	tp->rtl_ops.disable(tp);
+}
+
+static int r8152_write_hwaddr(struct eth_device *eth)
+{
+	struct ueth_data *dev = (struct ueth_data *)eth->priv;
+	struct r8152 *tp = (struct r8152 *)dev->dev_priv;
+
+	unsigned char enetaddr[8] = {0};
+
+	memcpy(enetaddr, eth->enetaddr, ETH_ALEN);
+
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
+	pla_ocp_write(tp, PLA_IDR, BYTE_EN_SIX_BYTES, 8, enetaddr);
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
+
+	debug("MAC %pM\n", eth->enetaddr);
+	return 0;
+}
+
+void r8152_eth_before_probe(void)
+{
+	curr_eth_dev = 0;
+}
+
+/* Probe to see if a new device is actually an realtek device */
+int r8152_eth_probe(struct usb_device *dev, unsigned int ifnum,
+		      struct ueth_data *ss)
+{
+	struct usb_interface *iface;
+	struct usb_interface_descriptor *iface_desc;
+	int ep_in_found = 0, ep_out_found = 0;
+	int i;
+
+	struct r8152 *tp;
+
+	/* let's examine the device now */
+	iface = &dev->config.if_desc[ifnum];
+	iface_desc = &dev->config.if_desc[ifnum].desc;
+
+	for (i = 0; ARRAY_SIZE(r8152_dongles); i++) {
+		if (dev->descriptor.idVendor == r8152_dongles[i].vendor &&
+		    dev->descriptor.idProduct == r8152_dongles[i].product)
+			/* Found a supported dongle */
+			break;
+	}
+
+	if (r8152_dongles[i].vendor == 0)
+		return 0;
+
+	memset(ss, 0, sizeof(struct ueth_data));
+
+	/* At this point, we know we've got a live one */
+	debug("\n\nUSB Ethernet device detected: %#04x:%#04x\n",
+	      dev->descriptor.idVendor, dev->descriptor.idProduct);
+
+	/* Initialize the ueth_data structure with some useful info */
+	ss->ifnum = ifnum;
+	ss->pusb_dev = dev;
+	ss->subclass = iface_desc->bInterfaceSubClass;
+	ss->protocol = iface_desc->bInterfaceProtocol;
+
+	/* alloc driver private */
+	ss->dev_priv = calloc(1, sizeof(struct r8152));
+
+	if (!ss->dev_priv)
+		return 0;
+
+	/*
+	 * We are expecting a minimum of 3 endpoints - in, out (bulk), and
+	 * int. We will ignore any others.
+	 */
+	for (i = 0; i < iface_desc->bNumEndpoints; i++) {
+		/* is it an BULK endpoint? */
+		if ((iface->ep_desc[i].bmAttributes &
+		     USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
+			u8 ep_addr = iface->ep_desc[i].bEndpointAddress;
+			if ((ep_addr & USB_DIR_IN) && !ep_in_found) {
+				ss->ep_in = ep_addr &
+					USB_ENDPOINT_NUMBER_MASK;
+				ep_in_found = 1;
+			} else {
+				if (!ep_out_found) {
+					ss->ep_out = ep_addr &
+						USB_ENDPOINT_NUMBER_MASK;
+					ep_out_found = 1;
+				}
+			}
+		}
+
+		/* is it an interrupt endpoint? */
+		if ((iface->ep_desc[i].bmAttributes &
+		    USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
+			ss->ep_int = iface->ep_desc[i].bEndpointAddress &
+				USB_ENDPOINT_NUMBER_MASK;
+			ss->irqinterval = iface->ep_desc[i].bInterval;
+		}
+	}
+
+	debug("Endpoints In %d Out %d Int %d\n",
+	      ss->ep_in, ss->ep_out, ss->ep_int);
+
+	/* Do some basic sanity checks, and bail if we find a problem */
+	if (usb_set_interface(dev, iface_desc->bInterfaceNumber, 0) ||
+	    !ss->ep_in || !ss->ep_out || !ss->ep_int) {
+		debug("Problems with device\n");
+		return 0;
+	}
+
+	dev->privptr = (void *)ss;
+
+	tp = ss->dev_priv;
+	tp->udev = dev;
+	tp->intf = iface;
+
+	r8152b_get_version(tp);
+
+	if (rtl_ops_init(tp))
+		return 0;
+
+	tp->rtl_ops.init(tp);
+	tp->rtl_ops.up(tp);
+
+	rtl8152_set_speed(tp, AUTONEG_ENABLE,
+			  tp->supports_gmii ? SPEED_1000 : SPEED_100,
+			  DUPLEX_FULL);
+
+	return 1;
+}
+
+int r8152_eth_get_info(struct usb_device *dev, struct ueth_data *ss,
+				struct eth_device *eth)
+{
+	if (!eth) {
+		debug("%s: missing parameter.\n", __func__);
+		return 0;
+	}
+
+	sprintf(eth->name, "%s#%d", R8152_BASE_NAME, curr_eth_dev++);
+	eth->init = r8152_init;
+	eth->send = r8152_send;
+	eth->recv = r8152_recv;
+	eth->halt = r8152_halt;
+	eth->write_hwaddr = r8152_write_hwaddr;
+	eth->priv = ss;
+
+	/* Get the MAC address */
+	if (r8152_read_mac(ss->dev_priv, eth->enetaddr) < 0)
+		return 0;
+
+	debug("MAC %pM\n", eth->enetaddr);
+	return 1;
+}
diff --git a/drivers/usb/eth/r8152.h b/drivers/usb/eth/r8152.h
new file mode 100644
index 0000000..aeb51e6
--- /dev/null
+++ b/drivers/usb/eth/r8152.h
@@ -0,0 +1,623 @@
+/*
+ * Copyright (c) 2015 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * SPDX-License-Identifier:     GPL-2.0
+ *
+  */
+
+#ifndef _RTL8152_ETH_H
+#define _RTL8152_ETH_H
+
+#define R8152_BASE_NAME		"r8152"
+
+#define PLA_IDR			0xc000
+#define PLA_RCR			0xc010
+#define PLA_RMS			0xc016
+#define PLA_RXFIFO_CTRL0	0xc0a0
+#define PLA_RXFIFO_CTRL1	0xc0a4
+#define PLA_RXFIFO_CTRL2	0xc0a8
+#define PLA_DMY_REG0		0xc0b0
+#define PLA_FMC			0xc0b4
+#define PLA_CFG_WOL		0xc0b6
+#define PLA_TEREDO_CFG		0xc0bc
+#define PLA_MAR			0xcd00
+#define PLA_BACKUP		0xd000
+#define PAL_BDC_CR		0xd1a0
+#define PLA_TEREDO_TIMER	0xd2cc
+#define PLA_REALWOW_TIMER	0xd2e8
+#define PLA_LEDSEL		0xdd90
+#define PLA_LED_FEATURE		0xdd92
+#define PLA_PHYAR		0xde00
+#define PLA_BOOT_CTRL		0xe004
+#define PLA_GPHY_INTR_IMR	0xe022
+#define PLA_EEE_CR		0xe040
+#define PLA_EEEP_CR		0xe080
+#define PLA_MAC_PWR_CTRL	0xe0c0
+#define PLA_MAC_PWR_CTRL2	0xe0ca
+#define PLA_MAC_PWR_CTRL3	0xe0cc
+#define PLA_MAC_PWR_CTRL4	0xe0ce
+#define PLA_WDT6_CTRL		0xe428
+#define PLA_TCR0		0xe610
+#define PLA_TCR1		0xe612
+#define PLA_MTPS		0xe615
+#define PLA_TXFIFO_CTRL		0xe618
+#define PLA_RSTTALLY		0xe800
+#define PLA_CR			0xe813
+#define PLA_CRWECR		0xe81c
+#define PLA_CONFIG12		0xe81e	/* CONFIG1, CONFIG2 */
+#define PLA_CONFIG34		0xe820	/* CONFIG3, CONFIG4 */
+#define PLA_CONFIG5		0xe822
+#define PLA_PHY_PWR		0xe84c
+#define PLA_OOB_CTRL		0xe84f
+#define PLA_CPCR		0xe854
+#define PLA_MISC_0		0xe858
+#define PLA_MISC_1		0xe85a
+#define PLA_OCP_GPHY_BASE	0xe86c
+#define PLA_TALLYCNT		0xe890
+#define PLA_SFF_STS_7		0xe8de
+#define PLA_PHYSTATUS		0xe908
+#define PLA_BP_BA		0xfc26
+#define PLA_BP_0		0xfc28
+#define PLA_BP_1		0xfc2a
+#define PLA_BP_2		0xfc2c
+#define PLA_BP_3		0xfc2e
+#define PLA_BP_4		0xfc30
+#define PLA_BP_5		0xfc32
+#define PLA_BP_6		0xfc34
+#define PLA_BP_7		0xfc36
+#define PLA_BP_EN		0xfc38
+
+#define USB_USB2PHY		0xb41e
+#define USB_SSPHYLINK2		0xb428
+#define USB_U2P3_CTRL		0xb460
+#define USB_CSR_DUMMY1		0xb464
+#define USB_CSR_DUMMY2		0xb466
+#define USB_DEV_STAT		0xb808
+#define USB_CONNECT_TIMER	0xcbf8
+#define USB_BURST_SIZE		0xcfc0
+#define USB_USB_CTRL		0xd406
+#define USB_PHY_CTRL		0xd408
+#define USB_TX_AGG		0xd40a
+#define USB_RX_BUF_TH		0xd40c
+#define USB_USB_TIMER		0xd428
+#define USB_RX_EARLY_TIMEOUT	0xd42c
+#define USB_RX_EARLY_SIZE	0xd42e
+#define USB_PM_CTRL_STATUS	0xd432
+#define USB_TX_DMA		0xd434
+#define USB_TOLERANCE		0xd490
+#define USB_LPM_CTRL		0xd41a
+#define USB_UPS_CTRL		0xd800
+#define USB_MISC_0		0xd81a
+#define USB_POWER_CUT		0xd80a
+#define USB_AFE_CTRL2		0xd824
+#define USB_WDT11_CTRL		0xe43c
+#define USB_BP_BA		0xfc26
+#define USB_BP_0		0xfc28
+#define USB_BP_1		0xfc2a
+#define USB_BP_2		0xfc2c
+#define USB_BP_3		0xfc2e
+#define USB_BP_4		0xfc30
+#define USB_BP_5		0xfc32
+#define USB_BP_6		0xfc34
+#define USB_BP_7		0xfc36
+#define USB_BP_EN		0xfc38
+
+/* OCP Registers */
+#define OCP_ALDPS_CONFIG	0x2010
+#define OCP_EEE_CONFIG1		0x2080
+#define OCP_EEE_CONFIG2		0x2092
+#define OCP_EEE_CONFIG3		0x2094
+#define OCP_BASE_MII		0xa400
+#define OCP_EEE_AR		0xa41a
+#define OCP_EEE_DATA		0xa41c
+#define OCP_PHY_STATUS		0xa420
+#define OCP_POWER_CFG		0xa430
+#define OCP_EEE_CFG		0xa432
+#define OCP_SRAM_ADDR		0xa436
+#define OCP_SRAM_DATA		0xa438
+#define OCP_DOWN_SPEED		0xa442
+#define OCP_EEE_ABLE		0xa5c4
+#define OCP_EEE_ADV		0xa5d0
+#define OCP_EEE_LPABLE		0xa5d2
+#define OCP_PHY_STATE		0xa708		/* nway state for 8153 */
+#define OCP_ADC_CFG		0xbc06
+
+/* SRAM Register */
+#define SRAM_LPF_CFG		0x8012
+#define SRAM_10M_AMP1		0x8080
+#define SRAM_10M_AMP2		0x8082
+#define SRAM_IMPEDANCE		0x8084
+
+/* PLA_RCR */
+#define RCR_AAP			0x00000001
+#define RCR_APM			0x00000002
+#define RCR_AM			0x00000004
+#define RCR_AB			0x00000008
+#define RCR_ACPT_ALL		(RCR_AAP | RCR_APM | RCR_AM | RCR_AB)
+
+/* PLA_RXFIFO_CTRL0 */
+#define RXFIFO_THR1_NORMAL	0x00080002
+#define RXFIFO_THR1_OOB		0x01800003
+
+/* PLA_RXFIFO_CTRL1 */
+#define RXFIFO_THR2_FULL	0x00000060
+#define RXFIFO_THR2_HIGH	0x00000038
+#define RXFIFO_THR2_OOB		0x0000004a
+#define RXFIFO_THR2_NORMAL	0x00a0
+
+/* PLA_RXFIFO_CTRL2 */
+#define RXFIFO_THR3_FULL	0x00000078
+#define RXFIFO_THR3_HIGH	0x00000048
+#define RXFIFO_THR3_OOB		0x0000005a
+#define RXFIFO_THR3_NORMAL	0x0110
+
+/* PLA_TXFIFO_CTRL */
+#define TXFIFO_THR_NORMAL	0x00400008
+#define TXFIFO_THR_NORMAL2	0x01000008
+
+/* PLA_DMY_REG0 */
+#define ECM_ALDPS		0x0002
+
+/* PLA_FMC */
+#define FMC_FCR_MCU_EN		0x0001
+
+/* PLA_EEEP_CR */
+#define EEEP_CR_EEEP_TX		0x0002
+
+/* PLA_WDT6_CTRL */
+#define WDT6_SET_MODE		0x0010
+
+/* PLA_TCR0 */
+#define TCR0_TX_EMPTY		0x0800
+#define TCR0_AUTO_FIFO		0x0080
+
+/* PLA_TCR1 */
+#define VERSION_MASK		0x7cf0
+
+/* PLA_MTPS */
+#define MTPS_JUMBO		(12 * 1024 / 64)
+#define MTPS_DEFAULT		(6 * 1024 / 64)
+
+/* PLA_RSTTALLY */
+#define TALLY_RESET		0x0001
+
+/* PLA_CR */
+#define PLA_CR_RST		0x10
+#define PLA_CR_RE		0x08
+#define PLA_CR_TE		0x04
+
+/* PLA_CRWECR */
+#define CRWECR_NORAML		0x00
+#define CRWECR_CONFIG		0xc0
+
+/* PLA_OOB_CTRL */
+#define NOW_IS_OOB		0x80
+#define TXFIFO_EMPTY		0x20
+#define RXFIFO_EMPTY		0x10
+#define LINK_LIST_READY		0x02
+#define DIS_MCU_CLROOB		0x01
+#define FIFO_EMPTY		(TXFIFO_EMPTY | RXFIFO_EMPTY)
+
+/* PLA_MISC_1 */
+#define RXDY_GATED_EN		0x0008
+
+/* PLA_SFF_STS_7 */
+#define RE_INIT_LL		0x8000
+#define MCU_BORW_EN		0x4000
+
+/* PLA_CPCR */
+#define CPCR_RX_VLAN		0x0040
+
+/* PLA_CFG_WOL */
+#define MAGIC_EN		0x0001
+
+/* PLA_TEREDO_CFG */
+#define TEREDO_SEL		0x8000
+#define TEREDO_WAKE_MASK	0x7f00
+#define TEREDO_RS_EVENT_MASK	0x00fe
+#define OOB_TEREDO_EN		0x0001
+
+/* PAL_BDC_CR */
+#define ALDPS_PROXY_MODE	0x0001
+
+/* PLA_CONFIG34 */
+#define LINK_ON_WAKE_EN		0x0010
+#define LINK_OFF_WAKE_EN	0x0008
+
+/* PLA_CONFIG5 */
+#define BWF_EN			0x0040
+#define MWF_EN			0x0020
+#define UWF_EN			0x0010
+#define LAN_WAKE_EN		0x0002
+
+/* PLA_LED_FEATURE */
+#define LED_MODE_MASK		0x0700
+
+/* PLA_PHY_PWR */
+#define TX_10M_IDLE_EN		0x0080
+#define PFM_PWM_SWITCH		0x0040
+
+/* PLA_MAC_PWR_CTRL */
+#define D3_CLK_GATED_EN		0x00004000
+#define MCU_CLK_RATIO		0x07010f07
+#define MCU_CLK_RATIO_MASK	0x0f0f0f0f
+#define ALDPS_SPDWN_RATIO	0x0f87
+
+/* PLA_MAC_PWR_CTRL2 */
+#define EEE_SPDWN_RATIO		0x8007
+
+/* PLA_MAC_PWR_CTRL3 */
+#define PKT_AVAIL_SPDWN_EN	0x0100
+#define SUSPEND_SPDWN_EN	0x0004
+#define U1U2_SPDWN_EN		0x0002
+#define L1_SPDWN_EN		0x0001
+
+/* PLA_MAC_PWR_CTRL4 */
+#define PWRSAVE_SPDWN_EN	0x1000
+#define RXDV_SPDWN_EN		0x0800
+#define TX10MIDLE_EN		0x0100
+#define TP100_SPDWN_EN		0x0020
+#define TP500_SPDWN_EN		0x0010
+#define TP1000_SPDWN_EN		0x0008
+#define EEE_SPDWN_EN		0x0001
+
+/* PLA_GPHY_INTR_IMR */
+#define GPHY_STS_MSK		0x0001
+#define SPEED_DOWN_MSK		0x0002
+#define SPDWN_RXDV_MSK		0x0004
+#define SPDWN_LINKCHG_MSK	0x0008
+
+/* PLA_PHYAR */
+#define PHYAR_FLAG		0x80000000
+
+/* PLA_EEE_CR */
+#define EEE_RX_EN		0x0001
+#define EEE_TX_EN		0x0002
+
+/* PLA_BOOT_CTRL */
+#define AUTOLOAD_DONE		0x0002
+
+/* USB_USB2PHY */
+#define USB2PHY_SUSPEND		0x0001
+#define USB2PHY_L1		0x0002
+
+/* USB_SSPHYLINK2 */
+#define pwd_dn_scale_mask	0x3ffe
+#define pwd_dn_scale(x)		((x) << 1)
+
+/* USB_CSR_DUMMY1 */
+#define DYNAMIC_BURST		0x0001
+
+/* USB_CSR_DUMMY2 */
+#define EP4_FULL_FC		0x0001
+
+/* USB_DEV_STAT */
+#define STAT_SPEED_MASK		0x0006
+#define STAT_SPEED_HIGH		0x0000
+#define STAT_SPEED_FULL		0x0002
+
+/* USB_TX_AGG */
+#define TX_AGG_MAX_THRESHOLD	0x03
+
+/* USB_RX_BUF_TH */
+#define RX_THR_SUPPER		0x0c350180
+#define RX_THR_HIGH		0x7a120180
+#define RX_THR_SLOW		0xffff0180
+
+/* USB_TX_DMA */
+#define TEST_MODE_DISABLE	0x00000001
+#define TX_SIZE_ADJUST1		0x00000100
+
+/* USB_UPS_CTRL */
+#define POWER_CUT		0x0100
+
+/* USB_PM_CTRL_STATUS */
+#define RESUME_INDICATE		0x0001
+
+/* USB_USB_CTRL */
+#define RX_AGG_DISABLE		0x0010
+#define RX_ZERO_EN		0x0080
+
+/* USB_U2P3_CTRL */
+#define U2P3_ENABLE		0x0001
+
+/* USB_POWER_CUT */
+#define PWR_EN			0x0001
+#define PHASE2_EN		0x0008
+
+/* USB_MISC_0 */
+#define PCUT_STATUS		0x0001
+
+/* USB_RX_EARLY_TIMEOUT */
+#define COALESCE_SUPER		 85000U
+#define COALESCE_HIGH		250000U
+#define COALESCE_SLOW		524280U
+
+/* USB_WDT11_CTRL */
+#define TIMER11_EN		0x0001
+
+/* USB_LPM_CTRL */
+/* bit 4 ~ 5: fifo empty boundary */
+#define FIFO_EMPTY_1FB		0x30	/* 0x1fb * 64 = 32448 bytes */
+/* bit 2 ~ 3: LMP timer */
+#define LPM_TIMER_MASK		0x0c
+#define LPM_TIMER_500MS		0x04	/* 500 ms */
+#define LPM_TIMER_500US		0x0c	/* 500 us */
+#define ROK_EXIT_LPM		0x02
+
+/* USB_AFE_CTRL2 */
+#define SEN_VAL_MASK		0xf800
+#define SEN_VAL_NORMAL		0xa000
+#define SEL_RXIDLE		0x0100
+
+/* OCP_ALDPS_CONFIG */
+#define ENPWRSAVE		0x8000
+#define ENPDNPS			0x0200
+#define LINKENA			0x0100
+#define DIS_SDSAVE		0x0010
+
+/* OCP_PHY_STATUS */
+#define PHY_STAT_MASK		0x0007
+#define PHY_STAT_LAN_ON		3
+#define PHY_STAT_PWRDN		5
+
+/* OCP_POWER_CFG */
+#define EEE_CLKDIV_EN		0x8000
+#define EN_ALDPS		0x0004
+#define EN_10M_PLLOFF		0x0001
+
+/* OCP_EEE_CONFIG1 */
+#define RG_TXLPI_MSK_HFDUP	0x8000
+#define RG_MATCLR_EN		0x4000
+#define EEE_10_CAP		0x2000
+#define EEE_NWAY_EN		0x1000
+#define TX_QUIET_EN		0x0200
+#define RX_QUIET_EN		0x0100
+#define sd_rise_time_mask	0x0070
+#define sd_rise_time(x)		(min((x), 7) << 4)	/* bit 4 ~ 6 */
+#define RG_RXLPI_MSK_HFDUP	0x0008
+#define SDFALLTIME		0x0007	/* bit 0 ~ 2 */
+
+/* OCP_EEE_CONFIG2 */
+#define RG_LPIHYS_NUM		0x7000	/* bit 12 ~ 15 */
+#define RG_DACQUIET_EN		0x0400
+#define RG_LDVQUIET_EN		0x0200
+#define RG_CKRSEL		0x0020
+#define RG_EEEPRG_EN		0x0010
+
+/* OCP_EEE_CONFIG3 */
+#define fast_snr_mask		0xff80
+#define fast_snr(x)		(min((x), 0x1ff) << 7)	/* bit 7 ~ 15 */
+#define RG_LFS_SEL		0x0060	/* bit 6 ~ 5 */
+#define MSK_PH			0x0006	/* bit 0 ~ 3 */
+
+/* OCP_EEE_AR */
+/* bit[15:14] function */
+#define FUN_ADDR		0x0000
+#define FUN_DATA		0x4000
+/* bit[4:0] device addr */
+
+/* OCP_EEE_CFG */
+#define CTAP_SHORT_EN		0x0040
+#define EEE10_EN		0x0010
+
+/* OCP_DOWN_SPEED */
+#define EN_10M_BGOFF		0x0080
+
+/* OCP_PHY_STATE */
+#define TXDIS_STATE		0x01
+#define ABD_STATE		0x02
+
+/* OCP_ADC_CFG */
+#define CKADSEL_L		0x0100
+#define ADC_EN			0x0080
+#define EN_EMI_L		0x0040
+
+/* SRAM_LPF_CFG */
+#define LPF_AUTO_TUNE		0x8000
+
+/* SRAM_10M_AMP1 */
+#define GDAC_IB_UPALL		0x0008
+
+/* SRAM_10M_AMP2 */
+#define AMP_DN			0x0200
+
+/* SRAM_IMPEDANCE */
+#define RX_DRIVING_MASK		0x6000
+
+#define RTL8152_MAX_TX		4
+#define RTL8152_MAX_RX		10
+#define INTBUFSIZE		2
+#define CRC_SIZE		4
+#define TX_ALIGN		4
+#define RX_ALIGN		8
+
+#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 RTL8152_ETH_FRAME_LEN	1514
+#define RTL8152_AGG_BUF_SZ	2048
+
+#define RTL8152_RMS		(RTL8152_ETH_FRAME_LEN + CRC_SIZE)
+#define RTL8153_RMS		(RTL8152_ETH_FRAME_LEN + CRC_SIZE)
+#define RTL8152_TX_TIMEOUT	(5 * HZ)
+
+#define MCU_TYPE_PLA			0x0100
+#define MCU_TYPE_USB			0x0000
+
+/* The forced speed, 10Mb, 100Mb, gigabit. */
+#define SPEED_10                10
+#define SPEED_100               100
+#define SPEED_1000              1000
+
+#define SPEED_UNKNOWN           -1
+
+/* Duplex, half or full. */
+#define DUPLEX_HALF             0x00
+#define DUPLEX_FULL             0x01
+#define DUPLEX_UNKNOWN          0xff
+
+/* Enable or disable autonegotiation. */
+#define AUTONEG_DISABLE         0x00
+#define AUTONEG_ENABLE          0x01
+
+/* Generic MII registers. */
+#define MII_BMCR                0x00    /* Basic mode control register */
+#define MII_BMSR                0x01    /* Basic mode status register  */
+#define MII_PHYSID1             0x02    /* PHYS ID 1                   */
+#define MII_PHYSID2             0x03    /* PHYS ID 2                   */
+#define MII_ADVERTISE           0x04    /* Advertisement control reg   */
+#define MII_LPA                 0x05    /* Link partner ability reg    */
+#define MII_EXPANSION           0x06    /* Expansion register          */
+#define MII_CTRL1000            0x09    /* 1000BASE-T control          */
+#define MII_STAT1000            0x0a    /* 1000BASE-T status           */
+#define MII_MMD_CTRL            0x0d    /* MMD Access Control Register */
+#define MII_MMD_DATA            0x0e    /* MMD Access Data Register */
+#define MII_ESTATUS             0x0f    /* Extended Status             */
+#define MII_DCOUNTER            0x12    /* Disconnect counter          */
+#define MII_FCSCOUNTER          0x13    /* False carrier counter       */
+#define MII_NWAYTEST            0x14    /* N-way auto-neg test reg     */
+#define MII_RERRCOUNTER         0x15    /* Receive error counter       */
+#define MII_SREVISION           0x16    /* Silicon revision            */
+#define MII_RESV1               0x17    /* Reserved...                 */
+#define MII_LBRERROR            0x18    /* Lpback, rx, bypass error    */
+#define MII_PHYADDR             0x19    /* PHY address                 */
+#define MII_RESV2               0x1a    /* Reserved...                 */
+#define MII_TPISTATUS           0x1b    /* TPI status for 10mbps       */
+#define MII_NCONFIG             0x1c    /* Network interface config    */
+
+#define TIMEOUT_RESOLUTION	50
+#define PHY_CONNECT_TIMEOUT     5000
+#define USB_BULK_SEND_TIMEOUT   5000
+#define USB_BULK_RECV_TIMEOUT   5000
+
+#define NIC_RESET_TIMEOUT	1000
+#define FIFO_EMPTY_TIMEOUT	2000
+#define REINT_LL_TIMEOUT	2000
+
+struct rx_desc {
+	__le32 opts1;
+#define RD_CRC				BIT(15)
+#define RX_LEN_MASK			0x7fff
+
+	__le32 opts2;
+#define RD_UDP_CS			BIT(23)
+#define RD_TCP_CS			BIT(22)
+#define RD_IPV6_CS			BIT(20)
+#define RD_IPV4_CS			BIT(19)
+
+	__le32 opts3;
+#define IPF				BIT(23) /* IP checksum fail */
+#define UDPF				BIT(22) /* UDP checksum fail */
+#define TCPF				BIT(21) /* TCP checksum fail */
+#define RX_VLAN_TAG			BIT(16)
+
+	__le32 opts4;
+	__le32 opts5;
+	__le32 opts6;
+};
+
+struct tx_desc {
+	__le32 opts1;
+#define TX_FS			BIT(31) /* First segment of a packet */
+#define TX_LS			BIT(30) /* Final segment of a packet */
+#define LGSEND			BIT(29)
+#define GTSENDV4		BIT(28)
+#define GTSENDV6		BIT(27)
+#define GTTCPHO_SHIFT		18
+#define GTTCPHO_MAX		0x7fU
+#define TX_LEN_MAX		0x3ffffU
+
+	__le32 opts2;
+#define UDP_CS			BIT(31) /* Calculate UDP/IP checksum */
+#define TCP_CS			BIT(30) /* Calculate TCP/IP checksum */
+#define IPV4_CS			BIT(29) /* Calculate IPv4 checksum */
+#define IPV6_CS			BIT(28) /* Calculate IPv6 checksum */
+#define MSS_SHIFT		17
+#define MSS_MAX			0x7ffU
+#define TCPHO_SHIFT		17
+#define TCPHO_MAX		0x7ffU
+#define TX_VLAN_TAG		BIT(16)
+};
+
+enum rtl_version {
+	RTL_VER_UNKNOWN = 0,
+	RTL_VER_01,
+	RTL_VER_02,
+	RTL_VER_03,
+	RTL_VER_04,
+	RTL_VER_05,
+	RTL_VER_06,
+	RTL_VER_07,
+	RTL_VER_MAX
+};
+
+enum rtl_register_content {
+	_1000bps	= 0x10,
+	_100bps		= 0x08,
+	_10bps		= 0x04,
+	LINK_STATUS	= 0x02,
+	FULL_DUP	= 0x01,
+};
+
+struct r8152 {
+	struct usb_device *udev;
+	struct usb_interface *intf;
+	bool supports_gmii;
+
+	struct rtl_ops {
+		void (*init)(struct r8152 *);
+		int (*enable)(struct r8152 *);
+		void (*disable)(struct r8152 *);
+		void (*up)(struct r8152 *);
+		void (*down)(struct r8152 *);
+		void (*unload)(struct r8152 *);
+	} rtl_ops;
+
+	u32 coalesce;
+	u16 ocp_base;
+
+	u8 version;
+};
+
+int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
+		      u16 size, void *data, u16 type);
+int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
+		     void *data, u16 type);
+
+int pla_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data);
+int pla_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
+		  u16 size, void *data);
+
+int usb_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data);
+int usb_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
+		  u16 size, void *data);
+
+u32 ocp_read_dword(struct r8152 *tp, u16 type, u16 index);
+void ocp_write_dword(struct r8152 *tp, u16 type, u16 index, u32 data);
+
+u16 ocp_read_word(struct r8152 *tp, u16 type, u16 index);
+void ocp_write_word(struct r8152 *tp, u16 type, u16 index, u32 data);
+
+u8 ocp_read_byte(struct r8152 *tp, u16 type, u16 index);
+void ocp_write_byte(struct r8152 *tp, u16 type, u16 index, u32 data);
+
+u16 ocp_reg_read(struct r8152 *tp, u16 addr);
+void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data);
+
+void sram_write(struct r8152 *tp, u16 addr, u16 data);
+
+void r8152b_firmware(struct r8152 *tp);
+void r8153_firmware(struct r8152 *tp);
+#endif
diff --git a/drivers/usb/eth/r8152_fw.c b/drivers/usb/eth/r8152_fw.c
new file mode 100644
index 0000000..8dc8cad
--- /dev/null
+++ b/drivers/usb/eth/r8152_fw.c
@@ -0,0 +1,980 @@
+/*
+ * Copyright (c) 2015 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * SPDX-License-Identifier:     GPL-2.0
+ *
+  */
+#include <common.h>
+#include <errno.h>
+#include "r8152.h"
+
+static u8 r8152b_pla_patch_a[] = {
+	0x08, 0xe0, 0x40, 0xe0, 0x78, 0xe0, 0x85, 0xe0,
+	0x5d, 0xe1, 0xa1, 0xe1, 0xa3, 0xe1, 0xab, 0xe1,
+	0x31, 0xc3, 0x60, 0x72, 0xa0, 0x49, 0x10, 0xf0,
+	0xa4, 0x49, 0x0e, 0xf0, 0x2c, 0xc3, 0x62, 0x72,
+	0x26, 0x70, 0x80, 0x49, 0x05, 0xf0, 0x2f, 0x48,
+	0x62, 0x9a, 0x24, 0x70, 0x60, 0x98, 0x24, 0xc3,
+	0x60, 0x99, 0x23, 0xc3, 0x00, 0xbb, 0x2c, 0x75,
+	0xdc, 0x21, 0xbc, 0x25, 0x04, 0x13, 0x0a, 0xf0,
+	0x03, 0x13, 0x08, 0xf0, 0x02, 0x13, 0x06, 0xf0,
+	0x01, 0x13, 0x04, 0xf0, 0x08, 0x13, 0x02, 0xf0,
+	0x03, 0xe0, 0xd4, 0x49, 0x04, 0xf1, 0x14, 0xc2,
+	0x12, 0xc3, 0x00, 0xbb, 0x12, 0xc3, 0x60, 0x75,
+	0xd0, 0x49, 0x05, 0xf1, 0x50, 0x48, 0x60, 0x9d,
+	0x09, 0xc6, 0x00, 0xbe, 0xd0, 0x48, 0x60, 0x9d,
+	0xf3, 0xe7, 0xc2, 0xc0, 0x38, 0xd2, 0xc6, 0xd2,
+	0x84, 0x17, 0xa2, 0x13, 0x0c, 0x17, 0xbc, 0xc0,
+	0xa2, 0xd1, 0x33, 0xc5, 0xa0, 0x74, 0xc0, 0x49,
+	0x1f, 0xf0, 0x30, 0xc5, 0xa0, 0x73, 0x00, 0x13,
+	0x04, 0xf1, 0xa2, 0x73, 0x00, 0x13, 0x14, 0xf0,
+	0x28, 0xc5, 0xa0, 0x74, 0xc8, 0x49, 0x1b, 0xf1,
+	0x26, 0xc5, 0xa0, 0x76, 0xa2, 0x74, 0x01, 0x06,
+	0x20, 0x37, 0xa0, 0x9e, 0xa2, 0x9c, 0x1e, 0xc5,
+	0xa2, 0x73, 0x23, 0x40, 0x10, 0xf8, 0x04, 0xf3,
+	0xa0, 0x73, 0x33, 0x40, 0x0c, 0xf8, 0x15, 0xc5,
+	0xa0, 0x74, 0x41, 0x48, 0xa0, 0x9c, 0x14, 0xc5,
+	0xa0, 0x76, 0x62, 0x48, 0xe0, 0x48, 0xa0, 0x9e,
+	0x10, 0xc6, 0x00, 0xbe, 0x0a, 0xc5, 0xa0, 0x74,
+	0x48, 0x48, 0xa0, 0x9c, 0x0b, 0xc5, 0x20, 0x1e,
+	0xa0, 0x9e, 0xe5, 0x48, 0xa0, 0x9e, 0xf0, 0xe7,
+	0xbc, 0xc0, 0xc8, 0xd2, 0xcc, 0xd2, 0x28, 0xe4,
+	0x22, 0x02, 0xf0, 0xc0, 0x0b, 0xc0, 0x00, 0x71,
+	0x0a, 0xc0, 0x00, 0x72, 0xa0, 0x49, 0x04, 0xf0,
+	0xa4, 0x49, 0x02, 0xf0, 0x93, 0x48, 0x04, 0xc0,
+	0x00, 0xb8, 0x00, 0xe4, 0xc2, 0xc0, 0x8c, 0x09,
+	0x14, 0xc2, 0x40, 0x73, 0xba, 0x48, 0x40, 0x9b,
+	0x11, 0xc2, 0x40, 0x73, 0xb0, 0x49, 0x17, 0xf0,
+	0xbf, 0x49, 0x03, 0xf1, 0x09, 0xc5, 0x00, 0xbd,
+	0xb1, 0x49, 0x11, 0xf0, 0xb1, 0x48, 0x40, 0x9b,
+	0x02, 0xc2, 0x00, 0xba, 0x82, 0x18, 0x00, 0xa0,
+	0x1e, 0xfc, 0xbc, 0xc0, 0xf0, 0xc0, 0xde, 0xe8,
+	0x00, 0x80, 0x00, 0x60, 0x2c, 0x75, 0xd4, 0x49,
+	0x12, 0xf1, 0x29, 0xe0, 0xf8, 0xc2, 0x46, 0x71,
+	0xf7, 0xc2, 0x40, 0x73, 0xbe, 0x49, 0x03, 0xf1,
+	0xf5, 0xc7, 0x02, 0xe0, 0xf2, 0xc7, 0x4f, 0x30,
+	0x26, 0x62, 0xa1, 0x49, 0xf0, 0xf1, 0x22, 0x72,
+	0xa0, 0x49, 0xed, 0xf1, 0x25, 0x25, 0x18, 0x1f,
+	0x97, 0x30, 0x91, 0x30, 0x36, 0x9a, 0x2c, 0x75,
+	0x32, 0xc3, 0x60, 0x73, 0xb1, 0x49, 0x0d, 0xf1,
+	0xdc, 0x21, 0xbc, 0x25, 0x27, 0xc6, 0xc0, 0x77,
+	0x04, 0x13, 0x18, 0xf0, 0x03, 0x13, 0x19, 0xf0,
+	0x02, 0x13, 0x1a, 0xf0, 0x01, 0x13, 0x1b, 0xf0,
+	0xd4, 0x49, 0x03, 0xf1, 0x1c, 0xc5, 0x00, 0xbd,
+	0xcd, 0xc6, 0xc6, 0x67, 0x2e, 0x75, 0xd7, 0x22,
+	0xdd, 0x26, 0x05, 0x15, 0x1a, 0xf0, 0x14, 0xc6,
+	0x00, 0xbe, 0x13, 0xc5, 0x00, 0xbd, 0x12, 0xc5,
+	0x00, 0xbd, 0xf1, 0x49, 0xfb, 0xf1, 0xef, 0xe7,
+	0xf4, 0x49, 0xfa, 0xf1, 0xec, 0xe7, 0xf3, 0x49,
+	0xf7, 0xf1, 0xe9, 0xe7, 0xf2, 0x49, 0xf4, 0xf1,
+	0xe6, 0xe7, 0xb6, 0xc0, 0x6a, 0x14, 0xac, 0x13,
+	0xd6, 0x13, 0xfa, 0x14, 0xa0, 0xd1, 0x00, 0x00,
+	0xc0, 0x75, 0xd0, 0x49, 0x46, 0xf0, 0x26, 0x72,
+	0xa7, 0x49, 0x43, 0xf0, 0x22, 0x72, 0x25, 0x25,
+	0x20, 0x1f, 0x97, 0x30, 0x91, 0x30, 0x40, 0x73,
+	0xf3, 0xc4, 0x1c, 0x40, 0x04, 0xf0, 0xd7, 0x49,
+	0x05, 0xf1, 0x37, 0xe0, 0x53, 0x48, 0xc0, 0x9d,
+	0x08, 0x02, 0x40, 0x66, 0x64, 0x27, 0x06, 0x16,
+	0x30, 0xf1, 0x46, 0x63, 0x3b, 0x13, 0x2d, 0xf1,
+	0x34, 0x9b, 0x18, 0x1b, 0x93, 0x30, 0x2b, 0xc3,
+	0x10, 0x1c, 0x2b, 0xe8, 0x01, 0x14, 0x25, 0xf1,
+	0x00, 0x1d, 0x26, 0x1a, 0x8a, 0x30, 0x22, 0x73,
+	0xb5, 0x25, 0x0e, 0x0b, 0x00, 0x1c, 0x2c, 0xe8,
+	0x1f, 0xc7, 0x27, 0x40, 0x1a, 0xf1, 0x38, 0xe8,
+	0x32, 0x1f, 0x8f, 0x30, 0x08, 0x1b, 0x24, 0xe8,
+	0x36, 0x72, 0x46, 0x77, 0x00, 0x17, 0x0d, 0xf0,
+	0x13, 0xc3, 0x1f, 0x40, 0x03, 0xf1, 0x00, 0x1f,
+	0x46, 0x9f, 0x44, 0x77, 0x9f, 0x44, 0x5f, 0x44,
+	0x17, 0xe8, 0x0a, 0xc7, 0x27, 0x40, 0x05, 0xf1,
+	0x02, 0xc3, 0x00, 0xbb, 0x50, 0x1a, 0x06, 0x1a,
+	0xff, 0xc7, 0x00, 0xbf, 0xb8, 0xcd, 0xff, 0xff,
+	0x02, 0x0c, 0x54, 0xa5, 0xdc, 0xa5, 0x2f, 0x40,
+	0x05, 0xf1, 0x00, 0x14, 0xfa, 0xf1, 0x01, 0x1c,
+	0x02, 0xe0, 0x00, 0x1c, 0x80, 0xff, 0xb0, 0x49,
+	0x04, 0xf0, 0x01, 0x0b, 0xd3, 0xa1, 0x03, 0xe0,
+	0x02, 0x0b, 0xd3, 0xa5, 0x27, 0x31, 0x20, 0x37,
+	0x02, 0x0b, 0xd3, 0xa5, 0x27, 0x31, 0x20, 0x37,
+	0x00, 0x13, 0xfb, 0xf1, 0x80, 0xff, 0x22, 0x73,
+	0xb5, 0x25, 0x18, 0x1e, 0xde, 0x30, 0xd9, 0x30,
+	0x64, 0x72, 0x11, 0x1e, 0x68, 0x23, 0x16, 0x31,
+	0x80, 0xff, 0xd4, 0x49, 0x28, 0xf0, 0x02, 0xb4,
+	0x2a, 0xc4, 0x00, 0x1d, 0x2e, 0xe8, 0xe0, 0x73,
+	0xb9, 0x21, 0xbd, 0x25, 0x04, 0x13, 0x02, 0xf0,
+	0x1a, 0xe0, 0x22, 0xc4, 0x23, 0xc3, 0x2f, 0xe8,
+	0x23, 0xc3, 0x2d, 0xe8, 0x00, 0x1d, 0x21, 0xe8,
+	0xe2, 0x73, 0xbb, 0x49, 0xfc, 0xf0, 0xe0, 0x73,
+	0xb7, 0x48, 0x03, 0xb4, 0x81, 0x1d, 0x19, 0xe8,
+	0x40, 0x1a, 0x84, 0x1d, 0x16, 0xe8, 0x12, 0xc3,
+	0x1e, 0xe8, 0x03, 0xb0, 0x81, 0x1d, 0x11, 0xe8,
+	0x0e, 0xc3, 0x19, 0xe8, 0x02, 0xb0, 0x06, 0xc7,
+	0x04, 0x1e, 0xe0, 0x9e, 0x02, 0xc6, 0x00, 0xbe,
+	0x22, 0x02, 0x20, 0xe4, 0x04, 0xb8, 0x34, 0xb0,
+	0x00, 0x02, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x0c,
+	0x09, 0xc7, 0xe0, 0x9b, 0xe2, 0x9a, 0xe4, 0x9c,
+	0xe6, 0x8d, 0xe6, 0x76, 0xef, 0x49, 0xfe, 0xf1,
+	0x80, 0xff, 0x08, 0xea, 0x82, 0x1d, 0xf5, 0xef,
+	0x00, 0x1a, 0x88, 0x1d, 0xf2, 0xef, 0xed, 0xc2,
+	0xf0, 0xef, 0x80, 0xff, 0x02, 0xc6, 0x00, 0xbe,
+	0x46, 0x06, 0x08, 0xc2, 0x40, 0x73, 0x3a, 0x48,
+	0x40, 0x9b, 0x06, 0xff, 0x02, 0xc6, 0x00, 0xbe,
+	0x86, 0x17, 0x1e, 0xfc, 0x36, 0xf0, 0x08, 0x1c,
+	0xea, 0x8c, 0xe3, 0x64, 0xc7, 0x49, 0x25, 0xf1,
+	0xe0, 0x75, 0xff, 0x1b, 0xeb, 0x47, 0xff, 0x1b,
+	0x6b, 0x47, 0xe0, 0x9d, 0x15, 0xc3, 0x60, 0x75,
+	0xd8, 0x49, 0x04, 0xf0, 0x81, 0x1d, 0xe2, 0x8d,
+	0x05, 0xe0, 0xe2, 0x63, 0x81, 0x1d, 0xdd, 0x47,
+	0xe2, 0x8b, 0x0b, 0xc3, 0x00, 0x1d, 0x61, 0x8d,
+	0x3c, 0x03, 0x60, 0x75, 0xd8, 0x49, 0x06, 0xf1,
+	0xdf, 0x48, 0x61, 0x95, 0x16, 0xe0, 0x4e, 0xe8,
+	0x12, 0xe8, 0x21, 0xc5, 0xa0, 0x73, 0xb0, 0x49,
+	0x03, 0xf0, 0x31, 0x48, 0xa0, 0x9b, 0x0d, 0xe0,
+	0xc0, 0x49, 0x0b, 0xf1, 0xe2, 0x63, 0x7e, 0x1d,
+	0xdd, 0x46, 0xe2, 0x8b, 0xe0, 0x75, 0x83, 0x1b,
+	0xeb, 0x46, 0xfe, 0x1b, 0x6b, 0x46, 0xe0, 0x9d,
+	0xe4, 0x49, 0x11, 0xf0, 0x10, 0x1d, 0xea, 0x8d,
+	0xe3, 0x64, 0xc6, 0x49, 0x09, 0xf1, 0x07, 0xc5,
+	0xa0, 0x73, 0xb1, 0x48, 0xa0, 0x9b, 0x02, 0xc5,
+	0x00, 0xbd, 0xe6, 0x04, 0xa0, 0xd1, 0x02, 0xc5,
+	0x00, 0xbd, 0xfe, 0x04, 0x02, 0xc5, 0x00, 0xbd,
+	0x30, 0x05, 0x00, 0x00 };
+
+static u16 r8152b_ram_code1[] = {
+	0x9700, 0x7fe0, 0x4c00, 0x4007, 0x4400, 0x4800, 0x7c1f, 0x4c00,
+	0x5310, 0x6000, 0x7c07, 0x6800, 0x673e, 0x0000, 0x0000, 0x571f,
+	0x5ffb, 0xaa05, 0x5b58, 0x7d80, 0x6100, 0x3019, 0x5b64, 0x7d80,
+	0x6080, 0xa6f8, 0xdcdb, 0x0015, 0xb915, 0xb511, 0xd16b, 0x000f,
+	0xb40f, 0xd06b, 0x000d, 0xb206, 0x7c01, 0x5800, 0x7c04, 0x5c00,
+	0x3011, 0x7c01, 0x5801, 0x7c04, 0x5c04, 0x3019, 0x30a5, 0x3127,
+	0x31d5, 0x7fe0, 0x4c60, 0x7c07, 0x6803, 0x7d00, 0x6900, 0x65a0,
+	0x0000, 0x0000, 0xaf03, 0x6015, 0x303e, 0x6017, 0x57e0, 0x580c,
+	0x588c, 0x7fdd, 0x5fa2, 0x4827, 0x7c1f, 0x4c00, 0x7c1f, 0x4c10,
+	0x8400, 0x7c30, 0x6020, 0x48bf, 0x7c1f, 0x4c00, 0x7c1f, 0x4c01,
+	0x7c07, 0x6803, 0xb806, 0x7c08, 0x6800, 0x0000, 0x0000, 0x305c,
+	0x7c08, 0x6808, 0x0000, 0x0000, 0xae06, 0x7c02, 0x5c02, 0x0000,
+	0x0000, 0x3067, 0x8e05, 0x7c02, 0x5c00, 0x0000, 0x0000, 0xad06,
+	0x7c20, 0x5c20, 0x0000, 0x0000, 0x3072, 0x8d05, 0x7c20, 0x5c00,
+	0x0000, 0x0000, 0xa008, 0x7c07, 0x6800, 0xb8db, 0x7c07, 0x6803,
+	0xd9b3, 0x00d7, 0x7fe0, 0x4c80, 0x7c08, 0x6800, 0x0000, 0x0000,
+	0x7c23, 0x5c23, 0x481d, 0x7c1f, 0x4c00, 0x7c1f, 0x4c02, 0x5310,
+	0x81ff, 0x30f5, 0x7fe0, 0x4d00, 0x4832, 0x7c1f, 0x4c00, 0x7c1f,
+	0x4c10, 0x7c08, 0x6000, 0xa49e, 0x7c07, 0x6800, 0xb89b, 0x7c07,
+	0x6803, 0xd9b3, 0x00f9, 0x7fe0, 0x4d20, 0x7e00, 0x6200, 0x3001,
+	0x7fe0, 0x4dc0, 0xd09d, 0x0002, 0xb4fe, 0x7fe0, 0x4d80, 0x7c04,
+	0x6004, 0x7c07, 0x6802, 0x6728, 0x0000, 0x0000, 0x7c08, 0x6000,
+	0x486c, 0x7c1f, 0x4c00, 0x7c1f, 0x4c01, 0x9503, 0x7e00, 0x6200,
+	0x571f, 0x5fbb, 0xaa05, 0x5b58, 0x7d80, 0x6100, 0x30c2, 0x5b64,
+	0x7d80, 0x6080, 0xcdab, 0x0063, 0xcd8d, 0x0061, 0xd96b, 0x005f,
+	0xd0a0, 0x00d7, 0xcba0, 0x0003, 0x80ec, 0x30cf, 0x30dc, 0x7fe0,
+	0x4ce0, 0x4832, 0x7c1f, 0x4c00, 0x7c1f, 0x4c08, 0x7c08, 0x6008,
+	0x8300, 0xb902, 0x30a5, 0x308a, 0x7fe0, 0x4da0, 0x65a8, 0x0000,
+	0x0000, 0x56a0, 0x590c, 0x7ffd, 0x5fa2, 0xae06, 0x7c02, 0x5c02,
+	0x0000, 0x0000, 0x30f0, 0x8e05, 0x7c02, 0x5c00, 0x0000, 0x0000,
+	0xcba4, 0x0004, 0xcd8d, 0x0002, 0x80f1, 0x7fe0, 0x4ca0, 0x7c08,
+	0x6408, 0x0000, 0x0000, 0x7d00, 0x6800, 0xb603, 0x7c10, 0x6010,
+	0x7d1f, 0x551f, 0x5fb3, 0xaa07, 0x7c80, 0x5800, 0x5b58, 0x7d80,
+	0x6100, 0x310f, 0x7c80, 0x5800, 0x5b64, 0x7d80, 0x6080, 0x4827,
+	0x7c1f, 0x4c00, 0x7c1f, 0x4c10, 0x8400, 0x7c10, 0x6000, 0x7fe0,
+	0x4cc0, 0x5fbb, 0x4824, 0x7c1f, 0x4c00, 0x7c1f, 0x4c04, 0x8200,
+	0x7ce0, 0x5400, 0x6728, 0x0000, 0x0000, 0x30cf, 0x3001, 0x7fe0,
+	0x4e00, 0x4007, 0x4400, 0x5310, 0x7c07, 0x6800, 0x673e, 0x0000,
+	0x0000, 0x570f, 0x5fff, 0xaa05, 0x585b, 0x7d80, 0x6100, 0x313b,
+	0x5867, 0x7d80, 0x6080, 0x9403, 0x7e00, 0x6200, 0xcda3, 0x00e7,
+	0xcd85, 0x00e5, 0xd96b, 0x00e3, 0x96e3, 0x7c07, 0x6800, 0x673e,
+	0x0000, 0x0000, 0x7fe0, 0x4e20, 0x96db, 0x8b04, 0x7c08, 0x5008,
+	0xab03, 0x7c08, 0x5000, 0x7c07, 0x6801, 0x677e, 0x0000, 0x0000,
+	0xdb7c, 0x00ec, 0x0000, 0x7fe1, 0x4f40, 0x4837, 0x4418, 0x41c7,
+	0x7fe0, 0x4e40, 0x7c40, 0x5400, 0x7c1f, 0x4c01, 0x7c1f, 0x4c01,
+	0x8fbf, 0xd2a0, 0x004b, 0x9204, 0xa042, 0x3168, 0x3127, 0x7fe1,
+	0x4f60, 0x489c, 0x4628, 0x7fe0, 0x4e60, 0x7e28, 0x4628, 0x7c40,
+	0x5400, 0x7c01, 0x5800, 0x7c04, 0x5c00, 0x41e8, 0x7c1f, 0x4c01,
+	0x7c1f, 0x4c01, 0x8fa5, 0xb241, 0xa02a, 0x3182, 0x7fe0, 0x4ea0,
+	0x7c02, 0x4402, 0x4448, 0x4894, 0x7c1f, 0x4c01, 0x7c1f, 0x4c03,
+	0x4824, 0x7c1f, 0x4c07, 0x41ef, 0x41ff, 0x4891, 0x7c1f, 0x4c07,
+	0x7c1f, 0x4c17, 0x8400, 0x8ef8, 0x41c7, 0x8f8a, 0x92d5, 0xa10f,
+	0xd480, 0x0008, 0xd580, 0x00b8, 0xa202, 0x319d, 0x7c04, 0x4404,
+	0x319d, 0xd484, 0x00f3, 0xd484, 0x00f1, 0x3127, 0x7fe0, 0x4ee0,
+	0x7c40, 0x5400, 0x4488, 0x41cf, 0x3127, 0x7fe0, 0x4ec0, 0x48f3,
+	0x7c1f, 0x4c01, 0x7c1f, 0x4c09, 0x4508, 0x41c7, 0x8fb0, 0xd218,
+	0x00ae, 0xd2a4, 0x009e, 0x31be, 0x7fe0, 0x4e80, 0x4832, 0x7c1f,
+	0x4c01, 0x7c1f, 0x4c11, 0x4428, 0x7c40, 0x5440, 0x7c01, 0x5801,
+	0x7c04, 0x5c04, 0x41e8, 0xa4b3, 0x31d3, 0x7fe0, 0x4f20, 0x7c07,
+	0x6800, 0x673e, 0x0000, 0x0000, 0x570f, 0x5fff, 0xaa04, 0x585b,
+	0x6100, 0x31e4, 0x5867, 0x6080, 0xbcf1, 0x3001 };
+
+static u16 r8152b_pla_patch_a_bp[] = {
+	0xfc26, 0x8000, 0xfc28, 0x170b, 0xfc2a, 0x01e1, 0xfc2c, 0x0989,
+	0xfc2e, 0x1349, 0xfc30, 0x01b7, 0xfc32, 0x061d, 0xe422, 0x0020,
+	0xe420, 0x0018, 0xfc34, 0x1785, 0xfc36, 0x047b };
+
+static u8 r8152b_pla_patch_a2[] = {
+	0x08, 0xe0, 0x1a, 0xe0, 0xf2, 0xe0, 0xfa, 0xe0,
+	0x32, 0xe1, 0x34, 0xe1, 0x36, 0xe1, 0x38, 0xe1,
+	0x2c, 0x75, 0xdc, 0x21, 0xbc, 0x25, 0x04, 0x13,
+	0x0b, 0xf0, 0x03, 0x13, 0x09, 0xf0, 0x02, 0x13,
+	0x07, 0xf0, 0x01, 0x13, 0x05, 0xf0, 0x08, 0x13,
+	0x03, 0xf0, 0x04, 0xc3, 0x00, 0xbb, 0x03, 0xc3,
+	0x00, 0xbb, 0xd2, 0x17, 0xbc, 0x17, 0x14, 0xc2,
+	0x40, 0x73, 0xba, 0x48, 0x40, 0x9b, 0x11, 0xc2,
+	0x40, 0x73, 0xb0, 0x49, 0x17, 0xf0, 0xbf, 0x49,
+	0x03, 0xf1, 0x09, 0xc5, 0x00, 0xbd, 0xb1, 0x49,
+	0x11, 0xf0, 0xb1, 0x48, 0x40, 0x9b, 0x02, 0xc2,
+	0x00, 0xba, 0x4e, 0x19, 0x00, 0xa0, 0x1e, 0xfc,
+	0xbc, 0xc0, 0xf0, 0xc0, 0xde, 0xe8, 0x00, 0x80,
+	0x00, 0x60, 0x2c, 0x75, 0xd4, 0x49, 0x12, 0xf1,
+	0x29, 0xe0, 0xf8, 0xc2, 0x46, 0x71, 0xf7, 0xc2,
+	0x40, 0x73, 0xbe, 0x49, 0x03, 0xf1, 0xf5, 0xc7,
+	0x02, 0xe0, 0xf2, 0xc7, 0x4f, 0x30, 0x26, 0x62,
+	0xa1, 0x49, 0xf0, 0xf1, 0x22, 0x72, 0xa0, 0x49,
+	0xed, 0xf1, 0x25, 0x25, 0x18, 0x1f, 0x97, 0x30,
+	0x91, 0x30, 0x36, 0x9a, 0x2c, 0x75, 0x32, 0xc3,
+	0x60, 0x73, 0xb1, 0x49, 0x0d, 0xf1, 0xdc, 0x21,
+	0xbc, 0x25, 0x27, 0xc6, 0xc0, 0x77, 0x04, 0x13,
+	0x18, 0xf0, 0x03, 0x13, 0x19, 0xf0, 0x02, 0x13,
+	0x1a, 0xf0, 0x01, 0x13, 0x1b, 0xf0, 0xd4, 0x49,
+	0x03, 0xf1, 0x1c, 0xc5, 0x00, 0xbd, 0xcd, 0xc6,
+	0xc6, 0x67, 0x2e, 0x75, 0xd7, 0x22, 0xdd, 0x26,
+	0x05, 0x15, 0x1a, 0xf0, 0x14, 0xc6, 0x00, 0xbe,
+	0x13, 0xc5, 0x00, 0xbd, 0x12, 0xc5, 0x00, 0xbd,
+	0xf1, 0x49, 0xfb, 0xf1, 0xef, 0xe7, 0xf4, 0x49,
+	0xfa, 0xf1, 0xec, 0xe7, 0xf3, 0x49, 0xf7, 0xf1,
+	0xe9, 0xe7, 0xf2, 0x49, 0xf4, 0xf1, 0xe6, 0xe7,
+	0xb6, 0xc0, 0xf6, 0x14, 0x36, 0x14, 0x62, 0x14,
+	0x86, 0x15, 0xa0, 0xd1, 0x00, 0x00, 0xc0, 0x75,
+	0xd0, 0x49, 0x46, 0xf0, 0x26, 0x72, 0xa7, 0x49,
+	0x43, 0xf0, 0x22, 0x72, 0x25, 0x25, 0x20, 0x1f,
+	0x97, 0x30, 0x91, 0x30, 0x40, 0x73, 0xf3, 0xc4,
+	0x1c, 0x40, 0x04, 0xf0, 0xd7, 0x49, 0x05, 0xf1,
+	0x37, 0xe0, 0x53, 0x48, 0xc0, 0x9d, 0x08, 0x02,
+	0x40, 0x66, 0x64, 0x27, 0x06, 0x16, 0x30, 0xf1,
+	0x46, 0x63, 0x3b, 0x13, 0x2d, 0xf1, 0x34, 0x9b,
+	0x18, 0x1b, 0x93, 0x30, 0x2b, 0xc3, 0x10, 0x1c,
+	0x2b, 0xe8, 0x01, 0x14, 0x25, 0xf1, 0x00, 0x1d,
+	0x26, 0x1a, 0x8a, 0x30, 0x22, 0x73, 0xb5, 0x25,
+	0x0e, 0x0b, 0x00, 0x1c, 0x2c, 0xe8, 0x1f, 0xc7,
+	0x27, 0x40, 0x1a, 0xf1, 0x38, 0xe8, 0x32, 0x1f,
+	0x8f, 0x30, 0x08, 0x1b, 0x24, 0xe8, 0x36, 0x72,
+	0x46, 0x77, 0x00, 0x17, 0x0d, 0xf0, 0x13, 0xc3,
+	0x1f, 0x40, 0x03, 0xf1, 0x00, 0x1f, 0x46, 0x9f,
+	0x44, 0x77, 0x9f, 0x44, 0x5f, 0x44, 0x17, 0xe8,
+	0x0a, 0xc7, 0x27, 0x40, 0x05, 0xf1, 0x02, 0xc3,
+	0x00, 0xbb, 0x1c, 0x1b, 0xd2, 0x1a, 0xff, 0xc7,
+	0x00, 0xbf, 0xb8, 0xcd, 0xff, 0xff, 0x02, 0x0c,
+	0x54, 0xa5, 0xdc, 0xa5, 0x2f, 0x40, 0x05, 0xf1,
+	0x00, 0x14, 0xfa, 0xf1, 0x01, 0x1c, 0x02, 0xe0,
+	0x00, 0x1c, 0x80, 0xff, 0xb0, 0x49, 0x04, 0xf0,
+	0x01, 0x0b, 0xd3, 0xa1, 0x03, 0xe0, 0x02, 0x0b,
+	0xd3, 0xa5, 0x27, 0x31, 0x20, 0x37, 0x02, 0x0b,
+	0xd3, 0xa5, 0x27, 0x31, 0x20, 0x37, 0x00, 0x13,
+	0xfb, 0xf1, 0x80, 0xff, 0x22, 0x73, 0xb5, 0x25,
+	0x18, 0x1e, 0xde, 0x30, 0xd9, 0x30, 0x64, 0x72,
+	0x11, 0x1e, 0x68, 0x23, 0x16, 0x31, 0x80, 0xff,
+	0x08, 0xc2, 0x40, 0x73, 0x3a, 0x48, 0x40, 0x9b,
+	0x06, 0xff, 0x02, 0xc6, 0x00, 0xbe, 0x4e, 0x18,
+	0x1e, 0xfc, 0x33, 0xc5, 0xa0, 0x74, 0xc0, 0x49,
+	0x1f, 0xf0, 0x30, 0xc5, 0xa0, 0x73, 0x00, 0x13,
+	0x04, 0xf1, 0xa2, 0x73, 0x00, 0x13, 0x14, 0xf0,
+	0x28, 0xc5, 0xa0, 0x74, 0xc8, 0x49, 0x1b, 0xf1,
+	0x26, 0xc5, 0xa0, 0x76, 0xa2, 0x74, 0x01, 0x06,
+	0x20, 0x37, 0xa0, 0x9e, 0xa2, 0x9c, 0x1e, 0xc5,
+	0xa2, 0x73, 0x23, 0x40, 0x10, 0xf8, 0x04, 0xf3,
+	0xa0, 0x73, 0x33, 0x40, 0x0c, 0xf8, 0x15, 0xc5,
+	0xa0, 0x74, 0x41, 0x48, 0xa0, 0x9c, 0x14, 0xc5,
+	0xa0, 0x76, 0x62, 0x48, 0xe0, 0x48, 0xa0, 0x9e,
+	0x10, 0xc6, 0x00, 0xbe, 0x0a, 0xc5, 0xa0, 0x74,
+	0x48, 0x48, 0xa0, 0x9c, 0x0b, 0xc5, 0x20, 0x1e,
+	0xa0, 0x9e, 0xe5, 0x48, 0xa0, 0x9e, 0xf0, 0xe7,
+	0xbc, 0xc0, 0xc8, 0xd2, 0xcc, 0xd2, 0x28, 0xe4,
+	0x22, 0x02, 0xf0, 0xc0, 0x02, 0xc6, 0x00, 0xbe,
+	0x00, 0x00, 0x02, 0xc6, 0x00, 0xbe, 0x00, 0x00,
+	0x02, 0xc6, 0x00, 0xbe, 0x00, 0x00, 0x02, 0xc6,
+	0x00, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static u16 r8152b_pla_patch_a2_bp[] = {
+	0xfc28, 0x8000, 0xfc28, 0x17a5, 0xfc2a, 0x13ad,
+	0xfc2c, 0x184d, 0xfc2e, 0x01e1 };
+
+static u16 r8153_ram_code_a[] = {
+	0xE86C, 0xA000, 0xB436, 0xB820, 0xB438, 0x0290, 0xB436, 0xA012,
+	0xB438, 0x0000, 0xB436, 0xA014, 0xB438, 0x2c04, 0xB438, 0x2c18,
+	0xB438, 0x2c45, 0xB438, 0x2c45, 0xB438, 0xd502, 0xB438, 0x8301,
+	0xB438, 0x8306, 0xB438, 0xd500, 0xB438, 0x8208, 0xB438, 0xd501,
+	0xB438, 0xe018, 0xB438, 0x0308, 0xB438, 0x60f2, 0xB438, 0x8404,
+	0xB438, 0x607d, 0xB438, 0xc117, 0xB438, 0x2c16, 0xB438, 0xc116,
+	0xB438, 0x2c16, 0xB438, 0x607d, 0xB438, 0xc117, 0xB438, 0xa404,
+	0xB438, 0xd500, 0xB438, 0x0800, 0xB438, 0xd501, 0xB438, 0x62d2,
+	0xB438, 0x615d, 0xB438, 0xc115, 0xB438, 0xa404, 0xB438, 0xc307,
+	0xB438, 0xd502, 0xB438, 0x8301, 0xB438, 0x8306, 0xB438, 0xd500,
+	0xB438, 0x8208, 0xB438, 0x2c42, 0xB438, 0xc114, 0xB438, 0x8404,
+	0xB438, 0xc317, 0xB438, 0xd701, 0xB438, 0x435d, 0xB438, 0xd500,
+	0xB438, 0xa208, 0xB438, 0xd502, 0xB438, 0xa306, 0xB438, 0xa301,
+	0xB438, 0x2c42, 0xB438, 0x8404, 0xB438, 0x613d, 0xB438, 0xc115,
+	0xB438, 0xc307, 0xB438, 0xd502, 0xB438, 0x8301, 0xB438, 0x8306,
+	0xB438, 0xd500, 0xB438, 0x8208, 0xB438, 0x2c42, 0xB438, 0xc114,
+	0xB438, 0xc317, 0xB438, 0xd701, 0xB438, 0x40dd, 0xB438, 0xd500,
+	0xB438, 0xa208, 0xB438, 0xd502, 0xB438, 0xa306, 0xB438, 0xa301,
+	0xB438, 0xd500, 0xB438, 0xd702, 0xB438, 0x0800, 0xB436, 0xA01A,
+	0xB438, 0x0000, 0xB436, 0xA006, 0xB438, 0x0fff, 0xB436, 0xA004,
+	0xB438, 0x0fff, 0xB436, 0xA002, 0xB438, 0x05a3, 0xB436, 0xA000,
+	0xB438, 0x3591, 0xB436, 0xB820, 0xB438, 0x0210 };
+
+static u8 r8153_usb_patch_c[] = {
+	0x08, 0xe0, 0x0a, 0xe0, 0x14, 0xe0, 0x2e, 0xe0,
+	0x37, 0xe0, 0x3e, 0xe0, 0x6d, 0xe0, 0x78, 0xe0,
+	0x02, 0xc5, 0x00, 0xbd, 0x38, 0x3b, 0xdb, 0x49,
+	0x04, 0xf1, 0x06, 0xc3, 0x00, 0xbb, 0x5a, 0x02,
+	0x05, 0xc4, 0x03, 0xc3, 0x00, 0xbb, 0xa4, 0x04,
+	0x7e, 0x02, 0x30, 0xd4, 0x30, 0x18, 0x18, 0xc1,
+	0x0c, 0xe8, 0x17, 0xc6, 0xc7, 0x65, 0xd0, 0x49,
+	0x05, 0xf0, 0x32, 0x48, 0x02, 0xc2, 0x00, 0xba,
+	0x3e, 0x16, 0x02, 0xc2, 0x00, 0xba, 0x48, 0x16,
+	0x02, 0xb4, 0x09, 0xc2, 0x40, 0x99, 0x0e, 0x48,
+	0x42, 0x98, 0x42, 0x70, 0x8e, 0x49, 0xfe, 0xf1,
+	0x02, 0xb0, 0x80, 0xff, 0xc0, 0xd4, 0xe4, 0x40,
+	0x20, 0xd4, 0xb0, 0x49, 0x04, 0xf0, 0x30, 0x18,
+	0x06, 0xc1, 0xef, 0xef, 0xfa, 0xc7, 0x02, 0xc0,
+	0x00, 0xb8, 0xd0, 0x10, 0xe4, 0x4b, 0x07, 0xc3,
+	0x70, 0x61, 0x12, 0x48, 0x70, 0x89, 0x02, 0xc3,
+	0x00, 0xbb, 0x9c, 0x15, 0x20, 0xd4, 0x2b, 0xc5,
+	0xa0, 0x77, 0x00, 0x1c, 0xa0, 0x9c, 0x28, 0xc5,
+	0xa0, 0x64, 0xc0, 0x48, 0xc1, 0x48, 0xc2, 0x48,
+	0xa0, 0x8c, 0xb1, 0x64, 0xc0, 0x48, 0xb1, 0x8c,
+	0x20, 0xc5, 0xa0, 0x64, 0x40, 0x48, 0x41, 0x48,
+	0xc2, 0x48, 0xa0, 0x8c, 0x19, 0xc5, 0xa4, 0x64,
+	0x44, 0x48, 0xa4, 0x8c, 0xb1, 0x64, 0x40, 0x48,
+	0xb1, 0x8c, 0x14, 0xc4, 0x80, 0x73, 0x13, 0xc4,
+	0x82, 0x9b, 0x11, 0x1b, 0x80, 0x9b, 0x0c, 0xc5,
+	0xa0, 0x64, 0x40, 0x48, 0x41, 0x48, 0x42, 0x48,
+	0xa0, 0x8c, 0x05, 0xc5, 0xa0, 0x9f, 0x02, 0xc5,
+	0x00, 0xbd, 0x6c, 0x3a, 0x1e, 0xfc, 0x10, 0xd8,
+	0x86, 0xd4, 0xf8, 0xcb, 0x20, 0xe4, 0x0a, 0xc0,
+	0x16, 0x61, 0x91, 0x48, 0x16, 0x89, 0x07, 0xc0,
+	0x11, 0x19, 0x0c, 0x89, 0x02, 0xc1, 0x00, 0xb9,
+	0x02, 0x06, 0x00, 0xd4, 0x40, 0xb4, 0xfe, 0xc0,
+	0x16, 0x61, 0x91, 0x48, 0x16, 0x89, 0xfb, 0xc0,
+	0x11, 0x19, 0x0c, 0x89, 0x02, 0xc1, 0x00, 0xb9,
+	0xd2, 0x05, 0x00, 0x00 };
+
+static u16 r8153_usb_patch_c_bp[] = {
+	0xfc26, 0xa000, 0xfc28, 0x3b34, 0xfc2a, 0x027c, 0xfc2c, 0x162c,
+	0xfc2e, 0x10ce, 0xfc30, 0x0000, 0xfc32, 0x3a28, 0xfc34, 0x05f8,
+	0xfc36, 0x05c8 };
+
+static u8 r8153_pla_patch_c[] = {
+	0x08, 0xe0, 0xea, 0xe0, 0xf2, 0xe0, 0x04, 0xe1,
+	0x06, 0xe1, 0x08, 0xe1, 0x40, 0xe1, 0xf1, 0xe1,
+	0x14, 0xc2, 0x40, 0x73, 0xba, 0x48, 0x40, 0x9b,
+	0x11, 0xc2, 0x40, 0x73, 0xb0, 0x49, 0x17, 0xf0,
+	0xbf, 0x49, 0x03, 0xf1, 0x09, 0xc5, 0x00, 0xbd,
+	0xb1, 0x49, 0x11, 0xf0, 0xb1, 0x48, 0x40, 0x9b,
+	0x02, 0xc2, 0x00, 0xba, 0xde, 0x18, 0x00, 0xe0,
+	0x1e, 0xfc, 0xbc, 0xc0, 0xf0, 0xc0, 0xde, 0xe8,
+	0x00, 0x80, 0x00, 0x20, 0x2c, 0x75, 0xd4, 0x49,
+	0x12, 0xf1, 0x32, 0xe0, 0xf8, 0xc2, 0x46, 0x71,
+	0xf7, 0xc2, 0x40, 0x73, 0xbe, 0x49, 0x03, 0xf1,
+	0xf5, 0xc7, 0x02, 0xe0, 0xf2, 0xc7, 0x4f, 0x30,
+	0x26, 0x62, 0xa1, 0x49, 0xf0, 0xf1, 0x22, 0x72,
+	0xa0, 0x49, 0xed, 0xf1, 0x25, 0x25, 0x18, 0x1f,
+	0x97, 0x30, 0x91, 0x30, 0x36, 0x9a, 0x2c, 0x75,
+	0x3c, 0xc3, 0x60, 0x73, 0xb1, 0x49, 0x0d, 0xf1,
+	0xdc, 0x21, 0xbc, 0x25, 0x30, 0xc6, 0xc0, 0x77,
+	0x04, 0x13, 0x21, 0xf0, 0x03, 0x13, 0x22, 0xf0,
+	0x02, 0x13, 0x23, 0xf0, 0x01, 0x13, 0x24, 0xf0,
+	0x08, 0x13, 0x08, 0xf1, 0x2e, 0x73, 0xba, 0x21,
+	0xbd, 0x25, 0x05, 0x13, 0x03, 0xf1, 0x24, 0xc5,
+	0x00, 0xbd, 0xd4, 0x49, 0x03, 0xf1, 0x1c, 0xc5,
+	0x00, 0xbd, 0xc4, 0xc6, 0xc6, 0x67, 0x2e, 0x75,
+	0xd7, 0x22, 0xdd, 0x26, 0x05, 0x15, 0x1b, 0xf0,
+	0x14, 0xc6, 0x00, 0xbe, 0x13, 0xc5, 0x00, 0xbd,
+	0x12, 0xc5, 0x00, 0xbd, 0xf1, 0x49, 0xfb, 0xf1,
+	0xef, 0xe7, 0xf4, 0x49, 0xfa, 0xf1, 0xec, 0xe7,
+	0xf3, 0x49, 0xf7, 0xf1, 0xe9, 0xe7, 0xf2, 0x49,
+	0xf4, 0xf1, 0xe6, 0xe7, 0xb6, 0xc0, 0x50, 0x14,
+	0x90, 0x13, 0xbc, 0x13, 0xf2, 0x14, 0x00, 0xa0,
+	0xa0, 0xd1, 0x00, 0x00, 0xc0, 0x75, 0xd0, 0x49,
+	0x46, 0xf0, 0x26, 0x72, 0xa7, 0x49, 0x43, 0xf0,
+	0x22, 0x72, 0x25, 0x25, 0x20, 0x1f, 0x97, 0x30,
+	0x91, 0x30, 0x40, 0x73, 0xf3, 0xc4, 0x1c, 0x40,
+	0x04, 0xf0, 0xd7, 0x49, 0x05, 0xf1, 0x37, 0xe0,
+	0x53, 0x48, 0xc0, 0x9d, 0x08, 0x02, 0x40, 0x66,
+	0x64, 0x27, 0x06, 0x16, 0x30, 0xf1, 0x46, 0x63,
+	0x3b, 0x13, 0x2d, 0xf1, 0x34, 0x9b, 0x18, 0x1b,
+	0x93, 0x30, 0x2b, 0xc3, 0x10, 0x1c, 0x2b, 0xe8,
+	0x01, 0x14, 0x25, 0xf1, 0x00, 0x1d, 0x26, 0x1a,
+	0x8a, 0x30, 0x22, 0x73, 0xb5, 0x25, 0x0e, 0x0b,
+	0x00, 0x1c, 0x2c, 0xe8, 0x1f, 0xc7, 0x27, 0x40,
+	0x1a, 0xf1, 0x38, 0xe8, 0x32, 0x1f, 0x8f, 0x30,
+	0x08, 0x1b, 0x24, 0xe8, 0x36, 0x72, 0x46, 0x77,
+	0x00, 0x17, 0x0d, 0xf0, 0x13, 0xc3, 0x1f, 0x40,
+	0x03, 0xf1, 0x00, 0x1f, 0x46, 0x9f, 0x44, 0x77,
+	0x9f, 0x44, 0x5f, 0x44, 0x17, 0xe8, 0x0a, 0xc7,
+	0x27, 0x40, 0x05, 0xf1, 0x02, 0xc3, 0x00, 0xbb,
+	0xbe, 0x1a, 0x74, 0x14, 0xff, 0xc7, 0x00, 0xbf,
+	0xb8, 0xcd, 0xff, 0xff, 0x02, 0x0c, 0x54, 0xa5,
+	0xdc, 0xa5, 0x2f, 0x40, 0x05, 0xf1, 0x00, 0x14,
+	0xfa, 0xf1, 0x01, 0x1c, 0x02, 0xe0, 0x00, 0x1c,
+	0x80, 0xff, 0xb0, 0x49, 0x04, 0xf0, 0x01, 0x0b,
+	0xd3, 0xa1, 0x03, 0xe0, 0x02, 0x0b, 0xd3, 0xa5,
+	0x27, 0x31, 0x20, 0x37, 0x02, 0x0b, 0xd3, 0xa5,
+	0x27, 0x31, 0x20, 0x37, 0x00, 0x13, 0xfb, 0xf1,
+	0x80, 0xff, 0x22, 0x73, 0xb5, 0x25, 0x18, 0x1e,
+	0xde, 0x30, 0xd9, 0x30, 0x64, 0x72, 0x11, 0x1e,
+	0x68, 0x23, 0x16, 0x31, 0x80, 0xff, 0x08, 0xc2,
+	0x40, 0x73, 0x3a, 0x48, 0x40, 0x9b, 0x06, 0xff,
+	0x02, 0xc6, 0x00, 0xbe, 0xcc, 0x17, 0x1e, 0xfc,
+	0x2c, 0x75, 0xdc, 0x21, 0xbc, 0x25, 0x04, 0x13,
+	0x0b, 0xf0, 0x03, 0x13, 0x09, 0xf0, 0x02, 0x13,
+	0x07, 0xf0, 0x01, 0x13, 0x05, 0xf0, 0x08, 0x13,
+	0x03, 0xf0, 0x04, 0xc3, 0x00, 0xbb, 0x03, 0xc3,
+	0x00, 0xbb, 0x50, 0x17, 0x3a, 0x17, 0x02, 0xc6,
+	0x00, 0xbe, 0x00, 0x00, 0x02, 0xc6, 0x00, 0xbe,
+	0x00, 0x00, 0x33, 0xc5, 0xa0, 0x74, 0xc0, 0x49,
+	0x1f, 0xf0, 0x30, 0xc5, 0xa0, 0x73, 0x00, 0x13,
+	0x04, 0xf1, 0xa2, 0x73, 0x00, 0x13, 0x14, 0xf0,
+	0x28, 0xc5, 0xa0, 0x74, 0xc8, 0x49, 0x1b, 0xf1,
+	0x26, 0xc5, 0xa0, 0x76, 0xa2, 0x74, 0x01, 0x06,
+	0x20, 0x37, 0xa0, 0x9e, 0xa2, 0x9c, 0x1e, 0xc5,
+	0xa2, 0x73, 0x23, 0x40, 0x10, 0xf8, 0x04, 0xf3,
+	0xa0, 0x73, 0x33, 0x40, 0x0c, 0xf8, 0x15, 0xc5,
+	0xa0, 0x74, 0x41, 0x48, 0xa0, 0x9c, 0x14, 0xc5,
+	0xa0, 0x76, 0x62, 0x48, 0xe0, 0x48, 0xa0, 0x9e,
+	0x10, 0xc6, 0x00, 0xbe, 0x0a, 0xc5, 0xa0, 0x74,
+	0x48, 0x48, 0xa0, 0x9c, 0x0b, 0xc5, 0x20, 0x1e,
+	0xa0, 0x9e, 0xe5, 0x48, 0xa0, 0x9e, 0xf0, 0xe7,
+	0xbc, 0xc0, 0xc8, 0xd2, 0xcc, 0xd2, 0x28, 0xe4,
+	0xfa, 0x01, 0xf0, 0xc0, 0x18, 0x89, 0x00, 0x1d,
+	0x43, 0xc3, 0x62, 0x62, 0xa0, 0x49, 0x06, 0xf0,
+	0x41, 0xc0, 0x02, 0x71, 0x60, 0x99, 0x3f, 0xc1,
+	0x03, 0xe0, 0x3c, 0xc0, 0x3d, 0xc1, 0x02, 0x99,
+	0x00, 0x61, 0x67, 0x11, 0x3d, 0xf1, 0x69, 0x33,
+	0x34, 0xc0, 0x28, 0x40, 0xf7, 0xf1, 0x35, 0xc0,
+	0x00, 0x19, 0x81, 0x1b, 0x89, 0xe8, 0x32, 0xc0,
+	0x04, 0x1a, 0x84, 0x1b, 0x85, 0xe8, 0x7a, 0xe8,
+	0xa3, 0x49, 0xfe, 0xf0, 0x2c, 0xc0, 0x76, 0xe8,
+	0xa1, 0x48, 0x29, 0xc0, 0x84, 0x1b, 0x7c, 0xe8,
+	0x00, 0x1d, 0x69, 0x33, 0x00, 0x1e, 0x01, 0x06,
+	0xff, 0x18, 0x30, 0x40, 0xfd, 0xf1, 0x7f, 0xc0,
+	0x00, 0x76, 0x2e, 0x40, 0xf7, 0xf1, 0x21, 0x48,
+	0x1a, 0xc0, 0x84, 0x1b, 0x6d, 0xe8, 0x76, 0xc0,
+	0x61, 0xe8, 0xa1, 0x49, 0xfd, 0xf0, 0x12, 0xc0,
+	0x00, 0x1a, 0x84, 0x1b, 0x65, 0xe8, 0x5a, 0xe8,
+	0xa5, 0x49, 0xfe, 0xf0, 0x0a, 0xc0, 0x01, 0x19,
+	0x81, 0x1b, 0x5e, 0xe8, 0x48, 0xe0, 0x8c, 0xd3,
+	0xb8, 0x0b, 0x50, 0xe8, 0x83, 0x00, 0x82, 0x00,
+	0x20, 0xb4, 0x10, 0xd8, 0x84, 0xd4, 0xfa, 0xc0,
+	0x00, 0x61, 0x9c, 0x20, 0x9c, 0x24, 0x06, 0x11,
+	0x06, 0xf1, 0x5d, 0xc0, 0x00, 0x61, 0x11, 0x48,
+	0x00, 0x89, 0x35, 0xe0, 0x00, 0x11, 0x02, 0xf1,
+	0x03, 0xe0, 0x04, 0x11, 0x06, 0xf1, 0x53, 0xc0,
+	0x00, 0x61, 0x92, 0x48, 0x00, 0x89, 0x2b, 0xe0,
+	0x05, 0x11, 0x08, 0xf1, 0x4c, 0xc0, 0x00, 0x61,
+	0x91, 0x49, 0x04, 0xf0, 0x91, 0x48, 0x00, 0x89,
+	0x11, 0xe0, 0xdc, 0xc0, 0x00, 0x61, 0x98, 0x20,
+	0x98, 0x24, 0x25, 0x11, 0x1c, 0xf1, 0x40, 0xc0,
+	0x25, 0xe8, 0x95, 0x49, 0x18, 0xf0, 0xd2, 0xc0,
+	0x00, 0x61, 0x98, 0x20, 0x98, 0x24, 0x25, 0x11,
+	0x12, 0xf1, 0x35, 0xc0, 0x00, 0x61, 0x92, 0x49,
+	0x0e, 0xf1, 0x12, 0x48, 0x00, 0x89, 0x2d, 0xc0,
+	0x00, 0x19, 0x00, 0x89, 0x2b, 0xc0, 0x01, 0x89,
+	0x27, 0xc0, 0x10, 0xe8, 0x25, 0xc0, 0x12, 0x48,
+	0x81, 0x1b, 0x16, 0xe8, 0xb9, 0xc3, 0x62, 0x62,
+	0xa0, 0x49, 0x05, 0xf0, 0xb5, 0xc3, 0x60, 0x71,
+	0xb5, 0xc0, 0x02, 0x99, 0x02, 0xc0, 0x00, 0xb8,
+	0xd6, 0x07, 0x13, 0xc4, 0x84, 0x98, 0x00, 0x1b,
+	0x86, 0x8b, 0x86, 0x73, 0xbf, 0x49, 0xfe, 0xf1,
+	0x80, 0x71, 0x82, 0x72, 0x80, 0xff, 0x09, 0xc4,
+	0x84, 0x98, 0x80, 0x99, 0x82, 0x9a, 0x86, 0x8b,
+	0x86, 0x73, 0xbf, 0x49, 0xfe, 0xf1, 0x80, 0xff,
+	0x08, 0xea, 0x10, 0xd4, 0x88, 0xd3, 0x30, 0xd4,
+	0x10, 0xc0, 0x12, 0xe8, 0x8a, 0xd3, 0x00, 0xd8,
+	0x02, 0xc0, 0x00, 0xb8, 0xe0, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static u16 r8153_pla_patch_c_bp[] = {
+	0xfc26, 0x8000, 0xfc28, 0x1306, 0xfc2a, 0x17ca, 0xfc2c, 0x171e,
+	0xfc2e, 0x0000, 0xfc30, 0x0000, 0xfc32, 0x01b4, 0xfc34, 0x07d4,
+	0xfc36, 0x0894, 0xfc38, 0x00e7 };
+
+static u16 r8153_ram_code_bc[] = {
+	0xB436, 0xB820, 0xB438, 0x0290, 0xB436, 0xA012, 0xB438, 0x0000,
+	0xB436, 0xA014, 0xB438, 0x2c04, 0xB438, 0x2c07, 0xB438, 0x2c0a,
+	0xB438, 0x2c0d, 0xB438, 0xa240, 0xB438, 0xa104, 0xB438, 0x292d,
+	0xB438, 0x8620, 0xB438, 0xa480, 0xB438, 0x2a2c, 0xB438, 0x8480,
+	0xB438, 0xa101, 0xB438, 0x2a36, 0xB438, 0xd056, 0xB438, 0x2223,
+	0xB436, 0xA01A, 0xB438, 0x0000, 0xB436, 0xA006, 0xB438, 0x0222,
+	0xB436, 0xA004, 0xB438, 0x0a35, 0xB436, 0xA002, 0xB438, 0x0a2b,
+	0xB436, 0xA000, 0xB438, 0xf92c, 0xB436, 0xB820, 0xB438, 0x0210 };
+
+static u8 r8153_usb_patch_b[] = {
+	0x08, 0xe0, 0x0f, 0xe0, 0x18, 0xe0, 0x24, 0xe0,
+	0x26, 0xe0, 0x3a, 0xe0, 0x84, 0xe0, 0x9c, 0xe0,
+	0xc2, 0x49, 0x04, 0xf0, 0x02, 0xc0, 0x00, 0xb8,
+	0x14, 0x18, 0x02, 0xc0, 0x00, 0xb8, 0x2e, 0x18,
+	0x06, 0x89, 0x08, 0xc0, 0x0c, 0x61, 0x92, 0x48,
+	0x93, 0x48, 0x0c, 0x89, 0x02, 0xc0, 0x00, 0xb8,
+	0x08, 0x05, 0x40, 0xb4, 0x16, 0x89, 0x6d, 0xc0,
+	0x00, 0x61, 0x95, 0x49, 0x06, 0xf0, 0xfa, 0xc0,
+	0x0c, 0x61, 0x92, 0x48, 0x93, 0x48, 0x0c, 0x89,
+	0x02, 0xc0, 0x00, 0xb8, 0xe2, 0x04, 0x02, 0xc2,
+	0x00, 0xba, 0xec, 0x11, 0x60, 0x60, 0x85, 0x49,
+	0x0d, 0xf1, 0x11, 0xc6, 0xd2, 0x61, 0x91, 0x49,
+	0xfd, 0xf0, 0x74, 0x60, 0x04, 0x48, 0x74, 0x88,
+	0x08, 0xc6, 0x08, 0xc0, 0xc4, 0x98, 0x01, 0x18,
+	0xc0, 0x88, 0x02, 0xc0, 0x00, 0xb8, 0x6e, 0x12,
+	0x04, 0xe4, 0x0d, 0x00, 0x00, 0xd4, 0xd1, 0x49,
+	0x3c, 0xf1, 0xd2, 0x49, 0x16, 0xf1, 0xd3, 0x49,
+	0x18, 0xf1, 0xd4, 0x49, 0x19, 0xf1, 0xd5, 0x49,
+	0x1a, 0xf1, 0xd6, 0x49, 0x1b, 0xf1, 0xd7, 0x49,
+	0x1c, 0xf1, 0xd8, 0x49, 0x1d, 0xf1, 0xd9, 0x49,
+	0x20, 0xf1, 0xda, 0x49, 0x23, 0xf1, 0xdb, 0x49,
+	0x24, 0xf1, 0x02, 0xc4, 0x00, 0xbc, 0x20, 0x04,
+	0xe5, 0x8e, 0x02, 0xc4, 0x00, 0xbc, 0x14, 0x02,
+	0x02, 0xc4, 0x00, 0xbc, 0x16, 0x02, 0x02, 0xc4,
+	0x00, 0xbc, 0x18, 0x02, 0x02, 0xc4, 0x00, 0xbc,
+	0x1a, 0x02, 0x02, 0xc4, 0x00, 0xbc, 0x1c, 0x02,
+	0x02, 0xc4, 0x00, 0xbc, 0x94, 0x02, 0x10, 0xc7,
+	0xe0, 0x8e, 0x02, 0xc4, 0x00, 0xbc, 0x8a, 0x02,
+	0x0b, 0xc7, 0xe4, 0x8e, 0x02, 0xc4, 0x00, 0xbc,
+	0x88, 0x02, 0x02, 0xc4, 0x00, 0xbc, 0x6e, 0x02,
+	0x02, 0xc4, 0x00, 0xbc, 0x5a, 0x02, 0x30, 0xe4,
+	0x0c, 0xc3, 0x60, 0x64, 0xc5, 0x49, 0x04, 0xf1,
+	0x74, 0x64, 0xc4, 0x48, 0x74, 0x8c, 0x06, 0xc3,
+	0x64, 0x8e, 0x02, 0xc4, 0x00, 0xbc, 0x20, 0x04,
+	0x00, 0xd8, 0x00, 0xe4, 0xb2, 0xc0, 0x00, 0x61,
+	0x90, 0x49, 0x09, 0xf1, 0x8b, 0xc6, 0xca, 0x61,
+	0x94, 0x49, 0x0e, 0xf1, 0xf6, 0xc6, 0xda, 0x60,
+	0x81, 0x49, 0x0a, 0xf0, 0x65, 0x60, 0x03, 0x48,
+	0x65, 0x88, 0xef, 0xc6, 0xdc, 0x60, 0x80, 0x48,
+	0xdc, 0x88, 0x05, 0xc6, 0x00, 0xbe, 0x02, 0xc6,
+	0x00, 0xbe, 0x36, 0x13, 0x4c, 0x17, 0x99, 0xc4,
+	0x80, 0x65, 0xd0, 0x49, 0x04, 0xf1, 0xfa, 0x75,
+	0x04, 0xc4, 0x00, 0xbc, 0x03, 0xc4, 0x00, 0xbc,
+	0x9a, 0x00, 0xee, 0x01 };
+
+static u16 r8153_usb_patch_b_bp[] = {
+	0xfc26, 0xa000, 0xfc28, 0x180c, 0xfc2a, 0x0506, 0xfc2c, 0x04E0,
+	0xfc2e, 0x11E4, 0xfc30, 0x125C, 0xfc32, 0x0232, 0xfc34, 0x131E,
+	0xfc36, 0x0098, 0xfc38, 0x00FF };
+
+static u8 r8153_pla_patch_b[] = {
+	0x08, 0xe0, 0xea, 0xe0, 0xf2, 0xe0, 0x04, 0xe1,
+	0x09, 0xe1, 0x0e, 0xe1, 0x46, 0xe1, 0xf3, 0xe1,
+	0x14, 0xc2, 0x40, 0x73, 0xba, 0x48, 0x40, 0x9b,
+	0x11, 0xc2, 0x40, 0x73, 0xb0, 0x49, 0x17, 0xf0,
+	0xbf, 0x49, 0x03, 0xf1, 0x09, 0xc5, 0x00, 0xbd,
+	0xb1, 0x49, 0x11, 0xf0, 0xb1, 0x48, 0x40, 0x9b,
+	0x02, 0xc2, 0x00, 0xba, 0x1a, 0x17, 0x00, 0xe0,
+	0x1e, 0xfc, 0xbc, 0xc0, 0xf0, 0xc0, 0xde, 0xe8,
+	0x00, 0x80, 0x00, 0x20, 0x2c, 0x75, 0xd4, 0x49,
+	0x12, 0xf1, 0x32, 0xe0, 0xf8, 0xc2, 0x46, 0x71,
+	0xf7, 0xc2, 0x40, 0x73, 0xbe, 0x49, 0x03, 0xf1,
+	0xf5, 0xc7, 0x02, 0xe0, 0xf2, 0xc7, 0x4f, 0x30,
+	0x26, 0x62, 0xa1, 0x49, 0xf0, 0xf1, 0x22, 0x72,
+	0xa0, 0x49, 0xed, 0xf1, 0x25, 0x25, 0x18, 0x1f,
+	0x97, 0x30, 0x91, 0x30, 0x36, 0x9a, 0x2c, 0x75,
+	0x3c, 0xc3, 0x60, 0x73, 0xb1, 0x49, 0x0d, 0xf1,
+	0xdc, 0x21, 0xbc, 0x25, 0x30, 0xc6, 0xc0, 0x77,
+	0x04, 0x13, 0x21, 0xf0, 0x03, 0x13, 0x22, 0xf0,
+	0x02, 0x13, 0x23, 0xf0, 0x01, 0x13, 0x24, 0xf0,
+	0x08, 0x13, 0x08, 0xf1, 0x2e, 0x73, 0xba, 0x21,
+	0xbd, 0x25, 0x05, 0x13, 0x03, 0xf1, 0x24, 0xc5,
+	0x00, 0xbd, 0xd4, 0x49, 0x03, 0xf1, 0x1c, 0xc5,
+	0x00, 0xbd, 0xc4, 0xc6, 0xc6, 0x67, 0x2e, 0x75,
+	0xd7, 0x22, 0xdd, 0x26, 0x05, 0x15, 0x1b, 0xf0,
+	0x14, 0xc6, 0x00, 0xbe, 0x13, 0xc5, 0x00, 0xbd,
+	0x12, 0xc5, 0x00, 0xbd, 0xf1, 0x49, 0xfb, 0xf1,
+	0xef, 0xe7, 0xf4, 0x49, 0xfa, 0xf1, 0xec, 0xe7,
+	0xf3, 0x49, 0xf7, 0xf1, 0xe9, 0xe7, 0xf2, 0x49,
+	0xf4, 0xf1, 0xe6, 0xe7, 0xb6, 0xc0, 0x9e, 0x12,
+	0xde, 0x11, 0x0a, 0x12, 0x3c, 0x13, 0x00, 0xa0,
+	0xa0, 0xd1, 0x00, 0x00, 0xc0, 0x75, 0xd0, 0x49,
+	0x46, 0xf0, 0x26, 0x72, 0xa7, 0x49, 0x43, 0xf0,
+	0x22, 0x72, 0x25, 0x25, 0x20, 0x1f, 0x97, 0x30,
+	0x91, 0x30, 0x40, 0x73, 0xf3, 0xc4, 0x1c, 0x40,
+	0x04, 0xf0, 0xd7, 0x49, 0x05, 0xf1, 0x37, 0xe0,
+	0x53, 0x48, 0xc0, 0x9d, 0x08, 0x02, 0x40, 0x66,
+	0x64, 0x27, 0x06, 0x16, 0x30, 0xf1, 0x46, 0x63,
+	0x3b, 0x13, 0x2d, 0xf1, 0x34, 0x9b, 0x18, 0x1b,
+	0x93, 0x30, 0x2b, 0xc3, 0x10, 0x1c, 0x2b, 0xe8,
+	0x01, 0x14, 0x25, 0xf1, 0x00, 0x1d, 0x26, 0x1a,
+	0x8a, 0x30, 0x22, 0x73, 0xb5, 0x25, 0x0e, 0x0b,
+	0x00, 0x1c, 0x2c, 0xe8, 0x1f, 0xc7, 0x27, 0x40,
+	0x1a, 0xf1, 0x38, 0xe8, 0x32, 0x1f, 0x8f, 0x30,
+	0x08, 0x1b, 0x24, 0xe8, 0x36, 0x72, 0x46, 0x77,
+	0x00, 0x17, 0x0d, 0xf0, 0x13, 0xc3, 0x1f, 0x40,
+	0x03, 0xf1, 0x00, 0x1f, 0x46, 0x9f, 0x44, 0x77,
+	0x9f, 0x44, 0x5f, 0x44, 0x17, 0xe8, 0x0a, 0xc7,
+	0x27, 0x40, 0x05, 0xf1, 0x02, 0xc3, 0x00, 0xbb,
+	0xfa, 0x18, 0xb0, 0x18, 0xff, 0xc7, 0x00, 0xbf,
+	0xb8, 0xcd, 0xff, 0xff, 0x02, 0x0c, 0x54, 0xa5,
+	0xdc, 0xa5, 0x2f, 0x40, 0x05, 0xf1, 0x00, 0x14,
+	0xfa, 0xf1, 0x01, 0x1c, 0x02, 0xe0, 0x00, 0x1c,
+	0x80, 0xff, 0xb0, 0x49, 0x04, 0xf0, 0x01, 0x0b,
+	0xd3, 0xa1, 0x03, 0xe0, 0x02, 0x0b, 0xd3, 0xa5,
+	0x27, 0x31, 0x20, 0x37, 0x02, 0x0b, 0xd3, 0xa5,
+	0x27, 0x31, 0x20, 0x37, 0x00, 0x13, 0xfb, 0xf1,
+	0x80, 0xff, 0x22, 0x73, 0xb5, 0x25, 0x18, 0x1e,
+	0xde, 0x30, 0xd9, 0x30, 0x64, 0x72, 0x11, 0x1e,
+	0x68, 0x23, 0x16, 0x31, 0x80, 0xff, 0x08, 0xc2,
+	0x40, 0x73, 0x3a, 0x48, 0x40, 0x9b, 0x06, 0xff,
+	0x02, 0xc6, 0x00, 0xbe, 0x08, 0x16, 0x1e, 0xfc,
+	0x2c, 0x75, 0xdc, 0x21, 0xbc, 0x25, 0x04, 0x13,
+	0x0b, 0xf0, 0x03, 0x13, 0x09, 0xf0, 0x02, 0x13,
+	0x07, 0xf0, 0x01, 0x13, 0x05, 0xf0, 0x08, 0x13,
+	0x03, 0xf0, 0x04, 0xc3, 0x00, 0xbb, 0x03, 0xc3,
+	0x00, 0xbb, 0x8c, 0x15, 0x76, 0x15, 0xa0, 0x64,
+	0x40, 0x48, 0xa0, 0x8c, 0x02, 0xc4, 0x00, 0xbc,
+	0x82, 0x00, 0xa0, 0x62, 0x21, 0x48, 0xa0, 0x8a,
+	0x02, 0xc2, 0x00, 0xba, 0x40, 0x03, 0x33, 0xc5,
+	0xa0, 0x74, 0xc0, 0x49, 0x1f, 0xf0, 0x30, 0xc5,
+	0xa0, 0x73, 0x00, 0x13, 0x04, 0xf1, 0xa2, 0x73,
+	0x00, 0x13, 0x14, 0xf0, 0x28, 0xc5, 0xa0, 0x74,
+	0xc8, 0x49, 0x1b, 0xf1, 0x26, 0xc5, 0xa0, 0x76,
+	0xa2, 0x74, 0x01, 0x06, 0x20, 0x37, 0xa0, 0x9e,
+	0xa2, 0x9c, 0x1e, 0xc5, 0xa2, 0x73, 0x23, 0x40,
+	0x10, 0xf8, 0x04, 0xf3, 0xa0, 0x73, 0x33, 0x40,
+	0x0c, 0xf8, 0x15, 0xc5, 0xa0, 0x74, 0x41, 0x48,
+	0xa0, 0x9c, 0x14, 0xc5, 0xa0, 0x76, 0x62, 0x48,
+	0xe0, 0x48, 0xa0, 0x9e, 0x10, 0xc6, 0x00, 0xbe,
+	0x0a, 0xc5, 0xa0, 0x74, 0x48, 0x48, 0xa0, 0x9c,
+	0x0b, 0xc5, 0x20, 0x1e, 0xa0, 0x9e, 0xe5, 0x48,
+	0xa0, 0x9e, 0xf0, 0xe7, 0xbc, 0xc0, 0xc8, 0xd2,
+	0xcc, 0xd2, 0x28, 0xe4, 0xe6, 0x01, 0xf0, 0xc0,
+	0x18, 0x89, 0x00, 0x1d, 0x3c, 0xc3, 0x60, 0x71,
+	0x3c, 0xc0, 0x02, 0x99, 0x00, 0x61, 0x67, 0x11,
+	0x3c, 0xf1, 0x69, 0x33, 0x35, 0xc0, 0x28, 0x40,
+	0xf6, 0xf1, 0x34, 0xc0, 0x00, 0x19, 0x81, 0x1b,
+	0x8c, 0xe8, 0x31, 0xc0, 0x04, 0x1a, 0x84, 0x1b,
+	0x88, 0xe8, 0x7d, 0xe8, 0xa3, 0x49, 0xfe, 0xf0,
+	0x2b, 0xc0, 0x79, 0xe8, 0xa1, 0x48, 0x28, 0xc0,
+	0x84, 0x1b, 0x7f, 0xe8, 0x00, 0x1d, 0x69, 0x33,
+	0x00, 0x1e, 0x01, 0x06, 0xff, 0x18, 0x30, 0x40,
+	0xfd, 0xf1, 0x18, 0xc0, 0x00, 0x76, 0x2e, 0x40,
+	0xf7, 0xf1, 0x21, 0x48, 0x19, 0xc0, 0x84, 0x1b,
+	0x70, 0xe8, 0x79, 0xc0, 0x64, 0xe8, 0xa1, 0x49,
+	0xfd, 0xf0, 0x11, 0xc0, 0x00, 0x1a, 0x84, 0x1b,
+	0x68, 0xe8, 0x5d, 0xe8, 0xa5, 0x49, 0xfe, 0xf0,
+	0x09, 0xc0, 0x01, 0x19, 0x81, 0x1b, 0x61, 0xe8,
+	0x4f, 0xe0, 0x88, 0xd3, 0x8c, 0xd3, 0xb8, 0x0b,
+	0x50, 0xe8, 0x20, 0xb4, 0x10, 0xd8, 0x84, 0xd4,
+	0xfc, 0xc0, 0x00, 0x61, 0x9c, 0x20, 0x9c, 0x24,
+	0x06, 0x11, 0x06, 0xf1, 0x60, 0xc0, 0x00, 0x61,
+	0x11, 0x48, 0x00, 0x89, 0x3d, 0xe0, 0x00, 0x11,
+	0x02, 0xf1, 0x03, 0xe0, 0x04, 0x11, 0x06, 0xf1,
+	0x56, 0xc0, 0x00, 0x61, 0x92, 0x48, 0x00, 0x89,
+	0x33, 0xe0, 0x05, 0x11, 0x08, 0xf1, 0x4f, 0xc0,
+	0x00, 0x61, 0x91, 0x49, 0x04, 0xf0, 0x91, 0x48,
+	0x00, 0x89, 0x11, 0xe0, 0xde, 0xc0, 0x00, 0x61,
+	0x98, 0x20, 0x98, 0x24, 0x25, 0x11, 0x24, 0xf1,
+	0x45, 0xc0, 0x29, 0xe8, 0x95, 0x49, 0x20, 0xf0,
+	0xd4, 0xc0, 0x00, 0x61, 0x98, 0x20, 0x98, 0x24,
+	0x25, 0x11, 0x1a, 0xf1, 0x38, 0xc0, 0x00, 0x61,
+	0x92, 0x49, 0x16, 0xf1, 0x12, 0x48, 0x00, 0x89,
+	0x30, 0xc0, 0x00, 0x19, 0x00, 0x89, 0x2e, 0xc0,
+	0x01, 0x89, 0x2e, 0xc0, 0x04, 0x19, 0x81, 0x1b,
+	0x1c, 0xe8, 0x2b, 0xc0, 0x14, 0x19, 0x81, 0x1b,
+	0x18, 0xe8, 0x22, 0xc0, 0x0c, 0xe8, 0x20, 0xc0,
+	0x12, 0x48, 0x81, 0x1b, 0x12, 0xe8, 0xb3, 0xc3,
+	0x62, 0x71, 0xb3, 0xc0, 0x02, 0x99, 0x02, 0xc0,
+	0x00, 0xb8, 0x96, 0x07, 0x13, 0xc4, 0x84, 0x98,
+	0x00, 0x1b, 0x86, 0x8b, 0x86, 0x73, 0xbf, 0x49,
+	0xfe, 0xf1, 0x80, 0x71, 0x82, 0x72, 0x80, 0xff,
+	0x09, 0xc4, 0x84, 0x98, 0x80, 0x99, 0x82, 0x9a,
+	0x86, 0x8b, 0x86, 0x73, 0xbf, 0x49, 0xfe, 0xf1,
+	0x80, 0xff, 0x08, 0xea, 0x10, 0xd4, 0x30, 0xd4,
+	0x10, 0xc0, 0x12, 0xe8, 0x8a, 0xd3, 0x28, 0xe4,
+	0x2c, 0xe4, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static u16 r8153_pla_patch_b_bp[] = {
+	0xfc26, 0x8000, 0xfc28, 0x1154, 0xfc2a, 0x1606, 0xfc2c, 0x155a,
+	0xfc2e, 0x0080, 0xfc30, 0x033c, 0xfc32, 0x01a0, 0xfc34, 0x0794,
+	0xfc36, 0x0000, 0xfc38, 0x007f };
+
+static u16 r8153_ram_code_d[] = {
+	0xa436, 0xb820, 0xa438, 0x0290, 0xa436, 0xa012, 0xa438, 0x0000,
+	0xa436, 0xa014, 0xa438, 0x2c04, 0xb438, 0x2c07, 0xb438, 0x2c07,
+	0xb438, 0x2c07, 0xb438, 0xa240, 0xb438, 0xa104, 0xb438, 0x2944,
+	0xa436, 0xa01a, 0xa438, 0x0000, 0xa436, 0xa006, 0xa438, 0x0fff,
+	0xa436, 0xa004, 0xa438, 0x0fff, 0xa436, 0xa002, 0xa438, 0x0fff,
+	0xa436, 0xa000, 0xa438, 0x1943, 0xa436, 0xb820, 0xa438, 0x0210 };
+
+static u8 usb_patch_d[] = {
+	0x08, 0xe0, 0x0a, 0xe0, 0x0c, 0xe0, 0x1f, 0xe0,
+	0x28, 0xe0, 0x2a, 0xe0, 0x2c, 0xe0, 0x2e, 0xe0,
+	0x02, 0xc5, 0x00, 0xbd, 0x00, 0x00, 0x02, 0xc3,
+	0x00, 0xbb, 0x00, 0x00, 0x30, 0x18, 0x11, 0xc1,
+	0x05, 0xe8, 0x10, 0xc6, 0x02, 0xc2, 0x00, 0xba,
+	0x94, 0x17, 0x02, 0xb4, 0x09, 0xc2, 0x40, 0x99,
+	0x0e, 0x48, 0x42, 0x98, 0x42, 0x70, 0x8e, 0x49,
+	0xfe, 0xf1, 0x02, 0xb0, 0x80, 0xff, 0xc0, 0xd4,
+	0xe4, 0x40, 0x20, 0xd4, 0xb0, 0x49, 0x04, 0xf0,
+	0x30, 0x18, 0x06, 0xc1, 0xef, 0xef, 0xfa, 0xc7,
+	0x02, 0xc0, 0x00, 0xb8, 0x38, 0x12, 0xe4, 0x4b,
+	0x02, 0xc3, 0x00, 0xbb, 0x00, 0x00, 0x02, 0xc5,
+	0x00, 0xbd, 0x00, 0x00, 0x02, 0xc1, 0x00, 0xb9,
+	0x00, 0x00, 0x02, 0xc1, 0x00, 0xb9, 0x00, 0x00 };
+
+static u16 r8153_usb_patch_d_bp[] = {
+	0xfc26, 0xa000, 0xfc28, 0x0000, 0xfc2a, 0x0000, 0xfc2c, 0x1792,
+	0xfc2e, 0x1236, 0xfc30, 0x0000, 0xfc32, 0x0000, 0xfc34, 0x0000,
+	0xfc36, 0x0000, 0xfc38, 0x000c };
+
+static void rtl_clear_bp(struct r8152 *tp)
+{
+	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_0, 0);
+	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_2, 0);
+	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_4, 0);
+	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_6, 0);
+	ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_0, 0);
+	ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_2, 0);
+	ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_4, 0);
+	ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_6, 0);
+
+	mdelay(6);
+
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_BP_BA, 0);
+	ocp_write_word(tp, MCU_TYPE_USB, USB_BP_BA, 0);
+}
+
+static void r8153_clear_bp(struct r8152 *tp)
+{
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_BP_EN, 0);
+	ocp_write_byte(tp, MCU_TYPE_USB, USB_BP_EN, 0);
+	rtl_clear_bp(tp);
+}
+
+static void patch4(struct r8152 *tp)
+{
+	u8 data;
+
+	data = ocp_read_byte(tp, MCU_TYPE_USB, 0xd429);
+	data |= 0x80;
+	ocp_write_byte(tp, MCU_TYPE_USB, 0xd429, data);
+	ocp_write_word(tp, MCU_TYPE_USB, 0xc0ce, 0x0210);
+	data = ocp_read_byte(tp, MCU_TYPE_USB, 0xd429);
+	data &= ~0x80;
+	ocp_write_byte(tp, MCU_TYPE_USB, 0xd429, data);
+}
+
+static int r8153_pre_ram_code(struct r8152 *tp, u16 patch_key)
+{
+	u16 data;
+	int i;
+
+	data = ocp_reg_read(tp, 0xb820);
+	data |= 0x0010;
+	ocp_reg_write(tp, 0xb820, data);
+
+	for (i = 0, data = 0; !data && i < 5000; i++) {
+		mdelay(2);
+		data = ocp_reg_read(tp, 0xb800) & 0x0040;
+	}
+
+	sram_write(tp, 0x8146, patch_key);
+	sram_write(tp, 0xb82e, 0x0001);
+
+	return -EBUSY;
+}
+
+static int r8153_post_ram_code(struct r8152 *tp)
+{
+	u16 data;
+
+	sram_write(tp, 0x0000, 0x0000);
+
+	data = ocp_reg_read(tp, 0xb82e);
+	data &= ~0x0001;
+	ocp_reg_write(tp, 0xb82e, data);
+
+	sram_write(tp, 0x8146, 0x0000);
+
+	data = ocp_reg_read(tp, 0xb820);
+	data &= ~0x0010;
+	ocp_reg_write(tp, 0xb820, data);
+
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, tp->ocp_base);
+
+	return 0;
+}
+
+static void r8153_wdt1_end(struct r8152 *tp)
+{
+	int i;
+
+	for (i = 0; i < 104; i++) {
+		if (!(ocp_read_byte(tp, MCU_TYPE_USB, 0xe404) & 1))
+			break;
+		mdelay(2);
+	}
+}
+
+void r8152b_firmware(struct r8152 *tp)
+{
+	int i;
+
+	if (tp->version == RTL_VER_01) {
+		int i;
+
+		patch4(tp);
+		rtl_clear_bp(tp);
+
+		generic_ocp_write(tp, 0xf800, 0x3f,
+				  sizeof(r8152b_pla_patch_a),
+				  r8152b_pla_patch_a, MCU_TYPE_PLA);
+
+		for (i = 0; i < ARRAY_SIZE(r8152b_pla_patch_a_bp); i += 2)
+			ocp_write_word(tp, MCU_TYPE_PLA,
+				       r8152b_pla_patch_a_bp[i],
+				       r8152b_pla_patch_a_bp[i+1]);
+
+		ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, 0x2000);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb092, 0x7070);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb098, 0x0600);
+		for (i = 0; i < ARRAY_SIZE(r8152b_ram_code1); i++)
+			ocp_write_word(tp, MCU_TYPE_PLA, 0xb09a,
+				       r8152b_ram_code1[i]);
+
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb098, 0x0200);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb092, 0x7030);
+	} else if (tp->version == RTL_VER_02) {
+		rtl_clear_bp(tp);
+
+		generic_ocp_write(tp, 0xf800, 0xff,
+				  sizeof(r8152b_pla_patch_a2),
+				  r8152b_pla_patch_a2, MCU_TYPE_PLA);
+
+		for (i = 0; i < ARRAY_SIZE(r8152b_pla_patch_a2_bp);
+		     i += 2)
+			ocp_write_word(tp, MCU_TYPE_PLA,
+				       r8152b_pla_patch_a2_bp[i],
+				       r8152b_pla_patch_a2_bp[i+1]);
+	}
+}
+
+void r8153_firmware(struct r8152 *tp)
+{
+	int i;
+
+	if (tp->version == RTL_VER_03) {
+		r8153_clear_bp(tp);
+
+		r8153_pre_ram_code(tp, 0x7000);
+
+		for (i = 0; i < ARRAY_SIZE(r8153_ram_code_a); i += 2)
+			ocp_write_word(tp, MCU_TYPE_PLA,
+				       r8153_ram_code_a[i],
+				       r8153_ram_code_a[i+1]);
+
+		r8153_post_ram_code(tp);
+	} else if (tp->version == RTL_VER_04) {
+		r8153_pre_ram_code(tp, 0x7001);
+
+	for (i = 0; i < ARRAY_SIZE(r8153_ram_code_bc); i += 2)
+		ocp_write_word(tp, MCU_TYPE_PLA,
+			       r8153_ram_code_bc[i],
+			       r8153_ram_code_bc[i+1]);
+
+		r8153_post_ram_code(tp);
+
+		r8153_wdt1_end(tp);
+		r8153_clear_bp(tp);
+
+		ocp_write_word(tp, MCU_TYPE_USB, USB_BP_EN, 0x0000);
+		generic_ocp_write(tp, 0xf800, 0xff,
+				  sizeof(r8153_usb_patch_b),
+				  r8153_usb_patch_b, MCU_TYPE_USB);
+
+		for (i = 0; i < ARRAY_SIZE(r8153_usb_patch_b_bp); i += 2)
+			ocp_write_word(tp, MCU_TYPE_USB,
+				       r8153_usb_patch_b_bp[i],
+				       r8153_usb_patch_b_bp[i+1]);
+
+		if (!(ocp_read_word(tp, MCU_TYPE_PLA, 0xd38e) & BIT(0))) {
+			ocp_write_word(tp, MCU_TYPE_PLA, 0xd38c, 0x0082);
+			ocp_write_word(tp, MCU_TYPE_PLA, 0xd38e, 0x0082);
+		}
+
+		ocp_write_word(tp, MCU_TYPE_PLA, PLA_BP_EN, 0x0000);
+		generic_ocp_write(tp, 0xf800, 0xff,
+				  sizeof(r8153_pla_patch_b),
+				  r8153_pla_patch_b, MCU_TYPE_PLA);
+
+		for (i = 0; i < ARRAY_SIZE(r8153_pla_patch_b_bp); i += 2)
+			ocp_write_word(tp, MCU_TYPE_PLA,
+				       r8153_pla_patch_b_bp[i],
+				       r8153_pla_patch_b_bp[i+1]);
+
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xd388, 0x08ca);
+	} else if (tp->version == RTL_VER_05) {
+		u32 ocp_data;
+
+		ocp_data = ocp_read_word(tp, MCU_TYPE_USB, 0xcfca);
+		ocp_data &= ~0x4000;
+		ocp_write_word(tp, MCU_TYPE_USB, 0xcfca, ocp_data);
+
+		r8153_pre_ram_code(tp, 0x7001);
+
+		for (i = 0; i < ARRAY_SIZE(r8153_ram_code_bc); i += 2)
+			ocp_write_word(tp, MCU_TYPE_PLA,
+				       r8153_ram_code_bc[i],
+				       r8153_ram_code_bc[i+1]);
+
+		r8153_post_ram_code(tp);
+
+		r8153_wdt1_end(tp);
+		r8153_clear_bp(tp);
+
+		ocp_write_word(tp, MCU_TYPE_USB, USB_BP_EN, 0x0000);
+		generic_ocp_write(tp, 0xf800, 0xff,
+				  sizeof(r8153_usb_patch_c),
+				  r8153_usb_patch_c, MCU_TYPE_USB);
+
+		for (i = 0; i < ARRAY_SIZE(r8153_usb_patch_c_bp); i += 2)
+			ocp_write_word(tp, MCU_TYPE_USB,
+				       r8153_usb_patch_c_bp[i],
+				       r8153_usb_patch_c_bp[i+1]);
+
+		if (ocp_read_byte(tp, MCU_TYPE_USB, 0xcfef) & 1) {
+			ocp_write_word(tp, MCU_TYPE_USB, 0xfc30, 0x1578);
+			ocp_write_word(tp, MCU_TYPE_USB, USB_BP_EN, 0x00ff);
+		} else {
+			ocp_write_word(tp, MCU_TYPE_USB, USB_BP_EN, 0x00ef);
+		}
+
+		ocp_write_word(tp, MCU_TYPE_PLA, PLA_BP_EN, 0x0000);
+		generic_ocp_write(tp, 0xf800, 0xff,
+				  sizeof(r8153_pla_patch_c),
+				  r8153_pla_patch_c, MCU_TYPE_PLA);
+
+		for (i = 0; i < ARRAY_SIZE(r8153_pla_patch_c_bp); i += 2)
+			ocp_write_word(tp, MCU_TYPE_PLA,
+				       r8153_pla_patch_c_bp[i],
+				       r8153_pla_patch_c_bp[i+1]);
+
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xd388, 0x08ca);
+
+		ocp_data = ocp_read_word(tp, MCU_TYPE_USB, 0xcfca);
+		ocp_data |= 0x4000;
+		ocp_write_word(tp, MCU_TYPE_USB, 0xcfca, ocp_data);
+	} else if (tp->version == RTL_VER_06) {
+		r8153_pre_ram_code(tp, 0x7002);
+
+		for (i = 0; i < ARRAY_SIZE(r8153_ram_code_d); i += 2)
+			ocp_write_word(tp, MCU_TYPE_PLA,
+				       r8153_ram_code_d[i],
+				       r8153_ram_code_d[i+1]);
+
+		r8153_post_ram_code(tp);
+
+		r8153_clear_bp(tp);
+
+		ocp_write_word(tp, MCU_TYPE_USB, USB_BP_EN, 0x0000);
+		generic_ocp_write(tp, 0xf800, 0xff, sizeof(usb_patch_d),
+				  usb_patch_d, MCU_TYPE_USB);
+
+		for (i = 0; i < ARRAY_SIZE(r8153_usb_patch_d_bp); i += 2)
+			ocp_write_word(tp, MCU_TYPE_USB,
+				       r8153_usb_patch_d_bp[i],
+				       r8153_usb_patch_d_bp[i+1]);
+	}
+}
diff --git a/drivers/usb/eth/usb_ether.c b/drivers/usb/eth/usb_ether.c
index 62d20f0..b9c9a84 100644
--- a/drivers/usb/eth/usb_ether.c
+++ b/drivers/usb/eth/usb_ether.c
@@ -180,6 +180,13 @@ static const struct usb_eth_prob_dev prob_dev[] = {
 		.get_info = smsc95xx_eth_get_info,
 	},
 #endif
+#ifdef CONFIG_USB_ETHER_RTL8152
+	{
+		.before_probe = r8152_eth_before_probe,
+		.probe = r8152_eth_probe,
+		.get_info = r8152_eth_get_info,
+	},
+#endif
 	{ },		/* END */
 };
 
diff --git a/include/usb_ether.h b/include/usb_ether.h
index c6d1416..51fce4e 100644
--- a/include/usb_ether.h
+++ b/include/usb_ether.h
@@ -131,6 +131,12 @@ int smsc95xx_eth_probe(struct usb_device *dev, unsigned int ifnum,
 			struct ueth_data *ss);
 int smsc95xx_eth_get_info(struct usb_device *dev, struct ueth_data *ss,
 			struct eth_device *eth);
+
+void r8152_eth_before_probe(void);
+int r8152_eth_probe(struct usb_device *dev, unsigned int ifnum,
+		    struct ueth_data *ss);
+int r8152_eth_get_info(struct usb_device *dev, struct ueth_data *ss,
+		       struct eth_device *eth);
 #endif
 
 #endif /* __USB_ETHER_H__ */
-- 
1.7.9.5

  reply	other threads:[~2016-01-14  5:22 UTC|newest]

Thread overview: 64+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-13 16:03 [U-Boot] [PATCH 1/2] checkpatch: ignore request to use ether_addr_copy() Stephen Warren
2015-11-13 16:03 ` [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver Stephen Warren
2015-11-14  1:13   ` Marek Vasut
2015-11-16 17:32     ` Stephen Warren
2015-11-17  7:18       ` Ted
2015-11-17  8:04         ` Marek Vasut
2015-11-19  6:07         ` Anand Moon
2015-11-19 16:51           ` Stephen Warren
2015-11-19 17:00             ` Lukasz Majewski
2015-11-19 17:00             ` Marek Vasut
2015-11-19 10:58         ` Anand Moon
2015-11-19 11:12           ` Marek Vasut
2015-11-19 12:49             ` Anand Moon
2015-11-19 13:12               ` Marek Vasut
2015-11-20 17:35                 ` Simon Glass
2015-11-20 17:38                   ` Marek Vasut
2015-11-21  4:10                     ` Anand Moon
2015-11-22 17:12                       ` Stephen Warren
2015-11-22 19:25                         ` Anand Moon
2015-11-21  7:27                     ` Stephen Warren
2015-11-21 16:50                       ` Simon Glass
2015-11-22 17:09                         ` Stephen Warren
2015-11-23  3:09                           ` Simon Glass
2015-11-23 17:16                             ` Stephen Warren
2015-11-25  5:30                               ` [U-Boot] [PATCH v2 " Ted Chen
2015-11-25  9:09                                 ` Anand Moon
2015-11-26 16:58                                 ` Marek Vasut
2015-11-30 22:07                                 ` Joe Hershberger
2015-12-01 11:24                                 ` [U-Boot] [PATCH v3 " Ted Chen
2015-12-01 15:10                                   ` Marek Vasut
2015-12-01 16:31                                     ` Stephen Warren
2015-12-01 17:11                                       ` Marek Vasut
2015-12-01 16:32                                   ` Simon Glass
2016-01-13 18:27                                   ` Stephen Warren
2016-01-14  4:37                                     ` [U-Boot] [PATCH v4 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER Ted Chen
2016-01-14  4:42                                       ` Marek Vasut
2016-01-14  5:22                                         ` Ted Chen [this message]
2016-01-14  5:37                                           ` Marek Vasut
2016-01-20  6:24                                             ` [U-Boot] [PATCH v5 " Ted Chen
2016-01-20 13:08                                               ` Marek Vasut
2016-01-20 16:52                                               ` Stephen Warren
2016-01-20 20:10                                                 ` Anand Moon
2016-01-20 20:34                                                   ` Marek Vasut
2016-01-21  8:55                                                     ` Anand Moon
2016-01-21 10:12                                                       ` Marek Vasut
2016-01-22 19:50                                               ` Joe Hershberger
2016-01-22 20:00                                                 ` Marek Vasut
2016-01-22 20:41                                                   ` Joe Hershberger
2016-01-23  0:42                                                     ` Marek Vasut
2016-01-23 15:23                                                       ` Marek Vasut
2016-01-23 18:55                                                         ` Anand Moon
2016-01-23 19:38                                                           ` Marek Vasut
2016-01-25  3:42                                                             ` Ted
2016-01-25  3:47                                                               ` Marek Vasut
2015-11-14  0:56 ` [U-Boot] [PATCH 1/2] checkpatch: ignore request to use ether_addr_copy() Marek Vasut
2015-11-23 23:36 ` Joe Hershberger
2015-12-15 23:34   ` Stephen Warren
2015-12-15 23:41     ` Joe Hershberger
     [not found]       ` <56969621.30204@wwwdotorg.org>
2016-01-20 20:47         ` Stephen Warren
2016-01-20 21:00           ` Tom Rini
2016-01-20 21:04             ` Stephen Warren
2016-01-21  1:22               ` Tom Rini
2016-01-21  4:09                 ` Joe Hershberger
2016-01-25 21:28 ` [U-Boot] [U-Boot, " Tom Rini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1452748927-60186-1-git-send-email-tedchen@realtek.com \
    --to=tedchen@realtek.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.