Merge branches 'pm-core', 'powercap', 'pm-opp', 'pm-avs' and 'pm-misc'
* pm-core: PM-runtime: add tracepoints for usage_count changes * powercap: powercap/intel_rapl: add support for JasperLake x86/cpu: Add Jasper Lake to Intel family powercap/intel_rapl: add support for TigerLake Mobile * pm-opp: opp: Replace list_kref with a local counter opp: Free static OPPs on errors while adding them * pm-avs: power: avs: qcom-cpr: remove duplicated include from qcom-cpr.c power: avs: fix uninitialized error return on failed cpr_read_fuse_uV() call power: avs: qcom-cpr: make cpr_get_opp_hz_for_req() static power: avs: qcom-cpr: remove set but unused variable power: avs: qcom-cpr: make sure that regmap is available power: avs: qcom-cpr: fix unsigned expression compared with zero power: avs: qcom-cpr: fix invalid printk specifier in debug print power: avs: Add support for CPR (Core Power Reduction) dt-bindings: power: avs: Add support for CPR (Core Power Reduction) * pm-misc: mailmap: Add entry for <rjw@sisk.pl>
This commit is contained in:
commit
c95d9c140c
1
.mailmap
1
.mailmap
|
@ -217,6 +217,7 @@ Praveen BP <praveenbp@ti.com>
|
|||
Punit Agrawal <punitagrawal@gmail.com> <punit.agrawal@arm.com>
|
||||
Qais Yousef <qsyousef@gmail.com> <qais.yousef@imgtec.com>
|
||||
Quentin Perret <qperret@qperret.net> <quentin.perret@arm.com>
|
||||
Rafael J. Wysocki <rjw@rjwysocki.net> <rjw@sisk.pl>
|
||||
Rajesh Shah <rajesh.shah@intel.com>
|
||||
Ralf Baechle <ralf@linux-mips.org>
|
||||
Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
QCOM CPR (Core Power Reduction)
|
||||
|
||||
CPR (Core Power Reduction) is a technology to reduce core power on a CPU
|
||||
or other device. Each OPP of a device corresponds to a "corner" that has
|
||||
a range of valid voltages for a particular frequency. While the device is
|
||||
running at a particular frequency, CPR monitors dynamic factors such as
|
||||
temperature, etc. and suggests adjustments to the voltage to save power
|
||||
and meet silicon characteristic requirements.
|
||||
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: should be "qcom,qcs404-cpr", "qcom,cpr" for qcs404
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: base address and size of the rbcpr register region
|
||||
|
||||
- interrupts:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: should specify the CPR interrupt
|
||||
|
||||
- clocks:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: phandle to the reference clock
|
||||
|
||||
- clock-names:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Definition: must be "ref"
|
||||
|
||||
- vdd-apc-supply:
|
||||
Usage: required
|
||||
Value type: <phandle>
|
||||
Definition: phandle to the vdd-apc-supply regulator
|
||||
|
||||
- #power-domain-cells:
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: should be 0
|
||||
|
||||
- operating-points-v2:
|
||||
Usage: required
|
||||
Value type: <phandle>
|
||||
Definition: A phandle to the OPP table containing the
|
||||
performance states supported by the CPR
|
||||
power domain
|
||||
|
||||
- acc-syscon:
|
||||
Usage: optional
|
||||
Value type: <phandle>
|
||||
Definition: phandle to syscon for writing ACC settings
|
||||
|
||||
- nvmem-cells:
|
||||
Usage: required
|
||||
Value type: <phandle>
|
||||
Definition: phandle to nvmem cells containing the data
|
||||
that makes up a fuse corner, for each fuse corner.
|
||||
As well as the CPR fuse revision.
|
||||
|
||||
- nvmem-cell-names:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Definition: should be "cpr_quotient_offset1", "cpr_quotient_offset2",
|
||||
"cpr_quotient_offset3", "cpr_init_voltage1",
|
||||
"cpr_init_voltage2", "cpr_init_voltage3", "cpr_quotient1",
|
||||
"cpr_quotient2", "cpr_quotient3", "cpr_ring_osc1",
|
||||
"cpr_ring_osc2", "cpr_ring_osc3", "cpr_fuse_revision"
|
||||
for qcs404.
|
||||
|
||||
Example:
|
||||
|
||||
cpr_opp_table: cpr-opp-table {
|
||||
compatible = "operating-points-v2-qcom-level";
|
||||
|
||||
cpr_opp1: opp1 {
|
||||
opp-level = <1>;
|
||||
qcom,opp-fuse-level = <1>;
|
||||
};
|
||||
cpr_opp2: opp2 {
|
||||
opp-level = <2>;
|
||||
qcom,opp-fuse-level = <2>;
|
||||
};
|
||||
cpr_opp3: opp3 {
|
||||
opp-level = <3>;
|
||||
qcom,opp-fuse-level = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
power-controller@b018000 {
|
||||
compatible = "qcom,qcs404-cpr", "qcom,cpr";
|
||||
reg = <0x0b018000 0x1000>;
|
||||
interrupts = <0 15 IRQ_TYPE_EDGE_RISING>;
|
||||
clocks = <&xo_board>;
|
||||
clock-names = "ref";
|
||||
vdd-apc-supply = <&pms405_s3>;
|
||||
#power-domain-cells = <0>;
|
||||
operating-points-v2 = <&cpr_opp_table>;
|
||||
acc-syscon = <&tcsr>;
|
||||
|
||||
nvmem-cells = <&cpr_efuse_quot_offset1>,
|
||||
<&cpr_efuse_quot_offset2>,
|
||||
<&cpr_efuse_quot_offset3>,
|
||||
<&cpr_efuse_init_voltage1>,
|
||||
<&cpr_efuse_init_voltage2>,
|
||||
<&cpr_efuse_init_voltage3>,
|
||||
<&cpr_efuse_quot1>,
|
||||
<&cpr_efuse_quot2>,
|
||||
<&cpr_efuse_quot3>,
|
||||
<&cpr_efuse_ring1>,
|
||||
<&cpr_efuse_ring2>,
|
||||
<&cpr_efuse_ring3>,
|
||||
<&cpr_efuse_revision>;
|
||||
nvmem-cell-names = "cpr_quotient_offset1",
|
||||
"cpr_quotient_offset2",
|
||||
"cpr_quotient_offset3",
|
||||
"cpr_init_voltage1",
|
||||
"cpr_init_voltage2",
|
||||
"cpr_init_voltage3",
|
||||
"cpr_quotient1",
|
||||
"cpr_quotient2",
|
||||
"cpr_quotient3",
|
||||
"cpr_ring_osc1",
|
||||
"cpr_ring_osc2",
|
||||
"cpr_ring_osc3",
|
||||
"cpr_fuse_revision";
|
||||
};
|
|
@ -13671,6 +13671,14 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt
|
||||
F: drivers/cpufreq/qcom-cpufreq-nvmem.c
|
||||
|
||||
QUALCOMM CORE POWER REDUCTION (CPR) AVS DRIVER
|
||||
M: Niklas Cassel <nks@flawful.org>
|
||||
L: linux-pm@vger.kernel.org
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/power/avs/qcom,cpr.txt
|
||||
F: drivers/power/avs/qcom-cpr.c
|
||||
|
||||
QUALCOMM EMAC GIGABIT ETHERNET DRIVER
|
||||
M: Timur Tabi <timur@kernel.org>
|
||||
L: netdev@vger.kernel.org
|
||||
|
|
|
@ -111,6 +111,7 @@
|
|||
|
||||
#define INTEL_FAM6_ATOM_TREMONT_D 0x86 /* Jacobsville */
|
||||
#define INTEL_FAM6_ATOM_TREMONT 0x96 /* Elkhart Lake */
|
||||
#define INTEL_FAM6_ATOM_TREMONT_L 0x9C /* Jasper Lake */
|
||||
|
||||
/* Xeon Phi */
|
||||
|
||||
|
|
|
@ -1006,8 +1006,10 @@ int __pm_runtime_idle(struct device *dev, int rpmflags)
|
|||
int retval;
|
||||
|
||||
if (rpmflags & RPM_GET_PUT) {
|
||||
if (!atomic_dec_and_test(&dev->power.usage_count))
|
||||
if (!atomic_dec_and_test(&dev->power.usage_count)) {
|
||||
trace_rpm_usage_rcuidle(dev, rpmflags);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
|
||||
|
@ -1038,8 +1040,10 @@ int __pm_runtime_suspend(struct device *dev, int rpmflags)
|
|||
int retval;
|
||||
|
||||
if (rpmflags & RPM_GET_PUT) {
|
||||
if (!atomic_dec_and_test(&dev->power.usage_count))
|
||||
if (!atomic_dec_and_test(&dev->power.usage_count)) {
|
||||
trace_rpm_usage_rcuidle(dev, rpmflags);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
|
||||
|
@ -1101,6 +1105,7 @@ int pm_runtime_get_if_in_use(struct device *dev)
|
|||
retval = dev->power.disable_depth > 0 ? -EINVAL :
|
||||
dev->power.runtime_status == RPM_ACTIVE
|
||||
&& atomic_inc_not_zero(&dev->power.usage_count);
|
||||
trace_rpm_usage_rcuidle(dev, 0);
|
||||
spin_unlock_irqrestore(&dev->power.lock, flags);
|
||||
return retval;
|
||||
}
|
||||
|
@ -1434,6 +1439,8 @@ void pm_runtime_allow(struct device *dev)
|
|||
dev->power.runtime_auto = true;
|
||||
if (atomic_dec_and_test(&dev->power.usage_count))
|
||||
rpm_idle(dev, RPM_AUTO | RPM_ASYNC);
|
||||
else
|
||||
trace_rpm_usage_rcuidle(dev, RPM_AUTO | RPM_ASYNC);
|
||||
|
||||
out:
|
||||
spin_unlock_irq(&dev->power.lock);
|
||||
|
@ -1501,6 +1508,8 @@ static void update_autosuspend(struct device *dev, int old_delay, int old_use)
|
|||
if (!old_use || old_delay >= 0) {
|
||||
atomic_inc(&dev->power.usage_count);
|
||||
rpm_resume(dev, 0);
|
||||
} else {
|
||||
trace_rpm_usage_rcuidle(dev, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -988,7 +988,6 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index)
|
|||
BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head);
|
||||
INIT_LIST_HEAD(&opp_table->opp_list);
|
||||
kref_init(&opp_table->kref);
|
||||
kref_init(&opp_table->list_kref);
|
||||
|
||||
/* Secure the device table modification */
|
||||
list_add(&opp_table->node, &opp_tables);
|
||||
|
@ -1072,33 +1071,6 @@ static void _opp_table_kref_release(struct kref *kref)
|
|||
mutex_unlock(&opp_table_lock);
|
||||
}
|
||||
|
||||
void _opp_remove_all_static(struct opp_table *opp_table)
|
||||
{
|
||||
struct dev_pm_opp *opp, *tmp;
|
||||
|
||||
list_for_each_entry_safe(opp, tmp, &opp_table->opp_list, node) {
|
||||
if (!opp->dynamic)
|
||||
dev_pm_opp_put(opp);
|
||||
}
|
||||
|
||||
opp_table->parsed_static_opps = false;
|
||||
}
|
||||
|
||||
static void _opp_table_list_kref_release(struct kref *kref)
|
||||
{
|
||||
struct opp_table *opp_table = container_of(kref, struct opp_table,
|
||||
list_kref);
|
||||
|
||||
_opp_remove_all_static(opp_table);
|
||||
mutex_unlock(&opp_table_lock);
|
||||
}
|
||||
|
||||
void _put_opp_list_kref(struct opp_table *opp_table)
|
||||
{
|
||||
kref_put_mutex(&opp_table->list_kref, _opp_table_list_kref_release,
|
||||
&opp_table_lock);
|
||||
}
|
||||
|
||||
void dev_pm_opp_put_opp_table(struct opp_table *opp_table)
|
||||
{
|
||||
kref_put_mutex(&opp_table->kref, _opp_table_kref_release,
|
||||
|
@ -1202,6 +1174,24 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
|
||||
|
||||
void _opp_remove_all_static(struct opp_table *opp_table)
|
||||
{
|
||||
struct dev_pm_opp *opp, *tmp;
|
||||
|
||||
mutex_lock(&opp_table->lock);
|
||||
|
||||
if (!opp_table->parsed_static_opps || --opp_table->parsed_static_opps)
|
||||
goto unlock;
|
||||
|
||||
list_for_each_entry_safe(opp, tmp, &opp_table->opp_list, node) {
|
||||
if (!opp->dynamic)
|
||||
dev_pm_opp_put_unlocked(opp);
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&opp_table->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* dev_pm_opp_remove_all_dynamic() - Remove all dynamically created OPPs
|
||||
* @dev: device for which we do this operation
|
||||
|
@ -2276,7 +2266,7 @@ void _dev_pm_opp_find_and_remove_table(struct device *dev)
|
|||
return;
|
||||
}
|
||||
|
||||
_put_opp_list_kref(opp_table);
|
||||
_opp_remove_all_static(opp_table);
|
||||
|
||||
/* Drop reference taken by _find_opp_table() */
|
||||
dev_pm_opp_put_opp_table(opp_table);
|
||||
|
|
|
@ -658,17 +658,15 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
|
|||
struct dev_pm_opp *opp;
|
||||
|
||||
/* OPP table is already initialized for the device */
|
||||
mutex_lock(&opp_table->lock);
|
||||
if (opp_table->parsed_static_opps) {
|
||||
kref_get(&opp_table->list_kref);
|
||||
opp_table->parsed_static_opps++;
|
||||
mutex_unlock(&opp_table->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Re-initialize list_kref every time we add static OPPs to the OPP
|
||||
* table as the reference count may be 0 after the last tie static OPPs
|
||||
* were removed.
|
||||
*/
|
||||
kref_init(&opp_table->list_kref);
|
||||
opp_table->parsed_static_opps = 1;
|
||||
mutex_unlock(&opp_table->lock);
|
||||
|
||||
/* We have opp-table node now, iterate over it and add OPPs */
|
||||
for_each_available_child_of_node(opp_table->np, np) {
|
||||
|
@ -678,15 +676,17 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
|
|||
dev_err(dev, "%s: Failed to add OPP, %d\n", __func__,
|
||||
ret);
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
goto remove_static_opp;
|
||||
} else if (opp) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* There should be one of more OPP defined */
|
||||
if (WARN_ON(!count))
|
||||
return -ENOENT;
|
||||
if (WARN_ON(!count)) {
|
||||
ret = -ENOENT;
|
||||
goto remove_static_opp;
|
||||
}
|
||||
|
||||
list_for_each_entry(opp, &opp_table->opp_list, node)
|
||||
pstate_count += !!opp->pstate;
|
||||
|
@ -695,15 +695,19 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
|
|||
if (pstate_count && pstate_count != count) {
|
||||
dev_err(dev, "Not all nodes have performance state set (%d: %d)\n",
|
||||
count, pstate_count);
|
||||
return -ENOENT;
|
||||
ret = -ENOENT;
|
||||
goto remove_static_opp;
|
||||
}
|
||||
|
||||
if (pstate_count)
|
||||
opp_table->genpd_performance_state = true;
|
||||
|
||||
opp_table->parsed_static_opps = true;
|
||||
|
||||
return 0;
|
||||
|
||||
remove_static_opp:
|
||||
_opp_remove_all_static(opp_table);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initializes OPP tables based on old-deprecated bindings */
|
||||
|
@ -738,6 +742,7 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table)
|
|||
if (ret) {
|
||||
dev_err(dev, "%s: Failed to add OPP %ld (%d)\n",
|
||||
__func__, freq, ret);
|
||||
_opp_remove_all_static(opp_table);
|
||||
return ret;
|
||||
}
|
||||
nr -= 2;
|
||||
|
|
|
@ -127,11 +127,10 @@ enum opp_table_access {
|
|||
* @dev_list: list of devices that share these OPPs
|
||||
* @opp_list: table of opps
|
||||
* @kref: for reference count of the table.
|
||||
* @list_kref: for reference count of the OPP list.
|
||||
* @lock: mutex protecting the opp_list and dev_list.
|
||||
* @np: struct device_node pointer for opp's DT node.
|
||||
* @clock_latency_ns_max: Max clock latency in nanoseconds.
|
||||
* @parsed_static_opps: True if OPPs are initialized from DT.
|
||||
* @parsed_static_opps: Count of devices for which OPPs are initialized from DT.
|
||||
* @shared_opp: OPP is shared between multiple devices.
|
||||
* @suspend_opp: Pointer to OPP to be used during device suspend.
|
||||
* @genpd_virt_dev_lock: Mutex protecting the genpd virtual device pointers.
|
||||
|
@ -167,7 +166,6 @@ struct opp_table {
|
|||
struct list_head dev_list;
|
||||
struct list_head opp_list;
|
||||
struct kref kref;
|
||||
struct kref list_kref;
|
||||
struct mutex lock;
|
||||
|
||||
struct device_node *np;
|
||||
|
@ -176,7 +174,7 @@ struct opp_table {
|
|||
/* For backward compatibility with v1 bindings */
|
||||
unsigned int voltage_tolerance_v1;
|
||||
|
||||
bool parsed_static_opps;
|
||||
unsigned int parsed_static_opps;
|
||||
enum opp_table_access shared_opp;
|
||||
struct dev_pm_opp *suspend_opp;
|
||||
|
||||
|
|
|
@ -12,6 +12,22 @@ menuconfig POWER_AVS
|
|||
|
||||
Say Y here to enable Adaptive Voltage Scaling class support.
|
||||
|
||||
config QCOM_CPR
|
||||
tristate "QCOM Core Power Reduction (CPR) support"
|
||||
depends on POWER_AVS
|
||||
select PM_OPP
|
||||
select REGMAP
|
||||
help
|
||||
Say Y here to enable support for the CPR hardware found on Qualcomm
|
||||
SoCs like QCS404.
|
||||
|
||||
This driver populates CPU OPPs tables and makes adjustments to the
|
||||
tables based on feedback from the CPR hardware. If you want to do
|
||||
CPUfrequency scaling say Y here.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will
|
||||
be called qcom-cpr
|
||||
|
||||
config ROCKCHIP_IODOMAIN
|
||||
tristate "Rockchip IO domain support"
|
||||
depends on POWER_AVS && ARCH_ROCKCHIP && OF
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_POWER_AVS_OMAP) += smartreflex.o
|
||||
obj-$(CONFIG_QCOM_CPR) += qcom-cpr.o
|
||||
obj-$(CONFIG_ROCKCHIP_IODOMAIN) += rockchip-io-domain.o
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -980,6 +980,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
|
|||
INTEL_CPU_FAM6(ICELAKE_D, rapl_defaults_hsw_server),
|
||||
INTEL_CPU_FAM6(COMETLAKE_L, rapl_defaults_core),
|
||||
INTEL_CPU_FAM6(COMETLAKE, rapl_defaults_core),
|
||||
INTEL_CPU_FAM6(TIGERLAKE_L, rapl_defaults_core),
|
||||
|
||||
INTEL_CPU_FAM6(ATOM_SILVERMONT, rapl_defaults_byt),
|
||||
INTEL_CPU_FAM6(ATOM_AIRMONT, rapl_defaults_cht),
|
||||
|
@ -989,6 +990,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
|
|||
INTEL_CPU_FAM6(ATOM_GOLDMONT_PLUS, rapl_defaults_core),
|
||||
INTEL_CPU_FAM6(ATOM_GOLDMONT_D, rapl_defaults_core),
|
||||
INTEL_CPU_FAM6(ATOM_TREMONT_D, rapl_defaults_core),
|
||||
INTEL_CPU_FAM6(ATOM_TREMONT_L, rapl_defaults_core),
|
||||
|
||||
INTEL_CPU_FAM6(XEON_PHI_KNL, rapl_defaults_hsw_server),
|
||||
INTEL_CPU_FAM6(XEON_PHI_KNM, rapl_defaults_hsw_server),
|
||||
|
|
|
@ -74,6 +74,12 @@ DEFINE_EVENT(rpm_internal, rpm_idle,
|
|||
|
||||
TP_ARGS(dev, flags)
|
||||
);
|
||||
DEFINE_EVENT(rpm_internal, rpm_usage,
|
||||
|
||||
TP_PROTO(struct device *dev, int flags),
|
||||
|
||||
TP_ARGS(dev, flags)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rpm_return_int,
|
||||
TP_PROTO(struct device *dev, unsigned long ip, int ret),
|
||||
|
|
Loading…
Reference in New Issue