source: trunk/target/linux/atheros/patches-2.6.31/210-reset_button.patch @ 17700

Last change on this file since 17700 was 17700, checked in by nbd, 7 years ago

atheros: add config and patches for 2.6.31 (untested), includes patch from #5847

File size: 4.0 KB
  • arch/mips/ar231x/Makefile

    a b  
    88# Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org> 
    99# 
    1010 
    11 obj-y += board.o prom.o devices.o 
     11obj-y += board.o prom.o devices.o reset.o 
    1212obj-$(CONFIG_ATHEROS_AR5312) += ar5312.o 
    1313obj-$(CONFIG_ATHEROS_AR2315) += ar2315.o 
    1414obj-$(CONFIG_ATHEROS_AR2315_PCI) += pci.o 
  • new file arch/mips/ar231x/reset.c

    - +  
     1#include <linux/init.h> 
     2#include <linux/module.h> 
     3#include <linux/timer.h> 
     4#include <linux/interrupt.h> 
     5#include <linux/kobject.h> 
     6#include <linux/workqueue.h> 
     7#include <linux/skbuff.h> 
     8#include <linux/netlink.h> 
     9#include <net/sock.h> 
     10#include <asm/uaccess.h> 
     11#include <ar231x_platform.h> 
     12#include <ar231x.h> 
     13#include <gpio.h> 
     14#include "devices.h" 
     15 
     16#define AR531X_RESET_GPIO_IRQ   (AR531X_GPIO_IRQ(ar231x_board.config->resetConfigGpio)) 
     17 
     18struct event_t { 
     19        struct work_struct wq; 
     20        int set; 
     21        unsigned long jiffies; 
     22}; 
     23 
     24static struct timer_list rst_button_timer; 
     25static unsigned long seen; 
     26 
     27extern struct sock *uevent_sock; 
     28extern u64 uevent_next_seqnum(void); 
     29 
     30static int no_release_workaround = 1; 
     31module_param(no_release_workaround, int, 0); 
     32 
     33static inline void 
     34add_msg(struct sk_buff *skb, char *msg) 
     35{ 
     36        char *scratch; 
     37        scratch = skb_put(skb, strlen(msg) + 1); 
     38        sprintf(scratch, msg); 
     39} 
     40 
     41static void 
     42hotplug_button(struct work_struct *wq) 
     43{ 
     44        struct sk_buff *skb; 
     45        struct event_t *event; 
     46        size_t len; 
     47        char *scratch, *s; 
     48        char buf[128]; 
     49 
     50        event = container_of(wq, struct event_t, wq); 
     51        if (!uevent_sock) 
     52                goto done; 
     53 
     54        /* allocate message with the maximum possible size */ 
     55        s = event->set ? "pressed" : "released"; 
     56        len = strlen(s) + 2; 
     57        skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); 
     58        if (!skb) 
     59                goto done; 
     60 
     61        /* add header */ 
     62        scratch = skb_put(skb, len); 
     63        sprintf(scratch, "%s@",s); 
     64 
     65        /* copy keys to our continuous event payload buffer */ 
     66        add_msg(skb, "HOME=/"); 
     67        add_msg(skb, "PATH=/sbin:/bin:/usr/sbin:/usr/bin"); 
     68        add_msg(skb, "SUBSYSTEM=button"); 
     69        add_msg(skb, "BUTTON=reset"); 
     70        add_msg(skb, (event->set ? "ACTION=pressed" : "ACTION=released")); 
     71        sprintf(buf, "SEEN=%ld", (event->jiffies - seen)/HZ); 
     72        add_msg(skb, buf); 
     73        snprintf(buf, 128, "SEQNUM=%llu", uevent_next_seqnum()); 
     74        add_msg(skb, buf); 
     75 
     76        NETLINK_CB(skb).dst_group = 1; 
     77        netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL); 
     78 
     79done: 
     80        kfree(event); 
     81} 
     82 
     83static void 
     84reset_button_poll(unsigned long unused) 
     85{ 
     86        struct event_t *event; 
     87        int gpio = ~0; 
     88 
     89        if(!no_release_workaround) 
     90                return; 
     91 
     92        gpio = ar231x_gpiodev->get(); 
     93        gpio &= (1 << (AR531X_RESET_GPIO_IRQ - AR531X_GPIO_IRQ_BASE)); 
     94        if(gpio) { 
     95                rst_button_timer.expires = jiffies + (HZ / 4); 
     96                add_timer(&rst_button_timer); 
     97                return; 
     98        } 
     99 
     100        event = (struct event_t *) kzalloc(sizeof(struct event_t), GFP_ATOMIC); 
     101        if (!event) 
     102                return; 
     103 
     104        event->set = 0; 
     105        event->jiffies = jiffies; 
     106        INIT_WORK(&event->wq, hotplug_button); 
     107        schedule_work(&event->wq); 
     108} 
     109 
     110static irqreturn_t 
     111button_handler(int irq, void *dev_id) 
     112{ 
     113        static int pressed = 0; 
     114        struct event_t *event; 
     115        u32 gpio = ~0; 
     116 
     117        event = (struct event_t *) kzalloc(sizeof(struct event_t), GFP_ATOMIC); 
     118        if (!event) 
     119                return IRQ_NONE; 
     120 
     121        pressed = !pressed; 
     122 
     123        gpio = ar231x_gpiodev->get() & (1 << (irq - AR531X_GPIO_IRQ_BASE)); 
     124 
     125        event->set = gpio; 
     126        if(!event->set) 
     127                no_release_workaround = 0; 
     128 
     129        event->jiffies = jiffies; 
     130 
     131        INIT_WORK(&event->wq, hotplug_button); 
     132        schedule_work(&event->wq); 
     133 
     134        seen = jiffies; 
     135        if(event->set && no_release_workaround) 
     136                mod_timer(&rst_button_timer, jiffies + (HZ / 4)); 
     137 
     138        return IRQ_HANDLED; 
     139} 
     140 
     141 
     142static int __init 
     143ar231x_init_reset(void) 
     144{ 
     145        seen = jiffies; 
     146 
     147        if (ar231x_board.config->resetConfigGpio == 0xffff) 
     148                return -ENODEV; 
     149 
     150        init_timer(&rst_button_timer); 
     151        rst_button_timer.function = reset_button_poll; 
     152        rst_button_timer.expires = jiffies + HZ / 50; 
     153        add_timer(&rst_button_timer); 
     154 
     155        request_irq(AR531X_RESET_GPIO_IRQ, &button_handler, IRQF_SAMPLE_RANDOM, "ar231x_reset", NULL); 
     156 
     157        return 0; 
     158} 
     159 
     160module_init(ar231x_init_reset); 
Note: See TracBrowser for help on using the repository browser.