Kernel: Add support for the RTL8168E-VL variant to the RTL8168 driver

Specifically chip version 17.
This commit is contained in:
Luke 2021-06-04 01:31:00 +03:00 committed by Andreas Kling
parent a898e01d4d
commit d2f1476428
2 changed files with 172 additions and 4 deletions

View file

@ -107,6 +107,7 @@ namespace Kernel {
#define CFG3_READY_TO_L23 0x2
#define CFG5_ASPM_ENABLE 0x1
#define CFG5_SPI_ENABLE 0x8
#define PHY_LINK_STATUS 0x2
@ -167,6 +168,7 @@ namespace Kernel {
#define MTPS_JUMBO 0x3F
#define MISC_RXDV_GATE_ENABLE 0x80000
#define MISC_PWM_ENABLE 0x400000
#define MISC2_PFM_D3COLD_ENABLE 0x40
@ -197,7 +199,7 @@ UNMAP_AFTER_INIT RTL8168NetworkAdapter::RTL8168NetworkAdapter(PCI::Address addre
identify_chip_version();
dmesgln("RTL8168: Version detected - {} ({}{})", possible_device_name(), (u8)m_version, m_version_uncertain ? "?" : "");
if (m_version == ChipVersion::Unknown || m_version >= ChipVersion::Version4) {
if (m_version == ChipVersion::Unknown || (m_version >= ChipVersion::Version4 && m_version <= ChipVersion::Version16) || m_version >= ChipVersion::Version18) {
dmesgln("RTL8168: Aborting initialization! Support for your chip version ({}) is not implemented yet, please open a GH issue and include this message.", (u8)m_version);
return; // Each ChipVersion requires a specific implementation of configure_phy and hardware_quirks
}
@ -384,8 +386,10 @@ void RTL8168NetworkAdapter::configure_phy()
TODO();
case ChipVersion::Version16:
TODO();
case ChipVersion::Version17:
TODO();
case ChipVersion::Version17: {
configure_phy_e_2();
return;
}
case ChipVersion::Version18:
TODO();
case ChipVersion::Version19:
@ -445,6 +449,93 @@ void RTL8168NetworkAdapter::configure_phy_b_2()
phy_out_batch(phy_registers, 3);
}
void RTL8168NetworkAdapter::configure_phy_e_2()
{
// FIXME: linux's driver writes a firmware blob to the device at this point, is this needed?
constexpr PhyRegister phy_registers[] = {
// Enable delay cap
{ 0x1f, 0x4 },
{ 0x1f, 0x7 },
{ 0x1e, 0xac },
{ 0x18, 0x6 },
{ 0x1f, 0x2 },
{ 0x1f, 0 },
{ 0x1f, 0 },
// Channel estimation fine tune
{ 0x1f, 0x3 },
{ 0x9, 0xa20f },
{ 0x1f, 0 },
{ 0x1f, 0 },
// Green Setting
{ 0x1f, 0x5 },
{ 0x5, 0x8b5b },
{ 0x6, 0x9222 },
{ 0x5, 0x8b6d },
{ 0x6, 0x8000 },
{ 0x5, 0x8b76 },
{ 0x6, 0x8000 },
{ 0x1f, 0 },
};
phy_out_batch(phy_registers, 19);
// 4 corner performance improvement
phy_out(0x1f, 0x5);
phy_out(0x5, 0x8b80);
phy_update(0x17, 0x6, 0);
phy_out(0x1f, 0);
// PHY auto speed down
phy_out(0x1f, 0x4);
phy_out(0x1f, 0x7);
phy_out(0x1e, 0x2d);
phy_update(0x18, 0x10, 0);
phy_out(0x1f, 0x2);
phy_out(0x1f, 0);
phy_update(0x14, 0x8000, 0);
// Improve 10M EEE waveform
phy_out(0x1f, 0x5);
phy_out(0x5, 0x8b86);
phy_update(0x6, 0x1, 0);
phy_out(0x1f, 0);
// Improve 2-pair detection performance
phy_out(0x1f, 0x5);
phy_out(0x5, 0x8b85);
phy_update(0x6, 0x4000, 0);
phy_out(0x1f, 0);
// EEE Setting
eri_update(0x1b0, ERI_MASK_1111, 0, 0x3, ERI_EXGMAC);
phy_out(0x1f, 0x5);
phy_out(0x5, 0x8b85);
phy_update(0x6, 0, 0x2000);
phy_out(0x1f, 0x4);
phy_out(0x1f, 0x7);
phy_out(0x1e, 0x20);
phy_update(0x15, 0, 0x100);
phy_out(0x1f, 0x2);
phy_out(0x1f, 0);
phy_out(0xd, 0x7);
phy_out(0xe, 0x3c);
phy_out(0xd, 0x4007);
phy_out(0xe, 0);
phy_out(0xd, 0);
// Green feature
phy_out(0x1f, 0x3);
phy_update(0x19, 0, 0x1);
phy_update(0x10, 0, 0x400);
phy_out(0x1f, 0);
// Broken BIOS workaround: feed GigaMAC registers with MAC address.
rar_exgmac_set();
}
void RTL8168NetworkAdapter::configure_phy_h_1()
{
// FIXME: linux's driver writes a firmware blob to the device at this point, is this needed?
@ -620,6 +711,25 @@ void RTL8168NetworkAdapter::configure_phy_h_2()
phy_out(0x1f, 0);
}
void RTL8168NetworkAdapter::rar_exgmac_set()
{
auto mac = mac_address();
const u16 w[] = {
(u16)(mac[0] | (mac[1] << 8)),
(u16)(mac[2] | (mac[3] << 8)),
(u16)(mac[4] | (mac[5] << 8)),
};
const ExgMacRegister exg_mac_registers[] = {
{ 0xe0, ERI_MASK_1111, (u32)(w[0] | (w[1] << 16)) },
{ 0xe4, ERI_MASK_1111, (u32)w[2] },
{ 0xf0, ERI_MASK_1111, (u32)(w[0] << 16) },
{ 0xf4, ERI_MASK_1111, (u32)(w[1] | (w[2] << 16)) },
};
exgmac_out_batch(exg_mac_registers, 4);
}
void RTL8168NetworkAdapter::start_hardware()
{
@ -709,7 +819,8 @@ void RTL8168NetworkAdapter::hardware_quirks()
case ChipVersion::Version16:
TODO();
case ChipVersion::Version17:
TODO();
hardware_quirks_e_2();
return;
case ChipVersion::Version18:
TODO();
case ChipVersion::Version19:
@ -760,6 +871,46 @@ void RTL8168NetworkAdapter::hardware_quirks_b_2()
out8(REG_CONFIG4, in8(REG_CONFIG4) & ~1);
}
void RTL8168NetworkAdapter::hardware_quirks_e_2()
{
constexpr EPhyUpdate ephy_info[] = {
{ 0x9, 0, 0x80 },
{ 0x19, 0, 0x224 },
};
csi_enable(CSI_ACCESS_1);
extended_phy_initialize(ephy_info, 2);
// FIXME: MTU performance tweak
eri_out(0xc0, ERI_MASK_0011, 0, ERI_EXGMAC);
eri_out(0xb8, ERI_MASK_0011, 0, ERI_EXGMAC);
eri_out(0xc8, ERI_MASK_1111, 0x100002, ERI_EXGMAC);
eri_out(0xe8, ERI_MASK_1111, 0x100006, ERI_EXGMAC);
eri_out(0xcc, ERI_MASK_1111, 0x50, ERI_EXGMAC);
eri_out(0xd0, ERI_MASK_1111, 0x7ff0060, ERI_EXGMAC);
eri_update(0x1b0, ERI_MASK_0001, 0x10, 0, ERI_EXGMAC);
eri_update(0xd4, ERI_MASK_0011, 0xc00, 0xff00, ERI_EXGMAC);
// Set early TX
out8(REG_MTPS, 0x27);
// FIXME: Disable PCIe clock request
// enable tx auto fifo
out32(REG_TXCFG, in32(REG_TXCFG) | TXCFG_AUTO_FIFO);
out8(REG_MCU, in8(REG_MCU) & ~MCU_NOW_IS_OOB);
// Set EEE LED frequency
out8(REG_EEE_LED, in8(REG_EEE_LED) & ~0x7);
out8(REG_DLLPR, in8(REG_DLLPR) | DLLPR_PFM_ENABLE);
out32(REG_MISC, in32(REG_MISC) | MISC_PWM_ENABLE);
out8(REG_CONFIG5, in8(REG_CONFIG5) & ~CFG5_SPI_ENABLE);
}
void RTL8168NetworkAdapter::hardware_quirks_h()
{
// disable aspm and clock request before accessing extended phy
@ -1189,6 +1340,13 @@ void RTL8168NetworkAdapter::eri_update(u32 address, u32 mask, u32 set, u32 clear
eri_out(address, mask, (value & ~clear) | set, type);
}
void RTL8168NetworkAdapter::exgmac_out_batch(const ExgMacRegister exgmac_registers[], size_t length)
{
for (size_t i = 0; i < length; i++) {
eri_out(exgmac_registers[i].address, exgmac_registers[i].mask, exgmac_registers[i].value, ERI_EXGMAC);
}
}
void RTL8168NetworkAdapter::csi_out(u32 address, u32 data)
{
VERIFY(m_version >= ChipVersion::Version4);

View file

@ -128,12 +128,16 @@ private:
void configure_phy();
void configure_phy_b_1();
void configure_phy_b_2();
void configure_phy_e_2();
void configure_phy_h_1();
void configure_phy_h_2();
void rar_exgmac_set();
void hardware_quirks();
void hardware_quirks_b_1();
void hardware_quirks_b_2();
void hardware_quirks_e_2();
void hardware_quirks_h();
void initialize_rx_descriptors();
@ -170,6 +174,12 @@ private:
void eri_out(u32 address, u32 mask, u32 data, u32 type);
u32 eri_in(u32 address, u32 type);
void eri_update(u32 address, u32 mask, u32 set, u32 clear, u32 type);
struct ExgMacRegister {
u16 address;
u16 mask;
u32 value;
};
void exgmac_out_batch(const ExgMacRegister[], size_t length);
void csi_out(u32 address, u32 data);
u32 csi_in(u32 address);