Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a465d38f authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branches 'pm-devfreq', 'pm-avs' and 'pm-tools'

* pm-devfreq:
  PM / devfreq: add devfreq_suspend/resume() functions
  PM / devfreq: add support for suspend/resume of a devfreq device
  PM / devfreq: refactor set_target frequency function

* pm-avs:
  PM / AVS: SmartReflex: Switch to SPDX Licence ID
  PM / AVS: SmartReflex: NULL check before some freeing functions is not needed
  PM / AVS: SmartReflex: remove unused function

* pm-tools:
  tools/power/x86/intel_pstate_tracer: Fix non root execution for post processing a trace file
  tools/power turbostat: consolidate duplicate model numbers
  tools/power turbostat: fix goldmont C-state limit decoding
  cpupower : Auto-completion for cpupower tool
  tools/power turbostat: reduce debug output
  tools/power turbosat: fix AMD APIC-id output
Loading
Loading
Loading
Loading
+121 −32
Original line number Diff line number Diff line
@@ -285,6 +285,44 @@ static int devfreq_notify_transition(struct devfreq *devfreq,
	return 0;
}

static int devfreq_set_target(struct devfreq *devfreq, unsigned long new_freq,
			      u32 flags)
{
	struct devfreq_freqs freqs;
	unsigned long cur_freq;
	int err = 0;

	if (devfreq->profile->get_cur_freq)
		devfreq->profile->get_cur_freq(devfreq->dev.parent, &cur_freq);
	else
		cur_freq = devfreq->previous_freq;

	freqs.old = cur_freq;
	freqs.new = new_freq;
	devfreq_notify_transition(devfreq, &freqs, DEVFREQ_PRECHANGE);

	err = devfreq->profile->target(devfreq->dev.parent, &new_freq, flags);
	if (err) {
		freqs.new = cur_freq;
		devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
		return err;
	}

	freqs.new = new_freq;
	devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);

	if (devfreq_update_status(devfreq, new_freq))
		dev_err(&devfreq->dev,
			"Couldn't update frequency transition information.\n");

	devfreq->previous_freq = new_freq;

	if (devfreq->suspend_freq)
		devfreq->resume_freq = cur_freq;

	return err;
}

/* Load monitoring helper functions for governors use */

/**
@@ -296,8 +334,7 @@ static int devfreq_notify_transition(struct devfreq *devfreq,
 */
int update_devfreq(struct devfreq *devfreq)
{
	struct devfreq_freqs freqs;
	unsigned long freq, cur_freq, min_freq, max_freq;
	unsigned long freq, min_freq, max_freq;
	int err = 0;
	u32 flags = 0;

@@ -333,31 +370,8 @@ int update_devfreq(struct devfreq *devfreq)
		flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */
	}

	if (devfreq->profile->get_cur_freq)
		devfreq->profile->get_cur_freq(devfreq->dev.parent, &cur_freq);
	else
		cur_freq = devfreq->previous_freq;

	freqs.old = cur_freq;
	freqs.new = freq;
	devfreq_notify_transition(devfreq, &freqs, DEVFREQ_PRECHANGE);
	return devfreq_set_target(devfreq, freq, flags);

	err = devfreq->profile->target(devfreq->dev.parent, &freq, flags);
	if (err) {
		freqs.new = cur_freq;
		devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
		return err;
	}

	freqs.new = freq;
	devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);

	if (devfreq_update_status(devfreq, freq))
		dev_err(&devfreq->dev,
			"Couldn't update frequency transition information.\n");

	devfreq->previous_freq = freq;
	return err;
}
EXPORT_SYMBOL(update_devfreq);

@@ -657,6 +671,9 @@ struct devfreq *devfreq_add_device(struct device *dev,
	}
	devfreq->max_freq = devfreq->scaling_max_freq;

	devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
	atomic_set(&devfreq->suspend_count, 0);

	dev_set_name(&devfreq->dev, "devfreq%d",
				atomic_inc_return(&devfreq_no));
	err = device_register(&devfreq->dev);
@@ -857,14 +874,28 @@ EXPORT_SYMBOL(devm_devfreq_remove_device);
 */
