r8169:add support for RTL8168H and RTL8107E

RTL8168H is Realtek PCIe Gigabit Ethernet controller.
RTL8107E is Realtek PCIe Fast Ethernet controller.

This patch add support for these two chips.

Signed-off-by: Chun-Hao Lin <hau@realtek.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Chun-Hao Lin 2014-08-20 01:54:04 +08:00 committed by David S. Miller
parent d4261e5650
commit 6e1d0b8988

View File

@ -52,6 +52,10 @@
#define FIRMWARE_8106E_2 "rtl_nic/rtl8106e-2.fw"
#define FIRMWARE_8168G_2 "rtl_nic/rtl8168g-2.fw"
#define FIRMWARE_8168G_3 "rtl_nic/rtl8168g-3.fw"
#define FIRMWARE_8168H_1 "rtl_nic/rtl8168h-1.fw"
#define FIRMWARE_8168H_2 "rtl_nic/rtl8168h-2.fw"
#define FIRMWARE_8107E_1 "rtl_nic/rtl8107e-1.fw"
#define FIRMWARE_8107E_2 "rtl_nic/rtl8107e-2.fw"
#ifdef RTL8169_DEBUG
#define assert(expr) \
@ -147,6 +151,10 @@ enum mac_version {
RTL_GIGA_MAC_VER_42,
RTL_GIGA_MAC_VER_43,
RTL_GIGA_MAC_VER_44,
RTL_GIGA_MAC_VER_45,
RTL_GIGA_MAC_VER_46,
RTL_GIGA_MAC_VER_47,
RTL_GIGA_MAC_VER_48,
RTL_GIGA_MAC_NONE = 0xff,
};
@ -282,6 +290,18 @@ static const struct {
[RTL_GIGA_MAC_VER_44] =
_R("RTL8411", RTL_TD_1, FIRMWARE_8411_2,
JUMBO_9K, false),
[RTL_GIGA_MAC_VER_45] =
_R("RTL8168h/8111h", RTL_TD_1, FIRMWARE_8168H_1,
JUMBO_9K, false),
[RTL_GIGA_MAC_VER_46] =
_R("RTL8168h/8111h", RTL_TD_1, FIRMWARE_8168H_2,
JUMBO_9K, false),
[RTL_GIGA_MAC_VER_47] =
_R("RTL8107e", RTL_TD_1, FIRMWARE_8107E_1,
JUMBO_1K, false),
[RTL_GIGA_MAC_VER_48] =
_R("RTL8107e", RTL_TD_1, FIRMWARE_8107E_2,
JUMBO_1K, false),
};
#undef _R
@ -410,6 +430,7 @@ enum rtl8168_8101_registers {
#define EPHYAR_DATA_MASK 0xffff
DLLPR = 0xd0,
#define PFM_EN (1 << 6)
#define TX_10M_PS_EN (1 << 7)
DBG_REG = 0xd1,
#define FIX_NAK_1 (1 << 4)
#define FIX_NAK_2 (1 << 3)
@ -429,6 +450,8 @@ enum rtl8168_8101_registers {
#define EFUSEAR_REG_MASK 0x03ff
#define EFUSEAR_REG_SHIFT 8
#define EFUSEAR_DATA_MASK 0xff
MISC_1 = 0xf2,
#define PFM_D3COLD_EN (1 << 6)
};
enum rtl8168_registers {
@ -447,6 +470,7 @@ enum rtl8168_registers {
#define ERIAR_MASK_SHIFT 12
#define ERIAR_MASK_0001 (0x1 << ERIAR_MASK_SHIFT)
#define ERIAR_MASK_0011 (0x3 << ERIAR_MASK_SHIFT)
#define ERIAR_MASK_0100 (0x4 << ERIAR_MASK_SHIFT)
#define ERIAR_MASK_0101 (0x5 << ERIAR_MASK_SHIFT)
#define ERIAR_MASK_1111 (0xf << ERIAR_MASK_SHIFT)
EPHY_RXER_NUM = 0x7c,
@ -598,6 +622,9 @@ enum rtl_register_content {
/* DumpCounterCommand */
CounterDump = 0x8,
/* magic enable v2 */
MagicPacket_v2 = (1 << 16), /* Wake up when receives a Magic Packet */
};
enum rtl_desc_bit {
@ -823,6 +850,8 @@ MODULE_FIRMWARE(FIRMWARE_8106E_1);
MODULE_FIRMWARE(FIRMWARE_8106E_2);
MODULE_FIRMWARE(FIRMWARE_8168G_2);
MODULE_FIRMWARE(FIRMWARE_8168G_3);
MODULE_FIRMWARE(FIRMWARE_8168H_1);
MODULE_FIRMWARE(FIRMWARE_8168H_2);
static void rtl_lock_work(struct rtl8169_private *tp)
{
@ -1514,8 +1543,17 @@ static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
options = RTL_R8(Config3);
if (options & LinkUp)
wolopts |= WAKE_PHY;
if (options & MagicPacket)
wolopts |= WAKE_MAGIC;
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_45:
case RTL_GIGA_MAC_VER_46:
if (rtl_eri_read(tp, 0xdc, ERIAR_EXGMAC) & MagicPacket_v2)
wolopts |= WAKE_MAGIC;
break;
default:
if (options & MagicPacket)
wolopts |= WAKE_MAGIC;
break;
}
options = RTL_R8(Config5);
if (options & UWF)
@ -1543,24 +1581,48 @@ static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
{
void __iomem *ioaddr = tp->mmio_addr;
unsigned int i;
unsigned int i, tmp;
static const struct {
u32 opt;
u16 reg;
u8 mask;
} cfg[] = {
{ WAKE_PHY, Config3, LinkUp },
{ WAKE_MAGIC, Config3, MagicPacket },
{ WAKE_UCAST, Config5, UWF },
{ WAKE_BCAST, Config5, BWF },
{ WAKE_MCAST, Config5, MWF },
{ WAKE_ANY, Config5, LanWake }
{ WAKE_ANY, Config5, LanWake },
{ WAKE_MAGIC, Config3, MagicPacket }
};
u8 options;
RTL_W8(Cfg9346, Cfg9346_Unlock);
for (i = 0; i < ARRAY_SIZE(cfg); i++) {
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_45:
case RTL_GIGA_MAC_VER_46:
tmp = ARRAY_SIZE(cfg) - 1;
if (wolopts & WAKE_MAGIC)
rtl_w1w0_eri(tp,
0x0dc,
ERIAR_MASK_0100,
MagicPacket_v2,
0x0000,
ERIAR_EXGMAC);
else
rtl_w1w0_eri(tp,
0x0dc,
ERIAR_MASK_0100,
0x0000,
MagicPacket_v2,
ERIAR_EXGMAC);
break;
default:
tmp = ARRAY_SIZE(cfg);
break;
}
for (i = 0; i < tmp; i++) {
options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
if (wolopts & cfg[i].opt)
options |= cfg[i].mask;
@ -2044,6 +2106,10 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
u32 val;
int mac_version;
} mac_info[] = {
/* 8168H family. */
{ 0x7cf00000, 0x54100000, RTL_GIGA_MAC_VER_46 },
{ 0x7cf00000, 0x54000000, RTL_GIGA_MAC_VER_45 },
/* 8168G family. */
{ 0x7cf00000, 0x5c800000, RTL_GIGA_MAC_VER_44 },
{ 0x7cf00000, 0x50900000, RTL_GIGA_MAC_VER_42 },
@ -2139,6 +2205,14 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
tp->mac_version = tp->mii.supports_gmii ?
RTL_GIGA_MAC_VER_42 :
RTL_GIGA_MAC_VER_43;
} else if (tp->mac_version == RTL_GIGA_MAC_VER_45) {
tp->mac_version = tp->mii.supports_gmii ?
RTL_GIGA_MAC_VER_45 :
RTL_GIGA_MAC_VER_47;
} else if (tp->mac_version == RTL_GIGA_MAC_VER_46) {
tp->mac_version = tp->mii.supports_gmii ?
RTL_GIGA_MAC_VER_46 :
RTL_GIGA_MAC_VER_48;
}
}
@ -3464,6 +3538,189 @@ static void rtl8168g_2_hw_phy_config(struct rtl8169_private *tp)
rtl_apply_firmware(tp);
}
static void rtl8168h_1_hw_phy_config(struct rtl8169_private *tp)
{
u16 dout_tapbin;
u32 data;
rtl_apply_firmware(tp);
/* CHN EST parameters adjust - giga master */
rtl_writephy(tp, 0x1f, 0x0a43);
rtl_writephy(tp, 0x13, 0x809b);
rtl_w1w0_phy(tp, 0x14, 0x8000, 0xf800);
rtl_writephy(tp, 0x13, 0x80a2);
rtl_w1w0_phy(tp, 0x14, 0x8000, 0xff00);
rtl_writephy(tp, 0x13, 0x80a4);
rtl_w1w0_phy(tp, 0x14, 0x8500, 0xff00);
rtl_writephy(tp, 0x13, 0x809c);
rtl_w1w0_phy(tp, 0x14, 0xbd00, 0xff00);
rtl_writephy(tp, 0x1f, 0x0000);
/* CHN EST parameters adjust - giga slave */
rtl_writephy(tp, 0x1f, 0x0a43);
rtl_writephy(tp, 0x13, 0x80ad);
rtl_w1w0_phy(tp, 0x14, 0x7000, 0xf800);
rtl_writephy(tp, 0x13, 0x80b4);
rtl_w1w0_phy(tp, 0x14, 0x5000, 0xff00);
rtl_writephy(tp, 0x13, 0x80ac);
rtl_w1w0_phy(tp, 0x14, 0x4000, 0xff00);
rtl_writephy(tp, 0x1f, 0x0000);
/* CHN EST parameters adjust - fnet */
rtl_writephy(tp, 0x1f, 0x0a43);
rtl_writephy(tp, 0x13, 0x808e);
rtl_w1w0_phy(tp, 0x14, 0x1200, 0xff00);
rtl_writephy(tp, 0x13, 0x8090);
rtl_w1w0_phy(tp, 0x14, 0xe500, 0xff00);
rtl_writephy(tp, 0x13, 0x8092);
rtl_w1w0_phy(tp, 0x14, 0x9f00, 0xff00);
rtl_writephy(tp, 0x1f, 0x0000);
/* enable R-tune & PGA-retune function */
dout_tapbin = 0;
rtl_writephy(tp, 0x1f, 0x0a46);
data = rtl_readphy(tp, 0x13);
data &= 3;
data <<= 2;
dout_tapbin |= data;
data = rtl_readphy(tp, 0x12);
data &= 0xc000;
data >>= 14;
dout_tapbin |= data;
dout_tapbin = ~(dout_tapbin^0x08);
dout_tapbin <<= 12;
dout_tapbin &= 0xf000;
rtl_writephy(tp, 0x1f, 0x0a43);
rtl_writephy(tp, 0x13, 0x827a);
rtl_w1w0_phy(tp, 0x14, dout_tapbin, 0xf000);
rtl_writephy(tp, 0x13, 0x827b);
rtl_w1w0_phy(tp, 0x14, dout_tapbin, 0xf000);
rtl_writephy(tp, 0x13, 0x827c);
rtl_w1w0_phy(tp, 0x14, dout_tapbin, 0xf000);
rtl_writephy(tp, 0x13, 0x827d);
rtl_w1w0_phy(tp, 0x14, dout_tapbin, 0xf000);
rtl_writephy(tp, 0x1f, 0x0a43);
rtl_writephy(tp, 0x13, 0x0811);
rtl_w1w0_phy(tp, 0x14, 0x0800, 0x0000);
rtl_writephy(tp, 0x1f, 0x0a42);
rtl_w1w0_phy(tp, 0x16, 0x0002, 0x0000);
rtl_writephy(tp, 0x1f, 0x0000);
/* enable GPHY 10M */
rtl_writephy(tp, 0x1f, 0x0a44);
rtl_w1w0_phy(tp, 0x11, 0x0800, 0x0000);
rtl_writephy(tp, 0x1f, 0x0000);
/* SAR ADC performance */
rtl_writephy(tp, 0x1f, 0x0bca);
rtl_w1w0_phy(tp, 0x17, 0x4000, 0x3000);
rtl_writephy(tp, 0x1f, 0x0000);
rtl_writephy(tp, 0x1f, 0x0a43);
rtl_writephy(tp, 0x13, 0x803f);
rtl_w1w0_phy(tp, 0x14, 0x0000, 0x3000);
rtl_writephy(tp, 0x13, 0x8047);
rtl_w1w0_phy(tp, 0x14, 0x0000, 0x3000);
rtl_writephy(tp, 0x13, 0x804f);
rtl_w1w0_phy(tp, 0x14, 0x0000, 0x3000);
rtl_writephy(tp, 0x13, 0x8057);
rtl_w1w0_phy(tp, 0x14, 0x0000, 0x3000);
rtl_writephy(tp, 0x13, 0x805f);
rtl_w1w0_phy(tp, 0x14, 0x0000, 0x3000);
rtl_writephy(tp, 0x13, 0x8067);
rtl_w1w0_phy(tp, 0x14, 0x0000, 0x3000);
rtl_writephy(tp, 0x13, 0x806f);
rtl_w1w0_phy(tp, 0x14, 0x0000, 0x3000);
rtl_writephy(tp, 0x1f, 0x0000);
/* disable phy pfm mode */
rtl_writephy(tp, 0x1f, 0x0a44);
rtl_w1w0_phy(tp, 0x14, 0x0000, 0x0080);
rtl_writephy(tp, 0x1f, 0x0000);
/* Check ALDPS bit, disable it if enabled */
rtl_writephy(tp, 0x1f, 0x0a43);
if (rtl_readphy(tp, 0x10) & 0x0004)
rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0004);
rtl_writephy(tp, 0x1f, 0x0000);
}
static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp)
{
u16 ioffset_p3, ioffset_p2, ioffset_p1, ioffset_p0;
u16 rlen;
u32 data;
rtl_apply_firmware(tp);
/* CHIN EST parameter update */
rtl_writephy(tp, 0x1f, 0x0a43);
rtl_writephy(tp, 0x13, 0x808a);
rtl_w1w0_phy(tp, 0x14, 0x000a, 0x003f);
rtl_writephy(tp, 0x1f, 0x0000);
/* enable R-tune & PGA-retune function */
rtl_writephy(tp, 0x1f, 0x0a43);
rtl_writephy(tp, 0x13, 0x0811);
rtl_w1w0_phy(tp, 0x14, 0x0800, 0x0000);
rtl_writephy(tp, 0x1f, 0x0a42);
rtl_w1w0_phy(tp, 0x16, 0x0002, 0x0000);
rtl_writephy(tp, 0x1f, 0x0000);
/* enable GPHY 10M */
rtl_writephy(tp, 0x1f, 0x0a44);
rtl_w1w0_phy(tp, 0x11, 0x0800, 0x0000);
rtl_writephy(tp, 0x1f, 0x0000);
r8168_mac_ocp_write(tp, 0xdd02, 0x807d);
data = r8168_mac_ocp_read(tp, 0xdd02);
ioffset_p3 = ((data & 0x80)>>7);
ioffset_p3 <<= 3;
data = r8168_mac_ocp_read(tp, 0xdd00);
ioffset_p3 |= ((data & (0xe000))>>13);
ioffset_p2 = ((data & (0x1e00))>>9);
ioffset_p1 = ((data & (0x01e0))>>5);
ioffset_p0 = ((data & 0x0010)>>4);
ioffset_p0 <<= 3;
ioffset_p0 |= (data & (0x07));
data = (ioffset_p3<<12)|(ioffset_p2<<8)|(ioffset_p1<<4)|(ioffset_p0);
if ((ioffset_p3 != 0x0F) || (ioffset_p2 != 0x0F) ||
(ioffset_p1 != 0x0F) || (ioffset_p0 == 0x0F)) {
rtl_writephy(tp, 0x1f, 0x0bcf);
rtl_writephy(tp, 0x16, data);
rtl_writephy(tp, 0x1f, 0x0000);
}
/* Modify rlen (TX LPF corner frequency) level */
rtl_writephy(tp, 0x1f, 0x0bcd);
data = rtl_readphy(tp, 0x16);
data &= 0x000f;
rlen = 0;
if (data > 3)
rlen = data - 3;
data = rlen | (rlen<<4) | (rlen<<8) | (rlen<<12);
rtl_writephy(tp, 0x17, data);
rtl_writephy(tp, 0x1f, 0x0bcd);
rtl_writephy(tp, 0x1f, 0x0000);
/* disable phy pfm mode */
rtl_writephy(tp, 0x1f, 0x0a44);
rtl_w1w0_phy(tp, 0x14, 0x0000, 0x0080);
rtl_writephy(tp, 0x1f, 0x0000);
/* Check ALDPS bit, disable it if enabled */
rtl_writephy(tp, 0x1f, 0x0a43);
if (rtl_readphy(tp, 0x10) & 0x0004)
rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0004);
rtl_writephy(tp, 0x1f, 0x0000);
}
static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
{
static const struct phy_reg phy_reg_init[] = {
@ -3654,6 +3911,14 @@ static void rtl_hw_phy_config(struct net_device *dev)
case RTL_GIGA_MAC_VER_44:
rtl8168g_2_hw_phy_config(tp);
break;
case RTL_GIGA_MAC_VER_45:
case RTL_GIGA_MAC_VER_47:
rtl8168h_1_hw_phy_config(tp);
break;
case RTL_GIGA_MAC_VER_46:
case RTL_GIGA_MAC_VER_48:
rtl8168h_2_hw_phy_config(tp);
break;
case RTL_GIGA_MAC_VER_41:
default:
@ -3865,6 +4130,10 @@ static void rtl_init_mdio_ops(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_42:
case RTL_GIGA_MAC_VER_43:
case RTL_GIGA_MAC_VER_44:
case RTL_GIGA_MAC_VER_45:
case RTL_GIGA_MAC_VER_46:
case RTL_GIGA_MAC_VER_47:
case RTL_GIGA_MAC_VER_48:
ops->write = r8168g_mdio_write;
ops->read = r8168g_mdio_read;
break;
@ -3919,6 +4188,10 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_42:
case RTL_GIGA_MAC_VER_43:
case RTL_GIGA_MAC_VER_44:
case RTL_GIGA_MAC_VER_45:
case RTL_GIGA_MAC_VER_46:
case RTL_GIGA_MAC_VER_47:
case RTL_GIGA_MAC_VER_48:
RTL_W32(RxConfig, RTL_R32(RxConfig) |
AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
break;
@ -3987,6 +4260,10 @@ static void r810x_pll_power_up(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_13:
case RTL_GIGA_MAC_VER_16:
break;
case RTL_GIGA_MAC_VER_47:
case RTL_GIGA_MAC_VER_48:
RTL_W8(PMCH, RTL_R8(PMCH) | 0xC0);
break;
default:
RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
break;
@ -4087,6 +4364,8 @@ static void r8168_pll_power_down(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_31:
case RTL_GIGA_MAC_VER_32:
case RTL_GIGA_MAC_VER_33:
case RTL_GIGA_MAC_VER_45:
case RTL_GIGA_MAC_VER_46:
RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
break;
case RTL_GIGA_MAC_VER_40:
@ -4111,6 +4390,10 @@ static void r8168_pll_power_up(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_33:
RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
break;
case RTL_GIGA_MAC_VER_45:
case RTL_GIGA_MAC_VER_46:
RTL_W8(PMCH, RTL_R8(PMCH) | 0xC0);
break;
case RTL_GIGA_MAC_VER_40:
case RTL_GIGA_MAC_VER_41:
rtl_w1w0_eri(tp, 0x1a8, ERIAR_MASK_1111, 0xfc000000,
@ -4153,6 +4436,8 @@ static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_37:
case RTL_GIGA_MAC_VER_39:
case RTL_GIGA_MAC_VER_43:
case RTL_GIGA_MAC_VER_47:
case RTL_GIGA_MAC_VER_48:
ops->down = r810x_pll_power_down;
ops->up = r810x_pll_power_up;
break;
@ -4182,6 +4467,8 @@ static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_41:
case RTL_GIGA_MAC_VER_42:
case RTL_GIGA_MAC_VER_44:
case RTL_GIGA_MAC_VER_45:
case RTL_GIGA_MAC_VER_46:
ops->down = r8168_pll_power_down;
ops->up = r8168_pll_power_up;
break;
@ -4232,6 +4519,10 @@ static void rtl_init_rxcfg(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_42:
case RTL_GIGA_MAC_VER_43:
case RTL_GIGA_MAC_VER_44:
case RTL_GIGA_MAC_VER_45:
case RTL_GIGA_MAC_VER_46:
case RTL_GIGA_MAC_VER_47:
case RTL_GIGA_MAC_VER_48:
RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST | RX_EARLY_OFF);
break;
default:
@ -4393,6 +4684,10 @@ static void rtl_init_jumbo_ops(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_42:
case RTL_GIGA_MAC_VER_43:
case RTL_GIGA_MAC_VER_44:
case RTL_GIGA_MAC_VER_45:
case RTL_GIGA_MAC_VER_46:
case RTL_GIGA_MAC_VER_47:
case RTL_GIGA_MAC_VER_48:
default:
ops->disable = NULL;
ops->enable = NULL;
@ -4495,15 +4790,19 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp)
tp->mac_version == RTL_GIGA_MAC_VER_31) {
rtl_udelay_loop_wait_low(tp, &rtl_npq_cond, 20, 42*42);
} else if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
tp->mac_version == RTL_GIGA_MAC_VER_35 ||
tp->mac_version == RTL_GIGA_MAC_VER_36 ||
tp->mac_version == RTL_GIGA_MAC_VER_37 ||
tp->mac_version == RTL_GIGA_MAC_VER_40 ||
tp->mac_version == RTL_GIGA_MAC_VER_41 ||
tp->mac_version == RTL_GIGA_MAC_VER_42 ||
tp->mac_version == RTL_GIGA_MAC_VER_43 ||
tp->mac_version == RTL_GIGA_MAC_VER_44 ||
tp->mac_version == RTL_GIGA_MAC_VER_38) {
tp->mac_version == RTL_GIGA_MAC_VER_35 ||
tp->mac_version == RTL_GIGA_MAC_VER_36 ||
tp->mac_version == RTL_GIGA_MAC_VER_37 ||
tp->mac_version == RTL_GIGA_MAC_VER_38 ||
tp->mac_version == RTL_GIGA_MAC_VER_40 ||
tp->mac_version == RTL_GIGA_MAC_VER_41 ||
tp->mac_version == RTL_GIGA_MAC_VER_42 ||
tp->mac_version == RTL_GIGA_MAC_VER_43 ||
tp->mac_version == RTL_GIGA_MAC_VER_44 ||
tp->mac_version == RTL_GIGA_MAC_VER_45 ||
tp->mac_version == RTL_GIGA_MAC_VER_46 ||
tp->mac_version == RTL_GIGA_MAC_VER_47 ||
tp->mac_version == RTL_GIGA_MAC_VER_48) {
RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
} else {
@ -5330,6 +5629,105 @@ static void rtl_hw_start_8411_2(struct rtl8169_private *tp)
rtl_ephy_init(tp, e_info_8411_2, ARRAY_SIZE(e_info_8411_2));
}
static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
struct pci_dev *pdev = tp->pci_dev;
u16 rg_saw_cnt;
u32 data;
static const struct ephy_info e_info_8168h_1[] = {
{ 0x1e, 0x0800, 0x0001 },
{ 0x1d, 0x0000, 0x0800 },
{ 0x05, 0xffff, 0x2089 },
{ 0x06, 0xffff, 0x5881 },
{ 0x04, 0xffff, 0x154a },
{ 0x01, 0xffff, 0x068b }
};
/* disable aspm and clock request before access ephy */
RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn);
RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en);
rtl_ephy_init(tp, e_info_8168h_1, ARRAY_SIZE(e_info_8168h_1));
RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x00080002, ERIAR_EXGMAC);
rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x38, ERIAR_EXGMAC);
rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x48, ERIAR_EXGMAC);
rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
rtl_csi_access_enable_1(tp);
rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_1111, 0x0010, 0x00, ERIAR_EXGMAC);
rtl_w1w0_eri(tp, 0xd4, ERIAR_MASK_1111, 0x1f00, 0x00, ERIAR_EXGMAC);
rtl_eri_write(tp, 0x5f0, ERIAR_MASK_0011, 0x4f87, ERIAR_EXGMAC);
RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN);
RTL_W8(MaxTxPacketSize, EarlySize);
rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
/* Adjust EEE LED frequency */
RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
RTL_W8(DLLPR, RTL_R8(MISC_1) & ~PFM_D3COLD_EN);
RTL_W8(DLLPR, RTL_R8(DLLPR) & ~TX_10M_PS_EN);
rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, 0x1000, ERIAR_EXGMAC);
rtl_pcie_state_l2l3_enable(tp, false);
rtl_writephy(tp, 0x1f, 0x0c42);
rg_saw_cnt = rtl_readphy(tp, 0x13);
rtl_writephy(tp, 0x1f, 0x0000);
if (rg_saw_cnt > 0) {
u16 sw_cnt_1ms_ini;
sw_cnt_1ms_ini = 16000000/rg_saw_cnt;
sw_cnt_1ms_ini &= 0x0fff;
data = r8168_mac_ocp_read(tp, 0xd412);
data &= 0x0fff;
data |= sw_cnt_1ms_ini;
r8168_mac_ocp_write(tp, 0xd412, data);
}
data = r8168_mac_ocp_read(tp, 0xe056);
data &= 0xf0;
data |= 0x07;
r8168_mac_ocp_write(tp, 0xe056, data);
data = r8168_mac_ocp_read(tp, 0xe052);
data &= 0x8008;
data |= 0x6000;
r8168_mac_ocp_write(tp, 0xe052, data);
data = r8168_mac_ocp_read(tp, 0xe0d6);
data &= 0x01ff;
data |= 0x017f;
r8168_mac_ocp_write(tp, 0xe0d6, data);
data = r8168_mac_ocp_read(tp, 0xd420);
data &= 0x0fff;
data |= 0x047f;
r8168_mac_ocp_write(tp, 0xd420, data);
r8168_mac_ocp_write(tp, 0xe63e, 0x0001);
r8168_mac_ocp_write(tp, 0xe63e, 0x0000);
r8168_mac_ocp_write(tp, 0xc094, 0x0000);
r8168_mac_ocp_write(tp, 0xc09e, 0x0000);
}
static void rtl_hw_start_8168(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
@ -5440,6 +5838,11 @@ static void rtl_hw_start_8168(struct net_device *dev)
rtl_hw_start_8411_2(tp);
break;
case RTL_GIGA_MAC_VER_45:
case RTL_GIGA_MAC_VER_46:
rtl_hw_start_8168h_1(tp);
break;
default:
printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
dev->name, tp->mac_version);
@ -5655,6 +6058,10 @@ static void rtl_hw_start_8101(struct net_device *dev)
case RTL_GIGA_MAC_VER_43:
rtl_hw_start_8168g_2(tp);
break;
case RTL_GIGA_MAC_VER_47:
case RTL_GIGA_MAC_VER_48:
rtl_hw_start_8168h_1(tp);
break;
}
RTL_W8(Cfg9346, Cfg9346_Lock);
@ -5895,7 +6302,7 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
{
struct skb_shared_info *info = skb_shinfo(skb);
unsigned int cur_frag, entry;
struct TxDesc * uninitialized_var(txd);
struct TxDesc *uninitialized_var(txd);
struct device *d = &tp->pci_dev->dev;
entry = tp->cur_tx;
@ -7110,6 +7517,10 @@ static void rtl_hw_initialize(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_42:
case RTL_GIGA_MAC_VER_43:
case RTL_GIGA_MAC_VER_44:
case RTL_GIGA_MAC_VER_45:
case RTL_GIGA_MAC_VER_46:
case RTL_GIGA_MAC_VER_47:
case RTL_GIGA_MAC_VER_48:
rtl_hw_init_8168g(tp);
break;
@ -7255,8 +7666,19 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
RTL_W8(Cfg9346, Cfg9346_Unlock);
RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
RTL_W8(Config5, RTL_R8(Config5) & (BWF | MWF | UWF | LanWake | PMEStatus));
if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
tp->features |= RTL_FEATURE_WOL;
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_45:
case RTL_GIGA_MAC_VER_46:
if (rtl_eri_read(tp, 0xdc, ERIAR_EXGMAC) & MagicPacket_v2)
tp->features |= RTL_FEATURE_WOL;
if ((RTL_R8(Config3) & LinkUp) != 0)
tp->features |= RTL_FEATURE_WOL;
break;
default:
if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
tp->features |= RTL_FEATURE_WOL;
break;
}
if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0)
tp->features |= RTL_FEATURE_WOL;
tp->features |= rtl_try_msi(tp, cfg);
@ -7283,6 +7705,18 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
u64_stats_init(&tp->tx_stats.syncp);
/* Get MAC address */
if (tp->mac_version == RTL_GIGA_MAC_VER_45 ||
tp->mac_version == RTL_GIGA_MAC_VER_46 ||
tp->mac_version == RTL_GIGA_MAC_VER_47 ||
tp->mac_version == RTL_GIGA_MAC_VER_48) {
u16 mac_addr[3];
*(u32 *)&mac_addr[0] = rtl_eri_read(tp, 0xE0, ERIAR_EXGMAC);
*(u16 *)&mac_addr[2] = rtl_eri_read(tp, 0xE4, ERIAR_EXGMAC);
if (is_valid_ether_addr((u8 *)mac_addr))
rtl_rar_set(tp, (u8 *)mac_addr);
}
for (i = 0; i < ETH_ALEN; i++)
dev->dev_addr[i] = RTL_R8(MAC0 + i);