fsl-imx25-tcq.c (15430B)
1// SPDX-License-Identifier: GPL-2.0 2// 3// Copyright (C) 2014-2015 Pengutronix, Markus Pargmann <mpa@pengutronix.de> 4// Based on driver from 2011: 5// Juergen Beisert, Pengutronix <kernel@pengutronix.de> 6// 7// This is the driver for the imx25 TCQ (Touchscreen Conversion Queue) 8// connected to the imx25 ADC. 9 10#include <linux/clk.h> 11#include <linux/device.h> 12#include <linux/input.h> 13#include <linux/interrupt.h> 14#include <linux/mfd/imx25-tsadc.h> 15#include <linux/module.h> 16#include <linux/of.h> 17#include <linux/platform_device.h> 18#include <linux/regmap.h> 19 20static const char mx25_tcq_name[] = "mx25-tcq"; 21 22enum mx25_tcq_mode { 23 MX25_TS_4WIRE, 24}; 25 26struct mx25_tcq_priv { 27 struct regmap *regs; 28 struct regmap *core_regs; 29 struct input_dev *idev; 30 enum mx25_tcq_mode mode; 31 unsigned int pen_threshold; 32 unsigned int sample_count; 33 unsigned int expected_samples; 34 unsigned int pen_debounce; 35 unsigned int settling_time; 36 struct clk *clk; 37 int irq; 38 struct device *dev; 39}; 40 41static struct regmap_config mx25_tcq_regconfig = { 42 .fast_io = true, 43 .max_register = 0x5c, 44 .reg_bits = 32, 45 .val_bits = 32, 46 .reg_stride = 4, 47}; 48 49static const struct of_device_id mx25_tcq_ids[] = { 50 { .compatible = "fsl,imx25-tcq", }, 51 { /* Sentinel */ } 52}; 53MODULE_DEVICE_TABLE(of, mx25_tcq_ids); 54 55#define TSC_4WIRE_PRE_INDEX 0 56#define TSC_4WIRE_X_INDEX 1 57#define TSC_4WIRE_Y_INDEX 2 58#define TSC_4WIRE_POST_INDEX 3 59#define TSC_4WIRE_LEAVE 4 60 61#define MX25_TSC_DEF_THRESHOLD 80 62#define TSC_MAX_SAMPLES 16 63 64#define MX25_TSC_REPEAT_WAIT 14 65 66enum mx25_adc_configurations { 67 MX25_CFG_PRECHARGE = 0, 68 MX25_CFG_TOUCH_DETECT, 69 MX25_CFG_X_MEASUREMENT, 70 MX25_CFG_Y_MEASUREMENT, 71}; 72 73#define MX25_PRECHARGE_VALUE (\ 74 MX25_ADCQ_CFG_YPLL_OFF | \ 75 MX25_ADCQ_CFG_XNUR_OFF | \ 76 MX25_ADCQ_CFG_XPUL_HIGH | \ 77 MX25_ADCQ_CFG_REFP_INT | \ 78 MX25_ADCQ_CFG_IN_XP | \ 79 MX25_ADCQ_CFG_REFN_NGND2 | \ 80 MX25_ADCQ_CFG_IGS) 81 82#define MX25_TOUCH_DETECT_VALUE (\ 83 MX25_ADCQ_CFG_YNLR | \ 84 MX25_ADCQ_CFG_YPLL_OFF | \ 85 MX25_ADCQ_CFG_XNUR_OFF | \ 86 MX25_ADCQ_CFG_XPUL_OFF | \ 87 MX25_ADCQ_CFG_REFP_INT | \ 88 MX25_ADCQ_CFG_IN_XP | \ 89 MX25_ADCQ_CFG_REFN_NGND2 | \ 90 MX25_ADCQ_CFG_PENIACK) 91 92static void imx25_setup_queue_cfgs(struct mx25_tcq_priv *priv, 93 unsigned int settling_cnt) 94{ 95 u32 precharge_cfg = 96 MX25_PRECHARGE_VALUE | 97 MX25_ADCQ_CFG_SETTLING_TIME(settling_cnt); 98 u32 touch_detect_cfg = 99 MX25_TOUCH_DETECT_VALUE | 100 MX25_ADCQ_CFG_NOS(1) | 101 MX25_ADCQ_CFG_SETTLING_TIME(settling_cnt); 102 103 regmap_write(priv->core_regs, MX25_TSC_TICR, precharge_cfg); 104 105 /* PRECHARGE */ 106 regmap_write(priv->regs, MX25_ADCQ_CFG(MX25_CFG_PRECHARGE), 107 precharge_cfg); 108 109 /* TOUCH_DETECT */ 110 regmap_write(priv->regs, MX25_ADCQ_CFG(MX25_CFG_TOUCH_DETECT), 111 touch_detect_cfg); 112 113 /* X Measurement */ 114 regmap_write(priv->regs, MX25_ADCQ_CFG(MX25_CFG_X_MEASUREMENT), 115 MX25_ADCQ_CFG_YPLL_OFF | 116 MX25_ADCQ_CFG_XNUR_LOW | 117 MX25_ADCQ_CFG_XPUL_HIGH | 118 MX25_ADCQ_CFG_REFP_XP | 119 MX25_ADCQ_CFG_IN_YP | 120 MX25_ADCQ_CFG_REFN_XN | 121 MX25_ADCQ_CFG_NOS(priv->sample_count) | 122 MX25_ADCQ_CFG_SETTLING_TIME(settling_cnt)); 123 124 /* Y Measurement */ 125 regmap_write(priv->regs, MX25_ADCQ_CFG(MX25_CFG_Y_MEASUREMENT), 126 MX25_ADCQ_CFG_YNLR | 127 MX25_ADCQ_CFG_YPLL_HIGH | 128 MX25_ADCQ_CFG_XNUR_OFF | 129 MX25_ADCQ_CFG_XPUL_OFF | 130 MX25_ADCQ_CFG_REFP_YP | 131 MX25_ADCQ_CFG_IN_XP | 132 MX25_ADCQ_CFG_REFN_YN | 133 MX25_ADCQ_CFG_NOS(priv->sample_count) | 134 MX25_ADCQ_CFG_SETTLING_TIME(settling_cnt)); 135 136 /* Enable the touch detection right now */ 137 regmap_write(priv->core_regs, MX25_TSC_TICR, touch_detect_cfg | 138 MX25_ADCQ_CFG_IGS); 139} 140 141static int imx25_setup_queue_4wire(struct mx25_tcq_priv *priv, 142 unsigned settling_cnt, int *items) 143{ 144 imx25_setup_queue_cfgs(priv, settling_cnt); 145 146 /* Setup the conversion queue */ 147 regmap_write(priv->regs, MX25_ADCQ_ITEM_7_0, 148 MX25_ADCQ_ITEM(0, MX25_CFG_PRECHARGE) | 149 MX25_ADCQ_ITEM(1, MX25_CFG_TOUCH_DETECT) | 150 MX25_ADCQ_ITEM(2, MX25_CFG_X_MEASUREMENT) | 151 MX25_ADCQ_ITEM(3, MX25_CFG_Y_MEASUREMENT) | 152 MX25_ADCQ_ITEM(4, MX25_CFG_PRECHARGE) | 153 MX25_ADCQ_ITEM(5, MX25_CFG_TOUCH_DETECT)); 154 155 /* 156 * We measure X/Y with 'sample_count' number of samples and execute a 157 * touch detection twice, with 1 sample each 158 */ 159 priv->expected_samples = priv->sample_count * 2 + 2; 160 *items = 6; 161 162 return 0; 163} 164 165static void mx25_tcq_disable_touch_irq(struct mx25_tcq_priv *priv) 166{ 167 regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_PDMSK, 168 MX25_ADCQ_CR_PDMSK); 169} 170 171static void mx25_tcq_enable_touch_irq(struct mx25_tcq_priv *priv) 172{ 173 regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_PDMSK, 0); 174} 175 176static void mx25_tcq_disable_fifo_irq(struct mx25_tcq_priv *priv) 177{ 178 regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_FDRY_IRQ, 179 MX25_ADCQ_MR_FDRY_IRQ); 180} 181 182static void mx25_tcq_enable_fifo_irq(struct mx25_tcq_priv *priv) 183{ 184 regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_FDRY_IRQ, 0); 185} 186 187static void mx25_tcq_force_queue_start(struct mx25_tcq_priv *priv) 188{ 189 regmap_update_bits(priv->regs, MX25_ADCQ_CR, 190 MX25_ADCQ_CR_FQS, 191 MX25_ADCQ_CR_FQS); 192} 193 194static void mx25_tcq_force_queue_stop(struct mx25_tcq_priv *priv) 195{ 196 regmap_update_bits(priv->regs, MX25_ADCQ_CR, 197 MX25_ADCQ_CR_FQS, 0); 198} 199 200static void mx25_tcq_fifo_reset(struct mx25_tcq_priv *priv) 201{ 202 u32 tcqcr; 203 204 regmap_read(priv->regs, MX25_ADCQ_CR, &tcqcr); 205 regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FRST, 206 MX25_ADCQ_CR_FRST); 207 regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FRST, 0); 208 regmap_write(priv->regs, MX25_ADCQ_CR, tcqcr); 209} 210 211static void mx25_tcq_re_enable_touch_detection(struct mx25_tcq_priv *priv) 212{ 213 /* stop the queue from looping */ 214 mx25_tcq_force_queue_stop(priv); 215 216 /* for a clean touch detection, preload the X plane */ 217 regmap_write(priv->core_regs, MX25_TSC_TICR, MX25_PRECHARGE_VALUE); 218 219 /* waste some time now to pre-load the X plate to high voltage */ 220 mx25_tcq_fifo_reset(priv); 221 222 /* re-enable the detection right now */ 223 regmap_write(priv->core_regs, MX25_TSC_TICR, 224 MX25_TOUCH_DETECT_VALUE | MX25_ADCQ_CFG_IGS); 225 226 regmap_update_bits(priv->regs, MX25_ADCQ_SR, MX25_ADCQ_SR_PD, 227 MX25_ADCQ_SR_PD); 228 229 /* enable the pen down event to be a source for the interrupt */ 230 regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_PD_IRQ, 0); 231 232 /* lets fire the next IRQ if someone touches the touchscreen */ 233 mx25_tcq_enable_touch_irq(priv); 234} 235 236static void mx25_tcq_create_event_for_4wire(struct mx25_tcq_priv *priv, 237 u32 *sample_buf, 238 unsigned int samples) 239{ 240 unsigned int x_pos = 0; 241 unsigned int y_pos = 0; 242 unsigned int touch_pre = 0; 243 unsigned int touch_post = 0; 244 unsigned int i; 245 246 for (i = 0; i < samples; i++) { 247 unsigned int index = MX25_ADCQ_FIFO_ID(sample_buf[i]); 248 unsigned int val = MX25_ADCQ_FIFO_DATA(sample_buf[i]); 249 250 switch (index) { 251 case 1: 252 touch_pre = val; 253 break; 254 case 2: 255 x_pos = val; 256 break; 257 case 3: 258 y_pos = val; 259 break; 260 case 5: 261 touch_post = val; 262 break; 263 default: 264 dev_dbg(priv->dev, "Dropped samples because of invalid index %d\n", 265 index); 266 return; 267 } 268 } 269 270 if (samples != 0) { 271 /* 272 * only if both touch measures are below a threshold, 273 * the position is valid 274 */ 275 if (touch_pre < priv->pen_threshold && 276 touch_post < priv->pen_threshold) { 277 /* valid samples, generate a report */ 278 x_pos /= priv->sample_count; 279 y_pos /= priv->sample_count; 280 input_report_abs(priv->idev, ABS_X, x_pos); 281 input_report_abs(priv->idev, ABS_Y, y_pos); 282 input_report_key(priv->idev, BTN_TOUCH, 1); 283 input_sync(priv->idev); 284 285 /* get next sample */ 286 mx25_tcq_enable_fifo_irq(priv); 287 } else if (touch_pre >= priv->pen_threshold && 288 touch_post >= priv->pen_threshold) { 289 /* 290 * if both samples are invalid, 291 * generate a release report 292 */ 293 input_report_key(priv->idev, BTN_TOUCH, 0); 294 input_sync(priv->idev); 295 mx25_tcq_re_enable_touch_detection(priv); 296 } else { 297 /* 298 * if only one of both touch measurements are 299 * below the threshold, still some bouncing 300 * happens. Take additional samples in this 301 * case to be sure 302 */ 303 mx25_tcq_enable_fifo_irq(priv); 304 } 305 } 306} 307 308static irqreturn_t mx25_tcq_irq_thread(int irq, void *dev_id) 309{ 310 struct mx25_tcq_priv *priv = dev_id; 311 u32 sample_buf[TSC_MAX_SAMPLES]; 312 unsigned int samples; 313 u32 stats; 314 unsigned int i; 315 316 /* 317 * Check how many samples are available. We always have to read exactly 318 * sample_count samples from the fifo, or a multiple of sample_count. 319 * Otherwise we mixup samples into different touch events. 320 */ 321 regmap_read(priv->regs, MX25_ADCQ_SR, &stats); 322 samples = MX25_ADCQ_SR_FDN(stats); 323 samples -= samples % priv->sample_count; 324 325 if (!samples) 326 return IRQ_HANDLED; 327 328 for (i = 0; i != samples; ++i) 329 regmap_read(priv->regs, MX25_ADCQ_FIFO, &sample_buf[i]); 330 331 mx25_tcq_create_event_for_4wire(priv, sample_buf, samples); 332 333 return IRQ_HANDLED; 334} 335 336static irqreturn_t mx25_tcq_irq(int irq, void *dev_id) 337{ 338 struct mx25_tcq_priv *priv = dev_id; 339 u32 stat; 340 int ret = IRQ_HANDLED; 341 342 regmap_read(priv->regs, MX25_ADCQ_SR, &stat); 343 344 if (stat & (MX25_ADCQ_SR_FRR | MX25_ADCQ_SR_FUR | MX25_ADCQ_SR_FOR)) 345 mx25_tcq_re_enable_touch_detection(priv); 346 347 if (stat & MX25_ADCQ_SR_PD) { 348 mx25_tcq_disable_touch_irq(priv); 349 mx25_tcq_force_queue_start(priv); 350 mx25_tcq_enable_fifo_irq(priv); 351 } 352 353 if (stat & MX25_ADCQ_SR_FDRY) { 354 mx25_tcq_disable_fifo_irq(priv); 355 ret = IRQ_WAKE_THREAD; 356 } 357 358 regmap_update_bits(priv->regs, MX25_ADCQ_SR, MX25_ADCQ_SR_FRR | 359 MX25_ADCQ_SR_FUR | MX25_ADCQ_SR_FOR | 360 MX25_ADCQ_SR_PD, 361 MX25_ADCQ_SR_FRR | MX25_ADCQ_SR_FUR | 362 MX25_ADCQ_SR_FOR | MX25_ADCQ_SR_PD); 363 364 return ret; 365} 366 367/* configure the state machine for a 4-wire touchscreen */ 368static int mx25_tcq_init(struct mx25_tcq_priv *priv) 369{ 370 u32 tgcr; 371 unsigned int ipg_div; 372 unsigned int adc_period; 373 unsigned int debounce_cnt; 374 unsigned int settling_cnt; 375 int itemct; 376 int error; 377 378 regmap_read(priv->core_regs, MX25_TSC_TGCR, &tgcr); 379 ipg_div = max_t(unsigned int, 4, MX25_TGCR_GET_ADCCLK(tgcr)); 380 adc_period = USEC_PER_SEC * ipg_div * 2 + 2; 381 adc_period /= clk_get_rate(priv->clk) / 1000 + 1; 382 debounce_cnt = DIV_ROUND_UP(priv->pen_debounce, adc_period * 8) - 1; 383 settling_cnt = DIV_ROUND_UP(priv->settling_time, adc_period * 8) - 1; 384 385 /* Reset */ 386 regmap_write(priv->regs, MX25_ADCQ_CR, 387 MX25_ADCQ_CR_QRST | MX25_ADCQ_CR_FRST); 388 regmap_update_bits(priv->regs, MX25_ADCQ_CR, 389 MX25_ADCQ_CR_QRST | MX25_ADCQ_CR_FRST, 0); 390 391 /* up to 128 * 8 ADC clocks are possible */ 392 if (debounce_cnt > 127) 393 debounce_cnt = 127; 394 395 /* up to 255 * 8 ADC clocks are possible */ 396 if (settling_cnt > 255) 397 settling_cnt = 255; 398 399 error = imx25_setup_queue_4wire(priv, settling_cnt, &itemct); 400 if (error) 401 return error; 402 403 regmap_update_bits(priv->regs, MX25_ADCQ_CR, 404 MX25_ADCQ_CR_LITEMID_MASK | MX25_ADCQ_CR_WMRK_MASK, 405 MX25_ADCQ_CR_LITEMID(itemct - 1) | 406 MX25_ADCQ_CR_WMRK(priv->expected_samples - 1)); 407 408 /* setup debounce count */ 409 regmap_update_bits(priv->core_regs, MX25_TSC_TGCR, 410 MX25_TGCR_PDBTIME_MASK, 411 MX25_TGCR_PDBTIME(debounce_cnt)); 412 413 /* enable debounce */ 414 regmap_update_bits(priv->core_regs, MX25_TSC_TGCR, MX25_TGCR_PDBEN, 415 MX25_TGCR_PDBEN); 416 regmap_update_bits(priv->core_regs, MX25_TSC_TGCR, MX25_TGCR_PDEN, 417 MX25_TGCR_PDEN); 418 419 /* enable the engine on demand */ 420 regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_QSM_MASK, 421 MX25_ADCQ_CR_QSM_FQS); 422 423 /* Enable repeat and repeat wait */ 424 regmap_update_bits(priv->regs, MX25_ADCQ_CR, 425 MX25_ADCQ_CR_RPT | MX25_ADCQ_CR_RWAIT_MASK, 426 MX25_ADCQ_CR_RPT | 427 MX25_ADCQ_CR_RWAIT(MX25_TSC_REPEAT_WAIT)); 428 429 return 0; 430} 431 432static int mx25_tcq_parse_dt(struct platform_device *pdev, 433 struct mx25_tcq_priv *priv) 434{ 435 struct device_node *np = pdev->dev.of_node; 436 u32 wires; 437 int error; 438 439 /* Setup defaults */ 440 priv->pen_threshold = 500; 441 priv->sample_count = 3; 442 priv->pen_debounce = 1000000; 443 priv->settling_time = 250000; 444 445 error = of_property_read_u32(np, "fsl,wires", &wires); 446 if (error) { 447 dev_err(&pdev->dev, "Failed to find fsl,wires properties\n"); 448 return error; 449 } 450 451 if (wires == 4) { 452 priv->mode = MX25_TS_4WIRE; 453 } else { 454 dev_err(&pdev->dev, "%u-wire mode not supported\n", wires); 455 return -EINVAL; 456 } 457 458 /* These are optional, we don't care about the return values */ 459 of_property_read_u32(np, "fsl,pen-threshold", &priv->pen_threshold); 460 of_property_read_u32(np, "fsl,settling-time-ns", &priv->settling_time); 461 of_property_read_u32(np, "fsl,pen-debounce-ns", &priv->pen_debounce); 462 463 return 0; 464} 465 466static int mx25_tcq_open(struct input_dev *idev) 467{ 468 struct device *dev = &idev->dev; 469 struct mx25_tcq_priv *priv = dev_get_drvdata(dev); 470 int error; 471 472 error = clk_prepare_enable(priv->clk); 473 if (error) { 474 dev_err(dev, "Failed to enable ipg clock\n"); 475 return error; 476 } 477 478 error = mx25_tcq_init(priv); 479 if (error) { 480 dev_err(dev, "Failed to init tcq\n"); 481 clk_disable_unprepare(priv->clk); 482 return error; 483 } 484 485 mx25_tcq_re_enable_touch_detection(priv); 486 487 return 0; 488} 489 490static void mx25_tcq_close(struct input_dev *idev) 491{ 492 struct mx25_tcq_priv *priv = input_get_drvdata(idev); 493 494 mx25_tcq_force_queue_stop(priv); 495 mx25_tcq_disable_touch_irq(priv); 496 mx25_tcq_disable_fifo_irq(priv); 497 clk_disable_unprepare(priv->clk); 498} 499 500static int mx25_tcq_probe(struct platform_device *pdev) 501{ 502 struct device *dev = &pdev->dev; 503 struct input_dev *idev; 504 struct mx25_tcq_priv *priv; 505 struct mx25_tsadc *tsadc = dev_get_drvdata(dev->parent); 506 void __iomem *mem; 507 int error; 508 509 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 510 if (!priv) 511 return -ENOMEM; 512 priv->dev = dev; 513 514 mem = devm_platform_ioremap_resource(pdev, 0); 515 if (IS_ERR(mem)) 516 return PTR_ERR(mem); 517 518 error = mx25_tcq_parse_dt(pdev, priv); 519 if (error) 520 return error; 521 522 priv->regs = devm_regmap_init_mmio(dev, mem, &mx25_tcq_regconfig); 523 if (IS_ERR(priv->regs)) { 524 dev_err(dev, "Failed to initialize regmap\n"); 525 return PTR_ERR(priv->regs); 526 } 527 528 priv->irq = platform_get_irq(pdev, 0); 529 if (priv->irq <= 0) 530 return priv->irq; 531 532 idev = devm_input_allocate_device(dev); 533 if (!idev) { 534 dev_err(dev, "Failed to allocate input device\n"); 535 return -ENOMEM; 536 } 537 538 idev->name = mx25_tcq_name; 539 input_set_capability(idev, EV_KEY, BTN_TOUCH); 540 input_set_abs_params(idev, ABS_X, 0, 0xfff, 0, 0); 541 input_set_abs_params(idev, ABS_Y, 0, 0xfff, 0, 0); 542 543 idev->id.bustype = BUS_HOST; 544 idev->open = mx25_tcq_open; 545 idev->close = mx25_tcq_close; 546 547 priv->idev = idev; 548 input_set_drvdata(idev, priv); 549 550 priv->core_regs = tsadc->regs; 551 if (!priv->core_regs) 552 return -EINVAL; 553 554 priv->clk = tsadc->clk; 555 if (!priv->clk) 556 return -EINVAL; 557 558 platform_set_drvdata(pdev, priv); 559 560 error = devm_request_threaded_irq(dev, priv->irq, mx25_tcq_irq, 561 mx25_tcq_irq_thread, 0, pdev->name, 562 priv); 563 if (error) { 564 dev_err(dev, "Failed requesting IRQ\n"); 565 return error; 566 } 567 568 error = input_register_device(idev); 569 if (error) { 570 dev_err(dev, "Failed to register input device\n"); 571 return error; 572 } 573 574 return 0; 575} 576 577static struct platform_driver mx25_tcq_driver = { 578 .driver = { 579 .name = "mx25-tcq", 580 .of_match_table = mx25_tcq_ids, 581 }, 582 .probe = mx25_tcq_probe, 583}; 584module_platform_driver(mx25_tcq_driver); 585 586MODULE_DESCRIPTION("TS input driver for Freescale mx25"); 587MODULE_AUTHOR("Markus Pargmann <mpa@pengutronix.de>"); 588MODULE_LICENSE("GPL v2");