From e2a6028da3eccac80337a17129174ae2d7716b66 Mon Sep 17 00:00:00 2001 From: hauke Date: Thu, 3 Jan 2013 01:53:30 +0000 Subject: brcm47xx: add a new version of the nvram rewrite patch This is the version like it was send for mainline inclusion. git-svn-id: svn://svn.openwrt.org/openwrt/trunk@34988 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/switch/src/switch-robo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'package/switch/src/switch-robo.c') diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c index f1160c889..3751653a6 100644 --- a/package/switch/src/switch-robo.c +++ b/package/switch/src/switch-robo.c @@ -35,7 +35,7 @@ #include "etc53xx.h" #ifdef CONFIG_BCM47XX -#include +#include #endif #define DRIVER_NAME "bcm53xx" @@ -236,7 +236,7 @@ static int robo_switch_enable(void) #ifdef CONFIG_BCM47XX /* WAN port LED, except for Netgear WGT634U */ - if (nvram_getenv("nvram_type", buf, sizeof(buf)) >= 0) { + if (bcm47xx_nvram_getenv("nvram_type", buf, sizeof(buf)) >= 0) { if (strcmp(buf, "cfe") != 0) robo_write16(ROBO_CTRL_PAGE, 0x16, 0x1F); } -- cgit v1.2.3 From e3e6518cfee3a14f1165beca0e2b71486243fd39 Mon Sep 17 00:00:00 2001 From: hauke Date: Thu, 3 Jan 2013 01:57:19 +0000 Subject: switch: improve error messages This is in part based on a patch send by Nathan Hintz git-svn-id: svn://svn.openwrt.org/openwrt/trunk@34991 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/switch/src/switch-robo.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'package/switch/src/switch-robo.c') diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c index 3751653a6..f9b306cf1 100644 --- a/package/switch/src/switch-robo.c +++ b/package/switch/src/switch-robo.c @@ -103,8 +103,7 @@ static u16 mdio_read(__u16 phy_id, __u8 reg) err = do_ioctl(SIOCGMIIREG); if (err < 0) { - printk(KERN_ERR PFX - "[%s:%d] SIOCGMIIREG failed! err: %i\n", __FILE__, __LINE__, err); + printk(KERN_ERR PFX "failed to read mdio reg %i with err %i.\n", reg, err); return 0xffff; } @@ -123,8 +122,7 @@ static void mdio_write(__u16 phy_id, __u8 reg, __u16 val) err = do_ioctl(SIOCSMIIREG); if (err < 0) { - printk(KERN_ERR PFX - "[%s:%d] SIOCSMIIREG failed! err: %i\n", __FILE__, __LINE__, err); + printk(KERN_ERR PFX "failed to write mdio reg: %i with err %i.\n", reg, err); return; } } @@ -147,7 +145,7 @@ static int robo_reg(__u8 page, __u8 reg, __u8 op) return 0; } - printk(KERN_ERR PFX "[%s:%d] timeout in robo_reg!\n", __FILE__, __LINE__); + printk(KERN_ERR PFX "timeout in robo_reg on page %i and reg %i with op %i.\n", page, reg, op); return 0; } @@ -224,7 +222,7 @@ static int robo_switch_enable(void) robo_write16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE, val); val = robo_read16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE); if (!(val & (1 << 1))) { - printk("Failed to enable switch\n"); + printk(KERN_ERR PFX "Failed to enable switch\n"); return -EBUSY; } @@ -262,15 +260,15 @@ static int robo_probe(char *devname) unsigned int i; int err = 1; - printk(KERN_INFO PFX "Probing device %s: ", devname); + printk(KERN_INFO PFX "Probing device '%s'\n", devname); strcpy(robo.ifr.ifr_name, devname); if ((robo.dev = dev_get_by_name(&init_net, devname)) == NULL) { - printk("No such device\n"); + printk(KERN_ERR PFX "No such device\n"); return 1; } if (!robo.dev->netdev_ops || !robo.dev->netdev_ops->ndo_do_ioctl) { - printk("ndo_do_ioctl not implemented in ethernet driver\n"); + printk(KERN_ERR PFX "ndo_do_ioctl not implemented in ethernet driver\n"); return 1; } @@ -280,8 +278,9 @@ static int robo_probe(char *devname) robo.port[5] = 8; /* try access using MII ioctls - get phy address */ - if (do_ioctl(SIOCGMIIPHY) < 0) { - printk("error while accessing MII phy registers with ioctls\n"); + err = do_ioctl(SIOCGMIIPHY); + if (err < 0) { + printk(KERN_ERR PFX "error (%i) while accessing MII phy registers with ioctls\n", err); goto done; } @@ -290,7 +289,7 @@ static int robo_probe(char *devname) if ((mii->phy_id != ROBO_PHY_ADDR) && (mii->phy_id != ROBO_PHY_ADDR_BCM63XX) && (mii->phy_id != ROBO_PHY_ADDR_TG3)) { - printk("Invalid phy address (%d)\n", mii->phy_id); + printk(KERN_ERR PFX "Invalid phy address (%d)\n", mii->phy_id); goto done; } @@ -298,7 +297,7 @@ static int robo_probe(char *devname) (mdio_read(ROBO_PHY_ADDR, 0x3) << 16); if (phyid == 0xffffffff || phyid == 0x55210022) { - printk("No Robo switch in managed mode found, phy_id = 0x%08x\n", phyid); + printk(KERN_ERR PFX "No Robo switch in managed mode found, phy_id = 0x%08x\n", phyid); goto done; } @@ -319,8 +318,8 @@ static int robo_probe(char *devname) goto done; err = 0; - printk("found a 5%s%x!%s\n", robo.devid & 0xff00 ? "" : "3", robo.devid, - robo.is_5350 ? " It's a 5350." : ""); + 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); done: if (err) { -- cgit v1.2.3 From e3a81c46a5b399e5579144aec5222d3c82055a63 Mon Sep 17 00:00:00 2001 From: hauke Date: Thu, 3 Jan 2013 01:58:01 +0000 Subject: switch: ROBO Switch Gigabit MII Support I wrote this patch some time ago because I had a need for one of the Gigabit ports (Linksys E3000) to be forced to 100FD. This is based on the robocfg sources included w/ the RT-N16 sources from ASUS. Since work is progressing on a BGMAC driver that could be included in OpenWRT, this may be useful to someone else. In testing, forcing the speed to 10/100 or 1000 worked fine; however, when trying to force full-duplex mode, the result was always half-duplex. I was not able to isolate the source of the problem (this patch, driver or H/W limitation). The only way I could get it to work was to set the port to Auto, but then only advertise 100FD (not included in this patch). I have a modified version of the robocfg package as well, I'd have to clean it up a little first (remove the full-duplex hack) before submitting it if there is interest. Signed-off-by: Nathan Hintz git-svn-id: svn://svn.openwrt.org/openwrt/trunk@34992 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/switch/src/switch-robo.c | 124 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 115 insertions(+), 9 deletions(-) (limited to 'package/switch/src/switch-robo.c') diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c index f9b306cf1..f3a0eacf1 100644 --- a/package/switch/src/switch-robo.c +++ b/package/switch/src/switch-robo.c @@ -72,6 +72,7 @@ struct robo_switch { char *device; /* The device name string (ethX) */ u16 devid; /* ROBO_DEVICE_ID_53xx */ bool is_5350; + u8 gmii; /* gigabit mii */ struct ifreq ifr; struct net_device *dev; unsigned char port[6]; @@ -147,7 +148,7 @@ static int robo_reg(__u8 page, __u8 reg, __u8 op) printk(KERN_ERR PFX "timeout in robo_reg on page %i and reg %i with op %i.\n", page, reg, op); - return 0; + return 1; } /* @@ -173,7 +174,7 @@ static __u32 robo_read32(__u8 page, __u8 reg) { robo_reg(page, reg, REG_MII_ADDR_READ); - return mdio_read(ROBO_PHY_ADDR, REG_MII_DATA0) + + return mdio_read(ROBO_PHY_ADDR, REG_MII_DATA0) | (mdio_read(ROBO_PHY_ADDR, REG_MII_DATA0 + 1) << 16); } @@ -188,21 +189,40 @@ static void robo_write16(__u8 page, __u8 reg, __u16 val16) static void robo_write32(__u8 page, __u8 reg, __u32 val32) { /* write data */ - mdio_write(ROBO_PHY_ADDR, REG_MII_DATA0, val32 & 65535); + mdio_write(ROBO_PHY_ADDR, REG_MII_DATA0, val32 & 0xFFFF); mdio_write(ROBO_PHY_ADDR, REG_MII_DATA0 + 1, val32 >> 16); robo_reg(page, reg, REG_MII_ADDR_WRITE); } -/* checks that attached switch is 5325E/5350 */ -static int robo_vlan5350(void) +/* checks that attached switch is 5325/5352/5354/5356/5357/53115 */ +static int robo_vlan5350(__u32 phyid) { /* set vlan access id to 15 and read it back */ __u16 val16 = 15; robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16); /* 5365 will refuse this as it does not have this reg */ - return (robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350) == val16); + if (robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350) != val16) + return 0; + /* gigabit ? */ + if (mdio_read(0, ROBO_MII_STAT) & 0x0100) + robo.gmii = ((mdio_read(0, 0x0f) & 0xf000) != 0); + /* 53115 ? */ + if (robo.gmii && robo_read32(ROBO_STAT_PAGE, ROBO_LSA_IM_PORT) != 0) { + robo_write16(ROBO_ARLIO_PAGE, ROBO_VTBL_INDX_5395, val16); + robo_write16(ROBO_ARLIO_PAGE, ROBO_VTBL_ACCESS_5395, + (1 << 7) /* start */ | 1 /* read */); + if (robo_read16(ROBO_ARLIO_PAGE, ROBO_VTBL_ACCESS_5395) == 1 && + robo_read16(ROBO_ARLIO_PAGE, ROBO_VTBL_INDX_5395) == val16) + return 4; + } + /* dirty trick for 5356/5357 */ + if ((phyid & 0xfff0ffff ) == 0x5da00362 || + (phyid & 0xfff0ffff ) == 0x5e000362) + return 3; + /* 5325/5352/5354*/ + return 1; } static int robo_switch_enable(void) @@ -259,6 +279,7 @@ static int robo_probe(char *devname) __u32 phyid; unsigned int i; int err = 1; + struct mii_ioctl_data *mii; printk(KERN_INFO PFX "Probing device '%s'\n", devname); strcpy(robo.ifr.ifr_name, devname); @@ -285,7 +306,7 @@ static int robo_probe(char *devname) } /* got phy address check for robo address */ - struct mii_ioctl_data *mii = if_mii(&robo.ifr); + mii = if_mii(&robo.ifr); if ((mii->phy_id != ROBO_PHY_ADDR) && (mii->phy_id != ROBO_PHY_ADDR_BCM63XX) && (mii->phy_id != ROBO_PHY_ADDR_TG3)) { @@ -310,7 +331,7 @@ static int robo_probe(char *devname) } if (!robo.devid) robo.devid = ROBO_DEVICE_ID_5325; /* Fake it */ - robo.is_5350 = robo_vlan5350(); + robo.is_5350 = robo_vlan5350(phyid); robo_switch_reset(); err = robo_switch_enable(); @@ -445,6 +466,80 @@ static int handle_enable_write(void *driver, char *buf, int nr) return 0; } +static int handle_port_enable_read(void *driver, char *buf, int nr) +{ + return sprintf(buf, "%d\n", ((robo_read16(ROBO_CTRL_PAGE, robo.port[nr]) & 3) == 3 ? 0 : 1)); +} + +static int handle_port_enable_write(void *driver, char *buf, int nr) +{ + u16 val16; + + if (buf[0] == '0') + val16 = 3; /* disabled */ + else if (buf[0] == '1') + val16 = 0; /* enabled */ + else + return -EINVAL; + + robo_write16(ROBO_CTRL_PAGE, robo.port[nr], + (robo_read16(ROBO_CTRL_PAGE, robo.port[nr]) & ~3) | val16); + + return 0; +} + +static int handle_port_media_read(void *driver, char *buf, int nr) +{ + u16 bmcr = mdio_read(robo.port[nr], MII_BMCR); + int media, len; + + if (bmcr & BMCR_ANENABLE) + media = SWITCH_MEDIA_AUTO; + else { + if (bmcr & BMCR_SPEED1000) + media = SWITCH_MEDIA_1000; + else if (bmcr & BMCR_SPEED100) + media = SWITCH_MEDIA_100; + else + media = 0; + + if (bmcr & BMCR_FULLDPLX) + media |= SWITCH_MEDIA_FD; + } + + len = switch_print_media(buf, media); + return len + sprintf(buf + len, "\n"); +} + +static int handle_port_media_write(void *driver, char *buf, int nr) +{ + int media = switch_parse_media(buf); + u16 bmcr, bmcr_mask; + + if (media & SWITCH_MEDIA_AUTO) + bmcr = BMCR_ANENABLE | BMCR_ANRESTART; + else { + if (media & SWITCH_MEDIA_1000) { + if (!robo.gmii) + return -EINVAL; + bmcr = BMCR_SPEED1000; + } + else if (media & SWITCH_MEDIA_100) + bmcr = BMCR_SPEED100; + else + bmcr = 0; + + if (media & SWITCH_MEDIA_FD) + bmcr |= BMCR_FULLDPLX; + } + + bmcr_mask = ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_ANENABLE | BMCR_ANRESTART); + mdio_write(robo.port[nr], MII_BMCR, + (mdio_read(robo.port[nr], MII_BMCR) & bmcr_mask) | bmcr); + + return 0; +} + static int handle_enable_vlan_read(void *driver, char *buf, int nr) { return sprintf(buf, "%d\n", (((robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0) & (1 << 7)) == (1 << 7)) ? 1 : 0)); @@ -539,6 +634,17 @@ static int __init robo_init(void) .write = handle_reset }, { NULL, }, }; + static const switch_config port[] = { + { + .name = "enable", + .read = handle_port_enable_read, + .write = handle_port_enable_write + }, { + .name = "media", + .read = handle_port_media_read, + .write = handle_port_media_write + }, { NULL, }, + }; static const switch_config vlan[] = { { .name = "ports", @@ -554,7 +660,7 @@ static int __init robo_init(void) .ports = 6, .vlans = 16, .driver_handlers = cfg, - .port_handlers = NULL, + .port_handlers = port, .vlan_handlers = vlan, }; if (robo.devid != ROBO_DEVICE_ID_5325) { -- cgit v1.2.3 From 2a26e021e1be150d25b9075b0c234a086823d5ef Mon Sep 17 00:00:00 2001 From: hauke Date: Wed, 13 Feb 2013 16:01:50 +0000 Subject: switch: run cleanfile over the source code git-svn-id: svn://svn.openwrt.org/openwrt/trunk@35577 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/switch/src/switch-robo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'package/switch/src/switch-robo.c') diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c index f3a0eacf1..1372fbd62 100644 --- a/package/switch/src/switch-robo.c +++ b/package/switch/src/switch-robo.c @@ -17,7 +17,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ @@ -314,7 +314,7 @@ static int robo_probe(char *devname) goto done; } - phyid = mdio_read(ROBO_PHY_ADDR, 0x2) | + phyid = mdio_read(ROBO_PHY_ADDR, 0x2) | (mdio_read(ROBO_PHY_ADDR, 0x3) << 16); if (phyid == 0xffffffff || phyid == 0x55210022) { @@ -534,7 +534,7 @@ static int handle_port_media_write(void *driver, char *buf, int nr) } bmcr_mask = ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_ANENABLE | BMCR_ANRESTART); - mdio_write(robo.port[nr], MII_BMCR, + mdio_write(robo.port[nr], MII_BMCR, (mdio_read(robo.port[nr], MII_BMCR) & bmcr_mask) | bmcr); return 0; -- cgit v1.2.3 From fa24ec668f8441354bad7e274a7b333219b3fff2 Mon Sep 17 00:00:00 2001 From: hauke Date: Wed, 13 Feb 2013 16:02:20 +0000 Subject: switch: improve error handling in robo_probe() git-svn-id: svn://svn.openwrt.org/openwrt/trunk@35578 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/switch/src/switch-robo.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'package/switch/src/switch-robo.c') diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c index 1372fbd62..e33c30ec4 100644 --- a/package/switch/src/switch-robo.c +++ b/package/switch/src/switch-robo.c @@ -278,7 +278,7 @@ static int robo_probe(char *devname) { __u32 phyid; unsigned int i; - int err = 1; + int err = -1; struct mii_ioctl_data *mii; printk(KERN_INFO PFX "Probing device '%s'\n", devname); @@ -286,11 +286,13 @@ static int robo_probe(char *devname) if ((robo.dev = dev_get_by_name(&init_net, devname)) == NULL) { printk(KERN_ERR PFX "No such device\n"); - return 1; + err = -ENODEV; + goto err_done; } if (!robo.dev->netdev_ops || !robo.dev->netdev_ops->ndo_do_ioctl) { printk(KERN_ERR PFX "ndo_do_ioctl not implemented in ethernet driver\n"); - return 1; + err = -ENXIO; + goto err_put; } robo.device = devname; @@ -302,7 +304,7 @@ static int robo_probe(char *devname) err = do_ioctl(SIOCGMIIPHY); if (err < 0) { printk(KERN_ERR PFX "error (%i) while accessing MII phy registers with ioctls\n", err); - goto done; + goto err_put; } /* got phy address check for robo address */ @@ -311,7 +313,8 @@ static int robo_probe(char *devname) (mii->phy_id != ROBO_PHY_ADDR_BCM63XX) && (mii->phy_id != ROBO_PHY_ADDR_TG3)) { printk(KERN_ERR PFX "Invalid phy address (%d)\n", mii->phy_id); - goto done; + err = -ENODEV; + goto err_put; } phyid = mdio_read(ROBO_PHY_ADDR, 0x2) | @@ -319,7 +322,8 @@ static int robo_probe(char *devname) if (phyid == 0xffffffff || phyid == 0x55210022) { printk(KERN_ERR PFX "No Robo switch in managed mode found, phy_id = 0x%08x\n", phyid); - goto done; + err = -ENODEV; + goto err_put; } /* Get the device ID */ @@ -336,17 +340,16 @@ static int robo_probe(char *devname) robo_switch_reset(); err = robo_switch_enable(); if (err) - goto done; - err = 0; + goto err_put; 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); -done: - if (err) { - dev_put(robo.dev); - robo.dev = NULL; - } + return 0; +err_put: + dev_put(robo.dev); + robo.dev = NULL; +err_done: return err; } -- cgit v1.2.3 From a72556358d30103084e9ebf0561d68db5fca89a1 Mon Sep 17 00:00:00 2001 From: hauke Date: Wed, 13 Feb 2013 16:02:41 +0000 Subject: switch: reset switch before using it. git-svn-id: svn://svn.openwrt.org/openwrt/trunk@35579 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/switch/src/switch-robo.c | 72 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 2 deletions(-) (limited to 'package/switch/src/switch-robo.c') diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c index e33c30ec4..38aa9eff5 100644 --- a/package/switch/src/switch-robo.c +++ b/package/switch/src/switch-robo.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #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); } -- cgit v1.2.3 From 7e9ad0bcc3c9b3d83ae6424e5a68d2d32849a2d4 Mon Sep 17 00:00:00 2001 From: hauke Date: Wed, 13 Feb 2013 16:03:03 +0000 Subject: switch: the BCM5365 is a special switch and the BCM5350 or BCM5325 is the normal case. This makes it easier to compare this code with the code from the Broadcom SDK. git-svn-id: svn://svn.openwrt.org/openwrt/trunk@35580 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/switch/src/switch-robo.c | 73 ++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 40 deletions(-) (limited to 'package/switch/src/switch-robo.c') diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c index 38aa9eff5..9c78d8281 100644 --- a/package/switch/src/switch-robo.c +++ b/package/switch/src/switch-robo.c @@ -72,8 +72,8 @@ struct robo_switch { char *device; /* The device name string (ethX) */ u16 devid; /* ROBO_DEVICE_ID_53xx */ - bool is_5350; - u8 gmii; /* gigabit mii */ + bool is_5365; + bool gmii; /* gigabit mii */ int gpio_robo_reset; int gpio_lanports_enable; struct ifreq ifr; @@ -198,34 +198,22 @@ static void robo_write32(__u8 page, __u8 reg, __u32 val32) robo_reg(page, reg, REG_MII_ADDR_WRITE); } -/* checks that attached switch is 5325/5352/5354/5356/5357/53115 */ -static int robo_vlan5350(__u32 phyid) +/* checks that attached switch is 5365 */ +static bool robo_bcm5365(void) { /* set vlan access id to 15 and read it back */ __u16 val16 = 15; - robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16); + robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16); /* 5365 will refuse this as it does not have this reg */ - if (robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350) != val16) - return 0; - /* gigabit ? */ + return robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS) != val16; +} + +static bool robo_gmii(void) +{ if (mdio_read(0, ROBO_MII_STAT) & 0x0100) - robo.gmii = ((mdio_read(0, 0x0f) & 0xf000) != 0); - /* 53115 ? */ - if (robo.gmii && robo_read32(ROBO_STAT_PAGE, ROBO_LSA_IM_PORT) != 0) { - robo_write16(ROBO_ARLIO_PAGE, ROBO_VTBL_INDX_5395, val16); - robo_write16(ROBO_ARLIO_PAGE, ROBO_VTBL_ACCESS_5395, - (1 << 7) /* start */ | 1 /* read */); - if (robo_read16(ROBO_ARLIO_PAGE, ROBO_VTBL_ACCESS_5395) == 1 && - robo_read16(ROBO_ARLIO_PAGE, ROBO_VTBL_INDX_5395) == val16) - return 4; - } - /* dirty trick for 5356/5357 */ - if ((phyid & 0xfff0ffff ) == 0x5da00362 || - (phyid & 0xfff0ffff ) == 0x5e000362) - return 3; - /* 5325/5352/5354*/ - return 1; + return ((mdio_read(0, 0x0f) & 0xf000) != 0); + return false; } static int robo_switch_enable(void) @@ -392,7 +380,12 @@ static int robo_probe(char *devname) } if (!robo.devid) robo.devid = ROBO_DEVICE_ID_5325; /* Fake it */ - robo.is_5350 = robo_vlan5350(phyid); + if (robo.devid == ROBO_DEVICE_ID_5325) + robo.is_5365 = robo_bcm5365(); + else + robo.is_5365 = false; + + robo.gmii = robo_gmii(); robo_switch_reset(); err = robo_switch_enable(); @@ -400,7 +393,7 @@ static int robo_probe(char *devname) 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); + robo.is_5365 ? " It's a BCM5365." : "", devname); return 0; @@ -426,9 +419,9 @@ static int handle_vlan_port_read(void *driver, char *buf, int nr) val16 = (nr) /* vlan */ | (0 << 12) /* read */ | (1 << 13) /* enable */; - if (robo.is_5350) { + if (!robo.is_5365) { u32 val32; - robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16); + robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16); /* actual read */ val32 = robo_read32(ROBO_VLAN_PAGE, ROBO_VLAN_READ); if ((val32 & (1 << 20)) /* valid */) { @@ -448,7 +441,7 @@ static int handle_vlan_port_read(void *driver, char *buf, int nr) len += sprintf(buf + len, "\n"); } } else { - robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16); + robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5365, val16); /* actual read */ val16 = robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_READ); if ((val16 & (1 << 14)) /* valid */) { @@ -504,13 +497,13 @@ static int handle_vlan_port_write(void *driver, char *buf, int nr) } val16 = (nr) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */; - if (robo.is_5350) { - robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5350, - (1 << 20) /* valid */ | (c->untag << 6) | c->port); - robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16); - } else { - robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE, + if (robo.is_5365) { + robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5365, (1 << 14) /* valid */ | (c->untag << 7) | c->port); + robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5365, val16); + } else { + robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE, + (1 << 20) /* valid */ | (c->untag << 6) | c->port); robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16); } @@ -643,14 +636,14 @@ static int handle_reset(void *driver, char *buf, int nr) set_switch(0); /* reset vlans */ - for (j = 0; j <= ((robo.is_5350) ? VLAN_ID_MAX5350 : VLAN_ID_MAX); j++) { + for (j = 0; j <= ((robo.is_5365) ? VLAN_ID_MAX_5365 : VLAN_ID_MAX); j++) { /* write config now */ val16 = (j) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */; - if (robo.is_5350) - robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5350, 0); + if (robo.is_5365) + robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5365, 0); else - robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE, 0); - robo_write16(ROBO_VLAN_PAGE, robo.is_5350 ? ROBO_VLAN_TABLE_ACCESS_5350 : + robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE, 0); + robo_write16(ROBO_VLAN_PAGE, robo.is_5365 ? ROBO_VLAN_TABLE_ACCESS_5365 : ROBO_VLAN_TABLE_ACCESS, val16); } -- cgit v1.2.3 From 1e779318e345ed83a51915307ede3d1e578d1301 Mon Sep 17 00:00:00 2001 From: hauke Date: Wed, 13 Feb 2013 16:03:27 +0000 Subject: switch: reverse if else in handle_vlan_port_read() git-svn-id: svn://svn.openwrt.org/openwrt/trunk@35581 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/switch/src/switch-robo.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'package/switch/src/switch-robo.c') diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c index 9c78d8281..0ab2f6934 100644 --- a/package/switch/src/switch-robo.c +++ b/package/switch/src/switch-robo.c @@ -419,17 +419,17 @@ static int handle_vlan_port_read(void *driver, char *buf, int nr) val16 = (nr) /* vlan */ | (0 << 12) /* read */ | (1 << 13) /* enable */; - if (!robo.is_5365) { - u32 val32; - robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16); + if (robo.is_5365) { + robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5365, val16); /* actual read */ - val32 = robo_read32(ROBO_VLAN_PAGE, ROBO_VLAN_READ); - if ((val32 & (1 << 20)) /* valid */) { + val16 = robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_READ); + if ((val16 & (1 << 14)) /* valid */) { for (j = 0; j < 6; j++) { - if (val32 & (1 << j)) { + if (val16 & (1 << j)) { len += sprintf(buf + len, "%d", j); - if (val32 & (1 << (j + 6))) { - if (j == 5) buf[len++] = 'u'; + if (val16 & (1 << (j + 7))) { + if (j == 5) + buf[len++] = 'u'; } else { buf[len++] = 't'; if (robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1)) == nr) @@ -441,15 +441,17 @@ static int handle_vlan_port_read(void *driver, char *buf, int nr) len += sprintf(buf + len, "\n"); } } else { - robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5365, val16); + u32 val32; + robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16); /* actual read */ - val16 = robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_READ); - if ((val16 & (1 << 14)) /* valid */) { + val32 = robo_read32(ROBO_VLAN_PAGE, ROBO_VLAN_READ); + if ((val32 & (1 << 20)) /* valid */) { for (j = 0; j < 6; j++) { - if (val16 & (1 << j)) { + if (val32 & (1 << j)) { len += sprintf(buf + len, "%d", j); - if (val16 & (1 << (j + 7))) { - if (j == 5) buf[len++] = 'u'; + if (val32 & (1 << (j + 6))) { + if (j == 5) + buf[len++] = 'u'; } else { buf[len++] = 't'; if (robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1)) == nr) -- cgit v1.2.3 From 0d72440fc6085ca9144c0eebd3a6bd9d02e1448d Mon Sep 17 00:00:00 2001 From: hauke Date: Wed, 13 Feb 2013 16:03:47 +0000 Subject: switch: fix switches with more than 6 ports This is based on a patch by jcharest and the Broadcom SDK. git-svn-id: svn://svn.openwrt.org/openwrt/trunk@35582 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/switch/src/switch-robo.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'package/switch/src/switch-robo.c') diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c index 0ab2f6934..0e39c8fe5 100644 --- a/package/switch/src/switch-robo.c +++ b/package/switch/src/switch-robo.c @@ -78,7 +78,7 @@ struct robo_switch { int gpio_lanports_enable; struct ifreq ifr; struct net_device *dev; - unsigned char port[6]; + unsigned char port[9]; }; /* Currently we can only have one device in the system. */ @@ -308,9 +308,6 @@ static int robo_probe(char *devname) } robo.device = devname; - for (i = 0; i < 5; i++) - robo.port[i] = i; - robo.port[5] = 8; /* try access using MII ioctls - get phy address */ err = do_ioctl(SIOCGMIIPHY); @@ -386,6 +383,14 @@ static int robo_probe(char *devname) robo.is_5365 = false; robo.gmii = robo_gmii(); + if (robo.devid == ROBO_DEVICE_ID_5325) { + for (i = 0; i < 5; i++) + robo.port[i] = i; + } else { + for (i = 0; i < 8; i++) + robo.port[i] = i; + } + robo.port[i] = ROBO_IM_PORT_CTRL; robo_switch_reset(); err = robo_switch_enable(); -- cgit v1.2.3 From 5b0d941a4dab394beb8c93e138ae84641e7b9de7 Mon Sep 17 00:00:00 2001 From: hauke Date: Wed, 13 Feb 2013 16:04:18 +0000 Subject: switch: improve robo_switch_enable() This is based on a patch by jcharest and the Broadcom SDK. git-svn-id: svn://svn.openwrt.org/openwrt/trunk@35583 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/switch/src/switch-robo.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'package/switch/src/switch-robo.c') diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c index 0e39c8fe5..41f0c1826 100644 --- a/package/switch/src/switch-robo.c +++ b/package/switch/src/switch-robo.c @@ -237,10 +237,14 @@ static int robo_switch_enable(void) return -EBUSY; } + /* No spanning tree for unmanaged mode */ last_port = (robo.devid == ROBO_DEVICE_ID_5398) ? - ROBO_PORT6_CTRL : ROBO_PORT3_CTRL; - for (i = ROBO_PORT0_CTRL; i < last_port + 1; i++) + ROBO_PORT7_CTRL : ROBO_PORT4_CTRL; + for (i = ROBO_PORT0_CTRL; i <= last_port; i++) robo_write16(ROBO_CTRL_PAGE, i, 0); + + /* No spanning tree on IMP port too */ + robo_write16(ROBO_CTRL_PAGE, ROBO_IM_PORT_CTRL, 0); } #ifdef CONFIG_BCM47XX -- cgit v1.2.3 From f39bb781b8e91b9a592ca948da3a2590e0a95e8d Mon Sep 17 00:00:00 2001 From: hauke Date: Wed, 13 Feb 2013 16:04:50 +0000 Subject: switch: read and write vlan config from and to gigabit switches This patch makes it possible to read and write the vlan config from and to recent switchs. This is based on a patch by jcharest and the Broadcom SDK. git-svn-id: svn://svn.openwrt.org/openwrt/trunk@35584 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/switch/src/switch-robo.c | 135 ++++++++++++++++++++++++++++++--------- 1 file changed, 105 insertions(+), 30 deletions(-) (limited to 'package/switch/src/switch-robo.c') diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c index 41f0c1826..aaccdd9f6 100644 --- a/package/switch/src/switch-robo.c +++ b/package/switch/src/switch-robo.c @@ -74,6 +74,7 @@ struct robo_switch { u16 devid; /* ROBO_DEVICE_ID_53xx */ bool is_5365; bool gmii; /* gigabit mii */ + u8 corerev; int gpio_robo_reset; int gpio_lanports_enable; struct ifreq ifr; @@ -419,8 +420,7 @@ err_done: return err; } - -static int handle_vlan_port_read(void *driver, char *buf, int nr) +static int handle_vlan_port_read_old(switch_driver *d, char *buf, int nr) { __u16 val16; int len = 0; @@ -433,11 +433,11 @@ static int handle_vlan_port_read(void *driver, char *buf, int nr) /* actual read */ val16 = robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_READ); if ((val16 & (1 << 14)) /* valid */) { - for (j = 0; j < 6; j++) { + for (j = 0; j < d->ports; j++) { if (val16 & (1 << j)) { len += sprintf(buf + len, "%d", j); if (val16 & (1 << (j + 7))) { - if (j == 5) + if (j == d->cpuport) buf[len++] = 'u'; } else { buf[len++] = 't'; @@ -455,11 +455,11 @@ static int handle_vlan_port_read(void *driver, char *buf, int nr) /* actual read */ val32 = robo_read32(ROBO_VLAN_PAGE, ROBO_VLAN_READ); if ((val32 & (1 << 20)) /* valid */) { - for (j = 0; j < 6; j++) { + for (j = 0; j < d->ports; j++) { if (val32 & (1 << j)) { len += sprintf(buf + len, "%d", j); - if (val32 & (1 << (j + 6))) { - if (j == 5) + if (val32 & (1 << (j + d->ports))) { + if (j == d->cpuport) buf[len++] = 'u'; } else { buf[len++] = 't'; @@ -478,45 +478,120 @@ static int handle_vlan_port_read(void *driver, char *buf, int nr) return len; } -static int handle_vlan_port_write(void *driver, char *buf, int nr) +static int handle_vlan_port_read_new(switch_driver *d, char *buf, int nr) { - switch_driver *d = (switch_driver *) driver; - switch_vlan_config *c = switch_parse_vlan(d, buf); + __u8 vtbl_entry, vtbl_index, vtbl_access; + __u32 val32; + int len = 0; int j; - __u16 val16; - if (c == NULL) - return -EINVAL; + if ((robo.devid == ROBO_DEVICE_ID_5395) || + (robo.devid == ROBO_DEVICE_ID_53115)) { + vtbl_access = ROBO_VTBL_ACCESS_5395; + vtbl_index = ROBO_VTBL_INDX_5395; + vtbl_entry = ROBO_VTBL_ENTRY_5395; + } else { + vtbl_access = ROBO_VTBL_ACCESS; + vtbl_index = ROBO_VTBL_INDX; + vtbl_entry = ROBO_VTBL_ENTRY; + } + robo_write16(ROBO_ARLIO_PAGE, vtbl_index, nr); + robo_write16(ROBO_ARLIO_PAGE, vtbl_access, (1 << 7) | (1 << 0)); + val32 = robo_read32(ROBO_ARLIO_PAGE, vtbl_entry); for (j = 0; j < d->ports; j++) { - if ((c->untag | c->pvid) & (1 << j)) - /* change default vlan tag */ - robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1), nr); + if (val32 & (1 << j)) { + len += sprintf(buf + len, "%d", j); + if (val32 & (1 << (j + d->ports))) { + if (j == d->cpuport) + buf[len++] = 'u'; + } else { + buf[len++] = 't'; + if (robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1)) == nr) + buf[len++] = '*'; + } + buf[len++] = '\t'; + } } + len += sprintf(buf + len, "\n"); + buf[len] = '\0'; + return len; +} - /* write config now */ +static int handle_vlan_port_read(void *driver, char *buf, int nr) +{ + switch_driver *d = (switch_driver *) driver; - if (robo.devid != ROBO_DEVICE_ID_5325) { - __u8 regoff = ((robo.devid == ROBO_DEVICE_ID_5395) || - (robo.devid == ROBO_DEVICE_ID_53115)) ? 0x20 : 0; + if (robo.devid != ROBO_DEVICE_ID_5325) + return handle_vlan_port_read_new(d, buf, nr); + else + return handle_vlan_port_read_old(d, buf, nr); +} - robo_write32(ROBO_ARLIO_PAGE, 0x63 + regoff, (c->untag << 9) | c->port); - robo_write16(ROBO_ARLIO_PAGE, 0x61 + regoff, nr); - robo_write16(ROBO_ARLIO_PAGE, 0x60 + regoff, 1 << 7); - kfree(c); - return 0; - } +static void handle_vlan_port_write_old(switch_driver *d, switch_vlan_config *c, int nr) +{ + __u16 val16; + __u32 val32; + __u32 untag = ((c->untag & ~(1 << d->cpuport)) << d->ports); + /* write config now */ val16 = (nr) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */; if (robo.is_5365) { - robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5365, - (1 << 14) /* valid */ | (c->untag << 7) | c->port); + robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5365, + (1 << 14) /* valid */ | (untag << 1 ) | c->port); robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5365, val16); } else { - robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE, - (1 << 20) /* valid */ | (c->untag << 6) | c->port); + if (robo.corerev < 3) + val32 = (1 << 20) | ((nr >> 4) << 12) | untag | c->port; + else + val32 = (1 << 24) | (nr << 12) | untag | c->port; + robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE, val32); robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16); } +} + +static void handle_vlan_port_write_new(switch_driver *d, switch_vlan_config *c, int nr) +{ + __u8 vtbl_entry, vtbl_index, vtbl_access; + __u32 untag = ((c->untag & ~(1 << d->cpuport)) << d->ports); + + /* write config now */ + if ((robo.devid == ROBO_DEVICE_ID_5395) || + (robo.devid == ROBO_DEVICE_ID_53115)) { + vtbl_access = ROBO_VTBL_ACCESS_5395; + vtbl_index = ROBO_VTBL_INDX_5395; + vtbl_entry = ROBO_VTBL_ENTRY_5395; + } else { + vtbl_access = ROBO_VTBL_ACCESS; + vtbl_index = ROBO_VTBL_INDX; + vtbl_entry = ROBO_VTBL_ENTRY; + } + + robo_write32(ROBO_ARLIO_PAGE, vtbl_entry, untag | c->port); + robo_write16(ROBO_ARLIO_PAGE, vtbl_index, nr); + robo_write16(ROBO_ARLIO_PAGE, vtbl_access, 1 << 7); +} + +static int handle_vlan_port_write(void *driver, char *buf, int nr) +{ + switch_driver *d = (switch_driver *)driver; + switch_vlan_config *c = switch_parse_vlan(d, buf); + int j; + + if (c == NULL) + return -EINVAL; + + for (j = 0; j < d->ports; j++) { + if ((c->untag | c->pvid) & (1 << j)) { + /* change default vlan tag */ + robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1), nr); + } + } + + if (robo.devid != ROBO_DEVICE_ID_5325) + handle_vlan_port_write_new(d, c, nr); + else + handle_vlan_port_write_old(d, c, nr); kfree(c); return 0; -- cgit v1.2.3 From fe6514cec0f6d694ecfd8adb0d75ce3711f3d073 Mon Sep 17 00:00:00 2001 From: hauke Date: Wed, 13 Feb 2013 16:05:13 +0000 Subject: switch: resetting and enabling vlan write for gigabit switches This patch makes it possible to reset and enable writing vlans to recent switchs. This is based on a patch by jcharest and the Broadcom SDK. git-svn-id: svn://svn.openwrt.org/openwrt/trunk@35585 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/switch/src/switch-robo.c | 52 ++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 7 deletions(-) (limited to 'package/switch/src/switch-robo.c') diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c index aaccdd9f6..2aacc3666 100644 --- a/package/switch/src/switch-robo.c +++ b/package/switch/src/switch-robo.c @@ -693,12 +693,16 @@ static int handle_enable_vlan_read(void *driver, char *buf, int nr) static int handle_enable_vlan_write(void *driver, char *buf, int nr) { + __u16 val16; int disable = ((buf[0] != '1') ? 1 : 0); + val16 = robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0); robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0, disable ? 0 : - (1 << 7) /* 802.1Q VLAN */ | (3 << 5) /* mac check and hash */); + val16 | (1 << 7) /* 802.1Q VLAN */ | (3 << 5) /* mac check and hash */); + + val16 = robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL1); robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL1, disable ? 0 : - (robo.devid == ROBO_DEVICE_ID_5325 ? (1 << 1) : + val16 | (robo.devid == ROBO_DEVICE_ID_5325 ? (1 << 1) : 0) | (1 << 2) | (1 << 3)); /* RSV multicast */ if (robo.devid != ROBO_DEVICE_ID_5325) @@ -712,15 +716,11 @@ static int handle_enable_vlan_write(void *driver, char *buf, int nr) return 0; } -static int handle_reset(void *driver, char *buf, int nr) +static void handle_reset_old(switch_driver *d, char *buf, int nr) { - switch_driver *d = (switch_driver *) driver; int j; __u16 val16; - /* disable switching */ - set_switch(0); - /* reset vlans */ for (j = 0; j <= ((robo.is_5365) ? VLAN_ID_MAX_5365 : VLAN_ID_MAX); j++) { /* write config now */ @@ -733,6 +733,44 @@ static int handle_reset(void *driver, char *buf, int nr) ROBO_VLAN_TABLE_ACCESS, val16); } +} + +static void handle_reset_new(switch_driver *d, char *buf, int nr) +{ + int j; + __u8 vtbl_entry, vtbl_index, vtbl_access; + + if ((robo.devid == ROBO_DEVICE_ID_5395) || + (robo.devid == ROBO_DEVICE_ID_53115)) { + vtbl_access = ROBO_VTBL_ACCESS_5395; + vtbl_index = ROBO_VTBL_INDX_5395; + vtbl_entry = ROBO_VTBL_ENTRY_5395; + } else { + vtbl_access = ROBO_VTBL_ACCESS; + vtbl_index = ROBO_VTBL_INDX; + vtbl_entry = ROBO_VTBL_ENTRY; + } + + for (j = 0; j <= VLAN_ID_MAX; j++) { + /* write config now */ + robo_write32(ROBO_ARLIO_PAGE, vtbl_entry, 0); + robo_write16(ROBO_ARLIO_PAGE, vtbl_index, j); + robo_write16(ROBO_ARLIO_PAGE, vtbl_access, 1 << 7); + } +} + +static int handle_reset(void *driver, char *buf, int nr) +{ + int j; + switch_driver *d = (switch_driver *) driver; + + /* disable switching */ + set_switch(0); + + if (robo.devid != ROBO_DEVICE_ID_5325) + handle_reset_new(d, buf, nr); + else + handle_reset_old(d, buf, nr); /* reset ports to a known good state */ for (j = 0; j < d->ports; j++) { -- cgit v1.2.3 From ecb8ddded5785d75acc2b7639c30691a6ab10e04 Mon Sep 17 00:00:00 2001 From: hauke Date: Wed, 13 Feb 2013 16:05:32 +0000 Subject: switch: add support for BCM53125 git-svn-id: svn://svn.openwrt.org/openwrt/trunk@35586 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/switch/src/switch-robo.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'package/switch/src/switch-robo.c') diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c index 2aacc3666..57240a3fd 100644 --- a/package/switch/src/switch-robo.c +++ b/package/switch/src/switch-robo.c @@ -63,6 +63,7 @@ #define ROBO_DEVICE_ID_5397 0x97 #define ROBO_DEVICE_ID_5398 0x98 #define ROBO_DEVICE_ID_53115 0x3115 +#define ROBO_DEVICE_ID_53125 0x3125 /* Private et.o ioctls */ #define SIOCGETCPHYRD (SIOCDEVPRIVATE + 9) @@ -248,6 +249,13 @@ static int robo_switch_enable(void) robo_write16(ROBO_CTRL_PAGE, ROBO_IM_PORT_CTRL, 0); } + if (robo.devid == ROBO_DEVICE_ID_53125) { + /* Make IM port status link by default */ + val = robo_read16(ROBO_CTRL_PAGE, ROBO_PORT_OVERRIDE_CTRL) | 0xb1; + robo_write16(ROBO_CTRL_PAGE, ROBO_PORT_OVERRIDE_CTRL, val); + // TODO: init EEE feature + } + #ifdef CONFIG_BCM47XX /* WAN port LED, except for Netgear WGT634U */ if (bcm47xx_nvram_getenv("nvram_type", buf, sizeof(buf)) >= 0) { @@ -486,7 +494,8 @@ static int handle_vlan_port_read_new(switch_driver *d, char *buf, int nr) int j; if ((robo.devid == ROBO_DEVICE_ID_5395) || - (robo.devid == ROBO_DEVICE_ID_53115)) { + (robo.devid == ROBO_DEVICE_ID_53115) || + (robo.devid == ROBO_DEVICE_ID_53125)) { vtbl_access = ROBO_VTBL_ACCESS_5395; vtbl_index = ROBO_VTBL_INDX_5395; vtbl_entry = ROBO_VTBL_ENTRY_5395; @@ -557,7 +566,8 @@ static void handle_vlan_port_write_new(switch_driver *d, switch_vlan_config *c, /* write config now */ if ((robo.devid == ROBO_DEVICE_ID_5395) || - (robo.devid == ROBO_DEVICE_ID_53115)) { + (robo.devid == ROBO_DEVICE_ID_53115) || + (robo.devid == ROBO_DEVICE_ID_53125)) { vtbl_access = ROBO_VTBL_ACCESS_5395; vtbl_index = ROBO_VTBL_INDX_5395; vtbl_entry = ROBO_VTBL_ENTRY_5395; @@ -741,7 +751,8 @@ static void handle_reset_new(switch_driver *d, char *buf, int nr) __u8 vtbl_entry, vtbl_index, vtbl_access; if ((robo.devid == ROBO_DEVICE_ID_5395) || - (robo.devid == ROBO_DEVICE_ID_53115)) { + (robo.devid == ROBO_DEVICE_ID_53115) || + (robo.devid == ROBO_DEVICE_ID_53125)) { vtbl_access = ROBO_VTBL_ACCESS_5395; vtbl_index = ROBO_VTBL_INDX_5395; vtbl_entry = ROBO_VTBL_ENTRY_5395; -- cgit v1.2.3 From d8af1489e0e3cbeba49897e8f6dee1572295dd43 Mon Sep 17 00:00:00 2001 From: hauke Date: Thu, 14 Feb 2013 12:36:52 +0000 Subject: switch: export name of device found via /proc git-svn-id: svn://svn.openwrt.org/openwrt/trunk@35596 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/switch/src/switch-robo.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'package/switch/src/switch-robo.c') diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c index 57240a3fd..f7159729b 100644 --- a/package/switch/src/switch-robo.c +++ b/package/switch/src/switch-robo.c @@ -3,6 +3,7 @@ * * Copyright (C) 2005 Felix Fietkau * Copyright (C) 2008 Michael Buesch + * Copyright (C) 2013 Hauke Mehrtens * Based on 'robocfg' by Oleg I. Vdovikin * * This program is free software; you can redistribute it and/or @@ -40,7 +41,7 @@ #endif #define DRIVER_NAME "bcm53xx" -#define DRIVER_VERSION "0.02" +#define DRIVER_VERSION "0.03" #define PFX "roboswitch: " #define ROBO_PHY_ADDR 0x1E /* robo switch phy address */ @@ -862,6 +863,10 @@ static int __init robo_init(void) driver.ports = 9; driver.cpuport = 8; } + if (robo.is_5365) + snprintf(driver.dev_name, SWITCH_NAME_BUFSZ, "BCM5365"); + else + snprintf(driver.dev_name, SWITCH_NAME_BUFSZ, "BCM5%s%x", robo.devid & 0xff00 ? "" : "3", robo.devid); return switch_register_driver(&driver); } -- cgit v1.2.3