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

Input: tsc2007 - add device tree support.

Signed-off-by: Denis Carikli <denis@eukrea.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Denis Carikli and committed by
Dmitry Torokhov
07f9e5cf bd77c321

+180 -46
+41
Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt
··· 1 + * Texas Instruments tsc2007 touchscreen controller 2 + 3 + Required properties: 4 + - compatible: must be "ti,tsc2007". 5 + - reg: I2C address of the chip. 6 + - ti,x-plate-ohms: X-plate resistance in ohms. 7 + 8 + Optional properties: 9 + - gpios: the interrupt gpio the chip is connected to (trough the penirq pin). 10 + The penirq pin goes to low when the panel is touched. 11 + (see GPIO binding[1] for more details). 12 + - interrupt-parent: the phandle for the gpio controller 13 + (see interrupt binding[0]). 14 + - interrupts: (gpio) interrupt to which the chip is connected 15 + (see interrupt binding[0]). 16 + - ti,max-rt: maximum pressure. 17 + - ti,fuzzx: specifies the absolute input fuzz x value. 18 + If set, it will permit noise in the data up to +- the value given to the fuzz 19 + parameter, that is used to filter noise from the event stream. 20 + - ti,fuzzy: specifies the absolute input fuzz y value. 21 + - ti,fuzzz: specifies the absolute input fuzz z value. 22 + - ti,poll-period: how much time to wait (in milliseconds) before reading again the 23 + values from the tsc2007. 24 + 25 + [0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt 26 + [1]: Documentation/devicetree/bindings/gpio/gpio.txt 27 + 28 + Example: 29 + &i2c1 { 30 + /* ... */ 31 + tsc2007@49 { 32 + compatible = "ti,tsc2007"; 33 + reg = <0x49>; 34 + interrupt-parent = <&gpio4>; 35 + interrupts = <0x0 0x8>; 36 + gpios = <&gpio4 0 0>; 37 + ti,x-plate-ohms = <180>; 38 + }; 39 + 40 + /* ... */ 41 + };
+1 -1
arch/arm/mach-imx/mach-cpuimx35.c
··· 53 53 }; 54 54 55 55 #define TSC2007_IRQGPIO IMX_GPIO_NR(3, 2) 56 - static int tsc2007_get_pendown_state(void) 56 + static int tsc2007_get_pendown_state(struct device *dev) 57 57 { 58 58 return !gpio_get_value(TSC2007_IRQGPIO); 59 59 }
+1 -1
arch/arm/mach-imx/mach-cpuimx51sd.c
··· 121 121 .flags = IMXUART_HAVE_RTSCTS, 122 122 }; 123 123 124 - static int tsc2007_get_pendown_state(void) 124 + static int tsc2007_get_pendown_state(struct device *dev) 125 125 { 126 126 if (mx51_revision() < IMX_CHIP_REVISION_3_0) 127 127 return !gpio_get_value(TSC2007_IRQGPIO_REV2);
+1 -1
arch/sh/boards/mach-ecovec24/setup.c
··· 501 501 /* TouchScreen */ 502 502 #define IRQ0 evt2irq(0x600) 503 503 504 - static int ts_get_pendown_state(void) 504 + static int ts_get_pendown_state(struct device *dev) 505 505 { 506 506 int val = 0; 507 507 gpio_free(GPIO_FN_INTC_IRQ0);
+133 -40
drivers/input/touchscreen/tsc2007.c
··· 26 26 #include <linux/interrupt.h> 27 27 #include <linux/i2c.h> 28 28 #include <linux/i2c/tsc2007.h> 29 + #include <linux/of_device.h> 30 + #include <linux/of.h> 31 + #include <linux/of_gpio.h> 29 32 30 33 #define TSC2007_MEASURE_TEMP0 (0x0 << 4) 31 34 #define TSC2007_MEASURE_AUX (0x2 << 4) ··· 77 74 u16 max_rt; 78 75 unsigned long poll_delay; 79 76 unsigned long poll_period; 77 + int fuzzx; 78 + int fuzzy; 79 + int fuzzz; 80 80 81 + unsigned gpio; 81 82 int irq; 82 83 83 84 wait_queue_head_t wait; 84 85 bool stopped; 85 86 86 - int (*get_pendown_state)(void); 87 + int (*get_pendown_state)(struct device *); 87 88 void (*clear_penirq)(void); 88 89 }; 89 90 ··· 168 161 if (!ts->get_pendown_state) 169 162 return true; 170 163 171 - return ts->get_pendown_state(); 164 + return ts->get_pendown_state(&ts->client->dev); 172 165 } 173 166 174 167 static irqreturn_t tsc2007_soft_irq(int irq, void *handle) ··· 185 178 186 179 rt = tsc2007_calculate_pressure(ts, &tc); 187 180 188 - if (rt == 0 && !ts->get_pendown_state) { 181 + if (!rt && !ts->get_pendown_state) { 189 182 /* 190 183 * If pressure reported is 0 and we don't have 191 184 * callback to check pendown state, we have to ··· 235 228 { 236 229 struct tsc2007 *ts = handle; 237 230 238 - if (!ts->get_pendown_state || likely(ts->get_pendown_state())) 231 + if (tsc2007_is_pen_down(ts)) 239 232 return IRQ_WAKE_THREAD; 240 233 241 234 if (ts->clear_penirq) ··· 280 273 tsc2007_stop(ts); 281 274 } 282 275 283 - static int tsc2007_probe(struct i2c_client *client, 284 - const struct i2c_device_id *id) 276 + #ifdef CONFIG_OF 277 + static int tsc2007_get_pendown_state_gpio(struct device *dev) 285 278 { 286 - struct tsc2007 *ts; 287 - struct tsc2007_platform_data *pdata = client->dev.platform_data; 288 - struct input_dev *input_dev; 289 - int err; 279 + struct i2c_client *client = to_i2c_client(dev); 280 + struct tsc2007 *ts = i2c_get_clientdata(client); 290 281 291 - if (!pdata) { 292 - dev_err(&client->dev, "platform data is required!\n"); 282 + return !gpio_get_value(ts->gpio); 283 + } 284 + 285 + static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts) 286 + { 287 + struct device_node *np = client->dev.of_node; 288 + u32 val32; 289 + u64 val64; 290 + 291 + if (!np) { 292 + dev_err(&client->dev, "missing device tree data\n"); 293 293 return -EINVAL; 294 294 } 295 295 296 - if (!i2c_check_functionality(client->adapter, 297 - I2C_FUNC_SMBUS_READ_WORD_DATA)) 298 - return -EIO; 296 + if (!of_property_read_u32(np, "ti,max-rt", &val32)) 297 + ts->max_rt = val32; 298 + else 299 + ts->max_rt = MAX_12BIT; 299 300 300 - ts = kzalloc(sizeof(struct tsc2007), GFP_KERNEL); 301 - input_dev = input_allocate_device(); 302 - if (!ts || !input_dev) { 303 - err = -ENOMEM; 304 - goto err_free_mem; 301 + if (!of_property_read_u32(np, "ti,fuzzx", &val32)) 302 + ts->fuzzx = val32; 303 + 304 + if (!of_property_read_u32(np, "ti,fuzzy", &val32)) 305 + ts->fuzzy = val32; 306 + 307 + if (!of_property_read_u32(np, "ti,fuzzz", &val32)) 308 + ts->fuzzz = val32; 309 + 310 + if (!of_property_read_u64(np, "ti,poll-period", &val64)) 311 + ts->poll_period = val64; 312 + else 313 + ts->poll_period = 1; 314 + 315 + if (!of_property_read_u32(np, "ti,x-plate-ohms", &val32)) { 316 + ts->x_plate_ohms = val32; 317 + } else { 318 + dev_err(&client->dev, "missing ti,x-plate-ohms devicetree property."); 319 + return -EINVAL; 305 320 } 306 321 307 - ts->client = client; 308 - ts->irq = client->irq; 309 - ts->input = input_dev; 310 - init_waitqueue_head(&ts->wait); 322 + ts->gpio = of_get_gpio(np, 0); 323 + if (gpio_is_valid(ts->gpio)) 324 + ts->get_pendown_state = tsc2007_get_pendown_state_gpio; 325 + else 326 + dev_warn(&client->dev, 327 + "GPIO not specified in DT (of_get_gpio returned %d)\n", 328 + ts->gpio); 311 329 330 + return 0; 331 + } 332 + #else 333 + static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts) 334 + { 335 + dev_err(&client->dev, "platform data is required!\n"); 336 + return -EINVAL; 337 + } 338 + #endif 339 + 340 + static int tsc2007_probe_pdev(struct i2c_client *client, struct tsc2007 *ts, 341 + const struct tsc2007_platform_data *pdata, 342 + const struct i2c_device_id *id) 343 + { 312 344 ts->model = pdata->model; 313 345 ts->x_plate_ohms = pdata->x_plate_ohms; 314 346 ts->max_rt = pdata->max_rt ? : MAX_12BIT; ··· 355 309 ts->poll_period = pdata->poll_period ? : 1; 356 310 ts->get_pendown_state = pdata->get_pendown_state; 357 311 ts->clear_penirq = pdata->clear_penirq; 312 + ts->fuzzx = pdata->fuzzx; 313 + ts->fuzzy = pdata->fuzzy; 314 + ts->fuzzz = pdata->fuzzz; 358 315 359 316 if (pdata->x_plate_ohms == 0) { 360 317 dev_err(&client->dev, "x_plate_ohms is not set up in platform data"); 361 - err = -EINVAL; 362 - goto err_free_mem; 318 + return -EINVAL; 363 319 } 320 + 321 + return 0; 322 + } 323 + 324 + static int tsc2007_probe(struct i2c_client *client, 325 + const struct i2c_device_id *id) 326 + { 327 + const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev); 328 + struct tsc2007 *ts; 329 + struct input_dev *input_dev; 330 + int err; 331 + 332 + if (!i2c_check_functionality(client->adapter, 333 + I2C_FUNC_SMBUS_READ_WORD_DATA)) 334 + return -EIO; 335 + 336 + ts = devm_kzalloc(&client->dev, sizeof(struct tsc2007), GFP_KERNEL); 337 + if (!ts) 338 + return -ENOMEM; 339 + 340 + if (pdata) 341 + err = tsc2007_probe_pdev(client, ts, pdata, id); 342 + else 343 + err = tsc2007_probe_dt(client, ts); 344 + if (err) 345 + return err; 346 + 347 + input_dev = input_allocate_device(); 348 + if (!input_dev) { 349 + err = -ENOMEM; 350 + goto err_free_input; 351 + }; 352 + 353 + i2c_set_clientdata(client, ts); 354 + 355 + ts->client = client; 356 + ts->irq = client->irq; 357 + ts->input = input_dev; 358 + init_waitqueue_head(&ts->wait); 364 359 365 360 snprintf(ts->phys, sizeof(ts->phys), 366 361 "%s/input0", dev_name(&client->dev)); ··· 418 331 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 419 332 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 420 333 421 - input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, pdata->fuzzx, 0); 422 - input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, pdata->fuzzy, 0); 334 + input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, ts->fuzzx, 0); 335 + input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, ts->fuzzy, 0); 423 336 input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 424 - pdata->fuzzz, 0); 337 + ts->fuzzz, 0); 425 338 426 - if (pdata->init_platform_hw) 339 + if (pdata && pdata->init_platform_hw) 427 340 pdata->init_platform_hw(); 428 341 429 342 err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq, 430 343 IRQF_ONESHOT, client->dev.driver->name, ts); 431 344 if (err < 0) { 432 345 dev_err(&client->dev, "irq %d busy?\n", ts->irq); 433 - goto err_free_mem; 346 + goto err_free_input; 434 347 } 435 348 436 349 tsc2007_stop(ts); ··· 439 352 if (err) 440 353 goto err_free_irq; 441 354 442 - i2c_set_clientdata(client, ts); 443 - 444 355 return 0; 445 356 446 357 err_free_irq: 447 358 free_irq(ts->irq, ts); 448 - if (pdata->exit_platform_hw) 359 + if (pdata && pdata->exit_platform_hw) 449 360 pdata->exit_platform_hw(); 450 - err_free_mem: 361 + err_free_input: 451 362 input_free_device(input_dev); 452 - kfree(ts); 453 363 return err; 454 364 } 455 365 456 366 static int tsc2007_remove(struct i2c_client *client) 457 367 { 458 - struct tsc2007 *ts = i2c_get_clientdata(client); 459 - struct tsc2007_platform_data *pdata = client->dev.platform_data; 368 + const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev); 369 + struct tsc2007 *ts = i2c_get_clientdata(client); 460 370 461 371 free_irq(ts->irq, ts); 462 372 463 - if (pdata->exit_platform_hw) 373 + if (pdata && pdata->exit_platform_hw) 464 374 pdata->exit_platform_hw(); 465 375 466 376 input_unregister_device(ts->input); ··· 473 389 474 390 MODULE_DEVICE_TABLE(i2c, tsc2007_idtable); 475 391 392 + #ifdef CONFIG_OF 393 + static const struct of_device_id tsc2007_of_match[] = { 394 + { .compatible = "ti,tsc2007" }, 395 + { /* sentinel */ } 396 + }; 397 + MODULE_DEVICE_TABLE(of, tsc2007_of_match); 398 + #endif 399 + 476 400 static struct i2c_driver tsc2007_driver = { 477 401 .driver = { 478 402 .owner = THIS_MODULE, 479 - .name = "tsc2007" 403 + .name = "tsc2007", 404 + .of_match_table = of_match_ptr(tsc2007_of_match), 480 405 }, 481 406 .id_table = tsc2007_idtable, 482 407 .probe = tsc2007_probe,
+3 -3
include/linux/i2c/tsc2007.h
··· 14 14 int fuzzy; 15 15 int fuzzz; 16 16 17 - int (*get_pendown_state)(void); 18 - void (*clear_penirq)(void); /* If needed, clear 2nd level 19 - interrupt source */ 17 + int (*get_pendown_state)(struct device *); 18 + /* If needed, clear 2nd level interrupt source */ 19 + void (*clear_penirq)(void); 20 20 int (*init_platform_hw)(void); 21 21 void (*exit_platform_hw)(void); 22 22 };