mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Jonghwa Lee <jonghwa3.lee@samsung.com>
To: linux-kernel@vger.kernel.org
Cc: cpufreq@vger.kernel.org, linux-pm@vger.kernel.org,
	Vicent Guittot <vincent.guittot@linaro.org>,
	Daniel Lezcano <daniel.lezcano@linaro.org>,
	"Rafael J. Wysocky" <rjw@sisk.pl>,
	Viresh Kumar <viresh.kumar@linaro.org>,
	MyungJoo Ham <myungjoo.ham@samsung.com>,
	Lukasz Majewski <l.majewski@samsung.com>
Subject: [RFC v2 1/3] cpufreq:overclocking: Overclocking support at Exynos4 SoC
Date: Fri, 03 May 2013 23:07:50 +0900	[thread overview]
Message-ID: <1367590072-10496-2-git-send-email-jonghwa3.lee@samsung.com> (raw)
In-Reply-To: <1367590072-10496-1-git-send-email-jonghwa3.lee@samsung.com>

From: Lukasz Majewski <l.majewski@samsung.com>

Exynos4 SoCs (e.g. 4x12) allow setting of frequency above its normal
condition limits. This can be done for some short time.

This commit comprises of:
- low-level code for overclocking support at Exynos4x12 SoC
- exynos-cpufreq.c modifications to support generic cpufreq_overclk_*
functions (which are used at LAB governor)
- Export cpufreq_overclk_* at cpufreq.h
- Code to enable cpufreq at Kconfig

It is crucial to also enable TMU (Thermal Monitoring Unit) to prevent from
overheating the SoC.

When CPU_FREQ_OVERCLOCK is enabled, two extra switches were added:
1. tb_en_over_clk - enable feature
2. tb_over_clk_freq - read overclocked freqency (defied at device tree)

Tested at 3.8 linux kernel, Exynos4412 Device.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
---
 drivers/cpufreq/Kconfig              |    7 +++
 drivers/cpufreq/exynos-cpufreq.c     |  108 ++++++++++++++++++++++++++++++++++
 drivers/cpufreq/exynos-cpufreq.h     |    7 +++
 drivers/cpufreq/exynos4x12-cpufreq.c |   15 +++++
 include/linux/cpufreq.h              |   32 ++++++++++
 5 files changed, 169 insertions(+)

diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index a1488f5..5a1c236 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -23,6 +23,13 @@ config CPU_FREQ_TABLE
 config CPU_FREQ_GOV_COMMON
 	bool
 
+config CPU_FREQ_OVERCLOCK
+	bool "CPU frequency overclocking support"
+	help
+	  Switch to enable support for overclocking support
+
+	  If in doubt, say N.
+
 config CPU_FREQ_STAT
 	tristate "CPU frequency translation statistics"
 	select CPU_FREQ_TABLE
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index 475b4f6..eac6818 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -239,6 +239,99 @@ static struct notifier_block exynos_cpufreq_nb = {
 	.notifier_call = exynos_cpufreq_pm_notifier,
 };
 
