12439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 22439e4bfSJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2002 32439e4bfSJean-Christophe PLAGNIOL-VILLARD * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 42439e4bfSJean-Christophe PLAGNIOL-VILLARD * 51a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 62439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 72439e4bfSJean-Christophe PLAGNIOL-VILLARD 82439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <common.h> 92439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <malloc.h> 102439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <net.h> 1110efa024SBen Warren #include <netdev.h> 122439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h> 132439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <pci.h> 142439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <miiphy.h> 152439e4bfSJean-Christophe PLAGNIOL-VILLARD 162439e4bfSJean-Christophe PLAGNIOL-VILLARD #undef DEBUG 172439e4bfSJean-Christophe PLAGNIOL-VILLARD 182439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Ethernet chip registers. 192439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 202439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBStatus 0 /* Rx/Command Unit Status *Word* */ 212439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBIntAckByte 1 /* Rx/Command Unit STAT/ACK byte */ 222439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBCmd 2 /* Rx/Command Unit Command *Word* */ 232439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBIntrCtlByte 3 /* Rx/Command Unit Intr.Control Byte */ 242439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBPointer 4 /* General purpose pointer. */ 252439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBPort 8 /* Misc. commands and operands. */ 262439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBflash 12 /* Flash memory control. */ 272439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBeeprom 14 /* EEPROM memory control. */ 282439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBCtrlMDI 16 /* MDI interface control. */ 292439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBEarlyRx 20 /* Early receive byte count. */ 302439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBGenControl 28 /* 82559 General Control Register */ 312439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCBGenStatus 29 /* 82559 General Status register */ 322439e4bfSJean-Christophe PLAGNIOL-VILLARD 332439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 82559 SCB status word defnitions 342439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 352439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_STATUS_CX 0x8000 /* CU finished command (transmit) */ 362439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_STATUS_FR 0x4000 /* frame received */ 372439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_STATUS_CNA 0x2000 /* CU left active state */ 382439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_STATUS_RNR 0x1000 /* receiver left ready state */ 392439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_STATUS_MDI 0x0800 /* MDI read/write cycle done */ 402439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_STATUS_SWI 0x0400 /* software generated interrupt */ 412439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_STATUS_FCP 0x0100 /* flow control pause interrupt */ 422439e4bfSJean-Christophe PLAGNIOL-VILLARD 432439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_INTACK_MASK 0xFD00 /* all the above */ 442439e4bfSJean-Christophe PLAGNIOL-VILLARD 452439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_INTACK_TX (SCB_STATUS_CX | SCB_STATUS_CNA) 462439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_INTACK_RX (SCB_STATUS_FR | SCB_STATUS_RNR) 472439e4bfSJean-Christophe PLAGNIOL-VILLARD 482439e4bfSJean-Christophe PLAGNIOL-VILLARD /* System control block commands 492439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 502439e4bfSJean-Christophe PLAGNIOL-VILLARD /* CU Commands */ 512439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_NOP 0x0000 522439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_START 0x0010 532439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_RESUME 0x0020 542439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_STATSADDR 0x0040 /* Load Dump Statistics ctrs addr */ 552439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_SHOWSTATS 0x0050 /* Dump statistics counters. */ 562439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_ADDR_LOAD 0x0060 /* Base address to add to CU commands */ 572439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_DUMPSTATS 0x0070 /* Dump then reset stats counters. */ 582439e4bfSJean-Christophe PLAGNIOL-VILLARD 592439e4bfSJean-Christophe PLAGNIOL-VILLARD /* RUC Commands */ 602439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RUC_NOP 0x0000 612439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RUC_START 0x0001 622439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RUC_RESUME 0x0002 632439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RUC_ABORT 0x0004 642439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RUC_ADDR_LOAD 0x0006 /* (seems not to clear on acceptance) */ 652439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RUC_RESUMENR 0x0007 662439e4bfSJean-Christophe PLAGNIOL-VILLARD 672439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_CMD_MASK 0x00f0 682439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_CMD_MASK 0x0007 692439e4bfSJean-Christophe PLAGNIOL-VILLARD 702439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_M 0x0100 /* 0 = enable interrupt, 1 = disable */ 712439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SCB_SWI 0x0200 /* 1 - cause device to interrupt */ 722439e4bfSJean-Christophe PLAGNIOL-VILLARD 732439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CU_STATUS_MASK 0x00C0 742439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_STATUS_MASK 0x003C 752439e4bfSJean-Christophe PLAGNIOL-VILLARD 762439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_STATUS_IDLE (0<<2) 772439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_STATUS_SUS (1<<2) 782439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_STATUS_NORES (2<<2) 792439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_STATUS_READY (4<<2) 802439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_STATUS_NO_RBDS_SUS ((1<<2)|(8<<2)) 812439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_STATUS_NO_RBDS_NORES ((2<<2)|(8<<2)) 822439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RU_STATUS_NO_RBDS_READY ((4<<2)|(8<<2)) 832439e4bfSJean-Christophe PLAGNIOL-VILLARD 842439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 82559 Port interface commands. 852439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 862439e4bfSJean-Christophe PLAGNIOL-VILLARD #define I82559_RESET 0x00000000 /* Software reset */ 872439e4bfSJean-Christophe PLAGNIOL-VILLARD #define I82559_SELFTEST 0x00000001 /* 82559 Selftest command */ 882439e4bfSJean-Christophe PLAGNIOL-VILLARD #define I82559_SELECTIVE_RESET 0x00000002 892439e4bfSJean-Christophe PLAGNIOL-VILLARD #define I82559_DUMP 0x00000003 902439e4bfSJean-Christophe PLAGNIOL-VILLARD #define I82559_DUMP_WAKEUP 0x00000007 912439e4bfSJean-Christophe PLAGNIOL-VILLARD 922439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 82559 Eeprom interface. 932439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 942439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */ 952439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_CS 0x02 /* EEPROM chip select. */ 962439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ 972439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_WRITE_0 0x01 982439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_WRITE_1 0x05 992439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_DATA_READ 0x08 /* EEPROM chip data out. */ 1002439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_ENB (0x4800 | EE_CS) 1012439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_CMD_BITS 3 1022439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_DATA_BITS 16 1032439e4bfSJean-Christophe PLAGNIOL-VILLARD 1042439e4bfSJean-Christophe PLAGNIOL-VILLARD /* The EEPROM commands include the alway-set leading bit. 1052439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 1062439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_EWENB_CMD (4 << addr_len) 1072439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_WRITE_CMD (5 << addr_len) 1082439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_READ_CMD (6 << addr_len) 1092439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_ERASE_CMD (7 << addr_len) 1102439e4bfSJean-Christophe PLAGNIOL-VILLARD 1112439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Receive frame descriptors. 1122439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 1132439e4bfSJean-Christophe PLAGNIOL-VILLARD struct RxFD { 1142439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u16 status; 1152439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u16 control; 1162439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u32 link; /* struct RxFD * */ 1172439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u32 rx_buf_addr; /* void * */ 1182439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u32 count; 1192439e4bfSJean-Christophe PLAGNIOL-VILLARD 1202439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u8 data[PKTSIZE_ALIGN]; 1212439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 1222439e4bfSJean-Christophe PLAGNIOL-VILLARD 1232439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_STATUS_C 0x8000 /* completion of received frame */ 1242439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_STATUS_OK 0x2000 /* frame received with no errors */ 1252439e4bfSJean-Christophe PLAGNIOL-VILLARD 1262439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_CONTROL_EL 0x8000 /* 1=last RFD in RFA */ 1272439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_CONTROL_S 0x4000 /* 1=suspend RU after receiving frame */ 1282439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_CONTROL_H 0x0010 /* 1=RFD is a header RFD */ 1292439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_CONTROL_SF 0x0008 /* 0=simplified, 1=flexible mode */ 1302439e4bfSJean-Christophe PLAGNIOL-VILLARD 1312439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_COUNT_MASK 0x3fff 1322439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_COUNT_F 0x4000 1332439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_COUNT_EOF 0x8000 1342439e4bfSJean-Christophe PLAGNIOL-VILLARD 1352439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_CRC 0x0800 /* crc error */ 1362439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_ALIGNMENT 0x0400 /* alignment error */ 1372439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_RESOURCE 0x0200 /* out of space, no resources */ 1382439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_DMA_OVER 0x0100 /* DMA overrun */ 1392439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_SHORT 0x0080 /* short frame error */ 1402439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_LENGTH 0x0020 1412439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_ERROR 0x0010 /* receive error */ 1422439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_NO_ADR_MATCH 0x0004 /* no address match */ 1432439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_IA_MATCH 0x0002 /* individual address does not match */ 1442439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RFD_RX_TCO 0x0001 /* TCO indication */ 1452439e4bfSJean-Christophe PLAGNIOL-VILLARD 1462439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Transmit frame descriptors 1472439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 1482439e4bfSJean-Christophe PLAGNIOL-VILLARD struct TxFD { /* Transmit frame descriptor set. */ 1492439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u16 status; 1502439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u16 command; 1512439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u32 link; /* void * */ 1522439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u32 tx_desc_addr; /* Always points to the tx_buf_addr element. */ 1532439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile s32 count; 1542439e4bfSJean-Christophe PLAGNIOL-VILLARD 1552439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u32 tx_buf_addr0; /* void *, frame to be transmitted. */ 1562439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile s32 tx_buf_size0; /* Length of Tx frame. */ 1572439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u32 tx_buf_addr1; /* void *, frame to be transmitted. */ 1582439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile s32 tx_buf_size1; /* Length of Tx frame. */ 1592439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 1602439e4bfSJean-Christophe PLAGNIOL-VILLARD 1612439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TxCB_CMD_TRANSMIT 0x0004 /* transmit command */ 1622439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TxCB_CMD_SF 0x0008 /* 0=simplified, 1=flexible mode */ 1632439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TxCB_CMD_NC 0x0010 /* 0=CRC insert by controller */ 1642439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TxCB_CMD_I 0x2000 /* generate interrupt on completion */ 1652439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TxCB_CMD_S 0x4000 /* suspend on completion */ 1662439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TxCB_CMD_EL 0x8000 /* last command block in CBL */ 1672439e4bfSJean-Christophe PLAGNIOL-VILLARD 1682439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TxCB_COUNT_MASK 0x3fff 1692439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TxCB_COUNT_EOF 0x8000 1702439e4bfSJean-Christophe PLAGNIOL-VILLARD 1712439e4bfSJean-Christophe PLAGNIOL-VILLARD /* The Speedo3 Rx and Tx frame/buffer descriptors. 1722439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 1732439e4bfSJean-Christophe PLAGNIOL-VILLARD struct descriptor { /* A generic descriptor. */ 1742439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u16 status; 1752439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u16 command; 1762439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile u32 link; /* struct descriptor * */ 1772439e4bfSJean-Christophe PLAGNIOL-VILLARD 1782439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char params[0]; 1792439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 1802439e4bfSJean-Christophe PLAGNIOL-VILLARD 1816d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_SYS_CMD_EL 0x8000 1826d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_SYS_CMD_SUSPEND 0x4000 1836d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_SYS_CMD_INT 0x2000 1846d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_SYS_CMD_IAS 0x0001 /* individual address setup */ 1856d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_SYS_CMD_CONFIGURE 0x0002 /* configure */ 1862439e4bfSJean-Christophe PLAGNIOL-VILLARD 1876d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_SYS_STATUS_C 0x8000 1886d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_SYS_STATUS_OK 0x2000 1892439e4bfSJean-Christophe PLAGNIOL-VILLARD 1902439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Misc. 1912439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 1922439e4bfSJean-Christophe PLAGNIOL-VILLARD #define NUM_RX_DESC PKTBUFSRX 1932439e4bfSJean-Christophe PLAGNIOL-VILLARD #define NUM_TX_DESC 1 /* Number of TX descriptors */ 1942439e4bfSJean-Christophe PLAGNIOL-VILLARD 1952439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TOUT_LOOP 1000000 1962439e4bfSJean-Christophe PLAGNIOL-VILLARD 1972439e4bfSJean-Christophe PLAGNIOL-VILLARD #define ETH_ALEN 6 1982439e4bfSJean-Christophe PLAGNIOL-VILLARD 1992439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct RxFD rx_ring[NUM_RX_DESC]; /* RX descriptor ring */ 2002439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct TxFD tx_ring[NUM_TX_DESC]; /* TX descriptor ring */ 2012439e4bfSJean-Christophe PLAGNIOL-VILLARD static int rx_next; /* RX descriptor ring pointer */ 2022439e4bfSJean-Christophe PLAGNIOL-VILLARD static int tx_next; /* TX descriptor ring pointer */ 2032439e4bfSJean-Christophe PLAGNIOL-VILLARD static int tx_threshold; 2042439e4bfSJean-Christophe PLAGNIOL-VILLARD 2052439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 2062439e4bfSJean-Christophe PLAGNIOL-VILLARD * The parameters for a CmdConfigure operation. 2072439e4bfSJean-Christophe PLAGNIOL-VILLARD * There are so many options that it would be difficult to document 2082439e4bfSJean-Christophe PLAGNIOL-VILLARD * each bit. We mostly use the default or recommended settings. 2092439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 2102439e4bfSJean-Christophe PLAGNIOL-VILLARD static const char i82557_config_cmd[] = { 2112439e4bfSJean-Christophe PLAGNIOL-VILLARD 22, 0x08, 0, 0, 0, 0, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */ 2122439e4bfSJean-Christophe PLAGNIOL-VILLARD 0, 0x2E, 0, 0x60, 0, 2132439e4bfSJean-Christophe PLAGNIOL-VILLARD 0xf2, 0x48, 0, 0x40, 0xf2, 0x80, /* 0x40=Force full-duplex */ 2142439e4bfSJean-Christophe PLAGNIOL-VILLARD 0x3f, 0x05, 2152439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 2162439e4bfSJean-Christophe PLAGNIOL-VILLARD static const char i82558_config_cmd[] = { 2172439e4bfSJean-Christophe PLAGNIOL-VILLARD 22, 0x08, 0, 1, 0, 0, 0x22, 0x03, 1, /* 1=Use MII 0=Use AUI */ 2182439e4bfSJean-Christophe PLAGNIOL-VILLARD 0, 0x2E, 0, 0x60, 0x08, 0x88, 2192439e4bfSJean-Christophe PLAGNIOL-VILLARD 0x68, 0, 0x40, 0xf2, 0x84, /* Disable FC */ 2202439e4bfSJean-Christophe PLAGNIOL-VILLARD 0x31, 0x05, 2212439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 2222439e4bfSJean-Christophe PLAGNIOL-VILLARD 2232439e4bfSJean-Christophe PLAGNIOL-VILLARD static void init_rx_ring (struct eth_device *dev); 2242439e4bfSJean-Christophe PLAGNIOL-VILLARD static void purge_tx_ring (struct eth_device *dev); 2252439e4bfSJean-Christophe PLAGNIOL-VILLARD 2262439e4bfSJean-Christophe PLAGNIOL-VILLARD static void read_hw_addr (struct eth_device *dev, bd_t * bis); 2272439e4bfSJean-Christophe PLAGNIOL-VILLARD 2282439e4bfSJean-Christophe PLAGNIOL-VILLARD static int eepro100_init (struct eth_device *dev, bd_t * bis); 229bccbe619SJoe Hershberger static int eepro100_send(struct eth_device *dev, void *packet, int length); 2302439e4bfSJean-Christophe PLAGNIOL-VILLARD static int eepro100_recv (struct eth_device *dev); 2312439e4bfSJean-Christophe PLAGNIOL-VILLARD static void eepro100_halt (struct eth_device *dev); 2322439e4bfSJean-Christophe PLAGNIOL-VILLARD 233*03b00407SWolfgang Denk #if defined(CONFIG_E500) 2342439e4bfSJean-Christophe PLAGNIOL-VILLARD #define bus_to_phys(a) (a) 2352439e4bfSJean-Christophe PLAGNIOL-VILLARD #define phys_to_bus(a) (a) 2362439e4bfSJean-Christophe PLAGNIOL-VILLARD #else 2372439e4bfSJean-Christophe PLAGNIOL-VILLARD #define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) 2382439e4bfSJean-Christophe PLAGNIOL-VILLARD #define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) 2392439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 2402439e4bfSJean-Christophe PLAGNIOL-VILLARD 2412439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline int INW (struct eth_device *dev, u_long addr) 2422439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2432439e4bfSJean-Christophe PLAGNIOL-VILLARD return le16_to_cpu (*(volatile u16 *) (addr + dev->iobase)); 2442439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2452439e4bfSJean-Christophe PLAGNIOL-VILLARD 2462439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline void OUTW (struct eth_device *dev, int command, u_long addr) 2472439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2482439e4bfSJean-Christophe PLAGNIOL-VILLARD *(volatile u16 *) ((addr + dev->iobase)) = cpu_to_le16 (command); 2492439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2502439e4bfSJean-Christophe PLAGNIOL-VILLARD 2512439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline void OUTL (struct eth_device *dev, int command, u_long addr) 2522439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2532439e4bfSJean-Christophe PLAGNIOL-VILLARD *(volatile u32 *) ((addr + dev->iobase)) = cpu_to_le32 (command); 2542439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2552439e4bfSJean-Christophe PLAGNIOL-VILLARD 2562439e4bfSJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) 2572439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline int INL (struct eth_device *dev, u_long addr) 2582439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2592439e4bfSJean-Christophe PLAGNIOL-VILLARD return le32_to_cpu (*(volatile u32 *) (addr + dev->iobase)); 2602439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2612439e4bfSJean-Christophe PLAGNIOL-VILLARD 2622439e4bfSJean-Christophe PLAGNIOL-VILLARD static int get_phyreg (struct eth_device *dev, unsigned char addr, 2632439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char reg, unsigned short *value) 2642439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2652439e4bfSJean-Christophe PLAGNIOL-VILLARD int cmd; 2662439e4bfSJean-Christophe PLAGNIOL-VILLARD int timeout = 50; 2672439e4bfSJean-Christophe PLAGNIOL-VILLARD 2682439e4bfSJean-Christophe PLAGNIOL-VILLARD /* read requested data */ 2692439e4bfSJean-Christophe PLAGNIOL-VILLARD cmd = (2 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); 2702439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, cmd, SCBCtrlMDI); 2712439e4bfSJean-Christophe PLAGNIOL-VILLARD 2722439e4bfSJean-Christophe PLAGNIOL-VILLARD do { 2732439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1000); 2742439e4bfSJean-Christophe PLAGNIOL-VILLARD cmd = INL (dev, SCBCtrlMDI); 2752439e4bfSJean-Christophe PLAGNIOL-VILLARD } while (!(cmd & (1 << 28)) && (--timeout)); 2762439e4bfSJean-Christophe PLAGNIOL-VILLARD 2772439e4bfSJean-Christophe PLAGNIOL-VILLARD if (timeout == 0) 2782439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 2792439e4bfSJean-Christophe PLAGNIOL-VILLARD 2802439e4bfSJean-Christophe PLAGNIOL-VILLARD *value = (unsigned short) (cmd & 0xffff); 2812439e4bfSJean-Christophe PLAGNIOL-VILLARD 2822439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 2832439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2842439e4bfSJean-Christophe PLAGNIOL-VILLARD 2852439e4bfSJean-Christophe PLAGNIOL-VILLARD static int set_phyreg (struct eth_device *dev, unsigned char addr, 2862439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char reg, unsigned short value) 2872439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2882439e4bfSJean-Christophe PLAGNIOL-VILLARD int cmd; 2892439e4bfSJean-Christophe PLAGNIOL-VILLARD int timeout = 50; 2902439e4bfSJean-Christophe PLAGNIOL-VILLARD 2912439e4bfSJean-Christophe PLAGNIOL-VILLARD /* write requested data */ 2922439e4bfSJean-Christophe PLAGNIOL-VILLARD cmd = (1 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); 2932439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, cmd | value, SCBCtrlMDI); 2942439e4bfSJean-Christophe PLAGNIOL-VILLARD 2952439e4bfSJean-Christophe PLAGNIOL-VILLARD while (!(INL (dev, SCBCtrlMDI) & (1 << 28)) && (--timeout)) 2962439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1000); 2972439e4bfSJean-Christophe PLAGNIOL-VILLARD 2982439e4bfSJean-Christophe PLAGNIOL-VILLARD if (timeout == 0) 2992439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 3002439e4bfSJean-Christophe PLAGNIOL-VILLARD 3012439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 3022439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3032439e4bfSJean-Christophe PLAGNIOL-VILLARD 3042439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Check if given phyaddr is valid, i.e. there is a PHY connected. 3052439e4bfSJean-Christophe PLAGNIOL-VILLARD * Do this by checking model value field from ID2 register. 3062439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 307d7fb9bcfSBen Warren static struct eth_device* verify_phyaddr (const char *devname, 308d7fb9bcfSBen Warren unsigned char addr) 3092439e4bfSJean-Christophe PLAGNIOL-VILLARD { 3102439e4bfSJean-Christophe PLAGNIOL-VILLARD struct eth_device *dev; 3112439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned short value; 3122439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char model; 3132439e4bfSJean-Christophe PLAGNIOL-VILLARD 3142439e4bfSJean-Christophe PLAGNIOL-VILLARD dev = eth_get_dev_by_name(devname); 3152439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dev == NULL) { 3162439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: no such device\n", devname); 3172439e4bfSJean-Christophe PLAGNIOL-VILLARD return NULL; 3182439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3192439e4bfSJean-Christophe PLAGNIOL-VILLARD 3202439e4bfSJean-Christophe PLAGNIOL-VILLARD /* read id2 register */ 3218ef583a0SMike Frysinger if (get_phyreg(dev, addr, MII_PHYSID2, &value) != 0) { 3222439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: mii read timeout!\n", devname); 3232439e4bfSJean-Christophe PLAGNIOL-VILLARD return NULL; 3242439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3252439e4bfSJean-Christophe PLAGNIOL-VILLARD 3262439e4bfSJean-Christophe PLAGNIOL-VILLARD /* get model */ 3272439e4bfSJean-Christophe PLAGNIOL-VILLARD model = (unsigned char)((value >> 4) & 0x003f); 3282439e4bfSJean-Christophe PLAGNIOL-VILLARD 3292439e4bfSJean-Christophe PLAGNIOL-VILLARD if (model == 0) { 3302439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: no PHY at address %d\n", devname, addr); 3312439e4bfSJean-Christophe PLAGNIOL-VILLARD return NULL; 3322439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3332439e4bfSJean-Christophe PLAGNIOL-VILLARD 3342439e4bfSJean-Christophe PLAGNIOL-VILLARD return dev; 3352439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3362439e4bfSJean-Christophe PLAGNIOL-VILLARD 3375700bb63SMike Frysinger static int eepro100_miiphy_read(const char *devname, unsigned char addr, 3382439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char reg, unsigned short *value) 3392439e4bfSJean-Christophe PLAGNIOL-VILLARD { 3402439e4bfSJean-Christophe PLAGNIOL-VILLARD struct eth_device *dev; 3412439e4bfSJean-Christophe PLAGNIOL-VILLARD 3422439e4bfSJean-Christophe PLAGNIOL-VILLARD dev = verify_phyaddr(devname, addr); 3432439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dev == NULL) 3442439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 3452439e4bfSJean-Christophe PLAGNIOL-VILLARD 3462439e4bfSJean-Christophe PLAGNIOL-VILLARD if (get_phyreg(dev, addr, reg, value) != 0) { 3472439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: mii read timeout!\n", devname); 3482439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 3492439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3502439e4bfSJean-Christophe PLAGNIOL-VILLARD 3512439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 3522439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3532439e4bfSJean-Christophe PLAGNIOL-VILLARD 3545700bb63SMike Frysinger static int eepro100_miiphy_write(const char *devname, unsigned char addr, 3552439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char reg, unsigned short value) 3562439e4bfSJean-Christophe PLAGNIOL-VILLARD { 3572439e4bfSJean-Christophe PLAGNIOL-VILLARD struct eth_device *dev; 3582439e4bfSJean-Christophe PLAGNIOL-VILLARD 3592439e4bfSJean-Christophe PLAGNIOL-VILLARD dev = verify_phyaddr(devname, addr); 3602439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dev == NULL) 3612439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 3622439e4bfSJean-Christophe PLAGNIOL-VILLARD 3632439e4bfSJean-Christophe PLAGNIOL-VILLARD if (set_phyreg(dev, addr, reg, value) != 0) { 3642439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("%s: mii write timeout!\n", devname); 3652439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 3662439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3672439e4bfSJean-Christophe PLAGNIOL-VILLARD 3682439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 3692439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3702439e4bfSJean-Christophe PLAGNIOL-VILLARD 3712439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 3722439e4bfSJean-Christophe PLAGNIOL-VILLARD 3732439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Wait for the chip get the command. 3742439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 3752439e4bfSJean-Christophe PLAGNIOL-VILLARD static int wait_for_eepro100 (struct eth_device *dev) 3762439e4bfSJean-Christophe PLAGNIOL-VILLARD { 3772439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 3782439e4bfSJean-Christophe PLAGNIOL-VILLARD 3792439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; INW (dev, SCBCmd) & (CU_CMD_MASK | RU_CMD_MASK); i++) { 3802439e4bfSJean-Christophe PLAGNIOL-VILLARD if (i >= TOUT_LOOP) { 3812439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 3822439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3832439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3842439e4bfSJean-Christophe PLAGNIOL-VILLARD 3852439e4bfSJean-Christophe PLAGNIOL-VILLARD return 1; 3862439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3872439e4bfSJean-Christophe PLAGNIOL-VILLARD 3882439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct pci_device_id supported[] = { 3892439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557}, 3902439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559}, 3912439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER}, 3922439e4bfSJean-Christophe PLAGNIOL-VILLARD {} 3932439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 3942439e4bfSJean-Christophe PLAGNIOL-VILLARD 3952439e4bfSJean-Christophe PLAGNIOL-VILLARD int eepro100_initialize (bd_t * bis) 3962439e4bfSJean-Christophe PLAGNIOL-VILLARD { 3972439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_dev_t devno; 3982439e4bfSJean-Christophe PLAGNIOL-VILLARD int card_number = 0; 3992439e4bfSJean-Christophe PLAGNIOL-VILLARD struct eth_device *dev; 4002439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 iobase, status; 4012439e4bfSJean-Christophe PLAGNIOL-VILLARD int idx = 0; 4022439e4bfSJean-Christophe PLAGNIOL-VILLARD 4032439e4bfSJean-Christophe PLAGNIOL-VILLARD while (1) { 4042439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Find PCI device 4052439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 4062439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((devno = pci_find_devices (supported, idx++)) < 0) { 4072439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 4082439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4092439e4bfSJean-Christophe PLAGNIOL-VILLARD 4102439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_read_config_dword (devno, PCI_BASE_ADDRESS_0, &iobase); 4112439e4bfSJean-Christophe PLAGNIOL-VILLARD iobase &= ~0xf; 4122439e4bfSJean-Christophe PLAGNIOL-VILLARD 4132439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 4142439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("eepro100: Intel i82559 PCI EtherExpressPro @0x%x\n", 4152439e4bfSJean-Christophe PLAGNIOL-VILLARD iobase); 4162439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 4172439e4bfSJean-Christophe PLAGNIOL-VILLARD 4182439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_write_config_dword (devno, 4192439e4bfSJean-Christophe PLAGNIOL-VILLARD PCI_COMMAND, 4202439e4bfSJean-Christophe PLAGNIOL-VILLARD PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); 4212439e4bfSJean-Christophe PLAGNIOL-VILLARD 4222439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Check if I/O accesses and Bus Mastering are enabled. 4232439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 4242439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_read_config_dword (devno, PCI_COMMAND, &status); 4252439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(status & PCI_COMMAND_MEMORY)) { 4262439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not enable MEM access.\n"); 4272439e4bfSJean-Christophe PLAGNIOL-VILLARD continue; 4282439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4292439e4bfSJean-Christophe PLAGNIOL-VILLARD 4302439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(status & PCI_COMMAND_MASTER)) { 4312439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not enable Bus Mastering.\n"); 4322439e4bfSJean-Christophe PLAGNIOL-VILLARD continue; 4332439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4342439e4bfSJean-Christophe PLAGNIOL-VILLARD 4352439e4bfSJean-Christophe PLAGNIOL-VILLARD dev = (struct eth_device *) malloc (sizeof *dev); 43672c4c33eSNobuhiro Iwamatsu if (!dev) { 43772c4c33eSNobuhiro Iwamatsu printf("eepro100: Can not allocate memory\n"); 43872c4c33eSNobuhiro Iwamatsu break; 43972c4c33eSNobuhiro Iwamatsu } 44072c4c33eSNobuhiro Iwamatsu memset(dev, 0, sizeof(*dev)); 4412439e4bfSJean-Christophe PLAGNIOL-VILLARD 4422439e4bfSJean-Christophe PLAGNIOL-VILLARD sprintf (dev->name, "i82559#%d", card_number); 4432439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->priv = (void *) devno; /* this have to come before bus_to_phys() */ 4442439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->iobase = bus_to_phys (iobase); 4452439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->init = eepro100_init; 4462439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->halt = eepro100_halt; 4472439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->send = eepro100_send; 4482439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->recv = eepro100_recv; 4492439e4bfSJean-Christophe PLAGNIOL-VILLARD 4502439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_register (dev); 4512439e4bfSJean-Christophe PLAGNIOL-VILLARD 4522439e4bfSJean-Christophe PLAGNIOL-VILLARD #if defined (CONFIG_MII) || defined(CONFIG_CMD_MII) 4532439e4bfSJean-Christophe PLAGNIOL-VILLARD /* register mii command access routines */ 4542439e4bfSJean-Christophe PLAGNIOL-VILLARD miiphy_register(dev->name, 4552439e4bfSJean-Christophe PLAGNIOL-VILLARD eepro100_miiphy_read, eepro100_miiphy_write); 4562439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 4572439e4bfSJean-Christophe PLAGNIOL-VILLARD 4582439e4bfSJean-Christophe PLAGNIOL-VILLARD card_number++; 4592439e4bfSJean-Christophe PLAGNIOL-VILLARD 4602439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set the latency timer for value. 4612439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 4622439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_write_config_byte (devno, PCI_LATENCY_TIMER, 0x20); 4632439e4bfSJean-Christophe PLAGNIOL-VILLARD 4642439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (10 * 1000); 4652439e4bfSJean-Christophe PLAGNIOL-VILLARD 4662439e4bfSJean-Christophe PLAGNIOL-VILLARD read_hw_addr (dev, bis); 4672439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4682439e4bfSJean-Christophe PLAGNIOL-VILLARD 4692439e4bfSJean-Christophe PLAGNIOL-VILLARD return card_number; 4702439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4712439e4bfSJean-Christophe PLAGNIOL-VILLARD 4722439e4bfSJean-Christophe PLAGNIOL-VILLARD 4732439e4bfSJean-Christophe PLAGNIOL-VILLARD static int eepro100_init (struct eth_device *dev, bd_t * bis) 4742439e4bfSJean-Christophe PLAGNIOL-VILLARD { 475422b1a01SBen Warren int i, status = -1; 4762439e4bfSJean-Christophe PLAGNIOL-VILLARD int tx_cur; 4772439e4bfSJean-Christophe PLAGNIOL-VILLARD struct descriptor *ias_cmd, *cfg_cmd; 4782439e4bfSJean-Christophe PLAGNIOL-VILLARD 4792439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Reset the ethernet controller 4802439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 4812439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, I82559_SELECTIVE_RESET, SCBPort); 4822439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (20); 4832439e4bfSJean-Christophe PLAGNIOL-VILLARD 4842439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, I82559_RESET, SCBPort); 4852439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (20); 4862439e4bfSJean-Christophe PLAGNIOL-VILLARD 4872439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 4882439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not reset ethernet controller.\n"); 4892439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 4902439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4912439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, 0, SCBPointer); 4922439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | RUC_ADDR_LOAD, SCBCmd); 4932439e4bfSJean-Christophe PLAGNIOL-VILLARD 4942439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 4952439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not reset ethernet controller.\n"); 4962439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 4972439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4982439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, 0, SCBPointer); 4992439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | CU_ADDR_LOAD, SCBCmd); 5002439e4bfSJean-Christophe PLAGNIOL-VILLARD 5012439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Initialize Rx and Tx rings. 5022439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 5032439e4bfSJean-Christophe PLAGNIOL-VILLARD init_rx_ring (dev); 5042439e4bfSJean-Christophe PLAGNIOL-VILLARD purge_tx_ring (dev); 5052439e4bfSJean-Christophe PLAGNIOL-VILLARD 5062439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Tell the adapter where the RX ring is located. 5072439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 5082439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 5092439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not reset ethernet controller.\n"); 5102439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 5112439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5122439e4bfSJean-Christophe PLAGNIOL-VILLARD 5132439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, phys_to_bus ((u32) & rx_ring[rx_next]), SCBPointer); 5142439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | RUC_START, SCBCmd); 5152439e4bfSJean-Christophe PLAGNIOL-VILLARD 5162439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Send the Configure frame */ 5172439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_cur = tx_next; 5182439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_next = ((tx_next + 1) % NUM_TX_DESC); 5192439e4bfSJean-Christophe PLAGNIOL-VILLARD 5202439e4bfSJean-Christophe PLAGNIOL-VILLARD cfg_cmd = (struct descriptor *) &tx_ring[tx_cur]; 5216d0f6bcfSJean-Christophe PLAGNIOL-VILLARD cfg_cmd->command = cpu_to_le16 ((CONFIG_SYS_CMD_SUSPEND | CONFIG_SYS_CMD_CONFIGURE)); 5222439e4bfSJean-Christophe PLAGNIOL-VILLARD cfg_cmd->status = 0; 5232439e4bfSJean-Christophe PLAGNIOL-VILLARD cfg_cmd->link = cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_next])); 5242439e4bfSJean-Christophe PLAGNIOL-VILLARD 5252439e4bfSJean-Christophe PLAGNIOL-VILLARD memcpy (cfg_cmd->params, i82558_config_cmd, 5262439e4bfSJean-Christophe PLAGNIOL-VILLARD sizeof (i82558_config_cmd)); 5272439e4bfSJean-Christophe PLAGNIOL-VILLARD 5282439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 5296d0f6bcfSJean-Christophe PLAGNIOL-VILLARD printf ("Error---CONFIG_SYS_CMD_CONFIGURE: Can not reset ethernet controller.\n"); 5302439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 5312439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5322439e4bfSJean-Christophe PLAGNIOL-VILLARD 5332439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, phys_to_bus ((u32) & tx_ring[tx_cur]), SCBPointer); 5342439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | CU_START, SCBCmd); 5352439e4bfSJean-Christophe PLAGNIOL-VILLARD 5362439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; 5376d0f6bcfSJean-Christophe PLAGNIOL-VILLARD !(le16_to_cpu (tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); 5382439e4bfSJean-Christophe PLAGNIOL-VILLARD i++) { 5392439e4bfSJean-Christophe PLAGNIOL-VILLARD if (i >= TOUT_LOOP) { 5402439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("%s: Tx error buffer not ready\n", dev->name); 5412439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 5422439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5432439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5442439e4bfSJean-Christophe PLAGNIOL-VILLARD 5456d0f6bcfSJean-Christophe PLAGNIOL-VILLARD if (!(le16_to_cpu (tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { 5462439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("TX error status = 0x%08X\n", 5472439e4bfSJean-Christophe PLAGNIOL-VILLARD le16_to_cpu (tx_ring[tx_cur].status)); 5482439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 5492439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5502439e4bfSJean-Christophe PLAGNIOL-VILLARD 5512439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Send the Individual Address Setup frame 5522439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 5532439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_cur = tx_next; 5542439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_next = ((tx_next + 1) % NUM_TX_DESC); 5552439e4bfSJean-Christophe PLAGNIOL-VILLARD 5562439e4bfSJean-Christophe PLAGNIOL-VILLARD ias_cmd = (struct descriptor *) &tx_ring[tx_cur]; 5576d0f6bcfSJean-Christophe PLAGNIOL-VILLARD ias_cmd->command = cpu_to_le16 ((CONFIG_SYS_CMD_SUSPEND | CONFIG_SYS_CMD_IAS)); 5582439e4bfSJean-Christophe PLAGNIOL-VILLARD ias_cmd->status = 0; 5592439e4bfSJean-Christophe PLAGNIOL-VILLARD ias_cmd->link = cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_next])); 5602439e4bfSJean-Christophe PLAGNIOL-VILLARD 5612439e4bfSJean-Christophe PLAGNIOL-VILLARD memcpy (ias_cmd->params, dev->enetaddr, 6); 5622439e4bfSJean-Christophe PLAGNIOL-VILLARD 5632439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Tell the adapter where the TX ring is located. 5642439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 5652439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 5662439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not reset ethernet controller.\n"); 5672439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 5682439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5692439e4bfSJean-Christophe PLAGNIOL-VILLARD 5702439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, phys_to_bus ((u32) & tx_ring[tx_cur]), SCBPointer); 5712439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | CU_START, SCBCmd); 5722439e4bfSJean-Christophe PLAGNIOL-VILLARD 5736d0f6bcfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; !(le16_to_cpu (tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); 5742439e4bfSJean-Christophe PLAGNIOL-VILLARD i++) { 5752439e4bfSJean-Christophe PLAGNIOL-VILLARD if (i >= TOUT_LOOP) { 5762439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("%s: Tx error buffer not ready\n", 5772439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->name); 5782439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 5792439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5802439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5812439e4bfSJean-Christophe PLAGNIOL-VILLARD 5826d0f6bcfSJean-Christophe PLAGNIOL-VILLARD if (!(le16_to_cpu (tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { 5832439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("TX error status = 0x%08X\n", 5842439e4bfSJean-Christophe PLAGNIOL-VILLARD le16_to_cpu (tx_ring[tx_cur].status)); 5852439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 5862439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5872439e4bfSJean-Christophe PLAGNIOL-VILLARD 588422b1a01SBen Warren status = 0; 5892439e4bfSJean-Christophe PLAGNIOL-VILLARD 5902439e4bfSJean-Christophe PLAGNIOL-VILLARD Done: 5912439e4bfSJean-Christophe PLAGNIOL-VILLARD return status; 5922439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5932439e4bfSJean-Christophe PLAGNIOL-VILLARD 594bccbe619SJoe Hershberger static int eepro100_send(struct eth_device *dev, void *packet, int length) 5952439e4bfSJean-Christophe PLAGNIOL-VILLARD { 5962439e4bfSJean-Christophe PLAGNIOL-VILLARD int i, status = -1; 5972439e4bfSJean-Christophe PLAGNIOL-VILLARD int tx_cur; 5982439e4bfSJean-Christophe PLAGNIOL-VILLARD 5992439e4bfSJean-Christophe PLAGNIOL-VILLARD if (length <= 0) { 6002439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("%s: bad packet size: %d\n", dev->name, length); 6012439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 6022439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6032439e4bfSJean-Christophe PLAGNIOL-VILLARD 6042439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_cur = tx_next; 6052439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_next = (tx_next + 1) % NUM_TX_DESC; 6062439e4bfSJean-Christophe PLAGNIOL-VILLARD 6072439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[tx_cur].command = cpu_to_le16 ( TxCB_CMD_TRANSMIT | 6082439e4bfSJean-Christophe PLAGNIOL-VILLARD TxCB_CMD_SF | 6092439e4bfSJean-Christophe PLAGNIOL-VILLARD TxCB_CMD_S | 6102439e4bfSJean-Christophe PLAGNIOL-VILLARD TxCB_CMD_EL ); 6112439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[tx_cur].status = 0; 6122439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[tx_cur].count = cpu_to_le32 (tx_threshold); 6132439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[tx_cur].link = 6142439e4bfSJean-Christophe PLAGNIOL-VILLARD cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_next])); 6152439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[tx_cur].tx_desc_addr = 6162439e4bfSJean-Christophe PLAGNIOL-VILLARD cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_cur].tx_buf_addr0)); 6172439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[tx_cur].tx_buf_addr0 = 6182439e4bfSJean-Christophe PLAGNIOL-VILLARD cpu_to_le32 (phys_to_bus ((u_long) packet)); 6192439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[tx_cur].tx_buf_size0 = cpu_to_le32 (length); 6202439e4bfSJean-Christophe PLAGNIOL-VILLARD 6212439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 6222439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("%s: Tx error ethernet controller not ready.\n", 6232439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->name); 6242439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 6252439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6262439e4bfSJean-Christophe PLAGNIOL-VILLARD 6272439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Send the packet. 6282439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 6292439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, phys_to_bus ((u32) & tx_ring[tx_cur]), SCBPointer); 6302439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | CU_START, SCBCmd); 6312439e4bfSJean-Christophe PLAGNIOL-VILLARD 6326d0f6bcfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; !(le16_to_cpu (tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_C); 6332439e4bfSJean-Christophe PLAGNIOL-VILLARD i++) { 6342439e4bfSJean-Christophe PLAGNIOL-VILLARD if (i >= TOUT_LOOP) { 6352439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("%s: Tx error buffer not ready\n", dev->name); 6362439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 6372439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6382439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6392439e4bfSJean-Christophe PLAGNIOL-VILLARD 6406d0f6bcfSJean-Christophe PLAGNIOL-VILLARD if (!(le16_to_cpu (tx_ring[tx_cur].status) & CONFIG_SYS_STATUS_OK)) { 6412439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("TX error status = 0x%08X\n", 6422439e4bfSJean-Christophe PLAGNIOL-VILLARD le16_to_cpu (tx_ring[tx_cur].status)); 6432439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 6442439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6452439e4bfSJean-Christophe PLAGNIOL-VILLARD 6462439e4bfSJean-Christophe PLAGNIOL-VILLARD status = length; 6472439e4bfSJean-Christophe PLAGNIOL-VILLARD 6482439e4bfSJean-Christophe PLAGNIOL-VILLARD Done: 6492439e4bfSJean-Christophe PLAGNIOL-VILLARD return status; 6502439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6512439e4bfSJean-Christophe PLAGNIOL-VILLARD 6522439e4bfSJean-Christophe PLAGNIOL-VILLARD static int eepro100_recv (struct eth_device *dev) 6532439e4bfSJean-Christophe PLAGNIOL-VILLARD { 6542439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 status, stat; 6552439e4bfSJean-Christophe PLAGNIOL-VILLARD int rx_prev, length = 0; 6562439e4bfSJean-Christophe PLAGNIOL-VILLARD 6572439e4bfSJean-Christophe PLAGNIOL-VILLARD stat = INW (dev, SCBStatus); 6582439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, stat & SCB_STATUS_RNR, SCBStatus); 6592439e4bfSJean-Christophe PLAGNIOL-VILLARD 6602439e4bfSJean-Christophe PLAGNIOL-VILLARD for (;;) { 6612439e4bfSJean-Christophe PLAGNIOL-VILLARD status = le16_to_cpu (rx_ring[rx_next].status); 6622439e4bfSJean-Christophe PLAGNIOL-VILLARD 6632439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(status & RFD_STATUS_C)) { 6642439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 6652439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6662439e4bfSJean-Christophe PLAGNIOL-VILLARD 6672439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Valid frame status. 6682439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 6692439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((status & RFD_STATUS_OK)) { 6702439e4bfSJean-Christophe PLAGNIOL-VILLARD /* A valid frame received. 6712439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 6722439e4bfSJean-Christophe PLAGNIOL-VILLARD length = le32_to_cpu (rx_ring[rx_next].count) & 0x3fff; 6732439e4bfSJean-Christophe PLAGNIOL-VILLARD 6742439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Pass the packet up to the protocol 6752439e4bfSJean-Christophe PLAGNIOL-VILLARD * layers. 6762439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 677bccbe619SJoe Hershberger NetReceive((u8 *)rx_ring[rx_next].data, length); 6782439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 6792439e4bfSJean-Christophe PLAGNIOL-VILLARD /* There was an error. 6802439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 6812439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("RX error status = 0x%08X\n", status); 6822439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6832439e4bfSJean-Christophe PLAGNIOL-VILLARD 6842439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[rx_next].control = cpu_to_le16 (RFD_CONTROL_S); 6852439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[rx_next].status = 0; 6862439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[rx_next].count = cpu_to_le32 (PKTSIZE_ALIGN << 16); 6872439e4bfSJean-Christophe PLAGNIOL-VILLARD 6882439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_prev = (rx_next + NUM_RX_DESC - 1) % NUM_RX_DESC; 6892439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[rx_prev].control = 0; 6902439e4bfSJean-Christophe PLAGNIOL-VILLARD 6912439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Update entry information. 6922439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 6932439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_next = (rx_next + 1) % NUM_RX_DESC; 6942439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6952439e4bfSJean-Christophe PLAGNIOL-VILLARD 6962439e4bfSJean-Christophe PLAGNIOL-VILLARD if (stat & SCB_STATUS_RNR) { 6972439e4bfSJean-Christophe PLAGNIOL-VILLARD 6982439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("%s: Receiver is not ready, restart it !\n", dev->name); 6992439e4bfSJean-Christophe PLAGNIOL-VILLARD 7002439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Reinitialize Rx ring. 7012439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 7022439e4bfSJean-Christophe PLAGNIOL-VILLARD init_rx_ring (dev); 7032439e4bfSJean-Christophe PLAGNIOL-VILLARD 7042439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 7052439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not restart ethernet controller.\n"); 7062439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 7072439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7082439e4bfSJean-Christophe PLAGNIOL-VILLARD 7092439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, phys_to_bus ((u32) & rx_ring[rx_next]), SCBPointer); 7102439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | RUC_START, SCBCmd); 7112439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7122439e4bfSJean-Christophe PLAGNIOL-VILLARD 7132439e4bfSJean-Christophe PLAGNIOL-VILLARD Done: 7142439e4bfSJean-Christophe PLAGNIOL-VILLARD return length; 7152439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7162439e4bfSJean-Christophe PLAGNIOL-VILLARD 7172439e4bfSJean-Christophe PLAGNIOL-VILLARD static void eepro100_halt (struct eth_device *dev) 7182439e4bfSJean-Christophe PLAGNIOL-VILLARD { 7192439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Reset the ethernet controller 7202439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 7212439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, I82559_SELECTIVE_RESET, SCBPort); 7222439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (20); 7232439e4bfSJean-Christophe PLAGNIOL-VILLARD 7242439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, I82559_RESET, SCBPort); 7252439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (20); 7262439e4bfSJean-Christophe PLAGNIOL-VILLARD 7272439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 7282439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not reset ethernet controller.\n"); 7292439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 7302439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7312439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, 0, SCBPointer); 7322439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | RUC_ADDR_LOAD, SCBCmd); 7332439e4bfSJean-Christophe PLAGNIOL-VILLARD 7342439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!wait_for_eepro100 (dev)) { 7352439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Error: Can not reset ethernet controller.\n"); 7362439e4bfSJean-Christophe PLAGNIOL-VILLARD goto Done; 7372439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7382439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTL (dev, 0, SCBPointer); 7392439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, SCB_M | CU_ADDR_LOAD, SCBCmd); 7402439e4bfSJean-Christophe PLAGNIOL-VILLARD 7412439e4bfSJean-Christophe PLAGNIOL-VILLARD Done: 7422439e4bfSJean-Christophe PLAGNIOL-VILLARD return; 7432439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7442439e4bfSJean-Christophe PLAGNIOL-VILLARD 7452439e4bfSJean-Christophe PLAGNIOL-VILLARD /* SROM Read. 7462439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 7472439e4bfSJean-Christophe PLAGNIOL-VILLARD static int read_eeprom (struct eth_device *dev, int location, int addr_len) 7482439e4bfSJean-Christophe PLAGNIOL-VILLARD { 7492439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned short retval = 0; 7502439e4bfSJean-Christophe PLAGNIOL-VILLARD int read_cmd = location | EE_READ_CMD; 7512439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 7522439e4bfSJean-Christophe PLAGNIOL-VILLARD 7532439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, EE_ENB & ~EE_CS, SCBeeprom); 7542439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, EE_ENB, SCBeeprom); 7552439e4bfSJean-Christophe PLAGNIOL-VILLARD 7562439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Shift the read command bits out. */ 7572439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 12; i >= 0; i--) { 7582439e4bfSJean-Christophe PLAGNIOL-VILLARD short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; 7592439e4bfSJean-Christophe PLAGNIOL-VILLARD 7602439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, EE_ENB | dataval, SCBeeprom); 7612439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (1); 7622439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); 7632439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (1); 7642439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7652439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, EE_ENB, SCBeeprom); 7662439e4bfSJean-Christophe PLAGNIOL-VILLARD 7672439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 15; i >= 0; i--) { 7682439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, EE_ENB | EE_SHIFT_CLK, SCBeeprom); 7692439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (1); 7702439e4bfSJean-Christophe PLAGNIOL-VILLARD retval = (retval << 1) | 7712439e4bfSJean-Christophe PLAGNIOL-VILLARD ((INW (dev, SCBeeprom) & EE_DATA_READ) ? 1 : 0); 7722439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, EE_ENB, SCBeeprom); 7732439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (1); 7742439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7752439e4bfSJean-Christophe PLAGNIOL-VILLARD 7762439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Terminate the EEPROM access. */ 7772439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW (dev, EE_ENB & ~EE_CS, SCBeeprom); 7782439e4bfSJean-Christophe PLAGNIOL-VILLARD return retval; 7792439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7802439e4bfSJean-Christophe PLAGNIOL-VILLARD 7812439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_EEPRO100_SROM_WRITE 7822439e4bfSJean-Christophe PLAGNIOL-VILLARD int eepro100_write_eeprom (struct eth_device* dev, int location, int addr_len, unsigned short data) 7832439e4bfSJean-Christophe PLAGNIOL-VILLARD { 7842439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned short dataval; 7852439e4bfSJean-Christophe PLAGNIOL-VILLARD int enable_cmd = 0x3f | EE_EWENB_CMD; 7862439e4bfSJean-Christophe PLAGNIOL-VILLARD int write_cmd = location | EE_WRITE_CMD; 7872439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 7882439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long datalong, tmplong; 7892439e4bfSJean-Christophe PLAGNIOL-VILLARD 7902439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); 7912439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 7922439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB, SCBeeprom); 7932439e4bfSJean-Christophe PLAGNIOL-VILLARD 7942439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Shift the enable command bits out. */ 7952439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = (addr_len+EE_CMD_BITS-1); i >= 0; i--) 7962439e4bfSJean-Christophe PLAGNIOL-VILLARD { 7972439e4bfSJean-Christophe PLAGNIOL-VILLARD dataval = (enable_cmd & (1 << i)) ? EE_DATA_WRITE : 0; 7982439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB | dataval, SCBeeprom); 7992439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 8002439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); 8012439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 8022439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8032439e4bfSJean-Christophe PLAGNIOL-VILLARD 8042439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB, SCBeeprom); 8052439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 8062439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); 8072439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 8082439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB, SCBeeprom); 8092439e4bfSJean-Christophe PLAGNIOL-VILLARD 8102439e4bfSJean-Christophe PLAGNIOL-VILLARD 8112439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Shift the write command bits out. */ 8122439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = (addr_len+EE_CMD_BITS-1); i >= 0; i--) 8132439e4bfSJean-Christophe PLAGNIOL-VILLARD { 8142439e4bfSJean-Christophe PLAGNIOL-VILLARD dataval = (write_cmd & (1 << i)) ? EE_DATA_WRITE : 0; 8152439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB | dataval, SCBeeprom); 8162439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 8172439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); 8182439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 8192439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8202439e4bfSJean-Christophe PLAGNIOL-VILLARD 8212439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Write the data */ 8222439e4bfSJean-Christophe PLAGNIOL-VILLARD datalong= (unsigned long) ((((data) & 0x00ff) << 8) | ( (data) >> 8)); 8232439e4bfSJean-Christophe PLAGNIOL-VILLARD 8242439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i< EE_DATA_BITS; i++) 8252439e4bfSJean-Christophe PLAGNIOL-VILLARD { 8262439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Extract and move data bit to bit DI */ 8272439e4bfSJean-Christophe PLAGNIOL-VILLARD dataval = ((datalong & 0x8000)>>13) ? EE_DATA_WRITE : 0; 8282439e4bfSJean-Christophe PLAGNIOL-VILLARD 8292439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB | dataval, SCBeeprom); 8302439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 8312439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); 8322439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 8332439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB | dataval, SCBeeprom); 8342439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 8352439e4bfSJean-Christophe PLAGNIOL-VILLARD 8362439e4bfSJean-Christophe PLAGNIOL-VILLARD datalong = datalong << 1; /* Adjust significant data bit*/ 8372439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8382439e4bfSJean-Christophe PLAGNIOL-VILLARD 8392439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Finish up command (toggle CS) */ 8402439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); 8412439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); /* delay for more than 250 ns */ 8422439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB, SCBeeprom); 8432439e4bfSJean-Christophe PLAGNIOL-VILLARD 8442439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Wait for programming ready (D0 = 1) */ 8452439e4bfSJean-Christophe PLAGNIOL-VILLARD tmplong = 10; 8462439e4bfSJean-Christophe PLAGNIOL-VILLARD do 8472439e4bfSJean-Christophe PLAGNIOL-VILLARD { 8482439e4bfSJean-Christophe PLAGNIOL-VILLARD dataval = INW(dev, SCBeeprom); 8492439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dataval & EE_DATA_READ) 8502439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 8512439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(10000); 8522439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8532439e4bfSJean-Christophe PLAGNIOL-VILLARD while (-- tmplong); 8542439e4bfSJean-Christophe PLAGNIOL-VILLARD 8552439e4bfSJean-Christophe PLAGNIOL-VILLARD if (tmplong == 0) 8562439e4bfSJean-Christophe PLAGNIOL-VILLARD { 8572439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("Write i82559 eeprom timed out (100 ms waiting for data ready.\n"); 8582439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 8592439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8602439e4bfSJean-Christophe PLAGNIOL-VILLARD 8612439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Terminate the EEPROM access. */ 8622439e4bfSJean-Christophe PLAGNIOL-VILLARD OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); 8632439e4bfSJean-Christophe PLAGNIOL-VILLARD 8642439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 8652439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8662439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 8672439e4bfSJean-Christophe PLAGNIOL-VILLARD 8682439e4bfSJean-Christophe PLAGNIOL-VILLARD static void init_rx_ring (struct eth_device *dev) 8692439e4bfSJean-Christophe PLAGNIOL-VILLARD { 8702439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 8712439e4bfSJean-Christophe PLAGNIOL-VILLARD 8722439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < NUM_RX_DESC; i++) { 8732439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[i].status = 0; 8742439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[i].control = 8752439e4bfSJean-Christophe PLAGNIOL-VILLARD (i == NUM_RX_DESC - 1) ? cpu_to_le16 (RFD_CONTROL_S) : 0; 8762439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[i].link = 8772439e4bfSJean-Christophe PLAGNIOL-VILLARD cpu_to_le32 (phys_to_bus 8782439e4bfSJean-Christophe PLAGNIOL-VILLARD ((u32) & rx_ring[(i + 1) % NUM_RX_DESC])); 8792439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[i].rx_buf_addr = 0xffffffff; 8802439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_ring[i].count = cpu_to_le32 (PKTSIZE_ALIGN << 16); 8812439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8822439e4bfSJean-Christophe PLAGNIOL-VILLARD 8832439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_next = 0; 8842439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8852439e4bfSJean-Christophe PLAGNIOL-VILLARD 8862439e4bfSJean-Christophe PLAGNIOL-VILLARD static void purge_tx_ring (struct eth_device *dev) 8872439e4bfSJean-Christophe PLAGNIOL-VILLARD { 8882439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 8892439e4bfSJean-Christophe PLAGNIOL-VILLARD 8902439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_next = 0; 8912439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_threshold = 0x01208000; 8922439e4bfSJean-Christophe PLAGNIOL-VILLARD 8932439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < NUM_TX_DESC; i++) { 8942439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].status = 0; 8952439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].command = 0; 8962439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].link = 0; 8972439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].tx_desc_addr = 0; 8982439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].count = 0; 8992439e4bfSJean-Christophe PLAGNIOL-VILLARD 9002439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].tx_buf_addr0 = 0; 9012439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].tx_buf_size0 = 0; 9022439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].tx_buf_addr1 = 0; 9032439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_ring[i].tx_buf_size1 = 0; 9042439e4bfSJean-Christophe PLAGNIOL-VILLARD } 9052439e4bfSJean-Christophe PLAGNIOL-VILLARD } 9062439e4bfSJean-Christophe PLAGNIOL-VILLARD 9072439e4bfSJean-Christophe PLAGNIOL-VILLARD static void read_hw_addr (struct eth_device *dev, bd_t * bis) 9082439e4bfSJean-Christophe PLAGNIOL-VILLARD { 9092439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 sum = 0; 9102439e4bfSJean-Christophe PLAGNIOL-VILLARD int i, j; 9112439e4bfSJean-Christophe PLAGNIOL-VILLARD int addr_len = read_eeprom (dev, 0, 6) == 0xffff ? 8 : 6; 9122439e4bfSJean-Christophe PLAGNIOL-VILLARD 9132439e4bfSJean-Christophe PLAGNIOL-VILLARD for (j = 0, i = 0; i < 0x40; i++) { 9142439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 value = read_eeprom (dev, i, addr_len); 9152439e4bfSJean-Christophe PLAGNIOL-VILLARD 9162439e4bfSJean-Christophe PLAGNIOL-VILLARD sum += value; 9172439e4bfSJean-Christophe PLAGNIOL-VILLARD if (i < 3) { 9182439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->enetaddr[j++] = value; 9192439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->enetaddr[j++] = value >> 8; 9202439e4bfSJean-Christophe PLAGNIOL-VILLARD } 9212439e4bfSJean-Christophe PLAGNIOL-VILLARD } 9222439e4bfSJean-Christophe PLAGNIOL-VILLARD 9232439e4bfSJean-Christophe PLAGNIOL-VILLARD if (sum != 0xBABA) { 9242439e4bfSJean-Christophe PLAGNIOL-VILLARD memset (dev->enetaddr, 0, ETH_ALEN); 9252439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 9262439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("%s: Invalid EEPROM checksum %#4.4x, " 9272439e4bfSJean-Christophe PLAGNIOL-VILLARD "check settings before activating this device!\n", 9282439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->name, sum); 9292439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 9302439e4bfSJean-Christophe PLAGNIOL-VILLARD } 9312439e4bfSJean-Christophe PLAGNIOL-VILLARD } 932