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

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

Merge branch 'pm-cpufreq'

* pm-cpufreq:
  cpufreq: arm_big_little_dt: Instantiate as platform_driver
  cpufreq: arm_big_little_dt: Register driver only if DT has valid data
  cpufreq / e_powersaver: Fix linker error when ACPI processor is a module
  cpufreq / intel_pstate: Add additional supported CPU ID
  cpufreq: Drop rwsem lock around CPUFREQ_GOV_POLICY_EXIT
parents f1a0b831 9076eaca
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -272,7 +272,7 @@ config X86_LONGHAUL
config X86_E_POWERSAVER
config X86_E_POWERSAVER
	tristate "VIA C7 Enhanced PowerSaver (DANGEROUS)"
	tristate "VIA C7 Enhanced PowerSaver (DANGEROUS)"
	select CPU_FREQ_TABLE
	select CPU_FREQ_TABLE
	depends on X86_32
	depends on X86_32 && ACPI_PROCESSOR
	help
	help
	  This adds the CPUFreq driver for VIA C7 processors.  However, this driver
	  This adds the CPUFreq driver for VIA C7 processors.  However, this driver
	  does not have any safeguards to prevent operating the CPU out of spec
	  does not have any safeguards to prevent operating the CPU out of spec
+57 −36
Original line number Original line Diff line number Diff line
@@ -19,89 +19,110 @@


#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt


#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/cpufreq.h>
#include <linux/device.h>
#include <linux/device.h>
#include <linux/export.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of.h>
#include <linux/opp.h>
#include <linux/opp.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/types.h>
#include "arm_big_little.h"
#include "arm_big_little.h"


static int dt_init_opp_table(struct device *cpu_dev)
/* get cpu node with valid operating-points */
static struct device_node *get_cpu_node_with_valid_op(int cpu)
{
{
	struct device_node *np, *parent;
	struct device_node *np = NULL, *parent;
	int count = 0, ret;
	int count = 0;


	parent = of_find_node_by_path("/cpus");
	parent = of_find_node_by_path("/cpus");
	if (!parent) {
	if (!parent) {
		pr_err("failed to find OF /cpus\n");
		pr_err("failed to find OF /cpus\n");
		return -ENOENT;
		return NULL;
	}
	}


	for_each_child_of_node(parent, np) {
	for_each_child_of_node(parent, np) {
		if (count++ != cpu_dev->id)
		if (count++ != cpu)
			continue;
			continue;
		if (!of_get_property(np, "operating-points", NULL)) {
		if (!of_get_property(np, "operating-points", NULL)) {
			ret = -ENODATA;
			of_node_put(np);
		} else {
			np = NULL;
		}

		break;
	}

	of_node_put(parent);
	return np;
}

static int dt_init_opp_table(struct device *cpu_dev)
{
	struct device_node *np;
	int ret;

	np = get_cpu_node_with_valid_op(cpu_dev->id);
	if (!np)
		return -ENODATA;

	cpu_dev->of_node = np;
	cpu_dev->of_node = np;
	ret = of_init_opp_table(cpu_dev);
	ret = of_init_opp_table(cpu_dev);
		}
	of_node_put(np);
	of_node_put(np);
		of_node_put(parent);


	return ret;
	return ret;
}
}


	return -ENODEV;
}

static int dt_get_transition_latency(struct device *cpu_dev)
static int dt_get_transition_latency(struct device *cpu_dev)
{
{
	struct device_node *np, *parent;
	struct device_node *np;
	u32 transition_latency = CPUFREQ_ETERNAL;
	u32 transition_latency = CPUFREQ_ETERNAL;
	int count = 0;


	parent = of_find_node_by_path("/cpus");
	np = get_cpu_node_with_valid_op(cpu_dev->id);
	if (!parent) {
	if (!np)
		pr_info("Failed to find OF /cpus. Use CPUFREQ_ETERNAL transition latency\n");
		return CPUFREQ_ETERNAL;
		return CPUFREQ_ETERNAL;
	}

	for_each_child_of_node(parent, np) {
		if (count++ != cpu_dev->id)
			continue;


	of_property_read_u32(np, "clock-latency", &transition_latency);
	of_property_read_u32(np, "clock-latency", &transition_latency);
	of_node_put(np);
	of_node_put(np);
		of_node_put(parent);


	pr_debug("%s: clock-latency: %d\n", __func__, transition_latency);
	return transition_latency;
	return transition_latency;
}
}


	pr_info("clock-latency isn't found, use CPUFREQ_ETERNAL transition latency\n");
	return CPUFREQ_ETERNAL;
}

