Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: add Broadcom iProc touchscreen driver

Add initial version of the Broadcom touchscreen driver.

Reviewed-by: Ray Jui <rjui@broadcom.com>
Reviewed-by: Scott Branden <sbranden@broadcom.com>
Tested-by: Scott Branden <sbranden@broadcom.com>
Signed-off-by: Jonathan Richardson <jonathar@broadcom.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Jonathan Richardson and committed by
Dmitry Torokhov
d5ae685f 188933ac

+611
+76
Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt
··· 1 + * Broadcom's IPROC Touchscreen Controller 2 + 3 + Required properties: 4 + - compatible: must be "brcm,iproc-touchscreen" 5 + - reg: physical base address of the controller and length of memory mapped 6 + region. 7 + - clocks: The clock provided by the SOC to driver the tsc 8 + - clock-name: name for the clock 9 + - interrupts: The touchscreen controller's interrupt 10 + 11 + Optional properties: 12 + - scanning_period: Time between scans. Each step is 1024 us. Valid 1-256. 13 + - debounce_timeout: Each step is 512 us. Valid 0-255 14 + - settling_timeout: The settling duration (in ms) is the amount of time 15 + the tsc waits to allow the voltage to settle after 16 + turning on the drivers in detection mode. 17 + Valid values: 0-11 18 + 0 = 0.008 ms 19 + 1 = 0.01 ms 20 + 2 = 0.02 ms 21 + 3 = 0.04 ms 22 + 4 = 0.08 ms 23 + 5 = 0.16 ms 24 + 6 = 0.32 ms 25 + 7 = 0.64 ms 26 + 8 = 1.28 ms 27 + 9 = 2.56 ms 28 + 10 = 5.12 ms 29 + 11 = 10.24 ms 30 + - touch_timeout: The continuous number of scan periods in which touch is 31 + not detected before the controller returns to idle state. 32 + Valid values 0-255. 33 + - average_data: Number of data samples which are averaged before a final 34 + data point is placed into the FIFO 35 + Valid values 0-7 36 + 0 = 1 sample 37 + 1 = 2 samples 38 + 2 = 4 samples 39 + 3 = 8 samples 40 + 4 = 16 samples 41 + 5 = 32 samples 42 + 6 = 64 samples 43 + 7 = 128 samples 44 + - fifo_threshold: Interrupt is generated whenever the number of fifo 45 + entries exceeds this value 46 + Valid values 0-31 47 + - touchscreen-size-x: horizontal resolution of touchscreen (in pixels) 48 + - touchscreen-size-y: vertical resolution of touchscreen (in pixels) 49 + - touchscreen-fuzz-x: horizontal noise value of the absolute input 50 + device (in pixels) 51 + - touchscreen-fuzz-y: vertical noise value of the absolute input 52 + device (in pixels) 53 + - touchscreen-inverted-x: X axis is inverted (boolean) 54 + - touchscreen-inverted-y: Y axis is inverted (boolean) 55 + 56 + Example: 57 + 58 + touchscreen: tsc@0x180A6000 { 59 + compatible = "brcm,iproc-touchscreen"; 60 + #address-cells = <1>; 61 + #size-cells = <1>; 62 + reg = <0x180A6000 0x40>; 63 + clocks = <&adc_clk>; 64 + clock-names = "tsc_clk"; 65 + interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>; 66 + 67 + scanning_period = <5>; 68 + debounce_timeout = <40>; 69 + settling_timeout = <7>; 70 + touch_timeout = <10>; 71 + average_data = <5>; 72 + fifo_threshold = <1>; 73 + /* Touchscreen is rotated 180 degrees. */ 74 + touchscreen-inverted-x; 75 + touchscreen-inverted-y; 76 + };
+12
drivers/input/touchscreen/Kconfig
··· 324 324 To compile this driver as a module, choose M here: the 325 325 module will be called ili210x. 326 326 327 + config TOUCHSCREEN_IPROC 328 + tristate "IPROC touch panel driver support" 329 + depends on ARCH_BCM_IPROC || COMPILE_TEST 330 + help 331 + Say Y here if you want to add support for the IPROC touch 332 + controller to your system. 333 + 334 + If unsure, say N. 335 + 336 + To compile this driver as a module, choose M here: the 337 + module will be called bcm_iproc_tsc. 338 + 327 339 config TOUCHSCREEN_S3C2410 328 340 tristate "Samsung S3C2410/generic touchscreen input driver" 329 341 depends on ARCH_S3C24XX || SAMSUNG_DEV_TS
+1
drivers/input/touchscreen/Makefile
··· 39 39 obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o 40 40 obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o 41 41 obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o 42 + obj-$(CONFIG_TOUCHSCREEN_IPROC) += bcm_iproc_tsc.o 42 43 obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o 43 44 obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o 44 45 obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
+522
drivers/input/touchscreen/bcm_iproc_tsc.c
··· 1 + /* 2 + * Copyright (C) 2015 Broadcom Corporation 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License as 6 + * published by the Free Software Foundation version 2. 7 + * 8 + * This program is distributed "as is" WITHOUT ANY WARRANTY of any 9 + * kind, whether express or implied; without even the implied warranty 10 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + */ 13 + #include <linux/module.h> 14 + #include <linux/init.h> 15 + #include <linux/input.h> 16 + #include <linux/delay.h> 17 + #include <linux/interrupt.h> 18 + #include <linux/keyboard.h> 19 + #include <linux/platform_device.h> 20 + #include <linux/slab.h> 21 + #include <linux/of.h> 22 + #include <asm/irq.h> 23 + #include <linux/io.h> 24 + #include <linux/clk.h> 25 + #include <linux/serio.h> 26 + 27 + #define IPROC_TS_NAME "iproc-ts" 28 + 29 + #define PEN_DOWN_STATUS 1 30 + #define PEN_UP_STATUS 0 31 + 32 + #define X_MIN 0 33 + #define Y_MIN 0 34 + #define X_MAX 0xFFF 35 + #define Y_MAX 0xFFF 36 + 37 + /* Value given by controller for invalid coordinate. */ 38 + #define INVALID_COORD 0xFFFFFFFF 39 + 40 + /* Register offsets */ 41 + #define REGCTL1 0x00 42 + #define REGCTL2 0x04 43 + #define INTERRUPT_THRES 0x08 44 + #define INTERRUPT_MASK 0x0c 45 + 46 + #define INTERRUPT_STATUS 0x10 47 + #define CONTROLLER_STATUS 0x14 48 + #define FIFO_DATA 0x18 49 + #define FIFO_DATA_X_Y_MASK 0xFFFF 50 + #define ANALOG_CONTROL 0x1c 51 + 52 + #define AUX_DATA 0x20 53 + #define DEBOUNCE_CNTR_STAT 0x24 54 + #define SCAN_CNTR_STAT 0x28 55 + #define REM_CNTR_STAT 0x2c 56 + 57 + #define SETTLING_TIMER_STAT 0x30 58 + #define SPARE_REG 0x34 59 + #define SOFT_BYPASS_CONTROL 0x38 60 + #define SOFT_BYPASS_DATA 0x3c 61 + 62 + 63 + /* Bit values for INTERRUPT_MASK and INTERRUPT_STATUS regs */ 64 + #define TS_PEN_INTR_MASK BIT(0) 65 + #define TS_FIFO_INTR_MASK BIT(2) 66 + 67 + /* Bit values for CONTROLLER_STATUS reg1 */ 68 + #define TS_PEN_DOWN BIT(0) 69 + 70 + /* Shift values for control reg1 */ 71 + #define SCANNING_PERIOD_SHIFT 24 72 + #define DEBOUNCE_TIMEOUT_SHIFT 16 73 + #define SETTLING_TIMEOUT_SHIFT 8 74 + #define TOUCH_TIMEOUT_SHIFT 0 75 + 76 + /* Shift values for coordinates from fifo */ 77 + #define X_COORD_SHIFT 0 78 + #define Y_COORD_SHIFT 16 79 + 80 + /* Bit values for REGCTL2 */ 81 + #define TS_CONTROLLER_EN_BIT BIT(16) 82 + #define TS_CONTROLLER_AVGDATA_SHIFT 8 83 + #define TS_CONTROLLER_AVGDATA_MASK (0x7 << TS_CONTROLLER_AVGDATA_SHIFT) 84 + #define TS_CONTROLLER_PWR_LDO BIT(5) 85 + #define TS_CONTROLLER_PWR_ADC BIT(4) 86 + #define TS_CONTROLLER_PWR_BGP BIT(3) 87 + #define TS_CONTROLLER_PWR_TS BIT(2) 88 + #define TS_WIRE_MODE_BIT BIT(1) 89 + 90 + #define dbg_reg(dev, priv, reg) \ 91 + dev_dbg(dev, "%20s= 0x%08x\n", #reg, readl((priv)->regs + reg)) 92 + 93 + struct tsc_param { 94 + /* Each step is 1024 us. Valid 1-256 */ 95 + u32 scanning_period; 96 + 97 + /* Each step is 512 us. Valid 0-255 */ 98 + u32 debounce_timeout; 99 + 100 + /* 101 + * The settling duration (in ms) is the amount of time the tsc 102 + * waits to allow the voltage to settle after turning on the 103 + * drivers in detection mode. Valid values: 0-11 104 + * 0 = 0.008 ms 105 + * 1 = 0.01 ms 106 + * 2 = 0.02 ms 107 + * 3 = 0.04 ms 108 + * 4 = 0.08 ms 109 + * 5 = 0.16 ms 110 + * 6 = 0.32 ms 111 + * 7 = 0.64 ms 112 + * 8 = 1.28 ms 113 + * 9 = 2.56 ms 114 + * 10 = 5.12 ms 115 + * 11 = 10.24 ms 116 + */ 117 + u32 settling_timeout; 118 + 119 + /* touch timeout in sample counts */ 120 + u32 touch_timeout; 121 + 122 + /* 123 + * Number of data samples which are averaged before a final data point 124 + * is placed into the FIFO 125 + */ 126 + u32 average_data; 127 + 128 + /* FIFO threshold */ 129 + u32 fifo_threshold; 130 + 131 + /* Optional standard touchscreen properties. */ 132 + u32 max_x; 133 + u32 max_y; 134 + u32 fuzz_x; 135 + u32 fuzz_y; 136 + bool invert_x; 137 + bool invert_y; 138 + }; 139 + 140 + struct iproc_ts_priv { 141 + struct platform_device *pdev; 142 + struct input_dev *idev; 143 + 144 + void __iomem *regs; 145 + struct clk *tsc_clk; 146 + 147 + int pen_status; 148 + struct tsc_param cfg_params; 149 + }; 150 + 151 + /* 152 + * Set default values the same as hardware reset values 153 + * except for fifo_threshold with is set to 1. 154 + */ 155 + static const struct tsc_param iproc_default_config = { 156 + .scanning_period = 0x5, /* 1 to 256 */ 157 + .debounce_timeout = 0x28, /* 0 to 255 */ 158 + .settling_timeout = 0x7, /* 0 to 11 */ 159 + .touch_timeout = 0xa, /* 0 to 255 */ 160 + .average_data = 5, /* entry 5 = 32 pts */ 161 + .fifo_threshold = 1, /* 0 to 31 */ 162 + .max_x = X_MAX, 163 + .max_y = Y_MAX, 164 + }; 165 + 166 + static void ts_reg_dump(struct iproc_ts_priv *priv) 167 + { 168 + struct device *dev = &priv->pdev->dev; 169 + 170 + dbg_reg(dev, priv, REGCTL1); 171 + dbg_reg(dev, priv, REGCTL2); 172 + dbg_reg(dev, priv, INTERRUPT_THRES); 173 + dbg_reg(dev, priv, INTERRUPT_MASK); 174 + dbg_reg(dev, priv, INTERRUPT_STATUS); 175 + dbg_reg(dev, priv, CONTROLLER_STATUS); 176 + dbg_reg(dev, priv, FIFO_DATA); 177 + dbg_reg(dev, priv, ANALOG_CONTROL); 178 + dbg_reg(dev, priv, AUX_DATA); 179 + dbg_reg(dev, priv, DEBOUNCE_CNTR_STAT); 180 + dbg_reg(dev, priv, SCAN_CNTR_STAT); 181 + dbg_reg(dev, priv, REM_CNTR_STAT); 182 + dbg_reg(dev, priv, SETTLING_TIMER_STAT); 183 + dbg_reg(dev, priv, SPARE_REG); 184 + dbg_reg(dev, priv, SOFT_BYPASS_CONTROL); 185 + dbg_reg(dev, priv, SOFT_BYPASS_DATA); 186 + } 187 + 188 + static irqreturn_t iproc_touchscreen_interrupt(int irq, void *data) 189 + { 190 + struct platform_device *pdev = data; 191 + struct iproc_ts_priv *priv = platform_get_drvdata(pdev); 192 + u32 intr_status; 193 + u32 raw_coordinate; 194 + u16 x; 195 + u16 y; 196 + int i; 197 + bool needs_sync = false; 198 + 199 + intr_status = readl(priv->regs + INTERRUPT_STATUS); 200 + intr_status &= TS_PEN_INTR_MASK | TS_FIFO_INTR_MASK; 201 + if (intr_status == 0) 202 + return IRQ_NONE; 203 + 204 + /* Clear all interrupt status bits, write-1-clear */ 205 + writel(intr_status, priv->regs + INTERRUPT_STATUS); 206 + 207 + /* Pen up/down */ 208 + if (intr_status & TS_PEN_INTR_MASK) { 209 + if (readl(priv->regs + CONTROLLER_STATUS) & TS_PEN_DOWN) 210 + priv->pen_status = PEN_DOWN_STATUS; 211 + else 212 + priv->pen_status = PEN_UP_STATUS; 213 + 214 + input_report_key(priv->idev, BTN_TOUCH, priv->pen_status); 215 + needs_sync = true; 216 + 217 + dev_dbg(&priv->pdev->dev, 218 + "pen up-down (%d)\n", priv->pen_status); 219 + } 220 + 221 + /* coordinates in FIFO exceed the theshold */ 222 + if (intr_status & TS_FIFO_INTR_MASK) { 223 + for (i = 0; i < priv->cfg_params.fifo_threshold; i++) { 224 + raw_coordinate = readl(priv->regs + FIFO_DATA); 225 + if (raw_coordinate == INVALID_COORD) 226 + continue; 227 + 228 + /* 229 + * The x and y coordinate are 16 bits each 230 + * with the x in the lower 16 bits and y in the 231 + * upper 16 bits. 232 + */ 233 + x = (raw_coordinate >> X_COORD_SHIFT) & 234 + FIFO_DATA_X_Y_MASK; 235 + y = (raw_coordinate >> Y_COORD_SHIFT) & 236 + FIFO_DATA_X_Y_MASK; 237 + 238 + /* We only want to retain the 12 msb of the 16 */ 239 + x = (x >> 4) & 0x0FFF; 240 + y = (y >> 4) & 0x0FFF; 241 + 242 + /* adjust x y according to lcd tsc mount angle */ 243 + if (priv->cfg_params.invert_x) 244 + x = priv->cfg_params.max_x - x; 245 + 246 + if (priv->cfg_params.invert_y) 247 + y = priv->cfg_params.max_y - y; 248 + 249 + input_report_abs(priv->idev, ABS_X, x); 250 + input_report_abs(priv->idev, ABS_Y, y); 251 + needs_sync = true; 252 + 253 + dev_dbg(&priv->pdev->dev, "xy (0x%x 0x%x)\n", x, y); 254 + } 255 + } 256 + 257 + if (needs_sync) 258 + input_sync(priv->idev); 259 + 260 + return IRQ_HANDLED; 261 + } 262 + 263 + static int iproc_ts_start(struct input_dev *idev) 264 + { 265 + struct iproc_ts_priv *priv = input_get_drvdata(idev); 266 + u32 val; 267 + int error; 268 + 269 + /* Enable clock */ 270 + error = clk_prepare_enable(priv->tsc_clk); 271 + if (error) { 272 + dev_err(&priv->pdev->dev, "%s clk_prepare_enable failed %d\n", 273 + __func__, error); 274 + return error; 275 + } 276 + 277 + /* 278 + * Interrupt is generated when: 279 + * FIFO reaches the int_th value, and pen event(up/down) 280 + */ 281 + val = TS_PEN_INTR_MASK | TS_FIFO_INTR_MASK; 282 + writel(val, priv->regs + INTERRUPT_MASK); 283 + 284 + writel(priv->cfg_params.fifo_threshold, priv->regs + INTERRUPT_THRES); 285 + 286 + /* Initialize control reg1 */ 287 + val = 0; 288 + val |= priv->cfg_params.scanning_period << SCANNING_PERIOD_SHIFT; 289 + val |= priv->cfg_params.debounce_timeout << DEBOUNCE_TIMEOUT_SHIFT; 290 + val |= priv->cfg_params.settling_timeout << SETTLING_TIMEOUT_SHIFT; 291 + val |= priv->cfg_params.touch_timeout << TOUCH_TIMEOUT_SHIFT; 292 + writel(val, priv->regs + REGCTL1); 293 + 294 + /* Try to clear all interrupt status */ 295 + val = readl(priv->regs + INTERRUPT_STATUS); 296 + val |= TS_FIFO_INTR_MASK | TS_PEN_INTR_MASK; 297 + writel(val, priv->regs + INTERRUPT_STATUS); 298 + 299 + /* Initialize control reg2 */ 300 + val = readl(priv->regs + REGCTL2); 301 + val |= TS_CONTROLLER_EN_BIT | TS_WIRE_MODE_BIT; 302 + 303 + val &= ~TS_CONTROLLER_AVGDATA_MASK; 304 + val |= priv->cfg_params.average_data << TS_CONTROLLER_AVGDATA_SHIFT; 305 + 306 + val &= ~(TS_CONTROLLER_PWR_LDO | /* PWR up LDO */ 307 + TS_CONTROLLER_PWR_ADC | /* PWR up ADC */ 308 + TS_CONTROLLER_PWR_BGP | /* PWR up BGP */ 309 + TS_CONTROLLER_PWR_TS); /* PWR up TS */ 310 + 311 + writel(val, priv->regs + REGCTL2); 312 + 313 + ts_reg_dump(priv); 314 + 315 + return 0; 316 + } 317 + 318 + static void iproc_ts_stop(struct input_dev *dev) 319 + { 320 + u32 val; 321 + struct iproc_ts_priv *priv = input_get_drvdata(dev); 322 + 323 + writel(0, priv->regs + INTERRUPT_MASK); /* Disable all interrupts */ 324 + 325 + /* Only power down touch screen controller */ 326 + val = readl(priv->regs + REGCTL2); 327 + val |= TS_CONTROLLER_PWR_TS; 328 + writel(val, priv->regs + REGCTL2); 329 + 330 + clk_disable(priv->tsc_clk); 331 + } 332 + 333 + static int iproc_get_tsc_config(struct device *dev, struct iproc_ts_priv *priv) 334 + { 335 + struct device_node *np = dev->of_node; 336 + u32 val; 337 + 338 + priv->cfg_params = iproc_default_config; 339 + 340 + if (!np) 341 + return 0; 342 + 343 + if (of_property_read_u32(np, "scanning_period", &val) >= 0) { 344 + if (val < 1 || val > 256) { 345 + dev_err(dev, "scanning_period (%u) must be [1-256]\n", 346 + val); 347 + return -EINVAL; 348 + } 349 + priv->cfg_params.scanning_period = val; 350 + } 351 + 352 + if (of_property_read_u32(np, "debounce_timeout", &val) >= 0) { 353 + if (val > 255) { 354 + dev_err(dev, "debounce_timeout (%u) must be [0-255]\n", 355 + val); 356 + return -EINVAL; 357 + } 358 + priv->cfg_params.debounce_timeout = val; 359 + } 360 + 361 + if (of_property_read_u32(np, "settling_timeout", &val) >= 0) { 362 + if (val > 11) { 363 + dev_err(dev, "settling_timeout (%u) must be [0-11]\n", 364 + val); 365 + return -EINVAL; 366 + } 367 + priv->cfg_params.settling_timeout = val; 368 + } 369 + 370 + if (of_property_read_u32(np, "touch_timeout", &val) >= 0) { 371 + if (val > 255) { 372 + dev_err(dev, "touch_timeout (%u) must be [0-255]\n", 373 + val); 374 + return -EINVAL; 375 + } 376 + priv->cfg_params.touch_timeout = val; 377 + } 378 + 379 + if (of_property_read_u32(np, "average_data", &val) >= 0) { 380 + if (val > 8) { 381 + dev_err(dev, "average_data (%u) must be [0-8]\n", val); 382 + return -EINVAL; 383 + } 384 + priv->cfg_params.average_data = val; 385 + } 386 + 387 + if (of_property_read_u32(np, "fifo_threshold", &val) >= 0) { 388 + if (val > 31) { 389 + dev_err(dev, "fifo_threshold (%u)) must be [0-31]\n", 390 + val); 391 + return -EINVAL; 392 + } 393 + priv->cfg_params.fifo_threshold = val; 394 + } 395 + 396 + /* Parse optional properties. */ 397 + of_property_read_u32(np, "touchscreen-size-x", &priv->cfg_params.max_x); 398 + of_property_read_u32(np, "touchscreen-size-y", &priv->cfg_params.max_y); 399 + 400 + of_property_read_u32(np, "touchscreen-fuzz-x", 401 + &priv->cfg_params.fuzz_x); 402 + of_property_read_u32(np, "touchscreen-fuzz-y", 403 + &priv->cfg_params.fuzz_y); 404 + 405 + priv->cfg_params.invert_x = 406 + of_property_read_bool(np, "touchscreen-inverted-x"); 407 + priv->cfg_params.invert_y = 408 + of_property_read_bool(np, "touchscreen-inverted-y"); 409 + 410 + return 0; 411 + } 412 + 413 + static int iproc_ts_probe(struct platform_device *pdev) 414 + { 415 + struct iproc_ts_priv *priv; 416 + struct input_dev *idev; 417 + struct resource *res; 418 + int irq; 419 + int error; 420 + 421 + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 422 + if (!priv) 423 + return -ENOMEM; 424 + 425 + /* touchscreen controller memory mapped regs */ 426 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 427 + priv->regs = devm_ioremap_resource(&pdev->dev, res); 428 + if (IS_ERR(priv->regs)) { 429 + error = PTR_ERR(priv->regs); 430 + dev_err(&pdev->dev, "unable to map I/O memory: %d\n", error); 431 + return error; 432 + } 433 + 434 + priv->tsc_clk = devm_clk_get(&pdev->dev, "tsc_clk"); 435 + if (IS_ERR(priv->tsc_clk)) { 436 + error = PTR_ERR(priv->tsc_clk); 437 + dev_err(&pdev->dev, 438 + "failed getting clock tsc_clk: %d\n", error); 439 + return error; 440 + } 441 + 442 + priv->pdev = pdev; 443 + error = iproc_get_tsc_config(&pdev->dev, priv); 444 + if (error) { 445 + dev_err(&pdev->dev, "get_tsc_config failed: %d\n", error); 446 + return error; 447 + } 448 + 449 + idev = devm_input_allocate_device(&pdev->dev); 450 + if (!idev) { 451 + dev_err(&pdev->dev, "failed to allocate input device\n"); 452 + return -ENOMEM; 453 + } 454 + 455 + priv->idev = idev; 456 + priv->pen_status = PEN_UP_STATUS; 457 + 458 + /* Set input device info */ 459 + idev->name = IPROC_TS_NAME; 460 + idev->dev.parent = &pdev->dev; 461 + 462 + idev->id.bustype = BUS_HOST; 463 + idev->id.vendor = SERIO_UNKNOWN; 464 + idev->id.product = 0; 465 + idev->id.version = 0; 466 + 467 + idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 468 + __set_bit(BTN_TOUCH, idev->keybit); 469 + 470 + input_set_abs_params(idev, ABS_X, X_MIN, priv->cfg_params.max_x, 471 + priv->cfg_params.fuzz_x, 0); 472 + input_set_abs_params(idev, ABS_Y, Y_MIN, priv->cfg_params.max_y, 473 + priv->cfg_params.fuzz_y, 0); 474 + 475 + idev->open = iproc_ts_start; 476 + idev->close = iproc_ts_stop; 477 + 478 + input_set_drvdata(idev, priv); 479 + platform_set_drvdata(pdev, priv); 480 + 481 + /* get interrupt */ 482 + irq = platform_get_irq(pdev, 0); 483 + if (irq < 0) { 484 + dev_err(&pdev->dev, "platform_get_irq failed: %d\n", irq); 485 + return irq; 486 + } 487 + 488 + error = devm_request_irq(&pdev->dev, irq, 489 + iproc_touchscreen_interrupt, 490 + IRQF_SHARED, IPROC_TS_NAME, pdev); 491 + if (error) 492 + return error; 493 + 494 + error = input_register_device(priv->idev); 495 + if (error) { 496 + dev_err(&pdev->dev, 497 + "failed to register input device: %d\n", error); 498 + return error; 499 + } 500 + 501 + return 0; 502 + } 503 + 504 + static const struct of_device_id iproc_ts_of_match[] = { 505 + {.compatible = "brcm,iproc-touchscreen", }, 506 + { }, 507 + }; 508 + MODULE_DEVICE_TABLE(of, iproc_ts_of_match); 509 + 510 + static struct platform_driver iproc_ts_driver = { 511 + .probe = iproc_ts_probe, 512 + .driver = { 513 + .name = IPROC_TS_NAME, 514 + .of_match_table = of_match_ptr(iproc_ts_of_match), 515 + }, 516 + }; 517 + 518 + module_platform_driver(iproc_ts_driver); 519 + 520 + MODULE_DESCRIPTION("IPROC Touchscreen driver"); 521 + MODULE_AUTHOR("Broadcom"); 522 + MODULE_LICENSE("GPL v2");