×
单片机 > 单片机程序设计 > 详情

基于设备树的TQ2440触摸屏驱动移植

发布时间:2020-08-31 发布时间:
|

平台

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


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多