]> git.sur5r.net Git - u-boot/blobdiff - drivers/net/ne2000.c
MPC512x: reduce timeout waiting for Ethernet autonegotiation to 2.5s
[u-boot] / drivers / net / ne2000.c
index d09da782951673b08484e28e076eb10d1693453f..ec92485cbe78794423aff5e71ae623369f588a97 100644 (file)
@@ -126,6 +126,9 @@ dp83902a_init(void)
 {
        dp83902a_priv_data_t *dp = &nic;
        u8* base;
+#if defined(NE2000_BASIC_INIT)
+       int i;
+#endif
 
        DEBUG_FUNCTION();
 
@@ -755,16 +758,97 @@ static hw_info_t hw_info[] = {
 
 #define NR_INFO                (sizeof(hw_info)/sizeof(hw_info_t))
 
-static hw_info_t default_info = { 0, 0, 0, 0, 0 };
-
-u8 dev_addr[6];
-
 #define PCNET_CMD      0x00
 #define PCNET_DATAPORT 0x10    /* NatSemi-defined port window offset. */
 #define PCNET_RESET    0x1f    /* Issue a read to reset, a write to clear. */
 #define PCNET_MISC     0x18    /* For IBM CCAE and Socket EA cards */
 
-u32 nic_base;
+static void pcnet_reset_8390(void)
+{
+       int i, r;
+
+       PRINTK("nic base is %lx\n", nic.base);
+
+       n2k_outb(E8390_NODMA + E8390_PAGE0+E8390_STOP, E8390_CMD);
+       PRINTK("cmd (at %lx) is %x\n", nic.base + E8390_CMD, n2k_inb(E8390_CMD));
+       n2k_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, E8390_CMD);
+       PRINTK("cmd (at %lx) is %x\n", nic.base + E8390_CMD, n2k_inb(E8390_CMD));
+       n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);
+       PRINTK("cmd (at %lx) is %x\n", nic.base + E8390_CMD, n2k_inb(E8390_CMD));
+       n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);
+
+       n2k_outb(n2k_inb(PCNET_RESET), PCNET_RESET);
+
+       for (i = 0; i < 100; i++) {
+               if ((r = (n2k_inb(EN0_ISR) & ENISR_RESET)) != 0)
+                       break;
+               PRINTK("got %x in reset\n", r);
+               udelay(100);
+       }
+       n2k_outb(ENISR_RESET, EN0_ISR); /* Ack intr. */
+
+       if (i == 100)
+               printf("pcnet_reset_8390() did not complete.\n");
+} /* pcnet_reset_8390 */
+
+int get_prom(u8* mac_addr) __attribute__ ((weak, alias ("__get_prom")));
+int __get_prom(u8* mac_addr)
+{
+       u8 prom[32];
+       int i, j;
+       struct {
+               u_char value, offset;
+       } program_seq[] = {
+               {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
+               {0x48, EN0_DCFG},               /* Set byte-wide (0x48) access. */
+               {0x00, EN0_RCNTLO},             /* Clear the count regs. */
+               {0x00, EN0_RCNTHI},
+               {0x00, EN0_IMR},                /* Mask completion irq. */
+               {0xFF, EN0_ISR},
+               {E8390_RXOFF, EN0_RXCR},        /* 0x20 Set to monitor */
+               {E8390_TXOFF, EN0_TXCR},        /* 0x02 and loopback mode. */
+               {32, EN0_RCNTLO},
+               {0x00, EN0_RCNTHI},
+               {0x00, EN0_RSARLO},             /* DMA starting at 0x0000. */
+               {0x00, EN0_RSARHI},
+               {E8390_RREAD+E8390_START, E8390_CMD},
+       };
+
+       PRINTK ("trying to get MAC via prom reading\n");
+
+       pcnet_reset_8390 ();
+
+       mdelay (10);
+
+       for (i = 0; i < sizeof (program_seq) / sizeof (program_seq[0]); i++)
+               n2k_outb (program_seq[i].value, program_seq[i].offset);
+
+       PRINTK ("PROM:");
+       for (i = 0; i < 32; i++) {
+               prom[i] = n2k_inb (PCNET_DATAPORT);
+               PRINTK (" %02x", prom[i]);
+       }
+       PRINTK ("\n");
+       for (i = 0; i < NR_INFO; i++) {
+               if ((prom[0] == hw_info[i].a0) &&
+                       (prom[2] == hw_info[i].a1) &&
+                       (prom[4] == hw_info[i].a2)) {
+                       PRINTK ("matched board %d\n", i);
+                       break;
+               }
+       }
+       if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) {
+               PRINTK ("on exit i is %d/%ld\n", i, NR_INFO);
+               PRINTK ("MAC address is ");
+               for (j = 0; j < 6; j++) {
+                       mac_addr[j] = prom[j << 1];
+                       PRINTK ("%02x:", mac_addr[i]);
+               }
+               PRINTK ("\n");
+               return (i < NR_INFO) ? i : 0;
+       }
+       return 0;
+}
 
 /* U-boot specific routines */
 static u8 *pbuf = NULL;
@@ -790,7 +874,8 @@ void uboot_push_tx_done(int key, int val) {
 }
 
 int eth_init(bd_t *bd) {
-       static hw_info_t * r;
+       int r;
+       u8 dev_addr[6];
        char ethaddr[20];
 
        PRINTK("### eth_init\n");
@@ -813,7 +898,6 @@ int eth_init(bd_t *bd) {
        }
 #endif
 
-       nic_base = CONFIG_DRIVER_NE2000_BASE;
        nic.base = (u8 *) CONFIG_DRIVER_NE2000_BASE;
 
        r = get_prom(dev_addr);