mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 09:51:57 -05:00
Kernel: Add support for the RTL8168E-VL variant to the RTL8168 driver
Specifically chip version 17.
This commit is contained in:
parent
a898e01d4d
commit
d2f1476428
2 changed files with 172 additions and 4 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue