kobox : key driver -v2

kobox中的key.ko的源码基本功能已经完成

数据结构已经调整OK

之前每个独立的GPIO和中断也用数据结构组织了起来

下一步:

1. 处理中断,使用workqueue、tasklet机制

2. 增加proc功能

目前的src:

#include "key.h"

#define S3C_ADDR_BASE	0xF6000000
#define S3C_ADDR(x)	(S3C_ADDR_BASE + (x))
#define S3C2410_PA_UART		(0x50000000)
#define S3C2410_PA_GPIO		(0x56000000)
#define S3C_VA_UART	S3C_ADDR(0x01000000)	/* UART */
#define S3C24XX_PA_UART		S3C2410_PA_UART
#define S3C24XX_VA_UART		S3C_VA_UART
#define S3C24XX_PA_GPIO		S3C2410_PA_GPIO
#define S3C24XX_VA_GPIO		((S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART)

#define S3C2410_GPIOREG(x) ((x) + S3C24XX_VA_GPIO)

#define S3C2410_GPBCON	   S3C2410_GPIOREG(0x10)
#define S3C2410_GPBDAT	   S3C2410_GPIOREG(0x14)
#define S3C2410_GPBUP	   S3C2410_GPIOREG(0x18)

#define S3C2410_GPFCON	   S3C2410_GPIOREG(0x50)
#define S3C2410_GPFDAT	   S3C2410_GPIOREG(0x54)
#define S3C2410_GPFUP	   S3C2410_GPIOREG(0x58)

#define S3C2410_EXTINT0	   S3C2410_GPIOREG(0x88)
#define S3C2410_EXTINT1	   S3C2410_GPIOREG(0x8C)
#define S3C2410_EXTINT2	   S3C2410_GPIOREG(0x90)

#define S3C2410_CPUIRQ_OFFSET	 (16)
#define S3C2410_IRQ(x) ((x) + S3C2410_CPUIRQ_OFFSET)
/* main cpu interrupts */
#define IRQ_EINT0      S3C2410_IRQ(0)	    /* 16 */
#define IRQ_EINT1      S3C2410_IRQ(1)		/* 17 */
#define IRQ_EINT2      S3C2410_IRQ(2)		/* 18 */
#define IRQ_EINT4t7    S3C2410_IRQ(4)	    /* 20 */
#define IRQ_EINT4      S3C2410_IRQ(36)	   /* 52 */

#define IRQF_DISABLED		0x00000020
#define IRQF_SHARED		0x00000080
#define IRQF_PROBE_SHARED	0x00000100
#define __IRQF_TIMER		0x00000200
#define IRQF_PERCPU		0x00000400
#define IRQF_NOBALANCING	0x00000800
#define IRQF_IRQPOLL		0x00001000
#define IRQF_ONESHOT		0x00002000
#define IRQF_NO_SUSPEND	0x00004000
#define IRQF_FORCE_RESUME	0x00008000
#define IRQF_NO_THREAD		0x00010000
#define IRQF_EARLY_RESUME	0x00020000

typedef struct gpioRes
{
	int irqNum;		/* 中断号 */
	unsigned int ctrlReg;	/* 控制寄存器,用于设置复用为GPIO */
	unsigned int ctrlBit; 	/* 控制寄存器的哪一位,用于复用为GPIO */
	unsigned int trigReg;	/* 中断方式寄存器,设置中断的触发方式 */
	unsigned int trigBit;	/* 中断方式寄存器哪一位,设置中断的触发方式 */
	unsigned int irqFlag;	/* 共享还是不共享,注册中断的flag */
	char irqName[32];		/* 中断名称 */
	char Reserved[10];		/* 保留 */
}gpioRes;

#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0]))

static int kobox_key_open(struct inode *inode, struct file *file)
{
	return 0;
}

static int kobox_key_release(struct inode *inode, struct file *file)
{
	return 0;
}

static long kobox_key_ioctl(struct file *file, unsigned int cmd,
			   unsigned long arg)
{
	return 0;
}

