diff options
author | Hauke Mehrtens <hauke@hauke-m.de> | 2013-02-13 16:02:41 +0000 |
---|---|---|
committer | Hauke Mehrtens <hauke@hauke-m.de> | 2013-02-13 16:02:41 +0000 |
commit | 827e315017a70c0f7033ffe50562c5e7c2126884 (patch) | |
tree | 1209dedb207b59c5e2894996df4ed6b5aa8d4175 /package/switch/src/switch-robo.c | |
parent | f3360fdf67271331040c9db0502f3083b2e274e6 (diff) | |
download | master-31e0f0ae-827e315017a70c0f7033ffe50562c5e7c2126884.tar.gz master-31e0f0ae-827e315017a70c0f7033ffe50562c5e7c2126884.tar.bz2 master-31e0f0ae-827e315017a70c0f7033ffe50562c5e7c2126884.zip |
switch: reset switch before using it.
SVN-Revision: 35579
Diffstat (limited to 'package/switch/src/switch-robo.c')
-rw-r--r-- | package/switch/src/switch-robo.c | 72 |
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); } |