net: dc2114x: Reorganize driver
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>
diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c
index 2bbe4e5..9de9634 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 @@
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 @@
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 */