in misc/iqs626a.c [1229:1425]
static int iqs626_parse_prop(struct iqs626_private *iqs626)
{
struct iqs626_sys_reg *sys_reg = &iqs626->sys_reg;
struct i2c_client *client = iqs626->client;
struct fwnode_handle *ch_node;
unsigned int val;
int error, i;
u16 general;
if (!device_property_read_u32(&client->dev, "azoteq,suspend-mode",
&val)) {
if (val > IQS626_SYS_SETTINGS_PWR_MODE_MAX) {
dev_err(&client->dev, "Invalid suspend mode: %u\n",
val);
return -EINVAL;
}
iqs626->suspend_mode = val;
}
error = regmap_raw_read(iqs626->regmap, IQS626_SYS_SETTINGS, sys_reg,
sizeof(*sys_reg));
if (error)
return error;
general = be16_to_cpu(sys_reg->general);
general &= IQS626_SYS_SETTINGS_ULP_UPDATE_MASK;
if (device_property_present(&client->dev, "azoteq,clk-div"))
general |= IQS626_SYS_SETTINGS_CLK_DIV;
if (device_property_present(&client->dev, "azoteq,ulp-enable"))
general |= IQS626_SYS_SETTINGS_ULP_AUTO;
if (!device_property_read_u32(&client->dev, "azoteq,ulp-update",
&val)) {
if (val > IQS626_SYS_SETTINGS_ULP_UPDATE_MAX) {
dev_err(&client->dev, "Invalid update rate: %u\n", val);
return -EINVAL;
}
general &= ~IQS626_SYS_SETTINGS_ULP_UPDATE_MASK;
general |= (val << IQS626_SYS_SETTINGS_ULP_UPDATE_SHIFT);
}
sys_reg->misc_a &= ~IQS626_MISC_A_ATI_BAND_DISABLE;
if (device_property_present(&client->dev, "azoteq,ati-band-disable"))
sys_reg->misc_a |= IQS626_MISC_A_ATI_BAND_DISABLE;
sys_reg->misc_a &= ~IQS626_MISC_A_ATI_LP_ONLY;
if (device_property_present(&client->dev, "azoteq,ati-lp-only"))
sys_reg->misc_a |= IQS626_MISC_A_ATI_LP_ONLY;
if (!device_property_read_u32(&client->dev, "azoteq,gpio3-select",
&val)) {
if (val > IQS626_MISC_A_GPIO3_SELECT_MAX) {
dev_err(&client->dev, "Invalid GPIO3 selection: %u\n",
val);
return -EINVAL;
}
sys_reg->misc_a &= ~IQS626_MISC_A_GPIO3_SELECT_MASK;
sys_reg->misc_a |= val;
}
if (!device_property_read_u32(&client->dev, "azoteq,reseed-select",
&val)) {
if (val > IQS626_MISC_B_RESEED_UI_SEL_MAX) {
dev_err(&client->dev, "Invalid reseed selection: %u\n",
val);
return -EINVAL;
}
sys_reg->misc_b &= ~IQS626_MISC_B_RESEED_UI_SEL_MASK;
sys_reg->misc_b |= (val << IQS626_MISC_B_RESEED_UI_SEL_SHIFT);
}
sys_reg->misc_b &= ~IQS626_MISC_B_THRESH_EXTEND;
if (device_property_present(&client->dev, "azoteq,thresh-extend"))
sys_reg->misc_b |= IQS626_MISC_B_THRESH_EXTEND;
sys_reg->misc_b &= ~IQS626_MISC_B_TRACKING_UI_ENABLE;
if (device_property_present(&client->dev, "azoteq,tracking-enable"))
sys_reg->misc_b |= IQS626_MISC_B_TRACKING_UI_ENABLE;
sys_reg->misc_b &= ~IQS626_MISC_B_RESEED_OFFSET;
if (device_property_present(&client->dev, "azoteq,reseed-offset"))
sys_reg->misc_b |= IQS626_MISC_B_RESEED_OFFSET;
if (!device_property_read_u32(&client->dev, "azoteq,rate-np-ms",
&val)) {
if (val > IQS626_RATE_NP_MS_MAX) {
dev_err(&client->dev, "Invalid report rate: %u\n", val);
return -EINVAL;
}
sys_reg->rate_np = val;
}
if (!device_property_read_u32(&client->dev, "azoteq,rate-lp-ms",
&val)) {
if (val > IQS626_RATE_LP_MS_MAX) {
dev_err(&client->dev, "Invalid report rate: %u\n", val);
return -EINVAL;
}
sys_reg->rate_lp = val;
}
if (!device_property_read_u32(&client->dev, "azoteq,rate-ulp-ms",
&val)) {
if (val > IQS626_RATE_ULP_MS_MAX) {
dev_err(&client->dev, "Invalid report rate: %u\n", val);
return -EINVAL;
}
sys_reg->rate_ulp = val / 16;
}
if (!device_property_read_u32(&client->dev, "azoteq,timeout-pwr-ms",
&val)) {
if (val > IQS626_TIMEOUT_PWR_MS_MAX) {
dev_err(&client->dev, "Invalid timeout: %u\n", val);
return -EINVAL;
}
sys_reg->timeout_pwr = val / 512;
}
if (!device_property_read_u32(&client->dev, "azoteq,timeout-lta-ms",
&val)) {
if (val > IQS626_TIMEOUT_LTA_MS_MAX) {
dev_err(&client->dev, "Invalid timeout: %u\n", val);
return -EINVAL;
}
sys_reg->timeout_lta = val / 512;
}
sys_reg->event_mask = ~((u8)IQS626_EVENT_MASK_SYS);
sys_reg->redo_ati = 0;
sys_reg->reseed = 0;
sys_reg->active = 0;
for (i = 0; i < ARRAY_SIZE(iqs626_channels); i++) {
ch_node = device_get_named_child_node(&client->dev,
iqs626_channels[i].name);
if (!ch_node)
continue;
error = iqs626_parse_channel(iqs626, ch_node, i);
if (error)
return error;
error = iqs626_parse_ati_target(iqs626, ch_node, i);
if (error)
return error;
error = iqs626_parse_events(iqs626, ch_node, i);
if (error)
return error;
if (!fwnode_property_present(ch_node, "azoteq,ati-exclude"))
sys_reg->redo_ati |= iqs626_channels[i].active;
if (!fwnode_property_present(ch_node, "azoteq,reseed-disable"))
sys_reg->reseed |= iqs626_channels[i].active;
sys_reg->active |= iqs626_channels[i].active;
}
general |= IQS626_SYS_SETTINGS_EVENT_MODE;
/*
* Enable streaming during normal-power mode if the trackpad is used to
* report raw coordinates instead of gestures. In that case, the device
* returns to event mode during low-power mode.
*/
if (sys_reg->active & iqs626_channels[IQS626_CH_TP_2].active &&
sys_reg->event_mask & IQS626_EVENT_MASK_GESTURE)
general |= IQS626_SYS_SETTINGS_EVENT_MODE_LP;
general |= IQS626_SYS_SETTINGS_REDO_ATI;
general |= IQS626_SYS_SETTINGS_ACK_RESET;
sys_reg->general = cpu_to_be16(general);
error = regmap_raw_write(iqs626->regmap, IQS626_SYS_SETTINGS,
&iqs626->sys_reg, sizeof(iqs626->sys_reg));
if (error)
return error;
iqs626_irq_wait();
return 0;
}