Skip to content

Commit 68bf66a

Browse files
committed
Merge tag 'opp-updates-6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm
Pull OPP updates for 6.2 from Viresh Kumar: "- Several DT fixes and code reorganization around opp-microvolt-<named> DT property (Viresh Kumar). - Allow any of opp-microvolt, opp-microamp, or opp-microwatt properties to be present without the others present (James Calligeros). - Fix clock-latency-ns prop in DT example (Serge Semin)." * tag 'opp-updates-6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm: dt-bindings: opp-v2: Fix clock-latency-ns prop in example OPP: decouple dt properties in opp_parse_supplies() OPP: Simplify opp_parse_supplies() by restructuring it OPP: Parse named opp-microwatt property too dt-bindings: opp: Fix named microwatt property dt-bindings: opp: Fix usage of current in microwatt property
2 parents b7b275e + dba79b7 commit 68bf66a

3 files changed

Lines changed: 103 additions & 133 deletions

File tree

Documentation/devicetree/bindings/opp/opp-v2-base.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ patternProperties:
108108
The power for the OPP in micro-Watts.
109109
110110
Entries for multiple regulators shall be provided in the same field
111-
separated by angular brackets <>. If current values aren't required
111+
separated by angular brackets <>. If power values aren't required
112112
for a regulator, then it shall be filled with 0. If power values
113113
aren't required for any of the regulators, then this field is not
114114
required. The OPP binding doesn't provide any provisions to relate the
@@ -230,9 +230,9 @@ patternProperties:
230230
minItems: 1
231231
maxItems: 8 # Should be enough regulators
232232

233-
'^opp-microwatt':
233+
'^opp-microwatt-':
234234
description:
235-
Named opp-microwatt property. Similar to opp-microamp property,
235+
Named opp-microwatt property. Similar to opp-microamp-<name> property,
236236
but for microwatt instead.
237237
$ref: /schemas/types.yaml#/definitions/uint32-array
238238
minItems: 1

Documentation/devicetree/bindings/opp/opp-v2.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ examples:
155155
opp-hz = /bits/ 64 <1200000000>;
156156
opp-microvolt = <1025000>;
157157
opp-microamp = <90000>;
158-
lock-latency-ns = <290000>;
158+
clock-latency-ns = <290000>;
159159
turbo-mode;
160160
};
161161
};

drivers/opp/of.c

Lines changed: 99 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -578,169 +578,140 @@ 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-
}
601+
if (!prop)
602+
return NULL;
617603
}
618604

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;
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);
625610
}
626611

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;
632-
}
633-
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;
650-
}
651-
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);
634+
kfree(out);
635+
return ERR_PTR(-EINVAL);
658636
}
659637

660-
if (!prop) {
661-
/* Search for "opp-microamp" */
662-
sprintf(name, "opp-microamp");
663-
prop = of_find_property(opp->np, name, NULL);
664-
}
638+
if (triplet)
639+
*triplet = count != opp_table->regulator_count;
665640

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. Check only for the first OPP, as
658+
* regulator_count may get initialized after that to a valid
659+
* value.
660+
*/
661+
if (list_empty(&opp_table->opp_list) &&
662+
opp_table->regulator_count > 0) {
663+
dev_err(dev, "%s: opp-microvolt missing although OPP managing regulators\n",
664+
__func__);
665+
return ERR_PTR(-EINVAL);
695666
}
696667
}
697668

698-
/* Search for "opp-microwatt" */
699-
sprintf(name, "opp-microwatt");
700-
prop = of_find_property(opp->np, name, NULL);
701-
702-
if (prop) {
703-
pcount = of_property_count_u32_elems(opp->np, name);
704-
if (pcount < 0) {
705-
dev_err(dev, "%s: Invalid %s property (%d)\n", __func__,
706-
name, pcount);
707-
ret = pcount;
708-
goto free_microamp;
709-
}
669+
return microvolt;
670+
}
710671

711-
if (pcount != supplies) {
712-
dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
713-
__func__, name, pcount, supplies);
714-
ret = -EINVAL;
715-
goto free_microamp;
716-
}
672+
static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
673+
struct opp_table *opp_table)
674+
{
675+
u32 *microvolt, *microamp, *microwatt;
676+
int ret = 0, i, j;
677+
bool triplet;
717678

718-
microwatt = kmalloc_array(pcount, sizeof(*microwatt),
719-
GFP_KERNEL);
720-
if (!microwatt) {
721-
ret = -EINVAL;
722-
goto free_microamp;
723-
}
679+
microvolt = opp_parse_microvolt(opp, dev, opp_table, &triplet);
680+
if (IS_ERR(microvolt))
681+
return PTR_ERR(microvolt);
724682

725-
ret = of_property_read_u32_array(opp->np, name, microwatt,
726-
pcount);
727-
if (ret) {
728-
dev_err(dev, "%s: error parsing %s: %d\n", __func__,
729-
name, ret);
730-
ret = -EINVAL;
731-
goto free_microwatt;
732-
}
683+
microamp = _parse_named_prop(opp, dev, opp_table, "microamp", NULL);
684+
if (IS_ERR(microamp)) {
685+
ret = PTR_ERR(microamp);
686+
goto free_microvolt;
733687
}
734688

735-
for (i = 0, j = 0; i < supplies; i++) {
736-
opp->supplies[i].u_volt = microvolt[j++];
689+
microwatt = _parse_named_prop(opp, dev, opp_table, "microwatt", NULL);
690+
if (IS_ERR(microwatt)) {
691+
ret = PTR_ERR(microwatt);
692+
goto free_microamp;
693+
}
737694

738-
if (vcount == supplies) {
739-
opp->supplies[i].u_volt_min = opp->supplies[i].u_volt;
740-
opp->supplies[i].u_volt_max = opp->supplies[i].u_volt;
741-
} else {
742-
opp->supplies[i].u_volt_min = microvolt[j++];
743-
opp->supplies[i].u_volt_max = microvolt[j++];
695+
/*
696+
* Initialize regulator_count if it is uninitialized and no properties
697+
* are found.
698+
*/
699+
if (unlikely(opp_table->regulator_count == -1)) {
700+
opp_table->regulator_count = 0;
701+
return 0;
702+
}
703+
704+
for (i = 0, j = 0; i < opp_table->regulator_count; i++) {
705+
if (microvolt) {
706+
opp->supplies[i].u_volt = microvolt[j++];
707+
708+
if (triplet) {
709+
opp->supplies[i].u_volt_min = microvolt[j++];
710+
opp->supplies[i].u_volt_max = microvolt[j++];
711+
} else {
712+
opp->supplies[i].u_volt_min = opp->supplies[i].u_volt;
713+
opp->supplies[i].u_volt_max = opp->supplies[i].u_volt;
714+
}
744715
}
745716

746717
if (microamp)
@@ -750,7 +721,6 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
750721
opp->supplies[i].u_watt = microwatt[i];
751722
}
752723

753-
free_microwatt:
754724
kfree(microwatt);
755725
free_microamp:
756726
kfree(microamp);

0 commit comments

Comments
 (0)