
Move the functions in the driver around to better fit future DM conversion, drop function forward declarations. No functional change.
Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Cc: Joe Hershberger joe.hershberger@ni.com --- drivers/net/dc2114x.c | 736 ++++++++++++++++++++---------------------- 1 file changed, 357 insertions(+), 379 deletions(-)
diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index 2bbe4e5d60..9de9634cd5 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -79,6 +79,30 @@ #define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) #endif
+#define NUM_RX_DESC PKTBUFSRX +#define NUM_TX_DESC 1 /* Number of TX descriptors */ +#define RX_BUFF_SZ PKTSIZE_ALIGN + +#define TOUT_LOOP 1000000 + +#define SETUP_FRAME_LEN 192 + +struct de4x5_desc { + volatile s32 status; + u32 des1; + u32 buf; + u32 next; +}; + +/* RX and TX descriptor ring */ +static struct de4x5_desc rx_ring[NUM_RX_DESC] __aligned(32); +static struct de4x5_desc tx_ring[NUM_TX_DESC] __aligned(32); +static int rx_new; /* RX descriptor ring pointer */ +static int tx_new; /* TX descriptor ring pointer */ + +static char rx_ring_size; +static char tx_ring_size; + static u32 dc2114x_inl(struct eth_device *dev, u32 addr) { return le32_to_cpu(*(volatile u32 *)(addr + dev->iobase)); @@ -126,191 +150,267 @@ static void stop_de4x5(struct eth_device *dev) dc2114x_outl(dev, omr, DE4X5_OMR); /* Disable the TX and/or RX */ }
-#define NUM_RX_DESC PKTBUFSRX -#define NUM_TX_DESC 1 /* Number of TX descriptors */ -#define RX_BUFF_SZ PKTSIZE_ALIGN - -#define TOUT_LOOP 1000000 +/* SROM Read and write routines. */ +static void sendto_srom(struct eth_device *dev, u_int command, u_long addr) +{ + dc2114x_outl(dev, command, addr); + udelay(1); +}
-#define SETUP_FRAME_LEN 192 +static int getfrom_srom(struct eth_device *dev, u_long addr) +{ + u32 tmp = dc2114x_inl(dev, addr);
-struct de4x5_desc { - volatile s32 status; - u32 des1; - u32 buf; - u32 next; -}; + udelay(1); + return tmp; +}
-/* RX and TX descriptor ring */ -static struct de4x5_desc rx_ring[NUM_RX_DESC] __aligned(32); -static struct de4x5_desc tx_ring[NUM_TX_DESC] __aligned(32); -static int rx_new; /* RX descriptor ring pointer */ -static int tx_new; /* TX descriptor ring pointer */ +/* Note: this routine returns extra data bits for size detection. */ +static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, + int addr_len) +{ + int read_cmd = location | (SROM_READ_CMD << addr_len); + unsigned int retval = 0; + int i;
-static char rx_ring_size; -static char tx_ring_size; + sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
-static void sendto_srom(struct eth_device *dev, u_int command, u_long addr); -static int getfrom_srom(struct eth_device *dev, u_long addr); -static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, - int cmd, int cmd_len); -static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, - int location, int addr_len); -#ifdef UPDATE_SROM -static int write_srom(struct eth_device *dev, u_long ioaddr, - int index, int new_value); -static void update_srom(struct eth_device *dev, bd_t *bis); +#ifdef DEBUG_SROM + printf(" EEPROM read at %d ", location); #endif -static int read_srom(struct eth_device *dev, u_long ioaddr, int index); -static void read_hw_addr(struct eth_device *dev, bd_t *bis); -static void send_setup_frame(struct eth_device *dev, bd_t *bis);
-static int dc21x4x_init(struct eth_device *dev, bd_t *bis); -static int dc21x4x_send(struct eth_device *dev, void *packet, int length); -static int dc21x4x_recv(struct eth_device *dev); -static void dc21x4x_halt(struct eth_device *dev); + /* Shift the read command bits out. */ + for (i = 4 + addr_len; i >= 0; i--) { + short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
-static struct pci_device_id supported[] = { - { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST }, - { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142 }, - { } -}; + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval, + ioaddr); + udelay(10); + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval | DT_CLK, + ioaddr); + udelay(10); +#ifdef DEBUG_SROM2 + printf("%X", getfrom_srom(dev, ioaddr) & 15); +#endif + retval = (retval << 1) | + !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ); + }
-int dc21x4x_initialize(bd_t *bis) -{ - struct eth_device *dev; - unsigned short status; - unsigned char timer; - unsigned int iobase; - int card_number = 0; - pci_dev_t devbusfn; - unsigned int cfrv; - int idx = 0; + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
- while (1) { - devbusfn = pci_find_devices(supported, idx++); - if (devbusfn == -1) - break; +#ifdef DEBUG_SROM2 + printf(" :%X:", getfrom_srom(dev, ioaddr) & 15); +#endif
- /* Get the chip configuration revision register. */ - pci_read_config_dword(devbusfn, PCI_REVISION_ID, &cfrv); + for (i = 16; i > 0; i--) { + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); + udelay(10); +#ifdef DEBUG_SROM2 + printf("%X", getfrom_srom(dev, ioaddr) & 15); +#endif + retval = (retval << 1) | + !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ); + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); + udelay(10); + }
- if ((cfrv & CFRV_RN) < DC2114x_BRK) { - printf("Error: The chip is not DC21143.\n"); - continue; - } + /* Terminate the EEPROM access. */ + sendto_srom(dev, SROM_RD | SROM_SR, ioaddr);
- pci_read_config_word(devbusfn, PCI_COMMAND, &status); - status |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - pci_write_config_word(devbusfn, PCI_COMMAND, status); +#ifdef DEBUG_SROM2 + printf(" EEPROM value at %d is %5.5x.\n", location, retval); +#endif
- pci_read_config_word(devbusfn, PCI_COMMAND, &status); - if (!(status & PCI_COMMAND_MEMORY)) { - printf("Error: Can not enable MEMORY access.\n"); - continue; - } + return retval; +}
- if (!(status & PCI_COMMAND_MASTER)) { - printf("Error: Can not enable Bus Mastering.\n"); - continue; - } +/* + * This executes a generic EEPROM command, typically a write or write + * enable. It returns the data output from the EEPROM, and thus may + * also be used for reads. + */ +static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, + int cmd_len) +{ + unsigned int retval = 0;
- /* Check the latency timer for values >= 0x60. */ - pci_read_config_byte(devbusfn, PCI_LATENCY_TIMER, &timer); +#ifdef DEBUG_SROM + printf(" EEPROM op 0x%x: ", cmd); +#endif
- if (timer < 0x60) { - pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, - 0x60); - } + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr);
- /* read BAR for memory space access */ - pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &iobase); - iobase &= PCI_BASE_ADDRESS_MEM_MASK; - debug("dc21x4x: DEC 21142 PCI Device @0x%x\n", iobase); + /* Shift the command bits out. */ + do { + short dataval = (cmd & BIT(cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
- dev = (struct eth_device *)malloc(sizeof(*dev)); - if (!dev) { - printf("Can not allocalte memory of dc21x4x\n"); - break; - } + sendto_srom(dev, dataval, ioaddr); + udelay(10);
- memset(dev, 0, sizeof(*dev)); +#ifdef DEBUG_SROM2 + printf("%X", getfrom_srom(dev, ioaddr) & 15); +#endif
- sprintf(dev->name, "dc21x4x#%d", card_number); + sendto_srom(dev, dataval | DT_CLK, ioaddr); + udelay(10); + retval = (retval << 1) | + !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ); + } while (--cmd_len >= 0);
- dev->iobase = pci_mem_to_phys(devbusfn, iobase); - dev->priv = (void *)devbusfn; - dev->init = dc21x4x_init; - dev->halt = dc21x4x_halt; - dev->send = dc21x4x_send; - dev->recv = dc21x4x_recv; + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
- /* Ensure we're not sleeping. */ - pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP); + /* Terminate the EEPROM access. */ + sendto_srom(dev, SROM_RD | SROM_SR, ioaddr);
- udelay(10 * 1000); +#ifdef DEBUG_SROM + printf(" EEPROM result is 0x%5.5x.\n", retval); +#endif
- read_hw_addr(dev, bis); + return retval; +}
- eth_register(dev); +static int read_srom(struct eth_device *dev, u_long ioaddr, int index) +{ + int ee_addr_size;
- card_number++; - } + ee_addr_size = (do_read_eeprom(dev, ioaddr, 0xff, 8) & BIT(18)) ? 8 : 6;
- return card_number; + return do_eeprom_cmd(dev, ioaddr, 0xffff | + (((SROM_READ_CMD << ee_addr_size) | index) << 16), + 3 + ee_addr_size + 16); }
-static int dc21x4x_init(struct eth_device *dev, bd_t *bis) +#ifdef UPDATE_SROM +static int write_srom(struct eth_device *dev, u_long ioaddr, int index, + int new_value) { + unsigned short newval; + int ee_addr_size; int i; - int devbusfn = (int)dev->priv;
- /* Ensure we're not sleeping. */ - pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP); + ee_addr_size = (do_read_eeprom(dev, ioaddr, 0xff, 8) & BIT(18)) ? 8 : 6;
- reset_de4x5(dev); + udelay(10 * 1000); /* test-only */
- if (dc2114x_inl(dev, DE4X5_STS) & (STS_TS | STS_RS)) { - printf("Error: Cannot reset ethernet controller.\n"); - return -1; - } +#ifdef DEBUG_SROM + printf("ee_addr_size=%d.\n", ee_addr_size); + printf("Writing new entry 0x%4.4x to offset %d.\n", new_value, index); +#endif
- dc2114x_outl(dev, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR); + /* Enable programming modes. */ + do_eeprom_cmd(dev, ioaddr, 0x4f << (ee_addr_size - 4), + 3 + ee_addr_size);
- for (i = 0; i < NUM_RX_DESC; i++) { - rx_ring[i].status = cpu_to_le32(R_OWN); - rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ); - rx_ring[i].buf = - cpu_to_le32(phys_to_bus((u32)net_rx_packets[i])); - rx_ring[i].next = 0; + /* Do the actual write. */ + do_eeprom_cmd(dev, ioaddr, new_value | + (((SROM_WRITE_CMD << ee_addr_size) | index) << 16), + 3 + ee_addr_size + 16); + + /* Poll for write finished. */ + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); + for (i = 0; i < 10000; i++) { /* Typical 2000 ticks */ + if (getfrom_srom(dev, ioaddr) & EE_DATA_READ) + break; }
- for (i = 0; i < NUM_TX_DESC; i++) { - tx_ring[i].status = 0; - tx_ring[i].des1 = 0; - tx_ring[i].buf = 0; - tx_ring[i].next = 0; +#ifdef DEBUG_SROM + printf(" Write finished after %d ticks.\n", i); +#endif + + /* Disable programming. */ + do_eeprom_cmd(dev, ioaddr, (0x40 << (ee_addr_size - 4)), + 3 + ee_addr_size); + + /* And read the result. */ + newval = do_eeprom_cmd(dev, ioaddr, + (((SROM_READ_CMD << ee_addr_size) | index) << 16) + | 0xffff, 3 + ee_addr_size + 16); +#ifdef DEBUG_SROM + printf(" New value at offset %d is %4.4x.\n", index, newval); +#endif + + return 1; +} + +static void update_srom(struct eth_device *dev, bd_t *bis) +{ + static unsigned short eeprom[0x40] = { + 0x140b, 0x6610, 0x0000, 0x0000, /* 00 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 04 */ + 0x00a3, 0x0103, 0x0000, 0x0000, /* 08 */ + 0x0000, 0x1f00, 0x0000, 0x0000, /* 0c */ + 0x0108, 0x038d, 0x0000, 0x0000, /* 10 */ + 0xe078, 0x0001, 0x0040, 0x0018, /* 14 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 18 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 1c */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 20 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 2c */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 30 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 34 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 38 */ + 0x0000, 0x0000, 0x0000, 0x4e07, /* 3c */ + }; + uchar enetaddr[6]; + int i; + + /* Ethernet Addr... */ + if (!eth_env_get_enetaddr("ethaddr", enetaddr)) + return; + + eeprom[0x0a] = (enetaddr[1] << 8) | enetaddr[0]; + eeprom[0x0b] = (enetaddr[3] << 8) | enetaddr[2]; + eeprom[0x0c] = (enetaddr[5] << 8) | enetaddr[4]; + + for (i = 0; i < 0x40; i++) + write_srom(dev, DE4X5_APROM, i, eeprom[i]); +} +#endif /* UPDATE_SROM */ + +static void send_setup_frame(struct eth_device *dev, bd_t *bis) +{ + char setup_frame[SETUP_FRAME_LEN]; + char *pa = &setup_frame[0]; + int i; + + memset(pa, 0xff, SETUP_FRAME_LEN); + + for (i = 0; i < ETH_ALEN; i++) { + *(pa + (i & 1)) = dev->enetaddr[i]; + if (i & 0x01) + pa += 4; }
- rx_ring_size = NUM_RX_DESC; - tx_ring_size = NUM_TX_DESC; + for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { + if (i < TOUT_LOOP) + continue;
- /* Write the end of list marker to the descriptor lists. */ - rx_ring[rx_ring_size - 1].des1 |= cpu_to_le32(RD_RER); - tx_ring[tx_ring_size - 1].des1 |= cpu_to_le32(TD_TER); + printf("%s: tx error buffer not ready\n", dev->name); + return; + }
- /* Tell the adapter where the TX/RX rings are located. */ - dc2114x_outl(dev, phys_to_bus((u32)&rx_ring), DE4X5_RRBA); - dc2114x_outl(dev, phys_to_bus((u32)&tx_ring), DE4X5_TRBA); + tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32)&setup_frame[0])); + tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_SET | SETUP_FRAME_LEN); + tx_ring[tx_new].status = cpu_to_le32(T_OWN);
- start_de4x5(dev); + dc2114x_outl(dev, POLL_DEMAND, DE4X5_TPD);
- tx_new = 0; - rx_new = 0; + for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { + if (i < TOUT_LOOP) + continue;
- send_setup_frame(dev, bis); + printf("%s: tx buffer not ready\n", dev->name); + return; + }
- return 0; + if (le32_to_cpu(tx_ring[tx_new].status) != 0x7FFFFFFF) { + printf("TX error status2 = 0x%08X\n", + le32_to_cpu(tx_ring[tx_new].status)); + } + + tx_new = (tx_new + 1) % NUM_TX_DESC; }
static int dc21x4x_send(struct eth_device *dev, void *packet, int length) @@ -397,297 +497,175 @@ static int dc21x4x_recv(struct eth_device *dev) return length; }
-static void dc21x4x_halt(struct eth_device *dev) +static int dc21x4x_init(struct eth_device *dev, bd_t *bis) { + int i; int devbusfn = (int)dev->priv;
- stop_de4x5(dev); - dc2114x_outl(dev, 0, DE4X5_SICR); + /* Ensure we're not sleeping. */ + pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP);
- pci_write_config_byte(devbusfn, PCI_CFDA_PSM, SLEEP); -} + reset_de4x5(dev);
-static void send_setup_frame(struct eth_device *dev, bd_t *bis) -{ - char setup_frame[SETUP_FRAME_LEN]; - char *pa = &setup_frame[0]; - int i; + if (dc2114x_inl(dev, DE4X5_STS) & (STS_TS | STS_RS)) { + printf("Error: Cannot reset ethernet controller.\n"); + return -1; + }
- memset(pa, 0xff, SETUP_FRAME_LEN); + dc2114x_outl(dev, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR);
- for (i = 0; i < ETH_ALEN; i++) { - *(pa + (i & 1)) = dev->enetaddr[i]; - if (i & 0x01) - pa += 4; + for (i = 0; i < NUM_RX_DESC; i++) { + rx_ring[i].status = cpu_to_le32(R_OWN); + rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ); + rx_ring[i].buf = + cpu_to_le32(phys_to_bus((u32)net_rx_packets[i])); + rx_ring[i].next = 0; }
- for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { - if (i < TOUT_LOOP) - continue; - - printf("%s: tx error buffer not ready\n", dev->name); - return; + for (i = 0; i < NUM_TX_DESC; i++) { + tx_ring[i].status = 0; + tx_ring[i].des1 = 0; + tx_ring[i].buf = 0; + tx_ring[i].next = 0; }
- tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32)&setup_frame[0])); - tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_SET | SETUP_FRAME_LEN); - tx_ring[tx_new].status = cpu_to_le32(T_OWN); + rx_ring_size = NUM_RX_DESC; + tx_ring_size = NUM_TX_DESC;
- dc2114x_outl(dev, POLL_DEMAND, DE4X5_TPD); + /* Write the end of list marker to the descriptor lists. */ + rx_ring[rx_ring_size - 1].des1 |= cpu_to_le32(RD_RER); + tx_ring[tx_ring_size - 1].des1 |= cpu_to_le32(TD_TER);
- for (i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { - if (i < TOUT_LOOP) - continue; + /* Tell the adapter where the TX/RX rings are located. */ + dc2114x_outl(dev, phys_to_bus((u32)&rx_ring), DE4X5_RRBA); + dc2114x_outl(dev, phys_to_bus((u32)&tx_ring), DE4X5_TRBA);
- printf("%s: tx buffer not ready\n", dev->name); - return; - } + start_de4x5(dev);
- if (le32_to_cpu(tx_ring[tx_new].status) != 0x7FFFFFFF) { - printf("TX error status2 = 0x%08X\n", - le32_to_cpu(tx_ring[tx_new].status)); - } + tx_new = 0; + rx_new = 0;
- tx_new = (tx_new + 1) % NUM_TX_DESC; -} + send_setup_frame(dev, bis);
-/* SROM Read and write routines. */ -static void sendto_srom(struct eth_device *dev, u_int command, u_long addr) -{ - dc2114x_outl(dev, command, addr); - udelay(1); + return 0; }
-static int getfrom_srom(struct eth_device *dev, u_long addr) +static void dc21x4x_halt(struct eth_device *dev) { - u32 tmp = dc2114x_inl(dev, addr); + int devbusfn = (int)dev->priv;
- udelay(1); - return tmp; + stop_de4x5(dev); + dc2114x_outl(dev, 0, DE4X5_SICR); + + pci_write_config_byte(devbusfn, PCI_CFDA_PSM, SLEEP); }
-/* Note: this routine returns extra data bits for size detection. */ -static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, - int addr_len) +static void read_hw_addr(struct eth_device *dev, bd_t *bis) { - int read_cmd = location | (SROM_READ_CMD << addr_len); - unsigned int retval = 0; - int i; - - sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); - -#ifdef DEBUG_SROM - printf(" EEPROM read at %d ", location); -#endif - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + u_short tmp, *p = (u_short *)(&dev->enetaddr[0]); + int i, j = 0;
- sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval, - ioaddr); - udelay(10); - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval | DT_CLK, - ioaddr); - udelay(10); -#ifdef DEBUG_SROM2 - printf("%X", getfrom_srom(dev, ioaddr) & 15); -#endif - retval = (retval << 1) | - !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ); + for (i = 0; i < (ETH_ALEN >> 1); i++) { + tmp = read_srom(dev, DE4X5_APROM, (SROM_HWADD >> 1) + i); + *p = le16_to_cpu(tmp); + j += *p++; }
- sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); - -#ifdef DEBUG_SROM2 - printf(" :%X:", getfrom_srom(dev, ioaddr) & 15); -#endif - - for (i = 16; i > 0; i--) { - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); - udelay(10); -#ifdef DEBUG_SROM2 - printf("%X", getfrom_srom(dev, ioaddr) & 15); + if (!j || j == 0x2fffd) { + memset(dev->enetaddr, 0, ETH_ALEN); + debug("Warning: can't read HW address from SROM.\n"); +#ifdef UPDATE_SROM + update_srom(dev, bis); #endif - retval = (retval << 1) | - !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ); - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); - udelay(10); } - - /* Terminate the EEPROM access. */ - sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); - -#ifdef DEBUG_SROM2 - printf(" EEPROM value at %d is %5.5x.\n", location, retval); -#endif - - return retval; }
-/* - * This executes a generic EEPROM command, typically a write or write - * enable. It returns the data output from the EEPROM, and thus may - * also be used for reads. - */ -static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, - int cmd_len) -{ - unsigned int retval = 0; - -#ifdef DEBUG_SROM - printf(" EEPROM op 0x%x: ", cmd); -#endif - - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); - - /* Shift the command bits out. */ - do { - short dataval = (cmd & BIT(cmd_len)) ? EE_WRITE_1 : EE_WRITE_0; - - sendto_srom(dev, dataval, ioaddr); - udelay(10); - -#ifdef DEBUG_SROM2 - printf("%X", getfrom_srom(dev, ioaddr) & 15); -#endif - - sendto_srom(dev, dataval | DT_CLK, ioaddr); - udelay(10); - retval = (retval << 1) | - !!(getfrom_srom(dev, ioaddr) & EE_DATA_READ); - } while (--cmd_len >= 0); - - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); - - /* Terminate the EEPROM access. */ - sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); - -#ifdef DEBUG_SROM - printf(" EEPROM result is 0x%5.5x.\n", retval); -#endif - - return retval; -} +static struct pci_device_id supported[] = { + { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST }, + { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142 }, + { } +};
-static int read_srom(struct eth_device *dev, u_long ioaddr, int index) +int dc21x4x_initialize(bd_t *bis) { - int ee_addr_size; - - ee_addr_size = (do_read_eeprom(dev, ioaddr, 0xff, 8) & BIT(18)) ? 8 : 6; + struct eth_device *dev; + unsigned short status; + unsigned char timer; + unsigned int iobase; + int card_number = 0; + pci_dev_t devbusfn; + unsigned int cfrv; + int idx = 0;
- return do_eeprom_cmd(dev, ioaddr, 0xffff | - (((SROM_READ_CMD << ee_addr_size) | index) << 16), - 3 + ee_addr_size + 16); -} + while (1) { + devbusfn = pci_find_devices(supported, idx++); + if (devbusfn == -1) + break;
-#ifdef UPDATE_SROM -static int write_srom(struct eth_device *dev, u_long ioaddr, int index, - int new_value) -{ - unsigned short newval; - int ee_addr_size; - int i; + /* Get the chip configuration revision register. */ + pci_read_config_dword(devbusfn, PCI_REVISION_ID, &cfrv);
- ee_addr_size = (do_read_eeprom(dev, ioaddr, 0xff, 8) & BIT(18)) ? 8 : 6; + if ((cfrv & CFRV_RN) < DC2114x_BRK) { + printf("Error: The chip is not DC21143.\n"); + continue; + }
- udelay(10 * 1000); /* test-only */ + pci_read_config_word(devbusfn, PCI_COMMAND, &status); + status |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + pci_write_config_word(devbusfn, PCI_COMMAND, status);
-#ifdef DEBUG_SROM - printf("ee_addr_size=%d.\n", ee_addr_size); - printf("Writing new entry 0x%4.4x to offset %d.\n", new_value, index); -#endif + pci_read_config_word(devbusfn, PCI_COMMAND, &status); + if (!(status & PCI_COMMAND_MEMORY)) { + printf("Error: Can not enable MEMORY access.\n"); + continue; + }
- /* Enable programming modes. */ - do_eeprom_cmd(dev, ioaddr, 0x4f << (ee_addr_size - 4), - 3 + ee_addr_size); + if (!(status & PCI_COMMAND_MASTER)) { + printf("Error: Can not enable Bus Mastering.\n"); + continue; + }
- /* Do the actual write. */ - do_eeprom_cmd(dev, ioaddr, new_value | - (((SROM_WRITE_CMD << ee_addr_size) | index) << 16), - 3 + ee_addr_size + 16); + /* Check the latency timer for values >= 0x60. */ + pci_read_config_byte(devbusfn, PCI_LATENCY_TIMER, &timer);
- /* Poll for write finished. */ - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); - for (i = 0; i < 10000; i++) { /* Typical 2000 ticks */ - if (getfrom_srom(dev, ioaddr) & EE_DATA_READ) - break; - } + if (timer < 0x60) { + pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, + 0x60); + }
-#ifdef DEBUG_SROM - printf(" Write finished after %d ticks.\n", i); -#endif + /* read BAR for memory space access */ + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &iobase); + iobase &= PCI_BASE_ADDRESS_MEM_MASK; + debug("dc21x4x: DEC 21142 PCI Device @0x%x\n", iobase);
- /* Disable programming. */ - do_eeprom_cmd(dev, ioaddr, (0x40 << (ee_addr_size - 4)), - 3 + ee_addr_size); + dev = (struct eth_device *)malloc(sizeof(*dev)); + if (!dev) { + printf("Can not allocalte memory of dc21x4x\n"); + break; + }
- /* And read the result. */ - newval = do_eeprom_cmd(dev, ioaddr, - (((SROM_READ_CMD << ee_addr_size) | index) << 16) - | 0xffff, 3 + ee_addr_size + 16); -#ifdef DEBUG_SROM - printf(" New value at offset %d is %4.4x.\n", index, newval); -#endif + memset(dev, 0, sizeof(*dev));
- return 1; -} -#endif + sprintf(dev->name, "dc21x4x#%d", card_number);
-static void read_hw_addr(struct eth_device *dev, bd_t *bis) -{ - u_short tmp, *p = (u_short *)(&dev->enetaddr[0]); - int i, j = 0; + dev->iobase = pci_mem_to_phys(devbusfn, iobase); + dev->priv = (void *)devbusfn; + dev->init = dc21x4x_init; + dev->halt = dc21x4x_halt; + dev->send = dc21x4x_send; + dev->recv = dc21x4x_recv;
- for (i = 0; i < (ETH_ALEN >> 1); i++) { - tmp = read_srom(dev, DE4X5_APROM, (SROM_HWADD >> 1) + i); - *p = le16_to_cpu(tmp); - j += *p++; - } + /* Ensure we're not sleeping. */ + pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP);
- if (!j || j == 0x2fffd) { - memset(dev->enetaddr, 0, ETH_ALEN); - debug("Warning: can't read HW address from SROM.\n"); -#ifdef UPDATE_SROM - update_srom(dev, bis); -#endif - } -} + udelay(10 * 1000);
-#ifdef UPDATE_SROM -static void update_srom(struct eth_device *dev, bd_t *bis) -{ - static unsigned short eeprom[0x40] = { - 0x140b, 0x6610, 0x0000, 0x0000, /* 00 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 04 */ - 0x00a3, 0x0103, 0x0000, 0x0000, /* 08 */ - 0x0000, 0x1f00, 0x0000, 0x0000, /* 0c */ - 0x0108, 0x038d, 0x0000, 0x0000, /* 10 */ - 0xe078, 0x0001, 0x0040, 0x0018, /* 14 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 18 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 1c */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 20 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 2c */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 30 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 34 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 38 */ - 0x0000, 0x0000, 0x0000, 0x4e07, /* 3c */ - }; - uchar enetaddr[6]; - int i; + read_hw_addr(dev, bis);
- /* Ethernet Addr... */ - if (!eth_env_get_enetaddr("ethaddr", enetaddr)) - return; + eth_register(dev);
- eeprom[0x0a] = (enetaddr[1] << 8) | enetaddr[0]; - eeprom[0x0b] = (enetaddr[3] << 8) | enetaddr[2]; - eeprom[0x0c] = (enetaddr[5] << 8) | enetaddr[4]; + card_number++; + }
- for (i = 0; i < 0x40; i++) - write_srom(dev, DE4X5_APROM, i, eeprom[i]); + return card_number; } -#endif /* UPDATE_SROM */