All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 1/2] checkpatch: ignore request to use ether_addr_copy()
@ 2015-11-13 16:03 Stephen Warren
  2015-11-13 16:03 ` [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver Stephen Warren
                   ` (3 more replies)
  0 siblings, 4 replies; 64+ messages in thread
From: Stephen Warren @ 2015-11-13 16:03 UTC (permalink / raw)
  To: u-boot

From: Stephen Warren <swarren@nvidia.com>

The Linux kernel, from which checkpatch originates, contains function
ether_addr_copy() to copy Ethernet MAC addresses, and checkpatch warns
that it should be used in preference to memcpy() where appropriate.
U-Boot doesn't contain ether_addr_copy(), so tell checkpatch not to issue
this warning.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 .checkpatch.conf | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/.checkpatch.conf b/.checkpatch.conf
index 35167e12015b..d1d32fac9db5 100644
--- a/.checkpatch.conf
+++ b/.checkpatch.conf
@@ -21,3 +21,7 @@
 
 # Ignore networking block comment style
 --ignore NETWORKING_BLOCK_COMMENT_STYLE
+
+# Ignore "WARNING: Prefer ether_addr_copy() over memcpy() if the Ethernet
+# addresses are __aligned(2)".
+--ignore PREFER_ETHER_ADDR_COPY
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  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 ` Stephen Warren
  2015-11-14  1:13   ` Marek Vasut
  2015-11-14  0:56 ` [U-Boot] [PATCH 1/2] checkpatch: ignore request to use ether_addr_copy() Marek Vasut
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 64+ messages in thread
From: Stephen Warren @ 2015-11-13 16:03 UTC (permalink / raw)
  To: u-boot

From: Ted Chen <tedchen@realtek.com>

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>
---
I've tested this driver on NVIDIA's Jetson TX1 (p2371-2180) board. I'm
working on the XHCI driver for that platform, and will enable this driver
on that board once the XHCI driver is sent.

 drivers/usb/eth/Makefile    |    1 +
 drivers/usb/eth/r8152.c     | 3809 +++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/eth/usb_ether.c |    8 +
 include/usb_ether.h         |    6 +
 4 files changed, 3824 insertions(+)
 create mode 100644 drivers/usb/eth/r8152.c

diff --git a/drivers/usb/eth/Makefile b/drivers/usb/eth/Makefile
index c92d2b02d261..74f5f87b9c09 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
diff --git a/drivers/usb/eth/r8152.c b/drivers/usb/eth/r8152.c
new file mode 100644
index 000000000000..7ab08bef4111
--- /dev/null
+++ b/drivers/usb/eth/r8152.c
@@ -0,0 +1,3809 @@
+/*
+ * Copyright (c) 2015 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ *
+ * This product is covered by one or more of the following patents:
+ * US6,570,884, US6,115,776, and US6,327,625.
+ */
+
+#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"
+
+#define DRIVER_VERSION "v1.0 (2015/09/17)"
+#define PATENTS		"This product is covered by one or more of the " \
+			"following patents:\n" \
+			"\t\tUS6,570,884, US6,115,776, and US6,327,625.\n"
+
+#define R8152_PHY_ID		32
+
+#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 CR_RST			0x10
+#define CR_RE			0x08
+#define 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
+
+enum rtl_register_content {
+	_1000bps	= 0x10,
+	_100bps		= 0x08,
+	_10bps		= 0x04,
+	LINK_STATUS	= 0x02,
+	FULL_DUP	= 0x01,
+};
+
+#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_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
+
+struct tally_counter {
+	__le64	tx_packets;
+	__le64	rx_packets;
+	__le64	tx_errors;
+	__le32	rx_errors;
+	__le16	rx_missed;
+	__le16	align_errors;
+	__le32	tx_one_collision;
+	__le32	tx_multi_collision;
+	__le64	rx_unicast;
+	__le64	rx_broadcast;
+	__le32	rx_multicast;
+	__le16	tx_aborted;
+	__le16	tx_underrun;
+};
+
+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)
+};
+
+struct r8152;
+
+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;
+};
+
+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
+};
+
+/* The forced speed, 10Mb, 100Mb, gigabit, [2.5|5|10|20|25|40|50|56|100]GbE. */
+#define SPEED_10                10
+#define SPEED_100               100
+#define SPEED_1000              1000
+#define SPEED_2500              2500
+#define SPEED_5000              5000
+#define SPEED_10000             10000
+#define SPEED_20000             20000
+#define SPEED_25000             25000
+#define SPEED_40000             40000
+#define SPEED_50000             50000
+#define SPEED_56000             56000
+#define SPEED_100000            100000
+
+#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 agg_buf_sz 2048
+
+/* local vars */
+static int curr_eth_dev; /* index for name of next device detected */
+
+#define R8152_BASE_NAME "r8152"
+
+
+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 },
+
+	{ 0x0000, 0x0000 }	/* END - Do not remove */
+};
+
+#define msleep(a)	udelay(a * 1000)
+#define BIT(nr)                 (1UL << (nr))
+
+static
+int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
+{
+	int ret;
+	void *tmp;
+
+	tmp = kmalloc(size, GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+
+	ret = usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0),
+			      RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
+			      value, index, tmp, size, 500);
+	if (ret < 0)
+		memset(data, 0xff, size);
+	else
+		memcpy(data, tmp, size);
+
+	kfree(tmp);
+
+	return ret;
+}
+
+static
+int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
+{
+	int ret;
+	void *tmp;
+
+	tmp = kmalloc(size, GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+
+	memcpy(tmp, data, size);
+
+	ret = usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0),
+			      RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE,
+			      value, index, tmp, size, 500);
+
+	kfree(tmp);
+	return ret;
+}
+
+static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
+			    void *data, u16 type)
+{
+	u16 limit = 64;
+	int ret = 0;
+
+	/* both size and indix must be 4 bytes align */
+	if ((size & 3) || !size || (index & 3) || !data)
+		return -EPERM;
+
+	if ((u32)index + (u32)size > 0xffff)
+		return -EPERM;
+
+	while (size) {
+		if (size > limit) {
+			ret = get_registers(tp, index, type, limit, data);
+			if (ret < 0)
+				break;
+
+			index += limit;
+			data += limit;
+			size -= limit;
+		} else {
+			ret = get_registers(tp, index, type, size, data);
+			if (ret < 0)
+				break;
+
+			index += size;
+			data += size;
+			size = 0;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
+			     u16 size, void *data, u16 type)
+{
+	int ret;
+	u16 byteen_start, byteen_end, byen;
+	u16 limit = 512;
+
+	/* both size and indix must be 4 bytes align */
+	if ((size & 3) || !size || (index & 3) || !data)
+		return -EPERM;
+
+	if ((u32)index + (u32)size > 0xffff)
+		return -EPERM;
+
+	byteen_start = byteen & BYTE_EN_START_MASK;
+	byteen_end = byteen & BYTE_EN_END_MASK;
+
+	byen = byteen_start | (byteen_start << 4);
+	ret = set_registers(tp, index, type | byen, 4, data);
+	if (ret < 0)
+		goto error1;
+
+	index += 4;
+	data += 4;
+	size -= 4;
+
+	if (size) {
+		size -= 4;
+
+		while (size) {
+			if (size > limit) {
+				ret = set_registers(tp, index,
+						    type | BYTE_EN_DWORD,
+						    limit, data);
+				if (ret < 0)
+					goto error1;
+
+				index += limit;
+				data += limit;
+				size -= limit;
+			} else {
+				ret = set_registers(tp, index,
+						    type | BYTE_EN_DWORD,
+						    size, data);
+				if (ret < 0)
+					goto error1;
+
+				index += size;
+				data += size;
+				size = 0;
+				break;
+			}
+		}
+
+		byen = byteen_end | (byteen_end >> 4);
+		ret = set_registers(tp, index, type | byen, 4, data);
+		if (ret < 0)
+			goto error1;
+	}
+
+error1:
+
+	return ret;
+}
+
+static inline
+int pla_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data)
+{
+	return generic_ocp_read(tp, index, size, data, MCU_TYPE_PLA);
+}
+
+static inline
+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);
+}
+
+static inline
+int usb_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data)
+{
+	return generic_ocp_read(tp, index, size, data, MCU_TYPE_USB);
+}
+
+static inline
+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);
+}
+
+static 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);
+}
+
+static 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);
+}
+
+static 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 (u16)data;
+}
+
+static 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);
+}
+
+static 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 (u8)data;
+}
+
+static 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);
+}
+
+static 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);
+}
+
+static 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 inline void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value)
+{
+	ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value);
+}
+
+static inline int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)
+{
+	return ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2);
+}
+
+static 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_nic_reset(struct r8152 *tp)
+{
+	int	i;
+
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, CR_RST);
+
+	for (i = 0; i < 1000; i++) {
+		if (!(ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR) & CR_RST))
+			break;
+
+		udelay(400);
+	}
+}
+
+static inline 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 |= CR_RE | 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 = (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;
+	int i;
+
+	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);
+
+	for (i = 0; i < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if ((ocp_data & FIFO_EMPTY) == FIFO_EMPTY)
+			break;
+
+		udelay(2000);
+	}
+
+	for (i = 0; i < 1000; i++) {
+		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0) & TCR0_TX_EMPTY)
+			break;
+		udelay(2000);
+	}
+
+	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 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);
+
+	udelay(6000);
+
+	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 void r8152b_firmware(struct r8152 *tp)
+{
+	if (tp->version == RTL_VER_01) {
+		int i;
+		static u8 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 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 };
+
+		patch4(tp);
+		rtl_clear_bp(tp);
+
+		generic_ocp_write(tp, 0xf800, 0x3f, sizeof(pla_patch_a),
+				  pla_patch_a, MCU_TYPE_PLA);
+
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc26, 0x8000);
+
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc28, 0x170b);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc2a, 0x01e1);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc2c, 0x0989);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc2e, 0x1349);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc30, 0x01b7);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc32, 0x061d);
+
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xe422, 0x0020);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xe420, 0x0018);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc34, 0x1785);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc36, 0x047b);
+
+		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(ram_code1); i++)
+			ocp_write_word(tp, MCU_TYPE_PLA, 0xb09a, 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) {
+		static u8 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 };
+
+		rtl_clear_bp(tp);
+
+		generic_ocp_write(tp, 0xf800, 0xff, sizeof(pla_patch_a2),
+				  pla_patch_a2, MCU_TYPE_PLA);
+
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc26, 0x8000);
+
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc28, 0x17a5);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc2a, 0x13ad);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc2c, 0x184d);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc2e, 0x01e1);
+	}
+}
+
+static int r8152_read_mac(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};
+
+	if (pla_ocp_read(tp, PLA_IDR, 8, enetaddr) < 0)
+		return -1;
+
+	memcpy(eth->enetaddr, enetaddr, ETH_ALEN);
+	return 0;
+}
+
+static void r8152b_disable_aldps(struct r8152 *tp)
+{
+	ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA | DIS_SDSAVE);
+	msleep(20);
+}
+
+static inline 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 r8152b_exit_oob(struct r8152 *tp)
+{
+	u32 ocp_data;
+	int i;
+
+	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);
+
+	for (i = 0; i < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+
+		udelay(2000);
+	}
+
+	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 < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		udelay(2000);
+	}
+
+	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;
+	int i;
+
+	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);
+
+	for (i = 0; i < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		udelay(2000);
+	}
+
+	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 < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		udelay(2000);
+	}
+
+	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 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++) {
+		udelay(2000);
+		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;
+		udelay(2000);
+	}
+}
+
+static void r8153_firmware(struct r8152 *tp)
+{
+	if (tp->version == RTL_VER_03) {
+		r8153_clear_bp(tp);
+
+		r8153_pre_ram_code(tp, 0x7000);
+		sram_write(tp, 0xb820, 0x0290);
+		sram_write(tp, 0xa012, 0x0000);
+		sram_write(tp, 0xa014, 0x2c04);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c18);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c45);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c45);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd502);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x8301);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x8306);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd500);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x8208);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd501);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xe018);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x0308);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x60f2);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x8404);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x607d);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xc117);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c16);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xc116);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c16);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x607d);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xc117);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa404);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd500);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x0800);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd501);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x62d2);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x615d);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xc115);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa404);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xc307);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd502);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x8301);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x8306);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd500);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x8208);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c42);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xc114);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x8404);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xc317);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd701);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x435d);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd500);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa208);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd502);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa306);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa301);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c42);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x8404);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x613d);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xc115);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xc307);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd502);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x8301);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x8306);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd500);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x8208);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c42);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xc114);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xc317);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd701);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x40dd);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd500);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa208);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd502);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa306);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa301);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd500);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd702);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x0800);
+		sram_write(tp, 0xa01a, 0x0000);
+		sram_write(tp, 0xa006, 0x0fff);
+		sram_write(tp, 0xa004, 0x0fff);
+		sram_write(tp, 0xa002, 0x05a3);
+		sram_write(tp, 0xa000, 0x3591);
+		sram_write(tp, 0xb820, 0x0210);
+		r8153_post_ram_code(tp);
+	} else if (tp->version == RTL_VER_04) {
+		static u8 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 u8 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 };
+
+		r8153_pre_ram_code(tp, 0x7001);
+		sram_write(tp, 0xb820, 0x0290);
+		sram_write(tp, 0xa012, 0x0000);
+		sram_write(tp, 0xa014, 0x2c04);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c07);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c0a);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c0d);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa240);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa104);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x292d);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x8620);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa480);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2a2c);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x8480);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa101);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2a36);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd056);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2223);
+		sram_write(tp, 0xa01a, 0x0000);
+		sram_write(tp, 0xa006, 0x0222);
+		sram_write(tp, 0xa004, 0x0a35);
+		sram_write(tp, 0xa002, 0x0a2b);
+		sram_write(tp, 0xa000, 0xf92c);
+		sram_write(tp, 0xb820, 0x0210);
+		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(usb_patch_b),
+				  usb_patch_b, MCU_TYPE_USB);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc26, 0xa000);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc28, 0x180c);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc2a, 0x0506);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc2c, 0x04E0);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc2e, 0x11E4);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc30, 0x125C);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc32, 0x0232);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc34, 0x131E);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc36, 0x0098);
+		ocp_write_word(tp, MCU_TYPE_USB, USB_BP_EN, 0x00FF);
+
+		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(pla_patch_b),
+				  pla_patch_b, MCU_TYPE_PLA);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc26, 0x8000);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc28, 0x1154);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc2a, 0x1606);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc2c, 0x155a);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc2e, 0x0080);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc30, 0x033c);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc32, 0x01a0);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc34, 0x0794);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc36, 0x0000);
+		ocp_write_word(tp, MCU_TYPE_PLA, PLA_BP_EN, 0x007f);
+
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xd388, 0x08ca);
+	} else if (tp->version == RTL_VER_05) {
+		u32 ocp_data;
+		static u8 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 u8 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 };
+
+		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);
+		sram_write(tp, 0xb820, 0x0290);
+		sram_write(tp, 0xa012, 0x0000);
+		sram_write(tp, 0xa014, 0x2c04);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c07);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c0a);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c0d);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa240);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa104);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x292d);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x8620);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa480);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2a2c);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x8480);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa101);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2a36);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xd056);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2223);
+		sram_write(tp, 0xa01a, 0x0000);
+		sram_write(tp, 0xa006, 0x0222);
+		sram_write(tp, 0xa004, 0x0a35);
+		sram_write(tp, 0xa002, 0x0a2b);
+		sram_write(tp, 0xa000, 0xf92c);
+		sram_write(tp, 0xb820, 0x0210);
+		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(usb_patch_c),
+				  usb_patch_c, MCU_TYPE_USB);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc26, 0xa000);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc28, 0x3b34);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc2a, 0x027c);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc2c, 0x162c);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc2e, 0x10ce);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc30, 0x0000);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc32, 0x3a28);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc34, 0x05f8);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc36, 0x05c8);
+		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(pla_patch_c),
+				  pla_patch_c, MCU_TYPE_PLA);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc26, 0x8000);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc28, 0x1306);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc2a, 0x17ca);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc2c, 0x171e);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc2e, 0x0000);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc30, 0x0000);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc32, 0x01b4);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc34, 0x07d4);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc36, 0x0894);
+		ocp_write_word(tp, MCU_TYPE_PLA, PLA_BP_EN, 0x00e7);
+
+		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) {
+		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 };
+
+		r8153_pre_ram_code(tp, 0x7002);
+		sram_write(tp, 0xb820, 0x0290);
+		sram_write(tp, 0xa012, 0x0000);
+		sram_write(tp, 0xa014, 0x2c04);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c07);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c07);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c07);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa240);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0xa104);
+		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2944);
+		sram_write(tp, 0xa01a, 0x0000);
+		sram_write(tp, 0xa006, 0x0fff);
+		sram_write(tp, 0xa004, 0x0fff);
+		sram_write(tp, 0xa002, 0x0fff);
+		sram_write(tp, 0xa000, 0x1943);
+		sram_write(tp, 0xb820, 0x0210);
+		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);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc26, 0xa000);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc28, 0x0000);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc2a, 0x0000);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc2c, 0x1792);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc2e, 0x1236);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc30, 0x0000);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc32, 0x0000);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc34, 0x0000);
+		ocp_write_word(tp, MCU_TYPE_USB, 0xfc36, 0x0000);
+		ocp_write_word(tp, MCU_TYPE_USB, USB_BP_EN, 0x000c);
+	}
+}
+
+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;
+	int i;
+
+	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);
+
+	for (i = 0; i < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		udelay(2000);
+	}
+
+	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 < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		udelay(2000);
+	}
+
+	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;
+	int i;
+
+	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);
+
+	for (i = 0; i < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		udelay(2000);
+	}
+
+	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 < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		udelay(2000);
+	}
+
+	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);
+	msleep(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;
+	int ret = 0;
+
+	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 {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		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 {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		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);
+out:
+
+	return ret;
+}
+
+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;
+		msleep(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;
+		msleep(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 = 0;
+
+	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;
+#define TIMEOUT_RESOLUTION 50	/* ms */
+#define PHY_CONNECT_TIMEOUT 5000
+	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... ");
+			udelay(TIMEOUT_RESOLUTION * 1000);
+			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;
+
+#define USB_BULK_SEND_TIMEOUT 5000
+
+	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 = %lu, 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[agg_buf_sz];
+	unsigned char *pkt_ptr;
+	int err;
+	int actual_len;
+	u16 packet_len;
+
+	u32 bytes_process = 0;
+
+	struct rx_desc *rx_desc;
+
+#define USB_BULK_RECV_TIMEOUT 5000
+
+	debug("** %s()\n", __func__);
+
+	err = usb_bulk_msg(dev->pusb_dev,
+				usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in),
+				(void *)recv_buf,
+				agg_buf_sz,
+				&actual_len,
+				USB_BULK_RECV_TIMEOUT);
+	debug("Rx: len = %u, actual = %u, err = %d\n", agg_buf_sz,
+	      actual_len, err);
+	if (err != 0) {
+		debug("Rx: failed to receive\n");
+		return -1;
+	}
+	if (actual_len > 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);
+
+	printf("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 asix 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; r8152_dongles[i].vendor != 0; 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) {
+				if (!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(eth) < 0)
+		return 0;
+
+	debug("MAC %pM\n", eth->enetaddr);
+	return 1;
+}
diff --git a/drivers/usb/eth/usb_ether.c b/drivers/usb/eth/usb_ether.c
index 3c3e082b278b..e0e1277bf706 100644
--- a/drivers/usb/eth/usb_ether.c
+++ b/drivers/usb/eth/usb_ether.c
@@ -180,6 +180,14 @@ 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 c6d1416048a1..51fce4e95dc5 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.9.1

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 1/2] checkpatch: ignore request to use ether_addr_copy()
  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  0:56 ` Marek Vasut
  2015-11-23 23:36 ` Joe Hershberger
  2016-01-25 21:28 ` [U-Boot] [U-Boot, " Tom Rini
  3 siblings, 0 replies; 64+ messages in thread
From: Marek Vasut @ 2015-11-14  0:56 UTC (permalink / raw)
  To: u-boot

On Friday, November 13, 2015 at 05:03:00 PM, Stephen Warren wrote:
> From: Stephen Warren <swarren@nvidia.com>
> 
> The Linux kernel, from which checkpatch originates, contains function
> ether_addr_copy() to copy Ethernet MAC addresses, and checkpatch warns
> that it should be used in preference to memcpy() where appropriate.
> U-Boot doesn't contain ether_addr_copy(), so tell checkpatch not to issue
> this warning.
> 
> Signed-off-by: Stephen Warren <swarren@nvidia.com>

Reviewed-by: Marek Vasut <marex@denx.de>

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  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
  0 siblings, 1 reply; 64+ messages in thread
From: Marek Vasut @ 2015-11-14  1:13 UTC (permalink / raw)
  To: u-boot

On Friday, November 13, 2015 at 05:03:01 PM, Stephen Warren wrote:
> From: Ted Chen <tedchen@realtek.com>

Hi,

> 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>

[...]

> new file mode 100644
> index 000000000000..7ab08bef4111
> --- /dev/null
> +++ b/drivers/usb/eth/r8152.c
> @@ -0,0 +1,3809 @@
> +/*
> + * Copyright (c) 2015 Realtek Semiconductor Corp. All rights reserved.
> + *
> + * SPDX-License-Identifier:	GPL-2.0
> + *
> + * This product is covered by one or more of the following patents:
> + * US6,570,884, US6,115,776, and US6,327,625.

Why do we even care, does this have any significance ?

> + */
> +
> +#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"
> +
> +#define DRIVER_VERSION "v1.0 (2015/09/17)"

This macro is unused, please remove it.

> +#define PATENTS		"This product is covered by one or more of the " 
\
> +			"following patents:\n" \
> +			"\t\tUS6,570,884, US6,115,776, and US6,327,625.\n"

DTTO

[...]

> +/* 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 */

Should be min((x).....) , the x should be in parenthesis, please fix globally.

> +#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 */

DTTO.

> +#define RG_LFS_SEL		0x0060	/* bit 6 ~ 5 */
> +#define MSK_PH			0x0006	/* bit 0 ~ 3 */

[...]

> +struct tally_counter {
> +	__le64	tx_packets;

Shouldn't this be standard u64 ?

> +	__le64	rx_packets;
> +	__le64	tx_errors;
> +	__le32	rx_errors;
> +	__le16	rx_missed;
> +	__le16	align_errors;
> +	__le32	tx_one_collision;
> +	__le32	tx_multi_collision;
> +	__le64	rx_unicast;
> +	__le64	rx_broadcast;
> +	__le32	rx_multicast;
> +	__le16	tx_aborted;
> +	__le16	tx_underrun;
> +};

[...]

> +struct r8152;

This forward declaration can be removed.

> +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;
> +};

[...]

> +#define agg_buf_sz 2048
> +
> +/* local vars */
> +static int curr_eth_dev; /* index for name of next device detected */

Shouldn't we remove this for the sake of using DM ?

> +#define R8152_BASE_NAME "r8152"
> +
> +
> +struct r8152_dongle {
> +	unsigned short vendor;
> +	unsigned short product;
> +};

[...]

> +#define msleep(a)	udelay(a * 1000)

That's called mdelay(), so please remove this and use mdelay()

> +#define BIT(nr)                 (1UL << (nr))

Don't we have a generic declaration of this bit macro ?

> +static
> +int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void
> *data) +{
> +	int ret;
> +	void *tmp;
> +
> +	tmp = kmalloc(size, GFP_KERNEL);
> +	if (!tmp)
> +		return -ENOMEM;

Allocating the structure on stack would be faster than doing this
malloc-free dance, right? Please fix globally.

> +	ret = usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0),
> +			      RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
> +			      value, index, tmp, size, 500);
> +	if (ret < 0)
> +		memset(data, 0xff, size);
> +	else
> +		memcpy(data, tmp, size);
> +
> +	kfree(tmp);
> +
> +	return ret;
> +}

[...]

