diff options
Diffstat (limited to 'drivers/input/misc/iqs7222.c')
-rw-r--r-- | drivers/input/misc/iqs7222.c | 504 |
1 files changed, 301 insertions, 203 deletions
diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c index ddb863bf63ee..e47ab6c1177f 100644 --- a/drivers/input/misc/iqs7222.c +++ b/drivers/input/misc/iqs7222.c @@ -86,7 +86,9 @@ enum iqs7222_reg_key_id { IQS7222_REG_KEY_TOUCH, IQS7222_REG_KEY_DEBOUNCE, IQS7222_REG_KEY_TAP, + IQS7222_REG_KEY_TAP_LEGACY, IQS7222_REG_KEY_AXIAL, + IQS7222_REG_KEY_AXIAL_LEGACY, IQS7222_REG_KEY_WHEEL, IQS7222_REG_KEY_NO_WHEEL, IQS7222_REG_KEY_RESERVED @@ -105,14 +107,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, @@ -202,6 +204,7 @@ struct iqs7222_dev_desc { int allow_offset; int event_offset; int comms_offset; + bool legacy_gesture; struct iqs7222_reg_grp_desc reg_grps[IQS7222_NUM_REG_GRPS]; }; @@ -209,12 +212,70 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { { .prod_num = IQS7222_PROD_NUM_A, .fw_major = 1, + .fw_minor = 13, + .sldr_res = U8_MAX * 16, + .touch_link = 1768, + .allow_offset = 9, + .event_offset = 10, + .comms_offset = 12, + .reg_grps = { + [IQS7222_REG_GRP_STAT] = { + .base = IQS7222_SYS_STATUS, + .num_row = 1, + .num_col = 8, + }, + [IQS7222_REG_GRP_CYCLE] = { + .base = 0x8000, + .num_row = 7, + .num_col = 3, + }, + [IQS7222_REG_GRP_GLBL] = { + .base = 0x8700, + .num_row = 1, + .num_col = 3, + }, + [IQS7222_REG_GRP_BTN] = { + .base = 0x9000, + .num_row = 12, + .num_col = 3, + }, + [IQS7222_REG_GRP_CHAN] = { + .base = 0xA000, + .num_row = 12, + .num_col = 6, + }, + [IQS7222_REG_GRP_FILT] = { + .base = 0xAC00, + .num_row = 1, + .num_col = 2, + }, + [IQS7222_REG_GRP_SLDR] = { + .base = 0xB000, + .num_row = 2, + .num_col = 11, + }, + [IQS7222_REG_GRP_GPIO] = { + .base = 0xC000, + .num_row = 1, + .num_col = 3, + }, + [IQS7222_REG_GRP_SYS] = { + .base = IQS7222_SYS_SETUP, + .num_row = 1, + .num_col = 13, + }, + }, + }, + { + .prod_num = IQS7222_PROD_NUM_A, + .fw_major = 1, .fw_minor = 12, .sldr_res = U8_MAX * 16, .touch_link = 1768, .allow_offset = 9, .event_offset = 10, .comms_offset = 12, + .legacy_gesture = true, .reg_grps = { [IQS7222_REG_GRP_STAT] = { .base = IQS7222_SYS_STATUS, @@ -874,6 +935,16 @@ static const struct iqs7222_prop_desc iqs7222_props[] = { .reg_offset = 9, .reg_shift = 8, .reg_width = 8, + .val_pitch = 16, + .label = "maximum gesture time", + }, + { + .name = "azoteq,gesture-max-ms", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_key = IQS7222_REG_KEY_TAP_LEGACY, + .reg_offset = 9, + .reg_shift = 8, + .reg_width = 8, .val_pitch = 4, .label = "maximum gesture time", }, @@ -884,6 +955,16 @@ static const struct iqs7222_prop_desc iqs7222_props[] = { .reg_offset = 9, .reg_shift = 3, .reg_width = 5, + .val_pitch = 16, + .label = "minimum gesture time", + }, + { + .name = "azoteq,gesture-min-ms", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_key = IQS7222_REG_KEY_TAP_LEGACY, + .reg_offset = 9, + .reg_shift = 3, + .reg_width = 5, .val_pitch = 4, .label = "minimum gesture time", }, @@ -898,12 +979,32 @@ static const struct iqs7222_prop_desc iqs7222_props[] = { .label = "gesture distance", }, { + .name = "azoteq,gesture-dist", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_key = IQS7222_REG_KEY_AXIAL_LEGACY, + .reg_offset = 10, + .reg_shift = 8, + .reg_width = 8, + .val_pitch = 16, + .label = "gesture distance", + }, + { .name = "azoteq,gesture-max-ms", .reg_grp = IQS7222_REG_GRP_SLDR, .reg_key = IQS7222_REG_KEY_AXIAL, .reg_offset = 10, .reg_shift = 0, .reg_width = 8, + .val_pitch = 16, + .label = "maximum gesture time", + }, + { + .name = "azoteq,gesture-max-ms", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_key = IQS7222_REG_KEY_AXIAL_LEGACY, + .reg_offset = 10, + .reg_shift = 0, + .reg_width = 8, .val_pitch = 4, .label = "maximum gesture time", }, @@ -1567,56 +1668,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 +1748,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 +1815,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 +1857,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 +1869,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); @@ -1810,8 +1908,9 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index) 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", @@ -1820,6 +1919,11 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index) } 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; } /* @@ -1892,21 +1996,10 @@ 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)) { + 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. @@ -1919,57 +2012,31 @@ 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; } *setup &= ~(U8_MAX << i * 8); *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); + } 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; } - 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]); + 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; if (!dev_desc->event_offset) continue; @@ -1981,16 +2048,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 +2065,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 @@ -2065,8 +2123,9 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) 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)) { - if (!val || val > dev_desc->sldr_res) { + 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); return -EINVAL; @@ -2079,9 +2138,21 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) 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 (!fwnode_property_read_u32(sldr_node, "azoteq,top-speed", &val)) { + if (!(reg_offset ? sldr_setup[3] + : sldr_setup[2] & IQS7222_SLDR_SETUP_2_RES_MASK)) { + dev_err(&client->dev, "Undefined %s size\n", + fwnode_get_name(sldr_node)); + return -EINVAL; + } + + 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); @@ -2094,9 +2165,14 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) 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) { @@ -2110,6 +2186,10 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) 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) { @@ -2130,46 +2210,47 @@ 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; + /* + * Depending on the device, gestures are either offered using + * one of two timing resolutions, or are not supported at all. + */ + if (reg_offset) + reg_key = IQS7222_REG_KEY_RESERVED; + else if (dev_desc->legacy_gesture && + iqs7222_sl_events[i].reg_key == IQS7222_REG_KEY_TAP) + reg_key = IQS7222_REG_KEY_TAP_LEGACY; + else if (dev_desc->legacy_gesture && + iqs7222_sl_events[i].reg_key == IQS7222_REG_KEY_AXIAL) + reg_key = IQS7222_REG_KEY_AXIAL_LEGACY; + 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; @@ -2190,19 +2271,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; @@ -2210,32 +2335,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; @@ -2258,29 +2364,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) |