switch: reset switch before using it.
authorHauke Mehrtens <hauke@hauke-m.de>
Wed, 13 Feb 2013 16:02:41 +0000 (16:02 +0000)
committerHauke Mehrtens <hauke@hauke-m.de>
Wed, 13 Feb 2013 16:02:41 +0000 (16:02 +0000)
SVN-Revision: 35579

package/switch/src/switch-robo.c

index e33c30ec4d76093f706601a66acd7e6928f5f674..38aa9eff554ee136dbf3567a6d7ed4de14a35fa2 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <asm/uaccess.h>
 
 #include "switch-core.h"
@@ -73,6 +74,8 @@ struct robo_switch {
        u16 devid;                      /* ROBO_DEVICE_ID_53xx */
        bool is_5350;
        u8 gmii;                        /* gigabit mii */
+       int gpio_robo_reset;
+       int gpio_lanports_enable;
        struct ifreq ifr;
        struct net_device *dev;
        unsigned char port[6];
@@ -274,6 +277,27 @@ static void robo_switch_reset(void)
        }
 }
 
+#ifdef CONFIG_BCM47XX
+static int get_gpio_pin(const char *name)
+{
+       int i, err;
+       char nvram_var[10];
+       char buf[30];
+
+       for (i = 0; i < 16; i++) {
+               err = snprintf(nvram_var, sizeof(nvram_var), "gpio%i", i);
+               if (err <= 0)
+                       continue;
+               err = bcm47xx_nvram_getenv(nvram_var, buf, sizeof(buf));
+               if (err <= 0)
+                       continue;
+               if (!strcmp(name, buf))
+                       return i;
+       }
+       return -1;
+}
+#endif
+
 static int robo_probe(char *devname)
 {
        __u32 phyid;
@@ -317,13 +341,46 @@ static int robo_probe(char *devname)
                goto err_put;
        }
 
+#ifdef CONFIG_BCM47XX
+       robo.gpio_lanports_enable = get_gpio_pin("lanports_enable");
+       if (robo.gpio_lanports_enable >= 0) {
+               err = gpio_request(robo.gpio_lanports_enable, "lanports_enable");
+               if (err) {
+                       printk(KERN_ERR PFX "error (%i) requesting lanports_enable gpio (%i)\n",
+                              err, robo.gpio_lanports_enable);
+                       goto err_put;
+               }
+               gpio_direction_output(robo.gpio_lanports_enable, 1);
+               mdelay(5);
+       }
+
+       robo.gpio_robo_reset = get_gpio_pin("robo_reset");
+       if (robo.gpio_robo_reset >= 0) {
+               err = gpio_request(robo.gpio_robo_reset, "robo_reset");
+               if (err) {
+                       printk(KERN_ERR PFX "error (%i) requesting robo_reset gpio (%i)\n",
+                              err, robo.gpio_robo_reset);
+                       goto err_gpio_robo;
+               }
+               gpio_set_value(robo.gpio_robo_reset, 0);
+               gpio_direction_output(robo.gpio_robo_reset, 1);
+               gpio_set_value(robo.gpio_robo_reset, 0);
+               mdelay(50);
+
+               gpio_set_value(robo.gpio_robo_reset, 1);
+               mdelay(20);
+       } else {
+               // TODO: reset the internal robo switch
+       }
+#endif
+
        phyid = mdio_read(ROBO_PHY_ADDR, 0x2) |
                (mdio_read(ROBO_PHY_ADDR, 0x3) << 16);
 
        if (phyid == 0xffffffff || phyid == 0x55210022) {
                printk(KERN_ERR PFX "No Robo switch in managed mode found, phy_id = 0x%08x\n", phyid);
                err = -ENODEV;
-               goto err_put;
+               goto err_gpio_lanports;
        }
 
        /* Get the device ID */
@@ -340,12 +397,19 @@ static int robo_probe(char *devname)
        robo_switch_reset();
        err = robo_switch_enable();
        if (err)
-               goto err_put;
+               goto err_gpio_lanports;
 
        printk(KERN_INFO PFX "found a 5%s%x!%s at %s\n", robo.devid & 0xff00 ? "" : "3", robo.devid,
                robo.is_5350 ? " It's a 5350." : "", devname);
 
        return 0;
+
+err_gpio_lanports:
+       if (robo.gpio_lanports_enable >= 0)
+               gpio_free(robo.gpio_lanports_enable);
+err_gpio_robo:
+       if (robo.gpio_robo_reset >= 0)
+               gpio_free(robo.gpio_robo_reset);
 err_put:
        dev_put(robo.dev);
        robo.dev = NULL;
@@ -680,6 +744,10 @@ static void __exit robo_exit(void)
        switch_unregister_driver(DRIVER_NAME);
        if (robo.dev)
                dev_put(robo.dev);
+       if (robo.gpio_robo_reset >= 0)
+               gpio_free(robo.gpio_robo_reset);
+       if (robo.gpio_lanports_enable >= 0)
+               gpio_free(robo.gpio_lanports_enable);
        kfree(robo.device);
 }