OSDN Git Service

r8152: disable DelayPhyPwrChg
[tomoyo/tomoyo-test1.git] / drivers / net / usb / r8152.c
index c5ebf35..3f425f9 100644 (file)
@@ -31,7 +31,7 @@
 #define NETNEXT_VERSION                "11"
 
 /* Information for net */
-#define NET_VERSION            "10"
+#define NET_VERSION            "11"
 
 #define DRIVER_VERSION         "v1." NETNEXT_VERSION "." NET_VERSION
 #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
@@ -68,6 +68,7 @@
 #define PLA_LED_FEATURE                0xdd92
 #define PLA_PHYAR              0xde00
 #define PLA_BOOT_CTRL          0xe004
+#define PLA_LWAKE_CTRL_REG     0xe007
 #define PLA_GPHY_INTR_IMR      0xe022
 #define PLA_EEE_CR             0xe040
 #define PLA_EEEP_CR            0xe080
@@ -95,6 +96,7 @@
 #define PLA_TALLYCNT           0xe890
 #define PLA_SFF_STS_7          0xe8de
 #define PLA_PHYSTATUS          0xe908
+#define PLA_CONFIG6            0xe90a /* CONFIG6 */
 #define PLA_BP_BA              0xfc26
 #define PLA_BP_0               0xfc28
 #define PLA_BP_1               0xfc2a
 #define PLA_BP_EN              0xfc38
 
 #define USB_USB2PHY            0xb41e
+#define USB_SSPHYLINK1         0xb426
 #define USB_SSPHYLINK2         0xb428
 #define USB_U2P3_CTRL          0xb460
 #define USB_CSR_DUMMY1         0xb464
 #define LINK_ON_WAKE_EN                0x0010
 #define LINK_OFF_WAKE_EN       0x0008
 
+/* PLA_CONFIG6 */
+#define LANWAKE_CLR_EN         BIT(0)
+
 /* PLA_CONFIG5 */
 #define BWF_EN                 0x0040
 #define MWF_EN                 0x0020
 /* PLA_PHY_PWR */
 #define TX_10M_IDLE_EN         0x0080
 #define PFM_PWM_SWITCH         0x0040
+#define TEST_IO_OFF            BIT(4)
 
 /* PLA_MAC_PWR_CTRL */
 #define D3_CLK_GATED_EN                0x00004000
 #define MAC_CLK_SPDWN_EN       BIT(15)
 
 /* PLA_MAC_PWR_CTRL3 */
+#define PLA_MCU_SPDWN_EN       BIT(14)
 #define PKT_AVAIL_SPDWN_EN     0x0100
 #define SUSPEND_SPDWN_EN       0x0004
 #define U1U2_SPDWN_EN          0x0002
 /* PLA_BOOT_CTRL */
 #define AUTOLOAD_DONE          0x0002
 
+/* PLA_LWAKE_CTRL_REG */
+#define LANWAKE_PIN            BIT(7)
+
 /* PLA_SUSPEND_FLAG */
 #define LINK_CHG_EVENT         BIT(0)
 
 #define DEBUG_LTSSM            0x0082
 
 /* PLA_EXTRA_STATUS */
+#define CUR_LINK_OK            BIT(15)
 #define U3P3_CHECK_EN          BIT(7)  /* RTL_VER_05 only */
 #define LINK_CHANGE_FLAG       BIT(8)
+#define POLL_LINK_CHG          BIT(0)
 
 /* USB_USB2PHY */
 #define USB2PHY_SUSPEND                0x0001
 #define USB2PHY_L1             0x0002
 
+/* USB_SSPHYLINK1 */
+#define DELAY_PHY_PWR_CHG      BIT(1)
+
 /* USB_SSPHYLINK2 */
 #define pwd_dn_scale_mask      0x3ffe
 #define pwd_dn_scale(x)                ((x) << 1)
@@ -2863,6 +2879,17 @@ static int rtl8153_enable(struct r8152 *tp)
        r8153_set_rx_early_timeout(tp);
        r8153_set_rx_early_size(tp);
 
