Add a chip_data struct which can be used to set different supply-names and default power-on-delay, reset-deassert-delay and hid_descriptor_address values. This is a preparation patch for consolidating the 2 specialized i2c-hid-of-elan.c and i2c-hid-of-goodix.c drivers into the generic i2c-hid-of driver. Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> --- drivers/hid/i2c-hid/i2c-hid-of.c | 67 +++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/drivers/hid/i2c-hid/i2c-hid-of.c b/drivers/hid/i2c-hid/i2c-hid-of.c index d0289afa57dc..4fafef1e36b9 100644 --- a/drivers/hid/i2c-hid/i2c-hid-of.c +++ b/drivers/hid/i2c-hid/i2c-hid-of.c @@ -32,24 +32,44 @@ #include "i2c-hid.h" +#define MAX_BULK_SUPPLIES 2 + +struct i2c_hid_of_chip_data { + const char * const *supply_names; + int num_supplies; + int post_power_delay_ms; + int post_reset_delay_ms; + u16 hid_descriptor_address; +}; + struct i2c_hid_of { struct i2chid_ops ops; struct i2c_client *client; struct gpio_desc *reset_gpio; - struct regulator_bulk_data supplies[2]; + struct regulator_bulk_data supplies[MAX_BULK_SUPPLIES]; + int num_supplies; int post_power_delay_ms; int post_reset_delay_ms; }; +static const char * const i2c_hid_of_default_supply_names[] = { + "vdd", + "vddl", +}; + +static const struct i2c_hid_of_chip_data i2c_hid_of_default_chip_data = { + .supply_names = i2c_hid_of_default_supply_names, + .num_supplies = ARRAY_SIZE(i2c_hid_of_default_supply_names), +}; + static int i2c_hid_of_power_up(struct i2chid_ops *ops) { struct i2c_hid_of *ihid_of = container_of(ops, struct i2c_hid_of, ops); struct device *dev = &ihid_of->client->dev; int ret; - ret = regulator_bulk_enable(ARRAY_SIZE(ihid_of->supplies), - ihid_of->supplies); + ret = regulator_bulk_enable(ihid_of->num_supplies, ihid_of->supplies); if (ret) { dev_warn(dev, "Failed to enable supplies: %d\n", ret); return ret; @@ -70,18 +90,28 @@ static void i2c_hid_of_power_down(struct i2chid_ops *ops) struct i2c_hid_of *ihid_of = container_of(ops, struct i2c_hid_of, ops); gpiod_set_value_cansleep(ihid_of->reset_gpio, 1); - regulator_bulk_disable(ARRAY_SIZE(ihid_of->supplies), - ihid_of->supplies); + regulator_bulk_disable(ihid_of->num_supplies, ihid_of->supplies); } static int i2c_hid_of_probe(struct i2c_client *client) { + const struct i2c_hid_of_chip_data *chip_data; struct device *dev = &client->dev; struct i2c_hid_of *ihid_of; u16 hid_descriptor_address; u32 quirks = 0; int ret; u32 val; + int i; + + chip_data = device_get_match_data(dev); + if (!chip_data) + chip_data = &i2c_hid_of_default_chip_data; + + if (chip_data->num_supplies > MAX_BULK_SUPPLIES) { + dev_err(dev, "Error chip_data->num_supplies > MAX_BULK_SUPPLIES (internal kernel error)\n"); + return -EINVAL; + } ihid_of = devm_kzalloc(dev, sizeof(*ihid_of), GFP_KERNEL); if (!ihid_of) @@ -90,16 +120,22 @@ static int i2c_hid_of_probe(struct i2c_client *client) ihid_of->ops.power_up = i2c_hid_of_power_up; ihid_of->ops.power_down = i2c_hid_of_power_down; + /* chip_data as defaults, allow device-properties to override things */ + ihid_of->post_power_delay_ms = chip_data->post_power_delay_ms; + ihid_of->post_reset_delay_ms = chip_data->post_reset_delay_ms; + hid_descriptor_address = chip_data->hid_descriptor_address; + ret = device_property_read_u32(dev, "hid-descr-addr", &val); - if (ret) { + if (ret == 0) { + if (val >> 16) { + dev_err(dev, "Bad HID register address: 0x%08x\n", val); + return -EINVAL; + } + hid_descriptor_address = val; + } else if (!hid_descriptor_address) { dev_err(dev, "HID register address not provided\n"); return -ENODEV; } - if (val >> 16) { - dev_err(dev, "Bad HID register address: 0x%08x\n", val); - return -EINVAL; - } - hid_descriptor_address = val; if (!device_property_read_u32(dev, "post-power-on-delay-ms", &val)) ihid_of->post_power_delay_ms = val; @@ -112,10 +148,11 @@ static int i2c_hid_of_probe(struct i2c_client *client) if (IS_ERR(ihid_of->reset_gpio)) return PTR_ERR(ihid_of->reset_gpio); - ihid_of->supplies[0].supply = "vdd"; - ihid_of->supplies[1].supply = "vddl"; - ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ihid_of->supplies), - ihid_of->supplies); + ihid_of->num_supplies = chip_data->num_supplies; + for (i = 0; i < ihid_of->num_supplies; i++) + ihid_of->supplies[i].supply = chip_data->supply_names[i]; + + ret = devm_regulator_bulk_get(dev, ihid_of->num_supplies, ihid_of->supplies); if (ret) return ret; -- 2.39.1