diff options
author | hayeswang <hayeswang@realtek.com> | 2014-02-18 08:49:06 -0500 |
---|---|---|
committer | Vladislav Zhurba <vzhurba@nvidia.com> | 2018-02-01 16:57:59 -0500 |
commit | 43510815800dac7be81a8899c6f339062ed72425 (patch) | |
tree | 329325b7c76f85e969c35fe1f27b62bf6288f1e8 /drivers/net/usb/r8152_shield.c | |
parent | ac120ff51aa6c15d0f1ca334b40762fdb6bb9b5f (diff) |
r8152: support WOL
Support WOL for RTL8152 and RTL8153.
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Preetham Chandru R <pchandru@nvidia.com>
(cherry picked from commit 21ff2e8976b1be23eb0125ee83eb807ad40fb226)
Conflicts:
drivers/net/usb/r8152_shield.c
Change-Id: Ia33c2ee113e7150c372c82d85becb811950b26f2
Reviewed-on: http://git-master/r/370022
Tested-by: Aly Hirani <ahirani@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>
Diffstat (limited to 'drivers/net/usb/r8152_shield.c')
-rw-r--r-- | drivers/net/usb/r8152_shield.c | 118 |
1 files changed, 105 insertions, 13 deletions
diff --git a/drivers/net/usb/r8152_shield.c b/drivers/net/usb/r8152_shield.c index f2bf71f5c..237e8edb6 100644 --- a/drivers/net/usb/r8152_shield.c +++ b/drivers/net/usb/r8152_shield.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/ipv6.h> | 24 | #include <linux/ipv6.h> |
25 | 25 | ||
26 | /* Version Information */ | 26 | /* Version Information */ |
27 | #define DRIVER_VERSION "v1.03.0 (2013/12/26)" | 27 | #define DRIVER_VERSION "v1.05.0 (2014/02/18)" |
28 | #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>" | 28 | #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>" |
29 | #define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters" | 29 | #define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters" |
30 | #define MODULENAME "r8152" | 30 | #define MODULENAME "r8152" |
@@ -63,6 +63,8 @@ | |||
63 | #define PLA_RSTTELLY 0xe800 | 63 | #define PLA_RSTTELLY 0xe800 |
64 | #define PLA_CR 0xe813 | 64 | #define PLA_CR 0xe813 |
65 | #define PLA_CRWECR 0xe81c | 65 | #define PLA_CRWECR 0xe81c |
66 | #define PLA_CONFIG12 0xe81e /* CONFIG1, CONFIG2 */ | ||
67 | #define PLA_CONFIG34 0xe820 /* CONFIG3, CONFIG4 */ | ||
66 | #define PLA_CONFIG5 0xe822 | 68 | #define PLA_CONFIG5 0xe822 |
67 | #define PLA_PHY_PWR 0xe84c | 69 | #define PLA_PHY_PWR 0xe84c |
68 | #define PLA_OOB_CTRL 0xe84f | 70 | #define PLA_OOB_CTRL 0xe84f |
@@ -217,7 +219,14 @@ | |||
217 | /* PAL_BDC_CR */ | 219 | /* PAL_BDC_CR */ |
218 | #define ALDPS_PROXY_MODE 0x0001 | 220 | #define ALDPS_PROXY_MODE 0x0001 |
219 | 221 | ||
222 | /* PLA_CONFIG34 */ | ||
223 | #define LINK_ON_WAKE_EN 0x0010 | ||
224 | #define LINK_OFF_WAKE_EN 0x0008 | ||
225 | |||
220 | /* PLA_CONFIG5 */ | 226 | /* PLA_CONFIG5 */ |
227 | #define BWF_EN 0x0040 | ||
228 | #define MWF_EN 0x0020 | ||
229 | #define UWF_EN 0x0010 | ||
221 | #define LAN_WAKE_EN 0x0002 | 230 | #define LAN_WAKE_EN 0x0002 |
222 | 231 | ||
223 | /* PLA_LED_FEATURE */ | 232 | /* PLA_LED_FEATURE */ |
@@ -519,6 +528,7 @@ struct r8152 { | |||
519 | } rtl_ops; | 528 | } rtl_ops; |
520 | 529 | ||
521 | int intr_interval; | 530 | int intr_interval; |
531 | u32 saved_wolopts; | ||
522 | u32 msg_enable; | 532 | u32 msg_enable; |
523 | u32 tx_qlen; | 533 | u32 tx_qlen; |
524 | u16 ocp_base; | 534 | u16 ocp_base; |
@@ -1796,6 +1806,74 @@ static void r8152_power_cut_en(struct r8152 *tp, bool enable) | |||
1796 | 1806 | ||
1797 | } | 1807 | } |
1798 | 1808 | ||
1809 | #define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) | ||
1810 | |||
1811 | static u32 __rtl_get_wol(struct r8152 *tp) | ||
1812 | { | ||
1813 | u32 ocp_data; | ||
1814 | u32 wolopts = 0; | ||
1815 | |||
1816 | ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CONFIG5); | ||
1817 | if (!(ocp_data & LAN_WAKE_EN)) | ||
1818 | return 0; | ||
1819 | |||
1820 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34); | ||
1821 | if (ocp_data & LINK_ON_WAKE_EN) | ||
1822 | wolopts |= WAKE_PHY; | ||
1823 | |||
1824 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG5); | ||
1825 | if (ocp_data & UWF_EN) | ||
1826 | wolopts |= WAKE_UCAST; | ||
1827 | if (ocp_data & BWF_EN) | ||
1828 | wolopts |= WAKE_BCAST; | ||
1829 | if (ocp_data & MWF_EN) | ||
1830 | wolopts |= WAKE_MCAST; | ||
1831 | |||
1832 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL); | ||
1833 | if (ocp_data & MAGIC_EN) | ||
1834 | wolopts |= WAKE_MAGIC; | ||
1835 | |||
1836 | return wolopts; | ||
1837 | } | ||
1838 | |||
1839 | static void __rtl_set_wol(struct r8152 *tp, u32 wolopts) | ||
1840 | { | ||
1841 | u32 ocp_data; | ||
1842 | |||
1843 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); | ||
1844 | |||
1845 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34); | ||
1846 | ocp_data &= ~LINK_ON_WAKE_EN; | ||
1847 | if (wolopts & WAKE_PHY) | ||
1848 | ocp_data |= LINK_ON_WAKE_EN; | ||
1849 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data); | ||
1850 | |||
1851 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG5); | ||
1852 | ocp_data &= ~(UWF_EN | BWF_EN | MWF_EN | LAN_WAKE_EN); | ||
1853 | if (wolopts & WAKE_UCAST) | ||
1854 | ocp_data |= UWF_EN; | ||
1855 | if (wolopts & WAKE_BCAST) | ||
1856 | ocp_data |= BWF_EN; | ||
1857 | if (wolopts & WAKE_MCAST) | ||
1858 | ocp_data |= MWF_EN; | ||
1859 | if (wolopts & WAKE_ANY) | ||
1860 | ocp_data |= LAN_WAKE_EN; | ||
1861 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG5, ocp_data); | ||
1862 | |||
1863 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML); | ||
1864 | |||
1865 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL); | ||
1866 | ocp_data &= ~MAGIC_EN; | ||
1867 | if (wolopts & WAKE_MAGIC) | ||
1868 | ocp_data |= MAGIC_EN; | ||
1869 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL, ocp_data); | ||
1870 | |||
1871 | if (wolopts & WAKE_ANY) | ||
1872 | device_set_wakeup_enable(&tp->udev->dev, true); | ||
1873 | else | ||
1874 | device_set_wakeup_enable(&tp->udev->dev, false); | ||
1875 | } | ||
1876 | |||
1799 | static void rtl_phy_reset(struct r8152 *tp) | 1877 | static void rtl_phy_reset(struct r8152 *tp) |
1800 | { | 1878 | { |
1801 | u16 data; | 1879 | u16 data; |
@@ -2000,10 +2078,6 @@ static void r8152b_enter_oob(struct r8152 *tp) | |||
2000 | 2078 | ||
2001 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS); | 2079 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS); |
2002 | 2080 | ||
2003 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL); | ||
2004 | ocp_data |= MAGIC_EN; | ||
2005 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL, ocp_data); | ||
2006 | |||
2007 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR); | 2081 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR); |
2008 | ocp_data |= CPCR_RX_VLAN; | 2082 | ocp_data |= CPCR_RX_VLAN; |
2009 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data); | 2083 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data); |
@@ -2016,8 +2090,6 @@ static void r8152b_enter_oob(struct r8152 *tp) | |||
2016 | ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB; | 2090 | ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB; |
2017 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); | 2091 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); |
2018 | 2092 | ||
2019 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG5, LAN_WAKE_EN); | ||
2020 | |||
2021 | rxdy_gated_en(tp, false); | 2093 | rxdy_gated_en(tp, false); |
2022 | 2094 | ||
2023 | ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); | 2095 | ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); |
@@ -2215,10 +2287,6 @@ static void r8153_enter_oob(struct r8152 *tp) | |||
2215 | 2287 | ||
2216 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS); | 2288 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS); |
2217 | 2289 | ||
2218 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL); | ||
2219 | ocp_data |= MAGIC_EN; | ||
2220 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL, ocp_data); | ||
2221 | |||
2222 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG); | 2290 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG); |
2223 | ocp_data &= ~TEREDO_WAKE_MASK; | 2291 | ocp_data &= ~TEREDO_WAKE_MASK; |
2224 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data); | 2292 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data); |
@@ -2235,8 +2303,6 @@ static void r8153_enter_oob(struct r8152 *tp) | |||
2235 | ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB; | 2303 | ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB; |
2236 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); | 2304 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); |
2237 | 2305 | ||
2238 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG5, LAN_WAKE_EN); | ||
2239 | |||
2240 | rxdy_gated_en(tp, false); | 2306 | rxdy_gated_en(tp, false); |
2241 | 2307 | ||
2242 | ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); | 2308 | ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); |
@@ -2650,6 +2716,24 @@ static int rtl8152_resume(struct usb_interface *intf) | |||
2650 | return 0; | 2716 | return 0; |
2651 | } | 2717 | } |
2652 | 2718 | ||
2719 | static void rtl8152_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | ||
2720 | { | ||
2721 | struct r8152 *tp = netdev_priv(dev); | ||
2722 | |||
2723 | wol->supported = WAKE_ANY; | ||
2724 | wol->wolopts = __rtl_get_wol(tp); | ||
2725 | } | ||
2726 | |||
2727 | static int rtl8152_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | ||
2728 | { | ||
2729 | struct r8152 *tp = netdev_priv(dev); | ||
2730 | |||
2731 | __rtl_set_wol(tp, wol->wolopts); | ||
2732 | tp->saved_wolopts = wol->wolopts & WAKE_ANY; | ||
2733 | |||
2734 | return 0; | ||
2735 | } | ||
2736 | |||
2653 | static void rtl8152_get_drvinfo(struct net_device *netdev, | 2737 | static void rtl8152_get_drvinfo(struct net_device *netdev, |
2654 | struct ethtool_drvinfo *info) | 2738 | struct ethtool_drvinfo *info) |
2655 | { | 2739 | { |
@@ -2683,6 +2767,8 @@ static struct ethtool_ops ops = { | |||
2683 | .get_settings = rtl8152_get_settings, | 2767 | .get_settings = rtl8152_get_settings, |
2684 | .set_settings = rtl8152_set_settings, | 2768 | .set_settings = rtl8152_set_settings, |
2685 | .get_link = ethtool_op_get_link, | 2769 | .get_link = ethtool_op_get_link, |
2770 | .get_wol = rtl8152_get_wol, | ||
2771 | .set_wol = rtl8152_set_wol, | ||
2686 | }; | 2772 | }; |
2687 | 2773 | ||
2688 | static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) | 2774 | static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) |
@@ -2891,6 +2977,12 @@ static int rtl8152_probe(struct usb_interface *intf, | |||
2891 | goto out1; | 2977 | goto out1; |
2892 | } | 2978 | } |
2893 | 2979 | ||
2980 | tp->saved_wolopts = __rtl_get_wol(tp); | ||
2981 | if (tp->saved_wolopts) | ||
2982 | device_set_wakeup_enable(&udev->dev, true); | ||
2983 | else | ||
2984 | device_set_wakeup_enable(&udev->dev, false); | ||
2985 | |||
2894 | netif_info(tp, probe, netdev, "%s\n", DRIVER_VERSION); | 2986 | netif_info(tp, probe, netdev, "%s\n", DRIVER_VERSION); |
2895 | 2987 | ||
2896 | return 0; | 2988 | return 0; |