Skip to content

Commit

Permalink
Merge branch 'pm-cpufreq'
Browse files Browse the repository at this point in the history
* pm-cpufreq:
  cpufreq: Avoid calling cpufreq_verify_current_freq() from handle_update()
  cpufreq: Consolidate cpufreq_update_current_freq() and __cpufreq_get()
  cpufreq: Don't skip frequency validation for has_target() drivers
  cpufreq: Use has_target() instead of !setpolicy
  cpufreq: Remove redundant !setpolicy check
  cpufreq: Move the IS_ENABLED(CPU_THERMAL) macro into a stub
  cpufreq: s5pv210: Don't flood kernel log after cpufreq change
  cpufreq: pcc-cpufreq: Fail initialization if driver cannot be registered
  cpufreq: add driver for Raspberry Pi
  cpufreq: Switch imx7d to imx-cpufreq-dt for speed grading
  cpufreq: imx-cpufreq-dt: Remove global platform match list
  cpufreq: brcmstb-avs-cpufreq: Fix types for voltage/frequency
  cpufreq: brcmstb-avs-cpufreq: Fix initial command check
  cpufreq: armada-37xx: Remove set but not used variable 'freq'
  cpufreq: imx-cpufreq-dt: Fix no OPPs available on unfused parts
  dt-bindings: imx-cpufreq-dt: Document opp-supported-hw usage
  cpufreq: Add imx-cpufreq-dt driver
  • Loading branch information
rafaeljw committed Jul 8, 2019
2 parents 13b06b7 + 70a59fd commit 586a07d
Show file tree
Hide file tree
Showing 13 changed files with 327 additions and 80 deletions.
37 changes: 37 additions & 0 deletions Documentation/devicetree/bindings/cpufreq/imx-cpufreq-dt.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
i.MX CPUFreq-DT OPP bindings
================================

Certain i.MX SoCs support different OPPs depending on the "market segment" and
"speed grading" value which are written in fuses. These bits are combined with
the opp-supported-hw values for each OPP to check if the OPP is allowed.

Required properties:
--------------------

For each opp entry in 'operating-points-v2' table:
- opp-supported-hw: Two bitmaps indicating:
- Supported speed grade mask
- Supported market segment mask
0: Consumer
1: Extended Consumer
2: Industrial
3: Automotive

Example:
--------

opp_table {
compatible = "operating-points-v2";
opp-1000000000 {
opp-hz = /bits/ 64 <1000000000>;
/* grade >= 0, consumer only */
opp-supported-hw = <0xf>, <0x3>;
};

opp-1300000000 {
opp-hz = /bits/ 64 <1300000000>;
opp-microvolt = <1000000>;
/* grade >= 1, all segments */
opp-supported-hw = <0xe>, <0x7>;
};
}
17 changes: 17 additions & 0 deletions drivers/cpufreq/Kconfig.arm
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,15 @@ config ARM_IMX6Q_CPUFREQ

If in doubt, say N.

config ARM_IMX_CPUFREQ_DT
tristate "Freescale i.MX8M cpufreq support"
depends on ARCH_MXC && CPUFREQ_DT
help
This adds cpufreq driver support for Freescale i.MX8M series SoCs,
based on cpufreq-dt.

If in doubt, say N.

config ARM_KIRKWOOD_CPUFREQ
def_bool MACH_KIRKWOOD
help
Expand Down Expand Up @@ -133,6 +142,14 @@ config ARM_QCOM_CPUFREQ_HW
The driver implements the cpufreq interface for this HW engine.
Say Y if you want to support CPUFreq HW.

config ARM_RASPBERRYPI_CPUFREQ
tristate "Raspberry Pi cpufreq support"
depends on CLK_RASPBERRYPI || COMPILE_TEST
help
This adds the CPUFreq driver for Raspberry Pi

If in doubt, say N.