+       if (tp->version == RTL_VER_09) {
+               u32 ocp_data;
+
+               ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK);
+               ocp_data &= ~FC_PATCH_TASK;
+               ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data);
+               usleep_range(1000, 2000);
+               ocp_data |= FC_PATCH_TASK;
+               ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data);
+       }
+
        return rtl_enable(tp);
 }
 
@@ -3376,8 +3403,8 @@ static void rtl8153b_runtime_enable(struct r8152 *tp, bool enable)
                r8153b_ups_en(tp, false);
                r8153_queue_wake(tp, false);
                rtl_runtime_suspend_enable(tp, false);
-               r8153_u2p3en(tp, true);
-               r8153b_u1u2en(tp, true);
+               if (tp->udev->speed != USB_SPEED_HIGH)
+                       r8153b_u1u2en(tp, true);
        }
 }
 
@@ -4675,7 +4702,6 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp)
 
        r8153_aldps_en(tp, true);
        r8152b_enable_fc(tp);
-       r8153_u2p3en(tp, true);
 
        set_bit(PHY_RESET, &tp->flags);
 }
@@ -4954,6 +4980,8 @@ static void rtl8152_down(struct r8152 *tp)
 
 static void rtl8153_up(struct r8152 *tp)
 {
+       u32 ocp_data;
+
        if (test_bit(RTL8152_UNPLUG, &tp->flags))
                return;
 
@@ -4961,6 +4989,19 @@ static void rtl8153_up(struct r8152 *tp)
        r8153_u2p3en(tp, false);
        r8153_aldps_en(tp, false);
        r8153_first_init(tp);
+
+       ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6);
+       ocp_data |= LANWAKE_CLR_EN;
+       ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6, ocp_data);
+
+       ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_LWAKE_CTRL_REG);
+       ocp_data &= ~LANWAKE_PIN;
+       ocp_write_byte(tp, MCU_TYPE_PLA, PLA_LWAKE_CTRL_REG, ocp_data);
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_SSPHYLINK1);
+       ocp_data &= ~DELAY_PHY_PWR_CHG;
+       ocp_write_word(tp, MCU_TYPE_USB, USB_SSPHYLINK1, ocp_data);
+
        r8153_aldps_en(tp, true);
 
        switch (tp->version) {
@@ -4979,11 +5020,17 @@ static void rtl8153_up(struct r8152 *tp)
 
 static void rtl8153_down(struct r8152 *tp)
 {
+       u32 ocp_data;
+
        if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
                rtl_drop_queued_tx(tp);
                return;
        }
 
+       ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6);
+       ocp_data &= ~LANWAKE_CLR_EN;
+       ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6, ocp_data);
+
        r8153_u1u2en(tp, false);
        r8153_u2p3en(tp, false);
        r8153_power_cut_en(tp, false);
@@ -4994,6 +5041,8 @@ static void rtl8153_down(struct r8152 *tp)
 
 static void rtl8153b_up(struct r8152 *tp)
 {
+       u32 ocp_data;
+
        if (test_bit(RTL8152_UNPLUG, &tp->flags))
                return;
 
@@ -5004,18 +5053,29 @@ static void rtl8153b_up(struct r8152 *tp)
        r8153_first_init(tp);
        ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_B);
 
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3);
+       ocp_data &= ~PLA_MCU_SPDWN_EN;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data);
+
        r8153_aldps_en(tp, true);
-       r8153_u2p3en(tp, true);
-       r8153b_u1u2en(tp, true);
+
+       if (tp->udev->speed != USB_SPEED_HIGH)
+               r8153b_u1u2en(tp, true);
 }
 
 static void rtl8153b_down(struct r8152 *tp)
 {
+       u32 ocp_data;
+
        if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
                rtl_drop_queued_tx(tp);
                return;
        }
 
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3);
+       ocp_data |= PLA_MCU_SPDWN_EN;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data);
+
        r8153b_u1u2en(tp, false);
        r8153_u2p3en(tp, false);
        r8153b_power_cut_en(tp, false);
@@ -5387,6 +5447,16 @@ static void r8153_init(struct r8152 *tp)
                else
                        ocp_data |= DYNAMIC_BURST;
                ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1, ocp_data);