static struct cpufreq_arm_bL_ops dt_bL_ops = {
static struct cpufreq_arm_bL_ops dt_bL_ops = {
	.name	= "dt-bl",
	.name	= "dt-bl",
	.get_transition_latency = dt_get_transition_latency,
	.get_transition_latency = dt_get_transition_latency,
	.init_opp_table = dt_init_opp_table,
	.init_opp_table = dt_init_opp_table,
};
};


static int generic_bL_init(void)
static int generic_bL_probe(struct platform_device *pdev)
{
{
	struct device_node *np;

	np = get_cpu_node_with_valid_op(0);
	if (!np)
		return -ENODEV;

	of_node_put(np);
	return bL_cpufreq_register(&dt_bL_ops);
	return bL_cpufreq_register(&dt_bL_ops);
}
}
module_init(generic_bL_init);


static void generic_bL_exit(void)
static int generic_bL_remove(struct platform_device *pdev)
{
{
	return bL_cpufreq_unregister(&dt_bL_ops);
	bL_cpufreq_unregister(&dt_bL_ops);
	return 0;
}
}
module_exit(generic_bL_exit);

static struct platform_driver generic_bL_platdrv = {
	.driver = {
		.name	= "arm-bL-cpufreq-dt",
		.owner	= THIS_MODULE,
	},
	.probe		= generic_bL_probe,
	.remove		= generic_bL_remove,
};
module_platform_driver(generic_bL_platdrv);


MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver via DT");
MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver via DT");
+7 −2
Original line number Original line Diff line number Diff line
@@ -1729,18 +1729,23 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
			/* end old governor */
			/* end old governor */
			if (data->governor) {
			if (data->governor) {
				__cpufreq_governor(data, CPUFREQ_GOV_STOP);
				__cpufreq_governor(data, CPUFREQ_GOV_STOP);
				unlock_policy_rwsem_write(policy->cpu);
				__cpufreq_governor(data,
				__cpufreq_governor(data,
						CPUFREQ_GOV_POLICY_EXIT);
						CPUFREQ_GOV_POLICY_EXIT);
				lock_policy_rwsem_write(policy->cpu);
			}
			}


			/* start new governor */
			/* start new governor */
			data->governor = policy->governor;
			data->governor = policy->governor;
			if (!__cpufreq_governor(data, CPUFREQ_GOV_POLICY_INIT)) {
			if (!__cpufreq_governor(data, CPUFREQ_GOV_POLICY_INIT)) {
				if (!__cpufreq_governor(data, CPUFREQ_GOV_START))
				if (!__cpufreq_governor(data, CPUFREQ_GOV_START)) {
					failed = 0;
					failed = 0;
				else
				} else {
					unlock_policy_rwsem_write(policy->cpu);
					__cpufreq_governor(data,
					__cpufreq_governor(data,
							CPUFREQ_GOV_POLICY_EXIT);
							CPUFREQ_GOV_POLICY_EXIT);
					lock_policy_rwsem_write(policy->cpu);
				}
			}
			}


			if (failed) {
			if (failed) {
+1 −0
Original line number Original line Diff line number Diff line
@@ -521,6 +521,7 @@ static void intel_pstate_timer_func(unsigned long __data)
static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
	ICPU(0x2a, default_policy),
	ICPU(0x2a, default_policy),
	ICPU(0x2d, default_policy),
	ICPU(0x2d, default_policy),
	ICPU(0x3a, default_policy),
	{}
	{}
};
};
MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);
MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);