From b592d36cb119ce407f6b82fe800892d9775188e0 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 9 Nov 2006 07:35:27 +0000 Subject: [PATCH] forward port diag changes from whiterussian, add extra abstraction for the gpio stuff SVN-Revision: 5478 --- package/broadcom-diag/src/diag.c | 544 ++++++++++++------------------- package/broadcom-diag/src/diag.h | 125 +++++++ package/broadcom-diag/src/gpio.h | 78 +++++ 3 files changed, 417 insertions(+), 330 deletions(-) create mode 100644 package/broadcom-diag/src/diag.h create mode 100644 package/broadcom-diag/src/gpio.h diff --git a/package/broadcom-diag/src/diag.c b/package/broadcom-diag/src/diag.c index e0b08be3dd..7c6e303fcf 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 #include @@ -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 -#include -#include -#include -#include -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -#include -#else -#include -#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 0000000000..30791cffe3 --- /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 , + * Felix Fietkau + * + * 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 0000000000..c6f34bdea2 --- /dev/null +++ b/package/broadcom-diag/src/gpio.h @@ -0,0 +1,78 @@ +#ifndef __DIAG_GPIO_H +#define __DIAG_GPIO_H + +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#include +#else +#include +#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