+
+               r8153_queue_wake(tp, false);
+
+               ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS);
+               if (rtl8152_get_speed(tp) & LINK_STATUS)
+                       ocp_data |= CUR_LINK_OK;
+               else
+                       ocp_data &= ~CUR_LINK_OK;
+               ocp_data |= POLL_LINK_CHG;
+               ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data);
        }
 
        ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY2);
@@ -5416,10 +5486,19 @@ static void r8153_init(struct r8152 *tp)
        ocp_write_word(tp, MCU_TYPE_USB, USB_CONNECT_TIMER, 0x0001);
 
        r8153_power_cut_en(tp, false);
+       rtl_runtime_suspend_enable(tp, false);
        r8153_u1u2en(tp, true);
        r8153_mac_clk_spd(tp, false);
        usb_enable_lpm(tp->udev);
 
+       ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6);
+       ocp_data |= LANWAKE_CLR_EN;
+       ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6, ocp_data);
+
+       ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_LWAKE_CTRL_REG);
+       ocp_data &= ~LANWAKE_PIN;
+       ocp_write_byte(tp, MCU_TYPE_PLA, PLA_LWAKE_CTRL_REG, ocp_data);
+
        /* rx aggregation */
        ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
        ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN);
@@ -5484,7 +5563,17 @@ static void r8153b_init(struct r8152 *tp)
        r8153b_ups_en(tp, false);
        r8153_queue_wake(tp, false);
        rtl_runtime_suspend_enable(tp, false);
-       r8153b_u1u2en(tp, true);
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS);
+       if (rtl8152_get_speed(tp) & LINK_STATUS)
+               ocp_data |= CUR_LINK_OK;
+       else
+               ocp_data &= ~CUR_LINK_OK;
+       ocp_data |= POLL_LINK_CHG;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data);
+
+       if (tp->udev->speed != USB_SPEED_HIGH)
+               r8153b_u1u2en(tp, true);
        usb_enable_lpm(tp->udev);
 
        /* MAC clock speed down */
@@ -5492,6 +5581,19 @@ static void r8153b_init(struct r8152 *tp)
        ocp_data |= MAC_CLK_SPDWN_EN;
        ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data);
 
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3);
+       ocp_data &= ~PLA_MCU_SPDWN_EN;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data);
+
+       if (tp->version == RTL_VER_09) {
+               /* Disable Test IO for 32QFN */
+               if (ocp_read_byte(tp, MCU_TYPE_PLA, 0xdc00) & BIT(5)) {
+                       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR);
+                       ocp_data |= TEST_IO_OFF;
+                       ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data);
+               }
+       }
+
        set_bit(GREEN_ETHERNET, &tp->flags);
 
        /* rx aggregation */
@@ -6597,6 +6699,9 @@ static int rtl8152_probe(struct usb_interface *intf,
                return -ENODEV;
        }
 
+       if (intf->cur_altsetting->desc.bNumEndpoints < 3)
+               return -ENODEV;
+
        usb_reset_device(udev);
        netdev = alloc_etherdev(sizeof(struct r8152));
        if (!netdev) {
@@ -6704,6 +6809,11 @@ static int rtl8152_probe(struct usb_interface *intf,
 
        intf->needs_remote_wakeup = 1;
 
+       if (!rtl_can_wakeup(tp))
+               __rtl_set_wol(tp, 0);
+       else
+               tp->saved_wolopts = __rtl_get_wol(tp);
+
        tp->rtl_ops.init(tp);
 #if IS_BUILTIN(CONFIG_USB_RTL8152)
        /* Retry in case request_firmware() is not ready yet. */
@@ -6721,10 +6831,6 @@ static int rtl8152_probe(struct usb_interface *intf,
                goto out1;
        }
 
-       if (!rtl_can_wakeup(tp))
-               __rtl_set_wol(tp, 0);
-
-       tp->saved_wolopts = __rtl_get_wol(tp);
        if (tp->saved_wolopts)
                device_set_wakeup_enable(&udev->dev, true);
        else