diff options
| -rw-r--r-- | package/broadcom-diag/src/diag.c | 544 | ||||
| -rw-r--r-- | package/broadcom-diag/src/diag.h | 125 | ||||
| -rw-r--r-- | package/broadcom-diag/src/gpio.h | 78 | 
3 files changed, 417 insertions, 330 deletions
| diff --git a/package/broadcom-diag/src/diag.c b/package/broadcom-diag/src/diag.c index e0b08be3d..7c6e303fc 100644 --- a/package/broadcom-diag/src/diag.c +++ b/package/broadcom-diag/src/diag.c @@ -18,7 +18,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.   * - * $Id$ + * $Id:$   */  #include <linux/module.h>  #include <linux/pci.h> @@ -37,79 +37,15 @@  #define INIT_WORK INIT_TQUEUE  #define schedule_work schedule_task  #define work_struct tq_struct -#define sbh bcm947xx_sbh -#define sbh_lock bcm947xx_sbh_lock  #endif -#include <typedefs.h> -#include <osl.h> -#include <bcmdevs.h> -#include <sbutils.h> -#include <sbconfig.h> -#include <sbchipc.h> -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -#include <sbmips.h> -#else -#include <hndcpu.h> -#endif - -#define MODULE_NAME "diag" - -#define MAX_GPIO 8 -#define FLASH_TIME HZ/6 - -#define EXTIF_ADDR 0x1f000000 -#define EXTIF_UART (EXTIF_ADDR + 0x00800000) - -/* For LEDs */ -#define GPIO_TYPE_NORMAL	(0x0 << 24) -#define GPIO_TYPE_EXTIF 	(0x1 << 24) -#define GPIO_TYPE_MASK  	(0xf << 24) +#include "gpio.h" +#include "diag.h" +#define getvar(str) (nvram_get(str)?:"")  static unsigned int gpiomask = 0;  module_param(gpiomask, int, 0644); -enum polarity_t { -	REVERSE = 0, -	NORMAL = 1, -}; - -enum { -	PROC_BUTTON, -	PROC_LED, -	PROC_MODEL, -	PROC_GPIOMASK -}; - -struct prochandler_t { -	int type; -	void *ptr; -}; - -struct button_t { -	struct prochandler_t proc; -	char *name; -	u16 gpio; -	u8 polarity; -	u8 pressed; -	unsigned long seen; -}; - -struct led_t { -	struct prochandler_t proc; -	char *name; -	u32 gpio; -	u8 polarity; -	u8 flash; -	u8 state; -}; - -struct platform_t { -	char *name; -	struct button_t buttons[MAX_GPIO]; -	struct led_t leds[MAX_GPIO]; -}; -  enum {  	/* Linksys */  	WAP54GV1, @@ -149,13 +85,13 @@ enum {  	/* Motorola */  	WE800G,  	WR850GV1, -	WR850GV2, +	WR850GV2V3,  	/* Belkin */  	BELKIN_UNKNOWN,  }; -static struct platform_t platforms[] = { +static struct platform_t __initdata platforms[] = {  	/* Linksys */  	[WAP54GV1] = {  		.name		= "Linksys WAP54G V1", @@ -190,7 +126,7 @@ static struct platform_t platforms[] = {  		},  	},  	[WRT54G] = { -		.name		= "Linksys WRT54G*", +		.name		= "Linksys WRT54G/GS/GL",  		.buttons	= {  			{ .name = "reset",	.gpio = 1 << 6 },  			{ .name = "ses",	.gpio = 1 << 4 }, @@ -291,12 +227,14 @@ static struct platform_t platforms[] = {  		.name		= "Buffalo WHR-G54S",  		.buttons	= {  			{ .name = "reset",	.gpio = 1 << 4 }, +			{ .name = "bridge",	.gpio = 1 << 5 },  			{ .name = "ses",	.gpio = 1 << 0 },  		},  		.leds		= { -			{ .name = "diag",	.gpio = 1 << 1, .polarity = REVERSE }, +			{ .name = "diag",	.gpio = 1 << 7, .polarity = REVERSE },  			{ .name = "internal",	.gpio = 1 << 3, .polarity = REVERSE },  			{ .name = "ses",	.gpio = 1 << 6, .polarity = REVERSE }, +			{ .name = "bridge",	.gpio = 1 << 1, .polarity = REVERSE },  		},  	},  	[WBR2_G54] = { @@ -422,21 +360,21 @@ static struct platform_t platforms[] = {  		.leds		= {  			{ .name = "power",	.gpio = 1 << 4, .polarity = NORMAL },  			{ .name = "diag",	.gpio = 1 << 3, .polarity = REVERSE }, -			{ .name = "modem",	.gpio = 1 << 6, .polarity = NORMAL }, +			{ .name = "dmz",	.gpio = 1 << 6, .polarity = NORMAL },  			{ .name = "wlan_red",	.gpio = 1 << 5, .polarity = REVERSE },  			{ .name = "wlan_green",	.gpio = 1 << 7, .polarity = REVERSE },  		},  	}, -	[WR850GV2] = { -		.name		= "Motorola WR850G V2", +	[WR850GV2V3] = { +		.name		= "Motorola WR850G V2/V3",  		.buttons	= {  			{ .name = "reset",	.gpio = 1 << 5 },  		},  		.leds		= { -			{ .name = "diag",	.gpio = 1 << 1, .polarity = REVERSE }, -			{ .name = "wlan",	.gpio = 1 << 0, .polarity = NORMAL }, -			{ .name = "modem_green",.gpio = 1 << 6, .polarity = REVERSE }, -			{ .name = "modem_red",	.gpio = 1 << 7, .polarity = REVERSE }, +			{ .name = "power",	.gpio = 1 << 1, .polarity = NORMAL }, +			{ .name = "wlan",	.gpio = 1 << 0, .polarity = REVERSE }, +			{ .name = "dmz",	.gpio = 1 << 6, .polarity = REVERSE }, +			{ .name = "diag",	.gpio = 1 << 7, .polarity = REVERSE },  		},  	},  	/* Belkin */ @@ -454,25 +392,6 @@ static struct platform_t platforms[] = {  	},  }; -extern void *sbh; -extern spinlock_t sbh_lock; -extern char *nvram_get(char *str); - -static struct proc_dir_entry *diag, *leds; -static struct platform_t platform; -static void led_flash(unsigned long dummy); - -#define getvar(str) (nvram_get(str)?:"") - -static void set_led_extif(struct led_t *led) -{ -	volatile u8 *addr = (volatile u8 *) KSEG1ADDR(EXTIF_UART) + (led->gpio & ~GPIO_TYPE_MASK); -	if (led->state) -		*addr = 0xFF; -	else -		*addr; -} -  static struct platform_t __init *platform_detect(void)  {  	char *boardnum, *boardtype, *buf; @@ -505,7 +424,7 @@ static struct platform_t __init *platform_detect(void)  		if (!strncmp(boardtype, "bcm94710dev", 11)) {  			if (!strcmp(boardnum, "42"))  				return &platforms[WRT54GV1]; -			if (simple_strtoul(boardnum, NULL, 9) == 2) +			if (simple_strtoul(boardnum, NULL, 0) == 2)  				return &platforms[WAP54GV1];  		}  		if (!strncmp(getvar("hardware_version"), "WL500-", 6)) @@ -513,10 +432,10 @@ static struct platform_t __init *platform_detect(void)  		if (!strncmp(getvar("hardware_version"), "WL300-", 6)) {  			/* Either WL-300g or WL-HDD, do more extensive checks */  			if ((simple_strtoul(getvar("et0phyaddr"), NULL, 0) == 0) && -				(simple_strtoul(getvar("et1phyaddr"), NULL, 9) == 1)) +				(simple_strtoul(getvar("et1phyaddr"), NULL, 0) == 1))  				return &platforms[WLHDD];  			if ((simple_strtoul(getvar("et0phyaddr"), NULL, 0) == 0) && -				(simple_strtoul(getvar("et1phyaddr"), NULL, 9) == 10)) +				(simple_strtoul(getvar("et1phyaddr"), NULL, 0) == 10))  				return &platforms[WL300G];  		} @@ -554,21 +473,173 @@ static struct platform_t __init *platform_detect(void)  			return &platforms[BUFFALO_UNKNOWN];  	} -	if (!strcmp(getvar("CFEver"), "MotoWRv203")) -		return &platforms[WR850GV2]; + +	if (!strcmp(getvar("CFEver"), "MotoWRv203") || +		!strcmp(getvar("MOTO_BOARD_TYPE"), "WR_FEM1")) { + +		return &platforms[WR850GV2V3]; +	}  	/* not found */  	return NULL;  } -static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos); -static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, void *data); -static struct file_operations diag_proc_fops = { -	read: diag_proc_read, -	write: diag_proc_write -}; +static void register_buttons(struct button_t *b) +{ +	for (; b->name; b++) +		platform.button_mask |= b->gpio; + +	platform.button_mask &= ~gpiomask; +	gpio_outen(platform.button_mask, 0); +	gpio_control(platform.button_mask, 0); +	platform.button_polarity = gpio_in() & platform.button_mask; +	gpio_intpolarity(platform.button_mask, platform.button_polarity); +	gpio_intmask(platform.button_mask, platform.button_mask); +	gpio_set_irqenable(1, button_handler); +} + +static void unregister_buttons(struct button_t *b) +{ +	gpio_intmask(platform.button_mask, 0); + +	gpio_set_irqenable(0, button_handler); +} + +static void hotplug_button(struct event_t *event) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +	call_usermodehelper (event->argv[0], event->argv, event->envp, 1); +#else +	call_usermodehelper (event->argv[0], event->argv, event->envp); +#endif +	kfree(event); +} + +static irqreturn_t button_handler(int irq, void *dev_id, struct pt_regs *regs) +{ +	struct button_t *b; +	u32 in, changed; + +	in = gpio_in() & platform.button_mask; +	gpio_intpolarity(platform.button_mask, in); +	changed = platform.button_polarity ^ in; +	platform.button_polarity = in; + +	for (b = platform.buttons; b->name; b++) {  +		struct event_t *event; + +		if (!(b->gpio & changed)) continue; + +		b->pressed ^= 1; + +		if ((event = (struct event_t *)kmalloc (sizeof(struct event_t), GFP_ATOMIC))) { +			int i; +			char *scratch = event->buf; + +			i = 0; +			event->argv[i++] = hotplug_path; +			event->argv[i++] = "button"; +			event->argv[i] = 0; + +			i = 0; +			event->envp[i++] = "HOME=/"; +			event->envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; +			event->envp[i++] = scratch; +			scratch += sprintf (scratch, "ACTION=%s", b->pressed?"pressed":"released") + 1; +			event->envp[i++] = scratch; +			scratch += sprintf (scratch, "BUTTON=%s", b->name) + 1; +			event->envp[i++] = scratch; +			scratch += sprintf (scratch, "SEEN=%ld", (jiffies - b->seen)/HZ) + 1; +			event->envp[i] = 0; + +			INIT_WORK(&event->wq, (void *)(void *)hotplug_button, (void *)event); +			schedule_work(&event->wq); +		} + +		b->seen = jiffies; +	} +	return IRQ_HANDLED; +} + +static void register_leds(struct led_t *l) +{ +	struct proc_dir_entry *p; +	u32 mask = 0; +	u32 val = 0; + +	leds = proc_mkdir("led", diag); +	if (!leds)  +		return; + +	for(; l->name; l++) { +		if (l->gpio & gpiomask) +			continue; +	 +		if (l->gpio & GPIO_TYPE_EXTIF) { +			l->state = 0; +			set_led_extif(l); +		} else { +			mask |= l->gpio; +			val |= (l->polarity == NORMAL)?0:l->gpio; +		} + +		if ((p = create_proc_entry(l->name, S_IRUSR, leds))) { +			l->proc.type = PROC_LED; +			l->proc.ptr = l; +			p->data = (void *) &l->proc; +			p->proc_fops = &diag_proc_fops; +		} +	} + +	gpio_outen(mask, mask); +	gpio_control(mask, 0); +	gpio_out(mask, val); +} + +static void unregister_leds(struct led_t *l) +{ +	for(; l->name; l++) +		remove_proc_entry(l->name, leds); + +	remove_proc_entry("led", diag); +} + +static void set_led_extif(struct led_t *led) +{ +	gpio_set_extif(led->gpio, led->state); +} + +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; +			} +		} +	} + +	mask &= ~gpiomask; +	if (mask) { +		u32 val = ~gpio_in(); + +		gpio_outen(mask, mask); +		gpio_control(mask, 0); +		gpio_out(mask, val); +	} +	if (mask || extif_blink) { +		mod_timer(&led_timer, jiffies + FLASH_TIME); +	} +}  static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos)  { @@ -595,8 +666,8 @@ static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t  					if (led->gpio & GPIO_TYPE_EXTIF) {  						len = sprintf(page, "%d\n", led->state);  					} else { -						int in = (sb_gpioin(sbh) & led->gpio ? 1 : 0); -						int p = (led->polarity == NORMAL ? 0 : 1); +						u32 in = (gpio_in() & led->gpio ? 1 : 0); +						u8 p = (led->polarity == NORMAL ? 0 : 1);  						len = sprintf(page, "%d\n", ((in ^ p) ? 1 : 0));  					}  				} @@ -606,7 +677,7 @@ static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t  				len = sprintf(page, "%s\n", platform.name);  				break;  			case PROC_GPIOMASK: -				len = sprintf(page, "%d\n", gpiomask); +				len = sprintf(page, "0x%04x\n", gpiomask);  				break;  		}  	} @@ -627,7 +698,7 @@ static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t  } -static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, void *data) +static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, loff_t *ppos)  {  #ifdef LINUX_2_4  	struct inode *inode = file->f_dentry->d_inode; @@ -654,9 +725,6 @@ static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count,  				struct led_t *led = (struct led_t *) handler->ptr;  				int p = (led->polarity == NORMAL ? 0 : 1); -				if (!(led->gpio & GPIO_TYPE_EXTIF) && (led->gpio & gpiomask)) -					break; -  				if (page[0] == 'f') {  					led->flash = 1;  					led_flash(0); @@ -666,15 +734,25 @@ static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count,  						led->state = p ^ ((page[0] == '1') ? 1 : 0);  						set_led_extif(led);  					} else { -						sb_gpioouten(sbh, led->gpio, led->gpio, GPIO_DRV_PRIORITY); -						sb_gpiocontrol(sbh, led->gpio, 0, GPIO_DRV_PRIORITY); -						sb_gpioout(sbh, led->gpio, ((p ^ (page[0] == '1')) ? led->gpio : 0), GPIO_DRV_PRIORITY); +						gpio_outen(led->gpio, led->gpio); +						gpio_control(led->gpio, 0); +						gpio_out(led->gpio, ((p ^ (page[0] == '1')) ? led->gpio : 0));  					}  				}  				break;  			}  			case PROC_GPIOMASK: -				gpiomask = simple_strtoul(page, NULL, 16); +				gpiomask = simple_strtoul(page, NULL, 0); + +				if (platform.buttons) { +					unregister_buttons(platform.buttons); +					register_buttons(platform.buttons); +				} + +				if (platform.leds) { +					unregister_leds(platform.leds); +					register_leds(platform.leds); +				}  				break;  		}  		ret = count; @@ -684,216 +762,6 @@ static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count,  	return ret;  } -struct event_t { -	struct work_struct tq; -	char buf[256]; -	char *argv[3]; -	char *envp[6]; -}; - -static void hotplug_button(struct event_t *event) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -	call_usermodehelper (event->argv[0], event->argv, event->envp, 1); -#else -	call_usermodehelper (event->argv[0], event->argv, event->envp); -#endif -	kfree(event); -} - -static void set_irqenable(int enabled) -{ -	unsigned int coreidx; -	unsigned long flags; -	chipcregs_t *cc; - -	spin_lock_irqsave(sbh_lock, flags); -	coreidx = sb_coreidx(sbh); -	if ((cc = sb_setcore(sbh, SB_CC, 0))) { -		int intmask; - -		intmask = readl(&cc->intmask); -		if (enabled) -			intmask |= CI_GPIO; -		else -			intmask &= ~CI_GPIO; -		writel(intmask, &cc->intmask); -	} -	sb_setcoreidx(sbh, coreidx); -	spin_unlock_irqrestore(sbh_lock, flags); -} - - -static irqreturn_t button_handler(int irq, void *dev_id, struct pt_regs *regs) -{ -	struct button_t *b; -	int in = sb_gpioin(sbh); -	struct event_t *event; - -	set_irqenable(0); -	for (b = platform.buttons; b->name; b++) {  -		if (b->gpio & gpiomask) -			continue; - -		if (b->polarity != (in & b->gpio)) { -			b->pressed ^= 1; - -			if ((event = (struct event_t *)kmalloc (sizeof(struct event_t), GFP_ATOMIC))) { -				int i; -				char *scratch = event->buf; - -				i = 0; -				event->argv[i++] = hotplug_path; -				event->argv[i++] = "button"; -				event->argv[i] = 0; - -				i = 0; -				event->envp[i++] = "HOME=/"; -				event->envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; -				event->envp[i++] = scratch; -				scratch += sprintf (scratch, "ACTION=%s", b->pressed?"pressed":"released") + 1; -				event->envp[i++] = scratch; -				scratch += sprintf (scratch, "BUTTON=%s", b->name) + 1; -				event->envp[i++] = scratch; -				scratch += sprintf (scratch, "SEEN=%ld", (jiffies - b->seen)/HZ) + 1; -				event->envp[i] = 0; - -				INIT_WORK(&event->tq, (void *)(void *)hotplug_button, (void *)event); -				schedule_work(&event->tq); -			} - -			b->seen = jiffies; -			b->polarity ^= b->gpio; -			sb_gpiointpolarity(sbh, b->gpio, b->polarity, GPIO_DRV_PRIORITY); -		} -	} -	set_irqenable(1); -	return IRQ_HANDLED; -} - -static struct timer_list led_timer = { -	function: &led_flash -}; - -static void led_flash(unsigned long dummy) { -	struct led_t *l; -	unsigned mask = 0; -	unsigned 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; -			} -		} -	} - -	mask &= ~gpiomask; -	if (mask) { -		unsigned val; - -		val = ~sb_gpioin(sbh); -		val &= mask; - -		sb_gpioouten(sbh, mask, mask, GPIO_DRV_PRIORITY); -		sb_gpiocontrol(sbh, mask, 0, GPIO_DRV_PRIORITY); -		sb_gpioout(sbh, mask, val, GPIO_DRV_PRIORITY); -	} -	if (mask || extif_blink) { -		mod_timer(&led_timer, jiffies + FLASH_TIME); -	} -} - -static void __init register_buttons(struct button_t *b) -{ -	int irq = sb_irq(sbh) + 2; - -	request_irq(irq, button_handler, SA_SHIRQ | SA_SAMPLE_RANDOM, "gpio", button_handler); - -	for (; b->name; b++) { -		if (b->gpio & gpiomask) -			continue; - -		sb_gpioouten(sbh, b->gpio,0, GPIO_DRV_PRIORITY); -		sb_gpiocontrol(sbh, b->gpio,0, GPIO_DRV_PRIORITY); -		b->polarity = sb_gpioin(sbh) & b->gpio; -		sb_gpiointpolarity(sbh, b->gpio, b->polarity, GPIO_DRV_PRIORITY); -		sb_gpiointmask(sbh, b->gpio, b->gpio, GPIO_DRV_PRIORITY); -	} -	set_irqenable(1); -} - -static void __exit unregister_buttons(struct button_t *b) -{ -	int irq = sb_irq(sbh) + 2; - -	for (; b->name; b++) -		sb_gpiointmask(sbh, b->gpio, 0, GPIO_DRV_PRIORITY); - -	free_irq(irq, button_handler); -} - -static void __init register_leds(struct led_t *l) -{ -	struct proc_dir_entry *p; - -	leds = proc_mkdir("led", diag); -	if (!leds)  -		return; - -	for(; l->name; l++) { -		if (l->gpio & gpiomask) -			continue; -	 -		if (l->gpio & GPIO_TYPE_EXTIF) { -			l->state = 0; -			set_led_extif(l); -		} else { -			sb_gpioouten(sbh, l->gpio, l->gpio, GPIO_DRV_PRIORITY); -			sb_gpiocontrol(sbh, l->gpio, 0, GPIO_DRV_PRIORITY); -			sb_gpioout(sbh, l->gpio, (l->polarity == NORMAL)?0:l->gpio, GPIO_DRV_PRIORITY); -		} - -		if ((p = create_proc_entry(l->name, S_IRUSR, leds))) { -			l->proc.type = PROC_LED; -			l->proc.ptr = l; -			p->data = (void *) &l->proc; -			p->proc_fops = &diag_proc_fops; -		} -	} -} - -static void __exit unregister_leds(struct led_t *l) -{ -	for(; l->name; l++) -		remove_proc_entry(l->name, leds); - -	remove_proc_entry("led", diag); -} - -static void __exit diag_exit(void) -{ - -	del_timer(&led_timer); - -	if (platform.buttons) -		unregister_buttons(platform.buttons); - -	if (platform.leds) -		unregister_leds(platform.leds); - -	remove_proc_entry("model", diag); -	remove_proc_entry("gpiomask", diag); -	remove_proc_entry("diag", NULL); -} - -static struct prochandler_t proc_model = { .type = PROC_MODEL }; -static struct prochandler_t proc_gpiomask = { .type = PROC_GPIOMASK }; -  static int __init diag_init(void)  {  	static struct proc_dir_entry *p; @@ -932,6 +800,22 @@ static int __init diag_init(void)  	return 0;  } +static void __exit diag_exit(void) +{ + +	del_timer(&led_timer); + +	if (platform.buttons) +		unregister_buttons(platform.buttons); + +	if (platform.leds) +		unregister_leds(platform.leds); + +	remove_proc_entry("model", diag); +	remove_proc_entry("gpiomask", diag); +	remove_proc_entry("diag", NULL); +} +  module_init(diag_init);  module_exit(diag_exit); diff --git a/package/broadcom-diag/src/diag.h b/package/broadcom-diag/src/diag.h new file mode 100644 index 000000000..30791cffe --- /dev/null +++ b/package/broadcom-diag/src/diag.h @@ -0,0 +1,125 @@ +/* + * diag.h - GPIO interface driver for Broadcom boards + * + * Copyright (C) 2006 Mike Baker <mbm@openwrt.org>, + *                    Felix Fietkau <nbd@openwrt.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. + * + * $Id:$ + */ + +#define MODULE_NAME "diag" + +#define MAX_GPIO 8 +#define FLASH_TIME HZ/6 + +enum polarity_t { +	REVERSE = 0, +	NORMAL = 1, +}; + +enum { +	PROC_BUTTON, +	PROC_LED, +	PROC_MODEL, +	PROC_GPIOMASK +}; + +struct prochandler_t { +	int type; +	void *ptr; +}; + +struct button_t { +	struct prochandler_t proc; +	char *name; +	u32 gpio; +	unsigned long seen; +	u8 pressed; +}; + +struct led_t { +	struct prochandler_t proc; +	char *name; +	u32 gpio; +	u8 polarity; +	u8 flash; +	u8 state; +}; + +struct platform_t { +	char *name; + +	struct button_t buttons[MAX_GPIO]; +	u32 button_mask; +	u32 button_polarity; + +	struct led_t leds[MAX_GPIO]; +}; + +struct event_t { +	struct work_struct wq; +	char buf[256]; +	char *argv[3]; +	char *envp[6]; +}; + +extern char *nvram_get(char *str); + +static struct platform_t platform; + +/* buttons */ + +static void register_buttons(struct button_t *b); +static void unregister_buttons(struct button_t *b); + +static void hotplug_button(struct event_t *event); +static irqreturn_t button_handler(int irq, void *dev_id, struct pt_regs *regs); + +/* leds */ + +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 led_flash(unsigned long dummy); + +/* 2.4 compatibility */ +#ifndef TIMER_INITIALIZER +#define TIMER_INITIALIZER(_function, _expires, _data) \ +	{ \ +		/* _expires and _data currently unused */ \ +		function: _function \ +	} +#endif + +static struct timer_list led_timer = TIMER_INITIALIZER(&led_flash, 0, 0); + +/* proc */ + +static struct proc_dir_entry *diag, *leds; + +static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos); +static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, loff_t *ppos); + +static struct file_operations diag_proc_fops = { +	read: diag_proc_read, +	write: diag_proc_write +}; + +static struct prochandler_t proc_model = { .type = PROC_MODEL }; +static struct prochandler_t proc_gpiomask = { .type = PROC_GPIOMASK }; + diff --git a/package/broadcom-diag/src/gpio.h b/package/broadcom-diag/src/gpio.h new file mode 100644 index 000000000..c6f34bdea --- /dev/null +++ b/package/broadcom-diag/src/gpio.h @@ -0,0 +1,78 @@ +#ifndef __DIAG_GPIO_H +#define __DIAG_GPIO_H + +#include <typedefs.h> +#include <osl.h> +#include <bcmdevs.h> +#include <sbutils.h> +#include <sbconfig.h> +#include <sbchipc.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#include <sbmips.h> +#else +#include <hndcpu.h> +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#define sbh bcm947xx_sbh +#define sbh_lock bcm947xx_sbh_lock +#endif + +#define EXTIF_ADDR 0x1f000000 +#define EXTIF_UART (EXTIF_ADDR + 0x00800000) + +#define GPIO_TYPE_NORMAL	(0x0 << 24) +#define GPIO_TYPE_EXTIF 	(0x1 << 24) +#define GPIO_TYPE_MASK  	(0xf << 24) + +extern void *sbh; +extern spinlock_t sbh_lock; + +#define gpio_in()	sb_gpioin(sbh) +#define gpio_out(mask, value) 	sb_gpioout(sbh, mask, ((value) & (mask)), GPIO_DRV_PRIORITY) +#define gpio_outen(mask, value) 	sb_gpioouten(sbh, mask, value, GPIO_DRV_PRIORITY) +#define gpio_control(mask, value) 	sb_gpiocontrol(sbh, mask, value, GPIO_DRV_PRIORITY) +#define gpio_intmask(mask, value) 	sb_gpiointmask(sbh, mask, value, GPIO_DRV_PRIORITY) +#define gpio_intpolarity(mask, value) 	sb_gpiointpolarity(sbh, mask, value, GPIO_DRV_PRIORITY) + +static void gpio_set_irqenable(int enabled, irqreturn_t (*handler)(int, void *, struct pt_regs *)) +{ +	unsigned int coreidx; +	unsigned long flags; +	chipcregs_t *cc; +	int irq; + +	spin_lock_irqsave(sbh_lock, flags); +	coreidx = sb_coreidx(sbh); + +	irq = sb_irq(sbh) + 2; +	if (enabled) +		request_irq(irq, handler, SA_SHIRQ | SA_SAMPLE_RANDOM, "gpio", handler); +	else +		free_irq(irq, handler); + +	if ((cc = sb_setcore(sbh, SB_CC, 0))) { +		int intmask; + +		intmask = readl(&cc->intmask); +		if (enabled) +			intmask |= CI_GPIO; +		else +			intmask &= ~CI_GPIO; +		writel(intmask, &cc->intmask); +	} +	sb_setcoreidx(sbh, coreidx); +	spin_unlock_irqrestore(sbh_lock, flags); +} + +static inline void gpio_set_extif(int gpio, int value) +{ +	volatile u8 *addr = (volatile u8 *) KSEG1ADDR(EXTIF_UART) + (gpio & ~GPIO_TYPE_MASK); +	if (value) +		*addr = 0xFF; +	else +		*addr; +} + + +#endif | 
