--- /dev/null
+From 0f902d45adc3a36b8ee18e1fecd9331e8086e5cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Oct 2022 19:56:04 -0500
+Subject: Input: iqs7222 - drop unused device node references
+
+From: Jeff LaBundy <jeff@labundy.com>
+
+[ Upstream commit bbd16b0d839978e8c8bec2b9a162373f64fc2fbb ]
+
+Each call to device/fwnode_get_named_child_node() must be matched
+with a call to fwnode_handle_put() once the corresponding node is
+no longer in use. This ensures a reference count remains balanced
+in the case of dynamic device tree support.
+
+Currently, the driver never calls fwnode_handle_put(). Solve this
+problem by moving the node handling from iqs7222_parse_props() to
+the new iqs7222_parse_reg_grp(), leaving the former to do nothing
+but parse properties. The latter then manages the reference count
+in a single location and consistent fashion.
+
+This change drastically simplifies iqs7222_parse_all(), which can
+then call iqs7222_parse_reg_grp() on every register group without
+having to treat each register group differently.
+
+For nested event nodes, common parsing code has been factored out
+to the new iqs7222_parse_event() so as to allow the event node to
+be dropped from as few locations as possible.
+
+As part of this refactor, the 'linux,code' property has been made
+optional. This enables applications that define an event with the
+sole purpose of enabling a GPIO.
+
+Fixes: e505edaedcb9 ("Input: add support for Azoteq IQS7222A/B/C")
+Signed-off-by: Jeff LaBundy <jeff@labundy.com>
+Link: https://lore.kernel.org/r/Y1SRJIQ3WPwNpC0K@nixie71
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/input/misc/iqs7222.c | 340 +++++++++++++++--------------------
+ 1 file changed, 146 insertions(+), 194 deletions(-)
+
+diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c
+index 32515946bbca..1c450ba4fdc3 100644
+--- a/drivers/input/misc/iqs7222.c
++++ b/drivers/input/misc/iqs7222.c
+@@ -105,14 +105,14 @@ enum iqs7222_reg_grp_id {
+ IQS7222_NUM_REG_GRPS
+ };
+
+-static const char * const iqs7222_reg_grp_names[] = {
++static const char * const iqs7222_reg_grp_names[IQS7222_NUM_REG_GRPS] = {
+ [IQS7222_REG_GRP_CYCLE] = "cycle",
+ [IQS7222_REG_GRP_CHAN] = "channel",
+ [IQS7222_REG_GRP_SLDR] = "slider",
+ [IQS7222_REG_GRP_GPIO] = "gpio",
+ };
+
+-static const unsigned int iqs7222_max_cols[] = {
++static const unsigned int iqs7222_max_cols[IQS7222_NUM_REG_GRPS] = {
+ [IQS7222_REG_GRP_STAT] = IQS7222_MAX_COLS_STAT,
+ [IQS7222_REG_GRP_CYCLE] = IQS7222_MAX_COLS_CYCLE,
+ [IQS7222_REG_GRP_GLBL] = IQS7222_MAX_COLS_GLBL,
+@@ -1567,56 +1567,17 @@ static int iqs7222_gpio_select(struct iqs7222_private *iqs7222,
+ }
+
+ static int iqs7222_parse_props(struct iqs7222_private *iqs7222,
+- struct fwnode_handle **child_node,
+- int child_index,
++ struct fwnode_handle *reg_grp_node,
++ int reg_grp_index,
+ enum iqs7222_reg_grp_id reg_grp,
+ enum iqs7222_reg_key_id reg_key)
+ {
+- u16 *setup = iqs7222_setup(iqs7222, reg_grp, child_index);
++ u16 *setup = iqs7222_setup(iqs7222, reg_grp, reg_grp_index);
+ struct i2c_client *client = iqs7222->client;
+- struct fwnode_handle *reg_grp_node;
+- char reg_grp_name[16];
+ int i;
+
+- switch (reg_grp) {
+- case IQS7222_REG_GRP_CYCLE:
+- case IQS7222_REG_GRP_CHAN:
+- case IQS7222_REG_GRP_SLDR:
+- case IQS7222_REG_GRP_GPIO:
+- case IQS7222_REG_GRP_BTN:
+- /*
+- * These groups derive a child node and return it to the caller
+- * for additional group-specific processing. In some cases, the
+- * child node may have already been derived.
+- */
+- reg_grp_node = *child_node;
+- if (reg_grp_node)
+- break;
+-
+- snprintf(reg_grp_name, sizeof(reg_grp_name), "%s-%d",
+- iqs7222_reg_grp_names[reg_grp], child_index);
+-
+- reg_grp_node = device_get_named_child_node(&client->dev,
+- reg_grp_name);
+- if (!reg_grp_node)
+- return 0;
+-
+- *child_node = reg_grp_node;
+- break;
+-
+- case IQS7222_REG_GRP_GLBL:
+- case IQS7222_REG_GRP_FILT:
+- case IQS7222_REG_GRP_SYS:
+- /*
+- * These groups are not organized beneath a child node, nor are
+- * they subject to any additional processing by the caller.
+- */
+- reg_grp_node = dev_fwnode(&client->dev);
+- break;
+-
+- default:
+- return -EINVAL;
+- }
++ if (!setup)
++ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(iqs7222_props); i++) {
+ const char *name = iqs7222_props[i].name;
+@@ -1686,11 +1647,66 @@ static int iqs7222_parse_props(struct iqs7222_private *iqs7222,
+ return 0;
+ }
+
+-static int iqs7222_parse_cycle(struct iqs7222_private *iqs7222, int cycle_index)
++static int iqs7222_parse_event(struct iqs7222_private *iqs7222,
++ struct fwnode_handle *event_node,
++ int reg_grp_index,
++ enum iqs7222_reg_grp_id reg_grp,
++ enum iqs7222_reg_key_id reg_key,
++ u16 event_enable, u16 event_link,
++ unsigned int *event_type,
++ unsigned int *event_code)
++{
++ struct i2c_client *client = iqs7222->client;
++ int error;
++
++ error = iqs7222_parse_props(iqs7222, event_node, reg_grp_index,
++ reg_grp, reg_key);
++ if (error)
++ return error;
++
++ error = iqs7222_gpio_select(iqs7222, event_node, event_enable,
++ event_link);
++ if (error)
++ return error;
++
++ error = fwnode_property_read_u32(event_node, "linux,code", event_code);
++ if (error == -EINVAL) {
++ return 0;
++ } else if (error) {
++ dev_err(&client->dev, "Failed to read %s code: %d\n",
++ fwnode_get_name(event_node), error);
++ return error;
++ }
++
++ if (!event_type) {
++ input_set_capability(iqs7222->keypad, EV_KEY, *event_code);
++ return 0;
++ }
++
++ error = fwnode_property_read_u32(event_node, "linux,input-type",
++ event_type);
++ if (error == -EINVAL) {
++ *event_type = EV_KEY;
++ } else if (error) {
++ dev_err(&client->dev, "Failed to read %s input type: %d\n",
++ fwnode_get_name(event_node), error);
++ return error;
++ } else if (*event_type != EV_KEY && *event_type != EV_SW) {
++ dev_err(&client->dev, "Invalid %s input type: %d\n",
++ fwnode_get_name(event_node), *event_type);
++ return -EINVAL;
++ }
++
++ input_set_capability(iqs7222->keypad, *event_type, *event_code);
++
++ return 0;
++}
++
++static int iqs7222_parse_cycle(struct iqs7222_private *iqs7222,
++ struct fwnode_handle *cycle_node, int cycle_index)
+ {
+ u16 *cycle_setup = iqs7222->cycle_setup[cycle_index];
+ struct i2c_client *client = iqs7222->client;
+- struct fwnode_handle *cycle_node = NULL;
+ unsigned int pins[9];
+ int error, count, i;
+
+@@ -1698,17 +1714,7 @@ static int iqs7222_parse_cycle(struct iqs7222_private *iqs7222, int cycle_index)
+ * Each channel shares a cycle with one other channel; the mapping of
+ * channels to cycles is fixed. Properties defined for a cycle impact
+ * both channels tied to the cycle.
+- */
+- error = iqs7222_parse_props(iqs7222, &cycle_node, cycle_index,
+- IQS7222_REG_GRP_CYCLE,
+- IQS7222_REG_KEY_NONE);
+- if (error)
+- return error;
+-
+- if (!cycle_node)
+- return 0;
+-
+- /*
++ *
+ * Unlike channels which are restricted to a select range of CRx pins
+ * based on channel number, any cycle can claim any of the device's 9
+ * CTx pins (CTx0-8).
+@@ -1750,11 +1756,11 @@ static int iqs7222_parse_cycle(struct iqs7222_private *iqs7222, int cycle_index)
+ return 0;
+ }
+
+-static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
++static int iqs7222_parse_chan(struct iqs7222_private *iqs7222,
++ struct fwnode_handle *chan_node, int chan_index)
+ {
+ const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc;
+ struct i2c_client *client = iqs7222->client;
+- struct fwnode_handle *chan_node = NULL;
+ int num_chan = dev_desc->reg_grps[IQS7222_REG_GRP_CHAN].num_row;
+ int ext_chan = rounddown(num_chan, 10);
+ int error, i;
+@@ -1762,15 +1768,6 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
+ u16 *sys_setup = iqs7222->sys_setup;
+ unsigned int val;
+
+- error = iqs7222_parse_props(iqs7222, &chan_node, chan_index,
+- IQS7222_REG_GRP_CHAN,
+- IQS7222_REG_KEY_NONE);
+- if (error)
+- return error;
+-
+- if (!chan_node)
+- return 0;
+-
+ if (dev_desc->allow_offset &&
+ fwnode_property_present(chan_node, "azoteq,ulp-allow"))
+ sys_setup[dev_desc->allow_offset] &= ~BIT(chan_index);
+@@ -1892,18 +1889,6 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
+ if (!event_node)
+ continue;
+
+- error = iqs7222_parse_props(iqs7222, &event_node, chan_index,
+- IQS7222_REG_GRP_BTN,
+- iqs7222_kp_events[i].reg_key);
+- if (error)
+- return error;
+-
+- error = iqs7222_gpio_select(iqs7222, event_node,
+- BIT(chan_index),
+- dev_desc->touch_link - (i ? 0 : 2));
+- if (error)
+- return error;
+-
+ if (!fwnode_property_read_u32(event_node,
+ "azoteq,timeout-press-ms",
+ &val)) {
+@@ -1919,7 +1904,8 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
+ if (val > U8_MAX * 500) {
+ dev_err(&client->dev,
+ "Invalid %s press timeout: %u\n",
+- fwnode_get_name(chan_node), val);
++ fwnode_get_name(event_node), val);
++ fwnode_handle_put(event_node);
+ return -EINVAL;
+ }
+
+@@ -1927,49 +1913,16 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
+ *setup |= (val / 500 << i * 8);
+ }
+
+- error = fwnode_property_read_u32(event_node, "linux,code",
+- &val);
+- if (error) {
+- dev_err(&client->dev, "Failed to read %s code: %d\n",
+- fwnode_get_name(chan_node), error);
++ error = iqs7222_parse_event(iqs7222, event_node, chan_index,
++ IQS7222_REG_GRP_BTN,
++ iqs7222_kp_events[i].reg_key,
++ BIT(chan_index),
++ dev_desc->touch_link - (i ? 0 : 2),
++ &iqs7222->kp_type[chan_index][i],
++ &iqs7222->kp_code[chan_index][i]);
++ fwnode_handle_put(event_node);
++ if (error)
+ return error;
+- }
+-
+- iqs7222->kp_code[chan_index][i] = val;
+- iqs7222->kp_type[chan_index][i] = EV_KEY;
+-
+- if (fwnode_property_present(event_node, "linux,input-type")) {
+- error = fwnode_property_read_u32(event_node,
+- "linux,input-type",
+- &val);
+- if (error) {
+- dev_err(&client->dev,
+- "Failed to read %s input type: %d\n",
+- fwnode_get_name(chan_node), error);
+- return error;
+- }
+-
+- if (val != EV_KEY && val != EV_SW) {
+- dev_err(&client->dev,
+- "Invalid %s input type: %u\n",
+- fwnode_get_name(chan_node), val);
+- return -EINVAL;
+- }
+-
+- iqs7222->kp_type[chan_index][i] = val;
+- }
+-
+- /*
+- * Reference channels can opt out of event reporting by using
+- * KEY_RESERVED in place of a true key or switch code.
+- */
+- if (iqs7222->kp_type[chan_index][i] == EV_KEY &&
+- iqs7222->kp_code[chan_index][i] == KEY_RESERVED)
+- continue;
+-
+- input_set_capability(iqs7222->keypad,
+- iqs7222->kp_type[chan_index][i],
+- iqs7222->kp_code[chan_index][i]);
+
+ if (!dev_desc->event_offset)
+ continue;
+@@ -1981,16 +1934,16 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
+ * The following call handles a special pair of properties that apply
+ * to a channel node, but reside within the button (event) group.
+ */
+- return iqs7222_parse_props(iqs7222, &chan_node, chan_index,
++ return iqs7222_parse_props(iqs7222, chan_node, chan_index,
+ IQS7222_REG_GRP_BTN,
+ IQS7222_REG_KEY_DEBOUNCE);
+ }
+
+-static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
++static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222,
++ struct fwnode_handle *sldr_node, int sldr_index)
+ {
+ const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc;
+ struct i2c_client *client = iqs7222->client;
+- struct fwnode_handle *sldr_node = NULL;
+ int num_chan = dev_desc->reg_grps[IQS7222_REG_GRP_CHAN].num_row;
+ int ext_chan = rounddown(num_chan, 10);
+ int count, error, reg_offset, i;
+@@ -1998,15 +1951,6 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
+ u16 *sldr_setup = iqs7222->sldr_setup[sldr_index];
+ unsigned int chan_sel[4], val;
+
+- error = iqs7222_parse_props(iqs7222, &sldr_node, sldr_index,
+- IQS7222_REG_GRP_SLDR,
+- IQS7222_REG_KEY_NONE);
+- if (error)
+- return error;
+-
+- if (!sldr_node)
+- return 0;
+-
+ /*
+ * Each slider can be spread across 3 to 4 channels. It is possible to
+ * select only 2 channels, but doing so prevents the slider from using
+@@ -2137,46 +2081,37 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
+ for (i = 0; i < ARRAY_SIZE(iqs7222_sl_events); i++) {
+ const char *event_name = iqs7222_sl_events[i].name;
+ struct fwnode_handle *event_node;
++ enum iqs7222_reg_key_id reg_key;
+
+ event_node = fwnode_get_named_child_node(sldr_node, event_name);
+ if (!event_node)
+ continue;
+
+- error = iqs7222_parse_props(iqs7222, &event_node, sldr_index,
+- IQS7222_REG_GRP_SLDR,
+- reg_offset ?
+- IQS7222_REG_KEY_RESERVED :
+- iqs7222_sl_events[i].reg_key);
+- if (error)
+- return error;
++ if (reg_offset)
++ reg_key = IQS7222_REG_KEY_RESERVED;
++ else
++ reg_key = iqs7222_sl_events[i].reg_key;
+
+ /*
+ * The press/release event does not expose a direct GPIO link,
+ * but one can be emulated by tying each of the participating
+ * channels to the same GPIO.
+ */
+- error = iqs7222_gpio_select(iqs7222, event_node,
++ error = iqs7222_parse_event(iqs7222, event_node, sldr_index,
++ IQS7222_REG_GRP_SLDR, reg_key,
+ i ? iqs7222_sl_events[i].enable
+ : sldr_setup[3 + reg_offset],
+ i ? 1568 + sldr_index * 30
+- : sldr_setup[4 + reg_offset]);
++ : sldr_setup[4 + reg_offset],
++ NULL,
++ &iqs7222->sl_code[sldr_index][i]);
++ fwnode_handle_put(event_node);
+ if (error)
+ return error;
+
+ if (!reg_offset)
+ sldr_setup[9] |= iqs7222_sl_events[i].enable;
+
+- error = fwnode_property_read_u32(event_node, "linux,code",
+- &val);
+- if (error) {
+- dev_err(&client->dev, "Failed to read %s code: %d\n",
+- fwnode_get_name(sldr_node), error);
+- return error;
+- }
+-
+- iqs7222->sl_code[sldr_index][i] = val;
+- input_set_capability(iqs7222->keypad, EV_KEY, val);
+-
+ if (!dev_desc->event_offset)
+ continue;
+
+@@ -2197,19 +2132,63 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
+ * The following call handles a special pair of properties that shift
+ * to make room for a wheel enable control in the case of IQS7222C.
+ */
+- return iqs7222_parse_props(iqs7222, &sldr_node, sldr_index,
++ return iqs7222_parse_props(iqs7222, sldr_node, sldr_index,
+ IQS7222_REG_GRP_SLDR,
+ dev_desc->wheel_enable ?
+ IQS7222_REG_KEY_WHEEL :
+ IQS7222_REG_KEY_NO_WHEEL);
+ }
+
++static int (*iqs7222_parse_extra[IQS7222_NUM_REG_GRPS])
++ (struct iqs7222_private *iqs7222,
++ struct fwnode_handle *reg_grp_node,
++ int reg_grp_index) = {
++ [IQS7222_REG_GRP_CYCLE] = iqs7222_parse_cycle,
++ [IQS7222_REG_GRP_CHAN] = iqs7222_parse_chan,
++ [IQS7222_REG_GRP_SLDR] = iqs7222_parse_sldr,
++};
++
++static int iqs7222_parse_reg_grp(struct iqs7222_private *iqs7222,
++ enum iqs7222_reg_grp_id reg_grp,
++ int reg_grp_index)
++{
++ struct i2c_client *client = iqs7222->client;
++ struct fwnode_handle *reg_grp_node;
++ int error;
++
++ if (iqs7222_reg_grp_names[reg_grp]) {
++ char reg_grp_name[16];
++
++ snprintf(reg_grp_name, sizeof(reg_grp_name), "%s-%d",
++ iqs7222_reg_grp_names[reg_grp], reg_grp_index);
++
++ reg_grp_node = device_get_named_child_node(&client->dev,
++ reg_grp_name);
++ } else {
++ reg_grp_node = fwnode_handle_get(dev_fwnode(&client->dev));
++ }
++
++ if (!reg_grp_node)
++ return 0;
++
++ error = iqs7222_parse_props(iqs7222, reg_grp_node, reg_grp_index,
++ reg_grp, IQS7222_REG_KEY_NONE);
++
++ if (!error && iqs7222_parse_extra[reg_grp])
++ error = iqs7222_parse_extra[reg_grp](iqs7222, reg_grp_node,
++ reg_grp_index);
++
++ fwnode_handle_put(reg_grp_node);
++
++ return error;
++}
++
+ static int iqs7222_parse_all(struct iqs7222_private *iqs7222)
+ {
+ const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc;
+ const struct iqs7222_reg_grp_desc *reg_grps = dev_desc->reg_grps;
+ u16 *sys_setup = iqs7222->sys_setup;
+- int error, i;
++ int error, i, j;
+
+ if (dev_desc->allow_offset)
+ sys_setup[dev_desc->allow_offset] = U16_MAX;
+@@ -2217,32 +2196,13 @@ static int iqs7222_parse_all(struct iqs7222_private *iqs7222)
+ if (dev_desc->event_offset)
+ sys_setup[dev_desc->event_offset] = IQS7222_EVENT_MASK_ATI;
+
+- for (i = 0; i < reg_grps[IQS7222_REG_GRP_CYCLE].num_row; i++) {
+- error = iqs7222_parse_cycle(iqs7222, i);
+- if (error)
+- return error;
+- }
+-
+- error = iqs7222_parse_props(iqs7222, NULL, 0, IQS7222_REG_GRP_GLBL,
+- IQS7222_REG_KEY_NONE);
+- if (error)
+- return error;
+-
+ for (i = 0; i < reg_grps[IQS7222_REG_GRP_GPIO].num_row; i++) {
+- struct fwnode_handle *gpio_node = NULL;
+ u16 *gpio_setup = iqs7222->gpio_setup[i];
+- int j;
+
+ gpio_setup[0] &= ~IQS7222_GPIO_SETUP_0_GPIO_EN;
+ gpio_setup[1] = 0;
+ gpio_setup[2] = 0;
+
+- error = iqs7222_parse_props(iqs7222, &gpio_node, i,
+- IQS7222_REG_GRP_GPIO,
+- IQS7222_REG_KEY_NONE);
+- if (error)
+- return error;
+-
+ if (reg_grps[IQS7222_REG_GRP_GPIO].num_row == 1)
+ continue;
+
+@@ -2265,29 +2225,21 @@ static int iqs7222_parse_all(struct iqs7222_private *iqs7222)
+ chan_setup[5] = 0;
+ }
+
+- for (i = 0; i < reg_grps[IQS7222_REG_GRP_CHAN].num_row; i++) {
+- error = iqs7222_parse_chan(iqs7222, i);
+- if (error)
+- return error;
+- }
+-
+- error = iqs7222_parse_props(iqs7222, NULL, 0, IQS7222_REG_GRP_FILT,
+- IQS7222_REG_KEY_NONE);
+- if (error)
+- return error;
+-
+ for (i = 0; i < reg_grps[IQS7222_REG_GRP_SLDR].num_row; i++) {
+ u16 *sldr_setup = iqs7222->sldr_setup[i];
+
+ sldr_setup[0] &= ~IQS7222_SLDR_SETUP_0_CHAN_CNT_MASK;
++ }
+
+- error = iqs7222_parse_sldr(iqs7222, i);
+- if (error)
+- return error;
++ for (i = 0; i < IQS7222_NUM_REG_GRPS; i++) {
++ for (j = 0; j < reg_grps[i].num_row; j++) {
++ error = iqs7222_parse_reg_grp(iqs7222, i, j);
++ if (error)
++ return error;
++ }
+ }
+
+- return iqs7222_parse_props(iqs7222, NULL, 0, IQS7222_REG_GRP_SYS,
+- IQS7222_REG_KEY_NONE);
++ return 0;
+ }
+
+ static int iqs7222_report(struct iqs7222_private *iqs7222)
+--
+2.35.1
+
--- /dev/null
+From 2a3ecc7b4fb772b8a0e82cdb430f9c4b66c120fb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Oct 2022 19:56:38 -0500
+Subject: Input: iqs7222 - report malformed properties
+
+From: Jeff LaBundy <jeff@labundy.com>
+
+[ Upstream commit 404f3b48e65f058d94429e4a1ec16a1f82ff3b2f ]
+
+Nonzero return values of several calls to fwnode_property_read_u32()
+are silently ignored, leaving no way to know the properties were not
+applied in the event of an error.
+
+Solve this problem by evaluating fwnode_property_read_u32()'s return
+value, and reporting an error for any nonzero return value not equal
+to -EINVAL which indicates the property was absent altogether.
+
+Fixes: e505edaedcb9 ("Input: add support for Azoteq IQS7222A/B/C")
+Signed-off-by: Jeff LaBundy <jeff@labundy.com>
+Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
+Link: https://lore.kernel.org/r/Y1SRRrpQXvkETjfm@nixie71
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/input/misc/iqs7222.c | 44 +++++++++++++++++++++++++++++-------
+ 1 file changed, 36 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c
+index 1c450ba4fdc3..6af25dfd1d2a 100644
+--- a/drivers/input/misc/iqs7222.c
++++ b/drivers/input/misc/iqs7222.c
+@@ -1807,8 +1807,9 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222,
+ chan_setup[0] |= IQS7222_CHAN_SETUP_0_REF_MODE_FOLLOW;
+ chan_setup[4] = val * 42 + 1048;
+
+- if (!fwnode_property_read_u32(chan_node, "azoteq,ref-weight",
+- &val)) {
++ error = fwnode_property_read_u32(chan_node, "azoteq,ref-weight",
++ &val);
++ if (!error) {
+ if (val > U16_MAX) {
+ dev_err(&client->dev,
+ "Invalid %s reference weight: %u\n",
+@@ -1817,6 +1818,11 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222,
+ }
+
+ chan_setup[5] = val;
++ } else if (error != -EINVAL) {
++ dev_err(&client->dev,
++ "Failed to read %s reference weight: %d\n",
++ fwnode_get_name(chan_node), error);
++ return error;
+ }
+
+ /*
+@@ -1889,9 +1895,10 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222,
+ if (!event_node)
+ continue;
+
+- if (!fwnode_property_read_u32(event_node,
+- "azoteq,timeout-press-ms",
+- &val)) {
++ error = fwnode_property_read_u32(event_node,
++ "azoteq,timeout-press-ms",
++ &val);
++ if (!error) {
+ /*
+ * The IQS7222B employs a global pair of press timeout
+ * registers as opposed to channel-specific registers.
+@@ -1911,6 +1918,12 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222,
+
+ *setup &= ~(U8_MAX << i * 8);
+ *setup |= (val / 500 << i * 8);
++ } else if (error != -EINVAL) {
++ dev_err(&client->dev,
++ "Failed to read %s press timeout: %d\n",
++ fwnode_get_name(event_node), error);
++ fwnode_handle_put(event_node);
++ return error;
+ }
+
+ error = iqs7222_parse_event(iqs7222, event_node, chan_index,
+@@ -2009,7 +2022,8 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222,
+ if (fwnode_property_present(sldr_node, "azoteq,use-prox"))
+ sldr_setup[4 + reg_offset] -= 2;
+
+- if (!fwnode_property_read_u32(sldr_node, "azoteq,slider-size", &val)) {
++ error = fwnode_property_read_u32(sldr_node, "azoteq,slider-size", &val);
++ if (!error) {
+ if (val > dev_desc->sldr_res) {
+ dev_err(&client->dev, "Invalid %s size: %u\n",
+ fwnode_get_name(sldr_node), val);
+@@ -2023,6 +2037,10 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222,
+ sldr_setup[2] |= (val / 16 <<
+ IQS7222_SLDR_SETUP_2_RES_SHIFT);
+ }
++ } else if (error != -EINVAL) {
++ dev_err(&client->dev, "Failed to read %s size: %d\n",
++ fwnode_get_name(sldr_node), error);
++ return error;
+ }
+
+ if (!(reg_offset ? sldr_setup[3]
+@@ -2032,7 +2050,8 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222,
+ return -EINVAL;
+ }
+
+- if (!fwnode_property_read_u32(sldr_node, "azoteq,top-speed", &val)) {
++ error = fwnode_property_read_u32(sldr_node, "azoteq,top-speed", &val);
++ if (!error) {
+ if (val > (reg_offset ? U16_MAX : U8_MAX * 4)) {
+ dev_err(&client->dev, "Invalid %s top speed: %u\n",
+ fwnode_get_name(sldr_node), val);
+@@ -2045,9 +2064,14 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222,
+ sldr_setup[2] &= ~IQS7222_SLDR_SETUP_2_TOP_SPEED_MASK;
+ sldr_setup[2] |= (val / 4);
+ }
++ } else if (error != -EINVAL) {
++ dev_err(&client->dev, "Failed to read %s top speed: %d\n",
++ fwnode_get_name(sldr_node), error);
++ return error;
+ }
+
+- if (!fwnode_property_read_u32(sldr_node, "linux,axis", &val)) {
++ error = fwnode_property_read_u32(sldr_node, "linux,axis", &val);
++ if (!error) {
+ u16 sldr_max = sldr_setup[3] - 1;
+
+ if (!reg_offset) {
+@@ -2061,6 +2085,10 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222,
+
+ input_set_abs_params(iqs7222->keypad, val, 0, sldr_max, 0, 0);
+ iqs7222->sl_axis[sldr_index] = val;
++ } else if (error != -EINVAL) {
++ dev_err(&client->dev, "Failed to read %s axis: %d\n",
++ fwnode_get_name(sldr_node), error);
++ return error;
+ }
+
+ if (dev_desc->wheel_enable) {
+--
+2.35.1
+