diff mbox series

[4/6] HID: i2c-hid-of: Add chip_data struct

Message ID 20230409144243.25360-5-hdegoede@redhat.com
State New
Headers show
Series HID: i2c-hid-of: Allow using i2c-hid-of on non OF platforms + remove specialized drivers | expand

Commit Message

Hans de Goede April 9, 2023, 2:42 p.m. UTC
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@redhat.com>
---
 drivers/hid/i2c-hid/i2c-hid-of.c | 67 +++++++++++++++++++++++++-------
 1 file changed, 52 insertions(+), 15 deletions(-)
diff mbox series

Patch

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;