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