X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fnet%2Frtl8169.c;h=e45d1a52212d5739c096dcc1b105d5816666f128;hb=f12d4cb48a1040c25a55148d0eedee1a896364e6;hp=63ea2cca9b1090e8945d46ec35458d1da10d6535;hpb=fe08fb658008cd4be54758faa5d382a2b3b1f86a;p=u-boot diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c index 63ea2cca9b..e45d1a5221 100644 --- a/drivers/net/rtl8169.c +++ b/drivers/net/rtl8169.c @@ -48,16 +48,17 @@ * * Indent Options: indent -kr -i8 ***************************************************************************/ - +/* + * 26 August 2006 Mihai Georgian + * Modified to use le32_to_cpu and cpu_to_le32 properly + */ #include #include #include +#include #include #include -#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \ - defined(CONFIG_RTL8169) - #undef DEBUG_RTL8169 #undef DEBUG_RTL8169_TX #undef DEBUG_RTL8169_RX @@ -68,12 +69,7 @@ static u32 ioaddr; /* Condensed operations for readability. */ -#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr)) -#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr)) - #define currticks() get_timer(0) -#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) -#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) /* media options */ #define MAX_UNITS 8 @@ -102,7 +98,7 @@ static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; #define RTL_MIN_IO_SIZE 0x80 #define TX_TIMEOUT (6*HZ) -/* write/read MMIO register */ +/* 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)) @@ -114,11 +110,16 @@ static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; #define ETH_ALEN MAC_ADDR_LEN #define ETH_ZLEN 60 +#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, (pci_addr_t)a) +#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, (phys_addr_t)a) + enum RTL8169_registers { MAC0 = 0, /* Ethernet hardware address. */ MAR0 = 8, /* Multicast filter. */ - TxDescStartAddr = 0x20, - TxHDescStartAddr = 0x28, + TxDescStartAddrLow = 0x20, + TxDescStartAddrHigh = 0x24, + TxHDescStartAddrLow = 0x28, + TxHDescStartAddrHigh = 0x2c, FLASH = 0x30, ERSR = 0x36, ChipCmd = 0x37, @@ -143,7 +144,8 @@ enum RTL8169_registers { PHYstatus = 0x6C, RxMaxSize = 0xDA, CPlusCmd = 0xE0, - RxDescStartAddr = 0xE4, + RxDescStartAddrLow = 0xE4, + RxDescStartAddrHigh = 0xE8, EarlyTxThres = 0xEC, FuncEvent = 0xF0, FuncEventMask = 0xF4, @@ -218,7 +220,7 @@ enum RTL8169_register_content { PHY_Enable_Auto_Nego = 0x1000, /* PHY_STAT_REG = 1; */ - PHY_Auto_Neco_Comp = 0x0020, + PHY_Auto_Nego_Comp = 0x0020, /* PHY_AUTO_NEGO_REG = 4; */ PHY_Cap_10_Half = 0x0020, @@ -249,6 +251,15 @@ static struct { } rtl_chip_info[] = { {"RTL-8169", 0x00, 0xff7e1880,}, {"RTL-8169", 0x04, 0xff7e1880,}, + {"RTL-8169", 0x00, 0xff7e1880,}, + {"RTL-8169s/8110s", 0x02, 0xff7e1880,}, + {"RTL-8169s/8110s", 0x04, 0xff7e1880,}, + {"RTL-8169sb/8110sb", 0x10, 0xff7e1880,}, + {"RTL-8169sc/8110sc", 0x18, 0xff7e1880,}, + {"RTL-8168b/8111sb", 0x30, 0xff7e1880,}, + {"RTL-8168b/8111sb", 0x38, 0xff7e1880,}, + {"RTL-8101e", 0x34, 0xff7e1880,}, + {"RTL-8100e", 0x32, 0xff7e1880,}, }; enum _DescStatusBit { @@ -314,6 +325,7 @@ static const unsigned int rtl8169_rx_config = (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); static struct pci_device_id supported[] = { + {PCI_VENDOR_ID_REALTEK, 0x8167}, {PCI_VENDOR_ID_REALTEK, 0x8169}, {} }; @@ -354,8 +366,6 @@ int mdio_read(int RegAddr) return value; } -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) - static int rtl8169_init_board(struct eth_device *dev) { int i; @@ -389,7 +399,7 @@ static int rtl8169_init_board(struct eth_device *dev) /* if unknown chip, assume array element #0, original RTL-8169 in this case */ printf("PCI device %s: unknown chip version, assuming RTL-8169\n", dev->name); - printf("PCI device: TxConfig = 0x%hX\n", (unsigned long) RTL_R32(TxConfig)); + printf("PCI device: TxConfig = 0x%lX\n", (unsigned long) RTL_R32(TxConfig)); tpc->chipset = 0; match: @@ -413,23 +423,27 @@ static int rtl_recv(struct eth_device *dev) ioaddr = dev->iobase; cur_rx = tpc->cur_rx; - if ((tpc->RxDescArray[cur_rx].status & OWNbit) == 0) { - if (!(tpc->RxDescArray[cur_rx].status & RxRES)) { + flush_cache((unsigned long)&tpc->RxDescArray[cur_rx], + sizeof(struct RxDesc)); + if ((le32_to_cpu(tpc->RxDescArray[cur_rx].status) & OWNbit) == 0) { + if (!(le32_to_cpu(tpc->RxDescArray[cur_rx].status) & RxRES)) { unsigned char rxdata[RX_BUF_LEN]; - length = (int) (tpc->RxDescArray[cur_rx]. - status & 0x00001FFF) - 4; + length = (int) (le32_to_cpu(tpc->RxDescArray[cur_rx]. + status) & 0x00001FFF) - 4; memcpy(rxdata, tpc->RxBufferRing[cur_rx], length); NetReceive(rxdata, length); if (cur_rx == NUM_RX_DESC - 1) tpc->RxDescArray[cur_rx].status = - (OWNbit | EORbit) + RX_BUF_SIZE; + cpu_to_le32((OWNbit | EORbit) + RX_BUF_SIZE); else tpc->RxDescArray[cur_rx].status = - OWNbit + RX_BUF_SIZE; + cpu_to_le32(OWNbit + RX_BUF_SIZE); tpc->RxDescArray[cur_rx].buf_addr = - virt_to_bus(tpc->RxBufferRing[cur_rx]); + cpu_to_le32(bus_to_phys(tpc->RxBufferRing[cur_rx])); + flush_cache((unsigned long)tpc->RxBufferRing[cur_rx], + RX_BUF_SIZE); } else { puts("Error Rx"); } @@ -437,6 +451,10 @@ static int rtl_recv(struct eth_device *dev) tpc->cur_rx = cur_rx; return 1; + } else { + ushort sts = RTL_R8(IntrStatus); + RTL_W8(IntrStatus, sts & ~(TxErr | RxErr | SYSErr)); + udelay(100); /* wait */ } tpc->cur_rx = cur_rx; return (0); /* initially as this is called to flush the input */ @@ -454,6 +472,7 @@ static int rtl_send(struct eth_device *dev, volatile void *packet, int length) u8 *ptxb; int entry = tpc->cur_tx % NUM_TX_DESC; u32 len = length; + int ret; #ifdef DEBUG_RTL8169_TX int stime = currticks(); @@ -466,38 +485,47 @@ static int rtl_send(struct eth_device *dev, volatile void *packet, int length) /* point to the current txb incase multiple tx_rings are used */ ptxb = tpc->Tx_skbuff[entry * MAX_ETH_FRAME_SIZE]; memcpy(ptxb, (char *)packet, (int)length); + flush_cache((unsigned long)ptxb, length); while (len < ETH_ZLEN) ptxb[len++] = '\0'; - tpc->TxDescArray[entry].buf_addr = virt_to_bus(ptxb); + tpc->TxDescArray[entry].buf_Haddr = 0; + tpc->TxDescArray[entry].buf_addr = cpu_to_le32(bus_to_phys(ptxb)); if (entry != (NUM_TX_DESC - 1)) { tpc->TxDescArray[entry].status = - (OWNbit | FSbit | LSbit) | ((len > ETH_ZLEN) ? - len : ETH_ZLEN); + cpu_to_le32((OWNbit | FSbit | LSbit) | + ((len > ETH_ZLEN) ? len : ETH_ZLEN)); } else { tpc->TxDescArray[entry].status = - (OWNbit | EORbit | FSbit | LSbit) | - ((len > ETH_ZLEN) ? length : ETH_ZLEN); + cpu_to_le32((OWNbit | EORbit | FSbit | LSbit) | + ((len > ETH_ZLEN) ? len : ETH_ZLEN)); } RTL_W8(TxPoll, 0x40); /* set polling bit */ tpc->cur_tx++; to = currticks() + TX_TIMEOUT; - while ((tpc->TxDescArray[entry].status & OWNbit) && (currticks() < to)); /* wait */ + do { + flush_cache((unsigned long)&tpc->TxDescArray[entry], + sizeof(struct TxDesc)); + } while ((le32_to_cpu(tpc->TxDescArray[entry].status) & OWNbit) + && (currticks() < to)); /* wait */ if (currticks() >= to) { #ifdef DEBUG_RTL8169_TX puts ("tx timeout/error\n"); printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); #endif - return 0; + ret = 0; } else { #ifdef DEBUG_RTL8169_TX puts("tx done\n"); #endif - return length; + ret = length; } + /* Delay to make net console (nc) work properly */ + udelay(20); + return ret; } static void rtl8169_set_rx_mode(struct eth_device *dev) @@ -546,7 +574,11 @@ static void rtl8169_hw_start(struct eth_device *dev) #endif RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); + + /* RTL-8169sb/8110sb or previous version */ + if (tpc->chipset <= 5) + RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); + RTL_W8(EarlyTxThres, EarlyTxThld); /* For gigabit rtl8169 */ @@ -564,8 +596,15 @@ static void rtl8169_hw_start(struct eth_device *dev) tpc->cur_rx = 0; - RTL_W32(TxDescStartAddr, virt_to_le32desc(tpc->TxDescArray)); - RTL_W32(RxDescStartAddr, virt_to_le32desc(tpc->RxDescArray)); + RTL_W32(TxDescStartAddrLow, bus_to_phys(tpc->TxDescArray)); + RTL_W32(TxDescStartAddrHigh, (unsigned long)0); + RTL_W32(RxDescStartAddrLow, bus_to_phys(tpc->RxDescArray)); + RTL_W32(RxDescStartAddrHigh, (unsigned long)0); + + /* RTL-8169sc/8110sc or later version */ + if (tpc->chipset > 5) + RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); + RTL_W8(Cfg9346, Cfg9346_Lock); udelay(10); @@ -603,13 +642,15 @@ static void rtl8169_init_ring(struct eth_device *dev) for (i = 0; i < NUM_RX_DESC; i++) { if (i == (NUM_RX_DESC - 1)) tpc->RxDescArray[i].status = - (OWNbit | EORbit) + RX_BUF_SIZE; + cpu_to_le32((OWNbit | EORbit) + RX_BUF_SIZE); else - tpc->RxDescArray[i].status = OWNbit + RX_BUF_SIZE; + tpc->RxDescArray[i].status = + cpu_to_le32(OWNbit + RX_BUF_SIZE); tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE]; tpc->RxDescArray[i].buf_addr = - virt_to_bus(tpc->RxBufferRing[i]); + cpu_to_le32(bus_to_phys(tpc->RxBufferRing[i])); + flush_cache((unsigned long)tpc->RxBufferRing[i], RX_BUF_SIZE); } #ifdef DEBUG_RTL8169 @@ -620,11 +661,9 @@ static void rtl8169_init_ring(struct eth_device *dev) /************************************************************************** RESET - Finish setting up the ethernet interface ***************************************************************************/ -static void rtl_reset(struct eth_device *dev, bd_t *bis) +static int rtl_reset(struct eth_device *dev, bd_t *bis) { int i; - u8 diff; - u32 TxPhyAddr, RxPhyAddr; #ifdef DEBUG_RTL8169 int stime = currticks(); @@ -632,25 +671,14 @@ static void rtl_reset(struct eth_device *dev, bd_t *bis) #endif tpc->TxDescArrays = tx_ring; - if (tpc->TxDescArrays == 0) - puts("Allot Error"); /* Tx Desscriptor needs 256 bytes alignment; */ - TxPhyAddr = virt_to_bus(tpc->TxDescArrays); - diff = 256 - (TxPhyAddr - ((TxPhyAddr >> 8) << 8)); - TxPhyAddr += diff; - tpc->TxDescArray = (struct TxDesc *) (tpc->TxDescArrays + diff); + tpc->TxDescArray = (struct TxDesc *) ((unsigned long)(tpc->TxDescArrays + + 255) & ~255); tpc->RxDescArrays = rx_ring; /* Rx Desscriptor needs 256 bytes alignment; */ - RxPhyAddr = virt_to_bus(tpc->RxDescArrays); - diff = 256 - (RxPhyAddr - ((RxPhyAddr >> 8) << 8)); - RxPhyAddr += diff; - tpc->RxDescArray = (struct RxDesc *) (tpc->RxDescArrays + diff); - - if (tpc->TxDescArrays == NULL || tpc->RxDescArrays == NULL) { - puts("Allocate RxDescArray or TxDescArray failed\n"); - return; - } + tpc->RxDescArray = (struct RxDesc *) ((unsigned long)(tpc->RxDescArrays + + 255) & ~255); rtl8169_init_ring(dev); rtl8169_hw_start(dev); @@ -669,6 +697,7 @@ static void rtl_reset(struct eth_device *dev, bd_t *bis) #ifdef DEBUG_RTL8169 printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); #endif + return 0; } /************************************************************************** @@ -736,6 +765,7 @@ static int rtl_init(struct eth_device *dev, bd_t *bis) dev->enetaddr[i] = RTL_R8(MAC0 + i); #ifdef DEBUG_RTL8169 + printf("chipset = %d\n", tpc->chipset); printf("MAC Address"); for (i = 0; i < MAC_ADDR_LEN; i++) printf(":%02x", dev->enetaddr[i]); @@ -808,7 +838,7 @@ static int rtl_init(struct eth_device *dev, bd_t *bis) /* 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) { + if (mdio_read(PHY_STAT_REG) & PHY_Auto_Nego_Comp) { udelay(100); option = RTL_R8(PHYstatus); if (option & _1000bpsF) { @@ -818,13 +848,12 @@ static int rtl_init(struct eth_device *dev, bd_t *bis) #endif } else { #ifdef DEBUG_RTL8169 - printf - ("%s: %sMbps %s-duplex operation.\n", - dev->name, - (option & _100bps) ? "100" : - "10", - (option & FullDup) ? "Full" : - "Half"); + printf("%s: %sMbps %s-duplex operation.\n", + dev->name, + (option & _100bps) ? "100" : + "10", + (option & FullDup) ? "Full" : + "Half"); #endif } break; @@ -869,7 +898,7 @@ int rtl8169_initialize(bd_t *bis) sprintf (dev->name, "RTL8169#%d", card_number); dev->priv = (void *) devno; - dev->iobase = (int)bus_to_phys(iobase); + dev->iobase = (int)pci_mem_to_phys(devno, iobase); dev->init = rtl_reset; dev->halt = rtl_halt; @@ -884,5 +913,3 @@ int rtl8169_initialize(bd_t *bis) } return card_number; } - -#endif