diff options
| -rw-r--r-- | package/broadcom-diag/src/diag.c | 120 | ||||
| -rw-r--r-- | package/broadcom-diag/src/diag.h | 1 | ||||
| -rw-r--r-- | package/broadcom-diag/src/gpio.h | 6 | ||||
| -rw-r--r-- | target/linux/brcm47xx/image/Makefile | 1 | 
4 files changed, 110 insertions, 18 deletions
| diff --git a/package/broadcom-diag/src/diag.c b/package/broadcom-diag/src/diag.c index 168f81d77..ccbaee2d2 100644 --- a/package/broadcom-diag/src/diag.c +++ b/package/broadcom-diag/src/diag.c @@ -123,6 +123,7 @@ enum {  	WNR834BV1,  	WNR834BV2,  	WNDR3400V1, +	WNDR3700V3,  	/* Trendware */  	TEW411BRPP, @@ -927,6 +928,28 @@ static struct platform_t __initdata platforms[] = {  			{ .name = "usb",	.gpio = 1 << 2, .polarity = REVERSE },  		},  	}, +	[WNDR3700V3] = { +		.name		= "Netgear WNDR3700 V3", +		.buttons	= { +			/* { .name = "usb",	.gpio = 1 << 1 }, */ /* this button doesn't seem to exist. */ +			{ .name = "wlan",	.gpio = 1 << 2 }, +			{ .name = "reset",	.gpio = 1 << 3 }, +			{ .name = "wps",	.gpio = 1 << 4 }, +			/* { .name = "switch",	.gpio = 1 << 5 },*/	/* nvram get gpio5=robo_reset */ +		}, +		.leds		= { +			{ .name = "power",	.gpio = (1 << 0) | GPIO_TYPE_SHIFT, .polarity = REVERSE }, +			{ .name = "diag",	.gpio = (1 << 1) | GPIO_TYPE_SHIFT, .polarity = REVERSE }, +			/* WAN LED doesn't respond to GPIO control. The switch is probably driving it. +			 * { .name = "wan",	.gpio = (1 << 2) | GPIO_TYPE_SHIFT, .polarity = REVERSE }, +			 */ +			{ .name = "wlan2g",	.gpio = (1 << 3) | GPIO_TYPE_SHIFT, .polarity = REVERSE }, +			{ .name = "wlan5g",	.gpio = (1 << 4) | GPIO_TYPE_SHIFT, .polarity = REVERSE }, +			{ .name = "usb",	.gpio = (1 << 5) | GPIO_TYPE_SHIFT, .polarity = REVERSE }, +			{ .name = "wps",	.gpio = (1 << 6) | GPIO_TYPE_SHIFT, .polarity = REVERSE }, +			{ .name = "wlan",	.gpio = (1 << 7) | GPIO_TYPE_SHIFT, .polarity = REVERSE }, +		}, +	},  	/* Trendware */  	[TEW411BRPP] = {  		.name           = "Trendware TEW411BRP+", @@ -1308,6 +1331,8 @@ static struct platform_t __init *platform_detect(void)  		return &platforms[WR850GV2V3];  	case BCM47XX_BOARD_NETGEAR_WNDR3400V1:  		return &platforms[WNDR3400V1]; +	case BCM47XX_BOARD_NETGEAR_WNDR3700V3: +		return &platforms[WNDR3700V3];  	case BCM47XX_BOARD_UNKNOWN:  	case BCM47XX_BOARD_NON:  		printk(MODULE_NAME ": unknown board found, try legacy detect\n"); @@ -1476,13 +1501,23 @@ static void register_leds(struct led_t *l)  		if (l->gpio & gpiomask)  			continue; -		if (l->gpio & GPIO_TYPE_EXTIF) { +		switch (l->gpio & GPIO_TYPE_MASK) { +		case GPIO_TYPE_EXTIF:  			l->state = 0;  			set_led_extif(l); -		} else { +			break; +		case GPIO_TYPE_SHIFT: +			mask |= (SHIFTREG_DATA | SHIFTREG_CLK); +			oe_mask |= (SHIFTREG_DATA | SHIFTREG_CLK); +			l->state = (l->polarity != NORMAL); +			set_led_shift(l); +			break; +		case GPIO_TYPE_NORMAL: +		default:  			if (l->polarity != INPUT) oe_mask |= l->gpio;  			mask |= l->gpio;  			val |= (l->polarity == NORMAL)?0:l->gpio; +			break;  		}  		if (l->polarity == INPUT) continue; @@ -1518,20 +1553,68 @@ static void set_led_extif(struct led_t *led)  		*addr;  } +/* + * This should be extended to allow the platform to specify the pins and width + * of the shift register. They're hardcoded for now because only the WNDR3700v3 + * uses it. + */ +static void shiftreg_output(unsigned int val) +{ +	unsigned int mask; + +	bcm47xx_gpio_out(SHIFTREG_DATA, SHIFTREG_DATA); /* init off, pull high */ +	bcm47xx_gpio_out(SHIFTREG_CLK, 0); /* init reset */ + +	/* shift 8 times */ +	for(mask = 1 << (SHIFTREG_MAX_BITS-1); mask; mask >>= 1) +	{ +		bcm47xx_gpio_out(SHIFTREG_DATA, (val & mask) ? SHIFTREG_DATA : 0); +		bcm47xx_gpio_out(SHIFTREG_CLK, SHIFTREG_CLK); /* pull high to trigger */ +		bcm47xx_gpio_out(SHIFTREG_CLK, 0); /* reset to low */ +	} +} + +static void set_led_shift(struct led_t *led) +{ +	static u32	shiftreg = 0; +	u32			old = shiftreg; +	u32			pin = (led->gpio & ~GPIO_TYPE_MASK); + +	if (led->state) { +		shiftreg |= pin; +	} else { +		shiftreg &= ~pin; +	} + +	/* Clock the bits out. */ +	if (shiftreg != old) { +		shiftreg_output(shiftreg); +	} +} + +  static void led_flash(unsigned long dummy) {  	struct led_t *l;  	u32 mask = 0;  	u8 extif_blink = 0;  	for (l = platform.leds; l->name; l++) { -		if (l->flash) { -			if (l->gpio & GPIO_TYPE_EXTIF) { -				extif_blink = 1; -				l->state = !l->state; -				set_led_extif(l); -			} else { -				mask |= l->gpio; -			} +		if (!l->flash) continue; +		switch (l->gpio & GPIO_TYPE_MASK) { +		case GPIO_TYPE_EXTIF: +			extif_blink = 1; +			l->state = !l->state; +			set_led_extif(l); +			break; +		case GPIO_TYPE_SHIFT: +			extif_blink = 1; +			l->state = !l->state; +			set_led_shift(l); +			break; +		case GPIO_TYPE_NORMAL: +		default: +			mask |= l->gpio; +			break;  		}  	} @@ -1562,16 +1645,14 @@ static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t  		switch (handler->type) {  			case PROC_LED: {  				struct led_t * led = (struct led_t *) handler->ptr; +				u8 p = (led->polarity == NORMAL ? 0 : 1);  				if (led->flash) {  					len = sprintf(page, "f\n"); +				} else if ((led->gpio & GPIO_TYPE_MASK) != GPIO_TYPE_NORMAL) { +					len = sprintf(page, "%d\n", ((led->state ^ p) ? 1 : 0));  				} else { -					if (led->gpio & GPIO_TYPE_EXTIF) { -						len = sprintf(page, "%d\n", led->state); -					} else { -						u32 in = (bcm47xx_gpio_in(~0) & led->gpio ? 1 : 0); -						u8 p = (led->polarity == NORMAL ? 0 : 1); -						len = sprintf(page, "%d\n", ((in ^ p) ? 1 : 0)); -					} +					u32 in = (bcm47xx_gpio_in(~0) & led->gpio ? 1 : 0); +					len = sprintf(page, "%d\n", ((in ^ p) ? 1 : 0));  				}  				break;  			} @@ -1628,9 +1709,12 @@ static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count,  					led_flash(0);  				} else {  					led->flash = 0; -					if (led->gpio & GPIO_TYPE_EXTIF) { +					if ((led->gpio & GPIO_TYPE_MASK) == GPIO_TYPE_EXTIF) {  						led->state = p ^ ((page[0] == '1') ? 1 : 0);  						set_led_extif(led); +					} else if ((led->gpio & GPIO_TYPE_MASK) == GPIO_TYPE_SHIFT) { +						led->state = p ^ ((page[0] == '1') ? 1 : 0); +						set_led_shift(led);  					} else {  						bcm47xx_gpio_outen(led->gpio, led->gpio);  						bcm47xx_gpio_control(led->gpio, 0); diff --git a/package/broadcom-diag/src/diag.h b/package/broadcom-diag/src/diag.h index 698c37651..d9b5b006f 100644 --- a/package/broadcom-diag/src/diag.h +++ b/package/broadcom-diag/src/diag.h @@ -104,6 +104,7 @@ static void register_leds(struct led_t *l);  static void unregister_leds(struct led_t *l);  static void set_led_extif(struct led_t *led); +static void set_led_shift(struct led_t *led);  static void led_flash(unsigned long dummy);  /* 2.4 compatibility */ diff --git a/package/broadcom-diag/src/gpio.h b/package/broadcom-diag/src/gpio.h index d0e3e06c8..8bd3fe02f 100644 --- a/package/broadcom-diag/src/gpio.h +++ b/package/broadcom-diag/src/gpio.h @@ -9,8 +9,14 @@  #define EXTIF_ADDR 0x1f000000  #define EXTIF_UART (EXTIF_ADDR + 0x00800000) +/* GPIO pins driving LEDs through a shift register */ +#define SHIFTREG_DATA		(1 << 6) +#define SHIFTREG_CLK		(1 << 7) +#define SHIFTREG_MAX_BITS	8 +  #define GPIO_TYPE_NORMAL	(0x0 << 24)  #define GPIO_TYPE_EXTIF 	(0x1 << 24) +#define GPIO_TYPE_SHIFT		(0x2 << 24)  #define GPIO_TYPE_MASK  	(0xf << 24)  #endif /* __DIAG_GPIO_H */ diff --git a/target/linux/brcm47xx/image/Makefile b/target/linux/brcm47xx/image/Makefile index 4043613c7..09109573f 100644 --- a/target/linux/brcm47xx/image/Makefile +++ b/target/linux/brcm47xx/image/Makefile @@ -140,6 +140,7 @@ define Image/Build  	$(call Image/Build/Chk,$(1),wndr3400_v1,U12H155T00_NETGEAR,2,$(patsubst jffs2-%,jffs2,$(1)))  	$(call Image/Build/Chk,$(1),wndr3400_v2,U12H187T00_NETGEAR,2,$(patsubst jffs2-%,jffs2,$(1)))  #	$(call Image/Build/Chk,$(1),wndr3400_vcna,U12H155T01_NETGEAR,2,$(patsubst jffs2-%,jffs2,$(1))) +	$(call Image/Build/Chk,$(1),wndr3700_v3,U12H194T00_NETGEAR,2,$(patsubst jffs2-%,jffs2,$(1)))  	$(call Image/Build/Chk,$(1),wndr4000,U12H181T00_NETGEAR,2,$(patsubst jffs2-%,jffs2,$(1)))  	$(call Image/Build/Chk,$(1),wnr834b_v2,U12H081T00_NETGEAR,2,$(patsubst jffs2-%,jffs2,$(1)))  	$(call Image/Build/Chk,$(1),wnr2000v2,U12H114T00_NETGEAR,2,$(patsubst jffs2-%,jffs2,$(1))) | 