gpioRes key_gpio_res[4] =
{
	{IRQ_EINT1, S3C2410_GPFCON, 2, S3C2410_EXTINT0, 5, NULL, "key1"},	/* key1 */
	{IRQ_EINT4, S3C2410_GPFCON, 8, S3C2410_EXTINT0, 17, IRQF_SHARED, "key2"},	/* key2 */
	{IRQ_EINT2, S3C2410_GPFCON, 4, S3C2410_EXTINT0, 9, NULL, "key3"},	/* key3 */
	{IRQ_EINT0, S3C2410_GPFCON, 0, S3C2410_EXTINT0, 1, NULL, "key4"},	/* key4 */
};

static void set_gpio_as_eint(void)
{
	int i;
	unsigned uiVal = 0;

	for(i=0; i<	ARRAY_SIZE(key_gpio_res); i++)
	{
		uiVal = readl(key_gpio_res[i].ctrlReg);
		uiVal &= ~(0x01 << key_gpio_res[i].ctrlBit);
		uiVal |= (0x01 << (key_gpio_res[i].ctrlBit + 1));
		writel(uiVal, key_gpio_res[i].ctrlReg);
	}

	return;
}

static irqreturn_t kobox_gpio_irq_handle(int irq, void *dev_id)
{
	//disable_irq(IRQ_EINT0);
	printk("irq = %d\n", irq);
	 
	//enable_irq(IRQ_EINT0);
	return IRQ_RETVAL(IRQ_HANDLED);
}

static int request_irq_for_gpio(void)
{
	int i;
	int ret;
	unsigned uiVal;
	int nouse;

	for(i=0; i<ARRAY_SIZE(key_gpio_res);i++)
	{
		uiVal = readl(key_gpio_res[i].trigReg);
		uiVal |= (0x1 << key_gpio_res[i].trigBit);
		uiVal &= ~(0x1 << (key_gpio_res[i].trigBit + 1));
		writel(uiVal, key_gpio_res[i].trigReg);

		ret = request_irq(key_gpio_res[i].irqNum, 
						   kobox_gpio_irq_handle,
						   key_gpio_res[i].irqFlag,
						   key_gpio_res[i].irqName,
						   (void *)key_gpio_res[i].irqName);
		if(ret)
			printk("[func:%s][line:%d] request_irq failed, ret:%d!\n", __FUNCTION__,__LINE__,ret);
		else
			printk("[func:%s][line:%d] request_irq ok, irq:%d!\n", __FUNCTION__,__LINE__, key_gpio_res[i].irqNum);	
	}

	return 0;
}

struct file_operations kobox_key_operations = {
	.owner          = THIS_MODULE,
	.open           = kobox_key_open,
	.release        = kobox_key_release,
	.unlocked_ioctl = kobox_key_ioctl,
};

//GPB0
int major;
int minor;
struct cdev cdev;
struct class *kobox_key_class;
struct device *pstdev = NULL;
#define GPIO_KEY_NAME "kobox_key"

int __init key_drv_init(void)
{
	int error;
	dev_t dev;

	printk("#####enter key_drv_init!\n");

	major = register_chrdev(0, GPIO_KEY_NAME, &kobox_key_operations);
	if (major < 0)
	{
		printk(" can't register major number\n");
		return major;
	}

	/* create class */
	kobox_key_class = class_create(THIS_MODULE, GPIO_KEY_NAME);
	if(IS_ERR(kobox_key_class))
	{
		printk("class_create failed!\n");
		goto fail;
	}

	/* create /dev/kobox_gpio */
	pstdev = device_create(kobox_key_class, NULL, MKDEV(major, 0), NULL, GPIO_KEY_NAME);
	if(!pstdev)
	{
		printk("device_create failed!\n");
		goto fail1;
	}

	/* set gpf0/1/2/4 as extern interrupt pins */
	set_gpio_as_eint();

	request_irq_for_gpio();

	printk("#####key_drv_init ok!\n");
	
	return 0;
fail1:
	class_destroy(kobox_key_class);
fail:
	unregister_chrdev(major, GPIO_KEY_NAME);
	return -1;
}

void __exit key_drv_exit(void)
{
	printk("exit gpio drv!\n");	

	device_destroy(kobox_key_class, MKDEV(major, 0));
	class_destroy(kobox_key_class);
	unregister_chrdev(major, GPIO_KEY_NAME);

	return;
}

module_init(key_drv_init);
module_exit(key_drv_exit);
MODULE_LICENSE("GPL");


你可能感兴趣的:(kobox : key driver -v2)