config ARM_S3C_CPUFREQ
bool
help
Expand Down
2 changes: 2 additions & 0 deletions drivers/cpufreq/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o
obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
obj-$(CONFIG_ARM_IMX_CPUFREQ_DT) += imx-cpufreq-dt.o
obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o
obj-$(CONFIG_ARM_MEDIATEK_CPUFREQ) += mediatek-cpufreq.o
obj-$(CONFIG_MACH_MVEBU_V7) += mvebu-cpufreq.o
Expand All @@ -64,6 +65,7 @@ obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o
obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o
obj-$(CONFIG_ARM_QCOM_CPUFREQ_HW) += qcom-cpufreq-hw.o
obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO) += qcom-cpufreq-kryo.o
obj-$(CONFIG_ARM_RASPBERRYPI_CPUFREQ) += raspberrypi-cpufreq.o
obj-$(CONFIG_ARM_S3C2410_CPUFREQ) += s3c2410-cpufreq.o
obj-$(CONFIG_ARM_S3C2412_CPUFREQ) += s3c2412-cpufreq.o
obj-$(CONFIG_ARM_S3C2416_CPUFREQ) += s3c2416-cpufreq.o
Expand Down
4 changes: 1 addition & 3 deletions drivers/cpufreq/armada-37xx-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ static void __init armada37xx_cpufreq_avs_configure(struct regmap *base,
static void __init armada37xx_cpufreq_avs_setup(struct regmap *base,
struct armada_37xx_dvfs *dvfs)
{
unsigned int avs_val = 0, freq;
unsigned int avs_val = 0;
int load_level = 0;

if (base == NULL)
Expand All @@ -275,8 +275,6 @@ static void __init armada37xx_cpufreq_avs_setup(struct regmap *base,


for (load_level = 1; load_level < LOAD_LEVEL_NR; load_level++) {
freq = dvfs->cpu_freq_max / dvfs->divider[load_level];

avs_val = dvfs->avs[load_level];
regmap_update_bits(base, ARMADA_37XX_AVS_VSET(load_level-1),
ARMADA_37XX_AVS_VDD_MASK << ARMADA_37XX_AVS_HIGH_VDD_LIMIT |
Expand Down
12 changes: 6 additions & 6 deletions drivers/cpufreq/brcmstb-avs-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -384,12 +384,12 @@ static int brcm_avs_set_pstate(struct private_data *priv, unsigned int pstate)
return __issue_avs_command(priv, AVS_CMD_SET_PSTATE, true, args);
}

static unsigned long brcm_avs_get_voltage(void __iomem *base)
static u32 brcm_avs_get_voltage(void __iomem *base)
{
return readl(base + AVS_MBOX_VOLTAGE1);
}

static unsigned long brcm_avs_get_frequency(void __iomem *base)
static u32 brcm_avs_get_frequency(void __iomem *base)
{
return readl(base + AVS_MBOX_FREQUENCY) * 1000; /* in kHz */
}
Expand Down Expand Up @@ -446,8 +446,8 @@ static bool brcm_avs_is_firmware_loaded(struct private_data *priv)
rc = brcm_avs_get_pmap(priv, NULL);
magic = readl(priv->base + AVS_MBOX_MAGIC);

return (magic == AVS_FIRMWARE_MAGIC) && (rc != -ENOTSUPP) &&
(rc != -EINVAL);
return (magic == AVS_FIRMWARE_MAGIC) && ((rc != -ENOTSUPP) ||
(rc != -EINVAL));
}

static unsigned int brcm_avs_cpufreq_get(unsigned int cpu)
Expand Down Expand Up @@ -653,14 +653,14 @@ static ssize_t show_brcm_avs_voltage(struct cpufreq_policy *policy, char *buf)
{
struct private_data *priv = policy->driver_data;

return sprintf(buf, "0x%08lx\n", brcm_avs_get_voltage(priv->base));
return sprintf(buf, "0x%08x\n", brcm_avs_get_voltage(priv->base));
}

static ssize_t show_brcm_avs_frequency(struct cpufreq_policy *policy, char *buf)
{
struct private_data *priv = policy->driver_data;

return sprintf(buf, "0x%08lx\n", brcm_avs_get_frequency(priv->base));
return sprintf(buf, "0x%08x\n", brcm_avs_get_frequency(priv->base));
}

cpufreq_freq_attr_ro(brcm_avs_pstate);
Expand Down
5 changes: 4 additions & 1 deletion drivers/cpufreq/cpufreq-dt-platdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ static const struct of_device_id whitelist[] __initconst = {
{ .compatible = "fsl,imx27", },
{ .compatible = "fsl,imx51", },
{ .compatible = "fsl,imx53", },
{ .compatible = "fsl,imx7d", },

{ .compatible = "marvell,berlin", },
{ .compatible = "marvell,pxa250", },
Expand Down Expand Up @@ -105,6 +104,10 @@ static const struct of_device_id blacklist[] __initconst = {
{ .compatible = "calxeda,highbank", },
{ .compatible = "calxeda,ecx-2000", },

{ .compatible = "fsl,imx7d", },
{ .compatible = "fsl,imx8mq", },
{ .compatible = "fsl,imx8mm", },

{ .compatible = "marvell,armadaxp", },

{ .compatible = "mediatek,mt2701", },
Expand Down
121 changes: 54 additions & 67 deletions drivers/cpufreq/cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,12 +356,10 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy,
* which is not equal to what the cpufreq core thinks is
* "old frequency".
*/
if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
if (policy->cur && (policy->cur != freqs->old)) {
pr_debug("Warning: CPU frequency is %u, cpufreq assumed %u kHz\n",
freqs->old, policy->cur);
freqs->old = policy->cur;
}
if (policy->cur && policy->cur != freqs->old) {
pr_debug("Warning: CPU frequency is %u, cpufreq assumed %u kHz\n",
freqs->old, policy->cur);
freqs->old = policy->cur;
}

srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
Expand Down Expand Up @@ -631,7 +629,7 @@ static int cpufreq_parse_policy(char *str_governor,
}

/**
* cpufreq_parse_governor - parse a governor string only for !setpolicy
* cpufreq_parse_governor - parse a governor string only for has_target()
*/
static int cpufreq_parse_governor(char *str_governor,
struct cpufreq_policy *policy)
Expand Down Expand Up @@ -1114,13 +1112,25 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cp
return ret;
}

static void refresh_frequency_limits(struct cpufreq_policy *policy)
{
struct cpufreq_policy new_policy = *policy;

pr_debug("updating policy for CPU %u\n", policy->cpu);

new_policy.min = policy->user_policy.min;
new_policy.max = policy->user_policy.max;

cpufreq_set_policy(policy, &new_policy);
}

static void handle_update(struct work_struct *work)
{
struct cpufreq_policy *policy =
container_of(work, struct cpufreq_policy, update);
unsigned int cpu = policy->cpu;
pr_debug("handle_update for cpu %u called\n", cpu);
cpufreq_update_policy(cpu);

pr_debug("handle_update for cpu %u called\n", policy->cpu);
refresh_frequency_limits(policy);
}

static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
Expand Down Expand Up @@ -1300,7 +1310,7 @@ static int cpufreq_online(unsigned int cpu)
policy->max = policy->user_policy.max;
}

if (cpufreq_driver->get && !cpufreq_driver->setpolicy) {
if (cpufreq_driver->get && has_target()) {
policy->cur = cpufreq_driver->get(policy->cpu);
if (!policy->cur) {
pr_err("%s: ->get() failed\n", __func__);
Expand Down Expand Up @@ -1375,8 +1385,7 @@ static int cpufreq_online(unsigned int cpu)
if (cpufreq_driver->ready)
cpufreq_driver->ready(policy);

if (IS_ENABLED(CONFIG_CPU_THERMAL) &&
cpufreq_driver->flags & CPUFREQ_IS_COOLING_DEV)
if (cpufreq_thermal_control_enabled(cpufreq_driver))
policy->cdev = of_cpufreq_cooling_register(policy);

pr_debug("initialization complete\n");
Expand Down Expand Up @@ -1466,8 +1475,7 @@ static int cpufreq_offline(unsigned int cpu)
goto unlock;
}

if (IS_ENABLED(CONFIG_CPU_THERMAL) &&
cpufreq_driver->flags & CPUFREQ_IS_COOLING_DEV) {
if (cpufreq_thermal_control_enabled(cpufreq_driver)) {
cpufreq_cooling_unregister(policy->cdev);
policy->cdev = NULL;
}
Expand Down Expand Up @@ -1546,6 +1554,30 @@ static void cpufreq_out_of_sync(struct cpufreq_policy *policy,
cpufreq_freq_transition_end(policy, &freqs, 0);
}

static unsigned int cpufreq_verify_current_freq(struct cpufreq_policy *policy, bool update)
{
unsigned int new_freq;

new_freq = cpufreq_driver->get(policy->cpu);
if (!new_freq)
return 0;

/*
* If fast frequency switching is used with the given policy, the check
* against policy->cur is pointless, so skip it in that case.
*/
if (policy->fast_switch_enabled || !has_target())
return new_freq;

if (policy->cur != new_freq) {
cpufreq_out_of_sync(policy, new_freq);
if (update)
schedule_work(&policy->update);
}

return new_freq;
}

/**
* cpufreq_quick_get - get the CPU frequency (in kHz) from policy->cur
* @cpu: CPU number
Expand Down Expand Up @@ -1601,31 +1633,10 @@ EXPORT_SYMBOL(cpufreq_quick_get_max);

static unsigned int __cpufreq_get(struct cpufreq_policy *policy)
{
unsigned int ret_freq = 0;

if (unlikely(policy_is_inactive(policy)))
return ret_freq;

ret_freq = cpufreq_driver->get(policy->cpu);

/*
* If fast frequency switching is used with the given policy, the check
* against policy->cur is pointless, so skip it in that case too.
*/
if (policy->fast_switch_enabled)
return ret_freq;

if (ret_freq && policy->cur &&
!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
/* verify no discrepancy between actual and
saved value exists */
if (unlikely(ret_freq != policy->cur)) {
cpufreq_out_of_sync(policy, ret_freq);
schedule_work(&policy->update);
}
}
return 0;

return ret_freq;
return cpufreq_verify_current_freq(policy, true);
}

/**
Expand All @@ -1652,24 +1663,6 @@ unsigned int cpufreq_get(unsigned int cpu)
}
EXPORT_SYMBOL(cpufreq_get);

static unsigned int cpufreq_update_current_freq(struct cpufreq_policy *policy)
{
unsigned int new_freq;

new_freq = cpufreq_driver->get(policy->cpu);
if (!new_freq)
return 0;

if (!policy->cur) {
pr_debug("cpufreq: Driver did not initialize current freq\n");
policy->cur = new_freq;
} else if (policy->cur != new_freq && has_target()) {
cpufreq_out_of_sync(policy, new_freq);
}

return new_freq;
}

static struct subsys_interface cpufreq_interface = {
.name = "cpufreq",
.subsys = &cpu_subsys,
Expand Down Expand Up @@ -2150,8 +2143,8 @@ static int cpufreq_start_governor(struct cpufreq_policy *policy)

pr_debug("%s: for CPU %u\n", __func__, policy->cpu);

if (cpufreq_driver->get && !cpufreq_driver->setpolicy)
cpufreq_update_current_freq(policy);
if (cpufreq_driver->get)
cpufreq_verify_current_freq(policy, false);

if (policy->governor->start) {
ret = policy->governor->start(policy);
Expand Down Expand Up @@ -2392,7 +2385,6 @@ int cpufreq_set_policy(struct cpufreq_policy *policy,
void cpufreq_update_policy(unsigned int cpu)
{
struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu);
struct cpufreq_policy new_policy;

if (!policy)
return;
Expand All @@ -2401,16 +2393,11 @@ void cpufreq_update_policy(unsigned int cpu)
* BIOS might change freq behind our back
* -> ask driver for current freq and notify governors about a change
*/
if (cpufreq_driver->get && !cpufreq_driver->setpolicy &&
(cpufreq_suspended || WARN_ON(!cpufreq_update_current_freq(policy))))
if (cpufreq_driver->get && has_target() &&
(cpufreq_suspended || WARN_ON(!cpufreq_verify_current_freq(policy, false))))
goto unlock;

pr_debug("updating policy for CPU %u\n", cpu);
memcpy(&new_policy, policy, sizeof(*policy));
new_policy.min = policy->user_policy.min;
new_policy.max = policy->user_policy.max;

cpufreq_set_policy(policy, &new_policy);
refresh_frequency_limits(policy);

unlock:
cpufreq_cpu_release(policy);
Expand Down
Loading

0 comments on commit 586a07d

Please sign in to comment.