// SPDX-License-Identifier: GPL-2.0+
/*
* rtl8169.c : U-Boot driver for the RealTek RTL8169
*
* Masami Komiya (mkomiya@sonare.it)
*
* Most part is taken from r8169.c of etherboot
*
*/
/**************************************************************************
* r8169.c: Etherboot device driver for the RealTek RTL-8169 Gigabit
* Written 2003 by Timothy Legge <tlegge@rogers.com>
*
* Portions of this code based on:
* r8169.c: A RealTek RTL-8169 Gigabit Ethernet driver
* for Linux kernel 2.4.x.
*
* Written 2002 ShuChen <shuchen@realtek.com.tw>
* See Linux Driver for full information
*
* Linux Driver Version 1.27a, 10.02.2002
*
* Thanks to:
* Jean Chen of RealTek Semiconductor Corp. for
* providing the evaluation NIC used to develop
* this driver. RealTek's support for Etherboot
* is appreciated.
*
* REVISION HISTORY:
* ================
*
* v1.0 11-26-2003 timlegge Initial port of Linux driver
* v1.5 01-17-2004 timlegge Initial driver output cleanup
*
* Indent Options: indent -kr -i8
***************************************************************************/
/*
* 26 August 2006 Mihai Georgian <u-boot@linuxnotincluded.org.uk>
* Modified to use le32_to_cpu and cpu_to_le32 properly
*/
#include <common.h>
#include <cpu_func.h>
#include <dm.h>
#include <errno.h>
#include <log.h>
#include <malloc.h>
#include <memalign.h>
#include <net.h>
#ifndef CONFIG_DM_ETH
#include <netdev.h>
#endif
#include <asm/cache.h>
#include <asm/io.h>
#include <pci.h>
#include <linux/delay.h>
#undef DEBUG_RTL8169
#undef DEBUG_RTL8169_TX
#undef DEBUG_RTL8169_RX
#define drv_version "v1.5"
#define drv_date "01-17-2004"
static unsigned long ioaddr;
/* Condensed operations for readability. */
#define currticks() get_timer(0)
/* media options */
#define MAX_UNITS 8
static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
/* MAC address length*/
#define MAC_ADDR_LEN 6
/* max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4).*/
#define MAX_ETH_FRAME_SIZE 1536
#define TX_FIFO_THRESH 256 /* In bytes */
#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */
#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */
#define RxPacketMaxSize 0x0800 /* Maximum size supported is 16K-1 */
#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
#define NUM_TX_DESC 1 /* Number of Tx descriptor registers */
#ifdef CONFIG_SYS_RX_ETH_BUFFER
#define NUM_RX_DESC CONFIG_SYS_RX_ETH_BUFFER
#else
#define NUM_RX_DESC 4 /* Number of Rx descriptor registers */
#endif
#define RX_BUF_SIZE 1536 /* Rx Buffer size */
#define RX_BUF_LEN 8192
#define RTL_MIN_IO_SIZE 0x80
#define TX_TIMEOUT (6*HZ)
/* write/read MMIO register. Notice: {read,write}[wl] do the necessary swapping */
#define RTL_W8(reg, val8) writeb((val8), ioaddr + (reg))
#define RTL_W16(reg, val16) writew((val16), ioaddr + (reg))
#define RTL_W32(reg, val32) writel((val32), ioaddr + (reg))
#define RTL_R8(reg) readb(ioaddr + (reg))
#define RTL_R16(reg) readw(ioaddr + (reg))
#define RTL_R32(reg) readl(ioaddr + (reg))
#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)(unsigned long)dev->priv, \
(pci_addr_t)(unsigned long)a)
#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)(unsigned long)dev->priv, \
(phys_addr_t)a)
enum RTL8169_registers {
MAC0 = 0, /* Ethernet hardware address. */
MAR0 = 8, /* Multicast filter. */
TxDescStartAddrLow = 0x20,
TxDescStartAddrHigh = 0x24,
TxHDescStartAddrLow = 0x28,
TxHDescStartAddrHigh = 0x2c,
FLASH = 0x30,
ERSR = 0x36,
ChipCmd = 0x37,
TxPoll = 0x38,
IntrMask = 0x3C,
IntrStatus = 0x3E,
TxConfig = 0x40,
RxConfig = 0x44,
RxMissed = 0x4C,
Cfg9346 = 0x50,
Config0 = 0x51,
Config1 = 0x52,
Config2 = 0x53,
Config3 = 0x54,
Config4 = 0x55,
Config5 = 0x56,
MultiIntr = 0x5C,
PHYAR = 0x60,
TBICSR = 0x64,
TBI_ANAR = 0x68,
TBI_LPAR = 0x6A,
PHYstatus = 0x6C,
RxMaxSize = 0xDA,
CPlusCmd = 0xE0,
RxDescStartAddrLow = 0xE4,
RxDescStartAddrHigh = 0xE8,
EarlyTxThres = 0xEC,
FuncEvent = 0xF0,
FuncEventMask = 0xF4,
FuncPresetState = 0xF8,
FuncForceEvent = 0xFC,
};
enum RTL8169_register_content {
/*InterruptStatusBits */
SYSErr = 0x8000,
PCSTimeout = 0x4000,
SWInt = 0x0100,
TxDescUnavail = 0x80,
RxFIFOOver = 0x40,
RxUnderrun = 0x20,
RxOverflow = 0x10,
TxErr = 0x08,
TxOK = 0x04,
RxErr = 0x02,
RxOK = 0x01,
/*RxStatusDesc */
RxRES = 0x00200000,
RxCRC = 0x00080000,
RxRUNT = 0x00100000,
RxRWT = 0x00400000,
/*ChipCmdBits */
CmdReset = 0x10,
CmdRxEnb = 0x08,
CmdTxEnb = 0x04,
RxBufEmpty = 0x01,
/*Cfg9346Bits */
Cfg9346_Lock = 0x00,
Cfg9346_Unlock = 0xC0,
/*rx_mode_bits */
AcceptErr = 0x20,
AcceptRunt = 0x10,
AcceptBroadcast = 0x08,
AcceptMulticast = 0x04,
AcceptMyPhys = 0x02,
AcceptAllPhys = 0x01,
/*RxConfigBits */
RxCfgFIFOShift = 13,
RxCfgDMAShift = 8,
/*TxConfigBits */
TxInterFrameGapShift = 24,
TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
/*rtl8169_PHYstatus */
TBI_Enable = 0x80,
TxFlowCtrl = 0x40,
RxFlowCtrl = 0x20,
_1000bpsF = 0x10,
_100bps = 0x08,
_10bps = 0x04,
LinkStatus = 0x02,
FullDup = 0x01,
/*GIGABIT_PHY_registers */
PHY_CTRL_REG = 0,
PHY_STAT_REG = 1,
PHY_AUTO_NEGO_REG = 4,
PHY_1000_CTRL_REG = 9,
/*GIGABIT_PHY_REG_BIT */
PHY_Restart_Auto_Nego = 0x0200,
PHY_Enable_Auto_Nego = 0x1000,
/* PHY_STAT_REG = 1; */
PHY_Auto_Nego_Comp = 0x0020,
/* PHY_AUTO_NEGO_REG = 4; */
PHY_Cap_10_Half = 0x0020,
PHY_Cap_10_Full = 0x0040,
|