207 lines
5.4 KiB
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");
|