aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Yan <leo.yan@linaro.org>2015-02-06 22:20:06 +0800
committerFei Wang <w.f@huawei.com>2015-02-07 18:40:12 +0800
commitf3f50f41b0865f93460720b3a7fac7ce2437f33a (patch)
treecb948cbd5a2be4eb53bb5630a0de837bff1db545
parent6230410219e2eb568b46375abe06da7506fea175 (diff)
cpufreq: hisilicon: support max frequency limitation
Add export symbol for max frequency limitation, this is a temporary solution for thermal cooling. Signed-off-by: Leo Yan <leo.yan@linaro.org>
-rw-r--r--drivers/cpufreq/hisi-acpu-cpufreq.c69
-rw-r--r--include/linux/hisi_acpu_cpufreq.h18
2 files changed, 76 insertions, 11 deletions
diff --git a/drivers/cpufreq/hisi-acpu-cpufreq.c b/drivers/cpufreq/hisi-acpu-cpufreq.c
index 2cb6d2150738..ec88ccc617dd 100644
--- a/drivers/cpufreq/hisi-acpu-cpufreq.c
+++ b/drivers/cpufreq/hisi-acpu-cpufreq.c
@@ -39,6 +39,9 @@
#define ACPU_DFS_FREQ_REQ 0x4
#define ACPU_DFS_TEMP_REQ 0x8
+#define ACPU_DFS_LOCK_FLAG (0xAEAEAEAE)
+#define ACPU_DFS_UNLOCK_FLAG (0x0)
+
/* Multi-core communication */
#define MC_COM_ADDR (0xF7510000)
#define MC_COM_SIZE (0x1000)
@@ -59,6 +62,7 @@ static atomic_t cluster_usage[MAX_CLUSTERS] =
{ ATOMIC_INIT(0), ATOMIC_INIT(0) };
static struct mutex cluster_lock[MAX_CLUSTERS];
+static DEFINE_SPINLOCK(dfs_lock);
static void __iomem *mc_base = NULL;
static void __iomem *dfs_base = NULL;
@@ -77,6 +81,57 @@ static noinline int __invoke_smc(u64 function_id, u64 arg0, u64 arg1, u64 arg2)
return function_id;
}
+unsigned int hisi_acpu_get_freq(void)
+{
+ unsigned long flags;
+ unsigned int freq;
+
+ spin_lock_irqsave(&dfs_lock, flags);
+ freq = readl(dfs_base + ACPU_DFS_FREQ_REQ);
+ spin_unlock_irqrestore(&dfs_lock, flags);
+
+ return freq;
+}
+EXPORT_SYMBOL_GPL(hisi_acpu_get_freq);
+
+void hisi_acpu_set_freq(unsigned int freq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dfs_lock, flags);
+
+ writel(freq, dfs_base + ACPU_DFS_FREQ_REQ);
+ writel((1 << MC_COM_INT_ACPU_DFS),
+ mc_base + MC_COM_CPU_RAW_INT_OFFSET(MC_CORE_ACPU));
+
+ spin_unlock_irqrestore(&dfs_lock, flags);
+ return;
+}
+EXPORT_SYMBOL_GPL(hisi_acpu_set_freq);
+
+int hisi_acpu_set_max_freq(unsigned int max_freq, unsigned int flag)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dfs_lock, flags);
+
+ writel(max_freq, dfs_base + ACPU_DFS_TEMP_REQ);
+
+ if (flag == 1)
+ writel(ACPU_DFS_LOCK_FLAG, dfs_base + ACPU_DFS_FLAG);
+ else if (flag == 0)
+ writel(ACPU_DFS_UNLOCK_FLAG, dfs_base + ACPU_DFS_FLAG);
+ else
+ return -EINVAL;
+
+ writel((1 << MC_COM_INT_ACPU_DFS),
+ mc_base + MC_COM_CPU_RAW_INT_OFFSET(MC_CORE_ACPU));
+
+ spin_unlock_irqrestore(&dfs_lock, flags);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(hisi_acpu_set_max_freq);
+
static unsigned int hisi_acpu_cpufreq_get_rate(unsigned int cpu)
{
int cluster = topology_physical_package_id(cpu);
@@ -87,20 +142,12 @@ static unsigned int hisi_acpu_cpufreq_get_rate(unsigned int cpu)
if (call_atf)
freq = __invoke_smc(HISI_SIP_CPUFREQ_GET, cluster, 0, 0);
else
- freq = readl(dfs_base + ACPU_DFS_FREQ_REQ);
+ freq = hisi_acpu_get_freq();
mutex_unlock(&cluster_lock[cluster]);
return freq;
}
-static void __invoke_acpu_dvfs_cmd(unsigned int freq)
-{
- writel(freq, dfs_base + ACPU_DFS_FREQ_REQ);
- writel((1 << MC_COM_INT_ACPU_DFS),
- mc_base + MC_COM_CPU_RAW_INT_OFFSET(MC_CORE_ACPU));
- return;
-}
-
/* Set clock frequency */
static int hisi_acpu_cpufreq_set_target(struct cpufreq_policy *policy,
unsigned int index)
@@ -124,7 +171,7 @@ static int hisi_acpu_cpufreq_set_target(struct cpufreq_policy *policy,
ret = -EIO;
}
} else
- __invoke_acpu_dvfs_cmd(freqs_new);
+ hisi_acpu_set_freq(freqs_new);
mutex_unlock(&cluster_lock[cluster]);
return ret;
@@ -304,7 +351,7 @@ static int hisi_acpu_init_mc(struct platform_device *pdev)
* current frequency value, so the register ACPU_DFS_FREQ_REQ
* is zero; so here just trigger to a fixed frequency firstly.
*/
- __invoke_acpu_dvfs_cmd(729000);
+ hisi_acpu_set_freq(729000);
return ret;
}
diff --git a/include/linux/hisi_acpu_cpufreq.h b/include/linux/hisi_acpu_cpufreq.h
new file mode 100644
index 000000000000..d487159e8fe8
--- /dev/null
+++ b/include/linux/hisi_acpu_cpufreq.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2015 Linaro.
+ * Leo Yan <leo.yan@linaro.org>
+ *
+ * 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 __HISI_ACPU_CPUFREQ__
+#define __HISI_ACPU_CPUFREQ__
+
+extern unsigned int hisi_acpu_get_freq(void);
+extern void hisi_acpu_set_freq(unsigned int freq);
+extern int hisi_acpu_set_max_freq(unsigned int max_freq, unsigned int flag);
+
+#endif /* __HISI_ACPU_CPUFREQ__ */