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)
This commit is contained in:
Benjamin Tissoires 2023-02-22 10:34:51 +01:00
commit 0f7566c7e5
4 changed files with 45 additions and 105 deletions

View File

@ -36,6 +36,13 @@ properties:
vdd-supply:
description: The 3.3V supply to the touchscreen.
mainboard-vddio-supply:
description:
The supply on the main board needed to power up IO signals going
to the touchscreen. This supply need not go to the touchscreen
itself as long as it allows the main board to make signals compatible
with what the touchscreen is expecting for its IO rails.
required:
- compatible
- reg

View File

@ -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);

View File

@ -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;
}

View File

@ -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)
{
if (regulator_just_turned_on && 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);
int ret;
return regulator_enable(ihid_goodix->vdd);
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);
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,42 +87,12 @@ 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);
/*
* 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);
}