]> err.no Git - linux-2.6/blobdiff - drivers/net/ixp2000/pm3386.c
Merge branch 'i915fb' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/intelf...
[linux-2.6] / drivers / net / ixp2000 / pm3386.c
index df960f1710f64aeac31ba57d893baafcb6ed0d84..5224651c9aac30e3ab308286c7d01f93c987ee79 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <asm/io.h>
+#include "pm3386.h"
 
 /*
  * Read from register 'reg' of PM3386 device 'pm'.
@@ -85,10 +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)
 {
-       /* @@@ Implement me.  */
+       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]);
+       if (secondary)
+               pm3386_get_mac(2, mac[2]);
+
+       /* Assert analog and digital reset.  */
+       pm3386_reg_write(0, 0x002, 0x0060);
+       if (secondary)
+               pm3386_reg_write(1, 0x002, 0x0060);
+       mdelay(1);
+
+       /* Deassert analog reset.  */
+       pm3386_reg_write(0, 0x002, 0x0062);
+       if (secondary)
+               pm3386_reg_write(1, 0x002, 0x0062);
+       mdelay(10);
+
+       /* Deassert digital reset.  */
+       pm3386_reg_write(0, 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]);
+       if (secondary)
+               pm3386_set_mac(2, mac[2]);
+
+       /* Disable carrier on all ports.  */
+       pm3386_set_carrier(0, 0);
+       pm3386_set_carrier(1, 0);
+       if (secondary)
+               pm3386_set_carrier(2, 0);
 }
 
 static u16 swaph(u16 x)
@@ -96,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;
@@ -166,9 +215,7 @@ void pm3386_init_port(int port)
         * Soft reset the EGMAC block.
         */
        pm3386_port_reg_write(port, 0x301, 0x100, 0x8000);
-       udelay(10);
        pm3386_port_reg_write(port, 0x301, 0x100, 0x0000);
-       udelay(10);
 
        /*
         * Auto-sense autonegotiation status.
@@ -191,15 +238,12 @@ void pm3386_init_port(int port)
         * Set autonegotiation parameters to 'no PAUSE, full duplex.'
         */
        pm3386_port_reg_write(port, 0x31c, 0x100, 0x0020);
-       udelay(10);
 
        /*
         * Enable and restart autonegotiation.
         */
        pm3386_port_reg_write(port, 0x318, 0x100, 0x0003);
-       udelay(1000);
        pm3386_port_reg_write(port, 0x318, 0x100, 0x0002);
-       udelay(10);
 }
 
 void pm3386_get_mac(int port, u8 *mac)
@@ -219,6 +263,13 @@ void pm3386_get_mac(int port, u8 *mac)
        mac[5] = (temp >> 8) & 0xff;
 }
 
+void pm3386_set_mac(int port, u8 *mac)
+{
+       pm3386_port_reg_write(port, 0x308, 0x100, (mac[1] << 8) | mac[0]);
+       pm3386_port_reg_write(port, 0x309, 0x100, (mac[3] << 8) | mac[2]);
+       pm3386_port_reg_write(port, 0x30a, 0x100, (mac[5] << 8) | mac[4]);
+}
+
 static u32 pm3386_get_stat(int port, u16 base)
 {
        u32 value;
@@ -247,6 +298,11 @@ void pm3386_get_stats(int port, struct net_device_stats *stats)
        /* @@@ Add other stats.  */
 }
 
+void pm3386_set_carrier(int port, int state)
+{
+       pm3386_port_reg_write(port, 0x703, 0x10, state ? 0x1001 : 0x0000);
+}
+
 int pm3386_is_link_up(int port)
 {
        u16 temp;
@@ -264,8 +320,6 @@ void pm3386_enable_rx(int port)
        temp = pm3386_port_reg_read(port, 0x303, 0x100);
        temp |= 0x1000;
        pm3386_port_reg_write(port, 0x303, 0x100, temp);
-
-       udelay(10);
 }
 
 void pm3386_disable_rx(int port)
@@ -275,8 +329,6 @@ void pm3386_disable_rx(int port)
        temp = pm3386_port_reg_read(port, 0x303, 0x100);
        temp &= 0xefff;
        pm3386_port_reg_write(port, 0x303, 0x100, temp);
-
-       udelay(10);
 }
 
 void pm3386_enable_tx(int port)
@@ -286,8 +338,6 @@ void pm3386_enable_tx(int port)
        temp = pm3386_port_reg_read(port, 0x303, 0x100);
        temp |= 0x4000;
        pm3386_port_reg_write(port, 0x303, 0x100, temp);
-
-       udelay(10);
 }
 
 void pm3386_disable_tx(int port)
@@ -297,8 +347,6 @@ void pm3386_disable_tx(int port)
        temp = pm3386_port_reg_read(port, 0x303, 0x100);
        temp &= 0xbfff;
        pm3386_port_reg_write(port, 0x303, 0x100, temp);
-
-       udelay(10);
 }
 
 MODULE_LICENSE("GPL");