1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * LPC32xx built-in touchscreen driver |
4 | * |
5 | * Copyright (C) 2010 NXP Semiconductors |
6 | */ |
7 | |
8 | #include <linux/platform_device.h> |
9 | #include <linux/input.h> |
10 | #include <linux/interrupt.h> |
11 | #include <linux/module.h> |
12 | #include <linux/clk.h> |
13 | #include <linux/io.h> |
14 | #include <linux/slab.h> |
15 | #include <linux/of.h> |
16 | |
17 | /* |
18 | * Touchscreen controller register offsets |
19 | */ |
20 | #define LPC32XX_TSC_STAT 0x00 |
21 | #define LPC32XX_TSC_SEL 0x04 |
22 | #define LPC32XX_TSC_CON 0x08 |
23 | #define LPC32XX_TSC_FIFO 0x0C |
24 | #define LPC32XX_TSC_DTR 0x10 |
25 | #define LPC32XX_TSC_RTR 0x14 |
26 | #define LPC32XX_TSC_UTR 0x18 |
27 | #define LPC32XX_TSC_TTR 0x1C |
28 | #define LPC32XX_TSC_DXP 0x20 |
29 | #define LPC32XX_TSC_MIN_X 0x24 |
30 | #define LPC32XX_TSC_MAX_X 0x28 |
31 | #define LPC32XX_TSC_MIN_Y 0x2C |
32 | #define LPC32XX_TSC_MAX_Y 0x30 |
33 | #define LPC32XX_TSC_AUX_UTR 0x34 |
34 | #define LPC32XX_TSC_AUX_MIN 0x38 |
35 | #define LPC32XX_TSC_AUX_MAX 0x3C |
36 | |
37 | #define LPC32XX_TSC_STAT_FIFO_OVRRN BIT(8) |
38 | #define LPC32XX_TSC_STAT_FIFO_EMPTY BIT(7) |
39 | |
40 | #define LPC32XX_TSC_SEL_DEFVAL 0x0284 |
41 | |
42 | #define LPC32XX_TSC_ADCCON_IRQ_TO_FIFO_4 (0x1 << 11) |
43 | #define LPC32XX_TSC_ADCCON_X_SAMPLE_SIZE(s) ((10 - (s)) << 7) |
44 | #define LPC32XX_TSC_ADCCON_Y_SAMPLE_SIZE(s) ((10 - (s)) << 4) |
45 | #define LPC32XX_TSC_ADCCON_POWER_UP BIT(2) |
46 | #define LPC32XX_TSC_ADCCON_AUTO_EN BIT(0) |
47 | |
48 | #define LPC32XX_TSC_FIFO_TS_P_LEVEL BIT(31) |
49 | #define LPC32XX_TSC_FIFO_NORMALIZE_X_VAL(x) (((x) & 0x03FF0000) >> 16) |
50 | #define LPC32XX_TSC_FIFO_NORMALIZE_Y_VAL(y) ((y) & 0x000003FF) |
51 | |
52 | #define LPC32XX_TSC_ADCDAT_VALUE_MASK 0x000003FF |
53 | |
54 | #define LPC32XX_TSC_MIN_XY_VAL 0x0 |
55 | #define LPC32XX_TSC_MAX_XY_VAL 0x3FF |
56 | |
57 | #define MOD_NAME "ts-lpc32xx" |
58 | |
59 | #define tsc_readl(dev, reg) \ |
60 | __raw_readl((dev)->tsc_base + (reg)) |
61 | #define tsc_writel(dev, reg, val) \ |
62 | __raw_writel((val), (dev)->tsc_base + (reg)) |
63 | |
64 | struct lpc32xx_tsc { |
65 | struct input_dev *dev; |
66 | void __iomem *tsc_base; |
67 | int irq; |
68 | struct clk *clk; |
69 | }; |
70 | |
71 | static void lpc32xx_fifo_clear(struct lpc32xx_tsc *tsc) |
72 | { |
73 | while (!(tsc_readl(tsc, LPC32XX_TSC_STAT) & |
74 | LPC32XX_TSC_STAT_FIFO_EMPTY)) |
75 | tsc_readl(tsc, LPC32XX_TSC_FIFO); |
76 | } |
77 | |
78 | static irqreturn_t lpc32xx_ts_interrupt(int irq, void *dev_id) |
79 | { |
80 | u32 tmp, rv[4], xs[4], ys[4]; |
81 | int idx; |
82 | struct lpc32xx_tsc *tsc = dev_id; |
83 | struct input_dev *input = tsc->dev; |
84 | |
85 | tmp = tsc_readl(tsc, LPC32XX_TSC_STAT); |
86 | |
87 | if (tmp & LPC32XX_TSC_STAT_FIFO_OVRRN) { |
88 | /* FIFO overflow - throw away samples */ |
89 | lpc32xx_fifo_clear(tsc); |
90 | return IRQ_HANDLED; |
91 | } |
92 | |
93 | /* |
94 | * Gather and normalize 4 samples. Pen-up events may have less |
95 | * than 4 samples, but its ok to pop 4 and let the last sample |
96 | * pen status check drop the samples. |
97 | */ |
98 | idx = 0; |
99 | while (idx < 4 && |
100 | !(tsc_readl(tsc, LPC32XX_TSC_STAT) & |
101 | LPC32XX_TSC_STAT_FIFO_EMPTY)) { |
102 | tmp = tsc_readl(tsc, LPC32XX_TSC_FIFO); |
103 | xs[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK - |
104 | LPC32XX_TSC_FIFO_NORMALIZE_X_VAL(tmp); |
105 | ys[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK - |
106 | LPC32XX_TSC_FIFO_NORMALIZE_Y_VAL(tmp); |
107 | rv[idx] = tmp; |
108 | idx++; |
109 | } |
110 | |
111 | /* Data is only valid if pen is still down in last sample */ |
112 | if (!(rv[3] & LPC32XX_TSC_FIFO_TS_P_LEVEL) && idx == 4) { |
113 | /* Use average of 2nd and 3rd sample for position */ |
114 | input_report_abs(dev: input, ABS_X, value: (xs[1] + xs[2]) / 2); |
115 | input_report_abs(dev: input, ABS_Y, value: (ys[1] + ys[2]) / 2); |
116 | input_report_key(dev: input, BTN_TOUCH, value: 1); |
117 | } else { |
118 | input_report_key(dev: input, BTN_TOUCH, value: 0); |
119 | } |
120 | |
121 | input_sync(dev: input); |
122 | |
123 | return IRQ_HANDLED; |
124 | } |
125 | |
126 | static void lpc32xx_stop_tsc(struct lpc32xx_tsc *tsc) |
127 | { |
128 | /* Disable auto mode */ |
129 | tsc_writel(tsc, LPC32XX_TSC_CON, |
130 | tsc_readl(tsc, LPC32XX_TSC_CON) & |
131 | ~LPC32XX_TSC_ADCCON_AUTO_EN); |
132 | |
133 | clk_disable_unprepare(clk: tsc->clk); |
134 | } |
135 | |
136 | static int lpc32xx_setup_tsc(struct lpc32xx_tsc *tsc) |
137 | { |
138 | u32 tmp; |
139 | int err; |
140 | |
141 | err = clk_prepare_enable(clk: tsc->clk); |
142 | if (err) |
143 | return err; |
144 | |
145 | tmp = tsc_readl(tsc, LPC32XX_TSC_CON) & ~LPC32XX_TSC_ADCCON_POWER_UP; |
146 | |
147 | /* Set the TSC FIFO depth to 4 samples @ 10-bits per sample (max) */ |
148 | tmp = LPC32XX_TSC_ADCCON_IRQ_TO_FIFO_4 | |
149 | LPC32XX_TSC_ADCCON_X_SAMPLE_SIZE(10) | |
150 | LPC32XX_TSC_ADCCON_Y_SAMPLE_SIZE(10); |
151 | tsc_writel(tsc, LPC32XX_TSC_CON, tmp); |
152 | |
153 | /* These values are all preset */ |
154 | tsc_writel(tsc, LPC32XX_TSC_SEL, LPC32XX_TSC_SEL_DEFVAL); |
155 | tsc_writel(tsc, LPC32XX_TSC_MIN_X, LPC32XX_TSC_MIN_XY_VAL); |
156 | tsc_writel(tsc, LPC32XX_TSC_MAX_X, LPC32XX_TSC_MAX_XY_VAL); |
157 | tsc_writel(tsc, LPC32XX_TSC_MIN_Y, LPC32XX_TSC_MIN_XY_VAL); |
158 | tsc_writel(tsc, LPC32XX_TSC_MAX_Y, LPC32XX_TSC_MAX_XY_VAL); |
159 | |
160 | /* Aux support is not used */ |
161 | tsc_writel(tsc, LPC32XX_TSC_AUX_UTR, 0); |
162 | tsc_writel(tsc, LPC32XX_TSC_AUX_MIN, 0); |
163 | tsc_writel(tsc, LPC32XX_TSC_AUX_MAX, 0); |
164 | |
165 | /* |
166 | * Set sample rate to about 240Hz per X/Y pair. A single measurement |
167 | * consists of 4 pairs which gives about a 60Hz sample rate based on |
168 | * a stable 32768Hz clock source. Values are in clocks. |
169 | * Rate is (32768 / (RTR + XCONV + RTR + YCONV + DXP + TTR + UTR) / 4 |
170 | */ |
171 | tsc_writel(tsc, LPC32XX_TSC_RTR, 0x2); |
172 | tsc_writel(tsc, LPC32XX_TSC_DTR, 0x2); |
173 | tsc_writel(tsc, LPC32XX_TSC_TTR, 0x10); |
174 | tsc_writel(tsc, LPC32XX_TSC_DXP, 0x4); |
175 | tsc_writel(tsc, LPC32XX_TSC_UTR, 88); |
176 | |
177 | lpc32xx_fifo_clear(tsc); |
178 | |
179 | /* Enable automatic ts event capture */ |
180 | tsc_writel(tsc, LPC32XX_TSC_CON, tmp | LPC32XX_TSC_ADCCON_AUTO_EN); |
181 | |
182 | return 0; |
183 | } |
184 | |
185 | static int lpc32xx_ts_open(struct input_dev *dev) |
186 | { |
187 | struct lpc32xx_tsc *tsc = input_get_drvdata(dev); |
188 | |
189 | return lpc32xx_setup_tsc(tsc); |
190 | } |
191 | |
192 | static void lpc32xx_ts_close(struct input_dev *dev) |
193 | { |
194 | struct lpc32xx_tsc *tsc = input_get_drvdata(dev); |
195 | |
196 | lpc32xx_stop_tsc(tsc); |
197 | } |
198 | |
199 | static int lpc32xx_ts_probe(struct platform_device *pdev) |
200 | { |
201 | struct device *dev = &pdev->dev; |
202 | struct lpc32xx_tsc *tsc; |
203 | struct input_dev *input; |
204 | int irq; |
205 | int error; |
206 | |
207 | irq = platform_get_irq(pdev, 0); |
208 | if (irq < 0) |
209 | return irq; |
210 | |
211 | tsc = devm_kzalloc(dev, size: sizeof(*tsc), GFP_KERNEL); |
212 | if (!tsc) |
213 | return -ENOMEM; |
214 | |
215 | tsc->irq = irq; |
216 | |
217 | tsc->tsc_base = devm_platform_ioremap_resource(pdev, index: 0); |
218 | if (IS_ERR(ptr: tsc->tsc_base)) |
219 | return PTR_ERR(ptr: tsc->tsc_base); |
220 | |
221 | tsc->clk = devm_clk_get(dev, NULL); |
222 | if (IS_ERR(ptr: tsc->clk)) { |
223 | dev_err(&pdev->dev, "failed getting clock\n" ); |
224 | return PTR_ERR(ptr: tsc->clk); |
225 | } |
226 | |
227 | input = devm_input_allocate_device(dev); |
228 | if (!input) { |
229 | dev_err(&pdev->dev, "failed allocating input device\n" ); |
230 | return -ENOMEM; |
231 | } |
232 | |
233 | input->name = MOD_NAME; |
234 | input->phys = "lpc32xx/input0" ; |
235 | input->id.bustype = BUS_HOST; |
236 | input->id.vendor = 0x0001; |
237 | input->id.product = 0x0002; |
238 | input->id.version = 0x0100; |
239 | input->open = lpc32xx_ts_open; |
240 | input->close = lpc32xx_ts_close; |
241 | |
242 | input_set_capability(dev: input, EV_KEY, BTN_TOUCH); |
243 | input_set_abs_params(dev: input, ABS_X, LPC32XX_TSC_MIN_XY_VAL, |
244 | LPC32XX_TSC_MAX_XY_VAL, fuzz: 0, flat: 0); |
245 | input_set_abs_params(dev: input, ABS_Y, LPC32XX_TSC_MIN_XY_VAL, |
246 | LPC32XX_TSC_MAX_XY_VAL, fuzz: 0, flat: 0); |
247 | |
248 | input_set_drvdata(dev: input, data: tsc); |
249 | tsc->dev = input; |
250 | |
251 | error = devm_request_irq(dev, irq: tsc->irq, handler: lpc32xx_ts_interrupt, |
252 | irqflags: 0, devname: pdev->name, dev_id: tsc); |
253 | if (error) { |
254 | dev_err(&pdev->dev, "failed requesting interrupt\n" ); |
255 | return error; |
256 | } |
257 | |
258 | error = input_register_device(input); |
259 | if (error) { |
260 | dev_err(&pdev->dev, "failed registering input device\n" ); |
261 | return error; |
262 | } |
263 | |
264 | platform_set_drvdata(pdev, data: tsc); |
265 | device_init_wakeup(dev: &pdev->dev, enable: true); |
266 | |
267 | return 0; |
268 | } |
269 | |
270 | #ifdef CONFIG_PM |
271 | static int lpc32xx_ts_suspend(struct device *dev) |
272 | { |
273 | struct lpc32xx_tsc *tsc = dev_get_drvdata(dev); |
274 | struct input_dev *input = tsc->dev; |
275 | |
276 | /* |
277 | * Suspend and resume can be called when the device hasn't been |
278 | * enabled. If there are no users that have the device open, then |
279 | * avoid calling the TSC stop and start functions as the TSC |
280 | * isn't yet clocked. |
281 | */ |
282 | mutex_lock(&input->mutex); |
283 | |
284 | if (input_device_enabled(dev: input)) { |
285 | if (device_may_wakeup(dev)) |
286 | enable_irq_wake(irq: tsc->irq); |
287 | else |
288 | lpc32xx_stop_tsc(tsc); |
289 | } |
290 | |
291 | mutex_unlock(lock: &input->mutex); |
292 | |
293 | return 0; |
294 | } |
295 | |
296 | static int lpc32xx_ts_resume(struct device *dev) |
297 | { |
298 | struct lpc32xx_tsc *tsc = dev_get_drvdata(dev); |
299 | struct input_dev *input = tsc->dev; |
300 | |
301 | mutex_lock(&input->mutex); |
302 | |
303 | if (input_device_enabled(dev: input)) { |
304 | if (device_may_wakeup(dev)) |
305 | disable_irq_wake(irq: tsc->irq); |
306 | else |
307 | lpc32xx_setup_tsc(tsc); |
308 | } |
309 | |
310 | mutex_unlock(lock: &input->mutex); |
311 | |
312 | return 0; |
313 | } |
314 | |
315 | static const struct dev_pm_ops lpc32xx_ts_pm_ops = { |
316 | .suspend = lpc32xx_ts_suspend, |
317 | .resume = lpc32xx_ts_resume, |
318 | }; |
319 | #define LPC32XX_TS_PM_OPS (&lpc32xx_ts_pm_ops) |
320 | #else |
321 | #define LPC32XX_TS_PM_OPS NULL |
322 | #endif |
323 | |
324 | #ifdef CONFIG_OF |
325 | static const struct of_device_id lpc32xx_tsc_of_match[] = { |
326 | { .compatible = "nxp,lpc3220-tsc" , }, |
327 | { }, |
328 | }; |
329 | MODULE_DEVICE_TABLE(of, lpc32xx_tsc_of_match); |
330 | #endif |
331 | |
332 | static struct platform_driver lpc32xx_ts_driver = { |
333 | .probe = lpc32xx_ts_probe, |
334 | .driver = { |
335 | .name = MOD_NAME, |
336 | .pm = LPC32XX_TS_PM_OPS, |
337 | .of_match_table = of_match_ptr(lpc32xx_tsc_of_match), |
338 | }, |
339 | }; |
340 | module_platform_driver(lpc32xx_ts_driver); |
341 | |
342 | MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com" ); |
343 | MODULE_DESCRIPTION("LPC32XX TSC Driver" ); |
344 | MODULE_LICENSE("GPL" ); |
345 | MODULE_ALIAS("platform:lpc32xx_ts" ); |
346 | |