i2c-hid-of-elan.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Driver for Elan touchscreens that use the i2c-hid protocol.
  4. *
  5. * Copyright 2020 Google LLC
  6. */
  7. #include <linux/delay.h>
  8. #include <linux/device.h>
  9. #include <linux/gpio/consumer.h>
  10. #include <linux/i2c.h>
  11. #include <linux/kernel.h>
  12. #include <linux/module.h>
  13. #include <linux/of.h>
  14. #include <linux/pm.h>
  15. #include <linux/regulator/consumer.h>
  16. #include "i2c-hid.h"
  17. struct elan_i2c_hid_chip_data {
  18. unsigned int post_gpio_reset_delay_ms;
  19. unsigned int post_power_delay_ms;
  20. u16 hid_descriptor_address;
  21. };
  22. struct i2c_hid_of_elan {
  23. struct i2chid_ops ops;
  24. struct regulator *vcc33;
  25. struct regulator *vccio;
  26. struct gpio_desc *reset_gpio;
  27. const struct elan_i2c_hid_chip_data *chip_data;
  28. };
  29. static int elan_i2c_hid_power_up(struct i2chid_ops *ops)
  30. {
  31. struct i2c_hid_of_elan *ihid_elan =
  32. container_of(ops, struct i2c_hid_of_elan, ops);
  33. int ret;
  34. ret = regulator_enable(ihid_elan->vcc33);
  35. if (ret)
  36. return ret;
  37. ret = regulator_enable(ihid_elan->vccio);
  38. if (ret) {
  39. regulator_disable(ihid_elan->vcc33);
  40. return ret;
  41. }
  42. if (ihid_elan->chip_data->post_power_delay_ms)
  43. msleep(ihid_elan->chip_data->post_power_delay_ms);
  44. gpiod_set_value_cansleep(ihid_elan->reset_gpio, 0);
  45. if (ihid_elan->chip_data->post_gpio_reset_delay_ms)
  46. msleep(ihid_elan->chip_data->post_gpio_reset_delay_ms);
  47. return 0;
  48. }
  49. static void elan_i2c_hid_power_down(struct i2chid_ops *ops)
  50. {
  51. struct i2c_hid_of_elan *ihid_elan =
  52. container_of(ops, struct i2c_hid_of_elan, ops);
  53. gpiod_set_value_cansleep(ihid_elan->reset_gpio, 1);
  54. regulator_disable(ihid_elan->vccio);
  55. regulator_disable(ihid_elan->vcc33);
  56. }
  57. static int i2c_hid_of_elan_probe(struct i2c_client *client,
  58. const struct i2c_device_id *id)
  59. {
  60. struct i2c_hid_of_elan *ihid_elan;
  61. ihid_elan = devm_kzalloc(&client->dev, sizeof(*ihid_elan), GFP_KERNEL);
  62. if (!ihid_elan)
  63. return -ENOMEM;
  64. ihid_elan->ops.power_up = elan_i2c_hid_power_up;
  65. ihid_elan->ops.power_down = elan_i2c_hid_power_down;
  66. /* Start out with reset asserted */
  67. ihid_elan->reset_gpio =
  68. devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH);
  69. if (IS_ERR(ihid_elan->reset_gpio))
  70. return PTR_ERR(ihid_elan->reset_gpio);
  71. ihid_elan->vccio = devm_regulator_get(&client->dev, "vccio");
  72. if (IS_ERR(ihid_elan->vccio))
  73. return PTR_ERR(ihid_elan->vccio);
  74. ihid_elan->vcc33 = devm_regulator_get(&client->dev, "vcc33");
  75. if (IS_ERR(ihid_elan->vcc33))
  76. return PTR_ERR(ihid_elan->vcc33);
  77. ihid_elan->chip_data = device_get_match_data(&client->dev);
  78. return i2c_hid_core_probe(client, &ihid_elan->ops,
  79. ihid_elan->chip_data->hid_descriptor_address, 0);
  80. }
  81. static const struct elan_i2c_hid_chip_data elan_ekth6915_chip_data = {
  82. .post_power_delay_ms = 1,
  83. .post_gpio_reset_delay_ms = 300,
  84. .hid_descriptor_address = 0x0001,
  85. };
  86. static const struct of_device_id elan_i2c_hid_of_match[] = {
  87. { .compatible = "elan,ekth6915", .data = &elan_ekth6915_chip_data },
  88. { }
  89. };
  90. MODULE_DEVICE_TABLE(of, elan_i2c_hid_of_match);
  91. static struct i2c_driver elan_i2c_hid_ts_driver = {
  92. .driver = {
  93. .name = "i2c_hid_of_elan",
  94. .pm = &i2c_hid_core_pm,
  95. .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  96. .of_match_table = of_match_ptr(elan_i2c_hid_of_match),
  97. },
  98. .probe = i2c_hid_of_elan_probe,
  99. .remove = i2c_hid_core_remove,
  100. .shutdown = i2c_hid_core_shutdown,
  101. };
  102. module_i2c_driver(elan_i2c_hid_ts_driver);
  103. MODULE_AUTHOR("Douglas Anderson <[email protected]>");
  104. MODULE_DESCRIPTION("Elan i2c-hid touchscreen driver");
  105. MODULE_LICENSE("GPL");