X-Git-Url: http://git.rohieb.name/openwrt.git/blobdiff_plain/dba3b610f25544c7e045b0b10464f51967f4c827..013e04a018a55287faff4ec9f5fe3305525e03cd:/openwrt/target/linux/package/switch/src/switch-adm.c?ds=sidebyside diff --git a/openwrt/target/linux/package/switch/src/switch-adm.c b/openwrt/target/linux/package/switch/src/switch-adm.c index 0b70a694c..919d685cb 100644 --- a/openwrt/target/linux/package/switch/src/switch-adm.c +++ b/openwrt/target/linux/package/switch/src/switch-adm.c @@ -32,11 +32,12 @@ #include "gpio.h" #define DRIVER_NAME "adm6996" +#define DRIVER_VERSION "0.01" -static int eecs = 2; -static int eesk = 3; -static int eedi = 5; -static int eerc = 6; +static int eecs = 0; +static int eesk = 0; +static int eedi = 0; +static int eerc = 0; static int force = 0; MODULE_AUTHOR("Felix Fietkau "); @@ -57,8 +58,35 @@ MODULE_PARM(force, "i"); #define adm_write16(cs, w) { __u16 val = hton16(w); adm_write(cs, (__u8 *)&val, sizeof(val)*8); } #define adm_write32(cs, i) { uint32 val = hton32(i); adm_write(cs, (__u8 *)&val, sizeof(val)*8); } +#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0) -extern int getintvar(char **vars, char *name); +#if defined(BCMGPIO2) || defined(BCMGPIO) +extern char *nvram_get(char *name); + +/* Return gpio pin number assigned to the named pin */ +/* +* Variable should be in format: +* +* gpio=pin_name +* +* 'def_pin' is returned if there is no such variable found. +*/ +static unsigned int getgpiopin(char *pin_name, unsigned int def_pin) +{ + char name[] = "gpioXXXX"; + char *val; + unsigned int pin; + + /* Go thru all possibilities till a match in pin name */ + for (pin = 0; pin < 16; pin ++) { + sprintf(name, "gpio%d", pin); + val = nvram_get(name); + if (val && !strcmp(val, pin_name)) + return pin; + } + return def_pin; +} +#endif static void adm_write(int cs, char *buf, unsigned int bits) @@ -240,7 +268,7 @@ static int port_conf[] = { 0x01, 0x03, 0x05, 0x07, 0x08, 0x09 }; /* Bits in VLAN port mapping */ static int vlan_ports[] = { 1 << 0, 1 << 2, 1 << 4, 1 << 6, 1 << 7, 1 << 8 }; -static int handle_vlan_port_read(char *buf, int nr) +static int handle_vlan_port_read(void *driver, char *buf, int nr) { int ports, i, c, len = 0; @@ -253,7 +281,16 @@ static int handle_vlan_port_read(char *buf, int nr) for (i = 0; i <= 5; i++) { if (ports & vlan_ports[i]) { c = adm_rreg(0, port_conf[i]); - len += sprintf(buf + len, (c & (1 << 4) ? "%dt\t" : (i == 5 ? "%du\t" : "%d\t")), i); + + len += sprintf(buf + len, "%d", i); + if (c & (1 << 4)) { + buf[len++] = 't'; + if (((c & (0xf << 10)) >> 10) == nr) + buf[len++] = '*'; + } else if (i == 5) + buf[len++] = 'u'; + + buf[len++] = '\t'; } } len += sprintf(buf + len, "\n"); @@ -261,30 +298,33 @@ static int handle_vlan_port_read(char *buf, int nr) return len; } -static int handle_vlan_port_write(char *buf, int nr) +static int handle_vlan_port_write(void *driver, char *buf, int nr) { - int i, c, ports; - int map = switch_parse_vlan(buf); + int i, cfg, ports; + switch_driver *d = (switch_driver *) driver; + switch_vlan_config *c = switch_parse_vlan(d, buf); - if (map == -1) + if (c == NULL) return -1; ports = adm_rreg(0, 0x13 + nr); - for (i = 0; i <= 5; i++) { - if (map & (1 << i)) { + for (i = 0; i < d->ports; i++) { + if (c->port & (1 << i)) { ports |= vlan_ports[i]; - c = adm_rreg(0, port_conf[i]); + cfg = adm_rreg(0, port_conf[i]); /* Tagging */ - if (map & (1 << (8 + i))) - c |= (1 << 4); + if (c->untag & (1 << i)) + cfg &= ~(1 << 4); else - c &= ~(1 << 4); - - c = (c & ~(0xf << 10)) | (nr << 10); + cfg |= (1 << 4); + + if ((c->untag | c->pvid) & (1 << i)) { + cfg = (cfg & ~(0xf << 10)) | (nr << 10); + } - adm_wreg(port_conf[i], (__u16) c); + adm_wreg(port_conf[i], (__u16) cfg); } else { ports &= ~(vlan_ports[i]); } @@ -294,12 +334,12 @@ static int handle_vlan_port_write(char *buf, int nr) return 0; } -static int handle_port_enable_read(char *buf, int nr) +static int handle_port_enable_read(void *driver, char *buf, int nr) { return sprintf(buf, "%d\n", ((adm_rreg(0, port_conf[nr]) & (1 << 5)) ? 0 : 1)); } -static int handle_port_enable_write(char *buf, int nr) +static int handle_port_enable_write(void *driver, char *buf, int nr) { int reg = adm_rreg(0, port_conf[nr]); @@ -313,7 +353,7 @@ static int handle_port_enable_write(char *buf, int nr) return 0; } -static int handle_port_media_read(char *buf, int nr) +static int handle_port_media_read(void *driver, char *buf, int nr) { int len; int media = 0; @@ -330,7 +370,7 @@ static int handle_port_media_read(char *buf, int nr) return len + sprintf(buf + len, "\n"); } -static int handle_port_media_write(char *buf, int nr) +static int handle_port_media_write(void *driver, char *buf, int nr) { int media = switch_parse_media(buf); int reg = adm_rreg(0, port_conf[nr]); @@ -351,12 +391,12 @@ static int handle_port_media_write(char *buf, int nr) return 0; } -static int handle_vlan_enable_read(char *buf, int nr) +static int handle_vlan_enable_read(void *driver, char *buf, int nr) { return sprintf(buf, "%d\n", ((adm_rreg(0, 0x11) & (1 << 5)) ? 1 : 0)); } -static int handle_vlan_enable_write(char *buf, int nr) +static int handle_vlan_enable_write(void *driver, char *buf, int nr) { int reg = adm_rreg(0, 0x11); @@ -370,9 +410,10 @@ static int handle_vlan_enable_write(char *buf, int nr) return 0; } -static int handle_reset(char *buf, int nr) +static int handle_reset(void *driver, char *buf, int nr) { int i; + u32 cfg; /* * Reset sequence: RC high->low(100ms)->high(30ms) @@ -381,30 +422,32 @@ static int handle_reset(char *buf, int nr) * reset logic therefore we must explicitly perform the * sequence in software. */ - /* Keep RC high for at least 20ms */ - adm_enout(eerc, eerc); - for (i = 0; i < 20; i ++) - udelay(1000); - /* Keep RC low for at least 100ms */ - adm_enout(eerc, 0); - for (i = 0; i < 100; i++) - udelay(1000); - /* Set default configuration */ - adm_enout((__u8)(eesk | eedi), eesk); - /* Keep RC high for at least 30ms */ - adm_enout(eerc, eerc); - for (i = 0; i < 30; i++) - udelay(1000); - /* Leave RC high and disable GPIO outputs */ - adm_disout((__u8)(eecs | eesk | eedi)); - - /* set up initial configuration for ports */ - for (i = 0; i <= 5; i++) { - int cfg = 0x8000 | /* Auto MDIX */ - (((i == 5) ? 1 : 0) << 4) | /* Tagging */ - 0xf; /* full duplex, 100Mbps, auto neg, flow ctrl */ - adm_wreg(port_conf[i], cfg); + if (eerc) { + /* Keep RC high for at least 20ms */ + adm_enout(eerc, eerc); + for (i = 0; i < 20; i ++) + udelay(1000); + /* Keep RC low for at least 100ms */ + adm_enout(eerc, 0); + for (i = 0; i < 100; i++) + udelay(1000); + /* Set default configuration */ + adm_enout((__u8)(eesk | eedi), eesk); + /* Keep RC high for at least 30ms */ + adm_enout(eerc, eerc); + for (i = 0; i < 30; i++) + udelay(1000); + /* Leave RC high and disable GPIO outputs */ + adm_disout((__u8)(eecs | eesk | eedi)); + } + + /* set up initial configuration for cpu port */ + cfg = (0x8000 | /* Auto MDIX */ + (0xf << 10) | /* PVID */ + (1 << 4) | /* Tagging */ + 0xf); /* full duplex, 100Mbps, auto neg, flow ctrl */ + adm_wreg(port_conf[5], cfg); /* vlan mode select register (0x11): vlan on, mac clone */ adm_wreg(0x11, 0xff30); @@ -412,7 +455,7 @@ static int handle_reset(char *buf, int nr) return 0; } -static int handle_registers(char *buf, int nr) +static int handle_registers(void *driver, char *buf, int nr) { int i, len = 0; @@ -423,7 +466,7 @@ static int handle_registers(char *buf, int nr) return len; } -static int handle_counters(char *buf, int nr) +static int handle_counters(void *driver, char *buf, int nr) { int i, len = 0; @@ -439,15 +482,35 @@ static int detect_adm() int ret = 0; #if defined(BCMGPIO2) || defined(BCMGPIO) -#ifdef LINUX_2_4 - int boardflags = getintvar(NULL, "boardflags"); -#else - extern int boardflags; -#endif - if ((boardflags & 0x80) || force) + int boardflags = atoi(nvram_get("boardflags")); + + if ((boardflags & 0x80) || force) { + ret = 1; + + eecs = getgpiopin("adm_eecs", 2); + eesk = getgpiopin("adm_eesk", 3); + eedi = getgpiopin("adm_eedi", 4); + eerc = getgpiopin("adm_rc", 0); + + } else if ((strcmp(nvram_get("boardtype") ?: "", "bcm94710dev") == 0) && + (strncmp(nvram_get("boardnum") ?: "", "42", 2) == 0)) { + /* WRT54G v1.1 hack */ + eecs = 2; + eesk = 3; + eedi = 5; + ret = 1; - else + } else printk("BFL_ENETADM not set in boardflags. Use force=1 to ignore.\n"); + + if (eecs) + eecs = (1 << eecs); + if (eesk) + eesk = (1 << eesk); + if (eedi) + eedi = (1 << eedi); + if (eerc) + eerc = (1 << eerc); #else ret = 1; #endif @@ -465,7 +528,7 @@ static int __init adm_init() {NULL, NULL, NULL} }; switch_config port[] = { - {"enabled", handle_port_enable_read, handle_port_enable_write}, + {"enable", handle_port_enable_read, handle_port_enable_write}, {"media", handle_port_media_read, handle_port_media_write}, {NULL, NULL, NULL} }; @@ -475,17 +538,16 @@ static int __init adm_init() }; switch_driver driver = { name: DRIVER_NAME, + version: DRIVER_VERSION, + interface: "eth0", ports: 6, + cpuport: 5, vlans: 16, driver_handlers: cfg, port_handlers: port, vlan_handlers: vlan, }; - eecs = (1 << eecs); - eesk = (1 << eesk); - eedi = (1 << eedi); - if (!detect_adm()) return -ENODEV;