static int opp_parse_supplies()

in of.c [575:712]


static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
			      struct opp_table *opp_table)
{
	u32 *microvolt, *microamp = NULL;
	int supplies = opp_table->regulator_count, vcount, icount, ret, i, j;
	struct property *prop = NULL;
	char name[NAME_MAX];

	/* Search for "opp-microvolt-<name>" */
	if (opp_table->prop_name) {
		snprintf(name, sizeof(name), "opp-microvolt-%s",
			 opp_table->prop_name);
		prop = of_find_property(opp->np, name, NULL);
	}

	if (!prop) {
		/* Search for "opp-microvolt" */
		sprintf(name, "opp-microvolt");
		prop = of_find_property(opp->np, name, NULL);

		/* Missing property isn't a problem, but an invalid entry is */
		if (!prop) {
			if (unlikely(supplies == -1)) {
				/* Initialize regulator_count */
				opp_table->regulator_count = 0;
				return 0;
			}

			if (!supplies)
				return 0;

			dev_err(dev, "%s: opp-microvolt missing although OPP managing regulators\n",
				__func__);
			return -EINVAL;
		}
	}

	if (unlikely(supplies == -1)) {
		/* Initialize regulator_count */
		supplies = opp_table->regulator_count = 1;
	} else if (unlikely(!supplies)) {
		dev_err(dev, "%s: opp-microvolt wasn't expected\n", __func__);
		return -EINVAL;
	}

	vcount = of_property_count_u32_elems(opp->np, name);
	if (vcount < 0) {
		dev_err(dev, "%s: Invalid %s property (%d)\n",
			__func__, name, vcount);
		return vcount;
	}

	/* There can be one or three elements per supply */
	if (vcount != supplies && vcount != supplies * 3) {
		dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
			__func__, name, vcount, supplies);
		return -EINVAL;
	}

	microvolt = kmalloc_array(vcount, sizeof(*microvolt), GFP_KERNEL);
	if (!microvolt)
		return -ENOMEM;

	ret = of_property_read_u32_array(opp->np, name, microvolt, vcount);
	if (ret) {
		dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
		ret = -EINVAL;
		goto free_microvolt;
	}

	/* Search for "opp-microamp-<name>" */
	prop = NULL;
	if (opp_table->prop_name) {
		snprintf(name, sizeof(name), "opp-microamp-%s",
			 opp_table->prop_name);
		prop = of_find_property(opp->np, name, NULL);
	}

	if (!prop) {
		/* Search for "opp-microamp" */
		sprintf(name, "opp-microamp");
		prop = of_find_property(opp->np, name, NULL);
	}

	if (prop) {
		icount = of_property_count_u32_elems(opp->np, name);
		if (icount < 0) {
			dev_err(dev, "%s: Invalid %s property (%d)\n", __func__,
				name, icount);
			ret = icount;
			goto free_microvolt;
		}

		if (icount != supplies) {
			dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
				__func__, name, icount, supplies);
			ret = -EINVAL;
			goto free_microvolt;
		}

		microamp = kmalloc_array(icount, sizeof(*microamp), GFP_KERNEL);
		if (!microamp) {
			ret = -EINVAL;
			goto free_microvolt;
		}

		ret = of_property_read_u32_array(opp->np, name, microamp,
						 icount);
		if (ret) {
			dev_err(dev, "%s: error parsing %s: %d\n", __func__,
				name, ret);
			ret = -EINVAL;
			goto free_microamp;
		}
	}

	for (i = 0, j = 0; i < supplies; i++) {
		opp->supplies[i].u_volt = microvolt[j++];

		if (vcount == supplies) {
			opp->supplies[i].u_volt_min = opp->supplies[i].u_volt;
			opp->supplies[i].u_volt_max = opp->supplies[i].u_volt;
		} else {
			opp->supplies[i].u_volt_min = microvolt[j++];
			opp->supplies[i].u_volt_max = microvolt[j++];
		}

		if (microamp)
			opp->supplies[i].u_amp = microamp[i];
	}

free_microamp:
	kfree(microamp);
free_microvolt:
	kfree(microvolt);

	return ret;
}