#include <linux/module.h> #include <linux/kernel.h> #include <linux/clk.h> #include <linux/init.h> #include <linux/input.h> #include <linux/serio.h> #include <plat/regs-adc.h> #include <asm/irq.h> #include <asm/io.h>
static struct clk *adc_clk; static void __iomem *adc_base; static struct input_dev *ts_dev; #define DEVICE_NAME "my2440_TouchScreen" #define WAIT4INT(x) (((x)<<8) | S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | \ S3C2410_ADCTSC_XP_SEN | S3C2410_ADCTSC_XY_PST(3)) static int __init ts_init(void) { int ret; adc_clk = clk_get(NULL, "adc"); if(!adc_clk) { printk(KERN_ERR "falied to find adc clock source\n"); return -ENOENT; } clk_enable(adc_clk); adc_base = ioremap(S3C2410_PA_ADC, 0x20); if(adc_base == NULL) { printk(KERN_ERR "failed to remap register block\n"); ret = -EINVAL; goto err_noclk; } adc_initialize(); ret = request_irq(IRQ_ADC, adc_irq, IRQF_SHARED | IRQF_SAMPLE_RANDOM, DEVICE_NAME, 1); if(ret) { printk(KERN_ERR "IRQ%d error %d\n", IRQ_ADC, ret); ret = -EINVAL; goto err_nomap; } ret = request_irq(IRQ_TC, tc_irq, IRQF_SAMPLE_RANDOM, DEVICE_NAME, 1); if(ret) { printk(KERN_ERR "IRQ%d error %d\n", IRQ_TC, ret); ret = -EINVAL; goto err_noirq; } ts_dev = input_allocate_device(); ts_dev->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS); ts_dev->keybit[BITS_TO_LONGS(BTN_TOUCH)] = BIT(BTN_TOUCH); input_set_abs_params(ts_dev, ABS_X, 0, 0x3FF, 0, 0); input_set_abs_params(ts_dev, ABS_Y, 0, 0x3FF, 0, 0); input_set_abs_params(ts_dev, ABS_PRESSURE, 0, 1, 0, 0); ts_dev->name = DEVICE_NAME; ts_dev->id.bustype = BUS_RS232; ts_dev->id.vendor = 0xDEAD; ts_dev->id.product = 0xBEEF; ts_dev->id.version = 0x0101; input_register_device(ts_dev); return 0; err_noclk: clk_disable(adc_clk); clk_put(adc_clk); err_nomap: iounmap(adc_base); err_noirq: free_irq(IRQ_ADC, 1); return ret; } static void adc_initialize(void) { writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(0xFF), adc_base + S3C2410_ADCCON); writel(0xffff, adc_base + S3C2410_ADCDLY); writel(WAIT4INT(0), adc_base + S3C2410_ADCTSC); } static void __exit ts_exit(void) { disable_irq(IRQ_ADC); disable_irq(IRQ_TC); free_irq(IRQ_ADC, 1); free_irq(IRQ_TC, 1); iounmap(adc_base); if(adc_clk) { clk_disable(adc_clk); clk_put(adc_clk); adc_clk = NULL; } input_unregister_device(ts_dev); } module_init(ts_init); module_exit(ts_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Huang Gang"); MODULE_DESCRIPTION("My2440 Touch Screen Driver"); |