Skip to content

Commit e0e4451

Browse files
committed
Merge branches 'powercap', 'pm-x86', 'pm-opp' and 'pm-misc'
Merge power capping code updates, x86-specific power management pdate, operating performance points library updates and miscellaneous power management updates for 6.2-rc1: - Fix compiler warnings with make W=1 in the idle_inject power capping driver (Srinivas Pandruvada). - Use kstrtobool() instead of strtobool() in the power capping sysfs interface (Christophe JAILLET). - Add SCMI Powercap based power capping driver (Cristian Marussi). - Add Emerald Rapids support to the intel-uncore-freq driver (Artem Bityutskiy). - Repair slips in kernel-doc comments in the generic notifier code (Lukas Bulwahn). - Fix several DT issues in the OPP library reorganize code 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 property in DT example (Serge Semin). * powercap: powercap: idle_inject: Fix warnings with make W=1 powercap: Use kstrtobool() instead of strtobool() powercap: arm_scmi: Add SCMI Powercap based driver * pm-x86: platform/x86: intel-uncore-freq: add Emerald Rapids support * pm-opp: 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 * pm-misc: notifier: repair slips in kernel-doc comments
5 parents 7680d45 + 98e596f + 9c252ec + 68bf66a + f9b4dc9 commit e0e4451

11 files changed

Lines changed: 636 additions & 137 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
};

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20004,6 +20004,7 @@ F: drivers/clk/clk-sc[mp]i.c
2000420004
F: drivers/cpufreq/sc[mp]i-cpufreq.c
2000520005
F: drivers/firmware/arm_scmi/
2000620006
F: drivers/firmware/arm_scpi.c
20007+
F: drivers/powercap/arm_scmi_powercap.c
2000720008
F: drivers/regulator/scmi-regulator.c
2000820009
F: drivers/reset/reset-scmi.c
2000920010
F: include/linux/sc[mp]i_protocol.h

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

drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ static const struct x86_cpu_id intel_uncore_cpu_ids[] = {
203203
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X, NULL),
204204
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D, NULL),
205205
X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X, NULL),
206+
X86_MATCH_INTEL_FAM6_MODEL(EMERALDRAPIDS_X, NULL),
206207
{}
207208
};
208209
MODULE_DEVICE_TABLE(x86cpu, intel_uncore_cpu_ids);

drivers/powercap/Kconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,19 @@ config IDLE_INJECT
4444
synchronously on a set of specified CPUs or alternatively
4545
on a per CPU basis.
4646

47+
config ARM_SCMI_POWERCAP
48+
tristate "ARM SCMI Powercap driver"
49+
depends on ARM_SCMI_PROTOCOL
50+
help
51+
This enables support for the ARM Powercap based on ARM SCMI
52+
Powercap protocol.
53+
54+
ARM SCMI Powercap protocol allows power limits to be enforced
55+
and monitored against the SCMI Powercap domains advertised as
56+
available by the SCMI platform firmware.
57+
58+
When compiled as module it will be called arm_scmi_powercap.ko.
59+
4760
config DTPM
4861
bool "Power capping for Dynamic Thermal Power Management (EXPERIMENTAL)"
4962
depends on OF

drivers/powercap/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ obj-$(CONFIG_POWERCAP) += powercap_sys.o
66
obj-$(CONFIG_INTEL_RAPL_CORE) += intel_rapl_common.o
77
obj-$(CONFIG_INTEL_RAPL) += intel_rapl_msr.o
88
obj-$(CONFIG_IDLE_INJECT) += idle_inject.o
9+
obj-$(CONFIG_ARM_SCMI_POWERCAP) += arm_scmi_powercap.o

0 commit comments

Comments
 (0)