基于设备树的TQ2440触摸屏驱动移植
平台
概述

正文
一、移植触摸屏驱动


tq2440ts@ {
compatible = "tq2440,ts";
reg = <0x58000000 0x100>;
reg-names = "adc_ts_physical";
interrupts = < >, < >;
interrupt-names = "int_ts", "int_adc_s";
clocks = <&clocks PCLK_ADC>;
clock-names = "adc";
};
git clone git@github.com:pengdonglin137/linux-4.9.git -b tq2440_dt
/************************************* NAME:tq2440_ts.c
COPYRIGHT:www.embedsky.net *************************************/
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <asm/io.h>
#include <asm/irq.h> #include <plat/regs-adc.h>
#include <mach/regs-gpio.h> /* For ts.dev.id.version */
#define S3C2410TSVERSION 0x0101 #define WAIT4INT(x) (((x)<<8) | \
S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
S3C2410_ADCTSC_XY_PST()) #define AUTOPST (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST()) static char *tq2440ts_name = "TQ2440 TouchScreen"; static struct input_dev *idev;
static long xp;
static long yp;
static int count; static void __iomem *base_addr; static void touch_timer_fire(unsigned long data)
{
u32 data0;
u32 data1;
int updown; data0 = readl(base_addr+S3C2410_ADCDAT0);
data1 = readl(base_addr+S3C2410_ADCDAT1); updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN)); if (updown) {
if (count != ) {
long tmp; tmp = xp;
xp = yp;
yp = tmp; xp >>= ;
yp >>= ; input_report_abs(idev, ABS_X, xp);
input_report_abs(idev, ABS_Y, yp); input_report_key(idev, BTN_TOUCH, );
input_report_abs(idev, ABS_PRESSURE, );
input_sync(idev);
} xp = ;
yp = ;
count = ; writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
} else {
count = ; input_report_key(idev, BTN_TOUCH, );
input_report_abs(idev, ABS_PRESSURE, );
input_sync(idev); writel(WAIT4INT(), base_addr+S3C2410_ADCTSC);
}
} static struct timer_list touch_timer =
TIMER_INITIALIZER(touch_timer_fire, , ); static irqreturn_t stylus_updown(int irq, void *dev_id)
{
u32 data0;
u32 data1;
int updown; data0 = readl(base_addr+S3C2410_ADCDAT0);
data1 = readl(base_addr+S3C2410_ADCDAT1); updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN)); if (updown)
touch_timer_fire(); return IRQ_HANDLED;
} static irqreturn_t stylus_action(int irq, void *dev_id)
{
u32 data0;
u32 data1; data0 = readl(base_addr+S3C2410_ADCDAT0);
data1 = readl(base_addr+S3C2410_ADCDAT1); xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;
yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;
count++; if (count < (<<)) {
writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
} else {
mod_timer(&touch_timer, jiffies+);
writel(WAIT4INT(), base_addr+S3C2410_ADCTSC);
} return IRQ_HANDLED;
} static int tq2440ts_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
struct clk *adc_clock;
struct resource *tsmem, *irq;
struct input_dev *input_dev;
int ret; if (!node) {
dev_dbg(dev, "of_node is NULL\n");
return -EINVAL;
} adc_clock = devm_clk_get(dev, "adc");
dev_dbg(dev, "adc_clock: %p\n", adc_clock);
if (IS_ERR(adc_clock)) {
dev_err(dev, "cannot get clock\n");
return -ENOENT;
}
clk_prepare(adc_clock);
clk_enable(adc_clock); dev_dbg(dev, "get mem\n");
tsmem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "adc_ts_physical");
if (!tsmem) {
dev_dbg(dev, "get mem resource failed.\n");
ret = -EINVAL;
goto err;
} base_addr = devm_ioremap_resource(dev, tsmem);
if (IS_ERR(base_addr)) {
dev_dbg(dev, "ioremap failed.\n");
ret = PTR_ERR(base_addr);
goto err;
} writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(0xFF),base_addr+S3C2410_ADCCON);
writel(0xffff, base_addr+S3C2410_ADCDLY);
writel(WAIT4INT(), base_addr+S3C2410_ADCTSC); input_dev = devm_input_allocate_device(dev);
if (!input_dev) {
dev_dbg(dev, "ioremap failed.\n");
ret = -ENOMEM;
goto err;
} idev = input_dev;
idev->evbit[] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS); __set_bit(EV_SYN, idev->evbit);
__set_bit(EV_KEY, idev->evbit);
__set_bit(EV_ABS, idev->evbit);
__set_bit(BTN_TOUCH, idev->keybit); input_set_abs_params(idev, ABS_X, , 0x3FF, , );
input_set_abs_params(idev, ABS_Y, , 0x3FF, , );
input_set_abs_params(idev, ABS_PRESSURE, , , , ); idev->name = tq2440ts_name;
idev->id.bustype = BUS_RS232;
idev->id.vendor = 0xDEAD;
idev->id.product = 0xBEEF;
idev->id.version = S3C2410TSVERSION; irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "int_ts");
if (!irq) {
dev_err(dev, "get irq resource int_ts failed.\n");
ret = -EINVAL;
goto err;
}
ret = devm_request_irq(dev, irq->start, stylus_updown, IRQF_ONESHOT, "int_ts", NULL);
if (ret < ){
dev_err(dev, "request irq tsirq %d failed.\n", irq->start);
goto err;
} irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "int_adc_s");
if (!irq) {
dev_err(dev, "get irq resource int_adc_s failed.\n");
ret = -EINVAL;
goto err;
}
ret = devm_request_irq(dev, irq->start, stylus_action, IRQF_ONESHOT, "int_adc_s", NULL);
if (ret < ) {
dev_err(dev, "request irq adcirq %d failed.\n", irq->start);
goto err;
} dev_info(dev, "%s successfully loaded\n", tq2440ts_name);
input_register_device(idev); return ;
err:
clk_disable(adc_clock);
return ret;
} static const struct of_device_id tq2440ts_match[] = {
{ .compatible = "tq2440,ts", .data = (void *) },
{},
}; static struct platform_driver tq2440ts_driver = {
.probe = tq2440ts_probe,
.driver = {
.name = "tq2440ts",
.of_match_table = of_match_ptr(tq2440ts_match),
},
}; static int __init tq2440ts_init(void)
{
return platform_driver_register(&tq2440ts_driver);
} static void __exit tq2440ts_exit(void)
{
platform_driver_unregister(&tq2440ts_driver);
} module_init(tq2440ts_init);
module_exit(tq2440ts_exit); MODULE_LICENSE("GPL");
[root@tq2440 ]# cat /proc/interrupts
CPU0
: s3c-eint Edge eth0
: s3c Edge s3c2410-rtc tick
: s3c Edge samsung_time_irq
: s3c Edge 4d000000.fb
: s3c Edge ohci_hcd:usb1
: s3c Edge .i2c
: s3c Edge s3c2410-rtc alarm
: s3c-level Level .serial
: s3c-level Level .serial
: s3c-level Edge int_ts
: s3c-level Edge int_adc_s
: s3c-level Edge .watchdog
Err:
使用hexdump /dev/input/event0:
[root@tq2440 ]# hexdump /dev/input/event0
cb74 386e bc0b 000b
cb74 386e bc0b 000b 01e4
cb74 386e bc0b 000b 014a
cb74 386e bc0b 000b
cb74 386e bc0b 000b
cb74 386e 0a4e 000c 01dc
cb74 386e 0a4e 000c 01fa
cb74 386e 0a4e 000c
cb74 386e 585a 000c 014a
cb74 386e 585a 000c
二、移植tslib
#!/bin/bash ./autogen.sh mkdir install ./configure \
--prefix="`pwd`/install" \
--host=arm-linux \
ac_cv_func_malloc_0_nonnull=yes make
make install
安装完成后,可以看到:
$ls install
bin/ etc/ include/ lib/ share/
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
修改完成后,重新启动开发板。
三、测试
[root@tq2440 ]# ts_calibrate
xres = , yres =
Took samples...
Top left : X = Y =
Took samples...
Top right : X = Y =
Took samples...
Bot right : X = Y =
Took samples...
Bot left : X = Y =
Took samples...
Center : X = Y =
582.617065 -0.602301 -0.108929
-72.806641 0.023253 0.396149
Calibration constants: - - -
[root@tq2440 ]# ts_test
946785862.424089:
946785862.444036:
946785865.264038:
946785865.284058:
946785865.519036:
946785865.539107:
946785865.559054:
946785865.829038:
基于设备树的TQ2440触摸屏驱动移植的更多相关文章
- 基于设备树的TQ2440的中断(2)
下面以按键中断为例看看基于设备数的中断的用法: 设备树: tq2440_key { compatible = "tq2440,key"; interrupt-parent = &l ...
- 基于设备树的TQ2440的中断(1)
作者 姓名:彭东林 E-mail:pengdonglin137@163.com QQ:405728433 平台 板子:TQ2440 内核:Linux-4.9 u-boot: 2015.04 工具链: ...
- 基于设备树的TQ2440 DMA学习(3)—— DMA控制器驱动
作者 彭东林pengdonglin137@163.com 平台 TQ2440Linux-4.9 概述 上一篇直接操作DMA控制器实现了一个mem2mem的DMA传输,但是这样不符合linux driv ...
- 基于设备树的TQ2440 DMA学习(4)—— client驱动
作者 彭东林pengdonglin137@163.com 平台 TQ2440Linux-4.9 概述 前面分析了DMA控制器驱动,下面我们调用DMAENGINE的API写一个MEM2MEM的驱动 正文 ...
- 基于设备树的TQ2440 DMA学习(1)—— 芯片手册
作者 彭东林pengdonglin137@163.com 平台 TQ2440内核Linux4.9 概述 一直想抽时间学习一下DMA驱动,今天就以S3C2440为例,这款芯片的DMA控制器足够简单,也比 ...
- 基于设备树的TQ2440 DMA学习(2)—— 简单的DMA传输
作者 彭东林 pengdonglin137@163.com 平台 TQ2440 Linux-4.9 概述 上一篇博客分析了DMA控制器的寄存器,循序渐进,下面我们直接操作DMA控制器的寄存器实 ...
- 基于设备树的controller学习(2)
作者 彭东林 pengdonglin137@163.com 平台 TQ2440 Linux-4.10.17 概述 上一篇大概介绍了一下demo-controller的结构,下面结合驱动分析. 正文 ...
- 基于设备树的controller学习(1)
作者 彭东林pengdonglin137@163.com 平台 TQ2440Linux-4.10.17 概述 在设备树中我们经常见到诸如"#clock-cells"."# ...
- 基于设备树的led驱动程序
#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include ...
随机推荐
- Linux内核源码分析--内核启动之(1)zImage自解压过程(Linux-3.0 ARMv7) 【转】
转自:http://blog.chinaunix.net/uid-25909619-id-4938388.html 研究内核源码和内核运行原理的时候,很总要的一点是要了解内核的初始情况,也就是要了解内 ...
- vs 调试不进入断点
背景 或许当时环境不知发了什么神经,就是不调试了.竟然还有这种简单错误. 解决方案---配置管理器---选择debug模式
- Java并发编程、多线程、线程池…
<实战java高并发程序设计>源码整理https://github.com/petercao/concurrent-programming/blob/master/README.md Ja ...
- .NetCore 利用Jenkins在 Windows平台下打包发布Angular项目
准备环境 安装Jenkins 首先装node,版本根据实际环境而定(node安装包中包含了npm) 安装一般都配置好了环境变量,检查下如果没有就配置下 Jenkins中安装NPM插件 GIt获取代码 ...
- StringUtils一些常用方法
StringUtils是org.apache.commons.lang jar包里面的类方法,当输入参数String为null则不会抛出NullPointerException,而是做了相应处理,nu ...
- nginx支持ssl双向认证配置
nginx支持ssl双向认证配置 listen 443; server_name test.com; ssl on; ssl_certificate server.crt; //server端公钥 s ...
- 在windows下使用多版本Python安装相应的虚拟开发环境
在windows下面使用多版本Python安装相应的虚拟开发环境 在搭建一个项目的时候,希望使用最新版的Python3.7版本,但是Python3.6的版本也要留下,那么问题来了,如何解决这个问题 ...
- sqrt
sqrt特别慢,两边同时平方,尽量避免开方.
- 003.KVM虚拟机部署-CentOS6.8
一 实验说明 CentOS 7的KVM虚拟机推荐使用qcow2磁盘格式,本实验在KVM中安装CentOS 6.8 64虚拟机. 二 命令部署过程 2.1 上传镜像 使用winscp上传至/data/i ...
- Sublime快速入门
在当前的互联网时代,任何程序语言和相关技术都只是实现互联网应用的一种手段,这也就造成了大量的互联网工程师长期与不同的语言.技术.系统环境.IDE等打交道.因此一个相对统一方便的IDE对于程序员来说显得 ...