Re: [PATCH next v1] net: rtl8169: add support for RTL8126A and RTL8127A

Jerome Forissier <[email protected]> Mon, 3 Aug 2026 14:45:08 +0200
Newsgroups gmane.comp.boot-loaders.u-boot
Message-ID <[email protected]>
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,
>> };
>>
>> +/* 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);
>> +}
>> +
>> 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 */
>> 	}
>> 	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;
>> +	}
>> +
>> 	/* 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?

Thanks,
-- 
Jerome