+#ifdef CONFIG_CPU_FREQ_OVERCLOCK
+static int tb_over_clk_update_freq(struct cpufreq_policy *policy, int enable)
+{
+	int ret, index;
+
+	index = exynos_info->get_freq_index(exynos_info->max_over_freq);
+	if (index < 0) {
+		pr_err("%s: Index not found !\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&cpufreq_lock);
+	exynos_info->max_over_idx = index;
+	exynos_info->en_over_clk = enable;
+
+	if (enable)
+		cpufreq_freq_table_set_valid_entry(exynos_info->freq_table,
+						   index,
+						   exynos_info->max_over_freq);
+	else
+		cpufreq_freq_table_set_invalid_entry(exynos_info->freq_table,
+						     index);
+
+	ret = cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table);
+	mutex_unlock(&cpufreq_lock);
+
+	return ret;
+}
+
+int cpufreq_overclk_en(struct cpufreq_policy *policy)
+{
+	if (!exynos_info->en_over_clk)
+		return tb_over_clk_update_freq(policy, 1);
+
+	return 0;
+}
+
+int cpufreq_overclk_dis(struct cpufreq_policy *policy)
+{
+	if (exynos_info->en_over_clk)
+		return tb_over_clk_update_freq(policy, 0);
+
+	return 0;
+}
+
+int cpufreq_overclk_max(void)
+{
+	return exynos_info->max_over_freq;
+}
+
+static ssize_t show_tb_en_over_clk(struct cpufreq_policy *policy, char *buf)
+{
+	return sprintf(buf, "%d\n", exynos_info->en_over_clk);
+}
+
+static ssize_t store_tb_en_over_clk(struct cpufreq_policy *policy,
+				    const char *buf, size_t count)
+{
+	int ret, enable;
+
+	ret = sscanf(buf, "%d", &enable);
+	if (ret != 1 || enable < 0 || enable > 1)
+		return -EINVAL;
+
+	if (tb_over_clk_update_freq(policy, enable)) {
+		pr_err("Cannot enable TurboBoost overclocking!\n");
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+struct freq_attr cpufreq_attr_tb_en_over_clk = {
+	.attr = { .name = "tb_en_over_clk",
+		  .mode = 0644,
+		},
+	.show = show_tb_en_over_clk,
+	.store = store_tb_en_over_clk,
+};
+
+static ssize_t show_tb_over_clk_freq(struct cpufreq_policy *policy, char *buf)
+{
+	return sprintf(buf, "%d\n", exynos_info->max_over_freq);
+}
+
+struct freq_attr cpufreq_attr_tb_over_clk_freq = {
+	.attr = { .name = "tb_over_clk_freq",
+		  .mode = 0444,
+		},
+	.show = show_tb_over_clk_freq,
+};
+#endif
+
 static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
 	policy->cur = policy->min = policy->max = exynos_getspeed(policy->cpu);
@@ -261,6 +354,10 @@ static int exynos_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 
 static struct freq_attr *exynos_cpufreq_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
+#ifdef CONFIG_CPU_FREQ_OVERCLOCK
+	&cpufreq_attr_tb_over_clk_freq,
+	&cpufreq_attr_tb_en_over_clk,
+#endif
 	NULL,
 };
 
@@ -281,6 +378,7 @@ static struct cpufreq_driver exynos_driver = {
 
 static int __init exynos_cpufreq_init(void)
 {
+	struct device_node *node = pdev->dev.of_node;
 	int ret = -EINVAL;
 
 	exynos_info = kzalloc(sizeof(struct exynos_dvfs_info), GFP_KERNEL);
@@ -310,6 +408,16 @@ static int __init exynos_cpufreq_init(void)
 		goto err_vdd_arm;
 	}
 
+#ifdef CONFIG_CPU_FREQ_OVERCLOCK
+	if (of_property_read_bool(node, "overclocking")) {
+		of_property_read_u32(node, "max_overclocking_freq",
+				     &exynos_info->max_over_freq);
+		pr_debug("%s: en_overclk: %d max_overclocking_freq: %d\n",
+			 __func__, exynos_info->en_over_clk,
+			 exynos_info->max_over_freq);
+	}
+#endif
+
 	locking_frequency = exynos_getspeed(0);
 
 	register_pm_notifier(&exynos_cpufreq_nb);
diff --git a/drivers/cpufreq/exynos-cpufreq.h b/drivers/cpufreq/exynos-cpufreq.h
index 92b852e..bc8ecfc 100644
--- a/drivers/cpufreq/exynos-cpufreq.h
+++ b/drivers/cpufreq/exynos-cpufreq.h
@@ -39,8 +39,15 @@ struct exynos_dvfs_info {
 	struct clk	*cpu_clk;
 	unsigned int	*volt_table;
 	struct cpufreq_frequency_table	*freq_table;
+	unsigned int    en_over_clk; /* enable overclocking
+					 for this policy */
+	unsigned int    max_over_freq; /* maximal overclocked
+					  frequency */
+	unsigned int    max_over_idx; /* maximal overclocked
+					 index at freq_table */
 	void (*set_freq)(unsigned int, unsigned int);
 	bool (*need_apll_change)(unsigned int, unsigned int);
+	int (*get_freq_index)(unsigned int);
 };
 
 extern int exynos4210_cpufreq_init(struct exynos_dvfs_info *);
diff --git a/drivers/cpufreq/exynos4x12-cpufreq.c b/drivers/cpufreq/exynos4x12-cpufreq.c
index 08b7477..08ccfae 100644
--- a/drivers/cpufreq/exynos4x12-cpufreq.c
+++ b/drivers/cpufreq/exynos4x12-cpufreq.c
@@ -216,6 +216,20 @@ static void exynos4x12_set_frequency(unsigned int old_index,
 	}
 }
 
+int exynos4x12_get_freq_index(unsigned int freq)
+{
+	/* apll_freq tables are equal size for exynos4412 and exynos 4212 */
+	int i, size = ARRAY_SIZE(apll_freq_4412);
+
+	for (i = 0; i < size; i++)
+		if (apll_freq_4x12[i].freq == freq)
+			return i;
+
+	pr_debug("Entry for freq: %u not found\n", freq);
+
+	return -EINVAL;
+}
+
 int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info)
 {
 	unsigned long rate;
@@ -251,6 +265,7 @@ int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info)
 	info->freq_table = exynos4x12_freq_table;
 	info->set_freq = exynos4x12_set_frequency;
 	info->need_apll_change = exynos4x12_pms_change;
+	info->get_freq_index = exynos4x12_get_freq_index;
 
 	return 0;
 
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 037d36a..8c185d6 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -331,6 +331,24 @@ static struct global_attr _name =		\
 __ATTR(_name, 0644, show_##_name, store_##_name)
 
 struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu);
+#ifdef CONFIG_CPU_FREQ_OVERCLOCK
+int cpufreq_overclk_dis(struct cpufreq_policy *policy);
+int cpufreq_overclk_en(struct cpufreq_policy *policy);
+int cpufreq_overclk_max(void);
+#else
+static inline int cpufreq_overclk_dis(struct cpufreq_policy *policy)
+{
+	return 0;
+}
+static inline int cpufreq_overclk_en (struct cpufreq_policy *policy)
+{
+	return 0;
+}
+static inline int cpufreq_overclk_max(void)
+{
+	return 0;
+}
+#endif
 void cpufreq_cpu_put(struct cpufreq_policy *data);
 const char *cpufreq_get_current_driver(void);
 
@@ -409,6 +427,20 @@ struct cpufreq_frequency_table {
 				    * order */
 };
 
+static inline void cpufreq_freq_table_set_valid_entry(
+					struct cpufreq_frequency_table *table,
+					unsigned int index, unsigned int freq)
+{
+	table[index].frequency = freq;
+}
+
+static inline void cpufreq_freq_table_set_invalid_entry(
+					  struct cpufreq_frequency_table *table,
+					  unsigned int index)
+{
+	table[index].frequency = CPUFREQ_ENTRY_INVALID;
+}
+
 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
 				    struct cpufreq_frequency_table *table);
 
