|
|
@ -44,6 +44,21 @@ static int fill_event(struct event_t *); |
|
|
|
static unsigned int gpiomask = 0; |
|
|
|
static unsigned int gpiomask = 0; |
|
|
|
module_param(gpiomask, int, 0644); |
|
|
|
module_param(gpiomask, int, 0644); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extern char *nvram_get(char *str); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void register_leds(struct led_t *l); |
|
|
|
|
|
|
|
static void unregister_leds(struct led_t *l); |
|
|
|
|
|
|
|
static void led_flash(unsigned long dummy); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct platform_t platform; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct timer_list led_timer = TIMER_INITIALIZER(&led_flash, 0, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct proc_dir_entry *diag, *leds; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct prochandler_t proc_model = { .type = PROC_MODEL }; |
|
|
|
|
|
|
|
static struct prochandler_t proc_gpiomask = { .type = PROC_GPIOMASK }; |
|
|
|
|
|
|
|
|
|
|
|
enum { |
|
|
|
enum { |
|
|
|
/* Linksys */ |
|
|
|
/* Linksys */ |
|
|
|
WAP54GV1, |
|
|
|
WAP54GV1, |
|
|
@ -1381,41 +1396,6 @@ static void gpio_set_irqenable(int enabled, irqreturn_t (*handler)(int, void *)) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void register_buttons(struct button_t *b) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for (; b->name; b++) |
|
|
|
|
|
|
|
platform.button_mask |= b->gpio; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
platform.button_mask &= ~gpiomask; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bcm47xx_gpio_outen(platform.button_mask, 0); |
|
|
|
|
|
|
|
bcm47xx_gpio_control(platform.button_mask, 0); |
|
|
|
|
|
|
|
platform.button_polarity = bcm47xx_gpio_in(~0) & platform.button_mask; |
|
|
|
|
|
|
|
bcm47xx_gpio_polarity(platform.button_mask, platform.button_polarity); |
|
|
|
|
|
|
|
bcm47xx_gpio_intmask(platform.button_mask, platform.button_mask); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gpio_set_irqenable(1, button_handler); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void unregister_buttons(struct button_t *b) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
bcm47xx_gpio_intmask(platform.button_mask, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gpio_set_irqenable(0, button_handler); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void add_msg(struct event_t *event, char *msg, int argv) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
char *s; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (argv) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s = skb_put(event->skb, strlen(msg) + 1); |
|
|
|
|
|
|
|
strcpy(s, msg); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void hotplug_button(struct work_struct *work) |
|
|
|
static void hotplug_button(struct work_struct *work) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct event_t *event = container_of(work, struct event_t, wq); |
|
|
|
struct event_t *event = container_of(work, struct event_t, wq); |
|
|
@ -1433,27 +1413,6 @@ static void hotplug_button(struct work_struct *work) |
|
|
|
kfree(event); |
|
|
|
kfree(event); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int fill_event (struct event_t *event) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
static char buf[128]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
add_msg(event, "HOME=/", 0); |
|
|
|
|
|
|
|
add_msg(event, "PATH=/sbin:/bin:/usr/sbin:/usr/bin", 0); |
|
|
|
|
|
|
|
add_msg(event, "SUBSYSTEM=button", 0); |
|
|
|
|
|
|
|
snprintf(buf, 128, "ACTION=%s", event->action); |
|
|
|
|
|
|
|
add_msg(event, buf, 0); |
|
|
|
|
|
|
|
snprintf(buf, 128, "BUTTON=%s", event->name); |
|
|
|
|
|
|
|
add_msg(event, buf, 0); |
|
|
|
|
|
|
|
snprintf(buf, 128, "SEEN=%ld", event->seen); |
|
|
|
|
|
|
|
add_msg(event, buf, 0); |
|
|
|
|
|
|
|
snprintf(buf, 128, "SEQNUM=%llu", uevent_next_seqnum()); |
|
|
|
|
|
|
|
add_msg(event, buf, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static irqreturn_t button_handler(int irq, void *dev_id) |
|
|
|
static irqreturn_t button_handler(int irq, void *dev_id) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct button_t *b; |
|
|
|
struct button_t *b; |
|
|
@ -1486,71 +1445,58 @@ static irqreturn_t button_handler(int irq, void *dev_id) |
|
|
|
return IRQ_HANDLED; |
|
|
|
return IRQ_HANDLED; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void register_leds(struct led_t *l) |
|
|
|
static void register_buttons(struct button_t *b) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct proc_dir_entry *p; |
|
|
|
for (; b->name; b++) |
|
|
|
u32 mask = 0; |
|
|
|
platform.button_mask |= b->gpio; |
|
|
|
u32 oe_mask = 0; |
|
|
|
|
|
|
|
u32 val = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
leds = proc_mkdir("led", diag); |
|
|
|
|
|
|
|
if (!leds) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(; l->name; l++) { |
|
|
|
platform.button_mask &= ~gpiomask; |
|
|
|
if (l->gpio & gpiomask) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (l->gpio & GPIO_TYPE_MASK) { |
|
|
|
bcm47xx_gpio_outen(platform.button_mask, 0); |
|
|
|
case GPIO_TYPE_EXTIF: |
|
|
|
bcm47xx_gpio_control(platform.button_mask, 0); |
|
|
|
l->state = 0; |
|
|
|
platform.button_polarity = bcm47xx_gpio_in(~0) & platform.button_mask; |
|
|
|
set_led_extif(l); |
|
|
|
bcm47xx_gpio_polarity(platform.button_mask, platform.button_polarity); |
|
|
|
break; |
|
|
|
bcm47xx_gpio_intmask(platform.button_mask, platform.button_mask); |
|
|
|
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; |
|
|
|
gpio_set_irqenable(1, button_handler); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if ((p = create_proc_entry(l->name, S_IRUSR, leds))) { |
|
|
|
static void unregister_buttons(struct button_t *b) |
|
|
|
l->proc.type = PROC_LED; |
|
|
|
{ |
|
|
|
l->proc.ptr = l; |
|
|
|
bcm47xx_gpio_intmask(platform.button_mask, 0); |
|
|
|
p->data = (void *) &l->proc; |
|
|
|
|
|
|
|
p->proc_fops = &diag_proc_fops; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bcm47xx_gpio_outen(mask, oe_mask); |
|
|
|
gpio_set_irqenable(0, button_handler); |
|
|
|
bcm47xx_gpio_control(mask, 0); |
|
|
|
|
|
|
|
bcm47xx_gpio_out(mask, val); |
|
|
|
|
|
|
|
bcm47xx_gpio_intmask(mask, 0); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void unregister_leds(struct led_t *l) |
|
|
|
|
|
|
|
|
|
|
|
static void add_msg(struct event_t *event, char *msg, int argv) |
|
|
|
{ |
|
|
|
{ |
|
|
|
for(; l->name; l++) |
|
|
|
char *s; |
|
|
|
remove_proc_entry(l->name, leds); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
remove_proc_entry("led", diag); |
|
|
|
if (argv) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s = skb_put(event->skb, strlen(msg) + 1); |
|
|
|
|
|
|
|
strcpy(s, msg); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void set_led_extif(struct led_t *led) |
|
|
|
static int fill_event (struct event_t *event) |
|
|
|
{ |
|
|
|
{ |
|
|
|
volatile u8 *addr = (volatile u8 *) KSEG1ADDR(EXTIF_UART) + (led->gpio & ~GPIO_TYPE_MASK); |
|
|
|
static char buf[128]; |
|
|
|
if (led->state) |
|
|
|
|
|
|
|
*addr = 0xFF; |
|
|
|
add_msg(event, "HOME=/", 0); |
|
|
|
else |
|
|
|
add_msg(event, "PATH=/sbin:/bin:/usr/sbin:/usr/bin", 0); |
|
|
|
*addr; |
|
|
|
add_msg(event, "SUBSYSTEM=button", 0); |
|
|
|
|
|
|
|
snprintf(buf, 128, "ACTION=%s", event->action); |
|
|
|
|
|
|
|
add_msg(event, buf, 0); |
|
|
|
|
|
|
|
snprintf(buf, 128, "BUTTON=%s", event->name); |
|
|
|
|
|
|
|
add_msg(event, buf, 0); |
|
|
|
|
|
|
|
snprintf(buf, 128, "SEEN=%ld", event->seen); |
|
|
|
|
|
|
|
add_msg(event, buf, 0); |
|
|
|
|
|
|
|
snprintf(buf, 128, "SEQNUM=%llu", uevent_next_seqnum()); |
|
|
|
|
|
|
|
add_msg(event, buf, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
@ -1592,6 +1538,15 @@ static void set_led_shift(struct led_t *led) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 void led_flash(unsigned long dummy) { |
|
|
|
static void led_flash(unsigned long dummy) { |
|
|
|
struct led_t *l; |
|
|
|
struct led_t *l; |
|
|
@ -1744,6 +1699,69 @@ static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, |
|
|
|
return ret; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct file_operations diag_proc_fops = { |
|
|
|
|
|
|
|
read: diag_proc_read, |
|
|
|
|
|
|
|
write: diag_proc_write |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void register_leds(struct led_t *l) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct proc_dir_entry *p; |
|
|
|
|
|
|
|
u32 mask = 0; |
|
|
|
|
|
|
|
u32 oe_mask = 0; |
|
|
|
|
|
|
|
u32 val = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
leds = proc_mkdir("led", diag); |
|
|
|
|
|
|
|
if (!leds) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(; l->name; l++) { |
|
|
|
|
|
|
|
if (l->gpio & gpiomask) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (l->gpio & GPIO_TYPE_MASK) { |
|
|
|
|
|
|
|
case GPIO_TYPE_EXTIF: |
|
|
|
|
|
|
|
l->state = 0; |
|
|
|
|
|
|
|
set_led_extif(l); |
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bcm47xx_gpio_outen(mask, oe_mask); |
|
|
|
|
|
|
|
bcm47xx_gpio_control(mask, 0); |
|
|
|
|
|
|
|
bcm47xx_gpio_out(mask, val); |
|
|
|
|
|
|
|
bcm47xx_gpio_intmask(mask, 0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void unregister_leds(struct led_t *l) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for(; l->name; l++) |
|
|
|
|
|
|
|
remove_proc_entry(l->name, leds); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
remove_proc_entry("led", diag); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int __init diag_init(void) |
|
|
|
static int __init diag_init(void) |
|
|
|
{ |
|
|
|
{ |
|
|
|
static struct proc_dir_entry *p; |
|
|
|
static struct proc_dir_entry *p; |
|
|
|