> +static int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
> +			     u16 size, void *data, u16 type)
> +{
> +	int ret;
> +	u16 byteen_start, byteen_end, byen;
> +	u16 limit = 512;
> +
> +	/* both size and indix must be 4 bytes align */
> +	if ((size & 3) || !size || (index & 3) || !data)
> +		return -EPERM;
> +
> +	if ((u32)index + (u32)size > 0xffff)

Please review unnecessary typecast before next submission and remove them.

> +		return -EPERM;
> +
> +	byteen_start = byteen & BYTE_EN_START_MASK;
> +	byteen_end = byteen & BYTE_EN_END_MASK;
> +
> +	byen = byteen_start | (byteen_start << 4);
> +	ret = set_registers(tp, index, type | byen, 4, data);
> +	if (ret < 0)
> +		goto error1;
> +
> +	index += 4;
> +	data += 4;
> +	size -= 4;

[...]

> +static void rtl_disable(struct r8152 *tp)
> +{
> +	u32 ocp_data;
> +	int i;
> +
> +	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);
> +
> +	for (i = 0; i < 1000; i++) {
> +		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +		if ((ocp_data & FIFO_EMPTY) == FIFO_EMPTY)
> +			break;
> +
> +		udelay(2000);
> +	}

Is this a poor-man's attempt at implementing wait-for-bit sort of functionality?
If so, I'm concerned about the case where that bit is never set/unset, since 
this case is not handled by the code.

Also, you can fix udelay(2000) to mdelay(2), but this sort of wait-for-bit 
should prefferably use get_timer() instead.

> +	for (i = 0; i < 1000; i++) {
> +		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0) & TCR0_TX_EMPTY)
> +			break;
> +		udelay(2000);
> +	}
> +
> +	rtl8152_nic_reset(tp);
> +}

[...]

> +static void r8152b_firmware(struct r8152 *tp)
> +{
> +	if (tp->version == RTL_VER_01) {
> +		int i;
> +		static u8 pla_patch_a[] = {
> +			0x08, 0xe0, 0x40, 0xe0,
> +			0x78, 0xe0, 0x85, 0xe0,

[...]

I think it might be better to pull this firmware blob into either a separate 
header file or into global variable. Also, it would make sense to reformat
this array such that there would be more elements on a line (8 or 16), so
that the declaration makes better use of horizontal space.

> +			0x00, 0x00, 0x02, 0xc6,
> +			0x00, 0xbe, 0x00, 0x00,
> +			0x00, 0x00, 0x00, 0x00 };
> +
> +		rtl_clear_bp(tp);
> +
> +		generic_ocp_write(tp, 0xf800, 0xff, sizeof(pla_patch_a2),
> +				  pla_patch_a2, MCU_TYPE_PLA);
> +
> +		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc26, 0x8000);
> +
> +		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc28, 0x17a5);
> +		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc2a, 0x13ad);
> +		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc2c, 0x184d);
> +		ocp_write_word(tp, MCU_TYPE_PLA, 0xfc2e, 0x01e1);
> +	}
> +}

[...]

> +static void r8153_firmware(struct r8152 *tp)
> +{
> +	if (tp->version == RTL_VER_03) {
> +		r8153_clear_bp(tp);
> +
> +		r8153_pre_ram_code(tp, 0x7000);
> +		sram_write(tp, 0xb820, 0x0290);
> +		sram_write(tp, 0xa012, 0x0000);
> +		sram_write(tp, 0xa014, 0x2c04);
> +		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c18);
> +		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c45);
> +		ocp_write_word(tp, MCU_TYPE_PLA, 0xb438, 0x2c45);

DTTO here, a nice loop over an array would be helpful.

[...]

> +		ocp_write_word(tp, MCU_TYPE_USB, 0xfc32, 0x0000);
> +		ocp_write_word(tp, MCU_TYPE_USB, 0xfc34, 0x0000);
> +		ocp_write_word(tp, MCU_TYPE_USB, 0xfc36, 0x0000);
> +		ocp_write_word(tp, MCU_TYPE_USB, USB_BP_EN, 0x000c);
> +	}
> +}

[...]

The beginning looked really crude, but the rest of the driver looked much
better then. Thanks!

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-14  1:13   ` Marek Vasut
@ 2015-11-16 17:32     ` Stephen Warren
  2015-11-17  7:18       ` Ted
  0 siblings, 1 reply; 64+ messages in thread
From: Stephen Warren @ 2015-11-16 17:32 UTC (permalink / raw)
  To: u-boot

On 11/13/2015 06:13 PM, Marek Vasut wrote:
> On Friday, November 13, 2015 at 05:03:01 PM, Stephen Warren wrote:
>> From: Ted Chen <tedchen@realtek.com>

Ted, are you able to update the driver to address Marek's comments? If 
so, that would be great. Otherwise let me know and I'll try to take a 
stab. Thanks.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-16 17:32     ` Stephen Warren
@ 2015-11-17  7:18       ` Ted
  2015-11-17  8:04         ` Marek Vasut
                           ` (2 more replies)
  0 siblings, 3 replies; 64+ messages in thread
From: Ted @ 2015-11-17  7:18 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

I am investigating how to modify this driver by Marek's comments, and will send you new patch ASAP.

Thanks~

BRs
Ted

________________________________________
?: Stephen Warren [swarren at wwwdotorg.org]
????: 2015?11?17? ?? 01:32
?: Ted
??: Marek Vasut; u-boot at lists.denx.de; Joe Hershberger; Stephen Warren; Wolfgang Denk
??: Re: [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver

On 11/13/2015 06:13 PM, Marek Vasut wrote:
> On Friday, November 13, 2015 at 05:03:01 PM, Stephen Warren wrote:
>> From: Ted Chen <tedchen@realtek.com>

Ted, are you able to update the driver to address Marek's comments? If
so, that would be great. Otherwise let me know and I'll try to take a
stab. Thanks.

------Please consider the environment before printing this e-mail.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-17  7:18       ` Ted
@ 2015-11-17  8:04         ` Marek Vasut
  2015-11-19  6:07         ` Anand Moon
  2015-11-19 10:58         ` Anand Moon
  2 siblings, 0 replies; 64+ messages in thread
From: Marek Vasut @ 2015-11-17  8:04 UTC (permalink / raw)
  To: u-boot

On Tuesday, November 17, 2015 at 08:18:17 AM, Ted wrote:
> Hi Stephen,
> 
> I am investigating how to modify this driver by Marek's comments, and will
> send you new patch ASAP.

Thanks!

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  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 10:58         ` Anand Moon
  2 siblings, 1 reply; 64+ messages in thread
From: Anand Moon @ 2015-11-19  6:07 UTC (permalink / raw)
  To: u-boot

Hi Ted/Stephen,

On Tuesday, November 17, 2015 12:48 PM, Ted <tedchen@realtek.com> wrote:


Hi Stephen,

I am investigating how to modify this driver by Marek's comments, and will send you new patch ASAP.

Thanks~

BRs
Ted

________________________________________
?: Stephen Warren [swarren at wwwdotorg.org]
????: 2015?11?17? ?? 01:32
?: Ted
??: Marek Vasut; u-boot at lists.denx.de; Joe Hershberger; Stephen Warren; Wolfgang Denk
??: Re: [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver

On 11/13/2015 06:13 PM, Marek Vasut wrote:
> On Friday, November 13, 2015 at 05:03:01 PM, Stephen Warren wrote:
>> From: Ted Chen <tedchen@realtek.com>

Ted, are you able to update the driver to address Marek's comments? If
so, that would be great. Otherwise let me know and I'll try to take a
stab. Thanks.


------------------------------------------------------------------
Actually this driver is also need for Odroid XU4 development boards.

Just for testing integrate this driver with u-boot.

Actually I have tried to compile this driver with u-boot mainline.
But their also I am not able to get the Ethernet working on u-boot.

What could be missing in the driver ?

Is this device compatible with USB 2.0 EHCI host drivers or it requires USB 3.0 XHCI host drivers.

---------------------------------------------------------
ODROID-XU3 # setenv ethaddr 00:10:75:2A:AE:E0
ODROID-XU3 # setenv gatewayip 10.0.0.1
ODROID-XU3 # setenv netmask 255.255.255.0
ODROID-XU3 # setenv serverip 10.0.0.102
ODROID-XU3 # setenv ipaddr 10.0.0.105
ODROID-XU3 # usb start
ODROID-XU3 # usb info
1: Hub, USB Revision 2.0
- u-boot EHCI Host Controller
- Class: Hub
- PacketSize: 64 Configurations: 1
- Vendor: 0x0000 Product 0x0000 Version 1.0
Configuration: 1
- Interfaces: 1 Self Powered 0mA
Interface: 0
- Alternate Setting 0, Endpoints: 1
- Class Hub
- Endpoint 1 In Interrupt MaxPacket 8 Interval 255ms

1: Hub, USB Revision 3.0
- U-Boot XHCI Host Controller
- Class: Hub
- PacketSize: 9 Configurations: 1
- Vendor: 0x0000 Product 0x0000 Version 1.0
Configuration: 1
- Interfaces: 1 Self Powered 0mA
Interface: 0
- Alternate Setting 0, Endpoints: 1
- Class Hub
- Endpoint 1 In Interrupt MaxPacket 8 Interval 255ms

2: Hub, USB Revision 2.10
- GenesysLogic USB2.0 Hub
- Class: Hub
- PacketSize: 64 Configurations: 1
- Vendor: 0x05e3 Product 0x0610 Version 146.34
Configuration: 1
- Interfaces: 1 Self Powered Remote Wakeup 100mA
Interface: 0
- Alternate Setting 0, Endpoints: 1
- Class Hub
- Endpoint 1 In Interrupt MaxPacket 1 Interval 12ms
- Endpoint 1 In Interrupt MaxPacket 1 Interval 12ms

1: Hub, USB Revision 3.0
- U-Boot XHCI Host Controller
- Class: Hub
- PacketSize: 9 Configurations: 1
- Vendor: 0x0000 Product 0x0000 Version 1.0
Configuration: 1
- Interfaces: 1 Self Powered 0mA
Interface: 0
- Alternate Setting 0, Endpoints: 1
- Class Hub
- Endpoint 1 In Interrupt MaxPacket 8 Interval 255ms

2: Vendor specific, USB Revision 2.10
- Realtek USB 10/100/1000 LAN 000001000000
- Class: (from Interface) Vendor specific
- PacketSize: 64 Configurations: 2
- Vendor: 0x0bda Product 0x8153 Version 48.0
Configuration: 1
- Interfaces: 1 Bus Powered Remote Wakeup 180mA
Interface: 0
- Alternate Setting 0, Endpoints: 3
- Class Vendor specific
- Endpoint 1 In Bulk MaxPacket 512
- Endpoint 2 Out Bulk MaxPacket 512
- Endpoint 3 In Interrupt MaxPacket 2 Interval 8ms

ODROID-XU3 # tftpboot 0x40080000 zImage
No ethernet found.
ODROID-XU3 #

-Anand Moon
------Please consider the environment before printing this e-mail.
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-17  7:18       ` Ted
  2015-11-17  8:04         ` Marek Vasut
  2015-11-19  6:07         ` Anand Moon
@ 2015-11-19 10:58         ` Anand Moon
  2015-11-19 11:12           ` Marek Vasut
  2 siblings, 1 reply; 64+ messages in thread
From: Anand Moon @ 2015-11-19 10:58 UTC (permalink / raw)
  To: u-boot

Hi Ted, Stephen,





On Tuesday, November 17, 2015 12:48 PM, Ted <tedchen@realtek.com> wrote:
Hi Stephen,

I am investigating how to modify this driver by Marek's comments, and will send you new patch ASAP.

Thanks~

BRs
Ted

----------------------------------------

Just wanted to share why this device is failed to initialize of Odroid XU4.

U-boot logs.
---------------------------------------------------

USB Ethernet device detected: 0xbda:0x8153
Endpoints In 1 Out 2 Int 3
Setup ERROR: address device command for slot 1.
Unknown version 0x7cf0
Unknown Device
---------------------------------------------------

What could be the reason for this failure.
My guess is that the firmware is not initialize for this device.

Please correct me if I am wrong.

-Anand Moon
________________________________________
?: Stephen Warren [swarren at wwwdotorg.org]
????: 2015?11?17? ?? 01:32
?: Ted
??: Marek Vasut; u-boot at lists.denx.de; Joe Hershberger; Stephen Warren; Wolfgang Denk
??: Re: [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver

On 11/13/2015 06:13 PM, Marek Vasut wrote:
> On Friday, November 13, 2015 at 05:03:01 PM, Stephen Warren wrote:
>> From: Ted Chen <tedchen@realtek.com>

Ted, are you able to update the driver to address Marek's comments? If
so, that would be great. Otherwise let me know and I'll try to take a
stab. Thanks.

------Please consider the environment before printing this e-mail.
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-19 10:58         ` Anand Moon
@ 2015-11-19 11:12           ` Marek Vasut
  2015-11-19 12:49             ` Anand Moon
  0 siblings, 1 reply; 64+ messages in thread
From: Marek Vasut @ 2015-11-19 11:12 UTC (permalink / raw)
  To: u-boot

On Thursday, November 19, 2015 at 11:58:26 AM, Anand Moon wrote:
> Hi Ted, Stephen,
> 
> 
> 
> 
> 
> On Tuesday, November 17, 2015 12:48 PM, Ted <tedchen@realtek.com> wrote:
> Hi Stephen,
> 
> I am investigating how to modify this driver by Marek's comments, and will
> send you new patch ASAP.
> 
> Thanks~
> 
> BRs
> Ted
> 
> ----------------------------------------
> 
> Just wanted to share why this device is failed to initialize of Odroid XU4.
> 
> U-boot logs.
> ---------------------------------------------------
> 
> USB Ethernet device detected: 0xbda:0x8153
> Endpoints In 1 Out 2 Int 3

Hi,

since this thread is a total fucking mess, I will just reply at random
position. Please read:

http://www.arm.linux.org.uk/mailinglists/etiquette.php#e3

> Setup ERROR: address device command for slot 1.
> Unknown version 0x7cf0
> Unknown Device
> ---------------------------------------------------
> 
> What could be the reason for this failure.
> My guess is that the firmware is not initialize for this device.
> 
> Please correct me if I am wrong.
> 
> -Anand Moon
> ________________________________________
> ?: Stephen Warren [swarren at wwwdotorg.org]
> ????: 2015?11?17? ?? 01:32
> ?: Ted
> ??: Marek Vasut; u-boot at lists.denx.de; Joe Hershberger; Stephen Warren;
> Wolfgang Denk ??: Re: [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153
> driver
> 
> On 11/13/2015 06:13 PM, Marek Vasut wrote:
> > On Friday, November 13, 2015 at 05:03:01 PM, Stephen Warren wrote:
> >> From: Ted Chen <tedchen@realtek.com>
> 
> Ted, are you able to update the driver to address Marek's comments? If
> so, that would be great. Otherwise let me know and I'll try to take a
> stab. Thanks.
> 
> ------Please consider the environment before printing this e-mail.
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-19 11:12           ` Marek Vasut
@ 2015-11-19 12:49             ` Anand Moon
  2015-11-19 13:12               ` Marek Vasut
  0 siblings, 1 reply; 64+ messages in thread
From: Anand Moon @ 2015-11-19 12:49 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On 19 November 2015 at 16:42, Marek Vasut <marex@denx.de> wrote:

> On Thursday, November 19, 2015 at 11:58:26 AM, Anand Moon wrote:
> > Hi Ted, Stephen,
> >
> >
> >
> >
> >
> > On Tuesday, November 17, 2015 12:48 PM, Ted <tedchen@realtek.com> wrote:
> > Hi Stephen,
> >
> > I am investigating how to modify this driver by Marek's comments, and
> will
> > send you new patch ASAP.
> >
> > Thanks~
> >
> > BRs
> > Ted
> >
> > ----------------------------------------
> >
> > Just wanted to share why this device is failed to initialize of Odroid
> XU4.
> >
> > U-boot logs.
> > ---------------------------------------------------
> >
> > USB Ethernet device detected: 0xbda:0x8153
> > Endpoints In 1 Out 2 Int 3
>
> Hi,
>
> since this thread is a total fucking mess, I will just reply at random
> position. Please read:
>
> ??
> http://www.arm.linux.org.uk/mailinglists/etiquette.php#e3
>
> > Setup ERROR: address device command for slot 1.
> > Unknown version 0x7cf0
> > Unknown Device
> > ---------------------------------------------------
> >
> > What could be the reason for this failure.
> > My guess is that the firmware is not initialize for this device.
> >
> > Please correct me if I am wrong.
> >
> > -Anand Moon
> > ________________________________________
> > ?: Stephen Warren [swarren at wwwdotorg.org]
> > ????: 2015?11?17? ?? 01:32
> > ?: Ted
> > ??: Marek Vasut; u-boot at lists.denx.de; Joe Hershberger; Stephen Warren;
> > Wolfgang Denk ??: Re: [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153
> > driver
> >
> > On 11/13/2015 06:13 PM, Marek Vasut wrote:
> > > On Friday, November 13, 2015 at 05:03:01 PM, Stephen Warren wrote:
> > >> From: Ted Chen <tedchen@realtek.com>
> >
> > Ted, are you able to update the driver to address Marek's comments? If
> > so, that would be great. Otherwise let me know and I'll try to take a
> > stab. Thanks.
> >
> > ------Please consider the environment before printing this e-mail.
> > _______________________________________________
> > U-Boot mailing list
> > U-Boot at lists.denx.de
> > http://lists.denx.de/mailman/listinfo/u-boot
>
> Best regards,
> Marek Vasut
>


?Sorry for the mess: Please accept my apology, I will not in the future.

-Anand Moon

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-19 12:49             ` Anand Moon
@ 2015-11-19 13:12               ` Marek Vasut
  2015-11-20 17:35                 ` Simon Glass
  0 siblings, 1 reply; 64+ messages in thread
From: Marek Vasut @ 2015-11-19 13:12 UTC (permalink / raw)
  To: u-boot

On Thursday, November 19, 2015 at 01:49:16 PM, Anand Moon wrote:
> Hi Marek,

Hi!

[...]

> ?Sorry for the mess: Please accept my apology, I will not in the future.

Cool, thanks! :)

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  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
  0 siblings, 2 replies; 64+ messages in thread
From: Stephen Warren @ 2015-11-19 16:51 UTC (permalink / raw)
  To: u-boot

On 11/18/2015 11:07 PM, Anand Moon wrote:
> Hi Ted/Stephen,

(trimming a lot of the email to try and fit my reply into an 
intelligible place)

> Actually this driver is also need for Odroid XU4 development boards.
>
> Just for testing integrate this driver with u-boot.
>
> Actually I have tried to compile this driver with u-boot mainline.
> But their also I am not able to get the Ethernet working on u-boot.
>
> What could be missing in the driver ?
>
> Is this device compatible with USB 2.0 EHCI host drivers or it requires USB 3.0 XHCI host drivers.

It should work with any USB controller that implements both control and 
data transfers. I'm using it with what is essentially a USB2 (non-EHCI) 
controller at present.

> ODROID-XU3 # usb start
> ODROID-XU3 # usb info

The fact that your "usb start" didn't print anything at all is a bit 
odd. Had you run "usb start" before that point? If so, you should have 
quoted the output from the first run instead. You could also run "usb 
reset" to force a re-enumeration. I'd expect something like the 
following to be printed (albeit with different driver names)

Tegra210 (P2371-2180) # usb start
starting USB...
USB0:   USB EHCI 1.10
scanning bus 0 for devices... 2 USB Device(s) found
        scanning usb for storage devices... 0 Storage Device(s) found
        scanning usb for ethernet devices...
Warning: asx0 using MAC address from net device
1 Ethernet Device(s) found


The fact that "usb info" shows the device is a good start; USB 
communication is obviously working. Perhaps you simply don't have the 
right config options enabled for base networking support, and/or the 
RTL8152 driver, or similar? I have at least the following set in 
include/configs/p2371-2180.h:

#define CONFIG_USB_HOST_ETHER
#define CONFIG_USB_ETHER_ASIX
#define CONFIG_USB_ETHER_RTL8152

as well as the typical "defaults" headers. "DM" etc. is enabled in 
arch/arm/mach-tegra/Kconfig.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-19 16:51           ` Stephen Warren
@ 2015-11-19 17:00             ` Lukasz Majewski
  2015-11-19 17:00             ` Marek Vasut
  1 sibling, 0 replies; 64+ messages in thread
From: Lukasz Majewski @ 2015-11-19 17:00 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

> On 11/18/2015 11:07 PM, Anand Moon wrote:
> > Hi Ted/Stephen,
> 
> (trimming a lot of the email to try and fit my reply into an 
> intelligible place)
> 
> > Actually this driver is also need for Odroid XU4 development boards.
> >
> > Just for testing integrate this driver with u-boot.
> >
> > Actually I have tried to compile this driver with u-boot mainline.
> > But their also I am not able to get the Ethernet working on u-boot.
> >
> > What could be missing in the driver ?
> >
> > Is this device compatible with USB 2.0 EHCI host drivers or it
> > requires USB 3.0 XHCI host drivers.
> 
> It should work with any USB controller that implements both control
> and data transfers. I'm using it with what is essentially a USB2
> (non-EHCI) controller at present.
> 
> > ODROID-XU3 # usb start
> > ODROID-XU3 # usb info
> 

On the Odroid XU3 there is the bug (after switching to DM). which causes
the USB1 hub (to which ETH is connected) to not be powered.

The "temporary" solution is to run "usb start" and "usb reset"
afterwards.

So you need to run:
"usb start"
"usb reset"
"usb info"

I'm working on this issue now.

> The fact that your "usb start" didn't print anything at all is a bit 
> odd. Had you run "usb start" before that point? If so, you should
> have quoted the output from the first run instead. You could also run
> "usb reset" to force a re-enumeration. I'd expect something like the 
> following to be printed (albeit with different driver names)
> 
> Tegra210 (P2371-2180) # usb start
> starting USB...
> USB0:   USB EHCI 1.10
> scanning bus 0 for devices... 2 USB Device(s) found
>         scanning usb for storage devices... 0 Storage Device(s) found
>         scanning usb for ethernet devices...
> Warning: asx0 using MAC address from net device
> 1 Ethernet Device(s) found
> 
> 
> The fact that "usb info" shows the device is a good start; USB 
> communication is obviously working. Perhaps you simply don't have the 
> right config options enabled for base networking support, and/or the 
> RTL8152 driver, or similar? I have at least the following set in 
> include/configs/p2371-2180.h:
> 
> #define CONFIG_USB_HOST_ETHER
> #define CONFIG_USB_ETHER_ASIX
> #define CONFIG_USB_ETHER_RTL8152
> 
> as well as the typical "defaults" headers. "DM" etc. is enabled in 
> arch/arm/mach-tegra/Kconfig.
> 



-- 
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-19 16:51           ` Stephen Warren
  2015-11-19 17:00             ` Lukasz Majewski
@ 2015-11-19 17:00             ` Marek Vasut
  1 sibling, 0 replies; 64+ messages in thread
From: Marek Vasut @ 2015-11-19 17:00 UTC (permalink / raw)
  To: u-boot

On Thursday, November 19, 2015 at 05:51:53 PM, Stephen Warren wrote:

[...]

> > ODROID-XU3 # usb start
> > ODROID-XU3 # usb info
> 
> The fact that your "usb start" didn't print anything at all is a bit
> odd. Had you run "usb start" before that point? If so, you should have
> quoted the output from the first run instead. You could also run "usb
> reset" to force a re-enumeration. I'd expect something like the
> following to be printed (albeit with different driver names)

I think USB start on either DM-enable or DM-disabled configuration doesn't
print anything. You can try usb tree if you want to be sure.

> Tegra210 (P2371-2180) # usb start
> starting USB...
> USB0:   USB EHCI 1.10
> scanning bus 0 for devices... 2 USB Device(s) found
>         scanning usb for storage devices... 0 Storage Device(s) found
>         scanning usb for ethernet devices...
> Warning: asx0 using MAC address from net device
> 1 Ethernet Device(s) found
> 
> 
> The fact that "usb info" shows the device is a good start; USB
> communication is obviously working. Perhaps you simply don't have the
> right config options enabled for base networking support, and/or the
> RTL8152 driver, or similar? I have at least the following set in
> include/configs/p2371-2180.h:
> 
> #define CONFIG_USB_HOST_ETHER
> #define CONFIG_USB_ETHER_ASIX
> #define CONFIG_USB_ETHER_RTL8152
> 
> as well as the typical "defaults" headers. "DM" etc. is enabled in
> arch/arm/mach-tegra/Kconfig.

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-19 13:12               ` Marek Vasut
@ 2015-11-20 17:35                 ` Simon Glass
  2015-11-20 17:38                   ` Marek Vasut
  0 siblings, 1 reply; 64+ messages in thread
From: Simon Glass @ 2015-11-20 17:35 UTC (permalink / raw)
  To: u-boot

Hi,

On 19 November 2015 at 06:12, Marek Vasut <marex@denx.de> wrote:
> On Thursday, November 19, 2015 at 01:49:16 PM, Anand Moon wrote:
>> Hi Marek,
>
> Hi!
>
> [...]
>
>> Sorry for the mess: Please accept my apology, I will not in the future.
>
> Cool, thanks! :)

This driver should use driver model, right?

Regards,
Simon

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-20 17:35                 ` Simon Glass
@ 2015-11-20 17:38                   ` Marek Vasut
  2015-11-21  4:10                     ` Anand Moon
  2015-11-21  7:27                     ` Stephen Warren
  0 siblings, 2 replies; 64+ messages in thread
From: Marek Vasut @ 2015-11-20 17:38 UTC (permalink / raw)
  To: u-boot

On Friday, November 20, 2015 at 06:35:41 PM, Simon Glass wrote:
> Hi,

Hi,

> On 19 November 2015 at 06:12, Marek Vasut <marex@denx.de> wrote:
> > On Thursday, November 19, 2015 at 01:49:16 PM, Anand Moon wrote:
> >> Hi Marek,
> > 
> > Hi!
> > 
> > [...]
> > 
> >> Sorry for the mess: Please accept my apology, I will not in the future.
> > 
> > Cool, thanks! :)
> 
> This driver should use driver model, right?

Of course.

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-20 17:38                   ` Marek Vasut
@ 2015-11-21  4:10                     ` Anand Moon
  2015-11-22 17:12                       ` Stephen Warren
  2015-11-21  7:27                     ` Stephen Warren
  1 sibling, 1 reply; 64+ messages in thread
From: Anand Moon @ 2015-11-21  4:10 UTC (permalink / raw)
  To: u-boot

Hi All,

On 20 November 2015 at 23:08, Marek Vasut <marex@denx.de> wrote:

> On Friday, November 20, 2015 at 06:35:41 PM, Simon Glass wrote:
> > Hi,
>
> Hi,
>
> > On 19 November 2015 at 06:12, Marek Vasut <marex@denx.de> wrote:
> > > On Thursday, November 19, 2015 at 01:49:16 PM, Anand Moon wrote:
> > >> Hi Marek,
> > >
> > > Hi!
> > >
> > > [...]
> > >
> > >> Sorry for the mess: Please accept my apology, I will not in the
> future.
> > >
> > > Cool, thanks! :)
> >
> > This driver should use driver model, right?
>
> Of course.
>
> Best regards,
> Marek Vasut
>

?I have just patch the driver and enable the driver.

diff --git a/include/configs/exynos5-common.h
b/include/configs/exynos5-common.h
index 4866836..7ff277f 100644
--- a/include/configs/exynos5-common.h
+++ b/include/configs/exynos5-common.h
@@ -174,6 +174,9 @@
 #define CONFIG_USB_HOST_ETHER
 #define CONFIG_USB_ETHER_ASIX
 #define CONFIG_USB_ETHER_SMSC95XX
+/* support Realtek RTL8152B/RTL8153 driver */
+#define CONFIG_USB_ETHER_RTL8152
+#define CONFIG_USB_ETHER_ASIX88179

 /* USB boot mode */
 #define CONFIG_USB_BOOTING
--------------------------------------
After doing 'usb start' and 'usb reset'

I have tested with ASIX88179 USB 3.0 Ethernet cable and the u-boot
successfully detected the device.
My fried also tested with RTL8152 USB 3.0 Ethernet cable and the u-boot
successfully detected the device.
But with this driver I am not able to detect the Ethernet USB3.0 RT8153-VB
connected to the OdroidXU4 board.

Below is the console log of u-boot.
--------------------------------------
?

?U-Boot 2015.10-25167-g439fcb9-dirty (Nov 21 2015 - 14:27:19 +1030) for
ODROID-XU3

CPU:   Exynos5422 @ 800 MHz
Model: Odroid XU3 based on EXYNOS5422
Board: Odroid XU3 based on EXYNOS5422
Type:  xu4
DRAM:  2 GiB
__of_translate_address: Bad cell count for gpx0
MMC:   EXYNOS DWMMC: 0, EXYNOS DWMMC: 1
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   No ethernet found.
Hit any key to stop autoboot:  0
ODROID-XU3 #
ODROID-XU3 #
ODROID-XU3 #
ODROID-XU3 # setenv ethaddr 00:10:75:2A:AE:E0
ODROID-XU3 # setenv gatewayip 10.0.0.1
ODROID-XU3 # setenv serverip 10.0.0.102
ODROID-XU3 # usb start
starting USB...
USB0:   USB EHCI 1.00
USB1:   Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.00
USB2:   Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.00
scanning bus 0 for devices... 1 USB Device(s) found
scanning bus 1 for devices... 2 USB Device(s) found
scanning bus 2 for devices... 2 USB Device(s) found
       scanning usb for ethernet devices...

USB Ethernet device detected: 0xbda:0x8153
Endpoints In 1 Out 2 Int 3
Setup ERROR: address device command for slot 1.
Unknown version 0x7cf0
Unknown Device
0 Ethernet Device(s) found
ODROID-XU3 # usb reset
resetting USB...
USB0:   USB EHCI 1.00
USB1:   Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.00
USB2:   Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.00
scanning bus 0 for devices... 1 USB Device(s) found
scanning bus 1 for devices... 2 USB Device(s) found
scanning bus 2 for devices... 2 USB Device(s) found
       scanning usb for ethernet devices...

USB Ethernet device detected: 0xbda:0x8153
Endpoints In 1 Out 2 Int 3
Setup ERROR: address device command for slot 1.
Unknown version 0x7cf0
Unknown Device
0 Ethernet Device(s) found
ODROID-XU3 # usb info
1: Hub,  USB Revision 2.0
 - u-boot EHCI Host Controller
 - Class: Hub
 - PacketSize: 64  Configurations: 1
 - Vendor: 0x0000  Product 0x0000 Version 1.0
   Configuration: 1
   - Interfaces: 1 Self Powered 0mA
     Interface: 0
     - Alternate Setting 0, Endpoints: 1
     - Class Hub
     - Endpoint 1 In Interrupt MaxPacket 8 Interval 255ms

1: Hub,  USB Revision 3.0
 - U-Boot XHCI Host Controller
 - Class: Hub
 - PacketSize: 9  Configurations: 1
 - Vendor: 0x0000  Product 0x0000 Version 1.0
   Configuration: 1
   - Interfaces: 1 Self Powered 0mA
     Interface: 0
     - Alternate Setting 0, Endpoints: 1
     - Class Hub
     - Endpoint 1 In Interrupt MaxPacket 8 Interval 255ms

2: Hub,  USB Revision 2.0
 - GenesysLogic USB2.0 Hub
 - Class: Hub
 - PacketSize: 64  Configurations: 1
 - Vendor: 0x05e3  Product 0x0610 Version 146.34
   Configuration: 1
   - Interfaces: 1 Self Powered Remote Wakeup 100mA
     Interface: 0
     - Alternate Setting 0, Endpoints: 1
     - Class Hub
     - Endpoint 1 In Interrupt MaxPacket 1 Interval 12ms
     - Endpoint 1 In Interrupt MaxPacket 1 Interval 12ms

1: Hub,  USB Revision 3.0
 - U-Boot XHCI Host Controller
 - Class: Hub
 - PacketSize: 9  Configurations: 1
 - Vendor: 0x0000  Product 0x0000 Version 1.0
   Configuration: 1
   - Interfaces: 1 Self Powered 0mA
     Interface: 0
     - Alternate Setting 0, Endpoints: 1
     - Class Hub
     - Endpoint 1 In Interrupt MaxPacket 8 Interval 255ms

2: Vendor specific,  USB Revision 2.10
 - Realtek USB 10/100/1000 LAN 000001000000
 - Class: (from Interface) Vendor specific
 - PacketSize: 64  Configurations: 2
 - Vendor: 0x0bda  Product 0x8153 Version 48.0
   Configuration: 1
   - Interfaces: 1 Bus Powered Remote Wakeup 180mA
     Interface: 0
     - Alternate Setting 0, Endpoints: 3
     - Class Vendor specific
     - Endpoint 1 In Bulk MaxPacket 512
     - Endpoint 2 Out Bulk MaxPacket 512
     - Endpoint 3 In Interrupt MaxPacket 2 Interval 8ms

ODROID-XU3 #
ODROID-XU3 # dhcp
No ethernet found.
ODROID-XU3 #

---------------------------------------
Please let me know if I am doing some thing wrong.

-Anand Moon?

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-20 17:38                   ` Marek Vasut
  2015-11-21  4:10                     ` Anand Moon
@ 2015-11-21  7:27                     ` Stephen Warren
  2015-11-21 16:50                       ` Simon Glass
  1 sibling, 1 reply; 64+ messages in thread
From: Stephen Warren @ 2015-11-21  7:27 UTC (permalink / raw)
  To: u-boot

On 11/20/2015 10:38 AM, Marek Vasut wrote:
> On Friday, November 20, 2015 at 06:35:41 PM, Simon Glass wrote:
>> Hi,
> 
> Hi,
> 
>> On 19 November 2015 at 06:12, Marek Vasut <marex@denx.de> wrote:
>>> On Thursday, November 19, 2015 at 01:49:16 PM, Anand Moon wrote:
>>>> Hi Marek,
>>>
>>> Hi!
>>>
>>> [...]
>>>
>>>> Sorry for the mess: Please accept my apology, I will not in the future.
>>>
>>> Cool, thanks! :)
>>
>> This driver should use driver model, right?
> 
> Of course.

Hopefully it can support both DM and non-DM?

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-21  7:27                     ` Stephen Warren
@ 2015-11-21 16:50                       ` Simon Glass
  2015-11-22 17:09                         ` Stephen Warren
  0 siblings, 1 reply; 64+ messages in thread
From: Simon Glass @ 2015-11-21 16:50 UTC (permalink / raw)
  To: u-boot

Hi,

On 21 November 2015 at 00:27, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 11/20/2015 10:38 AM, Marek Vasut wrote:
>> On Friday, November 20, 2015 at 06:35:41 PM, Simon Glass wrote:
>>> Hi,
>>
>> Hi,
>>
>>> On 19 November 2015 at 06:12, Marek Vasut <marex@denx.de> wrote:
>>>> On Thursday, November 19, 2015 at 01:49:16 PM, Anand Moon wrote:
>>>>> Hi Marek,
>>>>
>>>> Hi!
>>>>
>>>> [...]
>>>>
>>>>> Sorry for the mess: Please accept my apology, I will not in the future.
>>>>
>>>> Cool, thanks! :)
>>>
>>> This driver should use driver model, right?
>>
>> Of course.
>
> Hopefully it can support both DM and non-DM?
>

