Hi Jerome,
>
>Hi Javen,
>
>On 29/07/2026 09:27, Javen wrote:
>>> RTL8126A and RTL8127A share most of the register layouts and quirks
>>> with
>>> RTL8125 series, but require explicit desc type and CRC-drop setup during
>init.
>>>
>>> This patch adds PCI IDs and MAC versions. RTL8126A is 0x66 and
>>> RTL8127A is 0x6e. And RTL8127A requires Tx Desc V3 format and an
>>> additional RADM FIFO protection configuration according to vendor driver.
>>>
>>> Signed-off-by: Javen Xu <[email protected]>
>>> ---
>>> drivers/net/rtl8169.c | 103
>>> ++++++++++++++++++++++++++++++++++++++----
>>> 1 file changed, 94 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c index
>>> 5b093623619..a24cff97801 100644
>>> --- a/drivers/net/rtl8169.c
>>> +++ b/drivers/net/rtl8169.c
>>> @@ -49,6 +49,7 @@
>>> #include <asm/cache.h>
>>> #include <asm/io.h>
>>> #include <pci.h>
>>> +#include <linux/bitops.h>
>>> #include <linux/delay.h>
>>> #include <linux/printk.h>
>>>
>>> @@ -152,8 +153,24 @@ enum RTL8125_registers {
>>> IntrMask_8125 = 0x38,
>>> IntrStatus_8125 = 0x3C,
>>> TxPoll_8125 = 0x90,
>>> + RX_DESC_MODE = 0xd8,
>>> + MACOCP = 0xb0,
>>> + RADMFIFO_PROTECT = 0x0402,
>>> + TX_DESC_MODE = 0xeb58,
>>> };
These are the specific registers required for the RTL8126A/8127. MACOCP (0xb0)
is used for indirect access to extended MAC registers, such as TX_DESC_MODE
(0xeb58).
>>>
>>> +/* MAC OCP indirect access via the MACOCP register */
>>> +#define RTL8125_OCP_WRITE 0x80000000
>>> +#define RTL8125_OCP_ADDR_SHIFT 16
>>> +#define RX_DESC_CRC_DROP BIT(0)
>>> +#define RX_DESC_TYPE BIT(1)
>>> +
>>> +/* TX_DESC_MODE (MAC OCP 0xeb58): TX descriptor format select, bits
>>> +[1:0]
>>> */
>>> +#define TX_DESC_FMT_MASK GENMASK(1, 0)
>>> +#define TX_DESC_FMT_STD BIT(0)
>>> +#define TX_DESC_FMT_V3 BIT(1)
>>> +#define RX_PAUSE_SLOT_ON BIT(11)
>>> +
>>> enum RTL8169_register_content {
>>> /*InterruptStatusBits */
>>> SYSErr = 0x8000,
>>> @@ -271,6 +288,8 @@ static struct {
>>> {"RTL-8168h/8111h", 0x54, 0xff7e1880,},
>>> {"RTL-8125B", 0x64, 0xff7e1880,},
>>> {"RTL-8125d", 0x6a, 0xff7e5880,},
>>> + {"RTL-8126A", 0x66, 0xff7e5880,},
>>> + {"RTL-8127A", 0x6e, 0xff7e5880,},
>>> };
>>>
>>> enum _DescStatusBit {
>>> @@ -355,6 +374,8 @@ static const unsigned int rtl8169_rx_config =
>>>
>>> static struct pci_device_id supported[] = {
>>> { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8125) },
>>> + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8126) },
>>> + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8127) },
>>> { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8161) },
>>> { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167) },
>>> { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168) }, @@ -398,6 +419,33
>>> @@ int mdio_read(int RegAddr)
>>> return value;
>>> }
>>>
>>> +/* RTL8125/8126/8127 share the same register layout and quirks */
>>> +static bool rtl_is_8125(struct pci_child_plat *pplat) {
>>> + return pplat->device == 0x8125 || pplat->device == 0x8126 ||
>>> + pplat->device == 0x8127;
>>> +}
>>> +
>>> +static void rtl_mac_ocp_write(u16 reg_addr, u16 value) {
>>> + u32 data32;
>>> +
>>> + data32 = (u32)(reg_addr / 2) << RTL8125_OCP_ADDR_SHIFT;
>>> + data32 += value;
>>> + data32 |= RTL8125_OCP_WRITE;
>>> + RTL_W32(MACOCP, data32);
>>> +}
>>> +
>>> +static u16 rtl_mac_ocp_read(u16 reg_addr) {
>>> + u32 data32;
>>> +
>>> + data32 = (u32)(reg_addr / 2) << RTL8125_OCP_ADDR_SHIFT;
>>> + RTL_W32(MACOCP, data32);
>>> +
>>> + return (u16)RTL_R32(MACOCP);
>>> +}
Newer Realtek chips require these helper functions to read/write extended
registers indirectly via the MACOCP register. This is standard practice in our
vendor driver.
>>> +
>>> static int rtl8169_init_board(unsigned long dev_iobase, const char *name) {
>>> int i;
>>> @@ -571,12 +619,15 @@ static int rtl_recv_common(struct udevice *dev,
>>> unsigned long dev_iobase,
>>> return length;
>>>
>>> } else {
>>> - u32 IntrStatus = IntrStatus_8169;
>>> + u32 sts;
>>>
>>> - if (pplat->device == 0x8125)
>>> - IntrStatus = IntrStatus_8125;
>>> - ushort sts = RTL_R8(IntrStatus);
>>> - RTL_W8(IntrStatus, sts & ~(TxErr | RxErr | SYSErr));
>>> + if (rtl_is_8125(pplat)) {
>>> + sts = RTL_R32(IntrStatus_8125);
>>> + RTL_W32(IntrStatus_8125, sts & ~(TxErr | RxErr |
>>> SYSErr));
>>> + } else {
>>> + sts = RTL_R16(IntrStatus_8169);
>>> + RTL_W16(IntrStatus_8169, sts & ~(TxErr | RxErr |
>>> SYSErr));
>>> + }
>>> udelay(100); /* wait */
>>> }
RTL8125, 8126, and 8127 share the same base architecture. Unlike older 8169
chips that use 16-bit access, these newer chips require 32-bit I/O access for
IntrStatus, IntrMask, and TxPoll. I grouped them using rtl_is_8125() to handle
this difference properly.
>>> tpc->cur_rx = cur_rx;
>>> @@ -636,8 +687,8 @@ static int rtl_send_common(struct udevice *dev,
>>> unsigned long dev_iobase,
>>> ((len > ETH_ZLEN) ? len : ETH_ZLEN));
>>> }
>>> rtl_flush_tx_desc(&tpc->TxDescArray[entry]);
>>> - if (pplat->device == 0x8125)
>>> - RTL_W8(TxPoll_8125, 0x1); /* set polling bit */
>>> + if (rtl_is_8125(pplat))
>>> + RTL_W32(TxPoll_8125, 0x1); /* set polling bit */
>>> else
>>> RTL_W8(TxPoll_8169, 0x40); /* set polling bit */
>>>
>>> @@ -697,6 +748,8 @@ static void rtl8169_set_rx_mode(void)
>>>
>>> static void rtl8169_hw_start(struct udevice *dev) {
>>> + u8 version = rtl_chip_info[tpc->chipset].version;
>>> + u16 tx_desc_mode;
>>> u32 i;
>>>
>>> #ifdef DEBUG_RTL8169
>>> @@ -719,6 +772,36 @@ static void rtl8169_hw_start(struct udevice
>>> *dev)
>>>
>>> RTL_W8(Cfg9346, Cfg9346_Unlock);
>>>
>>> + /*
>>> + * RTL8125D/8126A/8127A require explicit descriptor-type and
>>> + CRC-
>>> drop setup.
>>> + * RTL8125B (0x64) is intentionally excluded to avoid regressing
>>> working hardware.
>>> + */
>>> + switch (version) {
>>> + case 0x6a:
>>> + case 0x66:
>>> + case 0x6e:
>>> + /* Reg 0xD8: Disable CRC drop and force legacy 16-byte
>>> + RX
>>> desc */
>>> + RTL_W8(RX_DESC_MODE, RTL_R8(RX_DESC_MODE) &
>>> ~(RX_DESC_CRC_DROP |
>>> +RX_DESC_TYPE));
>>> +
>>> + /* RxConfig 0x44: enable RX pause slot (RTL8125B and later) */
>>> + RTL_W32(RxConfig, RTL_R32(RxConfig) | RX_PAUSE_SLOT_ON);
>>> +
>>> + /* MAC OCP 0xEB58: TX descriptor format setup */
>>> + tx_desc_mode = rtl_mac_ocp_read(TX_DESC_MODE) &
>>> ~TX_DESC_FMT_MASK;
>>> +
>>> + if (version == 0x6e) {
>>> + /* RTL8127A specific: Tx desc V3 and RADM FIFO
>>> protection */
>>> + rtl_mac_ocp_write(TX_DESC_MODE, tx_desc_mode |
>>> TX_DESC_FMT_V3);
>>> + RTL_W16(RADMFIFO_PROTECT, 0x2001);
>>> + } else {
>>> + /* RTL8125D / RTL8126A specific: standard Tx desc */
>>> + rtl_mac_ocp_write(TX_DESC_MODE, tx_desc_mode |
>>> TX_DESC_FMT_STD);
>>> + }
>>> + break;
>>> + default:
>>> + break;
>>> + }
MAC version 0x6e is RTL8127A. According to the vendor driver, RTL8127A
explicitly requires the newer V3 TX descriptor format. Also, writing 0x2001 to
RADMFIFO_PROTECT (0x0402) is a hardware requirement to prevent FIFO
overflow/underflow issues.
RTL8126A (0x66) and RTL8125D (0x6a) just fall into the else branch to use the
standard TX descriptor.
>>> +
>>> /* RTL-8169sb/8110sb or previous version */
>>> if (tpc->chipset <= 5)
>>> RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); @@ -860,8
>>> +943,8 @@ static void rtl_halt_common(struct udevice *dev)
>>> RTL_W8(ChipCmd, 0x00);
>>>
>>> /* Disable interrupts by clearing the interrupt mask. */
>>> - if (pplat->device == 0x8125)
>>> - RTL_W16(IntrMask_8125, 0x0000);
>>> + if (rtl_is_8125(pplat))
>>> + RTL_W32(IntrMask_8125, 0x00000000);
>>> else
>>> RTL_W16(IntrMask_8169, 0x0000);
>>>
>>> @@ -1052,6 +1135,8 @@ static int rtl8169_eth_probe(struct udevice
>>> *dev)
>>>
>>> switch (pplat->device) {
>>> case 0x8125:
>>> + case 0x8126:
>>> + case 0x8127:
>>> case 0x8161:
>>> case 0x8168:
>>> region = 2;
>>> --
>>> 2.43.0
>>
>>
>> Hi, all
>>
>> Just a gentle ping for this patch.
>> I am reaching out to see if any had a chance to review this patch. I wonder
>> if
>there is anything I need to modify, clarify, or if I missed any submission
>guidelines. Thanks.
>
>I don't know this driver nor the chips so I'm afraid I can't give useful
>feedback.
>Can you please explain how you tested the change?
I tested this patch directly on a Realtek development board (rtd1619bes)
equipped with RTL8126A and RTL8127A PCIe network cards.
Here are the specific testing steps I performed in the U-Boot environment:
1. PCI Enumeration & Initialization:
Run the U-Boot `pci` command to dump the PCI list. This verified that the
PCIe devices are correctly enumerated, and the driver successfully probes them
by accurately matching the new PCI IDs (0x8126, 0x8127) and MAC versions.
2. Network Connectivity (Tx/Rx Path):
Executed `ping 8.8.8.8` and verified consistent ICMP replies. This basic
connectivity test confirms that the packet transmission and reception paths are
working correctly.
All the register can be found in Realtek vendor driver.
Links: https://www.realtek.com/Download/List?cate_id=584
I hope this provides the context you need. Please let me know if there's
anything else I should clarify.
Thanks,
Javen
>
>Thanks,
>--
>Jerome