From 34ba3657a503184e8d9b64afac7f2d83ddae52fb Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Fri, 23 Dec 2022 02:53:34 +0000 Subject: HID: i2c-hid: switch to standard debugging APIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of implementing a custom form of dynamic debugging we can use the standard debugging APIs. If the kernel is built with CONFIG_DYNAMIC_DEBUG this will be more discoverable and featureful. Also the previous module parameter "debug" is read-only so it can't actually be enabled. Signed-off-by: Thomas Weißschuh Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid-core.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers/hid/i2c-hid') diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c index b86b62f97108..b4ed21f25600 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -67,16 +67,7 @@ #define I2C_HID_PWR_ON 0x00 #define I2C_HID_PWR_SLEEP 0x01 -/* debug option */ -static bool debug; -module_param(debug, bool, 0444); -MODULE_PARM_DESC(debug, "print a lot of debug information"); - -#define i2c_hid_dbg(ihid, fmt, arg...) \ -do { \ - if (debug) \ - dev_printk(KERN_DEBUG, &(ihid)->client->dev, fmt, ##arg); \ -} while (0) +#define i2c_hid_dbg(ihid, ...) dev_dbg(&(ihid)->client->dev, __VA_ARGS__) struct i2c_hid_desc { __le16 wHIDDescLength; -- cgit v1.2.3 From f639e0b68036034c6ee9c01480cd2a13189dd306 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Fri, 23 Dec 2022 02:53:35 +0000 Subject: HID: i2c-hid: use uniform debugging APIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only two locations in i2c-hid are using the standard dev_dbg() APIs. The rest are all using the custom i2c_hid_dbg(), which in turn uses dev_dbg(). Signed-off-by: Thomas Weißschuh Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/hid/i2c-hid') diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c index b4ed21f25600..c83c93716782 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -850,7 +850,7 @@ static int i2c_hid_init_irq(struct i2c_client *client) unsigned long irqflags = 0; int ret; - dev_dbg(&client->dev, "Requesting IRQ: %d\n", client->irq); + i2c_hid_dbg(ihid, "Requesting IRQ: %d\n", client->irq); if (!irq_get_trigger_type(client->irq)) irqflags = IRQF_TRIGGER_LOW; @@ -994,7 +994,7 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, /* Make sure there is something at this address */ ret = i2c_smbus_read_byte(client); if (ret < 0) { - dev_dbg(&client->dev, "nothing at this address: %d\n", ret); + i2c_hid_dbg(ihid, "nothing at this address: %d\n", ret); ret = -ENXIO; goto err_powered; } -- cgit v1.2.3 From 572eaeb7fae8883612b9f410dafb0f9f5a563dc2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 16 Jan 2023 17:46:20 +0200 Subject: HID: i2c-hid: acpi: Drop unneded NULL check of adev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver is enumerated on ACPI platforms, so adev is valid. Since there is no valid I²C ID table provided, there is no possibility to bind a device to this driver via user space. Hence, drop unneeded NULL check of adev. Signed-off-by: Andy Shevchenko Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid-acpi.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers/hid/i2c-hid') diff --git a/drivers/hid/i2c-hid/i2c-hid-acpi.c b/drivers/hid/i2c-hid/i2c-hid-acpi.c index 375c77c3db74..5e28da45e762 100644 --- a/drivers/hid/i2c-hid/i2c-hid-acpi.c +++ b/drivers/hid/i2c-hid/i2c-hid-acpi.c @@ -48,8 +48,9 @@ static guid_t i2c_hid_guid = GUID_INIT(0x3CDFF6F7, 0x4267, 0x4555, 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE); -static int i2c_hid_acpi_get_descriptor(struct acpi_device *adev) +static int i2c_hid_acpi_get_descriptor(struct i2c_hid_acpi *ihid_acpi) { + struct acpi_device *adev = ihid_acpi->adev; acpi_handle handle = acpi_device_handle(adev); union acpi_object *obj; u16 hid_descriptor_address; @@ -81,29 +82,22 @@ static int i2c_hid_acpi_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct i2c_hid_acpi *ihid_acpi; - struct acpi_device *adev; u16 hid_descriptor_address; int ret; - adev = ACPI_COMPANION(dev); - if (!adev) { - dev_err(&client->dev, "Error could not get ACPI device\n"); - return -ENODEV; - } - ihid_acpi = devm_kzalloc(&client->dev, sizeof(*ihid_acpi), GFP_KERNEL); if (!ihid_acpi) return -ENOMEM; - ihid_acpi->adev = adev; + ihid_acpi->adev = ACPI_COMPANION(dev); ihid_acpi->ops.shutdown_tail = i2c_hid_acpi_shutdown_tail; - ret = i2c_hid_acpi_get_descriptor(adev); + ret = i2c_hid_acpi_get_descriptor(ihid_acpi); if (ret < 0) return ret; hid_descriptor_address = ret; - acpi_device_fix_up_power(adev); + acpi_device_fix_up_power(ihid_acpi->adev); return i2c_hid_core_probe(client, &ihid_acpi->ops, hid_descriptor_address, 0); -- cgit v1.2.3 From 4122abfed2193e752485282370abf5c419f05cad Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 16 Jan 2023 17:46:21 +0200 Subject: HID: i2c-hid: acpi: Unify ACPI ID tables format Unify ACPI ID tables format by: - surrounding HID by spaces - dropping unnecessary driver_data assignment to 0 - dropping comma at the terminator entry Signed-off-by: Andy Shevchenko Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid-acpi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/hid/i2c-hid') diff --git a/drivers/hid/i2c-hid/i2c-hid-acpi.c b/drivers/hid/i2c-hid/i2c-hid-acpi.c index 5e28da45e762..3a7e2bcb5412 100644 --- a/drivers/hid/i2c-hid/i2c-hid-acpi.c +++ b/drivers/hid/i2c-hid/i2c-hid-acpi.c @@ -39,8 +39,8 @@ static const struct acpi_device_id i2c_hid_acpi_blacklist[] = { * The CHPN0001 ACPI device, which is used to describe the Chipone * ICN8505 controller, has a _CID of PNP0C50 but is not HID compatible. */ - {"CHPN0001", 0 }, - { }, + { "CHPN0001" }, + { } }; /* HID I²C Device: 3cdff6f7-4267-4555-ad05-b30a3d8938de */ @@ -104,9 +104,9 @@ static int i2c_hid_acpi_probe(struct i2c_client *client) } static const struct acpi_device_id i2c_hid_acpi_match[] = { - {"ACPI0C50", 0 }, - {"PNP0C50", 0 }, - { }, + { "ACPI0C50" }, + { "PNP0C50" }, + { } }; MODULE_DEVICE_TABLE(acpi, i2c_hid_acpi_match); -- cgit v1.2.3 From 557e05fa9fdd0184890ca206cdec250cdd30375e Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Mon, 6 Feb 2023 18:48:13 -0800 Subject: HID: i2c-hid: goodix: Stop tying the reset line to the regulator In commit 18eeef46d359 ("HID: i2c-hid: goodix: Tie the reset line to true state of the regulator"), we started tying the reset line of Goodix touchscreens to the regulator. The primary motivation for that patch was some pre-production hardware (specifically sc7180-trogdor-homestar) where it was proposed to hook the touchscreen's main 3.3V power rail to an always-on supply. In such a case, when we turned "off" the touchscreen in Linux it was bad to assert the "reset" GPIO because that was causing a power drain. The patch accomplished that goal and did it in a general sort of way that didn't require special properties to be added in the device tree for homestar. It turns out that the design of using an always-on power rail for the touchscreen was rejected soon after the patch was written and long before sc7180-trogdor-homestar went into production. The final design of homestar actually fully separates the rail for the touchscreen and the display panel and both can be powered off and on. That means that the original motivation for the feature is gone. There are 3 other users of the goodix i2c-hid driver in mainline. I'll first talk about 2 of the other users in mainline: coachz and mrbland. On both coachz and mrbland the touchscreen power and panel power _are_ shared. That means that the patch to tie the reset line to the true state of the regulator _is_ doing something on those boards. Specifically, the patch reduced power consumption by tens of mA in the case where we turned the touchscreen off but left the panel on. Other than saving a small bit of power, the patch wasn't truly necessary. That being said, even though a small bit of power was saved in the state of "panel on + touchscreen off", that's not actually a state we ever expect to be in, except perhaps for very short periods of time at boot or during suspend/resume. Thus, the patch is truly not necessary. It should be further noted that, as documented in the original patch, the current code still didn't optimize power for every corner case of the "shared rail" situation. The last user in mainline was very recently added: evoker. Evoker is actually the motivation for me removing this bit of code. It turns out that for evoker we need to manage a second power rail for IO to the touchscreen. Trying to fit the management of this IO rail into the regulator notifiers turns out to be extremely hard. To avoid lockdep splats you shouldn't enable/disable other regulators in regulator notifiers and trying to find a way around this was going to be fairly difficult. Given the lack of any true motivation to tie the reset line to the regulator, lets go back to the simpler days and remove the code. This is, effectively, a revert of commit bdbc65eb77ee ("HID: i2c-hid: goodix: Fix a lockdep splat"), commit 25ddd7cfc582 ("HID: i2c-hid: goodix: Use the devm variant of regulator_register_notifier()"), and commit 18eeef46d359 ("HID: i2c-hid: goodix: Tie the reset line to true state of the regulator"). Signed-off-by: Douglas Anderson Reviewed-by: Matthias Kaehlcke Reviewed-by: Dmitry Torokhov Link: https://lore.kernel.org/r/20230206184744.4.I085b32b6140c7d1ac4e7e97b712bff9dd5962b62@changeid Signed-off-by: Benjamin Tissoires --- drivers/hid/i2c-hid/i2c-hid-of-goodix.c | 88 +++++---------------------------- 1 file changed, 13 insertions(+), 75 deletions(-) (limited to 'drivers/hid/i2c-hid') diff --git a/drivers/hid/i2c-hid/i2c-hid-of-goodix.c b/drivers/hid/i2c-hid/i2c-hid-of-goodix.c index 29c6cb174032..584d833dc0aa 100644 --- a/drivers/hid/i2c-hid/i2c-hid-of-goodix.c +++ b/drivers/hid/i2c-hid/i2c-hid-of-goodix.c @@ -26,28 +26,28 @@ struct i2c_hid_of_goodix { struct i2chid_ops ops; struct regulator *vdd; - struct notifier_block nb; struct gpio_desc *reset_gpio; const struct goodix_i2c_hid_timing_data *timings; }; -static void goodix_i2c_hid_deassert_reset(struct i2c_hid_of_goodix *ihid_goodix, - bool regulator_just_turned_on) +static int goodix_i2c_hid_power_up(struct i2chid_ops *ops) { - if (regulator_just_turned_on && ihid_goodix->timings->post_power_delay_ms) + struct i2c_hid_of_goodix *ihid_goodix = + container_of(ops, struct i2c_hid_of_goodix, ops); + int ret; + + ret = regulator_enable(ihid_goodix->vdd); + if (ret) + return ret; + + if (ihid_goodix->timings->post_power_delay_ms) msleep(ihid_goodix->timings->post_power_delay_ms); gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 0); if (ihid_goodix->timings->post_gpio_reset_delay_ms) msleep(ihid_goodix->timings->post_gpio_reset_delay_ms); -} - -static int goodix_i2c_hid_power_up(struct i2chid_ops *ops) -{ - struct i2c_hid_of_goodix *ihid_goodix = - container_of(ops, struct i2c_hid_of_goodix, ops); - return regulator_enable(ihid_goodix->vdd); + return 0; } static void goodix_i2c_hid_power_down(struct i2chid_ops *ops) @@ -55,42 +55,14 @@ static void goodix_i2c_hid_power_down(struct i2chid_ops *ops) struct i2c_hid_of_goodix *ihid_goodix = container_of(ops, struct i2c_hid_of_goodix, ops); + gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1); regulator_disable(ihid_goodix->vdd); } -static int ihid_goodix_vdd_notify(struct notifier_block *nb, - unsigned long event, - void *ignored) -{ - struct i2c_hid_of_goodix *ihid_goodix = - container_of(nb, struct i2c_hid_of_goodix, nb); - int ret = NOTIFY_OK; - - switch (event) { - case REGULATOR_EVENT_PRE_DISABLE: - gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1); - break; - - case REGULATOR_EVENT_ENABLE: - goodix_i2c_hid_deassert_reset(ihid_goodix, true); - break; - - case REGULATOR_EVENT_ABORT_DISABLE: - goodix_i2c_hid_deassert_reset(ihid_goodix, false); - break; - - default: - ret = NOTIFY_DONE; - break; - } - - return ret; -} - static int i2c_hid_of_goodix_probe(struct i2c_client *client) { struct i2c_hid_of_goodix *ihid_goodix; - int ret; + ihid_goodix = devm_kzalloc(&client->dev, sizeof(*ihid_goodix), GFP_KERNEL); if (!ihid_goodix) @@ -111,40 +83,6 @@ static int i2c_hid_of_goodix_probe(struct i2c_client *client) ihid_goodix->timings = device_get_match_data(&client->dev); - /* - * We need to control the "reset" line in lockstep with the regulator - * actually turning on an off instead of just when we make the request. - * This matters if the regulator is shared with another consumer. - * - If the regulator is off then we must assert reset. The reset - * line is active low and on some boards it could cause a current - * leak if left high. - * - If the regulator is on then we don't want reset asserted for very - * long. Holding the controller in reset apparently draws extra - * power. - */ - ihid_goodix->nb.notifier_call = ihid_goodix_vdd_notify; - ret = devm_regulator_register_notifier(ihid_goodix->vdd, &ihid_goodix->nb); - if (ret) - return dev_err_probe(&client->dev, ret, - "regulator notifier request failed\n"); - - /* - * If someone else is holding the regulator on (or the regulator is - * an always-on one) we might never be told to deassert reset. Do it - * now... and temporarily bump the regulator reference count just to - * make sure it is impossible for this to race with our own notifier! - * We also assume that someone else might have _just barely_ turned - * the regulator on so we'll do the full "post_power_delay" just in - * case. - */ - if (ihid_goodix->reset_gpio && regulator_is_enabled(ihid_goodix->vdd)) { - ret = regulator_enable(ihid_goodix->vdd); - if (ret) - return ret; - goodix_i2c_hid_deassert_reset(ihid_goodix, true); - regulator_disable(ihid_goodix->vdd); - } - return i2c_hid_core_probe(client, &ihid_goodix->ops, 0x0001, 0); } -- cgit v1.2.3 From eb16f59e8e584e94d68098da86e70f9c4e54fa86 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Mon, 6 Feb 2023 18:48:15 -0800 Subject: HID: i2c-hid: goodix: Add mainboard-vddio-supply As talked about in the patch ("dt-bindings: HID: i2c-hid: goodix: Add mainboard-vddio-supply") we may need to power up a 1.8V rail on the host associated with touchscreen IO. Let's add support in the driver for it. Signed-off-by: Douglas Anderson Reviewed-by: Dmitry Torokhov Reviewed-by: Matthias Kaehlcke Link: https://lore.kernel.org/r/20230206184744.6.Ic234b931025d1f920ce9e06fff294643943a65ad@changeid Signed-off-by: Benjamin Tissoires --- drivers/hid/i2c-hid/i2c-hid-of-goodix.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/hid/i2c-hid') diff --git a/drivers/hid/i2c-hid/i2c-hid-of-goodix.c b/drivers/hid/i2c-hid/i2c-hid-of-goodix.c index 584d833dc0aa..0060e3dcd775 100644 --- a/drivers/hid/i2c-hid/i2c-hid-of-goodix.c +++ b/drivers/hid/i2c-hid/i2c-hid-of-goodix.c @@ -26,6 +26,7 @@ struct i2c_hid_of_goodix { struct i2chid_ops ops; struct regulator *vdd; + struct regulator *vddio; struct gpio_desc *reset_gpio; const struct goodix_i2c_hid_timing_data *timings; }; @@ -40,6 +41,10 @@ static int goodix_i2c_hid_power_up(struct i2chid_ops *ops) if (ret) return ret; + ret = regulator_enable(ihid_goodix->vddio); + if (ret) + return ret; + if (ihid_goodix->timings->post_power_delay_ms) msleep(ihid_goodix->timings->post_power_delay_ms); @@ -56,6 +61,7 @@ static void goodix_i2c_hid_power_down(struct i2chid_ops *ops) container_of(ops, struct i2c_hid_of_goodix, ops); gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1); + regulator_disable(ihid_goodix->vddio); regulator_disable(ihid_goodix->vdd); } @@ -81,6 +87,10 @@ static int i2c_hid_of_goodix_probe(struct i2c_client *client) if (IS_ERR(ihid_goodix->vdd)) return PTR_ERR(ihid_goodix->vdd); + ihid_goodix->vddio = devm_regulator_get(&client->dev, "mainboard-vddio"); + if (IS_ERR(ihid_goodix->vddio)) + return PTR_ERR(ihid_goodix->vddio); + ihid_goodix->timings = device_get_match_data(&client->dev); return i2c_hid_core_probe(client, &ihid_goodix->ops, 0x0001, 0); -- cgit v1.2.3