1c1ed18c1SDouglas Anderson // SPDX-License-Identifier: GPL-2.0 2c1ed18c1SDouglas Anderson /* 3c1ed18c1SDouglas Anderson * Driver for Goodix touchscreens that use the i2c-hid protocol. 4c1ed18c1SDouglas Anderson * 5c1ed18c1SDouglas Anderson * Copyright 2020 Google LLC 6c1ed18c1SDouglas Anderson */ 7c1ed18c1SDouglas Anderson 8c1ed18c1SDouglas Anderson #include <linux/delay.h> 9c1ed18c1SDouglas Anderson #include <linux/device.h> 10c1ed18c1SDouglas Anderson #include <linux/gpio/consumer.h> 11c1ed18c1SDouglas Anderson #include <linux/i2c.h> 12c1ed18c1SDouglas Anderson #include <linux/kernel.h> 13c1ed18c1SDouglas Anderson #include <linux/module.h> 14c1ed18c1SDouglas Anderson #include <linux/of.h> 15c1ed18c1SDouglas Anderson #include <linux/pm.h> 16c1ed18c1SDouglas Anderson #include <linux/regulator/consumer.h> 17c1ed18c1SDouglas Anderson 18c1ed18c1SDouglas Anderson #include "i2c-hid.h" 19c1ed18c1SDouglas Anderson 20c1ed18c1SDouglas Anderson struct goodix_i2c_hid_timing_data { 21c1ed18c1SDouglas Anderson unsigned int post_gpio_reset_delay_ms; 22c1ed18c1SDouglas Anderson unsigned int post_power_delay_ms; 23c1ed18c1SDouglas Anderson }; 24c1ed18c1SDouglas Anderson 25c1ed18c1SDouglas Anderson struct i2c_hid_of_goodix { 26c1ed18c1SDouglas Anderson struct i2chid_ops ops; 27c1ed18c1SDouglas Anderson 28c1ed18c1SDouglas Anderson struct regulator *vdd; 2918eeef46SDouglas Anderson struct notifier_block nb; 30c1ed18c1SDouglas Anderson struct gpio_desc *reset_gpio; 31c1ed18c1SDouglas Anderson const struct goodix_i2c_hid_timing_data *timings; 32c1ed18c1SDouglas Anderson }; 33c1ed18c1SDouglas Anderson 3418eeef46SDouglas Anderson static void goodix_i2c_hid_deassert_reset(struct i2c_hid_of_goodix *ihid_goodix, 3518eeef46SDouglas Anderson bool regulator_just_turned_on) 36c1ed18c1SDouglas Anderson { 3718eeef46SDouglas Anderson if (regulator_just_turned_on && ihid_goodix->timings->post_power_delay_ms) 38c1ed18c1SDouglas Anderson msleep(ihid_goodix->timings->post_power_delay_ms); 39c1ed18c1SDouglas Anderson 40c1ed18c1SDouglas Anderson gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 0); 41c1ed18c1SDouglas Anderson if (ihid_goodix->timings->post_gpio_reset_delay_ms) 42c1ed18c1SDouglas Anderson msleep(ihid_goodix->timings->post_gpio_reset_delay_ms); 4318eeef46SDouglas Anderson } 44c1ed18c1SDouglas Anderson 4518eeef46SDouglas Anderson static int goodix_i2c_hid_power_up(struct i2chid_ops *ops) 4618eeef46SDouglas Anderson { 4718eeef46SDouglas Anderson struct i2c_hid_of_goodix *ihid_goodix = 4818eeef46SDouglas Anderson container_of(ops, struct i2c_hid_of_goodix, ops); 4918eeef46SDouglas Anderson 5018eeef46SDouglas Anderson return regulator_enable(ihid_goodix->vdd); 51c1ed18c1SDouglas Anderson } 52c1ed18c1SDouglas Anderson 53c1ed18c1SDouglas Anderson static void goodix_i2c_hid_power_down(struct i2chid_ops *ops) 54c1ed18c1SDouglas Anderson { 55c1ed18c1SDouglas Anderson struct i2c_hid_of_goodix *ihid_goodix = 56c1ed18c1SDouglas Anderson container_of(ops, struct i2c_hid_of_goodix, ops); 57c1ed18c1SDouglas Anderson 58c1ed18c1SDouglas Anderson regulator_disable(ihid_goodix->vdd); 59c1ed18c1SDouglas Anderson } 60c1ed18c1SDouglas Anderson 6118eeef46SDouglas Anderson static int ihid_goodix_vdd_notify(struct notifier_block *nb, 6218eeef46SDouglas Anderson unsigned long event, 6318eeef46SDouglas Anderson void *ignored) 6418eeef46SDouglas Anderson { 6518eeef46SDouglas Anderson struct i2c_hid_of_goodix *ihid_goodix = 6618eeef46SDouglas Anderson container_of(nb, struct i2c_hid_of_goodix, nb); 6718eeef46SDouglas Anderson int ret = NOTIFY_OK; 6818eeef46SDouglas Anderson 6918eeef46SDouglas Anderson switch (event) { 7018eeef46SDouglas Anderson case REGULATOR_EVENT_PRE_DISABLE: 7118eeef46SDouglas Anderson gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1); 7218eeef46SDouglas Anderson break; 7318eeef46SDouglas Anderson 7418eeef46SDouglas Anderson case REGULATOR_EVENT_ENABLE: 7518eeef46SDouglas Anderson goodix_i2c_hid_deassert_reset(ihid_goodix, true); 7618eeef46SDouglas Anderson break; 7718eeef46SDouglas Anderson 7818eeef46SDouglas Anderson case REGULATOR_EVENT_ABORT_DISABLE: 7918eeef46SDouglas Anderson goodix_i2c_hid_deassert_reset(ihid_goodix, false); 8018eeef46SDouglas Anderson break; 8118eeef46SDouglas Anderson 8218eeef46SDouglas Anderson default: 8318eeef46SDouglas Anderson ret = NOTIFY_DONE; 8418eeef46SDouglas Anderson break; 8518eeef46SDouglas Anderson } 8618eeef46SDouglas Anderson 8718eeef46SDouglas Anderson return ret; 8818eeef46SDouglas Anderson } 8918eeef46SDouglas Anderson 90*baf34f3bSStephen Kitt static int i2c_hid_of_goodix_probe(struct i2c_client *client) 91c1ed18c1SDouglas Anderson { 92c1ed18c1SDouglas Anderson struct i2c_hid_of_goodix *ihid_goodix; 9318eeef46SDouglas Anderson int ret; 94c1ed18c1SDouglas Anderson ihid_goodix = devm_kzalloc(&client->dev, sizeof(*ihid_goodix), 95c1ed18c1SDouglas Anderson GFP_KERNEL); 96c1ed18c1SDouglas Anderson if (!ihid_goodix) 97c1ed18c1SDouglas Anderson return -ENOMEM; 98c1ed18c1SDouglas Anderson 99c1ed18c1SDouglas Anderson ihid_goodix->ops.power_up = goodix_i2c_hid_power_up; 100c1ed18c1SDouglas Anderson ihid_goodix->ops.power_down = goodix_i2c_hid_power_down; 101c1ed18c1SDouglas Anderson 102c1ed18c1SDouglas Anderson /* Start out with reset asserted */ 103c1ed18c1SDouglas Anderson ihid_goodix->reset_gpio = 104c1ed18c1SDouglas Anderson devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH); 105c1ed18c1SDouglas Anderson if (IS_ERR(ihid_goodix->reset_gpio)) 106c1ed18c1SDouglas Anderson return PTR_ERR(ihid_goodix->reset_gpio); 107c1ed18c1SDouglas Anderson 108c1ed18c1SDouglas Anderson ihid_goodix->vdd = devm_regulator_get(&client->dev, "vdd"); 109c1ed18c1SDouglas Anderson if (IS_ERR(ihid_goodix->vdd)) 110c1ed18c1SDouglas Anderson return PTR_ERR(ihid_goodix->vdd); 111c1ed18c1SDouglas Anderson 112c1ed18c1SDouglas Anderson ihid_goodix->timings = device_get_match_data(&client->dev); 113c1ed18c1SDouglas Anderson 11418eeef46SDouglas Anderson /* 11518eeef46SDouglas Anderson * We need to control the "reset" line in lockstep with the regulator 11618eeef46SDouglas Anderson * actually turning on an off instead of just when we make the request. 11718eeef46SDouglas Anderson * This matters if the regulator is shared with another consumer. 11818eeef46SDouglas Anderson * - If the regulator is off then we must assert reset. The reset 11918eeef46SDouglas Anderson * line is active low and on some boards it could cause a current 12018eeef46SDouglas Anderson * leak if left high. 12118eeef46SDouglas Anderson * - If the regulator is on then we don't want reset asserted for very 12218eeef46SDouglas Anderson * long. Holding the controller in reset apparently draws extra 12318eeef46SDouglas Anderson * power. 12418eeef46SDouglas Anderson */ 12518eeef46SDouglas Anderson ihid_goodix->nb.notifier_call = ihid_goodix_vdd_notify; 12625ddd7cfSDouglas Anderson ret = devm_regulator_register_notifier(ihid_goodix->vdd, &ihid_goodix->nb); 1272787710fSDaniel Thompson if (ret) 12818eeef46SDouglas Anderson return dev_err_probe(&client->dev, ret, 12918eeef46SDouglas Anderson "regulator notifier request failed\n"); 13018eeef46SDouglas Anderson 13118eeef46SDouglas Anderson /* 13218eeef46SDouglas Anderson * If someone else is holding the regulator on (or the regulator is 13318eeef46SDouglas Anderson * an always-on one) we might never be told to deassert reset. Do it 1342787710fSDaniel Thompson * now... and temporarily bump the regulator reference count just to 1352787710fSDaniel Thompson * make sure it is impossible for this to race with our own notifier! 1362787710fSDaniel Thompson * We also assume that someone else might have _just barely_ turned 1372787710fSDaniel Thompson * the regulator on so we'll do the full "post_power_delay" just in 1382787710fSDaniel Thompson * case. 13918eeef46SDouglas Anderson */ 1402787710fSDaniel Thompson if (ihid_goodix->reset_gpio && regulator_is_enabled(ihid_goodix->vdd)) { 1412787710fSDaniel Thompson ret = regulator_enable(ihid_goodix->vdd); 1422787710fSDaniel Thompson if (ret) 1432787710fSDaniel Thompson return ret; 14418eeef46SDouglas Anderson goodix_i2c_hid_deassert_reset(ihid_goodix, true); 1452787710fSDaniel Thompson regulator_disable(ihid_goodix->vdd); 1462787710fSDaniel Thompson } 14718eeef46SDouglas Anderson 148b60d3c80SAlistair Francis return i2c_hid_core_probe(client, &ihid_goodix->ops, 0x0001, 0); 149c1ed18c1SDouglas Anderson } 150c1ed18c1SDouglas Anderson 151c1ed18c1SDouglas Anderson static const struct goodix_i2c_hid_timing_data goodix_gt7375p_timing_data = { 152c1ed18c1SDouglas Anderson .post_power_delay_ms = 10, 153c1ed18c1SDouglas Anderson .post_gpio_reset_delay_ms = 180, 154c1ed18c1SDouglas Anderson }; 155c1ed18c1SDouglas Anderson 156c1ed18c1SDouglas Anderson static const struct of_device_id goodix_i2c_hid_of_match[] = { 157c1ed18c1SDouglas Anderson { .compatible = "goodix,gt7375p", .data = &goodix_gt7375p_timing_data }, 158c1ed18c1SDouglas Anderson { } 159c1ed18c1SDouglas Anderson }; 160c1ed18c1SDouglas Anderson MODULE_DEVICE_TABLE(of, goodix_i2c_hid_of_match); 161c1ed18c1SDouglas Anderson 162c1ed18c1SDouglas Anderson static struct i2c_driver goodix_i2c_hid_ts_driver = { 163c1ed18c1SDouglas Anderson .driver = { 164c1ed18c1SDouglas Anderson .name = "i2c_hid_of_goodix", 165c1ed18c1SDouglas Anderson .pm = &i2c_hid_core_pm, 166c1ed18c1SDouglas Anderson .probe_type = PROBE_PREFER_ASYNCHRONOUS, 167c1ed18c1SDouglas Anderson .of_match_table = of_match_ptr(goodix_i2c_hid_of_match), 168c1ed18c1SDouglas Anderson }, 169*baf34f3bSStephen Kitt .probe_new = i2c_hid_of_goodix_probe, 170c1ed18c1SDouglas Anderson .remove = i2c_hid_core_remove, 171c1ed18c1SDouglas Anderson .shutdown = i2c_hid_core_shutdown, 172c1ed18c1SDouglas Anderson }; 173c1ed18c1SDouglas Anderson module_i2c_driver(goodix_i2c_hid_ts_driver); 174c1ed18c1SDouglas Anderson 175c1ed18c1SDouglas Anderson MODULE_AUTHOR("Douglas Anderson <dianders@chromium.org>"); 176c1ed18c1SDouglas Anderson MODULE_DESCRIPTION("Goodix i2c-hid touchscreen driver"); 177c1ed18c1SDouglas Anderson MODULE_LICENSE("GPL v2"); 178