These patches are used to support new chips.
Hayes Wang (3):
r8152: support new chip 8050
r8152: support RTL8153B
r8152: add byte_enable for ocp_read_word function
drivers/net/usb/r8152.c | 687 ++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 671 insertions(+), 16 deletions(-)
--
2.7.4
This patch supports two new chips for RTL8153B.
Signed-off-by: Hayes Wang <[email protected]>
---
drivers/net/usb/r8152.c | 673 ++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 658 insertions(+), 15 deletions(-)
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 2744405..4c197da 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -29,7 +29,7 @@
#include <linux/acpi.h>
/* Information for net-next */
-#define NETNEXT_VERSION "08"
+#define NETNEXT_VERSION "09"
/* Information for net */
#define NET_VERSION "9"
@@ -51,11 +51,14 @@
#define PLA_FMC 0xc0b4
#define PLA_CFG_WOL 0xc0b6
#define PLA_TEREDO_CFG 0xc0bc
+#define PLA_TEREDO_WAKE_BASE 0xc0c4
#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_EFUSE_DATA 0xdd00
+#define PLA_EFUSE_CMD 0xdd02
#define PLA_LEDSEL 0xdd90
#define PLA_LED_FEATURE 0xdd92
#define PLA_PHYAR 0xde00
@@ -105,7 +108,9 @@
#define USB_CSR_DUMMY2 0xb466
#define USB_DEV_STAT 0xb808
#define USB_CONNECT_TIMER 0xcbf8
+#define USB_MSC_TIMER 0xcbfc
#define USB_BURST_SIZE 0xcfc0
+#define USB_LPM_CONFIG 0xcfd8
#define USB_USB_CTRL 0xd406
#define USB_PHY_CTRL 0xd408
#define USB_TX_AGG 0xd40a
@@ -113,15 +118,20 @@
#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_PM_CTRL_STATUS 0xd432 /* RTL8153A */
+#define USB_RX_EXTRA_AGGR_TMR 0xd432 /* RTL8153B */
#define USB_TX_DMA 0xd434
+#define USB_UPT_RXDMA_OWN 0xd437
#define USB_TOLERANCE 0xd490
#define USB_LPM_CTRL 0xd41a
#define USB_BMU_RESET 0xd4b0
+#define USB_U1U2_TIMER 0xd4da
#define USB_UPS_CTRL 0xd800
-#define USB_MISC_0 0xd81a
#define USB_POWER_CUT 0xd80a
+#define USB_MISC_0 0xd81a
#define USB_AFE_CTRL2 0xd824
+#define USB_UPS_CFG 0xd842
+#define USB_UPS_FLAGS 0xd848
#define USB_WDT11_CTRL 0xe43c
#define USB_BP_BA 0xfc26
#define USB_BP_0 0xfc28
@@ -133,6 +143,15 @@
#define USB_BP_6 0xfc34
#define USB_BP_7 0xfc36
#define USB_BP_EN 0xfc38
+#define USB_BP_8 0xfc38
+#define USB_BP_9 0xfc3a
+#define USB_BP_10 0xfc3c
+#define USB_BP_11 0xfc3e
+#define USB_BP_12 0xfc40
+#define USB_BP_13 0xfc42
+#define USB_BP_14 0xfc44
+#define USB_BP_15 0xfc46
+#define USB_BP2_EN 0xfc48
/* OCP Registers */
#define OCP_ALDPS_CONFIG 0x2010
@@ -143,6 +162,7 @@
#define OCP_EEE_AR 0xa41a
#define OCP_EEE_DATA 0xa41c
#define OCP_PHY_STATUS 0xa420
+#define OCP_NCTL_CFG 0xa42c
#define OCP_POWER_CFG 0xa430
#define OCP_EEE_CFG 0xa432
#define OCP_SRAM_ADDR 0xa436
@@ -152,9 +172,14 @@
#define OCP_EEE_ADV 0xa5d0
#define OCP_EEE_LPABLE 0xa5d2
#define OCP_PHY_STATE 0xa708 /* nway state for 8153 */
+#define OCP_PHY_PATCH_STAT 0xb800
+#define OCP_PHY_PATCH_CMD 0xb820
+#define OCP_ADC_IOFFSET 0xbcfc
#define OCP_ADC_CFG 0xbc06
+#define OCP_SYSCLK_CFG 0xc416
/* SRAM Register */
+#define SRAM_GREEN_CFG 0x8011
#define SRAM_LPF_CFG 0x8012
#define SRAM_10M_AMP1 0x8080
#define SRAM_10M_AMP2 0x8082
@@ -252,6 +277,10 @@
/* PAL_BDC_CR */
#define ALDPS_PROXY_MODE 0x0001
+/* PLA_EFUSE_CMD */
+#define EFUSE_READ_CMD BIT(15)
+#define EFUSE_DATA_BIT16 BIT(7)
+
/* PLA_CONFIG34 */
#define LINK_ON_WAKE_EN 0x0010
#define LINK_OFF_WAKE_EN 0x0008
@@ -277,6 +306,7 @@
/* PLA_MAC_PWR_CTRL2 */
#define EEE_SPDWN_RATIO 0x8007
+#define MAC_CLK_SPDWN_EN BIT(15)
/* PLA_MAC_PWR_CTRL3 */
#define PKT_AVAIL_SPDWN_EN 0x0100
@@ -328,6 +358,9 @@
#define STAT_SPEED_HIGH 0x0000
#define STAT_SPEED_FULL 0x0002
+/* USB_LPM_CONFIG */
+#define LPM_U1U2_EN BIT(0)
+
/* USB_TX_AGG */
#define TX_AGG_MAX_THRESHOLD 0x03
@@ -335,6 +368,7 @@
#define RX_THR_SUPPER 0x0c350180
#define RX_THR_HIGH 0x7a120180
#define RX_THR_SLOW 0xffff0180
+#define RX_THR_B 0x00010001
/* USB_TX_DMA */
#define TEST_MODE_DISABLE 0x00000001
@@ -344,6 +378,10 @@
#define BMU_RESET_EP_IN 0x01
#define BMU_RESET_EP_OUT 0x02
+/* USB_UPT_RXDMA_OWN */
+#define OWN_UPDATE BIT(0)
+#define OWN_CLEAR BIT(1)
+
/* USB_UPS_CTRL */
#define POWER_CUT 0x0100
@@ -360,6 +398,8 @@
/* USB_POWER_CUT */
#define PWR_EN 0x0001
#define PHASE2_EN 0x0008
+#define UPS_EN BIT(4)
+#define USP_PREWAKE BIT(5)
/* USB_MISC_0 */
#define PCUT_STATUS 0x0001
@@ -386,6 +426,37 @@
#define SEN_VAL_NORMAL 0xa000
#define SEL_RXIDLE 0x0100
+/* USB_UPS_CFG */
+#define SAW_CNT_1MS_MASK 0x0fff
+
+/* USB_UPS_FLAGS */
+#define UPS_FLAGS_R_TUNE BIT(0)
+#define UPS_FLAGS_EN_10M_CKDIV BIT(1)
+#define UPS_FLAGS_250M_CKDIV BIT(2)
+#define UPS_FLAGS_EN_ALDPS BIT(3)
+#define UPS_FLAGS_CTAP_SHORT_DIS BIT(4)
+#define UPS_FLAGS_SPEED_MASK (0xf << 16)
+#define ups_flags_speed(x) ((x) << 16)
+#define UPS_FLAGS_EN_EEE BIT(20)
+#define UPS_FLAGS_EN_500M_EEE BIT(21)
+#define UPS_FLAGS_EN_EEE_CKDIV BIT(22)
+#define UPS_FLAGS_EEE_PLLOFF_GIGA BIT(24)
+#define UPS_FLAGS_EEE_CMOD_LV_EN BIT(25)
+#define UPS_FLAGS_EN_GREEN BIT(26)
+#define UPS_FLAGS_EN_FLOW_CTR BIT(27)
+
+enum spd_duplex {
+ NWAY_10M_HALF = 1,
+ NWAY_10M_FULL,
+ NWAY_100M_HALF,
+ NWAY_100M_FULL,
+ NWAY_1000M_FULL,
+ FORCE_10M_HALF,
+ FORCE_10M_FULL,
+ FORCE_100M_HALF,
+ FORCE_100M_FULL,
+};
+
/* OCP_ALDPS_CONFIG */
#define ENPWRSAVE 0x8000
#define ENPDNPS 0x0200
@@ -398,6 +469,9 @@
#define PHY_STAT_LAN_ON 3
#define PHY_STAT_PWRDN 5
+/* OCP_NCTL_CFG */
+#define PGA_RETURN_EN BIT(1)
+
/* OCP_POWER_CFG */
#define EEE_CLKDIV_EN 0x8000
#define EN_ALDPS 0x0004
@@ -439,17 +513,34 @@
#define EEE10_EN 0x0010
/* OCP_DOWN_SPEED */
+#define EN_EEE_CMODE BIT(14)
+#define EN_EEE_1000 BIT(13)
+#define EN_EEE_100 BIT(12)
+#define EN_10M_CLKDIV BIT(11)
#define EN_10M_BGOFF 0x0080
/* OCP_PHY_STATE */
#define TXDIS_STATE 0x01
#define ABD_STATE 0x02
+/* OCP_PHY_PATCH_STAT */
+#define PATCH_READY BIT(6)
+
+/* OCP_PHY_PATCH_CMD */
+#define PATCH_REQUEST BIT(4)
+
/* OCP_ADC_CFG */
#define CKADSEL_L 0x0100
#define ADC_EN 0x0080
#define EN_EMI_L 0x0040
+/* OCP_SYSCLK_CFG */
+#define clk_div_expo(x) (min(x, 5) << 8)
+
+/* SRAM_GREEN_CFG */
+#define GREEN_ETH_EN BIT(15)
+#define R_TUNE_EN BIT(11)
+
/* SRAM_LPF_CFG */
#define LPF_AUTO_TUNE 0x8000
@@ -514,6 +605,7 @@ enum rtl8152_flags {
SELECTIVE_SUSPEND,
PHY_RESET,
SCHEDULE_NAPI,
+ GREEN_ETHERNET,
};
/* Define these values to match your device */
@@ -660,6 +752,8 @@ enum rtl_version {
RTL_VER_05,
RTL_VER_06,
RTL_VER_07,
+ RTL_VER_08,
+ RTL_VER_09,
RTL_VER_MAX
};
@@ -984,6 +1078,12 @@ static void sram_write(struct r8152 *tp, u16 addr, u16 data)
ocp_reg_write(tp, OCP_SRAM_DATA, data);
}
+static u16 sram_read(struct r8152 *tp, u16 addr)
+{
+ ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
+ return ocp_reg_read(tp, OCP_SRAM_DATA);
+}
+
static int read_mii_word(struct net_device *netdev, int phy_id, int reg)
{
struct r8152 *tp = netdev_priv(netdev);
@@ -2251,18 +2351,64 @@ static int rtl8152_enable(struct r8152 *tp)
return rtl_enable(tp);
}
+static inline void r8153b_rx_agg_chg_indicate(struct r8152 *tp)
+{
+ ocp_write_byte(tp, MCU_TYPE_USB, USB_UPT_RXDMA_OWN,
+ OWN_UPDATE | OWN_CLEAR);
+}
+
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);
+ switch (tp->version) {
+ case RTL_VER_03:
+ case RTL_VER_04:
+ case RTL_VER_05:
+ case RTL_VER_06:
+ ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_TIMEOUT,
+ ocp_data);
+ break;
+
+ case RTL_VER_08:
+ case RTL_VER_09:
+ /* The RTL8153B uses USB_RX_EXTRA_AGGR_TMR for rx timeout
+ * primarily. For USB_RX_EARLY_TIMEOUT, we fix it to 128ns.
+ */
+ ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_TIMEOUT,
+ 128 / 8);
+ ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EXTRA_AGGR_TMR,
+ ocp_data);
+ r8153b_rx_agg_chg_indicate(tp);
+ break;
+
+ default:
+ break;
+ }
}
static void r8153_set_rx_early_size(struct r8152 *tp)
{
- u32 ocp_data = (agg_buf_sz - rx_reserved_size(tp->netdev->mtu)) / 4;
+ u32 ocp_data = agg_buf_sz - rx_reserved_size(tp->netdev->mtu);
- ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE, ocp_data);
+ switch (tp->version) {
+ case RTL_VER_03:
+ case RTL_VER_04:
+ case RTL_VER_05:
+ case RTL_VER_06:
+ ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE,
+ ocp_data / 4);
+ break;
+ case RTL_VER_08:
+ case RTL_VER_09:
+ ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE,
+ ocp_data / 8);
+ r8153b_rx_agg_chg_indicate(tp);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
}
static int rtl8153_enable(struct r8152 *tp)
@@ -2470,6 +2616,19 @@ static void r8153_u1u2en(struct r8152 *tp, bool enable)
usb_ocp_write(tp, USB_TOLERANCE, BYTE_EN_SIX_BYTES, sizeof(u1u2), u1u2);
}
+static void r8153b_u1u2en(struct r8152 *tp, bool enable)
+{
+ u32 ocp_data;
+
+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_LPM_CONFIG);
+ if (enable)
+ ocp_data |= LPM_U1U2_EN;
+ else
+ ocp_data &= ~LPM_U1U2_EN;
+
+ ocp_write_word(tp, MCU_TYPE_USB, USB_LPM_CONFIG, ocp_data);
+}
+
static void r8153_u2p3en(struct r8152 *tp, bool enable)
{
u32 ocp_data;
@@ -2482,6 +2641,37 @@ static void r8153_u2p3en(struct r8152 *tp, bool enable)
ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data);
}
+static void r8153b_ups_flags_w1w0(struct r8152 *tp, u32 set, u32 clear)
+{
+ u32 ocp_data;
+
+ ocp_data = ocp_read_dword(tp, MCU_TYPE_USB, USB_UPS_FLAGS);
+ ocp_data &= ~clear;
+ ocp_data |= set;
+ ocp_write_dword(tp, MCU_TYPE_USB, USB_UPS_FLAGS, ocp_data);
+}
+
+static void r8153b_green_en(struct r8152 *tp, bool enable)
+{
+ u16 data;
+
+ if (enable) {
+ sram_write(tp, 0x8045, 0); /* 10M abiq&ldvbias */
+ sram_write(tp, 0x804d, 0x1222); /* 100M short abiq&ldvbias */
+ sram_write(tp, 0x805d, 0x0022); /* 1000M short abiq&ldvbias */
+ } else {
+ sram_write(tp, 0x8045, 0x2444); /* 10M abiq&ldvbias */
+ sram_write(tp, 0x804d, 0x2444); /* 100M short abiq&ldvbias */
+ sram_write(tp, 0x805d, 0x2444); /* 1000M short abiq&ldvbias */
+ }
+
+ data = sram_read(tp, SRAM_GREEN_CFG);
+ data |= GREEN_ETH_EN;
+ sram_write(tp, SRAM_GREEN_CFG, data);
+
+ r8153b_ups_flags_w1w0(tp, UPS_FLAGS_EN_GREEN, 0);
+}
+
static u16 r8153_phy_status(struct r8152 *tp, u16 desired)
{
u16 data;
@@ -2504,6 +2694,55 @@ static u16 r8153_phy_status(struct r8152 *tp, u16 desired)
return data;
}
+static void r8153b_ups_en(struct r8152 *tp, bool enable)
+{
+ u32 ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_POWER_CUT);
+
+ if (enable) {
+ ocp_data |= UPS_EN | USP_PREWAKE | PHASE2_EN;
+ ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data);
+
+ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, 0xcfff);
+ ocp_data |= BIT(0);
+ ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data);
+ } else {
+ u16 data;
+
+ ocp_data &= ~(UPS_EN | USP_PREWAKE);
+ ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data);
+
+ ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, 0xcfff);
+ ocp_data &= ~BIT(0);
+ ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data);
+
+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0);
+ ocp_data &= ~PCUT_STATUS;
+ ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data);
+
+ data = r8153_phy_status(tp, 0);
+
+ switch (data) {
+ case PHY_STAT_PWRDN:
+ case PHY_STAT_EXT_INIT:
+ r8153b_green_en(tp,
+ test_bit(GREEN_ETHERNET, &tp->flags));
+
+ data = r8152_mdio_read(tp, MII_BMCR);
+ data &= ~BMCR_PDOWN;
+ data |= BMCR_RESET;
+ r8152_mdio_write(tp, MII_BMCR, data);
+
+ data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
+
+ default:
+ if (data != PHY_STAT_LAN_ON)
+ netif_warn(tp, link, tp->netdev,
+ "PHY not ready");
+ break;
+ }
+ }
+}
+
static void r8153_power_cut_en(struct r8152 *tp, bool enable)
{
u32 ocp_data;
@@ -2520,6 +2759,38 @@ static void r8153_power_cut_en(struct r8152 *tp, bool enable)
ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data);
}
+static void r8153b_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;
+ 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 r8153b_queue_wake(struct r8152 *tp, bool enable)
+{
+ u32 ocp_data;
+
+ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, 0xd38a);
+ if (enable)
+ ocp_data |= BIT(0);
+ else
+ ocp_data &= ~BIT(0);
+ ocp_write_byte(tp, MCU_TYPE_PLA, 0xd38a, ocp_data);
+
+ ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, 0xd38c);
+ ocp_data &= ~BIT(0);
+ ocp_write_byte(tp, MCU_TYPE_PLA, 0xd38c, ocp_data);
+}
+
static bool rtl_can_wakeup(struct r8152 *tp)
{
struct usb_device *udev = tp->udev;
@@ -2582,13 +2853,52 @@ static void rtl8153_runtime_enable(struct r8152 *tp, bool enable)
}
}
+static void rtl8153b_runtime_enable(struct r8152 *tp, bool enable)
+{
+ if (enable) {
+ r8153b_queue_wake(tp, true);
+ r8153b_u1u2en(tp, false);
+ r8153_u2p3en(tp, false);
+ rtl_runtime_suspend_enable(tp, true);
+ r8153b_ups_en(tp, true);
+ } else {
+ r8153b_ups_en(tp, false);
+ r8153b_queue_wake(tp, false);
+ rtl_runtime_suspend_enable(tp, false);
+ r8153_u2p3en(tp, true);
+ r8153b_u1u2en(tp, true);
+ }
+}
+
static void r8153_teredo_off(struct r8152 *tp)
{
u32 ocp_data;
- ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
- ocp_data &= ~(TEREDO_SEL | TEREDO_RS_EVENT_MASK | OOB_TEREDO_EN);
- ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
+ switch (tp->version) {
+ case RTL_VER_01:
+ case RTL_VER_02:
+ case RTL_VER_03:
+ case RTL_VER_04:
+ case RTL_VER_05:
+ case RTL_VER_06:
+ case RTL_VER_07:
+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
+ ocp_data &= ~(TEREDO_SEL | TEREDO_RS_EVENT_MASK |
+ OOB_TEREDO_EN);
+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
+ break;
+
+ case RTL_VER_08:
+ case RTL_VER_09:
+ /* The bit 0 ~ 7 are relative with teredo settings. They are
+ * W1C (write 1 to clear), so set all 1 to disable it.
+ */
+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, 0xff);
+ break;
+
+ default:
+ break;
+ }
ocp_write_word(tp, MCU_TYPE_PLA, PLA_WDT6_CTRL, WDT6_SET_MODE);
ocp_write_word(tp, MCU_TYPE_PLA, PLA_REALWOW_TIMER, 0);
@@ -2834,6 +3144,33 @@ static void r8152b_enter_oob(struct r8152 *tp)
ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
}
+static int r8153_patch_request(struct r8152 *tp, bool request)
+{
+ u16 data;
+ int i;
+
+ data = ocp_reg_read(tp, OCP_PHY_PATCH_CMD);
+ if (request)
+ data |= PATCH_REQUEST;
+ else
+ data &= ~PATCH_REQUEST;
+ ocp_reg_write(tp, OCP_PHY_PATCH_CMD, data);
+
+ for (i = 0; request && i < 5000; i++) {
+ usleep_range(1000, 2000);
+ if (ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY)
+ break;
+ }
+
+ if (request && !(ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY)) {
+ netif_err(tp, drv, tp->netdev, "patch request fail\n");
+ r8153_patch_request(tp, false);
+ return -ETIME;
+ } else {
+ return 0;
+ }
+}
+
static void r8153_aldps_en(struct r8152 *tp, bool enable)
{
u16 data;
@@ -2855,6 +3192,16 @@ static void r8153_aldps_en(struct r8152 *tp, bool enable)
}
}
+static void r8153b_aldps_en(struct r8152 *tp, bool enable)
+{
+ r8153_aldps_en(tp, enable);
+
+ if (enable)
+ r8153b_ups_flags_w1w0(tp, UPS_FLAGS_EN_ALDPS, 0);
+ else
+ r8153b_ups_flags_w1w0(tp, 0, UPS_FLAGS_EN_ALDPS);
+}
+
static void r8153_eee_en(struct r8152 *tp, bool enable)
{
u32 ocp_data;
@@ -2875,6 +3222,22 @@ static void r8153_eee_en(struct r8152 *tp, bool enable)
ocp_reg_write(tp, OCP_EEE_CFG, config);
}
+static void r8153b_eee_en(struct r8152 *tp, bool enable)
+{
+ r8153_eee_en(tp, enable);
+
+ if (enable)
+ r8153b_ups_flags_w1w0(tp, UPS_FLAGS_EN_EEE, 0);
+ else
+ r8153b_ups_flags_w1w0(tp, 0, UPS_FLAGS_EN_EEE);
+}
+
+static void r8153b_enable_fc(struct r8152 *tp)
+{
+ r8152b_enable_fc(tp);
+ r8153b_ups_flags_w1w0(tp, UPS_FLAGS_EN_FLOW_CTR, 0);
+}
+
static void r8153_hw_phy_cfg(struct r8152 *tp)
{
u32 ocp_data;
@@ -2936,6 +3299,100 @@ static void r8153_hw_phy_cfg(struct r8152 *tp)
set_bit(PHY_RESET, &tp->flags);
}
+static u32 r8152_efuse_read(struct r8152 *tp, u8 addr)
+{
+ u32 ocp_data;
+
+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_EFUSE_CMD, EFUSE_READ_CMD | addr);
+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EFUSE_CMD);
+ ocp_data = (ocp_data & EFUSE_DATA_BIT16) << 9; /* data of bit16 */
+ ocp_data |= ocp_read_word(tp, MCU_TYPE_PLA, PLA_EFUSE_DATA);
+
+ return ocp_data;
+}
+
+static void r8153b_hw_phy_cfg(struct r8152 *tp)
+{
+ u32 ocp_data, ups_flags = 0;
+ u16 data;
+
+ /* disable ALDPS before updating the PHY parameters */
+ r8153b_aldps_en(tp, false);
+
+ /* disable EEE before updating the PHY parameters */
+ r8153b_eee_en(tp, false);
+ ocp_reg_write(tp, OCP_EEE_ADV, 0);
+
+ r8153b_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags));
+
+ data = sram_read(tp, SRAM_GREEN_CFG);
+ data |= R_TUNE_EN;
+ sram_write(tp, SRAM_GREEN_CFG, data);
+ data = ocp_reg_read(tp, OCP_NCTL_CFG);
+ data |= PGA_RETURN_EN;
+ ocp_reg_write(tp, OCP_NCTL_CFG, data);
+
+ /* ADC Bias Calibration:
+ * read efuse offset 0x7d to get a 17-bit data. Remove the dummy/fake
+ * bit (bit3) to rebuild the real 16-bit data. Write the data to the
+ * ADC ioffset.
+ */
+ ocp_data = r8152_efuse_read(tp, 0x7d);
+ data = (u16)(((ocp_data & 0x1fff0) >> 1) | (ocp_data & 0x7));
+ if (data != 0xffff)
+ ocp_reg_write(tp, OCP_ADC_IOFFSET, data);
+
+ /* ups mode tx-link-pulse timing adjustment:
+ * rg_saw_cnt = OCP reg 0xC426 Bit[13:0]
+ * swr_cnt_1ms_ini = 16000000 / rg_saw_cnt
+ */
+ ocp_data = ocp_reg_read(tp, 0xc426);
+ ocp_data &= 0x3fff;
+ if (ocp_data) {
+ u32 swr_cnt_1ms_ini;
+
+ swr_cnt_1ms_ini = (16000000 / ocp_data) & SAW_CNT_1MS_MASK;
+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CFG);
+ ocp_data = (ocp_data & ~SAW_CNT_1MS_MASK) | swr_cnt_1ms_ini;
+ ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CFG, ocp_data);
+ }
+
+ 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);
+
+ /* Advnace EEE */
+ if (!r8153_patch_request(tp, true)) {
+ 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_EEE_CMODE | EN_EEE_1000 | EN_10M_CLKDIV;
+ ocp_reg_write(tp, OCP_DOWN_SPEED, data);
+
+ ocp_reg_write(tp, OCP_SYSCLK_CFG, 0);
+ ocp_reg_write(tp, OCP_SYSCLK_CFG, clk_div_expo(5));
+
+ ups_flags |= UPS_FLAGS_EN_10M_CKDIV | UPS_FLAGS_250M_CKDIV |
+ UPS_FLAGS_EN_EEE_CKDIV | UPS_FLAGS_EEE_CMOD_LV_EN |
+ UPS_FLAGS_EEE_PLLOFF_GIGA;
+
+ r8153_patch_request(tp, false);
+ }
+
+ r8153b_ups_flags_w1w0(tp, ups_flags, 0);
+
+ r8153b_eee_en(tp, true);
+ ocp_reg_write(tp, OCP_EEE_ADV, MDIO_EEE_1000T | MDIO_EEE_100TX);
+
+ r8153b_aldps_en(tp, true);
+ r8153b_enable_fc(tp);
+ r8153_u2p3en(tp, true);
+
+ set_bit(PHY_RESET, &tp->flags);
+}
+
static void r8153_first_init(struct r8152 *tp)
{
u32 ocp_data;
@@ -3033,9 +3490,28 @@ static void r8153_enter_oob(struct r8152 *tp)
ocp_data = tp->netdev->mtu + VLAN_ETH_HLEN + CRC_SIZE;
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);
+ switch (tp->version) {
+ case RTL_VER_03:
+ case RTL_VER_04:
+ case RTL_VER_05:
+ case RTL_VER_06:
+ 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);
+ break;
+
+ case RTL_VER_08:
+ case RTL_VER_09:
+ /* Clear teredo wake event. bit[15:8] is the teredo wakeup
+ * type. Set it to zero. bits[7:0] are the W1C bits about
+ * the events. Set them to all 1 to clear them.
+ */
+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_WAKE_BASE, 0x00ff);
+ break;
+
+ default:
+ break;
+ }
rtl_rx_vlan_en(tp, true);
@@ -3062,9 +3538,18 @@ static void rtl8153_disable(struct r8152 *tp)
r8153_aldps_en(tp, true);
}
+static void rtl8153b_disable(struct r8152 *tp)
+{
+ r8153b_aldps_en(tp, false);
+ rtl_disable(tp);
+ rtl_reset_bmu(tp);
+ r8153b_aldps_en(tp, true);
+}
+
static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
{
u16 bmcr, anar, gbcr;
+ enum spd_duplex speed_duplex;
int ret = 0;
anar = r8152_mdio_read(tp, MII_ADVERTISE);
@@ -3081,32 +3566,43 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
if (speed == SPEED_10) {
bmcr = 0;
anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
+ speed_duplex = FORCE_10M_HALF;
} else if (speed == SPEED_100) {
bmcr = BMCR_SPEED100;
anar |= ADVERTISE_100HALF | ADVERTISE_100FULL;
+ speed_duplex = FORCE_100M_HALF;
} else if (speed == SPEED_1000 && tp->mii.supports_gmii) {
bmcr = BMCR_SPEED1000;
gbcr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
+ speed_duplex = NWAY_1000M_FULL;
} else {
ret = -EINVAL;
goto out;
}
- if (duplex == DUPLEX_FULL)
+ if (duplex == DUPLEX_FULL) {
bmcr |= BMCR_FULLDPLX;
+ if (speed != SPEED_1000)
+ speed_duplex++;
+ }
} else {
if (speed == SPEED_10) {
- if (duplex == DUPLEX_FULL)
+ if (duplex == DUPLEX_FULL) {
anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
- else
+ speed_duplex = NWAY_10M_FULL;
+ } else {
anar |= ADVERTISE_10HALF;
+ speed_duplex = NWAY_10M_HALF;
+ }
} else if (speed == SPEED_100) {
if (duplex == DUPLEX_FULL) {
anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
anar |= ADVERTISE_100HALF | ADVERTISE_100FULL;
+ speed_duplex = NWAY_100M_FULL;
} else {
anar |= ADVERTISE_10HALF;
anar |= ADVERTISE_100HALF;
+ speed_duplex = NWAY_100M_HALF;
}
} else if (speed == SPEED_1000 && tp->mii.supports_gmii) {
if (duplex == DUPLEX_FULL) {
@@ -3118,6 +3614,7 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
anar |= ADVERTISE_100HALF;
gbcr |= ADVERTISE_1000HALF;
}
+ speed_duplex = NWAY_1000M_FULL;
} else {
ret = -EINVAL;
goto out;
@@ -3135,6 +3632,17 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
r8152_mdio_write(tp, MII_ADVERTISE, anar);
r8152_mdio_write(tp, MII_BMCR, bmcr);
+ switch (tp->version) {
+ case RTL_VER_08:
+ case RTL_VER_09:
+ r8153b_ups_flags_w1w0(tp, ups_flags_speed(speed_duplex),
+ UPS_FLAGS_SPEED_MASK);
+ break;
+
+ default:
+ break;
+ }
+
if (bmcr & BMCR_RESET) {
int i;
@@ -3212,6 +3720,38 @@ static void rtl8153_down(struct r8152 *tp)
r8153_aldps_en(tp, true);
}
+static void rtl8153b_up(struct r8152 *tp)
+{
+ if (test_bit(RTL8152_UNPLUG, &tp->flags))
+ return;
+
+ r8153b_u1u2en(tp, false);
+ r8153_u2p3en(tp, false);
+ r8153b_aldps_en(tp, false);
+
+ r8153_first_init(tp);
+ ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_B);
+
+ r8153b_aldps_en(tp, true);
+ r8153_u2p3en(tp, true);
+ r8153b_u1u2en(tp, true);
+}
+
+static void rtl8153b_down(struct r8152 *tp)
+{
+ if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
+ rtl_drop_queued_tx(tp);
+ return;
+ }
+
+ r8153b_u1u2en(tp, false);
+ r8153_u2p3en(tp, false);
+ r8153b_power_cut_en(tp, false);
+ r8153b_aldps_en(tp, false);
+ r8153_enter_oob(tp);
+ r8153b_aldps_en(tp, true);
+}
+
static bool rtl8152_in_nway(struct r8152 *tp)
{
u16 nway_state;
@@ -3607,6 +4147,66 @@ static void r8153_init(struct r8152 *tp)
}
}
+static void r8153b_init(struct r8152 *tp)
+{
+ u32 ocp_data;
+ u16 data;
+ int i;
+
+ if (test_bit(RTL8152_UNPLUG, &tp->flags))
+ return;
+
+ r8153b_u1u2en(tp, false);
+
+ for (i = 0; i < 500; i++) {
+ if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
+ AUTOLOAD_DONE)
+ break;
+ msleep(20);
+ }
+
+ data = r8153_phy_status(tp, 0);
+
+ data = r8152_mdio_read(tp, MII_BMCR);
+ if (data & BMCR_PDOWN) {
+ data &= ~BMCR_PDOWN;
+ r8152_mdio_write(tp, MII_BMCR, data);
+ }
+
+ data = r8153_phy_status(tp, PHY_STAT_LAN_ON);
+
+ r8153_u2p3en(tp, false);
+
+ /* MSC timer = 0xfff * 8ms = 32760 ms */
+ ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff);
+
+ /* U1/U2/L1 idle timer. 500 us */
+ ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);
+
+ r8153b_power_cut_en(tp, false);
+ r8153b_ups_en(tp, false);
+ r8153b_queue_wake(tp, false);
+ rtl_runtime_suspend_enable(tp, false);
+ r8153b_u1u2en(tp, true);
+ usb_enable_lpm(tp->udev);
+
+ /* MAC clock speed down */
+ ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2);
+ ocp_data |= MAC_CLK_SPDWN_EN;
+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data);
+
+ set_bit(GREEN_ETHERNET, &tp->flags);
+
+ /* rx aggregation */
+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
+ ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN);
+ ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
+
+ rtl_tally_reset(tp);
+
+ tp->coalesce = 15000; /* 15 us */
+}
+
static int rtl8152_pre_reset(struct usb_interface *intf)
{
struct r8152 *tp = usb_get_intfdata(intf);
@@ -4109,6 +4709,20 @@ static int r8153_set_eee(struct r8152 *tp, struct ethtool_eee *eee)
return 0;
}
+static int r8153b_set_eee(struct r8152 *tp, struct ethtool_eee *eee)
+{
+ u16 val = ethtool_adv_to_mmd_eee_adv_t(eee->advertised);
+
+ r8153b_eee_en(tp, eee->eee_enabled);
+
+ if (!eee->eee_enabled)
+ val = 0;
+
+ ocp_reg_write(tp, OCP_EEE_ADV, val);
+
+ return 0;
+}
+
static int
rtl_ethtool_get_eee(struct net_device *net, struct ethtool_eee *edata)
{
@@ -4366,6 +4980,14 @@ static void rtl8153_unload(struct r8152 *tp)
r8153_power_cut_en(tp, false);
}
+static void rtl8153b_unload(struct r8152 *tp)
+{
+ if (test_bit(RTL8152_UNPLUG, &tp->flags))
+ return;
+
+ r8153b_power_cut_en(tp, false);
+}
+
static int rtl_ops_init(struct r8152 *tp)
{
struct rtl_ops *ops = &tp->rtl_ops;
@@ -4405,6 +5027,21 @@ static int rtl_ops_init(struct r8152 *tp)
ops->autosuspend_en = rtl8153_runtime_enable;
break;
+ case RTL_VER_08:
+ case RTL_VER_09:
+ ops->init = r8153b_init;
+ ops->enable = rtl8153_enable;
+ ops->disable = rtl8153b_disable;
+ ops->up = rtl8153b_up;
+ ops->down = rtl8153b_down;
+ ops->unload = rtl8153b_unload;
+ ops->eee_get = r8153_get_eee;
+ ops->eee_set = r8153b_set_eee;
+ ops->in_nway = rtl8153_in_nway;
+ ops->hw_phy_cfg = r8153b_hw_phy_cfg;
+ ops->autosuspend_en = rtl8153b_runtime_enable;
+ break;
+
default:
ret = -ENODEV;
netif_err(tp, probe, tp->netdev, "Unknown Device\n");
@@ -4456,6 +5093,12 @@ static u8 rtl_get_version(struct usb_interface *intf)
case 0x4800:
version = RTL_VER_07;
break;
+ case 0x6000:
+ version = RTL_VER_08;
+ break;
+ case 0x6010:
+ version = RTL_VER_09;
+ break;
default:
version = RTL_VER_UNKNOWN;
dev_info(&intf->dev, "Unknown version 0x%04x\n", ocp_data);
--
2.7.4
Add byte_enable for ocp_read_word() to replace reading 4
bytes data with reading the desired 2 bytes data.
This is used to avoid the issue which is described in
commit b4d99def0938 ("r8152: remove sram_read"). The
original method always reads 4 bytes data, and it may
have problem when reading the PHY registers.
The new method is supported since RTL8153B, but it
doesn't influence the previous chips. The bits of the
byte_enable for the previous chips are the reserved
bits, and the hw would ignore them.
Signed-off-by: Hayes Wang <[email protected]>
---
drivers/net/usb/r8152.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 4c197da..184b680 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -962,11 +962,13 @@ static u16 ocp_read_word(struct r8152 *tp, u16 type, u16 index)
{
u32 data;
__le32 tmp;
+ u16 byen = BYTE_EN_WORD;
u8 shift = index & 2;
index &= ~3;
+ byen <<= shift;
- generic_ocp_read(tp, index, sizeof(tmp), &tmp, type);
+ generic_ocp_read(tp, index, sizeof(tmp), &tmp, type | byen);
data = __le32_to_cpu(tmp);
data >>= (shift * 8);
--
2.7.4
The settings of the new chip are the same with RTL8152, except that
its product ID is 0x8050.
Signed-off-by: Hayes Wang <[email protected]>
---
drivers/net/usb/r8152.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 5a02053..2744405 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -659,6 +659,7 @@ enum rtl_version {
RTL_VER_04,
RTL_VER_05,
RTL_VER_06,
+ RTL_VER_07,
RTL_VER_MAX
};
@@ -4183,6 +4184,7 @@ static int rtl8152_get_coalesce(struct net_device *netdev,
switch (tp->version) {
case RTL_VER_01:
case RTL_VER_02:
+ case RTL_VER_07:
return -EOPNOTSUPP;
default:
break;
@@ -4202,6 +4204,7 @@ static int rtl8152_set_coalesce(struct net_device *netdev,
switch (tp->version) {
case RTL_VER_01:
case RTL_VER_02:
+ case RTL_VER_07:
return -EOPNOTSUPP;
default:
break;
@@ -4301,6 +4304,7 @@ static int rtl8152_change_mtu(struct net_device *dev, int new_mtu)
switch (tp->version) {
case RTL_VER_01:
case RTL_VER_02:
+ case RTL_VER_07:
dev->mtu = new_mtu;
return 0;
default:
@@ -4370,6 +4374,7 @@ static int rtl_ops_init(struct r8152 *tp)
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;
@@ -4448,6 +4453,9 @@ static u8 rtl_get_version(struct usb_interface *intf)
case 0x5c30:
version = RTL_VER_06;
break;
+ case 0x4800:
+ version = RTL_VER_07;
+ break;
default:
version = RTL_VER_UNKNOWN;
dev_info(&intf->dev, "Unknown version 0x%04x\n", ocp_data);
@@ -4493,6 +4501,7 @@ static int rtl8152_probe(struct usb_interface *intf,
switch (version) {
case RTL_VER_01:
case RTL_VER_02:
+ case RTL_VER_07:
tp->mii.supports_gmii = 0;
break;
default:
@@ -4627,6 +4636,7 @@ static void rtl8152_disconnect(struct usb_interface *intf)
/* table of devices that work with this driver */
static struct usb_device_id rtl8152_table[] = {
+ {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8050)},
{REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152)},
{REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)},
{REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab)},
--
2.7.4
From: Hayes Wang <[email protected]>
Date: Thu, 15 Jun 2017 14:44:01 +0800
> These patches are used to support new chips.
Series applied, thank you.