aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHauke Mehrtens <hauke@hauke-m.de>2013-02-13 16:02:41 +0000
committerHauke Mehrtens <hauke@hauke-m.de>2013-02-13 16:02:41 +0000
commit827e315017a70c0f7033ffe50562c5e7c2126884 (patch)
tree1209dedb207b59c5e2894996df4ed6b5aa8d4175
parentf3360fdf67271331040c9db0502f3083b2e274e6 (diff)
downloadupstream-827e315017a70c0f7033ffe50562c5e7c2126884.tar.gz
upstream-827e315017a70c0f7033ffe50562c5e7c2126884.tar.bz2
upstream-827e315017a70c0f7033ffe50562c5e7c2126884.zip
switch: reset switch before using it.
SVN-Revision: 35579
-rw-r--r--package/switch/src/switch-robo.c72
1 files changed, 70 insertions, 2 deletions
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);
}