/* GPIO Push Button driver by ivan wang */
#include <linux/module.h>
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <asm/signal.h>
#include "gpio.h"
static struct proc_dir_entry *info_entry;
int play_c=0;
static pid_t mpid;
struct file *filp;
spinlock_t fgpio_lock;
MODULE_AUTHOR("GM Corp.");
MODULE_LICENSE("GM License");
gpio_params gm;
void fgpio_play_next(void)
{
printk("Play Next\n");
/* send signal */
sys_kill(mpid,SIGUSR1);
}
void fgpio_play_enter(void)
{
printk("Play Enter\n");
/* send signal */
sys_kill(mpid,SIGUSR2);
}
void fgpio_play_switch(void)
{
printk("Play Switch\n");
/* send signal */
sys_kill(mpid,SIGPWR);
}
irqreturn_t gpio_interrupt_handler(int irq, void *dev_id, struct pt_regs *dummy)
{
//determine which GPIO
int gpio_value,i,k;
unsigned long flags;
//printk("in...\n");
spin_lock_irqsave(&fgpio_lock,flags);
#ifdef CONFIG_PLATFORM_GM8180
for(i = 0; i <= 50000; i++)
{
k = read_data_input(0,0x36);
//if((k&0x3C) != 0x3C)
// printk("4 = 0x%x\n",k);
if((k & (1 << 1)) == 0)
{
gpio_value = 2;
//printk("K1 is pressed\n");
break;
}
else if((k & (1 << 2)) == 0)
{
gpio_value = 1;
//printk("K2 is pressed\n");
break;
}
else if((k & (1 << 4)) == 0)
{
gpio_value = 3;
//printk("K3 is pressed\n");
break;
}
else if((k & (1 << 5)) == 0)
{
gpio_value = 4;
//printk("K4 is pressed\n");
break;
}
}
#elif defined(CONFIG_PLATFORM_GM8185)
for(i = 0; i <= 50000; i++)
{
k = read_data_input(0,0x10);
if((k & (1 << 4)) == 0)
{
gpio_value = 3;
//printk("K3 is pressed\n");
break;
}
}
#elif defined(CONFIG_PLATFORM_GM8120)
for(k = 8; k <= 11; k++)
{
*(volatile unsigned int *)(GPIO_FTGPIO010_VA_BASE) = ~(1 << k);
//printk("reg 0 = 0x%x, 4 = 0x%x\n",*(volatile unsigned int *)(GPIO_FTGPIO010_VA_BASE),*(volatile unsigned int *)(GPIO_FTGPIO010_VA_BASE+0x4));
if(((*(volatile unsigned int *)(GPIO_FTGPIO010_VA_BASE+0x4)) & 0x04000) == 0)//k1,k2,k3,k4
{
gpio_value = k-8+1;
printk("int %d\n",gpio_value);
break;
}
}
#endif
if(gpio_value==1) //GPIO 1
fgpio_play_switch();
else if(gpio_value==2) //GPIO 2
fgpio_play_next();
else if(gpio_value==3) //GPIO 3
fgpio_play_enter();
#ifdef CONFIG_PLATFORM_GM8180
int_clear(0,0x36);
#elif defined(CONFIG_PLATFORM_GM8185)
int_clear(0,0x10);
#else
*(volatile unsigned int *)(GPIO_FTGPIO010_VA_BASE+0x30)=0xFFFF; //clear interrupt
#endif
spin_unlock_irqrestore(&fgpio_lock,flags);
//for compiler optimize issue, must outside spinlock, otherwize do_irq fail
#ifdef CONFIG_PLATFORM_GM8180
set_int(0,0x36,0x36);
#elif defined(CONFIG_PLATFORM_GM8185)
set_int(0,0x10,0x10);
#elif defined(CONFIG_PLATFORM_GM8120)
*(volatile unsigned int *)(GPIO_FTGPIO010_VA_BASE)=0xF0FF; // enable k1~k4 interrupt
#endif
return IRQ_HANDLED;
}
static int fgpio_atoi(char *s)
{
int k = 0;
k = 0;
while (*s != '\0' && *s >= '0' && *s <= '9')
{
k = 10 * k + (*s - '0');
s++;
}
return k;
}
static int proc_read_gpio_info(char *page, char **start,off_t off, int count,int *eof, void *data)
{
int len;
len=sprintf(page,"%d\n",mpid);
*eof=1; //end of file
*start = page + off;
//printk("mpid=%d len:%d off:%d\n",mpid,len,off);
len=len-off;
return len;
}
static int proc_write_gpio_info(struct file *file,const char *buffer,unsigned long count, void *data)
{
int len=count;
unsigned char value[20];
if(copy_from_user(value,buffer,len))
return 0;
value[len]='\0';
mpid=fgpio_atoi(value);
// printk("mpid=%d %s count=%d\n",mpid,value,count);
return count;
}
static int __init fgpio_init(void)
{
spin_lock_init(&fgpio_lock);
mpid=0;
/* info entry */
info_entry=create_proc_entry("gpio",777,0);
if(info_entry==NULL)
{
printk("Fail to create proc entry: info!\n");
return 0;
}
info_entry->read_proc=proc_read_gpio_info;
info_entry->write_proc=proc_write_gpio_info;
info_entry->owner=THIS_MODULE;
mpid=0;
#ifdef CONFIG_PLATFORM_GM8180
gm.group=0;
gm.int_enable=0x36;
gm.int_trigger=0;
gm.int_both=0;
gm.int_riseneg=0x36;
set_int(0,0x36,0x36);
set_data_direct(0,0x36, 0);
set_int_func(&gm);
#elif defined(CONFIG_PLATFORM_GM8185)
gm.group=0;
gm.int_enable=0x10;
gm.int_trigger=0;
gm.int_both=0;
gm.int_riseneg=0x10;
set_int(0,0x10,0x10);
set_data_direct(0,0x10, 0);
set_int_func(&gm);
#elif defined(CONFIG_PLATFORM_GM8120)
*(volatile unsigned int *)(GPIO_FTGPIO010_VA_BASE+0x38)|=0xFF00;
*(volatile unsigned int *)(GPIO_FTGPIO010_VA_BASE+0x8)|=0x0F00;
*(volatile unsigned int *)(GPIO_FTGPIO010_VA_BASE+0x20)|=0xFF00; //enable interrupt
#endif
if(request_irq(GPIO_FTGPIO010_IRQ, gpio_interrupt_handler, SA_INTERRUPT,"gpio",0) < 0)
printk(KERN_WARNING "GM GPIO: Unable to allocate IRQ %d\n",GPIO_FTGPIO010_IRQ);
return 0;
}
static void __exit fgpio_exit(void)
{
#ifdef CONFIG_PLATFORM_GM8180
set_int(0,0x36,0);
#elif defined(CONFIG_PLATFORM_GM8185)
set_int(0,0x10,0);
#else
*(volatile unsigned int *)(GPIO_FTGPIO010_VA_BASE+0x20) = 0x0000; //disable interrupt
#endif
free_irq(GPIO_FTGPIO010_IRQ,0);
remove_proc_entry("gpio",0);
}
module_init(fgpio_init);
module_exit(fgpio_exit);