int devfreq_suspend_device(struct devfreq *devfreq)
{
	int ret;

	if (!devfreq)
		return -EINVAL;

	if (!devfreq->governor)
	if (atomic_inc_return(&devfreq->suspend_count) > 1)
		return 0;

	return devfreq->governor->event_handler(devfreq,
	if (devfreq->governor) {
		ret = devfreq->governor->event_handler(devfreq,
					DEVFREQ_GOV_SUSPEND, NULL);
		if (ret)
			return ret;
	}

	if (devfreq->suspend_freq) {
		ret = devfreq_set_target(devfreq, devfreq->suspend_freq, 0);
		if (ret)
			return ret;
	}

	return 0;
}
EXPORT_SYMBOL(devfreq_suspend_device);

@@ -878,17 +909,75 @@ EXPORT_SYMBOL(devfreq_suspend_device);
 */
int devfreq_resume_device(struct devfreq *devfreq)
{
	int ret;

	if (!devfreq)
		return -EINVAL;

	if (!devfreq->governor)
	if (atomic_dec_return(&devfreq->suspend_count) >= 1)
		return 0;

	return devfreq->governor->event_handler(devfreq,
	if (devfreq->resume_freq) {
		ret = devfreq_set_target(devfreq, devfreq->resume_freq, 0);
		if (ret)
			return ret;
	}

	if (devfreq->governor) {
		ret = devfreq->governor->event_handler(devfreq,
					DEVFREQ_GOV_RESUME, NULL);
		if (ret)
			return ret;
	}

	return 0;
}
EXPORT_SYMBOL(devfreq_resume_device);

/**
 * devfreq_suspend() - Suspend devfreq governors and devices
 *
 * Called during system wide Suspend/Hibernate cycles for suspending governors
 * and devices preserving the state for resume. On some platforms the devfreq
 * device must have precise state (frequency) after resume in order to provide
 * fully operating setup.
 */
void devfreq_suspend(void)
{
	struct devfreq *devfreq;
	int ret;

	mutex_lock(&devfreq_list_lock);
	list_for_each_entry(devfreq, &devfreq_list, node) {
		ret = devfreq_suspend_device(devfreq);
		if (ret)
			dev_err(&devfreq->dev,
				"failed to suspend devfreq device\n");
	}
	mutex_unlock(&devfreq_list_lock);
}

/**
 * devfreq_resume() - Resume devfreq governors and devices
 *
 * Called during system wide Suspend/Hibernate cycle for resuming governors and
 * devices that are suspended with devfreq_suspend().
 */
void devfreq_resume(void)
{
	struct devfreq *devfreq;
	int ret;

	mutex_lock(&devfreq_list_lock);
	list_for_each_entry(devfreq, &devfreq_list, node) {
		ret = devfreq_resume_device(devfreq);
		if (ret)
			dev_warn(&devfreq->dev,
				 "failed to resume devfreq device\n");
	}
	mutex_unlock(&devfreq_list_lock);
}

/**
 * devfreq_add_governor() - Add devfreq governor
 * @governor:	the devfreq governor to be added
+2 −37
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * OMAP SmartReflex Voltage Control
 *
@@ -11,10 +12,6 @@
 *
 * Copyright (C) 2007 Texas Instruments, Inc.
 * Lesly A M <x0080970@ti.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/module.h>
@@ -37,7 +34,6 @@
static LIST_HEAD(sr_list);

static struct omap_sr_class_data *sr_class;
static struct omap_sr_pmic_data *sr_pmic_data;
static struct dentry		*sr_dbg_dir;

static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
@@ -780,25 +776,6 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
	sr_class->disable(sr, 1);
}

/**
 * omap_sr_register_pmic() - API to register pmic specific info.
 * @pmic_data:	The structure containing pmic specific data.
 *
 * This API is to be called from the PMIC specific code to register with
 * smartreflex driver pmic specific info. Currently the only info required
 * is the smartreflex init on the PMIC side.
 */
void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data)
{
	if (!pmic_data) {
		pr_warn("%s: Trying to register NULL PMIC data structure with smartreflex\n",
			__func__);
		return;
	}

	sr_pmic_data = pmic_data;
}

/* PM Debug FS entries to enable and disable smartreflex. */
static int omap_sr_autocomp_show(void *data, u64 *val)
{
@@ -1010,7 +987,6 @@ static int omap_sr_remove(struct platform_device *pdev)

	if (sr_info->autocomp_active)
		sr_stop_vddautocomp(sr_info);
	if (sr_info->dbg_dir)
	debugfs_remove_recursive(sr_info->dbg_dir);

	pm_runtime_disable(&pdev->dev);
@@ -1065,17 +1041,6 @@ static int __init sr_init(void)
{
	int ret = 0;

	/*
	 * sr_init is a late init. If by then a pmic specific API is not
	 * registered either there is no need for anything to be done on
	 * the PMIC side or somebody has forgotten to register a PMIC
	 * handler. Warn for the second condition.
	 */
	if (sr_pmic_data && sr_pmic_data->sr_pmic_init)
		sr_pmic_data->sr_pmic_init();
	else
		pr_warn("%s: No PMIC hook to init smartreflex\n", __func__);

	ret = platform_driver_register(&smartreflex_driver);
	if (ret) {
		pr_err("%s: platform driver register failed for SR\n",
+13 −0
Original line number Diff line number Diff line
@@ -131,6 +131,9 @@ struct devfreq_dev_profile {
 * @scaling_min_freq:	Limit minimum frequency requested by OPP interface
 * @scaling_max_freq:	Limit maximum frequency requested by OPP interface
 * @stop_polling:	 devfreq polling status of a device.
 * @suspend_freq:	 frequency of a device set during suspend phase.
 * @resume_freq:	 frequency of a device set in resume phase.
 * @suspend_count:	 suspend requests counter for a device.
 * @total_trans:	Number of devfreq transitions
 * @trans_table:	Statistics of devfreq transitions
 * @time_in_state:	Statistics of devfreq states
@@ -167,6 +170,10 @@ struct devfreq {
	unsigned long scaling_max_freq;
	bool stop_polling;

	unsigned long suspend_freq;
	unsigned long resume_freq;
	atomic_t suspend_count;

	/* information for device frequency transition */
	unsigned int total_trans;
	unsigned int *trans_table;
@@ -198,6 +205,9 @@ extern void devm_devfreq_remove_device(struct device *dev,
extern int devfreq_suspend_device(struct devfreq *devfreq);
extern int devfreq_resume_device(struct devfreq *devfreq);

extern void devfreq_suspend(void);
extern void devfreq_resume(void);

/**
 * update_devfreq() - Reevaluate the device and configure frequency
 * @devfreq:	the devfreq device
@@ -324,6 +334,9 @@ static inline int devfreq_resume_device(struct devfreq *devfreq)
	return 0;
}

static inline void devfreq_suspend(void) {}
static inline void devfreq_resume(void) {}

static inline struct dev_pm_opp *devfreq_recommended_opp(struct device *dev,
					   unsigned long *freq, u32 flags)
{
+1 −9
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * OMAP Smartreflex Defines and Routines
 *
@@ -11,10 +12,6 @@
 *
 * Copyright (C) 2007 Texas Instruments, Inc.
 * Lesly A M <x0080970@ti.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#ifndef __POWER_SMARTREFLEX_H
@@ -303,9 +300,6 @@ void omap_sr_enable(struct voltagedomain *voltdm);
void omap_sr_disable(struct voltagedomain *voltdm);
void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);

/* API to register the pmic specific data with the smartreflex driver. */
void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);

/* Smartreflex driver hooks to be called from Smartreflex class driver */
int sr_enable(struct omap_sr *sr, unsigned long volt);
void sr_disable(struct omap_sr *sr);
@@ -320,7 +314,5 @@ static inline void omap_sr_enable(struct voltagedomain *voltdm) {}
static inline void omap_sr_disable(struct voltagedomain *voltdm) {}
static inline void omap_sr_disable_reset_volt(
		struct voltagedomain *voltdm) {}
static inline void omap_sr_register_pmic(
		struct omap_sr_pmic_data *pmic_data) {}
#endif
#endif
+5 −1
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ endif
localedir ?=	/usr/share/locale
docdir ?=       /usr/share/doc/packages/cpupower
confdir ?=      /etc/
bash_completion_dir ?= /usr/share/bash-completion/completions

# Toolchain: what tools do we use, and what options do they need:

@@ -96,7 +97,8 @@ CP = cp -fpR
INSTALL = /usr/bin/install -c
INSTALL_PROGRAM = ${INSTALL}
INSTALL_DATA  = ${INSTALL} -m 644
INSTALL_SCRIPT = ${INSTALL_PROGRAM}
#bash completion scripts get sourced and so they should be rw only.
INSTALL_SCRIPT = ${INSTALL} -m 644

# If you are running a cross compiler, you may want to set this
# to something more interesting, like "arm-linux-".  If you want
@@ -288,6 +290,8 @@ install-lib:
install-tools:
	$(INSTALL) -d $(DESTDIR)${bindir}
	$(INSTALL_PROGRAM) $(OUTPUT)cpupower $(DESTDIR)${bindir}
	$(INSTALL) -d $(DESTDIR)${bash_completion_dir}
	$(INSTALL_SCRIPT) cpupower-completion.sh '$(DESTDIR)${bash_completion_dir}/cpupower'

install-man:
	$(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1
Loading