From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Wed, 13 Feb 2013 16:02:41 +0000 (+0000)
Subject: switch: reset switch before using it.
X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=827e315017a70c0f7033ffe50562c5e7c2126884;p=openwrt%2Fstaging%2Fjow.git

switch: reset switch before using it.

SVN-Revision: 35579
---

diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c
index e33c30ec4d..38aa9eff55 100644
--- a/package/switch/src/switch-robo.c
+++ b/package/switch/src/switch-robo.c
@@ -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);
 }