Why support non-DM? Isn't that just going to slow us down?

Regards,
Simon

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-21 16:50                       ` Simon Glass
@ 2015-11-22 17:09                         ` Stephen Warren
  2015-11-23  3:09                           ` Simon Glass
  0 siblings, 1 reply; 64+ messages in thread
From: Stephen Warren @ 2015-11-22 17:09 UTC (permalink / raw)
  To: u-boot

On 11/21/2015 09:50 AM, Simon Glass wrote:
> Hi,
> 
> On 21 November 2015 at 00:27, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 11/20/2015 10:38 AM, Marek Vasut wrote:
>>> On Friday, November 20, 2015 at 06:35:41 PM, Simon Glass wrote:
>>>> Hi,
>>>
>>> Hi,
>>>
>>>> On 19 November 2015 at 06:12, Marek Vasut <marex@denx.de> wrote:
>>>>> On Thursday, November 19, 2015 at 01:49:16 PM, Anand Moon wrote:
>>>>>> Hi Marek,
>>>>>
>>>>> Hi!
>>>>>
>>>>> [...]
>>>>>
>>>>>> Sorry for the mess: Please accept my apology, I will not in the future.
>>>>>
>>>>> Cool, thanks! :)
>>>>
>>>> This driver should use driver model, right?
>>>
>>> Of course.
>>
>> Hopefully it can support both DM and non-DM?
> 
> Why support non-DM? Isn't that just going to slow us down?

I don't think DM is activated everywhere for Ethernet yet is it?

I can't see why it'd slow us down. The non-DM code should be quite
static, and only have any effect on DM conversion whenever we finally
pull the trigger to remove it. It shouldn't be any kind of maintenance
issue in the interim.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-21  4:10                     ` Anand Moon
@ 2015-11-22 17:12                       ` Stephen Warren
  2015-11-22 19:25                         ` Anand Moon
  0 siblings, 1 reply; 64+ messages in thread
From: Stephen Warren @ 2015-11-22 17:12 UTC (permalink / raw)
  To: u-boot

On 11/20/2015 09:10 PM, Anand Moon wrote:
...
> ?I have just patch the driver and enable the driver.
...
> After doing 'usb start' and 'usb reset'
> 
> I have tested with ASIX88179 USB 3.0 Ethernet cable and the u-boot
> successfully detected the device.
> My fried also tested with RTL8152 USB 3.0 Ethernet cable and the u-boot
> successfully detected the device.
> But with this driver I am not able to detect the Ethernet USB3.0 RT8153-VB
> connected to the OdroidXU4 board.
...
> ?U-Boot 2015.10-25167-g439fcb9-dirty (Nov 21 2015 - 14:27:19 +1030) for
> ODROID-XU3
...
> ODROID-XU3 # usb start
...
> USB Ethernet device detected: 0xbda:0x8153
> Endpoints In 1 Out 2 Int 3
> Setup ERROR: address device command for slot 1.
> Unknown version 0x7cf0
> Unknown Device
> 0 Ethernet Device(s) found

Ted sent an off-list patch that might be related to this. Perhaps EHCI
has the same check? Try something like the following:

