summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-10-23 16:27:03 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2020-10-23 16:27:03 -0700
commit41f762a15a6324f67c3f084ece694c26f196cece (patch)
treeaa71ab100fbf1ba2cd0f911ba1cc19d133510ee2 /drivers
parentaf995383eb653f875c4e4e2349d5b0b4ba839eaa (diff)
parent41c169d9ae2c890552044e129d101995b62c8a02 (diff)
downloadlwn-41f762a15a6324f67c3f084ece694c26f196cece.tar.gz
lwn-41f762a15a6324f67c3f084ece694c26f196cece.zip
Merge tag 'pm-5.10-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull more power management updates from Rafael Wysocki: "First of all, the adaptive voltage scaling (AVS) drivers go to new platform-specific locations as planned (this part was reported to have merge conflicts against the new arm-soc updates in linux-next). In addition to that, there are some fixes (intel_idle, intel_pstate, RAPL, acpi_cpufreq), the addition of on/off notifiers and idle state accounting support to the generic power domains (genpd) code and some janitorial changes all over. Specifics: - Move the AVS drivers to new platform-specific locations and get rid of the drivers/power/avs directory (Ulf Hansson). - Add on/off notifiers and idle state accounting support to the generic power domains (genpd) framework (Ulf Hansson, Lina Iyer). - Ulf will maintain the PM domain part of cpuidle-psci (Ulf Hansson). - Make intel_idle disregard ACPI _CST if it cannot use the data returned by that method (Mel Gorman). - Modify intel_pstate to avoid leaving useless sysfs directory structure behind if it cannot be registered (Chen Yu). - Fix domain detection in the RAPL power capping driver and prevent it from failing to enumerate the Psys RAPL domain (Zhang Rui). - Allow acpi-cpufreq to use ACPI _PSD information with Family 19 and later AMD chips (Wei Huang). - Update the driver assumptions comment in intel_idle and fix a kerneldoc comment in the runtime PM framework (Alexander Monakov, Bean Huo). - Avoid unnecessary resets of the cached frequency in the schedutil cpufreq governor to reduce overhead (Wei Wang). - Clean up the cpufreq core a bit (Viresh Kumar). - Make assorted minor janitorial changes (Daniel Lezcano, Geert Uytterhoeven, Hubert Jasudowicz, Tom Rix). - Clean up and optimize the cpupower utility somewhat (Colin Ian King, Martin Kaistra)" * tag 'pm-5.10-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (23 commits) PM: sleep: remove unreachable break PM: AVS: Drop the avs directory and the corresponding Kconfig PM: AVS: qcom-cpr: Move the driver to the qcom specific drivers PM: runtime: Fix typo in pm_runtime_set_active() helper comment PM: domains: Fix build error for genpd notifiers powercap: Fix typo in Kconfig "Plance" -> "Plane" cpufreq: schedutil: restore cached freq when next_f is not changed acpi-cpufreq: Honor _PSD table setting on new AMD CPUs PM: AVS: smartreflex Move driver to soc specific drivers PM: AVS: rockchip-io: Move the driver to the rockchip specific drivers PM: domains: enable domain idle state accounting PM: domains: Add curly braces to delimit comment + statement block PM: domains: Add support for PM domain on/off notifiers for genpd powercap/intel_rapl: enumerate Psys RAPL domain together with package RAPL domain powercap/intel_rapl: Fix domain detection intel_idle: Ignore _CST if control cannot be taken from the platform cpuidle: Remove pointless stub intel_idle: mention assumption that WBINVD is not needed MAINTAINERS: Add section for cpuidle-psci PM domain cpufreq: intel_pstate: Delete intel_pstate sysfs if failed to register the driver ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/power/domain.c167
-rw-r--r--drivers/base/power/main.c1
-rw-r--r--drivers/cpufreq/acpi-cpufreq.c3
-rw-r--r--drivers/cpufreq/cpufreq.c15
-rw-r--r--drivers/cpufreq/intel_pstate.c22
-rw-r--r--drivers/idle/intel_idle.c15
-rw-r--r--drivers/power/Kconfig1
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/avs/Kconfig37
-rw-r--r--drivers/power/avs/Makefile4
-rw-r--r--drivers/powercap/Kconfig2
-rw-r--r--drivers/powercap/intel_rapl_common.c82
-rw-r--r--drivers/powercap/intel_rapl_msr.c5
-rw-r--r--drivers/soc/qcom/Kconfig16
-rw-r--r--drivers/soc/qcom/Makefile1
-rw-r--r--drivers/soc/qcom/cpr.c (renamed from drivers/power/avs/qcom-cpr.c)0
-rw-r--r--drivers/soc/rockchip/Kconfig8
-rw-r--r--drivers/soc/rockchip/Makefile1
-rw-r--r--drivers/soc/rockchip/io-domain.c (renamed from drivers/power/avs/rockchip-io-domain.c)0
-rw-r--r--drivers/soc/ti/Makefile1
-rw-r--r--drivers/soc/ti/smartreflex.c (renamed from drivers/power/avs/smartreflex.c)0
21 files changed, 236 insertions, 146 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 05bb4d4401b2..743268996336 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -415,26 +415,45 @@ static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed)
s64 elapsed_ns;
int ret;
+ /* Notify consumers that we are about to power on. */
+ ret = raw_notifier_call_chain_robust(&genpd->power_notifiers,
+ GENPD_NOTIFY_PRE_ON,
+ GENPD_NOTIFY_OFF, NULL);
+ ret = notifier_to_errno(ret);
+ if (ret)
+ return ret;
+
if (!genpd->power_on)
- return 0;
+ goto out;
- if (!timed)
- return genpd->power_on(genpd);
+ if (!timed) {
+ ret = genpd->power_on(genpd);
+ if (ret)
+ goto err;
+
+ goto out;
+ }
time_start = ktime_get();
ret = genpd->power_on(genpd);
if (ret)
- return ret;
+ goto err;
elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
if (elapsed_ns <= genpd->states[state_idx].power_on_latency_ns)
- return ret;
+ goto out;
genpd->states[state_idx].power_on_latency_ns = elapsed_ns;
genpd->max_off_time_changed = true;
pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n",
genpd->name, "on", elapsed_ns);
+out:
+ raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL);
+ return 0;
+err:
+ raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF,
+ NULL);
return ret;
}
@@ -445,27 +464,46 @@ static int _genpd_power_off(struct generic_pm_domain *genpd, bool timed)
s64 elapsed_ns;
int ret;
+ /* Notify consumers that we are about to power off. */
+ ret = raw_notifier_call_chain_robust(&genpd->power_notifiers,
+ GENPD_NOTIFY_PRE_OFF,
+ GENPD_NOTIFY_ON, NULL);
+ ret = notifier_to_errno(ret);
+ if (ret)
+ return ret;
+
if (!genpd->power_off)
- return 0;
+ goto out;
+
+ if (!timed) {
+ ret = genpd->power_off(genpd);
+ if (ret)
+ goto busy;
- if (!timed)
- return genpd->power_off(genpd);
+ goto out;
+ }
time_start = ktime_get();
ret = genpd->power_off(genpd);
if (ret)
- return ret;
+ goto busy;
elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
if (elapsed_ns <= genpd->states[state_idx].power_off_latency_ns)
- return 0;
+ goto out;
genpd->states[state_idx].power_off_latency_ns = elapsed_ns;
genpd->max_off_time_changed = true;
pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n",
genpd->name, "off", elapsed_ns);
+out:
+ raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF,
+ NULL);
return 0;
+busy:
+ raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL);
+ return ret;
}
/**
@@ -550,11 +588,14 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
return -EBUSY;
ret = _genpd_power_off(genpd, true);
- if (ret)
+ if (ret) {
+ genpd->states[genpd->state_idx].rejected++;
return ret;
+ }
genpd->status = GENPD_STATE_OFF;
genpd_update_accounting(genpd);
+ genpd->states[genpd->state_idx].usage++;
list_for_each_entry(link, &genpd->child_links, child_node) {
genpd_sd_counter_dec(link->parent);
@@ -1270,13 +1311,14 @@ static int genpd_restore_noirq(struct device *dev)
* first time for the given domain in the present cycle.
*/
genpd_lock(genpd);
- if (genpd->suspended_count++ == 0)
+ if (genpd->suspended_count++ == 0) {
/*
* The boot kernel might put the domain into arbitrary state,
* so make it appear as powered off to genpd_sync_power_on(),
* so that it tries to power it on in case it was really off.
*/
genpd->status = GENPD_STATE_OFF;
+ }
genpd_sync_power_on(genpd, true, 0);
genpd_unlock(genpd);
@@ -1592,6 +1634,101 @@ int pm_genpd_remove_device(struct device *dev)
}
EXPORT_SYMBOL_GPL(pm_genpd_remove_device);
+/**
+ * dev_pm_genpd_add_notifier - Add a genpd power on/off notifier for @dev
+ *
+ * @dev: Device that should be associated with the notifier
+ * @nb: The notifier block to register
+ *
+ * Users may call this function to add a genpd power on/off notifier for an
+ * attached @dev. Only one notifier per device is allowed. The notifier is
+ * sent when genpd is powering on/off the PM domain.
+ *
+ * It is assumed that the user guarantee that the genpd wouldn't be detached
+ * while this routine is getting called.
+ *
+ * Returns 0 on success and negative error values on failures.
+ */
+int dev_pm_genpd_add_notifier(struct device *dev, struct notifier_block *nb)
+{
+ struct generic_pm_domain *genpd;
+ struct generic_pm_domain_data *gpd_data;
+ int ret;
+
+ genpd = dev_to_genpd_safe(dev);
+ if (!genpd)
+ return -ENODEV;
+
+ if (WARN_ON(!dev->power.subsys_data ||
+ !dev->power.subsys_data->domain_data))
+ return -EINVAL;
+
+ gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
+ if (gpd_data->power_nb)
+ return -EEXIST;
+
+ genpd_lock(genpd);
+ ret = raw_notifier_chain_register(&genpd->power_notifiers, nb);
+ genpd_unlock(genpd);
+
+ if (ret) {
+ dev_warn(dev, "failed to add notifier for PM domain %s\n",
+ genpd->name);
+ return ret;
+ }
+
+ gpd_data->power_nb = nb;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dev_pm_genpd_add_notifier);
+
+/**
+ * dev_pm_genpd_remove_notifier - Remove a genpd power on/off notifier for @dev
+ *
+ * @dev: Device that is associated with the notifier
+ *
+ * Users may call this function to remove a genpd power on/off notifier for an
+ * attached @dev.
+ *
+ * It is assumed that the user guarantee that the genpd wouldn't be detached
+ * while this routine is getting called.
+ *
+ * Returns 0 on success and negative error values on failures.
+ */
+int dev_pm_genpd_remove_notifier(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+ struct generic_pm_domain_data *gpd_data;
+ int ret;
+
+ genpd = dev_to_genpd_safe(dev);
+ if (!genpd)
+ return -ENODEV;
+
+ if (WARN_ON(!dev->power.subsys_data ||
+ !dev->power.subsys_data->domain_data))
+ return -EINVAL;
+
+ gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
+ if (!gpd_data->power_nb)
+ return -ENODEV;
+
+ genpd_lock(genpd);
+ ret = raw_notifier_chain_unregister(&genpd->power_notifiers,
+ gpd_data->power_nb);
+ genpd_unlock(genpd);
+
+ if (ret) {
+ dev_warn(dev, "failed to remove notifier for PM domain %s\n",
+ genpd->name);
+ return ret;
+ }
+
+ gpd_data->power_nb = NULL;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dev_pm_genpd_remove_notifier);
+
static int genpd_add_subdomain(struct generic_pm_domain *genpd,
struct generic_pm_domain *subdomain)
{
@@ -1762,6 +1899,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
INIT_LIST_HEAD(&genpd->parent_links);
INIT_LIST_HEAD(&genpd->child_links);
INIT_LIST_HEAD(&genpd->dev_list);
+ RAW_INIT_NOTIFIER_HEAD(&genpd->power_notifiers);
genpd_lock_init(genpd);
genpd->gov = gov;
INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
@@ -2923,7 +3061,7 @@ static int idle_states_show(struct seq_file *s, void *data)
if (ret)
return -ERESTARTSYS;
- seq_puts(s, "State Time Spent(ms)\n");
+ seq_puts(s, "State Time Spent(ms) Usage Rejected\n");
for (i = 0; i < genpd->state_count; i++) {
ktime_t delta = 0;
@@ -2935,7 +3073,8 @@ static int idle_states_show(struct seq_file *s, void *data)
msecs = ktime_to_ms(
ktime_add(genpd->states[i].idle_time, delta));
- seq_printf(s, "S%-13i %lld\n", i, msecs);
+ seq_printf(s, "S%-13i %-14lld %-14llu %llu\n", i, msecs,
+ genpd->states[i].usage, genpd->states[i].rejected);
}
genpd_unlock(genpd);
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 205a06752ca9..c7ac49042cee 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -363,7 +363,6 @@ static pm_callback_t pm_op(const struct dev_pm_ops *ops, pm_message_t state)
case PM_EVENT_THAW:
case PM_EVENT_RECOVER:
return ops->thaw;
- break;
case PM_EVENT_RESTORE:
return ops->restore;
#endif /* CONFIG_HIBERNATE_CALLBACKS */
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index e4ff681faaaa..1e4fbb002a31 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -691,7 +691,8 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
cpumask_copy(policy->cpus, topology_core_cpumask(cpu));
}
- if (check_amd_hwpstate_cpu(cpu) && !acpi_pstate_strict) {
+ if (check_amd_hwpstate_cpu(cpu) && boot_cpu_data.x86 < 0x19 &&
+ !acpi_pstate_strict) {
cpumask_clear(policy->cpus);
cpumask_set_cpu(cpu, policy->cpus);
cpumask_copy(data->freqdomain_cpus,
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 1877f5e2e5b0..f4b60663efe6 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1454,14 +1454,13 @@ static int cpufreq_online(unsigned int cpu)
*/
if ((cpufreq_driver->flags & CPUFREQ_NEED_INITIAL_FREQ_CHECK)
&& has_target()) {
+ unsigned int old_freq = policy->cur;
+
/* Are we running at unknown frequency ? */
- ret = cpufreq_frequency_table_get_index(policy, policy->cur);
+ ret = cpufreq_frequency_table_get_index(policy, old_freq);
if (ret == -EINVAL) {
- /* Warn user and fix it */
- pr_warn("%s: CPU%d: Running at unlisted freq: %u KHz\n",
- __func__, policy->cpu, policy->cur);
- ret = __cpufreq_driver_target(policy, policy->cur - 1,
- CPUFREQ_RELATION_L);
+ ret = __cpufreq_driver_target(policy, old_freq - 1,
+ CPUFREQ_RELATION_L);
/*
* Reaching here after boot in a few seconds may not
@@ -1469,8 +1468,8 @@ static int cpufreq_online(unsigned int cpu)
* frequency for longer duration. Hence, a BUG_ON().
*/
BUG_ON(ret);
- pr_warn("%s: CPU%d: Unlisted initial frequency changed to: %u KHz\n",
- __func__, policy->cpu, policy->cur);
+ pr_info("%s: CPU%d: Running at unlisted initial frequency: %u KHz, changing to: %u KHz\n",
+ __func__, policy->cpu, old_freq, policy->cur);
}
}
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 9a515c460a00..3c1455518738 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -1420,6 +1420,24 @@ static void __init intel_pstate_sysfs_expose_params(void)
}
}
+static void __init intel_pstate_sysfs_remove(void)
+{
+ if (!intel_pstate_kobject)
+ return;
+
+ sysfs_remove_group(intel_pstate_kobject, &intel_pstate_attr_group);
+
+ if (!per_cpu_limits) {
+ sysfs_remove_file(intel_pstate_kobject, &max_perf_pct.attr);
+ sysfs_remove_file(intel_pstate_kobject, &min_perf_pct.attr);
+
+ if (x86_match_cpu(intel_pstate_cpu_ee_disable_ids))
+ sysfs_remove_file(intel_pstate_kobject, &energy_efficiency.attr);
+ }
+
+ kobject_put(intel_pstate_kobject);
+}
+
static void intel_pstate_sysfs_expose_hwp_dynamic_boost(void)
{
int rc;
@@ -3063,8 +3081,10 @@ hwp_cpu_matched:
mutex_lock(&intel_pstate_driver_lock);
rc = intel_pstate_register_driver(default_driver);
mutex_unlock(&intel_pstate_driver_lock);
- if (rc)
+ if (rc) {
+ intel_pstate_sysfs_remove();
return rc;
+ }
if (hwp_active) {
const struct x86_cpu_id *id;
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 9a810e4a7946..56f5b8077cba 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -8,7 +8,7 @@
*/
/*
- * intel_idle is a cpuidle driver that loads on specific Intel processors
+ * intel_idle is a cpuidle driver that loads on all Intel CPUs with MWAIT
* in lieu of the legacy ACPI processor_idle driver. The intent is to
* make Linux more efficient on these processors, as intel_idle knows
* more than ACPI, as well as make Linux more immune to ACPI BIOS bugs.
@@ -20,7 +20,11 @@
* All CPUs have same idle states as boot CPU
*
* Chipset BM_STS (bus master status) bit is a NOP
- * for preventing entry into deep C-stats
+ * for preventing entry into deep C-states
+ *
+ * CPU will flush caches as needed when entering a C-state via MWAIT
+ * (in contrast to entering ACPI C3, in which case the WBINVD
+ * instruction needs to be executed to flush the caches)
*/
/*
@@ -1212,14 +1216,13 @@ static bool __init intel_idle_acpi_cst_extract(void)
if (!intel_idle_cst_usable())
continue;
- if (!acpi_processor_claim_cst_control()) {
- acpi_state_table.count = 0;
- return false;
- }
+ if (!acpi_processor_claim_cst_control())
+ break;
return true;
}
+ acpi_state_table.count = 0;
pr_debug("ACPI _CST not found or not usable\n");
return false;
}
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index ff0350ca3b74..696bf77a7042 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -1,4 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
-source "drivers/power/avs/Kconfig"
source "drivers/power/reset/Kconfig"
source "drivers/power/supply/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index b7c2e372186b..effbf0377f32 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -1,4 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_POWER_AVS) += avs/
obj-$(CONFIG_POWER_RESET) += reset/
obj-$(CONFIG_POWER_SUPPLY) += supply/
diff --git a/drivers/power/avs/Kconfig b/drivers/power/avs/Kconfig
deleted file mode 100644
index cdb4237bfd02..000000000000
--- a/drivers/power/avs/Kconfig
+++ /dev/null
@@ -1,37 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-menuconfig POWER_AVS
- bool "Adaptive Voltage Scaling class support"
- help
- AVS is a power management technique which finely controls the
- operating voltage of a device in order to optimize (i.e. reduce)
- its power consumption.
- At a given operating point the voltage is adapted depending on
- static factors (chip manufacturing process) and dynamic factors
- (temperature depending performance).
- AVS is also called SmartReflex on OMAP devices.
-
- Say Y here to enable Adaptive Voltage Scaling class support.
-
-config QCOM_CPR
- tristate "QCOM Core Power Reduction (CPR) support"
- depends on POWER_AVS && HAS_IOMEM
- 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
- help
- Say y here to enable support io domains on Rockchip SoCs. It is
- necessary for the io domain setting of the SoC to match the
- voltage supplied by the regulators.
diff --git a/drivers/power/avs/Makefile b/drivers/power/avs/Makefile
deleted file mode 100644
index 9007d05853e2..000000000000
--- a/drivers/power/avs/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-# 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
diff --git a/drivers/powercap/Kconfig b/drivers/powercap/Kconfig
index ebc4d4578339..bc228725346b 100644
--- a/drivers/powercap/Kconfig
+++ b/drivers/powercap/Kconfig
@@ -30,7 +30,7 @@ config INTEL_RAPL
In RAPL, the platform level settings are divided into domains for
fine grained control. These domains include processor package, DRAM
- controller, CPU core (Power Plance 0), graphics uncore (Power Plane
+ controller, CPU core (Power Plane 0), graphics uncore (Power Plane
1), etc.
config IDLE_INJECT
diff --git a/drivers/powercap/intel_rapl_common.c b/drivers/powercap/intel_rapl_common.c
index 983d75bd5bd1..0b2830efc574 100644
--- a/drivers/powercap/intel_rapl_common.c
+++ b/drivers/powercap/intel_rapl_common.c
@@ -544,7 +544,14 @@ static void rapl_init_domains(struct rapl_package *rp)
continue;
rd->rp = rp;
- rd->name = rapl_domain_names[i];
+
+ if (i == RAPL_DOMAIN_PLATFORM && rp->id > 0) {
+ snprintf(rd->name, RAPL_DOMAIN_NAME_LENGTH, "psys-%d",
+ cpu_data(rp->lead_cpu).phys_proc_id);
+ } else
+ snprintf(rd->name, RAPL_DOMAIN_NAME_LENGTH, "%s",
+ rapl_domain_names[i]);
+
rd->id = i;
rd->rpl[0].prim_id = PL1_ENABLE;
rd->rpl[0].name = pl1_name;
@@ -1112,13 +1119,17 @@ static int rapl_package_register_powercap(struct rapl_package *rp)
}
/* now register domains as children of the socket/package */
for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
+ struct powercap_zone *parent = rp->power_zone;
+
if (rd->id == RAPL_DOMAIN_PACKAGE)
continue;
+ if (rd->id == RAPL_DOMAIN_PLATFORM)
+ parent = NULL;
/* number of power limits per domain varies */
nr_pl = find_nr_power_limit(rd);
power_zone = powercap_register_zone(&rd->power_zone,
rp->priv->control_type,
- rd->name, rp->power_zone,
+ rd->name, parent,
&zone_ops[rd->id], nr_pl,
&constraint_ops);
@@ -1145,67 +1156,6 @@ err_cleanup:
return ret;
}
-int rapl_add_platform_domain(struct rapl_if_priv *priv)
-{
- struct rapl_domain *rd;
- struct powercap_zone *power_zone;
- struct reg_action ra;
- int ret;
-
- ra.reg = priv->regs[RAPL_DOMAIN_PLATFORM][RAPL_DOMAIN_REG_STATUS];
- ra.mask = ~0;
- ret = priv->read_raw(0, &ra);
- if (ret || !ra.value)
- return -ENODEV;
-
- ra.reg = priv->regs[RAPL_DOMAIN_PLATFORM][RAPL_DOMAIN_REG_LIMIT];
- ra.mask = ~0;
- ret = priv->read_raw(0, &ra);
- if (ret || !ra.value)
- return -ENODEV;
-
- rd = kzalloc(sizeof(*rd), GFP_KERNEL);
- if (!rd)
- return -ENOMEM;
-
- rd->name = rapl_domain_names[RAPL_DOMAIN_PLATFORM];
- rd->id = RAPL_DOMAIN_PLATFORM;
- rd->regs[RAPL_DOMAIN_REG_LIMIT] =
- priv->regs[RAPL_DOMAIN_PLATFORM][RAPL_DOMAIN_REG_LIMIT];
- rd->regs[RAPL_DOMAIN_REG_STATUS] =
- priv->regs[RAPL_DOMAIN_PLATFORM][RAPL_DOMAIN_REG_STATUS];
- rd->rpl[0].prim_id = PL1_ENABLE;
- rd->rpl[0].name = pl1_name;
- rd->rpl[1].prim_id = PL2_ENABLE;
- rd->rpl[1].name = pl2_name;
- rd->rp = rapl_find_package_domain(0, priv);
-
- power_zone = powercap_register_zone(&rd->power_zone, priv->control_type,
- "psys", NULL,
- &zone_ops[RAPL_DOMAIN_PLATFORM],
- 2, &constraint_ops);
-
- if (IS_ERR(power_zone)) {
- kfree(rd);
- return PTR_ERR(power_zone);
- }
-
- priv->platform_rapl_domain = rd;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rapl_add_platform_domain);
-
-void rapl_remove_platform_domain(struct rapl_if_priv *priv)
-{
- if (priv->platform_rapl_domain) {
- powercap_unregister_zone(priv->control_type,
- &priv->platform_rapl_domain->power_zone);
- kfree(priv->platform_rapl_domain);
- }
-}
-EXPORT_SYMBOL_GPL(rapl_remove_platform_domain);
-
static int rapl_check_domain(int cpu, int domain, struct rapl_package *rp)
{
struct reg_action ra;
@@ -1215,11 +1165,9 @@ static int rapl_check_domain(int cpu, int domain, struct rapl_package *rp)
case RAPL_DOMAIN_PP0:
case RAPL_DOMAIN_PP1:
case RAPL_DOMAIN_DRAM:
+ case RAPL_DOMAIN_PLATFORM:
ra.reg = rp->priv->regs[domain][RAPL_DOMAIN_REG_STATUS];
break;
- case RAPL_DOMAIN_PLATFORM:
- /* PSYS(PLATFORM) is not a CPU domain, so avoid printng error */
- return -EINVAL;
default:
pr_err("invalid domain id %d\n", domain);
return -EINVAL;
@@ -1228,7 +1176,7 @@ static int rapl_check_domain(int cpu, int domain, struct rapl_package *rp)
* values, otherwise skip it.
*/
- ra.mask = ~0;
+ ra.mask = ENERGY_STATUS_MASK;
if (rp->priv->read_raw(cpu, &ra) || !ra.value)
return -ENODEV;
diff --git a/drivers/powercap/intel_rapl_msr.c b/drivers/powercap/intel_rapl_msr.c
index d2a2627507a9..1646808d354c 100644
--- a/drivers/powercap/intel_rapl_msr.c
+++ b/drivers/powercap/intel_rapl_msr.c
@@ -44,6 +44,7 @@ static struct rapl_if_priv rapl_msr_priv = {
.regs[RAPL_DOMAIN_PLATFORM] = {
MSR_PLATFORM_POWER_LIMIT, MSR_PLATFORM_ENERGY_STATUS, 0, 0, 0},
.limits[RAPL_DOMAIN_PACKAGE] = 2,
+ .limits[RAPL_DOMAIN_PLATFORM] = 2,
};
/* Handles CPU hotplug on multi-socket systems.
@@ -157,9 +158,6 @@ static int rapl_msr_probe(struct platform_device *pdev)
goto out;
rapl_msr_priv.pcap_rapl_online = ret;
- /* Don't bail out if PSys is not supported */
- rapl_add_platform_domain(&rapl_msr_priv);
-
return 0;
out:
@@ -171,7 +169,6 @@ out:
static int rapl_msr_remove(struct platform_device *pdev)
{
cpuhp_remove_state(rapl_msr_priv.pcap_rapl_online);
- rapl_remove_platform_domain(&rapl_msr_priv);
powercap_unregister_control_type(rapl_msr_priv.control_type);
return 0;
}
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 3dc3e3d61ea3..6a3b69b43ad5 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -26,6 +26,22 @@ config QCOM_COMMAND_DB
resource on a RPM-hardened platform must use this database to get
SoC specific identifier and information for the shared resources.
+config QCOM_CPR
+ tristate "QCOM Core Power Reduction (CPR) support"
+ depends on ARCH_QCOM && HAS_IOMEM
+ 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 QCOM_GENI_SE
tristate "QCOM GENI Serial Engine Driver"
depends on ARCH_QCOM || COMPILE_TEST
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 93392d9dc7f7..ad675a6593d0 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -3,6 +3,7 @@ CFLAGS_rpmh-rsc.o := -I$(src)
obj-$(CONFIG_QCOM_AOSS_QMP) += qcom_aoss.o
obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o
obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+obj-$(CONFIG_QCOM_CPR) += cpr.o
obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
diff --git a/drivers/power/avs/qcom-cpr.c b/drivers/soc/qcom/cpr.c
index b24cc77d1889..b24cc77d1889 100644
--- a/drivers/power/avs/qcom-cpr.c
+++ b/drivers/soc/qcom/cpr.c
diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig
index b71b73bf5fc5..2c13bf4dd5db 100644
--- a/drivers/soc/rockchip/Kconfig
+++ b/drivers/soc/rockchip/Kconfig
@@ -14,6 +14,14 @@ config ROCKCHIP_GRF
In a lot of cases there also need to be default settings initialized
to make some of them conform to expectations of the kernel.
+config ROCKCHIP_IODOMAIN
+ tristate "Rockchip IO domain support"
+ depends on OF
+ help
+ Say y here to enable support io domains on Rockchip SoCs. It is
+ necessary for the io domain setting of the SoC to match the
+ voltage supplied by the regulators.
+
config ROCKCHIP_PM_DOMAINS
bool "Rockchip generic power domain"
depends on PM
diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile
index afca0a4c4b72..875032f7344e 100644
--- a/drivers/soc/rockchip/Makefile
+++ b/drivers/soc/rockchip/Makefile
@@ -3,4 +3,5 @@
# Rockchip Soc drivers
#
obj-$(CONFIG_ROCKCHIP_GRF) += grf.o
+obj-$(CONFIG_ROCKCHIP_IODOMAIN) += io-domain.o
obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o
diff --git a/drivers/power/avs/rockchip-io-domain.c b/drivers/soc/rockchip/io-domain.c
index eece97f97ef8..eece97f97ef8 100644
--- a/drivers/power/avs/rockchip-io-domain.c
+++ b/drivers/soc/rockchip/io-domain.c
diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile
index 1110e5c98685..5463431ec96c 100644
--- a/drivers/soc/ti/Makefile
+++ b/drivers/soc/ti/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o
obj-$(CONFIG_TI_SCI_INTA_MSI_DOMAIN) += ti_sci_inta_msi.o
obj-$(CONFIG_TI_K3_RINGACC) += k3-ringacc.o
obj-$(CONFIG_TI_K3_SOCINFO) += k3-socinfo.o
+obj-$(CONFIG_POWER_AVS_OMAP) += smartreflex.o
diff --git a/drivers/power/avs/smartreflex.c b/drivers/soc/ti/smartreflex.c
index 5376f3d22f31..5376f3d22f31 100644
--- a/drivers/power/avs/smartreflex.c
+++ b/drivers/soc/ti/smartreflex.c