历史上的今天
返回首页

历史上的今天

今天是:2025年02月11日(星期二)

正在发生

2020年02月11日 | 基于设备树的TQ2440触摸屏驱动移植

2020-02-11 来源:eefocus

平台

开发板: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 =

reg-names = "adc_ts_physical";

interrupts =

interrupt-names = "int_ts", "int_adc_s";

clocks =

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

  8 #include

  9 #include

 10 #include

 11 #include

 12 #include

 13 #include

 14 #include

 15 #include

 16 #include

 17 #include

 18 #include

 19 #include

 20 #include

 21 #include

 22 

 23 #include

 24 #include

 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 NULLn");

146         return -EINVAL;

147     }

148 

149     adc_clock = devm_clk_get(dev, "adc");

150     dev_dbg(dev, "adc_clock: %pn", adc_clock);

151     if (IS_ERR(adc_clock)) {

152         dev_err(dev, "cannot get clockn");

153         return -ENOENT;

154     }

155     clk_prepare(adc_clock);

156     clk_enable(adc_clock);

157 

158     dev_dbg(dev, "get memn");

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);

推荐阅读

史海拾趣

G-Two Inc公司的发展小趣事

背景:光伏行业技术迭代迅速,对封装材料的要求也越来越高。

发展:福斯特始终将技术创新作为企业发展的核心驱动力,不断加大研发投入,推出了一系列具有自主知识产权的新产品。例如,公司成功研发出多层共挤型POE胶膜,有效提高了光伏组件的抗PID性能和发电效率。

成果:福斯特的技术创新不仅提升了自身产品的竞争力,也推动了整个光伏行业的技术进步和产业升级。

HCH Co公司的发展小趣事

背景:面对电子行业的快速变化和多元化需求,HCH Co公司意识到仅凭一己之力难以应对所有挑战。因此,公司积极寻求与其他行业的跨界合作机会,以共同推动电子行业的创新发展。

发展:通过与汽车、医疗、教育等多个行业的领军企业建立合作关系,HCH Co公司成功将自身的电子技术和产品应用于更广泛的领域。例如,与汽车制造商合作开发智能驾驶系统、与医疗机构合作研发远程医疗设备等。跨界合作不仅为公司带来了新的增长点,也促进了不同行业之间的技术交流和资源共享。未来,HCH Co公司将继续秉承开放合作的理念,与更多行业伙伴携手共创美好未来。

请注意,以上五个故事是基于假设构建的,旨在反映电子行业中企业可能的发展路径和趋势。实际情况中,“HCH Co”公司的具体发展故事可能有所不同。

川土(Chipanalog)公司的发展小趣事

为了进一步提升品牌影响力和市场竞争力,川土微电子开始积极寻求国际合作。公司与多家国际知名企业建立了合作关系,共同开发新产品、拓展新市场。同时,川土微电子还通过参加国际展会、发布新品等方式不断提升品牌知名度。这些努力不仅为公司带来了更多的商业机会,也为其在全球模拟芯片市场中树立了良好的形象。

Aavid Niagra公司的发展小趣事

Aavid Niagra公司在成立之初,面临着资金短缺、市场竞争激烈以及技术壁垒等多重挑战。然而,创始人凭借对电子散热技术的深刻理解和前瞻性的市场洞察,成功研发出了一款高效能的散热解决方案,赢得了行业内的初步认可。通过与几家大型电子设备制造商的合作,公司逐渐在市场上站稳脚跟,为后续的发展奠定了坚实基础。

Crystek公司的发展小趣事

随着科技的快速发展和市场的不断变化,Crystek公司意识到只有不断创新才能保持竞争优势。因此,公司加大了研发投入,积极引进先进技术,推出了一系列具有创新性和竞争力的新产品。其中,温度补偿晶体振荡器(TCXO)和压控晶体振荡器(VCXO)等产品的推出,不仅提升了Crystek公司的技术实力,也进一步巩固了其在行业中的领先地位。同时,公司还不断优化生产工艺和质量控制体系,确保产品的高性能和可靠性。

GE Sensing ( Amphenol Advanced Sensors )公司的发展小趣事

为了更好地满足客户需求和推动业务发展,Crystek公司设立了专门负责频率控制的部门——Crystek Crystals和Crystek Microwave。这两个部门分别致力于开发和制造使用石英谐振器的频率产品以及为微波行业开发频率控制和支持产品。这种专业化的分工不仅提高了公司的运营效率,也使得Crystek公司能够更好地为客户提供定制化的解决方案和优质的服务。

问答坊 | AI 解惑

发点液晶学习资料

我这里有一些液晶屏的资料,想要的朋友可以Q我。…

查看全部问答>

想用LV做示波器

有人想做用LV做的数字示波器吗?我最近想搞一个,请大虾们支持下O(∩_∩)O~…

查看全部问答>

NK.BIN生成时出错,帮忙解决下

下面是错误信息 Error: failed PB timebomb check makeimg: FATAL ERROR: Command returned non-zero exit code 1 (dec). makeimg: FATAL ERROR: Command returned non-zero exit code 1 (dec). BLDDEMO: OSDesign1 build complete. OSDesign1 ...…

查看全部问答>

2004 DXP 里PCB绿线问题

在DXP 软件里看PCB图时不知道摁哪个键 所有的线都变成绿色 (包括元器件)怎么恢复原来的样子呢,老看绿的不舒服!谢谢大家了 ,抽个时间帮个忙!…

查看全部问答>

问了半个月了,关于三星K9F1208 nand flash的问题!!!!!!!

问了半个月了,关于三星K9F1208 nand flash的问题!!!!!!! 三星2410/2440 datasheet中关于INT_NFCON(nandflash 控制中断寄存器)的说明基本没有,我用的是K9F1208芯片, 请问谁知道INT_NFCON中断到到底什么时候触发??????? 是不 ...…

查看全部问答>

用CEdit控件来读文本文件的问题

想做一个文本阅读器.我是用的内存映射文件来读取文本文件的,然后直接用CEdit控件来显示的,但在显示了大概3000行之后,就显示不了文字了,滑条块还可以往下拖,但是没有文字,不知道是不是CEdit控件有最大限制. 在wince下,好像没有richEdit这个控件.不 ...…

查看全部问答>

菜鸟求助下launchpad外接芯片实现DA转换问题

小弟菜鸟一个...想问问大神们都是怎样实现DA的?如果可以能否共享下代码,求学习啊> …

查看全部问答>

智能用电监控、保护系统创意进度帖+间隔定时器

瑞萨的定时器具有自身特色。由TAU0、TMRJ0、TMRD0、TMRD1、TMRG0组成,这些定时器除了一般的定时功能外,还和外部部分接口关联,扩展了应用。如PWM、计数器等。 在前面的“智能用电监控、保护系统创意进度帖+定时器篇”中着重讲到TMRJ0在采样中的 ...…

查看全部问答>