summaryrefslogtreecommitdiffstats
path: root/drivers/hid/i2c-hid
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2023-02-22 10:34:51 +0100
committerBenjamin Tissoires <benjamin.tissoires@redhat.com>2023-02-22 10:34:51 +0100
commit0f7566c7e55183b0310e291a94840ba23451322a (patch)
treea68e271e6e1b3ef73110c97b390c0618caefbbdb /drivers/hid/i2c-hid
parentMerge branch 'for-6.3/hid-sensor' into for-linus (diff)
parentHID: i2c-hid: goodix: Add mainboard-vddio-supply (diff)
downloadlinux-0f7566c7e55183b0310e291a94840ba23451322a.tar.xz
linux-0f7566c7e55183b0310e291a94840ba23451322a.zip
Merge branch 'for-6.3/i2c-hid' into for-linus
- dev_dbg cleanup (Thomas Weißschuh) - cleanup i2c-hid-acpi (Andy Shevchenko) - goodix: revert/fixes for an actual production device compared to the manufacturer sample (Douglas Anderson)
Diffstat (limited to 'drivers/hid/i2c-hid')
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-acpi.c26
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-core.c15
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-of-goodix.c98
3 files changed, 36 insertions, 103 deletions
diff --git a/drivers/hid/i2c-hid/i2c-hid-acpi.c b/drivers/hid/i2c-hid/i2c-hid-acpi.c
index 375c77c3db74..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 */
@@ -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,38 +82,31 @@ 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);
}
static const struct acpi_device_id i2c_hid_acpi_match[] = {
- {"ACPI0C50", 0 },
- {"PNP0C50", 0 },
- { },
+ { "ACPI0C50" },
+ { "PNP0C50" },
+ { }
};
MODULE_DEVICE_TABLE(acpi, i2c_hid_acpi_match);
diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index af98ac31c8d4..0ab8f47a84e9 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;
@@ -858,7 +849,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;
@@ -1002,7 +993,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;
}
diff --git a/drivers/hid/i2c-hid/i2c-hid-of-goodix.c b/drivers/hid/i2c-hid/i2c-hid-of-goodix.c
index 29c6cb174032..0060e3dcd775 100644
--- a/drivers/hid/i2c-hid/i2c-hid-of-goodix.c
+++ b/drivers/hid/i2c-hid/i2c-hid-of-goodix.c
@@ -26,28 +26,33 @@ struct i2c_hid_of_goodix {
struct i2chid_ops ops;
struct regulator *vdd;
- struct notifier_block nb;
+ struct regulator *vddio;
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;
+
+ 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);
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 +60,15 @@ 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->vddio);
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)
@@ -109,41 +87,11 @@ 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->timings = device_get_match_data(&client->dev);
+ ihid_goodix->vddio = devm_regulator_get(&client->dev, "mainboard-vddio");
+ if (IS_ERR(ihid_goodix->vddio))
+ return PTR_ERR(ihid_goodix->vddio);
- /*
- * 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);
- }
+ ihid_goodix->timings = device_get_match_data(&client->dev);
return i2c_hid_core_probe(client, &ihid_goodix->ops, 0x0001, 0);
}