> From 0aca6ac3391a3579815dd06ad981c2c7de0d59f7 Mon Sep 17 00:00:00 2001
> From: Ted Chen <tedchen@realtek.com>
> Date: Fri, 20 Nov 2015 18:09:20 +0800
> Subject: [PATCH] usb: xhci: Fix vendor command error if the request type is
>  USB_REQ_SET_ADDRESS or USB_REQ_SET_CONFIGURATION.
> 
> Add a condition of set_address and set_configuration to check
> if the request is standardized.
> 
> Signed-off-by: Ted Chen <tedchen@realtek.com>
> ---
>  drivers/usb/host/xhci.c |    6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
> index ca598aa..cb8a04b 100644
> --- a/drivers/usb/host/xhci.c
> +++ b/drivers/usb/host/xhci.c
> @@ -941,10 +941,12 @@ static int _xhci_submit_control_msg(struct usb_device *udev, unsigned long pipe,
>  	if (usb_pipedevice(pipe) == ctrl->rootdev)
>  		return xhci_submit_root(udev, pipe, buffer, setup);
>  
> -	if (setup->request == USB_REQ_SET_ADDRESS)
> +	if (setup->request == USB_REQ_SET_ADDRESS &&
> +	   (setup->requesttype & USB_TYPE_MASK) == USB_TYPE_STANDARD)
>  		return xhci_address_device(udev, root_portnr);
>  
> -	if (setup->request == USB_REQ_SET_CONFIGURATION) {
> +	if (setup->request == USB_REQ_SET_CONFIGURATION &&
> +	   (setup->requesttype & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
>  		ret = xhci_set_configuration(udev);
>  		if (ret) {
>  			puts("Failed to configure xHCI endpoint\n");
> -- 
> 1.7.9.5

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-22 17:12                       ` Stephen Warren
@ 2015-11-22 19:25                         ` Anand Moon
  0 siblings, 0 replies; 64+ messages in thread
From: Anand Moon @ 2015-11-22 19:25 UTC (permalink / raw)
  To: u-boot

Hi Stephen/Ted

On 22 November 2015 at 22:42, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 11/20/2015 09:10 PM, Anand Moon wrote:
> ...
>> I have just patch the driver and enable the driver.
> ...
>> After doing 'usb start' and 'usb reset'
>>
>> I have tested with ASIX88179 USB 3.0 Ethernet cable and the u-boot
>> successfully detected the device.
>> My fried also tested with RTL8152 USB 3.0 Ethernet cable and the u-boot
>> successfully detected the device.
>> But with this driver I am not able to detect the Ethernet USB3.0 RT8153-VB
>> connected to the OdroidXU4 board.
> ...
>> U-Boot 2015.10-25167-g439fcb9-dirty (Nov 21 2015 - 14:27:19 +1030) for
>> ODROID-XU3
> ...
>> ODROID-XU3 # usb start
> ...
>> USB Ethernet device detected: 0xbda:0x8153
>> Endpoints In 1 Out 2 Int 3
>> Setup ERROR: address device command for slot 1.
>> Unknown version 0x7cf0
>> Unknown Device
>> 0 Ethernet Device(s) found
>
> Ted sent an off-list patch that might be related to this. Perhaps EHCI
> has the same check? Try something like the following:
>
>> From 0aca6ac3391a3579815dd06ad981c2c7de0d59f7 Mon Sep 17 00:00:00 2001
>> From: Ted Chen <tedchen@realtek.com>
>> Date: Fri, 20 Nov 2015 18:09:20 +0800
>> Subject: [PATCH] usb: xhci: Fix vendor command error if the request type is
>>  USB_REQ_SET_ADDRESS or USB_REQ_SET_CONFIGURATION.
>>
>> Add a condition of set_address and set_configuration to check
>> if the request is standardized.
>>
>> Signed-off-by: Ted Chen <tedchen@realtek.com>
>> ---
>>  drivers/usb/host/xhci.c |    6 ++++--
>>  1 file changed, 4 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
>> index ca598aa..cb8a04b 100644
>> --- a/drivers/usb/host/xhci.c
>> +++ b/drivers/usb/host/xhci.c
>> @@ -941,10 +941,12 @@ static int _xhci_submit_control_msg(struct usb_device *udev, unsigned long pipe,
>>       if (usb_pipedevice(pipe) == ctrl->rootdev)
>>               return xhci_submit_root(udev, pipe, buffer, setup);
>>
>> -     if (setup->request == USB_REQ_SET_ADDRESS)
>> +     if (setup->request == USB_REQ_SET_ADDRESS &&
>> +        (setup->requesttype & USB_TYPE_MASK) == USB_TYPE_STANDARD)
>>               return xhci_address_device(udev, root_portnr);
>>
>> -     if (setup->request == USB_REQ_SET_CONFIGURATION) {
>> +     if (setup->request == USB_REQ_SET_CONFIGURATION &&
>> +        (setup->requesttype & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
>>               ret = xhci_set_configuration(udev);
>>               if (ret) {
>>                       puts("Failed to configure xHCI endpoint\n");
>> --
>> 1.7.9.5
>

Thanks for this patch. Now it seem to be working fine.
-----------------------------------------------------------------------
U-Boot 2015.10-25167-g439fcb9-dirty (Nov 23 2015 - 05:46:45 +1030) for
ODROID-XU3

CPU:   Exynos5422 @ 800 MHz
Model: Odroid XU3 based on EXYNOS5422
Board: Odroid XU3 based on EXYNOS5422
Type:  xu4
DRAM:  2 GiB
__of_translate_address: Bad cell count for gpx0
MMC:   EXYNOS DWMMC: 0, EXYNOS DWMMC: 1
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   No ethernet found.
Hit any key to stop autoboot:  0
ODROID-XU3 #
ODROID-XU3 # usb start
starting USB...
USB0:   USB EHCI 1.00
USB1:   Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.00
USB2:   Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.00
scanning bus 0 for devices... 1 USB Device(s) found
scanning bus 1 for devices... 2 USB Device(s) found
scanning bus 2 for devices... 2 USB Device(s) found
       scanning usb for ethernet devices...
Warning: r8152#0 using MAC address from net device
MAC 00:1e:06:31:06:b3
1 Ethernet Device(s) found
ODROID-XU3 #
ODROID-XU3 #
ODROID-XU3 # dhcp
BOOTP broadcast 1
DHCP client bound to address 10.0.0.114 (5 ms)
*** Warning: no boot file name; using '0A000072.img'
Using r8152#0 device
TFTP from server 0.0.0.0; our IP address is 10.0.0.114; sending
through gateway 10.0.0.1
Filename '0A000072.img'.
Load address: 0x43e00000
Loading: *
TFTP error: 'File not found' (1)
Not retrying...
ODROID-XU3 # setenv serverip 10.0.0.102
ODROID-XU3 #  tftpboot 40080000 zImage
Using r8152#0 device
TFTP from server 10.0.0.102; our IP address is 10.0.0.114
Filename 'zImage'.
Load address: 0x40080000
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ##############################################
         949.2 KiB/s
done
Bytes transferred = 3229744 (314830 hex)
ODROID-XU3 #
-----------------------------------------------------------------------
Thank you very much. :)

-Anand Moon

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-22 17:09                         ` Stephen Warren
@ 2015-11-23  3:09                           ` Simon Glass
  2015-11-23 17:16                             ` Stephen Warren
  0 siblings, 1 reply; 64+ messages in thread
From: Simon Glass @ 2015-11-23  3:09 UTC (permalink / raw)
  To: u-boot

+Tom

Hi Stephen,

On 22 November 2015 at 10:09, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 11/21/2015 09:50 AM, Simon Glass wrote:
>> Hi,
>>
>> On 21 November 2015 at 00:27, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>> On 11/20/2015 10:38 AM, Marek Vasut wrote:
>>>> On Friday, November 20, 2015 at 06:35:41 PM, Simon Glass wrote:
>>>>> Hi,
>>>>
>>>> Hi,
>>>>
>>>>> On 19 November 2015 at 06:12, Marek Vasut <marex@denx.de> wrote:
>>>>>> On Thursday, November 19, 2015 at 01:49:16 PM, Anand Moon wrote:
>>>>>>> Hi Marek,
>>>>>>
>>>>>> Hi!
>>>>>>
>>>>>> [...]
>>>>>>
>>>>>>> Sorry for the mess: Please accept my apology, I will not in the future.
>>>>>>
>>>>>> Cool, thanks! :)
>>>>>
>>>>> This driver should use driver model, right?
>>>>
>>>> Of course.
>>>
>>> Hopefully it can support both DM and non-DM?
>>
>> Why support non-DM? Isn't that just going to slow us down?
>
> I don't think DM is activated everywhere for Ethernet yet is it?
>
> I can't see why it'd slow us down. The non-DM code should be quite
> static, and only have any effect on DM conversion whenever we finally
> pull the trigger to remove it. It shouldn't be any kind of maintenance
> issue in the interim.

The conversion to driver model is a large and complex undertaking. It
cannot be done by a small group of people. If we add new features to
the 'old world' then there is a temptation for boards to stay there,
which slows the entire migration process.  Why convert your board to
driver model if all the shiny new drivers you want work without it? We
can only remove the old code for a subsystem when every board that
uses it is either converted or moved.

Adding a new driver that does not use driver model may add a board
that uses it. That's one more conversion to do and one more hurdle to
jump.

We will be much more successful if we avoid adding new features to
pre-driver-model code.

Regards,
Simon

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  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
  0 siblings, 1 reply; 64+ messages in thread
From: Stephen Warren @ 2015-11-23 17:16 UTC (permalink / raw)
  To: u-boot

On 11/22/2015 08:09 PM, Simon Glass wrote:
> +Tom
>
> Hi Stephen,
>
> On 22 November 2015 at 10:09, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 11/21/2015 09:50 AM, Simon Glass wrote:
>>> Hi,
>>>
>>> On 21 November 2015 at 00:27, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>>> On 11/20/2015 10:38 AM, Marek Vasut wrote:
>>>>> On Friday, November 20, 2015 at 06:35:41 PM, Simon Glass wrote:
>>>>>> Hi,
>>>>>
>>>>> Hi,
>>>>>
>>>>>> On 19 November 2015 at 06:12, Marek Vasut <marex@denx.de> wrote:
>>>>>>> On Thursday, November 19, 2015 at 01:49:16 PM, Anand Moon wrote:
>>>>>>>> Hi Marek,
>>>>>>>
>>>>>>> Hi!
>>>>>>>
>>>>>>> [...]
>>>>>>>
>>>>>>>> Sorry for the mess: Please accept my apology, I will not in the future.
>>>>>>>
>>>>>>> Cool, thanks! :)
>>>>>>
>>>>>> This driver should use driver model, right?
>>>>>
>>>>> Of course.
>>>>
>>>> Hopefully it can support both DM and non-DM?
>>>
>>> Why support non-DM? Isn't that just going to slow us down?
>>
>> I don't think DM is activated everywhere for Ethernet yet is it?
>>
>> I can't see why it'd slow us down. The non-DM code should be quite
>> static, and only have any effect on DM conversion whenever we finally
>> pull the trigger to remove it. It shouldn't be any kind of maintenance
>> issue in the interim.
>
> The conversion to driver model is a large and complex undertaking. It
> cannot be done by a small group of people. If we add new features to
> the 'old world' then there is a temptation for boards to stay there,
> which slows the entire migration process.  Why convert your board to
> driver model if all the shiny new drivers you want work without it? We
> can only remove the old code for a subsystem when every board that
> uses it is either converted or moved.
>
> Adding a new driver that does not use driver model may add a board
> that uses it. That's one more conversion to do and one more hurdle to
> jump.
>
> We will be much more successful if we avoid adding new features to

Given the conversion is quite simple (just deleting an ifdef'd block of 
code in the Ethernet driver) I'm really not sure that I agree that 
adding a new Ethernet driver that supports the old (i.e. 
**currently-in-use**) model is any kind of issue at all. It's just one 
more file to apply a fairly mechanical conversion to.

Either way, Ted, you'll definitely need to supply /me/ a version of the 
driver that's cleaned up according to the review comments here and works 
without DM_ETH (for use by the Linux4Tegra U-Boot), even if that's a 
different patch than what gets applied upstream. It's probably simplest 
if you get a patch accepted upstream that matches only upstream 
requirements, then add back non-DM support once that's accepted and send 
the resulting patch to me.

Thanks.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 1/2] checkpatch: ignore request to use ether_addr_copy()
  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  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
  2016-01-25 21:28 ` [U-Boot] [U-Boot, " Tom Rini
  3 siblings, 1 reply; 64+ messages in thread
From: Joe Hershberger @ 2015-11-23 23:36 UTC (permalink / raw)
  To: u-boot

On Fri, Nov 13, 2015 at 10:03 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> From: Stephen Warren <swarren@nvidia.com>
>
> The Linux kernel, from which checkpatch originates, contains function
> ether_addr_copy() to copy Ethernet MAC addresses, and checkpatch warns
> that it should be used in preference to memcpy() where appropriate.
> U-Boot doesn't contain ether_addr_copy(), so tell checkpatch not to issue
> this warning.
>
> Signed-off-by: Stephen Warren <swarren@nvidia.com>

Acked-by: Joe Hershberger <joe.hershberger@ni.com>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v2 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-23 17:16                             ` Stephen Warren
@ 2015-11-25  5:30                               ` Ted Chen
  2015-11-25  9:09                                 ` Anand Moon
                                                   ` (3 more replies)
  0 siblings, 4 replies; 64+ messages in thread
From: Ted Chen @ 2015-11-25  5:30 UTC (permalink / raw)
  To: u-boot

From: Ted Chen <tedchen@realtek.com>

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>

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.

Signed-off-by: Ted Chen <tedchen@realtek.com>
---
 drivers/usb/eth/Makefile    |    1 +
 drivers/usb/eth/r8152.c     | 3099 +++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/eth/usb_ether.c |    8 +
 include/usb_ether.h         |    6 +
 4 files changed, 3114 insertions(+)
 create mode 100644 drivers/usb/eth/r8152.c

diff --git a/drivers/usb/eth/Makefile b/drivers/usb/eth/Makefile
index c92d2b0..74f5f87 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
diff --git a/drivers/usb/eth/r8152.c b/drivers/usb/eth/r8152.c
new file mode 100644
index 0000000..345f2c3
--- /dev/null
+++ b/drivers/usb/eth/r8152.c
@@ -0,0 +1,3099 @@
+/*
+ * 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"
+
+#define DRIVER_VERSION "v1.0 (2015/11/24)"
+
+#define R8152_PHY_ID		32
+
+#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 CR_RST			0x10
+#define CR_RE			0x08
+#define 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
+
+enum rtl_register_content {
+	_1000bps	= 0x10,
+	_100bps		= 0x08,
+	_10bps		= 0x04,
+	LINK_STATUS	= 0x02,
+	FULL_DUP	= 0x01,
+};
+
+#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_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
+
+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)
+};
+
+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;
+};
+
+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
+};
+
+/* The forced speed, 10Mb, 100Mb, gigabit, [2.5|5|10|20|25|40|50|56|100]GbE. */
+#define SPEED_10                10
+#define SPEED_100               100
+#define SPEED_1000              1000
+#define SPEED_2500              2500
+#define SPEED_5000              5000
+#define SPEED_10000             10000
+#define SPEED_20000             20000
+#define SPEED_25000             25000
+#define SPEED_40000             40000
+#define SPEED_50000             50000
+#define SPEED_56000             56000
+#define SPEED_100000            100000
+
+#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 agg_buf_sz 2048
+
+/* local vars */
+static int curr_eth_dev; /* index for name of next device detected */
+
+#define R8152_BASE_NAME "r8152"
+
+
+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 },
+
+	{ 0x0000, 0x0000 }	/* END - Do not remove */
+};
+
+#define msleep(a)	mdelay(a)
+
+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
+int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
+{
+	int ret;
+
+	ret = usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0),
+			      RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
+			      value, index, data, size, 500);
+	if (ret < 0)
+		memset(data, 0xff, size);
+
+	return ret;
+}
+
+static
+int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
+{
+	int ret;
+
+	ret = usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0),
+			      RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE,
+			      value, index, data, size, 500);
+
+	return ret;
+}
+
+static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
+			    void *data, u16 type)
+{
+	u16 limit = 64;
+	int ret = 0;
+
+	/* both size and indix must be 4 bytes align */
+	if ((size & 3) || !size || (index & 3) || !data)
+		return -EPERM;
+
+	if ((u32)index + (u32)size > 0xffff)
+		return -EPERM;
+
+	while (size) {
+		if (size > limit) {
+			ret = get_registers(tp, index, type, limit, data);
+			if (ret < 0)
+				break;
+
+			index += limit;
+			data += limit;
+			size -= limit;
+		} else {
+			ret = get_registers(tp, index, type, size, data);
+			if (ret < 0)
+				break;
+
+			index += size;
+			data += size;
+			size = 0;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
+			     u16 size, void *data, u16 type)
+{
+	int ret;
+	u16 byteen_start, byteen_end, byen;
+	u16 limit = 512;
+
+	/* both size and indix must be 4 bytes align */
+	if ((size & 3) || !size || (index & 3) || !data)
+		return -EPERM;
+
+	if ((u32)index + (u32)size > 0xffff)
+		return -EPERM;
+
+	byteen_start = byteen & BYTE_EN_START_MASK;
+	byteen_end = byteen & BYTE_EN_END_MASK;
+
+	byen = byteen_start | (byteen_start << 4);
+	ret = set_registers(tp, index, type | byen, 4, data);
+	if (ret < 0)
+		goto error1;
+
+	index += 4;
+	data += 4;
+	size -= 4;
+
+	if (size) {
+		size -= 4;
+
+		while (size) {
+			if (size > limit) {
+				ret = set_registers(tp, index,
+						    type | BYTE_EN_DWORD,
+						    limit, data);
+				if (ret < 0)
+					goto error1;
+
+				index += limit;
+				data += limit;
+				size -= limit;
+			} else {
+				ret = set_registers(tp, index,
+						    type | BYTE_EN_DWORD,
+						    size, data);
+				if (ret < 0)
+					goto error1;
+
+				index += size;
+				data += size;
+				size = 0;
+				break;
+			}
+		}
+
+		byen = byteen_end | (byteen_end >> 4);
+		ret = set_registers(tp, index, type | byen, 4, data);
+		if (ret < 0)
+			goto error1;
+	}
+
+error1:
+
+	return ret;
+}
+
+static inline
+int pla_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data)
+{
+	return generic_ocp_read(tp, index, size, data, MCU_TYPE_PLA);
+}
+
+static inline
+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);
+}
+
+static inline
+int usb_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data)
+{
+	return generic_ocp_read(tp, index, size, data, MCU_TYPE_USB);
+}
+
+static inline
+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);
+}
+
+static 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);
+}
+
+static 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);
+}
+
+static 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 (u16)data;
+}
+
+static 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);
+}
+
+static 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 (u8)data;
+}
+
+static 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);
+}
+
+static 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);
+}
+
+static 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 inline void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value)
+{
+	ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value);
+}
+
+static inline int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)
+{
+	return ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2);
+}
+
+static 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_nic_reset(struct r8152 *tp)
+{
+	int	i;
+
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, CR_RST);
+
+	for (i = 0; i < 1000; i++) {
+		if (!(ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR) & CR_RST))
+			break;
+
+		udelay(400);
+	}
+}
+
+static inline 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 |= CR_RE | 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 = (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;
+	int i;
+
+	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);
+
+	for (i = 0; i < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if ((ocp_data & FIFO_EMPTY) == FIFO_EMPTY)
+			break;
+
+		mdelay(2);
+	}
+
+	for (i = 0; i < 1000; i++) {
+		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0) & TCR0_TX_EMPTY)
+			break;
+		mdelay(2);
+	}
+
+	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 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 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 = 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 = i+2)
+			ocp_write_word(tp, MCU_TYPE_PLA,
+				       r8152b_pla_patch_a2_bp[i],
+				       r8152b_pla_patch_a2_bp[i+1]);
+	}
+}
+
+static int r8152_read_mac(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};
+
+	if (pla_ocp_read(tp, PLA_IDR, 8, enetaddr) < 0)
+		return -1;
+
+	memcpy(eth->enetaddr, enetaddr, ETH_ALEN);
+	return 0;
+}
+
+static void r8152b_disable_aldps(struct r8152 *tp)
+{
+	ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA | DIS_SDSAVE);
+	msleep(20);
+}
+
+static inline 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 r8152b_exit_oob(struct r8152 *tp)
+{
+	u32 ocp_data;
+	int i;
+
+	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);
+
+	for (i = 0; i < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+
+		mdelay(2);
+	}
+
+	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 < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		mdelay(2);
+	}
+
+	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;
+	int i;
+
+	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);
+
+	for (i = 0; i < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		mdelay(2);
+	}
+
+	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 < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		mdelay(2);
+	}
+
+	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 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);
+	}
+}
+
+static 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = i+2)
+			ocp_write_word(tp, MCU_TYPE_USB,
+				       r8153_usb_patch_d_bp[i],
+				       r8153_usb_patch_d_bp[i+1]);
+	}
+}
+
+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;
+	int i;
+
+	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);
+
+	for (i = 0; i < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		mdelay(2);
+	}
+
+	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 < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		mdelay(2);
+	}
+
+	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;
+	int i;
+
+	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);
+
+	for (i = 0; i < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		mdelay(2);
+	}
+
+	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 < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		mdelay(2);
+	}
+
+	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);
+	msleep(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;
+	int ret = 0;
+
+	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 {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		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 {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		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);
+out:
+
+	return ret;
+}
+
+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;
+		msleep(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;
+		msleep(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 = 0;
+
+	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;
+#define TIMEOUT_RESOLUTION 50	/* ms */
+#define PHY_CONNECT_TIMEOUT 5000
+	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;
+
+#define USB_BULK_SEND_TIMEOUT 5000
+
+	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 = %lu, 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[agg_buf_sz];
+	unsigned char *pkt_ptr;
+	int err;
+	int actual_len;
+	u16 packet_len;
+
+	u32 bytes_process = 0;
+
+	struct rx_desc *rx_desc;
+
+#define USB_BULK_RECV_TIMEOUT 5000
+
+	debug("** %s()\n", __func__);
+
+	err = usb_bulk_msg(dev->pusb_dev,
+				usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in),
+				(void *)recv_buf,
+				agg_buf_sz,
+				&actual_len,
+				USB_BULK_RECV_TIMEOUT);
+	debug("Rx: len = %u, actual = %u, err = %d\n", agg_buf_sz,
+	      actual_len, err);
+	if (err != 0) {
+		debug("Rx: failed to receive\n");
+		return -1;
+	}
+	if (actual_len > 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);
+
+	printf("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 asix 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; r8152_dongles[i].vendor != 0; 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) {
+				if (!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(eth) < 0)
+		return 0;
+
+	debug("MAC %pM\n", eth->enetaddr);
+	return 1;
+}
diff --git a/drivers/usb/eth/usb_ether.c b/drivers/usb/eth/usb_ether.c
index 62d20f0..215b3d8 100644
--- a/drivers/usb/eth/usb_ether.c
+++ b/drivers/usb/eth/usb_ether.c
@@ -180,6 +180,14 @@ 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

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v2 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  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
                                                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 64+ messages in thread
From: Anand Moon @ 2015-11-25  9:09 UTC (permalink / raw)
  To: u-boot

Hi Ted,

On 25 November 2015 at 11:00, Ted Chen <tedchen@realtek.com> wrote:
> From: Ted Chen <tedchen@realtek.com>
>
> 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>
>
> 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.
>
> Signed-off-by: Ted Chen <tedchen@realtek.com>
> ---
>  drivers/usb/eth/Makefile    |    1 +
>  drivers/usb/eth/r8152.c     | 3099 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/usb/eth/usb_ether.c |    8 +
>  include/usb_ether.h         |    6 +
>  4 files changed, 3114 insertions(+)
>  create mode 100644 drivers/usb/eth/r8152.c
>
> diff --git a/drivers/usb/eth/Makefile b/drivers/usb/eth/Makefile
> index c92d2b0..74f5f87 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
> diff --git a/drivers/usb/eth/r8152.c b/drivers/usb/eth/r8152.c
> new file mode 100644
> index 0000000..345f2c3
> --- /dev/null
> +++ b/drivers/usb/eth/r8152.c
> @@ -0,0 +1,3099 @@
> +/*
> + * 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"
> +
> +#define DRIVER_VERSION "v1.0 (2015/11/24)"
> +
> +#define R8152_PHY_ID           32
> +
> +#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 CR_RST                 0x10
> +#define CR_RE                  0x08
> +#define 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
> +
> +enum rtl_register_content {
> +       _1000bps        = 0x10,
> +       _100bps         = 0x08,
> +       _10bps          = 0x04,
> +       LINK_STATUS     = 0x02,
> +       FULL_DUP        = 0x01,
> +};
> +
> +#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_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
> +
> +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)
> +};
> +
> +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;
> +};
> +
> +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
> +};
> +
> +/* The forced speed, 10Mb, 100Mb, gigabit, [2.5|5|10|20|25|40|50|56|100]GbE. */
> +#define SPEED_10                10
> +#define SPEED_100               100
> +#define SPEED_1000              1000
> +#define SPEED_2500              2500
> +#define SPEED_5000              5000
> +#define SPEED_10000             10000
> +#define SPEED_20000             20000
> +#define SPEED_25000             25000
> +#define SPEED_40000             40000
> +#define SPEED_50000             50000
> +#define SPEED_56000             56000
> +#define SPEED_100000            100000
> +
> +#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 agg_buf_sz 2048
> +
> +/* local vars */
> +static int curr_eth_dev; /* index for name of next device detected */
> +
> +#define R8152_BASE_NAME "r8152"
> +
> +
> +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 },
> +
> +       { 0x0000, 0x0000 }      /* END - Do not remove */
> +};
> +
> +#define msleep(a)      mdelay(a)
> +
> +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
> +int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
> +{
> +       int ret;
> +
> +       ret = usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0),
> +                             RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
> +                             value, index, data, size, 500);
> +       if (ret < 0)
> +               memset(data, 0xff, size);
> +
> +       return ret;
> +}
> +
> +static
> +int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
> +{
> +       int ret;
> +
> +       ret = usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0),
> +                             RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE,
> +                             value, index, data, size, 500);
> +
> +       return ret;
> +}
> +
> +static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
> +                           void *data, u16 type)
> +{
> +       u16 limit = 64;
> +       int ret = 0;
> +
> +       /* both size and indix must be 4 bytes align */
> +       if ((size & 3) || !size || (index & 3) || !data)
> +               return -EPERM;
> +
> +       if ((u32)index + (u32)size > 0xffff)
> +               return -EPERM;
> +
> +       while (size) {
> +               if (size > limit) {
> +                       ret = get_registers(tp, index, type, limit, data);
> +                       if (ret < 0)
> +                               break;
> +
> +                       index += limit;
> +                       data += limit;
> +                       size -= limit;
> +               } else {
> +                       ret = get_registers(tp, index, type, size, data);
> +                       if (ret < 0)
> +                               break;
> +
> +                       index += size;
> +                       data += size;
> +                       size = 0;
> +                       break;
> +               }
> +       }
> +
> +       return ret;
> +}
> +
> +static int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
> +                            u16 size, void *data, u16 type)
> +{
> +       int ret;
> +       u16 byteen_start, byteen_end, byen;
> +       u16 limit = 512;
> +
> +       /* both size and indix must be 4 bytes align */
> +       if ((size & 3) || !size || (index & 3) || !data)
> +               return -EPERM;
> +
> +       if ((u32)index + (u32)size > 0xffff)
> +               return -EPERM;
> +
> +       byteen_start = byteen & BYTE_EN_START_MASK;
> +       byteen_end = byteen & BYTE_EN_END_MASK;
> +
> +       byen = byteen_start | (byteen_start << 4);
> +       ret = set_registers(tp, index, type | byen, 4, data);
> +       if (ret < 0)
> +               goto error1;
> +
> +       index += 4;
> +       data += 4;
> +       size -= 4;
> +
> +       if (size) {
> +               size -= 4;
> +
> +               while (size) {
> +                       if (size > limit) {
> +                               ret = set_registers(tp, index,
> +                                                   type | BYTE_EN_DWORD,
> +                                                   limit, data);
> +                               if (ret < 0)
> +                                       goto error1;
> +
> +                               index += limit;
> +                               data += limit;
> +                               size -= limit;
> +                       } else {
> +                               ret = set_registers(tp, index,
> +                                                   type | BYTE_EN_DWORD,
> +                                                   size, data);
> +                               if (ret < 0)
> +                                       goto error1;
> +
> +                               index += size;
> +                               data += size;
> +                               size = 0;
> +                               break;
> +                       }
> +               }
> +
> +               byen = byteen_end | (byteen_end >> 4);
> +               ret = set_registers(tp, index, type | byen, 4, data);
> +               if (ret < 0)
> +                       goto error1;
> +       }
> +
> +error1:
> +
> +       return ret;
> +}
> +
> +static inline
> +int pla_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data)
> +{
> +       return generic_ocp_read(tp, index, size, data, MCU_TYPE_PLA);
> +}
> +
> +static inline
> +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);
> +}
> +
> +static inline
> +int usb_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data)
> +{
> +       return generic_ocp_read(tp, index, size, data, MCU_TYPE_USB);
> +}
> +
> +static inline
> +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);
> +}
> +
> +static 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);
> +}
> +
> +static 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);
> +}
> +
> +static 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 (u16)data;
> +}
> +
> +static 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);
> +}
> +
> +static 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 (u8)data;
> +}
> +
> +static 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);
> +}
> +
> +static 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);
> +}
> +
> +static 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 inline void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value)
> +{
> +       ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value);
> +}
> +
> +static inline int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)
> +{
> +       return ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2);
> +}
> +
> +static 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_nic_reset(struct r8152 *tp)
> +{
> +       int     i;
> +
> +       ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, CR_RST);
> +
> +       for (i = 0; i < 1000; i++) {
> +               if (!(ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR) & CR_RST))
> +                       break;
> +
> +               udelay(400);
> +       }
> +}
> +
> +static inline 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 |= CR_RE | 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 = (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;
> +       int i;
> +
> +       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);
> +
> +       for (i = 0; i < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if ((ocp_data & FIFO_EMPTY) == FIFO_EMPTY)
> +                       break;
> +
> +               mdelay(2);
> +       }
> +
> +       for (i = 0; i < 1000; i++) {
> +               if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0) & TCR0_TX_EMPTY)
> +                       break;
> +               mdelay(2);
> +       }
> +
> +       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 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 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 = 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 = i+2)
> +                       ocp_write_word(tp, MCU_TYPE_PLA,
> +                                      r8152b_pla_patch_a2_bp[i],
> +                                      r8152b_pla_patch_a2_bp[i+1]);
> +       }
> +}
> +
> +static int r8152_read_mac(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};
> +
> +       if (pla_ocp_read(tp, PLA_IDR, 8, enetaddr) < 0)
> +               return -1;
> +
> +       memcpy(eth->enetaddr, enetaddr, ETH_ALEN);
> +       return 0;
> +}
> +
> +static void r8152b_disable_aldps(struct r8152 *tp)
> +{
> +       ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA | DIS_SDSAVE);
> +       msleep(20);
> +}
> +
> +static inline 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 r8152b_exit_oob(struct r8152 *tp)
> +{
> +       u32 ocp_data;
> +       int i;
> +
> +       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);
> +
> +       for (i = 0; i < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if (ocp_data & LINK_LIST_READY)
> +                       break;
> +
> +               mdelay(2);
> +       }
> +
> +       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 < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if (ocp_data & LINK_LIST_READY)
> +                       break;
> +               mdelay(2);
> +       }
> +
> +       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;
> +       int i;
> +
> +       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);
> +
> +       for (i = 0; i < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if (ocp_data & LINK_LIST_READY)
> +                       break;
> +               mdelay(2);
> +       }
> +
> +       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 < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if (ocp_data & LINK_LIST_READY)
> +                       break;
> +               mdelay(2);
> +       }
> +
> +       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 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);
> +       }
> +}
> +
> +static 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = i+2)
> +                       ocp_write_word(tp, MCU_TYPE_USB,
> +                                      r8153_usb_patch_d_bp[i],
> +                                      r8153_usb_patch_d_bp[i+1]);
> +       }
> +}
> +
> +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;
> +       int i;
> +
> +       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);
> +
> +       for (i = 0; i < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if (ocp_data & LINK_LIST_READY)
> +                       break;
> +               mdelay(2);
> +       }
> +
> +       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 < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if (ocp_data & LINK_LIST_READY)
> +                       break;
> +               mdelay(2);
> +       }
> +
> +       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;
> +       int i;
> +
> +       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);
> +
> +       for (i = 0; i < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if (ocp_data & LINK_LIST_READY)
> +                       break;
> +               mdelay(2);
> +       }
> +
> +       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 < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if (ocp_data & LINK_LIST_READY)
> +                       break;
> +               mdelay(2);
> +       }
> +
> +       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);
> +       msleep(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;
> +       int ret = 0;
> +
> +       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 {
> +                       ret = -EINVAL;
> +                       goto out;
> +               }
> +
> +               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 {
> +                       ret = -EINVAL;
> +                       goto out;
> +               }
> +
> +               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);
> +out:
> +
> +       return ret;
> +}
> +
> +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;
> +               msleep(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;
> +               msleep(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 = 0;
> +
> +       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;
> +#define TIMEOUT_RESOLUTION 50  /* ms */
> +#define PHY_CONNECT_TIMEOUT 5000
> +       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;
> +
> +#define USB_BULK_SEND_TIMEOUT 5000
> +
> +       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 = %lu, 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[agg_buf_sz];
> +       unsigned char *pkt_ptr;
> +       int err;
> +       int actual_len;
> +       u16 packet_len;
> +
> +       u32 bytes_process = 0;
> +
> +       struct rx_desc *rx_desc;
> +
> +#define USB_BULK_RECV_TIMEOUT 5000
> +
> +       debug("** %s()\n", __func__);
> +
> +       err = usb_bulk_msg(dev->pusb_dev,
> +                               usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in),
> +                               (void *)recv_buf,
> +                               agg_buf_sz,
> +                               &actual_len,
> +                               USB_BULK_RECV_TIMEOUT);
> +       debug("Rx: len = %u, actual = %u, err = %d\n", agg_buf_sz,
> +             actual_len, err);
> +       if (err != 0) {
> +               debug("Rx: failed to receive\n");
> +               return -1;
> +       }
> +       if (actual_len > 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);
> +
> +       printf("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 asix 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; r8152_dongles[i].vendor != 0; 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) {
> +                               if (!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(eth) < 0)
> +               return 0;
> +
> +       debug("MAC %pM\n", eth->enetaddr);
> +       return 1;
> +}
> diff --git a/drivers/usb/eth/usb_ether.c b/drivers/usb/eth/usb_ether.c
> index 62d20f0..215b3d8 100644
> --- a/drivers/usb/eth/usb_ether.c
> +++ b/drivers/usb/eth/usb_ether.c
> @@ -180,6 +180,14 @@ 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
>

Tested on Odroid-XU4 with Ethernet USB3.0 RT8153-VB.

Tested-by: Anand Moon <linux.amoon@gmail.com>
Reviewed-by: Anand Moon <linux.amoon@gmail.com>

Few Issue I faced, But I have tested this patch.
--------------------------------------------------------------------------------------
I could not patch this with mainline u-boot cleanly.
I still face some compilation warning. Please fix them again.
--------------------------------------------------------------------------------------

U-Boot 2016.01-rc1-25373-g2b24e09-dirty (Nov 25 2015 - 18:46:01 +1030)
for ODROID-XU3

CPU:   Exynos5422 @ 800 MHz
Model: Odroid XU3 based on EXYNOS5422
Board: Odroid XU3 based on EXYNOS5422
Type:  xu4
DRAM:  2 GiB
__of_translate_address: Bad cell count for gpx0
MMC:   EXYNOS DWMMC: 0, EXYNOS DWMMC: 1
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   No ethernet found.
Hit any key to stop autoboot:  0
ODROID-XU3 # setenv usbethaddr 00:10:75:2A:AE:E0
ODROID-XU3 # setenv serverip 10.0.0.102
ODROID-XU3 # setenv gatewayip 10.0.0.1
ODROID-XU3 # usb start
starting USB...
USB0:   USB EHCI 1.00
USB1:   Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.00
USB2:   Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.00
scanning bus 0 for devices... 1 USB Device(s) found
scanning bus 1 for devices... 2 USB Device(s) found
scanning bus 2 for devices... 2 USB Device(s) found
       scanning usb for ethernet devices...
Warning: r8152#0 MAC addresses don't match:
Address in SROM is         00:1e:06:31:06:b3
Address in environment is  00:10:75:2a:ae:e0
MAC 00:10:75:2a:ae:e0
1 Ethernet Device(s) found
ODROID-XU3 #
ODROID-XU3 # dhcp
BOOTP broadcast 1
DHCP client bound to address 10.0.0.103 (228 ms)
*** Warning: no boot file name; using '0A000067.img'
Using r8152#0 device
TFTP from server 10.0.0.102; our IP address is 10.0.0.103
Filename '0A000067.img'.
Load address: 0x43e00000
Loading: *
TFTP error: 'File not found' (1)
Not retrying...
ODROID-XU3 # tftpboot 40080000 zImage
Using r8152#0 device
TFTP from server 10.0.0.102; our IP address is 10.0.0.103
Filename 'zImage'.
Load address: 0x40080000
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ##############################################
         960 KiB/s
done
Bytes transferred = 3229744 (314830 hex)
ODROID-XU3 #
------------------------------------------------------------
-Anand Moon

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v2 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  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
  3 siblings, 0 replies; 64+ messages in thread
From: Marek Vasut @ 2015-11-26 16:58 UTC (permalink / raw)
  To: u-boot

On Wednesday, November 25, 2015 at 06:30:54 AM, Ted Chen wrote:
> From: Ted Chen <tedchen@realtek.com>
> 
> 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>
> 
> 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.

The changelog should go into the diffstat part, otherwise it will be picked and
become part of the commit message. We don't want that.

I only have nitpicks below :)

