Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Driver for Goodix touchscreens that use the i2c-hid protocol.
0004  *
0005  * Copyright 2020 Google LLC
0006  */
0007 
0008 #include <linux/delay.h>
0009 #include <linux/device.h>
0010 #include <linux/gpio/consumer.h>
0011 #include <linux/i2c.h>
0012 #include <linux/kernel.h>
0013 #include <linux/module.h>
0014 #include <linux/of.h>
0015 #include <linux/pm.h>
0016 #include <linux/regulator/consumer.h>
0017 
0018 #include "i2c-hid.h"
0019 
0020 struct goodix_i2c_hid_timing_data {
0021     unsigned int post_gpio_reset_delay_ms;
0022     unsigned int post_power_delay_ms;
0023 };
0024 
0025 struct i2c_hid_of_goodix {
0026     struct i2chid_ops ops;
0027 
0028     struct regulator *vdd;
0029     struct notifier_block nb;
0030     struct gpio_desc *reset_gpio;
0031     const struct goodix_i2c_hid_timing_data *timings;
0032 };
0033 
0034 static void goodix_i2c_hid_deassert_reset(struct i2c_hid_of_goodix *ihid_goodix,
0035                       bool regulator_just_turned_on)
0036 {
0037     if (regulator_just_turned_on && ihid_goodix->timings->post_power_delay_ms)
0038         msleep(ihid_goodix->timings->post_power_delay_ms);
0039 
0040     gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 0);
0041     if (ihid_goodix->timings->post_gpio_reset_delay_ms)
0042         msleep(ihid_goodix->timings->post_gpio_reset_delay_ms);
0043 }
0044 
0045 static int goodix_i2c_hid_power_up(struct i2chid_ops *ops)
0046 {
0047     struct i2c_hid_of_goodix *ihid_goodix =
0048         container_of(ops, struct i2c_hid_of_goodix, ops);
0049 
0050     return regulator_enable(ihid_goodix->vdd);
0051 }
0052 
0053 static void goodix_i2c_hid_power_down(struct i2chid_ops *ops)
0054 {
0055     struct i2c_hid_of_goodix *ihid_goodix =
0056         container_of(ops, struct i2c_hid_of_goodix, ops);
0057 
0058     regulator_disable(ihid_goodix->vdd);
0059 }
0060 
0061 static int ihid_goodix_vdd_notify(struct notifier_block *nb,
0062                     unsigned long event,
0063                     void *ignored)
0064 {
0065     struct i2c_hid_of_goodix *ihid_goodix =
0066         container_of(nb, struct i2c_hid_of_goodix, nb);
0067     int ret = NOTIFY_OK;
0068 
0069     switch (event) {
0070     case REGULATOR_EVENT_PRE_DISABLE:
0071         gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1);
0072         break;
0073 
0074     case REGULATOR_EVENT_ENABLE:
0075         goodix_i2c_hid_deassert_reset(ihid_goodix, true);
0076         break;
0077 
0078     case REGULATOR_EVENT_ABORT_DISABLE:
0079         goodix_i2c_hid_deassert_reset(ihid_goodix, false);
0080         break;
0081 
0082     default:
0083         ret = NOTIFY_DONE;
0084         break;
0085     }
0086 
0087     return ret;
0088 }
0089 
0090 static int i2c_hid_of_goodix_probe(struct i2c_client *client,
0091                    const struct i2c_device_id *id)
0092 {
0093     struct i2c_hid_of_goodix *ihid_goodix;
0094     int ret;
0095     ihid_goodix = devm_kzalloc(&client->dev, sizeof(*ihid_goodix),
0096                    GFP_KERNEL);
0097     if (!ihid_goodix)
0098         return -ENOMEM;
0099 
0100     ihid_goodix->ops.power_up = goodix_i2c_hid_power_up;
0101     ihid_goodix->ops.power_down = goodix_i2c_hid_power_down;
0102 
0103     /* Start out with reset asserted */
0104     ihid_goodix->reset_gpio =
0105         devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH);
0106     if (IS_ERR(ihid_goodix->reset_gpio))
0107         return PTR_ERR(ihid_goodix->reset_gpio);
0108 
0109     ihid_goodix->vdd = devm_regulator_get(&client->dev, "vdd");
0110     if (IS_ERR(ihid_goodix->vdd))
0111         return PTR_ERR(ihid_goodix->vdd);
0112 
0113     ihid_goodix->timings = device_get_match_data(&client->dev);
0114 
0115     /*
0116      * We need to control the "reset" line in lockstep with the regulator
0117      * actually turning on an off instead of just when we make the request.
0118      * This matters if the regulator is shared with another consumer.
0119      * - If the regulator is off then we must assert reset. The reset
0120      *   line is active low and on some boards it could cause a current
0121      *   leak if left high.
0122      * - If the regulator is on then we don't want reset asserted for very
0123      *   long. Holding the controller in reset apparently draws extra
0124      *   power.
0125      */
0126     ihid_goodix->nb.notifier_call = ihid_goodix_vdd_notify;
0127     ret = devm_regulator_register_notifier(ihid_goodix->vdd, &ihid_goodix->nb);
0128     if (ret)
0129         return dev_err_probe(&client->dev, ret,
0130             "regulator notifier request failed\n");
0131 
0132     /*
0133      * If someone else is holding the regulator on (or the regulator is
0134      * an always-on one) we might never be told to deassert reset. Do it
0135      * now... and temporarily bump the regulator reference count just to
0136      * make sure it is impossible for this to race with our own notifier!
0137      * We also assume that someone else might have _just barely_ turned
0138      * the regulator on so we'll do the full "post_power_delay" just in
0139      * case.
0140      */
0141     if (ihid_goodix->reset_gpio && regulator_is_enabled(ihid_goodix->vdd)) {
0142         ret = regulator_enable(ihid_goodix->vdd);
0143         if (ret)
0144             return ret;
0145         goodix_i2c_hid_deassert_reset(ihid_goodix, true);
0146         regulator_disable(ihid_goodix->vdd);
0147     }
0148 
0149     return i2c_hid_core_probe(client, &ihid_goodix->ops, 0x0001, 0);
0150 }
0151 
0152 static const struct goodix_i2c_hid_timing_data goodix_gt7375p_timing_data = {
0153     .post_power_delay_ms = 10,
0154     .post_gpio_reset_delay_ms = 180,
0155 };
0156 
0157 static const struct of_device_id goodix_i2c_hid_of_match[] = {
0158     { .compatible = "goodix,gt7375p", .data = &goodix_gt7375p_timing_data },
0159     { }
0160 };
0161 MODULE_DEVICE_TABLE(of, goodix_i2c_hid_of_match);
0162 
0163 static struct i2c_driver goodix_i2c_hid_ts_driver = {
0164     .driver = {
0165         .name   = "i2c_hid_of_goodix",
0166         .pm = &i2c_hid_core_pm,
0167         .probe_type = PROBE_PREFER_ASYNCHRONOUS,
0168         .of_match_table = of_match_ptr(goodix_i2c_hid_of_match),
0169     },
0170     .probe      = i2c_hid_of_goodix_probe,
0171     .remove     = i2c_hid_core_remove,
0172     .shutdown   = i2c_hid_core_shutdown,
0173 };
0174 module_i2c_driver(goodix_i2c_hid_ts_driver);
0175 
0176 MODULE_AUTHOR("Douglas Anderson <dianders@chromium.org>");
0177 MODULE_DESCRIPTION("Goodix i2c-hid touchscreen driver");
0178 MODULE_LICENSE("GPL v2");