The ixp2000 driver for the enp2611 was developed on a board with
authorLennert Buytenhek <buytenh@wantstofly.org>
Mon, 15 May 2006 19:25:29 +0000 (12:25 -0700)
committerStephen Hemminger <shemminger@osdl.org>
Mon, 15 May 2006 19:25:29 +0000 (12:25 -0700)
three gigabit ports, but some enp2611 models only have two ports
(and only one onboard PM3386.)  The current driver assumes there
are always three ports and so it doesn't work on the two-port
version of the board at all.

This patch adds a bit of logic to the enp2611 driver to limit the
number of ports to 2 if the second PM3386 isn't detected.

Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
drivers/net/ixp2000/enp2611.c
drivers/net/ixp2000/pm3386.c
drivers/net/ixp2000/pm3386.h

index 6f7dce8eba51c329dd7412334823131749ab6ac8..b67f586d7392ab199e29181517d18af00cc9a8e1 100644 (file)
@@ -149,6 +149,8 @@ static void enp2611_check_link_status(unsigned long __dummy)
                int status;
 
                dev = nds[i];
+               if (dev == NULL)
+                       continue;
 
                status = pm3386_is_link_up(i);
                if (status && !netif_carrier_ok(dev)) {
@@ -191,6 +193,7 @@ static void enp2611_set_port_admin_status(int port, int up)
 
 static int __init enp2611_init_module(void)
 { 
+       int ports;
        int i;
 
        if (!machine_is_enp2611())
@@ -199,7 +202,8 @@ static int __init enp2611_init_module(void)
        caleb_reset();
        pm3386_reset();
 
-       for (i = 0; i < 3; i++) {
+       ports = pm3386_port_count();
+       for (i = 0; i < ports; i++) {
                nds[i] = ixpdev_alloc(i, sizeof(struct enp2611_ixpdev_priv));
                if (nds[i] == NULL) {
                        while (--i >= 0)
@@ -215,9 +219,10 @@ static int __init enp2611_init_module(void)
 
        ixp2400_msf_init(&enp2611_msf_parameters);
 
-       if (ixpdev_init(3, nds, enp2611_set_port_admin_status)) {
-               for (i = 0; i < 3; i++)
-                       free_netdev(nds[i]);
+       if (ixpdev_init(ports, nds, enp2611_set_port_admin_status)) {
+               for (i = 0; i < ports; i++)
+                       if (nds[i])
+                               free_netdev(nds[i]);
                return -EINVAL;
        }
 
index 5c7ab7564053af12a291f2be7875329cb6ac6e1d..5224651c9aac30e3ab308286c7d01f93c987ee79 100644 (file)
@@ -86,40 +86,53 @@ static void pm3386_port_reg_write(int port, int _reg, int spacing, u16 value)
        pm3386_reg_write(port >> 1, reg, value);
 }
 
+int pm3386_secondary_present(void)
+{
+       return pm3386_reg_read(1, 0) == 0x3386;
+}
 
 void pm3386_reset(void)
 {
        u8 mac[3][6];
+       int secondary;
+
+       secondary = pm3386_secondary_present();
 
        /* Save programmed MAC addresses.  */
        pm3386_get_mac(0, mac[0]);
        pm3386_get_mac(1, mac[1]);
-       pm3386_get_mac(2, mac[2]);
+       if (secondary)
+               pm3386_get_mac(2, mac[2]);
 
        /* Assert analog and digital reset.  */
        pm3386_reg_write(0, 0x002, 0x0060);
-       pm3386_reg_write(1, 0x002, 0x0060);
+       if (secondary)
+               pm3386_reg_write(1, 0x002, 0x0060);
        mdelay(1);
 
        /* Deassert analog reset.  */
        pm3386_reg_write(0, 0x002, 0x0062);
-       pm3386_reg_write(1, 0x002, 0x0062);
+       if (secondary)
+               pm3386_reg_write(1, 0x002, 0x0062);
        mdelay(10);
 
        /* Deassert digital reset.  */
        pm3386_reg_write(0, 0x002, 0x0063);
-       pm3386_reg_write(1, 0x002, 0x0063);
+       if (secondary)
+               pm3386_reg_write(1, 0x002, 0x0063);
        mdelay(10);
 
        /* Restore programmed MAC addresses.  */
        pm3386_set_mac(0, mac[0]);
        pm3386_set_mac(1, mac[1]);
-       pm3386_set_mac(2, mac[2]);
+       if (secondary)
+               pm3386_set_mac(2, mac[2]);
 
        /* Disable carrier on all ports.  */
        pm3386_set_carrier(0, 0);
        pm3386_set_carrier(1, 0);
-       pm3386_set_carrier(2, 0);
+       if (secondary)
+               pm3386_set_carrier(2, 0);
 }
 
 static u16 swaph(u16 x)
@@ -127,6 +140,11 @@ static u16 swaph(u16 x)
        return ((x << 8) | (x >> 8)) & 0xffff;
 }
 
+int pm3386_port_count(void)
+{
+       return 2 + pm3386_secondary_present();
+}
+
 void pm3386_init_port(int port)
 {
        int pm = port >> 1;
index fe92bb056ac424c9279ca8501016d2f3452187c3..cc4183dca9116959be453b1354065719c850fe4a 100644 (file)
@@ -13,6 +13,7 @@
 #define __PM3386_H
 
 void pm3386_reset(void);
+int pm3386_port_count(void);
 void pm3386_init_port(int port);
 void pm3386_get_mac(int port, u8 *mac);
 void pm3386_set_mac(int port, u8 *mac);