> Signed-off-by: Ted Chen <tedchen@realtek.com>
> ---
>  drivers/usb/eth/Makefile    |    1 +
>  drivers/usb/eth/r8152.c     | 3099
> +++++++++++++++++++++++++++++++++++++++++++ drivers/usb/eth/usb_ether.c | 
>   8 +
>  include/usb_ether.h         |    6 +
>  4 files changed, 3114 insertions(+)
>  create mode 100644 drivers/usb/eth/r8152.c

The changelog should go here.

> diff --git a/drivers/usb/eth/Makefile b/drivers/usb/eth/Makefile
> index c92d2b0..74f5f87 100644
> --- a/drivers/usb/eth/Makefile
> +++ b/drivers/usb/eth/Makefile

[...]

> +#define DRIVER_VERSION "v1.0 (2015/11/24)"

I don't think this is really relevant information.

> +#define R8152_PHY_ID		32

[...]

> +/* OCP_EEE_CONFIG3 */
> +#define fast_snr_mask		0xff80
> +#define fast_snr(x)		(min(x, 0x1ff) << 7)	/* bit 7 ~ 15 */

Please add parenthesis around the x -- min((x), ...

> +#define RG_LFS_SEL		0x0060	/* bit 6 ~ 5 */
> +#define MSK_PH			0x0006	/* bit 0 ~ 3 */

[...]

> +
> +#define msleep(a)	mdelay(a)

Please just drop this.

> +static u8 r8152b_pla_patch_a[] = {
> +	0x08, 0xe0, 0x40, 0xe0,	0x78, 0xe0, 0x85, 0xe0,

Please add space after comma to make it consistent. Fix globally.

> +	0x5d, 0xe1, 0xa1, 0xe1,	0xa3, 0xe1, 0xab, 0xe1,

[...]

> +static u16 r8152b_ram_code1[] = {
> +	0x9700, 0x7fe0, 0x4c00, 0x4007,	0x4400, 0x4800, 0x7c1f, 0x4c00,

Please drop the tab and add space. Fix globally.

> +	0x5310, 0x6000, 0x7c07, 0x6800,	0x673e, 0x0000, 0x0000, 0x571f,

[...]

> +static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
> +			    void *data, u16 type)
> +{
> +	u16 limit = 64;
> +	int ret = 0;
> +
> +	/* both size and indix must be 4 bytes align */
> +	if ((size & 3) || !size || (index & 3) || !data)
> +		return -EPERM;
> +
> +	if ((u32)index + (u32)size > 0xffff)

Are the casts here needed ?

> +		return -EPERM;
> +
> +	while (size) {
> +		if (size > limit) {
> +			ret = get_registers(tp, index, type, limit, data);
> +			if (ret < 0)
> +				break;
> +
> +			index += limit;
> +			data += limit;
> +			size -= limit;
> +		} else {
> +			ret = get_registers(tp, index, type, size, data);
> +			if (ret < 0)
> +				break;
> +
> +			index += size;
> +			data += size;
> +			size = 0;
> +			break;
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +static int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
> +			     u16 size, void *data, u16 type)
> +{
> +	int ret;
> +	u16 byteen_start, byteen_end, byen;
> +	u16 limit = 512;
> +
> +	/* both size and indix must be 4 bytes align */
> +	if ((size & 3) || !size || (index & 3) || !data)
> +		return -EPERM;
> +
> +	if ((u32)index + (u32)size > 0xffff)
> +		return -EPERM;
> +
> +	byteen_start = byteen & BYTE_EN_START_MASK;
> +	byteen_end = byteen & BYTE_EN_END_MASK;
> +
> +	byen = byteen_start | (byteen_start << 4);
> +	ret = set_registers(tp, index, type | byen, 4, data);
> +	if (ret < 0)
> +		goto error1;
> +
> +	index += 4;
> +	data += 4;
> +	size -= 4;
> +
> +	if (size) {
> +		size -= 4;
> +
> +		while (size) {
> +			if (size > limit) {
> +				ret = set_registers(tp, index,
> +						    type | BYTE_EN_DWORD,
> +						    limit, data);
> +				if (ret < 0)
> +					goto error1;
> +
> +				index += limit;
> +				data += limit;
> +				size -= limit;

Cannot the branches of this code be rewritten in a more compact way ?
It seems you're only decrementing two variables by a different factor, no?

> +			} else {
> +				ret = set_registers(tp, index,
> +						    type | BYTE_EN_DWORD,
> +						    size, data);
> +				if (ret < 0)
> +					goto error1;
> +
> +				index += size;
> +				data += size;
> +				size = 0;
> +				break;
> +			}
> +		}

[...]

> +static 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 (u8)data;

The cast is not needed, you might want to check this al around the place.

> +}

[...]

> +static 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 = 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 = 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 = i+2)

i += 2 is simpler, please fix globally

> +			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 = 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);
[...]

Otherwise looks OK, thanks!

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v2 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  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
  3 siblings, 0 replies; 64+ messages in thread
From: Joe Hershberger @ 2015-11-30 22:07 UTC (permalink / raw)
  To: u-boot

Hi Ted,

On Tue, Nov 24, 2015 at 11:30 PM, Ted Chen <tedchen@realtek.com> wrote:
> From: Ted Chen <tedchen@realtek.com>
>
> 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>
>
> 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.
>
> Signed-off-by: Ted Chen <tedchen@realtek.com>
> ---
>  drivers/usb/eth/Makefile    |    1 +
>  drivers/usb/eth/r8152.c     | 3099 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/usb/eth/usb_ether.c |    8 +
>  include/usb_ether.h         |    6 +
>  4 files changed, 3114 insertions(+)
>  create mode 100644 drivers/usb/eth/r8152.c
>
> diff --git a/drivers/usb/eth/Makefile b/drivers/usb/eth/Makefile
> index c92d2b0..74f5f87 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
> diff --git a/drivers/usb/eth/r8152.c b/drivers/usb/eth/r8152.c
> new file mode 100644
> index 0000000..345f2c3
> --- /dev/null
> +++ b/drivers/usb/eth/r8152.c
> @@ -0,0 +1,3099 @@
> +/*
> + * 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"
> +
> +#define DRIVER_VERSION "v1.0 (2015/11/24)"

If this is somehow useful to link back to a Realtek release or
something, then in belongs in the commit log, not in the code.

> +
> +#define R8152_PHY_ID           32
> +

8< snip >8

> +
> +/* The forced speed, 10Mb, 100Mb, gigabit, [2.5|5|10|20|25|40|50|56|100]GbE. */
> +#define SPEED_10                10
> +#define SPEED_100               100
> +#define SPEED_1000              1000
> +#define SPEED_2500              2500
> +#define SPEED_5000              5000
> +#define SPEED_10000             10000
> +#define SPEED_20000             20000
> +#define SPEED_25000             25000
> +#define SPEED_40000             40000
> +#define SPEED_50000             50000
> +#define SPEED_56000             56000
> +#define SPEED_100000            100000

Are all the speeds really relevant to define? They aren't used. Maybe
lose all the unused ones.

> +#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 agg_buf_sz 2048
> +
> +/* local vars */
> +static int curr_eth_dev; /* index for name of next device detected */
> +
> +#define R8152_BASE_NAME "r8152"
> +
> +
> +struct r8152_dongle {
> +       unsigned short vendor;
> +       unsigned short product;
> +};

With all the extensive defines here, this file is pretty deep to get
to any actual implementation. Maybe it would be cleaner to split
everything above here into a drivers/usb/eth/r8152.h

> +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 },
> +
> +       { 0x0000, 0x0000 }      /* END - Do not remove */
> +};
> +
> +#define msleep(a)      mdelay(a)

Just use mdelay() in the code.

> +static u8 r8152b_pla_patch_a[] = {
> +       0x08, 0xe0, 0x40, 0xe0, 0x78, 0xe0, 0x85, 0xe0,

8< snip >8

> +       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 };

Something about this firmware is very ugly to me. Seems like it should
live in its own file that noone ever opens. Maybe noone else cares,
but that's my opinion.

> +
> +static
> +int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
> +{
> +       int ret;
> +
> +       ret = usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0),
> +                             RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
> +                             value, index, data, size, 500);
> +       if (ret < 0)
> +               memset(data, 0xff, size);

That's peculiar. I guess you are emulating a bus pulled high?

> +       return ret;
> +}
> +
> +static
> +int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
> +{
> +       int ret;
> +
> +       ret = usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0),
> +                             RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE,
> +                             value, index, data, size, 500);
> +
> +       return ret;
> +}
> +
> +static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
> +                           void *data, u16 type)
> +{
> +       u16 limit = 64;

I think a better name would be something like "burst_size".

> +       int ret = 0;
> +
> +       /* both size and indix must be 4 bytes align */

indix -> index

> +       if ((size & 3) || !size || (index & 3) || !data)
> +               return -EPERM;

I think -EINVAL is more appropriate here.

> +
> +       if ((u32)index + (u32)size > 0xffff)
> +               return -EPERM;

I think -EINVAL is more appropriate here.

> +
> +       while (size) {
> +               if (size > limit) {
> +                       ret = get_registers(tp, index, type, limit, data);
> +                       if (ret < 0)
> +                               break;
> +
> +                       index += limit;
> +                       data += limit;
> +                       size -= limit;
> +               } else {
> +                       ret = get_registers(tp, index, type, size, data);
> +                       if (ret < 0)
> +                               break;
> +
> +                       index += size;
> +                       data += size;
> +                       size = 0;
> +                       break;
> +               }
> +       }
> +
> +       return ret;
> +}
> +
> +static int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
> +                            u16 size, void *data, u16 type)
> +{
> +       int ret;
> +       u16 byteen_start, byteen_end, byen;

What is a "byteen"? Is that supposed to be "byte_en"? How about
"byen"? how does it differ from the function parameter "byteen".
Please clean up the names used in here to make it clear.

> +       u16 limit = 512;
> +
> +       /* both size and indix must be 4 bytes align */

indix -> index

> +       if ((size & 3) || !size || (index & 3) || !data)
> +               return -EPERM;

I think -EINVAL is more appropriate here.

> +
> +       if ((u32)index + (u32)size > 0xffff)
> +               return -EPERM;

I think -EINVAL is more appropriate here.

> +
> +       byteen_start = byteen & BYTE_EN_START_MASK;
> +       byteen_end = byteen & BYTE_EN_END_MASK;
> +
> +       byen = byteen_start | (byteen_start << 4);
> +       ret = set_registers(tp, index, type | byen, 4, data);
> +       if (ret < 0)
> +               goto error1;

Why are you not just returning at each of these points? You do no cleanup.

> +
> +       index += 4;
> +       data += 4;
> +       size -= 4;
> +
> +       if (size) {
> +               size -= 4;
> +
> +               while (size) {
> +                       if (size > limit) {
> +                               ret = set_registers(tp, index,
> +                                                   type | BYTE_EN_DWORD,
> +                                                   limit, data);
> +                               if (ret < 0)
> +                                       goto error1;
> +
> +                               index += limit;
> +                               data += limit;
> +                               size -= limit;
> +                       } else {
> +                               ret = set_registers(tp, index,
> +                                                   type | BYTE_EN_DWORD,
> +                                                   size, data);
> +                               if (ret < 0)
> +                                       goto error1;
> +
> +                               index += size;
> +                               data += size;
> +                               size = 0;
> +                               break;
> +                       }
> +               }
> +
> +               byen = byteen_end | (byteen_end >> 4);
> +               ret = set_registers(tp, index, type | byen, 4, data);
> +               if (ret < 0)
> +                       goto error1;
> +       }
> +
> +error1:
> +
> +       return ret;
> +}
> +
> +static inline

You don't need to tell the compiler what to do here. It will ignore
you anyway. I recommend you drop the "inline" on these functions.

> +int pla_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data)
> +{
> +       return generic_ocp_read(tp, index, size, data, MCU_TYPE_PLA);
> +}
> +
> +static inline
> +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);
> +}
> +
> +static inline
> +int usb_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data)
> +{
> +       return generic_ocp_read(tp, index, size, data, MCU_TYPE_USB);
> +}
> +
> +static inline
> +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);
> +}
> +
> +static 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);
> +}
> +
> +static 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);
> +}
> +
> +static 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 (u16)data;
> +}
> +
> +static 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);
> +}
> +
> +static 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 (u8)data;
> +}
> +
> +static 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);
> +}
> +
> +static 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);
> +}
> +
> +static 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 inline void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value)
> +{
> +       ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value);
> +}
> +
> +static inline int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)
> +{
> +       return ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2);
> +}
> +
> +static 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_nic_reset(struct r8152 *tp)
> +{
> +       int     i;
> +
> +       ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, CR_RST);
> +
> +       for (i = 0; i < 1000; i++) {
> +               if (!(ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR) & CR_RST))
> +                       break;
> +
> +               udelay(400);
> +       }
> +}
> +
> +static inline 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);
> +}
> +
> +
> +

Why extra white space? Please remove.

> +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 |= CR_RE | 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 = (agg_buf_sz - RTL8153_RMS) / 4;

Add blank line. Checkpatch.pl?

> +       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;
> +       int i;
> +
> +       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);
> +
> +       for (i = 0; i < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if ((ocp_data & FIFO_EMPTY) == FIFO_EMPTY)
> +                       break;
> +
> +               mdelay(2);
> +       }
> +
> +       for (i = 0; i < 1000; i++) {
> +               if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0) & TCR0_TX_EMPTY)
> +                       break;
> +               mdelay(2);
> +       }
> +
> +       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 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 void r8152b_firmware(struct r8152 *tp)

It would be great if you collect all the firmware manipulation
functions into one part of the file so that they are all close
together.

> +{
> +       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 = 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 = i+2)
> +                       ocp_write_word(tp, MCU_TYPE_PLA,
> +                                      r8152b_pla_patch_a2_bp[i],
> +                                      r8152b_pla_patch_a2_bp[i+1]);
> +       }
> +}
> +
> +static int r8152_read_mac(struct eth_device *eth)

If you don't plan to add this initially with driver model support
(that would be best), you should at least write it in a way that is
easy to convert. That means instead of passing in the struct
eth_device, just pass a pointer to the MAC and your priv data, so that
either model can easily call.

> +{
> +       struct ueth_data *dev = (struct ueth_data *)eth->priv;
> +       struct r8152 *tp = (struct r8152 *)dev->dev_priv;
> +
> +       unsigned char enetaddr[8] = {0};
> +
> +       if (pla_ocp_read(tp, PLA_IDR, 8, enetaddr) < 0)
> +               return -1;

Just return the error code from the read?

> +
> +       memcpy(eth->enetaddr, enetaddr, ETH_ALEN);
> +       return 0;
> +}
> +
> +static void r8152b_disable_aldps(struct r8152 *tp)
> +{
> +       ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA | DIS_SDSAVE);
> +       msleep(20);
> +}
> +
> +static inline 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 r8152b_exit_oob(struct r8152 *tp)
> +{
> +       u32 ocp_data;
> +       int i;
> +
> +       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);
> +
> +       for (i = 0; i < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if (ocp_data & LINK_LIST_READY)
> +                       break;
> +
> +               mdelay(2);
> +       }
> +
> +       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 < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if (ocp_data & LINK_LIST_READY)
> +                       break;
> +               mdelay(2);
> +       }
> +
> +       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;
> +       int i;
> +
> +       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);
> +
> +       for (i = 0; i < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if (ocp_data & LINK_LIST_READY)
> +                       break;
> +               mdelay(2);
> +       }
> +
> +       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 < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if (ocp_data & LINK_LIST_READY)
> +                       break;
> +               mdelay(2);
> +       }
> +
> +       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 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);
> +       }
> +}
> +
> +static 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 = 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 = i+2)

Bad indentation.

> +               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 = 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 = 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 = 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 = 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 = 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 = 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 = i+2)
> +                       ocp_write_word(tp, MCU_TYPE_USB,
> +                                      r8153_usb_patch_d_bp[i],
> +                                      r8153_usb_patch_d_bp[i+1]);
> +       }
> +}
> +
> +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;
> +       int i;
> +
> +       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);
> +
> +       for (i = 0; i < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if (ocp_data & LINK_LIST_READY)
> +                       break;
> +               mdelay(2);
> +       }
> +
> +       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 < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if (ocp_data & LINK_LIST_READY)
> +                       break;
> +               mdelay(2);
> +       }
> +
> +       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;
> +       int i;
> +
> +       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);
> +
> +       for (i = 0; i < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if (ocp_data & LINK_LIST_READY)
> +                       break;
> +               mdelay(2);
> +       }
> +
> +       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 < 1000; i++) {
> +               ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +               if (ocp_data & LINK_LIST_READY)
> +                       break;
> +               mdelay(2);
> +       }
> +
> +       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);
> +       msleep(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;
> +       int ret = 0;
> +
> +       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 {
> +                       ret = -EINVAL;

Why not just return this value from here and others in this file. You
do no cleanup.

> +                       goto out;
> +               }
> +
> +               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 {
> +                       ret = -EINVAL;
> +                       goto out;
> +               }
> +
> +               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);
> +out:
> +
> +       return ret;
> +}
> +
> +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;
> +               msleep(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;
> +               msleep(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 = 0;
> +
> +       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;
> +#define TIMEOUT_RESOLUTION 50  /* ms */
> +#define PHY_CONNECT_TIMEOUT 5000
> +       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;
> +
> +#define USB_BULK_SEND_TIMEOUT 5000
> +
> +       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 = %lu, 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[agg_buf_sz];
> +       unsigned char *pkt_ptr;
> +       int err;
> +       int actual_len;
> +       u16 packet_len;
> +
> +       u32 bytes_process = 0;
> +
> +       struct rx_desc *rx_desc;
> +
> +#define USB_BULK_RECV_TIMEOUT 5000
> +
> +       debug("** %s()\n", __func__);
> +
> +       err = usb_bulk_msg(dev->pusb_dev,
> +                               usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in),
> +                               (void *)recv_buf,
> +                               agg_buf_sz,
> +                               &actual_len,
> +                               USB_BULK_RECV_TIMEOUT);
> +       debug("Rx: len = %u, actual = %u, err = %d\n", agg_buf_sz,
> +             actual_len, err);
> +       if (err != 0) {
> +               debug("Rx: failed to receive\n");
> +               return -1;
> +       }
> +       if (actual_len > 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);
> +
> +       printf("MAC %pM\n", eth->enetaddr);

Is it reasonable to print here? This should probably be a debug() and
it should include something about it being written to the MAC filter
on the device.

> +       return 0;
> +}
> +
> +void r8152_eth_before_probe(void)
> +{
> +       curr_eth_dev = 0;
> +}
> +
> +
> +/* Probe to see if a new device is actually an asix device */

Perhaps you mean Realtek? Was this comment copied from the Asix driver?

> +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; r8152_dongles[i].vendor != 0; 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) {
> +                               if (!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(eth) < 0)
> +               return 0;
> +
> +       debug("MAC %pM\n", eth->enetaddr);
> +       return 1;
> +}
> diff --git a/drivers/usb/eth/usb_ether.c b/drivers/usb/eth/usb_ether.c
> index 62d20f0..215b3d8 100644
> --- a/drivers/usb/eth/usb_ether.c
> +++ b/drivers/usb/eth/usb_ether.c
> @@ -180,6 +180,14 @@ 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
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v3 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-11-25  5:30                               ` [U-Boot] [PATCH v2 " Ted Chen
                                                   ` (2 preceding siblings ...)
  2015-11-30 22:07                                 ` Joe Hershberger
@ 2015-12-01 11:24                                 ` Ted Chen
  2015-12-01 15:10                                   ` Marek Vasut
                                                     ` (2 more replies)
  3 siblings, 3 replies; 64+ messages in thread
