Skip to content

Commit e5acb19

Browse files
committed
OPP: Simplify opp_parse_supplies() by restructuring it
opp_parse_supplies() has grown into too big of a routine (~190 lines) and it is not straight-forward to understand it anymore. Break it into smaller routines and reduce code redundancy a bit by using the same code to parse properties. This shouldn't result in any logical changes. Tested-by: James Calligeros <jcalligeros99@gmail.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
1 parent 71b0942 commit e5acb19

1 file changed

Lines changed: 81 additions & 135 deletions

File tree

drivers/opp/of.c

Lines changed: 81 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -578,179 +578,126 @@ static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table,
578578
return false;
579579
}
580580

581-
static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
582-
struct opp_table *opp_table)
581+
static u32 *_parse_named_prop(struct dev_pm_opp *opp, struct device *dev,
582+
struct opp_table *opp_table,
583+
const char *prop_type, bool *triplet)
583584
{
584-
u32 *microvolt, *microamp = NULL, *microwatt = NULL;
585-
int supplies = opp_table->regulator_count;
586-
int vcount, icount, pcount, ret, i, j;
587585
struct property *prop = NULL;
588586
char name[NAME_MAX];
587+
int count, ret;
588+
u32 *out;
589589

590-
/* Search for "opp-microvolt-<name>" */
590+
/* Search for "opp-<prop_type>-<name>" */
591591
if (opp_table->prop_name) {
592-
snprintf(name, sizeof(name), "opp-microvolt-%s",
592+
snprintf(name, sizeof(name), "opp-%s-%s", prop_type,
593593
opp_table->prop_name);
594594
prop = of_find_property(opp->np, name, NULL);
595595
}
596596

597597
if (!prop) {
598-
/* Search for "opp-microvolt" */
599-
sprintf(name, "opp-microvolt");
598+
/* Search for "opp-<prop_type>" */
599+
snprintf(name, sizeof(name), "opp-%s", prop_type);
600600
prop = of_find_property(opp->np, name, NULL);
601-
602-
/* Missing property isn't a problem, but an invalid entry is */
603-
if (!prop) {
604-
if (unlikely(supplies == -1)) {
605-
/* Initialize regulator_count */
606-
opp_table->regulator_count = 0;
607-
return 0;
608-
}
609-
610-
if (!supplies)
611-
return 0;
612-
613-
dev_err(dev, "%s: opp-microvolt missing although OPP managing regulators\n",
614-
__func__);
615-
return -EINVAL;
616-
}
617-
}
618-
619-
if (unlikely(supplies == -1)) {
620-
/* Initialize regulator_count */
621-
supplies = opp_table->regulator_count = 1;
622-
} else if (unlikely(!supplies)) {
623-
dev_err(dev, "%s: opp-microvolt wasn't expected\n", __func__);
624-
return -EINVAL;
601+
if (!prop)
602+
return NULL;
625603
}
626604

627-
vcount = of_property_count_u32_elems(opp->np, name);
628-
if (vcount < 0) {
629-
dev_err(dev, "%s: Invalid %s property (%d)\n",
630-
__func__, name, vcount);
631-
return vcount;
605+
count = of_property_count_u32_elems(opp->np, name);
606+
if (count < 0) {
607+
dev_err(dev, "%s: Invalid %s property (%d)\n", __func__, name,
608+
count);
609+
return ERR_PTR(count);
632610
}
633611

634-
/* There can be one or three elements per supply */
635-
if (vcount != supplies && vcount != supplies * 3) {
636-
dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
637-
__func__, name, vcount, supplies);
638-
return -EINVAL;
612+
/*
613+
* Initialize regulator_count, if regulator information isn't provided
614+
* by the platform. Now that one of the properties is available, fix the
615+
* regulator_count to 1.
616+
*/
617+
if (unlikely(opp_table->regulator_count == -1))
618+
opp_table->regulator_count = 1;
619+
620+
if (count != opp_table->regulator_count &&
621+
(!triplet || count != opp_table->regulator_count * 3)) {
622+
dev_err(dev, "%s: Invalid number of elements in %s property (%u) with supplies (%d)\n",
623+
__func__, prop_type, count, opp_table->regulator_count);
624+
return ERR_PTR(-EINVAL);
639625
}
640626

641-
microvolt = kmalloc_array(vcount, sizeof(*microvolt), GFP_KERNEL);
642-
if (!microvolt)
643-
return -ENOMEM;
627+
out = kmalloc_array(count, sizeof(*out), GFP_KERNEL);
628+
if (!out)
629+
return ERR_PTR(-EINVAL);
644630

645-
ret = of_property_read_u32_array(opp->np, name, microvolt, vcount);
631+
ret = of_property_read_u32_array(opp->np, name, out, count);
646632
if (ret) {
647633
dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
648-
ret = -EINVAL;
649-
goto free_microvolt;
634+
kfree(out);
635+
return ERR_PTR(-EINVAL);
650636
}
651637

652-
/* Search for "opp-microamp-<name>" */
653-
prop = NULL;
654-
if (opp_table->prop_name) {
655-
snprintf(name, sizeof(name), "opp-microamp-%s",
656-
opp_table->prop_name);
657-
prop = of_find_property(opp->np, name, NULL);
658-
}
638+
if (triplet)
639+
*triplet = count != opp_table->regulator_count;
659640

660-
if (!prop) {
661-
/* Search for "opp-microamp" */
662-
sprintf(name, "opp-microamp");
663-
prop = of_find_property(opp->np, name, NULL);
664-
}
665-
666-
if (prop) {
667-
icount = of_property_count_u32_elems(opp->np, name);
668-
if (icount < 0) {
669-
dev_err(dev, "%s: Invalid %s property (%d)\n", __func__,
670-
name, icount);
671-
ret = icount;
672-
goto free_microvolt;
673-
}
641+
return out;
642+
}
674643

675-
if (icount != supplies) {
676-
dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
677-
__func__, name, icount, supplies);
678-
ret = -EINVAL;
679-
goto free_microvolt;
680-
}
644+
static u32 *opp_parse_microvolt(struct dev_pm_opp *opp, struct device *dev,
645+
struct opp_table *opp_table, bool *triplet)
646+
{
647+
u32 *microvolt;
681648

682-
microamp = kmalloc_array(icount, sizeof(*microamp), GFP_KERNEL);
683-
if (!microamp) {
684-
ret = -EINVAL;
685-
goto free_microvolt;
686-
}
649+
microvolt = _parse_named_prop(opp, dev, opp_table, "microvolt", triplet);
650+
if (IS_ERR(microvolt))
651+
return microvolt;
687652

688-
ret = of_property_read_u32_array(opp->np, name, microamp,
689-
icount);
690-
if (ret) {
691-
dev_err(dev, "%s: error parsing %s: %d\n", __func__,
692-
name, ret);
693-
ret = -EINVAL;
694-
goto free_microamp;
653+
if (!microvolt) {
654+
/*
655+
* Missing property isn't a problem, but an invalid
656+
* entry is. This property isn't optional if regulator
657+
* information is provided.
658+
*/
659+
if (opp_table->regulator_count > 0) {
660+
dev_err(dev, "%s: opp-microvolt missing although OPP managing regulators\n",
661+
__func__);
662+
return ERR_PTR(-EINVAL);
695663
}
696664
}
697665

698-
/* Search for "opp-microwatt-<name>" */
699-
prop = NULL;
700-
if (opp_table->prop_name) {
701-
snprintf(name, sizeof(name), "opp-microwatt-%s",
702-
opp_table->prop_name);
703-
prop = of_find_property(opp->np, name, NULL);
704-
}
705-
706-
if (!prop) {
707-
/* Search for "opp-microwatt" */
708-
sprintf(name, "opp-microwatt");
709-
prop = of_find_property(opp->np, name, NULL);
710-
}
666+
return microvolt;
667+
}
711668

712-
if (prop) {
713-
pcount = of_property_count_u32_elems(opp->np, name);
714-
if (pcount < 0) {
715-
dev_err(dev, "%s: Invalid %s property (%d)\n", __func__,
716-
name, pcount);
717-
ret = pcount;
718-
goto free_microamp;
719-
}
669+
static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
670+
struct opp_table *opp_table)
671+
{
672+
u32 *microvolt, *microamp, *microwatt;
673+
int ret = 0, i, j;
674+
bool triplet;
720675

721-
if (pcount != supplies) {
722-
dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
723-
__func__, name, pcount, supplies);
724-
ret = -EINVAL;
725-
goto free_microamp;
726-
}
676+
microvolt = opp_parse_microvolt(opp, dev, opp_table, &triplet);
677+
if (IS_ERR_OR_NULL(microvolt))
678+
return PTR_ERR(microvolt);
727679

728-
microwatt = kmalloc_array(pcount, sizeof(*microwatt),
729-
GFP_KERNEL);
730-
if (!microwatt) {
731-
ret = -EINVAL;
732-
goto free_microamp;
733-
}
680+
microamp = _parse_named_prop(opp, dev, opp_table, "microamp", NULL);
681+
if (IS_ERR(microamp)) {
682+
ret = PTR_ERR(microamp);
683+
goto free_microvolt;
684+
}
734685

735-
ret = of_property_read_u32_array(opp->np, name, microwatt,
736-
pcount);
737-
if (ret) {
738-
dev_err(dev, "%s: error parsing %s: %d\n", __func__,
739-
name, ret);
740-
ret = -EINVAL;
741-
goto free_microwatt;
742-
}
686+
microwatt = _parse_named_prop(opp, dev, opp_table, "microwatt", NULL);
687+
if (IS_ERR(microwatt)) {
688+
ret = PTR_ERR(microwatt);
689+
goto free_microamp;
743690
}
744691

745-
for (i = 0, j = 0; i < supplies; i++) {
692+
for (i = 0, j = 0; i < opp_table->regulator_count; i++) {
746693
opp->supplies[i].u_volt = microvolt[j++];
747694

748-
if (vcount == supplies) {
749-
opp->supplies[i].u_volt_min = opp->supplies[i].u_volt;
750-
opp->supplies[i].u_volt_max = opp->supplies[i].u_volt;
751-
} else {
695+
if (triplet) {
752696
opp->supplies[i].u_volt_min = microvolt[j++];
753697
opp->supplies[i].u_volt_max = microvolt[j++];
698+
} else {
699+
opp->supplies[i].u_volt_min = opp->supplies[i].u_volt;
700+
opp->supplies[i].u_volt_max = opp->supplies[i].u_volt;
754701
}
755702

756703
if (microamp)
@@ -760,7 +707,6 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
760707
opp->supplies[i].u_watt = microwatt[i];
761708
}
762709

763-
free_microwatt:
764710
kfree(microwatt);
765711
free_microamp:
766712
kfree(microamp);

0 commit comments

Comments
 (0)