blob: bf0b32411b1a37804fe2c49406b6c97a9d361bd3 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Francois Romieu07d3f512007-02-21 22:40:46 +01002 * r8169.c: RealTek 8169/8168/8101 ethernet driver.
3 *
4 * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
5 * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
6 * Copyright (c) a lot of people too. Please respect their work.
7 *
8 * See MAINTAINERS file for support contact information.
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 */
10
11#include <linux/module.h>
12#include <linux/moduleparam.h>
13#include <linux/pci.h>
14#include <linux/netdevice.h>
15#include <linux/etherdevice.h>
16#include <linux/delay.h>
17#include <linux/ethtool.h>
18#include <linux/mii.h>
19#include <linux/if_vlan.h>
20#include <linux/crc32.h>
21#include <linux/in.h>
22#include <linux/ip.h>
23#include <linux/tcp.h>
24#include <linux/init.h>
Alexey Dobriyana6b7a402011-06-06 10:43:46 +000025#include <linux/interrupt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/dma-mapping.h>
Rafael J. Wysockie1759442010-03-14 14:33:51 +000027#include <linux/pm_runtime.h>
françois romieubca03d52011-01-03 15:07:31 +000028#include <linux/firmware.h>
Stanislaw Gruszkaba04c7c2011-02-22 02:00:11 +000029#include <linux/pci-aspm.h>
Paul Gortmaker70c71602011-05-22 16:47:17 -040030#include <linux/prefetch.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
32#include <asm/io.h>
33#include <asm/irq.h>
34
Francois Romieu865c6522008-05-11 14:51:00 +020035#define RTL8169_VERSION "2.3LK-NAPI"
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#define MODULENAME "r8169"
37#define PFX MODULENAME ": "
38
françois romieubca03d52011-01-03 15:07:31 +000039#define FIRMWARE_8168D_1 "rtl_nic/rtl8168d-1.fw"
40#define FIRMWARE_8168D_2 "rtl_nic/rtl8168d-2.fw"
hayeswang01dc7fe2011-03-21 01:50:28 +000041#define FIRMWARE_8168E_1 "rtl_nic/rtl8168e-1.fw"
42#define FIRMWARE_8168E_2 "rtl_nic/rtl8168e-2.fw"
Hayes Wang70090422011-07-06 15:58:06 +080043#define FIRMWARE_8168E_3 "rtl_nic/rtl8168e-3.fw"
Hayes Wangc2218922011-09-06 16:55:18 +080044#define FIRMWARE_8168F_1 "rtl_nic/rtl8168f-1.fw"
45#define FIRMWARE_8168F_2 "rtl_nic/rtl8168f-2.fw"
Hayes Wang5a5e4442011-02-22 17:26:21 +080046#define FIRMWARE_8105E_1 "rtl_nic/rtl8105e-1.fw"
Hayes Wang7e18dca2012-03-30 14:33:02 +080047#define FIRMWARE_8402_1 "rtl_nic/rtl8402-1.fw"
Hayes Wangb3d7b2f2012-03-30 14:48:06 +080048#define FIRMWARE_8411_1 "rtl_nic/rtl8411-1.fw"
Hayes Wang5598bfe2012-07-02 17:23:21 +080049#define FIRMWARE_8106E_1 "rtl_nic/rtl8106e-1.fw"
Hayes Wangc5583862012-07-02 17:23:22 +080050#define FIRMWARE_8168G_1 "rtl_nic/rtl8168g-1.fw"
françois romieubca03d52011-01-03 15:07:31 +000051
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#ifdef RTL8169_DEBUG
53#define assert(expr) \
Francois Romieu5b0384f2006-08-16 16:00:01 +020054 if (!(expr)) { \
55 printk( "Assertion failed! %s,%s,%s,line=%d\n", \
Harvey Harrisonb39d66a2008-08-20 16:52:04 -070056 #expr,__FILE__,__func__,__LINE__); \
Francois Romieu5b0384f2006-08-16 16:00:01 +020057 }
Joe Perches06fa7352007-10-18 21:15:00 +020058#define dprintk(fmt, args...) \
59 do { printk(KERN_DEBUG PFX fmt, ## args); } while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070060#else
61#define assert(expr) do {} while (0)
62#define dprintk(fmt, args...) do {} while (0)
63#endif /* RTL8169_DEBUG */
64
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +020065#define R8169_MSG_DEFAULT \
Francois Romieuf0e837d2005-09-30 16:54:02 -070066 (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN)
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +020067
Julien Ducourthial477206a2012-05-09 00:00:06 +020068#define TX_SLOTS_AVAIL(tp) \
69 (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx)
70
71/* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */
72#define TX_FRAGS_READY_FOR(tp,nr_frags) \
73 (TX_SLOTS_AVAIL(tp) >= (nr_frags + 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Linus Torvalds1da177e2005-04-16 15:20:36 -070075/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
76 The RTL chips use a 64 element hash table based on the Ethernet CRC. */
Arjan van de Venf71e1302006-03-03 21:33:57 -050077static const int multicast_filter_limit = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
Francois Romieu9c14cea2008-07-05 00:21:15 +020079#define MAX_READ_REQUEST_SHIFT 12
Michal Schmidtaee77e42012-09-09 13:55:26 +000080#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */
Linus Torvalds1da177e2005-04-16 15:20:36 -070081#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
82
83#define R8169_REGS_SIZE 256
84#define R8169_NAPI_WEIGHT 64
85#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */
86#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */
87#define RX_BUF_SIZE 1536 /* Rx Buffer size */
88#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
89#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
90
91#define RTL8169_TX_TIMEOUT (6*HZ)
92#define RTL8169_PHY_TIMEOUT (10*HZ)
93
françois romieuea8dbdd2009-03-15 01:10:50 +000094#define RTL_EEPROM_SIG cpu_to_le32(0x8129)
95#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff)
Francois Romieue1564ec2008-10-16 22:46:13 +020096#define RTL_EEPROM_SIG_ADDR 0x0000
97
Linus Torvalds1da177e2005-04-16 15:20:36 -070098/* write/read MMIO register */
99#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg))
100#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg))
101#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg))
102#define RTL_R8(reg) readb (ioaddr + (reg))
103#define RTL_R16(reg) readw (ioaddr + (reg))
Junchang Wang06f555f2010-05-30 02:26:07 +0000104#define RTL_R32(reg) readl (ioaddr + (reg))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
106enum mac_version {
Francois Romieu85bffe62011-04-27 08:22:39 +0200107 RTL_GIGA_MAC_VER_01 = 0,
108 RTL_GIGA_MAC_VER_02,
109 RTL_GIGA_MAC_VER_03,
110 RTL_GIGA_MAC_VER_04,
111 RTL_GIGA_MAC_VER_05,
112 RTL_GIGA_MAC_VER_06,
113 RTL_GIGA_MAC_VER_07,
114 RTL_GIGA_MAC_VER_08,
115 RTL_GIGA_MAC_VER_09,
116 RTL_GIGA_MAC_VER_10,
117 RTL_GIGA_MAC_VER_11,
118 RTL_GIGA_MAC_VER_12,
119 RTL_GIGA_MAC_VER_13,
120 RTL_GIGA_MAC_VER_14,
121 RTL_GIGA_MAC_VER_15,
122 RTL_GIGA_MAC_VER_16,
123 RTL_GIGA_MAC_VER_17,
124 RTL_GIGA_MAC_VER_18,
125 RTL_GIGA_MAC_VER_19,
126 RTL_GIGA_MAC_VER_20,
127 RTL_GIGA_MAC_VER_21,
128 RTL_GIGA_MAC_VER_22,
129 RTL_GIGA_MAC_VER_23,
130 RTL_GIGA_MAC_VER_24,
131 RTL_GIGA_MAC_VER_25,
132 RTL_GIGA_MAC_VER_26,
133 RTL_GIGA_MAC_VER_27,
134 RTL_GIGA_MAC_VER_28,
135 RTL_GIGA_MAC_VER_29,
136 RTL_GIGA_MAC_VER_30,
137 RTL_GIGA_MAC_VER_31,
138 RTL_GIGA_MAC_VER_32,
139 RTL_GIGA_MAC_VER_33,
Hayes Wang70090422011-07-06 15:58:06 +0800140 RTL_GIGA_MAC_VER_34,
Hayes Wangc2218922011-09-06 16:55:18 +0800141 RTL_GIGA_MAC_VER_35,
142 RTL_GIGA_MAC_VER_36,
Hayes Wang7e18dca2012-03-30 14:33:02 +0800143 RTL_GIGA_MAC_VER_37,
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800144 RTL_GIGA_MAC_VER_38,
Hayes Wang5598bfe2012-07-02 17:23:21 +0800145 RTL_GIGA_MAC_VER_39,
Hayes Wangc5583862012-07-02 17:23:22 +0800146 RTL_GIGA_MAC_VER_40,
147 RTL_GIGA_MAC_VER_41,
Francois Romieu85bffe62011-04-27 08:22:39 +0200148 RTL_GIGA_MAC_NONE = 0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149};
150
Francois Romieu2b7b4312011-04-18 22:53:24 -0700151enum rtl_tx_desc_version {
152 RTL_TD_0 = 0,
153 RTL_TD_1 = 1,
154};
155
Francois Romieud58d46b2011-05-03 16:38:29 +0200156#define JUMBO_1K ETH_DATA_LEN
157#define JUMBO_4K (4*1024 - ETH_HLEN - 2)
158#define JUMBO_6K (6*1024 - ETH_HLEN - 2)
159#define JUMBO_7K (7*1024 - ETH_HLEN - 2)
160#define JUMBO_9K (9*1024 - ETH_HLEN - 2)
161
162#define _R(NAME,TD,FW,SZ,B) { \
163 .name = NAME, \
164 .txd_version = TD, \
165 .fw_name = FW, \
166 .jumbo_max = SZ, \
167 .jumbo_tx_csum = B \
168}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169
Jesper Juhl3c6bee12006-01-09 20:54:01 -0800170static const struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 const char *name;
Francois Romieu2b7b4312011-04-18 22:53:24 -0700172 enum rtl_tx_desc_version txd_version;
Francois Romieu85bffe62011-04-27 08:22:39 +0200173 const char *fw_name;
Francois Romieud58d46b2011-05-03 16:38:29 +0200174 u16 jumbo_max;
175 bool jumbo_tx_csum;
Francois Romieu85bffe62011-04-27 08:22:39 +0200176} rtl_chip_infos[] = {
177 /* PCI devices. */
178 [RTL_GIGA_MAC_VER_01] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200179 _R("RTL8169", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200180 [RTL_GIGA_MAC_VER_02] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200181 _R("RTL8169s", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200182 [RTL_GIGA_MAC_VER_03] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200183 _R("RTL8110s", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200184 [RTL_GIGA_MAC_VER_04] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200185 _R("RTL8169sb/8110sb", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200186 [RTL_GIGA_MAC_VER_05] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200187 _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200188 [RTL_GIGA_MAC_VER_06] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200189 _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200190 /* PCI-E devices. */
191 [RTL_GIGA_MAC_VER_07] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200192 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200193 [RTL_GIGA_MAC_VER_08] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200194 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200195 [RTL_GIGA_MAC_VER_09] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200196 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200197 [RTL_GIGA_MAC_VER_10] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200198 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200199 [RTL_GIGA_MAC_VER_11] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200200 _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200201 [RTL_GIGA_MAC_VER_12] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200202 _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200203 [RTL_GIGA_MAC_VER_13] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200204 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200205 [RTL_GIGA_MAC_VER_14] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200206 _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200207 [RTL_GIGA_MAC_VER_15] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200208 _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200209 [RTL_GIGA_MAC_VER_16] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200210 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200211 [RTL_GIGA_MAC_VER_17] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200212 _R("RTL8168b/8111b", RTL_TD_1, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200213 [RTL_GIGA_MAC_VER_18] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200214 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200215 [RTL_GIGA_MAC_VER_19] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200216 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200217 [RTL_GIGA_MAC_VER_20] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200218 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200219 [RTL_GIGA_MAC_VER_21] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200220 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200221 [RTL_GIGA_MAC_VER_22] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200222 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200223 [RTL_GIGA_MAC_VER_23] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200224 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200225 [RTL_GIGA_MAC_VER_24] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200226 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200227 [RTL_GIGA_MAC_VER_25] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200228 _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1,
229 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200230 [RTL_GIGA_MAC_VER_26] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200231 _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2,
232 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200233 [RTL_GIGA_MAC_VER_27] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200234 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200235 [RTL_GIGA_MAC_VER_28] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200236 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200237 [RTL_GIGA_MAC_VER_29] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200238 _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
239 JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200240 [RTL_GIGA_MAC_VER_30] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200241 _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
242 JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200243 [RTL_GIGA_MAC_VER_31] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200244 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200245 [RTL_GIGA_MAC_VER_32] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200246 _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1,
247 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200248 [RTL_GIGA_MAC_VER_33] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200249 _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2,
250 JUMBO_9K, false),
Hayes Wang70090422011-07-06 15:58:06 +0800251 [RTL_GIGA_MAC_VER_34] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200252 _R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3,
253 JUMBO_9K, false),
Hayes Wangc2218922011-09-06 16:55:18 +0800254 [RTL_GIGA_MAC_VER_35] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200255 _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_1,
256 JUMBO_9K, false),
Hayes Wangc2218922011-09-06 16:55:18 +0800257 [RTL_GIGA_MAC_VER_36] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200258 _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_2,
259 JUMBO_9K, false),
Hayes Wang7e18dca2012-03-30 14:33:02 +0800260 [RTL_GIGA_MAC_VER_37] =
261 _R("RTL8402", RTL_TD_1, FIRMWARE_8402_1,
262 JUMBO_1K, true),
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800263 [RTL_GIGA_MAC_VER_38] =
264 _R("RTL8411", RTL_TD_1, FIRMWARE_8411_1,
265 JUMBO_9K, false),
Hayes Wang5598bfe2012-07-02 17:23:21 +0800266 [RTL_GIGA_MAC_VER_39] =
267 _R("RTL8106e", RTL_TD_1, FIRMWARE_8106E_1,
268 JUMBO_1K, true),
Hayes Wangc5583862012-07-02 17:23:22 +0800269 [RTL_GIGA_MAC_VER_40] =
270 _R("RTL8168g/8111g", RTL_TD_1, FIRMWARE_8168G_1,
271 JUMBO_9K, false),
272 [RTL_GIGA_MAC_VER_41] =
273 _R("RTL8168g/8111g", RTL_TD_1, NULL, JUMBO_9K, false),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274};
275#undef _R
276
Francois Romieubcf0bf92006-07-26 23:14:13 +0200277enum cfg_version {
278 RTL_CFG_0 = 0x00,
279 RTL_CFG_1,
280 RTL_CFG_2
281};
282
Alexey Dobriyana3aa1882010-01-07 11:58:11 +0000283static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = {
Francois Romieubcf0bf92006-07-26 23:14:13 +0200284 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 },
Francois Romieud2eed8c2006-08-31 22:01:07 +0200285 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 },
Francois Romieud81bf552006-09-20 21:31:20 +0200286 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 },
Francois Romieu07ce4062007-02-23 23:36:39 +0100287 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200288 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
Francois Romieu2a35cfa2012-08-31 23:06:17 +0200289 { PCI_VENDOR_ID_DLINK, 0x4300,
290 PCI_VENDOR_ID_DLINK, 0x4b10, 0, 0, RTL_CFG_1 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200291 { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 },
Lennart Sorensen93a3aa22011-07-28 13:18:11 +0000292 { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302), 0, 0, RTL_CFG_0 },
Francois Romieubc1660b2007-10-12 23:58:09 +0200293 { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200294 { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 },
295 { PCI_VENDOR_ID_LINKSYS, 0x1032,
296 PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 },
Ciaran McCreesh11d2e282007-11-01 22:48:15 +0100297 { 0x0001, 0x8168,
298 PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 {0,},
300};
301
302MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
303
Eric Dumazet6f0333b2010-10-11 11:17:47 +0000304static int rx_buf_sz = 16383;
David S. Miller4300e8c2010-03-26 10:23:30 -0700305static int use_dac;
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200306static struct {
307 u32 msg_enable;
308} debug = { -1 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
Francois Romieu07d3f512007-02-21 22:40:46 +0100310enum rtl_registers {
311 MAC0 = 0, /* Ethernet hardware address. */
Francois Romieu773d2022007-01-31 23:47:43 +0100312 MAC4 = 4,
Francois Romieu07d3f512007-02-21 22:40:46 +0100313 MAR0 = 8, /* Multicast filter. */
314 CounterAddrLow = 0x10,
315 CounterAddrHigh = 0x14,
316 TxDescStartAddrLow = 0x20,
317 TxDescStartAddrHigh = 0x24,
318 TxHDescStartAddrLow = 0x28,
319 TxHDescStartAddrHigh = 0x2c,
320 FLASH = 0x30,
321 ERSR = 0x36,
322 ChipCmd = 0x37,
323 TxPoll = 0x38,
324 IntrMask = 0x3c,
325 IntrStatus = 0x3e,
Francois Romieu2b7b4312011-04-18 22:53:24 -0700326
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800327 TxConfig = 0x40,
328#define TXCFG_AUTO_FIFO (1 << 7) /* 8111e-vl */
329#define TXCFG_EMPTY (1 << 11) /* 8111e-vl */
330
331 RxConfig = 0x44,
332#define RX128_INT_EN (1 << 15) /* 8111c and later */
333#define RX_MULTI_EN (1 << 14) /* 8111c only */
334#define RXCFG_FIFO_SHIFT 13
335 /* No threshold before first PCI xfer */
336#define RX_FIFO_THRESH (7 << RXCFG_FIFO_SHIFT)
337#define RXCFG_DMA_SHIFT 8
338 /* Unlimited maximum PCI burst. */
339#define RX_DMA_BURST (7 << RXCFG_DMA_SHIFT)
Francois Romieu2b7b4312011-04-18 22:53:24 -0700340
Francois Romieu07d3f512007-02-21 22:40:46 +0100341 RxMissed = 0x4c,
342 Cfg9346 = 0x50,
343 Config0 = 0x51,
344 Config1 = 0x52,
345 Config2 = 0x53,
Francois Romieud387b422012-04-17 11:12:01 +0200346#define PME_SIGNAL (1 << 5) /* 8168c and later */
347
Francois Romieu07d3f512007-02-21 22:40:46 +0100348 Config3 = 0x54,
349 Config4 = 0x55,
350 Config5 = 0x56,
351 MultiIntr = 0x5c,
352 PHYAR = 0x60,
Francois Romieu07d3f512007-02-21 22:40:46 +0100353 PHYstatus = 0x6c,
354 RxMaxSize = 0xda,
355 CPlusCmd = 0xe0,
356 IntrMitigate = 0xe2,
357 RxDescAddrLow = 0xe4,
358 RxDescAddrHigh = 0xe8,
françois romieuf0298f82011-01-03 15:07:42 +0000359 EarlyTxThres = 0xec, /* 8169. Unit of 32 bytes. */
360
361#define NoEarlyTx 0x3f /* Max value : no early transmit. */
362
363 MaxTxPacketSize = 0xec, /* 8101/8168. Unit of 128 bytes. */
364
365#define TxPacketMax (8064 >> 7)
Hayes Wang3090bd92011-09-06 16:55:15 +0800366#define EarlySize 0x27
françois romieuf0298f82011-01-03 15:07:42 +0000367
Francois Romieu07d3f512007-02-21 22:40:46 +0100368 FuncEvent = 0xf0,
369 FuncEventMask = 0xf4,
370 FuncPresetState = 0xf8,
371 FuncForceEvent = 0xfc,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372};
373
Francois Romieuf162a5d2008-06-01 22:37:49 +0200374enum rtl8110_registers {
375 TBICSR = 0x64,
376 TBI_ANAR = 0x68,
377 TBI_LPAR = 0x6a,
378};
379
380enum rtl8168_8101_registers {
381 CSIDR = 0x64,
382 CSIAR = 0x68,
383#define CSIAR_FLAG 0x80000000
384#define CSIAR_WRITE_CMD 0x80000000
385#define CSIAR_BYTE_ENABLE 0x0f
386#define CSIAR_BYTE_ENABLE_SHIFT 12
387#define CSIAR_ADDR_MASK 0x0fff
Hayes Wang7e18dca2012-03-30 14:33:02 +0800388#define CSIAR_FUNC_CARD 0x00000000
389#define CSIAR_FUNC_SDIO 0x00010000
390#define CSIAR_FUNC_NIC 0x00020000
françois romieu065c27c2011-01-03 15:08:12 +0000391 PMCH = 0x6f,
Francois Romieuf162a5d2008-06-01 22:37:49 +0200392 EPHYAR = 0x80,
393#define EPHYAR_FLAG 0x80000000
394#define EPHYAR_WRITE_CMD 0x80000000
395#define EPHYAR_REG_MASK 0x1f
396#define EPHYAR_REG_SHIFT 16
397#define EPHYAR_DATA_MASK 0xffff
Hayes Wang5a5e4442011-02-22 17:26:21 +0800398 DLLPR = 0xd0,
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800399#define PFM_EN (1 << 6)
Francois Romieuf162a5d2008-06-01 22:37:49 +0200400 DBG_REG = 0xd1,
401#define FIX_NAK_1 (1 << 4)
402#define FIX_NAK_2 (1 << 3)
Hayes Wang5a5e4442011-02-22 17:26:21 +0800403 TWSI = 0xd2,
404 MCU = 0xd3,
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800405#define NOW_IS_OOB (1 << 7)
Hayes Wangc5583862012-07-02 17:23:22 +0800406#define TX_EMPTY (1 << 5)
407#define RX_EMPTY (1 << 4)
408#define RXTX_EMPTY (TX_EMPTY | RX_EMPTY)
Hayes Wang5a5e4442011-02-22 17:26:21 +0800409#define EN_NDP (1 << 3)
410#define EN_OOB_RESET (1 << 2)
Hayes Wangc5583862012-07-02 17:23:22 +0800411#define LINK_LIST_RDY (1 << 1)
françois romieudaf9df62009-10-07 12:44:20 +0000412 EFUSEAR = 0xdc,
413#define EFUSEAR_FLAG 0x80000000
414#define EFUSEAR_WRITE_CMD 0x80000000
415#define EFUSEAR_READ_CMD 0x00000000
416#define EFUSEAR_REG_MASK 0x03ff
417#define EFUSEAR_REG_SHIFT 8
418#define EFUSEAR_DATA_MASK 0xff
Francois Romieuf162a5d2008-06-01 22:37:49 +0200419};
420
françois romieuc0e45c12011-01-03 15:08:04 +0000421enum rtl8168_registers {
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800422 LED_FREQ = 0x1a,
423 EEE_LED = 0x1b,
françois romieub646d902011-01-03 15:08:21 +0000424 ERIDR = 0x70,
425 ERIAR = 0x74,
426#define ERIAR_FLAG 0x80000000
427#define ERIAR_WRITE_CMD 0x80000000
428#define ERIAR_READ_CMD 0x00000000
429#define ERIAR_ADDR_BYTE_ALIGN 4
françois romieub646d902011-01-03 15:08:21 +0000430#define ERIAR_TYPE_SHIFT 16
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800431#define ERIAR_EXGMAC (0x00 << ERIAR_TYPE_SHIFT)
432#define ERIAR_MSIX (0x01 << ERIAR_TYPE_SHIFT)
433#define ERIAR_ASF (0x02 << ERIAR_TYPE_SHIFT)
434#define ERIAR_MASK_SHIFT 12
435#define ERIAR_MASK_0001 (0x1 << ERIAR_MASK_SHIFT)
436#define ERIAR_MASK_0011 (0x3 << ERIAR_MASK_SHIFT)
Hayes Wangc5583862012-07-02 17:23:22 +0800437#define ERIAR_MASK_0101 (0x5 << ERIAR_MASK_SHIFT)
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800438#define ERIAR_MASK_1111 (0xf << ERIAR_MASK_SHIFT)
françois romieuc0e45c12011-01-03 15:08:04 +0000439 EPHY_RXER_NUM = 0x7c,
440 OCPDR = 0xb0, /* OCP GPHY access */
441#define OCPDR_WRITE_CMD 0x80000000
442#define OCPDR_READ_CMD 0x00000000
443#define OCPDR_REG_MASK 0x7f
444#define OCPDR_GPHY_REG_SHIFT 16
445#define OCPDR_DATA_MASK 0xffff
446 OCPAR = 0xb4,
447#define OCPAR_FLAG 0x80000000
448#define OCPAR_GPHY_WRITE_CMD 0x8000f060
449#define OCPAR_GPHY_READ_CMD 0x0000f060
Hayes Wangc5583862012-07-02 17:23:22 +0800450 GPHY_OCP = 0xb8,
hayeswang01dc7fe2011-03-21 01:50:28 +0000451 RDSAR1 = 0xd0, /* 8168c only. Undocumented on 8168dp */
452 MISC = 0xf0, /* 8168e only. */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200453#define TXPLA_RST (1 << 29)
Hayes Wang5598bfe2012-07-02 17:23:21 +0800454#define DISABLE_LAN_EN (1 << 23) /* Enable GPIO pin */
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800455#define PWM_EN (1 << 22)
Hayes Wangc5583862012-07-02 17:23:22 +0800456#define RXDV_GATED_EN (1 << 19)
Hayes Wang5598bfe2012-07-02 17:23:21 +0800457#define EARLY_TALLY_EN (1 << 16)
françois romieuc0e45c12011-01-03 15:08:04 +0000458};
459
Francois Romieu07d3f512007-02-21 22:40:46 +0100460enum rtl_register_content {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 /* InterruptStatusBits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100462 SYSErr = 0x8000,
463 PCSTimeout = 0x4000,
464 SWInt = 0x0100,
465 TxDescUnavail = 0x0080,
466 RxFIFOOver = 0x0040,
467 LinkChg = 0x0020,
468 RxOverflow = 0x0010,
469 TxErr = 0x0008,
470 TxOK = 0x0004,
471 RxErr = 0x0002,
472 RxOK = 0x0001,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473
474 /* RxStatusDesc */
David S. Miller8decf862011-09-22 03:23:13 -0400475 RxBOVF = (1 << 24),
Francois Romieu9dccf612006-05-14 12:31:17 +0200476 RxFOVF = (1 << 23),
477 RxRWT = (1 << 22),
478 RxRES = (1 << 21),
479 RxRUNT = (1 << 20),
480 RxCRC = (1 << 19),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481
482 /* ChipCmdBits */
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800483 StopReq = 0x80,
Francois Romieu07d3f512007-02-21 22:40:46 +0100484 CmdReset = 0x10,
485 CmdRxEnb = 0x08,
486 CmdTxEnb = 0x04,
487 RxBufEmpty = 0x01,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488
Francois Romieu275391a2007-02-23 23:50:28 +0100489 /* TXPoll register p.5 */
490 HPQ = 0x80, /* Poll cmd on the high prio queue */
491 NPQ = 0x40, /* Poll cmd on the low prio queue */
492 FSWInt = 0x01, /* Forced software interrupt */
493
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 /* Cfg9346Bits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100495 Cfg9346_Lock = 0x00,
496 Cfg9346_Unlock = 0xc0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497
498 /* rx_mode_bits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100499 AcceptErr = 0x20,
500 AcceptRunt = 0x10,
501 AcceptBroadcast = 0x08,
502 AcceptMulticast = 0x04,
503 AcceptMyPhys = 0x02,
504 AcceptAllPhys = 0x01,
Francois Romieu1687b562011-07-19 17:21:29 +0200505#define RX_CONFIG_ACCEPT_MASK 0x3f
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 /* TxConfigBits */
508 TxInterFrameGapShift = 24,
509 TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
510
Francois Romieu5d06a992006-02-23 00:47:58 +0100511 /* Config1 register p.24 */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200512 LEDS1 = (1 << 7),
513 LEDS0 = (1 << 6),
Francois Romieuf162a5d2008-06-01 22:37:49 +0200514 Speed_down = (1 << 4),
515 MEMMAP = (1 << 3),
516 IOMAP = (1 << 2),
517 VPD = (1 << 1),
Francois Romieu5d06a992006-02-23 00:47:58 +0100518 PMEnable = (1 << 0), /* Power Management Enable */
519
Francois Romieu6dccd162007-02-13 23:38:05 +0100520 /* Config2 register p. 25 */
françois romieu2ca6cf02011-12-15 08:37:43 +0000521 MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */
Francois Romieu6dccd162007-02-13 23:38:05 +0100522 PCI_Clock_66MHz = 0x01,
523 PCI_Clock_33MHz = 0x00,
524
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100525 /* Config3 register p.25 */
526 MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
527 LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */
Francois Romieud58d46b2011-05-03 16:38:29 +0200528 Jumbo_En0 = (1 << 2), /* 8168 only. Reserved in the 8168b */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200529 Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100530
Francois Romieud58d46b2011-05-03 16:38:29 +0200531 /* Config4 register */
532 Jumbo_En1 = (1 << 1), /* 8168 only. Reserved in the 8168b */
533
Francois Romieu5d06a992006-02-23 00:47:58 +0100534 /* Config5 register p.27 */
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100535 BWF = (1 << 6), /* Accept Broadcast wakeup frame */
536 MWF = (1 << 5), /* Accept Multicast wakeup frame */
537 UWF = (1 << 4), /* Accept Unicast wakeup frame */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200538 Spi_en = (1 << 3),
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100539 LanWake = (1 << 1), /* LanWake enable/disable */
Francois Romieu5d06a992006-02-23 00:47:58 +0100540 PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */
541
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 /* TBICSR p.28 */
543 TBIReset = 0x80000000,
544 TBILoopback = 0x40000000,
545 TBINwEnable = 0x20000000,
546 TBINwRestart = 0x10000000,
547 TBILinkOk = 0x02000000,
548 TBINwComplete = 0x01000000,
549
550 /* CPlusCmd p.31 */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200551 EnableBist = (1 << 15), // 8168 8101
552 Mac_dbgo_oe = (1 << 14), // 8168 8101
553 Normal_mode = (1 << 13), // unused
554 Force_half_dup = (1 << 12), // 8168 8101
555 Force_rxflow_en = (1 << 11), // 8168 8101
556 Force_txflow_en = (1 << 10), // 8168 8101
557 Cxpl_dbg_sel = (1 << 9), // 8168 8101
558 ASF = (1 << 8), // 8168 8101
559 PktCntrDisable = (1 << 7), // 8168 8101
560 Mac_dbgo_sel = 0x001c, // 8168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 RxVlan = (1 << 6),
562 RxChkSum = (1 << 5),
563 PCIDAC = (1 << 4),
564 PCIMulRW = (1 << 3),
Francois Romieu0e485152007-02-20 00:00:26 +0100565 INTT_0 = 0x0000, // 8168
566 INTT_1 = 0x0001, // 8168
567 INTT_2 = 0x0002, // 8168
568 INTT_3 = 0x0003, // 8168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
570 /* rtl8169_PHYstatus */
Francois Romieu07d3f512007-02-21 22:40:46 +0100571 TBI_Enable = 0x80,
572 TxFlowCtrl = 0x40,
573 RxFlowCtrl = 0x20,
574 _1000bpsF = 0x10,
575 _100bps = 0x08,
576 _10bps = 0x04,
577 LinkStatus = 0x02,
578 FullDup = 0x01,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 /* _TBICSRBit */
Francois Romieu07d3f512007-02-21 22:40:46 +0100581 TBILinkOK = 0x02000000,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +0200582
583 /* DumpCounterCommand */
Francois Romieu07d3f512007-02-21 22:40:46 +0100584 CounterDump = 0x8,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585};
586
Francois Romieu2b7b4312011-04-18 22:53:24 -0700587enum rtl_desc_bit {
588 /* First doubleword. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 DescOwn = (1 << 31), /* Descriptor is owned by NIC */
590 RingEnd = (1 << 30), /* End of descriptor ring */
591 FirstFrag = (1 << 29), /* First segment of a packet */
592 LastFrag = (1 << 28), /* Final segment of a packet */
Francois Romieu2b7b4312011-04-18 22:53:24 -0700593};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594
Francois Romieu2b7b4312011-04-18 22:53:24 -0700595/* Generic case. */
596enum rtl_tx_desc_bit {
597 /* First doubleword. */
598 TD_LSO = (1 << 27), /* Large Send Offload */
599#define TD_MSS_MAX 0x07ffu /* MSS value */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
Francois Romieu2b7b4312011-04-18 22:53:24 -0700601 /* Second doubleword. */
602 TxVlanTag = (1 << 17), /* Add VLAN tag */
603};
604
605/* 8169, 8168b and 810x except 8102e. */
606enum rtl_tx_desc_bit_0 {
607 /* First doubleword. */
608#define TD0_MSS_SHIFT 16 /* MSS position (11 bits) */
609 TD0_TCP_CS = (1 << 16), /* Calculate TCP/IP checksum */
610 TD0_UDP_CS = (1 << 17), /* Calculate UDP/IP checksum */
611 TD0_IP_CS = (1 << 18), /* Calculate IP checksum */
612};
613
614/* 8102e, 8168c and beyond. */
615enum rtl_tx_desc_bit_1 {
616 /* Second doubleword. */
617#define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */
618 TD1_IP_CS = (1 << 29), /* Calculate IP checksum */
619 TD1_TCP_CS = (1 << 30), /* Calculate TCP/IP checksum */
620 TD1_UDP_CS = (1 << 31), /* Calculate UDP/IP checksum */
621};
622
623static const struct rtl_tx_desc_info {
624 struct {
625 u32 udp;
626 u32 tcp;
627 } checksum;
628 u16 mss_shift;
629 u16 opts_offset;
630} tx_desc_info [] = {
631 [RTL_TD_0] = {
632 .checksum = {
633 .udp = TD0_IP_CS | TD0_UDP_CS,
634 .tcp = TD0_IP_CS | TD0_TCP_CS
635 },
636 .mss_shift = TD0_MSS_SHIFT,
637 .opts_offset = 0
638 },
639 [RTL_TD_1] = {
640 .checksum = {
641 .udp = TD1_IP_CS | TD1_UDP_CS,
642 .tcp = TD1_IP_CS | TD1_TCP_CS
643 },
644 .mss_shift = TD1_MSS_SHIFT,
645 .opts_offset = 1
646 }
647};
648
649enum rtl_rx_desc_bit {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 /* Rx private */
651 PID1 = (1 << 18), /* Protocol ID bit 1/2 */
652 PID0 = (1 << 17), /* Protocol ID bit 2/2 */
653
654#define RxProtoUDP (PID1)
655#define RxProtoTCP (PID0)
656#define RxProtoIP (PID1 | PID0)
657#define RxProtoMask RxProtoIP
658
659 IPFail = (1 << 16), /* IP checksum failed */
660 UDPFail = (1 << 15), /* UDP/IP checksum failed */
661 TCPFail = (1 << 14), /* TCP/IP checksum failed */
662 RxVlanTag = (1 << 16), /* VLAN tag available */
663};
664
665#define RsvdMask 0x3fffc000
666
667struct TxDesc {
Rolf Eike Beer6cccd6e2007-05-21 22:11:04 +0200668 __le32 opts1;
669 __le32 opts2;
670 __le64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671};
672
673struct RxDesc {
Rolf Eike Beer6cccd6e2007-05-21 22:11:04 +0200674 __le32 opts1;
675 __le32 opts2;
676 __le64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677};
678
679struct ring_info {
680 struct sk_buff *skb;
681 u32 len;
682 u8 __pad[sizeof(void *) - sizeof(u32)];
683};
684
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200685enum features {
Francois Romieuccdffb92008-07-26 14:26:06 +0200686 RTL_FEATURE_WOL = (1 << 0),
687 RTL_FEATURE_MSI = (1 << 1),
688 RTL_FEATURE_GMII = (1 << 2),
hayeswange0c07552012-10-23 20:24:03 +0000689 RTL_FEATURE_FW_LOADED = (1 << 3),
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200690};
691
Ivan Vecera355423d2009-02-06 21:49:57 -0800692struct rtl8169_counters {
693 __le64 tx_packets;
694 __le64 rx_packets;
695 __le64 tx_errors;
696 __le32 rx_errors;
697 __le16 rx_missed;
698 __le16 align_errors;
699 __le32 tx_one_collision;
700 __le32 tx_multi_collision;
701 __le64 rx_unicast;
702 __le64 rx_broadcast;
703 __le32 rx_multicast;
704 __le16 tx_aborted;
705 __le16 tx_underun;
706};
707
Francois Romieuda78dbf2012-01-26 14:18:23 +0100708enum rtl_flag {
Francois Romieu6c4a70c2012-01-31 10:56:44 +0100709 RTL_FLAG_TASK_ENABLED,
Francois Romieuda78dbf2012-01-26 14:18:23 +0100710 RTL_FLAG_TASK_SLOW_PENDING,
711 RTL_FLAG_TASK_RESET_PENDING,
712 RTL_FLAG_TASK_PHY_PENDING,
713 RTL_FLAG_MAX
714};
715
Junchang Wang8027aa22012-03-04 23:30:32 +0100716struct rtl8169_stats {
717 u64 packets;
718 u64 bytes;
719 struct u64_stats_sync syncp;
720};
721
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722struct rtl8169_private {
723 void __iomem *mmio_addr; /* memory map physical address */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200724 struct pci_dev *pci_dev;
David Howellsc4028952006-11-22 14:57:56 +0000725 struct net_device *dev;
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700726 struct napi_struct napi;
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200727 u32 msg_enable;
Francois Romieu2b7b4312011-04-18 22:53:24 -0700728 u16 txd_version;
729 u16 mac_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
731 u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
732 u32 dirty_rx;
733 u32 dirty_tx;
Junchang Wang8027aa22012-03-04 23:30:32 +0100734 struct rtl8169_stats rx_stats;
735 struct rtl8169_stats tx_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */
737 struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */
738 dma_addr_t TxPhyAddr;
739 dma_addr_t RxPhyAddr;
Eric Dumazet6f0333b2010-10-11 11:17:47 +0000740 void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 struct timer_list timer;
743 u16 cp_cmd;
Francois Romieuda78dbf2012-01-26 14:18:23 +0100744
745 u16 event_slow;
françois romieuc0e45c12011-01-03 15:08:04 +0000746
747 struct mdio_ops {
Francois Romieu24192212012-07-06 20:19:42 +0200748 void (*write)(struct rtl8169_private *, int, int);
749 int (*read)(struct rtl8169_private *, int);
françois romieuc0e45c12011-01-03 15:08:04 +0000750 } mdio_ops;
751
françois romieu065c27c2011-01-03 15:08:12 +0000752 struct pll_power_ops {
753 void (*down)(struct rtl8169_private *);
754 void (*up)(struct rtl8169_private *);
755 } pll_power_ops;
756
Francois Romieud58d46b2011-05-03 16:38:29 +0200757 struct jumbo_ops {
758 void (*enable)(struct rtl8169_private *);
759 void (*disable)(struct rtl8169_private *);
760 } jumbo_ops;
761
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800762 struct csi_ops {
Francois Romieu52989f02012-07-06 13:37:00 +0200763 void (*write)(struct rtl8169_private *, int, int);
764 u32 (*read)(struct rtl8169_private *, int);
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800765 } csi_ops;
766
Oliver Neukum54405cd2011-01-06 21:55:13 +0100767 int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv);
Francois Romieuccdffb92008-07-26 14:26:06 +0200768 int (*get_settings)(struct net_device *, struct ethtool_cmd *);
françois romieu4da19632011-01-03 15:07:55 +0000769 void (*phy_reset_enable)(struct rtl8169_private *tp);
Francois Romieu07ce4062007-02-23 23:36:39 +0100770 void (*hw_start)(struct net_device *);
françois romieu4da19632011-01-03 15:07:55 +0000771 unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 unsigned int (*link_ok)(void __iomem *);
Francois Romieu8b4ab282008-11-19 22:05:25 -0800773 int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
Francois Romieu4422bcd2012-01-26 11:23:32 +0100774
775 struct {
Francois Romieuda78dbf2012-01-26 14:18:23 +0100776 DECLARE_BITMAP(flags, RTL_FLAG_MAX);
777 struct mutex mutex;
Francois Romieu4422bcd2012-01-26 11:23:32 +0100778 struct work_struct work;
779 } wk;
780
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200781 unsigned features;
Francois Romieuccdffb92008-07-26 14:26:06 +0200782
783 struct mii_if_info mii;
Ivan Vecera355423d2009-02-06 21:49:57 -0800784 struct rtl8169_counters counters;
Rafael J. Wysockie1759442010-03-14 14:33:51 +0000785 u32 saved_wolopts;
David S. Miller8decf862011-09-22 03:23:13 -0400786 u32 opts1_mask;
françois romieuf1e02ed2011-01-13 13:07:53 +0000787
Francois Romieub6ffd972011-06-17 17:00:05 +0200788 struct rtl_fw {
789 const struct firmware *fw;
Francois Romieu1c361ef2011-06-17 17:16:24 +0200790
791#define RTL_VER_SIZE 32
792
793 char version[RTL_VER_SIZE];
794
795 struct rtl_fw_phy_action {
796 __le32 *code;
797 size_t size;
798 } phy_action;
Francois Romieub6ffd972011-06-17 17:00:05 +0200799 } *rtl_fw;
Phil Carmody497888c2011-07-14 15:07:13 +0300800#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN)
Hayes Wangc5583862012-07-02 17:23:22 +0800801
802 u32 ocp_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803};
804
Ralf Baechle979b6c12005-06-13 14:30:40 -0700805MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807module_param(use_dac, int, 0);
David S. Miller4300e8c2010-03-26 10:23:30 -0700808MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200809module_param_named(debug, debug.msg_enable, int, 0);
810MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811MODULE_LICENSE("GPL");
812MODULE_VERSION(RTL8169_VERSION);
françois romieubca03d52011-01-03 15:07:31 +0000813MODULE_FIRMWARE(FIRMWARE_8168D_1);
814MODULE_FIRMWARE(FIRMWARE_8168D_2);
hayeswang01dc7fe2011-03-21 01:50:28 +0000815MODULE_FIRMWARE(FIRMWARE_8168E_1);
816MODULE_FIRMWARE(FIRMWARE_8168E_2);
David S. Miller8decf862011-09-22 03:23:13 -0400817MODULE_FIRMWARE(FIRMWARE_8168E_3);
Hayes Wang5a5e4442011-02-22 17:26:21 +0800818MODULE_FIRMWARE(FIRMWARE_8105E_1);
Hayes Wangc2218922011-09-06 16:55:18 +0800819MODULE_FIRMWARE(FIRMWARE_8168F_1);
820MODULE_FIRMWARE(FIRMWARE_8168F_2);
Hayes Wang7e18dca2012-03-30 14:33:02 +0800821MODULE_FIRMWARE(FIRMWARE_8402_1);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800822MODULE_FIRMWARE(FIRMWARE_8411_1);
Hayes Wang5598bfe2012-07-02 17:23:21 +0800823MODULE_FIRMWARE(FIRMWARE_8106E_1);
Hayes Wangc5583862012-07-02 17:23:22 +0800824MODULE_FIRMWARE(FIRMWARE_8168G_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825
Francois Romieuda78dbf2012-01-26 14:18:23 +0100826static void rtl_lock_work(struct rtl8169_private *tp)
827{
828 mutex_lock(&tp->wk.mutex);
829}
830
831static void rtl_unlock_work(struct rtl8169_private *tp)
832{
833 mutex_unlock(&tp->wk.mutex);
834}
835
Francois Romieud58d46b2011-05-03 16:38:29 +0200836static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
837{
Jiang Liu7d7903b2012-07-24 17:20:16 +0800838 pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL,
839 PCI_EXP_DEVCTL_READRQ, force);
Francois Romieud58d46b2011-05-03 16:38:29 +0200840}
841
Francois Romieuffc46952012-07-06 14:19:23 +0200842struct rtl_cond {
843 bool (*check)(struct rtl8169_private *);
844 const char *msg;
845};
846
847static void rtl_udelay(unsigned int d)
848{
849 udelay(d);
850}
851
852static bool rtl_loop_wait(struct rtl8169_private *tp, const struct rtl_cond *c,
853 void (*delay)(unsigned int), unsigned int d, int n,
854 bool high)
855{
856 int i;
857
858 for (i = 0; i < n; i++) {
859 delay(d);
860 if (c->check(tp) == high)
861 return true;
862 }
Francois Romieu82e316e2012-07-11 23:39:51 +0200863 netif_err(tp, drv, tp->dev, "%s == %d (loop: %d, delay: %d).\n",
864 c->msg, !high, n, d);
Francois Romieuffc46952012-07-06 14:19:23 +0200865 return false;
866}
867
868static bool rtl_udelay_loop_wait_high(struct rtl8169_private *tp,
869 const struct rtl_cond *c,
870 unsigned int d, int n)
871{
872 return rtl_loop_wait(tp, c, rtl_udelay, d, n, true);
873}
874
875static bool rtl_udelay_loop_wait_low(struct rtl8169_private *tp,
876 const struct rtl_cond *c,
877 unsigned int d, int n)
878{
879 return rtl_loop_wait(tp, c, rtl_udelay, d, n, false);
880}
881
882static bool rtl_msleep_loop_wait_high(struct rtl8169_private *tp,
883 const struct rtl_cond *c,
884 unsigned int d, int n)
885{
886 return rtl_loop_wait(tp, c, msleep, d, n, true);
887}
888
889static bool rtl_msleep_loop_wait_low(struct rtl8169_private *tp,
890 const struct rtl_cond *c,
891 unsigned int d, int n)
892{
893 return rtl_loop_wait(tp, c, msleep, d, n, false);
894}
895
896#define DECLARE_RTL_COND(name) \
897static bool name ## _check(struct rtl8169_private *); \
898 \
899static const struct rtl_cond name = { \
900 .check = name ## _check, \
901 .msg = #name \
902}; \
903 \
904static bool name ## _check(struct rtl8169_private *tp)
905
906DECLARE_RTL_COND(rtl_ocpar_cond)
907{
908 void __iomem *ioaddr = tp->mmio_addr;
909
910 return RTL_R32(OCPAR) & OCPAR_FLAG;
911}
912
françois romieub646d902011-01-03 15:08:21 +0000913static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
914{
915 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000916
917 RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200918
919 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ?
920 RTL_R32(OCPDR) : ~0;
françois romieub646d902011-01-03 15:08:21 +0000921}
922
923static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data)
924{
925 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000926
927 RTL_W32(OCPDR, data);
928 RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200929
930 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20);
931}
932
933DECLARE_RTL_COND(rtl_eriar_cond)
934{
935 void __iomem *ioaddr = tp->mmio_addr;
936
937 return RTL_R32(ERIAR) & ERIAR_FLAG;
françois romieub646d902011-01-03 15:08:21 +0000938}
939
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800940static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd)
françois romieub646d902011-01-03 15:08:21 +0000941{
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800942 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000943
944 RTL_W8(ERIDR, cmd);
945 RTL_W32(ERIAR, 0x800010e8);
946 msleep(2);
Francois Romieuffc46952012-07-06 14:19:23 +0200947
948 if (!rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 5))
949 return;
françois romieub646d902011-01-03 15:08:21 +0000950
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800951 ocp_write(tp, 0x1, 0x30, 0x00000001);
françois romieub646d902011-01-03 15:08:21 +0000952}
953
954#define OOB_CMD_RESET 0x00
955#define OOB_CMD_DRIVER_START 0x05
956#define OOB_CMD_DRIVER_STOP 0x06
957
Francois Romieucecb5fd2011-04-01 10:21:07 +0200958static u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp)
959{
960 return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10;
961}
962
Francois Romieuffc46952012-07-06 14:19:23 +0200963DECLARE_RTL_COND(rtl_ocp_read_cond)
françois romieub646d902011-01-03 15:08:21 +0000964{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200965 u16 reg;
françois romieub646d902011-01-03 15:08:21 +0000966
Francois Romieucecb5fd2011-04-01 10:21:07 +0200967 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000968
Francois Romieuffc46952012-07-06 14:19:23 +0200969 return ocp_read(tp, 0x0f, reg) & 0x00000800;
970}
971
972static void rtl8168_driver_start(struct rtl8169_private *tp)
973{
974 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START);
975
976 rtl_msleep_loop_wait_high(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000977}
978
979static void rtl8168_driver_stop(struct rtl8169_private *tp)
980{
françois romieub646d902011-01-03 15:08:21 +0000981 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP);
982
Francois Romieuffc46952012-07-06 14:19:23 +0200983 rtl_msleep_loop_wait_low(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000984}
985
hayeswang4804b3b2011-03-21 01:50:29 +0000986static int r8168dp_check_dash(struct rtl8169_private *tp)
987{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200988 u16 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000989
Francois Romieucecb5fd2011-04-01 10:21:07 +0200990 return (ocp_read(tp, 0x0f, reg) & 0x00008000) ? 1 : 0;
hayeswang4804b3b2011-03-21 01:50:29 +0000991}
françois romieub646d902011-01-03 15:08:21 +0000992
Hayes Wangc5583862012-07-02 17:23:22 +0800993static bool rtl_ocp_reg_failure(struct rtl8169_private *tp, u32 reg)
994{
995 if (reg & 0xffff0001) {
996 netif_err(tp, drv, tp->dev, "Invalid ocp reg %x!\n", reg);
997 return true;
998 }
999 return false;
1000}
1001
1002DECLARE_RTL_COND(rtl_ocp_gphy_cond)
1003{
1004 void __iomem *ioaddr = tp->mmio_addr;
1005
1006 return RTL_R32(GPHY_OCP) & OCPAR_FLAG;
1007}
1008
1009static void r8168_phy_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1010{
1011 void __iomem *ioaddr = tp->mmio_addr;
1012
1013 if (rtl_ocp_reg_failure(tp, reg))
1014 return;
1015
1016 RTL_W32(GPHY_OCP, OCPAR_FLAG | (reg << 15) | data);
1017
1018 rtl_udelay_loop_wait_low(tp, &rtl_ocp_gphy_cond, 25, 10);
1019}
1020
1021static u16 r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)
1022{
1023 void __iomem *ioaddr = tp->mmio_addr;
1024
1025 if (rtl_ocp_reg_failure(tp, reg))
1026 return 0;
1027
1028 RTL_W32(GPHY_OCP, reg << 15);
1029
1030 return rtl_udelay_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ?
1031 (RTL_R32(GPHY_OCP) & 0xffff) : ~0;
1032}
1033
1034static void rtl_w1w0_phy_ocp(struct rtl8169_private *tp, int reg, int p, int m)
1035{
1036 int val;
1037
1038 val = r8168_phy_ocp_read(tp, reg);
1039 r8168_phy_ocp_write(tp, reg, (val | p) & ~m);
1040}
1041
Hayes Wangc5583862012-07-02 17:23:22 +08001042static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1043{
1044 void __iomem *ioaddr = tp->mmio_addr;
1045
1046 if (rtl_ocp_reg_failure(tp, reg))
1047 return;
1048
1049 RTL_W32(OCPDR, OCPAR_FLAG | (reg << 15) | data);
Hayes Wangc5583862012-07-02 17:23:22 +08001050}
1051
1052static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
1053{
1054 void __iomem *ioaddr = tp->mmio_addr;
1055
1056 if (rtl_ocp_reg_failure(tp, reg))
1057 return 0;
1058
1059 RTL_W32(OCPDR, reg << 15);
1060
Hayes Wang3a83ad12012-07-11 20:31:56 +08001061 return RTL_R32(OCPDR);
Hayes Wangc5583862012-07-02 17:23:22 +08001062}
1063
1064#define OCP_STD_PHY_BASE 0xa400
1065
1066static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value)
1067{
1068 if (reg == 0x1f) {
1069 tp->ocp_base = value ? value << 4 : OCP_STD_PHY_BASE;
1070 return;
1071 }
1072
1073 if (tp->ocp_base != OCP_STD_PHY_BASE)
1074 reg -= 0x10;
1075
1076 r8168_phy_ocp_write(tp, tp->ocp_base + reg * 2, value);
1077}
1078
1079static int r8168g_mdio_read(struct rtl8169_private *tp, int reg)
1080{
1081 if (tp->ocp_base != OCP_STD_PHY_BASE)
1082 reg -= 0x10;
1083
1084 return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2);
1085}
1086
Francois Romieuffc46952012-07-06 14:19:23 +02001087DECLARE_RTL_COND(rtl_phyar_cond)
1088{
1089 void __iomem *ioaddr = tp->mmio_addr;
1090
1091 return RTL_R32(PHYAR) & 0x80000000;
1092}
1093
Francois Romieu24192212012-07-06 20:19:42 +02001094static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095{
Francois Romieu24192212012-07-06 20:19:42 +02001096 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
Francois Romieu24192212012-07-06 20:19:42 +02001098 RTL_W32(PHYAR, 0x80000000 | (reg & 0x1f) << 16 | (value & 0xffff));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
Francois Romieuffc46952012-07-06 14:19:23 +02001100 rtl_udelay_loop_wait_low(tp, &rtl_phyar_cond, 25, 20);
Timo Teräs024a07b2010-06-06 15:38:47 -07001101 /*
Timo Teräs81a95f02010-06-09 17:31:48 -07001102 * According to hardware specs a 20us delay is required after write
1103 * complete indication, but before sending next command.
Timo Teräs024a07b2010-06-06 15:38:47 -07001104 */
Timo Teräs81a95f02010-06-09 17:31:48 -07001105 udelay(20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106}
1107
Francois Romieu24192212012-07-06 20:19:42 +02001108static int r8169_mdio_read(struct rtl8169_private *tp, int reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109{
Francois Romieu24192212012-07-06 20:19:42 +02001110 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieuffc46952012-07-06 14:19:23 +02001111 int value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
Francois Romieu24192212012-07-06 20:19:42 +02001113 RTL_W32(PHYAR, 0x0 | (reg & 0x1f) << 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114
Francois Romieuffc46952012-07-06 14:19:23 +02001115 value = rtl_udelay_loop_wait_high(tp, &rtl_phyar_cond, 25, 20) ?
1116 RTL_R32(PHYAR) & 0xffff : ~0;
1117
Timo Teräs81a95f02010-06-09 17:31:48 -07001118 /*
1119 * According to hardware specs a 20us delay is required after read
1120 * complete indication, but before sending next command.
1121 */
1122 udelay(20);
1123
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 return value;
1125}
1126
Francois Romieu24192212012-07-06 20:19:42 +02001127static void r8168dp_1_mdio_access(struct rtl8169_private *tp, int reg, u32 data)
françois romieuc0e45c12011-01-03 15:08:04 +00001128{
Francois Romieu24192212012-07-06 20:19:42 +02001129 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001130
Francois Romieu24192212012-07-06 20:19:42 +02001131 RTL_W32(OCPDR, data | ((reg & OCPDR_REG_MASK) << OCPDR_GPHY_REG_SHIFT));
françois romieuc0e45c12011-01-03 15:08:04 +00001132 RTL_W32(OCPAR, OCPAR_GPHY_WRITE_CMD);
1133 RTL_W32(EPHY_RXER_NUM, 0);
1134
Francois Romieuffc46952012-07-06 14:19:23 +02001135 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 1000, 100);
françois romieuc0e45c12011-01-03 15:08:04 +00001136}
1137
Francois Romieu24192212012-07-06 20:19:42 +02001138static void r8168dp_1_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieuc0e45c12011-01-03 15:08:04 +00001139{
Francois Romieu24192212012-07-06 20:19:42 +02001140 r8168dp_1_mdio_access(tp, reg,
1141 OCPDR_WRITE_CMD | (value & OCPDR_DATA_MASK));
françois romieuc0e45c12011-01-03 15:08:04 +00001142}
1143
Francois Romieu24192212012-07-06 20:19:42 +02001144static int r8168dp_1_mdio_read(struct rtl8169_private *tp, int reg)
françois romieuc0e45c12011-01-03 15:08:04 +00001145{
Francois Romieu24192212012-07-06 20:19:42 +02001146 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001147
Francois Romieu24192212012-07-06 20:19:42 +02001148 r8168dp_1_mdio_access(tp, reg, OCPDR_READ_CMD);
françois romieuc0e45c12011-01-03 15:08:04 +00001149
1150 mdelay(1);
1151 RTL_W32(OCPAR, OCPAR_GPHY_READ_CMD);
1152 RTL_W32(EPHY_RXER_NUM, 0);
1153
Francois Romieuffc46952012-07-06 14:19:23 +02001154 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 1000, 100) ?
1155 RTL_R32(OCPDR) & OCPDR_DATA_MASK : ~0;
françois romieuc0e45c12011-01-03 15:08:04 +00001156}
1157
françois romieue6de30d2011-01-03 15:08:37 +00001158#define R8168DP_1_MDIO_ACCESS_BIT 0x00020000
1159
1160static void r8168dp_2_mdio_start(void __iomem *ioaddr)
1161{
1162 RTL_W32(0xd0, RTL_R32(0xd0) & ~R8168DP_1_MDIO_ACCESS_BIT);
1163}
1164
1165static void r8168dp_2_mdio_stop(void __iomem *ioaddr)
1166{
1167 RTL_W32(0xd0, RTL_R32(0xd0) | R8168DP_1_MDIO_ACCESS_BIT);
1168}
1169
Francois Romieu24192212012-07-06 20:19:42 +02001170static void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieue6de30d2011-01-03 15:08:37 +00001171{
Francois Romieu24192212012-07-06 20:19:42 +02001172 void __iomem *ioaddr = tp->mmio_addr;
1173
françois romieue6de30d2011-01-03 15:08:37 +00001174 r8168dp_2_mdio_start(ioaddr);
1175
Francois Romieu24192212012-07-06 20:19:42 +02001176 r8169_mdio_write(tp, reg, value);
françois romieue6de30d2011-01-03 15:08:37 +00001177
1178 r8168dp_2_mdio_stop(ioaddr);
1179}
1180
Francois Romieu24192212012-07-06 20:19:42 +02001181static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)
françois romieue6de30d2011-01-03 15:08:37 +00001182{
Francois Romieu24192212012-07-06 20:19:42 +02001183 void __iomem *ioaddr = tp->mmio_addr;
françois romieue6de30d2011-01-03 15:08:37 +00001184 int value;
1185
1186 r8168dp_2_mdio_start(ioaddr);
1187
Francois Romieu24192212012-07-06 20:19:42 +02001188 value = r8169_mdio_read(tp, reg);
françois romieue6de30d2011-01-03 15:08:37 +00001189
1190 r8168dp_2_mdio_stop(ioaddr);
1191
1192 return value;
1193}
1194
françois romieu4da19632011-01-03 15:07:55 +00001195static void rtl_writephy(struct rtl8169_private *tp, int location, u32 val)
Francois Romieudacf8152008-08-02 20:44:13 +02001196{
Francois Romieu24192212012-07-06 20:19:42 +02001197 tp->mdio_ops.write(tp, location, val);
Francois Romieudacf8152008-08-02 20:44:13 +02001198}
1199
françois romieu4da19632011-01-03 15:07:55 +00001200static int rtl_readphy(struct rtl8169_private *tp, int location)
1201{
Francois Romieu24192212012-07-06 20:19:42 +02001202 return tp->mdio_ops.read(tp, location);
françois romieu4da19632011-01-03 15:07:55 +00001203}
1204
1205static void rtl_patchphy(struct rtl8169_private *tp, int reg_addr, int value)
1206{
1207 rtl_writephy(tp, reg_addr, rtl_readphy(tp, reg_addr) | value);
1208}
1209
1210static void rtl_w1w0_phy(struct rtl8169_private *tp, int reg_addr, int p, int m)
françois romieudaf9df62009-10-07 12:44:20 +00001211{
1212 int val;
1213
françois romieu4da19632011-01-03 15:07:55 +00001214 val = rtl_readphy(tp, reg_addr);
1215 rtl_writephy(tp, reg_addr, (val | p) & ~m);
françois romieudaf9df62009-10-07 12:44:20 +00001216}
1217
Francois Romieuccdffb92008-07-26 14:26:06 +02001218static void rtl_mdio_write(struct net_device *dev, int phy_id, int location,
1219 int val)
1220{
1221 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001222
françois romieu4da19632011-01-03 15:07:55 +00001223 rtl_writephy(tp, location, val);
Francois Romieuccdffb92008-07-26 14:26:06 +02001224}
1225
1226static int rtl_mdio_read(struct net_device *dev, int phy_id, int location)
1227{
1228 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001229
françois romieu4da19632011-01-03 15:07:55 +00001230 return rtl_readphy(tp, location);
Francois Romieuccdffb92008-07-26 14:26:06 +02001231}
1232
Francois Romieuffc46952012-07-06 14:19:23 +02001233DECLARE_RTL_COND(rtl_ephyar_cond)
1234{
1235 void __iomem *ioaddr = tp->mmio_addr;
1236
1237 return RTL_R32(EPHYAR) & EPHYAR_FLAG;
1238}
1239
Francois Romieufdf6fc02012-07-06 22:40:38 +02001240static void rtl_ephy_write(struct rtl8169_private *tp, int reg_addr, int value)
Francois Romieudacf8152008-08-02 20:44:13 +02001241{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001242 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001243
1244 RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) |
1245 (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1246
Francois Romieuffc46952012-07-06 14:19:23 +02001247 rtl_udelay_loop_wait_low(tp, &rtl_ephyar_cond, 10, 100);
1248
1249 udelay(10);
Francois Romieudacf8152008-08-02 20:44:13 +02001250}
1251
Francois Romieufdf6fc02012-07-06 22:40:38 +02001252static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr)
Francois Romieudacf8152008-08-02 20:44:13 +02001253{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001254 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001255
1256 RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1257
Francois Romieuffc46952012-07-06 14:19:23 +02001258 return rtl_udelay_loop_wait_high(tp, &rtl_ephyar_cond, 10, 100) ?
1259 RTL_R32(EPHYAR) & EPHYAR_DATA_MASK : ~0;
Francois Romieudacf8152008-08-02 20:44:13 +02001260}
1261
Francois Romieufdf6fc02012-07-06 22:40:38 +02001262static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
1263 u32 val, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001264{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001265 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001266
1267 BUG_ON((addr & 3) || (mask == 0));
1268 RTL_W32(ERIDR, val);
1269 RTL_W32(ERIAR, ERIAR_WRITE_CMD | type | mask | addr);
1270
Francois Romieuffc46952012-07-06 14:19:23 +02001271 rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 100);
Hayes Wang133ac402011-07-06 15:58:05 +08001272}
1273
Francois Romieufdf6fc02012-07-06 22:40:38 +02001274static u32 rtl_eri_read(struct rtl8169_private *tp, int addr, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001275{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001276 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001277
1278 RTL_W32(ERIAR, ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr);
1279
Francois Romieuffc46952012-07-06 14:19:23 +02001280 return rtl_udelay_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ?
1281 RTL_R32(ERIDR) : ~0;
Hayes Wang133ac402011-07-06 15:58:05 +08001282}
1283
Francois Romieufdf6fc02012-07-06 22:40:38 +02001284static void rtl_w1w0_eri(struct rtl8169_private *tp, int addr, u32 mask, u32 p,
1285 u32 m, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001286{
1287 u32 val;
1288
Francois Romieufdf6fc02012-07-06 22:40:38 +02001289 val = rtl_eri_read(tp, addr, type);
1290 rtl_eri_write(tp, addr, mask, (val & ~m) | p, type);
Hayes Wang133ac402011-07-06 15:58:05 +08001291}
1292
françois romieuc28aa382011-08-02 03:53:43 +00001293struct exgmac_reg {
1294 u16 addr;
1295 u16 mask;
1296 u32 val;
1297};
1298
Francois Romieufdf6fc02012-07-06 22:40:38 +02001299static void rtl_write_exgmac_batch(struct rtl8169_private *tp,
françois romieuc28aa382011-08-02 03:53:43 +00001300 const struct exgmac_reg *r, int len)
1301{
1302 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001303 rtl_eri_write(tp, r->addr, r->mask, r->val, ERIAR_EXGMAC);
françois romieuc28aa382011-08-02 03:53:43 +00001304 r++;
1305 }
1306}
1307
Francois Romieuffc46952012-07-06 14:19:23 +02001308DECLARE_RTL_COND(rtl_efusear_cond)
1309{
1310 void __iomem *ioaddr = tp->mmio_addr;
1311
1312 return RTL_R32(EFUSEAR) & EFUSEAR_FLAG;
1313}
1314
Francois Romieufdf6fc02012-07-06 22:40:38 +02001315static u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr)
françois romieudaf9df62009-10-07 12:44:20 +00001316{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001317 void __iomem *ioaddr = tp->mmio_addr;
françois romieudaf9df62009-10-07 12:44:20 +00001318
1319 RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT);
1320
Francois Romieuffc46952012-07-06 14:19:23 +02001321 return rtl_udelay_loop_wait_high(tp, &rtl_efusear_cond, 100, 300) ?
1322 RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK : ~0;
françois romieudaf9df62009-10-07 12:44:20 +00001323}
1324
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001325static u16 rtl_get_events(struct rtl8169_private *tp)
1326{
1327 void __iomem *ioaddr = tp->mmio_addr;
1328
1329 return RTL_R16(IntrStatus);
1330}
1331
1332static void rtl_ack_events(struct rtl8169_private *tp, u16 bits)
1333{
1334 void __iomem *ioaddr = tp->mmio_addr;
1335
1336 RTL_W16(IntrStatus, bits);
1337 mmiowb();
1338}
1339
1340static void rtl_irq_disable(struct rtl8169_private *tp)
1341{
1342 void __iomem *ioaddr = tp->mmio_addr;
1343
1344 RTL_W16(IntrMask, 0);
1345 mmiowb();
1346}
1347
Francois Romieu3e990ff2012-01-26 12:50:01 +01001348static void rtl_irq_enable(struct rtl8169_private *tp, u16 bits)
1349{
1350 void __iomem *ioaddr = tp->mmio_addr;
1351
1352 RTL_W16(IntrMask, bits);
1353}
1354
Francois Romieuda78dbf2012-01-26 14:18:23 +01001355#define RTL_EVENT_NAPI_RX (RxOK | RxErr)
1356#define RTL_EVENT_NAPI_TX (TxOK | TxErr)
1357#define RTL_EVENT_NAPI (RTL_EVENT_NAPI_RX | RTL_EVENT_NAPI_TX)
1358
1359static void rtl_irq_enable_all(struct rtl8169_private *tp)
1360{
1361 rtl_irq_enable(tp, RTL_EVENT_NAPI | tp->event_slow);
1362}
1363
françois romieu811fd302011-12-04 20:30:45 +00001364static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365{
françois romieu811fd302011-12-04 20:30:45 +00001366 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001368 rtl_irq_disable(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001369 rtl_ack_events(tp, RTL_EVENT_NAPI | tp->event_slow);
françois romieu811fd302011-12-04 20:30:45 +00001370 RTL_R8(ChipCmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371}
1372
françois romieu4da19632011-01-03 15:07:55 +00001373static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374{
françois romieu4da19632011-01-03 15:07:55 +00001375 void __iomem *ioaddr = tp->mmio_addr;
1376
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 return RTL_R32(TBICSR) & TBIReset;
1378}
1379
françois romieu4da19632011-01-03 15:07:55 +00001380static unsigned int rtl8169_xmii_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381{
françois romieu4da19632011-01-03 15:07:55 +00001382 return rtl_readphy(tp, MII_BMCR) & BMCR_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383}
1384
1385static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr)
1386{
1387 return RTL_R32(TBICSR) & TBILinkOk;
1388}
1389
1390static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr)
1391{
1392 return RTL_R8(PHYstatus) & LinkStatus;
1393}
1394
françois romieu4da19632011-01-03 15:07:55 +00001395static void rtl8169_tbi_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396{
françois romieu4da19632011-01-03 15:07:55 +00001397 void __iomem *ioaddr = tp->mmio_addr;
1398
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset);
1400}
1401
françois romieu4da19632011-01-03 15:07:55 +00001402static void rtl8169_xmii_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403{
1404 unsigned int val;
1405
françois romieu4da19632011-01-03 15:07:55 +00001406 val = rtl_readphy(tp, MII_BMCR) | BMCR_RESET;
1407 rtl_writephy(tp, MII_BMCR, val & 0xffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408}
1409
Hayes Wang70090422011-07-06 15:58:06 +08001410static void rtl_link_chg_patch(struct rtl8169_private *tp)
1411{
1412 void __iomem *ioaddr = tp->mmio_addr;
1413 struct net_device *dev = tp->dev;
1414
1415 if (!netif_running(dev))
1416 return;
1417
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08001418 if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
1419 tp->mac_version == RTL_GIGA_MAC_VER_38) {
Hayes Wang70090422011-07-06 15:58:06 +08001420 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001421 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1422 ERIAR_EXGMAC);
1423 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1424 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001425 } else if (RTL_R8(PHYstatus) & _100bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001426 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1427 ERIAR_EXGMAC);
1428 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1429 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001430 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001431 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1432 ERIAR_EXGMAC);
1433 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1434 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001435 }
1436 /* Reset packet filter */
Francois Romieufdf6fc02012-07-06 22:40:38 +02001437 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01,
Hayes Wang70090422011-07-06 15:58:06 +08001438 ERIAR_EXGMAC);
Francois Romieufdf6fc02012-07-06 22:40:38 +02001439 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00,
Hayes Wang70090422011-07-06 15:58:06 +08001440 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001441 } else if (tp->mac_version == RTL_GIGA_MAC_VER_35 ||
1442 tp->mac_version == RTL_GIGA_MAC_VER_36) {
1443 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001444 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1445 ERIAR_EXGMAC);
1446 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1447 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001448 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001449 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1450 ERIAR_EXGMAC);
1451 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1452 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001453 }
Hayes Wang7e18dca2012-03-30 14:33:02 +08001454 } else if (tp->mac_version == RTL_GIGA_MAC_VER_37) {
1455 if (RTL_R8(PHYstatus) & _10bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001456 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02,
1457 ERIAR_EXGMAC);
1458 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060,
1459 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001460 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001461 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000,
1462 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001463 }
Hayes Wang70090422011-07-06 15:58:06 +08001464 }
1465}
1466
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001467static void __rtl8169_check_link_status(struct net_device *dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02001468 struct rtl8169_private *tp,
1469 void __iomem *ioaddr, bool pm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 if (tp->link_ok(ioaddr)) {
Hayes Wang70090422011-07-06 15:58:06 +08001472 rtl_link_chg_patch(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001473 /* This is to cancel a scheduled suspend if there's one. */
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001474 if (pm)
1475 pm_request_resume(&tp->pci_dev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 netif_carrier_on(dev);
Francois Romieu1519e572011-02-03 12:02:36 +01001477 if (net_ratelimit())
1478 netif_info(tp, ifup, dev, "link up\n");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001479 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 netif_carrier_off(dev);
Joe Perchesbf82c182010-02-09 11:49:50 +00001481 netif_info(tp, ifdown, dev, "link down\n");
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001482 if (pm)
hayeswang10953db2011-11-07 20:44:37 +00001483 pm_schedule_suspend(&tp->pci_dev->dev, 5000);
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001484 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485}
1486
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001487static void rtl8169_check_link_status(struct net_device *dev,
1488 struct rtl8169_private *tp,
1489 void __iomem *ioaddr)
1490{
1491 __rtl8169_check_link_status(dev, tp, ioaddr, false);
1492}
1493
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001494#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
1495
1496static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
1497{
1498 void __iomem *ioaddr = tp->mmio_addr;
1499 u8 options;
1500 u32 wolopts = 0;
1501
1502 options = RTL_R8(Config1);
1503 if (!(options & PMEnable))
1504 return 0;
1505
1506 options = RTL_R8(Config3);
1507 if (options & LinkUp)
1508 wolopts |= WAKE_PHY;
1509 if (options & MagicPacket)
1510 wolopts |= WAKE_MAGIC;
1511
1512 options = RTL_R8(Config5);
1513 if (options & UWF)
1514 wolopts |= WAKE_UCAST;
1515 if (options & BWF)
1516 wolopts |= WAKE_BCAST;
1517 if (options & MWF)
1518 wolopts |= WAKE_MCAST;
1519
1520 return wolopts;
1521}
1522
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001523static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1524{
1525 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001526
Francois Romieuda78dbf2012-01-26 14:18:23 +01001527 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001528
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001529 wol->supported = WAKE_ANY;
1530 wol->wolopts = __rtl8169_get_wol(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001531
Francois Romieuda78dbf2012-01-26 14:18:23 +01001532 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001533}
1534
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001535static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001536{
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001537 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu07d3f512007-02-21 22:40:46 +01001538 unsigned int i;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08001539 static const struct {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001540 u32 opt;
1541 u16 reg;
1542 u8 mask;
1543 } cfg[] = {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001544 { WAKE_PHY, Config3, LinkUp },
1545 { WAKE_MAGIC, Config3, MagicPacket },
1546 { WAKE_UCAST, Config5, UWF },
1547 { WAKE_BCAST, Config5, BWF },
1548 { WAKE_MCAST, Config5, MWF },
1549 { WAKE_ANY, Config5, LanWake }
1550 };
Francois Romieu851e6022012-04-17 11:10:11 +02001551 u8 options;
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001552
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001553 RTL_W8(Cfg9346, Cfg9346_Unlock);
1554
1555 for (i = 0; i < ARRAY_SIZE(cfg); i++) {
Francois Romieu851e6022012-04-17 11:10:11 +02001556 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001557 if (wolopts & cfg[i].opt)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001558 options |= cfg[i].mask;
1559 RTL_W8(cfg[i].reg, options);
1560 }
1561
Francois Romieu851e6022012-04-17 11:10:11 +02001562 switch (tp->mac_version) {
1563 case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17:
1564 options = RTL_R8(Config1) & ~PMEnable;
1565 if (wolopts)
1566 options |= PMEnable;
1567 RTL_W8(Config1, options);
1568 break;
1569 default:
Francois Romieud387b422012-04-17 11:12:01 +02001570 options = RTL_R8(Config2) & ~PME_SIGNAL;
1571 if (wolopts)
1572 options |= PME_SIGNAL;
1573 RTL_W8(Config2, options);
Francois Romieu851e6022012-04-17 11:10:11 +02001574 break;
1575 }
1576
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001577 RTL_W8(Cfg9346, Cfg9346_Lock);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001578}
1579
1580static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1581{
1582 struct rtl8169_private *tp = netdev_priv(dev);
1583
Francois Romieuda78dbf2012-01-26 14:18:23 +01001584 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001585
Francois Romieuf23e7fd2007-10-04 22:36:14 +02001586 if (wol->wolopts)
1587 tp->features |= RTL_FEATURE_WOL;
1588 else
1589 tp->features &= ~RTL_FEATURE_WOL;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001590 __rtl8169_set_wol(tp, wol->wolopts);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001591
1592 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001593
françois romieuea809072010-11-08 13:23:58 +00001594 device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts);
1595
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001596 return 0;
1597}
1598
Francois Romieu31bd2042011-04-26 18:58:59 +02001599static const char *rtl_lookup_firmware_name(struct rtl8169_private *tp)
1600{
Francois Romieu85bffe62011-04-27 08:22:39 +02001601 return rtl_chip_infos[tp->mac_version].fw_name;
Francois Romieu31bd2042011-04-26 18:58:59 +02001602}
1603
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604static void rtl8169_get_drvinfo(struct net_device *dev,
1605 struct ethtool_drvinfo *info)
1606{
1607 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieub6ffd972011-06-17 17:00:05 +02001608 struct rtl_fw *rtl_fw = tp->rtl_fw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609
Rick Jones68aad782011-11-07 13:29:27 +00001610 strlcpy(info->driver, MODULENAME, sizeof(info->driver));
1611 strlcpy(info->version, RTL8169_VERSION, sizeof(info->version));
1612 strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
Francois Romieu1c361ef2011-06-17 17:16:24 +02001613 BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version));
Rick Jones8ac72d12011-11-22 14:06:26 +00001614 if (!IS_ERR_OR_NULL(rtl_fw))
1615 strlcpy(info->fw_version, rtl_fw->version,
1616 sizeof(info->fw_version));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617}
1618
1619static int rtl8169_get_regs_len(struct net_device *dev)
1620{
1621 return R8169_REGS_SIZE;
1622}
1623
1624static int rtl8169_set_speed_tbi(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001625 u8 autoneg, u16 speed, u8 duplex, u32 ignored)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626{
1627 struct rtl8169_private *tp = netdev_priv(dev);
1628 void __iomem *ioaddr = tp->mmio_addr;
1629 int ret = 0;
1630 u32 reg;
1631
1632 reg = RTL_R32(TBICSR);
1633 if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) &&
1634 (duplex == DUPLEX_FULL)) {
1635 RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart));
1636 } else if (autoneg == AUTONEG_ENABLE)
1637 RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);
1638 else {
Joe Perchesbf82c182010-02-09 11:49:50 +00001639 netif_warn(tp, link, dev,
1640 "incorrect speed setting refused in TBI mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 ret = -EOPNOTSUPP;
1642 }
1643
1644 return ret;
1645}
1646
1647static int rtl8169_set_speed_xmii(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001648 u8 autoneg, u16 speed, u8 duplex, u32 adv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649{
1650 struct rtl8169_private *tp = netdev_priv(dev);
françois romieu3577aa12009-05-19 10:46:48 +00001651 int giga_ctrl, bmcr;
Oliver Neukum54405cd2011-01-06 21:55:13 +01001652 int rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653
Hayes Wang716b50a2011-02-22 17:26:18 +08001654 rtl_writephy(tp, 0x1f, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655
1656 if (autoneg == AUTONEG_ENABLE) {
françois romieu3577aa12009-05-19 10:46:48 +00001657 int auto_nego;
1658
françois romieu4da19632011-01-03 15:07:55 +00001659 auto_nego = rtl_readphy(tp, MII_ADVERTISE);
Oliver Neukum54405cd2011-01-06 21:55:13 +01001660 auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
1661 ADVERTISE_100HALF | ADVERTISE_100FULL);
1662
1663 if (adv & ADVERTISED_10baseT_Half)
1664 auto_nego |= ADVERTISE_10HALF;
1665 if (adv & ADVERTISED_10baseT_Full)
1666 auto_nego |= ADVERTISE_10FULL;
1667 if (adv & ADVERTISED_100baseT_Half)
1668 auto_nego |= ADVERTISE_100HALF;
1669 if (adv & ADVERTISED_100baseT_Full)
1670 auto_nego |= ADVERTISE_100FULL;
1671
françois romieu3577aa12009-05-19 10:46:48 +00001672 auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
1673
françois romieu4da19632011-01-03 15:07:55 +00001674 giga_ctrl = rtl_readphy(tp, MII_CTRL1000);
françois romieu3577aa12009-05-19 10:46:48 +00001675 giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
1676
1677 /* The 8100e/8101e/8102e do Fast Ethernet only. */
Francois Romieu826e6cb2011-03-11 20:30:24 +01001678 if (tp->mii.supports_gmii) {
Oliver Neukum54405cd2011-01-06 21:55:13 +01001679 if (adv & ADVERTISED_1000baseT_Half)
1680 giga_ctrl |= ADVERTISE_1000HALF;
1681 if (adv & ADVERTISED_1000baseT_Full)
1682 giga_ctrl |= ADVERTISE_1000FULL;
1683 } else if (adv & (ADVERTISED_1000baseT_Half |
1684 ADVERTISED_1000baseT_Full)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00001685 netif_info(tp, link, dev,
1686 "PHY does not support 1000Mbps\n");
Oliver Neukum54405cd2011-01-06 21:55:13 +01001687 goto out;
Francois Romieubcf0bf92006-07-26 23:14:13 +02001688 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689
françois romieu3577aa12009-05-19 10:46:48 +00001690 bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
Francois Romieu623a1592006-05-14 12:42:14 +02001691
françois romieu4da19632011-01-03 15:07:55 +00001692 rtl_writephy(tp, MII_ADVERTISE, auto_nego);
1693 rtl_writephy(tp, MII_CTRL1000, giga_ctrl);
françois romieu3577aa12009-05-19 10:46:48 +00001694 } else {
1695 giga_ctrl = 0;
1696
1697 if (speed == SPEED_10)
1698 bmcr = 0;
1699 else if (speed == SPEED_100)
1700 bmcr = BMCR_SPEED100;
1701 else
Oliver Neukum54405cd2011-01-06 21:55:13 +01001702 goto out;
françois romieu3577aa12009-05-19 10:46:48 +00001703
1704 if (duplex == DUPLEX_FULL)
1705 bmcr |= BMCR_FULLDPLX;
Roger So2584fbc2007-07-31 23:52:42 +02001706 }
1707
françois romieu4da19632011-01-03 15:07:55 +00001708 rtl_writephy(tp, MII_BMCR, bmcr);
françois romieu3577aa12009-05-19 10:46:48 +00001709
Francois Romieucecb5fd2011-04-01 10:21:07 +02001710 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
1711 tp->mac_version == RTL_GIGA_MAC_VER_03) {
françois romieu3577aa12009-05-19 10:46:48 +00001712 if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) {
françois romieu4da19632011-01-03 15:07:55 +00001713 rtl_writephy(tp, 0x17, 0x2138);
1714 rtl_writephy(tp, 0x0e, 0x0260);
françois romieu3577aa12009-05-19 10:46:48 +00001715 } else {
françois romieu4da19632011-01-03 15:07:55 +00001716 rtl_writephy(tp, 0x17, 0x2108);
1717 rtl_writephy(tp, 0x0e, 0x0000);
françois romieu3577aa12009-05-19 10:46:48 +00001718 }
1719 }
1720
Oliver Neukum54405cd2011-01-06 21:55:13 +01001721 rc = 0;
1722out:
1723 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724}
1725
1726static int rtl8169_set_speed(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001727 u8 autoneg, u16 speed, u8 duplex, u32 advertising)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728{
1729 struct rtl8169_private *tp = netdev_priv(dev);
1730 int ret;
1731
Oliver Neukum54405cd2011-01-06 21:55:13 +01001732 ret = tp->set_speed(dev, autoneg, speed, duplex, advertising);
Francois Romieu4876cc12011-03-11 21:07:11 +01001733 if (ret < 0)
1734 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735
Francois Romieu4876cc12011-03-11 21:07:11 +01001736 if (netif_running(dev) && (autoneg == AUTONEG_ENABLE) &&
1737 (advertising & ADVERTISED_1000baseT_Full)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);
Francois Romieu4876cc12011-03-11 21:07:11 +01001739 }
1740out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 return ret;
1742}
1743
1744static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1745{
1746 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 int ret;
1748
Francois Romieu4876cc12011-03-11 21:07:11 +01001749 del_timer_sync(&tp->timer);
1750
Francois Romieuda78dbf2012-01-26 14:18:23 +01001751 rtl_lock_work(tp);
Francois Romieucecb5fd2011-04-01 10:21:07 +02001752 ret = rtl8169_set_speed(dev, cmd->autoneg, ethtool_cmd_speed(cmd),
David Decotigny25db0332011-04-27 18:32:39 +00001753 cmd->duplex, cmd->advertising);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001754 rtl_unlock_work(tp);
Francois Romieu5b0384f2006-08-16 16:00:01 +02001755
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 return ret;
1757}
1758
Michał Mirosławc8f44af2011-11-15 15:29:55 +00001759static netdev_features_t rtl8169_fix_features(struct net_device *dev,
1760 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761{
Francois Romieud58d46b2011-05-03 16:38:29 +02001762 struct rtl8169_private *tp = netdev_priv(dev);
1763
Francois Romieu2b7b4312011-04-18 22:53:24 -07001764 if (dev->mtu > TD_MSS_MAX)
Michał Mirosław350fb322011-04-08 06:35:56 +00001765 features &= ~NETIF_F_ALL_TSO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766
Francois Romieud58d46b2011-05-03 16:38:29 +02001767 if (dev->mtu > JUMBO_1K &&
1768 !rtl_chip_infos[tp->mac_version].jumbo_tx_csum)
1769 features &= ~NETIF_F_IP_CSUM;
1770
Michał Mirosław350fb322011-04-08 06:35:56 +00001771 return features;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772}
1773
Francois Romieuda78dbf2012-01-26 14:18:23 +01001774static void __rtl8169_set_features(struct net_device *dev,
1775 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776{
1777 struct rtl8169_private *tp = netdev_priv(dev);
Ben Greear6bbe0212012-02-10 15:04:33 +00001778 netdev_features_t changed = features ^ dev->features;
Francois Romieuda78dbf2012-01-26 14:18:23 +01001779 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780
Ben Greear6bbe0212012-02-10 15:04:33 +00001781 if (!(changed & (NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)))
1782 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783
Ben Greear6bbe0212012-02-10 15:04:33 +00001784 if (changed & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)) {
1785 if (features & NETIF_F_RXCSUM)
1786 tp->cp_cmd |= RxChkSum;
1787 else
1788 tp->cp_cmd &= ~RxChkSum;
Michał Mirosław350fb322011-04-08 06:35:56 +00001789
Ben Greear6bbe0212012-02-10 15:04:33 +00001790 if (dev->features & NETIF_F_HW_VLAN_RX)
1791 tp->cp_cmd |= RxVlan;
1792 else
1793 tp->cp_cmd &= ~RxVlan;
1794
1795 RTL_W16(CPlusCmd, tp->cp_cmd);
1796 RTL_R16(CPlusCmd);
1797 }
1798 if (changed & NETIF_F_RXALL) {
1799 int tmp = (RTL_R32(RxConfig) & ~(AcceptErr | AcceptRunt));
1800 if (features & NETIF_F_RXALL)
1801 tmp |= (AcceptErr | AcceptRunt);
1802 RTL_W32(RxConfig, tmp);
1803 }
Francois Romieuda78dbf2012-01-26 14:18:23 +01001804}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805
Francois Romieuda78dbf2012-01-26 14:18:23 +01001806static int rtl8169_set_features(struct net_device *dev,
1807 netdev_features_t features)
1808{
1809 struct rtl8169_private *tp = netdev_priv(dev);
1810
1811 rtl_lock_work(tp);
1812 __rtl8169_set_features(dev, features);
1813 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814
1815 return 0;
1816}
1817
Francois Romieuda78dbf2012-01-26 14:18:23 +01001818
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
1820 struct sk_buff *skb)
1821{
Jesse Grosseab6d182010-10-20 13:56:03 +00001822 return (vlan_tx_tag_present(skb)) ?
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
1824}
1825
Francois Romieu7a8fc772011-03-01 17:18:33 +01001826static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827{
1828 u32 opts2 = le32_to_cpu(desc->opts2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829
Francois Romieu7a8fc772011-03-01 17:18:33 +01001830 if (opts2 & RxVlanTag)
1831 __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));
Eric Dumazet2edae082010-09-06 18:46:39 +00001832
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 desc->opts2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834}
1835
Francois Romieuccdffb92008-07-26 14:26:06 +02001836static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837{
1838 struct rtl8169_private *tp = netdev_priv(dev);
1839 void __iomem *ioaddr = tp->mmio_addr;
1840 u32 status;
1841
1842 cmd->supported =
1843 SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE;
1844 cmd->port = PORT_FIBRE;
1845 cmd->transceiver = XCVR_INTERNAL;
1846
1847 status = RTL_R32(TBICSR);
1848 cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0;
1849 cmd->autoneg = !!(status & TBINwEnable);
1850
David Decotigny70739492011-04-27 18:32:40 +00001851 ethtool_cmd_speed_set(cmd, SPEED_1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 cmd->duplex = DUPLEX_FULL; /* Always set */
Francois Romieuccdffb92008-07-26 14:26:06 +02001853
1854 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855}
1856
Francois Romieuccdffb92008-07-26 14:26:06 +02001857static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858{
1859 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860
Francois Romieuccdffb92008-07-26 14:26:06 +02001861 return mii_ethtool_gset(&tp->mii, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862}
1863
1864static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1865{
1866 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001867 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868
Francois Romieuda78dbf2012-01-26 14:18:23 +01001869 rtl_lock_work(tp);
Francois Romieuccdffb92008-07-26 14:26:06 +02001870 rc = tp->get_settings(dev, cmd);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001871 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872
Francois Romieuccdffb92008-07-26 14:26:06 +02001873 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874}
1875
1876static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
1877 void *p)
1878{
Francois Romieu5b0384f2006-08-16 16:00:01 +02001879 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880
Francois Romieu5b0384f2006-08-16 16:00:01 +02001881 if (regs->len > R8169_REGS_SIZE)
1882 regs->len = R8169_REGS_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883
Francois Romieuda78dbf2012-01-26 14:18:23 +01001884 rtl_lock_work(tp);
Francois Romieu5b0384f2006-08-16 16:00:01 +02001885 memcpy_fromio(p, tp->mmio_addr, regs->len);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001886 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887}
1888
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001889static u32 rtl8169_get_msglevel(struct net_device *dev)
1890{
1891 struct rtl8169_private *tp = netdev_priv(dev);
1892
1893 return tp->msg_enable;
1894}
1895
1896static void rtl8169_set_msglevel(struct net_device *dev, u32 value)
1897{
1898 struct rtl8169_private *tp = netdev_priv(dev);
1899
1900 tp->msg_enable = value;
1901}
1902
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001903static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
1904 "tx_packets",
1905 "rx_packets",
1906 "tx_errors",
1907 "rx_errors",
1908 "rx_missed",
1909 "align_errors",
1910 "tx_single_collisions",
1911 "tx_multi_collisions",
1912 "unicast",
1913 "broadcast",
1914 "multicast",
1915 "tx_aborted",
1916 "tx_underrun",
1917};
1918
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001919static int rtl8169_get_sset_count(struct net_device *dev, int sset)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001920{
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001921 switch (sset) {
1922 case ETH_SS_STATS:
1923 return ARRAY_SIZE(rtl8169_gstrings);
1924 default:
1925 return -EOPNOTSUPP;
1926 }
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001927}
1928
Francois Romieuffc46952012-07-06 14:19:23 +02001929DECLARE_RTL_COND(rtl_counters_cond)
1930{
1931 void __iomem *ioaddr = tp->mmio_addr;
1932
1933 return RTL_R32(CounterAddrLow) & CounterDump;
1934}
1935
Ivan Vecera355423d2009-02-06 21:49:57 -08001936static void rtl8169_update_counters(struct net_device *dev)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001937{
1938 struct rtl8169_private *tp = netdev_priv(dev);
1939 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieucecb5fd2011-04-01 10:21:07 +02001940 struct device *d = &tp->pci_dev->dev;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001941 struct rtl8169_counters *counters;
1942 dma_addr_t paddr;
1943 u32 cmd;
1944
Ivan Vecera355423d2009-02-06 21:49:57 -08001945 /*
1946 * Some chips are unable to dump tally counters when the receiver
1947 * is disabled.
1948 */
1949 if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0)
1950 return;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001951
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001952 counters = dma_alloc_coherent(d, sizeof(*counters), &paddr, GFP_KERNEL);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001953 if (!counters)
1954 return;
1955
1956 RTL_W32(CounterAddrHigh, (u64)paddr >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07001957 cmd = (u64)paddr & DMA_BIT_MASK(32);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001958 RTL_W32(CounterAddrLow, cmd);
1959 RTL_W32(CounterAddrLow, cmd | CounterDump);
1960
Francois Romieuffc46952012-07-06 14:19:23 +02001961 if (rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000))
1962 memcpy(&tp->counters, counters, sizeof(*counters));
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001963
1964 RTL_W32(CounterAddrLow, 0);
1965 RTL_W32(CounterAddrHigh, 0);
1966
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001967 dma_free_coherent(d, sizeof(*counters), counters, paddr);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001968}
1969
Ivan Vecera355423d2009-02-06 21:49:57 -08001970static void rtl8169_get_ethtool_stats(struct net_device *dev,
1971 struct ethtool_stats *stats, u64 *data)
1972{
1973 struct rtl8169_private *tp = netdev_priv(dev);
1974
1975 ASSERT_RTNL();
1976
1977 rtl8169_update_counters(dev);
1978
1979 data[0] = le64_to_cpu(tp->counters.tx_packets);
1980 data[1] = le64_to_cpu(tp->counters.rx_packets);
1981 data[2] = le64_to_cpu(tp->counters.tx_errors);
1982 data[3] = le32_to_cpu(tp->counters.rx_errors);
1983 data[4] = le16_to_cpu(tp->counters.rx_missed);
1984 data[5] = le16_to_cpu(tp->counters.align_errors);
1985 data[6] = le32_to_cpu(tp->counters.tx_one_collision);
1986 data[7] = le32_to_cpu(tp->counters.tx_multi_collision);
1987 data[8] = le64_to_cpu(tp->counters.rx_unicast);
1988 data[9] = le64_to_cpu(tp->counters.rx_broadcast);
1989 data[10] = le32_to_cpu(tp->counters.rx_multicast);
1990 data[11] = le16_to_cpu(tp->counters.tx_aborted);
1991 data[12] = le16_to_cpu(tp->counters.tx_underun);
1992}
1993
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001994static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
1995{
1996 switch(stringset) {
1997 case ETH_SS_STATS:
1998 memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings));
1999 break;
2000 }
2001}
2002
Jeff Garzik7282d492006-09-13 14:30:00 -04002003static const struct ethtool_ops rtl8169_ethtool_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 .get_drvinfo = rtl8169_get_drvinfo,
2005 .get_regs_len = rtl8169_get_regs_len,
2006 .get_link = ethtool_op_get_link,
2007 .get_settings = rtl8169_get_settings,
2008 .set_settings = rtl8169_set_settings,
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02002009 .get_msglevel = rtl8169_get_msglevel,
2010 .set_msglevel = rtl8169_set_msglevel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011 .get_regs = rtl8169_get_regs,
Francois Romieu61a4dcc2006-02-23 00:55:25 +01002012 .get_wol = rtl8169_get_wol,
2013 .set_wol = rtl8169_set_wol,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002014 .get_strings = rtl8169_get_strings,
Jeff Garzikb9f2c042007-10-03 18:07:32 -07002015 .get_sset_count = rtl8169_get_sset_count,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002016 .get_ethtool_stats = rtl8169_get_ethtool_stats,
Richard Cochrane1593bb2012-04-03 22:59:35 +00002017 .get_ts_info = ethtool_op_get_ts_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018};
2019
Francois Romieu07d3f512007-02-21 22:40:46 +01002020static void rtl8169_get_mac_version(struct rtl8169_private *tp,
Francois Romieu5d320a22011-05-08 17:47:36 +02002021 struct net_device *dev, u8 default_version)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022{
Francois Romieu5d320a22011-05-08 17:47:36 +02002023 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu0e485152007-02-20 00:00:26 +01002024 /*
2025 * The driver currently handles the 8168Bf and the 8168Be identically
2026 * but they can be identified more specifically through the test below
2027 * if needed:
2028 *
2029 * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
Francois Romieu01272152007-02-20 22:58:51 +01002030 *
2031 * Same thing for the 8101Eb and the 8101Ec:
2032 *
2033 * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
Francois Romieu0e485152007-02-20 00:00:26 +01002034 */
Francois Romieu37441002011-06-17 22:58:54 +02002035 static const struct rtl_mac_info {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 u32 mask;
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002037 u32 val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 int mac_version;
2039 } mac_info[] = {
Hayes Wangc5583862012-07-02 17:23:22 +08002040 /* 8168G family. */
2041 { 0x7cf00000, 0x4c100000, RTL_GIGA_MAC_VER_41 },
2042 { 0x7cf00000, 0x4c000000, RTL_GIGA_MAC_VER_40 },
2043
Hayes Wangc2218922011-09-06 16:55:18 +08002044 /* 8168F family. */
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08002045 { 0x7c800000, 0x48800000, RTL_GIGA_MAC_VER_38 },
Hayes Wangc2218922011-09-06 16:55:18 +08002046 { 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 },
2047 { 0x7cf00000, 0x48000000, RTL_GIGA_MAC_VER_35 },
2048
hayeswang01dc7fe2011-03-21 01:50:28 +00002049 /* 8168E family. */
Hayes Wang70090422011-07-06 15:58:06 +08002050 { 0x7c800000, 0x2c800000, RTL_GIGA_MAC_VER_34 },
hayeswang01dc7fe2011-03-21 01:50:28 +00002051 { 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 },
2052 { 0x7cf00000, 0x2c100000, RTL_GIGA_MAC_VER_32 },
2053 { 0x7c800000, 0x2c000000, RTL_GIGA_MAC_VER_33 },
2054
Francois Romieu5b538df2008-07-20 16:22:45 +02002055 /* 8168D family. */
françois romieudaf9df62009-10-07 12:44:20 +00002056 { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 },
2057 { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 },
françois romieudaf9df62009-10-07 12:44:20 +00002058 { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002059
françois romieue6de30d2011-01-03 15:08:37 +00002060 /* 8168DP family. */
2061 { 0x7cf00000, 0x28800000, RTL_GIGA_MAC_VER_27 },
2062 { 0x7cf00000, 0x28a00000, RTL_GIGA_MAC_VER_28 },
hayeswang4804b3b2011-03-21 01:50:29 +00002063 { 0x7cf00000, 0x28b00000, RTL_GIGA_MAC_VER_31 },
françois romieue6de30d2011-01-03 15:08:37 +00002064
Francois Romieuef808d52008-06-29 13:10:54 +02002065 /* 8168C family. */
Francois Romieu17c99292010-07-11 17:10:09 -07002066 { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 },
Francois Romieuef3386f2008-06-29 12:24:30 +02002067 { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 },
Francois Romieuef808d52008-06-29 13:10:54 +02002068 { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 },
Francois Romieu7f3e3d32008-07-20 18:53:20 +02002069 { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002070 { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 },
2071 { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 },
Francois Romieu197ff762008-06-28 13:16:02 +02002072 { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 },
Francois Romieu6fb07052008-06-29 11:54:28 +02002073 { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 },
Francois Romieuef808d52008-06-29 13:10:54 +02002074 { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002075
2076 /* 8168B family. */
2077 { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 },
2078 { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 },
2079 { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 },
2080 { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 },
2081
2082 /* 8101 family. */
Hayes Wang5598bfe2012-07-02 17:23:21 +08002083 { 0x7cf00000, 0x44900000, RTL_GIGA_MAC_VER_39 },
2084 { 0x7c800000, 0x44800000, RTL_GIGA_MAC_VER_39 },
Hayes Wang7e18dca2012-03-30 14:33:02 +08002085 { 0x7c800000, 0x44000000, RTL_GIGA_MAC_VER_37 },
hayeswang36a0e6c2011-03-21 01:50:30 +00002086 { 0x7cf00000, 0x40b00000, RTL_GIGA_MAC_VER_30 },
Hayes Wang5a5e4442011-02-22 17:26:21 +08002087 { 0x7cf00000, 0x40a00000, RTL_GIGA_MAC_VER_30 },
2088 { 0x7cf00000, 0x40900000, RTL_GIGA_MAC_VER_29 },
2089 { 0x7c800000, 0x40800000, RTL_GIGA_MAC_VER_30 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002090 { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 },
2091 { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 },
2092 { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 },
2093 { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 },
2094 { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 },
2095 { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002096 { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002097 { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002098 { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002099 { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 },
2100 { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002101 { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 },
2102 /* FIXME: where did these entries come from ? -- FR */
2103 { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 },
2104 { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 },
2105
2106 /* 8110 family. */
2107 { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 },
2108 { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 },
2109 { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 },
2110 { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 },
2111 { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 },
2112 { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 },
2113
Jean Delvaref21b75e2009-05-26 20:54:48 -07002114 /* Catch-all */
2115 { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE }
Francois Romieu37441002011-06-17 22:58:54 +02002116 };
2117 const struct rtl_mac_info *p = mac_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 u32 reg;
2119
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002120 reg = RTL_R32(TxConfig);
2121 while ((reg & p->mask) != p->val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 p++;
2123 tp->mac_version = p->mac_version;
Francois Romieu5d320a22011-05-08 17:47:36 +02002124
2125 if (tp->mac_version == RTL_GIGA_MAC_NONE) {
2126 netif_notice(tp, probe, dev,
2127 "unknown MAC, using family default\n");
2128 tp->mac_version = default_version;
2129 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130}
2131
2132static void rtl8169_print_mac_version(struct rtl8169_private *tp)
2133{
Francois Romieubcf0bf92006-07-26 23:14:13 +02002134 dprintk("mac_version = 0x%02x\n", tp->mac_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135}
2136
Francois Romieu867763c2007-08-17 18:21:58 +02002137struct phy_reg {
2138 u16 reg;
2139 u16 val;
2140};
2141
françois romieu4da19632011-01-03 15:07:55 +00002142static void rtl_writephy_batch(struct rtl8169_private *tp,
2143 const struct phy_reg *regs, int len)
Francois Romieu867763c2007-08-17 18:21:58 +02002144{
2145 while (len-- > 0) {
françois romieu4da19632011-01-03 15:07:55 +00002146 rtl_writephy(tp, regs->reg, regs->val);
Francois Romieu867763c2007-08-17 18:21:58 +02002147 regs++;
2148 }
2149}
2150
françois romieubca03d52011-01-03 15:07:31 +00002151#define PHY_READ 0x00000000
2152#define PHY_DATA_OR 0x10000000
2153#define PHY_DATA_AND 0x20000000
2154#define PHY_BJMPN 0x30000000
2155#define PHY_READ_EFUSE 0x40000000
2156#define PHY_READ_MAC_BYTE 0x50000000
2157#define PHY_WRITE_MAC_BYTE 0x60000000
2158#define PHY_CLEAR_READCOUNT 0x70000000
2159#define PHY_WRITE 0x80000000
2160#define PHY_READCOUNT_EQ_SKIP 0x90000000
2161#define PHY_COMP_EQ_SKIPN 0xa0000000
2162#define PHY_COMP_NEQ_SKIPN 0xb0000000
2163#define PHY_WRITE_PREVIOUS 0xc0000000
2164#define PHY_SKIPN 0xd0000000
2165#define PHY_DELAY_MS 0xe0000000
2166#define PHY_WRITE_ERI_WORD 0xf0000000
2167
Hayes Wang960aee62011-06-18 11:37:48 +02002168struct fw_info {
2169 u32 magic;
2170 char version[RTL_VER_SIZE];
2171 __le32 fw_start;
2172 __le32 fw_len;
2173 u8 chksum;
2174} __packed;
2175
Francois Romieu1c361ef2011-06-17 17:16:24 +02002176#define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code))
2177
2178static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
françois romieubca03d52011-01-03 15:07:31 +00002179{
Francois Romieub6ffd972011-06-17 17:00:05 +02002180 const struct firmware *fw = rtl_fw->fw;
Hayes Wang960aee62011-06-18 11:37:48 +02002181 struct fw_info *fw_info = (struct fw_info *)fw->data;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002182 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
2183 char *version = rtl_fw->version;
2184 bool rc = false;
françois romieubca03d52011-01-03 15:07:31 +00002185
Francois Romieu1c361ef2011-06-17 17:16:24 +02002186 if (fw->size < FW_OPCODE_SIZE)
2187 goto out;
Hayes Wang960aee62011-06-18 11:37:48 +02002188
2189 if (!fw_info->magic) {
2190 size_t i, size, start;
2191 u8 checksum = 0;
2192
2193 if (fw->size < sizeof(*fw_info))
2194 goto out;
2195
2196 for (i = 0; i < fw->size; i++)
2197 checksum += fw->data[i];
2198 if (checksum != 0)
2199 goto out;
2200
2201 start = le32_to_cpu(fw_info->fw_start);
2202 if (start > fw->size)
2203 goto out;
2204
2205 size = le32_to_cpu(fw_info->fw_len);
2206 if (size > (fw->size - start) / FW_OPCODE_SIZE)
2207 goto out;
2208
2209 memcpy(version, fw_info->version, RTL_VER_SIZE);
2210
2211 pa->code = (__le32 *)(fw->data + start);
2212 pa->size = size;
2213 } else {
Francois Romieu1c361ef2011-06-17 17:16:24 +02002214 if (fw->size % FW_OPCODE_SIZE)
2215 goto out;
2216
2217 strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE);
2218
2219 pa->code = (__le32 *)fw->data;
2220 pa->size = fw->size / FW_OPCODE_SIZE;
2221 }
2222 version[RTL_VER_SIZE - 1] = 0;
2223
2224 rc = true;
2225out:
2226 return rc;
2227}
2228
Francois Romieufd112f22011-06-18 00:10:29 +02002229static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev,
2230 struct rtl_fw_phy_action *pa)
Francois Romieu1c361ef2011-06-17 17:16:24 +02002231{
Francois Romieufd112f22011-06-18 00:10:29 +02002232 bool rc = false;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002233 size_t index;
2234
Francois Romieu1c361ef2011-06-17 17:16:24 +02002235 for (index = 0; index < pa->size; index++) {
2236 u32 action = le32_to_cpu(pa->code[index]);
hayeswang42b82dc2011-01-10 02:07:25 +00002237 u32 regno = (action & 0x0fff0000) >> 16;
françois romieubca03d52011-01-03 15:07:31 +00002238
hayeswang42b82dc2011-01-10 02:07:25 +00002239 switch(action & 0xf0000000) {
2240 case PHY_READ:
2241 case PHY_DATA_OR:
2242 case PHY_DATA_AND:
2243 case PHY_READ_EFUSE:
2244 case PHY_CLEAR_READCOUNT:
2245 case PHY_WRITE:
2246 case PHY_WRITE_PREVIOUS:
2247 case PHY_DELAY_MS:
françois romieubca03d52011-01-03 15:07:31 +00002248 break;
2249
hayeswang42b82dc2011-01-10 02:07:25 +00002250 case PHY_BJMPN:
2251 if (regno > index) {
Francois Romieufd112f22011-06-18 00:10:29 +02002252 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002253 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002254 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002255 }
2256 break;
2257 case PHY_READCOUNT_EQ_SKIP:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002258 if (index + 2 >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002259 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002260 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002261 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002262 }
2263 break;
2264 case PHY_COMP_EQ_SKIPN:
2265 case PHY_COMP_NEQ_SKIPN:
2266 case PHY_SKIPN:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002267 if (index + 1 + regno >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002268 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002269 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002270 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002271 }
2272 break;
2273
2274 case PHY_READ_MAC_BYTE:
2275 case PHY_WRITE_MAC_BYTE:
2276 case PHY_WRITE_ERI_WORD:
2277 default:
Francois Romieufd112f22011-06-18 00:10:29 +02002278 netif_err(tp, ifup, tp->dev,
hayeswang42b82dc2011-01-10 02:07:25 +00002279 "Invalid action 0x%08x\n", action);
Francois Romieufd112f22011-06-18 00:10:29 +02002280 goto out;
françois romieubca03d52011-01-03 15:07:31 +00002281 }
2282 }
Francois Romieufd112f22011-06-18 00:10:29 +02002283 rc = true;
2284out:
2285 return rc;
2286}
françois romieubca03d52011-01-03 15:07:31 +00002287
Francois Romieufd112f22011-06-18 00:10:29 +02002288static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2289{
2290 struct net_device *dev = tp->dev;
2291 int rc = -EINVAL;
2292
2293 if (!rtl_fw_format_ok(tp, rtl_fw)) {
2294 netif_err(tp, ifup, dev, "invalid firwmare\n");
2295 goto out;
2296 }
2297
2298 if (rtl_fw_data_ok(tp, dev, &rtl_fw->phy_action))
2299 rc = 0;
2300out:
2301 return rc;
2302}
2303
2304static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2305{
2306 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
2307 u32 predata, count;
2308 size_t index;
2309
2310 predata = count = 0;
hayeswang42b82dc2011-01-10 02:07:25 +00002311
Francois Romieu1c361ef2011-06-17 17:16:24 +02002312 for (index = 0; index < pa->size; ) {
2313 u32 action = le32_to_cpu(pa->code[index]);
françois romieubca03d52011-01-03 15:07:31 +00002314 u32 data = action & 0x0000ffff;
hayeswang42b82dc2011-01-10 02:07:25 +00002315 u32 regno = (action & 0x0fff0000) >> 16;
2316
2317 if (!action)
2318 break;
françois romieubca03d52011-01-03 15:07:31 +00002319
2320 switch(action & 0xf0000000) {
hayeswang42b82dc2011-01-10 02:07:25 +00002321 case PHY_READ:
2322 predata = rtl_readphy(tp, regno);
2323 count++;
2324 index++;
françois romieubca03d52011-01-03 15:07:31 +00002325 break;
hayeswang42b82dc2011-01-10 02:07:25 +00002326 case PHY_DATA_OR:
2327 predata |= data;
2328 index++;
2329 break;
2330 case PHY_DATA_AND:
2331 predata &= data;
2332 index++;
2333 break;
2334 case PHY_BJMPN:
2335 index -= regno;
2336 break;
2337 case PHY_READ_EFUSE:
Francois Romieufdf6fc02012-07-06 22:40:38 +02002338 predata = rtl8168d_efuse_read(tp, regno);
hayeswang42b82dc2011-01-10 02:07:25 +00002339 index++;
2340 break;
2341 case PHY_CLEAR_READCOUNT:
2342 count = 0;
2343 index++;
2344 break;
2345 case PHY_WRITE:
2346 rtl_writephy(tp, regno, data);
2347 index++;
2348 break;
2349 case PHY_READCOUNT_EQ_SKIP:
Francois Romieucecb5fd2011-04-01 10:21:07 +02002350 index += (count == data) ? 2 : 1;
hayeswang42b82dc2011-01-10 02:07:25 +00002351 break;
2352 case PHY_COMP_EQ_SKIPN:
2353 if (predata == data)
2354 index += regno;
2355 index++;
2356 break;
2357 case PHY_COMP_NEQ_SKIPN:
2358 if (predata != data)
2359 index += regno;
2360 index++;
2361 break;
2362 case PHY_WRITE_PREVIOUS:
2363 rtl_writephy(tp, regno, predata);
2364 index++;
2365 break;
2366 case PHY_SKIPN:
2367 index += regno + 1;
2368 break;
2369 case PHY_DELAY_MS:
2370 mdelay(data);
2371 index++;
2372 break;
2373
2374 case PHY_READ_MAC_BYTE:
2375 case PHY_WRITE_MAC_BYTE:
2376 case PHY_WRITE_ERI_WORD:
françois romieubca03d52011-01-03 15:07:31 +00002377 default:
2378 BUG();
2379 }
2380 }
2381}
2382
françois romieuf1e02ed2011-01-13 13:07:53 +00002383static void rtl_release_firmware(struct rtl8169_private *tp)
2384{
Francois Romieub6ffd972011-06-17 17:00:05 +02002385 if (!IS_ERR_OR_NULL(tp->rtl_fw)) {
2386 release_firmware(tp->rtl_fw->fw);
2387 kfree(tp->rtl_fw);
2388 }
2389 tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
françois romieuf1e02ed2011-01-13 13:07:53 +00002390}
2391
François Romieu953a12c2011-04-24 17:38:48 +02002392static void rtl_apply_firmware(struct rtl8169_private *tp)
françois romieuf1e02ed2011-01-13 13:07:53 +00002393{
Francois Romieub6ffd972011-06-17 17:00:05 +02002394 struct rtl_fw *rtl_fw = tp->rtl_fw;
françois romieuf1e02ed2011-01-13 13:07:53 +00002395
2396 /* TODO: release firmware once rtl_phy_write_fw signals failures. */
hayeswange0c07552012-10-23 20:24:03 +00002397 if (!IS_ERR_OR_NULL(rtl_fw)) {
Francois Romieub6ffd972011-06-17 17:00:05 +02002398 rtl_phy_write_fw(tp, rtl_fw);
hayeswange0c07552012-10-23 20:24:03 +00002399 tp->features |= RTL_FEATURE_FW_LOADED;
2400 }
François Romieu953a12c2011-04-24 17:38:48 +02002401}
2402
2403static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
2404{
2405 if (rtl_readphy(tp, reg) != val)
2406 netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n");
2407 else
2408 rtl_apply_firmware(tp);
françois romieuf1e02ed2011-01-13 13:07:53 +00002409}
2410
hayeswange0c07552012-10-23 20:24:03 +00002411static void r810x_aldps_disable(struct rtl8169_private *tp)
2412{
2413 rtl_writephy(tp, 0x1f, 0x0000);
2414 rtl_writephy(tp, 0x18, 0x0310);
2415 msleep(100);
2416}
2417
2418static void r810x_aldps_enable(struct rtl8169_private *tp)
2419{
2420 if (!(tp->features & RTL_FEATURE_FW_LOADED))
2421 return;
2422
2423 rtl_writephy(tp, 0x1f, 0x0000);
2424 rtl_writephy(tp, 0x18, 0x8310);
2425}
2426
2427static void r8168_aldps_enable_1(struct rtl8169_private *tp)
2428{
2429 if (!(tp->features & RTL_FEATURE_FW_LOADED))
2430 return;
2431
2432 rtl_writephy(tp, 0x1f, 0x0000);
2433 rtl_w1w0_phy(tp, 0x15, 0x1000, 0x0000);
2434}
2435
françois romieu4da19632011-01-03 15:07:55 +00002436static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002438 static const struct phy_reg phy_reg_init[] = {
françois romieu0b9b5712009-08-10 19:44:56 +00002439 { 0x1f, 0x0001 },
2440 { 0x06, 0x006e },
2441 { 0x08, 0x0708 },
2442 { 0x15, 0x4000 },
2443 { 0x18, 0x65c7 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444
françois romieu0b9b5712009-08-10 19:44:56 +00002445 { 0x1f, 0x0001 },
2446 { 0x03, 0x00a1 },
2447 { 0x02, 0x0008 },
2448 { 0x01, 0x0120 },
2449 { 0x00, 0x1000 },
2450 { 0x04, 0x0800 },
2451 { 0x04, 0x0000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452
françois romieu0b9b5712009-08-10 19:44:56 +00002453 { 0x03, 0xff41 },
2454 { 0x02, 0xdf60 },
2455 { 0x01, 0x0140 },
2456 { 0x00, 0x0077 },
2457 { 0x04, 0x7800 },
2458 { 0x04, 0x7000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459
françois romieu0b9b5712009-08-10 19:44:56 +00002460 { 0x03, 0x802f },
2461 { 0x02, 0x4f02 },
2462 { 0x01, 0x0409 },
2463 { 0x00, 0xf0f9 },
2464 { 0x04, 0x9800 },
2465 { 0x04, 0x9000 },
2466
2467 { 0x03, 0xdf01 },
2468 { 0x02, 0xdf20 },
2469 { 0x01, 0xff95 },
2470 { 0x00, 0xba00 },
2471 { 0x04, 0xa800 },
2472 { 0x04, 0xa000 },
2473
2474 { 0x03, 0xff41 },
2475 { 0x02, 0xdf20 },
2476 { 0x01, 0x0140 },
2477 { 0x00, 0x00bb },
2478 { 0x04, 0xb800 },
2479 { 0x04, 0xb000 },
2480
2481 { 0x03, 0xdf41 },
2482 { 0x02, 0xdc60 },
2483 { 0x01, 0x6340 },
2484 { 0x00, 0x007d },
2485 { 0x04, 0xd800 },
2486 { 0x04, 0xd000 },
2487
2488 { 0x03, 0xdf01 },
2489 { 0x02, 0xdf20 },
2490 { 0x01, 0x100a },
2491 { 0x00, 0xa0ff },
2492 { 0x04, 0xf800 },
2493 { 0x04, 0xf000 },
2494
2495 { 0x1f, 0x0000 },
2496 { 0x0b, 0x0000 },
2497 { 0x00, 0x9200 }
2498 };
2499
françois romieu4da19632011-01-03 15:07:55 +00002500 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501}
2502
françois romieu4da19632011-01-03 15:07:55 +00002503static void rtl8169sb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5615d9f2007-08-17 17:50:46 +02002504{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002505 static const struct phy_reg phy_reg_init[] = {
Francois Romieua441d7b2007-08-17 18:26:35 +02002506 { 0x1f, 0x0002 },
2507 { 0x01, 0x90d0 },
2508 { 0x1f, 0x0000 }
2509 };
2510
françois romieu4da19632011-01-03 15:07:55 +00002511 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5615d9f2007-08-17 17:50:46 +02002512}
2513
françois romieu4da19632011-01-03 15:07:55 +00002514static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002515{
2516 struct pci_dev *pdev = tp->pci_dev;
françois romieu2e9558562009-08-10 19:44:19 +00002517
Sergei Shtylyovccbae552011-07-22 05:37:24 +00002518 if ((pdev->subsystem_vendor != PCI_VENDOR_ID_GIGABYTE) ||
2519 (pdev->subsystem_device != 0xe000))
françois romieu2e9558562009-08-10 19:44:19 +00002520 return;
2521
françois romieu4da19632011-01-03 15:07:55 +00002522 rtl_writephy(tp, 0x1f, 0x0001);
2523 rtl_writephy(tp, 0x10, 0xf01b);
2524 rtl_writephy(tp, 0x1f, 0x0000);
françois romieu2e9558562009-08-10 19:44:19 +00002525}
2526
françois romieu4da19632011-01-03 15:07:55 +00002527static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002528{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002529 static const struct phy_reg phy_reg_init[] = {
françois romieu2e9558562009-08-10 19:44:19 +00002530 { 0x1f, 0x0001 },
2531 { 0x04, 0x0000 },
2532 { 0x03, 0x00a1 },
2533 { 0x02, 0x0008 },
2534 { 0x01, 0x0120 },
2535 { 0x00, 0x1000 },
2536 { 0x04, 0x0800 },
2537 { 0x04, 0x9000 },
2538 { 0x03, 0x802f },
2539 { 0x02, 0x4f02 },
2540 { 0x01, 0x0409 },
2541 { 0x00, 0xf099 },
2542 { 0x04, 0x9800 },
2543 { 0x04, 0xa000 },
2544 { 0x03, 0xdf01 },
2545 { 0x02, 0xdf20 },
2546 { 0x01, 0xff95 },
2547 { 0x00, 0xba00 },
2548 { 0x04, 0xa800 },
2549 { 0x04, 0xf000 },
2550 { 0x03, 0xdf01 },
2551 { 0x02, 0xdf20 },
2552 { 0x01, 0x101a },
2553 { 0x00, 0xa0ff },
2554 { 0x04, 0xf800 },
2555 { 0x04, 0x0000 },
2556 { 0x1f, 0x0000 },
2557
2558 { 0x1f, 0x0001 },
2559 { 0x10, 0xf41b },
2560 { 0x14, 0xfb54 },
2561 { 0x18, 0xf5c7 },
2562 { 0x1f, 0x0000 },
2563
2564 { 0x1f, 0x0001 },
2565 { 0x17, 0x0cc0 },
2566 { 0x1f, 0x0000 }
2567 };
2568
françois romieu4da19632011-01-03 15:07:55 +00002569 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu2e9558562009-08-10 19:44:19 +00002570
françois romieu4da19632011-01-03 15:07:55 +00002571 rtl8169scd_hw_phy_config_quirk(tp);
françois romieu2e9558562009-08-10 19:44:19 +00002572}
2573
françois romieu4da19632011-01-03 15:07:55 +00002574static void rtl8169sce_hw_phy_config(struct rtl8169_private *tp)
françois romieu8c7006a2009-08-10 19:43:29 +00002575{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002576 static const struct phy_reg phy_reg_init[] = {
françois romieu8c7006a2009-08-10 19:43:29 +00002577 { 0x1f, 0x0001 },
2578 { 0x04, 0x0000 },
2579 { 0x03, 0x00a1 },
2580 { 0x02, 0x0008 },
2581 { 0x01, 0x0120 },
2582 { 0x00, 0x1000 },
2583 { 0x04, 0x0800 },
2584 { 0x04, 0x9000 },
2585 { 0x03, 0x802f },
2586 { 0x02, 0x4f02 },
2587 { 0x01, 0x0409 },
2588 { 0x00, 0xf099 },
2589 { 0x04, 0x9800 },
2590 { 0x04, 0xa000 },
2591 { 0x03, 0xdf01 },
2592 { 0x02, 0xdf20 },
2593 { 0x01, 0xff95 },
2594 { 0x00, 0xba00 },
2595 { 0x04, 0xa800 },
2596 { 0x04, 0xf000 },
2597 { 0x03, 0xdf01 },
2598 { 0x02, 0xdf20 },
2599 { 0x01, 0x101a },
2600 { 0x00, 0xa0ff },
2601 { 0x04, 0xf800 },
2602 { 0x04, 0x0000 },
2603 { 0x1f, 0x0000 },
2604
2605 { 0x1f, 0x0001 },
2606 { 0x0b, 0x8480 },
2607 { 0x1f, 0x0000 },
2608
2609 { 0x1f, 0x0001 },
2610 { 0x18, 0x67c7 },
2611 { 0x04, 0x2000 },
2612 { 0x03, 0x002f },
2613 { 0x02, 0x4360 },
2614 { 0x01, 0x0109 },
2615 { 0x00, 0x3022 },
2616 { 0x04, 0x2800 },
2617 { 0x1f, 0x0000 },
2618
2619 { 0x1f, 0x0001 },
2620 { 0x17, 0x0cc0 },
2621 { 0x1f, 0x0000 }
2622 };
2623
françois romieu4da19632011-01-03 15:07:55 +00002624 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu8c7006a2009-08-10 19:43:29 +00002625}
2626
françois romieu4da19632011-01-03 15:07:55 +00002627static void rtl8168bb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002628{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002629 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002630 { 0x10, 0xf41b },
2631 { 0x1f, 0x0000 }
2632 };
2633
françois romieu4da19632011-01-03 15:07:55 +00002634 rtl_writephy(tp, 0x1f, 0x0001);
2635 rtl_patchphy(tp, 0x16, 1 << 0);
Francois Romieu236b8082008-05-30 16:11:48 +02002636
françois romieu4da19632011-01-03 15:07:55 +00002637 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002638}
2639
françois romieu4da19632011-01-03 15:07:55 +00002640static void rtl8168bef_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002641{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002642 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002643 { 0x1f, 0x0001 },
2644 { 0x10, 0xf41b },
2645 { 0x1f, 0x0000 }
2646 };
2647
françois romieu4da19632011-01-03 15:07:55 +00002648 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002649}
2650
françois romieu4da19632011-01-03 15:07:55 +00002651static void rtl8168cp_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu867763c2007-08-17 18:21:58 +02002652{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002653 static const struct phy_reg phy_reg_init[] = {
Francois Romieu867763c2007-08-17 18:21:58 +02002654 { 0x1f, 0x0000 },
2655 { 0x1d, 0x0f00 },
2656 { 0x1f, 0x0002 },
2657 { 0x0c, 0x1ec8 },
2658 { 0x1f, 0x0000 }
2659 };
2660
françois romieu4da19632011-01-03 15:07:55 +00002661 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu867763c2007-08-17 18:21:58 +02002662}
2663
françois romieu4da19632011-01-03 15:07:55 +00002664static void rtl8168cp_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02002665{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002666 static const struct phy_reg phy_reg_init[] = {
Francois Romieuef3386f2008-06-29 12:24:30 +02002667 { 0x1f, 0x0001 },
2668 { 0x1d, 0x3d98 },
2669 { 0x1f, 0x0000 }
2670 };
2671
françois romieu4da19632011-01-03 15:07:55 +00002672 rtl_writephy(tp, 0x1f, 0x0000);
2673 rtl_patchphy(tp, 0x14, 1 << 5);
2674 rtl_patchphy(tp, 0x0d, 1 << 5);
Francois Romieuef3386f2008-06-29 12:24:30 +02002675
françois romieu4da19632011-01-03 15:07:55 +00002676 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuef3386f2008-06-29 12:24:30 +02002677}
2678
françois romieu4da19632011-01-03 15:07:55 +00002679static void rtl8168c_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu867763c2007-08-17 18:21:58 +02002680{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002681 static const struct phy_reg phy_reg_init[] = {
Francois Romieua3f80672007-10-18 14:35:11 +02002682 { 0x1f, 0x0001 },
2683 { 0x12, 0x2300 },
Francois Romieu867763c2007-08-17 18:21:58 +02002684 { 0x1f, 0x0002 },
2685 { 0x00, 0x88d4 },
2686 { 0x01, 0x82b1 },
2687 { 0x03, 0x7002 },
2688 { 0x08, 0x9e30 },
2689 { 0x09, 0x01f0 },
2690 { 0x0a, 0x5500 },
2691 { 0x0c, 0x00c8 },
2692 { 0x1f, 0x0003 },
2693 { 0x12, 0xc096 },
2694 { 0x16, 0x000a },
Francois Romieuf50d4272008-05-30 16:07:07 +02002695 { 0x1f, 0x0000 },
2696 { 0x1f, 0x0000 },
2697 { 0x09, 0x2000 },
2698 { 0x09, 0x0000 }
Francois Romieu867763c2007-08-17 18:21:58 +02002699 };
2700
françois romieu4da19632011-01-03 15:07:55 +00002701 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002702
françois romieu4da19632011-01-03 15:07:55 +00002703 rtl_patchphy(tp, 0x14, 1 << 5);
2704 rtl_patchphy(tp, 0x0d, 1 << 5);
2705 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu867763c2007-08-17 18:21:58 +02002706}
2707
françois romieu4da19632011-01-03 15:07:55 +00002708static void rtl8168c_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu7da97ec2007-10-18 15:20:43 +02002709{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002710 static const struct phy_reg phy_reg_init[] = {
Francois Romieuf50d4272008-05-30 16:07:07 +02002711 { 0x1f, 0x0001 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002712 { 0x12, 0x2300 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002713 { 0x03, 0x802f },
2714 { 0x02, 0x4f02 },
2715 { 0x01, 0x0409 },
2716 { 0x00, 0xf099 },
2717 { 0x04, 0x9800 },
2718 { 0x04, 0x9000 },
2719 { 0x1d, 0x3d98 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002720 { 0x1f, 0x0002 },
2721 { 0x0c, 0x7eb8 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002722 { 0x06, 0x0761 },
2723 { 0x1f, 0x0003 },
2724 { 0x16, 0x0f0a },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002725 { 0x1f, 0x0000 }
2726 };
2727
françois romieu4da19632011-01-03 15:07:55 +00002728 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002729
françois romieu4da19632011-01-03 15:07:55 +00002730 rtl_patchphy(tp, 0x16, 1 << 0);
2731 rtl_patchphy(tp, 0x14, 1 << 5);
2732 rtl_patchphy(tp, 0x0d, 1 << 5);
2733 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu7da97ec2007-10-18 15:20:43 +02002734}
2735
françois romieu4da19632011-01-03 15:07:55 +00002736static void rtl8168c_3_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02002737{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002738 static const struct phy_reg phy_reg_init[] = {
Francois Romieu197ff762008-06-28 13:16:02 +02002739 { 0x1f, 0x0001 },
2740 { 0x12, 0x2300 },
2741 { 0x1d, 0x3d98 },
2742 { 0x1f, 0x0002 },
2743 { 0x0c, 0x7eb8 },
2744 { 0x06, 0x5461 },
2745 { 0x1f, 0x0003 },
2746 { 0x16, 0x0f0a },
2747 { 0x1f, 0x0000 }
2748 };
2749
françois romieu4da19632011-01-03 15:07:55 +00002750 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu197ff762008-06-28 13:16:02 +02002751
françois romieu4da19632011-01-03 15:07:55 +00002752 rtl_patchphy(tp, 0x16, 1 << 0);
2753 rtl_patchphy(tp, 0x14, 1 << 5);
2754 rtl_patchphy(tp, 0x0d, 1 << 5);
2755 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu197ff762008-06-28 13:16:02 +02002756}
2757
françois romieu4da19632011-01-03 15:07:55 +00002758static void rtl8168c_4_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02002759{
françois romieu4da19632011-01-03 15:07:55 +00002760 rtl8168c_3_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02002761}
2762
françois romieubca03d52011-01-03 15:07:31 +00002763static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02002764{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002765 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002766 /* Channel Estimation */
Francois Romieu5b538df2008-07-20 16:22:45 +02002767 { 0x1f, 0x0001 },
françois romieudaf9df62009-10-07 12:44:20 +00002768 { 0x06, 0x4064 },
2769 { 0x07, 0x2863 },
2770 { 0x08, 0x059c },
2771 { 0x09, 0x26b4 },
2772 { 0x0a, 0x6a19 },
2773 { 0x0b, 0xdcc8 },
2774 { 0x10, 0xf06d },
2775 { 0x14, 0x7f68 },
2776 { 0x18, 0x7fd9 },
2777 { 0x1c, 0xf0ff },
2778 { 0x1d, 0x3d9c },
Francois Romieu5b538df2008-07-20 16:22:45 +02002779 { 0x1f, 0x0003 },
françois romieudaf9df62009-10-07 12:44:20 +00002780 { 0x12, 0xf49f },
2781 { 0x13, 0x070b },
2782 { 0x1a, 0x05ad },
françois romieubca03d52011-01-03 15:07:31 +00002783 { 0x14, 0x94c0 },
2784
2785 /*
2786 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002787 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002788 */
Francois Romieu5b538df2008-07-20 16:22:45 +02002789 { 0x1f, 0x0002 },
françois romieudaf9df62009-10-07 12:44:20 +00002790 { 0x06, 0x5561 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002791 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002792 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002793 { 0x06, 0x5561 },
2794
2795 /*
2796 * Can not link to 1Gbps with bad cable
2797 * Decrease SNR threshold form 21.07dB to 19.04dB
2798 */
2799 { 0x1f, 0x0001 },
2800 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002801
2802 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002803 { 0x0d, 0xf880 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002804 };
2805
françois romieu4da19632011-01-03 15:07:55 +00002806 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
Francois Romieu5b538df2008-07-20 16:22:45 +02002807
françois romieubca03d52011-01-03 15:07:31 +00002808 /*
2809 * Rx Error Issue
2810 * Fine Tune Switching regulator parameter
2811 */
françois romieu4da19632011-01-03 15:07:55 +00002812 rtl_writephy(tp, 0x1f, 0x0002);
2813 rtl_w1w0_phy(tp, 0x0b, 0x0010, 0x00ef);
2814 rtl_w1w0_phy(tp, 0x0c, 0xa200, 0x5d00);
françois romieudaf9df62009-10-07 12:44:20 +00002815
Francois Romieufdf6fc02012-07-06 22:40:38 +02002816 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002817 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002818 { 0x1f, 0x0002 },
2819 { 0x05, 0x669a },
Francois Romieu5b538df2008-07-20 16:22:45 +02002820 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002821 { 0x05, 0x8330 },
2822 { 0x06, 0x669a },
2823 { 0x1f, 0x0002 }
2824 };
2825 int val;
2826
françois romieu4da19632011-01-03 15:07:55 +00002827 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002828
françois romieu4da19632011-01-03 15:07:55 +00002829 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002830
2831 if ((val & 0x00ff) != 0x006c) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002832 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002833 0x0065, 0x0066, 0x0067, 0x0068,
2834 0x0069, 0x006a, 0x006b, 0x006c
2835 };
2836 int i;
2837
françois romieu4da19632011-01-03 15:07:55 +00002838 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002839
2840 val &= 0xff00;
2841 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002842 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002843 }
2844 } else {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002845 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002846 { 0x1f, 0x0002 },
2847 { 0x05, 0x6662 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002848 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002849 { 0x05, 0x8330 },
2850 { 0x06, 0x6662 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002851 };
2852
françois romieu4da19632011-01-03 15:07:55 +00002853 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02002854 }
2855
françois romieubca03d52011-01-03 15:07:31 +00002856 /* RSET couple improve */
françois romieu4da19632011-01-03 15:07:55 +00002857 rtl_writephy(tp, 0x1f, 0x0002);
2858 rtl_patchphy(tp, 0x0d, 0x0300);
2859 rtl_patchphy(tp, 0x0f, 0x0010);
françois romieudaf9df62009-10-07 12:44:20 +00002860
françois romieubca03d52011-01-03 15:07:31 +00002861 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002862 rtl_writephy(tp, 0x1f, 0x0002);
2863 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2864 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002865
françois romieu4da19632011-01-03 15:07:55 +00002866 rtl_writephy(tp, 0x1f, 0x0005);
2867 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002868
2869 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00);
françois romieubca03d52011-01-03 15:07:31 +00002870
françois romieu4da19632011-01-03 15:07:55 +00002871 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002872}
2873
françois romieubca03d52011-01-03 15:07:31 +00002874static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002875{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002876 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002877 /* Channel Estimation */
françois romieudaf9df62009-10-07 12:44:20 +00002878 { 0x1f, 0x0001 },
2879 { 0x06, 0x4064 },
2880 { 0x07, 0x2863 },
2881 { 0x08, 0x059c },
2882 { 0x09, 0x26b4 },
2883 { 0x0a, 0x6a19 },
2884 { 0x0b, 0xdcc8 },
2885 { 0x10, 0xf06d },
2886 { 0x14, 0x7f68 },
2887 { 0x18, 0x7fd9 },
2888 { 0x1c, 0xf0ff },
2889 { 0x1d, 0x3d9c },
2890 { 0x1f, 0x0003 },
2891 { 0x12, 0xf49f },
2892 { 0x13, 0x070b },
2893 { 0x1a, 0x05ad },
2894 { 0x14, 0x94c0 },
2895
françois romieubca03d52011-01-03 15:07:31 +00002896 /*
2897 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002898 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002899 */
françois romieudaf9df62009-10-07 12:44:20 +00002900 { 0x1f, 0x0002 },
2901 { 0x06, 0x5561 },
2902 { 0x1f, 0x0005 },
2903 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002904 { 0x06, 0x5561 },
2905
2906 /*
2907 * Can not link to 1Gbps with bad cable
2908 * Decrease SNR threshold form 21.07dB to 19.04dB
2909 */
2910 { 0x1f, 0x0001 },
2911 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002912
2913 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002914 { 0x0d, 0xf880 }
françois romieudaf9df62009-10-07 12:44:20 +00002915 };
2916
françois romieu4da19632011-01-03 15:07:55 +00002917 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
françois romieudaf9df62009-10-07 12:44:20 +00002918
Francois Romieufdf6fc02012-07-06 22:40:38 +02002919 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002920 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002921 { 0x1f, 0x0002 },
2922 { 0x05, 0x669a },
2923 { 0x1f, 0x0005 },
2924 { 0x05, 0x8330 },
2925 { 0x06, 0x669a },
2926
2927 { 0x1f, 0x0002 }
2928 };
2929 int val;
2930
françois romieu4da19632011-01-03 15:07:55 +00002931 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002932
françois romieu4da19632011-01-03 15:07:55 +00002933 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002934 if ((val & 0x00ff) != 0x006c) {
Joe Perchesb6bc7652010-12-21 02:16:08 -08002935 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002936 0x0065, 0x0066, 0x0067, 0x0068,
2937 0x0069, 0x006a, 0x006b, 0x006c
2938 };
2939 int i;
2940
françois romieu4da19632011-01-03 15:07:55 +00002941 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002942
2943 val &= 0xff00;
2944 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002945 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002946 }
2947 } else {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002948 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002949 { 0x1f, 0x0002 },
2950 { 0x05, 0x2642 },
2951 { 0x1f, 0x0005 },
2952 { 0x05, 0x8330 },
2953 { 0x06, 0x2642 }
2954 };
2955
françois romieu4da19632011-01-03 15:07:55 +00002956 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002957 }
2958
françois romieubca03d52011-01-03 15:07:31 +00002959 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002960 rtl_writephy(tp, 0x1f, 0x0002);
2961 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2962 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002963
françois romieubca03d52011-01-03 15:07:31 +00002964 /* Switching regulator Slew rate */
françois romieu4da19632011-01-03 15:07:55 +00002965 rtl_writephy(tp, 0x1f, 0x0002);
2966 rtl_patchphy(tp, 0x0f, 0x0017);
françois romieudaf9df62009-10-07 12:44:20 +00002967
françois romieu4da19632011-01-03 15:07:55 +00002968 rtl_writephy(tp, 0x1f, 0x0005);
2969 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002970
2971 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300);
françois romieubca03d52011-01-03 15:07:31 +00002972
françois romieu4da19632011-01-03 15:07:55 +00002973 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002974}
2975
françois romieu4da19632011-01-03 15:07:55 +00002976static void rtl8168d_3_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002977{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002978 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002979 { 0x1f, 0x0002 },
2980 { 0x10, 0x0008 },
2981 { 0x0d, 0x006c },
2982
2983 { 0x1f, 0x0000 },
2984 { 0x0d, 0xf880 },
2985
2986 { 0x1f, 0x0001 },
2987 { 0x17, 0x0cc0 },
2988
2989 { 0x1f, 0x0001 },
2990 { 0x0b, 0xa4d8 },
2991 { 0x09, 0x281c },
2992 { 0x07, 0x2883 },
2993 { 0x0a, 0x6b35 },
2994 { 0x1d, 0x3da4 },
2995 { 0x1c, 0xeffd },
2996 { 0x14, 0x7f52 },
2997 { 0x18, 0x7fc6 },
2998 { 0x08, 0x0601 },
2999 { 0x06, 0x4063 },
3000 { 0x10, 0xf074 },
3001 { 0x1f, 0x0003 },
3002 { 0x13, 0x0789 },
3003 { 0x12, 0xf4bd },
3004 { 0x1a, 0x04fd },
3005 { 0x14, 0x84b0 },
3006 { 0x1f, 0x0000 },
3007 { 0x00, 0x9200 },
3008
3009 { 0x1f, 0x0005 },
3010 { 0x01, 0x0340 },
3011 { 0x1f, 0x0001 },
3012 { 0x04, 0x4000 },
3013 { 0x03, 0x1d21 },
3014 { 0x02, 0x0c32 },
3015 { 0x01, 0x0200 },
3016 { 0x00, 0x5554 },
3017 { 0x04, 0x4800 },
3018 { 0x04, 0x4000 },
3019 { 0x04, 0xf000 },
3020 { 0x03, 0xdf01 },
3021 { 0x02, 0xdf20 },
3022 { 0x01, 0x101a },
3023 { 0x00, 0xa0ff },
3024 { 0x04, 0xf800 },
3025 { 0x04, 0xf000 },
3026 { 0x1f, 0x0000 },
3027
3028 { 0x1f, 0x0007 },
3029 { 0x1e, 0x0023 },
3030 { 0x16, 0x0000 },
3031 { 0x1f, 0x0000 }
3032 };
3033
françois romieu4da19632011-01-03 15:07:55 +00003034 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02003035}
3036
françois romieue6de30d2011-01-03 15:08:37 +00003037static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp)
3038{
3039 static const struct phy_reg phy_reg_init[] = {
3040 { 0x1f, 0x0001 },
3041 { 0x17, 0x0cc0 },
3042
3043 { 0x1f, 0x0007 },
3044 { 0x1e, 0x002d },
3045 { 0x18, 0x0040 },
3046 { 0x1f, 0x0000 }
3047 };
3048
3049 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3050 rtl_patchphy(tp, 0x0d, 1 << 5);
3051}
3052
Hayes Wang70090422011-07-06 15:58:06 +08003053static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00003054{
3055 static const struct phy_reg phy_reg_init[] = {
3056 /* Enable Delay cap */
3057 { 0x1f, 0x0005 },
3058 { 0x05, 0x8b80 },
3059 { 0x06, 0xc896 },
3060 { 0x1f, 0x0000 },
3061
3062 /* Channel estimation fine tune */
3063 { 0x1f, 0x0001 },
3064 { 0x0b, 0x6c20 },
3065 { 0x07, 0x2872 },
3066 { 0x1c, 0xefff },
3067 { 0x1f, 0x0003 },
3068 { 0x14, 0x6420 },
3069 { 0x1f, 0x0000 },
3070
3071 /* Update PFM & 10M TX idle timer */
3072 { 0x1f, 0x0007 },
3073 { 0x1e, 0x002f },
3074 { 0x15, 0x1919 },
3075 { 0x1f, 0x0000 },
3076
3077 { 0x1f, 0x0007 },
3078 { 0x1e, 0x00ac },
3079 { 0x18, 0x0006 },
3080 { 0x1f, 0x0000 }
3081 };
3082
Francois Romieu15ecd032011-04-27 13:52:22 -07003083 rtl_apply_firmware(tp);
3084
hayeswang01dc7fe2011-03-21 01:50:28 +00003085 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3086
3087 /* DCO enable for 10M IDLE Power */
3088 rtl_writephy(tp, 0x1f, 0x0007);
3089 rtl_writephy(tp, 0x1e, 0x0023);
3090 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3091 rtl_writephy(tp, 0x1f, 0x0000);
3092
3093 /* For impedance matching */
3094 rtl_writephy(tp, 0x1f, 0x0002);
3095 rtl_w1w0_phy(tp, 0x08, 0x8000, 0x7f00);
Francois Romieucecb5fd2011-04-01 10:21:07 +02003096 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003097
3098 /* PHY auto speed down */
3099 rtl_writephy(tp, 0x1f, 0x0007);
3100 rtl_writephy(tp, 0x1e, 0x002d);
3101 rtl_w1w0_phy(tp, 0x18, 0x0050, 0x0000);
3102 rtl_writephy(tp, 0x1f, 0x0000);
3103 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3104
3105 rtl_writephy(tp, 0x1f, 0x0005);
3106 rtl_writephy(tp, 0x05, 0x8b86);
3107 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3108 rtl_writephy(tp, 0x1f, 0x0000);
3109
3110 rtl_writephy(tp, 0x1f, 0x0005);
3111 rtl_writephy(tp, 0x05, 0x8b85);
3112 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3113 rtl_writephy(tp, 0x1f, 0x0007);
3114 rtl_writephy(tp, 0x1e, 0x0020);
3115 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x1100);
3116 rtl_writephy(tp, 0x1f, 0x0006);
3117 rtl_writephy(tp, 0x00, 0x5a00);
3118 rtl_writephy(tp, 0x1f, 0x0000);
3119 rtl_writephy(tp, 0x0d, 0x0007);
3120 rtl_writephy(tp, 0x0e, 0x003c);
3121 rtl_writephy(tp, 0x0d, 0x4007);
3122 rtl_writephy(tp, 0x0e, 0x0000);
3123 rtl_writephy(tp, 0x0d, 0x0000);
3124}
3125
Hayes Wang70090422011-07-06 15:58:06 +08003126static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
3127{
3128 static const struct phy_reg phy_reg_init[] = {
3129 /* Enable Delay cap */
3130 { 0x1f, 0x0004 },
3131 { 0x1f, 0x0007 },
3132 { 0x1e, 0x00ac },
3133 { 0x18, 0x0006 },
3134 { 0x1f, 0x0002 },
3135 { 0x1f, 0x0000 },
3136 { 0x1f, 0x0000 },
3137
3138 /* Channel estimation fine tune */
3139 { 0x1f, 0x0003 },
3140 { 0x09, 0xa20f },
3141 { 0x1f, 0x0000 },
3142 { 0x1f, 0x0000 },
3143
3144 /* Green Setting */
3145 { 0x1f, 0x0005 },
3146 { 0x05, 0x8b5b },
3147 { 0x06, 0x9222 },
3148 { 0x05, 0x8b6d },
3149 { 0x06, 0x8000 },
3150 { 0x05, 0x8b76 },
3151 { 0x06, 0x8000 },
3152 { 0x1f, 0x0000 }
3153 };
3154
3155 rtl_apply_firmware(tp);
3156
3157 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3158
3159 /* For 4-corner performance improve */
3160 rtl_writephy(tp, 0x1f, 0x0005);
3161 rtl_writephy(tp, 0x05, 0x8b80);
3162 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3163 rtl_writephy(tp, 0x1f, 0x0000);
3164
3165 /* PHY auto speed down */
3166 rtl_writephy(tp, 0x1f, 0x0004);
3167 rtl_writephy(tp, 0x1f, 0x0007);
3168 rtl_writephy(tp, 0x1e, 0x002d);
3169 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3170 rtl_writephy(tp, 0x1f, 0x0002);
3171 rtl_writephy(tp, 0x1f, 0x0000);
3172 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3173
3174 /* improve 10M EEE waveform */
3175 rtl_writephy(tp, 0x1f, 0x0005);
3176 rtl_writephy(tp, 0x05, 0x8b86);
3177 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3178 rtl_writephy(tp, 0x1f, 0x0000);
3179
3180 /* Improve 2-pair detection performance */
3181 rtl_writephy(tp, 0x1f, 0x0005);
3182 rtl_writephy(tp, 0x05, 0x8b85);
3183 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3184 rtl_writephy(tp, 0x1f, 0x0000);
3185
3186 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003187 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0000, 0x0003, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08003188 rtl_writephy(tp, 0x1f, 0x0005);
3189 rtl_writephy(tp, 0x05, 0x8b85);
3190 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3191 rtl_writephy(tp, 0x1f, 0x0004);
3192 rtl_writephy(tp, 0x1f, 0x0007);
3193 rtl_writephy(tp, 0x1e, 0x0020);
David S. Miller1805b2f2011-10-24 18:18:09 -04003194 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
Hayes Wang70090422011-07-06 15:58:06 +08003195 rtl_writephy(tp, 0x1f, 0x0002);
3196 rtl_writephy(tp, 0x1f, 0x0000);
3197 rtl_writephy(tp, 0x0d, 0x0007);
3198 rtl_writephy(tp, 0x0e, 0x003c);
3199 rtl_writephy(tp, 0x0d, 0x4007);
3200 rtl_writephy(tp, 0x0e, 0x0000);
3201 rtl_writephy(tp, 0x0d, 0x0000);
3202
3203 /* Green feature */
3204 rtl_writephy(tp, 0x1f, 0x0003);
3205 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3206 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3207 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003208
3209 r8168_aldps_enable_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08003210}
3211
Hayes Wang5f886e02012-03-30 14:33:03 +08003212static void rtl8168f_hw_phy_config(struct rtl8169_private *tp)
3213{
3214 /* For 4-corner performance improve */
3215 rtl_writephy(tp, 0x1f, 0x0005);
3216 rtl_writephy(tp, 0x05, 0x8b80);
3217 rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
3218 rtl_writephy(tp, 0x1f, 0x0000);
3219
3220 /* PHY auto speed down */
3221 rtl_writephy(tp, 0x1f, 0x0007);
3222 rtl_writephy(tp, 0x1e, 0x002d);
3223 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3224 rtl_writephy(tp, 0x1f, 0x0000);
3225 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3226
3227 /* Improve 10M EEE waveform */
3228 rtl_writephy(tp, 0x1f, 0x0005);
3229 rtl_writephy(tp, 0x05, 0x8b86);
3230 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3231 rtl_writephy(tp, 0x1f, 0x0000);
3232}
3233
Hayes Wangc2218922011-09-06 16:55:18 +08003234static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
3235{
3236 static const struct phy_reg phy_reg_init[] = {
3237 /* Channel estimation fine tune */
3238 { 0x1f, 0x0003 },
3239 { 0x09, 0xa20f },
3240 { 0x1f, 0x0000 },
3241
3242 /* Modify green table for giga & fnet */
3243 { 0x1f, 0x0005 },
3244 { 0x05, 0x8b55 },
3245 { 0x06, 0x0000 },
3246 { 0x05, 0x8b5e },
3247 { 0x06, 0x0000 },
3248 { 0x05, 0x8b67 },
3249 { 0x06, 0x0000 },
3250 { 0x05, 0x8b70 },
3251 { 0x06, 0x0000 },
3252 { 0x1f, 0x0000 },
3253 { 0x1f, 0x0007 },
3254 { 0x1e, 0x0078 },
3255 { 0x17, 0x0000 },
3256 { 0x19, 0x00fb },
3257 { 0x1f, 0x0000 },
3258
3259 /* Modify green table for 10M */
3260 { 0x1f, 0x0005 },
3261 { 0x05, 0x8b79 },
3262 { 0x06, 0xaa00 },
3263 { 0x1f, 0x0000 },
3264
3265 /* Disable hiimpedance detection (RTCT) */
3266 { 0x1f, 0x0003 },
3267 { 0x01, 0x328a },
3268 { 0x1f, 0x0000 }
3269 };
3270
3271 rtl_apply_firmware(tp);
3272
3273 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3274
Hayes Wang5f886e02012-03-30 14:33:03 +08003275 rtl8168f_hw_phy_config(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003276
3277 /* Improve 2-pair detection performance */
3278 rtl_writephy(tp, 0x1f, 0x0005);
3279 rtl_writephy(tp, 0x05, 0x8b85);
3280 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3281 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003282
3283 r8168_aldps_enable_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003284}
3285
3286static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
3287{
3288 rtl_apply_firmware(tp);
3289
Hayes Wang5f886e02012-03-30 14:33:03 +08003290 rtl8168f_hw_phy_config(tp);
hayeswange0c07552012-10-23 20:24:03 +00003291
3292 r8168_aldps_enable_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003293}
3294
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003295static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
3296{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003297 static const struct phy_reg phy_reg_init[] = {
3298 /* Channel estimation fine tune */
3299 { 0x1f, 0x0003 },
3300 { 0x09, 0xa20f },
3301 { 0x1f, 0x0000 },
3302
3303 /* Modify green table for giga & fnet */
3304 { 0x1f, 0x0005 },
3305 { 0x05, 0x8b55 },
3306 { 0x06, 0x0000 },
3307 { 0x05, 0x8b5e },
3308 { 0x06, 0x0000 },
3309 { 0x05, 0x8b67 },
3310 { 0x06, 0x0000 },
3311 { 0x05, 0x8b70 },
3312 { 0x06, 0x0000 },
3313 { 0x1f, 0x0000 },
3314 { 0x1f, 0x0007 },
3315 { 0x1e, 0x0078 },
3316 { 0x17, 0x0000 },
3317 { 0x19, 0x00aa },
3318 { 0x1f, 0x0000 },
3319
3320 /* Modify green table for 10M */
3321 { 0x1f, 0x0005 },
3322 { 0x05, 0x8b79 },
3323 { 0x06, 0xaa00 },
3324 { 0x1f, 0x0000 },
3325
3326 /* Disable hiimpedance detection (RTCT) */
3327 { 0x1f, 0x0003 },
3328 { 0x01, 0x328a },
3329 { 0x1f, 0x0000 }
3330 };
3331
3332
3333 rtl_apply_firmware(tp);
3334
3335 rtl8168f_hw_phy_config(tp);
3336
3337 /* Improve 2-pair detection performance */
3338 rtl_writephy(tp, 0x1f, 0x0005);
3339 rtl_writephy(tp, 0x05, 0x8b85);
3340 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3341 rtl_writephy(tp, 0x1f, 0x0000);
3342
3343 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3344
3345 /* Modify green table for giga */
3346 rtl_writephy(tp, 0x1f, 0x0005);
3347 rtl_writephy(tp, 0x05, 0x8b54);
3348 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3349 rtl_writephy(tp, 0x05, 0x8b5d);
3350 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3351 rtl_writephy(tp, 0x05, 0x8a7c);
3352 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3353 rtl_writephy(tp, 0x05, 0x8a7f);
3354 rtl_w1w0_phy(tp, 0x06, 0x0100, 0x0000);
3355 rtl_writephy(tp, 0x05, 0x8a82);
3356 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3357 rtl_writephy(tp, 0x05, 0x8a85);
3358 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3359 rtl_writephy(tp, 0x05, 0x8a88);
3360 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3361 rtl_writephy(tp, 0x1f, 0x0000);
3362
3363 /* uc same-seed solution */
3364 rtl_writephy(tp, 0x1f, 0x0005);
3365 rtl_writephy(tp, 0x05, 0x8b85);
3366 rtl_w1w0_phy(tp, 0x06, 0x8000, 0x0000);
3367 rtl_writephy(tp, 0x1f, 0x0000);
3368
3369 /* eee setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003370 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x00, 0x03, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003371 rtl_writephy(tp, 0x1f, 0x0005);
3372 rtl_writephy(tp, 0x05, 0x8b85);
3373 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3374 rtl_writephy(tp, 0x1f, 0x0004);
3375 rtl_writephy(tp, 0x1f, 0x0007);
3376 rtl_writephy(tp, 0x1e, 0x0020);
3377 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
3378 rtl_writephy(tp, 0x1f, 0x0000);
3379 rtl_writephy(tp, 0x0d, 0x0007);
3380 rtl_writephy(tp, 0x0e, 0x003c);
3381 rtl_writephy(tp, 0x0d, 0x4007);
3382 rtl_writephy(tp, 0x0e, 0x0000);
3383 rtl_writephy(tp, 0x0d, 0x0000);
3384
3385 /* Green feature */
3386 rtl_writephy(tp, 0x1f, 0x0003);
3387 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3388 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3389 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003390
3391 r8168_aldps_enable_1(tp);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003392}
3393
Hayes Wangc5583862012-07-02 17:23:22 +08003394static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
3395{
3396 static const u16 mac_ocp_patch[] = {
3397 0xe008, 0xe01b, 0xe01d, 0xe01f,
3398 0xe021, 0xe023, 0xe025, 0xe027,
3399 0x49d2, 0xf10d, 0x766c, 0x49e2,
3400 0xf00a, 0x1ec0, 0x8ee1, 0xc60a,
3401
3402 0x77c0, 0x4870, 0x9fc0, 0x1ea0,
3403 0xc707, 0x8ee1, 0x9d6c, 0xc603,
3404 0xbe00, 0xb416, 0x0076, 0xe86c,
3405 0xc602, 0xbe00, 0x0000, 0xc602,
3406
3407 0xbe00, 0x0000, 0xc602, 0xbe00,
3408 0x0000, 0xc602, 0xbe00, 0x0000,
3409 0xc602, 0xbe00, 0x0000, 0xc602,
3410 0xbe00, 0x0000, 0xc602, 0xbe00,
3411
3412 0x0000, 0x0000, 0x0000, 0x0000
3413 };
3414 u32 i;
3415
3416 /* Patch code for GPHY reset */
3417 for (i = 0; i < ARRAY_SIZE(mac_ocp_patch); i++)
3418 r8168_mac_ocp_write(tp, 0xf800 + 2*i, mac_ocp_patch[i]);
3419 r8168_mac_ocp_write(tp, 0xfc26, 0x8000);
3420 r8168_mac_ocp_write(tp, 0xfc28, 0x0075);
3421
3422 rtl_apply_firmware(tp);
3423
3424 if (r8168_phy_ocp_read(tp, 0xa460) & 0x0100)
3425 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x8000);
3426 else
3427 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x8000, 0x0000);
3428
3429 if (r8168_phy_ocp_read(tp, 0xa466) & 0x0100)
3430 rtl_w1w0_phy_ocp(tp, 0xc41a, 0x0002, 0x0000);
3431 else
3432 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x0002);
3433
3434 rtl_w1w0_phy_ocp(tp, 0xa442, 0x000c, 0x0000);
3435 rtl_w1w0_phy_ocp(tp, 0xa4b2, 0x0004, 0x0000);
3436
3437 r8168_phy_ocp_write(tp, 0xa436, 0x8012);
3438 rtl_w1w0_phy_ocp(tp, 0xa438, 0x8000, 0x0000);
3439
3440 rtl_w1w0_phy_ocp(tp, 0xc422, 0x4000, 0x2000);
3441}
3442
françois romieu4da19632011-01-03 15:07:55 +00003443static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02003444{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08003445 static const struct phy_reg phy_reg_init[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02003446 { 0x1f, 0x0003 },
3447 { 0x08, 0x441d },
3448 { 0x01, 0x9100 },
3449 { 0x1f, 0x0000 }
3450 };
3451
françois romieu4da19632011-01-03 15:07:55 +00003452 rtl_writephy(tp, 0x1f, 0x0000);
3453 rtl_patchphy(tp, 0x11, 1 << 12);
3454 rtl_patchphy(tp, 0x19, 1 << 13);
3455 rtl_patchphy(tp, 0x10, 1 << 15);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003456
françois romieu4da19632011-01-03 15:07:55 +00003457 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu2857ffb2008-08-02 21:08:49 +02003458}
3459
Hayes Wang5a5e4442011-02-22 17:26:21 +08003460static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
3461{
3462 static const struct phy_reg phy_reg_init[] = {
3463 { 0x1f, 0x0005 },
3464 { 0x1a, 0x0000 },
3465 { 0x1f, 0x0000 },
3466
3467 { 0x1f, 0x0004 },
3468 { 0x1c, 0x0000 },
3469 { 0x1f, 0x0000 },
3470
3471 { 0x1f, 0x0001 },
3472 { 0x15, 0x7701 },
3473 { 0x1f, 0x0000 }
3474 };
3475
3476 /* Disable ALDPS before ram code */
hayeswange0c07552012-10-23 20:24:03 +00003477 r810x_aldps_disable(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003478
François Romieu953a12c2011-04-24 17:38:48 +02003479 rtl_apply_firmware(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003480
3481 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
hayeswange0c07552012-10-23 20:24:03 +00003482
3483 r810x_aldps_enable(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003484}
3485
Hayes Wang7e18dca2012-03-30 14:33:02 +08003486static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
3487{
Hayes Wang7e18dca2012-03-30 14:33:02 +08003488 /* Disable ALDPS before setting firmware */
hayeswange0c07552012-10-23 20:24:03 +00003489 r810x_aldps_disable(tp);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003490
3491 rtl_apply_firmware(tp);
3492
3493 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003494 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003495 rtl_writephy(tp, 0x1f, 0x0004);
3496 rtl_writephy(tp, 0x10, 0x401f);
3497 rtl_writephy(tp, 0x19, 0x7030);
3498 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003499
3500 r810x_aldps_enable(tp);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003501}
3502
Hayes Wang5598bfe2012-07-02 17:23:21 +08003503static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
3504{
Hayes Wang5598bfe2012-07-02 17:23:21 +08003505 static const struct phy_reg phy_reg_init[] = {
3506 { 0x1f, 0x0004 },
3507 { 0x10, 0xc07f },
3508 { 0x19, 0x7030 },
3509 { 0x1f, 0x0000 }
3510 };
3511
3512 /* Disable ALDPS before ram code */
hayeswange0c07552012-10-23 20:24:03 +00003513 r810x_aldps_disable(tp);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003514
3515 rtl_apply_firmware(tp);
3516
Francois Romieufdf6fc02012-07-06 22:40:38 +02003517 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003518 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3519
Francois Romieufdf6fc02012-07-06 22:40:38 +02003520 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
hayeswange0c07552012-10-23 20:24:03 +00003521
3522 r810x_aldps_enable(tp);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003523}
3524
Francois Romieu5615d9f2007-08-17 17:50:46 +02003525static void rtl_hw_phy_config(struct net_device *dev)
3526{
3527 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003528
3529 rtl8169_print_mac_version(tp);
3530
3531 switch (tp->mac_version) {
3532 case RTL_GIGA_MAC_VER_01:
3533 break;
3534 case RTL_GIGA_MAC_VER_02:
3535 case RTL_GIGA_MAC_VER_03:
françois romieu4da19632011-01-03 15:07:55 +00003536 rtl8169s_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003537 break;
3538 case RTL_GIGA_MAC_VER_04:
françois romieu4da19632011-01-03 15:07:55 +00003539 rtl8169sb_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003540 break;
françois romieu2e9558562009-08-10 19:44:19 +00003541 case RTL_GIGA_MAC_VER_05:
françois romieu4da19632011-01-03 15:07:55 +00003542 rtl8169scd_hw_phy_config(tp);
françois romieu2e9558562009-08-10 19:44:19 +00003543 break;
françois romieu8c7006a2009-08-10 19:43:29 +00003544 case RTL_GIGA_MAC_VER_06:
françois romieu4da19632011-01-03 15:07:55 +00003545 rtl8169sce_hw_phy_config(tp);
françois romieu8c7006a2009-08-10 19:43:29 +00003546 break;
Francois Romieu2857ffb2008-08-02 21:08:49 +02003547 case RTL_GIGA_MAC_VER_07:
3548 case RTL_GIGA_MAC_VER_08:
3549 case RTL_GIGA_MAC_VER_09:
françois romieu4da19632011-01-03 15:07:55 +00003550 rtl8102e_hw_phy_config(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003551 break;
Francois Romieu236b8082008-05-30 16:11:48 +02003552 case RTL_GIGA_MAC_VER_11:
françois romieu4da19632011-01-03 15:07:55 +00003553 rtl8168bb_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003554 break;
3555 case RTL_GIGA_MAC_VER_12:
françois romieu4da19632011-01-03 15:07:55 +00003556 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003557 break;
3558 case RTL_GIGA_MAC_VER_17:
françois romieu4da19632011-01-03 15:07:55 +00003559 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003560 break;
Francois Romieu867763c2007-08-17 18:21:58 +02003561 case RTL_GIGA_MAC_VER_18:
françois romieu4da19632011-01-03 15:07:55 +00003562 rtl8168cp_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003563 break;
3564 case RTL_GIGA_MAC_VER_19:
françois romieu4da19632011-01-03 15:07:55 +00003565 rtl8168c_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003566 break;
Francois Romieu7da97ec2007-10-18 15:20:43 +02003567 case RTL_GIGA_MAC_VER_20:
françois romieu4da19632011-01-03 15:07:55 +00003568 rtl8168c_2_hw_phy_config(tp);
Francois Romieu7da97ec2007-10-18 15:20:43 +02003569 break;
Francois Romieu197ff762008-06-28 13:16:02 +02003570 case RTL_GIGA_MAC_VER_21:
françois romieu4da19632011-01-03 15:07:55 +00003571 rtl8168c_3_hw_phy_config(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02003572 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02003573 case RTL_GIGA_MAC_VER_22:
françois romieu4da19632011-01-03 15:07:55 +00003574 rtl8168c_4_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02003575 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003576 case RTL_GIGA_MAC_VER_23:
Francois Romieu7f3e3d32008-07-20 18:53:20 +02003577 case RTL_GIGA_MAC_VER_24:
françois romieu4da19632011-01-03 15:07:55 +00003578 rtl8168cp_2_hw_phy_config(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02003579 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02003580 case RTL_GIGA_MAC_VER_25:
françois romieubca03d52011-01-03 15:07:31 +00003581 rtl8168d_1_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003582 break;
3583 case RTL_GIGA_MAC_VER_26:
françois romieubca03d52011-01-03 15:07:31 +00003584 rtl8168d_2_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003585 break;
3586 case RTL_GIGA_MAC_VER_27:
françois romieu4da19632011-01-03 15:07:55 +00003587 rtl8168d_3_hw_phy_config(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02003588 break;
françois romieue6de30d2011-01-03 15:08:37 +00003589 case RTL_GIGA_MAC_VER_28:
3590 rtl8168d_4_hw_phy_config(tp);
3591 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08003592 case RTL_GIGA_MAC_VER_29:
3593 case RTL_GIGA_MAC_VER_30:
3594 rtl8105e_hw_phy_config(tp);
3595 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02003596 case RTL_GIGA_MAC_VER_31:
3597 /* None. */
3598 break;
hayeswang01dc7fe2011-03-21 01:50:28 +00003599 case RTL_GIGA_MAC_VER_32:
hayeswang01dc7fe2011-03-21 01:50:28 +00003600 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08003601 rtl8168e_1_hw_phy_config(tp);
3602 break;
3603 case RTL_GIGA_MAC_VER_34:
3604 rtl8168e_2_hw_phy_config(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00003605 break;
Hayes Wangc2218922011-09-06 16:55:18 +08003606 case RTL_GIGA_MAC_VER_35:
3607 rtl8168f_1_hw_phy_config(tp);
3608 break;
3609 case RTL_GIGA_MAC_VER_36:
3610 rtl8168f_2_hw_phy_config(tp);
3611 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003612
Hayes Wang7e18dca2012-03-30 14:33:02 +08003613 case RTL_GIGA_MAC_VER_37:
3614 rtl8402_hw_phy_config(tp);
3615 break;
3616
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003617 case RTL_GIGA_MAC_VER_38:
3618 rtl8411_hw_phy_config(tp);
3619 break;
3620
Hayes Wang5598bfe2012-07-02 17:23:21 +08003621 case RTL_GIGA_MAC_VER_39:
3622 rtl8106e_hw_phy_config(tp);
3623 break;
3624
Hayes Wangc5583862012-07-02 17:23:22 +08003625 case RTL_GIGA_MAC_VER_40:
3626 rtl8168g_1_hw_phy_config(tp);
3627 break;
3628
3629 case RTL_GIGA_MAC_VER_41:
Francois Romieu5615d9f2007-08-17 17:50:46 +02003630 default:
3631 break;
3632 }
3633}
3634
Francois Romieuda78dbf2012-01-26 14:18:23 +01003635static void rtl_phy_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637 struct timer_list *timer = &tp->timer;
3638 void __iomem *ioaddr = tp->mmio_addr;
3639 unsigned long timeout = RTL8169_PHY_TIMEOUT;
3640
Francois Romieubcf0bf92006-07-26 23:14:13 +02003641 assert(tp->mac_version > RTL_GIGA_MAC_VER_01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642
françois romieu4da19632011-01-03 15:07:55 +00003643 if (tp->phy_reset_pending(tp)) {
Francois Romieu5b0384f2006-08-16 16:00:01 +02003644 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645 * A busy loop could burn quite a few cycles on nowadays CPU.
3646 * Let's delay the execution of the timer for a few ticks.
3647 */
3648 timeout = HZ/10;
3649 goto out_mod_timer;
3650 }
3651
3652 if (tp->link_ok(ioaddr))
Francois Romieuda78dbf2012-01-26 14:18:23 +01003653 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654
Francois Romieuda78dbf2012-01-26 14:18:23 +01003655 netif_warn(tp, link, tp->dev, "PHY reset until link up\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656
françois romieu4da19632011-01-03 15:07:55 +00003657 tp->phy_reset_enable(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658
3659out_mod_timer:
3660 mod_timer(timer, jiffies + timeout);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003661}
3662
3663static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag)
3664{
Francois Romieuda78dbf2012-01-26 14:18:23 +01003665 if (!test_and_set_bit(flag, tp->wk.flags))
3666 schedule_work(&tp->wk.work);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003667}
3668
3669static void rtl8169_phy_timer(unsigned long __opaque)
3670{
3671 struct net_device *dev = (struct net_device *)__opaque;
3672 struct rtl8169_private *tp = netdev_priv(dev);
3673
Francois Romieu98ddf982012-01-31 10:47:34 +01003674 rtl_schedule_task(tp, RTL_FLAG_TASK_PHY_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675}
3676
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev,
3678 void __iomem *ioaddr)
3679{
3680 iounmap(ioaddr);
3681 pci_release_regions(pdev);
françois romieu87aeec72010-04-26 11:42:06 +00003682 pci_clear_mwi(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683 pci_disable_device(pdev);
3684 free_netdev(dev);
3685}
3686
Francois Romieuffc46952012-07-06 14:19:23 +02003687DECLARE_RTL_COND(rtl_phy_reset_cond)
3688{
3689 return tp->phy_reset_pending(tp);
3690}
3691
Francois Romieubf793292006-11-01 00:53:05 +01003692static void rtl8169_phy_reset(struct net_device *dev,
3693 struct rtl8169_private *tp)
3694{
françois romieu4da19632011-01-03 15:07:55 +00003695 tp->phy_reset_enable(tp);
Francois Romieuffc46952012-07-06 14:19:23 +02003696 rtl_msleep_loop_wait_low(tp, &rtl_phy_reset_cond, 1, 100);
Francois Romieubf793292006-11-01 00:53:05 +01003697}
3698
David S. Miller8decf862011-09-22 03:23:13 -04003699static bool rtl_tbi_enabled(struct rtl8169_private *tp)
3700{
3701 void __iomem *ioaddr = tp->mmio_addr;
3702
3703 return (tp->mac_version == RTL_GIGA_MAC_VER_01) &&
3704 (RTL_R8(PHYstatus) & TBI_Enable);
3705}
3706
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003707static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708{
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003709 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003710
Francois Romieu5615d9f2007-08-17 17:50:46 +02003711 rtl_hw_phy_config(dev);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003712
Marcus Sundberg773328942008-07-10 21:28:08 +02003713 if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
3714 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3715 RTL_W8(0x82, 0x01);
3716 }
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003717
Francois Romieu6dccd162007-02-13 23:38:05 +01003718 pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
3719
3720 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
3721 pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003722
Francois Romieubcf0bf92006-07-26 23:14:13 +02003723 if (tp->mac_version == RTL_GIGA_MAC_VER_02) {
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003724 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3725 RTL_W8(0x82, 0x01);
3726 dprintk("Set PHY Reg 0x0bh = 0x00h\n");
françois romieu4da19632011-01-03 15:07:55 +00003727 rtl_writephy(tp, 0x0b, 0x0000); //w 0x0b 15 0 0
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003728 }
3729
Francois Romieubf793292006-11-01 00:53:05 +01003730 rtl8169_phy_reset(dev, tp);
3731
Oliver Neukum54405cd2011-01-06 21:55:13 +01003732 rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
Francois Romieucecb5fd2011-04-01 10:21:07 +02003733 ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
3734 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
3735 (tp->mii.supports_gmii ?
3736 ADVERTISED_1000baseT_Half |
3737 ADVERTISED_1000baseT_Full : 0));
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003738
David S. Miller8decf862011-09-22 03:23:13 -04003739 if (rtl_tbi_enabled(tp))
Joe Perchesbf82c182010-02-09 11:49:50 +00003740 netif_info(tp, link, dev, "TBI auto-negotiating\n");
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003741}
3742
Francois Romieu773d2022007-01-31 23:47:43 +01003743static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
3744{
3745 void __iomem *ioaddr = tp->mmio_addr;
3746 u32 high;
3747 u32 low;
3748
3749 low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
3750 high = addr[4] | (addr[5] << 8);
3751
Francois Romieuda78dbf2012-01-26 14:18:23 +01003752 rtl_lock_work(tp);
Francois Romieu773d2022007-01-31 23:47:43 +01003753
3754 RTL_W8(Cfg9346, Cfg9346_Unlock);
françois romieu908ba2b2010-04-26 11:42:58 +00003755
Francois Romieu773d2022007-01-31 23:47:43 +01003756 RTL_W32(MAC4, high);
françois romieu908ba2b2010-04-26 11:42:58 +00003757 RTL_R32(MAC4);
3758
Francois Romieu78f1cd02010-03-27 19:35:46 -07003759 RTL_W32(MAC0, low);
françois romieu908ba2b2010-04-26 11:42:58 +00003760 RTL_R32(MAC0);
3761
françois romieuc28aa382011-08-02 03:53:43 +00003762 if (tp->mac_version == RTL_GIGA_MAC_VER_34) {
3763 const struct exgmac_reg e[] = {
3764 { .addr = 0xe0, ERIAR_MASK_1111, .val = low },
3765 { .addr = 0xe4, ERIAR_MASK_1111, .val = high },
3766 { .addr = 0xf0, ERIAR_MASK_1111, .val = low << 16 },
3767 { .addr = 0xf4, ERIAR_MASK_1111, .val = high << 16 |
3768 low >> 16 },
3769 };
3770
Francois Romieufdf6fc02012-07-06 22:40:38 +02003771 rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e));
françois romieuc28aa382011-08-02 03:53:43 +00003772 }
3773
Francois Romieu773d2022007-01-31 23:47:43 +01003774 RTL_W8(Cfg9346, Cfg9346_Lock);
3775
Francois Romieuda78dbf2012-01-26 14:18:23 +01003776 rtl_unlock_work(tp);
Francois Romieu773d2022007-01-31 23:47:43 +01003777}
3778
3779static int rtl_set_mac_address(struct net_device *dev, void *p)
3780{
3781 struct rtl8169_private *tp = netdev_priv(dev);
3782 struct sockaddr *addr = p;
3783
3784 if (!is_valid_ether_addr(addr->sa_data))
3785 return -EADDRNOTAVAIL;
3786
3787 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
3788
3789 rtl_rar_set(tp, dev->dev_addr);
3790
3791 return 0;
3792}
3793
Francois Romieu5f787a12006-08-17 13:02:36 +02003794static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
3795{
3796 struct rtl8169_private *tp = netdev_priv(dev);
3797 struct mii_ioctl_data *data = if_mii(ifr);
3798
Francois Romieu8b4ab282008-11-19 22:05:25 -08003799 return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV;
3800}
Francois Romieu5f787a12006-08-17 13:02:36 +02003801
Francois Romieucecb5fd2011-04-01 10:21:07 +02003802static int rtl_xmii_ioctl(struct rtl8169_private *tp,
3803 struct mii_ioctl_data *data, int cmd)
Francois Romieu8b4ab282008-11-19 22:05:25 -08003804{
Francois Romieu5f787a12006-08-17 13:02:36 +02003805 switch (cmd) {
3806 case SIOCGMIIPHY:
3807 data->phy_id = 32; /* Internal PHY */
3808 return 0;
3809
3810 case SIOCGMIIREG:
françois romieu4da19632011-01-03 15:07:55 +00003811 data->val_out = rtl_readphy(tp, data->reg_num & 0x1f);
Francois Romieu5f787a12006-08-17 13:02:36 +02003812 return 0;
3813
3814 case SIOCSMIIREG:
françois romieu4da19632011-01-03 15:07:55 +00003815 rtl_writephy(tp, data->reg_num & 0x1f, data->val_in);
Francois Romieu5f787a12006-08-17 13:02:36 +02003816 return 0;
3817 }
3818 return -EOPNOTSUPP;
3819}
3820
Francois Romieu8b4ab282008-11-19 22:05:25 -08003821static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd)
3822{
3823 return -EOPNOTSUPP;
3824}
3825
Francois Romieufbac58f2007-10-04 22:51:38 +02003826static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
3827{
3828 if (tp->features & RTL_FEATURE_MSI) {
3829 pci_disable_msi(pdev);
3830 tp->features &= ~RTL_FEATURE_MSI;
3831 }
3832}
3833
françois romieuc0e45c12011-01-03 15:08:04 +00003834static void __devinit rtl_init_mdio_ops(struct rtl8169_private *tp)
3835{
3836 struct mdio_ops *ops = &tp->mdio_ops;
3837
3838 switch (tp->mac_version) {
3839 case RTL_GIGA_MAC_VER_27:
3840 ops->write = r8168dp_1_mdio_write;
3841 ops->read = r8168dp_1_mdio_read;
3842 break;
françois romieue6de30d2011-01-03 15:08:37 +00003843 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00003844 case RTL_GIGA_MAC_VER_31:
françois romieue6de30d2011-01-03 15:08:37 +00003845 ops->write = r8168dp_2_mdio_write;
3846 ops->read = r8168dp_2_mdio_read;
3847 break;
Hayes Wangc5583862012-07-02 17:23:22 +08003848 case RTL_GIGA_MAC_VER_40:
3849 case RTL_GIGA_MAC_VER_41:
3850 ops->write = r8168g_mdio_write;
3851 ops->read = r8168g_mdio_read;
3852 break;
françois romieuc0e45c12011-01-03 15:08:04 +00003853 default:
3854 ops->write = r8169_mdio_write;
3855 ops->read = r8169_mdio_read;
3856 break;
3857 }
3858}
3859
David S. Miller1805b2f2011-10-24 18:18:09 -04003860static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
3861{
3862 void __iomem *ioaddr = tp->mmio_addr;
3863
3864 switch (tp->mac_version) {
3865 case RTL_GIGA_MAC_VER_29:
3866 case RTL_GIGA_MAC_VER_30:
3867 case RTL_GIGA_MAC_VER_32:
3868 case RTL_GIGA_MAC_VER_33:
3869 case RTL_GIGA_MAC_VER_34:
Hayes Wang7e18dca2012-03-30 14:33:02 +08003870 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003871 case RTL_GIGA_MAC_VER_38:
Hayes Wang5598bfe2012-07-02 17:23:21 +08003872 case RTL_GIGA_MAC_VER_39:
Hayes Wangc5583862012-07-02 17:23:22 +08003873 case RTL_GIGA_MAC_VER_40:
3874 case RTL_GIGA_MAC_VER_41:
David S. Miller1805b2f2011-10-24 18:18:09 -04003875 RTL_W32(RxConfig, RTL_R32(RxConfig) |
3876 AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
3877 break;
3878 default:
3879 break;
3880 }
3881}
3882
3883static bool rtl_wol_pll_power_down(struct rtl8169_private *tp)
3884{
3885 if (!(__rtl8169_get_wol(tp) & WAKE_ANY))
3886 return false;
3887
3888 rtl_writephy(tp, 0x1f, 0x0000);
3889 rtl_writephy(tp, MII_BMCR, 0x0000);
3890
3891 rtl_wol_suspend_quirk(tp);
3892
3893 return true;
3894}
3895
françois romieu065c27c2011-01-03 15:08:12 +00003896static void r810x_phy_power_down(struct rtl8169_private *tp)
3897{
3898 rtl_writephy(tp, 0x1f, 0x0000);
3899 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
3900}
3901
3902static void r810x_phy_power_up(struct rtl8169_private *tp)
3903{
3904 rtl_writephy(tp, 0x1f, 0x0000);
3905 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
3906}
3907
3908static void r810x_pll_power_down(struct rtl8169_private *tp)
3909{
Hayes Wang00042992012-03-30 14:33:00 +08003910 void __iomem *ioaddr = tp->mmio_addr;
3911
David S. Miller1805b2f2011-10-24 18:18:09 -04003912 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00003913 return;
françois romieu065c27c2011-01-03 15:08:12 +00003914
3915 r810x_phy_power_down(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003916
3917 switch (tp->mac_version) {
3918 case RTL_GIGA_MAC_VER_07:
3919 case RTL_GIGA_MAC_VER_08:
3920 case RTL_GIGA_MAC_VER_09:
3921 case RTL_GIGA_MAC_VER_10:
3922 case RTL_GIGA_MAC_VER_13:
3923 case RTL_GIGA_MAC_VER_16:
3924 break;
3925 default:
3926 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
3927 break;
3928 }
françois romieu065c27c2011-01-03 15:08:12 +00003929}
3930
3931static void r810x_pll_power_up(struct rtl8169_private *tp)
3932{
Hayes Wang00042992012-03-30 14:33:00 +08003933 void __iomem *ioaddr = tp->mmio_addr;
3934
françois romieu065c27c2011-01-03 15:08:12 +00003935 r810x_phy_power_up(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003936
3937 switch (tp->mac_version) {
3938 case RTL_GIGA_MAC_VER_07:
3939 case RTL_GIGA_MAC_VER_08:
3940 case RTL_GIGA_MAC_VER_09:
3941 case RTL_GIGA_MAC_VER_10:
3942 case RTL_GIGA_MAC_VER_13:
3943 case RTL_GIGA_MAC_VER_16:
3944 break;
3945 default:
3946 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
3947 break;
3948 }
françois romieu065c27c2011-01-03 15:08:12 +00003949}
3950
3951static void r8168_phy_power_up(struct rtl8169_private *tp)
3952{
3953 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003954 switch (tp->mac_version) {
3955 case RTL_GIGA_MAC_VER_11:
3956 case RTL_GIGA_MAC_VER_12:
3957 case RTL_GIGA_MAC_VER_17:
3958 case RTL_GIGA_MAC_VER_18:
3959 case RTL_GIGA_MAC_VER_19:
3960 case RTL_GIGA_MAC_VER_20:
3961 case RTL_GIGA_MAC_VER_21:
3962 case RTL_GIGA_MAC_VER_22:
3963 case RTL_GIGA_MAC_VER_23:
3964 case RTL_GIGA_MAC_VER_24:
3965 case RTL_GIGA_MAC_VER_25:
3966 case RTL_GIGA_MAC_VER_26:
3967 case RTL_GIGA_MAC_VER_27:
3968 case RTL_GIGA_MAC_VER_28:
3969 case RTL_GIGA_MAC_VER_31:
3970 rtl_writephy(tp, 0x0e, 0x0000);
3971 break;
3972 default:
3973 break;
3974 }
françois romieu065c27c2011-01-03 15:08:12 +00003975 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
3976}
3977
3978static void r8168_phy_power_down(struct rtl8169_private *tp)
3979{
3980 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003981 switch (tp->mac_version) {
3982 case RTL_GIGA_MAC_VER_32:
3983 case RTL_GIGA_MAC_VER_33:
3984 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN);
3985 break;
3986
3987 case RTL_GIGA_MAC_VER_11:
3988 case RTL_GIGA_MAC_VER_12:
3989 case RTL_GIGA_MAC_VER_17:
3990 case RTL_GIGA_MAC_VER_18:
3991 case RTL_GIGA_MAC_VER_19:
3992 case RTL_GIGA_MAC_VER_20:
3993 case RTL_GIGA_MAC_VER_21:
3994 case RTL_GIGA_MAC_VER_22:
3995 case RTL_GIGA_MAC_VER_23:
3996 case RTL_GIGA_MAC_VER_24:
3997 case RTL_GIGA_MAC_VER_25:
3998 case RTL_GIGA_MAC_VER_26:
3999 case RTL_GIGA_MAC_VER_27:
4000 case RTL_GIGA_MAC_VER_28:
4001 case RTL_GIGA_MAC_VER_31:
4002 rtl_writephy(tp, 0x0e, 0x0200);
4003 default:
4004 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
4005 break;
4006 }
françois romieu065c27c2011-01-03 15:08:12 +00004007}
4008
4009static void r8168_pll_power_down(struct rtl8169_private *tp)
4010{
4011 void __iomem *ioaddr = tp->mmio_addr;
4012
Francois Romieucecb5fd2011-04-01 10:21:07 +02004013 if ((tp->mac_version == RTL_GIGA_MAC_VER_27 ||
4014 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
4015 tp->mac_version == RTL_GIGA_MAC_VER_31) &&
hayeswang4804b3b2011-03-21 01:50:29 +00004016 r8168dp_check_dash(tp)) {
françois romieu065c27c2011-01-03 15:08:12 +00004017 return;
Hayes Wang5d2e1952011-02-22 17:26:22 +08004018 }
françois romieu065c27c2011-01-03 15:08:12 +00004019
Francois Romieucecb5fd2011-04-01 10:21:07 +02004020 if ((tp->mac_version == RTL_GIGA_MAC_VER_23 ||
4021 tp->mac_version == RTL_GIGA_MAC_VER_24) &&
françois romieu065c27c2011-01-03 15:08:12 +00004022 (RTL_R16(CPlusCmd) & ASF)) {
4023 return;
4024 }
4025
hayeswang01dc7fe2011-03-21 01:50:28 +00004026 if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
4027 tp->mac_version == RTL_GIGA_MAC_VER_33)
Francois Romieufdf6fc02012-07-06 22:40:38 +02004028 rtl_ephy_write(tp, 0x19, 0xff64);
hayeswang01dc7fe2011-03-21 01:50:28 +00004029
David S. Miller1805b2f2011-10-24 18:18:09 -04004030 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00004031 return;
françois romieu065c27c2011-01-03 15:08:12 +00004032
4033 r8168_phy_power_down(tp);
4034
4035 switch (tp->mac_version) {
4036 case RTL_GIGA_MAC_VER_25:
4037 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004038 case RTL_GIGA_MAC_VER_27:
4039 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004040 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004041 case RTL_GIGA_MAC_VER_32:
4042 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004043 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
4044 break;
4045 }
4046}
4047
4048static void r8168_pll_power_up(struct rtl8169_private *tp)
4049{
4050 void __iomem *ioaddr = tp->mmio_addr;
4051
françois romieu065c27c2011-01-03 15:08:12 +00004052 switch (tp->mac_version) {
4053 case RTL_GIGA_MAC_VER_25:
4054 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004055 case RTL_GIGA_MAC_VER_27:
4056 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004057 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004058 case RTL_GIGA_MAC_VER_32:
4059 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004060 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
4061 break;
4062 }
4063
4064 r8168_phy_power_up(tp);
4065}
4066
Francois Romieud58d46b2011-05-03 16:38:29 +02004067static void rtl_generic_op(struct rtl8169_private *tp,
4068 void (*op)(struct rtl8169_private *))
françois romieu065c27c2011-01-03 15:08:12 +00004069{
4070 if (op)
4071 op(tp);
4072}
4073
4074static void rtl_pll_power_down(struct rtl8169_private *tp)
4075{
Francois Romieud58d46b2011-05-03 16:38:29 +02004076 rtl_generic_op(tp, tp->pll_power_ops.down);
françois romieu065c27c2011-01-03 15:08:12 +00004077}
4078
4079static void rtl_pll_power_up(struct rtl8169_private *tp)
4080{
Francois Romieud58d46b2011-05-03 16:38:29 +02004081 rtl_generic_op(tp, tp->pll_power_ops.up);
françois romieu065c27c2011-01-03 15:08:12 +00004082}
4083
4084static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
4085{
4086 struct pll_power_ops *ops = &tp->pll_power_ops;
4087
4088 switch (tp->mac_version) {
4089 case RTL_GIGA_MAC_VER_07:
4090 case RTL_GIGA_MAC_VER_08:
4091 case RTL_GIGA_MAC_VER_09:
4092 case RTL_GIGA_MAC_VER_10:
4093 case RTL_GIGA_MAC_VER_16:
Hayes Wang5a5e4442011-02-22 17:26:21 +08004094 case RTL_GIGA_MAC_VER_29:
4095 case RTL_GIGA_MAC_VER_30:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004096 case RTL_GIGA_MAC_VER_37:
Hayes Wang5598bfe2012-07-02 17:23:21 +08004097 case RTL_GIGA_MAC_VER_39:
françois romieu065c27c2011-01-03 15:08:12 +00004098 ops->down = r810x_pll_power_down;
4099 ops->up = r810x_pll_power_up;
4100 break;
4101
4102 case RTL_GIGA_MAC_VER_11:
4103 case RTL_GIGA_MAC_VER_12:
4104 case RTL_GIGA_MAC_VER_17:
4105 case RTL_GIGA_MAC_VER_18:
4106 case RTL_GIGA_MAC_VER_19:
4107 case RTL_GIGA_MAC_VER_20:
4108 case RTL_GIGA_MAC_VER_21:
4109 case RTL_GIGA_MAC_VER_22:
4110 case RTL_GIGA_MAC_VER_23:
4111 case RTL_GIGA_MAC_VER_24:
4112 case RTL_GIGA_MAC_VER_25:
4113 case RTL_GIGA_MAC_VER_26:
4114 case RTL_GIGA_MAC_VER_27:
françois romieue6de30d2011-01-03 15:08:37 +00004115 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004116 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004117 case RTL_GIGA_MAC_VER_32:
4118 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08004119 case RTL_GIGA_MAC_VER_34:
Hayes Wangc2218922011-09-06 16:55:18 +08004120 case RTL_GIGA_MAC_VER_35:
4121 case RTL_GIGA_MAC_VER_36:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004122 case RTL_GIGA_MAC_VER_38:
Hayes Wangc5583862012-07-02 17:23:22 +08004123 case RTL_GIGA_MAC_VER_40:
4124 case RTL_GIGA_MAC_VER_41:
françois romieu065c27c2011-01-03 15:08:12 +00004125 ops->down = r8168_pll_power_down;
4126 ops->up = r8168_pll_power_up;
4127 break;
4128
4129 default:
4130 ops->down = NULL;
4131 ops->up = NULL;
4132 break;
4133 }
4134}
4135
Hayes Wange542a222011-07-06 15:58:04 +08004136static void rtl_init_rxcfg(struct rtl8169_private *tp)
4137{
4138 void __iomem *ioaddr = tp->mmio_addr;
4139
4140 switch (tp->mac_version) {
4141 case RTL_GIGA_MAC_VER_01:
4142 case RTL_GIGA_MAC_VER_02:
4143 case RTL_GIGA_MAC_VER_03:
4144 case RTL_GIGA_MAC_VER_04:
4145 case RTL_GIGA_MAC_VER_05:
4146 case RTL_GIGA_MAC_VER_06:
4147 case RTL_GIGA_MAC_VER_10:
4148 case RTL_GIGA_MAC_VER_11:
4149 case RTL_GIGA_MAC_VER_12:
4150 case RTL_GIGA_MAC_VER_13:
4151 case RTL_GIGA_MAC_VER_14:
4152 case RTL_GIGA_MAC_VER_15:
4153 case RTL_GIGA_MAC_VER_16:
4154 case RTL_GIGA_MAC_VER_17:
4155 RTL_W32(RxConfig, RX_FIFO_THRESH | RX_DMA_BURST);
4156 break;
4157 case RTL_GIGA_MAC_VER_18:
4158 case RTL_GIGA_MAC_VER_19:
4159 case RTL_GIGA_MAC_VER_20:
4160 case RTL_GIGA_MAC_VER_21:
4161 case RTL_GIGA_MAC_VER_22:
4162 case RTL_GIGA_MAC_VER_23:
4163 case RTL_GIGA_MAC_VER_24:
françois romieueb2dc352012-06-20 12:09:18 +00004164 case RTL_GIGA_MAC_VER_34:
Hayes Wange542a222011-07-06 15:58:04 +08004165 RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
4166 break;
4167 default:
4168 RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST);
4169 break;
4170 }
4171}
4172
Hayes Wang92fc43b2011-07-06 15:58:03 +08004173static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
4174{
4175 tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
4176}
4177
Francois Romieud58d46b2011-05-03 16:38:29 +02004178static void rtl_hw_jumbo_enable(struct rtl8169_private *tp)
4179{
françois romieu9c5028e2012-03-02 04:43:14 +00004180 void __iomem *ioaddr = tp->mmio_addr;
4181
4182 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004183 rtl_generic_op(tp, tp->jumbo_ops.enable);
françois romieu9c5028e2012-03-02 04:43:14 +00004184 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004185}
4186
4187static void rtl_hw_jumbo_disable(struct rtl8169_private *tp)
4188{
françois romieu9c5028e2012-03-02 04:43:14 +00004189 void __iomem *ioaddr = tp->mmio_addr;
4190
4191 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004192 rtl_generic_op(tp, tp->jumbo_ops.disable);
françois romieu9c5028e2012-03-02 04:43:14 +00004193 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004194}
4195
4196static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp)
4197{
4198 void __iomem *ioaddr = tp->mmio_addr;
4199
4200 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4201 RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1);
4202 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
4203}
4204
4205static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
4206{
4207 void __iomem *ioaddr = tp->mmio_addr;
4208
4209 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4210 RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1);
4211 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
4212}
4213
4214static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp)
4215{
4216 void __iomem *ioaddr = tp->mmio_addr;
4217
4218 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4219}
4220
4221static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
4222{
4223 void __iomem *ioaddr = tp->mmio_addr;
4224
4225 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4226}
4227
4228static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
4229{
4230 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004231
4232 RTL_W8(MaxTxPacketSize, 0x3f);
4233 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4234 RTL_W8(Config4, RTL_R8(Config4) | 0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004235 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004236}
4237
4238static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
4239{
4240 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004241
4242 RTL_W8(MaxTxPacketSize, 0x0c);
4243 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4244 RTL_W8(Config4, RTL_R8(Config4) & ~0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004245 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004246}
4247
4248static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp)
4249{
4250 rtl_tx_performance_tweak(tp->pci_dev,
4251 (0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4252}
4253
4254static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp)
4255{
4256 rtl_tx_performance_tweak(tp->pci_dev,
4257 (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4258}
4259
4260static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp)
4261{
4262 void __iomem *ioaddr = tp->mmio_addr;
4263
4264 r8168b_0_hw_jumbo_enable(tp);
4265
4266 RTL_W8(Config4, RTL_R8(Config4) | (1 << 0));
4267}
4268
4269static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
4270{
4271 void __iomem *ioaddr = tp->mmio_addr;
4272
4273 r8168b_0_hw_jumbo_disable(tp);
4274
4275 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
4276}
4277
4278static void __devinit rtl_init_jumbo_ops(struct rtl8169_private *tp)
4279{
4280 struct jumbo_ops *ops = &tp->jumbo_ops;
4281
4282 switch (tp->mac_version) {
4283 case RTL_GIGA_MAC_VER_11:
4284 ops->disable = r8168b_0_hw_jumbo_disable;
4285 ops->enable = r8168b_0_hw_jumbo_enable;
4286 break;
4287 case RTL_GIGA_MAC_VER_12:
4288 case RTL_GIGA_MAC_VER_17:
4289 ops->disable = r8168b_1_hw_jumbo_disable;
4290 ops->enable = r8168b_1_hw_jumbo_enable;
4291 break;
4292 case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */
4293 case RTL_GIGA_MAC_VER_19:
4294 case RTL_GIGA_MAC_VER_20:
4295 case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */
4296 case RTL_GIGA_MAC_VER_22:
4297 case RTL_GIGA_MAC_VER_23:
4298 case RTL_GIGA_MAC_VER_24:
4299 case RTL_GIGA_MAC_VER_25:
4300 case RTL_GIGA_MAC_VER_26:
4301 ops->disable = r8168c_hw_jumbo_disable;
4302 ops->enable = r8168c_hw_jumbo_enable;
4303 break;
4304 case RTL_GIGA_MAC_VER_27:
4305 case RTL_GIGA_MAC_VER_28:
4306 ops->disable = r8168dp_hw_jumbo_disable;
4307 ops->enable = r8168dp_hw_jumbo_enable;
4308 break;
4309 case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */
4310 case RTL_GIGA_MAC_VER_32:
4311 case RTL_GIGA_MAC_VER_33:
4312 case RTL_GIGA_MAC_VER_34:
4313 ops->disable = r8168e_hw_jumbo_disable;
4314 ops->enable = r8168e_hw_jumbo_enable;
4315 break;
4316
4317 /*
4318 * No action needed for jumbo frames with 8169.
4319 * No jumbo for 810x at all.
4320 */
Hayes Wangc5583862012-07-02 17:23:22 +08004321 case RTL_GIGA_MAC_VER_40:
4322 case RTL_GIGA_MAC_VER_41:
Francois Romieud58d46b2011-05-03 16:38:29 +02004323 default:
4324 ops->disable = NULL;
4325 ops->enable = NULL;
4326 break;
4327 }
4328}
4329
Francois Romieuffc46952012-07-06 14:19:23 +02004330DECLARE_RTL_COND(rtl_chipcmd_cond)
4331{
4332 void __iomem *ioaddr = tp->mmio_addr;
4333
4334 return RTL_R8(ChipCmd) & CmdReset;
4335}
4336
Francois Romieu6f43adc2011-04-29 15:05:51 +02004337static void rtl_hw_reset(struct rtl8169_private *tp)
4338{
4339 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu6f43adc2011-04-29 15:05:51 +02004340
Francois Romieu6f43adc2011-04-29 15:05:51 +02004341 RTL_W8(ChipCmd, CmdReset);
4342
Francois Romieuffc46952012-07-06 14:19:23 +02004343 rtl_udelay_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100);
Francois Romieu6f43adc2011-04-29 15:05:51 +02004344}
4345
Francois Romieub6ffd972011-06-17 17:00:05 +02004346static void rtl_request_uncached_firmware(struct rtl8169_private *tp)
4347{
4348 struct rtl_fw *rtl_fw;
4349 const char *name;
4350 int rc = -ENOMEM;
4351
4352 name = rtl_lookup_firmware_name(tp);
4353 if (!name)
4354 goto out_no_firmware;
4355
4356 rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL);
4357 if (!rtl_fw)
4358 goto err_warn;
4359
4360 rc = request_firmware(&rtl_fw->fw, name, &tp->pci_dev->dev);
4361 if (rc < 0)
4362 goto err_free;
4363
Francois Romieufd112f22011-06-18 00:10:29 +02004364 rc = rtl_check_firmware(tp, rtl_fw);
4365 if (rc < 0)
4366 goto err_release_firmware;
4367
Francois Romieub6ffd972011-06-17 17:00:05 +02004368 tp->rtl_fw = rtl_fw;
4369out:
4370 return;
4371
Francois Romieufd112f22011-06-18 00:10:29 +02004372err_release_firmware:
4373 release_firmware(rtl_fw->fw);
Francois Romieub6ffd972011-06-17 17:00:05 +02004374err_free:
4375 kfree(rtl_fw);
4376err_warn:
4377 netif_warn(tp, ifup, tp->dev, "unable to load firmware patch %s (%d)\n",
4378 name, rc);
4379out_no_firmware:
4380 tp->rtl_fw = NULL;
4381 goto out;
4382}
4383
François Romieu953a12c2011-04-24 17:38:48 +02004384static void rtl_request_firmware(struct rtl8169_private *tp)
4385{
Francois Romieub6ffd972011-06-17 17:00:05 +02004386 if (IS_ERR(tp->rtl_fw))
4387 rtl_request_uncached_firmware(tp);
François Romieu953a12c2011-04-24 17:38:48 +02004388}
4389
Hayes Wang92fc43b2011-07-06 15:58:03 +08004390static void rtl_rx_close(struct rtl8169_private *tp)
4391{
4392 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang92fc43b2011-07-06 15:58:03 +08004393
Francois Romieu1687b562011-07-19 17:21:29 +02004394 RTL_W32(RxConfig, RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004395}
4396
Francois Romieuffc46952012-07-06 14:19:23 +02004397DECLARE_RTL_COND(rtl_npq_cond)
4398{
4399 void __iomem *ioaddr = tp->mmio_addr;
4400
4401 return RTL_R8(TxPoll) & NPQ;
4402}
4403
4404DECLARE_RTL_COND(rtl_txcfg_empty_cond)
4405{
4406 void __iomem *ioaddr = tp->mmio_addr;
4407
4408 return RTL_R32(TxConfig) & TXCFG_EMPTY;
4409}
4410
françois romieue6de30d2011-01-03 15:08:37 +00004411static void rtl8169_hw_reset(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412{
françois romieue6de30d2011-01-03 15:08:37 +00004413 void __iomem *ioaddr = tp->mmio_addr;
4414
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415 /* Disable interrupts */
françois romieu811fd302011-12-04 20:30:45 +00004416 rtl8169_irq_mask_and_ack(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417
Hayes Wang92fc43b2011-07-06 15:58:03 +08004418 rtl_rx_close(tp);
4419
Hayes Wang5d2e1952011-02-22 17:26:22 +08004420 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
hayeswang4804b3b2011-03-21 01:50:29 +00004421 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
4422 tp->mac_version == RTL_GIGA_MAC_VER_31) {
Francois Romieuffc46952012-07-06 14:19:23 +02004423 rtl_udelay_loop_wait_low(tp, &rtl_npq_cond, 20, 42*42);
Hayes Wangc2218922011-09-06 16:55:18 +08004424 } else if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
4425 tp->mac_version == RTL_GIGA_MAC_VER_35 ||
Hayes Wang7e18dca2012-03-30 14:33:02 +08004426 tp->mac_version == RTL_GIGA_MAC_VER_36 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004427 tp->mac_version == RTL_GIGA_MAC_VER_37 ||
Hayes Wangc5583862012-07-02 17:23:22 +08004428 tp->mac_version == RTL_GIGA_MAC_VER_40 ||
4429 tp->mac_version == RTL_GIGA_MAC_VER_41 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004430 tp->mac_version == RTL_GIGA_MAC_VER_38) {
David S. Miller8decf862011-09-22 03:23:13 -04004431 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
Francois Romieuffc46952012-07-06 14:19:23 +02004432 rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004433 } else {
4434 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
4435 udelay(100);
françois romieue6de30d2011-01-03 15:08:37 +00004436 }
4437
Hayes Wang92fc43b2011-07-06 15:58:03 +08004438 rtl_hw_reset(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439}
4440
Francois Romieu7f796d832007-06-11 23:04:41 +02004441static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004442{
4443 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu9cb427b2006-11-02 00:10:16 +01004444
4445 /* Set DMA burst size and Interframe Gap Time */
4446 RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
4447 (InterFrameGap << TxInterFrameGapShift));
4448}
4449
Francois Romieu07ce4062007-02-23 23:36:39 +01004450static void rtl_hw_start(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451{
4452 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453
Francois Romieu07ce4062007-02-23 23:36:39 +01004454 tp->hw_start(dev);
4455
Francois Romieuda78dbf2012-01-26 14:18:23 +01004456 rtl_irq_enable_all(tp);
Francois Romieu07ce4062007-02-23 23:36:39 +01004457}
4458
Francois Romieu7f796d832007-06-11 23:04:41 +02004459static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp,
4460 void __iomem *ioaddr)
4461{
4462 /*
4463 * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
4464 * register to be written before TxDescAddrLow to work.
4465 * Switching from MMIO to I/O access fixes the issue as well.
4466 */
4467 RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004468 RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004469 RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004470 RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004471}
4472
4473static u16 rtl_rw_cpluscmd(void __iomem *ioaddr)
4474{
4475 u16 cmd;
4476
4477 cmd = RTL_R16(CPlusCmd);
4478 RTL_W16(CPlusCmd, cmd);
4479 return cmd;
4480}
4481
Eric Dumazetfdd7b4c2009-06-09 04:01:02 -07004482static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz)
Francois Romieu7f796d832007-06-11 23:04:41 +02004483{
4484 /* Low hurts. Let's disable the filtering. */
Raimonds Cicans207d6e872009-10-26 10:52:37 +00004485 RTL_W16(RxMaxSize, rx_buf_sz + 1);
Francois Romieu7f796d832007-06-11 23:04:41 +02004486}
4487
Francois Romieu6dccd162007-02-13 23:38:05 +01004488static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
4489{
Francois Romieu37441002011-06-17 22:58:54 +02004490 static const struct rtl_cfg2_info {
Francois Romieu6dccd162007-02-13 23:38:05 +01004491 u32 mac_version;
4492 u32 clk;
4493 u32 val;
4494 } cfg2_info [] = {
4495 { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd
4496 { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff },
4497 { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe
4498 { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff }
Francois Romieu37441002011-06-17 22:58:54 +02004499 };
4500 const struct rtl_cfg2_info *p = cfg2_info;
Francois Romieu6dccd162007-02-13 23:38:05 +01004501 unsigned int i;
4502 u32 clk;
4503
4504 clk = RTL_R8(Config2) & PCI_Clock_66MHz;
Francois Romieucadf1852008-01-03 23:38:38 +01004505 for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) {
Francois Romieu6dccd162007-02-13 23:38:05 +01004506 if ((p->mac_version == mac_version) && (p->clk == clk)) {
4507 RTL_W32(0x7c, p->val);
4508 break;
4509 }
4510 }
4511}
4512
Francois Romieue6b763e2012-03-08 09:35:39 +01004513static void rtl_set_rx_mode(struct net_device *dev)
4514{
4515 struct rtl8169_private *tp = netdev_priv(dev);
4516 void __iomem *ioaddr = tp->mmio_addr;
4517 u32 mc_filter[2]; /* Multicast hash filter */
4518 int rx_mode;
4519 u32 tmp = 0;
4520
4521 if (dev->flags & IFF_PROMISC) {
4522 /* Unconditionally log net taps. */
4523 netif_notice(tp, link, dev, "Promiscuous mode enabled\n");
4524 rx_mode =
4525 AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
4526 AcceptAllPhys;
4527 mc_filter[1] = mc_filter[0] = 0xffffffff;
4528 } else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
4529 (dev->flags & IFF_ALLMULTI)) {
4530 /* Too many to filter perfectly -- accept all multicasts. */
4531 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
4532 mc_filter[1] = mc_filter[0] = 0xffffffff;
4533 } else {
4534 struct netdev_hw_addr *ha;
4535
4536 rx_mode = AcceptBroadcast | AcceptMyPhys;
4537 mc_filter[1] = mc_filter[0] = 0;
4538 netdev_for_each_mc_addr(ha, dev) {
4539 int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
4540 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
4541 rx_mode |= AcceptMulticast;
4542 }
4543 }
4544
4545 if (dev->features & NETIF_F_RXALL)
4546 rx_mode |= (AcceptErr | AcceptRunt);
4547
4548 tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode;
4549
4550 if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
4551 u32 data = mc_filter[0];
4552
4553 mc_filter[0] = swab32(mc_filter[1]);
4554 mc_filter[1] = swab32(data);
4555 }
4556
4557 RTL_W32(MAR0 + 4, mc_filter[1]);
4558 RTL_W32(MAR0 + 0, mc_filter[0]);
4559
4560 RTL_W32(RxConfig, tmp);
4561}
4562
Francois Romieu07ce4062007-02-23 23:36:39 +01004563static void rtl_hw_start_8169(struct net_device *dev)
4564{
4565 struct rtl8169_private *tp = netdev_priv(dev);
4566 void __iomem *ioaddr = tp->mmio_addr;
4567 struct pci_dev *pdev = tp->pci_dev;
Francois Romieu07ce4062007-02-23 23:36:39 +01004568
Francois Romieu9cb427b2006-11-02 00:10:16 +01004569 if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
4570 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
4571 pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
4572 }
4573
Linus Torvalds1da177e2005-04-16 15:20:36 -07004574 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieucecb5fd2011-04-01 10:21:07 +02004575 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4576 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4577 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4578 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004579 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4580
Hayes Wange542a222011-07-06 15:58:04 +08004581 rtl_init_rxcfg(tp);
4582
françois romieuf0298f82011-01-03 15:07:42 +00004583 RTL_W8(EarlyTxThres, NoEarlyTx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004584
Eric Dumazet6f0333b2010-10-11 11:17:47 +00004585 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004586
Francois Romieucecb5fd2011-04-01 10:21:07 +02004587 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4588 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4589 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4590 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieuc946b302007-10-04 00:42:50 +02004591 rtl_set_rx_tx_config_registers(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004592
Francois Romieu7f796d832007-06-11 23:04:41 +02004593 tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
Francois Romieubcf0bf92006-07-26 23:14:13 +02004594
Francois Romieucecb5fd2011-04-01 10:21:07 +02004595 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4596 tp->mac_version == RTL_GIGA_MAC_VER_03) {
Joe Perches06fa7352007-10-18 21:15:00 +02004597 dprintk("Set MAC Reg C+CR Offset 0xE0. "
Linus Torvalds1da177e2005-04-16 15:20:36 -07004598 "Bit-3 and bit-14 MUST be 1\n");
Francois Romieubcf0bf92006-07-26 23:14:13 +02004599 tp->cp_cmd |= (1 << 14);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004600 }
4601
Francois Romieubcf0bf92006-07-26 23:14:13 +02004602 RTL_W16(CPlusCmd, tp->cp_cmd);
4603
Francois Romieu6dccd162007-02-13 23:38:05 +01004604 rtl8169_set_magic_reg(ioaddr, tp->mac_version);
4605
Linus Torvalds1da177e2005-04-16 15:20:36 -07004606 /*
4607 * Undocumented corner. Supposedly:
4608 * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
4609 */
4610 RTL_W16(IntrMitigate, 0x0000);
4611
Francois Romieu7f796d832007-06-11 23:04:41 +02004612 rtl_set_rx_tx_desc_registers(tp, ioaddr);
Francois Romieu9cb427b2006-11-02 00:10:16 +01004613
Francois Romieucecb5fd2011-04-01 10:21:07 +02004614 if (tp->mac_version != RTL_GIGA_MAC_VER_01 &&
4615 tp->mac_version != RTL_GIGA_MAC_VER_02 &&
4616 tp->mac_version != RTL_GIGA_MAC_VER_03 &&
4617 tp->mac_version != RTL_GIGA_MAC_VER_04) {
Francois Romieuc946b302007-10-04 00:42:50 +02004618 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4619 rtl_set_rx_tx_config_registers(tp);
4620 }
4621
Linus Torvalds1da177e2005-04-16 15:20:36 -07004622 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieub518fa82006-08-16 15:23:13 +02004623
4624 /* Initially a 10 us delay. Turned it into a PCI commit. - FR */
4625 RTL_R8(IntrMask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004626
4627 RTL_W32(RxMissed, 0);
4628
Francois Romieu07ce4062007-02-23 23:36:39 +01004629 rtl_set_rx_mode(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004630
4631 /* no early-rx interrupts */
4632 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01004633}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004634
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004635static void rtl_csi_write(struct rtl8169_private *tp, int addr, int value)
4636{
4637 if (tp->csi_ops.write)
Francois Romieu52989f02012-07-06 13:37:00 +02004638 tp->csi_ops.write(tp, addr, value);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004639}
4640
4641static u32 rtl_csi_read(struct rtl8169_private *tp, int addr)
4642{
Francois Romieu52989f02012-07-06 13:37:00 +02004643 return tp->csi_ops.read ? tp->csi_ops.read(tp, addr) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004644}
4645
4646static void rtl_csi_access_enable(struct rtl8169_private *tp, u32 bits)
Francois Romieudacf8152008-08-02 20:44:13 +02004647{
4648 u32 csi;
4649
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004650 csi = rtl_csi_read(tp, 0x070c) & 0x00ffffff;
4651 rtl_csi_write(tp, 0x070c, csi | bits);
françois romieu650e8d52011-01-03 15:08:29 +00004652}
4653
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004654static void rtl_csi_access_enable_1(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00004655{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004656 rtl_csi_access_enable(tp, 0x17000000);
françois romieue6de30d2011-01-03 15:08:37 +00004657}
4658
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004659static void rtl_csi_access_enable_2(struct rtl8169_private *tp)
françois romieu650e8d52011-01-03 15:08:29 +00004660{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004661 rtl_csi_access_enable(tp, 0x27000000);
4662}
4663
Francois Romieuffc46952012-07-06 14:19:23 +02004664DECLARE_RTL_COND(rtl_csiar_cond)
4665{
4666 void __iomem *ioaddr = tp->mmio_addr;
4667
4668 return RTL_R32(CSIAR) & CSIAR_FLAG;
4669}
4670
Francois Romieu52989f02012-07-06 13:37:00 +02004671static void r8169_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004672{
Francois Romieu52989f02012-07-06 13:37:00 +02004673 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004674
4675 RTL_W32(CSIDR, value);
4676 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4677 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4678
Francois Romieuffc46952012-07-06 14:19:23 +02004679 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004680}
4681
Francois Romieu52989f02012-07-06 13:37:00 +02004682static u32 r8169_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004683{
Francois Romieu52989f02012-07-06 13:37:00 +02004684 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004685
4686 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) |
4687 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4688
Francois Romieuffc46952012-07-06 14:19:23 +02004689 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4690 RTL_R32(CSIDR) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004691}
4692
Francois Romieu52989f02012-07-06 13:37:00 +02004693static void r8402_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004694{
Francois Romieu52989f02012-07-06 13:37:00 +02004695 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004696
4697 RTL_W32(CSIDR, value);
4698 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4699 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT |
4700 CSIAR_FUNC_NIC);
4701
Francois Romieuffc46952012-07-06 14:19:23 +02004702 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wang7e18dca2012-03-30 14:33:02 +08004703}
4704
Francois Romieu52989f02012-07-06 13:37:00 +02004705static u32 r8402_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004706{
Francois Romieu52989f02012-07-06 13:37:00 +02004707 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004708
4709 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_FUNC_NIC |
4710 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4711
Francois Romieuffc46952012-07-06 14:19:23 +02004712 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4713 RTL_R32(CSIDR) : ~0;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004714}
4715
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004716static void __devinit rtl_init_csi_ops(struct rtl8169_private *tp)
4717{
4718 struct csi_ops *ops = &tp->csi_ops;
4719
4720 switch (tp->mac_version) {
4721 case RTL_GIGA_MAC_VER_01:
4722 case RTL_GIGA_MAC_VER_02:
4723 case RTL_GIGA_MAC_VER_03:
4724 case RTL_GIGA_MAC_VER_04:
4725 case RTL_GIGA_MAC_VER_05:
4726 case RTL_GIGA_MAC_VER_06:
4727 case RTL_GIGA_MAC_VER_10:
4728 case RTL_GIGA_MAC_VER_11:
4729 case RTL_GIGA_MAC_VER_12:
4730 case RTL_GIGA_MAC_VER_13:
4731 case RTL_GIGA_MAC_VER_14:
4732 case RTL_GIGA_MAC_VER_15:
4733 case RTL_GIGA_MAC_VER_16:
4734 case RTL_GIGA_MAC_VER_17:
4735 ops->write = NULL;
4736 ops->read = NULL;
4737 break;
4738
Hayes Wang7e18dca2012-03-30 14:33:02 +08004739 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004740 case RTL_GIGA_MAC_VER_38:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004741 ops->write = r8402_csi_write;
4742 ops->read = r8402_csi_read;
4743 break;
4744
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004745 default:
4746 ops->write = r8169_csi_write;
4747 ops->read = r8169_csi_read;
4748 break;
4749 }
Francois Romieudacf8152008-08-02 20:44:13 +02004750}
4751
4752struct ephy_info {
4753 unsigned int offset;
4754 u16 mask;
4755 u16 bits;
4756};
4757
Francois Romieufdf6fc02012-07-06 22:40:38 +02004758static void rtl_ephy_init(struct rtl8169_private *tp, const struct ephy_info *e,
4759 int len)
Francois Romieudacf8152008-08-02 20:44:13 +02004760{
4761 u16 w;
4762
4763 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02004764 w = (rtl_ephy_read(tp, e->offset) & ~e->mask) | e->bits;
4765 rtl_ephy_write(tp, e->offset, w);
Francois Romieudacf8152008-08-02 20:44:13 +02004766 e++;
4767 }
4768}
4769
Francois Romieub726e492008-06-28 12:22:59 +02004770static void rtl_disable_clock_request(struct pci_dev *pdev)
4771{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004772 pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL,
4773 PCI_EXP_LNKCTL_CLKREQ_EN);
Francois Romieub726e492008-06-28 12:22:59 +02004774}
4775
françois romieue6de30d2011-01-03 15:08:37 +00004776static void rtl_enable_clock_request(struct pci_dev *pdev)
4777{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004778 pcie_capability_set_word(pdev, PCI_EXP_LNKCTL,
4779 PCI_EXP_LNKCTL_CLKREQ_EN);
françois romieue6de30d2011-01-03 15:08:37 +00004780}
4781
Francois Romieub726e492008-06-28 12:22:59 +02004782#define R8168_CPCMD_QUIRK_MASK (\
4783 EnableBist | \
4784 Mac_dbgo_oe | \
4785 Force_half_dup | \
4786 Force_rxflow_en | \
4787 Force_txflow_en | \
4788 Cxpl_dbg_sel | \
4789 ASF | \
4790 PktCntrDisable | \
4791 Mac_dbgo_sel)
4792
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004793static void rtl_hw_start_8168bb(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004794{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004795 void __iomem *ioaddr = tp->mmio_addr;
4796 struct pci_dev *pdev = tp->pci_dev;
4797
Francois Romieub726e492008-06-28 12:22:59 +02004798 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4799
4800 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4801
Francois Romieu2e68ae42008-06-28 12:00:55 +02004802 rtl_tx_performance_tweak(pdev,
4803 (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
Francois Romieu219a1e92008-06-28 11:58:39 +02004804}
4805
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004806static void rtl_hw_start_8168bef(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004807{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004808 void __iomem *ioaddr = tp->mmio_addr;
4809
4810 rtl_hw_start_8168bb(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004811
françois romieuf0298f82011-01-03 15:07:42 +00004812 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieub726e492008-06-28 12:22:59 +02004813
4814 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
Francois Romieu219a1e92008-06-28 11:58:39 +02004815}
4816
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004817static void __rtl_hw_start_8168cp(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004818{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004819 void __iomem *ioaddr = tp->mmio_addr;
4820 struct pci_dev *pdev = tp->pci_dev;
4821
Francois Romieub726e492008-06-28 12:22:59 +02004822 RTL_W8(Config1, RTL_R8(Config1) | Speed_down);
4823
4824 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4825
Francois Romieu219a1e92008-06-28 11:58:39 +02004826 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieub726e492008-06-28 12:22:59 +02004827
4828 rtl_disable_clock_request(pdev);
4829
4830 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
Francois Romieu219a1e92008-06-28 11:58:39 +02004831}
4832
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004833static void rtl_hw_start_8168cp_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004834{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004835 static const struct ephy_info e_info_8168cp[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004836 { 0x01, 0, 0x0001 },
4837 { 0x02, 0x0800, 0x1000 },
4838 { 0x03, 0, 0x0042 },
4839 { 0x06, 0x0080, 0x0000 },
4840 { 0x07, 0, 0x2000 }
4841 };
4842
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004843 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004844
Francois Romieufdf6fc02012-07-06 22:40:38 +02004845 rtl_ephy_init(tp, e_info_8168cp, ARRAY_SIZE(e_info_8168cp));
Francois Romieub726e492008-06-28 12:22:59 +02004846
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004847 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004848}
4849
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004850static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02004851{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004852 void __iomem *ioaddr = tp->mmio_addr;
4853 struct pci_dev *pdev = tp->pci_dev;
4854
4855 rtl_csi_access_enable_2(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02004856
4857 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4858
4859 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4860
4861 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4862}
4863
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004864static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp)
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004865{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004866 void __iomem *ioaddr = tp->mmio_addr;
4867 struct pci_dev *pdev = tp->pci_dev;
4868
4869 rtl_csi_access_enable_2(tp);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004870
4871 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4872
4873 /* Magic. */
4874 RTL_W8(DBG_REG, 0x20);
4875
françois romieuf0298f82011-01-03 15:07:42 +00004876 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004877
4878 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4879
4880 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4881}
4882
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004883static void rtl_hw_start_8168c_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004884{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004885 void __iomem *ioaddr = tp->mmio_addr;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004886 static const struct ephy_info e_info_8168c_1[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004887 { 0x02, 0x0800, 0x1000 },
4888 { 0x03, 0, 0x0002 },
4889 { 0x06, 0x0080, 0x0000 }
4890 };
4891
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004892 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004893
4894 RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2);
4895
Francois Romieufdf6fc02012-07-06 22:40:38 +02004896 rtl_ephy_init(tp, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1));
Francois Romieub726e492008-06-28 12:22:59 +02004897
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004898 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004899}
4900
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004901static void rtl_hw_start_8168c_2(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004902{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004903 static const struct ephy_info e_info_8168c_2[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004904 { 0x01, 0, 0x0001 },
4905 { 0x03, 0x0400, 0x0220 }
4906 };
4907
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004908 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004909
Francois Romieufdf6fc02012-07-06 22:40:38 +02004910 rtl_ephy_init(tp, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2));
Francois Romieub726e492008-06-28 12:22:59 +02004911
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004912 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004913}
4914
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004915static void rtl_hw_start_8168c_3(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02004916{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004917 rtl_hw_start_8168c_2(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02004918}
4919
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004920static void rtl_hw_start_8168c_4(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02004921{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004922 rtl_csi_access_enable_2(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02004923
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004924 __rtl_hw_start_8168cp(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02004925}
4926
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004927static void rtl_hw_start_8168d(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02004928{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004929 void __iomem *ioaddr = tp->mmio_addr;
4930 struct pci_dev *pdev = tp->pci_dev;
4931
4932 rtl_csi_access_enable_2(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02004933
4934 rtl_disable_clock_request(pdev);
4935
françois romieuf0298f82011-01-03 15:07:42 +00004936 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu5b538df2008-07-20 16:22:45 +02004937
4938 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4939
4940 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4941}
4942
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004943static void rtl_hw_start_8168dp(struct rtl8169_private *tp)
hayeswang4804b3b2011-03-21 01:50:29 +00004944{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004945 void __iomem *ioaddr = tp->mmio_addr;
4946 struct pci_dev *pdev = tp->pci_dev;
4947
4948 rtl_csi_access_enable_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00004949
4950 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4951
4952 RTL_W8(MaxTxPacketSize, TxPacketMax);
4953
4954 rtl_disable_clock_request(pdev);
4955}
4956
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004957static void rtl_hw_start_8168d_4(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00004958{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004959 void __iomem *ioaddr = tp->mmio_addr;
4960 struct pci_dev *pdev = tp->pci_dev;
françois romieue6de30d2011-01-03 15:08:37 +00004961 static const struct ephy_info e_info_8168d_4[] = {
4962 { 0x0b, ~0, 0x48 },
4963 { 0x19, 0x20, 0x50 },
4964 { 0x0c, ~0, 0x20 }
4965 };
4966 int i;
4967
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004968 rtl_csi_access_enable_1(tp);
françois romieue6de30d2011-01-03 15:08:37 +00004969
4970 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4971
4972 RTL_W8(MaxTxPacketSize, TxPacketMax);
4973
4974 for (i = 0; i < ARRAY_SIZE(e_info_8168d_4); i++) {
4975 const struct ephy_info *e = e_info_8168d_4 + i;
4976 u16 w;
4977
Francois Romieufdf6fc02012-07-06 22:40:38 +02004978 w = rtl_ephy_read(tp, e->offset);
4979 rtl_ephy_write(tp, 0x03, (w & e->mask) | e->bits);
françois romieue6de30d2011-01-03 15:08:37 +00004980 }
4981
4982 rtl_enable_clock_request(pdev);
4983}
4984
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004985static void rtl_hw_start_8168e_1(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00004986{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004987 void __iomem *ioaddr = tp->mmio_addr;
4988 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08004989 static const struct ephy_info e_info_8168e_1[] = {
hayeswang01dc7fe2011-03-21 01:50:28 +00004990 { 0x00, 0x0200, 0x0100 },
4991 { 0x00, 0x0000, 0x0004 },
4992 { 0x06, 0x0002, 0x0001 },
4993 { 0x06, 0x0000, 0x0030 },
4994 { 0x07, 0x0000, 0x2000 },
4995 { 0x00, 0x0000, 0x0020 },
4996 { 0x03, 0x5800, 0x2000 },
4997 { 0x03, 0x0000, 0x0001 },
4998 { 0x01, 0x0800, 0x1000 },
4999 { 0x07, 0x0000, 0x4000 },
5000 { 0x1e, 0x0000, 0x2000 },
5001 { 0x19, 0xffff, 0xfe6c },
5002 { 0x0a, 0x0000, 0x0040 }
5003 };
5004
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005005 rtl_csi_access_enable_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00005006
Francois Romieufdf6fc02012-07-06 22:40:38 +02005007 rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1));
hayeswang01dc7fe2011-03-21 01:50:28 +00005008
5009 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5010
5011 RTL_W8(MaxTxPacketSize, TxPacketMax);
5012
5013 rtl_disable_clock_request(pdev);
5014
5015 /* Reset tx FIFO pointer */
Francois Romieucecb5fd2011-04-01 10:21:07 +02005016 RTL_W32(MISC, RTL_R32(MISC) | TXPLA_RST);
5017 RTL_W32(MISC, RTL_R32(MISC) & ~TXPLA_RST);
hayeswang01dc7fe2011-03-21 01:50:28 +00005018
Francois Romieucecb5fd2011-04-01 10:21:07 +02005019 RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
hayeswang01dc7fe2011-03-21 01:50:28 +00005020}
5021
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005022static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
Hayes Wang70090422011-07-06 15:58:06 +08005023{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005024 void __iomem *ioaddr = tp->mmio_addr;
5025 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08005026 static const struct ephy_info e_info_8168e_2[] = {
5027 { 0x09, 0x0000, 0x0080 },
5028 { 0x19, 0x0000, 0x0224 }
5029 };
5030
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005031 rtl_csi_access_enable_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005032
Francois Romieufdf6fc02012-07-06 22:40:38 +02005033 rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2));
Hayes Wang70090422011-07-06 15:58:06 +08005034
5035 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5036
Francois Romieufdf6fc02012-07-06 22:40:38 +02005037 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5038 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5039 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5040 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5041 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5042 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x07ff0060, ERIAR_EXGMAC);
5043 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5044 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08005045
Hayes Wang3090bd92011-09-06 16:55:15 +08005046 RTL_W8(MaxTxPacketSize, EarlySize);
Hayes Wang70090422011-07-06 15:58:06 +08005047
5048 rtl_disable_clock_request(pdev);
5049
5050 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5051 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
5052
5053 /* Adjust EEE LED frequency */
5054 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5055
5056 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
5057 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
5058 RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
5059}
5060
Hayes Wang5f886e02012-03-30 14:33:03 +08005061static void rtl_hw_start_8168f(struct rtl8169_private *tp)
Hayes Wangc2218922011-09-06 16:55:18 +08005062{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005063 void __iomem *ioaddr = tp->mmio_addr;
5064 struct pci_dev *pdev = tp->pci_dev;
Hayes Wangc2218922011-09-06 16:55:18 +08005065
Hayes Wang5f886e02012-03-30 14:33:03 +08005066 rtl_csi_access_enable_2(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005067
5068 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5069
Francois Romieufdf6fc02012-07-06 22:40:38 +02005070 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5071 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5072 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5073 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5074 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5075 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5076 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5077 rtl_w1w0_eri(tp, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5078 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5079 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08005080
5081 RTL_W8(MaxTxPacketSize, EarlySize);
5082
5083 rtl_disable_clock_request(pdev);
5084
5085 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5086 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
Hayes Wangc2218922011-09-06 16:55:18 +08005087 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
5088 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
5089 RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
5090}
5091
Hayes Wang5f886e02012-03-30 14:33:03 +08005092static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
5093{
5094 void __iomem *ioaddr = tp->mmio_addr;
5095 static const struct ephy_info e_info_8168f_1[] = {
5096 { 0x06, 0x00c0, 0x0020 },
5097 { 0x08, 0x0001, 0x0002 },
5098 { 0x09, 0x0000, 0x0080 },
5099 { 0x19, 0x0000, 0x0224 }
5100 };
5101
5102 rtl_hw_start_8168f(tp);
5103
Francois Romieufdf6fc02012-07-06 22:40:38 +02005104 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wang5f886e02012-03-30 14:33:03 +08005105
Francois Romieufdf6fc02012-07-06 22:40:38 +02005106 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang5f886e02012-03-30 14:33:03 +08005107
5108 /* Adjust EEE LED frequency */
5109 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5110}
5111
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005112static void rtl_hw_start_8411(struct rtl8169_private *tp)
5113{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005114 static const struct ephy_info e_info_8168f_1[] = {
5115 { 0x06, 0x00c0, 0x0020 },
5116 { 0x0f, 0xffff, 0x5200 },
5117 { 0x1e, 0x0000, 0x4000 },
5118 { 0x19, 0x0000, 0x0224 }
5119 };
5120
5121 rtl_hw_start_8168f(tp);
5122
Francois Romieufdf6fc02012-07-06 22:40:38 +02005123 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005124
Francois Romieufdf6fc02012-07-06 22:40:38 +02005125 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0x0000, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005126}
5127
Hayes Wangc5583862012-07-02 17:23:22 +08005128static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
5129{
5130 void __iomem *ioaddr = tp->mmio_addr;
5131 struct pci_dev *pdev = tp->pci_dev;
5132
5133 rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x080002, ERIAR_EXGMAC);
5134 rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x38, ERIAR_EXGMAC);
5135 rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x48, ERIAR_EXGMAC);
5136 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5137
5138 rtl_csi_access_enable_1(tp);
5139
5140 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5141
5142 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5143 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5144
5145 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5146 RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN);
5147 RTL_W8(MaxTxPacketSize, EarlySize);
5148
5149 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5150 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5151
5152 /* Adjust EEE LED frequency */
5153 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5154
5155 rtl_w1w0_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x02, ERIAR_EXGMAC);
5156}
5157
Francois Romieu07ce4062007-02-23 23:36:39 +01005158static void rtl_hw_start_8168(struct net_device *dev)
5159{
Francois Romieu2dd99532007-06-11 23:22:52 +02005160 struct rtl8169_private *tp = netdev_priv(dev);
5161 void __iomem *ioaddr = tp->mmio_addr;
5162
5163 RTL_W8(Cfg9346, Cfg9346_Unlock);
5164
françois romieuf0298f82011-01-03 15:07:42 +00005165 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu2dd99532007-06-11 23:22:52 +02005166
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005167 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Francois Romieu2dd99532007-06-11 23:22:52 +02005168
Francois Romieu0e485152007-02-20 00:00:26 +01005169 tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
Francois Romieu2dd99532007-06-11 23:22:52 +02005170
5171 RTL_W16(CPlusCmd, tp->cp_cmd);
5172
Francois Romieu0e485152007-02-20 00:00:26 +01005173 RTL_W16(IntrMitigate, 0x5151);
5174
5175 /* Work around for RxFIFO overflow. */
françois romieu811fd302011-12-04 20:30:45 +00005176 if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01005177 tp->event_slow |= RxFIFOOver | PCSTimeout;
5178 tp->event_slow &= ~RxOverflow;
Francois Romieu0e485152007-02-20 00:00:26 +01005179 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005180
5181 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5182
Francois Romieub8363902008-06-01 12:31:57 +02005183 rtl_set_rx_mode(dev);
5184
5185 RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
5186 (InterFrameGap << TxInterFrameGapShift));
Francois Romieu2dd99532007-06-11 23:22:52 +02005187
5188 RTL_R8(IntrMask);
5189
Francois Romieu219a1e92008-06-28 11:58:39 +02005190 switch (tp->mac_version) {
5191 case RTL_GIGA_MAC_VER_11:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005192 rtl_hw_start_8168bb(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005193 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005194
5195 case RTL_GIGA_MAC_VER_12:
5196 case RTL_GIGA_MAC_VER_17:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005197 rtl_hw_start_8168bef(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005198 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005199
5200 case RTL_GIGA_MAC_VER_18:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005201 rtl_hw_start_8168cp_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005202 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005203
5204 case RTL_GIGA_MAC_VER_19:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005205 rtl_hw_start_8168c_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005206 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005207
5208 case RTL_GIGA_MAC_VER_20:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005209 rtl_hw_start_8168c_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005210 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005211
Francois Romieu197ff762008-06-28 13:16:02 +02005212 case RTL_GIGA_MAC_VER_21:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005213 rtl_hw_start_8168c_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005214 break;
Francois Romieu197ff762008-06-28 13:16:02 +02005215
Francois Romieu6fb07052008-06-29 11:54:28 +02005216 case RTL_GIGA_MAC_VER_22:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005217 rtl_hw_start_8168c_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005218 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02005219
Francois Romieuef3386f2008-06-29 12:24:30 +02005220 case RTL_GIGA_MAC_VER_23:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005221 rtl_hw_start_8168cp_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005222 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02005223
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005224 case RTL_GIGA_MAC_VER_24:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005225 rtl_hw_start_8168cp_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005226 break;
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005227
Francois Romieu5b538df2008-07-20 16:22:45 +02005228 case RTL_GIGA_MAC_VER_25:
françois romieudaf9df62009-10-07 12:44:20 +00005229 case RTL_GIGA_MAC_VER_26:
5230 case RTL_GIGA_MAC_VER_27:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005231 rtl_hw_start_8168d(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005232 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02005233
françois romieue6de30d2011-01-03 15:08:37 +00005234 case RTL_GIGA_MAC_VER_28:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005235 rtl_hw_start_8168d_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005236 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02005237
hayeswang4804b3b2011-03-21 01:50:29 +00005238 case RTL_GIGA_MAC_VER_31:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005239 rtl_hw_start_8168dp(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005240 break;
5241
hayeswang01dc7fe2011-03-21 01:50:28 +00005242 case RTL_GIGA_MAC_VER_32:
5243 case RTL_GIGA_MAC_VER_33:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005244 rtl_hw_start_8168e_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005245 break;
5246 case RTL_GIGA_MAC_VER_34:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005247 rtl_hw_start_8168e_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00005248 break;
françois romieue6de30d2011-01-03 15:08:37 +00005249
Hayes Wangc2218922011-09-06 16:55:18 +08005250 case RTL_GIGA_MAC_VER_35:
5251 case RTL_GIGA_MAC_VER_36:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005252 rtl_hw_start_8168f_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005253 break;
5254
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005255 case RTL_GIGA_MAC_VER_38:
5256 rtl_hw_start_8411(tp);
5257 break;
5258
Hayes Wangc5583862012-07-02 17:23:22 +08005259 case RTL_GIGA_MAC_VER_40:
5260 case RTL_GIGA_MAC_VER_41:
5261 rtl_hw_start_8168g_1(tp);
5262 break;
5263
Francois Romieu219a1e92008-06-28 11:58:39 +02005264 default:
5265 printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
5266 dev->name, tp->mac_version);
hayeswang4804b3b2011-03-21 01:50:29 +00005267 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005268 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005269
Francois Romieu0e485152007-02-20 00:00:26 +01005270 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5271
Francois Romieub8363902008-06-01 12:31:57 +02005272 RTL_W8(Cfg9346, Cfg9346_Lock);
5273
Francois Romieu2dd99532007-06-11 23:22:52 +02005274 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01005275}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005276
Francois Romieu2857ffb2008-08-02 21:08:49 +02005277#define R810X_CPCMD_QUIRK_MASK (\
5278 EnableBist | \
5279 Mac_dbgo_oe | \
5280 Force_half_dup | \
françois romieu5edcc532009-08-10 19:41:52 +00005281 Force_rxflow_en | \
Francois Romieu2857ffb2008-08-02 21:08:49 +02005282 Force_txflow_en | \
5283 Cxpl_dbg_sel | \
5284 ASF | \
5285 PktCntrDisable | \
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005286 Mac_dbgo_sel)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005287
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005288static void rtl_hw_start_8102e_1(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005289{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005290 void __iomem *ioaddr = tp->mmio_addr;
5291 struct pci_dev *pdev = tp->pci_dev;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08005292 static const struct ephy_info e_info_8102e_1[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02005293 { 0x01, 0, 0x6e65 },
5294 { 0x02, 0, 0x091f },
5295 { 0x03, 0, 0xc2f9 },
5296 { 0x06, 0, 0xafb5 },
5297 { 0x07, 0, 0x0e00 },
5298 { 0x19, 0, 0xec80 },
5299 { 0x01, 0, 0x2e65 },
5300 { 0x01, 0, 0x6e65 }
5301 };
5302 u8 cfg1;
5303
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005304 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005305
5306 RTL_W8(DBG_REG, FIX_NAK_1);
5307
5308 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5309
5310 RTL_W8(Config1,
5311 LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable);
5312 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
5313
5314 cfg1 = RTL_R8(Config1);
5315 if ((cfg1 & LEDS0) && (cfg1 & LEDS1))
5316 RTL_W8(Config1, cfg1 & ~LEDS0);
5317
Francois Romieufdf6fc02012-07-06 22:40:38 +02005318 rtl_ephy_init(tp, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1));
Francois Romieu2857ffb2008-08-02 21:08:49 +02005319}
5320
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005321static void rtl_hw_start_8102e_2(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005322{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005323 void __iomem *ioaddr = tp->mmio_addr;
5324 struct pci_dev *pdev = tp->pci_dev;
5325
5326 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005327
5328 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5329
5330 RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable);
5331 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005332}
5333
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005334static void rtl_hw_start_8102e_3(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005335{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005336 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005337
Francois Romieufdf6fc02012-07-06 22:40:38 +02005338 rtl_ephy_write(tp, 0x03, 0xc2f9);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005339}
5340
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005341static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005342{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005343 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005344 static const struct ephy_info e_info_8105e_1[] = {
5345 { 0x07, 0, 0x4000 },
5346 { 0x19, 0, 0x0200 },
5347 { 0x19, 0, 0x0020 },
5348 { 0x1e, 0, 0x2000 },
5349 { 0x03, 0, 0x0001 },
5350 { 0x19, 0, 0x0100 },
5351 { 0x19, 0, 0x0004 },
5352 { 0x0a, 0, 0x0020 }
5353 };
5354
Francois Romieucecb5fd2011-04-01 10:21:07 +02005355 /* Force LAN exit from ASPM if Rx/Tx are not idle */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005356 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5357
Francois Romieucecb5fd2011-04-01 10:21:07 +02005358 /* Disable Early Tally Counter */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005359 RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000);
5360
5361 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
Hayes Wang4f6b00e52011-07-06 15:58:02 +08005362 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005363
Francois Romieufdf6fc02012-07-06 22:40:38 +02005364 rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
Hayes Wang5a5e4442011-02-22 17:26:21 +08005365}
5366
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005367static void rtl_hw_start_8105e_2(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005368{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005369 rtl_hw_start_8105e_1(tp);
Francois Romieufdf6fc02012-07-06 22:40:38 +02005370 rtl_ephy_write(tp, 0x1e, rtl_ephy_read(tp, 0x1e) | 0x8000);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005371}
5372
Hayes Wang7e18dca2012-03-30 14:33:02 +08005373static void rtl_hw_start_8402(struct rtl8169_private *tp)
5374{
5375 void __iomem *ioaddr = tp->mmio_addr;
5376 static const struct ephy_info e_info_8402[] = {
5377 { 0x19, 0xffff, 0xff64 },
5378 { 0x1e, 0, 0x4000 }
5379 };
5380
5381 rtl_csi_access_enable_2(tp);
5382
5383 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5384 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5385
5386 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5387 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
5388
Francois Romieufdf6fc02012-07-06 22:40:38 +02005389 rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402));
Hayes Wang7e18dca2012-03-30 14:33:02 +08005390
5391 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
5392
Francois Romieufdf6fc02012-07-06 22:40:38 +02005393 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00000002, ERIAR_EXGMAC);
5394 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00000006, ERIAR_EXGMAC);
5395 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5396 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5397 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5398 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5399 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08005400}
5401
Hayes Wang5598bfe2012-07-02 17:23:21 +08005402static void rtl_hw_start_8106(struct rtl8169_private *tp)
5403{
5404 void __iomem *ioaddr = tp->mmio_addr;
5405
5406 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5407 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5408
5409 RTL_W32(MISC, (RTL_R32(MISC) | DISABLE_LAN_EN) & ~EARLY_TALLY_EN);
5410 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
5411 RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
5412}
5413
Francois Romieu07ce4062007-02-23 23:36:39 +01005414static void rtl_hw_start_8101(struct net_device *dev)
5415{
Francois Romieucdf1a602007-06-11 23:29:50 +02005416 struct rtl8169_private *tp = netdev_priv(dev);
5417 void __iomem *ioaddr = tp->mmio_addr;
5418 struct pci_dev *pdev = tp->pci_dev;
5419
Francois Romieuda78dbf2012-01-26 14:18:23 +01005420 if (tp->mac_version >= RTL_GIGA_MAC_VER_30)
5421 tp->event_slow &= ~RxFIFOOver;
françois romieu811fd302011-12-04 20:30:45 +00005422
Francois Romieucecb5fd2011-04-01 10:21:07 +02005423 if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||
Jiang Liu7d7903b2012-07-24 17:20:16 +08005424 tp->mac_version == RTL_GIGA_MAC_VER_16)
Bjorn Helgaas8200bc72012-08-22 10:29:42 -06005425 pcie_capability_set_word(pdev, PCI_EXP_DEVCTL,
5426 PCI_EXP_DEVCTL_NOSNOOP_EN);
Francois Romieucdf1a602007-06-11 23:29:50 +02005427
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005428 RTL_W8(Cfg9346, Cfg9346_Unlock);
5429
Francois Romieu2857ffb2008-08-02 21:08:49 +02005430 switch (tp->mac_version) {
5431 case RTL_GIGA_MAC_VER_07:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005432 rtl_hw_start_8102e_1(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005433 break;
5434
5435 case RTL_GIGA_MAC_VER_08:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005436 rtl_hw_start_8102e_3(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005437 break;
5438
5439 case RTL_GIGA_MAC_VER_09:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005440 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005441 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005442
5443 case RTL_GIGA_MAC_VER_29:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005444 rtl_hw_start_8105e_1(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005445 break;
5446 case RTL_GIGA_MAC_VER_30:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005447 rtl_hw_start_8105e_2(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005448 break;
Hayes Wang7e18dca2012-03-30 14:33:02 +08005449
5450 case RTL_GIGA_MAC_VER_37:
5451 rtl_hw_start_8402(tp);
5452 break;
Hayes Wang5598bfe2012-07-02 17:23:21 +08005453
5454 case RTL_GIGA_MAC_VER_39:
5455 rtl_hw_start_8106(tp);
5456 break;
Francois Romieucdf1a602007-06-11 23:29:50 +02005457 }
5458
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005459 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieucdf1a602007-06-11 23:29:50 +02005460
françois romieuf0298f82011-01-03 15:07:42 +00005461 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieucdf1a602007-06-11 23:29:50 +02005462
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005463 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Francois Romieucdf1a602007-06-11 23:29:50 +02005464
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005465 tp->cp_cmd &= ~R810X_CPCMD_QUIRK_MASK;
Francois Romieucdf1a602007-06-11 23:29:50 +02005466 RTL_W16(CPlusCmd, tp->cp_cmd);
5467
5468 RTL_W16(IntrMitigate, 0x0000);
5469
5470 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5471
5472 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5473 rtl_set_rx_tx_config_registers(tp);
5474
Francois Romieucdf1a602007-06-11 23:29:50 +02005475 RTL_R8(IntrMask);
5476
Francois Romieucdf1a602007-06-11 23:29:50 +02005477 rtl_set_rx_mode(dev);
5478
5479 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005480}
5481
5482static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
5483{
Francois Romieud58d46b2011-05-03 16:38:29 +02005484 struct rtl8169_private *tp = netdev_priv(dev);
5485
5486 if (new_mtu < ETH_ZLEN ||
5487 new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005488 return -EINVAL;
5489
Francois Romieud58d46b2011-05-03 16:38:29 +02005490 if (new_mtu > ETH_DATA_LEN)
5491 rtl_hw_jumbo_enable(tp);
5492 else
5493 rtl_hw_jumbo_disable(tp);
5494
Linus Torvalds1da177e2005-04-16 15:20:36 -07005495 dev->mtu = new_mtu;
Michał Mirosław350fb322011-04-08 06:35:56 +00005496 netdev_update_features(dev);
5497
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00005498 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005499}
5500
5501static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
5502{
Al Viro95e09182007-12-22 18:55:39 +00005503 desc->addr = cpu_to_le64(0x0badbadbadbadbadull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005504 desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask);
5505}
5506
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005507static void rtl8169_free_rx_databuff(struct rtl8169_private *tp,
5508 void **data_buff, struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005509{
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005510 dma_unmap_single(&tp->pci_dev->dev, le64_to_cpu(desc->addr), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005511 DMA_FROM_DEVICE);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005512
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005513 kfree(*data_buff);
5514 *data_buff = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005515 rtl8169_make_unusable_by_asic(desc);
5516}
5517
5518static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz)
5519{
5520 u32 eor = le32_to_cpu(desc->opts1) & RingEnd;
5521
5522 desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz);
5523}
5524
5525static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
5526 u32 rx_buf_sz)
5527{
5528 desc->addr = cpu_to_le64(mapping);
5529 wmb();
5530 rtl8169_mark_to_asic(desc, rx_buf_sz);
5531}
5532
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005533static inline void *rtl8169_align(void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005534{
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005535 return (void *)ALIGN((long)data, 16);
5536}
5537
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005538static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp,
5539 struct RxDesc *desc)
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005540{
5541 void *data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005542 dma_addr_t mapping;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005543 struct device *d = &tp->pci_dev->dev;
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005544 struct net_device *dev = tp->dev;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005545 int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005546
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005547 data = kmalloc_node(rx_buf_sz, GFP_KERNEL, node);
5548 if (!data)
5549 return NULL;
Francois Romieue9f63f32007-02-28 23:16:57 +01005550
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005551 if (rtl8169_align(data) != data) {
5552 kfree(data);
5553 data = kmalloc_node(rx_buf_sz + 15, GFP_KERNEL, node);
5554 if (!data)
5555 return NULL;
5556 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005557
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005558 mapping = dma_map_single(d, rtl8169_align(data), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005559 DMA_FROM_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005560 if (unlikely(dma_mapping_error(d, mapping))) {
5561 if (net_ratelimit())
5562 netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005563 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005564 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005565
5566 rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005567 return data;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005568
5569err_out:
5570 kfree(data);
5571 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005572}
5573
5574static void rtl8169_rx_clear(struct rtl8169_private *tp)
5575{
Francois Romieu07d3f512007-02-21 22:40:46 +01005576 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005577
5578 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005579 if (tp->Rx_databuff[i]) {
5580 rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005581 tp->RxDescArray + i);
5582 }
5583 }
5584}
5585
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005586static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005587{
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005588 desc->opts1 |= cpu_to_le32(RingEnd);
5589}
Francois Romieu5b0384f2006-08-16 16:00:01 +02005590
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005591static int rtl8169_rx_fill(struct rtl8169_private *tp)
5592{
5593 unsigned int i;
5594
5595 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005596 void *data;
Francois Romieu4ae47c22007-06-16 23:28:45 +02005597
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005598 if (tp->Rx_databuff[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005599 continue;
Francois Romieubcf0bf92006-07-26 23:14:13 +02005600
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005601 data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005602 if (!data) {
5603 rtl8169_make_unusable_by_asic(tp->RxDescArray + i);
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005604 goto err_out;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005605 }
5606 tp->Rx_databuff[i] = data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005607 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005608
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005609 rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
5610 return 0;
5611
5612err_out:
5613 rtl8169_rx_clear(tp);
5614 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005615}
5616
Linus Torvalds1da177e2005-04-16 15:20:36 -07005617static int rtl8169_init_ring(struct net_device *dev)
5618{
5619 struct rtl8169_private *tp = netdev_priv(dev);
5620
5621 rtl8169_init_ring_indexes(tp);
5622
5623 memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info));
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005624 memset(tp->Rx_databuff, 0x0, NUM_RX_DESC * sizeof(void *));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005625
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005626 return rtl8169_rx_fill(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005627}
5628
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005629static void rtl8169_unmap_tx_skb(struct device *d, struct ring_info *tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005630 struct TxDesc *desc)
5631{
5632 unsigned int len = tx_skb->len;
5633
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005634 dma_unmap_single(d, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE);
5635
Linus Torvalds1da177e2005-04-16 15:20:36 -07005636 desc->opts1 = 0x00;
5637 desc->opts2 = 0x00;
5638 desc->addr = 0x00;
5639 tx_skb->len = 0;
5640}
5641
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005642static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start,
5643 unsigned int n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005644{
5645 unsigned int i;
5646
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005647 for (i = 0; i < n; i++) {
5648 unsigned int entry = (start + i) % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005649 struct ring_info *tx_skb = tp->tx_skb + entry;
5650 unsigned int len = tx_skb->len;
5651
5652 if (len) {
5653 struct sk_buff *skb = tx_skb->skb;
5654
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005655 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005656 tp->TxDescArray + entry);
5657 if (skb) {
Stanislaw Gruszkacac4b222010-10-20 22:25:40 +00005658 tp->dev->stats.tx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005659 dev_kfree_skb(skb);
5660 tx_skb->skb = NULL;
5661 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005662 }
5663 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005664}
5665
5666static void rtl8169_tx_clear(struct rtl8169_private *tp)
5667{
5668 rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005669 tp->cur_tx = tp->dirty_tx = 0;
5670}
5671
Francois Romieu4422bcd2012-01-26 11:23:32 +01005672static void rtl_reset_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005673{
David Howellsc4028952006-11-22 14:57:56 +00005674 struct net_device *dev = tp->dev;
Francois Romieu56de4142011-03-15 17:29:31 +01005675 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005676
Francois Romieuda78dbf2012-01-26 14:18:23 +01005677 napi_disable(&tp->napi);
5678 netif_stop_queue(dev);
5679 synchronize_sched();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005680
françois romieuc7c2c392011-12-04 20:30:52 +00005681 rtl8169_hw_reset(tp);
5682
Francois Romieu56de4142011-03-15 17:29:31 +01005683 for (i = 0; i < NUM_RX_DESC; i++)
5684 rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz);
5685
Linus Torvalds1da177e2005-04-16 15:20:36 -07005686 rtl8169_tx_clear(tp);
françois romieuc7c2c392011-12-04 20:30:52 +00005687 rtl8169_init_ring_indexes(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005688
Francois Romieuda78dbf2012-01-26 14:18:23 +01005689 napi_enable(&tp->napi);
Francois Romieu56de4142011-03-15 17:29:31 +01005690 rtl_hw_start(dev);
5691 netif_wake_queue(dev);
5692 rtl8169_check_link_status(dev, tp, tp->mmio_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005693}
5694
5695static void rtl8169_tx_timeout(struct net_device *dev)
5696{
Francois Romieuda78dbf2012-01-26 14:18:23 +01005697 struct rtl8169_private *tp = netdev_priv(dev);
5698
5699 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005700}
5701
5702static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
Francois Romieu2b7b4312011-04-18 22:53:24 -07005703 u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005704{
5705 struct skb_shared_info *info = skb_shinfo(skb);
5706 unsigned int cur_frag, entry;
Jeff Garzika6343af2007-07-17 05:39:58 -04005707 struct TxDesc * uninitialized_var(txd);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005708 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005709
5710 entry = tp->cur_tx;
5711 for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
Eric Dumazet9e903e02011-10-18 21:00:24 +00005712 const skb_frag_t *frag = info->frags + cur_frag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005713 dma_addr_t mapping;
5714 u32 status, len;
5715 void *addr;
5716
5717 entry = (entry + 1) % NUM_TX_DESC;
5718
5719 txd = tp->TxDescArray + entry;
Eric Dumazet9e903e02011-10-18 21:00:24 +00005720 len = skb_frag_size(frag);
Ian Campbell929f6182011-08-31 00:47:06 +00005721 addr = skb_frag_address(frag);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005722 mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005723 if (unlikely(dma_mapping_error(d, mapping))) {
5724 if (net_ratelimit())
5725 netif_err(tp, drv, tp->dev,
5726 "Failed to map TX fragments DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005727 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005728 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729
Francois Romieucecb5fd2011-04-01 10:21:07 +02005730 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07005731 status = opts[0] | len |
5732 (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005733
5734 txd->opts1 = cpu_to_le32(status);
Francois Romieu2b7b4312011-04-18 22:53:24 -07005735 txd->opts2 = cpu_to_le32(opts[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005736 txd->addr = cpu_to_le64(mapping);
5737
5738 tp->tx_skb[entry].len = len;
5739 }
5740
5741 if (cur_frag) {
5742 tp->tx_skb[entry].skb = skb;
5743 txd->opts1 |= cpu_to_le32(LastFrag);
5744 }
5745
5746 return cur_frag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005747
5748err_out:
5749 rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag);
5750 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005751}
5752
Francois Romieu2b7b4312011-04-18 22:53:24 -07005753static inline void rtl8169_tso_csum(struct rtl8169_private *tp,
5754 struct sk_buff *skb, u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005755{
Francois Romieu2b7b4312011-04-18 22:53:24 -07005756 const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version;
Michał Mirosław350fb322011-04-08 06:35:56 +00005757 u32 mss = skb_shinfo(skb)->gso_size;
Francois Romieu2b7b4312011-04-18 22:53:24 -07005758 int offset = info->opts_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005759
Francois Romieu2b7b4312011-04-18 22:53:24 -07005760 if (mss) {
5761 opts[0] |= TD_LSO;
5762 opts[offset] |= min(mss, TD_MSS_MAX) << info->mss_shift;
5763 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07005764 const struct iphdr *ip = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005765
5766 if (ip->protocol == IPPROTO_TCP)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005767 opts[offset] |= info->checksum.tcp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005768 else if (ip->protocol == IPPROTO_UDP)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005769 opts[offset] |= info->checksum.udp;
5770 else
5771 WARN_ON_ONCE(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005772 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005773}
5774
Stephen Hemminger613573252009-08-31 19:50:58 +00005775static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
5776 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005777{
5778 struct rtl8169_private *tp = netdev_priv(dev);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005779 unsigned int entry = tp->cur_tx % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005780 struct TxDesc *txd = tp->TxDescArray + entry;
5781 void __iomem *ioaddr = tp->mmio_addr;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005782 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005783 dma_addr_t mapping;
5784 u32 status, len;
Francois Romieu2b7b4312011-04-18 22:53:24 -07005785 u32 opts[2];
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005786 int frags;
Francois Romieu5b0384f2006-08-16 16:00:01 +02005787
Julien Ducourthial477206a2012-05-09 00:00:06 +02005788 if (unlikely(!TX_FRAGS_READY_FOR(tp, skb_shinfo(skb)->nr_frags))) {
Joe Perchesbf82c182010-02-09 11:49:50 +00005789 netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005790 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005791 }
5792
5793 if (unlikely(le32_to_cpu(txd->opts1) & DescOwn))
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005794 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005795
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005796 len = skb_headlen(skb);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005797 mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005798 if (unlikely(dma_mapping_error(d, mapping))) {
5799 if (net_ratelimit())
5800 netif_err(tp, drv, dev, "Failed to map TX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005801 goto err_dma_0;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005802 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005803
5804 tp->tx_skb[entry].len = len;
5805 txd->addr = cpu_to_le64(mapping);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005806
Francois Romieu2b7b4312011-04-18 22:53:24 -07005807 opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb));
5808 opts[0] = DescOwn;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005809
Francois Romieu2b7b4312011-04-18 22:53:24 -07005810 rtl8169_tso_csum(tp, skb, opts);
5811
5812 frags = rtl8169_xmit_frags(tp, skb, opts);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005813 if (frags < 0)
5814 goto err_dma_1;
5815 else if (frags)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005816 opts[0] |= FirstFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005817 else {
Francois Romieu2b7b4312011-04-18 22:53:24 -07005818 opts[0] |= FirstFrag | LastFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005819 tp->tx_skb[entry].skb = skb;
5820 }
5821
Francois Romieu2b7b4312011-04-18 22:53:24 -07005822 txd->opts2 = cpu_to_le32(opts[1]);
5823
Richard Cochran5047fb52012-03-10 07:29:42 +00005824 skb_tx_timestamp(skb);
5825
Linus Torvalds1da177e2005-04-16 15:20:36 -07005826 wmb();
5827
Francois Romieucecb5fd2011-04-01 10:21:07 +02005828 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07005829 status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005830 txd->opts1 = cpu_to_le32(status);
5831
Linus Torvalds1da177e2005-04-16 15:20:36 -07005832 tp->cur_tx += frags + 1;
5833
David Dillow4c020a92010-03-03 16:33:10 +00005834 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005835
Francois Romieucecb5fd2011-04-01 10:21:07 +02005836 RTL_W8(TxPoll, NPQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005837
Francois Romieuda78dbf2012-01-26 14:18:23 +01005838 mmiowb();
5839
Julien Ducourthial477206a2012-05-09 00:00:06 +02005840 if (!TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Francois Romieuae1f23f2012-01-31 00:00:19 +01005841 /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
5842 * not miss a ring update when it notices a stopped queue.
5843 */
5844 smp_wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005845 netif_stop_queue(dev);
Francois Romieuae1f23f2012-01-31 00:00:19 +01005846 /* Sync with rtl_tx:
5847 * - publish queue status and cur_tx ring index (write barrier)
5848 * - refresh dirty_tx ring index (read barrier).
5849 * May the current thread have a pessimistic view of the ring
5850 * status and forget to wake up queue, a racing rtl_tx thread
5851 * can't.
5852 */
Francois Romieu1e874e02012-01-27 15:05:38 +01005853 smp_mb();
Julien Ducourthial477206a2012-05-09 00:00:06 +02005854 if (TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005855 netif_wake_queue(dev);
5856 }
5857
Stephen Hemminger613573252009-08-31 19:50:58 +00005858 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005859
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005860err_dma_1:
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005861 rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005862err_dma_0:
5863 dev_kfree_skb(skb);
5864 dev->stats.tx_dropped++;
5865 return NETDEV_TX_OK;
5866
5867err_stop_0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005868 netif_stop_queue(dev);
Francois Romieucebf8cc2007-10-18 12:06:54 +02005869 dev->stats.tx_dropped++;
Stephen Hemminger613573252009-08-31 19:50:58 +00005870 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005871}
5872
5873static void rtl8169_pcierr_interrupt(struct net_device *dev)
5874{
5875 struct rtl8169_private *tp = netdev_priv(dev);
5876 struct pci_dev *pdev = tp->pci_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005877 u16 pci_status, pci_cmd;
5878
5879 pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
5880 pci_read_config_word(pdev, PCI_STATUS, &pci_status);
5881
Joe Perchesbf82c182010-02-09 11:49:50 +00005882 netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n",
5883 pci_cmd, pci_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005884
5885 /*
5886 * The recovery sequence below admits a very elaborated explanation:
5887 * - it seems to work;
Francois Romieud03902b2006-11-23 00:00:42 +01005888 * - I did not see what else could be done;
5889 * - it makes iop3xx happy.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005890 *
5891 * Feel free to adjust to your needs.
5892 */
Francois Romieua27993f2006-12-18 00:04:19 +01005893 if (pdev->broken_parity_status)
Francois Romieud03902b2006-11-23 00:00:42 +01005894 pci_cmd &= ~PCI_COMMAND_PARITY;
5895 else
5896 pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
5897
5898 pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005899
5900 pci_write_config_word(pdev, PCI_STATUS,
5901 pci_status & (PCI_STATUS_DETECTED_PARITY |
5902 PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT |
5903 PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT));
5904
5905 /* The infamous DAC f*ckup only happens at boot time */
5906 if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) {
françois romieue6de30d2011-01-03 15:08:37 +00005907 void __iomem *ioaddr = tp->mmio_addr;
5908
Joe Perchesbf82c182010-02-09 11:49:50 +00005909 netif_info(tp, intr, dev, "disabling PCI DAC\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005910 tp->cp_cmd &= ~PCIDAC;
5911 RTL_W16(CPlusCmd, tp->cp_cmd);
5912 dev->features &= ~NETIF_F_HIGHDMA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005913 }
5914
françois romieue6de30d2011-01-03 15:08:37 +00005915 rtl8169_hw_reset(tp);
Francois Romieud03902b2006-11-23 00:00:42 +01005916
Francois Romieu98ddf982012-01-31 10:47:34 +01005917 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005918}
5919
Francois Romieuda78dbf2012-01-26 14:18:23 +01005920static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005921{
5922 unsigned int dirty_tx, tx_left;
5923
Linus Torvalds1da177e2005-04-16 15:20:36 -07005924 dirty_tx = tp->dirty_tx;
5925 smp_rmb();
5926 tx_left = tp->cur_tx - dirty_tx;
5927
5928 while (tx_left > 0) {
5929 unsigned int entry = dirty_tx % NUM_TX_DESC;
5930 struct ring_info *tx_skb = tp->tx_skb + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005931 u32 status;
5932
5933 rmb();
5934 status = le32_to_cpu(tp->TxDescArray[entry].opts1);
5935 if (status & DescOwn)
5936 break;
5937
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005938 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
5939 tp->TxDescArray + entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005940 if (status & LastFrag) {
Francois Romieu17bcb682012-07-23 22:55:55 +02005941 u64_stats_update_begin(&tp->tx_stats.syncp);
5942 tp->tx_stats.packets++;
5943 tp->tx_stats.bytes += tx_skb->skb->len;
5944 u64_stats_update_end(&tp->tx_stats.syncp);
5945 dev_kfree_skb(tx_skb->skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005946 tx_skb->skb = NULL;
5947 }
5948 dirty_tx++;
5949 tx_left--;
5950 }
5951
5952 if (tp->dirty_tx != dirty_tx) {
5953 tp->dirty_tx = dirty_tx;
Francois Romieuae1f23f2012-01-31 00:00:19 +01005954 /* Sync with rtl8169_start_xmit:
5955 * - publish dirty_tx ring index (write barrier)
5956 * - refresh cur_tx ring index and queue status (read barrier)
5957 * May the current thread miss the stopped queue condition,
5958 * a racing xmit thread can only have a right view of the
5959 * ring status.
5960 */
Francois Romieu1e874e02012-01-27 15:05:38 +01005961 smp_mb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005962 if (netif_queue_stopped(dev) &&
Julien Ducourthial477206a2012-05-09 00:00:06 +02005963 TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005964 netif_wake_queue(dev);
5965 }
Francois Romieud78ae2d2007-08-26 20:08:19 +02005966 /*
5967 * 8168 hack: TxPoll requests are lost when the Tx packets are
5968 * too close. Let's kick an extra TxPoll request when a burst
5969 * of start_xmit activity is detected (if it is not detected,
5970 * it is slow enough). -- FR
5971 */
Francois Romieuda78dbf2012-01-26 14:18:23 +01005972 if (tp->cur_tx != dirty_tx) {
5973 void __iomem *ioaddr = tp->mmio_addr;
5974
Francois Romieud78ae2d2007-08-26 20:08:19 +02005975 RTL_W8(TxPoll, NPQ);
Francois Romieuda78dbf2012-01-26 14:18:23 +01005976 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005977 }
5978}
5979
Francois Romieu126fa4b2005-05-12 20:09:17 -04005980static inline int rtl8169_fragmented_frame(u32 status)
5981{
5982 return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag);
5983}
5984
Eric Dumazetadea1ac72010-09-05 20:04:05 -07005985static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005986{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005987 u32 status = opts1 & RxProtoMask;
5988
5989 if (((status == RxProtoTCP) && !(opts1 & TCPFail)) ||
Shan Weid5d3ebe2010-11-12 00:15:25 +00005990 ((status == RxProtoUDP) && !(opts1 & UDPFail)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005991 skb->ip_summed = CHECKSUM_UNNECESSARY;
5992 else
Eric Dumazetbc8acf22010-09-02 13:07:41 -07005993 skb_checksum_none_assert(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005994}
5995
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005996static struct sk_buff *rtl8169_try_rx_copy(void *data,
5997 struct rtl8169_private *tp,
5998 int pkt_size,
5999 dma_addr_t addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006000{
Stephen Hemmingerb4496552007-06-17 01:06:49 +02006001 struct sk_buff *skb;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006002 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006003
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006004 data = rtl8169_align(data);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006005 dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006006 prefetch(data);
6007 skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size);
6008 if (skb)
6009 memcpy(skb->data, data, pkt_size);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006010 dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE);
6011
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006012 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006013}
6014
Francois Romieuda78dbf2012-01-26 14:18:23 +01006015static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006016{
6017 unsigned int cur_rx, rx_left;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006018 unsigned int count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006019
Linus Torvalds1da177e2005-04-16 15:20:36 -07006020 cur_rx = tp->cur_rx;
6021 rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
Francois Romieu865c6522008-05-11 14:51:00 +02006022 rx_left = min(rx_left, budget);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006023
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006024 for (; rx_left > 0; rx_left--, cur_rx++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006025 unsigned int entry = cur_rx % NUM_RX_DESC;
Francois Romieu126fa4b2005-05-12 20:09:17 -04006026 struct RxDesc *desc = tp->RxDescArray + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006027 u32 status;
6028
6029 rmb();
David S. Miller8decf862011-09-22 03:23:13 -04006030 status = le32_to_cpu(desc->opts1) & tp->opts1_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006031
6032 if (status & DescOwn)
6033 break;
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006034 if (unlikely(status & RxRES)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00006035 netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n",
6036 status);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006037 dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006038 if (status & (RxRWT | RxRUNT))
Francois Romieucebf8cc2007-10-18 12:06:54 +02006039 dev->stats.rx_length_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006040 if (status & RxCRC)
Francois Romieucebf8cc2007-10-18 12:06:54 +02006041 dev->stats.rx_crc_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006042 if (status & RxFOVF) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01006043 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006044 dev->stats.rx_fifo_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006045 }
Ben Greear6bbe0212012-02-10 15:04:33 +00006046 if ((status & (RxRUNT | RxCRC)) &&
6047 !(status & (RxRWT | RxFOVF)) &&
6048 (dev->features & NETIF_F_RXALL))
6049 goto process_pkt;
6050
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006051 rtl8169_mark_to_asic(desc, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006052 } else {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006053 struct sk_buff *skb;
Ben Greear6bbe0212012-02-10 15:04:33 +00006054 dma_addr_t addr;
6055 int pkt_size;
6056
6057process_pkt:
6058 addr = le64_to_cpu(desc->addr);
Ben Greear79d0c1d2012-02-10 15:04:34 +00006059 if (likely(!(dev->features & NETIF_F_RXFCS)))
6060 pkt_size = (status & 0x00003fff) - 4;
6061 else
6062 pkt_size = status & 0x00003fff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006063
Francois Romieu126fa4b2005-05-12 20:09:17 -04006064 /*
6065 * The driver does not support incoming fragmented
6066 * frames. They are seen as a symptom of over-mtu
6067 * sized frames.
6068 */
6069 if (unlikely(rtl8169_fragmented_frame(status))) {
Francois Romieucebf8cc2007-10-18 12:06:54 +02006070 dev->stats.rx_dropped++;
6071 dev->stats.rx_length_errors++;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006072 rtl8169_mark_to_asic(desc, rx_buf_sz);
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006073 continue;
Francois Romieu126fa4b2005-05-12 20:09:17 -04006074 }
6075
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006076 skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry],
6077 tp, pkt_size, addr);
6078 rtl8169_mark_to_asic(desc, rx_buf_sz);
6079 if (!skb) {
6080 dev->stats.rx_dropped++;
6081 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006082 }
6083
Eric Dumazetadea1ac72010-09-05 20:04:05 -07006084 rtl8169_rx_csum(skb, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006085 skb_put(skb, pkt_size);
6086 skb->protocol = eth_type_trans(skb, dev);
6087
Francois Romieu7a8fc772011-03-01 17:18:33 +01006088 rtl8169_rx_vlan_tag(desc, skb);
6089
Francois Romieu56de4142011-03-15 17:29:31 +01006090 napi_gro_receive(&tp->napi, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006091
Junchang Wang8027aa22012-03-04 23:30:32 +01006092 u64_stats_update_begin(&tp->rx_stats.syncp);
6093 tp->rx_stats.packets++;
6094 tp->rx_stats.bytes += pkt_size;
6095 u64_stats_update_end(&tp->rx_stats.syncp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006096 }
Francois Romieu6dccd162007-02-13 23:38:05 +01006097
6098 /* Work around for AMD plateform. */
Al Viro95e09182007-12-22 18:55:39 +00006099 if ((desc->opts2 & cpu_to_le32(0xfffe000)) &&
Francois Romieu6dccd162007-02-13 23:38:05 +01006100 (tp->mac_version == RTL_GIGA_MAC_VER_05)) {
6101 desc->opts2 = 0;
6102 cur_rx++;
6103 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006104 }
6105
6106 count = cur_rx - tp->cur_rx;
6107 tp->cur_rx = cur_rx;
6108
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006109 tp->dirty_rx += count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006110
6111 return count;
6112}
6113
Francois Romieu07d3f512007-02-21 22:40:46 +01006114static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006115{
Francois Romieu07d3f512007-02-21 22:40:46 +01006116 struct net_device *dev = dev_instance;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006117 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006118 int handled = 0;
Francois Romieu9085cdfa2012-01-26 12:59:08 +01006119 u16 status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006120
Francois Romieu9085cdfa2012-01-26 12:59:08 +01006121 status = rtl_get_events(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006122 if (status && status != 0xffff) {
6123 status &= RTL_EVENT_NAPI | tp->event_slow;
6124 if (status) {
6125 handled = 1;
françois romieu811fd302011-12-04 20:30:45 +00006126
Francois Romieuda78dbf2012-01-26 14:18:23 +01006127 rtl_irq_disable(tp);
6128 napi_schedule(&tp->napi);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006129 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006130 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006131 return IRQ_RETVAL(handled);
6132}
6133
Francois Romieuda78dbf2012-01-26 14:18:23 +01006134/*
6135 * Workqueue context.
6136 */
6137static void rtl_slow_event_work(struct rtl8169_private *tp)
6138{
6139 struct net_device *dev = tp->dev;
6140 u16 status;
6141
6142 status = rtl_get_events(tp) & tp->event_slow;
6143 rtl_ack_events(tp, status);
6144
6145 if (unlikely(status & RxFIFOOver)) {
6146 switch (tp->mac_version) {
6147 /* Work around for rx fifo overflow */
6148 case RTL_GIGA_MAC_VER_11:
6149 netif_stop_queue(dev);
Francois Romieu934714d2012-01-31 11:09:21 +01006150 /* XXX - Hack alert. See rtl_task(). */
6151 set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006152 default:
6153 break;
6154 }
6155 }
6156
6157 if (unlikely(status & SYSErr))
6158 rtl8169_pcierr_interrupt(dev);
6159
6160 if (status & LinkChg)
6161 __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true);
6162
françois romieu7dbb4912012-06-09 10:53:16 +00006163 rtl_irq_enable_all(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006164}
6165
Francois Romieu4422bcd2012-01-26 11:23:32 +01006166static void rtl_task(struct work_struct *work)
6167{
Francois Romieuda78dbf2012-01-26 14:18:23 +01006168 static const struct {
6169 int bitnr;
6170 void (*action)(struct rtl8169_private *);
6171 } rtl_work[] = {
Francois Romieu934714d2012-01-31 11:09:21 +01006172 /* XXX - keep rtl_slow_event_work() as first element. */
Francois Romieuda78dbf2012-01-26 14:18:23 +01006173 { RTL_FLAG_TASK_SLOW_PENDING, rtl_slow_event_work },
6174 { RTL_FLAG_TASK_RESET_PENDING, rtl_reset_work },
6175 { RTL_FLAG_TASK_PHY_PENDING, rtl_phy_work }
6176 };
Francois Romieu4422bcd2012-01-26 11:23:32 +01006177 struct rtl8169_private *tp =
6178 container_of(work, struct rtl8169_private, wk.work);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006179 struct net_device *dev = tp->dev;
6180 int i;
Francois Romieu4422bcd2012-01-26 11:23:32 +01006181
Francois Romieuda78dbf2012-01-26 14:18:23 +01006182 rtl_lock_work(tp);
6183
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006184 if (!netif_running(dev) ||
6185 !test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
Francois Romieuda78dbf2012-01-26 14:18:23 +01006186 goto out_unlock;
6187
6188 for (i = 0; i < ARRAY_SIZE(rtl_work); i++) {
6189 bool pending;
6190
Francois Romieuda78dbf2012-01-26 14:18:23 +01006191 pending = test_and_clear_bit(rtl_work[i].bitnr, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006192 if (pending)
6193 rtl_work[i].action(tp);
6194 }
6195
6196out_unlock:
6197 rtl_unlock_work(tp);
Francois Romieu4422bcd2012-01-26 11:23:32 +01006198}
6199
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006200static int rtl8169_poll(struct napi_struct *napi, int budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006201{
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006202 struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi);
6203 struct net_device *dev = tp->dev;
Francois Romieuda78dbf2012-01-26 14:18:23 +01006204 u16 enable_mask = RTL_EVENT_NAPI | tp->event_slow;
6205 int work_done= 0;
6206 u16 status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006207
Francois Romieuda78dbf2012-01-26 14:18:23 +01006208 status = rtl_get_events(tp);
6209 rtl_ack_events(tp, status & ~tp->event_slow);
6210
6211 if (status & RTL_EVENT_NAPI_RX)
6212 work_done = rtl_rx(dev, tp, (u32) budget);
6213
6214 if (status & RTL_EVENT_NAPI_TX)
6215 rtl_tx(dev, tp);
6216
6217 if (status & tp->event_slow) {
6218 enable_mask &= ~tp->event_slow;
6219
6220 rtl_schedule_task(tp, RTL_FLAG_TASK_SLOW_PENDING);
6221 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006222
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006223 if (work_done < budget) {
Ben Hutchings288379f2009-01-19 16:43:59 -08006224 napi_complete(napi);
David Dillowf11a3772009-05-22 15:29:34 +00006225
Francois Romieuda78dbf2012-01-26 14:18:23 +01006226 rtl_irq_enable(tp, enable_mask);
6227 mmiowb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006228 }
6229
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006230 return work_done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006231}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006232
Francois Romieu523a6092008-09-10 22:28:56 +02006233static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr)
6234{
6235 struct rtl8169_private *tp = netdev_priv(dev);
6236
6237 if (tp->mac_version > RTL_GIGA_MAC_VER_06)
6238 return;
6239
6240 dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff);
6241 RTL_W32(RxMissed, 0);
6242}
6243
Linus Torvalds1da177e2005-04-16 15:20:36 -07006244static void rtl8169_down(struct net_device *dev)
6245{
6246 struct rtl8169_private *tp = netdev_priv(dev);
6247 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006248
Francois Romieu4876cc12011-03-11 21:07:11 +01006249 del_timer_sync(&tp->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006250
Stephen Hemminger93dd79e2007-10-28 17:14:06 +01006251 napi_disable(&tp->napi);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006252 netif_stop_queue(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006253
Hayes Wang92fc43b2011-07-06 15:58:03 +08006254 rtl8169_hw_reset(tp);
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00006255 /*
6256 * At this point device interrupts can not be enabled in any function,
Francois Romieu209e5ac2012-01-26 09:59:50 +01006257 * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task)
6258 * and napi is disabled (rtl8169_poll).
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00006259 */
Francois Romieu523a6092008-09-10 22:28:56 +02006260 rtl8169_rx_missed(dev, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006261
Linus Torvalds1da177e2005-04-16 15:20:36 -07006262 /* Give a racing hard_start_xmit a few cycles to complete. */
Francois Romieuda78dbf2012-01-26 14:18:23 +01006263 synchronize_sched();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006264
Linus Torvalds1da177e2005-04-16 15:20:36 -07006265 rtl8169_tx_clear(tp);
6266
6267 rtl8169_rx_clear(tp);
françois romieu065c27c2011-01-03 15:08:12 +00006268
6269 rtl_pll_power_down(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006270}
6271
6272static int rtl8169_close(struct net_device *dev)
6273{
6274 struct rtl8169_private *tp = netdev_priv(dev);
6275 struct pci_dev *pdev = tp->pci_dev;
6276
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006277 pm_runtime_get_sync(&pdev->dev);
6278
Francois Romieucecb5fd2011-04-01 10:21:07 +02006279 /* Update counters before going down */
Ivan Vecera355423d2009-02-06 21:49:57 -08006280 rtl8169_update_counters(dev);
6281
Francois Romieuda78dbf2012-01-26 14:18:23 +01006282 rtl_lock_work(tp);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006283 clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006284
Linus Torvalds1da177e2005-04-16 15:20:36 -07006285 rtl8169_down(dev);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006286 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006287
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006288 free_irq(pdev->irq, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006289
Stanislaw Gruszka82553bb2010-10-08 04:25:01 +00006290 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
6291 tp->RxPhyAddr);
6292 dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
6293 tp->TxPhyAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006294 tp->TxDescArray = NULL;
6295 tp->RxDescArray = NULL;
6296
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006297 pm_runtime_put_sync(&pdev->dev);
6298
Linus Torvalds1da177e2005-04-16 15:20:36 -07006299 return 0;
6300}
6301
Francois Romieudc1c00c2012-03-08 10:06:18 +01006302#ifdef CONFIG_NET_POLL_CONTROLLER
6303static void rtl8169_netpoll(struct net_device *dev)
6304{
6305 struct rtl8169_private *tp = netdev_priv(dev);
6306
6307 rtl8169_interrupt(tp->pci_dev->irq, dev);
6308}
6309#endif
6310
Francois Romieudf43ac72012-03-08 09:48:40 +01006311static int rtl_open(struct net_device *dev)
6312{
6313 struct rtl8169_private *tp = netdev_priv(dev);
6314 void __iomem *ioaddr = tp->mmio_addr;
6315 struct pci_dev *pdev = tp->pci_dev;
6316 int retval = -ENOMEM;
6317
6318 pm_runtime_get_sync(&pdev->dev);
6319
6320 /*
Jiri Kosinae75d6602012-04-08 21:48:52 +02006321 * Rx and Tx descriptors needs 256 bytes alignment.
Francois Romieudf43ac72012-03-08 09:48:40 +01006322 * dma_alloc_coherent provides more.
6323 */
6324 tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES,
6325 &tp->TxPhyAddr, GFP_KERNEL);
6326 if (!tp->TxDescArray)
6327 goto err_pm_runtime_put;
6328
6329 tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES,
6330 &tp->RxPhyAddr, GFP_KERNEL);
6331 if (!tp->RxDescArray)
6332 goto err_free_tx_0;
6333
6334 retval = rtl8169_init_ring(dev);
6335 if (retval < 0)
6336 goto err_free_rx_1;
6337
6338 INIT_WORK(&tp->wk.work, rtl_task);
6339
6340 smp_mb();
6341
6342 rtl_request_firmware(tp);
6343
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006344 retval = request_irq(pdev->irq, rtl8169_interrupt,
Francois Romieudf43ac72012-03-08 09:48:40 +01006345 (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED,
6346 dev->name, dev);
6347 if (retval < 0)
6348 goto err_release_fw_2;
6349
6350 rtl_lock_work(tp);
6351
6352 set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
6353
6354 napi_enable(&tp->napi);
6355
6356 rtl8169_init_phy(dev, tp);
6357
6358 __rtl8169_set_features(dev, dev->features);
6359
6360 rtl_pll_power_up(tp);
6361
6362 rtl_hw_start(dev);
6363
6364 netif_start_queue(dev);
6365
6366 rtl_unlock_work(tp);
6367
6368 tp->saved_wolopts = 0;
6369 pm_runtime_put_noidle(&pdev->dev);
6370
6371 rtl8169_check_link_status(dev, tp, ioaddr);
6372out:
6373 return retval;
6374
6375err_release_fw_2:
6376 rtl_release_firmware(tp);
6377 rtl8169_rx_clear(tp);
6378err_free_rx_1:
6379 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
6380 tp->RxPhyAddr);
6381 tp->RxDescArray = NULL;
6382err_free_tx_0:
6383 dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
6384 tp->TxPhyAddr);
6385 tp->TxDescArray = NULL;
6386err_pm_runtime_put:
6387 pm_runtime_put_noidle(&pdev->dev);
6388 goto out;
6389}
6390
Junchang Wang8027aa22012-03-04 23:30:32 +01006391static struct rtnl_link_stats64 *
6392rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006393{
6394 struct rtl8169_private *tp = netdev_priv(dev);
6395 void __iomem *ioaddr = tp->mmio_addr;
Junchang Wang8027aa22012-03-04 23:30:32 +01006396 unsigned int start;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006397
Francois Romieuda78dbf2012-01-26 14:18:23 +01006398 if (netif_running(dev))
Francois Romieu523a6092008-09-10 22:28:56 +02006399 rtl8169_rx_missed(dev, ioaddr);
Francois Romieu5b0384f2006-08-16 16:00:01 +02006400
Junchang Wang8027aa22012-03-04 23:30:32 +01006401 do {
6402 start = u64_stats_fetch_begin_bh(&tp->rx_stats.syncp);
6403 stats->rx_packets = tp->rx_stats.packets;
6404 stats->rx_bytes = tp->rx_stats.bytes;
6405 } while (u64_stats_fetch_retry_bh(&tp->rx_stats.syncp, start));
6406
6407
6408 do {
6409 start = u64_stats_fetch_begin_bh(&tp->tx_stats.syncp);
6410 stats->tx_packets = tp->tx_stats.packets;
6411 stats->tx_bytes = tp->tx_stats.bytes;
6412 } while (u64_stats_fetch_retry_bh(&tp->tx_stats.syncp, start));
6413
6414 stats->rx_dropped = dev->stats.rx_dropped;
6415 stats->tx_dropped = dev->stats.tx_dropped;
6416 stats->rx_length_errors = dev->stats.rx_length_errors;
6417 stats->rx_errors = dev->stats.rx_errors;
6418 stats->rx_crc_errors = dev->stats.rx_crc_errors;
6419 stats->rx_fifo_errors = dev->stats.rx_fifo_errors;
6420 stats->rx_missed_errors = dev->stats.rx_missed_errors;
6421
6422 return stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006423}
6424
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006425static void rtl8169_net_suspend(struct net_device *dev)
Francois Romieu5d06a992006-02-23 00:47:58 +01006426{
françois romieu065c27c2011-01-03 15:08:12 +00006427 struct rtl8169_private *tp = netdev_priv(dev);
6428
Francois Romieu5d06a992006-02-23 00:47:58 +01006429 if (!netif_running(dev))
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006430 return;
Francois Romieu5d06a992006-02-23 00:47:58 +01006431
6432 netif_device_detach(dev);
6433 netif_stop_queue(dev);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006434
6435 rtl_lock_work(tp);
6436 napi_disable(&tp->napi);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006437 clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006438 rtl_unlock_work(tp);
6439
6440 rtl_pll_power_down(tp);
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006441}
Francois Romieu5d06a992006-02-23 00:47:58 +01006442
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006443#ifdef CONFIG_PM
6444
6445static int rtl8169_suspend(struct device *device)
6446{
6447 struct pci_dev *pdev = to_pci_dev(device);
6448 struct net_device *dev = pci_get_drvdata(pdev);
6449
6450 rtl8169_net_suspend(dev);
Francois Romieu1371fa62007-04-02 23:01:11 +02006451
Francois Romieu5d06a992006-02-23 00:47:58 +01006452 return 0;
6453}
6454
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006455static void __rtl8169_resume(struct net_device *dev)
6456{
françois romieu065c27c2011-01-03 15:08:12 +00006457 struct rtl8169_private *tp = netdev_priv(dev);
6458
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006459 netif_device_attach(dev);
françois romieu065c27c2011-01-03 15:08:12 +00006460
6461 rtl_pll_power_up(tp);
6462
Artem Savkovcff4c162012-04-03 10:29:11 +00006463 rtl_lock_work(tp);
6464 napi_enable(&tp->napi);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006465 set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Artem Savkovcff4c162012-04-03 10:29:11 +00006466 rtl_unlock_work(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006467
Francois Romieu98ddf982012-01-31 10:47:34 +01006468 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006469}
6470
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006471static int rtl8169_resume(struct device *device)
Francois Romieu5d06a992006-02-23 00:47:58 +01006472{
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006473 struct pci_dev *pdev = to_pci_dev(device);
Francois Romieu5d06a992006-02-23 00:47:58 +01006474 struct net_device *dev = pci_get_drvdata(pdev);
Stanislaw Gruszkafccec102010-10-20 22:25:42 +00006475 struct rtl8169_private *tp = netdev_priv(dev);
6476
6477 rtl8169_init_phy(dev, tp);
Francois Romieu5d06a992006-02-23 00:47:58 +01006478
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006479 if (netif_running(dev))
6480 __rtl8169_resume(dev);
Francois Romieu5d06a992006-02-23 00:47:58 +01006481
Francois Romieu5d06a992006-02-23 00:47:58 +01006482 return 0;
6483}
6484
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006485static int rtl8169_runtime_suspend(struct device *device)
6486{
6487 struct pci_dev *pdev = to_pci_dev(device);
6488 struct net_device *dev = pci_get_drvdata(pdev);
6489 struct rtl8169_private *tp = netdev_priv(dev);
6490
6491 if (!tp->TxDescArray)
6492 return 0;
6493
Francois Romieuda78dbf2012-01-26 14:18:23 +01006494 rtl_lock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006495 tp->saved_wolopts = __rtl8169_get_wol(tp);
6496 __rtl8169_set_wol(tp, WAKE_ANY);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006497 rtl_unlock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006498
6499 rtl8169_net_suspend(dev);
6500
6501 return 0;
6502}
6503
6504static int rtl8169_runtime_resume(struct device *device)
6505{
6506 struct pci_dev *pdev = to_pci_dev(device);
6507 struct net_device *dev = pci_get_drvdata(pdev);
6508 struct rtl8169_private *tp = netdev_priv(dev);
6509
6510 if (!tp->TxDescArray)
6511 return 0;
6512
Francois Romieuda78dbf2012-01-26 14:18:23 +01006513 rtl_lock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006514 __rtl8169_set_wol(tp, tp->saved_wolopts);
6515 tp->saved_wolopts = 0;
Francois Romieuda78dbf2012-01-26 14:18:23 +01006516 rtl_unlock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006517
Stanislaw Gruszkafccec102010-10-20 22:25:42 +00006518 rtl8169_init_phy(dev, tp);
6519
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006520 __rtl8169_resume(dev);
6521
6522 return 0;
6523}
6524
6525static int rtl8169_runtime_idle(struct device *device)
6526{
6527 struct pci_dev *pdev = to_pci_dev(device);
6528 struct net_device *dev = pci_get_drvdata(pdev);
6529 struct rtl8169_private *tp = netdev_priv(dev);
6530
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00006531 return tp->TxDescArray ? -EBUSY : 0;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006532}
6533
Alexey Dobriyan47145212009-12-14 18:00:08 -08006534static const struct dev_pm_ops rtl8169_pm_ops = {
Francois Romieucecb5fd2011-04-01 10:21:07 +02006535 .suspend = rtl8169_suspend,
6536 .resume = rtl8169_resume,
6537 .freeze = rtl8169_suspend,
6538 .thaw = rtl8169_resume,
6539 .poweroff = rtl8169_suspend,
6540 .restore = rtl8169_resume,
6541 .runtime_suspend = rtl8169_runtime_suspend,
6542 .runtime_resume = rtl8169_runtime_resume,
6543 .runtime_idle = rtl8169_runtime_idle,
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006544};
6545
6546#define RTL8169_PM_OPS (&rtl8169_pm_ops)
6547
6548#else /* !CONFIG_PM */
6549
6550#define RTL8169_PM_OPS NULL
6551
6552#endif /* !CONFIG_PM */
6553
David S. Miller1805b2f2011-10-24 18:18:09 -04006554static void rtl_wol_shutdown_quirk(struct rtl8169_private *tp)
6555{
6556 void __iomem *ioaddr = tp->mmio_addr;
6557
6558 /* WoL fails with 8168b when the receiver is disabled. */
6559 switch (tp->mac_version) {
6560 case RTL_GIGA_MAC_VER_11:
6561 case RTL_GIGA_MAC_VER_12:
6562 case RTL_GIGA_MAC_VER_17:
6563 pci_clear_master(tp->pci_dev);
6564
6565 RTL_W8(ChipCmd, CmdRxEnb);
6566 /* PCI commit */
6567 RTL_R8(ChipCmd);
6568 break;
6569 default:
6570 break;
6571 }
6572}
6573
Francois Romieu1765f952008-09-13 17:21:40 +02006574static void rtl_shutdown(struct pci_dev *pdev)
6575{
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006576 struct net_device *dev = pci_get_drvdata(pdev);
françois romieu4bb3f522009-06-17 11:41:45 +00006577 struct rtl8169_private *tp = netdev_priv(dev);
françois romieu2a15cd22012-03-06 01:14:12 +00006578 struct device *d = &pdev->dev;
6579
6580 pm_runtime_get_sync(d);
Francois Romieu1765f952008-09-13 17:21:40 +02006581
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006582 rtl8169_net_suspend(dev);
6583
Francois Romieucecb5fd2011-04-01 10:21:07 +02006584 /* Restore original MAC address */
Ivan Veceracc098dc2009-11-29 23:12:52 -08006585 rtl_rar_set(tp, dev->perm_addr);
6586
Hayes Wang92fc43b2011-07-06 15:58:03 +08006587 rtl8169_hw_reset(tp);
françois romieu4bb3f522009-06-17 11:41:45 +00006588
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006589 if (system_state == SYSTEM_POWER_OFF) {
David S. Miller1805b2f2011-10-24 18:18:09 -04006590 if (__rtl8169_get_wol(tp) & WAKE_ANY) {
6591 rtl_wol_suspend_quirk(tp);
6592 rtl_wol_shutdown_quirk(tp);
françois romieuca52efd2009-07-24 12:34:19 +00006593 }
6594
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006595 pci_wake_from_d3(pdev, true);
6596 pci_set_power_state(pdev, PCI_D3hot);
6597 }
françois romieu2a15cd22012-03-06 01:14:12 +00006598
6599 pm_runtime_put_noidle(d);
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006600}
Francois Romieu5d06a992006-02-23 00:47:58 +01006601
Francois Romieue27566e2012-03-08 09:54:01 +01006602static void __devexit rtl_remove_one(struct pci_dev *pdev)
6603{
6604 struct net_device *dev = pci_get_drvdata(pdev);
6605 struct rtl8169_private *tp = netdev_priv(dev);
6606
6607 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
6608 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
6609 tp->mac_version == RTL_GIGA_MAC_VER_31) {
6610 rtl8168_driver_stop(tp);
6611 }
6612
6613 cancel_work_sync(&tp->wk.work);
6614
Devendra Nagaad1be8d2012-05-31 01:51:20 +00006615 netif_napi_del(&tp->napi);
6616
Francois Romieue27566e2012-03-08 09:54:01 +01006617 unregister_netdev(dev);
6618
6619 rtl_release_firmware(tp);
6620
6621 if (pci_dev_run_wake(pdev))
6622 pm_runtime_get_noresume(&pdev->dev);
6623
6624 /* restore original MAC address */
6625 rtl_rar_set(tp, dev->perm_addr);
6626
6627 rtl_disable_msi(pdev, tp);
6628 rtl8169_release_board(pdev, dev, tp->mmio_addr);
6629 pci_set_drvdata(pdev, NULL);
6630}
6631
Francois Romieufa9c3852012-03-08 10:01:50 +01006632static const struct net_device_ops rtl_netdev_ops = {
Francois Romieudf43ac72012-03-08 09:48:40 +01006633 .ndo_open = rtl_open,
Francois Romieufa9c3852012-03-08 10:01:50 +01006634 .ndo_stop = rtl8169_close,
6635 .ndo_get_stats64 = rtl8169_get_stats64,
6636 .ndo_start_xmit = rtl8169_start_xmit,
6637 .ndo_tx_timeout = rtl8169_tx_timeout,
6638 .ndo_validate_addr = eth_validate_addr,
6639 .ndo_change_mtu = rtl8169_change_mtu,
6640 .ndo_fix_features = rtl8169_fix_features,
6641 .ndo_set_features = rtl8169_set_features,
6642 .ndo_set_mac_address = rtl_set_mac_address,
6643 .ndo_do_ioctl = rtl8169_ioctl,
6644 .ndo_set_rx_mode = rtl_set_rx_mode,
6645#ifdef CONFIG_NET_POLL_CONTROLLER
6646 .ndo_poll_controller = rtl8169_netpoll,
6647#endif
6648
6649};
6650
Francois Romieu31fa8b12012-03-08 10:09:40 +01006651static const struct rtl_cfg_info {
6652 void (*hw_start)(struct net_device *);
6653 unsigned int region;
6654 unsigned int align;
6655 u16 event_slow;
6656 unsigned features;
6657 u8 default_ver;
6658} rtl_cfg_infos [] = {
6659 [RTL_CFG_0] = {
6660 .hw_start = rtl_hw_start_8169,
6661 .region = 1,
6662 .align = 0,
6663 .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver,
6664 .features = RTL_FEATURE_GMII,
6665 .default_ver = RTL_GIGA_MAC_VER_01,
6666 },
6667 [RTL_CFG_1] = {
6668 .hw_start = rtl_hw_start_8168,
6669 .region = 2,
6670 .align = 8,
6671 .event_slow = SYSErr | LinkChg | RxOverflow,
6672 .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI,
6673 .default_ver = RTL_GIGA_MAC_VER_11,
6674 },
6675 [RTL_CFG_2] = {
6676 .hw_start = rtl_hw_start_8101,
6677 .region = 2,
6678 .align = 8,
6679 .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver |
6680 PCSTimeout,
6681 .features = RTL_FEATURE_MSI,
6682 .default_ver = RTL_GIGA_MAC_VER_13,
6683 }
6684};
6685
6686/* Cfg9346_Unlock assumed. */
6687static unsigned rtl_try_msi(struct rtl8169_private *tp,
6688 const struct rtl_cfg_info *cfg)
6689{
6690 void __iomem *ioaddr = tp->mmio_addr;
6691 unsigned msi = 0;
6692 u8 cfg2;
6693
6694 cfg2 = RTL_R8(Config2) & ~MSIEnable;
6695 if (cfg->features & RTL_FEATURE_MSI) {
6696 if (pci_enable_msi(tp->pci_dev)) {
6697 netif_info(tp, hw, tp->dev, "no MSI. Back to INTx.\n");
6698 } else {
6699 cfg2 |= MSIEnable;
6700 msi = RTL_FEATURE_MSI;
6701 }
6702 }
6703 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
6704 RTL_W8(Config2, cfg2);
6705 return msi;
6706}
6707
Hayes Wangc5583862012-07-02 17:23:22 +08006708DECLARE_RTL_COND(rtl_link_list_ready_cond)
6709{
6710 void __iomem *ioaddr = tp->mmio_addr;
6711
6712 return RTL_R8(MCU) & LINK_LIST_RDY;
6713}
6714
6715DECLARE_RTL_COND(rtl_rxtx_empty_cond)
6716{
6717 void __iomem *ioaddr = tp->mmio_addr;
6718
6719 return (RTL_R8(MCU) & RXTX_EMPTY) == RXTX_EMPTY;
6720}
6721
6722static void __devinit rtl_hw_init_8168g(struct rtl8169_private *tp)
6723{
6724 void __iomem *ioaddr = tp->mmio_addr;
6725 u32 data;
6726
6727 tp->ocp_base = OCP_STD_PHY_BASE;
6728
6729 RTL_W32(MISC, RTL_R32(MISC) | RXDV_GATED_EN);
6730
6731 if (!rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42))
6732 return;
6733
6734 if (!rtl_udelay_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42))
6735 return;
6736
6737 RTL_W8(ChipCmd, RTL_R8(ChipCmd) & ~(CmdTxEnb | CmdRxEnb));
6738 msleep(1);
6739 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
6740
Hayes Wang5f8bcce2012-07-10 08:47:05 +02006741 data = r8168_mac_ocp_read(tp, 0xe8de);
Hayes Wangc5583862012-07-02 17:23:22 +08006742 data &= ~(1 << 14);
6743 r8168_mac_ocp_write(tp, 0xe8de, data);
6744
6745 if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42))
6746 return;
6747
Hayes Wang5f8bcce2012-07-10 08:47:05 +02006748 data = r8168_mac_ocp_read(tp, 0xe8de);
Hayes Wangc5583862012-07-02 17:23:22 +08006749 data |= (1 << 15);
6750 r8168_mac_ocp_write(tp, 0xe8de, data);
6751
6752 if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42))
6753 return;
6754}
6755
6756static void __devinit rtl_hw_initialize(struct rtl8169_private *tp)
6757{
6758 switch (tp->mac_version) {
6759 case RTL_GIGA_MAC_VER_40:
6760 case RTL_GIGA_MAC_VER_41:
6761 rtl_hw_init_8168g(tp);
6762 break;
6763
6764 default:
6765 break;
6766 }
6767}
6768
Francois Romieu3b6cf252012-03-08 09:59:04 +01006769static int __devinit
6770rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
6771{
6772 const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
6773 const unsigned int region = cfg->region;
6774 struct rtl8169_private *tp;
6775 struct mii_if_info *mii;
6776 struct net_device *dev;
6777 void __iomem *ioaddr;
6778 int chipset, i;
6779 int rc;
6780
6781 if (netif_msg_drv(&debug)) {
6782 printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
6783 MODULENAME, RTL8169_VERSION);
6784 }
6785
6786 dev = alloc_etherdev(sizeof (*tp));
6787 if (!dev) {
6788 rc = -ENOMEM;
6789 goto out;
6790 }
6791
6792 SET_NETDEV_DEV(dev, &pdev->dev);
Francois Romieufa9c3852012-03-08 10:01:50 +01006793 dev->netdev_ops = &rtl_netdev_ops;
Francois Romieu3b6cf252012-03-08 09:59:04 +01006794 tp = netdev_priv(dev);
6795 tp->dev = dev;
6796 tp->pci_dev = pdev;
6797 tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
6798
6799 mii = &tp->mii;
6800 mii->dev = dev;
6801 mii->mdio_read = rtl_mdio_read;
6802 mii->mdio_write = rtl_mdio_write;
6803 mii->phy_id_mask = 0x1f;
6804 mii->reg_num_mask = 0x1f;
6805 mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII);
6806
6807 /* disable ASPM completely as that cause random device stop working
6808 * problems as well as full system hangs for some PCIe devices users */
6809 pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
6810 PCIE_LINK_STATE_CLKPM);
6811
6812 /* enable device (incl. PCI PM wakeup and hotplug setup) */
6813 rc = pci_enable_device(pdev);
6814 if (rc < 0) {
6815 netif_err(tp, probe, dev, "enable failure\n");
6816 goto err_out_free_dev_1;
6817 }
6818
6819 if (pci_set_mwi(pdev) < 0)
6820 netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n");
6821
6822 /* make sure PCI base addr 1 is MMIO */
6823 if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) {
6824 netif_err(tp, probe, dev,
6825 "region #%d not an MMIO resource, aborting\n",
6826 region);
6827 rc = -ENODEV;
6828 goto err_out_mwi_2;
6829 }
6830
6831 /* check for weird/broken PCI region reporting */
6832 if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) {
6833 netif_err(tp, probe, dev,
6834 "Invalid PCI region size(s), aborting\n");
6835 rc = -ENODEV;
6836 goto err_out_mwi_2;
6837 }
6838
6839 rc = pci_request_regions(pdev, MODULENAME);
6840 if (rc < 0) {
6841 netif_err(tp, probe, dev, "could not request regions\n");
6842 goto err_out_mwi_2;
6843 }
6844
6845 tp->cp_cmd = RxChkSum;
6846
6847 if ((sizeof(dma_addr_t) > 4) &&
6848 !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) {
6849 tp->cp_cmd |= PCIDAC;
6850 dev->features |= NETIF_F_HIGHDMA;
6851 } else {
6852 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
6853 if (rc < 0) {
6854 netif_err(tp, probe, dev, "DMA configuration failed\n");
6855 goto err_out_free_res_3;
6856 }
6857 }
6858
6859 /* ioremap MMIO region */
6860 ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE);
6861 if (!ioaddr) {
6862 netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n");
6863 rc = -EIO;
6864 goto err_out_free_res_3;
6865 }
6866 tp->mmio_addr = ioaddr;
6867
6868 if (!pci_is_pcie(pdev))
6869 netif_info(tp, probe, dev, "not PCI Express\n");
6870
6871 /* Identify chip attached to board */
6872 rtl8169_get_mac_version(tp, dev, cfg->default_ver);
6873
6874 rtl_init_rxcfg(tp);
6875
6876 rtl_irq_disable(tp);
6877
Hayes Wangc5583862012-07-02 17:23:22 +08006878 rtl_hw_initialize(tp);
6879
Francois Romieu3b6cf252012-03-08 09:59:04 +01006880 rtl_hw_reset(tp);
6881
6882 rtl_ack_events(tp, 0xffff);
6883
6884 pci_set_master(pdev);
6885
6886 /*
6887 * Pretend we are using VLANs; This bypasses a nasty bug where
6888 * Interrupts stop flowing on high load on 8110SCd controllers.
6889 */
6890 if (tp->mac_version == RTL_GIGA_MAC_VER_05)
6891 tp->cp_cmd |= RxVlan;
6892
6893 rtl_init_mdio_ops(tp);
6894 rtl_init_pll_power_ops(tp);
6895 rtl_init_jumbo_ops(tp);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08006896 rtl_init_csi_ops(tp);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006897
6898 rtl8169_print_mac_version(tp);
6899
6900 chipset = tp->mac_version;
6901 tp->txd_version = rtl_chip_infos[chipset].txd_version;
6902
6903 RTL_W8(Cfg9346, Cfg9346_Unlock);
6904 RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
6905 RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
6906 if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
6907 tp->features |= RTL_FEATURE_WOL;
6908 if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0)
6909 tp->features |= RTL_FEATURE_WOL;
6910 tp->features |= rtl_try_msi(tp, cfg);
6911 RTL_W8(Cfg9346, Cfg9346_Lock);
6912
6913 if (rtl_tbi_enabled(tp)) {
6914 tp->set_speed = rtl8169_set_speed_tbi;
6915 tp->get_settings = rtl8169_gset_tbi;
6916 tp->phy_reset_enable = rtl8169_tbi_reset_enable;
6917 tp->phy_reset_pending = rtl8169_tbi_reset_pending;
6918 tp->link_ok = rtl8169_tbi_link_ok;
6919 tp->do_ioctl = rtl_tbi_ioctl;
6920 } else {
6921 tp->set_speed = rtl8169_set_speed_xmii;
6922 tp->get_settings = rtl8169_gset_xmii;
6923 tp->phy_reset_enable = rtl8169_xmii_reset_enable;
6924 tp->phy_reset_pending = rtl8169_xmii_reset_pending;
6925 tp->link_ok = rtl8169_xmii_link_ok;
6926 tp->do_ioctl = rtl_xmii_ioctl;
6927 }
6928
6929 mutex_init(&tp->wk.mutex);
6930
6931 /* Get MAC address */
6932 for (i = 0; i < ETH_ALEN; i++)
6933 dev->dev_addr[i] = RTL_R8(MAC0 + i);
6934 memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
6935
6936 SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops);
6937 dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
Francois Romieu3b6cf252012-03-08 09:59:04 +01006938
6939 netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT);
6940
6941 /* don't enable SG, IP_CSUM and TSO by default - it might not work
6942 * properly for all devices */
6943 dev->features |= NETIF_F_RXCSUM |
6944 NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
6945
6946 dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
6947 NETIF_F_RXCSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
6948 dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
6949 NETIF_F_HIGHDMA;
6950
6951 if (tp->mac_version == RTL_GIGA_MAC_VER_05)
6952 /* 8110SCd requires hardware Rx VLAN - disallow toggling */
6953 dev->hw_features &= ~NETIF_F_HW_VLAN_RX;
6954
6955 dev->hw_features |= NETIF_F_RXALL;
6956 dev->hw_features |= NETIF_F_RXFCS;
6957
6958 tp->hw_start = cfg->hw_start;
6959 tp->event_slow = cfg->event_slow;
6960
6961 tp->opts1_mask = (tp->mac_version != RTL_GIGA_MAC_VER_01) ?
6962 ~(RxBOVF | RxFOVF) : ~0;
6963
6964 init_timer(&tp->timer);
6965 tp->timer.data = (unsigned long) dev;
6966 tp->timer.function = rtl8169_phy_timer;
6967
6968 tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
6969
6970 rc = register_netdev(dev);
6971 if (rc < 0)
6972 goto err_out_msi_4;
6973
6974 pci_set_drvdata(pdev, dev);
6975
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006976 netif_info(tp, probe, dev, "%s at 0x%p, %pM, XID %08x IRQ %d\n",
6977 rtl_chip_infos[chipset].name, ioaddr, dev->dev_addr,
6978 (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), pdev->irq);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006979 if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) {
6980 netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, "
6981 "tx checksumming: %s]\n",
6982 rtl_chip_infos[chipset].jumbo_max,
6983 rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko");
6984 }
6985
6986 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
6987 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
6988 tp->mac_version == RTL_GIGA_MAC_VER_31) {
6989 rtl8168_driver_start(tp);
6990 }
6991
6992 device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
6993
6994 if (pci_dev_run_wake(pdev))
6995 pm_runtime_put_noidle(&pdev->dev);
6996
6997 netif_carrier_off(dev);
6998
6999out:
7000 return rc;
7001
7002err_out_msi_4:
Devendra Nagaad1be8d2012-05-31 01:51:20 +00007003 netif_napi_del(&tp->napi);
Francois Romieu3b6cf252012-03-08 09:59:04 +01007004 rtl_disable_msi(pdev, tp);
7005 iounmap(ioaddr);
7006err_out_free_res_3:
7007 pci_release_regions(pdev);
7008err_out_mwi_2:
7009 pci_clear_mwi(pdev);
7010 pci_disable_device(pdev);
7011err_out_free_dev_1:
7012 free_netdev(dev);
7013 goto out;
7014}
7015
Linus Torvalds1da177e2005-04-16 15:20:36 -07007016static struct pci_driver rtl8169_pci_driver = {
7017 .name = MODULENAME,
7018 .id_table = rtl8169_pci_tbl,
Francois Romieu3b6cf252012-03-08 09:59:04 +01007019 .probe = rtl_init_one,
Francois Romieue27566e2012-03-08 09:54:01 +01007020 .remove = __devexit_p(rtl_remove_one),
Francois Romieu1765f952008-09-13 17:21:40 +02007021 .shutdown = rtl_shutdown,
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00007022 .driver.pm = RTL8169_PM_OPS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07007023};
7024
Devendra Naga3eeb7da2012-10-26 09:27:42 +00007025module_pci_driver(rtl8169_pci_driver);