-From a9ebdf9fa18fd317a4e97f46e8c5263898094864 Mon Sep 17 00:00:00 2001
+From b018e44a68dc2f4df819ae194e39e07313841dad Mon Sep 17 00:00:00 2001
From: Yangbo Lu <yangbo.lu@nxp.com>
-Date: Mon, 25 Sep 2017 12:20:10 +0800
-Subject: [PATCH] cpufreq: support layerscape
+Date: Wed, 17 Jan 2018 15:27:58 +0800
+Subject: [PATCH 15/30] cpufreq: support layerscape
-This is a integrated patch for layerscape pm support.
+This is an integrated patch for layerscape pm support.
Signed-off-by: Tang Yuantian <Yuantian.Tang@nxp.com>
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
drivers/cpufreq/Kconfig | 2 +-
drivers/cpufreq/qoriq-cpufreq.c | 176 +++++++++++++++-------------------------
drivers/firmware/psci.c | 12 ++-
- 3 files changed, 77 insertions(+), 113 deletions(-)
+ drivers/soc/fsl/rcpm.c | 158 ++++++++++++++++++++++++++++++++++++
+ 4 files changed, 235 insertions(+), 113 deletions(-)
+ create mode 100644 drivers/soc/fsl/rcpm.c
-diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
-index d8b164a7..bc9264c7 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -332,7 +332,7 @@ endif
depends on !CPU_THERMAL || THERMAL
select CLK_QORIQ
help
-diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c
-index 53d8c3fb..e2ea433a 100644
--- a/drivers/cpufreq/qoriq-cpufreq.c
+++ b/drivers/cpufreq/qoriq-cpufreq.c
@@ -11,6 +11,7 @@
if (!cpu_present(cpu))
return NULL;
-@@ -112,37 +87,28 @@ static struct device_node *cpu_to_clk_node(int cpu)
+@@ -112,37 +87,28 @@ static struct device_node *cpu_to_clk_no
if (!np)
return NULL;
}
/* reduce the duplicated frequencies in frequency table */
-@@ -198,10 +164,11 @@ static void freq_table_sort(struct cpufreq_frequency_table *freq_table,
+@@ -198,10 +164,11 @@ static void freq_table_sort(struct cpufr
static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
struct cpufreq_frequency_table *table;
struct cpu_data *data;
unsigned int cpu = policy->cpu;
-@@ -221,17 +188,13 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
+@@ -221,17 +188,13 @@ static int qoriq_cpufreq_cpu_init(struct
goto err_nomem2;
}
}
table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
-@@ -240,23 +203,11 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
+@@ -240,23 +203,11 @@ static int qoriq_cpufreq_cpu_init(struct
goto err_pclk;
}
table[i].driver_data = i;
}
freq_table_redup(table, count);
-@@ -282,7 +233,6 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
+@@ -282,7 +233,6 @@ static int qoriq_cpufreq_cpu_init(struct
policy->cpuinfo.transition_latency = u64temp + 1;
of_node_put(np);
return 0;
-@@ -290,10 +240,7 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
+@@ -290,10 +240,7 @@ err_nomem1:
kfree(table);
err_pclk:
kfree(data->pclk);
kfree(data);
err_np:
of_node_put(np);
-@@ -357,12 +304,25 @@ static struct cpufreq_driver qoriq_cpufreq_driver = {
+@@ -357,12 +304,25 @@ static struct cpufreq_driver qoriq_cpufr
.attr = cpufreq_generic_attr,
};
{ .compatible = "fsl,qoriq-clockgen-2.0", },
{}
};
-@@ -380,16 +340,12 @@ static int __init qoriq_cpufreq_init(void)
+@@ -380,16 +340,12 @@ static int __init qoriq_cpufreq_init(voi
match = of_match_node(node_matches, np);
data = match->data;
ret = cpufreq_register_driver(&qoriq_cpufreq_driver);
if (!ret)
pr_info("Freescale QorIQ CPU frequency scaling driver\n");
-diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
-index 8263429e..323c9fc0 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
-@@ -418,8 +418,12 @@ CPUIDLE_METHOD_OF_DECLARE(psci, "psci", &psci_cpuidle_ops);
+@@ -418,8 +418,12 @@ CPUIDLE_METHOD_OF_DECLARE(psci, "psci",
static int psci_system_suspend(unsigned long unused)
{
}
static int psci_system_suspend_enter(suspend_state_t state)
-@@ -439,6 +443,8 @@ static void __init psci_init_system_suspend(void)
+@@ -439,6 +443,8 @@ static void __init psci_init_system_susp
if (!IS_ENABLED(CONFIG_SUSPEND))
return;
ret = psci_features(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND));
if (ret != PSCI_RET_NOT_SUPPORTED)
-@@ -516,6 +522,8 @@ static void __init psci_0_2_set_functions(void)
+@@ -516,6 +522,8 @@ static void __init psci_0_2_set_function
arm_pm_restart = psci_sys_reset;
pm_power_off = psci_sys_poweroff;
}
/*
---
-2.14.1
-
+--- /dev/null
++++ b/drivers/soc/fsl/rcpm.c
+@@ -0,0 +1,158 @@
++/*
++ * Run Control and Power Management (RCPM) driver
++ *
++ * Copyright 2016 NXP
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ */
++#define pr_fmt(fmt) "RCPM: %s: " fmt, __func__
++
++#include <linux/kernel.h>
++#include <linux/io.h>
++#include <linux/of_platform.h>
++#include <linux/of_address.h>
++#include <linux/suspend.h>
++
++/* RCPM register offset */
++#define RCPM_IPPDEXPCR0 0x140
++
++#define RCPM_WAKEUP_CELL_SIZE 2
++
++struct rcpm_config {
++ int ipp_num;
++ int ippdexpcr_offset;
++ u32 ippdexpcr[2];
++ void *rcpm_reg_base;
++};
++
++static struct rcpm_config *rcpm;
++
++static inline void rcpm_reg_write(u32 offset, u32 value)
++{
++ iowrite32be(value, rcpm->rcpm_reg_base + offset);
++}
++
++static inline u32 rcpm_reg_read(u32 offset)
++{
++ return ioread32be(rcpm->rcpm_reg_base + offset);
++}
++
++static void rcpm_wakeup_fixup(struct device *dev, void *data)
++{
++ struct device_node *node = dev ? dev->of_node : NULL;
++ u32 value[RCPM_WAKEUP_CELL_SIZE];
++ int ret, i;
++
++ if (!dev || !node || !device_may_wakeup(dev))
++ return;
++
++ /*
++ * Get the values in the "rcpm-wakeup" property.
++ * Three values are:
++ * The first is a pointer to the RCPM node.
++ * The second is the value of the ippdexpcr0 register.
++ * The third is the value of the ippdexpcr1 register.
++ */
++ ret = of_property_read_u32_array(node, "fsl,rcpm-wakeup",
++ value, RCPM_WAKEUP_CELL_SIZE);
++ if (ret)
++ return;
++
++ pr_debug("wakeup source: the device %s\n", node->full_name);
++
++ for (i = 0; i < rcpm->ipp_num; i++)
++ rcpm->ippdexpcr[i] |= value[i + 1];
++}
++
++static int rcpm_suspend_prepare(void)
++{
++ int i;
++ u32 val;
++
++ BUG_ON(!rcpm);
++
++ for (i = 0; i < rcpm->ipp_num; i++)
++ rcpm->ippdexpcr[i] = 0;
++
++ dpm_for_each_dev(NULL, rcpm_wakeup_fixup);
++
++ for (i = 0; i < rcpm->ipp_num; i++) {
++ if (rcpm->ippdexpcr[i]) {
++ val = rcpm_reg_read(rcpm->ippdexpcr_offset + 4 * i);
++ rcpm_reg_write(rcpm->ippdexpcr_offset + 4 * i,
++ val | rcpm->ippdexpcr[i]);
++ pr_debug("ippdexpcr%d = 0x%x\n", i, rcpm->ippdexpcr[i]);
++ }
++ }
++
++ return 0;
++}
++
++static int rcpm_suspend_notifier_call(struct notifier_block *bl,
++ unsigned long state,
++ void *unused)
++{
++ switch (state) {
++ case PM_SUSPEND_PREPARE:
++ rcpm_suspend_prepare();
++ break;
++ }
++
++ return NOTIFY_DONE;
++}
++
++static struct rcpm_config rcpm_default_config = {
++ .ipp_num = 1,
++ .ippdexpcr_offset = RCPM_IPPDEXPCR0,
++};
++
++static const struct of_device_id rcpm_matches[] = {
++ {
++ .compatible = "fsl,qoriq-rcpm-2.1",
++ .data = &rcpm_default_config,
++ },
++ {}
++};
++
++static struct notifier_block rcpm_suspend_notifier = {
++ .notifier_call = rcpm_suspend_notifier_call,
++};
++
++static int __init layerscape_rcpm_init(void)
++{
++ const struct of_device_id *match;
++ struct device_node *np;
++
++ np = of_find_matching_node_and_match(NULL, rcpm_matches, &match);
++ if (!np) {
++ pr_err("Can't find the RCPM node.\n");
++ return -EINVAL;
++ }
++
++ if (match->data)
++ rcpm = (struct rcpm_config *)match->data;
++ else
++ return -EINVAL;
++
++ rcpm->rcpm_reg_base = of_iomap(np, 0);
++ of_node_put(np);
++ if (!rcpm->rcpm_reg_base)
++ return -ENOMEM;
++
++ register_pm_notifier(&rcpm_suspend_notifier);
++
++ pr_info("The RCPM driver initialized.\n");
++
++ return 0;
++}
++
++subsys_initcall(layerscape_rcpm_init);