From: Ted Chen @ 2015-12-01 11:24 UTC (permalink / raw)
  To: u-boot

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     | 1522 +++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/eth/r8152.h     |  614 +++++++++++++++++
 drivers/usb/eth/r8152_fw.c  |  980 ++++++++++++++++++++++++++++
 drivers/usb/eth/usb_ether.c |    7 +
 include/usb_ether.h         |    6 +
 6 files changed, 3130 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.

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..78d0b38
--- /dev/null
+++ b/drivers/usb/eth/r8152.c
@@ -0,0 +1,1522 @@
+/*
+ * 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 },
+
+	{ 0x0000, 0x0000 }	/* END - Do not remove */
+};
+
+static
+int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
+{
+	int ret;
+
+	ret = usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0),
+			      RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
+			      value, index, data, size, 500);
+
+	return ret;
+}
+
+static
+int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
+{
+	int ret;
+
+	ret = usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0),
+			      RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE,
+			      value, index, data, size, 500);
+
+	return ret;
+}
+
+int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
+		     void *data, u16 type)
+{
+	u16 burst_size = 64;
+	int ret = 0;
+
+	/* 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) {
+		if (size > burst_size) {
+			ret = get_registers(tp, index, type, burst_size, data);
+			if (ret < 0)
+				break;
+
+			index += burst_size;
+			data += burst_size;
+			size -= burst_size;
+		} else {
+			ret = get_registers(tp, index, type, size, data);
+			if (ret < 0)
+				break;
+
+			index += size;
+			data += size;
+			size = 0;
+			break;
+		}
+	}
+
+	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;
+
+	/* 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) {
+			if (size > burst_size) {
+				ret = set_registers(tp, index,
+						    type | BYTE_EN_DWORD,
+						    burst_size, data);
+				if (ret < 0)
+					return ret;
+
+				index += burst_size;
+				data += burst_size;
+				size -= burst_size;
+			} else {
+				ret = set_registers(tp, index,
+						    type | BYTE_EN_DWORD,
+						    size, data);
+				if (ret < 0)
+					return ret;
+
+				index += size;
+				data += size;
+				size = 0;
+				break;
+			}
+		}
+
+		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 (u16)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_nic_reset(struct r8152 *tp)
+{
+	int	i;
+
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, PLA_CR_RST);
+
+	for (i = 0; i < 1000; i++) {
+		if (!(ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR) & PLA_CR_RST))
+			break;
+
+		udelay(400);
+	}
+}
+
+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;
+	int i;
+
+	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);
+
+	for (i = 0; i < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if ((ocp_data & FIFO_EMPTY) == FIFO_EMPTY)
+			break;
+
+		mdelay(2);
+	}
+
+	for (i = 0; i < 1000; i++) {
+		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0) & TCR0_TX_EMPTY)
+			break;
+		mdelay(2);
+	}
+
+	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 = 0;
+	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 r8152b_exit_oob(struct r8152 *tp)
+{
+	u32 ocp_data;
+	int i;
+
+	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);
+
+	for (i = 0; i < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+
+		mdelay(2);
+	}
+
+	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 < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		mdelay(2);
+	}
+
+	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;
+	int i;
+
+	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);
+
+	for (i = 0; i < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		mdelay(2);
+	}
+
+	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 < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		mdelay(2);
+	}
+
+	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;
+	int i;
+
+	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);
+
+	for (i = 0; i < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		mdelay(2);
+	}
+
+	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 < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		mdelay(2);
+	}
+
+	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;
+	int i;
+
+	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);
+
+	for (i = 0; i < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		mdelay(2);
+	}
+
+	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 < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		mdelay(2);
+	}
+
+	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 = 0;
+
+	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;
+#define TIMEOUT_RESOLUTION 50	/* ms */
+#define PHY_CONNECT_TIMEOUT 5000
+	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;
+
+#define USB_BULK_SEND_TIMEOUT 5000
+
+	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;
+
+#define USB_BULK_RECV_TIMEOUT 5000
+
+	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; r8152_dongles[i].vendor != 0; 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) {
+				if (!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..b3a1bc0
--- /dev/null
+++ b/drivers/usb/eth/r8152.h
@@ -0,0 +1,614 @@
+/*
+ * 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    */
+
+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..86bdf5a
--- /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

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v3 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  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 16:32                                   ` Simon Glass
  2016-01-13 18:27                                   ` Stephen Warren
  2 siblings, 1 reply; 64+ messages in thread
From: Marek Vasut @ 2015-12-01 15:10 UTC (permalink / raw)
  To: u-boot

On Tuesday, December 01, 2015 at 12:24:41 PM, Ted Chen wrote:
> This patch adds driver support for the Realtek RTL8152B/RTL8153 USB
> network adapters.

Hi!

looks pretty good, just a few final nitpicks below.

> 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()]

This changelog should be removed, really. It doesn't have to be in the commit 
message, right ?

> Signed-off-by: Stephen Warren <swarren@nvidia.com>

[...]

> +#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 */

This $curr_eth_dev doesn't seem very DM friendly. Is this really needed?

> +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 },
> +
> +	{ 0x0000, 0x0000 }	/* END - Do not remove */
> +};
> +
> +static
> +int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void
> *data) +{
> +	int ret;
> +
> +	ret = usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0),
> +			      RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
> +			      value, index, data, size, 500);
> +
> +	return ret;
> +}
> +
> +static
> +int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void
> *data) +{
> +	int ret;
> +
> +	ret = usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0),
> +			      RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE,
> +			      value, index, data, size, 500);
> +
> +	return ret;
> +}
> +
> +int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
> +		     void *data, u16 type)
> +{
> +	u16 burst_size = 64;
> +	int ret = 0;

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;

And you can drop this whole conditional statement. Right ?

> +		if (size > burst_size) {
> +			ret = get_registers(tp, index, type, burst_size, data);
> +			if (ret < 0)
> +				break;
> +
> +			index += burst_size;
> +			data += burst_size;
> +			size -= burst_size;
> +		} else {
> +			ret = get_registers(tp, index, type, size, data);
> +			if (ret < 0)
> +				break;
> +
> +			index += size;
> +			data += size;
> +			size = 0;
> +			break;
> +		}
> +	}
> +
> +	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;
> +
> +	/* 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) {
> +			if (size > burst_size) {
> +				ret = set_registers(tp, index,
> +						    type | BYTE_EN_DWORD,
> +						    burst_size, data);
> +				if (ret < 0)
> +					return ret;
> +
> +				index += burst_size;
> +				data += burst_size;
> +				size -= burst_size;
> +			} else {
> +				ret = set_registers(tp, index,
> +						    type | BYTE_EN_DWORD,
> +						    size, data);
> +				if (ret < 0)
> +					return ret;
> +
> +				index += size;
> +				data += size;
> +				size = 0;
> +				break;

DTTO here

> +			}
> +		}
> +
> +		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;
> +}

[...]

> +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;

Can you please review the typecasts in the driver ? I don't think that a
lot of them are really necessary.

> +	return (u16)data;
> +}

[...]

> +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 < 1000; i++) {
> +		if (!(ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR) & PLA_CR_RST))
> +			break;
> +
> +		udelay(400);
> +	}

So what exactly happens if this function fails 1000 times ? The NIC will not
be reset, but the code will proceed with whatever other actions?

> +}

[...]

> +static void rtl_disable(struct r8152 *tp)
> +{
> +	u32 ocp_data;
> +	int i;
> +
> +	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);
> +
> +	for (i = 0; i < 1000; i++) {

You might want to pull this magic value, 1000, into a macro, since it's being
pretty repetitive in this driver. It seems to have some sort of significance.

> +		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
> +		if ((ocp_data & FIFO_EMPTY) == FIFO_EMPTY)
> +			break;
> +
> +		mdelay(2);
> +	}
> +
> +	for (i = 0; i < 1000; i++) {
> +		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0) & TCR0_TX_EMPTY)
> +			break;
> +		mdelay(2);
> +	}
> +
> +	rtl8152_nic_reset(tp);
> +}

[...]

> +static int r8152_init(struct eth_device *eth, bd_t *bd)
> +{
> +	struct ueth_data	*dev = (struct ueth_data *)eth->priv;

ueth_data[SPACE]*dev please.

> +	struct r8152 *tp = (struct r8152 *)dev->dev_priv;
> +
> +	u8 speed;
> +	int timeout = 0;
> +#define TIMEOUT_RESOLUTION 50	/* ms */
> +#define PHY_CONNECT_TIMEOUT 5000

I'd suggest to use const variable instead to leverage the typechecking.

> +	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;
> +
> +#define USB_BULK_SEND_TIMEOUT 5000

DTTO here and in all the places where you use #define FOO in a function.

> +	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;
> +}

[...]

