364 lines
11 KiB
C
Executable File
364 lines
11 KiB
C
Executable File
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
#include <linux/gpio.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/irq.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/completion.h>
|
|
|
|
|
|
static int gpio_in_num = -1;
|
|
static int gpio_out_num = -1;
|
|
static int int_type = -1;
|
|
static int gpio_test_case = 0;
|
|
|
|
module_param(gpio_in_num, int, S_IRUSR);
|
|
module_param(gpio_out_num, int, S_IRUSR);
|
|
module_param(int_type, int, S_IRUSR);
|
|
module_param(gpio_test_case, int, S_IRUSR);
|
|
|
|
DECLARE_COMPLETION(work);
|
|
|
|
|
|
static irqreturn_t gpio_input_output_interrupt_test_interrupt_call(int irq, void *dev_id)
|
|
{
|
|
disable_irq_nosync(gpio_to_irq(gpio_in_num));
|
|
printk("%s:Interrupt triggered success for gpio:%d irq:%d int_type:%d\n",__FUNCTION__,gpio_in_num,irq,int_type);
|
|
complete_all(&work);
|
|
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
static int gpio_input_output_interrupt_test_entry(void)
|
|
{
|
|
int ret = -1;
|
|
|
|
printk("%s:current args:gpio_in_num=%d gpio_out_num=%d int_type=%d gpio_test_case=%d\n",__FUNCTION__,gpio_in_num,gpio_out_num,int_type,gpio_test_case);
|
|
if(gpio_in_num == -1 || gpio_out_num == -1 || int_type < 1 || int_type > 5)
|
|
{
|
|
printk("you input args is error!!!\n");
|
|
printk("int_type=1 //IRQ_TYPE_EDGE_RISING\n");
|
|
printk("int_type=2 //IRQ_TYPE_EDGE_FALLING\n");
|
|
printk("int_type=3 //IRQ_TYPE_EDGE_BOTH\n");
|
|
printk("int_type=4 //IRQ_TYPE_LEVEL_HIGH\n");
|
|
printk("int_type=5 //IRQ_TYPE_LEVEL_LOW\n");
|
|
return ret;
|
|
}
|
|
|
|
init_completion(&work);
|
|
|
|
gpio_free(gpio_in_num);
|
|
gpio_free(gpio_out_num);
|
|
|
|
ret = gpio_request(gpio_in_num, "gpio_in\n");
|
|
if (ret != 0) {
|
|
printk("error %d: gpio%d request is failed\n",ret,gpio_in_num);
|
|
return ret;
|
|
}
|
|
|
|
ret = gpio_request(gpio_out_num, "gpio_out\n");
|
|
if (ret != 0) {
|
|
printk("error %d: gpio%d request is failed\n",ret,gpio_out_num);
|
|
gpio_free(gpio_in_num);
|
|
return ret;
|
|
}
|
|
|
|
ret = gpio_direction_input(gpio_in_num);
|
|
if (ret != 0) {
|
|
printk("error %d: gpio%d direction input is failed\n",ret,gpio_in_num);
|
|
goto err;
|
|
}
|
|
|
|
ret = gpio_direction_output(gpio_out_num, 0);
|
|
if (ret != 0) {
|
|
printk("error %d: gpio%d direction output is failed\n",ret,gpio_out_num);
|
|
goto err;
|
|
}
|
|
|
|
if (int_type == 1) {
|
|
ret = request_irq(gpio_to_irq(gpio_in_num), gpio_input_output_interrupt_test_interrupt_call, IRQ_TYPE_EDGE_RISING, "gpio_interrupt_edge_rising", NULL);
|
|
} else if (int_type == 2) {
|
|
ret = request_irq(gpio_to_irq(gpio_in_num), gpio_input_output_interrupt_test_interrupt_call, IRQ_TYPE_EDGE_FALLING, "gpio_interrupt_edge_falling", NULL);
|
|
} else if (int_type == 3) {
|
|
ret = request_irq(gpio_to_irq(gpio_in_num), gpio_input_output_interrupt_test_interrupt_call, IRQ_TYPE_EDGE_BOTH, "gpio_interrupt_edge_both", NULL);
|
|
} else if (int_type == 4) {
|
|
ret = request_irq(gpio_to_irq(gpio_in_num), gpio_input_output_interrupt_test_interrupt_call, IRQ_TYPE_LEVEL_HIGH, "gpio_interrupt_level_high", NULL);
|
|
} else if (int_type == 5) {
|
|
ret = request_irq(gpio_to_irq(gpio_in_num), gpio_input_output_interrupt_test_interrupt_call, IRQ_TYPE_LEVEL_LOW, "gpio_interrupt_level_low", NULL);
|
|
}
|
|
|
|
if(ret != 0) {
|
|
printk(KERN_ERR "error %d: request irq is failed gpio:%d irq:%d int_type:%d\n",ret,gpio_in_num,gpio_to_irq(gpio_in_num),int_type);
|
|
goto err;
|
|
}
|
|
|
|
|
|
gpio_set_value(gpio_out_num ,0);
|
|
mdelay(1000);
|
|
gpio_set_value(gpio_out_num ,1);
|
|
mdelay(1000);
|
|
gpio_set_value(gpio_out_num ,0);
|
|
mdelay(1000);
|
|
gpio_set_value(gpio_out_num ,1);
|
|
mdelay(1000);
|
|
|
|
|
|
wait_for_completion_interruptible(&work);
|
|
printk("gpio test done\n");
|
|
|
|
return ret;
|
|
|
|
err:
|
|
gpio_free(gpio_in_num);
|
|
gpio_free(gpio_out_num);
|
|
return ret;
|
|
}
|
|
|
|
static void gpio_input_output_interrupt_test_exit(void)
|
|
{
|
|
free_irq(gpio_to_irq(gpio_in_num), NULL);
|
|
gpio_free(gpio_in_num);
|
|
gpio_free(gpio_out_num);
|
|
gpio_in_num = -1;
|
|
gpio_out_num = -1;
|
|
int_type = -1;
|
|
gpio_test_case = 0;
|
|
printk("%s:gpio_in_num=%d gpio_out_num=%d int_type=%d gpio_test_case=%d\n",__FUNCTION__,gpio_in_num,gpio_out_num,int_type,gpio_test_case);
|
|
}
|
|
|
|
static void addr_ioremap(unsigned long int phy_addr, unsigned int val)
|
|
{
|
|
void __iomem *vir = NULL;
|
|
|
|
vir = ioremap(phy_addr,0x4);
|
|
writel(val, vir);
|
|
iounmap(vir);
|
|
vir = NULL;
|
|
}
|
|
|
|
static void gpio_pin_func(void)
|
|
{
|
|
addr_ioremap(0x102000ec, 0x1); //pin5
|
|
addr_ioremap(0x102000f0, 0x1); //pin6
|
|
addr_ioremap(0x10200020, 0x1); //pin9
|
|
addr_ioremap(0x10200024, 0x1); //pin10
|
|
addr_ioremap(0x10200028, 0x1); //pin11
|
|
addr_ioremap(0x1020002c, 0x1); //pin12
|
|
addr_ioremap(0x10200030, 0x1); //pin13
|
|
addr_ioremap(0x10200034, 0x1); //pin14
|
|
addr_ioremap(0x10200038, 0x1); //pin15
|
|
addr_ioremap(0x10200048, 0x1); //pin16
|
|
addr_ioremap(0x10200054, 0x1); //pin17
|
|
addr_ioremap(0x1020004c, 0x1); //pin18
|
|
addr_ioremap(0x10200044, 0x1); //pin19
|
|
addr_ioremap(0x10200040, 0x1); //pin20
|
|
addr_ioremap(0x1020003c, 0x1); //pin21
|
|
addr_ioremap(0x10200050, 0x1); //pin22
|
|
addr_ioremap(0x102000b4, 0x1); //pin23
|
|
addr_ioremap(0x102000b8, 0x1); //pin24
|
|
addr_ioremap(0x1020005c, 0x1); //pin25
|
|
addr_ioremap(0x10200060, 0x1); //pin26
|
|
addr_ioremap(0x10200064, 0x1); //pin27
|
|
addr_ioremap(0x10200068, 0x1); //pin28
|
|
addr_ioremap(0x1020006c, 0x1); //pin29
|
|
addr_ioremap(0x10200070, 0x1); //pin30
|
|
addr_ioremap(0x10200074, 0x1); //pin31
|
|
addr_ioremap(0x10200078, 0x1); //pin32
|
|
addr_ioremap(0x1020007c, 0x1); //pin33
|
|
addr_ioremap(0x10200084, 0x1); //pin34
|
|
addr_ioremap(0x10200080, 0x1); //pin35
|
|
addr_ioremap(0x10200088, 0x1); //pin36
|
|
addr_ioremap(0x10200090, 0x1); //pin37
|
|
addr_ioremap(0x1020008c, 0x1); //pin38
|
|
addr_ioremap(0x10200098, 0x1); //pin39
|
|
addr_ioremap(0x10200094, 0x1); //pin40
|
|
addr_ioremap(0x1020009c, 0x1); //pin41
|
|
addr_ioremap(0x102000a0, 0x1); //pin42
|
|
addr_ioremap(0x102000a4, 0x1); //pin43
|
|
addr_ioremap(0x102000a8, 0x1); //pin44
|
|
addr_ioremap(0x102000ac, 0x1); //pin45
|
|
addr_ioremap(0x102000b0, 0x1); //pin46
|
|
addr_ioremap(0x102000d0, 0x1); //pin47
|
|
addr_ioremap(0x102000cc, 0x1); //pin48
|
|
addr_ioremap(0x102000c0, 0x1); //pin49
|
|
addr_ioremap(0x102000bc, 0x1); //pin50
|
|
addr_ioremap(0x102000c8, 0x1); //pin51
|
|
addr_ioremap(0x102000c4, 0x1); //pin52
|
|
addr_ioremap(0x102000d4, 0x1); //pin53
|
|
addr_ioremap(0x102000d8, 0x1); //pin54
|
|
addr_ioremap(0x102000dc, 0x1); //pin55
|
|
addr_ioremap(0x102000e0, 0x1); //pin56
|
|
addr_ioremap(0x102000e4, 0x1); //pin57
|
|
addr_ioremap(0x102000e8, 0x1); //pin58
|
|
}
|
|
|
|
static void gpio_pin_pulldown_en(void)
|
|
{
|
|
addr_ioremap(0x0b100080, 0x64); //pin5
|
|
addr_ioremap(0x0b100084, 0x64); //pin6
|
|
addr_ioremap(0x25b00018, 0x64); //pin9
|
|
addr_ioremap(0x25b0001C, 0x64); //pin10
|
|
addr_ioremap(0x25b00020, 0x64); //pin11
|
|
addr_ioremap(0x25b00024, 0x64); //pin12
|
|
addr_ioremap(0x25b00028, 0x64); //pin13
|
|
addr_ioremap(0x25b0002C, 0x64); //pin14
|
|
addr_ioremap(0x25b00030, 0x64); //pin15
|
|
addr_ioremap(0x25b00040, 0x64); //pin16
|
|
addr_ioremap(0x25b0004C, 0x64); //pin17
|
|
addr_ioremap(0x25b00044, 0x64); //pin18
|
|
addr_ioremap(0x25b0003C, 0x64); //pin19
|
|
addr_ioremap(0x25b00038, 0x64); //pin20
|
|
addr_ioremap(0x25b00034, 0x64); //pin21
|
|
addr_ioremap(0x25b00048, 0x64); //pin22
|
|
addr_ioremap(0x0b100078, 0x64); //pin23
|
|
addr_ioremap(0x0b10007C, 0x64); //pin24
|
|
addr_ioremap(0x25b00054, 0x64); //pin25
|
|
addr_ioremap(0x25b00058, 0x64); //pin26
|
|
addr_ioremap(0x0b100028, 0x64); //pin27
|
|
addr_ioremap(0x0b10002C, 0x64); //pin28
|
|
addr_ioremap(0x0b100030, 0x64); //pin29
|
|
addr_ioremap(0x0b100034, 0x64); //pin30
|
|
addr_ioremap(0x0b100038, 0x64); //pin31
|
|
addr_ioremap(0x0b10003C, 0x64); //pin32
|
|
addr_ioremap(0x0b100040, 0x64); //pin33
|
|
addr_ioremap(0x0b100048, 0x64); //pin34
|
|
addr_ioremap(0x0b100044, 0x64); //pin35
|
|
addr_ioremap(0x0b10004C, 0x64); //pin36
|
|
addr_ioremap(0x0b100054, 0x64); //pin37
|
|
addr_ioremap(0x0b100050, 0x64); //pin38
|
|
addr_ioremap(0x0b10005C, 0x64); //pin39
|
|
addr_ioremap(0x0b100058, 0x64); //pin40
|
|
addr_ioremap(0x0b100060, 0x64); //pin41
|
|
addr_ioremap(0x0b100064, 0x64); //pin42
|
|
addr_ioremap(0x0b100068, 0x64); //pin43
|
|
addr_ioremap(0x0b10006C, 0x64); //pin44
|
|
addr_ioremap(0x0b100070, 0x64); //pin45
|
|
addr_ioremap(0x0b100074, 0x64); //pin46
|
|
addr_ioremap(0x25b00070, 0x64); //pin47
|
|
addr_ioremap(0x25b0006C, 0x64); //pin48
|
|
addr_ioremap(0x25b00060, 0x64); //pin49
|
|
addr_ioremap(0x25b0005c, 0x64); //pin50
|
|
addr_ioremap(0x25b00068, 0x64); //pin51
|
|
addr_ioremap(0x25b00064, 0x64); //pin52
|
|
addr_ioremap(0x25b00074, 0x64); //pin53
|
|
addr_ioremap(0x25b00078, 0x64); //pin54
|
|
addr_ioremap(0x25b0007C, 0x64); //pin55
|
|
addr_ioremap(0x25b00080, 0x64); //pin56
|
|
addr_ioremap(0x25b00084, 0x64); //pin57
|
|
addr_ioremap(0x25b00088, 0x64); //pin58
|
|
}
|
|
|
|
static irqreturn_t gpio_wakeup_test_interrupt_call(int irq, void *dev_id)
|
|
{
|
|
disable_irq_nosync(gpio_to_irq(gpio_in_num));
|
|
printk("%s:high level Interrupt triggered success for gpio:%d irq:%d\n",__FUNCTION__,gpio_in_num,irq);
|
|
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
static int gpio_wakeup_test_entry(void)
|
|
{
|
|
int ret = -1;
|
|
|
|
printk("%s:current args:gpio_in_num=%d gpio_test_case=%d\n",__FUNCTION__,gpio_in_num,gpio_test_case);
|
|
if(gpio_in_num == -1)
|
|
{
|
|
printk("you input args is error\n");
|
|
return ret;
|
|
}
|
|
|
|
gpio_free(gpio_in_num);
|
|
|
|
ret = gpio_request(gpio_in_num, "gpio_in\n");
|
|
if (ret != 0) {
|
|
printk("error %d: gpio%d request is failed\n",ret,gpio_in_num);
|
|
return ret;
|
|
}
|
|
|
|
ret = gpio_direction_input(gpio_in_num);
|
|
if (ret != 0) {
|
|
printk("error %d: gpio%d direction input is failed\n",ret,gpio_in_num);
|
|
goto err;
|
|
}
|
|
|
|
ret = request_irq(gpio_to_irq(gpio_in_num), gpio_wakeup_test_interrupt_call, IRQ_TYPE_LEVEL_HIGH, "gpio_interrupt_level_high", NULL);
|
|
if(ret != 0) {
|
|
printk(KERN_ERR "error %d: request irq is failed gpio:%d irq:%d int_type:level_high\n",ret,gpio_in_num,gpio_to_irq(gpio_in_num));
|
|
goto err;
|
|
}
|
|
|
|
//disable_irq(gpio_to_irq(gpio_in_num));
|
|
//enable_irq(gpio_to_irq(gpio_in_num));
|
|
|
|
printk("gpio waite trigger interrupu .....\n");
|
|
|
|
return ret;
|
|
|
|
err:
|
|
gpio_free(gpio_in_num);
|
|
return ret;
|
|
}
|
|
|
|
static void gpio_wakeup_test_exit(void)
|
|
{
|
|
free_irq(gpio_to_irq(gpio_in_num), NULL);
|
|
gpio_free(gpio_in_num);
|
|
gpio_in_num = -1;
|
|
gpio_test_case = 0;
|
|
printk("%s:gpio_in_num=%d int_type=level_high gpio_test_case=%d\n",__FUNCTION__,gpio_in_num,gpio_test_case);
|
|
}
|
|
|
|
static void gpio_test_case_message(void)
|
|
{
|
|
printk("\ndescription:\n");
|
|
printk("you input:\n");
|
|
printk("insmod gpio_test.ko gpio_in_num= gpio_out_num= int_type= gpio_test_case=0\n");
|
|
printk("test gpio input/output/interrupt\n");
|
|
printk("you input:\n");
|
|
printk("insmod gpio_test.ko gpio_in_num= gpio_test_case=1\n");
|
|
printk("test gpio wakeup\n\n");
|
|
}
|
|
|
|
static int __init gpio_test_init(void)
|
|
{
|
|
printk("%s.....\n",__FUNCTION__);
|
|
|
|
gpio_test_case_message();
|
|
gpio_pin_func();
|
|
gpio_pin_pulldown_en();
|
|
|
|
switch (gpio_test_case) {
|
|
case 0 :
|
|
gpio_input_output_interrupt_test_entry();
|
|
break;
|
|
case 1 :
|
|
gpio_wakeup_test_entry();
|
|
break;
|
|
default :
|
|
printk("%s err, no this gpio_test_case(%d).....\n",__FUNCTION__,gpio_test_case);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void __exit gpio_test_exit(void)
|
|
{
|
|
printk("%s.....\n",__FUNCTION__);
|
|
|
|
switch (gpio_test_case) {
|
|
case 0 :
|
|
gpio_input_output_interrupt_test_exit();
|
|
break;
|
|
case 1 :
|
|
gpio_wakeup_test_exit();
|
|
break;
|
|
default :
|
|
printk("%s err, no this gpio_test_case(%d).....\n",__FUNCTION__,gpio_test_case);
|
|
}
|
|
}
|
|
|
|
module_init(gpio_test_init);
|
|
module_exit(gpio_test_exit);
|
|
|
|
MODULE_LICENSE("GPL v2");
|