ckfwq/linux-3.0.4/drivers/char/test_gpio.c

207 lines
5.4 KiB
C

#include <linux/types.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/rcupdate.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/completion.h>
#include <asm/io.h>
#include <linux/fs.h>
#include <linux/fcntl.h>
#include <asm/uaccess.h>
#include <linux/gpio.h>
#include <gsc3280/gpio.h>
#include <gsc3280/sysctl.h>
#define GSC3280_SET_GPIO_REG_BIT(reg) do {\
unsigned int reg_val = 0;\
reg_val = __raw_readl((volatile unsigned int *)(reg));\
reg_val |= (0x01 << tgpios[0].gpio);\
__raw_writel(reg_val, (volatile unsigned int *)(reg));\
} while (0)
#define GSC3280_CLR_GPIO_REG_BIT(reg) do {\
unsigned int reg_val = 0;\
reg_val = __raw_readl((volatile unsigned int *)(reg));\
reg_val &= ~(0x01 << tgpios[0].gpio);\
__raw_writel(reg_val, (volatile unsigned int *)(reg));\
} while (0)
enum{
TGPIO, //GPIO23
TGPIO_MAX_PIN_NR
};
struct gpio tgpios[TGPIO_MAX_PIN_NR] = {
{GSC3280_GPA(29), GPIOF_IN, "GPIO"},
};
struct tgpio {
struct cdev cdev;
struct gpio *tgpio;
struct class *tgpio_class;
dev_t dev;
struct mutex t_lock;
};
struct tgpio tgpio_priv;
int test()
{
printk(KERN_INFO "Do something !\n");
GSC3280_SET_GPIO_REG_BIT(GSC3280_REGADDR_GPIO_INTEN);
GSC3280_SET_GPIO_REG_BIT(GSC3280_REGADDR_GPIO_PORTA_EOI);
GSC3280_CLR_GPIO_REG_BIT(GSC3280_REGADDR_GPIO_INTMASK);
return 0;
}
irqreturn_t tgpio_isr ( int irq, void * dev_id )
{
if(*(volatile unsigned int*)0xbc110040 & 1 << 29) //GPIO29
{
printk(KERN_INFO "in vuart_isr\n");
GSC3280_SET_GPIO_REG_BIT(GSC3280_REGADDR_GPIO_INTMASK);
GSC3280_CLR_GPIO_REG_BIT(GSC3280_REGADDR_GPIO_INTEN);
test();
GSC3280_SET_GPIO_REG_BIT(GSC3280_REGADDR_GPIO_PORTA_EOI);
}
return IRQ_HANDLED;
}
static int tgpio_open(struct inode *inode, struct file *filp)
{
return 0;
}
static int tgpio_release(struct inode *inode, struct file *filp)
{
return 0;
}
void tgpio_gpio_ctrl(void)
{
#if 0
//边沿触发
GSC3280_SET_GPIO_REG_BIT(GSC3280_REGADDR_GPIO_INTTYPE_LEVEL);
//GSC3280_CLR_GPIO_REG_BIT(GSC3280_REGADDR_GPIO_INTTYPE_LEVEL);
#endif
//
GSC3280_CLR_GPIO_REG_BIT(GSC3280_REGADDR_GPIO_INTTYPE_LEVEL);
GSC3280_CLR_GPIO_REG_BIT(GSC3280_REGADDR_GPIO_INT_POLARITY);
GSC3280_CLR_GPIO_REG_BIT(GSC3280_REGADDR_GPIO_INT_POLARITY);
//去毛刺
GSC3280_SET_GPIO_REG_BIT(GSC3280_REGADDR_GPIO_DEBOUNCE);
//不屏蔽该中断
GSC3280_CLR_GPIO_REG_BIT(GSC3280_REGADDR_GPIO_INTMASK);
GSC3280_SET_GPIO_REG_BIT(GSC3280_REGADDR_GPIO_INTEN);
GSC3280_SET_GPIO_REG_BIT(GSC3280_REGADDR_GPIO_PORTA_EOI);
}
struct file_operations tgpio_fops = {
.owner = THIS_MODULE,
.open = tgpio_open,
.release = tgpio_release,
};
static int __init tgpio_init(void)
{
int err,ret;
int result;
int major;
int p_irq;
printk(KERN_INFO "test gpio init \n");
result = alloc_chrdev_region(&tgpio_priv.dev, 0, 0, "tgpio");
major = MAJOR(tgpio_priv.dev);
if (result < 0) {
printk(KERN_WARNING "vuart: can't get major %d\n", major);
return result;
}
cdev_init(&tgpio_priv.cdev, &tgpio_fops);
tgpio_priv.cdev.owner = THIS_MODULE;
tgpio_priv.cdev.ops = &tgpio_fops;
err = cdev_add(&tgpio_priv.cdev, tgpio_priv.dev, 1);
if (err) {
printk(KERN_NOTICE "Error[%d] cdev_add .\n", err);
return -1;
}
tgpio_priv.tgpio_class = class_create(THIS_MODULE, "tgpio");
if (IS_ERR(tgpio_priv.tgpio_class)) {
printk(KERN_ERR "Failed in create vuart_cdev class\n");
return -1;
}
device_create(tgpio_priv.tgpio_class, NULL, tgpio_priv.dev, NULL, "tgpio");
p_irq = gpio_to_irq(tgpios[TGPIO].gpio);
ret = gpio_request_array(tgpios, TGPIO_MAX_PIN_NR);
if (ret < 0)
{
printk(KERN_INFO "GPIO request error \n");
}
tgpio_priv.tgpio = tgpios;
err = request_irq(p_irq, &tgpio_isr, IRQF_SHARED, "gsc3280-gpio", &tgpio_priv);
if (err < 0) {
printk(KERN_ERR "test_gpio request_irq[%d] failed!\n", p_irq);
err = -ENODEV;
goto FREE_GPIO;
}
tgpio_gpio_ctrl();
return 0;
FREE_GPIO:
gpio_free_array(tgpios, TGPIO_MAX_PIN_NR);
return err;
}
static void __exit tgpio_exit(void)
{
int p_irq;
p_irq = gpio_to_irq(tgpios[TGPIO].gpio);
free_irq(p_irq, &tgpios[TGPIO]);
gpio_free_array(tgpios, TGPIO_MAX_PIN_NR);
cdev_del(&tgpio_priv.cdev);
unregister_chrdev_region(tgpio_priv.dev, 1);
device_destroy(tgpio_priv.tgpio_class, tgpio_priv.dev);
class_destroy(tgpio_priv.tgpio_class);
}
module_init(tgpio_init);
module_exit(tgpio_exit);
MODULE_AUTHOR("songxingjia@china-cpu.com");
MODULE_DESCRIPTION("GSC3280 INTERRUPT GPIO Driver");
MODULE_LICENSE("GPL");