> +/* 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; r8152_dongles[i].vendor != 0; i++) {

Maybe you can use ARRAY_SIZE() instead and avoid having 0x00 as a terminating
entry in the array . What do you think ?

> +		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) {
> +				if (!ep_in_found) {

You can probably rewrite it this way

if (!ep_in_found && (ep_addr & USB_DIR_IN)) {
 do stuff ...
}

This might trim down the indentation, which looks really bad. But if it doesn't,
then don't worry about this.

> +					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;
> +		}
> +	}

[...]

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v3 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-12-01 15:10                                   ` Marek Vasut
@ 2015-12-01 16:31                                     ` Stephen Warren
  2015-12-01 17:11                                       ` Marek Vasut
  0 siblings, 1 reply; 64+ messages in thread
From: Stephen Warren @ 2015-12-01 16:31 UTC (permalink / raw)
  To: u-boot

On 12/01/2015 08:10 AM, Marek Vasut wrote:
> On Tuesday, December 01, 2015 at 12:24:41 PM, Ted Chen wrote:
>> This patch adds driver support for the Realtek RTL8152B/RTL8153 USB
>> network adapters.
>
> Hi!
>
> looks pretty good, just a few final nitpicks below.
>
>> 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()]
>
> This changelog should be removed, really. It doesn't have to be in the commit
> message, right ?

In general it's good practice when people edit someone else's patch to 
note that in the patch description so that it's obvious who to blame for 
what.

However in this particular case an exception could likely be made since 
the original patch author has taken over the patch again and made 
significantly more changes than listed above.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v3 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-12-01 11:24                                 ` [U-Boot] [PATCH v3 " Ted Chen
  2015-12-01 15:10                                   ` Marek Vasut
@ 2015-12-01 16:32                                   ` Simon Glass
  2016-01-13 18:27                                   ` Stephen Warren
  2 siblings, 0 replies; 64+ messages in thread
From: Simon Glass @ 2015-12-01 16:32 UTC (permalink / raw)
  To: u-boot

Hi Ted,

On 1 December 2015 at 04:24, Ted Chen <tedchen@realtek.com> wrote:
> 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     | 1522 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/usb/eth/r8152.h     |  614 +++++++++++++++++
>  drivers/usb/eth/r8152_fw.c  |  980 ++++++++++++++++++++++++++++
>  drivers/usb/eth/usb_ether.c |    7 +
>  include/usb_ether.h         |    6 +
>  6 files changed, 3130 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.

NAK from me. This should use driver model.

Please look at smsc95xx.c or asix.c for an example. Also this one:

http://patchwork.ozlabs.org/patch/549812/
http://patchwork.ozlabs.org/patch/549807/

Also I think you *only* need to support driver model, since you can
require any new platforms to enable it for Ethernet.

Regards,
Simon

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v3 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-12-01 16:31                                     ` Stephen Warren
@ 2015-12-01 17:11                                       ` Marek Vasut
  0 siblings, 0 replies; 64+ messages in thread
From: Marek Vasut @ 2015-12-01 17:11 UTC (permalink / raw)
  To: u-boot

On Tuesday, December 01, 2015 at 05:31:30 PM, Stephen Warren wrote:
> On 12/01/2015 08:10 AM, Marek Vasut wrote:
> > On Tuesday, December 01, 2015 at 12:24:41 PM, Ted Chen wrote:
> >> This patch adds driver support for the Realtek RTL8152B/RTL8153 USB
> >> network adapters.
> > 
> > Hi!
> > 
> > looks pretty good, just a few final nitpicks below.
> > 
> >> 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()]
> > 
> > This changelog should be removed, really. It doesn't have to be in the
> > commit message, right ?
> 
> In general it's good practice when people edit someone else's patch to
> note that in the patch description so that it's obvious who to blame for
> what.
> 
> However in this particular case an exception could likely be made since
> the original patch author has taken over the patch again and made
> significantly more changes than listed above.

OK, whichever way you prefer then.

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 1/2] checkpatch: ignore request to use ether_addr_copy()
  2015-11-23 23:36 ` Joe Hershberger
@ 2015-12-15 23:34   ` Stephen Warren
  2015-12-15 23:41     ` Joe Hershberger
  0 siblings, 1 reply; 64+ messages in thread
From: Stephen Warren @ 2015-12-15 23:34 UTC (permalink / raw)
  To: u-boot

On 11/23/2015 04:36 PM, Joe Hershberger wrote:
> On Fri, Nov 13, 2015 at 10:03 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> From: Stephen Warren <swarren@nvidia.com>
>>
>> The Linux kernel, from which checkpatch originates, contains function
>> ether_addr_copy() to copy Ethernet MAC addresses, and checkpatch warns
>> that it should be used in preference to memcpy() where appropriate.
>> U-Boot doesn't contain ether_addr_copy(), so tell checkpatch not to issue
>> this warning.
>>
>> Signed-off-by: Stephen Warren <swarren@nvidia.com>
>
> Acked-by: Joe Hershberger <joe.hershberger@ni.com>

Were you intending someone else to apply this? I think now that Ted Chen 
has taken over the USB NIC driver (which was patch 2 in this series), 
this patch should be applied separately.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 1/2] checkpatch: ignore request to use ether_addr_copy()
  2015-12-15 23:34   ` Stephen Warren
@ 2015-12-15 23:41     ` Joe Hershberger
       [not found]       ` <56969621.30204@wwwdotorg.org>
  0 siblings, 1 reply; 64+ messages in thread
From: Joe Hershberger @ 2015-12-15 23:41 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On Tue, Dec 15, 2015 at 5:34 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 11/23/2015 04:36 PM, Joe Hershberger wrote:
>>
>> On Fri, Nov 13, 2015 at 10:03 AM, Stephen Warren <swarren@wwwdotorg.org>
>> wrote:
>>>
>>> From: Stephen Warren <swarren@nvidia.com>
>>>
>>> The Linux kernel, from which checkpatch originates, contains function
>>> ether_addr_copy() to copy Ethernet MAC addresses, and checkpatch warns
>>> that it should be used in preference to memcpy() where appropriate.
>>> U-Boot doesn't contain ether_addr_copy(), so tell checkpatch not to issue
>>> this warning.
>>>
>>> Signed-off-by: Stephen Warren <swarren@nvidia.com>
>>
>>
>> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
>
>
> Were you intending someone else to apply this? I think now that Ted Chen has
> taken over the USB NIC driver (which was patch 2 in this series), this patch
> should be applied separately.

It is assigned to Marek in patchwork. If he's not going to take it,
then assign it to me and I'll pull it in.

-Joe

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v3 2/2] usb: eth: add Realtek RTL8152B/RTL8153 driver
  2015-12-01 11:24                                 ` [U-Boot] [PATCH v3 " Ted Chen
  2015-12-01 15:10                                   ` 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
  2 siblings, 1 reply; 64+ messages in thread
From: Stephen Warren @ 2016-01-13 18:27 UTC (permalink / raw)
  To: u-boot

On 12/01/2015 04:24 AM, Ted Chen wrote:
> This patch adds driver support for the Realtek RTL8152B/RTL8153 USB
> network adapters.

Ted, are you going to repost a new version to address the review comments?

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v4 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  2016-01-13 18:27                                   ` Stephen Warren
@ 2016-01-14  4:37                                     ` Ted Chen
  2016-01-14  4:42                                       ` Marek Vasut
  0 siblings, 1 reply; 64+ messages in thread
From: Ted Chen @ 2016-01-14  4:37 UTC (permalink / raw)
  To: u-boot

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

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

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v4 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  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
  0 siblings, 1 reply; 64+ messages in thread
From: Marek Vasut @ 2016-01-14  4:42 UTC (permalink / raw)
  To: u-boot

On Thursday, January 14, 2016 at 05:37:18 AM, Ted Chen wrote:
> 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

Where is the changelog ?

Sorry, I don't feel like reviewing 1.5k LoC all over again :-(

[...]

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v4 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  2016-01-14  4:42                                       ` Marek Vasut
@ 2016-01-14  5:22                                         ` Ted Chen
  2016-01-14  5:37                                           ` Marek Vasut
  0 siblings, 1 reply; 64+ messages in thread
From: Ted Chen @ 2016-01-14  5:22 UTC (permalink / raw)
  To: u-boot

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

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v4 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  2016-01-14  5:22                                         ` Ted Chen
@ 2016-01-14  5:37                                           ` Marek Vasut
  2016-01-20  6:24                                             ` [U-Boot] [PATCH v5 " Ted Chen
  0 siblings, 1 reply; 64+ messages in thread
From: Marek Vasut @ 2016-01-14  5:37 UTC (permalink / raw)
  To: u-boot

On Thursday, January 14, 2016 at 06:22:07 AM, Ted Chen wrote:
> This patch adds driver support for the Realtek RTL8152B/RTL8153 USB
> network adapters.

[...]

> +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);

You can implement something like wait_for_bit() here to avoid having multiple
copies of the same code.

> +	}
> +
> +	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);
> +	}

DTTO here.

> +	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 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;

I'd implement this as a lookup table, it might be more readable.
What do you think ?

> +		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 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);

Yet another ad-hoc wait_for_bit() implementation here.

> +	}
> +
> +	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);

And here ...

> +	}
> +
> +	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);
> +}

[...]

> 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

[...]

> +static void patch4(struct r8152 *tp)

Please make this consistent and name it with r8153_ prefix. Some more
obvious name would help too, patch4 doesn't tell me anything about the
function or what it does.

> +{
> +	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 void r8153_wdt1_end(struct r8152 *tp)
> +{

This is, again, ad-hoc implementation of wait_for_bit() alike.

> +	int i;
> +
> +	for (i = 0; i < 104; i++) {
> +		if (!(ocp_read_byte(tp, MCU_TYPE_USB, 0xe404) & 1))
> +			break;
> +		mdelay(2);
> +	}
> +}

[...]

Thanks!

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  2016-01-14  5:37                                           ` Marek Vasut
@ 2016-01-20  6:24                                             ` Ted Chen
  2016-01-20 13:08                                               ` Marek Vasut
                                                                 ` (2 more replies)
  0 siblings, 3 replies; 64+ messages in thread
From: Ted Chen @ 2016-01-20  6:24 UTC (permalink / raw)
  To: u-boot

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     | 1456 +++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/eth/r8152.h     |  631 +++++++++++++++++++
 drivers/usb/eth/r8152_fw.c  |  980 +++++++++++++++++++++++++++++
 drivers/usb/eth/usb_ether.c |    7 +
 include/usb_ether.h         |    6 +
 6 files changed, 3081 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.

Changes for v5: Modified by Marek's comments.
- add r8152_wait_for_bit to replace busy wait.
- change the name of patch4 to r8152b_set_dq_desc.
- add r8152_versions to store the hw's version.

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..325b70c
--- /dev/null
+++ b/drivers/usb/eth/r8152.c
@@ -0,0 +1,1456 @@
+/*
+ * 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;
+};
+
+struct r8152_version {
+	unsigned short tcr;
+	unsigned short version;
+	bool           gmii;
+};
+
+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 const struct r8152_version const r8152_versions[] = {
+	{ 0x4c00, RTL_VER_01, 0 },
+	{ 0x4c10, RTL_VER_02, 0 },
+	{ 0x5c00, RTL_VER_03, 1 },
+	{ 0x5c10, RTL_VER_04, 1 },
+	{ 0x5c20, RTL_VER_05, 1 },
+	{ 0x5c30, RTL_VER_06, 1 },
+	{ 0x4800, RTL_VER_07, 0 },
+};
+
+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);
+}
+
+int r8152_wait_for_bit(struct r8152 *tp, bool ocp_reg, u16 type, u16 index,
+		       const u32 mask, bool set, unsigned int timeout)
+{
+	u32 val;
+
+	while (--timeout) {
+		if (ocp_reg)
+			val = ocp_reg_read(tp, index);
+		else
+			val = ocp_read_dword(tp, type, index);
+
+		if (!set)
+			val = ~val;
+
+		if ((val & mask) == mask)
+			return 0;
+
+		mdelay(1);
+	}
+
+	debug("%s: Timeout (index=%04x mask=%08x timeout=%d)\n",
+	      __func__, index, mask, timeout);
+
+	return -ETIMEDOUT;
+}
+
+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 ret;
+
+	ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_PHY_PWR,
+				 PLA_PHY_PWR_TXEMP, 1, R8152_WAIT_TIMEOUT);
+	if (ret)
+		debug("Timeout waiting for FIFO empty\n");
+
+	ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_TCR0,
+				 TCR0_TX_EMPTY, 1, R8152_WAIT_TIMEOUT);
+	if (ret)
+		debug("Timeout waiting for TX empty\n");
+}
+
+static void rtl8152_nic_reset(struct r8152 *tp)
+{
+	int ret;
+	u32 ocp_data;
+
+	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, BIST_CTRL);
+	ocp_data |= BIST_CTRL_SW_RESET;
+	ocp_write_dword(tp, MCU_TYPE_PLA, BIST_CTRL, ocp_data);
+
+	ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, BIST_CTRL,
+				 BIST_CTRL_SW_RESET, 0, R8152_WAIT_TIMEOUT);
+	if (ret)
+		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 ret;
+
+	ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_PHY_PWR,
+				 PLA_PHY_PWR_LLR, 1, R8152_WAIT_TIMEOUT);
+	if (ret)
+		debug("Timeout waiting for link list ready\n");
+
+	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);
+
+	ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_PHY_PWR,
+				 PLA_PHY_PWR_LLR, 1, R8152_WAIT_TIMEOUT);
+	if (ret)
+		debug("Timeout waiting for link list ready\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 tcr;
+	int i;
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR1);
+	tcr = (u16)(ocp_data & VERSION_MASK);
+
+	for (i = 0; i < ARRAY_SIZE(r8152_versions); i++) {
+		if (tcr == r8152_versions[i].tcr) {
+			/* Found a supported version */
+			tp->version = r8152_versions[i].version;
+			tp->supports_gmii = r8152_versions[i].gmii;
+			break;
+		}
+	}
+
+	if (tp->version == RTL_VER_UNKNOWN)
+		debug("r8152 Unknown tcr version 0x%04x\n", tcr);
+}
+
+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)
+{
+	int i;
+	u32 ocp_data;
+
+	r8153_disable_aldps(tp);
+	r8153_u1u2en(tp, false);
+
+	r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_BOOT_CTRL,
+			   AUTOLOAD_DONE, 1, R8152_WAIT_TIMEOUT);
+
+	for (i = 0; i < R8152_WAIT_TIMEOUT; 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(1);
+	}
+
+	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 = 0;
+
+	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("r8152 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; i < 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 (i == ARRAY_SIZE(r8152_dongles))
+		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..cd44da2
--- /dev/null
+++ b/drivers/usb/eth/r8152.h
@@ -0,0 +1,631 @@
+/*
+ * 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 BIST_CTRL		0xe810
+#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_BIST_CTRL */
+#define BIST_CTRL_SW_RESET (0x10 << 24)
+
+/* 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_PHY_PWR */
+#define PLA_PHY_PWR_LLR	(LINK_LIST_READY << 24)
+#define PLA_PHY_PWR_TXEMP	(TXFIFO_EMPTY << 24)
+
+/* 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 R8152_WAIT_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);
+
+int r8152_wait_for_bit(struct r8152 *tp, bool ocp_reg, u16 type, u16 index,
+		       const u32 mask, bool set, unsigned int timeout);
+
+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..f820b16
--- /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 r8152b_set_dq_desc(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;
+
+		r8152b_set_dq_desc(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

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  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-22 19:50                                               ` Joe Hershberger
  2 siblings, 0 replies; 64+ messages in thread
From: Marek Vasut @ 2016-01-20 13:08 UTC (permalink / raw)
  To: u-boot

On Wednesday, January 20, 2016 at 07:24:52 AM, Ted Chen wrote:
> 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>

Looks good,

Acked-by: Marek Vasut <marex@denx.de>

Let's see if others have any comments and I can pick it then.

[...]

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  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-22 19:50                                               ` Joe Hershberger
  2 siblings, 1 reply; 64+ messages in thread
From: Stephen Warren @ 2016-01-20 16:52 UTC (permalink / raw)
  To: u-boot

On 01/19/2016 11:24 PM, Ted Chen wrote:
> This patch adds driver support for the Realtek RTL8152B/RTL8153 USB
> network adapters.

This looks fine to me, although I didn't take a detailed enough look to 
actually give and an ack/reviewed-by.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  2016-01-20 16:52                                               ` Stephen Warren
@ 2016-01-20 20:10                                                 ` Anand Moon
  2016-01-20 20:34                                                   ` Marek Vasut
  0 siblings, 1 reply; 64+ messages in thread
From: Anand Moon @ 2016-01-20 20:10 UTC (permalink / raw)
  To: u-boot

Hi Ted / Marek / Stephen,

On 20 January 2016 at 22:22, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 01/19/2016 11:24 PM, Ted Chen wrote:
>>
>> This patch adds driver support for the Realtek RTL8152B/RTL8153 USB
>> network adapters.
>
>
> This looks fine to me, although I didn't take a detailed enough look to
> actually give and an ack/reviewed-by.

What about the other patch: usb xhci Fix vendor command error if the
request.patch

After setting the usbether mac address my odroid xu4 board shop booting.
even after reset of environment it dose not boot.
---------------------------------------------------------------------------------------------------------
U-Boot 2016.01-00406-g048c61d-dirty (Jan 21 2016 - 06:27:09 +1030) for
ODROID-XU3

CPU:   Exynos5422 @ 800 MHz
Model: Odroid XU3 based on EXYNOS5422
Board: Odroid XU3 based on EXYNOS5422
Type:  xu4
DRAM:  2 GiB
MMC:   EXYNOS DWMMC: 0, EXYNOS DWMMC: 1
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   No ethernet found.
Hit any key to stop autoboot:  0
ODROID-XU3 #
ODROID-XU3 #
ODROID-XU3 #
ODROID-XU3 # setenv usbethaddr 00:1e:06:31:06:b3
ODROID-XU3 # saveenv
Saving Environment to MMC...
Writing to MMC(0)... done
ODROID-XU3 # usb info
USB is stopped. Please issue 'usb start' first.
ODROID-XU3 # usb start
starting USB...
USB0:   USB EHCI 1.00
USB1:   Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.00
USB2:   Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.00
scanning bus 0 for devices... 1 USB Device(s) found
scanning bus 1 for devices... Device not responding to set address.

      USB device not accepting new address (error=80000000)
2 USB Device(s) found
scanning bus 2 for devices... 2 USB Device(s) found
       scanning usb for ethernet devices... 1 Ethernet Device(s) found
ODROID-XU3 # usb info
1: Hub,  USB Revision 2.0
 - u-boot EHCI Host Controller
 - Class: Hub
 - PacketSize: 64  Configurations: 1
 - Vendor: 0x0000  Product 0x0000 Version 1.0
   Configuration: 1
   - Interfaces: 1 Self Powered 0mA
     Interface: 0
     - Alternate Setting 0, Endpoints: 1
     - Class Hub
     - Endpoint 1 In Interrupt MaxPacket 8 Interval 255ms

1: Hub,  USB Revision 3.0
 - U-Boot XHCI Host Controller
 - Class: Hub
 - PacketSize: 9  Configurations: 1
 - Vendor: 0x0000  Product 0x0000 Version 1.0
   Configuration: 1
   - Interfaces: 1 Self Powered 0mA
     Interface: 0
     - Alternate Setting 0, Endpoints: 1
     - Class Hub
     - Endpoint 1 In Interrupt MaxPacket 8 Interval 255ms

2: Hub,  USB Revision 2.10
 - GenesysLogic USB2.0 Hub
 - Class: Hub
 - PacketSize: 64  Configurations: 1
 - Vendor: 0x05e3  Product 0x0610 Version 146.34
   Configuration: 1
   - Interfaces: 1 Self Powered Remote Wakeup 100mA
     Interface: 0
     - Alternate Setting 0, Endpoints: 1
     - Class Hub
     - Endpoint 1 In Interrupt MaxPacket 1 Interval 12ms
     - Endpoint 1 In Interrupt MaxPacket 1 Interval 12ms

1: Hub,  USB Revision 3.0
 - U-Boot XHCI Host Controller
 - Class: Hub
 - PacketSize: 9  Configurations: 1
 - Vendor: 0x0000  Product 0x0000 Version 1.0
   Configuration: 1
   - Interfaces: 1 Self Powered 0mA
     Interface: 0
     - Alternate Setting 0, Endpoints: 1
     - Class Hub
     - Endpoint 1 In Interrupt MaxPacket 8 Interval 255ms

2: Vendor specific,  USB Revision 2.10
 - Realtek USB 10/100/1000 LAN 000001000000
 - Class: (from Interface) Vendor specific
 - PacketSize: 64  Configurations: 2
 - Vendor: 0x0bda  Product 0x8153 Version 48.0
   Configuration: 1
   - Interfaces: 1 Bus Powered Remote Wakeup 180mA
     Interface: 0
     - Alternate Setting 0, Endpoints: 3
     - Class Vendor specific
     - Endpoint 1 In Bulk MaxPacket 512
     - Endpoint 2 Out Bulk MaxPacket 512
     - Endpoint 3 In Interrupt MaxPacket 2 Interval 8ms

ODROID-XU3 # reset
resetting ...


U-Boot 2016.01-00406-g048c61d-dirty (Jan 21 2016 - 06:27:09 +1030) for
ODROID-XU3

CPU:   Exynos5422 @ 800 MHz
Model: Odroid XU3 based on EXYNOS5422
Board: Odroid XU3 based on EXYNOS5422
Type:  xu4
DRAM:  2 GiB
MMC:   EXYNOS DWMMC: 0, EXYNOS DWMMC: 1
In:    serial
Out:   serial
Err:   serial
Net:   No ethernet found.
Hit any key to stop autoboot:  0
Card did not respond to voltage select!
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
Found U-Boot script /boot.scr
reading /boot.scr
3033 bytes read in 3 ms (987.3 KiB/s)
## Executing script at 50000000
Found kernel image: zImage
reading exynos5422-odroidxu4.dtb
50674 bytes read in 9 ms (5.4 MiB/s)
Found ramdisk image.
reading uInitrd
2159156 bytes read in 127 ms (16.2 MiB/s)
reading zImage
3225648 bytes read in 187 ms (16.4 MiB/s)
Kernel image @ 0x40007fc0 [ 0x000000 - 0x313830 ]
## Loading init Ramdisk from Legacy Image at 42000000 ...
   Image Name:   uInitrd 3.10.92
   Image Type:   ARM Linux RAMDisk Image (uncompressed)
   Data Size:    2159092 Bytes = 2.1 MiB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK
## Flattened Device Tree blob at 40800000
   Booting using the fdt blob at 0x40800000
   Loading Ramdisk to 4fdf0000, end 4ffff1f4 ... OK
   Loading Device Tree to 4fde0000, end 4fdef5f1 ... OK

Starting kernel ...


Best regards.
-Anand Moon

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  2016-01-20 20:10                                                 ` Anand Moon
@ 2016-01-20 20:34                                                   ` Marek Vasut
  2016-01-21  8:55                                                     ` Anand Moon
  0 siblings, 1 reply; 64+ messages in thread
From: Marek Vasut @ 2016-01-20 20:34 UTC (permalink / raw)
  To: u-boot

On Wednesday, January 20, 2016 at 09:10:07 PM, Anand Moon wrote:
> Hi Ted / Marek / Stephen,
> 
> On 20 January 2016 at 22:22, Stephen Warren <swarren@wwwdotorg.org> wrote:
> > On 01/19/2016 11:24 PM, Ted Chen wrote:
> >> This patch adds driver support for the Realtek RTL8152B/RTL8153 USB
> >> network adapters.
> > 
> > This looks fine to me, although I didn't take a detailed enough look to
> > actually give and an ack/reviewed-by.
> 
> What about the other patch: usb xhci Fix vendor command error if the
> request.patch

Please repost it , make sure to CC everyone . If there is agreement that
it fixes real issue, I'll pick it.

> After setting the usbether mac address my odroid xu4 board shop booting.
> even after reset of environment it dose not boot.
> ---------------------------------------------------------------------------
> ------------------------------ U-Boot 2016.01-00406-g048c61d-dirty (Jan 21
> 2016 - 06:27:09 +1030) for ODROID-XU3
> 
> CPU:   Exynos5422 @ 800 MHz
> Model: Odroid XU3 based on EXYNOS5422
> Board: Odroid XU3 based on EXYNOS5422
> Type:  xu4
> DRAM:  2 GiB
> MMC:   EXYNOS DWMMC: 0, EXYNOS DWMMC: 1
> *** Warning - bad CRC, using default environment
> 
> In:    serial
> Out:   serial
> Err:   serial
> Net:   No ethernet found.
> Hit any key to stop autoboot:  0
> ODROID-XU3 #
> ODROID-XU3 #
> ODROID-XU3 #
> ODROID-XU3 # setenv usbethaddr 00:1e:06:31:06:b3
> ODROID-XU3 # saveenv

You ran saveenv, so usbethaddr is now in permanent storage. That's why
'reset' won't help you.

> Saving Environment to MMC...
> Writing to MMC(0)... done
> ODROID-XU3 # usb info
> USB is stopped. Please issue 'usb start' first.
> ODROID-XU3 # usb start
> starting USB...
> USB0:   USB EHCI 1.00
> USB1:   Register 2000140 NbrPorts 2
> Starting the controller
> USB XHCI 1.00
> USB2:   Register 2000140 NbrPorts 2
> Starting the controller
> USB XHCI 1.00
> scanning bus 0 for devices... 1 USB Device(s) found
> scanning bus 1 for devices... Device not responding to set address.
> 
>       USB device not accepting new address (error=80000000)

This error looks suspicious.

> 2 USB Device(s) found
> scanning bus 2 for devices... 2 USB Device(s) found
>        scanning usb for ethernet devices... 1 Ethernet Device(s) found
[...]

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 1/2] checkpatch: ignore request to use ether_addr_copy()
       [not found]       ` <56969621.30204@wwwdotorg.org>
@ 2016-01-20 20:47         ` Stephen Warren
  2016-01-20 21:00           ` Tom Rini
  0 siblings, 1 reply; 64+ messages in thread
From: Stephen Warren @ 2016-01-20 20:47 UTC (permalink / raw)
  To: u-boot

On 01/13/2016 11:23 AM, Stephen Warren wrote:
> On 12/15/2015 04:41 PM, Joe Hershberger wrote:
>> Hi Stephen,
>>
>> On Tue, Dec 15, 2015 at 5:34 PM, Stephen Warren
>> <swarren@wwwdotorg.org> wrote:
>>> On 11/23/2015 04:36 PM, Joe Hershberger wrote:
>>>>
>>>> On Fri, Nov 13, 2015 at 10:03 AM, Stephen Warren
>>>> <swarren@wwwdotorg.org>
>>>> wrote:
>>>>>
>>>>> From: Stephen Warren <swarren@nvidia.com>
>>>>>
>>>>> The Linux kernel, from which checkpatch originates, contains function
>>>>> ether_addr_copy() to copy Ethernet MAC addresses, and checkpatch warns
>>>>> that it should be used in preference to memcpy() where appropriate.
>>>>> U-Boot doesn't contain ether_addr_copy(), so tell checkpatch not to
>>>>> issue
>>>>> this warning.
>>>>>
>>>>> Signed-off-by: Stephen Warren <swarren@nvidia.com>
>>>>
>>>>
>>>> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
>>>
>>>
>>> Were you intending someone else to apply this? I think now that Ted
>>> Chen has
>>> taken over the USB NIC driver (which was patch 2 in this series),
>>> this patch
>>> should be applied separately.
>>
>> It is assigned to Marek in patchwork. If he's not going to take it,
>> then assign it to me and I'll pull it in.
>
> Marek,
>
> Are you taking this patch? If not, could you please re-assign it to Joe;
> I don't believe I can modify patchwork myself.

Marek?

Tom, are you able to re-assign this patch to Joe in patchwork?

Thanks.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 1/2] checkpatch: ignore request to use ether_addr_copy()
  2016-01-20 20:47         ` Stephen Warren
@ 2016-01-20 21:00           ` Tom Rini
  2016-01-20 21:04             ` Stephen Warren
  0 siblings, 1 reply; 64+ messages in thread
From: Tom Rini @ 2016-01-20 21:00 UTC (permalink / raw)
  To: u-boot

On Wed, Jan 20, 2016 at 01:47:55PM -0700, Stephen Warren wrote:
> On 01/13/2016 11:23 AM, Stephen Warren wrote:
> >On 12/15/2015 04:41 PM, Joe Hershberger wrote:
> >>Hi Stephen,
> >>
> >>On Tue, Dec 15, 2015 at 5:34 PM, Stephen Warren
> >><swarren@wwwdotorg.org> wrote:
> >>>On 11/23/2015 04:36 PM, Joe Hershberger wrote:
> >>>>
> >>>>On Fri, Nov 13, 2015 at 10:03 AM, Stephen Warren
> >>>><swarren@wwwdotorg.org>
> >>>>wrote:
> >>>>>
> >>>>>From: Stephen Warren <swarren@nvidia.com>
> >>>>>
> >>>>>The Linux kernel, from which checkpatch originates, contains function
> >>>>>ether_addr_copy() to copy Ethernet MAC addresses, and checkpatch warns
> >>>>>that it should be used in preference to memcpy() where appropriate.
> >>>>>U-Boot doesn't contain ether_addr_copy(), so tell checkpatch not to
> >>>>>issue
> >>>>>this warning.
> >>>>>
> >>>>>Signed-off-by: Stephen Warren <swarren@nvidia.com>
> >>>>
> >>>>
> >>>>Acked-by: Joe Hershberger <joe.hershberger@ni.com>
> >>>
> >>>
> >>>Were you intending someone else to apply this? I think now that Ted
> >>>Chen has
> >>>taken over the USB NIC driver (which was patch 2 in this series),
> >>>this patch
> >>>should be applied separately.
> >>
> >>It is assigned to Marek in patchwork. If he's not going to take it,
> >>then assign it to me and I'll pull it in.
> >
> >Marek,
> >
> >Are you taking this patch? If not, could you please re-assign it to Joe;
> >I don't believe I can modify patchwork myself.
> 
> Marek?
> 
> Tom, are you able to re-assign this patch to Joe in patchwork?

Which? https://patchwork.ozlabs.org/patch/570547/ ?

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160120/ece0235c/attachment.sig>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 1/2] checkpatch: ignore request to use ether_addr_copy()
  2016-01-20 21:00           ` Tom Rini
@ 2016-01-20 21:04             ` Stephen Warren
  2016-01-21  1:22               ` Tom Rini
  0 siblings, 1 reply; 64+ messages in thread
From: Stephen Warren @ 2016-01-20 21:04 UTC (permalink / raw)
  To: u-boot

On 01/20/2016 02:00 PM, Tom Rini wrote:
> On Wed, Jan 20, 2016 at 01:47:55PM -0700, Stephen Warren wrote:
>> On 01/13/2016 11:23 AM, Stephen Warren wrote:
>>> On 12/15/2015 04:41 PM, Joe Hershberger wrote:
>>>> Hi Stephen,
>>>>
>>>> On Tue, Dec 15, 2015 at 5:34 PM, Stephen Warren
>>>> <swarren@wwwdotorg.org> wrote:
>>>>> On 11/23/2015 04:36 PM, Joe Hershberger wrote:
>>>>>>
>>>>>> On Fri, Nov 13, 2015 at 10:03 AM, Stephen Warren
>>>>>> <swarren@wwwdotorg.org>
>>>>>> wrote:
>>>>>>>
>>>>>>> From: Stephen Warren <swarren@nvidia.com>
>>>>>>>
>>>>>>> The Linux kernel, from which checkpatch originates, contains function
>>>>>>> ether_addr_copy() to copy Ethernet MAC addresses, and checkpatch warns
>>>>>>> that it should be used in preference to memcpy() where appropriate.
>>>>>>> U-Boot doesn't contain ether_addr_copy(), so tell checkpatch not to
>>>>>>> issue
>>>>>>> this warning.
>>>>>>>
>>>>>>> Signed-off-by: Stephen Warren <swarren@nvidia.com>
>>>>>>
>>>>>>
>>>>>> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
>>>>>
>>>>>
>>>>> Were you intending someone else to apply this? I think now that Ted
>>>>> Chen has
>>>>> taken over the USB NIC driver (which was patch 2 in this series),
>>>>> this patch
>>>>> should be applied separately.
>>>>
>>>> It is assigned to Marek in patchwork. If he's not going to take it,
>>>> then assign it to me and I'll pull it in.
>>>
>>> Marek,
>>>
>>> Are you taking this patch? If not, could you please re-assign it to Joe;
>>> I don't believe I can modify patchwork myself.
>>
>> Marek?
>>
>> Tom, are you able to re-assign this patch to Joe in patchwork?
>
> Which? https://patchwork.ozlabs.org/patch/570547/ ?

Just patch 1/2 not 2/2:

https://patchwork.ozlabs.org/patch/544360/
checkpatch: ignore request to use ether_addr_copy()

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 1/2] checkpatch: ignore request to use ether_addr_copy()
  2016-01-20 21:04             ` Stephen Warren
@ 2016-01-21  1:22               ` Tom Rini
  2016-01-21  4:09                 ` Joe Hershberger
  0 siblings, 1 reply; 64+ messages in thread
From: Tom Rini @ 2016-01-21  1:22 UTC (permalink / raw)
  To: u-boot

On Wed, Jan 20, 2016 at 02:04:04PM -0700, Stephen Warren wrote:
> On 01/20/2016 02:00 PM, Tom Rini wrote:
> >On Wed, Jan 20, 2016 at 01:47:55PM -0700, Stephen Warren wrote:
> >>On 01/13/2016 11:23 AM, Stephen Warren wrote:
> >>>On 12/15/2015 04:41 PM, Joe Hershberger wrote:
> >>>>Hi Stephen,
> >>>>
> >>>>On Tue, Dec 15, 2015 at 5:34 PM, Stephen Warren
> >>>><swarren@wwwdotorg.org> wrote:
> >>>>>On 11/23/2015 04:36 PM, Joe Hershberger wrote:
> >>>>>>
> >>>>>>On Fri, Nov 13, 2015 at 10:03 AM, Stephen Warren
> >>>>>><swarren@wwwdotorg.org>
> >>>>>>wrote:
> >>>>>>>
> >>>>>>>From: Stephen Warren <swarren@nvidia.com>
> >>>>>>>
> >>>>>>>The Linux kernel, from which checkpatch originates, contains function
> >>>>>>>ether_addr_copy() to copy Ethernet MAC addresses, and checkpatch warns
> >>>>>>>that it should be used in preference to memcpy() where appropriate.
> >>>>>>>U-Boot doesn't contain ether_addr_copy(), so tell checkpatch not to
> >>>>>>>issue
> >>>>>>>this warning.
> >>>>>>>
> >>>>>>>Signed-off-by: Stephen Warren <swarren@nvidia.com>
> >>>>>>
> >>>>>>
> >>>>>>Acked-by: Joe Hershberger <joe.hershberger@ni.com>
> >>>>>
> >>>>>
> >>>>>Were you intending someone else to apply this? I think now that Ted
> >>>>>Chen has
> >>>>>taken over the USB NIC driver (which was patch 2 in this series),
> >>>>>this patch
> >>>>>should be applied separately.
> >>>>
> >>>>It is assigned to Marek in patchwork. If he's not going to take it,
> >>>>then assign it to me and I'll pull it in.
> >>>
> >>>Marek,
> >>>
> >>>Are you taking this patch? If not, could you please re-assign it to Joe;
> >>>I don't believe I can modify patchwork myself.
> >>
> >>Marek?
> >>
> >>Tom, are you able to re-assign this patch to Joe in patchwork?
> >
> >Which? https://patchwork.ozlabs.org/patch/570547/ ?
> 
> Just patch 1/2 not 2/2:
> 
> https://patchwork.ozlabs.org/patch/544360/
> checkpatch: ignore request to use ether_addr_copy()

Ah, ok.  I've taken 1/2 but if Joe beats me to it (patchwork assignments
are suggestions) that's fine too.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160120/1aadbebc/attachment.sig>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH 1/2] checkpatch: ignore request to use ether_addr_copy()
  2016-01-21  1:22               ` Tom Rini
@ 2016-01-21  4:09                 ` Joe Hershberger
  0 siblings, 0 replies; 64+ messages in thread
From: Joe Hershberger @ 2016-01-21  4:09 UTC (permalink / raw)
  To: u-boot

Hi Tom,

On Wed, Jan 20, 2016 at 7:22 PM, Tom Rini <trini@konsulko.com> wrote:
> On Wed, Jan 20, 2016 at 02:04:04PM -0700, Stephen Warren wrote:
>> On 01/20/2016 02:00 PM, Tom Rini wrote:
>> >On Wed, Jan 20, 2016 at 01:47:55PM -0700, Stephen Warren wrote:
>> >>On 01/13/2016 11:23 AM, Stephen Warren wrote:
>> >>>On 12/15/2015 04:41 PM, Joe Hershberger wrote:
>> >>>>Hi Stephen,
>> >>>>
>> >>>>On Tue, Dec 15, 2015 at 5:34 PM, Stephen Warren
>> >>>><swarren@wwwdotorg.org> wrote:
>> >>>>>On 11/23/2015 04:36 PM, Joe Hershberger wrote:
>> >>>>>>
>> >>>>>>On Fri, Nov 13, 2015 at 10:03 AM, Stephen Warren
>> >>>>>><swarren@wwwdotorg.org>
>> >>>>>>wrote:
>> >>>>>>>
>> >>>>>>>From: Stephen Warren <swarren@nvidia.com>
>> >>>>>>>
>> >>>>>>>The Linux kernel, from which checkpatch originates, contains function
>> >>>>>>>ether_addr_copy() to copy Ethernet MAC addresses, and checkpatch warns
>> >>>>>>>that it should be used in preference to memcpy() where appropriate.
>> >>>>>>>U-Boot doesn't contain ether_addr_copy(), so tell checkpatch not to
>> >>>>>>>issue
>> >>>>>>>this warning.
>> >>>>>>>
>> >>>>>>>Signed-off-by: Stephen Warren <swarren@nvidia.com>
>> >>>>>>
>> >>>>>>
>> >>>>>>Acked-by: Joe Hershberger <joe.hershberger@ni.com>
>> >>>>>
>> >>>>>
>> >>>>>Were you intending someone else to apply this? I think now that Ted
>> >>>>>Chen has
>> >>>>>taken over the USB NIC driver (which was patch 2 in this series),
>> >>>>>this patch
>> >>>>>should be applied separately.
>> >>>>
>> >>>>It is assigned to Marek in patchwork. If he's not going to take it,
>> >>>>then assign it to me and I'll pull it in.
>> >>>
>> >>>Marek,
>> >>>
>> >>>Are you taking this patch? If not, could you please re-assign it to Joe;
>> >>>I don't believe I can modify patchwork myself.
>> >>
>> >>Marek?
>> >>
>> >>Tom, are you able to re-assign this patch to Joe in patchwork?
>> >
>> >Which? https://patchwork.ozlabs.org/patch/570547/ ?
>>
>> Just patch 1/2 not 2/2:
>>
>> https://patchwork.ozlabs.org/patch/544360/
>> checkpatch: ignore request to use ether_addr_copy()
>
> Ah, ok.  I've taken 1/2 but if Joe beats me to it (patchwork assignments
> are suggestions) that's fine too.

All yours!

-Joe

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  2016-01-20 20:34                                                   ` Marek Vasut
@ 2016-01-21  8:55                                                     ` Anand Moon
  2016-01-21 10:12                                                       ` Marek Vasut
  0 siblings, 1 reply; 64+ messages in thread
From: Anand Moon @ 2016-01-21  8:55 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On 21 January 2016 at 02:04, Marek Vasut <marex@denx.de> wrote:
> On Wednesday, January 20, 2016 at 09:10:07 PM, Anand Moon wrote:
>> Hi Ted / Marek / Stephen,
>>
>> On 20 January 2016 at 22:22, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> > On 01/19/2016 11:24 PM, Ted Chen wrote:
>> >> This patch adds driver support for the Realtek RTL8152B/RTL8153 USB
>> >> network adapters.
>> >
>> > This looks fine to me, although I didn't take a detailed enough look to
>> > actually give and an ack/reviewed-by.
>>
>> What about the other patch: usb xhci Fix vendor command error if the
>> request.patch
>
> Please repost it , make sure to CC everyone . If there is agreement that
> it fixes real issue, I'll pick it.
>
>> After setting the usbether mac address my odroid xu4 board shop booting.
>> even after reset of environment it dose not boot.
>> ---------------------------------------------------------------------------
>> ------------------------------ U-Boot 2016.01-00406-g048c61d-dirty (Jan 21
>> 2016 - 06:27:09 +1030) for ODROID-XU3
>>
>> CPU:   Exynos5422 @ 800 MHz
>> Model: Odroid XU3 based on EXYNOS5422
>> Board: Odroid XU3 based on EXYNOS5422
>> Type:  xu4
>> DRAM:  2 GiB
>> MMC:   EXYNOS DWMMC: 0, EXYNOS DWMMC: 1
>> *** Warning - bad CRC, using default environment
>>
>> In:    serial
>> Out:   serial
>> Err:   serial
>> Net:   No ethernet found.
>> Hit any key to stop autoboot:  0
>> ODROID-XU3 #
>> ODROID-XU3 #
>> ODROID-XU3 #
>> ODROID-XU3 # setenv usbethaddr 00:1e:06:31:06:b3
>> ODROID-XU3 # saveenv
>
> You ran saveenv, so usbethaddr is now in permanent storage. That's why
> 'reset' won't help you.
>

But I need to set common mac address so that I will get single IP.
I don't need random mac address.

Any way thanks for your input.

>> Saving Environment to MMC...
>> Writing to MMC(0)... done
>> ODROID-XU3 # usb info
>> USB is stopped. Please issue 'usb start' first.
>> ODROID-XU3 # usb start
>> starting USB...
>> USB0:   USB EHCI 1.00
>> USB1:   Register 2000140 NbrPorts 2
>> Starting the controller
>> USB XHCI 1.00
>> USB2:   Register 2000140 NbrPorts 2
>> Starting the controller
>> USB XHCI 1.00
>> scanning bus 0 for devices... 1 USB Device(s) found
>> scanning bus 1 for devices... Device not responding to set address.
>>
>>       USB device not accepting new address (error=80000000)
>
> This error looks suspicious.

I had another wireless mouse and USB to Ethernet adapter connected to the board
may be it's not getting recognized at that moment.

Any way thanks for you input.

>
>> 2 USB Device(s) found
>> scanning bus 2 for devices... 2 USB Device(s) found
>>        scanning usb for ethernet devices... 1 Ethernet Device(s) found
> [...]

Well I have tested the TFTP booting functionality of the board and it
was success.
Fell free to add my tested by for this version.

Tested-by: Anand Moon <linux.amoon@gmail.com>

Best Regards.
-Anand Moon

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  2016-01-21  8:55                                                     ` Anand Moon
@ 2016-01-21 10:12                                                       ` Marek Vasut
  0 siblings, 0 replies; 64+ messages in thread
From: Marek Vasut @ 2016-01-21 10:12 UTC (permalink / raw)
  To: u-boot

On Thursday, January 21, 2016 at 09:55:59 AM, Anand Moon wrote:
> Hi Marek,
> 
> On 21 January 2016 at 02:04, Marek Vasut <marex@denx.de> wrote:
> > On Wednesday, January 20, 2016 at 09:10:07 PM, Anand Moon wrote:
> >> Hi Ted / Marek / Stephen,
> >> 
> >> On 20 January 2016 at 22:22, Stephen Warren <swarren@wwwdotorg.org> wrote:
> >> > On 01/19/2016 11:24 PM, Ted Chen wrote:
> >> >> This patch adds driver support for the Realtek RTL8152B/RTL8153 USB
> >> >> network adapters.
> >> > 
> >> > This looks fine to me, although I didn't take a detailed enough look
> >> > to actually give and an ack/reviewed-by.
> >> 
> >> What about the other patch: usb xhci Fix vendor command error if the
> >> request.patch
> > 
> > Please repost it , make sure to CC everyone . If there is agreement that
> > it fixes real issue, I'll pick it.
> > 
> >> After setting the usbether mac address my odroid xu4 board shop booting.
> >> even after reset of environment it dose not boot.
> >> ------------------------------------------------------------------------
> >> --- ------------------------------ U-Boot 2016.01-00406-g048c61d-dirty
> >> (Jan 21 2016 - 06:27:09 +1030) for ODROID-XU3
> >> 
> >> CPU:   Exynos5422 @ 800 MHz
> >> Model: Odroid XU3 based on EXYNOS5422
> >> Board: Odroid XU3 based on EXYNOS5422
> >> Type:  xu4
> >> DRAM:  2 GiB
> >> MMC:   EXYNOS DWMMC: 0, EXYNOS DWMMC: 1
> >> *** Warning - bad CRC, using default environment
> >> 
> >> In:    serial
> >> Out:   serial
> >> Err:   serial
> >> Net:   No ethernet found.
> >> Hit any key to stop autoboot:  0
> >> ODROID-XU3 #
> >> ODROID-XU3 #
> >> ODROID-XU3 #
> >> ODROID-XU3 # setenv usbethaddr 00:1e:06:31:06:b3
> >> ODROID-XU3 # saveenv
> > 
> > You ran saveenv, so usbethaddr is now in permanent storage. That's why
> > 'reset' won't help you.
> 
> But I need to set common mac address so that I will get single IP.
> I don't need random mac address.
> 
> Any way thanks for your input.

That was just a comment /wrt your observation that the board stops booting
and reset doesn't fix it ;-)

> >> Saving Environment to MMC...
> >> Writing to MMC(0)... done
> >> ODROID-XU3 # usb info
> >> USB is stopped. Please issue 'usb start' first.
> >> ODROID-XU3 # usb start
> >> starting USB...
> >> USB0:   USB EHCI 1.00
> >> USB1:   Register 2000140 NbrPorts 2
> >> Starting the controller
> >> USB XHCI 1.00
> >> USB2:   Register 2000140 NbrPorts 2
> >> Starting the controller
> >> USB XHCI 1.00
> >> scanning bus 0 for devices... 1 USB Device(s) found
> >> scanning bus 1 for devices... Device not responding to set address.
> >> 
> >>       USB device not accepting new address (error=80000000)
> > 
> > This error looks suspicious.
> 
> I had another wireless mouse and USB to Ethernet adapter connected to the
> board may be it's not getting recognized at that moment.
> 
> Any way thanks for you input.

Looks like something might be afoot with the controller itself ?

> >> 2 USB Device(s) found
> >> scanning bus 2 for devices... 2 USB Device(s) found
> >> 
> >>        scanning usb for ethernet devices... 1 Ethernet Device(s) found
> > 
> > [...]
> 
> Well I have tested the TFTP booting functionality of the board and it
> was success.
> Fell free to add my tested by for this version.
> 
> Tested-by: Anand Moon <linux.amoon@gmail.com>

Excellent, thanks!

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  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-22 19:50                                               ` Joe Hershberger
  2016-01-22 20:00                                                 ` Marek Vasut
  2 siblings, 1 reply; 64+ messages in thread
From: Joe Hershberger @ 2016-01-22 19:50 UTC (permalink / raw)
  To: u-boot

On Wed, Jan 20, 2016 at 12:24 AM, Ted Chen <tedchen@realtek.com> wrote:
> 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     | 1456 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/usb/eth/r8152.h     |  631 +++++++++++++++++++
>  drivers/usb/eth/r8152_fw.c  |  980 +++++++++++++++++++++++++++++
>  drivers/usb/eth/usb_ether.c |    7 +
>  include/usb_ether.h         |    6 +
>  6 files changed, 3081 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.
>
> Changes for v5: Modified by Marek's comments.
> - add r8152_wait_for_bit to replace busy wait.
> - change the name of patch4 to r8152b_set_dq_desc.
> - add r8152_versions to store the hw's version.

Acked-by: Joe Hershberger <joe.hershberger@ni.com>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  2016-01-22 19:50                                               ` Joe Hershberger
@ 2016-01-22 20:00                                                 ` Marek Vasut
  2016-01-22 20:41                                                   ` Joe Hershberger
  0 siblings, 1 reply; 64+ messages in thread
From: Marek Vasut @ 2016-01-22 20:00 UTC (permalink / raw)
  To: u-boot

On Friday, January 22, 2016 at 08:50:04 PM, Joe Hershberger wrote:
> On Wed, Jan 20, 2016 at 12:24 AM, Ted Chen <tedchen@realtek.com> wrote:
> > 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     | 1456
> >  +++++++++++++++++++++++++++++++++++++++++++ drivers/usb/eth/r8152.h    
> >  |  631 +++++++++++++++++++
> >  drivers/usb/eth/r8152_fw.c  |  980 +++++++++++++++++++++++++++++
> >  drivers/usb/eth/usb_ether.c |    7 +
> >  include/usb_ether.h         |    6 +
> >  6 files changed, 3081 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.
> > 
> > Changes for v5: Modified by Marek's comments.
> > - add r8152_wait_for_bit to replace busy wait.
> > - change the name of patch4 to r8152b_set_dq_desc.
> > - add r8152_versions to store the hw's version.
> 
> Acked-by: Joe Hershberger <joe.hershberger@ni.com>

Do you want to pick this or shall I ?

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  2016-01-22 20:00                                                 ` Marek Vasut
@ 2016-01-22 20:41                                                   ` Joe Hershberger
  2016-01-23  0:42                                                     ` Marek Vasut
  0 siblings, 1 reply; 64+ messages in thread
From: Joe Hershberger @ 2016-01-22 20:41 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On Fri, Jan 22, 2016 at 2:00 PM, Marek Vasut <marex@denx.de> wrote:
> On Friday, January 22, 2016 at 08:50:04 PM, Joe Hershberger wrote:
>> On Wed, Jan 20, 2016 at 12:24 AM, Ted Chen <tedchen@realtek.com> wrote:
>> > 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     | 1456
>> >  +++++++++++++++++++++++++++++++++++++++++++ drivers/usb/eth/r8152.h
>> >  |  631 +++++++++++++++++++
>> >  drivers/usb/eth/r8152_fw.c  |  980 +++++++++++++++++++++++++++++
>> >  drivers/usb/eth/usb_ether.c |    7 +
>> >  include/usb_ether.h         |    6 +
>> >  6 files changed, 3081 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.
>> >
>> > Changes for v5: Modified by Marek's comments.
>> > - add r8152_wait_for_bit to replace busy wait.
>> > - change the name of patch4 to r8152b_set_dq_desc.
>> > - add r8152_versions to store the hw's version.
>>
>> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
>
> Do you want to pick this or shall I ?

If there is some dependency (patch 1) that you will take first, you
can just take this as well.

-Joe

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  2016-01-22 20:41                                                   ` Joe Hershberger
@ 2016-01-23  0:42                                                     ` Marek Vasut
  2016-01-23 15:23                                                       ` Marek Vasut
  0 siblings, 1 reply; 64+ messages in thread
From: Marek Vasut @ 2016-01-23  0:42 UTC (permalink / raw)
  To: u-boot

On Friday, January 22, 2016 at 09:41:33 PM, Joe Hershberger wrote:
> Hi Marek,
> 
> On Fri, Jan 22, 2016 at 2:00 PM, Marek Vasut <marex@denx.de> wrote:
> > On Friday, January 22, 2016 at 08:50:04 PM, Joe Hershberger wrote:
> >> On Wed, Jan 20, 2016 at 12:24 AM, Ted Chen <tedchen@realtek.com> wrote:
> >> > 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     | 1456
> >> >  +++++++++++++++++++++++++++++++++++++++++++ drivers/usb/eth/r8152.h
> >> >  
> >> >  |  631 +++++++++++++++++++
> >> >  
> >> >  drivers/usb/eth/r8152_fw.c  |  980 +++++++++++++++++++++++++++++
> >> >  drivers/usb/eth/usb_ether.c |    7 +
> >> >  include/usb_ether.h         |    6 +
> >> >  6 files changed, 3081 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.
> >> > 
> >> > Changes for v5: Modified by Marek's comments.
> >> > - add r8152_wait_for_bit to replace busy wait.
> >> > - change the name of patch4 to r8152b_set_dq_desc.
> >> > - add r8152_versions to store the hw's version.
> >> 
> >> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
> > 
> > Do you want to pick this or shall I ?
> 
> If there is some dependency (patch 1) that you will take first, you
> can just take this as well.

I cannot find patch 1/2.

Ted, can you repost both of the patches , so I can pick them ?

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  2016-01-23  0:42                                                     ` Marek Vasut
@ 2016-01-23 15:23                                                       ` Marek Vasut
  2016-01-23 18:55                                                         ` Anand Moon
  0 siblings, 1 reply; 64+ messages in thread
From: Marek Vasut @ 2016-01-23 15:23 UTC (permalink / raw)
  To: u-boot

On Saturday, January 23, 2016 at 01:42:55 AM, Marek Vasut wrote:
> On Friday, January 22, 2016 at 09:41:33 PM, Joe Hershberger wrote:
> > Hi Marek,
> > 
> > On Fri, Jan 22, 2016 at 2:00 PM, Marek Vasut <marex@denx.de> wrote:
> > > On Friday, January 22, 2016 at 08:50:04 PM, Joe Hershberger wrote:
> > >> On Wed, Jan 20, 2016 at 12:24 AM, Ted Chen <tedchen@realtek.com> wrote:
> > >> > 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     | 1456
> > >> >  +++++++++++++++++++++++++++++++++++++++++++ drivers/usb/eth/r8152.h
> > >> >  
> > >> >  |  631 +++++++++++++++++++
> > >> >  
> > >> >  drivers/usb/eth/r8152_fw.c  |  980 +++++++++++++++++++++++++++++
> > >> >  drivers/usb/eth/usb_ether.c |    7 +
> > >> >  include/usb_ether.h         |    6 +
> > >> >  6 files changed, 3081 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.
> > >> > 
> > >> > Changes for v5: Modified by Marek's comments.
> > >> > - add r8152_wait_for_bit to replace busy wait.
> > >> > - change the name of patch4 to r8152b_set_dq_desc.
> > >> > - add r8152_versions to store the hw's version.
> > >> 
> > >> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
> > > 
> > > Do you want to pick this or shall I ?
> > 
> > If there is some dependency (patch 1) that you will take first, you
> > can just take this as well.
> 
> I cannot find patch 1/2.
> 
> Ted, can you repost both of the patches , so I can pick them ?

I applied 2/2 to u-boot-usb since it seems harmless, but I still don't know
what 1/2 is .

Best regards,

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  2016-01-23 15:23                                                       ` Marek Vasut
@ 2016-01-23 18:55                                                         ` Anand Moon
  2016-01-23 19:38                                                           ` Marek Vasut
  0 siblings, 1 reply; 64+ messages in thread
From: Anand Moon @ 2016-01-23 18:55 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On 23 January 2016 at 20:53, Marek Vasut <marex@denx.de> wrote:
> On Saturday, January 23, 2016 at 01:42:55 AM, Marek Vasut wrote:
>> On Friday, January 22, 2016 at 09:41:33 PM, Joe Hershberger wrote:
>> > Hi Marek,
>> >
>> > On Fri, Jan 22, 2016 at 2:00 PM, Marek Vasut <marex@denx.de> wrote:
>> > > On Friday, January 22, 2016 at 08:50:04 PM, Joe Hershberger wrote:
>> > >> On Wed, Jan 20, 2016 at 12:24 AM, Ted Chen <tedchen@realtek.com> wrote:
>> > >> > 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     | 1456
>> > >> >  +++++++++++++++++++++++++++++++++++++++++++ drivers/usb/eth/r8152.h
>> > >> >
>> > >> >  |  631 +++++++++++++++++++
>> > >> >
>> > >> >  drivers/usb/eth/r8152_fw.c  |  980 +++++++++++++++++++++++++++++
>> > >> >  drivers/usb/eth/usb_ether.c |    7 +
>> > >> >  include/usb_ether.h         |    6 +
>> > >> >  6 files changed, 3081 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.
>> > >> >
>> > >> > Changes for v5: Modified by Marek's comments.
>> > >> > - add r8152_wait_for_bit to replace busy wait.
>> > >> > - change the name of patch4 to r8152b_set_dq_desc.
>> > >> > - add r8152_versions to store the hw's version.
>> > >>
>> > >> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
>> > >
>> > > Do you want to pick this or shall I ?
>> >
>> > If there is some dependency (patch 1) that you will take first, you
>> > can just take this as well.
>>
>> I cannot find patch 1/2.
>>
>> Ted, can you repost both of the patches , so I can pick them ?
>
> I applied 2/2 to u-boot-usb since it seems harmless, but I still don't know
> what 1/2 is .
>
> Best regards,

I probably belive this is the patch.

https://patchwork.ozlabs.org/patch/548453/

Best Regards

-Anand Moon

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  2016-01-23 18:55                                                         ` Anand Moon
@ 2016-01-23 19:38                                                           ` Marek Vasut
  2016-01-25  3:42                                                             ` Ted
  0 siblings, 1 reply; 64+ messages in thread
From: Marek Vasut @ 2016-01-23 19:38 UTC (permalink / raw)
  To: u-boot

On Saturday, January 23, 2016 at 07:55:58 PM, Anand Moon wrote:
> Hi Marek,
> 
> On 23 January 2016 at 20:53, Marek Vasut <marex@denx.de> wrote:
> > On Saturday, January 23, 2016 at 01:42:55 AM, Marek Vasut wrote:
> >> On Friday, January 22, 2016 at 09:41:33 PM, Joe Hershberger wrote:
> >> > Hi Marek,
> >> > 
> >> > On Fri, Jan 22, 2016 at 2:00 PM, Marek Vasut <marex@denx.de> wrote:
> >> > > On Friday, January 22, 2016 at 08:50:04 PM, Joe Hershberger wrote:
> >> > >> On Wed, Jan 20, 2016 at 12:24 AM, Ted Chen <tedchen@realtek.com> 
wrote:
> >> > >> > 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     | 1456
> >> > >> >  +++++++++++++++++++++++++++++++++++++++++++
> >> > >> >  drivers/usb/eth/r8152.h
> >> > >> >  
> >> > >> >  |  631 +++++++++++++++++++
> >> > >> >  
> >> > >> >  drivers/usb/eth/r8152_fw.c  |  980 +++++++++++++++++++++++++++++
> >> > >> >  drivers/usb/eth/usb_ether.c |    7 +
> >> > >> >  include/usb_ether.h         |    6 +
> >> > >> >  6 files changed, 3081 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.
> >> > >> > 
> >> > >> > Changes for v5: Modified by Marek's comments.
> >> > >> > - add r8152_wait_for_bit to replace busy wait.
> >> > >> > - change the name of patch4 to r8152b_set_dq_desc.
> >> > >> > - add r8152_versions to store the hw's version.
> >> > >> 
> >> > >> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
> >> > > 
> >> > > Do you want to pick this or shall I ?
> >> > 
> >> > If there is some dependency (patch 1) that you will take first, you
> >> > can just take this as well.
> >> 
> >> I cannot find patch 1/2.
> >> 
> >> Ted, can you repost both of the patches , so I can pick them ?
> > 
> > I applied 2/2 to u-boot-usb since it seems harmless, but I still don't
> > know what 1/2 is .
> > 
> > Best regards,
> 
> I probably belive this is the patch.
> 
> https://patchwork.ozlabs.org/patch/548453/

Thanks, in that case , please repost that one patch.

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  2016-01-23 19:38                                                           ` Marek Vasut
@ 2016-01-25  3:42                                                             ` Ted
  2016-01-25  3:47                                                               ` Marek Vasut
  0 siblings, 1 reply; 64+ messages in thread
From: Ted @ 2016-01-25  3:42 UTC (permalink / raw)
  To: u-boot

Hi Marek, 

> -----Original Message-----
> From: Marek Vasut [mailto:marex at denx.de] 
> Sent: Sunday, January 24, 2016 3:38 AM
> To: Anand Moon
> Cc: Joe Hershberger; Ted; Stephen Warren; Joe Hershberger; u-boot
> Subject: Re: [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek 
> RTL8152B/RTL8153 DRIVER
> 
> On Saturday, January 23, 2016 at 07:55:58 PM, Anand Moon wrote:
> > Hi Marek,
> > 
> > On 23 January 2016 at 20:53, Marek Vasut <marex@denx.de> wrote:
> > > On Saturday, January 23, 2016 at 01:42:55 AM, Marek Vasut wrote:
> > >> On Friday, January 22, 2016 at 09:41:33 PM, Joe 
> Hershberger wrote:
> > >> > Hi Marek,
> > >> > 
> > >> > On Fri, Jan 22, 2016 at 2:00 PM, Marek Vasut 
> <marex@denx.de> wrote:
> > >> > > On Friday, January 22, 2016 at 08:50:04 PM, Joe 
> Hershberger wrote:
> > >> > >> On Wed, Jan 20, 2016 at 12:24 AM, Ted Chen 
> > >> > >> <tedchen@realtek.com>
> wrote:
> > >> > >> > 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     | 1456
> > >> > >> >  +++++++++++++++++++++++++++++++++++++++++++
> > >> > >> >  drivers/usb/eth/r8152.h
> > >> > >> >  
> > >> > >> >  |  631 +++++++++++++++++++
> > >> > >> >  
> > >> > >> >  drivers/usb/eth/r8152_fw.c  |  980 
> +++++++++++++++++++++++++++++
> > >> > >> >  drivers/usb/eth/usb_ether.c |    7 +
> > >> > >> >  include/usb_ether.h         |    6 +
> > >> > >> >  6 files changed, 3081 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.
> > >> > >> > 
> > >> > >> > Changes for v5: Modified by Marek's comments.
> > >> > >> > - add r8152_wait_for_bit to replace busy wait.
> > >> > >> > - change the name of patch4 to r8152b_set_dq_desc.
> > >> > >> > - add r8152_versions to store the hw's version.
> > >> > >> 
> > >> > >> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
> > >> > > 
> > >> > > Do you want to pick this or shall I ?
> > >> > 
> > >> > If there is some dependency (patch 1) that you will 
> take first, 
> > >> > you can just take this as well.
> > >> 
> > >> I cannot find patch 1/2.
> > >> 
> > >> Ted, can you repost both of the patches , so I can pick them ?
> > > 
> > > I applied 2/2 to u-boot-usb since it seems harmless, but I still 
> > > don't know what 1/2 is .
> > > 
> > > Best regards,
> > 
> > I probably belive this is the patch.
> > 
> > https://patchwork.ozlabs.org/patch/548453/
> 
> Thanks, in that case , please repost that one patch.

The patch 1/2 is there :
https://patchwork.ozlabs.org/patch/544360/

That patch is posted by "Stephen Warren".

Thanks~

BRs
Ted

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek RTL8152B/RTL8153 DRIVER
  2016-01-25  3:42                                                             ` Ted
@ 2016-01-25  3:47                                                               ` Marek Vasut
  0 siblings, 0 replies; 64+ messages in thread
From: Marek Vasut @ 2016-01-25  3:47 UTC (permalink / raw)
  To: u-boot

On Monday, January 25, 2016 at 04:42:50 AM, Ted wrote:
> Hi Marek,

Hi,

> > -----Original Message-----
> > From: Marek Vasut [mailto:marex at denx.de]
> > Sent: Sunday, January 24, 2016 3:38 AM
> > To: Anand Moon
> > Cc: Joe Hershberger; Ted; Stephen Warren; Joe Hershberger; u-boot
> > Subject: Re: [U-Boot] [PATCH v5 2/2] usb: eth: add Realtek
> > RTL8152B/RTL8153 DRIVER
> > 
> > On Saturday, January 23, 2016 at 07:55:58 PM, Anand Moon wrote:
> > > Hi Marek,
> > > 
> > > On 23 January 2016 at 20:53, Marek Vasut <marex@denx.de> wrote:
> > > > On Saturday, January 23, 2016 at 01:42:55 AM, Marek Vasut wrote:
> > > >> On Friday, January 22, 2016 at 09:41:33 PM, Joe
> > 
> > Hershberger wrote:
> > > >> > Hi Marek,
> > > >> > 
> > > >> > On Fri, Jan 22, 2016 at 2:00 PM, Marek Vasut
> > 
> > <marex@denx.de> wrote:
> > > >> > > On Friday, January 22, 2016 at 08:50:04 PM, Joe
> > 
> > Hershberger wrote:
> > > >> > >> On Wed, Jan 20, 2016 at 12:24 AM, Ted Chen
> > > >> > >> <tedchen@realtek.com>
> > 
> > wrote:
> > > >> > >> > 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     | 1456
> > > >> > >> >  +++++++++++++++++++++++++++++++++++++++++++
> > > >> > >> >  drivers/usb/eth/r8152.h
> > > >> > >> >  
> > > >> > >> >  |  631 +++++++++++++++++++
> > > >> > >> >  
> > > >> > >> >  drivers/usb/eth/r8152_fw.c  |  980
> > 
> > +++++++++++++++++++++++++++++
> > 
> > > >> > >> >  drivers/usb/eth/usb_ether.c |    7 +
> > > >> > >> >  include/usb_ether.h         |    6 +
> > > >> > >> >  6 files changed, 3081 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.
> > > >> > >> > 
> > > >> > >> > Changes for v5: Modified by Marek's comments.
> > > >> > >> > - add r8152_wait_for_bit to replace busy wait.
> > > >> > >> > - change the name of patch4 to r8152b_set_dq_desc.
> > > >> > >> > - add r8152_versions to store the hw's version.
> > > >> > >> 
> > > >> > >> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
> > > >> > > 
> > > >> > > Do you want to pick this or shall I ?
> > > >> > 
> > > >> > If there is some dependency (patch 1) that you will
> > 
> > take first,
> > 
> > > >> > you can just take this as well.
> > > >> 
> > > >> I cannot find patch 1/2.
> > > >> 
> > > >> Ted, can you repost both of the patches , so I can pick them ?
> > > > 
> > > > I applied 2/2 to u-boot-usb since it seems harmless, but I still
> > > > don't know what 1/2 is .
> > > > 
> > > > Best regards,
> > > 
> > > I probably belive this is the patch.
> > > 
> > > https://patchwork.ozlabs.org/patch/548453/
> > 
> > Thanks, in that case , please repost that one patch.
> 
> The patch 1/2 is there :
> https://patchwork.ozlabs.org/patch/544360/

Urgh, looks like PW mixed 1/2 and 2/2 and all the review of 2/2 is part of
that 1/2 patch too. Sigh.

> That patch is posted by "Stephen Warren".

Did that 1/2 patch get any review other than mine ? If not , please do repost
it and and CC Tom Rini and Simon Glass at least . Feel free to keep my reviewed-
by already.

Thanks!


> Thanks~
> 
> BRs
> Ted

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [U-Boot] [U-Boot, 1/2] checkpatch: ignore request to use ether_addr_copy()
  2015-11-13 16:03 [U-Boot] [PATCH 1/2] checkpatch: ignore request to use ether_addr_copy() Stephen Warren
                   ` (2 preceding siblings ...)
  2015-11-23 23:36 ` Joe Hershberger
@ 2016-01-25 21:28 ` Tom Rini
  3 siblings, 0 replies; 64+ messages in thread
From: Tom Rini @ 2016-01-25 21:28 UTC (permalink / raw)
  To: u-boot

On Fri, Nov 13, 2015 at 09:03:00AM -0700, Stephen Warren wrote:

> From: Stephen Warren <swarren@nvidia.com>
> 
> The Linux kernel, from which checkpatch originates, contains function
> ether_addr_copy() to copy Ethernet MAC addresses, and checkpatch warns
> that it should be used in preference to memcpy() where appropriate.
> U-Boot doesn't contain ether_addr_copy(), so tell checkpatch not to issue
> this warning.
> 
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> Reviewed-by: Marek Vasut <marex@denx.de>
> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
> Tested-by: Anand Moon <linux.amoon@gmail.com>
> Reviewed-by: Anand Moon <linux.amoon@gmail.com>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160125/42634bdd/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 64+ messages in thread

end of thread, other threads:[~2016-01-25 21:28 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
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

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.