static int iqs626_parse_prop()

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;
}