基于设备树的TQ2440触摸屏驱动移植
生活随笔
收集整理的這篇文章主要介紹了
基于设备树的TQ2440触摸屏驱动移植
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
平臺
開發板:tq2440 內核:Linux-4.9 u-boot:u-boot-2015.04 ?概述
之前移植了LCD驅動,下面繼續移植觸摸屏驅動,然后將tslib也移植上去。正文
一、移植觸摸屏驅動
為了簡單起見我們對TQ2440自帶的觸摸屏驅動進行改寫,改成設備樹的形式。 1、設備樹 觸摸屏使用了兩個中斷,如下: 這兩個中斷是子中斷,隸屬于主中斷INT_ADC: 關于寄存器,參考芯片手冊的第16章,知道了上面的信息,我們就可以得到如下的設備樹節點(可以參考博文基于設備樹的TQ2440的中斷(1)): tq2440ts@5800000 { compatible = "tq2440,ts"; reg = <0x58000000 0x100>; reg-names = "adc_ts_physical"; interrupts = <1 31 9 3>, <1 31 10 3>; interrupt-names = "int_ts", "int_adc_s"; clocks = <&clocks PCLK_ADC>; clock-names = "adc"; };?2、驅動 對應的觸摸屏驅動是drivers/input/touchscreen/tq2440_ts.c 這部分我已經上傳到github上面了,可以使用下面的命令下載: git clone git@github.com:pengdonglin137/linux-4.9.git -b tq2440_dt
代碼如下: 1 /************************************* 2 3 NAME:tq2440_ts.c 4 COPYRIGHT:www.embedsky.net 5 6 *************************************/ 7 #include <linux/errno.h> 8 #include <linux/kernel.h> 9 #include <linux/module.h> 10 #include <linux/slab.h> 11 #include <linux/input.h> 12 #include <linux/init.h> 13 #include <linux/serio.h> 14 #include <linux/delay.h> 15 #include <linux/platform_device.h> 16 #include <linux/clk.h> 17 #include <linux/of_device.h> 18 #include <linux/of.h> 19 #include <linux/of_gpio.h> 20 #include <asm/io.h> 21 #include <asm/irq.h> 22 23 #include <plat/regs-adc.h> 24 #include <mach/regs-gpio.h> 25 26 /* For ts.dev.id.version */ 27 #define S3C2410TSVERSION 0x0101 28 29 #define WAIT4INT(x) (((x)<<8) | \ 30 S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \ 31 S3C2410_ADCTSC_XY_PST(3)) 32 33 #define AUTOPST (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \ 34 S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST(0)) 35 36 static char *tq2440ts_name = "TQ2440 TouchScreen"; 37 38 static struct input_dev *idev; 39 static long xp; 40 static long yp; 41 static int count; 42 43 static void __iomem *base_addr; 44 45 static void touch_timer_fire(unsigned long data) 46 { 47 u32 data0; 48 u32 data1; 49 int updown; 50 51 data0 = readl(base_addr+S3C2410_ADCDAT0); 52 data1 = readl(base_addr+S3C2410_ADCDAT1); 53 54 updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN)); 55 56 if (updown) { 57 if (count != 0) { 58 long tmp; 59 60 tmp = xp; 61 xp = yp; 62 yp = tmp; 63 64 xp >>= 2; 65 yp >>= 2; 66 67 input_report_abs(idev, ABS_X, xp); 68 input_report_abs(idev, ABS_Y, yp); 69 70 input_report_key(idev, BTN_TOUCH, 1); 71 input_report_abs(idev, ABS_PRESSURE, 1); 72 input_sync(idev); 73 } 74 75 xp = 0; 76 yp = 0; 77 count = 0; 78 79 writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC); 80 writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON); 81 } else { 82 count = 0; 83 84 input_report_key(idev, BTN_TOUCH, 0); 85 input_report_abs(idev, ABS_PRESSURE, 0); 86 input_sync(idev); 87 88 writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC); 89 } 90 } 91 92 static struct timer_list touch_timer = 93 TIMER_INITIALIZER(touch_timer_fire, 0, 0); 94 95 static irqreturn_t stylus_updown(int irq, void *dev_id) 96 { 97 u32 data0; 98 u32 data1; 99 int updown; 100 101 data0 = readl(base_addr+S3C2410_ADCDAT0); 102 data1 = readl(base_addr+S3C2410_ADCDAT1); 103 104 updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN)); 105 106 if (updown) 107 touch_timer_fire(0); 108 109 return IRQ_HANDLED; 110 } 111 112 static irqreturn_t stylus_action(int irq, void *dev_id) 113 { 114 u32 data0; 115 u32 data1; 116 117 data0 = readl(base_addr+S3C2410_ADCDAT0); 118 data1 = readl(base_addr+S3C2410_ADCDAT1); 119 120 xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK; 121 yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK; 122 count++; 123 124 if (count < (1<<2)) { 125 writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC); 126 writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON); 127 } else { 128 mod_timer(&touch_timer, jiffies+1); 129 writel(WAIT4INT(1), base_addr+S3C2410_ADCTSC); 130 } 131 132 return IRQ_HANDLED; 133 } 134 135 static int tq2440ts_probe(struct platform_device *pdev) 136 { 137 struct device *dev = &pdev->dev; 138 struct device_node *node = dev->of_node; 139 struct clk *adc_clock; 140 struct resource *tsmem, *irq; 141 struct input_dev *input_dev; 142 int ret; 143 144 if (!node) { 145 dev_dbg(dev, "of_node is NULL\n"); 146 return -EINVAL; 147 } 148 149 adc_clock = devm_clk_get(dev, "adc"); 150 dev_dbg(dev, "adc_clock: %p\n", adc_clock); 151 if (IS_ERR(adc_clock)) { 152 dev_err(dev, "cannot get clock\n"); 153 return -ENOENT; 154 } 155 clk_prepare(adc_clock); 156 clk_enable(adc_clock); 157 158 dev_dbg(dev, "get mem\n"); 159 tsmem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "adc_ts_physical"); 160 if (!tsmem) { 161 dev_dbg(dev, "get mem resource failed.\n"); 162 ret = -EINVAL; 163 goto err; 164 } 165 166 base_addr = devm_ioremap_resource(dev, tsmem); 167 if (IS_ERR(base_addr)) { 168 dev_dbg(dev, "ioremap failed.\n"); 169 ret = PTR_ERR(base_addr); 170 goto err; 171 } 172 173 writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(0xFF),base_addr+S3C2410_ADCCON); 174 writel(0xffff, base_addr+S3C2410_ADCDLY); 175 writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC); 176 177 input_dev = devm_input_allocate_device(dev); 178 if (!input_dev) { 179 dev_dbg(dev, "ioremap failed.\n"); 180 ret = -ENOMEM; 181 goto err; 182 } 183 184 idev = input_dev; 185 idev->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS); 186 187 188 __set_bit(EV_SYN, idev->evbit); 189 __set_bit(EV_KEY, idev->evbit); 190 __set_bit(EV_ABS, idev->evbit); 191 __set_bit(BTN_TOUCH, idev->keybit); 192 193 input_set_abs_params(idev, ABS_X, 0, 0x3FF, 0, 0); 194 input_set_abs_params(idev, ABS_Y, 0, 0x3FF, 0, 0); 195 input_set_abs_params(idev, ABS_PRESSURE, 0, 1, 0, 0); 196 197 idev->name = tq2440ts_name; 198 idev->id.bustype = BUS_RS232; 199 idev->id.vendor = 0xDEAD; 200 idev->id.product = 0xBEEF; 201 idev->id.version = S3C2410TSVERSION; 202 203 irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "int_ts"); 204 if (!irq) { 205 dev_err(dev, "get irq resource int_ts failed.\n"); 206 ret = -EINVAL; 207 goto err; 208 } 209 ret = devm_request_irq(dev, irq->start, stylus_updown, IRQF_ONESHOT, "int_ts", NULL); 210 if (ret < 0){ 211 dev_err(dev, "request irq tsirq %d failed.\n", irq->start); 212 goto err; 213 } 214 215 irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "int_adc_s"); 216 if (!irq) { 217 dev_err(dev, "get irq resource int_adc_s failed.\n"); 218 ret = -EINVAL; 219 goto err; 220 } 221 ret = devm_request_irq(dev, irq->start, stylus_action, IRQF_ONESHOT, "int_adc_s", NULL); 222 if (ret < 0) { 223 dev_err(dev, "request irq adcirq %d failed.\n", irq->start); 224 goto err; 225 } 226 227 dev_info(dev, "%s successfully loaded\n", tq2440ts_name); 228 input_register_device(idev); 229 230 return 0; 231 err: 232 clk_disable(adc_clock); 233 return ret; 234 } 235 236 static const struct of_device_id tq2440ts_match[] = { 237 { .compatible = "tq2440,ts", .data = (void *)0 }, 238 {}, 239 }; 240 241 static struct platform_driver tq2440ts_driver = { 242 .probe = tq2440ts_probe, 243 .driver = { 244 .name = "tq2440ts", 245 .of_match_table = of_match_ptr(tq2440ts_match), 246 }, 247 }; 248 249 static int __init tq2440ts_init(void) 250 { 251 return platform_driver_register(&tq2440ts_driver); 252 } 253 254 static void __exit tq2440ts_exit(void) 255 { 256 platform_driver_unregister(&tq2440ts_driver); 257 } 258 259 module_init(tq2440ts_init); 260 module_exit(tq2440ts_exit); 261 262 MODULE_LICENSE("GPL"); View Code 3、測試 查看中斷信息: [root@tq2440 ]# cat /proc/interrupts CPU0 7: 973 s3c-eint 7 Edge eth08: 0 s3c 8 Edge s3c2410-rtc tick13: 559459 s3c 13 Edge samsung_time_irq16: 0 s3c 16 Edge 4d000000.fb26: 0 s3c 26 Edge ohci_hcd:usb127: 4 s3c 27 Edge 54000000.i2c30: 0 s3c 30 Edge s3c2410-rtc alarm32: 218 s3c-level 32 Level 50000000.serial33: 11203 s3c-level 33 Level 50000000.serial41: 758 s3c-level 41 Edge int_ts42: 16712 s3c-level 42 Edge int_adc_s59: 0 s3c-level 59 Edge 53000000.watchdog Err: 0
?使用hexdump /dev/input/event0:
[root@tq2440 ]# hexdump /dev/input/event0 0000000 cb74 386e bc0b 000b 0003 0000 0201 0000 0000010 cb74 386e bc0b 000b 0003 0001 01e4 0000 0000020 cb74 386e bc0b 000b 0001 014a 0001 0000 0000030 cb74 386e bc0b 000b 0003 0018 0001 0000 0000040 cb74 386e bc0b 000b 0000 0000 0000 0000 0000050 cb74 386e 0a4e 000c 0003 0000 01dc 0000 0000060 cb74 386e 0a4e 000c 0003 0001 01fa 0000 0000070 cb74 386e 0a4e 000c 0000 0000 0000 0000 0000080 cb74 386e 585a 000c 0001 014a 0000 0000 0000090 cb74 386e 585a 000c 0003 0018 0000 0000二、移植tslib
參考: http://www.latelee.org/embedded-linux/porting-linux-tslib.html http://www.it165.net/embed/html/201409/2656.html 登陸http://www.tslib.org/下載最新的版本: https://github.com/kergoth/tslib/releases/download/1.10/tslib-1.10.tar.xz 或者tslib-1.10.tar.gz 編譯安裝: #!/bin/bash./autogen.shmkdir install./configure \ --prefix="`pwd`/install" \ --host=arm-linux \ ac_cv_func_malloc_0_nonnull=yesmake make install安裝完成后,可以看到:
$ls install bin/ etc/ include/ lib/ share/ 將這些文件拷貝到開發板上面,然后修改板子上面的/etc/profile文件,添加如下內容: echo "Set Env for Tslib" export TSLIB_ROOT=/ export TSLIB_TSDEVICE=/dev/input/event0 export TSLIB_CONFFILE=$TSLIB_ROOT/etc/ts.conf export TSLIB_PLUGINDIR=$TSLIB_ROOT/lib/ts export TSLIB_CALIBFILE=/etc/pointercal export TSLIB_CONSOLEDEVICE=none export TSLIB_FBDEVICE=/dev/fb0 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TSLIB_ROOT/lib?修改完成后,重新啟動開發板。
三、測試
運行ts_calibrate生成校準數據 [root@tq2440 ]# ts_calibrate xres = 480, yres = 272 Took 4 samples... Top left : X = 870 Y = 279 Took 8 samples... Top right : X = 162 Y = 277 Took 5 samples... Bot right : X = 156 Y = 757 Took 2 samples... Bot left : X = 688 Y = 660 Took 3 samples... Center : X = 517 Y = 522 582.617065 -0.602301 -0.108929 -72.806641 0.023253 0.396149 Calibration constants: 38182392 -39472 -7138 -4771456 1523 25962 65536 運行ts_test測試: [root@tq2440 ]# ts_test 946785862.424089: 321 141 1 946785862.444036: 321 141 0 946785865.264038: 82 196 1 946785865.284058: 82 196 0 946785865.519036: 26 219 1 946785865.539107: 29 219 1 946785865.559054: 30 220 0 946785865.829038: 229 206 1 完。總結
以上是生活随笔為你收集整理的基于设备树的TQ2440触摸屏驱动移植的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SEO优化_关键词布局与选择
- 下一篇: 改变记忆的好习惯