#include <linux/module.h> #include <linux/init.h> #include <linux/ioport.h> #include <linux/interrupt.h> #include <linux/input.h> #include <asm/io.h> #include <asm/arch/regs-gpio.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("zhanglong"); struct touchscreen { unsigned long adccon, adctsc, adcdly, adcdat0, adcdat1, adcupdn; struct clk *ts_clk; int down; void (*wait4irq)(struct touchscreen *, int); //set ts in wait-for-irq mode int (*isdown)(struct touchscreen *); //check stylus down or not struct input_dev dev; }; unsigned long ts_virt; struct touchscreen s3c2440_ts; void s3c2440_ts_wait4irq(struct touchscreen *ts, int down) { if (down) { iowrite32( 0x3 | ( 1 << 4) | ( 1 << 6) | (1 << 7) , ts->adctsc); } else { iowrite32( 0x3 | ( 1 << 4) | ( 1 << 6) | (1 << 7) | (1 << 8) , ts->adctsc); } } int s3c2440_ts_isdown(struct touchscreen *ts) { int down; down = ioread32(ts->adcupdn); iowrite32(0, ts->adcupdn); return (down & 1); } irqreturn_t s3c2440_tstc_handle(int irq, struct touchscreen *ts) { if(IRQ_TC == irq) { if(ts->isdown(ts)) { //stylus down ts->wait4irq(ts, 0); input_report_abs(&ts->dev, ABS_PRESSURE, 1); s3c2410_gpio_setpin(S3C2410_GPF4, 0); //LED on } else { //stylus up ts->wait4irq(ts, 1); input_report_abs(&ts->dev, ABS_PRESSURE, 0); input_sync(&ts->dev); s3c2410_gpio_setpin(S3C2410_GPF4, 1); //LED off } } return IRQ_HANDLED; } int test_init(void) { int ret; ret = request_mem_region(0x58000000, 0x1000, "s3c2440-ts"); if(NULL == ret) { printk("request_mem_region failed .\n"); ret = -EBUSY; goto err0; } ts_virt = ioremap(0x58000000, 0x1000); s3c2440_ts.down = 0; s3c2440_ts.adccon = ts_virt; s3c2440_ts.adctsc = ts_virt + 0x04; s3c2440_ts.adcdly = ts_virt + 0x08; s3c2440_ts.adcdat0 = ts_virt + 0x0c; s3c2440_ts.adcdat1 = ts_virt + 0x10; s3c2440_ts.adcupdn = ts_virt + 0x14; //--- s3c2440_ts.wait4irq = s3c2440_ts_wait4irq; s3c2440_ts.isdown = s3c2440_ts_isdown; ret = request_irq(IRQ_TC, s3c2440_tstc_handle, 0, "s3c2440-ts", &s3c2440_ts); if(0 != ret) { printk("request irq[1] failed .\n"); ret = -EBUSY; goto err1; } s3c2440_ts.ts_clk = clk_get(NULL, "adc"); clk_use(s3c2440_ts.ts_clk); clk_enable(s3c2440_ts.ts_clk); s3c2440_ts.wait4irq(&s3c2440_ts, 1); s3c2440_ts.dev.evbit[0] = BIT(EV_ABS) | BIT(EV_SYN); input_set_abs_params(&s3c2440_ts.dev, ABS_PRESSURE, 0, 1, 0, 0); input_register_device(&s3c2440_ts.dev); return 0; err1: iounmap(ts_virt); release_mem_region(0x58000000, 0x1000); err0: return ret; } void test_exit(void) { input_unregister_device(&s3c2440_ts.dev); free_irq(IRQ_TC, &s3c2440_ts); clk_disable(s3c2440_ts.ts_clk); clk_unuse(s3c2440_ts.ts_clk); clk_put(s3c2440_ts.ts_clk); iounmap(ts_virt); release_mem_region(0x58000000, 0x1000); } module_init(test_init); module_exit(test_exit); |