From: Michael Brown Date: Thu, 16 Mar 2006 18:44:31 +0000 (+0000) Subject: Merge from Etherboot 5.4 X-Git-Tag: v0.9.3~1566 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=46e7bd5b522c40f180df70fc75a23781db886f6a;p=thirdparty%2Fipxe.git Merge from Etherboot 5.4 --- 46e7bd5b522c40f180df70fc75a23781db886f6a diff --cc src/drivers/net/r8169.c index 427fad0f8,ad3b62bd6..26454307f --- a/src/drivers/net/r8169.c +++ b/src/drivers/net/r8169.c @@@ -23,7 -23,7 +23,9 @@@ * Written 2002 ShuChen * See Linux Driver for full information * --* Linux Driver Version 1.27a, 10.02.2002 ++* Linux Driver Versions: ++* 1.27a, 10.02.2002 ++* RTL8169_VERSION "2.2" <2004/08/09> * * Thanks to: * Jean Chen of RealTek Semiconductor Corp. for @@@ -37,6 -37,6 +39,7 @@@ * v1.0 11-26-2003 timlegge Initial port of Linux driver * v1.5 01-17-2004 timlegge Initial driver output cleanup * v1.6 03-27-2004 timlegge Additional Cleanup ++* v1.7 11-22-2005 timlegge Update to RealTek Driver Version 2.2 * * Indent Options: indent -kr -i8 ***************************************************************************/ @@@ -68,6 -75,6 +71,25 @@@ static u32 ioaddr #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) ++#undef RTL8169_DEBUG ++#undef RTL8169_JUMBO_FRAME_SUPPORT ++#undef RTL8169_HW_FLOW_CONTROL_SUPPORT ++ ++ ++#undef RTL8169_IOCTL_SUPPORT ++#undef RTL8169_DYNAMIC_CONTROL ++#define RTL8169_USE_IO ++ ++ ++#ifdef RTL8169_DEBUG ++#define assert(expr) \ ++ if(!(expr)) { printk( "Assertion failed! %s,%s,%s,line=%d\n", #expr,__FILE__,__FUNCTION__,__LINE__); } ++#define DBG_PRINT( fmt, args...) printk("r8169: " fmt, ## args); ++#else ++#define assert(expr) do {} while (0) ++#define DBG_PRINT( fmt, args...) ; ++#endif // end of #ifdef RTL8169_DEBUG ++ /* media options _10_Half = 0x01, _10_Full = 0x02, @@@ -97,8 -104,8 +119,10 @@@ static int multicast_filter_limit = 32 #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 RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ ++#define TX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ ++#define ETTh 0x3F /* 0x3F means NO threshold */ ++ #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 */ @@@ -110,6 -117,6 +134,28 @@@ #define RTL_MIN_IO_SIZE 0x80 #define TX_TIMEOUT (6*HZ) ++#define RTL8169_TIMER_EXPIRE_TIME 100 //100 ++ ++#define ETH_HDR_LEN 14 ++#define DEFAULT_MTU 1500 ++#define DEFAULT_RX_BUF_LEN 1536 ++ ++ ++#ifdef RTL8169_JUMBO_FRAME_SUPPORT ++#define MAX_JUMBO_FRAME_MTU ( 10000 ) ++#define MAX_RX_SKBDATA_SIZE ( MAX_JUMBO_FRAME_MTU + ETH_HDR_LEN ) ++#else ++#define MAX_RX_SKBDATA_SIZE 1600 ++#endif //end #ifdef RTL8169_JUMBO_FRAME_SUPPORT ++ ++#ifdef RTL8169_USE_IO ++#define RTL_W8(reg, val8) outb ((val8), ioaddr + (reg)) ++#define RTL_W16(reg, val16) outw ((val16), ioaddr + (reg)) ++#define RTL_W32(reg, val32) outl ((val32), ioaddr + (reg)) ++#define RTL_R8(reg) inb (ioaddr + (reg)) ++#define RTL_R16(reg) inw (ioaddr + (reg)) ++#define RTL_R32(reg) ((unsigned long) inl (ioaddr + (reg))) ++#else /* write/read MMIO register */ #define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) #define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) @@@ -117,10 -124,10 +163,30 @@@ #define RTL_R8(reg) readb (ioaddr + (reg)) #define RTL_R16(reg) readw (ioaddr + (reg)) #define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) ++#endif ++ ++#define MCFG_METHOD_1 0x01 ++#define MCFG_METHOD_2 0x02 ++#define MCFG_METHOD_3 0x03 ++#define MCFG_METHOD_4 0x04 ++ ++#define PCFG_METHOD_1 0x01 //PHY Reg 0x03 bit0-3 == 0x0000 ++#define PCFG_METHOD_2 0x02 //PHY Reg 0x03 bit0-3 == 0x0001 ++#define PCFG_METHOD_3 0x03 //PHY Reg 0x03 bit0-3 == 0x0002 ++ ++static struct { ++ const char *name; ++ u8 mcfg; /* depend on RTL8169 docs */ ++ u32 RxConfigMask; /* should clear the bits supported by this chip */ ++} rtl_chip_info[] = { ++ { ++ "RTL-8169", MCFG_METHOD_1, 0xff7e1880,}, { ++ "RTL8169s/8110s", MCFG_METHOD_2, 0xff7e1880}, { ++"RTL8169s/8110s", MCFG_METHOD_3, 0xff7e1880},}; enum RTL8169_registers { -- MAC0 = 0, /* Ethernet hardware address. */ -- MAR0 = 8, /* Multicast filter. */ ++ MAC0 = 0x0, /* Ethernet hardware address. */ ++ MAR0 = 0x8, /* Multicast filter. */ TxDescStartAddr = 0x20, TxHDescStartAddr = 0x28, FLASH = 0x30, @@@ -148,7 -155,7 +214,7 @@@ RxMaxSize = 0xDA, CPlusCmd = 0xE0, RxDescStartAddr = 0xE4, -- EarlyTxThres = 0xEC, ++ ETThReg = 0xEC, FuncEvent = 0xF0, FuncEventMask = 0xF4, FuncPresetState = 0xF8, @@@ -162,7 -169,7 +228,7 @@@ enum RTL8169_register_content SWInt = 0x0100, TxDescUnavail = 0x80, RxFIFOOver = 0x40, -- RxUnderrun = 0x20, ++ LinkChg = 0x20, RxOverflow = 0x10, TxErr = 0x08, TxOK = 0x04, @@@ -232,6 -239,6 +298,10 @@@ /* PHY_1000_CTRL_REG = 9; */ PHY_Cap_1000_Full = 0x0200, ++ PHY_Cap_1000_Half = 0x0100, ++ ++ PHY_Cap_PAUSE = 0x0400, ++ PHY_Cap_ASYM_PAUSE = 0x0800, PHY_Cap_Null = 0x0, @@@ -246,14 -253,14 +316,6 @@@ TBILinkOK = 0x02000000, }; --static struct { -- const char *name; -- u8 version; /* depend on RTL8169 docs */ -- u32 RxConfigMask; /* should clear the bits supported by this chip */ --} rtl_chip_info[] = { -- { --"RTL-8169", 0x00, 0xff7e1880,},}; -- enum _DescStatusBit { OWNbit = 0x80000000, EORbit = 0x40000000, @@@ -299,6 -306,6 +361,8 @@@ struct static struct rtl8169_private { void *mmio_addr; /* memory map physical address */ int chipset; ++ int pcfg; ++ int mcfg; unsigned long cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ unsigned long cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ struct TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */ @@@ -310,10 -317,10 +374,67 @@@ static struct rtl8169_private *tpc; static const u16 rtl8169_intr_mask = -- SYSErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | TxErr | -- TxOK | RxErr | RxOK; ++ LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; static const unsigned int rtl8169_rx_config = -- (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); ++ (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift) | ++ 0x0000000E; ++ ++static void rtl8169_hw_PHY_config(struct nic *nic __unused); ++//static void rtl8169_hw_PHY_reset(struct net_device *dev); ++ ++#define RTL8169_WRITE_GMII_REG_BIT( ioaddr, reg, bitnum, bitval )\ ++{ \ ++ int val; \ ++ if( bitval == 1 ){ val = ( RTL8169_READ_GMII_REG( ioaddr, reg ) | (bitval< 0; i--) { ++ // Check if the RTL8169 has completed writing to the specified MII register ++ if (!(RTL_R32(PHYAR) & 0x80000000)) { ++ break; ++ } else { ++ udelay(100); ++ } // end of if( ! (RTL_R32(PHYAR)&0x80000000) ) ++ } // end of for() loop ++} ++ ++//================================================================= ++int RTL8169_READ_GMII_REG(unsigned long ioaddr, int RegAddr) ++{ ++ int i, value = -1; ++ ++ RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16); ++ udelay(1000); ++ ++ for (i = 2000; i > 0; i--) { ++ // Check if the RTL8169 has completed retrieving data from the specified MII register ++ if (RTL_R32(PHYAR) & 0x80000000) { ++ value = (int) (RTL_R32(PHYAR) & 0xFFFF); ++ break; ++ } else { ++ udelay(100); ++ } // end of if( RTL_R32(PHYAR) & 0x80000000 ) ++ } // end of for() loop ++ return value; ++} ++ static void mdio_write(int RegAddr, int value) { @@@ -351,27 -358,27 +472,41 @@@ static int mdio_read(int RegAddr return value; } ++#define IORESOURCE_MEM 0x00000200 ++ static int rtl8169_init_board(struct pci_device *pdev) { int i; -- unsigned long rtreg_base, rtreg_len; -- u32 tmp; ++ unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; -- rtreg_base = pci_bar_start(pdev, PCI_BASE_ADDRESS_1); -- rtreg_len = pci_bar_size(pdev, PCI_BASE_ADDRESS_1); ++ adjust_pci_device(pdev); -- /* check for weird/broken PCI region reporting */ -- if (rtreg_len < RTL_MIN_IO_SIZE) { -- printf("Invalid PCI region size(s), aborting\n"); -- } ++ mmio_start = pci_bar_start(pdev, PCI_BASE_ADDRESS_1); ++// mmio_end = pci_resource_end (pdev, 1); ++// mmio_flags = pci_resource_flags (pdev, PCI_BASE_ADDRESS_1); ++ mmio_len = pci_bar_size(pdev, PCI_BASE_ADDRESS_1); -- adjust_pci_device(pdev); --/* pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); */ ++ // make sure PCI base addr 1 is MMIO ++// if (!(mmio_flags & IORESOURCE_MEM)) { ++// printf ("region #1 not an MMIO resource, aborting\n"); ++// return 0; ++// } -- /* ioremap MMIO region */ -- ioaddr = (unsigned long) ioremap(rtreg_base, rtreg_len); -- if (ioaddr == 0) ++ // check for weird/broken PCI region reporting ++ if (mmio_len < RTL_MIN_IO_SIZE) { ++ printf("Invalid PCI region size(s), aborting\n"); ++ return 0; ++ } ++#ifdef RTL8169_USE_IO ++ ioaddr = pci_bar_start(pdev, PCI_BASE_ADDRESS_0); ++#else ++ // ioremap MMIO region ++ ioaddr = (unsigned long) ioremap(mmio_start, mmio_len); ++ if (ioaddr == 0) { ++ printk("cannot remap MMIO, aborting\n"); return 0; ++ } ++#endif tpc->mmio_addr = &ioaddr; /* Soft reset the chip. */ @@@ -383,13 -390,13 +518,40 @@@ break; else udelay(10); ++ // identify config method ++ { ++ unsigned long val32 = (RTL_R32(TxConfig) & 0x7c800000); ++ if (val32 == (0x1 << 28)) { ++ tpc->mcfg = MCFG_METHOD_4; ++ } else if (val32 == (0x1 << 26)) { ++ tpc->mcfg = MCFG_METHOD_3; ++ } else if (val32 == (0x1 << 23)) { ++ tpc->mcfg = MCFG_METHOD_2; ++ } else if (val32 == 0x00000000) { ++ tpc->mcfg = MCFG_METHOD_1; ++ } else { ++ tpc->mcfg = MCFG_METHOD_1; ++ } ++ } ++ { ++ unsigned char val8 = ++ (unsigned char) (RTL8169_READ_GMII_REG(ioaddr, 3) & ++ 0x000f); ++ if (val8 == 0x00) { ++ tpc->pcfg = PCFG_METHOD_1; ++ } else if (val8 == 0x01) { ++ tpc->pcfg = PCFG_METHOD_2; ++ } else if (val8 == 0x02) { ++ tpc->pcfg = PCFG_METHOD_3; ++ } else { ++ tpc->pcfg = PCFG_METHOD_3; ++ } ++ } /* identify chip attached to board */ -- tmp = RTL_R32(TxConfig); -- tmp = ((tmp & 0x7c000000) + ((tmp & 0x00800000) << 2)) >> 24; for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) -- if (tmp == rtl_chip_info[i].version) { ++ if (tpc->mcfg == rtl_chip_info[i].mcfg) { tpc->chipset = i; goto match; } @@@ -397,8 -404,8 +559,10 @@@ dprintf(("PCI device: unknown chip version, assuming RTL-8169\n")); dprintf(("PCI device: TxConfig = 0x%hX\n", (unsigned long) RTL_R32(TxConfig))); ++ tpc->chipset = 0; return 1; ++ match: return 0; @@@ -407,6 -414,6 +571,31 @@@ /************************************************************************** IRQ - Wait for a frame ***************************************************************************/ ++void r8169_irq(struct nic *nic __unused, irq_action_t action) ++{ ++ int intr_status = 0; ++ int interested = RxOverflow | RxFIFOOver | RxErr | RxOK; ++ ++ switch (action) { ++ case DISABLE: ++ case ENABLE: ++ intr_status = RTL_R16(IntrStatus); ++ /* h/w no longer present (hotplug?) or major error, ++ bail */ ++ if (intr_status == 0xFFFF) ++ break; ++ ++ intr_status = intr_status & ~interested; ++ if (action == ENABLE) ++ intr_status = intr_status | interested; ++ RTL_W16(IntrMask, intr_status); ++ break; ++ case FORCE: ++ RTL_W8(TxPoll, (RTL_R8(TxPoll) | 0x01)); ++ break; ++ } ++} ++ static void r8169_irq ( struct nic *nic __unused, irq_action_t action ) { int intr_status = 0; int interested = RxUnderrun | RxOverflow | RxFIFOOver | RxErr | RxOK; @@@ -443,15 -450,15 +632,15 @@@ static int r8169_poll(struct nic *nic, unsigned int intr_status = 0; cur_rx = tpc->cur_rx; if ((tpc->RxDescArray[cur_rx].status & OWNbit) == 0) { -- /* There is a packet ready */ -- if(!retreive) -- return 1; ++ /* There is a packet ready */ ++ if (!retreive) ++ return 1; intr_status = RTL_R16(IntrStatus); /* h/w no longer present (hotplug?) or major error, -- bail */ ++ bail */ if (intr_status == 0xFFFF) return 0; -- RTL_W16(IntrStatus, intr_status & ++ RTL_W16(IntrStatus, intr_status & ~(RxFIFOOver | RxOverflow | RxOK)); if (!(tpc->RxDescArray[cur_rx].status & RxRES)) { @@@ -472,7 -479,7 +661,7 @@@ /* FIXME: shouldn't I reset the status on an error */ cur_rx = (cur_rx + 1) % NUM_RX_DESC; tpc->cur_rx = cur_rx; -- RTL_W16(IntrStatus, intr_status & ++ RTL_W16(IntrStatus, intr_status & (RxFIFOOver | RxOverflow | RxOK)); return 1; @@@ -569,7 -576,7 +758,7 @@@ static void rtl8169_hw_start(struct ni RTL_W8(Cfg9346, Cfg9346_Unlock); RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); -- RTL_W8(EarlyTxThres, EarlyTxThld); ++ RTL_W8(ETThReg, ETTh); /* For gigabit rtl8169 */ RTL_W16(RxMaxSize, RxPacketMaxSize); @@@ -585,6 -592,6 +774,27 @@@ TxInterFrameGapShift)); ++ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd)); ++ ++ if (tpc->mcfg == MCFG_METHOD_2 || tpc->mcfg == MCFG_METHOD_3) { ++ RTL_W16(CPlusCmd, ++ (RTL_R16(CPlusCmd) | (1 << 14) | (1 << 3))); ++ DBG_PRINT ++ ("Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14\n"); ++ } else { ++ RTL_W16(CPlusCmd, (RTL_R16(CPlusCmd) | (1 << 3))); ++ DBG_PRINT("Set MAC Reg C+CR Offset 0xE0: bit-3.\n"); ++ } ++ ++ { ++ //RTL_W16(0xE2, 0x1517); ++ //RTL_W16(0xE2, 0x152a); ++ //RTL_W16(0xE2, 0x282a); ++ RTL_W16(0xE2, 0x0000); ++ } ++ ++ ++ tpc->cur_rx = 0; RTL_W32(TxDescStartAddr, virt_to_le32desc(tpc->TxDescArray)); @@@ -598,6 -605,6 +808,9 @@@ /* no early-rx interrupts */ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); ++ ++ RTL_W16(IntrMask, rtl8169_intr_mask); ++ } static void rtl8169_init_ring(struct nic *nic __unused) @@@ -616,9 -623,9 +829,9 @@@ for (i = 0; i < NUM_RX_DESC; i++) { if (i == (NUM_RX_DESC - 1)) tpc->RxDescArray[i].status = -- (OWNbit | EORbit) + RX_BUF_SIZE; ++ (OWNbit | EORbit) | RX_BUF_SIZE; else -- tpc->RxDescArray[i].status = OWNbit + RX_BUF_SIZE; ++ tpc->RxDescArray[i].status = OWNbit | RX_BUF_SIZE; tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE]; tpc->RxDescArray[i].buf_addr = @@@ -681,6 -688,6 +894,8 @@@ static struct nic_operations r8169_oper static struct pci_id r8169_nics[] = { PCI_ROM(0x10ec, 0x8169, "r8169", "RealTek RTL8169 Gigabit Ethernet"), ++ PCI_ROM(0x16ec, 0x0116, "usr-r8169", "US Robotics RTL8169 Gigabit Ethernet"), ++ PCI_ROM(0x1186, 0x4300, "dlink-r8169", "D-Link RTL8169 Gigabit Ethernet"), }; PCI_DRIVER ( r8169_driver, r8169_nics, PCI_NO_CLASS ); @@@ -720,9 -727,9 +935,31 @@@ static int r8169_probe ( struct nic *ni printf("%s: %! at ioaddr %hX, ", pci->name, nic->node_addr, ioaddr); ++ // Config PHY ++ rtl8169_hw_PHY_config(nic); ++ ++ DBG_PRINT("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); ++ RTL_W8(0x82, 0x01); ++ ++ if (tpc->mcfg < MCFG_METHOD_3) { ++ DBG_PRINT("Set PCI Latency=0x40\n"); ++ pci_write_config_byte(pci, PCI_LATENCY_TIMER, 0x40); ++ } ++ ++ if (tpc->mcfg == MCFG_METHOD_2) { ++ DBG_PRINT("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); ++ RTL_W8(0x82, 0x01); ++ DBG_PRINT("Set PHY Reg 0x0bh = 0x00h\n"); ++ RTL8169_WRITE_GMII_REG(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 ++ } ++ /* if TBI is not endbled */ if (!(RTL_R8(PHYstatus) & TBI_Enable)) { -- int val = mdio_read(PHY_AUTO_NEGO_REG); ++ int val = RTL8169_READ_GMII_REG(ioaddr, PHY_AUTO_NEGO_REG); ++ ++#ifdef RTL8169_HW_FLOW_CONTROL_SUPPORT ++ val |= PHY_Cap_PAUSE | PHY_Cap_ASYM_PAUSE; ++#endif //end #define RTL8169_HW_FLOW_CONTROL_SUPPORT option = media; /* Force RTL8169 in 10/100/1000 Full/Half mode. */ @@@ -753,34 -760,34 +990,38 @@@ default: break; } -- /* leave PHY_AUTO_NEGO_REG bit4:0 unchanged */ -- mdio_write(PHY_AUTO_NEGO_REG, -- Cap10_100 | (val & 0x1F)); -- mdio_write(PHY_1000_CTRL_REG, Cap1000); ++ RTL8169_WRITE_GMII_REG(ioaddr, PHY_AUTO_NEGO_REG, Cap10_100 | (val & 0xC1F)); //leave PHY_AUTO_NEGO_REG bit4:0 unchanged ++ RTL8169_WRITE_GMII_REG(ioaddr, PHY_1000_CTRL_REG, ++ Cap1000); } else { dprintf(("Auto-negotiation Enabled.\n", pci->name)); -- /* enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged */ -- mdio_write(PHY_AUTO_NEGO_REG, -- PHY_Cap_10_Half | PHY_Cap_10_Full | -- PHY_Cap_100_Half | PHY_Cap_100_Full | -- (val & 0x1F)); ++ // enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged ++ RTL8169_WRITE_GMII_REG(ioaddr, PHY_AUTO_NEGO_REG, ++ PHY_Cap_10_Half | ++ PHY_Cap_10_Full | ++ PHY_Cap_100_Half | ++ PHY_Cap_100_Full | (val & ++ 0xC1F)); -- /* enable 1000 Full Mode */ -- mdio_write(PHY_1000_CTRL_REG, PHY_Cap_1000_Full); ++ // enable 1000 Full Mode ++// RTL8169_WRITE_GMII_REG( ioaddr, PHY_1000_CTRL_REG, PHY_Cap_1000_Full ); ++ RTL8169_WRITE_GMII_REG(ioaddr, PHY_1000_CTRL_REG, PHY_Cap_1000_Full | PHY_Cap_1000_Half); //rtl8168 -- } ++ } // end of if( option > 0 ) -- /* Enable auto-negotiation and restart auto-nigotiation */ -- mdio_write(PHY_CTRL_REG, -- PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego); ++ // Enable auto-negotiation and restart auto-nigotiation ++ RTL8169_WRITE_GMII_REG(ioaddr, PHY_CTRL_REG, ++ PHY_Enable_Auto_Nego | ++ PHY_Restart_Auto_Nego); udelay(100); -- /* wait for auto-negotiation process */ ++ // wait for auto-negotiation process for (i = 10000; i > 0; i--) { -- /* Check if auto-negotiation complete */ -- if (mdio_read(PHY_STAT_REG) & PHY_Auto_Neco_Comp) { ++ //check if auto-negotiation complete ++ if (RTL8169_READ_GMII_REG(ioaddr, PHY_STAT_REG) & ++ PHY_Auto_Neco_Comp) { udelay(100); option = RTL_R8(PHYstatus); if (option & _1000bpsF) { @@@ -797,8 -804,8 +1038,9 @@@ break; } else { udelay(100); -- } -- } /* end for-loop to wait for auto-negotiation process */ ++ } // end of if( RTL8169_READ_GMII_REG(ioaddr, 1) & 0x20 ) ++ } // end for-loop to wait for auto-negotiation process ++ } else { udelay(100); @@@ -819,5 -826,5 +1061,144 @@@ } ++//====================================================================================================== ++/* ++static void rtl8169_hw_PHY_reset(struct nic *nic __unused) ++{ ++ int val, phy_reset_expiretime = 50; ++ struct rtl8169_private *priv = dev->priv; ++ unsigned long ioaddr = priv->ioaddr; ++ ++ DBG_PRINT("%s: Reset RTL8169s PHY\n", dev->name); ++ ++ val = ( RTL8169_READ_GMII_REG( ioaddr, 0 ) | 0x8000 ) & 0xffff; ++ RTL8169_WRITE_GMII_REG( ioaddr, 0, val ); ++ ++ do //waiting for phy reset ++ { ++ if( RTL8169_READ_GMII_REG( ioaddr, 0 ) & 0x8000 ){ ++ phy_reset_expiretime --; ++ udelay(100); ++ } ++ else{ ++ break; ++ } ++ }while( phy_reset_expiretime >= 0 ); ++ ++ assert( phy_reset_expiretime > 0 ); ++} ++ ++*/ ++ ++//====================================================================================================== ++static void rtl8169_hw_PHY_config(struct nic *nic __unused) ++{ ++ ++ DBG_PRINT("priv->mcfg=%d, priv->pcfg=%d\n", tpc->mcfg, tpc->pcfg); ++ ++ if (tpc->mcfg == MCFG_METHOD_4) { ++/* ++ RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x1F, 0x0001 ); ++ RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x1b, 0x841e ); ++ RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x0e, 0x7bfb ); ++ RTL8169_WRITE_GMII_REG( (unsigned long)ioaddr, 0x09, 0x273a ); ++*/ ++ ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x1F, ++ 0x0002); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x01, ++ 0x90D0); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x1F, ++ 0x0000); ++ } else if ((tpc->mcfg == MCFG_METHOD_2) ++ || (tpc->mcfg == MCFG_METHOD_3)) { ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x1F, ++ 0x0001); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x15, ++ 0x1000); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x18, ++ 0x65C7); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04, ++ 0x0000); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x03, ++ 0x00A1); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x02, ++ 0x0008); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x01, ++ 0x1020); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x00, ++ 0x1000); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04, ++ 0x0800); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04, ++ 0x0000); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04, ++ 0x7000); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x03, ++ 0xFF41); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x02, ++ 0xDE60); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x01, ++ 0x0140); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x00, ++ 0x0077); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04, ++ 0x7800); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04, ++ 0x7000); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04, ++ 0xA000); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x03, ++ 0xDF01); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x02, ++ 0xDF20); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x01, ++ 0xFF95); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x00, ++ 0xFA00); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04, ++ 0xA800); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04, ++ 0xA000); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04, ++ 0xB000); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x03, ++ 0xFF41); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x02, ++ 0xDE20); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x01, ++ 0x0140); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x00, ++ 0x00BB); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04, ++ 0xB800); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04, ++ 0xB000); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04, ++ 0xF000); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x03, ++ 0xDF01); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x02, ++ 0xDF20); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x01, ++ 0xFF95); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x00, ++ 0xBF00); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04, ++ 0xF800); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04, ++ 0xF000); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x04, ++ 0x0000); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x1F, ++ 0x0000); ++ RTL8169_WRITE_GMII_REG((unsigned long) ioaddr, 0x0B, ++ 0x0000); ++ } else { ++ DBG_PRINT("tpc->mcfg=%d. Discard hw PHY config.\n", ++ tpc->mcfg); ++ } ++} ++ DRIVER ( "r8169/PCI", nic_driver, pci_driver, r8169_driver, r8169_probe, r8169_disable ); diff --cc src/drivers/net/smc9000.h index ffe5bbdb9,ac7f91639..318b77981 --- a/src/drivers/net/smc9000.h +++ b/src/drivers/net/smc9000.h @@@ -91,24 -91,6 +91,42 @@@ typedef unsigned long int dword #define MCR 10 /* 12 is reserved */ +// Receive/Phy Control Register +/* BANK 0 */ +#define RPC_REG 0x000A +#define RPC_SPEED 0x2000 // When 1 PHY is in 100Mbps mode. +#define RPC_DPLX 0x1000 // When 1 PHY is in Full-Duplex Mode +#define RPC_ANEG 0x0800 // When 1 PHY is in Auto-Negotiate Mode +#define RPC_LSXA_SHFT 5 // Bits to shift LS2A,LS1A,LS0A to lsb +#define RPC_LSXB_SHFT 2 // Bits to get LS2B,LS1B,LS0B to lsb +#define RPC_LED_100_10 (0x00) // LED = 100Mbps OR's with 10Mbps link detect +#define RPC_LED_RES (0x01) // LED = Reserved +#define RPC_LED_10 (0x02) // LED = 10Mbps link detect +#define RPC_LED_FD (0x03) // LED = Full Duplex Mode +#define RPC_LED_TX_RX (0x04) // LED = TX or RX packet occurred +#define RPC_LED_100 (0x05) // LED = 100Mbps link dectect +#define RPC_LED_TX (0x06) // LED = TX packet occurred +#define RPC_LED_RX (0x07) // LED = RX packet occurred +#define RPC_DEFAULT (RPC_ANEG | (RPC_LED_100 << RPC_LSXA_SHFT) | (RPC_LED_FD << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX) + ++// Receive/Phy Control Register ++/* BANK 0 */ ++#define RPC_REG 0x000A ++#define RPC_SPEED 0x2000 // When 1 PHY is in 100Mbps mode. ++#define RPC_DPLX 0x1000 // When 1 PHY is in Full-Duplex Mode ++#define RPC_ANEG 0x0800 // When 1 PHY is in Auto-Negotiate Mode ++#define RPC_LSXA_SHFT 5 // Bits to shift LS2A,LS1A,LS0A to lsb ++#define RPC_LSXB_SHFT 2 // Bits to get LS2B,LS1B,LS0B to lsb ++#define RPC_LED_100_10 (0x00) // LED = 100Mbps OR's with 10Mbps link detect ++#define RPC_LED_RES (0x01) // LED = Reserved ++#define RPC_LED_10 (0x02) // LED = 10Mbps link detect ++#define RPC_LED_FD (0x03) // LED = Full Duplex Mode ++#define RPC_LED_TX_RX (0x04) // LED = TX or RX packet occurred ++#define RPC_LED_100 (0x05) // LED = 100Mbps link dectect ++#define RPC_LED_TX (0x06) // LED = TX packet occurred ++#define RPC_LED_RX (0x07) // LED = RX packet occurred ++#define RPC_DEFAULT (RPC_ANEG | (RPC_LED_100 << RPC_LSXA_SHFT) | (RPC_LED_FD << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX) ++ /* BANK 1 */ #define CONFIG 0 #define CFG_AUI_SELECT 0x100 @@@ -210,95 -185,6 +228,191 @@@ #define RS_MULTICAST 0x0001 #define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT) ++// Management Interface Register (MII) ++#define MII_REG 0x0008 ++#define MII_MSK_CRS100 0x4000 // Disables CRS100 detection during tx half dup ++#define MII_MDOE 0x0008 // MII Output Enable ++#define MII_MCLK 0x0004 // MII Clock, pin MDCLK ++#define MII_MDI 0x0002 // MII Input, pin MDI ++#define MII_MDO 0x0001 // MII Output, pin MDO ++ ++// PHY Register Addresses (LAN91C111 Internal PHY) ++ ++// PHY Control Register ++#define PHY_CNTL_REG 0x00 ++#define PHY_CNTL_RST 0x8000 // 1=PHY Reset ++#define PHY_CNTL_LPBK 0x4000 // 1=PHY Loopback ++#define PHY_CNTL_SPEED 0x2000 // 1=100Mbps, 0=10Mpbs ++#define PHY_CNTL_ANEG_EN 0x1000 // 1=Enable Auto negotiation ++#define PHY_CNTL_PDN 0x0800 // 1=PHY Power Down mode ++#define PHY_CNTL_MII_DIS 0x0400 // 1=MII 4 bit interface disabled ++#define PHY_CNTL_ANEG_RST 0x0200 // 1=Reset Auto negotiate ++#define PHY_CNTL_DPLX 0x0100 // 1=Full Duplex, 0=Half Duplex ++#define PHY_CNTL_COLTST 0x0080 // 1= MII Colision Test ++ ++// PHY Status Register ++#define PHY_STAT_REG 0x01 ++#define PHY_STAT_CAP_T4 0x8000 // 1=100Base-T4 capable ++#define PHY_STAT_CAP_TXF 0x4000 // 1=100Base-X full duplex capable ++#define PHY_STAT_CAP_TXH 0x2000 // 1=100Base-X half duplex capable ++#define PHY_STAT_CAP_TF 0x1000 // 1=10Mbps full duplex capable ++#define PHY_STAT_CAP_TH 0x0800 // 1=10Mbps half duplex capable ++#define PHY_STAT_CAP_SUPR 0x0040 // 1=recv mgmt frames with not preamble ++#define PHY_STAT_ANEG_ACK 0x0020 // 1=ANEG has completed ++#define PHY_STAT_REM_FLT 0x0010 // 1=Remote Fault detected ++#define PHY_STAT_CAP_ANEG 0x0008 // 1=Auto negotiate capable ++#define PHY_STAT_LINK 0x0004 // 1=valid link ++#define PHY_STAT_JAB 0x0002 // 1=10Mbps jabber condition ++#define PHY_STAT_EXREG 0x0001 // 1=extended registers implemented ++ ++// PHY Identifier Registers ++#define PHY_ID1_REG 0x02 // PHY Identifier 1 ++#define PHY_ID2_REG 0x03 // PHY Identifier 2 ++ ++// PHY Auto-Negotiation Advertisement Register ++#define PHY_AD_REG 0x04 ++#define PHY_AD_NP 0x8000 // 1=PHY requests exchange of Next Page ++#define PHY_AD_ACK 0x4000 // 1=got link code word from remote ++#define PHY_AD_RF 0x2000 // 1=advertise remote fault ++#define PHY_AD_T4 0x0200 // 1=PHY is capable of 100Base-T4 ++#define PHY_AD_TX_FDX 0x0100 // 1=PHY is capable of 100Base-TX FDPLX ++#define PHY_AD_TX_HDX 0x0080 // 1=PHY is capable of 100Base-TX HDPLX ++#define PHY_AD_10_FDX 0x0040 // 1=PHY is capable of 10Base-T FDPLX ++#define PHY_AD_10_HDX 0x0020 // 1=PHY is capable of 10Base-T HDPLX ++#define PHY_AD_CSMA 0x0001 // 1=PHY is capable of 802.3 CMSA ++ ++// PHY Auto-negotiation Remote End Capability Register ++#define PHY_RMT_REG 0x05 ++// Uses same bit definitions as PHY_AD_REG ++ ++// PHY Configuration Register 1 ++#define PHY_CFG1_REG 0x10 ++#define PHY_CFG1_LNKDIS 0x8000 // 1=Rx Link Detect Function disabled ++#define PHY_CFG1_XMTDIS 0x4000 // 1=TP Transmitter Disabled ++#define PHY_CFG1_XMTPDN 0x2000 // 1=TP Transmitter Powered Down ++#define PHY_CFG1_BYPSCR 0x0400 // 1=Bypass scrambler/descrambler ++#define PHY_CFG1_UNSCDS 0x0200 // 1=Unscramble Idle Reception Disable ++#define PHY_CFG1_EQLZR 0x0100 // 1=Rx Equalizer Disabled ++#define PHY_CFG1_CABLE 0x0080 // 1=STP(150ohm), 0=UTP(100ohm) ++#define PHY_CFG1_RLVL0 0x0040 // 1=Rx Squelch level reduced by 4.5db ++#define PHY_CFG1_TLVL_SHIFT 2 // Transmit Output Level Adjust ++#define PHY_CFG1_TLVL_MASK 0x003C ++#define PHY_CFG1_TRF_MASK 0x0003 // Transmitter Rise/Fall time ++ ++ ++// PHY Configuration Register 2 ++#define PHY_CFG2_REG 0x11 ++#define PHY_CFG2_APOLDIS 0x0020 // 1=Auto Polarity Correction disabled ++#define PHY_CFG2_JABDIS 0x0010 // 1=Jabber disabled ++#define PHY_CFG2_MREG 0x0008 // 1=Multiple register access (MII mgt) ++#define PHY_CFG2_INTMDIO 0x0004 // 1=Interrupt signaled with MDIO pulseo ++ ++// PHY Status Output (and Interrupt status) Register ++#define PHY_INT_REG 0x12 // Status Output (Interrupt Status) ++#define PHY_INT_INT 0x8000 // 1=bits have changed since last read ++#define PHY_INT_LNKFAIL 0x4000 // 1=Link Not detected ++#define PHY_INT_LOSSSYNC 0x2000 // 1=Descrambler has lost sync ++#define PHY_INT_CWRD 0x1000 // 1=Invalid 4B5B code detected on rx ++#define PHY_INT_SSD 0x0800 // 1=No Start Of Stream detected on rx ++#define PHY_INT_ESD 0x0400 // 1=No End Of Stream detected on rx ++#define PHY_INT_RPOL 0x0200 // 1=Reverse Polarity detected ++#define PHY_INT_JAB 0x0100 // 1=Jabber detected ++#define PHY_INT_SPDDET 0x0080 // 1=100Base-TX mode, 0=10Base-T mode ++#define PHY_INT_DPLXDET 0x0040 // 1=Device in Full Duplex ++ ++// PHY Interrupt/Status Mask Register ++#define PHY_MASK_REG 0x13 // Interrupt Mask ++// Uses the same bit definitions as PHY_INT_REG ++ + +// PHY Register Addresses (LAN91C111 Internal PHY) + +// PHY Control Register +#define PHY_CNTL_REG 0x00 +#define PHY_CNTL_RST 0x8000 // 1=PHY Reset +#define PHY_CNTL_LPBK 0x4000 // 1=PHY Loopback +#define PHY_CNTL_SPEED 0x2000 // 1=100Mbps, 0=10Mpbs +#define PHY_CNTL_ANEG_EN 0x1000 // 1=Enable Auto negotiation +#define PHY_CNTL_PDN 0x0800 // 1=PHY Power Down mode +#define PHY_CNTL_MII_DIS 0x0400 // 1=MII 4 bit interface disabled +#define PHY_CNTL_ANEG_RST 0x0200 // 1=Reset Auto negotiate +#define PHY_CNTL_DPLX 0x0100 // 1=Full Duplex, 0=Half Duplex +#define PHY_CNTL_COLTST 0x0080 // 1= MII Colision Test + +// PHY Status Register +#define PHY_STAT_REG 0x01 +#define PHY_STAT_CAP_T4 0x8000 // 1=100Base-T4 capable +#define PHY_STAT_CAP_TXF 0x4000 // 1=100Base-X full duplex capable +#define PHY_STAT_CAP_TXH 0x2000 // 1=100Base-X half duplex capable +#define PHY_STAT_CAP_TF 0x1000 // 1=10Mbps full duplex capable +#define PHY_STAT_CAP_TH 0x0800 // 1=10Mbps half duplex capable +#define PHY_STAT_CAP_SUPR 0x0040 // 1=recv mgmt frames with not preamble +#define PHY_STAT_ANEG_ACK 0x0020 // 1=ANEG has completed +#define PHY_STAT_REM_FLT 0x0010 // 1=Remote Fault detected +#define PHY_STAT_CAP_ANEG 0x0008 // 1=Auto negotiate capable +#define PHY_STAT_LINK 0x0004 // 1=valid link +#define PHY_STAT_JAB 0x0002 // 1=10Mbps jabber condition +#define PHY_STAT_EXREG 0x0001 // 1=extended registers implemented + +// PHY Identifier Registers +#define PHY_ID1_REG 0x02 // PHY Identifier 1 +#define PHY_ID2_REG 0x03 // PHY Identifier 2 + +// PHY Auto-Negotiation Advertisement Register +#define PHY_AD_REG 0x04 +#define PHY_AD_NP 0x8000 // 1=PHY requests exchange of Next Page +#define PHY_AD_ACK 0x4000 // 1=got link code word from remote +#define PHY_AD_RF 0x2000 // 1=advertise remote fault +#define PHY_AD_T4 0x0200 // 1=PHY is capable of 100Base-T4 +#define PHY_AD_TX_FDX 0x0100 // 1=PHY is capable of 100Base-TX FDPLX +#define PHY_AD_TX_HDX 0x0080 // 1=PHY is capable of 100Base-TX HDPLX +#define PHY_AD_10_FDX 0x0040 // 1=PHY is capable of 10Base-T FDPLX +#define PHY_AD_10_HDX 0x0020 // 1=PHY is capable of 10Base-T HDPLX +#define PHY_AD_CSMA 0x0001 // 1=PHY is capable of 802.3 CMSA + +// PHY Auto-negotiation Remote End Capability Register +#define PHY_RMT_REG 0x05 +// Uses same bit definitions as PHY_AD_REG + +// PHY Configuration Register 1 +#define PHY_CFG1_REG 0x10 +#define PHY_CFG1_LNKDIS 0x8000 // 1=Rx Link Detect Function disabled +#define PHY_CFG1_XMTDIS 0x4000 // 1=TP Transmitter Disabled +#define PHY_CFG1_XMTPDN 0x2000 // 1=TP Transmitter Powered Down +#define PHY_CFG1_BYPSCR 0x0400 // 1=Bypass scrambler/descrambler +#define PHY_CFG1_UNSCDS 0x0200 // 1=Unscramble Idle Reception Disable +#define PHY_CFG1_EQLZR 0x0100 // 1=Rx Equalizer Disabled +#define PHY_CFG1_CABLE 0x0080 // 1=STP(150ohm), 0=UTP(100ohm) +#define PHY_CFG1_RLVL0 0x0040 // 1=Rx Squelch level reduced by 4.5db +#define PHY_CFG1_TLVL_SHIFT 2 // Transmit Output Level Adjust +#define PHY_CFG1_TLVL_MASK 0x003C +#define PHY_CFG1_TRF_MASK 0x0003 // Transmitter Rise/Fall time + + +// PHY Configuration Register 2 +#define PHY_CFG2_REG 0x11 +#define PHY_CFG2_APOLDIS 0x0020 // 1=Auto Polarity Correction disabled +#define PHY_CFG2_JABDIS 0x0010 // 1=Jabber disabled +#define PHY_CFG2_MREG 0x0008 // 1=Multiple register access (MII mgt) +#define PHY_CFG2_INTMDIO 0x0004 // 1=Interrupt signaled with MDIO pulseo + +// PHY Status Output (and Interrupt status) Register +#define PHY_INT_REG 0x12 // Status Output (Interrupt Status) +#define PHY_INT_INT 0x8000 // 1=bits have changed since last read +#define PHY_INT_LNKFAIL 0x4000 // 1=Link Not detected +#define PHY_INT_LOSSSYNC 0x2000 // 1=Descrambler has lost sync +#define PHY_INT_CWRD 0x1000 // 1=Invalid 4B5B code detected on rx +#define PHY_INT_SSD 0x0800 // 1=No Start Of Stream detected on rx +#define PHY_INT_ESD 0x0400 // 1=No End Of Stream detected on rx +#define PHY_INT_RPOL 0x0200 // 1=Reverse Polarity detected +#define PHY_INT_JAB 0x0100 // 1=Jabber detected +#define PHY_INT_SPDDET 0x0080 // 1=100Base-TX mode, 0=10Base-T mode +#define PHY_INT_DPLXDET 0x0040 // 1=Device in Full Duplex + +// PHY Interrupt/Status Mask Register +#define PHY_MASK_REG 0x13 // Interrupt Mask +// Uses the same bit definitions as PHY_INT_REG + /*------------------------------------------------------------------------- * I define some macros to make it easier to do somewhat common