-- 
1.7.9.5


  reply	other threads:[~2013-05-03 14:08 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-05-03 14:07 [RFC v2 0/3] LAB: Support for Legacy Application Booster governor Jonghwa Lee
2013-05-03 14:07 ` Jonghwa Lee [this message]
2013-05-03 14:07 ` [RFC v2 2/3] cpufreq:LAB: Introduce new cpufreq LAB(Legacy Application Boost) governor Jonghwa Lee
2013-05-03 14:07 ` [RFC v2 3/3] cpufreq:LAB: Modify cpufreq_governor to support LAB Governor Jonghwa Lee
2013-05-22  9:07 ` [RFC v2 0/3] LAB: Support for Legacy Application Booster governor Viresh Kumar
2013-05-22 10:27   ` Lukasz Majewski
2013-05-22 11:16     ` Viresh Kumar
2013-05-22 12:05       ` Lukasz Majewski
2013-05-22 14:44       ` [RFC v2 0/3][TESTS] LAB: Support for Legacy Application Booster governor - tests results Lukasz Majewski
2013-05-24  5:56         ` Lukasz Majewski
2013-05-24  7:52           ` Viresh Kumar
2013-05-24  8:30             ` Lukasz Majewski
2013-05-24  8:51               ` Viresh Kumar
2013-05-24  9:06                 ` Daniel Lezcano
2013-05-24  9:13                   ` Viresh Kumar
2013-05-24 10:28                     ` Daniel Lezcano
2013-05-24 10:32                       ` Viresh Kumar
2013-05-24 11:34                     ` Lukasz Majewski
2013-05-24 11:20                 ` Lukasz Majewski
2013-05-27  5:33                   ` Viresh Kumar
2013-05-27  7:34                     ` Lukasz Majewski
2013-05-27 12:00                     ` Rafael J. Wysocki
2013-05-27 12:16                       ` Lukasz Majewski
2013-05-27 13:24                       ` Viresh Kumar
2013-05-27 19:48                         ` Rafael J. Wysocki
2013-05-28  6:40                           ` Lukasz Majewski
2013-05-28  9:44                             ` Viresh Kumar
2013-05-28 12:30                               ` Rafael J. Wysocki
2013-05-28 13:26                                 ` Lukasz Majewski
2013-05-28 21:48                                   ` Rafael J. Wysocki
2013-05-29  5:23                                     ` Viresh Kumar
2013-05-29  7:09                                       ` Lukasz Majewski
2013-05-29  7:39                                         ` Viresh Kumar
2013-05-29 13:45                                           ` Lukasz Majewski
2014-03-04 10:27 ` [RFC v3 0/5] cpufreq:LAB: Support for LAB governor Lukasz Majewski
2014-03-04 10:27   ` [RFC v3 1/5] cpufreq:LAB:ondemand Adjust ondemand to be able to reuse its methods Lukasz Majewski
2014-03-04 10:27   ` [RFC v3 2/5] cpufreq:LAB:cpufreq_governor Adjust cpufreq_governor.[h|c] to support LAB Lukasz Majewski
2014-03-04 10:27   ` [RFC v3 3/5] cpufreq:LAB:lab Add LAB governor code Lukasz Majewski
2014-03-04 10:27   ` [RFC v3 4/5] cpufreq:LAB:Kconfig Add LAB definitions to Kconfig Lukasz Majewski
2014-03-04 10:27   ` [RFC v3 5/5] cpufreq:LAB:dts:trats2: Add DTS nodes for LAB governor Lukasz Majewski
2014-03-17 15:38   ` [RFC v3 0/5] cpufreq:LAB: Support " Lukasz Majewski
2014-03-18  6:55     ` Viresh Kumar
2014-03-18  9:17       ` Lukasz Majewski
2014-03-24  6:47         ` Lukasz Majewski
2014-03-24  6:51           ` Viresh Kumar
2014-03-24  8:48   ` Viresh Kumar
2014-03-24 10:00     ` Lukasz Majewski
2014-03-24 10:15       ` Viresh Kumar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1367590072-10496-2-git-send-email-jonghwa3.lee@samsung.com \
    --to=jonghwa3.lee@samsung.com \
    --cc=cpufreq@vger.kernel.org \
    --cc=daniel.lezcano@linaro.org \
    --cc=l.majewski@samsung.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=myungjoo.ham@samsung.com \
    --cc=rjw@sisk.pl \
    --cc=vincent.guittot@linaro.org \
    --cc=viresh.kumar@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®