基于设备树的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 ...
随机推荐
- mysql grep database error(cannot rmdir /dbname)
service mysql stop cd /var/lib/mysql/dbname rm -rf .fmr rm -rf .txt service mysql start srop databas ...
- Qt 数字和字符处理总结
1. 四舍五入保留小数几位 QString str="12.3456789"; double d1=str.toDouble(); qDebug()<<"d1 ...
- Eureka的自我保护模式
一 Eureka的自我保护模式 进入自我保护模式最直观的体现就是Eureka Server首页的警告,如下图: 默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,E ...
- C#操作Mongo进行数据读写
C#操作MongoHelp类 using System; using System.Collections.Generic; using System.Linq; using System.Web; ...
- 《剑指offer》写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
弱菜刷题还是刷中文题好了,没必要和英文过不去,现在的重点是基本代码能力的恢复. [题目] 剑指offer 写一个函数,求两个整数之和,要求在函数体内不得使用+.-.*./四则运算符号. [思路] 直觉 ...
- Gearman In Action
分布式任务系统是一个常见的需求,如果将 Gearman 作为 build block 来搭建这个系统的话,这样能够 make your life much easier. 首先看看 Gearman 是 ...
- 一个linux下简单的纯C++实现Http请求类(GET,POST,上传,下载)
目录 一个linux下简单的纯C++实现Http请求类(GET,POST,上传,下载) Http协议简述 HttpRequest类设计 请求部分 接收部分 关于上传和下载 Cpp实现 关于源码中的Lo ...
- vue-router填坑之路
1.在结构化css时,习惯将不同的css文件通过一个入口文件打包,而入口文件在引入其他css文件时,需要强烈注意,要在单行末尾加分号: 少分号的,单行相对应的css文件会引用无效 @import '. ...
- 用Thread类创建线程
在Java中创建线程有两种方法:使用Thread类和使用Runnable接口.在使用Runnable接口时需要建立一个Thread实例.因此,无论是通过Thread类还是Runnable接口建立线程, ...
- Linux驱动之串口(UART)
<uart驱动程序概述> 在嵌入式Linux系统中,串口被看成终端设备,终端设备(tty)的驱动程序分为3部分: tty_core tty_disicipline tty_driver ...