blob: 9cd794461af74b175bb906f5728e49d1e24a6b34 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * ASR built-in touchscreen driver
4 *
5 * Copyright (C) 2023 ASR
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#include <linux/timer.h>
17
18/*
19 * Touchscreen controller register offsets
20 */
21#define ASR_TSCR 0x0
22#define ASR_TSSR 0x4
23#define ASR_XYDR(x) (0x8 + (x) * 0x4)
24
25#define ASR_TSSR_DOWN 0
26#define ASR_TSSR_UP 1
27
28#define ASR_TSC_MIN_XY_VAL 0
29#define ASR_TSC_MAX_XY_VAL 4095
30#define ASR_TSC_DOT_CNT_MAX 8
31
32#define MOD_NAME "ts-asr"
33
34#define tsc_readl(dev, reg) \
35 __raw_readl((dev)->tsc_base + (reg))
36#define tsc_writel(dev, reg, val) \
37 __raw_writel((val), (dev)->tsc_base + (reg))
38
39struct asr_tp_info {
40 int x;
41 int y;
42 int last_x;
43 int last_y;
44};
45
46struct asr_tsc {
47 struct timer_list move_timer;
48 struct input_dev *dev;
49 void __iomem *tsc_base;
50 int rdy_irq;
51 int up_irq;
52 int down_irq;
53 struct clk *clk;
54 struct asr_tp_info tp;
55 int dummpy_points;
56};
57
58#define ASR_TSC_MOVE_TIMEOUT 10 /* ms */
59#define ASR_TSC_DUMMY_POINTS 10
60#define ASR_TSC_TP_MARGIN 10
61
62enum {
63 TSC_MODE_IDLE = 0,
64 TSC_MODE_WAIT_PRESSDOWN,
65 TSC_MODE_WAIT_RISEUP,
66 TSC_MODE_WAIT_AUTOMEASURE,
67};
68static void asr_ts_set_mode(struct asr_tsc *tsc, int mode);
69
70static void asr_ts_movement_detect(struct timer_list *t)
71{
72 struct asr_tsc *tsc = from_timer(tsc, t, move_timer);
73 u32 val;
74 val = tsc_readl(tsc, ASR_TSSR);
75 if (val & ASR_TSSR_UP) {
76 asr_ts_set_mode(tsc, TSC_MODE_WAIT_PRESSDOWN);
77 return;
78 }
79
80 asr_ts_set_mode(tsc, TSC_MODE_WAIT_AUTOMEASURE);
81}
82
83static void asr_ts_adc_init(void)
84{
85 void __iomem* apb_spare;
86 u32 val;
87
88 apb_spare = ioremap(0xD4090000, SZ_4K);
89 if (!apb_spare) {
90 pr_err("%s: error to ioremap apb_spare base\n", __func__);
91 return;
92 }
93
94 val = readl(apb_spare + 0x12c);
95 val |= (1 << 8) | (1 << 20) | (1 << 22) | (0x4 << 24);
96 writel(val, apb_spare + 0x12c);
97 iounmap(apb_spare);
98}
99
100static void asr_ts_set_mode(struct asr_tsc *tsc, int mode)
101{
102 u32 val;
103 val = tsc_readl(tsc, ASR_TSCR);
104 val &= ~(0x3 << 1);
105 switch (mode) {
106 case TSC_MODE_WAIT_PRESSDOWN:
107 val &= ~((1 << 8) | (1 << 7));
108 val |= (1 << 6) | (1 << 9);
109 break;
110 case TSC_MODE_WAIT_RISEUP:
111 val &= ~((1 << 8) | (1 << 6));
112 val |= (1 << 7) | (1 << 9);
113 break;
114 case TSC_MODE_WAIT_AUTOMEASURE:
115 val &= ~((1 << 6) | (1 << 7) | (1 << 9));
116 val |= (1 << 8);
117 break;
118 }
119 val |= (mode << 1);
120 tsc_writel(tsc, ASR_TSCR, val);
121}
122
123static void asr_ts_measure(struct asr_tsc *tsc)
124{
125 int i;
126 u32 val, meas_x, meas_y, sum_x = 0, sum_y = 0;
127 u16 min_x, max_x, min_y, max_y;
128 u16 x[ASR_TSC_DOT_CNT_MAX] = {0};
129 u16 y[ASR_TSC_DOT_CNT_MAX] = {0};
130 struct asr_tp_info *tp = (struct asr_tp_info *)&tsc->tp;
131
132 for (i = 0; i < ASR_TSC_DOT_CNT_MAX; i++) {
133 val = tsc_readl(tsc, ASR_XYDR(i));
134 x[i] = val & 0xffff;
135 sum_x += x[i];
136 if (i == 0 ) {
137 min_x = x[0];
138 max_x = x[0];
139 }
140 if (min_x > x[i])
141 min_x = x[i];
142 if (max_x < x[i])
143 max_x = x[i];
144
145 y[i] = (val >> 16) & 0xffff;
146 sum_y += y[i];
147
148 if (i == 0 ) {
149 min_y = y[0];
150 max_y = y[0];
151 }
152 if (min_y > y[i])
153 min_y = y[i];
154 if(max_y < y[i])
155 max_y = y[i];
156 pr_debug(" %s: [%d] (%d, %d)\n", __func__, i, x[i], y[i]);
157 }
158
159 meas_x = (sum_x - max_x - min_x) / (ASR_TSC_DOT_CNT_MAX - 2);
160 meas_y = (sum_y - max_y - min_y) / (ASR_TSC_DOT_CNT_MAX - 2);
161
162 pr_debug("meas_x: %d, meas_y: %d\n", meas_x, meas_y);
163 tp->x = meas_x;
164 tp->y = meas_y;
165}
166
167static irqreturn_t asr_ts_down_isr(int irq, void *dev_id)
168{
169 u32 val;
170 struct asr_tsc *tsc = (struct asr_tsc *)dev_id;
171 val = tsc_readl(tsc, ASR_TSSR);
172
173 if (val & (1 << 6)) {
174 val |= (1 << 6);
175 tsc_writel(tsc, ASR_TSSR, val);
176 if (val & ASR_TSSR_UP) {
177 asr_ts_set_mode(tsc, TSC_MODE_WAIT_PRESSDOWN);
178 return IRQ_HANDLED;
179 }
180
181 tsc->dummpy_points = 1;
182 asr_ts_set_mode(tsc, TSC_MODE_WAIT_AUTOMEASURE);
183 pr_debug("%s: got down irq.\n", __func__);
184 } else {
185 pr_warn("%s: mismatch irq?\n", __func__);
186 }
187 return IRQ_HANDLED;
188}
189
190static irqreturn_t asr_ts_rdy_isr(int irq, void *dev_id)
191{
192 u32 val;
193 int x, y;
194 struct asr_tsc *tsc = (struct asr_tsc *)dev_id;
195 struct input_dev *input = tsc->dev;
196
197 val = tsc_readl(tsc, ASR_TSSR);
198 if (val & (1 << 8)) {
199 val |= (1 << 8);
200 tsc_writel(tsc, ASR_TSSR, val);
201#if 0
202 if (val & ASR_TSSR_UP) {
203 asr_ts_set_mode(tsc, TSC_MODE_WAIT_PRESSDOWN);
204 return IRQ_HANDLED;
205 }
206#endif
207 asr_ts_measure(tsc);
208 if (tsc->dummpy_points) {
209 tsc->dummpy_points++;
210 if (tsc->dummpy_points > ASR_TSC_DUMMY_POINTS) {
211 tsc->dummpy_points = 0;
212 x = tsc->tp.last_x = tsc->tp.x;
213 y = tsc->tp.last_y = tsc->tp.y;
214 } else
215 goto skip;
216 } else {
217 if (abs(tsc->tp.x - tsc->tp.last_x) < ASR_TSC_TP_MARGIN &&
218 abs(tsc->tp.y - tsc->tp.last_y) < ASR_TSC_TP_MARGIN)
219 goto skip;
220 }
221
222 x = tsc->tp.last_x = tsc->tp.x;
223 y = tsc->tp.last_y = tsc->tp.y;
224
225 input_report_abs(input, ABS_X, x);
226 input_report_abs(input, ABS_Y, y);
227 input_report_key(input, BTN_TOUCH, 1);
228 input_sync(input);
229skip:
230 asr_ts_set_mode(tsc, TSC_MODE_WAIT_RISEUP);
231 mod_timer(&tsc->move_timer, jiffies + msecs_to_jiffies(ASR_TSC_MOVE_TIMEOUT));
232 pr_debug("%s: got rdy irq. 0x%x, (%d, %d)\n", __func__, val, tsc->tp.x, tsc->tp.y);
233 } else {
234 pr_warn("%s: mismatch irq?\n", __func__);
235 }
236 return IRQ_HANDLED;
237}
238
239static irqreturn_t asr_ts_up_isr(int irq, void *dev_id)
240{
241 u32 val;
242 struct asr_tsc *tsc = (struct asr_tsc *)dev_id;
243 struct input_dev *input = tsc->dev;
244
245 val = tsc_readl(tsc, ASR_TSSR);
246 if (val & (1 << 7)) {
247 val |= (1 << 7);
248 tsc_writel(tsc, ASR_TSSR, val);
249 if ((val & 1) == ASR_TSSR_DOWN)
250 return IRQ_HANDLED;
251
252 pr_debug("%s: got up irq. (%d, %d)\n", __func__, tsc->tp.x, tsc->tp.y);
253 input_report_key(input, BTN_TOUCH, 0);
254 input_sync(input);
255 asr_ts_set_mode(tsc, TSC_MODE_WAIT_PRESSDOWN);
256 } else {
257 pr_warn("%s: mismatch irq?\n", __func__);
258 }
259 return IRQ_HANDLED;
260}
261
262static void asr_stop_tsc(struct asr_tsc *tsc)
263{
264 tsc_writel(tsc, ASR_TSCR, 0);
265 clk_disable_unprepare(tsc->clk);
266}
267
268static int asr_setup_tsc(struct asr_tsc *tsc)
269{
270 u32 tmp;
271 int err;
272 asr_ts_adc_init();
273
274 err = clk_prepare_enable(tsc->clk);
275 if (err)
276 return err;
277
278 tmp = tsc_readl(tsc, ASR_TSCR);
279 tmp |= (1 << 0); /* enabled tsc */
280 tmp |= 0x7 << 16; /* YD ADC channel slection */
281 tmp |= 0x6 << 11; /* XL ADC channel slection */
282 tmp |= (1 << 8); /* INT_RDY_EN */
283 tmp |= (0x20 << 24);
284 tmp |= (0 << 21); /* XL_PU_RES_SEL */
285 tmp |= ((ASR_TSC_DOT_CNT_MAX - 1) << 3); /* DOT_CNT */
286 tsc_writel(tsc, ASR_TSCR, tmp);
287 asr_ts_set_mode(tsc, TSC_MODE_WAIT_PRESSDOWN);
288 return 0;
289}
290
291static int asr_ts_open(struct input_dev *dev)
292{
293 struct asr_tsc *tsc = input_get_drvdata(dev);
294 return asr_setup_tsc(tsc);
295}
296
297static void asr_ts_close(struct input_dev *dev)
298{
299 struct asr_tsc *tsc = input_get_drvdata(dev);
300 asr_stop_tsc(tsc);
301}
302
303static int asr_ts_probe(struct platform_device *pdev)
304{
305 struct asr_tsc *tsc;
306 struct input_dev *input;
307 struct resource *res;
308 resource_size_t size;
309 int irq0, irq1, irq2;
310 int error;
311
312 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
313 if (!res) {
314 dev_err(&pdev->dev, "Can't get memory resource\n");
315 return -ENOENT;
316 }
317
318 irq0 = platform_get_irq(pdev, 0);
319 irq1 = platform_get_irq(pdev, 1);
320 irq2 = platform_get_irq(pdev, 2);
321 if (irq0 < 0 || irq1 < 0 || irq2 < 0) {
322 dev_err(&pdev->dev, "err irq:%d, %d, %d\n", irq0, irq1, irq2);
323 return -ENOENT;
324 }
325
326 tsc = kzalloc(sizeof(*tsc), GFP_KERNEL);
327 input = input_allocate_device();
328 if (!tsc || !input) {
329 dev_err(&pdev->dev, "failed allocating memory\n");
330 error = -ENOMEM;
331 goto err_free_mem;
332 }
333
334 tsc->dev = input;
335 tsc->down_irq = irq0;
336 tsc->rdy_irq = irq1;
337 tsc->up_irq = irq2;
338
339 size = resource_size(res);
340
341 if (!request_mem_region(res->start, size, pdev->name)) {
342 dev_err(&pdev->dev, "TSC registers are not free\n");
343 error = -EBUSY;
344 goto err_free_mem;
345 }
346
347 tsc->tsc_base = ioremap(res->start, size);
348 if (!tsc->tsc_base) {
349 dev_err(&pdev->dev, "Can't map memory\n");
350 error = -ENOMEM;
351 goto err_release_mem;
352 }
353
354 tsc->clk = clk_get(&pdev->dev, NULL);
355 if (IS_ERR(tsc->clk)) {
356 dev_err(&pdev->dev, "failed getting clock\n");
357 error = PTR_ERR(tsc->clk);
358 goto err_unmap;
359 }
360
361 input->name = MOD_NAME;
362 input->phys = "asr/input0";
363 input->id.bustype = BUS_HOST;
364 input->id.vendor = 0x0001;
365 input->id.product = 0x0002;
366 input->id.version = 0x0100;
367 input->dev.parent = &pdev->dev;
368 input->open = asr_ts_open;
369 input->close = asr_ts_close;
370
371 __set_bit(EV_ABS, input->evbit);
372 __set_bit(ABS_X, input->absbit);
373 __set_bit(ABS_Y, input->absbit);
374 __set_bit(EV_SYN, input->evbit);
375 __set_bit(EV_KEY, input->evbit);
376 __set_bit(BTN_TOUCH, input->keybit);
377
378 input_set_abs_params(input, ABS_X, ASR_TSC_MIN_XY_VAL,
379 ASR_TSC_MAX_XY_VAL, 0, 0);
380 input_set_abs_params(input, ABS_Y, ASR_TSC_MIN_XY_VAL,
381 ASR_TSC_MAX_XY_VAL, 0, 0);
382
383 input_set_drvdata(input, tsc);
384
385 error = request_irq(tsc->down_irq, asr_ts_down_isr,
386 IRQF_SHARED, pdev->name, tsc);
387 if (error) {
388 dev_err(&pdev->dev, "failed requesting down irq\n");
389 goto err_put_clock;
390 }
391
392 error = request_irq(tsc->rdy_irq, asr_ts_rdy_isr,
393 IRQF_SHARED, pdev->name, tsc);
394 if (error) {
395 dev_err(&pdev->dev, "failed requesting rdy irq\n");
396 goto err_free_irq0;
397 }
398
399 error = request_irq(tsc->up_irq, asr_ts_up_isr,
400 IRQF_SHARED, pdev->name, tsc);
401 if (error) {
402 dev_err(&pdev->dev, "failed requesting up irq\n");
403 goto err_free_irq1;
404 }
405
406 error = input_register_device(input);
407 if (error) {
408 dev_err(&pdev->dev, "failed registering input device\n");
409 goto err_free_irq2;
410 }
411
412 platform_set_drvdata(pdev, tsc);
413 device_init_wakeup(&pdev->dev, 1);
414 timer_setup(&tsc->move_timer, asr_ts_movement_detect, 0);
415 dev_info(&pdev->dev, "bringup ok.\n");
416 return 0;
417
418err_free_irq2:
419 free_irq(tsc->up_irq, tsc);
420err_free_irq1:
421 free_irq(tsc->rdy_irq, tsc);
422err_free_irq0:
423 free_irq(tsc->down_irq, tsc);
424err_put_clock:
425 clk_put(tsc->clk);
426err_unmap:
427 iounmap(tsc->tsc_base);
428err_release_mem:
429 release_mem_region(res->start, size);
430err_free_mem:
431 input_free_device(input);
432 kfree(tsc);
433
434 return error;
435}
436
437static int asr_ts_remove(struct platform_device *pdev)
438{
439 struct asr_tsc *tsc = platform_get_drvdata(pdev);
440 struct resource *res;
441
442 free_irq(tsc->down_irq, tsc);
443 free_irq(tsc->rdy_irq, tsc);
444 free_irq(tsc->up_irq, tsc);
445
446 input_unregister_device(tsc->dev);
447
448 clk_put(tsc->clk);
449
450 iounmap(tsc->tsc_base);
451 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
452 release_mem_region(res->start, resource_size(res));
453
454 kfree(tsc);
455
456 return 0;
457}
458
459#ifdef CONFIG_PM
460static int asr_ts_suspend(struct device *dev)
461{
462 struct asr_tsc *tsc = dev_get_drvdata(dev);
463 struct input_dev *input = tsc->dev;
464
465 /*
466 * Suspend and resume can be called when the device hasn't been
467 * enabled. If there are no users that have the device open, then
468 * avoid calling the TSC stop and start functions as the TSC
469 * isn't yet clocked.
470 */
471 mutex_lock(&input->mutex);
472
473 if (input->users) {
474 if (device_may_wakeup(dev)) {
475 enable_irq_wake(tsc->down_irq);
476 enable_irq_wake(tsc->rdy_irq);
477 enable_irq_wake(tsc->up_irq);
478 } else
479 asr_stop_tsc(tsc);
480 }
481
482 mutex_unlock(&input->mutex);
483
484 return 0;
485}
486
487static int asr_ts_resume(struct device *dev)
488{
489 struct asr_tsc *tsc = dev_get_drvdata(dev);
490 struct input_dev *input = tsc->dev;
491
492 mutex_lock(&input->mutex);
493
494 if (input->users) {
495 if (device_may_wakeup(dev)) {
496 disable_irq_wake(tsc->down_irq);
497 disable_irq_wake(tsc->rdy_irq);
498 disable_irq_wake(tsc->up_irq);
499 } else
500 asr_setup_tsc(tsc);
501 }
502
503 mutex_unlock(&input->mutex);
504
505 return 0;
506}
507
508static const struct dev_pm_ops asr_ts_pm_ops = {
509 .suspend = asr_ts_suspend,
510 .resume = asr_ts_resume,
511};
512#define ASR_TS_PM_OPS (&asr_ts_pm_ops)
513#else
514#define ASR_TS_PM_OPS NULL
515#endif
516
517#ifdef CONFIG_OF
518static const struct of_device_id asr_tsc_of_match[] = {
519 { .compatible = "asr,tsc", },
520 { },
521};
522MODULE_DEVICE_TABLE(of, asr_tsc_of_match);
523#endif
524
525static struct platform_driver asr_ts_driver = {
526 .probe = asr_ts_probe,
527 .remove = asr_ts_remove,
528 .driver = {
529 .name = MOD_NAME,
530 .pm = ASR_TS_PM_OPS,
531 .of_match_table = of_match_ptr(asr_tsc_of_match),
532 },
533};
534module_platform_driver(asr_ts_driver);
535
536MODULE_AUTHOR("Mark Zhang <markzhang@asrmicro.com>");
537MODULE_DESCRIPTION("ASR TSC Driver");
538MODULE_LICENSE("GPL");
539MODULE_ALIAS("platform:asr_ts");
540